summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-05-10 18:56:23 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-05-10 18:56:23 +0000
commitf6bd7625ba83fcf78845aeca4ec01cbfa98fb260 (patch)
treed7c084f5b6fb452fbd5e0761f47ab121a276fe55
downloadcups-release-1.1.23rc1.tar.gz
Import cups.org releasesrelease-1.1.23rc1
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/tags/release-1.1.23rc1@4306 a1ca3aef-8c08-0410-bb20-df032aa958be
-rw-r--r--.cvsignore33
-rw-r--r--CGI.txt81
-rw-r--r--CHANGES.txt3676
-rw-r--r--CREDITS.txt33
-rw-r--r--ENCRYPTION.txt142
-rw-r--r--INSTALL.txt190
-rw-r--r--INSTALL_fr.txt19
-rw-r--r--LICENSE.html956
-rw-r--r--LICENSE.txt861
-rw-r--r--Makedefs.in191
-rw-r--r--Makefile170
-rw-r--r--README.txt278
-rw-r--r--README_fr.txt19
-rw-r--r--backend/.cvsignore8
-rw-r--r--backend/Dependencies17
-rw-r--r--backend/Makefile156
-rw-r--r--backend/betest.c87
-rw-r--r--backend/ipp.c1383
-rw-r--r--backend/lpd.c1047
-rw-r--r--backend/parallel.c679
-rw-r--r--backend/scsi-irix.c210
-rw-r--r--backend/scsi-linux.c228
-rw-r--r--backend/scsi.c220
-rw-r--r--backend/serial.c996
-rw-r--r--backend/socket.c418
-rw-r--r--backend/usb-darwin.c1899
-rw-r--r--backend/usb-unix.c807
-rw-r--r--backend/usb.c270
-rw-r--r--berkeley/.cvsignore4
-rw-r--r--berkeley/Dependencies12
-rw-r--r--berkeley/Makefile112
-rw-r--r--berkeley/lpc.c486
-rw-r--r--berkeley/lpq.c615
-rw-r--r--berkeley/lpr.c455
-rw-r--r--berkeley/lprm.c276
-rw-r--r--cgi-bin/.cvsignore5
-rw-r--r--cgi-bin/Dependencies20
-rw-r--r--cgi-bin/Makefile123
-rw-r--r--cgi-bin/admin.c1605
-rw-r--r--cgi-bin/cgi.h86
-rw-r--r--cgi-bin/classes.c346
-rw-r--r--cgi-bin/html.c89
-rw-r--r--cgi-bin/ipp-var.c575
-rw-r--r--cgi-bin/ipp-var.h58
-rw-r--r--cgi-bin/jobs.c261
-rw-r--r--cgi-bin/printers.c356
-rw-r--r--cgi-bin/template.c492
-rw-r--r--cgi-bin/var.c672
-rw-r--r--conf/.cvsignore2
-rw-r--r--conf/Makefile76
-rw-r--r--conf/classes.conf89
-rw-r--r--conf/client.conf67
-rw-r--r--conf/cupsd.conf.in845
-rw-r--r--conf/mime.convs118
-rw-r--r--conf/mime.types162
-rw-r--r--conf/pam.darwin7
-rw-r--r--conf/pam.irix3
-rw-r--r--conf/pam.std.in2
-rw-r--r--conf/printcap2
-rw-r--r--conf/printers.conf96
-rw-r--r--config-scripts/cups-common.m4217
-rw-r--r--config-scripts/cups-compiler.m4206
-rw-r--r--config-scripts/cups-directories.m4242
-rw-r--r--config-scripts/cups-image.m482
-rw-r--r--config-scripts/cups-libtool.m449
-rw-r--r--config-scripts/cups-manpages.m4104
-rw-r--r--config-scripts/cups-network.m459
-rw-r--r--config-scripts/cups-openslp.m448
-rw-r--r--config-scripts/cups-openssl.m4112
-rw-r--r--config-scripts/cups-opsys.m499
-rw-r--r--config-scripts/cups-pam.m494
-rw-r--r--config-scripts/cups-scripting.m491
-rw-r--r--config-scripts/cups-sharedlibs.m4156
-rw-r--r--config.h.in305
-rw-r--r--configure.in50
-rwxr-xr-xcups-config.in134
-rw-r--r--cups.dsw29
-rw-r--r--cups.list.in588
-rw-r--r--cups.osx39
-rw-r--r--cups.plist7
-rwxr-xr-xcups.sh.in211
-rw-r--r--cups.spec295
-rw-r--r--cups.strings9
-rw-r--r--cups/.cvsignore13
-rw-r--r--cups/Dependencies31
-rw-r--r--cups/Makefile212
-rw-r--r--cups/attr.c180
-rw-r--r--cups/auth.c249
-rw-r--r--cups/cups.dsp220
-rw-r--r--cups/cups.h211
-rw-r--r--cups/cups.vcproj601
-rw-r--r--cups/cups_C.h135
-rw-r--r--cups/cupsdll.def136
-rw-r--r--cups/debug.h59
-rw-r--r--cups/dest.c856
-rw-r--r--cups/emit.c756
-rw-r--r--cups/encode.c388
-rw-r--r--cups/getputfile.c419
-rw-r--r--cups/http-addr.c122
-rw-r--r--cups/http-private.h102
-rw-r--r--cups/http-support.c378
-rw-r--r--cups/http.c2561
-rw-r--r--cups/http.h379
-rw-r--r--cups/ipp-support.c175
-rw-r--r--cups/ipp.c2561
-rw-r--r--cups/ipp.h467
-rw-r--r--cups/language.c993
-rw-r--r--cups/language.h228
-rw-r--r--cups/mark.c443
-rw-r--r--cups/md5.c392
-rw-r--r--cups/md5.h94
-rw-r--r--cups/md5passwd.c150
-rw-r--r--cups/options.c499
-rw-r--r--cups/page.c191
-rw-r--r--cups/ppd.c2659
-rw-r--r--cups/ppd.h338
-rw-r--r--cups/snprintf.c344
-rw-r--r--cups/string.c226
-rw-r--r--cups/string.h130
-rw-r--r--cups/tempfile.c221
-rw-r--r--cups/testhttp.c127
-rw-r--r--cups/testipp.c521
-rw-r--r--cups/testlang.c119
-rw-r--r--cups/testmime.dsp102
-rw-r--r--cups/testppd.dsp102
-rw-r--r--cups/usersys.c460
-rw-r--r--cups/util.c1712
-rw-r--r--data/HPGLprolog37
-rw-r--r--data/Makefile103
-rw-r--r--data/classified277
-rw-r--r--data/confidential277
-rw-r--r--data/iso-8859-1251
-rw-r--r--data/iso-8859-10251
-rw-r--r--data/iso-8859-13251
-rw-r--r--data/iso-8859-14251
-rw-r--r--data/iso-8859-15251
-rw-r--r--data/iso-8859-2253
-rw-r--r--data/iso-8859-3244
-rw-r--r--data/iso-8859-4251
-rw-r--r--data/iso-8859-5251
-rw-r--r--data/iso-8859-6206
-rw-r--r--data/iso-8859-7246
-rw-r--r--data/iso-8859-8214
-rw-r--r--data/iso-8859-9251
-rw-r--r--data/koi8-r261
-rw-r--r--data/koi8-u259
-rw-r--r--data/psglyphs1051
-rw-r--r--data/secret277
-rw-r--r--data/standard261
-rw-r--r--data/testprint.ps522
-rw-r--r--data/topsecret277
-rw-r--r--data/unclassified277
-rw-r--r--data/utf-839
-rw-r--r--data/windows-1250254
-rw-r--r--data/windows-1251258
-rw-r--r--data/windows-1252254
-rw-r--r--data/windows-1253243
-rw-r--r--data/windows-1254252
-rw-r--r--data/windows-1255236
-rw-r--r--data/windows-1256259
-rw-r--r--data/windows-1257247
-rw-r--r--data/windows-1258250
-rw-r--r--data/windows-874228
-rw-r--r--doc/Makefile248
-rw-r--r--doc/be/Makefile90
-rw-r--r--doc/be/cups.css4
-rw-r--r--doc/be/cupsdoc.css9
-rw-r--r--doc/be/documentation.html91
-rw-r--r--doc/be/images/accept-jobs.gifbin0 -> 986 bytes
-rw-r--r--doc/be/images/add-class.gifbin0 -> 922 bytes
-rw-r--r--doc/be/images/add-printer.gifbin0 -> 999 bytes
-rw-r--r--doc/be/images/cancel-job.gifbin0 -> 1450 bytes
-rw-r--r--doc/be/images/classes.gifbin0 -> 591 bytes
-rw-r--r--doc/be/images/config-printer.gifbin0 -> 1066 bytes
-rw-r--r--doc/be/images/continue.gifbin0 -> 752 bytes
-rw-r--r--doc/be/images/cups-large.gifbin0 -> 7457 bytes
-rw-r--r--doc/be/images/cups-medium.gifbin0 -> 3163 bytes
-rw-r--r--doc/be/images/cups-small.gifbin0 -> 1266 bytes
-rw-r--r--doc/be/images/delete-class.gifbin0 -> 1379 bytes
-rw-r--r--doc/be/images/delete-printer.gifbin0 -> 1475 bytes
-rw-r--r--doc/be/images/hold-job.gifbin0 -> 1479 bytes
-rw-r--r--doc/be/images/left.gifbin0 -> 110 bytes
-rw-r--r--doc/be/images/logo.gifbin0 -> 1958 bytes
-rw-r--r--doc/be/images/manage-classes.gifbin0 -> 979 bytes
-rw-r--r--doc/be/images/manage-jobs.gifbin0 -> 1012 bytes
-rw-r--r--doc/be/images/manage-printers.gifbin0 -> 1487 bytes
-rw-r--r--doc/be/images/modify-class.gifbin0 -> 924 bytes
-rw-r--r--doc/be/images/modify-printer.gifbin0 -> 1460 bytes
-rw-r--r--doc/be/images/navbar.gifbin0 -> 6024 bytes
-rw-r--r--doc/be/images/print-test-page.gifbin0 -> 1755 bytes
-rw-r--r--doc/be/images/printer-idle.gifbin0 -> 706 bytes
-rw-r--r--doc/be/images/printer-processing.gifbin0 -> 805 bytes
-rw-r--r--doc/be/images/printer-stopped.gifbin0 -> 794 bytes
-rw-r--r--doc/be/images/reject-jobs.gifbin0 -> 998 bytes
-rw-r--r--doc/be/images/release-job.gifbin0 -> 1494 bytes
-rw-r--r--doc/be/images/restart-job.gifbin0 -> 1038 bytes
-rw-r--r--doc/be/images/right.gifbin0 -> 145 bytes
-rw-r--r--doc/be/images/show-active.gifbin0 -> 1580 bytes
-rw-r--r--doc/be/images/show-completed.gifbin0 -> 1119 bytes
-rw-r--r--doc/be/images/start-class.gifbin0 -> 1394 bytes
-rw-r--r--doc/be/images/start-printer.gifbin0 -> 1500 bytes
-rw-r--r--doc/be/images/stop-class.gifbin0 -> 883 bytes
-rw-r--r--doc/be/images/stop-printer.gifbin0 -> 1414 bytes
-rw-r--r--doc/be/index.html37
-rw-r--r--doc/be/robots.txt31
-rw-r--r--doc/cmp.html745
-rw-r--r--doc/cmp.pdfbin0 -> 346044 bytes
-rw-r--r--doc/cmp.shtml736
-rw-r--r--doc/cups.css4
-rw-r--r--doc/cupsdoc.css9
-rw-r--r--doc/de/Makefile90
-rw-r--r--doc/de/documentation.html81
-rw-r--r--doc/de/images/accept-jobs.gifbin0 -> 324 bytes
-rw-r--r--doc/de/images/add-class.gifbin0 -> 315 bytes
-rw-r--r--doc/de/images/add-printer.gifbin0 -> 325 bytes
-rw-r--r--doc/de/images/cancel-job.gifbin0 -> 291 bytes
-rw-r--r--doc/de/images/config-printer.gifbin0 -> 337 bytes
-rw-r--r--doc/de/images/continue.gifbin0 -> 208 bytes
-rw-r--r--doc/de/images/delete-class.gifbin0 -> 276 bytes
-rw-r--r--doc/de/images/delete-printer.gifbin0 -> 296 bytes
-rw-r--r--doc/de/images/hold-job.gifbin0 -> 302 bytes
-rw-r--r--doc/de/images/manage-classes.gifbin0 -> 407 bytes
-rw-r--r--doc/de/images/manage-jobs.gifbin0 -> 317 bytes
-rw-r--r--doc/de/images/manage-printers.gifbin0 -> 407 bytes
-rw-r--r--doc/de/images/modify-class.gifbin0 -> 321 bytes
-rw-r--r--doc/de/images/modify-printer.gifbin0 -> 322 bytes
-rw-r--r--doc/de/images/navbar.gifbin0 -> 3927 bytes
-rw-r--r--doc/de/images/print-test-page.gifbin0 -> 303 bytes
-rw-r--r--doc/de/images/reject-jobs.gifbin0 -> 318 bytes
-rw-r--r--doc/de/images/release-job.gifbin0 -> 314 bytes
-rw-r--r--doc/de/images/restart-job.gifbin0 -> 346 bytes
-rw-r--r--doc/de/images/show-active.gifbin0 -> 375 bytes
-rw-r--r--doc/de/images/show-completed.gifbin0 -> 384 bytes
-rw-r--r--doc/de/images/start-class.gifbin0 -> 273 bytes
-rw-r--r--doc/de/images/start-printer.gifbin0 -> 287 bytes
-rw-r--r--doc/de/images/stop-class.gifbin0 -> 290 bytes
-rw-r--r--doc/de/images/stop-printer.gifbin0 -> 302 bytes
-rw-r--r--doc/de/index.html36
-rw-r--r--doc/documentation.html90
-rw-r--r--doc/es/Makefile91
-rw-r--r--doc/es/documentation.html90
-rw-r--r--doc/es/images/accept-jobs.gifbin0 -> 297 bytes
-rw-r--r--doc/es/images/add-class.gifbin0 -> 259 bytes
-rw-r--r--doc/es/images/add-printer.gifbin0 -> 296 bytes
-rw-r--r--doc/es/images/cancel-job.gifbin0 -> 297 bytes
-rw-r--r--doc/es/images/config-printer.gifbin0 -> 325 bytes
-rw-r--r--doc/es/images/continue.gifbin0 -> 234 bytes
-rw-r--r--doc/es/images/delete-class.gifbin0 -> 253 bytes
-rw-r--r--doc/es/images/delete-printer.gifbin0 -> 286 bytes
-rw-r--r--doc/es/images/hold-job.gifbin0 -> 287 bytes
-rw-r--r--doc/es/images/left.gifbin0 -> 110 bytes
-rw-r--r--doc/es/images/manage-classes.gifbin0 -> 302 bytes
-rw-r--r--doc/es/images/manage-jobs.gifbin0 -> 324 bytes
-rw-r--r--doc/es/images/manage-printers.gifbin0 -> 337 bytes
-rw-r--r--doc/es/images/modify-class.gifbin0 -> 284 bytes
-rw-r--r--doc/es/images/modify-printer.gifbin0 -> 318 bytes
-rw-r--r--doc/es/images/navbar.gifbin0 -> 4321 bytes
-rw-r--r--doc/es/images/print-test-page.gifbin0 -> 372 bytes
-rw-r--r--doc/es/images/reject-jobs.gifbin0 -> 309 bytes
-rw-r--r--doc/es/images/release-job.gifbin0 -> 278 bytes
-rw-r--r--doc/es/images/restart-job.gifbin0 -> 291 bytes
-rw-r--r--doc/es/images/right.gifbin0 -> 145 bytes
-rw-r--r--doc/es/images/set-as-default.gifbin0 -> 382 bytes
-rw-r--r--doc/es/images/show-active.gifbin0 -> 358 bytes
-rw-r--r--doc/es/images/show-completed.gifbin0 -> 371 bytes
-rw-r--r--doc/es/images/start-class.gifbin0 -> 246 bytes
-rw-r--r--doc/es/images/start-printer.gifbin0 -> 282 bytes
-rw-r--r--doc/es/images/stop-class.gifbin0 -> 264 bytes
-rw-r--r--doc/es/images/stop-printer.gifbin0 -> 302 bytes
-rw-r--r--doc/es/index.html36
-rw-r--r--doc/figures.scbin0 -> 619 bytes
-rw-r--r--doc/fr/Makefile189
-rw-r--r--doc/fr/cups.css4
-rw-r--r--doc/fr/cupsdoc.css9
-rw-r--r--doc/fr/documentation.html81
-rw-r--r--doc/fr/glossary.shtml73
-rw-r--r--doc/fr/images/accept-jobs.gifbin0 -> 295 bytes
-rw-r--r--doc/fr/images/add-class.gifbin0 -> 269 bytes
-rw-r--r--doc/fr/images/add-printer.gifbin0 -> 307 bytes
-rw-r--r--doc/fr/images/cancel-job.gifbin0 -> 272 bytes
-rw-r--r--doc/fr/images/config-printer.gifbin0 -> 334 bytes
-rw-r--r--doc/fr/images/continue.gifbin0 -> 229 bytes
-rw-r--r--doc/fr/images/delete-class.gifbin0 -> 293 bytes
-rw-r--r--doc/fr/images/delete-printer.gifbin0 -> 330 bytes
-rw-r--r--doc/fr/images/hold-job.gifbin0 -> 269 bytes
-rw-r--r--doc/fr/images/manage-classes.gifbin0 -> 312 bytes
-rw-r--r--doc/fr/images/manage-jobs.gifbin0 -> 316 bytes
-rw-r--r--doc/fr/images/manage-printers.gifbin0 -> 345 bytes
-rw-r--r--doc/fr/images/modify-class.gifbin0 -> 282 bytes
-rw-r--r--doc/fr/images/modify-printer.gifbin0 -> 316 bytes
-rw-r--r--doc/fr/images/navbar.gifbin0 -> 2429 bytes
-rw-r--r--doc/fr/images/print-test-page.gifbin0 -> 316 bytes
-rw-r--r--doc/fr/images/reject-jobs.gifbin0 -> 281 bytes
-rw-r--r--doc/fr/images/release-job.gifbin0 -> 271 bytes
-rw-r--r--doc/fr/images/restart-job.gifbin0 -> 312 bytes
-rw-r--r--doc/fr/images/show-active.gifbin0 -> 302 bytes
-rw-r--r--doc/fr/images/show-completed.gifbin0 -> 343 bytes
-rw-r--r--doc/fr/images/start-class.gifbin0 -> 282 bytes
-rw-r--r--doc/fr/images/start-printer.gifbin0 -> 324 bytes
-rw-r--r--doc/fr/images/stop-class.gifbin0 -> 260 bytes
-rw-r--r--doc/fr/images/stop-printer.gifbin0 -> 307 bytes
-rw-r--r--doc/fr/index.html36
-rw-r--r--doc/fr/overview.html503
-rw-r--r--doc/fr/overview.pdfbin0 -> 42722 bytes
-rw-r--r--doc/fr/printing-overview.shtml125
-rw-r--r--doc/fr/references.shtml42
-rw-r--r--doc/fr/sam.html5233
-rw-r--r--doc/fr/sam.pdfbin0 -> 781426 bytes
-rw-r--r--doc/fr/sam.shtml4607
-rw-r--r--doc/fr/sum.html1776
-rw-r--r--doc/fr/sum.pdfbin0 -> 612615 bytes
-rw-r--r--doc/fr/sum.shtml1596
-rw-r--r--doc/fr/system-overview.shtml19
-rw-r--r--doc/glossary.shtml73
-rw-r--r--doc/idd.html1145
-rw-r--r--doc/idd.pdfbin0 -> 393976 bytes
-rw-r--r--doc/idd.shtml1493
-rw-r--r--doc/images/accept-jobs.gifbin0 -> 259 bytes
-rw-r--r--doc/images/add-class.gifbin0 -> 242 bytes
-rw-r--r--doc/images/add-printer.gifbin0 -> 252 bytes
-rw-r--r--doc/images/cancel-job.gifbin0 -> 248 bytes
-rw-r--r--doc/images/classes.gifbin0 -> 591 bytes
-rw-r--r--doc/images/config-printer.gifbin0 -> 296 bytes
-rw-r--r--doc/images/continue.gifbin0 -> 224 bytes
-rw-r--r--doc/images/cups-block-diagram.gifbin0 -> 11637 bytes
-rw-r--r--doc/images/cups-large.gifbin0 -> 7457 bytes
-rw-r--r--doc/images/cups-medium.gifbin0 -> 3163 bytes
-rw-r--r--doc/images/cups-small.gifbin0 -> 1266 bytes
-rw-r--r--doc/images/delete-class.gifbin0 -> 259 bytes
-rw-r--r--doc/images/delete-printer.gifbin0 -> 267 bytes
-rw-r--r--doc/images/hold-job.gifbin0 -> 228 bytes
-rw-r--r--doc/images/left.gifbin0 -> 110 bytes
-rw-r--r--doc/images/logo.gifbin0 -> 1958 bytes
-rw-r--r--doc/images/manage-classes.gifbin0 -> 289 bytes
-rw-r--r--doc/images/manage-jobs.gifbin0 -> 266 bytes
-rw-r--r--doc/images/manage-printers.gifbin0 -> 296 bytes
-rw-r--r--doc/images/modify-class.gifbin0 -> 267 bytes
-rw-r--r--doc/images/modify-printer.gifbin0 -> 277 bytes
-rw-r--r--doc/images/navbar.gifbin0 -> 2869 bytes
-rw-r--r--doc/images/navbar.xcf.gzbin0 -> 4253 bytes
-rw-r--r--doc/images/print-test-page.gifbin0 -> 288 bytes
-rw-r--r--doc/images/printer-idle.gifbin0 -> 706 bytes
-rw-r--r--doc/images/printer-processing.gifbin0 -> 805 bytes
-rw-r--r--doc/images/printer-stopped.gifbin0 -> 794 bytes
-rw-r--r--doc/images/reject-jobs.gifbin0 -> 252 bytes
-rw-r--r--doc/images/release-job.gifbin0 -> 255 bytes
-rw-r--r--doc/images/restart-job.gifbin0 -> 249 bytes
-rw-r--r--doc/images/right.gifbin0 -> 145 bytes
-rw-r--r--doc/images/set-as-default.gifbin0 -> 278 bytes
-rw-r--r--doc/images/show-active.gifbin0 -> 303 bytes
-rw-r--r--doc/images/show-completed.gifbin0 -> 337 bytes
-rw-r--r--doc/images/start-class.gifbin0 -> 238 bytes
-rw-r--r--doc/images/start-printer.gifbin0 -> 255 bytes
-rw-r--r--doc/images/stop-class.gifbin0 -> 245 bytes
-rw-r--r--doc/images/stop-printer.gifbin0 -> 252 bytes
-rw-r--r--doc/index.html36
-rw-r--r--doc/ipp.html1566
-rw-r--r--doc/ipp.pdfbin0 -> 395813 bytes
-rw-r--r--doc/ipp.shtml2085
-rw-r--r--doc/overview.html500
-rw-r--r--doc/overview.pdfbin0 -> 37765 bytes
-rw-r--r--doc/printing-overview.shtml125
-rw-r--r--doc/references.shtml43
-rw-r--r--doc/robots.txt31
-rw-r--r--doc/sam.html6366
-rw-r--r--doc/sam.pdfbin0 -> 786973 bytes
-rw-r--r--doc/sam.shtml6265
-rw-r--r--doc/sdd.html606
-rw-r--r--doc/sdd.pdfbin0 -> 396109 bytes
-rw-r--r--doc/sdd.shtml564
-rw-r--r--doc/spm.html9491
-rw-r--r--doc/spm.pdfbin0 -> 1054813 bytes
-rw-r--r--doc/spm.shtml10799
-rw-r--r--doc/sps.html312
-rw-r--r--doc/sps.pdfbin0 -> 321133 bytes
-rw-r--r--doc/sps.shtml457
-rw-r--r--doc/ssr.html289
-rw-r--r--doc/ssr.pdfbin0 -> 319795 bytes
-rw-r--r--doc/ssr.shtml165
-rw-r--r--doc/stp.html277
-rw-r--r--doc/stp.pdfbin0 -> 361783 bytes
-rw-r--r--doc/stp.shtml144
-rw-r--r--doc/sum.html1789
-rw-r--r--doc/sum.pdfbin0 -> 574568 bytes
-rw-r--r--doc/sum.shtml969
-rw-r--r--doc/svd.html311
-rw-r--r--doc/svd.pdfbin0 -> 376195 bytes
-rw-r--r--doc/svd.shtml212
-rw-r--r--doc/system-overview.shtml34
-rw-r--r--doc/translation.html620
-rw-r--r--doc/translation.pdfbin0 -> 516291 bytes
-rw-r--r--doc/translation.shtml734
-rw-r--r--filter/.cvsignore16
-rw-r--r--filter/Dependencies75
-rw-r--r--filter/Makefile273
-rw-r--r--filter/common.c471
-rw-r--r--filter/common.h92
-rw-r--r--filter/form-main.c62
-rw-r--r--filter/form-ps.c49
-rw-r--r--filter/form-tree.c624
-rw-r--r--filter/form.h177
-rw-r--r--filter/gziptoany.c131
-rw-r--r--filter/hpgl-attr.c454
-rw-r--r--filter/hpgl-char.c640
-rw-r--r--filter/hpgl-config.c645
-rw-r--r--filter/hpgl-input.c252
-rw-r--r--filter/hpgl-main.c274
-rw-r--r--filter/hpgl-polygon.c394
-rw-r--r--filter/hpgl-prolog.c377
-rw-r--r--filter/hpgl-vector.c775
-rw-r--r--filter/hpgltops.dsp130
-rw-r--r--filter/hpgltops.h241
-rw-r--r--filter/image-bmp.c539
-rw-r--r--filter/image-colorspace.c1544
-rw-r--r--filter/image-gif.c694
-rw-r--r--filter/image-jpeg.c315
-rw-r--r--filter/image-photocd.c325
-rw-r--r--filter/image-pix.c240
-rw-r--r--filter/image-png.c270
-rw-r--r--filter/image-pnm.c306
-rw-r--r--filter/image-sgi.c285
-rw-r--r--filter/image-sgi.h96
-rw-r--r--filter/image-sgilib.c859
-rw-r--r--filter/image-sun.c399
-rw-r--r--filter/image-tiff.c1743
-rw-r--r--filter/image-zoom.c335
-rw-r--r--filter/image.c775
-rw-r--r--filter/image.h249
-rw-r--r--filter/imagetops.c1031
-rw-r--r--filter/imagetoraster.c4598
-rw-r--r--filter/pstops.c1900
-rw-r--r--filter/pstops.dsp107
-rw-r--r--filter/raster.c258
-rw-r--r--filter/raster.h263
-rw-r--r--filter/rastertodymo.c597
-rw-r--r--filter/rastertoepson.c1152
-rw-r--r--filter/rastertohp.c888
-rw-r--r--filter/testimage.c101
-rw-r--r--filter/textcommon.c1187
-rw-r--r--filter/textcommon.h122
-rw-r--r--filter/texttops.c1311
-rw-r--r--filter/texttops.dsp98
-rw-r--r--fonts/Courier1494
-rw-r--r--fonts/Courier-Bold1652
-rw-r--r--fonts/Courier-BoldOblique1686
-rw-r--r--fonts/Courier-Oblique1448
-rw-r--r--fonts/Makefile62
-rw-r--r--fonts/Symbol1150
-rwxr-xr-xinstall-sh251
-rw-r--r--locale/C/cups_C135
-rw-r--r--locale/Makefile76
-rw-r--r--locale/be/cups_be134
-rw-r--r--locale/cs/cups_cs135
-rw-r--r--locale/de/cups_de136
-rw-r--r--locale/en/cups_en135
-rw-r--r--locale/en_US/cups_en_US135
-rw-r--r--locale/es/cups_es135
-rw-r--r--locale/fr/cups_fr135
-rw-r--r--locale/he/cups_he135
-rw-r--r--locale/it/cups_it135
-rw-r--r--locale/locale.txt32
-rw-r--r--locale/ru_RU/cups_ru_RU134
-rw-r--r--locale/sv/cups_sv135
-rw-r--r--locale/translate.c259
-rw-r--r--locale/uk/cups_uk134
-rw-r--r--locale/uk_UA/cups_uk_UA134
-rw-r--r--locale/zh_CN/cups_zh_CN135
-rw-r--r--man/.cvsignore7
-rw-r--r--man/Makefile121
-rw-r--r--man/Makefile.common86
-rw-r--r--man/accept.man60
-rw-r--r--man/backend.man122
-rw-r--r--man/classes.conf.man72
-rw-r--r--man/cups-config.man95
-rw-r--r--man/cups-lpd.man125
-rw-r--r--man/cups-polld.man46
-rw-r--r--man/cupsaddsmb.man185
-rw-r--r--man/cupsd.conf.man411
-rw-r--r--man/cupsd.man61
-rw-r--r--man/cupstestppd.man105
-rw-r--r--man/enable.man67
-rw-r--r--man/es/Makefile103
-rw-r--r--man/es/accept.man57
-rw-r--r--man/es/backend.man108
-rw-r--r--man/es/classes.conf.man70
-rw-r--r--man/es/cups-config.man91
-rw-r--r--man/es/cups-lpd.man100
-rw-r--r--man/es/cups-polld.man46
-rw-r--r--man/es/cupsaddsmb.man149
-rw-r--r--man/es/cupsd.conf.man383
-rw-r--r--man/es/cupsd.man54
-rw-r--r--man/es/cupstestppd.man90
-rw-r--r--man/es/enable.man64
-rw-r--r--man/es/filter.man110
-rw-r--r--man/es/lp.man165
-rw-r--r--man/es/lpadmin.man138
-rw-r--r--man/es/lpc.man75
-rw-r--r--man/es/lpinfo.man61
-rw-r--r--man/es/lpmove.man54
-rw-r--r--man/es/lpoptions.man119
-rw-r--r--man/es/lppasswd.man52
-rw-r--r--man/es/lpq.man55
-rw-r--r--man/es/lpr.man96
-rw-r--r--man/es/lprm.man52
-rw-r--r--man/es/lpstat.man126
-rw-r--r--man/es/mime.convs.man49
-rw-r--r--man/es/mime.types.man93
-rw-r--r--man/es/printers.conf.man71
-rw-r--r--man/filter.man123
-rw-r--r--man/fr/.cvsignore7
-rw-r--r--man/fr/Makefile103
-rw-r--r--man/fr/accept.man63
-rw-r--r--man/fr/backend.man118
-rw-r--r--man/fr/classes.conf.man75
-rw-r--r--man/fr/cups-config.man97
-rw-r--r--man/fr/cups-lpd.man112
-rw-r--r--man/fr/cups-polld.man49
-rw-r--r--man/fr/cupsaddsmb.man151
-rw-r--r--man/fr/cupsd.conf.man359
-rw-r--r--man/fr/cupsd.man52
-rw-r--r--man/fr/cupstestppd.man102
-rw-r--r--man/fr/enable.man68
-rw-r--r--man/fr/filter.man127
-rw-r--r--man/fr/lp.man184
-rw-r--r--man/fr/lpadmin.man168
-rw-r--r--man/fr/lpc.man82
-rw-r--r--man/fr/lpinfo.man63
-rw-r--r--man/fr/lpmove.man58
-rw-r--r--man/fr/lpoptions.man127
-rw-r--r--man/fr/lppasswd.man64
-rw-r--r--man/fr/lpq.man60
-rw-r--r--man/fr/lpr.man107
-rw-r--r--man/fr/lprm.man57
-rw-r--r--man/fr/lpstat.man144
-rw-r--r--man/fr/mime.convs.man59
-rw-r--r--man/fr/mime.types.man104
-rw-r--r--man/fr/printers.conf.man76
-rw-r--r--man/lp.man181
-rw-r--r--man/lpadmin.man163
-rw-r--r--man/lpc.man80
-rw-r--r--man/lpinfo.man60
-rw-r--r--man/lpmove.man53
-rw-r--r--man/lpoptions.man128
-rw-r--r--man/lppasswd.man61
-rw-r--r--man/lpq.man57
-rw-r--r--man/lpr.man107
-rw-r--r--man/lprm.man54
-rw-r--r--man/lpstat.man140
-rw-r--r--man/mime.convs.man54
-rw-r--r--man/mime.types.man102
-rw-r--r--man/printers.conf.man73
-rw-r--r--pdftops/.cvsignore1
-rw-r--r--pdftops/Annot.cxx134
-rw-r--r--pdftops/Annot.h69
-rw-r--r--pdftops/Array.cxx73
-rw-r--r--pdftops/Array.h58
-rw-r--r--pdftops/BuiltinFont.cxx65
-rw-r--r--pdftops/BuiltinFont.h57
-rw-r--r--pdftops/BuiltinFontTables.cxx4284
-rw-r--r--pdftops/BuiltinFontTables.h23
-rw-r--r--pdftops/CMap.cxx384
-rw-r--r--pdftops/CMap.h102
-rw-r--r--pdftops/CNS13CMapInfo.h47771
-rw-r--r--pdftops/COPYING339
-rw-r--r--pdftops/Catalog.cxx360
-rw-r--r--pdftops/Catalog.h89
-rw-r--r--pdftops/CharCodeToUnicode.cxx533
-rw-r--r--pdftops/CharCodeToUnicode.h113
-rw-r--r--pdftops/CharTypes.h24
-rw-r--r--pdftops/CompactFontTables.h464
-rw-r--r--pdftops/Decrypt.cxx399
-rw-r--r--pdftops/Decrypt.h61
-rw-r--r--pdftops/Dependencies88
-rw-r--r--pdftops/Dict.cxx95
-rw-r--r--pdftops/Dict.h77
-rw-r--r--pdftops/DisplayFontTable.h29
-rw-r--r--pdftops/Error.cxx38
-rw-r--r--pdftops/Error.h23
-rw-r--r--pdftops/ErrorCodes.h34
-rw-r--r--pdftops/FontEncoding.cxx143
-rw-r--r--pdftops/FontEncoding.h64
-rw-r--r--pdftops/FontEncodingTables.cxx1824
-rw-r--r--pdftops/FontEncodingTables.h20
-rw-r--r--pdftops/FontFile.cxx4109
-rw-r--r--pdftops/FontFile.h261
-rw-r--r--pdftops/Function.cxx1520
-rw-r--r--pdftops/Function.h183
-rw-r--r--pdftops/GB12CMapInfo.h50880
-rw-r--r--pdftops/GHash.cxx241
-rw-r--r--pdftops/GHash.h69
-rw-r--r--pdftops/GList.cxx92
-rw-r--r--pdftops/GList.h91
-rw-r--r--pdftops/GString.cxx236
-rw-r--r--pdftops/GString.h100
-rw-r--r--pdftops/Gfx.cxx3101
-rw-r--r--pdftops/Gfx.h280
-rw-r--r--pdftops/GfxFont.cxx1480
-rw-r--r--pdftops/GfxFont.h315
-rw-r--r--pdftops/GfxState.cxx2762
-rw-r--r--pdftops/GfxState.h1055
-rw-r--r--pdftops/GlobalParams.cxx1556
-rw-r--r--pdftops/GlobalParams.h313
-rw-r--r--pdftops/JBIG2Stream.cxx3658
-rw-r--r--pdftops/JBIG2Stream.h143
-rw-r--r--pdftops/Japan12CMapInfo.h31362
-rw-r--r--pdftops/Japan12ToRKSJ.h1038
-rw-r--r--pdftops/Lexer.cxx474
-rw-r--r--pdftops/Lexer.h77
-rw-r--r--pdftops/Link.cxx849
-rw-r--r--pdftops/Link.h409
-rw-r--r--pdftops/Makefile127
-rw-r--r--pdftops/NameToCharCode.cxx116
-rw-r--r--pdftops/NameToCharCode.h42
-rw-r--r--pdftops/NameToUnicodeTable.h1097
-rw-r--r--pdftops/Object.cxx224
-rw-r--r--pdftops/Object.h302
-rw-r--r--pdftops/Outline.cxx140
-rw-r--r--pdftops/Outline.h74
-rw-r--r--pdftops/OutputDev.cxx103
-rw-r--r--pdftops/OutputDev.h161
-rw-r--r--pdftops/PDFDoc.cxx303
-rw-r--r--pdftops/PDFDoc.h172
-rw-r--r--pdftops/PDFDocEncoding.cxx44
-rw-r--r--pdftops/PDFDocEncoding.h16
-rw-r--r--pdftops/PSOutputDev.cxx3618
-rw-r--r--pdftops/PSOutputDev.h296
-rw-r--r--pdftops/PSTokenizer.cxx135
-rw-r--r--pdftops/PSTokenizer.h41
-rw-r--r--pdftops/Page.cxx349
-rw-r--r--pdftops/Page.h166
-rw-r--r--pdftops/Params.cxx90
-rw-r--r--pdftops/Params.h38
-rw-r--r--pdftops/Parser.cxx231
-rw-r--r--pdftops/Parser.h60
-rw-r--r--pdftops/README446
-rw-r--r--pdftops/Stream-CCITT.h459
-rw-r--r--pdftops/Stream.cxx3969
-rw-r--r--pdftops/Stream.h842
-rw-r--r--pdftops/UTF8.h56
-rw-r--r--pdftops/UnicodeMap.cxx293
-rw-r--r--pdftops/UnicodeMap.h123
-rw-r--r--pdftops/UnicodeMapTables.h361
-rw-r--r--pdftops/XRef.cxx709
-rw-r--r--pdftops/XRef.h123
-rw-r--r--pdftops/config.h110
-rw-r--r--pdftops/gfile.cxx708
-rw-r--r--pdftops/gfile.h138
-rw-r--r--pdftops/gmem.c204
-rw-r--r--pdftops/gmem.h53
-rw-r--r--pdftops/gmempp.cxx32
-rw-r--r--pdftops/gtypes.h29
-rw-r--r--pdftops/parseargs.c190
-rw-r--r--pdftops/parseargs.h71
-rw-r--r--pdftops/pdftops.cxx342
-rw-r--r--ppd/Makefile63
-rw-r--r--ppd/deskjet.ppd198
-rw-r--r--ppd/deskjet2.ppd217
-rw-r--r--ppd/dymo.ppd155
-rw-r--r--ppd/epson24.ppd138
-rw-r--r--ppd/epson9.ppd136
-rw-r--r--ppd/laserjet.ppd200
-rw-r--r--ppd/okidat24.ppd128
-rw-r--r--ppd/okidata9.ppd126
-rw-r--r--ppd/stcolor.ppd132
-rw-r--r--ppd/stcolor2.ppd132
-rw-r--r--ppd/stphoto.ppd132
-rw-r--r--ppd/stphoto2.ppd132
-rw-r--r--ppd/zebra.ppd147
-rw-r--r--pstoraster/.cvsignore3
-rw-r--r--pstoraster/README.pstoraster73
-rw-r--r--pstoraster/cups.mak53
-rw-r--r--pstoraster/gdevcups.c4464
-rw-r--r--pstoraster/gs707-lib.patch110
-rw-r--r--pstoraster/gs811-lib.patch110
-rw-r--r--pstoraster/pstopxl67
-rwxr-xr-xpstoraster/pstopxl.in67
-rwxr-xr-xpstoraster/pstoraster52
-rw-r--r--pstoraster/pstoraster.convs29
-rwxr-xr-xpstoraster/pstoraster.in62
-rw-r--r--pstoraster/pxlcolor.ppd205
-rw-r--r--pstoraster/pxlmono.ppd199
-rw-r--r--scheduler/.cvsignore5
-rw-r--r--scheduler/Dependencies105
-rw-r--r--scheduler/Makefile144
-rw-r--r--scheduler/auth.c1677
-rw-r--r--scheduler/auth.h139
-rw-r--r--scheduler/banners.c215
-rw-r--r--scheduler/banners.h57
-rw-r--r--scheduler/cert.c297
-rw-r--r--scheduler/cert.h60
-rw-r--r--scheduler/classes.c725
-rw-r--r--scheduler/classes.h44
-rw-r--r--scheduler/client.c3467
-rw-r--r--scheduler/client.h118
-rw-r--r--scheduler/conf.c2232
-rw-r--r--scheduler/conf.h201
-rw-r--r--scheduler/cups-lpd.c1427
-rw-r--r--scheduler/cups-polld.c409
-rw-r--r--scheduler/cups.pam2
-rw-r--r--scheduler/cupsd.dsp173
-rw-r--r--scheduler/cupsd.h215
-rw-r--r--scheduler/devices.c484
-rw-r--r--scheduler/dirsvc.c1974
-rw-r--r--scheduler/dirsvc.h145
-rw-r--r--scheduler/file.c997
-rw-r--r--scheduler/file.h108
-rw-r--r--scheduler/filter.c326
-rw-r--r--scheduler/ipp.c6877
-rw-r--r--scheduler/job.c2845
-rw-r--r--scheduler/job.h111
-rw-r--r--scheduler/listen.c258
-rw-r--r--scheduler/log.c529
-rw-r--r--scheduler/main.c1383
-rw-r--r--scheduler/mime.c587
-rw-r--r--scheduler/mime.h147
-rw-r--r--scheduler/network.c491
-rw-r--r--scheduler/network.h64
-rw-r--r--scheduler/ppds.c781
-rw-r--r--scheduler/printers.c2495
-rw-r--r--scheduler/printers.h135
-rw-r--r--scheduler/quotas.c238
-rw-r--r--scheduler/server.c183
-rw-r--r--scheduler/testmime.c247
-rw-r--r--scheduler/testspeed.c292
-rw-r--r--scheduler/type.c1132
-rw-r--r--scripting/java/CUPSPrinter.java438
-rw-r--r--scripting/java/README9
-rw-r--r--scripting/java/cups.jarbin0 -> 35017 bytes
-rw-r--r--scripting/java/docs/allclasses-frame.html53
-rw-r--r--scripting/java/docs/deprecated-list.html119
-rw-r--r--scripting/java/docs/help-doc.html168
-rw-r--r--scripting/java/docs/index-all.html1603
-rw-r--r--scripting/java/docs/index.html22
-rw-r--r--scripting/java/docs/org/cups/Cups.html692
-rw-r--r--scripting/java/docs/org/cups/CupsJob.html622
-rw-r--r--scripting/java/docs/org/cups/CupsPrinter.html614
-rw-r--r--scripting/java/docs/org/cups/IPP.html479
-rw-r--r--scripting/java/docs/org/cups/IPPAttribute.html545
-rw-r--r--scripting/java/docs/org/cups/IPPDefs.html3756
-rw-r--r--scripting/java/docs/org/cups/IPPError.html208
-rw-r--r--scripting/java/docs/org/cups/IPPHttp.html2931
-rw-r--r--scripting/java/docs/org/cups/IPPRequest.html290
-rw-r--r--scripting/java/docs/org/cups/IPPStatus.html218
-rw-r--r--scripting/java/docs/org/cups/IPPURLConnection.html315
-rw-r--r--scripting/java/docs/org/cups/IPPValue.html400
-rw-r--r--scripting/java/docs/overview-tree.html131
-rw-r--r--scripting/java/docs/package-list1
-rw-r--r--scripting/java/docs/packages.html26
-rw-r--r--scripting/java/docs/serialized-form.html89
-rw-r--r--scripting/java/docs/stylesheet.css29
-rw-r--r--scripting/java/example/GLP.java59
-rw-r--r--scripting/java/example/GLPcolors.java22
-rw-r--r--scripting/java/example/GLPdetail.java279
-rw-r--r--scripting/java/example/GLPjobList.java150
-rw-r--r--scripting/java/example/GLPjobTableModel.java104
-rw-r--r--scripting/java/example/GLPoptions.java662
-rw-r--r--scripting/java/example/GLPprinterDetail.java244
-rw-r--r--scripting/java/example/GLPprinters.java509
-rw-r--r--scripting/java/example/GLPsearch.java121
-rw-r--r--scripting/java/example/GLPsearchProgressPanel.java195
-rw-r--r--scripting/java/example/GLPserver.java192
-rw-r--r--scripting/java/example/GLPtabs.java117
-rw-r--r--scripting/java/example/GLPvars.java93
-rw-r--r--scripting/java/example/class.list13
-rw-r--r--scripting/java/example/images/left.gifbin0 -> 110 bytes
-rw-r--r--scripting/java/example/images/print-test-page.gifbin0 -> 519 bytes
-rw-r--r--scripting/java/example/images/printer-idle.gifbin0 -> 706 bytes
-rw-r--r--scripting/java/example/images/printer-stopped.gifbin0 -> 794 bytes
-rw-r--r--scripting/java/example/images/restart-job.gifbin0 -> 440 bytes
-rw-r--r--scripting/java/example/images/show-active.gifbin0 -> 581 bytes
-rw-r--r--scripting/java/example/images/show-completed.gifbin0 -> 657 bytes
-rw-r--r--scripting/java/src/org/cups/Cups.java1413
-rw-r--r--scripting/java/src/org/cups/CupsJob.java216
-rw-r--r--scripting/java/src/org/cups/CupsPrinter.java837
-rw-r--r--scripting/java/src/org/cups/IPP.java251
-rw-r--r--scripting/java/src/org/cups/IPPAttribute.java593
-rw-r--r--scripting/java/src/org/cups/IPPBase64Encoder.java46
-rw-r--r--scripting/java/src/org/cups/IPPCalendar.java62
-rw-r--r--scripting/java/src/org/cups/IPPDefs.java310
-rw-r--r--scripting/java/src/org/cups/IPPError.java159
-rw-r--r--scripting/java/src/org/cups/IPPHttp.java1353
-rw-r--r--scripting/java/src/org/cups/IPPMD5.java134
-rw-r--r--scripting/java/src/org/cups/IPPRequest.java97
-rw-r--r--scripting/java/src/org/cups/IPPStatus.java195
-rw-r--r--scripting/java/src/org/cups/IPPURLConnection.java78
-rw-r--r--scripting/java/src/org/cups/IPPValue.java264
-rw-r--r--scripting/java/src/org/cups/Makefile92
-rw-r--r--scripting/java/src/org/cups/cups.nfo34
-rw-r--r--scripting/perl/CUPS.pm144
-rw-r--r--scripting/perl/CUPS.xs270
-rw-r--r--scripting/perl/Makefile.PL17
-rw-r--r--scripting/perl/README46
-rw-r--r--scripting/perl/test.pl17
-rw-r--r--scripting/php/Dependencies6
-rw-r--r--scripting/php/Example/phpcups.inc.php4310
-rw-r--r--scripting/php/Makefile101
-rw-r--r--scripting/php/README21
-rw-r--r--scripting/php/config.m460
-rw-r--r--scripting/php/php_phpcups.h87
-rw-r--r--scripting/php/phpcups.c1357
-rw-r--r--scripting/php/phpcups.php53
-rw-r--r--standards/pwg5100.1.pdfbin0 -> 37359 bytes
-rw-r--r--standards/pwg5100.2.pdfbin0 -> 37360 bytes
-rw-r--r--standards/pwg5100.3.pdfbin0 -> 262279 bytes
-rw-r--r--standards/pwg5100.4.pdfbin0 -> 150078 bytes
-rw-r--r--standards/rfc1179.txt787
-rw-r--r--standards/rfc1321.txt1179
-rw-r--r--standards/rfc2246.txt4483
-rw-r--r--standards/rfc2396.txt2243
-rw-r--r--standards/rfc2487.txt451
-rw-r--r--standards/rfc2565.txt2075
-rw-r--r--standards/rfc2566.txt9691
-rw-r--r--standards/rfc2567.txt2411
-rw-r--r--standards/rfc2568.txt563
-rw-r--r--standards/rfc2569.txt1571
-rw-r--r--standards/rfc2595.txt843
-rw-r--r--standards/rfc2616.txt9859
-rw-r--r--standards/rfc2617.txt1907
-rw-r--r--standards/rfc2639.txt3587
-rw-r--r--standards/rfc2712.txt395
-rw-r--r--standards/rfc2817.txt731
-rw-r--r--standards/rfc2818.txt395
-rw-r--r--standards/rfc2821.txt4427
-rw-r--r--standards/rfc2822.txt2859
-rw-r--r--standards/rfc2910.txt2579
-rw-r--r--standards/rfc2911.txt12547
-rw-r--r--standards/rfc2965.txt1459
-rw-r--r--standards/rfc3380.txt3307
-rw-r--r--standards/rfc3381.txt955
-rw-r--r--standards/rfc3382.txt2131
-rw-r--r--systemv/.cvsignore11
-rw-r--r--systemv/Dependencies28
-rw-r--r--systemv/Makefile198
-rw-r--r--systemv/accept.c286
-rw-r--r--systemv/cancel.c384
-rw-r--r--systemv/cupsaddsmb.c951
-rw-r--r--systemv/cupstestppd.c1237
-rw-r--r--systemv/lp.c770
-rw-r--r--systemv/lpadmin.c2053
-rw-r--r--systemv/lpinfo.c454
-rw-r--r--systemv/lpmove.c235
-rw-r--r--systemv/lpoptions.c442
-rw-r--r--systemv/lppasswd.c498
-rw-r--r--systemv/lpstat.c2111
-rw-r--r--templates/Makefile111
-rw-r--r--templates/add-class.tmpl33
-rw-r--r--templates/add-printer.tmpl33
-rw-r--r--templates/admin-op.tmpl1
-rw-r--r--templates/admin.tmpl57
-rw-r--r--templates/be/Makefile106
-rw-r--r--templates/be/add-class.tmpl33
-rw-r--r--templates/be/add-printer.tmpl33
-rw-r--r--templates/be/admin-op.tmpl1
-rw-r--r--templates/be/admin.tmpl57
-rw-r--r--templates/be/choose-device.tmpl32
-rw-r--r--templates/be/choose-make.tmpl35
-rw-r--r--templates/be/choose-members.tmpl30
-rw-r--r--templates/be/choose-model.tmpl35
-rw-r--r--templates/be/choose-serial.tmpl56
-rw-r--r--templates/be/choose-uri.tmpl43
-rw-r--r--templates/be/class-added.tmpl2
-rw-r--r--templates/be/class-confirm.tmpl5
-rw-r--r--templates/be/class-deleted.tmpl1
-rw-r--r--templates/be/class-modified.tmpl1
-rw-r--r--templates/be/classes.tmpl51
-rw-r--r--templates/be/config-printer.tmpl6
-rw-r--r--templates/be/config-printer2.tmpl2
-rw-r--r--templates/be/error.tmpl3
-rw-r--r--templates/be/header.tmpl24
-rw-r--r--templates/be/job-cancel.tmpl1
-rw-r--r--templates/be/job-hold.tmpl1
-rw-r--r--templates/be/job-op.tmpl1
-rw-r--r--templates/be/job-release.tmpl1
-rw-r--r--templates/be/job-restart.tmpl1
-rw-r--r--templates/be/jobs.tmpl54
-rw-r--r--templates/be/modify-class.tmpl34
-rw-r--r--templates/be/modify-printer.tmpl36
-rw-r--r--templates/be/option-boolean.tmpl7
-rw-r--r--templates/be/option-conflict.tmpl7
-rw-r--r--templates/be/option-header.tmpl8
-rw-r--r--templates/be/option-pickmany.tmpl7
-rw-r--r--templates/be/option-pickone.tmpl7
-rw-r--r--templates/be/option-trailer.tmpl8
-rw-r--r--templates/be/printer-accept.tmpl1
-rw-r--r--templates/be/printer-added.tmpl1
-rw-r--r--templates/be/printer-configured.tmpl2
-rw-r--r--templates/be/printer-confirm.tmpl5
-rw-r--r--templates/be/printer-deleted.tmpl1
-rw-r--r--templates/be/printer-modified.tmpl2
-rw-r--r--templates/be/printer-purge.tmpl2
-rw-r--r--templates/be/printer-reject.tmpl2
-rw-r--r--templates/be/printer-start.tmpl2
-rw-r--r--templates/be/printer-stop.tmpl2
-rw-r--r--templates/be/printers.tmpl61
-rw-r--r--templates/be/test-page.tmpl2
-rw-r--r--templates/be/trailer.tmpl7
-rw-r--r--templates/choose-device.tmpl32
-rw-r--r--templates/choose-make.tmpl35
-rw-r--r--templates/choose-members.tmpl30
-rw-r--r--templates/choose-model.tmpl35
-rw-r--r--templates/choose-serial.tmpl56
-rw-r--r--templates/choose-uri.tmpl43
-rw-r--r--templates/class-added.tmpl2
-rw-r--r--templates/class-confirm.tmpl6
-rw-r--r--templates/class-deleted.tmpl1
-rw-r--r--templates/class-modified.tmpl2
-rw-r--r--templates/classes.tmpl53
-rw-r--r--templates/config-printer.tmpl6
-rw-r--r--templates/config-printer2.tmpl2
-rw-r--r--templates/de/Makefile106
-rw-r--r--templates/de/add-class.tmpl33
-rw-r--r--templates/de/add-printer.tmpl33
-rw-r--r--templates/de/admin-op.tmpl1
-rw-r--r--templates/de/admin.tmpl56
-rw-r--r--templates/de/choose-device.tmpl32
-rw-r--r--templates/de/choose-make.tmpl35
-rw-r--r--templates/de/choose-members.tmpl30
-rw-r--r--templates/de/choose-model.tmpl35
-rw-r--r--templates/de/choose-serial.tmpl56
-rw-r--r--templates/de/choose-uri.tmpl43
-rw-r--r--templates/de/class-added.tmpl1
-rw-r--r--templates/de/class-confirm.tmpl5
-rw-r--r--templates/de/class-deleted.tmpl1
-rw-r--r--templates/de/class-modified.tmpl1
-rw-r--r--templates/de/classes.tmpl51
-rw-r--r--templates/de/config-printer.tmpl6
-rw-r--r--templates/de/config-printer2.tmpl2
-rw-r--r--templates/de/error.tmpl3
-rw-r--r--templates/de/header.tmpl24
-rw-r--r--templates/de/job-cancel.tmpl1
-rw-r--r--templates/de/job-hold.tmpl1
-rw-r--r--templates/de/job-op.tmpl1
-rw-r--r--templates/de/job-release.tmpl1
-rw-r--r--templates/de/job-restart.tmpl1
-rw-r--r--templates/de/jobs.tmpl58
-rw-r--r--templates/de/modify-class.tmpl34
-rw-r--r--templates/de/modify-printer.tmpl36
-rw-r--r--templates/de/option-boolean.tmpl7
-rw-r--r--templates/de/option-conflict.tmpl7
-rw-r--r--templates/de/option-header.tmpl8
-rw-r--r--templates/de/option-pickmany.tmpl7
-rw-r--r--templates/de/option-pickone.tmpl7
-rw-r--r--templates/de/option-trailer.tmpl8
-rw-r--r--templates/de/printer-accept.tmpl1
-rw-r--r--templates/de/printer-added.tmpl1
-rw-r--r--templates/de/printer-configured.tmpl1
-rw-r--r--templates/de/printer-confirm.tmpl5
-rw-r--r--templates/de/printer-deleted.tmpl1
-rw-r--r--templates/de/printer-modified.tmpl1
-rw-r--r--templates/de/printer-purge.tmpl1
-rw-r--r--templates/de/printer-reject.tmpl1
-rw-r--r--templates/de/printer-start.tmpl1
-rw-r--r--templates/de/printer-stop.tmpl1
-rw-r--r--templates/de/printers.tmpl61
-rw-r--r--templates/de/test-page.tmpl2
-rw-r--r--templates/de/trailer.tmpl7
-rw-r--r--templates/error.tmpl3
-rw-r--r--templates/es/Makefile106
-rw-r--r--templates/es/add-class.tmpl33
-rw-r--r--templates/es/add-printer.tmpl33
-rw-r--r--templates/es/admin-op.tmpl1
-rw-r--r--templates/es/admin.tmpl57
-rw-r--r--templates/es/choose-device.tmpl32
-rw-r--r--templates/es/choose-make.tmpl35
-rw-r--r--templates/es/choose-members.tmpl30
-rw-r--r--templates/es/choose-model.tmpl35
-rw-r--r--templates/es/choose-serial.tmpl56
-rw-r--r--templates/es/choose-uri.tmpl43
-rw-r--r--templates/es/class-added.tmpl1
-rw-r--r--templates/es/class-confirm.tmpl5
-rw-r--r--templates/es/class-deleted.tmpl1
-rw-r--r--templates/es/class-modified.tmpl1
-rw-r--r--templates/es/classes.tmpl53
-rw-r--r--templates/es/config-printer.tmpl6
-rw-r--r--templates/es/config-printer2.tmpl2
-rw-r--r--templates/es/error.tmpl3
-rw-r--r--templates/es/header.tmpl23
-rw-r--r--templates/es/job-cancel.tmpl1
-rw-r--r--templates/es/job-hold.tmpl1
-rw-r--r--templates/es/job-op.tmpl1
-rw-r--r--templates/es/job-release.tmpl1
-rw-r--r--templates/es/job-restart.tmpl1
-rw-r--r--templates/es/jobs.tmpl54
-rw-r--r--templates/es/modify-class.tmpl34
-rw-r--r--templates/es/modify-printer.tmpl36
-rw-r--r--templates/es/option-boolean.tmpl7
-rw-r--r--templates/es/option-conflict.tmpl7
-rw-r--r--templates/es/option-header.tmpl8
-rw-r--r--templates/es/option-pickmany.tmpl7
-rw-r--r--templates/es/option-pickone.tmpl7
-rw-r--r--templates/es/option-trailer.tmpl8
-rw-r--r--templates/es/printer-accept.tmpl1
-rw-r--r--templates/es/printer-added.tmpl1
-rw-r--r--templates/es/printer-configured.tmpl1
-rw-r--r--templates/es/printer-confirm.tmpl6
-rw-r--r--templates/es/printer-default.tmpl4
-rw-r--r--templates/es/printer-deleted.tmpl1
-rw-r--r--templates/es/printer-modified.tmpl1
-rw-r--r--templates/es/printer-purge.tmpl1
-rw-r--r--templates/es/printer-reject.tmpl1
-rw-r--r--templates/es/printer-start.tmpl1
-rw-r--r--templates/es/printer-stop.tmpl1
-rw-r--r--templates/es/printers.tmpl63
-rw-r--r--templates/es/test-page.tmpl2
-rw-r--r--templates/es/trailer.tmpl7
-rw-r--r--templates/fr/Makefile106
-rw-r--r--templates/fr/add-class.tmpl33
-rw-r--r--templates/fr/add-printer.tmpl33
-rw-r--r--templates/fr/admin-op.tmpl1
-rw-r--r--templates/fr/admin.tmpl57
-rw-r--r--templates/fr/choose-device.tmpl32
-rw-r--r--templates/fr/choose-make.tmpl35
-rw-r--r--templates/fr/choose-members.tmpl30
-rw-r--r--templates/fr/choose-model.tmpl35
-rw-r--r--templates/fr/choose-serial.tmpl56
-rw-r--r--templates/fr/choose-uri.tmpl43
-rw-r--r--templates/fr/class-added.tmpl2
-rw-r--r--templates/fr/class-confirm.tmpl6
-rw-r--r--templates/fr/class-deleted.tmpl1
-rw-r--r--templates/fr/class-modified.tmpl2
-rw-r--r--templates/fr/classes.tmpl51
-rw-r--r--templates/fr/config-printer.tmpl6
-rw-r--r--templates/fr/config-printer2.tmpl2
-rw-r--r--templates/fr/error.tmpl3
-rw-r--r--templates/fr/header.tmpl23
-rw-r--r--templates/fr/job-cancel.tmpl1
-rw-r--r--templates/fr/job-hold.tmpl1
-rw-r--r--templates/fr/job-op.tmpl1
-rw-r--r--templates/fr/job-release.tmpl2
-rw-r--r--templates/fr/job-restart.tmpl1
-rw-r--r--templates/fr/jobs.tmpl54
-rw-r--r--templates/fr/modify-class.tmpl34
-rw-r--r--templates/fr/modify-printer.tmpl36
-rw-r--r--templates/fr/option-boolean.tmpl7
-rw-r--r--templates/fr/option-conflict.tmpl7
-rw-r--r--templates/fr/option-header.tmpl8
-rw-r--r--templates/fr/option-pickmany.tmpl7
-rw-r--r--templates/fr/option-pickone.tmpl7
-rw-r--r--templates/fr/option-trailer.tmpl8
-rw-r--r--templates/fr/printer-accept.tmpl2
-rw-r--r--templates/fr/printer-added.tmpl1
-rw-r--r--templates/fr/printer-configured.tmpl2
-rw-r--r--templates/fr/printer-confirm.tmpl6
-rw-r--r--templates/fr/printer-deleted.tmpl1
-rw-r--r--templates/fr/printer-modified.tmpl1
-rw-r--r--templates/fr/printer-purge.tmpl1
-rw-r--r--templates/fr/printer-reject.tmpl1
-rw-r--r--templates/fr/printer-start.tmpl1
-rw-r--r--templates/fr/printer-stop.tmpl1
-rw-r--r--templates/fr/printers.tmpl61
-rw-r--r--templates/fr/test-page.tmpl2
-rw-r--r--templates/fr/trailer.tmpl7
-rw-r--r--templates/header.tmpl23
-rw-r--r--templates/job-cancel.tmpl1
-rw-r--r--templates/job-hold.tmpl1
-rw-r--r--templates/job-op.tmpl1
-rw-r--r--templates/job-release.tmpl1
-rw-r--r--templates/job-restart.tmpl1
-rw-r--r--templates/jobs.tmpl54
-rw-r--r--templates/modify-class.tmpl34
-rw-r--r--templates/modify-printer.tmpl36
-rw-r--r--templates/option-boolean.tmpl7
-rw-r--r--templates/option-conflict.tmpl7
-rw-r--r--templates/option-header.tmpl8
-rw-r--r--templates/option-pickmany.tmpl7
-rw-r--r--templates/option-pickone.tmpl7
-rw-r--r--templates/option-trailer.tmpl8
-rw-r--r--templates/printer-accept.tmpl1
-rw-r--r--templates/printer-added.tmpl2
-rw-r--r--templates/printer-configured.tmpl2
-rw-r--r--templates/printer-confirm.tmpl6
-rw-r--r--templates/printer-default.tmpl4
-rw-r--r--templates/printer-deleted.tmpl1
-rw-r--r--templates/printer-modified.tmpl2
-rw-r--r--templates/printer-purge.tmpl1
-rw-r--r--templates/printer-reject.tmpl1
-rw-r--r--templates/printer-start.tmpl2
-rw-r--r--templates/printer-stop.tmpl2
-rw-r--r--templates/printers.tmpl63
-rw-r--r--templates/test-page.tmpl2
-rw-r--r--templates/trailer.tmpl7
-rw-r--r--test/.cvsignore1
-rw-r--r--test/4.1-requests.test140
-rw-r--r--test/4.2-cups-printer-ops.test214
-rw-r--r--test/4.3-job-ops.test297
-rwxr-xr-xtest/5.1-lpadmin.sh64
-rwxr-xr-xtest/5.2-lpc.sh40
-rwxr-xr-xtest/5.3-lpq.sh40
-rwxr-xr-xtest/5.4-lpstat.sh40
-rwxr-xr-xtest/5.5-lp.sh71
-rwxr-xr-xtest/5.6-lpr.sh71
-rwxr-xr-xtest/5.7-lprm.sh52
-rwxr-xr-xtest/5.8-cancel.sh52
-rwxr-xr-xtest/5.9-lpinfo.sh52
-rw-r--r--test/Dependencies4
-rw-r--r--test/Makefile85
-rw-r--r--test/create-job-format.test56
-rw-r--r--test/create-job-sheets.test55
-rw-r--r--test/create-job-timeout.test55
-rw-r--r--test/create-job.test54
-rw-r--r--test/get-devices.test21
-rw-r--r--test/get-job-attributes.test27
-rw-r--r--test/get-job-attributes2.test29
-rw-r--r--test/get-ppds.test21
-rw-r--r--test/get-printer-attributes.test44
-rw-r--r--test/ipptest.c826
-rw-r--r--test/print-job-hold.test33
-rw-r--r--test/print-job.test33
-rwxr-xr-xtest/run-stp-tests.sh471
-rw-r--r--test/set-attrs-hold.test180
-rw-r--r--test/str-header.html35
-rw-r--r--test/str-trailer.html5
-rw-r--r--test/testfile.jpgbin0 -> 598930 bytes
-rw-r--r--test/testfile.pdfbin0 -> 36613 bytes
-rw-r--r--test/testfile.ps512
-rw-r--r--test/testfile.txt60
-rw-r--r--test/testhp.ppd195
-rw-r--r--test/testps.ppd192
-rw-r--r--visualc/config.h290
1119 files changed, 509420 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 000000000..c0b24b8fd
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,33 @@
+config.cache
+config.h
+config.log
+config.status
+configure
+cups-config
+cups.list
+cups.sh
+make.log
+printpro.common
+printpro.version
+Makedefs
+aix-4.3-powerpc
+darwin-5.2-powerpc
+darwin-5.3-powerpc
+darwin-6.0-powerpc
+freebsd-4.5-intel
+hpux-10.20-hppa
+hpux-11.00-hppa
+irix-5.3-mips
+irix-6.5-mips
+linux-2.0-intel
+linux-2.2-intel
+linux-2.4-intel
+solaris-2.5-intel
+solaris-2.5-sparc
+solaris-2.7-intel
+solaris-2.7-sparc
+solaris-2.8-intel
+solaris-2.8-sparc
+solaris-2.9-intel
+solaris-2.9-sparc
+tru64-4.0-alpha
diff --git a/CGI.txt b/CGI.txt
new file mode 100644
index 000000000..337acb891
--- /dev/null
+++ b/CGI.txt
@@ -0,0 +1,81 @@
+CGI - CUPS v1.1.21 - 06/29/2004
+-------------------------------
+
+This file describes the experimental scripting/CGI support
+provided by CUPS starting with CUPS 1.1.19.
+
+WARNING: CGI support is not complete; you may run into problems
+and limitations in the implementation of CGI in CUPS that are
+not present in full-featured web servers like Apache.
+
+
+OVERVIEW OF CGI SUPPORT IN CUPS
+
+CUPS has traditionally provided a dynamic web interface through
+four CGI programs that are executed when users open special
+directories on the CUPS server. Each CGI performs
+administration, class, job, and printer functions as directed by
+the user, but the actual programs that are run and functions
+that are available are limited to those that were originally
+designed into the scheduler.
+
+Starting with CUPS 1.1.19, support is now available for CGI
+programs and specific scripting languages, currently Java, Perl,
+PHP, and Python. The interpreters for these languages are
+currently configured at compile time. Future versions may
+expand the interface to allow for generic support of scripting
+languages similar to the Apache "AddHandler" directive, but with
+external programs instead of modules.
+
+The following MIME types are reserved for the CGI support in
+CUPS (the names have been chosen to mirror those used by
+Apache):
+
+ application/x-httpd-cgi CGI script/program
+ application/x-httpd-java Java program
+ application/x-httpd-perl Perl script
+ application/x-httpd-php PHP script
+ application/x-httpd-python Python script
+
+In order to enable the corresponding type, you must create a new
+/etc/cups/cgi.types file which maps the filename extensions to
+the appropriate MIME type, for example:
+
+ application/x-httpd-cgi cgi
+ application/x-httpd-php php
+
+CGI scripts/programs (application/x-httpd-cgi) also must have
+execution permissions to be treated as a CGI script or program.
+
+
+LIMITATIONS
+
+CUPS implements most of the CGI/1.1 specification, with the
+following limitations:
+
+ - No Location: redirection support.
+ - No PATH_INFO or PATH_TRANSLATED support.
+ - Limited HTTP field support; only the Content-Length
+ (CONTENT_LENGTH), Cookie (HTTP_COOKIE), and User-Agent
+ (HTTP_USER_AGENT) fields are placed in environment
+ variables at this time.
+
+
+REPORTING PROBLEMS
+
+If you have problems, READ THE DOCUMENTATION FIRST! If the
+documentation does not solve your problems please send an email
+to "cups-support@cups.org". Include your operating system and
+version, compiler and version, and any errors or problems you've
+run into. The "/var/log/cups/error_log" file should also be sent,
+as it often helps to determine the cause of your problem.
+
+If you are running a version of Linux, be sure to provide the
+Linux distribution you have, too.
+
+Please note that the "cups-support@cups.org" email address goes
+to the CUPS developers; they are busy people, so your email may
+go unanswered for days or weeks. In general, only general build
+or distribution problems will actually get answered - for
+end-user support see the "README.txt" for a summary of the
+resources available.
diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 000000000..d061725a7
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,3676 @@
+CHANGES.txt - 12/16/2004
+------------------------
+
+CHANGES IN CUPS V1.1.23rc1
+
+ - The lpr man page did not document the "-U" option (STR
+ #998)
+ - The scheduler no longer sends the page-set option when
+ printing banner pages (STR #995)
+ - Fixed a debug message in the imagetops filter (STR
+ #1012)
+ - The lprm man page listed the "-" option in the wrong
+ order (STR #911)
+ - The hpgltops filter contained two buffer overflows
+ that could potentially allow remote access to the "lp"
+ account (STR #1024)
+ - The lppasswd command did not protect against file
+ descriptor or ulimit attacks (STR #1023)
+ - The "lpc status" command used the wrong resource path
+ when querying the list of printers and jobs, causing
+ unnecessary authentication requests (STR #1018)
+ - The httpWait() function did not handle signal
+ interruptions (STR #1020)
+ - The USB backend used the wrong size status variable
+ when checking the printer status (STR #1017)
+ - The scheduler did not delete classes from other
+ classes or implicit classes, which could cause a crash
+ (STR #1015)
+ - The IPP backend now logs the remote print job ID at
+ log level NOTICE instead of INFO (so it shows up in
+ the error_log file...)
+
+
+CHANGES IN CUPS V1.1.22
+
+ - The lpstat man page incorrectly listed the "-s" option
+ as using the equivalent of the "-p" option to list the
+ printers; it uses the "-v" option to list the printers
+ (STR #986)
+ - Now allow 0-length reads in the CUPS file API (STR
+ #985)
+ - cupsDoFileRequest() now sets cupsLastError() to
+ IPP_ERROR on network errors (STR #953)
+ - The pdftops filter didn't scale small pages up to the
+ output page size when the fitplot option was used (STR
+ #984)
+ - Fixed the ipptest program usage message (STR #959)
+ - Added Spanish man pages (STR #963)
+ - Fixed the order of comparisons in the client.conf
+ reading code (STR #971)
+ - cupsLangGet() incorrectly set the current locale (STR
+ #970)
+
+
+CHANGES IN CUPS V1.1.22rc2
+
+ - The pdftops filter didn't check the range of all
+ integer attributes (STR #972)
+ - Documentation corrections (STR #944, STR #946)
+ - Also sanitize device URI in argv[0] (STR #933)
+ - cupsRasterReadHeader() didn't swap bytes for the
+ numeric fields properly (STR #930)
+
+
+CHANGES IN CUPS V1.1.22rc1
+
+ - Now sanitize the device URI that is reported in the
+ error_log file (STR #920)
+ - Fixed some memory and file descriptor leaks in the job
+ dispatch code (STR #921)
+ - Deleting a printer could cause a crash with browsing
+ enabled (STR #865, STR #881, STR #928)
+ - Browsing would turn off if the scheduler got an EAGAIN
+ error (STR #924)
+ - The mime.types file didn't recognize PostScript as a
+ PJL language name (STR #925)
+
+
+CHANGES IN CUPS V1.1.21
+
+ - The scheduler did not separate Digest authentication
+ parameters with commas (STR #882)
+ - Fixed some problems with image printing to custom page
+ sizes (STR #891)
+ - Removed the remaining scheduler code that did not use
+ the "close-on-exec" file descriptor flag to speed up
+ program invocations (STR #890)
+ - The "lpr -r" command removed the print file even if it
+ was not printed. It now only removes the file if the
+ job is successfully created (STR #886)
+ - Revamped the custom page size orientation fix (STR
+ #127)
+ - The lp, lpq, lpr, and lpstat commands now report when
+ an environment variable is pointing to a non-existent
+ printer instead of just saying "no default
+ destination" (STR #879)
+ - Queue names with 2 periods (e.g. "printer..2") were
+ not supported (STR #866)
+
+
+CHANGES IN CUPS V1.1.21rc2
+
+ - Fixed a denial-of-service bug in the CUPS browse
+ protocol support (STR #863)
+ - The scheduler used a select() timeout of INT_MAX
+ seconds when there was nothing to do, which doesn't
+ work on IRIX (STR #864)
+ - Updated the cupsaddsmb program to use the new Windows
+ 2000 PostScript drivers instead of the Windows NT
+ printer drivers (STR #390)
+ - The gziptoany filter did not produce copies for raw
+ print jobs (STR #808)
+ - The cupsLangGet() function now uses nl_langinfo(),
+ when available, to get the current encoding (STR #856)
+ - Added a ReloadTimeout directive to control how long
+ the scheduler waits for jobs to complete before
+ restarting the scheduler (STR #861)
+ - Added a note to the default cupsd.conf file which
+ mentions that you must allow connections from
+ localhost for the command-line and web interfaces to
+ work (STR #850)
+ - The IPP backend incorrectly used the local port when
+ communicating with a remote server; this caused
+ problems with some custom configurations (STR #852)
+ - The cups-lpd mini-daemon wasn't using the right
+ default banner option (STR #851)
+ - Updated the new httpDecode64_2() and httpEncode64_2()
+ functions to handle arbitrary binary data, not just
+ text (STR #860)
+ - String options with quotes in their values were not
+ quoted properly by the scheduler (STR #839)
+ - Configure script changes for GNU/Hurd (STR #838)
+ - The lppasswd program was not installed properly by GNU
+ install when the installer was not root (STR #836)
+ - Updated the cups-lpd man page (STR #843)
+ - Fixed a typo in the cupsd man page (STR #833)
+ - The USB backend now defaults to using the newer
+ /dev/usb/lpN filenames; this helps on systems which
+ use the devfs filesystem type on Linux (STR #818)
+ - The config.h file did not define the HAVE_USERSEC_H
+ constant when the configure script detected the
+ usersec.h header file. This caused authentication
+ errors on AIX (STR #832)
+ - The lp and lpr commands now report the temporary
+ filename and error if they are unable to create a
+ temporary file (STR #812)
+ - Added ServerTokens directive to control the Server
+ header in HTTP responses (STR #792)
+ - Added new httpDecode64_2(), httpEncode64_2(), and
+ httpSeparate2() functions which offer buffer size
+ arguments (STR #797)
+ - The cupsGetFile() and cupsPutFile() code did not
+ support CDSA or GNUTLS (STR #794)
+ - The httpSeparate() function did not decode all
+ character escapes (STR #795)
+ - The cupstestppd program now checks for invalid Duplex
+ option choices and fails PPD files that use
+ non-standard values (STR #791)
+ - Updated the printer name error message to indicate
+ that spaces are not allowed (STR #675)
+ - The scheduler didn't handle HTTP GET form data
+ properly (STR #744)
+ - The pstops filter now makes sure that the prolog code
+ is sent before the setup code (STR #776)
+ - The pstops filter now handles print files that
+ incorrectly start @PJL commands without a language
+ escape (STR #734)
+ - Miscellaneous build fixes for NetBSD (STR #788)
+ - Added support for quoted system group names (STR #784)
+ - Added "version" option to IPP backend to workaround
+ serious bug in Linksys's IPP implementation (STR #767)
+ - Added Spanish translation of web interface (STR #772,
+ STR #802)
+ - The LPD backend now uses geteuid() instead of getuid()
+ when it is available (STR #752)
+ - The IPP backend did not report the printer state if
+ the wait option was set to "no" (STR #761)
+ - The printer state was not updated for "STATE: foo,bar"
+ messages (STR #745)
+ - Added new CUPS API convenience functions which accept
+ a HTTP connection to eliminate extra username/password
+ prompts. This resolves a previous authentication
+ caching issue (STR #729, STR #743)
+ - The scheduler did not correctly throttle the browse
+ broadcasts, resulting in missing printers on client
+ machines (STR #754)
+ - The scheduler did not pass the correct CUPS_ENCRYPTION
+ setting to CGI programs which caused problems on
+ systems which used non-standard encryption settings
+ (STR #773)
+ - The lpq command showed 11st, 12nd, and 13rd instead of
+ 11th, 12th, and 13th for the rank (STR #769)
+ - "make install" didn't work on some platforms due to an
+ error in the man page makefiles (STR #775)
+ - Changed some calls to snprintf() in the scheduler to
+ SetStringf() (STR #740)
+
+
+CHANGES IN CUPS V1.1.21rc1
+
+ - Fixed some "type-punned" warnings produced by GCC when
+ -fstrict-aliasing is specified (STR #679)
+ - The PDF filter incorrectly calculated the bounding box
+ of a page (STR #682)
+ - The IPP backend did not use SSL when printing over a
+ port other than 443 (STR #730)
+ - The scheduler could crash when processing a Limit or
+ LimitExcept directive (STR #728)
+ - The lpq, lpr, and lp commands did not differentiate
+ between the server being unresponsive and the lack of
+ a default printer (STR #728)
+ - The PAM checks in the configure script did not stop
+ after the first match (STR #728)
+ - The cups-config man page was incorrectly placed in
+ section 3 (STR #728)
+ - The cupstestppd utility did not show a warning message
+ when a PPD file indicated BCP protocol support with
+ PJL (STR #720)
+ - The scheduler did not return the correct exit code
+ when startup failed (STR #718)
+ - The cupsRasterReadPixels() function checked for
+ EAGAIN, which caused problems on FreeBSD (STR #723)
+ - The cupsGetDests() function did not use the current
+ encryption setting (STR #653)
+ - The scheduler did not properly parse name-based
+ BrowseRelay directives in the cupsd.conf file (STR
+ #711)
+ - The IPP backend now supports the following options in
+ the device URI: encryption, waitjob, and waitprinter
+ (STR #699)
+ - The parallel, serial, socket, and USB backends did not
+ return a non-zero exit status when a job failed to
+ print in the middle of sending it (STR #715)
+ - Location directives in the cupsd.conf file were
+ case-sensitive for printer and class names, so
+ queue-specific access control was not reliable (STR
+ #700)
+ - cupsDoFileRequest() did not handle HTTP continue
+ status messages in all cases, causing sporatic
+ problems with IPP printers from some vendors (STR
+ #716)
+ - The rastertodymo driver now supports the Zebra ZPL
+ language (STR #713)
+ - The test suite no longer generates a printcap file,
+ which caused problems when testing as the root user
+ (STR #693)
+ - The scheduler now updates the accepting state of an
+ implicit class based upon the accepting state of its
+ member printers (STR #697)
+ - The pstops filter didn't properly skip leading PJL
+ commands (STR #664)
+ - The reinterpret_cast keyword was not highlighted when
+ printing C/C++ source files in prettyprint mode (STR
+ #694)
+ - Fixed a segfault problem with some of the client
+ programs (STR #668)
+ - When using RunAsUser, the scheduler did not correctly
+ set the ownership of the log files, preventing log
+ file rotation (STR #686)
+ - The image filters did not correctly load 1-bit PNG
+ files (STR #687)
+ - The pdftops filter did not show all annotation objects
+ in a PDF file (STR #674)
+ - The pdftops filter did not print the contents of
+ textual form elements, making it impossible to print a
+ filled-in form (STR #663)
+ - Integrated the MacOS X/Darwin USB backend into the
+ CUPS baseline (STR #661)
+ - The USB backend incorrectly reported "media tray
+ empty" (STR #660)
+ - The scheduler did not use a case-insensitive
+ comparison when checking for group membership, which
+ caused problems with Win9x clients printing via SAMBA
+ (STR #647)
+ - The scheduler did not report the addresses associated
+ with certain network errors, making troubleshooting
+ difficult (STR #648, #649)
+ - The cupstestppd program did not allow a default choice
+ of "Unknown" as required by the PPD spec (STR #651)
+ - The select() buffers are now allocated to be at least
+ as large as sizeof(fd_set) (STR #639)
+ - The LPD backend now supports overriding the print job
+ username via the device URI (STR #631)
+ - The scheduler did not handle an unknown MIME type when
+ checking for a CGI script (STR #603)
+ - Added a timeout optimization to the scheduler's main
+ loop to allow CUPS to sleep more of the time (STR
+ #629)
+ - The USB backend now retries printing to devices of the
+ form "usb://make/model" if any USB port shows up as
+ "busy" (STR #617)
+ - The httpGetHostByName() function did not range check
+ IP address values (STR #608)
+ - The httpUpdate() function could return HTTP_ERROR
+ instead of the HTTP status if the server closed the
+ connection before the client received the whole
+ response (STR #611)
+ - The LPD mini-daemon did not allow the administrator to
+ force banner pages on (STR #605)
+ - Added PAM support for Darwin/MacOS X (STR #550)
+ - The web interface now provides a "Set As Default"
+ button to set the default printer or class on a server
+ (STR #577)
+ - The HTTP authentication cache was broken (STR #517)
+ - The cupstestppd utility now fails PPD files that have
+ a DefaultOption keyword for a non-existance option
+ name (STR #476)
+ - Optimized the scanning of new PPD files on scheduler
+ startup (STR #424)
+ - The EPM list file did not include the bin, lib, or
+ sbin directories (STR #598)
+ - The web interface did not redirect administration
+ tasks to the primary server for a class or printer
+ (STR #491, #652)
+ - The cups-lpd mini-daemon did not reject print jobs to
+ queues that were rejecting new print jobs (STR #515)
+ - Some calls to the ctype functions did not account for
+ platforms that use a signed char type by default (STR
+ #518)
+ - The scheduler could use excess amounts of CPU if a CGI
+ program was sending data faster than the client could
+ take it (STR #595)
+ - Updated the Ghostscript 8.x integration stuff (STR
+ #484)
+ - The lpd backend used a source port of 732 by default,
+ which is outside of the range defined by RFC 1179;
+ also added a new (default) "reserve=any" option for
+ any priviledged port from 1 to 1023 (STR #474)
+ - The scheduler did not check for a valid Listen/Port
+ configuration (STR #499)
+ - The cupsPrintFiles() function did not always set the
+ last IPP error message (STR #538)
+ - The pstops filter did not write the PostScript header
+ line if the file began with a PJL escape sequence (STR
+ #574)
+ - The printer-is-accepting-jobs status of remote
+ printers was not sent to clients via browsing or
+ polling (STR #571)
+ - The web interface did not show the printer state
+ history information (STR #592)
+ - The rastertoepson filter would crash under certain
+ cirsumstances (STR #583)
+ - The USB backend did not handle serial numbers using
+ the (incorrect) SN keyword and did not terminate the
+ make and model name strings properly (STR #471, STR
+ #588)
+ - The USB backend did not build on Solaris x86 (STR
+ #585)
+ - The cupsDoAuthentication() function did not use the
+ method name for Digest authentication (STR #584)
+ - The scheduler could crash if a print job could not be
+ printed and the PreserveJobHistory option was turned
+ off (STR #535)
+ - cups-lpd now logs the temporary filenames that could
+ not be opened in order to make troubleshooting easier
+ (STR #565)
+ - cupsGetJobs() now returns -1 on error (STR #569)
+ - Added localization for Belarusian (STR #575)
+ - The LPD backend used the full length of the hostname
+ when creating the data and control filenames, which
+ causes problems with older systems that can't handle
+ long filenames (STR #560)
+ - The scheduler did not refresh the common printer data
+ after a fast reload; this prevented banner and other
+ information from being updated (STR #562)
+ - The scheduler did not send common or history data to
+ the client when processing a CUPS-Get-Default request
+ (STR #559)
+ - The httpFlush() function did not always flush the
+ remaining response data in requests (STR #558)
+ - The scheduler could complete a job before it collected
+ the exit status from all filters and the backend (STR
+ #448)
+ - The PPD conformance tests did not catch group
+ translation strings that exceeded the maximum allowed
+ size (STR #454)
+ - Updated the client code in the scheduler to close the
+ client connection on errors rather than shutting down
+ the receive end of the socket; this caused resource
+ problems on some systems (STR #434)
+ - cups-polld didn't compile on Tru64 5.1B (STR #436)
+ - "lpc stat" crashed if the device URI was empty (STR
+ #548)
+ - The scheduler did not compile without zlib (STR #433)
+ - std:floor() cast needed on IRIX 6.5 with SGI C++
+ compiler (STR #497)
+ - cupsRasterReadPixels() and cupsRasterWritePixels() did
+ not handle EAGAIN and EINTR properly (STR #473)
+ - RequiresPageRegion should not be consulted for Manual
+ Feed (STR #514)
+ - International characters were not substituted in
+ banner files properly (STR #468)
+ - Updated pdftops to Xpdf 2.03 code to fix printing bugs
+ (STR #470)
+ - The Digest authentication code did not include the
+ (required) "uri" attribute in the Authorization
+ response, preventing interoperation with Apache
+ (STR #408)
+ - The web interface could lockup when displaying certain
+ URLs (STR #459)
+ - The PostScript filters now convert underscores ("_")
+ to spaces for custom classification names (STR #555)
+
+
+CHANGES IN CUPS V1.1.20
+
+ - The pstops filter didn't properly handle collated,
+ duplexed copies of documents with an odd number of
+ pages on printers that did not do their own collated
+ copies (STR #389)
+ - Tru64 doesn't define a prototype for hstrerror() (STR
+ #430)
+ - Updated the pdftops filter to use the annotation flags
+ instead of the subtype to determine whether to print
+ an annotation (STR #425)
+ - The French web interface localization did not use
+ absolute paths for the navigation bar (STR #428)
+ - The CUPS test suite did not undefine the PRINTER and
+ LPDEST environment variables. This could lead to bogus
+ test results (STR #380)
+ - The cupsLangDefault() function now works if you don't
+ have the base OS localization installed (STR #418)
+ - The pdftops filter no longer needs to create temporary
+ files with tmpnam (STR #406)
+ - The HTTP code did not use a case-insensitive
+ comparison when checking for the Basic authentication
+ method (STR #407)
+ - The httpEncode() function always added a trailing "="
+ character, which is not required by the Base64
+ encoding specification (STR #407)
+ - The signal handlers did not need to call sigset();
+ this caused a recursion problem on some versions of
+ IRIX (STR #422)
+ - Moved the scheduler termination code into the mainline
+ to be consistent with the way other signals are
+ handled (STR #423)
+ - The cupsaddsmb program didn't export the new CUPS
+ driver for Windows properly (STR #390)
+ - The ppdOpen() functions did not issue an error when a
+ translation string exceeded the maximum allowed by the
+ Adobe PPD specification (STR #399)
+ - The default landscape orientation was not the same as
+ that defined in the PPD file (STR #397)
+ - Updated the pstoraster patch files and CUPS driver to
+ work with Ghostscript 8 (STR #402)
+ - The hpgltops filter did not skip PJL commands (STR
+ #379)
+
+
+CHANGES IN CUPS V1.1.20rc6
+
+ - "lp -i jobid -H restart" would often return an error
+ even though the job restarted successfully (STR #362)
+ - The scheduler did not check for invalid allow/deny
+ addresses such as "11.22.33.44/24". It now masks off
+ the extra address bits and logs a warning message in
+ the error_log file (STR #337)
+ - The cupstestppd utility now checks for missing
+ ImageableArea and PaperDimension attributes for each
+ defined PageSize (STR #365)
+ - The IPP code did not wait for a reply indefinitely on
+ HTTP connections in "blocking" mode (STR #377)
+ - The web interfaces did not rewrite the default printer
+ URI properly (STR #369 and #299)
+ - The LPD backend passed the C and L commands in the
+ wrong order (STR #378)
+ - The Dymo label printer driver did not set the label
+ length properly (STR #373)
+ - The scheduler did not support job IDs higher than
+ 99999 (STR #371)
+ - The Visual C++ project files did not work (STR #366)
+ - The scheduler's cupsLangSeek() function did not reset
+ the "EOF" flag, preventing compressed files from being
+ typed properly in some cases (STR #368)
+ - The cupsLangGet() cache was only used if the locale
+ name provided an explicit character set name (STR
+ #354)
+ - The CUPS API convenience functions did not call
+ cupsLangFree() when they were done with the
+ localization data (STR #354)
+ - The scheduler did not return the
+ job-hold-until-supported or job-hold-until-default
+ attributes (STR #356)
+ - The cupsaddsmb program did not support the new CUPS
+ driver for Windows (STR #357)
+
+
+CHANGES IN CUPS V1.1.20rc5
+
+ - The scheduler did not initialize the browse socket
+ file descriptor properly when only SLP browsing was
+ enabled (STR #259)
+ - The scheduler accessed the job attributes before they
+ were set (STR #347, fix to STR #335)
+ - The cupsCancelJob() function did not return 0 when the
+ job could not be canceled (STR #340)
+
+
+CHANGES IN CUPS V1.1.20rc4
+
+ - The scheduler did not move the incoming job attributes
+ in the operation group to the job group (STR #335)
+ - The cupsDoFileRequest() function did not check for an
+ early HTTP response while sending the file (STR #314)
+ - The web interfaces did not quote #, ?, or . in printer
+ names, which caused some problems with the generated
+ URLs (STR #320)
+ - CUPS couldn't be completely compiled with the -dDEBUG
+ option (STR #331)
+
+
+CHANGES IN CUPS V1.1.20rc3
+
+ - More SLP changes (STR #259)
+ - Revamped the child signal handling code to completely
+ avoid deadlock issues on Solaris (STR #325)
+ - The lpadmin command displayed an incorrect error
+ message when the "-u" option was provided with no
+ arguments (STR #313)
+ - The web admin interface did not display an error
+ message if the PPD file could not be loaded (STR #308)
+ - The ppdEmit() functions did not use the correct
+ orientation value position for custom page sizes (STR
+ #292)
+
+
+CHANGES IN CUPS V1.1.20rc2
+
+ - The serial backend set the IXANY option on the port
+ for XON/XOFF flow control; this caused problems with
+ printers that returned status info but were not ready
+ for more print data (STR #287)
+ - The scheduler didn't support scripted index files
+ (index.php, index.pl, etc. - STR #290)
+ - The scheduler did not correctly localize script files
+ with "GET" variables (STR #268)
+ - Changes in job classification are now logged (STR
+ #289)
+ - Fixed a few more SLP-related bugs (STR #259)
+ - Updated the user/group configure checks for MacOS X
+ 10.3 (STR #270)
+ - Fixed an offset bug in the PDF filter (STR #284)
+ - The cupsDoRequest() and cupsDoFileRequest() functions
+ did not map several HTTP status codes to their IPP
+ counterparts. This made detecting certain conditions
+ very difficult (STR #277)
+ - Config, spool, and status files are now owned by the
+ scheduler user (usually root) with read permission for
+ the filter group (STR #283)
+ - The HP-GL/2 filter did not support the SI command,
+ some values for the AD and SD commands, and did not
+ rotate labels properly via the DI command (STR #282)
+ - The fax support did not update/set the job-hold-until
+ attribute when a fax job fails (STR #269)
+ - The cupsLangGet() function didn't support locales of
+ the form "ll.charset" (STR #271)
+ - The scheduler did not use the charset when getting the
+ language localization for a request; this caused extra
+ disk IO for every request (STR #271)
+ - The scheduler did not support requests with more than
+ one language specified (STR #267)
+
+
+CHANGES IN CUPS V1.1.20rc1
+
+ - The scheduler now waits up to 60 seconds before
+ restarting to allow active jobs to complete printing
+ and pending requests to be processed (STR #226)
+ - The web interface did not work on systems where time_t
+ is 64 bits (STR #262)
+ - Added backend tweeks and content-length check from Red
+ Hat (STR #253)
+ - The USB backend now uses the 8255 constants instead of
+ the standard constants when reporting printer status
+ bits on Linux (STR #254)
+ - Added new cupsDoAuthentication(), cupsGetFd(),
+ cupsGetFile(), cupsPutFd(), and cupsPutFile() functions
+ to the CUPS API (STR #112)
+ - The PDF filter always scaled and offset pages; this
+ caused problems under MacOS X, so now the "fitplot"
+ option controls whether PDF files are scaled to fit
+ within the printable area of the page (STR #250)
+ - The LPD backend did not support the port number in a
+ URI (STR #247)
+ - Some filters didn't properly support boolean options
+ (STR #249)
+ - Landscape PDF files were not always offset by the
+ correct amount when rotating (STR #243)
+ - The scheduler could hang in a call to localtime() when
+ logging messages from the signal handler (STR #242)
+ - The PDF filter no longer prints form widgets; this
+ duplicates the behavior of Acrobat Reader (STR #241)
+ - cupsGetPPD() didn't handle a late termination of a
+ HTTP connection with the server (STR #220)
+ - ppdOpen() did not correctly check for "*PPD-Adobe-4."
+ on the first line of a PPD file. This caused incorrect
+ PASS results for some PPD files (STR #233)
+ - cupsEncodeOptions() did not allow boolean options to
+ use "yes" and "on" for true values (STR #227)
+ - The pstops filter only sent the TBCP exit sequence if
+ it was defined in the JCLEnd attribute in the PPD file
+ (STR #224)
+ - Support for more than 1024 files was broken on Solaris
+ 9 (STR #217)
+ - The setgroups() calls now pass in 1 group (the
+ configured group) instead of 0 for compatibility with
+ BSD and Darwin (STR #213)
+ - The scheduler's built-in broadcast throttling was
+ ineffective since incoming packets would cause the
+ next group of outgoing packets to be sent immediately
+ rather than waiting for the next time slot (STR #211)
+ - Added a new ppdSetConformance() function to set the
+ conformance requirements for PPD files. Currently only
+ two levels are defined, PPD_CONFORM_RELAXED and
+ PPD_CONFORM_STRICT, and the default is the relaxed
+ level (STR #212)
+ - The IPP backend did not correctly execute the
+ pictwpstops filter on OSX (STR #210)
+ - The LPD backend did not set the banner class when the
+ "banner=yes" option was specified in the device URI
+ (STR #209)
+ - The imagetoraster filter did not support all of the
+ page device attributes (STR #208)
+ - The pdftops filter incorrectly auto-rotated pages when
+ the user already had specified the proper orientation
+ (STR #207)
+ - Fixed AIX shared library support (STR #201)
+ - Added support for live testing with Valgrind (STR
+ #193)
+ - The CGI programs now collect the list of needed
+ attributes for the class, job, and printer template
+ files (STR #192)
+ - The scheduler now passes the first port that is bound
+ to the local loopback or "any" addresses to the CGI
+ programs rather than the port that the browser
+ connected to (STR #103)
+ - The cupstestppd program now checks for bad
+ JobPatchFile attributes and incorrect versions of the
+ Manufacturer attribute for HP printers (STR #155)
+ - The filter makefile incorrectly installed
+ libcupsimage.a in the filter directory (STR #180)
+ - The scheduler did not verify that the job history
+ files define the job-priority and
+ job-originating-user-name attributes (STR #178)
+ - The pstops filter didn't handle poorly-formed binary
+ PostScript files that had CTRL-D's in them (STR #156)
+ - The ppdOpen*() and cupsLangGet() functions did not
+ make a copy of the old locale strings when using the
+ POSIX locale when reading files, which apparently
+ caused problems with some implementations of the
+ standard C library. (STR #159)
+ - The pdftops filter did not work properly with some
+ embedded Type1C fonts (STR #177)
+ - Updated the pdftops filter to be based upon Xpdf
+ 2.02pl1 (STR #191)
+ - The scheduler did not reset the group list when
+ running CGI and filter processes (STR #185)
+ - The scheduler no longer calls malloc and free from the
+ signal handlers (STR #190)
+ - The USB backend now uses the manufacturer and model
+ strings if the description string is not available
+ (STR #174)
+ - The ppdOpen functions still supported the
+ VariablePaperSize attribute, which was removed in v4.0
+ of the PPD spec. This caused problems with PPD files
+ that relocated the PageSize option to a non-standard
+ group (STR #158)
+ - The cups.list file referenced MAN1EXT, MAN3EXT, and
+ MAN5EXT, but none of those were actually defined (STR
+ #147)
+ - Chunked requests could cause a Denial of Service if
+ the connection is terminated before the first byte of
+ chunk data is sent/received (STR #143)
+ - Printers with special characters in their names were
+ not accessible from the web interface (STR #120)
+ - The lpstat command now shows the correct interface
+ script or PPD file, if any, for a print queue (STR #89)
+ - The lpstat command now shows the printer-state-message
+ and printer-state-reasons attributes whenever they are
+ not blank (STR #152)
+ - The French and German option-conflict.tmpl template
+ files did not get installed (STR #148)
+ - The cups.list.in file did not work when compiling
+ without shared libraries (STR #149)
+ - The DSOFLAGS included the LDFLAGS, which causes
+ problems on at least HP-UX (STR #150)
+ - The fax printer support did not keep track of the fax
+ capability bit (STR #144)
+ - The appleLangDefault() function could leak a small
+ amount of memory (STR #145)
+ - The ppdOpen() functions now mirror all normal
+ attributes to the attribute list; previously only
+ certain unassigned attributes would be added (STR
+ #139)
+ - The ppdEmitJCL() function wrote JCL commands to stdout
+ instead of the passed file pointer (STR #142)
+ - The httpGets() function could, in certain states,
+ block waiting for data (STR #132)
+ - The cupsEmitJCL() function not outputs an empty @PJL
+ command after the PJL language escape to work around
+ bugs in certain PJL implementations (STR #131)
+ - The cupsEmit*() functions didn't set the orientation
+ value properly (STR #127)
+ - The cups.spec file didn't list the rc2.d init
+ directory or the cupstestppd file (STR #134)
+
+
+CHANGES IN CUPS V1.1.19
+
+ - The GNU TLS code incorrectly used
+ gnutls_check_pending() instead of
+ gnutls_record_check_pending() (STR #128)
+ - The ppdEmit() functions output "PageSize Custom"
+ instead of "CustomPageSize True" in the DSC comments.
+ Also, the custom page size code did not use the
+ ParamCustomPageSize attributes (STR #127)
+ - The cupstestppd command did not list the conflicting
+ options (STR #123)
+ - The lpq command did not ensure that there was
+ whitespace between the fields in the job listing (STR
+ #117)
+ - The German web templates had errors (STR #119)
+ - The configure script didn't specify the static
+ libraries properly when configuring with the
+ --disable-shared option (STR #104)
+ - The cups.list file used file dependencies for package
+ formats other than portable, RPM, and Debian (STR #98)
+ - cupsLangGet() didn't use its language cache (STR #97)
+ - "lpq -P" would segfault instead of showing a usage
+ message (STR #94)
+ - Fixed compiler warnings in pdftops filter (STR #96)
+
+
+CHANGES IN CUPS V1.1.19rc5
+
+ - Jobs with banner pages that were printed to implicit
+ classes would get double banner pages for each
+ file/banner in the job (STR #68)
+ - The mime.convs file was missing the filter definition
+ for Windows BMP (image/x-bitmap) files (STR #85)
+ - The scheduler allowed some READ-ONLY job attributes to
+ be set, which could cause the scheduler to fail on the
+ next restart (STR #82)
+ - The lp and lpr commands did not report when the
+ scheduler was not responding; instead, the user would
+ incorrectly see a "no default destination" error (STR
+ #70)
+ - cupsLangGet() could fail on OSX due to a corrupt
+ language preference (STR #78)
+ - Added more checks for HTTP request timeouts.
+ - The scheduler dropped the first non-alpha character
+ after an open brace when doing attribute substitutions
+ in banner pages (STR #77)
+ - The scheduler child might send SIGUSR1 to the parent
+ before the signal handler was installed; this didn't
+ prevent the scheduler from starting but produced an
+ annoying error message (STR #45)
+
+
+CHANGES IN CUPS V1.1.19rc4
+
+ - The lp command did not accept "-" for printing from
+ the standard input as required by POSIX 1003.1 (STR
+ #59)
+ - Added the job-originating-host-name information for
+ the page_log file documentation in the SAM (STR #31)
+ - The German web interface templates did not use the
+ right paths for job operations (STR #54)
+ - The scheduler would consume all available CPU if
+ started with a pending job in the queue (STR #35)
+ - The polling daemon allocated an extra localization
+ buffer but did not free it, causing cups-polld to
+ eventually use all available memory (STR #40)
+
+
+CHANGES IN CUPS V1.1.19rc3
+
+ - The scheduler could get in an infinite loop cancelling
+ jobs using "cancel -u user dest" (STR #48)
+ - The "cancel -u user" command did nothing (it should
+ cancel all jobs on all printers owned by the named
+ user - STR #48)
+ - The scheduler would write 0-length job control files
+ (STR #46)
+ - Updated the French man pages (translation provided by
+ Gilles QUERRET)
+ - The scheduler would delete all printers from
+ printers.conf if a job was active when a HUP signal
+ was handled (STR #47)
+ - The cups-polld program would leak memory if it was
+ unable to send browse packets to the loopback
+ interface (STR #40)
+ - The scheduler did not put the
+ job-originating-host-name attribute in the job
+ attributes group.
+ - The text filter did not default to wrapping text as
+ defined by the IPP implementation document.
+ - Scan backends first, PPDs second (STR #37)
+ - Updated the Netatalk documentation in the SAM (STR #38
+ and #39)
+ - The test suite sent text files to a non-PS print queue,
+ which requires ESP Ghostscript (provided separately).
+ Now send the JPEG test file (STR #33)
+ - The test suite did not show the estimated disk space
+ requirements (STR #33)
+ - The test suite did not set the MaxLogSize directive to
+ 0 to prevent log file rotation (STR #33)
+ - The test suite still setup the old CUPS Ghostscript
+ symlinks (STR #33)
+ - The pstops filter did not report the correct number of
+ copies for the page_log file when printing collated
+ copies to a printer that doesn't support them in
+ hardware (STR #32)
+ - cupsLangGet() needs to set the CTYPE locale to "C"
+ (POSIX) to avoid erroneous tolower/toupper values (fix
+ suggested by Bjoern Jacke)
+ - Fixed a typo in the cups.list.in file.
+ - Updated all of the Western European locales to default
+ to ISO-8859-15 (for Euro support, suggested by Bjoern
+ Jacke)
+ - Updated the German message catalog (update provided by
+ Bjoern Jacke)
+
+
+CHANGES IN CUPS V1.1.19rc2
+
+ - cupsLangGet() now sets the encoding field based on the
+ trailing charset in the locale name, and doesn't look
+ for a message catalog in a specific locale.charset
+ directory. This fixes STR #26 and is more in line
+ with the CUPS 1.2 implementation.
+ - The configure script now aborts if the "ar" command or
+ compilers cannot be found.
+ - The static cupsimage library was not built by default.
+ - The path for the "ln" command was hardcoded in
+ Makedefs.in instead of being checked at configure time
+ (STR #28).
+ - Banner pages containing unescaped { characters would
+ not work.
+ - The printer-state-time collection attribute was
+ encoded as an enumeration instead of an integer.
+ - The printer-is-accepting-jobs collection attribute was
+ was not added to the collection value.
+ - The printer-state-sequence-number collection attribute
+ was not added to the collection value.
+ - Fixed typo and const mismatch in IPP backend.
+ - Updated the man pages for the new configuration
+ directives.
+ - Updated the SAM for MacOS 10.2, the CUPS drivers for
+ windows, the available LPD backend options, and the
+ new configuration directives.
+ - The imagetops filter didn't position images properly
+ on the page (STR #18)
+ - The configure script didn't add CPPFLAGS to the
+ compiler options or LDFLAGS to the DSO options (STR
+ #13)
+ - The scheduler would try to write a debug log message
+ when starting a job that contained a NULL string.
+ Since not all versions of snprintf() support NULL
+ string pointers this caused some problems (STR #20)
+ - The testipp program now supports reading of IPP
+ message files such as those used for the job history
+ in /var/spool/cups.
+
+
+CHANGES IN CUPS V1.1.19rc1
+
+ - Added CUPS support files for Java, Perl, and PHP
+ (located in the "scripting" subdirectory...)
+ - The scheduler now supports fast-reloads of the
+ cupsd.conf file when it is updated via HTTP.
+ - The scheduler always changed the ownership of log
+ files; it now only does so if they are not in the /dev
+ directory (i.e. don't want to change the ownership and
+ permissions of /dev/null...)
+ - Added libpaper support (patch from Jeff Licquia)
+ - Added a new istring() rule for MIME types files that
+ does a case-insensitive comparison of strings.
+ - The cups-lpd mini-daemon now sends jobs to the default
+ queue when an empty queue name (or "lp" and there is
+ no "lp" queue) is sent.
+ - The scheduler now supports fax queues identified by a
+ "*cupsFax: True" attribute in the PPD file. When a job
+ can't be sent, it is held for 5 minutes by default
+ while other jobs are attempted. The FaxRetryLimit and
+ FaxRetryInterval directives control the number of
+ retries and the time between retries.
+ - The scheduler now preserves the default options of PPD
+ files when modifying/upgrading an existing PPD file.
+ When installing a new printer, the scheduler sets the
+ default media size to Letter or A4 as appropriate for
+ your locale.
+ - The scheduler no longer limits the number of
+ BrowseAddress, BrowsePoll, BrowseRelay, Listen, Port,
+ SSLListen, and SSLPort directives to 10.
+ - The scheduler now supports print files that have been
+ compressed using gzip.
+ - The scheduler used the stdio functions to read any job
+ ticket information in a PostScript print job. Since
+ some platforms limit the number of stdio files to 256,
+ job ticket information was ignored when the server had
+ a large number of clients connected to the system.
+ - Filters and backends may now report the total number
+ of pages ("PAGE: total NNN") to the scheduler.
+ - The LPD backend now supports timeout and
+ sanitize_title options (default to 300 and yes,
+ respectively) and has some additional changes to
+ reduce the chances of multiple copies being printed
+ when only one copy was requested.
+ - Fixed a polygon drawing bug in the HP-GL/2 filter.
+ - Added a robots.txt file to the standard install to
+ prevent search engines from indexing the CUPS server.
+ - Added support for STATE: messages
+ (printer-state-reasons), printer-state-history, and
+ printer-state-time to the scheduler.
+ - When using RunAsUser, the scheduler would initially
+ start any previously queued (pending) jobs with
+ RunAsUser disabled - all backends would be running as
+ root.
+ - If a backend failed for a printer, CUPS would
+ incorrectly requeue the job for printing again.
+ - Added support for IPP collections and files.
+ - Added experimental support for generic CGI scripts and
+ programs, Java, Perl, PHP, and Python to the
+ scheduler. See the file "CGI.txt" for more
+ information.
+ - The CUPS API now supports HTTP cookies and the Expect:
+ field.
+ - The cancel command now correctly supports the "-u
+ user" option to cancel all jobs for the named user.
+ - The Purge-Jobs operation now supports the my-jobs
+ boolean attribute and a new purge-jobs boolean
+ attribute to control whether job history data is
+ purged from the scheduler; the default is false for
+ my-jobs and true for purge-jobs to match the original
+ implementation.
+ - The scheduler would not timeout printers when only
+ using SLP browsing.
+ - If the scheduler was unable to execute a filter, it
+ would try to restart the job indefinitely until the
+ filter could be executed.
+ - When writing BSD printcap files, the scheduler now
+ includes the rm and rp attributes, allowing the file
+ to be exported to LPD clients. [Patch from Dominic
+ Kubla]
+ - The scheduler optimization to reference IPP attribute
+ data instead of performing a full copy caused problems
+ when the referenced data was deleted before it was
+ sent. It now only references attributes that change
+ only when the scheduler is restarted. The change also
+ reduced the memory footprint of a printer object to
+ 2k.
+ - The scheduler now holds signals while logging messages
+ to avoid potential deadlock issues when handling
+ signals on Solaris 8.
+ - The lpadmin command now allows printer access control
+ by group name as well as user name.
+ - "lpoptions -l" got in an infinite loop if no default
+ printer was available.
+ - The scheduler now logs the job-originating-host-name
+ attribute in the page_log file, and uses "-" for any
+ empty fields (patch from Dominik Kubla).
+ - The pdftops filter now scales PDF pages within the
+ printable area of the page.
+ - The pstops filter didn't include the page-label and
+ classification boxes when printing EPS or non-
+ conformant PS files.
+ - The imagetops filter didn't always correctly position
+ the image on the page when printing in landscape
+ orientation.
+ - The ppdEmit() functions now support the
+ RequiresPageRegion attribute when sending InputSlot
+ and ManualFeed commands.
+ - The PPD loading code now supports standard options
+ outside of OpenUI/CloseUI as required by the PPD spec.
+ - The cupstestppd program has been upgraded to provide a
+ concise PASS/FAIL report, additional detailed
+ conformance testing, and support for gzip'd PPD files.
+ - The PPD loading code is now much more strict when
+ loading a PPD file, and tracks more format errors.
+ - The scheduler ignored child signals when gathering the
+ list of available devices, when it should have been
+ using the default signal handler.
+ - The cupsEncodeOptions() function could encode an
+ option with a NULL last string.
+ - The socket backend could report the wrong number of
+ backchannel bytes if an error occurred on the link.
+ - The cups-polld program now only sleeps after getting
+ all printers and classes. This allows for longer
+ intervals without excessive delays before classes show
+ up...
+ - Added a new httpWait() function to support waiting for
+ data for a specific number of milliseconds.
+ - httpGets() now times out after 1 second on
+ non-blocking HTTP connections.
+ - The scheduler no longer accepts rangeOfInteger values
+ that are out of order (e.g. 5-1)
+ - The sides attribute was incorrectly sent as a name
+ value; it is a keyword value.
+ - The IPP backend now detects if the destination queue
+ has gone away and reports an error.
+ - The scheduler and HTTP API now allocate their select()
+ sets to support larger numbers of clients on systems
+ that support it.
+ - The scheduler now sets the CFProcessPath environment
+ variable under MacOS X.
+ - The cupsLangDefault() function now uses the
+ CoreFoundation localization API under MacOS X.
+ - The httpSeparate() function didn't handle file URIs of
+ the form "file:///path" properly.
+ - The lpadmin command now supports a "protocol" option
+ for specifying the binary communications protocol to
+ use when printing binary PostScript data.
+ - The scheduler did not properly parse the SystemGroup
+ directive, so only the first group would be used.
+ - Revamped how strings are stored in the scheduler,
+ providing a substantial improvement in memory usage
+ for systems with large numbers of printers.
+ - The PostScript filter now supports binary PostScript
+ files and files beginning with the PJL language escape
+ sequence.
+ - The PPD API now provides additional information from
+ the PPD file.
+ - The USB backend didn't compile on Solaris Intel.
+ - The cupstestppd utility now supports the "-q" option
+ (quiet) for use in scripts, etc.
+ - Merged several weight-reducing changes into the CUPS
+ baseline donated by Apple.
+ - Added preliminary support for CDSA; patch provided by
+ Apple.
+ - Implicit classes are now created from identical
+ printer classes on the network.
+ - The lp command now supports a "-H restart" option to
+ restart previously printed jobs. This functionality
+ only works if you have enabled the PreserveJobFiles
+ option.
+ - The scheduler now supports URIs in HTTP request lines
+ to conform to the HTTP/1.1 specification.
+ - The time-at-xyz attributes were not recognized in
+ banner files if prefixed by a question mark, e.g.
+ "{?time-at-creation}".
+ - Added support for pre-filtering application/pictwps
+ files on MacOS clients before sending them to a server
+ via IPP.
+ - The scheduler now allows file:/dev/null device URIs
+ even if FileDevices is set to No.
+ - CUPS uses strerror() for hostname resolution errors,
+ when it should have used hstrerror().
+ - The USB backend no longer tries to guess the serial
+ number of a device from the USB devices file; this
+ means that printers that don't report their serial
+ numbers in the device ID string will not be
+ individually selectable.
+ - The pstops filter didn't handle page ranges properly
+ when a page contained an embedded document.
+ - Added a translation of the web interface to German.
+ - When printing using the OutputOrder=Reverse option
+ with duplexing, the output order is now truly
+ reversed; the order of sub-pages when printing N-up is
+ the same.
+ - The pstops filter did not always output the extra
+ blank page when printing a document with an odd number
+ of pages with duplexing enabled.
+ - The ippAddXYZ functions no longer allow the
+ application to add less than 1 value.
+ - Fixed a URL rewrite bug in the web interface - local
+ access was sometimes redirected away from localhost...
+ - The ppdOpen() functions could get in an infinite loop
+ if the PPD file contained a keyword or text that was
+ too large for the buffer.
+ - Added preliminary support for GNU TLS; patch provided
+ by Jeff Licquia.
+ - Now timeout IPP attribute reads after 1 second inside
+ an attribute definition.
+ - Now timeout connections that have been shutdown (due
+ to errors) after 30 seconds instead of the Timeout
+ setting (300 seconds by default). This provides
+ faster recovery from DoS attacks.
+ - A denial-of-service attack warning message was being
+ written to the log files by the scheduler for every
+ detection. This caused a DoS of its own in some
+ situations. The warning message is now written no more
+ than once per minute.
+ - Fixed the CIE colorspace support code in the image and
+ PS RIPs.
+ - The job-quota-period, job-page-limit, and job-k-limit
+ attributes were not flagged as integers, so setting
+ quotas would not work.
+ - Added an additional response check in the scheduler to
+ more quickly recover from denial-of-service attacks.
+ - The cupstestppd file was incorrectly installed in the
+ /usr/sbin directory instead of /usr/bin.
+ - The EPM list file did not include the cupstestppd
+ program or man page files.
+
+
+CHANGES IN CUPS V1.1.18
+
+ - Fixed a bug in the Set-Job-Attributes code in the
+ scheduler that would cause it to crash or continuously
+ write a job control file.
+ - SECURITY FIX: The scheduler now provides a FileDevice
+ directive to control whether new printers can be added
+ using device URIs of the form "file:/filename". The
+ default is to not allow printers with these device
+ URIs.
+ - The scheduler did not compute the cost of filters
+ properly, nor did it choose a multi-filter solution
+ with a lower cost than a single filter solution.
+ - Now install CUPS PPD file test utility (cupstestppd)
+ to support basic conformance testing of PPD files.
+ - The scheduler now logs an error message when it sees a
+ non-conforming PPD file.
+ - Upgraded pdftops filter to Xpdf 2.01 with fixes for
+ TrueType fonts.
+ - Added a MaxClientsPerHost configuration directive to
+ provide limited protection against Denial of Service
+ attacks.
+ - SECURITY FIX: Potential underflow/overflow bug in web
+ interface.
+ - SECURITY FIX: Race condition in certificate creation.
+ - SECURITY FIX: Bad URIs in browse packets could be used
+ to exploint the web interface underflow/overflow bug.
+ - SECURITY FIX: Some types of Denial of Service attacks
+ were not handled properly, so once the attack was over
+ the scheduler did not close the connections
+ immediately on all platforms.
+ - SECURITY FIXES: Added integer overflow/underflow
+ checks for all image formats.
+ - The pstops filter didn't reset the showpage operator
+ back to its original at the end of a job; this
+ prevented the concatenation of documents (used
+ primarily for CUPS 1.2...)
+ - The cupsGetPPD() function didn't always set the
+ cupsLastError() value when an error occurred.
+ - The IPP media, output-bin, and sides attributes took
+ precedence over the corresponding PPD options, which
+ caused inconsistent behavior under MacOS X with some
+ PPD files.
+ - The cupsaddsmb utility specified the wrong number of
+ arguments to the adddriver command when adding the
+ Win9x PostScript drivers.
+ - The web interface did not always report the correct
+ error message.
+ - The scheduler did not clear the POSIX signal action
+ structure when waiting for the child to send it a
+ SIGUSR1 signal; this could cause the signal handler
+ not to be called properly, preventing the parent
+ process from returning.
+
+
+CHANGES IN CUPS V1.1.17
+
+ - The "manual_copies" option did not work when the LPD
+ backend had to retry a print job.
+ - The image filters did not convert GIF images properly.
+ - The RunAsUser option was incompatible with the new
+ daemon-mode code in 1.1.16.
+ - Fixed a problem with the Set-Job-Attributes and
+ PostScript job ticket code in the scheduler - the
+ "last" attribute pointer was never updated, which
+ could cause the scheduler to crash when applying job
+ ticket data.
+ - Fixed a problem in the scheduler that caused it to
+ continue processing HTTP requests on a connection
+ after it was shutdown.
+ - The scheduler now allows accounts authenticated via
+ PAM to not have a corresponding UNIX account, but
+ group membership still requires the account name to be
+ listed in the UNIX group file(s)...
+ - The scheduler used a fixed-size (16k) buffer for
+ encoding job options for filters; it now dynamically
+ allocates and expands the buffer as needed depending
+ on the options that are sent in a job.
+ - The pdftops filter didn't support all of the MacOS
+ characters for MacRoman encoded fonts.
+ - The cupsEncodeOptions() and cupsParseOptions()
+ functions now conform to the grammer defined by the
+ current draft of the PAPI specification. The main
+ difference is that option=yes and option=no are no
+ longer treated as boolean options.
+ - The IPP backend didn't honor the encryption settings
+ in /etc/cups/client.conf.
+ - Fixed a potential bug in the HTTP code which was
+ caused by servers sending the status line and
+ newline(s) in separate packets.
+ - User-defined classification strings are now printed
+ verbatim - previously the classification box would be
+ empty.
+ - Re-added Spanish to the list of PPD languages that
+ CUPS supports.
+ - CUPS API library user and temp file updates for
+ Windows.
+ - The image filters did not properly handle grayscale
+ printing of Sun Raster images.
+ - The scheduler never reset the NumJobs variable before
+ loading the job list (previously this only happened on
+ a full start, so the problem was never apparent...)
+ - The HTTP and IPP read/write code didn't handle EINTR
+ (interrupted system call) errors.
+ - When under high load, the scheduler could abort due to
+ the wrong errno value after a select() call. This was
+ caused by the child signal handler.
+ - Added new load tests to the test target to verify that
+ cupsd can handle hundreds of simultaneous jobs without
+ error.
+ - The Solaris USB backend now supports the new device
+ URI syntax.
+ - The ppdOpen*() functions now reset the numeric locale
+ settings while loading a PPD file.
+ - Fixed the libtool build rules.
+ - The manpage make rules didn't use $(MAKE) and
+ $(MFLAGS) for the language subdirectories.
+ - Now set the LC_TIME locale category to get the
+ properly localized time string.
+ - Fixed a problem in the scheduler that would cause the
+ web interface problems when adding, modifying, or
+ configuring a printer or class.
+ - The backends now ignore SIGPIPE so that failed job
+ filters will not stop a print queue.
+ - The lpstat command did not allow for destination lists
+ ("lpstat -v printer1,printer2")
+ - Fixed parsing of long filter status messages in the
+ scheduler.
+ - Added some startup performance enhancements to the
+ scheduler so that the printer object information is
+ regenerated fewer times and the MIME type database is
+ not filled with lots of empty filters for raw/direct
+ queues.
+ - The LPD backend now sends the job title as the print
+ filename.
+ - Added support for variable sizes in the EPSON dot
+ matrix printer drivers. This allows for pages as
+ short as 1/2" (1 row of labels) and does not do an
+ automatic form feed.
+ - French translation updates.
+ - The filters did not quote the page label string when
+ embedding it in PostScript output.
+ - The serial backend now enumerates serial ports under
+ MacOS X.
+ - The pdftops filter contained font rasterizer code that
+ wasn't being used and that depended on X11. This code
+ has been removed.
+
+
+CHANGES IN CUPS V1.1.16
+
+ - The cancel and lprm commands now both display an error
+ message and return a non-zero exit status if an
+ attempt is made to cancel a job on a non-existent
+ printer.
+ - The lpoptions command incorrectly complained if a
+ request to delete a non-existent printer was made.
+ - If the client.conf file defines an alternate server
+ name, the "configure printer" action in the web
+ interface might not work.
+ - The lpstat command now supports a "-W" option so that
+ you can display completed jobs as well as
+ not-completed (pending) jobs.
+ - The lp and lpr commands did not return an error when
+ one or more files in a set of files for printing could
+ not be printed.
+ - The lp, lpadmin, and lpstat commands now consistently
+ return with a non-zero exit status when an error
+ occurs.
+ - The scheduler would not accept print jobs sent to a
+ stopped remote printer.
+ - The texttops filter incorrectly converted the page
+ numbers in the prettyprint header to double-byte
+ characters when printing a non-Unicode text file. This
+ caused an extra space to appear between each digit in
+ the page number.
+ - The scheduler did not use a case-insensitive
+ comparison when adding filters for a printer.
+ - Upgraded the pdftops filter to Xpdf 1.01.
+ - The scheduler no longer passes the page-border and
+ number-up-layout attributes to filters when printing
+ banner pages.
+ - The LPD backend now uses a 30-second timeout when
+ sending commands and control files, and a 30-second
+ timeout when retrieving responses from an LPD server.
+ If a timeout occurs, it retries indefinitely. This
+ helps to make LPD printing over VPNs work more
+ reliably.
+ - The USB backend now supports device URIs based on the
+ printer serial number and/or model number under Linux.
+ This avoids the "wrong device filename" problem when
+ using more than one USB printer.
+ - Now just shutdown the receiving end of a client
+ connection when sending an error that requires the
+ server to disconnect from the client afterwards. This
+ fixes a problem when doing remote administration with
+ encryption enabled.
+ - The scheduler did not send a printer-state-message
+ attribute if the string was empty; it now always sends
+ this attribute. This caused the printer message to be
+ displayed for other printers in the web interface.
+ - The LPD backend now supports a "manual_copies" option,
+ e.g.: "lpd://server/queue?manual_copies=no", in order
+ to handle copies for raw jobs to printers that don't
+ implement the LPD protocol properly...
+ - The "mirror" option was not being handled by the
+ PostScript or image filters.
+ - Updated the cupsaddsmb command to support the new CUPS
+ driver for Windows NT/2k/XP.
+ - Filter status lines longer than 1023 characters could
+ cause the scheduler to get into an infinite loop.
+ - The scheduler didn't reset the job state to pending
+ when modifying an active printer.
+ - Now limit the maximum number of recursion steps when
+ searching for a filter for a job, in case a user
+ defines a circular filter rule.
+ - The PostScript filter would embed an invalid
+ requirements comment in some cases.
+ - Added support for embedded job tickets in PostScript
+ files.
+ - The PostScript filter now detects EPS files and should
+ better handle printing EPS files.
+ - The cancel command now ignores a trailing destination
+ name when cancelling a specific job ID (Solaris
+ compatibility).
+ - The scheduler now rejects jobs with copies outside the
+ range of 1 to MaxCopies, inclusive.
+ - Added new MaxCopies directive to set the maximum
+ number of copies that a user can request.
+ - The scheduler didn't block signals while it processed
+ others and when it forked processes.
+ - The scheduler checked for new jobs to print when
+ stopping a job. This caused jobs to restart before a
+ shutdown.
+ - Updated the CUPS startup script to better support
+ different timezones and to support the RedHat/Mandrake
+ init script functions, if available.
+ - The scheduler did not properly handle backslashes in
+ banner files; it incorrectly assumed that "\c" should
+ always be replaced by "c", instead of only looking for
+ "\{" and replacing it by "{".
+ - The texttops filter didn't handle prettyprint=no.
+ - The text and HP-GL/2 filters didn't check for other
+ common duplex option names like cupsMarkOptions() did.
+ - "lpoptions -x printer" no longer clears the "default
+ printer" status of the printer.
+ - cupsTempFd() now stops trying to create a temporary
+ file after 1000 tries, and aborts on any error other
+ than EEXIST. This should prevent lp/lpr hangs due to
+ a bad or missing temporary directory.
+ - The lpadmin command did not send the right URI to the
+ scheduler when setting options on classes. This
+ caused a client-error-bad-request error.
+ - The CUPS API convenience functions would attempt to
+ connect to the remote server name in a
+ "printer@server" printer name instead of dealing with
+ the default (usually local) server. Aside from
+ causing user confusion, the remote server name might
+ not be resolved properly, causing further problems.
+ - "lp -q" would cause the "lp" command to segfault, as
+ the program would try to print the option letter that
+ caused the error using the wrong index into the
+ command-line; bugfix from Debian.
+ - Fixed a minor inconsistancy in the encoding of boolean
+ attributes from printer options in
+ cupsEncodeOptions().
+ - Added a FilterNice directive which sets the priority
+ of job filter processes that are run by the scheduler.
+ - Added Solaris x86 USB printer support.
+ - The USB backend now reports both the ulpt and unlpt
+ devices under *BSD.
+ - The "lpstat -o" command would truncate the
+ "printer-jobid" string if it was longer than 21
+ characters.
+ - The PJL-based MIME type rules now look in the first
+ 1024 bytes instead of just the first 512 bytes to find
+ the language mode.
+ - The image file types are now listed explicitly in the
+ mime.convs file so that additional image file formats
+ do not use the standard CUPS image filters by default.
+ - Updated the Software Programmers Manual to include
+ all of the CUPS API functions.
+ - ppdOpen*() no longer sorts choices for an option.
+ - The web interface now enforces constraints in PPD
+ files when configuring a printer.
+ - When stopping a printer, the scheduler didn't set the
+ printer state before stopping the current job.
+ - The cupsaddsmb utility now lists all data files for
+ Win9x and WinMe clients when installing that Windows
+ driver.
+ - Jobs submitted to a class now bounce immediately to
+ the next available printer rather than waiting until
+ that printer is available.
+ - Filters and backends now also get the CLASS
+ environment variable set when a job is printed to a
+ printer class instead of a normal printer.
+ - Added French translations of the web interface, CUPS
+ Overview, Software Administrators Manual, and Software
+ Users Manual contributed by Marian REYT-LLABRES.
+ - Added several "hint" messages for common configuration
+ problems that are stored in the error_log file.
+ - httpSeparate() now unquotes %xx characters in the
+ username:password field of a URI.
+ - When starting the scheduler in daemon mode, the parent
+ process now waits for the child to signal it is ready
+ to accept connections.
+ - Added -F option to cupsd to run cupsd in the
+ foreground but detach from the controlling terminal
+ and current directory.
+ - The scheduler did not reload jobs when receiving a HUP
+ signal; this would cause problems since the pointers
+ into the file type database would no longer be valid
+ for existing jobs.
+ - The scheduler did not save the network interface list
+ update time, thus no caching of the network data was
+ actually provided.
+ - Updated the SuSE PAM configuration file.
+ - The LPD backend now supports a "reserve" option and no
+ longer reserves a priviledged port by default.
+ - The cupsaddsmb command now continues past printers
+ that do not have a PPD file to export.
+ - The lpstat command didn't treat printer names as
+ case-insensitive.
+ - The lpstat command now reports the printer location
+ attribute with "lpstat -l -p".
+ - Fixed a bug in the vsnprintf() emulation function,
+ which was used on old versions of HP-UX, IRIX, and
+ Solaris.
+ - The number-up option was incorrectly being used when
+ printing banner pages.
+ - Added support for Greek and Slovak PPD files.
+ - CUPS now supports printer names containing any
+ printable character, e.g. "123-abc", "foo-bar", etc.
+ - The null filter was not supported in mime.convs due to
+ a bug in the filter validation code.
+ - Changes in the default printer and printer attributes
+ were not always reflected in the generated printcap
+ file.
+ - Implicit classes did not inherit the location or
+ description from member printers.
+ - The httpGetHostByName() function did not handle
+ hostnames that started with a number.
+ - Updated the filters to use the %cupsRotation comment
+ instead of %%Orientation to auto-rotate pages, since
+ the use of %%Orientation is inconsistent.
+ - Added the RootCertDuration directive to control how
+ often the root authentication certificate is updated.
+ - Increased the size of the IPP write buffer to 32k to
+ allow for larger attribute values and to provide more
+ efficient output of large numbers of attributes.
+ - The polling daemon now retries the initial connection
+ to the remote server; this fixes a problem when the
+ remote server is unavailable when the scheduler starts
+ up...
+ - The scheduler didn't validate Digest users against the
+ system group(s), so Digest and BasicDigest
+ authentication didn't work for administration
+ operations.
+ - The scheduler now passes the SHLIB_PATH environment
+ variable to child processes (HP-UX shared libraries)
+ - The scheduler now maps accesses from the loopback
+ interface to "localhost".
+ - The cups-lpd mini-daemon sent a status code byte in
+ response to queue state commands, but those commands
+ only return textual data.
+
+
+CHANGES IN CUPS V1.1.15-1
+
+ - The lpc and lprm sources didn't include the CUPS
+ string function header, which is required on systems
+ that don't have their own snprintf() function.
+ - The French manpage Makefile tried to install the
+ language subdirectories when it (obviously) didn't
+ have to.
+
+
+CHANGES IN CUPS V1.1.15
+
+ - Updated the CUPS license agreement for the new MacOS
+ and OpenSSL license exceptions.
+ - The printer-info attribute now defaults to the printer
+ name if no value has been set.
+ - ppdOpen() and friends now add an "Auto" InputSlot
+ option if none is provided to automatically select the
+ correct tray.
+ - Updated the ppdEmit() and ppdEmitFd() functions to
+ (re)mark the correct PageSize or PageRegion option
+ depending on the selected ManualFeed or InputSlot
+ options.
+ - ppdEmitFd() didn't handle custom page sizes.
+ - Darwin uses <pam/pam_appl.h> instead of
+ <security/pam_appl.h>.
+ - The jobs.cgi web interface now handles all job
+ operations, allowing the administrator to allow "job
+ administrators" or operators to manage jobs (but not
+ queues) on the server.
+ - The cupsDoFileRequest() function now checks if the
+ filename passed into the function is a directory, and
+ returns the IPP_NOT_POSSIBLE error if so.
+ - New SCSI printer backend.
+ - Cleaned up handling of locales with trailing character
+ set definitions.
+ - Fixed handling of invalid PPD attributes inside
+ OpenUI/CloseUI.
+ - Fixed a problem with SSL and the job, printer, and
+ admin CGIs on ports other than 443.
+ - The scheduler didn't handle AuthClass properly.
+ - Added French translation of man pages.
+ - Updated the text filter to support the const_cast,
+ dynamic_cast, and static_cast keywords in ISO C++.
+ - Now use strlcat() and strlcpy() (or emulation
+ functions) for easier string/buffer protection.
+ - The auto-generated printcap/printers.conf files now
+ have a small comment header explaining where the file
+ comes from...
+ - The PostScript filter now supports 6, 9, and 16-up
+ output, as well as new page-border and
+ number-up-layout options.
+ - The lpoptions command didn't set options properly when
+ using the default printer.
+ - Added ConfigFilePerm and LogFilePerm directives.
+ - Increased maximum size of MIME types to IPP_MAX_NAME
+ to allow for longer printer names.
+ - No longer create remote printers when loading job
+ history data.
+ - The printer-make-and-model attribute wasn't set when
+ the PPD file didn't contain a NickName attribute.
+ - Now handle PPD files with translation strings longer
+ than 80 bytes - they are truncated if they go over...
+ - The scheduler didn't handle signals until after it
+ loaded the configuration files the first time; this
+ caused problems on some installations that would
+ restart the scheduler as the system booted into run
+ level 3.
+ - Now throttle broadcasts like we do for polling.
+ - Fixed a bug in the reading of PPD files using CR's
+ instead of CR LF's or LF's.
+ - The scheduler would crash if cupsd.conf contained a
+ BrowseProtocols line with no protocols listed.
+ - The HTML job operation templates now link back to the
+ destination printer or class.
+ - The serial backend now detects USB serial devices.
+ - The LPD mini-daemon (cups-lpd) now passes the
+ job-originating-host-name attribute to the scheduler
+ (cupsd).
+ - Updated the IPP backend to reconnect after downgrading
+ from IPP/1.1 to 1.0, and when sending requests to HP
+ JetDirect interfaces that don't support HTTP
+ Keep-Alive like they should.
+ - Now pass NLSPATH and DYLD_LIBRARY_PATH environment
+ variables, if defined, to CGI and job processes.
+ - Removed the pstoraster filter (based on GNU
+ Ghostscript 5.50) and now provide the raster "driver"
+ and patch file necessary to use the current GNU
+ Ghostscript 7.05 release.
+ - Removed unnecessary fonts and updated the Courier and
+ Symbol fonts to the latest versions to better support
+ non-ISOLatin1 text.
+ - The text filter now always embeds the Courier and
+ Symbol fonts to ensure that they contain the full set
+ of glyphs.
+ - The lp and lpr commands now only override the SIGINT
+ handler if it is not being ignored (patch from Robert
+ Ambrose for some interactive software that catches
+ SIGINT and will gracefully cancel the print...)
+ - The PostScript image filter (imagetops) now supports
+ printing CMYK images using the CMYK colorspace.
+ - The image filters now support CMYK JPEG files, and
+ correctly handles the inverted files from Photoshop
+ (which seems to save RGBW data, not CMYK...)
+ - Added a "check" target to the top-level makefile to
+ conform with GNU standards (same as "test").
+ - The IPP code didn't always map the POSIX locale "C" to
+ the proper IPP language code.
+ - The cupsaddsmb program was updated to use the
+ setdriver command instead of addprinter.
+ - Banner pages were not handled properly for implicit
+ classes.
+ - When tunneling to a remote system using SSH, the
+ printer URIs for local printers on the remote system
+ did not reflect the correct port number.
+ - The Allow, Deny, BrowseAllow, BrowseDeny, and
+ BrowseAddress directives now support the network
+ interface names "@LOCAL" and "@IF(name)" for access
+ control and browsing based on the current interface
+ addresses instead of fixed names or IP addresses.
+ - The texttops filter did not properly recognize the
+ "nowrap" (wrap=false) option.
+ - The InstallableOptions group name in a PPD file is now
+ translated separately (CUPS_MSG_OPTIONS_INSTALLED) so
+ that UIs can accurately detect the presence of this
+ group.
+ - The scheduler no longer keeps job history data for
+ remote printers on the client (just on the server.)
+ - The parallel and USB backends now retry if the backend
+ detects that the printer is not connected to the
+ system (rather than stopping the queue...)
+ - The network backends now retry if the backend detects
+ that the printer is not connected to the network or is
+ unreachable (rather than stopping the queue...)
+ - The cupsGetDests() function no longer lists options
+ and instances for printers that no longer exist.
+ - The scheduler now converts the document language to
+ the correct LANG string.
+ - The cupsaddsmb program now supports alternative CUPS
+ and SAMBA server names.
+ - The PostScript filter now supports the Orientation
+ comment and rotates the page as needed automatically.
+ - Revamped the makefiles slightly to use automatically
+ generated dependencies.
+ - Build fixes for OS X.
+ - The TIFF reading code depended on the newest version
+ of libtiff; now conditionally compile that portion of
+ the loader.
+ - The PPD code now decodes all JCL options in the
+ JCLSetup group, not just those options that start with
+ the prefix "JCL".
+ - The backends now read print data using the read()
+ system call to ensure that the current page is printed
+ while the next page is being processed.
+ - The pdftops filter did not support shading type 3
+ (radial fill) for the "sh" operator.
+ - The cups-polld program now throttles the local
+ broadcasts of polled printers and classes so that the
+ local system is not overwhelmed with hundreds of
+ printers and classes all at once.
+ - Updated the serial backend to support 230,400 baud for
+ the Linux PPC port.
+ - The cupsGetJobs() function wouldn't report completed
+ jobs that did not have a document-format attribute
+ value.
+ - The cupsEncodeOptions() function now maintains a table
+ of known boolean and numeric options, and encodes all
+ other options as strings.
+ - Now add a newline before the end-of-page code in the
+ PostScript filter; this fixes a problem with files
+ that don't end with a newline.
+ - The image filters looked for the "orientation" option
+ instead of the correctly named "orientation-requested"
+ option.
+ - The cupsEncodeOptions() function now handles mixed
+ integers and ranges.
+ - New translation guide for developers to provide native
+ language support for CUPS.
+
+
+CHANGES IN CUPS V1.1.14
+
+ - The ippRead() function did not verify that the
+ attribute name length or string with language value
+ was not larger than the read buffer.
+ - The scheduler set the signal handlers before loading
+ the configuration files the first time; this prevented
+ the RunAsUser directive from blocking server reloads.
+ - Added Swedish message catalog.
+ - The parallel backend now recognizes the /dev/printers
+ device directory under Linux 2.4.x.
+ - MacOS X fixes.
+ - The cupsaddsmb utility sent the server name after the
+ user information when executing the rpcclient program.
+ This caused problems with some versions of SAMBA
+ 2.2.x.
+ - The IPP backend did not pass the requesting user name
+ when checking on the print job status. This prevented
+ it from waiting for the job to complete when
+ communicating with some IPP implementations that
+ require it.
+
+
+CHANGES IN CUPS V1.1.13
+
+ - The lpstat command did not report jobs submitted to
+ regular printer classes.
+ - The texttops filter didn't use sufficient precision
+ when positioning text with some values of cpi and lpi.
+ This could cause the alignment of text to stray.
+ - cupsGetDests() didn't merge the options from the
+ /etc/cups/lpoptions file with ~/.lpoptions - options
+ in ~/.lpoptions overrode them completely.
+ - Added support for KOI8-R and KOI8-U character sets,
+ and added several Russian message catalogs.
+ - The scheduler put the wrong timezone offset in the log
+ files (e.g. +0500 instead of -0500 for EST...)
+ - The scheduler did not ignore trailing whitespace in
+ *.convs files.
+ - The scheduler now forces all processes to exit (kill
+ -9) when it is stopped. This prevents parallel and
+ USB devices from running in the background after cupsd
+ goes away.
+ - The cupsParseOptions() function didn't skip trailing
+ whitespace after quoted values.
+ - More changes to support CUPS on OS/2.
+ - Added Simplified Chinese message catalog.
+ - Added PAM support for IRIX.
+ - The cupsGetPPD() function didn't remove the @server
+ portion of the printer name, and since it would
+ connect immediately to the remote server instead of
+ the local server, the printer would not be found.
+ - Classification and page labels were not rotated to
+ match the page orientation.
+ - Now set the TCP "no delay" option on network
+ connections to improve performance/response time.
+ - Improved the IRIX printing tools support with patches
+ from Andrea Suatoni.
+ - Added a new PrintcapGUI directive to specify the GUI
+ option panel program to use for the IRIX printing
+ tools support.
+ - The cupsGetDests() function did not check to see if a
+ user-defined default printer (set via lpoptions) still
+ existed.
+ - The pstops filter no longer assumes that the default
+ dictionary is writable when doing N-up processing.
+ - The pstops filter now supports printing N-up with the
+ page-set option.
+ - The imagetoraster filter now supports direct printing
+ of CMYK image data without conversion/correction.
+ - The IPP backend now reports printer state/error
+ conditions when possible (toner low, media empty,
+ etc.)
+ - The lpstat command now supports the (undocumented)
+ IRIX -l option ("-lprintername") for a compact job
+ listing for a printer.
+ - The lpstat command now includes printer date/time
+ information in the output (always Jan 01 00:00) to
+ make third-party tools happy.
+ - The text filter now supports non-integer cpi and lpi
+ values.
+ - The Margins field in the CUPS raster header was not
+ initialized by the pstoraster filter.
+ - Added --with-optim="flags" option to configure script.
+ - Updated the Italian message translations.
+ - Updated the cups.list file to install the correct
+ files.
+ - The pstoraster filter accessed the third element of a
+ 2 element array.
+ - The scheduler did not setup a status pipe for polling
+ processes, so error messages went to whatever file
+ descriptor 2 was pointing to when they were started.
+ - The httpMD5Final() function didn't put a colon between
+ the password and nonce strings.
+ - The pstops filter did not default to Binary data for
+ "%%BeginData:".
+ - The pstops filter did not stop processing when a line
+ containing a CTRL-D is seen.
+ - The scheduler no longer replaces the JobSheets values
+ from the printers.conf and classes.conf files with the
+ classification level, if set. This way the original
+ banner settings are preserved when classification
+ levels are changed or turned off.
+ - The serial backend didn't drain the output queue, nor
+ did it restore the original settings.
+ - Updated the default system group under MacOS X.
+ - If no SystemGroup was defined in cupsd.conf, the
+ system default group was not used.
+ - The cups-lpd mini-daemon now supports LPD clients that
+ send multiple control files.
+ - httpConnectEncrypt() now always uses encryption for
+ connections on port 443, since port 443 is reserved
+ for the "https" scheme.
+ - Group authentication via certificates did not work
+ from the web interface for accounts other than
+ "root".
+ - The serial port backend did not clear the OPOST
+ option, which could cause problems with some printers.
+ - The cups-lpd mini-daemon didn't lookup the client IP
+ address properly.
+ - The parallel backend now identifies the polled and
+ interrupt-driven devices under *BSD.
+ - The scheduler allowed the "always" encryption mode
+ inside a Location, which is not valid.
+ - The CUPS startup script now checks for the timezone
+ information under Linux.
+ - Now also map the sides attribute to the JCLDuplex
+ option (if present) in PPD files.
+ - Updated pdftops to Xpdf 0.93a.
+ - Added support for MD5 passwords under Slackware.
+ - Added new AuthType BasicDigest that does Basic
+ authentication using the MD5 password file managed by
+ the lppasswd command.
+ - The banner page attribute substitution code now
+ retains {name} sequences in banner files when the
+ named attribute is undefined. Use {?name} to
+ conditionally substitute an IPP attribute.
+ - The scheduler now ensures that the ServerRoot
+ directory and configuration files are owned by and
+ writable by the User and Group in cupsd.conf.
+ - The USB backend now lists all USB printer devices
+ regardless of whether a printer is connected or not.
+ This allows new USB printers to be connected without
+ restarting cupsd.
+ - Added some more minor performance tweeks to the IPP
+ protocol code to reduce copying and array indexing.
+ - The cupsaddsmb utility now uses the -c option with
+ smbclient and rpcclient to avoid the read length limit
+ for commands on the standard input.
+ - Added an include file to the CRD handling code in
+ pstoraster so that it would compile properly on 64-bit
+ pointer platforms...
+ - The cups-config script reported the wrong version
+ number.
+ - The cups-config script was installed in $(bindir)
+ instead of $(BINDIR).
+ - The init script did not correctly check for a running
+ cupsd under IRIX 5.x.
+
+
+CHANGES IN CUPS V1.1.12
+
+ - Added "Polish" to the list of known languages for PPD
+ files.
+ - Added missing directory definition to cups-config.
+ - The CUPS-Move-Job operation did not set the
+ destination type for the new destination.
+ - The CUPS-Add-Printer operation did not support the
+ allow=all or deny=none values to clear the per-user
+ printer ACLs.
+ - The SetPrinterAttrs() function did not handle invalid
+ PPD files that were missing the required NickName
+ attribute. It now looks for NickName, ModelName, and
+ then substitutes the string "Bad PPD File" for the
+ printer-make-and-model attribute.
+
+
+CHANGES IN CUPS V1.1.11
+
+ - Added support for embedded TrueType fonts in PDF
+ files.
+ - Added support for PostScript functions in PDF
+ files.
+ - Added new "cupsaddsmb" utility for exporting
+ CUPS printer drivers to SAMBA/Windows clients.
+ - Added preliminary support for Darwin/MacOS X.
+ - The CUPS-Add-Printer operation no longer allows
+ arbitrary scheme names in device URIs to be used - it
+ now restricts the available schemes to those found in
+ the device list (lpinfo -m).
+ - The ippRead() and ipp_read_file() functions could not
+ handle more than IPP_MAX_VALUES (100) values in a
+ 1setOf attribute. These functions have been updated
+ to dynamically allocate more memory as needed, and the
+ IPP_MAX_VALUES constant now represents the allocation
+ increment. [this caused some versions of the
+ GIMP-print drivers to fail since the number of media
+ options exceeded 100...]
+ - The scheduler could crash when BrowseShortNames
+ was set to "No".
+ - The scheduler did not prevent MaxClients from being
+ set to 0, which could cause the scheduler to go in an
+ infinite loop when accepting a request.
+ - Made some performance optimizations in the ippRead()
+ functions to make IPP request/response processing
+ faster.
+ - The accept/reject/enable/disable command did not
+ support properly support the "-h" or default
+ server name.
+ - The scheduler did not save the quota configuration
+ when the job-quota-period attribute was set to 0.
+ - The LPDEST and PRINTER environment variables did not
+ support printer instances.
+ - The text filter now handles more types of boldface and
+ underline formatting.
+ - The cupsTempFd() function did not fail if the
+ temporary directory did not exist; this would cause it
+ to loop indefinitely instead of returning an error
+ (-1).
+ - Stopping (disabling) a printer class did not stop jobs
+ from printing to printers in that class.
+ - The cupsGetDests() function was sending the
+ requested-attributes attribute as a name instead of a
+ keyword; this caused a serious performance problem on
+ slower systems since more information had to be
+ transferred from server to client.
+ - The web interfaces did not always quote < and & in
+ things like the job title. This had the potential for
+ browser-based security violations (on the browser's
+ machine); bug report from SuSE.
+ - The scheduler now treats unauthenticated usernames as
+ case-insensitive when doing quota and allow/deny
+ processing.
+ - The lp command sent the "request ID is ..." message
+ to stderr instead of stdout...
+ - The PostScript filter (pstops) now handles EPS files,
+ adding a showpage command to the files as needed.
+ - The configure script checked for the <stdlib.h> header
+ file before the JPEG libraries; since the JPEG headers
+ can define HAVE_STDLIB_H, the configure check would
+ cause the JPEG check to fail on some systems.
+ - The scheduler now supports localized banner files,
+ using the subdirectory approach, e.g. the "es"
+ subdirectory under /usr/share/cups/banners is used for
+ the Spanish banner files.
+ - Updated the scheduler so it knows the correct
+ language abbreviation to use for all supported
+ PPD LanguageVersion values. The new code also
+ supports country codes as well, so "English-GB"
+ maps to the "en_GB" locale.
+ - The cups-lpd mini-daemon did not support
+ anonymous printing (no username specified).
+ While the username is REQUIRED by RFC-1179,
+ MacOS clients do not send the REQUIRED username
+ information when printing via LPD.
+ - Added many warning and informational messages
+ to cups-lpd where they were missing.
+ - Added Czech message file contributed by SuSE.
+ - The cups-lpd mini-daemon now returns a non-zero
+ status if an invalid destination or job ID is
+ provided.
+ - The scheduler did not honor the KeepAlive setting in
+ cupsd.conf.
+ - Increased the size of the file read/write buffers to
+ 32k.
+ - *BSD static library creation fixes.
+ - Use mkstemps() instead of tmpnam() in pdftops whenever
+ possible.
+ - Added httpGetHostByName() function as a wrapper around
+ gethostbyname() - some implementations of this
+ function do not support IP addresses (e.g. MacOS X.)
+ - Added casts to all printf's of file lengths, since
+ there is currently no standard way of formatting long
+ long values.
+ - The client filename field was not cleared in all
+ instances, resulting in old form data being submitted
+ to CGIs.
+ - The httpConnect*() functions now try all available
+ addresses for a host when connecting for the first
+ time.
+ - The pstoraster filter would "lose" all drawing
+ commands when the PageSize was set but the printer
+ bitmap was not reallocated. This was most noticeable
+ with the output from StarOffice 6 beta and would
+ result in a blank page being output...
+ - The IPP backend was sending a PAGE comment even when
+ printing the output from a filter (it should only send
+ page comments when printing files directly...)
+ - The pdftops filter didn't properly map glyph names of
+ embedded Asian TrueType fonts.
+ - Changed the CUPS startup script to look for a program
+ named "cupsd", not just any program with "cupsd" in
+ the name (this caused the apcupsd UPS monitoring
+ daemon to be stopped/restarted...)
+ - The CUPS-Move-Job operation did not change the
+ internal destination name for held jobs, so moved (but
+ held) jobs would still show up as queued on the
+ original destination.
+ - The cups-polld program didn't send the
+ requested-attributes attribute in the
+ CUPS-Get-Printers and CUPS-Get-Classes requests, which
+ made it use more CPU and bandwidth than required.
+ - The scheduler and CUPS API incorrectly added a
+ job-sheets-default attribute for remote printers. This
+ caused banner pages to be omitted from client system
+ prints.
+
+
+CHANGES IN CUPS V1.1.10-1
+
+ - Minor fixes to the filter, systemv, and template
+ makefiles to install files properly.
+
+
+CHANGES IN CUPS V1.1.10
+
+ - Added a driver for DYMO label printers.
+ - Added new ClassifyOverride directive to allow users
+ to override the classification of individual jobs.
+ - Added new BrowseProtocols directive to control which
+ browse protocols are used (currently CUPS and SLP).
+ - Added SLPv2 support (thanks to Matt Peterson for
+ contributing the initial implementation for CUPS.)
+ - Adding a raw printer on a remote CUPS server now
+ correctly redirects PPD file requests to the remote
+ server.
+ - The serial backend now limits writes to 1/10th
+ second worth of data to avoid buffer overflows
+ with some types of flow control.
+ - The scheduler did not properly process PUT requests,
+ so configuration files could not be uploaded to the
+ server.
+ - The scheduler did not strip trailing whitespace on
+ lines in the configuration files.
+ - The httpWrite() function did not transition the PUT
+ request to the HTTP_STATUS state to get the status
+ from the server.
+ - The scheduler did not properly handle trailing null
+ ("-") filters when testing a driver that sent data
+ to the file: pseudo-backend.
+ - The IPP backend now only sends a document-format of
+ "application/vnd.cups-raw" when printing to another
+ CUPS server using a local printer driver or interface
+ script. Previously the job's document format was
+ used, which was incorrect.
+ - The lpadmin command didn't use the ppd-name attribute
+ with the -m option; this prevented the use of the
+ "raw" model from the command-line.
+ - The pstoraster filter output draft (1-bit) 6-color
+ output in the wrong order; this resulted in yellow
+ being printed instead of black on Stylus Photo
+ printers.
+ - The pdftops filter did not have the Japanese and
+ Chinese text support compiled into it.
+ - The IPP and AppSocket backends did not clear the
+ "waiting for print job to complete" status message,
+ which caused some confusion... :)
+ - The serial backend now opens the port in "no delay"
+ mode to avoid DCD detection problems with some OS's.
+
+
+CHANGES IN CUPS V1.1.9-1
+
+ - The configure script did not substitute the
+ correct user and group names.
+ - The configure script did not use the full path
+ to the install-sh script when it was used.
+ - The pstoraster filter did not correctly support
+ DuplexTumble mode for printers that used flip
+ duplexing.
+ - The cups.list.in file was missing from the
+ distribution.
+ - The New DeskJet series driver did not use the
+ correct OrderDependency for the Duplex option.
+ - Use read() instead of fread() to read piped
+ print files in lpr/lp. This avoids a bug in the
+ HP-UX 10.20 fread() function.
+ - Updated the pstoraster filter to use the MIPS_FIXADE
+ system call under IRIX to fix bus error problems on
+ R12000 processors (Ghostscript is not 64-bit clean...)
+ - Some Xerox PPD files (most notably the Phaser 790)
+ have illegal whitespace in the option keyword in the
+ OpenUI line. This caused the PageRegion option to not
+ be recognized properly for the Phaser 790.
+
+
+CHANGES IN CUPS V1.1.9
+
+ - Revamped the configure script to use a modular
+ approach for the various tests.
+ - Added --with-openssl-* options to properly reference
+ the OpenSSL libraries in DSOs.
+ - Added --with-cups-user and --with-cups-group
+ options to specify the default user and group for
+ CUPS.
+ - Added AIX shared library support.
+ - Added AIX device discovery for the serial and
+ parallel ports.
+ - Now use install program or script to install
+ directories, files, and symlinks.
+ - Updated pstops filter to use strict handling of EPS
+ files embedded in a PostScript document. The %%EOF
+ handling in 1.1.8 caused some dvips files not to
+ print.
+ - Fixed yet another memory allocation bug in pstoraster
+ that would cause it to crash. This fix also ensures
+ that all memory allocations are done on (at least) a
+ 64-bit boundary.
+ - Fixed Digest authentication - httpGetSubField() didn't
+ skip the Digest keyword.
+ - The scheduler did not properly handle Digest
+ authentication with the new multiple-group support.
+ - The scheduler did not allow usernames that were
+ not in the UNIX password file to be used for Digest
+ authentication from passwd.md5.
+ - The scheduler could not scan PPD files that only used
+ a carriage return (i.e. MacOS PPD files); the new code
+ is also about 40% faster, so servers with thousands of
+ PPD files should start much faster now.
+ - The scheduler now stores the PPD file size and
+ modification times in the ppds.dat file, so it can now
+ incrementally update the PPD database from the model
+ directory, resulting in significantly faster startup
+ times.
+ - The lpinfo command did not return a non-zero status
+ code if an error occurred.
+ - Fixed a bug in the scheduler's UpdateJob() function.
+ Basically, all jobs shared the same status buffer, and
+ the "buffer start" pointer could point to 1 byte
+ before the beginning of the buffer. The new
+ implementation uses a separate buffer for each job and
+ eliminates the buffer start bug.
+ - The IPP backend would send N copies of a document if
+ the receiving device didn't support the copies
+ attribute, even if the upstream driver already added
+ the necessary commands to generate the copies. This
+ was most noticeable with HP printers where N * N
+ copies would come out instead of N.
+ - The PostScript filter (pstops) did not properly handle
+ duplex printing on inkjet printers that provide this
+ option. Copies would be put on the front and back
+ sides of the duplexed page, and the filter did not
+ output an even number of pages.
+ - The backends always caught SIGTERM after they
+ connected to the printer. This prevented raw jobs
+ from being cancelled early.
+ - The cupsSetDests() function now removes any printers,
+ instances, and options that are not defined by the
+ user or server. This should prevent old system-wide
+ options from being used in individual user accounts.
+ - Updated the EPSON printer driver and added PPDs for
+ the newer EPSON Stylus printers that only support the
+ "ESC i" graphics command.
+ - The lpadmin command didn't allow you to add remote
+ printers to a local class.
+ - The lpadmin command didn't allow you to set the
+ options (quotas, etc.) for a class.
+ - The scheduler did not load or save the
+ job-sheets-default attribute for classes.
+ - The scheduler did not automatically recreate remote
+ printers that were part of a class.
+ - It was possible for a printer class to list the same
+ printer more than once.
+ - The scheduler now makes a backup copy of classes.conf
+ and printers.conf before writing the new file.
+ - The lppasswd program incorrectly asked for a new
+ password when deleting an existing MD5 password
+ account.
+ - The scheduler did not match "/printers/name.ppd"
+ against a location of "/printers/name".
+ - The client code did not always handle HTTP encryption
+ upgrades properly.
+ - The client code now caches the last Digest password so
+ it can retry using a new resource path or nonce value,
+ which are included in the MD5 sum sent to the server.
+ This should eliminate unnecessary password prompts
+ when using Digest authentication.
+ - The lppasswd command didn't have a man page.
+ - Updated the PJL detection rules to allow the universal
+ escape to occur anywhere in the first 128 bytes of the
+ file.
+ - The cups-polld program would poll servers continuously
+ with no delay if there was an error contacting the
+ server.
+ - The IPP backend would send an empty job-name or
+ requesting-user-name attribute if the corresponding
+ job attribute was an empty string. While this is
+ allowed by the IPP specification, some HP JetDirect
+ implementations return a client-error-bad-request
+ error if an empty name attribute value is received.
+ The new code only sends these attributes if they are
+ not the empty string.
+ - At least some versions of the HP JetDirect firmware
+ do not correctly implement IPP. Added additional
+ checks to the IPP backend to eliminate extra,
+ unsupported attributes which should normally be
+ ignored by a compliant IPP device.
+ - The scheduler did not copy the complete list of
+ supported file types into the
+ document-format-supported attribute. This caused
+ clients to not send the local file type (such as
+ application/vnd.cups-raw for raw print files) and the
+ corresponding bad output in some cases.
+ - The scheduler did not fully copy attributes from a
+ set-job-attributes request - string attributes were
+ only referenced, which could cause cupsd to crash
+ or behave irratically.
+ - The lp command didn't send the right value for the
+ job-hold-until attribute when "-H resume" was
+ specified.
+ - The IPP backend now returns as soon as a job is
+ completed or reported as "pending-held".
+ - Added new ImplicitAnyClasses and HideImplicitMembers
+ directives to the cupsd.conf file to make implicit
+ classes more usable/transparent to the user.
+ - Clients can now (with the appropriate authentication)
+ retrieve and update the server configuration files
+ using HTTP GET and PUT requests.
+ - The web interface didn't allow you to modify the
+ location or description of the printer.
+ - The pdftops filter now uses its own temporary file
+ function to work with PDF files using LZW compression
+ (which use the uncompress program or gunzip)
+ - The SystemGroup directive now supports specification of
+ multiple groups.
+ - Added new Include directive to cupsd.conf, a la
+ Apache.
+ - Added new pseudo-driver/PPD called "raw" that can be
+ used to create/convert a raw queue. This also allows
+ raw queues to be created in the web interface.
+ - The pdftops filter didn't handle image objects that
+ used JPEG and Flate compression together.
+ - The pstops filter counted pages wrong when using the
+ N-up and even/odd printing options. This prevented
+ the page-ranges option from working properly.
+ - Added another fix to pstoraster for a bus error
+ condition caused by a lack of parenthesis in the
+ Ghostscript code.
+ - Added new "natural-scaling" option which scales the
+ natural size of the image (percent of natural image
+ size instead of percent of page size.)
+ - The lppasswd program is now setuid to the CUPS user
+ instead of root.
+ - The PPD functions did not allow for PPD files that
+ defined the page sizes and margins before the page
+ size options.
+ - The mime.types file now checks for the PJL "LANGUAGE =
+ Postscript" command for PostScript files.
+ - The scheduler did not truncate file: output files.
+ - The PPD file reading code did not handle options with
+ raw quotes (") in the human-readable names.
+ - The pdftops filter now remaps the space character when
+ (bad) PDF files contain a .notdef glyph for the space
+ character.
+
+
+CHANGES IN CUPS V1.1.8
+
+ - Updated configure script to check for /etc/pam.d and
+ to only set PAMDIR if it exists.
+ - Updated spec file to generate separate cups-pstoraster
+ package for pstoraster.
+ - The spec file wasn't setting LOGDIR in the install.
+ - The scheduler might restart a stopped printer after
+ stopping a print job. Thanks to Florent
+ Guiliani for finding this bug!
+ - The init script showed run level 0 for the Red Hat
+ chkconfig program. This is incorrect because Red Hat
+ doesn't use run level 0 for shutdown scripts.
+ - The IPP backend did not handle the
+ client-error-not-found error when checking the status
+ of the job that was sent. This caused remote queues
+ to stop on client machines when the server had job
+ history disabled.
+ - Added httpConnectEncrypt() function to avoid
+ performance penalty for setting up encrypted
+ connections initially.
+ - Use httpConnectEncrypt() in all client apps and in the
+ CUPS API to ensure consistent usage of encryption
+ throughout.
+ - Jobs weren't queued to remote classes (fix from
+ Richard Begg.)
+ - AIX changes from Richard Begg.
+ - Fixed the pstops fix for GNOME output - no longer use
+ the page numbers in the %%Page: comment since GNOME
+ puts a filename instead (!?@!#?!). There is still an
+ issue with N-up printing since GNOME defines its fonts
+ in the first page instead of the document setup section
+ (pages must be independent according to the DSC spec)
+ People with GNOME printing problems should consult bug
+ #54489...
+ - The imagetops filter produced PAGE: messages when
+ generating PostScript for a non-PostScript printer
+ (only affects page-label and Classification
+ options.)
+ - The updated pdftops filter was looking for an options
+ file called xpdf.conf instead of pdftops.conf.
+ - The scheduler would not force the default job sheets
+ for printers to the current classification setting.
+ - Added a new ippFindNextAttribute() function to the
+ CUPS API.
+ - ppdEmitJCL() now strips any leading path info from
+ the title string. This is only an issue for non-CUPS
+ clients that don't do this already...
+ - Other pstops fixed from Helge Blischke for printing
+ non-conforming documents.
+ - The MaxJobs parameter was not reset when loading the
+ cupsd.conf file.
+
+
+CHANGES IN CUPS V1.1.7
+
+ - Configuration script changes, including new
+ "--with-docdir=/dir" option to relocate CUPS
+ documentation and web content according to your
+ favorite version of the FHS.
+ - Documentation updates for encryption, SLP, etc.
+ - New Software Test Plan and automated test script to
+ test CUPS prior to installation.
+ - All scheduler configuration files are now case
+ insensitive to match Apache.
+ - Added support for Apache ListenBackLog, Require,
+ Satisfy, <Limit>, <LimitExcept>, and LimitRequestSize
+ directives.
+ - Added support for all Apache log levels...
+ - Added support for "double" HostNameLookups.
+ - Added new "RunAsUser" directive to support non-root
+ configurations on the standard (priviledged) ports.
+ - Added support for non-root invocation of the lpd
+ backend (does no reserve a priviledged port, which
+ might not work with some LPD servers...)
+ - Added new PrintcapFormat directive to control the
+ output format of the printcap file (BSD or Solaris
+ formats are supported at present.)
+ - The CUPS directory service routines now handle
+ ECONNREFUSED errors gracefully rather than shutting
+ all browsing off.
+ - ippErrorString() now returns the recommended error
+ messages from the IPP/1.1 Model and Semantics
+ document.
+ - Fixed a minor IPP compliance issue with responses
+ to requests without the attributes-charset or
+ attributes-natural-language attributes.
+ - Sun fix: need httpFlush() call for chunked IPP
+ requests in cupsDoFileRequest().
+ - httpConnect() now looks up "localhost" by name and
+ by address (127.0.0.1) for users the go to the
+ trouble of removing the required localhost entry
+ in /etc/hosts or on their DNS server...
+ - Added support for Linux 2.4.x devfs parallel port
+ filenames (/dev/parallel/N).
+ - cupsDo[File]Request() and cupsGetPPD() no longer
+ block trying to reconnect to a crashed or inaccessable
+ server.
+ - Added new ppdEmitJCL() function to better handle
+ PJL commands from PPD files.
+ - A bug in UpdateJob() would cause the scheduler to
+ consume 100% CPU until another request was submitted.
+ - The cancel command did not support the "-" option to
+ cancel all jobs on all printers.
+ - The cancel and lprm commands did not support cancelling
+ the next/current job in the queue.
+ - The pdftops and pstoraster filters were using unsafe
+ temporary file functions; while this is not a problem
+ in normal configurations (the CUPS temporary directory
+ is restricted), they now use the cupsTempFd() function.
+ - The mime.types file was missing the recognition rule
+ for Sun Raster images.
+ - The admin CGI was passing a printer make string to
+ ippSetCGIVars() that was being replaced in that
+ function.
+ - "lpoptions -l" would resave the options...
+ - The EPSON drivers now send the "end packet mode"
+ command when printing to USB devices.
+ - The scheduler initialized certificates before loading
+ the cupsd.conf file.
+ - The scheduler used /dev/random to collect random data,
+ which could block if insufficient entropy information
+ had been collected by the kernel. Now use
+ /dev/urandom.
+ - Fixed a bug in the whitespace skipping code in
+ httpGetSubField().
+ - The LPD backend now supports a new "order" option:
+ "lpd://server/queue?order=control,data" (default) and
+ "lpd://server/queue?order=data,control".
+ - The scheduler enforced a 30 second timeout on all
+ clients regardless of the Timeout directive and if a
+ CGI was currently running.
+ - cupsParseOptions() now sets boolean options to
+ option=true or option=false.
+ - The "percent complete" calculations in the LPD backend
+ could overflow on large files, causing the percentage
+ to wrap to 0 every 40MB or so.
+ - Fixed a memory reallocation bug in pstoraster that
+ could cause it to crash.
+ - The LPD backend now sanitizes the job title to avoid
+ potential problems on remote LPD servers.
+ - The lp command did not send the requesting-user-name
+ attribute when altering a job.
+ - The pstops filter did not handle PostScript files with
+ lines longer than 8191 bytes.
+ - The scheduler no longer uses inet_addr() to convert IP
+ addresses in dot format (mmm.nnn.ooo.ppp) to the
+ 32-bit format, since it will not work for IPv6
+ addresses.
+ - New "Classification" directive to force labeling of
+ the current classification on each page.
+ - New "page-label" attribute to add per-page labels
+ ("For Official Use Only", "Draft", etc.)
+ - The scheduler now sets the HTTPS environment variable
+ for CGI programs when a client connects using
+ encryption.
+ - Fixed a recursion bug in the scheduler that could
+ cause cupsd to crash when a printer was removed.
+ - The LPDEST and PRINTER environment variables didn't
+ support instances.
+ - Dropped the "file" backend from the device list that
+ is reported, since it is only available for *testing*
+ and should never be used in a production environment.
+ The file: device can still be used, but it won't show
+ up in the list of devices from lpinfo or the web
+ interface.
+ - Added support for /dev/lpa# parallel ports under *BSD.
+ - Added META variables to the CGI header template to
+ prevent caching of the results.
+ - Fixed an unaligned memory buffer for the pstoraster
+ clist states; this caused bus errors for some
+ combinations of printers, drivers, and options.
+ - Re-added black reduction for colorful colors; this
+ helps to prevent dark colors from getting desaturated.
+ (only used when converting RGB to CMYK)
+ - Added two new directives - MaxJobsPerPrinter and
+ MaxJobsPerUser - to allow an administrator to set
+ the maximum number of pending jobs in a queue or
+ submitted by a user.
+ - The scheduler no longer stops a printer if it can't
+ create the status pipe or run the filters or backend.
+ This will allow heavily loaded servers to service
+ clients or start print jobs as the load allows.
+ - Fixed a bug in the Set-Job-Attributes code that could
+ crash the scheduler (patch from Martin Zielinski)
+ - cupsSetDests() did not quote option values with
+ embedded spaces.
+ - Added support for the Enable-Printer and
+ Disable-Printer extension operations (same as
+ CUPS-Accept-Jobs and CUPS-Reject-Jobs.)
+ - The AppSocket and IPP backends now wait for the print
+ job to be finished before exiting; this should prevent
+ the loss of print jobs with older JetDirect firmware
+ and make consecutive print jobs print faster.
+ - The BMP loading code did not handle resolution values
+ of 0. This is a problem with BMP image files produced
+ by the GIMP.
+ - The HTTP Upgrade code (upgrade to TLS encryption)
+ bypassed the authentication checks.
+ - The HTTP Upgrade code did not send a 426 status code
+ to the client and end the current request. This caused
+ a race condition between the client and server for the
+ upgrade to TLS.
+ - Fixed a bug in the EOF and Trailer detection code in
+ the pstops filter.
+ - The imagetoraster filter did not add the margins to
+ the custom page size in the raster header.
+ - The imagetops filter did not adjust the custom page
+ size to the size of the printed image.
+ - The imagetops filter did not include DSC comments
+ which are required by some printers.
+ - The imagetops filter did not insert newlines in
+ Base85 encoded output, causing files to contain
+ lines longer than 255 characters (violation of the
+ DSC).
+ - Added support for the DeskJet 900 series duplexer
+ and CRET color modes in the HP driver.
+ - Added support for PPD-defined margins in the HP
+ driver.
+ - Fixed the debugging output from pstoraster - the
+ font list was not terminated by a newline.
+ - Some versions of the HP-UX pam_unix authentication
+ module apparently do not pass the appdata_ptr argument
+ to the conversation function, preventing the scheduler
+ from authenticating users using PAM under HP-UX. A
+ workaround using a static variable has been added to
+ address this problem.
+ - Fixed a bug in the scheduler SortPrinters() function
+ that could cause printers to disappear or the
+ scheduler to crash when adding a printer.
+ - Changed the pstops filter to not do per-page filtering
+ if the file does not conform to at least version 3.0
+ of the document structuring conventions. This seems
+ to "fix" printing with broken apps.
+ - The image filters did not handle older TIFF files that
+ lacked the samples-per-pixel and bits-per-pixel tags.
+ - Added new cupsGetJobs() and cupsFreeJobs() functions
+ to manage print jobs.
+ - cupsEncodeOptions() would encode names of 0 length and
+ cupsAddOption() and cupsParseOptions() would add names
+ of 0 length.
+ - The scheduler might block waiting for status messages
+ after starting a new print job. Thanks to Florent
+ Guiliani for finding this bug!
+
+
+CHANGES IN CUPS V1.1.6-3
+
+ - The configure script put the JPEG library before the
+ TIFF library; this caused problems in some
+ configurations since the TIFF library also supports
+ JPEG compression of TIFF images.
+ - Updated the configure script and makefiles to handle
+ admin man pages with the "1m" extension (HP-UX, IRIX,
+ Solaris, Tru64) and in odd directories (IRIX)
+ - The updated cupsTempFile() function did not return
+ the filename when called with a filename buffer of
+ NULL (previously it used a static buffer.)
+ - FreeBSD uses /dev/unlptN, but NetBSD and OpenBSD use
+ /dev/ulptN.
+ - DeletePrinter() didn't remove the printer from any
+ classes it was a member of.
+ - DeletePrinterFromClass() didn't preserve the
+ implicit status of a class.
+ - DeletePrinterFromClasses() didn't remove printers
+ from implicit classes.
+ - StartJob() didn't send the job-sheets, job-priority,
+ and job-hold-until attributes to remote printers.
+ - LoadAllJobs() was looking for job-sheets-completed
+ instead of job-media-sheets-completed. This would
+ prevent accumulation of page data after a restart
+ of the scheduler.
+ - The pstops and imagetops filters now generate copies
+ using the appropriate method for a Level 1, 2, or 3
+ printer since some Level 2/3 printers don't support
+ the /#copies variable anymore.
+ - The man page for cups-lpd did not mention the "-o"
+ option.
+ - The IPP backend didn't handle version-not-supported
+ errors and revert to IPP/1.0 (previously it only checked
+ for a bad-request error)
+ - Caldera fix: lpc now reports unimplemented commands as
+ unimplemented, not invalid.
+ - Caldera fix: lpq didn't recognize BSD lpq "-a" option.
+ - Caldera fix: lpr didn't recognize BSD lpr "-1", "-2",
+ "-3", "-4", "-q", or "-U" options.
+ - RedHat fixes: patches to GNU Ghostscript
+ - SuSE fix: temp file creation patch to GNU Ghostscript
+ (pstoraster).
+ - SuSE fix: remove cgi-bin/abort.c and cgi-bin/email.c,
+ which are not used.
+ - SuSE fix: missing NULL check in cgi_initialize_post().
+ - SuSE fix: potential buffer overflows in
+ cgi_initialize_string().
+ - SuSE fix: potential buffer overflows in
+ ippSetCGIVars()
+ - SuSE fix: more NULL checks in ppdOpen(); also make
+ sure that all memory is freed on error to avoid memory
+ leaks.
+ - SuSE fix: Exit from child if setgid() or setuid()
+ fails.
+ - SuSE fix: Added setgroups() calls after setgid() and
+ setuid() calls.
+ - SuSE fix: potential buffer overflows in httpEncode64()
+ calls.
+ - SuSE fix: potential buffer overflows in httpSeparate()
+ - SuSE fix: potential buffer overflows in ippWrite() for
+ bad input.
+ - SuSE fix: potential nul skip in ppd_decode() for
+ missing hex digits.
+
+
+CHANGES IN CUPS V1.1.6-2
+
+ - Added changes to support NetBSD startup scripts.
+ - Added separate compiler options for pstoraster
+ (Ghostscript) to avoid compiler-induced errors
+ from Ghostscript's twisted code.
+ - The mime.types file contained syntax errors.
+ - Updated the *BSD USB device filenames to use
+ the /dev/unlptN files so that the USB device
+ is not reset prior to printing (causes print
+ corruption on many printers)
+ - Added new cupsTempFd() function to avoid serious
+ security bug in glibc fopen() function. The glibc
+ fopen() function unlinks a file before creating it,
+ which opens up possible symlink attacks.
+ - Now reject 0-length names in add-printer and add-class
+ requests.
+ - Fix for pstoraster when ZLIB is not available.
+ - cupsGetPPD() didn't reconnect when a HTTP connection
+ was lost.
+ - SuSE fix: httpConnect() didn't check that the
+ value from gethostbyname() was a valid IPv4 address.
+ - SuSE fix: httpConnect() didn't allow file descriptor 0
+ to be used for a socket.
+ - SuSE fix: ippRead() didn't confirm that all values in
+ a set were numeric or string types.
+ - SuSE fix: lppasswd race condition fixes.
+ - SuSE fix: directive names could overflow buffer when
+ reading *.conf files.
+ - SuSE fix: HEAD requests for PPD files did not use the
+ same logic as GET requests.
+ - SuSE fix: possible buffer overflow when adding
+ /index.html to requested directory name.
+ - SuSE fix: possible buffer overflow when converting
+ IPP attributes to string options for filters.
+ - SuSE fix: creating file: device output with mode 0666
+ instead of mode 0600.
+ - SuSE fix: creating job info files with mode 0640
+ instead of 0600.
+ - SuSE fix: don't rely on snprintf() for including
+ system name in log filenames.
+ - SuSE fix: add bounds checking when copying quoted
+ and hex strings.
+
+
+CHANGES IN CUPS V1.1.6-1
+
+ - Added configure check for getting the correct
+ strftime() format string; %c is not Y2k safe,
+ and %KC and NULL are not universally supported.
+
+
+CHANGES IN CUPS V1.1.6
+
+ - Fixed another possible DoS attack in httpGets()
+ - Added check for "LANGUAGE = PCL" and "LANGUAGE =
+ POSTSCRIPT" in mime.types.
+ - Resolution options were not being passed into the
+ filter programs properly.
+ - The default compiler options for GCC no longer include
+ "-g3", which apparently is deprecated in newer
+ versions of GCC.
+ - CheckJobs() could cause cupsd to crash if a job is
+ cancelled in StartJob().
+ - The printers.conf and classes.conf files are now
+ written with restricted permissions.
+ - The round-robin algorithm used by FindAvailablePrinter()
+ had problems; fixes contributed by Joel Fredrikson.
+ - If LoadAllJobs() is unable to determine the file type
+ of a print job, assume "application/vnd.cups-raw".
+ - The web interface now provides a job_printer_name
+ value for any corresponding job_printer_uri value.
+ - The cups-lpd mini-daemon now logs the client address
+ and hostname as well as all commands and errors in the
+ syslog file.
+ - The IPP backend now detects the supported file formats
+ and only specifies the document format if it is
+ supported. This makes IPP printing to network print
+ servers and cards more reliable without affecting the
+ capabilities of CUPS servers.
+ - The time_at_xyz attributes are now converted to human-
+ readable dates and times for the web interfaces.
+ - The HP and EPSON sample drivers now correctly catch
+ signals and eject the current page when a job is
+ cancelled.
+ - Fixed bug in CGI code - did not ignore control
+ characters (e.g. newlines) in form data. This caused
+ sporatic web interface problems.
+ - The file type logging code in the scheduler referenced
+ the optional document-format attribute; the new code
+ uses the resolved MIME type instead.
+ - The client.conf parsing code now removes trailing
+ whitespace.
+ - The MaxJobs directive was being treated as a boolean
+ instead of an integer.
+ - The scheduler would not timeout remote printers if
+ BrowseInterval was set to 0.
+ - The lpadmin command now supports setting of options
+ and user-level access control.
+ - Added "-E" option to all printing commands to force
+ encryption.
+ - The client code did not consume the response to the
+ OPTIONS request when switching to secure mode.
+ - The scheduler did not output a Content-Length field
+ when responding to an OPTIONS request.
+ - Added documentation on using cups-lpd with xinetd
+ to the man page.
+ - The socket backend now starts retries at 5 seconds and
+ increases the interval to 30 seconds. This should
+ provide faster printing when multiple jobs/files are
+ queued for a printer.
+ - The filters and backends no longer buffer output to
+ stderr. This should provide much more accurate status
+ reporting.
+
+
+CHANGES IN CUPS V1.1.5-2
+
+ - Fixed configure check for OpenSSL to work with RSA
+ code.
+ - Added configure check for <sys/ioctl.h>, and use this
+ check in backend/serial.c.
+ - Updated configure script handling of data,
+ configuration, and state directories to use datadir,
+ sysconfdir, and localstatedir variables.
+ - NetBSD uses different serial port filenames than
+ FreeBSD and OpenBSD.
+ - The pdftops filter didn't need some X-specific files.
+ - The scheduler makefile doesn't do a chown anymore when
+ installing (cupsd did this automatically on startup
+ anyways)
+
+
+CHANGES IN CUPS V1.1.5-1
+
+ - There was a typo in the top-level Makefile
+ - The top-level Makefile did not install an init script
+ for run level 5.
+ - The configure script did not add the "crypto" library
+ when checking for the OpenSSL library.
+ - The OKIDATA PPD files were missing.
+ - The config.h.in file defined the wrong version number.
+ - The serial backend did not define "funky_hex" under *BSD.
+ - Updated the Visual C++ project files and some of the
+ CUPS API sources to compile under Windows again.
+
+
+CHANGES IN CUPS V1.1.5
+
+ - Security updates - new default configuration does
+ not broadcast printer information and only allows
+ access from the local system.
+ - EXPERIMENTAL encryption support - CUPS now optionally
+ supports TLS/SSL encryption via the OpenSSL library.
+ - Documentation updates.
+ - Makefile/configure script updates.
+ - The RPM spec file didn't work out-of-the-box under
+ RedHat or Mandrake.
+ - Minor code cleanup to remove extraneous compiler
+ warnings.
+ - cupsTempFile() was using %p for the temporary
+ filename; this should have been %08x (just 8 digit
+ hex)
+ - Deleting a printer with active print jobs would still
+ crash the server.
+ - ippWrite() and ipp_write_file() didn't send the
+ correct value length for name-with-language and
+ text-with-language attributes.
+ - Updated IPP code to support copied strings (that
+ should not be freed); this provides slightly more
+ efficient IPP server performance.
+ - Updated PDF filter to Xpdf 0.91.
+ - httpGets() could go into an infinite loop if a line
+ longer than the input buffer size was sent by a
+ client. This could be used in a Denial-of-Service
+ attack.
+ - The lpstat and CUPS API functions now request only the
+ data required when getting the list of printer or
+ class information. This should improve performance
+ with large numbers of printers on slower machines.
+ - The scheduler was always enforcing the FilterLimit,
+ even if FilterLimit was set to 0.
+ - Updated the Linux USB backend to support Mandrake's
+ /dev/usb/usblp# filenames.
+ - The PRINTER and LPDEST environment variables did not
+ override the lpoptions default printer.
+ - The PPD read functions incorrectly included trailing
+ characters (usually whitespace) after quoted string
+ attributes.
+ - The multiple-document-handling attribute handling code
+ did not check for the correct value for collated
+ copies (separate-documents-uncollated-copies).
+ - The EPSON driver did not work with OKIDATA printers in
+ EPSON emulation mode (needed change-emulation command)
+ - The HP-GL/2 filter did not scale the plot properly in
+ scale mode 2.
+ - Added PPD files for 9-pin and 24-pin OKIDATA printers.
+ - The httpSeparate() function didn't handle passwords
+ that started with a number.
+ - ippDelete() could free the character set string
+ multiple times in name-with-language and
+ text-with-language attributes.
+ - The scheduler would access freed memory right after
+ freeing it (for debug messages); these parts of the
+ code have been reordered to avoid this situation
+ which was causing sporatic errors and crashes.
+ - The ppdClose() function didn't free all of the strings
+ in the ppd_file_t structure.
+ - The LoadAllJobs() function in the scheduler did not
+ close the spool directory.
+ - Changed all sprintf's that use string formats to
+ snprintf's, even if the destination buffer is
+ larger than the source string(s); this protects
+ against buffer overflows caused outside of CUPS...
+ - Changed all strcpy's to strncpy's between local and
+ global variables, even if the destination buffer is
+ larger than the source string; this protects
+ against buffer overflows caused outside of CUPS...
+ - The CUPS certificate functions didn't use the
+ CUPS_SERVERROOT environment variable when set.
+ - The directory services code was copying instead of
+ comparing the remote printer info, resulting in
+ unnecessary updates of the printer attributes for
+ remote printers.
+ - Added new mime.types rules to allow automatic raw
+ printing of PCL and ESC/P files; PJL headers are
+ parsed to differentiate between PostScript and
+ PCL job files. This should eliminate a lot of
+ the reports of SAMBA printing problems due to
+ the missing "-oraw" or "-l" options.
+ - The mimeLoadType() function didn't handle the
+ 3-argument contains() function.
+ - The LoadPPDs() function in the scheduler didn't
+ properly set the alloc_ppds variable or handle a PPD
+ database containing 0 printers.
+ - The scheduler FindAvailablePrinter() function didn't
+ use the same queuing logic as the CheckJobs()
+ function. This caused classes to stall if a remote
+ printer was always busy.
+ - Jobs are now assigned to printers in a class
+ round-robin style. This should prevent the first
+ server in the class from bearing the brunt of the
+ jobs.
+ - The scheduler's LoadAllJobs() function didn't always
+ restore remote printers for queued jobs on startup.
+ - The serial backend didn't support the higher baud
+ rates with the old termios interface. It now supports
+ 57600 and 115200 baud.
+ - The serial backend now supports different types of
+ flow control; previously it ignored the flow=XYZ
+ option in the device URI.
+ - The serial backend now supports DTR/DSR flow control,
+ which is popular on dot-matrix printers (access with
+ "flow=dtrdsr" in the device URI)
+ - Added new job-originating-host-name attribute for
+ jobs. The new attribute provides the hostname or
+ IP address of the machine that submitted the job.
+ - The set-job-attributes code no longer allows read-only
+ job attributes to be changed.
+ - Expanded the click area for the navigation bar in the
+ web interface.
+ - Updated the lp and cancel commands to support all of
+ the Solaris print options (some are simply ignored
+ since they do not map)
+ - Updated the scheduler to limit the number of file
+ descriptors to the maximum select() set size. This
+ was causing problems on Solaris systems where the
+ max FD count was increased beyond 1024.
+ - The scheduler's LoadDevices() function was getting
+ interrupted by the SIGCHLD signal handler; now ignore
+ child signals while loading devices.
+ - Added quota and allow/deny user support for printers
+ and classes.
+ - Removed black/CMY adjustment code from the PS and
+ image file RIPs; it was interfering with some CUPS
+ driver dithering code.
+ - The lpc program stopped listing the queue statuses
+ after the first active printer.
+ - The cups-lpd program used an output format that the
+ Solaris printing system did not understand.
+ - Updated the lpq program to use the Solaris format
+ except under Tru64 UNIX.
+ - Some DEC PPD files incorrectly use "Off" for the null
+ value in UI constraints. Added "Off" to the list of
+ accepted null values.
+ - Changed the *BSD define constants to __*BSD__ in all
+ of the backends.
+ - Added support for "lpstat printername", which is an
+ undocumented feature in Solaris.
+ - The HP-GL/2 filter now only sets the plot size if it
+ is set in the plot file.
+ - The lpmove command wasn't sending the requesting
+ user name, causing it to always fail.
+ - Updated the cupsTempFile() code to use GetTempPath()
+ under Windows.
+ - The cups-lpd mini-daemon didn't limit the number of
+ data files accepted, didn't use cupsTempFile(),
+ didn't handle control file job information in any
+ order, and didn't free job options after printing
+ a file.
+ - The scheduler copy_banner() function did not
+ explicitly set the owner and permissions of the banner
+ files, which could prevent the banner pages from
+ printing on some systems.
+ - The lpstat program wasn't listing remote classes.
+ - The scheduler did not verify that the printer-uri
+ attribute was specified in all requests that required
+ it.
+
+
+CHANGES IN CUPS v1.1.4
+
+ - Makefile and configure script fixes.
+ - **** Changed the default Printcap setting **** to
+ /etc/printcap. There are just too many people asking
+ why application XYZ doesn't see their printers!
+ - The web admin interface now displays an error if it
+ can't get the list of printer drivers from cupsd.
+ - The IPP backend was putting the copies option before
+ the other job options were set. This caused the IPP
+ request to contain attribute groups in the wrong
+ order, which prevented remote printing.
+ - Added checks in scheduler to free memory used for
+ IPP requests and language information when closing
+ a client connection.
+ - Fixed the duplex option in the HP LaserJet driver. It
+ should now work with all LaserJet printers (and
+ compatibles)
+ - The add-printer web interface didn't initialize the
+ "old info" data pointer, which caused random crashes
+ on many OS's.
+ - Fixed many page sizes defined in the Level 1
+ compatibility file "gs_statd.ps" to match reality.
+ - Fixed another bug in the setpagedevice "code" in
+ Ghostscript. It should now accept all standard
+ Adobe attributes on all platforms.
+ - Fixed pstoraster so that it reallocates memory for
+ color depth changes as well as size/resolution
+ changes. This removes an ordering constraint on
+ the color, page size, and resolution options in
+ PPD files.
+ - The IPP backend didn't use the job's character set
+ when the destination printer supported it. This
+ caused problems when printing text files to other
+ CUPS servers.
+ - Updated the logic used to determine when to rebuild
+ the PPD file database. The scheduler now checks the
+ dates and the number of PPD files (was just checking
+ the dates.)
+ - Updated the ippSetCGIVars() function (used by the
+ web interfaces) to only filter valid string values.
+ - The PostScript filter was scaling 2-up pages
+ incorrectly. This caused the edges of some pages to
+ be clipped.
+
+
+CHANGES IN CUPS v1.1.3
+
+ - Makefile fixes.
+ - RPM spec file changes.
+ - Documentation updates.
+ - Enabled pstoraster debug messages for everything
+ (only logged when LogLevel set to "debug"...)
+ - Changed the Input/OutputAttributes fix in
+ pstoraster so that it works on all platforms.
+ - The HP-GL/2 filter didn't set the right green
+ color value in encoded polylines or text.
+ - Updated the "fitplot" code to handle plot sizes
+ specified as "PSwidth,length" and "PSlength,width".
+ - Updated the Linux parallel and USB backends to open
+ the device files prior to looking in /proc for
+ autoprobe info. This makes sure that loadable device
+ driver modules are in fact loaded...
+ - Added new FilterLimit directive to limit the number
+ of processing jobs/filters on a system.
+ - set-job-attributes didn't change the job-state to
+ held/pending when the job-hold-until attribute was
+ specified.
+ - set-job-attributes didn't save the new job attributes.
+ - Now change the "requesting-user-name" attribute in
+ requests from remote systems to "remroot" when an
+ unauthenticated "root" user is sent. This can be
+ changed using the new RemoteRoot directive in
+ cupsd.conf.
+ - The cancel-job, hold-job, release-job, and restart-job
+ operations didn't log the authenticated username.
+ - The cups-lpd mini-daemon now checks for a
+ document-format option before forcing raw mode with
+ filter mode 'l'.
+ - The cups-lpd mini-daemon now supports "-o" options
+ on the command-line (passed by inetd) to set global
+ defaults for all print queues.
+ - The pstops filter assumed that a file with a Trailer
+ comment would also have an EOF comment.
+ - Added new cupsSetPasswordCB(), cupsSetServer(),
+ cupsSetUser(), and ippSetPort() functions to better
+ support client applications (especially GUIs...)
+ - The CUPS-add-class and CUPS-add-printer operations
+ didn't reset the printer-name attribute on remote
+ print queues that had to be renamed when a local
+ printer was defined with the same name.
+ - The lpoptions command now supports a "-r" option to
+ remove options for a printer or instance.
+ - The lpadmin and admin.cgi programs no longer allow
+ class and printer names to begin with a number; this
+ caused the command-line utilities to become confused.
+ - The Linux USB backend now looks for both the parallel
+ and usblp driver names in the device list.
+ - Added a new FontPath directive to cupsd.conf, and also
+ a "--with-fontpath" option for the configure script to
+ specify alternate font paths for pstoraster.
+ - The CUPS-move-job operation didn't update the
+ job-printer-uri attribute.
+ - The scheduler only looked up printers and classes by
+ name in IPP requests, instead of using the full URI.
+ This caused problems with KUPS and friends with
+ remote printers.
+ - The scheduler now handles better localization of
+ hostnames (e.g. server is host.foo.com, remote is
+ host.subfoo.foo.com, localized is not host.subfoo...)
+ - The scheduler logging functions now use a common
+ log file checking/rotation function (courtesy of
+ Crutcher Dunnavant at Red Hat)
+ - The scheduler could accept more client connections
+ than it allocated for if more than one Port or Listen
+ line was present in cupsd.conf.
+ - Other minor scheduler performance tweeks.
+ - The lpq and lprm commands didn't support the default
+ printer set using lpoptions.
+ - The lpoptions command now supports a "-l" option to
+ list the printer-specific options and their current
+ settings.
+ - The web printer and class lists now show a link to the
+ default printer or class at the top of the page.
+ - The text filter now supports pretty printing of shell
+ and perl scripts as well as C/C++ source files.
+ - The top and bottom margins were reversed for landscape
+ text printing.
+ - The lpq and lprm commands didn't understand printer
+ instances.
+ - The scheduler only selected on the first 100 file
+ descriptors instead of the maximum file descriptor
+ limit.
+ - The scheduler client, listener, and mainline functions
+ now share code to disable and enable monitoring for
+ new client connections.
+ - The imagetoraster filter didn't support all of the
+ required pagedevice parameters.
+ - The serial backend now checks for 100 serial ports
+ under Linux.
+ - The scheduler used sscanf() to pull out the remote
+ printer location, description, and make/model strings,
+ but if any of these options was empty then sscanf()
+ would stop processing.
+ - Added "debug2" log level to provide a little less
+ verbose debugging information at the "debug" level.
+ - The scheduler would crash if you stopped a printer
+ that was currently printing a job.
+ - The scheduler incorrectly allowed jobs in the cancelled,
+ aborted, or completed state to be cancelled.
+ - The image filters did not load TIFF images properly
+ for bottom-to-top and right-to-left orientations.
+ - Added new cupsEncodeOptions() function to encode
+ CUPS options as IPP job attributes.
+ - The IPP backend, LPD mini-daemon, client commands,
+ and CUPS API did not properly encode multiple
+ option values separated by commas.
+ - Added new scheduler malloc logging in debug mode
+ (provides summary of total arena size, allocated,
+ and free bytes once a minute)
+ - The EPM-based distributions didn't install the
+ correct symlinks for a few man pages.
+ - Fixed a memory leak in the scheduler - wasn't
+ freeing old filters when deleting or renaming
+ printers.
+ - The scheduler now queries the primary IP address
+ for the name of the server and maps any incoming
+ requests from that address to the server name.
+ This fixes web admin mapping problems from
+ server.domain.com to localhost.
+ - The web printer modify interface now remembers
+ the previous device and driver settings (except
+ for serial ports.)
+ - The job-k-octets attribute is now stored as part of
+ the job attributes; this preserves the information
+ after a job is completed when job file history is
+ turned off.
+ - Dropped option sub-group parsing code for the moment,
+ since many Xerox PPD files abuse this feature in PPD
+ files and don't follow the hierarchy rules.
+ - Added new wrapper code around options so that duplex
+ options for some HP printers don't prevent prints.
+ - Added support for Digital UNIX/Tru64 UNIX/OSF/1 format
+ for "lpstat -v" output.
+ - Now show the URI for remote printers instead of
+ /dev/null in "lpstat -v" output.
+ - Creating classes and adding printers to a class with
+ the lpadmin command didn't work.
+ - The banner pages and test page should now format
+ correctly in both portrait and landscape orientations.
+ - Updated banner page substitution so that { can appear
+ by itself without quoting.
+
+
+CHANGES IN CUPS v1.1.2
+
+ - Makefile/configure fixes
+ - RPM spec file and EPM list file fixes
+ - The cupsTempFile() function now uses a different
+ algorithm for generating temp files and "reserves"
+ them to avoid possible security exploitation.
+ - Now use /dev/random (if available) to seed the random
+ number generator for certificates.
+ - The /var/spool/cups and /var/spool/cups/tmp directories
+ were incorrectly owned by root; they are now owned by
+ the filter user, typically "lp".
+ - The scheduler now resets the permissions on the spool
+ and temp directories as needed to match the filter
+ user.
+ - Now expose ppdCollect() as an externally callable
+ function.
+ - The image filters now support filtering from the
+ standard input.
+ - The imagetoraster filter now collects all printer
+ options and job patch files and applies them to the
+ page header as needed.
+ - Added format and banner options to LPD backend.
+ - The send-document operation didn't start a job
+ immediately when last-document was true.
+ - The set-job-attributes operation didn't correctly
+ replace the current job-hold-until value.
+ - Removed the option wrapper code from ppdEmit() and
+ friends since it caused problems with Ghostscript
+ and many PS printers.
+ - Was setting TZ environment variable twice for job
+ filters.
+ - Added syslog logging in cups-lpd to aide in
+ debugging problems.
+ - The HP-UX parallel port backend did not list the
+ available parallel ports on some systems (printf
+ calling problem...)
+ - The lp and lpr commands overrode user options if
+ -d/-P were specified after -o.
+ - The scheduler would crash with a */* filter.
+ - Added support for a "default" filter for unknown file
+ types. The example provided in the mime.types and
+ mime.convs file prints unknown files as if "-oraw" was
+ specified for the job. This functionality is disabled
+ by default.
+ - The "compatibility" mode fix for older backends did not
+ work for smbspool. Added a workaround for it.
+ - The HP-GL/2 filter didn't perform the right pen scaling
+ with some files and the "fitplot" option.
+ - New Software Performance Specification document that
+ describes the memory, disk, and CPU usage of all the
+ CUPS software.
+
+
+CHANGES IN CUPS v1.1.1
+
+ - The pstoraster Makefile still referenced one of the
+ old PDF filter files.
+ - The filter Makefile used INSTALL_DATA instead of
+ INSTALL_LIB to install the CUPS image library.
+ - The administration CGI didn't work properly with
+ network devices.
+ - The BrowseACL variable was not updated after the
+ cupsd.conf file was loaded.
+ - The lpd mini-daemon didn't support printer instances.
+ - Now use a default umask of 077 for child processes.
+ - Now put temp files in /var/spool/cups/tmp for child
+ processes and the root user, unless TMPDIR or TempDir
+ is defined otherwise.
+ - cupsGetPPD() no longer uses easy-to-guess filenames.
+ - The CUPS-Delete-Class and CUPS-Delete-Printer
+ operations now save classes.conf file as needed.
+ - The lppasswd command wouldn't add a user.
+ - The ppdOpen() function could cause a segfault if a
+ 0-length PPD file was read.
+ - The image filters were not handling images with
+ different X and Y resolutions properly.
+ - The imagetoraster filter defaulted to RGB output
+ instead of black output like pstoraster.
+ - The pstops filter didn't handle binary data properly.
+ - The pstops filter didn't handle copies properly for
+ PS files lacking DSC comments.
+ - The pstops filter now appends %%EOF to the end of
+ documents if they don't have it.
+ - The cupsGetPPD() function didn't work with remote
+ printers lacking the @server in the name.
+ - The configure script didn't work right when only
+ --prefix was specified.
+ - The ppdEmit() code now wraps all printer commands so
+ that buggy PostScript printers will still print a file
+ after receiving an option that isn't available.
+ - Fixed the DeskJet margin bug, and disabled 600dpi
+ color mode until it can be fixed.
+ - The cupsAddDest() function didn't sort instances
+ correctly in all cases.
+ - The time-at-xyz attributes now expand to the date and
+ time in banner files.
+
+
+CHANGES IN CUPS v1.1
+
+ - Documentation updates.
+ - Configuration script updates.
+ - Didn't map charset and language value strings to lowercase
+ and _ to - as required by SLP and IPP.
+ - ppdLoadXYZ() didn't add the list of available fonts to the
+ ppd_file_t structure.
+ - The text filter common code was freeing the PPD file data
+ before it was used.
+ - The text filter now embeds missing fonts.
+ - The CGI interface now maps local access to the server to
+ the localhost address.
+ - The HP-GL/2 filter didn't use the specified (or default)
+ color ranges, resulting in strange colors.
+ - The HP-GL/2 filter didn't default to no input window, which
+ caused unnecessary clipping of plots.
+ - Integrated Xpdf's pdftops filter into CUPS, which is a
+ lightweight and reliable replacement for Ghostscript's
+ PDF support.
+ - Removed all PDF support from Ghostscript.
+ - Updated HP driver to set top margin; this seems to fix
+ the offset problem seen on HP DeskJet printers.
+ - Fixed dependencies on the ZLIB and JPEG libraries in
+ pstoraster.
+ - The lpr command wasn't using the lpoptions defined by
+ the user.
+ - The lpr command would segfault if the CUPS server was
+ not running.
+ - The top-level makefile was not installing the CUPS
+ initialization script. It now does so if it sees there
+ is an init.d directory in /sbin, /etc/rc.d, or /etc.
+ - "lpstat -v all" didn't work.
+ - pstoraster would crash on some platforms doing the
+ setpagedevice operator.
+ - The web administration interface now allows you to set
+ the default banner pages.
+ - Images can now be positioned on the page using the new
+ "position" option.
+ - The AccessLog, ErrorLog, and PageLog directives now
+ support "%s" to insert the server name.
+ - Added a new BrowseShortNames directive to allow for
+ short remote printer names ("printer" instead of
+ "printer@server") when possible.
+ - The scheduler could crash if given an invalid PPD file
+ with no PageSize attributes.
+ - Updated the serial, parallel, and usb backends to do
+ multiple writes and ignore ioctl() errors as needed;
+ this should fix problems with serial printing on old
+ serial drivers and with the UltraSPARC parallel port
+ driver under Solaris 2.7.
+ - Now propagate LD_LIBRARY_PATH to child processes from
+ cupsd.
+ - New DataDir directive for installing in alternate
+ locations.
+ - New CUPS_SERVERROOT and CUPS_DATADIR environment
+ variables to specify installation directories as
+ needed.
+ - Queued remote jobs recreate remote printers as needed
+ when the scheduler is started.
+ - Deleting a printer also purges all jobs on that
+ printer.
+ - Old job and control files that don't belong to a
+ printer are automatically deleted.
+ - Wasn't updating time-at-processing and
+ time-at-completed attributes in job.
+ - Didn't send required multiple-operation-time-out
+ attribute in response to a get-printer-attributes
+ request.
+ - cups-lpd now supports options set with lpoptions.
+ - The job-hold-until attribute is now provided with all
+ jobs. For jobs that are not currently held the value
+ is "no-hold".
+ - The scheduler was not sending "unknown" values in IPP
+ responses.
+ - The lpoptions command now accumulates options from
+ previous runs rather than replacing all options for a
+ printer.
+ - The IPP backend now switches to IPP/1.0 if a 1.1
+ request fails.
+ - The lpadmin and admin.cgi programs now validate new
+ printer and class names.
+ - The access_log file now includes the number of IPP bytes
+ received in a POST request.
+
+
+CHANGES IN CUPS v1.1b5
+
+ - Documentation updates.
+ - The pstoraster filter didn't compile without the JPEG library.
+ - The cupsd server didn't support the HTTP OPTIONS request
+ method.
+ - Dropped the "CLOSE" method supported by the cupsd server.
+ (not defined in HTTP specification)
+ - Makefile/configure script fixes.
+ - Missing the job-restart template.
+ - Added IPP test suite for testing.
+ - Missing IPP documentation from binary distributions.
+ - Fixed multiple-document handling code when last-document
+ not specified.
+ - Added more checks to IPP requests to prevent bad requests
+ from getting through.
+ - Not all of the Ghostscript error output was being sent to
+ stderr.
+ - The PostScript filter now added PJL commands to set the
+ job name and display string, if supported.
+ - The scheduler would crash if the browse socket could not
+ be bound. Now disables browsing if port 631 (reserved for
+ IPP) is being used by a misbehaving daemon.
+ - The USB backend now looks for the older Linux 2.2.x USB
+ printer device filenames as well as the newer ones.
+ - The IPP backend now uses the UTF-8 charset exclusively,
+ since apparently only CUPS handles more than US-ASCII and
+ UTF-8...
+ - Wasn't quoting ( in PostScript banners...
+ - Send-document requests with no document-format attribute
+ could cause cupsd to crash.
+ - Old jobs in the spool directory might cause cupsd to
+ crash.
+ - CUPS now supports all of the recommended job-hold-until
+ keywords as well as name values of the form "HH:MM" and
+ "HH:MM:SS".
+ - Added placeholder pointer for TLS encryption to the HTTP
+ connection structure.
+ - Fixed the "fast poll" bug reported by DISA - the
+ status pipe wasn't being closed for multi-file jobs.
+ - Revamped put_params code in pstoraster to fix bitmap
+ allocation bug with FrameMaker output.
+ - Ripped out filename, etc. code from pstoraster as it
+ is a potential security hole.
+ - Added support for RIP_CACHE environment variable in the
+ new pstoraster.
+ - Fixed USB device filenames for Linux; now support new
+ pre-2.4 devices (/dev/usb/lp#) and 2.2 devices
+ (/dev/usblp#)
+ - Fixed accept-jobs crash with classes.
+ - Didn't include dot-matrix EPSON drivers in previous
+ release.
+
+
+CHANGES IN CUPS v1.1b4
+
+ - Documentation updates.
+ - Many makefile and configuration script fixes (should
+ now compile better under *BSD.)
+ - The MediaPosition attribute was being mishandled by
+ GhostScript, causing the RIP to fail whenever a paper
+ tray was selected.
+ - The scheduler now logs the final line of log information
+ from a filter, even if it doesn't end with a newline; this
+ primarily affects GhostScript error output.
+ - The scheduler was saving implicit classes, so after a few
+ restarts you'll end up with AnyPrinter, AnyAnyPrinter, etc.
+ - The JPEG autodetection didn't work with some JPEG files that
+ came from digital cameras (JPEG but not JFIF); the new
+ magic types should work with all images that the JPEG library
+ can handle.
+ - Fixed a bug in the new contains() MIME type rule that could
+ cause cupsd to crash.
+ - Switched to using strtol() in the MIME type code so that you
+ can use hex, octal, or decimal constants as desired in the
+ mime.types file.
+ - Banner files are now treated as templates, allowing any type
+ of file to be used as a banner.
+ - Added a 30-second timeout to backend device reports so that a
+ hung backend will not prevent the scheduler from starting.
+ - Backends are once again terminated when jobs are stopped; the
+ CUPS-supplied backends will stay alive until the downstream
+ filters have had a chance to clear out old page data.
+ - The charset lookup in the CUPS localization support was wrong
+ (iso8859-x instead of iso-8859-x)
+ - Changed the "cpNNNN" code page files to "windows-NNNN" to match
+ the IANA registrations.
+ - New PostScript banner pages.
+ - Added Windows BMP and Alias PIX image file support to the image
+ filter.
+ - The PNG reading coded didn't free all of its buffers.
+ - Added Digest authentication support to the client and server
+ code.
+ - Added Solaris options to System V commands.
+ - Now support the output-bin job template attribute.
+ - Now log the job-billing attribute in the page_log file, and
+ keep track of the total number of pages in the
+ job-media-sheets-completed attribute.
+ - The penwidth option is now in micrometers to support more
+ accurate width specification.
+ - The image filters now support interlaced and transparent PNG
+ files.
+ - Didn't handle Keep-Alive for HTTP/1.0 clients.
+ - The BrowsePoll support didn't handle when BrowseInterval
+ was set to 0 (now uses 30 seconds if BrowseInterval is 0)
+ - The DeskJet driver now supports 600 DPI color for printers
+ that support it.
+ - New lpinfo and lpmove commands.
+ - The lpq command now supports the Digital UNIX output format.
+ - The LPD mini-daemon now supports all required LPD operations.
+ - Implemented timeouts for multi-file documents.
+ - New cupsPrintFiles() function in the CUPS API library to
+ print multiple files using create-job and send-document
+ requests (1 job ID for multiple files)
+ - The lp command now sends multiple files as a single job,
+ matching the behavior of the System V command.
+ - The "cancel -a" command now purges job history files.
+
+
+CHANGES IN CUPS v1.1b3
+
+ - Documentation updates.
+ - The startup script redirected stderr before stdout,
+ which caused problems with some versions of Bourne
+ shell and Bash.
+ - Fixed a bug in the scheduler's PPD language reading
+ code.
+ - Fixed a bug in the scheduler's check for the
+ manufacturer in the PPD.
+ - The pstoraster filter didn't allow some input and
+ output attributes to be set.
+ - Added banner page support.
+ - Added missing PAM configuration file.
+ - Configuration script fixes for Linux and *BSD.
+ - The log file code was using the wrong sign for the
+ timezone offset.
+ - The default printcap file is now empty (no printcap
+ file is generated).
+ - The scheduler did not start jobs destined for remote
+ printers when they became available.
+ - The scheduler now sends jobs to remote printers
+ immediately. (when sending jobs to a class, the remote
+ printer is only used when it becomes available)
+ - The scheduler now supports printing of banner pages
+ via the job-sheets attribute (banner files go in
+ /usr/share/cups/banners)
+ - The cupsd process now forks itself into the background
+ (override with -f)
+ - Added several *BSD enhancements.
+ - Added UNSUPPORTED libtool option to configuration
+ script to allow the use of libtool. Note that this is
+ UNSUPPORTED by us, but added by request of the *BSD
+ folks.
+ - The parallel, serial, and usb backends now retry the
+ opening of their ports. This allows multiple print
+ queues to be associated with a single physical port,
+ and will allow CUPS to support several types of
+ parallel port auto-switches in the near future.
+ - Set-Job-Attributes now supports adding, changing, and
+ deleting job template attributes, and no longer allows
+ job-printer-uri to be set (see CUPS-Move-Job)
+ - Added CUPS-Move-Job operation to support moving of jobs.
+ - The CGI template functionality now supports multiple
+ languages (still only have templates for English)
+ - The CUPS-Get-Printers and CUPS-Get-Classes operations
+ now support filtering as defined in the IDD.
+ - The Get-Jobs, CUPS-Get-Printers, and CUPS-Get-Classes
+ operations no longer limit themselves to 1000 jobs,
+ printers, or classes (believe it or not, this is
+ needed for some sites)
+ - The web interfaces now support language-specific
+ templates.
+ - The web admin interface now supports class management.
+ - The web admin interface now shows a list of
+ manufacturers before selecting the PPD/driver for a
+ specific printer.
+ - The web admin interface now supports configuration of
+ the default printer options in the PPD file.
+ - The web interface now uses printer/class
+ authentication for the test page instead of admin
+ authentication.
+ - Updated the RPM spec file for the current release.
+ - Updated language support for Windows code pages.
+ - 8-bit character set files can now use multiple fonts
+ (needed for Arabic, Greek, Hebrew, etc.)
+ - Added basic right-to-left text support in the text
+ filter.
+ - The POSIX locale now uses ISO-8859-1 instead of
+ US-ASCII.
+ - Fixed PDF printing problems.
+ - Fixed PostScript RIP page device dictionary elements
+ that weren't getting passed in cups_get_params().
+ - Added a new "contains" rule for the magic file typing.
+ - The "printable" rule now accepts characters from 128 to 255
+ (needed for Microsoft character sets)
+ - Added support for ~/.cupsrc as well as /etc/cups/client.conf
+ so that the default server can be configured on a per-user
+ basis without environment variables.
+ - Added LPD mini-daemon to support incoming LPD jobs.
+
+
+CHANGES IN CUPS v1.1b2
+
+ - Documentation updates.
+ - The lp command didn't always load the user-defined
+ destinations, preventing it from seeing the default
+ printer.
+ - Many configure script and makefile fixes.
+ - The Microsoft code page files were missing from the
+ distribution.
+ - Added a workaround for the HP IPP client (which is sending
+ an invalid printer-uri in requests)
+ - Fixed the encoding of text-with-language and name-with-language
+ to match the IPP spec.
+ - Added support for unknown value tags in the IPP routines
+ (previously they would be ignored)
+ - Integrated GNU GhostScript 5.50 into the pstoraster filter.
+ - Client hostname resolution was broken on little-endian
+ machines.
+ - Now look at client.conf file for client's default server
+ and printer.
+ - The cupsServer() function did not close the client.conf file
+ if it contained a ServerName directive.
+ - Added BrowseAllow, BrowseDeny, BrowseOrder, BrowsePoll, and
+ BrowseRelay directives.
+ - BrowseInterval 0 disables advertising of local printers, but
+ still receives information on remote printers.
+ - New browse polling daemon (for polling servers on different
+ networks)
+ - New PPD cache file for faster startup times with large numbers
+ of PPD files.
+ - The Host: field was incorrectly required for HTTP/1.0 clients.
+ - New set-job-attributes operation now supported.
+ - The mime_load_types() and mime_load_convs() functions did not
+ close their input files.
+
+
+CHANGES IN CUPS v1.1b1
+
+ - NEW web-based administration interface.
+ - NEW EPSON printer drivers.
+ - NEW user-defined printers and options.
+ - NEW persistent jobs and job history
+ - NEW IPP/1.1 support
+ - NEW template-based web interfaces.
+ - NEW CUPS-get-devices and CUPS-get-ppds operations.
+ - NEW support for create-job and send-file operations.
+ - NEW certificate-based authentication for local
+ administration.
+ - NEW USB backend.
+ - The lpr command now produces human-readable error messages.
+ - The lpq command now produces BSD standard format output
+ instead of OSF/1 output. This should resolve the SAMBA
+ print queue problems that have been reported.
+ - The IPP backend did not always detect when the "raw" option
+ was being used.
+ - The "lpstat -p" command would stop after the first active
+ printer.
+ - The "lpstat -v" command would stop before the first remote
+ printer.
+
+
+CHANGES IN CUPS v1.0.5
+
+ - The HP-GL/2 filter did not correctly set the pen color
+ for pens other than #1.
+ - The scheduler would only accept 26 simultaneous jobs
+ under some OS releases (mkstemp() limitation.) It now
+ handles up to 2^32 simultaneous jobs.
+ - The PostScript filter loaded the printer's PPD file
+ twice.
+ - The PAM authentication code now uses pam_strerror() to
+ provide a textual error message in the error_log file.
+ - The scheduler now copies PPD and interface script
+ files instead of moving them; this fixes installations
+ with a separate requests directory.
+ - The PostScript RIP did not generate correct 6-color
+ output.
+ - Several filters were marking PPD options twice when
+ they didn't need to.
+ - The scheduler did not save the printer or class state
+ after an accept-jobs or reject-jobs operation.
+ - The cupsGetDefault() function now ignores the PRINTER
+ environment variable if it is set to "lp".
+ - New ippErrorString() function to get textual error
+ messages.
+ - Better error reporting in the System V commands.
+ - The lpadmin and lpstat commands always tried to
+ connect to the default server.
+ - The text filter didn't load the charset files from the
+ correct location.
+ - Wasn't sending a WWW-Authenticate: field to HTTP
+ clients when authentication was required.
+ - httpSeparate() didn't always set the default port
+ number for known methods.
+ - The HP-GL/2 filter now looks for "PSwidth,length"
+ instead of (the correct) "PSlength,width" as
+ documented by HP. It appears that many major CAD
+ applications are broken and this change allows the
+ auto-rotation to work with them.
+ - The IPP "printer-resolution" option was not being
+ translated.
+ - The charset files did not include the Microsoft
+ "standard" characters from 128 to 159 (unused by the
+ ISO-8859-x charsets)
+ - The scheduler was chunking the Content-Type field from
+ CGI programs; this problem was most noticeable with
+ Microsoft Internet Explorer 5.
+ - By popular demand, the printers, jobs, and classes
+ CGIs no longer force a reload of the page every 10/30
+ seconds.
+ - The scheduler incorrectly required that the IPP client
+ provide a document-format attribute for the
+ validate-job operation.
+ - Clients that sent bad IPP requests without the
+ required attributes-natural-language and
+ attributes-charset attributes would crash the
+ scheduler.
+
+
+CHANGES IN CUPS v1.0.4
+
+ - Documentation updates.
+ - Jobs would get stuck in the queue and wouldn't print
+ until you enabled the queue.
+ - The lp and lpr commands now catch SIGHUP and SIGINTR.
+ - The lp and lpr commands now use sigaction or sigset
+ when available.
+ - CUPS library updates for WIN32/OS-2
+
+
+CHANGES IN CUPS v1.0.3
+
+ - Documentation updates.
+ - The lpq man page was missing.
+ - The configure script was not properly detecting the
+ image libraries.
+ - The top-level makefile was calling "make" instead of
+ "$(MAKE)".
+ - PostScript filter fixes for number-up, OutputOrder,
+ and %Trailer.
+ - The imagetops filter didn't end the base-85 encoding
+ properly if the image data was not a multiple of 4
+ bytes in length.
+ - The imagetoraster filter didn't generate good banded
+ RGB or CMY data (was dividing the line width by 4
+ instead of 3...)
+ - The imagetoraster filter now records the bounding
+ box of the image on the page.
+ - The CUPS image library cache code wasn't working as
+ designed; images larger than the maximum RIP cache
+ would eventually thrash using the same cache tile.
+ - The CUPS image library TIFF loading code didn't
+ handle unknown resolution units properly; the fixed
+ code uses a default resolution of 128 PPI.
+ - cupsGetClasses() and cupsGetPrinters() did not free
+ existing strings if they ran out of memory.
+ - The scheduler logs incorrectly contained 3 digits for
+ the timezone offset instead of 4.
+ - The scheduler now does a lookup for the default user
+ and group ID; the previous hardcoded values caused
+ problems with the LPD backend.
+ - The cancel-job operation now allows any user in the
+ system group to cancel any job.
+ - The cancel-job operation stopped the print queue if
+ the job was being printed.
+ - Now only stop printers if the backend fails. If the
+ filter fails then the failure is noted in the
+ error_log and printing continues with the next file in
+ the queue.
+ - Now log whether a filter fails because of a signal
+ or because it returned a non-zero exit status.
+ - The root user now always passes the system group test.
+ - Printers with an interface script and remote printers
+ and classes didn't have a printer-make-and-model
+ attribute.
+ - Added logging of lost/timed-out remote printers.
+ - The HP-GL/2 filter was scaling the pen width twice.
+ - Updated the HP-GL/2 filter to use a single SP (Set
+ Pen) procedure. This makes the output smaller and is
+ more appropriate since the filter keeps track of the
+ pen states already.
+ - The scheduler didn't handle passwords with spaces.
+ - The IPP backend now does multiple copies and retries
+ if the destination server requires it (e.g. HP
+ JetDirect.)
+ - The disable command didn't implement the "-c" option
+ (cancel all jobs.)
+ - Changed the CMYK generation function for the image file
+ and PostScript RIPs.
+ - The lp command didn't support the "-h" option as
+ documented.
+ - The AppSocket, IPP, and LPD backends now retry on all
+ network errors. This should prevent stopped queues
+ caused by a printer being disconnected from the
+ network or powered off.
+ - The scheduler now restarts a job if the corresponding
+ printer is modified.
+ - The image RIPs now rotate the image if needed to fit
+ on the page.
+
+
+CHANGES IN CUPS v1.0.2
+
+ - The HP-GL/2 filter didn't always scale the output
+ correctly.
+ - The HP-GL/2 filter now supports changing the page size
+ automatically when the "fitplot" option is not used.
+ - The cancel-job operation was expecting a resource name
+ of the form "/job/#" instead of "/jobs/#"; this
+ prevented the cancel and lprm commands from working.
+ - The backends didn't log pages when files were printed
+ using the "-oraw" option.
+ - The authorization code did not work with the Slackware
+ long shadow password package because its crypt() can
+ return NULL.
+ - The chunking code didn't work for reading the response
+ of a POST request.
+ - cupsGetPPD() now does authentication as needed.
+ - The N-up code in the PostScript filter didn't work
+ with some printers (grestoreall would restore the
+ default blank page and device settings).
+ - The N-up code in the PostScript filter didn't scale
+ the pages to fit within the imageable area of the
+ page.
+ - Wasn't doing an fchown() on the request files. This
+ caused problems when the default root account group
+ and CUPS group were not the same.
+
+
+CHANGES IN CUPS v1.0.1
+
+ - Documentation updates.
+ - Fixed a bunch of possible buffer-overflow conditions.
+ - The scheduler now supports authentication using PAM.
+ - Updated the Italian message file.
+ - httpEncode64() didn't add an extra "=" if there was
+ only one byte in the last three-byte group.
+ - Now drop any trailing character set from the locale
+ string (e.g. "en_US.ISO_8859-1" becomes "en_US")
+ - Fixed "timezone" vs "tm_gmtoff" usage for BSD-based
+ operating systems.
+ - Updated IPP security so that "get" operations can be
+ done from any resource name; this allows the CGIs to
+ work with printer authentication enabled so long as
+ authentication isn't turned on for the whole "site".
+ - The IPP code didn't properly handle the "unsupported"
+ group; this caused problems with the HP JetDirect since
+ it doesn't seem to support the "copies" attribute.
+ - The HTTP chunking code was missing a CR LF pair at the
+ end of a 0-length chunk.
+ - The httpSeparate() function didn't handle embedded
+ usernames and passwords in the URI properly.
+ - Doing "lpadmin -p printer -E" didn't restart printing
+ if there were pending jobs.
+ - The cancel-job operation now requires either a
+ requesting-user-name attribute or an authenticated
+ username.
+ - The add-printer code did not report errors if the
+ interface script or PPD file could not be renamed.
+ - Request files are now created without world read
+ permissions.
+ - Added a cupsLastError() function to the CUPS API to
+ retrieve the IPP error code from the last request.
+ - Options are now case-insensitive.
+ - The lpq command now provides 10 characters for the
+ username instead of the original (Berkeley standard)
+ 7.
+ - The cancel command needed a local CUPS server to work
+ (or the appropriate ServerName in cupsd.conf)
+ - The cancel and lprm commands didn't report the IPP
+ error if the job could not be cancelled.
+ - The lp and lpr commands didn't intercept SIGTERM to
+ remove temporary files when printing from stdin.
+ - The lp and lpr commands didn't report the IPP error if
+ the job could not be printed.
diff --git a/CREDITS.txt b/CREDITS.txt
new file mode 100644
index 000000000..522774972
--- /dev/null
+++ b/CREDITS.txt
@@ -0,0 +1,33 @@
+CREDITS.txt - 04/26/2003
+------------------------
+
+Few projects are completed by one person, and CUPS is no exception. We'd
+like to thank the following individuals for their contributions:
+
+ Nathaniel Barbour - Lots of testing and feedback.
+ N. Becker - setsid().
+ Jean-Eric Cuendet - GhostScript filters for CUPS.
+ Van Dang - HTTP and IPP policeman.
+ L. Peter Deutsch - MD5 code.
+ Dr. ZP Han - setgid()/setuid().
+ Guy Harris - *BSD shared libraries and lots of other fixes.
+ Bjoern Jacke - I18N stuff.
+ Wang Jian - CUPS RPM corrections.
+ Roderick Johnstone - Beta tester of the millenium.
+ Till Kamppeter - Bug fixes, beta testing, evangelism.
+ Kiko - Bug fixes.
+ Sergey V. Kovalyov - ESP Print Pro and CUPS beta tester.
+ Mark Lawrence - Microsoft interoperability testing.
+ Jeff Licquia - Bug fixes, beta testing, evangelism.
+ Jason McMullan - Original CUPS RPM distributions.
+ Wes Morgan - *BSD fixes.
+ Ulrich Oldendorf - German locale.
+ Giulio Orsero - Bug fixes and testing.
+ Kurt Pfeifle - Bug fixes, beta testing, evangelism.
+ Gilles QUERRET - French man pages.
+ Petter Reinholdtsen - HP-UX compiler stuff.
+ Stuart Stevens - HP JetDirect IPP information.
+ Andrea Suatoni - IRIX desktop integration and testing.
+
+If I've missed someone, please let me know by sending an email to
+"mike@easysw.com".
diff --git a/ENCRYPTION.txt b/ENCRYPTION.txt
new file mode 100644
index 000000000..e0e3ba9ff
--- /dev/null
+++ b/ENCRYPTION.txt
@@ -0,0 +1,142 @@
+ENCRYPTION - CUPS v1.1.20 - 11/24/2003
+--------------------------------------
+
+This file describes the encryption support provided by CUPS.
+
+WARNING: CLIENTS CURRENTLY TRUST ALL CERTIFICATES FROM SERVERS.
+This makes the CUPS client applications vulnerable to "man in
+the middle" attacks, so we don't recommend using this to do
+remote administration over WANs at this time.
+
+Future versions of CUPS will keep track of server certificates
+and provide a callback/confirmation interface for accepting new
+certificates and warning when a certificate has changed.
+
+
+LEGAL STUFF
+
+BEFORE USING THE ENCRYPTION SUPPORT, PLEASE VERIFY THAT IT IS
+LEGAL TO DO SO IN YOUR COUNTRY. CUPS by itself doesn't include
+any encryption code, but it can link against the OpenSSL, GNU
+TLS, or CDSA libraries which do.
+
+
+OVERVIEW OF ENCRYPTION SUPPORT IN CUPS
+
+CUPS supports SSL/2.0, SSL/3.0, and TLS/1.0 encryption using
+keys as large as 128-bits. Encryption support is provided via
+the OpenSSL, GNU TLS, or CDSA libraries and some new hooks in
+the CUPS code.
+
+CUPS provides support for dedicated (https) and "upgrade" (TLS)
+encryption of sessions. The "HTTP Upgrade" method is described
+in RFC 2817; basically, the client can be secure or unsecure,
+and the client or server initiates an upgrade to a secure
+connection via some new HTTP fields and status codes. The HTTP
+Upgrade method is new and no browsers we know of support it yet.
+Stick with "https" for web browsers.
+
+The current implementation is very basic. The CUPS client
+software (lp, lpr, etc.) uses encryption as requested by the
+user or server.
+
+The user can specify the "-E" option with the printing commands
+to force encryption of the connection. Encryption can also be
+specified using the Encryption directive in the client.conf file
+or in the CUPS_ENCRYPTION environment variable:
+
+ Never
+
+ Never do encryption.
+
+ Always
+
+ Always do SSL/TLS encryption using the https scheme.
+
+ IfRequested
+
+ Upgrade to TLS encryption if the server asks for it.
+ This is the default setting.
+
+ Required
+
+ Always upgrade to TLS encryption as soon as the
+ connection is made. This is different than the "Always"
+ mode above since the connection is initially unsecure
+ and the client initiates the upgrade to TLS encryption.
+ (same as using the "-E" option)
+
+These keywords are also used in the cupsd.conf file to secure
+particular locations. To secure all traffic on the server, listen
+on port 443 (https port) instead of port 631 and change the "ipp"
+service listing (or add it if you don't have one) in /etc/services
+to 443. To provide both secure and normal methods, add a line
+reading:
+
+ SSLPort 443
+
+to /etc/cups/cupsd.conf.
+
+
+BEFORE YOU BEGIN
+
+You'll need the OpenSSL, GNU TLS, or CDSA libraries from:
+
+ http://www.openssl.org/
+ http://www.gnutls.org/
+ http://www.intel.com/labs/archive/cdsa.htm
+
+
+CONFIGURING WITH ENCRYPTION SUPPORT
+
+Once you have the OpenSSL, GNU TLS, or CDSA libraries installed,
+you'll need to configure CUPS to use it with the "--enable-ssl"
+option:
+
+ ./configure --enable-ssl
+
+If the library stuff is not in a standard location, make sure to
+define the CFLAGS, CXXFLAGS, and LDFLAGS environment variables
+with the appropriate compiler and linker options first.
+
+
+GENERATING A SERVER CERTIFICATE AND KEY
+
+The following OpenSSL command will generate a server certificate
+and key that you can play with. Since the certificate is not
+properly signed it will generate all kinds of warnings in
+Netscape and MSIE:
+
+ openssl req -new -x509 -keyout /etc/cups/ssl/server.key \
+ -out /etc/cups/ssl/server.crt -days 365 -nodes
+
+ chmod 600 /etc/cups/ssl/server.*
+
+The "-nodes" option prevents the certificate and key from being
+encrypted. The cupsd process runs in the background, detached
+from any input source; if you encrypt these files then cupsd
+will not be able to load them!
+
+Send all rants about non-encrypted certificate and key files to
+/dev/null. It makes sense to encrypt user files, but not for
+files used by system processes/daemons...
+
+
+REPORTING PROBLEMS
+
+If you have problems, READ THE DOCUMENTATION FIRST! If the
+documentation does not solve your problems please send an email
+to "cups-support@cups.org". Include your operating system and
+version, compiler and version, and any errors or problems you've
+run into. The "/var/log/cups/error_log" file should also be sent,
+as it often helps to determine the cause of your problem.
+
+If you are running a version of Linux, be sure to provide the
+Linux distribution you have, too.
+
+Please note that the "cups-support@cups.org" email address goes
+to the CUPS developers; they are busy people, so your email may
+go unanswered for days or weeks. In general, only general build
+or distribution problems will actually get answered - for
+end-user support see the "README.txt" for a summary of the
+resources available.
diff --git a/INSTALL.txt b/INSTALL.txt
new file mode 100644
index 000000000..3206a9147
--- /dev/null
+++ b/INSTALL.txt
@@ -0,0 +1,190 @@
+INSTALL - CUPS v1.1.22 - 10/29/2004
+-----------------------------------
+
+This file describes how to compile and install CUPS from source
+code. For more information on CUPS see the file called
+"README.txt". A complete change log can be found in
+"CHANGES.txt".
+
+**** IF YOU HAVE A NON-POSTSCRIPT PRINTER, YOU WILL ALSO ****
+**** NEED TO INSTALL ESP GHOSTSCRIPT OR A PATCHED VERSION ****
+**** OF THE STANDARD GHOSTSCRIPT RELEASES. ****
+
+
+BEFORE YOU BEGIN
+
+You'll need ANSI-compliant C and C++ compilers, plus a make
+program and Bourne shell. The GNU compiler tools work well -
+we've tested the current CUPS code against GCC 2.95.x with
+excellent results.
+
+The makefiles used by the project should work with all versions
+of make. We've tested them with GNU make as well as the make
+programs shipped by Compaq, HP, SGI, and Sun. FreeBSD users
+should use GNU make (gmake).
+
+Besides these tools you'll want the following libraries:
+
+ - JPEG 6b or higher
+ - PNG 1.0.6 or higher
+ - TIFF 3.4 or higher
+ - ZLIB 1.1.3 or higher
+
+CUPS will compile and run without these, however you'll miss out on
+many of the features provided by CUPS.
+
+Also, please note that CUPS no longer includes the Ghostscript-
+based pstoraster filter. You *must* download Ghostscript
+separately and patch it using the files in the pstoraster
+subdirectory, or download the ESP Ghostscript distribution from
+the CUPS web site. For more information see the README file in
+the pstoraster subdirectory.
+
+
+COMPILING FROM CVS
+
+The CUPS CVS repository doesn't hold a copy of the pre-built
+configure script. You'll need to run the GNU autoconf software
+(2.52 or higher) before compiling the software from CVS:
+
+ autoconf ENTER
+
+
+CONFIGURATION
+
+CUPS uses GNU autoconf, so you should find the usual "configure"
+script in the main CUPS source directory. To configure CUPS for
+your system, type:
+
+ ./configure ENTER
+
+The default installation will put the CUPS software in the
+"/etc", "/usr", and "/var" directories on your system, which
+will overwrite any existing printing commands on your system.
+Use the "--prefix" option to install the CUPS software in
+another location:
+
+ ./configure --prefix=/some/directory ENTER
+
+If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in
+a system default location (typically "/usr/include" and
+"/usr/lib") you'll need to set the CFLAGS, CXXFLAGS, DSOFLAGS,
+and LDFLAGS environment variables prior to running configure:
+
+ setenv CFLAGS "-I/some/directory" ENTER
+ setenv CXXFLAGS "-I/some/directory" ENTER
+ setenv DSOFLAGS "-L/some/directory" ENTER
+ setenv LDFLAGS "-L/some/directory" ENTER
+ ./configure ... ENTER
+
+or:
+
+ CFLAGS="-I/some/directory"; export CFLAGS ENTER
+ CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER
+ DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTER
+ LDFLAGS="-L/some/directory"; export LDFLAGS ENTER
+ ./configure ... ENTER
+
+To enable support for encryption, you'll also want to add the
+"--enable-ssl" option:
+
+ ./configure --enable-ssl
+
+SSL and TLS support require the OpenSSL library, available at:
+
+ http://www.openssl.org
+
+If the OpenSSL header files and libraries are not in a standard
+location, specify the locations of these files using the
+--with-openssl-includes and --with-openssl-libs directives:
+
+ ./configure --enable-ssl \
+ --with-openssl-includes=/foo/bar/include \
+ --with-openssl-libs=/foo/bar/lib
+
+See the file "ENCRYPTION.txt" for information on using the
+encryption support in CUPS.
+
+Once you have configured things, just type:
+
+ make ENTER
+
+or if you have FreeBSD, NetBSD, or OpenBSD type:
+
+ gmake ENTER
+
+to build the software.
+
+
+INSTALLING THE SOFTWARE
+
+Once you have built the software you need to install it. The
+"install" target provides a quick way to install the software on
+your local system:
+
+ make install ENTER
+
+or for FreeBSD, NetBSD, or OpenBSD:
+
+ gmake install ENTER
+
+You can also build binary packages that can be installed on other
+machines using the RPM spec file ("cups.spec") or EPM list file
+("cups.list"). The latter also supports building of binary RPMs,
+so it may be more convenient to use - we use EPM to build all of
+our binary distributions.
+
+You can find the RPM software at:
+
+ http://www.rpm.org
+
+The EPM software is at:
+
+ http://www.easysw.com/epm/
+
+
+CREATING BINARY DISTRIBUTIONS WITH EPM
+
+The top level makefile supports generation of many types of binary
+distributions using EPM. To build a binary distribution type:
+
+ make <format> ENTER
+
+or
+
+ gmake <format> ENTER
+
+for FreeBSD, NetBSD, and OpenBSD. The <format> target is one of
+the following:
+
+ epm - Builds a portable shell script and tar file based
+ distribution. This format will also backup your
+ existing printing system if you decide to remove
+ CUPS at some future time.
+ aix - Builds an AIX binary distribution.
+ bsd - Builds a *BSD binary distribution.
+ deb - Builds a Debian binary distribution.
+ depot - Builds a HP-UX binary distribution.
+ pkg - Builds a Solaris binary distribution.
+ rpm - Builds a RPM binary distribution.
+ tardist - Builds an IRIX binary distribution.
+
+
+REPORTING PROBLEMS
+
+If you have problems, READ THE DOCUMENTATION FIRST! If the
+documentation does not solve your problems please send an email
+to "cups-support@cups.org". Include your operating system and
+version, compiler and version, and any errors or problems you've
+run into. The "/var/log/cups/error_log" file should also be sent,
+as it often helps to determine the cause of your problem.
+
+If you are running a version of Linux, be sure to provide the
+Linux distribution you have, too.
+
+Please note that the "cups-support@cups.org" email address goes
+to the CUPS developers; they are busy people, so your email may
+go unanswered for days or weeks. In general, only general build
+or distribution problems will actually get answered - for
+end-user support see the "README.txt" for a summary of the
+resources available.
diff --git a/INSTALL_fr.txt b/INSTALL_fr.txt
new file mode 100644
index 000000000..841c10df4
--- /dev/null
+++ b/INSTALL_fr.txt
@@ -0,0 +1,19 @@
+INSTALL_fr - CUPS v1.1.19 - 04/08/2003
+--------------------------------------
+
+Vous cherchez des instructions d'installation ? Lisez le fichier
+INSTALL.txt (anglais) et/ou reportez vous au "Manuel de
+l'administrateur" (en français) situé dans le sous-répertoire
+"doc/fr"
+
+Vous trouverez deux autres manuels en français dans ce
+sous-répertoire :
+
+ - Aperçu de CUPS
+ - Manuel de l'utilisateur
+
+Une fois CUPS installé, si vous configurez votre navigateur
+"web" pour que la langue de base soit le français, vous
+disposerez également d'une interface "web" en français pour
+l'administration et d'utilistation de CUPS.
+
diff --git a/LICENSE.html b/LICENSE.html
new file mode 100644
index 000000000..17bfcc72c
--- /dev/null
+++ b/LICENSE.html
@@ -0,0 +1,956 @@
+<HTML>
+<HEAD>
+ <TITLE>Software License Agreement - Common UNIX Printing System</TITLE>
+</HEAD>
+
+<BODY BGCOLOR="#ffffff" TEXT="#000000">
+
+<H2 ALIGN="CENTER">Common UNIX Printing System License Agreement</H2>
+
+<P ALIGN="CENTER">Copyright 1997-2004 by Easy Software Products<BR>
+44141 AIRPORT VIEW DR STE 204<BR>
+HOLLYWOOD, MARYLAND 20636-3142 USA<BR>
+<BR>
+Voice: +1.301.373.9600<BR>
+Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A><BR>
+WWW: <A HREF="http://www.cups.org">http://www.cups.org</A>
+
+<H3>Introduction</H3>
+
+<P>The Common UNIX Printing System<SUP>TM</SUP>,
+("CUPS<SUP>TM</SUP>"), is provided under the GNU General Public
+License ("GPL") and GNU Library General Public License ("LGPL"),
+Version 2, with exceptions for Apple operating systems and the
+OpenSSL toolkit. A copy of the exceptions and licenses follow
+this introduction.
+
+<P>The GNU LGPL applies to the CUPS API library, located in the
+"cups" subdirectory of the CUPS source distribution and in the
+"cups" include directory and library files in the binary
+distributions. The GNU GPL applies to the remainder of the CUPS
+distribution, including the "pdftops" filter which is based upon
+Xpdf and the CUPS imaging library.
+
+<P>For those not familiar with the GNU GPL, the license basically
+allows you to:
+
+<UL>
+
+ <LI>Use the CUPS software at no charge.</LI>
+
+ <LI>Distribute verbatim copies of the software in source
+ or binary form.</LI>
+
+ <LI>Sell verbatim copies of the software for a media
+ fee, or sell support for the software.</LI>
+
+ <LI>Distribute or sell printer drivers and filters that
+ use CUPS so long as source code is made available under
+ the GPL.</LI>
+
+</UL>
+
+<P>What this license <B>does not</B> allow you to do is make
+changes or add features to CUPS and then sell a binary
+distribution without source code. You must provide source for
+any new drivers, changes, or additions to the software, and all
+code must be provided under the GPL or LGPL as appropriate. The
+only exceptions to this are the portions of the CUPS software
+covered by the Apple operating system license exceptions
+outlined later in this license agreement.
+
+<P>The GNU LGPL relaxes the "link-to" restriction, allowing you
+to develop applications that use the CUPS API library under
+other licenses and/or conditions as appropriate for your
+application.
+
+<H3>License Exceptions</H3>
+
+<P>In addition, as the copyright holder of CUPS, Easy Software
+Products grants the following special exceptions:
+
+<OL>
+
+ <LI><B>Apple Operating System Development License
+ Exception</B>;
+
+ <OL TYPE="a">
+
+ <LI>Software that is developed by any person or
+ entity for an Apple Operating System ("Apple
+ OS-Developed Software"), including but not
+ limited to Apple and third party printer
+ drivers, filters, and backends for an Apple
+ Operating System, that is linked to the CUPS
+ imaging library or based on any sample filters
+ or backends provided with CUPS shall not be
+ considered to be a derivative work or collective
+ work based on the CUPS program and is exempt
+ from the mandatory source code release clauses
+ of the GNU GPL. You may therefore distribute
+ linked combinations of the CUPS imaging library
+ with Apple OS-Developed Software without
+ releasing the source code of the Apple
+ OS-Developed Software. You may also use sample
+ filters and backends provided with CUPS to
+ develop Apple OS-Developed Software without
+ releasing the source code of the Apple
+ OS-Developed Software.</LI>
+
+ <LI>An Apple Operating System means any
+ operating system software developed and/or
+ marketed by Apple Computer, Inc., including but
+ not limited to all existing releases and
+ versions of Apple's Darwin, Mac OS X, and Mac OS
+ X Server products and all follow-on releases and
+ future versions thereof.</LI>
+
+ <LI>This exception is only available for Apple
+ OS-Developed Software and does not apply to
+ software that is distributed for use on other
+ operating systems.</LI>
+
+ <LI>All CUPS software that falls under this
+ license exception have the following text at the
+ top of each source file:
+
+ <BLOCKQUOTE>This file is subject to the Apple
+ OS-Developed Software
+ exception.</BLOCKQUOTE></LI>
+
+ </OL>
+
+ <LI><B>OpenSSL Toolkit License Exception</B>;
+
+ <OL TYPE="a">
+
+ <LI>Easy Software Products explicitly allows the
+ compilation and distribution of the CUPS
+ software with the OpenSSL Toolkit.</LI>
+
+ </OL>
+
+</OL>
+
+<P>No developer is required to provide these exceptions in a
+derived work.
+
+<H3>Trademarks</H3>
+
+<P>Easy Software Products has trademarked the Common UNIX
+Printing System, CUPS, and CUPS logo. You may use these names
+and logos in any direct port or binary distribution of CUPS.
+Please contact Easy Software Products for written permission to
+use them in derivative products. Our intention is to protect the
+value of these trademarks and ensure that any derivative product
+meets the same high-quality standards as the original.
+
+<H3>Binary Distribution Rights</H3>
+
+<P>Easy Software Products also sells rights to the CUPS source
+code under a binary distribution license for vendors that are
+unable to release source code for their drivers, additions, and
+modifications to CUPS under the GNU GPL and LGPL. For
+information please contact us at the address shown above.
+
+<P>The Common UNIX Printing System provides a "pdftops" filter
+that is based on the Xpdf software. For binary distribution
+licensing of this software, please contact:
+
+<BLOCKQUOTE>
+Derek B. Noonburg<BR>
+Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A><BR>
+WWW: <A HREF="http://www.foolabs.com/xpdf/">http://www.foolabs.com/xpdf/</A>
+</BLOCKQUOTE>
+
+<H3>Support</H3>
+
+<P>Easy Software Products sells software support for CUPS as
+well as a commercial printing product based on CUPS called ESP
+Print Pro. You can find out more at our web site:
+
+<UL><PRE>
+<A HREF="http://www.easysw.com/">http://www.easysw.com/</A>
+</PRE></UL>
+
+<!-- NEW PAGE -->
+<H2>GNU GENERAL PUBLIC LICENSE</H2>
+
+<P>Version 2, June 1991
+
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+
+<H4>Preamble</H4>
+
+<P>The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+<P>When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+<P>To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+<P>For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+<P>We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+<P>Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+<P>Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+<P>The precise terms and conditions for copying, distribution and
+modification follow.
+
+<H4>GNU GENERAL PUBLIC LICENSE<BR>
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+
+<OL START="0">
+
+<LI>This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+<P>Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+<LI>You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+<P>You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+<LI>You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+<OL TYPE="a">
+
+<LI>You must cause the modified files to carry prominent notices
+stating that you changed the files and the date of any change.
+
+<LI>You must cause any work that you distribute or publish, that in
+whole or in part contains or is derived from the Program or any
+part thereof, to be licensed as a whole at no charge to all third
+parties under the terms of this License.
+
+<LI>if the modified program normally reads commands interactively
+when run, you must cause it, when started running for such
+interactive use in the most ordinary way, to print or display an
+announcement including an appropriate copyright notice and a
+notice that there is no warranty (or else, saying that you provide
+a warranty) and that users may redistribute the program under
+these conditions, and telling the user how to view a copy of this
+License. (Exception: if the Program itself is interactive but
+does not normally print such an announcement, your work based on
+the Program is not required to print an announcement.)
+
+</OL>
+
+<P>These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+<P>Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+<P>In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+<LI>You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+<OL TYPE="a">
+
+<LI>Accompany it with the complete corresponding machine-readable
+source code, which must be distributed under the terms of Sections
+1 and 2 above on a medium customarily used for software interchange; or,
+
+<LI>Accompany it with a written offer, valid for at least three
+years, to give any third party, for a charge no more than your
+cost of physically performing source distribution, a complete
+machine-readable copy of the corresponding source code, to be
+distributed under the terms of Sections 1 and 2 above on a medium
+customarily used for software interchange; or,
+
+<LI>Accompany it with the information you received as to the offer
+to distribute corresponding source code. (This alternative is
+allowed only for noncommercial distribution and only if you
+received the program in object code or executable form with such
+an offer, in accord with Subsection b above.)
+
+</OL>
+
+<P>The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+<P>If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+<LI>You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+<LI>You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+<LI>Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+<LI>If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+<P>If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+<P>It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+<P>This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+<LI>If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+<LI>The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+<P>Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+<LI>If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+</OL>
+
+<H4>NO WARRANTY</H4>
+
+<OL START="11">
+
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+</OL>
+
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2>GNU LIBRARY GENERAL PUBLIC LICENSE</H2>
+
+<P>Version 2, June 1991
+
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+
+<H4>Preamble</H4>
+
+<P>The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+<P>This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+<P>When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+<P>To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+<P>For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+<P>Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+<P>Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+<P>Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+<P>Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+<P>The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+<P>Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+<P>However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+<P>The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+<P>Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+
+<P><STRONG>0.</STRONG>
+This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+<P>A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+<P>The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+<P>"Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+<P>Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+<P><STRONG>1.</STRONG>
+You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+<P>You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+<P><STRONG>2.</STRONG>
+You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+<OL TYPE="a">
+
+ <LI>The modified work must itself be a software library.
+
+ <P>
+ <LI>You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ <P>
+ <LI>You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ <P>
+ <LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ <P>(For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+</OL>
+
+<P>These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+<P>Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+<P>In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+<P><STRONG>3.</STRONG>
+You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+<P>Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+<P>This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+<P><STRONG>4.</STRONG>
+You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+<P>If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+<P><STRONG>5.</STRONG>
+A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+<P>However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+<P>When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+<P>If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+<P>Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+<P><STRONG>6.</STRONG>
+As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+<P>You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+<OL TYPE="a">
+
+ <LI>Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ <P>
+ <LI>Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ <P>
+ <LI>If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ <P>
+ <LI>Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+</OL>
+
+<P>For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+<P>It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+<P><STRONG>7.</STRONG>
+You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+<OL TYPE="a">
+
+ <LI>Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ <P>
+ <LI>Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+</OL>
+
+<P><STRONG>8.</STRONG>
+You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+<P><STRONG>9.</STRONG>
+You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+<P><STRONG>10.</STRONG>
+Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+<P><STRONG>11.</STRONG>
+If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+<P>If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+<P>It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+<P>This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+<P><STRONG>12.</STRONG>
+If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+<P><STRONG>13.</STRONG>
+The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+<P>Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+<P><STRONG>14.</STRONG>
+If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+<P><STRONG>NO WARRANTY</STRONG>
+
+<P><STRONG>15.</STRONG>
+BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+<P><STRONG>16.</STRONG>
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+</BODY>
+</HTML>
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..d3095f2fe
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,861 @@
+ Common UNIX Printing System License Agreement
+
+ Copyright 1997-2004 by Easy Software Products
+ 44141 AIRPORT VIEW DR STE 204
+ HOLLYWOOD, MARYLAND 20636-3142 USA
+
+ Voice: +1.301.373.9600
+ Email: cups-info@cups.org
+ WWW: http://www.cups.org
+
+
+INTRODUCTION
+
+The Common UNIX Printing System(tm), ("CUPS(tm)"), is provided
+under the GNU General Public License ("GPL") and GNU Library
+General Public License ("LGPL"), Version 2, with exceptions for
+Apple operating systems and the OpenSSL toolkit. A copy of the
+exceptions and licenses follow this introduction.
+
+The GNU LGPL applies to the CUPS API library, located in the
+"cups" subdirectory of the CUPS source distribution and in the
+"cups" include directory and library files in the binary
+distributions. The GNU GPL applies to the remainder of the CUPS
+distribution, including the "pdftops" filter which is based upon
+Xpdf and the CUPS imaging library.
+
+For those not familiar with the GNU GPL, the license basically
+allows you to:
+
+ - Use the CUPS software at no charge.
+ - Distribute verbatim copies of the software in source or
+ binary form.
+ - Sell verbatim copies of the software for a media fee, or
+ sell support for the software.
+ - Distribute or sell printer drivers and filters that use
+ CUPS so long as source code is made available under the
+ GPL.
+
+What this license *does not* allow you to do is make changes or
+add features to CUPS and then sell a binary distribution without
+source code. You must provide source for any new drivers,
+changes, or additions to the software, and all code must be
+provided under the GPL or LGPL as appropriate. The only
+exceptions to this are the portions of the CUPS software covered
+by the Apple operating system license exceptions outlined later
+in this license agreement.
+
+The GNU LGPL relaxes the "link-to" restriction, allowing you to
+develop applications that use the CUPS API library under other
+licenses and/or conditions as appropriate for your application.
+
+
+LICENSE EXCEPTIONS
+
+In addition, as the copyright holder of CUPS, Easy Software
+Products grants the following special exceptions:
+
+ 1. Apple Operating System Development License Exception;
+
+ a. Software that is developed by any person or entity
+ for an Apple Operating System ("Apple OS-Developed
+ Software"), including but not limited to Apple and
+ third party printer drivers, filters, and backends
+ for an Apple Operating System, that is linked to the
+ CUPS imaging library or based on any sample filters
+ or backends provided with CUPS shall not be
+ considered to be a derivative work or collective work
+ based on the CUPS program and is exempt from the
+ mandatory source code release clauses of the GNU GPL.
+ You may therefore distribute linked combinations of
+ the CUPS imaging library with Apple OS-Developed
+ Software without releasing the source code of the
+ Apple OS-Developed Software. You may also use sample
+ filters and backends provided with CUPS to develop
+ Apple OS-Developed Software without releasing the
+ source code of the Apple OS-Developed Software.
+
+ b. An Apple Operating System means any operating system
+ software developed and/or marketed by Apple Computer,
+ Inc., including but not limited to all existing
+ releases and versions of Apple's Darwin, Mac OS X,
+ and Mac OS X Server products and all follow-on
+ releases and future versions thereof.
+
+ c. This exception is only available for Apple
+ OS-Developed Software and does not apply to software
+ that is distributed for use on other operating
+ systems.
+
+ d. All CUPS software that falls under this license
+ exception have the following text at the top of each
+ source file:
+
+ This file is subject to the Apple OS-Developed
+ Software exception.
+
+ 2. OpenSSL Toolkit License Exception;
+
+ a. Easy Software Products explicitly allows the
+ compilation and distribution of the CUPS software
+ with the OpenSSL Toolkit.
+
+No developer is required to provide these exceptions in a
+derived work.
+
+
+TRADEMARKS
+
+Easy Software Products has trademarked the Common UNIX Printing
+System, CUPS, and CUPS logo. You may use these names and logos
+in any direct port or binary distribution of CUPS. Please
+contact Easy Software Products for written permission to use
+them in derivative products. Our intention is to protect the
+value of these trademarks and ensure that any derivative product
+meets the same high-quality standards as the original.
+
+
+BINARY DISTRIBUTION RIGHTS
+
+Easy Software Products also sells rights to the CUPS source code
+under a binary distribution license for vendors that are unable
+to release source code for their drivers, additions, and
+modifications to CUPS under the GNU GPL and LGPL. For
+information please contact us at the address shown above.
+
+The Common UNIX Printing System provides a "pdftops" filter that
+is based on the Xpdf software. For binary distribution licensing
+of this software, please contact:
+
+ Derek B. Noonburg
+ Email: derekn@foolabs.com
+ WWW: http://www.foolabs.com/xpdf/
+
+
+SUPPORT
+
+Easy Software Products sells software support for CUPS as well
+as a commercial printing product based on CUPS called ESP Print
+Pro. You can find out more at our web site:
+
+ http://www.easysw.com/
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ [This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/Makedefs.in b/Makedefs.in
new file mode 100644
index 000000000..402862496
--- /dev/null
+++ b/Makedefs.in
@@ -0,0 +1,191 @@
+#
+# "$Id$"
+#
+# Common makefile definitions for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+#
+# Programs...
+#
+
+AR = @AR@
+AWK = @AWK@
+CC = @LIBTOOL@ @CC@
+CXX = @LIBTOOL@ @CXX@
+DSO = @DSO@
+HTMLDOC = @HTMLDOC@
+INSTALL = @INSTALL@
+LIBTOOL = @LIBTOOL@
+LN = @LN@ -sf
+MV = @MV@
+NROFF = @NROFF@
+RANLIB = @RANLIB@
+RM = @RM@ -f
+SED = @SED@
+SHELL = /bin/sh
+STRIP = @STRIP@
+
+#
+# Installation programs...
+#
+
+INSTALL_BIN = $(LIBTOOL) $(INSTALL) -m 755 -s
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_DIR = $(INSTALL) -d
+INSTALL_LIB = $(LIBTOOL) $(INSTALL) -m 755
+INSTALL_MAN = $(INSTALL) -m 644
+INSTALL_SCRIPT = $(INSTALL) -m 755
+
+#
+# Default user and group for the scheduler...
+#
+
+CUPS_USER = @CUPS_USER@
+CUPS_GROUP = @CUPS_GROUP@
+
+#
+# Libraries...
+#
+
+LIBCUPS = @LIBCUPS@
+LIBCUPSIMAGE = @LIBCUPSIMAGE@
+LIBJPEG = @LIBJPEG@
+LIBMALLOC = @LIBMALLOC@
+LIBPAPER = @LIBPAPER@
+LIBPNG = @LIBPNG@
+LIBSLP = @LIBSLP@
+LIBTIFF = @LIBTIFF@
+LIBZ = @LIBZ@
+
+#
+# Program options...
+#
+# OPTIM defines the common compiler optimization/debugging options.
+# OPTIONS defines other compile-time options (currently only -dDEBUG for
+# extra debug info)
+#
+
+ARFLAGS = @ARFLAGS@
+BACKLIBS = @BACKLIBS@
+CFLAGS = $(RC_CFLAGS) $(SSLFLAGS) @CPPFLAGS@ @CFLAGS@ -I.. $(OPTIONS)
+COMMONLIBS = @COMMONLIBS@
+CXXFLAGS = $(RC_CFLAGS) @CPPFLAGS@ @CXXFLAGS@ -I.. $(OPTIONS)
+CXXLIBS = @CXXLIBS@
+DSOFLAGS = @DSOFLAGS@
+DSOLIBS = @DSOLIBS@ $(COMMONLIBS)
+IMGLIBS = @IMGLIBS@ -lm
+LDFLAGS = -L../cups -L../filter $(RC_CFLAGS) @LDFLAGS@ $(OPTIM)
+LINKCUPS = @LINKCUPS@
+LINKCUPSIMAGE = @LINKCUPSIMAGE@
+LIBS = $(LINKCUPS) $(NETLIBS) @LIBS@ $(COMMONLIBS)
+NETLIBS = @NETLIBS@
+OPTIM = @OPTIM@
+OPTIONS =
+PAMLIBS = @PAMLIBS@
+SSLFLAGS = @SSLFLAGS@
+SSLLIBS = @SSLLIBS@
+
+#
+# Directories...
+#
+# The first section uses the GNU names (which are *extremely*
+# difficult to find in a makefile because they are lowercase...)
+# We have to define these first because autoconf uses ${prefix}
+# and ${exec_prefix} for most of the other directories...
+#
+# This is immediately followed by definition in ALL CAPS for the
+# needed directories...
+#
+
+bindir = @bindir@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+infodir = @infodir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+top_srcdir = @top_srcdir@
+
+BUILDROOT = $(DSTROOT)
+
+AMANDIR = $(BUILDROOT)@AMANDIR@
+BINDIR = $(BUILDROOT)@bindir@
+DATADIR = $(BUILDROOT)@CUPS_DATADIR@
+DOCDIR = $(BUILDROOT)@CUPS_DOCROOT@
+INCLUDEDIR = $(BUILDROOT)$(includedir)
+INITDIR = @INITDIR@
+INITDDIR = @INITDDIR@
+LIBDIR = $(BUILDROOT)$(libdir)
+LOCALEDIR = $(BUILDROOT)@CUPS_LOCALEDIR@
+LOGDIR = $(BUILDROOT)@CUPS_LOGDIR@
+MANDIR = $(BUILDROOT)@mandir@
+PMANDIR = $(BUILDROOT)@PMANDIR@
+REQUESTS = $(BUILDROOT)@CUPS_REQUESTS@
+SBINDIR = $(BUILDROOT)@sbindir@
+SERVERBIN = $(BUILDROOT)@CUPS_SERVERBIN@
+SERVERROOT = $(BUILDROOT)@CUPS_SERVERROOT@
+
+CAT1EXT = @CAT1EXT@
+CAT3EXT = @CAT3EXT@
+CAT5EXT = @CAT5EXT@
+CAT8EXT = @CAT8EXT@
+MAN8EXT = @MAN8EXT@
+MAN8DIR = @MAN8DIR@
+
+PAMDIR = $(BUILDROOT)@PAMDIR@
+PAMFILE = @PAMFILE@
+
+
+#
+# Rules...
+#
+
+.SILENT:
+.SUFFIXES: .a .c .cxx .h .man .o .0 .1 .1m .3 .5 .8 .z
+.c.o:
+ echo Compiling $<...
+ $(CC) $(OPTIM) $(CFLAGS) -c $<
+.cxx.o:
+ echo Compiling $<...
+ $(CXX) $(OPTIM) $(CXXFLAGS) -c $<
+.man.0 .man.1 .man.1m .man.3 .man.5 .man.8:
+ echo Formatting $<...
+ $(RM) $@
+ -$(NROFF) -man $< >$@
+.man.z:
+ echo Formatting $<...
+ $(RM) $@ $@.tmp $@.tmp.z
+ -$(NROFF) -man $< >$@.tmp
+ pack -f $@.tmp
+ $(MV) $@.tmp.z $@
+
+
+#
+# End of "$Id$"
+#
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..d0a1bd61a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,170 @@
+#
+# "$Id$"
+#
+# Top-level Makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include Makedefs
+
+#
+# Directories to make...
+#
+
+DIRS = cups backend berkeley cgi-bin filter man pdftops \
+ scheduler systemv
+
+#
+# Make all targets...
+#
+
+all:
+ chmod +x cups-config
+ for dir in $(DIRS); do\
+ echo Making all in $$dir... ;\
+ (cd $$dir ; $(MAKE) $(MFLAGS)) || exit 1;\
+ done
+
+#
+# Remove object and target files...
+#
+
+clean:
+ for dir in $(DIRS); do\
+ echo Cleaning in $$dir... ;\
+ (cd $$dir; $(MAKE) $(MFLAGS) clean) || exit 1;\
+ done
+
+#
+# Make dependencies
+#
+
+depend:
+ for dir in $(DIRS); do\
+ echo Making dependencies in $$dir... ;\
+ (cd $$dir; $(MAKE) $(MFLAGS) depend) || exit 1;\
+ done
+
+
+#
+# Install object and target files...
+#
+
+install: installhdrs
+ for dir in $(DIRS); do\
+ echo Installing in $$dir... ;\
+ (cd $$dir; $(MAKE) $(MFLAGS) install) || exit 1;\
+ done
+ echo Installing in conf...
+ (cd conf; $(MAKE) $(MFLAGS) install)
+ echo Installing in data...
+ (cd data; $(MAKE) $(MFLAGS) install)
+ echo Installing in doc...
+ (cd doc; $(MAKE) $(MFLAGS) install)
+ echo Installing in fonts...
+ (cd fonts; $(MAKE) $(MFLAGS) install)
+ echo Installing in locale...
+ (cd locale; $(MAKE) $(MFLAGS) install)
+ echo Installing in ppd...
+ (cd ppd; $(MAKE) $(MFLAGS) install)
+ echo Installing in templates...
+ (cd templates; $(MAKE) $(MFLAGS) install)
+ echo Installing cups-config script...
+ $(INSTALL_DIR) $(BINDIR)
+ $(INSTALL_SCRIPT) cups-config $(BINDIR)/cups-config
+ echo Installing startup script...
+ if test "x$(INITDIR)" != "x"; then \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/init.d; \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/init.d/cups; \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc0.d; \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc0.d/K00cups; \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc2.d; \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc2.d/S99cups; \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc3.d; \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc3.d/S99cups; \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDIR)/rc5.d; \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDIR)/rc5.d/S99cups; \
+ fi
+ if test "x$(INITDIR)" = "x" -a "x$(INITDDIR)" != "x"; then \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR); \
+ if test "$(INITDDIR)" = "/System/Library/StartupItems/PrintingServices"; then \
+ $(INSTALL_SCRIPT) cups.osx $(BUILDROOT)$(INITDDIR)/PrintingServices; \
+ $(INSTALL_DATA) cups.plist $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \
+ $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj; \
+ $(INSTALL_DATA) cups.strings $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \
+ else \
+ $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR)/cups; \
+ fi \
+ fi
+
+#
+# Install source and header files...
+#
+
+installsrc:
+ gnutar --dereference --exclude=CVS -cf - . | gnutar -C $(SRCROOT) -xf -
+
+installhdrs:
+ (cd cups ; $(MAKE) $(MFLAGS) installhdrs) || exit 1;\
+ (cd filter ; $(MAKE) $(MFLAGS) installhdrs) || exit 1;
+
+
+#
+# Run the test suite...
+#
+
+check test: all
+ echo Running CUPS test suite...
+ cd test; ./run-stp-tests.sh
+
+
+#
+# Make software distributions using EPM (http://www.easysw.com/epm)...
+#
+
+EPMFLAGS = -v
+
+aix:
+ epm $(EPMFLAGS) -f aix cups
+
+bsd:
+ epm $(EPMFLAGS) -f bsd cups
+
+epm:
+ epm $(EPMFLAGS) cups
+
+rpm:
+ epm $(EPMFLAGS) -f rpm cups
+
+deb:
+ epm $(EPMFLAGS) -f deb cups
+
+depot:
+ epm $(EPMFLAGS) -f depot cups
+
+pkg:
+ epm $(EPMFLAGS) -f pkg cups
+
+tardist:
+ epm $(EPMFLAGS) -f tardist cups
+
+#
+# End of "$Id$".
+#
diff --git a/README.txt b/README.txt
new file mode 100644
index 000000000..302cd8dec
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,278 @@
+README - CUPS v1.1.22 - 10/29/2004
+----------------------------------
+
+Looking for compile instructions? Read the file "INSTALL.txt"
+instead...
+
+**** IF YOU HAVE A NON-POSTSCRIPT PRINTER, YOU WILL ALSO ****
+**** NEED TO INSTALL ESP GHOSTSCRIPT OR A PATCHED VERSION ****
+**** OF THE STANDARD GHOSTSCRIPT RELEASES. ****
+
+
+INTRODUCTION
+
+CUPS provides a portable printing layer for UNIX(r)-based
+operating systems. It has been developed by Easy Software
+Products to promote a standard printing solution for all UNIX
+vendors and users. CUPS provides the System V and Berkeley
+command-line interfaces.
+
+CUPS uses the Internet Printing Protocol ("IPP") as the basis
+for managing print jobs and queues. The Line Printer Daemon
+("LPD") Server Message Block ("SMB"), and AppSocket (a.k.a.
+JetDirect) protocols are also supported with reduced
+functionality. CUPS adds network printer browsing and
+PostScript Printer Description ("PPD") based printing options to
+support real-world printing under UNIX.
+
+CUPS includes an image file RIP that supports printing of image
+files to non-PostScript printers. A customized version of GNU
+Ghostscript 7.05 for CUPS called ESP Ghostscript is available
+separately to support printing of PostScript files within the
+CUPS driver framework. Sample drivers for Dymo, EPSON, HP, and
+OKIDATA printers are included that use these filters.
+
+Drivers for thousands of printers are provided with our ESP
+Print Pro software, available at:
+
+ http://www.easysw.com/printpro
+
+CUPS is licensed under the GNU General Public License and GNU
+Library General Public License. Please contact Easy Software
+Products for commercial support and "binary distribution"
+rights.
+
+
+SYSTEM REQUIREMENTS
+
+Binary distributions require a minimum of 10MB of free disk
+space. We do not recommend using CUPS on a workstation with less
+than 32MB of RAM or a PC with less than 16MB of RAM.
+
+If you are installing from source you'll need ANSI-compliant C
+and C++ compilers and optionally one or more image file support
+libraries. Complete source installation instructions can be
+found in the file "INSTALL.txt".
+
+
+SOFTWARE REQUIREMENTS
+
+The following operating system software is required to install
+one of the binary distributions from Easy Software Products:
+
+ - AIX 4.3 or higher
+ - HP-UX 11.00 or higher
+ - IRIX 6.5 or higher
+ - Linux 2.4 with glibc 2.2 or higher
+ - Solaris 7 or higher (SPARC or Intel)
+
+
+INSTALLING "PORTABLE" CUPS DISTRIBUTIONS
+
+We are currently distributing "portable" CUPS binary
+distributions in TAR format with installation and removal
+scripts generated by our ESP Package Manager (EPM) software,
+which is available from:
+
+ http://www.easysw.com/epm
+
+WARNING: Installing CUPS will overwrite your existing printing
+system. Backup files are made by the installation script and
+restored by the removal script, so if you experience problems
+you should be able to remove the CUPS software to restore your
+previous configuration. However, Easy Software Products makes
+no warranty for this and will not be liable for any lost
+revenues, etc.
+
+To install the CUPS software you will need to be logged in as
+root (doing an "su" is good enough). Once you are the root
+user, run the installation script with:
+
+ ./cups.install ENTER
+
+After asking you a few yes/no questions the CUPS software will
+be installed and the scheduler will be started automatically.
+
+
+INSTALLING HOST-SPECIFIC (RPM, DEBIAN, ETC.) DISTRIBUTIONS
+
+The host-specific distributions use the operating system
+software installation tools. To install a host-specific
+distribution please consult the CUPS Software Administrators
+Manual or your operating system documentation.
+
+
+READING THE DOCUMENTATION
+
+Once you have installed the software you can access the
+documentation (and a bunch of other stuff) on-line at:
+
+ http://localhost:631
+
+If you're having trouble getting that far, the documentation is
+located in the "/usr/share/doc/cups" directory in the binary
+distributions, and under the "doc" directory in the source
+archives.
+
+Please read the documentation before asking questions.
+
+
+GETTING SUPPORT AND OTHER RESOURCES
+
+If you have problems, READ THE DOCUMENTATION FIRST!
+
+You can subscribe to the CUPS mailing list by sending a message
+containing "subscribe cups" to majordomo@cups.org. This list is
+provided to discuss problems, questions, and improvements to the
+CUPS software. New releases of CUPS are announced to this list
+as well.
+
+Commercial support (with a guaranteed response time) is
+available from Easy Software Products. For more information
+see:
+
+ http://www.easysw.com/cups
+
+See the CUPS web site at "http://www.cups.org" for other site
+links.
+
+
+SETTING UP PRINTER QUEUES USING YOUR WEB BROWSER
+
+CUPS 1.1 includes a new web-based administration tool that
+allows you to manage printers, classes, and jobs on your
+server. To access the printer administration tools open the
+following URL in your browser:
+
+ http://localhost:631/admin
+
+You will be asked for the administration password (root or any
+other user in the sys/system/root group on your system) and then
+shown a menu of available functions.
+
+DO NOT use the hostname for your machine - it will not work with
+the default CUPS configuration. To enable administration access
+on other addresses, consult the CUPS Software Administrators
+Manual.
+
+
+SETTING UP PRINTER QUEUES FROM THE COMMAND-LINE
+
+CUPS works best with PPD (PostScript Printer Description)
+files. In a pinch you can also use System V style printer
+interface scripts.
+
+Six sample PPD files are provided with this distribution that
+utilize the PostScript and image file RIPs and the sample EPSON
+and HP printer drivers. To add the sample DeskJet driver to the
+system for a printer connected to the parallel port, use one of
+the following commands:
+
+ HP-UX:
+
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/c2t0d0_lp -E
+
+ IRIX:
+
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/plp -E
+
+ Linux:
+
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp0 -E
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp1 -E
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/lp2 -E
+
+ Solaris:
+
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/bpp0 -E
+ /usr/lib/lpadmin -p DeskJet -m deskjet.ppd -v parallel:/dev/ecpp0 -E
+
+Similarly, for the other sample drivers you can use:
+
+ Driver PPD File
+ ----------------------------- ------------
+ Dymo Label Printers dymo.ppd
+ EPSON Stylus Color Series stcolor.ppd
+ EPSON Stylus Photo Series stphoto.ppd
+ EPSON Stylus New Color Series stcolor2.ppd
+ EPSON Stylus New Photo Series stphoto2.ppd
+ EPSON 9-pin Series epson9.ppd
+ EPSON 24-pin Series epson24.ppd
+ HP DeskJet Series deskjet.ppd
+ HP New DeskJet Series deskjet2.ppd
+ HP LaserJet Series laserjet.ppd
+ OKIDATA 9-Pin Series okidata9.ppd
+ OKIDATA 24-Pin Series okidat24.ppd
+
+These sample drivers provide basic printing capabilities, but
+generally do not exercise the full potential of the printers or
+CUPS. For commercial printer drivers check out our ESP Print
+Pro software at:
+
+ http://www.easysw.com/printpro
+
+
+PRINTING FILES
+
+CUPS provides both the System V "lp" and Berkeley "lpr" commands
+for printing:
+
+ lp filename
+ lpr filename
+
+Both the "lp" and "lpr" commands support printing options for
+the driver:
+
+ lp -omedia=A4 -oresolution=600dpi filename
+ lpr -omedia=A4 -oresolution=600dpi filename
+
+CUPS recognizes many types of images files as well as PDF,
+PostScript, HP-GL/2, and text files, so you can print those
+files directly rather than through an application.
+
+If you have an application that generates output specifically
+for your printer then you need to use the "-oraw" or "-l"
+options:
+
+ lp -oraw filename
+ lpr -l filename
+
+This will prevent the filters from misinterpreting your print
+file.
+
+
+LEGAL STUFF
+
+CUPS is Copyright 1993-2004 by Easy Software Products. CUPS,
+the CUPS logo, and the Common UNIX Printing System are the
+trademark property of Easy Software Products.
+
+The MD5 Digest code is Copyright 1999 Aladdin Enterprises.
+
+The PDF filter (pdftops) is based on the Xpdf software,
+Copyright 1996-2002 by Derek B. Noonburg.
+
+This software is based in part on the work of the Independent
+JPEG Group.
+
+CUPS is provided under the terms of the GNU General Public
+License and GNU Library General Public License. This program is
+distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the "LICENSE.html",
+"LICENSE.txt", or "cups.license" files for more information.
+
+For commercial licensing information, please contact:
+
+ Attn: CUPS Licensing Information
+ Easy Software Products
+ 44141 Airport View Drive, Suite 204
+ Hollywood, Maryland 20636-3111 USA
+
+ Voice: +1.301.373.9600
+ Email: cups-info@cups.org
+ WWW: http://www.cups.org
+
+Note that commercial licensors may also require a license from
+Derek B. Noonburg who developed the Xpdf software used to print
+PDF files.
diff --git a/README_fr.txt b/README_fr.txt
new file mode 100644
index 000000000..64a2f11b2
--- /dev/null
+++ b/README_fr.txt
@@ -0,0 +1,19 @@
+README_fr - CUPS v1.1.19 - 04/08/2003
+-------------------------------------
+
+Vous cherchez des instructions d'installation ? Lisez le fichier
+INSTALL.txt (anglais) et/ou reportez vous au "Manuel de
+l'administrateur" (en français) situé dans le sous-répertoire
+"doc/fr"
+
+Vous trouverez deux autres manuels en français dans ce
+sous-répertoire :
+
+ - Aperçu de CUPS
+ - Manuel de l'utilisateur
+
+Une fois CUPS installé, si vous configurez votre navigateur
+"web" pour que la langue de base soit le français, vous
+disposerez également d'une interface "web" en français pour
+l'administration et d'utilistation de CUPS.
+
diff --git a/backend/.cvsignore b/backend/.cvsignore
new file mode 100644
index 000000000..5a2ee85c3
--- /dev/null
+++ b/backend/.cvsignore
@@ -0,0 +1,8 @@
+betest
+ipp
+lpd
+parallel
+scsi
+serial
+socket
+usb
diff --git a/backend/Dependencies b/backend/Dependencies
new file mode 100644
index 000000000..70b331e29
--- /dev/null
+++ b/backend/Dependencies
@@ -0,0 +1,17 @@
+# DO NOT DELETE
+
+betest.o: ../cups/string.h ../config.h
+ipp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+ipp.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
+lpd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpd.o: ../cups/ppd.h ../cups/string.h ../config.h
+parallel.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+parallel.o: ../cups/ppd.h ../cups/string.h ../config.h
+scsi.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+scsi.o: ../cups/ppd.h ../cups/string.h ../config.h
+serial.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+serial.o: ../cups/ppd.h ../cups/string.h ../config.h
+socket.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+socket.o: ../cups/ppd.h ../cups/string.h ../config.h
+usb.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+usb.o: ../cups/ppd.h ../cups/string.h ../config.h
diff --git a/backend/Makefile b/backend/Makefile
new file mode 100644
index 000000000..0f09abb1f
--- /dev/null
+++ b/backend/Makefile
@@ -0,0 +1,156 @@
+#
+# "$Id$"
+#
+# Backend makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+# This file is subject to the Apple OS-Developed Software exception.
+#
+
+include ../Makedefs
+
+BACKENDS = ipp lpd parallel scsi serial socket usb
+TARGETS = betest $(BACKENDS)
+OBJS = betest.o ipp.o lpd.o parallel.o scsi.o serial.o socket.o usb.o
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS) http
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install: all
+ $(INSTALL_DIR) $(SERVERBIN)/backend
+ for file in $(BACKENDS); do \
+ $(INSTALL_BIN) $$file $(SERVERBIN)/backend; \
+ done
+ $(RM) $(SERVERBIN)/backend/http
+ $(LN) ipp $(SERVERBIN)/backend/http
+
+
+#
+# betest
+#
+
+betest: betest.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o betest betest.o $(LIBS)
+
+
+#
+# ipp
+#
+
+ipp: ipp.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o ipp ipp.o $(LIBS)
+ $(RM) http
+ $(LN) ipp http
+
+
+#
+# lpd
+#
+
+lpd: lpd.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpd lpd.o $(LIBS)
+
+
+#
+# parallel
+#
+
+parallel: parallel.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o parallel parallel.o $(LIBS)
+
+
+#
+# scsi
+#
+
+scsi: scsi.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o scsi scsi.o $(LIBS)
+
+scsi.o: scsi.c scsi-irix.c scsi-linux.c
+
+
+#
+# serial
+#
+
+serial: serial.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o serial serial.o $(BACKLIBS) $(LIBS)
+
+
+#
+# socket
+#
+
+socket: socket.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o socket socket.o $(LIBS)
+
+
+#
+# usb
+#
+
+usb: usb.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o usb usb.o $(BACKLIBS) $(LIBS)
+usb.o: usb.c usb-darwin.c usb-unix.c
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/backend/betest.c b/backend/betest.c
new file mode 100644
index 000000000..68594e48e
--- /dev/null
+++ b/backend/betest.c
@@ -0,0 +1,87 @@
+/*
+ * "$Id$"
+ *
+ * Backend test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Run the named backend.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/string.h>
+#include <unistd.h>
+
+
+/*
+ * 'main()' - Run the named backend.
+ *
+ * Usage:
+ *
+ * betest device-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (7 or 8) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char backend[255]; /* Method in URI */
+
+
+ if (argc < 7 || argc > 8)
+ {
+ fputs("Usage: betest device-uri job-id user title copies options [file]\n",
+ stderr);
+ return (1);
+ }
+
+ /*
+ * Extract the method from the device-uri - that's the program we want to
+ * execute.
+ */
+
+ if (sscanf(argv[1], "%254[^:]", backend) != 1)
+ {
+ fputs("betest: Bad device-uri - no colon!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Execute and return
+ */
+
+ execl(backend, argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7],
+ NULL);
+
+ return (1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/ipp.c b/backend/ipp.c
new file mode 100644
index 000000000..97d9ad019
--- /dev/null
+++ b/backend/ipp.c
@@ -0,0 +1,1383 @@
+/*
+ * "$Id$"
+ *
+ * IPP backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the printer or server.
+ * check_printer_state() - Check the printer state...
+ * password_cb() - Disable the password prompt for
+ * cupsDoFileRequest().
+ * report_printer_state() - Report the printer state.
+ * run_pictwps_filter() - Convert PICT files to PostScript when printing
+ * remotely.
+ * sigterm_handler() - Handle 'terminate' signals that stop the backend.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <cups/http-private.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/string.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+
+/*
+ * Globals...
+ */
+
+static char *password = NULL; /* Password for device URI */
+#ifdef __APPLE__
+static char pstmpname[1024] = ""; /* Temporary PostScript file name */
+#endif /* __APPLE__ */
+static char tmpfilename[1024] = ""; /* Temporary spool file name */
+
+
+/*
+ * Local functions...
+ */
+
+void check_printer_state(http_t *http, cups_lang_t *language,
+ const char *charset, const char *uri, /* I - Printer URI */
+ const char *resource, const char *user,
+ int version);
+const char *password_cb(const char *);
+int report_printer_state(ipp_t *ipp);
+
+#ifdef __APPLE__
+int run_pictwps_filter(char **argv, const char *filename);
+#endif /* __APPLE__ */
+static void sigterm_handler(int sig);
+
+
+/*
+ * 'main()' - Send a file to the printer or server.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ int num_options; /* Number of printer options */
+ cups_option_t *options; /* Printer options */
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info */
+ resource[1024], /* Resource info (printer name) */
+ *optptr, /* Pointer to URI options */
+ name[255], /* Name of option */
+ value[255], /* Value of option */
+ *ptr; /* Pointer into name or value */
+ char *filename; /* File to print */
+ int port; /* Port number (not used) */
+ char uri[HTTP_MAX_URI];/* Updated URI without user/pass */
+ ipp_status_t ipp_status; /* Status of IPP request */
+ http_t *http; /* HTTP connection */
+ ipp_t *request, /* IPP request */
+ *response, /* IPP response */
+ *supported; /* get-printer-attributes response */
+ int waitjob, /* Wait for job complete? */
+ waitprinter; /* Wait for printer ready? */
+ ipp_attribute_t *job_id_attr; /* job-id attribute */
+ int job_id; /* job-id value */
+ ipp_attribute_t *job_sheets; /* job-media-sheets-completed attribute */
+ ipp_attribute_t *job_state; /* job-state attribute */
+ ipp_attribute_t *copies_sup; /* copies-supported attribute */
+ ipp_attribute_t *charset_sup; /* charset-supported attribute */
+ ipp_attribute_t *format_sup; /* document-format-supported attribute */
+ ipp_attribute_t *printer_state;
+ /* printer-state attribute */
+ ipp_attribute_t *printer_accepting;
+ /* printer-is-accepting-jobs attribute */
+ const char *charset; /* Character set to use */
+ cups_lang_t *language; /* Default language */
+ int copies; /* Number of copies remaining */
+ const char *content_type; /* CONTENT_TYPE environment variable */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+ int version; /* IPP version */
+ int reasons; /* Number of printer-state-reasons shown */
+ static const char * const pattrs[] =
+ { /* Printer attributes we want */
+ "copies-supported",
+ "charset-supported",
+ "document-format-supported",
+ "printer-is-accepting-jobs",
+ "printer-state",
+ "printer-state-reasons",
+ };
+ static const char * const jattrs[] =
+ { /* Job attributes we want */
+ "job-media-sheets-completed",
+ "job-state"
+ };
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE and catch SIGTERM signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+ sigset(SIGTERM, sigterm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGTERM);
+ action.sa_handler = sigterm_handler;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGTERM, sigterm_handler);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ char *s;
+
+ if ((s = strrchr(argv[0], '/')) != NULL)
+ s ++;
+ else
+ s = argv[0];
+
+ printf("network %s \"Unknown\" \"Internet Printing Protocol (%s)\"\n", s, s);
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
+ argv[0]);
+ return (1);
+ }
+
+ /*
+ * Get the content type...
+ */
+
+ if (argc > 6)
+ content_type = getenv("CONTENT_TYPE");
+ else
+ content_type = "application/vnd.cups-raw";
+
+ if (content_type == NULL)
+ content_type = "application/octet-stream";
+
+ /*
+ * Extract the hostname and printer name from the URI...
+ */
+
+ if (getenv("DEVICE_URI") != NULL)
+ /* authentication information is only available in the env var */
+ httpSeparate(getenv("DEVICE_URI"), method, username, hostname, &port,
+ resource);
+ else if (strchr(argv[0], ':') != NULL)
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+ else
+ {
+ fputs("ERROR: Missing device URI on command-line and no DEVICE_URI environment variable!\n",
+ stderr);
+ return (1);
+ }
+
+ if (!strcmp(method, "https"))
+ cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, copy stdin to a temporary file and print the temporary
+ * file.
+ */
+
+ if (argc == 6)
+ {
+ /*
+ * Copy stdin to a temporary file...
+ */
+
+ int fd; /* Temporary file */
+ char buffer[8192]; /* Buffer for copying */
+ int bytes; /* Number of bytes read */
+
+
+ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
+ {
+ perror("ERROR: unable to create temporary file");
+ return (1);
+ }
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ if (write(fd, buffer, bytes) < bytes)
+ {
+ perror("ERROR: unable to write to temporary file");
+ close(fd);
+ unlink(tmpfilename);
+ return (1);
+ }
+
+ close(fd);
+ filename = tmpfilename;
+ }
+ else
+ filename = argv[6];
+
+ /*
+ * See if there are any options...
+ */
+
+ version = 1;
+ waitjob = 1;
+ waitprinter = 1;
+
+ if ((optptr = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the optptr...
+ */
+
+ *optptr++ = '\0';
+
+ /*
+ * Then parse the optptr...
+ */
+
+ while (*optptr)
+ {
+ /*
+ * Get the name...
+ */
+
+ for (ptr = name; *optptr && *optptr != '=';)
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = *optptr++;
+ *ptr = '\0';
+
+ if (*optptr == '=')
+ {
+ /*
+ * Get the value...
+ */
+
+ optptr ++;
+
+ for (ptr = value; *optptr && *optptr != '+';)
+ if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = *optptr++;
+ *ptr = '\0';
+
+ if (*optptr == '+')
+ optptr ++;
+ }
+ else
+ value[0] = '\0';
+
+ /*
+ * Process the option...
+ */
+
+ if (!strcasecmp(name, "waitjob"))
+ {
+ /*
+ * Wait for job completion?
+ */
+
+ waitjob = !strcasecmp(value, "on") ||
+ !strcasecmp(value, "yes") ||
+ !strcasecmp(value, "true");
+ }
+ else if (!strcasecmp(name, "waitprinter"))
+ {
+ /*
+ * Wait for printer idle?
+ */
+
+ waitprinter = !strcasecmp(value, "on") ||
+ !strcasecmp(value, "yes") ||
+ !strcasecmp(value, "true");
+ }
+ else if (!strcasecmp(name, "encryption"))
+ {
+ /*
+ * Enable/disable encryption?
+ */
+
+ if (!strcasecmp(value, "always"))
+ cupsSetEncryption(HTTP_ENCRYPT_ALWAYS);
+ else if (!strcasecmp(value, "required"))
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+ else if (!strcasecmp(value, "never"))
+ cupsSetEncryption(HTTP_ENCRYPT_NEVER);
+ else if (!strcasecmp(value, "ifrequested"))
+ cupsSetEncryption(HTTP_ENCRYPT_IF_REQUESTED);
+ else
+ {
+ fprintf(stderr, "ERROR: Unknown encryption option value \"%s\"!\n",
+ value);
+ }
+ }
+ else if (!strcasecmp(name, "version"))
+ {
+ if (!strcmp(value, "1.0"))
+ version = 0;
+ else if (!strcmp(value, "1.1"))
+ version = 1;
+ else
+ {
+ fprintf(stderr, "ERROR: Unknown version option value \"%s\"!\n",
+ value);
+ }
+ }
+ else
+ {
+ /*
+ * Unknown option...
+ */
+
+ fprintf(stderr, "ERROR: Unknown option \"%s\" with value \"%s\"!\n",
+ name, value);
+ }
+ }
+ }
+
+ /*
+ * Set the authentication info, if any...
+ */
+
+ cupsSetPasswordCB(password_cb);
+
+ if (username[0])
+ {
+ if ((password = strchr(username, ':')) != NULL)
+ *password++ = '\0';
+
+ cupsSetUser(username);
+ }
+
+ /*
+ * Try connecting to the remote server...
+ */
+
+ do
+ {
+ fprintf(stderr, "INFO: Connecting to %s on port %d...\n", hostname, port);
+
+ if ((http = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL)
+ {
+ if (getenv("CLASS") != NULL)
+ {
+ /*
+ * If the CLASS environment variable is set, the job was submitted
+ * to a class and not to a specific queue. In this case, we want
+ * to abort immediately so that the job can be requeued on the next
+ * available printer in the class.
+ */
+
+ fprintf(stderr, "INFO: Unable to connect to %s, queuing on next printer in class...\n",
+ hostname);
+
+ if (argc == 6 || strcmp(filename, argv[6]))
+ unlink(filename);
+
+ /*
+ * Sleep 5 seconds to keep the job from requeuing too rapidly...
+ */
+
+ sleep(5);
+
+ return (1);
+ }
+
+ if (errno == ECONNREFUSED || errno == EHOSTDOWN ||
+ errno == EHOSTUNREACH)
+ {
+ fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...\n",
+ hostname);
+ sleep(30);
+ }
+ else if (h_errno)
+ {
+ fprintf(stderr, "INFO: Unable to lookup host \'%s\' - %s\n",
+ hostname, hstrerror(h_errno));
+ sleep(30);
+ }
+ else
+ {
+ perror("ERROR: Unable to connect to IPP host");
+ sleep(30);
+ }
+ }
+ }
+ while (http == NULL);
+
+ fprintf(stderr, "INFO: Connected to %s...\n", hostname);
+
+ /*
+ * Build a URI for the printer and fill the standard IPP attributes for
+ * an IPP_PRINT_FILE request. We can't use the URI in argv[0] because it
+ * might contain username:password information...
+ */
+
+ snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, hostname, port, resource);
+
+ /*
+ * First validate the destination and see if the device supports multiple
+ * copies. We have to do this because some IPP servers (e.g. HP JetDirect)
+ * don't support the copies attribute...
+ */
+
+ language = cupsLangDefault();
+ charset_sup = NULL;
+ copies_sup = NULL;
+ format_sup = NULL;
+ supported = NULL;
+
+ do
+ {
+ /*
+ * Build the IPP request...
+ */
+
+ request = ippNew();
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, "utf-8");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "en");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request...
+ */
+
+ fputs("DEBUG: Getting supported attributes...\n", stderr);
+
+ if ((supported = cupsDoRequest(http, request, resource)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = supported->request.status.status_code;
+
+ if (ipp_status > IPP_OK_CONFLICT)
+ {
+ if (ipp_status == IPP_PRINTER_BUSY ||
+ ipp_status == IPP_SERVICE_UNAVAILABLE)
+ {
+ fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr);
+ report_printer_state(supported);
+ sleep(10);
+ }
+ else if ((ipp_status == IPP_BAD_REQUEST ||
+ ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1)
+ {
+ /*
+ * Switch to IPP/1.0...
+ */
+
+ fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr);
+ version = 0;
+ httpReconnect(http);
+ }
+ else if (ipp_status == IPP_NOT_FOUND)
+ {
+ fputs("ERROR: Destination printer does not exist!\n", stderr);
+
+ if (supported)
+ ippDelete(supported);
+
+ return (1);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Unable to get printer status (%s)!\n",
+ ippErrorString(ipp_status));
+ sleep(10);
+ }
+
+ if (supported)
+ ippDelete(supported);
+
+ continue;
+ }
+ else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
+ IPP_TAG_RANGE)) != NULL)
+ {
+ /*
+ * Has the "copies-supported" attribute - does it have an upper
+ * bound > 1?
+ */
+
+ if (copies_sup->values[0].range.upper <= 1)
+ copies_sup = NULL; /* No */
+ }
+
+ charset_sup = ippFindAttribute(supported, "charset-supported",
+ IPP_TAG_CHARSET);
+ format_sup = ippFindAttribute(supported, "document-format-supported",
+ IPP_TAG_MIMETYPE);
+
+ if (format_sup)
+ {
+ fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
+ format_sup->num_values);
+ for (i = 0; i < format_sup->num_values; i ++)
+ fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
+ format_sup->values[i].string.text);
+ }
+
+ report_printer_state(supported);
+ }
+ while (ipp_status > IPP_OK_CONFLICT);
+
+ /*
+ * See if the printer is accepting jobs and is not stopped; if either
+ * condition is true and we are printing to a class, requeue the job...
+ */
+
+ if (getenv("CLASS") != NULL)
+ {
+ printer_state = ippFindAttribute(supported, "printer-state",
+ IPP_TAG_ENUM);
+ printer_accepting = ippFindAttribute(supported, "printer-is-accepting-jobs",
+ IPP_TAG_BOOLEAN);
+
+ if (printer_state == NULL ||
+ (printer_state->values[0].integer > IPP_PRINTER_PROCESSING && waitprinter) ||
+ printer_accepting == NULL ||
+ !printer_accepting->values[0].boolean)
+ {
+ /*
+ * If the CLASS environment variable is set, the job was submitted
+ * to a class and not to a specific queue. In this case, we want
+ * to abort immediately so that the job can be requeued on the next
+ * available printer in the class.
+ */
+
+ fprintf(stderr, "INFO: Unable to queue job on %s, queuing on next printer in class...\n",
+ hostname);
+
+ ippDelete(supported);
+ httpClose(http);
+
+ if (argc == 6 || strcmp(filename, argv[6]))
+ unlink(filename);
+
+ /*
+ * Sleep 5 seconds to keep the job from requeuing too rapidly...
+ */
+
+ sleep(5);
+
+ return (1);
+ }
+ }
+
+ /*
+ * See if the printer supports multiple copies...
+ */
+
+ if (copies_sup || argc < 7)
+ copies = 1;
+ else
+ copies = atoi(argv[4]);
+
+ /*
+ * Figure out the character set to use...
+ */
+
+ charset = language ? cupsLangEncoding(language) : "us-ascii";
+
+ if (charset_sup)
+ {
+ /*
+ * See if IPP server supports the requested character set...
+ */
+
+ for (i = 0; i < charset_sup->num_values; i ++)
+ if (strcasecmp(charset, charset_sup->values[i].string.text) == 0)
+ break;
+
+ /*
+ * If not, choose us-ascii or utf-8...
+ */
+
+ if (i >= charset_sup->num_values)
+ {
+ /*
+ * See if us-ascii is supported...
+ */
+
+ for (i = 0; i < charset_sup->num_values; i ++)
+ if (strcasecmp("us-ascii", charset_sup->values[i].string.text) == 0)
+ break;
+
+ if (i < charset_sup->num_values)
+ charset = "us-ascii";
+ else
+ charset = "utf-8";
+ }
+ }
+
+ /*
+ * Then issue the print-job request...
+ */
+
+ reasons = 0;
+
+ while (copies > 0)
+ {
+ /*
+ * Build the IPP request...
+ */
+
+ request = ippNew();
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, charset);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "en");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri);
+
+ if (argv[2][0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, argv[2]);
+
+ fprintf(stderr, "DEBUG: requesting-user-name = \"%s\"\n", argv[2]);
+
+ if (argv[3][0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+ argv[3]);
+
+ fprintf(stderr, "DEBUG: job-name = \"%s\"\n", argv[3]);
+
+ /*
+ * Handle options on the command-line...
+ */
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+#ifdef __APPLE__
+ if (content_type != NULL && strcasecmp(content_type, "application/pictwps") == 0)
+ {
+ if (format_sup != NULL)
+ {
+ for (i = 0; i < format_sup->num_values; i ++)
+ if (strcasecmp(content_type, format_sup->values[i].string.text) == 0)
+ break;
+ }
+
+ if (format_sup == NULL || i >= format_sup->num_values)
+ {
+ /*
+ * Remote doesn't support "application/pictwps" (i.e. it's not MacOS X)
+ * so convert the document to PostScript...
+ */
+
+ if (run_pictwps_filter(argv, filename))
+ return (1);
+
+ filename = pstmpname;
+
+ /*
+ * Change the MIME type to application/postscript...
+ */
+
+ content_type = "application/postscript";
+ }
+ }
+#endif /* __APPLE__ */
+
+ if (content_type != NULL && format_sup != NULL)
+ {
+ for (i = 0; i < format_sup->num_values; i ++)
+ if (strcasecmp(content_type, format_sup->values[i].string.text) == 0)
+ break;
+
+ if (i < format_sup->num_values)
+ num_options = cupsAddOption("document-format", content_type,
+ num_options, &options);
+ }
+
+ if (copies_sup)
+ {
+ /*
+ * Only send options if the destination printer supports the copies
+ * attribute. This is a hack for the HP JetDirect implementation of
+ * IPP, which does not accept extension attributes and incorrectly
+ * reports a client-error-bad-request error instead of the
+ * successful-ok-unsupported-attributes status. In short, at least
+ * some HP implementations of IPP are non-compliant.
+ */
+
+ cupsEncodeOptions(request, num_options, options);
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies",
+ atoi(argv[4]));
+ }
+
+ cupsFreeOptions(num_options, options);
+
+ /*
+ * If copies aren't supported, then we are likely dealing with an HP
+ * JetDirect. The HP IPP implementation seems to close the connection
+ * after every request (that is, it does *not* implement HTTP Keep-
+ * Alive, which is REQUIRED by HTTP/1.1...
+ */
+
+ if (!copies_sup)
+ httpReconnect(http);
+
+ /*
+ * Do the request...
+ */
+
+ if ((response = cupsDoFileRequest(http, request, resource, filename)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = response->request.status.status_code;
+
+ if (ipp_status > IPP_OK_CONFLICT)
+ {
+ job_id = 0;
+
+ if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
+ ipp_status == IPP_PRINTER_BUSY)
+ {
+ fputs("INFO: Printer is busy; retrying print job...\n", stderr);
+ sleep(10);
+ }
+ else
+ fprintf(stderr, "ERROR: Print file was not accepted (%s)!\n",
+ ippErrorString(ipp_status));
+ }
+ else if ((job_id_attr = ippFindAttribute(response, "job-id",
+ IPP_TAG_INTEGER)) == NULL)
+ {
+ fputs("NOTICE: Print file accepted - job ID unknown.\n", stderr);
+ job_id = 0;
+ }
+ else
+ {
+ job_id = job_id_attr->values[0].integer;
+ fprintf(stderr, "NOTICE: Print file accepted - job ID %d.\n", job_id);
+ }
+
+ if (response)
+ ippDelete(response);
+
+ if (ipp_status <= IPP_OK_CONFLICT && argc > 6)
+ {
+ fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
+ copies --;
+ }
+ else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+ ipp_status != IPP_PRINTER_BUSY)
+ break;
+
+ /*
+ * Wait for the job to complete...
+ */
+
+ if (!job_id || !waitjob)
+ continue;
+
+ fputs("INFO: Waiting for job to complete...\n", stderr);
+
+ for (;;)
+ {
+ /*
+ * Build an IPP_GET_JOB_ATTRIBUTES request...
+ */
+
+ request = ippNew();
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = IPP_GET_JOB_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, charset);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "en");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+ job_id);
+
+ if (argv[2][0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, argv[2]);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]),
+ NULL, jattrs);
+
+ /*
+ * Do the request...
+ */
+
+ if (!copies_sup)
+ httpReconnect(http);
+
+ if ((response = cupsDoRequest(http, request, resource)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = response->request.status.status_code;
+
+ if (ipp_status == IPP_NOT_FOUND)
+ {
+ /*
+ * Job has gone away and/or the server has no job history...
+ */
+
+ ippDelete(response);
+
+ ipp_status = IPP_OK;
+ break;
+ }
+
+ if (ipp_status > IPP_OK_CONFLICT)
+ {
+ if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+ ipp_status != IPP_PRINTER_BUSY)
+ {
+ if (response)
+ ippDelete(response);
+
+ fprintf(stderr, "ERROR: Unable to get job %d attributes (%s)!\n",
+ job_id, ippErrorString(ipp_status));
+ break;
+ }
+ }
+
+ if (response != NULL)
+ {
+ if ((job_sheets = ippFindAttribute(response, "job-media-sheets-completed",
+ IPP_TAG_INTEGER)) != NULL)
+ fprintf(stderr, "PAGE: total %d\n", job_sheets->values[0].integer);
+
+ if ((job_state = ippFindAttribute(response, "job-state",
+ IPP_TAG_ENUM)) != NULL)
+ {
+ /*
+ * Stop polling if the job is finished or pending-held...
+ */
+
+ if (job_state->values[0].integer > IPP_JOB_PROCESSING ||
+ job_state->values[0].integer == IPP_JOB_HELD)
+ {
+ ippDelete(response);
+ break;
+ }
+ }
+ }
+
+ if (response)
+ ippDelete(response);
+
+ /*
+ * Check the printer state and report it if necessary...
+ */
+
+/* if (!copies_sup)
+ httpReconnect(http);*/
+
+ check_printer_state(http, language, charset, uri, resource, argv[2],
+ version);
+
+ /*
+ * Wait 10 seconds before polling again...
+ */
+
+ sleep(10);
+ }
+ }
+
+ /*
+ * Check the printer state and report it if necessary...
+ */
+
+/* if (!copies_sup)
+ httpReconnect(http);*/
+
+ check_printer_state(http, language, charset, uri, resource, argv[2], version);
+
+ /*
+ * Free memory...
+ */
+
+ httpClose(http);
+
+ if (supported)
+ ippDelete(supported);
+
+ /*
+ * Remove the temporary file(s) if necessary...
+ */
+
+ if (tmpfilename[0])
+ unlink(tmpfilename);
+
+#ifdef __APPLE__
+ if (pstmpname[0])
+ unlink(pstmpname);
+#endif /* __APPLE__ */
+
+ /*
+ * Return the queue status...
+ */
+
+ return (ipp_status > IPP_OK_CONFLICT);
+}
+
+
+/*
+ * 'check_printer_state()' - Check the printer state...
+ */
+
+void
+check_printer_state(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language,
+ /* I - Language */
+ const char *charset,
+ /* I - Charset */
+ const char *uri, /* I - Printer URI */
+ const char *resource,
+ /* I - Resource path */
+ const char *user, /* I - Username, if any */
+ int version)/* I - IPP version */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+
+
+ /*
+ * Check on the printer state...
+ */
+
+ request = ippNew();
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, charset);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "en");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ if (user && user[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-state-reasons");
+
+ /*
+ * Do the request...
+ */
+
+ if ((response = cupsDoRequest(http, request, resource)) != NULL)
+ {
+ report_printer_state(response);
+ ippDelete(response);
+ }
+}
+
+
+/*
+ * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
+ */
+
+const char * /* O - Password */
+password_cb(const char *prompt) /* I - Prompt (not used) */
+{
+ (void)prompt;
+
+ return (password);
+}
+
+
+/*
+ * 'report_printer_state()' - Report the printer state.
+ */
+
+int /* O - Number of reasons shown */
+report_printer_state(ipp_t *ipp) /* I - IPP response */
+{
+ int i; /* Looping var */
+ int count; /* Count of reasons shown... */
+ ipp_attribute_t *reasons; /* printer-state-reasons */
+ const char *reason; /* Current reason */
+ const char *message; /* Message to show */
+ char unknown[1024]; /* Unknown message string */
+ const char *prefix; /* Prefix for STATE: line */
+ char state[1024]; /* State string */
+
+
+ if ((reasons = ippFindAttribute(ipp, "printer-state-reasons",
+ IPP_TAG_KEYWORD)) == NULL)
+ return (0);
+
+ state[0] = '\0';
+ prefix = "STATE: ";
+
+ for (i = 0, count = 0; i < reasons->num_values; i ++)
+ {
+ reason = reasons->values[i].string.text;
+
+ strlcat(state, prefix, sizeof(state));
+ strlcat(state, reason, sizeof(state));
+
+ prefix = ",";
+ message = NULL;
+
+ if (strncmp(reason, "media-needed", 12) == 0)
+ message = "Media tray needs to be filled.";
+ else if (strncmp(reason, "media-jam", 9) == 0)
+ message = "Media jam!";
+ else if (strncmp(reason, "moving-to-paused", 16) == 0 ||
+ strncmp(reason, "paused", 6) == 0 ||
+ strncmp(reason, "shutdown", 8) == 0)
+ message = "Printer off-line.";
+ else if (strncmp(reason, "toner-low", 9) == 0)
+ message = "Toner low.";
+ else if (strncmp(reason, "toner-empty", 11) == 0)
+ message = "Out of toner!";
+ else if (strncmp(reason, "cover-open", 10) == 0)
+ message = "Cover open.";
+ else if (strncmp(reason, "interlock-open", 14) == 0)
+ message = "Interlock open.";
+ else if (strncmp(reason, "door-open", 9) == 0)
+ message = "Door open.";
+ else if (strncmp(reason, "input-tray-missing", 18) == 0)
+ message = "Media tray missing!";
+ else if (strncmp(reason, "media-low", 9) == 0)
+ message = "Media tray almost empty.";
+ else if (strncmp(reason, "media-empty", 11) == 0)
+ message = "Media tray empty!";
+ else if (strncmp(reason, "output-tray-missing", 19) == 0)
+ message = "Output tray missing!";
+ else if (strncmp(reason, "output-area-almost-full", 23) == 0)
+ message = "Output bin almost full.";
+ else if (strncmp(reason, "output-area-full", 16) == 0)
+ message = "Output bin full!";
+ else if (strncmp(reason, "marker-supply-low", 17) == 0)
+ message = "Ink/toner almost empty.";
+ else if (strncmp(reason, "marker-supply-empty", 19) == 0)
+ message = "Ink/toner empty!";
+ else if (strncmp(reason, "marker-waste-almost-full", 24) == 0)
+ message = "Ink/toner waste bin almost full.";
+ else if (strncmp(reason, "marker-waste-full", 17) == 0)
+ message = "Ink/toner waste bin full!";
+ else if (strncmp(reason, "fuser-over-temp", 15) == 0)
+ message = "Fuser temperature high!";
+ else if (strncmp(reason, "fuser-under-temp", 16) == 0)
+ message = "Fuser temperature low!";
+ else if (strncmp(reason, "opc-near-eol", 12) == 0)
+ message = "OPC almost at end-of-life.";
+ else if (strncmp(reason, "opc-life-over", 13) == 0)
+ message = "OPC at end-of-life!";
+ else if (strncmp(reason, "developer-low", 13) == 0)
+ message = "Developer almost empty.";
+ else if (strncmp(reason, "developer-empty", 15) == 0)
+ message = "Developer empty!";
+ else if (strstr(reason, "error") != NULL)
+ {
+ message = unknown;
+
+ snprintf(unknown, sizeof(unknown), "Unknown printer error (%s)!",
+ reason);
+ }
+
+ if (message)
+ {
+ count ++;
+ if (strstr(reasons->values[i].string.text, "error"))
+ fprintf(stderr, "ERROR: %s\n", message);
+ else if (strstr(reasons->values[i].string.text, "warning"))
+ fprintf(stderr, "WARNING: %s\n", message);
+ else
+ fprintf(stderr, "INFO: %s\n", message);
+ }
+ }
+
+ fprintf(stderr, "%s\n", state);
+
+ return (count);
+}
+
+
+#ifdef __APPLE__
+/*
+ * 'run_pictwps_filter()' - Convert PICT files to PostScript when printing
+ * remotely.
+ *
+ * This step is required because the PICT format is not documented and
+ * subject to change, so developing a filter for other OS's is infeasible.
+ * Also, fonts required by the PICT file need to be embedded on the
+ * client side (which has the fonts), so we run the filter to get a
+ * PostScript file for printing...
+ */
+
+int /* O - Exit status of filter */
+run_pictwps_filter(char **argv, /* I - Command-line arguments */
+ const char *filename) /* I - Filename */
+{
+ struct stat fileinfo; /* Print file information */
+ const char *ppdfile; /* PPD file for destination printer */
+ int pid; /* Child process ID */
+ int fd; /* Temporary file descriptor */
+ int status; /* Exit status of filter */
+ const char *printer; /* PRINTER env var */
+ static char ppdenv[1024]; /* PPD environment variable */
+
+
+ /*
+ * First get the PPD file for the printer...
+ */
+
+ printer = getenv("PRINTER");
+ if (!printer)
+ {
+ fputs("ERROR: PRINTER environment variable not defined!\n", stderr);
+ return (-1);
+ }
+
+ if ((ppdfile = cupsGetPPD(printer)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to get PPD file for printer \"%s\" - %s.\n",
+ printer, ippErrorString(cupsLastError()));
+ /*return (-1);*/
+ }
+ else
+ {
+ snprintf(ppdenv, sizeof(ppdenv), "PPD=%s", ppdfile);
+ putenv(ppdenv);
+ }
+
+ /*
+ * Then create a temporary file for printing...
+ */
+
+ if ((fd = cupsTempFd(pstmpname, sizeof(pstmpname))) < 0)
+ {
+ fprintf(stderr, "ERROR: Unable to create temporary file - %s.\n",
+ strerror(errno));
+ if (ppdfile)
+ unlink(ppdfile);
+ return (-1);
+ }
+
+ /*
+ * Get the owner of the spool file - it is owned by the user we want to run
+ * as...
+ */
+
+ if (argv[6])
+ stat(argv[6], &fileinfo);
+ else
+ {
+ /*
+ * Use the OSX defaults, as an up-stream filter created the PICT
+ * file...
+ */
+
+ fileinfo.st_uid = 1;
+ fileinfo.st_gid = 80;
+ }
+
+ if (ppdfile)
+ chown(ppdfile, fileinfo.st_uid, fileinfo.st_gid);
+
+ fchown(fd, fileinfo.st_uid, fileinfo.st_gid);
+
+ /*
+ * Finally, run the filter to convert the file...
+ */
+
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child process for pictwpstops... Redirect output of pictwpstops to a
+ * file...
+ */
+
+ close(1);
+ dup(fd);
+ close(fd);
+
+ if (!getuid())
+ {
+ /*
+ * Change to an unpriviledged user...
+ */
+
+ setgid(fileinfo.st_gid);
+ setuid(fileinfo.st_uid);
+ }
+
+ execlp("pictwpstops", printer, argv[1], argv[2], argv[3], argv[4], argv[5],
+ filename, NULL);
+ perror("ERROR: Unable to exec pictwpstops");
+ return (errno);
+ }
+
+ close(fd);
+
+ if (pid < 0)
+ {
+ /*
+ * Error!
+ */
+
+ perror("ERROR: Unable to fork pictwpstops");
+ unlink(filename);
+ if (ppdfile)
+ unlink(ppdfile);
+ return (-1);
+ }
+
+ /*
+ * Now wait for the filter to complete...
+ */
+
+ if (wait(&status) < 0)
+ {
+ perror("ERROR: Unable to wait for pictwpstops");
+ close(fd);
+ unlink(filename);
+ if (ppdfile)
+ unlink(ppdfile);
+ return (-1);
+ }
+
+ if (ppdfile)
+ unlink(ppdfile);
+
+ close(fd);
+
+ if (status)
+ {
+ if (status >= 256)
+ fprintf(stderr, "ERROR: pictwpstops exited with status %d!\n",
+ status / 256);
+ else
+ fprintf(stderr, "ERROR: pictwpstops exited on signal %d!\n",
+ status);
+
+ unlink(filename);
+ return (status);
+ }
+
+ /*
+ * Return with no errors..
+ */
+
+ return (0);
+}
+#endif /* __APPLE__ */
+
+
+/*
+ * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal */
+{
+ (void)sig; /* remove compiler warnings... */
+
+ /*
+ * Remove the temporary file(s) if necessary...
+ */
+
+ if (tmpfilename[0])
+ unlink(tmpfilename);
+
+#ifdef __APPLE__
+ if (pstmpname[0])
+ unlink(pstmpname);
+#endif /* __APPLE__ */
+
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/lpd.c b/backend/lpd.c
new file mode 100644
index 000000000..744804522
--- /dev/null
+++ b/backend/lpd.c
@@ -0,0 +1,1047 @@
+/*
+ * "$Id$"
+ *
+ * Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the printer or server.
+ * lpd_command() - Send an LPR command sequence and wait for a reply.
+ * lpd_queue() - Queue a file using the Line Printer Daemon protocol.
+ * lpd_timeout() - Handle timeout alarms...
+ * lpd_write() - Write a buffer of data to an LPD server.
+ * rresvport() - A simple implementation of rresvport().
+ * sigterm_handler() - Handle 'terminate' signals that stop the backend.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <cups/http-private.h>
+#include <cups/string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#ifdef WIN32
+# include <winsock.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif /* WIN32 */
+
+
+/*
+ * Globals...
+ */
+
+static char tmpfilename[1024] = ""; /* Temporary spool file name */
+
+
+/*
+ * The order for control and data files in LPD requests...
+ */
+
+#define ORDER_CONTROL_DATA 0 /* Control file first, then data */
+#define ORDER_DATA_CONTROL 1 /* Data file first, then control */
+
+
+/*
+ * What to reserve...
+ */
+
+#define RESERVE_NONE 0 /* Don't reserve a priviledged port */
+#define RESERVE_RFC1179 1 /* Reserve port 721-731 */
+#define RESERVE_ANY 2 /* Reserve port 1-1023 */
+
+
+/*
+ * It appears that rresvport() is never declared on most systems...
+ */
+
+extern int rresvport(int *port);
+
+
+/*
+ * Local functions...
+ */
+
+static int lpd_command(int lpd_fd, int timeout, char *format, ...);
+static int lpd_queue(const char *hostname, int port, const char *printer,
+ const char *filename,
+ const char *user, const char *title, int copies,
+ int banner, int format, int order, int reserve,
+ int manual_copies, int timeout);
+static void lpd_timeout(int sig);
+static int lpd_write(int lpd_fd, char *buffer, int length);
+static void sigterm_handler(int sig);
+
+
+/*
+ * 'main()' - Send a file to the printer or server.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info */
+ resource[1024], /* Resource info (printer name) */
+ *options, /* Pointer to options */
+ name[255], /* Name of option */
+ value[255], /* Value of option */
+ *ptr, /* Pointer into name or value */
+ *filename, /* File to print */
+ title[256]; /* Title string */
+ int port; /* Port number */
+ int status; /* Status of LPD job */
+ int banner; /* Print banner page? */
+ int format; /* Print format */
+ int order; /* Order of control/data files */
+ int reserve; /* Reserve priviledged port? */
+ int sanitize_title; /* Sanitize title string? */
+ int manual_copies, /* Do manual copies? */
+ timeout, /* Timeout */
+ copies; /* Number of copies */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE and catch SIGTERM signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+ sigset(SIGTERM, sigterm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGTERM);
+ action.sa_handler = sigterm_handler;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGTERM, sigterm_handler);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\"");
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
+ argv[0]);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, copy stdin to a temporary file and print the temporary
+ * file.
+ */
+
+ if (argc == 6)
+ {
+ /*
+ * Copy stdin to a temporary file...
+ */
+
+ int fd; /* Temporary file */
+ char buffer[8192]; /* Buffer for copying */
+ int bytes; /* Number of bytes read */
+
+
+ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
+ {
+ perror("ERROR: unable to create temporary file");
+ return (1);
+ }
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ if (write(fd, buffer, bytes) < bytes)
+ {
+ perror("ERROR: unable to write to temporary file");
+ close(fd);
+ unlink(tmpfilename);
+ return (1);
+ }
+
+ close(fd);
+ filename = tmpfilename;
+ }
+ else
+ filename = argv[6];
+
+ /*
+ * Extract the hostname and printer name from the URI...
+ */
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ if (!username[0])
+ {
+ /*
+ * If no username is in the device URI, then use the print job user...
+ */
+
+ strlcpy(username, argv[2], sizeof(username));
+ }
+
+ /*
+ * See if there are any options...
+ */
+
+ banner = 0;
+ format = 'l';
+ order = ORDER_CONTROL_DATA;
+ reserve = RESERVE_ANY;
+ manual_copies = 1;
+ timeout = 300;
+ sanitize_title = 1;
+
+#if defined(__APPLE__)
+ /* We want to pass utf-8 characters, not re-map them (3071945) */
+ sanitize_title= 0;
+#endif
+
+ if ((options = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the options...
+ */
+
+ *options++ = '\0';
+
+ /*
+ * Parse options...
+ */
+
+ while (*options)
+ {
+ /*
+ * Get the name...
+ */
+
+ for (ptr = name; *options && *options != '=';)
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = *options++;
+ *ptr = '\0';
+
+ if (*options == '=')
+ {
+ /*
+ * Get the value...
+ */
+
+ options ++;
+
+ for (ptr = value; *options && *options != '+';)
+ if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = *options++;
+ *ptr = '\0';
+
+ if (*options == '+')
+ options ++;
+ }
+ else
+ value[0] = '\0';
+
+ /*
+ * Process the option...
+ */
+
+ if (strcasecmp(name, "banner") == 0)
+ {
+ /*
+ * Set the banner...
+ */
+
+ banner = !value[0] ||
+ strcasecmp(value, "on") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ strcasecmp(value, "true") == 0;
+ }
+ else if (strcasecmp(name, "format") == 0 && value[0])
+ {
+ /*
+ * Set output format...
+ */
+
+ if (strchr("cdfglnoprtv", value[0]) != NULL)
+ format = value[0];
+ else
+ fprintf(stderr, "ERROR: Unknown format character \"%c\"\n", value[0]);
+ }
+ else if (strcasecmp(name, "order") == 0 && value[0])
+ {
+ /*
+ * Set control/data order...
+ */
+
+ if (strcasecmp(value, "control,data") == 0)
+ order = ORDER_CONTROL_DATA;
+ else if (strcasecmp(value, "data,control") == 0)
+ order = ORDER_DATA_CONTROL;
+ else
+ fprintf(stderr, "ERROR: Unknown file order \"%s\"\n", value);
+ }
+ else if (strcasecmp(name, "reserve") == 0)
+ {
+ /*
+ * Set port reservation mode...
+ */
+
+ if (!value[0] ||
+ !strcasecmp(value, "on") ||
+ !strcasecmp(value, "yes") ||
+ !strcasecmp(value, "true") ||
+ !strcasecmp(value, "rfc1179"))
+ reserve = RESERVE_RFC1179;
+ else if (!strcasecmp(value, "any"))
+ reserve = RESERVE_ANY;
+ else
+ reserve = RESERVE_NONE;
+ }
+ else if (strcasecmp(name, "manual_copies") == 0)
+ {
+ /*
+ * Set manual copies...
+ */
+
+ manual_copies = !value[0] ||
+ strcasecmp(value, "on") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ strcasecmp(value, "true") == 0;
+ }
+ else if (strcasecmp(name, "sanitize_title") == 0)
+ {
+ /*
+ * Set sanitize title...
+ */
+
+ sanitize_title = !value[0] ||
+ strcasecmp(value, "on") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ strcasecmp(value, "true") == 0;
+ }
+ else if (strcasecmp(name, "timeout") == 0)
+ {
+ /*
+ * Set the timeout...
+ */
+
+ if (atoi(value) > 0)
+ timeout = atoi(value);
+ }
+ }
+ }
+
+ /*
+ * Sanitize the document title...
+ */
+
+ strlcpy(title, argv[3], sizeof(title));
+
+ if (sanitize_title)
+ {
+ /*
+ * Sanitize the title string so that we don't cause problems on
+ * the remote end...
+ */
+
+ for (ptr = title; *ptr; ptr ++)
+ if (!isalnum(*ptr & 255) && !isspace(*ptr & 255))
+ *ptr = '_';
+ }
+
+ /*
+ * Queue the job...
+ */
+
+ if (argc > 6)
+ {
+ if (manual_copies)
+ {
+ manual_copies = atoi(argv[4]);
+ copies = 1;
+ }
+ else
+ {
+ manual_copies = 1;
+ copies = atoi(argv[4]);
+ }
+
+ status = lpd_queue(hostname, port, resource + 1, filename,
+ username, title, copies,
+ banner, format, order, reserve, manual_copies, timeout);
+
+ if (!status)
+ fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
+ }
+ else
+ status = lpd_queue(hostname, port, resource + 1, filename,
+ username, title, 1,
+ banner, format, order, reserve, 1, timeout);
+
+ /*
+ * Remove the temporary file if necessary...
+ */
+
+ if (tmpfilename[0])
+ unlink(tmpfilename);
+
+ /*
+ * Return the queue status...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
+ */
+
+static int /* O - Status of command */
+lpd_command(int fd, /* I - Socket connection to LPD host */
+ int timeout, /* I - Seconds to wait for a response */
+ char *format, /* I - printf()-style format string */
+ ...) /* I - Additional args as necessary */
+{
+ va_list ap; /* Argument pointer */
+ char buf[1024]; /* Output buffer */
+ int bytes; /* Number of bytes to output */
+ char status; /* Status from command */
+
+
+ /*
+ * Format the string...
+ */
+
+ va_start(ap, format);
+ bytes = vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+
+ fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1);
+
+ /*
+ * Send the command...
+ */
+
+ fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes);
+
+ if (lpd_write(fd, buf, bytes) < bytes)
+ {
+ perror("ERROR: Unable to send LPD command");
+ return (-1);
+ }
+
+ /*
+ * Read back the status from the command and return it...
+ */
+
+ fprintf(stderr, "DEBUG: Reading command status...\n");
+
+ alarm(timeout);
+
+ if (recv(fd, &status, 1, 0) < 1)
+ {
+ fprintf(stderr, "WARNING: Remote host did not respond with command "
+ "status byte after %d seconds!\n", timeout);
+ status = errno;
+ }
+
+ alarm(0);
+
+ fprintf(stderr, "DEBUG: lpd_command returning %d\n", status);
+
+ return (status);
+}
+
+
+/*
+ * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
+ */
+
+static int /* O - Zero on success, non-zero on failure */
+lpd_queue(const char *hostname, /* I - Host to connect to */
+ int port, /* I - Port to connect on */
+ const char *printer, /* I - Printer/queue name */
+ const char *filename, /* I - File to print */
+ const char *user, /* I - Requesting user */
+ const char *title, /* I - Job title */
+ int copies, /* I - Number of copies */
+ int banner, /* I - Print LPD banner? */
+ int format, /* I - Format specifier */
+ int order, /* I - Order of data/control files */
+ int reserve, /* I - Reserve ports? */
+ int manual_copies, /* I - Do copies by hand... */
+ int timeout) /* I - Timeout... */
+{
+ FILE *fp; /* Job file */
+ char localhost[255]; /* Local host name */
+ int error; /* Error number */
+ struct stat filestats; /* File statistics */
+ int lport; /* LPD connection local port */
+ int fd; /* LPD socket */
+ char control[10240], /* LPD control 'file' */
+ *cptr; /* Pointer into control file string */
+ char status; /* Status byte from command */
+ struct sockaddr_in addr; /* Socket address */
+ struct hostent *hostaddr; /* Host address */
+ int copy; /* Copies written */
+ size_t nbytes, /* Number of bytes written */
+ tbytes; /* Total bytes written */
+ char buffer[8192]; /* Output buffer */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Setup an alarm handler for timeouts...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGALRM, lpd_timeout);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = lpd_timeout;
+ sigaction(SIGALRM, &action, NULL);
+#else
+ signal(SIGALRM, lpd_timeout);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Loop forever trying to print the file...
+ */
+
+ for (;;) /* FOREVER */
+ {
+ /*
+ * First try to reserve a port for this connection...
+ */
+
+ if ((hostaddr = httpGetHostByName(hostname)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
+ hostname, hstrerror(h_errno));
+ return (1);
+ }
+
+ fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n",
+ hostname, printer);
+
+ memset(&addr, 0, sizeof(addr));
+ memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
+ addr.sin_family = hostaddr->h_addrtype;
+ addr.sin_port = htons(port);
+
+ for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024;;)
+ {
+ /*
+ * Choose the next priviledged port...
+ */
+
+ lport --;
+
+ if (lport < 721 && reserve == RESERVE_RFC1179)
+ lport = 731;
+ else if (lport < 1)
+ lport = 1023;
+
+#ifdef HAVE_GETEUID
+ if (geteuid() || !reserve)
+#else
+ if (getuid() || !reserve)
+#endif /* HAVE_GETEUID */
+ {
+ /*
+ * Just create a regular socket...
+ */
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ perror("ERROR: Unable to create socket");
+ return (1);
+ }
+
+ lport = 0;
+ }
+ else
+ {
+ /*
+ * We're running as root and want to comply with RFC 1179. Reserve a
+ * priviledged lport between 721 and 731...
+ */
+
+ if ((fd = rresvport(&lport)) < 0)
+ {
+ perror("ERROR: Unable to reserve port");
+ sleep(1);
+
+ continue;
+ }
+ }
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ error = errno;
+ close(fd);
+ fd = -1;
+
+ if (error == ECONNREFUSED || error == EHOSTDOWN ||
+ error == EHOSTUNREACH)
+ {
+ fprintf(stderr, "WARNING: Network host \'%s\' is busy, down, or unreachable; will retry in 30 seconds...\n",
+ hostname);
+ sleep(30);
+ }
+ else if (error == EADDRINUSE)
+ {
+ /*
+ * Try on another port...
+ */
+
+ sleep(1);
+ }
+ else
+ {
+ perror("ERROR: Unable to connect to printer; will retry in 30 seconds...");
+ sleep(30);
+ }
+ }
+ else
+ break;
+ }
+
+ fprintf(stderr, "INFO: Connected to %s...\n", hostname);
+ fprintf(stderr, "DEBUG: Connected on ports %d (local %d)...\n", port,
+ lport);
+
+ /*
+ * Next, open the print file and figure out its size...
+ */
+
+ if (stat(filename, &filestats))
+ {
+ perror("ERROR: unable to stat print file");
+ return (1);
+ }
+
+ filestats.st_size *= manual_copies;
+
+ if ((fp = fopen(filename, "rb")) == NULL)
+ {
+ perror("ERROR: unable to open print file for reading");
+ return (1);
+ }
+
+ /*
+ * Send a job header to the printer, specifying no banner page and
+ * literal output...
+ */
+
+ if (lpd_command(fd, timeout, "\002%s\n",
+ printer)) /* Receive print job(s) */
+ return (1);
+
+ gethostname(localhost, sizeof(localhost));
+ localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */
+
+ snprintf(control, sizeof(control), "H%s\nP%s\nJ%s\n", localhost, user,
+ title);
+ cptr = control + strlen(control);
+
+ if (banner)
+ {
+ snprintf(cptr, sizeof(control) - (cptr - control), "C%s\nL%s\n",
+ localhost, user);
+ cptr += strlen(cptr);
+ }
+
+ while (copies > 0)
+ {
+ snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%.15s\n", format,
+ getpid() % 1000, localhost);
+ cptr += strlen(cptr);
+ copies --;
+ }
+
+ snprintf(cptr, sizeof(control) - (cptr - control),
+ "UdfA%03d%.15s\nN%s\n",
+ getpid() % 1000, localhost, title);
+
+ fprintf(stderr, "DEBUG: Control file is:\n%s", control);
+
+ if (order == ORDER_CONTROL_DATA)
+ {
+ if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
+ getpid() % 1000, localhost))
+ return (1);
+
+ fprintf(stderr, "INFO: Sending control file (%lu bytes)\n",
+ (unsigned long)strlen(control));
+
+ if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
+ {
+ status = errno;
+ perror("ERROR: Unable to write control file");
+ }
+ else
+ {
+ alarm(timeout);
+
+ if (read(fd, &status, 1) < 1)
+ {
+ fprintf(stderr, "WARNING: Remote host did not respond with control "
+ "status byte after %d seconds!\n", timeout);
+ status = errno;
+ }
+
+ alarm(0);
+ }
+
+ if (status != 0)
+ fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
+ status);
+ else
+ fputs("INFO: Control file sent successfully\n", stderr);
+ }
+ else
+ status = 0;
+
+ if (status == 0)
+ {
+ /*
+ * Send the print file...
+ */
+
+ if (lpd_command(fd, timeout, "\003%u dfA%03.3d%.15s\n",
+ (unsigned)filestats.st_size, getpid() % 1000,
+ localhost))
+ return (1);
+
+ fprintf(stderr, "INFO: Sending data file (%u bytes)\n",
+ (unsigned)filestats.st_size);
+
+ tbytes = 0;
+ for (copy = 0; copy < manual_copies; copy ++)
+ {
+ rewind(fp);
+
+ while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+ {
+ fprintf(stderr, "INFO: Spooling LPR job, %u%% complete...\n",
+ (unsigned)(100.0f * tbytes / filestats.st_size));
+
+ if (lpd_write(fd, buffer, nbytes) < nbytes)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+ else
+ tbytes += nbytes;
+ }
+ }
+
+ if (tbytes < filestats.st_size)
+ status = errno;
+ else if (lpd_write(fd, "", 1) < 1)
+ {
+ perror("ERROR: Unable to send trailing nul to printer");
+ status = errno;
+ }
+ else
+ {
+ /*
+ * Read the status byte from the printer; if we can't read the byte
+ * back now, we should set status to "errno", however at this point
+ * we know the printer got the whole file and we don't necessarily
+ * want to requeue it over and over...
+ */
+
+ alarm(timeout);
+
+ if (recv(fd, &status, 1, 0) < 1)
+ {
+ fprintf(stderr, "WARNING: Remote host did not respond with data "
+ "status byte after %d seconds!\n", timeout);
+ status = 0;
+ }
+
+ alarm(0);
+ }
+
+ if (status != 0)
+ fprintf(stderr, "ERROR: Remote host did not accept data file (%d)\n",
+ status);
+ else
+ fputs("INFO: Data file sent successfully\n", stderr);
+ }
+
+ if (status == 0 && order == ORDER_DATA_CONTROL)
+ {
+ if (lpd_command(fd, timeout, "\002%d cfA%03.3d%.15s\n", strlen(control),
+ getpid() % 1000, localhost))
+ return (1);
+
+ fprintf(stderr, "INFO: Sending control file (%lu bytes)\n",
+ (unsigned long)strlen(control));
+
+ if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
+ {
+ status = errno;
+ perror("ERROR: Unable to write control file");
+ }
+ else
+ {
+ alarm(timeout);
+
+ if (read(fd, &status, 1) < 1)
+ {
+ fprintf(stderr, "WARNING: Remote host did not respond with control "
+ "status byte after %d seconds!\n", timeout);
+ status = errno;
+ }
+
+ alarm(0);
+ }
+
+ if (status != 0)
+ fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
+ status);
+ else
+ fputs("INFO: Control file sent successfully\n", stderr);
+ }
+
+ /*
+ * Close the socket connection and input file...
+ */
+
+ close(fd);
+ fclose(fp);
+
+ if (status == 0)
+ return (0);
+
+ /*
+ * Waiting for a retry...
+ */
+
+ sleep(30);
+ }
+}
+
+
+/*
+ * 'lpd_timeout()' - Handle timeout alarms...
+ */
+
+static void
+lpd_timeout(int sig) /* I - Signal number */
+{
+ (void)sig;
+
+#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
+ signal(SIGALRM, lpd_timeout);
+#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
+}
+
+
+/*
+ * 'lpd_write()' - Write a buffer of data to an LPD server.
+ */
+
+static int /* O - Number of bytes written or -1 on error */
+lpd_write(int lpd_fd, /* I - LPD socket */
+ char *buffer, /* I - Buffer to write */
+ int length) /* I - Number of bytes to write */
+{
+ int bytes, /* Number of bytes written */
+ total; /* Total number of bytes written */
+
+
+ total = 0;
+ while ((bytes = send(lpd_fd, buffer, length - total, 0)) >= 0)
+ {
+ total += bytes;
+ buffer += bytes;
+
+ if (total == length)
+ break;
+ }
+
+ if (bytes < 0)
+ return (-1);
+ else
+ return (length);
+}
+
+
+#ifndef HAVE_RRESVPORT
+/*
+ * 'rresvport()' - A simple implementation of rresvport().
+ */
+
+int /* O - Socket or -1 on error */
+rresvport(int *port) /* IO - Port number to bind to */
+{
+ struct sockaddr_in addr; /* Socket address */
+ int fd; /* Socket file descriptor */
+
+
+ /*
+ * Try to create an IPv4 socket...
+ */
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return (-1);
+
+ /*
+ * Initialize the address buffer...
+ */
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ /*
+ * Try to bind the socket to a reserved port; unlike the standard
+ * BSD rresvport(), we limit the port number to 721 through 732
+ * (instead of 512 to 1023) since RFC 1179 defines the local port
+ * number between 721 and 732...
+ */
+
+ while (*port > 720)
+ {
+ /*
+ * Set the port number...
+ */
+
+ addr.sin_port = htons(*port);
+
+ /*
+ * Try binding the port to the socket; return if all is OK...
+ */
+
+ if (!bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
+ return (fd);
+
+ /*
+ * Stop if we have any error other than "address already in use"...
+ */
+
+ if (errno != EADDRINUSE)
+ {
+# ifdef WIN32
+ closesocket(fd);
+# else
+ close(fd);
+# endif /* WIN32 */
+
+ return (-1);
+ }
+
+ /*
+ * Try the next port...
+ */
+
+ (*port)--;
+ }
+
+ /*
+ * Wasn't able to bind to a reserved port, so close the socket and return
+ * -1...
+ */
+
+# ifdef WIN32
+ closesocket(fd);
+# else
+ close(fd);
+# endif /* WIN32 */
+
+ return (-1);
+}
+#endif /* !HAVE_RRESVPORT */
+
+
+/*
+ * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal */
+{
+ (void)sig; /* remove compiler warnings... */
+
+ /*
+ * Remove the temporary file if necessary...
+ */
+
+ if (tmpfilename[0])
+ unlink(tmpfilename);
+
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/parallel.c b/backend/parallel.c
new file mode 100644
index 000000000..4c37313e1
--- /dev/null
+++ b/backend/parallel.c
@@ -0,0 +1,679 @@
+/*
+ * "$Id$"
+ *
+ * Parallel port backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the specified parallel port.
+ * list_devices() - List all parallel devices.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/string.h>
+#include <signal.h>
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# include <termios.h>
+#endif /* WIN32 */
+
+#ifdef __sgi
+# include <invent.h>
+# ifndef INV_EPP_ECP_PLP
+# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
+# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
+# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
+# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
+# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
+# endif /* !INV_EPP_ECP_PLP */
+#endif /* __sgi */
+
+
+/*
+ * Local functions...
+ */
+
+void list_devices(void);
+
+
+/*
+ * 'main()' - Send a file to the specified parallel port.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info (not used) */
+ resource[1024], /* Resource info (device and options) */
+ *options; /* Pointer to options */
+ int port; /* Port number (not used) */
+ int fp; /* Print file */
+ int copies; /* Number of copies to print */
+ int fd; /* Parallel device */
+ int wbytes; /* Number of bytes written */
+ size_t nbytes, /* Number of bytes read */
+ tbytes; /* Total number of bytes written */
+ char buffer[8192], /* Output buffer */
+ *bufptr; /* Pointer into buffer */
+ struct termios opts; /* Parallel port options */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ list_devices();
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fputs("Usage: parallel job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ {
+ fp = 0;
+ copies = 1;
+ }
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = open(argv[6], O_RDONLY)) < 0)
+ {
+ perror("ERROR: unable to open print file");
+ return (1);
+ }
+
+ copies = atoi(argv[4]);
+ }
+
+ /*
+ * Extract the device name and options from the URI...
+ */
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ /*
+ * See if there are any options...
+ */
+
+ if ((options = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the options...
+ */
+
+ *options++ = '\0';
+ }
+
+ /*
+ * Open the parallel port device...
+ */
+
+ do
+ {
+ if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1)
+ {
+ if (errno == EBUSY)
+ {
+ fputs("INFO: Parallel port busy; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else if (errno == ENXIO || errno == EIO || errno == ENOENT)
+ {
+ fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Unable to open parallel port device file \"%s\": %s\n",
+ resource, strerror(errno));
+ return (1);
+ }
+ }
+ }
+ while (fd < 0);
+
+ /*
+ * Set any options provided...
+ */
+
+ tcgetattr(fd, &opts);
+
+ opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
+
+ /**** No options supported yet ****/
+
+ tcsetattr(fd, TCSANOW, &opts);
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (argc < 7)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ /*
+ * Finally, send the print file...
+ */
+
+ wbytes = 0;
+
+ while (copies > 0)
+ {
+ copies --;
+
+ if (fp != 0)
+ {
+ fputs("PAGE: 1 1\n", stderr);
+ lseek(fp, 0, SEEK_SET);
+ }
+
+ tbytes = 0;
+ while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
+ {
+ /*
+ * Write the print data to the printer...
+ */
+
+ tbytes += nbytes;
+ bufptr = buffer;
+
+ while (nbytes > 0)
+ {
+ if ((wbytes = write(fd, bufptr, nbytes)) < 0)
+ if (errno == ENOTTY)
+ wbytes = write(fd, bufptr, nbytes);
+
+ if (wbytes < 0)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+ }
+
+ if (wbytes < 0)
+ break;
+
+ if (argc > 6)
+ fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
+ (unsigned long)tbytes);
+ }
+ }
+
+ /*
+ * Close the socket connection and input file and return...
+ */
+
+ close(fd);
+ if (fp != 0)
+ close(fp);
+
+ return (wbytes < 0);
+}
+
+
+/*
+ * 'list_devices()' - List all parallel devices.
+ */
+
+void
+list_devices(void)
+{
+#if defined(__hpux) || defined(__sgi) || defined(__sun)
+ static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
+ /* Funky hex numbering used for some devices */
+#endif /* __hpux || __sgi || __sun */
+
+#ifdef __linux
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255], /* Device filename */
+ probefile[255], /* Probe filename */
+ basedevice[255]; /* Base device filename for ports */
+ FILE *probe; /* /proc/parport/n/autoprobe file */
+ char line[1024], /* Line from file */
+ *delim, /* Delimiter in file */
+ make[IPP_MAX_NAME], /* Make from file */
+ model[IPP_MAX_NAME]; /* Model from file */
+
+
+ for (i = 0; i < 4; i ++)
+ {
+ /*
+ * First open the device to make sure the driver module is loaded...
+ */
+
+ if ((fd = open("/dev/parallel/0", O_WRONLY)) >= 0)
+ {
+ close(fd);
+ strcpy(basedevice, "/dev/parallel/");
+ }
+ else
+ {
+ sprintf(device, "/dev/lp%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ strcpy(basedevice, "/dev/lp");
+ }
+ else
+ {
+ sprintf(device, "/dev/par%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ strcpy(basedevice, "/dev/par");
+ }
+ else
+ {
+ sprintf(device, "/dev/printers/%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ strcpy(basedevice, "/dev/printers/");
+ }
+ else
+ strcpy(basedevice, "/dev/unknown-parallel");
+ }
+ }
+ }
+
+ /*
+ * Then try looking at the probe file...
+ */
+
+ sprintf(probefile, "/proc/parport/%d/autoprobe", i);
+ if ((probe = fopen(probefile, "r")) == NULL)
+ {
+ /*
+ * Linux 2.4 kernel has different path...
+ */
+
+ sprintf(probefile, "/proc/sys/dev/parport/parport%d/autoprobe", i);
+ probe = fopen(probefile, "r");
+ }
+
+ if (probe != NULL)
+ {
+ /*
+ * Found a probe file!
+ */
+
+ memset(make, 0, sizeof(make));
+ memset(model, 0, sizeof(model));
+ strcpy(model, "Unknown");
+
+ while (fgets(line, sizeof(line), probe) != NULL)
+ {
+ /*
+ * Strip trailing ; and/or newline.
+ */
+
+ if ((delim = strrchr(line, ';')) != NULL)
+ *delim = '\0';
+ else if ((delim = strrchr(line, '\n')) != NULL)
+ *delim = '\0';
+
+ /*
+ * Look for MODEL and MANUFACTURER lines...
+ */
+
+ if (strncmp(line, "MODEL:", 6) == 0 &&
+ strncmp(line, "MODEL:Unknown", 13) != 0)
+ strlcpy(model, line + 6, sizeof(model));
+ else if (strncmp(line, "MANUFACTURER:", 13) == 0 &&
+ strncmp(line, "MANUFACTURER:Unknown", 20) != 0)
+ strlcpy(make, line + 13, sizeof(make));
+ }
+
+ fclose(probe);
+
+ if (make[0])
+ printf("direct parallel:%s%d \"%s %s\" \"Parallel Port #%d\"\n",
+ basedevice, i, make, model, i + 1);
+ else
+ printf("direct parallel:%s%d \"%s\" \"Parallel Port #%d\"\n",
+ basedevice, i, model, i + 1);
+ }
+ else if (fd >= 0)
+ {
+ /*
+ * No probe file, but we know the port is there...
+ */
+
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1);
+ }
+ }
+#elif defined(__sgi)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+ inventory_t *inv; /* Hardware inventory info */
+
+
+ /*
+ * IRIX maintains a hardware inventory of most devices...
+ */
+
+ setinvent();
+
+ while ((inv = getinvent()) != NULL)
+ {
+ if (inv->inv_class == INV_PARALLEL &&
+ (inv->inv_type == INV_ONBOARD_PLP ||
+ inv->inv_type == INV_EPP_ECP_PLP))
+ {
+ /*
+ * Standard parallel port...
+ */
+
+ puts("direct parallel:/dev/plp \"Unknown\" \"Onboard Parallel Port\"");
+ }
+ else if (inv->inv_class == INV_PARALLEL &&
+ inv->inv_type == INV_EPC_PLP)
+ {
+ /*
+ * EPC parallel port...
+ */
+
+ printf("direct parallel:/dev/plp%d \"Unknown\" \"Integral EPC parallel port, Ebus slot %d\"\n",
+ inv->inv_controller, inv->inv_controller);
+ }
+ }
+
+ endinvent();
+
+ /*
+ * Central Data makes serial and parallel "servers" that can be
+ * connected in a number of ways. Look for ports...
+ */
+
+ for (i = 0; i < 10; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/lpn%d%c", j, funky_hex[n]);
+ else if (i == 9) /* PCI */
+ sprintf(device, "/dev/lpp%d%c", j, funky_hex[n]);
+ else /* SCSI */
+ sprintf(device, "/dev/lp%d%d%c", i, j, funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n",
+ device, j, n);
+ else if (i == 9)
+ printf("direct parallel:%s \"Unknown\" \"Central Data PCI Parallel Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__sun)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard parallel ports...
+ */
+
+ for (i = 0; i < 10; i ++)
+ {
+ sprintf(device, "/dev/ecpp%d", i);
+ if (access(device, 0) == 0)
+ printf("direct parallel:%s \"Unknown\" \"Sun IEEE-1284 Parallel Port #%d\"\n",
+ device, i + 1);
+ }
+
+ for (i = 0; i < 10; i ++)
+ {
+ sprintf(device, "/dev/bpp%d", i);
+ if (access(device, 0) == 0)
+ printf("direct parallel:%s \"Unknown\" \"Sun Standard Parallel Port #%d\"\n",
+ device, i + 1);
+ }
+
+ for (i = 0; i < 3; i ++)
+ {
+ sprintf(device, "/dev/lp%d", i);
+
+ if (access(device, 0) == 0)
+ printf("direct parallel:%s \"Unknown\" \"PC Parallel Port #%d\"\n",
+ device, i + 1);
+ }
+
+ /*
+ * MAGMA parallel ports...
+ */
+
+ for (i = 0; i < 40; i ++)
+ {
+ sprintf(device, "/dev/pm%02d", i);
+ if (access(device, 0) == 0)
+ printf("direct parallel:%s \"Unknown\" \"MAGMA Parallel Board #%d Port #%d\"\n",
+ device, (i / 10) + 1, (i % 10) + 1);
+ }
+
+ /*
+ * Central Data parallel ports...
+ */
+
+ for (i = 0; i < 9; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/sts/lpN%d%c", j, funky_hex[n]);
+ else
+ sprintf(device, "/dev/sts/lp%c%d%c", i + 'C', j,
+ funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__hpux)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard parallel ports...
+ */
+
+ if (access("/dev/rlp", 0) == 0)
+ puts("direct parallel:/dev/rlp \"Unknown\" \"Standard Parallel Port (/dev/rlp)\"");
+
+ for (i = 0; i < 7; i ++)
+ for (j = 0; j < 7; j ++)
+ {
+ sprintf(device, "/dev/c%dt%dd0_lp", i, j);
+ if (access(device, 0) == 0)
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d,%d\"\n",
+ device, i, j);
+ }
+
+ /*
+ * Central Data parallel ports...
+ */
+
+ for (i = 0; i < 9; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/lpN%d%c", j, funky_hex[n]);
+ else
+ sprintf(device, "/dev/lp%c%d%c", i + 'C', j,
+ funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("direct parallel:%s \"Unknown\" \"Central Data EtherLite Parallel Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("direct parallel:%s \"Unknown\" \"Central Data SCSI Parallel Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__osf__)
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ for (i = 0; i < 3; i ++)
+ {
+ sprintf(device, "/dev/lp%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1);
+ }
+ }
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ for (i = 0; i < 3; i ++)
+ {
+ sprintf(device, "/dev/lpt%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d (interrupt-driven)\"\n", device, i + 1);
+ }
+
+ sprintf(device, "/dev/lpa%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d (polled)\"\n", device, i + 1);
+ }
+ }
+#elif defined(_AIX)
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ for (i = 0; i < 8; i ++)
+ {
+ sprintf(device, "/dev/lp%d", i);
+ if ((fd = open(device, O_WRONLY)) >= 0)
+ {
+ close(fd);
+ printf("direct parallel:%s \"Unknown\" \"Parallel Port #%d\"\n", device, i + 1);
+ }
+ }
+#endif
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/scsi-irix.c b/backend/scsi-irix.c
new file mode 100644
index 000000000..33f42fa03
--- /dev/null
+++ b/backend/scsi-irix.c
@@ -0,0 +1,210 @@
+/*
+ * "$Id$"
+ *
+ * IRIX SCSI printer support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2003-2004 by Easy Software Products, all rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use
+ * of this software must display the following
+ * acknowledgement:
+ *
+ * This product includes software developed by Easy
+ * Software Products.
+ *
+ * 4. The name of Easy Software Products may not be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Contents:
+ *
+ * list_devices() - List the available SCSI printer devices.
+ * print_device() - Print a file to a SCSI device.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <bstring.h> /* memcpy() and friends */
+#include <sys/dsreq.h> /* SCSI interface stuff */
+
+
+/*
+ * 'list_devices()' - List the available SCSI printer devices.
+ */
+
+void
+list_devices(void)
+{
+ puts("direct scsi \"Unknown\" \"SCSI Printer\"");
+}
+
+
+/*
+ * 'print_device()' - Print a file to a SCSI device.
+ */
+
+int /* O - Print status */
+print_device(const char *resource, /* I - SCSI device */
+ int fd, /* I - File to print */
+ int copies) /* I - Number of copies to print */
+{
+ int scsi_fd; /* SCSI file descriptor */
+ char buffer[8192]; /* Data buffer */
+ int bytes; /* Number of bytes */
+ int try; /* Current try */
+ dsreq_t scsi_req; /* SCSI request */
+ char scsi_cmd[6]; /* SCSI command data */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure we have a valid resource name...
+ */
+
+ if (strncmp(resource, "/dev/scsi/", 10) != 0)
+ {
+ fprintf(stderr, "ERROR: Bad SCSI device file \"%s\"!\n", resource);
+ return (1);
+ }
+
+ /*
+ * Open the SCSI device file...
+ */
+
+ do
+ {
+ if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
+ {
+ if (errno != EAGAIN && errno != EBUSY)
+ {
+ fprintf(stderr, "ERROR: Unable to open SCSI device \"%s\" - %s\n",
+ resource, strerror(errno));
+ return (1);
+ }
+ else
+ {
+ fprintf(stderr, "INFO: SCSI device \"%s\" busy; retrying...\n",
+ resource);
+ sleep(30);
+ }
+ }
+ }
+ while (scsi_fd == -1);
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (fd != 0)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ /*
+ * Copy the print file to the device...
+ */
+
+ while (copies > 0)
+ {
+ if (fd != 0)
+ lseek(fd, 0, SEEK_SET);
+
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ {
+ memset(&scsi_req, 0, sizeof(scsi_req));
+
+ scsi_req.ds_flags = DSRQ_WRITE;
+ scsi_req.ds_time = 60 * 1000;
+ scsi_req.ds_cmdbuf = scsi_cmd;
+ scsi_req.ds_cmdlen = 6;
+ scsi_req.ds_databuf = buffer;
+ scsi_req.ds_datalen = bytes;
+
+ scsi_cmd[0] = 0x0a; /* Group 0 print command */
+ scsi_cmd[1] = 0x00;
+ scsi_cmd[2] = bytes / 65536;
+ scsi_cmd[3] = bytes / 256;
+ scsi_cmd[4] = bytes;
+ scsi_cmd[5] = 0x00;
+
+ for (try = 0; try < 10; try ++)
+ if (ioctl(scsi_fd, DS_ENTER, &scsi_req) < 0 ||
+ scsi_req.ds_status != 0)
+ {
+ fprintf(stderr, "WARNING: SCSI command timed out (%d); retrying...\n",
+ scsi_req.ds_status);
+ sleep(try + 1);
+ }
+ else
+ break;
+
+ if (try >= 10)
+ {
+ fprintf(stderr, "ERROR: Unable to send print data (%d)\n",
+ scsi_req.ds_status);
+ close(scsi_fd);
+ return (1);
+ }
+ }
+
+ copies --;
+ }
+
+ /*
+ * Close the device and return...
+ */
+
+ close(fd);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/scsi-linux.c b/backend/scsi-linux.c
new file mode 100644
index 000000000..9b75cd1a2
--- /dev/null
+++ b/backend/scsi-linux.c
@@ -0,0 +1,228 @@
+/*
+ * "$Id$"
+ *
+ * Linux SCSI printer support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2003-2004 by Easy Software Products, all rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use
+ * of this software must display the following
+ * acknowledgement:
+ *
+ * This product includes software developed by Easy
+ * Software Products.
+ *
+ * 4. The name of Easy Software Products may not be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Contents:
+ *
+ * list_devices() - List the available SCSI printer devices.
+ * print_device() - Print a file to a SCSI device.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <scsi/sg.h>
+
+
+/*
+ * We currently only support the Linux 2.4 generic SCSI interface.
+ */
+
+#ifndef SG_DXFER_TO_DEV
+/*
+ * Dummy functions that do nothing on unsupported platforms...
+ */
+void list_devices(void) {}
+int print_device(const char *resource, int fd, int copies) { return (1); }
+#else
+
+
+/*
+ * 'list_devices()' - List the available SCSI printer devices.
+ */
+
+void
+list_devices(void)
+{
+ puts("direct scsi \"Unknown\" \"SCSI Printer\"");
+}
+
+
+/*
+ * 'print_device()' - Print a file to a SCSI device.
+ */
+
+int /* O - Print status */
+print_device(const char *resource, /* I - SCSI device */
+ int fd, /* I - File to print */
+ int copies) /* I - Number of copies to print */
+{
+ int scsi_fd; /* SCSI file descriptor */
+ char buffer[8192]; /* Data buffer */
+ int bytes; /* Number of bytes */
+ int try; /* Current try */
+ sg_io_hdr_t scsi_req; /* SCSI request */
+ char scsi_cmd[6], /* SCSI command data */
+ scsi_sense[32]; /* SCSI sense data */
+# if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+# endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure we have a valid resource name...
+ */
+
+ if (strncmp(resource, "/dev/sg", 7) != 0)
+ {
+ fprintf(stderr, "ERROR: Bad SCSI device file \"%s\"!\n", resource);
+ return (1);
+ }
+
+ /*
+ * Open the SCSI device file...
+ */
+
+ do
+ {
+ if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
+ {
+ if (errno != EAGAIN && errno != EBUSY)
+ {
+ fprintf(stderr, "ERROR: Unable to open SCSI device \"%s\" - %s\n",
+ resource, strerror(errno));
+ return (1);
+ }
+ else
+ {
+ fprintf(stderr, "INFO: SCSI device \"%s\" busy; retrying...\n",
+ resource);
+ sleep(30);
+ }
+ }
+ }
+ while (scsi_fd == -1);
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (fd != 0)
+ {
+# ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+# elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+# else
+ signal(SIGTERM, SIG_IGN);
+# endif /* HAVE_SIGSET */
+ }
+
+ /*
+ * Copy the print file to the device...
+ */
+
+ while (copies > 0)
+ {
+ if (fd != 0)
+ lseek(fd, 0, SEEK_SET);
+
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ {
+ memset(&scsi_req, 0, sizeof(scsi_req));
+
+ scsi_req.interface_id = 'S';
+ scsi_req.dxfer_direction = SG_DXFER_TO_DEV;
+ scsi_req.cmd_len = 6;
+ scsi_req.mx_sb_len = sizeof(scsi_sense);
+ scsi_req.iovec_count = 0;
+ scsi_req.dxfer_len = bytes;
+ scsi_req.dxferp = buffer;
+ scsi_req.cmdp = scsi_cmd;
+ scsi_req.sbp = scsi_sense;
+ scsi_req.timeout = 60 * 1000;
+
+ scsi_cmd[0] = 0x0a; /* Group 0 print command */
+ scsi_cmd[1] = 0x00;
+ scsi_cmd[2] = bytes / 65536;
+ scsi_cmd[3] = bytes / 256;
+ scsi_cmd[4] = bytes;
+ scsi_cmd[5] = 0x00;
+
+ for (try = 0; try < 10; try ++)
+ if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 ||
+ scsi_req.status != 0)
+ {
+ fprintf(stderr, "WARNING: SCSI command timed out (%d); retrying...\n",
+ scsi_req.status);
+ sleep(try + 1);
+ }
+ else
+ break;
+
+ if (try >= 10)
+ {
+ fprintf(stderr, "ERROR: Unable to send print data (%d)\n",
+ scsi_req.status);
+ close(scsi_fd);
+ return (1);
+ }
+ }
+
+ copies --;
+ }
+
+ /*
+ * Close the device and return...
+ */
+
+ close(fd);
+
+ return (0);
+}
+#endif /* !SG_DXFER_TO_DEV */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/scsi.c b/backend/scsi.c
new file mode 100644
index 000000000..0f37be835
--- /dev/null
+++ b/backend/scsi.c
@@ -0,0 +1,220 @@
+/*
+ * "$Id$"
+ *
+ * SCSI printer backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2003-2004 by Easy Software Products, all rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use
+ * of this software must display the following
+ * acknowledgement:
+ *
+ * This product includes software developed by Easy
+ * Software Products.
+ *
+ * 4. The name of Easy Software Products may not be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the specified SCSI printer.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/string.h>
+#include <signal.h>
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif /* HAVE_SYS_IOCTL_H */
+#endif /* WIN32 */
+
+
+/*
+ * Local functions...
+ */
+
+void list_devices(void);
+int print_device(const char *resource, int fd, int copies);
+
+
+#ifdef __linux__
+# include "scsi-linux.c"
+#elif defined(__sgi)
+# include "scsi-irix.c"
+#else
+/*
+ * Dummy functions that do nothing on unsupported platforms...
+ */
+void list_devices(void) {}
+int print_device(const char *resource, int fd, int copies) { return (1); }
+#endif /* __linux */
+
+
+/*
+ * 'main()' - Send a file to the specified SCSI printer.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info (not used) */
+ resource[1024], /* Resource info (device and options) */
+ *options; /* Pointer to options */
+ int port; /* Port number (not used) */
+ int fp; /* Print file */
+ int copies; /* Number of copies to print */
+ int status; /* Exit status */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ list_devices();
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fputs("Usage: scsi:/dev/file job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ {
+ fp = 0;
+ copies = 1;
+ }
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = open(argv[6], O_RDONLY)) < 0)
+ {
+ perror("ERROR: unable to open print file");
+ return (1);
+ }
+
+ copies = atoi(argv[4]);
+ }
+
+ /*
+ * Extract the device name and options from the URI...
+ */
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ /*
+ * See if there are any options...
+ */
+
+ if ((options = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the options...
+ */
+
+ *options++ = '\0';
+ }
+
+ /*
+ * Finally, send the print file...
+ */
+
+ status = print_device(resource, fp, copies);
+
+ /*
+ * Close input file and return...
+ */
+
+ if (fp != 0)
+ close(fp);
+
+ return (status);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/serial.c b/backend/serial.c
new file mode 100644
index 000000000..c351bd953
--- /dev/null
+++ b/backend/serial.c
@@ -0,0 +1,996 @@
+/*
+ * "$Id$"
+ *
+ * Serial port backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the printer or server.
+ * list_devices() - List all serial devices.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/string.h>
+#include <signal.h>
+
+#ifdef __hpux
+# include <sys/modem.h>
+#endif /* __hpux */
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# include <termios.h>
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif /* HAVE_SYS_IOCTL_H */
+#endif /* WIN32 */
+
+#ifdef __sgi
+# include <invent.h>
+# ifndef INV_EPP_ECP_PLP
+# define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
+# define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
+# define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
+# define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
+# define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
+# endif /* !INV_EPP_ECP_PLP */
+#endif /* __sgi */
+
+#ifndef CRTSCTS
+# ifdef CNEW_RTSCTS
+# define CRTSCTS CNEW_RTSCTS
+# else
+# define CRTSCTS 0
+# endif /* CNEW_RTSCTS */
+#endif /* !CRTSCTS */
+
+#if defined(__APPLE__)
+# include <CoreFoundation/CoreFoundation.h>
+# include <IOKit/IOKitLib.h>
+# include <IOKit/serial/IOSerialKeys.h>
+# include <IOKit/IOBSD.h>
+#endif /* __APPLE__ */
+
+
+/*
+ * Local functions...
+ */
+
+void list_devices(void);
+
+
+/*
+ * 'main()' - Send a file to the printer or server.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info (not used) */
+ resource[1024], /* Resource info (device and options) */
+ *options, /* Pointer to options */
+ name[255], /* Name of option */
+ value[255], /* Value of option */
+ *ptr; /* Pointer into name or value */
+ int port; /* Port number (not used) */
+ int fp; /* Print file */
+ int copies; /* Number of copies to print */
+ int fd; /* Parallel device */
+ int wbytes; /* Number of bytes written */
+ size_t nbytes, /* Number of bytes read */
+ tbytes; /* Total number of bytes written */
+ int dtrdsr; /* Do dtr/dsr flow control? */
+ int bufsize; /* Size of output buffer for writes */
+ char buffer[8192], /* Output buffer */
+ *bufptr; /* Pointer into buffer */
+ struct termios opts; /* Serial port options */
+ struct termios origopts; /* Original port options */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ list_devices();
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fputs("Usage: serial job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ {
+ fp = 0;
+ copies = 1;
+ }
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = open(argv[6], O_RDONLY)) < 0)
+ {
+ perror("ERROR: unable to open print file");
+ return (1);
+ }
+
+ copies = atoi(argv[4]);
+ }
+
+ /*
+ * Extract the device name and options from the URI...
+ */
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ /*
+ * See if there are any options...
+ */
+
+ if ((options = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the options...
+ */
+
+ *options++ = '\0';
+ }
+
+ /*
+ * Open the serial port device...
+ */
+
+ do
+ {
+ if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL | O_NDELAY)) == -1)
+ {
+ if (errno == EBUSY)
+ {
+ fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Unable to open serial port device file \"%s\": %s\n",
+ resource, strerror(errno));
+ return (1);
+ }
+ }
+ }
+ while (fd < 0);
+
+ /*
+ * Set any options provided...
+ */
+
+ tcgetattr(fd, &origopts);
+ tcgetattr(fd, &opts);
+
+ opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
+ opts.c_oflag &= ~OPOST; /* Don't post-process */
+
+ bufsize = 96; /* 9600 baud / 10 bits/char / 10Hz */
+ dtrdsr = 0; /* No dtr/dsr flow control */
+
+ if (options != NULL)
+ while (*options)
+ {
+ /*
+ * Get the name...
+ */
+
+ for (ptr = name; *options && *options != '=';)
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = *options++;
+ *ptr = '\0';
+
+ if (*options == '=')
+ {
+ /*
+ * Get the value...
+ */
+
+ options ++;
+
+ for (ptr = value; *options && *options != '+';)
+ if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = *options++;
+ *ptr = '\0';
+
+ if (*options == '+')
+ options ++;
+ }
+ else
+ value[0] = '\0';
+
+ /*
+ * Process the option...
+ */
+
+ if (strcasecmp(name, "baud") == 0)
+ {
+ /*
+ * Set the baud rate...
+ */
+
+ bufsize = atoi(value) / 100;
+
+#if B19200 == 19200
+ cfsetispeed(&opts, atoi(value));
+ cfsetospeed(&opts, atoi(value));
+#else
+ switch (atoi(value))
+ {
+ case 1200 :
+ cfsetispeed(&opts, B1200);
+ cfsetospeed(&opts, B1200);
+ break;
+ case 2400 :
+ cfsetispeed(&opts, B2400);
+ cfsetospeed(&opts, B2400);
+ break;
+ case 4800 :
+ cfsetispeed(&opts, B4800);
+ cfsetospeed(&opts, B4800);
+ break;
+ case 9600 :
+ cfsetispeed(&opts, B9600);
+ cfsetospeed(&opts, B9600);
+ break;
+ case 19200 :
+ cfsetispeed(&opts, B19200);
+ cfsetospeed(&opts, B19200);
+ break;
+ case 38400 :
+ cfsetispeed(&opts, B38400);
+ cfsetospeed(&opts, B38400);
+ break;
+# ifdef B57600
+ case 57600 :
+ cfsetispeed(&opts, B57600);
+ cfsetospeed(&opts, B57600);
+ break;
+# endif /* B57600 */
+# ifdef B115200
+ case 115200 :
+ cfsetispeed(&opts, B115200);
+ cfsetospeed(&opts, B115200);
+ break;
+# endif /* B115200 */
+# ifdef B230400
+ case 230400 :
+ cfsetispeed(&opts, B230400);
+ cfsetospeed(&opts, B230400);
+ break;
+# endif /* B230400 */
+ default :
+ fprintf(stderr, "WARNING: Unsupported baud rate %s!\n", value);
+ break;
+ }
+#endif /* B19200 == 19200 */
+ }
+ else if (strcasecmp(name, "bits") == 0)
+ {
+ /*
+ * Set number of data bits...
+ */
+
+ switch (atoi(value))
+ {
+ case 7 :
+ opts.c_cflag &= ~CSIZE;
+ opts.c_cflag |= CS7;
+ opts.c_cflag |= PARENB;
+ opts.c_cflag &= ~PARODD;
+ break;
+ case 8 :
+ opts.c_cflag &= ~CSIZE;
+ opts.c_cflag |= CS8;
+ opts.c_cflag &= ~PARENB;
+ break;
+ }
+ }
+ else if (strcasecmp(name, "parity") == 0)
+ {
+ /*
+ * Set parity checking...
+ */
+
+ if (strcasecmp(value, "even") == 0)
+ {
+ opts.c_cflag |= PARENB;
+ opts.c_cflag &= ~PARODD;
+ }
+ else if (strcasecmp(value, "odd") == 0)
+ {
+ opts.c_cflag |= PARENB;
+ opts.c_cflag |= PARODD;
+ }
+ else if (strcasecmp(value, "none") == 0)
+ opts.c_cflag &= ~PARENB;
+ }
+ else if (strcasecmp(name, "flow") == 0)
+ {
+ /*
+ * Set flow control...
+ */
+
+ if (strcasecmp(value, "none") == 0)
+ {
+ opts.c_iflag &= ~(IXON | IXOFF);
+ opts.c_cflag &= ~CRTSCTS;
+ }
+ else if (strcasecmp(value, "soft") == 0)
+ {
+ opts.c_iflag |= IXON | IXOFF;
+ opts.c_cflag &= ~CRTSCTS;
+ }
+ else if (strcasecmp(value, "hard") == 0 ||
+ strcasecmp(value, "rtscts") == 0)
+ {
+ opts.c_iflag &= ~(IXON | IXOFF);
+ opts.c_cflag |= CRTSCTS;
+ }
+ else if (strcasecmp(value, "dtrdsr") == 0)
+ {
+ opts.c_iflag &= ~(IXON | IXOFF);
+ opts.c_cflag &= ~CRTSCTS;
+
+ dtrdsr = 1;
+ }
+ }
+ }
+
+ tcsetattr(fd, TCSANOW, &opts);
+ fcntl(fd, F_SETFL, 0);
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (argc < 7)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ /*
+ * Finally, send the print file...
+ */
+
+ if (bufsize > sizeof(buffer))
+ bufsize = sizeof(buffer);
+
+ wbytes = 0;
+
+ while (copies > 0)
+ {
+ copies --;
+
+ if (fp != 0)
+ {
+ fputs("PAGE: 1 1\n", stderr);
+ lseek(fp, 0, SEEK_SET);
+ }
+
+ if (dtrdsr)
+ {
+ /*
+ * Check the port and sleep until DSR is set...
+ */
+
+ int status;
+
+
+ if (!ioctl(fd, TIOCMGET, &status))
+ if (!(status & TIOCM_DSR))
+ {
+ /*
+ * Wait for DSR to go high...
+ */
+
+ fputs("DEBUG: DSR is low; waiting for device...\n", stderr);
+
+ do
+ {
+ sleep(1);
+ if (ioctl(fd, TIOCMGET, &status))
+ break;
+ }
+ while (!(status & TIOCM_DSR));
+
+ fputs("DEBUG: DSR is high; writing to device...\n", stderr);
+ }
+ }
+
+ tbytes = 0;
+ while ((nbytes = read(fp, buffer, bufsize)) > 0)
+ {
+ /*
+ * Write the print data to the printer...
+ */
+
+ tbytes += nbytes;
+ bufptr = buffer;
+
+ while (nbytes > 0)
+ {
+ if ((wbytes = write(fd, bufptr, nbytes)) < 0)
+ if (errno == ENOTTY)
+ wbytes = write(fd, bufptr, nbytes);
+
+ if (wbytes < 0)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+ }
+
+ if (wbytes < 0)
+ break;
+
+ if (argc > 6)
+ fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
+ (unsigned long)tbytes);
+ }
+ }
+
+ /*
+ * Close the serial port and input file and return...
+ */
+
+ tcsetattr(fd, TCSADRAIN, &origopts);
+
+ close(fd);
+ if (fp != 0)
+ close(fp);
+
+ return (wbytes < 0);
+}
+
+
+/*
+ * 'list_devices()' - List all serial devices.
+ */
+
+void
+list_devices(void)
+{
+#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
+ /* Funky hex numbering used for some devices */
+#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
+
+#if defined(__linux) || defined(linux) || defined(__linux__)
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ for (i = 0; i < 100; i ++)
+ {
+ sprintf(device, "/dev/ttyS%d", i);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+# if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
+ printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+# else
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+# endif /* _ARCH_PPC || powerpc || __powerpc */
+ }
+ }
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(device, "/dev/usb/ttyUSB%d", i);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
+ device, i + 1);
+ }
+ }
+#elif defined(__sgi)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+ inventory_t *inv; /* Hardware inventory info */
+
+
+ /*
+ * IRIX maintains a hardware inventory of most devices...
+ */
+
+ setinvent();
+
+ while ((inv = getinvent()) != NULL)
+ {
+ if (inv->inv_class == INV_SERIAL)
+ {
+ /*
+ * Some sort of serial port...
+ */
+
+ if (inv->inv_type == INV_CDSIO || inv->inv_type == INV_CDSIO_E)
+ {
+ /*
+ * CDSIO port...
+ */
+
+ for (n = 0; n < 6; n ++)
+ printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
+ n + 5 + 8 * inv->inv_controller, inv->inv_controller, n + 1);
+ }
+ else if (inv->inv_type == INV_EPC_SERIAL)
+ {
+ /*
+ * Everest serial port...
+ */
+
+ if (inv->inv_unit == 0)
+ i = 1;
+ else
+ i = 41 + 4 * (int)inv->inv_controller;
+
+ for (n = 0; n < (int)inv->inv_state; n ++)
+ printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
+ n + i, n + 1, (int)inv->inv_controller);
+ }
+ else if (inv->inv_state > 1)
+ {
+ /*
+ * Standard serial port under IRIX 6.4 and earlier...
+ */
+
+ for (n = 0; n < (int)inv->inv_state; n ++)
+ printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
+ n + (int)inv->inv_unit + 1, n + (int)inv->inv_unit + 1);
+ }
+ else
+ {
+ /*
+ * Standard serial port under IRIX 6.5 and beyond...
+ */
+
+ printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
+ (int)inv->inv_controller, (int)inv->inv_controller);
+ }
+ }
+ }
+
+ endinvent();
+
+ /*
+ * Central Data makes serial and parallel "servers" that can be
+ * connected in a number of ways. Look for ports...
+ */
+
+ for (i = 0; i < 10; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/ttydn%d%c", j, funky_hex[n]);
+ else if (i == 9) /* PCI */
+ sprintf(device, "/dev/ttydp%d%c", j, funky_hex[n]);
+ else /* SCSI */
+ sprintf(device, "/dev/ttyd%d%d%c", i, j, funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
+ device, j, n);
+ else if (i == 9)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__sun)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard serial ports...
+ */
+
+ for (i = 0; i < 26; i ++)
+ {
+ sprintf(device, "/dev/cua/%c", 'a' + i);
+ if (access(device, 0) == 0)
+#ifdef B115200
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+#else
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+#endif /* B115200 */
+ }
+
+ /*
+ * MAGMA serial ports...
+ */
+
+ for (i = 0; i < 40; i ++)
+ {
+ sprintf(device, "/dev/term/%02d", i);
+ if (access(device, 0) == 0)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
+ device, (i / 10) + 1, (i % 10) + 1);
+ }
+
+ /*
+ * Central Data serial ports...
+ */
+
+ for (i = 0; i < 9; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/sts/ttyN%d%c", j, funky_hex[n]);
+ else
+ sprintf(device, "/dev/sts/tty%c%d%c", i + 'C', j,
+ funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__hpux)
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard serial ports...
+ */
+
+ for (i = 0; i < 10; i ++)
+ {
+ sprintf(device, "/dev/tty%dp0", i);
+ if (access(device, 0) == 0)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+ }
+
+ /*
+ * Central Data serial ports...
+ */
+
+ for (i = 0; i < 9; i ++)
+ for (j = 0; j < 8; j ++)
+ for (n = 0; n < 32; n ++)
+ {
+ if (i == 8) /* EtherLite */
+ sprintf(device, "/dev/ttyN%d%c", j, funky_hex[n]);
+ else
+ sprintf(device, "/dev/tty%c%d%c", i + 'C', j,
+ funky_hex[n]);
+
+ if (access(device, 0) == 0)
+ {
+ if (i == 8)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
+ device, j, n);
+ else
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
+ device, i, j, n);
+ }
+ }
+#elif defined(__osf__)
+ int i; /* Looping var */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard serial ports...
+ */
+
+ for (i = 0; i < 100; i ++)
+ {
+ sprintf(device, "/dev/tty%02d", i);
+ if (access(device, 0) == 0)
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+ }
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
+ int i, j; /* Looping vars */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * SIO ports...
+ */
+
+ for (i = 0; i < 32; i ++)
+ {
+ sprintf(device, "/dev/ttyd%c", funky_hex[i]);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
+ device, i + 1);
+ }
+ }
+
+ /*
+ * Cyclades ports...
+ */
+
+ for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
+ for (j = 0; j < 32; j ++)
+ {
+ sprintf(device, "/dev/ttyc%d%c", i, funky_hex[j]);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
+ device, i, j + 1);
+ }
+ }
+
+ /*
+ * Digiboard ports...
+ */
+
+ for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
+ for (j = 0; j < 32; j ++)
+ {
+ sprintf(device, "/dev/ttyD%d%c", i, funky_hex[j]);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
+ device, i, j + 1);
+ }
+ }
+
+ /*
+ * Stallion ports...
+ */
+
+ for (i = 0; i < 32; i ++)
+ {
+ sprintf(device, "/dev/ttyE%c", funky_hex[i]);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
+ device, i + 1);
+ }
+ }
+
+ /*
+ * SX ports...
+ */
+
+ for (i = 0; i < 128; i ++)
+ {
+ sprintf(device, "/dev/ttyA%d", i + 1);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
+ device, i + 1);
+ }
+ }
+#elif defined(__NetBSD__)
+ int i, j; /* Looping vars */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+
+
+ /*
+ * Standard serial ports...
+ */
+
+ for (i = 0; i < 4; i ++)
+ {
+ sprintf(device, "/dev/tty%02d", i);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
+ device, i + 1);
+ }
+ }
+
+ /*
+ * Cyclades-Z ports...
+ */
+
+ for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
+ for (j = 0; j < 64; j ++)
+ {
+ sprintf(device, "/dev/ttyCZ%02d%02d", i, j);
+ if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
+ {
+ close(fd);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
+ device, i, j + 1);
+ }
+ }
+#elif defined(__APPLE__)
+ /*
+ * Standard serial ports on MacOS X...
+ */
+
+ kern_return_t kernResult;
+ mach_port_t masterPort;
+ io_iterator_t serialPortIterator;
+ CFMutableDictionaryRef classesToMatch;
+ io_object_t serialService;
+
+ printf("serial serial \"Unknown\" \"Serial Printer (serial)\"\n");
+
+ kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if (KERN_SUCCESS != kernResult)
+ return;
+
+ /*
+ * Serial devices are instances of class IOSerialBSDClient.
+ */
+
+ classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
+ if (classesToMatch != NULL)
+ {
+ CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
+ CFSTR(kIOSerialBSDRS232Type));
+
+ kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch,
+ &serialPortIterator);
+ if (kernResult == KERN_SUCCESS)
+ {
+ while ((serialService = IOIteratorNext(serialPortIterator)))
+ {
+ CFTypeRef serialNameAsCFString;
+ CFTypeRef bsdPathAsCFString;
+ char serialName[128];
+ char bsdPath[1024];
+ Boolean result;
+
+
+ serialNameAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOTTYDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (serialNameAsCFString)
+ {
+ result = CFStringGetCString(serialNameAsCFString, serialName,
+ sizeof(serialName),
+ kCFStringEncodingASCII);
+ CFRelease(serialNameAsCFString);
+
+ if (result)
+ {
+ bsdPathAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOCalloutDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (bsdPathAsCFString)
+ {
+ result = CFStringGetCString(bsdPathAsCFString, bsdPath,
+ sizeof(bsdPath),
+ kCFStringEncodingASCII);
+ CFRelease(bsdPathAsCFString);
+
+ if (result)
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", bsdPath,
+ serialName);
+ }
+ }
+ }
+
+ IOObjectRelease(serialService);
+ }
+
+ IOObjectRelease(serialPortIterator); /* Release the iterator. */
+ }
+ }
+#endif
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/socket.c b/backend/socket.c
new file mode 100644
index 000000000..7c6ed2613
--- /dev/null
+++ b/backend/socket.c
@@ -0,0 +1,418 @@
+/*
+ * "$Id$"
+ *
+ * AppSocket backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the printer or server.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <cups/http-private.h>
+#include <cups/string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#ifdef WIN32
+# include <winsock.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif /* WIN32 */
+
+
+/*
+ * Local functions...
+ */
+
+void print_backchannel(const unsigned char *buffer, int nbytes);
+
+
+/*
+ * 'main()' - Send a file to the printer or server.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info (not used) */
+ resource[1024]; /* Resource info (not used) */
+ int fp; /* Print file */
+ int copies; /* Number of copies to print */
+ int port; /* Port number */
+ int delay; /* Delay for retries... */
+ int fd; /* AppSocket */
+ int error; /* Error code (if any) */
+ struct sockaddr_in addr; /* Socket address */
+ struct hostent *hostaddr; /* Host address */
+ int wbytes; /* Number of bytes written */
+ int nbytes; /* Number of bytes read */
+ size_t tbytes; /* Total number of bytes written */
+ char buffer[8192], /* Output buffer */
+ *bufptr; /* Pointer into buffer */
+ struct timeval timeout; /* Timeout for select() */
+ fd_set input; /* Input set for select() */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\"");
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
+ argv[0]);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ {
+ fp = 0;
+ copies = 1;
+ }
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = open(argv[6], O_RDONLY)) < 0)
+ {
+ perror("ERROR: unable to open print file");
+ return (1);
+ }
+
+ copies = atoi(argv[4]);
+ }
+
+ /*
+ * Extract the hostname and port number from the URI...
+ */
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ if (port == 0)
+ port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */
+
+ /*
+ * Then try to connect to the remote host...
+ */
+
+ if ((hostaddr = httpGetHostByName(hostname)) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
+ hostname, hstrerror(h_errno));
+ return (1);
+ }
+
+ fprintf(stderr, "INFO: Attempting to connect to host %s on port %d\n",
+ hostname, port);
+
+ memset(&addr, 0, sizeof(addr));
+ memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
+ addr.sin_family = hostaddr->h_addrtype;
+ addr.sin_port = htons(port);
+
+ wbytes = 0;
+
+ while (copies > 0)
+ {
+ for (delay = 5;;)
+ {
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ perror("ERROR: Unable to create socket");
+ return (1);
+ }
+
+ if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ error = errno;
+ close(fd);
+ fd = -1;
+
+ if (error == ECONNREFUSED || error == EHOSTDOWN ||
+ error == EHOSTUNREACH)
+ {
+ fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n",
+ hostname, delay);
+ sleep(delay);
+
+ if (delay < 30)
+ delay += 5;
+ }
+ else
+ {
+ perror("ERROR: Unable to connect to printer (retrying in 30 seconds)");
+ sleep(30);
+ }
+ }
+ else
+ break;
+ }
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (argc < 7)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ /*
+ * Finally, send the print file...
+ */
+
+ copies --;
+
+ if (fp != 0)
+ {
+ fputs("PAGE: 1 1\n", stderr);
+ lseek(fp, 0, SEEK_SET);
+ }
+
+ fputs("INFO: Connected to host, sending print job...\n", stderr);
+
+ tbytes = 0;
+ while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
+ {
+ /*
+ * Write the print data to the printer...
+ */
+
+ tbytes += nbytes;
+ bufptr = buffer;
+
+ while (nbytes > 0)
+ {
+ if ((wbytes = send(fd, bufptr, nbytes, 0)) < 0)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+ }
+
+ if (wbytes < 0)
+ break;
+
+ /*
+ * Check for possible data coming back from the printer...
+ */
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&input);
+ FD_SET(fd, &input);
+ if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+ {
+ /*
+ * Grab the data coming back and spit it out to stderr...
+ */
+
+ if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
+ {
+ fprintf(stderr, "INFO: Received %d bytes of back-channel data!\n",
+ nbytes);
+ print_backchannel((unsigned char *)buffer, nbytes);
+ }
+ }
+ else if (argc > 6)
+ fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
+ (unsigned long)tbytes);
+ }
+
+ /*
+ * Shutdown the socket and wait for the other end to finish...
+ */
+
+ fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr);
+
+ shutdown(fd, 1);
+
+ for (;;)
+ {
+ /*
+ * Wait a maximum of 90 seconds for backchannel data or a closed
+ * connection...
+ */
+
+ timeout.tv_sec = 90;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&input);
+ FD_SET(fd, &input);
+
+#ifdef __hpux
+ if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
+#else
+ if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+#endif /* __hpux */
+ {
+ /*
+ * Grab the data coming back and spit it out to stderr...
+ */
+
+ if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
+ {
+ fprintf(stderr, "INFO: Received %d bytes of back-channel data!\n",
+ nbytes);
+ print_backchannel((unsigned char *)buffer, nbytes);
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Close the socket connection...
+ */
+
+ close(fd);
+ }
+
+ /*
+ * Close the input file and return...
+ */
+
+ if (fp != 0)
+ close(fp);
+
+ return (wbytes < 0);
+}
+
+
+/*
+ * 'print_backchannel()' - Print the contents of a back-channel buffer.
+ */
+
+void
+print_backchannel(const unsigned char *buffer, /* I - Data buffer */
+ int nbytes) /* I - Number of bytes */
+{
+ char line[255], /* Formatted line */
+ *lineptr; /* Pointer into line */
+
+
+ for (lineptr = line; nbytes > 0; buffer ++, nbytes --)
+ {
+ if (*buffer < 0x20 || *buffer >= 0x7f)
+ {
+ snprintf(lineptr, sizeof(line) - (lineptr - line), "<%02X>", *buffer);
+ lineptr += strlen(lineptr);
+ }
+ else
+ *lineptr++ = *buffer;
+
+ if ((lineptr - line) > 72)
+ {
+ *lineptr = '\0';
+ fprintf(stderr, "DEBUG: DATA: %s\n", line);
+ lineptr = line;
+ }
+ }
+
+ if (lineptr > line)
+ {
+ *lineptr = '\0';
+ fprintf(stderr, "DEBUG: DATA: %s\n", line);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c
new file mode 100644
index 000000000..897328c5c
--- /dev/null
+++ b/backend/usb-darwin.c
@@ -0,0 +1,1899 @@
+/*
+ * "$Id$"
+ *
+ * USB port on Darwin backend for the Common UNIX Printing System (CUPS).
+ *
+ * This file is included from "usb.c" when compiled on MacOS X or Darwin.
+ *
+ * Copyright 2004 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.
+ *
+ * Contents:
+ *
+ * print_device() - Send a file to the specified USB port.
+ * list_devices() - List all USB devices.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <pthread.h> /* Used for writegReadMutex */
+
+#ifndef kPMPrinterURI
+# define kPMPrinterURI CFSTR("Printer URI")
+#endif
+
+/*
+ * Panther/10.3 kIOUSBInterfaceInterfaceID190
+ * Jaguar/10.2 kIOUSBInterfaceInterfaceID182
+ */
+
+#define USB_INTERFACE_KIND CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID190)
+#define kUSBLanguageEnglish 0x409
+
+/*
+ * Section 5.3 USB Printing Class spec
+ */
+
+#define kUSBPrintingSubclass 1
+#define kUSBPrintingProtocolNoOpen 0
+#define kUSBPrintingProtocolUnidirectional 1
+#define kUSBPrintingProtocolBidirectional 2
+
+#define kUSBPrintClassGetDeviceID 0
+#define kUSBPrintClassGetCentronicsStatus 1
+#define kUSBPrintClassSoftReset 2
+
+/*
+ * Apple MacOS X printer-class plugins
+ */
+
+#define kUSBPrinterClassTypeID (CFUUIDGetConstantUUIDWithBytes(NULL, 0x06, 0x04, 0x7D, 0x16, 0x53, 0xA2, 0x11, 0xD6, 0x92, 0x06, 0x00, 0x30, 0x65, 0x52, 0x45, 0x92))
+
+#define kUSBPrinterClassInterfaceID (CFUUIDGetConstantUUIDWithBytes(NULL, 0x03, 0x34, 0x6D, 0x74, 0x53, 0xA3, 0x11, 0xD6, 0x9E, 0xA1, 0x76, 0x30, 0x65, 0x52, 0x45, 0x92))
+
+#define kUSBGenericPrinterClassDriver CFSTR("/System/Library/Printers/Libraries/USBGenericPrintingClass.plugin")
+#define kUSBGenericTOPrinterClassDriver CFSTR("/System/Library/Printers/Libraries/USBGenericTOPrintingClass.plugin")
+
+#define kUSBClassDriverProperty CFSTR("USB Printing Class")
+#define kUSBPrinterClassDeviceNotOpen -9664 /*kPMInvalidIOMContext*/
+
+typedef union
+{
+ char b;
+ struct
+ {
+ unsigned reserved0 : 2;
+ unsigned paperError : 1;
+ unsigned select : 1;
+ unsigned notError : 1;
+ unsigned reserved1 : 3;
+ } status;
+} CentronicsStatusByte;
+
+typedef struct
+{
+ CFStringRef manufacturer; /* manufacturer name */
+ CFStringRef product; /* product name */
+ CFStringRef compatible; /* compatible product name */
+ CFStringRef serial; /* serial number */
+ CFStringRef command; /* command set */
+ CFStringRef ppdURL; /* url of the selected PPD, if any */
+} USBPrinterAddress;
+
+typedef IOUSBInterfaceInterface190 **USBPrinterInterface;
+
+typedef struct
+{
+ UInt8 requestType;
+ UInt8 request;
+ UInt16 value;
+ UInt16 index;
+ UInt16 length;
+ void *buffer;
+} USBIODeviceRequest;
+
+typedef struct classDriverContext
+{
+ IUNKNOWN_C_GUTS;
+ CFPlugInRef plugin; /* release plugin */
+ IUnknownVTbl **factory;
+ void *vendorReference;/* vendor class specific usage */
+ UInt32 location; /* unique location in bus topology */
+ UInt8 interfaceNumber;
+ UInt16 vendorID;
+ UInt16 productID;
+ USBPrinterInterface interface; /* identify the device to IOKit */
+ UInt8 outpipe; /* mandatory bulkOut pipe */
+ UInt8 inpipe; /* optional bulkIn pipe */
+ /*
+ ** general class requests
+ */
+ kern_return_t (*DeviceRequest)( struct classDriverContext **printer, USBIODeviceRequest *iorequest, UInt16 timeout );
+ kern_return_t (*GetString)( struct classDriverContext **printer, UInt8 whichString, UInt16 language, UInt16 timeout, CFStringRef *result );
+ /*
+ ** standard printer class requests
+ */
+ kern_return_t (*SoftReset)( struct classDriverContext **printer, UInt16 timeout );
+ kern_return_t (*GetCentronicsStatus)( struct classDriverContext **printer, CentronicsStatusByte *result, UInt16 timeout );
+ kern_return_t (*GetDeviceID)( struct classDriverContext **printer, CFStringRef *devid, UInt16 timeout );
+ /*
+ ** standard bulk device requests
+ */
+ kern_return_t (*ReadPipe)( struct classDriverContext **printer, UInt8 *buffer, UInt32 *count );
+ kern_return_t (*WritePipe)( struct classDriverContext **printer, UInt8 *buffer, UInt32 *count, Boolean eoj );
+ /*
+ ** interface requests
+ */
+ kern_return_t (*Open)( struct classDriverContext **printer, UInt32 location, UInt8 protocol );
+ kern_return_t (*Abort)( struct classDriverContext **printer );
+ kern_return_t (*Close)( struct classDriverContext **printer );
+ /*
+ ** initialize and terminate
+ */
+ kern_return_t (*Initialize)( struct classDriverContext **printer, struct classDriverContext **baseclass );
+ kern_return_t (*Terminate)( struct classDriverContext **printer );
+} USBPrinterClassContext;
+
+
+typedef struct usbPrinterClassType
+{
+ USBPrinterClassContext *classdriver;
+ CFUUIDRef factoryID;
+ UInt32 refCount;
+} USBPrinterClassType;
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Constants
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/*
+ Debugging output to Console
+ DEBUG undefined or
+ DEBUG=0 production code: suppress console output
+
+ DEBUG=1 report errors (non-zero results)
+ DEBUG=2 report all results, generate dumps
+*/
+#if DEBUG==2
+#define DEBUG_ERR(c, x) showint(x, c)
+#define DEBUG_DUMP( text, buf, len ) dump( text, buf, len )
+#define DEBUG_CFString( text, a ) showcfstring( text, a )
+#define DEBUG_CFCompareString( text, a, b ) cmpcfs( text, a, b )
+#elif DEBUG==1
+#define DEBUG_ERR(c, x) if (c) fprintf(stderr, x, c)
+#define DEBUG_DUMP( text, buf, len )
+#define DEBUG_CFString( text, a )
+#define DEBUG_CFCompareString( text, a, b )
+#else
+#define DEBUG_ERR(c, x)
+#define DEBUG_DUMP( text, buf, len )
+#define DEBUG_CFString( text, a )
+#define DEBUG_CFCompareString( text, a, b )
+#endif
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Type Definitions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+typedef struct
+{
+ /*
+ * Tagged/Tranparent Binary Communications Protocol
+ * TBCP read
+ */
+ Boolean tbcpQuoteReads; /* enable tbcp on reads */
+ Boolean escapeNextRead; /* last char of last read buffer was escape */
+ UInt8 *tbcpReadData; /* read buffer */
+ UInt32 readLength; /* read buffer length (all used) */
+ int match_endoffset, /* partial match of end TBCP sequence */
+ match_startoffset; /* partial match of start TBCP sequence */
+ /*
+ * TBCP write
+ */
+ UInt8 *tbcpWriteData; /* write buffer */
+ UInt32 tbcpBufferLength, /* write buffer allocated length */
+ tbcpBufferRemaining; /* write buffer not used */
+
+ Boolean sendStatusNextWrite;
+
+} PostScriptData;
+
+typedef struct
+{
+ CFPlugInRef plugin; /* valid until plugin is release */
+ USBPrinterClassContext **classdriver; /* usb printer class in user space */
+ CFStringRef bundle; /* class driver URI */
+ UInt32 location; /* unique location in USB topology */
+ USBPrinterAddress address; /* topology independent bus address */
+ CFURLRef reference; /* internal use */
+} USBPrinterInfo;
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/*
+** IOKit to CF functions
+*/
+USBPrinterInfo *UsbCopyPrinter( USBPrinterInfo *aPrinter );
+CFMutableArrayRef UsbGetAllPrinters( void );
+void UsbReleasePrinter( USBPrinterInfo *aPrinter );
+void UsbReleaseAllPrinters( CFMutableArrayRef printers );
+kern_return_t UsbRegistryOpen( USBPrinterAddress *usbAddress, USBPrinterInfo **result );
+kern_return_t UsbUnloadClassDriver( USBPrinterInfo *printer );
+kern_return_t UsbLoadClassDriver( USBPrinterInfo *printer, CFUUIDRef interfaceID, CFStringRef classDriverBundle );
+CFStringRef UsbMakeFullUriAddress( USBPrinterInfo *aPrinter );
+
+int UsbSamePrinter( const USBPrinterAddress *lastTime, const USBPrinterAddress *thisTime );
+
+OSStatus UsbGetPrinterAddress( USBPrinterInfo *thePrinter, USBPrinterAddress *address, UInt16 timeout );
+
+
+/*******************************************************************************
+ Contains: Support IEEE-1284 DeviceID as a CFString.
+
+ Copyright 2000-2002 by Apple Computer, Inc., all rights reserved.
+
+ Description:
+ IEEE-1284 Device ID is referenced in USB and PPDT (1394.3). It allows
+ a computer peripheral to convey information about its required software
+ to the host system.
+
+ DeviceID is defined as a stream of ASCII bytes, commencing with one 16-bit
+ binary integer in Little-Endian format which describes how many bytes
+ of data are required by the entire DeviceID.
+
+ The stream of bytes is further characterized as a series of
+ key-value list pairs. In other words each key can be followed by one
+ or more values. Multiple key-value list pairs fill out the DeviceID stream.
+
+ Some keys are required: COMMAND SET (or CMD), MANUFACTURER (or MFG),
+ and MODEL (or MDL).
+
+ One needs to read the first two bytes of DeviceID to allocate storage
+ for the complete DeviceID string. Then a second read operation can
+ retrieve the entire string.
+
+ Often DeviceID is not very large. By allocating a reasonable buffer one
+ can fetch most device's DeviceID string on the first read.
+
+ A more formal definition of DeviceID.
+
+ <DeviceID> = <Length><Key_ValueList_Pair>+
+
+ <Length> = <low byte of 16 bit integer><high byte of 16 bit integer>
+ <Key_ValueList_Pair> = <Key>:<Value>[,<Value>]*;
+
+ <Key> = <ASCII Byte>+
+ <Value> = <ASCII Byte>+
+
+ Some keys are defined in the standard. The standard specifies that
+ keys are case sensitive. White space is allowed in the key.
+
+ The standard does not say that values are case-sensitive.
+ Lexmark is known to ship printers with mixed-case value:
+ i.e., 'CLASS:Printer'
+
+ Required Keys:
+ 'COMMAND SET' or CMD
+ MANUFACTURER or MFG
+ MODEL or MDL
+
+ Optional Keys:
+ CLASS
+ Value PRINTER is referenced in the standard.
+
+ Observed Keys:
+ SN,SERN
+ Used by Hewlett-Packard for the serial number.
+
+
+*******************************************************************************/
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Pragmas
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Constants
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#define kDeviceIDKeyCommand CFSTR("COMMAND SET:")
+#define kDeviceIDKeyCommandAbbrev CFSTR( "CMD:" )
+
+#define kDeviceIDKeyManufacturer CFSTR("MANUFACTURER:")
+#define kDeviceIDKeyManufacturerAbbrev CFSTR( "MFG:" )
+
+#define kDeviceIDKeyModel CFSTR("MODEL:")
+#define kDeviceIDKeyModelAbbrev CFSTR( "MDL:" )
+
+#define kDeviceIDKeySerial CFSTR("SN:")
+#define kDeviceIDKeySerialAbbrev CFSTR("SERN:")
+
+#define kDeviceIDKeyCompatible CFSTR("COMPATIBLITY ID:")
+#define kDeviceIDKeyCompatibleAbbrev CFSTR("CID:")
+
+/* delimiters */
+#define kDeviceIDKeyValuePairDelimiter CFSTR(";")
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Type definitions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Function prototypes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+static CFStringRef CreateEncodedCFString(CFStringRef string);
+static CFRange DelimitSubstring( CFStringRef stringToSearch, CFStringRef delim, CFRange bounds, CFStringCompareFlags options );
+static void parseOptions(const char *options, char *serial);
+
+CFStringRef
+DeviceIDCreateValueList( const CFStringRef deviceID,
+ const CFStringRef abbrevKey,
+ const CFStringRef key );
+
+static int addPercentEscapes(const unsigned char* src, char* dst, int dstMax);
+static int removePercentEscapes(const char* src, unsigned char* dst, int dstMax);
+
+/* Required to suppress redefinition warnings for these two symbols
+*/
+#if defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
+
+#include <cups/cups.h>
+
+
+#define PRINTER_POLLING_INTERVAL 5 /* seconds */
+#define INITIAL_LOG_INTERVAL (PRINTER_POLLING_INTERVAL)
+#define SUBSEQUENT_LOG_INTERVAL (3*INITIAL_LOG_INTERVAL)
+
+/* WAITEOF_DELAY is number of seconds we'll wait for responses from the printer */
+/* after we've finished sending all the data */
+#define WAITEOF_DELAY 7
+
+#define USB_MAX_STR_SIZE 1024
+
+
+static volatile int done = 0;
+static int gWaitEOF = false;
+static pthread_cond_t *gReadCompleteConditionPtr = NULL;
+static pthread_mutex_t *gReadMutexPtr = NULL;
+
+
+
+#if DEBUG==2
+
+static char
+hexdigit( char c )
+{
+ return ( c < 0 || c > 15 )? '?': (c < 10)? c + '0': c - 10 + 'A';
+}
+
+static char
+asciidigit( char c )
+{
+ return (c< 20 || c > 0x7E)? '.': c;
+}
+
+void
+dump( char *text, void *s, int len )
+{
+ int i;
+ char *p = (char *) s;
+ char m[1+2*16+1+16+1];
+
+ fprintf( stderr, "%s pointer %x len %d\n", text, (unsigned int) p, len );
+
+ for ( ; len > 0; len -= 16 )
+ {
+ char *q = p;
+ char *out = m;
+ *out++ = '\t';
+ for ( i = 0; i < 16 && i < len; ++i, ++p )
+ {
+ *out++ = hexdigit( (*p >> 4) & 0x0F );
+ *out++ = hexdigit( *p & 0x0F );
+ }
+ for ( ;i < 16; ++i )
+ {
+ *out++ = ' ';
+ *out++ = ' ';
+ }
+ *out++ = '\t';
+ for ( i = 0; i < 16 && i < len; ++i, ++q )
+ *out++ = asciidigit( *q );
+ *out = 0;
+ m[ strlen( m ) ] = '\0';
+ fprintf( stderr, "%s\n", m );
+ }
+}
+
+void
+printcfs( char *text, CFStringRef s )
+{
+ char dest[1024];
+ if ( s != NULL )
+ {
+ if ( CFStringGetCString(s, dest, sizeof(dest), kCFStringEncodingUTF8) )
+ sprintf( dest, "%s <%s>\n", text, dest );
+ else
+ sprintf( dest, "%s [Unknown string]\n", text );
+ } else {
+ sprintf( dest, "%s [NULL]\n", text );
+ }
+ perror( dest );
+}
+
+void
+cmpcfs( char *text, CFStringRef a, CFStringRef b )
+{
+ CFRange found = {0, 0};
+
+ printcfs( text, a );
+ printcfs( " ", b );
+
+ if (a != NULL && b != NULL) {
+ found = CFStringFind( a, b, kCFCompareCaseInsensitive );
+
+ } else if (a == NULL && b == NULL) {
+ found.length = 1; /* Match */
+ found.location = 0;
+ } else {
+ found.length = 0; /* No match. */
+ }
+
+ if ( found.length > 0 )
+ fprintf( stderr, "matched @%d:%d\n", (int) found.location, (int) found.length);
+ else
+ fprintf( stderr, "not matched\n" );
+}
+#endif /*DEBUG==2 */
+
+#ifdef PARSE_PS_ERRORS
+static const char *nextLine (const char *buffer);
+static void parsePSError (char *sockBuffer, int len);
+
+
+static const char *nextLine (const char *buffer)
+{
+ const char *cptr, *lptr = NULL;
+ for (cptr = buffer; *cptr && lptr == NULL; cptr++)
+ if (*cptr == '\n' || *cptr == '\r')
+ lptr = cptr;
+ return lptr;
+}
+
+static void parsePSError (char *sockBuffer, int len)
+{
+ static char gErrorBuffer[1024] = "";
+ static char *gErrorBufferPtr = gErrorBuffer;
+ static char *gErrorBufferEndPtr = gErrorBuffer + sizeof(gErrorBuffer);
+
+ char *pCommentBegin, *pCommentEnd, *pLineEnd;
+ char *logLevel;
+ char logstr[1024];
+ int logstrlen;
+
+ if (gErrorBufferPtr + len > gErrorBufferEndPtr - 1)
+ gErrorBufferPtr = gErrorBuffer;
+ if (len > sizeof(gErrorBuffer) - 1)
+ len = sizeof(gErrorBuffer) - 1;
+
+ memcpy(gErrorBufferPtr, (const void *)sockBuffer, len);
+ gErrorBufferPtr += len;
+ *(gErrorBufferPtr + 1) = '\0';
+
+
+ pLineEnd = (char *)nextLine((const char *)gErrorBuffer);
+ while (pLineEnd != NULL)
+ {
+ *pLineEnd++ = '\0';
+
+ pCommentBegin = strstr(gErrorBuffer,"%%[");
+ pCommentEnd = strstr(gErrorBuffer, "]%%");
+ if (pCommentBegin != gErrorBuffer && pCommentEnd != NULL)
+ {
+ pCommentEnd += 3; /* Skip past "]%%" */
+ *pCommentEnd = '\0'; /* There's always room for the nul */
+
+ if (strncasecmp(pCommentBegin, "%%[ Error:", 10) == 0)
+ logLevel = "DEBUG";
+ else if (strncasecmp(pCommentBegin, "%%[ Flushing", 12) == 0)
+ logLevel = "DEBUG";
+ else
+ logLevel = "INFO";
+
+ if ((logstrlen = snprintf(logstr, sizeof(logstr), "%s: %s\n", logLevel, pCommentBegin)) >= sizeof(logstr))
+ {
+ /* If the string was trucnated make sure it has a linefeed before the nul */
+ logstrlen = sizeof(logstr) - 1;
+ logstr[logstrlen - 1] = '\n';
+ }
+ write(STDERR_FILENO, logstr, logstrlen);
+ }
+
+ /* move everything over... */
+ strcpy(gErrorBuffer, pLineEnd);
+ gErrorBufferPtr = gErrorBuffer;
+ pLineEnd = (char *)nextLine((const char *)gErrorBuffer);
+ }
+}
+#endif /* PARSE_PS_ERRORS */
+
+void *
+readthread( void *reference )
+{
+ /*
+ ** post a read to the device and write results to stdout
+ ** the final pending read will be Aborted in the main thread
+ */
+ UInt8 readbuffer[512];
+ UInt32 rbytes;
+ kern_return_t readstatus;
+ USBPrinterClassContext **classdriver = (USBPrinterClassContext **) reference;
+
+
+ do
+ {
+ rbytes = sizeof(readbuffer) - 1;
+ readstatus = (*classdriver)->ReadPipe( classdriver, readbuffer, &rbytes );
+ if ( kIOReturnSuccess == readstatus && rbytes > 0 )
+ {
+ write( STDOUT_FILENO, readbuffer, rbytes );
+ /* cntrl-d is echoed by the printer.
+ * NOTES:
+ * Xerox Phaser 6250D doesn't echo the cntrl-d.
+ * Xerox Phaser 6250D doesn't always send the product query.
+ */
+ if (gWaitEOF && readbuffer[rbytes-1] == 0x4)
+ break;
+#ifdef PARSE_PS_ERRORS
+ parsePSError(readbuffer, rbytes);
+#endif
+ }
+ } while ( gWaitEOF || !done ); /* Abort from main thread tests error here */
+
+ /* Let the other thread (main thread) know that we have
+ * completed the read thread...
+ */
+ pthread_mutex_lock(gReadMutexPtr);
+ pthread_cond_signal(gReadCompleteConditionPtr);
+ pthread_mutex_unlock(gReadMutexPtr);
+
+ return NULL;
+}
+
+/*
+* 'print_device()' - Send a file to the specified USB port.
+*/
+
+int print_device(const char *uri, const char *hostname, const char *resource, const char *options, int fd, int copies)
+{
+ UInt32 wbytes, /* Number of bytes written */
+ buffersize = 2048;
+ size_t nbytes; /* Number of bytes read */
+ off_t tbytes; /* Total number of bytes written */
+ char *buffer, /* Output buffer */
+ *bufptr; /* Pointer into buffer */
+
+ pthread_cond_t readCompleteCondition;
+ pthread_mutex_t readMutex;
+ pthread_t thr;
+ int thread_created = 0;
+
+ USBPrinterInfo *targetPrinter = NULL;
+ CFMutableArrayRef usbPrinters;
+ char manufacturer_buf[USB_MAX_STR_SIZE],
+ product_buf[USB_MAX_STR_SIZE],
+ serial_buf[USB_MAX_STR_SIZE];
+ CFStringRef manufacturer;
+ CFStringRef product;
+ CFStringRef serial;
+
+ OSStatus status = noErr;
+
+
+ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+ fprintf(stderr, "INFO: Opening the print file and connection...\n");
+
+ parseOptions(options, serial_buf);
+
+ if (resource[0] == '/')
+ resource++;
+
+ removePercentEscapes(hostname, manufacturer_buf, sizeof(manufacturer_buf));
+ removePercentEscapes(resource, product_buf, sizeof(product_buf));
+
+ manufacturer = CFStringCreateWithCString(NULL, manufacturer_buf, kCFStringEncodingUTF8);
+ product = CFStringCreateWithCString(NULL, product_buf, kCFStringEncodingUTF8);
+ serial = CFStringCreateWithCString(NULL, serial_buf, kCFStringEncodingUTF8);
+
+ USBPrinterInfo *activePrinter = NULL;
+ USBPrinterClassContext **classdriver;
+ int countdown = INITIAL_LOG_INTERVAL;
+ do
+ {
+ /* */
+ /* given a manufacturer and product, bind to a specific printer on the bus */
+ /* */
+ usbPrinters = UsbGetAllPrinters();
+ /* */
+ /* if we have at least one element of the URI, find a printer module that matches */
+ /* */
+ if ( NULL != usbPrinters && (manufacturer || product ) )
+ {
+ int i,
+ numPrinters = CFArrayGetCount(usbPrinters);
+ for ( i = 0; i < numPrinters; ++i )
+ {
+ int match = FALSE;
+ USBPrinterInfo *printer = (USBPrinterInfo *) CFArrayGetValueAtIndex( usbPrinters, i );
+ if ( printer )
+ {
+ match = printer->address.manufacturer && manufacturer? CFEqual(printer->address.manufacturer, manufacturer ): FALSE;
+ if ( match )
+ {
+ match = printer->address.product && product? CFEqual(printer->address.product, product ): FALSE;
+ }
+ if ( match && serial )
+ {
+ /* Note with old queues (pre Panther) the CUPS uri may have no serial number (serial==NULL). */
+ /* In this case, we will ignore serial number (as before), and we'll match to the first */
+ /* printer that agrees with manufacturer and product. */
+ /* If the CUPS uri does include a serial number, we'll enter this clause */
+ /* which requires the printer's serial number to match the CUPS serial number. */
+ /* The net effect is that for printers with a serial number, */
+ /* new queues must match the serial number, while old queues match any printer */
+ /* that satisfies the manufacturer/product match. */
+ /* */
+ match = printer->address.serial? CFEqual(printer->address.serial, serial ): FALSE;
+ }
+ if ( match )
+ {
+ targetPrinter = UsbCopyPrinter( printer );
+ break; /* for, compare partial address to address for each printer on usb bus */
+ }
+ }
+ }
+ }
+ UsbReleaseAllPrinters( usbPrinters );
+ if ( NULL != targetPrinter )
+ status = UsbRegistryOpen( &targetPrinter->address, &activePrinter );
+
+ if ( NULL == activePrinter )
+ {
+ sleep( PRINTER_POLLING_INTERVAL );
+ countdown -= PRINTER_POLLING_INTERVAL;
+ if ( !countdown )
+ {
+ /* periodically, write to the log so someone knows we're waiting */
+ if (NULL == targetPrinter)
+ fprintf( stderr, "WARNING: Printer not responding\n" );
+ else
+ fprintf( stderr, "INFO: Printer busy\n" );
+ countdown = SUBSEQUENT_LOG_INTERVAL; /* subsequent log entries, every 30 minutes */
+ }
+ }
+ } while ( NULL == activePrinter );
+
+ classdriver = activePrinter->classdriver;
+ if ( NULL == classdriver )
+ {
+ perror("ERROR: Unable to open USB Printing Class port");
+ return (status);
+ }
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (fd != 0)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+ buffer = malloc( buffersize );
+ if ( !buffer ) {
+ fprintf( stderr, "ERROR: Couldn't allocate internal buffer\n" );
+ status = -1;
+ }
+ else
+ {
+ fprintf(stderr, "INFO: Sending the print file...\n");
+ if (pthread_cond_init(&readCompleteCondition, NULL) == 0)
+ {
+ gReadCompleteConditionPtr = &readCompleteCondition;
+
+ if (pthread_mutex_init(&readMutex, NULL) == 0)
+ {
+ gReadMutexPtr = &readMutex;
+
+ if (pthread_create(&thr, NULL, readthread, classdriver ) > 0)
+ fprintf(stderr, "WARNING: Couldn't create read channel\n");
+ else
+ thread_created = 1;
+ }
+ }
+ }
+ /*
+ * the main thread sends the print file...
+ */
+ while (noErr == status && copies > 0)
+ {
+ copies --;
+ if (STDIN_FILENO != fd)
+ {
+ fputs("PAGE: 1 1", stderr);
+ lseek( fd, 0, SEEK_SET ); /* rewind */
+ }
+
+ tbytes = 0;
+ while (noErr == status && (nbytes = read(fd, buffer, buffersize)) > 0)
+ {
+ /*
+ * Write the print data to the printer...
+ */
+
+ tbytes += nbytes;
+ bufptr = buffer;
+
+ while (nbytes > 0 && noErr == status )
+ {
+ wbytes = nbytes;
+ status = (*classdriver)->WritePipe( classdriver, (UInt8*)bufptr, &wbytes, 0 /*nbytes > wbytes? 0: feof(fp)*/ );
+ if (wbytes < 0 || noErr != status)
+ {
+ OSStatus err;
+ err = (*classdriver)->Abort( classdriver );
+ fprintf(stderr, "ERROR: %ld: Unable to send print file to printer (canceled %ld)\n", status, err );
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+ }
+
+ if (fd != 0 && noErr == status)
+ fprintf(stderr, "INFO: Sending print file, %qd bytes...\n", (off_t)tbytes);
+ }
+ }
+ done = 1; /* stop scheduling reads */
+
+ if ( thread_created )
+ {
+ /* Give the read thread WAITEOF_DELAY seconds to complete all the data. If
+ * we are not signaled in that time then force the thread to exit by setting
+ * the waiteof to be false. Plese note that this relies on us using the timeout
+ * class driver.
+ */
+ struct timespec sleepUntil = { time(NULL) + WAITEOF_DELAY, 0 };
+ pthread_mutex_lock(&readMutex);
+ if (pthread_cond_timedwait(&readCompleteCondition, &readMutex, (const struct timespec *)&sleepUntil) != 0)
+ gWaitEOF = false;
+ pthread_mutex_unlock(&readMutex);
+ pthread_join( thr,NULL); /* wait for the child thread to return */
+ }
+
+ (*classdriver)->Close( classdriver ); /* forces the read to stop incase we are doing a blocking read */
+ UsbUnloadClassDriver( activePrinter );
+ /*
+ * Close the socket connection and input file and return...
+ */
+ free( buffer );
+
+ if (STDIN_FILENO != fd)
+ close(fd);
+
+ if (gReadCompleteConditionPtr != NULL)
+ pthread_cond_destroy(gReadCompleteConditionPtr);
+ if (gReadMutexPtr != NULL)
+ pthread_mutex_destroy(gReadMutexPtr);
+
+ return status == kIOReturnSuccess? 0: status;
+}
+
+static Boolean
+encodecfstr( CFStringRef cfsrc, char *dst, long len )
+{
+ return CFStringGetCString(cfsrc, dst, len, kCFStringEncodingUTF8 );
+}
+
+/*
+* 'list_devices()' - List all USB devices.
+*/
+void list_devices(void)
+{
+ char encodedManufacturer[1024];
+ char encodedProduct[1024];
+ char uri[1024];
+ CFMutableArrayRef usbBusPrinters = UsbGetAllPrinters();
+ CFIndex i, numPrinters = NULL != usbBusPrinters? CFArrayGetCount( usbBusPrinters ): 0;
+
+ puts("direct usb \"Unknown\" \"USB Printer (usb)\"");
+ for ( i = 0; i < numPrinters; ++i )
+ {
+ USBPrinterInfo *printer = (USBPrinterInfo *) CFArrayGetValueAtIndex( usbBusPrinters, i );
+
+ if ( printer )
+ {
+ CFStringRef addressRef = UsbMakeFullUriAddress( printer );
+ if ( addressRef )
+ {
+ if ( CFStringGetCString(addressRef, uri, sizeof(uri), kCFStringEncodingUTF8) ) {
+
+ encodecfstr( printer->address.manufacturer, encodedManufacturer, sizeof(encodedManufacturer) );
+ encodecfstr( printer->address.product, encodedProduct, sizeof(encodedProduct) );
+ printf("direct %s \"%s %s\" \"%s\"\n", uri, encodedManufacturer, encodedProduct, encodedProduct);
+ }
+ }
+ }
+ }
+ UsbReleaseAllPrinters( usbBusPrinters );
+ fflush(NULL);
+}
+
+
+static void parseOptions(const char *options, char *serial)
+{
+ char *serialnumber; /* ?serial=<serial> or ?location=<location> */
+ char optionName[255], /* Name of option */
+ value[255], /* Value of option */
+ *ptr; /* Pointer into name or value */
+
+ if (serial)
+ *serial = '\0';
+
+ if (!options)
+ return;
+
+ serialnumber = NULL;
+
+ while (*options != '\0')
+ {
+ /*
+ * Get the name...
+ */
+ for (ptr = optionName; *options && *options != '=' && *options != '+'; )
+ *ptr++ = *options++;
+
+ *ptr = '\0';
+ value[0] = '\0';
+
+ if (*options == '=')
+ {
+ /*
+ * Get the value...
+ */
+
+ options ++;
+
+ for (ptr = value; *options && *options != '+';)
+ *ptr++ = *options++;
+
+ *ptr = '\0';
+
+ if (*options == '+')
+ options ++;
+ }
+ else if (*options == '+')
+ {
+ options ++;
+ }
+
+ /*
+ * Process the option...
+ */
+ if (strcasecmp(optionName, "waiteof") == 0)
+ {
+ if (strcasecmp(value, "on") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ strcasecmp(value, "true") == 0)
+ {
+ gWaitEOF = true;
+ }
+ else if (strcasecmp(value, "off") == 0 ||
+ strcasecmp(value, "no") == 0 ||
+ strcasecmp(value, "false") == 0)
+ {
+ gWaitEOF = false;
+ }
+ else
+ {
+ fprintf(stderr, "WARNING: Boolean expected for waiteof option \"%s\"\n", value);
+ }
+ }
+ else if (strcasecmp(optionName, "serial") == 0 ||
+ strcasecmp(optionName, "location") == 0 )
+ {
+ strcpy(serial, value);
+ serialnumber = serial;
+ }
+ }
+
+ return;
+}
+
+
+/*!
+ * @function addPercentEscapes
+ * @abstract Encode a string with percent escapes
+ *
+ * @param src The source C string
+ * @param dst Desination buffer
+ * @param dstMax Size of desination buffer
+ *
+ * @result A non-zero return value for errors
+ */
+static int addPercentEscapes(const unsigned char* src, char* dst, int dstMax)
+{
+ unsigned char c;
+ char *dstEnd = dst + dstMax - 1; /* -1 to leave room for the NUL */
+
+ while (*src)
+ {
+ c = *src++;
+
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || (c == '.' || c == '-' || c == '*' || c == '_'))
+ {
+ if (dst >= dstEnd)
+ return -1;
+
+ *dst++ = c;
+ }
+ else
+ {
+ if (dst >= dstEnd - 2)
+ return -1;
+
+ snprintf(dst, dstEnd - dst, "%%%02x", c);
+ dst += 3;
+ }
+ }
+
+ *dst = '\0';
+ return 0;
+}
+
+
+/*!
+ * @function removePercentEscapes
+ * @abstract Returns a string with any percent escape sequences replaced with their equivalent character
+ *
+ * @param src Source buffer
+ * @param srclen Number of bytes in source buffer
+ * @param dst Desination buffer
+ * @param dstMax Size of desination buffer
+ *
+ * @result A non-zero return value for errors
+ */
+static int removePercentEscapes(const char* src, unsigned char* dst, int dstMax)
+{
+ int c;
+ const unsigned char *dstEnd = dst + dstMax;
+
+ while (*src && dst < dstEnd)
+ {
+ c = *src++;
+
+ if (c == '%')
+ {
+ sscanf(src, "%02x", &c);
+ src += 2;
+ }
+ *dst++ = (char)c;
+ }
+
+ if (dst >= dstEnd)
+ return -1;
+
+ *dst = '\0';
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------*
+
+ DelimitSubstring
+
+ Desc: Search a string from a starting location, looking for a given
+ delimiter. Return the range from the start of the search to the
+ delimiter, or end of string (whichever is shorter).
+
+ In: stringToSearch string which contains a substring that we search
+ delim string which marks the end of the string
+ bounds start and length of substring of stringToSearch
+ options case sensitive, anchored, etc.
+
+ Out: Range up to the delimiter.
+
+*-----------------------------------------------------------------------------*/
+static CFRange
+DelimitSubstring( CFStringRef stringToSearch, CFStringRef delim, CFRange bounds, CFStringCompareFlags options )
+{
+ CFRange where_delim, /* where the delimiter was found */
+ value;
+ /* */
+ /* trim leading space by changing bounds */
+ /* */
+ while ( bounds.length > 0 && CFStringFindWithOptions( stringToSearch, CFSTR(" "), bounds, kCFCompareAnchored, &where_delim ) )
+ {
+ ++bounds.location; /* drop a leading ' ' */
+ --bounds.length;
+ }
+ value = bounds; /* assume match to the end of string, may be NULL */
+ /* */
+ /* find the delimiter in the remaining string */
+ /* */
+ if ( bounds.length > 0 && CFStringFindWithOptions( stringToSearch, delim, bounds, options, &where_delim ) )
+ {
+ /* */
+ /* match to the delimiter */
+ /* */
+ value.length = where_delim.location /* delim */ - bounds.location /* start of search */;
+ }
+ DEBUG_CFString( "\tFind target", stringToSearch );
+ DEBUG_CFString( "\tFind pattern", delim );
+ DEBUG_ERR( (int) value.location, "\t\tFound %d\n" );
+ DEBUG_ERR( (int) value.length, " length %d" );
+
+ return value;
+}
+
+
+/*-----------------------------------------------------------------------------*
+
+ DeviceIDCreateValueList
+
+ Desc: Create a new string for the value list of the specified key.
+ The key may be specified as two strings (an abbreviated form
+ and a standard form). NULL can be passed for either form of
+ the key.
+
+ (Although passing NULL for both forms of the key is considered
+ bad form[!] it is handled correctly.)
+
+ In: deviceID the device's IEEE-1284 DeviceID key-value list
+ abbrevKey the key we're interested in (NULL allowed)
+ key
+
+ Out: CFString the value list
+ or NULL key wasn't found in deviceID
+
+*-----------------------------------------------------------------------------*/
+CFStringRef
+DeviceIDCreateValueList( const CFStringRef deviceID, const CFStringRef abbrevKey, const CFStringRef key )
+{
+ CFRange found = CFRangeMake( -1,0); /* note CFStringFind sets length 0 if string not found */
+ CFStringRef valueList = NULL;
+
+ DEBUG_CFString( "---------DeviceIDCreateValueList DeviceID:", deviceID );
+ DEBUG_CFString( "---------DeviceIDCreateValueList key:", key );
+ DEBUG_CFString( "---------DeviceIDCreateValueList abbrevkey:", abbrevKey );
+ if ( NULL != deviceID && NULL != abbrevKey )
+ found = CFStringFind( deviceID, abbrevKey, kCFCompareCaseInsensitive );
+ if ( NULL != deviceID && NULL != key && found.length <= 0 )
+ found = CFStringFind( deviceID, key, kCFCompareCaseInsensitive );
+ if ( found.length > 0 )
+ {
+ /* the key is at found */
+ /* the value follows the key until we reach the semi-colon, or end of string */
+ /* */
+ CFRange search = CFRangeMake( found.location + found.length,
+ CFStringGetLength( deviceID ) - (found.location + found.length) );
+ /* */
+ /* finally extract the string */
+ /* */
+ valueList = CFStringCreateWithSubstring ( kCFAllocatorDefault, deviceID,
+ DelimitSubstring( deviceID, kDeviceIDKeyValuePairDelimiter, search, kCFCompareCaseInsensitive ) );
+ DEBUG_CFString( "---------DeviceIDCreateValueList:", valueList );
+ }
+ return valueList;
+
+}
+
+
+
+/******************************************************************************/
+
+/*-----------------------------------------------------------------------------*
+
+CompareSameString
+
+Desc: Return the CFCompare result for two strings, either or both of which
+ can be NULL.
+
+In:
+ a current value
+ b last value
+
+Out:
+ 0 if the strings match
+ non-zero if the strings don't match
+
+*-----------------------------------------------------------------------------*/
+static int
+CompareSameString( const CFStringRef a, const CFStringRef b )
+{
+ if ( NULL == a && NULL == b )
+ return 0;
+ else if ( NULL != a && NULL != b )
+ return CFStringCompare( a, b, kCFCompareAnchored );
+ else
+ return 1; /* one of a or b is NULL this time, but wasn't last time */
+}
+
+
+/******************************************************************************/
+kern_return_t
+UsbLoadClassDriver( USBPrinterInfo *printer, CFUUIDRef interfaceID, CFStringRef classDriverBundle )
+{
+ kern_return_t kr = kUSBPrinterClassDeviceNotOpen;
+ if ( NULL != classDriverBundle )
+ printer->bundle = classDriverBundle; /* vendor-specific class override */
+ else
+#ifdef TIMEOUT
+ classDriverBundle = kUSBGenericTOPrinterClassDriver; /* supply the generic TIMEOUT class driver */
+#else
+ classDriverBundle = kUSBGenericPrinterClassDriver; /* supply the generic class driver */
+#endif
+ DEBUG_CFString( "UsbLoadClassDriver classDriverBundle", classDriverBundle );
+ if ( NULL != classDriverBundle )
+ {
+ USBPrinterClassContext **classdriver = NULL;
+ CFURLRef classDriverURL = CFURLCreateWithFileSystemPath( NULL, classDriverBundle, kCFURLPOSIXPathStyle, TRUE );
+ CFPlugInRef plugin = NULL == classDriverURL? NULL: CFPlugInCreate( NULL, classDriverURL );
+ if ( NULL != plugin)
+ {
+ /* See if this plug-in implements the Test type. */
+ CFArrayRef factories = CFPlugInFindFactoriesForPlugInTypeInPlugIn( kUSBPrinterClassTypeID, plugin );
+
+ /* If there are factories for the requested type, attempt to */
+ /* get the IUnknown interface. */
+ DEBUG_ERR( 0, "UsbLoadClassDriver plugin %x\n" );
+ if (NULL != factories && CFArrayGetCount(factories) > 0)
+ {
+ /* Get the factory ID for the first location in the array of IDs. */
+ CFUUIDRef factoryID = CFArrayGetValueAtIndex( factories, 0 );
+ /* Use the factory ID to get an IUnknown interface. */
+ /* Here the code for the PlugIn is loaded. */
+ IUnknownVTbl **iunknown = CFPlugInInstanceCreate( NULL, factoryID, kUSBPrinterClassTypeID );
+ /* If this is an IUnknown interface, query for the Test interface. */
+ DEBUG_ERR( 0, "UsbLoadClassDriver factories %x\n" );
+ if (NULL != iunknown)
+ {
+ DEBUG_ERR( 0, "UsbLoadClassDriver CFPlugInInstanceCreate %x\n" );
+ kr = (*iunknown)->QueryInterface( iunknown, CFUUIDGetUUIDBytes(interfaceID), (LPVOID *) &classdriver );
+
+ (*iunknown)->Release( iunknown );
+ if ( S_OK == kr && NULL != classdriver )
+ {
+ DEBUG_ERR( kr, "UsbLoadClassDriver QueryInterface %x\n" );
+ printer->plugin = plugin;
+ kr = (*classdriver)->Initialize( classdriver, printer->classdriver );
+
+ kr = kIOReturnSuccess;
+ printer->classdriver = classdriver;
+ }
+ else
+ {
+ DEBUG_ERR( kr, "UsbLoadClassDriver QueryInterface FAILED %x\n" );
+ }
+ }
+ else
+ {
+ DEBUG_ERR( kr, "UsbLoadClassDriver CFPlugInInstanceCreate FAILED %x\n" );
+ }
+ }
+ else
+ {
+ DEBUG_ERR( kr, "UsbLoadClassDriver factories FAILED %x\n" );
+ }
+ }
+ else
+ {
+ DEBUG_ERR( kr, "UsbLoadClassDriver plugin FAILED %x\n" );
+ }
+ if ( kr != kIOReturnSuccess || NULL == plugin || NULL == classdriver )
+ {
+ UsbUnloadClassDriver( printer );
+ }
+ }
+
+ return kr;
+}
+
+
+kern_return_t
+UsbUnloadClassDriver( USBPrinterInfo *printer )
+{
+ DEBUG_ERR( kIOReturnSuccess, "UsbUnloadClassDriver %x\n" );
+ if ( NULL != printer->classdriver )
+ (*printer->classdriver)->Release( printer->classdriver );
+ printer->classdriver = NULL;
+
+ if ( NULL != printer->plugin )
+ CFRelease( printer->plugin );
+ printer->plugin = NULL;
+
+ return kIOReturnSuccess;
+}
+
+
+/*-----------------------------------------------------------------------------*
+
+ UsbAddressDispose
+
+ Desc: deallocates anything used to create a persistent printer address
+
+ In: address the printer address we've created
+
+ Out: <none>
+
+*-----------------------------------------------------------------------------*/
+void
+UsbAddressDispose( USBPrinterAddress *address )
+{
+ if ( address->product != NULL ) CFRelease( address->product );
+ if ( address->manufacturer != NULL ) CFRelease( address->manufacturer );
+ if ( address->serial != NULL ) CFRelease( address->serial );
+ if ( address->command != NULL ) CFRelease( address->command );
+
+ address->product =
+ address->manufacturer =
+ address->serial =
+ address->command = NULL;
+
+}
+
+/*-----------------------------------------------------------------------------*
+
+ UsbGetPrinterAddress
+
+ Desc: Given a printer we're enumerating, discover it's persistent
+ reference.
+
+ A "persistent reference" is one which enables us to identify
+ a printer regardless of where it resides on the USB topology,
+ and enumeration sequence.
+
+ To do this, we actually construct a reference from information
+ buried inside the printer. First we look at the USB device
+ descripton: an ideally defined device will support strings for
+ manufacturer and product id, and serial number. The serial number
+ will be unique for each printer.
+
+ Our prefered identification fetches the IEEE-1284 device id string.
+ This transparently handled IEEE-1284 compatible printers which
+ connected over a USB-parallel cable. Only if we can't get all the
+ information to uniquely identify the printer do we try the strings
+ referenced in the printer's USB device descriptor. (These strings
+ are typically absent in a USB-parallel cable.)
+
+ If a device doesn't support serial numbers we have a problem:
+ we can't distinguish between two identical printers. Unique serial
+ numbers allow us to distinguish between two same-model, same-manufacturer
+ USB printers.
+
+ In:
+ thePrinter iterator required for fetching device descriptor
+ devRefNum required to configure the interface
+
+ Out:
+ address->manufacturer
+ address->product
+ address->serial
+ Any (and all) of these may be NULL if we can't retrieve
+ information for IEEE1284 DeviceID or the USB device
+ descriptor. Caller should be prepared to handle such a case.
+ address->command
+ May be updated.
+
+*-----------------------------------------------------------------------------*/
+OSStatus
+UsbGetPrinterAddress( USBPrinterInfo *thePrinter, USBPrinterAddress *address, UInt16 timeout )
+{
+
+ /* */
+ /* start by assuming the device is not IEEE-1284 compliant */
+ /* and that we can't read in the required strings. */
+ /* */
+ OSStatus err;
+ CFStringRef deviceId = NULL;
+ USBPrinterClassContext **printer = NULL == thePrinter? NULL: thePrinter->classdriver;
+
+ address->manufacturer =
+ address->product =
+ address->compatible =
+ address->serial =
+ address->command = NULL;
+
+ DEBUG_DUMP( "UsbGetPrinterAddress thePrinter", thePrinter, sizeof(USBPrinterInfo) );
+
+ err = (*printer)->GetDeviceID( printer, &deviceId, timeout );
+ if ( noErr == err && NULL != deviceId )
+ {
+ /* the strings embedded here are defined in the IEEE1284 spec */
+ /* */
+ /* use the MFG/MANUFACTURER for the manufacturer */
+ /* and the MDL/MODEL for the product */
+ /* there is no serial number defined in IEEE1284 */
+ /* but it's been observed in recent HP printers */
+ /* */
+ address->command = DeviceIDCreateValueList( deviceId, kDeviceIDKeyCommandAbbrev, kDeviceIDKeyCommand );
+
+ address->product = DeviceIDCreateValueList( deviceId, kDeviceIDKeyModelAbbrev, kDeviceIDKeyModel );
+ address->compatible = DeviceIDCreateValueList( deviceId, kDeviceIDKeyCompatibleAbbrev, kDeviceIDKeyCompatible );
+
+ address->manufacturer = DeviceIDCreateValueList( deviceId, kDeviceIDKeyManufacturerAbbrev, kDeviceIDKeyManufacturer );
+
+ address->serial = DeviceIDCreateValueList( deviceId, kDeviceIDKeySerialAbbrev, kDeviceIDKeySerial );
+ CFRelease( deviceId );
+ }
+ DEBUG_CFString( "UsbGetPrinterAddress DeviceID address->product", address->product );
+ DEBUG_CFString( "UsbGetPrinterAddress DeviceID address->compatible", address->compatible );
+ DEBUG_CFString( "UsbGetPrinterAddress DeviceID address->manufacturer", address->manufacturer );
+ DEBUG_CFString( "UsbGetPrinterAddress DeviceID address->serial", address->serial );
+
+ if ( NULL == address->product || NULL == address->manufacturer || NULL == address->serial )
+ {
+ /* */
+ /* if the manufacturer or the product or serial number were not specified in DeviceID */
+ /* try to construct the address using USB English string descriptors */
+ /* */
+ IOUSBDeviceDescriptor desc;
+ USBIODeviceRequest request;
+
+ request.requestType = USBmakebmRequestType( kUSBIn, kUSBStandard, kUSBDevice );
+ request.request = kUSBRqGetDescriptor;
+ request.value = (kUSBDeviceDesc << 8) | 0;
+ request.index = 0; /* not kUSBLanguageEnglish*/
+ request.length = sizeof(desc);
+ request.buffer = &desc;
+ err = (*printer)->DeviceRequest( printer, &request, timeout );
+ DEBUG_ERR( (kern_return_t) err, "UsbGetPrinterAddress: GetDescriptor %x" );
+ if ( kIOReturnSuccess == err )
+ {
+ /* once we've retrieved the device descriptor */
+ /* try to fill in missing pieces of information */
+ /* */
+ /* Don't override any information already retrieved from DeviceID. */
+
+ if ( NULL == address->product)
+ {
+ err = (*printer)->GetString( printer, desc.iProduct, kUSBLanguageEnglish, timeout, &address->product );
+ if ( kIOReturnSuccess != err || address->product == NULL) {
+ address->product = CFSTR("Unknown");
+ }
+ }
+ DEBUG_CFString( "UsbGetPrinterAddress: UsbGetString address->product\n", address->product );
+
+ if ( NULL == address->manufacturer )
+ {
+ err = (*printer)->GetString( printer, desc.iManufacturer, kUSBLanguageEnglish, timeout, &address->manufacturer );
+ if (kIOReturnSuccess != err || address->manufacturer == NULL) {
+ address->manufacturer = CFSTR("Unknown");
+ }
+ }
+ DEBUG_CFString( "UsbGetPrinterAddress: UsbGetString address->manufacturer\n", address->manufacturer );
+
+ if ( NULL == address->serial )
+ {
+ /* if the printer doesn't have a serial number, use locationId */
+ if ( 0 == desc.iSerialNumber )
+ {
+ address->serial = CFStringCreateWithFormat( NULL, NULL, CFSTR("%lx"), (*printer)->location );
+ }
+ else
+ {
+ err = (*printer)->GetString( printer, desc.iSerialNumber, kUSBLanguageEnglish, timeout, &address->serial );
+ /* trailing NULs aren't handled correctly in URI */
+ if ( address->serial )
+ {
+ UniChar nulbyte = { 0 };
+ CFStringRef trim = CFStringCreateWithCharacters(NULL, &nulbyte, 1);
+ CFMutableStringRef newserial = CFStringCreateMutableCopy(NULL, 0, address->serial);
+
+ CFStringTrim( newserial, trim );
+
+ CFRelease(trim);
+ CFRelease( address->serial );
+
+ address->serial = newserial;
+ }
+ }
+ }
+ DEBUG_CFString( "UsbGetPrinterAddress: UsbGetString address->serial\n", address->serial );
+ }
+ }
+ if ( NULL != address->product)
+ CFRetain(address->product); /* UsbGetString is really a UsbCopyString. */
+ if ( NULL != address->manufacturer )
+ CFRetain( address->manufacturer );
+ if ( NULL != address->serial )
+ CFRetain( address->serial );
+ return err;
+}
+
+
+/*-----------------------------------------------------------------------------*
+
+UsbSamePrinter
+
+ Desc: match two Usb printer address; return TRUE if they are the same.
+
+ In: a the persistent address found last time
+ b the persistent address found this time
+
+ Out: non-zero iff the addresses are the same
+
+*-----------------------------------------------------------------------------*/
+int
+UsbSamePrinter( const USBPrinterAddress *a, const USBPrinterAddress *b )
+{
+ int result = 0;
+ DEBUG_CFCompareString( "UsbSamePrinter serial", a->serial, b->serial );
+ DEBUG_CFCompareString( "UsbSamePrinter product", a->product, b->product );
+ DEBUG_CFCompareString( "UsbSamePrinter manufacturer", a->manufacturer, b->manufacturer );
+
+ result = !CompareSameString( a->serial, b->serial );
+ if ( result ) result = !CompareSameString( a->product, b->product );
+ if ( result ) result = !CompareSameString( a->manufacturer, b->manufacturer );
+
+ return result;
+}
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Method: UsbMakeFullUriAddress
+
+ Input Parameters:
+
+ Output Parameters:
+
+ Description:
+ Fill in missing address information
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+CFStringRef
+UsbMakeFullUriAddress( USBPrinterInfo *printer )
+{
+ /* */
+ /* fill in missing address information. */
+ /* */
+ CFMutableStringRef printerUri = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("usb://") );
+ if ( NULL != printerUri )
+ {
+ CFStringRef serial = printer->address.serial;
+
+ CFStringAppend(printerUri, printer->address.manufacturer? CreateEncodedCFString( printer->address.manufacturer ): CFSTR("Unknown") );
+ CFStringAppend(printerUri, CFSTR("/") );
+
+ CFStringAppend(printerUri, printer->address.product? CreateEncodedCFString( printer->address.product ): CFSTR("Unknown") );
+
+ /*Handle the common case where there is no serial number (S450?) */
+ CFStringAppend(printerUri, serial == NULL? CFSTR("?location="): CFSTR("?serial=") );
+ if ( serial == NULL)
+ serial = CFStringCreateWithFormat( NULL, NULL, CFSTR("%lx"), printer->location );
+
+ CFStringAppend(printerUri, serial? CreateEncodedCFString( serial ): CFSTR("Unknown") );
+ }
+
+ return printerUri;
+}
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Method: UsbGetAllPrinters
+
+ Input Parameters:
+
+ Output Parameters:
+ array of all USB printers on the system
+
+ Description:
+ Build a list of USB printers by iterating IOKit USB objects
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+CFMutableArrayRef
+UsbGetAllPrinters( void )
+{
+ kern_return_t kr; /* kernel errors */
+ mach_port_t master_device_port = 0;
+ io_service_t usbInterface = 0;
+ io_iterator_t iter = 0;
+ CFMutableArrayRef printers = CFArrayCreateMutable( NULL, 0, NULL ); /* all printers */
+
+ do
+ {
+
+ kr = IOMasterPort( bootstrap_port, &master_device_port );
+ DEBUG_ERR( kr, "UsbGetAllPrinters IOMasterPort %x\n" );
+ if(kIOReturnSuccess != kr) break;
+
+ {
+ CFDictionaryRef usbMatch = NULL;
+
+ /* iterate over all interfaces. */
+ usbMatch = IOServiceMatching(kIOUSBInterfaceClassName);
+ if ( !usbMatch ) break;
+ DEBUG_ERR( kr, "UsbGetAllPrinters IOServiceMatching %x\n" );
+
+ /* IOServiceGetMatchingServices() consumes the usbMatch reference so we don't need to release it. */
+ kr = IOServiceGetMatchingServices(master_device_port, usbMatch, &iter);
+ usbMatch = NULL;
+
+ DEBUG_ERR( kr, "UsbGetAllPrinters IOServiceGetMatchingServices %x\n" );
+ if(kIOReturnSuccess != kr || iter == NULL) break;
+ }
+
+ while ( NULL != (usbInterface = IOIteratorNext(iter)) )
+ {
+ IOCFPlugInInterface **iodev;
+ USBPrinterInterface intf;
+ HRESULT res;
+ SInt32 score;
+ CFMutableDictionaryRef properties;
+ CFStringRef classDriver = NULL;
+
+ kr = IORegistryEntryCreateCFProperties( usbInterface, &properties, kCFAllocatorDefault, kNilOptions);
+ if ( kIOReturnSuccess == kr && NULL != properties)
+ {
+ classDriver = (CFStringRef) CFDictionaryGetValue( properties, kUSBClassDriverProperty );
+ if ( NULL != classDriver )
+ CFRetain( classDriver );
+ CFRelease( properties );
+ }
+
+ kr = IOCreatePlugInInterfaceForService( usbInterface,
+ kIOUSBInterfaceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &iodev,
+ &score);
+
+ DEBUG_ERR( kr, "UsbGetAllPrinters IOCreatePlugInInterfaceForService %x\n" );
+ if ( kIOReturnSuccess == kr )
+ {
+ UInt8 intfClass = 0;
+ UInt8 intfSubClass = 0;
+
+ res = (*iodev)->QueryInterface( iodev, USB_INTERFACE_KIND, (LPVOID *) &intf);
+ DEBUG_ERR( (kern_return_t) res, "UsbGetAllPrinters QueryInterface %x\n" );
+
+ (*iodev)->Release(iodev);
+ if ( noErr != res ) break;
+
+ kr = (*intf)->GetInterfaceClass(intf, &intfClass);
+ DEBUG_ERR(kr, "UsbGetAllPrinters GetInterfaceClass %x\n");
+ if ( kIOReturnSuccess == kr )
+ kr = (*intf)->GetInterfaceSubClass(intf, &intfSubClass);
+ DEBUG_ERR(kr, "UsbGetAllPrinters GetInterfaceSubClass %x\n");
+
+ if ( kIOReturnSuccess == kr &&
+ kUSBPrintingClass == intfClass &&
+ kUSBPrintingSubclass == intfSubClass )
+ {
+
+ USBPrinterInfo printer,
+ *printerInfo;
+ /*
+ For each type of printer specified in the lookup spec array, find
+ all of that type of printer and add the results to the list of found
+ printers.
+ */
+ /* create this printer's persistent address */
+ memset( &printer, 0, sizeof(USBPrinterInfo) );
+ kr = (*intf)->GetLocationID(intf, &printer.location);
+ DEBUG_ERR(kr, "UsbGetAllPrinters GetLocationID %x\n");
+ if ( kIOReturnSuccess == kr )
+ {
+ kr = UsbLoadClassDriver( &printer, kUSBPrinterClassInterfaceID, classDriver );
+ DEBUG_ERR(kr, "UsbGetAllPrinters UsbLoadClassDriver %x\n");
+ if ( kIOReturnSuccess == kr && printer.classdriver )
+ {
+ (*(printer.classdriver))->interface = intf;
+ kr = UsbGetPrinterAddress( &printer, &printer.address, 60000L );
+ {
+ /* always unload the driver */
+ /* but don't mask last error */
+ kern_return_t unload_err = UsbUnloadClassDriver( &printer );
+ if ( kIOReturnSuccess == kr )
+ kr = unload_err;
+ }
+ }
+ }
+
+ printerInfo = UsbCopyPrinter( &printer );
+ if ( NULL != printerInfo )
+ CFArrayAppendValue( printers, (const void *) printerInfo ); /* keep track of it */
+
+ } /* if there's a printer */
+ kr = (*intf)->Release(intf);
+ } /* if IOCreatePlugInInterfaceForService */
+
+ IOObjectRelease(usbInterface);
+ usbInterface = NULL;
+
+ } /* while there's an interface */
+ } while ( 0 );
+
+ if (iter)
+ {
+ IOObjectRelease(iter);
+ iter = 0;
+ }
+
+ if (master_device_port)
+ {
+ mach_port_deallocate(mach_task_self(), master_device_port);
+ master_device_port = 0;
+ }
+ return printers;
+
+} /* UsbGetAllPrinters */
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Method: UsbReleasePrinter
+
+ Input Parameters:
+
+ Output Parameters:
+
+ Description:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+void
+UsbReleasePrinter( USBPrinterInfo *printer )
+{
+ if ( printer )
+ {
+ UsbUnloadClassDriver( printer );
+ if ( NULL != printer->address.manufacturer )
+ CFRelease( printer->address.manufacturer );
+ if ( NULL != printer->address.product )
+ CFRelease( printer->address.product );
+ if ( NULL != printer->address.serial )
+ CFRelease( printer->address.serial );
+ if ( NULL != printer->address.command )
+ CFRelease( printer->address.command );
+ if ( NULL != printer->bundle )
+ CFRelease( printer->bundle );
+ free( printer );
+ }
+}
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Method: UsbReleaseAllPrinters
+
+ Input Parameters:
+
+ Output Parameters:
+
+ Description:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+void
+UsbReleaseAllPrinters( CFMutableArrayRef printers )
+{
+ if ( NULL != printers )
+ {
+ CFIndex i,
+ numPrinters = CFArrayGetCount(printers);
+ for ( i = 0; i < numPrinters; ++i )
+ UsbReleasePrinter( (USBPrinterInfo *) CFArrayGetValueAtIndex( printers, i ) );
+ CFRelease( printers );
+ }
+}
+
+USBPrinterInfo *
+UsbCopyPrinter( USBPrinterInfo *aPrinter )
+{
+ /* */
+ /* note this does not copy interface information, just address information */
+ /* */
+ USBPrinterInfo *printerInfo = (USBPrinterInfo *) calloc( 1, sizeof(USBPrinterInfo));
+ if ( NULL != printerInfo && NULL != aPrinter )
+ {
+ printerInfo->location = aPrinter->location;
+ if ( NULL != (printerInfo->address.manufacturer = aPrinter->address.manufacturer) )
+ CFRetain( printerInfo->address.manufacturer );
+ if ( NULL != (printerInfo->address.product = aPrinter->address.product) )
+ CFRetain( printerInfo->address.product );
+ if ( NULL != (printerInfo->address.serial = aPrinter->address.serial) )
+ CFRetain( printerInfo->address.serial );
+ if ( NULL != (printerInfo->address.command = aPrinter->address.command) )
+ CFRetain( printerInfo->address.command );
+ if ( NULL != (printerInfo->bundle = aPrinter->bundle) )
+ CFRetain( printerInfo->bundle );
+ }
+
+ return printerInfo;
+}
+
+/*-----------------------------------------------------------------------------*
+
+ UsbRegistryOpen
+
+ Desc: opens the USB printer which matches the supplied printerAddress
+
+ In: myContext->printerAddress persistent name which identifies the printer
+
+ Out: myContext->usbDeviceRef current IOKit address of this printer
+*-----------------------------------------------------------------------------*/
+kern_return_t
+UsbRegistryOpen( USBPrinterAddress *usbAddress, USBPrinterInfo **result )
+{
+ kern_return_t kr = -1; /* indeterminate failure */
+ CFMutableArrayRef printers = UsbGetAllPrinters();
+ CFIndex numPrinters = NULL != printers? CFArrayGetCount( printers): 0;
+ CFIndex i;
+
+ *result = NULL; /* nothing matched */
+ for ( i = 0; i < numPrinters; ++i )
+ {
+ USBPrinterInfo *thisPrinter = (USBPrinterInfo *) CFArrayGetValueAtIndex( printers, i );
+ if ( NULL != thisPrinter && UsbSamePrinter( usbAddress, &thisPrinter->address ) )
+ {
+ *result = UsbCopyPrinter( thisPrinter ); /* retains reference */
+ if ( NULL != *result )
+ {
+ /* */
+ /* if we can't find a bi-di interface, settle for a known uni-directional interface */
+ /* */
+ USBPrinterClassContext **printer = NULL;
+ /* */
+ /* setup the default class driver */
+ /* If one is specified, allow the vendor driver to override our default implementation */
+ /* */
+ kr = UsbLoadClassDriver( *result, kUSBPrinterClassInterfaceID, NULL );
+ if ( kIOReturnSuccess == kr && (*result)->bundle )
+ kr = UsbLoadClassDriver( *result, kUSBPrinterClassInterfaceID, (*result)->bundle );
+ if ( kIOReturnSuccess == kr && NULL != (*result)->classdriver )
+ {
+ printer = (*result)->classdriver;
+ kr = (*printer)->Open( printer, (*result)->location, kUSBPrintingProtocolBidirectional );
+ if ( kIOReturnSuccess != kr || NULL == (*printer)->interface )
+ kr = (*printer)->Open( printer, (*result)->location, kUSBPrintingProtocolUnidirectional );
+ /* it's possible kIOReturnSuccess == kr && NULL == (*printer)->interface */
+ /* in the event that we can't open either Bidirectional or Unidirectional interface */
+ if ( kIOReturnSuccess == kr )
+ {
+ if ( NULL == (*printer)->interface )
+ {
+ (*printer)->Close( printer );
+ UsbReleasePrinter( *result );
+ *result = NULL;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ UsbReleaseAllPrinters( printers ); /* but, copied printer is retained */
+ DEBUG_ERR( kr, "UsbRegistryOpen return %x\n" );
+
+ return kr;
+}
+
+/*!
+ * @function CreateEncodedCFString
+ *
+ * @abstract Create an encoded version of the string parameter
+ * so that it can be included in a URI.
+ *
+ * @param string A CFStringRef of the string to be encoded.
+ * @result An encoded CFString.
+ *
+ * @discussion This function will change all characters in string into URL acceptable format
+ * by encoding the text using the US-ASCII coded character set. The following
+ * are invalid characters: the octets 00-1F, 7F, and 80-FF hex. Also called out
+ * are the chars "<", ">", """, "#", "{", "}", "|", "\", "^", "~", "[", "]", "`".
+ * The reserved characters for URL syntax are also to be encoded: (so don't pass
+ * in a full URL here!) ";", "/", "?", ":", "@", "=", "%", and "&".
+ */
+static CFStringRef CreateEncodedCFString(CFStringRef string)
+{
+ CFStringRef result = NULL;
+ char *bufferUTF8 = NULL;
+ char *bufferEncoded = NULL;
+
+ if (string != NULL)
+ {
+ CFIndex bufferSizeUTF8 = (3 * CFStringGetLength(string));
+ if ((bufferUTF8 = (char*)malloc(bufferSizeUTF8)) != NULL)
+ {
+ CFStringGetCString(string, bufferUTF8, bufferSizeUTF8, kCFStringEncodingUTF8);
+ {
+ UInt16 bufferSizeEncoded = (3 * strlen(bufferUTF8)) + 1;
+ if ((bufferEncoded = (char*)malloc(bufferSizeEncoded)) != NULL)
+ {
+ addPercentEscapes(bufferUTF8, bufferEncoded, bufferSizeEncoded);
+ result = CFStringCreateWithCString(kCFAllocatorDefault, bufferEncoded, kCFStringEncodingUTF8);
+ }
+ }
+ }
+ }
+
+ if (bufferUTF8) free(bufferUTF8);
+ if (bufferEncoded) free(bufferEncoded);
+
+ return result;
+}
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/usb-unix.c b/backend/usb-unix.c
new file mode 100644
index 000000000..0247d755c
--- /dev/null
+++ b/backend/usb-unix.c
@@ -0,0 +1,807 @@
+/*
+ * "$Id$"
+ *
+ * USB port backend for the Common UNIX Printing System (CUPS).
+ *
+ * This file is included from "usb.c" when compiled on UNIX/Linux.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Send a file to the specified USB port.
+ * list_devices() - List all USB devices.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#ifdef __linux
+# include <sys/ioctl.h>
+# include <linux/lp.h>
+# define IOCNR_GET_DEVICE_ID 1
+
+/*
+ * Get device_id string
+ */
+# define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
+#endif /* __linux */
+
+#ifdef __sun
+# ifdef __sparc
+# include <sys/ecppio.h>
+# else
+# include <sys/ioccom.h>
+# include <sys/ecppsys.h>
+# endif /* __sparc */
+#endif /* __sun */
+
+
+/*
+ * Local functions...
+ */
+
+void decode_device_id(int port, const char *device_id,
+ char *make_model, int mmsize,
+ char *uri, int urisize);
+int open_device(const char *uri);
+
+
+/*
+ * 'print_device()' - Print a file to a USB device.
+ */
+
+int /* O - Exit status */
+print_device(const char *uri, /* I - Device URI */
+ const char *hostname, /* I - Hostname/manufacturer */
+ const char *resource, /* I - Resource/modelname */
+ const char *options, /* I - Device options/serial number */
+ int fp, /* I - File descriptor to print */
+ int copies) /* I - Copies to print */
+{
+ int fd; /* USB device */
+ int wbytes; /* Number of bytes written */
+ size_t nbytes, /* Number of bytes read */
+ tbytes; /* Total number of bytes written */
+ char buffer[8192], /* Output buffer */
+ *bufptr; /* Pointer into buffer */
+ struct termios opts; /* Parallel port options */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#ifdef __linux
+ unsigned int status; /* Port status (off-line, out-of-paper, etc.) */
+#endif /* __linux */
+
+
+ /*
+ * Open the USB port device...
+ */
+
+ do
+ {
+ if ((fd = open_device(uri)) == -1)
+ {
+ if (errno == EBUSY)
+ {
+ fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else if (errno == ENXIO || errno == EIO || errno == ENOENT)
+ {
+ fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Unable to open USB device \"%s\": %s\n",
+ uri, strerror(errno));
+ return (1);
+ }
+ }
+ }
+ while (fd < 0);
+
+ /*
+ * Set any options provided...
+ */
+
+ tcgetattr(fd, &opts);
+
+ opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
+
+ /**** No options supported yet ****/
+
+ tcsetattr(fd, TCSANOW, &opts);
+
+ /*
+ * Now that we are "connected" to the port, ignore SIGTERM so that we
+ * can finish out any page data the driver sends (e.g. to eject the
+ * current page... Only ignore SIGTERM if we are printing data from
+ * stdin (otherwise you can't cancel raw jobs...)
+ */
+
+ if (fp)
+ {
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+ }
+
+#if defined(__linux) && defined(LP_POUTPA)
+ /*
+ * Show the printer status before we send the file; normally, we'd
+ * do this while we write data to the printer, however at least some
+ * Linux kernels have buggy USB drivers which don't like to be
+ * queried while sending data to the printer...
+ *
+ * Also, we're using the 8255 constants instead of the ones that are
+ * supposed to be used, as it appears that the USB driver also doesn't
+ * follow standards...
+ */
+
+ if (ioctl(fd, LPGETSTATUS, &status) == 0)
+ {
+ fprintf(stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status);
+
+ if (status & LP_POUTPA)
+ fputs("WARNING: Media tray empty!\n", stderr);
+ else if (!(status & LP_PERRORP))
+ fputs("WARNING: Printer fault!\n", stderr);
+ else if (!(status & LP_PSELECD))
+ fputs("WARNING: Printer off-line.\n", stderr);
+ }
+#endif /* __linux && LP_POUTPA */
+
+ /*
+ * Finally, send the print file...
+ */
+
+ wbytes = 0;
+
+ while (copies > 0)
+ {
+ copies --;
+
+ if (fp != 0)
+ {
+ fputs("PAGE: 1 1\n", stderr);
+ lseek(fp, 0, SEEK_SET);
+ }
+
+ tbytes = 0;
+ while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
+ {
+ /*
+ * Write the print data to the printer...
+ */
+
+ tbytes += nbytes;
+ bufptr = buffer;
+
+ while (nbytes > 0)
+ {
+
+ if ((wbytes = write(fd, bufptr, nbytes)) < 0)
+ if (errno == ENOTTY)
+ wbytes = write(fd, bufptr, nbytes);
+
+ if (wbytes < 0)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+ }
+
+ if (wbytes < 0)
+ break;
+
+ if (fp)
+ fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
+ (unsigned long)tbytes);
+ }
+ }
+
+ /*
+ * Close the USB port and return...
+ */
+
+ close(fd);
+
+ return (wbytes < 0);
+}
+
+
+/*
+ * 'decode_device_id()' - Decode the IEEE-1284 device ID string.
+ */
+
+void
+decode_device_id(int port, /* I - Port number */
+ const char *device_id, /* I - 1284 device ID string */
+ char *make_model, /* O - Make/model */
+ int mmsize, /* I - Size of buffer */
+ char *uri, /* O - Device URI */
+ int urisize) /* I - Size of buffer */
+{
+ char *attr, /* 1284 attribute */
+ *delim, /* 1284 delimiter */
+ *uriptr, /* Pointer into URI */
+ *mfg, /* Manufacturer string */
+ *mdl, /* Model string */
+ serial_number[1024]; /* Serial number string */
+
+
+ /*
+ * Look for the description field...
+ */
+
+ if ((attr = strstr(device_id, "DES:")) != NULL)
+ attr += 4;
+ else if ((attr = strstr(device_id, "DESCRIPTION:")) != NULL)
+ attr += 12;
+
+ if ((mfg = strstr(device_id, "MANUFACTURER:")) != NULL)
+ mfg += 13;
+ else if ((mfg = strstr(device_id, "MFG:")) != NULL)
+ mfg += 4;
+
+ if ((mdl = strstr(device_id, "MODEL:")) != NULL)
+ mdl += 6;
+ else if ((mdl = strstr(device_id, "MDL:")) != NULL)
+ mdl += 4;
+
+ if (attr)
+ {
+ if (strncasecmp(attr, "Hewlett-Packard ", 16) == 0)
+ {
+ strlcpy(make_model, "HP ", mmsize);
+ strlcpy(make_model + 3, attr + 16, mmsize - 3);
+ }
+ else
+ {
+ strlcpy(make_model, attr, mmsize);
+ }
+
+ if ((delim = strchr(make_model, ';')) != NULL)
+ *delim = '\0';
+ }
+ else if (mfg && mdl)
+ {
+ /*
+ * Build a make-model string from the manufacturer and model attributes...
+ */
+
+ strlcpy(make_model, mfg, mmsize);
+
+ if ((delim = strchr(make_model, ';')) != NULL)
+ *delim = '\0';
+
+ strlcat(make_model, " ", mmsize);
+ strlcat(make_model, mdl, mmsize);
+
+ if ((delim = strchr(make_model, ';')) != NULL)
+ *delim = '\0';
+ }
+ else
+ {
+ /*
+ * Use "Unknown" as the printer make and model...
+ */
+
+ strlcpy(make_model, "Unknown", mmsize);
+ }
+
+ /*
+ * Look for the serial number field...
+ */
+
+ if ((attr = strstr(device_id, "SERN:")) != NULL)
+ attr += 5;
+ else if ((attr = strstr(device_id, "SERIALNUMBER:")) != NULL)
+ attr += 13;
+ else if ((attr = strstr(device_id, ";SN:")) != NULL)
+ attr += 4;
+
+ if (mfg)
+ {
+ /*
+ * Make sure manufacturer is truncated at delimiter...
+ */
+
+ if ((delim = strchr(mfg, ';')) != NULL)
+ *delim = '\0';
+ }
+
+ if (mdl)
+ {
+ /*
+ * Make sure model is truncated at delimiter...
+ */
+
+ if ((delim = strchr(mdl, ';')) != NULL)
+ *delim = '\0';
+ }
+
+ if (attr)
+ {
+ strlcpy(serial_number, attr, sizeof(serial_number));
+
+ if ((delim = strchr(serial_number, ';')) != NULL)
+ *delim = '\0';
+ }
+ else
+ serial_number[0] = '\0';
+
+ /*
+ * Generate the device URI from the make_model and serial number strings.
+ */
+
+ strlcpy(uri, "usb://", urisize);
+ for (uriptr = uri + 6, delim = make_model;
+ *delim && uriptr < (uri + urisize - 1);
+ delim ++)
+ if (*delim == ' ')
+ {
+ delim ++;
+ *uriptr++ = '/';
+ break;
+ }
+ else
+ *uriptr++ = *delim;
+
+ for (; *delim && uriptr < (uri + urisize - 3); delim ++)
+ if (*delim == ' ')
+ {
+ *uriptr++ = '%';
+ *uriptr++ = '2';
+ *uriptr++ = '0';
+ }
+ else
+ *uriptr++ = *delim;
+
+ *uriptr = '\0';
+
+ if (serial_number[0])
+ {
+ /*
+ * Add the serial number to the URI...
+ */
+
+ strlcat(uri, "?serial=", urisize);
+ strlcat(uri, serial_number, urisize);
+ }
+}
+
+
+/*
+ * 'list_devices()' - List all USB devices.
+ */
+
+void
+list_devices(void)
+{
+#ifdef __linux
+ int i; /* Looping var */
+ int length; /* Length of device ID info */
+ int fd; /* File descriptor */
+ char format[255], /* Format for device filename */
+ device[255], /* Device filename */
+ device_id[1024], /* Device ID string */
+ device_uri[1024], /* Device URI string */
+ make_model[1024]; /* Make and model */
+
+
+ /*
+ * First figure out which USB printer filename to use...
+ */
+
+ if (access("/dev/usblp0", 0) == 0)
+ strcpy(format, "/dev/usblp%d");
+ else if (access("/dev/usb/usblp0", 0) == 0)
+ strcpy(format, "/dev/usb/usblp%d");
+ else
+ strcpy(format, "/dev/usb/lp%d");
+
+ /*
+ * Then open each USB device...
+ */
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(device, format, i);
+
+ if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
+ {
+ if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0)
+ {
+ length = (((unsigned)device_id[0] & 255) << 8) +
+ ((unsigned)device_id[1] & 255);
+
+ /*
+ * Check to see if the length is larger than our buffer; first
+ * assume that the vendor incorrectly implemented the 1284 spec,
+ * and then limit the length to the size of our buffer...
+ */
+
+ if (length > (sizeof(device_id) - 2))
+ length = (((unsigned)device_id[1] & 255) << 8) +
+ ((unsigned)device_id[0] & 255);
+
+ if (length > (sizeof(device_id) - 2))
+ length = sizeof(device_id) - 2;
+
+ memmove(device_id, device_id + 2, length);
+ device_id[length] = '\0';
+ }
+ else
+ device_id[0] = '\0';
+
+ close(fd);
+ }
+ else
+ device_id[0] = '\0';
+
+ if (device_id[0])
+ {
+ decode_device_id(i, device_id, make_model, sizeof(make_model),
+ device_uri, sizeof(device_uri));
+
+ printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri,
+ make_model, i + 1);
+ }
+ else
+ printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+ }
+#elif defined(__sgi)
+#elif defined(__sun)
+ int i; /* Looping var */
+ int fd; /* File descriptor */
+ char device[255], /* Device filename */
+ device_id[1024], /* Device ID string */
+ device_uri[1024], /* Device URI string */
+ make_model[1024]; /* Make and model */
+# ifdef ECPPIOC_GETDEVID
+ struct ecpp_device_id did; /* Device ID buffer */
+# endif /* ECPPIOC_GETDEVID */
+
+
+ /*
+ * Open each USB device...
+ */
+
+ for (i = 0; i < 8; i ++)
+ {
+ sprintf(device, "/dev/usb/printer%d", i);
+
+# ifndef ECPPIOC_GETDEVID
+ if (!access(device, 0))
+ printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+# else
+ if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
+ {
+ did.mode = ECPP_CENTRONICS;
+ did.len = sizeof(device_id);
+ did.rlen = 0;
+ did.addr = device_id;
+
+ if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0)
+ {
+ if (did.rlen < (sizeof(device_id) - 1))
+ device_id[did.rlen] = '\0';
+ else
+ device_id[sizeof(device_id) - 1] = '\0';
+ }
+ else
+ device_id[0] = '\0';
+
+ close(fd);
+ }
+ else
+ device_id[0] = '\0';
+
+ if (device_id[0])
+ {
+ decode_device_id(i, device_id, make_model, sizeof(make_model),
+ device_uri, sizeof(device_uri));
+
+ printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri,
+ make_model, i + 1);
+ }
+ else
+ printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+# endif /* !ECPPIOC_GETDEVID */
+ }
+#elif defined(__hpux)
+#elif defined(__osf)
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ int i; /* Looping var */
+ char device[255]; /* Device filename */
+
+
+ for (i = 0; i < 8; i ++)
+ {
+ sprintf(device, "/dev/ulpt%d", i);
+ if (!access(device, 0))
+ printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
+
+ sprintf(device, "/dev/unlpt%d", i);
+ if (!access(device, 0))
+ printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1);
+ }
+#endif
+}
+
+
+/*
+ * 'open_device()' - Open a USB device...
+ */
+
+int /* O - File descriptor or -1 on error */
+open_device(const char *uri) /* I - Device URI */
+{
+ /*
+ * The generic implementation just treats the URI as a device filename...
+ * Specific operating systems may also support using the device serial
+ * number and/or make/model.
+ */
+
+ if (strncmp(uri, "usb:/dev/", 9) == 0)
+ return (open(uri + 4, O_RDWR | O_EXCL));
+#ifdef __linux
+ else if (strncmp(uri, "usb://", 6) == 0)
+ {
+ /*
+ * For Linux, try looking up the device serial number or model...
+ */
+
+ int i; /* Looping var */
+ int busy; /* Are any ports busy? */
+ int length; /* Length of device ID info */
+ int fd; /* File descriptor */
+ char format[255], /* Format for device filename */
+ device[255], /* Device filename */
+ device_id[1024], /* Device ID string */
+ make_model[1024], /* Make and model */
+ device_uri[1024]; /* Device URI string */
+
+
+ /*
+ * First figure out which USB printer filename to use...
+ */
+
+ if (access("/dev/usblp0", 0) == 0)
+ strcpy(format, "/dev/usblp%d");
+ else if (access("/dev/usb/usblp0", 0) == 0)
+ strcpy(format, "/dev/usb/usblp%d");
+ else
+ strcpy(format, "/dev/usb/lp%d");
+
+ /*
+ * Then find the correct USB device...
+ */
+
+ do
+ {
+ for (busy = 0, i = 0; i < 16; i ++)
+ {
+ sprintf(device, format, i);
+
+ if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
+ {
+ if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0)
+ {
+ length = (((unsigned)device_id[0] & 255) << 8) +
+ ((unsigned)device_id[1] & 255);
+ memmove(device_id, device_id + 2, length);
+ device_id[length] = '\0';
+ }
+ else
+ device_id[0] = '\0';
+ }
+ else
+ {
+ /*
+ * If the open failed because it was busy, flag it so we retry
+ * as needed...
+ */
+
+ if (errno == EBUSY)
+ busy = 1;
+
+ device_id[0] = '\0';
+ }
+
+ if (device_id[0])
+ {
+ /*
+ * Got the device ID - is this the one?
+ */
+
+ decode_device_id(i, device_id, make_model, sizeof(make_model),
+ device_uri, sizeof(device_uri));
+
+ if (strcmp(uri, device_uri) == 0)
+ {
+ /*
+ * Yes, return this file descriptor...
+ */
+
+ fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device);
+
+ return (fd);
+ }
+ }
+
+ /*
+ * This wasn't the one...
+ */
+
+ if (fd >= 0)
+ close(fd);
+ }
+
+ /*
+ * If we get here and at least one of the printer ports showed up
+ * as "busy", then sleep for a bit and retry...
+ */
+
+ if (busy)
+ {
+ fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
+ stderr);
+ sleep(5);
+ }
+ }
+ while (busy);
+
+ /*
+ * Couldn't find the printer, return "no such device or address"...
+ */
+
+ errno = ENODEV;
+
+ return (-1);
+ }
+#elif defined(__sun) && defined(ECPPIOC_GETDEVID)
+ else if (strncmp(uri, "usb://", 6) == 0)
+ {
+ /*
+ * For Solaris, try looking up the device serial number or model...
+ */
+
+ int i; /* Looping var */
+ int busy; /* Are any ports busy? */
+ int fd; /* File descriptor */
+ char device[255], /* Device filename */
+ device_id[1024], /* Device ID string */
+ make_model[1024], /* Make and model */
+ device_uri[1024]; /* Device URI string */
+ struct ecpp_device_id did; /* Device ID buffer */
+
+
+ /*
+ * Find the correct USB device...
+ */
+
+ do
+ {
+ for (i = 0, busy = 0; i < 8; i ++)
+ {
+ sprintf(device, "/dev/usb/printer%d", i);
+
+ if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
+ {
+ did.mode = ECPP_CENTRONICS;
+ did.len = sizeof(device_id);
+ did.rlen = 0;
+ did.addr = device_id;
+
+ if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0)
+ {
+ if (did.rlen < (sizeof(device_id) - 1))
+ device_id[did.rlen] = '\0';
+ else
+ device_id[sizeof(device_id) - 1] = '\0';
+ }
+ else
+ device_id[0] = '\0';
+ }
+ else
+ {
+ /*
+ * If the open failed because it was busy, flag it so we retry
+ * as needed...
+ */
+
+ if (errno == EBUSY)
+ busy = 1;
+
+ device_id[0] = '\0';
+ }
+
+ if (device_id[0])
+ {
+ /*
+ * Got the device ID - is this the one?
+ */
+
+ decode_device_id(i, device_id, make_model, sizeof(make_model),
+ device_uri, sizeof(device_uri));
+
+ if (strcmp(uri, device_uri) == 0)
+ return (fd); /* Yes, return this file descriptor... */
+ }
+
+ /*
+ * This wasn't the one...
+ */
+
+ if (fd >= 0)
+ close(fd);
+ }
+
+ /*
+ * If we get here and at least one of the printer ports showed up
+ * as "busy", then sleep for a bit and retry...
+ */
+
+ if (busy)
+ {
+ fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
+ stderr);
+ sleep(5);
+ }
+ }
+ while (busy);
+
+ /*
+ * Couldn't find the printer, return "no such device or address"...
+ */
+
+ errno = ENODEV;
+
+ return (-1);
+ }
+#endif /* __linux */
+ else
+ {
+ errno = ENODEV;
+ return (-1);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/backend/usb.c b/backend/usb.c
new file mode 100644
index 000000000..5757475f5
--- /dev/null
+++ b/backend/usb.c
@@ -0,0 +1,270 @@
+/*
+ * "$Id$"
+ *
+ * USB port backend for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * list_devices() - List all available USB devices to stdout.
+ * print_device() - Print a file to a USB device.
+ * main() - Send a file to the specified USB port.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#ifdef __APPLE__
+ /* A header order dependency requires this be first */
+# include <ApplicationServices/ApplicationServices.h>
+#endif /* __APPLE__ */
+
+#include <cups/cups.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/string.h>
+#include <signal.h>
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+# include <termios.h>
+#endif /* WIN32 */
+
+
+/*
+ * Local functions...
+ */
+
+void list_devices(void);
+int print_device(const char *uri, const char *hostname,
+ const char *resource, const char *options,
+ int fp, int copies);
+
+
+/*
+ * Include the vendor-specific USB implementation...
+ */
+
+#ifdef __APPLE__
+# include "usb-darwin.c"
+#elif defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# include "usb-unix.c"
+#else
+/*
+ * Use dummy functions that do nothing on unsupported platforms...
+ * These can be used as templates for implementing USB printing on new
+ * platforms...
+ */
+
+/*
+ * 'list_devices()' - List all available USB devices to stdout.
+ */
+
+void
+list_devices(void)
+{
+ /*
+ * Don't have any devices to list... Use output of the form:
+ *
+ * direct usb:/make/model?serial=foo "Make Model" "USB Printer"
+ *
+ * Note that "Hewlett Packard" or any other variation MUST be mapped to
+ * "HP" for compatibility with the PPD and ICC specs.
+ */
+}
+
+
+/*
+ * 'print_device()' - Print a file to a USB device.
+ */
+
+int /* O - Exit status */
+print_device(const char *uri, /* I - Device URI */
+ const char *hostname, /* I - Hostname/manufacturer */
+ const char *resource, /* I - Resource/modelname */
+ const char *options, /* I - Device options/serial number */
+ int fp, /* I - File descriptor to print */
+ int copies) /* I - Copies to print */
+{
+ /*
+ * Can't print, so just reference the arguments to eliminate compiler
+ * warnings and return and exit status of 1. Normally you would use the
+ * arguments to send a file to the printer and return 0 if everything
+ * worked OK and non-zero if there was an error.
+ */
+
+ (void)uri;
+ (void)hostname;
+ (void)resource;
+ (void)options;
+ (void)fp;
+ (void)copies;
+
+ return (1);
+}
+#endif /* __APPLE__ */
+
+
+/*
+ * 'main()' - Send a file to the specified USB port.
+ *
+ * Usage:
+ *
+ * printer-uri job-id user title copies options [file]
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments (6 or 7) */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int fp; /* Print file */
+ int copies; /* Number of copies to print */
+ int status; /* Exit status */
+ int port; /* Port number (not used) */
+ const char *uri; /* Device URI */
+ char method[255], /* Method in URI */
+ hostname[1024], /* Hostname */
+ username[255], /* Username info (not used) */
+ resource[1024], /* Resource info (device and options) */
+ *options; /* Pointer to options */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc == 1)
+ {
+ list_devices();
+ return (0);
+ }
+ else if (argc < 6 || argc > 7)
+ {
+ fputs("Usage: usb job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Extract the device name and options from the URI...
+ */
+
+ if (strncmp(argv[0], "usb:", 4))
+ uri = getenv("DEVICE_URI");
+ else
+ uri = argv[0];
+
+ if (!uri)
+ {
+ fputs("ERROR: No device URI found in argv[0] or in DEVICE_URI environment variable!\n", stderr);
+ return (1);
+ }
+
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
+
+ /*
+ * See if there are any options...
+ */
+
+ if ((options = strchr(resource, '?')) != NULL)
+ {
+ /*
+ * Yup, terminate the device name string and move to the first
+ * character of the options...
+ */
+
+ *options++ = '\0';
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ {
+ fp = 0;
+ copies = 1;
+ }
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = open(argv[6], O_RDONLY)) < 0)
+ {
+ fprintf(stderr, "ERROR: unable to open print file %s - %s\n",
+ argv[6], strerror(errno));
+ return (1);
+ }
+
+ copies = atoi(argv[4]);
+ }
+
+ /*
+ * Finally, send the print file...
+ */
+
+ status = print_device(uri, hostname, resource, options, fp, copies);
+
+ /*
+ * Close the input file and return...
+ */
+
+ if (fp != 0)
+ close(fp);
+
+ return (status);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/berkeley/.cvsignore b/berkeley/.cvsignore
new file mode 100644
index 000000000..3ff70bf38
--- /dev/null
+++ b/berkeley/.cvsignore
@@ -0,0 +1,4 @@
+lpc
+lpq
+lpr
+lprm
diff --git a/berkeley/Dependencies b/berkeley/Dependencies
new file mode 100644
index 000000000..b4b5e447d
--- /dev/null
+++ b/berkeley/Dependencies
@@ -0,0 +1,12 @@
+# DO NOT DELETE
+
+lpc.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpc.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h ../cups/string.h
+lpc.o: ../config.h
+lpq.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
+lpq.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+lpq.o: ../cups/debug.h
+lpr.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
+lpr.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h
+lprm.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lprm.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
diff --git a/berkeley/Makefile b/berkeley/Makefile
new file mode 100644
index 000000000..d570b4646
--- /dev/null
+++ b/berkeley/Makefile
@@ -0,0 +1,112 @@
+#
+# "$Id$"
+#
+# Berkeley commands makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+TARGETS = lpc lpq lpr lprm
+OBJS = lpc.o lpq.o lpr.o lprm.o
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS)
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install: all
+ $(INSTALL_DIR) $(BINDIR)
+ $(INSTALL_BIN) lpq $(BINDIR)
+ $(INSTALL_BIN) lpr $(BINDIR)
+ $(INSTALL_BIN) lprm $(BINDIR)
+ $(INSTALL_DIR) $(SBINDIR)
+ $(INSTALL_BIN) lpc $(SBINDIR)
+
+
+#
+# lpc
+#
+
+lpc: lpc.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpc lpc.o $(LIBS)
+
+
+#
+# lpq
+#
+
+lpq: lpq.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpq lpq.o $(LIBS)
+
+
+#
+# lpr
+#
+
+lpr: lpr.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpr lpr.o $(LIBS)
+
+
+#
+# lprm
+#
+
+lprm: lprm.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lprm lprm.o $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/berkeley/lpc.c b/berkeley/lpc.c
new file mode 100644
index 000000000..04087a43c
--- /dev/null
+++ b/berkeley/lpc.c
@@ -0,0 +1,486 @@
+/*
+ * "$Id$"
+ *
+ * "lpc" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and commands.
+ * compare_strings() - Compare two command-line strings.
+ * do_command() - Do an lpc command...
+ * show_help() - Show help messages.
+ * show_status() - Show printers.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <cups/string.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_strings(char *, char *, int);
+static void do_command(http_t *, char *, char *);
+static void show_help(char *);
+static void show_status(http_t *, char *);
+
+
+/*
+ * 'main()' - Parse options and commands.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* Connection to server */
+ char line[1024], /* Input line from user */
+ *params; /* Pointer to parameters */
+
+
+ /*
+ * Connect to the scheduler...
+ */
+
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ if (argc > 1)
+ {
+ /*
+ * Process a single command on the command-line...
+ */
+
+ do_command(http, argv[1], argv[2]);
+ }
+ else
+ {
+ /*
+ * Do the command prompt thing...
+ */
+
+ printf("lpc> ");
+ while (fgets(line, sizeof(line), stdin) != NULL)
+ {
+ /*
+ * Strip the trailing newline...
+ */
+
+ line[strlen(line) - 1] = '\0';
+
+ /*
+ * Find any options in the string...
+ */
+
+ while (isspace(line[0] & 255))
+ cups_strcpy(line, line + 1);
+
+ for (params = line; *params != '\0'; params ++)
+ if (isspace(*params & 255))
+ break;
+
+ /*
+ * Remove whitespace between the command and parameters...
+ */
+
+ while (isspace(*params & 255))
+ *params++ = '\0';
+
+ /*
+ * The "quit" and "exit" commands exit; otherwise, process as needed...
+ */
+
+ if (compare_strings(line, "quit", 1) == 0 ||
+ compare_strings(line, "exit", 2) == 0)
+ break;
+
+ if (*params == '\0')
+ do_command(http, line, NULL);
+ else
+ do_command(http, line, params);
+
+ /*
+ * Put another prompt out to the user...
+ */
+
+ printf("lpc> ");
+ }
+ }
+
+ /*
+ * Close the connection to the server and return...
+ */
+
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * 'compare_strings()' - Compare two command-line strings.
+ */
+
+static int /* O - -1 or 1 = no match, 0 = match */
+compare_strings(char *s, /* I - Command-line string */
+ char *t, /* I - Option string */
+ int tmin) /* I - Minimum number of unique chars in option */
+{
+ int slen; /* Length of command-line string */
+
+
+ slen = strlen(s);
+ if (slen < tmin)
+ return (-1);
+ else
+ return (strncmp(s, t, slen));
+}
+
+
+/*
+ * 'do_command()' - Do an lpc command...
+ */
+
+static void
+do_command(http_t *http, /* I - HTTP connection to server */
+ char *command, /* I - Command string */
+ char *params) /* I - Parameters for command */
+{
+ if (compare_strings(command, "status", 4) == 0)
+ show_status(http, params);
+ else if (compare_strings(command, "help", 1) == 0 ||
+ strcmp(command, "?") == 0)
+ show_help(params);
+ else
+ printf("%s is not implemented by the CUPS version of lpc.\n", command);
+}
+
+
+/*
+ * 'show_help()' - Show help messages.
+ */
+
+static void
+show_help(char *command) /* I - Command to describe or NULL */
+{
+ if (command == NULL)
+ {
+ puts("Commands may be abbreviated. Commands are:");
+ puts("");
+ puts("exit help quit status ?");
+ }
+ else if (compare_strings(command, "help", 1) == 0 ||
+ strcmp(command, "?") == 0)
+ puts("help\t\tget help on commands");
+ else if (compare_strings(command, "status", 4) == 0)
+ puts("status\t\tshow status of daemon and queue");
+ else
+ puts("?Invalid help command unknown");
+}
+
+
+/*
+ * 'show_status()' - Show printers.
+ */
+
+static void
+show_status(http_t *http, /* I - HTTP connection to server */
+ char *dests) /* I - Destinations */
+{
+ ipp_t *request, /* IPP Request */
+ *response, /* IPP Response */
+ *jobs; /* IPP Get Jobs response */
+ ipp_attribute_t *attr, /* Current attribute */
+ *jattr; /* Current job attribute */
+ cups_lang_t *language; /* Default language */
+ char *printer, /* Printer name */
+ *device, /* Device URI */
+ *delimiter; /* Char search result */
+ ipp_pstate_t pstate; /* Printer state */
+ int accepting; /* Is printer accepting jobs? */
+ int jobcount; /* Count of current jobs */
+ char *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ char printer_uri[HTTP_MAX_URI];
+ /* Printer URI */
+ static const char *requested[] =
+ { /* Requested attributes */
+ "printer-name",
+ "device-uri",
+ "printer-state",
+ "printer-is-accepting-jobs"
+ };
+
+
+ DEBUG_printf(("show_status(%08x, %08x)\n", http, dests));
+
+ if (http == NULL)
+ return;
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(requested) / sizeof(requested[0]),
+ NULL, requested);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ DEBUG_puts("show_status: request succeeded...");
+
+ /*
+ * Loop through the printers returned in the list and display
+ * their status...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ printer = NULL;
+ device = "file:/dev/null";
+ pstate = IPP_PRINTER_IDLE;
+ jobcount = 0;
+ accepting = 1;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "device-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ device = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ pstate = (ipp_pstate_t)attr->values[0].integer;
+
+ if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 &&
+ attr->value_tag == IPP_TAG_BOOLEAN)
+ accepting = attr->values[0].boolean;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (printer == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a printer we're interested in...
+ */
+
+ match = dests == NULL;
+
+ if (dests != NULL)
+ {
+ for (dptr = dests; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = printer;
+ *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the printer entry if needed...
+ */
+
+ if (match)
+ {
+ /*
+ * If the printer state is "IPP_PRINTER_PROCESSING", then grab the
+ * current job for the printer.
+ */
+
+ if (pstate == IPP_PRINTER_PROCESSING)
+ {
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * limit
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL,
+ cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language->language);
+
+ snprintf(printer_uri, sizeof(printer_uri),
+ "ipp://localhost/printers/%s", printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "job-id");
+
+ if ((jobs = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ for (jattr = jobs->attrs; jattr != NULL; jattr = jattr->next)
+ if (jattr->name && strcmp(jattr->name, "job-id") == 0)
+ jobcount ++;
+
+ ippDelete(jobs);
+ }
+ }
+
+ /*
+ * Display it...
+ */
+
+ printf("%s:\n", printer);
+ if (strncmp(device, "file:", 5) == 0)
+ printf("\tprinter is on device \'%s\' speed -1\n", device + 5);
+ else
+ {
+ /*
+ * Just show the method...
+ */
+
+ if ((delimiter = strchr(device, ':')) != NULL )
+ {
+ *delimiter = '\0';
+ printf("\tprinter is on device \'%s\' speed -1\n", device);
+ }
+ }
+
+ printf("\tqueuing is %sabled\n", accepting ? "en" : "dis");
+ printf("\tprinting is %sabled\n",
+ pstate == IPP_PRINTER_STOPPED ? "dis" : "en");
+ if (jobcount == 0)
+ puts("\tno entries");
+ else
+ printf("\t%d entries\n", jobcount);
+ puts("\tdaemon present");
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/berkeley/lpq.c b/berkeley/lpq.c
new file mode 100644
index 000000000..b1f941de8
--- /dev/null
+++ b/berkeley/lpq.c
@@ -0,0 +1,615 @@
+/*
+ * "$Id$"
+ *
+ * "lpq" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and commands.
+ * show_jobs() - Show jobs.
+ * show_printer() - Show printer status.
+ * usage() - Show program usage.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/string.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int show_jobs(http_t *, const char *, const char *, const int,
+ const int);
+static void show_printer(http_t *, const char *);
+static void usage(void);
+
+
+/*
+ * 'main()' - Parse options and commands.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ http_t *http; /* Connection to server */
+ const char *dest, /* Desired printer */
+ *user, /* Desired user */
+ *val; /* Environment variable name */
+ char *instance; /* Printer instance */
+ int id, /* Desired job ID */
+ all, /* All printers */
+ interval, /* Reporting interval */
+ longstatus; /* Show file details */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+#ifdef HAVE_SSL
+ http_encryption_t encryption; /* Encryption? */
+#endif /* HAVE_SSL */
+
+
+ /*
+ * Connect to the scheduler...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ fputs("lpq: Unable to contact server!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Check for command-line options...
+ */
+
+ dest = NULL;
+ user = NULL;
+ id = 0;
+ interval = 0;
+ longstatus = 0;
+ all = 0;
+
+ num_dests = cupsGetDests(&dests);
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '+')
+ interval = atoi(argv[i] + 1);
+ else if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ encryption = HTTP_ENCRYPT_REQUIRED;
+
+ if (http)
+ httpEncryption(http, encryption);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'P' : /* Printer */
+ if (argv[i][2])
+ dest = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ httpClose(http);
+ cupsFreeDests(num_dests, dests);
+
+ usage();
+ }
+
+ dest = argv[i];
+ }
+
+ if ((instance = strchr(dest, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (cupsGetDest(dest, instance, num_dests, dests) == NULL)
+ {
+ if (instance)
+ fprintf(stderr, "lpq: Unknown destination \"%s/%s\"!\n",
+ dest, instance);
+ else
+ fprintf(stderr, "lpq: Unknown destination \"%s\"!\n", dest);
+
+ return (1);
+ }
+ break;
+
+ case 'a' : /* All printers */
+ all = 1;
+ break;
+
+ case 'l' : /* Long status */
+ longstatus = 1;
+ break;
+
+ default :
+ httpClose(http);
+ cupsFreeDests(num_dests, dests);
+
+ usage();
+ break;
+ }
+ }
+ else if (isdigit(argv[i][0] & 255))
+ id = atoi(argv[i]);
+ else
+ user = argv[i];
+
+ if (dest == NULL && !all)
+ {
+ for (i = 0; i < num_dests; i ++)
+ if (dests[i].is_default)
+ dest = dests[i].name;
+
+ if (dest == NULL)
+ {
+ val = NULL;
+
+ if ((dest = getenv("LPDEST")) == NULL)
+ {
+ if ((dest = getenv("PRINTER")) != NULL)
+ {
+ if (!strcmp(dest, "lp"))
+ dest = NULL;
+ else
+ val = "PRINTER";
+ }
+ }
+ else
+ val = "LPDEST";
+
+ if (dest && !cupsGetDest(dest, NULL, num_dests, dests))
+ fprintf(stderr, "lp: error - %s environment variable names non-existent destination \"%s\"!\n",
+ val, dest);
+ else
+ fputs("lpq: error - no default destination available.\n", stderr);
+ httpClose(http);
+ cupsFreeDests(num_dests, dests);
+ return (1);
+ }
+ }
+
+ /*
+ * Show the status in a loop...
+ */
+
+ for (;;)
+ {
+ if (dest)
+ show_printer(http, dest);
+
+ i = show_jobs(http, dest, user, id, longstatus);
+
+ if (i && interval)
+ {
+ fflush(stdout);
+ sleep(interval);
+ }
+ else
+ break;
+ }
+
+ /*
+ * Close the connection to the server and return...
+ */
+
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * 'show_jobs()' - Show jobs.
+ */
+
+static int /* O - Number of jobs in queue */
+show_jobs(http_t *http, /* I - HTTP connection to server */
+ const char *dest, /* I - Destination */
+ const char *user, /* I - User */
+ const int id, /* I - Job ID */
+ const int longstatus)/* I - 1 if long report desired */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *jobdest, /* Pointer into job-printer-uri */
+ *jobuser, /* Pointer to job-originating-user-name */
+ *jobname; /* Pointer to job-name */
+ ipp_jstate_t jobstate; /* job-state */
+ int jobid, /* job-id */
+ jobsize, /* job-k-octets */
+#ifdef __osf__
+ jobpriority, /* job-priority */
+#endif /* __osf__ */
+ jobcount, /* Number of jobs */
+ jobcopies, /* Number of copies */
+ rank; /* Rank of job */
+ char resource[1024]; /* Resource string */
+ char rankstr[255]; /* Rank string */
+ char namestr[1024]; /* Job name string */
+ static const char *ranks[10] =/* Ranking strings */
+ {
+ "th",
+ "st",
+ "nd",
+ "rd",
+ "th",
+ "th",
+ "th",
+ "th",
+ "th",
+ "th"
+ };
+
+
+ DEBUG_printf(("show_jobs(%08x, %08x, %08x, %d, %d)\n", http, dest, user, id,
+ longstatus));
+
+ if (http == NULL)
+ return (0);
+
+ /*
+ * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
+ * the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri or printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ attr = ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (dest == NULL)
+ {
+ if (id)
+ sprintf(resource, "ipp://localhost/jobs/%d", id);
+ else
+ strcpy(resource, "ipp://localhost/jobs");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+ NULL, resource);
+ }
+ else
+ {
+ snprintf(resource, sizeof(resource), "ipp://localhost/printers/%s", dest);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, resource);
+ }
+
+ if (user)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+ }
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ jobcount = 0;
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpq: get-jobs failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (0);
+ }
+
+ rank = 1;
+
+ /*
+ * Loop through the job list and display them...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ jobid = 0;
+ jobsize = 0;
+#ifdef __osf__
+ jobpriority = 50;
+#endif /* __osf__ */
+ jobstate = IPP_JOB_PENDING;
+ jobname = "untitled";
+ jobuser = NULL;
+ jobdest = NULL;
+ jobcopies = 1;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobid = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobsize = attr->values[0].integer * 1024;
+
+#ifdef __osf__
+ if (strcmp(attr->name, "job-priority") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobpriority = attr->values[0].integer;
+#endif /* __osf__ */
+
+ if (strcmp(attr->name, "job-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ jobstate = (ipp_jstate_t)attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ jobdest ++;
+
+ if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobuser = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "job-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobname = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "copies") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobcopies = attr->values[0].integer;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (jobdest == NULL || jobid == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ if (!longstatus && jobcount == 0)
+#ifdef __osf__
+ puts("Rank Owner Pri Job Files Total Size");
+#else
+ puts("Rank Owner Job File(s) Total Size");
+#endif /* __osf__ */
+
+ jobcount ++;
+
+ /*
+ * Display the job...
+ */
+
+ if (jobstate == IPP_JOB_PROCESSING)
+ strcpy(rankstr, "active");
+ else
+ {
+ /*
+ * Make the rank show the "correct" suffix for each number
+ * (11-13 are the only special cases, for English anyways...)
+ */
+
+ if ((rank % 100) >= 11 && (rank % 100) <= 13)
+ snprintf(rankstr, sizeof(rankstr), "%dth", rank);
+ else
+ snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
+
+ rank ++;
+ }
+
+ if (longstatus)
+ {
+ puts("");
+
+ if (jobcopies > 1)
+ snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
+ jobname);
+ else
+ strlcpy(namestr, jobname, sizeof(namestr));
+
+ printf("%s: %-33.33s [job %d localhost]\n", jobuser, rankstr, jobid);
+ printf(" %-39.39s %d bytes\n", namestr, jobsize);
+ }
+ else
+#ifdef __osf__
+ printf("%-6s %-10.10s %-4d %-10d %-27.27s %d bytes\n", rankstr, jobuser,
+ jobpriority, jobid, jobname, jobsize);
+#else
+ printf("%-7s %-7.7s %-7d %-31.31s %d bytes\n", rankstr, jobuser,
+ jobid, jobname, jobsize);
+#endif /* __osf */
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpq: get-jobs failed: %s\n", ippErrorString(cupsLastError()));
+ return (0);
+ }
+
+ if (jobcount == 0)
+ puts("no entries");
+
+ return (jobcount);
+}
+
+
+/*
+ * 'show_printer()' - Show printer status.
+ */
+
+static void
+show_printer(http_t *http, /* I - HTTP connection to server */
+ const char *dest) /* I - Destination */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ ipp_pstate_t state; /* Printer state */
+ char uri[HTTP_MAX_URI];
+ /* Printer URI */
+
+
+ if (http == NULL)
+ return;
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpq: get-printer-attributes failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return;
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
+ state = (ipp_pstate_t)attr->values[0].integer;
+ else
+ state = IPP_PRINTER_STOPPED;
+
+ switch (state)
+ {
+ case IPP_PRINTER_IDLE :
+ printf("%s is ready\n", dest);
+ break;
+ case IPP_PRINTER_PROCESSING :
+ printf("%s is ready and printing\n", dest);
+ break;
+ case IPP_PRINTER_STOPPED :
+ printf("%s is not ready\n", dest);
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ fprintf(stderr, "lpq: get-printer-attributes failed: %s\n",
+ ippErrorString(cupsLastError()));
+}
+
+
+/*
+ * 'usage()' - Show program usage.
+ */
+
+static void
+usage(void)
+{
+ fputs("Usage: lpq [-P dest] [-l] [+interval]\n", stderr);
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/berkeley/lpr.c b/berkeley/lpr.c
new file mode 100644
index 000000000..5c318c283
--- /dev/null
+++ b/berkeley/lpr.c
@@ -0,0 +1,455 @@
+/*
+ * "$Id$"
+ *
+ * "lpr" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and send files for printing.
+ * sighandler() - Signal catcher for when we print from stdin...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <cups/string.h>
+#include <cups/cups.h>
+
+
+#ifndef WIN32
+# include <unistd.h>
+# include <signal.h>
+
+
+/*
+ * Local functions.
+ */
+
+void sighandler(int);
+#endif /* !WIN32 */
+
+
+/*
+ * Globals...
+ */
+
+char tempfile[1024]; /* Temporary file for printing from stdin */
+
+
+/*
+ * 'main()' - Parse options and send files for printing.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping var */
+ int job_id; /* Job ID */
+ char ch; /* Option character */
+ char *printer, /* Destination printer or class */
+ *instance; /* Instance */
+ const char *title, /* Job title */
+ *val; /* Environment variable name */
+ int num_copies; /* Number of copies per file */
+ int num_files; /* Number of files to print */
+ const char *files[1000]; /* Files to print */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests, /* Destinations */
+ *dest; /* Selected destination */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ int deletefile; /* Delete file after print? */
+ char buffer[8192]; /* Copy buffer */
+ int temp; /* Temporary file descriptor */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Signal action */
+ struct sigaction oldaction; /* Old signal action */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ deletefile = 0;
+ printer = NULL;
+ num_dests = 0;
+ dests = NULL;
+ num_options = 0;
+ options = NULL;
+ num_files = 0;
+ title = NULL;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (ch = argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case '1' : /* TROFF font set 1 */
+ case '2' : /* TROFF font set 2 */
+ case '3' : /* TROFF font set 3 */
+ case '4' : /* TROFF font set 4 */
+ case 'i' : /* indent */
+ case 'w' : /* width */
+ if (argv[i][2] == '\0')
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fprintf(stderr, "lpr: error - expected value after -%c option!\n", ch);
+ return (1);
+ }
+ }
+
+ case 'c' : /* CIFPLOT */
+ case 'd' : /* DVI */
+ case 'f' : /* FORTRAN */
+ case 'g' : /* plot */
+ case 'n' : /* Ditroff */
+ case 't' : /* Troff */
+ case 'v' : /* Raster image */
+ fprintf(stderr, "lpr: warning - \'%c\' format modifier not supported - output may not be correct!\n",
+ ch);
+ break;
+
+ case 'o' : /* Option */
+ if (argv[i][2] != '\0')
+ num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fputs("lpr: error - expected option=value after -o option!\n", stderr);
+ return (1);
+ }
+
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+ }
+ break;
+
+ case 'l' : /* Literal/raw */
+ num_options = cupsAddOption("raw", "", num_options, &options);
+ break;
+
+ case 'p' : /* Prettyprint */
+ num_options = cupsAddOption("prettyprint", "", num_options, &options);
+ break;
+
+ case 'h' : /* Suppress burst page */
+ num_options = cupsAddOption("job-sheets", "none", num_options, &options);
+ break;
+
+ case 's' : /* Don't use symlinks */
+ break;
+
+ case 'm' : /* Mail on completion */
+ fputs("lpr: warning - email notification is not currently supported!\n", stderr);
+ break;
+
+ case 'q' : /* Queue file but don't print */
+ num_options = cupsAddOption("job-hold-until", "indefinite",
+ num_options, &options);
+ break;
+
+ case 'r' : /* Remove file after printing */
+ deletefile = 1;
+ break;
+
+ case 'P' : /* Destination printer or class */
+ if (argv[i][2] != '\0')
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fputs("lpr: error - expected destination after -P option!\n", stderr);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
+ {
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ }
+ break;
+
+ case '#' : /* Number of copies */
+ if (argv[i][2] != '\0')
+ num_copies = atoi(argv[i] + 2);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fputs("lpr: error - expected copy count after -# option!\n", stderr);
+ return (1);
+ }
+
+ num_copies = atoi(argv[i]);
+ }
+
+ sprintf(buffer, "%d", num_copies);
+ num_options = cupsAddOption("copies", buffer, num_options, &options);
+ break;
+
+ case 'C' : /* Class */
+ case 'J' : /* Job name */
+ case 'T' : /* Title */
+ if (argv[i][2] != '\0')
+ title = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fprintf(stderr, "lpr: error - expected name after -%c option!\n", ch);
+ return (1);
+ }
+
+ title = argv[i];
+ }
+ break;
+
+ case 'U' : /* User */
+ if (argv[i][2] != '\0')
+ cupsSetUser(argv[i] + 2);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fputs("lpr: error - expected username after -U option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetUser(argv[i]);
+ }
+ break;
+
+ default :
+ fprintf(stderr, "lpr: error - unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else if (num_files < 1000)
+ {
+ /*
+ * Print a file...
+ */
+
+ if (access(argv[i], R_OK) != 0)
+ {
+ fprintf(stderr, "lpr: error - unable to access \"%s\" - %s\n", argv[i],
+ strerror(errno));
+ return (1);
+ }
+
+ files[num_files] = argv[i];
+ num_files ++;
+
+ if (title == NULL)
+ {
+ if ((title = strrchr(argv[i], '/')) != NULL)
+ title ++;
+ else
+ title = argv[i];
+ }
+ }
+ else
+ fprintf(stderr, "lpr: error - too many files - \"%s\"\n", argv[i]);
+ /*
+ * See if we have any files to print; if not, print from stdin...
+ */
+
+ if (printer == NULL)
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
+ {
+ printer = dest->name;
+
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ val = NULL;
+
+ if ((printer = getenv("LPDEST")) == NULL)
+ {
+ if ((printer = getenv("PRINTER")) != NULL)
+ {
+ if (!strcmp(printer, "lp"))
+ printer = NULL;
+ else
+ val = "PRINTER";
+ }
+ }
+ else
+ val = "LPDEST";
+
+ if (printer && !cupsGetDest(printer, NULL, num_dests, dests))
+ fprintf(stderr, "lpr: error - %s environment variable names non-existent destination \"%s\"!\n",
+ val, printer);
+ else if (cupsLastError() == IPP_NOT_FOUND)
+ fputs("lpr: error - no default destination available.\n", stderr);
+ else
+ fputs("lpr: error - scheduler not responding!\n", stderr);
+
+ return (1);
+ }
+
+ if (num_files > 0)
+ {
+ job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
+
+ if (deletefile && job_id > 0)
+ {
+ /*
+ * Delete print files after printing...
+ */
+
+ for (i = 0; i < num_files; i ++)
+ unlink(files[i]);
+ }
+ }
+ else
+ {
+ num_files = 1;
+
+#ifndef WIN32
+# if defined(HAVE_SIGSET)
+ sigset(SIGHUP, sighandler);
+ if (sigset(SIGINT, sighandler) == SIG_IGN)
+ sigset(SIGINT, SIG_IGN);
+ sigset(SIGTERM, sighandler);
+# elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = sighandler;
+
+ sigaction(SIGHUP, &action, NULL);
+ sigaction(SIGINT, NULL, &oldaction);
+ if (oldaction.sa_handler != SIG_IGN)
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+# else
+ signal(SIGHUP, sighandler);
+ if (signal(SIGINT, sighandler) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, sighandler);
+# endif
+#endif /* !WIN32 */
+
+ if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ {
+ fprintf(stderr, "lpr: error - unable to create temporary file \"%s\" - %s\n",
+ tempfile, strerror(errno));
+ return (1);
+ }
+
+ while ((i = read(0, buffer, sizeof(buffer))) > 0)
+ write(temp, buffer, i);
+
+ i = lseek(temp, 0, SEEK_CUR);
+ close(temp);
+
+ if (i == 0)
+ {
+ fputs("lpr: error - stdin is empty, so no job has been sent.\n", stderr);
+ return (1);
+ }
+
+ if (title)
+ job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
+ else
+ job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
+
+ unlink(tempfile);
+ }
+
+ if (job_id < 1)
+ {
+ fprintf(stderr, "lpr: error - unable to print file: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+#ifndef WIN32
+/*
+ * 'sighandler()' - Signal catcher for when we print from stdin...
+ */
+
+void
+sighandler(int s) /* I - Signal number */
+{
+ /*
+ * Remove the temporary file we're using to print from stdin...
+ */
+
+ unlink(tempfile);
+
+ /*
+ * Exit...
+ */
+
+ exit(s);
+}
+#endif /* !WIN32 */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/berkeley/lprm.c b/berkeley/lprm.c
new file mode 100644
index 000000000..3026ccb13
--- /dev/null
+++ b/berkeley/lprm.c
@@ -0,0 +1,276 @@
+/*
+ * "$Id$"
+ *
+ * "lprm" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and cancel jobs.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/string.h>
+
+
+/*
+ * 'main()' - Parse options and cancel jobs.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* HTTP connection to server */
+ int i; /* Looping var */
+ int job_id; /* Job ID */
+ const char *dest; /* Destination printer */
+ char *instance; /* Pointer to instance name */
+ char uri[1024]; /* Printer or job URI */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_op_t op; /* Operation */
+ cups_lang_t *language; /* Language */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+ http_encryption_t encryption; /* Encryption? */
+
+
+ /*
+ * Setup to cancel individual print jobs...
+ */
+
+ op = IPP_CANCEL_JOB;
+ job_id = 0;
+ dest = NULL;
+ response = NULL;
+ http = NULL;
+ encryption = cupsEncryption();
+
+ num_dests = cupsGetDests(&dests);
+
+ for (i = 0; i < num_dests; i ++)
+ if (dests[i].is_default)
+ dest = dests[i].name;
+
+ /*
+ * Open a connection to the server...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL)
+ {
+ fputs("lprm: Unable to contact server!\n", stderr);
+ cupsFreeDests(num_dests, dests);
+ return (1);
+ }
+
+ /*
+ * Process command-line arguments...
+ */
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-' && argv[i][1] != '\0')
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ encryption = HTTP_ENCRYPT_REQUIRED;
+
+ httpEncryption(http, encryption);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'P' : /* Cancel jobs on a printer */
+ if (argv[i][2])
+ dest = argv[i] + 2;
+ else
+ {
+ i ++;
+ dest = argv[i];
+ }
+
+ if ((instance = strchr(dest, '/')) != NULL)
+ *instance = '\0';
+
+ if (cupsGetDest(dest, NULL, num_dests, dests) == NULL)
+ {
+ fprintf(stderr, "lprm: Unknown destination \"%s\"!\n", dest);
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+ return(1);
+ }
+ break;
+
+ default :
+ fprintf(stderr, "lprm: Unknown option \'%c\'!\n", argv[i][1]);
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+ return (1);
+ }
+ else
+ {
+ /*
+ * Cancel a job or printer...
+ */
+
+ if (isdigit(argv[i][0] & 255) &&
+ cupsGetDest(argv[i], NULL, num_dests, dests) == NULL)
+ {
+ dest = NULL;
+ op = IPP_CANCEL_JOB;
+ job_id = atoi(argv[i]);
+ }
+ else if (strcmp(argv[i], "-") == 0)
+ {
+ /*
+ * Cancel all jobs
+ */
+
+ op = IPP_PURGE_JOBS;
+ }
+ else
+ {
+ dest = argv[i];
+ job_id = 0;
+ }
+
+ /*
+ * Build an IPP request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri + job-id *or* job-uri
+ * [requesting-user-name]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (dest)
+ {
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+ job_id);
+ }
+ else
+ {
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
+ uri);
+ }
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if (op == IPP_PURGE_JOBS)
+ response = cupsDoRequest(http, request, "/admin/");
+ else
+ response = cupsDoRequest(http, request, "/jobs/");
+
+ if (response != NULL)
+ {
+ switch (response->request.status.status_code)
+ {
+ case IPP_NOT_FOUND :
+ fputs("lprm: Job or printer not found!\n", stderr);
+ break;
+ case IPP_NOT_AUTHORIZED :
+ fputs("lprm: Not authorized to lprm job(s)!\n", stderr);
+ break;
+ case IPP_FORBIDDEN :
+ fprintf(stderr, "lprm: You don't own job ID %d!\n", job_id);
+ break;
+ default :
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ fputs("lprm: Unable to lprm job(s)!\n", stderr);
+ break;
+ }
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ ippDelete(response);
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fputs("lprm: Unable to cancel job(s)!\n", stderr);
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+ return (1);
+ }
+ }
+
+ /*
+ * If nothing has been cancelled yet, cancel the current job on the specified
+ * (or default) printer...
+ */
+
+ if (response == NULL)
+ if (!cupsCancelJob(dest, 0))
+ {
+ fputs("lprm: Unable to cancel job(s)!\n", stderr);
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+ return (1);
+ }
+
+ cupsFreeDests(num_dests, dests);
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/.cvsignore b/cgi-bin/.cvsignore
new file mode 100644
index 000000000..77c74e433
--- /dev/null
+++ b/cgi-bin/.cvsignore
@@ -0,0 +1,5 @@
+admin.cgi
+classes.cgi
+jobs.cgi
+libcgi.a
+printers.cgi
diff --git a/cgi-bin/Dependencies b/cgi-bin/Dependencies
new file mode 100644
index 000000000..d69abebfa
--- /dev/null
+++ b/cgi-bin/Dependencies
@@ -0,0 +1,20 @@
+# DO NOT DELETE
+
+html.o: cgi.h ../cups/string.h ../config.h
+ipp-var.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+ipp-var.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h
+ipp-var.o: ../cups/string.h ../config.h cgi.h
+template.o: cgi.h ../cups/string.h ../config.h
+var.o: cgi.h ../cups/string.h ../config.h
+admin.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+admin.o: ../cups/ppd.h ../cups/debug.h ../cups/language.h ../cups/string.h
+admin.o: ../config.h cgi.h
+classes.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+classes.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h
+classes.o: ../cups/string.h ../config.h cgi.h
+jobs.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+jobs.o: ../cups/ppd.h ../cups/debug.h ../cups/language.h ../cups/string.h
+jobs.o: ../config.h cgi.h
+printers.o: ipp-var.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+printers.o: ../cups/md5.h ../cups/ppd.h ../cups/debug.h ../cups/language.h
+printers.o: ../cups/string.h ../config.h cgi.h
diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile
new file mode 100644
index 000000000..b8718b907
--- /dev/null
+++ b/cgi-bin/Makefile
@@ -0,0 +1,123 @@
+#
+# "$Id$"
+#
+# CGI makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+CGIS = admin.cgi classes.cgi jobs.cgi printers.cgi
+TARGETS = libcgi.a $(CGIS)
+LIBOBJS = html.o ipp-var.o template.o var.o
+OBJS = $(LIBOBJS) admin.o classes.o jobs.o printers.o
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS)
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install: all
+ $(INSTALL_DIR) $(SERVERBIN)/cgi-bin
+ for file in $(CGIS); do \
+ $(INSTALL_BIN) $$file $(SERVERBIN)/cgi-bin; \
+ done
+
+
+#
+# libcgi.a
+#
+
+libcgi.a: $(LIBOBJS)
+ echo Archiving $@...
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $(LIBOBJS)
+ $(RANLIB) $@
+
+
+#
+# admin.cgi
+#
+
+admin.cgi: admin.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ admin.o libcgi.a $(LIBS)
+
+
+#
+# classes.cgi
+#
+
+classes.cgi: classes.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ classes.o libcgi.a $(LIBS)
+
+
+#
+# jobs.cgi
+#
+
+jobs.cgi: jobs.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ jobs.o libcgi.a $(LIBS)
+
+
+#
+# printers.cgi
+#
+
+printers.cgi: printers.o ../Makedefs ../cups/$(LIBCUPS) libcgi.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ printers.o libcgi.a $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c
new file mode 100644
index 000000000..2655ecbaa
--- /dev/null
+++ b/cgi-bin/admin.c
@@ -0,0 +1,1605 @@
+/*
+ * "$Id$"
+ *
+ * Administration CGI for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for CGI.
+ * do_am_class() - Add or modify a class.
+ * do_am_printer() - Add or modify a printer.
+ * do_config_printer() - Configure the default options for a printer.
+ * do_delete_class() - Delete a class...
+ * do_delete_printer() - Delete a printer...
+ * do_printer_op() - Do a printer operation.
+ * get_line() - Get a line that is terminated by a LF, CR, or CR LF.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ipp-var.h"
+#include <ctype.h>
+#include <errno.h>
+
+
+/*
+ * Local functions...
+ */
+
+static void do_am_class(http_t *http, cups_lang_t *language, int modify);
+static void do_am_printer(http_t *http, cups_lang_t *language, int modify);
+static void do_config_printer(http_t *http, cups_lang_t *language);
+static void do_delete_class(http_t *http, cups_lang_t *language);
+static void do_delete_printer(http_t *http, cups_lang_t *language);
+static void do_printer_op(http_t *http, cups_lang_t *language, ipp_op_t op);
+static char *get_line(char *buf, int length, FILE *fp);
+
+
+/*
+ * 'main()' - Main entry for CGI.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ cups_lang_t *language; /* Language information */
+ http_t *http; /* Connection to the server */
+ const char *op; /* Operation name */
+
+
+ /*
+ * Get the request language...
+ */
+
+ language = cupsLangDefault();
+
+ /*
+ * Send a standard header...
+ */
+
+ printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language));
+
+ cgiSetVariable("TITLE", "Admin");
+ ippSetServerVersion();
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG"));
+
+ /*
+ * See if we have form data...
+ */
+
+ if (!cgiInitialize())
+ {
+ /*
+ * Nope, send the administration menu...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "admin.tmpl", getenv("LANG"));
+ }
+ else if ((op = cgiGetVariable("OP")) != NULL)
+ {
+ /*
+ * Connect to the HTTP server...
+ */
+
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
+
+ /*
+ * Do the operation...
+ */
+
+ if (strcmp(op, "start-printer") == 0)
+ do_printer_op(http, language, IPP_RESUME_PRINTER);
+ else if (strcmp(op, "stop-printer") == 0)
+ do_printer_op(http, language, IPP_PAUSE_PRINTER);
+ else if (strcmp(op, "accept-jobs") == 0)
+ do_printer_op(http, language, CUPS_ACCEPT_JOBS);
+ else if (strcmp(op, "reject-jobs") == 0)
+ do_printer_op(http, language, CUPS_REJECT_JOBS);
+ else if (strcmp(op, "purge-jobs") == 0)
+ do_printer_op(http, language, IPP_PURGE_JOBS);
+ else if (strcmp(op, "set-as-default") == 0)
+ do_printer_op(http, language, CUPS_SET_DEFAULT);
+ else if (strcmp(op, "add-class") == 0)
+ do_am_class(http, language, 0);
+ else if (strcmp(op, "add-printer") == 0)
+ do_am_printer(http, language, 0);
+ else if (strcmp(op, "modify-class") == 0)
+ do_am_class(http, language, 1);
+ else if (strcmp(op, "modify-printer") == 0)
+ do_am_printer(http, language, 1);
+ else if (strcmp(op, "delete-class") == 0)
+ do_delete_class(http, language);
+ else if (strcmp(op, "delete-printer") == 0)
+ do_delete_printer(http, language);
+ else if (strcmp(op, "config-printer") == 0)
+ do_config_printer(http, language);
+ else
+ {
+ /*
+ * Bad operation code... Display an error...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG"));
+ }
+
+ /*
+ * Close the HTTP server connection...
+ */
+
+ httpClose(http);
+ }
+ else
+ {
+ /*
+ * Form data but no operation code... Display an error...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "admin-op.tmpl", getenv("LANG"));
+ }
+
+ /*
+ * Send the standard trailer...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG"));
+
+ /*
+ * Free the request language...
+ */
+
+ cupsLangFree(language);
+
+ /*
+ * Return with no errors...
+ */
+
+ return (0);
+}
+
+
+/*
+ * 'do_am_class()' - Add or modify a class.
+ */
+
+static void
+do_am_class(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language, /* I - Client's language */
+ int modify) /* I - Modify the printer? */
+{
+ int i, j; /* Looping vars */
+ int element; /* Element number */
+ int num_printers; /* Number of printers */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* member-uris attribute */
+ ipp_status_t status; /* Request status */
+ char uri[HTTP_MAX_URI]; /* Device or printer URI */
+ const char *name, /* Pointer to class name */
+ *ptr; /* Pointer to CGI variable */
+
+
+ if (cgiGetVariable("PRINTER_LOCATION") == NULL)
+ {
+ if (modify)
+ {
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+ }
+
+ /*
+ * Update the location and description of an existing printer...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "modify-class.tmpl", getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Get the name, location, and description for a new printer...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "add-class.tmpl", getenv("LANG"));
+ }
+
+ return;
+ }
+
+ name = cgiGetVariable("PRINTER_NAME");
+ for (ptr = name; *ptr; ptr ++)
+ if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/')
+ break;
+
+ if (*ptr || ptr == name || strlen(name) > 127)
+ {
+ cgiSetVariable("ERROR", "The class name may only contain up to 127 printable "
+ "characters and may not contain spaces.");
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ if (cgiGetVariable("MEMBER_URIS") == NULL)
+ {
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * Create MEMBER_URIS and MEMBER_NAMES arrays...
+ */
+
+ for (element = 0, attr = response->attrs;
+ attr != NULL;
+ attr = attr->next)
+ if (attr->name && strcmp(attr->name, "printer-uri-supported") == 0)
+ {
+ cgiSetArray("MEMBER_URIS", element, attr->values[0].string.text);
+ element ++;
+ }
+
+ for (element = 0, attr = response->attrs;
+ attr != NULL;
+ attr = attr->next)
+ if (attr->name && strcmp(attr->name, "printer-name") == 0)
+ {
+ cgiSetArray("MEMBER_NAMES", element, attr->values[0].string.text);
+ element ++;
+ }
+
+ num_printers = cgiGetSize("MEMBER_URIS");
+
+ ippDelete(response);
+ }
+ else
+ num_printers = 0;
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Mark any current members in the class...
+ */
+
+ for (j = 0; j < num_printers; j ++)
+ cgiSetArray("MEMBER_SELECTED", j, "");
+
+ for (i = 0; i < attr->num_values; i ++)
+ for (j = 0; j < num_printers; j ++)
+ if (strcmp(attr->values[i].string.text, cgiGetArray("MEMBER_URIS", j)) == 0)
+ {
+ cgiSetArray("MEMBER_SELECTED", j, "SELECTED");
+ break;
+ }
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Let the user choose...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-members.tmpl", getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Build a CUPS_ADD_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * printer-location
+ * printer-info
+ * printer-is-accepting-jobs
+ * printer-state
+ * member-uris
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_CLASS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
+ NULL, cgiGetVariable("PRINTER_LOCATION"));
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
+ NULL, cgiGetVariable("PRINTER_INFO"));
+
+ ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
+
+ ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ IPP_PRINTER_IDLE);
+
+ if ((num_printers = cgiGetSize("MEMBER_URIS")) > 0)
+ {
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
+ num_printers, NULL, NULL);
+ for (i = 0; i < num_printers; i ++)
+ attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i));
+ }
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ status = response->request.status.status_code;
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else if (modify)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "class-modified.tmpl", getenv("LANG"));
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "class-added.tmpl", getenv("LANG"));
+ }
+}
+
+
+/*
+ * 'do_am_printer()' - Add or modify a printer.
+ */
+
+static void
+do_am_printer(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language, /* I - Client's language */
+ int modify) /* I - Modify the printer? */
+{
+ int i; /* Looping var */
+ int element; /* Element number */
+ ipp_attribute_t *attr, /* Current attribute */
+ *last; /* Last attribute */
+ ipp_t *request, /* IPP request */
+ *response, /* IPP response */
+ *oldinfo; /* Old printer information */
+ ipp_status_t status; /* Request status */
+ const char *var; /* CGI variable */
+ char uri[HTTP_MAX_URI], /* Device or printer URI */
+ *uriptr; /* Pointer into URI */
+ int maxrate; /* Maximum baud rate */
+ char baudrate[255]; /* Baud rate string */
+ char make[255]; /* Make string */
+ const char *name, /* Pointer to class name */
+ *ptr; /* Pointer to CGI variable */
+ static int baudrates[] = /* Baud rates */
+ {
+ 1200,
+ 2400,
+ 4800,
+ 9600,
+ 19200,
+ 38400,
+ 57600,
+ 115200,
+ 230400,
+ 460800
+ };
+
+
+ if (modify)
+ {
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ oldinfo = cupsDoRequest(http, request, "/");
+ }
+ else
+ oldinfo = NULL;
+
+ if ((name = cgiGetVariable("PRINTER_NAME")) == NULL ||
+ cgiGetVariable("PRINTER_LOCATION") == NULL)
+ {
+ if (modify)
+ {
+ /*
+ * Update the location and description of an existing printer...
+ */
+
+ if (oldinfo)
+ ippSetCGIVars(oldinfo, NULL, NULL, NULL, 0);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "modify-printer.tmpl", getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Get the name, location, and description for a new printer...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "add-printer.tmpl", getenv("LANG"));
+ }
+
+ if (oldinfo)
+ ippDelete(oldinfo);
+
+ return;
+ }
+
+ for (ptr = name; *ptr; ptr ++)
+ if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/')
+ break;
+
+ if (*ptr || ptr == name || strlen(name) > 127)
+ {
+ cgiSetVariable("ERROR", "The printer name may only contain up to 127 printable "
+ "characters and may not contain spaces.");
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ if ((var = cgiGetVariable("DEVICE_URI")) == NULL)
+ {
+ /*
+ * Build a CUPS_GET_DEVICES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_DEVICES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+ }
+
+ /*
+ * Let the user choose...
+ */
+
+ if (oldinfo &&
+ (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
+ {
+ strlcpy(uri, attr->values[0].string.text, sizeof(uri));
+ if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0)
+ *uriptr = '\0';
+
+ cgiSetVariable("CURRENT_DEVICE_URI", uri);
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-device.tmpl", getenv("LANG"));
+ }
+ else if (strchr(var, '/') == NULL)
+ {
+ if (oldinfo &&
+ (attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Set the current device URI for the form to the old one...
+ */
+
+ if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0)
+ cgiSetVariable("DEVICE_URI", attr->values[0].string.text);
+ }
+
+ /*
+ * User needs to set the full URI...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-uri.tmpl", getenv("LANG"));
+ }
+ else if (strncmp(var, "serial:", 7) == 0 && cgiGetVariable("BAUDRATE") == NULL)
+ {
+ /*
+ * Need baud rate, parity, etc.
+ */
+
+ if ((var = strchr(var, '?')) != NULL &&
+ strncmp(var, "?baud=", 6) == 0)
+ maxrate = atoi(var + 6);
+ else
+ maxrate = 19200;
+
+ for (i = 0; i < 10; i ++)
+ if (baudrates[i] > maxrate)
+ break;
+ else
+ {
+ sprintf(baudrate, "%d", baudrates[i]);
+ cgiSetArray("BAUDRATES", i, baudrate);
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-serial.tmpl", getenv("LANG"));
+ }
+ else if ((var = cgiGetVariable("PPD_NAME")) == NULL)
+ {
+ if (modify)
+ {
+ /*
+ * Get the PPD file...
+ */
+
+ int fd; /* PPD file */
+ char filename[1024]; /* PPD filename */
+ ppd_file_t *ppd; /* PPD information */
+ char buffer[1024]; /* Buffer */
+ int bytes; /* Number of bytes */
+
+
+ snprintf(uri, sizeof(uri), "/printers/%s.ppd", name);
+
+ if (httpGet(http, uri))
+ httpGet(http, uri);
+
+ while (httpUpdate(http) == HTTP_CONTINUE);
+
+ if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0)
+ {
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ write(fd, buffer, bytes);
+
+ close(fd);
+
+ if ((ppd = ppdOpenFile(filename)) != NULL)
+ {
+ if (ppd->manufacturer)
+ cgiSetVariable("CURRENT_MAKE", ppd->manufacturer);
+ if (ppd->nickname)
+ cgiSetVariable("CURRENT_MAKE_AND_MODEL", ppd->nickname);
+
+ ppdClose(ppd);
+ }
+
+ unlink(filename);
+ }
+ else
+ httpFlush(http);
+ }
+
+ /*
+ * Build a CUPS_GET_PPDS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PPDS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((var = cgiGetVariable("PPD_MAKE")) == NULL)
+ {
+ /*
+ * Let the user choose a make...
+ */
+
+ for (element = 0, attr = response->attrs, last = NULL;
+ attr != NULL;
+ attr = attr->next)
+ if (attr->name && strcmp(attr->name, "ppd-make") == 0)
+ if (last == NULL ||
+ strcasecmp(last->values[0].string.text,
+ attr->values[0].string.text) != 0)
+ {
+ cgiSetArray("PPD_MAKE", element, attr->values[0].string.text);
+ element ++;
+ last = attr;
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-make.tmpl",
+ getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Let the user choose a model...
+ */
+
+ strlcpy(make, var, sizeof(make));
+
+ ippSetCGIVars(response, "ppd-make", make, NULL, 0);
+ cgiCopyTemplateLang(stdout, TEMPLATES, "choose-model.tmpl",
+ getenv("LANG"));
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ char message[1024];
+
+
+ snprintf(message, sizeof(message), "Unable to get list of printer drivers: %s",
+ ippErrorString(cupsLastError()));
+ cgiSetVariable("ERROR", message);
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ }
+ else
+ {
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * printer-location
+ * printer-info
+ * ppd-name
+ * device-uri
+ * printer-is-accepting-jobs
+ * printer-state
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
+ NULL, cgiGetVariable("PRINTER_LOCATION"));
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
+ NULL, cgiGetVariable("PRINTER_INFO"));
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
+ NULL, cgiGetVariable("PPD_NAME"));
+
+ strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri));
+ if (strncmp(uri, "serial:", 7) == 0)
+ {
+ /*
+ * Update serial port URI to include baud rate, etc.
+ */
+
+ if ((uriptr = strchr(uri, '?')) == NULL)
+ uriptr = uri + strlen(uri);
+
+ snprintf(uriptr, sizeof(uri) - (uriptr - uri),
+ "?baud=%s+bits=%s+parity=%s+flow=%s",
+ cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"),
+ cgiGetVariable("PARITY"), cgiGetVariable("FLOW"));
+ }
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri",
+ NULL, uri);
+
+ ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
+
+ ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ IPP_PRINTER_IDLE);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ status = response->request.status.status_code;
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else if (modify)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-modified.tmpl", getenv("LANG"));
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-added.tmpl", getenv("LANG"));
+ }
+
+ if (oldinfo)
+ ippDelete(oldinfo);
+}
+
+
+/*
+ * 'do_config_printer()' - Configure the default options for a printer.
+ */
+
+static void
+do_config_printer(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language)/* I - Client's language */
+{
+ int i, j, k; /* Looping vars */
+ int have_options; /* Have options? */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *var; /* Variable value */
+ const char *printer; /* Printer printer name */
+ ipp_status_t status; /* Operation status... */
+ const char *filename; /* PPD filename */
+ char tempfile[1024]; /* Temporary filename */
+ FILE *in, /* Input file */
+ *out; /* Output file */
+ int outfd; /* Output file descriptor */
+ char line[1024]; /* Line from PPD file */
+ char keyword[1024], /* Keyword from Default line */
+ *keyptr; /* Pointer into keyword... */
+ ppd_file_t *ppd; /* PPD file */
+ ppd_group_t *group; /* Option group */
+ ppd_option_t *option; /* Option */
+ ppd_attr_t *protocol; /* cupsProtocol attribute */
+
+
+ /*
+ * Get the printer name...
+ */
+
+ if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+ else
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ /*
+ * Get the PPD file...
+ */
+
+ cupsSetServer("localhost");
+
+ if ((filename = cupsGetPPD(printer)) == NULL)
+ {
+ if (cupsLastError() == IPP_NOT_FOUND)
+ {
+ /*
+ * No PPD file for this printer, so we can't configure it!
+ */
+
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_POSSIBLE));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Unable to access the PPD file for some reason...
+ */
+
+ cgiSetVariable("ERROR", ippErrorString(cupsLastError()));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ return;
+ }
+
+ if ((ppd = ppdOpenFile(filename)) == NULL)
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_DEVICE_ERROR));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ if (cgiGetVariable("job_sheets_start") != NULL ||
+ cgiGetVariable("job_sheets_end") != NULL)
+ have_options = 1;
+ else
+ have_options = 0;
+
+ ppdMarkDefaults(ppd);
+
+ DEBUG_printf(("<P>ppd->num_groups = %d\n"
+ "<UL>\n", ppd->num_groups));
+
+ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+ {
+ DEBUG_printf(("<LI>%s<UL>\n", group->text));
+
+ for (j = group->num_options, option = group->options; j > 0; j --, option ++)
+ if ((var = cgiGetVariable(option->keyword)) != NULL)
+ {
+ DEBUG_printf(("<LI>%s = \"%s\"</LI>\n", option->keyword, var));
+ have_options = 1;
+ ppdMarkOption(ppd, option->keyword, var);
+ }
+#ifdef DEBUG
+ else
+ printf("<LI>%s not defined!</LI>\n", option->keyword);
+#endif /* DEBUG */
+
+ DEBUG_puts("</UL></LI>");
+ }
+
+ DEBUG_printf(("</UL>\n"
+ "<P>ppdConflicts(ppd) = %d\n", ppdConflicts(ppd)));
+
+ if (!have_options || ppdConflicts(ppd))
+ {
+ /*
+ * Show the options to the user...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer.tmpl",
+ getenv("LANG"));
+
+ if (ppdConflicts(ppd))
+ {
+ for (i = ppd->num_groups, k = 0, group = ppd->groups; i > 0; i --, group ++)
+ for (j = group->num_options, option = group->options; j > 0; j --, option ++)
+ if (option->conflicted)
+ {
+ cgiSetArray("ckeyword", k, option->keyword);
+ cgiSetArray("ckeytext", k, option->text);
+ k ++;
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-conflict.tmpl",
+ getenv("LANG"));
+ }
+
+ for (i = ppd->num_groups, group = ppd->groups;
+ i > 0;
+ i --, group ++)
+ {
+ if (strcmp(group->text, "InstallableOptions") == 0)
+ cgiSetVariable("GROUP",
+ cupsLangString(language, CUPS_MSG_OPTIONS_INSTALLED));
+ else
+ cgiSetVariable("GROUP", group->text);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl",
+ getenv("LANG"));
+
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ {
+ if (strcmp(option->keyword, "PageRegion") == 0)
+ continue;
+
+ cgiSetVariable("KEYWORD", option->keyword);
+ cgiSetVariable("KEYTEXT", option->text);
+
+ if (option->conflicted)
+ cgiSetVariable("CONFLICTED", "1");
+ else
+ cgiSetVariable("CONFLICTED", "0");
+
+ cgiSetSize("CHOICES", option->num_choices);
+ cgiSetSize("TEXT", option->num_choices);
+ for (k = 0; k < option->num_choices; k ++)
+ {
+ cgiSetArray("CHOICES", k, option->choices[k].choice);
+ cgiSetArray("TEXT", k, option->choices[k].text);
+
+ if (option->choices[k].marked)
+ cgiSetVariable("DEFCHOICE", option->choices[k].choice);
+ }
+
+ switch (option->ui)
+ {
+ case PPD_UI_BOOLEAN :
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-boolean.tmpl",
+ getenv("LANG"));
+ break;
+ case PPD_UI_PICKONE :
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl",
+ getenv("LANG"));
+ break;
+ case PPD_UI_PICKMANY :
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickmany.tmpl",
+ getenv("LANG"));
+ break;
+ }
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl",
+ getenv("LANG"));
+ }
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((attr = ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO)) != NULL)
+ {
+ /*
+ * Add the job sheets options...
+ */
+
+ cgiSetVariable("GROUP", "Banners");
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl",
+ getenv("LANG"));
+
+ cgiSetSize("CHOICES", attr->num_values);
+ cgiSetSize("TEXT", attr->num_values);
+ for (k = 0; k < attr->num_values; k ++)
+ {
+ cgiSetArray("CHOICES", k, attr->values[k].string.text);
+ cgiSetArray("TEXT", k, attr->values[k].string.text);
+ }
+
+ attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
+
+ cgiSetVariable("KEYWORD", "job_sheets_start");
+ cgiSetVariable("KEYTEXT", "Starting Banner");
+ cgiSetVariable("DEFCHOICE", attr == NULL ?
+ "" : attr->values[0].string.text);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl",
+ getenv("LANG"));
+
+ cgiSetVariable("KEYWORD", "job_sheets_end");
+ cgiSetVariable("KEYTEXT", "Ending Banner");
+ cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ?
+ "" : attr->values[1].string.text);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl",
+ getenv("LANG"));
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl",
+ getenv("LANG"));
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Binary protocol support...
+ */
+
+ if (ppd->protocols && strstr(ppd->protocols, "BCP"))
+ {
+ protocol = ppdFindAttr(ppd, "cupsProtocol", NULL);
+
+ cgiSetVariable("GROUP", "PS Binary Protocol");
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-header.tmpl",
+ getenv("LANG"));
+
+ cgiSetSize("CHOICES", 2);
+ cgiSetSize("TEXT", 2);
+ cgiSetArray("CHOICES", 0, "None");
+ cgiSetArray("TEXT", 0, "None");
+
+ if (strstr(ppd->protocols, "TBCP"))
+ {
+ cgiSetArray("CHOICES", 1, "TBCP");
+ cgiSetArray("TEXT", 1, "TBCP");
+ }
+ else
+ {
+ cgiSetArray("CHOICES", 1, "BCP");
+ cgiSetArray("TEXT", 1, "BCP");
+ }
+
+ cgiSetVariable("KEYWORD", "protocol");
+ cgiSetVariable("KEYTEXT", "PS Binary Protocol");
+ cgiSetVariable("DEFCHOICE", protocol ? protocol->value : "None");
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-pickone.tmpl",
+ getenv("LANG"));
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "option-trailer.tmpl",
+ getenv("LANG"));
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "config-printer2.tmpl",
+ getenv("LANG"));
+ }
+ else
+ {
+ /*
+ * Set default options...
+ */
+
+ outfd = cupsTempFd(tempfile, sizeof(tempfile));
+ in = fopen(filename, "rb");
+ out = fdopen(outfd, "wb");
+
+ if (outfd < 0 || in == NULL || out == NULL)
+ {
+ cgiSetVariable("ERROR", strerror(errno));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ unlink(filename);
+ return;
+ }
+
+ while (get_line(line, sizeof(line), in) != NULL)
+ {
+ if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol"))
+ continue;
+ else if (strncmp(line, "*Default", 8))
+ fprintf(out, "%s\n", line);
+ else
+ {
+ /*
+ * Get default option name...
+ */
+
+ strlcpy(keyword, line + 8, sizeof(keyword));
+
+ for (keyptr = keyword; *keyptr; keyptr ++)
+ if (*keyptr == ':' || isspace(*keyptr & 255))
+ break;
+
+ *keyptr = '\0';
+
+ if (strcmp(keyword, "PageRegion") == 0)
+ var = cgiGetVariable("PageSize");
+ else
+ var = cgiGetVariable(keyword);
+
+ if (var != NULL)
+ fprintf(out, "*Default%s: %s\n", keyword, var);
+ else
+ fprintf(out, "%s\n", line);
+ }
+ }
+
+ if ((var = cgiGetVariable("protocol")) != NULL)
+ fprintf(out, "*cupsProtocol: %s\n", cgiGetVariable("protocol"));
+
+ fclose(in);
+ fclose(out);
+ close(outfd);
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * job-sheets-default
+ * [ppd file]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-default", 2, NULL, NULL);
+ attr->values[0].string.text = strdup(cgiGetVariable("job_sheets_start"));
+ attr->values[1].string.text = strdup(cgiGetVariable("job_sheets_end"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoFileRequest(http, request, "/admin/", tempfile)) != NULL)
+ {
+ status = response->request.status.status_code;
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-configured.tmpl", getenv("LANG"));
+
+ unlink(tempfile);
+ }
+
+ unlink(filename);
+}
+
+
+/*
+ * 'do_delete_class()' - Delete a class...
+ */
+
+static void
+do_delete_class(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language) /* I - Client's language */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *pclass; /* Printer class name */
+ ipp_status_t status; /* Operation status... */
+
+
+ if (cgiGetVariable("CONFIRM") == NULL)
+ {
+ cgiCopyTemplateLang(stdout, TEMPLATES, "class-confirm.tmpl", getenv("LANG"));
+ return;
+ }
+
+ if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL)
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass);
+ else
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ /*
+ * Build a CUPS_DELETE_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_DELETE_CLASS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ status = response->request.status.status_code;
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "class-deleted.tmpl", getenv("LANG"));
+}
+
+
+/*
+ * 'do_delete_printer()' - Delete a printer...
+ */
+
+static void
+do_delete_printer(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language)/* I - Client's language */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *printer; /* Printer printer name */
+ ipp_status_t status; /* Operation status... */
+
+
+ if (cgiGetVariable("CONFIRM") == NULL)
+ {
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-confirm.tmpl", getenv("LANG"));
+ return;
+ }
+
+ if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+ else
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ /*
+ * Build a CUPS_DELETE_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_DELETE_PRINTER;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ status = response->request.status.status_code;
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-deleted.tmpl", getenv("LANG"));
+}
+
+
+/*
+ * 'do_printer_op()' - Do a printer operation.
+ */
+
+static void
+do_printer_op(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language, /* I - Client's language */
+ ipp_op_t op) /* I - Operation to perform */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ const char *printer; /* Printer name (purge-jobs) */
+ ipp_status_t status; /* Operation status... */
+
+
+ if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+ else
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ /*
+ * Build a printer request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ status = response->request.status.status_code;
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else if (op == IPP_PAUSE_PRINTER)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-stop.tmpl", getenv("LANG"));
+ else if (op == IPP_RESUME_PRINTER)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-start.tmpl", getenv("LANG"));
+ else if (op == CUPS_ACCEPT_JOBS)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-accept.tmpl", getenv("LANG"));
+ else if (op == CUPS_REJECT_JOBS)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-reject.tmpl", getenv("LANG"));
+ else if (op == IPP_PURGE_JOBS)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-purge.tmpl", getenv("LANG"));
+ else if (op == CUPS_SET_DEFAULT)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printer-default.tmpl", getenv("LANG"));
+}
+
+
+/*
+ * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
+ */
+
+static char * /* O - Pointer to buf or NULL on EOF */
+get_line(char *buf, /* I - Line buffer */
+ int length, /* I - Length of buffer */
+ FILE *fp) /* I - File to read from */
+{
+ char *bufptr; /* Pointer into buffer */
+ int ch; /* Character from file */
+
+
+ length --;
+ bufptr = buf;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == '\n')
+ break;
+ else if (ch == '\r')
+ {
+ /*
+ * Look for LF...
+ */
+
+ ch = getc(fp);
+ if (ch != '\n' && ch != EOF)
+ ungetc(ch, fp);
+
+ break;
+ }
+
+ *bufptr++ = ch;
+ length --;
+ if (length == 0)
+ break;
+ }
+
+ *bufptr = '\0';
+
+ if (ch == EOF)
+ return (NULL);
+ else
+ return (buf);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/cgi.h b/cgi-bin/cgi.h
new file mode 100644
index 000000000..40e6c9caf
--- /dev/null
+++ b/cgi-bin/cgi.h
@@ -0,0 +1,86 @@
+/*
+ * "$Id$"
+ *
+ * CGI support library definitions.
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CGI_H_
+# define _CGI_H_
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <time.h>
+
+# include <cups/string.h>
+
+# ifdef WIN32
+# include <direct.h>
+# include <io.h>
+# include <malloc.h>
+# else
+# include <unistd.h>
+# endif /* WIN32 */
+
+
+/*
+ * Prototypes...
+ */
+
+extern int cgiInitialize(void);
+extern void cgiAbort(const char *title, const char *stylesheet,
+ const char *format, ...);
+extern int cgiCheckVariables(const char *names);
+extern const char *cgiGetArray(const char *name, int element);
+extern int cgiGetSize(const char *name);
+extern void cgiSetSize(const char *name, int size);
+extern const char *cgiGetVariable(const char *name);
+extern void cgiSetArray(const char *name, int element,
+ const char *value);
+extern void cgiSetVariable(const char *name, const char *value);
+extern void cgiCopyTemplateFile(FILE *out, const char *tmpl);
+extern void cgiCopyTemplateLang(FILE *out, const char *directory,
+ const char *tmpl, const char *lang);
+
+extern void cgiStartHTML(FILE *out, const char *author,
+ const char *stylesheet,
+ const char *keywords,
+ const char *description,
+ const char *title, ...);
+extern void cgiEndHTML(FILE *out);
+
+extern FILE *cgiEMailOpen(const char *from, const char *to,
+ const char *cc, const char *subject,
+ int multipart);
+extern void cgiEMailPart(FILE *mail, const char *type,
+ const char *charset, const char *encoding);
+extern void cgiEMailClose(FILE *mail);
+
+extern char *cgiGetCookie(const char *name, char *buf, int buflen);
+extern void cgiSetCookie(const char *name, const char *value,
+ const char *path, const char *domain,
+ time_t expires, int secure);
+
+# define cgiGetUser() getenv("REMOTE_USER")
+# define cgiGetHost() (getenv("REMOTE_HOST") == NULL ? getenv("REMOTE_ADDR") : getenv("REMOTE_HOST"))
+
+#endif /* !_CGI_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/classes.c b/cgi-bin/classes.c
new file mode 100644
index 000000000..2cba6397e
--- /dev/null
+++ b/cgi-bin/classes.c
@@ -0,0 +1,346 @@
+/*
+ * "$Id$"
+ *
+ * Class status CGI for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for CGI.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ipp-var.h"
+
+
+/*
+ * 'main()' - Main entry for CGI.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ cups_lang_t *language; /* Language information */
+ char *pclass; /* Printer class name */
+ http_t *http; /* Connection to the server */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ ipp_status_t status; /* Operation status... */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ const char *which_jobs; /* Which jobs to show */
+ const char *op; /* Operation to perform, if any */
+ static const char *def_attrs[] = /* Attributes for default printer */
+ {
+ "printer-name",
+ "printer-uri-supported"
+ };
+
+
+ /*
+ * Get any form variables...
+ */
+
+ cgiInitialize();
+ op = cgiGetVariable("OP");
+
+ /*
+ * Get the request language...
+ */
+
+ language = cupsLangDefault();
+
+ /*
+ * Connect to the HTTP server...
+ */
+
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
+
+ /*
+ * Tell the client to expect HTML...
+ */
+
+ printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language));
+
+ /*
+ * See if we need to show a list of printers or the status of a
+ * single printer...
+ */
+
+ ippSetServerVersion();
+
+ pclass = argv[0];
+ if (strcmp(pclass, "/") == 0 || strcmp(pclass, "classes.cgi") == 0)
+ {
+ pclass = NULL;
+ cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_CLASS));
+ }
+ else
+ cgiSetVariable("TITLE", pclass);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG"));
+
+ if (op == NULL || strcasecmp(op, "print-test-page") != 0)
+ {
+ /*
+ * Get the default destination...
+ */
+
+ request = ippNew();
+ request->request.op.operation_id = CUPS_GET_DEFAULT;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ sizeof(def_attrs) / sizeof(def_attrs[0]), NULL, def_attrs);
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
+ cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL)
+ {
+ char url[HTTP_MAX_URI]; /* New URL */
+
+
+ cgiSetVariable("DEFAULT_URI",
+ ippRewriteURL(attr->values[0].string.text,
+ url, sizeof(url), NULL));
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Get the class info...
+ */
+
+ request = ippNew();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (pclass == NULL)
+ {
+ /*
+ * Build a CUPS_GET_CLASSES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ */
+
+ request->request.op.operation_id = CUPS_GET_CLASSES;
+ request->request.op.request_id = 1;
+ }
+ else
+ {
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"),
+ pclass);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ uri);
+ }
+
+ ippGetAttributes(request, TEMPLATES, "classes.tmpl", getenv("LANG"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+ }
+
+ /*
+ * Write the report...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "classes.tmpl", getenv("LANG"));
+
+ /*
+ * Get jobs for the specified class if a class has been chosen...
+ */
+
+ if (pclass != NULL)
+ {
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s/classes/%s", getenv("SERVER_NAME"),
+ pclass);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ uri);
+
+ if ((which_jobs = cgiGetVariable("which_jobs")) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
+ NULL, which_jobs);
+
+ ippGetAttributes(request, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Print a test page...
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass);
+
+ /*
+ * Build an IPP_PRINT_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ * document-format
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ if (getenv("REMOTE_USER") != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, getenv("REMOTE_USER"));
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, "root");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+ NULL, "Test Page");
+
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/postscript");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoFileRequest(http, request, uri + 15,
+ CUPS_DATADIR "/data/testprint.ps")) != NULL)
+ {
+ status = response->request.status.status_code;
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ cgiSetVariable("PRINTER_NAME", pclass);
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG"));
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG"));
+
+ /*
+ * Close the HTTP server connection...
+ */
+
+ httpClose(http);
+ cupsLangFree(language);
+
+ /*
+ * Return with no errors...
+ */
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/html.c b/cgi-bin/html.c
new file mode 100644
index 000000000..7d7d5d8ba
--- /dev/null
+++ b/cgi-bin/html.c
@@ -0,0 +1,89 @@
+/*
+ * "$Id$"
+ *
+ * CGI HTML functions.
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contents:
+ *
+ * cgiStartHTML() - Start an HTML document stream.
+ * cgiEndHTML() - End an HTML document stream.
+ */
+
+#include "cgi.h"
+#include <stdarg.h>
+
+
+/*
+ * 'cgiStartHTML()' - Start an HTML document stream.
+ */
+
+void
+cgiStartHTML(FILE *out, /* I - Output file to use */
+ const char *stylesheet, /* I - Stylesheet to use */
+ const char *author, /* I - Author name */
+ const char *keywords, /* I - Search keywords */
+ const char *description, /* I - Description of document */
+ const char *title, /* I - Title for page */
+ ...) /* I - Any addition args for title */
+{
+ va_list ap; /* Argument pointer */
+
+
+ fputs("Content-type: text/html\n\n", out);
+ fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/loose.dtd\">\n", out);
+ fputs("<HTML>\n", out);
+ fputs("<HEAD>\n", out);
+
+ fputs("\t<TITLE>\n", out);
+ va_start(ap, title);
+ vfprintf(out, title, ap);
+ va_end(ap);
+ fputs("</TITLE>\n", out);
+
+ if (stylesheet)
+ fprintf(out, "\t<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" HREF=\"%s\">\n",
+ stylesheet);
+ if (author)
+ fprintf(out, "\t<META NAME=\"AUTHOR\" CONTENT=\"%s\">\n", author);
+ if (keywords)
+ fprintf(out, "\t<META NAME=\"KEYWORDS\" CONTENT=\"%s\">\n", keywords);
+ if (description)
+ fprintf(out, "\t<META NAME=\"DESCRIPTION\" CONTENT=\"%s\">\n", description);
+
+ fputs("</HEAD>\n", out);
+ fputs("<BODY>\n", out);
+}
+
+
+/*
+ * 'cgiEndHTML()' - End an HTML document stream.
+ */
+
+void
+cgiEndHTML(FILE *out) /* I - Output file to use */
+{
+ fputs("</BODY>\n", out);
+ fputs("</HTML>\n", out);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c
new file mode 100644
index 000000000..4a5eb4eb6
--- /dev/null
+++ b/cgi-bin/ipp-var.c
@@ -0,0 +1,575 @@
+/*
+ * "$Id$"
+ *
+ * IPP variable routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * ippGetAttributes() - Get the list of attributes that are needed
+ * by the template file.
+ * ippGetTemplateDir() - Get the templates directory...
+ * ippRewriteURL() - Rewrite a printer URI into a web browser URL...
+ * ippSetServerVersion() - Set the server name and CUPS version...
+ * ippSetCGIVars() - Set CGI variables from an IPP response.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ipp-var.h"
+
+
+/*
+ * 'ippGetAttributes()' - Get the list of attributes that are needed
+ * by the template file.
+ */
+
+void
+ippGetAttributes(ipp_t *request, /* I - IPP request */
+ const char *directory, /* I - Directory */
+ const char *tmpl, /* I - Base filename */
+ const char *lang) /* I - Language */
+{
+ int num_attrs; /* Number of attributes */
+ char *attrs[1000]; /* Attributes */
+ int i; /* Looping var */
+ char filename[1024], /* Filename */
+ locale[16]; /* Locale name */
+ FILE *in; /* Input file */
+ int ch; /* Character from file */
+ char name[255], /* Name of variable */
+ *nameptr; /* Pointer into name */
+
+
+ /*
+ * Convert the language to a locale name...
+ */
+
+ if (lang != NULL)
+ {
+ for (i = 0; lang[i] && i < 15; i ++)
+ if (isalnum(lang[i] & 255))
+ locale[i] = tolower(lang[i]);
+ else
+ locale[i] = '_';
+
+ locale[i] = '\0';
+ }
+ else
+ locale[0] = '\0';
+
+ /*
+ * See if we have a template file for this language...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
+ if (access(filename, 0))
+ {
+ locale[2] = '\0';
+
+ snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
+ if (access(filename, 0))
+ snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
+ }
+
+ /*
+ * Open the template file...
+ */
+
+ if ((in = fopen(filename, "r")) == NULL)
+ return;
+
+ /*
+ * Loop through the file adding attribute names as needed...
+ */
+
+ num_attrs = 0;
+
+ while ((ch = getc(in)) != EOF)
+ if (ch == '\\')
+ getc(in);
+ else if (ch == '{' && num_attrs < (sizeof(attrs) / sizeof(attrs[0])))
+ {
+ /*
+ * Grab the name...
+ */
+
+ for (nameptr = name; (ch = getc(in)) != EOF;)
+ if (strchr("}]<>=! \t\n", ch))
+ break;
+ else if (nameptr > name && ch == '?')
+ break;
+ else if (nameptr < (name + sizeof(name) - 1))
+ {
+ if (ch == '_')
+ *nameptr++ = '-';
+ else
+ *nameptr++ = ch;
+ }
+
+ *nameptr = '\0';
+
+ if (!strncmp(name, "printer_state_history", 21))
+ strcpy(name, "printer_state_history");
+
+ /*
+ * Possibly add it to the list of attributes...
+ */
+
+ for (i = 0; i < num_attrs; i ++)
+ if (!strcmp(attrs[i], name))
+ break;
+
+ if (i >= num_attrs)
+ {
+ attrs[num_attrs] = strdup(name);
+ num_attrs ++;
+ }
+ }
+
+ /*
+ * If we have attributes, add a requested-attributes attribute to the
+ * request...
+ */
+
+ if (num_attrs > 0)
+ {
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", num_attrs, NULL, (const char **)attrs);
+
+ for (i = 0; i < num_attrs; i ++)
+ free(attrs[i]);
+ }
+}
+
+
+/*
+ * 'ippGetTemplateDir()' - Get the templates directory...
+ */
+
+char * /* O - Template directory */
+ippGetTemplateDir(void)
+{
+ const char *datadir; /* CUPS_DATADIR env var */
+ static char templates[1024] = ""; /* Template directory */
+
+
+ if (!templates[0])
+ {
+ /*
+ * Build the template directory pathname...
+ */
+
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+ datadir = CUPS_DATADIR;
+
+ snprintf(templates, sizeof(templates), "%s/templates", datadir);
+ }
+
+ return (templates);
+}
+
+
+/*
+ * 'ippRewriteURL()' - Rewrite a printer URI into a web browser URL...
+ */
+
+char * /* O - New URL */
+ippRewriteURL(const char *uri, /* I - Current URI */
+ char *url, /* O - New URL */
+ int urlsize, /* I - Size of URL buffer */
+ const char *newresource) /* I - Replacement resource */
+{
+ char method[HTTP_MAX_URI],
+ userpass[HTTP_MAX_URI],
+ hostname[HTTP_MAX_URI],
+ rawresource[HTTP_MAX_URI],
+ resource[HTTP_MAX_URI],
+ /* URI components... */
+ *rawptr, /* Pointer into rawresource */
+ *resptr; /* Pointer into resource */
+ int port; /* Port number */
+ static int ishttps = -1; /* Using encryption? */
+ static const char *server; /* Name of server */
+ static char servername[1024];
+ /* Local server name */
+ static const char hexchars[] = "0123456789ABCDEF";
+ /* Hexadecimal conversion characters */
+
+
+ /*
+ * Check if we have been called before...
+ */
+
+ if (ishttps < 0)
+ {
+ /*
+ * No, initialize static vars for the conversion...
+ *
+ * First get the server name associated with the client interface as
+ * well as the locally configured hostname. We'll check *both* of
+ * these to see if the printer URL is local...
+ */
+
+ server = getenv("SERVER_NAME");
+ gethostname(servername, sizeof(servername));
+
+ /*
+ * Then flag whether we are using SSL on this connection...
+ */
+
+ ishttps = getenv("HTTPS") != NULL;
+ }
+
+ /*
+ * Convert the URI to a URL...
+ */
+
+ httpSeparate(uri, method, userpass, hostname, &port, rawresource);
+
+ if (strcmp(method, "ipp") == 0 ||
+ strcmp(method, "http") == 0)
+ {
+ if (newresource)
+ {
+ /*
+ * Force the specified resource name instead of the one in the URL...
+ */
+
+ strlcpy(resource, newresource, sizeof(resource));
+ }
+ else
+ {
+ /*
+ * Rewrite the resource string so it doesn't contain any
+ * illegal chars...
+ */
+
+ for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++)
+ if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' ||
+ *rawptr == '#' || *rawptr == '?' ||
+ *rawptr == '.') /* For MSIE */
+ {
+ if (resptr < (resource + sizeof(resource) - 3))
+ {
+ *resptr++ = '%';
+ *resptr++ = hexchars[(*rawptr >> 4) & 15];
+ *resptr++ = hexchars[*rawptr & 15];
+ }
+ }
+ else if (resptr < (resource + sizeof(resource) - 1))
+ *resptr++ = *rawptr;
+
+ *resptr = '\0';
+ }
+
+ /*
+ * Map local access to a local URI...
+ */
+
+ if (strcasecmp(hostname, server) == 0 ||
+ strcasecmp(hostname, servername) == 0)
+ {
+ /*
+ * Make URI relative to the current server...
+ */
+
+ strlcpy(url, resource, urlsize);
+ }
+ else
+ {
+ /*
+ * Rewrite URI with HTTP/HTTPS scheme...
+ */
+
+ if (userpass[0])
+ snprintf(url, urlsize, "%s://%s@%s:%d%s",
+ ishttps ? "https" : "http",
+ userpass, hostname, port, resource);
+ else
+ snprintf(url, urlsize, "%s://%s:%d%s",
+ ishttps ? "https" : "http",
+ hostname, port, resource);
+ }
+ }
+ else
+ strlcpy(url, uri, urlsize);
+
+ return (url);
+}
+
+
+/*
+ * 'ippSetServerVersion()' - Set the server name and CUPS version...
+ */
+
+void
+ippSetServerVersion(void)
+{
+ cgiSetVariable("SERVER_NAME", getenv("SERVER_NAME"));
+ cgiSetVariable("REMOTE_USER", getenv("REMOTE_USER"));
+ cgiSetVariable("CUPS_VERSION", CUPS_SVERSION);
+
+#ifdef LC_TIME
+ setlocale(LC_TIME, "");
+#endif /* LC_TIME */
+}
+
+
+/*
+ * 'ippSetCGIVars()' - Set CGI variables from an IPP response.
+ */
+
+void
+ippSetCGIVars(ipp_t *response, /* I - Response data to be copied... */
+ const char *filter_name, /* I - Filter name */
+ const char *filter_value, /* I - Filter value */
+ const char *prefix, /* I - Prefix for name or NULL */
+ int parent_el) /* I - Parent element number */
+{
+ int element; /* Element in CGI array */
+ ipp_attribute_t *attr, /* Attribute in response... */
+ *filter; /* Filtering attribute */
+ int i; /* Looping var */
+ char name[1024], /* Name of attribute */
+ *nameptr, /* Pointer into name */
+ value[16384], /* Value(s) */
+ *valptr; /* Pointer into value */
+ struct tm *date; /* Date information */
+
+
+ DEBUG_printf(("<P>ippSetCGIVars(response=%p, filter_name=\"%s\", filter_value=\"%s\", prefix=\"%s\")\n",
+ response, filter_name, filter_value, prefix));
+
+ /*
+ * Set common CGI template variables...
+ */
+
+ if (!prefix)
+ ippSetServerVersion();
+
+ /*
+ * Loop through the attributes and set them for the template...
+ */
+
+ attr = response->attrs;
+
+ if (!prefix)
+ while (attr && attr->group_tag == IPP_TAG_OPERATION)
+ attr = attr->next;
+
+ for (element = parent_el; attr != NULL; attr = attr->next, element ++)
+ {
+ /*
+ * Copy attributes to a separator...
+ */
+
+ if (filter_name)
+ {
+ for (filter = attr;
+ filter != NULL && filter->group_tag != IPP_TAG_ZERO;
+ filter = filter->next)
+ if (filter->name && strcmp(filter->name, filter_name) == 0 &&
+ (filter->value_tag == IPP_TAG_STRING ||
+ (filter->value_tag >= IPP_TAG_TEXTLANG &&
+ filter->value_tag <= IPP_TAG_MIMETYPE)) &&
+ filter->values[0].string.text != NULL &&
+ strcasecmp(filter->values[0].string.text, filter_value) == 0)
+ break;
+
+ if (!filter)
+ return;
+
+ if (filter->group_tag == IPP_TAG_ZERO)
+ {
+ attr = filter;
+ element --;
+ continue;
+ }
+ }
+
+ for (; attr != NULL && attr->group_tag != IPP_TAG_ZERO; attr = attr->next)
+ {
+ /*
+ * Copy the attribute name, substituting "_" for "-"...
+ */
+
+ if (attr->name == NULL)
+ continue;
+
+ if (prefix)
+ {
+ snprintf(name, sizeof(name), "%s.", prefix);
+ nameptr = name + strlen(name);
+ }
+ else
+ nameptr = name;
+
+ for (i = 0; attr->name[i] && nameptr < (name + sizeof(name) - 1); i ++)
+ if (attr->name[i] == '-')
+ *nameptr++ = '_';
+ else
+ *nameptr++ = attr->name[i];
+
+ *nameptr = '\0';
+
+ /*
+ * Add "job_printer_name" variable if we have a "job_printer_uri"
+ * attribute...
+ */
+
+ if (!strcmp(name, "job_printer_uri"))
+ {
+ if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL)
+ valptr = "unknown";
+ else
+ valptr ++;
+
+ cgiSetArray("job_printer_name", element, valptr);
+ }
+
+ /*
+ * Add "admin_uri" variable if we have a "printer_uri_supported"
+ * attribute...
+ */
+
+ if (!strcmp(name, "printer_uri_supported"))
+ {
+ ippRewriteURL(attr->values[0].string.text, value, sizeof(value),
+ "/admin/");
+
+ cgiSetArray("admin_uri", element, value);
+ }
+
+ /*
+ * Copy values...
+ */
+
+ value[0] = '\0'; /* Initially an empty string */
+ valptr = value; /* Start at the beginning */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (i)
+ strlcat(valptr, ",", sizeof(value) - (valptr - value));
+
+ valptr += strlen(valptr);
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ if (strncmp(name, "time_at_", 8) == 0)
+ {
+ time_t t; /* Temporary time value */
+
+ t = (time_t)attr->values[i].integer;
+ date = localtime(&t);
+
+ strftime(valptr, sizeof(value) - (valptr - value),
+ CUPS_STRFTIME_FORMAT, date);
+ }
+ else
+ snprintf(valptr, sizeof(value) - (valptr - value),
+ "%d", attr->values[i].integer);
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ snprintf(valptr, sizeof(value) - (valptr - value),
+ "%d", attr->values[i].boolean);
+ break;
+
+ case IPP_TAG_NOVALUE :
+ strlcat(valptr, "novalue", sizeof(value) - (valptr - value));
+ break;
+
+ case IPP_TAG_RANGE :
+ snprintf(valptr, sizeof(value) - (valptr - value),
+ "%d-%d", attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ snprintf(valptr, sizeof(value) - (valptr - value),
+ "%dx%d%s", attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ break;
+
+ case IPP_TAG_URI :
+ if (strchr(attr->values[i].string.text, ':') != NULL)
+ {
+ /*
+ * Rewrite URIs...
+ */
+
+ ippRewriteURL(attr->values[i].string.text, valptr,
+ sizeof(value) - (valptr - value), NULL);
+ break;
+ }
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ strlcat(valptr, attr->values[i].string.text,
+ sizeof(value) - (valptr - value));
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ snprintf(value, sizeof(value), "%s%d", name, i + 1);
+ ippSetCGIVars(attr->values[i].collection, filter_name,
+ filter_value, value, element);
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+ }
+
+ /*
+ * Add the element...
+ */
+
+ if (attr->value_tag != IPP_TAG_BEGIN_COLLECTION)
+ {
+ cgiSetArray(name, element, value);
+
+ DEBUG_printf(("<P>%s[%d]=\"%s\"\n", name, element, value));
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ DEBUG_puts("<P>Leaving ippSetCGIVars()...");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/ipp-var.h b/cgi-bin/ipp-var.h
new file mode 100644
index 000000000..144d3bfd1
--- /dev/null
+++ b/cgi-bin/ipp-var.h
@@ -0,0 +1,58 @@
+/*
+ * "$Id$"
+ *
+ * IPP variable definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/debug.h>
+#include <cups/language.h>
+#include <cups/string.h>
+#include "cgi.h"
+
+
+/*
+ * Definitions...
+ */
+
+#define TEMPLATES ippGetTemplateDir()
+
+
+/*
+ * Prototype...
+ */
+
+extern void ippGetAttributes(ipp_t *request, const char *directory,
+ const char *tmpl, const char *lang);
+extern char *ippGetTemplateDir(void);
+extern char *ippRewriteURL(const char *, char *, int, const char *);
+extern void ippSetServerVersion(void);
+extern void ippSetCGIVars(ipp_t *, const char *, const char *,
+ const char *, int);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/jobs.c b/cgi-bin/jobs.c
new file mode 100644
index 000000000..8127a920c
--- /dev/null
+++ b/cgi-bin/jobs.c
@@ -0,0 +1,261 @@
+/*
+ * "$Id$"
+ *
+ * Job status CGI for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for CGI.
+ * do_job_op() - Do a job operation.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ipp-var.h"
+
+
+/*
+ * Local functions...
+ */
+
+static void do_job_op(http_t *http, cups_lang_t *language, ipp_op_t op);
+
+
+/*
+ * 'main()' - Main entry for CGI.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ cups_lang_t *language; /* Language information */
+ http_t *http; /* Connection to the server */
+ const char *which_jobs; /* Which jobs to show */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ const char *op; /* Operation name */
+
+
+ /*
+ * Get any form variables...
+ */
+
+ cgiInitialize();
+
+ /*
+ * Get the request language...
+ */
+
+ language = cupsLangDefault();
+
+ /*
+ * Connect to the HTTP server...
+ */
+
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
+
+ /*
+ * Tell the client to expect HTML...
+ */
+
+ printf("Content-Type: text/html;charset=%s\n\n", cupsLangEncoding(language));
+
+ cgiSetVariable("TITLE", "Jobs");
+
+ ippSetServerVersion();
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG"));
+
+ if ((op = cgiGetVariable("OP")) != NULL)
+ {
+ /*
+ * Do the operation...
+ */
+
+ if (strcmp(op, "cancel-job") == 0)
+ do_job_op(http, language, IPP_CANCEL_JOB);
+ else if (strcmp(op, "hold-job") == 0)
+ do_job_op(http, language, IPP_HOLD_JOB);
+ else if (strcmp(op, "release-job") == 0)
+ do_job_op(http, language, IPP_RELEASE_JOB);
+ else if (strcmp(op, "restart-job") == 0)
+ do_job_op(http, language, IPP_RESTART_JOB);
+ else
+ {
+ /*
+ * Bad operation code... Display an error...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "job-op.tmpl", getenv("LANG"));
+ }
+ }
+ else
+ {
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
+ "ipp://localhost/jobs");
+
+ if ((which_jobs = cgiGetVariable("which_jobs")) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
+ NULL, which_jobs);
+
+ ippGetAttributes(request, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+ }
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG"));
+
+ /*
+ * Close the HTTP server connection...
+ */
+
+ httpClose(http);
+ cupsLangFree(language);
+
+ /*
+ * Return with no errors...
+ */
+
+ return (0);
+}
+
+
+/*
+ * 'do_job_op()' - Do a job operation.
+ */
+
+static void
+do_job_op(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language, /* I - Client's language */
+ ipp_op_t op) /* I - Operation to perform */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *job; /* Job ID */
+ ipp_status_t status; /* Operation status... */
+
+
+ if ((job = cgiGetVariable("JOB_ID")) != NULL)
+ snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%s", job);
+ else
+ {
+ cgiSetVariable("ERROR", ippErrorString(IPP_NOT_FOUND));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ return;
+ }
+
+ /*
+ * Build a job request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri or printer-uri (purge-jobs)
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+ NULL, uri);
+
+ if (getenv("REMOTE_USER") != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, getenv("REMOTE_USER"));
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, "unknown");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ status = response->request.status.status_code;
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else if (op == IPP_CANCEL_JOB)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "job-cancel.tmpl", getenv("LANG"));
+ else if (op == IPP_HOLD_JOB)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "job-hold.tmpl", getenv("LANG"));
+ else if (op == IPP_RELEASE_JOB)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "job-release.tmpl", getenv("LANG"));
+ else if (op == IPP_RESTART_JOB)
+ cgiCopyTemplateLang(stdout, TEMPLATES, "job-restart.tmpl", getenv("LANG"));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c
new file mode 100644
index 000000000..f7dac2f48
--- /dev/null
+++ b/cgi-bin/printers.c
@@ -0,0 +1,356 @@
+/*
+ * "$Id$"
+ *
+ * Printer status CGI for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for CGI.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ipp-var.h"
+
+
+/*
+ * 'main()' - Main entry for CGI.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ cups_lang_t *language; /* Language information */
+ char *printer; /* Printer name */
+ http_t *http; /* Connection to the server */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ ipp_status_t status; /* Operation status... */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ const char *which_jobs; /* Which jobs to show */
+ const char *op; /* Operation to perform, if any */
+ static const char *def_attrs[] = /* Attributes for default printer */
+ {
+ "printer-name",
+ "printer-uri-supported"
+ };
+
+
+ /*
+ * Get any form variables...
+ */
+
+ cgiInitialize();
+ op = cgiGetVariable("OP");
+
+ /*
+ * Get the request language...
+ */
+
+ language = cupsLangDefault();
+
+ /*
+ * Connect to the HTTP server...
+ */
+
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
+
+ /*
+ * Tell the client to expect HTML...
+ */
+
+ printf("Content-Type: text/html;charset=%s\r\n\r\n",
+ cupsLangEncoding(language));
+
+ /*
+ * See if we need to show a list of printers or the status of a
+ * single printer...
+ */
+
+ ippSetServerVersion();
+
+ printer = argv[0];
+ if (strcmp(printer, "/") == 0 || strstr(printer, "printers.cgi") != NULL)
+ {
+ printer = NULL;
+ cgiSetVariable("TITLE", cupsLangString(language, CUPS_MSG_PRINTER));
+ }
+ else
+ cgiSetVariable("TITLE", printer);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "header.tmpl", getenv("LANG"));
+
+ if (op == NULL || strcasecmp(op, "print-test-page") != 0)
+ {
+ /*
+ * Get the default destination...
+ */
+
+ request = ippNew();
+ request->request.op.operation_id = CUPS_GET_DEFAULT;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ sizeof(def_attrs) / sizeof(def_attrs[0]), NULL, def_attrs);
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
+ cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL)
+ {
+ char url[HTTP_MAX_URI]; /* New URL */
+
+
+ cgiSetVariable("DEFAULT_URI",
+ ippRewriteURL(attr->values[0].string.text,
+ url, sizeof(url), NULL));
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Get the printer info...
+ */
+
+ request = ippNew();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (printer == NULL)
+ {
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ */
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+ }
+ else
+ {
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"),
+ printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ uri);
+ }
+
+ ippGetAttributes(request, TEMPLATES, "printers.tmpl", getenv("LANG"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+ }
+ else if (printer)
+ fprintf(stderr, "ERROR: Get-Printer-Attributes request failed - %s (%x)\n",
+ ippErrorString(cupsLastError()), cupsLastError());
+ else
+ fprintf(stderr, "ERROR: CUPS-Get-Printers request failed - %s (%x)\n",
+ ippErrorString(cupsLastError()), cupsLastError());
+
+ /*
+ * Write the report...
+ */
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "printers.tmpl", getenv("LANG"));
+
+ /*
+ * Get jobs for the specified printer if a printer has been chosen...
+ */
+
+ if (printer != NULL)
+ {
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s/printers/%s", getenv("SERVER_NAME"),
+ printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ uri);
+
+ if ((which_jobs = cgiGetVariable("which_jobs")) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
+ NULL, which_jobs);
+
+ ippGetAttributes(request, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+ ippDelete(response);
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "jobs.tmpl", getenv("LANG"));
+ }
+ else
+ fprintf(stderr, "ERROR: Get-Jobs request failed - %s (%x)\n",
+ ippErrorString(cupsLastError()), cupsLastError());
+ }
+ }
+ else
+ {
+ /*
+ * Print a test page...
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ /*
+ * Build an IPP_PRINT_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ * document-format
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ if (getenv("REMOTE_USER") != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, getenv("REMOTE_USER"));
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, "root");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+ NULL, "Test Page");
+
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/postscript");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoFileRequest(http, request, uri + 15,
+ CUPS_DATADIR "/data/testprint.ps")) != NULL)
+ {
+ status = response->request.status.status_code;
+ ippSetCGIVars(response, NULL, NULL, NULL, 0);
+
+ ippDelete(response);
+ }
+ else
+ status = cupsLastError();
+
+ cgiSetVariable("PRINTER_NAME", printer);
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ cgiSetVariable("ERROR", ippErrorString(status));
+ cgiCopyTemplateLang(stdout, TEMPLATES, "error.tmpl", getenv("LANG"));
+ }
+ else
+ cgiCopyTemplateLang(stdout, TEMPLATES, "test-page.tmpl", getenv("LANG"));
+ }
+
+ cgiCopyTemplateLang(stdout, TEMPLATES, "trailer.tmpl", getenv("LANG"));
+
+ /*
+ * Close the HTTP server connection...
+ */
+
+ httpClose(http);
+ cupsLangFree(language);
+
+ /*
+ * Return with no errors...
+ */
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/template.c b/cgi-bin/template.c
new file mode 100644
index 000000000..54f8845bf
--- /dev/null
+++ b/cgi-bin/template.c
@@ -0,0 +1,492 @@
+/*
+ * "$Id$"
+ *
+ * CGI template function.
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contents:
+ *
+ * cgiCopyTemplateFile() - Copy a template file and replace all the
+ * '{variable}' strings with the variable value.
+ * cgiCopyTemplateLang() - Copy a template file using a language...
+ * cgi_copy() - Copy the template file, substituting as needed...
+ * cgi_puts() - Put a string to the output file, quoting as
+ * needed...
+ */
+
+#include "cgi.h"
+
+
+/*
+ * Local functions...
+ */
+
+static void cgi_copy(FILE *out, FILE *in, int element, char term);
+static void cgi_puts(const char *s, FILE *out);
+
+
+/*
+ * 'cgiCopyTemplateFile()' - Copy a template file and replace all the
+ * '{variable}' strings with the variable value.
+ */
+
+void
+cgiCopyTemplateFile(FILE *out, /* I - Output file */
+ const char *tmpl) /* I - Template file to read */
+{
+ FILE *in; /* Input file */
+
+
+ /*
+ * Open the template file...
+ */
+
+ if ((in = fopen(tmpl, "r")) == NULL)
+ return;
+
+ /*
+ * Parse the file to the end...
+ */
+
+ cgi_copy(out, in, 0, 0);
+
+ /*
+ * Close the template file and return...
+ */
+
+ fclose(in);
+}
+
+
+/*
+ * 'cgiCopyTemplateLang()' - Copy a template file using a language...
+ */
+
+void
+cgiCopyTemplateLang(FILE *out, /* I - Output file */
+ const char *directory, /* I - Directory */
+ const char *tmpl, /* I - Base filename */
+ const char *lang) /* I - Language */
+{
+ int i; /* Looping var */
+ char filename[1024], /* Filename */
+ locale[16]; /* Locale name */
+ FILE *in; /* Input file */
+
+
+ /*
+ * Convert the language to a locale name...
+ */
+
+ if (lang != NULL)
+ {
+ for (i = 0; lang[i] && i < 15; i ++)
+ if (isalnum(lang[i] & 255))
+ locale[i] = tolower(lang[i]);
+ else
+ locale[i] = '_';
+
+ locale[i] = '\0';
+ }
+ else
+ locale[0] = '\0';
+
+ /*
+ * See if we have a template file for this language...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
+ if (access(filename, 0))
+ {
+ locale[2] = '\0';
+
+ snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
+ if (access(filename, 0))
+ snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
+ }
+
+ /*
+ * Open the template file...
+ */
+
+ if ((in = fopen(filename, "r")) == NULL)
+ return;
+
+ /*
+ * Parse the file to the end...
+ */
+
+ cgi_copy(out, in, 0, 0);
+
+ /*
+ * Close the template file and return...
+ */
+
+ fclose(in);
+}
+
+
+/*
+ * 'cgi_copy()' - Copy the template file, substituting as needed...
+ */
+
+static void
+cgi_copy(FILE *out, /* I - Output file */
+ FILE *in, /* I - Input file */
+ int element, /* I - Element number (0 to N) */
+ char term) /* I - Terminating character */
+{
+ int ch; /* Character from file */
+ char op; /* Operation */
+ char name[255], /* Name of variable */
+ *nameptr, /* Pointer into name */
+ innername[255], /* Inner comparison name */
+ *innerptr, /* Pointer into inner name */
+ *s; /* String pointer */
+ const char *value; /* Value of variable */
+ const char *innerval; /* Inner value */
+ const char *outptr; /* Output string pointer */
+ char outval[1024], /* Formatted output string */
+ compare[1024]; /* Comparison string */
+ int result; /* Result of comparison */
+
+
+ /*
+ * Parse the file to the end...
+ */
+
+ while ((ch = getc(in)) != EOF)
+ if (ch == term)
+ break;
+ else if (ch == '{')
+ {
+ /*
+ * Get a variable name...
+ */
+
+ for (s = name; (ch = getc(in)) != EOF;)
+ if (strchr("}]<>=! \t\n", ch))
+ break;
+ else if (s > name && ch == '?')
+ break;
+ else if (s < (name + sizeof(name) - 1))
+ *s++ = ch;
+
+ *s = '\0';
+
+ if (s == name && isspace(ch & 255))
+ {
+ if (out)
+ {
+ putc('{', out);
+ putc(ch, out);
+ }
+
+ continue;
+ }
+
+ /*
+ * See if it has a value...
+ */
+
+ if (name[0] == '?')
+ {
+ /*
+ * Insert value only if it exists...
+ */
+
+ if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
+ {
+ *nameptr++ = '\0';
+
+ if ((value = cgiGetArray(name + 1, atoi(nameptr) - 1)) != NULL)
+ outptr = value;
+ else
+ {
+ outval[0] = '\0';
+ outptr = outval;
+ }
+ }
+ else if ((value = cgiGetArray(name + 1, element)) != NULL)
+ outptr = value;
+ else
+ {
+ outval[0] = '\0';
+ outptr = outval;
+ }
+ }
+ else if (name[0] == '#')
+ {
+ /*
+ * Insert count...
+ */
+
+ if (name[1])
+ sprintf(outval, "%d", cgiGetSize(name + 1));
+ else
+ sprintf(outval, "%d", element + 1);
+
+ outptr = outval;
+ }
+ else if (name[0] == '[')
+ {
+ /*
+ * Loop for # of elements...
+ */
+
+ int i; /* Looping var */
+ long pos; /* File position */
+ int count; /* Number of elements */
+
+
+ if (isdigit(name[1] & 255))
+ count = atoi(name + 1);
+ else
+ count = cgiGetSize(name + 1);
+
+ pos = ftell(in);
+
+ if (count > 0)
+ {
+ for (i = 0; i < count; i ++)
+ {
+ fseek(in, pos, SEEK_SET);
+ cgi_copy(out, in, i, '}');
+ }
+ }
+ else
+ cgi_copy(NULL, in, 0, '}');
+
+ continue;
+ }
+ else
+ {
+ /*
+ * Insert variable or variable name (if element is NULL)...
+ */
+
+ if ((nameptr = strrchr(name, '-')) != NULL && isdigit(nameptr[1] & 255))
+ {
+ *nameptr++ = '\0';
+ if ((value = cgiGetArray(name, atoi(nameptr) - 1)) == NULL)
+ {
+ snprintf(outval, sizeof(outval), "{%s}", name);
+ outptr = outval;
+ }
+ else
+ outptr = value;
+ }
+ else if ((value = cgiGetArray(name, element)) == NULL)
+ {
+ snprintf(outval, sizeof(outval), "{%s}", name);
+ outptr = outval;
+ }
+ else
+ outptr = value;
+ }
+
+ /*
+ * See if the terminating character requires another test...
+ */
+
+ if (ch == '}')
+ {
+ /*
+ * End of substitution...
+ */
+
+ if (out)
+ cgi_puts(outptr, out);
+
+ continue;
+ }
+
+ /*
+ * OK, process one of the following checks:
+ *
+ * {name?exist:not-exist} Exists?
+ * {name=value?true:false} Equal
+ * {name<value?true:false} Less than
+ * {name>value?true:false} Greater than
+ * {name!value?true:false} Not equal
+ */
+
+ if (ch == '?')
+ {
+ /*
+ * Test for existance...
+ */
+
+ result = cgiGetArray(name, element) != NULL && outptr[0];
+ }
+ else
+ {
+ /*
+ * Compare to a string...
+ */
+
+ op = ch;
+
+ for (s = compare; (ch = getc(in)) != EOF;)
+ if (ch == '?')
+ break;
+ else if (s >= (compare + sizeof(compare) - 1))
+ continue;
+ else if (ch == '#')
+ {
+ sprintf(s, "%d", element + 1);
+ s += strlen(s);
+ }
+ else if (ch == '{')
+ {
+ /*
+ * Grab the value of a variable...
+ */
+
+ innerptr = innername;
+ while ((ch = getc(in)) != EOF && ch != '}')
+ if (innerptr < (innername + sizeof(innername) - 1))
+ *innerptr++ = ch;
+ *innerptr = '\0';
+
+ if (innername[0] == '#')
+ sprintf(s, "%d", cgiGetSize(innername + 1));
+ else if ((innerptr = strrchr(innername, '-')) != NULL &&
+ isdigit(innerptr[1] & 255))
+ {
+ *innerptr++ = '\0';
+ if ((innerval = cgiGetArray(innername, atoi(innerptr) - 1)) == NULL)
+ *s = '\0';
+ else
+ strlcpy(s, innerval, sizeof(compare) - (s - compare));
+ }
+ else if (innername[0] == '?')
+ {
+ if ((innerval = cgiGetArray(innername + 1, element)) == NULL)
+ *s = '\0';
+ else
+ strlcpy(s, innerval, sizeof(compare) - (s - compare));
+ }
+ else if ((innerval = cgiGetArray(innername, element)) == NULL)
+ snprintf(s, sizeof(s), "{%s}", innername);
+ else
+ strlcpy(s, innerval, sizeof(compare) - (s - compare));
+
+ s += strlen(s);
+ }
+ else if (ch == '\\')
+ *s++ = getc(in);
+ else
+ *s++ = ch;
+
+ *s = '\0';
+
+ if (ch != '?')
+ return;
+
+ /*
+ * Do the comparison...
+ */
+
+ switch (op)
+ {
+ case '<' :
+ result = strcasecmp(outptr, compare) < 0;
+ break;
+ case '>' :
+ result = strcasecmp(outptr, compare) > 0;
+ break;
+ case '=' :
+ result = strcasecmp(outptr, compare) == 0;
+ break;
+ case '!' :
+ result = strcasecmp(outptr, compare) != 0;
+ break;
+ default :
+ result = 1;
+ break;
+ }
+ }
+
+ if (result)
+ {
+ /*
+ * Comparison true; output first part and ignore second...
+ */
+
+ cgi_copy(out, in, element, ':');
+ cgi_copy(NULL, in, element, '}');
+ }
+ else
+ {
+ /*
+ * Comparison false; ignore first part and output second...
+ */
+
+ cgi_copy(NULL, in, element, ':');
+ cgi_copy(out, in, element, '}');
+ }
+ }
+ else if (ch == '\\') /* Quoted char */
+ {
+ if (out)
+ putc(getc(in), out);
+ else
+ getc(in);
+ }
+ else if (out)
+ putc(ch, out);
+
+ /*
+ * Flush any pending output...
+ */
+
+ if (out)
+ fflush(out);
+}
+
+
+/*
+ * 'cgi_puts()' - Put a string to the output file, quoting as needed...
+ */
+
+static void
+cgi_puts(const char *s,
+ FILE *out)
+{
+ while (*s)
+ {
+ if (s[0] == '<')
+ fputs("&lt;", out);
+ else if (s[0] == '>')
+ fputs("&gt;", out);
+ else if (*s == '\"')
+ fputs("&quot;", out);
+ else if (s[0] == '&')
+ fputs("&amp;", out);
+ else
+ putc(*s, out);
+
+ s ++;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cgi-bin/var.c b/cgi-bin/var.c
new file mode 100644
index 000000000..6a7052706
--- /dev/null
+++ b/cgi-bin/var.c
@@ -0,0 +1,672 @@
+/*
+ * "$Id$"
+ *
+ * CGI form variable and array functions.
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Contents:
+ *
+ * cgiInitialize() - Initialize the CGI variable "database"...
+ * cgiCheckVariables() - Check for the presence of "required" variables.
+ * cgiGetArray() - Get an element from a form array...
+ * cgiGetSize() - Get the size of a form array value.
+ * cgiGetVariable() - Get a CGI variable from the database...
+ * cgiSetArray() - Set array element N to the specified string.
+ * cgiSetVariable() - Set a CGI variable in the database...
+ * cgi_add_variable() - Add a form variable.
+ * cgi_compare_variables() - Compare two variables.
+ * cgi_find_variable() - Find a variable...
+ * cgi_initialize_get() - Initialize form variables using the GET method.
+ * cgi_initialize_post() - Initialize variables using the POST method.
+ * cgi_initialize_string() - Initialize form variables from a string.
+ * cgi_sort_variables() - Sort all form variables for faster lookup.
+ */
+
+/*#define DEBUG*/
+#include "cgi.h"
+#include <errno.h>
+#include <syslog.h>
+
+
+/*
+ * Data structure to hold all the CGI form variables and arrays...
+ */
+
+typedef struct
+{
+ const char *name; /* Name of variable */
+ int nvalues, /* Number of values */
+ avalues; /* Number of values allocated */
+ const char **values; /* Value(s) of variable */
+} var_t;
+
+
+/*
+ * Local globals...
+ */
+
+static int form_count = 0, /* Form variable count */
+ form_alloc = 0; /* Number of variables allocated */
+static var_t *form_vars = NULL; /* Form variables */
+
+
+/*
+ * Local functions...
+ */
+
+static void cgi_add_variable(const char *name, int element,
+ const char *value);
+static int cgi_compare_variables(const var_t *v1, const var_t *v2);
+static var_t *cgi_find_variable(const char *name);
+static int cgi_initialize_get(void);
+static int cgi_initialize_post(void);
+static int cgi_initialize_string(const char *data);
+static void cgi_sort_variables(void);
+
+
+/*
+ * 'cgiInitialize()' - Initialize the CGI variable "database"...
+ */
+
+int /* O - Non-zero if there was form data */
+cgiInitialize(void)
+{
+ char *method; /* Form posting method */
+
+
+#ifdef DEBUG
+ setbuf(stdout, NULL);
+ puts("Content-type: text/plain\n");
+#endif /* DEBUG */
+
+ method = getenv("REQUEST_METHOD");
+
+ if (method == NULL)
+ return (0);
+
+ if (strcasecmp(method, "GET") == 0)
+ return (cgi_initialize_get());
+ else if (strcasecmp(method, "POST") == 0)
+ return (cgi_initialize_post());
+ else
+ return (0);
+}
+
+
+/*
+ * 'cgiCheckVariables()' - Check for the presence of "required" variables.
+ *
+ * Names may be separated by spaces and/or commas.
+ */
+
+int /* O - 1 if all variables present, 0 otherwise */
+cgiCheckVariables(const char *names) /* I - Variables to look for */
+{
+ char name[255], /* Current variable name */
+ *s; /* Pointer in string */
+ const char *val; /* Value of variable */
+ int element; /* Array element number */
+
+
+ if (names == NULL)
+ return (1);
+
+ while (*names != '\0')
+ {
+ while (*names == ' ' || *names == ',')
+ names ++;
+
+ for (s = name; *names != '\0' && *names != ' ' && *names != ','; s ++, names ++)
+ *s = *names;
+
+ *s = 0;
+ if (name[0] == '\0')
+ break;
+
+ if ((s = strrchr(name, '-')) != NULL)
+ {
+ *s = '\0';
+ element = atoi(s + 1) - 1;
+ val = cgiGetArray(name, element);
+ }
+ else
+ val = cgiGetVariable(name);
+
+ if (val == NULL)
+ return (0);
+
+ if (*val == '\0')
+ return (0); /* Can't be blank, either! */
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'cgiGetArray()' - Get an element from a form array...
+ */
+
+const char * /* O - Element value or NULL */
+cgiGetArray(const char *name, /* I - Name of array variable */
+ int element) /* I - Element number (0 to N) */
+{
+ var_t *var; /* Pointer to variable */
+
+
+ if ((var = cgi_find_variable(name)) == NULL)
+ return (NULL);
+
+ if (var->nvalues == 1)
+ return (var->values[0]);
+
+ if (element < 0 || element >= var->nvalues)
+ return (NULL);
+
+ return (var->values[element]);
+}
+
+
+/*
+ * 'cgiGetSize()' - Get the size of a form array value.
+ */
+
+int /* O - Number of elements */
+cgiGetSize(const char *name) /* I - Name of variable */
+{
+ var_t *var; /* Pointer to variable */
+
+
+ if ((var = cgi_find_variable(name)) == NULL)
+ return (0);
+
+ return (var->nvalues);
+}
+
+
+/*
+ * 'cgiGetVariable()' - Get a CGI variable from the database...
+ *
+ * Returns NULL if the variable doesn't exist... If the variable is an
+ * array of values, returns the last element...
+ */
+
+const char * /* O - Value of variable */
+cgiGetVariable(const char *name)/* I - Name of variable */
+{
+ const var_t *var; /* Returned variable */
+
+
+ var = cgi_find_variable(name);
+
+#ifdef DEBUG
+ if (var == NULL)
+ printf("cgiGetVariable(\"%s\") is returning NULL...\n", name);
+ else
+ printf("cgiGetVariable(\"%s\") is returning \"%s\"...\n", name,
+ var->values[var->nvalues - 1]);
+#endif /* DEBUG */
+
+ return ((var == NULL) ? NULL : var->values[var->nvalues - 1]);
+}
+
+
+/*
+ * 'cgiSetArray()' - Set array element N to the specified string.
+ *
+ * If the variable array is smaller than (element + 1), the intervening
+ * elements are set to NULL.
+ */
+
+void
+cgiSetArray(const char *name, /* I - Name of variable */
+ int element, /* I - Element number (0 to N) */
+ const char *value) /* I - Value of variable */
+{
+ int i; /* Looping var */
+ var_t *var; /* Returned variable */
+
+
+ if (name == NULL || value == NULL || element < 0 || element > 100000)
+ return;
+
+ if ((var = cgi_find_variable(name)) == NULL)
+ {
+ cgi_add_variable(name, element, value);
+ cgi_sort_variables();
+ }
+ else
+ {
+ if (element >= var->avalues)
+ {
+ var->avalues = element + 16;
+ var->values = (const char **)realloc((void *)(var->values),
+ sizeof(char *) * var->avalues);
+ }
+
+ if (element >= var->nvalues)
+ {
+ for (i = var->nvalues; i < element; i ++)
+ var->values[i] = NULL;
+
+ var->nvalues = element + 1;
+ }
+ else if (var->values[element])
+ free((char *)var->values[element]);
+
+ var->values[element] = strdup(value);
+ }
+}
+
+
+/*
+ * 'cgiSetSize()' - Set the array size.
+ */
+
+void
+cgiSetSize(const char *name, /* I - Name of variable */
+ int size) /* I - Number of elements (0 to N) */
+{
+ int i; /* Looping var */
+ var_t *var; /* Returned variable */
+
+
+ if (name == NULL || size < 0 || size > 100000)
+ return;
+
+ if ((var = cgi_find_variable(name)) == NULL)
+ return;
+
+ if (size >= var->avalues)
+ {
+ var->avalues = size + 16;
+ var->values = (const char **)realloc((void *)(var->values),
+ sizeof(char *) * var->avalues);
+ }
+
+ if (size > var->nvalues)
+ {
+ for (i = var->nvalues; i < size; i ++)
+ var->values[i] = NULL;
+ }
+ else if (size < var->nvalues)
+ {
+ for (i = size; i < var->nvalues; i ++)
+ if (var->values[i])
+ free((void *)(var->values[i]));
+ }
+
+ var->nvalues = size;
+}
+
+
+/*
+ * 'cgiSetVariable()' - Set a CGI variable in the database...
+ *
+ * If the variable is an array, this truncates the array to a single element.
+ */
+
+void
+cgiSetVariable(const char *name, /* I - Name of variable */
+ const char *value) /* I - Value of variable */
+{
+ int i; /* Looping var */
+ var_t *var; /* Returned variable */
+
+
+ if (name == NULL || value == NULL)
+ return;
+
+ if ((var = cgi_find_variable(name)) == NULL)
+ {
+ cgi_add_variable(name, 0, value);
+ cgi_sort_variables();
+ }
+ else
+ {
+ for (i = 0; i < var->nvalues; i ++)
+ if (var->values[i])
+ free((char *)var->values[i]);
+
+ var->values[0] = strdup(value);
+ var->nvalues = 1;
+ }
+}
+
+
+/*
+ * 'cgi_add_variable()' - Add a form variable.
+ */
+
+static void
+cgi_add_variable(const char *name, /* I - Variable name */
+ int element, /* I - Array element number */
+ const char *value) /* I - Variable value */
+{
+ var_t *var; /* New variable */
+
+
+ if (name == NULL || value == NULL || element < 0 || element > 100000)
+ return;
+
+#ifdef DEBUG
+ printf("Adding variable \'%s\' with value \'%s\'...\n", name, value);
+#endif /* DEBUG */
+
+ if (form_count >= form_alloc)
+ {
+ if (form_alloc == 0)
+ form_vars = malloc(sizeof(var_t) * 16);
+ else
+ form_vars = realloc(form_vars, (form_alloc + 16) * sizeof(var_t));
+
+ form_alloc += 16;
+ }
+
+ var = form_vars + form_count;
+ var->name = strdup(name);
+ var->nvalues = element + 1;
+ var->avalues = element + 1;
+ var->values = calloc(element + 1, sizeof(char *));
+ var->values[element] = strdup(value);
+
+ form_count ++;
+}
+
+
+/*
+ * 'cgi_compare_variables()' - Compare two variables.
+ */
+
+static int /* O - Result of comparison */
+cgi_compare_variables(const var_t *v1, /* I - First variable */
+ const var_t *v2) /* I - Second variable */
+{
+ return (strcasecmp(v1->name, v2->name));
+}
+
+
+/*
+ * 'cgi_find_variable()' - Find a variable...
+ */
+
+static var_t * /* O - Variable pointer or NULL */
+cgi_find_variable(const char *name) /* I - Name of variable */
+{
+ var_t key; /* Search key */
+
+
+ if (form_count < 1 || name == NULL)
+ return (NULL);
+
+ key.name = name;
+
+ return ((var_t *)bsearch(&key, form_vars, form_count, sizeof(var_t),
+ (int (*)(const void *, const void *))cgi_compare_variables));
+}
+
+
+/*
+ * 'cgi_initialize_get()' - Initialize form variables using the GET method.
+ */
+
+static int /* O - 1 if form data read */
+cgi_initialize_get(void)
+{
+ char *data; /* Pointer to form data string */
+
+
+#ifdef DEBUG
+ puts("Initializing variables using GET method...");
+#endif /* DEBUG */
+
+ /*
+ * Check to see if there is anything for us to read...
+ */
+
+ data = getenv("QUERY_STRING");
+ if (data == NULL || strlen(data) == 0)
+ return (0);
+
+ /*
+ * Parse it out and return...
+ */
+
+ return (cgi_initialize_string(data));
+}
+
+
+/*
+ * 'cgi_initialize_post()' - Initialize variables using the POST method.
+ */
+
+static int /* O - 1 if form data was read */
+cgi_initialize_post(void)
+{
+ char *content_length, /* Length of input data (string) */
+ *data; /* Pointer to form data string */
+ int length, /* Length of input data */
+ nbytes, /* Number of bytes read this read() */
+ tbytes, /* Total number of bytes read */
+ status; /* Return status */
+
+
+#ifdef DEBUG
+ puts("Initializing variables using POST method...");
+#endif /* DEBUG */
+
+ /*
+ * Check to see if there is anything for us to read...
+ */
+
+ content_length = getenv("CONTENT_LENGTH");
+ if (content_length == NULL || atoi(content_length) <= 0)
+ return (0);
+
+ /*
+ * Get the length of the input stream and allocate a buffer for it...
+ */
+
+ length = atoi(content_length);
+ data = malloc(length + 1);
+
+ if (data == NULL)
+ return (0);
+
+ /*
+ * Read the data into the buffer...
+ */
+
+ for (tbytes = 0; tbytes < length; tbytes += nbytes)
+ if ((nbytes = read(0, data + tbytes, length - tbytes)) < 0)
+ if (errno != EAGAIN)
+ {
+ free(data);
+ return (0);
+ }
+
+ data[length] = '\0';
+
+ /*
+ * Parse it out...
+ */
+
+ status = cgi_initialize_string(data);
+
+ /*
+ * Free the data and return...
+ */
+
+ free(data);
+
+ return (status);
+}
+
+
+/*
+ * 'cgi_initialize_string()' - Initialize form variables from a string.
+ */
+
+static int
+cgi_initialize_string(const char *data) /* I - Form data string */
+{
+ int done; /* True if we're done reading a form variable */
+ char *s, /* Pointer to current form string */
+ ch, /* Temporary character */
+ name[255], /* Name of form variable */
+ value[65536]; /* Variable value... */
+
+
+ /*
+ * Check input...
+ */
+
+ if (data == NULL)
+ return (0);
+
+ /*
+ * Loop until we've read all the form data...
+ */
+
+ while (*data != '\0')
+ {
+ /*
+ * Get the variable name...
+ */
+
+ for (s = name; *data != '\0'; data ++)
+ if (*data == '=')
+ break;
+ else if (*data >= ' ' && s < (name + sizeof(name) - 1))
+ *s++ = *data;
+
+ *s = '\0';
+ if (*data == '=')
+ data ++;
+ else
+ return (0);
+
+ /*
+ * Read the variable value...
+ */
+
+ for (s = value, done = 0; !done && *data != '\0'; data ++)
+ switch (*data)
+ {
+ case '&' : /* End of data... */
+ done = 1;
+ break;
+
+ case '+' : /* Escaped space character */
+ if (s < (value + sizeof(value) - 1))
+ *s++ = ' ';
+ break;
+
+ case '%' : /* Escaped control character */
+ /*
+ * Read the hex code...
+ */
+
+ if (s < (value + sizeof(value) - 1))
+ {
+ data ++;
+ ch = *data - '0';
+ if (ch > 9)
+ ch -= 7;
+ *s = ch << 4;
+
+ data ++;
+ ch = *data - '0';
+ if (ch > 9)
+ ch -= 7;
+ *s++ |= ch;
+ }
+ else
+ data += 2;
+ break;
+
+ default : /* Other characters come straight through */
+ if (*data >= ' ' && s < (value + sizeof(value) - 1))
+ *s++ = *data;
+ break;
+ }
+
+ *s = '\0'; /* nul terminate the string */
+
+ /*
+ * Remove trailing whitespace...
+ */
+
+ if (s > value)
+ s --;
+
+ while (s >= value && *s == ' ')
+ *s-- = '\0';
+
+ /*
+ * Add the string to the variable "database"...
+ */
+
+ if ((s = strrchr(name, '-')) != NULL && isdigit(s[1] & 255))
+ {
+ *s++ = '\0';
+ if (value[0])
+ cgiSetArray(name, atoi(s) - 1, value);
+ }
+ else if (cgiGetVariable(name) != NULL)
+ cgiSetArray(name, cgiGetSize(name), value);
+ else
+ cgiSetVariable(name, value);
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'cgi_sort_variables()' - Sort all form variables for faster lookup.
+ */
+
+static void
+cgi_sort_variables(void)
+{
+#ifdef DEBUG
+ int i;
+
+
+ puts("Sorting variables...");
+#endif /* DEBUG */
+
+ if (form_count < 2)
+ return;
+
+ qsort(form_vars, form_count, sizeof(var_t),
+ (int (*)(const void *, const void *))cgi_compare_variables);
+
+#ifdef DEBUG
+ puts("Sorted variable list is:");
+ for (i = 0; i < form_count; i ++)
+ printf("%d: %s (%d) = \"%s\" ...\n", i, form_vars[i].name,
+ form_vars[i].nvalues, form_vars[i].values[0]);
+#endif /* DEBUG */
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/conf/.cvsignore b/conf/.cvsignore
new file mode 100644
index 000000000..023ca04cf
--- /dev/null
+++ b/conf/.cvsignore
@@ -0,0 +1,2 @@
+cupsd.conf
+pam.conf
diff --git a/conf/Makefile b/conf/Makefile
new file mode 100644
index 000000000..5213dff3c
--- /dev/null
+++ b/conf/Makefile
@@ -0,0 +1,76 @@
+#
+# "$Id$"
+#
+# Configuration file makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# Config files...
+#
+
+KEEP = classes.conf client.conf cupsd.conf printers.conf
+REPLACE = mime.convs mime.types
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(SERVERROOT)
+ for file in $(KEEP); do \
+ if test -r $(SERVERROOT)/$$file ; then \
+ $(INSTALL_DATA) $$file $(SERVERROOT)/$$file.N ; \
+ else \
+ $(INSTALL_DATA) $$file $(SERVERROOT) ; \
+ fi ; \
+ done
+ for file in $(REPLACE); do \
+ if test -r $(SERVERROOT)/$$file ; then \
+ $(MV) $(SERVERROOT)/$$file $(SERVERROOT)/$$file.O ; \
+ fi ; \
+ $(INSTALL_DATA) $$file $(SERVERROOT) ; \
+ done
+ -if test x$(PAMDIR) != x$(BUILDROOT); then \
+ $(INSTALL_DIR) $(PAMDIR); \
+ $(INSTALL_DATA) $(PAMFILE) $(PAMDIR)/cups; \
+ fi
+
+
+#
+# End of "$Id$".
+#
diff --git a/conf/classes.conf b/conf/classes.conf
new file mode 100644
index 000000000..55988e142
--- /dev/null
+++ b/conf/classes.conf
@@ -0,0 +1,89 @@
+#
+# "$Id: classes.conf 4088 2004-02-25 20:15:27Z mike $"
+#
+# Sample class configuration file for the Common UNIX Printing System
+# (CUPS) scheduler.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+# #
+# This is a sample class configuration file. This file is included #
+# from the main configuration file (cups.conf) and lists all of the #
+# printer classes known to the system. #
+# #
+########################################################################
+
+#
+# Each class starts with a <Class name> definition. Class names
+# can be up to 128 characters in length and are *not* case sensitive.
+#
+# One <DefaultClass name> entry can appear in this file; if you don't
+# define a default destination, the first printer or class becomes
+# the default.
+#
+
+#<Class sample>
+#
+# Info: the description for the class.
+#
+
+#Info Acme LaserPrint 1000 Printers
+
+#
+# Location: the location of the printer.
+#
+
+#Location Room 101 in the activities building
+
+#
+# State: sets the initial state of the class. Can be one of the
+# following:
+#
+# Idle - Class is available to print new jobs.
+# Stopped - Class is disabled but accepting new jobs.
+#
+
+#State Idle
+
+#
+# StateMessage: sets the printer-state-message attribute for the class.
+#
+
+#StateMessage Class is idle.
+
+#
+# Accepting: is the class accepting jobs?
+#
+#Accepting Yes
+#Accepting No
+#
+
+#
+# Printer: adds a printer to the class.
+#
+
+#Printer sample
+#Printer sample@host2
+#</Class>
+
+#
+# End of "$Id: classes.conf 4088 2004-02-25 20:15:27Z mike $".
+#
diff --git a/conf/client.conf b/conf/client.conf
new file mode 100644
index 000000000..f87a6acf6
--- /dev/null
+++ b/conf/client.conf
@@ -0,0 +1,67 @@
+#
+# "$Id: client.conf 4088 2004-02-25 20:15:27Z mike $"
+#
+# Sample client configuration file for the Common UNIX Printing System
+# (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+# #
+# This is the CUPS client configuration file. This file is used to #
+# define client-specific parameters, such as the default server or #
+# default encryption settings. #
+# #
+########################################################################
+
+#
+# ServerName: the hostname of your server. By default CUPS will use the
+# hostname of the system or the value of the CUPS_SERVER environment
+# variable. ONLY ONE SERVER NAME MAY BE SPECIFIED AT A TIME. To use
+# more than one server you must use a local scheduler with browsing
+# and possibly polling.
+#
+
+#ServerName myhost.domain.com
+
+#
+# Encryption: whether or not to use encryption; this depends on having
+# the OpenSSL library linked into the CUPS library.
+#
+# Possible values:
+#
+# Always - Always use encryption (SSL)
+# Never - Never use encryption
+# Required - Use TLS encryption upgrade
+# IfRequested - Use encryption if the server requests it
+#
+# The default value is "IfRequested". This parameter can also be set
+# using the CUPS_ENCRYPTION environment variable.
+#
+
+#Encryption Always
+#Encryption Never
+#Encryption Required
+#Encryption IfRequested
+
+
+#
+# End of "$Id: client.conf 4088 2004-02-25 20:15:27Z mike $".
+#
diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in
new file mode 100644
index 000000000..6b2b8f2e2
--- /dev/null
+++ b/conf/cupsd.conf.in
@@ -0,0 +1,845 @@
+#
+# "$Id$"
+#
+# Sample configuration file for the Common UNIX Printing System (CUPS)
+# scheduler.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+# #
+# This is the CUPS configuration file. If you are familiar with #
+# Apache or any of the other popular web servers, we've followed the #
+# same format. Any configuration variable used here has the same #
+# semantics as the corresponding variable in Apache. If we need #
+# different functionality then a different name is used to avoid #
+# confusion... #
+# #
+########################################################################
+
+
+########
+######## Server Identity
+########
+
+#
+# ServerName: the hostname of your server, as advertised to the world.
+# By default CUPS will use the hostname of the system.
+#
+# To set the default server used by clients, see the client.conf file.
+#
+
+#ServerName myhost.domain.com
+
+#
+# ServerAdmin: the email address to send all complaints/problems to.
+# By default CUPS will use "root@hostname".
+#
+
+#ServerAdmin root@your.domain.com
+
+
+########
+######## Server Options
+########
+
+#
+# AccessLog: the access log file; if this does not start with a leading /
+# then it is assumed to be relative to ServerRoot. By default set to
+# "@CUPS_LOGDIR@/access_log"
+#
+# You can also use the special name "syslog" to send the output to the
+# syslog file or daemon.
+#
+
+#AccessLog @CUPS_LOGDIR@/access_log
+
+#
+# Classification: the classification level of the server. If set, this
+# classification is displayed on all pages, and raw printing is disabled.
+# The default is the empty string.
+#
+
+#Classification classified
+#Classification confidential
+#Classification secret
+#Classification topsecret
+#Classification unclassified
+
+#
+# ClassifyOverride: whether to allow users to override the classification
+# on printouts. If enabled, users can limit banner pages to before or
+# after the job, and can change the classification of a job, but cannot
+# completely eliminate the classification or banners.
+#
+# The default is off.
+#
+
+#ClassifyOverride off
+
+#
+# DataDir: the root directory for the CUPS data files.
+# By default "@CUPS_DATADIR@".
+#
+
+#DataDir @CUPS_DATADIR@
+
+#
+# DefaultCharset: the default character set to use. If not specified,
+# defaults to "utf-8". Note that this can also be overridden in
+# HTML documents...
+#
+
+#DefaultCharset utf-8
+
+#
+# DefaultLanguage: the default language if not specified by the browser.
+# If not specified, the current locale is used.
+#
+
+#DefaultLanguage en
+
+#
+# DocumentRoot: the root directory for HTTP documents that are served.
+# By default "@CUPS_DOCROOT@".
+#
+
+#DocumentRoot @CUPS_DOCROOT@
+
+#
+# ErrorLog: the error log file; if this does not start with a leading /
+# then it is assumed to be relative to ServerRoot. By default set to
+# "@CUPS_LOGDIR@/error_log"
+#
+# You can also use the special name "syslog" to send the output to the
+# syslog file or daemon.
+#
+
+#ErrorLog @CUPS_LOGDIR@/error_log
+
+#
+# FileDevice: determines whether the scheduler will allow new printers
+# to be added using device URIs of the form "file:/foo/bar". The default
+# is not to allow file devices due to the potential security vulnerability
+# and due to the fact that file devices do not support raw printing.
+#
+
+#FileDevice No
+
+
+#
+# FontPath: the path to locate all font files (currently only for pstoraster)
+# By default "@CUPS_FONTPATH@".
+#
+
+#FontPath @CUPS_FONTPATH@
+
+#
+# LogLevel: controls the number of messages logged to the ErrorLog
+# file and can be one of the following:
+#
+# debug2 Log everything.
+# debug Log almost everything.
+# info Log all requests and state changes.
+# warn Log errors and warnings.
+# error Log only errors.
+# none Log nothing.
+#
+
+LogLevel info
+
+#
+# MaxLogSize: controls the maximum size of each log file before they are
+# rotated. Defaults to 1048576 (1MB). Set to 0 to disable log rotating.
+#
+
+#MaxLogSize 0
+
+#
+# PageLog: the page log file; if this does not start with a leading /
+# then it is assumed to be relative to ServerRoot. By default set to
+# "@CUPS_LOGDIR@/page_log"
+#
+# You can also use the special name "syslog" to send the output to the
+# syslog file or daemon.
+#
+
+#PageLog @CUPS_LOGDIR@/page_log
+
+#
+# PreserveJobHistory: whether or not to preserve the job history after a
+# job is completed, cancelled, or stopped. Default is Yes.
+#
+
+#PreserveJobHistory Yes
+
+#
+# PreserveJobFiles: whether or not to preserve the job files after a
+# job is completed, cancelled, or stopped. Default is No.
+#
+
+#PreserveJobFiles No
+
+#
+# AutoPurgeJobs: automatically purge jobs when not needed for quotas.
+# Default is No.
+#
+
+#AutoPurgeJobs No
+
+#
+# MaxCopies: maximum number of copies that a user can request. Default is
+# 100.
+#
+
+#MaxCopies 100
+
+#
+# MaxJobs: maximum number of jobs to keep in memory (active and completed.)
+# Default is 500; the value 0 is used for no limit.
+#
+
+#MaxJobs 500
+
+#
+# MaxJobsPerPrinter: maximum number of active jobs per printer. The default
+# is 0 for no limit.
+#
+
+#MaxJobsPerPrinter 0
+
+#
+# MaxJobsPerUser: maximum number of active jobs per user. The default
+# is 0 for no limit.
+#
+
+#MaxJobsPerUser 0
+
+#
+# MaxPrinterHistory: controls the maximum number of history collections
+# in the printer-state-history attribute. Set to 0 to disable history
+# data.
+#
+
+#MaxPrinterHistory 10
+
+#
+# Printcap: the name of the printcap file. Default is /etc/printcap.
+# Leave blank to disable printcap file generation.
+#
+
+#Printcap /etc/printcap
+
+#
+# PrintcapFormat: the format of the printcap file, currently either
+# BSD or Solaris. The default is "BSD".
+#
+
+#PrintcapFormat BSD
+#PrintcapFormat Solaris
+
+#
+# PrintcapGUI: the name of the GUI options panel program to associate
+# with print queues under IRIX. The default is "/usr/bin/glpoptions"
+# from ESP Print Pro.
+#
+# This option is only used under IRIX; the options panel program
+# must accept the "-d printer" and "-o options" options and write
+# the selected printer options back to stdout on completion.
+#
+
+#PrintcapGUI /usr/bin/glpoptions
+
+#
+# RequestRoot: the directory where request files are stored.
+# By default "@CUPS_REQUESTS@".
+#
+
+#RequestRoot @CUPS_REQUESTS@
+
+#
+# RemoteRoot: the name of the user assigned to unauthenticated accesses
+# from remote systems. By default "remroot".
+#
+
+#RemoteRoot remroot
+
+#
+# ServerBin: the root directory for the scheduler executables.
+# By default "@CUPS_SERVERBIN@".
+#
+
+#ServerBin @CUPS_SERVERBIN@
+
+#
+# ServerRoot: the root directory for the scheduler.
+# By default "@CUPS_SERVERROOT@".
+#
+
+#ServerRoot @CUPS_SERVERROOT@
+
+
+#
+# ServerTokens: specifies what information in provided in the Server
+# header of HTTP responses. The default is Minor.
+#
+# ServerTokens None
+# ServerTokens ProductOnly CUPS
+# ServerTokens Major CUPS/1
+# ServerTokens Minor CUPS/1.1
+# ServerTokens Minimal CUPS/@CUPS_VERSION@
+# ServerTokens OS CUPS/@CUPS_VERSION@ (uname)
+# ServerTokens Full CUPS/@CUPS_VERSION@ (uname) IPP/1.1
+#
+
+#ServerTokens Minor
+
+
+########
+######## Fax Support
+########
+
+#
+# FaxRetryLimit: the number of times a fax job is retried.
+# The default is 5 times.
+#
+
+#FaxRetryLimit 5
+
+#
+# FaxRetryInterval: the number of seconds between fax job retries.
+# The default is 300 seconds/5 minutes.
+#
+
+#FaxRetryInterval 300
+
+
+########
+######## Encryption Support
+########
+
+#
+# ServerCertificate: the file to read containing the server's certificate.
+# Defaults to "@CUPS_SERVERROOT@/ssl/server.crt".
+#
+
+#ServerCertificate @CUPS_SERVERROOT@/ssl/server.crt
+
+#
+# ServerKey: the file to read containing the server's key.
+# Defaults to "@CUPS_SERVERROOT@/ssl/server.key".
+#
+
+#ServerKey @CUPS_SERVERROOT@/ssl/server.key
+
+
+########
+######## Filter Options
+########
+
+#
+# User/Group: the user and group the server runs under. Normally this
+# must be @CUPS_USER@ and @CUPS_GROUP@, however you can configure things for another
+# user or group as needed.
+#
+# Note: the server must be run initially as root to support the
+# default IPP port of 631. It changes users whenever an external
+# program is run, or if the RunAsUser directive is specified...
+#
+
+#User @CUPS_USER@
+#Group @CUPS_GROUP@
+
+#
+# RIPCache: the amount of memory that each RIP should use to cache
+# bitmaps. The value can be any real number followed by "k" for
+# kilobytes, "m" for megabytes, "g" for gigabytes, or "t" for tiles
+# (1 tile = 256x256 pixels.) Defaults to "8m" (8 megabytes).
+#
+
+#RIPCache 8m
+
+#
+# TempDir: the directory to put temporary files in. This directory must be
+# writable by the user defined above! Defaults to "@CUPS_REQUESTS@/tmp" or
+# the value of the TMPDIR environment variable.
+#
+
+#TempDir @CUPS_REQUESTS@/tmp
+
+#
+# FilterLimit: sets the maximum cost of all job filters that can be run
+# at the same time. A limit of 0 means no limit. A typical job may need
+# a filter limit of at least 200; limits less than the minimum required
+# by a job force a single job to be printed at any time.
+#
+# The default limit is 0 (unlimited).
+#
+
+#FilterLimit 0
+
+########
+######## Network Options
+########
+
+#
+# Ports/addresses that we listen to. The default port 631 is reserved
+# for the Internet Printing Protocol (IPP) and is what we use here.
+#
+# You can have multiple Port/Listen lines to listen to more than one
+# port or address, or to restrict access:
+#
+# Port 80
+# Port 631
+# Listen hostname
+# Listen hostname:80
+# Listen hostname:631
+# Listen 1.2.3.4
+# Listen 1.2.3.4:631
+#
+# NOTE: Unfortunately, most web browsers don't support TLS or HTTP Upgrades
+# for encryption. If you want to support web-based encryption you'll
+# probably need to listen on port 443 (the "https" port...)
+#
+# NOTE 2: In order for the command-line and web interfaces to work, you
+# must have at least one Port or Listen line that allows access from the
+# local loopback address (localhost).
+#
+
+#Port 80
+#Port 443
+Port 631
+
+#
+# HostNameLookups: whether or not to do lookups on IP addresses to get a
+# fully-qualified hostname. This defaults to Off for performance reasons...
+#
+
+#HostNameLookups On
+
+#
+# KeepAlive: whether or not to support the Keep-Alive connection
+# option. Default is on.
+#
+
+#KeepAlive On
+
+#
+# KeepAliveTimeout: the timeout before Keep-Alive connections are
+# automatically closed. Default is 60 seconds.
+#
+
+#KeepAliveTimeout 60
+
+#
+# MaxClients: controls the maximum number of simultaneous clients that
+# will be handled. Defaults to 100.
+#
+
+#MaxClients 100
+
+#
+# MaxClientsPerHost: controls the maximum number of simultaneous clients that
+# will be handled from a specific host. Defaults to 10 or 1/10th of the
+# MaxClients setting, whichever is larger. A value of 0 specifies the
+# automatic (10 or 1/10th) setting.
+#
+
+#MaxClientsPerHost 0
+
+#
+# MaxRequestSize: controls the maximum size of HTTP requests and print files.
+# Set to 0 to disable this feature (defaults to 0.)
+#
+
+#MaxRequestSize 0
+
+#
+# Timeout: the timeout before requests time out. Default is 300 seconds.
+#
+
+#Timeout 300
+
+
+########
+######## Browsing Options
+########
+
+#
+# Browsing: whether or not to broadcast and/or listen for CUPS printer
+# information on the network. Enabled by default.
+#
+
+#Browsing On
+
+#
+# BrowseProtocols: which protocols to use for browsing. Can be
+# any of the following separated by whitespace and/or commas:
+#
+# all - Use all supported protocols.
+# cups - Use the CUPS browse protocol.
+# slp - Use the SLPv2 protocol.
+#
+# The default is "cups".
+#
+# NOTE: If you choose to use SLPv2, it is *strongly* recommended that
+# you have at least one SLP Directory Agent (DA) on your
+# network. Otherwise, browse updates can take several seconds,
+# during which the scheduler will not respond to client
+# requests.
+#
+
+#BrowseProtocols cups
+
+#
+# BrowseAddress: specifies a broadcast address to be used. By
+# default browsing information is not sent!
+#
+# Note: HP-UX does not properly handle broadcast unless you have a
+# Class A, B, C, or D netmask (i.e. no CIDR support).
+#
+# Note: Using the "global" broadcast address (255.255.255.255) will
+# activate a Linux demand-dial link with the default configuration.
+# If you have a LAN as well as the dial-up link, use the LAN's
+# broadcast address.
+#
+# The @LOCAL address broadcasts to all non point-to-point interfaces.
+# For example, if you have a LAN and a dial-up link, @LOCAL would
+# send printer updates to the LAN but not to the dial-up link.
+# Similarly, the @IF(name) address sends to the named network
+# interface, e.g. @IF(eth0) under Linux. Interfaces are refreshed
+# automatically (no more than once every 60 seconds), so they can
+# be used on dynamically-configured interfaces, e.g. PPP, 802.11, etc.
+#
+
+#BrowseAddress x.y.z.255
+#BrowseAddress x.y.255.255
+#BrowseAddress x.255.255.255
+#BrowseAddress 255.255.255.255
+#BrowseAddress @LOCAL
+#BrowseAddress @IF(name)
+
+#
+# BrowseShortNames: whether or not to use "short" names for remote printers
+# when possible (e.g. "printer" instead of "printer@host".) Enabled by
+# default.
+#
+
+#BrowseShortNames Yes
+
+#
+# BrowseAllow: specifies an address mask to allow for incoming browser
+# packets. The default is to allow packets from all addresses.
+#
+# BrowseDeny: specifies an address mask to deny for incoming browser
+# packets. The default is to deny packets from no addresses.
+#
+# Both "BrowseAllow" and "BrowseDeny" accept the following notations for
+# addresses:
+#
+# All
+# None
+# *.domain.com
+# .domain.com
+# host.domain.com
+# nnn.*
+# nnn.nnn.*
+# nnn.nnn.nnn.*
+# nnn.nnn.nnn.nnn
+# nnn.nnn.nnn.nnn/mm
+# nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+# @LOCAL
+# @IF(name)
+#
+# The hostname/domainname restrictions only work if you have turned hostname
+# lookups on!
+#
+
+#BrowseAllow address
+#BrowseDeny address
+
+#
+# BrowseInterval: the time between browsing updates in seconds. Default
+# is 30 seconds.
+#
+# Note that browsing information is sent whenever a printer's state changes
+# as well, so this represents the maximum time between updates.
+#
+# Set this to 0 to disable outgoing broadcasts so your local printers are
+# not advertised but you can still see printers on other hosts.
+#
+
+#BrowseInterval 30
+
+#
+# BrowseOrder: specifies the order of BrowseAllow/BrowseDeny comparisons.
+#
+
+#BrowseOrder allow,deny
+#BrowseOrder deny,allow
+
+#
+# BrowsePoll: poll the named server(s) for printers
+#
+
+#BrowsePoll address:port
+
+#
+# BrowsePort: the port used for UDP broadcasts. By default this is
+# the IPP port; if you change this you need to do it on all servers.
+# Only one BrowsePort is recognized.
+#
+
+#BrowsePort 631
+
+#
+# BrowseRelay: relay browser packets from one address/network to another.
+#
+
+#BrowseRelay source-address destination-address
+#BrowseRelay @IF(src) @IF(dst)
+
+#
+# BrowseTimeout: the timeout for network printers - if we don't
+# get an update within this time the printer will be removed
+# from the printer list. This number definitely should not be
+# less the BrowseInterval value for obvious reasons. Defaults
+# to 300 seconds.
+#
+
+#BrowseTimeout 300
+
+#
+# ImplicitClasses: whether or not to use implicit classes.
+#
+# Printer classes can be specified explicitly in the classes.conf
+# file, implicitly based upon the printers available on the LAN, or
+# both.
+#
+# When ImplicitClasses is On, printers on the LAN with the same name
+# (e.g. Acme-LaserPrint-1000) will be put into a class with the same
+# name. This allows you to setup multiple redundant queues on a LAN
+# without a lot of administrative difficulties. If a user sends a
+# job to Acme-LaserPrint-1000, the job will go to the first available
+# queue.
+#
+# Enabled by default.
+#
+
+#ImplicitClasses On
+
+#
+# ImplicitAnyClasses: whether or not to create "AnyPrinter" implicit
+# classes.
+#
+# When ImplicitAnyClasses is On and a local queue of the same name
+# exists, e.g. "printer", "printer@server1", "printer@server1", then
+# an implicit class called "Anyprinter" is created instead.
+#
+# When ImplicitAnyClasses is Off, implicit classes are not created
+# when there is a local queue of the same name.
+#
+# Disabled by default.
+#
+
+#ImplicitAnyCLasses Off
+
+#
+# HideImplicitMembers: whether or not to show the members of an
+# implicit class.
+#
+# When HideImplicitMembers is On, any remote printers that are
+# part of an implicit class are hidden from the user, who will
+# then only see a single queue even though many queues will be
+# supporting the implicit class.
+#
+# Enabled by default.
+#
+
+#HideImplicitMembers On
+
+
+########
+######## Security Options
+########
+
+#
+# SystemGroup: the group name for "System" (printer administration)
+# access. The default varies depending on the operating system, but
+# will be "sys", "system", or "root" (checked for in that order.)
+#
+
+#SystemGroup @CUPS_GROUP@
+
+#
+# RootCertDuration: How frequently the root certificate is regenerated.
+# Defaults to 300 seconds.
+#
+
+#RootCertDuration 300
+
+#
+# Access permissions for each directory served by the scheduler.
+# Locations are relative to DocumentRoot...
+#
+# AuthType: the authorization to use:
+#
+# None - Perform no authentication
+# Basic - Perform authentication using the HTTP Basic method.
+# Digest - Perform authentication using the HTTP Digest method.
+#
+# (Note: local certificate authentication can be substituted by
+# the client for Basic or Digest when connecting to the
+# localhost interface)
+#
+# AuthClass: the authorization class; currently only "Anonymous", "User",
+# "System" (valid user belonging to group SystemGroup), and "Group"
+# (valid user belonging to the specified group) are supported.
+#
+# AuthGroupName: the group name for "Group" authorization.
+#
+# Order: the order of Allow/Deny processing.
+#
+# Allow: allows access from the specified hostname, domain, IP address,
+# network, or interface.
+#
+# Deny: denies access from the specified hostname, domain, IP address,
+# network, or interface.
+#
+# Both "Allow" and "Deny" accept the following notations for addresses:
+#
+# All
+# None
+# *.domain.com
+# .domain.com
+# host.domain.com
+# nnn.*
+# nnn.nnn.*
+# nnn.nnn.nnn.*
+# nnn.nnn.nnn.nnn
+# nnn.nnn.nnn.nnn/mm
+# nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+# @LOCAL
+# @IF(name)
+#
+# The host and domain address require that you enable hostname lookups
+# with "HostNameLookups On" above.
+#
+# The @LOCAL address allows or denies from all non point-to-point
+# interfaces. For example, if you have a LAN and a dial-up link,
+# @LOCAL could allow connections from the LAN but not from the dial-up
+# link. Similarly, the @IF(name) address allows or denies from the
+# named network interface, e.g. @IF(eth0) under Linux. Interfaces are
+# refreshed automatically (no more than once every 60 seconds), so
+# they can be used on dynamically-configured interfaces, e.g. PPP,
+# 802.11, etc.
+#
+# Encryption: whether or not to use encryption; this depends on having
+# the OpenSSL library linked into the CUPS library and scheduler.
+#
+# Possible values:
+#
+# Always - Always use encryption (SSL)
+# Never - Never use encryption
+# Required - Use TLS encryption upgrade
+# IfRequested - Use encryption if the server requests it
+#
+# The default value is "IfRequested".
+#
+
+<Location />
+Order Deny,Allow
+Deny From All
+Allow From 127.0.0.1
+</Location>
+
+#<Location /classes>
+#
+# You may wish to limit access to printers and classes, either with Allow
+# and Deny lines, or by requiring a username and password.
+#
+#</Location>
+
+#<Location /classes/name>
+#
+# You may wish to limit access to printers and classes, either with Allow
+# and Deny lines, or by requiring a username and password.
+#
+#</Location>
+
+#<Location /jobs>
+#
+# You may wish to limit access to job operations, either with Allow
+# and Deny lines, or by requiring a username and password.
+#
+#</Location>
+
+#<Location /printers>
+#
+# You may wish to limit access to printers and classes, either with Allow
+# and Deny lines, or by requiring a username and password.
+#
+#</Location>
+
+#<Location /printers/name>
+#
+# You may wish to limit access to printers and classes, either with Allow
+# and Deny lines, or by requiring a username and password.
+#
+
+## Anonymous access (default)
+#AuthType None
+
+## Require a username and password (Basic authentication)
+#AuthType Basic
+#AuthClass User
+
+## Require a username and password (Digest/MD5 authentication)
+#AuthType Digest
+#AuthClass User
+
+## Restrict access to local domain
+#Order Deny,Allow
+#Deny From All
+#Allow From .mydomain.com
+#</Location>
+
+<Location /admin>
+#
+# You definitely will want to limit access to the administration functions.
+# The default configuration requires a local connection from a user who
+# is a member of the system group to do any admin tasks. You can change
+# the group name using the SystemGroup directive.
+#
+
+AuthType Basic
+AuthClass System
+
+## Restrict access to local domain
+Order Deny,Allow
+Deny From All
+Allow From 127.0.0.1
+
+#Encryption Required
+</Location>
+
+#
+# End of "$Id$".
+#
diff --git a/conf/mime.convs b/conf/mime.convs
new file mode 100644
index 000000000..6114e690e
--- /dev/null
+++ b/conf/mime.convs
@@ -0,0 +1,118 @@
+#
+# "$Id: mime.convs 4087 2004-02-25 20:14:54Z mike $"
+#
+# MIME converts file for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+#
+# Format of Lines:
+#
+# source/type destination/type cost filter
+#
+# General Notes:
+#
+# The "cost" field is used to find the least costly filters to run
+# when converting a job file to a printable format.
+#
+# All filters *must* accept the standard command-line arguments
+# (job-id, user, title, copies, options, [filename or stdin]) to
+# work with CUPS.
+#
+
+########################################################################
+#
+# PostScript filters
+#
+
+application/pdf application/postscript 33 pdftops
+application/postscript application/vnd.cups-postscript 66 pstops
+application/vnd.hp-HPGL application/postscript 66 hpgltops
+application/x-cshell application/postscript 33 texttops
+application/x-perl application/postscript 33 texttops
+application/x-shell application/postscript 33 texttops
+text/plain application/postscript 33 texttops
+text/html application/postscript 33 texttops
+image/gif application/vnd.cups-postscript 66 imagetops
+image/png application/vnd.cups-postscript 66 imagetops
+image/jpeg application/vnd.cups-postscript 66 imagetops
+image/tiff application/vnd.cups-postscript 66 imagetops
+image/x-bitmap application/vnd.cups-postscript 66 imagetops
+image/x-photocd application/vnd.cups-postscript 66 imagetops
+image/x-portable-anymap application/vnd.cups-postscript 66 imagetops
+image/x-portable-bitmap application/vnd.cups-postscript 66 imagetops
+image/x-portable-graymap application/vnd.cups-postscript 66 imagetops
+image/x-portable-pixmap application/vnd.cups-postscript 66 imagetops
+image/x-sgi-rgb application/vnd.cups-postscript 66 imagetops
+image/x-xbitmap application/vnd.cups-postscript 66 imagetops
+image/x-xpixmap application/vnd.cups-postscript 66 imagetops
+#image/x-xwindowdump application/vnd.cups-postscript 66 imagetops
+image/x-sun-raster application/vnd.cups-postscript 66 imagetops
+
+
+########################################################################
+#
+# Form filter...
+#
+# This filter does not currently exist, but the file format is defined
+# in the IDD and registered with the IANA for future use...
+#
+
+#application/vnd.cups-form application/vnd.cups-postscript 33 formtops
+
+########################################################################
+#
+# Raster filters...
+#
+
+image/gif application/vnd.cups-raster 100 imagetoraster
+image/png application/vnd.cups-raster 100 imagetoraster
+image/jpeg application/vnd.cups-raster 100 imagetoraster
+image/tiff application/vnd.cups-raster 100 imagetoraster
+image/x-bitmap application/vnd.cups-raster 100 imagetoraster
+image/x-photocd application/vnd.cups-raster 100 imagetoraster
+image/x-portable-anymap application/vnd.cups-raster 100 imagetoraster
+image/x-portable-bitmap application/vnd.cups-raster 100 imagetoraster
+image/x-portable-graymap application/vnd.cups-raster 100 imagetoraster
+image/x-portable-pixmap application/vnd.cups-raster 100 imagetoraster
+image/x-sgi-rgb application/vnd.cups-raster 100 imagetoraster
+image/x-xbitmap application/vnd.cups-raster 100 imagetoraster
+image/x-xpixmap application/vnd.cups-raster 100 imagetoraster
+#image/x-xwindowdump application/vnd.cups-raster 100 imagetoraster
+image/x-sun-raster application/vnd.cups-raster 100 imagetoraster
+
+# pstoraster is now part of ESP Ghostscript...
+#application/vnd.cups-postscript application/vnd.cups-raster 100 pstoraster
+
+########################################################################
+#
+# Raw filter...
+#
+# Uncomment the following filter and the application/octet-stream type
+# in mime.types to allow printing of arbitrary files without the -oraw
+# option.
+#
+
+#application/octet-stream application/vnd.cups-raw 0 -
+
+#
+# End of "$Id: mime.convs 4087 2004-02-25 20:14:54Z mike $".
+#
diff --git a/conf/mime.types b/conf/mime.types
new file mode 100644
index 000000000..49fbefc26
--- /dev/null
+++ b/conf/mime.types
@@ -0,0 +1,162 @@
+#
+# "$Id: mime.types 4413 2004-09-23 14:30:19Z mike $"
+#
+# MIME types file for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+#
+# Format of Lines:
+#
+# super/type rules
+#
+# "rules" can be any combination of:
+#
+# ( expr ) Parenthesis for expression grouping
+# + Logical AND
+# , or whitespace Logical OR
+# ! Logical NOT
+# match("pattern") Pattern match on filename
+# extension Pattern match on "*.extension"
+# ascii(offset,length) True if bytes are valid printable ASCII
+# (CR, NL, TAB, BS, 32-126)
+# printable(offset,length) True if bytes are printable 8-bit chars
+# (CR, NL, TAB, BS, 32-126, 128-254)
+# string(offset,"string") True if bytes are identical to string
+# istring(offset,"string") True if bytes are identical to
+# case-insensitive string
+# char(offset,value) True if byte is identical
+# short(offset,value) True if 16-bit integer is identical
+# int(offset,value) True if 32-bit integer is identical
+# locale("string") True if current locale matches string
+# contains(offset,range,"string") True if the range contains the string
+#
+# General Notes:
+#
+# MIME type names are case-insensitive. Internally they are converted
+# to lowercase. Multiple occurrences of a type will cause the provided
+# rules to be appended to the existing definition. Type names are sorted
+# in ascending order, so if two types use the same rules to resolve a type
+# (e.g. doc extension for two types), the returned type will be the first
+# type in the sorted list.
+#
+# The "printable" rule differs from the "ascii" rule in that it also
+# accepts 8-bit characters in the range 128-255.
+#
+# String constants must be surrounded by "" if they contain whitespace.
+# To insert binary data into a string, use the <hex> notation.
+#
+
+########################################################################
+#
+# Application-generated files...
+#
+
+#application/msword doc string(0,<D0CF11E0A1B11AE1>)
+application/pdf pdf string(0,%PDF)
+application/postscript ai eps ps string(0,%!) string(0,<04>%!) \
+ contains(0,128,<1B>%-12345X) + \
+ (contains(0,1024,"LANGUAGE=POSTSCRIPT") \
+ contains(0,1024,"LANGUAGE = Postscript") \
+ contains(0,1024,"LANGUAGE = PostScript") \
+ contains(0,1024,"LANGUAGE = POSTSCRIPT"))
+application/vnd.hp-HPGL hpgl string(0,<1B>&)\
+ string(0,<1B>E<1B>%0B) \
+ string(0,<1B>%-1B) string(0,<201B>)\
+ string(0,BP;) string(0,IN;) string(0,DF;) \
+ string(0,BPINPS;) \
+ (contains(0,128,<1B>%-12345X) + \
+ (contains(0,1024,"LANGUAGE=HPGL") \
+ contains(0,1024,"LANGUAGE = HPGL")))
+
+########################################################################
+#
+# Image files...
+#
+
+image/gif gif string(0,GIF87a) string(0,GIF89a)
+image/png png string(0,<89>PNG)
+image/jpeg jpeg jpg jpe string(0,<FFD8FF>) &&\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+image/tiff tiff tif string(0,MM) string(0,II)
+image/x-photocd pcd string(2048,PCD_IPI)
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm string(0,P1) string(0,P4)
+image/x-portable-graymap pgm string(0,P2) string(0,P5)
+image/x-portable-pixmap ppm string(0,P3) string(0,P6)
+image/x-sgi-rgb rgb sgi bw icon short(0,474)
+image/x-xbitmap xbm
+image/x-xpixmap xpm ascii(0,1024) + string(3,"XPM")
+#image/x-xwindowdump xwd string(4,<00000007>)
+image/x-sun-raster ras string(0,<59a66a95>)
+
+#image/fpx fpx
+image/x-alias pix short(8,8) short(8,24)
+image/x-bitmap bmp string(0,BM) && !printable(2,14)
+
+########################################################################
+#
+# Text files...
+#
+
+text/html html htm printable(0,1024) +\
+ (istring(0,"<HTML>") istring(0,"<!DOCTYPE"))
+application/x-cshell csh printable(0,1024) + string(0,#!) +\
+ (contains(2,80,/csh) contains(2,80,/tcsh))
+application/x-perl pl printable(0,1024) + string(0,#!) +\
+ contains(2,80,/perl)
+application/x-shell sh printable(0,1024) + string(0,#!) +\
+ (contains(2,80,/bash) contains(2,80,/ksh)\
+ contains(2,80,/sh) contains(2,80,/zsh))
+text/plain txt printable(0,1024)
+
+########################################################################
+#
+# CUPS-specific types...
+#
+
+application/vnd.cups-command string(0,'#CUPS-COMMAND')
+application/vnd.cups-form string(0,"<CUPSFORM>")
+application/vnd.cups-postscript
+application/vnd.cups-raster string(0,"RaSt") string(0,"tSaR")
+application/vnd.cups-raw (string(0,<1B>E) + !string(2,<1B>%0B)) \
+ string(0,<1B>@) \
+ (contains(0,128,<1B>%-12345X) + \
+ (contains(0,1024,"LANGUAGE=PCL") \
+ contains(0,1024,"LANGUAGE = PCL")))
+
+########################################################################
+#
+# Raw print file support...
+#
+# Uncomment the following type and the application/octet-stream
+# filter line in mime.convs to allow raw file printing without the
+# -oraw option.
+#
+
+#application/octet-stream
+
+#
+# End of "$Id: mime.types 4413 2004-09-23 14:30:19Z mike $".
+#
diff --git a/conf/pam.darwin b/conf/pam.darwin
new file mode 100644
index 000000000..ff724da4d
--- /dev/null
+++ b/conf/pam.darwin
@@ -0,0 +1,7 @@
+# cups: auth account password session
+auth sufficient pam_securityserver.so
+auth sufficient pam_unix.so
+auth required pam_deny.so
+account required pam_permit.so
+password required pam_deny.so
+session required pam_permit.so
diff --git a/conf/pam.irix b/conf/pam.irix
new file mode 100644
index 000000000..476383acb
--- /dev/null
+++ b/conf/pam.irix
@@ -0,0 +1,3 @@
+#%PAM-1.0
+auth required pam_unix.so shadow nodelay nullok
+account required pam_unix.so
diff --git a/conf/pam.std.in b/conf/pam.std.in
new file mode 100644
index 000000000..3ddcdd0d3
--- /dev/null
+++ b/conf/pam.std.in
@@ -0,0 +1,2 @@
+auth required @PAMMOD@ nullok shadow
+account required @PAMMOD@
diff --git a/conf/printcap b/conf/printcap
new file mode 100644
index 000000000..230c3017d
--- /dev/null
+++ b/conf/printcap
@@ -0,0 +1,2 @@
+# This is a dummy printcap file that is automatically generated by the
+# CUPS software for old applications that rely on it.
diff --git a/conf/printers.conf b/conf/printers.conf
new file mode 100644
index 000000000..a00980dbb
--- /dev/null
+++ b/conf/printers.conf
@@ -0,0 +1,96 @@
+#
+# "$Id: printers.conf 4088 2004-02-25 20:15:27Z mike $"
+#
+# Sample printer configuration file for the Common UNIX Printing System
+# (CUPS) scheduler.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+########################################################################
+# #
+# This is a sample printer configuration file. This file is included #
+# from the main configuration file (cups.conf) and lists all of the #
+# printers known to the system. #
+# #
+########################################################################
+
+#
+# Each printer starts with a <Printer name> definition. Printer names
+# can be up to 128 characters in length and are *not* case sensitive.
+#
+# One <DefaultPrinter name> entry can appear in this file; if you don't
+# define a default destination, the first printer or class becomes the
+# default.
+#
+
+#<Printer sample>
+#
+# Info: the description for the printer.
+#
+
+#Info Acme LaserPrint 1000
+
+#
+# Location: the location of the printer.
+#
+
+#Location Room 101 in the activities building
+
+#
+# DeviceURI: the device URI for this printer.
+#
+
+#DeviceURI parallel:/dev/plp
+#DeviceURI serial:/dev/ttyd1?baud=38400+size=8+parity=none+flow=soft
+#DeviceURI scsi:/dev/scsi/sc1d6l0
+#DeviceURI socket://hostname:port
+#DeviceURI tftp://hostname/path
+#DeviceURI ftp://hostname/path
+#DeviceURI http://hostname[:port]/path
+#DeviceURI ipp://hostname/path
+#DeviceURI smb://hostname/printer
+
+#
+# State: sets the initial state of the printer. Can be one of the
+# following:
+#
+# Idle - Printer is available to print new jobs.
+# Stopped - Printer is disabled but accepting new jobs.
+#
+
+#State Idle
+
+#
+# StateMessage: sets the printer-state-message attribute for the printer.
+#
+
+#StateMessage Printer is idle.
+
+#
+# Accepting: is the printer accepting jobs?
+#
+#Accepting Yes
+#Accepting No
+
+#</Printer>
+
+#
+# End of "$Id: printers.conf 4088 2004-02-25 20:15:27Z mike $".
+#
diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4
new file mode 100644
index 000000000..bd0eded54
--- /dev/null
+++ b/config-scripts/cups-common.m4
@@ -0,0 +1,217 @@
+dnl
+dnl "$Id: cups-common.m4 4473 2004-12-16 19:42:22Z mike $"
+dnl
+dnl Common configuration stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+dnl We need at least autoconf 2.50...
+AC_PREREQ(2.50)
+
+dnl Set the name of the config header file...
+AC_CONFIG_HEADER(config.h)
+
+dnl Version number information...
+CUPS_VERSION="1.1.23rc1"
+AC_SUBST(CUPS_VERSION)
+AC_DEFINE_UNQUOTED(CUPS_SVERSION, "CUPS v$CUPS_VERSION")
+AC_DEFINE_UNQUOTED(CUPS_MINIMAL, "CUPS/$CUPS_VERSION")
+
+dnl Default compiler flags...
+CFLAGS="${CFLAGS:=}"
+CPPFLAGS="${CPPFLAGS:=}"
+CXXFLAGS="${CXXFLAGS:=}"
+LDFLAGS="${LDFLAGS:=}"
+
+dnl Checks for programs...
+AC_PROG_AWK
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_CPP
+AC_PROG_INSTALL
+if test "$INSTALL" = "$ac_install_sh"; then
+ # Use full path to install-sh script...
+ INSTALL="`pwd`/install-sh -c"
+fi
+AC_PROG_RANLIB
+AC_PATH_PROG(AR,ar)
+AC_PATH_PROG(HTMLDOC,htmldoc)
+AC_PATH_PROG(LN,ln)
+AC_PATH_PROG(MV,mv)
+AC_PATH_PROG(NROFF,nroff)
+if test "x$NROFF" = x; then
+ AC_PATH_PROG(GROFF,groff)
+ if test "x$GROFF" = x; then
+ NROFF="echo"
+ else
+ NROFF="$GROFF -T ascii"
+ fi
+fi
+AC_PATH_PROG(RM,rm)
+AC_PATH_PROG(SED,sed)
+AC_PATH_PROG(STRIP,strip)
+
+if test "x$AR" = x; then
+ AC_MSG_ERROR([Unable to find required library archive command.])
+fi
+if test "x$CC" = x; then
+ AC_MSG_ERROR([Unable to find required C compiler command.])
+fi
+if test "x$CXX" = x; then
+ AC_MSG_ERROR([Unable to find required C++ compiler command.])
+fi
+
+dnl Architecture checks...
+AC_C_BIGENDIAN
+
+dnl Check for libraries...
+AC_SEARCH_LIBS(crypt, crypt)
+AC_SEARCH_LIBS(getspent, sec gen)
+
+LIBMALLOC=""
+AC_ARG_ENABLE(mallinfo, [ --enable-mallinfo turn on malloc debug information, default=no])
+
+if test x$enable_mallinfo = xyes; then
+ AC_CHECK_LIB(c,mallinfo,LIBS="$LIBS"; AC_DEFINE(HAVE_MALLINFO),LIBS="$LIBS")
+ if test "$ac_cv_lib_c_mallinfo" = "no"; then
+ AC_CHECK_LIB(malloc,mallinfo,
+ LIBS="$LIBS"
+ LIBMALLOC="-lmalloc"
+ AC_DEFINE(HAVE_MALLINFO),
+ LIBS="$LIBS")
+ fi
+fi
+
+AC_SUBST(LIBMALLOC)
+
+dnl Check for libpaper support...
+AC_ARG_ENABLE(libpaper, [ --enable-libpaper turn on libpaper support, default=no])
+
+if test x$enable_libpaper = xyes; then
+ AC_CHECK_LIB(paper,systempapername,
+ AC_DEFINE(HAVE_LIBPAPER)
+ LIBPAPER="-lpaper",
+ LIBPAPER="")
+else
+ LIBPAPER=""
+fi
+AC_SUBST(LIBPAPER)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_DIRENT
+AC_CHECK_HEADER(crypt.h,AC_DEFINE(HAVE_CRYPT_H))
+AC_CHECK_HEADER(langinfo.h,AC_DEFINE(HAVE_LANGINFO_H))
+AC_CHECK_HEADER(malloc.h,AC_DEFINE(HAVE_MALLOC_H))
+AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H))
+AC_CHECK_HEADER(string.h,AC_DEFINE(HAVE_STRING_H))
+AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H))
+AC_CHECK_HEADER(bstring.h,AC_DEFINE(HAVE_BSTRING_H))
+AC_CHECK_HEADER(usersec.h,AC_DEFINE(HAVE_USERSEC_H))
+AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_H))
+
+dnl Checks for string functions.
+AC_CHECK_FUNCS(strdup strcasecmp strncasecmp strlcat strlcpy)
+if test "$uname" = "HP-UX" -a "$uversion" = "1020"; then
+ echo Forcing snprintf emulation for HP-UX.
+else
+ AC_CHECK_FUNCS(snprintf vsnprintf)
+fi
+
+dnl Check OS version and use appropriate format string for strftime...
+AC_MSG_CHECKING(for correct format string to use with strftime)
+
+case "$uname" in
+ IRIX | SunOS*)
+ # IRIX and SunOS
+ AC_MSG_RESULT(NULL)
+ AC_DEFINE(CUPS_STRFTIME_FORMAT, NULL)
+ ;;
+ *)
+ # All others
+ AC_MSG_RESULT("%c")
+ AC_DEFINE(CUPS_STRFTIME_FORMAT, "%c")
+ ;;
+esac
+
+dnl Checks for mkstemp and mkstemps functions.
+AC_CHECK_FUNCS(mkstemp mkstemps)
+
+dnl Check for geteuid function.
+AC_CHECK_FUNCS(geteuid)
+
+dnl Check for vsyslog function.
+AC_CHECK_FUNCS(vsyslog)
+
+dnl Checks for signal functions.
+case "$uname" in
+ Linux | GNU)
+ # Do not use sigset on Linux or GNU HURD
+ ;;
+ *)
+ # Use sigset on other platforms, if available
+ AC_CHECK_FUNCS(sigset)
+ ;;
+esac
+
+AC_CHECK_FUNCS(sigaction)
+
+dnl Checks for wait functions.
+AC_CHECK_FUNCS(waitpid)
+AC_CHECK_FUNCS(wait3)
+
+dnl See if the tm structure has the tm_gmtoff member...
+AC_MSG_CHECKING(for tm_gmtoff member in tm structure)
+AC_TRY_COMPILE([#include <time.h>],[struct tm t;
+ int o = t.tm_gmtoff;],
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_TM_GMTOFF),
+ AC_MSG_RESULT(no))
+
+dnl Flags for "ar" command...
+case $uname in
+ Darwin* | *BSD*)
+ ARFLAGS="-rcv"
+ ;;
+ *)
+ ARFLAGS="crvs"
+ ;;
+esac
+
+AC_SUBST(ARFLAGS)
+
+dnl Extra platform-specific libraries...
+case $uname in
+ Darwin*)
+ BACKLIBS="-framework IOKit"
+ COMMONLIBS="-framework CoreFoundation"
+ ;;
+ *)
+ BACKLIBS=""
+ COMMONLIBS=""
+ ;;
+esac
+
+AC_SUBST(BACKLIBS)
+AC_SUBST(COMMONLIBS)
+
+dnl
+dnl End of "$Id: cups-common.m4 4473 2004-12-16 19:42:22Z mike $".
+dnl
diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4
new file mode 100644
index 000000000..9ae6a1030
--- /dev/null
+++ b/config-scripts/cups-compiler.m4
@@ -0,0 +1,206 @@
+dnl
+dnl "$Id: cups-compiler.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl Common configuration stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+dnl Clear the debugging and non-shared library options unless the user asks
+dnl for them...
+
+OPTIM=""
+AC_SUBST(OPTIM)
+
+AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no],
+ [if test x$enable_debug = xyes; then
+ OPTIM="-g"
+ fi])
+
+AC_ARG_WITH(optim, [ --with-optim="flags" set optimization flags ])
+
+dnl Update compiler options...
+CXXLIBS=""
+AC_SUBST(CXXLIBS)
+
+if test -n "$GCC"; then
+ # Starting with GCC 3.0, you must link C++ programs against either
+ # libstdc++ (shared by default), or libsupc++ (always static). If
+ # you care about binary portability between Linux distributions,
+ # you need to either 1) build your own GCC with static C++ libraries
+ # or 2) link using gcc and libsupc++. We choose the latter since
+ # CUPS doesn't (currently) use any of the stdc++ library.
+ #
+ # Also, GCC 3.0.x still has problems compiling some code. You may
+ # or may not have success with it. USE 3.0.x WITH EXTREME CAUTION!
+ #
+ # Previous versions of GCC do not have the reliance on the stdc++
+ # or g++ libraries, so the extra supc++ library is not needed.
+
+ AC_MSG_CHECKING(if libsupc++ is required)
+
+ SUPC="`$CXX -print-file-name=libsupc++.a 2>/dev/null`"
+ case "$SUPC" in
+ libsupc++.a*)
+ # Library not found, so this is and older GCC...
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ # This is gcc 3.x, and it knows of libsupc++, so we need it
+ CXXLIBS="-lsupc++"
+ AC_MSG_RESULT(yes)
+ ;;
+ esac
+
+ CXX="$CC"
+
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ if test $uname = HP-UX; then
+ # GCC under HP-UX has bugs with -O2
+ OPTIM="-O1"
+ else
+ OPTIM="-O2"
+ fi
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+
+ if test $PICFLAG = 1 -a $uname != AIX; then
+ OPTIM="-fPIC $OPTIM"
+ fi
+
+ if test "x$with_optim" = x; then
+ OPTIM="-Wall $OPTIM"
+ fi
+else
+ case $uname in
+ AIX*)
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ OPTIM="-O2 -qmaxmem=6000"
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+ ;;
+ HP-UX*)
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ OPTIM="+O2"
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+
+ CFLAGS="-Ae $CFLAGS"
+
+ if test "x$with_optim" = x; then
+ OPTIM="+DAportable $OPTIM"
+ fi
+
+ if test $PICFLAG = 1; then
+ OPTIM="+z $OPTIM"
+ fi
+ ;;
+ IRIX)
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ OPTIM="-O2"
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+
+ if test $uversion -ge 62 -a "x$with_optim" = x; then
+ OPTIM="$OPTIM -n32 -mips3"
+ fi
+
+ if test "x$with_optim" = x; then
+ # Show most warnings, but suppress the
+ # ones about arguments not being used,
+ # string constants assigned to const
+ # char *'s, etc. We only set the warning
+ # options on IRIX 6.2 and higher because
+ # of limitations in the older SGI compiler
+ # tools.
+ if test $uversion -ge 62; then
+ OPTIM="-fullwarn -woff 1183,1209,1349,3201 $OPTIM"
+ fi
+ fi
+ ;;
+ SunOS*)
+ # Solaris
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ OPTIM="-xO4"
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+
+ if test "x$with_optim" = x; then
+ # Specify "generic" SPARC output and suppress
+ # all of Sun's questionable warning messages...
+ OPTIM="-w $OPTIM -xarch=generic"
+ fi
+
+ if test $PICFLAG = 1; then
+ OPTIM="-KPIC $OPTIM"
+ fi
+ ;;
+ UNIX_SVR*)
+ # UnixWare
+ if test -z "$OPTIM"; then
+ if test "x$with_optim" = x; then
+ OPTIM="-O"
+ else
+ OPTIM="$with_optim $OPTIM"
+ fi
+ fi
+
+ if test $PICFLAG = 1; then
+ OPTIM="-KPIC $OPTIM"
+ fi
+ ;;
+ *)
+ # Running some other operating system; inform the user they
+ # should contribute the necessary options to
+ # cups-support@cups.org...
+ echo "Building CUPS with default compiler optimizations; contact"
+ echo "cups-bugs@cups.org with uname and compiler options needed"
+ echo "for your platform, or set the CFLAGS and CXXFLAGS"
+ echo "environment variable before running configure."
+ ;;
+ esac
+fi
+
+if test $uname = HP-UX; then
+ # HP-UX 10.20 (at least) needs this definition to get the
+ # h_errno global...
+ OPTIM="$OPTIM -D_XOPEN_SOURCE_EXTENDED"
+
+ # HP-UX 11.00 (at least) needs this definition to get the
+ # u_short type used by the IP headers...
+ OPTIM="$OPTIM -D_INCLUDE_HPUX_SOURCE"
+fi
+
+dnl
+dnl End of "$Id: cups-compiler.m4 4358 2004-08-11 14:39:26Z mike $".
+dnl
diff --git a/config-scripts/cups-directories.m4 b/config-scripts/cups-directories.m4
new file mode 100644
index 000000000..6d40304a5
--- /dev/null
+++ b/config-scripts/cups-directories.m4
@@ -0,0 +1,242 @@
+dnl
+dnl "$Id: cups-directories.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl Directory stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_PREFIX_DEFAULT(/)
+
+AC_ARG_WITH(fontpath, [ --with-fontpath set font path for pstoraster],fontpath="$withval",fontpath="")
+AC_ARG_WITH(docdir, [ --with-docdir set path for documentation],docdir="$withval",docdir="")
+AC_ARG_WITH(logdir, [ --with-logdir set path for log files],logdir="$withval",logdir="")
+AC_ARG_WITH(rcdir, [ --with-rcdir set path for rc scripts],rcdir="$withval",rcdir="")
+
+dnl Fix "prefix" variable if it hasn't been specified...
+if test "$prefix" = "NONE"; then
+ prefix="/"
+fi
+
+dnl Fix "exec_prefix" variable if it hasn't been specified...
+if test "$exec_prefix" = "NONE"; then
+ if test "$prefix" = "/"; then
+ exec_prefix="/usr"
+ else
+ exec_prefix="$prefix"
+ fi
+fi
+
+dnl Fix "sharedstatedir" variable if it hasn't been specified...
+if test "$sharedstatedir" = "\${prefix}/com" -a "$prefix" = "/"; then
+ sharedstatedir="/usr/com"
+fi
+
+dnl Fix "datadir" variable if it hasn't been specified...
+if test "$datadir" = "\${prefix}/share"; then
+ if test "$prefix" = "/"; then
+ datadir="/usr/share"
+ else
+ datadir="$prefix/share"
+ fi
+fi
+
+dnl Fix "includedir" variable if it hasn't been specified...
+if test "$includedir" = "\${prefix}/include" -a "$prefix" = "/"; then
+ includedir="/usr/include"
+fi
+
+dnl Fix "localstatedir" variable if it hasn't been specified...
+if test "$localstatedir" = "\${prefix}/var"; then
+ if test "$prefix" = "/"; then
+ localstatedir="/var"
+ else
+ localstatedir="$prefix/var"
+ fi
+fi
+
+dnl Fix "sysconfdir" variable if it hasn't been specified...
+if test "$sysconfdir" = "\${prefix}/etc"; then
+ if test "$prefix" = "/"; then
+ sysconfdir="/etc"
+ else
+ sysconfdir="$prefix/etc"
+ fi
+fi
+
+dnl Fix "libdir" variable for IRIX 6.x...
+if test "$libdir" = "\${exec_prefix}/lib"; then
+ libdir="$exec_prefix/lib"
+fi
+
+if test "$uname" = "IRIX" -a $uversion -ge 62; then
+ libdir="$exec_prefix/lib32"
+fi
+
+dnl Fix "fontpath" variable...
+if test "x$fontpath" = "x"; then
+ fontpath="$datadir/cups/fonts"
+fi
+
+dnl Setup init.d locations...
+if test x$rcdir = x; then
+ case "$uname" in
+ FreeBSD* | OpenBSD*)
+ # FreeBSD and OpenBSD
+ INITDIR=""
+ INITDDIR=""
+ ;;
+
+ NetBSD*)
+ # NetBSD
+ INITDIR=""
+ INITDDIR="/etc/rc.d"
+ ;;
+
+ Darwin*)
+ # Darwin and MacOS X...
+ INITDIR=""
+ INITDDIR="/System/Library/StartupItems/PrintingServices"
+ ;;
+
+ Linux | GNU)
+ # Linux/HURD seems to choose an init.d directory at random...
+ if test -d /sbin/init.d; then
+ # SuSE
+ INITDIR="/sbin/init.d"
+ INITDDIR=".."
+ else
+ if test -d /etc/rc.d; then
+ # RedHat
+ INITDIR="/etc/rc.d"
+ INITDDIR="../init.d"
+ else
+ # Others
+ INITDIR="/etc"
+ INITDDIR="../init.d"
+ fi
+ fi
+ ;;
+
+ OSF1* | HP-UX*)
+ INITDIR="/sbin"
+ INITDDIR="../init.d"
+ ;;
+
+ AIX*)
+ INITDIR="/etc/rc.d"
+ INITDDIR=".."
+ ;;
+
+ *)
+ INITDIR="/etc"
+ INITDDIR="../init.d"
+ ;;
+
+ esac
+else
+ INITDIR=""
+ INITDDIR="$rcdir"
+fi
+
+AC_SUBST(INITDIR)
+AC_SUBST(INITDDIR)
+
+dnl Setup default locations...
+CUPS_SERVERROOT="$sysconfdir/cups"
+CUPS_REQUESTS="$localstatedir/spool/cups"
+
+AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$sysconfdir/cups")
+AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$localstatedir/spool/cups")
+
+if test x$logdir = x; then
+ CUPS_LOGDIR="$localstatedir/log/cups"
+ AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
+else
+ CUPS_LOGDIR="$logdir"
+ AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$logdir")
+fi
+
+dnl See what directory to put server executables...
+case "$uname" in
+ *BSD* | Darwin*)
+ # *BSD and Darwin (MacOS X)
+ INSTALL_SYSV=""
+ CUPS_SERVERBIN="$exec_prefix/libexec/cups"
+ AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$exec_prefix/libexec/cups")
+ ;;
+ *)
+ # All others
+ INSTALL_SYSV="install-sysv"
+ CUPS_SERVERBIN="$libdir/cups"
+ AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$libdir/cups")
+ ;;
+esac
+
+AC_SUBST(INSTALL_SYSV)
+AC_SUBST(CUPS_SERVERROOT)
+AC_SUBST(CUPS_SERVERBIN)
+AC_SUBST(CUPS_LOGDIR)
+AC_SUBST(CUPS_REQUESTS)
+
+dnl Set the CUPS_LOCALE directory...
+case "$uname" in
+ Linux | GNU | *BSD* | Darwin*)
+ CUPS_LOCALEDIR="$datadir/locale"
+ AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$datadir/locale")
+ ;;
+
+ OSF1* | AIX*)
+ CUPS_LOCALEDIR="$exec_prefix/lib/nls/msg"
+ AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/nls/msg")
+ ;;
+
+ *)
+ # This is the standard System V location...
+ CUPS_LOCALEDIR="$exec_prefix/lib/locale"
+ AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/locale")
+ ;;
+esac
+
+AC_SUBST(CUPS_LOCALEDIR)
+
+dnl Set the CUPS_DATADIR directory...
+CUPS_DATADIR="$datadir/cups"
+AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$datadir/cups")
+AC_SUBST(CUPS_DATADIR)
+
+dnl Set the CUPS_DOCROOT directory...
+if test x$docdir = x; then
+ CUPS_DOCROOT="$datadir/doc/cups"
+ docdir="$datadir/doc/cups"
+else
+ CUPS_DOCROOT="$docdir"
+fi
+
+AC_DEFINE_UNQUOTED(CUPS_DOCROOT, "$docdir")
+AC_SUBST(CUPS_DOCROOT)
+
+dnl Set the CUPS_FONTPATH directory...
+CUPS_FONTPATH="$fontpath"
+AC_SUBST(CUPS_FONTPATH)
+AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$fontpath")
+
+dnl
+dnl End of "$Id: cups-directories.m4 4358 2004-08-11 14:39:26Z mike $".
+dnl
diff --git a/config-scripts/cups-image.m4 b/config-scripts/cups-image.m4
new file mode 100644
index 000000000..e2b1e8b6b
--- /dev/null
+++ b/config-scripts/cups-image.m4
@@ -0,0 +1,82 @@
+dnl
+dnl "$Id: cups-image.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl Image library stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+dnl Save the current libraries since we don't want the image libraries
+dnl included with every program...
+SAVELIBS="$LIBS"
+
+dnl Check for image libraries...
+LIBJPEG=""
+LIBPNG=""
+LIBTIFF=""
+LIBZ=""
+
+AC_SUBST(LIBJPEG)
+AC_SUBST(LIBPNG)
+AC_SUBST(LIBTIFF)
+AC_SUBST(LIBZ)
+
+AC_CHECK_HEADER(jpeglib.h,
+ AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
+ AC_DEFINE(HAVE_LIBJPEG)
+ LIBJPEG="-ljpeg"
+ LIBS="$LIBS -ljpeg"))
+
+AC_CHECK_HEADER(zlib.h,
+ AC_CHECK_LIB(z, gzgets,
+ AC_DEFINE(HAVE_LIBZ)
+ LIBZ="-lz"
+ LIBS="$LIBS -lz"))
+
+dnl PNG library uses math library functions...
+AC_CHECK_LIB(m, pow)
+
+AC_CHECK_HEADER(png.h,
+ AC_CHECK_LIB(png, png_set_tRNS_to_alpha,
+ AC_DEFINE(HAVE_LIBPNG)
+ LIBPNG="-lpng -lm"))
+
+AC_CHECK_HEADER(tiff.h,
+ AC_CHECK_LIB(tiff, TIFFReadScanline,
+ AC_DEFINE(HAVE_LIBTIFF)
+ LIBTIFF="-ltiff"))
+
+dnl Restore original LIBS settings...
+LIBS="$SAVELIBS"
+
+EXPORT_LIBJPEG="$LIBJPEG"
+EXPORT_LIBPNG="$LIBPNG"
+EXPORT_LIBTIFF="$LIBTIFF"
+EXPORT_LIBZ="$LIBZ"
+
+AC_SUBST(EXPORT_LIBJPEG)
+AC_SUBST(EXPORT_LIBPNG)
+AC_SUBST(EXPORT_LIBTIFF)
+AC_SUBST(EXPORT_LIBZ)
+
+AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H))
+
+dnl
+dnl End of "$Id: cups-image.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-libtool.m4 b/config-scripts/cups-libtool.m4
new file mode 100644
index 000000000..6ae1e6dbd
--- /dev/null
+++ b/config-scripts/cups-libtool.m4
@@ -0,0 +1,49 @@
+dnl
+dnl "$Id: cups-libtool.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl Libtool stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_ARG_ENABLE(libtool_unsupported, [ --enable-libtool-unsupported=LIBTOOL_PATH
+ turn on building with libtool (UNSUPPORTED!), default=no],
+ [if test x$enable_libtool_unsupported != xno; then
+ LIBTOOL="$enable_libtool_unsupported"
+ enable_shared=no
+ echo "WARNING: libtool is not supported or endorsed by Easy Software Products."
+ echo " WE DO NOT PROVIDE TECHNICAL SUPPORT FOR LIBTOOL PROBLEMS."
+ echo " (even if you have a support contract)"
+ else
+ LIBTOOL=""
+ fi])
+
+AC_SUBST(LIBTOOL)
+
+if test x$LIBTOOL != x; then
+ LIBCUPS="libcups.la"
+ LIBCUPSIMAGE="libcupsimage.la"
+ LINKCUPS="../cups/\$(LIBCUPS)"
+ LINKCUPSIMAGE="../filter/\$(LIBCUPSIMAGE)"
+ DSO="\$(CC)"
+fi
+
+dnl
+dnl End of "$Id: cups-libtool.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-manpages.m4 b/config-scripts/cups-manpages.m4
new file mode 100644
index 000000000..df5248413
--- /dev/null
+++ b/config-scripts/cups-manpages.m4
@@ -0,0 +1,104 @@
+dnl
+dnl "$Id: cups-manpages.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl Manpage stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+dnl Fix "mandir" variable...
+if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then
+ case "$uname" in
+ Darwin* | Linux | GNU | *BSD* | AIX*)
+ # Darwin, MacOS X, Linux, GNU HURD, *BSD, and AIX
+ mandir="/usr/share/man"
+ AMANDIR="/usr/share/man"
+ PMANDIR="/usr/share/man"
+ ;;
+ IRIX)
+ # SGI IRIX
+ mandir="/usr/share/catman/u_man"
+ AMANDIR="/usr/share/catman/a_man"
+ PMANDIR="/usr/share/catman/p_man"
+ ;;
+ *)
+ # All others
+ mandir="/usr/man"
+ AMANDIR="/usr/man"
+ PMANDIR="/usr/man"
+ ;;
+ esac
+else
+ AMANDIR="$mandir"
+ PMANDIR="$mandir"
+fi
+
+AC_SUBST(AMANDIR)
+AC_SUBST(PMANDIR)
+
+dnl Setup manpage extensions...
+case "$uname" in
+ *BSD* | Darwin*)
+ # *BSD
+ CAT1EXT=0
+ CAT3EXT=0
+ CAT5EXT=0
+ CAT8EXT=0
+ MAN8EXT=8
+ MAN8DIR=8
+ ;;
+ IRIX*)
+ # SGI IRIX
+ CAT1EXT=z
+ CAT3EXT=z
+ CAT5EXT=z
+ CAT8EXT=z
+ MAN8EXT=1m
+ MAN8DIR=1
+ ;;
+ SunOS* | HP-UX*)
+ # Solaris and HP-UX
+ CAT1EXT=1
+ CAT3EXT=3
+ CAT5EXT=5
+ CAT8EXT=1m
+ MAN8EXT=1m
+ MAN8DIR=1m
+ ;;
+ *)
+ # All others
+ CAT1EXT=1
+ CAT3EXT=3
+ CAT5EXT=5
+ CAT8EXT=8
+ MAN8EXT=8
+ MAN8DIR=8
+ ;;
+esac
+
+AC_SUBST(CAT1EXT)
+AC_SUBST(CAT3EXT)
+AC_SUBST(CAT5EXT)
+AC_SUBST(CAT8EXT)
+AC_SUBST(MAN8EXT)
+AC_SUBST(MAN8DIR)
+
+dnl
+dnl End of "$Id: cups-manpages.m4 4358 2004-08-11 14:39:26Z mike $".
+dnl
diff --git a/config-scripts/cups-network.m4 b/config-scripts/cups-network.m4
new file mode 100644
index 000000000..ddc22357c
--- /dev/null
+++ b/config-scripts/cups-network.m4
@@ -0,0 +1,59 @@
+dnl
+dnl "$Id: cups-network.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl Networking stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+NETLIBS=""
+
+if test "$uname" != "IRIX"; then
+ AC_CHECK_LIB(socket,socket,NETLIBS="-lsocket")
+ AC_CHECK_LIB(nsl,gethostbyaddr,NETLIBS="$NETLIBS -lnsl")
+fi
+
+AC_CHECK_FUNCS(rresvport getifaddrs hstrerror)
+
+AC_CHECK_MEMBER(struct sockaddr.sa_len,,,[#include <sys/socket.h>])
+AC_CHECK_HEADER(sys/sockio.h,AC_DEFINE(HAVE_SYS_SOCKIO_H))
+
+AC_SUBST(NETLIBS)
+
+if test "$uname" = "SunOS"; then
+ case "$uversion" in
+ 55* | 56*)
+ maxfiles=1024
+ ;;
+ *)
+ maxfiles=4096
+ ;;
+ esac
+else
+ maxfiles=4096
+fi
+
+AC_ARG_WITH(maxfiles, [ --with-maxfiles=N set maximum number of file descriptors for scheduler ],
+ maxfiles=$withval)
+
+AC_DEFINE_UNQUOTED(CUPS_MAX_FDS, $maxfiles)
+
+dnl
+dnl End of "$Id: cups-network.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-openslp.m4 b/config-scripts/cups-openslp.m4
new file mode 100644
index 000000000..f9ff6704c
--- /dev/null
+++ b/config-scripts/cups-openslp.m4
@@ -0,0 +1,48 @@
+dnl
+dnl "$Id: cups-openslp.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl OpenSLP configuration stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_ARG_ENABLE(slp, [ --enable-slp turn on SLP support, default=yes])
+AC_ARG_WITH(openslp-libs, [ --with-openslp-libs set directory for OpenSLP library],
+ LDFLAGS="-L$withval $LDFLAGS"
+ DSOFLAGS="-L$withval $DSOFLAGS",)
+AC_ARG_WITH(openslp-includes, [ --with-openslp-includes set directory for OpenSLP includes],
+ CFLAGS="-I$withval $CFLAGS"
+ CXXFLAGS="-I$withval $CXXFLAGS"
+ CPPFLAGS="-I$withval $CPPFLAGS",)
+
+LIBSLP=""
+
+if test x$enable_slp != xno; then
+ AC_CHECK_HEADER(slp.h,
+ AC_CHECK_LIB(slp, SLPOpen,
+ AC_DEFINE(HAVE_LIBSLP)
+ LIBSLP="-lslp"))
+fi
+
+AC_SUBST(LIBSLP)
+
+
+dnl
+dnl End of "$Id: cups-openslp.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-openssl.m4 b/config-scripts/cups-openssl.m4
new file mode 100644
index 000000000..85b012bb1
--- /dev/null
+++ b/config-scripts/cups-openssl.m4
@@ -0,0 +1,112 @@
+dnl
+dnl "$Id: cups-openssl.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl OpenSSL/GNUTLS stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_ARG_ENABLE(ssl, [ --enable-ssl turn on SSL/TLS support, default=yes])
+AC_ARG_ENABLE(openssl, [ --enable-openssl use OpenSSL for SSL/TLS support, default=yes])
+AC_ARG_ENABLE(gnutls, [ --enable-gnutls use GNU TLS for SSL/TLS support, default=yes])
+AC_ARG_ENABLE(cdsassl, [ --enable-cdsassl use CDSA for SSL/TLS support, default=yes])
+AC_ARG_WITH(openssl-libs, [ --with-openssl-libs set directory for OpenSSL library],
+ LDFLAGS="-L$withval $LDFLAGS"
+ DSOFLAGS="-L$withval $DSOFLAGS",)
+AC_ARG_WITH(openssl-includes, [ --with-openssl-includes set directory for OpenSSL includes],
+ CFLAGS="-I$withval $CFLAGS"
+ CXXFLAGS="-I$withval $CXXFLAGS"
+ CPPFLAGS="-I$withval $CPPFLAGS",)
+
+SSLFLAGS=""
+SSLLIBS=""
+
+if test x$enable_ssl != xno; then
+ dnl Check for the OpenSSL library first, which has precedence over
+ dnl CDSA and GNUTLS...
+ if test "x${SSLLIBS}" = "x" -a "x${enable_openssl}" != "xno"; then
+ AC_CHECK_HEADER(openssl/ssl.h,
+ dnl Save the current libraries so the crypto stuff isn't always
+ dnl included...
+ SAVELIBS="$LIBS"
+
+ dnl Some ELF systems can't resolve all the symbols in libcrypto
+ dnl if libcrypto was linked against RSAREF, and fail to link the
+ dnl test program correctly, even though a correct installation
+ dnl of OpenSSL exists. So we test the linking three times in
+ dnl case the RSAREF libraries are needed.
+
+ for libcrypto in \
+ "-lcrypto" \
+ "-lcrypto -lrsaref" \
+ "-lcrypto -lRSAglue -lrsaref"
+ do
+ AC_CHECK_LIB(ssl,SSL_new,
+ [SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
+ SSLLIBS="-lssl $libcrypto"
+ AC_DEFINE(HAVE_SSL)
+ AC_DEFINE(HAVE_LIBSSL)],,
+ $libcrypto)
+
+ if test "x${SSLLIBS}" != "x"; then
+ break
+ fi
+ done
+
+ LIBS="$SAVELIBS")
+ fi
+
+ dnl If OpenSSL wasn't found, look for CDSA...
+ if test "x${SSLLIBS}" = "x" -a "x${enable_cdsassl}" != "xno"; then
+ if test $uname = Darwin; then
+ AC_CHECK_HEADER(Security/SecureTransport.h,
+ [SSLLIBS="-framework CoreFoundation -framework Security"
+ AC_DEFINE(HAVE_SSL)
+ AC_DEFINE(HAVE_CDSASSL)])
+ fi
+ fi
+
+ dnl Then look for GNU TLS...
+ if test "x${SSLLIBS}" = "x" -a "x${enable_gnutls}" != "xno"; then
+ AC_CHECK_HEADER(gnutls/gnutls.h,
+ dnl Save the current libraries so the crypto stuff isn't always
+ dnl included...
+ SAVELIBS="$LIBS"
+
+ TEST_GNUTLS_LIBS=`libgnutls-config --libs`
+ AC_CHECK_LIB(gnutls, gnutls_init,
+ [SSLLIBS=$TEST_GNUTLS_LIBS
+ AC_DEFINE(HAVE_SSL)
+ AC_DEFINE(HAVE_GNUTLS)],,
+ $TEST_GNUTLS_LIBS)
+
+ LIBS="$SAVELIBS")
+ fi
+fi
+
+AC_SUBST(SSLFLAGS)
+AC_SUBST(SSLLIBS)
+
+EXPORT_SSLLIBS="$SSLLIBS"
+AC_SUBST(EXPORT_SSLLIBS)
+
+
+dnl
+dnl End of "$Id: cups-openssl.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-opsys.m4 b/config-scripts/cups-opsys.m4
new file mode 100644
index 000000000..b304de9cd
--- /dev/null
+++ b/config-scripts/cups-opsys.m4
@@ -0,0 +1,99 @@
+dnl
+dnl "$Id: cups-opsys.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl Operating system stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+dnl Get the operating system and version number...
+uname=`uname`
+uversion=`uname -r | sed -e '1,$s/[[^0-9]]//g'`
+case "$uname" in
+ GNU* | GNU/*)
+ uname="GNU"
+ ;;
+ IRIX*)
+ uname="IRIX"
+ ;;
+ Linux*)
+ uname="Linux"
+ ;;
+esac
+
+dnl Determine the correct username and group for this OS...
+AC_ARG_WITH(cups-user, [ --with-cups-user set default user for CUPS],
+ CUPS_USER="$withval",
+ AC_MSG_CHECKING(for default print user)
+ if test -f /etc/passwd; then
+ CUPS_USER=""
+ for user in lp lpd guest daemon nobody; do
+ if test "`grep \^${user}: /etc/passwd`" != ""; then
+ CUPS_USER="$user"
+ AC_MSG_RESULT($user)
+ break;
+ fi
+ done
+
+ if test x$CUPS_USER = x; then
+ CUPS_USER="${USER:=nobody}"
+ AC_MSG_RESULT(not found, using "$CUPS_USER")
+ fi
+ else
+ CUPS_USER="${USER:=nobody}"
+ AC_MSG_RESULT(no password file, using "$CUPS_USER")
+ fi)
+
+AC_ARG_WITH(cups-group, [ --with-cups-group set default group for CUPS],
+ CUPS_GROUP="$withval",
+ AC_MSG_CHECKING(for default print group)
+ if test -f /etc/group; then
+ if test x$uname = xDarwin; then
+ GROUP_LIST="lp admin"
+ else
+ GROUP_LIST="sys system root"
+ fi
+
+ CUPS_GROUP=""
+ for group in $GROUP_LIST; do
+ if test "`grep \^${group}: /etc/group`" != ""; then
+ CUPS_GROUP="$group"
+ AC_MSG_RESULT($group)
+ break;
+ fi
+ done
+
+ if test x$CUPS_GROUP = x; then
+ CUPS_GROUP="${GROUP:=nobody}"
+ AC_MSG_RESULT(not found, using "$CUPS_GROUP")
+ fi
+ else
+ CUPS_GROUP="${GROUP:=nobody}"
+ AC_MSG_RESULT(no group file, using "$CUPS_GROUP")
+ fi)
+
+AC_SUBST(CUPS_USER)
+AC_SUBST(CUPS_GROUP)
+
+AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USER, "$CUPS_USER")
+AC_DEFINE_UNQUOTED(CUPS_DEFAULT_GROUP, "$CUPS_GROUP")
+
+dnl
+dnl "$Id: cups-opsys.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
diff --git a/config-scripts/cups-pam.m4 b/config-scripts/cups-pam.m4
new file mode 100644
index 000000000..2b2738587
--- /dev/null
+++ b/config-scripts/cups-pam.m4
@@ -0,0 +1,94 @@
+dnl
+dnl "$Id: cups-pam.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl PAM stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_ARG_ENABLE(pam, [ --enable-pam turn on PAM support, default=yes])
+
+dnl Don't use PAM with AIX...
+if test $uname = AIX; then
+ enable_pam=no
+fi
+
+PAMDIR=""
+PAMFILE=""
+PAMLIBS=""
+PAMMOD="pam_unknown.so"
+
+if test x$enable_pam != xno; then
+ SAVELIBS="$LIBS"
+
+ AC_CHECK_LIB(dl,dlopen)
+ AC_CHECK_LIB(pam,pam_start)
+ AC_CHECK_HEADER(pam/pam_appl.h,AC_DEFINE(HAVE_PAM_PAM_APPL_H))
+
+ if test x$ac_cv_lib_pam_pam_start != xno; then
+ # Set the necessary libraries for PAM...
+ if test x$ac_cv_lib_dl_dlopen != xno; then
+ PAMLIBS="-lpam -ldl"
+ else
+ PAMLIBS="-lpam"
+ fi
+
+ # Find the PAM configuration directory, if any...
+ for dir in /private/etc/pam.d /etc/pam.d; do
+ if test -d $dir; then
+ PAMDIR=$dir
+ break;
+ fi
+ done
+ fi
+
+ LIBS="$SAVELIBS"
+
+ case "$uname" in
+ Darwin*)
+ # Darwin, MacOS X
+ PAMFILE="pam.darwin"
+ ;;
+ IRIX)
+ # SGI IRIX
+ PAMFILE="pam.irix"
+ ;;
+ *)
+ # All others; this test might need to be updated
+ # as Linux distributors move things around...
+ for mod in pam_unix2.so pam_unix.so pam_pwdb.so; do
+ if test -f /lib/security/$mod; then
+ PAMMOD="$mod"
+ break;
+ fi
+ done
+
+ PAMFILE="pam.std"
+ ;;
+ esac
+fi
+
+AC_SUBST(PAMDIR)
+AC_SUBST(PAMFILE)
+AC_SUBST(PAMLIBS)
+AC_SUBST(PAMMOD)
+
+dnl
+dnl End of "$Id: cups-pam.m4 4358 2004-08-11 14:39:26Z mike $".
+dnl
diff --git a/config-scripts/cups-scripting.m4 b/config-scripts/cups-scripting.m4
new file mode 100644
index 000000000..19fbbf8d3
--- /dev/null
+++ b/config-scripts/cups-scripting.m4
@@ -0,0 +1,91 @@
+dnl
+dnl "$Id: cups-scripting.m4 4213 2004-06-29 03:44:53Z mike $"
+dnl
+dnl Scripting configuration stuff for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+dnl Do we have Java?
+AC_ARG_WITH(java, [ --with-java set Java interpreter for web interfaces ],
+ CUPS_JAVA="$withval",
+ CUPS_JAVA="")
+
+if test "x$CUPS_JAVA" = x; then
+ AC_PATH_PROG(JAVA,java)
+ CUPS_JAVA="$JAVA"
+fi
+
+AC_DEFINE_UNQUOTED(CUPS_JAVA, "$CUPS_JAVA")
+
+if test "x$CUPS_JAVA" != x; then
+ AC_DEFINE(HAVE_JAVA)
+fi
+
+dnl Do we have Perl?
+AC_ARG_WITH(perl, [ --with-perl set Perl interpreter for web interfaces ],
+ CUPS_PERL="$withval",
+ CUPS_PERL="")
+
+if test "x$CUPS_PERL" = x; then
+ AC_PATH_PROG(PERL,perl)
+ CUPS_PERL="$PERL"
+fi
+
+AC_DEFINE_UNQUOTED(CUPS_PERL, "$CUPS_PERL")
+
+if test "x$CUPS_PERL" != x; then
+ AC_DEFINE(HAVE_PERL)
+fi
+
+dnl Do we have PHP?
+AC_ARG_WITH(php, [ --with-php set PHP interpreter for web interfaces ],
+ CUPS_PHP="$withval",
+ CUPS_PHP="")
+
+if test "x$CUPS_PHP" = x; then
+ AC_PATH_PROG(PHP,php)
+ CUPS_PHP="$PHP"
+fi
+
+AC_DEFINE_UNQUOTED(CUPS_PHP, "$CUPS_PHP")
+
+if test "x$CUPS_PHP" != x; then
+ AC_DEFINE(HAVE_PHP)
+fi
+
+dnl Do we have Python?
+AC_ARG_WITH(python, [ --with-python set Python interpreter for web interfaces ],
+ CUPS_PYTHON="$withval",
+ CUPS_PYTHON="")
+
+if test "x$CUPS_PYTHON" = x; then
+ AC_PATH_PROG(PYTHON,python)
+ CUPS_PYTHON="$PYTHON"
+fi
+
+AC_DEFINE_UNQUOTED(CUPS_PYTHON, "$CUPS_PYTHON")
+
+if test "x$CUPS_PYTHON" != x; then
+ AC_DEFINE(HAVE_PYTHON)
+fi
+
+dnl
+dnl End of "$Id: cups-scripting.m4 4213 2004-06-29 03:44:53Z mike $".
+dnl
diff --git a/config-scripts/cups-sharedlibs.m4 b/config-scripts/cups-sharedlibs.m4
new file mode 100644
index 000000000..d0b2cf379
--- /dev/null
+++ b/config-scripts/cups-sharedlibs.m4
@@ -0,0 +1,156 @@
+dnl
+dnl "$Id: cups-sharedlibs.m4 4358 2004-08-11 14:39:26Z mike $"
+dnl
+dnl Shared library support for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+PICFLAG=1
+DSOFLAGS="${DSOFLAGS:=}"
+
+AC_ARG_ENABLE(shared, [ --enable-shared turn on shared libraries, default=yes])
+
+if test x$enable_shared != xno; then
+ case "$uname" in
+ SunOS* | UNIX_S*)
+ LIBCUPS="libcups.so.2"
+ LIBCUPSIMAGE="libcupsimage.so.2"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS -Wl,-h,\$@ -G \$(OPTIM)"
+ ;;
+ HP-UX*)
+ LIBCUPS="libcups.sl.2"
+ LIBCUPSIMAGE="libcupsimage.sl.2"
+ DSO="ld"
+ DSOFLAGS="$DSOFLAGS -b -z +h \$@"
+ ;;
+ IRIX)
+ LIBCUPS="libcups.so.2"
+ LIBCUPSIMAGE="libcupsimage.so.2"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS -Wl,-rpath,\$(libdir),-set_version,sgi2.5,-soname,\$@ -shared \$(OPTIM)"
+ ;;
+ OSF1* | Linux | GNU | *BSD*)
+ LIBCUPS="libcups.so.2"
+ LIBCUPSIMAGE="libcupsimage.so.2"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
+ ;;
+ Darwin*)
+ LIBCUPS="libcups.2.dylib"
+ LIBCUPSIMAGE="libcupsimage.2.dylib"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS \$(RC_CFLAGS) -dynamiclib -lc"
+ ;;
+ AIX*)
+ LIBCUPS="libcups_s.a"
+ LIBCUPSIMAGE="libcupsimage_s.a"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS -Wl,-bexpall,-bM:SRE,-bnoentry,-blibpath:\$(libdir)"
+ ;;
+ *)
+ echo "Warning: shared libraries may not be supported. Trying -shared"
+ echo " option with compiler."
+ LIBCUPS="libcups.so.2"
+ LIBCUPSIMAGE="libcupsimage.so.2"
+ DSO="\$(CC)"
+ DSOFLAGS="$DSOFLAGS -Wl,-soname,\$@ -shared \$(OPTIM)"
+ ;;
+ esac
+else
+ PICFLAG=0
+ LIBCUPS="libcups.a"
+ LIBCUPSIMAGE="libcupsimage.a"
+ DSO=":"
+fi
+
+AC_SUBST(DSO)
+AC_SUBST(DSOFLAGS)
+AC_SUBST(LIBCUPS)
+AC_SUBST(LIBCUPSIMAGE)
+
+if test x$enable_shared = xno; then
+ LINKCUPS="../cups/libcups.a \$(SSLLIBS)"
+ LINKCUPSIMAGE="../filter/libcupsimage.a"
+else
+ if test $uname = AIX; then
+ LINKCUPS="-lcups_s"
+ LINKCUPSIMAGE="-lcupsimage_s"
+ else
+ LINKCUPS="-lcups"
+ LINKCUPSIMAGE="-lcupsimage"
+ fi
+fi
+
+AC_SUBST(LINKCUPS)
+AC_SUBST(LINKCUPSIMAGE)
+
+dnl Update libraries for DSOs...
+EXPORT_LDFLAGS=""
+
+if test "$DSO" != ":"; then
+ # When using DSOs the image libraries are linked to libcupsimage.so
+ # rather than to the executables. This makes things smaller if you
+ # are using any static libraries, and it also allows us to distribute
+ # a single DSO rather than a bunch...
+ DSOLIBS="\$(LIBPNG) \$(LIBTIFF) \$(LIBJPEG) \$(LIBZ)"
+ IMGLIBS=""
+
+ # The *BSD, HP-UX, and Solaris run-time linkers need help when
+ # deciding where to find a DSO. Add linker options to tell them
+ # where to find the DSO (usually in /usr/lib... duh!)
+ case $uname in
+ HP-UX*)
+ # HP-UX
+ DSOFLAGS="+s +b $libdir $DSOFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,+s,+b,$libdir"
+ EXPORT_LDFLAGS="-Wl,+s,+b,$libdir"
+ ;;
+ SunOS*)
+ # Solaris
+ DSOFLAGS="-R$libdir $DSOFLAGS"
+ LDFLAGS="$LDFLAGS -R$libdir"
+ EXPORT_LDFLAGS="-R$libdir"
+ ;;
+ *BSD*)
+ # *BSD
+ DSOFLAGS="-Wl,-R$libdir $DSOFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,-R$libdir"
+ EXPORT_LDFLAGS="-Wl,-R$libdir"
+ ;;
+ Linux | GNU)
+ # Linux and HURD
+ DSOFLAGS="-Wl,-rpath,$libdir $DSOFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,-rpath,$libdir"
+ EXPORT_LDFLAGS="-Wl,-rpath,$libdir"
+ ;;
+ esac
+else
+ DSOLIBS=""
+ IMGLIBS="\$(LIBPNG) \$(LIBTIFF) \$(LIBJPEG) \$(LIBZ)"
+fi
+
+AC_SUBST(DSOLIBS)
+AC_SUBST(IMGLIBS)
+AC_SUBST(EXPORT_LDFLAGS)
+
+dnl
+dnl End of "$Id: cups-sharedlibs.m4 4358 2004-08-11 14:39:26Z mike $".
+dnl
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 000000000..70bff8eb9
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,305 @@
+/*
+ * "$Id$"
+ *
+ * Configuration file for the Common UNIX Printing System (CUPS).
+ *
+ * @configure_input@
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifndef _CUPS_CONFIG_H_
+#define _CUPS_CONFIG_H_
+
+/*
+ * Version of software...
+ */
+
+#define CUPS_SVERSION "CUPS v1.1.21"
+#define CUPS_MINIMAL "CUPS/1.1.21"
+
+
+/*
+ * Default user and group...
+ */
+
+#define CUPS_DEFAULT_USER "lp"
+#define CUPS_DEFAULT_GROUP "sys"
+
+
+/*
+ * Maximum number of file descriptors to support.
+ */
+
+#define CUPS_MAX_FDS 4096
+
+
+/*
+ * Where are files stored?
+ */
+
+#define CUPS_LOCALEDIR "/usr/share/locale"
+#define CUPS_SERVERROOT "/etc/cups"
+#define CUPS_SERVERBIN "/usr/lib/cups"
+#define CUPS_DOCROOT "/usr/share/doc/cups"
+#define CUPS_REQUESTS "/var/spool/cups"
+#define CUPS_LOGDIR "/var/logs/cups"
+#define CUPS_DATADIR "/usr/share/cups"
+#define CUPS_FONTPATH "/usr/share/cups/fonts"
+
+
+/*
+ * What is the format string for strftime?
+ */
+
+#define CUPS_STRFTIME_FORMAT NULL
+
+
+/*
+ * Do we have various image libraries?
+ */
+
+#undef HAVE_LIBPNG
+#undef HAVE_LIBZ
+#undef HAVE_LIBJPEG
+#undef HAVE_LIBTIFF
+
+
+/*
+ * Does this machine store words in big-endian (MSB-first) order?
+ */
+
+#undef WORDS_BIGENDIAN
+
+
+/*
+ * Which directory functions and headers do we use?
+ */
+
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_NDIR_H
+
+
+/*
+ * Do we have PAM stuff?
+ */
+
+#ifndef HAVE_LIBPAM
+#define HAVE_LIBPAM 0
+#endif /* !HAVE_LIBPAM */
+
+#undef HAVE_PAM_PAM_APPL_H
+
+
+/*
+ * Do we have <shadow.h>?
+ */
+
+#undef HAVE_SHADOW_H
+
+
+/*
+ * Do we have <crypt.h>?
+ */
+
+#undef HAVE_CRYPT_H
+
+
+/*
+ * Use <string.h>, <strings.h>, and/or <bstring.h>?
+ */
+
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+#undef HAVE_BSTRING_H
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#undef HAVE_STRDUP
+#undef HAVE_STRCASECMP
+#undef HAVE_STRNCASECMP
+#undef HAVE_STRLCAT
+#undef HAVE_STRLCPY
+
+
+/*
+ * Do we have the geteuid() function?
+ */
+
+#undef HAVE_GETEUID
+
+
+/*
+ * Do we have the vsyslog() function?
+ */
+
+#undef HAVE_VSYSLOG
+
+
+/*
+ * Do we have the (v)snprintf() functions?
+ */
+
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+
+
+/*
+ * What signal functions to use?
+ */
+
+#undef HAVE_SIGSET
+#undef HAVE_SIGACTION
+
+
+/*
+ * What wait functions to use?
+ */
+
+#undef HAVE_WAITPID
+#undef HAVE_WAIT3
+
+
+/*
+ * Do we have the mallinfo function and malloc.h?
+ */
+
+#undef HAVE_MALLINFO
+#undef HAVE_MALLOC_H
+
+
+/*
+ * Do we have the langinfo.h header file?
+ */
+
+#undef HAVE_LANGINFO_H
+
+
+/*
+ * Which encryption libraries do we have?
+ */
+
+#undef HAVE_CDSASSL
+#undef HAVE_GNUTLS
+#undef HAVE_LIBSSL
+#undef HAVE_SSL
+
+
+/*
+ * Do we have the OpenSLP library?
+ */
+
+#undef HAVE_LIBSLP
+
+
+/*
+ * Do we have libpaper?
+ */
+
+#undef HAVE_LIBPAPER
+
+
+/*
+ * Do we have <sys/ioctl.h>?
+ */
+
+#undef HAVE_SYS_IOCTL_H
+
+
+/*
+ * Do we have mkstemp() and/or mkstemps()?
+ */
+
+#undef HAVE_MKSTEMP
+#undef HAVE_MKSTEMPS
+
+
+/*
+ * Does the "tm" structure contain the "tm_gmtoff" member?
+ */
+
+#undef HAVE_TM_GMTOFF
+
+
+/*
+ * Do we have rresvport()?
+ */
+
+#undef HAVE_RRESVPORT
+
+
+/*
+ * Do we have getifaddrs()?
+ */
+
+#undef HAVE_GETIFADDRS
+
+
+/*
+ * Do we have hstrerror()?
+ */
+
+#undef HAVE_HSTRERROR
+
+
+/*
+ * Do we have the <sys/sockio.h> header file?
+ */
+
+#undef HAVE_SYS_SOCKIO_H
+
+
+/*
+ * Does the sockaddr structure contain an sa_len parameter?
+ */
+
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+
+/*
+ * Do we have the AIX usersec.h header file?
+ */
+
+#undef HAVE_USERSEC_H
+
+
+/*
+ * Various scripting languages...
+ */
+
+#undef HAVE_JAVA
+#define CUPS_JAVA "/usr/bin/java"
+#undef HAVE_PERL
+#define CUPS_PERL "/usr/bin/perl"
+#undef HAVE_PHP
+#define CUPS_PHP "/usr/bin/php"
+#undef HAVE_PYTHON
+#define CUPS_PYTHON "/usr/bin/python"
+
+
+#endif /* !_CUPS_CONFIG_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/configure.in b/configure.in
new file mode 100644
index 000000000..fdd119824
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,50 @@
+dnl
+dnl "$Id$"
+dnl
+dnl Configuration script for the Common UNIX Printing System (CUPS).
+dnl
+dnl Copyright 1997-2004 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Easy Software Products and are protected by Federal
+dnl copyright law. Distribution and use rights are outlined in the file
+dnl "LICENSE.txt" which should have been included with this file. If this
+dnl file is missing or damaged please contact Easy Software Products
+dnl at:
+dnl
+dnl Attn: CUPS Licensing Information
+dnl Easy Software Products
+dnl 44141 Airport View Drive, Suite 204
+dnl Hollywood, Maryland 20636-3142 USA
+dnl
+dnl Voice: (301) 373-9600
+dnl EMail: cups-info@cups.org
+dnl WWW: http://www.cups.org
+dnl
+
+AC_INIT(cups/cups.h)
+
+sinclude(config-scripts/cups-opsys.m4)
+sinclude(config-scripts/cups-common.m4)
+sinclude(config-scripts/cups-directories.m4)
+sinclude(config-scripts/cups-manpages.m4)
+
+sinclude(config-scripts/cups-sharedlibs.m4)
+sinclude(config-scripts/cups-libtool.m4)
+sinclude(config-scripts/cups-compiler.m4)
+
+sinclude(config-scripts/cups-image.m4)
+sinclude(config-scripts/cups-network.m4)
+sinclude(config-scripts/cups-openslp.m4)
+sinclude(config-scripts/cups-openssl.m4)
+sinclude(config-scripts/cups-pam.m4)
+
+sinclude(config-scripts/cups-scripting.m4)
+
+AC_OUTPUT(Makedefs cups.list cups.sh cups-config conf/cupsd.conf conf/pam.std)
+
+chmod +x cups-config
+
+dnl
+dnl End of "$Id$".
+dnl
diff --git a/cups-config.in b/cups-config.in
new file mode 100755
index 000000000..ee4c0c2d0
--- /dev/null
+++ b/cups-config.in
@@ -0,0 +1,134 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# CUPS configuration utility.
+#
+# Copyright 2001-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+VERSION="@CUPS_VERSION@"
+APIVERSION="1.1"
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+includedir=@includedir@
+libdir=@libdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+cups_datadir=@CUPS_DATADIR@
+cups_serverbin=@CUPS_SERVERBIN@
+cups_serverroot=@CUPS_SERVERROOT@
+
+# flags for C++ compiler:
+CFLAGS=""
+LDFLAGS="@EXPORT_LDFLAGS@"
+LIBS="@EXPORT_SSLLIBS@ @NETLIBS@ @COMMONLIBS@"
+IMGLIBS="@EXPORT_LIBTIFF@ @EXPORT_LIBJPEG@ @EXPORT_LIBPNG@ @EXPORT_LIBZ@"
+
+if test $includedir != /usr/include; then
+ CFLAGS="$CFLAGS -I$includedir"
+fi
+
+if test $libdir != /usr/lib -a $libdir != /usr/lib32; then
+ LDFLAGS="$LDFLAGS -L$libdir"
+fi
+
+usage ()
+{
+ echo "Usage: cups-config --api-version"
+ echo " cups-config --cflags"
+ echo " cups-config --datadir"
+ echo " cups-config --help"
+ echo " cups-config --ldflags"
+ echo " cups-config [--image] [--static] --libs"
+ echo " cups-config --serverbin"
+ echo " cups-config --serverroot"
+ echo " cups-config --version"
+
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1
+fi
+
+# Parse command line options
+static=no
+image=no
+
+while test $# -gt 0; do
+ case $1 in
+ --api-version)
+ echo $APIVERSION
+ ;;
+ --cflags)
+ echo $CFLAGS
+ ;;
+ --datadir)
+ echo $cups_datadir
+ ;;
+ --help)
+ usage 0
+ ;;
+ --image)
+ image=yes
+ ;;
+ --ldflags)
+ echo $LDFLAGS
+ ;;
+ --libs)
+ if test $static = no; then
+ if test $image = no; then
+ echo -lcups $LIBS
+ else
+ echo -lcupsimage $IMGLIBS -lcups $LIBS
+ fi
+ else
+ if test $image = no; then
+ echo $libdir/libcups.a $LIBS
+ else
+ echo $libdir/libcupsimage.a $IMGLIBS $libdir/libcups.a $LIBS
+ fi
+ fi
+ ;;
+ --serverbin)
+ echo $cups_serverbin
+ ;;
+ --serverroot)
+ echo $cups_serverroot
+ ;;
+ --static)
+ static=yes
+ ;;
+ --version)
+ echo $VERSION
+ ;;
+ *)
+ usage 1
+ ;;
+ esac
+
+ shift
+done
+
+#
+# End of "$Id$".
+#
diff --git a/cups.dsw b/cups.dsw
new file mode 100644
index 000000000..c5b05ea0f
--- /dev/null
+++ b/cups.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "cups"=".\cups\cups.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/cups.list.in b/cups.list.in
new file mode 100644
index 000000000..d8aed7536
--- /dev/null
+++ b/cups.list.in
@@ -0,0 +1,588 @@
+#
+# "$Id$"
+#
+# ESP Package Manager (EPM) file list for the Common UNIX Printing
+# System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+# Product information
+%product Common UNIX Printing System
+%copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+%vendor Easy Software Products
+%license LICENSE.txt
+%readme README.txt
+%version @CUPS_VERSION@
+%description The Common UNIX Printing System provides a portable printing
+%description layer for UNIX® operating systems. It has been developed by
+%description Easy Software Products to promote a standard printing solution
+%description for all UNIX vendors and users. CUPS provides the System V and
+%description Berkeley command-line interfaces.
+%provides cups-devel
+%provides cups-libs
+%provides cupsys
+%provides cupsys-bsd
+%provides cupsys-client
+%provides cupsys-devel
+%provides libcups1
+%provides libcupsys2
+%provides libcupsys2-dev
+
+%format rpm deb portable
+%provides @LIBCUPS@
+%provides @LIBCUPSIMAGE@
+%format all
+
+#
+# GNU variables...
+#
+
+$prefix=@prefix@
+$exec_prefix=@exec_prefix@
+$bindir=@bindir@
+$datadir=@datadir@
+$includedir=@includedir@
+$infodir=@infodir@
+$libdir=@libdir@
+$libexecdir=@libexecdir@
+$localstatedir=@localstatedir@
+$mandir=@mandir@
+$oldincludedir=@oldincludedir@
+$sbindir=@sbindir@
+$sharedstatedir=@sharedstatedir@
+$srcdir=@srcdir@
+$sysconfdir=@sysconfdir@
+$top_srcdir=@top_srcdir@
+
+#
+# ESP variables...
+#
+
+$AMANDIR=@AMANDIR@
+$BINDIR=@bindir@
+$DATADIR=@CUPS_DATADIR@
+$DOCDIR=@CUPS_DOCROOT@
+$INCLUDEDIR=${includedir}
+$INITDIR=@INITDIR@
+$INITDDIR=@INITDDIR@
+$LIBDIR=${libdir}
+$LOCALEDIR=@CUPS_LOCALEDIR@
+$LOGDIR=@CUPS_LOGDIR@
+$MANDIR=@mandir@
+$PAMDIR=@PAMDIR@
+$PMANDIR=@PMANDIR@
+$REQUESTS=@CUPS_REQUESTS@
+$SBINDIR=@sbindir@
+$SERVERBIN=@CUPS_SERVERBIN@
+$SERVERROOT=@CUPS_SERVERROOT@
+
+$CUPS_USER=@CUPS_USER@
+$CUPS_GROUP=@CUPS_GROUP@
+
+$CAT1EXT=@CAT1EXT@
+$CAT3EXT=@CAT3EXT@
+$CAT5EXT=@CAT5EXT@
+$CAT8EXT=@CAT8EXT@
+$MAN8EXT=@MAN8EXT@
+$MAN8DIR=@MAN8DIR@
+
+$DSOLIBS=@DSOLIBS@
+
+# Make sure the MD5 password file is now owned by CUPS_USER...
+%postinstall if test -f $SERVERROOT/passwd.md5; then
+%postinstall chown $CUPS_USER $SERVERROOT/passwd.md5
+%postinstall fi
+
+# Make sure the shared libraries are refreshed...
+%system linux
+%postinstall ldconfig
+%system all
+
+# Server programs
+%system all
+# Server files
+f 0555 root sys $SBINDIR/cupsd scheduler/cupsd
+
+d 0555 root sys $SERVERBIN -
+d 0555 root sys $SERVERBIN/backend -
+f 0555 root sys $SERVERBIN/backend/ipp backend/ipp
+l 0555 root sys $SERVERBIN/backend/http ipp
+f 0555 root sys $SERVERBIN/backend/lpd backend/lpd
+f 0555 root sys $SERVERBIN/backend/parallel backend/parallel
+f 0555 root sys $SERVERBIN/backend/scsi backend/scsi
+f 0555 root sys $SERVERBIN/backend/serial backend/serial
+f 0555 root sys $SERVERBIN/backend/socket backend/socket
+f 0555 root sys $SERVERBIN/backend/usb backend/usb
+d 0555 root sys $SERVERBIN/cgi-bin -
+f 0555 root sys $SERVERBIN/cgi-bin/admin.cgi cgi-bin/admin.cgi
+f 0555 root sys $SERVERBIN/cgi-bin/classes.cgi cgi-bin/classes.cgi
+f 0555 root sys $SERVERBIN/cgi-bin/jobs.cgi cgi-bin/jobs.cgi
+f 0555 root sys $SERVERBIN/cgi-bin/printers.cgi cgi-bin/printers.cgi
+d 0555 root sys $SERVERBIN/daemon -
+f 0555 root sys $SERVERBIN/daemon/cups-lpd scheduler/cups-lpd
+f 0555 root sys $SERVERBIN/daemon/cups-polld scheduler/cups-polld
+d 0555 root sys $SERVERBIN/filter -
+f 0555 root sys $SERVERBIN/filter/gziptoany filter/gziptoany
+f 0555 root sys $SERVERBIN/filter/hpgltops filter/hpgltops
+f 0555 root sys $SERVERBIN/filter/imagetops filter/imagetops
+f 0555 root sys $SERVERBIN/filter/imagetoraster filter/imagetoraster
+f 0555 root sys $SERVERBIN/filter/pdftops pdftops/pdftops
+f 0555 root sys $SERVERBIN/filter/pstops filter/pstops
+f 0555 root sys $SERVERBIN/filter/rastertodymo filter/rastertodymo
+f 0555 root sys $SERVERBIN/filter/rastertoepson filter/rastertoepson
+f 0555 root sys $SERVERBIN/filter/rastertohp filter/rastertohp
+f 0555 root sys $SERVERBIN/filter/texttops filter/texttops
+
+# Admin commands
+d 0555 root sys $BINDIR -
+l 0555 root sys $BINDIR/disable $SBINDIR/accept
+l 0555 root sys $BINDIR/enable $SBINDIR/accept
+l 0555 root sys $LIBDIR/accept $SBINDIR/accept
+d 0555 root sys $LIBDIR -
+l 0555 root sys $LIBDIR/lpadmin $SBINDIR/lpadmin
+l 0555 root sys $LIBDIR/reject accept
+d 0555 root sys $SBINDIR -
+f 0555 root sys $SBINDIR/accept systemv/accept
+f 0555 root sys $SBINDIR/cupsaddsmb systemv/cupsaddsmb
+f 0555 root sys $SBINDIR/lpadmin systemv/lpadmin
+f 0555 root sys $SBINDIR/lpc berkeley/lpc
+f 0555 root sys $SBINDIR/lpinfo systemv/lpinfo
+f 0555 root sys $SBINDIR/lpmove systemv/lpmove
+l 0555 root sys $SBINDIR/reject accept
+
+%system irix
+l 0555 root sys /usr/etc/lpc $SBINDIR/lpc
+%system all
+
+# User commands
+f 0555 root sys $BINDIR/cancel systemv/cancel
+f 0555 root sys $BINDIR/cupstestppd systemv/cupstestppd
+f 0555 root sys $BINDIR/lp systemv/lp
+f 0555 root sys $BINDIR/lpoptions systemv/lpoptions
+f 4555 $CUPS_USER sys $BINDIR/lppasswd systemv/lppasswd
+f 0555 root sys $BINDIR/lpq berkeley/lpq
+f 0555 root sys $BINDIR/lpr berkeley/lpr
+f 0555 root sys $BINDIR/lprm berkeley/lprm
+f 0555 root sys $BINDIR/lpstat systemv/lpstat
+
+%system irix
+l 0555 root sys /usr/bsd/lpq $BINDIR/lpq
+l 0555 root sys /usr/bsd/lpr $BINDIR/lpr
+l 0555 root sys /usr/bsd/lprm $BINDIR/lprm
+%system all
+
+# DSOs
+%if DSOLIBS
+%system hpux
+f 0555 root sys $LIBDIR/libcups.sl.2 cups/libcups.sl.2
+l 0555 root sys $LIBDIR/libcups.sl libcups.sl.2
+f 0555 root sys $LIBDIR/libcupsimage.sl.2 filter/libcupsimage.sl.2
+l 0555 root sys $LIBDIR/libcupsimage.sl libcupsimage.sl.2
+%system aix
+f 0555 root sys $LIBDIR/libcups_s.a cups/libcups_s.a
+f 0555 root sys $LIBDIR/libcupsimage_s.a filter/libcupsimage_s.a
+%system darwin
+f 0555 root sys $LIBDIR/libcups.2.dylib cups/libcups.2.dylib
+l 0555 root sys $LIBDIR/libcups.dylib libcups.2.dylib
+f 0555 root sys $LIBDIR/libcupsimage.2.dylib filter/libcupsimage.2.dylib
+l 0555 root sys $LIBDIR/libcupsimage.dylib libcupsimage.2.dylib
+%system !hpux !aix !darwin
+f 0555 root sys $LIBDIR/libcups.so.2 cups/libcups.so.2
+l 0555 root sys $LIBDIR/libcups.so libcups.so.2
+f 0555 root sys $LIBDIR/libcupsimage.so.2 filter/libcupsimage.so.2
+l 0555 root sys $LIBDIR/libcupsimage.so libcupsimage.so.2
+%system all
+%endif
+
+# Directories
+d 0755 root sys $LOGDIR -
+d 0700 $CUPS_USER sys $REQUESTS -
+d 1700 $CUPS_USER sys $REQUESTS/tmp -
+
+# Data files
+f 0444 root sys $LOCALEDIR/C/cups_C locale/C/cups_C
+f 0444 root sys $LOCALEDIR/be/cups_be locale/be/cups_be
+f 0444 root sys $LOCALEDIR/cs/cups_cs locale/cs/cups_cs
+f 0444 root sys $LOCALEDIR/de/cups_de locale/de/cups_de
+f 0444 root sys $LOCALEDIR/en/cups_en locale/en/cups_en
+f 0444 root sys $LOCALEDIR/en_US/cups_en_US locale/en_US/cups_en_US
+f 0444 root sys $LOCALEDIR/es/cups_es locale/es/cups_es
+f 0444 root sys $LOCALEDIR/fr/cups_fr locale/fr/cups_fr
+f 0444 root sys $LOCALEDIR/he/cups_he locale/he/cups_he
+f 0444 root sys $LOCALEDIR/it/cups_it locale/it/cups_it
+f 0444 root sys $LOCALEDIR/ru_RU/cups_ru_RU locale/ru_RU/cups_ru_RU
+f 0444 root sys $LOCALEDIR/sv/cups_sv locale/sv/cups_sv
+f 0444 root sys $LOCALEDIR/uk/cups_uk locale/uk/cups_uk
+f 0444 root sys $LOCALEDIR/uk_UA/cups_uk_UA locale/uk_UA/cups_uk_UA
+f 0444 root sys $LOCALEDIR/zh_CN/cups_zh_CN locale/zh_CN/cups_zh_CN
+
+d 0555 root sys $DATADIR -
+
+d 0555 root sys $DATADIR/banners -
+f 0444 root sys $DATADIR/banners/classified data/classified
+f 0444 root sys $DATADIR/banners/confidential data/confidential
+f 0444 root sys $DATADIR/banners/secret data/secret
+f 0444 root sys $DATADIR/banners/standard data/standard
+f 0444 root sys $DATADIR/banners/topsecret data/topsecret
+f 0444 root sys $DATADIR/banners/unclassified data/unclassified
+
+d 0555 root sys $DATADIR/charsets -
+f 0444 root sys $DATADIR/charsets/windows-874 data/windows-874
+f 0444 root sys $DATADIR/charsets/windows-1250 data/windows-1250
+f 0444 root sys $DATADIR/charsets/windows-1251 data/windows-1251
+f 0444 root sys $DATADIR/charsets/windows-1252 data/windows-1252
+f 0444 root sys $DATADIR/charsets/windows-1253 data/windows-1253
+f 0444 root sys $DATADIR/charsets/windows-1254 data/windows-1254
+f 0444 root sys $DATADIR/charsets/windows-1255 data/windows-1255
+f 0444 root sys $DATADIR/charsets/windows-1256 data/windows-1256
+f 0444 root sys $DATADIR/charsets/windows-1257 data/windows-1257
+f 0444 root sys $DATADIR/charsets/windows-1258 data/windows-1258
+f 0444 root sys $DATADIR/charsets/iso-8859-1 data/iso-8859-1
+f 0444 root sys $DATADIR/charsets/iso-8859-2 data/iso-8859-2
+f 0444 root sys $DATADIR/charsets/iso-8859-3 data/iso-8859-3
+f 0444 root sys $DATADIR/charsets/iso-8859-4 data/iso-8859-4
+f 0444 root sys $DATADIR/charsets/iso-8859-5 data/iso-8859-5
+f 0444 root sys $DATADIR/charsets/iso-8859-6 data/iso-8859-6
+f 0444 root sys $DATADIR/charsets/iso-8859-7 data/iso-8859-7
+f 0444 root sys $DATADIR/charsets/iso-8859-8 data/iso-8859-8
+f 0444 root sys $DATADIR/charsets/iso-8859-9 data/iso-8859-9
+f 0444 root sys $DATADIR/charsets/iso-8859-10 data/iso-8859-10
+f 0444 root sys $DATADIR/charsets/iso-8859-13 data/iso-8859-13
+f 0444 root sys $DATADIR/charsets/iso-8859-14 data/iso-8859-14
+f 0444 root sys $DATADIR/charsets/iso-8859-15 data/iso-8859-15
+f 0444 root sys $DATADIR/charsets/utf-8 data/utf-8
+
+d 0555 root sys $DATADIR/data -
+f 0444 root sys $DATADIR/data/HPGLprolog data/HPGLprolog
+f 0444 root sys $DATADIR/data/psglyphs data/psglyphs
+f 0444 root sys $DATADIR/data/testprint.ps data/testprint.ps
+
+d 0555 root sys $DATADIR/fonts -
+f 0444 root sys $DATADIR/fonts fonts/Courier*
+f 0444 root sys $DATADIR/fonts/Symbol fonts/Symbol
+
+d 0555 root sys $DATADIR/model -
+f 0444 root sys $DATADIR/model ppd/*.ppd
+
+d 0555 root sys $DATADIR/templates -
+c 0444 root sys $DATADIR/templates templates/*.tmpl
+
+d 0555 root sys $DATADIR/templates/be -
+c 0444 root sys $DATADIR/templates/be templates/be/*.tmpl
+
+d 0555 root sys $DATADIR/templates/de -
+c 0444 root sys $DATADIR/templates/de templates/de/*.tmpl
+
+d 0555 root sys $DATADIR/templates/es -
+c 0444 root sys $DATADIR/templates/es templates/es/*.tmpl
+
+d 0555 root sys $DATADIR/templates/fr -
+c 0444 root sys $DATADIR/templates/fr templates/fr/*.tmpl
+
+# Config files
+d 0555 root sys $SERVERROOT -
+d 0711 $CUPS_USER $CUPS_GROUP $SERVERROOT/certs -
+d 0755 root sys $SERVERROOT/interfaces -
+d 0755 root sys $SERVERROOT/ppd -
+c 0600 root sys $SERVERROOT conf/*.conf
+c 0600 root sys $SERVERROOT/mime.convs conf/mime.convs
+c 0600 root sys $SERVERROOT/mime.types conf/mime.types
+
+%if PAMDIR
+d 0555 root sys $PAMDIR -
+c 0644 root sys $PAMDIR/cups conf/@PAMFILE@
+%endif
+
+# Developer files
+f 0555 root sys $BINDIR/cups-config cups-config
+d 0555 root sys $INCLUDEDIR/cups -
+f 0444 root sys $INCLUDEDIR/cups/cups.h cups/cups.h
+f 0444 root sys $INCLUDEDIR/cups/http.h cups/http.h
+f 0444 root sys $INCLUDEDIR/cups/image.h filter/image.h
+f 0444 root sys $INCLUDEDIR/cups/ipp.h cups/ipp.h
+f 0444 root sys $INCLUDEDIR/cups/language.h cups/language.h
+f 0444 root sys $INCLUDEDIR/cups/md5.h cups/md5.h
+f 0444 root sys $INCLUDEDIR/cups/ppd.h cups/ppd.h
+f 0444 root sys $INCLUDEDIR/cups/raster.h filter/raster.h
+
+f 0444 root sys $LIBDIR/libcups.a cups/libcups.a
+f 0444 root sys $LIBDIR/libcupsimage.a filter/libcupsimage.a
+
+# Documentation files
+d 0555 root sys $DOCDIR -
+f 0444 root sys $DOCDIR doc/*.css
+f 0444 root sys $DOCDIR doc/*.html
+f 0444 root sys $DOCDIR doc/*.pdf
+f 0444 root sys $DOCDIR/robots.txt doc/robots.txt
+d 0555 root sys $DOCDIR/be -
+f 0444 root sys $DOCDIR/be doc/be/*.css
+f 0444 root sys $DOCDIR/be doc/be/*.html
+f 0444 root sys $DOCDIR/be doc/be/*.pdf
+d 0555 root sys $DOCDIR/de -
+f 0444 root sys $DOCDIR/de doc/de/*.css
+f 0444 root sys $DOCDIR/de doc/de/*.html
+f 0444 root sys $DOCDIR/de doc/de/*.pdf
+d 0555 root sys $DOCDIR/es -
+f 0444 root sys $DOCDIR/es doc/es/*.css
+f 0444 root sys $DOCDIR/es doc/es/*.html
+f 0444 root sys $DOCDIR/es doc/es/*.pdf
+d 0555 root sys $DOCDIR/fr -
+f 0444 root sys $DOCDIR/fr doc/fr/*.css
+f 0444 root sys $DOCDIR/fr doc/fr/*.html
+f 0444 root sys $DOCDIR/fr doc/fr/*.pdf
+d 0555 root sys $DOCDIR/images -
+f 0444 root sys $DOCDIR/images doc/images/*.gif
+
+# Man pages
+d 0555 root sys $AMANDIR -
+d 0555 root sys $AMANDIR/cat$MAN8DIR -
+d 0555 root sys $AMANDIR/man$MAN8DIR -
+d 0555 root sys $MANDIR -
+d 0555 root sys $MANDIR/cat1 -
+d 0555 root sys $MANDIR/cat5 -
+d 0555 root sys $MANDIR/man1 -
+d 0555 root sys $MANDIR/man5 -
+d 0555 root sys $PMANDIR -
+d 0555 root sys $PMANDIR/cat3 -
+d 0555 root sys $PMANDIR/man3 -
+
+f 0444 root sys $MANDIR/cat1/backend.$CAT1EXT man/backend.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/cups-config.$CAT1EXT man/cups-config.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/cupstestppd.$CAT1EXT man/cupstestppd.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/filter.$CAT1EXT man/filter.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lpoptions.$CAT1EXT man/lpoptions.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lppasswd.$CAT1EXT man/lppasswd.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lpq.$CAT1EXT man/lpq.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lprm.$CAT1EXT man/lprm.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lpr.$CAT1EXT man/lpr.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lpstat.$CAT1EXT man/lpstat.$CAT1EXT
+f 0444 root sys $MANDIR/cat1/lp.$CAT1EXT man/lp.$CAT1EXT
+l 0444 root sys $MANDIR/cat1/cancel.$CAT1EXT lp.$CAT1EXT
+
+f 0444 root sys $MANDIR/cat5/classes.conf.$CAT5EXT man/classes.conf.$CAT5EXT
+f 0444 root sys $MANDIR/cat5/cupsd.conf.$CAT5EXT man/cupsd.conf.$CAT5EXT
+f 0444 root sys $MANDIR/cat5/mime.convs.$CAT5EXT man/mime.convs.$CAT5EXT
+f 0444 root sys $MANDIR/cat5/mime.types.$CAT5EXT man/mime.types.$CAT5EXT
+f 0444 root sys $MANDIR/cat5/printers.conf.$CAT5EXT man/printers.conf.$CAT5EXT
+
+f 0444 root sys $AMANDIR/cat$MAN8DIR/accept.$CAT8EXT man/accept.$CAT8EXT
+l 0444 root sys $AMANDIR/cat$MAN8DIR/reject.$CAT8EXT accept.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/cupsaddsmb.$CAT8EXT man/cupsaddsmb.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/cups-lpd.$CAT8EXT man/cups-lpd.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/cups-polld.$CAT8EXT man/cups-polld.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/cupsd.$CAT8EXT man/cupsd.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/enable.$CAT8EXT man/enable.$CAT8EXT
+l 0444 root sys $AMANDIR/cat$MAN8DIR/disable.$CAT8EXT enable.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/lpadmin.$CAT8EXT man/lpadmin.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/lpc.$CAT8EXT man/lpc.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/lpinfo.$CAT8EXT man/lpinfo.$CAT8EXT
+f 0444 root sys $AMANDIR/cat$MAN8DIR/lpmove.$CAT8EXT man/lpmove.$CAT8EXT
+
+f 0444 root sys $MANDIR/man1/backend.1 man/backend.man
+f 0444 root sys $MANDIR/man1/cups-config.1 man/cups-config.man
+f 0444 root sys $MANDIR/man1/cupstestppd.1 man/cupstestppd.man
+f 0444 root sys $MANDIR/man1/filter.1 man/filter.man
+f 0444 root sys $MANDIR/man1/lpoptions.1 man/lpoptions.man
+f 0444 root sys $MANDIR/man1/lppasswd.1 man/lppasswd.man
+f 0444 root sys $MANDIR/man1/lpq.1 man/lpq.man
+f 0444 root sys $MANDIR/man1/lprm.1 man/lprm.man
+f 0444 root sys $MANDIR/man1/lpr.1 man/lpr.man
+f 0444 root sys $MANDIR/man1/lpstat.1 man/lpstat.man
+f 0444 root sys $MANDIR/man1/lp.1 man/lp.man
+l 0444 root sys $MANDIR/man1/cancel.1 lp.1
+
+f 0444 root sys $MANDIR/man5/classes.conf.5 man/classes.conf.man
+f 0444 root sys $MANDIR/man5/cupsd.conf.5 man/cupsd.conf.man
+f 0444 root sys $MANDIR/man5/mime.convs.5 man/mime.convs.man
+f 0444 root sys $MANDIR/man5/mime.types.5 man/mime.types.man
+f 0444 root sys $MANDIR/man5/printers.conf.5 man/printers.conf.man
+
+f 0444 root sys $AMANDIR/man$MAN8DIR/accept.$MAN8EXT man/accept.man
+l 0444 root sys $AMANDIR/man$MAN8DIR/reject.$MAN8EXT accept.$MAN8EXT
+f 0444 root sys $AMANDIR/man$MAN8DIR/cupsaddsmb.$MAN8EXT man/cupsaddsmb.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/cups-lpd.$MAN8EXT man/cups-lpd.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/cups-polld.$MAN8EXT man/cups-polld.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/cupsd.$MAN8EXT man/cupsd.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/enable.$MAN8EXT man/enable.man
+l 0444 root sys $AMANDIR/man$MAN8DIR/disable.$MAN8EXT enable.$MAN8EXT
+f 0444 root sys $AMANDIR/man$MAN8DIR/lpadmin.$MAN8EXT man/lpadmin.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/lpc.$MAN8EXT man/lpc.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/lpinfo.$MAN8EXT man/lpinfo.man
+f 0444 root sys $AMANDIR/man$MAN8DIR/lpmove.$MAN8EXT man/lpmove.man
+
+d 0555 root sys $AMANDIR/es -
+d 0555 root sys $AMANDIR/es/cat$MAN8DIR -
+d 0555 root sys $AMANDIR/es/man$MAN8DIR -
+d 0555 root sys $MANDIR/es -
+d 0555 root sys $MANDIR/es/cat1 -
+d 0555 root sys $MANDIR/es/cat5 -
+d 0555 root sys $MANDIR/es/man1 -
+d 0555 root sys $MANDIR/es/man5 -
+d 0555 root sys $PMANDIR/es -
+d 0555 root sys $PMANDIR/es/cat3 -
+d 0555 root sys $PMANDIR/es/man3 -
+
+f 0444 root sys $MANDIR/es/cat1/backend.$CAT1EXT man/es/backend.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/filter.$CAT1EXT man/es/filter.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lpoptions.$CAT1EXT man/es/lpoptions.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lppasswd.$CAT1EXT man/es/lppasswd.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lpq.$CAT1EXT man/es/lpq.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lprm.$CAT1EXT man/es/lprm.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lpr.$CAT1EXT man/es/lpr.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lpstat.$CAT1EXT man/es/lpstat.$CAT1EXT
+f 0444 root sys $MANDIR/es/cat1/lp.$CAT1EXT man/es/lp.$CAT1EXT
+l 0444 root sys $MANDIR/es/cat1/cancel.$CAT1EXT lp.$CAT1EXT
+
+f 0444 root sys $PMANDIR/es/cat1/cups-config.$CAT1EXT man/es/cups-config.$CAT1EXT
+
+f 0444 root sys $MANDIR/es/cat5/classes.conf.$CAT5EXT man/es/classes.conf.$CAT5EXT
+f 0444 root sys $MANDIR/es/cat5/cupsd.conf.$CAT5EXT man/es/cupsd.conf.$CAT5EXT
+f 0444 root sys $MANDIR/es/cat5/mime.convs.$CAT5EXT man/es/mime.convs.$CAT5EXT
+f 0444 root sys $MANDIR/es/cat5/mime.types.$CAT5EXT man/es/mime.types.$CAT5EXT
+f 0444 root sys $MANDIR/es/cat5/printers.conf.$CAT5EXT man/es/printers.conf.$CAT5EXT
+
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/accept.$CAT8EXT man/es/accept.$CAT8EXT
+l 0444 root sys $AMANDIR/es/cat$MAN8DIR/reject.$CAT8EXT accept.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/cupsaddsmb.$CAT8EXT man/es/cupsaddsmb.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/cups-lpd.$CAT8EXT man/es/cups-lpd.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/cups-polld.$CAT8EXT man/es/cups-polld.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/cupsd.$CAT8EXT man/es/cupsd.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/enable.$CAT8EXT man/es/enable.$CAT8EXT
+l 0444 root sys $AMANDIR/es/cat$MAN8DIR/disable.$CAT8EXT enable.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/lpadmin.$CAT8EXT man/es/lpadmin.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/lpc.$CAT8EXT man/es/lpc.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/lpinfo.$CAT8EXT man/es/lpinfo.$CAT8EXT
+f 0444 root sys $AMANDIR/es/cat$MAN8DIR/lpmove.$CAT8EXT man/es/lpmove.$CAT8EXT
+
+f 0444 root sys $MANDIR/es/man1/backend.1 man/es/backend.man
+f 0444 root sys $MANDIR/es/man1/filter.1 man/es/filter.man
+f 0444 root sys $MANDIR/es/man1/lpoptions.1 man/es/lpoptions.man
+f 0444 root sys $MANDIR/es/man1/lppasswd.1 man/es/lppasswd.man
+f 0444 root sys $MANDIR/es/man1/lpq.1 man/es/lpq.man
+f 0444 root sys $MANDIR/es/man1/lprm.1 man/es/lprm.man
+f 0444 root sys $MANDIR/es/man1/lpr.1 man/es/lpr.man
+f 0444 root sys $MANDIR/es/man1/lpstat.1 man/es/lpstat.man
+f 0444 root sys $MANDIR/es/man1/lp.1 man/es/lp.man
+l 0444 root sys $MANDIR/es/man1/cancel.1 lp.1
+
+f 0444 root sys $PMANDIR/es/man1/cups-config.1 man/es/cups-config.man
+
+f 0444 root sys $MANDIR/es/man5/classes.conf.5 man/es/classes.conf.man
+f 0444 root sys $MANDIR/es/man5/cupsd.conf.5 man/es/cupsd.conf.man
+f 0444 root sys $MANDIR/es/man5/mime.convs.5 man/es/mime.convs.man
+f 0444 root sys $MANDIR/es/man5/mime.types.5 man/es/mime.types.man
+f 0444 root sys $MANDIR/es/man5/printers.conf.5 man/es/printers.conf.man
+
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/accept.$MAN8EXT man/es/accept.man
+l 0444 root sys $AMANDIR/es/man$MAN8DIR/reject.$MAN8EXT accept.$MAN8EXT
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/cupsaddsmb.$MAN8EXT man/es/cupsaddsmb.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/cups-lpd.$MAN8EXT man/es/cups-lpd.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/cups-polld.$MAN8EXT man/es/cups-polld.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/cupsd.$MAN8EXT man/es/cupsd.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/enable.$MAN8EXT man/es/enable.man
+l 0444 root sys $AMANDIR/es/man$MAN8DIR/disable.$MAN8EXT enable.$MAN8EXT
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/lpadmin.$MAN8EXT man/es/lpadmin.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/lpc.$MAN8EXT man/es/lpc.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/lpinfo.$MAN8EXT man/es/lpinfo.man
+f 0444 root sys $AMANDIR/es/man$MAN8DIR/lpmove.$MAN8EXT man/es/lpmove.man
+
+d 0555 root sys $AMANDIR/fr -
+d 0555 root sys $AMANDIR/fr/cat$MAN8DIR -
+d 0555 root sys $AMANDIR/fr/man$MAN8DIR -
+d 0555 root sys $MANDIR/fr -
+d 0555 root sys $MANDIR/fr/cat1 -
+d 0555 root sys $MANDIR/fr/cat5 -
+d 0555 root sys $MANDIR/fr/man1 -
+d 0555 root sys $MANDIR/fr/man5 -
+d 0555 root sys $PMANDIR/fr -
+d 0555 root sys $PMANDIR/fr/cat3 -
+d 0555 root sys $PMANDIR/fr/man3 -
+
+f 0444 root sys $MANDIR/fr/cat1/backend.$CAT1EXT man/fr/backend.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/filter.$CAT1EXT man/fr/filter.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lpoptions.$CAT1EXT man/fr/lpoptions.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lppasswd.$CAT1EXT man/fr/lppasswd.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lpq.$CAT1EXT man/fr/lpq.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lprm.$CAT1EXT man/fr/lprm.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lpr.$CAT1EXT man/fr/lpr.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lpstat.$CAT1EXT man/fr/lpstat.$CAT1EXT
+f 0444 root sys $MANDIR/fr/cat1/lp.$CAT1EXT man/fr/lp.$CAT1EXT
+l 0444 root sys $MANDIR/fr/cat1/cancel.$CAT1EXT lp.$CAT1EXT
+
+f 0444 root sys $PMANDIR/fr/cat1/cups-config.$CAT1EXT man/fr/cups-config.$CAT1EXT
+
+f 0444 root sys $MANDIR/fr/cat5/classes.conf.$CAT5EXT man/fr/classes.conf.$CAT5EXT
+f 0444 root sys $MANDIR/fr/cat5/cupsd.conf.$CAT5EXT man/fr/cupsd.conf.$CAT5EXT
+f 0444 root sys $MANDIR/fr/cat5/mime.convs.$CAT5EXT man/fr/mime.convs.$CAT5EXT
+f 0444 root sys $MANDIR/fr/cat5/mime.types.$CAT5EXT man/fr/mime.types.$CAT5EXT
+f 0444 root sys $MANDIR/fr/cat5/printers.conf.$CAT5EXT man/fr/printers.conf.$CAT5EXT
+
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/accept.$CAT8EXT man/fr/accept.$CAT8EXT
+l 0444 root sys $AMANDIR/fr/cat$MAN8DIR/reject.$CAT8EXT accept.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cupsaddsmb.$CAT8EXT man/fr/cupsaddsmb.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cups-lpd.$CAT8EXT man/fr/cups-lpd.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cups-polld.$CAT8EXT man/fr/cups-polld.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/cupsd.$CAT8EXT man/fr/cupsd.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/enable.$CAT8EXT man/fr/enable.$CAT8EXT
+l 0444 root sys $AMANDIR/fr/cat$MAN8DIR/disable.$CAT8EXT enable.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpadmin.$CAT8EXT man/fr/lpadmin.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpc.$CAT8EXT man/fr/lpc.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpinfo.$CAT8EXT man/fr/lpinfo.$CAT8EXT
+f 0444 root sys $AMANDIR/fr/cat$MAN8DIR/lpmove.$CAT8EXT man/fr/lpmove.$CAT8EXT
+
+f 0444 root sys $MANDIR/fr/man1/backend.1 man/fr/backend.man
+f 0444 root sys $MANDIR/fr/man1/filter.1 man/fr/filter.man
+f 0444 root sys $MANDIR/fr/man1/lpoptions.1 man/fr/lpoptions.man
+f 0444 root sys $MANDIR/fr/man1/lppasswd.1 man/fr/lppasswd.man
+f 0444 root sys $MANDIR/fr/man1/lpq.1 man/fr/lpq.man
+f 0444 root sys $MANDIR/fr/man1/lprm.1 man/fr/lprm.man
+f 0444 root sys $MANDIR/fr/man1/lpr.1 man/fr/lpr.man
+f 0444 root sys $MANDIR/fr/man1/lpstat.1 man/fr/lpstat.man
+f 0444 root sys $MANDIR/fr/man1/lp.1 man/fr/lp.man
+l 0444 root sys $MANDIR/fr/man1/cancel.1 lp.1
+
+f 0444 root sys $PMANDIR/fr/man1/cups-config.1 man/fr/cups-config.man
+
+f 0444 root sys $MANDIR/fr/man5/classes.conf.5 man/fr/classes.conf.man
+f 0444 root sys $MANDIR/fr/man5/cupsd.conf.5 man/fr/cupsd.conf.man
+f 0444 root sys $MANDIR/fr/man5/mime.convs.5 man/fr/mime.convs.man
+f 0444 root sys $MANDIR/fr/man5/mime.types.5 man/fr/mime.types.man
+f 0444 root sys $MANDIR/fr/man5/printers.conf.5 man/fr/printers.conf.man
+
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/accept.$MAN8EXT man/fr/accept.man
+l 0444 root sys $AMANDIR/fr/man$MAN8DIR/reject.$MAN8EXT accept.$MAN8EXT
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cupsaddsmb.$MAN8EXT man/fr/cupsaddsmb.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cups-lpd.$MAN8EXT man/fr/cups-lpd.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cups-polld.$MAN8EXT man/fr/cups-polld.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/cupsd.$MAN8EXT man/fr/cupsd.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/enable.$MAN8EXT man/fr/enable.man
+l 0444 root sys $AMANDIR/fr/man$MAN8DIR/disable.$MAN8EXT enable.$MAN8EXT
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpadmin.$MAN8EXT man/fr/lpadmin.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpc.$MAN8EXT man/fr/lpc.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpinfo.$MAN8EXT man/fr/lpinfo.man
+f 0444 root sys $AMANDIR/fr/man$MAN8DIR/lpmove.$MAN8EXT man/fr/lpmove.man
+
+# Startup script
+%system all
+i 0555 root sys cups cups.sh
+
+#
+# End of "$Id$".
+#
diff --git a/cups.osx b/cups.osx
new file mode 100644
index 000000000..bff65dcc6
--- /dev/null
+++ b/cups.osx
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+##
+# PrintingServices - a.k.a. CUPS
+##
+
+. /etc/rc.common
+
+StartService ()
+{
+ if [ "${CUPS:=-YES-}" = "-YES-" ]; then
+ ConsoleMessage "Starting printing services"
+ /usr/sbin/cupsd
+ fi
+}
+
+StopService ()
+{
+ # Until cupsd has a pid file...
+ pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
+ if test "$pid" != ""; then
+ ConsoleMessage "Stopping printing services"
+ kill "${pid}"
+ fi
+}
+
+RestartService ()
+{
+ # Until cupsd has a pid file...
+ pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
+ if test "x$pid" != x; then
+ ConsoleMessage "Restarting printing services"
+ kill -HUP "${pid}"
+ else
+ StartService
+ fi
+}
+
+RunService "$1"
diff --git a/cups.plist b/cups.plist
new file mode 100644
index 000000000..0633bf88a
--- /dev/null
+++ b/cups.plist
@@ -0,0 +1,7 @@
+{
+ Description = "Printing Services";
+ Provides = ("PrintingServices");
+ Requires = ("Resolver");
+ Uses = ("Network Time");
+ OrderPreference = "Late";
+}
diff --git a/cups.sh.in b/cups.sh.in
new file mode 100755
index 000000000..aeeb26833
--- /dev/null
+++ b/cups.sh.in
@@ -0,0 +1,211 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Startup/shutdown script for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+#### OS-Dependent Information
+
+#
+# Linux chkconfig stuff:
+#
+# chkconfig: 235 99 00
+# description: Startup/shutdown script for the Common UNIX \
+# Printing System (CUPS).
+#
+
+#
+# NetBSD 1.5+ rcorder script lines. The format of the following two
+# lines is very strict -- please don't add additional spaces!
+#
+# PROVIDE: cups
+# REQUIRE: DAEMON
+#
+
+
+#### OS-Dependent Configuration
+
+case "`uname`" in
+ IRIX*)
+ IS_ON=/sbin/chkconfig
+
+ if $IS_ON verbose; then
+ ECHO=echo
+ else
+ ECHO=:
+ fi
+ ECHO_OK=:
+ ECHO_ERROR=:
+ ;;
+
+ *BSD*)
+ IS_ON=:
+ ECHO=echo
+ ECHO_OK=:
+ ECHO_ERROR=:
+ ;;
+
+ Darwin*)
+ . /etc/rc.common
+
+ if test "${CUPS:=-YES-}" = "-NO-"; then
+ exit 0
+ fi
+
+ IS_ON=:
+ ECHO=ConsoleMessage
+ ECHO_OK=:
+ ECHO_ERROR=:
+ ;;
+
+ Linux*)
+ IS_ON=/bin/true
+ if test -f /etc/init.d/functions; then
+ . /etc/init.d/functions
+ ECHO=echo
+ ECHO_OK="echo_success"
+ ECHO_ERROR="echo_failure"
+ else
+ ECHO=echo
+ ECHO_OK=:
+ ECHO_ERROR=:
+ fi
+ ;;
+
+ *)
+ IS_ON=/bin/true
+ ECHO=echo
+ ECHO_OK=:
+ ECHO_ERROR=:
+ ;;
+esac
+
+#### OS-Independent Stuff
+
+#
+# Set the timezone, if possible... This allows the
+# scheduler and all child processes to know the local
+# timezone when reporting dates and times to the user.
+# If no timezone information is found, then Greenwich
+# Mean Time (GMT) will probably be used.
+#
+
+for file in /etc/TIMEZONE /etc/rc.config /etc/sysconfig/clock; do
+ if test -f $file; then
+ . $file
+ fi
+done
+
+if test "x$ZONE" != x; then
+ TZ="$ZONE"
+fi
+
+if test "x$TIMEZONE" != x; then
+ TZ="$TIMEZONE"
+fi
+
+if test "x$TZ" != x; then
+ export TZ
+fi
+
+#
+# See if the CUPS server (cupsd) is running...
+#
+
+case "`uname`" in
+ HP-UX* | AIX* | SINIX*)
+ pid=`ps -e | awk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'`
+ ;;
+ IRIX* | SunOS*)
+ pid=`ps -e | nawk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'`
+ ;;
+ UnixWare*)
+ pid=`ps -e | awk '{if (match($6, ".*/cupsd$") || $6 == "cupsd") print $1}'`
+ . /etc/TIMEZONE
+ ;;
+ OSF1*)
+ pid=`ps -e | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
+ ;;
+ Linux* | *BSD* | Darwin*)
+ pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'`
+ ;;
+ *)
+ pid=""
+ ;;
+esac
+
+#
+# Start or stop the CUPS server based upon the first argument to the script.
+#
+
+case $1 in
+ start | restart | reload)
+ if $IS_ON cups; then
+ if test "$pid" != ""; then
+ kill -HUP $pid
+ else
+ prefix=@prefix@
+ exec_prefix=@exec_prefix@
+ @sbindir@/cupsd
+ if test $? != 0; then
+ $ECHO_FAIL
+ $ECHO "cups: unable to $1 scheduler."
+ exit 1
+ fi
+ fi
+ $ECHO_OK
+ $ECHO "cups: ${1}ed scheduler."
+ fi
+ ;;
+
+ stop)
+ if test "$pid" != ""; then
+ kill $pid
+ $ECHO_OK
+ $ECHO "cups: stopped scheduler."
+ fi
+ ;;
+
+ status)
+ if test "$pid" != ""; then
+ echo "cups: scheduler is running."
+ else
+ echo "cups: scheduler is not running."
+ fi
+ ;;
+
+ *)
+ echo "Usage: cups {reload|restart|start|status|stop}"
+ exit 1
+ ;;
+esac
+
+#
+# Exit with no errors.
+#
+
+exit 0
+
+
+#
+# End of "$Id$".
+#
diff --git a/cups.spec b/cups.spec
new file mode 100644
index 000000000..4ebda70bb
--- /dev/null
+++ b/cups.spec
@@ -0,0 +1,295 @@
+#
+# "$Id: cups.spec 4473 2004-12-16 19:42:22Z mike $"
+#
+# RPM "spec" file for the Common UNIX Printing System (CUPS).
+#
+# Original version by Jason McMullan <jmcc@ontv.com>.
+#
+# Copyright 1999-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+Summary: Common Unix Printing System
+Name: cups
+Version: 1.1.23rc1
+Release: 1
+Copyright: GPL
+Group: System Environment/Daemons
+Source: ftp://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-source.tar.gz
+Url: http://www.cups.org
+Packager: Anonymous <anonymous@foo.com>
+Vendor: Easy Software Products
+
+# Use buildroot so as not to disturb the version already installed
+BuildRoot: /var/tmp/%{name}-root
+
+# Dependencies...
+Conflicts: lpr, LPRng
+Provides: libcups.so.2
+Provides: libcupsimage.so.2
+
+%package devel
+Summary: Common Unix Printing System - development environment
+Group: Development/Libraries
+
+%package libs
+Summary: Common Unix Printing System - shared libraries
+Group: System Environment/Libraries
+Provides: libcups1
+
+%description
+The Common UNIX Printing System provides a portable printing layer for
+UNIX® operating systems. It has been developed by Easy Software Products
+to promote a standard printing solution for all UNIX vendors and users.
+CUPS provides the System V and Berkeley command-line interfaces.
+
+%description devel
+The Common UNIX Printing System provides a portable printing layer for
+UNIX® operating systems. This is the development package for creating
+additional printer drivers and other CUPS services.
+
+%description libs
+The Common UNIX Printing System provides a portable printing layer for
+UNIX® operating systems. This package contains the CUPS shared libraries.
+
+%prep
+%setup
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure
+
+# If we got this far, all prerequisite libraries must be here.
+make
+
+%install
+# Make sure the RPM_BUILD_ROOT directory exists.
+rm -rf $RPM_BUILD_ROOT
+
+make BUILDROOT=$RPM_BUILD_ROOT install
+
+%post
+ldconfig
+
+if test -x /sbin/chkconfig; then
+ /sbin/chkconfig --add cups
+ /sbin/chkconfig cups on
+fi
+
+# these lines automatically start cupsd after installation; commented out
+# by request...
+#if test -f /sbin/init.d/cups; then
+# /sbin/init.d/cups start
+#fi
+#if test -f /etc/rc.d/init.d/cups; then
+# /etc/rc.d/init.d/cups start
+#fi
+#if test -f /etc/init.d/cups; then
+# /etc/init.d/cups start
+#fi
+
+%preun
+if test -f /sbin/init.d/cups; then
+ /sbin/init.d/cups stop
+fi
+if test -f /etc/rc.d/init.d/cups; then
+ /etc/rc.d/init.d/cups stop
+fi
+if test -f /etc/init.d/cups; then
+ /etc/init.d/cups stop
+fi
+
+if test -x /sbin/chkconfig; then
+ /sbin/chkconfig --del cups
+fi
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%dir /etc/cups
+%config(noreplace) /etc/cups/*.conf
+%dir /etc/cups/certs
+%dir /etc/cups/interfaces
+/etc/cups/mime.types
+/etc/cups/mime.convs
+%dir /etc/cups/ppd
+%dir /etc/pam.d
+/etc/pam.d/*
+
+# RC dirs are a pain under Linux... Uncomment the appropriate ones if you
+# don't use Red Hat or Mandrake...
+
+# OLD RedHat/Mandrake
+/etc/rc.d/init.d/*
+/etc/rc.d/rc0.d/*
+/etc/rc.d/rc2.d/*
+/etc/rc.d/rc3.d/*
+/etc/rc.d/rc5.d/*
+
+#/sbin/rc.d/*
+#/sbin/rc.d/rc0.d/*
+#/sbin/rc.d/rc2.d/*
+#/sbin/rc.d/rc3.d/*
+#/sbin/rc.d/rc5.d/*
+
+# NEW RedHat/Mandrake
+#/etc/init.d/*
+#/etc/rc0.d/*
+#/etc/rc2.d/*
+#/etc/rc3.d/*
+#/etc/rc5.d/*
+
+/usr/bin/cancel
+/usr/bin/cupstestppd
+/usr/bin/disable
+/usr/bin/enable
+/usr/bin/lp*
+%dir /usr/lib/cups
+/usr/lib/cups/*
+/usr/sbin/*
+%dir /usr/share/cups
+/usr/share/cups/*
+%dir /usr/share/doc/cups
+/usr/share/doc/cups/*
+%dir /usr/share/locale
+/usr/share/locale/*
+
+%dir /usr/share/man/cat1
+/usr/share/man/cat1/backend.1
+/usr/share/man/cat1/cupstestppd.1
+/usr/share/man/cat1/filter.1
+/usr/share/man/cat1/lp.1
+/usr/share/man/cat1/lpoptions.1
+/usr/share/man/cat1/lppasswd.1
+/usr/share/man/cat1/lpq.1
+/usr/share/man/cat1/lpr.1
+/usr/share/man/cat1/lprm.1
+/usr/share/man/cat1/lpstat.1
+%dir /usr/share/man/cat5
+/usr/share/man/cat5/*
+%dir /usr/share/man/cat8
+/usr/share/man/cat8/*
+%dir /usr/share/man/man1
+/usr/share/man/man1/backend.1.gz
+/usr/share/man/man1/cupstestppd.1.gz
+/usr/share/man/man1/filter.1.gz
+/usr/share/man/man1/lp.1.gz
+/usr/share/man/man1/lpoptions.1.gz
+/usr/share/man/man1/lppasswd.1.gz
+/usr/share/man/man1/lpq.1.gz
+/usr/share/man/man1/lpr.1.gz
+/usr/share/man/man1/lprm.1.gz
+/usr/share/man/man1/lpstat.1.gz
+%dir /usr/share/man/man5
+/usr/share/man/man5/*
+%dir /usr/share/man/man8
+/usr/share/man/man8/*
+
+%dir /usr/share/man/es/cat1
+/usr/share/man/es/cat1/backend.1
+/usr/share/man/es/cat1/cupstestppd.1
+/usr/share/man/es/cat1/filter.1
+/usr/share/man/es/cat1/lp.1
+/usr/share/man/es/cat1/lpoptions.1
+/usr/share/man/es/cat1/lppasswd.1
+/usr/share/man/es/cat1/lpq.1
+/usr/share/man/es/cat1/lpr.1
+/usr/share/man/es/cat1/lprm.1
+/usr/share/man/es/cat1/lpstat.1
+%dir /usr/share/man/es/cat5
+/usr/share/man/es/cat5/*
+%dir /usr/share/man/es/cat8
+/usr/share/man/es/cat8/*
+%dir /usr/share/man/es/man1
+/usr/share/man/es/man1/backend.1.gz
+/usr/share/man/es/man1/cupstestppd.1.gz
+/usr/share/man/es/man1/filter.1.gz
+/usr/share/man/es/man1/lp.1.gz
+/usr/share/man/es/man1/lpoptions.1.gz
+/usr/share/man/es/man1/lppasswd.1.gz
+/usr/share/man/es/man1/lpq.1.gz
+/usr/share/man/es/man1/lpr.1.gz
+/usr/share/man/es/man1/lprm.1.gz
+/usr/share/man/es/man1/lpstat.1.gz
+%dir /usr/share/man/es/man5
+/usr/share/man/es/man5/*
+%dir /usr/share/man/es/man8
+/usr/share/man/es/man8/*
+
+%dir /usr/share/man/fr/cat1
+/usr/share/man/fr/cat1/backend.1
+/usr/share/man/fr/cat1/cupstestppd.1
+/usr/share/man/fr/cat1/filter.1
+/usr/share/man/fr/cat1/lp.1
+/usr/share/man/fr/cat1/lpoptions.1
+/usr/share/man/fr/cat1/lppasswd.1
+/usr/share/man/fr/cat1/lpq.1
+/usr/share/man/fr/cat1/lpr.1
+/usr/share/man/fr/cat1/lprm.1
+/usr/share/man/fr/cat1/lpstat.1
+%dir /usr/share/man/fr/cat5
+/usr/share/man/fr/cat5/*
+%dir /usr/share/man/fr/cat8
+/usr/share/man/fr/cat8/*
+%dir /usr/share/man/fr/man1
+/usr/share/man/fr/man1/backend.1.gz
+/usr/share/man/fr/man1/cupstestppd.1.gz
+/usr/share/man/fr/man1/filter.1.gz
+/usr/share/man/fr/man1/lp.1.gz
+/usr/share/man/fr/man1/lpoptions.1.gz
+/usr/share/man/fr/man1/lppasswd.1.gz
+/usr/share/man/fr/man1/lpq.1.gz
+/usr/share/man/fr/man1/lpr.1.gz
+/usr/share/man/fr/man1/lprm.1.gz
+/usr/share/man/fr/man1/lpstat.1.gz
+%dir /usr/share/man/fr/man5
+/usr/share/man/fr/man5/*
+%dir /usr/share/man/fr/man8
+/usr/share/man/fr/man8/*
+
+%attr(0700,lp,root) %dir /var/spool/cups
+%attr(1700,lp,root) %dir /var/spool/cups/tmp
+
+%files devel
+%dir /usr/share/man/cat1
+/usr/share/man/cat1/cups-config.1
+%dir /usr/share/man/man1
+/usr/share/man/man1/cups-config.1.gz
+
+%dir /usr/share/man/es/cat1
+/usr/share/man/es/cat1/cups-config.1
+%dir /usr/share/man/es/man1
+/usr/share/man/es/man1/cups-config.1.gz
+
+%dir /usr/share/man/fr/cat1
+/usr/share/man/fr/cat1/cups-config.1
+%dir /usr/share/man/fr/man1
+/usr/share/man/fr/man1/cups-config.1.gz
+
+/usr/bin/cups-config
+%dir /usr/include/cups
+/usr/include/cups/*
+/usr/lib/*.a
+
+%files libs
+/usr/lib/*.so*
+
+#
+# End of "$Id: cups.spec 4473 2004-12-16 19:42:22Z mike $".
+#
diff --git a/cups.strings b/cups.strings
new file mode 100644
index 000000000..d08f91972
--- /dev/null
+++ b/cups.strings
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>Starting printing services</key>
+ <string>Starting printing services</string>
+</dict>
+</plist>
+
diff --git a/cups/.cvsignore b/cups/.cvsignore
new file mode 100644
index 000000000..07158f4e7
--- /dev/null
+++ b/cups/.cvsignore
@@ -0,0 +1,13 @@
+libcups.a
+libcups.la
+libcups.sl
+libcups.sl.2
+libcups.so
+libcups.so.2
+libcups_s.a
+libcups.2.dylib
+libcups.dylib
+testhttp
+testipp
+testlang
+testppd
diff --git a/cups/Dependencies b/cups/Dependencies
new file mode 100644
index 000000000..899eeea72
--- /dev/null
+++ b/cups/Dependencies
@@ -0,0 +1,31 @@
+# DO NOT DELETE
+
+attr.o: ppd.h debug.h string.h ../config.h
+auth.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h language.h
+auth.o: debug.h
+dest.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h language.h
+emit.o: ppd.h string.h ../config.h
+encode.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h debug.h
+getputfile.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h language.h
+getputfile.o: debug.h
+http.o: http-private.h ../config.h http.h string.h md5.h debug.h
+http-addr.o: string.h ../config.h http.h md5.h
+http-support.o: string.h ../config.h http.h md5.h ipp.h
+ipp.o: string.h ../config.h ipp.h http.h md5.h debug.h
+ipp-support.o: string.h ../config.h language.h ipp.h http.h md5.h debug.h
+language.o: string.h ../config.h language.h debug.h cups_C.h
+mark.o: ppd.h string.h ../config.h debug.h
+md5.o: md5.h string.h ../config.h
+md5passwd.o: http.h string.h ../config.h md5.h
+options.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h debug.h
+page.o: ppd.h string.h ../config.h
+ppd.o: ppd.h string.h ../config.h language.h debug.h
+snprintf.o: string.h ../config.h
+string.o: string.h ../config.h
+tempfile.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h debug.h
+usersys.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h
+util.o: cups.h ipp.h http.h string.h ../config.h md5.h ppd.h language.h
+util.o: debug.h
+testhttp.o: http.h string.h ../config.h md5.h
+testipp.o: ../cups/string.h ../config.h string.h ipp.h http.h md5.h
+testlang.o: language.h
diff --git a/cups/Makefile b/cups/Makefile
new file mode 100644
index 000000000..8b8791aba
--- /dev/null
+++ b/cups/Makefile
@@ -0,0 +1,212 @@
+#
+# "$Id$"
+#
+# Support library Makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+# This file is subject to the Apple OS-Developed Software exception.
+#
+
+include ../Makedefs
+
+#
+# Object files...
+#
+
+LIBOBJS = attr.o auth.o dest.o emit.o encode.o getputfile.o \
+ http.o http-addr.o http-support.o ipp.o ipp-support.o \
+ language.o mark.o md5.o md5passwd.o options.o page.o \
+ ppd.o snprintf.o string.o tempfile.o usersys.o util.o
+OBJS = $(LIBOBJS) testhttp.o testipp.o testlang.o
+
+
+#
+# Header files to install...
+#
+
+HEADERS = cups.h http.h ipp.h language.h md5.h ppd.h
+
+
+#
+# Targets in this directory...
+#
+
+TARGETS = $(LIBCUPS) libcups.a \
+ testhttp testipp testlang
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Remove object and target files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS) `basename $(LIBCUPS) .2` libcups.dylib
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install object and target files...
+#
+
+install: all installhdrs
+ $(INSTALL_DIR) $(LIBDIR)
+ $(INSTALL_LIB) $(LIBCUPS) $(LIBDIR)
+ if test $(LIBCUPS) = "libcups.so.2" -o $(LIBCUPS) = "libcups.sl.2"; then \
+ $(RM) $(LIBDIR)/`basename $(LIBCUPS) .2`; \
+ $(LN) $(LIBCUPS) $(LIBDIR)/`basename $(LIBCUPS) .2`; \
+ fi
+ if test $(LIBCUPS) = "libcups.2.dylib"; then \
+ $(STRIP) -x $(LIBDIR)/$(LIBCUPS); \
+ $(RM) $(LIBDIR)/libcups.dylib; \
+ $(LN) $(LIBCUPS) $(LIBDIR)/libcups.dylib; \
+ fi
+ if test $(LIBCUPS) != "libcups.a"; then \
+ $(INSTALL_LIB) libcups.a $(LIBDIR); \
+ $(RANLIB) $(LIBDIR)/libcups.a; \
+ fi
+
+installhdrs:
+ $(INSTALL_DIR) $(INCLUDEDIR)/cups
+ for file in $(HEADERS); do \
+ $(INSTALL_DATA) $$file $(INCLUDEDIR)/cups; \
+ done
+
+
+#
+# libcups.so.2, libcups.sl.2
+#
+
+libcups.so.2 libcups.sl.2: $(LIBOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ $(LIBOBJS) $(SSLLIBS) $(COMMONLIBS)
+ $(RM) `basename $@ .2`
+ $(LN) $@ `basename $@ .2`
+
+
+#
+# libcups.2.dylib
+#
+
+libcups.2.dylib: $(LIBOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 2.7.0 \
+ -compatibility_version 2.0.0 \
+ $(LIBOBJS) $(SSLLIBS) $(COMMONLIBS)
+ $(RM) libcups.dylib
+ $(LN) $@ libcups.dylib
+
+
+#
+# libcups_s.a
+#
+
+libcups_s.a: $(LIBOBJS) ../Makedefs
+ echo Creating $@...
+ $(RM) libcups_s.exp
+ (echo _ipp_add_attr; echo _ipp_free_attr) >libcups_s.exp
+ $(DSO) $(DSOFLAGS) -Wl,-bexport:libcups_s.exp -o libcups_s.o $(LIBOBJS) $(SSLLIBS) $(COMMONLIBS) -lm
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ libcups_s.o
+
+
+#
+# libcups.la
+#
+
+libcups.la: $(LIBOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) -rpath $(LIBDIR) \
+ -version-info 2:7 $(SSLLIBS) $(COMMONLIBS)
+
+
+#
+# libcups.a
+#
+
+libcups.a: $(LIBOBJS)
+ echo Archiving $@...
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $(LIBOBJS)
+ $(RANLIB) $@
+
+
+#
+# cups_C.h - the default POSIX locale that is compiled in.
+#
+
+cups_C.h: ../locale/C/cups_C
+ echo Generating $@...
+ $(RM) cups_C.h
+ $(AWK) '{print "\"" $$0 "\","}' < ../locale/C/cups_C > cups_C.h
+
+
+#
+# testhttp (dependency on static CUPS library is intentional)
+#
+
+testhttp: testhttp.o libcups.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ testhttp.o libcups.a $(NETLIBS) $(SSLLIBS) $(COMMONLIBS)
+
+
+#
+# testipp (dependency on static CUPS library is intentional)
+#
+
+testipp: testipp.o libcups.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ testipp.o libcups.a $(NETLIBS) $(SSLLIBS) $(COMMONLIBS)
+
+
+#
+# testlang (dependency on static CUPS library is intentional)
+#
+
+testlang: testlang.o libcups.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ testlang.o libcups.a $(NETLIBS) $(SSLLIBS) $(COMMONLIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/cups/attr.c b/cups/attr.c
new file mode 100644
index 000000000..36863fd9c
--- /dev/null
+++ b/cups/attr.c
@@ -0,0 +1,180 @@
+/*
+ * "$Id$"
+ *
+ * PPD model-specific attribute routines for the Common UNIX Printing System
+ * (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * ppdFindAttr() - Find the first matching attribute...
+ * ppdFindNextAttr() - Find the next matching attribute...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ppd.h"
+#include "debug.h"
+#include "string.h"
+#include <stdlib.h>
+
+
+/*
+ * Private function...
+ */
+
+extern int _ppd_attr_compare(ppd_attr_t **a, ppd_attr_t **b);
+
+
+/*
+ * 'ppdFindAttr()' - Find the first matching attribute...
+ */
+
+ppd_attr_t * /* O - Attribute or NULL if not found */
+ppdFindAttr(ppd_file_t *ppd, /* I - PPD file data */
+ const char *name, /* I - Attribute name */
+ const char *spec) /* I - Specifier string or NULL */
+{
+ ppd_attr_t key, /* Search key */
+ *keyptr, /* Pointer to key */
+ **match; /* Matching attribute */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (ppd == NULL || name == NULL || ppd->num_attrs == 0)
+ return (NULL);
+
+ /*
+ * Do a binary search for a matching attribute...
+ */
+
+ memset(&key, 0, sizeof(key));
+ strncpy(key.name, name, sizeof(key.name) - 1);
+ if (spec)
+ strncpy(key.spec, spec, sizeof(key.spec) - 1);
+
+ keyptr = &key;
+
+ match = bsearch(&keyptr, ppd->attrs, ppd->num_attrs, sizeof(ppd_attr_t *),
+ (int (*)(const void *, const void *))_ppd_attr_compare);
+
+ if (match == NULL)
+ {
+ /*
+ * No match!
+ */
+
+ ppd->cur_attr = -1;
+ return (NULL);
+ }
+
+ if (match > ppd->attrs && spec == NULL)
+ {
+ /*
+ * Find the first attribute with the same name...
+ */
+
+ while (match > ppd->attrs)
+ {
+ if (strcmp(match[-1]->name, name) != 0)
+ break;
+
+ match --;
+ }
+ }
+
+ /*
+ * Save the current attribute and return its value...
+ */
+
+ ppd->cur_attr = match - ppd->attrs;
+
+ return (*match);
+}
+
+
+/*
+ * 'ppdFindNextAttr()' - Find the next matching attribute...
+ */
+
+ppd_attr_t * /* O - Attribute or NULL if not found */
+ppdFindNextAttr(ppd_file_t *ppd, /* I - PPD file data */
+ const char *name, /* I - Attribute name */
+ const char *spec) /* I - Specifier string or NULL */
+{
+ ppd_attr_t **match; /* Matching attribute */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (ppd == NULL || name == NULL || ppd->num_attrs == 0 || ppd->cur_attr < 0)
+ return (NULL);
+
+ /*
+ * See if there are more attributes to return...
+ */
+
+ ppd->cur_attr ++;
+
+ if (ppd->cur_attr >= ppd->num_attrs)
+ {
+ /*
+ * Nope...
+ */
+
+ ppd->cur_attr = -1;
+ return (NULL);
+ }
+
+ /*
+ * Check the next attribute to see if it is a match...
+ */
+
+ match = ppd->attrs + ppd->cur_attr;
+
+ if (strcmp((*match)->name, name) != 0 ||
+ (spec != NULL && strcmp((*match)->spec, spec) != 0))
+ {
+ /*
+ * Nope...
+ */
+
+ ppd->cur_attr = -1;
+ return (NULL);
+ }
+
+ /*
+ * Return the next attribute's value...
+ */
+
+ return (*match);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/auth.c b/cups/auth.c
new file mode 100644
index 000000000..cf0ed1669
--- /dev/null
+++ b/cups/auth.c
@@ -0,0 +1,249 @@
+/*
+ * "$Id$"
+ *
+ * Authentication functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsDoAuthentication() - Authenticate a request...
+ * cups_local_auth() - Get the local authorization certificate if
+ * available/applicable...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "ipp.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * Local functions...
+ */
+
+static int cups_local_auth(http_t *http);
+
+
+/*
+ * 'cupsDoAuthentication()' - Authenticate a request...
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsDoAuthentication(http_t *http, /* I - HTTP connection to server */
+ const char *method,/* I - Request method (GET, POST, PUT) */
+ const char *resource)
+ /* I - Resource path */
+{
+ const char *password; /* Password string */
+ char prompt[1024], /* Prompt for user */
+ realm[HTTP_MAX_VALUE], /* realm="xyz" string */
+ nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
+ encode[512]; /* Encoded username:password */
+
+
+ DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")\n",
+ http, method, resource));
+ DEBUG_printf(("cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"\n",
+ http->digest_tries, http->userpass));
+
+ /*
+ * Clear the current authentication string...
+ */
+
+ http->authstring[0] = '\0';
+
+ /*
+ * See if we can do local authentication...
+ */
+
+ if (!cups_local_auth(http))
+ {
+ DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring));
+ return (0);
+ }
+
+ /*
+ * Nope, see if we should retry the current username:password...
+ */
+
+ if (http->digest_tries > 1 || !http->userpass[0])
+ {
+ /*
+ * Nope - get a new password from the user...
+ */
+
+ snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(),
+ http->hostname);
+
+ http->digest_tries = strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE],
+ "Basic", 5) == 0;
+ http->userpass[0] = '\0';
+
+ if ((password = cupsGetPassword(prompt)) == NULL)
+ return (-1);
+
+ if (!password[0])
+ return (-1);
+
+ snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
+ password);
+ }
+ else if (http->status == HTTP_UNAUTHORIZED)
+ http->digest_tries ++;
+
+ /*
+ * Got a password; encode it for the server...
+ */
+
+ if (strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0)
+ {
+ /*
+ * Basic authentication...
+ */
+
+ httpEncode64(encode, http->userpass);
+ snprintf(http->authstring, sizeof(http->authstring), "Basic %s", encode);
+ }
+ else
+ {
+ /*
+ * Digest authentication...
+ */
+
+ httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
+ httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
+
+ httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
+ httpMD5Final(nonce, method, resource, encode);
+ snprintf(http->authstring, sizeof(http->authstring),
+ "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
+ "uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce,
+ resource, encode);
+ }
+
+ DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring));
+
+ return (0);
+}
+
+
+/*
+ * 'cups_local_auth()' - Get the local authorization certificate if
+ * available/applicable...
+ */
+
+static int /* O - 0 if available, -1 if not */
+cups_local_auth(http_t *http) /* I - HTTP connection to server */
+{
+#if defined(WIN32) || defined(__EMX__)
+ /*
+ * Currently WIN32 and OS-2 do not support the CUPS server...
+ */
+
+ return (-1);
+#else
+ int pid; /* Current process ID */
+ FILE *fp; /* Certificate file */
+ char filename[1024], /* Certificate filename */
+ certificate[33]; /* Certificate string */
+ const char *root; /* Server root directory */
+
+
+ DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%08x, hostname=\"%s\"\n",
+ http, ntohl(http->hostaddr.sin_addr.s_addr), http->hostname));
+
+ /*
+ * See if we are accessing localhost...
+ */
+
+ if (ntohl(http->hostaddr.sin_addr.s_addr) != 0x7f000001 &&
+ strcasecmp(http->hostname, "localhost") != 0)
+ {
+ DEBUG_puts("cups_local_auth: Not a local connection!");
+ return (-1);
+ }
+
+ /*
+ * Try opening a certificate file for this PID. If that fails,
+ * try the root certificate...
+ */
+
+ if ((root = getenv("CUPS_SERVERROOT")) == NULL)
+ root = CUPS_SERVERROOT;
+
+ pid = getpid();
+ snprintf(filename, sizeof(filename), "%s/certs/%d", root, pid);
+ if ((fp = fopen(filename, "r")) == NULL && pid > 0)
+ {
+ DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n",
+ filename, strerror(errno)));
+
+ snprintf(filename, sizeof(filename), "%s/certs/0", root);
+ fp = fopen(filename, "r");
+ }
+
+ if (fp == NULL)
+ {
+ DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n",
+ filename, strerror(errno)));
+ return (-1);
+ }
+
+ /*
+ * Read the certificate from the file...
+ */
+
+ fgets(certificate, sizeof(certificate), fp);
+ fclose(fp);
+
+ /*
+ * Set the authorization string and return...
+ */
+
+ snprintf(http->authstring, sizeof(http->authstring), "Local %s", certificate);
+
+ DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n",
+ http->authstring));
+
+ return (0);
+#endif /* WIN32 || __EMX__ */
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/cups.dsp b/cups/cups.dsp
new file mode 100644
index 000000000..496ec30f8
--- /dev/null
+++ b/cups/cups.dsp
@@ -0,0 +1,220 @@
+# Microsoft Developer Studio Project File - Name="cups" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=cups - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cups.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cups.mak" CFG="cups - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cups - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "cups - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cups - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../visualc" /I ".." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"cups.lib"
+
+!ELSEIF "$(CFG)" == "cups - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../visualc" /I ".." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"cupsd.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "cups - Win32 Release"
+# Name "cups - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\auth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dest.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\emit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\encode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getputfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\http-addr.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\http-support.c"
+# End Source File
+# Begin Source File
+
+SOURCE=.\http.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\ipp-support.c"
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\language.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mark.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5passwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\page.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ppd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tempfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\usersys.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\util.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\cups.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cups_C.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\debug.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\http.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\language.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\oemlicense\license.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ppd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\string.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/cups/cups.h b/cups/cups.h
new file mode 100644
index 000000000..350345548
--- /dev/null
+++ b/cups/cups.h
@@ -0,0 +1,211 @@
+/*
+ * "$Id$"
+ *
+ * API definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_CUPS_H_
+# define _CUPS_CUPS_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include "ipp.h"
+# include "ppd.h"
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
+ * Constants...
+ */
+
+# define CUPS_VERSION 1.0123
+# define CUPS_VERSION_MAJOR 1
+# define CUPS_VERSION_MINOR 1
+# define CUPS_VERSION_PATCH 23
+# define CUPS_DATE_ANY -1
+
+
+/*
+ * Types and structures...
+ */
+
+typedef unsigned cups_ptype_t; /**** Printer Type/Capability Bits ****/
+enum /* Not a typedef'd enum so we can OR */
+{
+ CUPS_PRINTER_LOCAL = 0x0000, /* Local printer or class */
+ CUPS_PRINTER_CLASS = 0x0001, /* Printer class */
+ CUPS_PRINTER_REMOTE = 0x0002, /* Remote printer or class */
+ CUPS_PRINTER_BW = 0x0004, /* Can do B&W printing */
+ CUPS_PRINTER_COLOR = 0x0008, /* Can do color printing */
+ CUPS_PRINTER_DUPLEX = 0x0010, /* Can do duplexing */
+ CUPS_PRINTER_STAPLE = 0x0020, /* Can staple output */
+ CUPS_PRINTER_COPIES = 0x0040, /* Can do copies */
+ CUPS_PRINTER_COLLATE = 0x0080, /* Can collage copies */
+ CUPS_PRINTER_PUNCH = 0x0100, /* Can punch output */
+ CUPS_PRINTER_COVER = 0x0200, /* Can cover output */
+ CUPS_PRINTER_BIND = 0x0400, /* Can bind output */
+ CUPS_PRINTER_SORT = 0x0800, /* Can sort output */
+ CUPS_PRINTER_SMALL = 0x1000, /* Can do Letter/Legal/A4 */
+ CUPS_PRINTER_MEDIUM = 0x2000, /* Can do Tabloid/B/C/A3/A2 */
+ CUPS_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */
+ CUPS_PRINTER_VARIABLE = 0x8000, /* Can do variable sizes */
+ CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class */
+ CUPS_PRINTER_DEFAULT = 0x20000, /* Default printer on network */
+ CUPS_PRINTER_FAX = 0x40000, /* Fax queue */
+ CUPS_PRINTER_REJECTING = 0x80000, /* Printer is rejecting jobs */
+ CUPS_PRINTER_OPTIONS = 0x6fffc /* ~(CLASS | REMOTE | IMPLICIT) */
+};
+
+typedef struct /**** Printer Options ****/
+{
+ char *name; /* Name of option */
+ char *value; /* Value of option */
+} cups_option_t;
+
+typedef struct /**** Destination ****/
+{
+ char *name, /* Printer or class name */
+ *instance; /* Local instance name or NULL */
+ int is_default; /* Is this printer the default? */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+} cups_dest_t;
+
+typedef struct /**** Job ****/
+{
+ int id; /* The job ID */
+ char *dest, /* Printer or class name */
+ *title, /* Title/job name */
+ *user, /* User the submitted the job */
+ *format; /* Document format */
+ ipp_jstate_t state; /* Job state */
+ int size, /* Size in kilobytes */
+ priority; /* Priority (1-100) */
+ time_t completed_time, /* Time the job was completed */
+ creation_time, /* Time the job was created */
+ processing_time; /* Time the job was processed */
+} cups_job_t;
+
+
+/*
+ * Functions...
+ */
+
+extern int cupsCancelJob(const char *printer, int job);
+#define cupsDoRequest(http,request,resource) cupsDoFileRequest((http),(request),(resource),NULL)
+extern ipp_t *cupsDoFileRequest(http_t *http, ipp_t *request,
+ const char *resource, const char *filename);
+extern http_encryption_t cupsEncryption(void);
+extern void cupsFreeJobs(int num_jobs, cups_job_t *jobs);
+extern int cupsGetClasses(char ***classes);
+extern const char *cupsGetDefault(void);
+extern int cupsGetJobs(cups_job_t **jobs, const char *dest,
+ int myjobs, int completed);
+extern const char *cupsGetPPD(const char *printer);
+extern int cupsGetPrinters(char ***printers);
+extern ipp_status_t cupsLastError(void);
+extern int cupsPrintFile(const char *printer, const char *filename,
+ const char *title, int num_options,
+ cups_option_t *options);
+extern int cupsPrintFiles(const char *printer, int num_files,
+ const char **files, const char *title,
+ int num_options, cups_option_t *options);
+extern char *cupsTempFile(char *filename, int len);
+extern int cupsTempFd(char *filename, int len);
+
+extern int cupsAddDest(const char *name, const char *instance,
+ int num_dests, cups_dest_t **dests);
+extern void cupsFreeDests(int num_dests, cups_dest_t *dests);
+extern cups_dest_t *cupsGetDest(const char *name, const char *instance,
+ int num_dests, cups_dest_t *dests);
+extern int cupsGetDests(cups_dest_t **dests);
+extern void cupsSetDests(int num_dests, cups_dest_t *dests);
+
+extern int cupsAddOption(const char *name, const char *value,
+ int num_options, cups_option_t **options);
+extern void cupsEncodeOptions(ipp_t *ipp, int num_options,
+ cups_option_t *options);
+extern void cupsFreeOptions(int num_options, cups_option_t *options);
+extern const char *cupsGetOption(const char *name, int num_options,
+ cups_option_t *options);
+extern int cupsParseOptions(const char *arg, int num_options,
+ cups_option_t **options);
+extern int cupsMarkOptions(ppd_file_t *ppd, int num_options,
+ cups_option_t *options);
+
+extern const char *cupsGetPassword(const char *prompt);
+extern const char *cupsServer(void);
+extern void cupsSetEncryption(http_encryption_t e);
+extern void cupsSetPasswordCB(const char *(*cb)(const char *));
+extern void cupsSetServer(const char *server);
+extern void cupsSetUser(const char *user);
+extern const char *cupsUser(void);
+
+/**** New in CUPS 1.1.20 ****/
+extern int cupsDoAuthentication(http_t *http, const char *method,
+ const char *resource);
+extern http_status_t cupsGetFile(http_t *http, const char *resource,
+ const char *filename);
+extern http_status_t cupsGetFd(http_t *http, const char *resource, int fd);
+extern http_status_t cupsPutFile(http_t *http, const char *resource,
+ const char *filename);
+extern http_status_t cupsPutFd(http_t *http, const char *resource, int fd);
+
+/**** New in CUPS 1.1.21 ****/
+extern const char *cupsGetDefault2(http_t *http);
+extern int cupsGetDests2(http_t *http, cups_dest_t **dests);
+extern int cupsGetJobs2(http_t *http, cups_job_t **jobs,
+ const char *dest, int myjobs,
+ int completed);
+extern const char *cupsGetPPD2(http_t *http, const char *printer);
+extern int cupsPrintFile2(http_t *http, const char *printer,
+ const char *filename,
+ const char *title, int num_options,
+ cups_option_t *options);
+extern int cupsPrintFiles2(http_t *http, const char *printer,
+ int num_files, const char **files,
+ const char *title, int num_options,
+ cups_option_t *options);
+extern int cupsSetDests2(http_t *http, int num_dests,
+ cups_dest_t *dests);
+
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+
+#endif /* !_CUPS_CUPS_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/cups.vcproj b/cups/cups.vcproj
new file mode 100644
index 000000000..bcf637ba0
--- /dev/null
+++ b/cups/cups.vcproj
@@ -0,0 +1,601 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="cups"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../visualc,.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/cups.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="cups.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../visualc,.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/cups.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="3"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="cupsd.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="auth.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dest.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="emit.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="encode.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="getputfile.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="http-addr.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="http-support.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="http.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ipp-support.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ipp.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="language.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mark.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="md5.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="md5passwd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="options.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="page.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ppd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="snprintf.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="string.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tempfile.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="usersys.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="util.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="cups.h">
+ </File>
+ <File
+ RelativePath="cups_C.h">
+ </File>
+ <File
+ RelativePath="debug.h">
+ </File>
+ <File
+ RelativePath="http.h">
+ </File>
+ <File
+ RelativePath="ipp.h">
+ </File>
+ <File
+ RelativePath="language.h">
+ </File>
+ <File
+ RelativePath="..\oemlicense\license.h">
+ </File>
+ <File
+ RelativePath="md5.h">
+ </File>
+ <File
+ RelativePath="ppd.h">
+ </File>
+ <File
+ RelativePath="string.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/cups/cups_C.h b/cups/cups_C.h
new file mode 100644
index 000000000..1f4716f16
--- /dev/null
+++ b/cups/cups_C.h
@@ -0,0 +1,135 @@
+"iso-8859-1",
+"OK",
+"Cancel",
+"Help",
+"Quit",
+"Close",
+"Yes",
+"No",
+"On",
+"Off",
+"Save",
+"Discard",
+"Default",
+"Options",
+"More Info",
+"Black",
+"Color",
+"Cyan",
+"Magenta",
+"Yellow",
+"Copyright 1993-2004 by Easy Software Products, All Rights Reserved.",
+"General",
+"Printer",
+"Image",
+"HP-GL/2",
+"Extra",
+"Document",
+"Other",
+"Print Pages: ",
+"Entire Document",
+"Page Range:",
+"Reverse Order: ",
+"Page Format: ",
+" 1-Up",
+" 2-Up",
+" 4-Up",
+"Image Scaling: ",
+"Use Natural Image Size",
+"Zoom by Percent",
+"Zoom by PPI",
+"Mirror Image: ",
+"Color Saturation: ",
+"Color Hue: ",
+"Fit to Page: ",
+"Shading: ",
+"Pen Width: ",
+"Gamma Correction: ",
+"Brightness: ",
+"Add",
+"Delete",
+"Modify",
+"Printer URI",
+"Printer Name",
+"Printer Location",
+"Printer Info",
+"Printer Make and Model",
+"Device URI",
+"Formatting Page",
+"Printing Page",
+"Initializing Printer",
+"Printer State",
+"Accepting Jobs",
+"Not Accepting Jobs",
+"Print Jobs",
+"Class",
+"Local",
+"Remote",
+"Duplexing",
+"Stapling",
+"Fast Copies",
+"Collated Copies",
+"Hole Punching",
+"Covering",
+"Binding",
+"Sorting",
+"Small (up to 9.5x14in)",
+"Medium (9.5x14in to 13x19in)",
+"Large (13x19in and larger)",
+"Custom Size",
+"Idle",
+"Processing",
+"Stopped",
+"All",
+"Odd",
+"Even",
+"Darker Lighter",
+"Media Size",
+"Media Type",
+"Media Source",
+"Orientation: ",
+"Portrait",
+"Landscape",
+"Job State",
+"Job Name",
+"User Name",
+"Priority",
+"Copies",
+"File Size",
+"Pending",
+"Output Mode",
+"Resolution",
+"Text",
+"Pretty Print",
+"Margins",
+"Left",
+"Right",
+"Bottom",
+"Top",
+"Filename(s)",
+"Print",
+"Options Installed",
+"Auto",
+"400 Your browser sent a request that this server could not understand.",
+"This server could not verify that you are authorized to access the resource.",
+"You must pay to access this server.",
+"You don't have permission to access the resource on this server.",
+"The requested resource was not found on this server.",
+"The requested method is not allowed with the resource.",
+"An appropriate representation for the resource was not found on this server.",
+"You don't have permission to use this server as a proxy host.",
+"The request has taken too long to complete and has been aborted.",
+"The requested resource has more than one value.",
+"The requested resource is gone and has not been replaced.",
+"The requested method requires a valid Content-Length.",
+"The precondition on the request evaluated to false.",
+"The request is too large for this server to process.",
+"The request URI is too large for this server to process.",
+"The request format is not understood by this server.",
+"426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.",
+"500 The server has detected an unrecoverable error and cannot process your request.",
+"The requested method is not implemented by this server.",
+"The proxy server received an invalid response from an upstream server.",
+"The requested resource is currently unavailable on this server.",
+"The proxy server has taken too long to respond to this server.",
+"This server does not support the HTTP version required by your browser.",
diff --git a/cups/cupsdll.def b/cups/cupsdll.def
new file mode 100644
index 000000000..f533f84a2
--- /dev/null
+++ b/cups/cupsdll.def
@@ -0,0 +1,136 @@
+cupsAddDest
+cupsAddOption
+cupsCancelJob
+cupsDoAuthentication
+cupsDoFileRequest
+cupsEncodeOptions
+cupsEncryption
+cupsFreeDests
+cupsFreeJobs
+cupsFreeOptions
+cupsGetClasses
+cupsGetDefault
+cupsGetDest
+cupsGetDests
+cupsGetFd
+cupsGetFile
+cupsGetJobs
+cupsGetOption
+cupsGetPassword
+cupsGetPPD
+cupsGetPrinters
+cupsLangEncoding
+cupsLangFlush
+cupsLangFree
+cupsLangGet
+cupsLastError
+cupsMarkOptions
+cupsParseOptions
+cupsPrintFile
+cupsPrintFiles
+cupsPutFd
+cupsPutFile
+cupsServer
+cupsSetDests
+cupsSetEncryption
+cupsSetPasswordCB
+cupsSetServer
+cupsSetUser
+cupsTempFd
+cupsTempFile
+cupsUser
+httpCheck
+httpClearCookie
+httpClose
+httpConnect
+httpConnectEncrypt
+httpDecode64
+httpDelete
+httpEncode64
+httpEncryption
+httpFlush
+httpGet
+httpGetDateString
+httpGetDateTime
+httpGetHostByName
+httpGetLength
+httpGets
+httpGetSubField
+httpHead
+httpInitialize
+httpMD5
+httpMD5Final
+httpMD5String
+httpOptions
+httpPost
+httpPrintf
+httpPut
+httpRead
+httpReconnect
+httpSeparate
+httpSetCookie
+httpSetField
+httpStatus
+httpTrace
+httpUpdate
+httpWait
+httpWrite
+_ipp_add_attr
+ippAddBoolean
+ippAddBooleans
+ippAddCollection
+ippAddCollections
+ippAddDate
+ippAddInteger
+ippAddIntegers
+ippAddRange
+ippAddRanges
+ippAddResolution
+ippAddResolutions
+ippAddSeparator
+ippAddString
+ippAddStrings
+ippDateToTime
+ippDelete
+ippDeleteAttribute
+ippErrorString
+ippFindAttribute
+ippFindNextAttribute
+_ipp_free_attr
+ippLength
+ippNew
+ippPort
+ippRead
+ippReadFile
+ippReadIO
+ippSetPort
+ippTimeToDate
+ippWrite
+ippWriteFile
+ippWriteIO
+md5_append
+md5_finish
+md5_init
+ppdClose
+ppdCollect
+ppdConflicts
+ppdEmit
+ppdEmitFd
+ppdEmitJCL
+ppdErrorString
+ppdFindAttr
+ppdFindChoice
+ppdFindMarkedChoice
+ppdFindNextAttr
+ppdFindOption
+ppdIsMarked
+ppdLastError
+ppdMarkDefaults
+ppdMarkOption
+ppdOpen
+ppdOpenFd
+ppdOpenFile
+ppdPageLength
+ppdPageSize
+ppdPageWidth
+ppdSetConformance
diff --git a/cups/debug.h b/cups/debug.h
new file mode 100644
index 000000000..3091010cc
--- /dev/null
+++ b/cups/debug.h
@@ -0,0 +1,59 @@
+/*
+ * "$Id$"
+ *
+ * Debugging macros for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_DEBUG_H_
+# define _CUPS_DEBUG_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <stdio.h>
+
+/*
+ * The debug macros are used if you compile with DEBUG defined.
+ *
+ * Usage:
+ *
+ * DEBUG_puts("string")
+ * DEBUG_printf(("format string", arg, arg, ...));
+ *
+ * Note the extra parenthesis around the DEBUG_printf macro...
+ */
+
+# ifdef DEBUG
+# define DEBUG_puts(x) puts(x)
+# define DEBUG_printf(x) printf x
+# else
+# define DEBUG_puts(x)
+# define DEBUG_printf(x)
+# endif /* DEBUG */
+
+#endif /* !_CUPS_DEBUG_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/dest.c b/cups/dest.c
new file mode 100644
index 000000000..6bc7433c7
--- /dev/null
+++ b/cups/dest.c
@@ -0,0 +1,856 @@
+/*
+ * "$Id$"
+ *
+ * User-defined destination (and option) support for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsAddDest() - Add a destination to the list of destinations.
+ * cupsFreeDests() - Free the memory used by the list of destinations.
+ * cupsGetDest() - Get the named destination from the list.
+ * cupsGetDests() - Get the list of destinations.
+ * cupsGetDests2() - Get the list of destinations using a HTTP connection.
+ * cupsSetDests() - Set the list of destinations.
+ * cups_get_dests() - Get destinations from a file.
+ * cups_get_sdests() - Get destinations from a server.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "language.h"
+#include "string.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int cups_get_dests(const char *filename, int num_dests,
+ cups_dest_t **dests);
+static int cups_get_sdests(http_t *http, ipp_op_t op, int num_dests,
+ cups_dest_t **dests);
+
+
+/*
+ * 'cupsAddDest()' - Add a destination to the list of destinations.
+ */
+
+int /* O - New number of destinations */
+cupsAddDest(const char *name, /* I - Name of destination */
+ const char *instance, /* I - Instance of destination */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
+{
+ int i; /* Looping var */
+ cups_dest_t *dest; /* Destination pointer */
+
+
+ if (name == NULL || dests == NULL)
+ return (0);
+
+ if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+ return (num_dests);
+
+ /*
+ * Add new destination...
+ */
+
+ if (num_dests == 0)
+ dest = malloc(sizeof(cups_dest_t));
+ else
+ dest = realloc(*dests, sizeof(cups_dest_t) * (num_dests + 1));
+
+ if (dest == NULL)
+ return (num_dests);
+
+ *dests = dest;
+
+ for (i = num_dests; i > 0; i --, dest ++)
+ if (strcasecmp(name, dest->name) < 0)
+ break;
+ else if (strcasecmp(name, dest->name) == 0 &&
+ instance != NULL && dest->instance != NULL &&
+ strcasecmp(instance, dest->instance) < 0)
+ break;
+
+ if (i > 0)
+ memmove(dest + 1, dest, i * sizeof(cups_dest_t));
+
+ dest->name = strdup(name);
+ dest->is_default = 0;
+ dest->num_options = 0;
+ dest->options = (cups_option_t *)0;
+
+ if (instance == NULL)
+ dest->instance = NULL;
+ else
+ dest->instance = strdup(instance);
+
+ return (num_dests + 1);
+}
+
+
+/*
+ * 'cupsFreeDests()' - Free the memory used by the list of destinations.
+ */
+
+void
+cupsFreeDests(int num_dests, /* I - Number of destinations */
+ cups_dest_t *dests) /* I - Destinations */
+{
+ int i; /* Looping var */
+ cups_dest_t *dest; /* Current destination */
+
+
+ if (num_dests == 0 || dests == NULL)
+ return;
+
+ for (i = num_dests, dest = dests; i > 0; i --, dest ++)
+ {
+ free(dest->name);
+
+ if (dest->instance)
+ free(dest->instance);
+
+ cupsFreeOptions(dest->num_options, dest->options);
+ }
+
+ free(dests);
+}
+
+
+/*
+ * 'cupsGetDest()' - Get the named destination from the list.
+ */
+
+cups_dest_t * /* O - Destination pointer or NULL */
+cupsGetDest(const char *name, /* I - Name of destination */
+ const char *instance, /* I - Instance of destination */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t *dests) /* I - Destinations */
+{
+ int comp; /* Result of comparison */
+
+
+ if (num_dests == 0 || dests == NULL)
+ return (NULL);
+
+ if (name == NULL)
+ {
+ /*
+ * NULL name for default printer.
+ */
+
+ while (num_dests > 0)
+ {
+ if (dests->is_default)
+ return (dests);
+
+ num_dests --;
+ dests ++;
+ }
+ }
+ else
+ {
+ /*
+ * Lookup name and optionally the instance...
+ */
+
+ while (num_dests > 0)
+ {
+ if ((comp = strcasecmp(name, dests->name)) < 0)
+ return (NULL);
+ else if (comp == 0)
+ {
+ if ((instance == NULL && dests->instance == NULL) ||
+ (instance != NULL && dests->instance != NULL &&
+ strcasecmp(instance, dests->instance) == 0))
+ return (dests);
+ }
+
+ num_dests --;
+ dests ++;
+ }
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'cupsGetDests()' - Get the list of destinations.
+ */
+
+int /* O - Number of destinations */
+cupsGetDests(cups_dest_t **dests) /* O - Destinations */
+{
+ int num_dests; /* Number of destinations */
+ http_t *http; /* HTTP connection */
+
+
+ /*
+ * Connect to the CUPS server and get the destination list and options...
+ */
+
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ num_dests = cupsGetDests2(http, dests);
+
+ if (http)
+ httpClose(http);
+
+ return (num_dests);
+}
+
+
+/*
+ * 'cupsGetDests2()' - Get the list of destinations.
+ */
+
+int /* O - Number of destinations */
+cupsGetDests2(http_t *http, /* I - HTTP connection */
+ cups_dest_t **dests) /* O - Destinations */
+{
+ int i; /* Looping var */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dest; /* Destination pointer */
+ const char *home; /* HOME environment variable */
+ char filename[1024]; /* Local ~/.lpoptions file */
+ const char *defprinter; /* Default printer */
+ char name[1024], /* Copy of printer name */
+ *instance; /* Pointer to instance name */
+ int num_reals; /* Number of real queues */
+ cups_dest_t *reals; /* Real queues */
+
+
+ /*
+ * Range check the input...
+ */
+
+ if (!http || !dests)
+ return (0);
+
+ /*
+ * Initialize destination array...
+ */
+
+ num_dests = 0;
+ *dests = (cups_dest_t *)0;
+
+ /*
+ * Grab the printers and classes...
+ */
+
+ num_dests = cups_get_sdests(http, CUPS_GET_PRINTERS, num_dests, dests);
+ num_dests = cups_get_sdests(http, CUPS_GET_CLASSES, num_dests, dests);
+
+ /*
+ * Make a copy of the "real" queues for a later sanity check...
+ */
+
+ if (num_dests > 0)
+ {
+ num_reals = num_dests;
+ reals = calloc(num_reals, sizeof(cups_dest_t));
+
+ if (reals)
+ memcpy(reals, *dests, num_reals * sizeof(cups_dest_t));
+ else
+ num_reals = 0;
+ }
+ else
+ {
+ num_reals = 0;
+ reals = NULL;
+ }
+
+ /*
+ * Grab the default destination...
+ */
+
+ if ((defprinter = cupsGetDefault2(http)) != NULL)
+ {
+ /*
+ * Grab printer and instance name...
+ */
+
+ strlcpy(name, defprinter, sizeof(name));
+
+ if ((instance = strchr(name, '/')) != NULL)
+ *instance++ = '\0';
+
+ /*
+ * Lookup the printer and instance and make it the default...
+ */
+
+ if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+ dest->is_default = 1;
+ }
+ else
+ {
+ /*
+ * This initialization of "instance" is unnecessary, but avoids a
+ * compiler warning...
+ */
+
+ instance = NULL;
+ }
+
+ /*
+ * Load the /etc/cups/lpoptions and ~/.lpoptions files...
+ */
+
+ if ((home = getenv("CUPS_SERVERROOT")) != NULL)
+ {
+ snprintf(filename, sizeof(filename), "%s/lpoptions", home);
+ num_dests = cups_get_dests(filename, num_dests, dests);
+ }
+ else
+ num_dests = cups_get_dests(CUPS_SERVERROOT "/lpoptions", num_dests, dests);
+
+ if ((home = getenv("HOME")) != NULL)
+ {
+ snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
+ num_dests = cups_get_dests(filename, num_dests, dests);
+ }
+
+ /*
+ * Validate the current default destination - this prevents old
+ * Default lines in /etc/cups/lpoptions and ~/.lpoptions from
+ * pointing to a non-existent printer or class...
+ */
+
+ if (num_reals)
+ {
+ /*
+ * See if we have a default printer...
+ */
+
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, *dests)) != NULL)
+ {
+ /*
+ * Have a default; see if it is real...
+ */
+
+ dest = cupsGetDest(dest->name, NULL, num_reals, reals);
+ }
+
+ /*
+ * If dest is NULL, then no default (that exists) is set, so we
+ * need to set a default if one exists...
+ */
+
+ if (dest == NULL && defprinter != NULL)
+ {
+ for (i = 0; i < num_dests; i ++)
+ (*dests)[i].is_default = 0;
+
+ if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+ dest->is_default = 1;
+ }
+
+ /*
+ * Free memory...
+ */
+
+ free(reals);
+ }
+
+ /*
+ * Return the number of destinations...
+ */
+
+ return (num_dests);
+}
+
+
+/*
+ * 'cupsSetDests()' - Set the list of destinations.
+ */
+
+void
+cupsSetDests(int num_dests, /* I - Number of destinations */
+ cups_dest_t *dests) /* I - Destinations */
+{
+ http_t *http; /* HTTP connection */
+
+
+ /*
+ * Connect to the CUPS server and save the destination list and options...
+ */
+
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ cupsSetDests2(http, num_dests, dests);
+
+ if (http)
+ httpClose(http);
+}
+
+
+/*
+ * 'cupsSetDests()' - Set the list of destinations.
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsSetDests2(http_t *http, /* I - HTTP connection */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t *dests) /* I - Destinations */
+{
+ int i, j; /* Looping vars */
+ int wrote; /* Wrote definition? */
+ cups_dest_t *dest; /* Current destination */
+ cups_option_t *option; /* Current option */
+ FILE *fp; /* File pointer */
+ const char *home; /* HOME environment variable */
+ char filename[1024]; /* lpoptions file */
+ int num_temps; /* Number of temporary destinations */
+ cups_dest_t *temps, /* Temporary destinations */
+ *temp; /* Current temporary dest */
+ const char *val; /* Value of temporary option */
+
+
+ /*
+ * Range check the input...
+ */
+
+ if (!http || !num_dests || !dests)
+ return (-1);
+
+ /*
+ * Get the server destinations...
+ */
+
+ num_temps = cups_get_sdests(http, CUPS_GET_PRINTERS, 0, &temps);
+ num_temps = cups_get_sdests(http, CUPS_GET_CLASSES, num_temps, &temps);
+
+ /*
+ * Figure out which file to write to...
+ */
+
+ if ((home = getenv("CUPS_SERVERROOT")) != NULL)
+ snprintf(filename, sizeof(filename), "%s/lpoptions", home);
+ else
+ strcpy(filename, CUPS_SERVERROOT "/lpoptions");
+
+#ifndef WIN32
+ if (getuid())
+ {
+ /*
+ * Merge in server defaults...
+ */
+
+ num_temps = cups_get_dests(filename, num_temps, &temps);
+
+ /*
+ * Point to user defaults...
+ */
+
+ if ((home = getenv("HOME")) != NULL)
+ snprintf(filename, sizeof(filename), "%s/.lpoptions", home);
+ }
+#endif /* !WIN32 */
+
+ /*
+ * Try to open the file...
+ */
+
+ if ((fp = fopen(filename, "w")) == NULL)
+ {
+ cupsFreeDests(num_temps, temps);
+ return (-1);
+ }
+
+ /*
+ * Write each printer; each line looks like:
+ *
+ * Dest name[/instance] options
+ * Default name[/instance] options
+ */
+
+ for (i = num_dests, dest = dests; i > 0; i --, dest ++)
+ if (dest->instance != NULL || dest->num_options != 0 || dest->is_default)
+ {
+ if (dest->is_default)
+ {
+ fprintf(fp, "Default %s", dest->name);
+ if (dest->instance)
+ fprintf(fp, "/%s", dest->instance);
+
+ wrote = 1;
+ }
+ else
+ wrote = 0;
+
+ if ((temp = cupsGetDest(dest->name, dest->instance, num_temps, temps)) == NULL)
+ temp = cupsGetDest(dest->name, NULL, num_temps, temps);
+
+ for (j = dest->num_options, option = dest->options; j > 0; j --, option ++)
+ {
+ /*
+ * See if the server/global options match these; if so, don't
+ * write 'em.
+ */
+
+ if (temp && (val = cupsGetOption(option->name, temp->num_options,
+ temp->options)) != NULL)
+ {
+ if (strcasecmp(val, option->value) == 0)
+ continue;
+ }
+
+ /*
+ * Options don't match, write to the file...
+ */
+
+ if (!wrote)
+ {
+ fprintf(fp, "Dest %s", dest->name);
+ if (dest->instance)
+ fprintf(fp, "/%s", dest->instance);
+ wrote = 1;
+ }
+
+ if (option->value[0])
+ {
+ if (strchr(option->value, ' ') != NULL)
+ fprintf(fp, " %s=\"%s\"", option->name, option->value);
+ else
+ fprintf(fp, " %s=%s", option->name, option->value);
+ }
+ else
+ fprintf(fp, " %s", option->name);
+ }
+
+ if (wrote)
+ fputs("\n", fp);
+ }
+
+ /*
+ * Free the temporary destinations...
+ */
+
+ cupsFreeDests(num_temps, temps);
+
+ /*
+ * Close the file and return...
+ */
+
+ fclose(fp);
+
+ return (0);
+}
+
+
+/*
+ * 'cups_get_dests()' - Get destinations from a file.
+ */
+
+static int /* O - Number of destinations */
+cups_get_dests(const char *filename, /* I - File to read from */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
+{
+ int i; /* Looping var */
+ cups_dest_t *dest; /* Current destination */
+ FILE *fp; /* File pointer */
+ char line[8192], /* Line from file */
+ *lineptr, /* Pointer into line */
+ *name, /* Name of destination/option */
+ *instance; /* Instance of destination */
+ const char *printer; /* PRINTER or LPDEST */
+
+
+ /*
+ * Check environment variables...
+ */
+
+ if ((printer = getenv("LPDEST")) == NULL)
+ if ((printer = getenv("PRINTER")) != NULL)
+ if (strcmp(printer, "lp") == 0)
+ printer = NULL;
+
+ /*
+ * Try to open the file...
+ */
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ return (num_dests);
+
+ /*
+ * Read each printer; each line looks like:
+ *
+ * Dest name[/instance] options
+ * Default name[/instance] options
+ */
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * See what type of line it is...
+ */
+
+ if (strncasecmp(line, "dest", 4) == 0 && isspace(line[4] & 255))
+ lineptr = line + 4;
+ else if (strncasecmp(line, "default", 7) == 0 && isspace(line[7] & 255))
+ lineptr = line + 7;
+ else
+ continue;
+
+ /*
+ * Skip leading whitespace...
+ */
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ if (!*lineptr)
+ continue;
+
+ name = lineptr;
+
+ /*
+ * Search for an instance...
+ */
+
+ while (!isspace(*lineptr & 255) && *lineptr && *lineptr != '/')
+ lineptr ++;
+
+ if (!*lineptr)
+ continue;
+
+ if (*lineptr == '/')
+ {
+ /*
+ * Found an instance...
+ */
+
+ *lineptr++ = '\0';
+ instance = lineptr;
+
+ /*
+ * Search for an instance...
+ */
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+ }
+ else
+ instance = NULL;
+
+ *lineptr++ = '\0';
+
+ /*
+ * See if the primary instance of the destination exists; if not,
+ * ignore this entry and move on...
+ */
+
+ if (cupsGetDest(name, NULL, num_dests, *dests) == NULL)
+ continue;
+
+ /*
+ * Add the destination...
+ */
+
+ num_dests = cupsAddDest(name, instance, num_dests, dests);
+
+ if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL)
+ {
+ /*
+ * Out of memory!
+ */
+
+ fclose(fp);
+ return (num_dests);
+ }
+
+ /*
+ * Add options until we hit the end of the line...
+ */
+
+ dest->num_options = cupsParseOptions(lineptr, dest->num_options,
+ &(dest->options));
+
+ /*
+ * Set this as default if needed...
+ */
+
+ if (strncasecmp(line, "default", 7) == 0 && printer == NULL)
+ {
+ for (i = 0; i < num_dests; i ++)
+ (*dests)[i].is_default = 0;
+
+ dest->is_default = 1;
+ }
+ }
+
+ /*
+ * Close the file and return...
+ */
+
+ fclose(fp);
+
+ return (num_dests);
+}
+
+
+/*
+ * 'cups_get_sdests()' - Get destinations from a server.
+ */
+
+static int /* O - Number of destinations */
+cups_get_sdests(http_t *http, /* I - HTTP connection */
+ ipp_op_t op, /* I - get-printers or get-classes */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
+{
+ cups_dest_t *dest; /* Current destination */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *name; /* printer-name attribute */
+ char job_sheets[1024]; /* job-sheets option */
+ static const char * const pattrs[] = /* Attributes we're interested in */
+ {
+ "printer-name",
+ "job-sheets-default"
+ };
+
+
+ /*
+ * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which require
+ * the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a printer...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ name = NULL;
+
+ strcpy(job_sheets, "");
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ name = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "job-sheets-default") == 0 &&
+ (attr->value_tag == IPP_TAG_KEYWORD ||
+ attr->value_tag == IPP_TAG_NAME))
+ {
+ if (attr->num_values == 2)
+ snprintf(job_sheets, sizeof(job_sheets), "%s,%s",
+ attr->values[0].string.text, attr->values[1].string.text);
+ else
+ strcpy(job_sheets, attr->values[0].string.text);
+ }
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (!name)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ num_dests = cupsAddDest(name, NULL, num_dests, dests);
+
+ if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL)
+ if (job_sheets[0])
+ dest->num_options = cupsAddOption("job-sheets", job_sheets, 0,
+ &(dest->options));
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Return the count...
+ */
+
+ return (num_dests);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/emit.c b/cups/emit.c
new file mode 100644
index 000000000..1d9951c28
--- /dev/null
+++ b/cups/emit.c
@@ -0,0 +1,756 @@
+/*
+ * "$Id$"
+ *
+ * PPD code emission routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ppdCollect() - Collect all marked options that reside in the
+ * specified section.
+ * ppdEmit() - Emit code for marked options to a file.
+ * ppdEmitFd() - Emit code for marked options to a file.
+ * ppdEmitJCL() - Emit code for JCL options to a file.
+ * ppd_handle_media() - Handle media selection...
+ * ppd_sort() - Sort options by ordering numbers...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ppd.h"
+#include <stdlib.h>
+#include "string.h"
+
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * Local functions...
+ */
+
+static void ppd_handle_media(ppd_file_t *ppd);
+static int ppd_sort(ppd_choice_t **c1, ppd_choice_t **c2);
+
+
+/*
+ * Local globals...
+ */
+
+static const char *ppd_custom_code =
+ "pop pop pop\n"
+ "<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n";
+
+
+/*
+ * 'ppdCollect()' - Collect all marked options that reside in the specified
+ * section.
+ */
+
+int /* O - Number of options marked */
+ppdCollect(ppd_file_t *ppd, /* I - PPD file data */
+ ppd_section_t section, /* I - Section to collect */
+ ppd_choice_t ***choices) /* O - Pointers to choices */
+{
+ int i, j, k, m; /* Looping vars */
+ ppd_group_t *g, /* Current group */
+ *sg; /* Current sub-group */
+ ppd_option_t *o; /* Current option */
+ ppd_choice_t *c; /* Current choice */
+ int count; /* Number of choices collected */
+ ppd_choice_t **collect; /* Collected choices */
+
+
+ if (ppd == NULL)
+ return (0);
+
+ /*
+ * Allocate memory for up to 1000 selected choices...
+ */
+
+ count = 0;
+ collect = calloc(sizeof(ppd_choice_t *), 1000);
+
+ /*
+ * Loop through all options and add choices as needed...
+ */
+
+ for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
+ {
+ for (j = g->num_options, o = g->options; j > 0; j --, o ++)
+ if (o->section == section)
+ for (k = o->num_choices, c = o->choices; k > 0; k --, c ++)
+ if (c->marked && count < 1000)
+ {
+ collect[count] = c;
+ count ++;
+ }
+
+ for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
+ for (k = sg->num_options, o = sg->options; k > 0; k --, o ++)
+ if (o->section == section)
+ for (m = o->num_choices, c = o->choices; m > 0; m --, c ++)
+ if (c->marked && count < 1000)
+ {
+ collect[count] = c;
+ count ++;
+ }
+ }
+
+ /*
+ * If we have more than 1 marked choice, sort them...
+ */
+
+ if (count > 1)
+ qsort(collect, count, sizeof(ppd_choice_t *),
+ (int (*)(const void *, const void *))ppd_sort);
+
+ /*
+ * Return the array and number of choices; if 0, free the array since
+ * it isn't needed.
+ */
+
+ if (count > 0)
+ {
+ *choices = collect;
+ return (count);
+ }
+ else
+ {
+ *choices = NULL;
+ free(collect);
+ return (0);
+ }
+}
+
+
+/*
+ * 'ppdEmit()' - Emit code for marked options to a file.
+ */
+
+int /* O - 0 on success, -1 on failure */
+ppdEmit(ppd_file_t *ppd, /* I - PPD file record */
+ FILE *fp, /* I - File to write to */
+ ppd_section_t section) /* I - Section to write */
+{
+ int i, /* Looping var */
+ count; /* Number of choices */
+ ppd_choice_t **choices; /* Choices */
+ ppd_size_t *size; /* Custom page size */
+
+
+ /*
+ * Use PageSize or PageRegion as required...
+ */
+
+ ppd_handle_media(ppd);
+
+ /*
+ * Collect the options we need to emit and emit them!
+ */
+
+ if ((count = ppdCollect(ppd, section, &choices)) == 0)
+ return (0);
+
+ for (i = 0; i < count; i ++)
+ if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
+ {
+ /*
+ * Send wrapper commands to prevent printer errors for unsupported
+ * options...
+ */
+
+ if (fputs("[{\n", fp) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ /*
+ * Send DSC comments with option...
+ */
+
+ if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 ||
+ strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) &&
+ strcasecmp(choices[i]->choice, "Custom") == 0)
+ {
+ /*
+ * Variable size; write out standard size options, using the
+ * parameter positions defined in the PPD file...
+ */
+
+ ppd_attr_t *attr; /* PPD attribute */
+ int pos, /* Position of custom value */
+ values[5], /* Values for custom command */
+ orientation; /* Orientation to use */
+
+
+ fputs("%%BeginFeature: *CustomPageSize True\n", fp);
+
+ size = ppdPageSize(ppd, "Custom");
+
+ memset(values, 0, sizeof(values));
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
+ {
+ pos = atoi(attr->value) - 1;
+
+ if (pos < 0 || pos > 4)
+ pos = 0;
+ }
+ else
+ pos = 0;
+
+ values[pos] = (int)size->width;
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
+ {
+ pos = atoi(attr->value) - 1;
+
+ if (pos < 0 || pos > 4)
+ pos = 1;
+ }
+ else
+ pos = 1;
+
+ values[pos] = (int)size->length;
+
+ /*
+ * According to the Adobe PPD specification, an orientation of 1
+ * will produce a print that comes out upside-down with the X
+ * axis perpendicular to the direction of feed, which is exactly
+ * what we want to be consistent with non-PS printers.
+ *
+ * We could also use an orientation of 3 to produce output that
+ * comes out rightside-up (this is the default for many large format
+ * printer PPDs), however for consistency we will stick with the
+ * value 1.
+ *
+ * If we wanted to get fancy, we could use orientations of 0 or
+ * 2 and swap the width and length, however we don't want to get
+ * fancy, we just want it to work consistently.
+ *
+ * The orientation value is range limited by the Orientation
+ * parameter definition, so certain non-PS printer drivers that
+ * only support an Orientation of 0 will get the value 0 as
+ * expected.
+ */
+
+ orientation = 1;
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
+ "Orientation")) != NULL)
+ {
+ int min_orient, max_orient; /* Minimum and maximum orientations */
+
+
+ if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
+ &max_orient) != 3)
+ pos = 4;
+ else
+ {
+ pos --;
+
+ if (pos < 0 || pos > 4)
+ pos = 4;
+
+ if (orientation > max_orient)
+ orientation = max_orient;
+ else if (orientation < min_orient)
+ orientation = min_orient;
+ }
+ }
+ else
+ pos = 4;
+
+ values[pos] = orientation;
+
+ fprintf(fp, "%d %d %d %d %d\n", values[0], values[1],
+ values[2], values[3], values[4]);
+
+ if (choices[i]->code == NULL)
+ {
+ /*
+ * This can happen with certain buggy PPD files that don't include
+ * a CustomPageSize command sequence... We just use a generic
+ * Level 2 command sequence...
+ */
+
+ fputs(ppd_custom_code, fp);
+ }
+ }
+ else if (fprintf(fp, "%%%%BeginFeature: *%s %s\n",
+ ((ppd_option_t *)choices[i]->option)->keyword,
+ choices[i]->choice) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
+ {
+ if (fputs(choices[i]->code, fp) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (choices[i]->code[strlen(choices[i]->code) - 1] != '\n')
+ putc('\n', fp);
+ }
+
+ if (fputs("%%EndFeature\n", fp) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (fputs("} stopped cleartomark\n", fp) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+ }
+ else if (fputs(choices[i]->code, fp) < 0)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ free(choices);
+ return (0);
+}
+
+
+/*
+ * 'ppdEmitFd()' - Emit code for marked options to a file.
+ */
+
+int /* O - 0 on success, -1 on failure */
+ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */
+ int fd, /* I - File to write to */
+ ppd_section_t section) /* I - Section to write */
+{
+ int i, /* Looping var */
+ count, /* Number of choices */
+ custom_size; /* Non-zero if this option is a custom size */
+ ppd_choice_t **choices; /* Choices */
+ ppd_size_t *size; /* Custom page size */
+ char buf[1024]; /* Output buffer for feature */
+
+
+ /*
+ * Use PageSize or PageRegion as required...
+ */
+
+ ppd_handle_media(ppd);
+
+ /*
+ * Collect the options we need to emit and emit them!
+ */
+
+ if ((count = ppdCollect(ppd, section, &choices)) == 0)
+ return (0);
+
+ for (i = 0; i < count; i ++)
+ if (section != PPD_ORDER_EXIT && section != PPD_ORDER_JCL)
+ {
+ /*
+ * Send wrapper commands to prevent printer errors for unsupported
+ * options...
+ */
+
+ if (write(fd, "[{\n", 3) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ /*
+ * Send DSC comments with option...
+ */
+
+ if ((strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageSize") == 0 ||
+ strcasecmp(((ppd_option_t *)choices[i]->option)->keyword, "PageRegion") == 0) &&
+ strcasecmp(choices[i]->choice, "Custom") == 0)
+ {
+ custom_size = 1;
+
+ strcpy(buf, "%%BeginFeature: *CustomPageSize True\n");
+ }
+ else
+ {
+ custom_size = 0;
+
+ snprintf(buf, sizeof(buf), "%%%%BeginFeature: *%s %s\n",
+ ((ppd_option_t *)choices[i]->option)->keyword,
+ choices[i]->choice);
+ }
+
+ if (write(fd, buf, strlen(buf)) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (custom_size)
+ {
+ /*
+ * Variable size; write out standard size options, using the
+ * parameter positions defined in the PPD file...
+ */
+
+ ppd_attr_t *attr; /* PPD attribute */
+ int pos, /* Position of custom value */
+ values[5], /* Values for custom command */
+ orientation; /* Orientation to use */
+
+
+ size = ppdPageSize(ppd, "Custom");
+
+ memset(values, 0, sizeof(values));
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Width")) != NULL)
+ {
+ pos = atoi(attr->value) - 1;
+
+ if (pos < 0 || pos > 4)
+ pos = 0;
+ }
+ else
+ pos = 0;
+
+ values[pos] = (int)size->width;
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize", "Height")) != NULL)
+ {
+ pos = atoi(attr->value) - 1;
+
+ if (pos < 0 || pos > 4)
+ pos = 1;
+ }
+ else
+ pos = 1;
+
+ values[pos] = (int)size->length;
+
+ if (size->width < size->length)
+ orientation = 1;
+ else
+ orientation = 0;
+
+ if ((attr = ppdFindAttr(ppd, "ParamCustomPageSize",
+ "Orientation")) != NULL)
+ {
+ int min_orient, max_orient; /* Minimum and maximum orientations */
+
+
+ if (sscanf(attr->value, "%d%*s%d%d", &pos, &min_orient,
+ &max_orient) != 3)
+ pos = 4;
+ else
+ {
+ pos --;
+
+ if (pos < 0 || pos > 4)
+ pos = 4;
+
+ if (orientation > max_orient)
+ orientation = max_orient;
+ else if (orientation < min_orient)
+ orientation = min_orient;
+ }
+ }
+ else
+ pos = 4;
+
+ values[pos] = orientation;
+
+ snprintf(buf, sizeof(buf), "%d %d %d %d %d\n", values[0], values[1],
+ values[2], values[3], values[4]);
+
+ if (write(fd, buf, strlen(buf)) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (choices[i]->code == NULL)
+ {
+ /*
+ * This can happen with certain buggy PPD files that don't include
+ * a CustomPageSize command sequence... We just use a generic
+ * Level 2 command sequence...
+ */
+
+ if (write(fd, ppd_custom_code, strlen(ppd_custom_code)) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+ }
+ }
+
+ if (choices[i]->code != NULL && choices[i]->code[0] != '\0')
+ {
+ if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+ }
+
+ if (write(fd, "%%EndFeature\n", 13) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ if (write(fd, "} stopped cleartomark\n", 22) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+ }
+ else if (write(fd, choices[i]->code, strlen(choices[i]->code)) < 1)
+ {
+ free(choices);
+ return (-1);
+ }
+
+ free(choices);
+ return (0);
+}
+
+
+/*
+ * 'ppdEmitJCL()' - Emit code for JCL options to a file.
+ */
+
+int /* O - 0 on success, -1 on failure */
+ppdEmitJCL(ppd_file_t *ppd, /* I - PPD file record */
+ FILE *fp, /* I - File to write to */
+ int job_id, /* I - Job ID */
+ const char *user, /* I - Username */
+ const char *title) /* I - Title */
+{
+ char *ptr; /* Pointer into JCL string */
+ char temp[81]; /* Local title string */
+
+
+ /*
+ * Range check the input...
+ */
+
+ if (ppd == NULL || ppd->jcl_begin == NULL || ppd->jcl_ps == NULL)
+ return (0);
+
+ /*
+ * See if the printer supports HP PJL...
+ */
+
+ if (strncmp(ppd->jcl_begin, "\033%-12345X@", 10) == 0)
+ {
+ /*
+ * This printer uses HP PJL commands for output; filter the output
+ * so that we only have a single "@PJL JOB" command in the header...
+ *
+ * To avoid bugs in the PJL implementation of certain vendors' products
+ * (Xerox in particular), we add a dummy "@PJL" command at the beginning
+ * of the PJL commands to initialize PJL processing.
+ */
+
+ fputs("\033%-12345X@PJL\n", fp);
+ for (ptr = ppd->jcl_begin + 9; *ptr;)
+ if (strncmp(ptr, "@PJL JOB", 8) == 0)
+ {
+ /*
+ * Skip job command...
+ */
+
+ for (;*ptr; ptr ++)
+ if (*ptr == '\n')
+ break;
+
+ if (*ptr)
+ ptr ++;
+ }
+ else
+ {
+ /*
+ * Copy line...
+ */
+
+ for (;*ptr; ptr ++)
+ {
+ putc(*ptr, fp);
+ if (*ptr == '\n')
+ break;
+ }
+
+ if (*ptr)
+ ptr ++;
+ }
+
+ /*
+ * Eliminate any path info from the job title...
+ */
+
+ if ((ptr = strrchr(title, '/')) != NULL)
+ title = ptr + 1;
+
+ /*
+ * Replace double quotes with single quotes so that the title
+ * does not cause a PJL syntax error.
+ */
+
+ strlcpy(temp, title, sizeof(temp));
+
+ for (ptr = temp; *ptr; ptr ++)
+ if (*ptr == '\"')
+ *ptr = '\'';
+
+ /*
+ * Send PJL JOB command before we enter PostScript mode...
+ */
+
+ fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%d %s %s\"\n", temp,
+ job_id, user, temp);
+ }
+ else
+ fputs(ppd->jcl_begin, fp);
+
+ ppdEmit(ppd, fp, PPD_ORDER_JCL);
+ fputs(ppd->jcl_ps, fp);
+
+ return (0);
+}
+
+
+/*
+ * 'ppd_handle_media()' - Handle media selection...
+ */
+
+static void
+ppd_handle_media(ppd_file_t *ppd)
+{
+ ppd_choice_t *manual_feed, /* ManualFeed choice, if any */
+ *input_slot, /* InputSlot choice, if any */
+ *page; /* PageSize/PageRegion */
+ ppd_size_t *size; /* Current media size */
+ ppd_attr_t *rpr; /* RequiresPageRegion value */
+
+
+ /*
+ * This function determines if the user has selected a media source
+ * via the InputSlot or ManualFeed options; if so, it marks the
+ * PageRegion option corresponding to the current media size.
+ * Otherwise it marks the PageSize option.
+ */
+
+ if ((size = ppdPageSize(ppd, NULL)) == NULL)
+ return;
+
+ manual_feed = ppdFindMarkedChoice(ppd, "ManualFeed");
+ input_slot = ppdFindMarkedChoice(ppd, "InputSlot");
+
+ if (input_slot != NULL)
+ rpr = ppdFindAttr(ppd, "RequiresPageRegion", input_slot->choice);
+ else
+ rpr = NULL;
+
+ if (!rpr)
+ rpr = ppdFindAttr(ppd, "RequiresPageRegion", "All");
+
+ if (strcasecmp(size->name, "Custom") == 0 ||
+ (manual_feed == NULL && input_slot == NULL) ||
+ (manual_feed != NULL && strcasecmp(manual_feed->choice, "False") == 0) ||
+ (input_slot != NULL && (input_slot->code == NULL || !input_slot->code[0])))
+ {
+ /*
+ * Manual feed was not selected and/or the input slot selection does
+ * not contain any PostScript code. Use the PageSize option...
+ */
+
+ ppdMarkOption(ppd, "PageSize", size->name);
+ }
+ else
+ {
+ /*
+ * Manual feed was selected and/or the input slot selection contains
+ * PostScript code. Use the PageRegion option...
+ */
+
+ ppdMarkOption(ppd, "PageRegion", size->name);
+
+ /*
+ * RequiresPageRegion does not apply to manual feed so we need to
+ * check that we are not doing manual feed before unmarking PageRegion.
+ */
+
+ if (!(manual_feed && !strcasecmp(manual_feed->choice, "True")) &&
+ ((rpr && rpr->value && !strcmp(rpr->value, "False")) ||
+ (!rpr && !ppd->num_filters)))
+ {
+ /*
+ * Either the PPD file specifies no PageRegion code or the PPD file
+ * not for a CUPS raster driver and thus defaults to no PageRegion
+ * code... Unmark the PageRegion choice so that we don't output the
+ * code...
+ */
+
+ page = ppdFindMarkedChoice(ppd, "PageRegion");
+
+ if (page)
+ page->marked = 0;
+ }
+ }
+}
+
+
+/*
+ * 'ppd_sort()' - Sort options by ordering numbers...
+ */
+
+static int /* O - -1 if c1 < c2, 0 if equal, 1 otherwise */
+ppd_sort(ppd_choice_t **c1, /* I - First choice */
+ ppd_choice_t **c2) /* I - Second choice */
+{
+ if (((ppd_option_t *)(*c1)->option)->order < ((ppd_option_t *)(*c2)->option)->order)
+ return (-1);
+ else if (((ppd_option_t *)(*c1)->option)->order > ((ppd_option_t *)(*c2)->option)->order)
+ return (1);
+ else
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/encode.c b/cups/encode.c
new file mode 100644
index 000000000..bebe81d49
--- /dev/null
+++ b/cups/encode.c
@@ -0,0 +1,388 @@
+/*
+ * "$Id$"
+ *
+ * Option encoding routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsEncodeOptions() - Encode printer options into IPP attributes.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include "string.h"
+#include "debug.h"
+
+
+/*
+ * Local list of option names and the value tags they should use...
+ */
+
+typedef struct
+{
+ const char *name;
+ ipp_tag_t value_tag;
+} ipp_option_t;
+
+static const ipp_option_t ipp_options[] =
+ {
+ { "blackplot", IPP_TAG_BOOLEAN },
+ { "brightness", IPP_TAG_INTEGER },
+ { "columns", IPP_TAG_INTEGER },
+ { "copies", IPP_TAG_INTEGER },
+ { "finishings", IPP_TAG_ENUM },
+ { "fitplot", IPP_TAG_BOOLEAN },
+ { "gamma", IPP_TAG_INTEGER },
+ { "hue", IPP_TAG_INTEGER },
+ { "job-k-limit", IPP_TAG_INTEGER },
+ { "job-page-limit", IPP_TAG_INTEGER },
+ { "job-priority", IPP_TAG_INTEGER },
+ { "job-quota-period", IPP_TAG_INTEGER },
+ { "landscape", IPP_TAG_BOOLEAN },
+ { "media", IPP_TAG_KEYWORD },
+ { "mirror", IPP_TAG_BOOLEAN },
+ { "natural-scaling", IPP_TAG_INTEGER },
+ { "number-up", IPP_TAG_INTEGER },
+ { "orientation-requested", IPP_TAG_ENUM },
+ { "page-bottom", IPP_TAG_INTEGER },
+ { "page-left", IPP_TAG_INTEGER },
+ { "page-ranges", IPP_TAG_RANGE },
+ { "page-right", IPP_TAG_INTEGER },
+ { "page-top", IPP_TAG_INTEGER },
+ { "penwidth", IPP_TAG_INTEGER },
+ { "ppi", IPP_TAG_INTEGER },
+ { "prettyprint", IPP_TAG_BOOLEAN },
+ { "printer-resolution", IPP_TAG_RESOLUTION },
+ { "print-quality", IPP_TAG_ENUM },
+ { "saturation", IPP_TAG_INTEGER },
+ { "scaling", IPP_TAG_INTEGER },
+ { "sides", IPP_TAG_KEYWORD },
+ { "wrap", IPP_TAG_BOOLEAN }
+ };
+
+
+/*
+ * 'cupsEncodeOptions()' - Encode printer options into IPP attributes.
+ */
+
+void
+cupsEncodeOptions(ipp_t *ipp, /* I - Request to add to */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ int i, j; /* Looping vars */
+ int count; /* Number of values */
+ char *s, /* Pointer into option value */
+ *val, /* Pointer to option value */
+ *copy, /* Copy of option value */
+ *sep; /* Option separator */
+ ipp_attribute_t *attr; /* IPP job-id attribute */
+
+
+ DEBUG_printf(("cupsEncodeOptions(%p, %d, %p)\n", ipp, num_options, options));
+
+ if (ipp == NULL || num_options < 1 || options == NULL)
+ return;
+
+ /*
+ * Handle the document format stuff first...
+ */
+
+ if ((val = (char *)cupsGetOption("document-format", num_options, options)) != NULL)
+ ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, val);
+ else if (cupsGetOption("raw", num_options, options))
+ ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/vnd.cups-raw");
+ else
+ ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/octet-stream");
+
+ /*
+ * Then add all other options...
+ */
+
+ for (i = 0; i < num_options; i ++)
+ {
+ /*
+ * Skip document format options - handled above...
+ */
+
+ if (strcasecmp(options[i].name, "raw") == 0 ||
+ strcasecmp(options[i].name, "document-format") == 0 ||
+ !options[i].name[0])
+ continue;
+
+ /*
+ * Count the number of values...
+ */
+
+ for (count = 1, sep = options[i].value; *sep; sep ++)
+ {
+ if (*sep == '\'')
+ {
+ /*
+ * Skip quoted option value...
+ */
+
+ sep ++;
+
+ while (*sep && *sep != '\'')
+ sep ++;
+
+ if (!*sep)
+ sep --;
+ }
+ else if (*sep == '\"')
+ {
+ /*
+ * Skip quoted option value...
+ */
+
+ sep ++;
+
+ while (*sep && *sep != '\"')
+ sep ++;
+
+ if (!*sep)
+ sep --;
+ }
+ else if (*sep == ',')
+ count ++;
+ else if (*sep == '\\' && sep[1])
+ sep ++;
+ }
+
+ DEBUG_printf(("cupsEncodeOptions: option = \'%s\', count = %d\n",
+ options[i].name, count));
+
+ /*
+ * Allocate memory for the attribute values...
+ */
+
+ if ((attr = _ipp_add_attr(ipp, count)) == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ DEBUG_puts("cupsEncodeOptions: Ran out of memory for attributes!");
+ return;
+ }
+
+ /*
+ * Now figure out what type of value we have...
+ */
+
+ attr->group_tag = IPP_TAG_JOB;
+
+ if (strcasecmp(options[i].value, "true") == 0 ||
+ strcasecmp(options[i].value, "false") == 0)
+ attr->value_tag = IPP_TAG_BOOLEAN;
+ else
+ attr->value_tag = IPP_TAG_NAME;
+
+ for (j = 0; j < (int)(sizeof(ipp_options) / sizeof(ipp_options[0])); j ++)
+ if (strcasecmp(options[i].name, ipp_options[j].name) == 0)
+ {
+ attr->value_tag = ipp_options[j].value_tag;
+ break;
+ }
+
+ /*
+ * Copy the name over...
+ */
+
+ if ((attr->name = strdup(options[i].name)) == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ DEBUG_puts("cupsEncodeOptions: Ran out of memory for name!");
+ return;
+ }
+
+ if (count > 1)
+ {
+ /*
+ * Make a copy of the value we can fiddle with...
+ */
+
+ if ((copy = strdup(options[i].value)) == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ DEBUG_puts("cupsEncodeOptions: Ran out of memory for value copy!");
+ return;
+ }
+
+ val = copy;
+ }
+ else
+ {
+ /*
+ * Since we have a single value, use the value directly...
+ */
+
+ val = options[i].value;
+ copy = NULL;
+ }
+
+ /*
+ * Scan the value string for values...
+ */
+
+ for (j = 0; j < count; val = sep, j ++)
+ {
+ /*
+ * Find the end of this value and mark it if needed...
+ */
+
+ if ((sep = strchr(val, ',')) != NULL)
+ *sep++ = '\0';
+ else
+ sep = val + strlen(val);
+
+ /*
+ * Copy the option value(s) over as needed by the type...
+ */
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ /*
+ * Integer/enumeration value...
+ */
+
+ attr->values[j].integer = strtol(val, &s, 0);
+
+ DEBUG_printf(("cupsEncodeOptions: Adding integer option value %d...\n",
+ attr->values[j].integer));
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ if (!strcasecmp(val, "true") ||
+ !strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes"))
+ {
+ /*
+ * Boolean value - true...
+ */
+
+ attr->values[j].boolean = 1;
+
+ DEBUG_puts("cupsEncodeOptions: Added boolean true value...");
+ }
+ else
+ {
+ /*
+ * Boolean value - false...
+ */
+
+ attr->values[j].boolean = 0;
+
+ DEBUG_puts("cupsEncodeOptions: Added boolean false value...");
+ }
+ break;
+
+ case IPP_TAG_RANGE :
+ /*
+ * Range...
+ */
+
+ if (*val == '-')
+ {
+ attr->values[j].range.lower = 1;
+ s = val;
+ }
+ else
+ attr->values[j].range.lower = strtol(val, &s, 0);
+
+ if (*s == '-')
+ {
+ if (s[1])
+ attr->values[j].range.upper = strtol(s + 1, NULL, 0);
+ else
+ attr->values[j].range.upper = 2147483647;
+ }
+ else
+ attr->values[j].range.upper = attr->values[j].range.lower;
+
+ DEBUG_printf(("cupsEncodeOptions: Added range option value %d-%d...\n",
+ attr->values[j].range.lower,
+ attr->values[j].range.upper));
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ /*
+ * Resolution...
+ */
+
+ attr->values[j].resolution.xres = strtol(val, &s, 0);
+
+ if (*s == 'x')
+ attr->values[j].resolution.yres = strtol(s + 1, &s, 0);
+ else
+ attr->values[j].resolution.yres = attr->values[j].resolution.xres;
+
+ if (strcasecmp(s, "dpc") == 0)
+ attr->values[j].resolution.units = IPP_RES_PER_CM;
+ else
+ attr->values[j].resolution.units = IPP_RES_PER_INCH;
+
+ DEBUG_printf(("cupsEncodeOptions: Adding resolution option value %s...\n",
+ val));
+ break;
+
+ default :
+ if ((attr->values[j].string.text = strdup(val)) == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ DEBUG_puts("cupsEncodeOptions: Ran out of memory for string!");
+ return;
+ }
+
+ DEBUG_printf(("cupsEncodeOptions: Added string value \'%s\'...\n",
+ val));
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/getputfile.c b/cups/getputfile.c
new file mode 100644
index 000000000..67776be0e
--- /dev/null
+++ b/cups/getputfile.c
@@ -0,0 +1,419 @@
+/*
+ * "$Id$"
+ *
+ * Get/put file functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsGetFd() - Get a file from the server.
+ * cupsGetFile() - Get a file from the server.
+ * cupsPutFd() - Put a file on the server.
+ * cupsPutFile() - Put a file on the server.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "ipp.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * 'cupsGetFd()' - Get a file from the server.
+ */
+
+http_status_t /* O - Status */
+cupsGetFd(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ int fd) /* I - File descriptor */
+{
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ http_status_t status; /* HTTP status from server */
+
+
+ /*
+ * Range check input...
+ */
+
+ DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http,
+ resource, fd));
+
+ if (!http || !resource || fd < 0)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Then send GET requests to the HTTP server...
+ */
+
+ do
+ {
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+
+ if (httpGet(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * See if we can do authentication...
+ */
+
+ if (cupsDoAuthentication(http, "GET", resource))
+ break;
+
+ httpReconnect(http);
+
+ continue;
+ }
+#ifdef HAVE_SSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /* Flush any error message... */
+ httpFlush(http);
+
+ /* Reconnect... */
+ httpReconnect(http);
+
+ /* Upgrade with encryption... */
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ /* Try again, this time with encryption enabled... */
+ continue;
+ }
+#endif /* HAVE_SSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
+
+ /*
+ * See if we actually got the file or an error...
+ */
+
+ if (status == HTTP_OK)
+ {
+ /*
+ * Yes, copy the file...
+ */
+
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ write(fd, buffer, bytes);
+ }
+ else
+ httpFlush(http);
+
+ /*
+ * Return the request status...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'cupsGetFile()' - Get a file from the server.
+ */
+
+http_status_t /* O - Status */
+cupsGetFile(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ const char *filename) /* I - Filename */
+{
+ int fd; /* File descriptor */
+ http_status_t status; /* Status */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || !filename)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Create the file...
+ */
+
+ if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
+ {
+ /*
+ * Couldn't open the file!
+ */
+
+ http->error = errno;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Get the file...
+ */
+
+ status = cupsGetFd(http, resource, fd);
+
+ /*
+ * If the file couldn't be gotten, then remove the file...
+ */
+
+ close(fd);
+
+ if (status != HTTP_OK)
+ unlink(filename);
+
+ /*
+ * Return the HTTP status code...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'cupsPutFd()' - Put a file on the server.
+ */
+
+http_status_t /* O - Status */
+cupsPutFd(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ int fd) /* I - File descriptor */
+{
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ http_status_t status; /* HTTP status from server */
+
+
+ /*
+ * Range check input...
+ */
+
+ DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)\n", http,
+ resource, fd));
+
+ if (!http || !resource || fd < 0)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Then send PUT requests to the HTTP server...
+ */
+
+ do
+ {
+ DEBUG_printf(("cupsPutFd: starting attempt, authstring=\"%s\"...\n",
+ http->authstring));
+
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+ httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+
+ if (httpPut(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ /*
+ * Copy the file...
+ */
+
+ lseek(fd, 0, SEEK_SET);
+
+ status = HTTP_CONTINUE;
+
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ if (httpCheck(http))
+ {
+ if ((status = httpUpdate(http)) != HTTP_CONTINUE)
+ break;
+ }
+ else
+ httpWrite(http, buffer, bytes);
+
+ if (status == HTTP_CONTINUE)
+ {
+ httpWrite(http, buffer, 0);
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+ }
+
+ DEBUG_printf(("cupsPutFd: status=%d\n", status));
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * See if we can do authentication...
+ */
+
+ if (cupsDoAuthentication(http, "PUT", resource))
+ break;
+
+ httpReconnect(http);
+
+ continue;
+ }
+#ifdef HAVE_SSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /* Flush any error message... */
+ httpFlush(http);
+
+ /* Reconnect... */
+ httpReconnect(http);
+
+ /* Upgrade with encryption... */
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ /* Try again, this time with encryption enabled... */
+ continue;
+ }
+#endif /* HAVE_SSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
+
+ /*
+ * See if we actually put the file or an error...
+ */
+
+ if (status != HTTP_CREATED)
+ httpFlush(http);
+
+ return (status);
+}
+
+
+/*
+ * 'cupsPutFile()' - Put a file on the server.
+ */
+
+http_status_t /* O - Status */
+cupsPutFile(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ const char *filename) /* I - Filename */
+{
+ int fd; /* File descriptor */
+ http_status_t status; /* Status */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || !filename)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Open the local file...
+ */
+
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ {
+ /*
+ * Couldn't open the file!
+ */
+
+ http->error = errno;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Put the file...
+ */
+
+ status = cupsPutFd(http, resource, fd);
+
+ close(fd);
+
+ return (status);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/http-addr.c b/cups/http-addr.c
new file mode 100644
index 000000000..0e0ef0b59
--- /dev/null
+++ b/cups/http-addr.c
@@ -0,0 +1,122 @@
+/*
+ * "$Id$"
+ *
+ * HTTP host/address routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * httpGetHostByName() - Lookup a hostname or IP address, and return
+ * address records for the specified name.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "string.h"
+
+#include "http.h"
+
+
+/*
+ * 'httpGetHostByName()' - Lookup a hostname or IP address, and return
+ * address records for the specified name.
+ */
+
+struct hostent * /* O - Host entry */
+httpGetHostByName(const char *name) /* I - Hostname or IP address */
+{
+ const char *nameptr; /* Pointer into name */
+ unsigned ip[4]; /* IP address components */
+ static unsigned packed_ip; /* Packed IPv4 address */
+ static char *packed_ptr[2]; /* Pointer to packed address */
+ static struct hostent host_ip; /* Host entry for IP address */
+
+
+#if defined(__APPLE__)
+ /* OS X hack to avoid it's ocassional long delay in lookupd */
+ static const char sLoopback[] = "127.0.0.1";
+ if (strcmp(name, "localhost") == 0)
+ name = sLoopback;
+#endif /* __APPLE__ */
+
+ /*
+ * This function is needed because some operating systems have a
+ * buggy implementation of gethostbyname() that does not support
+ * IP addresses. If the first character of the name string is a
+ * number, then sscanf() is used to extract the IP components.
+ * We then pack the components into an IPv4 address manually,
+ * since the inet_aton() function is deprecated. We use the
+ * htonl() macro to get the right byte order for the address.
+ */
+
+ for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++);
+
+ if (!*nameptr)
+ {
+ /*
+ * We have an IP address; break it up and provide the host entry
+ * to the caller. Currently only supports IPv4 addresses, although
+ * it should be trivial to support IPv6 in CUPS 1.2.
+ */
+
+ if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4)
+ return (NULL); /* Must have 4 numbers */
+
+ if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255)
+ return (NULL); /* Invalid byte ranges! */
+
+ packed_ip = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3]));
+
+ /*
+ * Fill in the host entry and return it...
+ */
+
+ host_ip.h_name = (char *)name;
+ host_ip.h_aliases = NULL;
+ host_ip.h_addrtype = AF_INET;
+ host_ip.h_length = 4;
+ host_ip.h_addr_list = packed_ptr;
+ packed_ptr[0] = (char *)(&packed_ip);
+ packed_ptr[1] = NULL;
+
+ return (&host_ip);
+ }
+ else
+ {
+ /*
+ * Use the gethostbyname() function to get the IP address for
+ * the name...
+ */
+
+ return (gethostbyname(name));
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/http-private.h b/cups/http-private.h
new file mode 100644
index 000000000..294e7a4d9
--- /dev/null
+++ b/cups/http-private.h
@@ -0,0 +1,102 @@
+/*
+ * "$Id$"
+ *
+ * Private HTTP definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_HTTP_PRIVATE_H_
+# define _CUPS_HTTP_PRIVATE_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include "config.h"
+
+# ifdef __sun
+/*
+ * Define FD_SETSIZE to CUPS_MAX_FDS on Solaris to get the correct version of
+ * select() for large numbers of file descriptors.
+ */
+
+# define FD_SETSIZE CUPS_MAX_FDS
+# include <sys/select.h>
+# endif /* __sun */
+
+# include "http.h"
+
+# if defined HAVE_LIBSSL
+/*
+ * The OpenSSL library provides its own SSL/TLS context structure for its
+ * IO and protocol management...
+ */
+
+# include <openssl/err.h>
+# include <openssl/rand.h>
+# include <openssl/ssl.h>
+
+typedef SSL http_tls_t;
+
+# elif defined HAVE_GNUTLS
+/*
+ * The GNU TLS library is more of a "bare metal" SSL/TLS library...
+ */
+# include <gnutls/gnutls.h>
+
+typedef struct
+{
+ gnutls_session session; /* GNU TLS session object */
+ void *credentials; /* GNU TLS credentials object */
+} http_tls_t;
+
+# elif defined(HAVE_CDSASSL)
+/*
+ * Darwin's Security framework provides its own SSL/TLS context structure
+ * for its IO and protocol management...
+ */
+
+# include <Security/SecureTransport.h>
+
+typedef SSLConnectionRef http_tls_t;
+
+# endif /* HAVE_LIBSSL */
+
+/*
+ * Some OS's don't have hstrerror(), most notably Solaris...
+ */
+
+# ifndef HAVE_HSTRERROR
+extern const char *cups_hstrerror(int error);
+# define hstrerror cups_hstrerror
+# elif defined(_AIX) || defined(__osf__)
+/*
+ * AIX and Tru64 UNIX don't provide a prototype but do provide the function...
+ */
+extern const char *hstrerror(int error);
+# endif /* !HAVE_HSTRERROR */
+
+#endif /* !_CUPS_HTTP_PRIVATE_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/http-support.c b/cups/http-support.c
new file mode 100644
index 000000000..0e08c94a8
--- /dev/null
+++ b/cups/http-support.c
@@ -0,0 +1,378 @@
+/*
+ * "$Id$"
+ *
+ * HTTP support routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * httpSeparate() - Separate a Universal Resource Identifier into its
+ * components.
+ * httpSeparate2() - Separate a Universal Resource Identifier into its
+ * components.
+ * httpStatus() - Return a short string describing a HTTP status code.
+ * cups_hstrerror() - hstrerror() emulation function for Solaris and others...
+ * http_copy_decode() - Copy and decode a URI.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "string.h"
+
+#include "http.h"
+#include "ipp.h"
+
+
+/*
+ * Local functions...
+ */
+
+static const char *http_copy_decode(char *dst, const char *src,
+ int dstsize, const char *term);
+
+
+/*
+ * 'httpSeparate()' - Separate a Universal Resource Identifier into its
+ * components.
+ */
+
+void
+httpSeparate(const char *uri, /* I - Universal Resource Identifier */
+ char *method, /* O - Method [32] (http, https, etc.) */
+ char *username, /* O - Username [1024] */
+ char *host, /* O - Hostname [1024] */
+ int *port, /* O - Port number to use */
+ char *resource) /* O - Resource/filename [1024] */
+{
+ httpSeparate2(uri, method, 32, username, HTTP_MAX_URI, host, HTTP_MAX_URI,
+ port, resource, HTTP_MAX_URI);
+}
+
+
+/*
+ * 'httpSeparate2()' - Separate a Universal Resource Identifier into its
+ * components.
+ */
+
+void
+httpSeparate2(const char *uri, /* I - Universal Resource Identifier */
+ char *method, /* O - Method (http, https, etc.) */
+ int methodlen, /* I - Size of method buffer */
+ char *username, /* O - Username */
+ int usernamelen, /* I - Size of username buffer */
+ char *host, /* O - Hostname */
+ int hostlen, /* I - Size of hostname buffer */
+ int *port, /* O - Port number to use */
+ char *resource, /* O - Resource/filename */
+ int resourcelen) /* I - Size of resource buffer */
+{
+ char *ptr; /* Pointer into string... */
+ const char *atsign, /* @ sign */
+ *slash; /* Separator */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (uri == NULL || method == NULL || username == NULL || host == NULL ||
+ port == NULL || resource == NULL)
+ return;
+
+ /*
+ * Grab the method portion of the URI...
+ */
+
+ if (strncmp(uri, "//", 2) == 0)
+ {
+ /*
+ * Workaround for HP IPP client bug...
+ */
+
+ strlcpy(method, "ipp", methodlen);
+ }
+ else
+ {
+ /*
+ * Standard URI with method...
+ */
+
+ uri = http_copy_decode(host, uri, hostlen, ":");
+
+ if (*uri == ':')
+ uri ++;
+
+ /*
+ * If the method contains a period or slash, then it's probably
+ * hostname/filename...
+ */
+
+ if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0')
+ {
+ if ((ptr = strchr(host, '/')) != NULL)
+ {
+ strlcpy(resource, ptr, resourcelen);
+ *ptr = '\0';
+ }
+ else
+ resource[0] = '\0';
+
+ if (isdigit(*uri & 255))
+ {
+ /*
+ * OK, we have "hostname:port[/resource]"...
+ */
+
+ *port = strtol(uri, (char **)&uri, 10);
+
+ if (*uri == '/')
+ strlcpy(resource, uri, resourcelen);
+ }
+ else
+ *port = 631;
+
+ strlcpy(method, "http", methodlen);
+ username[0] = '\0';
+ return;
+ }
+ else
+ strlcpy(method, host, methodlen);
+ }
+
+ /*
+ * If the method starts with less than 2 slashes then it is a local resource...
+ */
+
+ if (strncmp(uri, "//", 2) != 0)
+ {
+ strlcpy(resource, uri, resourcelen);
+
+ username[0] = '\0';
+ host[0] = '\0';
+ *port = 0;
+ return;
+ }
+
+ /*
+ * Grab the username, if any...
+ */
+
+ uri += 2;
+
+ if ((slash = strchr(uri, '/')) == NULL)
+ slash = uri + strlen(uri);
+
+ if ((atsign = strchr(uri, '@')) != NULL && atsign < slash)
+ {
+ /*
+ * Got a username:password combo...
+ */
+
+ uri = http_copy_decode(username, uri, usernamelen, "@") + 1;
+ }
+ else
+ username[0] = '\0';
+
+ /*
+ * Grab the hostname...
+ */
+
+ uri = http_copy_decode(host, uri, hostlen, ":/");
+
+ if (*uri != ':')
+ {
+ if (strcasecmp(method, "http") == 0)
+ *port = 80;
+ else if (strcasecmp(method, "https") == 0)
+ *port = 443;
+ else if (strcasecmp(method, "ipp") == 0)
+ *port = 631;
+ else if (strcasecmp(method, "lpd") == 0)
+ *port = 515;
+ else if (strcasecmp(method, "socket") == 0) /* Not registered yet... */
+ *port = 9100;
+ else
+ *port = 0;
+ }
+ else
+ {
+ /*
+ * Parse port number...
+ */
+
+ *port = strtol(uri + 1, (char **)&uri, 10);
+ }
+
+ if (*uri == '\0')
+ {
+ /*
+ * Hostname but no port or path...
+ */
+
+ resource[0] = '/';
+ resource[1] = '\0';
+ return;
+ }
+
+ /*
+ * The remaining portion is the resource string...
+ */
+
+ http_copy_decode(resource, uri, resourcelen, "");
+}
+
+
+/*
+ * 'httpStatus()' - Return a short string describing a HTTP status code.
+ */
+
+const char * /* O - String or NULL */
+httpStatus(http_status_t status) /* I - HTTP status code */
+{
+ switch (status)
+ {
+ case HTTP_CONTINUE :
+ return ("Continue");
+ case HTTP_SWITCHING_PROTOCOLS :
+ return ("Switching Protocols");
+ case HTTP_OK :
+ return ("OK");
+ case HTTP_CREATED :
+ return ("Created");
+ case HTTP_ACCEPTED :
+ return ("Accepted");
+ case HTTP_NO_CONTENT :
+ return ("No Content");
+ case HTTP_NOT_MODIFIED :
+ return ("Not Modified");
+ case HTTP_BAD_REQUEST :
+ return ("Bad Request");
+ case HTTP_UNAUTHORIZED :
+ return ("Unauthorized");
+ case HTTP_FORBIDDEN :
+ return ("Forbidden");
+ case HTTP_NOT_FOUND :
+ return ("Not Found");
+ case HTTP_REQUEST_TOO_LARGE :
+ return ("Request Entity Too Large");
+ case HTTP_URI_TOO_LONG :
+ return ("URI Too Long");
+ case HTTP_UPGRADE_REQUIRED :
+ return ("Upgrade Required");
+ case HTTP_NOT_IMPLEMENTED :
+ return ("Not Implemented");
+ case HTTP_NOT_SUPPORTED :
+ return ("Not Supported");
+ default :
+ return ("Unknown");
+ }
+}
+
+
+#ifndef HAVE_HSTRERROR
+/*
+ * 'cups_hstrerror()' - hstrerror() emulation function for Solaris and others...
+ */
+
+const char * /* O - Error string */
+cups_hstrerror(int error) /* I - Error number */
+{
+ static const char * const errors[] = /* Error strings */
+ {
+ "OK",
+ "Host not found.",
+ "Try again.",
+ "Unrecoverable lookup error.",
+ "No data associated with name."
+ };
+
+
+ if (error < 0 || error > 4)
+ return ("Unknown hostname lookup error.");
+ else
+ return (errors[error]);
+}
+#endif /* !HAVE_HSTRERROR */
+
+
+/*
+ * 'http_copy_decode()' - Copy and decode a URI.
+ */
+
+static const char * /* O - New source pointer */
+http_copy_decode(char *dst, /* O - Destination buffer */
+ const char *src, /* I - Source pointer */
+ int dstsize, /* I - Destination size */
+ const char *term) /* I - Terminating characters */
+{
+ char *ptr, /* Pointer into buffer */
+ *end; /* End of buffer */
+ int quoted; /* Quoted character */
+
+
+ /*
+ * Copy the src to the destination until we hit a terminating character
+ * or the end of the string.
+ */
+
+ for (ptr = dst, end = dst + dstsize - 1; *src && !strchr(term, *src); src ++)
+ if (ptr < end)
+ {
+ if (*src == '%' && isxdigit(src[1] & 255) && isxdigit(src[2] & 255))
+ {
+ /*
+ * Grab a hex-encoded character...
+ */
+
+ src ++;
+ if (isalpha(*src))
+ quoted = (tolower(*src) - 'a' + 10) << 4;
+ else
+ quoted = (*src - '0') << 4;
+
+ src ++;
+ if (isalpha(*src))
+ quoted |= tolower(*src) - 'a' + 10;
+ else
+ quoted |= *src - '0';
+
+ *ptr++ = quoted;
+ }
+ else
+ *ptr++ = *src;
+ }
+
+ *ptr = '\0';
+
+ return (src);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/http.c b/cups/http.c
new file mode 100644
index 000000000..47462d644
--- /dev/null
+++ b/cups/http.c
@@ -0,0 +1,2561 @@
+/*
+ * "$Id$"
+ *
+ * HTTP routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * httpInitialize() - Initialize the HTTP interface library and set the
+ * default HTTP proxy (if any).
+ * httpCheck() - Check to see if there is a pending response from
+ * the server.
+ * httpClearCookie() - Clear the cookie value(s).
+ * httpClose() - Close an HTTP connection...
+ * httpConnect() - Connect to a HTTP server.
+ * httpConnectEncrypt() - Connect to a HTTP server using encryption.
+ * httpEncryption() - Set the required encryption on the link.
+ * httpReconnect() - Reconnect to a HTTP server...
+ * httpGetSubField() - Get a sub-field value.
+ * httpSetField() - Set the value of an HTTP header.
+ * httpDelete() - Send a DELETE request to the server.
+ * httpGet() - Send a GET request to the server.
+ * httpHead() - Send a HEAD request to the server.
+ * httpOptions() - Send an OPTIONS request to the server.
+ * httpPost() - Send a POST request to the server.
+ * httpPut() - Send a PUT request to the server.
+ * httpTrace() - Send an TRACE request to the server.
+ * httpFlush() - Flush data from a HTTP connection.
+ * httpRead() - Read data from a HTTP connection.
+ * httpSetCookie() - Set the cookie value(s)...
+ * httpWait() - Wait for data available on a connection.
+ * httpWrite() - Write data to a HTTP connection.
+ * httpGets() - Get a line of text from a HTTP connection.
+ * httpPrintf() - Print a formatted string to a HTTP connection.
+ * httpGetDateString() - Get a formatted date/time string from a time value.
+ * httpGetDateTime() - Get a time value from a formatted date/time string.
+ * httpUpdate() - Update the current HTTP state for incoming data.
+ * httpDecode64() - Base64-decode a string.
+ * httpDecode64_2() - Base64-decode a string.
+ * httpEncode64() - Base64-encode a string.
+ * httpEncode64_2() - Base64-encode a string.
+ * httpGetLength() - Get the amount of data remaining from the
+ * content-length or transfer-encoding fields.
+ * http_field() - Return the field index for a field name.
+ * http_send() - Send a request with all fields and the trailing
+ * blank line.
+ * http_wait() - Wait for data available on a connection.
+ * http_upgrade() - Force upgrade to TLS encryption.
+ * http_setup_ssl() - Set up SSL/TLS on a connection.
+ * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
+ * http_read_ssl() - Read from a SSL/TLS connection.
+ * http_write_ssl() - Write to a SSL/TLS connection.
+ * CDSAReadFunc() - Read function for CDSA decryption code.
+ * CDSAWriteFunc() - Write function for CDSA encryption code.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "http-private.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "string.h"
+#include <fcntl.h>
+#include <errno.h>
+
+#include "http.h"
+#include "debug.h"
+
+#ifndef WIN32
+# include <signal.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif /* !WIN32 */
+
+
+/*
+ * Some operating systems have done away with the Fxxxx constants for
+ * the fcntl() call; this works around that "feature"...
+ */
+
+#ifndef FNONBLK
+# define FNONBLK O_NONBLOCK
+#endif /* !FNONBLK */
+
+
+/*
+ * Local functions...
+ */
+
+static http_field_t http_field(const char *name);
+static int http_send(http_t *http, http_state_t request,
+ const char *uri);
+static int http_wait(http_t *http, int msec);
+#ifdef HAVE_SSL
+static int http_upgrade(http_t *http);
+static int http_setup_ssl(http_t *http);
+static void http_shutdown_ssl(http_t *http);
+static int http_read_ssl(http_t *http, char *buf, int len);
+static int http_write_ssl(http_t *http, const char *buf, int len);
+# ifdef HAVE_CDSASSL
+static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data, size_t *dataLength);
+static OSStatus CDSAWriteFunc(SSLConnectionRef connection, const void *data, size_t *dataLength);
+# endif /* HAVE_CDSASSL */
+#endif /* HAVE_SSL */
+
+
+/*
+ * Local globals...
+ */
+
+static const char * const http_fields[] =
+ {
+ "Accept-Language",
+ "Accept-Ranges",
+ "Authorization",
+ "Connection",
+ "Content-Encoding",
+ "Content-Language",
+ "Content-Length",
+ "Content-Location",
+ "Content-MD5",
+ "Content-Range",
+ "Content-Type",
+ "Content-Version",
+ "Date",
+ "Host",
+ "If-Modified-Since",
+ "If-Unmodified-since",
+ "Keep-Alive",
+ "Last-Modified",
+ "Link",
+ "Location",
+ "Range",
+ "Referer",
+ "Retry-After",
+ "Transfer-Encoding",
+ "Upgrade",
+ "User-Agent",
+ "WWW-Authenticate"
+ };
+static const char * const days[7] =
+ {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ };
+static const char * const months[12] =
+ {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ };
+
+
+/*
+ * 'httpInitialize()' - Initialize the HTTP interface library and set the
+ * default HTTP proxy (if any).
+ */
+
+void
+httpInitialize(void)
+{
+#ifdef HAVE_LIBSSL
+# ifndef WIN32
+ struct timeval curtime; /* Current time in microseconds */
+# endif /* !WIN32 */
+ int i; /* Looping var */
+ unsigned char data[1024]; /* Seed data */
+#endif /* HAVE_LIBSSL */
+
+#ifdef WIN32
+ WSADATA winsockdata; /* WinSock data */
+ static int initialized = 0; /* Has WinSock been initialized? */
+
+
+ if (!initialized)
+ WSAStartup(MAKEWORD(1,1), &winsockdata);
+#elif defined(HAVE_SIGSET)
+ sigset(SIGPIPE, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ struct sigaction action; /* POSIX sigaction data */
+
+
+ /*
+ * Ignore SIGPIPE signals...
+ */
+
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif /* WIN32 */
+
+#ifdef HAVE_GNUTLS
+ gnutls_global_init();
+#endif /* HAVE_GNUTLS */
+
+#ifdef HAVE_LIBSSL
+ SSL_load_error_strings();
+ SSL_library_init();
+
+ /*
+ * Using the current time is a dubious random seed, but on some systems
+ * it is the best we can do (on others, this seed isn't even used...)
+ */
+
+#ifdef WIN32
+#else
+ gettimeofday(&curtime, NULL);
+ srand(curtime.tv_sec + curtime.tv_usec);
+#endif /* WIN32 */
+
+ for (i = 0; i < sizeof(data); i ++)
+ data[i] = rand(); /* Yes, this is a poor source of random data... */
+
+ RAND_seed(&data, sizeof(data));
+#endif /* HAVE_LIBSSL */
+}
+
+
+/*
+ * 'httpCheck()' - Check to see if there is a pending response from the server.
+ */
+
+int /* O - 0 = no data, 1 = data available */
+httpCheck(http_t *http) /* I - HTTP connection */
+{
+ return (httpWait(http, 0));
+}
+
+
+/*
+ * 'httpClearCookie()' - Clear the cookie value(s).
+ */
+
+void
+httpClearCookie(http_t *http) /* I - Connection */
+{
+ if (!http)
+ return;
+
+ if (http->cookie)
+ {
+ free(http->cookie);
+ http->cookie = NULL;
+ }
+}
+
+
+/*
+ * 'httpClose()' - Close an HTTP connection...
+ */
+
+void
+httpClose(http_t *http) /* I - Connection to close */
+{
+ DEBUG_printf(("httpClose(http=%p)\n", http));
+
+ if (!http)
+ return;
+
+ if (http->input_set)
+ free(http->input_set);
+
+ if (http->cookie)
+ free(http->cookie);
+
+#ifdef HAVE_SSL
+ if (http->tls)
+ http_shutdown_ssl(http);
+#endif /* HAVE_SSL */
+
+#ifdef WIN32
+ closesocket(http->fd);
+#else
+ close(http->fd);
+#endif /* WIN32 */
+
+ free(http);
+}
+
+
+/*
+ * 'httpConnect()' - Connect to a HTTP server.
+ */
+
+http_t * /* O - New HTTP connection */
+httpConnect(const char *host, /* I - Host to connect to */
+ int port) /* I - Port number */
+{
+ http_encryption_t encrypt;/* Type of encryption to use */
+
+
+ /*
+ * Set the default encryption status...
+ */
+
+ if (port == 443)
+ encrypt = HTTP_ENCRYPT_ALWAYS;
+ else
+ encrypt = HTTP_ENCRYPT_IF_REQUESTED;
+
+ return (httpConnectEncrypt(host, port, encrypt));
+}
+
+
+/*
+ * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
+ */
+
+http_t * /* O - New HTTP connection */
+httpConnectEncrypt(const char *host, /* I - Host to connect to */
+ int port, /* I - Port number */
+ http_encryption_t encrypt)
+ /* I - Type of encryption to use */
+{
+ int i; /* Looping var */
+ http_t *http; /* New HTTP connection */
+ struct hostent *hostaddr; /* Host address data */
+
+
+ DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encrypt=%d)\n",
+ host ? host : "(null)", port, encrypt));
+
+ if (!host)
+ return (NULL);
+
+ httpInitialize();
+
+ /*
+ * Lookup the host...
+ */
+
+ if ((hostaddr = httpGetHostByName(host)) == NULL)
+ {
+ /*
+ * This hack to make users that don't have a localhost entry in
+ * their hosts file or DNS happy...
+ */
+
+ if (strcasecmp(host, "localhost") != 0)
+ return (NULL);
+ else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
+ return (NULL);
+ }
+
+ /*
+ * Verify that it is an IPv4 address (IPv6 support will come in CUPS 1.2...)
+ */
+
+ if (hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4)
+ return (NULL);
+
+ /*
+ * Allocate memory for the structure...
+ */
+
+ http = calloc(sizeof(http_t), 1);
+ if (http == NULL)
+ return (NULL);
+
+ http->version = HTTP_1_1;
+ http->blocking = 1;
+ http->activity = time(NULL);
+ http->fd = -1;
+
+ /*
+ * Copy the hostname and port and then "reconnect"...
+ */
+
+ strlcpy(http->hostname, host, sizeof(http->hostname));
+ http->hostaddr.sin_family = hostaddr->h_addrtype;
+#ifdef WIN32
+ http->hostaddr.sin_port = htons((u_short)port);
+#else
+ http->hostaddr.sin_port = htons(port);
+#endif /* WIN32 */
+
+ /*
+ * Set the encryption status...
+ */
+
+ if (port == 443) /* Always use encryption for https */
+ http->encryption = HTTP_ENCRYPT_ALWAYS;
+ else
+ http->encryption = encrypt;
+
+ /*
+ * Loop through the addresses we have until one of them connects...
+ */
+
+ strlcpy(http->hostname, host, sizeof(http->hostname));
+
+ for (i = 0; hostaddr->h_addr_list[i]; i ++)
+ {
+ /*
+ * Load the address...
+ */
+
+ memcpy((char *)&(http->hostaddr.sin_addr), hostaddr->h_addr_list[i],
+ hostaddr->h_length);
+
+ /*
+ * Connect to the remote system...
+ */
+
+ if (!httpReconnect(http))
+ return (http);
+ }
+
+ /*
+ * Could not connect to any known address - bail out!
+ */
+
+ free(http);
+ return (NULL);
+}
+
+
+/*
+ * 'httpEncryption()' - Set the required encryption on the link.
+ */
+
+int /* O - -1 on error, 0 on success */
+httpEncryption(http_t *http, /* I - HTTP data */
+ http_encryption_t e) /* I - New encryption preference */
+{
+ DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
+
+#ifdef HAVE_SSL
+ if (!http)
+ return (0);
+
+ http->encryption = e;
+
+ if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
+ (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
+ return (httpReconnect(http));
+ else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
+ return (http_upgrade(http));
+ else
+ return (0);
+#else
+ if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
+ return (-1);
+ else
+ return (0);
+#endif /* HAVE_SSL */
+}
+
+
+/*
+ * 'httpReconnect()' - Reconnect to a HTTP server...
+ */
+
+int /* O - 0 on success, non-zero on failure */
+httpReconnect(http_t *http) /* I - HTTP data */
+{
+ int val; /* Socket option value */
+
+
+ DEBUG_printf(("httpReconnect(http=%p)\n", http));
+
+ if (!http)
+ return (-1);
+
+#ifdef HAVE_SSL
+ if (http->tls)
+ http_shutdown_ssl(http);
+#endif /* HAVE_SSL */
+
+ /*
+ * Close any previously open socket...
+ */
+
+ if (http->fd >= 0)
+#ifdef WIN32
+ closesocket(http->fd);
+#else
+ close(http->fd);
+#endif /* WIN32 */
+
+ /*
+ * Create the socket and set options to allow reuse.
+ */
+
+ if ((http->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+#ifdef WIN32
+ http->error = WSAGetLastError();
+#else
+ http->error = errno;
+#endif /* WIN32 */
+ http->status = HTTP_ERROR;
+ return (-1);
+ }
+
+#ifdef FD_CLOEXEC
+ fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting *
+ * other processes... */
+#endif /* FD_CLOEXEC */
+
+ val = 1;
+ setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+
+#ifdef SO_REUSEPORT
+ val = 1;
+ setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
+#endif /* SO_REUSEPORT */
+
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface... Since we write large buffers
+ * when sending print files and requests, there shouldn't be any
+ * performance penalty for this...
+ */
+
+ val = 1;
+#ifdef WIN32
+ setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
+#else
+ setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+#endif // WIN32
+
+ /*
+ * Connect to the server...
+ */
+
+ if (connect(http->fd, (struct sockaddr *)&(http->hostaddr),
+ sizeof(http->hostaddr)) < 0)
+ {
+#ifdef WIN32
+ http->error = WSAGetLastError();
+#else
+ http->error = errno;
+#endif /* WIN32 */
+ http->status = HTTP_ERROR;
+
+#ifdef WIN32
+ closesocket(http->fd);
+#else
+ close(http->fd);
+#endif
+
+ http->fd = -1;
+
+ return (-1);
+ }
+
+ http->error = 0;
+ http->status = HTTP_CONTINUE;
+
+#ifdef HAVE_SSL
+ if (http->encryption == HTTP_ENCRYPT_ALWAYS)
+ {
+ /*
+ * Always do encryption via SSL.
+ */
+
+ if (http_setup_ssl(http) != 0)
+ {
+#ifdef WIN32
+ closesocket(http->fd);
+#else
+ close(http->fd);
+#endif /* WIN32 */
+
+ return (-1);
+ }
+ }
+ else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
+ return (http_upgrade(http));
+#endif /* HAVE_SSL */
+
+ return (0);
+}
+
+
+/*
+ * 'httpGetSubField()' - Get a sub-field value.
+ */
+
+char * /* O - Value or NULL */
+httpGetSubField(http_t *http, /* I - HTTP data */
+ http_field_t field, /* I - Field index */
+ const char *name, /* I - Name of sub-field */
+ char *value) /* O - Value string */
+{
+ const char *fptr; /* Pointer into field */
+ char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
+ *ptr; /* Pointer into string buffer */
+
+
+ DEBUG_printf(("httpGetSubField(http=%p, field=%d, name=\"%s\", value=%p)\n",
+ http, field, name, value));
+
+ if (http == NULL ||
+ field < HTTP_FIELD_ACCEPT_LANGUAGE ||
+ field > HTTP_FIELD_WWW_AUTHENTICATE ||
+ name == NULL || value == NULL)
+ return (NULL);
+
+ for (fptr = http->fields[field]; *fptr;)
+ {
+ /*
+ * Skip leading whitespace...
+ */
+
+ while (isspace(*fptr & 255))
+ fptr ++;
+
+ if (*fptr == ',')
+ {
+ fptr ++;
+ continue;
+ }
+
+ /*
+ * Get the sub-field name...
+ */
+
+ for (ptr = temp;
+ *fptr && *fptr != '=' && !isspace(*fptr & 255) && ptr < (temp + sizeof(temp) - 1);
+ *ptr++ = *fptr++);
+
+ *ptr = '\0';
+
+ DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
+
+ /*
+ * Skip trailing chars up to the '='...
+ */
+
+ while (isspace(*fptr & 255))
+ fptr ++;
+
+ if (!*fptr)
+ break;
+
+ if (*fptr != '=')
+ continue;
+
+ /*
+ * Skip = and leading whitespace...
+ */
+
+ fptr ++;
+
+ while (isspace(*fptr & 255))
+ fptr ++;
+
+ if (*fptr == '\"')
+ {
+ /*
+ * Read quoted string...
+ */
+
+ for (ptr = value, fptr ++;
+ *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1);
+ *ptr++ = *fptr++);
+
+ *ptr = '\0';
+
+ while (*fptr && *fptr != '\"')
+ fptr ++;
+
+ if (*fptr)
+ fptr ++;
+ }
+ else
+ {
+ /*
+ * Read unquoted string...
+ */
+
+ for (ptr = value;
+ *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1);
+ *ptr++ = *fptr++);
+
+ *ptr = '\0';
+
+ while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
+ fptr ++;
+ }
+
+ DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
+
+ /*
+ * See if this is the one...
+ */
+
+ if (strcmp(name, temp) == 0)
+ return (value);
+ }
+
+ value[0] = '\0';
+
+ return (NULL);
+}
+
+
+/*
+ * 'httpSetField()' - Set the value of an HTTP header.
+ */
+
+void
+httpSetField(http_t *http, /* I - HTTP data */
+ http_field_t field, /* I - Field index */
+ const char *value) /* I - Value */
+{
+ if (http == NULL ||
+ field < HTTP_FIELD_ACCEPT_LANGUAGE ||
+ field > HTTP_FIELD_WWW_AUTHENTICATE ||
+ value == NULL)
+ return;
+
+ strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
+}
+
+
+/*
+ * 'httpDelete()' - Send a DELETE request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpDelete(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI to delete */
+{
+ return (http_send(http, HTTP_DELETE, uri));
+}
+
+
+/*
+ * 'httpGet()' - Send a GET request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpGet(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI to get */
+{
+ return (http_send(http, HTTP_GET, uri));
+}
+
+
+/*
+ * 'httpHead()' - Send a HEAD request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpHead(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI for head */
+{
+ return (http_send(http, HTTP_HEAD, uri));
+}
+
+
+/*
+ * 'httpOptions()' - Send an OPTIONS request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpOptions(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI for options */
+{
+ return (http_send(http, HTTP_OPTIONS, uri));
+}
+
+
+/*
+ * 'httpPost()' - Send a POST request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpPost(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI for post */
+{
+ httpGetLength(http);
+
+ return (http_send(http, HTTP_POST, uri));
+}
+
+
+/*
+ * 'httpPut()' - Send a PUT request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpPut(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI to put */
+{
+ httpGetLength(http);
+
+ return (http_send(http, HTTP_PUT, uri));
+}
+
+
+/*
+ * 'httpTrace()' - Send an TRACE request to the server.
+ */
+
+int /* O - Status of call (0 = success) */
+httpTrace(http_t *http, /* I - HTTP data */
+ const char *uri) /* I - URI for trace */
+{
+ return (http_send(http, HTTP_TRACE, uri));
+}
+
+
+/*
+ * 'httpFlush()' - Flush data from a HTTP connection.
+ */
+
+void
+httpFlush(http_t *http) /* I - HTTP data */
+{
+ char buffer[8192]; /* Junk buffer */
+
+
+ DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
+
+ while (httpRead(http, buffer, sizeof(buffer)) > 0);
+}
+
+
+/*
+ * 'httpRead()' - Read data from a HTTP connection.
+ */
+
+int /* O - Number of bytes read */
+httpRead(http_t *http, /* I - HTTP data */
+ char *buffer, /* I - Buffer for data */
+ int length) /* I - Maximum number of bytes */
+{
+ int bytes; /* Bytes read */
+ char len[32]; /* Length string */
+
+
+ DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
+ http, buffer, length));
+
+ if (http == NULL || buffer == NULL)
+ return (-1);
+
+ http->activity = time(NULL);
+
+ if (length <= 0)
+ return (0);
+
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
+ http->data_remaining <= 0)
+ {
+ DEBUG_puts("httpRead: Getting chunk length...");
+
+ if (httpGets(len, sizeof(len), http) == NULL)
+ {
+ DEBUG_puts("httpRead: Could not get length!");
+ return (0);
+ }
+
+ http->data_remaining = strtol(len, NULL, 16);
+ if (http->data_remaining < 0)
+ {
+ DEBUG_puts("httpRead: Negative chunk length!");
+ return (0);
+ }
+ }
+
+ DEBUG_printf(("httpRead: data_remaining=%d\n", http->data_remaining));
+
+ if (http->data_remaining <= 0)
+ {
+ /*
+ * A zero-length chunk ends a transfer; unless we are reading POST
+ * data, go idle...
+ */
+
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ httpGets(len, sizeof(len), http);
+
+ if (http->state == HTTP_POST_RECV)
+ http->state ++;
+ else
+ http->state = HTTP_WAITING;
+
+ /*
+ * Prevent future reads for this request...
+ */
+
+ http->data_encoding = HTTP_ENCODE_LENGTH;
+
+ return (0);
+ }
+ else if (length > http->data_remaining)
+ length = http->data_remaining;
+
+ if (http->used == 0 && length <= 256)
+ {
+ /*
+ * Buffer small reads for better performance...
+ */
+
+ if (!http->blocking && !httpWait(http, 1000))
+ return (0);
+
+ if (http->data_remaining > sizeof(http->buffer))
+ bytes = sizeof(http->buffer);
+ else
+ bytes = http->data_remaining;
+
+#ifdef HAVE_SSL
+ if (http->tls)
+ bytes = http_read_ssl(http, http->buffer, bytes);
+ else
+#endif /* HAVE_SSL */
+ {
+ DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
+ bytes));
+
+ bytes = recv(http->fd, http->buffer, bytes, 0);
+
+ DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
+ bytes));
+ }
+
+ if (bytes > 0)
+ http->used = bytes;
+ else if (bytes < 0)
+ {
+#ifdef WIN32
+ http->error = WSAGetLastError();
+ return (-1);
+#else
+ if (errno != EINTR)
+ {
+ http->error = errno;
+ return (-1);
+ }
+#endif /* WIN32 */
+ }
+ else
+ {
+ http->error = EPIPE;
+ return (0);
+ }
+ }
+
+ if (http->used > 0)
+ {
+ if (length > http->used)
+ length = http->used;
+
+ bytes = length;
+
+ DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
+
+ memcpy(buffer, http->buffer, length);
+ http->used -= length;
+
+ if (http->used > 0)
+ memmove(http->buffer, http->buffer + length, http->used);
+ }
+#ifdef HAVE_SSL
+ else if (http->tls)
+ {
+ if (!http->blocking && !httpWait(http, 1000))
+ return (0);
+
+ bytes = http_read_ssl(http, buffer, length);
+ }
+#endif /* HAVE_SSL */
+ else
+ {
+ if (!http->blocking && !httpWait(http, 1000))
+ return (0);
+
+ DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
+ bytes = recv(http->fd, buffer, length, 0);
+ DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
+ }
+
+ if (bytes > 0)
+ http->data_remaining -= bytes;
+ else if (bytes < 0)
+ {
+#ifdef WIN32
+ http->error = WSAGetLastError();
+#else
+ if (errno == EINTR)
+ bytes = 0;
+ else
+ http->error = errno;
+#endif /* WIN32 */
+ }
+ else
+ {
+ http->error = EPIPE;
+ return (0);
+ }
+
+ if (http->data_remaining == 0)
+ {
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ httpGets(len, sizeof(len), http);
+
+ if (http->data_encoding != HTTP_ENCODE_CHUNKED)
+ {
+ if (http->state == HTTP_POST_RECV)
+ http->state ++;
+ else
+ http->state = HTTP_WAITING;
+ }
+ }
+
+#ifdef DEBUG
+ {
+ int i, j, ch;
+ printf("httpRead: Read %d bytes:\n", bytes);
+ for (i = 0; i < bytes; i += 16)
+ {
+ printf(" ");
+
+ for (j = 0; j < 16 && (i + j) < bytes; j ++)
+ printf(" %02X", buffer[i + j] & 255);
+
+ while (j < 16)
+ {
+ printf(" ");
+ j ++;
+ }
+
+ printf(" ");
+ for (j = 0; j < 16 && (i + j) < bytes; j ++)
+ {
+ ch = buffer[i + j] & 255;
+
+ if (ch < ' ' || ch == 127)
+ ch = '.';
+
+ putchar(ch);
+ }
+ putchar('\n');
+ }
+ }
+#endif /* DEBUG */
+
+ return (bytes);
+}
+
+
+/*
+ * 'httpSetCookie()' - Set the cookie value(s)...
+ */
+
+void
+httpSetCookie(http_t *http, /* I - Connection */
+ const char *cookie) /* I - Cookie string */
+{
+ if (!http)
+ return;
+
+ if (http->cookie)
+ free(http->cookie);
+
+ if (cookie)
+ http->cookie = strdup(cookie);
+ else
+ http->cookie = NULL;
+}
+
+
+/*
+ * 'httpWait()' - Wait for data available on a connection.
+ */
+
+int /* O - 1 if data is available, 0 otherwise */
+httpWait(http_t *http, /* I - HTTP data */
+ int msec) /* I - Milliseconds to wait */
+{
+ /*
+ * First see if there is data in the buffer...
+ */
+
+ if (http == NULL)
+ return (0);
+
+ if (http->used)
+ return (1);
+
+ /*
+ * If not, check the SSL/TLS buffers and do a select() on the connection...
+ */
+
+ return (http_wait(http, msec));
+}
+
+
+/*
+ * 'httpWrite()' - Write data to a HTTP connection.
+ */
+
+int /* O - Number of bytes written */
+httpWrite(http_t *http, /* I - HTTP data */
+ const char *buffer, /* I - Buffer for data */
+ int length) /* I - Number of bytes to write */
+{
+ int tbytes, /* Total bytes sent */
+ bytes; /* Bytes sent */
+
+
+ if (http == NULL || buffer == NULL)
+ return (-1);
+
+ http->activity = time(NULL);
+
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ {
+ if (httpPrintf(http, "%x\r\n", length) < 0)
+ return (-1);
+
+ if (length == 0)
+ {
+ /*
+ * A zero-length chunk ends a transfer; unless we are sending POST
+ * or PUT data, go idle...
+ */
+
+ DEBUG_puts("httpWrite: changing states...");
+
+ if (http->state == HTTP_POST_RECV)
+ http->state ++;
+ else if (http->state == HTTP_PUT_RECV)
+ http->state = HTTP_STATUS;
+ else
+ http->state = HTTP_WAITING;
+
+ if (httpPrintf(http, "\r\n") < 0)
+ return (-1);
+
+ return (0);
+ }
+ }
+
+ tbytes = 0;
+
+ while (length > 0)
+ {
+#ifdef HAVE_SSL
+ if (http->tls)
+ bytes = http_write_ssl(http, buffer, length);
+ else
+#endif /* HAVE_SSL */
+ bytes = send(http->fd, buffer, length, 0);
+
+ if (bytes < 0)
+ {
+#ifdef WIN32
+ if (WSAGetLastError() != http->error)
+ {
+ http->error = WSAGetLastError();
+ continue;
+ }
+#else
+ if (errno == EINTR)
+ continue;
+ else if (errno != http->error && errno != ECONNRESET)
+ {
+ http->error = errno;
+ continue;
+ }
+#endif /* WIN32 */
+
+ DEBUG_puts("httpWrite: error writing data...\n");
+
+ return (-1);
+ }
+
+ buffer += bytes;
+ tbytes += bytes;
+ length -= bytes;
+ if (http->data_encoding == HTTP_ENCODE_LENGTH)
+ http->data_remaining -= bytes;
+ }
+
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ if (httpPrintf(http, "\r\n") < 0)
+ return (-1);
+
+ if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
+ {
+ /*
+ * Finished with the transfer; unless we are sending POST or PUT
+ * data, go idle...
+ */
+
+ DEBUG_puts("httpWrite: changing states...");
+
+ if (http->state == HTTP_POST_RECV)
+ http->state ++;
+ else if (http->state == HTTP_PUT_RECV)
+ http->state = HTTP_STATUS;
+ else
+ http->state = HTTP_WAITING;
+ }
+
+#ifdef DEBUG
+ {
+ int i, j, ch;
+ printf("httpWrite: wrote %d bytes: \n", tbytes);
+ for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
+ {
+ printf(" ");
+
+ for (j = 0; j < 16 && (i + j) < tbytes; j ++)
+ printf(" %02X", buffer[i + j] & 255);
+
+ while (j < 16)
+ {
+ printf(" ");
+ j ++;
+ }
+
+ printf(" ");
+ for (j = 0; j < 16 && (i + j) < tbytes; j ++)
+ {
+ ch = buffer[i + j] & 255;
+
+ if (ch < ' ' || ch == 127)
+ ch = '.';
+
+ putchar(ch);
+ }
+ putchar('\n');
+ }
+ }
+#endif /* DEBUG */
+ return (tbytes);
+}
+
+
+/*
+ * 'httpGets()' - Get a line of text from a HTTP connection.
+ */
+
+char * /* O - Line or NULL */
+httpGets(char *line, /* I - Line to read into */
+ int length, /* I - Max length of buffer */
+ http_t *http) /* I - HTTP data */
+{
+ char *lineptr, /* Pointer into line */
+ *bufptr, /* Pointer into input buffer */
+ *bufend; /* Pointer to end of buffer */
+ int bytes; /* Number of bytes read */
+
+
+ DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
+
+ if (http == NULL || line == NULL)
+ return (NULL);
+
+ /*
+ * Pre-scan the buffer and see if there is a newline in there...
+ */
+
+#ifdef WIN32
+ WSASetLastError(0);
+#else
+ errno = 0;
+#endif /* WIN32 */
+
+ do
+ {
+ bufptr = http->buffer;
+ bufend = http->buffer + http->used;
+
+ while (bufptr < bufend)
+ if (*bufptr == 0x0a)
+ break;
+ else
+ bufptr ++;
+
+ if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER)
+ {
+ /*
+ * No newline; see if there is more data to be read...
+ */
+
+ if (!http->blocking && !http_wait(http, 1000))
+ return (NULL);
+
+#ifdef HAVE_SSL
+ if (http->tls)
+ bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used);
+ else
+#endif /* HAVE_SSL */
+ bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0);
+
+ DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
+
+ if (bytes < 0)
+ {
+ /*
+ * Nope, can't get a line this time...
+ */
+
+#ifdef WIN32
+ if (WSAGetLastError() != http->error)
+ {
+ http->error = WSAGetLastError();
+ continue;
+ }
+
+ DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
+#else
+ DEBUG_printf(("httpGets: recv() error %d!\n", errno));
+
+ if (errno == EINTR)
+ continue;
+ else if (errno != http->error)
+ {
+ http->error = errno;
+ continue;
+ }
+#endif /* WIN32 */
+
+ return (NULL);
+ }
+ else if (bytes == 0)
+ {
+ http->error = EPIPE;
+
+ return (NULL);
+ }
+
+ /*
+ * Yup, update the amount used and the end pointer...
+ */
+
+ http->used += bytes;
+ bufend += bytes;
+ bufptr = bufend;
+ }
+ }
+ while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER);
+
+ http->activity = time(NULL);
+
+ /*
+ * Read a line from the buffer...
+ */
+
+ lineptr = line;
+ bufptr = http->buffer;
+ bytes = 0;
+ length --;
+
+ while (bufptr < bufend && bytes < length)
+ {
+ bytes ++;
+
+ if (*bufptr == 0x0a)
+ {
+ bufptr ++;
+ break;
+ }
+ else if (*bufptr == 0x0d)
+ bufptr ++;
+ else
+ *lineptr++ = *bufptr++;
+ }
+
+ if (bytes > 0)
+ {
+ *lineptr = '\0';
+
+ http->used -= bytes;
+ if (http->used > 0)
+ memmove(http->buffer, bufptr, http->used);
+
+ DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
+ return (line);
+ }
+
+ DEBUG_puts("httpGets: No new line available!");
+
+ return (NULL);
+}
+
+
+/*
+ * 'httpPrintf()' - Print a formatted string to a HTTP connection.
+ */
+
+int /* O - Number of bytes written */
+httpPrintf(http_t *http, /* I - HTTP data */
+ const char *format, /* I - printf-style format string */
+ ...) /* I - Additional args as needed */
+{
+ int bytes, /* Number of bytes to write */
+ nbytes, /* Number of bytes written */
+ tbytes; /* Number of bytes all together */
+ char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */
+ *bufptr; /* Pointer into buffer */
+ va_list ap; /* Variable argument pointer */
+
+
+ DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
+
+ va_start(ap, format);
+ bytes = vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+
+ DEBUG_printf(("httpPrintf: %s", buf));
+
+ for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes)
+ {
+#ifdef HAVE_SSL
+ if (http->tls)
+ nbytes = http_write_ssl(http, bufptr, bytes - tbytes);
+ else
+#endif /* HAVE_SSL */
+ nbytes = send(http->fd, bufptr, bytes - tbytes, 0);
+
+ if (nbytes < 0)
+ {
+ nbytes = 0;
+
+#ifdef WIN32
+ if (WSAGetLastError() != http->error)
+ {
+ http->error = WSAGetLastError();
+ continue;
+ }
+#else
+ if (errno == EINTR)
+ continue;
+ else if (errno != http->error)
+ {
+ http->error = errno;
+ continue;
+ }
+#endif /* WIN32 */
+
+ return (-1);
+ }
+ }
+
+ return (bytes);
+}
+
+
+/*
+ * 'httpGetDateString()' - Get a formatted date/time string from a time value.
+ */
+
+const char * /* O - Date/time string */
+httpGetDateString(time_t t) /* I - UNIX time */
+{
+ struct tm *tdate;
+ static char datetime[256];
+
+
+ tdate = gmtime(&t);
+ snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT",
+ days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon],
+ tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec);
+
+ return (datetime);
+}
+
+
+/*
+ * 'httpGetDateTime()' - Get a time value from a formatted date/time string.
+ */
+
+time_t /* O - UNIX time */
+httpGetDateTime(const char *s) /* I - Date/time string */
+{
+ int i; /* Looping var */
+ struct tm tdate; /* Time/date structure */
+ char mon[16]; /* Abbreviated month name */
+ int day, year; /* Day of month and year */
+ int hour, min, sec; /* Time */
+
+
+ if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
+ return (0);
+
+ for (i = 0; i < 12; i ++)
+ if (strcasecmp(mon, months[i]) == 0)
+ break;
+
+ if (i >= 12)
+ return (0);
+
+ tdate.tm_mon = i;
+ tdate.tm_mday = day;
+ tdate.tm_year = year - 1900;
+ tdate.tm_hour = hour;
+ tdate.tm_min = min;
+ tdate.tm_sec = sec;
+ tdate.tm_isdst = 0;
+
+ return (mktime(&tdate));
+}
+
+
+/*
+ * 'httpUpdate()' - Update the current HTTP state for incoming data.
+ */
+
+http_status_t /* O - HTTP status */
+httpUpdate(http_t *http) /* I - HTTP data */
+{
+ char line[1024], /* Line from connection... */
+ *value; /* Pointer to value on line */
+ http_field_t field; /* Field index */
+ int major, minor, /* HTTP version numbers */
+ status; /* Request status */
+
+
+ DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
+
+ /*
+ * If we haven't issued any commands, then there is nothing to "update"...
+ */
+
+ if (http->state == HTTP_WAITING)
+ return (HTTP_CONTINUE);
+
+ /*
+ * Grab all of the lines we can from the connection...
+ */
+
+ while (httpGets(line, sizeof(line), http) != NULL)
+ {
+ DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
+
+ if (line[0] == '\0')
+ {
+ /*
+ * Blank line means the start of the data section (if any). Return
+ * the result code, too...
+ *
+ * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
+ * Instead, we just return HTTP_CONTINUE to the caller and keep on
+ * tryin'...
+ */
+
+ if (http->status == HTTP_CONTINUE)
+ return (http->status);
+
+ if (http->status < HTTP_BAD_REQUEST)
+ http->digest_tries = 0;
+
+#ifdef HAVE_SSL
+ if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
+ {
+ if (http_setup_ssl(http) != 0)
+ {
+# ifdef WIN32
+ closesocket(http->fd);
+# else
+ close(http->fd);
+# endif /* WIN32 */
+
+ return (HTTP_ERROR);
+ }
+
+ return (HTTP_CONTINUE);
+ }
+#endif /* HAVE_SSL */
+
+ httpGetLength(http);
+
+ switch (http->state)
+ {
+ case HTTP_GET :
+ case HTTP_POST :
+ case HTTP_POST_RECV :
+ case HTTP_PUT :
+ http->state ++;
+ case HTTP_POST_SEND :
+ break;
+
+ default :
+ http->state = HTTP_WAITING;
+ break;
+ }
+
+ return (http->status);
+ }
+ else if (strncmp(line, "HTTP/", 5) == 0)
+ {
+ /*
+ * Got the beginning of a response...
+ */
+
+ if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
+ return (HTTP_ERROR);
+
+ http->version = (http_version_t)(major * 100 + minor);
+ http->status = (http_status_t)status;
+ }
+ else if ((value = strchr(line, ':')) != NULL)
+ {
+ /*
+ * Got a value...
+ */
+
+ *value++ = '\0';
+ while (isspace(*value & 255))
+ value ++;
+
+ /*
+ * Be tolerants of servers that send unknown attribute fields...
+ */
+
+ if (!strcasecmp(line, "expect"))
+ {
+ /*
+ * "Expect: 100-continue" or similar...
+ */
+
+ http->expect = (http_status_t)atoi(value);
+ }
+ else if (!strcasecmp(line, "cookie"))
+ {
+ /*
+ * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
+ */
+
+ httpSetCookie(http, value);
+ }
+ else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
+ {
+ DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
+ continue;
+ }
+ else
+ httpSetField(http, field, value);
+ }
+ else
+ {
+ http->status = HTTP_ERROR;
+ return (HTTP_ERROR);
+ }
+ }
+
+ /*
+ * See if there was an error...
+ */
+
+ if (http->error == EPIPE && http->status > HTTP_CONTINUE)
+ return (http->status);
+
+ if (http->error)
+ {
+ DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
+ strerror(http->error)));
+ http->status = HTTP_ERROR;
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * If we haven't already returned, then there is nothing new...
+ */
+
+ return (HTTP_CONTINUE);
+}
+
+
+/*
+ * 'httpDecode64()' - Base64-decode a string.
+ */
+
+char * /* O - Decoded string */
+httpDecode64(char *out, /* I - String to write to */
+ const char *in) /* I - String to read from */
+{
+ int outlen; /* Output buffer length */
+
+
+ /*
+ * Use the old maximum buffer size for binary compatibility...
+ */
+
+ outlen = 512;
+
+ return (httpDecode64_2(out, &outlen, in));
+}
+
+
+/*
+ * 'httpDecode64_2()' - Base64-decode a string.
+ */
+
+char * /* O - Decoded string */
+httpDecode64_2(char *out, /* I - String to write to */
+ int *outlen, /* IO - Size of output string */
+ const char *in) /* I - String to read from */
+{
+ int pos, /* Bit position */
+ base64; /* Value of this character */
+ char *outptr, /* Output pointer */
+ *outend; /* End of output buffer */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!out || !outlen || *outlen < 1 || !in || !*in)
+ return (NULL);
+
+ /*
+ * Convert from base-64 to bytes...
+ */
+
+ for (outptr = out, outend = out + *outlen - 1, pos = 0; *in != '\0'; in ++)
+ {
+ /*
+ * Decode this character into a number from 0 to 63...
+ */
+
+ if (*in >= 'A' && *in <= 'Z')
+ base64 = *in - 'A';
+ else if (*in >= 'a' && *in <= 'z')
+ base64 = *in - 'a' + 26;
+ else if (*in >= '0' && *in <= '9')
+ base64 = *in - '0' + 52;
+ else if (*in == '+')
+ base64 = 62;
+ else if (*in == '/')
+ base64 = 63;
+ else if (*in == '=')
+ break;
+ else
+ continue;
+
+ /*
+ * Store the result in the appropriate chars...
+ */
+
+ switch (pos)
+ {
+ case 0 :
+ if (outptr < outend)
+ *outptr = base64 << 2;
+ pos ++;
+ break;
+ case 1 :
+ if (outptr < outend)
+ *outptr++ |= (base64 >> 4) & 3;
+ if (outptr < outend)
+ *outptr = (base64 << 4) & 255;
+ pos ++;
+ break;
+ case 2 :
+ if (outptr < outend)
+ *outptr++ |= (base64 >> 2) & 15;
+ if (outptr < outend)
+ *outptr = (base64 << 6) & 255;
+ pos ++;
+ break;
+ case 3 :
+ if (outptr < outend)
+ *outptr++ |= base64;
+ pos = 0;
+ break;
+ }
+ }
+
+ *outptr = '\0';
+
+ /*
+ * Return the decoded string and size...
+ */
+
+ *outlen = (int)(outptr - out);
+
+ return (out);
+}
+
+
+/*
+ * 'httpEncode64()' - Base64-encode a string.
+ */
+
+char * /* O - Encoded string */
+httpEncode64(char *out, /* I - String to write to */
+ const char *in) /* I - String to read from */
+{
+ return (httpEncode64_2(out, 512, in, strlen(in)));
+}
+
+
+/*
+ * 'httpEncode64_2()' - Base64-encode a string.
+ */
+
+char * /* O - Encoded string */
+httpEncode64_2(char *out, /* I - String to write to */
+ int outlen, /* I - Size of output string */
+ const char *in, /* I - String to read from */
+ int inlen) /* I - Size of input string */
+{
+ char *outptr, /* Output pointer */
+ *outend; /* End of output buffer */
+ static const char base64[] = /* Base64 characters... */
+ {
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "+/"
+ };
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!out || outlen < 1 || !in || inlen < 1)
+ return (NULL);
+
+ /*
+ * Convert bytes to base-64...
+ */
+
+ for (outptr = out, outend = out + outlen - 1; inlen > 0; in ++, inlen --)
+ {
+ /*
+ * Encode the up to 3 characters as 4 Base64 numbers...
+ */
+
+ if (outptr < outend)
+ *outptr ++ = base64[(in[0] & 255) >> 2];
+ if (outptr < outend)
+ *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63];
+
+ in ++;
+ inlen --;
+ if (inlen <= 0)
+ {
+ if (outptr < outend)
+ *outptr ++ = '=';
+ if (outptr < outend)
+ *outptr ++ = '=';
+ break;
+ }
+
+ if (outptr < outend)
+ *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63];
+
+ in ++;
+ inlen --;
+ if (inlen <= 0)
+ {
+ if (outptr < outend)
+ *outptr ++ = '=';
+ break;
+ }
+
+ if (outptr < outend)
+ *outptr ++ = base64[in[0] & 63];
+ }
+
+ *outptr = '\0';
+
+ /*
+ * Return the encoded string...
+ */
+
+ return (out);
+}
+
+
+/*
+ * 'httpGetLength()' - Get the amount of data remaining from the
+ * content-length or transfer-encoding fields.
+ */
+
+int /* O - Content length */
+httpGetLength(http_t *http) /* I - HTTP data */
+{
+ DEBUG_printf(("httpGetLength(http=%p), state=%d\n", http, http->state));
+
+ if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0)
+ {
+ DEBUG_puts("httpGetLength: chunked request!");
+
+ http->data_encoding = HTTP_ENCODE_CHUNKED;
+ http->data_remaining = 0;
+ }
+ else
+ {
+ http->data_encoding = HTTP_ENCODE_LENGTH;
+
+ /*
+ * The following is a hack for HTTP servers that don't send a
+ * content-length or transfer-encoding field...
+ *
+ * If there is no content-length then the connection must close
+ * after the transfer is complete...
+ */
+
+ if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
+ http->data_remaining = 2147483647;
+ else
+ http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]);
+
+ DEBUG_printf(("httpGetLength: content_length=%d\n", http->data_remaining));
+ }
+
+ return (http->data_remaining);
+}
+
+
+/*
+ * 'http_field()' - Return the field index for a field name.
+ */
+
+static http_field_t /* O - Field index */
+http_field(const char *name) /* I - String name */
+{
+ int i; /* Looping var */
+
+
+ for (i = 0; i < HTTP_FIELD_MAX; i ++)
+ if (strcasecmp(name, http_fields[i]) == 0)
+ return ((http_field_t)i);
+
+ return (HTTP_FIELD_UNKNOWN);
+}
+
+
+/*
+ * 'http_send()' - Send a request with all fields and the trailing blank line.
+ */
+
+static int /* O - 0 on success, non-zero on error */
+http_send(http_t *http, /* I - HTTP data */
+ http_state_t request, /* I - Request code */
+ const char *uri) /* I - URI */
+{
+ int i; /* Looping var */
+ char *ptr, /* Pointer in buffer */
+ buf[1024]; /* Encoded URI buffer */
+ static const char * const codes[] =
+ { /* Request code strings */
+ NULL,
+ "OPTIONS",
+ "GET",
+ NULL,
+ "HEAD",
+ "POST",
+ NULL,
+ NULL,
+ "PUT",
+ NULL,
+ "DELETE",
+ "TRACE",
+ "CLOSE"
+ };
+ static const char hex[] = "0123456789ABCDEF";
+ /* Hex digits */
+
+
+ DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
+ http, codes[request], uri));
+
+ if (http == NULL || uri == NULL)
+ return (-1);
+
+ /*
+ * Encode the URI as needed...
+ */
+
+ for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
+ if (*uri <= ' ' || *uri >= 127)
+ {
+ if (ptr < (buf + sizeof(buf) - 1))
+ *ptr ++ = '%';
+ if (ptr < (buf + sizeof(buf) - 1))
+ *ptr ++ = hex[(*uri >> 4) & 15];
+ if (ptr < (buf + sizeof(buf) - 1))
+ *ptr ++ = hex[*uri & 15];
+ }
+ else
+ *ptr ++ = *uri;
+
+ *ptr = '\0';
+
+ /*
+ * See if we had an error the last time around; if so, reconnect...
+ */
+
+ if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
+ httpReconnect(http);
+
+ /*
+ * Send the request header...
+ */
+
+ http->state = request;
+ if (request == HTTP_POST || request == HTTP_PUT)
+ http->state ++;
+
+ http->status = HTTP_CONTINUE;
+
+#ifdef HAVE_SSL
+ if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
+ {
+ httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
+ httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
+ }
+#endif /* HAVE_SSL */
+
+ if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
+ {
+ http->status = HTTP_ERROR;
+ return (-1);
+ }
+
+ for (i = 0; i < HTTP_FIELD_MAX; i ++)
+ if (http->fields[i][0] != '\0')
+ {
+ DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
+
+ if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
+ {
+ http->status = HTTP_ERROR;
+ return (-1);
+ }
+ }
+
+ if (httpPrintf(http, "\r\n") < 1)
+ {
+ http->status = HTTP_ERROR;
+ return (-1);
+ }
+
+ httpClearFields(http);
+
+ return (0);
+}
+
+
+/*
+ * 'http_wait()' - Wait for data available on a connection.
+ */
+
+static int /* O - 1 if data is available, 0 otherwise */
+http_wait(http_t *http, /* I - HTTP data */
+ int msec) /* I - Milliseconds to wait */
+{
+#ifndef WIN32
+ struct rlimit limit; /* Runtime limit */
+#endif /* !WIN32 */
+ struct timeval timeout; /* Timeout */
+ int nfds; /* Result from select() */
+ int set_size; /* Size of select set */
+
+
+ DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
+
+ /*
+ * Check the SSL/TLS buffers for data first...
+ */
+
+#ifdef HAVE_SSL
+ if (http->tls)
+ {
+# ifdef HAVE_LIBSSL
+ if (SSL_pending((SSL *)(http->tls)))
+ return (1);
+# elif defined(HAVE_GNUTLS)
+ if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
+ return (1);
+# elif defined(HAVE_CDSASSL)
+ size_t bytes; /* Bytes that are available */
+
+ if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
+ return;
+# endif /* HAVE_LIBSSL */
+ }
+#endif /* HAVE_SSL */
+
+ /*
+ * Then try doing a select() to poll the socket...
+ */
+
+ if (!http->input_set)
+ {
+#ifdef WIN32
+ /*
+ * Windows has a fixed-size select() structure, different (surprise,
+ * surprise!) from all UNIX implementations. Just allocate this
+ * fixed structure...
+ */
+
+ http->input_set = calloc(1, sizeof(fd_set));
+#else
+ /*
+ * Allocate the select() input set based upon the max number of file
+ * descriptors available for this process...
+ */
+
+ getrlimit(RLIMIT_NOFILE, &limit);
+
+ set_size = (limit.rlim_cur + 31) / 8 + 4;
+ if (set_size < sizeof(fd_set))
+ set_size = sizeof(fd_set);
+
+ http->input_set = calloc(1, set_size);
+#endif /* WIN32 */
+
+ if (!http->input_set)
+ return (0);
+ }
+
+ do
+ {
+ FD_SET(http->fd, http->input_set);
+
+ if (msec >= 0)
+ {
+ timeout.tv_sec = msec / 1000;
+ timeout.tv_usec = (msec % 1000) * 1000;
+
+ nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
+ }
+ else
+ nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
+ }
+#ifdef WIN32
+ while (nfds < 0 && WSAGetLastError() == WSAEINTR);
+#else
+ while (nfds < 0 && errno == EINTR);
+#endif /* WIN32 */
+
+ FD_CLR(http->fd, http->input_set);
+
+ return (nfds > 0);
+}
+
+
+#ifdef HAVE_SSL
+/*
+ * 'http_upgrade()' - Force upgrade to TLS encryption.
+ */
+
+static int /* O - Status of connection */
+http_upgrade(http_t *http) /* I - HTTP data */
+{
+ int ret; /* Return value */
+ http_t myhttp; /* Local copy of HTTP data */
+
+
+ DEBUG_printf(("http_upgrade(%p)\n", http));
+
+ /*
+ * Copy the HTTP data to a local variable so we can do the OPTIONS
+ * request without interfering with the existing request data...
+ */
+
+ memcpy(&myhttp, http, sizeof(myhttp));
+
+ /*
+ * Send an OPTIONS request to the server, requiring SSL or TLS
+ * encryption on the link...
+ */
+
+ httpClearFields(&myhttp);
+ httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
+ httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
+
+ if ((ret = httpOptions(&myhttp, "*")) == 0)
+ {
+ /*
+ * Wait for the secure connection...
+ */
+
+ while (httpUpdate(&myhttp) == HTTP_CONTINUE);
+ }
+
+ httpFlush(&myhttp);
+
+ /*
+ * Copy the HTTP data back over, if any...
+ */
+
+ http->fd = myhttp.fd;
+ http->error = myhttp.error;
+ http->activity = myhttp.activity;
+ http->status = myhttp.status;
+ http->version = myhttp.version;
+ http->keep_alive = myhttp.keep_alive;
+ http->used = myhttp.used;
+
+ if (http->used)
+ memcpy(http->buffer, myhttp.buffer, http->used);
+
+ http->auth_type = myhttp.auth_type;
+ http->nonce_count = myhttp.nonce_count;
+
+ memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
+
+ http->tls = myhttp.tls;
+ http->encryption = myhttp.encryption;
+
+ /*
+ * See if we actually went secure...
+ */
+
+ if (!http->tls)
+ {
+ /*
+ * Server does not support HTTP upgrade...
+ */
+
+ DEBUG_puts("Server does not support HTTP upgrade!");
+
+# ifdef WIN32
+ closesocket(http->fd);
+# else
+ close(http->fd);
+# endif
+
+ http->fd = -1;
+
+ return (-1);
+ }
+ else
+ return (ret);
+}
+
+
+/*
+ * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
+ */
+
+static int /* O - Status of connection */
+http_setup_ssl(http_t *http) /* I - HTTP data */
+{
+# ifdef HAVE_LIBSSL
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
+# elif defined(HAVE_GNUTLS)
+ http_tls_t *conn; /* TLS session object */
+ gnutls_certificate_client_credentials *credentials;
+ /* TLS credentials */
+# elif defined(HAVE_CDSASSL)
+ SSLContextRef conn; /* Context for encryption */
+ OSStatus error; /* Error info */
+# endif /* HAVE_LIBSSL */
+
+
+ DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
+
+# ifdef HAVE_LIBSSL
+ context = SSL_CTX_new(SSLv23_client_method());
+ conn = SSL_new(context);
+
+ SSL_set_fd(conn, http->fd);
+ if (SSL_connect(conn) != 1)
+ {
+# ifdef DEBUG
+ unsigned long error; /* Error code */
+
+ while ((error = ERR_get_error()) != 0)
+ printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
+# endif /* DEBUG */
+
+ SSL_CTX_free(context);
+ SSL_free(conn);
+
+# ifdef WIN32
+ http->error = WSAGetLastError();
+# else
+ http->error = errno;
+# endif /* WIN32 */
+ http->status = HTTP_ERROR;
+
+ return (HTTP_ERROR);
+ }
+
+# elif defined(HAVE_GNUTLS)
+ conn = (http_tls_t *)malloc(sizeof(http_tls_t));
+
+ if (conn == NULL)
+ {
+ http->error = errno;
+ http->status = HTTP_ERROR;
+
+ return (-1);
+ }
+
+ credentials = (gnutls_certificate_client_credentials *)
+ malloc(sizeof(gnutls_certificate_client_credentials));
+ if (credentials == NULL)
+ {
+ free(conn);
+
+ http->error = errno;
+ http->status = HTTP_ERROR;
+
+ return (-1);
+ }
+
+ gnutls_certificate_allocate_credentials(credentials);
+
+ gnutls_init(&(conn->session), GNUTLS_CLIENT);
+ gnutls_set_default_priority(conn->session);
+ gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
+ gnutls_transport_set_ptr(conn->session, http->fd);
+
+ if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
+ {
+ http->error = errno;
+ http->status = HTTP_ERROR;
+
+ return (-1);
+ }
+
+ conn->credentials = credentials;
+
+# elif defined(HAVE_CDSASSL)
+ error = SSLNewContext(false, &conn);
+
+ if (!error)
+ error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc);
+
+ if (!error)
+ error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
+
+ if (!error)
+ error = SSLSetAllowsExpiredCerts(conn, true);
+
+ if (!error)
+ error = SSLSetAllowsAnyRoot(conn, true);
+
+ if (!error)
+ error = SSLHandshake(conn);
+
+ if (error != 0)
+ {
+ http->error = error;
+ http->status = HTTP_ERROR;
+
+ SSLDisposeContext(conn);
+
+ close(http->fd);
+
+ return (-1);
+ }
+# endif /* HAVE_CDSASSL */
+
+ http->tls = conn;
+ return (0);
+}
+
+
+/*
+ * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
+ */
+
+static void
+http_shutdown_ssl(http_t *http) /* I - HTTP data */
+{
+# ifdef HAVE_LIBSSL
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
+
+
+ conn = (SSL *)(http->tls);
+ context = SSL_get_SSL_CTX(conn);
+
+ SSL_shutdown(conn);
+ SSL_CTX_free(context);
+ SSL_free(conn);
+
+# elif defined(HAVE_GNUTLS)
+ http_tls_t *conn; /* Encryption session */
+ gnutls_certificate_client_credentials *credentials;
+ /* TLS credentials */
+
+
+ conn = (http_tls_t *)(http->tls);
+ credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
+
+ gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
+ gnutls_deinit(conn->session);
+ gnutls_certificate_free_credentials(*credentials);
+ free(credentials);
+ free(conn);
+
+# elif defined(HAVE_CDSASSL)
+ SSLClose((SSLContextRef)http->tls);
+ SSLDisposeContext((SSLContextRef)http->tls);
+# endif /* HAVE_LIBSSL */
+
+ http->tls = NULL;
+}
+
+
+/*
+ * 'http_read_ssl()' - Read from a SSL/TLS connection.
+ */
+
+static int /* O - Bytes read */
+http_read_ssl(http_t *http, /* I - HTTP data */
+ char *buf, /* I - Buffer to store data */
+ int len) /* I - Length of buffer */
+{
+# if defined(HAVE_LIBSSL)
+ return (SSL_read((SSL *)(http->tls), buf, len));
+
+# elif defined(HAVE_GNUTLS)
+ return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
+
+# elif defined(HAVE_CDSASSL)
+ OSStatus error; /* Error info */
+ size_t processed; /* Number of bytes processed */
+
+
+ error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
+
+ if (error == 0)
+ return (processed);
+ else
+ {
+ http->error = error;
+
+ return (-1);
+ }
+# endif /* HAVE_LIBSSL */
+}
+
+
+/*
+ * 'http_write_ssl()' - Write to a SSL/TLS connection.
+ */
+
+static int /* O - Bytes written */
+http_write_ssl(http_t *http, /* I - HTTP data */
+ const char *buf, /* I - Buffer holding data */
+ int len) /* I - Length of buffer */
+{
+# if defined(HAVE_LIBSSL)
+ return (SSL_write((SSL *)(http->tls), buf, len));
+
+# elif defined(HAVE_GNUTLS)
+ return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
+# elif defined(HAVE_CDSASSL)
+ OSStatus error; /* Error info */
+ size_t processed; /* Number of bytes processed */
+
+
+ error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
+
+ if (error == 0)
+ return (processed);
+ else
+ {
+ http->error = error;
+ return (-1);
+ }
+# endif /* HAVE_LIBSSL */
+}
+
+
+# if defined(HAVE_CDSASSL)
+/*
+ * 'CDSAReadFunc()' - Read function for CDSA decryption code.
+ */
+
+static OSStatus /* O - -1 on error, 0 on success */
+CDSAReadFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
+ void *data, /* I - Data buffer */
+ size_t *dataLength) /* IO - Number of bytes */
+{
+ ssize_t bytes; /* Number of bytes read */
+
+
+ bytes = recv((int)connection, data, *dataLength, 0);
+ if (bytes >= 0)
+ {
+ *dataLength = bytes;
+ return (0);
+ }
+ else
+ return (-1);
+}
+
+
+/*
+ * 'CDSAWriteFunc()' - Write function for CDSA encryption code.
+ */
+
+static OSStatus /* O - -1 on error, 0 on success */
+CDSAWriteFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
+ const void *data, /* I - Data buffer */
+ size_t *dataLength) /* IO - Number of bytes */
+{
+ ssize_t bytes;
+
+
+ bytes = write((int)connection, data, *dataLength);
+ if (bytes >= 0)
+ {
+ *dataLength = bytes;
+ return (0);
+ }
+ else
+ return (-1);
+}
+# endif /* HAVE_CDSASSL */
+#endif /* HAVE_SSL */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/http.h b/cups/http.h
new file mode 100644
index 000000000..f78f2a238
--- /dev/null
+++ b/cups/http.h
@@ -0,0 +1,379 @@
+/*
+ * "$Id$"
+ *
+ * Hyper-Text Transport Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_HTTP_H_
+# define _CUPS_HTTP_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <string.h>
+# include <time.h>
+# ifdef WIN32
+# include <winsock.h>
+# else
+# include <unistd.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# if !defined(__APPLE__) || !defined(TCP_NODELAY)
+# include <netinet/tcp.h>
+# endif /* !__APPLE__ || !TCP_NODELAY */
+# endif /* WIN32 */
+
+# include "md5.h"
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
+ * Limits...
+ */
+
+# define HTTP_MAX_URI 1024 /* Max length of URI string */
+# define HTTP_MAX_HOST 256 /* Max length of hostname string */
+# define HTTP_MAX_BUFFER 2048 /* Max length of data buffer */
+# define HTTP_MAX_VALUE 256 /* Max header field value length */
+
+
+/*
+ * HTTP state values...
+ */
+
+typedef enum /* States are server-oriented */
+{
+ HTTP_WAITING, /* Waiting for command */
+ HTTP_OPTIONS, /* OPTIONS command, waiting for blank line */
+ HTTP_GET, /* GET command, waiting for blank line */
+ HTTP_GET_SEND, /* GET command, sending data */
+ HTTP_HEAD, /* HEAD command, waiting for blank line */
+ HTTP_POST, /* POST command, waiting for blank line */
+ HTTP_POST_RECV, /* POST command, receiving data */
+ HTTP_POST_SEND, /* POST command, sending data */
+ HTTP_PUT, /* PUT command, waiting for blank line */
+ HTTP_PUT_RECV, /* PUT command, receiving data */
+ HTTP_DELETE, /* DELETE command, waiting for blank line */
+ HTTP_TRACE, /* TRACE command, waiting for blank line */
+ HTTP_CLOSE, /* CLOSE command, waiting for blank line */
+ HTTP_STATUS /* Command complete, sending status */
+} http_state_t;
+
+
+/*
+ * HTTP version numbers...
+ */
+
+typedef enum
+{
+ HTTP_0_9 = 9, /* HTTP/0.9 */
+ HTTP_1_0 = 100, /* HTTP/1.0 */
+ HTTP_1_1 = 101 /* HTTP/1.1 */
+} http_version_t;
+
+
+/*
+ * HTTP keep-alive values...
+ */
+
+typedef enum
+{
+ HTTP_KEEPALIVE_OFF = 0,
+ HTTP_KEEPALIVE_ON
+} http_keepalive_t;
+
+
+/*
+ * HTTP transfer encoding values...
+ */
+
+typedef enum
+{
+ HTTP_ENCODE_LENGTH, /* Data is sent with Content-Length */
+ HTTP_ENCODE_CHUNKED /* Data is chunked */
+} http_encoding_t;
+
+
+/*
+ * HTTP encryption values...
+ */
+
+typedef enum
+{
+ HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */
+ HTTP_ENCRYPT_NEVER, /* Never encrypt */
+ HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */
+ HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */
+} http_encryption_t;
+
+
+/*
+ * HTTP authentication types...
+ */
+
+typedef enum
+{
+ HTTP_AUTH_NONE, /* No authentication in use */
+ HTTP_AUTH_BASIC, /* Basic authentication in use */
+ HTTP_AUTH_MD5, /* Digest authentication in use */
+ HTTP_AUTH_MD5_SESS, /* MD5-session authentication in use */
+ HTTP_AUTH_MD5_INT, /* Digest authentication in use for body */
+ HTTP_AUTH_MD5_SESS_INT /* MD5-session authentication in use for body */
+} http_auth_t;
+
+
+/*
+ * HTTP status codes...
+ */
+
+typedef enum
+{
+ HTTP_ERROR = -1, /* An error response from httpXxxx() */
+
+ HTTP_CONTINUE = 100, /* Everything OK, keep going... */
+ HTTP_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */
+
+ HTTP_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */
+ HTTP_CREATED, /* PUT command was successful */
+ HTTP_ACCEPTED, /* DELETE command was successful */
+ HTTP_NOT_AUTHORITATIVE, /* Information isn't authoritative */
+ HTTP_NO_CONTENT, /* Successful command, no new data */
+ HTTP_RESET_CONTENT, /* Content was reset/recreated */
+ HTTP_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */
+
+ HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */
+ HTTP_MOVED_PERMANENTLY, /* Document has moved permanently */
+ HTTP_MOVED_TEMPORARILY, /* Document has moved temporarily */
+ HTTP_SEE_OTHER, /* See this other link... */
+ HTTP_NOT_MODIFIED, /* File not modified */
+ HTTP_USE_PROXY, /* Must use a proxy to access this URI */
+
+ HTTP_BAD_REQUEST = 400, /* Bad request */
+ HTTP_UNAUTHORIZED, /* Unauthorized to access host */
+ HTTP_PAYMENT_REQUIRED, /* Payment required */
+ HTTP_FORBIDDEN, /* Forbidden to access this URI */
+ HTTP_NOT_FOUND, /* URI was not found */
+ HTTP_METHOD_NOT_ALLOWED, /* Method is not allowed */
+ HTTP_NOT_ACCEPTABLE, /* Not Acceptable */
+ HTTP_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */
+ HTTP_REQUEST_TIMEOUT, /* Request timed out */
+ HTTP_CONFLICT, /* Request is self-conflicting */
+ HTTP_GONE, /* Server has gone away */
+ HTTP_LENGTH_REQUIRED, /* A content length or encoding is required */
+ HTTP_PRECONDITION, /* Precondition failed */
+ HTTP_REQUEST_TOO_LARGE, /* Request entity too large */
+ HTTP_URI_TOO_LONG, /* URI too long */
+ HTTP_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */
+ HTTP_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */
+
+ HTTP_SERVER_ERROR = 500, /* Internal server error */
+ HTTP_NOT_IMPLEMENTED, /* Feature not implemented */
+ HTTP_BAD_GATEWAY, /* Bad gateway */
+ HTTP_SERVICE_UNAVAILABLE, /* Service is unavailable */
+ HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */
+ HTTP_NOT_SUPPORTED /* HTTP version not supported */
+} http_status_t;
+
+
+/*
+ * HTTP field names...
+ */
+
+typedef enum
+{
+ HTTP_FIELD_UNKNOWN = -1,
+ HTTP_FIELD_ACCEPT_LANGUAGE,
+ HTTP_FIELD_ACCEPT_RANGES,
+ HTTP_FIELD_AUTHORIZATION,
+ HTTP_FIELD_CONNECTION,
+ HTTP_FIELD_CONTENT_ENCODING,
+ HTTP_FIELD_CONTENT_LANGUAGE,
+ HTTP_FIELD_CONTENT_LENGTH,
+ HTTP_FIELD_CONTENT_LOCATION,
+ HTTP_FIELD_CONTENT_MD5,
+ HTTP_FIELD_CONTENT_RANGE,
+ HTTP_FIELD_CONTENT_TYPE,
+ HTTP_FIELD_CONTENT_VERSION,
+ HTTP_FIELD_DATE,
+ HTTP_FIELD_HOST,
+ HTTP_FIELD_IF_MODIFIED_SINCE,
+ HTTP_FIELD_IF_UNMODIFIED_SINCE,
+ HTTP_FIELD_KEEP_ALIVE,
+ HTTP_FIELD_LAST_MODIFIED,
+ HTTP_FIELD_LINK,
+ HTTP_FIELD_LOCATION,
+ HTTP_FIELD_RANGE,
+ HTTP_FIELD_REFERER,
+ HTTP_FIELD_RETRY_AFTER,
+ HTTP_FIELD_TRANSFER_ENCODING,
+ HTTP_FIELD_UPGRADE,
+ HTTP_FIELD_USER_AGENT,
+ HTTP_FIELD_WWW_AUTHENTICATE,
+ HTTP_FIELD_MAX
+} http_field_t;
+
+
+/*
+ * HTTP connection structure...
+ */
+
+typedef struct
+{
+ int fd; /* File descriptor for this socket */
+ int blocking; /* To block or not to block */
+ int error; /* Last error on read */
+ time_t activity; /* Time since last read/write */
+ http_state_t state; /* State of client */
+ http_status_t status; /* Status of last request */
+ http_version_t version; /* Protocol version */
+ http_keepalive_t keep_alive; /* Keep-alive supported? */
+ struct sockaddr_in hostaddr; /* Address of connected host */
+ char hostname[HTTP_MAX_HOST],
+ /* Name of connected host */
+ fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE];
+ /* Field values */
+ char *data; /* Pointer to data buffer */
+ http_encoding_t data_encoding; /* Chunked or not */
+ int data_remaining; /* Number of bytes left */
+ int used; /* Number of bytes used in buffer */
+ char buffer[HTTP_MAX_BUFFER];
+ /* Buffer for messages */
+ int auth_type; /* Authentication in use */
+ md5_state_t md5_state; /* MD5 state */
+ char nonce[HTTP_MAX_VALUE];
+ /* Nonce value */
+ int nonce_count; /* Nonce count */
+ void *tls; /* TLS state information */
+ http_encryption_t encryption; /* Encryption requirements */
+ /**** New in CUPS 1.1.19 ****/
+ fd_set *input_set; /* select() set for httpWait() */
+ http_status_t expect; /* Expect: header */
+ char *cookie; /* Cookie value(s) */
+ /**** New in CUPS 1.1.20 ****/
+ char authstring[HTTP_MAX_VALUE],
+ /* Current Authentication value */
+ userpass[HTTP_MAX_VALUE];
+ /* Username:password string */
+ int digest_tries; /* Number of tries for digest auth */
+} http_t;
+
+
+/*
+ * Prototypes...
+ */
+
+# define httpBlocking(http,b) (http)->blocking = (b)
+extern int httpCheck(http_t *http);
+# define httpClearFields(http) memset((http)->fields, 0, sizeof((http)->fields)),\
+ httpSetField((http), HTTP_FIELD_HOST, (http)->hostname)
+extern void httpClose(http_t *http);
+extern http_t *httpConnect(const char *host, int port);
+extern http_t *httpConnectEncrypt(const char *host, int port,
+ http_encryption_t encrypt);
+extern int httpDelete(http_t *http, const char *uri);
+extern int httpEncryption(http_t *http, http_encryption_t e);
+# define httpError(http) ((http)->error)
+extern void httpFlush(http_t *http);
+extern int httpGet(http_t *http, const char *uri);
+extern char *httpGets(char *line, int length, http_t *http);
+extern const char *httpGetDateString(time_t t);
+extern time_t httpGetDateTime(const char *s);
+# define httpGetField(http,field) (http)->fields[field]
+extern struct hostent *httpGetHostByName(const char *name);
+extern char *httpGetSubField(http_t *http, http_field_t field,
+ const char *name, char *value);
+extern int httpHead(http_t *http, const char *uri);
+extern void httpInitialize(void);
+extern int httpOptions(http_t *http, const char *uri);
+extern int httpPost(http_t *http, const char *uri);
+extern int httpPrintf(http_t *http, const char *format, ...)
+# ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 2, 3)))
+# endif /* __GNUC__ */
+;
+extern int httpPut(http_t *http, const char *uri);
+extern int httpRead(http_t *http, char *buffer, int length);
+extern int httpReconnect(http_t *http);
+extern void httpSeparate(const char *uri, char *method,
+ char *username, char *host, int *port,
+ char *resource);
+extern void httpSetField(http_t *http, http_field_t field,
+ const char *value);
+extern const char *httpStatus(http_status_t status);
+extern int httpTrace(http_t *http, const char *uri);
+extern http_status_t httpUpdate(http_t *http);
+extern int httpWrite(http_t *http, const char *buffer, int length);
+extern char *httpEncode64(char *out, const char *in);
+extern char *httpDecode64(char *out, const char *in);
+extern int httpGetLength(http_t *http);
+extern char *httpMD5(const char *, const char *, const char *,
+ char [33]);
+extern char *httpMD5Final(const char *, const char *, const char *,
+ char [33]);
+extern char *httpMD5String(const md5_byte_t *, char [33]);
+
+/**** New in CUPS 1.1.19 ****/
+extern void httpClearCookie(http_t *http);
+#define httpGetCookie(http) ((http)->cookie)
+extern void httpSetCookie(http_t *http, const char *cookie);
+extern int httpWait(http_t *http, int msec);
+
+/**** New in CUPS 1.1.21 ****/
+extern char *httpDecode64_2(char *out, int *outlen, const char *in);
+extern char *httpEncode64_2(char *out, int outlen, const char *in,
+ int inlen);
+extern void httpSeparate2(const char *uri,
+ char *method, int methodlen,
+ char *username, int usernamelen,
+ char *host, int hostlen, int *port,
+ char *resource, int resourcelen);
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+#endif /* !_CUPS_HTTP_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ipp-support.c b/cups/ipp-support.c
new file mode 100644
index 000000000..ed6aa5ea8
--- /dev/null
+++ b/cups/ipp-support.c
@@ -0,0 +1,175 @@
+/*
+ * "$Id$"
+ *
+ * Internet Printing Protocol support functions for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ippErrorString() - Return a textual message for the given error
+ * message.
+ * ippPort() - Return the default IPP port number.
+ * ippSetPort() - Set the default port number.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "string.h"
+#include "language.h"
+
+#include "ipp.h"
+#include "debug.h"
+#include <ctype.h>
+
+
+/*
+ * Local globals...
+ */
+
+static int ipp_port = 0;
+
+
+/*
+ * 'ippErrorString()' - Return a textual message for the given error message.
+ */
+
+const char * /* O - Text string */
+ippErrorString(ipp_status_t error) /* I - Error status */
+{
+ static char unknown[255]; /* Unknown error statuses */
+ static const char * const status_oks[] =
+ { /* "OK" status codes */
+ "successful-ok",
+ "successful-ok-ignored-or-substituted-attributes",
+ "successful-ok-conflicting-attributes",
+ "successful-ok-ignored-subscriptions",
+ "successful-ok-ignored-notifications",
+ "successful-ok-too-many-events",
+ "successful-ok-but-cancel-subscription"
+ },
+ * const status_400s[] = /* Client errors */
+ {
+ "client-error-bad-request",
+ "client-error-forbidden",
+ "client-error-not-authenticated",
+ "client-error-not-authorized",
+ "client-error-not-possible",
+ "client-error-timeout",
+ "client-error-not-found",
+ "client-error-gone",
+ "client-error-request-entity-too-large",
+ "client-error-request-value-too-long",
+ "client-error-document-format-not-supported",
+ "client-error-attributes-or-values-not-supported",
+ "client-error-uri-scheme-not-supported",
+ "client-error-charset-not-supported",
+ "client-error-conflicting-attributes",
+ "client-error-compression-not-supported",
+ "client-error-compression-error",
+ "client-error-document-format-error",
+ "client-error-document-access-error",
+ "client-error-attributes-not-settable",
+ "client-error-ignored-all-subscriptions",
+ "client-error-too-many-subscriptions",
+ "client-error-ignored-all-notifications",
+ "client-error-print-support-file-not-found"
+ },
+ * const status_500s[] = /* Server errors */
+ {
+ "server-error-internal-error",
+ "server-error-operation-not-supported",
+ "server-error-service-unavailable",
+ "server-error-version-not-supported",
+ "server-error-device-error",
+ "server-error-temporary-error",
+ "server-error-not-accepting-jobs",
+ "server-error-busy",
+ "server-error-job-canceled",
+ "server-error-multiple-document-jobs-not-supported",
+ "server-error-printer-is-deactivated"
+ };
+
+
+ /*
+ * See if the error code is a known value...
+ */
+
+ if (error >= IPP_OK && error <= IPP_OK_BUT_CANCEL_SUBSCRIPTION)
+ return (status_oks[error]);
+ else if (error == IPP_REDIRECTION_OTHER_SITE)
+ return ("redirection-other-site");
+ else if (error >= IPP_BAD_REQUEST && error <= IPP_PRINT_SUPPORT_FILE_NOT_FOUND)
+ return (status_400s[error - IPP_BAD_REQUEST]);
+ else if (error >= IPP_INTERNAL_ERROR && error <= IPP_PRINTER_IS_DEACTIVATED)
+ return (status_500s[error - IPP_INTERNAL_ERROR]);
+
+ /*
+ * No, build an "unknown-xxxx" error string...
+ */
+
+ sprintf(unknown, "unknown-%04x", error);
+
+ return (unknown);
+}
+
+
+/*
+ * 'ippPort()' - Return the default IPP port number.
+ */
+
+int /* O - Port number */
+ippPort(void)
+{
+ const char *server_port; /* SERVER_PORT environment variable */
+ struct servent *port; /* Port number info */
+
+
+ if (ipp_port)
+ return (ipp_port);
+ else if ((server_port = getenv("IPP_PORT")) != NULL)
+ return (ipp_port = atoi(server_port));
+ else if ((port = getservbyname("ipp", NULL)) == NULL)
+ return (ipp_port = IPP_PORT);
+ else
+ return (ipp_port = ntohs(port->s_port));
+}
+
+
+/*
+ * 'ippSetPort()' - Set the default port number.
+ */
+
+void
+ippSetPort(int p) /* I - Port number to use */
+{
+ ipp_port = p;
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ipp.c b/cups/ipp.c
new file mode 100644
index 000000000..d14f047b8
--- /dev/null
+++ b/cups/ipp.c
@@ -0,0 +1,2561 @@
+/*
+ * "$Id$"
+ *
+ * Internet Printing Protocol support functions for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ippAddBoolean() - Add a boolean attribute to an IPP request.
+ * ippAddBooleans() - Add an array of boolean values.
+ * ippAddDate() - Add a date attribute to an IPP request.
+ * ippAddInteger() - Add a integer attribute to an IPP request.
+ * ippAddIntegers() - Add an array of integer values.
+ * ippAddString() - Add a language-encoded string to an IPP request.
+ * ippAddStrings() - Add language-encoded strings to an IPP request.
+ * ippAddRange() - Add a range of values to an IPP request.
+ * ippAddRanges() - Add ranges of values to an IPP request.
+ * ippAddResolution() - Add a resolution value to an IPP request.
+ * ippAddResolutions() - Add resolution values to an IPP request.
+ * ippAddSeparator() - Add a group separator to an IPP request.
+ * ippDateToTime() - Convert from RFC 1903 Date/Time format to
+ * UNIX time in seconds.
+ * ippDelete() - Delete an IPP request.
+ * ippDeleteAttribute() - Delete a single attribute in an IPP request.
+ * ippFindAttribute() - Find a named attribute in a request...
+ * ippFindNextAttribute() - Find the next named attribute in a request...
+ * ippLength() - Compute the length of an IPP request.
+ * ippNew() - Allocate a new IPP request.
+ * ippRead() - Read data for an IPP request from a HTTP
+ * connection.
+ * ippReadFile() - Read data for an IPP request from a file.
+ * ippReadIO() - Read data for an IPP request.
+ * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
+ * ippWrite() - Write data for an IPP request to a HTTP
+ * connection.
+ * ippWriteFile() - Write data for an IPP request to a file.
+ * ippWriteIO() - Write data for an IPP request.
+ * _ipp_add_attr() - Add a new attribute to the request.
+ * _ipp_free_attr() - Free an attribute.
+ * ipp_length() - Compute the length of an IPP request or
+ * collection value.
+ * ipp_read_http() - Semi-blocking read on a HTTP connection...
+ * ipp_read_file() - Read IPP data from a file.
+ * ipp_write_file() - Write IPP data to a file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "string.h"
+
+#include "ipp.h"
+#include "debug.h"
+#include <ctype.h>
+#include <errno.h>
+
+#ifdef WIN32
+# include <io.h>
+#endif // WIN32
+
+
+/*
+ * Local functions...
+ */
+
+static size_t ipp_length(ipp_t *ipp, int collection);
+static int ipp_read_http(http_t *http, ipp_uchar_t *buffer, int length);
+static int ipp_read_file(int *fd, ipp_uchar_t *buffer, int length);
+static int ipp_write_file(int *fd, ipp_uchar_t *buffer, int length);
+
+
+/*
+ * 'ippAddBoolean()' - Add a boolean attribute to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddBoolean(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ char value) /* I - Value of attribute */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("ippAddBoolean(%p, %02x, \'%s\', %d)\n", ipp, group, name, value));
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_BOOLEAN;
+ attr->values[0].boolean = value;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddBooleans()' - Add an array of boolean values.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddBooleans(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ const char *values) /* I - Values */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ DEBUG_printf(("ippAddBooleans(%p, %02x, \'%s\', %d, %p)\n", ipp,
+ group, name, num_values, values));
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_BOOLEAN;
+
+ if (values != NULL)
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ value->boolean = values[i];
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddCollection()' - Add a collection value.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddCollection(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ ipp_t *value) /* I - Value */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("ippAddCollection(%p, %02x, \'%s\', %p)\n", ipp, group, name,
+ value));
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
+ attr->values[0].collection = value;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddCollections()' - Add an array of collection values.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddCollections(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ const ipp_t **values) /* I - Values */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ DEBUG_printf(("ippAddCollections(%p, %02x, \'%s\', %d, %p)\n", ipp,
+ group, name, num_values, values));
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
+
+ if (values != NULL)
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ value->collection = (ipp_t *)values[i];
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddDate()' - Add a date attribute to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddDate(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ const ipp_uchar_t *value) /* I - Value */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("ippAddDate(%p, %02x, \'%s\', %p)\n", ipp, group, name,
+ value));
+
+ if (ipp == NULL || name == NULL || value == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_DATE;
+ memcpy(attr->values[0].date, value, 11);
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddInteger()' - Add a integer attribute to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddInteger(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t type, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ int value) /* I - Value of attribute */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("ippAddInteger(%p, %d, \'%s\', %d)\n", ipp, group, name,
+ value));
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = type;
+ attr->values[0].integer = value;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddIntegers()' - Add an array of integer values.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddIntegers(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t type, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ const int *values) /* I - Values */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = type;
+
+ if (values != NULL)
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ value->integer = values[i];
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddString()' - Add a language-encoded string to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddString(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t type, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ const char *charset, /* I - Character set */
+ const char *value) /* I - Value */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ /*
+ * Force value to be English for the POSIX locale...
+ */
+
+ if (type == IPP_TAG_LANGUAGE && strcasecmp(value, "C") == 0)
+ value = "en";
+
+ /*
+ * Initialize the attribute data...
+ */
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = type;
+ attr->values[0].string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
+ charset ? strdup(charset) : NULL;
+ attr->values[0].string.text = ((int)type & IPP_TAG_COPY) ? (char *)value :
+ value ? strdup(value) : NULL;
+
+ /*
+ * Convert language values to lowercase and change _ to - as needed...
+ */
+
+ if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) &&
+ attr->values[0].string.text)
+ {
+ char *p;
+
+
+ for (p = attr->values[0].string.text; *p; p ++)
+ if (*p == '_')
+ *p = '-';
+ else
+ *p = tolower(*p & 255);
+ }
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddStrings()' - Add language-encoded strings to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddStrings(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ ipp_tag_t type, /* I - Type of attribute */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ const char *charset, /* I - Character set */
+ const char * const *values) /* I - Values */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ /*
+ * Initialize the attribute data...
+ */
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = type;
+
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ {
+ if (i == 0)
+ value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
+ charset ? strdup(charset) : NULL;
+ else
+ value->string.charset = attr->values[0].string.charset;
+
+ if (values != NULL)
+ {
+ /*
+ * Force language to be English for the POSIX locale...
+ */
+
+ if (type == IPP_TAG_LANGUAGE && strcasecmp(values[i], "C") == 0)
+ value->string.text = ((int)type & IPP_TAG_COPY) ? "en" :
+ strdup("en");
+ else
+ value->string.text = ((int)type & IPP_TAG_COPY) ? (char *)values[i] :
+ strdup(values[i]);
+ }
+ }
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddRange()' - Add a range of values to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddRange(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ int lower, /* I - Lower value */
+ int upper) /* I - Upper value */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_RANGE;
+ attr->values[0].range.lower = lower;
+ attr->values[0].range.upper = upper;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddRanges()' - Add ranges of values to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddRanges(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ const int *lower, /* I - Lower values */
+ const int *upper) /* I - Upper values */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_RANGE;
+
+ if (lower != NULL && upper != NULL)
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ {
+ value->range.lower = lower[i];
+ value->range.upper = upper[i];
+ }
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddResolution()' - Add a resolution value to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddResolution(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ ipp_res_t units, /* I - Units for resolution */
+ int xres, /* I - X resolution */
+ int yres) /* I - Y resolution */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 1)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_RESOLUTION;
+ attr->values[0].resolution.xres = xres;
+ attr->values[0].resolution.yres = yres;
+ attr->values[0].resolution.units = units;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddResolutions()' - Add resolution values to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddResolutions(ipp_t *ipp, /* I - IPP request */
+ ipp_tag_t group, /* I - IPP group */
+ const char *name, /* I - Name of attribute */
+ int num_values, /* I - Number of values */
+ ipp_res_t units, /* I - Units for resolution */
+ const int *xres, /* I - X resolutions */
+ const int *yres) /* I - Y resolutions */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* New attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ if (ipp == NULL || name == NULL || num_values < 1)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, num_values)) == NULL)
+ return (NULL);
+
+ attr->name = strdup(name);
+ attr->group_tag = group;
+ attr->value_tag = IPP_TAG_RESOLUTION;
+
+ if (xres != NULL && yres != NULL)
+ for (i = 0, value = attr->values;
+ i < num_values;
+ i ++, value ++)
+ {
+ value->resolution.xres = xres[i];
+ value->resolution.yres = yres[i];
+ value->resolution.units = units;
+ }
+
+ return (attr);
+}
+
+
+/*
+ * 'ippAddSeparator()' - Add a group separator to an IPP request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+ippAddSeparator(ipp_t *ipp) /* I - IPP request */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("ippAddSeparator(%p)\n", ipp));
+
+ if (ipp == NULL)
+ return (NULL);
+
+ if ((attr = _ipp_add_attr(ipp, 0)) == NULL)
+ return (NULL);
+
+ attr->group_tag = IPP_TAG_ZERO;
+ attr->value_tag = IPP_TAG_ZERO;
+
+ return (attr);
+}
+
+
+/*
+ * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
+ * in seconds.
+ */
+
+time_t /* O - UNIX time value */
+ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
+{
+ struct tm unixdate; /* UNIX date/time info */
+ time_t t; /* Computed time */
+
+
+ memset(&unixdate, 0, sizeof(unixdate));
+
+ /*
+ * RFC-1903 date/time format is:
+ *
+ * Byte(s) Description
+ * ------- -----------
+ * 0-1 Year (0 to 65535)
+ * 2 Month (1 to 12)
+ * 3 Day (1 to 31)
+ * 4 Hours (0 to 23)
+ * 5 Minutes (0 to 59)
+ * 6 Seconds (0 to 60, 60 = "leap second")
+ * 7 Deciseconds (0 to 9)
+ * 8 +/- UTC
+ * 9 UTC hours (0 to 11)
+ * 10 UTC minutes (0 to 59)
+ */
+
+ unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900;
+ unixdate.tm_mon = date[2] - 1;
+ unixdate.tm_mday = date[3];
+ unixdate.tm_hour = date[4];
+ unixdate.tm_min = date[5];
+ unixdate.tm_sec = date[6];
+
+ t = mktime(&unixdate);
+
+ if (date[8] == '-')
+ t += date[9] * 3600 + date[10] * 60;
+ else
+ t -= date[9] * 3600 + date[10] * 60;
+
+ return (t);
+}
+
+
+/*
+ * 'ippDelete()' - Delete an IPP request.
+ */
+
+void
+ippDelete(ipp_t *ipp) /* I - IPP request */
+{
+ ipp_attribute_t *attr, /* Current attribute */
+ *next; /* Next attribute */
+
+
+ DEBUG_printf(("ippDelete(): %p\n", ipp));
+
+ if (ipp == NULL)
+ return;
+
+ for (attr = ipp->attrs; attr != NULL; attr = next)
+ {
+ next = attr->next;
+ _ipp_free_attr(attr);
+ }
+
+ free(ipp);
+}
+
+
+/*
+ * 'ippDeleteAttribute()' - Delete a single attribute in an IPP request.
+ */
+
+void
+ippDeleteAttribute(ipp_t *ipp, /* I - IPP request */
+ ipp_attribute_t *attr) /* I - Attribute to delete */
+{
+}
+
+
+/*
+ * 'ippFindAttribute()' - Find a named attribute in a request...
+ */
+
+ipp_attribute_t * /* O - Matching attribute */
+ippFindAttribute(ipp_t *ipp, /* I - IPP request */
+ const char *name, /* I - Name of attribute */
+ ipp_tag_t type) /* I - Type of attribute */
+{
+ DEBUG_printf(("ippFindAttribute(%p, \'%s\')\n", ipp, name));
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ /*
+ * Reset the current pointer...
+ */
+
+ ipp->current = NULL;
+
+ /*
+ * Search for the attribute...
+ */
+
+ return (ippFindNextAttribute(ipp, name, type));
+}
+
+
+/*
+ * 'ippFindNextAttribute()' - Find the next named attribute in a request...
+ */
+
+ipp_attribute_t * /* O - Matching attribute */
+ippFindNextAttribute(ipp_t *ipp, /* I - IPP request */
+ const char *name, /* I - Name of attribute */
+ ipp_tag_t type) /* I - Type of attribute */
+{
+ ipp_attribute_t *attr; /* Current atttribute */
+ ipp_tag_t value_tag; /* Value tag */
+
+
+ DEBUG_printf(("ippFindNextAttribute(%p, \'%s\')\n", ipp, name));
+
+ if (ipp == NULL || name == NULL)
+ return (NULL);
+
+ if (ipp->current)
+ attr = ipp->current->next;
+ else
+ attr = ipp->attrs;
+
+ for (; attr != NULL; attr = attr->next)
+ {
+ DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr,
+ attr->name));
+
+ value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+
+ if (attr->name != NULL && strcasecmp(attr->name, name) == 0 &&
+ (value_tag == type || type == IPP_TAG_ZERO ||
+ (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) ||
+ (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
+ {
+ ipp->current = attr;
+
+ return (attr);
+ }
+ }
+
+ ipp->current = NULL;
+
+ return (NULL);
+}
+
+
+/*
+ * 'ippLength()' - Compute the length of an IPP request.
+ */
+
+size_t /* O - Size of IPP request */
+ippLength(ipp_t *ipp) /* I - IPP request */
+{
+ return (ipp_length(ipp, 0));
+}
+
+
+/*
+ * 'ippNew()' - Allocate a new IPP request.
+ */
+
+ipp_t * /* O - New IPP request */
+ippNew(void)
+{
+ ipp_t *temp; /* New IPP request */
+
+
+ if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL)
+ {
+ /*
+ * Default to IPP 1.1...
+ */
+
+ temp->request.any.version[0] = 1;
+ temp->request.any.version[1] = 1;
+ }
+
+ DEBUG_printf(("ippNew(): %p\n", temp));
+
+ return (temp);
+}
+
+
+/*
+ * 'ippRead()' - Read data for an IPP request from a HTTP connection.
+ */
+
+ipp_state_t /* O - Current state */
+ippRead(http_t *http, /* I - HTTP connection */
+ ipp_t *ipp) /* I - IPP data */
+{
+ DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=%d\n", http, ipp,
+ http ? http->data_remaining : -1));
+
+ if (http == NULL)
+ return (IPP_ERROR);
+
+ DEBUG_printf(("http->state = %d\n", http->state));
+
+ return (ippReadIO(http, (ipp_iocb_t)ipp_read_http,
+ http->blocking || http->used != 0, NULL, ipp));
+}
+
+
+/*
+ * 'ippReadFile()' - Read data for an IPP request from a file.
+ */
+
+ipp_state_t /* O - Current state */
+ippReadFile(int fd, /* I - HTTP data */
+ ipp_t *ipp) /* I - IPP data */
+{
+ DEBUG_printf(("ippReadFile(%d, %p)\n", fd, ipp));
+
+ return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
+}
+
+
+/*
+ * 'ippReadIO()' - Read data for an IPP request.
+ */
+
+ipp_state_t /* O - Current state */
+ippReadIO(void *src, /* I - Data source */
+ ipp_iocb_t cb, /* I - Read callback function */
+ int blocking, /* I - Use blocking IO? */
+ ipp_t *parent, /* I - Parent request, if any */
+ ipp_t *ipp) /* I - IPP data */
+{
+ int n; /* Length of data */
+ unsigned char buffer[32768], /* Data buffer */
+ *bufptr; /* Pointer into buffer */
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_tag_t tag; /* Current tag */
+ ipp_value_t *value; /* Current value */
+
+
+ DEBUG_printf(("ippReadIO(%p, %p, %d, %p, %p)\n", src, cb, blocking,
+ parent, ipp));
+
+ if (src == NULL || ipp == NULL)
+ return (IPP_ERROR);
+
+ switch (ipp->state)
+ {
+ case IPP_IDLE :
+ ipp->state ++; /* Avoid common problem... */
+
+ case IPP_HEADER :
+ if (parent == NULL)
+ {
+ /*
+ * Get the request header...
+ */
+
+ if ((n = (*cb)(src, buffer, 8)) < 8)
+ {
+ DEBUG_printf(("ippReadIO: Unable to read header (%d bytes read)!\n", n));
+ return (n == 0 ? IPP_IDLE : IPP_ERROR);
+ }
+
+ /*
+ * Verify the major version number...
+ */
+
+ if (buffer[0] != 1)
+ {
+ DEBUG_printf(("ippReadIO: version number (%d.%d) is bad.\n", buffer[0],
+ buffer[1]));
+ return (IPP_ERROR);
+ }
+
+ /*
+ * Then copy the request header over...
+ */
+
+ ipp->request.any.version[0] = buffer[0];
+ ipp->request.any.version[1] = buffer[1];
+ ipp->request.any.op_status = (buffer[2] << 8) | buffer[3];
+ ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) |
+ buffer[6]) << 8) | buffer[7];
+ }
+
+ ipp->state = IPP_ATTRIBUTE;
+ ipp->current = NULL;
+ ipp->curtag = IPP_TAG_ZERO;
+
+ DEBUG_printf(("ippReadIO: version=%d.%d\n", buffer[0], buffer[1]));
+ DEBUG_printf(("ippReadIO: op_status=%04x\n", ipp->request.any.op_status));
+ DEBUG_printf(("ippReadIO: request_id=%d\n", ipp->request.any.request_id));
+
+ /*
+ * If blocking is disabled, stop here...
+ */
+
+ if (!blocking)
+ break;
+
+ case IPP_ATTRIBUTE :
+ while ((*cb)(src, buffer, 1) > 0)
+ {
+ /*
+ * Read this attribute...
+ */
+
+ tag = (ipp_tag_t)buffer[0];
+
+ if (tag == IPP_TAG_END)
+ {
+ /*
+ * No more attributes left...
+ */
+
+ DEBUG_puts("ippReadIO: IPP_TAG_END!");
+
+ ipp->state = IPP_DATA;
+ break;
+ }
+ else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
+ {
+ /*
+ * Group tag... Set the current group and continue...
+ */
+
+ if (ipp->curtag == tag)
+ ippAddSeparator(ipp);
+
+ ipp->curtag = tag;
+ ipp->current = NULL;
+ DEBUG_printf(("ippReadIO: group tag = %x\n", tag));
+ continue;
+ }
+
+ DEBUG_printf(("ippReadIO: value tag = %x\n", tag));
+
+ /*
+ * Get the name...
+ */
+
+ if ((*cb)(src, buffer, 2) < 2)
+ {
+ DEBUG_puts("ippReadIO: unable to read name length!");
+ return (IPP_ERROR);
+ }
+
+ n = (buffer[0] << 8) | buffer[1];
+
+ if (n > (sizeof(buffer) - 1))
+ {
+ DEBUG_printf(("ippReadIO: bad name length %d!\n", n));
+ return (IPP_ERROR);
+ }
+
+ DEBUG_printf(("ippReadIO: name length = %d\n", n));
+
+ if (n == 0 && tag != IPP_TAG_MEMBERNAME)
+ {
+ /*
+ * More values for current attribute...
+ */
+
+ if (ipp->current == NULL)
+ return (IPP_ERROR);
+
+ attr = ipp->current;
+
+ /*
+ * Make sure we aren't adding a new value of a different
+ * type...
+ */
+
+ if (attr->value_tag == IPP_TAG_ZERO)
+ {
+ attr->value_tag = tag;
+ }
+ else if (attr->value_tag == IPP_TAG_STRING ||
+ (attr->value_tag >= IPP_TAG_TEXTLANG &&
+ attr->value_tag <= IPP_TAG_MIMETYPE))
+ {
+ /*
+ * String values can sometimes come across in different
+ * forms; accept sets of differing values...
+ */
+
+ if (tag != IPP_TAG_STRING &&
+ (tag < IPP_TAG_TEXTLANG || tag > IPP_TAG_MIMETYPE))
+ return (IPP_ERROR);
+ }
+ else if (attr->value_tag != tag &&
+ tag != IPP_TAG_END_COLLECTION)
+ return (IPP_ERROR);
+
+ /*
+ * Finally, reallocate the attribute array as needed...
+ */
+
+ if ((attr->num_values % IPP_MAX_VALUES) == 0 &&
+ attr->num_values > 0)
+ {
+ ipp_attribute_t *temp, /* Pointer to new buffer */
+ *ptr; /* Pointer in attribute list */
+
+
+ /*
+ * Reallocate memory...
+ */
+
+ if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
+ (attr->num_values + IPP_MAX_VALUES - 1) *
+ sizeof(ipp_value_t))) == NULL)
+ return (IPP_ERROR);
+
+ /*
+ * Reset pointers in the list...
+ */
+
+ for (ptr = ipp->attrs; ptr && ptr->next != attr; ptr = ptr->next);
+
+ if (ptr)
+ ptr->next = temp;
+ else
+ ipp->attrs = temp;
+
+ attr = ipp->current = ipp->last = temp;
+ }
+ }
+ else if (tag == IPP_TAG_MEMBERNAME)
+ {
+ /*
+ * Name must be length 0!
+ */
+
+ if (n)
+ {
+ DEBUG_puts("ippReadIO: member name not empty!");
+ return (IPP_ERROR);
+ }
+
+ attr = ipp->current = _ipp_add_attr(ipp, IPP_MAX_VALUES);
+
+ attr->group_tag = ipp->curtag;
+ attr->value_tag = IPP_TAG_ZERO;
+ attr->num_values = 0;
+ }
+ else
+ {
+ /*
+ * New attribute; read the name and add it...
+ */
+
+ if ((*cb)(src, buffer, n) < n)
+ {
+ DEBUG_puts("ippReadIO: unable to read name!");
+ return (IPP_ERROR);
+ }
+
+ buffer[n] = '\0';
+ DEBUG_printf(("ippReadIO: name = \'%s\'\n", buffer));
+
+ attr = ipp->current = _ipp_add_attr(ipp, IPP_MAX_VALUES);
+
+ attr->group_tag = ipp->curtag;
+ attr->value_tag = tag;
+ attr->name = strdup((char *)buffer);
+ attr->num_values = 0;
+ }
+
+ value = attr->values + attr->num_values;
+
+ if ((*cb)(src, buffer, 2) < 2)
+ {
+ DEBUG_puts("ippReadIO: unable to read value length!");
+ return (IPP_ERROR);
+ }
+
+ n = (buffer[0] << 8) | buffer[1];
+ DEBUG_printf(("ippReadIO: value length = %d\n", n));
+
+ switch (tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ if ((*cb)(src, buffer, 4) < 4)
+ {
+ DEBUG_puts("ippReadIO: Unable to read integer value!");
+ return (IPP_ERROR);
+ }
+
+ n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+ buffer[3];
+
+ value->integer = n;
+ break;
+ case IPP_TAG_BOOLEAN :
+ if ((*cb)(src, buffer, 1) < 1)
+ {
+ DEBUG_puts("ippReadIO: Unable to read boolean value!");
+ return (IPP_ERROR);
+ }
+
+ value->boolean = buffer[0];
+ break;
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_STRING :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ value->string.text = calloc(n + 1, 1);
+
+ if ((*cb)(src, (ipp_uchar_t *)value->string.text, n) < n)
+ {
+ DEBUG_puts("ippReadIO: Unable to read string value!");
+ return (IPP_ERROR);
+ }
+
+ DEBUG_printf(("ippReadIO: value = \'%s\'\n",
+ value->string.text));
+ break;
+ case IPP_TAG_DATE :
+ if ((*cb)(src, value->date, 11) < 11)
+ {
+ DEBUG_puts("ippReadIO: Unable to date integer value!");
+ return (IPP_ERROR);
+ }
+ break;
+ case IPP_TAG_RESOLUTION :
+ if ((*cb)(src, buffer, 9) < 9)
+ {
+ DEBUG_puts("ippReadIO: Unable to read resolution value!");
+ return (IPP_ERROR);
+ }
+
+ value->resolution.xres =
+ (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+ buffer[3];
+ value->resolution.yres =
+ (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+ buffer[7];
+ value->resolution.units =
+ (ipp_res_t)buffer[8];
+ break;
+ case IPP_TAG_RANGE :
+ if ((*cb)(src, buffer, 8) < 8)
+ {
+ DEBUG_puts("ippReadIO: Unable to read range value!");
+ return (IPP_ERROR);
+ }
+
+ value->range.lower =
+ (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+ buffer[3];
+ value->range.upper =
+ (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+ buffer[7];
+ break;
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ if (n > sizeof(buffer) || n < 4)
+ {
+ DEBUG_printf(("ippReadIO: bad value length %d!\n", n));
+ return (IPP_ERROR);
+ }
+
+ if ((*cb)(src, buffer, n) < n)
+ {
+ DEBUG_puts("ippReadIO: Unable to read string w/language value!");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+
+ /*
+ * text-with-language and name-with-language are composite
+ * values:
+ *
+ * charset-length
+ * charset
+ * text-length
+ * text
+ */
+
+ n = (bufptr[0] << 8) | bufptr[1];
+
+ value->string.charset = calloc(n + 1, 1);
+
+ memcpy(value->string.charset,
+ bufptr + 2, n);
+
+ bufptr += 2 + n;
+ n = (bufptr[0] << 8) | bufptr[1];
+
+ value->string.text = calloc(n + 1, 1);
+
+ memcpy(value->string.text,
+ bufptr + 2, n);
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ /*
+ * Oh, boy, here comes a collection value, so read it...
+ */
+
+ value->collection = ippNew();
+
+ if (n > 0)
+ {
+ DEBUG_puts("ippReadIO: begCollection tag with value length > 0!");
+ return (IPP_ERROR);
+ }
+
+ if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
+ {
+ DEBUG_puts("ippReadIO: Unable to read collection value!");
+ return (IPP_ERROR);
+ }
+ break;
+
+ case IPP_TAG_END_COLLECTION :
+ if (n > 0)
+ {
+ DEBUG_puts("ippReadIO: endCollection tag with value length > 0!");
+ return (IPP_ERROR);
+ }
+
+ DEBUG_puts("ippReadIO: endCollection tag...");
+
+ return (ipp->state = IPP_DATA);
+
+ case IPP_TAG_MEMBERNAME :
+ /*
+ * The value the name of the member in the collection, which
+ * we need to carry over...
+ */
+
+ attr->name = calloc(n + 1, 1);
+
+ if ((*cb)(src, (ipp_uchar_t *)attr->name, n) < n)
+ {
+ DEBUG_puts("ippReadIO: Unable to read member name value!");
+ return (IPP_ERROR);
+ }
+
+ DEBUG_printf(("ippReadIO: member name = \"%s\"\n", attr->name));
+ break;
+
+ default : /* Other unsupported values */
+ value->unknown.length = n;
+ if (n > 0)
+ {
+ value->unknown.data = malloc(n);
+ if ((*cb)(src, value->unknown.data, n) < n)
+ {
+ DEBUG_puts("ippReadIO: Unable to read unsupported value!");
+ return (IPP_ERROR);
+ }
+ }
+ else
+ value->unknown.data = NULL;
+ break;
+ }
+
+ attr->num_values ++;
+
+ /*
+ * If blocking is disabled, stop here...
+ */
+
+ if (!blocking)
+ break;
+ }
+ break;
+
+ case IPP_DATA :
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+
+ return (ipp->state);
+}
+
+
+/*
+ * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
+ */
+
+const ipp_uchar_t * /* O - RFC-1903 date/time data */
+ippTimeToDate(time_t t) /* I - UNIX time value */
+{
+ struct tm *unixdate; /* UNIX unixdate/time info */
+ static ipp_uchar_t date[11]; /* RFC-1903 date/time data */
+
+
+ /*
+ * RFC-1903 date/time format is:
+ *
+ * Byte(s) Description
+ * ------- -----------
+ * 0-1 Year (0 to 65535)
+ * 2 Month (1 to 12)
+ * 3 Day (1 to 31)
+ * 4 Hours (0 to 23)
+ * 5 Minutes (0 to 59)
+ * 6 Seconds (0 to 60, 60 = "leap second")
+ * 7 Deciseconds (0 to 9)
+ * 8 +/- UTC
+ * 9 UTC hours (0 to 11)
+ * 10 UTC minutes (0 to 59)
+ */
+
+ unixdate = gmtime(&t);
+ unixdate->tm_year += 1900;
+
+ date[0] = unixdate->tm_year >> 8;
+ date[1] = unixdate->tm_year;
+ date[2] = unixdate->tm_mon + 1;
+ date[3] = unixdate->tm_mday;
+ date[4] = unixdate->tm_hour;
+ date[5] = unixdate->tm_min;
+ date[6] = unixdate->tm_sec;
+ date[7] = 0;
+ date[8] = '+';
+ date[9] = 0;
+ date[10] = 0;
+
+ return (date);
+}
+
+
+/*
+ * 'ippWrite()' - Write data for an IPP request to a HTTP connection.
+ */
+
+ipp_state_t /* O - Current state */
+ippWrite(http_t *http, /* I - HTTP connection */
+ ipp_t *ipp) /* I - IPP data */
+{
+ DEBUG_printf(("ippWrite(%p, %p)\n", http, ipp));
+
+ if (http == NULL)
+ return (IPP_ERROR);
+
+ return (ippWriteIO(http, (ipp_iocb_t)httpWrite,
+ http->blocking, NULL, ipp));
+}
+
+
+/*
+ * 'ippWriteFile()' - Write data for an IPP request to a file.
+ */
+
+ipp_state_t /* O - Current state */
+ippWriteFile(int fd, /* I - HTTP data */
+ ipp_t *ipp) /* I - IPP data */
+{
+ DEBUG_printf(("ippWriteFile(%d, %p)\n", fd, ipp));
+
+ ipp->state = IPP_IDLE;
+
+ return (ippWriteIO(&fd, (ipp_iocb_t)ipp_write_file, 1, NULL, ipp));
+}
+
+
+/*
+ * 'ippWriteIO()' - Write data for an IPP request.
+ */
+
+ipp_state_t /* O - Current state */
+ippWriteIO(void *dst, /* I - Destination */
+ ipp_iocb_t cb, /* I - Write callback function */
+ int blocking, /* I - Use blocking IO? */
+ ipp_t *parent, /* I - Parent IPP request */
+ ipp_t *ipp) /* I - IPP data */
+{
+ int i; /* Looping var */
+ int n; /* Length of data */
+ unsigned char buffer[32768], /* Data buffer */
+ *bufptr; /* Pointer into buffer */
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_value_t *value; /* Current value */
+
+
+ DEBUG_printf(("ippWriteIO(%p, %p, %d, %p, %p)\n", dst, cb, blocking,
+ parent, ipp));
+
+ if (dst == NULL || ipp == NULL)
+ return (IPP_ERROR);
+
+ switch (ipp->state)
+ {
+ case IPP_IDLE :
+ ipp->state ++; /* Avoid common problem... */
+
+ case IPP_HEADER :
+ if (parent == NULL)
+ {
+ /*
+ * Send the request header:
+ *
+ * Version = 2 bytes
+ * Operation/Status Code = 2 bytes
+ * Request ID = 4 bytes
+ * Total = 8 bytes
+ */
+
+ bufptr = buffer;
+
+ *bufptr++ = ipp->request.any.version[0];
+ *bufptr++ = ipp->request.any.version[1];
+ *bufptr++ = ipp->request.any.op_status >> 8;
+ *bufptr++ = ipp->request.any.op_status;
+ *bufptr++ = ipp->request.any.request_id >> 24;
+ *bufptr++ = ipp->request.any.request_id >> 16;
+ *bufptr++ = ipp->request.any.request_id >> 8;
+ *bufptr++ = ipp->request.any.request_id;
+
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP header...");
+ return (IPP_ERROR);
+ }
+ }
+
+ /*
+ * Reset the state engine to point to the first attribute
+ * in the request/response, with no current group.
+ */
+
+ ipp->state = IPP_ATTRIBUTE;
+ ipp->current = ipp->attrs;
+ ipp->curtag = IPP_TAG_ZERO;
+
+ DEBUG_printf(("ippWrite: version=%d.%d\n", buffer[0], buffer[1]));
+ DEBUG_printf(("ippWrite: op_status=%04x\n", ipp->request.any.op_status));
+ DEBUG_printf(("ippWrite: request_id=%d\n", ipp->request.any.request_id));
+
+ /*
+ * If blocking is disabled, stop here...
+ */
+
+ if (!blocking)
+ break;
+
+ case IPP_ATTRIBUTE :
+ while (ipp->current != NULL)
+ {
+ /*
+ * Write this attribute...
+ */
+
+ bufptr = buffer;
+ attr = ipp->current;
+
+ ipp->current = ipp->current->next;
+
+ if (ipp->curtag != attr->group_tag && parent == NULL)
+ {
+ /*
+ * Send a group tag byte...
+ */
+
+ ipp->curtag = attr->group_tag;
+
+ if (attr->group_tag == IPP_TAG_ZERO)
+ continue;
+
+ DEBUG_printf(("ippWrite: wrote group tag = %x\n", attr->group_tag));
+ *bufptr++ = attr->group_tag;
+ }
+
+ /*
+ * Write the attribute tag and name. The current implementation
+ * does not support the extension value tags above 0x7f, so all
+ * value tags are 1 byte.
+ *
+ * The attribute name length does not include the trailing nul
+ * character in the source string.
+ *
+ * Collection values (parent != NULL) are written differently...
+ */
+
+ if (parent == NULL)
+ {
+ /*
+ * Get the length of the attribute name, and make sure it won't
+ * overflow the buffer...
+ */
+
+ if ((n = strlen(attr->name)) > (sizeof(buffer) - 4))
+ return (IPP_ERROR);
+
+ /*
+ * Write the value tag, name length, and name string...
+ */
+
+ DEBUG_printf(("ippWrite: writing value tag = %x\n", attr->value_tag));
+ DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n, attr->name));
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+ memcpy(bufptr, attr->name, n);
+ bufptr += n;
+ }
+ else
+ {
+ /*
+ * Get the length of the attribute name, and make sure it won't
+ * overflow the buffer...
+ */
+
+ if ((n = strlen(attr->name)) > (sizeof(buffer) - 7))
+ return (IPP_ERROR);
+
+ /*
+ * Write the member name tag, name length, name string, value tag,
+ * and empty name for the collection member attribute...
+ */
+
+ DEBUG_printf(("ippWrite: writing value tag = %x\n",
+ IPP_TAG_MEMBERNAME));
+ DEBUG_printf(("ippWrite: writing name = %d, \'%s\'\n", n, attr->name));
+ DEBUG_printf(("ippWrite: writing value tag = %x\n", attr->value_tag));
+ DEBUG_puts("ippWrite: writing name = 0, \'\'\n");
+
+ *bufptr++ = IPP_TAG_MEMBERNAME;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+ memcpy(bufptr, attr->name, n);
+ bufptr += n;
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Now write the attribute value(s)...
+ */
+
+ switch (attr->value_tag & ~IPP_TAG_COPY)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if ((sizeof(buffer) - (bufptr - buffer)) < 9)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Integers and enumerations are both 4-byte signed
+ * (twos-complement) values.
+ *
+ * Put the 2-byte length and 4-byte value into the buffer...
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 4;
+ *bufptr++ = value->integer >> 24;
+ *bufptr++ = value->integer >> 16;
+ *bufptr++ = value->integer >> 8;
+ *bufptr++ = value->integer;
+ }
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if ((sizeof(buffer) - (bufptr - buffer)) < 6)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Boolean values are 1-byte; 0 = false, 1 = true.
+ *
+ * Put the 2-byte length and 1-byte value into the buffer...
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 1;
+ *bufptr++ = value->boolean;
+ }
+ break;
+
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_STRING :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ DEBUG_printf(("ippWrite: writing value tag = %x\n",
+ attr->value_tag));
+ DEBUG_printf(("ippWrite: writing name = 0, \'\'\n"));
+
+ if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ if (value->string.text != NULL)
+ n = strlen(value->string.text);
+ else
+ n = 0;
+
+ if (n > (sizeof(buffer) - 2))
+ return (IPP_ERROR);
+
+ DEBUG_printf(("ippWrite: writing string = %d, \'%s\'\n", n,
+ value->string.text));
+
+ if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ /*
+ * All simple strings consist of the 2-byte length and
+ * character data without the trailing nul normally found
+ * in C strings. Also, strings cannot be longer than 32767
+ * bytes since the 2-byte length is a signed (twos-complement)
+ * value.
+ *
+ * Put the 2-byte length and string characters in the buffer.
+ */
+
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+
+ if (n > 0)
+ {
+ memcpy(bufptr, value->string.text, n);
+ bufptr += n;
+ }
+ }
+ break;
+
+ case IPP_TAG_DATE :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if ((sizeof(buffer) - (bufptr - buffer)) < 16)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Date values consist of a 2-byte length and an
+ * 11-byte date/time structure defined by RFC 1903.
+ *
+ * Put the 2-byte length and 11-byte date/time
+ * structure in the buffer.
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 11;
+ memcpy(bufptr, value->date, 11);
+ bufptr += 11;
+ }
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if ((sizeof(buffer) - (bufptr - buffer)) < 14)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Resolution values consist of a 2-byte length,
+ * 4-byte horizontal resolution value, 4-byte vertical
+ * resolution value, and a 1-byte units value.
+ *
+ * Put the 2-byte length and resolution value data
+ * into the buffer.
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 9;
+ *bufptr++ = value->resolution.xres >> 24;
+ *bufptr++ = value->resolution.xres >> 16;
+ *bufptr++ = value->resolution.xres >> 8;
+ *bufptr++ = value->resolution.xres;
+ *bufptr++ = value->resolution.yres >> 24;
+ *bufptr++ = value->resolution.yres >> 16;
+ *bufptr++ = value->resolution.yres >> 8;
+ *bufptr++ = value->resolution.yres;
+ *bufptr++ = value->resolution.units;
+ }
+ break;
+
+ case IPP_TAG_RANGE :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if ((sizeof(buffer) - (bufptr - buffer)) < 13)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Range values consist of a 2-byte length,
+ * 4-byte lower value, and 4-byte upper value.
+ *
+ * Put the 2-byte length and range value data
+ * into the buffer.
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 8;
+ *bufptr++ = value->range.lower >> 24;
+ *bufptr++ = value->range.lower >> 16;
+ *bufptr++ = value->range.lower >> 8;
+ *bufptr++ = value->range.lower;
+ *bufptr++ = value->range.upper >> 24;
+ *bufptr++ = value->range.upper >> 16;
+ *bufptr++ = value->range.upper >> 8;
+ *bufptr++ = value->range.upper;
+ }
+ break;
+
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * textWithLanguage and nameWithLanguage values consist
+ * of a 2-byte length for both strings and their
+ * individual lengths, a 2-byte length for the
+ * character string, the character string without the
+ * trailing nul, a 2-byte length for the character
+ * set string, and the character set string without
+ * the trailing nul.
+ */
+
+ n = 4;
+
+ if (value->string.charset != NULL)
+ n += strlen(value->string.charset);
+
+ if (value->string.text != NULL)
+ n += strlen(value->string.text);
+
+ if (n > (sizeof(buffer) - 2))
+ return (IPP_ERROR);
+
+ if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ /* Length of entire value */
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+
+ /* Length of charset */
+ if (value->string.charset != NULL)
+ n = strlen(value->string.charset);
+ else
+ n = 0;
+
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+
+ /* Charset */
+ if (n > 0)
+ {
+ memcpy(bufptr, value->string.charset, n);
+ bufptr += n;
+ }
+
+ /* Length of text */
+ if (value->string.text != NULL)
+ n = strlen(value->string.text);
+ else
+ n = 0;
+
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+
+ /* Text */
+ if (n > 0)
+ {
+ memcpy(bufptr, value->string.text, n);
+ bufptr += n;
+ }
+ }
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ /*
+ * Collections are written with the begin-collection
+ * tag first with a value of 0 length, followed by the
+ * attributes in the collection, then the end-collection
+ * value...
+ */
+
+ if ((sizeof(buffer) - (bufptr - buffer)) < 5)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * Write a data length of 0 and flush the buffer...
+ */
+
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+
+ /*
+ * Then write the collection attribute...
+ */
+
+ value->collection->state = IPP_IDLE;
+
+ if (ippWriteIO(dst, cb, 1, ipp, value->collection) == IPP_ERROR)
+ return (IPP_ERROR);
+ }
+ break;
+
+ default :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if (i)
+ {
+ /*
+ * Arrays and sets are done by sending additional
+ * values with a zero-length name...
+ */
+
+ if ((sizeof(buffer) - (bufptr - buffer)) < 3)
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ *bufptr++ = attr->value_tag;
+ *bufptr++ = 0;
+ *bufptr++ = 0;
+ }
+
+ /*
+ * An unknown value might some new value that a
+ * vendor has come up with. It consists of a
+ * 2-byte length and the bytes in the unknown
+ * value buffer.
+ */
+
+ n = value->unknown.length;
+
+ if (n > (sizeof(buffer) - 2))
+ return (IPP_ERROR);
+
+ if ((int)(sizeof(buffer) - (bufptr - buffer)) < (n + 2))
+ {
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ bufptr = buffer;
+ }
+
+ /* Length of unknown value */
+ *bufptr++ = n >> 8;
+ *bufptr++ = n;
+
+ /* Value */
+ if (n > 0)
+ {
+ memcpy(bufptr, value->unknown.data, n);
+ bufptr += n;
+ }
+ }
+ break;
+ }
+
+ /*
+ * Write the data out...
+ */
+
+ if ((*cb)(dst, buffer, bufptr - buffer) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP attribute...");
+ return (IPP_ERROR);
+ }
+
+ DEBUG_printf(("ippWrite: wrote %d bytes\n", bufptr - buffer));
+
+ /*
+ * If blocking is disabled, stop here...
+ */
+
+ if (!blocking)
+ break;
+ }
+
+ if (ipp->current == NULL)
+ {
+ /*
+ * Done with all of the attributes; add the end-of-attributes
+ * tag or end-collection attribute...
+ */
+
+ if (parent == NULL)
+ {
+ buffer[0] = IPP_TAG_END;
+ n = 1;
+ }
+ else
+ {
+ buffer[0] = IPP_TAG_END_COLLECTION;
+ buffer[1] = 0; /* empty name */
+ buffer[2] = 0;
+ buffer[3] = 0; /* empty value */
+ buffer[4] = 0;
+ n = 5;
+ }
+
+ if ((*cb)(dst, buffer, n) < 0)
+ {
+ DEBUG_puts("ippWrite: Could not write IPP end-tag...");
+ return (IPP_ERROR);
+ }
+
+ ipp->state = IPP_DATA;
+ }
+ break;
+
+ case IPP_DATA :
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+
+ return (ipp->state);
+}
+
+
+/*
+ * '_ipp_add_attr()' - Add a new attribute to the request.
+ */
+
+ipp_attribute_t * /* O - New attribute */
+_ipp_add_attr(ipp_t *ipp, /* I - IPP request */
+ int num_values) /* I - Number of values */
+{
+ ipp_attribute_t *attr; /* New attribute */
+
+
+ DEBUG_printf(("_ipp_add_attr(%p, %d)\n", ipp, num_values));
+
+ if (ipp == NULL || num_values < 0)
+ return (NULL);
+
+ attr = calloc(sizeof(ipp_attribute_t) +
+ (num_values - 1) * sizeof(ipp_value_t), 1);
+
+ attr->num_values = num_values;
+
+ if (attr == NULL)
+ return (NULL);
+
+ if (ipp->last == NULL)
+ ipp->attrs = attr;
+ else
+ ipp->last->next = attr;
+
+ ipp->last = attr;
+
+ DEBUG_printf(("_ipp_add_attr(): %p\n", attr));
+
+ return (attr);
+}
+
+
+/*
+ * '_ipp_free_attr()' - Free an attribute.
+ */
+
+void
+_ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */
+{
+ int i; /* Looping var */
+ ipp_value_t *value; /* Current value */
+
+
+ DEBUG_printf(("_ipp_free_attr(): %p\n", attr));
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_STRING :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ free(value->string.text);
+ break;
+
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if (value->string.charset && i == 0)
+ free(value->string.charset);
+ free(value->string.text);
+ }
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+
+ if (attr->name != NULL)
+ free(attr->name);
+
+ free(attr);
+}
+
+
+/*
+ * 'ipp_length()' - Compute the length of an IPP request or collection value.
+ */
+
+static size_t /* O - Size of IPP request */
+ipp_length(ipp_t *ipp, /* I - IPP request or collection */
+ int collection) /* I - 1 if a collection, 0 otherwise */
+{
+ int i; /* Looping var */
+ int bytes; /* Number of bytes */
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_tag_t group; /* Current group */
+ ipp_value_t *value; /* Current value */
+
+
+ if (ipp == NULL)
+ return (0);
+
+ /*
+ * Start with 8 bytes for the IPP request or status header...
+ */
+
+ bytes = collection ? 0 : 8;
+
+ /*
+ * Then add the lengths of each attribute...
+ */
+
+ group = IPP_TAG_ZERO;
+
+ for (attr = ipp->attrs; attr != NULL; attr = attr->next)
+ {
+ if (attr->group_tag != group && !collection)
+ {
+ group = attr->group_tag;
+ if (group == IPP_TAG_ZERO)
+ continue;
+
+ bytes ++; /* Group tag */
+ }
+
+ DEBUG_printf(("attr->name = %s, attr->num_values = %d, bytes = %d\n",
+ attr->name, attr->num_values, bytes));
+
+ bytes += strlen(attr->name); /* Name */
+ bytes += attr->num_values; /* Value tag for each value */
+ bytes += 2 * attr->num_values; /* Name lengths */
+ bytes += 2 * attr->num_values; /* Value lengths */
+
+ if (collection)
+ bytes += 5; /* Add membername overhead */
+
+ switch (attr->value_tag & ~IPP_TAG_COPY)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ bytes += 4 * attr->num_values;
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ bytes += attr->num_values;
+ break;
+
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_STRING :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ if (value->string.text != NULL)
+ bytes += strlen(value->string.text);
+ break;
+
+ case IPP_TAG_DATE :
+ bytes += 11 * attr->num_values;
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ bytes += 9 * attr->num_values;
+ break;
+
+ case IPP_TAG_RANGE :
+ bytes += 8 * attr->num_values;
+ break;
+
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ bytes += 4 * attr->num_values;/* Charset + text length */
+
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+ if (value->string.charset != NULL)
+ bytes += strlen(value->string.charset);
+
+ if (value->string.text != NULL)
+ bytes += strlen(value->string.text);
+ }
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ {
+/* bytes += 5;*/ /* Overhead of begCollection */
+ bytes += ipp_length(attr->values[i].collection, 1);
+/* bytes += 5;*/ /* Overhead of endCollection */
+ }
+ break;
+
+ default :
+ for (i = 0, value = attr->values;
+ i < attr->num_values;
+ i ++, value ++)
+ bytes += attr->values[0].unknown.length;
+ break;
+ }
+ }
+
+ /*
+ * Finally, add 1 byte for the "end of attributes" tag or 5 bytes
+ * for the "end of collection" tag and return...
+ */
+
+ if (collection)
+ bytes += 5;
+ else
+ bytes ++;
+
+ DEBUG_printf(("bytes = %d\n", bytes));
+
+ return (bytes);
+}
+
+
+/*
+ * 'ipp_read_http()' - Semi-blocking read on a HTTP connection...
+ */
+
+static int /* O - Number of bytes read */
+ipp_read_http(http_t *http, /* I - Client connection */
+ ipp_uchar_t *buffer, /* O - Buffer for data */
+ int length) /* I - Total length */
+{
+ int tbytes, /* Total bytes read */
+ bytes; /* Bytes read this pass */
+ char len[32]; /* Length string */
+
+
+ DEBUG_printf(("ipp_read_http(http=%p, buffer=%p, length=%d)\n",
+ http, buffer, length));
+
+ /*
+ * Loop until all bytes are read...
+ */
+
+ for (tbytes = 0, bytes = 0; tbytes < length; tbytes += bytes, buffer += bytes)
+ {
+ DEBUG_printf(("tbytes = %d, http->state = %d\n", tbytes, http->state));
+
+ if (http->state == HTTP_WAITING)
+ break;
+
+ if (http->used > 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
+ {
+ /*
+ * Do "fast read" from HTTP buffer directly...
+ */
+
+ if (http->used > (length - tbytes))
+ bytes = length - tbytes;
+ else
+ bytes = http->used;
+
+ if (bytes == 1)
+ buffer[0] = http->buffer[0];
+ else
+ memcpy(buffer, http->buffer, bytes);
+
+ http->used -= bytes;
+ http->data_remaining -= bytes;
+
+ if (http->used > 0)
+ memmove(http->buffer, http->buffer + bytes, http->used);
+
+ if (http->data_remaining == 0)
+ {
+ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+ {
+ /*
+ * Get the trailing CR LF after the chunk...
+ */
+
+ if (!httpGets(len, sizeof(len), http))
+ return (-1);
+ }
+
+ if (http->data_encoding != HTTP_ENCODE_CHUNKED)
+ {
+ if (http->state == HTTP_POST_RECV)
+ http->state ++;
+ else
+ http->state = HTTP_WAITING;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Wait a maximum of 1 second for data...
+ */
+
+ if (!http->blocking)
+ {
+ /*
+ * Wait up to 1 second for more data on non-blocking sockets...
+ */
+
+ if (!httpWait(http, 1000))
+ {
+ /*
+ * Signal no data...
+ */
+
+ bytes = -1;
+ break;
+ }
+ }
+
+ if ((bytes = httpRead(http, (char *)buffer, length - tbytes)) <= 0)
+ break;
+ }
+ }
+
+ /*
+ * Return the number of bytes read...
+ */
+
+ if (tbytes == 0 && bytes < 0)
+ tbytes = -1;
+
+ DEBUG_printf(("returning %d bytes...\n", tbytes));
+
+ return (tbytes);
+}
+
+
+/*
+ * 'ipp_read_file()' - Read IPP data from a file.
+ */
+
+static int /* O - Number of bytes read */
+ipp_read_file(int *fd, /* I - File descriptor */
+ ipp_uchar_t *buffer, /* O - Read buffer */
+ int length) /* I - Number of bytes to read */
+{
+ return (read(*fd, buffer, length));
+}
+
+
+/*
+ * 'ipp_write_file()' - Write IPP data to a file.
+ */
+
+static int /* O - Number of bytes written */
+ipp_write_file(int *fd, /* I - File descriptor */
+ ipp_uchar_t *buffer, /* I - Data to write */
+ int length) /* I - Number of bytes to write */
+{
+ return (write(*fd, buffer, length));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ipp.h b/cups/ipp.h
new file mode 100644
index 000000000..f1ffca378
--- /dev/null
+++ b/cups/ipp.h
@@ -0,0 +1,467 @@
+/*
+ * "$Id$"
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_IPP_H_
+# define _CUPS_IPP_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include "http.h"
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
+ * IPP version string...
+ */
+
+# define IPP_VERSION "\001\001"
+
+/*
+ * IPP registered port number...
+ *
+ * Note: Applications should never use IPP_PORT, but instead use the
+ * ippPort() function to allow overrides via the IPP_PORT environment
+ * variable and services file if needed!
+ */
+
+# define IPP_PORT 631
+
+/*
+ * Common limits...
+ */
+
+# define IPP_MAX_NAME 256
+# define IPP_MAX_VALUES 10 /* Now just an allocation increment */
+
+
+/*
+ * Types and structures...
+ */
+
+typedef enum /**** Format tags for attribute formats... ****/
+{
+ IPP_TAG_ZERO = 0x00,
+ IPP_TAG_OPERATION,
+ IPP_TAG_JOB,
+ IPP_TAG_END,
+ IPP_TAG_PRINTER,
+ IPP_TAG_UNSUPPORTED_GROUP,
+ IPP_TAG_SUBSCRIPTION,
+ IPP_TAG_EVENT_NOTIFICATION,
+ IPP_TAG_UNSUPPORTED_VALUE = 0x10,
+ IPP_TAG_DEFAULT,
+ IPP_TAG_UNKNOWN,
+ IPP_TAG_NOVALUE,
+ IPP_TAG_NOTSETTABLE = 0x15,
+ IPP_TAG_DELETEATTR,
+ IPP_TAG_ADMINDEFINE,
+ IPP_TAG_INTEGER = 0x21,
+ IPP_TAG_BOOLEAN,
+ IPP_TAG_ENUM,
+ IPP_TAG_STRING = 0x30,
+ IPP_TAG_DATE,
+ IPP_TAG_RESOLUTION,
+ IPP_TAG_RANGE,
+ IPP_TAG_BEGIN_COLLECTION,
+ IPP_TAG_TEXTLANG,
+ IPP_TAG_NAMELANG,
+ IPP_TAG_END_COLLECTION,
+ IPP_TAG_TEXT = 0x41,
+ IPP_TAG_NAME,
+ IPP_TAG_KEYWORD = 0x44,
+ IPP_TAG_URI,
+ IPP_TAG_URISCHEME,
+ IPP_TAG_CHARSET,
+ IPP_TAG_LANGUAGE,
+ IPP_TAG_MIMETYPE,
+ IPP_TAG_MEMBERNAME,
+ IPP_TAG_MASK = 0x7fffffff, /* Mask for copied attribute values */
+ IPP_TAG_COPY = -0x7fffffff-1 /* Bitflag for copied attribute values */
+} ipp_tag_t;
+
+typedef enum /**** Resolution units... ****/
+{
+ IPP_RES_PER_INCH = 3,
+ IPP_RES_PER_CM
+} ipp_res_t;
+
+typedef enum /**** Finishings... ****/
+{
+ IPP_FINISHINGS_NONE = 3,
+ IPP_FINISHINGS_STAPLE,
+ IPP_FINISHINGS_PUNCH,
+ IPP_FINISHINGS_COVER,
+ IPP_FINISHINGS_BIND,
+ IPP_FINISHINGS_SADDLE_STITCH,
+ IPP_FINISHINGS_EDGE_STITCH,
+ IPP_FINISHINGS_FOLD,
+ IPP_FINISHINGS_TRIM,
+ IPP_FINISHINGS_BALE,
+ IPP_FINISHINGS_BOOKLET_MAKER,
+ IPP_FINISHINGS_JOB_OFFSET,
+ IPP_FINISHINGS_STAPLE_TOP_LEFT = 20,
+ IPP_FINISHINGS_STAPLE_BOTTOM_LEFT,
+ IPP_FINISHINGS_STAPLE_TOP_RIGHT,
+ IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT,
+ IPP_FINISHINGS_EDGE_STITCH_LEFT,
+ IPP_FINISHINGS_EDGE_STITCH_TOP,
+ IPP_FINISHINGS_EDGE_STITCH_RIGHT,
+ IPP_FINISHINGS_EDGE_STITCH_BOTTOM,
+ IPP_FINISHINGS_STAPLE_DUAL_LEFT,
+ IPP_FINISHINGS_STAPLE_DUAL_TOP,
+ IPP_FINISHINGS_STAPLE_DUAL_RIGHT,
+ IPP_FINISHINGS_STAPLE_DUAL_BOTTOM,
+ IPP_FINISHINGS_BIND_LEFT = 50,
+ IPP_FINISHINGS_BIND_TOP,
+ IPP_FINISHINGS_BIND_RIGHT,
+ IPP_FINISHINGS_BIND_BOTTOM
+} ipp_finish_t;
+
+typedef enum /**** Orientation... ****/
+{
+ IPP_PORTRAIT = 3, /* No rotation */
+ IPP_LANDSCAPE, /* 90 degrees counter-clockwise */
+ IPP_REVERSE_LANDSCAPE, /* 90 degrees clockwise */
+ IPP_REVERSE_PORTRAIT /* 180 degrees */
+} ipp_orient_t;
+
+typedef enum /**** Qualities... ****/
+{
+ IPP_QUALITY_DRAFT = 3,
+ IPP_QUALITY_NORMAL,
+ IPP_QUALITY_HIGH
+} ipp_quality_t;
+
+typedef enum /**** Job States.... */
+{
+ IPP_JOB_PENDING = 3,
+ IPP_JOB_HELD,
+ IPP_JOB_PROCESSING,
+ IPP_JOB_STOPPED,
+ IPP_JOB_CANCELLED,
+ IPP_JOB_ABORTED,
+ IPP_JOB_COMPLETED
+} ipp_jstate_t;
+
+typedef enum /**** Printer States.... */
+{
+ IPP_PRINTER_IDLE = 3,
+ IPP_PRINTER_PROCESSING,
+ IPP_PRINTER_STOPPED
+} ipp_pstate_t;
+
+typedef enum /**** IPP states... ****/
+{
+ IPP_ERROR = -1, /* An error occurred */
+ IPP_IDLE, /* Nothing is happening/request completed */
+ IPP_HEADER, /* The request header needs to be sent/received */
+ IPP_ATTRIBUTE, /* One or more attributes need to be sent/received */
+ IPP_DATA /* IPP request data needs to be sent/received */
+} ipp_state_t;
+
+typedef enum /**** IPP operations... ****/
+{
+ IPP_PRINT_JOB = 0x0002,
+ IPP_PRINT_URI,
+ IPP_VALIDATE_JOB,
+ IPP_CREATE_JOB,
+ IPP_SEND_DOCUMENT,
+ IPP_SEND_URI,
+ IPP_CANCEL_JOB,
+ IPP_GET_JOB_ATTRIBUTES,
+ IPP_GET_JOBS,
+ IPP_GET_PRINTER_ATTRIBUTES,
+ IPP_HOLD_JOB,
+ IPP_RELEASE_JOB,
+ IPP_RESTART_JOB,
+ IPP_PAUSE_PRINTER = 0x0010,
+ IPP_RESUME_PRINTER,
+ IPP_PURGE_JOBS,
+ IPP_SET_PRINTER_ATTRIBUTES,
+ IPP_SET_JOB_ATTRIBUTES,
+ IPP_GET_PRINTER_SUPPORTED_VALUES,
+ IPP_CREATE_PRINTER_SUBSCRIPTION,
+ IPP_CREATE_JOB_SUBSCRIPTION,
+ IPP_GET_SUBSCRIPTION_ATTRIBUTES,
+ IPP_GET_SUBSCRIPTIONS,
+ IPP_RENEW_SUBSCRIPTION,
+ IPP_CANCEL_SUBSCRIPTION,
+ IPP_GET_NOTIFICATIONS,
+ IPP_SEND_NOTIFICATIONS,
+ IPP_GET_PRINT_SUPPORT_FILES = 0x0021,
+ IPP_ENABLE_PRINTER,
+ IPP_DISABLE_PRINTER,
+ IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB,
+ IPP_HOLD_NEW_JOBS,
+ IPP_RELEASE_HELD_NEW_JOBS,
+ IPP_DEACTIVATE_PRINTER,
+ IPP_ACTIVATE_PRINTER,
+ IPP_RESTART_PRINTER,
+ IPP_SHUTDOWN_PRINTER,
+ IPP_STARTUP_PRINTER,
+ IPP_REPROCESS_JOB,
+ IPP_CANCEL_CURRENT_JOB,
+ IPP_SUSPEND_CURRENT_JOB,
+ IPP_RESUME_JOB,
+ IPP_PROMOTE_JOB,
+ IPP_SCHEDULE_JOB_AFTER,
+ IPP_PRIVATE = 0x4000,
+ CUPS_GET_DEFAULT,
+ CUPS_GET_PRINTERS,
+ CUPS_ADD_PRINTER,
+ CUPS_DELETE_PRINTER,
+ CUPS_GET_CLASSES,
+ CUPS_ADD_CLASS,
+ CUPS_DELETE_CLASS,
+ CUPS_ACCEPT_JOBS,
+ CUPS_REJECT_JOBS,
+ CUPS_SET_DEFAULT,
+ CUPS_GET_DEVICES,
+ CUPS_GET_PPDS,
+ CUPS_MOVE_JOB,
+ CUPS_ADD_DEVICE,
+ CUPS_DELETE_DEVICE
+} ipp_op_t;
+
+typedef enum /**** IPP status codes... ****/
+{
+ IPP_OK = 0x0000,
+ IPP_OK_SUBST,
+ IPP_OK_CONFLICT,
+ IPP_OK_IGNORED_SUBSCRIPTIONS,
+ IPP_OK_IGNORED_NOTIFICATIONS,
+ IPP_OK_TOO_MANY_EVENTS,
+ IPP_OK_BUT_CANCEL_SUBSCRIPTION,
+ IPP_REDIRECTION_OTHER_SITE = 0x300,
+ IPP_BAD_REQUEST = 0x0400,
+ IPP_FORBIDDEN,
+ IPP_NOT_AUTHENTICATED,
+ IPP_NOT_AUTHORIZED,
+ IPP_NOT_POSSIBLE,
+ IPP_TIMEOUT,
+ IPP_NOT_FOUND,
+ IPP_GONE,
+ IPP_REQUEST_ENTITY,
+ IPP_REQUEST_VALUE,
+ IPP_DOCUMENT_FORMAT,
+ IPP_ATTRIBUTES,
+ IPP_URI_SCHEME,
+ IPP_CHARSET,
+ IPP_CONFLICT,
+ IPP_COMPRESSION_NOT_SUPPORTED,
+ IPP_COMPRESSION_ERROR,
+ IPP_DOCUMENT_FORMAT_ERROR,
+ IPP_DOCUMENT_ACCESS_ERROR,
+ IPP_ATTRIBUTES_NOT_SETTABLE,
+ IPP_IGNORED_ALL_SUBSCRIPTIONS,
+ IPP_TOO_MANY_SUBSCRIPTIONS,
+ IPP_IGNORED_ALL_NOTIFICATIONS,
+ IPP_PRINT_SUPPORT_FILE_NOT_FOUND,
+
+ IPP_INTERNAL_ERROR = 0x0500,
+ IPP_OPERATION_NOT_SUPPORTED,
+ IPP_SERVICE_UNAVAILABLE,
+ IPP_VERSION_NOT_SUPPORTED,
+ IPP_DEVICE_ERROR,
+ IPP_TEMPORARY_ERROR,
+ IPP_NOT_ACCEPTING,
+ IPP_PRINTER_BUSY,
+ IPP_ERROR_JOB_CANCELLED,
+ IPP_MULTIPLE_JOBS_NOT_SUPPORTED,
+ IPP_PRINTER_IS_DEACTIVATED
+} ipp_status_t;
+
+typedef unsigned char ipp_uchar_t;/**** Unsigned 8-bit integer/character ****/
+
+/**** New in CUPS 1.1.19 ****/
+typedef int (*ipp_iocb_t)(void *, ipp_uchar_t *, int);
+ /**** IPP IO Callback Function ****/
+
+typedef union /**** Request Header ****/
+{
+ struct /* Any Header */
+ {
+ ipp_uchar_t version[2]; /* Protocol version number */
+ int op_status; /* Operation ID or status code*/
+ int request_id; /* Request ID */
+ } any;
+
+ struct /* Operation Header */
+ {
+ ipp_uchar_t version[2]; /* Protocol version number */
+ ipp_op_t operation_id; /* Operation ID */
+ int request_id; /* Request ID */
+ } op;
+
+ struct /* Status Header */
+ {
+ ipp_uchar_t version[2]; /* Protocol version number */
+ ipp_status_t status_code; /* Status code */
+ int request_id; /* Request ID */
+ } status;
+
+ /**** New in CUPS 1.1.19 ****/
+ struct /* Event Header */
+ {
+ ipp_uchar_t version[2]; /* Protocol version number */
+ ipp_status_t status_code; /* Status code */
+ int request_id; /* Request ID */
+ } event;
+} ipp_request_t;
+
+/**** New in CUPS 1.1.19 ****/
+typedef struct ipp_str ipp_t;
+
+typedef union /**** Attribute Value ****/
+{
+ int integer; /* Integer/enumerated value */
+
+ char boolean; /* Boolean value */
+
+ ipp_uchar_t date[11]; /* Date/time value */
+
+ struct
+ {
+ int xres, /* Horizontal resolution */
+ yres; /* Vertical resolution */
+ ipp_res_t units; /* Resolution units */
+ } resolution; /* Resolution value */
+
+ struct
+ {
+ int lower, /* Lower value */
+ upper; /* Upper value */
+ } range; /* Range of integers value */
+
+ struct
+ {
+ char *charset; /* Character set */
+ char *text; /* String */
+ } string; /* String with language value */
+
+ struct
+ {
+ int length; /* Length of attribute */
+ void *data; /* Data in attribute */
+ } unknown; /* Unknown attribute type */
+
+/**** New in CUPS 1.1.19 ****/
+ ipp_t *collection; /* Collection value */
+} ipp_value_t;
+
+typedef struct ipp_attribute_s /**** Attribute ****/
+{
+ struct ipp_attribute_s *next; /* Next attribute in list */
+ ipp_tag_t group_tag, /* Job/Printer/Operation group tag */
+ value_tag; /* What type of value is it? */
+ char *name; /* Name of attribute */
+ int num_values; /* Number of values */
+ ipp_value_t values[1]; /* Values */
+} ipp_attribute_t;
+
+struct ipp_str /**** IPP Request/Response/Notification ****/
+{
+ ipp_state_t state; /* State of request */
+ ipp_request_t request; /* Request header */
+ ipp_attribute_t *attrs, /* Attributes */
+ *last, /* Last attribute in list */
+ *current; /* Current attribute (for read/write) */
+ ipp_tag_t curtag; /* Current attribute group tag */
+};
+
+
+/*
+ * Prototypes...
+ */
+
+extern ipp_attribute_t *ippAddBoolean(ipp_t *ipp, ipp_tag_t group, const char *name, char value);
+extern ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const char *values);
+extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group, const char *name, const ipp_uchar_t *value);
+extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int value);
+extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const int *values);
+extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group, const char *name, int lower, int upper);
+extern ipp_attribute_t *ippAddRanges(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const int *lower, const int *upper);
+extern ipp_attribute_t *ippAddResolution(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_res_t units, int xres, int yres);
+extern ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, ipp_res_t units, const int *xres, const int *yres);
+extern ipp_attribute_t *ippAddSeparator(ipp_t *ipp);
+extern ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, const char *charset, const char *value);
+extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group, ipp_tag_t type, const char *name, int num_values, const char *charset, const char * const *values);
+extern time_t ippDateToTime(const ipp_uchar_t *date);
+extern void ippDelete(ipp_t *ipp);
+extern const char *ippErrorString(ipp_status_t error);
+extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const char *name,
+ ipp_tag_t type);
+extern ipp_attribute_t *ippFindNextAttribute(ipp_t *ipp, const char *name,
+ ipp_tag_t type);
+extern size_t ippLength(ipp_t *ipp);
+extern ipp_t *ippNew(void);
+extern ipp_state_t ippRead(http_t *http, ipp_t *ipp);
+extern const ipp_uchar_t *ippTimeToDate(time_t t);
+extern ipp_state_t ippWrite(http_t *http, ipp_t *ipp);
+extern int ippPort(void);
+extern void ippSetPort(int p);
+
+/**** New in CUPS 1.1.19 ****/
+extern ipp_attribute_t *ippAddCollection(ipp_t *ipp, ipp_tag_t group, const char *name, ipp_t *value);
+extern ipp_attribute_t *ippAddCollections(ipp_t *ipp, ipp_tag_t group, const char *name, int num_values, const ipp_t **values);
+extern void ippDeleteAttribute(ipp_t *ipp, ipp_attribute_t *attr);
+extern ipp_state_t ippReadFile(int fd, ipp_t *ipp);
+extern ipp_state_t ippReadIO(void *src, ipp_iocb_t cb, int blocking, ipp_t *parent, ipp_t *ipp);
+extern ipp_state_t ippWriteFile(int fd, ipp_t *ipp);
+extern ipp_state_t ippWriteIO(void *dst, ipp_iocb_t cb, int blocking, ipp_t *parent, ipp_t *ipp);
+
+
+/*
+ * "Private" functions used internally by CUPS...
+ */
+
+extern ipp_attribute_t *_ipp_add_attr(ipp_t *, int);
+extern void _ipp_free_attr(ipp_attribute_t *);
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+#endif /* !_CUPS_IPP_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/language.c b/cups/language.c
new file mode 100644
index 000000000..8134cd9b7
--- /dev/null
+++ b/cups/language.c
@@ -0,0 +1,993 @@
+/*
+ * "$Id$"
+ *
+ * I18N/language support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsLangEncoding() - Return the character encoding (us-ascii, etc.)
+ * for the given language.
+ * cupsLangFlush() - Flush all language data out of the cache.
+ * cupsLangFree() - Free language data.
+ * cupsLangGet() - Get a language.
+ * _cupsRestoreLocale() - Restore the original locale...
+ * _cupsSaveLocale() - Set the locale and save a copy of the old locale...
+ * appleLangDefault() - Get the default locale string.
+ * cups_cache_lookup() - Lookup a language in the cache...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif /* HAVE_LANGINFO_H */
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 */
+#include "string.h"
+#include "language.h"
+#include "debug.h"
+
+
+/*
+ * Local functions...
+ */
+
+#ifdef __APPLE__
+# include <CoreFoundation/CoreFoundation.h>
+static const char *appleLangDefault(void);
+#endif /* __APPLE__ */
+
+static cups_lang_t *cups_cache_lookup(const char *name,
+ cups_encoding_t encoding);
+
+
+/*
+ * Local globals...
+ */
+
+static cups_lang_t *lang_cache = NULL;
+ /* Language string cache */
+static const char lang_blank[] = "";
+ /* Blank constant string */
+static const char * const lang_encodings[] =
+ { /* Encoding strings */
+ "us-ascii",
+ "iso-8859-1",
+ "iso-8859-2",
+ "iso-8859-3",
+ "iso-8859-4",
+ "iso-8859-5",
+ "iso-8859-6",
+ "iso-8859-7",
+ "iso-8859-8",
+ "iso-8859-9",
+ "iso-8859-10",
+ "utf-8",
+ "iso-8859-13",
+ "iso-8859-14",
+ "iso-8859-15",
+ "windows-874",
+ "windows-1250",
+ "windows-1251",
+ "windows-1252",
+ "windows-1253",
+ "windows-1254",
+ "windows-1255",
+ "windows-1256",
+ "windows-1257",
+ "windows-1258",
+ "koi8-r",
+ "koi8-u"
+ };
+static const char * const lang_default[] =
+ { /* Default POSIX locale */
+#include "cups_C.h"
+ NULL
+ };
+
+
+/*
+ * 'cupsLangEncoding()' - Return the character encoding (us-ascii, etc.)
+ * for the given language.
+ */
+
+char * /* O - Character encoding */
+cupsLangEncoding(cups_lang_t *lang) /* I - Language data */
+{
+ if (lang == NULL)
+ return ((char*)lang_encodings[0]);
+ else
+ return ((char*)lang_encodings[lang->encoding]);
+}
+
+
+/*
+ * 'cupsLangFlush()' - Flush all language data out of the cache.
+ */
+
+void
+cupsLangFlush(void)
+{
+ int i; /* Looping var */
+ cups_lang_t *lang, /* Current language */
+ *next; /* Next language */
+
+
+ /*
+ * Free all languages in the cache...
+ */
+
+ for (lang = lang_cache; lang != NULL; lang = next)
+ {
+ /*
+ * Free all messages...
+ */
+
+ for (i = 0; i < CUPS_MSG_MAX; i ++)
+ if (lang->messages[i] != NULL && lang->messages[i] != lang_blank)
+ free(lang->messages[i]);
+
+ /*
+ * Then free the language structure itself...
+ */
+
+ next = lang->next;
+ free(lang);
+ }
+
+ lang_cache = NULL;
+}
+
+
+/*
+ * 'cupsLangFree()' - Free language data.
+ *
+ * This does not actually free anything; use cupsLangFlush() for that.
+ */
+
+void
+cupsLangFree(cups_lang_t *lang) /* I - Language to free */
+{
+ if (lang != NULL && lang->used > 0)
+ lang->used --;
+}
+
+
+/*
+ * 'cupsLangGet()' - Get a language.
+ */
+
+cups_lang_t * /* O - Language data */
+cupsLangGet(const char *language) /* I - Language or locale */
+{
+ int i, count; /* Looping vars */
+ char locale[255], /* Copy of locale name */
+ langname[16], /* Requested language name */
+ country[16], /* Country code */
+ charset[16], /* Character set */
+#ifdef CODESET
+ *csptr, /* Pointer to CODESET string */
+#endif /* CODESET */
+ *ptr, /* Pointer into language/charset */
+ real[48], /* Real language name */
+ filename[1024], /* Filename for language locale file */
+ *localedir; /* Directory for locale files */
+ cups_encoding_t encoding; /* Encoding to use */
+ FILE *fp; /* Language locale file pointer */
+ char line[1024]; /* Line from file */
+ cups_msg_t msg; /* Message number */
+ char *text; /* Message text */
+ cups_lang_t *lang; /* Current language... */
+ char *oldlocale; /* Old locale name */
+ static const char * const locale_encodings[] =
+ { /* Locale charset names */
+ "ASCII",
+ "ISO88591",
+ "ISO88592",
+ "ISO88593",
+ "ISO88594",
+ "ISO88595",
+ "ISO88596",
+ "ISO88597",
+ "ISO88598",
+ "ISO88599",
+ "ISO885910",
+ "UTF8",
+ "ISO885913",
+ "ISO885914",
+ "ISO885915",
+ "CP874",
+ "CP1250",
+ "CP1251",
+ "CP1252",
+ "CP1253",
+ "CP1254",
+ "CP1255",
+ "CP1256",
+ "CP1257",
+ "CP1258",
+ "KOI8R",
+ "KOI8U"
+ };
+
+
+ DEBUG_printf(("cupsLangGet(language=\"%s\")\n", language ? language : "(null)"));
+
+#ifdef __APPLE__
+ /*
+ * Apple's setlocale doesn't give us the user's localization
+ * preference so we have to look it up this way...
+ */
+
+ if (language == NULL)
+ language = appleLangDefault();
+#else
+ if (language == NULL)
+ {
+ /*
+ * First see if the locale has been set; if it is still "C" or
+ * "POSIX", set the locale to the default...
+ */
+
+# ifdef LC_MESSAGES
+ ptr = setlocale(LC_MESSAGES, NULL);
+# else
+ ptr = setlocale(LC_ALL, NULL);
+# endif /* LC_MESSAGES */
+
+ DEBUG_printf(("cupsLangGet: current locale is \"%s\"\n",
+ ptr ? ptr : "(null)"));
+
+ if (!ptr || !strcmp(ptr, "C") || !strcmp(ptr, "POSIX"))
+# ifdef LC_MESSAGES
+ {
+ ptr = setlocale(LC_MESSAGES, "");
+ setlocale(LC_CTYPE, "");
+ }
+# else
+ ptr = setlocale(LC_ALL, "");
+# endif /* LC_MESSAGES */
+
+ if (ptr)
+ {
+ strlcpy(locale, ptr, sizeof(locale));
+ language = locale;
+
+ DEBUG_printf(("cupsLangGet: new language value is \"%s\"\n",
+ language ? language : "(null)"));
+ }
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * If "language" is NULL at this point, then chances are we are using
+ * a language that is not installed for the base OS.
+ */
+
+ if (!language)
+ {
+ /*
+ * Switch to the value of the "LANG" environment variable, and if
+ * that is NULL as well, use "C".
+ */
+
+ if ((language = getenv("LANG")) == NULL)
+ language = "C";
+ }
+
+ /*
+ * Set the charset to "unknown"...
+ */
+
+ charset[0] = '\0';
+
+#ifdef CODESET
+ /*
+ * On systems that support the nl_langinfo(CODESET) call, use
+ * this value as the character set...
+ */
+
+ if ((csptr = nl_langinfo(CODESET)) != NULL)
+ {
+ /*
+ * Copy all of the letters and numbers in the CODESET string...
+ */
+
+ for (ptr = charset; *csptr; csptr ++)
+ if (isalnum(*csptr & 255) && ptr < (charset + sizeof(charset) - 1))
+ *ptr++ = *csptr;
+
+ *ptr = '\0';
+
+ DEBUG_printf(("cupsLangGet: charset set to \"%s\" via nl_langinfo(CODESET)...\n",
+ charset));
+ }
+#endif /* CODESET */
+
+ /*
+ * Set the locale back to POSIX while we do string ops, since
+ * apparently some buggy C libraries break ctype() for non-I18N
+ * chars...
+ */
+
+#if defined(__APPLE__)
+ /* The ctype bug isn't in Apple's libc */
+#elif !defined(LC_CTYPE)
+ oldlocale = _cupsSaveLocale(LC_ALL, "C");
+#else
+ oldlocale = _cupsSaveLocale(LC_CTYPE, "C");
+#endif /* __APPLE__ */
+
+ /*
+ * Parse the language string passed in to a locale string. "C" is the
+ * standard POSIX locale and is copied unchanged. Otherwise the
+ * language string is converted from ll-cc[.charset] (language-country)
+ * to ll_CC[.CHARSET] to match the file naming convention used by all
+ * POSIX-compliant operating systems. Invalid language names are mapped
+ * to the POSIX locale.
+ */
+
+ country[0] = '\0';
+
+ if (language == NULL || !language[0] ||
+ strcmp(language, "POSIX") == 0)
+ strcpy(langname, "C");
+ else
+ {
+ /*
+ * Copy the parts of the locale string over safely...
+ */
+
+ for (ptr = langname; *language; language ++)
+ if (*language == '_' || *language == '-' || *language == '.')
+ break;
+ else if (ptr < (langname + sizeof(langname) - 1))
+ *ptr++ = tolower(*language & 255);
+
+ *ptr = '\0';
+
+ if (*language == '_' || *language == '-')
+ {
+ /*
+ * Copy the country code...
+ */
+
+ for (language ++, ptr = country; *language; language ++)
+ if (*language == '.')
+ break;
+ else if (ptr < (country + sizeof(country) - 1))
+ *ptr++ = toupper(*language & 255);
+
+ *ptr = '\0';
+ }
+
+ if (*language == '.' && !charset[0])
+ {
+ /*
+ * Copy the encoding...
+ */
+
+ for (language ++, ptr = charset; *language; language ++)
+ if (isalnum(*language & 255) && ptr < (charset + sizeof(charset) - 1))
+ *ptr++ = toupper(*language & 255);
+
+ *ptr = '\0';
+ }
+
+ /*
+ * Force a POSIX locale for an invalid language name...
+ */
+
+ if (strlen(langname) != 2)
+ {
+ strcpy(langname, "C");
+ country[0] = '\0';
+ charset[0] = '\0';
+ }
+ }
+
+ /*
+ * Restore the locale...
+ */
+
+#if defined(__APPLE__)
+ /* The ctype bug isn't in Apple's libc */
+#elif !defined(LC_CTYPE)
+ _cupsRestoreLocale(LC_ALL, oldlocale);
+#else
+ _cupsRestoreLocale(LC_CTYPE, oldlocale);
+#endif /* __APPLE__ */
+
+ DEBUG_printf(("cupsLangGet: langname=\"%s\", country=\"%s\", charset=\"%s\"\n",
+ langname, country, charset));
+
+ /*
+ * Figure out the desired encoding...
+ */
+
+ encoding = CUPS_AUTO_ENCODING;
+
+ if (charset[0])
+ {
+ for (i = 0; i < (int)(sizeof(locale_encodings) / sizeof(locale_encodings[0])); i ++)
+ if (!strcasecmp(charset, locale_encodings[i]))
+ {
+ encoding = (cups_encoding_t)i;
+ break;
+ }
+ }
+
+ DEBUG_printf(("cupsLangGet: encoding=%d(%s)\n", encoding,
+ encoding == CUPS_AUTO_ENCODING ? "auto" :
+ lang_encodings[encoding]));
+
+ /*
+ * Now find the message catalog for this locale...
+ */
+
+ if ((localedir = getenv("LOCALEDIR")) == NULL)
+ localedir = CUPS_LOCALEDIR;
+
+ /*
+ * See if we already have this language/country loaded...
+ */
+
+ snprintf(real, sizeof(real), "%s_%s", langname, country);
+
+ if ((lang = cups_cache_lookup(real, encoding)) != NULL)
+ return (lang);
+
+ snprintf(filename, sizeof(filename), "%s/%s/cups_%s", localedir, real, real);
+
+ if (!country[0] || access(filename, 0))
+ {
+ /*
+ * Country localization not available, look for generic localization...
+ */
+
+ if ((lang = cups_cache_lookup(langname, encoding)) != NULL)
+ return (lang);
+
+ snprintf(filename, sizeof(filename), "%s/%s/cups_%s", localedir,
+ langname, langname);
+
+ if (access(filename, 0))
+ {
+ /*
+ * No generic localization, so use POSIX...
+ */
+
+ strcpy(real, "C");
+ snprintf(filename, sizeof(filename), "%s/C/cups_C", localedir);
+ }
+ else
+ strcpy(real, langname);
+ }
+
+ /*
+ * Open the messages file; the first line contains the default
+ * language encoding (us-ascii, iso-8859-1, etc.), and the rest are
+ * messages consisting of:
+ *
+ * #### SP message text
+ *
+ * or:
+ *
+ * message text
+ *
+ * If the line starts with a number, then message processing picks up
+ * where the number indicates. Otherwise the last message number is
+ * incremented.
+ *
+ * All leading whitespace is deleted.
+ */
+
+ if (strcmp(real, "C"))
+ fp = fopen(filename, "r");
+ else
+ fp = NULL;
+
+ if (fp == NULL)
+ strlcpy(line, lang_default[0], sizeof(line));
+ else if (fgets(line, sizeof(line), fp) == NULL)
+ {
+ /*
+ * Can't read encoding!
+ */
+
+ fclose(fp);
+ return (NULL);
+ }
+
+ i = strlen(line) - 1;
+ if (line[i] == '\n')
+ line[i] = '\0'; /* Strip LF */
+
+ /*
+ * See if there is a free language available; if so, use that
+ * record...
+ */
+
+ for (lang = lang_cache; lang != NULL; lang = lang->next)
+ if (lang->used == 0)
+ break;
+
+ if (lang == NULL)
+ {
+ /*
+ * Allocate memory for the language and add it to the cache.
+ */
+
+ if ((lang = calloc(sizeof(cups_lang_t), 1)) == NULL)
+ {
+ fclose(fp);
+ return (NULL);
+ }
+
+ lang->next = lang_cache;
+ lang_cache = lang;
+ }
+
+ /*
+ * Free all old strings as needed...
+ */
+
+ for (i = 0; i < CUPS_MSG_MAX; i ++)
+ {
+ if (lang->messages[i] != NULL && lang->messages[i] != lang_blank)
+ free(lang->messages[i]);
+
+ lang->messages[i] = (char*)lang_blank;
+ }
+
+ /*
+ * Then assign the language and encoding fields...
+ */
+
+ lang->used ++;
+ strlcpy(lang->language, real, sizeof(lang->language));
+
+ if (encoding != CUPS_AUTO_ENCODING)
+ lang->encoding = encoding;
+ else
+ {
+ lang->encoding = CUPS_US_ASCII;
+
+ for (i = 0; i < (sizeof(lang_encodings) / sizeof(lang_encodings[0])); i ++)
+ if (strcmp(lang_encodings[i], line) == 0)
+ {
+ lang->encoding = (cups_encoding_t)i;
+ break;
+ }
+ }
+
+ /*
+ * Read the strings from the file...
+ */
+
+ msg = (cups_msg_t)-1;
+ count = 1;
+
+ for (;;)
+ {
+ /*
+ * Read a line from memory or from a file...
+ */
+
+ if (fp == NULL)
+ {
+ if (lang_default[count] == NULL)
+ break;
+
+ strlcpy(line, lang_default[count], sizeof(line));
+ }
+ else if (fgets(line, sizeof(line), fp) == NULL)
+ break;
+
+ count ++;
+
+ /*
+ * Ignore blank lines...
+ */
+
+ i = strlen(line) - 1;
+ if (line[i] == '\n')
+ line[i] = '\0'; /* Strip LF */
+
+ if (line[0] == '\0')
+ continue;
+
+ /*
+ * Grab the message number and text...
+ */
+
+ if (isdigit(line[0] & 255))
+ msg = (cups_msg_t)atoi(line);
+ else
+ msg ++;
+
+ if (msg < 0 || msg >= CUPS_MSG_MAX)
+ continue;
+
+ text = line;
+ while (isdigit(*text & 255))
+ text ++;
+ while (isspace(*text & 255))
+ text ++;
+
+ lang->messages[msg] = strdup(text);
+ }
+
+ /*
+ * Close the file and return...
+ */
+
+ if (fp != NULL)
+ fclose(fp);
+
+ return (lang);
+}
+
+
+/*
+ * '_cupsRestoreLocale()' - Restore the original locale...
+ */
+
+void
+_cupsRestoreLocale(int category, /* I - Category */
+ char *oldlocale) /* I - Old locale or NULL */
+{
+ DEBUG_printf(("_cupsRestoreLocale(category=%d, oldlocale=\"%s\")\n",
+ category, oldlocale));
+
+ if (oldlocale)
+ {
+ /*
+ * Reset the locale and free the locale string...
+ */
+
+ setlocale(category, oldlocale);
+ free(oldlocale);
+ }
+}
+
+
+/*
+ * '_cupsSaveLocale()' - Set the locale and save a copy of the old locale...
+ */
+
+char * /* O - Old locale or NULL */
+_cupsSaveLocale(int category, /* I - Category */
+ const char *locale) /* I - New locale or NULL */
+{
+ char *oldlocale; /* Old locale */
+
+
+ DEBUG_printf(("_cupsSaveLocale(category=%d, locale=\"%s\")\n",
+ category, locale));
+
+ /*
+ * Get the old locale and copy it...
+ */
+
+ if ((oldlocale = setlocale(category, NULL)) != NULL)
+ oldlocale = strdup(oldlocale);
+
+ DEBUG_printf((" oldlocale=\"%s\"\n", oldlocale ? oldlocale : "(null)"));
+
+ /*
+ * Set the new locale...
+ */
+
+ setlocale(category, locale);
+
+ /*
+ * Return a copy of the old locale...
+ */
+
+ return (oldlocale);
+}
+
+
+#ifdef __APPLE__
+/*
+ * Code & data to translate OSX's language names to their ISO 639-1 locale.
+ *
+ * The first version uses the new CoreFoundation API added in 10.3 (Panther),
+ * the second is for 10.2 (Jaguar).
+ */
+
+# ifdef HAVE_CF_LOCALE_ID
+/*
+ * 'appleLangDefault()' - Get the default locale string.
+ */
+
+static const char * /* O - Locale string */
+appleLangDefault(void)
+{
+ CFPropertyListRef localizationList;
+ /* List of localization data */
+ CFStringRef languageName; /* Current name */
+ CFStringRef localeName; /* Canonical from of name */
+ static char language[32] = "";
+ /* Cached language */
+
+
+ /*
+ * Only do the lookup and translation the first time.
+ */
+
+ if (!language[0])
+ {
+ localizationList =
+ CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
+
+ if (localizationList != NULL)
+ {
+ if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
+ CFArrayGetCount(localizationList) > 0)
+ {
+ languageName = CFArrayGetValueAtIndex(localizationList, 0);
+
+ if (languageName != NULL &&
+ CFGetTypeID(languageName) == CFStringGetTypeID())
+ {
+ localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(
+ kCFAllocatorDefault, languageName);
+
+ if (localeName != NULL)
+ {
+ CFStringGetCString(localeName, language, sizeof(language),
+ kCFStringEncodingASCII);
+ CFRelease(localeName);
+
+ if (!strcmp(language, "en"))
+ strlcpy(language, "en_US.UTF-8", sizeof(language));
+ else if (strchr(language, '.') == NULL)
+ strlcat(language, ".UTF-8", sizeof(language));
+ }
+ }
+ }
+
+ CFRelease(localizationList);
+ }
+
+ /*
+ * If we didn't find the language, default to en_US...
+ */
+
+ if (!language[0])
+ strlcpy(language, "en_US.UTF-8", sizeof(language));
+ }
+
+ /*
+ * Return the cached locale...
+ */
+
+ return (language);
+}
+# else
+/*
+ * Code & data to translate OSX 10.2's language names to their ISO 639-1
+ * locale.
+ */
+
+typedef struct
+{
+ const char * const name; /* Language name */
+ const char * const locale; /* Locale name */
+} apple_name_locale_t;
+
+static const apple_name_locale_t apple_name_locale[] =
+{
+ { "English" , "en_US.UTF-8" }, { "French" , "fr.UTF-8" },
+ { "German" , "de.UTF-8" }, { "Italian" , "it.UTF-8" },
+ { "Dutch" , "nl.UTF-8" }, { "Swedish" , "sv.UTF-8" },
+ { "Spanish" , "es.UTF-8" }, { "Danish" , "da.UTF-8" },
+ { "Portuguese" , "pt.UTF-8" }, { "Norwegian" , "no.UTF-8" },
+ { "Hebrew" , "he.UTF-8" }, { "Japanese" , "ja.UTF-8" },
+ { "Arabic" , "ar.UTF-8" }, { "Finnish" , "fi.UTF-8" },
+ { "Greek" , "el.UTF-8" }, { "Icelandic" , "is.UTF-8" },
+ { "Maltese" , "mt.UTF-8" }, { "Turkish" , "tr.UTF-8" },
+ { "Croatian" , "hr.UTF-8" }, { "Chinese" , "zh.UTF-8" },
+ { "Urdu" , "ur.UTF-8" }, { "Hindi" , "hi.UTF-8" },
+ { "Thai" , "th.UTF-8" }, { "Korean" , "ko.UTF-8" },
+ { "Lithuanian" , "lt.UTF-8" }, { "Polish" , "pl.UTF-8" },
+ { "Hungarian" , "hu.UTF-8" }, { "Estonian" , "et.UTF-8" },
+ { "Latvian" , "lv.UTF-8" }, { "Sami" , "se.UTF-8" },
+ { "Faroese" , "fo.UTF-8" }, { "Farsi" , "fa.UTF-8" },
+ { "Russian" , "ru.UTF-8" }, { "Chinese" , "zh.UTF-8" },
+ { "Dutch" , "nl.UTF-8" }, { "Irish" , "ga.UTF-8" },
+ { "Albanian" , "sq.UTF-8" }, { "Romanian" , "ro.UTF-8" },
+ { "Czech" , "cs.UTF-8" }, { "Slovak" , "sk.UTF-8" },
+ { "Slovenian" , "sl.UTF-8" }, { "Yiddish" , "yi.UTF-8" },
+ { "Serbian" , "sr.UTF-8" }, { "Macedonian" , "mk.UTF-8" },
+ { "Bulgarian" , "bg.UTF-8" }, { "Ukrainian" , "uk.UTF-8" },
+ { "Byelorussian", "be.UTF-8" }, { "Uzbek" , "uz.UTF-8" },
+ { "Kazakh" , "kk.UTF-8" }, { "Azerbaijani", "az.UTF-8" },
+ { "Azerbaijani" , "az.UTF-8" }, { "Armenian" , "hy.UTF-8" },
+ { "Georgian" , "ka.UTF-8" }, { "Moldavian" , "mo.UTF-8" },
+ { "Kirghiz" , "ky.UTF-8" }, { "Tajiki" , "tg.UTF-8" },
+ { "Turkmen" , "tk.UTF-8" }, { "Mongolian" , "mn.UTF-8" },
+ { "Mongolian" , "mn.UTF-8" }, { "Pashto" , "ps.UTF-8" },
+ { "Kurdish" , "ku.UTF-8" }, { "Kashmiri" , "ks.UTF-8" },
+ { "Sindhi" , "sd.UTF-8" }, { "Tibetan" , "bo.UTF-8" },
+ { "Nepali" , "ne.UTF-8" }, { "Sanskrit" , "sa.UTF-8" },
+ { "Marathi" , "mr.UTF-8" }, { "Bengali" , "bn.UTF-8" },
+ { "Assamese" , "as.UTF-8" }, { "Gujarati" , "gu.UTF-8" },
+ { "Punjabi" , "pa.UTF-8" }, { "Oriya" , "or.UTF-8" },
+ { "Malayalam" , "ml.UTF-8" }, { "Kannada" , "kn.UTF-8" },
+ { "Tamil" , "ta.UTF-8" }, { "Telugu" , "te.UTF-8" },
+ { "Sinhalese" , "si.UTF-8" }, { "Burmese" , "my.UTF-8" },
+ { "Khmer" , "km.UTF-8" }, { "Lao" , "lo.UTF-8" },
+ { "Vietnamese" , "vi.UTF-8" }, { "Indonesian" , "id.UTF-8" },
+ { "Tagalog" , "tl.UTF-8" }, { "Malay" , "ms.UTF-8" },
+ { "Malay" , "ms.UTF-8" }, { "Amharic" , "am.UTF-8" },
+ { "Tigrinya" , "ti.UTF-8" }, { "Oromo" , "om.UTF-8" },
+ { "Somali" , "so.UTF-8" }, { "Swahili" , "sw.UTF-8" },
+ { "Kinyarwanda" , "rw.UTF-8" }, { "Rundi" , "rn.UTF-8" },
+ { "Nyanja" , "" }, { "Malagasy" , "mg.UTF-8" },
+ { "Esperanto" , "eo.UTF-8" }, { "Welsh" , "cy.UTF-8" },
+ { "Basque" , "eu.UTF-8" }, { "Catalan" , "ca.UTF-8" },
+ { "Latin" , "la.UTF-8" }, { "Quechua" , "qu.UTF-8" },
+ { "Guarani" , "gn.UTF-8" }, { "Aymara" , "ay.UTF-8" },
+ { "Tatar" , "tt.UTF-8" }, { "Uighur" , "ug.UTF-8" },
+ { "Dzongkha" , "dz.UTF-8" }, { "Javanese" , "jv.UTF-8" },
+ { "Sundanese" , "su.UTF-8" }, { "Galician" , "gl.UTF-8" },
+ { "Afrikaans" , "af.UTF-8" }, { "Breton" , "br.UTF-8" },
+ { "Inuktitut" , "iu.UTF-8" }, { "Scottish" , "gd.UTF-8" },
+ { "Manx" , "gv.UTF-8" }, { "Irish" , "ga.UTF-8" },
+ { "Tongan" , "to.UTF-8" }, { "Greek" , "el.UTF-8" },
+ { "Greenlandic" , "kl.UTF-8" }, { "Azerbaijani", "az.UTF-8" }
+};
+
+
+/*
+ * 'appleLangDefault()' - Get the default locale string.
+ */
+
+static const char * /* O - Locale string */
+appleLangDefault(void)
+{
+ int i; /* Looping var */
+ CFPropertyListRef localizationList;
+ /* List of localization data */
+ CFStringRef localizationName;
+ /* Current name */
+ char buff[256]; /* Temporary buffer */
+ static const char *language = NULL;
+ /* Cached language */
+
+
+ /*
+ * Only do the lookup and translation the first time.
+ */
+
+ if (language == NULL)
+ {
+ localizationList =
+ CFPreferencesCopyAppValue(CFSTR("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
+
+ if (localizationList != NULL)
+ {
+ if (CFGetTypeID(localizationList) == CFArrayGetTypeID() &&
+ CFArrayGetCount(localizationList) > 0)
+ {
+ localizationName = CFArrayGetValueAtIndex(localizationList, 0);
+
+ if (localizationName != NULL &&
+ CFGetTypeID(localizationName) == CFStringGetTypeID())
+ {
+ CFIndex length = CFStringGetLength(localizationName);
+
+ if (length <= sizeof(buff) &&
+ CFStringGetCString(localizationName, buff, sizeof(buff),
+ kCFStringEncodingASCII))
+ {
+ buff[sizeof(buff) - 1] = '\0';
+
+ for (i = 0;
+ i < sizeof(apple_name_locale) / sizeof(apple_name_locale[0]);
+ i++)
+ {
+ if (strcasecmp(buff, apple_name_locale[i].name) == 0)
+ {
+ language = apple_name_locale[i].locale;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ CFRelease(localizationList);
+ }
+
+ /*
+ * If we didn't find the language, default to en_US...
+ */
+
+ if (language == NULL)
+ language = apple_name_locale[0].locale;
+ }
+
+ /*
+ * Return the cached locale...
+ */
+
+ return (language);
+}
+# endif /* HAVE_CF_LOCALE_ID */
+#endif /* __APPLE__ */
+
+
+/*
+ * 'cups_cache_lookup()' - Lookup a language in the cache...
+ */
+
+static cups_lang_t * /* O - Language data or NULL */
+cups_cache_lookup(const char *name,/* I - Name of locale */
+ cups_encoding_t encoding)
+ /* I - Encoding of locale */
+{
+ cups_lang_t *lang; /* Current language */
+
+
+ DEBUG_printf(("cups_cache_lookup(name=\"%s\", encoding=%d(%s))\n", name,
+ encoding, encoding == CUPS_AUTO_ENCODING ? "auto" :
+ lang_encodings[encoding]));
+
+ /*
+ * Loop through the cache and return a match if found...
+ */
+
+ for (lang = lang_cache; lang != NULL; lang = lang->next)
+ if (!strcmp(lang->language, name) &&
+ (encoding == CUPS_AUTO_ENCODING || encoding == lang->encoding))
+ {
+ lang->used ++;
+
+ DEBUG_puts("cups_cache_lookup: returning match!");
+
+ return (lang);
+ }
+
+ DEBUG_puts("cups_cache_lookup: returning NULL!");
+
+ return (NULL);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/language.h b/cups/language.h
new file mode 100644
index 000000000..ab3c3e411
--- /dev/null
+++ b/cups/language.h
@@ -0,0 +1,228 @@
+/*
+ * "$Id$"
+ *
+ * Multi-language support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_LANGUAGE_H_
+# define _CUPS_LANGUAGE_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <locale.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+/*
+ * Messages...
+ */
+
+typedef enum /**** Message Indices ****/
+{
+ CUPS_MSG_OK,
+ CUPS_MSG_CANCEL,
+ CUPS_MSG_HELP,
+ CUPS_MSG_QUIT,
+ CUPS_MSG_CLOSE,
+ CUPS_MSG_YES,
+ CUPS_MSG_NO,
+ CUPS_MSG_ON,
+ CUPS_MSG_OFF,
+ CUPS_MSG_SAVE,
+ CUPS_MSG_DISCARD,
+ CUPS_MSG_DEFAULT,
+ CUPS_MSG_OPTIONS,
+ CUPS_MSG_MORE_INFO,
+ CUPS_MSG_BLACK,
+ CUPS_MSG_COLOR,
+ CUPS_MSG_CYAN,
+ CUPS_MSG_MAGENTA,
+ CUPS_MSG_YELLOW,
+ CUPS_MSG_COPYRIGHT,
+ CUPS_MSG_GENERAL,
+ CUPS_MSG_PRINTER,
+ CUPS_MSG_IMAGE,
+ CUPS_MSG_HPGL2,
+ CUPS_MSG_EXTRA,
+ CUPS_MSG_DOCUMENT,
+ CUPS_MSG_OTHER,
+ CUPS_MSG_PRINT_PAGES,
+ CUPS_MSG_ENTIRE_DOCUMENT,
+ CUPS_MSG_PAGE_RANGE,
+ CUPS_MSG_REVERSE_ORDER,
+ CUPS_MSG_PAGE_FORMAT,
+ CUPS_MSG_1_UP,
+ CUPS_MSG_2_UP,
+ CUPS_MSG_4_UP,
+ CUPS_MSG_IMAGE_SCALING,
+ CUPS_MSG_USE_NATURAL_IMAGE_SIZE,
+ CUPS_MSG_ZOOM_BY_PERCENT,
+ CUPS_MSG_ZOOM_BY_PPI,
+ CUPS_MSG_MIRROR_IMAGE,
+ CUPS_MSG_COLOR_SATURATION,
+ CUPS_MSG_COLOR_HUE,
+ CUPS_MSG_FIT_TO_PAGE,
+ CUPS_MSG_SHADING,
+ CUPS_MSG_DEFAULT_PEN_WIDTH,
+ CUPS_MSG_GAMMA_CORRECTION,
+ CUPS_MSG_BRIGHTNESS,
+ CUPS_MSG_ADD,
+ CUPS_MSG_DELETE,
+ CUPS_MSG_MODIFY,
+ CUPS_MSG_PRINTER_URI,
+ CUPS_MSG_PRINTER_NAME,
+ CUPS_MSG_PRINTER_LOCATION,
+ CUPS_MSG_PRINTER_INFO,
+ CUPS_MSG_PRINTER_MAKE_AND_MODEL,
+ CUPS_MSG_DEVICE_URI,
+ CUPS_MSG_FORMATTING_PAGE,
+ CUPS_MSG_PRINTING_PAGE,
+ CUPS_MSG_INITIALIZING_PRINTER,
+ CUPS_MSG_PRINTER_STATE,
+ CUPS_MSG_ACCEPTING_JOBS,
+ CUPS_MSG_NOT_ACCEPTING_JOBS,
+ CUPS_MSG_PRINT_JOBS,
+ CUPS_MSG_CLASS,
+ CUPS_MSG_LOCAL,
+ CUPS_MSG_REMOTE,
+ CUPS_MSG_DUPLEXING,
+ CUPS_MSG_STAPLING,
+ CUPS_MSG_FAST_COPIES,
+ CUPS_MSG_COLLATED_COPIES,
+ CUPS_MSG_PUNCHING,
+ CUPS_MSG_COVERING,
+ CUPS_MSG_BINDING,
+ CUPS_MSG_SORTING,
+ CUPS_MSG_SMALL,
+ CUPS_MSG_MEDIUM,
+ CUPS_MSG_LARGE,
+ CUPS_MSG_VARIABLE,
+ CUPS_MSG_IDLE,
+ CUPS_MSG_PROCESSING,
+ CUPS_MSG_STOPPED,
+ CUPS_MSG_ALL,
+ CUPS_MSG_ODD,
+ CUPS_MSG_EVEN_PAGES,
+ CUPS_MSG_DARKER_LIGHTER,
+ CUPS_MSG_MEDIA_SIZE,
+ CUPS_MSG_MEDIA_TYPE,
+ CUPS_MSG_MEDIA_SOURCE,
+ CUPS_MSG_ORIENTATION,
+ CUPS_MSG_PORTRAIT,
+ CUPS_MSG_LANDSCAPE,
+ CUPS_MSG_JOB_STATE,
+ CUPS_MSG_JOB_NAME,
+ CUPS_MSG_USER_NAME,
+ CUPS_MSG_PRIORITY,
+ CUPS_MSG_COPIES,
+ CUPS_MSG_FILE_SIZE,
+ CUPS_MSG_PENDING,
+ CUPS_MSG_OUTPUT_MODE,
+ CUPS_MSG_RESOLUTION,
+ CUPS_MSG_TEXT,
+ CUPS_MSG_PRETTYPRINT,
+ CUPS_MSG_MARGINS,
+ CUPS_MSG_LEFT,
+ CUPS_MSG_RIGHT,
+ CUPS_MSG_BOTTOM,
+ CUPS_MSG_TOP,
+ CUPS_MSG_FILENAME,
+ CUPS_MSG_PRINT,
+ CUPS_MSG_OPTIONS_INSTALLED,
+ CUPS_MSG_AUTO,
+ CUPS_MSG_HTTP_BASE = 200,
+ CUPS_MSG_HTTP_END = 505,
+ CUPS_MSG_MAX
+} cups_msg_t;
+
+typedef enum /**** Language Encodings ****/
+{
+ CUPS_AUTO_ENCODING = -1,
+ CUPS_US_ASCII,
+ CUPS_ISO8859_1,
+ CUPS_ISO8859_2,
+ CUPS_ISO8859_3,
+ CUPS_ISO8859_4,
+ CUPS_ISO8859_5,
+ CUPS_ISO8859_6,
+ CUPS_ISO8859_7,
+ CUPS_ISO8859_8,
+ CUPS_ISO8859_9,
+ CUPS_ISO8859_10,
+ CUPS_UTF8,
+ CUPS_ISO8859_13,
+ CUPS_ISO8859_14,
+ CUPS_ISO8859_15,
+ CUPS_WINDOWS_874,
+ CUPS_WINDOWS_1250,
+ CUPS_WINDOWS_1251,
+ CUPS_WINDOWS_1252,
+ CUPS_WINDOWS_1253,
+ CUPS_WINDOWS_1254,
+ CUPS_WINDOWS_1255,
+ CUPS_WINDOWS_1256,
+ CUPS_WINDOWS_1257,
+ CUPS_WINDOWS_1258,
+ CUPS_KOI8_R,
+ CUPS_KOI8_U
+} cups_encoding_t;
+
+typedef struct cups_lang_str /**** Language Cache Structure ****/
+{
+ struct cups_lang_str *next; /* Next language in cache */
+ int used; /* Number of times this entry has been used. */
+ cups_encoding_t encoding; /* Text encoding */
+ char language[16]; /* Language/locale name */
+ char *messages[CUPS_MSG_MAX];
+ /* Message array */
+} cups_lang_t;
+
+
+/*
+ * Prototypes...
+ */
+
+# define cupsLangDefault() cupsLangGet(NULL)
+extern char *cupsLangEncoding(cups_lang_t *lang);
+extern void cupsLangFlush(void);
+extern void cupsLangFree(cups_lang_t *lang);
+extern cups_lang_t *cupsLangGet(const char *language);
+# define cupsLangString(lang,msg) (lang)->messages[(msg)]
+
+/**** New in CUPS 1.1.20 ****/
+extern void _cupsRestoreLocale(int category, char *oldlocale);
+extern char *_cupsSaveLocale(int category, const char *locale);
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+
+#endif /* !_CUPS_LANGUAGE_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/mark.c b/cups/mark.c
new file mode 100644
index 000000000..6cb376343
--- /dev/null
+++ b/cups/mark.c
@@ -0,0 +1,443 @@
+/*
+ * "$Id$"
+ *
+ * Option marking routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ppdConflicts() - Check to see if there are any conflicts.
+ * ppdFindChoice() - Return a pointer to an option choice.
+ * ppdFindMarkedChoice() - Return the marked choice for the specified option.
+ * ppdFindOption() - Return a pointer to the specified option.
+ * ppdIsMarked() - Check to see if an option is marked...
+ * ppdMarkDefaults() - Mark all default options in the PPD file.
+ * ppdMarkOption() - Mark an option in a PPD file.
+ * ppd_defaults() - Set the defaults for this group and all sub-groups.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ppd.h"
+#include "string.h"
+#include "debug.h"
+
+
+/*
+ * Local functions...
+ */
+
+static void ppd_defaults(ppd_file_t *ppd, ppd_group_t *g);
+
+
+/*
+ * 'ppdConflicts()' - Check to see if there are any conflicts.
+ */
+
+int /* O - Number of conflicts found */
+ppdConflicts(ppd_file_t *ppd) /* I - PPD to check */
+{
+ int i, j, k, /* Looping variables */
+ conflicts; /* Number of conflicts */
+ ppd_const_t *c; /* Current constraint */
+ ppd_group_t *g, *sg; /* Groups */
+ ppd_option_t *o1, *o2; /* Options */
+ ppd_choice_t *c1, *c2; /* Choices */
+
+
+ if (ppd == NULL)
+ return (0);
+
+ /*
+ * Clear all conflicts...
+ */
+
+ conflicts = 0;
+
+ for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
+ {
+ for (j = g->num_options, o1 = g->options; j > 0; j --, o1 ++)
+ o1->conflicted = 0;
+
+ for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
+ for (k = sg->num_options, o1 = sg->options; k > 0; k --, o1 ++)
+ o1->conflicted = 0;
+ }
+
+ /*
+ * Loop through all of the UI constraints and flag any options
+ * that conflict...
+ */
+
+ for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
+ {
+ /*
+ * Grab pointers to the first option...
+ */
+
+ o1 = ppdFindOption(ppd, c->option1);
+
+ if (o1 == NULL)
+ continue;
+ else if (c->choice1[0] != '\0')
+ {
+ /*
+ * This constraint maps to a specific choice.
+ */
+
+ c1 = ppdFindChoice(o1, c->choice1);
+ }
+ else
+ {
+ /*
+ * This constraint applies to any choice for this option.
+ */
+
+ for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
+ if (c1->marked)
+ break;
+
+ if (j == 0 ||
+ strcasecmp(c1->choice, "None") == 0 ||
+ strcasecmp(c1->choice, "Off") == 0 ||
+ strcasecmp(c1->choice, "False") == 0)
+ c1 = NULL;
+ }
+
+ /*
+ * Grab pointers to the second option...
+ */
+
+ o2 = ppdFindOption(ppd, c->option2);
+
+ if (o2 == NULL)
+ continue;
+ else if (c->choice2[0] != '\0')
+ {
+ /*
+ * This constraint maps to a specific choice.
+ */
+
+ c2 = ppdFindChoice(o2, c->choice2);
+ }
+ else
+ {
+ /*
+ * This constraint applies to any choice for this option.
+ */
+
+ for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
+ if (c2->marked)
+ break;
+
+ if (j == 0 ||
+ strcasecmp(c2->choice, "None") == 0 ||
+ strcasecmp(c2->choice, "Off") == 0 ||
+ strcasecmp(c2->choice, "False") == 0)
+ c2 = NULL;
+ }
+
+ /*
+ * If both options are marked then there is a conflict...
+ */
+
+ if (c1 != NULL && c1->marked &&
+ c2 != NULL && c2->marked)
+ {
+ DEBUG_printf(("%s->%s conflicts with %s->%s (%s %s %s %s)\n",
+ o1->keyword, c1->choice, o2->keyword, c2->choice,
+ c->option1, c->choice1, c->option2, c->choice2));
+ conflicts ++;
+ o1->conflicted = 1;
+ o2->conflicted = 1;
+ }
+ }
+
+ /*
+ * Return the number of conflicts found...
+ */
+
+ return (conflicts);
+}
+
+
+/*
+ * 'ppdFindChoice()' - Return a pointer to an option choice.
+ */
+
+ppd_choice_t * /* O - Choice pointer or NULL */
+ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */
+ const char *choice) /* I - Name of choice */
+{
+ int i; /* Looping var */
+ ppd_choice_t *c; /* Current choice */
+
+
+ if (o == NULL || choice == NULL)
+ return (NULL);
+
+ for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
+ if (strcasecmp(c->choice, choice) == 0)
+ return (c);
+
+ return (NULL);
+}
+
+
+/*
+ * 'ppdFindMarkedChoice()' - Return the marked choice for the specified option.
+ */
+
+ppd_choice_t * /* O - Pointer to choice or NULL */
+ppdFindMarkedChoice(ppd_file_t *ppd, /* I - PPD file */
+ const char *option) /* I - Keyword/option name */
+{
+ int i; /* Looping var */
+ ppd_option_t *o; /* Pointer to option */
+ ppd_choice_t *c; /* Pointer to choice */
+
+
+ if ((o = ppdFindOption(ppd, option)) == NULL)
+ return (NULL);
+
+ for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
+ if (c->marked)
+ return (c);
+
+ return (NULL);
+}
+
+
+/*
+ * 'ppdFindOption()' - Return a pointer to the specified option.
+ */
+
+ppd_option_t * /* O - Pointer to option or NULL */
+ppdFindOption(ppd_file_t *ppd, /* I - PPD file data */
+ const char *option) /* I - Option/Keyword name */
+{
+ int i, j, k; /* Looping vars */
+ ppd_option_t *o; /* Pointer to option */
+ ppd_group_t *g, /* Pointer to group */
+ *sg; /* Pointer to subgroup */
+
+
+ if (ppd == NULL || option == NULL)
+ return (NULL);
+
+ for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
+ {
+ for (j = g->num_options, o = g->options; j > 0; j --, o ++)
+ if (strcasecmp(o->keyword, option) == 0)
+ return (o);
+
+ for (j = g->num_subgroups, sg = g->subgroups; j > 0; j --, sg ++)
+ for (k = sg->num_options, o = sg->options; k > 0; k --, o ++)
+ if (strcasecmp(o->keyword, option) == 0)
+ return (o);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'ppdIsMarked()' - Check to see if an option is marked...
+ */
+
+int /* O - Non-zero if option is marked */
+ppdIsMarked(ppd_file_t *ppd, /* I - PPD file data */
+ const char *option, /* I - Option/Keyword name */
+ const char *choice) /* I - Choice name */
+{
+ ppd_option_t *o; /* Option pointer */
+ ppd_choice_t *c; /* Choice pointer */
+
+
+ if (ppd == NULL)
+ return (0);
+
+ if ((o = ppdFindOption(ppd, option)) == NULL)
+ return (0);
+
+ if ((c = ppdFindChoice(o, choice)) == NULL)
+ return (0);
+
+ return (c->marked);
+}
+
+
+/*
+ * 'ppdMarkDefaults()' - Mark all default options in the PPD file.
+ */
+
+void
+ppdMarkDefaults(ppd_file_t *ppd)/* I - PPD file record */
+{
+ int i; /* Looping variables */
+ ppd_group_t *g; /* Current group */
+
+
+ if (ppd == NULL)
+ return;
+
+ for (i = ppd->num_groups, g = ppd->groups; i > 0; i --, g ++)
+ ppd_defaults(ppd, g);
+}
+
+
+/*
+ * 'ppdMarkOption()' - Mark an option in a PPD file.
+ *
+ * Notes:
+ *
+ * -1 is returned if the given option would conflict with any currently
+ * selected option.
+ */
+
+int /* O - Number of conflicts */
+ppdMarkOption(ppd_file_t *ppd, /* I - PPD file record */
+ const char *option, /* I - Keyword */
+ const char *choice) /* I - Option name */
+{
+ int i; /* Looping var */
+ ppd_option_t *o; /* Option pointer */
+ ppd_choice_t *c; /* Choice pointer */
+
+
+ if (ppd == NULL)
+ return (0);
+
+ if (strcasecmp(option, "PageSize") == 0 && strncasecmp(choice, "Custom.", 7) == 0)
+ {
+ /*
+ * Handle variable page sizes...
+ */
+
+ ppdPageSize(ppd, choice);
+ choice = "Custom";
+ }
+
+ if ((o = ppdFindOption(ppd, option)) == NULL)
+ return (0);
+
+ for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
+ if (strcasecmp(c->choice, choice) == 0)
+ break;
+
+ if (i)
+ {
+ /*
+ * Option found; mark it and then handle unmarking any other options.
+ */
+
+ c->marked = 1;
+
+ if (o->ui != PPD_UI_PICKMANY)
+ for (i = o->num_choices, c = o->choices; i > 0; i --, c ++)
+ if (strcasecmp(c->choice, choice) != 0)
+ c->marked = 0;
+
+ if (strcasecmp(option, "PageSize") == 0 || strcasecmp(option, "PageRegion") == 0)
+ {
+ /*
+ * Mark current page size...
+ */
+
+ for (i = 0; i < ppd->num_sizes; i ++)
+ ppd->sizes[i].marked = strcasecmp(ppd->sizes[i].name, choice) == 0;
+
+ /*
+ * Unmark the current PageSize or PageRegion setting, as appropriate...
+ */
+
+ if (strcasecmp(option, "PageSize") == 0)
+ {
+ if ((o = ppdFindOption(ppd, "PageRegion")) != NULL)
+ for (i = 0; i < o->num_choices; i ++)
+ o->choices[i].marked = 0;
+ }
+ else
+ {
+ if ((o = ppdFindOption(ppd, "PageSize")) != NULL)
+ for (i = 0; i < o->num_choices; i ++)
+ o->choices[i].marked = 0;
+ }
+ }
+ else if (strcasecmp(option, "InputSlot") == 0)
+ {
+ /*
+ * Unmark ManualFeed option...
+ */
+
+ if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL)
+ for (i = 0; i < o->num_choices; i ++)
+ o->choices[i].marked = 0;
+ }
+ else if (strcasecmp(option, "ManualFeed") == 0)
+ {
+ /*
+ * Unmark InputSlot option...
+ */
+
+ if ((o = ppdFindOption(ppd, "InputSlot")) != NULL)
+ for (i = 0; i < o->num_choices; i ++)
+ o->choices[i].marked = 0;
+ }
+ }
+
+ return (ppdConflicts(ppd));
+}
+
+
+/*
+ * 'ppd_defaults()' - Set the defaults for this group and all sub-groups.
+ */
+
+static void
+ppd_defaults(ppd_file_t *ppd, /* I - PPD file */
+ ppd_group_t *g) /* I - Group to default */
+{
+ int i; /* Looping var */
+ ppd_option_t *o; /* Current option */
+ ppd_group_t *sg; /* Current sub-group */
+
+
+ if (g == NULL)
+ return;
+
+ for (i = g->num_options, o = g->options; i > 0; i --, o ++)
+ if (strcasecmp(o->keyword, "PageRegion") != 0)
+ ppdMarkOption(ppd, o->keyword, o->defchoice);
+
+ for (i = g->num_subgroups, sg = g->subgroups; i > 0; i --, sg ++)
+ ppd_defaults(ppd, sg);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/md5.c b/cups/md5.c
new file mode 100644
index 000000000..5db868858
--- /dev/null
+++ b/cups/md5.c
@@ -0,0 +1,392 @@
+/*
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/*$Id$ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321.
+ It is derived directly from the text of the RFC and not from the
+ reference implementation.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include "string.h"
+
+#ifdef TEST
+/*
+ * Compile with -DTEST to create a self-contained executable test program.
+ * The test program should print out the same values as given in section
+ * A.5 of RFC 1321, reproduced below.
+ */
+main()
+{
+ static const char *const test[7] = {
+ "", /*d41d8cd98f00b204e9800998ecf8427e*/
+ "a", /*0cc175b9c0f1b6a831c399e269772661*/
+ "abc", /*900150983cd24fb0d6963f7d28e17f72*/
+ "message digest", /*f96b697d7cb7938d525a2f31aaf161d0*/
+ "abcdefghijklmnopqrstuvwxyz", /*c3fcd3d76192e4007dfb496cca67e13b*/
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ /*d174ab98d277d9f5a5611c2c9f419d9f*/
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" /*57edf4a22be3c955ac49da2e2107b67a*/
+ };
+ int i;
+
+ for (i = 0; i < 7; ++i) {
+ md5_state_t state;
+ md5_byte_t digest[16];
+ int di;
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i]));
+ md5_finish(&state, digest);
+ printf("MD5 (\"%s\") = ", test[i]);
+ for (di = 0; di < 16; ++di)
+ printf("%02x", digest[di]);
+ printf("\n");
+ }
+ return 0;
+}
+#endif /* TEST */
+
+
+/*
+ * For reference, here is the program that computed the T values.
+ */
+#if 0
+#include <math.h>
+main()
+{
+ int i;
+ for (i = 1; i <= 64; ++i) {
+ unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i)));
+ printf("#define T%d 0x%08lx\n", i, v);
+ }
+ return 0;
+}
+#endif
+/*
+ * End of T computation program.
+ */
+#define T1 0xd76aa478
+#define T2 0xe8c7b756
+#define T3 0x242070db
+#define T4 0xc1bdceee
+#define T5 0xf57c0faf
+#define T6 0x4787c62a
+#define T7 0xa8304613
+#define T8 0xfd469501
+#define T9 0x698098d8
+#define T10 0x8b44f7af
+#define T11 0xffff5bb1
+#define T12 0x895cd7be
+#define T13 0x6b901122
+#define T14 0xfd987193
+#define T15 0xa679438e
+#define T16 0x49b40821
+#define T17 0xf61e2562
+#define T18 0xc040b340
+#define T19 0x265e5a51
+#define T20 0xe9b6c7aa
+#define T21 0xd62f105d
+#define T22 0x02441453
+#define T23 0xd8a1e681
+#define T24 0xe7d3fbc8
+#define T25 0x21e1cde6
+#define T26 0xc33707d6
+#define T27 0xf4d50d87
+#define T28 0x455a14ed
+#define T29 0xa9e3e905
+#define T30 0xfcefa3f8
+#define T31 0x676f02d9
+#define T32 0x8d2a4c8a
+#define T33 0xfffa3942
+#define T34 0x8771f681
+#define T35 0x6d9d6122
+#define T36 0xfde5380c
+#define T37 0xa4beea44
+#define T38 0x4bdecfa9
+#define T39 0xf6bb4b60
+#define T40 0xbebfbc70
+#define T41 0x289b7ec6
+#define T42 0xeaa127fa
+#define T43 0xd4ef3085
+#define T44 0x04881d05
+#define T45 0xd9d4d039
+#define T46 0xe6db99e5
+#define T47 0x1fa27cf8
+#define T48 0xc4ac5665
+#define T49 0xf4292244
+#define T50 0x432aff97
+#define T51 0xab9423a7
+#define T52 0xfc93a039
+#define T53 0x655b59c3
+#define T54 0x8f0ccc92
+#define T55 0xffeff47d
+#define T56 0x85845dd1
+#define T57 0x6fa87e4f
+#define T58 0xfe2ce6e0
+#define T59 0xa3014314
+#define T60 0x4e0811a1
+#define T61 0xf7537e82
+#define T62 0xbd3af235
+#define T63 0x2ad7d2bb
+#define T64 0xeb86d391
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+
+#ifndef ARCH_IS_BIG_ENDIAN
+# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */
+#endif
+#if ARCH_IS_BIG_ENDIAN
+
+ /*
+ * On big-endian machines, we must arrange the bytes in the right
+ * order. (This also works on machines of unknown byte order.)
+ */
+ md5_word_t X[16];
+ const md5_byte_t *xp = data;
+ int i;
+
+ for (i = 0; i < 16; ++i, xp += 4)
+ X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+
+#else /* !ARCH_IS_BIG_ENDIAN */
+
+ /*
+ * On little-endian machines, we can process properly aligned data
+ * without copying it.
+ */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+#endif
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = 0xefcdab89;
+ pms->abcd[2] = 0x98badcfe;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/cups/md5.h b/cups/md5.h
new file mode 100644
index 000000000..a2d7b3415
--- /dev/null
+++ b/cups/md5.h
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/*$Id$ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321.
+ It is derived directly from the text of the RFC and not from the
+ reference implementation.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This code has some adaptations for the Ghostscript environment, but it
+ * will compile and run correctly in any environment with 8-bit chars and
+ * 32-bit ints. Specifically, it assumes that if the following are
+ * defined, they have the same meaning as in Ghostscript: P1, P2, P3,
+ * ARCH_IS_BIG_ENDIAN.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Initialize the algorithm. */
+#ifdef P1
+void md5_init(P1(md5_state_t *pms));
+#else
+void md5_init(md5_state_t *pms);
+#endif
+
+/* Append a string to the message. */
+#ifdef P3
+void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));
+#else
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+#endif
+
+/* Finish the message and return the digest. */
+#ifdef P2
+void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));
+#else
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+#endif
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/cups/md5passwd.c b/cups/md5passwd.c
new file mode 100644
index 000000000..c88a8ec43
--- /dev/null
+++ b/cups/md5passwd.c
@@ -0,0 +1,150 @@
+/*
+ * "$Id$"
+ *
+ * MD5 password support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * httpMD5() - Compute the MD5 sum of the username:group:password.
+ * httpMD5Nonce() - Combine the MD5 sum of the username, group, and password
+ * with the server-supplied nonce value.
+ * httpMD5String() - Convert an MD5 sum to a character string.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "http.h"
+#include "string.h"
+
+
+/*
+ * 'httpMD5()' - Compute the MD5 sum of the username:group:password.
+ */
+
+char * /* O - MD5 sum */
+httpMD5(const char *username, /* I - User name */
+ const char *realm, /* I - Realm name */
+ const char *passwd, /* I - Password string */
+ char md5[33]) /* O - MD5 string */
+{
+ md5_state_t state; /* MD5 state info */
+ md5_byte_t sum[16]; /* Sum data */
+ char line[256]; /* Line to sum */
+
+
+ /*
+ * Compute the MD5 sum of the user name, group name, and password.
+ */
+
+ snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd);
+ md5_init(&state);
+ md5_append(&state, (md5_byte_t *)line, strlen(line));
+ md5_finish(&state, sum);
+
+ /*
+ * Return the sum...
+ */
+
+ return (httpMD5String(sum, md5));
+}
+
+
+/*
+ * 'httpMD5Final()' - Combine the MD5 sum of the username, group, and password
+ * with the server-supplied nonce value, method, and
+ * request-uri.
+ */
+
+char * /* O - New sum */
+httpMD5Final(const char *nonce, /* I - Server nonce value */
+ const char *method, /* I - METHOD (GET, POST, etc.) */
+ const char *resource, /* I - Resource path */
+ char md5[33]) /* IO - MD5 sum */
+{
+ md5_state_t state; /* MD5 state info */
+ md5_byte_t sum[16]; /* Sum data */
+ char line[1024]; /* Line of data */
+ char a2[33]; /* Hash of method and resource */
+
+
+ /*
+ * First compute the MD5 sum of the method and resource...
+ */
+
+ snprintf(line, sizeof(line), "%s:%s", method, resource);
+ md5_init(&state);
+ md5_append(&state, (md5_byte_t *)line, strlen(line));
+ md5_finish(&state, sum);
+ httpMD5String(sum, a2);
+
+ /*
+ * Then combine A1 (MD5 of username, realm, and password) with the nonce
+ * and A2 (method + resource) values to get the final MD5 sum for the
+ * request...
+ */
+
+ snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2);
+
+ md5_init(&state);
+ md5_append(&state, (md5_byte_t *)line, strlen(line));
+ md5_finish(&state, sum);
+
+ return (httpMD5String(sum, md5));
+}
+
+
+/*
+ * 'httpMD5String()' - Convert an MD5 sum to a character string.
+ */
+
+char * /* O - MD5 sum in hex */
+httpMD5String(const md5_byte_t *sum, /* I - MD5 sum data */
+ char md5[33]) /* O - MD5 sum in hex */
+{
+ int i; /* Looping var */
+ char *md5ptr; /* Pointer into MD5 string */
+ static const char hex[] = "0123456789abcdef";
+ /* Hex digits */
+
+
+ /*
+ * Convert the MD5 sum to hexadecimal...
+ */
+
+ for (i = 16, md5ptr = md5; i > 0; i --, sum ++)
+ {
+ *md5ptr++ = hex[*sum >> 4];
+ *md5ptr++ = hex[*sum & 15];
+ }
+
+ *md5ptr = '\0';
+
+ return (md5);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/options.c b/cups/options.c
new file mode 100644
index 000000000..0c9017c0e
--- /dev/null
+++ b/cups/options.c
@@ -0,0 +1,499 @@
+/*
+ * "$Id$"
+ *
+ * Option routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsAddOption() - Add an option to an option array.
+ * cupsFreeOptions() - Free all memory used by options.
+ * cupsGetOption() - Get an option value.
+ * cupsParseOptions() - Parse options from a command-line argument.
+ * cupsMarkOptions() - Mark command-line options in a PPD file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include "string.h"
+#include "debug.h"
+
+
+/*
+ * 'cupsAddOption()' - Add an option to an option array.
+ */
+
+int /* O - Number of options */
+cupsAddOption(const char *name, /* I - Name of option */
+ const char *value, /* I - Value of option */
+ int num_options, /* I - Number of options */
+ cups_option_t **options) /* IO - Pointer to options */
+{
+ int i; /* Looping var */
+ cups_option_t *temp; /* Pointer to new option */
+
+
+ if (name == NULL || !name[0] || value == NULL ||
+ options == NULL || num_options < 0)
+ return (num_options);
+
+ /*
+ * Look for an existing option with the same name...
+ */
+
+ for (i = 0, temp = *options; i < num_options; i ++, temp ++)
+ if (strcasecmp(temp->name, name) == 0)
+ break;
+
+ if (i >= num_options)
+ {
+ /*
+ * No matching option name...
+ */
+
+ if (num_options == 0)
+ temp = (cups_option_t *)malloc(sizeof(cups_option_t));
+ else
+ temp = (cups_option_t *)realloc(*options, sizeof(cups_option_t) *
+ (num_options + 1));
+
+ if (temp == NULL)
+ return (0);
+
+ *options = temp;
+ temp += num_options;
+ temp->name = strdup(name);
+ num_options ++;
+ }
+ else
+ {
+ /*
+ * Match found; free the old value...
+ */
+
+ free(temp->value);
+ }
+
+ temp->value = strdup(value);
+
+ return (num_options);
+}
+
+
+/*
+ * 'cupsFreeOptions()' - Free all memory used by options.
+ */
+
+void
+cupsFreeOptions(int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Pointer to options */
+{
+ int i; /* Looping var */
+
+
+ if (num_options <= 0 || options == NULL)
+ return;
+
+ for (i = 0; i < num_options; i ++)
+ {
+ free(options[i].name);
+ free(options[i].value);
+ }
+
+ free(options);
+}
+
+
+/*
+ * 'cupsGetOption()' - Get an option value.
+ */
+
+const char * /* O - Option value or NULL */
+cupsGetOption(const char *name, /* I - Name of option */
+ int num_options,/* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ int i; /* Looping var */
+
+
+ if (name == NULL || num_options <= 0 || options == NULL)
+ return (NULL);
+
+ for (i = 0; i < num_options; i ++)
+ if (strcasecmp(options[i].name, name) == 0)
+ return (options[i].value);
+
+ return (NULL);
+}
+
+
+/*
+ * 'cupsParseOptions()' - Parse options from a command-line argument.
+ */
+
+int /* O - Number of options found */
+cupsParseOptions(const char *arg, /* I - Argument to parse */
+ int num_options, /* I - Number of options */
+ cups_option_t **options) /* O - Options found */
+{
+ char *copyarg, /* Copy of input string */
+ *ptr, /* Pointer into string */
+ *name, /* Pointer to name */
+ *value; /* Pointer to value */
+
+
+ if (arg == NULL || options == NULL || num_options < 0)
+ return (0);
+
+ /*
+ * Make a copy of the argument string and then divide it up...
+ */
+
+ copyarg = strdup(arg);
+ ptr = copyarg;
+
+ /*
+ * Skip leading spaces...
+ */
+
+ while (isspace(*ptr & 255))
+ ptr ++;
+
+ /*
+ * Loop through the string...
+ */
+
+ while (*ptr != '\0')
+ {
+ /*
+ * Get the name up to a SPACE, =, or end-of-string...
+ */
+
+ name = ptr;
+ while (!isspace(*ptr & 255) && *ptr != '=' && *ptr != '\0')
+ ptr ++;
+
+ /*
+ * Avoid an empty name...
+ */
+
+ if (ptr == name)
+ break;
+
+ /*
+ * Skip trailing spaces...
+ */
+
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
+
+ if (*ptr != '=')
+ {
+ /*
+ * Start of another option...
+ */
+
+ if (strncasecmp(name, "no", 2) == 0)
+ num_options = cupsAddOption(name + 2, "false", num_options,
+ options);
+ else
+ num_options = cupsAddOption(name, "true", num_options, options);
+
+ continue;
+ }
+
+ /*
+ * Remove = and parse the value...
+ */
+
+ *ptr++ = '\0';
+
+ if (*ptr == '\'')
+ {
+ /*
+ * Quoted string constant...
+ */
+
+ ptr ++;
+ value = ptr;
+
+ while (*ptr != '\'' && *ptr != '\0')
+ {
+ if (*ptr == '\\')
+ cups_strcpy(ptr, ptr + 1);
+
+ ptr ++;
+ }
+
+ if (*ptr != '\0')
+ *ptr++ = '\0';
+ }
+ else if (*ptr == '\"')
+ {
+ /*
+ * Double-quoted string constant...
+ */
+
+ ptr ++;
+ value = ptr;
+
+ while (*ptr != '\"' && *ptr != '\0')
+ {
+ if (*ptr == '\\')
+ cups_strcpy(ptr, ptr + 1);
+
+ ptr ++;
+ }
+
+ if (*ptr != '\0')
+ *ptr++ = '\0';
+ }
+ else if (*ptr == '{')
+ {
+ /*
+ * Collection value...
+ */
+
+ int depth;
+
+ value = ptr;
+
+ for (depth = 1; *ptr; ptr ++)
+ if (*ptr == '{')
+ depth ++;
+ else if (*ptr == '}')
+ {
+ depth --;
+ if (!depth)
+ {
+ ptr ++;
+
+ if (*ptr != ',')
+ break;
+ }
+ }
+ else if (*ptr == '\\')
+ cups_strcpy(ptr, ptr + 1);
+
+ if (*ptr != '\0')
+ *ptr++ = '\0';
+ }
+ else
+ {
+ /*
+ * Normal space-delimited string...
+ */
+
+ value = ptr;
+
+ while (!isspace(*ptr & 255) && *ptr != '\0')
+ {
+ if (*ptr == '\\')
+ cups_strcpy(ptr, ptr + 1);
+
+ ptr ++;
+ }
+ }
+
+ /*
+ * Skip trailing whitespace...
+ */
+
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
+
+ /*
+ * Add the string value...
+ */
+
+ num_options = cupsAddOption(name, value, num_options, options);
+ }
+
+ /*
+ * Free the copy of the argument we made and return the number of options
+ * found.
+ */
+
+ free(copyarg);
+
+ return (num_options);
+}
+
+
+/*
+ * 'cupsMarkOptions()' - Mark command-line options in a PPD file.
+ */
+
+int /* O - 1 if conflicting */
+cupsMarkOptions(ppd_file_t *ppd, /* I - PPD file */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ int i; /* Looping var */
+ int conflict; /* Option conflicts */
+ char *val, /* Pointer into value */
+ *ptr, /* Pointer into string */
+ s[255]; /* Temporary string */
+ cups_option_t *optptr; /* Current option */
+
+
+ /*
+ * Check arguments...
+ */
+
+ if (ppd == NULL || num_options <= 0 || options == NULL)
+ return (0);
+
+ /*
+ * Mark options...
+ */
+
+ conflict = 0;
+
+ for (i = num_options, optptr = options; i > 0; i --, optptr ++)
+ if (strcasecmp(optptr->name, "media") == 0)
+ {
+ /*
+ * Loop through the option string, separating it at commas and
+ * marking each individual option.
+ */
+
+ for (val = optptr->value; *val;)
+ {
+ /*
+ * Extract the sub-option from the string...
+ */
+
+ for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);)
+ *ptr++ = *val++;
+ *ptr++ = '\0';
+
+ if (*val == ',')
+ val ++;
+
+ /*
+ * Mark it...
+ */
+
+ if (cupsGetOption("PageSize", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "PageSize", s))
+ conflict = 1;
+
+ if (cupsGetOption("InputSlot", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "InputSlot", s))
+ conflict = 1;
+
+ if (cupsGetOption("MediaType", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "MediaType", s))
+ conflict = 1;
+
+ if (cupsGetOption("EFMediaQualityMode", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "EFMediaQualityMode", s)) /* EFI */
+ conflict = 1;
+
+ if (strcasecmp(s, "manual") == 0 &&
+ cupsGetOption("ManualFeed", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "ManualFeed", "True"))
+ conflict = 1;
+ }
+ }
+ else if (strcasecmp(optptr->name, "sides") == 0)
+ {
+ if (cupsGetOption("Duplex", num_options, options) != NULL ||
+ cupsGetOption("JCLDuplex", num_options, options) != NULL ||
+ cupsGetOption("EFDuplex", num_options, options) != NULL ||
+ cupsGetOption("KD03Duplex", num_options, options) != NULL)
+ {
+ /*
+ * Don't override the PPD option with the IPP attribute...
+ */
+
+ continue;
+ }
+ else if (strcasecmp(optptr->value, "one-sided") == 0)
+ {
+ if (ppdMarkOption(ppd, "Duplex", "None"))
+ conflict = 1;
+ if (ppdMarkOption(ppd, "JCLDuplex", "None")) /* Samsung */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "EFDuplex", "None")) /* EFI */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "KD03Duplex", "None")) /* Kodak */
+ conflict = 1;
+ }
+ else if (strcasecmp(optptr->value, "two-sided-long-edge") == 0)
+ {
+ if (ppdMarkOption(ppd, "Duplex", "DuplexNoTumble"))
+ conflict = 1;
+ if (ppdMarkOption(ppd, "JCLDuplex", "DuplexNoTumble")) /* Samsung */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "EFDuplex", "DuplexNoTumble")) /* EFI */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "KD03Duplex", "DuplexNoTumble")) /* Kodak */
+ conflict = 1;
+ }
+ else if (strcasecmp(optptr->value, "two-sided-short-edge") == 0)
+ {
+ if (ppdMarkOption(ppd, "Duplex", "DuplexTumble"))
+ conflict = 1;
+ if (ppdMarkOption(ppd, "JCLDuplex", "DuplexTumble")) /* Samsung */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "EFDuplex", "DuplexTumble")) /* EFI */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "KD03Duplex", "DuplexTumble")) /* Kodak */
+ conflict = 1;
+ }
+ }
+ else if (strcasecmp(optptr->name, "resolution") == 0 ||
+ strcasecmp(optptr->name, "printer-resolution") == 0)
+ {
+ if (ppdMarkOption(ppd, "Resolution", optptr->value))
+ conflict = 1;
+ if (ppdMarkOption(ppd, "SetResolution", optptr->value))
+ /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "JCLResolution", optptr->value)) /* HP */
+ conflict = 1;
+ if (ppdMarkOption(ppd, "CNRes_PGP", optptr->value)) /* Canon */
+ conflict = 1;
+ }
+ else if (strcasecmp(optptr->name, "output-bin") == 0)
+ {
+ if (cupsGetOption("OutputBin", num_options, options) == NULL)
+ if (ppdMarkOption(ppd, "OutputBin", optptr->value))
+ conflict = 1;
+ }
+ else if (ppdMarkOption(ppd, optptr->name, optptr->value))
+ conflict = 1;
+
+ return (conflict);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/page.c b/cups/page.c
new file mode 100644
index 000000000..e0a2ba2f7
--- /dev/null
+++ b/cups/page.c
@@ -0,0 +1,191 @@
+/*
+ * "$Id$"
+ *
+ * Page size functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ppdPageSize() - Get the page size record for the given size.
+ * ppdPageWidth() - Get the page width for the given size.
+ * ppdPageLength() - Get the page length for the given size.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "ppd.h"
+#include "string.h"
+#include <ctype.h>
+
+
+/*
+ * 'ppdPageSize()' - Get the page size record for the given size.
+ */
+
+ppd_size_t * /* O - Size record for page or NULL */
+ppdPageSize(ppd_file_t *ppd, /* I - PPD file record */
+ const char *name) /* I - Size name */
+{
+ int i; /* Looping var */
+ float w, l; /* Width and length of page */
+ char units[255]; /* Page size units... */
+
+
+ if (ppd == NULL)
+ return (NULL);
+
+ if (name != NULL)
+ {
+ if (strncmp(name, "Custom.", 7) == 0 && ppd->variable_sizes)
+ {
+ /*
+ * Find the custom page size...
+ */
+
+ for (i = 0; i < ppd->num_sizes; i ++)
+ if (strcmp("Custom", ppd->sizes[i].name) == 0)
+ break;
+
+ if (i == ppd->num_sizes)
+ return (NULL);
+
+ /*
+ * Variable size; size name can be one of the following:
+ *
+ * Custom.WIDTHxLENGTHin - Size in inches
+ * Custom.WIDTHxLENGTHcm - Size in centimeters
+ * Custom.WIDTHxLENGTHmm - Size in millimeters
+ * Custom.WIDTHxLENGTH[pt] - Size in points
+ */
+
+ units[0] = '\0';
+ if (sscanf(name + 7, "%fx%f%254s", &w, &l, units) < 2)
+ return (NULL);
+
+ if (strcasecmp(units, "in") == 0)
+ {
+ ppd->sizes[i].width = w * 72.0f;
+ ppd->sizes[i].length = l * 72.0f;
+ ppd->sizes[i].left = ppd->custom_margins[0];
+ ppd->sizes[i].bottom = ppd->custom_margins[1];
+ ppd->sizes[i].right = w * 72.0f - ppd->custom_margins[2];
+ ppd->sizes[i].top = l * 72.0f - ppd->custom_margins[3];
+ }
+ else if (strcasecmp(units, "cm") == 0)
+ {
+ ppd->sizes[i].width = w / 2.54f * 72.0f;
+ ppd->sizes[i].length = l / 2.54f * 72.0f;
+ ppd->sizes[i].left = ppd->custom_margins[0];
+ ppd->sizes[i].bottom = ppd->custom_margins[1];
+ ppd->sizes[i].right = w / 2.54f * 72.0f - ppd->custom_margins[2];
+ ppd->sizes[i].top = l / 2.54f * 72.0f - ppd->custom_margins[3];
+ }
+ else if (strcasecmp(units, "mm") == 0)
+ {
+ ppd->sizes[i].width = w / 25.4f * 72.0f;
+ ppd->sizes[i].length = l / 25.4f * 72.0f;
+ ppd->sizes[i].left = ppd->custom_margins[0];
+ ppd->sizes[i].bottom = ppd->custom_margins[1];
+ ppd->sizes[i].right = w / 25.4f * 72.0f - ppd->custom_margins[2];
+ ppd->sizes[i].top = l / 25.4f * 72.0f - ppd->custom_margins[3];
+ }
+ else
+ {
+ ppd->sizes[i].width = w;
+ ppd->sizes[i].length = l;
+ ppd->sizes[i].left = ppd->custom_margins[0];
+ ppd->sizes[i].bottom = ppd->custom_margins[1];
+ ppd->sizes[i].right = w - ppd->custom_margins[2];
+ ppd->sizes[i].top = l - ppd->custom_margins[3];
+ }
+
+ return (ppd->sizes + i);
+ }
+ else
+ {
+ /*
+ * Lookup by name...
+ */
+
+ for (i = 0; i < ppd->num_sizes; i ++)
+ if (strcmp(name, ppd->sizes[i].name) == 0)
+ return (ppd->sizes + i);
+ }
+ }
+ else
+ {
+ /*
+ * Find default...
+ */
+
+ for (i = 0; i < ppd->num_sizes; i ++)
+ if (ppd->sizes[i].marked)
+ return (ppd->sizes + i);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'ppdPageWidth()' - Get the page width for the given size.
+ */
+
+float /* O - Width of page in points or 0.0 */
+ppdPageWidth(ppd_file_t *ppd, /* I - PPD file record */
+ const char *name) /* I - Size name */
+{
+ ppd_size_t *size; /* Page size */
+
+
+ if ((size = ppdPageSize(ppd, name)) == NULL)
+ return (0.0);
+ else
+ return (size->width);
+}
+
+
+/*
+ * 'ppdPageLength()' - Get the page length for the given size.
+ */
+
+float /* O - Length of page in points or 0.0 */
+ppdPageLength(ppd_file_t *ppd, /* I - PPD file */
+ const char *name) /* I - Size name */
+{
+ ppd_size_t *size; /* Page size */
+
+
+ if ((size = ppdPageSize(ppd, name)) == NULL)
+ return (0.0);
+ else
+ return (size->length);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ppd.c b/cups/ppd.c
new file mode 100644
index 000000000..ae89c4c6c
--- /dev/null
+++ b/cups/ppd.c
@@ -0,0 +1,2659 @@
+/*
+ * "$Id$"
+ *
+ * PPD file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This code and any derivative of it may be used and distributed
+ * freely under the terms of the GNU General Public License when
+ * used with GNU Ghostscript or its derivatives. Use of the code
+ * (or any derivative of it) with software other than GNU
+ * GhostScript (or its derivatives) is governed by the CUPS license
+ * agreement.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * _ppd_attr_compare() - Compare two attributes.
+ * ppdClose() - Free all memory used by the PPD file.
+ * ppdErrorString() - Returns the text assocated with a status.
+ * ppdLastError() - Return the status from the last ppdOpen*().
+ * ppdOpen() - Read a PPD file into memory.
+ * ppdOpenFd() - Read a PPD file into memory.
+ * ppdOpenFile() - Read a PPD file into memory.
+ * ppdSetConformance() - Set the conformance level for PPD files.
+ * ppd_add_attr() - Add an attribute to the PPD data.
+ * ppd_add_choice() - Add a choice to an option.
+ * ppd_add_size() - Add a page size.
+ * ppd_compare_groups() - Compare two groups.
+ * ppd_compare_options() - Compare two options.
+ * ppd_decode() - Decode a string value...
+ * ppd_fix() - Fix WinANSI characters in the range 0x80 to
+ * 0x9f to be valid ISO-8859-1 characters...
+ * ppd_free_group() - Free a single UI group.
+ * ppd_free_option() - Free a single option.
+ * ppd_get_group() - Find or create the named group as needed.
+ * ppd_get_option() - Find or create the named option as needed.
+ * ppd_read() - Read a line from a PPD file, skipping comment
+ * lines as necessary.
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include "ppd.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include "string.h"
+#include "language.h"
+#include "debug.h"
+
+
+/*
+ * Definitions...
+ */
+
+#if defined(WIN32) || defined(__EMX__)
+# define READ_BINARY "rb" /* Open a binary file for reading */
+# define WRITE_BINARY "wb" /* Open a binary file for writing */
+#else
+# define READ_BINARY "r" /* Open a binary file for reading */
+# define WRITE_BINARY "w" /* Open a binary file for writing */
+#endif /* WIN32 || __EMX__ */
+
+#define ppd_free(p) if (p) free(p) /* Safe free macro */
+
+#define PPD_KEYWORD 1 /* Line contained a keyword */
+#define PPD_OPTION 2 /* Line contained an option name */
+#define PPD_TEXT 4 /* Line contained human-readable text */
+#define PPD_STRING 8 /* Line contained a string or code */
+
+
+/*
+ * Local globals...
+ */
+
+static ppd_status_t ppd_status = PPD_OK;
+ /* Status of last ppdOpen*() */
+static int ppd_line = 0; /* Current line number */
+static ppd_conform_t ppd_conform = PPD_CONFORM_RELAXED;
+ /* Level of conformance required */
+
+
+/*
+ * Local functions...
+ */
+
+static ppd_attr_t *ppd_add_attr(ppd_file_t *ppd, const char *name,
+ const char *spec, const char *text,
+ const char *value);
+static ppd_choice_t *ppd_add_choice(ppd_option_t *option, const char *name);
+static ppd_size_t *ppd_add_size(ppd_file_t *ppd, const char *name);
+#ifndef __APPLE__
+static int ppd_compare_groups(ppd_group_t *g0, ppd_group_t *g1);
+static int ppd_compare_options(ppd_option_t *o0, ppd_option_t *o1);
+#endif /* !__APPLE__ */
+static int ppd_decode(char *string);
+#ifndef __APPLE__
+static void ppd_fix(char *string);
+#else
+# define ppd_fix(s)
+#endif /* !__APPLE__ */
+static void ppd_free_group(ppd_group_t *group);
+static void ppd_free_option(ppd_option_t *option);
+static ppd_group_t *ppd_get_group(ppd_file_t *ppd, const char *name,
+ const char *text);
+static ppd_option_t *ppd_get_option(ppd_group_t *group, const char *name);
+static int ppd_read(FILE *fp, char *keyword, char *option,
+ char *text, char **string, int ignoreblank);
+
+
+/*
+ * '_ppd_attr_compare()' - Compare two attributes.
+ */
+
+int /* O - Result of comparison */
+_ppd_attr_compare(ppd_attr_t **a, /* I - First attribute */
+ ppd_attr_t **b) /* I - Second attribute */
+{
+ int ret; /* Result of comparison */
+
+
+ if ((ret = strcasecmp((*a)->name, (*b)->name)) != 0)
+ return (ret);
+ else if ((*a)->spec[0] && (*b)->spec[0])
+ return (strcasecmp((*a)->spec, (*b)->spec));
+ else
+ return (0);
+}
+
+
+/*
+ * 'ppdClose()' - Free all memory used by the PPD file.
+ */
+
+void
+ppdClose(ppd_file_t *ppd) /* I - PPD file record */
+{
+ int i; /* Looping var */
+ ppd_emul_t *emul; /* Current emulation */
+ ppd_group_t *group; /* Current group */
+ char **font; /* Current font */
+ char **filter; /* Current filter */
+ ppd_attr_t **attr; /* Current attribute */
+
+
+ /*
+ * Range check the PPD file record...
+ */
+
+ if (ppd == NULL)
+ return;
+
+ /*
+ * Free all strings at the top level...
+ */
+
+ ppd_free(ppd->patches);
+ ppd_free(ppd->jcl_begin);
+ ppd_free(ppd->jcl_end);
+ ppd_free(ppd->jcl_ps);
+
+ /*
+ * Free any emulations...
+ */
+
+ if (ppd->num_emulations > 0)
+ {
+ for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++)
+ {
+ ppd_free(emul->start);
+ ppd_free(emul->stop);
+ }
+
+ ppd_free(ppd->emulations);
+ }
+
+ /*
+ * Free any UI groups, subgroups, and options...
+ */
+
+ if (ppd->num_groups > 0)
+ {
+ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+ ppd_free_group(group);
+
+ ppd_free(ppd->groups);
+ }
+
+ /*
+ * Free any page sizes...
+ */
+
+ if (ppd->num_sizes > 0)
+ {
+ ppd_free(ppd->sizes);
+ }
+
+ /*
+ * Free any constraints...
+ */
+
+ if (ppd->num_consts > 0)
+ {
+ ppd_free(ppd->consts);
+ }
+
+ /*
+ * Free any filters...
+ */
+
+ if (ppd->num_filters > 0)
+ {
+ for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++)
+ {
+ ppd_free(*filter);
+ }
+
+ ppd_free(ppd->filters);
+ }
+
+ /*
+ * Free any fonts...
+ */
+
+ if (ppd->num_fonts > 0)
+ {
+ for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++)
+ {
+ ppd_free(*font);
+ }
+
+ ppd_free(ppd->fonts);
+ }
+
+ /*
+ * Free any profiles...
+ */
+
+ if (ppd->num_profiles > 0)
+ {
+ ppd_free(ppd->profiles);
+ }
+
+ /*
+ * Free any attributes...
+ */
+
+ if (ppd->num_attrs > 0)
+ {
+ for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++)
+ {
+ ppd_free((*attr)->value);
+ ppd_free(*attr);
+ }
+
+ ppd_free(ppd->attrs);
+ }
+
+ /*
+ * Free the whole record...
+ */
+
+ ppd_free(ppd);
+}
+
+
+/*
+ * 'ppdErrorString()' - Returns the text assocated with a status.
+ */
+
+const char * /* O - Status string */
+ppdErrorString(ppd_status_t status) /* I - PPD status */
+{
+ static const char * const messages[] =/* Status messages */
+ {
+ "OK",
+ "Unable to open PPD file",
+ "NULL PPD file pointer",
+ "Memory allocation error",
+ "Missing PPD-Adobe-4.x header",
+ "Missing value string",
+ "Internal error",
+ "Bad OpenGroup",
+ "OpenGroup without a CloseGroup first",
+ "Bad OpenUI/JCLOpenUI",
+ "OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first",
+ "Bad OrderDependency",
+ "Bad UIConstraints",
+ "Missing asterisk in column 1",
+ "Line longer than the maximum allowed (255 characters)",
+ "Illegal control character",
+ "Illegal main keyword string",
+ "Illegal option keyword string",
+ "Illegal translation string",
+ "Illegal whitespace character"
+ };
+
+
+ if (status < PPD_OK || status > PPD_ILLEGAL_WHITESPACE)
+ return ("Unknown");
+ else
+ return (messages[status]);
+}
+
+
+/*
+ * 'ppdLastError()' - Return the status from the last ppdOpen*().
+ */
+
+ppd_status_t /* O - Status code */
+ppdLastError(int *line) /* O - Line number */
+{
+ if (line)
+ *line = ppd_line;
+
+ return (ppd_status);
+}
+
+
+/*
+ * 'ppdOpen()' - Read a PPD file into memory.
+ */
+
+ppd_file_t * /* O - PPD file record */
+ppdOpen(FILE *fp) /* I - File to read from */
+{
+ char *oldlocale; /* Old locale settings */
+ int i, j, k, m; /* Looping vars */
+ int count; /* Temporary count */
+ ppd_file_t *ppd; /* PPD file record */
+ ppd_group_t *group, /* Current group */
+ *subgroup; /* Current sub-group */
+ ppd_option_t *option; /* Current option */
+ ppd_choice_t *choice; /* Current choice */
+ ppd_const_t *constraint; /* Current constraint */
+ ppd_size_t *size; /* Current page size */
+ int mask; /* Line data mask */
+ char keyword[PPD_MAX_NAME],
+ /* Keyword from file */
+ name[PPD_MAX_NAME],
+ /* Option from file */
+ text[PPD_MAX_LINE],
+ /* Human-readable text from file */
+ *string, /* Code/text from file */
+ *sptr, /* Pointer into string */
+ *nameptr, /* Pointer into name */
+ *temp, /* Temporary string pointer */
+ **tempfonts; /* Temporary fonts pointer */
+ float order; /* Order dependency number */
+ ppd_section_t section; /* Order dependency section */
+ ppd_profile_t *profile; /* Pointer to color profile */
+ char **filter; /* Pointer to filter */
+ cups_lang_t *language; /* Default language */
+ int ui_keyword; /* Is this line a UI keyword? */
+ static const char * const ui_keywords[] =
+ {
+ /* Boolean keywords */
+ "BlackSubstitution",
+ "Booklet",
+ "Collate",
+ "ManualFeed",
+ "MirrorPrint",
+ "NegativePrint",
+ "Sorter",
+ "TraySwitch",
+
+ /* PickOne keywords */
+ "AdvanceMedia",
+ "BindColor",
+ "BindEdge",
+ "BindType",
+ "BindWhen",
+ "BitsPerPixel",
+ "ColorModel",
+ "CutMedia",
+ "Duplex",
+ "FoldType",
+ "FoldWhen",
+ "InputSlot",
+ "JCLFrameBufferSize",
+ "JCLResolution",
+ "Jog",
+ "MediaColor",
+ "MediaType",
+ "MediaWeight",
+ "OutputBin",
+ "OutputMode",
+ "OutputOrder",
+ "PageRegion",
+ "PageSize",
+ "Resolution",
+ "Separations",
+ "Signature",
+ "Slipsheet",
+ "Smoothing",
+ "StapleLocation",
+ "StapleOrientation",
+ "StapleWhen",
+ "StapleX",
+ "StapleY"
+ };
+
+
+ /*
+ * Default to "OK" status...
+ */
+
+ ppd_status = PPD_OK;
+ ppd_line = 0;
+
+ /*
+ * Range check input...
+ */
+
+ if (fp == NULL)
+ {
+ ppd_status = PPD_NULL_FILE;
+ return (NULL);
+ }
+
+ /*
+ * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'...
+ */
+
+ mask = ppd_read(fp, keyword, name, text, &string, 0);
+
+ DEBUG_printf(("mask=%x, keyword=\"%s\"...\n", mask, keyword));
+
+ if (mask == 0 ||
+ strcmp(keyword, "PPD-Adobe") != 0 ||
+ string == NULL || string[0] != '4')
+ {
+ /*
+ * Either this is not a PPD file, or it is not a 4.x PPD file.
+ */
+
+ if (ppd_status == PPD_OK)
+ ppd_status = PPD_MISSING_PPDADOBE4;
+
+ ppd_free(string);
+
+ return (NULL);
+ }
+
+ DEBUG_printf(("ppdOpen: keyword = %s, string = %p\n", keyword, string));
+
+ ppd_free(string);
+
+ /*
+ * Allocate memory for the PPD file record...
+ */
+
+ if ((ppd = calloc(1, sizeof(ppd_file_t))) == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ return (NULL);
+ }
+
+ ppd->language_level = 1;
+ ppd->color_device = 0;
+ ppd->colorspace = PPD_CS_GRAY;
+ ppd->landscape = -90;
+
+ /*
+ * Get the default language for the user...
+ */
+
+ language = cupsLangDefault();
+
+#ifdef LC_NUMERIC
+ oldlocale = _cupsSaveLocale(LC_NUMERIC, "C");
+#else
+ oldlocale = _cupsSaveLocale(LC_ALL, "C");
+#endif /* LC_NUMERIC */
+
+ /*
+ * Read lines from the PPD file and add them to the file record...
+ */
+
+ group = NULL;
+ subgroup = NULL;
+ option = NULL;
+ choice = NULL;
+ ui_keyword = 0;
+
+ while ((mask = ppd_read(fp, keyword, name, text, &string, 1)) != 0)
+ {
+#ifdef DEBUG
+ printf("mask = %x, keyword = \"%s\"", mask, keyword);
+
+ if (name[0] != '\0')
+ printf(", name = \"%s\"", name);
+
+ if (text[0] != '\0')
+ printf(", text = \"%s\"", text);
+
+ if (string != NULL)
+ {
+ if (strlen(string) > 40)
+ printf(", string = %p", string);
+ else
+ printf(", string = \"%s\"", string);
+ }
+
+ puts("");
+#endif /* DEBUG */
+
+ if (strcmp(keyword, "CloseUI") && strcmp(keyword, "CloseGroup") &&
+ strcmp(keyword, "CloseSubGroup") && strncmp(keyword, "Default", 7) &&
+ strcmp(keyword, "JCLCloseUI") && strcmp(keyword, "JCLOpenUI") &&
+ strcmp(keyword, "OpenUI") && strcmp(keyword, "OpenGroup") &&
+ strcmp(keyword, "OpenSubGroup") && string == NULL)
+ {
+ /*
+ * Need a string value!
+ */
+
+ ppd_status = PPD_MISSING_VALUE;
+
+ goto error;
+ }
+
+ /*
+ * Certain main keywords (as defined by the PPD spec) may be used
+ * without the usual OpenUI/CloseUI stuff. Presumably this is just
+ * so that Adobe wouldn't completely break compatibility with PPD
+ * files prior to v4.0 of the spec, but it is hopelessly
+ * inconsistent... Catch these main keywords and automatically
+ * create the corresponding option, as needed...
+ */
+
+ if (ui_keyword)
+ {
+ /*
+ * Previous line was a UI keyword...
+ */
+
+ option = NULL;
+ ui_keyword = 0;
+ }
+
+ if (option == NULL &&
+ (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
+ (PPD_KEYWORD | PPD_OPTION | PPD_STRING))
+ {
+ for (i = 0; i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])); i ++)
+ if (!strcmp(keyword, ui_keywords[i]))
+ break;
+
+ if (i < (int)(sizeof(ui_keywords) / sizeof(ui_keywords[0])))
+ {
+ /*
+ * Create the option in the appropriate group...
+ */
+
+ ui_keyword = 1;
+
+ DEBUG_printf(("**** FOUND ADOBE UI KEYWORD %s WITHOUT OPENUI!\n",
+ keyword));
+
+ if (!group)
+ {
+ if (strcmp(keyword, "Collate") && strcmp(keyword, "Duplex") &&
+ strcmp(keyword, "InputSlot") && strcmp(keyword, "ManualFeed") &&
+ strcmp(keyword, "MediaType") && strcmp(keyword, "MediaColor") &&
+ strcmp(keyword, "MediaWeight") && strcmp(keyword, "OutputBin") &&
+ strcmp(keyword, "OutputMode") && strcmp(keyword, "OutputOrder") &&
+ strcmp(keyword, "PageSize") && strcmp(keyword, "PageRegion"))
+ group = ppd_get_group(ppd, "Extra",
+ cupsLangString(language, CUPS_MSG_EXTRA));
+ else
+ group = ppd_get_group(ppd, "General",
+ cupsLangString(language, CUPS_MSG_GENERAL));
+
+ if (group == NULL)
+ goto error;
+
+ DEBUG_printf(("Adding to group %s...\n", group->text));
+ option = ppd_get_option(group, keyword);
+ group = NULL;
+ }
+ else
+ option = ppd_get_option(group, keyword);
+
+ if (option == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ /*
+ * Now fill in the initial information for the option...
+ */
+
+ if (!strncmp(keyword, "JCL", 3))
+ option->section = PPD_ORDER_JCL;
+ else
+ option->section = PPD_ORDER_ANY;
+
+ option->order = 10.0f;
+
+ if (i < 8)
+ option->ui = PPD_UI_BOOLEAN;
+ else
+ option->ui = PPD_UI_PICKONE;
+
+ for (j = 0; j < ppd->num_attrs; j ++)
+ if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
+ !strcmp(ppd->attrs[j]->name + 7, keyword) &&
+ ppd->attrs[j]->value)
+ {
+ DEBUG_printf(("Setting Default%s to %s via attribute...\n",
+ option->keyword, ppd->attrs[j]->value));
+ strlcpy(option->defchoice, ppd->attrs[j]->value,
+ sizeof(option->defchoice));
+ break;
+ }
+
+ if (strcmp(keyword, "PageSize") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SIZE),
+ sizeof(option->text));
+ else if (strcmp(keyword, "MediaType") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_TYPE),
+ sizeof(option->text));
+ else if (strcmp(keyword, "InputSlot") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SOURCE),
+ sizeof(option->text));
+ else if (strcmp(keyword, "ColorModel") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_OUTPUT_MODE),
+ sizeof(option->text));
+ else if (strcmp(keyword, "Resolution") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_RESOLUTION),
+ sizeof(option->text));
+ else
+ strlcpy(option->text, keyword, sizeof(option->text));
+ }
+ }
+
+ if (strcmp(keyword, "LanguageLevel") == 0)
+ ppd->language_level = atoi(string);
+ else if (strcmp(keyword, "LanguageEncoding") == 0)
+ ppd->lang_encoding = string;
+ else if (strcmp(keyword, "LanguageVersion") == 0)
+ ppd->lang_version = string;
+ else if (strcmp(keyword, "Manufacturer") == 0)
+ ppd->manufacturer = string;
+ else if (strcmp(keyword, "ModelName") == 0)
+ ppd->modelname = string;
+ else if (strcmp(keyword, "Protocols") == 0)
+ ppd->protocols = string;
+ else if (strcmp(keyword, "PCFileName") == 0)
+ ppd->pcfilename = string;
+ else if (strcmp(keyword, "NickName") == 0)
+ ppd->nickname = string;
+ else if (strcmp(keyword, "Product") == 0)
+ ppd->product = string;
+ else if (strcmp(keyword, "ShortNickName") == 0)
+ ppd->shortnickname = string;
+ else if (strcmp(keyword, "TTRasterizer") == 0)
+ ppd->ttrasterizer = string;
+ else if (strcmp(keyword, "JCLBegin") == 0)
+ {
+ ppd->jcl_begin = strdup(string);
+ ppd_decode(ppd->jcl_begin); /* Decode quoted string */
+ }
+ else if (strcmp(keyword, "JCLEnd") == 0)
+ {
+ ppd->jcl_end = strdup(string);
+ ppd_decode(ppd->jcl_end); /* Decode quoted string */
+ }
+ else if (strcmp(keyword, "JCLToPSInterpreter") == 0)
+ {
+ ppd->jcl_ps = strdup(string);
+ ppd_decode(ppd->jcl_ps); /* Decode quoted string */
+ }
+ else if (strcmp(keyword, "AccurateScreensSupport") == 0)
+ ppd->accurate_screens = strcmp(string, "True") == 0;
+ else if (strcmp(keyword, "ColorDevice") == 0)
+ ppd->color_device = strcmp(string, "True") == 0;
+ else if (strcmp(keyword, "ContoneOnly") == 0)
+ ppd->contone_only = strcmp(string, "True") == 0;
+ else if (strcmp(keyword, "cupsFlipDuplex") == 0)
+ ppd->flip_duplex = strcmp(string, "True") == 0;
+ else if (strcmp(keyword, "cupsManualCopies") == 0)
+ ppd->manual_copies = strcmp(string, "True") == 0;
+ else if (strcmp(keyword, "cupsModelNumber") == 0)
+ ppd->model_number = atoi(string);
+ else if (strcmp(keyword, "cupsColorProfile") == 0)
+ {
+ if (ppd->num_profiles == 0)
+ profile = malloc(sizeof(ppd_profile_t));
+ else
+ profile = realloc(ppd->profiles, sizeof(ppd_profile_t) *
+ (ppd->num_profiles + 1));
+
+ ppd->profiles = profile;
+ profile += ppd->num_profiles;
+ ppd->num_profiles ++;
+
+ memset(profile, 0, sizeof(ppd_profile_t));
+ strlcpy(profile->resolution, name, sizeof(profile->resolution));
+ strlcpy(profile->media_type, text, sizeof(profile->media_type));
+ sscanf(string, "%f%f%f%f%f%f%f%f%f%f%f", &(profile->density),
+ &(profile->gamma),
+ profile->matrix[0] + 0, profile->matrix[0] + 1,
+ profile->matrix[0] + 2, profile->matrix[1] + 0,
+ profile->matrix[1] + 1, profile->matrix[1] + 2,
+ profile->matrix[2] + 0, profile->matrix[2] + 1,
+ profile->matrix[2] + 2);
+ }
+ else if (strcmp(keyword, "cupsFilter") == 0)
+ {
+ if (ppd->num_filters == 0)
+ filter = malloc(sizeof(char *));
+ else
+ filter = realloc(ppd->filters, sizeof(char *) * (ppd->num_filters + 1));
+
+ if (filter == NULL)
+ {
+ ppd_free(filter);
+
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ ppd->filters = filter;
+ filter += ppd->num_filters;
+ ppd->num_filters ++;
+
+ /*
+ * Copy filter string and prevent it from being freed below...
+ */
+
+ *filter = string;
+ string = NULL;
+ }
+ else if (strcmp(keyword, "Throughput") == 0)
+ ppd->throughput = atoi(string);
+ else if (strcmp(keyword, "Font") == 0)
+ {
+ /*
+ * Add this font to the list of available fonts...
+ */
+
+ if (ppd->num_fonts == 0)
+ tempfonts = (char **)malloc(sizeof(char *));
+ else
+ tempfonts = (char **)realloc(ppd->fonts,
+ sizeof(char *) * (ppd->num_fonts + 1));
+
+ if (tempfonts == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ ppd->fonts = tempfonts;
+ ppd->fonts[ppd->num_fonts] = strdup(name);
+ ppd->num_fonts ++;
+ }
+ else if (strcmp(keyword, "ParamCustomPageSize") == 0)
+ {
+ if (strcmp(name, "Width") == 0)
+ sscanf(string, "%*s%*s%f%f", ppd->custom_min + 0,
+ ppd->custom_max + 0);
+ else if (strcmp(name, "Height") == 0)
+ sscanf(string, "%*s%*s%f%f", ppd->custom_min + 1,
+ ppd->custom_max + 1);
+ }
+ else if (strcmp(keyword, "HWMargins") == 0)
+ sscanf(string, "%f%f%f%f", ppd->custom_margins + 0,
+ ppd->custom_margins + 1, ppd->custom_margins + 2,
+ ppd->custom_margins + 3);
+ else if (strcmp(keyword, "CustomPageSize") == 0 &&
+ strcmp(name, "True") == 0)
+ {
+ DEBUG_puts("Processing CustomPageSize...");
+
+ if (!ppd->variable_sizes)
+ {
+ ppd->variable_sizes = 1;
+
+ /*
+ * Add a "Custom" page size entry...
+ */
+
+ ppd_add_size(ppd, "Custom");
+
+ /*
+ * Add a "Custom" page size option...
+ */
+
+ if ((option = ppdFindOption(ppd, "PageSize")) == NULL)
+ {
+ ppd_group_t *temp;
+
+
+ DEBUG_puts("PageSize option not found for CustomPageSize...");
+
+ if ((temp = ppd_get_group(ppd, "General",
+ cupsLangString(language,
+ CUPS_MSG_GENERAL))) == NULL)
+ {
+ DEBUG_puts("Unable to get general group!");
+
+ goto error;
+ }
+
+ if ((option = ppd_get_option(temp, "PageSize")) == NULL)
+ {
+ DEBUG_puts("Unable to get PageSize option!");
+
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+ }
+
+ if ((choice = ppd_add_choice(option, "Custom")) == NULL)
+ {
+ DEBUG_puts("Unable to add Custom choice!");
+
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ strlcpy(choice->text, cupsLangString(language, CUPS_MSG_VARIABLE),
+ sizeof(choice->text));
+ option = NULL;
+ }
+
+ if ((option = ppdFindOption(ppd, "PageSize")) == NULL)
+ {
+ DEBUG_puts("Unable to find PageSize option!");
+
+ ppd_status = PPD_INTERNAL_ERROR;
+
+ goto error;
+ }
+
+ if ((choice = ppdFindChoice(option, "Custom")) == NULL)
+ {
+ DEBUG_puts("Unable to find Custom choice!");
+
+ ppd_status = PPD_INTERNAL_ERROR;
+
+ goto error;
+ }
+
+ choice->code = string;
+ option = NULL;
+ string = NULL; /* Don't add as an attribute below */
+ }
+ else if (strcmp(keyword, "LandscapeOrientation") == 0)
+ {
+ if (strcmp(string, "Minus90") == 0)
+ ppd->landscape = -90;
+ else if (strcmp(string, "Plus90") == 0)
+ ppd->landscape = 90;
+ }
+ else if (strcmp(keyword, "Emulators") == 0)
+ {
+ for (count = 1, sptr = string; sptr != NULL;)
+ if ((sptr = strchr(sptr, ' ')) != NULL)
+ {
+ count ++;
+ while (*sptr == ' ')
+ sptr ++;
+ }
+
+ ppd->num_emulations = count;
+ ppd->emulations = calloc(count, sizeof(ppd_emul_t));
+
+ for (i = 0, sptr = string; i < count; i ++)
+ {
+ for (nameptr = ppd->emulations[i].name;
+ *sptr != '\0' && *sptr != ' ';
+ sptr ++)
+ if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1))
+ *nameptr++ = *sptr;
+
+ *nameptr = '\0';
+
+ while (*sptr == ' ')
+ sptr ++;
+ }
+ }
+ else if (strncmp(keyword, "StartEmulator_", 14) == 0)
+ {
+ ppd_decode(string);
+
+ for (i = 0; i < ppd->num_emulations; i ++)
+ if (strcmp(keyword + 14, ppd->emulations[i].name) == 0)
+ {
+ ppd->emulations[i].start = string;
+ string = NULL;
+ }
+ }
+ else if (strncmp(keyword, "StopEmulator_", 13) == 0)
+ {
+ ppd_decode(string);
+
+ for (i = 0; i < ppd->num_emulations; i ++)
+ if (strcmp(keyword + 13, ppd->emulations[i].name) == 0)
+ {
+ ppd->emulations[i].stop = string;
+ string = NULL;
+ }
+ }
+ else if (strcmp(keyword, "JobPatchFile") == 0)
+ {
+ if (ppd->patches == NULL)
+ ppd->patches = strdup(string);
+ else
+ {
+ temp = realloc(ppd->patches, strlen(ppd->patches) +
+ strlen(string) + 1);
+ if (temp == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ ppd->patches = temp;
+
+ strcpy(ppd->patches + strlen(ppd->patches), string);
+ }
+ }
+ else if (strcmp(keyword, "OpenUI") == 0)
+ {
+ /*
+ * Don't allow nesting of options...
+ */
+
+ if (option && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_NESTED_OPEN_UI;
+
+ goto error;
+ }
+
+ /*
+ * Add an option record to the current sub-group, group, or file...
+ */
+
+ if (name[0] == '*')
+ cups_strcpy(name, name + 1); /* Eliminate leading asterisk */
+
+ for (i = strlen(name) - 1; i > 0 && isspace(name[i] & 255); i --)
+ name[i] = '\0'; /* Eliminate trailing spaces */
+
+ DEBUG_printf(("OpenUI of %s in group %s...\n", name,
+ group ? group->text : "(null)"));
+
+ if (subgroup != NULL)
+ option = ppd_get_option(subgroup, name);
+ else if (group == NULL)
+ {
+ if (strcmp(name, "Collate") && strcmp(name, "Duplex") &&
+ strcmp(name, "InputSlot") && strcmp(name, "ManualFeed") &&
+ strcmp(name, "MediaType") && strcmp(name, "MediaColor") &&
+ strcmp(name, "MediaWeight") && strcmp(name, "OutputBin") &&
+ strcmp(name, "OutputMode") && strcmp(name, "OutputOrder") &&
+ strcmp(name, "PageSize") && strcmp(name, "PageRegion"))
+ group = ppd_get_group(ppd, "Extra",
+ cupsLangString(language, CUPS_MSG_EXTRA));
+ else
+ group = ppd_get_group(ppd, "General",
+ cupsLangString(language, CUPS_MSG_GENERAL));
+
+ if (group == NULL)
+ goto error;
+
+ DEBUG_printf(("Adding to group %s...\n", group->text));
+ option = ppd_get_option(group, name);
+ group = NULL;
+ }
+ else
+ option = ppd_get_option(group, name);
+
+ if (option == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ /*
+ * Now fill in the initial information for the option...
+ */
+
+ if (string && strcmp(string, "PickMany") == 0)
+ option->ui = PPD_UI_PICKMANY;
+ else if (string && strcmp(string, "Boolean") == 0)
+ option->ui = PPD_UI_BOOLEAN;
+ else if (string && strcmp(string, "PickOne") == 0)
+ option->ui = PPD_UI_PICKONE;
+ else if (ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_BAD_OPEN_UI;
+
+ goto error;
+ }
+ else
+ option->ui = PPD_UI_PICKONE;
+
+ for (j = 0; j < ppd->num_attrs; j ++)
+ if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
+ !strcmp(ppd->attrs[j]->name + 7, name) &&
+ ppd->attrs[j]->value)
+ {
+ DEBUG_printf(("Setting Default%s to %s via attribute...\n",
+ option->keyword, ppd->attrs[j]->value));
+ strlcpy(option->defchoice, ppd->attrs[j]->value,
+ sizeof(option->defchoice));
+ break;
+ }
+
+ if (text[0])
+ {
+ strlcpy(option->text, text, sizeof(option->text));
+ ppd_fix(option->text);
+ }
+ else
+ {
+ if (strcmp(name, "PageSize") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SIZE),
+ sizeof(option->text));
+ else if (strcmp(name, "MediaType") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_TYPE),
+ sizeof(option->text));
+ else if (strcmp(name, "InputSlot") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_MEDIA_SOURCE),
+ sizeof(option->text));
+ else if (strcmp(name, "ColorModel") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_OUTPUT_MODE),
+ sizeof(option->text));
+ else if (strcmp(name, "Resolution") == 0)
+ strlcpy(option->text, cupsLangString(language, CUPS_MSG_RESOLUTION),
+ sizeof(option->text));
+ else
+ strlcpy(option->text, name, sizeof(option->text));
+ }
+
+ option->section = PPD_ORDER_ANY;
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "JCLOpenUI") == 0)
+ {
+ /*
+ * Don't allow nesting of options...
+ */
+
+ if (option && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_NESTED_OPEN_UI;
+
+ goto error;
+ }
+
+ /*
+ * Find the JCL group, and add if needed...
+ */
+
+ group = ppd_get_group(ppd, "JCL", "JCL");
+
+ if (group == NULL)
+ goto error;
+
+ /*
+ * Add an option record to the current JCLs...
+ */
+
+ if (name[0] == '*')
+ cups_strcpy(name, name + 1);
+
+ option = ppd_get_option(group, name);
+
+ if (option == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ /*
+ * Now fill in the initial information for the option...
+ */
+
+ if (string && strcmp(string, "PickMany") == 0)
+ option->ui = PPD_UI_PICKMANY;
+ else if (string && strcmp(string, "Boolean") == 0)
+ option->ui = PPD_UI_BOOLEAN;
+ else if (string && strcmp(string, "PickOne") == 0)
+ option->ui = PPD_UI_PICKONE;
+ else
+ {
+ ppd_status = PPD_BAD_OPEN_UI;
+
+ goto error;
+ }
+
+ for (j = 0; j < ppd->num_attrs; j ++)
+ if (!strncmp(ppd->attrs[j]->name, "Default", 7) &&
+ !strcmp(ppd->attrs[j]->name + 7, name) &&
+ ppd->attrs[j]->value)
+ {
+ DEBUG_printf(("Setting Default%s to %s via attribute...\n",
+ option->keyword, ppd->attrs[j]->value));
+ strlcpy(option->defchoice, ppd->attrs[j]->value,
+ sizeof(option->defchoice));
+ break;
+ }
+
+ strlcpy(option->text, text, sizeof(option->text));
+
+ option->section = PPD_ORDER_JCL;
+ group = NULL;
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "CloseUI") == 0 ||
+ strcmp(keyword, "JCLCloseUI") == 0)
+ {
+ option = NULL;
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "OpenGroup") == 0)
+ {
+ /*
+ * Open a new group...
+ */
+
+ if (group != NULL)
+ {
+ ppd_status = PPD_NESTED_OPEN_GROUP;
+
+ goto error;
+ }
+
+ if (!string)
+ {
+ ppd_status = PPD_BAD_OPEN_GROUP;
+
+ goto error;
+ }
+
+ /*
+ * Separate the group name from the text (name/text)...
+ */
+
+ if ((sptr = strchr(string, '/')) != NULL)
+ *sptr++ = '\0';
+ else
+ sptr = string;
+
+ /*
+ * Fix up the text...
+ */
+
+ ppd_decode(sptr);
+ ppd_fix(sptr);
+
+ /*
+ * Find/add the group...
+ */
+
+ group = ppd_get_group(ppd, string, sptr);
+
+ if (group == NULL)
+ goto error;
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "CloseGroup") == 0)
+ {
+ group = NULL;
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "OrderDependency") == 0 ||
+ strcmp(keyword, "NonUIOrderDependency") == 0)
+ {
+ if (sscanf(string, "%f%40s%40s", &order, name, keyword) != 3)
+ {
+ ppd_status = PPD_BAD_ORDER_DEPENDENCY;
+
+ goto error;
+ }
+
+ if (keyword[0] == '*')
+ cups_strcpy(keyword, keyword + 1);
+
+ if (strcmp(name, "ExitServer") == 0)
+ section = PPD_ORDER_EXIT;
+ else if (strcmp(name, "Prolog") == 0)
+ section = PPD_ORDER_PROLOG;
+ else if (strcmp(name, "DocumentSetup") == 0)
+ section = PPD_ORDER_DOCUMENT;
+ else if (strcmp(name, "PageSetup") == 0)
+ section = PPD_ORDER_PAGE;
+ else if (strcmp(name, "JCLSetup") == 0)
+ section = PPD_ORDER_JCL;
+ else
+ section = PPD_ORDER_ANY;
+
+ if (option == NULL)
+ {
+ ppd_group_t *temp;
+
+
+ /*
+ * Only valid for Non-UI options...
+ */
+
+ for (i = ppd->num_groups, temp = ppd->groups; i > 0; i --, temp ++)
+ if (temp->text[0] == '\0')
+ break;
+
+ if (i > 0)
+ for (i = 0; i < temp->num_options; i ++)
+ if (strcmp(keyword, temp->options[i].keyword) == 0)
+ {
+ temp->options[i].section = section;
+ temp->options[i].order = order;
+ break;
+ }
+ }
+ else
+ {
+ option->section = section;
+ option->order = order;
+ }
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strncmp(keyword, "Default", 7) == 0)
+ {
+ if (string == NULL)
+ continue;
+
+ /*
+ * Drop UI text, if any, from value...
+ */
+
+ if (strchr(string, '/') != NULL)
+ *strchr(string, '/') = '\0';
+
+ /*
+ * Assign the default value as appropriate...
+ */
+
+ if (strcmp(keyword, "DefaultColorSpace") == 0)
+ {
+ /*
+ * Set default colorspace...
+ */
+
+ if (strcmp(string, "CMY") == 0)
+ ppd->colorspace = PPD_CS_CMY;
+ else if (strcmp(string, "CMYK") == 0)
+ ppd->colorspace = PPD_CS_CMYK;
+ else if (strcmp(string, "RGB") == 0)
+ ppd->colorspace = PPD_CS_RGB;
+ else if (strcmp(string, "RGBK") == 0)
+ ppd->colorspace = PPD_CS_RGBK;
+ else if (strcmp(string, "N") == 0)
+ ppd->colorspace = PPD_CS_N;
+ else
+ ppd->colorspace = PPD_CS_GRAY;
+ }
+ else if (option && strcmp(keyword + 7, option->keyword) == 0)
+ {
+ /*
+ * Set the default as part of the current option...
+ */
+
+ DEBUG_printf(("Setting %s to %s...\n", keyword, string));
+
+ strlcpy(option->defchoice, string, sizeof(option->defchoice));
+
+ DEBUG_printf(("%s is now %s...\n", keyword, option->defchoice));
+ }
+ else
+ {
+ /*
+ * Lookup option and set if it has been defined...
+ */
+
+ ppd_option_t *toption; /* Temporary option */
+
+
+ if ((toption = ppdFindOption(ppd, keyword + 7)) != NULL)
+ {
+ DEBUG_printf(("Setting %s to %s...\n", keyword, string));
+ strlcpy(toption->defchoice, string, sizeof(toption->defchoice));
+ }
+ }
+ }
+ else if (strcmp(keyword, "UIConstraints") == 0 ||
+ strcmp(keyword, "NonUIConstraints") == 0)
+ {
+ if (ppd->num_consts == 0)
+ constraint = calloc(1, sizeof(ppd_const_t));
+ else
+ constraint = realloc(ppd->consts,
+ (ppd->num_consts + 1) * sizeof(ppd_const_t));
+
+ if (constraint == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ ppd->consts = constraint;
+ constraint += ppd->num_consts;
+ ppd->num_consts ++;
+
+ switch (sscanf(string, "%40s%40s%40s%40s", constraint->option1,
+ constraint->choice1, constraint->option2,
+ constraint->choice2))
+ {
+ case 0 : /* Error */
+ case 1 : /* Error */
+ ppd_status = PPD_BAD_UI_CONSTRAINTS;
+ goto error;
+
+ case 2 : /* Two options... */
+ /*
+ * The following strcpy's are safe, as optionN and
+ * choiceN are all the same size (size defined by PPD spec...)
+ */
+
+ if (constraint->option1[0] == '*')
+ cups_strcpy(constraint->option1, constraint->option1 + 1);
+
+ if (constraint->choice1[0] == '*')
+ cups_strcpy(constraint->option2, constraint->choice1 + 1);
+ else
+ cups_strcpy(constraint->option2, constraint->choice1);
+
+ constraint->choice1[0] = '\0';
+ constraint->choice2[0] = '\0';
+ break;
+
+ case 3 : /* Two options, one choice... */
+ /*
+ * The following cups_strcpy's are safe, as optionN and
+ * choiceN are all the same size (size defined by PPD spec...)
+ */
+
+ if (constraint->option1[0] == '*')
+ cups_strcpy(constraint->option1, constraint->option1 + 1);
+
+ if (constraint->choice1[0] == '*')
+ {
+ cups_strcpy(constraint->choice2, constraint->option2);
+ cups_strcpy(constraint->option2, constraint->choice1 + 1);
+ constraint->choice1[0] = '\0';
+ }
+ else
+ {
+ if (constraint->option2[0] == '*')
+ cups_strcpy(constraint->option2, constraint->option2 + 1);
+
+ constraint->choice2[0] = '\0';
+ }
+ break;
+
+ case 4 : /* Two options, two choices... */
+ if (constraint->option1[0] == '*')
+ cups_strcpy(constraint->option1, constraint->option1 + 1);
+
+ if (constraint->option2[0] == '*')
+ cups_strcpy(constraint->option2, constraint->option2 + 1);
+ break;
+ }
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "PaperDimension") == 0)
+ {
+ if ((size = ppdPageSize(ppd, name)) == NULL)
+ size = ppd_add_size(ppd, name);
+
+ if (size == NULL)
+ {
+ /*
+ * Unable to add or find size!
+ */
+
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ sscanf(string, "%f%f", &(size->width), &(size->length));
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (strcmp(keyword, "ImageableArea") == 0)
+ {
+ if ((size = ppdPageSize(ppd, name)) == NULL)
+ size = ppd_add_size(ppd, name);
+
+ if (size == NULL)
+ {
+ /*
+ * Unable to add or find size!
+ */
+
+ ppd_status = PPD_ALLOC_ERROR;
+
+ goto error;
+ }
+
+ sscanf(string, "%f%f%f%f", &(size->left), &(size->bottom),
+ &(size->right), &(size->top));
+
+ ppd_free(string);
+ string = NULL;
+ }
+ else if (option != NULL &&
+ (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) ==
+ (PPD_KEYWORD | PPD_OPTION | PPD_STRING) &&
+ strcmp(keyword, option->keyword) == 0)
+ {
+ DEBUG_printf(("group = %p, subgroup = %p\n", group, subgroup));
+
+ if (strcmp(keyword, "PageSize") == 0)
+ {
+ /*
+ * Add a page size...
+ */
+
+ if (ppdPageSize(ppd, name) == NULL)
+ ppd_add_size(ppd, name);
+ }
+
+ /*
+ * Add the option choice...
+ */
+
+ choice = ppd_add_choice(option, name);
+
+ if (mask & PPD_TEXT)
+ {
+ strlcpy(choice->text, text, sizeof(choice->text));
+ ppd_fix(choice->text);
+ }
+ else if (strcmp(name, "True") == 0)
+ strcpy(choice->text, "Yes");
+ else if (strcmp(name, "False") == 0)
+ strcpy(choice->text, "No");
+ else
+ strlcpy(choice->text, name, sizeof(choice->text));
+
+ if (option->section == PPD_ORDER_JCL)
+ ppd_decode(string); /* Decode quoted string */
+
+ choice->code = string;
+ string = NULL; /* Don't add as an attribute below */
+ }
+
+ /*
+ * Add remaining lines with keywords and string values as attributes...
+ */
+
+ if (string &&
+ (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING))
+ ppd_add_attr(ppd, keyword, name, text, string);
+ else
+ {
+ ppd_free(string);
+ }
+ }
+
+ /*
+ * Reset language preferences...
+ */
+
+ cupsLangFree(language);
+
+#ifdef LC_NUMERIC
+ _cupsRestoreLocale(LC_NUMERIC, oldlocale);
+#else
+ _cupsRestoreLocale(LC_ALL, oldlocale);
+#endif /* LC_NUMERIC */
+
+#ifdef DEBUG
+ if (!feof(fp))
+ printf("Premature EOF at %lu...\n", (unsigned long)ftell(fp));
+#endif /* DEBUG */
+
+ if (ppd_status != PPD_OK)
+ {
+ /*
+ * Had an error reading the PPD file, cannot continue!
+ */
+
+ ppdClose(ppd);
+
+ return (NULL);
+ }
+
+#ifndef __APPLE__
+ /*
+ * Make sure that all PPD files with an InputSlot option have an
+ * "auto" choice that maps to no specific tray or media type.
+ */
+
+ if ((option = ppdFindOption(ppd, "InputSlot")) != NULL)
+ {
+ for (i = 0; i < option->num_choices; i ++)
+ if (option->choices[i].code == NULL || !option->choices[i].code[0] ||
+ !strncasecmp(option->choices[i].choice, "Auto", 4))
+ break;
+
+ if (i >= option->num_choices)
+ {
+ /*
+ * No "auto" input slot, add one...
+ */
+
+ choice = ppd_add_choice(option, "Auto");
+
+ strlcpy(choice->text, cupsLangString(language, CUPS_MSG_AUTO),
+ sizeof(choice->text));
+ choice->code = NULL;
+ }
+ }
+#endif /* !__APPLE__ */
+
+ /*
+ * Set the option back-pointer for each choice...
+ */
+
+#ifndef __APPLE__
+ qsort(ppd->groups, ppd->num_groups, sizeof(ppd_group_t),
+ (int (*)(const void *, const void *))ppd_compare_groups);
+#endif /* !__APPLE__ */
+
+ for (i = ppd->num_groups, group = ppd->groups;
+ i > 0;
+ i --, group ++)
+ {
+#ifndef __APPLE__
+ qsort(group->options, group->num_options, sizeof(ppd_option_t),
+ (int (*)(const void *, const void *))ppd_compare_options);
+#endif /* !__APPLE__ */
+
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ {
+ for (k = 0; k < option->num_choices; k ++)
+ option->choices[k].option = (void *)option;
+ }
+
+#ifndef __APPLE__
+ qsort(group->subgroups, group->num_subgroups, sizeof(ppd_group_t),
+ (int (*)(const void *, const void *))ppd_compare_groups);
+#endif /* !__APPLE__ */
+
+ for (j = group->num_subgroups, subgroup = group->subgroups;
+ j > 0;
+ j --, subgroup ++)
+ {
+#ifndef __APPLE__
+ qsort(subgroup->options, subgroup->num_options, sizeof(ppd_option_t),
+ (int (*)(const void *, const void *))ppd_compare_options);
+#endif /* !__APPLE__ */
+
+ for (k = group->num_options, option = group->options;
+ k > 0;
+ k --, option ++)
+ {
+ for (m = 0; m < option->num_choices; m ++)
+ option->choices[m].option = (void *)option;
+ }
+ }
+ }
+
+ /*
+ * Sort the attributes...
+ */
+
+ if (ppd->num_attrs > 1)
+ qsort(ppd->attrs, ppd->num_attrs, sizeof(ppd_attr_t *),
+ (int (*)(const void *, const void *))_ppd_attr_compare);
+
+ /*
+ * Return the PPD file structure...
+ */
+
+ return (ppd);
+
+ /*
+ * Common exit point for errors to save code size...
+ */
+
+ error:
+
+ ppd_free(string);
+
+ ppdClose(ppd);
+
+ cupsLangFree(language);
+
+#ifdef LC_NUMERIC
+ _cupsRestoreLocale(LC_NUMERIC, oldlocale);
+#else
+ _cupsRestoreLocale(LC_ALL, oldlocale);
+#endif /* LC_NUMERIC */
+
+ return (NULL);
+}
+
+
+/*
+ * 'ppdOpenFd()' - Read a PPD file into memory.
+ */
+
+ppd_file_t * /* O - PPD file record */
+ppdOpenFd(int fd) /* I - File to read from */
+{
+ FILE *fp; /* File pointer */
+ ppd_file_t *ppd; /* PPD file record */
+
+
+ /*
+ * Set the line number to 0...
+ */
+
+ ppd_line = 0;
+
+ /*
+ * Range check input...
+ */
+
+ if (fd < 0)
+ {
+ ppd_status = PPD_NULL_FILE;
+
+ return (NULL);
+ }
+
+ /*
+ * Try to open the file and parse it...
+ */
+
+ if ((fp = fdopen(fd, "r")) != NULL)
+ {
+ setbuf(fp, NULL);
+
+ ppd = ppdOpen(fp);
+
+ fclose(fp);
+ }
+ else
+ {
+ ppd_status = PPD_FILE_OPEN_ERROR;
+ ppd = NULL;
+ }
+
+ return (ppd);
+}
+
+
+/*
+ * 'ppdOpenFile()' - Read a PPD file into memory.
+ */
+
+ppd_file_t * /* O - PPD file record */
+ppdOpenFile(const char *filename) /* I - File to read from */
+{
+ FILE *fp; /* File pointer */
+ ppd_file_t *ppd; /* PPD file record */
+
+
+ /*
+ * Set the line number to 0...
+ */
+
+ ppd_line = 0;
+
+ /*
+ * Range check input...
+ */
+
+ if (filename == NULL)
+ {
+ ppd_status = PPD_NULL_FILE;
+
+ return (NULL);
+ }
+
+ /*
+ * Try to open the file and parse it...
+ */
+
+ if ((fp = fopen(filename, "r")) != NULL)
+ {
+ ppd = ppdOpen(fp);
+
+ fclose(fp);
+ }
+ else
+ {
+ ppd_status = PPD_FILE_OPEN_ERROR;
+ ppd = NULL;
+ }
+
+ return (ppd);
+}
+
+
+/*
+ * 'ppdSetConformance()' - Set the conformance level for PPD files.
+ */
+
+void
+ppdSetConformance(ppd_conform_t c) /* I - Conformance level */
+{
+ ppd_conform = c;
+}
+
+
+/*
+ * 'ppd_add_attr()' - Add an attribute to the PPD data.
+ */
+
+static ppd_attr_t * /* O - New attribute */
+ppd_add_attr(ppd_file_t *ppd, /* I - PPD file data */
+ const char *name, /* I - Attribute name */
+ const char *spec, /* I - Specifier string, if any */
+ const char *text, /* I - Text string, if any */
+ const char *value) /* I - Value of attribute */
+{
+ ppd_attr_t **ptr, /* New array */
+ *temp; /* New attribute */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (ppd == NULL || name == NULL || spec == NULL)
+ return (NULL);
+
+ /*
+ * Allocate memory for the new attribute...
+ */
+
+ if (ppd->num_attrs == 0)
+ ptr = malloc(sizeof(ppd_attr_t *));
+ else
+ ptr = realloc(ppd->attrs, (ppd->num_attrs + 1) * sizeof(ppd_attr_t *));
+
+ if (ptr == NULL)
+ return (NULL);
+
+ ppd->attrs = ptr;
+ ptr += ppd->num_attrs;
+
+ if ((temp = calloc(1, sizeof(ppd_attr_t))) == NULL)
+ return (NULL);
+
+ *ptr = temp;
+
+ ppd->num_attrs ++;
+
+ /*
+ * Copy data over...
+ */
+
+ strlcpy(temp->name, name, sizeof(temp->name));
+ strlcpy(temp->spec, spec, sizeof(temp->spec));
+ strlcpy(temp->text, text, sizeof(temp->text));
+ temp->value = (char *)value;
+
+ /*
+ * Return the attribute...
+ */
+
+ return (temp);
+}
+
+
+/*
+ * 'ppd_add_choice()' - Add a choice to an option.
+ */
+
+static ppd_choice_t * /* O - Named choice */
+ppd_add_choice(ppd_option_t *option, /* I - Option */
+ const char *name) /* I - Name of choice */
+{
+ ppd_choice_t *choice; /* Choice */
+
+
+ if (option->num_choices == 0)
+ choice = malloc(sizeof(ppd_choice_t));
+ else
+ choice = realloc(option->choices,
+ sizeof(ppd_choice_t) * (option->num_choices + 1));
+
+ if (choice == NULL)
+ return (NULL);
+
+ option->choices = choice;
+ choice += option->num_choices;
+ option->num_choices ++;
+
+ memset(choice, 0, sizeof(ppd_choice_t));
+ strlcpy(choice->choice, name, sizeof(choice->choice));
+
+ return (choice);
+}
+
+
+/*
+ * 'ppd_add_size()' - Add a page size.
+ */
+
+static ppd_size_t * /* O - Named size */
+ppd_add_size(ppd_file_t *ppd, /* I - PPD file */
+ const char *name) /* I - Name of size */
+{
+ ppd_size_t *size; /* Size */
+
+
+ if (ppd->num_sizes == 0)
+ size = malloc(sizeof(ppd_size_t));
+ else
+ size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1));
+
+ if (size == NULL)
+ return (NULL);
+
+ ppd->sizes = size;
+ size += ppd->num_sizes;
+ ppd->num_sizes ++;
+
+ memset(size, 0, sizeof(ppd_size_t));
+ strlcpy(size->name, name, sizeof(size->name));
+
+ return (size);
+}
+
+
+#ifndef __APPLE__
+/*
+ * 'ppd_compare_groups()' - Compare two groups.
+ */
+
+static int /* O - Result of comparison */
+ppd_compare_groups(ppd_group_t *g0, /* I - First group */
+ ppd_group_t *g1) /* I - Second group */
+{
+ return (strcasecmp(g0->text, g1->text));
+}
+
+
+/*
+ * 'ppd_compare_options()' - Compare two options.
+ */
+
+static int /* O - Result of comparison */
+ppd_compare_options(ppd_option_t *o0, /* I - First option */
+ ppd_option_t *o1) /* I - Second option */
+{
+ return (strcasecmp(o0->text, o1->text));
+}
+#endif /* !__APPLE__ */
+
+
+/*
+ * 'ppd_decode()' - Decode a string value...
+ */
+
+static int /* O - Length of decoded string */
+ppd_decode(char *string) /* I - String to decode */
+{
+ char *inptr, /* Input pointer */
+ *outptr; /* Output pointer */
+
+
+ inptr = string;
+ outptr = string;
+
+ while (*inptr != '\0')
+ if (*inptr == '<' && isxdigit(inptr[1] & 255))
+ {
+ /*
+ * Convert hex to 8-bit values...
+ */
+
+ inptr ++;
+ while (isxdigit(*inptr & 255))
+ {
+ if (isalpha(*inptr))
+ *outptr = (tolower(*inptr) - 'a' + 10) << 4;
+ else
+ *outptr = (*inptr - '0') << 4;
+
+ inptr ++;
+
+ if (!isxdigit(*inptr & 255))
+ break;
+
+ if (isalpha(*inptr))
+ *outptr |= tolower(*inptr) - 'a' + 10;
+ else
+ *outptr |= *inptr - '0';
+
+ inptr ++;
+ outptr ++;
+ }
+
+ while (*inptr != '>' && *inptr != '\0')
+ inptr ++;
+ while (*inptr == '>')
+ inptr ++;
+ }
+ else
+ *outptr++ = *inptr++;
+
+ *outptr = '\0';
+
+ return (outptr - string);
+}
+
+
+#ifndef __APPLE__
+/*
+ * 'ppd_fix()' - Fix WinANSI characters in the range 0x80 to 0x9f to be
+ * valid ISO-8859-1 characters...
+ */
+
+static void
+ppd_fix(char *string) /* IO - String to fix */
+{
+ unsigned char *p; /* Pointer into string */
+ static const unsigned char lut[32] = /* Lookup table for characters */
+ {
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 0x20,
+ 'l',
+ '`',
+ '\'',
+ '^',
+ '~',
+ 0x20, /* bar */
+ 0x20, /* circumflex */
+ 0x20, /* dot */
+ 0x20, /* double dot */
+ 0x20,
+ 0x20, /* circle */
+ 0x20, /* ??? */
+ 0x20,
+ '\"', /* should be right quotes */
+ 0x20, /* ??? */
+ 0x20 /* accent */
+ };
+
+
+ for (p = (unsigned char *)string; *p; p ++)
+ if (*p >= 0x80 && *p < 0xa0)
+ *p = lut[*p - 0x80];
+}
+#endif /* !__APPLE__ */
+
+
+/*
+ * 'ppd_free_group()' - Free a single UI group.
+ */
+
+static void
+ppd_free_group(ppd_group_t *group) /* I - Group to free */
+{
+ int i; /* Looping var */
+ ppd_option_t *option; /* Current option */
+ ppd_group_t *subgroup; /* Current sub-group */
+
+
+ if (group->num_options > 0)
+ {
+ for (i = group->num_options, option = group->options;
+ i > 0;
+ i --, option ++)
+ ppd_free_option(option);
+
+ ppd_free(group->options);
+ }
+
+ if (group->num_subgroups > 0)
+ {
+ for (i = group->num_subgroups, subgroup = group->subgroups;
+ i > 0;
+ i --, subgroup ++)
+ ppd_free_group(subgroup);
+
+ ppd_free(group->subgroups);
+ }
+}
+
+
+/*
+ * 'ppd_free_option()' - Free a single option.
+ */
+
+static void
+ppd_free_option(ppd_option_t *option) /* I - Option to free */
+{
+ int i; /* Looping var */
+ ppd_choice_t *choice; /* Current choice */
+
+
+ if (option->num_choices > 0)
+ {
+ for (i = option->num_choices, choice = option->choices;
+ i > 0;
+ i --, choice ++)
+ {
+ ppd_free(choice->code);
+ }
+
+ ppd_free(option->choices);
+ }
+}
+
+
+/*
+ * 'ppd_get_group()' - Find or create the named group as needed.
+ */
+
+static ppd_group_t * /* O - Named group */
+ppd_get_group(ppd_file_t *ppd, /* I - PPD file */
+ const char *name, /* I - Name of group */
+ const char *text) /* I - Text for group */
+{
+ int i; /* Looping var */
+ ppd_group_t *group; /* Group */
+
+
+ DEBUG_printf(("ppd_get_group(%p, \"%s\")\n", ppd, name));
+
+ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+ if (strcmp(group->name, name) == 0)
+ break;
+
+ if (i == 0)
+ {
+ DEBUG_printf(("Adding group %s...\n", name));
+
+ if (ppd_conform == PPD_CONFORM_STRICT && strlen(text) >= sizeof(group->text))
+ {
+ ppd_status = PPD_ILLEGAL_TRANSLATION;
+
+ return (NULL);
+ }
+
+ if (ppd->num_groups == 0)
+ group = malloc(sizeof(ppd_group_t));
+ else
+ group = realloc(ppd->groups,
+ (ppd->num_groups + 1) * sizeof(ppd_group_t));
+
+ if (group == NULL)
+ {
+ ppd_status = PPD_ALLOC_ERROR;
+
+ return (NULL);
+ }
+
+ ppd->groups = group;
+ group += ppd->num_groups;
+ ppd->num_groups ++;
+
+ memset(group, 0, sizeof(ppd_group_t));
+ strlcpy(group->name, name, sizeof(group->name));
+ strlcpy(group->text, text, sizeof(group->text));
+ }
+
+ return (group);
+}
+
+
+/*
+ * 'ppd_get_option()' - Find or create the named option as needed.
+ */
+
+static ppd_option_t * /* O - Named option */
+ppd_get_option(ppd_group_t *group, /* I - Group */
+ const char *name) /* I - Name of option */
+{
+ int i; /* Looping var */
+ ppd_option_t *option; /* Option */
+
+
+ DEBUG_printf(("ppd_get_option(group=%p(\"%s\"), name=\"%s\")\n",
+ group, group->name, name));
+
+ for (i = group->num_options, option = group->options; i > 0; i --, option ++)
+ if (strcmp(option->keyword, name) == 0)
+ break;
+
+ if (i == 0)
+ {
+ if (group->num_options == 0)
+ option = malloc(sizeof(ppd_option_t));
+ else
+ option = realloc(group->options,
+ (group->num_options + 1) * sizeof(ppd_option_t));
+
+ if (option == NULL)
+ return (NULL);
+
+ group->options = option;
+ option += group->num_options;
+ group->num_options ++;
+
+ memset(option, 0, sizeof(ppd_option_t));
+ strlcpy(option->keyword, name, sizeof(option->keyword));
+ }
+
+ return (option);
+}
+
+
+/*
+ * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as
+ * necessary.
+ */
+
+static int /* O - Bitmask of fields read */
+ppd_read(FILE *fp, /* I - File to read from */
+ char *keyword, /* O - Keyword from line */
+ char *option, /* O - Option from line */
+ char *text, /* O - Human-readable text from line */
+ char **string, /* O - Code/string data */
+ int ignoreblank) /* I - Ignore blank lines? */
+{
+ int ch, /* Character from file */
+ col, /* Column in line */
+ colon, /* Colon seen? */
+ endquote, /* Waiting for an end quote */
+ mask, /* Mask to be returned */
+ startline, /* Start line */
+ textlen; /* Length of text */
+ char *keyptr, /* Keyword pointer */
+ *optptr, /* Option pointer */
+ *textptr, /* Text pointer */
+ *strptr, /* Pointer into string */
+ *lineptr, /* Current position in line buffer */
+ line[65536]; /* Line buffer (64k) */
+
+
+ /*
+ * Range check everything...
+ */
+
+ if (fp == NULL || keyword == NULL || option == NULL || text == NULL ||
+ string == NULL)
+ return (0);
+
+ /*
+ * Now loop until we have a valid line...
+ */
+
+ *string = NULL;
+ col = 0;
+ startline = ppd_line + 1;
+
+ do
+ {
+ /*
+ * Read the line...
+ */
+
+ lineptr = line;
+ endquote = 0;
+ colon = 0;
+
+ while ((ch = getc(fp)) != EOF &&
+ (lineptr - line) < (sizeof(line) - 1))
+ {
+ if (ch == '\r' || ch == '\n')
+ {
+ /*
+ * Line feed or carriage return...
+ */
+
+ ppd_line ++;
+ col = 0;
+
+ if (ch == '\r')
+ {
+ /*
+ * Check for a trailing line feed...
+ */
+
+ if ((ch = getc(fp)) == EOF)
+ break;
+ if (ch != 0x0a)
+ ungetc(ch, fp);
+ }
+
+ if (lineptr == line && ignoreblank)
+ continue; /* Skip blank lines */
+
+ ch = '\n';
+
+ if (!endquote) /* Continue for multi-line text */
+ break;
+
+ *lineptr++ = '\n';
+ }
+ else if (ch < ' ' && ch != '\t' && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ /*
+ * Other control characters...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_ILLEGAL_CHARACTER;
+
+ return (0);
+ }
+ else if (ch != 0x1a)
+ {
+ /*
+ * Any other character...
+ */
+
+ *lineptr++ = ch;
+ col ++;
+
+ if (col > (PPD_MAX_LINE - 1))
+ {
+ /*
+ * Line is too long...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_LINE_TOO_LONG;
+
+ return (0);
+ }
+
+ if (ch == ':' && strncmp(line, "*%", 2) != 0)
+ colon = 1;
+
+ if (ch == '\"' && colon)
+ endquote = !endquote;
+ }
+ }
+
+ if (endquote)
+ {
+ /*
+ * Didn't finish this quoted string...
+ */
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\"')
+ break;
+ else if (ch == '\r' || ch == '\n')
+ {
+ ppd_line ++;
+ col = 0;
+
+ if (ch == '\r')
+ {
+ /*
+ * Check for a trailing line feed...
+ */
+
+ if ((ch = getc(fp)) == EOF)
+ break;
+ if (ch != 0x0a)
+ ungetc(ch, fp);
+ }
+
+ ch = '\n';
+ }
+ else if (ch < ' ' && ch != '\t' && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ /*
+ * Other control characters...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_ILLEGAL_CHARACTER;
+
+ return (0);
+ }
+ else if (ch != 0x1a)
+ {
+ col ++;
+
+ if (col > (PPD_MAX_LINE - 1))
+ {
+ /*
+ * Line is too long...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_LINE_TOO_LONG;
+
+ return (0);
+ }
+ }
+ }
+
+ if (ch != '\n')
+ {
+ /*
+ * Didn't finish this line...
+ */
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\r' || ch == '\n')
+ {
+ /*
+ * Line feed or carriage return...
+ */
+
+ ppd_line ++;
+ col = 0;
+
+ if (ch == '\r')
+ {
+ /*
+ * Check for a trailing line feed...
+ */
+
+ if ((ch = getc(fp)) == EOF)
+ break;
+ if (ch != 0x0a)
+ ungetc(ch, fp);
+ }
+
+ break;
+ }
+ else if (ch < ' ' && ch != '\t' && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ /*
+ * Other control characters...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_ILLEGAL_CHARACTER;
+
+ return (0);
+ }
+ else if (ch != 0x1a)
+ {
+ col ++;
+
+ if (col > (PPD_MAX_LINE - 1))
+ {
+ /*
+ * Line is too long...
+ */
+
+ ppd_line = startline;
+ ppd_status = PPD_LINE_TOO_LONG;
+
+ return (0);
+ }
+ }
+ }
+
+ if (lineptr > line && lineptr[-1] == '\n')
+ lineptr --;
+
+ *lineptr = '\0';
+
+ DEBUG_printf(("LINE = \"%s\"\n", line));
+
+ if (ch == EOF && lineptr == line)
+ return (0);
+
+ /*
+ * Now parse it...
+ */
+
+ mask = 0;
+ lineptr = line + 1;
+
+ keyword[0] = '\0';
+ option[0] = '\0';
+ text[0] = '\0';
+ *string = NULL;
+
+ if ((!line[0] || /* Blank line */
+ strncmp(line, "*%", 2) == 0 || /* Comment line */
+ strcmp(line, "*End") == 0) && /* End of multi-line string */
+ ignoreblank) /* Ignore these? */
+ {
+ startline = ppd_line + 1;
+ continue;
+ }
+
+ if (strcmp(line, "*") == 0) /* (Bad) comment line */
+ {
+ if (ppd_conform == PPD_CONFORM_RELAXED)
+ {
+ startline = ppd_line + 1;
+ continue;
+ }
+ else
+ {
+ ppd_line = startline;
+ ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
+
+ return (0);
+ }
+ }
+
+ if (line[0] != '*') /* All lines start with an asterisk */
+ {
+ if (ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_MISSING_ASTERISK;
+ return (0);
+ }
+
+ /*
+ * Allow lines consisting of just whitespace...
+ */
+
+ for (lineptr = line; *lineptr; lineptr ++)
+ if (!isspace(*lineptr & 255))
+ break;
+
+ if (*lineptr)
+ {
+ ppd_status = PPD_MISSING_ASTERISK;
+ return (0);
+ }
+ else if (ignoreblank)
+ continue;
+ else
+ return (0);
+ }
+
+ /*
+ * Get a keyword...
+ */
+
+ keyptr = keyword;
+
+ while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr & 255))
+ {
+ if (*lineptr <= ' ' || *lineptr > 126 || *lineptr == '/' ||
+ (keyptr - keyword) >= (PPD_MAX_NAME - 1))
+ {
+ ppd_status = PPD_ILLEGAL_MAIN_KEYWORD;
+ return (0);
+ }
+
+ *keyptr++ = *lineptr++;
+ }
+
+ *keyptr = '\0';
+
+ if (strcmp(keyword, "End") == 0)
+ continue;
+
+ mask |= PPD_KEYWORD;
+
+/* DEBUG_printf(("keyword = \"%s\", lineptr = \"%s\"\n", keyword, lineptr));*/
+
+ if (isspace(*lineptr & 255))
+ {
+ /*
+ * Get an option name...
+ */
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ optptr = option;
+
+ while (*lineptr != '\0' && !isspace(*lineptr & 255) && *lineptr != ':' &&
+ *lineptr != '/')
+ {
+ if (*lineptr <= ' ' || *lineptr > 126 ||
+ (optptr - option) >= (PPD_MAX_NAME - 1))
+ {
+ ppd_status = PPD_ILLEGAL_OPTION_KEYWORD;
+ return (0);
+ }
+
+ *optptr++ = *lineptr++;
+ }
+
+ *optptr = '\0';
+
+ if (isspace(*lineptr & 255) && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_ILLEGAL_WHITESPACE;
+ return (0);
+ }
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ mask |= PPD_OPTION;
+
+/* DEBUG_printf(("option = \"%s\", lineptr = \"%s\"\n", option, lineptr));*/
+
+ if (*lineptr == '/')
+ {
+ /*
+ * Get human-readable text...
+ */
+
+ lineptr ++;
+
+ textptr = text;
+
+ while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':')
+ {
+ if (((unsigned char)*lineptr < ' ' && *lineptr != '\t') ||
+ (textptr - text) >= (PPD_MAX_LINE - 1))
+ {
+ ppd_status = PPD_ILLEGAL_TRANSLATION;
+ return (0);
+ }
+
+ *textptr++ = *lineptr++;
+ }
+
+ *textptr = '\0';
+ textlen = ppd_decode(text);
+
+ if (textlen > PPD_MAX_TEXT && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_ILLEGAL_TRANSLATION;
+ return (0);
+ }
+
+ mask |= PPD_TEXT;
+ }
+
+/* DEBUG_printf(("text = \"%s\", lineptr = \"%s\"\n", text, lineptr));*/
+ }
+
+ if (isspace(*lineptr & 255) && ppd_conform == PPD_CONFORM_STRICT)
+ {
+ ppd_status = PPD_ILLEGAL_WHITESPACE;
+ return (0);
+ }
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ if (*lineptr == ':')
+ {
+ /*
+ * Get string after triming leading and trailing whitespace...
+ */
+
+ lineptr ++;
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ strptr = lineptr + strlen(lineptr) - 1;
+ while (strptr >= lineptr && isspace(*strptr & 255))
+ *strptr-- = '\0';
+
+ if (*strptr == '\"')
+ {
+ /*
+ * Quoted string by itself...
+ */
+
+ *string = malloc(strlen(lineptr) + 1);
+
+ strptr = *string;
+
+ for (; *lineptr != '\0'; lineptr ++)
+ if (*lineptr != '\"')
+ *strptr++ = *lineptr;
+
+ *strptr = '\0';
+ }
+ else
+ *string = strdup(lineptr);
+
+/* DEBUG_printf(("string = \"%s\", lineptr = \"%s\"\n", *string, lineptr));*/
+
+ mask |= PPD_STRING;
+ }
+ }
+ while (mask == 0);
+
+ return (mask);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/ppd.h b/cups/ppd.h
new file mode 100644
index 000000000..796ca1a36
--- /dev/null
+++ b/cups/ppd.h
@@ -0,0 +1,338 @@
+/*
+ * "$Id$"
+ *
+ * PostScript Printer Description definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This code and any derivative of it may be used and distributed
+ * freely under the terms of the GNU General Public License when
+ * used with GNU Ghostscript or its derivatives. Use of the code
+ * (or any derivative of it) with software other than GNU
+ * GhostScript (or its derivatives) is governed by the CUPS license
+ * agreement.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_PPD_H_
+# define _CUPS_PPD_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <stdio.h>
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
+ * PPD version...
+ */
+
+# define PPD_VERSION 4.3 /* Kept in sync with Adobe version number */
+
+
+/*
+ * PPD size limits (defined in Adobe spec)
+ */
+
+# define PPD_MAX_NAME 41 /* Maximum size of name + 1 for nul */
+# define PPD_MAX_TEXT 81 /* Maximum size of text + 1 for nul */
+# define PPD_MAX_LINE 256 /* Maximum size of line + 1 for nul */
+
+
+/*
+ * Types and structures...
+ */
+
+typedef enum /**** UI Types ****/
+{
+ PPD_UI_BOOLEAN, /* True or False option */
+ PPD_UI_PICKONE, /* Pick one from a list */
+ PPD_UI_PICKMANY /* Pick zero or more from a list */
+} ppd_ui_t;
+
+typedef enum /**** Order dependency sections ****/
+{
+ PPD_ORDER_ANY, /* Option code can be anywhere in the file */
+ PPD_ORDER_DOCUMENT, /* ... must be in the DocumentSetup section */
+ PPD_ORDER_EXIT, /* ... must be sent prior to the document */
+ PPD_ORDER_JCL, /* ... must be sent as a JCL command */
+ PPD_ORDER_PAGE, /* ... must be in the PageSetup section */
+ PPD_ORDER_PROLOG /* ... must be in the Prolog section */
+} ppd_section_t;
+
+typedef enum /**** Colorspaces ****/
+{
+ PPD_CS_CMYK = -4, /* CMYK colorspace */
+ PPD_CS_CMY, /* CMY colorspace */
+ PPD_CS_GRAY = 1, /* Grayscale colorspace */
+ PPD_CS_RGB = 3, /* RGB colorspace */
+ PPD_CS_RGBK, /* RGBK (K = gray) colorspace */
+ PPD_CS_N /* DeviceN colorspace */
+} ppd_cs_t;
+
+typedef enum /**** Status Codes ****/
+{
+ PPD_OK = 0, /* OK */
+ PPD_FILE_OPEN_ERROR, /* Unable to open PPD file */
+ PPD_NULL_FILE, /* NULL PPD file pointer */
+ PPD_ALLOC_ERROR, /* Memory allocation error */
+ PPD_MISSING_PPDADOBE4, /* Missing PPD-Adobe-4.x header */
+ PPD_MISSING_VALUE, /* Missing value string */
+ PPD_INTERNAL_ERROR, /* Internal error */
+ PPD_BAD_OPEN_GROUP, /* Bad OpenGroup */
+ PPD_NESTED_OPEN_GROUP, /* OpenGroup without a CloseGroup first */
+ PPD_BAD_OPEN_UI, /* Bad OpenUI/JCLOpenUI */
+ PPD_NESTED_OPEN_UI, /* OpenUI/JCLOpenUI without a CloseUI/JCLCloseUI first */
+ PPD_BAD_ORDER_DEPENDENCY, /* Bad OrderDependency */
+ PPD_BAD_UI_CONSTRAINTS, /* Bad UIConstraints */
+ PPD_MISSING_ASTERISK, /* Missing asterisk in column 0 */
+ PPD_LINE_TOO_LONG, /* Line longer than 255 chars */
+ PPD_ILLEGAL_CHARACTER, /* Illegal control character */
+ PPD_ILLEGAL_MAIN_KEYWORD, /* Illegal main keyword string */
+ PPD_ILLEGAL_OPTION_KEYWORD, /* Illegal option keyword string */
+ PPD_ILLEGAL_TRANSLATION, /* Illegal translation string */
+ PPD_ILLEGAL_WHITESPACE /* Illegal whitespace character */
+} ppd_status_t;
+
+typedef enum /**** Conformance Levels ****/
+{
+ PPD_CONFORM_RELAXED, /* Relax whitespace and control char */
+ PPD_CONFORM_STRICT /* Require strict conformance */
+} ppd_conform_t;
+
+typedef struct /**** PPD Attribute Structure ****/
+{
+ char name[PPD_MAX_NAME],
+ /* Name of attribute (cupsXYZ) */
+ spec[PPD_MAX_NAME],
+ /* Specifier string, if any */
+ text[PPD_MAX_TEXT],
+ /* Human-readable text, if any */
+ *value; /* Value string */
+} ppd_attr_t;
+
+typedef struct /**** Option choices ****/
+{
+ char marked, /* 0 if not selected, 1 otherwise */
+ choice[PPD_MAX_NAME],
+ /* Computer-readable option name */
+ text[PPD_MAX_TEXT],
+ /* Human-readable option name */
+ *code; /* Code to send for this option */
+ void *option; /* Pointer to parent option structure */
+} ppd_choice_t;
+
+typedef struct /**** Options ****/
+{
+ char conflicted, /* 0 if no conflicts exist, 1 otherwise */
+ keyword[PPD_MAX_NAME],
+ /* Option keyword name ("PageSize", etc.) */
+ defchoice[PPD_MAX_NAME],
+ /* Default option choice */
+ text[PPD_MAX_TEXT];
+ /* Human-readable text */
+ ppd_ui_t ui; /* Type of UI option */
+ ppd_section_t section; /* Section for command */
+ float order; /* Order number */
+ int num_choices; /* Number of option choices */
+ ppd_choice_t *choices; /* Option choices */
+} ppd_option_t;
+
+typedef struct ppd_group_str /**** Groups ****/
+{
+ /**** Group text strings are limited to 39 chars + nul in order to
+ **** preserve binary compatibility and allow applications to get
+ **** the group's keyword name.
+ ****/
+ char text[PPD_MAX_TEXT - PPD_MAX_NAME],
+ /* Human-readable group name */
+ name[PPD_MAX_NAME];
+ /* Group name */
+ int num_options; /* Number of options */
+ ppd_option_t *options; /* Options */
+ int num_subgroups; /* Number of sub-groups */
+ struct ppd_group_str *subgroups;
+ /* Sub-groups (max depth = 1) */
+} ppd_group_t;
+
+typedef struct /**** Constraints ****/
+{
+ char option1[PPD_MAX_NAME],
+ /* First keyword */
+ choice1[PPD_MAX_NAME],
+ /* First option/choice (blank for all) */
+ option2[PPD_MAX_NAME],
+ /* Second keyword */
+ choice2[PPD_MAX_NAME];
+ /* Second option/choice (blank for all) */
+} ppd_const_t;
+
+typedef struct /**** Page Sizes ****/
+{
+ int marked; /* Page size selected? */
+ char name[PPD_MAX_NAME];
+ /* Media size option */
+ float width, /* Width of media in points */
+ length, /* Length of media in points */
+ left, /* Left printable margin in points */
+ bottom, /* Bottom printable margin in points */
+ right, /* Right printable margin in points */
+ top; /* Top printable margin in points */
+} ppd_size_t;
+
+typedef struct /**** Emulators ****/
+{
+ char name[PPD_MAX_NAME],
+ /* Emulator name */
+ *start, /* Code to switch to this emulation */
+ *stop; /* Code to stop this emulation */
+} ppd_emul_t;
+
+typedef struct /**** sRGB Color Profiles ****/
+{
+ char resolution[PPD_MAX_NAME],
+ /* Resolution or "-" */
+ media_type[PPD_MAX_NAME];
+ /* Media type of "-" */
+ float density, /* Ink density to use */
+ gamma, /* Gamma correction to use */
+ matrix[3][3]; /* Transform matrix */
+} ppd_profile_t;
+
+typedef struct /**** Files ****/
+{
+ int language_level, /* Language level of device */
+ color_device, /* 1 = color device, 0 = grayscale */
+ variable_sizes, /* 1 = supports variable sizes, 0 = doesn't */
+ accurate_screens,/* 1 = supports accurate screens, 0 = not */
+ contone_only, /* 1 = continuous tone only, 0 = not */
+ landscape, /* -90 or 90 */
+ model_number, /* Device-specific model number */
+ manual_copies, /* 1 = Copies done manually, 0 = hardware */
+ throughput; /* Pages per minute */
+ ppd_cs_t colorspace; /* Default colorspace */
+ char *patches; /* Patch commands to be sent to printer */
+ int num_emulations; /* Number of emulations supported */
+ ppd_emul_t *emulations; /* Emulations and the code to invoke them */
+ char *jcl_begin, /* Start JCL commands */
+ *jcl_ps, /* Enter PostScript interpreter */
+ *jcl_end, /* End JCL commands */
+ *lang_encoding, /* Language encoding */
+ *lang_version, /* Language version (English, Spanish, etc.) */
+ *modelname, /* Model name (general) */
+ *ttrasterizer, /* Truetype rasterizer */
+ *manufacturer, /* Manufacturer name */
+ *product, /* Product name (from PS RIP/interpreter) */
+ *nickname, /* Nickname (specific) */
+ *shortnickname; /* Short version of nickname */
+ int num_groups; /* Number of UI groups */
+ ppd_group_t *groups; /* UI groups */
+ int num_sizes; /* Number of page sizes */
+ ppd_size_t *sizes; /* Page sizes */
+ float custom_min[2], /* Minimum variable page size */
+ custom_max[2], /* Maximum variable page size */
+ custom_margins[4];/* Margins around page */
+ int num_consts; /* Number of UI/Non-UI constraints */
+ ppd_const_t *consts; /* UI/Non-UI constraints */
+ int num_fonts; /* Number of pre-loaded fonts */
+ char **fonts; /* Pre-loaded fonts */
+ int num_profiles; /* Number of sRGB color profiles */
+ ppd_profile_t *profiles; /* sRGB color profiles */
+ int num_filters; /* Number of filters */
+ char **filters; /* Filter strings... */
+
+ /**** New in CUPS 1.1 ****/
+ int flip_duplex; /* 1 = Flip page for back sides */
+
+ /**** New in CUPS 1.1.19 ****/
+ char *protocols, /* Protocols (BCP, TBCP) string */
+ *pcfilename; /* PCFileName string */
+ int num_attrs, /* Number of attributes */
+ cur_attr; /* Current attribute */
+ ppd_attr_t **attrs; /* Attributes */
+} ppd_file_t;
+
+
+/*
+ * Prototypes...
+ */
+
+extern void ppdClose(ppd_file_t *ppd);
+extern int ppdCollect(ppd_file_t *ppd, ppd_section_t section,
+ ppd_choice_t ***choices);
+extern int ppdConflicts(ppd_file_t *ppd);
+extern int ppdEmit(ppd_file_t *ppd, FILE *fp,
+ ppd_section_t section);
+extern int ppdEmitFd(ppd_file_t *ppd, int fd,
+ ppd_section_t section);
+extern int ppdEmitJCL(ppd_file_t *ppd, FILE *fp, int job_id,
+ const char *user, const char *title);
+extern ppd_choice_t *ppdFindChoice(ppd_option_t *o, const char *option);
+extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword);
+extern ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword);
+extern int ppdIsMarked(ppd_file_t *ppd, const char *keyword,
+ const char *option);
+extern void ppdMarkDefaults(ppd_file_t *ppd);
+extern int ppdMarkOption(ppd_file_t *ppd, const char *keyword,
+ const char *option);
+extern ppd_file_t *ppdOpen(FILE *fp);
+extern ppd_file_t *ppdOpenFd(int fd);
+extern ppd_file_t *ppdOpenFile(const char *filename);
+extern float ppdPageLength(ppd_file_t *ppd, const char *name);
+extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name);
+extern float ppdPageWidth(ppd_file_t *ppd, const char *name);
+
+/**** New in CUPS 1.1.19 ****/
+extern const char *ppdErrorString(ppd_status_t status);
+extern ppd_attr_t *ppdFindAttr(ppd_file_t *ppd, const char *name,
+ const char *spec);
+extern ppd_attr_t *ppdFindNextAttr(ppd_file_t *ppd, const char *name,
+ const char *spec);
+extern ppd_status_t ppdLastError(int *line);
+
+/**** New in CUPS 1.1.20 ****/
+extern void ppdSetConformance(ppd_conform_t c);
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+#endif /* !_CUPS_PPD_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/snprintf.c b/cups/snprintf.c
new file mode 100644
index 000000000..faa4e2ee9
--- /dev/null
+++ b/cups/snprintf.c
@@ -0,0 +1,344 @@
+/*
+ * "$Id$"
+ *
+ * snprintf functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cups_vsnprintf() - Format a string into a fixed size buffer.
+ * cups_snprintf() - Format a string into a fixed size buffer.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "string.h"
+
+
+#ifndef HAVE_VSNPRINTF
+/*
+ * 'cups_vsnprintf()' - Format a string into a fixed size buffer.
+ */
+
+int /* O - Number of bytes formatted */
+cups_vsnprintf(char *buffer, /* O - Output buffer */
+ size_t bufsize, /* O - Size of output buffer */
+ const char *format, /* I - printf-style format string */
+ va_list ap) /* I - Pointer to additional arguments */
+{
+ char *bufptr, /* Pointer to position in buffer */
+ *bufend, /* Pointer to end of buffer */
+ sign, /* Sign of format width */
+ size, /* Size character (h, l, L) */
+ type; /* Format type character */
+ const char *bufformat; /* Start of format */
+ int width, /* Width of field */
+ prec; /* Number of characters of precision */
+ char tformat[100], /* Temporary format string for sprintf() */
+ temp[1024]; /* Buffer for formatted numbers */
+ char *s; /* Pointer to string */
+ int slen; /* Length of string */
+ int bytes; /* Total number of bytes needed */
+
+
+ /*
+ * Loop through the format string, formatting as needed...
+ */
+
+ bufptr = buffer;
+ bufend = buffer + bufsize - 1;
+ bytes = 0;
+
+ while (*format)
+ {
+ if (*format == '%')
+ {
+ bufformat = format;
+ format ++;
+
+ if (*format == '%')
+ {
+ *bufptr++ = *format++;
+ continue;
+ }
+ else if (strchr(" -+#\'", *format))
+ sign = *format++;
+ else
+ sign = 0;
+
+ width = 0;
+ while (isdigit(*format))
+ width = width * 10 + *format++ - '0';
+
+ if (*format == '.')
+ {
+ format ++;
+ prec = 0;
+
+ while (isdigit(*format))
+ prec = prec * 10 + *format++ - '0';
+ }
+ else
+ prec = -1;
+
+ if (*format == 'l' && format[1] == 'l')
+ {
+ size = 'L';
+ format += 2;
+ }
+ else if (*format == 'h' || *format == 'l' || *format == 'L')
+ size = *format++;
+
+ if (!*format)
+ break;
+
+ type = *format++;
+
+ switch (type)
+ {
+ case 'E' : /* Floating point formats */
+ case 'G' :
+ case 'e' :
+ case 'f' :
+ case 'g' :
+ if ((format - bufformat + 1) > sizeof(tformat) ||
+ (width + 2) > sizeof(temp))
+ break;
+
+ strncpy(tformat, bufformat, format - bufformat);
+ tformat[format - bufformat] = '\0';
+
+ sprintf(temp, tformat, va_arg(ap, double));
+
+ bytes += strlen(temp);
+
+ if (bufptr)
+ {
+ if ((bufptr + strlen(temp)) > bufend)
+ {
+ strncpy(bufptr, temp, bufend - bufptr);
+ bufptr = bufend;
+ break;
+ }
+ else
+ {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'B' : /* Integer formats */
+ case 'X' :
+ case 'b' :
+ case 'd' :
+ case 'i' :
+ case 'o' :
+ case 'u' :
+ case 'x' :
+ if ((format - bufformat + 1) > sizeof(tformat) ||
+ (width + 2) > sizeof(temp))
+ break;
+
+ strncpy(tformat, bufformat, format - bufformat);
+ tformat[format - bufformat] = '\0';
+
+ sprintf(temp, tformat, va_arg(ap, int));
+
+ bytes += strlen(temp);
+
+ if (bufptr)
+ {
+ if ((bufptr + strlen(temp)) > bufend)
+ {
+ strncpy(bufptr, temp, bufend - bufptr);
+ bufptr = bufend;
+ break;
+ }
+ else
+ {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'p' : /* Pointer value */
+ if ((format - bufformat + 1) > sizeof(tformat) ||
+ (width + 2) > sizeof(temp))
+ break;
+
+ strncpy(tformat, bufformat, format - bufformat);
+ tformat[format - bufformat] = '\0';
+
+ sprintf(temp, tformat, va_arg(ap, void *));
+
+ bytes += strlen(temp);
+
+ if (bufptr)
+ {
+ if ((bufptr + strlen(temp)) > bufend)
+ {
+ strncpy(bufptr, temp, bufend - bufptr);
+ bufptr = bufend;
+ break;
+ }
+ else
+ {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+
+ case 'c' : /* Character or character array */
+ bytes += width;
+
+ if (bufptr)
+ {
+ if (width <= 1)
+ *bufptr++ = va_arg(ap, int);
+ else
+ {
+ if ((bufptr + width) > bufend)
+ width = bufend - bufptr;
+
+ memcpy(bufptr, va_arg(ap, char *), width);
+ bufptr += width;
+ }
+ }
+ break;
+
+ case 's' : /* String */
+ if ((s = va_arg(ap, char *)) == NULL)
+ s = "(null)";
+
+ slen = strlen(s);
+ if (slen > width && prec != width)
+ width = slen;
+
+ bytes += width;
+
+ if (bufptr)
+ {
+ if ((bufptr + width) > bufend)
+ width = bufend - bufptr;
+
+ if (slen > width)
+ slen = width;
+
+ if (sign == '-')
+ {
+ strncpy(bufptr, s, slen);
+ memset(bufptr + slen, ' ', width - slen);
+ }
+ else
+ {
+ memset(bufptr, ' ', width - slen);
+ strncpy(bufptr + width - slen, s, slen);
+ }
+
+ bufptr += width;
+ }
+ break;
+
+ case 'n' : /* Output number of chars so far */
+ if ((format - bufformat + 1) > sizeof(tformat) ||
+ (width + 2) > sizeof(temp))
+ break;
+
+ strncpy(tformat, bufformat, format - bufformat);
+ tformat[format - bufformat] = '\0';
+
+ sprintf(temp, tformat, va_arg(ap, int));
+
+ bytes += strlen(temp);
+
+ if (bufptr)
+ {
+ if ((bufptr + strlen(temp)) > bufend)
+ {
+ strncpy(bufptr, temp, bufend - bufptr);
+ bufptr = bufend;
+ break;
+ }
+ else
+ {
+ strcpy(bufptr, temp);
+ bufptr += strlen(temp);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ bytes ++;
+
+ if (bufptr && bufptr < bufend)
+ *bufptr++ = *format++;
+ }
+ }
+
+ /*
+ * Nul-terminate the string and return the number of characters needed.
+ */
+
+ *bufptr = '\0';
+
+ return (bytes);
+}
+#endif /* !HAVE_VSNPRINT */
+
+
+#ifndef HAVE_SNPRINTF
+/*
+ * 'cups_snprintf()' - Format a string into a fixed size buffer.
+ */
+
+int /* O - Number of bytes formatted */
+cups_snprintf(char *buffer, /* O - Output buffer */
+ size_t bufsize, /* O - Size of output buffer */
+ const char *format, /* I - printf-style format string */
+ ...) /* I - Additional arguments as needed */
+{
+ int bytes; /* Number of bytes formatted */
+ va_list ap; /* Pointer to additional arguments */
+
+
+ va_start(ap, format);
+ bytes = vsnprintf(buffer, bufsize, format, ap);
+ va_end(ap);
+
+ return (bytes);
+}
+#endif /* !HAVE_SNPRINTF */
+
+
+/*
+ * End of "$Id$".
+ */
+
diff --git a/cups/string.c b/cups/string.c
new file mode 100644
index 000000000..b2e6f2f5c
--- /dev/null
+++ b/cups/string.c
@@ -0,0 +1,226 @@
+/*
+ * "$Id$"
+ *
+ * String functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cups_strcpy() - Copy a string allowing for overlapping strings.
+ * cups_strdup() - Duplicate a string.
+ * cups_strcasecmp() - Do a case-insensitive comparison.
+ * cups_strncasecmp() - Do a case-insensitive comparison on up to N chars.
+ * cups_strlcat() - Safely concatenate two strings.
+ * cups_strlcpy() - Safely copy two strings.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "string.h"
+
+
+/*
+ * 'cups_strcpy()' - Copy a string allowing for overlapping strings.
+ */
+
+void
+cups_strcpy(char *dst, /* I - Destination string */
+ const char *src) /* I - Source string */
+{
+ while (*src)
+ *dst++ = *src++;
+
+ *dst = '\0';
+}
+
+
+/*
+ * 'cups_strdup()' - Duplicate a string.
+ */
+
+#ifndef HAVE_STRDUP
+char * /* O - New string pointer */
+cups_strdup(const char *s) /* I - String to duplicate */
+{
+ char *t; /* New string pointer */
+
+
+ if (s == NULL)
+ return (NULL);
+
+ if ((t = malloc(strlen(s) + 1)) == NULL)
+ return (NULL);
+
+ return (strcpy(t, s));
+}
+#endif /* !HAVE_STRDUP */
+
+
+/*
+ * 'cups_strcasecmp()' - Do a case-insensitive comparison.
+ */
+
+#ifndef HAVE_STRCASECMP
+int /* O - Result of comparison (-1, 0, or 1) */
+cups_strcasecmp(const char *s, /* I - First string */
+ const char *t) /* I - Second string */
+{
+ while (*s != '\0' && *t != '\0')
+ {
+ if (tolower(*s & 255) < tolower(*t & 255))
+ return (-1);
+ else if (tolower(*s & 255) > tolower(*t & 255))
+ return (1);
+
+ s ++;
+ t ++;
+ }
+
+ if (*s == '\0' && *t == '\0')
+ return (0);
+ else if (*s != '\0')
+ return (1);
+ else
+ return (-1);
+}
+#endif /* !HAVE_STRCASECMP */
+
+/*
+ * 'cups_strncasecmp()' - Do a case-insensitive comparison on up to N chars.
+ */
+
+#ifndef HAVE_STRNCASECMP
+int /* O - Result of comparison (-1, 0, or 1) */
+cups_strncasecmp(const char *s, /* I - First string */
+ const char *t, /* I - Second string */
+ size_t n) /* I - Maximum number of characters to compare */
+{
+ while (*s != '\0' && *t != '\0' && n > 0)
+ {
+ if (tolower(*s & 255) < tolower(*t & 255))
+ return (-1);
+ else if (tolower(*s & 255) > tolower(*t & 255))
+ return (1);
+
+ s ++;
+ t ++;
+ n --;
+ }
+
+ if (n == 0)
+ return (0);
+ else if (*s == '\0' && *t == '\0')
+ return (0);
+ else if (*s != '\0')
+ return (1);
+ else
+ return (-1);
+}
+#endif /* !HAVE_STRNCASECMP */
+
+
+#ifndef HAVE_STRLCAT
+/*
+ * 'cups_strlcat()' - Safely concatenate two strings.
+ */
+
+size_t /* O - Length of string */
+cups_strlcat(char *dst, /* O - Destination string */
+ const char *src, /* I - Source string */
+ size_t size) /* I - Size of destination string buffer */
+{
+ size_t srclen; /* Length of source string */
+ size_t dstlen; /* Length of destination string */
+
+
+ /*
+ * Figure out how much room is left...
+ */
+
+ dstlen = strlen(dst);
+ size -= dstlen + 1;
+
+ if (!size)
+ return (dstlen); /* No room, return immediately... */
+
+ /*
+ * Figure out how much room is needed...
+ */
+
+ srclen = strlen(src);
+
+ /*
+ * Copy the appropriate amount...
+ */
+
+ if (srclen > size)
+ srclen = size;
+
+ memcpy(dst + dstlen, src, srclen);
+ dst[dstlen + srclen] = '\0';
+
+ return (dstlen + srclen);
+}
+#endif /* !HAVE_STRLCAT */
+
+
+#ifndef HAVE_STRLCPY
+/*
+ * 'cups_strlcpy()' - Safely copy two strings.
+ */
+
+size_t /* O - Length of string */
+cups_strlcpy(char *dst, /* O - Destination string */
+ const char *src, /* I - Source string */
+ size_t size) /* I - Size of destination string buffer */
+{
+ size_t srclen; /* Length of source string */
+
+
+ /*
+ * Figure out how much room is needed...
+ */
+
+ size --;
+
+ srclen = strlen(src);
+
+ /*
+ * Copy the appropriate amount...
+ */
+
+ if (srclen > size)
+ srclen = size;
+
+ memcpy(dst, src, srclen);
+ dst[srclen] = '\0';
+
+ return (srclen);
+}
+#endif /* !HAVE_STRLCPY */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/string.h b/cups/string.h
new file mode 100644
index 000000000..3c618d27d
--- /dev/null
+++ b/cups/string.h
@@ -0,0 +1,130 @@
+/*
+ * "$Id$"
+ *
+ * String definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_STRING_H_
+# define _CUPS_STRING_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <config.h>
+
+# include <stdio.h>
+# include <stdarg.h>
+# include <ctype.h>
+
+# ifdef HAVE_STRING_H
+# include <string.h>
+# endif /* HAVE_STRING_H */
+
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif /* HAVE_STRINGS_H */
+
+# ifdef HAVE_BSTRING_H
+# include <bstring.h>
+# endif /* HAVE_BSTRING_H */
+
+
+/*
+ * Stuff for WIN32 and OS/2...
+ */
+
+# if defined(WIN32) || defined(__EMX__)
+# define strcasecmp stricmp
+# define strncasecmp strnicmp
+# endif /* WIN32 || __EMX__ */
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void cups_strcpy(char *dst, const char *src);
+
+# ifndef HAVE_STRDUP
+extern char *cups_strdup(const char *);
+# define strdup cups_strdup
+# endif /* !HAVE_STRDUP */
+
+# ifndef HAVE_STRCASECMP
+extern int cups_strcasecmp(const char *, const char *);
+# define strcasecmp cups_strcasecmp
+# endif /* !HAVE_STRCASECMP */
+
+# ifndef HAVE_STRNCASECMP
+extern int cups_strncasecmp(const char *, const char *, size_t n);
+# define strncasecmp cups_strncasecmp
+# endif /* !HAVE_STRNCASECMP */
+
+# ifndef HAVE_STRLCAT
+extern size_t cups_strlcat(char *, const char *, size_t);
+# define strlcat cups_strlcat
+# endif /* !HAVE_STRLCAT */
+
+# ifndef HAVE_STRLCPY
+extern size_t cups_strlcpy(char *, const char *, size_t);
+# define strlcpy cups_strlcpy
+# endif /* !HAVE_STRLCPY */
+
+# ifndef HAVE_SNPRINTF
+extern int cups_snprintf(char *, size_t, const char *, ...)
+# ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 3, 4)))
+# endif /* __GNUC__ */
+;
+# define snprintf cups_snprintf
+# endif /* !HAVE_SNPRINTF */
+
+# ifndef HAVE_VSNPRINTF
+extern int cups_vsnprintf(char *, size_t, const char *, va_list);
+# define vsnprintf cups_vsnprintf
+# endif /* !HAVE_VSNPRINTF */
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+
+#endif /* !_CUPS_STRING_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/tempfile.c b/cups/tempfile.c
new file mode 100644
index 000000000..447951d79
--- /dev/null
+++ b/cups/tempfile.c
@@ -0,0 +1,221 @@
+/*
+ * "$Id$"
+ *
+ * Temp file utilities for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsTempFd() - Create a temporary file.
+ * cupsTempFile() - Generate a temporary filename.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * 'cupsTempFd()' - Create a temporary file.
+ */
+
+int /* O - New file descriptor */
+cupsTempFd(char *filename, /* I - Pointer to buffer */
+ int len) /* I - Size of buffer */
+{
+ int fd; /* File descriptor for temp file */
+ int tries; /* Number of tries */
+ const char *tmpdir; /* TMPDIR environment var */
+#ifdef WIN32
+ char tmppath[1024]; /* Windows temporary directory */
+ DWORD curtime; /* Current time */
+#else
+ struct timeval curtime; /* Current time */
+#endif /* WIN32 */
+ static char *buf = NULL; /* Buffer if you pass in NULL and 0 */
+
+
+ /*
+ * See if a filename was specified...
+ */
+
+ if (filename == NULL)
+ {
+ if (buf == NULL)
+ buf = calloc(1024, sizeof(char));
+
+ if (buf == NULL)
+ return (-1);
+
+ filename = buf;
+ len = 1024;
+ }
+
+ /*
+ * See if TMPDIR is defined...
+ */
+
+#ifdef WIN32
+ if ((tmpdir = getenv("TEMP")) == NULL)
+ {
+ GetTempPath(sizeof(tmppath), tmppath);
+ tmpdir = tmppath;
+ }
+#else
+ if ((tmpdir = getenv("TMPDIR")) == NULL)
+ {
+ /*
+ * Put root temp files in restricted temp directory...
+ */
+
+ if (getuid() == 0)
+ tmpdir = CUPS_REQUESTS "/tmp";
+ else
+ tmpdir = "/var/tmp";
+ }
+#endif /* WIN32 */
+
+ /*
+ * Make the temporary name using the specified directory...
+ */
+
+ tries = 0;
+
+ do
+ {
+#ifdef WIN32
+ /*
+ * Get the current time of day...
+ */
+
+ curtime = GetTickCount() + tries;
+
+ /*
+ * Format a string using the hex time values...
+ */
+
+ snprintf(filename, len - 1, "%s/%05lx%08lx", tmpdir,
+ GetCurrentProcessId(), curtime);
+#else
+ /*
+ * Get the current time of day...
+ */
+
+ gettimeofday(&curtime, NULL);
+
+ /*
+ * Format a string using the hex time values...
+ */
+
+ snprintf(filename, len - 1, "%s/%08lx%05lx", tmpdir,
+ (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec);
+#endif /* WIN32 */
+
+ /*
+ * Open the file in "exclusive" mode, making sure that we don't
+ * stomp on an existing file or someone's symlink crack...
+ */
+
+#ifdef WIN32
+ fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY,
+ _S_IREAD | _S_IWRITE);
+#elif defined(O_NOFOLLOW)
+ fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
+#else
+ fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+#endif /* WIN32 */
+
+ if (fd < 0 && errno != EEXIST)
+ break;
+
+ tries ++;
+ }
+ while (fd < 0 && tries < 1000);
+
+ /*
+ * Return the file descriptor...
+ */
+
+ return (fd);
+}
+
+
+/*
+ * 'cupsTempFile()' - Generate a temporary filename.
+ */
+
+char * /* O - Filename */
+cupsTempFile(char *filename, /* I - Pointer to buffer */
+ int len) /* I - Size of buffer */
+{
+ int fd; /* File descriptor for temp file */
+ static char buf[1024] = ""; /* Buffer if you pass in NULL and 0 */
+
+
+ /*
+ * See if a filename was specified...
+ */
+
+ if (filename == NULL)
+ {
+ filename = buf;
+ len = sizeof(buf);
+ }
+
+ /*
+ * Create the temporary file...
+ */
+
+ if ((fd = cupsTempFd(filename, len)) < 0)
+ return (NULL);
+
+ /*
+ * Close the temp file - it'll be reopened later as needed...
+ */
+
+ close(fd);
+
+ /*
+ * Return the temp filename...
+ */
+
+ return (filename);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/testhttp.c b/cups/testhttp.c
new file mode 100644
index 000000000..9530392b7
--- /dev/null
+++ b/cups/testhttp.c
@@ -0,0 +1,127 @@
+/*
+ * "$Id$"
+ *
+ * HTTP test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "http.h"
+
+
+/*
+ * 'main()' - Main entry.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ http_t *http; /* HTTP connection */
+ http_status_t status; /* Status of GET command */
+ char buffer[8192]; /* Input buffer */
+ long bytes; /* Number of bytes read */
+ FILE *out; /* Output file */
+ char host[HTTP_MAX_URI],
+ method[HTTP_MAX_URI],
+ username[HTTP_MAX_URI],
+ resource[HTTP_MAX_URI];
+ int port;
+ long length, total;
+ time_t start, current;
+
+
+
+ http = NULL;
+ out = stdout;
+
+ for (i = 1; i < argc; i ++)
+ {
+ if (strcmp(argv[i], "-o") == 0)
+ {
+ i ++;
+ out = fopen(argv[i], "wb");
+ continue;
+ }
+
+ httpSeparate(argv[i], method, username, host, &port, resource);
+
+ http = httpConnect(host, port);
+ if (http == NULL)
+ {
+ perror(host);
+ continue;
+ }
+ printf("Requesting file \"%s\"...\n", resource);
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
+ httpGet(http, resource);
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_OK)
+ puts("GET OK:");
+ else
+ printf("GET failed with status %d...\n", status);
+
+
+ start = time(NULL);
+ length = atoi(httpGetField(http, HTTP_FIELD_CONTENT_LENGTH));
+ total = 0;
+
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ {
+ total += bytes;
+ fwrite(buffer, bytes, 1, out);
+ if (out != stdout)
+ {
+ current = time(NULL);
+ if (current == start) current ++;
+ printf("\r%ld/%ld bytes (%ld bytes/sec) ", total, length,
+ total / (current - start));
+ fflush(stdout);
+ }
+ }
+ }
+
+ puts("Closing connection to server...");
+ httpClose(http);
+
+ if (out != stdout)
+ fclose(out);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/testipp.c b/cups/testipp.c
new file mode 100644
index 000000000..c3d8113b8
--- /dev/null
+++ b/cups/testipp.c
@@ -0,0 +1,521 @@
+/*
+ * "$Id$"
+ *
+ * IPP test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/string.h>
+#include <errno.h>
+#include "ipp.h"
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+#endif /* WIN32 */
+
+
+/*
+ * Local globals...
+ */
+
+int rpos; /* Current position in buffer */
+ipp_uchar_t wbuffer[8192]; /* Write buffer */
+int wused; /* Number of bytes in buffer */
+ipp_uchar_t collection[] = /* Collection buffer */
+ {
+ 0x01, 0x01, /* IPP version */
+ 0x00, 0x02, /* Print-Job operation */
+ 0x00, 0x00, 0x00, 0x01, /* Request ID */
+ IPP_TAG_OPERATION,
+ IPP_TAG_CHARSET,
+ 0x00, 0x12, /* Name length + name */
+ 'a','t','t','r','i','b','u','t','e','s','-',
+ 'c','h','a','r','s','e','t',
+ 0x00, 0x05, /* Value length + value */
+ 'u','t','f','-','8',
+ IPP_TAG_LANGUAGE,
+ 0x00, 0x1b, /* Name length + name */
+ 'a','t','t','r','i','b','u','t','e','s','-',
+ 'n','a','t','u','r','a','l','-','l','a','n',
+ 'g','u','a','g','e',
+ 0x00, 0x02, /* Value length + value */
+ 'e','n',
+ IPP_TAG_URI,
+ 0x00, 0x0b, /* Name length + name */
+ 'p','r','i','n','t','e','r','-','u','r','i',
+ 0x00, 0x1c, /* Value length + value */
+ 'i','p','p',':','/','/','l','o','c','a','l',
+ 'h','o','s','t','/','p','r','i','n','t','e',
+ 'r','s','/','f','o','o',
+ IPP_TAG_JOB, /* job group tag */
+ IPP_TAG_BEGIN_COLLECTION, /* begCollection tag */
+ 0x00, 0x09, /* Name length + name */
+ 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l',
+ 0x00, 0x00, /* No value */
+ IPP_TAG_MEMBERNAME, /* memberAttrName tag */
+ 0x00, 0x00, /* No name */
+ 0x00, 0x0b, /* Value length + value */
+ 'm', 'e', 'd', 'i', 'a', '-', 'c', 'o', 'l', 'o', 'r',
+ IPP_TAG_KEYWORD, /* keyword tag */
+ 0x00, 0x00, /* No name */
+ 0x00, 0x04, /* Value length + value */
+ 'b', 'l', 'u', 'e',
+ IPP_TAG_END_COLLECTION, /* endCollection tag */
+ 0x00, 0x00, /* No name */
+ 0x00, 0x00, /* No value */
+ IPP_TAG_END /* end tag */
+ };
+
+
+/*
+ * Local functions...
+ */
+
+void hex_dump(ipp_uchar_t *buffer, int bytes);
+void print_attributes(ipp_t *ipp, int indent);
+int read_cb(void *data, ipp_uchar_t *buffer, int bytes);
+int write_cb(void *data, ipp_uchar_t *buffer, int bytes);
+
+
+/*
+ * 'main()' - Main entry.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ ipp_t *col; /* Collection */
+ ipp_t *request; /* Request */
+ ipp_state_t state; /* State */
+ int length; /* Length of data */
+ int fd; /* File descriptor */
+ int i; /* Looping var */
+
+
+ request = ippNew();
+ request->request.op.version[0] = 0x01;
+ request->request.op.version[1] = 0x01;
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, "utf-8");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, "en");
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "ipp://localhost/printers/foo");
+
+ col = ippNew();
+ ippAddString(col, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue");
+ ippAddCollection(request, IPP_TAG_JOB, "media-col", col);
+
+ length = ippLength(request);
+ if (length != sizeof(collection))
+ printf("ERROR ippLength didn't compute the correct length (%d instead of %d bytes!)\n",
+ length, sizeof(collection));
+
+ wused = 0;
+ while ((state = ippWriteIO(wbuffer, write_cb, 1, NULL, request)) != IPP_DATA)
+ if (state == IPP_ERROR)
+ break;
+
+ if (state != IPP_DATA)
+ puts("ERROR writing collection attribute!");
+
+ printf("%d bytes written:\n", wused);
+ hex_dump(wbuffer, wused);
+
+ if (wused != sizeof(collection))
+ {
+ printf("ERROR expected %d bytes!\n", sizeof(collection));
+ hex_dump(collection, sizeof(collection));
+ }
+ else if (memcmp(wbuffer, collection, wused))
+ {
+ puts("ERROR output does not match baseline!");
+ hex_dump(collection, sizeof(collection));
+ }
+
+ ippDelete(col);
+ ippDelete(request);
+
+ request = ippNew();
+ rpos = 0;
+
+ while ((state = ippReadIO(wbuffer, read_cb, 1, NULL, request)) != IPP_DATA)
+ if (state == IPP_ERROR)
+ break;
+
+ if (state != IPP_DATA)
+ puts("ERROR reading collection attribute!");
+
+ printf("%d bytes read.\n", rpos);
+
+ puts("Core IPP tests passed.");
+
+ for (i = 1; i < argc; i ++)
+ {
+ if ((fd = open(argv[i], O_RDONLY)) < 0)
+ {
+ printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno));
+ continue;
+ }
+
+ request = ippNew();
+ while ((state = ippReadFile(fd, request)) == IPP_ATTRIBUTE);
+
+ if (state != IPP_DATA)
+ printf("Error reading IPP message from \"%s\"!\n", argv[i]);
+ else
+ {
+ printf("\n%s:\n", argv[i]);
+ print_attributes(request, 4);
+ }
+
+ ippDelete(request);
+ close(fd);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'hex_dump()' - Produce a hex dump of a buffer.
+ */
+
+void
+hex_dump(ipp_uchar_t *buffer, /* I - Buffer to dump */
+ int bytes) /* I - Number of bytes */
+{
+ int i, j; /* Looping vars */
+ int ch; /* Current ASCII char */
+
+
+ /*
+ * Show lines of 16 bytes at a time...
+ */
+
+ for (i = 0; i < bytes; i += 16)
+ {
+ /*
+ * Show the offset...
+ */
+
+ printf("%04x ", i);
+
+ /*
+ * Then up to 16 bytes in hex...
+ */
+
+ for (j = 0; j < 16; j ++)
+ if ((i + j) < bytes)
+ printf(" %02x", buffer[i + j]);
+ else
+ printf(" ");
+
+ /*
+ * Then the ASCII representation of the bytes...
+ */
+
+ putchar(' ');
+ putchar(' ');
+
+ for (j = 0; j < 16 && (i + j) < bytes; j ++)
+ {
+ ch = buffer[i + j] & 127;
+
+ if (ch < ' ' || ch == 127)
+ putchar('.');
+ else
+ putchar(ch);
+ }
+
+ putchar('\n');
+ }
+}
+
+
+/*
+ * 'print_attributes()' - Print the attributes in a request...
+ */
+
+void
+print_attributes(ipp_t *ipp, /* I - IPP request */
+ int indent) /* I - Indentation */
+{
+ int i; /* Looping var */
+ ipp_tag_t group; /* Current group */
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_value_t *val; /* Current value */
+ static const char * const tags[] = /* Value/group tag strings */
+ {
+ "reserved-00",
+ "operation-attributes-tag",
+ "job-attributes-tag",
+ "end-of-attributes-tag",
+ "printer-attributes-tag",
+ "unsupported-attributes-tag",
+ "subscription-attributes-tag",
+ "event-attributes-tag",
+ "reserved-08",
+ "reserved-09",
+ "reserved-0A",
+ "reserved-0B",
+ "reserved-0C",
+ "reserved-0D",
+ "reserved-0E",
+ "reserved-0F",
+ "unsupported",
+ "default",
+ "unknown",
+ "no-value",
+ "reserved-14",
+ "not-settable",
+ "delete-attr",
+ "admin-define",
+ "reserved-18",
+ "reserved-19",
+ "reserved-1A",
+ "reserved-1B",
+ "reserved-1C",
+ "reserved-1D",
+ "reserved-1E",
+ "reserved-1F",
+ "reserved-20",
+ "integer",
+ "boolean",
+ "enum",
+ "reserved-24",
+ "reserved-25",
+ "reserved-26",
+ "reserved-27",
+ "reserved-28",
+ "reserved-29",
+ "reserved-2a",
+ "reserved-2b",
+ "reserved-2c",
+ "reserved-2d",
+ "reserved-2e",
+ "reserved-2f",
+ "octetString",
+ "dateTime",
+ "resolution",
+ "rangeOfInteger",
+ "begCollection",
+ "textWithLanguage",
+ "nameWithLanguage",
+ "endCollection",
+ "reserved-38",
+ "reserved-39",
+ "reserved-3a",
+ "reserved-3b",
+ "reserved-3c",
+ "reserved-3d",
+ "reserved-3e",
+ "reserved-3f",
+ "reserved-40",
+ "textWithoutLanguage",
+ "nameWithoutLanguage",
+ "reserved-43",
+ "keyword",
+ "uri",
+ "uriScheme",
+ "charset",
+ "naturalLanguage",
+ "mimeMediaType",
+ "memberName"
+ };
+
+
+ for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
+ {
+ if (attr->group_tag == IPP_TAG_ZERO || !attr->name)
+ {
+ group = IPP_TAG_ZERO;
+ putchar('\n');
+ continue;
+ }
+
+ if (group != attr->group_tag)
+ {
+ group = attr->group_tag;
+
+ putchar('\n');
+ for (i = 2; i < indent; i ++)
+ putchar(' ');
+
+ printf("%s:\n\n", tags[group]);
+ }
+
+ for (i = 0; i < indent; i ++)
+ putchar(' ');
+
+ printf("%s (%s):", attr->name, tags[attr->value_tag]);
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_ENUM :
+ case IPP_TAG_INTEGER :
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ printf(" %d", val->integer);
+ putchar('\n');
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ printf(" %s", val->boolean ? "true" : "false");
+ putchar('\n');
+ break;
+
+ case IPP_TAG_RANGE :
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ printf(" %d-%d", val->range.lower, val->range.upper);
+ putchar('\n');
+ break;
+
+ case IPP_TAG_DATE :
+ {
+ time_t vtime; /* Date/Time value */
+ struct tm *vdate; /* Date info */
+ char vstring[256]; /* Formatted time */
+
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ {
+ vtime = ippDateToTime(val->date);
+ vdate = localtime(&vtime);
+ strftime(vstring, sizeof(vstring), "%c", vdate);
+ printf(" (%s)", vstring);
+ }
+ }
+ putchar('\n');
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
+ val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc");
+ putchar('\n');
+ break;
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ printf(" \"%s\"", val->string.text);
+ putchar('\n');
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ putchar('\n');
+
+ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
+ print_attributes(val->collection, indent + 4);
+ break;
+
+ default :
+ putchar('\n');
+ break;
+ }
+
+ }
+}
+
+
+/*
+ * 'read_cb()' - Read data from a buffer.
+ */
+
+int /* O - Number of bytes read */
+read_cb(void *data, /* I - Data */
+ ipp_uchar_t *buffer, /* O - Buffer to read */
+ int bytes) /* I - Number of bytes to read */
+{
+ int count; /* Number of bytes */
+
+
+ /*
+ * Copy bytes from the data buffer to the read buffer...
+ */
+
+ for (count = bytes; count > 0 && rpos < wused; count --, rpos ++)
+ *buffer++ = wbuffer[rpos];
+
+ /*
+ * Return the number of bytes read...
+ */
+
+ return (bytes - count);
+}
+
+
+/*
+ * 'write_cb()' - Write data into a buffer.
+ */
+
+int /* O - Number of bytes written */
+write_cb(void *data, /* I - Data */
+ ipp_uchar_t *buffer, /* I - Buffer to write */
+ int bytes) /* I - Number of bytes to write */
+{
+ int count; /* Number of bytes */
+
+
+ /*
+ * Loop until all bytes are written...
+ */
+
+ for (count = bytes; count > 0 && wused < sizeof(wbuffer); count --, wused ++)
+ wbuffer[wused] = *buffer++;
+
+ /*
+ * Return the number of bytes written...
+ */
+
+ return (bytes - count);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/testlang.c b/cups/testlang.c
new file mode 100644
index 000000000..064d1b1e1
--- /dev/null
+++ b/cups/testlang.c
@@ -0,0 +1,119 @@
+/*
+ * "$Id$"
+ *
+ * Localization test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Load the specified language and show the strings for yes and no.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include "language.h"
+
+
+/*
+ * 'main()' - Load the specified language and show the strings for yes and no.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ cups_lang_t *language; /* Message catalog */
+ cups_lang_t *language2; /* Message catalog */
+ static const char * const charsets[] =/* Character sets */
+ {
+ "us-ascii",
+ "iso-8859-1",
+ "iso-8859-2",
+ "iso-8859-3",
+ "iso-8859-4",
+ "iso-8859-5",
+ "iso-8859-6",
+ "iso-8859-7",
+ "iso-8859-8",
+ "iso-8859-9",
+ "iso-8859-10",
+ "utf-8",
+ "iso8859-13",
+ "iso8859-14",
+ "iso8859-15",
+ "windows-874",
+ "windows-1250",
+ "windows-1251",
+ "windows-1252",
+ "windows-1253",
+ "windows-1254",
+ "windows-1255",
+ "windows-1256",
+ "windows-1257",
+ "windows-1258",
+ "koi8-r",
+ "koi8-u"
+ };
+
+
+ if (argc == 1)
+ {
+ language = cupsLangDefault();
+ language2 = cupsLangDefault();
+ }
+ else
+ {
+ language = cupsLangGet(argv[1]);
+ language2 = cupsLangGet(argv[1]);
+ }
+
+ if (language != language2)
+ {
+ puts("**** ERROR: Language cache did not work! ****");
+ puts("First result from cupsLangGet:");
+ }
+
+ printf("Language = \"%s\"\n", language->language);
+ printf("Encoding = \"%s\"\n", charsets[language->encoding]);
+ printf("No = \"%s\"\n", cupsLangString(language, CUPS_MSG_NO));
+ printf("Yes = \"%s\"\n", cupsLangString(language, CUPS_MSG_YES));
+
+ if (language != language2)
+ {
+ puts("Second result from cupsLangGet:");
+
+ printf("Language = \"%s\"\n", language2->language);
+ printf("Encoding = \"%s\"\n", charsets[language2->encoding]);
+ printf("No = \"%s\"\n", cupsLangString(language2, CUPS_MSG_NO));
+ printf("Yes = \"%s\"\n", cupsLangString(language2, CUPS_MSG_YES));
+ }
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/testmime.dsp b/cups/testmime.dsp
new file mode 100644
index 000000000..33fbd301a
--- /dev/null
+++ b/cups/testmime.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="testmime" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=testmime - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "testmime.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "testmime.mak" CFG="testmime - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "testmime - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "testmime - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "testmime - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testmime.exe"
+
+!ELSEIF "$(CFG)" == "testmime - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "testmime___Win32_Debug"
+# PROP BASE Intermediate_Dir "testmime___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../visualc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testmimed.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "testmime - Win32 Release"
+# Name "testmime - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\testmime.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\mime.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/cups/testppd.dsp b/cups/testppd.dsp
new file mode 100644
index 000000000..27d4f035c
--- /dev/null
+++ b/cups/testppd.dsp
@@ -0,0 +1,102 @@
+# Microsoft Developer Studio Project File - Name="testppd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=testppd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "testppd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "testppd.mak" CFG="testppd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "testppd - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "testppd - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "testppd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"testppd.exe"
+
+!ELSEIF "$(CFG)" == "testppd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "testppd___Win32_Debug"
+# PROP BASE Intermediate_Dir "testppd___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /I "../visualc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"testppdd.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "testppd - Win32 Release"
+# Name "testppd - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\testppd.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ppd.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/cups/usersys.c b/cups/usersys.c
new file mode 100644
index 000000000..effd5d1ef
--- /dev/null
+++ b/cups/usersys.c
@@ -0,0 +1,460 @@
+/*
+ * "$Id$"
+ *
+ * User, system, and password routines for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsEncryption() - Get the default encryption settings...
+ * cupsGetPassword() - Get a password from the user...
+ * cupsServer() - Return the hostname of the default server...
+ * cupsSetEncryption() - Set the encryption preference.
+ * cupsSetPasswordCB() - Set the password callback for CUPS.
+ * cupsSetServer() - Set the default server name...
+ * cupsSetUser() - Set the default user name...
+ * cupsUser() - Return the current users name.
+ * cups_get_password() - Get a password from the user...
+ * cups_get_line() - Get a line from a file...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "string.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef WIN32
+# include <windows.h>
+#endif /* WIN32 */
+
+
+/*
+ * Local functions...
+ */
+
+static const char *cups_get_password(const char *prompt);
+static char *cups_get_line(char *buf, int buflen, FILE *fp);
+
+
+/*
+ * Local globals...
+ */
+
+static http_encryption_t cups_encryption = (http_encryption_t)-1;
+static char cups_user[65] = "",
+ cups_server[256] = "";
+static const char *(*cups_pwdcb)(const char *) = cups_get_password;
+
+
+/*
+ * 'cupsEncryption()' - Get the default encryption settings...
+ */
+
+http_encryption_t
+cupsEncryption(void)
+{
+ FILE *fp; /* client.conf file */
+ char *encryption; /* CUPS_ENCRYPTION variable */
+ const char *home; /* Home directory of user */
+ char line[1024]; /* Line from file */
+
+
+ /*
+ * First see if we have already set the encryption stuff...
+ */
+
+ if (cups_encryption == (http_encryption_t)-1)
+ {
+ /*
+ * Then see if the CUPS_ENCRYPTION environment variable is set...
+ */
+
+ if ((encryption = getenv("CUPS_ENCRYPTION")) == NULL)
+ {
+ /*
+ * Next check to see if we have a $HOME/.cupsrc or client.conf file...
+ */
+
+ if ((home = getenv("HOME")) != NULL)
+ {
+ snprintf(line, sizeof(line), "%s/.cupsrc", home);
+ fp = fopen(line, "r");
+ }
+ else
+ fp = NULL;
+
+ if (fp == NULL)
+ {
+ if ((home = getenv("CUPS_SERVERROOT")) != NULL)
+ {
+ snprintf(line, sizeof(line), "%s/client.conf", home);
+ fp = fopen(line, "r");
+ }
+ else
+ fp = fopen(CUPS_SERVERROOT "/client.conf", "r");
+ }
+
+ encryption = "IfRequested";
+
+ if (fp != NULL)
+ {
+ /*
+ * Read the config file and look for an Encryption line...
+ */
+
+ while (cups_get_line(line, sizeof(line), fp) != NULL)
+ if (strncmp(line, "Encryption ", 11) == 0 ||
+ strncmp(line, "Encryption\t", 11) == 0)
+ {
+ /*
+ * Got it! Drop any trailing newline and find the name...
+ */
+
+ encryption = line + strlen(line) - 1;
+ if (*encryption == '\n')
+ *encryption = '\0';
+
+ for (encryption = line + 11; isspace(*encryption & 255); encryption ++);
+ break;
+ }
+
+ fclose(fp);
+ }
+ }
+
+ /*
+ * Set the encryption preference...
+ */
+
+ if (strcasecmp(encryption, "never") == 0)
+ cups_encryption = HTTP_ENCRYPT_NEVER;
+ else if (strcasecmp(encryption, "always") == 0)
+ cups_encryption = HTTP_ENCRYPT_ALWAYS;
+ else if (strcasecmp(encryption, "required") == 0)
+ cups_encryption = HTTP_ENCRYPT_REQUIRED;
+ else
+ cups_encryption = HTTP_ENCRYPT_IF_REQUESTED;
+ }
+
+ return (cups_encryption);
+}
+
+
+/*
+ * 'cupsGetPassword()' - Get a password from the user...
+ */
+
+const char * /* O - Password */
+cupsGetPassword(const char *prompt) /* I - Prompt string */
+{
+ return ((*cups_pwdcb)(prompt));
+}
+
+
+/*
+ * 'cupsSetEncryption()' - Set the encryption preference.
+ */
+
+void
+cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */
+{
+ cups_encryption = e;
+}
+
+
+/*
+ * 'cupsServer()' - Return the hostname of the default server...
+ */
+
+const char * /* O - Server name */
+cupsServer(void)
+{
+ FILE *fp; /* client.conf file */
+ char *server; /* Pointer to server name */
+ const char *home; /* Home directory of user */
+ char line[1024]; /* Line from file */
+
+
+ /*
+ * First see if we have already set the server name...
+ */
+
+ if (!cups_server[0])
+ {
+ /*
+ * Then see if the CUPS_SERVER environment variable is set...
+ */
+
+ if ((server = getenv("CUPS_SERVER")) == NULL)
+ {
+ /*
+ * Next check to see if we have a $HOME/.cupsrc or client.conf file...
+ */
+
+ if ((home = getenv("HOME")) != NULL)
+ {
+ snprintf(line, sizeof(line), "%s/.cupsrc", home);
+ fp = fopen(line, "r");
+ }
+ else
+ fp = NULL;
+
+ if (fp == NULL)
+ {
+ if ((home = getenv("CUPS_SERVERROOT")) != NULL)
+ {
+ snprintf(line, sizeof(line), "%s/client.conf", home);
+ fp = fopen(line, "r");
+ }
+ else
+ fp = fopen(CUPS_SERVERROOT "/client.conf", "r");
+ }
+
+ server = "localhost";
+
+ if (fp != NULL)
+ {
+ /*
+ * Read the config file and look for a ServerName line...
+ */
+
+ while (cups_get_line(line, sizeof(line), fp) != NULL)
+ if (strncmp(line, "ServerName ", 11) == 0 ||
+ strncmp(line, "ServerName\t", 11) == 0)
+ {
+ /*
+ * Got it! Drop any trailing newline and find the name...
+ */
+
+ server = line + strlen(line) - 1;
+ if (*server == '\n')
+ *server = '\0';
+
+ for (server = line + 11; isspace(*server & 255); server ++);
+ break;
+ }
+
+ fclose(fp);
+ }
+ }
+
+ /*
+ * Copy the server name over...
+ */
+
+ strlcpy(cups_server, server, sizeof(cups_server));
+ }
+
+ return (cups_server);
+}
+
+
+/*
+ * 'cupsSetPasswordCB()' - Set the password callback for CUPS.
+ */
+
+void
+cupsSetPasswordCB(const char *(*cb)(const char *)) /* I - Callback function */
+{
+ if (cb == (const char *(*)(const char *))0)
+ cups_pwdcb = cups_get_password;
+ else
+ cups_pwdcb = cb;
+}
+
+
+/*
+ * 'cupsSetServer()' - Set the default server name...
+ */
+
+void
+cupsSetServer(const char *server) /* I - Server name */
+{
+ if (server)
+ strlcpy(cups_server, server, sizeof(cups_server));
+ else
+ cups_server[0] = '\0';
+}
+
+
+/*
+ * 'cupsSetUser()' - Set the default user name...
+ */
+
+void
+cupsSetUser(const char *user) /* I - User name */
+{
+ if (user)
+ strlcpy(cups_user, user, sizeof(cups_user));
+ else
+ cups_user[0] = '\0';
+}
+
+
+#if defined(WIN32)
+/*
+ * WIN32 username and password stuff...
+ */
+
+/*
+ * 'cupsUser()' - Return the current user's name.
+ */
+
+const char * /* O - User name */
+cupsUser(void)
+{
+ if (!cups_user[0])
+ {
+ DWORD size; /* Size of string */
+
+
+ size = sizeof(cups_user);
+ if (!GetUserName(cups_user, &size))
+ {
+ /*
+ * Use the default username...
+ */
+
+ strcpy(cups_user, "unknown");
+ }
+ }
+
+ return (cups_user);
+}
+
+
+/*
+ * 'cups_get_password()' - Get a password from the user...
+ */
+
+static const char * /* O - Password */
+cups_get_password(const char *prompt) /* I - Prompt string */
+{
+ return (NULL);
+}
+#else
+/*
+ * UNIX username and password stuff...
+ */
+
+# include <pwd.h>
+
+/*
+ * 'cupsUser()' - Return the current user's name.
+ */
+
+const char * /* O - User name */
+cupsUser(void)
+{
+ struct passwd *pwd; /* User/password entry */
+
+
+ if (!cups_user[0])
+ {
+ /*
+ * Rewind the password file...
+ */
+
+ setpwent();
+
+ /*
+ * Lookup the password entry for the current user.
+ */
+
+ if ((pwd = getpwuid(getuid())) == NULL)
+ strcpy(cups_user, "unknown"); /* Unknown user! */
+ else
+ {
+ /*
+ * Copy the username...
+ */
+
+ setpwent();
+
+ strlcpy(cups_user, pwd->pw_name, sizeof(cups_user));
+ }
+
+ /*
+ * Rewind the password file again...
+ */
+
+ setpwent();
+ }
+
+ return (cups_user);
+}
+
+
+/*
+ * 'cups_get_password()' - Get a password from the user...
+ */
+
+static const char * /* O - Password */
+cups_get_password(const char *prompt) /* I - Prompt string */
+{
+ return (getpass(prompt));
+}
+#endif /* WIN32 */
+
+
+/*
+ * 'cups_get_line()' - Get a line from a file.
+ */
+
+static char * /* O - Line from file */
+cups_get_line(char *buf, /* I - Line buffer */
+ int buflen, /* I - Size of line buffer */
+ FILE *fp) /* I - File to read from */
+{
+ char *bufptr; /* Pointer to end of buffer */
+
+
+ /*
+ * Get the line from a file...
+ */
+
+ if (fgets(buf, buflen, fp) == NULL)
+ return (NULL);
+
+ /*
+ * Remove all trailing whitespace...
+ */
+
+ bufptr = buf + strlen(buf) - 1;
+ if (bufptr < buf)
+ return (NULL);
+
+ while (bufptr >= buf && isspace(*bufptr & 255))
+ *bufptr-- = '\0';
+
+ return (buf);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/cups/util.c b/cups/util.c
new file mode 100644
index 000000000..b7a820fa6
--- /dev/null
+++ b/cups/util.c
@@ -0,0 +1,1712 @@
+/*
+ * "$Id$"
+ *
+ * Printing utilities for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsCancelJob() - Cancel a print job.
+ * cupsDoFileRequest() - Do an IPP request...
+ * cupsFreeJobs() - Free memory used by job data.
+ * cupsGetClasses() - Get a list of printer classes.
+ * cupsGetDefault() - Get the default printer or class.
+ * cupsGetDefault2() - Get the default printer or class.
+ * cupsGetJobs() - Get the jobs from the server.
+ * cupsGetJobs2() - Get the jobs from the server.
+ * cupsGetPPD() - Get the PPD file for a printer.
+ * cupsGetPPD2() - Get the PPD file for a printer.
+ * cupsGetPrinters() - Get a list of printers.
+ * cupsLastError() - Return the last IPP error that occurred.
+ * cupsPrintFile() - Print a file to a printer or class.
+ * cupsPrintFile2() - Print a file to a printer or class.
+ * cupsPrintFiles() - Print one or more files to a printer or class.
+ * cupsPrintFiles2() - Print one or more files to a printer or class.
+ * cups_connect() - Connect to the specified host...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * Local globals...
+ */
+
+static http_t *cups_server = NULL; /* Current server connection */
+static ipp_status_t last_error = IPP_OK; /* Last IPP error */
+
+
+/*
+ * Local functions...
+ */
+
+static char *cups_connect(const char *name, char *printer, char *hostname);
+
+
+/*
+ * 'cupsCancelJob()' - Cancel a print job.
+ */
+
+int /* O - 1 on success, 0 on failure */
+cupsCancelJob(const char *name, /* I - Name of printer or class */
+ int job) /* I - Job ID */
+{
+ char printer[HTTP_MAX_URI], /* Printer name */
+ hostname[HTTP_MAX_URI], /* Hostname */
+ uri[HTTP_MAX_URI]; /* Printer URI */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ cups_lang_t *language; /* Language info */
+
+
+ /*
+ * See if we can connect to the server...
+ */
+
+ if (!cups_connect(name, printer, hostname))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Build an IPP_CANCEL_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * job-id
+ * [requesting-user-name]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_CANCEL_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ cupsLangFree(language);
+
+ snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ /*
+ * Do the request...
+ */
+
+ if ((response = cupsDoRequest(cups_server, request, "/jobs/")) != NULL)
+ ippDelete(response);
+
+ return (last_error < IPP_REDIRECTION_OTHER_SITE);
+}
+
+
+/*
+ * 'cupsDoFileRequest()' - Do an IPP request...
+ */
+
+ipp_t * /* O - Response data */
+cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
+ ipp_t *request, /* I - IPP request */
+ const char *resource, /* I - HTTP resource for POST */
+ const char *filename) /* I - File to send or NULL */
+{
+ ipp_t *response; /* IPP response data */
+ char length[255]; /* Content-Length field */
+ http_status_t status; /* Status of HTTP request */
+ FILE *file; /* File to send */
+ struct stat fileinfo; /* File information */
+ int bytes; /* Number of bytes read/written */
+ char buffer[32768]; /* Output buffer */
+
+
+ DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
+ http, request, resource ? resource : "(null)",
+ filename ? filename : "(null)"));
+
+ if (http == NULL || request == NULL || resource == NULL)
+ {
+ if (request != NULL)
+ ippDelete(request);
+
+ last_error = IPP_INTERNAL_ERROR;
+ return (NULL);
+ }
+
+ /*
+ * See if we have a file to send...
+ */
+
+ if (filename != NULL)
+ {
+ if (stat(filename, &fileinfo))
+ {
+ /*
+ * Can't get file information!
+ */
+
+ ippDelete(request);
+ last_error = IPP_NOT_FOUND;
+ return (NULL);
+ }
+
+#ifdef WIN32
+ if (fileinfo.st_mode & _S_IFDIR)
+#else
+ if (S_ISDIR(fileinfo.st_mode))
+#endif /* WIN32 */
+ {
+ /*
+ * Can't send a directory...
+ */
+
+ ippDelete(request);
+ last_error = IPP_NOT_POSSIBLE;
+ return (NULL);
+ }
+
+ if ((file = fopen(filename, "rb")) == NULL)
+ {
+ /*
+ * Can't open file!
+ */
+
+ ippDelete(request);
+ last_error = IPP_NOT_FOUND;
+ return (NULL);
+ }
+ }
+ else
+ file = NULL;
+
+ /*
+ * Loop until we can send the request without authorization problems.
+ */
+
+ response = NULL;
+ status = HTTP_ERROR;
+
+ while (response == NULL)
+ {
+ DEBUG_puts("cupsDoFileRequest: setup...");
+
+ /*
+ * Setup the HTTP variables needed...
+ */
+
+ if (filename != NULL)
+ sprintf(length, "%lu", (unsigned long)(ippLength(request) +
+ (size_t)fileinfo.st_size));
+ else
+ sprintf(length, "%lu", (unsigned long)ippLength(request));
+
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
+ httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+
+ DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+
+ /*
+ * Try the request...
+ */
+
+ DEBUG_puts("cupsDoFileRequest: post...");
+
+ if (httpPost(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ continue;
+ }
+
+ /*
+ * Send the IPP data and wait for the response...
+ */
+
+ DEBUG_puts("cupsDoFileRequest: ipp write...");
+
+ request->state = IPP_IDLE;
+ status = HTTP_CONTINUE;
+
+ if (ippWrite(http, request) != IPP_ERROR)
+ if (filename != NULL)
+ {
+ DEBUG_puts("cupsDoFileRequest: file write...");
+
+ /*
+ * Send the file...
+ */
+
+ rewind(file);
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0)
+ {
+ if (httpCheck(http))
+ {
+ if ((status = httpUpdate(http)) != HTTP_CONTINUE)
+ break;
+ }
+
+ if (httpWrite(http, buffer, bytes) < bytes)
+ break;
+ }
+ }
+
+ /*
+ * Get the server's return status...
+ */
+
+ DEBUG_puts("cupsDoFileRequest: update...");
+
+ while (status == HTTP_CONTINUE)
+ status = httpUpdate(http);
+
+ DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ DEBUG_puts("cupsDoFileRequest: unauthorized...");
+
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * See if we can do authentication...
+ */
+
+ if (cupsDoAuthentication(http, "POST", resource))
+ break;
+
+ httpReconnect(http);
+
+ continue;
+ }
+ else if (status == HTTP_ERROR)
+ {
+#ifdef WIN32
+ if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
+#else
+ if (http->error != ENETDOWN && http->error != ENETUNREACH)
+#endif /* WIN32 */
+ continue;
+ else
+ break;
+ }
+#ifdef HAVE_SSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /* Flush any error message... */
+ httpFlush(http);
+
+ /* Reconnect... */
+ httpReconnect(http);
+
+ /* Upgrade with encryption... */
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ /* Try again, this time with encryption enabled... */
+ continue;
+ }
+#endif /* HAVE_SSL */
+ else if (status != HTTP_OK)
+ {
+ DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+ break;
+ }
+ else
+ {
+ /*
+ * Read the response...
+ */
+
+ DEBUG_puts("cupsDoFileRequest: response...");
+
+ response = ippNew();
+
+ if (ippRead(http, response) == IPP_ERROR)
+ {
+ /*
+ * Delete the response...
+ */
+
+ DEBUG_puts("IPP read error!");
+ ippDelete(response);
+ response = NULL;
+
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Close the file if needed...
+ */
+
+ if (filename != NULL)
+ fclose(file);
+
+ /*
+ * Flush any remaining data...
+ */
+
+ httpFlush(http);
+
+ /*
+ * Delete the original request and return the response...
+ */
+
+ ippDelete(request);
+
+ if (response)
+ last_error = response->request.status.status_code;
+ else if (status != HTTP_OK)
+ {
+ switch (status)
+ {
+ case HTTP_NOT_FOUND :
+ last_error = IPP_NOT_FOUND;
+ break;
+
+ case HTTP_UNAUTHORIZED :
+ last_error = IPP_NOT_AUTHORIZED;
+ break;
+
+ case HTTP_FORBIDDEN :
+ last_error = IPP_FORBIDDEN;
+ break;
+
+ case HTTP_BAD_REQUEST :
+ last_error = IPP_BAD_REQUEST;
+ break;
+
+ case HTTP_REQUEST_TOO_LARGE :
+ last_error = IPP_REQUEST_VALUE;
+ break;
+
+ case HTTP_NOT_IMPLEMENTED :
+ last_error = IPP_OPERATION_NOT_SUPPORTED;
+ break;
+
+ case HTTP_NOT_SUPPORTED :
+ last_error = IPP_VERSION_NOT_SUPPORTED;
+ break;
+
+ default :
+ DEBUG_printf(("HTTP error %d mapped to IPP_SERVICE_UNAVAILABLE!\n",
+ status));
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ break;
+ }
+ }
+
+ return (response);
+}
+
+
+/*
+ * 'cupsFreeJobs()' - Free memory used by job data.
+ */
+
+void
+cupsFreeJobs(int num_jobs, /* I - Number of jobs */
+ cups_job_t *jobs) /* I - Jobs */
+{
+ int i; /* Looping var */
+
+
+ if (num_jobs <= 0 || jobs == NULL)
+ return;
+
+ for (i = 0; i < num_jobs; i ++)
+ {
+ free(jobs[i].dest);
+ free(jobs[i].user);
+ free(jobs[i].format);
+ free(jobs[i].title);
+ }
+
+ free(jobs);
+}
+
+
+/*
+ * 'cupsGetClasses()' - Get a list of printer classes.
+ */
+
+int /* O - Number of classes */
+cupsGetClasses(char ***classes) /* O - Classes */
+{
+ int n; /* Number of classes */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ char **temp; /* Temporary pointer */
+
+
+ if (classes == NULL)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (0);
+ }
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if (!cups_connect("default", NULL, NULL))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Build a CUPS_GET_CLASSES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_CLASSES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-name");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ n = 0;
+ *classes = NULL;
+
+ if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ if (attr->name != NULL &&
+ strcasecmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ {
+ if (n == 0)
+ temp = malloc(sizeof(char *));
+ else
+ temp = realloc(*classes, sizeof(char *) * (n + 1));
+
+ if (temp == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ while (n > 0)
+ {
+ n --;
+ free((*classes)[n]);
+ }
+
+ free(*classes);
+ ippDelete(response);
+ return (0);
+ }
+
+ *classes = temp;
+ temp[n] = strdup(attr->values[0].string.text);
+ n ++;
+ }
+
+ ippDelete(response);
+ }
+ else
+ last_error = IPP_BAD_REQUEST;
+
+ return (n);
+}
+
+
+/*
+ * 'cupsGetDefault()' - Get the default printer or class.
+ */
+
+const char * /* O - Default printer or NULL */
+cupsGetDefault(void)
+{
+ const char *var; /* Environment variable */
+
+
+ /*
+ * First see if the LPDEST or PRINTER environment variables are
+ * set... However, if PRINTER is set to "lp", ignore it to work
+ * around a "feature" in most Linux distributions - the default
+ * user login scripts set PRINTER to "lp"...
+ */
+
+ if ((var = getenv("LPDEST")) != NULL)
+ return (var);
+ else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
+ return (var);
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if (!cups_connect("default", NULL, NULL))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (NULL);
+ }
+
+ /*
+ * Return the default printer...
+ */
+
+ return (cupsGetDefault2(cups_server));
+}
+
+
+/*
+ * 'cupsGetDefault2()' - Get the default printer or class.
+ */
+
+const char * /* O - Default printer or NULL */
+cupsGetDefault2(http_t *http) /* I - HTTP connection */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *var; /* Environment variable */
+ static char def_printer[256]; /* Default printer */
+
+
+ /*
+ * First see if the LPDEST or PRINTER environment variables are
+ * set... However, if PRINTER is set to "lp", ignore it to work
+ * around a "feature" in most Linux distributions - the default
+ * user login scripts set PRINTER to "lp"...
+ */
+
+ if ((var = getenv("LPDEST")) != NULL)
+ return (var);
+ else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
+ return (var);
+
+ /*
+ * Range check input...
+ */
+
+ if (!http)
+ return (NULL);
+
+ /*
+ * Build a CUPS_GET_DEFAULT request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_DEFAULT;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
+ {
+ strlcpy(def_printer, attr->values[0].string.text, sizeof(def_printer));
+ ippDelete(response);
+ return (def_printer);
+ }
+
+ ippDelete(response);
+ }
+ else
+ last_error = IPP_BAD_REQUEST;
+
+ return (NULL);
+}
+
+
+/*
+ * 'cupsGetJobs()' - Get the jobs from the server.
+ */
+
+int /* O - Number of jobs */
+cupsGetJobs(cups_job_t **jobs, /* O - Job data */
+ const char *mydest, /* I - Only show jobs for dest? */
+ int myjobs, /* I - Only show my jobs? */
+ int completed) /* I - Only show completed jobs? */
+{
+ /*
+ * Try to connect to the server...
+ */
+
+ if (!cups_connect("default", NULL, NULL))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (-1);
+ }
+
+ /*
+ * Return the jobs...
+ */
+
+ return (cupsGetJobs2(cups_server, jobs, mydest, myjobs, completed));
+}
+
+
+
+/*
+ * 'cupsGetJobs2()' - Get the jobs from the server.
+ */
+
+int /* O - Number of jobs */
+cupsGetJobs2(http_t *http, /* I - HTTP connection */
+ cups_job_t **jobs, /* O - Job data */
+ const char *mydest, /* I - Only show jobs for dest? */
+ int myjobs, /* I - Only show my jobs? */
+ int completed) /* I - Only show completed jobs? */
+{
+ int n; /* Number of jobs */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ cups_job_t *temp; /* Temporary pointer */
+ int id, /* job-id */
+ priority, /* job-priority */
+ size; /* job-k-octets */
+ ipp_jstate_t state; /* job-state */
+ time_t completed_time, /* time-at-completed */
+ creation_time, /* time-at-creation */
+ processing_time; /* time-at-processing */
+ const char *dest, /* job-printer-uri */
+ *format, /* document-format */
+ *title, /* job-name */
+ *user; /* job-originating-user-name */
+ char uri[HTTP_MAX_URI]; /* URI for jobs */
+ static const char * const attrs[] = /* Requested attributes */
+ {
+ "job-id",
+ "job-priority",
+ "job-k-octets",
+ "job-state",
+ "time-at-completed",
+ "time-at-creation",
+ "time-at-processing",
+ "job-printer-uri",
+ "document-format",
+ "job-name",
+ "job-originating-user-name"
+ };
+
+
+ if (!http || !jobs)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (-1);
+ }
+
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ * which-jobs
+ * my-jobs
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ if (mydest)
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", mydest);
+ else
+ strcpy(uri, "ipp://localhost/jobs");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ if (myjobs)
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+
+ if (completed)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "which-jobs", NULL, "completed");
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
+ NULL, attrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ n = 0;
+ *jobs = NULL;
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ id = 0;
+ size = 0;
+ priority = 50;
+ state = IPP_JOB_PENDING;
+ user = "unknown";
+ dest = NULL;
+ format = "application/octet-stream";
+ title = "untitled";
+ creation_time = 0;
+ completed_time = 0;
+ processing_time = 0;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ id = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ state = (ipp_jstate_t)attr->values[0].integer;
+ else if (strcmp(attr->name, "job-priority") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ priority = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ size = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-completed") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ completed_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-creation") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ creation_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-processing") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ processing_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ {
+ if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ dest ++;
+ }
+ else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ user = attr->values[0].string.text;
+ else if (strcmp(attr->name, "document-format") == 0 &&
+ attr->value_tag == IPP_TAG_MIMETYPE)
+ format = attr->values[0].string.text;
+ else if (strcmp(attr->name, "job-name") == 0 &&
+ (attr->value_tag == IPP_TAG_TEXT ||
+ attr->value_tag == IPP_TAG_NAME))
+ title = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (dest == NULL || id == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * Allocate memory for the job...
+ */
+
+ if (n == 0)
+ temp = malloc(sizeof(cups_job_t));
+ else
+ temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
+
+ if (temp == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ cupsFreeJobs(n, *jobs);
+ *jobs = NULL;
+
+ ippDelete(response);
+ return (0);
+ }
+
+ *jobs = temp;
+ temp += n;
+ n ++;
+
+ /*
+ * Copy the data over...
+ */
+
+ temp->dest = strdup(dest);
+ temp->user = strdup(user);
+ temp->format = strdup(format);
+ temp->title = strdup(title);
+ temp->id = id;
+ temp->priority = priority;
+ temp->state = state;
+ temp->size = size;
+ temp->completed_time = completed_time;
+ temp->creation_time = creation_time;
+ temp->processing_time = processing_time;
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ last_error = IPP_BAD_REQUEST;
+
+ if (n == 0 && last_error >= IPP_BAD_REQUEST)
+ return (-1);
+ else
+ return (n);
+}
+
+
+/*
+ * 'cupsGetPPD()' - Get the PPD file for a printer.
+ */
+
+const char * /* O - Filename for PPD file */
+cupsGetPPD(const char *name) /* I - Printer name */
+{
+ /*
+ * See if we can connect to the server...
+ */
+
+ if (!cups_connect(name, NULL, NULL))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (NULL);
+ }
+
+ /*
+ * Return the PPD file...
+ */
+
+ return (cupsGetPPD2(cups_server, name));
+}
+
+
+/*
+ * 'cupsGetPPD2()' - Get the PPD file for a printer.
+ */
+
+const char * /* O - Filename for PPD file */
+cupsGetPPD2(http_t *http, /* I - HTTP connection */
+ const char *name) /* I - Printer name */
+{
+ int i; /* Looping var */
+ http_t *http2; /* Alternate HTTP connection */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Local language */
+ int fd; /* PPD file */
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ printer[HTTP_MAX_URI], /* Printer name */
+ method[HTTP_MAX_URI], /* Method/scheme name */
+ username[HTTP_MAX_URI], /* Username:password */
+ hostname[HTTP_MAX_URI], /* Hostname */
+ resource[HTTP_MAX_URI]; /* Resource name */
+ int port; /* Port number */
+ http_status_t status; /* HTTP status from server */
+ static char filename[HTTP_MAX_URI]; /* Local filename */
+ static const char * const requested_attrs[] =
+ { /* Requested attributes */
+ "printer-uri-supported",
+ "printer-type",
+ "member-uris"
+ };
+
+
+ /*
+ * Range check input...
+ */
+
+ DEBUG_printf(("cupsGetPPD2(http=%p, name=\"%s\")\n", http,
+ name ? name : "(null)"));
+
+ if (!http || !name)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (NULL);
+ }
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ DEBUG_printf(("cupsGetPPD2: printer-uri=\"%s\"\n", uri));
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requested-attributes",
+ sizeof(requested_attrs) / sizeof(requested_attrs[0]),
+ NULL, requested_attrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+ printer[0] = '\0';
+ hostname[0] = '\0';
+
+ if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Get the first actual server and printer name in the class...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ httpSeparate(attr->values[0].string.text, method, username, hostname,
+ &port, resource);
+ if (strncmp(resource, "/printers/", 10) == 0)
+ {
+ /*
+ * Found a printer!
+ */
+
+ strlcpy(printer, resource + 10, sizeof(printer));
+ break;
+ }
+ }
+ }
+ else if ((attr = ippFindAttribute(response, "printer-uri-supported",
+ IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Get the actual server and printer names...
+ */
+
+ httpSeparate(attr->values[0].string.text, method, username, hostname,
+ &port, resource);
+ strlcpy(printer, strrchr(resource, '/') + 1, sizeof(printer));
+ }
+
+ ippDelete(response);
+
+ /*
+ * Remap local hostname to localhost...
+ */
+
+ gethostname(uri, sizeof(uri));
+
+ if (strcasecmp(uri, hostname) == 0)
+ strcpy(hostname, "localhost");
+ }
+
+ if (!printer[0])
+ {
+ last_error = IPP_NOT_FOUND;
+ return (NULL);
+ }
+
+ /*
+ * Reconnect to the correct server as needed...
+ */
+
+ if (!strcasecmp(http->hostname, hostname))
+ http2 = http;
+ else if ((http2 = httpConnectEncrypt(hostname, ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (NULL);
+ }
+
+ /*
+ * Get a temp file...
+ */
+
+ if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
+ {
+ /*
+ * Can't open file; close the server connection and return NULL...
+ */
+
+ last_error = IPP_INTERNAL_ERROR;
+
+ if (http2 != http)
+ httpClose(http2);
+
+ return (NULL);
+ }
+
+ /*
+ * And send a request to the HTTP server...
+ */
+
+ snprintf(resource, sizeof(resource), "/printers/%s.ppd", printer);
+
+ status = cupsGetFd(http2, resource, fd);
+
+ close(fd);
+
+ if (http2 != http)
+ httpClose(http2);
+
+ /*
+ * See if we actually got the file or an error...
+ */
+
+ if (status != HTTP_OK)
+ {
+ switch (status)
+ {
+ case HTTP_NOT_FOUND :
+ last_error = IPP_NOT_FOUND;
+ break;
+ case HTTP_ERROR :
+ DEBUG_puts("Mapping HTTP error to IPP_ERROR");
+ last_error = IPP_ERROR;
+ break;
+ case HTTP_UNAUTHORIZED :
+ last_error = IPP_NOT_AUTHORIZED;
+ break;
+ default :
+ last_error = IPP_INTERNAL_ERROR;
+ break;
+ }
+
+ unlink(filename);
+
+ return (NULL);
+ }
+
+ /*
+ * Return the PPD file...
+ */
+
+ return (filename);
+}
+
+
+/*
+ * 'cupsGetPrinters()' - Get a list of printers.
+ */
+
+int /* O - Number of printers */
+cupsGetPrinters(char ***printers) /* O - Printers */
+{
+ int n; /* Number of printers */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ char **temp; /* Temporary pointer */
+
+
+ if (printers == NULL)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (0);
+ }
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if (!cups_connect("default", NULL, NULL))
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ cupsLangFree(language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-name");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ n = 0;
+ *printers = NULL;
+
+ if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ if (attr->name != NULL &&
+ strcasecmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ {
+ if (n == 0)
+ temp = malloc(sizeof(char *));
+ else
+ temp = realloc(*printers, sizeof(char *) * (n + 1));
+
+ if (temp == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ while (n > 0)
+ {
+ n --;
+ free((*printers)[n]);
+ }
+
+ free(*printers);
+ ippDelete(response);
+ return (0);
+ }
+
+ *printers = temp;
+ temp[n] = strdup(attr->values[0].string.text);
+ n ++;
+ }
+
+ ippDelete(response);
+ }
+ else
+ last_error = IPP_BAD_REQUEST;
+
+ return (n);
+}
+
+
+/*
+ * 'cupsLastError()' - Return the last IPP error that occurred.
+ */
+
+ipp_status_t /* O - IPP error code */
+cupsLastError(void)
+{
+ return (last_error);
+}
+
+/*
+ * 'cupsPrintFile()' - Print a file to a printer or class.
+ */
+
+int /* O - Job ID */
+cupsPrintFile(const char *name, /* I - Printer or class name */
+ const char *filename, /* I - File to print */
+ const char *title, /* I - Title of job */
+ int num_options,/* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ DEBUG_printf(("cupsPrintFile(name=\"%s\", filename=\"%s\", "
+ "title=\"%s\", num_options=%d, options=%p)\n",
+ name, filename, title, num_options, options));
+
+ return (cupsPrintFiles(name, 1, &filename, title, num_options, options));
+}
+
+
+/*
+ * 'cupsPrintFile2()' - Print a file to a printer or class.
+ */
+
+int /* O - Job ID */
+cupsPrintFile2(http_t *http, /* I - HTTP connection */
+ const char *name, /* I - Printer or class name */
+ const char *filename, /* I - File to print */
+ const char *title, /* I - Title of job */
+ int num_options,
+ /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", "
+ "title=\"%s\", num_options=%d, options=%p)\n",
+ http, name, filename, title, num_options, options));
+
+ return (cupsPrintFiles2(http, name, 1, &filename, title, num_options, options));
+}
+
+
+/*
+ * 'cupsPrintFiles()' - Print one or more files to a printer or class.
+ */
+
+int /* O - Job ID */
+cupsPrintFiles(const char *name, /* I - Printer or class name */
+ int num_files, /* I - Number of files */
+ const char **files, /* I - File(s) to print */
+ const char *title, /* I - Title of job */
+ int num_options,
+ /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, "
+ "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
+ name, num_files, files, title, num_options, options));
+
+
+ /*
+ * Setup a connection and request data...
+ */
+
+ if (!cups_connect(name, NULL, NULL))
+ {
+ DEBUG_printf(("cupsPrintFiles: Unable to open connection - %s.\n",
+ strerror(errno)));
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Print the file(s)...
+ */
+
+ return (cupsPrintFiles2(cups_server, name, num_files, files, title,
+ num_options, options));
+}
+
+
+
+/*
+ * 'cupsPrintFiles2()' - Print one or more files to a printer or class.
+ */
+
+int /* O - Job ID */
+cupsPrintFiles2(http_t *http, /* I - HTTP connection */
+ const char *name, /* I - Printer or class name */
+ int num_files,/* I - Number of files */
+ const char **files, /* I - File(s) to print */
+ const char *title, /* I - Title of job */
+ int num_options,
+ /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ int i; /* Looping var */
+ const char *val; /* Pointer to option value */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP job-id attribute */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ cups_lang_t *language; /* Language to use */
+ int jobid; /* New job ID */
+
+
+ DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, "
+ "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
+ http, name, num_files, files, title, num_options, options));
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !name || num_files < 1 || files == NULL)
+ return (0);
+
+ /*
+ * Setup the request data...
+ */
+
+ language = cupsLangDefault();
+
+ /*
+ * Build a standard CUPS URI for the printer and fill the standard IPP
+ * attributes...
+ */
+
+ if ((request = ippNew()) == NULL)
+ return (0);
+
+ request->request.op.operation_id = num_files == 1 ? IPP_PRINT_JOB :
+ IPP_CREATE_JOB;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", http->hostname,
+ ippPort(), name);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ if (title)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+ title);
+
+ /*
+ * Then add all options...
+ */
+
+ cupsEncodeOptions(request, num_options, options);
+
+ /*
+ * Do the request...
+ */
+
+ snprintf(uri, sizeof(uri), "/printers/%s", name);
+
+ if (num_files == 1)
+ response = cupsDoFileRequest(http, request, uri, *files);
+ else
+ response = cupsDoRequest(http, request, uri);
+
+ if (response == NULL)
+ jobid = 0;
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ DEBUG_printf(("IPP response code was 0x%x!\n",
+ response->request.status.status_code));
+ jobid = 0;
+ }
+ else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ DEBUG_puts("No job ID!");
+
+ last_error = IPP_SERVICE_UNAVAILABLE;
+
+ jobid = 0;
+ }
+ else
+ jobid = attr->values[0].integer;
+
+ if (response != NULL)
+ ippDelete(response);
+
+ /*
+ * Handle multiple file jobs if the create-job operation worked...
+ */
+
+ if (jobid > 0 && num_files > 1)
+ for (i = 0; i < num_files; i ++)
+ {
+ /*
+ * Build a standard CUPS URI for the job and fill the standard IPP
+ * attributes...
+ */
+
+ if ((request = ippNew()) == NULL)
+ return (0);
+
+ request->request.op.operation_id = IPP_SEND_DOCUMENT;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s:%d/jobs/%d", http->hostname,
+ ippPort(), jobid);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+ NULL, uri);
+
+ /*
+ * Handle raw print files...
+ */
+
+ if (cupsGetOption("raw", num_options, options))
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/vnd.cups-raw");
+ else if ((val = cupsGetOption("document-format", num_options, options)) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, val);
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
+ NULL, "application/octet-stream");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ /*
+ * Is this the last document?
+ */
+
+ if (i == (num_files - 1))
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+
+ /*
+ * Send the file...
+ */
+
+ snprintf(uri, sizeof(uri), "/printers/%s", name);
+
+ if ((response = cupsDoFileRequest(http, request, uri,
+ files[i])) != NULL)
+ ippDelete(response);
+ }
+
+ cupsLangFree(language);
+
+ return (jobid);
+}
+
+
+/*
+ * 'cups_connect()' - Connect to the specified host...
+ */
+
+static char * /* I - Printer name or NULL */
+cups_connect(const char *name, /* I - Destination (printer[@host]) */
+ char *printer, /* O - Printer name [HTTP_MAX_URI] */
+ char *hostname) /* O - Hostname [HTTP_MAX_URI] */
+{
+ char hostbuf[HTTP_MAX_URI]; /* Name of host */
+
+
+ DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
+
+ if (name == NULL)
+ {
+ last_error = IPP_BAD_REQUEST;
+ return (NULL);
+ }
+
+ /*
+ * All jobs are now queued to cupsServer() to avoid hostname
+ * resolution problems and to ensure that the user sees all
+ * locally queued jobs locally.
+ */
+
+ strlcpy(hostbuf, cupsServer(), sizeof(hostbuf));
+
+ if (hostname != NULL)
+ strlcpy(hostname, hostbuf, HTTP_MAX_URI);
+ else
+ hostname = hostbuf;
+
+ if (printer != NULL)
+ strlcpy(printer, name, HTTP_MAX_URI);
+ else
+ printer = (char *)name;
+
+ if (cups_server != NULL)
+ {
+ if (strcasecmp(cups_server->hostname, hostname) == 0)
+ return (printer);
+
+ httpClose(cups_server);
+ }
+
+ DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
+
+ if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ DEBUG_puts("Unable to connect to server!");
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (NULL);
+ }
+ else
+ return (printer);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/data/HPGLprolog b/data/HPGLprolog
new file mode 100644
index 000000000..3fa6ff1b2
--- /dev/null
+++ b/data/HPGLprolog
@@ -0,0 +1,37 @@
+%%BeginResource: procset hpgltops 1.1 0
+%
+% "$Id: HPGLprolog 3041 2002-12-17 19:00:27Z swdev $"
+%
+% HP-GL/2 filter procset for the Common UNIX Printing System (CUPS).
+%
+% This procset contains the basic drawing commands that are used to
+% reduce output size. Note the 'MP' (make newpath) definition - this
+% should be called 'NP' (newpath), but GhostScript uses the 'NP' name
+% for 'noaccess put' in some of its font files...
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/MO { moveto } bind def
+/LI { lineto } bind def
+/FI { fill } bind def
+/ST { stroke } bind def
+/CP { closepath } bind def
+/MP { newpath } bind def
+/SP { setlinewidth setrgbcolor } bind def
+%%EndResource
diff --git a/data/Makefile b/data/Makefile
new file mode 100644
index 000000000..38fe89561
--- /dev/null
+++ b/data/Makefile
@@ -0,0 +1,103 @@
+#
+# "$Id$"
+#
+# Datafile makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# Data files...
+#
+
+BANNERS = classified \
+ confidential \
+ secret \
+ standard \
+ topsecret \
+ unclassified
+
+CHARSETS = iso-8859-1 \
+ iso-8859-2 \
+ iso-8859-3 \
+ iso-8859-4 \
+ iso-8859-5 \
+ iso-8859-6 \
+ iso-8859-7 \
+ iso-8859-8 \
+ iso-8859-9 \
+ iso-8859-10 \
+ iso-8859-13 \
+ iso-8859-14 \
+ iso-8859-15 \
+ koi8-r \
+ koi8-u \
+ utf-8 \
+ windows-874 \
+ windows-1250 \
+ windows-1251 \
+ windows-1252 \
+ windows-1253 \
+ windows-1254 \
+ windows-1255 \
+ windows-1256 \
+ windows-1257 \
+ windows-1258
+
+DATAFILES = HPGLprolog psglyphs testprint.ps
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/banners
+ for file in $(BANNERS); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/banners; \
+ done
+ $(INSTALL_DIR) $(DATADIR)/charsets
+ for file in $(CHARSETS); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/charsets; \
+ done
+ $(INSTALL_DIR) $(DATADIR)/data
+ for file in $(DATAFILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/data; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/data/classified b/data/classified
new file mode 100644
index 000000000..b6cd2db91
--- /dev/null
+++ b/data/classified
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ (Classified) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ (Classified) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: classified 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/confidential b/data/confidential
new file mode 100644
index 000000000..0066a9d48
--- /dev/null
+++ b/data/confidential
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ (Confidential) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ (Confidential) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: confidential 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/iso-8859-1 b/data/iso-8859-1
new file mode 100644
index 000000000..90fd31209
--- /dev/null
+++ b/data/iso-8859-1
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-1
+# (Latin1/West European) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00BA
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 00D0
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 00DD
+DE 00DE
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 00F0
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 00FD
+FE 00FE
+FF 00FF
diff --git a/data/iso-8859-10 b/data/iso-8859-10
new file mode 100644
index 000000000..8aca211d9
--- /dev/null
+++ b/data/iso-8859-10
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-10
+# (Latin6/Nordic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 0104
+A2 0112
+A3 0122
+A4 012A
+A5 0128
+A6 0136
+A7 00A7
+A8 013B
+A9 0110
+AA 0160
+AB 0166
+AC 017D
+AD 00AD
+AE 016A
+AF 014A
+B0 00B0
+B1 0105
+B2 0113
+B3 0123
+B4 012B
+B5 0129
+B6 0137
+B7 00B7
+B8 013C
+B9 0111
+BA 0161
+BB 0167
+BC 017E
+BD 2015
+BE 016B
+BF 014B
+C0 0100
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 012E
+C8 010C
+C9 00C9
+CA 0118
+CB 00CB
+CC 0116
+CD 00CD
+CE 00CE
+CF 00CF
+D0 0110
+D1 0145
+D2 014C
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 0168
+D8 00D8
+D9 0172
+DA 00DA
+DB 00DB
+DC 00DC
+DD 00DD
+DE 00DE
+DF 00DF
+E0 0101
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 012F
+E8 010D
+E9 00E9
+EA 0119
+EB 00EB
+EC 0117
+ED 00ED
+EE 00EE
+EF 00EF
+F0 00F0
+F1 0146
+F2 014D
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 0169
+F8 00F8
+F9 0173
+FA 00FA
+FB 00FB
+FC 00FC
+FD 00FD
+FE 00FD
+FF 0138
diff --git a/data/iso-8859-13 b/data/iso-8859-13
new file mode 100644
index 000000000..1736fc57d
--- /dev/null
+++ b/data/iso-8859-13
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-13
+# (Latin7/Baltic Rim) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 201D
+A2 00A2
+A3 00A3
+A4 00A4
+A5 201E
+A6 00A6
+A7 00A7
+A8 00D8
+A9 00A9
+AA 0156
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00C6
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 201C
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00F8
+B9 00B9
+BA 0157
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00E6
+C0 0104
+C1 012E
+C2 0100
+C3 0106
+C4 00C4
+C5 00C5
+C6 0118
+C7 0112
+C8 010C
+C9 00C9
+CA 0179
+CB 0116
+CC 0122
+CD 0136
+CE 012A
+CF 013B
+D0 0160
+D1 0143
+D2 0145
+D3 00D3
+D4 014C
+D5 00D5
+D6 00D6
+D7 00D7
+D8 0172
+D9 0141
+DA 015A
+DB 016A
+DC 00DC
+DD 017B
+DE 017D
+DF 00DF
+E0 0105
+E1 012F
+E2 0101
+E3 0107
+E4 00E4
+E5 00E5
+E6 0119
+E7 0113
+E8 010D
+E9 00E9
+EA 017A
+EB 0117
+EC 0123
+ED 0137
+EE 012B
+EF 013C
+F0 0161
+F1 0144
+F2 0146
+F3 00F3
+F4 014D
+F5 00F5
+F6 00F6
+F7 00F7
+F8 0173
+F9 0142
+FA 015B
+FB 016B
+FC 00FC
+FD 017C
+FE 017E
+FF 2019
diff --git a/data/iso-8859-14 b/data/iso-8859-14
new file mode 100644
index 000000000..460f1c2e0
--- /dev/null
+++ b/data/iso-8859-14
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-14
+# (Latin8/Celtic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 1E02
+A2 1E03
+A3 00A3
+A4 010A
+A5 010B
+A6 1E0A
+A7 00A7
+A8 1E80
+A9 00A9
+AA 1E82
+AB 1E0B
+AC 1EF2
+AD 00AD
+AE 00AE
+AF 0178
+B0 1E1E
+B1 1E1F
+B2 0120
+B3 0121
+B4 1E40
+B5 1E41
+B6 00B6
+B7 1E56
+B8 1E81
+B9 1E57
+BA 1E83
+BB 1E60
+BC 1EF3
+BD 1E84
+BE 1E85
+BF 1E61
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 0174
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 1E6A
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 00DD
+DE 0176
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 0175
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 1E6B
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 00FD
+FE 0177
+FF 00FF
diff --git a/data/iso-8859-15 b/data/iso-8859-15
new file mode 100644
index 000000000..b7ce82bde
--- /dev/null
+++ b/data/iso-8859-15
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-15
+# (Latin9/West Europe + Euro) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 20AC
+A5 00A5
+A6 0160
+A7 00A7
+A8 0161
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 017D
+B5 00B5
+B6 00B6
+B7 00B7
+B8 017E
+B9 00B9
+BA 00BA
+BB 00BB
+BC 0152
+BD 0153
+BE 0178
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 00D0
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 00DD
+DE 00DE
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 00F0
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 00FD
+FE 00FE
+FF 00FF
diff --git a/data/iso-8859-2 b/data/iso-8859-2
new file mode 100644
index 000000000..b5f3c852c
--- /dev/null
+++ b/data/iso-8859-2
@@ -0,0 +1,253 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-2
+# (Latin2/East European) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+84 201E
+85 2026
+86 2020
+87 2021
+89 2030
+8A 0160
+8B 2039
+8C 015A
+8D 0164
+8E 017D
+8F 0179
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+99 2122
+9A 0161
+9B 203A
+8C 015B
+8D 0165
+8E 017E
+8F 017A
+A0 00A0
+A1 0104
+A2 02D8
+A3 0141
+A4 00A4
+A5 013D
+A6 015A
+A7 00A7
+A8 00A8
+A9 0160
+AA 015E
+AB 0164
+AC 0179
+AD 00AD
+AE 017D
+AF 017B
+B0 00B0
+B1 0105
+B2 02DB
+B3 0142
+B4 00B4
+B5 013E
+B6 015B
+B7 02C7
+B8 00B8
+B9 0161
+BA 015F
+BB 0165
+BC 017A
+BD 02DD
+BE 017E
+BF 017C
+C0 0154
+C1 00C1
+C2 00C2
+C3 0102
+C4 00C4
+C5 0139
+C6 0106
+C7 00C7
+C8 010C
+C9 00C9
+CA 0118
+CB 00CB
+CC 011A
+CD 00CD
+CE 00CE
+CF 010E
+D0 0110
+D1 0143
+D2 0147
+D3 00D3
+D4 00D4
+D5 0150
+D6 00D6
+D7 00D7
+D8 0158
+D9 016E
+DA 00DA
+DB 0170
+DC 00DC
+DD 00DD
+DE 0162
+DF 00DF
+E0 0155
+E1 00E1
+E2 00E2
+E3 0103
+E4 00E4
+E5 013A
+E6 0107
+E7 00E7
+E8 010D
+E9 00E9
+EA 0119
+EB 00EB
+EC 011B
+ED 00ED
+EE 00EE
+EF 010F
+F0 0111
+F1 0144
+F2 0148
+F3 00F3
+F4 00F4
+F5 0151
+F6 00F6
+F7 00F7
+F8 0159
+F9 016F
+FA 00FA
+FB 0171
+FC 00FC
+FD 00FD
+FE 0163
+FF 02D9
diff --git a/data/iso-8859-3 b/data/iso-8859-3
new file mode 100644
index 000000000..fe3675ae1
--- /dev/null
+++ b/data/iso-8859-3
@@ -0,0 +1,244 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-3
+# (Latin3/South European) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 0126
+A2 02D8
+A3 00A3
+A4 00A4
+A6 0124
+A7 00A7
+A8 00A8
+A9 0130
+AA 015E
+AB 011E
+AC 0134
+AD 00AD
+AF 017B
+B0 00B0
+B1 0127
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 0125
+B7 00B7
+B8 00B8
+B9 0131
+BA 015F
+BB 011F
+BC 0135
+BD 00BD
+BF 017C
+C0 00C0
+C1 00C1
+C2 00C2
+C4 00C4
+C5 010A
+C6 0108
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 0120
+D6 00D6
+D7 00D7
+D8 011C
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 016C
+DE 015C
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E4 00E4
+E5 010B
+E6 0109
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 0121
+F6 00F6
+F7 00F7
+F8 011D
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 016D
+FE 015D
+FF 02D9
diff --git a/data/iso-8859-4 b/data/iso-8859-4
new file mode 100644
index 000000000..3295cb56a
--- /dev/null
+++ b/data/iso-8859-4
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-4
+# (Latin4/North European) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 0104
+A2 0138
+A3 0156
+A4 00A4
+A5 0128
+A6 013B
+A7 00A7
+A8 00A8
+A9 0160
+AA 0112
+AB 0122
+AC 0166
+AD 00AD
+AE 017D
+AF 00AF
+B0 00B0
+B1 0105
+B2 02DB
+B3 0157
+B4 00B4
+B5 0129
+B6 013C
+B7 02C7
+B8 00B8
+B9 0161
+BA 0113
+BB 0123
+BC 0167
+BD 014A
+BE 017E
+BF 014B
+C0 0100
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 012E
+C8 010C
+C9 00C9
+CA 0118
+CB 00CB
+CC 0116
+CD 00CD
+CE 00CE
+CF 012A
+D0 0110
+D1 0145
+D2 014C
+D3 0136
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 0172
+DA 00DA
+DB 00DB
+DC 00DC
+DD 0168
+DE 016A
+DF 00DF
+E0 0101
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 012F
+E8 010D
+E9 00E9
+EA 0119
+EB 00EB
+EC 0117
+ED 00ED
+EE 00EE
+EF 012B
+F0 0111
+F1 0146
+F2 014D
+F3 0137
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 0173
+FA 00FA
+FB 00FB
+FC 00FC
+FD 0169
+FE 016B
+FF 02D9
diff --git a/data/iso-8859-5 b/data/iso-8859-5
new file mode 100644
index 000000000..64bd0ea60
--- /dev/null
+++ b/data/iso-8859-5
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-5
+# (Cyrillic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 0401
+A2 0402
+A3 0403
+A4 0404
+A5 0405
+A6 0406
+A7 0407
+A8 0408
+A9 0409
+AA 040A
+AB 040B
+AC 040C
+AD 00AD
+AE 040E
+AF 040F
+B0 0410
+B1 0411
+B2 0412
+B3 0413
+B4 0414
+B5 0415
+B6 0416
+B7 0417
+B8 0418
+B9 0419
+BA 041A
+BB 041B
+BC 041C
+BD 041D
+BE 041E
+BF 041F
+C0 0420
+C1 0421
+C2 0422
+C3 0423
+C4 0424
+C5 0425
+C6 0426
+C7 0427
+C8 0428
+C9 0429
+CA 042A
+CB 042B
+CC 042C
+CD 042D
+CE 042E
+CF 042F
+D0 0430
+D1 0431
+D2 0432
+D3 0433
+D4 0434
+D5 0435
+D6 0436
+D7 0437
+D8 0438
+D9 0439
+DA 043A
+DB 043B
+DC 043C
+DD 043D
+DE 043E
+DF 043F
+E0 0440
+E1 0441
+E2 0442
+E3 0443
+E4 0444
+E5 0445
+E6 0446
+E7 0447
+E8 0448
+E9 0449
+EA 044A
+EB 044B
+EC 044C
+ED 044D
+EE 044E
+EF 044F
+F0 2116
+F1 0451
+F2 0452
+F3 0453
+F4 0454
+F5 0455
+F6 0456
+F7 0457
+F8 0458
+F9 0459
+FA 045A
+FB 045B
+FC 045C
+FD 00A7
+FE 045E
+FF 045F
diff --git a/data/iso-8859-6 b/data/iso-8859-6
new file mode 100644
index 000000000..18bdeff4f
--- /dev/null
+++ b/data/iso-8859-6
@@ -0,0 +1,206 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-6
+# (Arabic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0660
+31 0661
+32 0662
+33 0663
+34 0664
+35 0665
+36 0666
+37 0667
+38 0668
+39 0669
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A4 00A4
+AC 060C
+AD 00AD
+BB 061B
+BF 061F
+C1 0621
+C2 0622
+C3 0623
+C4 0624
+C5 0625
+C6 0626
+C7 0627
+C8 0628
+C9 0629
+CA 062A
+CB 062B
+CC 062C
+CD 062D
+CE 062E
+CF 062F
+D0 0630
+D1 0631
+D2 0632
+D3 0633
+D4 0634
+D5 0635
+D6 0636
+D7 0637
+D8 0638
+D9 0639
+DA 063A
+E0 0640
+E1 0641
+E2 0642
+E3 0643
+E4 0644
+E5 0645
+E6 0646
+E7 0647
+E8 0648
+E9 0649
+EA 064A
+EB 064B
+EC 064C
+ED 064D
+EE 064E
+EF 064F
+F0 0650
+F1 0651
+F2 0652
diff --git a/data/iso-8859-7 b/data/iso-8859-7
new file mode 100644
index 000000000..812828e8a
--- /dev/null
+++ b/data/iso-8859-7
@@ -0,0 +1,246 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-7
+# (Greek) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 9f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+a0 ff ltor single Symbol
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 02BD
+A2 02BC
+A3 00A3
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AB 00AB
+AC 00AC
+AD 00AD
+AF 2015
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 0384
+B5 0385
+B6 0386
+B7 00B7
+B8 0388
+B9 0389
+BA 038A
+BB 00BB
+BC 038C
+BD 00BD
+BE 038E
+BF 038F
+C0 0390
+C1 0391
+C2 0392
+C3 0393
+C4 0394
+C5 0395
+C6 0396
+C7 0397
+C8 0398
+C9 0399
+CA 039A
+CB 039B
+CC 039C
+CD 039D
+CE 039E
+CF 039F
+D0 03A0
+D1 03A1
+D3 03A3
+D4 03A4
+D5 03A5
+D6 03A6
+D7 03A7
+D8 03A8
+D9 03A9
+DA 03AA
+DB 03AB
+DC 03AC
+DD 03AD
+DE 03AE
+DF 03AF
+E0 03B0
+E1 03B1
+E2 03B2
+E3 03B3
+E4 03B4
+E5 03B5
+E6 03B6
+E7 03B7
+E8 03B8
+E9 03B9
+EA 03BA
+EB 03BB
+EC 03BC
+ED 03BD
+EE 03BE
+EF 03BF
+F0 03C0
+F1 03C1
+F2 03C2
+F3 03C3
+F4 03C4
+F5 03C5
+F6 03C6
+F7 03C7
+F8 03C8
+F9 03C9
+FA 03CA
+FB 03CB
+FC 03CC
+FD 03CD
+FE 03CE
diff --git a/data/iso-8859-8 b/data/iso-8859-8
new file mode 100644
index 000000000..cfbd4483b
--- /dev/null
+++ b/data/iso-8859-8
@@ -0,0 +1,214 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-8
+# (Hebrew) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 7f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+80 ff rtol single Courier
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00D7
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 203E
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00F7
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+DF 2017
+E0 05D0
+E1 05D1
+E2 05D2
+E3 05D3
+E4 05D4
+E5 05D5
+E6 05D6
+E7 05D7
+E8 05D8
+E9 05D9
+EA 05DA
+EB 05DB
+EC 05DC
+ED 05DD
+EE 05DE
+EF 05DF
+F0 05E0
+F1 05E1
+F2 05E2
+F3 05E3
+F4 05E4
+F5 05E5
+F6 05E6
+F7 05E7
+F8 05E8
+F9 05E9
+FA 05EA
diff --git a/data/iso-8859-9 b/data/iso-8859-9
new file mode 100644
index 000000000..7406122dd
--- /dev/null
+++ b/data/iso-8859-9
@@ -0,0 +1,251 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for ISO-8859-9
+# (Latin5/Turkish) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00BA
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 011E
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 0130
+DE 015E
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 011F
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 0131
+FE 015F
+FF 00FF
diff --git a/data/koi8-r b/data/koi8-r
new file mode 100644
index 000000000..c1fed66cc
--- /dev/null
+++ b/data/koi8-r
@@ -0,0 +1,261 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Russian
+# Code Page KOI8-R text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 2500
+81 2502
+82 250C
+83 2510
+84 2514
+85 2518
+86 251C
+87 2524
+88 252C
+89 2534
+8A 253C
+8B 2580
+8C 2584
+8D 2588
+8E 258C
+8F 2590
+90 2591
+91 2592
+92 2593
+93 2320
+94 25A0
+95 2219
+96 221A
+97 2248
+98 2264
+99 2265
+9A 00A0
+9B 2321
+9C 00B0
+9D 00B2
+9E 00B7
+9F 00F7
+A0 2550
+A1 2551
+A2 2552
+A3 0451
+A4 2553
+A5 2554
+A6 2555
+A7 2556
+A8 2557
+A9 2558
+AA 2559
+AB 255A
+AC 255B
+AD 255C
+AE 255D
+AF 255E
+B0 255F
+B1 2560
+B2 2561
+B3 0401
+B4 2562
+B5 2563
+B6 2564
+B7 2565
+B8 2566
+B9 2567
+BA 2568
+BB 2569
+BC 256A
+BD 256B
+BE 256C
+BF 00A9
+C0 044E
+C1 0430
+C2 0431
+C3 0446
+C4 0434
+C5 0435
+C6 0444
+C7 0433
+C8 0445
+C9 0438
+CA 0439
+CB 043A
+CC 043B
+CD 043C
+CE 043D
+CF 043E
+D0 043F
+D1 044F
+D2 0440
+D3 0441
+D4 0442
+D5 0443
+D6 0436
+D7 0432
+D8 044C
+D9 044B
+DA 0437
+DB 0448
+DC 044D
+DD 0449
+DE 0447
+DF 044A
+E0 042E
+E1 0410
+E2 0411
+E3 0426
+E4 0414
+E5 0415
+E6 0424
+E7 0413
+E8 0425
+E9 0418
+EA 0419
+EB 041A
+EC 041B
+ED 041C
+EE 041D
+EF 041E
+F0 041F
+F1 042F
+F2 0420
+F3 0421
+F4 0422
+F5 0423
+F6 0416
+F7 0412
+F8 042C
+F9 042B
+FA 0417
+FB 0428
+FC 042D
+FD 0429
+FE 0427
+FF 042A
+
+
diff --git a/data/koi8-u b/data/koi8-u
new file mode 100644
index 000000000..35c48645d
--- /dev/null
+++ b/data/koi8-u
@@ -0,0 +1,259 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Ukrainian
+# Code Page KOI8-U text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 2500
+81 2502
+82 250C
+83 2510
+84 2514
+85 2518
+86 251C
+87 2524
+88 252C
+89 2534
+8A 253C
+8B 2580
+8C 2584
+8D 2588
+8E 258C
+8F 2590
+90 2591
+91 2592
+92 2593
+93 2320
+94 25A0
+95 2219
+96 221A
+97 2248
+98 2264
+99 2265
+9A 00A0
+9B 2321
+9C 00B0
+9D 00B2
+9E 00B7
+9F 00F7
+A0 2550
+A1 2551
+A2 2552
+A3 0451
+A4 0454
+A5 2554
+A6 0456
+A7 0457
+A8 2557
+A9 2558
+AA 2559
+AB 255A
+AC 255B
+AD 0491
+AE 255D
+AF 255E
+B0 255F
+B1 2560
+B2 2561
+B3 0401
+B4 0404
+B5 2563
+B6 0406
+B7 0407
+B8 2566
+B9 2567
+BA 2568
+BB 2569
+BC 256A
+BD 0490
+BE 256C
+BF 00A9
+C0 044E
+C1 0430
+C2 0431
+C3 0446
+C4 0434
+C5 0435
+C6 0444
+C7 0433
+C8 0445
+C9 0438
+CA 0439
+CB 043A
+CC 043B
+CD 043C
+CE 043D
+CF 043E
+D0 043F
+D1 044F
+D2 0440
+D3 0441
+D4 0442
+D5 0443
+D6 0436
+D7 0432
+D8 044C
+D9 044B
+DA 0437
+DB 0448
+DC 044D
+DD 0449
+DE 0447
+DF 044A
+E0 042E
+E1 0410
+E2 0411
+E3 0426
+E4 0414
+E5 0415
+E6 0424
+E7 0413
+E8 0425
+E9 0418
+EA 0419
+EB 041A
+EC 041B
+ED 041C
+EE 041D
+EF 041E
+F0 041F
+F1 042F
+F2 0420
+F3 0421
+F4 0422
+F5 0423
+F6 0416
+F7 0412
+F8 042C
+F9 042B
+FA 0417
+FB 0428
+FC 042D
+FD 0429
+FE 0427
+FF 042A
diff --git a/data/psglyphs b/data/psglyphs
new file mode 100644
index 000000000..392e782c0
--- /dev/null
+++ b/data/psglyphs
@@ -0,0 +1,1051 @@
+0020 space
+0021 exclam
+0022 quotedbl
+0023 numbersign
+0024 dollar
+0025 percent
+0026 ampersand
+0027 quotesingle
+0028 parenleft
+0029 parenright
+002a asterisk
+002b plus
+002c comma
+002d hyphen
+002e period
+002f slash
+0030 zero
+0031 one
+0032 two
+0033 three
+0034 four
+0035 five
+0036 six
+0037 seven
+0038 eight
+0039 nine
+003a colon
+003b semicolon
+003c less
+003d equal
+003e greater
+003f question
+0040 at
+0041 A
+0042 B
+0043 C
+0044 D
+0045 E
+0046 F
+0047 G
+0048 H
+0049 I
+004a J
+004b K
+004c L
+004d M
+004e N
+004f O
+0050 P
+0051 Q
+0052 R
+0053 S
+0054 T
+0055 U
+0056 V
+0057 W
+0058 X
+0059 Y
+005a Z
+005b bracketleft
+005c backslash
+005d bracketright
+005e asciicircum
+005f underscore
+0060 grave
+0061 a
+0062 b
+0063 c
+0064 d
+0065 e
+0066 f
+0067 g
+0068 h
+0069 i
+006a j
+006b k
+006c l
+006d m
+006e n
+006f o
+0070 p
+0071 q
+0072 r
+0073 s
+0074 t
+0075 u
+0076 v
+0077 w
+0078 x
+0079 y
+007a z
+007b braceleft
+007c bar
+007d braceright
+007e asciitilde
+00a0 space
+00a1 exclamdown
+00a2 cent
+00a3 sterling
+00a4 currency
+00a5 yen
+00a6 brokenbar
+00a7 section
+00a8 dieresis
+00a9 copyright
+00aa ordfeminine
+00ab guillemotleft
+00ac logicalnot
+00ad minus
+00ae registered
+00af macron
+00b0 degree
+00b1 plusminus
+00b2 twosuperior
+00b3 threesuperior
+00b4 acute
+00b5 mu
+00b6 paragraph
+00b7 periodcentered
+00b8 cedilla
+00b9 onesuperior
+00ba ordmasculine
+00bb guillemotright
+00bc onequarter
+00bd onehalf
+00be threequarters
+00bf questiondown
+00c0 Agrave
+00c1 Aacute
+00c2 Acircumflex
+00c3 Atilde
+00c4 Adieresis
+00c5 Aring
+00c6 AE
+00c7 Ccedilla
+00c8 Egrave
+00c9 Eacute
+00ca Ecircumflex
+00cb Edieresis
+00cc Igrave
+00cd Iacute
+00ce Icircumflex
+00cf Idieresis
+00d0 Eth
+00d1 Ntilde
+00d2 Ograve
+00d3 Oacute
+00d4 Ocircumflex
+00d5 Otilde
+00d6 Odieresis
+00d7 multiply
+00d8 Oslash
+00d9 Ugrave
+00da Uacute
+00db Ucircumflex
+00dc Udieresis
+00dd Yacute
+00de Thorn
+00df germandbls
+00e0 agrave
+00e1 aacute
+00e2 acircumflex
+00e3 atilde
+00e4 adieresis
+00e5 aring
+00e6 ae
+00e7 ccedilla
+00e8 egrave
+00e9 eacute
+00ea ecircumflex
+00eb edieresis
+00ec igrave
+00ed iacute
+00ee icircumflex
+00ef idieresis
+00f0 eth
+00f1 ntilde
+00f2 ograve
+00f3 oacute
+00f4 ocircumflex
+00f5 otilde
+00f6 odieresis
+00f7 divide
+00f8 oslash
+00f9 ugrave
+00fa uacute
+00fb ucircumflex
+00fc udieresis
+00fd yacute
+00fe thorn
+00ff ydieresis
+0100 Amacron
+0101 amacron
+0102 Abreve
+0103 abreve
+0104 Aogonek
+0105 aogonek
+0106 Cacute
+0107 cacute
+0108 Ccircumflex
+0109 ccircumflex
+010a Cdotaccent
+010b cdotaccent
+010c Ccaron
+010d ccaron
+010e Dcaron
+010f dcaron
+0110 Dcroat
+0111 dcroat
+0112 Emacron
+0113 emacron
+0114 Ebreve
+0115 ebreve
+0116 Edotaccent
+0117 edotaccent
+0118 Eogonek
+0119 eogonek
+011a Ecaron
+011b ecaron
+011c Gcircumflex
+011d gcircumflex
+011e Gbreve
+011f gbreve
+0120 Gdotaccent
+0121 gdotaccent
+0122 Gcommaaccent
+0123 gcommaaccent
+0124 Hcircumflex
+0125 hcircumflex
+0126 Hbar
+0127 hbar
+0128 Itilde
+0129 itilde
+012a Imacron
+012b imacron
+012c Ibreve
+012d ibreve
+012e Iogonek
+012f iogonek
+0130 Idotaccent
+0131 dotlessi
+0132 IJ
+0133 ij
+0134 Jcircumflex
+0135 jcircumflex
+0136 Kcommaaccent
+0137 kcommaaccent
+0138 kgreenlandic
+0139 Lacute
+013a lacute
+013b Lcommaaccent
+013c lcommaaccent
+013d Lcaron
+013e lcaron
+013f Ldot
+0140 ldot
+0141 Lslash
+0142 lslash
+0143 Nacute
+0144 nacute
+0145 Ncommaaccent
+0146 ncommaaccent
+0147 Ncaron
+0148 ncaron
+0149 napostrophe
+014a Eng
+014b eng
+014c Omacron
+014d omacron
+014e Obreve
+014f obreve
+0150 Ohungarumlaut
+0151 ohungarumlaut
+0152 OE
+0153 oe
+0154 Racute
+0155 racute
+0156 Rcommaaccent
+0157 rcommaaccent
+0158 Rcaron
+0159 rcaron
+015a Sacute
+015b sacute
+015c Scircumflex
+015d scircumflex
+015e Scedilla
+015f scedilla
+0160 Scaron
+0161 scaron
+0162 Tcommaaccent
+0163 tcommaaccent
+0164 Tcaron
+0165 tcaron
+0166 Tbar
+0167 tbar
+0168 Utilde
+0169 utilde
+016a Umacron
+016b umacron
+016c Ubreve
+016d ubreve
+016e Uring
+016f uring
+0170 Uhungarumlaut
+0171 uhungarumlaut
+0172 Uogonek
+0173 uogonek
+0174 Wcircumflex
+0175 wcircumflex
+0176 Ycircumflex
+0177 ycircumflex
+0178 Ydieresis
+0179 Zacute
+017a zacute
+017b Zdotaccent
+017c zdotaccent
+017d Zcaron
+017e zcaron
+017f longs
+0192 florin
+01a0 Ohorn
+01a1 ohorn
+01af Uhorn
+01b0 uhorn
+01e6 Gcaron
+01e7 gcaron
+01fa Aringacute
+01fb aringacute
+01fc AEacute
+01fd aeacute
+01fe Oslashacute
+01ff oslashacute
+0218 Scommaaccent
+0219 scommaaccent
+021a Tcommaaccent
+021b tcommaaccent
+02bc afii57929
+02bd afii64937
+02c6 circumflex
+02c7 caron
+02c9 macron
+02d8 breve
+02d9 dotaccent
+02da ring
+02db ogonek
+02dc tilde
+02dd hungarumlaut
+0300 gravecomb
+0301 acutecomb
+0303 tildecomb
+0309 hookabovecomb
+0323 dotbelowcomb
+0384 tonos
+0385 dieresistonos
+0386 Alphatonos
+0387 anoteleia
+0388 Epsilontonos
+0389 Etatonos
+038a Iotatonos
+038c Omicrontonos
+038e Upsilontonos
+038f Omegatonos
+0390 iotadieresistonos
+0391 Alpha
+0392 Beta
+0393 Gamma
+0394 Delta
+0395 Epsilon
+0396 Zeta
+0397 Eta
+0398 Theta
+0399 Iota
+039a Kappa
+039b Lambda
+039c Mu
+039d Nu
+039e Xi
+039f Omicron
+03a0 Pi
+03a1 Rho
+03a3 Sigma
+03a4 Tau
+03a5 Upsilon
+03a6 Phi
+03a7 Chi
+03a8 Psi
+03a9 Omega
+03aa Iotadieresis
+03ab Upsilondieresis
+03ac alphatonos
+03ad epsilontonos
+03ae etatonos
+03af iotatonos
+03b0 upsilondieresistonos
+03b1 alpha
+03b2 beta
+03b3 gamma
+03b4 delta
+03b5 epsilon
+03b6 zeta
+03b7 eta
+03b8 theta
+03b9 iota
+03ba kappa
+03bb lambda
+03bc mu
+03bd nu
+03be xi
+03bf omicron
+03c0 pi
+03c1 rho
+03c2 sigma1
+03c3 sigma
+03c4 tau
+03c5 upsilon
+03c6 phi
+03c7 chi
+03c8 psi
+03c9 omega
+03ca iotadieresis
+03cb upsilondieresis
+03cc omicrontonos
+03cd upsilontonos
+03ce omegatonos
+03d1 theta1
+03d2 Upsilon1
+03d5 phi1
+03d6 omega1
+0401 afii10023
+0402 afii10051
+0403 afii10052
+0404 afii10053
+0405 afii10054
+0406 afii10055
+0407 afii10056
+0408 afii10057
+0409 afii10058
+040a afii10059
+040b afii10060
+040c afii10061
+040e afii10062
+040f afii10145
+0410 afii10017
+0411 afii10018
+0412 afii10019
+0413 afii10020
+0414 afii10021
+0415 afii10022
+0416 afii10024
+0417 afii10025
+0418 afii10026
+0419 afii10027
+041a afii10028
+041b afii10029
+041c afii10030
+041d afii10031
+041e afii10032
+041f afii10033
+0420 afii10034
+0421 afii10035
+0422 afii10036
+0423 afii10037
+0424 afii10038
+0425 afii10039
+0426 afii10040
+0427 afii10041
+0428 afii10042
+0429 afii10043
+042a afii10044
+042b afii10045
+042c afii10046
+042d afii10047
+042e afii10048
+042f afii10049
+0430 afii10065
+0431 afii10066
+0432 afii10067
+0433 afii10068
+0434 afii10069
+0435 afii10070
+0436 afii10072
+0437 afii10073
+0438 afii10074
+0439 afii10075
+043a afii10076
+043b afii10077
+043c afii10078
+043d afii10079
+043e afii10080
+043f afii10081
+0440 afii10082
+0441 afii10083
+0442 afii10084
+0443 afii10085
+0444 afii10086
+0445 afii10087
+0446 afii10088
+0447 afii10089
+0448 afii10090
+0449 afii10091
+044a afii10092
+044b afii10093
+044c afii10094
+044d afii10095
+044e afii10096
+044f afii10097
+0451 afii10071
+0452 afii10099
+0453 afii10100
+0454 afii10101
+0455 afii10102
+0456 afii10103
+0457 afii10104
+0458 afii10105
+0459 afii10106
+045a afii10107
+045b afii10108
+045c afii10109
+045e afii10110
+045f afii10193
+0462 afii10146
+0463 afii10194
+0472 afii10147
+0473 afii10195
+0474 afii10148
+0475 afii10196
+0490 afii10050
+0491 afii10098
+04d9 afii10846
+05b0 afii57799
+05b1 afii57801
+05b2 afii57800
+05b3 afii57802
+05b4 afii57793
+05b5 afii57794
+05b6 afii57795
+05b7 afii57798
+05b8 afii57797
+05b9 afii57806
+05bb afii57796
+05bc afii57807
+05bd afii57839
+05be afii57645
+05bf afii57841
+05c0 afii57842
+05c1 afii57804
+05c2 afii57803
+05c3 afii57658
+05d0 afii57664
+05d1 afii57665
+05d2 afii57666
+05d3 afii57667
+05d4 afii57668
+05d5 afii57669
+05d6 afii57670
+05d7 afii57671
+05d8 afii57672
+05d9 afii57673
+05da afii57674
+05db afii57675
+05dc afii57676
+05dd afii57677
+05de afii57678
+05df afii57679
+05e0 afii57680
+05e1 afii57681
+05e2 afii57682
+05e3 afii57683
+05e4 afii57684
+05e5 afii57685
+05e6 afii57686
+05e7 afii57687
+05e8 afii57688
+05e9 afii57689
+05ea afii57690
+05f0 afii57716
+05f1 afii57717
+05f2 afii57718
+060c afii57388
+061b afii57403
+061f afii57407
+0621 afii57409
+0622 afii57410
+0623 afii57411
+0624 afii57412
+0625 afii57413
+0626 afii57414
+0627 afii57415
+0628 afii57416
+0629 afii57417
+062a afii57418
+062b afii57419
+062c afii57420
+062d afii57421
+062e afii57422
+062f afii57423
+0630 afii57424
+0631 afii57425
+0632 afii57426
+0633 afii57427
+0634 afii57428
+0635 afii57429
+0636 afii57430
+0637 afii57431
+0638 afii57432
+0639 afii57433
+063a afii57434
+0640 afii57440
+0641 afii57441
+0642 afii57442
+0643 afii57443
+0644 afii57444
+0645 afii57445
+0646 afii57446
+0647 afii57470
+0648 afii57448
+0649 afii57449
+064a afii57450
+064b afii57451
+064c afii57452
+064d afii57453
+064e afii57454
+064f afii57455
+0650 afii57456
+0651 afii57457
+0652 afii57458
+0660 afii57392
+0661 afii57393
+0662 afii57394
+0663 afii57395
+0664 afii57396
+0665 afii57397
+0666 afii57398
+0667 afii57399
+0668 afii57400
+0669 afii57401
+066a afii57381
+066d afii63167
+0679 afii57511
+067e afii57506
+0686 afii57507
+0688 afii57512
+0691 afii57513
+0698 afii57508
+06a4 afii57505
+06af afii57509
+06ba afii57514
+06d2 afii57519
+06d5 afii57534
+1e80 Wgrave
+1e81 wgrave
+1e82 Wacute
+1e83 wacute
+1e84 Wdieresis
+1e85 wdieresis
+1ef2 Ygrave
+1ef3 ygrave
+200c afii61664
+200d afii301
+200e afii299
+200f afii300
+2012 figuredash
+2013 endash
+2014 emdash
+2015 afii00208
+2017 underscoredbl
+2018 quoteleft
+2019 quoteright
+201a quotesinglbase
+201b quotereversed
+201c quotedblleft
+201d quotedblright
+201e quotedblbase
+2020 dagger
+2021 daggerdbl
+2022 bullet
+2024 onedotenleader
+2025 twodotenleader
+2026 ellipsis
+202c afii61573
+202d afii61574
+202e afii61575
+2030 perthousand
+2032 minute
+2033 second
+2039 guilsinglleft
+203a guilsinglright
+203c exclamdbl
+2044 fraction
+2070 zerosuperior
+2074 foursuperior
+2075 fivesuperior
+2076 sixsuperior
+2077 sevensuperior
+2078 eightsuperior
+2079 ninesuperior
+207d parenleftsuperior
+207e parenrightsuperior
+207f nsuperior
+2080 zeroinferior
+2081 oneinferior
+2082 twoinferior
+2083 threeinferior
+2084 fourinferior
+2085 fiveinferior
+2086 sixinferior
+2087 seveninferior
+2088 eightinferior
+2089 nineinferior
+208d parenleftinferior
+208e parenrightinferior
+20a1 colonmonetary
+20a3 franc
+20a4 lira
+20a7 peseta
+20aa afii57636
+20ab dong
+20ac Euro
+2105 afii61248
+2111 Ifraktur
+2113 afii61289
+2116 afii61352
+2118 weierstrass
+211c Rfraktur
+211e prescription
+2122 trademark
+2126 Omega
+212e estimated
+2135 aleph
+2153 onethird
+2154 twothirds
+215b oneeighth
+215c threeeighths
+215d fiveeighths
+215e seveneighths
+2190 arrowleft
+2191 arrowup
+2192 arrowright
+2193 arrowdown
+2194 arrowboth
+2195 arrowupdn
+21a8 arrowupdnbse
+21b5 carriagereturn
+21d0 arrowdblleft
+21d1 arrowdblup
+21d2 arrowdblright
+21d3 arrowdbldown
+21d4 arrowdblboth
+2200 universal
+2202 partialdiff
+2203 existential
+2205 emptyset
+2206 Delta
+2207 gradient
+2208 element
+2209 notelement
+220b suchthat
+220f product
+2211 summation
+2212 minus
+2215 fraction
+2217 asteriskmath
+2219 periodcentered
+221a radical
+221d proportional
+221e infinity
+221f orthogonal
+2220 angle
+2227 logicaland
+2228 logicalor
+2229 intersection
+222a union
+222b integral
+2234 therefore
+223c similar
+2245 congruent
+2248 approxequal
+2260 notequal
+2261 equivalence
+2264 lessequal
+2265 greaterequal
+2282 propersubset
+2283 propersuperset
+2284 notsubset
+2286 reflexsubset
+2287 reflexsuperset
+2295 circleplus
+2297 circlemultiply
+22a5 perpendicular
+22c5 dotmath
+2302 house
+2310 revlogicalnot
+2320 integraltp
+2321 integralbt
+2329 angleleft
+232a angleright
+2500 SF100000
+2502 SF110000
+250c SF010000
+2510 SF030000
+2514 SF020000
+2518 SF040000
+251c SF080000
+2524 SF090000
+252c SF060000
+2534 SF070000
+253c SF050000
+2550 SF430000
+2551 SF240000
+2552 SF510000
+2553 SF520000
+2554 SF390000
+2555 SF220000
+2556 SF210000
+2557 SF250000
+2558 SF500000
+2559 SF490000
+255a SF380000
+255b SF280000
+255c SF270000
+255d SF260000
+255e SF360000
+255f SF370000
+2560 SF420000
+2561 SF190000
+2562 SF200000
+2563 SF230000
+2564 SF470000
+2565 SF480000
+2566 SF410000
+2567 SF450000
+2568 SF460000
+2569 SF400000
+256a SF540000
+256b SF530000
+256c SF440000
+2580 upblock
+2584 dnblock
+2588 block
+258c lfblock
+2590 rtblock
+2591 ltshade
+2592 shade
+2593 dkshade
+25a0 filledbox
+25a1 H22073
+25aa H18543
+25ab H18551
+25ac filledrect
+25b2 triagup
+25ba triagrt
+25bc triagdn
+25c4 triaglf
+25ca lozenge
+25cb circle
+25cf H18533
+25d8 invbullet
+25d9 invcircle
+25e6 openbullet
+263a smileface
+263b invsmileface
+263c sun
+2640 female
+2642 male
+2660 spade
+2663 club
+2665 heart
+2666 diamond
+266a musicalnote
+266b musicalnotedbl
+f6be dotlessj
+f6bf LL
+f6c0 ll
+f6c1 Scedilla
+f6c2 scedilla
+f6c3 commaaccent
+f6c4 afii10063
+f6c5 afii10064
+f6c6 afii10192
+f6c7 afii10831
+f6c8 afii10832
+f6c9 Acute
+f6ca Caron
+f6cb Dieresis
+f6cc DieresisAcute
+f6cd DieresisGrave
+f6ce Grave
+f6cf Hungarumlaut
+f6d0 Macron
+f6d1 cyrBreve
+f6d2 cyrFlex
+f6d3 dblGrave
+f6d4 cyrbreve
+f6d5 cyrflex
+f6d6 dblgrave
+f6d7 dieresisacute
+f6d8 dieresisgrave
+f6d9 copyrightserif
+f6da registerserif
+f6db trademarkserif
+f6dc onefitted
+f6dd rupiah
+f6de threequartersemdash
+f6df centinferior
+f6e0 centsuperior
+f6e1 commainferior
+f6e2 commasuperior
+f6e3 dollarinferior
+f6e4 dollarsuperior
+f6e5 hypheninferior
+f6e6 hyphensuperior
+f6e7 periodinferior
+f6e8 periodsuperior
+f6e9 asuperior
+f6ea bsuperior
+f6eb dsuperior
+f6ec esuperior
+f6ed isuperior
+f6ee lsuperior
+f6ef msuperior
+f6f0 osuperior
+f6f1 rsuperior
+f6f2 ssuperior
+f6f3 tsuperior
+f6f4 Brevesmall
+f6f5 Caronsmall
+f6f6 Circumflexsmall
+f6f7 Dotaccentsmall
+f6f8 Hungarumlautsmall
+f6f9 Lslashsmall
+f6fa OEsmall
+f6fb Ogoneksmall
+f6fc Ringsmall
+f6fd Scaronsmall
+f6fe Tildesmall
+f6ff Zcaronsmall
+f721 exclamsmall
+f724 dollaroldstyle
+f726 ampersandsmall
+f730 zerooldstyle
+f731 oneoldstyle
+f732 twooldstyle
+f733 threeoldstyle
+f734 fouroldstyle
+f735 fiveoldstyle
+f736 sixoldstyle
+f737 sevenoldstyle
+f738 eightoldstyle
+f739 nineoldstyle
+f73f questionsmall
+f760 Gravesmall
+f761 Asmall
+f762 Bsmall
+f763 Csmall
+f764 Dsmall
+f765 Esmall
+f766 Fsmall
+f767 Gsmall
+f768 Hsmall
+f769 Ismall
+f76a Jsmall
+f76b Ksmall
+f76c Lsmall
+f76d Msmall
+f76e Nsmall
+f76f Osmall
+f770 Psmall
+f771 Qsmall
+f772 Rsmall
+f773 Ssmall
+f774 Tsmall
+f775 Usmall
+f776 Vsmall
+f777 Wsmall
+f778 Xsmall
+f779 Ysmall
+f77a Zsmall
+f7a1 exclamdownsmall
+f7a2 centoldstyle
+f7a8 Dieresissmall
+f7af Macronsmall
+f7b4 Acutesmall
+f7b8 Cedillasmall
+f7bf questiondownsmall
+f7e0 Agravesmall
+f7e1 Aacutesmall
+f7e2 Acircumflexsmall
+f7e3 Atildesmall
+f7e4 Adieresissmall
+f7e5 Aringsmall
+f7e6 AEsmall
+f7e7 Ccedillasmall
+f7e8 Egravesmall
+f7e9 Eacutesmall
+f7ea Ecircumflexsmall
+f7eb Edieresissmall
+f7ec Igravesmall
+f7ed Iacutesmall
+f7ee Icircumflexsmall
+f7ef Idieresissmall
+f7f0 Ethsmall
+f7f1 Ntildesmall
+f7f2 Ogravesmall
+f7f3 Oacutesmall
+f7f4 Ocircumflexsmall
+f7f5 Otildesmall
+f7f6 Odieresissmall
+f7f8 Oslashsmall
+f7f9 Ugravesmall
+f7fa Uacutesmall
+f7fb Ucircumflexsmall
+f7fc Udieresissmall
+f7fd Yacutesmall
+f7fe Thornsmall
+f7ff Ydieresissmall
+f8e5 radicalex
+f8e6 arrowvertex
+f8e7 arrowhorizex
+f8e8 registersans
+f8e9 copyrightsans
+f8ea trademarksans
+f8eb parenlefttp
+f8ec parenleftex
+f8ed parenleftbt
+f8ee bracketlefttp
+f8ef bracketleftex
+f8f0 bracketleftbt
+f8f1 bracelefttp
+f8f2 braceleftmid
+f8f3 braceleftbt
+f8f4 braceex
+f8f5 integralex
+f8f6 parenrighttp
+f8f7 parenrightex
+f8f8 parenrightbt
+f8f9 bracketrighttp
+f8fa bracketrightex
+f8fb bracketrightbt
+f8fc bracerighttp
+f8fd bracerightmid
+f8fe bracerightbt
+fb00 ff
+fb01 fi
+fb02 fl
+fb03 ffi
+fb04 ffl
+fb1f afii57705
+fb2a afii57694
+fb2b afii57695
+fb35 afii57723
+fb4b afii57700
diff --git a/data/secret b/data/secret
new file mode 100644
index 000000000..46f240a80
--- /dev/null
+++ b/data/secret
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ (Secret) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ (Secret) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: secret 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/standard b/data/standard
new file mode 100644
index 000000000..d65828085
--- /dev/null
+++ b/data/standard
@@ -0,0 +1,261 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: standard 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/testprint.ps b/data/testprint.ps
new file mode 100644
index 000000000..c082909cb
--- /dev/null
+++ b/data/testprint.ps
@@ -0,0 +1,522 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset testprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 11, 1999
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset testprint 1.1 0
+%
+% PostScript test page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/OCTANT { % Draw a color wheel OCTANT...
+ % (name) radius r g b OCTANT -
+ % Loop through 100 shades...
+ 0 0.010101 0.98 {
+ % Set the color...
+ 3 index 1 eq % R == 1?
+ 3 index 1 eq % G == 1?
+ 3 index 1 eq % B == 1?
+ and and {
+ 0 index 4 index mul % R * val
+ 1 index 4 index mul % G * val
+ 2 index 4 index mul % B * val
+ } {
+ 0 index 4 index mul % R * val
+ 1 index neg 1 add add % + (1 - val)
+ 1 index 4 index mul % G * val
+ 2 index neg 1 add add % + (1 - val)
+ 2 index 4 index mul % B * val
+ 3 index neg 1 add add % + (1 - val)
+ } ifelse
+ setrgbcolor
+
+ % Draw a polygon...
+ dup 5 index mul dup 0 % x1, y1
+ moveto
+ 0.707106781 mul dup lineto % x2, y2
+
+ 0.010101 add 4 index mul dup % x3
+ 0.707106781 mul dup lineto % x3, y3
+ 0 lineto % x4, y4
+ closepath
+ fill
+ } for
+
+ % Draw a line around the polygons...
+ pop pop pop dup
+ 0 setgray
+ 0 0 moveto
+ dup 0 lineto
+ 0.707106781 mul dup lineto
+ closepath
+ stroke
+
+ % Draw the label...
+ 0 exch dup -9 div exch % text offset = 0, -radius/9
+ dup 0.923879532 mul % x = radius * cos(22.5)
+ exch 0.382683432 mul % y = radius * cos(22.5)
+ moveto % position label
+ gsave
+ 22.5 rotate % rotate label
+ rmoveto % offset label
+ show % show label
+ grestore
+} bind def
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ 4 setlinewidth % Draw wide lines
+ 0 setgray closepath stroke % Draw a clipping rectangle
+ 1 setlinewidth % Draw normal lines
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ 72 72 dtransform % Get device resolution per inch
+ /yResolution exch abs def % yResolution = abs(yres)
+ /xResolution exch abs def % xResolution = abs(xres)
+
+ % Figure out the sizes of things...
+ /wheelSize % size of wheels
+ pageWidth pageHeight lt
+ { pageWidth 9 mul }
+ { pageHeight 7 mul }
+ ifelse def
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ /smallFont /Times-Roman findfont % smallFont = Times-Roman
+ pageHeight scalefont def % size = pageHeight (nominally 11)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the color wheel...
+ mediumFont setfont % Font
+ 0 setgray % Color
+
+ gsave
+ % Position the wheel on the left side...
+ pageWidth 18 mul % x = pageWidth * 1/4 * 72
+ pageHeight 54 mul % y = pageHeight * 3/4 * 72
+ translate
+
+ % Size the wheel...
+ wheelSize
+
+ % Draw the colors...
+ dup (C) exch 0 1 1 OCTANT 45 rotate
+ dup (M) exch 1 0 1 OCTANT 45 rotate
+ dup (Y) exch 1 1 0 OCTANT 45 rotate
+ dup (K) exch 0 0 0 OCTANT 45 rotate
+ dup (R) exch 1 0 0 OCTANT 45 rotate
+ dup (G) exch 0 1 0 OCTANT 45 rotate
+ dup (B) exch 0 0 1 OCTANT 45 rotate
+ (W) exch 1 1 1 OCTANT 45 rotate
+ grestore
+
+ % Label the color wheel...
+ pageWidth 18 mul % x = pageWidth * 1/4 * 72
+ pageHeight 44 mul % y = pageHeight * 19/32 * 72
+ moveto % Position the text
+ (Color Wheel) CENTER % Show the text centered
+
+ % Draw radial lines...
+ gsave
+ 0 setlinewidth % 1 pixel lines
+
+ % Position the lines on the left side...
+ pageWidth 54 mul % x = pageWidth * 3/4 * 72
+ pageHeight 54 mul % y = pageHeight * 3/4 * 72
+ translate
+
+ % Size the wheel...
+ wheelSize
+
+ % Loop at 1 degree increments
+ 0 1 359 {
+ pop % Discard angle - not used
+ 0 0 moveto % Start line at the center
+ dup 0 lineto % Draw to the radius
+ 1 rotate % Rotate 1 degree
+ } for
+
+ pop % Discard radius - not needed anymore
+ stroke % Draw lines...
+
+ grestore
+
+ % Label the lines...
+ pageWidth 54 mul % x = pageWidth * 3/4 * 72
+ pageHeight 44 mul % y = pageHeight * 19/32 * 72
+ moveto % Position the text
+ (1 Degree Radial Lines) CENTER % Show the text centered
+
+ % Imageable area...
+ pageHeight 15 mul % Height of imageable area
+
+ pageWidth 4.5 mul % x = pageWidth * 1/16 * 72
+ pageHeight 35.5 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 1/4 * 72
+ 3 index % height
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 4 mul % x = pageWidth * 1/16 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 3/8 * 72
+ 3 index % height
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ pop % Discard height
+
+ % Label the imageable area...
+ pageWidth 4 mul % x = pageWidth * 1/16 * 72
+ pageHeight 37 mul % y = pageHeight * 1/2 * 72
+ moveto % Position the text
+ mediumFont setfont % Font
+ (Imageable Area) show % Show the text
+
+ smallFont setfont % Font
+ pageWidth 14 mul % x = pageWidth * 3/16 * 72
+ pageHeight 36 mul % y = pageWidth * 1/2 * 72
+ pageHeight -2 mul add % y -= 2 * smallFont height
+
+ % Page Size inches
+ 2 copy moveto % Move to x & y
+ (Page Size: ) RIGHT % Label
+ 100 pageWidth NUMBER % pageWidth
+ (x) show % "x"
+ 100 pageHeight NUMBER % pageHeight
+ (in) show % "in"
+
+ % Page Size millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageWidth 25.4 mul NUMBER % pageWidth
+ (x) show % "x"
+ 10 pageHeight 25.4 mul NUMBER % pageHeight
+ (mm) show % "mm"
+
+ % Lower-left inches
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Lower-Left: ) RIGHT % Label
+ 100 pageLeft NUMBER % pageLeft
+ (x) show % "x"
+ 100 pageBottom NUMBER % pageBottom
+ (in) show % "in"
+
+ % Lower-left millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageLeft 25.4 mul NUMBER % pageLeft
+ (x) show % "x"
+ 10 pageBottom 25.4 mul NUMBER % pageBottom
+ (mm) show % "mm"
+
+ % Upper-right inches
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Upper-Right: ) RIGHT % Label
+ 100 pageRight NUMBER % pageRight
+ (x) show % "x"
+ 100 pageTop NUMBER % pageTop
+ (in) show % "in"
+
+ % Upper-right millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageRight 25.4 mul NUMBER % pageRight
+ (x) show % "x"
+ 10 pageTop 25.4 mul NUMBER % pageTop
+ (mm) show % "mm"
+
+ % Resolution dots-per-inch
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Resolution: ) RIGHT % Label
+ 1 xResolution NUMBER % xResolution
+ (x) show % "x"
+ 1 yResolution NUMBER % yResolution
+ (dpi) show % "dpi"
+
+ % Resolution dots-per-meter
+ pageHeight sub % Move down...
+
+ moveto % Move to x & y
+ 1 xResolution 39.27 mul NUMBER % xResolution
+ (x) show % "x"
+ 1 yResolution 39.27 mul NUMBER % yResolution
+ (dpm) show % "dpm"
+
+ % Interpreter Information...
+ pageHeight 15 mul % Height of interpreter information
+
+ pageWidth 40.5 mul % x = pageWidth * 9/16 * 72
+ pageHeight 35.5 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 1/4 * 72
+ 3 index % height
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 40 mul % x = pageWidth * 9/16 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 3/8 * 72
+ 3 index % height
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ pop % Discard height
+
+ % Label the interpreter info...
+ pageWidth 40 mul % x = pageWidth * 9/16 * 72
+ pageHeight 37 mul % y = pageHeight * 1/2 * 72
+ moveto % Position the text
+ mediumFont setfont % Font
+ (Interpreter Information) show % Show the text
+
+ smallFont setfont % Font
+ pageWidth 49 mul % x = pageWidth * 11/16 * 72
+ pageHeight 36 mul % y = pageWidth * 1/2 * 72
+ pageHeight 2 mul sub % y -= 2 * smallFont height
+
+ % Language level
+ 2 copy moveto % Move to x & y
+ (PostScript: ) RIGHT % Label
+ (Level ) show % "Level "
+ 1 languagelevel NUMBER % Language level
+
+ % Version
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Version: ) RIGHT % Label
+ version show % Version
+ ( \() show % " ("
+ 1 revision NUMBER % Revision
+ (\)) show % ")"
+
+ % Product
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Product: ) RIGHT % Label
+ product show % Product name
+
+ % Serial Number
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Serial #: ) RIGHT % Label
+ 1 serialnumber NUMBER % S/N
+
+ % Draw the label at the top...
+ pageWidth 36 mul % Center of page
+ pageHeight 68 mul % Top of page (15/16ths)
+ 2 copy moveto % Position text
+ bigFont setfont % Font
+ (Printer Test Page) CENTER % Show text centered
+
+ % Draw the copyright notice at the bottom...
+ pageWidth 36 mul % Center of page
+ pageHeight 10 mul % Bottom of page
+ 2 copy moveto % Position text
+ (Printed Using CUPS v1.1.x) CENTER % Show text centered
+
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Position text
+ smallFont setfont % Font
+ (Copyright 1993-2003 by Easy Software Products, All Rights Reserved.) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (CUPS, Easy Software Products and their logos are the trademark property of) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (Easy Software Products, 44141 Airport View Drive, Suite 204,) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (Hollywood, Maryland, 20636-3111, USA.) CENTER
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageHeight 4 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageHeight 4 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: testprint.ps 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/topsecret b/data/topsecret
new file mode 100644
index 000000000..6e39e35f4
--- /dev/null
+++ b/data/topsecret
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ (Top Secret) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ (Top Secret) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: topsecret 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/unclassified b/data/unclassified
new file mode 100644
index 000000000..4b287de42
--- /dev/null
+++ b/data/unclassified
@@ -0,0 +1,277 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset bannerprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 10, 2000
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset bannerprint 1.1 0
+%
+% PostScript banner page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs are the
+% property of Easy Software Products and are protected by Federal
+% copyright law. Distribution and use rights are outlined in the file
+% "LICENSE.txt" which should have been included with this file. If this
+% file is missing or damaged please contact Easy Software Products
+% at:
+%
+% Attn: CUPS Licensing Information
+% Easy Software Products
+% 44141 Airport View Drive, Suite 204
+% Hollywood, Maryland 20636-3111 USA
+%
+% Voice: (301) 373-9603
+% EMail: cups-info@cups.org
+% WWW: http://www.cups.org
+%
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ /boxWidth % width of text box
+ pageWidth pageHeight lt
+ { pageWidth 54 mul }
+ { pageHeight 42 mul }
+ ifelse def
+
+ newpath % Clear bounding path
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the label at the top and bottom...
+ 0 setgray % Color
+
+ pageWidth 36 mul % Center of page
+ pageHeight 72 mul % Top of page
+ pageWidth -7 mul add % - 2 lines
+ moveto % Position text
+ bigFont setfont % Font
+ (Unclassified) CENTER % Show text centered
+
+ pageWidth 36 mul % Center of page
+ pageHeight 6 mul % Bottom of page
+ moveto % Position text
+ bigFont setfont % Font
+ (Unclassified) CENTER % Show text centered
+
+ % Job information box...
+ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ boxWidth 0.5 mul sub % x-= 1/2 box width
+ pageHeight 30 mul % y = pageHeight * 1/4 * 72
+ boxWidth % w = box width
+ pageHeight 14 mul % h = pageHeight * 1/2 * 72
+
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ % Job information text...
+ mediumFont setfont % Medium sized font
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 5 mul add % y += 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Job ID: ) RIGHT
+ moveto
+ ({printer-name}-{job-id}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight 2 mul add % y += 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Title: ) RIGHT
+ moveto
+ ({job-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -1 mul add % y -= 1 line
+ 2 copy % Copy X & Y
+ moveto
+ (Requesting User: ) RIGHT
+ moveto
+ ({job-originating-user-name}) show
+
+ pageWidth 36 mul % x = pageWidth * 1/2 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ pageHeight -4 mul add % y -= 2 lines
+ 2 copy % Copy X & Y
+ moveto
+ (Billing Info: ) RIGHT
+ moveto
+ ({?job-billing}) show
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageWidth 6 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: unclassified 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/data/utf-8 b/data/utf-8
new file mode 100644
index 000000000..d2e916179
--- /dev/null
+++ b/data/utf-8
@@ -0,0 +1,39 @@
+charset utf8
+
+#
+# This file defines the font mappings used for Unicode/UTF-8 text printing.
+#
+# Each line consists of:
+#
+# first last direction width normal bold italic bold-italic
+#
+# First and last are the first and last glyphs in the font mapping
+# that correspond to that font; a maximum of 256 characters can be
+# mapped within each group, with a maximum of 256 mappings (this is a
+# PostScript limitation.) The glyph values are hexadecimal.
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+0000 00FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+0100 01FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+0200 02FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+0300 03FF ltor single Symbol
+0400 04FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+0500 05FF rtol single Courier
+1E00 1EFF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+2000 20FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+2100 21FF ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+2200 22FF ltor single Symbol
+2300 23FF ltor single Symbol
diff --git a/data/windows-1250 b/data/windows-1250
new file mode 100644
index 000000000..5d45eff01
--- /dev/null
+++ b/data/windows-1250
@@ -0,0 +1,254 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1250 (WinLatin2) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+84 201E
+85 2026
+86 2020
+87 2021
+89 2030
+8A 0160
+8B 2039
+8C 015A
+8D 0164
+8E 017D
+8F 0179
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+99 2122
+9A 0161
+9B 203A
+9C 015B
+9D 0165
+9E 017E
+9F 017A
+A0 00A0
+A1 02C7
+A2 02D8
+A3 0141
+A4 00A4
+A5 0104
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 015E
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 017B
+B0 00B0
+B1 00B1
+B2 02DB
+B3 0142
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 0105
+BA 015F
+BB 00BB
+BC 013D
+BD 02DD
+BE 013E
+BF 017C
+C0 0154
+C1 00C1
+C2 00C2
+C3 0102
+C4 00C4
+C5 0139
+C6 0106
+C7 00C7
+C8 010C
+C9 00C9
+CA 0118
+CB 00CB
+CC 011A
+CD 00CD
+CE 00CE
+CF 010E
+D0 0110
+D1 0143
+D2 0147
+D3 00D3
+D4 00D4
+D5 0150
+D6 00D6
+D7 00D7
+D8 0158
+D9 016E
+DA 00DA
+DB 0170
+DC 00DC
+DD 00DD
+DE 0162
+DF 00DF
+E0 0155
+E1 00E1
+E2 00E2
+E3 0103
+E4 00E4
+E5 013A
+E6 0107
+E7 00E7
+E8 010D
+E9 00E9
+EA 0119
+EB 00EB
+EC 011B
+ED 00ED
+EE 00EE
+EF 010F
+F0 0111
+F1 0144
+F2 0148
+F3 00F3
+F4 00F4
+F5 0151
+F6 00F6
+F7 00F7
+F8 0159
+F9 016F
+FA 00FA
+FB 0171
+FC 00FC
+FD 00FD
+FE 0163
+FF 02D9
diff --git a/data/windows-1251 b/data/windows-1251
new file mode 100644
index 000000000..200bbde45
--- /dev/null
+++ b/data/windows-1251
@@ -0,0 +1,258 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1251 (WinCyrillic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 0402
+81 0403
+82 201A
+83 0453
+84 201E
+85 2026
+86 2020
+87 2021
+88 20AC
+89 2030
+8A 0409
+8B 2039
+8C 040A
+8D 040C
+8E 040B
+8F 040F
+90 0452
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+99 2122
+9A 0459
+9B 203A
+9C 045A
+9D 045C
+9E 045B
+9F 045F
+A0 00A0
+A1 040E
+A2 045E
+A3 0408
+A4 00A4
+A5 0490
+A6 00A6
+A7 00A7
+A8 0401
+A9 00A9
+AA 0404
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 0407
+B0 00B0
+B1 00B1
+B2 0406
+B3 0456
+B4 0491
+B5 00B5
+B6 00B6
+B7 00B7
+B8 0451
+B9 2116
+BA 0454
+BB 00BB
+BC 0458
+BD 0405
+BE 0455
+BF 0457
+C0 0410
+C1 0411
+C2 0412
+C3 0413
+C4 0414
+C5 0415
+C6 0416
+C7 0417
+C8 0418
+C9 0419
+CA 041A
+CB 041B
+CC 041C
+CD 041D
+CE 041E
+CF 041F
+D0 0420
+D1 0421
+D2 0422
+D3 0423
+D4 0424
+D5 0425
+D6 0426
+D7 0427
+D8 0428
+D9 0429
+DA 042A
+DB 042B
+DC 042C
+DD 042D
+DE 042E
+DF 042F
+E0 0430
+E1 0431
+E2 0432
+E3 0433
+E4 0434
+E5 0435
+E6 0436
+E7 0437
+E8 0438
+E9 0439
+EA 043A
+EB 043B
+EC 043C
+ED 043D
+EE 043E
+EF 043F
+F0 0440
+F1 0441
+F2 0442
+F3 0443
+F4 0444
+F5 0445
+F6 0446
+F7 0447
+F8 0448
+F9 0449
+FA 044A
+FB 044B
+FC 044C
+FD 044D
+FE 044E
+FF 044F
diff --git a/data/windows-1252 b/data/windows-1252
new file mode 100644
index 000000000..d758d536e
--- /dev/null
+++ b/data/windows-1252
@@ -0,0 +1,254 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1252 (WinLatin1) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+8E 017D
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9E 017E
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00BA
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 00D0
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 00DD
+DE 00DE
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 00F0
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 00FD
+FE 00FE
+FF 00FF
diff --git a/data/windows-1253 b/data/windows-1253
new file mode 100644
index 000000000..a9dfcb8eb
--- /dev/null
+++ b/data/windows-1253
@@ -0,0 +1,243 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1253 (WinGreek) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 9f ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+a0 ff ltor single Symbol
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+89 2030
+8B 2039
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+99 2122
+9B 203A
+A0 00A0
+A1 0385
+A2 0386
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 2015
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 0384
+B5 00B5
+B6 00B6
+B7 00B7
+B8 0388
+B9 0389
+BA 038A
+BB 00BB
+BC 038C
+BD 00BD
+BE 038E
+BF 038F
+C0 0390
+C1 0391
+C2 0392
+C3 0393
+C4 0394
+C5 0395
+C6 0396
+C7 0397
+C8 0398
+C9 0399
+CA 039A
+CB 039B
+CC 039C
+CD 039D
+CE 039E
+CF 039F
+D0 03A0
+D1 03A1
+D3 03A3
+D4 03A4
+D5 03A5
+D6 03A6
+D7 03A7
+D8 03A8
+D9 03A9
+DA 03AA
+DB 03AB
+DC 03AC
+DD 03AD
+DE 03AE
+DF 03AF
+E0 03B0
+E1 03B1
+E2 03B2
+E3 03B3
+E4 03B4
+E5 03B5
+E6 03B6
+E7 03B7
+E8 03B8
+E9 03B9
+EA 03BA
+EB 03BB
+EC 03BC
+ED 03BD
+EE 03BE
+EF 03BF
+F0 03C0
+F1 03C1
+F2 03C2
+F3 03C3
+F4 03C4
+F5 03C5
+F6 03C6
+F7 03C7
+F8 03C8
+F9 03C9
+FA 03CA
+FB 03CB
+FC 03CC
+FD 03CD
+FE 03CE
diff --git a/data/windows-1254 b/data/windows-1254
new file mode 100644
index 000000000..434c65c47
--- /dev/null
+++ b/data/windows-1254
@@ -0,0 +1,252 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1254 (WinTurkish) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0160
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9A 0161
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00BA
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 00C3
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 00CC
+CD 00CD
+CE 00CE
+CF 00CF
+D0 011E
+D1 00D1
+D2 00D2
+D3 00D3
+D4 00D4
+D5 00D5
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 0130
+DE 015E
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 00E3
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 00EC
+ED 00ED
+EE 00EE
+EF 00EF
+F0 011F
+F1 00F1
+F2 00F2
+F3 00F3
+F4 00F4
+F5 00F5
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 0131
+FE 015F
+FF 00FF
diff --git a/data/windows-1255 b/data/windows-1255
new file mode 100644
index 000000000..66681ec1b
--- /dev/null
+++ b/data/windows-1255
@@ -0,0 +1,236 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1255 (WinHebrew) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8B 2039
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9B 203A
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 20AA
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00D7
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00F7
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 05B0
+C1 05B1
+C2 05B2
+C3 05B3
+C4 05B4
+C5 05B5
+C6 05B6
+C7 05B7
+C8 05B8
+C9 05B9
+CB 05BB
+CC 05BC
+CD 05BD
+CE 05BE
+CF 05BF
+D0 05C0
+D1 05C1
+D2 05C2
+D3 05C3
+D4 05F0
+D5 05F1
+D6 05F2
+D7 05F3
+D8 05F4
+E0 05D0
+E1 05D1
+E2 05D2
+E3 05D3
+E4 05D4
+E5 05D5
+E6 05D6
+E7 05D7
+E8 05D8
+E9 05D9
+EA 05DA
+EB 05DB
+EC 05DC
+ED 05DD
+EE 05DE
+EF 05DF
+F0 05E0
+F1 05E1
+F2 05E2
+F3 05E3
+F4 05E4
+F5 05E5
+F6 05E6
+F7 05E7
+F8 05E8
+F9 05E9
+FA 05EA
+FD 200E
+FE 200F
diff --git a/data/windows-1256 b/data/windows-1256
new file mode 100644
index 000000000..6f41b24c9
--- /dev/null
+++ b/data/windows-1256
@@ -0,0 +1,259 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1256 (WinArabic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff rtol single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+81 067E
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8A 0679
+8B 2039
+8C 0152
+8D 0686
+8E 0698
+8F 0688
+90 06AF
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 06A9
+99 2122
+9A 0691
+9B 203A
+9C 0153
+9D 200C
+9E 200D
+9F 06BA
+A0 00A0
+A1 060C
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 06BE
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 061B
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 061F
+C0 06C1
+C1 0621
+C2 0622
+C3 0623
+C4 0624
+C5 0625
+C6 0626
+C7 0627
+C8 0628
+C9 0629
+CA 062A
+CB 062B
+CC 062C
+CD 062D
+CE 062E
+CF 062F
+D0 0630
+D1 0631
+D2 0632
+D3 0633
+D4 0634
+D5 0635
+D6 0636
+D7 00D7
+D8 0637
+D9 0638
+DA 0639
+DB 063A
+DC 0640
+DD 0641
+DE 0642
+DF 0643
+E0 00E0
+E1 0644
+E2 00E2
+E3 0645
+E4 0646
+E5 0647
+E6 0648
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 0649
+ED 064A
+EE 00EE
+EF 00EF
+F0 064B
+F1 064C
+F2 064D
+F3 064E
+F4 00F4
+F5 064F
+F6 0650
+F7 00F7
+F8 0651
+F9 00F9
+FA 0652
+FB 00FB
+FC 00FC
+FD 200E
+FE 200F
+FF 06D2
diff --git a/data/windows-1257 b/data/windows-1257
new file mode 100644
index 000000000..b56b33729
--- /dev/null
+++ b/data/windows-1257
@@ -0,0 +1,247 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1257 (WinBaltic) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+84 201E
+85 2026
+86 2020
+87 2021
+89 2030
+8B 2039
+8D 00A8
+8E 02C7
+8F 00B8
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+99 2122
+9B 203A
+9D 00AF
+9E 02DB
+A0 00A0
+A2 00A2
+A3 00A3
+A4 00A4
+A6 00A6
+A7 00A7
+A8 00D8
+A9 00A9
+AA 0156
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00C6
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00F8
+B9 00B9
+BA 0157
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00E6
+C0 0104
+C1 012E
+C2 0100
+C3 0106
+C4 00C4
+C5 00C5
+C6 0118
+C7 0112
+C8 010C
+C9 00C9
+CA 0179
+CB 0116
+CC 0122
+CD 0136
+CE 012A
+CF 013B
+D0 0160
+D1 0143
+D2 0145
+D3 00D3
+D4 014C
+D5 00D5
+D6 00D6
+D7 00D7
+D8 0172
+D9 0141
+DA 015A
+DB 016A
+DC 00DC
+DD 017B
+DE 017D
+DF 00DF
+E0 0105
+E1 012F
+E2 0101
+E3 0107
+E4 00E4
+E5 00E5
+E6 0119
+E7 0113
+E8 010D
+E9 00E9
+EA 017A
+EB 0117
+EC 0123
+ED 0137
+EE 012B
+EF 013C
+F0 0161
+F1 0144
+F2 0146
+F3 00F3
+F4 014D
+F5 00F5
+F6 00F6
+F7 00F7
+F8 0173
+F9 0142
+FA 015B
+FB 016B
+FC 00FC
+FD 017C
+FE 017E
+FF 02D9
diff --git a/data/windows-1258 b/data/windows-1258
new file mode 100644
index 000000000..dcd4790ab
--- /dev/null
+++ b/data/windows-1258
@@ -0,0 +1,250 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 1258 (WinVietnamese) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+82 201A
+83 0192
+84 201E
+85 2026
+86 2020
+87 2021
+88 02C6
+89 2030
+8B 2039
+8C 0152
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+98 02DC
+99 2122
+9B 203A
+9C 0153
+9F 0178
+A0 00A0
+A1 00A1
+A2 00A2
+A3 00A3
+A4 00A4
+A5 00A5
+A6 00A6
+A7 00A7
+A8 00A8
+A9 00A9
+AA 00AA
+AB 00AB
+AC 00AC
+AD 00AD
+AE 00AE
+AF 00AF
+B0 00B0
+B1 00B1
+B2 00B2
+B3 00B3
+B4 00B4
+B5 00B5
+B6 00B6
+B7 00B7
+B8 00B8
+B9 00B9
+BA 00BA
+BB 00BB
+BC 00BC
+BD 00BD
+BE 00BE
+BF 00BF
+C0 00C0
+C1 00C1
+C2 00C2
+C3 0102
+C4 00C4
+C5 00C5
+C6 00C6
+C7 00C7
+C8 00C8
+C9 00C9
+CA 00CA
+CB 00CB
+CC 0300
+CD 00CD
+CE 00CE
+CF 00CF
+D0 0110
+D1 00D1
+D2 0309
+D3 00D3
+D4 00D4
+D5 01A0
+D6 00D6
+D7 00D7
+D8 00D8
+D9 00D9
+DA 00DA
+DB 00DB
+DC 00DC
+DD 01AF
+DE 0303
+DF 00DF
+E0 00E0
+E1 00E1
+E2 00E2
+E3 0103
+E4 00E4
+E5 00E5
+E6 00E6
+E7 00E7
+E8 00E8
+E9 00E9
+EA 00EA
+EB 00EB
+EC 0301
+ED 00ED
+EE 00EE
+EF 00EF
+F0 0111
+F1 00F1
+F2 0323
+F3 00F3
+F4 00F4
+F5 01A1
+F6 00F6
+F7 00F7
+F8 00F8
+F9 00F9
+FA 00FA
+FB 00FB
+FC 00FC
+FD 01B0
+FE 20AB
+FF 00FF
diff --git a/data/windows-874 b/data/windows-874
new file mode 100644
index 000000000..a231ce733
--- /dev/null
+++ b/data/windows-874
@@ -0,0 +1,228 @@
+charset 8bit
+
+#
+# This file defines the font and character mappings used for Windows
+# Code Page 874 (Thai) text printing.
+#
+# The first line consists of:
+#
+# direction width normal bold italic bold-italic
+#
+# Direction is the string "ltor" or "rtol", indicating left-to-right or
+# right-to-left text.
+#
+# Width is the string "single" or "double"; double means that the glyphs
+# are twice as wide as ASCII characters in the Courier typeface.
+#
+# "Normal", "bold", "italic", and "bold-italic" are the typefaces to use
+# for each presentation. If characters are only available in a single
+# style then only one typeface should be listed (e.g. "Symbol")
+#
+# Each font that is listed will be used (and downloaded if needed) when
+# printing.
+#
+
+00 ff ltor single Courier Courier-Bold Courier-Oblique Courier-BoldOblique
+
+#
+# The following lines define the mapping from the 8-bit character set to
+# the Unicode glyphs for each character:
+#
+# char glyph
+#
+# "Char" and "glyph" are hexadecimal values.
+#
+
+20 0020
+21 0021
+22 0022
+23 0023
+24 0024
+25 0025
+26 0026
+27 0027
+28 0028
+29 0029
+2A 002A
+2B 002B
+2C 002C
+2D 002D
+2E 002E
+2F 002F
+30 0030
+31 0031
+32 0032
+33 0033
+34 0034
+35 0035
+36 0036
+37 0037
+38 0038
+39 0039
+3A 003A
+3B 003B
+3C 003C
+3D 003D
+3E 003E
+3F 003F
+40 0040
+41 0041
+42 0042
+43 0043
+44 0044
+45 0045
+46 0046
+47 0047
+48 0048
+49 0049
+4A 004A
+4B 004B
+4C 004C
+4D 004D
+4E 004E
+4F 004F
+50 0050
+51 0051
+52 0052
+53 0053
+54 0054
+55 0055
+56 0056
+57 0057
+58 0058
+59 0059
+5A 005A
+5B 005B
+5C 005C
+5D 005D
+5E 005E
+5F 005F
+60 0060
+61 0061
+62 0062
+63 0063
+64 0064
+65 0065
+66 0066
+67 0067
+68 0068
+69 0069
+6A 006A
+6B 006B
+6C 006C
+6D 006D
+6E 006E
+6F 006F
+70 0070
+71 0071
+72 0072
+73 0073
+74 0074
+75 0075
+76 0076
+77 0077
+78 0078
+79 0079
+7A 007A
+7B 007B
+7C 007C
+7D 007D
+7E 007E
+7F 007F
+80 20AC
+85 2026
+91 2018
+92 2019
+93 201C
+94 201D
+95 2022
+96 2013
+97 2014
+A0 00A0
+A1 0E01
+A2 0E02
+A3 0E03
+A4 0E04
+A5 0E05
+A6 0E06
+A7 0E07
+A8 0E08
+A9 0E09
+AA 0E0A
+AB 0E0B
+AC 0E0C
+AD 0E0D
+AE 0E0E
+AF 0E0F
+B0 0E10
+B1 0E11
+B2 0E12
+B3 0E13
+B4 0E14
+B5 0E15
+B6 0E16
+B7 0E17
+B8 0E18
+B9 0E19
+BA 0E1A
+BB 0E1B
+BC 0E1C
+BD 0E1D
+BE 0E1E
+BF 0E1F
+C0 0E20
+C1 0E21
+C2 0E22
+C3 0E23
+C4 0E24
+C5 0E25
+C6 0E26
+C7 0E27
+C8 0E28
+C9 0E29
+CA 0E2A
+CB 0E2B
+CC 0E2C
+CD 0E2D
+CE 0E2E
+CF 0E2F
+D0 0E30
+D1 0E31
+D2 0E32
+D3 0E33
+D4 0E34
+D5 0E35
+D6 0E36
+D7 0E37
+D8 0E38
+D9 0E39
+DA 0E3A
+DF 0E3F
+E0 0E40
+E1 0E41
+E2 0E42
+E3 0E43
+E4 0E44
+E5 0E45
+E6 0E46
+E7 0E47
+E8 0E48
+E9 0E49
+EA 0E4A
+EB 0E4B
+EC 0E4C
+ED 0E4D
+EE 0E4E
+EF 0E4F
+F0 0E50
+F1 0E51
+F2 0E52
+F3 0E53
+F4 0E54
+F5 0E55
+F6 0E56
+F7 0E57
+F8 0E58
+F9 0E59
+FA 0E5A
+FB 0E5B
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 000000000..bc92f3e7e
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,248 @@
+#
+# "$Id$"
+#
+# Documentation makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# HTMLDOC generation rules...
+#
+
+.SUFFIXES: .html .pdf .ps .shtml
+.shtml.html:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --numbered -f $@ $<
+.shtml.pdf:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --numbered --jpeg -f $@ $<
+.shtml.ps:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --numbered \
+ --jpeg -f $@ $<
+
+HTMLDOC = htmldoc --strict --verbose --bodycolor white
+
+
+#
+# Document files...
+#
+
+DOCUMENTS = cmp.shtml idd.shtml ipp.shtml sam.shtml sdd.shtml \
+ spm.shtml sps.shtml ssr.shtml stp.shtml sum.shtml \
+ svd.shtml translation.shtml
+DOCIMAGES = images/cups-block-diagram.gif images/cups-large.gif \
+ images/cups-medium.gif images/cups-small.gif
+WEBPAGES = cups.css cupsdoc.css index.html documentation.html \
+ robots.txt
+WEBIMAGES = images/accept-jobs.gif \
+ images/add-class.gif \
+ images/add-printer.gif \
+ images/cancel-job.gif \
+ images/classes.gif \
+ images/config-printer.gif \
+ images/continue.gif \
+ images/delete-class.gif \
+ images/delete-printer.gif \
+ images/hold-job.gif \
+ images/left.gif \
+ images/logo.gif \
+ images/manage-classes.gif \
+ images/manage-jobs.gif \
+ images/manage-printers.gif \
+ images/modify-class.gif \
+ images/modify-printer.gif \
+ images/navbar.gif \
+ images/print-test-page.gif \
+ images/printer-idle.gif \
+ images/printer-processing.gif \
+ images/printer-stopped.gif \
+ images/reject-jobs.gif \
+ images/release-job.gif \
+ images/restart-job.gif \
+ images/right.gif \
+ images/set-as-default.gif \
+ images/show-active.gif \
+ images/show-completed.gif \
+ images/start-class.gif \
+ images/start-printer.gif \
+ images/stop-class.gif \
+ images/stop-printer.gif
+
+
+#
+# Make all documents...
+#
+
+all: $(DOCUMENTS:.shtml=.pdf) $(DOCUMENTS:.shtml=.html) overview.pdf
+ cd be; $(MAKE) $(MFLAGS) all
+ cd de; $(MAKE) $(MFLAGS) all
+ cd es; $(MAKE) $(MFLAGS) all
+ cd fr; $(MAKE) $(MFLAGS) all
+
+
+#
+# Make PS files...
+#
+
+ps: $(DOCUMENTS:.shtml=.ps) overview.ps
+ cd fr; $(MAKE) $(MFLAGS) ps
+
+
+#
+# Remove all generated files...
+#
+
+clean:
+ $(RM) $(DOCUMENTS:.shtml=.pdf)
+ $(RM) $(DOCUMENTS:.shtml=.html)
+ $(RM) overview.pdf
+ cd de; $(MAKE) $(MFLAGS) clean
+ cd fr; $(MAKE) $(MFLAGS) clean
+
+
+#
+# Install all documentation files...
+#
+
+install:
+ $(INSTALL_DIR) $(DOCDIR)
+ for file in $(WEBPAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR); \
+ done
+ $(INSTALL_MAN) overview.html $(DOCDIR)
+ $(INSTALL_MAN) overview.pdf $(DOCDIR)
+ for file in $(DOCUMENTS:.shtml=.html); do \
+ $(INSTALL_MAN) $$file $(DOCDIR); \
+ done
+ for file in $(DOCUMENTS:.shtml=.pdf); do \
+ $(INSTALL_MAN) $$file $(DOCDIR); \
+ done
+ $(INSTALL_DIR) $(DOCDIR)/images
+ for file in $(WEBIMAGES) $(DOCIMAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/images; \
+ done
+ cd be; $(MAKE) $(MFLAGS) install
+ cd de; $(MAKE) $(MFLAGS) install
+ cd es; $(MAKE) $(MFLAGS) install
+ cd fr; $(MAKE) $(MFLAGS) install
+
+
+#
+# The overview, admin manual, programmers manual, and users manual get
+# special attention...
+#
+
+overview.pdf: overview.html
+ echo Formatting $@...
+ $(HTMLDOC) --duplex --compression=9 --jpeg --webpage -f overview.pdf overview.html
+overview.ps: overview.html
+ echo Formatting $@...
+ $(HTMLDOC) --duplex --jpeg --webpage -f overview.ps overview.html
+
+sam.html: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif -f $@ $<
+sam.pdf: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+sam.ps: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+spm.html: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif -f $@ $<
+spm.pdf: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+spm.ps: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+sum.html: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --verbose --titleimage images/cups-large.gif -f $@ $<
+sum.pdf: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+sum.ps: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+sam-7x8.pdf: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --pagelayout tworight --pagemode document \
+ --jpeg --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml
+sam-7x8.ps: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \
+ --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sam.shtml
+spm-7x8.pdf: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --pagelayout tworight --pagemode document \
+ --jpeg --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml
+spm-7x8.ps: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \
+ --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ spm.shtml
+sum-7x8.pdf: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --pagelayout tworight --pagemode document \
+ --jpeg --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml
+sum-7x8.ps: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --jpeg \
+ --size 7x8.5in --left 0.5in --right 0.25in \
+ --top 0.25in --bottom 0.25in --fontsize 10 --headfootsize 10 -f $@ sum.shtml
+
+$(DOCUMENTS:.shtml=.html): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../LICENSE.html
+
+$(DOCUMENTS:.shtml=.pdf): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../LICENSE.html
+
+$(DOCUMENTS:.shtml=.ps): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../LICENSE.html
+
+
+#
+# End of Makefile.
+#
diff --git a/doc/be/Makefile b/doc/be/Makefile
new file mode 100644
index 000000000..3273b395a
--- /dev/null
+++ b/doc/be/Makefile
@@ -0,0 +1,90 @@
+#
+# "$Id$"
+#
+# Documentation makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Document files...
+#
+
+WEBPAGES = index.html documentation.html
+WEBIMAGES = images/accept-jobs.gif \
+ images/add-class.gif \
+ images/add-printer.gif \
+ images/cancel-job.gif \
+ images/config-printer.gif \
+ images/continue.gif \
+ images/delete-class.gif \
+ images/delete-printer.gif \
+ images/hold-job.gif \
+ images/manage-classes.gif \
+ images/manage-jobs.gif \
+ images/manage-printers.gif \
+ images/modify-class.gif \
+ images/modify-printer.gif \
+ images/navbar.gif \
+ images/print-test-page.gif \
+ images/reject-jobs.gif \
+ images/release-job.gif \
+ images/restart-job.gif \
+ images/show-active.gif \
+ images/show-completed.gif \
+ images/start-class.gif \
+ images/start-printer.gif \
+ images/stop-class.gif \
+ images/stop-printer.gif
+
+
+#
+# Make all documents...
+#
+
+all:
+
+
+#
+# Remove all generated files...
+#
+
+clean:
+
+
+#
+# Install all documentation files...
+#
+
+install:
+ $(INSTALL_DIR) $(DOCDIR)/be
+ for file in $(WEBPAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/be; \
+ done
+ $(INSTALL_DIR) $(DOCDIR)/be/images
+ for file in $(WEBIMAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/be/images; \
+ done
+
+
+#
+# End of Makefile.
+#
diff --git a/doc/be/cups.css b/doc/be/cups.css
new file mode 100644
index 000000000..9285a5b5e
--- /dev/null
+++ b/doc/be/cups.css
@@ -0,0 +1,4 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+TH { text-align: left }
+
diff --git a/doc/be/cupsdoc.css b/doc/be/cupsdoc.css
new file mode 100644
index 000000000..333f20144
--- /dev/null
+++ b/doc/be/cupsdoc.css
@@ -0,0 +1,9 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUP { font-family: sans-serif; font-size: 6pt }
+PRE { margin-left: 2em }
+CODE { font-weight: bold }
diff --git a/doc/be/documentation.html b/doc/be/documentation.html
new file mode 100644
index 000000000..a9a425bf7
--- /dev/null
+++ b/doc/be/documentation.html
@@ -0,0 +1,91 @@
+<HTML>
+<HEAD>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <TITLE>Даведка - Common UNIX Printing System</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,0,50,30" HREF="http://www.easysw.com" ALT="СвойÑÐºÐ°Ñ Ñтаронка Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,0,208,30" HREF="/admin" ALT="Выканаць адмініÑÑ‚Ñ€Ð°Ñ‚Ñ‹ÑžÐ½ÑƒÑ Ð¿Ñ€Ð°Ñ†Ñ‹">
+ <AREA SHAPE="RECT" COORDS="225,0,267,30" HREF="/classes" ALT="Кіраваць Ñтанам клÑÑаў друкарак">
+ <AREA SHAPE="RECT" COORDS="284,0,342,30" HREF="/documentation.html" ALT="Ð–Ñ‹Ð²Ð°Ñ Ð´Ð°Ð²ÐµÐ´ÐºÐ°">
+ <AREA SHAPE="RECT" COORDS="359,0,420,30" HREF="/jobs" ALT="Кіраваць заданьнÑмі">
+ <AREA SHAPE="RECT" COORDS="437,0,500,30" HREF="/printers" ALT="Кіраваць друкаркамі">
+ <AREA SHAPE="RECT" COORDS="518,0,585,30" HREF="http://www.cups.org" ALT="Выгрузіць бÑгучую вÑÑ€ÑÑ‹ÑŽ праграмнага забеÑьпÑчÑÐ½ÑŒÐ½Ñ CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="601" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System (ÐÐ³ÑƒÐ»ÑŒÐ½Ð°Ñ ÑÑ‹ÑÑ‚Ñма друку Ð´Ð»Ñ UNIX)">
+</CENTER>
+
+<H1>Даведка</H1>
+
+<P>Ðа гÑтым паÑлужніке маецца Ñž наÑўнаÑьці наÑÑ‚ÑƒÐ¿Ð½Ð°Ñ Ð´Ð°ÐºÑƒÐ¼ÑÐ½Ñ‚Ð°Ñ†Ñ‹Ñ Ð¿Ð° CUPS:
+
+<UL>
+
+ <LI>ÐглÑд агульнае ÑÑ‹ÑÑ‚Ñмы друку Ð´Ð»Ñ UNIX (
+ <A HREF="overview.html">HTML</A> |
+ <A HREF="overview.pdf">PDF</A> )
+
+ <LI>Дапаможнік карыÑтальніка (
+ <A HREF="sum.html">HTML</A> |
+ <A HREF="sum.pdf">PDF</A> )
+
+ <LI>Дапаможнік ÑÑ‹ÑÑ‚Ñмнага адмініÑтратара (
+ <A HREF="sam.html">HTML</A> |
+ <A HREF="sam.pdf">PDF</A> )
+
+ <LI>Дапаможнік праграміÑта (
+ <A HREF="spm.html">HTML</A> |
+ <A HREF="spm.pdf">PDF</A> )
+
+ <LI>ПлÑн кіраўніцтва наладкай (
+ <A HREF="cmp.html">HTML</A> |
+ <A HREF="cmp.pdf">PDF</A> )
+
+ <LI>ÐжыцьцÑўленьне IPP у CUPS (
+ <A HREF="ipp.html">HTML</A> |
+ <A HREF="ipp.pdf">PDF</A> )
+
+ <LI>ÐпіÑаньне дызайну ÑпалучÑньнÑÑž (
+ <A HREF="idd.html">HTML</A> |
+ <A HREF="idd.pdf">PDF</A> )
+
+ <LI>ÐпіÑаньне дызайну праграмы (
+ <A HREF="sdd.html">HTML</A> |
+ <A HREF="sdd.pdf">PDF</A> )
+
+ <LI>СпÑÑ†Ñ‹Ñ„Ñ–ÐºÐ°Ñ†Ñ‹Ñ Ð²Ñ‹Ñ‚Ð²Ð¾Ñ€Ñ‡Ð°Ñьці праграмы (
+ <A HREF="sps.html">HTML</A> |
+ <A HREF="sps.pdf">PDF</A> )
+
+ <LI>Справаздача аб бÑÑьпецы (
+ <A HREF="ssr.html">HTML</A> |
+ <A HREF="ssr.pdf">PDF</A> )
+
+ <LI>Кіраўніцтва па перакладаньню (
+ <A HREF="translation.html">HTML</A> |
+ <A HREF="translation.pdf">PDF</A> )
+
+ <LI>ПлÑн Ñ‚ÑÑту праграмы (
+ <A HREF="stp.html">HTML</A> |
+ <A HREF="stp.pdf">PDF</A> )
+
+ <LI>ÐпіÑаньне вÑÑ€ÑÑ‹Ñ– праграмы (
+ <A HREF="svd.html">HTML</A> |
+ <A HREF="svd.pdf">PDF</A> )
+
+</UL>
+
+<HR>
+
+<P>Common UNIX Printing System, CUPS Ñ– лÑгатып CUPS зьÑўлÑюцца гандлёвымі маркамі
+<A HREF="http://www.easysw.com">Easy Software
+Products</A>. ÐўтарÑÐºÑ–Ñ Ð¿Ñ€Ð°Ð²Ñ‹ Ñž 1997-2003 гадох належаць Easy Software Products. УÑе правы абаронены.
+</BODY>
+</HTML>
diff --git a/doc/be/images/accept-jobs.gif b/doc/be/images/accept-jobs.gif
new file mode 100644
index 000000000..67463b18a
--- /dev/null
+++ b/doc/be/images/accept-jobs.gif
Binary files differ
diff --git a/doc/be/images/add-class.gif b/doc/be/images/add-class.gif
new file mode 100644
index 000000000..7ce1215d4
--- /dev/null
+++ b/doc/be/images/add-class.gif
Binary files differ
diff --git a/doc/be/images/add-printer.gif b/doc/be/images/add-printer.gif
new file mode 100644
index 000000000..c59eebae1
--- /dev/null
+++ b/doc/be/images/add-printer.gif
Binary files differ
diff --git a/doc/be/images/cancel-job.gif b/doc/be/images/cancel-job.gif
new file mode 100644
index 000000000..56e2f88fb
--- /dev/null
+++ b/doc/be/images/cancel-job.gif
Binary files differ
diff --git a/doc/be/images/classes.gif b/doc/be/images/classes.gif
new file mode 100644
index 000000000..ace15df98
--- /dev/null
+++ b/doc/be/images/classes.gif
Binary files differ
diff --git a/doc/be/images/config-printer.gif b/doc/be/images/config-printer.gif
new file mode 100644
index 000000000..98dbd1412
--- /dev/null
+++ b/doc/be/images/config-printer.gif
Binary files differ
diff --git a/doc/be/images/continue.gif b/doc/be/images/continue.gif
new file mode 100644
index 000000000..008fead14
--- /dev/null
+++ b/doc/be/images/continue.gif
Binary files differ
diff --git a/doc/be/images/cups-large.gif b/doc/be/images/cups-large.gif
new file mode 100644
index 000000000..fc66ef07c
--- /dev/null
+++ b/doc/be/images/cups-large.gif
Binary files differ
diff --git a/doc/be/images/cups-medium.gif b/doc/be/images/cups-medium.gif
new file mode 100644
index 000000000..c45ed6ab9
--- /dev/null
+++ b/doc/be/images/cups-medium.gif
Binary files differ
diff --git a/doc/be/images/cups-small.gif b/doc/be/images/cups-small.gif
new file mode 100644
index 000000000..6adb4a29f
--- /dev/null
+++ b/doc/be/images/cups-small.gif
Binary files differ
diff --git a/doc/be/images/delete-class.gif b/doc/be/images/delete-class.gif
new file mode 100644
index 000000000..996a116ff
--- /dev/null
+++ b/doc/be/images/delete-class.gif
Binary files differ
diff --git a/doc/be/images/delete-printer.gif b/doc/be/images/delete-printer.gif
new file mode 100644
index 000000000..71095e304
--- /dev/null
+++ b/doc/be/images/delete-printer.gif
Binary files differ
diff --git a/doc/be/images/hold-job.gif b/doc/be/images/hold-job.gif
new file mode 100644
index 000000000..cb3858446
--- /dev/null
+++ b/doc/be/images/hold-job.gif
Binary files differ
diff --git a/doc/be/images/left.gif b/doc/be/images/left.gif
new file mode 100644
index 000000000..fd7b04104
--- /dev/null
+++ b/doc/be/images/left.gif
Binary files differ
diff --git a/doc/be/images/logo.gif b/doc/be/images/logo.gif
new file mode 100644
index 000000000..9999795ca
--- /dev/null
+++ b/doc/be/images/logo.gif
Binary files differ
diff --git a/doc/be/images/manage-classes.gif b/doc/be/images/manage-classes.gif
new file mode 100644
index 000000000..339985815
--- /dev/null
+++ b/doc/be/images/manage-classes.gif
Binary files differ
diff --git a/doc/be/images/manage-jobs.gif b/doc/be/images/manage-jobs.gif
new file mode 100644
index 000000000..22b867d6b
--- /dev/null
+++ b/doc/be/images/manage-jobs.gif
Binary files differ
diff --git a/doc/be/images/manage-printers.gif b/doc/be/images/manage-printers.gif
new file mode 100644
index 000000000..3e99c55df
--- /dev/null
+++ b/doc/be/images/manage-printers.gif
Binary files differ
diff --git a/doc/be/images/modify-class.gif b/doc/be/images/modify-class.gif
new file mode 100644
index 000000000..509df9f51
--- /dev/null
+++ b/doc/be/images/modify-class.gif
Binary files differ
diff --git a/doc/be/images/modify-printer.gif b/doc/be/images/modify-printer.gif
new file mode 100644
index 000000000..06b64de17
--- /dev/null
+++ b/doc/be/images/modify-printer.gif
Binary files differ
diff --git a/doc/be/images/navbar.gif b/doc/be/images/navbar.gif
new file mode 100644
index 000000000..d372e7a5b
--- /dev/null
+++ b/doc/be/images/navbar.gif
Binary files differ
diff --git a/doc/be/images/print-test-page.gif b/doc/be/images/print-test-page.gif
new file mode 100644
index 000000000..9fd951ccd
--- /dev/null
+++ b/doc/be/images/print-test-page.gif
Binary files differ
diff --git a/doc/be/images/printer-idle.gif b/doc/be/images/printer-idle.gif
new file mode 100644
index 000000000..68d990c62
--- /dev/null
+++ b/doc/be/images/printer-idle.gif
Binary files differ
diff --git a/doc/be/images/printer-processing.gif b/doc/be/images/printer-processing.gif
new file mode 100644
index 000000000..a9a23f795
--- /dev/null
+++ b/doc/be/images/printer-processing.gif
Binary files differ
diff --git a/doc/be/images/printer-stopped.gif b/doc/be/images/printer-stopped.gif
new file mode 100644
index 000000000..76f45649b
--- /dev/null
+++ b/doc/be/images/printer-stopped.gif
Binary files differ
diff --git a/doc/be/images/reject-jobs.gif b/doc/be/images/reject-jobs.gif
new file mode 100644
index 000000000..c47cdecbc
--- /dev/null
+++ b/doc/be/images/reject-jobs.gif
Binary files differ
diff --git a/doc/be/images/release-job.gif b/doc/be/images/release-job.gif
new file mode 100644
index 000000000..67e1ab082
--- /dev/null
+++ b/doc/be/images/release-job.gif
Binary files differ
diff --git a/doc/be/images/restart-job.gif b/doc/be/images/restart-job.gif
new file mode 100644
index 000000000..716ced450
--- /dev/null
+++ b/doc/be/images/restart-job.gif
Binary files differ
diff --git a/doc/be/images/right.gif b/doc/be/images/right.gif
new file mode 100644
index 000000000..8ae8213ce
--- /dev/null
+++ b/doc/be/images/right.gif
Binary files differ
diff --git a/doc/be/images/show-active.gif b/doc/be/images/show-active.gif
new file mode 100644
index 000000000..f36dd42f6
--- /dev/null
+++ b/doc/be/images/show-active.gif
Binary files differ
diff --git a/doc/be/images/show-completed.gif b/doc/be/images/show-completed.gif
new file mode 100644
index 000000000..7ac49cad1
--- /dev/null
+++ b/doc/be/images/show-completed.gif
Binary files differ
diff --git a/doc/be/images/start-class.gif b/doc/be/images/start-class.gif
new file mode 100644
index 000000000..e592bd96c
--- /dev/null
+++ b/doc/be/images/start-class.gif
Binary files differ
diff --git a/doc/be/images/start-printer.gif b/doc/be/images/start-printer.gif
new file mode 100644
index 000000000..8eeea544d
--- /dev/null
+++ b/doc/be/images/start-printer.gif
Binary files differ
diff --git a/doc/be/images/stop-class.gif b/doc/be/images/stop-class.gif
new file mode 100644
index 000000000..a0861af6c
--- /dev/null
+++ b/doc/be/images/stop-class.gif
Binary files differ
diff --git a/doc/be/images/stop-printer.gif b/doc/be/images/stop-printer.gif
new file mode 100644
index 000000000..cdbacc8b1
--- /dev/null
+++ b/doc/be/images/stop-printer.gif
Binary files differ
diff --git a/doc/be/index.html b/doc/be/index.html
new file mode 100644
index 000000000..5f5c31d47
--- /dev/null
+++ b/doc/be/index.html
@@ -0,0 +1,37 @@
+<HTML>
+<HEAD>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <TITLE>Common UNIX Printing System / ÐÐ³ÑƒÐ»ÑŒÐ½Ð°Ñ ÑÑ‹ÑÑ‚Ñма друку Ð´Ð»Ñ UNIX</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,0,50,30" HREF="http://www.easysw.com" ALT="СвойÑÐºÐ°Ñ Ñтаронка Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,0,208,30" HREF="/admin" ALT="Выканаць адмініÑÑ‚Ñ€Ð°Ñ‚Ñ‹ÑžÐ½ÑƒÑ Ð¿Ñ€Ð°Ñ†Ñ‹">
+ <AREA SHAPE="RECT" COORDS="225,0,267,30" HREF="/classes" ALT="Кіраваць Ñтанам клÑÑаў друкарак">
+ <AREA SHAPE="RECT" COORDS="284,0,342,30" HREF="/documentation.html" ALT="Ð–Ñ‹Ð²Ð°Ñ Ð´Ð°Ð²ÐµÐ´ÐºÐ°">
+ <AREA SHAPE="RECT" COORDS="359,0,420,30" HREF="/jobs" ALT="Кіраваць заданьнÑмі">
+ <AREA SHAPE="RECT" COORDS="437,0,500,30" HREF="/printers" ALT="Кіраваць друкаркамі">
+ <AREA SHAPE="RECT" COORDS="518,0,585,30" HREF="http://www.cups.org" ALT="Выгрузіць бÑгучую вÑÑ€ÑÑ‹ÑŽ праграмнага забеÑьпÑчÑÐ½ÑŒÐ½Ñ CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="601" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System (ÐÐ³ÑƒÐ»ÑŒÐ½Ð°Ñ ÑÑ‹ÑÑ‚Ñма друку Ð´Ð»Ñ UNIX)">
+</CENTER>
+
+<H2><A HREF="admin">ÐдмініÑтраваньне</A></H2>
+<H2><A HREF="classes">Кіраваньне клÑÑамі друкарак</A></H2>
+<H2><A HREF="documentation.html">Даведка</A></H2>
+<H2><A HREF="jobs">Кіраваньне заданьнÑмі</A></H2>
+<H2><A HREF="printers">Кіраваньне друкаркамі</A></H2>
+<H2><A HREF="http://www.cups.org">Выгрузіць бÑгучае праграмнае забеÑьпÑчÑньне CUPS</A></H2>
+
+<HR>
+
+<P>Common UNIX Printing System, CUPS Ñ– лÑгатып CUPS зьÑўлÑюцца гандлёвымі
+маркамі <A HREF="http://www.easysw.com">Easy Software
+Products</A>. ÐўтарÑÐºÑ–Ñ Ð¿Ñ€Ð°Ð²Ñ‹ Ñž 1997-2003 гадох належаць Easy Software Products.
+УÑе правы абаронены.</P
+
+</BODY>
+</HTML>
diff --git a/doc/be/robots.txt b/doc/be/robots.txt
new file mode 100644
index 000000000..b8ff9b469
--- /dev/null
+++ b/doc/be/robots.txt
@@ -0,0 +1,31 @@
+#
+# "$Id: robots.txt 4054 2004-02-17 20:10:45Z mike $"
+#
+# This file tells search engines not to index your CUPS server.
+#
+# Copyright 1993-2003 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+User-agent: *
+Disallow: /
+
+#
+# End of "$Id: robots.txt 4054 2004-02-17 20:10:45Z mike $".
+#
+
diff --git a/doc/cmp.html b/doc/cmp.html
new file mode 100644
index 000000000..cafc724ea
--- /dev/null
+++ b/doc/cmp.html
@@ -0,0 +1,745 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Configuration Management Plan</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-CMP-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Configuration Management Plan</H1></A><BR>
+CUPS-CMP-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 File Management</A></B>
+<UL>
+<LI><A HREF="#3_1">3.1 Directory Structure</A></LI>
+<LI><A HREF="#3_2">3.2 Source Files</A></LI>
+<LI><A HREF="#3_3">3.3 Configuration Management</A></LI>
+</UL>
+<B><A HREF="#4">4 Trouble Report Processing</A></B>
+<UL>
+<LI><A HREF="#4_1">4.1 Classification</A></LI>
+<LI><A HREF="#4_2">4.2 Identification</A></LI>
+<LI><A HREF="#4_3">4.3 Correction</A></LI>
+<LI><A HREF="#4_4">4.4 Notification</A></LI>
+</UL>
+<B><A HREF="#5">5 Software Releases</A></B>
+<UL>
+<LI><A HREF="#5_1">5.1 Version Numbering</A></LI>
+<LI><A HREF="#5_2">5.2 Generation</A></LI>
+<LI><A HREF="#5_3">5.3 Testing</A></LI>
+<LI><A HREF="#5_4">5.4 Releases</A></LI>
+<UL>
+<LI><A HREF="#5_4_1">5.4.1 Beta Releases</A></LI>
+<LI><A HREF="#5_4_2">5.4.2 Release Candidates</A></LI>
+<LI><A HREF="#5_4_3">5.4.3 Production Releases</A></LI>
+</UL>
+</UL>
+<B><A HREF="#6">A Glossary</A></B>
+<UL>
+<LI><A HREF="#6_1">A.1 Terms</A></LI>
+<LI><A HREF="#6_2">A.2 Acronyms</A></LI>
+</UL>
+<B><A HREF="#7">B Coding Requirements</A></B>
+<UL>
+<LI><A HREF="#7_1">B.1 Source Files</A></LI>
+<UL>
+<LI><A HREF="#7_1_1">B.1.1 Naming</A></LI>
+<LI><A HREF="#7_1_2">B.1.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_2">B.2 Functions</A></LI>
+<UL>
+<LI><A HREF="#7_2_1">B.2.1 Naming</A></LI>
+<LI><A HREF="#7_2_2">B.2.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_3">B.3 Methods</A></LI>
+<UL>
+<LI><A HREF="#7_3_1">B.3.1 Naming</A></LI>
+<LI><A HREF="#7_3_2">B.3.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_4">B.4 Variables</A></LI>
+<UL>
+<LI><A HREF="#7_4_1">B.4.1 Naming</A></LI>
+<LI><A HREF="#7_4_2">B.4.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_5">B.5 Types</A></LI>
+<UL>
+<LI><A HREF="#7_5_1">B.5.1 Naming</A></LI>
+<LI><A HREF="#7_5_2">B.5.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_6">B.6 Structures</A></LI>
+<UL>
+<LI><A HREF="#7_6_1">B.6.1 Naming</A></LI>
+<LI><A HREF="#7_6_2">B.6.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_7">B.7 Classes</A></LI>
+<UL>
+<LI><A HREF="#7_7_1">B.7.1 Naming</A></LI>
+<LI><A HREF="#7_7_2">B.7.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_8">B.8 Constants</A></LI>
+<UL>
+<LI><A HREF="#7_8_1">B.8.1 Naming</A></LI>
+<LI><A HREF="#7_8_2">B.8.2 Documentation</A></LI>
+</UL>
+<LI><A HREF="#7_9">B.9 Code</A></LI>
+<UL>
+<LI><A HREF="#7_9_1">B.9.1 Documentation</A></LI>
+<LI><A HREF="#7_9_2">B.9.2 Style</A></LI>
+</UL>
+</UL>
+<B><A HREF="#8">C Software Trouble Report Form</A></B><HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This configuration management plan document provides the guidelines
+ for development and maintenance of the Common UNIX Printing System
+ (&quot;CUPS&quot;) Version 1.1 software.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This configuration management document is organized into the
+ following sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - File Management</LI>
+<LI>4 - Trouble Report Processing</LI>
+<LI>5 - Software Releases</LI>
+<LI>A - Glossary</LI>
+<LI>B - Coding Requirements</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 File Management</A></H1>
+<H2><A NAME="3_1">3.1 Directory Structure</A></H2>
+<P>Each source file shall be placed a sub-directory corresponding to the
+ software sub-system it belongs to (&quot;scheduler&quot;, &quot;cups&quot;, etc.) To remain
+ compatible with older UNIX filesystems, directory names shall not
+ exceed 16 characters in length.</P>
+<H2><A NAME="3_2">3.2 Source Files</A></H2>
+<P>Source files shall be documented and formatted as described in
+ Appendix B, Coding Requirements. To remain compatible with older UNIX
+ filesystems, source file names shall not exceed 16 characters in
+ length.</P>
+<H2><A NAME="3_3">3.3 Configuration Management</A></H2>
+<P>Source files shall be placed under the control of the Concurrent
+ Versions System (&quot;CVS&quot;) software. Source files shall be &quot;checked in&quot;
+ with each change so that modifications can be tracked.</P>
+<P>Documentation on the CVS software is included with the whitepaper,
+ &quot;CVS II: Parallelizing Software Development&quot;.</P>
+<H1><A NAME="4">4 Trouble Report Processing</A></H1>
+<P>A Software Trouble Report (&quot;STR&quot;) shall be submitted every time a
+ user or vendor experiences a problem with the CUPS software. Trouble
+ reports are maintained in a database with one of the following states:</P>
+<OL>
+<LI>STR is closed with complete resolution</LI>
+<LI>STR is closed without resolution</LI>
+<LI>STR is active</LI>
+<LI>STR is pending (new STR or additional information available)</LI>
+</OL>
+<P>Trouble reports shall be processed using the following steps.</P>
+<H2><A NAME="4_1">4.1 Classification</A></H2>
+<P>When a trouble report is received it must be classified at one of the
+ following priority levels:</P>
+<OL>
+<LI>Request for enhancement, e.g. asking for a feature</LI>
+<LI>Low, e.g. a documentation error or undocumented side-effect</LI>
+<LI>Moderate, e.g. unable to print a file or unable to compile the
+ software</LI>
+<LI>High, e.g. unable to print to a printer or key functionality not
+ working</LI>
+<LI>Critical, e.g. unable to print at all</LI>
+</OL>
+<P>Level 4 and 5 trouble reports must be resolved in the next software
+ release. Level 1 to 3 trouble reports are scheduled for resolution in a
+ specific release at the discretion of the release coordinator.</P>
+<P>The scope of the problem should also be determined as:</P>
+<OL>
+<LI>Specific to a machine or printer</LI>
+<LI>Specific to an operating system</LI>
+<LI>Applies to all machines, printers, and operating systems</LI>
+</OL>
+<H2><A NAME="4_2">4.2 Identification</A></H2>
+<P>Once the level and scope of the trouble report is determined the
+ software sub-system(s) involved with the problem are determined. This
+ may involve additional communication with the user or vendor to isolate
+ the problem to a specific cause.</P>
+<P>When the sub-system(s) involved have been identified, an engineer
+ will then determine the change(s) needed and estimate the time required
+ for the change(s).</P>
+<H2><A NAME="4_3">4.3 Correction</A></H2>
+<P>Corrections are scheduled based upon the severity and complexity of
+ the problem. Once all changes have been made, documented, and tested
+ successfully a new software release snapshot is generated. Additional
+ tests are added as necessary for proper testing of the changes.</P>
+<H2><A NAME="4_4">4.4 Notification</A></H2>
+<P>The user or vendor is notified when the fix is available or if the
+ problem was caused by user error.</P>
+<H1><A NAME="5">5 Software Releases</A></H1>
+<H2><A NAME="5_1">5.1 Version Numbering</A></H2>
+<P>CUPS uses a three-part version number separated by periods to
+ represent the major, minor, and patch release numbers:</P>
+<PRE>
+ MAJOR.MINOR.PATCH
+ 1.1.0
+</PRE>
+<P>Beta-test releases are indentified by appending the letter B followed
+ by the build number:</P>
+<PRE>
+ MAJOR.MINOR.PATCHbBUILD
+ 1.1.0b1
+</PRE>
+<P>Release candidates are indentified by appending the letters RC
+ followed by the build number:</P>
+<PRE>
+ MAJOR.MINOR.PATCHrcBUILD
+ 1.1.0rc1
+</PRE>
+<P>A CVS snapshot is generated for every beta and final release and uses
+ the version number preceded by the letter &quot;v&quot; and with the decimal
+ points replaced by underscores:</P>
+<PRE>
+ v1_1_0b1
+ v1_1_0rc1
+ v1_1_0
+</PRE>
+<P>Each change that corrects a fault in a software sub-system increments
+ the patch release number. If a change affects the overall software
+ design of CUPS then the minor release number will be incremented and
+ the patch release number reset to 0. If CUPS is completely redesigned
+ the major release number will be incremented and the minor and patch
+ release numbers reset to 0:</P>
+<PRE>
+ 1.1.0b1 First beta release
+ 1.1.0b2 Second beta release
+ 1.1.0rc1 First release candidate
+ 1.1.0rc2 Second release candidate
+ 1.1.0 First production release
+ 1.1.1b1 First beta of 1.1.1
+ 1.1.1rc1 First release candidate of 1.1.1
+ 1.1.1 Production release of 1.1.1
+ 1.1.2b1 First beta of 1.1.2
+ 1.1.2rc1 First release candidate of 1.1.2
+ 1.1.2 Production release of 1.1.2
+ 2.0.0b1 First beta of 2.0.0
+ 2.0.0rc1 First release candidate of 2.0.0
+ 2.0.0 Production release of 2.0.0
+</PRE>
+<H2><A NAME="5_2">5.2 Generation</A></H2>
+<P>Software releases shall be generated for each successfully completed
+ software trouble report. All object and executable files shall be
+ deleted prior to performing a full build to ensure that source files
+ are recompiled.</P>
+<H2><A NAME="5_3">5.3 Testing</A></H2>
+<P>Software testing shall be conducted according to the CUPS Software
+ Test Plan, CUPS-STP-1.1. Failed tests cause STRs to be generated to
+ correct the problems found.</P>
+<H2><A NAME="5_4">5.4 Releases</A></H2>
+<P>When testing has been completed successfully a new distribution image
+ is created from the current CVS code &quot;snapshot&quot;. No release shall
+ contain software that has not passed the appropriate software tests.
+ Three types of releases are used, beta, release candidate, and
+ production, and are released using the following basic schedule:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH>Week</TH><TH>Version</TH><TH>Description</TH></TR>
+<TR><TD>T-6 weeks</TD><TD>1.1.0b1</TD><TD>First beta</TD></TR>
+<TR><TD>T-5 weeks</TD><TD>1.1.0b2</TD><TD>Second beta</TD></TR>
+<TR><TD>T-4 weeks</TD><TD>1.1.0b3</TD><TD>Third beta</TD></TR>
+<TR><TD>T-3 weeks</TD><TD>1.1.0rc1</TD><TD>First release candidate</TD></TR>
+<TR><TD>T-2 weeks</TD><TD>1.1.0rc2</TD><TD>Second release candidate</TD></TR>
+<TR><TD>T-0 weeks</TD><TD>1.1.0</TD><TD>Production</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>Beta releases are typically used prior to new major and minor version
+ releases. At least one release candidate is generated prior to each
+ production release.</P>
+<H3><A NAME="5_4_1">5.4.1 Beta Releases</A></H3>
+<P>Beta releases are generated when substantial changes have been made
+ that may affect the reliability of the software. Beta releases may
+ cause loss of data, functionality, or services and are provided for
+ testing by qualified individuals.</P>
+<P>Beta releases are an OPTIONAL part of the release process and are
+ generated as deemed appropriate by the release coordinator. Functional
+ changes may be included in subsequent beta releases until the first
+ release candidate.</P>
+<H3><A NAME="5_4_2">5.4.2 Release Candidates</A></H3>
+<P>Release candidates are generated at least two weeks prior to a
+ production release. Release candidates are targeted for end-users that
+ wish to test new functionality or bug fixes prior to the production
+ release. While release candidates are intended to be substantially
+ bug-free, they may still contain defects and/or not compile on specific
+ platforms.</P>
+<P>At least one release candidate is REQUIRED prior to any production
+ release. The distribution of a release candidate marks the end of any
+ functional improvements. Release candidates are generated at weekly
+ intervals until all level 4/5 trouble reports are resolved.</P>
+<H3><A NAME="5_4_3">5.4.3 Production Releases</A></H3>
+<P>Production releases are generated after a successful release
+ candidate and represent a stable release of the software suitable for
+ all users.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
+<H2><A NAME="6_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="6_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+<H1><A NAME="7">B Coding Requirements</A></H1>
+<P>These coding requirements provide detailed information on source file
+ formatting and documentation content. These guidelines shall be applied
+ to all C and C++ source files provided with CUPS. Source code for other
+ languages should conform to these requirements as allowed by the
+ language.</P>
+<H2><A NAME="7_1">B.1 Source Files</A></H2>
+<H3><A NAME="7_1_1">B.1.1 Naming</A></H3>
+<P>All source files names shall be 16 characters or less in length to
+ ensure compatibility with older UNIX filesystems. Source files
+ containing functions shall have an extension of &quot;.c&quot; for ANSI C and
+ &quot;.cxx&quot; for C++ source files. All other &quot;include&quot; files shall have an
+ extension of &quot;.h&quot;.</P>
+<H3><A NAME="7_1_2">B.1.2 Documentation</A></H3>
+<P>The top of each source file shall contain a header giving the name of
+ the file, the purpose or nature of the source file, the copyright and
+ licensing notice, and the functions contained in the file. The file
+ name and revision information is provided by the CVS &quot;$Id$&quot; tag:</P>
+<PRE>
+ /*
+ * &quot;$Id$&quot;
+ *
+ * Description of file contents.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights
+ * reserved.
+ *
+ * These coded instructions, statements, and computer programs are
+ * the property of Easy Software Products and are protected by
+ * Federal copyright law. Distribution and use rights are outlined
+ * in the file &quot;LICENSE.txt&quot; which should have been included with
+ * this file. If this file is missing or damaged please contact
+ * Easy Software Products at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * function1() - Description 1.
+ * function2() - Description 2.
+ * function3() - Description 3.
+ */
+</PRE>
+
+<!-- NEED 1in -->
+<P>For source files that are subject to the Apple OS-Developed Software
+ exception, the following additional comment should appear after the
+ contact information:</P>
+<PRE>
+ * This file is subject to the Apple OS-Developed Software exception.
+</PRE>
+<P>The bottom of each source file shall contain a trailer giving the
+ name of the file using the CVS &quot;$Id$&quot; tag. The primary purpose of this
+ is to mark the end of a source file; if the trailer is missing it is
+ possible that code has been lost near the end of the file:</P>
+<PRE>
+ /*
+ * End of &quot;$Id$&quot;.
+ */
+</PRE>
+<H2><A NAME="7_2">B.2 Functions</A></H2>
+<H3><A NAME="7_2_1">B.2.1 Naming</A></H3>
+<P>Functions with a global scope shall be capitalized (&quot;DoThis&quot;,
+ &quot;DoThat&quot;, &quot;DoSomethingElse&quot;, etc.) The only exception to this rule
+ shall be the CUPS interface library functions which may begin with a
+ prefix word in lowercase (&quot;cupsDoThis&quot;, &quot;cupsDoThat&quot;, etc.)</P>
+<P>Functions with a local scope shall be declared &quot;static&quot; and be
+ lowercase with underscores between words (&quot;do_this&quot;, &quot;do_that&quot;,
+ &quot;do_something_else&quot;, etc.)</P>
+<H3><A NAME="7_2_2">B.2.2 Documentation</A></H3>
+<P>Each function shall begin with a comment header describing what the
+ function does, the possible input limits (if any), and the possible
+ output values (if any), and any special information needed:</P>
+<PRE>
+ /*
+ * 'do_this()' - Compute y = this(x).
+ *
+ * Notes: none.
+ */
+
+ static float /* O - Inverse power value, 0.0 &lt;= y &lt;= 1.1 */
+ do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.1) */
+ {
+ ...
+ return (y);
+ }
+</PRE>
+<P>Return/output values are indicated using an &quot;O&quot; prefix, input values
+ are indicated using the &quot;I&quot; prefix, and values that are both input and
+ output use the &quot;IO&quot; prefix for the corresponding in-line comment.</P>
+<H2><A NAME="7_3">B.3 Methods</A></H2>
+<H3><A NAME="7_3_1">B.3.1 Naming</A></H3>
+<P>Methods shall be in lowercase with underscores between words
+ (&quot;do_this&quot;, &quot;do_that&quot;, &quot;do_something_else&quot;, etc.)</P>
+<H3><A NAME="7_3_2">B.3.2 Documentation</A></H3>
+<P>Each method shall begin with a comment header describing what the
+ method does, the possible input limits (if any), and the possible
+ output values (if any), and any special information needed:</P>
+<PRE>
+ /*
+ * 'class::do_this()' - Compute y = this(x).
+ *
+ * Notes: none.
+ */
+
+ float /* O - Inverse power value, 0.0 &lt;= y &lt;= 1.0 */
+ class::do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.0) */
+ {
+ ...
+ return (y);
+ }
+</PRE>
+<P>Return/output values are indicated using an &quot;O&quot; prefix, input values
+ are indicated using the &quot;I&quot; prefix, and values that are both input and
+ output use the &quot;IO&quot; prefix for the corresponding in-line comment.</P>
+<H2><A NAME="7_4">B.4 Variables</A></H2>
+<H3><A NAME="7_4_1">B.4.1 Naming</A></H3>
+<P>Variables with a global scope shall be capitalized (&quot;ThisVariable&quot;,
+ &quot;ThatVariable&quot;, &quot;ThisStateVariable&quot;, etc.) The only exception to this
+ rule shall be the CUPS interface library global variables which must
+ begin with the prefix &quot;cups&quot; (&quot;cupsThisVariable&quot;, &quot;cupsThatVariable&quot;,
+ etc.) Global variables shall be replaced by function arguments whenever
+ possible.</P>
+<P>Variables with a local scope shall be lowercase with underscores
+ between words (&quot;this_variable&quot;, &quot;that_variable&quot;, etc.) Any local
+ variables shared by functions within a source file shall be declared
+ &quot;static&quot;.</P>
+<H3><A NAME="7_4_2">B.4.2 Documentation</A></H3>
+<P>Each variable shall be declared on a separate line and shall be
+ immediately followed by a comment block describing the variable:</P>
+<PRE>
+ int this_variable; /* The current state of this */
+ int that_variable; /* The current state of that */
+</PRE>
+<H2><A NAME="7_5">B.5 Types</A></H2>
+<H3><A NAME="7_5_1">B.5.1 Naming</A></H3>
+<P>All type names shall be lowercase with underscores between words and
+ &quot;_t&quot; appended to the end of the name (&quot;this_type_t&quot;, &quot;that_type_t&quot;,
+ etc.)</P>
+<H3><A NAME="7_5_2">B.5.2 Documentation</A></H3>
+<P>Each type shall have a comment block immediately before the typedef:</P>
+<PRE>
+ /*
+ * This type is for CUPS foobar options.
+ */
+ typedef int cups_this_type_t;
+</PRE>
+<H2><A NAME="7_6">B.6 Structures</A></H2>
+<H3><A NAME="7_6_1">B.6.1 Naming</A></H3>
+<P>All structure names shall be lowercase with underscores between words
+ and &quot;_str&quot; appended to the end of the name (&quot;this_struct_str&quot;,
+ &quot;that_struct_str&quot;, etc.)</P>
+<H3><A NAME="7_6_2">B.6.2 Documentation</A></H3>
+<P>Each structure shall have a comment block immediately before the
+ struct and each member shall be documented in accordance with the
+ variable naming policy above:</P>
+<PRE>
+ /*
+ * This structure is for CUPS foobar options.
+ */
+ struct cups_this_struct_str
+ {
+ int this_member; /* Current state for this */
+ int that_member; /* Current state for that */
+ };
+</PRE>
+<H2><A NAME="7_7">B.7 Classes</A></H2>
+<H3><A NAME="7_7_1">B.7.1 Naming</A></H3>
+<P>All class names shall be lowercase with underscores between words
+ (&quot;this_class&quot;, &quot;that_class&quot;, etc.)</P>
+<H3><A NAME="7_7_2">B.7.2 Documentation</A></H3>
+<P>Each class shall have a comment block immediately before the class
+ and each member shall be documented in accordance with the variable
+ naming policy above:</P>
+<PRE>
+ /*
+ * This class is for CUPS foobar options.
+ */
+ class cups_this_class
+ {
+ int this_member; /* Current state for this */
+ int that_member; /* Current state for that */
+ };
+</PRE>
+<H2><A NAME="7_8">B.8 Constants</A></H2>
+<H3><A NAME="7_8_1">B.8.1 Naming</A></H3>
+<P>All constant names shall be uppercase with underscored between words
+ (&quot;THIS_CONSTANT&quot;, &quot;THAT_CONSTANT&quot;, etc.) Constants defined for the CUPS
+ interface library must begin with an uppercase prefix
+ (&quot;CUPS_THIS_CONSTANT&quot;, &quot;CUPS_THAT_CONSTANT&quot;, etc.)</P>
+<P>Typed enumerations shall be used whenever possible to allow for type
+ checking by the compiler.</P>
+<H3><A NAME="7_8_2">B.8.2 Documentation</A></H3>
+<P>Comment blocks shall immediately follow each constant:</P>
+<PRE>
+ enum
+ {
+ CUPS_THIS_TRAY, /* This tray */
+ CUPS_THAT_TRAY /* That tray */
+ };
+</PRE>
+<H2><A NAME="7_9">B.9 Code</A></H2>
+<H3><A NAME="7_9_1">B.9.1 Documentation</A></H3>
+<P>All source code shall utilize block comments within functions to
+ describe the operations being performed by a group of statements:</P>
+<PRE>
+ /*
+ * Clear the state array before we begin...
+ */
+
+ for (i = 0; i &lt; (sizeof(array) / sizeof(sizeof(array[0])); i ++)
+ array[i] = STATE_IDLE;
+
+ /*
+ * Wait for state changes...
+ */
+
+ do
+ {
+ for (i = 0; i &lt; (sizeof(array) / sizeof(sizeof(array[0])); i ++)
+ if (array[i] != STATE_IDLE)
+ break;
+
+ if (i == (sizeof(array) / sizeof(array[0])))
+ sleep(1);
+ } while (i == (sizeof(array) / sizeof(array[0])));
+</PRE>
+<H3><A NAME="7_9_2">B.9.2 Style</A></H3>
+<H4 TYPE="a">B.9.2.a Indentation</H4>
+<P>All code blocks enclosed by brackets shall begin with the opening
+ brace on a new line. The code then follows starting on a new line after
+ the brace and is indented 2 spaces. The closing brace is then placed on
+ a new line following the code at the original indentation:</P>
+<PRE>
+ {
+ int i; /* Looping var */
+
+ /*
+ * Process foobar values from 0 to 999...
+ */
+
+ for (i = 0; i &lt; 1000; i ++)
+ {
+ do_this(i);
+ do_that(i);
+ }
+ }
+</PRE>
+<P>Single-line statements following &quot;do&quot;, &quot;else&quot;, &quot;for&quot;, &quot;if&quot;, and
+ &quot;while&quot; shall be indented 2 spaces as well. Blocks of code in a
+ &quot;switch&quot; block shall be indented 4 spaces after each &quot;case&quot; and
+ &quot;default&quot; case:</P>
+<PRE>
+ switch (array[i])
+ {
+ case STATE_IDLE :
+ do_this(i);
+ do_that(i);
+ break;
+ default :
+ do_nothing(i);
+ break;
+ }
+</PRE>
+<H4>B.9.2.b Spacing</H4>
+<P>A space shall follow each reserved word (&quot;if&quot;, &quot;while&quot;, etc.) Spaces
+ shall not be inserted between a function name and the arguments in
+ parenthesis.</P>
+<H4>B.9.2.c Return Values</H4>
+<P>Parenthesis shall surround values returned from a function using
+ &quot;return&quot;:</P>
+<PRE>
+ return (STATE_IDLE);
+</PRE>
+<H4>B.9.2.d Loops</H4>
+<P>Whenever convenient loops should count downward to zero to improve
+ program performance:</P>
+<PRE>
+ for (i = sizeof(array) / sizeof(array[0]) - 1; i &gt;= 0; i --)
+ array[i] = STATE_IDLE;
+</PRE>
+<H1 ALIGN="RIGHT"><A NAME="8">C Software Trouble Report Form</A></H1>
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH ALIGN="RIGHT">Summary of Problem:</TH><TD COLSPAN="2">
+_____________________________________________</TD></TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR><TH ALIGN="RIGHT" ROWSPAN="5" VALIGN="TOP">Problem Severity:</TH><TD>
+__1</TD><TD>Request for enhancement, e.g. asking for a feature</TD></TR>
+<TR><TD>__2</TD><TD>Low, e.g. a documentation error or undocumented
+ side-effect</TD></TR>
+<TR><TD>__3</TD><TD>Moderate, e.g. unable to print a file or unable to
+ compile the software</TD></TR>
+<TR><TD>__4</TD><TD>High, e.g. unable to print to a printer or key
+ functionality not working</TD></TR>
+<TR><TD>__5</TD><TD>Critical, e.g. unable to print at all</TD></TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR><TH ALIGN="RIGHT" ROWSPAN="3" VALIGN="TOP">Problem Scope:</TH><TD>
+__1</TD><TD>Machine or printer</TD></TR>
+<TR><TD>__2</TD><TD>Operating System</TD></TR>
+<TR><TD>__3</TD><TD>All machines, printers, or operating systems</TD></TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR><TH ALIGN="RIGHT" VALIGN="TOP">Detailed Description of Problem:</TH><TD
+COLSPAN="2">_____________________________________________
+<BR> _____________________________________________
+<BR> _____________________________________________
+<BR> _____________________________________________
+<BR> _____________________________________________</TD></TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
diff --git a/doc/cmp.pdf b/doc/cmp.pdf
new file mode 100644
index 000000000..4d53a7463
--- /dev/null
+++ b/doc/cmp.pdf
Binary files differ
diff --git a/doc/cmp.shtml b/doc/cmp.shtml
new file mode 100644
index 000000000..2b5cb8270
--- /dev/null
+++ b/doc/cmp.shtml
@@ -0,0 +1,736 @@
+<HTML>
+<HEAD>
+ <META NAME="DOCNUMBER" CONTENT="CUPS-CMP-1.1">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Configuration Management Plan</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This configuration management plan document provides the
+guidelines for development and maintenance of the Common UNIX
+Printing System ("CUPS") Version 1.1 software.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This configuration management document is organized into the
+following sections:
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - File Management</LI>
+ <LI>4 - Trouble Report Processing</LI>
+ <LI>5 - Software Releases</LI>
+ <LI>A - Glossary</LI>
+ <LI>B - Coding Requirements</LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>File Management</H1>
+
+<H2>Directory Structure</H2>
+
+<P>Each source file shall be placed a sub-directory
+corresponding to the software sub-system it belongs to
+("scheduler", "cups", etc.) To remain compatible with older UNIX
+filesystems, directory names shall not exceed 16 characters in
+length.
+
+<H2>Source Files</H2>
+
+<P>Source files shall be documented and formatted as described
+in Appendix B, Coding Requirements. To remain compatible with
+older UNIX filesystems, source file names shall not exceed 16
+characters in length.
+
+<H2>Configuration Management</H2>
+
+<P>Source files shall be placed under the control of the
+Concurrent Versions System ("CVS") software. Source files shall
+be "checked in" with each change so that modifications can be
+tracked.
+
+<P>Documentation on the CVS software is included with the
+whitepaper, "CVS II: Parallelizing Software Development".
+
+<H1>Trouble Report Processing</H1>
+
+<P>A Software Trouble Report ("STR") shall be submitted every
+time a user or vendor experiences a problem with the CUPS
+software. Trouble reports are maintained in a database with one
+of the following states:
+
+<OL>
+ <LI>STR is closed with complete resolution</LI>
+ <LI>STR is closed without resolution</LI>
+ <LI>STR is active</LI>
+ <LI>STR is pending (new STR or additional information available)</LI>
+</OL>
+
+<P>Trouble reports shall be processed using the following steps.
+
+<H2>Classification</H2>
+
+<P>When a trouble report is received it must be classified at
+one of the following priority levels:
+
+<OL>
+
+ <LI>Request for enhancement, e.g. asking for a
+ feature</LI>
+
+ <LI>Low, e.g. a documentation error or undocumented
+ side-effect</LI>
+
+ <LI>Moderate, e.g. unable to print a file or unable to
+ compile the software</LI>
+
+ <LI>High, e.g. unable to print to a printer or key
+ functionality not working</LI>
+
+ <LI>Critical, e.g. unable to print at all</LI>
+
+</OL>
+
+<P>Level 4 and 5 trouble reports must be resolved in the next
+software release. Level 1 to 3 trouble reports are scheduled for
+resolution in a specific release at the discretion of the
+release coordinator.
+
+<P>The scope of the problem should also be determined as:
+
+<OL>
+ <LI>Specific to a machine or printer</LI>
+ <LI>Specific to an operating system</LI>
+ <LI>Applies to all machines, printers, and operating systems</LI>
+</OL>
+
+<H2>Identification</H2>
+
+<P>Once the level and scope of the trouble report is determined
+the software sub-system(s) involved with the problem are
+determined. This may involve additional communication with the
+user or vendor to isolate the problem to a specific cause.
+
+<P>When the sub-system(s) involved have been identified, an
+engineer will then determine the change(s) needed and estimate
+the time required for the change(s).
+
+<H2>Correction</H2>
+
+<P>Corrections are scheduled based upon the severity and
+complexity of the problem. Once all changes have been made,
+documented, and tested successfully a new software release
+snapshot is generated. Additional tests are added as necessary
+for proper testing of the changes.
+
+<H2>Notification</H2>
+
+<P>The user or vendor is notified when the fix is available or
+if the problem was caused by user error.
+
+<H1>Software Releases</H1>
+
+<H2>Version Numbering</H2>
+
+<P>CUPS uses a three-part version number separated by periods to
+represent the major, minor, and patch release numbers:
+
+<PRE>
+ MAJOR.MINOR.PATCH
+ 1.1.0
+</PRE>
+
+<P>Beta-test releases are indentified by appending the letter B
+followed by the build number:
+
+<PRE>
+ MAJOR.MINOR.PATCHbBUILD
+ 1.1.0b1
+</PRE>
+
+<P>Release candidates are indentified by appending the letters
+RC followed by the build number:
+
+<PRE>
+ MAJOR.MINOR.PATCHrcBUILD
+ 1.1.0rc1
+</PRE>
+
+<P>A CVS snapshot is generated for every beta and final release
+and uses the version number preceded by the letter "v" and with
+the decimal points replaced by underscores:
+
+<PRE>
+ v1_1_0b1
+ v1_1_0rc1
+ v1_1_0
+</PRE>
+
+<P>Each change that corrects a fault in a software sub-system
+increments the patch release number. If a change affects the
+overall software design of CUPS then the minor release number
+will be incremented and the patch release number reset to 0. If
+CUPS is completely redesigned the major release number will be
+incremented and the minor and patch release numbers reset to 0:
+
+<PRE>
+ 1.1.0b1 First beta release
+ 1.1.0b2 Second beta release
+ 1.1.0rc1 First release candidate
+ 1.1.0rc2 Second release candidate
+ 1.1.0 First production release
+ 1.1.1b1 First beta of 1.1.1
+ 1.1.1rc1 First release candidate of 1.1.1
+ 1.1.1 Production release of 1.1.1
+ 1.1.2b1 First beta of 1.1.2
+ 1.1.2rc1 First release candidate of 1.1.2
+ 1.1.2 Production release of 1.1.2
+ 2.0.0b1 First beta of 2.0.0
+ 2.0.0rc1 First release candidate of 2.0.0
+ 2.0.0 Production release of 2.0.0
+</PRE>
+
+<H2>Generation</H2>
+
+<P>Software releases shall be generated for each successfully
+completed software trouble report. All object and executable
+files shall be deleted prior to performing a full build to
+ensure that source files are recompiled.</P>
+
+<H2>Testing</H2>
+
+<P>Software testing shall be conducted according to the CUPS
+Software Test Plan, CUPS-STP-1.1. Failed tests cause STRs to be
+generated to correct the problems found.</P>
+
+<H2>Releases</H2>
+
+<P>When testing has been completed successfully a new
+distribution image is created from the current CVS code
+"snapshot". No release shall contain software that has not
+passed the appropriate software tests. Three types of releases
+are used, beta, release candidate, and production, and are
+released using the following basic schedule:
+
+<CENTER><TABLE BORDER="1">
+<TR>
+ <TH>Week</TH>
+ <TH>Version</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>T-6 weeks</TD>
+ <TD>1.1.0b1</TD>
+ <TD>First beta</TD>
+</TR>
+<TR>
+ <TD>T-5 weeks</TD>
+ <TD>1.1.0b2</TD>
+ <TD>Second beta</TD>
+</TR>
+<TR>
+ <TD>T-4 weeks</TD>
+ <TD>1.1.0b3</TD>
+ <TD>Third beta</TD>
+</TR>
+<TR>
+ <TD>T-3 weeks</TD>
+ <TD>1.1.0rc1</TD>
+ <TD>First release candidate</TD>
+</TR>
+<TR>
+ <TD>T-2 weeks</TD>
+ <TD>1.1.0rc2</TD>
+ <TD>Second release candidate</TD>
+</TR>
+<TR>
+ <TD>T-0 weeks</TD>
+ <TD>1.1.0</TD>
+ <TD>Production</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>Beta releases are typically used prior to new major and minor
+version releases. At least one release candidate is generated
+prior to each production release.</P>
+
+<H3>Beta Releases</H3>
+
+<P>Beta releases are generated when substantial changes have
+been made that may affect the reliability of the software. Beta
+releases may cause loss of data, functionality, or services and
+are provided for testing by qualified individuals.</P>
+
+<P>Beta releases are an OPTIONAL part of the release process and
+are generated as deemed appropriate by the release coordinator.
+Functional changes may be included in subsequent beta releases
+until the first release candidate.</P>
+
+<H3>Release Candidates</H3>
+
+<P>Release candidates are generated at least two weeks prior to
+a production release. Release candidates are targeted for
+end-users that wish to test new functionality or bug fixes prior
+to the production release. While release candidates are intended
+to be substantially bug-free, they may still contain defects
+and/or not compile on specific platforms.
+
+<P>At least one release candidate is REQUIRED prior to any
+production release. The distribution of a release candidate
+marks the end of any functional improvements. Release candidates
+are generated at weekly intervals until all level 4/5 trouble
+reports are resolved.
+
+<H3>Production Releases</H3>
+
+<P>Production releases are generated after a successful release
+candidate and represent a stable release of the software
+suitable for all users.
+
+<EMBED SRC="glossary.shtml">
+
+<H1>Coding Requirements</H1>
+
+<P>These coding requirements provide detailed information on
+source file formatting and documentation content. These
+guidelines shall be applied to all C and C++ source files
+provided with CUPS. Source code for other languages should
+conform to these requirements as allowed by the language.
+
+<H2>Source Files</H2>
+
+<H3>Naming</H3>
+
+<P>All source files names shall be 16 characters or less in
+length to ensure compatibility with older UNIX filesystems.
+Source files containing functions shall have an extension of
+".c" for ANSI C and ".cxx" for C++ source files. All other
+"include" files shall have an extension of ".h".
+
+<H3>Documentation</H3>
+
+<P>The top of each source file shall contain a header giving the
+name of the file, the purpose or nature of the source file, the
+copyright and licensing notice, and the functions contained in
+the file. The file name and revision information is provided by
+the CVS "&#36;Id$" tag:
+
+<PRE>
+ /*
+ * "&#36;Id$"
+ *
+ * Description of file contents.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights
+ * reserved.
+ *
+ * These coded instructions, statements, and computer programs are
+ * the property of Easy Software Products and are protected by
+ * Federal copyright law. Distribution and use rights are outlined
+ * in the file "LICENSE.txt" which should have been included with
+ * this file. If this file is missing or damaged please contact
+ * Easy Software Products at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * function1() - Description 1.
+ * function2() - Description 2.
+ * function3() - Description 3.
+ */
+</PRE>
+
+<!-- NEED 1in -->
+<P>For source files that are subject to the Apple OS-Developed Software
+exception, the following additional comment should appear after the
+contact information:
+
+<PRE>
+ * This file is subject to the Apple OS-Developed Software exception.
+</PRE>
+
+<P>The bottom of each source file shall contain a trailer giving
+the name of the file using the CVS "&#36;Id$" tag. The primary
+purpose of this is to mark the end of a source file; if the
+trailer is missing it is possible that code has been lost near
+the end of the file:
+
+<PRE>
+ /*
+ * End of "&#36;Id$".
+ */
+</PRE>
+
+<H2>Functions</H2>
+
+<H3>Naming</H3>
+
+<P>Functions with a global scope shall be capitalized ("DoThis",
+"DoThat", "DoSomethingElse", etc.) The only exception to this
+rule shall be the CUPS interface library functions which may
+begin with a prefix word in lowercase ("cupsDoThis",
+"cupsDoThat", etc.)
+
+<P>Functions with a local scope shall be declared "static" and
+be lowercase with underscores between words ("do_this",
+"do_that", "do_something_else", etc.)
+
+<H3>Documentation</H3>
+
+<P>Each function shall begin with a comment header describing
+what the function does, the possible input limits (if any), and
+the possible output values (if any), and any special information
+needed:
+
+<PRE>
+ /*
+ * 'do_this()' - Compute y = this(x).
+ *
+ * Notes: none.
+ */
+
+ static float /* O - Inverse power value, 0.0 &lt;= y &lt;= 1.1 */
+ do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.1) */
+ {
+ ...
+ return (y);
+ }
+</PRE>
+
+<P>Return/output values are indicated using an "O" prefix, input
+values are indicated using the "I" prefix, and values that are
+both input and output use the "IO" prefix for the corresponding
+in-line comment.
+
+<H2>Methods</H2>
+
+<H3>Naming</H3>
+
+<P>Methods shall be in lowercase with underscores between words
+("do_this", "do_that", "do_something_else", etc.)
+
+<H3>Documentation</H3>
+
+<P>Each method shall begin with a comment header describing what
+the method does, the possible input limits (if any), and the
+possible output values (if any), and any special information
+needed:
+
+<PRE>
+ /*
+ * 'class::do_this()' - Compute y = this(x).
+ *
+ * Notes: none.
+ */
+
+ float /* O - Inverse power value, 0.0 &lt;= y &lt;= 1.0 */
+ class::do_this(float x) /* I - Power value (0.0 &lt;= x &lt;= 1.0) */
+ {
+ ...
+ return (y);
+ }
+</PRE>
+
+<P>Return/output values are indicated using an "O" prefix, input
+values are indicated using the "I" prefix, and values that are
+both input and output use the "IO" prefix for the corresponding
+in-line comment.
+
+<H2>Variables</H2>
+
+<H3>Naming</H3>
+
+<P>Variables with a global scope shall be capitalized
+("ThisVariable", "ThatVariable", "ThisStateVariable", etc.) The
+only exception to this rule shall be the CUPS interface library
+global variables which must begin with the prefix "cups"
+("cupsThisVariable", "cupsThatVariable", etc.) Global variables
+shall be replaced by function arguments whenever possible.
+
+<P>Variables with a local scope shall be lowercase with
+underscores between words ("this_variable", "that_variable",
+etc.) Any local variables shared by functions within a source
+file shall be declared "static".
+
+<H3>Documentation</H3>
+
+<P>Each variable shall be declared on a separate line and shall
+be immediately followed by a comment block describing the
+variable:
+
+<PRE>
+ int this_variable; /* The current state of this */
+ int that_variable; /* The current state of that */
+</PRE>
+
+<H2>Types</H2>
+
+<H3>Naming</H3>
+
+<P>All type names shall be lowercase with underscores between
+words and "_t" appended to the end of the name ("this_type_t",
+"that_type_t", etc.)
+
+<H3>Documentation</H3>
+
+<P>Each type shall have a comment block immediately before the
+typedef:
+
+<PRE>
+ /*
+ * This type is for CUPS foobar options.
+ */
+ typedef int cups_this_type_t;
+</PRE>
+
+<H2>Structures</H2>
+
+<H3>Naming</H3>
+
+<P>All structure names shall be lowercase with underscores
+between words and "_str" appended to the end of the name
+("this_struct_str", "that_struct_str", etc.)
+
+<H3>Documentation</H3>
+
+<P>Each structure shall have a comment block immediately before
+the struct and each member shall be documented in accordance
+with the variable naming policy above:
+
+<PRE>
+ /*
+ * This structure is for CUPS foobar options.
+ */
+ struct cups_this_struct_str
+ {
+ int this_member; /* Current state for this */
+ int that_member; /* Current state for that */
+ };
+</PRE>
+
+<H2>Classes</H2>
+
+<H3>Naming</H3>
+
+<P>All class names shall be lowercase with underscores between
+words ("this_class", "that_class", etc.)
+
+<H3>Documentation</H3>
+
+<P>Each class shall have a comment block immediately before the
+class and each member shall be documented in accordance with the
+variable naming policy above:
+
+<PRE>
+ /*
+ * This class is for CUPS foobar options.
+ */
+ class cups_this_class
+ {
+ int this_member; /* Current state for this */
+ int that_member; /* Current state for that */
+ };
+</PRE>
+
+<H2>Constants</H2>
+
+<H3>Naming</H3>
+
+<P>All constant names shall be uppercase with underscored
+between words ("THIS_CONSTANT", "THAT_CONSTANT", etc.) Constants
+defined for the CUPS interface library must begin with an
+uppercase prefix ("CUPS_THIS_CONSTANT", "CUPS_THAT_CONSTANT",
+etc.)
+
+<P>Typed enumerations shall be used whenever possible to allow
+for type checking by the compiler.
+
+<H3>Documentation</H3>
+
+<P>Comment blocks shall immediately follow each constant:
+
+<PRE>
+ enum
+ {
+ CUPS_THIS_TRAY, /* This tray */
+ CUPS_THAT_TRAY /* That tray */
+ };
+</PRE>
+
+<H2>Code</H2>
+
+<H3>Documentation</H3>
+
+<P>All source code shall utilize block comments within functions
+to describe the operations being performed by a group of
+statements:
+
+<PRE>
+ /*
+ * Clear the state array before we begin...
+ */
+
+ for (i = 0; i &lt; (sizeof(array) / sizeof(sizeof(array[0])); i ++)
+ array[i] = STATE_IDLE;
+
+ /*
+ * Wait for state changes...
+ */
+
+ do
+ {
+ for (i = 0; i &lt; (sizeof(array) / sizeof(sizeof(array[0])); i ++)
+ if (array[i] != STATE_IDLE)
+ break;
+
+ if (i == (sizeof(array) / sizeof(array[0])))
+ sleep(1);
+ } while (i == (sizeof(array) / sizeof(array[0])));
+</PRE>
+
+<H3>Style</H3>
+
+<H4 TYPE="a">Indentation</H4>
+
+<P>All code blocks enclosed by brackets shall begin with the
+opening brace on a new line. The code then follows starting on a
+new line after the brace and is indented 2 spaces. The closing
+brace is then placed on a new line following the code at the
+original indentation:
+
+<PRE>
+ {
+ int i; /* Looping var */
+
+ /*
+ * Process foobar values from 0 to 999...
+ */
+
+ for (i = 0; i &lt; 1000; i ++)
+ {
+ do_this(i);
+ do_that(i);
+ }
+ }
+</PRE>
+
+<P>Single-line statements following "do", "else", "for", "if",
+and "while" shall be indented 2 spaces as well. Blocks of code
+in a "switch" block shall be indented 4 spaces after each "case"
+and "default" case:
+
+<PRE>
+ switch (array[i])
+ {
+ case STATE_IDLE :
+ do_this(i);
+ do_that(i);
+ break;
+ default :
+ do_nothing(i);
+ break;
+ }
+</PRE>
+
+<H4>Spacing</H4>
+
+<P>A space shall follow each reserved word ("if", "while", etc.)
+Spaces shall not be inserted between a function name and the
+arguments in parenthesis.
+
+<H4>Return Values</H4>
+
+<P>Parenthesis shall surround values returned from a function
+using "return":
+
+<PRE>
+ return (STATE_IDLE);
+</PRE>
+
+<H4>Loops</H4>
+
+<P>Whenever convenient loops should count downward to zero to
+improve program performance:
+
+<PRE>
+ for (i = sizeof(array) / sizeof(array[0]) - 1; i >= 0; i --)
+ array[i] = STATE_IDLE;
+</PRE>
+
+<H1 ALIGN="RIGHT">Software Trouble Report Form</H1>
+
+<CENTER><TABLE WIDTH="80%">
+<TR>
+ <TH ALIGN="RIGHT">Summary of Problem:</TH>
+ <TD COLSPAN="2">_____________________________________________</TD>
+</TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR>
+ <TH ALIGN="RIGHT" ROWSPAN="5" VALIGN="TOP">Problem Severity:</TH>
+ <TD>__1</TD>
+ <TD>Request for enhancement, e.g. asking for a
+ feature</TD>
+</TR>
+<TR>
+ <TD>__2</TD>
+ <TD>Low, e.g. a documentation error or undocumented
+ side-effect</TD>
+</TR>
+<TR>
+ <TD>__3</TD>
+ <TD>Moderate, e.g. unable to print a file or unable to
+ compile the software</TD>
+</TR>
+<TR>
+ <TD>__4</TD>
+ <TD>High, e.g. unable to print to a printer or key
+ functionality not working</TD>
+</TR>
+<TR>
+ <TD>__5</TD>
+ <TD>Critical, e.g. unable to print at all</TD>
+</TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR>
+ <TH ALIGN="RIGHT" ROWSPAN="3" VALIGN="TOP">Problem Scope:</TH>
+ <TD>__1</TD>
+ <TD>Machine or printer</TD>
+</TR>
+<TR>
+ <TD>__2</TD>
+ <TD>Operating System</TD>
+</TR>
+<TR>
+ <TD>__3</TD>
+ <TD>All machines, printers, or operating systems</TD>
+</TR>
+<TR><TD COLSPAN="3">&nbsp;</TD></TR>
+<TR>
+ <TH ALIGN="RIGHT" VALIGN="TOP">Detailed Description of Problem:</TH>
+ <TD COLSPAN="2">_____________________________________________
+ <BR>_____________________________________________
+ <BR>_____________________________________________
+ <BR>_____________________________________________
+ <BR>_____________________________________________</TD>
+</TR>
+</TABLE></CENTER>
+
+</BODY>
+</HTML>
diff --git a/doc/cups.css b/doc/cups.css
new file mode 100644
index 000000000..9285a5b5e
--- /dev/null
+++ b/doc/cups.css
@@ -0,0 +1,4 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+TH { text-align: left }
+
diff --git a/doc/cupsdoc.css b/doc/cupsdoc.css
new file mode 100644
index 000000000..333f20144
--- /dev/null
+++ b/doc/cupsdoc.css
@@ -0,0 +1,9 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUP { font-family: sans-serif; font-size: 6pt }
+PRE { margin-left: 2em }
+CODE { font-weight: bold }
diff --git a/doc/de/Makefile b/doc/de/Makefile
new file mode 100644
index 000000000..8284148ff
--- /dev/null
+++ b/doc/de/Makefile
@@ -0,0 +1,90 @@
+#
+# "$Id$"
+#
+# Documentation makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Document files...
+#
+
+WEBPAGES = index.html documentation.html
+WEBIMAGES = images/accept-jobs.gif \
+ images/add-class.gif \
+ images/add-printer.gif \
+ images/cancel-job.gif \
+ images/config-printer.gif \
+ images/continue.gif \
+ images/delete-class.gif \
+ images/delete-printer.gif \
+ images/hold-job.gif \
+ images/manage-classes.gif \
+ images/manage-jobs.gif \
+ images/manage-printers.gif \
+ images/modify-class.gif \
+ images/modify-printer.gif \
+ images/navbar.gif \
+ images/print-test-page.gif \
+ images/reject-jobs.gif \
+ images/release-job.gif \
+ images/restart-job.gif \
+ images/show-active.gif \
+ images/show-completed.gif \
+ images/start-class.gif \
+ images/start-printer.gif \
+ images/stop-class.gif \
+ images/stop-printer.gif
+
+
+#
+# Make all documents...
+#
+
+all:
+
+
+#
+# Remove all generated files...
+#
+
+clean:
+
+
+#
+# Install all documentation files...
+#
+
+install:
+ $(INSTALL_DIR) $(DOCDIR)/de
+ for file in $(WEBPAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/de; \
+ done
+ $(INSTALL_DIR) $(DOCDIR)/de/images
+ for file in $(WEBIMAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/de/images; \
+ done
+
+
+#
+# End of Makefile.
+#
diff --git a/doc/de/documentation.html b/doc/de/documentation.html
new file mode 100644
index 000000000..3290f3548
--- /dev/null
+++ b/doc/de/documentation.html
@@ -0,0 +1,81 @@
+<HTML>
+<HEAD>
+ <TITLE>Dokumentation - Common UNIX Printing System</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,10,50,20" HREF="http://www.easysw.com" ALT="Easy Software Produkt-Homepage">
+ <AREA SHAPE="RECT" COORDS="82,10,226,20" HREF="admin" ALT="Einrichtungsaufgaben">
+ <AREA SHAPE="RECT" COORDS="235,10,403,20" HREF="classes" ALT="Druckerklassen verwalten">
+ <AREA SHAPE="RECT" COORDS="412,10,488,20" HREF="documentation.html" ALT="Online Hilfe">
+ <AREA SHAPE="RECT" COORDS="497,10,590,20" HREF="jobs" ALT="Druckauftr&auml;ge">
+ <AREA SHAPE="RECT" COORDS="599,10,717,20" HREF="printers" ALT="Drucker verwalten">
+ <AREA SHAPE="RECT" COORDS="726,10,887,20" HREF="http://www.cups.org" ALT="Aktuelle CUPS Software">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="902" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1>Dokumentation</H1>
+
+Folgende Dokumentation f&uuml;r CUPS ist auf diesem Server verf&uuml;gbar:
+
+<UL>
+
+ <LI>Whitepaper - Ein &Uuml;berblick &uuml;ber das Common UNIX Printing System (
+ <A HREF="overview.html">HTML</A> |
+ <A HREF="overview.pdf">PDF</A> )
+
+ <LI>Software Benutzerhandbuch (
+ <A HREF="sum.html">HTML</A> |
+ <A HREF="sum.pdf">PDF</A> )
+
+ <LI>Software Administratorhandbuch (
+ <A HREF="sam.html">HTML</A> |
+ <A HREF="sam.pdf">PDF</A> )
+
+ <LI>Software Programmiererhandbuch (
+ <A HREF="spm.html">HTML</A> |
+ <A HREF="spm.pdf">PDF</A> )
+
+ <LI>Entwicklungsmanagement (
+ <A HREF="cmp.html">HTML</A> |
+ <A HREF="cmp.pdf">PDF</A> )
+
+ <LI>CUPS Implementation des IPP (
+ <A HREF="ipp.html">HTML</A> |
+ <A HREF="ipp.pdf">PDF</A> )
+
+ <LI>Schnittstellenbeschreibung (
+ <A HREF="idd.html">HTML</A> |
+ <A HREF="idd.pdf">PDF</A> )
+
+ <LI>Software Designbeschreibung (
+ <A HREF="sdd.html">HTML</A> |
+ <A HREF="sdd.pdf">PDF</A> )
+
+ <LI>Software Wirkleistungsanalyse (
+ <A HREF="sps.html">HTML</A> |
+ <A HREF="sps.pdf">PDF</A> )
+
+ <LI>Software Versionsbeschreibung (
+ <A HREF="svd.html">HTML</A> |
+ <A HREF="svd.pdf">PDF</A> )
+
+ <LI>Software Sicherheitsbericht (
+ <A HREF="ssr.html">HTML</A> |
+ <A HREF="ssr.pdf">PDF</A> )
+
+</UL>
+
+<HR>
+
+<P>Das Common UNIX Printing System, CUPS, und das CUPS Logo sind
+Warenzeichen der <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS ist urheberrechtlich gesch&uuml;tzt 1997-2003 von Easy Software Products,
+Alle Rechte vorbehalten.
+
+</BODY>
+</HTML>
diff --git a/doc/de/images/accept-jobs.gif b/doc/de/images/accept-jobs.gif
new file mode 100644
index 000000000..aa76eff11
--- /dev/null
+++ b/doc/de/images/accept-jobs.gif
Binary files differ
diff --git a/doc/de/images/add-class.gif b/doc/de/images/add-class.gif
new file mode 100644
index 000000000..4ec0a0d7f
--- /dev/null
+++ b/doc/de/images/add-class.gif
Binary files differ
diff --git a/doc/de/images/add-printer.gif b/doc/de/images/add-printer.gif
new file mode 100644
index 000000000..653672811
--- /dev/null
+++ b/doc/de/images/add-printer.gif
Binary files differ
diff --git a/doc/de/images/cancel-job.gif b/doc/de/images/cancel-job.gif
new file mode 100644
index 000000000..5a50da479
--- /dev/null
+++ b/doc/de/images/cancel-job.gif
Binary files differ
diff --git a/doc/de/images/config-printer.gif b/doc/de/images/config-printer.gif
new file mode 100644
index 000000000..1cda2d0e0
--- /dev/null
+++ b/doc/de/images/config-printer.gif
Binary files differ
diff --git a/doc/de/images/continue.gif b/doc/de/images/continue.gif
new file mode 100644
index 000000000..a4df3f2f6
--- /dev/null
+++ b/doc/de/images/continue.gif
Binary files differ
diff --git a/doc/de/images/delete-class.gif b/doc/de/images/delete-class.gif
new file mode 100644
index 000000000..0008a084b
--- /dev/null
+++ b/doc/de/images/delete-class.gif
Binary files differ
diff --git a/doc/de/images/delete-printer.gif b/doc/de/images/delete-printer.gif
new file mode 100644
index 000000000..437f49af1
--- /dev/null
+++ b/doc/de/images/delete-printer.gif
Binary files differ
diff --git a/doc/de/images/hold-job.gif b/doc/de/images/hold-job.gif
new file mode 100644
index 000000000..5ffae6e24
--- /dev/null
+++ b/doc/de/images/hold-job.gif
Binary files differ
diff --git a/doc/de/images/manage-classes.gif b/doc/de/images/manage-classes.gif
new file mode 100644
index 000000000..6737640ae
--- /dev/null
+++ b/doc/de/images/manage-classes.gif
Binary files differ
diff --git a/doc/de/images/manage-jobs.gif b/doc/de/images/manage-jobs.gif
new file mode 100644
index 000000000..02814887c
--- /dev/null
+++ b/doc/de/images/manage-jobs.gif
Binary files differ
diff --git a/doc/de/images/manage-printers.gif b/doc/de/images/manage-printers.gif
new file mode 100644
index 000000000..6737640ae
--- /dev/null
+++ b/doc/de/images/manage-printers.gif
Binary files differ
diff --git a/doc/de/images/modify-class.gif b/doc/de/images/modify-class.gif
new file mode 100644
index 000000000..b6e9236dc
--- /dev/null
+++ b/doc/de/images/modify-class.gif
Binary files differ
diff --git a/doc/de/images/modify-printer.gif b/doc/de/images/modify-printer.gif
new file mode 100644
index 000000000..3ba609146
--- /dev/null
+++ b/doc/de/images/modify-printer.gif
Binary files differ
diff --git a/doc/de/images/navbar.gif b/doc/de/images/navbar.gif
new file mode 100644
index 000000000..a9024cbf0
--- /dev/null
+++ b/doc/de/images/navbar.gif
Binary files differ
diff --git a/doc/de/images/print-test-page.gif b/doc/de/images/print-test-page.gif
new file mode 100644
index 000000000..26679cfd0
--- /dev/null
+++ b/doc/de/images/print-test-page.gif
Binary files differ
diff --git a/doc/de/images/reject-jobs.gif b/doc/de/images/reject-jobs.gif
new file mode 100644
index 000000000..5f2edb4e3
--- /dev/null
+++ b/doc/de/images/reject-jobs.gif
Binary files differ
diff --git a/doc/de/images/release-job.gif b/doc/de/images/release-job.gif
new file mode 100644
index 000000000..80f2bec5d
--- /dev/null
+++ b/doc/de/images/release-job.gif
Binary files differ
diff --git a/doc/de/images/restart-job.gif b/doc/de/images/restart-job.gif
new file mode 100644
index 000000000..2c2de787f
--- /dev/null
+++ b/doc/de/images/restart-job.gif
Binary files differ
diff --git a/doc/de/images/show-active.gif b/doc/de/images/show-active.gif
new file mode 100644
index 000000000..7455a649a
--- /dev/null
+++ b/doc/de/images/show-active.gif
Binary files differ
diff --git a/doc/de/images/show-completed.gif b/doc/de/images/show-completed.gif
new file mode 100644
index 000000000..6079b48d3
--- /dev/null
+++ b/doc/de/images/show-completed.gif
Binary files differ
diff --git a/doc/de/images/start-class.gif b/doc/de/images/start-class.gif
new file mode 100644
index 000000000..e432d26cc
--- /dev/null
+++ b/doc/de/images/start-class.gif
Binary files differ
diff --git a/doc/de/images/start-printer.gif b/doc/de/images/start-printer.gif
new file mode 100644
index 000000000..3a78a9fce
--- /dev/null
+++ b/doc/de/images/start-printer.gif
Binary files differ
diff --git a/doc/de/images/stop-class.gif b/doc/de/images/stop-class.gif
new file mode 100644
index 000000000..65fdbcdd2
--- /dev/null
+++ b/doc/de/images/stop-class.gif
Binary files differ
diff --git a/doc/de/images/stop-printer.gif b/doc/de/images/stop-printer.gif
new file mode 100644
index 000000000..ff7469e38
--- /dev/null
+++ b/doc/de/images/stop-printer.gif
Binary files differ
diff --git a/doc/de/index.html b/doc/de/index.html
new file mode 100644
index 000000000..3137083b0
--- /dev/null
+++ b/doc/de/index.html
@@ -0,0 +1,36 @@
+<HTML>
+<HEAD>
+ <TITLE>Gemeinsames UNIX Drucksystem</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,10,50,20" HREF="http://www.easysw.com" ALT="Easy Software Produkt-Homepage">
+ <AREA SHAPE="RECT" COORDS="82,10,226,20" HREF="admin" ALT="Einrichtungsaufgaben">
+ <AREA SHAPE="RECT" COORDS="235,10,403,20" HREF="classes" ALT="Druckerklassen verwalten">
+ <AREA SHAPE="RECT" COORDS="412,10,488,20" HREF="documentation.html" ALT="Online Hilfe">
+ <AREA SHAPE="RECT" COORDS="497,10,590,20" HREF="jobs" ALT="Druckauftr&auml;ge">
+ <AREA SHAPE="RECT" COORDS="599,10,717,20" HREF="printers" ALT="Drucker verwalten">
+ <AREA SHAPE="RECT" COORDS="726,10,887,20" HREF="http://www.cups.org" ALT="Aktuelle CUPS Software">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="902" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1><A HREF="admin">Einrichtungsaufgaben</A></H1>
+<H1><A HREF="classes">Druckerklassen verwalten</A></H1>
+<H1><A HREF="documentation.html">Online Hilfe</A></H1>
+<H1><A HREF="jobs">Druckauftr&auml;ge verwalten</A></H1>
+<H1><A HREF="printers">Drucker verwalten</A></H1>
+<H1><A HREF="http://www.cups.org">Aktuelle CUPS Software</A></H1>
+
+<HR>
+
+<P>Das Common UNIX Printing System, CUPS, und das CUPS Logo sind
+Warenzeichen der <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS ist urheberrechtlich gesch&uuml;tzt 1997-2003 von Easy Software Products,
+Alle Rechte vorbehalten.
+
+</BODY>
+</HTML>
diff --git a/doc/documentation.html b/doc/documentation.html
new file mode 100644
index 000000000..e2ad1eca0
--- /dev/null
+++ b/doc/documentation.html
@@ -0,0 +1,90 @@
+<HTML>
+<HEAD>
+ <TITLE>Documentation - Common UNIX Printing System</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,10,50,20" HREF="http://www.easysw.com" ALT="Easy Software Products Home Page">
+ <AREA SHAPE="RECT" COORDS="82,10,196,20" HREF="/admin" ALT="Do Administration Tasks">
+ <AREA SHAPE="RECT" COORDS="216,10,280,20" HREF="/classes" ALT="Manage Printer Classes Status">
+ <AREA SHAPE="RECT" COORDS="300,10,336,20" HREF="/documentation.html" ALT="On-Line Help">
+ <AREA SHAPE="RECT" COORDS="356,10,394,20" HREF="/jobs" ALT="Manage Jobs">
+ <AREA SHAPE="RECT" COORDS="414,10,476,20" HREF="/printers" ALT="Manage Printers">
+ <AREA SHAPE="RECT" COORDS="496,10,568,20" HREF="http://www.cups.org" ALT="Download the Current CUPS Software">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="583" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1>Documentation</H1>
+
+<P>The following documentation for CUPS is available on this
+server:
+
+<UL>
+
+ <LI>Whitepaper - An Overview of the Common UNIX Printing System (
+ <A HREF="overview.html">HTML</A> |
+ <A HREF="overview.pdf">PDF</A> )
+
+ <LI>Software Users Manual (
+ <A HREF="sum.html">HTML</A> |
+ <A HREF="sum.pdf">PDF</A> )
+
+ <LI>Software Administrators Manual (
+ <A HREF="sam.html">HTML</A> |
+ <A HREF="sam.pdf">PDF</A> )
+
+ <LI>Software Programmers Manual (
+ <A HREF="spm.html">HTML</A> |
+ <A HREF="spm.pdf">PDF</A> )
+
+ <LI>Configuration Management Plan (
+ <A HREF="cmp.html">HTML</A> |
+ <A HREF="cmp.pdf">PDF</A> )
+
+ <LI>CUPS Implementation of IPP (
+ <A HREF="ipp.html">HTML</A> |
+ <A HREF="ipp.pdf">PDF</A> )
+
+ <LI>Interface Design Description (
+ <A HREF="idd.html">HTML</A> |
+ <A HREF="idd.pdf">PDF</A> )
+
+ <LI>Software Design Description (
+ <A HREF="sdd.html">HTML</A> |
+ <A HREF="sdd.pdf">PDF</A> )
+
+ <LI>Software Performance Specification (
+ <A HREF="sps.html">HTML</A> |
+ <A HREF="sps.pdf">PDF</A> )
+
+ <LI>Software Security Report (
+ <A HREF="ssr.html">HTML</A> |
+ <A HREF="ssr.pdf">PDF</A> )
+
+ <LI>Software Translation Guide (
+ <A HREF="translation.html">HTML</A> |
+ <A HREF="translation.pdf">PDF</A> )
+
+ <LI>Software Test Plan (
+ <A HREF="stp.html">HTML</A> |
+ <A HREF="stp.pdf">PDF</A> )
+
+ <LI>Software Version Description (
+ <A HREF="svd.html">HTML</A> |
+ <A HREF="svd.pdf">PDF</A> )
+
+</UL>
+
+<HR>
+
+<P>The Common UNIX Printing System, CUPS, and the CUPS logo are the
+trademark property of <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS is copyright 1997-2003 by Easy Software Products,
+All Rights Reserved.
+
+</BODY>
+</HTML>
diff --git a/doc/es/Makefile b/doc/es/Makefile
new file mode 100644
index 000000000..3f0fcb5ff
--- /dev/null
+++ b/doc/es/Makefile
@@ -0,0 +1,91 @@
+#
+# "$Id$"
+#
+# Documentation makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Document files...
+#
+
+WEBPAGES = index.html documentation.html
+WEBIMAGES = images/accept-jobs.gif \
+ images/add-class.gif \
+ images/add-printer.gif \
+ images/cancel-job.gif \
+ images/config-printer.gif \
+ images/continue.gif \
+ images/delete-class.gif \
+ images/delete-printer.gif \
+ images/hold-job.gif \
+ images/manage-classes.gif \
+ images/manage-jobs.gif \
+ images/manage-printers.gif \
+ images/modify-class.gif \
+ images/modify-printer.gif \
+ images/navbar.gif \
+ images/print-test-page.gif \
+ images/reject-jobs.gif \
+ images/release-job.gif \
+ images/restart-job.gif \
+ images/set-as-default.gif \
+ images/show-active.gif \
+ images/show-completed.gif \
+ images/start-class.gif \
+ images/start-printer.gif \
+ images/stop-class.gif \
+ images/stop-printer.gif
+
+
+#
+# Make all documents...
+#
+
+all:
+
+
+#
+# Remove all generated files...
+#
+
+clean:
+
+
+#
+# Install all documentation files...
+#
+
+install:
+ $(INSTALL_DIR) $(DOCDIR)/es
+ for file in $(WEBPAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/es; \
+ done
+ $(INSTALL_DIR) $(DOCDIR)/es/images
+ for file in $(WEBIMAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/es/images; \
+ done
+
+
+#
+# End of Makefile.
+#
diff --git a/doc/es/documentation.html b/doc/es/documentation.html
new file mode 100644
index 000000000..9dda40e0b
--- /dev/null
+++ b/doc/es/documentation.html
@@ -0,0 +1,90 @@
+<HTML>
+<HEAD>
+ <TITLE>Documentaci&oacute;n de CUPS (Sistema de impresi&oacute;n com&uacute;n de UNIX)</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,8,50,22" HREF="http://www.easysw.com" ALT="P&aacute;gina inicial de Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,8,198,22" HREF="/admin" ALT="Tareas de administraci&oacute;n">
+ <AREA SHAPE="RECT" COORDS="216,8,270,22" HREF="/classes" ALT="Administra las clases de impresoras">
+ <AREA SHAPE="RECT" COORDS="292,8,344,22" HREF="/documentation.html" ALT="Ayuda en l&iacute;nea">
+ <AREA SHAPE="RECT" COORDS="366,8,435,22" HREF="/jobs" ALT="Administra trabajos">
+ <AREA SHAPE="RECT" COORDS="456,8,544,22" HREF="/printers" ALT="Administra impresoras">
+ <AREA SHAPE="RECT" COORDS="566,8,638,22" HREF="http://www.cups.org" ALT="Descargar la versi&oacute;n actual de CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="653" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="CUPS (Sistema de impresi&oacute;n com&uacute;n de UNIX)">
+</CENTER>
+
+<H1>Documentaci&oacute;n</H1>
+
+<P>La siguiente documentaci&oacute;n de CUPS est&aacute; disponible en este
+servidor:
+
+<UL>
+
+ <LI>Visi&oacute;n general de CUPS (
+ <A HREF="overview.html">HTML</A> |
+ <A HREF="overview.pdf">PDF</A> )
+
+ <LI>Manual de usuario (
+ <A HREF="sum.html">HTML</A> |
+ <A HREF="sum.pdf">PDF</A> )
+
+ <LI>Manual de administrador (
+ <A HREF="sam.html">HTML</A> |
+ <A HREF="sam.pdf">PDF</A> )
+
+ <LI>Manual del programador de software (
+ <A HREF="spm.html">HTML</A> |
+ <A HREF="spm.pdf">PDF</A> )
+
+ <LI>Plan de gesti&oacute;n de la configuraci&oacute;n (
+ <A HREF="cmp.html">HTML</A> |
+ <A HREF="cmp.pdf">PDF</A> )
+
+ <LI>La implementaci&oacute;n de CUPS de IPP (Internet Printing Protocol) (
+ <A HREF="ipp.html">HTML</A> |
+ <A HREF="ipp.pdf">PDF</A> )
+
+ <LI>Descripci&oacute;n del dise&ntilde;o de la interface (
+ <A HREF="idd.html">HTML</A> |
+ <A HREF="idd.pdf">PDF</A> )
+
+ <LI>Descripci&oacute;n del dise&ntilde;o del programa (
+ <A HREF="sdd.html">HTML</A> |
+ <A HREF="sdd.pdf">PDF</A> )
+
+ <LI>Especificaci&oacute;n de las capacidades del programa (
+ <A HREF="sps.html">HTML</A> |
+ <A HREF="sps.pdf">PDF</A> )
+
+ <LI>Informe de seguridad del software (
+ <A HREF="ssr.html">HTML</A> |
+ <A HREF="ssr.pdf">PDF</A> )
+
+ <LI>Gu&iacute;a para la traducci&oacute;n del programa (
+ <A HREF="translation.html">HTML</A> |
+ <A HREF="translation.pdf">PDF</A> )
+
+ <LI>Plan de prueba del programa (
+ <A HREF="stp.html">HTML</A> |
+ <A HREF="stp.pdf">PDF</A> )
+
+ <LI>Descripci&oacute;n de la versi&oacute;n del programa (
+ <A HREF="svd.html">HTML</A> |
+ <A HREF="svd.pdf">PDF</A> )
+
+</UL>
+
+<HR>
+
+<P>Common UNIX Printing System, CUPS, y el logo de CUPS son
+marcas registradas de <A HREF="http://www.easysw.com">Easy Software
+Products</A>. El copyright de CUPS 1997-2004 es de Easy Software Products,
+Todos los derechos reservados.
+
+</BODY>
+</HTML>
diff --git a/doc/es/images/accept-jobs.gif b/doc/es/images/accept-jobs.gif
new file mode 100644
index 000000000..71173ebc0
--- /dev/null
+++ b/doc/es/images/accept-jobs.gif
Binary files differ
diff --git a/doc/es/images/add-class.gif b/doc/es/images/add-class.gif
new file mode 100644
index 000000000..fe82e48f9
--- /dev/null
+++ b/doc/es/images/add-class.gif
Binary files differ
diff --git a/doc/es/images/add-printer.gif b/doc/es/images/add-printer.gif
new file mode 100644
index 000000000..dbaa312b3
--- /dev/null
+++ b/doc/es/images/add-printer.gif
Binary files differ
diff --git a/doc/es/images/cancel-job.gif b/doc/es/images/cancel-job.gif
new file mode 100644
index 000000000..06c8f5585
--- /dev/null
+++ b/doc/es/images/cancel-job.gif
Binary files differ
diff --git a/doc/es/images/config-printer.gif b/doc/es/images/config-printer.gif
new file mode 100644
index 000000000..0f967b0f8
--- /dev/null
+++ b/doc/es/images/config-printer.gif
Binary files differ
diff --git a/doc/es/images/continue.gif b/doc/es/images/continue.gif
new file mode 100644
index 000000000..7797d4d1b
--- /dev/null
+++ b/doc/es/images/continue.gif
Binary files differ
diff --git a/doc/es/images/delete-class.gif b/doc/es/images/delete-class.gif
new file mode 100644
index 000000000..18c5c828f
--- /dev/null
+++ b/doc/es/images/delete-class.gif
Binary files differ
diff --git a/doc/es/images/delete-printer.gif b/doc/es/images/delete-printer.gif
new file mode 100644
index 000000000..35c8bc615
--- /dev/null
+++ b/doc/es/images/delete-printer.gif
Binary files differ
diff --git a/doc/es/images/hold-job.gif b/doc/es/images/hold-job.gif
new file mode 100644
index 000000000..f38212a53
--- /dev/null
+++ b/doc/es/images/hold-job.gif
Binary files differ
diff --git a/doc/es/images/left.gif b/doc/es/images/left.gif
new file mode 100644
index 000000000..fd7b04104
--- /dev/null
+++ b/doc/es/images/left.gif
Binary files differ
diff --git a/doc/es/images/manage-classes.gif b/doc/es/images/manage-classes.gif
new file mode 100644
index 000000000..73453dd34
--- /dev/null
+++ b/doc/es/images/manage-classes.gif
Binary files differ
diff --git a/doc/es/images/manage-jobs.gif b/doc/es/images/manage-jobs.gif
new file mode 100644
index 000000000..6018539aa
--- /dev/null
+++ b/doc/es/images/manage-jobs.gif
Binary files differ
diff --git a/doc/es/images/manage-printers.gif b/doc/es/images/manage-printers.gif
new file mode 100644
index 000000000..03cea9e3c
--- /dev/null
+++ b/doc/es/images/manage-printers.gif
Binary files differ
diff --git a/doc/es/images/modify-class.gif b/doc/es/images/modify-class.gif
new file mode 100644
index 000000000..ed30966ab
--- /dev/null
+++ b/doc/es/images/modify-class.gif
Binary files differ
diff --git a/doc/es/images/modify-printer.gif b/doc/es/images/modify-printer.gif
new file mode 100644
index 000000000..b8e79ff11
--- /dev/null
+++ b/doc/es/images/modify-printer.gif
Binary files differ
diff --git a/doc/es/images/navbar.gif b/doc/es/images/navbar.gif
new file mode 100644
index 000000000..30dfb3f67
--- /dev/null
+++ b/doc/es/images/navbar.gif
Binary files differ
diff --git a/doc/es/images/print-test-page.gif b/doc/es/images/print-test-page.gif
new file mode 100644
index 000000000..f1b8806d3
--- /dev/null
+++ b/doc/es/images/print-test-page.gif
Binary files differ
diff --git a/doc/es/images/reject-jobs.gif b/doc/es/images/reject-jobs.gif
new file mode 100644
index 000000000..1a83f5fbe
--- /dev/null
+++ b/doc/es/images/reject-jobs.gif
Binary files differ
diff --git a/doc/es/images/release-job.gif b/doc/es/images/release-job.gif
new file mode 100644
index 000000000..1aaea979b
--- /dev/null
+++ b/doc/es/images/release-job.gif
Binary files differ
diff --git a/doc/es/images/restart-job.gif b/doc/es/images/restart-job.gif
new file mode 100644
index 000000000..c3b0aeb4a
--- /dev/null
+++ b/doc/es/images/restart-job.gif
Binary files differ
diff --git a/doc/es/images/right.gif b/doc/es/images/right.gif
new file mode 100644
index 000000000..8ae8213ce
--- /dev/null
+++ b/doc/es/images/right.gif
Binary files differ
diff --git a/doc/es/images/set-as-default.gif b/doc/es/images/set-as-default.gif
new file mode 100644
index 000000000..c0982f7af
--- /dev/null
+++ b/doc/es/images/set-as-default.gif
Binary files differ
diff --git a/doc/es/images/show-active.gif b/doc/es/images/show-active.gif
new file mode 100644
index 000000000..9d8e1d5bd
--- /dev/null
+++ b/doc/es/images/show-active.gif
Binary files differ
diff --git a/doc/es/images/show-completed.gif b/doc/es/images/show-completed.gif
new file mode 100644
index 000000000..57f9b4396
--- /dev/null
+++ b/doc/es/images/show-completed.gif
Binary files differ
diff --git a/doc/es/images/start-class.gif b/doc/es/images/start-class.gif
new file mode 100644
index 000000000..245eb0176
--- /dev/null
+++ b/doc/es/images/start-class.gif
Binary files differ
diff --git a/doc/es/images/start-printer.gif b/doc/es/images/start-printer.gif
new file mode 100644
index 000000000..75942b6b2
--- /dev/null
+++ b/doc/es/images/start-printer.gif
Binary files differ
diff --git a/doc/es/images/stop-class.gif b/doc/es/images/stop-class.gif
new file mode 100644
index 000000000..a551fad8e
--- /dev/null
+++ b/doc/es/images/stop-class.gif
Binary files differ
diff --git a/doc/es/images/stop-printer.gif b/doc/es/images/stop-printer.gif
new file mode 100644
index 000000000..44ae5b875
--- /dev/null
+++ b/doc/es/images/stop-printer.gif
Binary files differ
diff --git a/doc/es/index.html b/doc/es/index.html
new file mode 100644
index 000000000..6c58fe4c5
--- /dev/null
+++ b/doc/es/index.html
@@ -0,0 +1,36 @@
+<HTML>
+<HEAD>
+ <TITLE>CUPS (Sistema de impresi&oacute;n com&uacute;n de UNIX)</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,8,50,22" HREF="http://www.easysw.com" ALT="P&aacute;gina inicial de Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,8,198,22" HREF="/admin" ALT="Tareas de administraci&oacute;n">
+ <AREA SHAPE="RECT" COORDS="216,8,270,22" HREF="/classes" ALT="Administra las clases de impresoras">
+ <AREA SHAPE="RECT" COORDS="292,8,344,22" HREF="/documentation.html" ALT="Ayuda en l&iacute;nea">
+ <AREA SHAPE="RECT" COORDS="366,8,435,22" HREF="/jobs" ALT="Administra trabajos">
+ <AREA SHAPE="RECT" COORDS="456,8,544,22" HREF="/printers" ALT="Administra impresoras">
+ <AREA SHAPE="RECT" COORDS="566,8,638,22" HREF="http://www.cups.org" ALT="Descargar la versi&oacute;n actual de CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="653" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="CUPS (Sistema de impresi&oacute;n com&uacute;n de UNIX)">
+</CENTER>
+
+<H1><A HREF="admin">Tareas de administraci&oacute;n</A></H1>
+<H1><A HREF="classes">Administrar las clases de impresoras</A></H1>
+<H1><A HREF="documentation.html">Ayuda en l&iacute;nea</A></H1>
+<H1><A HREF="jobs">Administrar trabajos</A></H1>
+<H1><A HREF="printers">Administrar impresoras</A></H1>
+<H1><A HREF="http://www.cups.org">Descargar la versi&oacute;n actual de CUPS</A></H1>
+
+<HR>
+
+<P>Common UNIX Printing System, CUPS, y el logo de CUPS son
+marcas registradas de <A HREF="http://www.easysw.com">Easy Software
+Products</A>. El copyright de CUPS 1997-2004 es de Easy Software Products.
+Todos los derechos reservados.
+
+</BODY>
+</HTML>
diff --git a/doc/figures.sc b/doc/figures.sc
new file mode 100644
index 000000000..7f7461070
--- /dev/null
+++ b/doc/figures.sc
Binary files differ
diff --git a/doc/fr/Makefile b/doc/fr/Makefile
new file mode 100644
index 000000000..4cdee96ac
--- /dev/null
+++ b/doc/fr/Makefile
@@ -0,0 +1,189 @@
+#
+# "$Id$"
+#
+# Documentation makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# HTMLDOC generation rules...
+#
+
+.SUFFIXES: .html .pdf .ps .shtml
+.shtml.html:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --numbered -f $@ $<
+.shtml.pdf:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --compression=9 \
+ --numbered --jpeg -f $@ $<
+.shtml.ps:
+ echo Formatting $@...
+ $(HTMLDOC) --titleimage images/cups-large.gif --duplex --numbered \
+ --jpeg -f $@ $<
+
+HTMLDOC = htmldoc --strict --quiet --bodycolor white
+
+#
+# Document files...
+#
+
+DOCUMENTS = sam.shtml sum.shtml
+WEBPAGES = cups.css cupsdoc.css index.html documentation.html
+WEBIMAGES = images/accept-jobs.gif \
+ images/add-class.gif \
+ images/add-printer.gif \
+ images/cancel-job.gif \
+ images/config-printer.gif \
+ images/continue.gif \
+ images/delete-class.gif \
+ images/delete-printer.gif \
+ images/hold-job.gif \
+ images/manage-classes.gif \
+ images/manage-jobs.gif \
+ images/manage-printers.gif \
+ images/modify-class.gif \
+ images/modify-printer.gif \
+ images/navbar.gif \
+ images/print-test-page.gif \
+ images/reject-jobs.gif \
+ images/release-job.gif \
+ images/restart-job.gif \
+ images/show-active.gif \
+ images/show-completed.gif \
+ images/start-class.gif \
+ images/start-printer.gif \
+ images/stop-class.gif \
+ images/stop-printer.gif
+
+
+#
+# Make all documents...
+#
+
+all: $(DOCUMENTS:.shtml=.pdf) $(DOCUMENTS:.shtml=.html) overview.pdf
+
+
+#
+# Make PS files...
+#
+
+ps: $(DOCUMENTS:.shtml=.ps) overview.ps
+
+
+#
+# Remove all generated files...
+#
+
+clean:
+ $(RM) $(DOCUMENTS:.shtml=.pdf)
+ $(RM) $(DOCUMENTS:.shtml=.html)
+ $(RM) overview.pdf
+
+
+#
+# Install all documentation files...
+#
+
+install:
+ $(INSTALL_DIR) $(DOCDIR)/fr
+ for file in $(WEBPAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/fr; \
+ done
+ $(INSTALL_MAN) overview.html $(DOCDIR)/fr
+ $(INSTALL_MAN) overview.pdf $(DOCDIR)/fr
+ for file in $(DOCUMENTS:.shtml=.html); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/fr; \
+ done
+ for file in $(DOCUMENTS:.shtml=.pdf); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/fr; \
+ done
+ $(INSTALL_DIR) $(DOCDIR)/fr/images
+ for file in $(WEBIMAGES); do \
+ $(INSTALL_MAN) $$file $(DOCDIR)/fr/images; \
+ done
+
+
+#
+# The overview, admin manual, programmers manual, and users manual get
+# special attention...
+#
+
+overview.pdf: overview.html
+ echo Formatting $@...
+ $(HTMLDOC) --path ".;.." --duplex --compression=9 --jpeg --webpage -f overview.pdf overview.html
+overview.ps: overview.html
+ echo Formatting $@...
+ $(HTMLDOC) --path ".;.." --duplex --jpeg --webpage -f overview.ps overview.html
+
+sam.html: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif -f $@ $<
+sam.pdf: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+sam.ps: sam.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+spm.html: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --path ".;.." --titleimage images/cups-large.gif -f $@ $<
+spm.pdf: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --path ".;.." --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+spm.ps: spm.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --path ".;.." --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+sum.html: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif -f $@ $<
+sum.pdf: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif --duplex --compression=9 \
+ --jpeg -f $@ $<
+sum.ps: sum.shtml
+ echo Formatting $@...
+ $(HTMLDOC) --toctitle "Table des matières" --path ".;.." --titleimage images/cups-large.gif --duplex --jpeg -f $@ $<
+
+$(DOCUMENTS:.shtml=.html): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../../LICENSE.html
+
+$(DOCUMENTS:.shtml=.pdf): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../../LICENSE.html
+
+$(DOCUMENTS:.shtml=.ps): \
+ glossary.shtml printing-overview.shtml \
+ references.shtml system-overview.shtml \
+ ../../LICENSE.html
+
+
+#
+# End of Makefile.
+#
diff --git a/doc/fr/cups.css b/doc/fr/cups.css
new file mode 100644
index 000000000..9285a5b5e
--- /dev/null
+++ b/doc/fr/cups.css
@@ -0,0 +1,4 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+TH { text-align: left }
+
diff --git a/doc/fr/cupsdoc.css b/doc/fr/cupsdoc.css
new file mode 100644
index 000000000..333f20144
--- /dev/null
+++ b/doc/fr/cupsdoc.css
@@ -0,0 +1,9 @@
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUP { font-family: sans-serif; font-size: 6pt }
+PRE { margin-left: 2em }
+CODE { font-weight: bold }
diff --git a/doc/fr/documentation.html b/doc/fr/documentation.html
new file mode 100644
index 000000000..f06f3160e
--- /dev/null
+++ b/doc/fr/documentation.html
@@ -0,0 +1,81 @@
+<HTML>
+<HEAD>
+ <TITLE>Documentation CUPS (Common UNIX Printing System)</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,50,22" HREF="http://www.easysw.com" ALT="Page d'accueil Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="76,8,182,22" HREF="admin" ALT="Accès aux tâches d'administration">
+ <AREA SHAPE="RECT" COORDS="202,8,260,22" HREF="classes" ALT="Administrer l'état des classes d'imprimantes">
+ <AREA SHAPE="RECT" COORDS="280,8,316,22" HREF="documentation.html" ALT="Aide électronique en ligne">
+ <AREA SHAPE="RECT" COORDS="334,8,394,22" HREF="jobs" ALT="Administrer les travaux d'impression">
+ <AREA SHAPE="RECT" COORDS="416,8,506,22" HREF="printers" ALT="Administrer les imprimantes">
+ <AREA SHAPE="RECT" COORDS="526,8,582,22" HREF="http://www.cups.org" ALT="Télécharger la dernière version du logiciel CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="596" HEIGHT="28" USEMAP="#navbar" BORDER="0" ALT="CUPS (Common UNIX Printing System)">
+</CENTER>
+
+<H1>Documentation</H1>
+
+La documentation CUPS suivante est disponible sur ce serveur:
+
+<UL>
+
+ <LI>Aperçu du logiciel CUPS - Common UNIX Printing System (français) (
+ <A HREF="overview.html">HTML</A> |
+ <A HREF="overview.pdf">PDF</A> )
+
+ <LI>Manuel de l'utilisateur (français) (
+ <A HREF="sum.html">HTML</A> |
+ <A HREF="sum.pdf">PDF</A> )
+
+ <LI>Manuel de l'administrateur (français) (
+ <A HREF="sam.html">HTML</A> |
+ <A HREF="sam.pdf">PDF</A> )
+
+ <LI>Manuel du programmeur (anglais) (
+ <A HREF="spm.html">HTML</A> |
+ <A HREF="spm.pdf">PDF</A> )
+
+ <LI>Plan d'organisation de la configuration (anglais) (
+ <A HREF="cmp.html">HTML</A> |
+ <A HREF="cmp.pdf">PDF</A> )
+
+ <LI>Implémentation du protocole IPP (Internet Printing Protocol) dans CUPS (anglais) (
+ <A HREF="ipp.html">HTML</A> |
+ <A HREF="ipp.pdf">PDF</A> )
+
+ <LI>Description de conception de l'interface (anglais) (
+ <A HREF="idd.html">HTML</A> |
+ <A HREF="idd.pdf">PDF</A> )
+
+ <LI>Description de conception logicielle (anglais) (
+ <A HREF="sdd.html">HTML</A> |
+ <A HREF="sdd.pdf">PDF</A> )
+
+ <LI>Spécification des capacités du logiciel (anglais) (
+ <A HREF="sps.html">HTML</A> |
+ <A HREF="sps.pdf">PDF</A> )
+
+ <LI>Description de la version du logiciel (anglais) (
+ <A HREF="svd.html">HTML</A> |
+ <A HREF="svd.pdf">PDF</A> )
+
+ <LI>Rapport de sécurité du logiciel (anglais) (
+ <A HREF="ssr.html">HTML</A> |
+ <A HREF="ssr.pdf">PDF</A> )
+
+</UL>
+
+<HR>
+
+<P>Common UNIX Printing System, CUPS, et le logo CUPS sont des marques déposées
+appartenant à <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS copyright 1997-2003 by Easy Software Products,
+Tous droits réservés.
+
+</BODY>
+</HTML>
diff --git a/doc/fr/glossary.shtml b/doc/fr/glossary.shtml
new file mode 100644
index 000000000..2cc0c1c89
--- /dev/null
+++ b/doc/fr/glossary.shtml
@@ -0,0 +1,73 @@
+<H1 TYPE="A" VALUE="1">Glossary</H1>
+
+<H2>Terms</H2>
+
+<DL>
+
+ <DT>C
+ <DD>A computer language.
+
+ <DT>parallel
+ <DD>Sending or receiving data more than 1 bit at a time.
+
+ <DT>pipe
+ <DD>A one-way communications channel between two programs.
+
+ <DT>serial
+ <DD>Sending or receiving data 1 bit at a time.
+
+ <DT>socket
+ <DD>A two-way network communications channel.
+
+</DL>
+
+<H2>Acronyms</H2>
+
+<DL>
+
+ <DT>ASCII
+ <DD>American Standard Code for Information Interchange
+
+ <DT>CUPS
+ <DD>Common UNIX Printing System
+
+ <DT>ESC/P
+ <DD>EPSON Standard Code for Printers
+
+ <DT>FTP
+ <DD>File Transfer Protocol
+
+ <DT>HP-GL
+ <DD>Hewlett-Packard Graphics Language
+
+ <DT>HP-PCL
+ <DD>Hewlett-Packard Page Control Language
+
+ <DT>HP-PJL
+ <DD>Hewlett-Packard Printer Job Language
+
+ <DT>IETF
+ <DD>Internet Engineering Task Force
+
+ <DT>IPP
+ <DD>Internet Printing Protocol
+
+ <DT>ISO
+ <DD>International Standards Organization
+
+ <DT>LPD
+ <DD>Line Printer Daemon
+
+ <DT>MIME
+ <DD>Multimedia Internet Mail Exchange
+
+ <DT>PPD
+ <DD>PostScript Printer Description
+
+ <DT>SMB
+ <DD>Server Message Block
+
+ <DT>TFTP
+ <DD>Trivial File Transfer Protocol
+
+</DL>
diff --git a/doc/fr/images/accept-jobs.gif b/doc/fr/images/accept-jobs.gif
new file mode 100644
index 000000000..99a4446e8
--- /dev/null
+++ b/doc/fr/images/accept-jobs.gif
Binary files differ
diff --git a/doc/fr/images/add-class.gif b/doc/fr/images/add-class.gif
new file mode 100644
index 000000000..b3a9fd980
--- /dev/null
+++ b/doc/fr/images/add-class.gif
Binary files differ
diff --git a/doc/fr/images/add-printer.gif b/doc/fr/images/add-printer.gif
new file mode 100644
index 000000000..0369a0e55
--- /dev/null
+++ b/doc/fr/images/add-printer.gif
Binary files differ
diff --git a/doc/fr/images/cancel-job.gif b/doc/fr/images/cancel-job.gif
new file mode 100644
index 000000000..b8f580011
--- /dev/null
+++ b/doc/fr/images/cancel-job.gif
Binary files differ
diff --git a/doc/fr/images/config-printer.gif b/doc/fr/images/config-printer.gif
new file mode 100644
index 000000000..7e09990fe
--- /dev/null
+++ b/doc/fr/images/config-printer.gif
Binary files differ
diff --git a/doc/fr/images/continue.gif b/doc/fr/images/continue.gif
new file mode 100644
index 000000000..09a0dd48b
--- /dev/null
+++ b/doc/fr/images/continue.gif
Binary files differ
diff --git a/doc/fr/images/delete-class.gif b/doc/fr/images/delete-class.gif
new file mode 100644
index 000000000..19331087a
--- /dev/null
+++ b/doc/fr/images/delete-class.gif
Binary files differ
diff --git a/doc/fr/images/delete-printer.gif b/doc/fr/images/delete-printer.gif
new file mode 100644
index 000000000..7a358d0db
--- /dev/null
+++ b/doc/fr/images/delete-printer.gif
Binary files differ
diff --git a/doc/fr/images/hold-job.gif b/doc/fr/images/hold-job.gif
new file mode 100644
index 000000000..6cf473cd9
--- /dev/null
+++ b/doc/fr/images/hold-job.gif
Binary files differ
diff --git a/doc/fr/images/manage-classes.gif b/doc/fr/images/manage-classes.gif
new file mode 100644
index 000000000..30ead441e
--- /dev/null
+++ b/doc/fr/images/manage-classes.gif
Binary files differ
diff --git a/doc/fr/images/manage-jobs.gif b/doc/fr/images/manage-jobs.gif
new file mode 100644
index 000000000..c968698d5
--- /dev/null
+++ b/doc/fr/images/manage-jobs.gif
Binary files differ
diff --git a/doc/fr/images/manage-printers.gif b/doc/fr/images/manage-printers.gif
new file mode 100644
index 000000000..3cd147748
--- /dev/null
+++ b/doc/fr/images/manage-printers.gif
Binary files differ
diff --git a/doc/fr/images/modify-class.gif b/doc/fr/images/modify-class.gif
new file mode 100644
index 000000000..2774a6532
--- /dev/null
+++ b/doc/fr/images/modify-class.gif
Binary files differ
diff --git a/doc/fr/images/modify-printer.gif b/doc/fr/images/modify-printer.gif
new file mode 100644
index 000000000..b9b6e0a98
--- /dev/null
+++ b/doc/fr/images/modify-printer.gif
Binary files differ
diff --git a/doc/fr/images/navbar.gif b/doc/fr/images/navbar.gif
new file mode 100644
index 000000000..9de54be18
--- /dev/null
+++ b/doc/fr/images/navbar.gif
Binary files differ
diff --git a/doc/fr/images/print-test-page.gif b/doc/fr/images/print-test-page.gif
new file mode 100644
index 000000000..cd214cf78
--- /dev/null
+++ b/doc/fr/images/print-test-page.gif
Binary files differ
diff --git a/doc/fr/images/reject-jobs.gif b/doc/fr/images/reject-jobs.gif
new file mode 100644
index 000000000..39ee3092f
--- /dev/null
+++ b/doc/fr/images/reject-jobs.gif
Binary files differ
diff --git a/doc/fr/images/release-job.gif b/doc/fr/images/release-job.gif
new file mode 100644
index 000000000..59e9c6347
--- /dev/null
+++ b/doc/fr/images/release-job.gif
Binary files differ
diff --git a/doc/fr/images/restart-job.gif b/doc/fr/images/restart-job.gif
new file mode 100644
index 000000000..86c654471
--- /dev/null
+++ b/doc/fr/images/restart-job.gif
Binary files differ
diff --git a/doc/fr/images/show-active.gif b/doc/fr/images/show-active.gif
new file mode 100644
index 000000000..36388e72a
--- /dev/null
+++ b/doc/fr/images/show-active.gif
Binary files differ
diff --git a/doc/fr/images/show-completed.gif b/doc/fr/images/show-completed.gif
new file mode 100644
index 000000000..9685dbe93
--- /dev/null
+++ b/doc/fr/images/show-completed.gif
Binary files differ
diff --git a/doc/fr/images/start-class.gif b/doc/fr/images/start-class.gif
new file mode 100644
index 000000000..ca6cfc890
--- /dev/null
+++ b/doc/fr/images/start-class.gif
Binary files differ
diff --git a/doc/fr/images/start-printer.gif b/doc/fr/images/start-printer.gif
new file mode 100644
index 000000000..be66c5b1d
--- /dev/null
+++ b/doc/fr/images/start-printer.gif
Binary files differ
diff --git a/doc/fr/images/stop-class.gif b/doc/fr/images/stop-class.gif
new file mode 100644
index 000000000..828b98a51
--- /dev/null
+++ b/doc/fr/images/stop-class.gif
Binary files differ
diff --git a/doc/fr/images/stop-printer.gif b/doc/fr/images/stop-printer.gif
new file mode 100644
index 000000000..24c5b1e7b
--- /dev/null
+++ b/doc/fr/images/stop-printer.gif
Binary files differ
diff --git a/doc/fr/index.html b/doc/fr/index.html
new file mode 100644
index 000000000..7ffd62664
--- /dev/null
+++ b/doc/fr/index.html
@@ -0,0 +1,36 @@
+<HTML>
+<HEAD>
+ <TITLE>CUPS (Common UNIX Printing System)</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,50,22" HREF="http://www.easysw.com" ALT="Page d'accueil Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="76,8,182,22" HREF="admin" ALT="Tâches d'administration">
+ <AREA SHAPE="RECT" COORDS="202,8,260,22" HREF="classes" ALT="Etat des classes d'imprimantes">
+ <AREA SHAPE="RECT" COORDS="280,8,316,22" HREF="documentation.html" ALT="Aide électronique en ligne">
+ <AREA SHAPE="RECT" COORDS="334,8,394,22" HREF="jobs" ALT="Etat des travaux d'impression">
+ <AREA SHAPE="RECT" COORDS="416,8,506,22" HREF="printers" ALT="Etat des imprimantes">
+ <AREA SHAPE="RECT" COORDS="526,8,582,22" HREF="http://www.cups.org" ALT="Télécharger la dernière version du logiciel CUPS">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="596" HEIGHT="28" USEMAP="#navbar" BORDER="0" ALT="CUPS (Common UNIX Printing System)">
+</CENTER>
+
+<H1><A HREF="admin">Tâches d'administration</A></H1>
+<H1><A HREF="classes">Administrer les classes d'imprimantes</A></H1>
+<H1><A HREF="documentation.html">Aide électronique en ligne</A></H1>
+<H1><A HREF="jobs">Administrer les travaux d'impression</A></H1>
+<H1><A HREF="printers">Administrer les imprimantes</A></H1>
+<H1><A HREF="http://www.cups.org">Télécharger la dernière version du logiciel CUPS</A></H1>
+
+<HR>
+<P>Common UNIX Printing System, CUPS, et le logo CUPS sont des marques déposées
+appartenant à <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS copyright 1997-2003 by Easy Software Products,
+Tous droits réservés.
+
+
+</BODY>
+</HTML>
diff --git a/doc/fr/overview.html b/doc/fr/overview.html
new file mode 100644
index 000000000..366f7ea22
--- /dev/null
+++ b/doc/fr/overview.html
@@ -0,0 +1,503 @@
+<HTML>
+<HEAD>
+ <META NAME="Author" CONTENT="Michael Sweet">
+ <META NAME="Translator" CONTENT="Marian REYT-LLABRES">
+ <TITLE>Un aperçu de CUPS (Common UNIX Printing System)</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cupsdoc.css">
+</HEAD>
+<BODY>
+<TABLE WIDTH="100%">
+<TR VALIGN=TOP>
+ <TD><IMG SRC="images/cups-large.gif" WIDTH="103" HEIGHT="120"></TD>
+ <TD><H1 ALIGN="RIGHT">Un aperçu de CUPS <BR>
+ (Common UNIX Printing System),<BR>
+ Version 1.1</H1>
+
+ <P ALIGN="RIGHT">July 10, 2000<BR>
+ Michael Sweet, Easy Software Products<BR>
+ Copyright 1998-2003, All Rights Reserved.</P>
+ <P ALIGN="RIGHT">Traduction française - 27/06/2002 : Marian REYT-LLABRES (mrl21_pub <i>at</i> netcourrier.com).</P>
+ </TD>
+</TR>
+</TABLE>
+
+<P>Ce document décrit le logiciel CUPS<SUP>TM</SUP> (Common UNIX Printing
+System<SUP>TM</SUP>), un système d'impression portable et extensible pour UNIX<SUP>&reg;</SUP>.
+CUPS est développé par
+<A HREF="http://www.easysw.com">Easy Software Products</A>, un éditeur logiciel
+implanté à Hollywood, Maryland qui vend des logiciels commerciaux pour UNIX depuis 1993
+par le biais de plus de 40 distributeurs répartis dans plus de 80 pays de par le monde.
+
+<P>Des informations supplémentaires sur CUPS sont disponibles sur le Web à l'adresse "<A HREF="http://www.cups.org">http://www.cups.org</A>".
+
+<H2>Avant-propos</H2>
+
+<P><hr width="50%" size="1px" color="#000000"><I><b>Note du traducteur : </b>Amies lectrices, amis lecteurs, j'ai fait le choix de <b>ne pas traduire</b> l'expression anglaise <b>"default"</b> par la
+version française
+habituellent utilisée <b>"par défaut"</b> que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents".
+<br /><br />
+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès",
+personnellement je cherche encore mon "imprimante par excès" !)
+mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en
+précise pas <b>explicitement</b> la valeur/nature/teneur".
+<br /><br />
+Or la langue française possède justement un mot pout exprimer ce concept
+: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la
+conséquence nécessaire."). Dans la mesure du possible, j'utiliserai
+cet adjectif sauf dans les cas où son emploi n'est pas suffisamment <b>explicite</b> (sic !). Je lui
+préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard".
+<br /><br />
+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable,
+je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le
+reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur !
+<br /><br />
+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à
+l'amélioration constante de la qualité du présent manuel.
+<br /><br />
+Bonne lecture !
+</I><hr width="50%" size="1px" color="#000000"></P>
+
+
+<P>
+Historiquement, l'impression sous UNIX a toujours été réalisée en utilisant
+un des deux systèmes d'impression - le Berkeley Line Printer Daemon ("LPD") [RFC1179]
+et l'AT&amp;T Line Printer. Ces systèmes d'impression ont été conçus dans les années 70 pour
+imprimer du texte sur des imprimantes matricielles à aiguilles; les constructeurs ont
+depuis ajouté divers systèmes de pilotage sur bien d'autres types d'imprimantes.
+
+<P>
+Des remplaçants pour ces systèmes d'impression ont émergé [LPRng,
+Palladin, PLP], cependant aucun d'eux n'a fondamentalement changé les capacités de ces systèmes historiques.
+
+<P>
+Au cours des dernières années, plusieurs tentatives de développement
+d'une interface d'impression standard ont été faites, celles-ci incluant le projet
+de standard d'impression POSIX développé par l'IEEE (Institute of Electrical and Electronics
+Engineers, Inc.) [IEEE-1387.4] ainsi que le protocole IPP (Internet Printing
+Protocol) développé par l'IETF (Internet Engineering Task Force) par le biais du PWG
+(Printer Working Group) [IETF-IPP]. Le standard d'impression POSIX définit un ensemble commun
+d'outils en ligne de commande ainsi qu'une interface C pour l'administration des
+imprimantes et des travaux d'impression, mais il a été abandonné par l'IEEE.
+
+<P>Le protocole IPP définit des extensions au protocole HTTP 1.1 (Hypertext Transport Protocol)
+[RFC2616] afin de fournir le support pour un service d'impression à distance.
+IPP/1.0 a été accepté par l'IETF comme une RFC (Request For Comments - Requête pour commentaires )
+expérimentale en octobre 1999. Depuis lors, le PWG (Printing Working Group) a développé un jeu
+de spécifications mises à jour pour IPP/1.1 qui a été accepté par l'IETF et attendent leur publication
+en tant que proposition de standard. Contrairement au système d'impression POSIX, IPP enthousiasme les
+acteurs de l'industrie et est en passe de devenir la solution standard d'impression via réseau pour tous
+les systèmes d'exploitation.
+
+<P>CUPS utilise le protocole IPP/1.1 pour fournir un système d'impression complet et moderne
+pour UNIX qui peut être étendu pour prendre en charge d'autres imprimantes, périphériques et protocoles tout
+en fournissant une compatibilité avec les applications UNIX existantes. CUPS est un logiciel libre distribué
+conformément aux termes de la licence GPL (General Public License).
+
+<H2>Historique</H2>
+
+
+<P>La première version de production de CUPS (basée sur le protocole IPP/1.0) a été réalisée
+en octobre 1999. Depuis ce jour, nous avons réalisé diverses mises à jour du produit original CUPS 1.0 qui
+concernaient la sécurité, la portabilité et des corrections de bogues, mais aucune nouvelle fonctionnalité n'a été
+ajoutée, ceci afin de garantir la stabilité du code de CUPS
+
+<P>CUPS 1.1 est basé sur IPP/1.1 et ajoute nombre des améliorations fonctionnelles qui ont été demandées
+par les utilsateurs. Comme pour la version 1.0, CUPS 1.1 sera suivie de mises à jour qui résoudront tout
+problème découvert sur le logiciel, mais elles n'ajouteront aucune nouvelle fonctionnalité.
+
+<H2>Aperçu de l'architecture</H2>
+
+<P>Comme la plupart des systèmes d'impression, CUPS est conçu autour d'un processus d'ordonnancement central qui
+répartit les travaux d'impression, exécute des tâches d'administration, fournit des informations sur l'état des imprimantes
+aux programmes locaux et distants, et informe les utilisateurs si nécessaire. La Figure 1 montre la base de l'organisation de CUPS.
+
+<CENTER><IMG SRC="images/cups-block-diagram.gif" WIDTH="470" HEIGHT="170"></CENTER>
+<P ALIGN="CENTER">Figure 1 - Diagramme de l'architecture globale de CUPS</P>
+
+<H3>L'ordonnanceur (Scheduler)</H3>
+
+<P>L'ordonnanceur est une application serveur HTTP 1.1 qui traite les requêtes HTTP. En plus de
+traiter les demandes reçues par le biais de requêtes IPP POST, l'ordonnanceur agit également comme un serveur
+"web" totalement fonctionnel qui ouvre l'accès à la documentation, à la surveillance de l'état du système et
+ à son administration.
+
+
+<P>L'ordonnanceur maintient également une liste des imprimantes disponibles sur le réseau local (LAN) et répartit
+les travaux d'impression si nécessaire en employant les filtres ou les programmes appropriés.
+
+<H3>Fichiers de configuration</H3>
+
+Les fichiers se répartissent de la manière suivante :
+
+<UL>
+
+ <LI>Le fichier de configuration du serveur HTTP.
+
+ <LI>Les fichiers de définition des imprimantes et des classes d'imprimantes.
+
+ <LI>Les fichiers décrivant les règles de conversion des types MIME.
+
+ <LI>Les fichiers PPD (PostScript Printer Description).
+
+</UL>
+
+<P>Le fichier de configuration du serveur HTTP est conçu dans la même optique que celle du fichier de configuration du serveur Apache et
+définit toutes les règles de contrôle d'accès pour le serveur.
+
+<P>Les fichiers de définition des imprimantes et des classes d'imprimantes listent les classes d'imprimantes et les
+files d'impression disponibles. Les classes d'imprimantes sont des collections d'imprimantes. Les travaux
+d'impression envoyés à une classe sont transmis à la première imprimante disponible de la classe selon un méthode de type "round-robin".
+
+<P>Les fichiers de définition des types MIME listent les différents types MIME pris en charge (texte simple, postscript, etc...)
+et des règles "magiques" pour détecter automatiquement le format d'un fichier. Ils sont utilisés par le serveur
+HTTP pour renseigner le champ <I>Content-Type</I> des requêtes <I>GET</I> et <I>HEAD</I>, et par le
+gestionnaire de requêtes IPP pour déterminer le type de fichier lorsqu'une requête <I>Print-Job</I> ou <I>Send-File</I>
+est reçue avec un champ <I>document-format</I> contenant la valeur <I>application/octet-stream</I>.
+
+<P>Les fichiers de règles de conversion MIME listent les filtres disponibles. Les filtres sont utilisés
+quand un travail d'impression est soumis, de sorte qu'une application puisse envoyer un format de fichier
+adapté au système d'impression qui convertit alors le document dans un format imprimable. Chaque filtre a un
+coût relatif associé, et l'algorithme de filtrage choisit le jeu de filtres qui permettra de convertir le
+fichier avec un coût minimal.
+
+<P>Les fichiers PPD décrivent les capacités de toutes les imprimantes, pas seulement celles de type PostScript.
+Il y a un fichier PPD pour chaque imprimante. Les fichier PPD pour les imprimantes non-PostScript définissent des
+filtres additionnels au moyen des attributs <I>cupsFilter</I> afin de prendre en charge les pilotes d'imprimantes.
+
+<H3>L'API CUPS</H3>
+
+<P>L'API CUPS contient des fonctions spécifiques à CUPS pour mettre en file d'attente les travaux
+d'impression, récupérer de l'information sur les imprimantes, accéder aux ressources via les
+protocoles HTTP et IPP, manipuler les fichiers PPD. Contrairement au reste de CUPS, l'API CUPS
+est distribuée conformément aux termes de la licence LGPL ainsi elle peut être utilisée par des
+applications non-GPL.
+
+<H3>Commandes de type Berkeley et System V</H3>
+
+<P>CUPS fournit une interface en ligne de commande de type System V et Berkeley pour soumettre des travaux
+d'impression et vérifier l'état des imprimantes. Les commandes <CODE>lpstat</CODE> et <CODE>lpc status</CODE>
+affichent aussi les imprimantes réseau ("imprimante@serveur") lorsque l'exploration réseau des imprimantes ("printer browsing") est activée.
+
+<P>Les commandes d'administration de type System V sont fournies pour administrer les imprimantes et les classes
+d'imprimantes. L'outil d'administration d'imrpimante Berkeley <CODE>lpc</CODE> est uniquement pris en charge en mode
+"lecture seule" pour vérifier l'état actuel des files d'impression et de l'ordonnanceur.
+
+<H3>Filtres</H3>
+
+<P>Un programme de filtrage lit les données depuis l'entrée standard ou depuis un fichier si un nom de fichier est indiqué.
+Tous les filtres doivent prendre en charge un jeu commun d'options incluant le nom d'imprimante, ne n°
+d'identification du travail d'impression (ID), le nom de l'utilisateur, le nombre de copies,
+et des options pour le travail d'impression. Toute sortie est envoyée vers la sortie standard.
+
+<P>Des filtres sont fournis pour de nombreux formats de fichiers y compris les fichiers image et des filtres
+PostScript "matriciels" <i>(NdT : "raster" = au sens où le document imprimé est en fait une image générée par une trame de points,
+par exemple une imprimante à jet d'encre est de type "matriciel" même si l'impression ne se fait pas au moyen
+d'aiguilles venant frapper un ruban et déposer de l'encre sur le papier, souvenirs, souvenirs...)</i> qui prennent
+en charge les
+imprimantes non-PostScript <i>(NdT : par opposition, le langage PostScript est un langage de description de
+page de type vectoriel)</i>. Plusieurs filtres sont exécutés
+en parallèle pour produire le format de sortie désiré.
+
+<P>Le filtre PostScript "matriciel" est basé sur le coeur du logiciel GNU Ghostscript 5.50. Au lieu
+d'utiliser l'application d'arrière-plan et les pilotes d'imprimantes Ghostscript, le filtre CUPS utilise un
+pilote "matriciel" d'imprimante générique et une application d'arrière-plan compatible CUPS pour prendre en
+compte toute imprimante de type "matriciel". Ceci permet d'employer le même filtre de pilote d'impression
+pour imprimer des données de type "matriciel" provenant de n'importe quel filtre. <i>(NdT : je suis preneur de toute information ou tout éclaircissement qui pourrait me permettre de produire une
+meilleure traduction pour les trois paragraphes précédents.)</i>
+
+<H3>Rendu d'image dans CUPS</H3>
+
+<P>La librairie de rendu d'image de CUPS fournit des fonctions pour manipuler
+des images de grande taille, faire des conversions de palettes et des manipulations
+sur les couleurs, dimensionner les images en vue de l'impression et administrer les flux de données
+pour les pages de type "matriciel". Elle est utilisée par les filtres de fichiers image de CUPS,
+et tous les pilotes d'imprimantes de type "matriciel".
+
+<H3>Programmes d'arrière-plan (Backends)</H3>
+
+<P>Un programme d'arrière-plan est programme qui envoie des données d'impression à un périphérique ou
+à une connexion réseau. Des programmes d'arrière-plan pour port parallèle, port série, USB, LPD, IPP,
+et les connexions AppSocket (JetDirect) sont fournis dans CUPS 1.1.
+
+<P>Les versions de SAMBA commençant à partir de la version 2.0.6. incluent un programme d'arrière-plan SMB
+(<CODE>smbspool(1)</CODE>) qui peut être employé avec CUPS 1.0 ou 1.1 pour imprimer vers des
+machines Windows.
+
+<H2>Impression réseau</H2>
+
+<P>Traditionnellement, l'impression réseau a toujour été l'une des choses les plus difficiles à faire
+fonctionner sous UNIX. Une des raisons est que chaque fabricant ou vendeur a ajouté ses propres extensions
+au protocol LPD (le standard précédent pour l'impression réseau), rendant l'impression inter-plateformes difficile
+voire impossible.
+
+<P>Une autre raison est que vous devez administrer chaque imprimante réseau sur chaque machine cliente.
+Dans certains cas, vous pouvez clôner la configuration à partir d'un original pour tous les autres postes, mais
+même cette méthode peut être une perte de temps et une source d'erreur. Quelque chose de mieux est nécessaire.
+
+<P>CUPS fournit l'exploration des imprimantes réseau ("printer browsing") qui autorise les clients à
+voir et utiliser automatiquement les imprimantes de tout serveur sur le réseau local (LAN). Cela signifie que
+vous devez seulement configurer le serveur et les clients verront automatiquement les imprimantes et les classes
+d'imprimantes définies sur celui-ci.
+
+<P>En plus de cela, CUPS peut automatiquement fusionner plusieurs imprimantes réseau identiques en des
+classes implicites <i>(NdT : le terme "implicite" est ici la traduction littérale du même mot anglais "implicit" et non celle de l'expression "default". Cf. ma note en tête du présent manuel.)</i>. Cela permet aux clients de soumettre des travaux d'impression à une classe implicite et que
+ceux-ci soient imprimés sur la première imprimante ou le premier serveur disponible. En plus de cela, des fonctions de
+répartition de charge et de tolérance de panne sont activées en définissant simplement la même imprimante sur plusieurs serveurs!
+
+<H2>Nouvelles fonctionnalités dans CUPS 1.1</H2>
+
+<P>CUPS 1.1 inclut de nombreuses nouvelles fonctionnalités et caractéristiques:
+
+<OL>
+
+ <LI><A HREF="#BACKENDS">Programmes d'arrière-plan (Backends)</A>
+
+ <LI><A HREF="#BANNERS">Support des pages de garde (Banner Page)</A>
+
+ <LI><A HREF="#DIGEST">Authentication "Digest"</A>
+
+ <LI><A HREF="#DIRSVC">Services d'annuaires</A>
+
+ <LI><A HREF="#FHS2">Changement de stucture des répertoires</A>
+
+ <LI><A HREF="#DOCOS">Documentation</A>
+
+ <LI><A HREF="#DRIVERS">Pilotes</A>
+
+ <LI><A HREF="#FILTERS">Filtres</A>
+
+ <LI><A HREF="#IPP">Prise en charge IPP</A>
+
+ <LI><A HREF="#PERSISTENCE">Persistance des travaux d'impression</A>
+
+ <LI><A HREF="#LPD">Prise en charge des clients LPD</A>
+
+ <LI><A HREF="#USEROPTS">Imprimantes et options définies par l'utilisateur</A>
+
+ <LI><A HREF="#WEB">Interface d'administration "web"</A>
+
+</OL>
+
+<H3><A NAME="BACKENDS">1. Programmes d'arrière-plan (Backends)</A></H3>
+
+<P>CUPS 1.1 implémente une nouvelle interface pour les programmes d'arrière-plan afin de récupérer
+la liste des périphériques disponibles pour les clients CUPS. Ceci permet aux interfaces d'administration
+d'interroger l'ordonnanceur CUPS pour obtenir une liste des périphériques disponibles, configurer automatiquement
+les imprimante si les informations d'identification du périphérique sont disponibles, et présenter une liste à
+l'utilisateur plutôt que compter sur celui-ci pour savoir quels périphériques sont réellement disponibles sur son système.
+
+
+<P>La nouvelle version inclut un programme d'arrière-plan pour les imprimantes USB sous
+*BSD et GNU/Linux. La prise en charge USB sous Solaris 8 sera fournie dans une prochaine mise à
+jour du produit.
+
+<H3><A NAME="BANNERS">2. Pages de garde (Banner Page)</A></H3>
+
+<P>CUPS 1.1 inclut la prise en charge des page de garde au début et à la fin d'un travail d'impression. Les
+pages de garde peuvent être dans n'importe quel format de fichier et prennent en charge la substitution de
+variable pour le titre des travaux d'impression, les noms d'utilisateurs, etc. Des pages de garde implicites
+("par défaut") peuvent être associées à chaque imprimante et peuvent être outrepassées par l'utilisateur
+au moyen des options sur la ligne de commande.
+
+<H3><A NAME="DIGEST">3. Authentification "Digest"</A></H3>
+
+<P>L'authentification "Digest" fournit une méthode plus sécurisée pour
+accéder au système d'impression. Contrairement à l'authentification "Basic", l'authentification "Digest"
+n'envoie pas de mots de passe en clair sur le réseau ainsi il est plus difficile d'avoir un accès non
+autorisé à votre système.
+
+<P>CUPS 1.1 implémente l'authentification "Digest" en utilisant un fichier de mot de passe MD5 spécial
+au lieu du fichier de mots de passe UNIX. Ce fichier est administré au moyen de la commande <CODE>lppasswd</CODE>.
+
+<H3><A NAME="DIRSVC">4. Services d'annuaires</A></H3>
+
+<P>CUPS 1.1 ajoute une nouvelle fonctionnalité de service d'annuaire ("printer browsing" = exploration des
+imprimantes) pour permettre d'employer plus facilement CUPS sur de grands réseaux locaux (LAN) ou des réseaux WAN.
+Vous pouvez maintenant surveiller un serveur distant pour obtenir des informations d'impression et les relayer
+sur le LAN, ainsi que limiter les informations d'impression qui sont traitées (par exemple, cacher des serveurs,
+des domaines ou des réseaux que vous ne voulez pas voir).
+
+<H3><A NAME="FHS2">5. Changement de structure de répertoires</A></H3>
+
+<P>CUPS 1.1 utilise désormais une structure de répertoire conforme à la version 2.0 des recommandations FHS ("Filesystem Hierarchy Standard")
+Ceci devrait rendre son intégration dans des distributions *BSD ou GNU/Linux plus facile.
+
+<H3><A NAME="DOCOS">6. Documentation</A></H3>
+
+<P>La documentation de CUPS 1.1 a subi de nombreuses révisions incluant une réécriture complète du guide de
+l'administrateur, un nouveau guide du programmeur et un manuel de référence de l'implémentation du protocole IPP.
+<i>(NdT : ...et maintenant, une traduction française d'une partie celle-ci... ;o)</i>
+
+<H3><A NAME="DRIVERS">7. Pilotes</A></H3>
+
+<P>CUPS 1.1 inclut des pilotes pour imprimantes matricielles à aiguilles et jet d'encre EPSON.
+Comme pour les pilots HP PCL, les pilotes EPSON ne fournissent pas forcément la meilleure sortie possible pour
+chaque imprimante mais devrait produire une qualité suffisante pour les impressions de la vie courante.
+
+<H3><A NAME="FILTERS">8. Filtres</A></H3>
+
+<P>CUPS 1.1 inclut de nouveaux filtres image, PostScript, PDF et texte. Les filtres image ont
+été mis à jour pour prendre en charge les fichiers Windows BMP et Alias PIX.
+
+<P>Le filtre PostScript est maintenant basé sur GNU/Ghostscript 5.50. Le nouveau filtre fournit des performances
+bien meilleures avec les imprimantes haute résolution et prend en charge la plupart des caractéristiques du
+langage PostScript 3.
+
+<P>Le nouveau filtre PDF est basé sur l'excellent programme Xpdf de Derek Noonburg et prend en charge la mise
+à l'échelle automatique de page. Le nouveau filtre est plus rapide, plus petit, un remplaçant plus avantageux
+pour le filtre PDF GNU/Ghostscript qui était utilisé dans CUPS 1.0.
+
+<P>Le nouveau filtre texte prend à présent en charge le texte bidirectionnel et peut encapsuler les polices
+de caractères si nécessaire.
+
+<H3><A NAME="IPP">9. Support IPP</A></H3>
+
+<P>La partie la moins visible de CUPS est probablement le support IPP. CUPS 1.1 implémente toutes les opérations
+et attributs requis dans le protocole IPP/1.1 et la plupart de ceux qui sont facultatifs.Les opérations optionnelles
+Create-Job et Send-File sont maintenant implémentées, permettant une meilleur compatibilité avec les systèmes
+d'impression de type System V (un n° de travail d'impression par commande <CODE>lp</CODE>) et le support des pages
+de garde.
+
+<H3><A NAME="PERSISTENCE">10. Persistance des travaux d'impression</A></H3>
+
+<P>CUPS 1.1 supporte la persistance des travaux d'impression. Cela signifie que les travaux d'impression sont
+préservés même après un redémarrage du système, une fonctionnalité qui était malheureusement absente de CUPS 1.0.
+
+<P>En plus de cela, CUPS 1.1 vous permet de conserver des informations sur un travail d'impression après que le
+travail ait été imprimé. Le mode de base de persistance de travaux d'impression fournit un historique des travaux
+(nombre de pages imprimées, heure de soumission du travail, etc...) mais ne conserve pas les fichiers réels du
+travail d'impression. Cela peut être changé pour supprimer toute information sur les travaux d'impression après
+qu'ils aient été imprimés ou pour conserver les fichiers réels des travaux d'impression de manière à pouvoir
+les resoumettre ultérieurement.
+
+<H3><A NAME="LPD">11. Support de clients LPD</A></H3>
+
+<P>A la demande générale, CUPS 1.1 prend en charge les client basés sur LPD au moyen d'un nouveu mini démon qui
+traite les requêtes LPD et les transmet au serveur principal.
+
+<H3><A NAME="USEROPTS">12. Imprimantes et options définies par l'utilisateur</A></H3>
+
+<P>CUPS 1.1 inclut la prise en charge d'imprimantes et d'options définies par l'utilisateur via une nouvelle
+commande <CODE>lpoptions</CODE>. Les imprimantes définies par l'utilisateur sont des instances spéciales
+d'imprimantes disponibles (par exemple "imprimante/instance" ou "imprimante@serveur/instance") qui peuvent avoir
+leur propre options de base telles la taille du papier, la résolution, et ainsi de suite.
+La commande <CODE>lpoptions</CODE> peut également être utilisée pour définir une autre file d'impression implicite.
+
+<H3><A NAME="WEB">13. Interface d'administration "web"</A></H3>
+
+<P>CUPS 1.0 fournissait une interface très limitée pour la surveillance des classes d'imprimantes, des travaux
+d'impression et des imprimantes au moyen des navigateurs web. CUPS 1.1 remplace cette interface par une interface
+d'administration améliorée qui vous permet d'ajouter, modifier, supprimer, configurer et contrôler les classes
+d'imprimantes, les travaux d'impression et les imprimantes.
+
+<H2>Logiciels utilisant CUPS</H2>
+
+<P>Il s'est passé beaucoup de choses depuis que CUPS 1.0 est sorti, et beaucoup de produits logiciels prennent en
+charge CUPS. Nous avons contribué au code de l'équipe SAMBA pour prendre en charge CUPS, et une partie de cela
+est déjà disponible dans SAMBA 2.0.6 et 2.0.7. Avec un peu de chance, les pièces finales qui fournissent une
+complète intégration dans SAMBA seront disponibles dans la prochaine version de SAMBA.
+
+<P>Deux interfaces graphiques utilisant CUPS ont également vu le jour. Le projet KUPS fournit une interface
+pour CUPS basée sur KDE et peut être trouvée à l'adresse :
+
+<UL><PRE>
+<A HREF="http://kups.sourceforge.net">http://kups.sourceforge.net</A>
+</PRE></UL>
+
+<P>Le projet XPP ("X Printing Panel") fournit une interface graphique de panneau d'impression pour CUPS et
+peut être trouvé à l'adresse:
+
+<UL><PRE>r
+<A HREF="http://www.phy.uni-bayreuth.de/till/xpp">http://www.phy.uni-bayreuth.de/till/xpp/</A>
+</PRE></UL>
+
+<P>De nombreux autres filtres, pilotes et tutoriels, etc ont été rendus disponibles dans le "bazaar" CUPS à
+l'adresse:
+
+<UL><PRE>
+<A HREF="http://www.cups.org/bazaar.cgi">http://www.cups.org/bazaar.cgi</A>
+</PRE></UL>
+
+<P>Finalement, notre propre logiciel ESP Print Pro utilise CUPS pour fournir des pilotes pour des milliers
+d'imprimantes et peut être trouvé à l'adresse:
+
+<UL><PRE>
+<A HREF="http://www.easysw.com/printpro">http://www.easysw.com/printpro</A>
+</PRE></UL>
+
+<H2>Systèmes d'exploitation utilisant CUPS</H2>
+
+<P>Un de nos buts a toujours été d'amener autant de distributions UNIX et GNU/Linux que possible à utiliser CUPS.
+Debian fournit actuellement CUPS dans sa distribution stable, et beaucoup d'autres distributions projettent
+d'en faire autant dans leurs prochaines versions.
+
+<H2>Résumé</H2>
+
+<P>Le système CUPS fournit une interface d'impression moderne pour les applications UNIX qui est à la fois
+flexible et ergonomique. Le logiciel fournit des interfaces sur ligne de commande compatibles avec System V et Berkeley pour
+assurer la compatibilité avec les applications existantes. CUPS 1.1 ajoute de nombreuses nouvelles fonctionnalités
+qui en font encore plus un excellent choix pour imprimer sous UNIX.
+
+<H2>Qui contacter ?</H2>
+
+<P>Pour de plus amples informations, contactez-nous à:
+
+<UL><PRE>
+Attn: CUPS Information
+Easy Software Products
+44141 Airport View Drive Suite 204
+Hollywood, Maryland 20636-3111 USA
+
++1.301.373.9600
+
+<A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
+</PRE></UL>
+
+<H2>Références</H2>
+
+<DL>
+
+ <DT>IEEE-1387.4</DT>
+
+ <DD>System Administration - Part 4: Printing Interfaces (draft)</DD>
+
+ <DT><A HREF="http://www.pwg.org/ipp/index.html">IETF-IPP</A></DT>
+
+ <DD>Internet Printing Protocol/1.1</DD>
+
+ <DT><A HREF="http://www.astart.com/lprng.html">LPRng</A></DT>
+
+ <DD>An enhanced, extended, and portable implementation of the
+ Berkeley LPR print spooler functionality</DD>
+
+ <DT>Palladin</DT>
+
+ <DD>A printing system developed at the Massachussetts Institute
+ of Technology</DD>
+
+ <DT><A HREF="http://www-usa.iona.com//hyplan/jmason/plp.html">PLP</A></DT>
+
+ <DD>The Portable Line Printer spooler system</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC1179</A></DT>
+
+ <DD>Line Printer Daemon Protocol</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc2046.txt">RFC2046</A></DT>
+
+ <DD>Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</A></DT>
+
+ <DD>Hypertext Transfer Protocol -- HTTP/1.1</DD>
+
+</DL>
+
+<H2>Trademarks</H2>
+
+<P>The Common UNIX Printing System, CUPS, and the CUPS logo are the
+trademark property of Easy Software Products. All other trademarks are
+the property of their respective owners.
+
+</BODY>
+</HTML>
diff --git a/doc/fr/overview.pdf b/doc/fr/overview.pdf
new file mode 100644
index 000000000..07294c1cd
--- /dev/null
+++ b/doc/fr/overview.pdf
Binary files differ
diff --git a/doc/fr/printing-overview.shtml b/doc/fr/printing-overview.shtml
new file mode 100644
index 000000000..1682dae7f
--- /dev/null
+++ b/doc/fr/printing-overview.shtml
@@ -0,0 +1,125 @@
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
+
+<P>This chapter provides an overview of how the Common UNIX Printing System
+works.
+
+<H2>The Printing Problem</H2>
+
+<P>For years <I>the printing problem</I> has plagued UNIX. Unlike
+Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or
+system in place for supporting printers. Among the solutions currently
+available, the Berkeley and System V printing systems are the most
+prevalent.
+
+<P>These printing systems support line printers (text only) or
+PostScript printers (text and graphics), and with some coaxing they can
+be made to support a full range of printers and file formats. However,
+because each varient of the UNIX operating system uses a different
+printing system than the next developing printer drivers for a wide
+range of printers and operating systems is extremely difficult. That
+combined with the limited volume of customers for each UNIX varient has
+forced most printer vendors to give up supporting UNIX entirely.
+
+<P>CUPS is designed to eliminate <I>the printing problem</I>. One
+common printing system can be used by all UNIX varients to support the
+printing needs of users. Printer vendors can use its modular filter
+interface to develop a single driver program that supports a wide range
+of file formats with little or no effort. Since CUPS provides both the
+System V and Berkeley printing commands, users (and applications) can
+reap the benefits of this new technology with no changes.
+
+<H2>The Technology</H2>
+
+<P>CUPS is based upon an emerging Internet standard called the Internet
+Printing Protocol. IPP has been embraced by dozens of printer and
+printer server manufacturers and is supported by Microsoft Windows
+2000.
+
+<P>IPP defines a standard protocol for printing as well as managing
+print jobs and printer options like media size, resolution, and so
+forth. Like all IP-based protocols, IPP can be used locally or over the
+Internet to printers hundreds or thousands of miles away. Unlike other
+protocols, however, IPP also supports access control, authentication,
+and encryption, making it a much more capable and secure printing
+solution than older ones.
+
+<P>IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP")
+which is the basis of web servers on the Internet. This allows users
+to view documentation, check status information on a printer or server,
+and manage their printers, classes, and jobs using their web browser.
+
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+Basic, Digest, and local certificate authentication and user, domain,
+or IP-based access control. TLS encryption will be available in future
+versions of CUPS.
+
+<H2>Jobs</H2>
+
+<P>Each file or set of files that is submitted for printing is called a
+<I>job</I>. Jobs are identified by a unique number starting at 1 and
+are assigned to a particular destination, usually a printer. Jobs can
+also have options associated with them such as media size, number of
+copies, and priority.
+
+<H2>Classes</H2>
+
+<P>CUPS supports collections of printers known as <I>classes</I>. Jobs
+sent to a class are forwarded to the first available printer in the
+class.
+
+<H2>Filters</H2>
+
+<P>Filters allow a user or application to print many types of files
+without extra effort. Print jobs sent to a CUPS server are filtered
+before sending them to a printer. Some filters convert job files to
+different formats that the printer can understand. Others perform page
+selection and ordering tasks.
+
+<P>CUPS provides filters for printing many types of image files,
+HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript
+and image file Raster Image Processor ("RIP") filters that convert
+PostScript or image files into bitmaps that can be sent to a raster
+printer.
+
+<H2>Backends</H2>
+
+<P>Backends perform the most important task of all - they send the
+filtered print data to the printer.
+
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ports, and over the network via the IPP, JetDirect (AppSocket), and
+Line Printer Daemon ("LPD") protocols. Additional backends are
+available in network service packages such as the SMB backend
+included with the popular SAMBA software.
+
+<P>Backends are also used to determine the available devices. On
+startup each backend is asked for a list of devices it supports,
+and any information that is available. This allows the parallel
+backend to tell CUPS that an EPSON Stylus Color 600 printer is
+attached to parallel port 1, for example.
+
+<H2>Printer Drivers</H2>
+
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+printer. CUPS includes sample printer drivers for Hewlett-Packard
+LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+and Stylus Photo printers. While these drivers do not generate optimal
+output for the different printer models, they do provide basic printing
+and demonstrate how you can write your own printer drivers and
+incorporate them into CUPS.
+
+<H2>Networking</H2>
+
+<P>Printers and classes on the local system are automatically shared
+with other systems on the network. This allows you to setup one system
+to print to a printer and use this system as a printer server or spool
+host for all of the others. Users may then select a local printer by
+name or a remote printer using "name@server".
+
+<P>CUPS also provides <I>implicit classes</I>, which are collections of
+printers and/or classes with the same name. This allows you to setup
+multiple servers pointing to the same physical network printer, for
+example, so that you aren't relying on a single system for printing.
+Because this also works with printer classes, you can setup multiple
+servers and printers and never worry about a single point of failure
+unless all of the printers and servers go down!
diff --git a/doc/fr/references.shtml b/doc/fr/references.shtml
new file mode 100644
index 000000000..4b4930e57
--- /dev/null
+++ b/doc/fr/references.shtml
@@ -0,0 +1,42 @@
+<H1>References</H1>
+
+<H2>CUPS Documentation</H2>
+
+<P>The following CUPS documentation is referenced by this document:
+
+<UL>
+ <LI>CUPS-CMP-1.1: CUPS Configuration Management Plan
+ <LI>CUPS-IDD-1.1: CUPS System Interface Design Description
+ <LI>CUPS-IPP-1.1: CUPS Implementation of IPP
+ <LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual
+ <LI>CUPS-SDD-1.1: CUPS Software Design Description
+ <LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual
+ <LI>CUPS-SSR-1.1: CUPS Software Security Report
+ <LI>CUPS-STP-1.1: CUPS Software Test Plan
+ <LI>CUPS-SUM-1.1.x: CUPS Software Users Manual
+ <LI>CUPS-SVD-1.1: CUPS Software Version Description
+</UL>
+
+<H2>Other Documents</H2>
+
+<P>The following non-CUPS documents are referenced by this document:
+
+<UL>
+ <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">Adobe
+ PostScript Printer Description File Format Specification,
+ Version 4.3.</A>
+ <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">Adobe
+ PostScript Language Reference, Third Edition.</A>
+ <LI>IPP: Job and Printer Set Operations
+ <LI>IPP/1.1: Encoding and Transport
+ <LI>IPP/1.1: Implementers Guide
+ <LI>IPP/1.1: Model and Semantics
+ <LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer Daemon Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals for an Internet Printing Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale for the Structure of the Model and Protocol</A>
+ for the Internet Printing Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping between LPD and IPP Protocols</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP Authentication: Basic and Digest Access</A>
+ Authentication
+</UL>
diff --git a/doc/fr/sam.html b/doc/fr/sam.html
new file mode 100644
index 000000000..8c8ba7eb1
--- /dev/null
+++ b/doc/fr/sam.html
@@ -0,0 +1,5233 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS - Manuel de l'administrateur CUPS</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2003, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SAM-1.1.14">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS - Manuel de l'administrateur CUPS</H1></A><BR>
+CUPS-SAM-1.1.14<BR>
+Easy Software Products<BR>
+Copyright 1997-2003, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table des mati&egrave;res</A></H1>
+<BR>
+<BR><B><A HREF="#1">Pr&eacute;face</A></B>
+<UL>
+<LI><A HREF="#1_1">Aper&ccedil;u du syst&egrave;me</A></LI>
+<LI><A HREF="#1_2">Aper&ccedil;u du document</A></LI>
+<LI><A HREF="#1_3">Conventions d'&eacute;criture</A></LI>
+<LI><A HREF="#1_4">Abr&eacute;viations</A></LI>
+<LI><A HREF="#1_5">Autres r&eacute;f&eacute;rences</A></LI>
+</UL>
+<B><A HREF="#OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A></B>
+<UL>
+<LI><A HREF="#2_1">Le probl&egrave;me d'impression</A></LI>
+<LI><A HREF="#2_2">La technologie</A></LI>
+<LI><A HREF="#2_3">Travaux d'impression</A></LI>
+<LI><A HREF="#2_4">Classes d'imprimantes</A></LI>
+<LI><A HREF="#2_5">Filtres</A></LI>
+<LI><A HREF="#2_6">Programmes d'arri&egrave;re-plan (Backends)</A></LI>
+<LI><A HREF="#2_7">Pilotes d'imprimantes</A></LI>
+<LI><A HREF="#2_8">R&eacute;seau</A></LI>
+</UL>
+<B><A HREF="#BUILDING_INSTALLING">2 - Construire et installer CUPS</A></B>
+<UL>
+<LI><A HREF="#3_1">Installer &agrave; partir d'une distribution du code source</A>
+</LI>
+<UL>
+<LI><A HREF="#REQUIREMENTS">Conditions n&eacute;cessaires</A></LI>
+<LI><A HREF="#COMPILING">Compiler CUPS</A></LI>
+<LI><A HREF="#INSTALLING">Installer le logiciel</A></LI>
+<LI><A HREF="#RUNNING">Ex&eacute;cuter le logiciel</A></LI>
+</UL>
+<LI><A HREF="#BINARY">Installer une distribution binaire du logiciel</A></LI>
+<UL>
+<LI><A HREF="#PORTABLE-BINARY">Installer une distribution portable</A></LI>
+<LI><A HREF="#RPM-BINARY">Installer une distribution de type RPM</A></LI>
+<LI><A HREF="#DPKG-BINARY">Installer une distribution de type DEBIAN</A></LI>
+</UL>
+</UL>
+<B><A HREF="#MANAGING_PRINTERS">3 - Administration les imprimantes</A></B>
+<UL>
+<LI><A HREF="#4_1">Les bases</A></LI>
+<LI><A HREF="#4_2">Ajouter votre premi&egrave;re imprimante</A></LI>
+<UL>
+<LI><A HREF="#4_2_1">Ajouter votre premi&egrave;re imprimante depuis la ligne
+ de commande</A></LI>
+<LI><A HREF="#ADD_WEB">Ajouter votre premi&egrave;re imprimante depuis
+ l'interface &quot;web&quot;</A></LI>
+</UL>
+<LI><A HREF="#4_3">Administrer les imprimantes depuis la ligne de
+ commande</A></LI>
+<UL>
+<LI><A HREF="#4_3_1">Ajouter et modifier des imprimantes</A></LI>
+<LI><A HREF="#4_3_2">Supprimer des imprimantes</A></LI>
+<LI><A HREF="#4_3_3">Choisir l'imprimante implicite</A></LI>
+<LI><A HREF="#4_3_4">D&eacute;marrer et arr&ecirc;ter des imprimantes</A></LI>
+<LI><A HREF="#4_3_5">Accepter et rejeter les travaux d'impression</A></LI>
+</UL>
+<LI><A HREF="#4_4">Administrer les imprimantes depuis l'interface &quot;web&quot;</A>
+</LI>
+</UL>
+<B><A HREF="#PRINTER_CLASSES">4 - Classes d'imprimantes</A></B>
+<UL>
+<LI><A HREF="#5_1">Les bases</A></LI>
+<LI><A HREF="#5_2">Administrer les classes d'imprimantes depuis la ligne
+ de commande</A></LI>
+<LI><A HREF="#5_3">Administrer les classes d'imprimante depuis
+ l'interface &quot;web&quot;</A></LI>
+<LI><A HREF="#5_4">Classes implicites</A></LI>
+</UL>
+<B><A HREF="#CLIENT_SETUP">5 - Configuration c&ocirc;t&eacute; client</A></B>
+<UL>
+<LI><A HREF="#6_1">Les bases</A></LI>
+<UL>
+<LI><A HREF="#CLIENT_MANUAL">Configuration manuelle des files
+ d'impression</A></LI>
+<LI><A HREF="#CLIENT_SERVER">Choix d'un serveur unique pour l'impression</A>
+</LI>
+<LI><A HREF="#CLIENT_AUTO">Configuration automatique des files
+ d'impression</A></LI>
+<LI><A HREF="#CLIENT_POLL">Choix de plusieurs serveurs pour l'impression</A>
+</LI>
+</UL>
+</UL>
+<B><A HREF="#PRINTING_MANAGEMENT">6 - Administration du syst&egrave;me
+ d'impression</A></B>
+<UL>
+<LI><A HREF="#7_1">Les bases</A></LI>
+<LI><A HREF="#RESTARTING">Red&eacute;marrer le serveur CUPS</A></LI>
+<LI><A HREF="#7_3">Changer la configuration du serveur</A></LI>
+<LI><A HREF="#7_4">Directives de configuration du serveur</A></LI>
+<UL>
+<LI><A HREF="#AccessLog">AccessLog</A></LI>
+<LI><A HREF="#Allow">Allow</A></LI>
+<LI><A HREF="#AuthClass">AuthClass</A></LI>
+<LI><A HREF="#AuthGroupName">AuthGroupName</A></LI>
+<LI><A HREF="#AuthType">AuthType</A></LI>
+<LI><A HREF="#AutoPurgeJobs">AutoPurgeJobs</A></LI>
+<LI><A HREF="#BrowseAddress">BrowseAddress</A></LI>
+<LI><A HREF="#BrowseAllow">BrowseAllow</A></LI>
+<LI><A HREF="#BrowseDeny">BrowseDeny</A></LI>
+<LI><A HREF="#BrowseOrder">BrowseOrder</A></LI>
+<LI><A HREF="#BrowseInterval">BrowseInterval</A></LI>
+<LI><A HREF="#BrowsePoll">BrowsePoll</A></LI>
+<LI><A HREF="#BrowsePort">BrowsePort</A></LI>
+<LI><A HREF="#BrowseProtocols">BrowseProtocols</A></LI>
+<LI><A HREF="#BrowseRelay">BrowseRelay</A></LI>
+<LI><A HREF="#BrowseShortNames">BrowseShortNames</A></LI>
+<LI><A HREF="#BrowseTimeout">BrowseTimeout</A></LI>
+<LI><A HREF="#Browsing">Browsing</A></LI>
+<LI><A HREF="#Classification">Classification</A></LI>
+<LI><A HREF="#ClassifyOverride">ClassifyOverride</A></LI>
+<LI><A HREF="#DataDir">DataDir</A></LI>
+<LI><A HREF="#DefaultCharset">DefaultCharset</A></LI>
+<LI><A HREF="#DefaultLanguage">DefaultLanguage</A></LI>
+<LI><A HREF="#Deny">Deny</A></LI>
+<LI><A HREF="#DocumentRoot">DocumentRoot</A></LI>
+<LI><A HREF="#Encryption">Encryption</A></LI>
+<LI><A HREF="#ErrorLog">ErrorLog</A></LI>
+<LI><A HREF="#FilterLimit">FilterLimit</A></LI>
+<LI><A HREF="#FontPath">FontPath</A></LI>
+<LI><A HREF="#Group">Group</A></LI>
+<LI><A HREF="#HideImplicitMembers">HideImplicitMembers</A></LI>
+<LI><A HREF="#HostNameLookups">HostNameLookups</A></LI>
+<LI><A HREF="#ImplicitClasses">ImplicitClasses</A></LI>
+<LI><A HREF="#ImplicitAnyClasses">ImplicitAnyClasses</A></LI>
+<LI><A HREF="#Include">Include</A></LI>
+<LI><A HREF="#KeepAlive">KeepAlive</A></LI>
+<LI><A HREF="#KeepAliveTimeout">KeepAliveTimeout</A></LI>
+<LI><A HREF="#Limit">Limit</A></LI>
+<LI><A HREF="#LimitExcept">LimitExcept</A></LI>
+<LI><A HREF="#LimitRequestBody">LimitRequestBody</A></LI>
+<LI><A HREF="#Listen">Listen</A></LI>
+<LI><A HREF="#Location">Location</A></LI>
+<LI><A HREF="#LogLevel">LogLevel</A></LI>
+<LI><A HREF="#MaxClients">MaxClients</A></LI>
+<LI><A HREF="#MaxJobs">MaxJobs</A></LI>
+<LI><A HREF="#MaxJobsPerPrinter">MaxJobsPerPrinter</A></LI>
+<LI><A HREF="#MaxJobsPerUser">MaxJobsPerUser</A></LI>
+<LI><A HREF="#MaxLogSize">MaxLogSize</A></LI>
+<LI><A HREF="#MaxRequestSize">MaxRequestSize</A></LI>
+<LI><A HREF="#Order">Order</A></LI>
+<LI><A HREF="#PageLog">PageLog</A></LI>
+<LI><A HREF="#Port">Port</A></LI>
+<LI><A HREF="#PreserveJobHistory">PreserveJobHistory</A></LI>
+<LI><A HREF="#PreserveJobFiles">PreserveJobFiles</A></LI>
+<LI><A HREF="#Printcap">Printcap</A></LI>
+<LI><A HREF="#PrintcapFormat">PrintcapFormat</A></LI>
+<LI><A HREF="#PrintcapGUI">PrintcapGUI</A></LI>
+<LI><A HREF="#RemoteRoot">RemoteRoot</A></LI>
+<LI><A HREF="#RequestRoot">RequestRoot</A></LI>
+<LI><A HREF="#Require">Require</A></LI>
+<LI><A HREF="#RIPCache">RIPCache</A></LI>
+<LI><A HREF="#RunAsUser">RunAsUser</A></LI>
+<LI><A HREF="#Satisfy">Satisfy</A></LI>
+<LI><A HREF="#ServerAdmin">ServerAdmin</A></LI>
+<LI><A HREF="#ServerBin">ServerBin</A></LI>
+<LI><A HREF="#ServerCertificate">ServerCertificate</A></LI>
+<LI><A HREF="#ServerKey">ServerKey</A></LI>
+<LI><A HREF="#ServerName">ServerName</A></LI>
+<LI><A HREF="#ServerRoot">ServerRoot</A></LI>
+<LI><A HREF="#SSLListen">SSLListen</A></LI>
+<LI><A HREF="#SSLPort">SSLPort</A></LI>
+<LI><A HREF="#SystemGroup">SystemGroup</A></LI>
+<LI><A HREF="#TempDir">TempDir</A></LI>
+<LI><A HREF="#Timeout">Timeout</A></LI>
+<LI><A HREF="#User">User</A></LI>
+</UL>
+<LI><A HREF="#PRINTING_SECURITY">S&eacute;curit&eacute; du syst&egrave;me d'impression</A></LI>
+<UL>
+<LI><A HREF="#CERTIFICATES">Authentification bas&eacute;e sur les certificats</A>
+</LI>
+<LI><A HREF="#7_5_2">Utilisation de l'authentification &quot;Basic&quot;</A></LI>
+<LI><A HREF="#7_5_3">Utilisation de l'authentification &quot;Digest&quot;</A></LI>
+<LI><A HREF="#7_5_4">Authentifications &quot;System&quot; et &quot;Group&quot;</A></LI>
+</UL>
+<LI><A HREF="#PRINTER_ACCOUNTING">Suivi/facturation de travaux et
+ d'imprimantes</A></LI>
+<UL>
+<LI><A HREF="#7_6_1">Le fichier access_log</A></LI>
+<LI><A HREF="#7_6_2">Le fichier error_log</A></LI>
+<LI><A HREF="#7_6_3">Le fichier page_log</A></LI>
+</UL>
+<LI><A HREF="#FILE_TYPING_FILTERING">Filtrage et d&eacute;termination des types
+ de fichiers</A></LI>
+<UL>
+<LI><A HREF="#7_7_1">Le fichier mime.types</A></LI>
+<LI><A HREF="#7_7_2">Le fichier mime.convs</A></LI>
+<LI><A HREF="#7_7_3">Ajouter des filtres et des types de fichiers</A></LI>
+<LI><A HREF="#7_7_4">Pilotes d'imprimantes et fichiers PPD</A></LI>
+<LI><A HREF="#7_7_5">Ecrire vos propres filtres ou pilotes d'imprimantes</A>
+</LI>
+</UL>
+</UL>
+<B><A HREF="#PRINTING_OTHER">7 - Imprimer depuis et vers d'autres
+ syst&egrave;mes</A></B>
+<UL>
+<LI><A HREF="#8_1">Les bases</A></LI>
+<LI><A HREF="#8_2">Imprimer depuis des clients LPD</A></LI>
+<LI><A HREF="#8_3">Imprimer vers des serveurs LPD</A></LI>
+<LI><A HREF="#8_4">Imprimer depuis des client Mac OS</A></LI>
+<UL>
+<LI><A HREF="#8_4_1">Columbia Appletalk Package (CAP)</A></LI>
+<LI><A HREF="#8_4_2">XINET KA/Spool</A></LI>
+<LI><A HREF="#8_4_3">NetATalk</A></LI>
+</UL>
+<LI><A HREF="#8_5">Imprimer vers des serveurs d'impression Mac OS</A></LI>
+<LI><A HREF="#8_6">Imprimer depuis des clients Windows</A></LI>
+<UL>
+<LI><A HREF="#8_6_1">Exporter les pilotes d'imprimantes</A></LI>
+</UL>
+<LI><A HREF="#8_7">Imprimer vers des serveurs d'impression Windows</A></LI>
+</UL>
+<B><A HREF="#LICENSE">A - Licence d'utilisation du logiciel</A></B>
+<UL>
+<LI><A HREF="#9_1">Common UNIX Printing System License Agreement</A></LI>
+<UL>
+<LI><A HREF="#9_1_1">Introduction</A></LI>
+<LI><A HREF="#9_1_2">Trademarks</A></LI>
+<LI><A HREF="#9_1_3">Binary Distribution Rights</A></LI>
+<LI><A HREF="#9_1_4">Support</A></LI>
+</UL>
+<LI><A HREF="#9_2">GNU GENERAL PUBLIC LICENSE</A></LI>
+<UL>
+<LI><A HREF="#9_2_1">Preamble</A></LI>
+</UL>
+<LI><A HREF="#9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></LI>
+<UL>
+<LI><A HREF="#9_3_1">Preamble</A></LI>
+</UL>
+</UL>
+<B><A HREF="#COMMON_NETWORK">B - R&eacute;glages r&eacute;seau courants</A></B>
+<UL>
+<LI><A HREF="#10_1">Configurer une interface r&eacute;seau</A></LI>
+<UL>
+<LI><A HREF="#10_1_1">Configuration de l'adresse IP utilisant ARP</A></LI>
+<LI><A HREF="#10_1_2">Configuration de l'adresse IP utilisant RARP</A></LI>
+<LI><A HREF="#10_1_3">Configuration de l'adresse IP utilisant BOOTP</A></LI>
+</UL>
+<LI><A HREF="#10_2">V&eacute;rifier la connexion de l'imprimante</A></LI>
+<LI><A HREF="#10_3">R&eacute;glages d'interfaces r&eacute;seau et serveur d'impression
+ courants</A></LI>
+<LI><A HREF="#AXIS">Configuration de serveurs d'impression Axis</A></LI>
+<LI><A HREF="#LINKSYS">Configuration de serveurs d'impression Linksys</A>
+</LI>
+</UL>
+<B><A HREF="#PRINTER_DRIVERS">C - Pilotes d'imprimantes</A></B>
+<UL>
+<LI><A HREF="#11_1">Pilotes d'imprimantes</A></LI>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A></LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A></LI>
+</UL>
+<B><A HREF="#FILES">D - Liste des fichiers</A></B>
+<BR>
+<BR><B><A HREF="#FAQ">E - R&eacute;soudre les probl&egrave;mes courants</A></B>
+<UL>
+<LI><A HREF="#13_1">Mes applications ne voient pas les imprimantes
+ disponibles</A></LI>
+<LI><A HREF="#13_2">CUPS ne reconna&icirc;t pas mon nom d'utilisateur et mon
+ mot de passe!</A></LI>
+<LI><A HREF="#ALLOW_REMOTE">Je ne peux pas effectuer de t&acirc;ches
+ d'administration depuis un poste distant!</A></LI>
+<LI><A HREF="#13_4">Je ne peux pas effectuer de t&acirc;ches d'administration
+ depuis mon navigateur &quot;web&quot;!</A></LI>
+<LI><A HREF="#13_5">Messages &quot;Connection Refused&quot;</A></LI>
+<LI><A HREF="#13_6">Message &quot;Write Error&quot;</A></LI>
+</UL>
+<HR NOSHADE>
+<H1 ALIGN="RIGHT"><A NAME="1">Pr&eacute;face</A></H1>
+<P>Ce manuel de l'administrateur fournit les informations
+ d'administration pour le syst&egrave;me d'impression CUPS<SUP>TM</SUP> (Common
+ UNIX Printing System<SUP>TM</SUP>) version 1.1.14.</P>
+<P></P>
+<HR color="#000000" size="1px" width="50%"><I><B>Note du traducteur :</B>
+ Amies lectrices, amis lecteurs, j'ai fait le choix de<B> ne pas
+ traduire</B> l'expression anglaise<B> &quot;default&quot;</B> par la version
+ fran&ccedil;aise habituellent utilis&eacute;e<B> &quot;par d&eacute;faut&quot;</B> que l'on doit,
+ entre autres, &agrave; la documentation d'un c&eacute;l&egrave;bre syst&egrave;me d'exploitation
+ &quot;ouvert &agrave; tous vents&quot;.
+<BR>
+<BR> En effet, l'expression &quot;par d&eacute;faut&quot; est normalement utilis&eacute;e en
+ math&eacute;matiques (arrondi &quot;par d&eacute;faut&quot; ou &quot;par exc&egrave;s&quot;, personnellement je
+ cherche encore mon &quot;imprimante par exc&egrave;s&quot; !) mais elle est abusivement
+ employ&eacute;e en informatique pour signifier &quot;donn&eacute;e/comportement qui
+ s'applique si l'on n'en pr&eacute;cise pas<B> explicitement</B> la
+ valeur/nature/teneur&quot;.
+<BR>
+<BR> Or la langue fran&ccedil;aise poss&egrave;de justement un mot pout exprimer ce
+ concept : &quot;implicite&quot; (Larousse 1998 : &quot;Qui est contenu dans une
+ proposition sans &ecirc;tre exprim&eacute; en termes pr&eacute;cis formels; qui est la
+ cons&eacute;quence n&eacute;cessaire.&quot;). Dans la mesure du possible, j'utiliserai cet
+ adjectif sauf dans les cas o&ugrave; son emploi n'est pas suffisamment<B>
+ explicite</B> (sic !). Je lui pr&eacute;f&egrave;rerai alors l'expression &quot;... de
+ base ...&quot; ou l'adjectif &quot;standard&quot;.
+<BR>
+<BR> Ce choix est totalement personnel et le fait que j'ai fait l'effort
+ (non n&eacute;gligeable) de traduire ces lignes pour vos yeux d&eacute;licats suffit
+ &agrave; le justifier! Si, par malheur, ma prose vous est insupportable, je ne
+ vous emp&ecirc;che aucunement de vous reporter &agrave; la version originale o&ugrave; vous
+ retrouverez &quot;default&quot; entour&eacute; de tout le reste... en anglais, bien s&ucirc;r.
+ Enfin, si vous avez une meilleure traduction, je suis preneur !
+<BR>
+<BR> Malgr&eacute; les tr&egrave;s nombreuses relectures et corrections, certaines
+ fautes de frappe, d'orthographe ou de grammaire ont pu &eacute;chapper &agrave; ma
+ vigilance (ou &agrave; celles de mes relecteurs/correcteurs). Merci de me les
+ signaler afin de contribuer &agrave; l'am&eacute;lioration constante de la qualit&eacute; du
+ pr&eacute;sent manuel.
+<BR>
+<BR> Bonne lecture !</I>
+<HR color="#000000" size="1px" width="50%">
+<H2><A NAME="1_1">Aper&ccedil;u du syst&egrave;me</A></H2>
+<P>CUPS fournit une couche d'impression portable pour les syst&egrave;mes
+ d'exploitation de type UNIX&reg;. Il a &eacute;t&eacute; d&eacute;velopp&eacute; par <A HREF="http://www.easysw.com">
+Easy Software Products</A> pour promouvoir une solution d'impression
+ standard pour tous les vendeurs et utilisateurs d'UNIX. CUPS fournit
+ des interfaces en ligne de commande de type System V et Berkeley.</P>
+<P>CUPS utilise le protocol IPP (Internet Printing Protocol) comme base
+ de l'administration des travaux et files d'impression. Les protocoles
+ LPD (&quot;Line Printer Daemon&quot;), SMB (&quot;Server Message Block&quot;), et AppSocket
+ (JetDirect) sont &eacute;galement pris en charge avec des fontionnalit&eacute;s
+ r&eacute;duites. CUPS ajoute l'exploration r&eacute;seau des imprimantes (&quot;network
+ printer browsing&quot;) et des options d'impression bas&eacute;es sur PPD
+ (&quot;PostScript Printer Definition&quot;) pour prendre en charge l'impression
+ &quot;dans le monde r&eacute;el&quot; sous UNIX.</P>
+<P>CUPS inclut &eacute;galement une version adapt&eacute;e de GNU/Ghostscript
+ (actuellement bas&eacute;e sur la version 5.50) et un module de rendu (RIP -
+ Raster Image Processor) pour fichier image qui sont utilis&eacute;s pour
+ prendre en charge les imprimantes non-PostScript. Des pilotes d'exemple
+ (incluant ces filtres) pour imprimantes HP et EPSON sont &eacute;galement
+ inclus.</P>
+
+<!-- NEED 3in -->
+<H2><A NAME="1_2">Aper&ccedil;u du document</A></H2>
+<P> Ce manuel de l'administrateur est organis&eacute; de la mani&egrave;re suivante:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A></LI>
+<LI><A HREF="#BUILDING_INSTALLING">2 - Construire et installer CUPS</A></LI>
+<LI><A HREF="#MANAGING_PRINTERS">3 - Administration des imprimantes</A></LI>
+<LI><A HREF="#PRINTER_CLASSES">4 - Classes d'imprimantes</A></LI>
+<LI><A HREF="#CLIENT_SETUP">5 - Configuration c&ocirc;t&eacute; client</A></LI>
+<LI><A HREF="#PRINTING_MANAGEMENT">6 - Administration du syst&egrave;me
+ d'impression</A></LI>
+<LI><A HREF="#PRINTING_OTHER">7 - Imprimer depuis et vers d'autres
+ syst&egrave;me</A></LI>
+<LI><A HREF="#LICENSE">A - Licence d'utilisation du logiciel (NdT : en
+ anglais)</A></LI>
+<LI><A HREF="#COMMON_NETWORK">B - R&eacute;glages r&eacute;seau courants</A></LI>
+<LI><A HREF="#PRINTER_DRIVERS">C - Pilotes d'imprimantes</A></LI>
+<LI><A HREF="#FILES">D - Liste des fichiers</A></LI>
+<LI><A HREF="#FAQ">E - R&eacute;soudre les probl&egrave;mes courants</A></LI>
+</UL>
+<H2><A NAME="1_3">Conventions d'&eacute;criture</A></H2>
+<P>
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abr&eacute;viations</A></H2>
+ Les abr&eacute;viations suivantes sont utilis&eacute;es au cours de ce manuel:
+<UL>
+<DL>
+<DT>ko</DT>
+<DD>Kilo-octets, ou 1024 octets
+<BR> &nbsp;</DD>
+<DT>Mo</DT>
+<DD>M&eacute;ga-octets, ou 1048576 octets
+<BR> &nbsp;</DD>
+<DT>Go</DT>
+<DD>Giga-octets, ou 1073741824 octets
+<BR> &nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Autres r&eacute;f&eacute;rences</A></H2>
+<UL>
+<DL>
+<DT>CUPS - Manuel du programmeur (en anglais)</DT>
+<DD>Un guide du programmeur pour interagir avec CUPS ou y ajouter des
+ extensions.
+<BR> &nbsp;</DD>
+<DT>CUPS - Manuel de l'utilisateur</DT>
+<DD>Un guide d'utilisation pour l'utilisateur final du logiciel CUPS.
+<BR> &nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A>
+</H1>
+<P>Ce chapitre fournit un aper&ccedil;u de la mani&egrave;re dont CUPS fonctionne.</P>
+<H2><A NAME="2_1">Le probl&egrave;me d'impression</A></H2>
+<P>Depuis des ann&eacute;es<I> le probl&egrave;me d'impression</I> a empoisonn&eacute; le
+ monde UNIX. Contrairement &agrave; Microsoft&reg; Windows&reg; ou Mac OS, UNIX n'a pas
+ d'interface standard ou de syst&egrave;me en place pour prendre en charge les
+ imprimantes. Parmi les solutions actuellement disponibles, les syst&egrave;mes
+ Berkeley et System V sont pr&eacute;dominants.</P>
+<P> Ces syst&egrave;mes d'impressions prennent en charge les imprimantes de
+ type matriciel texte ou les imprimantes PostScript (texte et
+ graphique), et avec quelques ajustements il peuvent prendre en charge
+ un grand nombre d'imprimantes et de formats de fichiers. Cependant,
+ puisque chaque version de syst&egrave;me d'exploitation UNIX utilise un
+ syst&egrave;me d'impression diff&eacute;rent de celui de son voisin, il est
+ extr&ecirc;mement difficile de d&eacute;velopper des pilotes d'imprimantes pour une
+ vaste gamme d'imprimantes et de syst&egrave;mes d'exploitation. Ceci, combin&eacute;
+ au faible nombre de clients pour chaque variante d'UNIX, a pouss&eacute; les
+ fabricants d'imprimantes &agrave; abandonner la prise en charge globale de
+ tous les UNIX.</P>
+<P> CUPS est con&ccedil;u pour &eacute;liminer<I> le probl&egrave;me d'impression</I>. Un
+ syst&egrave;me d'impression commun peut &ecirc;tre utilis&eacute; par toutes les variantes
+ d'UNIX pour prendre en charge les capacit&eacute;s d'impression dont les
+ utilisateurs ont besoin. Les fabricants d'imprimantes peuvent utiliser
+ l'interface modulaire des filtres pour d&eacute;velopper un unique pilote qui
+ prend en charge une large gamme de formats de fichiers et ce, sans
+ presque aucun effort. Etant donn&eacute; que CUPS fournit une interface
+ compatible avec les commandes Berkeley et System V, les utilisateurs
+ (et les applications) peuvent tirer b&eacute;n&eacute;fice de cette nouvelle
+ technologie sans avoir &agrave; faire de changements.</P>
+<H2><A NAME="2_2">La technologie</A></H2>
+<P> CUPS est bas&eacute; sur un standard &eacute;mergeant d'Internet appel&eacute; IPP
+ (Internet Printing Protocol). IPP a &eacute;t&eacute; adopt&eacute; par des douzaines de
+ fabricants d'imprimantes et de serveurs d'impression et est pris en
+ charge par Microsoft Windows 2000.</P>
+<P> IPP d&eacute;finit un protocole standard pour imprimer ainsi qu'administrer
+ les travaux d'impression et les options des imprimantes telles que la
+ taille du support d'impression, la r&eacute;solution, etc. Comme tout
+ protocole de la pile TCP/IP, IPP peut &ecirc;tre utilis&eacute; localement ou &agrave;
+ travers Internet pour atteindre des imprimantes &eacute;loign&eacute;es de centaines
+ ou de milliers de kilom&egrave;tres. Contrairement &agrave; d'autres protocoles de la
+ pile TCP/IP, IPP prend en charge le contr&ocirc;le d'acc&egrave;s,
+ l'authentification et l'encryptage, ce qui fait de lui une solution
+ d'impression bien plus efficace et s&eacute;curis&eacute;e que ses anc&ecirc;tres.</P>
+<P> IPP est une surcouche ajout&eacute;e au-dessus du protocole HTTP (HyperText
+ Transport Protocol) qui est &agrave; la base des serveurs &quot;web&quot; sur
+ l'Internet. Ceci permet aux utilisateurs de lire la documentation,
+ v&eacute;rifier les informations sur l'&eacute;tat des imprimantes ou du serveur,
+ administrer les imprimantes, les classes d'imprimantes et les travaux
+ d'impression en utilisant leur navigateur &quot;web&quot;.</P>
+<P> CUPS fournit un syst&egrave;me d'impression complet bas&eacute; sur IPP/1.1
+ prenant en charge l'authentification &quot;Basic&quot;, &quot;Digest&quot; et par
+ certificats locaux ainsi qu'un contr&ocirc;le d'acc&egrave;s bas&eacute; sur l'utilisateur,
+ le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une
+ future version de CUPS.</P>
+<H2><A NAME="2_3">Travaux d'impression</A></H2>
+<P> Tout fichier ou groupe de fichiers soumis &agrave; l'impression est appel&eacute;
+ un<I> travail d'impression</I>. Les travaux d'impression sont
+ identifi&eacute;s par un nombre unique en commen&ccedil;ant &agrave; 1 et sont affect&eacute;s &agrave;
+ une destination particuli&egrave;re, g&eacute;n&eacute;ralement une imprimante. Les travaux
+ d'impression peuvent &eacute;galement inclure des options associ&eacute;es telles que
+ la taille du support d'impression, le nombre de copies et la priorit&eacute;
+ dans la file d'impression.</P>
+<H2><A NAME="2_4">Classes d'imprimantes</A></H2>
+<P> CUPS prend en charge des collections d'imprimantes connues sous le
+ nom de<I> classes</I>. Les travaux d'impression transmis &agrave; une classe
+ d'imprimantes sont envoy&eacute;s &agrave; la premi&egrave;re imprimante disponible dans la
+ classe.</P>
+<H2><A NAME="2_5">Filtres</A></H2>
+<P>Les filtres permettent &agrave; un utilisateur ou une application d'imprimer
+ de nombreux types de documents sans effort suppl&eacute;mentaire. Les travaux
+ d'impressions envoy&eacute;s au serveur CUPS sont filtr&eacute;s avant d'&ecirc;tre envoy&eacute;s
+ &agrave; l'imprimante. Certains filtres convertissent les fichiers de travaux
+ d'impression dans diff&eacute;rents formats que l'imprimante peut comprendre.
+ D'autres ne font que des s&eacute;lections de page et des tris.</P>
+<P>CUPS fournit des filtres pour imprimer de nombreux types de fichiers
+ image, des fichier HP-GL/2, fichiers PDF et texte. CUPS fournit
+ &eacute;galement des filtres PostScript et RIP (Raster Image Processor) qui
+ convertissent les fichiers PostScript ou image en format &quot;bitmap&quot; qui
+ peut &ecirc;tre envoy&eacute; &agrave; une imprimante de type &quot;matriciel&quot; (NdT : il s'agit
+ ici, des imprimantes dont l'impression est g&eacute;n&eacute;r&eacute;e au moyen d'une
+ grille de points comme l'&eacute;taient les v&eacute;n&eacute;rables imprimantes &agrave; aiguilles
+ de notre enfance, mais pas seulement elles puisque les imprimantes &agrave;
+ jet d'encre actuelles sont &eacute;galement de type matriciel... par
+ opposition aux imprimantes laser dont la m&eacute;thode de g&eacute;n&eacute;ration
+ d'impression est diff&eacute;rente.)</P>
+<H2><A NAME="2_6">Programmes d'arri&egrave;re-plan (Backends)</A></H2>
+<P>Les programmes d'arri&egrave;re-plan effectuent le travail le plus important
+ : ils envoient les donn&eacute;es d'impression &agrave; l'imprimante.</P>
+<P>CUPS fournit des programmes d'arri&egrave;re-plan pour imprimer via des
+ ports de type parall&egrave;le, s&eacute;rie, USB et &agrave; travers un r&eacute;seau au moyen des
+ protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des
+ programmes d'arri&egrave;re-plan additionnels sont disponibles sous forme de
+ paquetage de service r&eacute;seau comme le programme d'arri&egrave;re_plan SMB
+ inclus dans le c&eacute;l&egrave;bre logiciel SAMBA.</P>
+<P>Les programmes d'arri&egrave;re-plan sont &eacute;galement utilis&eacute;s pour d&eacute;terminer
+ les p&eacute;riph&eacute;riques disponibles. Au d&eacute;marrage, chaque programme
+ d'arri&egrave;re-plan est interrog&eacute; afin de d&eacute;terminer la liste des
+ p&eacute;riph&eacute;riques qu'il prend en charge, ainsi que toute information
+ disponible. Cela permet au programme d'arri&egrave;re-plan de gestion du port
+ parall&egrave;re d'indiquer &agrave; CUPS qu'une imprimante EPSON Stylus Color 600
+ est branch&eacute;e sur le port parall&egrave;le 1, par exemple.</P>
+<H2><A NAME="2_7">Pilotes d'imprimantes</A></H2>
+<P>Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs
+ filtres sp&eacute;cifiques &agrave; une imprimante. CUPS inclut des pilotes
+ d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet
+ Hewlett-Packard et les imprimantes EPSON jet d'encre couleur Stylus
+ Color, Stylus Photo et les mod&egrave;les 9 et 24 aiguilles matricielles. Bien
+ que ces pilotes ne produisent pas des impressions de qualit&eacute; optimale
+ pour les diff&eacute;rents mod&egrave;les d'imprimantes, ils fournissent une
+ impression de base et d&eacute;montrent comment vous pouvez &eacute;crire vos propres
+ pilotes d'imprimantes et les incorporer dans CUPS.</P>
+<H2><A NAME="2_8">R&eacute;seau</A></H2>
+<P>Les imprimantes et classes d'imprimantes sur le syst&egrave;me local sont
+ automatiquement partag&eacute;es avec les autres syst&egrave;mes sur le r&eacute;seau. Cela
+ vous permet de configurer un syst&egrave;me h&ocirc;te pour tous les autres. Les
+ utilisateurs pourront s&eacute;lectionner une imprimante locale par son nom ou
+ une imprimante &agrave; distance en utilisant la syntaxe
+ &quot;nom_imprimante@serveur&quot;.</P>
+<P>CUPS fournit &eacute;galement des<I> classes d'imprimantes implicites</I>
+ (NdT : le terme &quot;implicite&quot; est ici la traduction lit&eacute;rale du m&ecirc;me mot
+ anglais &quot;implicit&quot; et non celle de l'expression &quot;default&quot;. cf. ma
+ remarque dans la pr&eacute;face du pr&eacute;sent manuel. De toute fa&ccedil;on, CUPS ne
+ pr&eacute;voit pas de &quot;default class&quot; c'est-&agrave;-dire de &quot;classe de base&quot;, donc
+ aucune ambigu&iuml;t&eacute; possible ici.), qui sont des collections d'imprimantes
+ ou de classes d'imprimantes qui portent le m&ecirc;me nom. Cela vous permet
+ de configurer de multiples serveurs pointant vers la m&ecirc;me imprimante
+ r&eacute;seau physique, par exemple, de sorte que vous ne d&eacute;pendez pas d'un
+ seul serveur pour pouvoir imprimer. Etant donn&eacute; que cette m&eacute;thode vous
+ permet de travailler avec des classes d'imprimantes, vous pouvez
+ configurer de multiples serveurs et imprimantes sans jamais vous
+ soucier d'un simple point en panne tant que tous les autres serveurs ne
+ tombent pas en panne en m&ecirc;me temps.</P>
+<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Construire et
+ installer CUPS</A></H1>
+<P>Ce chapitre d&eacute;crit comment construire et installer CUPS. Si vous
+ installez une distribution binaire (pr&eacute;compil&eacute;e) du produit, veuillez
+ vous reporter &agrave; la section,<A HREF="#BINARY"> Installer une
+ distribution binaire</A>.</P>
+<H2><A NAME="3_1">Installer &agrave; partir d'une distribution du code source</A>
+</H2>
+<P>Cette section d&eacute;crit comment compiler et installer CUPS sur votre
+ syst&egrave;me &agrave; partir du code source du produit.</P>
+<H3><A NAME="REQUIREMENTS">Conditions n&eacute;cessaires</A></H3>
+<P>Vous aurez besoin d'un compilateur C et C++ conforme &agrave; la norme ANSI
+ pour construire CUPS sur votre syst&egrave;me. Comme son nom l'indique, CUPS
+ est con&ccedil;u pour fonctionner sur le syst&egrave;me d'exploitation UNIX,
+ cependant la plupart des librairies, des filtres et des programmes
+ d'arri&egrave;re-plan devraient &eacute;galement se compiler et fonctionner sous
+ Microsoft Windows.</P>
+<P>Pour les filtres de fichiers image et PostScript, vous aurez besoin
+ des librairies JPEG, PNG, TIFF et ZLIB. CUPS se construira sans elles
+ mais avec des fonctionnalit&eacute;s singuli&egrave;rement r&eacute;duites. Easy Software
+ Products maintient un miroir des versions actuelles de ces librairies &agrave;
+ l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="ftp://ftp.easysw.com/pub/libraries">ftp://ftp.easysw.com/pub/libraries</A>
+</PRE>
+</UL>
+<P>Si vous fa&icirc;tes des changements dans les pages de manuel vous aurez
+ besoin de GNU groff ou d'un autre paquetage compatible nroff. GNU groff
+ est disponible &agrave; l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="ftp://ftp.gnu.org/pub/groff">ftp://ftp.gnu.org/pub/groff</A>
+</PRE>
+</UL>
+<P>La documentation est format&eacute;e en utilisant le programme HTMLDOC. Si
+ vous voulez faire des changements, vous pouvez obtenir le programme
+ HTMLDOC &agrave; l'adresse:</P>
+<P></P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
+</PRE>
+</UL>
+<P>Enfin, vous aurez besoin d'un programme <CODE>make</CODE> qui
+ comprend les directives <CODE>include</CODE> - les d&eacute;veloppeurs
+ FreeBSD, NetBSD et OpenBSD devraient utiliser le programme <CODE>gmake</CODE>
+.</P>
+<H3><A NAME="COMPILING">Compiler CUPS</A></H3>
+<P>CUPS utilise GNU autoconf pour configurer les &quot;makefiles&quot; et le code
+ source pour votre syst&egrave;me. Tapez simplement la commande suivante pour
+ configurer CUPS pour votre syst&egrave;me:</P>
+<UL>
+<PRE>
+<B>./configure ENTREE</B>
+</PRE>
+</UL>
+<P>L'installation standard installera CUPS dans les r&eacute;pertoires<VAR>
+ /etc</VAR>,<VAR> /usr</VAR>, et<VAR> /var</VAR> de votre syst&egrave;me, ce
+ qui &eacute;crasera toute commande d'impression existant d&eacute;j&agrave; dans votre
+ syst&egrave;me. Utilisez l'option <CODE>--prefix</CODE> pour installer CUPS &agrave;
+ un autre emplacement:</P>
+<UL>
+<PRE>
+<B>./configure --prefix=/autre/r&eacute;pertoire ENTREE</B>
+</PRE>
+</UL>
+<P>Si les librairies PNG, JPEG, TIFF, et ZLIB ne sont pas install&eacute;es &agrave;
+ un emplacement habituel du syst&egrave;me (g&eacute;n&eacute;ralement il s'agit de<VAR>
+ /usr/include</VAR> et<VAR> /usr/lib</VAR>) vous devrez d&eacute;finir les
+ variables d'environnement <CODE>CFLAGS</CODE>, <CODE>CXXFLAGS</CODE>,
+ et <CODE>LDFLAGS</CODE> avant d'ex&eacute;cuter la commande configure:</P>
+<UL>
+<PRE>
+<B>setenv CFLAGS &quot;-I/some/directory&quot; ENTREE</B>
+<B>setenv CXXFLAGS &quot;-I/some/directory&quot; ENTREE</B>
+<B>setenv LDFLAGS &quot;-L/some/directory&quot; ENTREE</B>
+<B>setenv DSOFLAGS &quot;-L/some/directory&quot; ENTREE</B>
+<B>./configure ... ENTREE</B>
+</PRE>
+</UL>
+<P>ou:</P>
+<UL>
+<PRE>
+<B>CFLAGS=&quot;-I/some/directory&quot;; export CFLAGS ENTREE</B>
+<B>CXXFLAGS=&quot;-I/some/directory&quot;; export CXXFLAGS ENTREE</B>
+<B>LDFLAGS=&quot;-L/some/directory&quot;; export LDFLAGS ENTREE</B>
+<B>DSOFLAGS=&quot;-L/some/directory&quot;; export DSOFLAGS ENTREE</B>
+<B>./configure ... ENTREE</B>
+</PRE>
+</UL>
+<P>Pour activer le support de l'encryptage, vous devrez &eacute;galement
+ activer l'option &quot;--enable-ssl&quot;:</P>
+<UL>
+<PRE>
+./configure --enable-ssl
+</PRE>
+</UL>
+<P>La prise en charge SSL et TLS n&eacute;cessite la librairie OpenSSL,
+ disponible &agrave; l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://www.openssl.org">http://www.openssl.org</A>
+</PRE>
+</UL>
+<P>Si les en-t&ecirc;tes et les librairies OpenSSL ne sont pas install&eacute;es dans
+ les r&eacute;pertoires standards, utilisez les options <CODE>
+--with-openssl-includes</CODE> et <CODE>--with-openssl-libs</CODE>:</P>
+<UL>
+<PRE>
+./configure --enable-ssl \
+ --with-openssl-includes=/foo/bar/include \
+ --with-openssl-libs=/foo/bar/lib
+</PRE>
+</UL>
+<P>Une fois que vous avez configur&eacute; toutes ces choses, tapez simplement:</P>
+<UL>
+<PRE>
+<B>make ENTER</B>
+</PRE>
+</UL>
+<P>pour compiler le logiciel.</P>
+
+<!-- NEED 4in -->
+<H3><A NAME="INSTALLING">Installer le logiciel</A></H3>
+<P>Utilisez la cible &quot;install&quot; pour installer le logiciel:</P>
+<UL>
+<PRE>
+<B>make install ENTREE</B>
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> AVERTISSEMENT:</B>
+<P>Installer CUPS &eacute;crasera votre syst&egrave;me d'impression pr&eacute;c&eacute;dent. Si vous
+ rencontrez des difficult&eacute;s avec le logiciel CUPS et devez revenir &agrave;
+ votre ancien syst&egrave;me d'impression, vous devrez r&eacute;installer celui-ci &agrave;
+ partir de CD originaux de votre syst&egrave;me d'exploitation.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="RUNNING">Ex&eacute;cuter le logiciel</A></H3>
+<P>Une fois que vous avez install&eacute; le logiciel vous pouvez d&eacute;marrer le
+ serveur CUPS en tapant:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/cupsd ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<H2><A NAME="BINARY">Installer une distribution binaire du logiciel</A></H2>
+<P>CUPS est fourni dans une vari&eacute;t&eacute; de formats binaires. Easy Software
+ Products fournit des binaires sous forme d'archives au format TAR avec
+ des scripts d'installation et de d&eacute;sinstallation (distributiond dites
+ &quot;portables&quot;), sous forme de format RPM et DPKG pour les distributions
+ RedHat et Debian. Les distributions portables sont disponibles pour
+ toutes les plateformes tandis que les distributions RPM et DPKG ne le
+ sont que pour GNU/Linux</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> AVERTISSEMENT:</B>
+<P>Installer CUPS &eacute;crasera votre syst&egrave;me d'impression pr&eacute;c&eacute;dent. Si vous
+ rencontrez des difficult&eacute;s avec le logiciel CUPS et devez revenir &agrave;
+ votre ancien syst&egrave;me d'impression, vous devrez r&eacute;installer celui-ci &agrave;
+ partir de CD originaux de votre syst&egrave;me d'exploitation.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="PORTABLE-BINARY">Installer une distribution portable</A></H3>
+<P>Pour installer le logiciel CUPS &agrave; partir d'une distribution portable
+ vous devrez ouvrir une session en tant qu'utilisateur root; utiliser la
+ commande <CODE>su</CODE> est suffisant. Une fois que vous &ecirc;tes
+ utilisateur root, lancer le script d'installation avec la commande:</P>
+<UL>
+<PRE>
+<B>./cups.install ENTREE</B>
+</PRE>
+</UL>
+<P>Apr&egrave;s vous avoir pos&eacute; quelques questions de type oui/non, le logiciel
+ CUPS va s'installer et l'ordonnanceur sera d&eacute;marr&eacute; automatiquement.</P>
+
+<!-- NEED 2in -->
+<H3><A NAME="RPM-BINARY">Installer une distribution de type RPM</A></H3>
+<P>Pour installer le logiciel CUPS &agrave; partir d'une distribution RPM vous
+ devez ouvrir une session en tant qu'utilisateur root; utiliser la
+ commande <CODE>su</CODE> est suffisant. Une fois connect&eacute; en tant
+ qu'utilisateur root, lancez simplement RPM au moyen de la commande:</P>
+<UL>
+<PRE>
+<B>rpm -e lpr</B>
+<B>rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTREE</B>
+</PRE>
+</UL>
+<P>Apr&egrave;s un petit d&eacute;lai, le logiciel CUPS sera install&eacute; et
+ l'ordonnanceur sera d&eacute;marr&eacute; automatiquement.</P>
+<H3><A NAME="DPKG-BINARY">Installer une distribution de type DEBIAN</A></H3>
+<P>Pour installer le logiciel CUPS &agrave; partir d'une distribution DEBIAN
+ vous devez ouvrir une session en tant qu'utilisateur root; utiliser la
+ commande <CODE>su</CODE> est suffisant. Une fois connect&eacute; en tant
+ qu'utilisateur root, lancez simplement dpkg au moyen de la commande:</P>
+<UL>
+<PRE>
+<B>dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTREE</B>
+</PRE>
+</UL>
+<P>Apr&egrave;s un court d&eacute;lai, le logiciel CUPS sera install&eacute; et
+ l'ordonnanceur sera automatiquement d&eacute;marr&eacute;.</P>
+<H1 ALIGN="RIGHT"><A NAME="MANAGING_PRINTERS">3 - Administration les
+ imprimantes</A></H1>
+<P>Ce chapitre d&eacute;crit comment ajouter votre premi&egrave;re imprimante et
+ comment administrer vos imprimantes.</P>
+<H2><A NAME="4_1">Les bases</A></H2>
+<P>Chaque file d'impression a un nom associ&eacute;; le nom de l'imprimante
+ doit commencer avec une lettre et peut comporter jusqu'&agrave; 127 lettres,
+ des chiffres ou un caract&egrave;re de soulignement &quot;_&quot; (&quot;underscore&quot;). La
+ casse des caract&egrave;res n'est pas significative, par exemple les cha&icirc;nes
+ de caract&egrave;res &quot;IMPRIMANTE&quot;, &quot;Imprimante&quot; et &quot;imprimante&quot; sont
+ consid&eacute;r&eacute;es comme le m&ecirc;me nom.</P>
+<P>Les files d'impression ont &eacute;galement un p&eacute;riph&eacute;rique associ&eacute;. Ce
+ p&eacute;riph&eacute;rique peut &ecirc;tre un port parall&egrave;le, une interface r&eacute;seau, etc.
+ Les p&eacute;riph&eacute;riques dans CUPS utilisent des URI (Uniform Resource
+ Identifiers) qui sont une forme plus g&eacute;n&eacute;rale des URL (Uniform Resource
+ Locator) qui sont utilis&eacute;s par votre noavigateur &quot;web&quot;. Par exemple, le
+ premier port parall&egrave;le dans GNU/Linux est habituellement d&eacute;sign&eacute; par
+ l'URI de p&eacute;riph&eacute;rique <CODE>parallel:/dev/lp1</CODE>.</P>
+
+<!-- NEED 2.5in -->
+<P>Vous pouvez voir une liste compl&egrave;te des p&eacute;riph&eacute;riques pris en charge
+ en lan&ccedil;ant la commande <CODE>lpinfo(8)</CODE>:</P>
+<UL>
+<PRE>
+<B>lpinfo -v ENTREE</B>
+file file
+network socket
+network http
+network ipp
+network lpd
+direct parallel:/dev/lp1
+serial serial:/dev/ttyS1?baud=115200
+serial serial:/dev/ttyS2?baud=115200
+direct usb:/dev/usb/lp0
+network smb
+</PRE>
+</UL>
+<P>L'option <CODE>-v</CODE> indique que vous voulez la liste de tous les
+ p&eacute;riph&eacute;riques disponibles. Le premier mot de chaque ligne est le type
+ de p&eacute;riph&eacute;rique (direct, fichier, r&eacute;seau, s&eacute;rie) et est suivi par l'URI
+ du p&eacute;riph&eacute;rique ou le nom de la m&eacute;thode d'acc&egrave;s &agrave; ce p&eacute;riph&eacute;rique. Les
+ p&eacute;riph&eacute;riques de type fichier ont des URI de p&eacute;riph&eacute;rique de la forme <CODE>
+file:/r&eacute;pertoire/nom_fichier</CODE> tandis que les p&eacute;riph&eacute;riques r&eacute;seau
+ utilisent la forme plus famili&egrave;re <CODE>methode://serveur</CODE> ou <CODE>
+m&eacute;thode://serveur/chemin</CODE>.</P>
+<P>Enfin, les files d'impression ont g&eacute;n&eacute;ralement un fichier PPD
+ (PostScript Printer Definition) associ&eacute;. Les fichiers PPD d&eacute;crivent les
+ capacit&eacute;s de chaque imprimante, les tailles de support prises en
+ charge, etc., et sont utilis&eacute;s pour les imprimantes PostScript et
+ non-PostScript. CUPS inclut des fichiers PPD pour les imprimantes HP
+ LaserJet et Deskjet, EPSON Stylus, et EPSON 9 et 24 aiguilles.</P>
+<H2><A NAME="4_2">Ajouter votre premi&egrave;re imprimante</A></H2>
+<P>CUPS fournit deux m&eacute;thodes pour ajouter des imprimantes : un
+ programme en ligne de commande nomm&eacute; <CODE>lpadmin(8)</CODE> et une
+ inteface &quot;web&quot;. La commande <CODE>lpadmin</CODE> vous permet
+ d'effectuer la plupart des t&acirc;ches d'administration d'imprimantes &agrave;
+ partir de la ligne de commande, elle est situ&eacute;e dans le r&eacute;pertoire<VAR>
+ /usr/sbin</VAR>. L'interface &quot;web&quot; est disponible &agrave; l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>et vous quide pas &agrave; pas au travers des &eacute;tapes de configuration
+ d'imprimante. Si vous n'aimez pas les interfaces en ligne de commande,
+ essayez plut&ocirc;t <A HREF="#ADD_WEB">l'interface web</A>.</P>
+<H3><A NAME="4_2_1">Ajouter votre premi&egrave;re imprimante depuis la ligne de
+ commande</A></H3>
+<P>Ex&eacute;cutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-p</CODE>
+ pour ajouter une imprimante &agrave; CUPS:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -E -v <I>p&eacute;riph&eacute;rique</I> -m <I>ppd</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Pour une imprimante HP DeskJet connect&eacute;e au port parall&egrave;le, la
+ commande serait:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTREE</B>
+</PRE>
+</UL>
+<P>De la m&ecirc;me mani&egrave;re, une imprimante HP LaserJet utilisant une
+ interface r&eacute;seau de type JetDirect &agrave; l'adresse IP 11.22.33.44 serait
+ ajout&eacute;e avec la commande:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTREE</B>
+</PRE>
+</UL>
+<P>Comme vous pouvez le voir, <CODE>deskjet.ppd</CODE> et <CODE>
+laserjet.ppd</CODE> sont les fichiers PPD pour les pilotes HP DeskJet et
+ HP LaserJet inclus dans CUPS. Vous trouverez une liste compl&egrave;te des
+ fichiers PPD ainsi que celle des imprimantes avec lesquelles ils
+ fonctionnent dans l'<A HREF="#PRINTER_DRIVERS">Annexe C, &quot;Pilotes
+ d'imprimantes&quot;</A>.</P>
+<P>Pour une imprimante matricielle &agrave; aiguilles connect&eacute;e au port s&eacute;rie,
+ la commande serait:</P>
+<P></P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTREE</B>
+</PRE>
+</UL>
+<P>Ici, vous indiquez le port s&eacute;rie (par exemple S0, S1, d0, s1), le
+ taux de transfert en bauds (par exemple 9600, 19200, 38400, 115200,
+ etc.), le nombre de bits de parti&eacute;, et le contr&ocirc;le de flux. Si vous
+ n'avez pas besoin de contr&ocirc;le de flux, supprimez la partie
+ &quot;+flow=soft&quot;.</P>
+<H3><A NAME="ADD_WEB">Ajouter votre premi&egrave;re imprimante depuis
+ l'interface &quot;web&quot;</A></H3>
+<P>Le serveur CUPS fournit une interface ergonomique sous forme d'un
+ assistant (&quot;wizard&quot;) pour ajouter les imprimantes. Plut&ocirc;t que devoir
+ d&eacute;terminer quel URI de p&eacute;riph&eacute;rique et quel fichier PPD utiliser, vous
+ cliquez simplement sur l'option ad&eacute;quate de la liste et vous remplissez
+ quelques champs de formulaires avec des informations simples. Entrez
+ l'adresse suivante dans votre navigateur &quot;web&quot; pour commencer:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>Cliquez sur le bouton<VAR> Ajouter imprimante</VAR> pour en ajouter
+ une.</P>
+<H2><A NAME="4_3">Administrer les imprimantes depuis la ligne de
+ commande</A></H2>
+<P>La commande <CODE>lpadmin</CODE> vous permet d'effectuer la plupart
+ des t&acirc;ches d'administration d'imprimantes depuis la ligne de commande.
+ Vous trouverez <CODE>lpadmin</CODE> dans le r&eacute;pertoire<VAR> /usr/bin</VAR>
+.</P>
+<H3><A NAME="4_3_1">Ajouter et modifier des imprimantes</A></H3>
+<P>Ex&eacute;cutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-p</CODE>
+ pour ajouter ou modifier une imprimante.</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> <I>options</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Les arguments<I> options</I> peuvent &ecirc;tre n'importe lesquels parmi:</P>
+<UL>
+<DL>
+<DT>-c<I> classe</I></DT>
+<DD>Ajoute l'imprimante nomm&eacute;e &agrave; la classe d'imprimantes<VAR> classe</VAR>
+. Si la classe d'imprimantes n'existe pas alors elle est cr&eacute;&eacute;e.</DD>
+<DT>-i<I> interface</I></DT>
+<DD>Copie le script pour l'<I>interface</I> vers l'imprimante. Les
+ scripts d'interface sont utilis&eacute;s par les pilotes d'imprimantes System
+ V. Etant donn&eacute; que tous les filtres sont d&eacute;sactiv&eacute;s lorsque les scripts
+ d'interface sont employ&eacute;s, les scripts ne devraient normalement jamais
+ &ecirc;tre utilis&eacute;s &agrave; moins qu'il n'y ait aucun autre pilote pour
+ l'imprimante.</DD>
+<DT>-m<I> mod&egrave;le</I></DT>
+<DD>Indique une pilote d'imprimante standard qui est g&eacute;n&eacute;ralement un
+ fichier PPD. Une liste de tous les mod&egrave;les disponibles peut &ecirc;tre
+ affich&eacute;e au moyen de l'option <CODE>-m</CODE>. Une liste de tous les
+ pilotes d'imprimantes inclus dans CUPS peut &ecirc;tre consult&eacute;e dans l'<A HREF="#PRINTER_DRIVERS">
+Annexe C, &quot;Pilotes d'imprimantes&quot;</A>.</DD>
+<DT>-r<I> classe</I></DT>
+<DD>Retire l'imprimante sp&eacute;cifi&eacute;e de la classe d'imprimantes<VAR> classe</VAR>
+. Si la classe qui en r&eacute;sulte est vide, elle est supprim&eacute;e.</DD>
+<DT>-v<I> uri-p&eacute;riph&eacute;rique</I></DT>
+<DD>Indique le p&eacute;riph&eacute;rique &agrave; employer pour dialoguer avec l'imprimante.
+ Si un travail d'impression est actuellement en cours d'&eacute;dition sur
+ l'imprimante sp&eacute;cifi&eacute;e, il est relanc&eacute; et envoy&eacute; au nouveau
+ p&eacute;riph&eacute;rique.</DD>
+<DT>-D<I> info</I></DT>
+<DD>Fournit une description textuelle de l'imprimante, par exemple
+ &quot;Imprimante personnelle de Marcel&quot;.</DD>
+<DT>-E</DT>
+<DD>Active l'imprimante et accepte les travaux d'impression. Cette
+ option &eacute;quivaut &agrave; ex&eacute;cuter les commandes <CODE>enable(1)</CODE> et <CODE>
+accept(8)</CODE>.</DD>
+<DT>-L<I> emplacement</I></DT>
+<DD>Fournit une description textuelle de l'emplacement de l'imprimante,
+ par exemple &quot;Salle informatique n&deg;5&quot;.</DD>
+<DT>-P<I> fichier-ppd</I></DT>
+<DD>Indique un fichier PPD local pour le pilote d'imprimante.</DD>
+</DL>
+</UL>
+<H3><A NAME="4_3_2">Supprimer des imprimantes</A></H3>
+<P>Ex&eacute;cutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-x</CODE>
+ pour supprimer une imprimante:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>printer</I> ENTREE</B>
+</PRE>
+</UL>
+<H3><A NAME="4_3_3">Choisir l'imprimante implicite</A></H3>
+<P>Ex&eacute;cutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-d</CODE>
+ pour d&eacute;finir l'imprimante standard:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -d <I>printer</I> ENTREE</B>
+</PRE>
+</UL>
+<P>L'imprimante standard peut-&ecirc;tre outrepass&eacute;e par l'utilisateur au
+ moyen de la commande <CODE>lpoptions(1)</CODE>.</P>
+<H3><A NAME="4_3_4">D&eacute;marrer et arr&ecirc;ter des imprimantes</A></H3>
+<P>Les commandes <CODE>enable</CODE> et <CODE>disable</CODE> d&eacute;marrent
+ et arr&ecirc;tent les files d'impression, avec les syntaxes respectives
+ suivantes :</P>
+<UL>
+<PRE>
+<B>/usr/bin/enable <I>imrimante</I> ENTREE</B>
+<B>/usr/bin/disable <I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+<P><I><B>Note du traducteur :</B> utilisateurs du shell BASH attention !
+ <CODE>enable</CODE> est une commande interne de celui-ci. Si vous tapez
+ simplement <CODE>enable</CODE> vous obtiendrez un message d'erreur car
+ c'est la version interne de BASH qui sera utilis&eacute;e en standard. Pour
+ effectivement utiliser la commande <CODE>enable</CODE> de CUPS vous <U>
+devez</U> faire pr&eacute;c&eacute;der son nom du chemin d'acc&egrave;s complet : <CODE>
+/usr/bin/enable</CODE>.</I></P>
+<P>Les imprimantes qui sont d&eacute;sactiv&eacute;es peuvent toujours accepter les
+ travaux d'impression mais n'en imprimeront effectivement aucun tant
+ qu'elle ne seront pas r&eacute;activ&eacute;es. Cela est utile si une imprimante
+ fonctionne mal et que vous avez besoin de corriger le probl&egrave;me
+ (bourrage). Tout travail d'impression mis en file d'attente est imprim&eacute;
+ d&egrave;s que la l'imprimante est r&eacute;activ&eacute;e.</P>
+<H3><A NAME="4_3_5">Accepter et rejeter les travaux d'impression</A></H3>
+<P>Les commandes <CODE>accept</CODE> et <CODE>reject</CODE> permettent
+ respectivement d'indiquer &agrave; une imprimante qu'elle doit accepter ou
+ rejeter les nouveaux travaux d'impression:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/accept <I>imprimante</I> ENTREE</B>
+<B>/usr/sbin/reject <I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Comme indiqu&eacute; ci-dessus, une imprimante peut &ecirc;tre configur&eacute;e pour ne
+ plus accepter de nouveaux travaux d'impression. Une imprimante peut
+ aussi rejeter les nouveaux travaux d'impression bien qu'elle soit en
+ train de terminer le traitement de ceux qui ont &eacute;t&eacute; mis en file
+ d'attente avant que celle-ci soit d&eacute;sactiv&eacute;e. Ceci est utile si vous
+ avez besoin d'effectuer des op&eacute;rations de maintenance sur l'imprimante
+ et que vous ne voulez pas qu'elle soit disponible pour les utilisateurs
+ pendante une longue p&eacute;riode.</P>
+<H2><A NAME="4_4">Administrer les imprimantes depuis l'interface &quot;web&quot;</A>
+</H2>
+<P>L'interface &quot;web&quot; est disponible &agrave; l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>Depuis celle-ci vous pouvez effectuer toutes les t&acirc;ches
+ d'administrations sur les imprimantes au moyen de quelques clics de
+ souris.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_CLASSES">4 - Classes d'imprimantes</A>
+</H1>
+<P>Ce chapitre d&eacute;crit ce que sont les classes d'imprimantes et comment
+ les administrer.</P>
+<H2><A NAME="5_1">Les bases</A></H2>
+<P>CUPS fournit des collections d'imprimantes appel&eacute;es<I> classes
+ d'imprimantes</I>. Les travaux soumis &agrave; une classe sont transmis &agrave; la
+ premi&egrave;re imprimante disponible de la classe. Les classes peuvent elles
+ auusi &ecirc;tre membres d'autres classes, ainsi il est possible que vous
+ d&eacute;finissiez de grandes classes r&eacute;parties afin de fournir un syst&egrave;me
+ d'impression &agrave; haute disponibilit&eacute;.</P>
+<P>CUPS prend &eacute;galement en charge les<I> classe implicites</I>. Les
+ classes implicites fonctionnent comme les classes d'imprimantes, mais
+ elles sont cr&eacute;&eacute;es automatiquement &agrave; partir des classes et imprimantes
+ disponibles sur le r&eacute;seau. Cela vous permet de configurer de multiples
+ serveurs d'impression avec des configurations d'imprimantes identiques
+ de sorte que les syst&egrave;mes clients envoient des travaux d'impression au
+ premier serveur disponible. Si un ou plusieurs serveurs deviennent
+ indisponibles, les travaux d'impressions sont automatiquement redirig&eacute;s
+ vers les serveurs encore en fonctionnement, fournissant ainsi un
+ syst&egrave;me d'impression r&eacute;sistant aux pannes.</P>
+<H2><A NAME="5_2">Administrer les classes d'imprimantes depuis la ligne
+ de commande</A></H2>
+<P>Ex&eacute;cutez la commande <CODE>lpadmin</CODE> avec les options <CODE>-p</CODE>
+ et <CODE>-c</CODE> pour ajouter une classe d'imprimantes:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -c <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<P>La<I> classe</I> est cr&eacute;&eacute;e automatiquement si elle n'existe pas. Pour
+ retirer une imprimante d'une classe, utilisez l'option <CODE>-r</CODE>:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -r <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Pour enlever toute la classe, utilisez l'option <CODE>-x</CODE>:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Administrer les classes d'imprimante depuis
+ l'interface &quot;web&quot;</A></H2>
+<P>L'interface &quot;web&quot; est disponible &agrave; l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>Les pages<VAR> Ajouter classe</VAR> et<VAR> Modifier classe</VAR>
+ fournissent une liste des imprimantes disponibles. Cliquez sur la ou
+ les imprimantes de votre choix pour les ajouter &agrave; la classe.</P>
+<H2><A NAME="5_4">Classes implicites</A></H2>
+<P>Comme indiqu&eacute; auparavant, les classes implicites sont automatiquement
+ cr&eacute;&eacute;es &agrave; partir des imprimantes et des classes disponibles sur le
+ r&eacute;seau. Pour d&eacute;sactiver cette fonctionnalit&eacute;, r&eacute;glez la valeur de la
+ directive <A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+ sur <CODE>Off</CODE> dans le fichier <CODE>cupsd.conf</CODE>. Vous
+ trouverez plus d'information sur la mani&egrave;re de faire cela dans le <A HREF="#PRINTING_MANAGEMENT">
+ Chapitre 6, &quot;Administration du syst&egrave;me d'impression&quot;</A>.</P>
+<H1 ALIGN="RIGHT"><A NAME="CLIENT_SETUP">5 - Configuration c&ocirc;t&eacute; client</A>
+</H1>
+<P>Ce chapitre expose diverses mani&egrave;res de configurer les clients CUPS
+ pour pouvoir imprimer.</P>
+<H2><A NAME="6_1">Les bases</A></H2>
+<P>Un client est toute machine qui envoie des travaux d'impression &agrave; une
+ autre machine pour &eacute;dition finale. Les clients peuvent &eacute;galement &ecirc;tre
+ des serveurs s'il communiquent directement avec des imprimantes qui
+ leur appartiennent.</P>
+<P>CUPS prend en charge plusieurs m&eacute;thodes pour configurer les machines
+ clientes:</P>
+<UL>
+<LI><A HREF="#CLIENT_MANUAL">Configuration manuelle des files
+ d'impression.</A></LI>
+<LI><A HREF="#CLIENT_SERVER">Choix d'un serveur unique pour
+ l'impression.</A></LI>
+<LI><A HREF="#CLIENT_AUTO">Configuration automatique des files
+ d'impression.</A></LI>
+<LI><A HREF="#CLIENT_POLL">Choix de plusieurs serveurs pour
+ l'impression.</A></LI>
+</UL>
+<H3><A NAME="CLIENT_MANUAL">Configuration manuelle des files
+ d'impression</A></H3>
+<P>La m&eacute;thode la plus fastidieuse pour configurer les machines clientes
+ est de configurer chaque file d'impression &agrave; distance &agrave; la main au
+ moyen de la commande <CODE>lpadmin</CODE>:</P>
+<UL>
+<PRE>
+<B>lpadmin -p <I>imprimante</I> -E -v ipp://<I>serveur</I>/printers/<I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Le nom<I> imprimante</I> est le nom de l'imprimante sur la machine
+ serveur. Le nom <CODE>serveur</CODE> est le nom d'h&ocirc;te ou l'adresse IP
+ de la machine serveur. R&eacute;p&egrave;tez la commande <CODE>lpadmin</CODE> pour
+ chaque imprimante distante que vous d&eacute;sirez utilser.</P>
+<H3><A NAME="CLIENT_SERVER">Choix d'un serveur unique pour l'impression</A>
+</H3>
+<P>CUPS peut &ecirc;tre configur&eacute; pour fonctionnner sans file d'attente locale
+ et envoyer tous les travaux d'impression &agrave; un serveur unique.
+ Cependant, si ce serveur vient &agrave; tomber en panne, toute possibilit&eacute;
+ d'imprimer sera supprim&eacute;e. Utilisez cette configuration uniquement
+ lorsque c'est absolument n&eacute;cessaire.</P>
+<P>Le serveur implicite est normalement &quot;localhost&quot;. Pour outrepasser ce
+ r&eacute;glage de base, cr&eacute;ez un fichier nomm&eacute;<VAR> /etc/cups/client.conf</VAR>
+ et ajoutez une ligne:</P>
+<UL>
+<PRE>
+ServerName <I>serveur</I>
+</PRE>
+</UL>
+<P>au fichier. Le nom<VAR> serveur</VAR> peut &ecirc;tre le nom d'h&ocirc;te ou
+ l'adresse IP du serveur implicite.</P>
+<P>Le serveur implicite peut &eacute;galement &ecirc;tre adapt&eacute; en fonction de
+ l'utilisateur. Pour cr&eacute;er un r&eacute;glage sp&eacute;cifique &agrave; l'utilisateur, cr&eacute;ez
+ un fichier nomm&eacute;<VAR> ~/.cupsrc</VAR> et ajoutez une ligne:</P>
+<UL>
+<PRE>
+ServerName <I>serveur</I>
+</PRE>
+</UL>
+<P></P>
+<P>au fichier. Le nom<VAR> serveur</VAR> peut &ecirc;tre le nom d'h&ocirc;te ou
+ l'adresse IP du serveur implicite.</P>
+<H3><A NAME="CLIENT_AUTO">Configuration automatique des files
+ d'impression</A></H3>
+<P>CUPS prend en charge la configuration automatique des clients pour
+ les imprimantes sur le m&ecirc;me sous-r&eacute;seau. Pour configurer des
+ imprimantes pr&eacute;sentes sur le m&ecirc;me sous-r&eacute;seau,<I> ne fa&icirc;tes rien</I>.
+ Chaque client devrait voir automatiquement les imprimantes disponibles
+ dans un d&eacute;lai de 30 secondes. Les listes des classes et des imprimantes
+ sont automatiquement mises &agrave; jour chaque fois que des imprimantes et
+ des serveurs sont ajout&eacute;s ou retir&eacute;s.</P>
+<P>Si vous d&eacute;sirez &eacute;galement voir les imprimantes sur d'autres
+ sous-r&eacute;seau, utilisez la directive <A HREF="#BrowsePoll"><CODE>
+BrowsePoll</CODE></A> comme indiqu&eacute; ci-apr&egrave;s.</P>
+<H3><A NAME="CLIENT_POLL">Choix de plusieurs serveurs pour l'impression</A>
+</H3>
+<P>Si vous disposez de plusieurs serveurs CUPS sur plusieurs
+ sous-r&eacute;seaux, vous devriez configurer CUPS pour surveiller ces
+ serveurs. La surveillance fournit l'avantage d'automatiser
+ singuli&egrave;rement la configuration sur les clients, et plusieurs clients
+ sur le m&ecirc;me sous-r&eacute;seau peuvent partager les m&ecirc;mes informations de
+ configuration.</P>
+<P>La surveillance est activ&eacute;e en indiquant une ou plusieurs directives <A
+HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A> dans le fichier<VAR>
+ /etc/cups/cupsd.conf</VAR>. Pour savoir comment faire ces changements,
+ veuillez vous reporter au <A HREF="#PRINTING_MANAGEMENT"> Chapitre 6,
+ &quot;Administration du syst&egrave;me d'impression&quot;</A>.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Administration du
+ syst&egrave;me d'impression</A></H1>
+<P>Ce chapitre montre comment configurer le serveur CUPS.</P>
+<H2><A NAME="7_1">Les bases</A></H2>
+<P>Plusieurs fichiers texte sont utilis&eacute;s pour configurer CUPS. Tous les
+ fichiers de configuration du serveur sont plac&eacute;s dans le r&eacute;pertoire<VAR>
+ /etc/cups</VAR>:</P>
+<UL>
+<DL>
+<!-- NEED 1in -->
+<DT>classes.conf</DT>
+<DD>Ce fichier contient les informations sur chaque classe d'imprimante.
+ Normalement vous manipulez ce fichier en utilisant la commande <CODE>
+lpadmin</CODE> ou l'interface &quot;web&quot;.
+<BR> &nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>client.conf</DT>
+<DD> Ce fichier fournit le nom du serveur implicite pour les machines
+ clientes. Veuillez vous reporter au <A HREF="#CLIENT_SETUP">Chapitre 5,
+ &quot;Configuration c&ocirc;t&eacute; client&quot;</A> pour de plus amples informations.
+<BR> &nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>cupsd.conf</DT>
+<DD> Ce fichier contr&ocirc;le la mani&egrave;re de fonctionner sur serveur CUPS (<VAR>
+/usr/sbin/cupsd</VAR>) et est normalement &eacute;dit&eacute; &agrave; la main.
+<BR> &nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.convs</DT>
+<DD>Ce fichier contient une liste des filtres de base pour la conversion
+ de fichier et leurs co&ucirc;ts respectifs. Normalement, vous n'&eacute;diterez pas
+ ce fichier.
+<BR> &nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.types</DT>
+<DD>Ce fichier contient la liste des formats de fichiers standards et
+ comment les reconna&icirc;tre. Normalement, vous n'&eacute;diterez pas ce fichier.
+<BR> &nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>printers.conf</DT>
+<DD> Ce fichier contient des informations sur chaque imprimante.
+ Normalement, vous manipulez ce fichier en utilisant la commande <CODE>
+lpadmin</CODE> ou l'interface &quot;web&quot;.
+<BR> &nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="RESTARTING">Red&eacute;marrer le serveur CUPS</A></H2>
+<P>Une fois que vous avez fait des changements au fichier de
+ configuration, vous devez red&eacute;marrer le serveur CUPS en lui envoyant un
+ signal <CODE>HUP</CODE> ou en utilisant le script d'initialisation
+ ad&eacute;quat. Les distributions de CUPS installent le script dans le
+ r&eacute;pertoire<VAR> init.d</VAR> sous le nom<VAR> cups</VAR>. L'emplacement
+ varie selon le syst&egrave;me d'exploitation:</P>
+<UL>
+<PRE>
+<B>/etc/rc.d/init.d/cups restart ENTREE</B>
+<B>/etc/init.d/cups restart ENTREE</B>
+<B>/sbin/init.d/cups restart ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="7_3">Changer la configuration du serveur</A></H2>
+<P>Le fichier<VAR> /etc/cups/cupsd.conf</VAR> contient des<I> directives</I>
+ de configuration qui contr&ocirc;lent le fonctionnement du serveur. Chaque
+ directive suivie de sa valeur est dispos&eacute;e seule sur une ligne. Les
+ commentaires sont ouverts par le signe di&egrave;se (&quot;#&quot;) au d&eacute;but de la
+ ligne. Etant donn&eacute; que le fichier de configuration du serveur est un
+ fichier texte, vous pouvez le modifier au moyen de votre &eacute;diteur de
+ texte pr&eacute;f&eacute;r&eacute;.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="7_4">Directives de configuration du serveur</A></H2>
+<P>Le fichier<VAR> cupsd.conf</VAR> contient de nombreuses directives
+ qui d&eacute;terminent le comportement du serveur:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#AccessLog"><CODE>AccessLog</CODE></A></LI>
+<LI><A HREF="#Allow"><CODE>Allow</CODE></A></LI>
+<LI><A HREF="#AuthClass"><CODE>AuthClass</CODE></A></LI>
+<LI><A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A></LI>
+<LI><A HREF="#AuthType"><CODE>AuthType</CODE></A></LI>
+<LI><A HREF="#AutoPurgeJobs"><CODE>AutoPurgeJobs</CODE></A></LI>
+<LI><A HREF="#BrowseAddress"><CODE>BrowseAddress</CODE></A></LI>
+<LI><A HREF="#BrowseAllow"><CODE>BrowseAllow</CODE></A></LI>
+<LI><A HREF="#BrowseDeny"><CODE>BrowseDeny</CODE></A></LI>
+<LI><A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A></LI>
+<LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A></LI>
+<LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A></LI>
+<LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A></LI>
+<LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A></LI>
+<LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A></LI>
+<LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
+<LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
+<LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
+<LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
+<LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A></LI>
+<LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
+<LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
+<LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
+<LI><A HREF="#Deny"><CODE>Deny</CODE></A></LI>
+<LI><A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#Encryption"><CODE>Encryption</CODE></A></LI>
+<LI><A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A></LI>
+<LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A></LI>
+<LI><A HREF="#FontPath"><CODE>FontPath</CODE></A></LI>
+<LI><A HREF="#Group"><CODE>Group</CODE></A></LI>
+<LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A></LI>
+<LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A></LI>
+<LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A></LI>
+<LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A></LI>
+<LI><A HREF="#Include"><CODE>Include</CODE></A></LI>
+<LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A></LI>
+<LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A></LI>
+<LI><A HREF="#Limit"><CODE>Limit</CODE></A></LI>
+<LI><A HREF="#LimitExcept"><CODE>LimitExcept</CODE></A></LI>
+<LI><A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A></LI>
+<LI><A HREF="#Listen"><CODE>Listen</CODE></A></LI>
+<LI><A HREF="#Location"><CODE>Location</CODE></A></LI>
+<LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A></LI>
+<LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A></LI>
+<LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A></LI>
+<LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
+<LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
+<LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
+<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
+<LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
+<LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
+<LI><A HREF="#Printcap"><CODE>Printcap</CODE></A></LI>
+<LI><A HREF="#PrintcapFormat"><CODE>PrintcapFormat</CODE></A></LI>
+<LI><A HREF="#PrintcapGUI"><CODE>PrintcapGUI</CODE></A></LI>
+<LI><A HREF="#RemoteRoot"><CODE>RemoteRoot</CODE></A></LI>
+<LI><A HREF="#RequestRoot"><CODE>RequestRoot</CODE></A></LI>
+<LI><A HREF="#Require"><CODE>Require</CODE></A></LI>
+<LI><A HREF="#RIPCache"><CODE>RIPCache</CODE></A></LI>
+<LI><A HREF="#RunAsUser"><CODE>RunAsUser</CODE></A></LI>
+<LI><A HREF="#Satisfy"><CODE>Satisfy</CODE></A></LI>
+<LI><A HREF="#ServerAdmin"><CODE>ServerAdmin</CODE></A></LI>
+<LI><A HREF="#ServerBin"><CODE>ServerBin</CODE></A></LI>
+<LI><A HREF="#ServerCertificate"><CODE>ServerCertificate</CODE></A></LI>
+<LI><A HREF="#ServerKey"><CODE>ServerKey</CODE></A></LI>
+<LI><A HREF="#ServerName"><CODE>ServerName</CODE></A></LI>
+<LI><A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A></LI>
+<LI><A HREF="#SSLListen"><CODE>SSLListen</CODE></A></LI>
+<LI><A HREF="#SSLPort"><CODE>SSLPort</CODE></A></LI>
+<LI><A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A></LI>
+<LI><A HREF="#TempDir"><CODE>TempDir</CODE></A></LI>
+<LI><A HREF="#Timeout"><CODE>Timeout</CODE></A></LI>
+<LI><A HREF="#User"><CODE>User</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="AccessLog">AccessLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AccessLog /var/log/cups/access_log
+AccessLog /var/log/cups/access_log-%s
+AccessLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AccessLog</CODE> donne le nom du fichier de suivi
+ d'acc&egrave;s (&quot;access log&quot;). Si le chemin d'acc&egrave;s au fichier n'est pas
+ absolu, il est consid&eacute;r&eacute; comme relatif au r&eacute;pertoire<A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A>. Le fichier &quot;access log&quot; est stock&eacute; dans le
+ format &quot;log&quot; habituel et peut ais&eacute;ment &ecirc;tre utilis&eacute; par tout outil
+ d'analyse d'acc&egrave;s &quot;web&quot; pour g&eacute;n&eacute;rer un rapport sur l'activit&eacute; du
+ serveur CUPS.</P>
+<P>Le nom du serveur peut &ecirc;tre inclus dans le nom du fichier en
+ utilisant <CODE>%s</CODE> dans le nom.</P>
+<P>Le nom sp&eacute;cial &quot;syslog&quot; peut &ecirc;tre utilis&eacute; pour envoyer les
+ informations d'acc&egrave;s au fichier de suivi syst&egrave;me au lieu d'un simple
+ fichier texte.</P>
+<P>Le fichier de suivi d'acc&egrave;s implicite est<VAR>
+ /var/log/cups/access_log</VAR>.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="Allow">Allow</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Allow from All
+Allow from None
+Allow from *.domain.com
+Allow from .domain.com
+Allow from host.domain.com
+Allow from nnn.*
+Allow from nnn.nnn.*
+Allow from nnn.nnn.nnn.*
+Allow from nnn.nnn.nnn.nnn
+Allow from nnn.nnn.nnn.nnn/mm
+Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Allow</CODE> indique un nom d'h&ocirc;te, une adresse IP
+ ou un r&eacute;seau qui est autoris&eacute; &agrave; acc&eacute;der au serveur. Les directives <CODE>
+Allow</CODE> se cumulent, ainsi plusieurs directives <CODE>Allow</CODE>
+ peuvent &ecirc;tre utilis&eacute;es pour autoriser l'acc&egrave;s &agrave; de multiples h&ocirc;tes
+ et/ou r&eacute;seaux. La notation <CODE>/mm</CODE> indique une notation de
+ sous-r&eacute;seau CIDR:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+ mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+ 8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+ 16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+ 24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+ 32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La directive <CODE>Allow</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur d'une
+ directive <A HREF="#Location"><CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthClass">AuthClass</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthClass Anonymous
+AuthClass User
+AuthClass System
+AuthClass Group
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthClass</CODE> d&eacute;finit le niveau
+ d'authentification requis:</P>
+<UL>
+<LI><CODE>Anonymous</CODE> - Pas d'authentification n&eacute;cessaire. C'est la
+ valeur implicite</LI>
+<LI><CODE>User</CODE> - Un nom d'utilisateur et un mot de passe valides
+ sont requis.</LI>
+<LI><CODE>System</CODE> - Un nom d'utilisateur et un mot de passe
+ valides sont requis, et cet utilisateur doit &ecirc;tre membre du groupe
+ &quot;sys&quot;; cela peut &ecirc;tre chang&eacute; au moyen de la directive<A HREF="#SystemGroup">
+<CODE>SystemGroup</CODE></A>.</LI>
+<LI><CODE>Group</CODE> - Un nom d'utilisateur et un mot de passe valides
+ sont requis, et cet utilisateur doit &ecirc;tre membre du groupe indiqu&eacute; dans
+ la directive <CODE>AuthGroupName</CODE>.</LI>
+</UL>
+<P>La directive <CODE>AuthClass</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur
+ d'une directive<A HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthGroupName">AuthGroupName</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthGroupName mygroup
+AuthGroupName lp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthGroupName</CODE> d&eacute;finit le groupe &agrave; utiliser
+ pour l'authentification de type <CODE>Group</CODE>.</P>
+<P>La directive <CODE>AuthGroupName</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur
+ d'une directive <A HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthType">AuthType</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthType None
+AuthType Basic
+AuthType Digest
+AuthType BasicDigest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthType</CODE> d&eacute;finit le type d'authentification
+ qui doit &ecirc;tre effectu&eacute;e:</P>
+<UL>
+<LI><CODE>None</CODE> - Pas d'authentification. C'est la valeur
+ implicite</LI>
+<LI><CODE>Basic</CODE> - Une authentification &quot;Basic&quot; doit &ecirc;tre
+ effectu&eacute;e en utilisant le fichier de mots de passe et de groupe d'UNIX.</LI>
+<LI><CODE>Digest</CODE> - Une authentification &quot;Digest&quot; doit &ecirc;tre
+ effectu&eacute;e en utilisant le fichier<VAR> /etc/cups/passwd.md5</VAR>.</LI>
+<LI><CODE>BasicDigest</CODE> - Une authentification &quot;Basic&quot; doit &ecirc;tre
+ effectu&eacute;e en utilisant le fichier<VAR> /etc/cups/passwd.md5</VAR>.</LI>
+</UL>
+<P> Lorsque vous utilisez <CODE>Basic</CODE>, <CODE>Digest</CODE>, ou <CODE>
+BasicDigest</CODE>, les clients se connectant en utilisant l'adresse <CODE>
+localhost</CODE> peuvent &eacute;galement le faire en utilisant les <A HREF="#CERTIFICATES">
+certificats</A>.</P>
+<P>La directive <CODE>AuthType</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur
+ d'une directive <A HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AutoPurgeJobs">AutoPurgeJobs</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AutoPurgeJobs Yes
+AutoPurgeJobs No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AutoPurgeJobs</CODE> indique si oui ou non il faut
+ purger les travaux d'impression lorsqu'ils ne sont plus n&eacute;cessaires au
+ vu des quotas. Cet option n'a aucun effet si les quotas ne sont pas
+ activ&eacute;s. La valeur implicite est <CODE>No</CODE>.
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="BrowseAddress">BrowseAddress</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseAddress 255.255.255.255:631
+BrowseAddress 192.0.2.255:631
+BrowseAddress host.domain.com:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseAddress</CODE> indique une adresse &agrave;
+ laquelle il faut envoyer les informations d'exploration. Plusieurs
+ directives <CODE>BrowseAddress</CODE> peuvent &ecirc;tre indiqu&eacute;es pour
+ envoyer les informations d'exploration &agrave; diff&eacute;rents syst&egrave;mes ou
+ r&eacute;seaux.</P>
+<P>La valeur implicite de l'adresse est <CODE>255.255.255.255:631</CODE>
+ ce qui diffusera les informations &agrave; tous les r&eacute;seaux auxquels le
+ serveur est connect&eacute;.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTA:</B>
+<P>Si vous utilisez HP-UX 10.20 sur un sous-r&eacute;seau dont le masque n'est
+ pas sur 24, 16 ou 8 bits, l'exploration des imprimantes (et en fait
+ toute r&eacute;ception d'information diffus&eacute;e) ne fonctionnera pas. Ce
+ probl&egrave;me semble r&eacute;solu dans HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseAllow">BrowseAllow</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseAllow from all
+BrowseAllow from none
+BrowseAllow from 192.0.2
+BrowseAllow from 192.0.2.0/24
+BrowseAllow from 192.0.2.0/255.255.255.0
+BrowseAllow from *.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseAllow</CODE> indique un syst&egrave;me dont on
+ accepte de recevoir des paquets d'exploration. Le comportement
+ implicite est d'accepter des paquets d'exploration de n'importe quel
+ h&ocirc;te.</P>
+<P>Le contr&ocirc;le sur la base du nom d'h&ocirc;te et de domaine impose que vous
+ activiez la directive <A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE>
+</A>.</P>
+<P>Le contr&ocirc;le sur la base de l'adresse IP prend en charge les
+ correspondances exactes, les adresses partielles qui correspondent &agrave;
+ des r&eacute;seaux dont le masque est 255.0.0.0, 255.255.0.0, et
+ 255.255.255.0, ou des adresses r&eacute;seau utilisant le masque indiqu&eacute;.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseDeny">BrowseDeny</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseDeny from all
+BrowseDeny from none
+BrowseDeny from 192.0.2
+BrowseDeny from 192.0.2.0/24
+BrowseDeny from 192.0.2.0/255.255.255.0
+BrowseDeny from *.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseDeny</CODE> indique un syst&egrave;me dont on
+ refuse de recevoir des paquets d'exploration. Le comportement implicite
+ est de ne refuser aucun paquet d'exploration d'aucun h&ocirc;te.</P>
+<P>Le contr&ocirc;le sur la base du nom d'h&ocirc;te et de domaine impose que vous
+ activiez la directive <A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE>
+</A>.</P>
+<P>Le contr&ocirc;le sur la base de l'adresse IP prend en charge les
+ correspondances exactes, les adresses partielles qui correspondent &agrave;
+ des r&eacute;seaux dont le masque est 255.0.0.0, 255.255.0.0, et
+ 255.255.255.0, ou des adresses r&eacute;seau utilisant le masque indiqu&eacute;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseOrder">BrowseOrder</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseOrder allow,deny
+BrowseOrder deny,allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseOrder</CODE> indique l'ordre de traitement
+ accord/refus. L'ordre implicite est <CODE>deny,allow</CODE>:</P>
+<UL>
+<LI><CODE>allow,deny</CODE> - Les paquets d'exploration sont accept&eacute;s &agrave;
+ moins qu'ils ne soient explicitement refus&eacute;s.</LI>
+<LI><CODE>deny,allow</CODE> - Les paquets d'exploration sont rejet&eacute;s &agrave;
+ moins qu'ils ne soient explicitement accept&eacute;s.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseInterval 0
+BrowseInterval 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseInterval</CODE> indique le d&eacute;lai maximum
+ entre deux mises &agrave; jour de l'exploration. Le fait d'indiquer une valeur
+ de 0 interdit de diffuser des mises &agrave; jour mais autorise n&eacute;anmoins un
+ serveur &agrave; recevoir des mises &agrave; jour en provenance d'autres h&ocirc;tes.</P>
+<P>La valeur <CODE>BrowseInterval</CODE> devrait toujours &ecirc;tre
+ inf&eacute;rieure &agrave; la valeur <A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE>
+</A>. Sinon des imprimantes et des classes pourraient dispara&icirc;tre des
+ syst&egrave;me clients entre les mises &agrave; jour.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowsePoll">BrowsePoll</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowsePoll 192.0.2.2:631
+BrowsePoll host.domain.com:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowsePoll</CODE> collecte la liste des
+ imprimantes disponibles sur un serveur une fois toutes les <A HREF="#BrowseInterval">
+<CODE>BrowseInterval</CODE></A> secondes. Plusieurs directives <CODE>
+BrowsePoll</CODE> peuvent &ecirc;tre indiqu&eacute;es pour surveiller plusieurs
+ serveurs.</P>
+<P>Si <CODE>BrowseInterval</CODE> est mis &agrave; 0 alors le serveur est
+ surveill&eacute; une fois toutes les 30 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowsePort">BrowsePort</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowsePort 631
+BrowsePort 9999
+</PRE>
+</UL>
+<H4>Description</H4>
+<P> La directive <CODE>BrowsePort</CODE> indique un num&eacute;ro de port UDP &agrave;
+ employer pour les &eacute;changes de paquets d'exploration. La valeur
+ implicite est 631.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Vous devez choisir une valeur identique pour la directive <CODE>
+BrowsePort</CODE> sur tous les syst&egrave;mes que vous voulez voir.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseProtocols</CODE> indique les protocoles &agrave;
+ employer pour collecter et distribuer les informations sur les
+ imprimantes partag&eacute;es sur le r&eacute;seau local. Le protocole implicite est <CODE>
+CUPS</CODE>, c'est un protocole bas&eacute; sur la diffusion r&eacute;seau
+ (&quot;broadcast&quot;).
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Lorsque vous utilisez le protocole <CODE>SLP</CODE>, vous devez avoir
+ au moins un serveur &quot;Directory Agent&quot; (DA) sur votre r&eacute;seau. A d&eacute;faut,
+ l'ordonnanceur CUPS (<CODE>cupsd</CODE>) ne r&eacute;pondra pas aux requ&ecirc;tes
+ des clients pendant plusieurs secondes pendant qu'il sera en train
+ d'explorer le r&eacute;seau.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseRelay">BrowseRelay</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseRelay 193.0.2.1 192.0.2.255
+BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
+BrowseRelay 193.0.2.0/24 192.0.2.255
+BrowseRelay *.domain.com 192.0.2.255
+BrowseRelay host.domain.com 192.0.2.255
+</PRE>
+</UL>
+<H4>Description</H4>
+<P> la directive indique des adresses source et destination pour relayer
+ les informations d'exploration en provenance d'un h&ocirc;te ou d'un r&eacute;seau
+ vers un autre. Plusieurs directives <CODE>BrowseRelay</CODE> peuvent
+ &ecirc;tre indiqu&eacute;es si n&eacute;cessaire.</P>
+<P><CODE>BrowseRelay</CODE> est g&eacute;n&eacute;ralement utilis&eacute; sur des syst&egrave;mes
+ qui assurent la passerelle entre des r&eacute;seaux multiples au moyen d'une
+ ou plusieurs interfaces r&eacute;seau. Elle peut &eacute;galement &ecirc;tre utilis&eacute;e pour
+ relayer des informations sur les imprimantes provenant de serveurs
+ surveill&eacute;s, au moyen de la ligne:</P>
+<UL>
+<PRE>
+BrowseRelay 127.0.0.1 255.255.255.255
+</PRE>
+</UL>
+<P>Cela fournit un acc&egrave;s effectif aux imprimantes d'un WAN pour tous les
+ clients d'un LAN.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseShortNames">BrowseShortNames</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseShortNames Yes
+BrowseShortNames No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseShortNames</CODE> indique s'il faut ou non
+ utiliser les noms courts pour les imprimantes &agrave; distance. Les noms
+ courts sont simplement compos&eacute;s du nom de l'imprimante, sans celui du
+ serveur (&quot;imprimante&quot;). Si le syst&egrave;me d&eacute;tecte plus d'une imprimante &agrave;
+ distance portant le m&ecirc;me nom, les imprimantes seront affich&eacute;es avec les
+ noms longs (&quot;imprimante@erveur1&quot;, &quot;imprimante@erveur2&quot;)</P>
+<P>La valeur implicite de cette option est <CODE>Yes</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseTimeout">BrowseTimeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseTimeout 300
+BrowseTimeout 60
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseTimeout</CODE> fixe la dur&eacute;e de vie des
+ informations re&ccedil;ues sous forme de paquets d'exploration et concernant
+ les imprimantese et les classes. Une fois que les informations
+ concernant une imprimante ou une classe d&eacute;passent ce d&eacute;lai, elles sont
+ retir&eacute;es de la liste des destinations disponibles.</P>
+<P>La valeur <CODE>BrowseTimeout</CODE> devrait toujours &ecirc;tre sup&eacute;rieure
+ &agrave; la valeur <A HREF="#BrowseInterval"> <CODE>BrowseInterval</CODE></A>.
+ Sinon des imprimantes et des classes pourraient dispara&icirc;tres des
+ syst&egrave;mes clients entre les mises &agrave; jour.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Browsing">Browsing</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Browsing On
+Browsing Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Browsing</CODE> contr&ocirc;le l'activation ou non de
+ l'exploration r&eacute;seau des imprimantes. La valeur implicite est <CODE>On</CODE>
+.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Si vous utilisez HP-UX 10.20 sur un sous-r&eacute;seau dont le masque n'est
+ pas sur 24, 16 ou 8 bits, l'exploration des imprimantes (et en fait
+ toute r&eacute;ception d'information diffus&eacute;e) ne fonctionnera pas. Ce
+ probl&egrave;me semble r&eacute;solu dans HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Classification</CODE> fixe le niveau de
+ classification sur le serveur. Lorsque cette option est activ&eacute;e au
+ moins une des pages de garde est forc&eacute;e &agrave; ce niveau et l'information de
+ classification est plac&eacute;e sur chaque page imprim&eacute;e. La valeur implicite
+ est de n'avoir aucun niveau de classification.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ClassifyOverride</CODE> indique si les
+ utilisateurs peuvent outrepasser le niveau de classification du serveur
+ ou non. Lorsque la classification du serveur est activ&eacute;e, les
+ utilisateurs peuvent changer la classification en employant l'option <CODE>
+job-sheets</CODE> et peuvent choisir de n'imprimer qu'une seule page de
+ garde de s&eacute;curit&eacute; avant ou apr&egrave;s le travail d'impression. Si l'option <CODE>
+job-sheets</CODE> est positionn&eacute;e &agrave; la valeur <CODE>none</CODE> alors le
+ niveau de classification implicite du serveur est utilis&eacute;.</P>
+<P>La valeur implicite est de ne pas autoriser les utilisateurs &agrave;
+ outrepasser la classification.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DataDir">DataDir</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DataDir /usr/share/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DataDir</CODE> fixe le r&eacute;pertoire &agrave; employer pour
+ les fichiers de donn&eacute;es.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultCharset">DefaultCharset</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DefaultCharset utf-8
+DefaultCharset iso-8859-1
+DefaultCharset windows-1251
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DefaultCharset</CODE> d&eacute;finit le jeu de caract&egrave;res
+ &agrave; utiliser pour les connexions avec les clients. Le jeu de caract&egrave;re
+ implicite est le jeu <CODE>utf-8</CODE> mais il est outrepass&eacute; par le
+ jeu de caract&egrave;res associ&eacute; &agrave; la langue indiqu&eacute;e par le client ou par la
+ directive <CODE>DefaultLanguage</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DefaultLanguage de
+DefaultLanguage en
+DefaultLanguage es
+DefaultLanguage fr
+DefaultLanguage it
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DefaultLanguage</CODE> d&eacute;finit le langage &agrave;
+ utiliser pour les connexions avec les clients. R&eacute;gler la langue r&egrave;gle
+ &eacute;galement le jeu de caract&egrave;res si un fichier de localisation existe
+ pour celle-ci. La valeur implicite est &quot;en&quot; c'est-&agrave;-dire &quot;anglais&quot;.
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="Deny">Deny</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Deny from All
+Deny from None
+Deny from *.domain.com
+Deny from .domain.com
+Deny from host.domain.com
+Deny from nnn.*
+Deny from nnn.nnn.*
+Deny from nnn.nnn.nnn.*
+Deny from nnn.nnn.nnn.nnn
+Deny from nnn.nnn.nnn.nnn/mm
+Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Deny</CODE> indique un nom d'h&ocirc;te, une adresse IP
+ ou un r&eacute;seau qui n'est pas autoris&eacute; &agrave; acc&eacute;der au serveur. Les
+ directives <CODE>Deny</CODE> se cumulent, ainsi plusieurs directives <CODE>
+Deny</CODE> peuvent &ecirc;tre utilis&eacute;es pour interdire l'acc&egrave;s &agrave; de multiples
+ h&ocirc;tes et/ou r&eacute;seaux. La notation <CODE>/mm</CODE> indique une notation
+ de sous-r&eacute;seau CIDR:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+ mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+ 8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+ 16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+ 24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+ 32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La directive <CODE>Deny</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur d'une
+ directive <A HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DocumentRoot">DocumentRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DocumentRoot /usr/share/doc/cups
+DocumentRoot /foo/bar/doc/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DocumentRoot</CODE> indique l'emplacement du
+ contenu que le serveur HTTP de CUPS doit publier. Si un chemin absolu
+ n'est pas indiqu&eacute;, celui-ci est consid&eacute;r&eacute; comme relatif au r&eacute;pertoire <A
+HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>. La valeur implicite est<VAR>
+ /usr/share/doc/cups</VAR>.</P>
+<P>Les documents sont d'abord recherch&eacute;s dans un sous-r&eacute;pertoire
+ correspondant &agrave; la langue demand&eacute;e par le client (par exemple<VAR>
+ /usr/share/doc/cups/fr/...</VAR>) et ensuite directement dans le
+ r&eacute;pertoire <CODE>DocumentRoot</CODE> (par exemple<VAR>
+ /usr/share/doc/cups/...</VAR>), ainsi il est possible de localiser le
+ contenu &quot;web&quot; en fournissant des sous-r&eacute;pertoires pour chaque langue
+ n&eacute;cessaire.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+Encryption Always
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Encryption</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur
+ d'une section <A HREF="#Location"><CODE>Location</CODE></A> et d&eacute;finit
+ les r&eacute;glages d'encryptage pour cet emplacement. Le r&eacute;glage implicite
+ est <CODE>IfRequested</CODE> pour tous les emplacements.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ErrorLog">ErrorLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ErrorLog /var/log/cups/error_log
+ErrorLog /var/log/cups/error_log-%s
+ErrorLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ErrorLog</CODE> d&eacute;finit le nom du fichier de suivi
+ d'erreurs (&quot;error log&quot;). Si le nom de fichier n'est pas un chemin
+ absolu, il est consid&eacute;r&eacute; comme un chemin relatif au r&eacute;pertoire <A HREF="#ServerRoot">
+ <CODE>ServerRoot</CODE></A>. Le fichier standard est<VAR>
+ /var/log/cups/error_log</VAR>.</P>
+<P>Le nom du serveur peut &ecirc;tre inclus dans le nom du fichier en
+ utilisant le nom <CODE>%s</CODE>.</P>
+<P>Le nom sp&eacute;cial &quot;syslog&quot; peut &ecirc;tre utilis&eacute; pour envoyer les
+ informations de suivi d'erreurs vers le fichier de suivi d'erreur
+ syst&egrave;me au lieu d'un fichier texte simple.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FilterLimit">FilterLimit</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+FilterLimit 0
+FilterLimit 200
+FilterLimit 1000
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>FilterLimit</CODE> d&eacute;finit le co&ucirc;t maximal de tous
+ les filtres appliqu&eacute;s au travaux en cours de traitement. Elle peut &ecirc;tre
+ utilis&eacute;e pour limiter le nombre de programmes de filtres qui son
+ ex&eacute;cut&eacute;s dans un serveur pour minimiser les probl&egrave;mes de ressources
+ disque, m&eacute;moire ou CPU. Une limite de 0 d&eacute;sactive la limitation des
+ filtres.</P>
+<P>Le co&ucirc;t moyen d'une impression vers une imprimante non-PostScript
+ n&eacute;cessite une limitation de filtre aux alentours de 200. Une imprimante
+ PostScript n&eacute;cessite une limite d'environ la moiti&eacute; (100). Positionner
+ la limite en dessous de ces seuils va effectivement limiter
+ l'ordonnanceur &agrave; l'impression d'un travail &agrave; la fois.</P>
+<P>La valeur implicite est 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FontPath">FontPath</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+FontPath /foo/bar/fonts
+FontPath /usr/share/cups/fonts:/foo/bar/fonts
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>FontPath</CODE> d&eacute;finit le chemin de recherche des
+ polices de caract&egrave;res &agrave; utiliser. La valeur implicite est <CODE>
+/usr/share/cups/fonts</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Group">Group</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Group sys
+Group system
+Group root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Group</CODE> d&eacute;finit le groupe UNIX sous
+ l'identit&eacute; duquel les programmes CGI et de filtrage fonctionnent. Le
+ groupe implicite est <CODE>sys</CODE>, <CODE>system</CODE>, ou <CODE>
+root</CODE> selon le syst&egrave;me d'exploitation.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>HideImplicitMembers</CODE> contr&ocirc;le l'appartenance
+ ou non d'imprimantes individuelles aux classes implicites qui sont
+ montr&eacute;es &agrave; l'utilisateur. La valeur standard est <CODE>No</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> doit &ecirc;tre
+ activ&eacute;e pour que cette directive ait un quelconque effet.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+HostNameLookups On
+HostNameLookups Off
+HostNameLookups Double
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>HostNameLookups</CODE> indique si CUPS doit ou non
+ rechercher le nom d'h&ocirc;te des clients qui se connectent. La clause <CODE>
+Double</CODE> force CUPS &agrave; v&eacute;rifier que le nom d'h&ocirc;te trouv&eacute; &agrave; partir de
+ l'adresse correspond bien &agrave; l'une des adresses retourn&eacute;es pour ce nom
+ d'h&ocirc;te. Les recherches <CODE>Double</CODE> emp&ecirc;chent &eacute;galement que des
+ clients ayant des adresses non enregistr&eacute;es ne se connectent au
+ serveur. La valeur implicite est <CODE>Off</CODE> pour &eacute;viter tout
+ probl&egrave;me potentiel de performance du serveur du fait des r&eacute;solutions de
+ nom. Positionnez cette directive &agrave; la valeur <CODE>On</CODE> ou <CODE>
+Double</CODE> uniquement si n&eacute;cessaire.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ImplicitClasses">ImplicitClasses</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ImplicitClasses On
+ImplicitClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ImplicitClasses</CODE> contr&ocirc;le si les classes
+ implicites sont cr&eacute;&eacute;es sur la base des imprimantes et classes
+ disponibles sur le r&eacute;seau. La valeur implicite est <CODE>On</CODE> mais
+ est automatiquement positionn&eacute;e sur <CODE>Off</CODE> si <A HREF="#Browsing">
+<CODE>Browsing</CODE></A> est &agrave; la valeur <CODE>Off</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ImplicitAnyClasses</CODE> contr&ocirc;le si oui ou non
+ les classes implicites pour les imprimantes locales et &agrave; distance sont
+ cr&eacute;es avec le nom <CODE>AnyPrinter</CODE>. La valeur implicite est <CODE>
+Off</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> doit &ecirc;tre
+ activ&eacute;e pour que cette directive ait un quelconque effet.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Include filename
+Include /foo/bar/filename
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Include</CODE> inclut le fichier indiqu&eacute; dans le
+ corps du fichier <CODE>cupsd.conf</CODE>. Si aucun chemin n'est
+ indiqu&eacute;, le fichier est consid&eacute;r&eacute; comme &eacute;tant relatif au r&eacute;pertoire <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A>.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="KeepAlive">KeepAlive</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+KeepAlive On
+KeepAlive Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>KeepAlive</CODE> contr&ocirc;le la prise en charge ou
+ non des connexions HTTP persitantes. La valeur implicite est <CODE>On</CODE>
+.</P>
+<P>Les clients HTTP/1.1 prennent automatiquement en charge les
+ connexions persistantes, tandis que clients HTTP/1.0 doivent
+ sp&eacute;cifiquement les demander en utiliser l'attribut <CODE>Keep-Alive</CODE>
+ attribute dans le champ <CODE>Connection:</CODE> de chaque requ&ecirc;te.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="KeepAliveTimeout">KeepAliveTimeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+KeepAliveTimeout 60
+KeepAliveTimeout 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>KeepAliveTimeout</CODE> contr&ocirc;le combien de temps
+ une connexion HTTP persistante restera ouverte apr&egrave;s la derni&egrave;re
+ requ&ecirc;te. La valeur implicite est de 60 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Limit">Limit</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;Limit GET POST&gt;
+...
+&lt;/Limit&gt;
+
+&lt;Limit ALL&gt;
+...
+&lt;/Limit&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Limit</CODE> groupe les directives de contr&ocirc;le
+ d'acc&egrave;s pour certains types sp&eacute;cifiques de requ&ecirc;tes HTTP et doit
+ appara&icirc;tre &agrave; l'int&eacute;rieur d'une section <A HREF="#Location"><CODE>
+Location</CODE></A>. L'acc&egrave;s peut &ecirc;tre limit&eacute; &agrave; des types individuels de
+ requ&ecirc;tes (<CODE>DELETE</CODE>, <CODE>GET</CODE>, <CODE>HEAD</CODE> , <CODE>
+OPTIONS</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE>, et <CODE>TRACE</CODE>
+) ou pour tous les types de requ&ecirc;tes (<CODE>ALL</CODE>). Les noms de
+ types de requ&ecirc;tes sont d&eacute;pendants de la casse pour des raisons de
+ compatibilit&eacute; avec Apache.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitExcept">LimitExcept</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;LimitExcept GET POST&gt;
+...
+&lt;/LimitExcept&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LimitExcept</CODE> groupe les directives de
+ contr&ocirc;le d'acc&egrave;s pour certains types sp&eacute;cifiques de requ&ecirc;tes HTTP et
+ doit appara&icirc;tre &agrave; l'int&eacute;rieur d'une section <A HREF="#Location"> <CODE>
+Location</CODE></A>. Contrairement &agrave; la directive <A HREF="#Limit"><CODE>
+Limit</CODE></A>, <CODE>LimitExcept</CODE> restreint l'acc&egrave;s pour toutes
+ les requ&ecirc;tes<I> &agrave; l'exception</I> de celles list&eacute;es dans la ligne <CODE>
+LimitExcept</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitRequestBody">LimitRequestBody</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+LimitRequestBody 10485760
+LimitRequestBody 10m
+LimitRequestBody 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LimitRequestBody</CODE> contr&ocirc;le la taille
+ maximale des fichiers d'impression, des requ&ecirc;tes IPP, et des donn&eacute;es
+ des formulaires HTML dans les requ&ecirc;tes HTTP POST. La limite implicite
+ est de 0 ce qui d&eacute;sactive la v&eacute;rification de la limite.</P>
+<P>Reportez-vous &eacute;galement &agrave; la directive similaire <A HREF="#MaxRequestSize">
+<CODE>MaxRequestSize</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Listen">Listen</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Listen 127.0.0.1:631
+Listen 192.0.2.1:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Listen</CODE> indique une adresse r&eacute;seau et un
+ port sur lequel &eacute;couter en attente de connexions. Plusieurs directives <CODE>
+Listen</CODE> peuvent &ecirc;tre indiqu&eacute;es pour &eacute;couter sur de multiples
+ adresses.</P>
+<P>La directive <CODE>Listen</CODE> est similaire &agrave; la directive <A HREF="#Port">
+<CODE>Port</CODE></A> mais vous permet de restreindre l'acc&egrave;s &agrave; des
+ interfaces ou des r&eacute;seaux sp&eacute;cifiques.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Location">Location</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;Location /&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /admin&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers/name&gt;
+...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Location</CODE> indique des options de contr&ocirc;le
+ d'acc&egrave;s et d'authentification pour le chemin ou la ressource HTTP
+ indiqu&eacute;e. Des informations suppl&eacute;mentaires sont disponibles plus loin
+ dans le chapitre dans la section <A HREF="#PRINTING_SECURITY">&quot;S&eacute;curit&eacute;
+ du syst&egrave;me d'impression&quot;</A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LogLevel">LogLevel</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+LogLevel none
+LogLevel emerg
+LogLevel alert
+LogLevel crit
+LogLevel error
+LogLevel warn
+LogLevel notice
+LogLevel info
+LogLevel debug
+LogLevel debug2
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LogLevel</CODE> indique la quantit&eacute; d'informations
+ &agrave; consigner dans le fichier <A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A>
+. Les valeurs suivantes sont reconnues (chaque niveau inclut tout ce qui
+ l'est dans les niveaux inf&eacute;rieurs):</P>
+<UL>
+<LI><CODE>none</CODE> - Ne consigne rien.</LI>
+<LI><CODE>emerg</CODE> - Consigne les conditions d'urgence qui emp&ecirc;chent
+ le serveur de fonctionner.</LI>
+<LI><CODE>alert</CODE> - Consigne les alertes qui doivent &ecirc;tre trait&eacute;es
+ imm&eacute;diatement.</LI>
+<LI><CODE>crit</CODE> - Consigne les erreurs critiques qui n'emp&ecirc;chent
+ pas le serveur de fonctionner.</LI>
+<LI><CODE>error</CODE> - Consigne les erreurs g&eacute;n&eacute;rales.</LI>
+<LI><CODE>warn</CODE> - Consigne les erreurs et les avertissements.</LI>
+<LI><CODE>notice</CODE> - Consigne les conditions d'erreurs temporaires.</LI>
+<LI><CODE>info</CODE> - Consigne toutes les requ&ecirc;tes de modifications et
+ de changement d'&eacute;tat (valeur implicite).</LI>
+<LI><CODE>debug</CODE> - Consigne des informations basiques de d&eacute;bogage.</LI>
+<LI><CODE>debug2</CODE> - Consigne toutes les informations de d&eacute;bogage.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClients">MaxClients</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxClients 100
+MaxClients 1024
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxClients</CODE> contr&ocirc;le le nombre maximum de
+ clients simultan&eacute;s qui seront autoris&eacute;s par le serveur. La valeur
+ implicite (&quot;par d&eacute;faut&quot;) est de 100 clients.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Etant donn&eacute; que chaque travail d'impression demande un descripteur de
+ fichier pour le tube de contr&ocirc;le, le serveur CUPS limite de mani&egrave;re
+ interne la valeur <CODE>MaxClients</CODE> au tiers des descripteurs de
+ fichiers disponibles pour &eacute;viter les possibles probl&egrave;mes lors de
+ l'impression de nombreux travaux d'impression.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobs">MaxJobs</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobs 100
+MaxJobs 9999
+MaxJobs 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobs</CODE> contr&ocirc;le le nombre maximum de
+ travaux d'impression qui sont conserv&eacute;s en m&eacute;moire. D&egrave;s que le nombre
+ de travaux atteint la limite, le plus ancien travail compl&eacute;t&eacute; est
+ automatiquement purg&eacute; du syst&egrave;me pour lib&eacute;rer de l'espace pour le
+ nouveau travail. Si tous les travaux connus sont toujours en attente de
+ traitement ou actifs, alors le nouveau travail sera rejet&eacute;.</P>
+<P>R&eacute;gler cette valeur sur 0 (valeur implicite) d&eacute;sactive cette
+ fonctionnalit&eacute;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobsPerPrinter</CODE> contr&ocirc;le le nombre
+ maximum de travaux actifs qui sont autoris&eacute;s pour chaque imprimante ou
+ classe d'imprimantes. D&egrave;s que le nombre est atteint pour une imprimante
+ ou une classe, les nouveaux travaux sont rejet&eacute;s tant que l'un des
+ travaux actifs n'est pas compl&eacute;t&eacute;, arr&ecirc;t&eacute;, annul&eacute; ou abandonn&eacute;.</P>
+<P>R&eacute;gler le maximum sur la valeur 0 (valeur implicite) d&eacute;sactive cette
+ fonctionnalit&eacute;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobsPerUser</CODE> contr&ocirc;le le nombre maximum
+ de travaux d'impression qui sont autoris&eacute;s pour chaque utilisateur. D&egrave;s
+ qu'un utilsateur atteint le maximum autoris&eacute;, tout nouveau travail sera
+ rejet&eacute; avant qu'un des travaux actifs soit compl&eacute;t&eacute;, arr&ecirc;t&eacute;, annul&eacute; ou
+ abandonn&eacute;.</P>
+<P>R&eacute;gler le maximum sur 0 (valeur implicite) d&eacute;sactive cette
+ fonctionnalit&eacute;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxLogSize 1048576
+MaxLogSize 1m
+MaxLogSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxLogSize</CODE> contr&ocirc;le la taille maximum de
+ chaque fichier de suivi (&quot;log&quot;). D&egrave;s qu'un fichier atteint ou d&eacute;passe
+ la limite il est ferm&eacute; ou renomm&eacute; en<VAR> filename.O</VAR>. Cela vous
+ permet de mettre en place automatiquement une rotation des fichiers de
+ suivi. La taille implicite est de 1048576 octets (1Mo).</P>
+<P>R&eacute;gler le maximum sur 0 d&eacute;sactive la rotation de fichier de suivi.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxRequestSize">MaxRequestSize</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxRequestSize 10485760
+MaxRequestSize 10m
+MaxRequestSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxRequestSize</CODE> contr&ocirc;le la taille maximum
+ des fichiers d'impression, des requ&ecirc;tes IPP, et des donn&eacute;es des
+ formulaires HTML contenus dans les requ&ecirc;tes HTTP POST. La valeur
+ implicite est 0, ce qui d&eacute;sactive cette v&eacute;rification de limite.</P>
+<P>Reportez-vous &eacute;galement &agrave; la directive similaire <A HREF="#LimitRequestBody">
+<CODE>LimitRequestBody</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Order">Order</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Order Allow,Deny
+Order Deny,Allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Order</CODE> d&eacute;finit le type implicite de contr&ocirc;le
+ d'acc&egrave;s. Les valeurs suivantes sont prises en charge:</P>
+<UL>
+<LI><CODE>Allow,Deny</CODE> - Autorise les requ&ecirc;tes depuis tous les
+ syst&egrave;mes<I> &agrave; l'exception</I> de ceux list&eacute;s dans une directive <CODE>
+Deny</CODE>.</LI>
+<LI><CODE>Deny,Allow</CODE> - Autorise les requ&ecirc;tes uniquement depuis
+ les h&ocirc;tes list&eacute;s dans une directive <CODE>Allow</CODE>.</LI>
+</UL>
+<P>La directive <CODE>Order</CODE> doit appara&icirc;tre &agrave; l'int&eacute;rieur d'une
+ directive <A HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PageLog">PageLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PageLog /var/log/cups/page_log
+PageLog /var/log/cups/page_log-%s
+PageLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PageLog</CODE> d&eacute;finit le nom du fichier &quot;page
+ log&quot;. Si le nom du fichier n'est pas absolu, il est consid&eacute;r&eacute; comme
+ &eacute;tant relatif au r&eacute;pertoire <A HREF="#ServerRoot"><CODE>ServerRoot</CODE>
+</A>. Le fichier standard &quot;page log&quot; est<VAR> /var/log/cups/page_log</VAR>
+.</P>
+<P>Le nom du serveur peut &ecirc;tre inclus dans le nom de fichier en
+ utilisant le nom <CODE>%s</CODE>.</P>
+<P>Le nom sp&eacute;cial &quot;syslog&quot; peut &ecirc;tre utilis&eacute; pour envoyer les
+ informations de page vers le fichier de suivi syst&egrave;me au lieu d'un
+ simple fichier texte.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Port">Port</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Port 631
+Port 80
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Port</CODE> indique un port sur lequel &eacute;couter en
+ attente de connexions. Plusieurs lignes <CODE>Port</CODE> peuvent &ecirc;tre
+ indiqu&eacute;es pour &eacute;couter sur plusieurs ports. La valeur implicite est
+ 631.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobHistory">PreserveJobHistory</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PreserveJobHistory On
+PreserveJobHistory Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PreserveJobHistory</CODE> contr&ocirc;le si l'historique
+ des travaux compl&eacute;t&eacute;s, annul&eacute;s ou abandonn&eacute;s est conserv&eacute; sur disque ou
+ non.</P>
+<P>Une valeur <CODE>On</CODE> (valeur implicite) conserve les
+ informations concernant les travaux jusqu'&agrave; ce que l'administrateur les
+ purge avec la commande <CODE>cancel</CODE>.</P>
+<P>Une valeur <CODE>Off</CODE> retire les informations concernant les
+ travaux d&egrave;s que ceux-ci sont compl&eacute;t&eacute;s, annul&eacute;s ou abandonn&eacute;s.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobFiles">PreserveJobFiles</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PreserveJobFiles On
+PreserveJobFiles Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PreserveJobFiles</CODE> contr&ocirc;le si les fichiers
+ des documents compl&eacute;t&eacute;s, annul&eacute;s ou abandonn&eacute;s sont stock&eacute;s sur disque.</P>
+<P>La valeur <CODE>On</CODE> conserve les fichiers des travaux jusqu'&agrave;
+ ce que l'administrateur les purge au moyen de la commande <CODE>cancel</CODE>
+. Les travaux peuvent &ecirc;tre resoumis (r&eacute;imprim&eacute;s) jusqu'&agrave; ce qu'ils
+ soient purg&eacute;s.</P>
+<P>La valeur <CODE>Off</CODE> (valeur implicite) retire les fichiers des
+ travaux d&egrave;s ceux-ci sont compl&eacute;t&eacute;s, annul&eacute;s ou abandonn&eacute;s.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Printcap">Printcap</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Printcap
+Printcap /etc/printcap
+Printcap /etc/printers.conf
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Printcap</CODE> contr&ocirc;le si le fichier printcap
+ est automatiquement g&eacute;n&eacute;r&eacute; et mis &agrave; jour ou non avec une liste des
+ imprimantes disponibles. Si la directive est utilis&eacute;e sans valeur,
+ alors aucun fichier printcap ne sera g&eacute;n&eacute;r&eacute;. La valeur implicite est de
+ g&eacute;n&eacute;rer un fichier nomm&eacute;<VAR> /etc/printcap</VAR>.</P>
+<P>Quand un nom de fichier est indiqu&eacute; (par exemple<VAR> /etc/printcap</VAR>
+), le fichier printcap est &eacute;crit d&egrave;s qu'une imprimante est ajout&eacute;e ou
+ supprim&eacute;e. Le fichier printcap peut alors &ecirc;tre utilis&eacute; par les
+ applications dont l'utilisation du fichier printcap comme r&eacute;f&eacute;rence des
+ imprimantes disponibles est cod&eacute;e en dur.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapFormat">PrintcapFormat</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PrintcapFormat BSD
+PrintcapFormat Solaris
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PrintcapFormat</CODE> contr&ocirc;le le format de sortie
+ du fichier printcap. Le comportement implicite est de g&eacute;n&eacute;rer un
+ fichier printcap de type BSD.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapGUI">PrintcapGUI</A></H3>
+<HR>
+<H4>Example</H4>
+<UL>
+<PRE>
+PrintcapGUI /usr/bin/glpoptions
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PrintcapGUI</CODE> indique le programme &agrave; utiliser
+ pour afficher le panneau d'options &agrave; partir d'une application IRIX qui
+ utiliser l'API d'impression Impressario. Le programme implicite est le
+ programme graphique &quot;glpoptions&quot; d'ESP Print Pro.</P>
+<P>Le programme doit accepter l'option <CODE>-d</CODE> pour indiquer
+ l'imprimante et l'option <CODE>-o</CODE> pour indiquer une ou plusieurs
+ options. Apr&egrave;s avoir autoris&eacute; l'utilisateur &agrave; s&eacute;lectionner/changer les
+ options, le programme doit &eacute;crire la liste des options d'impression
+ sans le <CODE>-o</CODE> sur la sortie standard.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RemoteRoot remroot
+RemoteRoot root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RemoteRoot</CODE> fixe le nom d'utilisateur &agrave;
+ utiliser pour les requ&ecirc;tes root non authentifi&eacute;es depuis des h&ocirc;tes
+ distants. Le nom d'utilisateur standard est<VAR> remroot</VAR>. R&eacute;gler <CODE>
+RemoteRoot</CODE> sur<VAR> root</VAR> d&eacute;sactive effectivement ce
+ m&eacute;canisme de s&eacute;curit&eacute;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RequestRoot">RequestRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RequestRoot /var/spool/cups
+RequestRoot /foo/bar/spool/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RequestRoot</CODE> d&eacute;finit le r&eacute;pertoire pour les
+ requ&ecirc;tes entrantes IPP et les formulaires HTML. Si un chemin absolu
+ n'est pas fourni alors il est consid&eacute;r&eacute; comme relatif au r&eacute;pertoire <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A>. Le r&eacute;pertoire implicite est<VAR>
+ /var/spool/cups</VAR>.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Require">Require</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Require group foo bar
+Require user john mary
+Require valid-user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Require</CODE> indique que l'authentification est
+ n&eacute;cessaire pour l'acc&egrave;s &agrave; la ressource consid&eacute;r&eacute;e. Le mot clef <CODE>
+group</CODE> indique que l'utilisateur authentifi&eacute; doit &ecirc;tre membre d'un
+ ou plusieurs des groupes qui suivent.</P>
+<P>Le mot clef <CODE>user</CODE> indique que l'utilisateur authentifi&eacute;
+ doit &ecirc;tre l'un des utilisateurs dont les noms suivent.</P>
+<P>Le mot clef <CODE>valid-user</CODE> indique que tout utilisateur
+ authentifi&eacute; peut acc&eacute;der &agrave; la ressource.</P>
+<P>Le comportement implicite (&quot;par d&eacute;faut&quot;) est de ne faire aucune
+ authentification. Cette directive doit appara&icirc;tre &agrave; l'int&eacute;rieur d'une
+ directive <A HREF="#Location"><CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RIPCache">RIPCache</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RIPCache 8m
+RIPCache 1g
+RIPCache 2048k
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RIPCache</CODE> d&eacute;finit la quantit&eacute; de m&eacute;moire
+ utilis&eacute;e par les filtres RIP (&quot;Raster Images Processor&quot;) tels que <CODE>
+imagetoraster</CODE> et <CODE>pstoraster</CODE>. La taille peut &ecirc;tre
+ suffix&eacute;e par &quot;k&quot; pour kilo-octets, &quot;m&quot; pour m&eacute;ga-octets, ou &quot;g&quot; pour
+ giga-octets. La taille implicite est de &quot;8m&quot;, ou 8 m&eacute;ga-octets.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RunAsUser">RunAsUser</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RunAsUser Yes
+RunAsUser No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RunAsUser</CODE> contr&ocirc;le si l'ordonnanceur
+ fonctionne sous l'identit&eacute; d'un compte utilisateur non privil&eacute;gi&eacute;
+ (habituellement <CODE>lp</CODE>). La valeur implicite est <CODE>No</CODE>
+ qui laisse l'utilisateur fonctionner en tant qu'utilisateur <CODE>root</CODE>
+.</P>
+<P><B>Note:</B> Faire fonctionner CUPS en tant qu'utilisateur non
+ privil&eacute;gi&eacute; peut emp&ecirc;cher LPD et les imprimantes connect&eacute;es localement
+ de fonctionner correctement en raison de probl&egrave;mes de permissions. Le
+ programme d'arri&egrave;re-plan <CODE>lpd</CODE> utilisera automatiquement le
+ mode non privil&eacute;gi&eacute; ce qui est 100% conforme &agrave; la RFC 1179. Les
+ programmes d'arri&egrave;re-plan <CODE>parallel</CODE>, <CODE>serial</CODE>,
+ et <CODE>usb</CODE> auront besoin d'acc&egrave;s en &eacute;criture aux fichiers de
+ p&eacute;riph&eacute;riques correspondants.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Satisfy">Satisfy</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Satisfy all
+Satisfy any
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Satisfy</CODE> indique si toutes les conditions
+ doivent &ecirc;tre satisfaites pour ouvrir l'acc&egrave;s &agrave; la ressource. Si la
+ valeur est <CODE>all</CODE> alors toutes les conditions
+ d'authentification et de contr&ocirc;le d'acc&egrave;s doivent &ecirc;tre satisfaites pour
+ que l'acc&egrave;s soit autoris&eacute;.</P>
+<P>R&eacute;gler <CODE>Satisfy</CODE> &agrave; la valeur <CODE>any</CODE> autorise un
+ utilisateur &agrave; obtenir l'acc&egrave;s si l'authentification ou le contr&ocirc;le
+ d'acc&egrave;s est satisfait. Par exemple, vous pourriez exiger
+ l'authentifiation pour l'acc&egrave;s &agrave; distance mais autoriser l'acc&egrave;s local
+ sans elle.</P>
+<P>La valeur implicite est <CODE>all</CODE>. Cette directive doit
+ appara&icirc;tre &agrave; l'int&eacute;rieur d'une directive <A HREF="#Location"> <CODE>
+Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerAdmin">ServerAdmin</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerAdmin user@host
+ServerAdmin root@foo.bar.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerAdmin</CODE> identifie l'adresse de courriel
+ de l'administrateur du syst&egrave;me. La valeur implicite est <CODE>
+root@serveur</CODE>, o&ugrave; <CODE>server</CODE> est le nom du serveur.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerBin">ServerBin</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerBin /usr/lib/cups
+ServerBin /foo/bar/lib/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerBin</CODE> d&eacute;finit le r&eacute;pertoire contenant
+ les fichiers ex&eacute;cutables du serveur. Si un chemin absolu n'est pas
+ indiqu&eacute;, il est consid&eacute;r&eacute; comme relatif au r&eacute;pertoire <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A> . Le r&eacute;pertoire implicite est<VAR>
+ /usr/lib/cups</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerCertificate">ServerCertificate</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerCertificate /etc/cups/ssl/server.crt
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerCertificate</CODE> d&eacute;finit l'emplacement du
+ fichier de certificat SSL utilis&eacute; par le serveur lors de la n&eacute;gociation
+ des connexions encrypt&eacute;es. Le certificat ne doit pas &ecirc;tre encrypt&eacute;
+ (prot&eacute;g&eacute; par un mot de passe) car l'ordonnanceur fonctionne normalement
+ en arri&egrave;re-plan et et ne sera pas en mesure de demander un mot de
+ passe. Le fichier standard de certificat est<VAR>
+ /etc/cups/ssl/server.crt</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerKey">ServerKey</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerKey /etc/cups/ssl/server.key
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerKey</CODE> indique l'emplacement du fichier
+ de cl&eacute; priv&eacute;e SSL utilis&eacute; par le serveur pour n&eacute;gocier les connexions
+ encrypt&eacute;es. Le fichier standard de cl&eacute; est<VAR>
+ /etc/cups/ssl/server.crt</VAR> .
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerName"></A>ServerName</H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerName foo.domain.com
+ServerName myserver.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerName</CODE> indique le nom d'h&ocirc;te qui doit
+ &ecirc;tre envoy&eacute; aux clients. En standard, le nom du serveur est le nom
+ d'h&ocirc;te.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerRoot">ServerRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerRoot /etc/cups
+ServerRoot /foo/bar/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerRoot</CODE> indique un chemin absolu pour
+ les fichiers de configuration et d'&eacute;tat du serveur. Il est &eacute;galement
+ utilis&eacute; pour interpr&eacute;ter les chemins relatifs pr&eacute;sents dans le fichier<VAR>
+ cupsd.conf</VAR> file. Le r&eacute;pertoire standard est<VAR> /etc/cups</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLListen">SSLListen</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SSLListen 127.0.0.1:443
+SSLListen 192.0.2.1:443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SSLListen</CODE> indique une adresse r&eacute;seau et un
+ port sur lequel &eacute;couter les tentatives de connexion s&eacute;curis&eacute;es.
+ Plusieurs directives <CODE>SSLListen</CODE> peuvent &ecirc;tre fournies pour
+ indiquer plusieurs adresses sur lesquelles &eacute;couter.</P>
+<P>La directive <CODE>SSLListen</CODE> est similaire &agrave; la directive <A HREF="#SSLPort">
+<CODE>SSLPort</CODE></A> mais vous permet de restreindre l'acc&egrave;s &agrave;
+ certaines interfaces ou r&eacute;seaux.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLPort">SSLPort</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SSLPort 443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SSLPort</CODE> indique le port sur lequel &eacute;couter
+ les tentatives de connexions s&eacute;curis&eacute;es. Plusieurs lignes <CODE>SSLPort</CODE>
+ peuvent &ecirc;tre indiqu&eacute;es pour &eacute;couter les connexions sur plusieurs ports.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SystemGroup">SystemGroup</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SystemGroup sys
+SystemGroup system
+SystemGroup root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SystemGroup</CODE> indique le groupe syst&egrave;me
+ d'aministration pour l'authentification de type <CODE>System</CODE>.
+ Plus d'information peut &ecirc;tre trouv&eacute;e plus loin dans ce chapitre dans la
+ section <A HREF="#PRINTING_SECURITY">&quot;S&eacute;curit&eacute; du syst&egrave;me d'impression&quot;</A>
+.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="TempDir">TempDir</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+TempDir /var/tmp
+TempDir /foo/bar/tmp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>TempDir</CODE> indique un chemin absolu pour le
+ r&eacute;pertoire &agrave; employer pour les fichiers temporaires. Le r&eacute;pertoire
+ standard est<VAR> /var/tmp</VAR>.</P>
+<P>Les r&eacute;pertoires temporaires doivent &ecirc;tre inscriptibles pour tous et
+ devraient avoir le &quot;sticky&quot; bit activ&eacute; de sorte que les utilisateurs ne
+ puissent pas supprimer les fichiers temporaires de filtres. Les
+ commandes suivantes cr&eacute;erons un r&eacute;pertoire temporaire appropri&eacute; appel&eacute;<VAR>
+ /foo/bar/tmp</VAR>:</P>
+<UL>
+<PRE>
+<B>mkdir /foo/bar/tmp ENTREE</B>
+<B>chmod a+rwxt /foo/bar/tmp ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Timeout">Timeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Timeout 300
+Timeout 90
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Timeout</CODE> d&eacute;finit le d&eacute;lai &agrave; attendre avant
+ qu'une requ&ecirc;te HTTP ou IPP active ne soit hors d&eacute;lai. La valeur
+ implicite est de 300 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="User">User</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+User lp
+User guest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>User</CODE> indique l'utilisateur UNIX sous
+ l'identit&eacute; duquel les programmes CGI et les filtres doivent
+ fonctionner. La valeur implicite est <CODE>lp</CODE>.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="PRINTING_SECURITY">S&eacute;curit&eacute; du syst&egrave;me d'impression</A></H2>
+<P>CUPS prend en charge le contr&ocirc;le d'acc&egrave;s et l'authentification bas&eacute;e
+ sur l'adresse, un certificat ou un mot de passe (mode &quot;Basic&quot; et
+ &quot;Digest&quot;). Les authentifications par mot de passe et certificat
+ fournissent des moyens de limiter l'acc&egrave;s &agrave; certaines personnes ou
+ certains groupes.</P>
+<P>Le contr&ocirc;le d'acc&egrave;s bas&eacute; sur l'adresse vous permet de limiter l'acc&egrave;s
+ &agrave; certains syst&egrave;mes, r&eacute;seaux ou domaines particuliers. Bien que cela ne
+ soit pas de l'authentification, cela vous permet de restreindre
+ efficacement le nombre potentiel d'utilisateurs de votre syst&egrave;me.</P>
+<P>CUPS maintient &agrave; jour une liste des emplacements dont
+ l'authentification et/ou le contr&ocirc;le d'acc&egrave;s est/sont activ&eacute;(e)(s). Ces
+ emplacements sont indiqu&eacute;s en utilisant la directive <A HREF="#Location">
+<CODE>Location</CODE></A>:</P>
+<UL>
+<PRE>
+&lt;Location /ressource&gt;
+<A HREF="#AuthClass">AuthClass</A> ...
+<A HREF="#AuthGroupName">AuthGroupName</A> ...
+<A HREF="#AuthType">AuthType</A> ...
+
+<A HREF="#Order">Order</A> ...
+<A HREF="#Allow">Allow</A> from ...
+<A HREF="#Deny">Deny</A> from ...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>Les emplacements suivent g&eacute;n&eacute;ralement la structure arborescente du
+ contenu du r&eacute;pertoire <A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A>
+, cependant CUPS poss&egrave;de de nombreux emplacements virtuels pour
+ l'administration, les classes, les travaux d'impression et les
+ imprimantes:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH>Emplacement</TH><TH>Description</TH></TR>
+<TR><TD>/admin</TD><TD>Le chemin pour toutes les op&eacute;rations
+ d'administration.</TD></TR>
+<TR><TD>/classes</TD><TD>Le chemin pour toutes les classes
+ d'imprimantes.</TD></TR>
+<TR><TD>/classes/nom_classe</TD><TD>Les ressources pour la classe nomm&eacute;e
+ <CODE>nom_classe</CODE>.</TD></TR>
+<TR><TD>/jobs</TD><TD>Le chemin pour tous les travaux d'impression.</TD></TR>
+<TR><TD>/jobs/id</TD><TD>Les ressources pour le travail d'impression n&deg;<CODE>
+id</CODE>.</TD></TR>
+<TR><TD>/printers</TD><TD>Le chemin pour toutes les imprimantes.</TD></TR>
+<TR><TD>/printers/nom_imprimante</TD><TD>Le chemin pour l'imprimante
+ nomm&eacute;e <CODE>nom_imprimante</CODE>.</TD></TR>
+<TR><TD>/printers/nom_imprimante.ppd</TD><TD>Le chemin du fichier PPD
+ pour l'imprimante <CODE>nom_imprimante</CODE>.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="CERTIFICATES">Authentification bas&eacute;e sur les certificats</A>
+</H3>
+<P>CUPS prend en charge une authentification locale bas&eacute;e sur les
+ certificats qui peut &ecirc;tre utilis&eacute;e &agrave; la place des authentifications
+ &quot;Basic&quot; et &quot;Digest&quot; pour les clients se connectant &agrave; l'interface <CODE>
+localhost</CODE>. L'authentification par certificats n'est ni prise en
+ charge, ni permise pour les clients se connectant par le biais de toute
+ autre interface.</P>
+<P>Les certificats sont des nombres al&eacute;atoires cod&eacute;s sur 128 bits qui
+ font r&eacute;f&eacute;rence &agrave; un enregistrement interne d'authentification sur le
+ serveur. Un client se connectant via l'interface <CODE>localhost</CODE>
+ envoie une requ&ecirc;te avec un en-t&ecirc;te d'autorisation:</P>
+<UL>
+<PRE>
+Authorization: Local 0123456789ABCDEF0123456789ABCDEF
+</PRE>
+</UL>
+<P>Le serveur v&eacute;rifie alors le certificat local correspondant et
+ authentifie le nom d'utilisateur qui y est associ&eacute;.</P>
+<P>Les certificats sont automatiquement g&eacute;n&eacute;r&eacute;s par le serveur et
+ stock&eacute;s dans le r&eacute;pertoire<VAR> /etc/cups/certs</VAR> en utilisant le
+ n&deg; de processus du programme CGI (&quot;process ID&quot;) ex&eacute;cut&eacute; par le serveur.
+ Les fichiers de certificats sont en lecture seule pour les utilisateurs
+ <A HREF="#User"><CODE>User</CODE></A> et groupes <A HREF="#Group"><CODE>
+Group</CODE></A> d&eacute;finis dans le fichier<VAR> cupsd.conf</VAR>. Quand le
+ programme CGI se termine, le certificat est retir&eacute; et rendu
+ automatiquement invalide.</P>
+<P>Le fichier sp&eacute;cial<VAR> /etc/cups/certs/0</VAR> d&eacute;finit le<I>
+ certificat de root</I> qui peut &ecirc;tre utilis&eacute; par tout client
+ fonctionnant sous l'identit&eacute; du super-utilisateur et qui appartient au
+ group d&eacute;fini par la directive <A HREF="#SystemGroup"><CODE>SystemGroup</CODE>
+</A>. Le certificat de root est automatiquement r&eacute;g&eacute;n&eacute;r&eacute; toutes les 5
+ minutes.</P>
+<H3><A NAME="7_5_2">Utilisation de l'authentification &quot;Basic&quot;</A></H3>
+<P>L'authentification &quot;Basic&quot; utilise les utilisateurs et mots de passe
+ UNIX pour authentifier l'acc&egrave;s &agrave; des ressources telles que les
+ imprimantes ou les classes et pour limiter l'acc&egrave;s aux fonctions
+ d'administration.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>L'authentification &quot;Basic&quot; transmet le nom d'utilisateur et le mot de
+ passe en clair (encodage Base64) du client vers le serveur, donc elle
+ n'offre aucune protection contre l'espionnage. Cela signifie qu'une
+ utilisateur mal intentionn&eacute; peut &eacute;couter les paquets r&eacute;seau et
+ d&eacute;couvrir ces informations. Il peut en r&eacute;sulter une s&eacute;rieuse
+ compromission de la s&eacute;curit&eacute; de votre r&eacute;seau. Utilisez
+ l'authentification avec la plus grande prudence.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>L'impl&eacute;mentation de l'authentification &quot;Basic&quot; dans CUPS ne permet
+ pas l'acc&egrave;s en utilisant des comptes sans mot de passe. Si vous tentez
+ d'authentifier un tel compte, l'acc&egrave;s sera imm&eacute;diatement bloqu&eacute;.</P>
+<P>Une fois le nom d'utilisateur et le mot de passe authentifi&eacute;s par
+ CUPS, les contraintes suppl&eacute;mentaires d'appartenance &agrave; des groupes sont
+ v&eacute;rifi&eacute;es
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Pour CUPS, l'utilisateur root est consid&eacute;r&eacute; comme membre de tous les
+ groupes.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 1in -->
+</P>
+<P>Utilisez la directive <CODE>AuthType</CODE> pour activer
+ l'authentification &quot;Basic&quot;:</P>
+<UL>
+<PRE>
+AuthType Basic
+</PRE>
+</UL>
+
+<!-- NEED 7in -->
+<H3><A NAME="7_5_3">Utilisation de l'authentification &quot;Digest&quot;</A></H3>
+<P>L'authentification &quot;Digest&quot; utilise des utilisateurs et mots de passe
+ d&eacute;finis dans le fichier<VAR> /etc/cups/passwd.md5</VAR> pour
+ authentifier l'acc&egrave;s aux ressources telles que les imprimantes et les
+ classes et pour limiter l'acc&egrave;s aux fonctions d'administration.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Contrairement &agrave; l'authentification &quot;Basic&quot;, &quot;Digest&quot; transmet une
+ version cod&eacute;e du nom d'utilisateur et du mot de passe en utilisant le
+ codage MD5 (en r&eacute;sum&eacute;, une somme de contr&ocirc;le compliqu&eacute;e) au lieu de
+ leur version en clair. De plus, l'authentification &quot;Digest&quot; n'utilise
+ pas les utilisateurs et mots de passe UNIX, ainsi si un attaquant
+ d&eacute;couvre le mot de passe original il est moins probable qu'il en
+ r&eacute;sulte un probl&egrave;me de s&eacute;curit&eacute;, pour peu que vous utilisiez un mot de
+ passe &quot;Digest&quot; diff&eacute;rent de celui stock&eacute; par UNIX.</P>
+<P>L'impl&eacute;mentation actuelle de l'authenfication &quot;Digest&quot; dans CUPS
+ utilise le nom d'h&ocirc;te du client ou son adresse IP comme valeur &quot;nonce&quot;.
+ La valeur &quot;nonce&quot; est une cha&icirc;ne de caract&egrave;res additionnelle ajout&eacute;e au
+ nom d'utilisateur et au mot de passe pour rendre la d&eacute;couverte de ce
+ dernier plus difficile. Le serveur v&eacute;rifie que la valeur &quot;nonce&quot;
+ correspond au nom d'h&ocirc;te ou l'adresse IP du client et, si tel n'est pas
+ le cas, rejette la somme MD5 propos&eacute;e par celui-ci. Les prochaines
+ versions de CUPS prendront en charge l'authentification &quot;Digest&quot; par
+ &quot;session&quot; qui ajoutera les donn&eacute;es de la requ&ecirc;te &agrave; la somme MD5,
+ fournissant ainsi une s&eacute;curit&eacute; et une authentification encore
+ meilleures.</P>
+<P>L'authentification &quot;Digest&quot; ne garantit pas qu'un attaquant ne peut
+ pas obtenir un acc&egrave;s non autoris&eacute; mais elle est plus s&ucirc;re que
+ l'authentification &quot;Basic&quot; et devrait &ecirc;tre utilis&eacute;e &agrave; la place de
+ celle-ci chaque fois que c'est possible.<B> La prise en charge de
+ l'authentification &quot;Digest&quot; dans les navigateurs &quot;web&quot; n'est pas encore
+ universellement disponible.</B></P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 2in -->
+</P>
+<P>La commande <CODE>lppasswd(1)</CODE> est utilis&eacute;e pour ajouter,
+ changer et retirer des comptes du fichier<VAR> passwd.md5</VAR>. Pour
+ ajouter un utilisateur au groupe syst&egrave;me standard, tapez:</P>
+<UL>
+<PRE>
+<B>lppasswd -a utilisateur ENTREE</B>
+Password: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Une fois ajout&eacute;, un utilisateur peut changer son mot de passe en
+ tapant:</P>
+<UL>
+<PRE>
+<B>lppasswd ENTREE</B>
+Old Password: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+Password : <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>Pour retirer un utilisateur du fichier des mots de passe, tapez:</P>
+<UL>
+<PRE>
+<B>lppasswd -x utilisateur ENTREE</B>
+</PRE>
+</UL>
+<P>Une fois qu'un utilisateur et un mot de passe valides ont &eacute;t&eacute;
+ authentifi&eacute;s pas CUPS, celui-ci v&eacute;rifie les contraintes suppl&eacute;mentaires
+ d'appartenance &agrave; des groupes.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Pour CUPS, l'utilisateur root est membre de tous les groupes.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>Utilisez la directive <CODE>AuthType</CODE> pour activer
+ l'authentification &quot;Digest&quot;:</P>
+<UL>
+<PRE>
+AuthType Digest
+</PRE>
+</UL>
+<H3><A NAME="7_5_4">Authentifications &quot;System&quot; et &quot;Group&quot;</A></H3>
+<P>La directive <A HREF="#AuthClass"><CODE>AuthClass</CODE></A> contr&ocirc;le
+ le niveau d'authentification &agrave; effectuer. Les authentifications <CODE>
+System</CODE> et <CODE>Group</CODE> ajoutent &agrave; l'authentification
+ normale bas&eacute;e sur l'utilisateur une contrainte d'appartenance &agrave; un
+ groupe UNIX. Pour l'authentification <CODE>System</CODE>, chaque
+ utilisateur doit &ecirc;tre membre du groupe <CODE>sys</CODE>, <CODE>system</CODE>
+, ou <CODE>root</CODE>; le groupe r&eacute;el d&eacute;pend du syst&egrave;me d'exploitation.</P>
+<P>Pour l'authentification <CODE>Group</CODE> l'utilisateur doit &ecirc;tre
+ membre du group indiqu&eacute; par la directive <A HREF="#AuthGroupName"><CODE>
+AuthGroupName</CODE></A>:</P>
+<UL>
+<PRE>
+&lt;Location /path&gt;
+AuthType Digest
+AuthClass Group
+AuthGroupName mygroup
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>Le groupe indiqu&eacute; doit &ecirc;tre un groupe UNIX valide, habituellement
+ d&eacute;fini dans les fichiers<VAR> /etc/group</VAR> ou<VAR> /etc/netgroup</VAR>
+. De plus, lors de l'utilisation de l'authentification &quot;Digest&quot;, vous
+ devez cr&eacute;er les comptes utilisateur avec le groupe indiqu&eacute;:</P>
+<UL>
+<PRE>
+<B>lppasswd -g mon_groupe -a utilisateur ENTER</B>
+Password : <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affich&eacute;]
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTER_ACCOUNTING">Suivi/facturation de travaux et
+ d'imprimantes</A></H2>
+<P>ESP Print Pro maintient &agrave; jour un suivi (&quot;log&quot;) de tous les acc&egrave;s,
+ erreurs et pages qui sont imprim&eacute;es. Les fichiers de suivi sont
+ normalement stock&eacute;s dans le r&eacute;pertoire<VAR> /var/log/cups</VAR>. Vous
+ pouvez changer cela en &eacute;ditant le fichier de configuration<VAR>
+ /etc/cups/cupsd.conf</VAR>.</P>
+<H3><A NAME="7_6_1">Le fichier access_log</A></H3>
+<P>Le fichier<VAR> access_log</VAR> liste chaque ressource HTTP qui est
+ utilis&eacute;e par le serveur &quot;web&quot; ou un client CUPS/IPP. Chaque ligne est
+ structur&eacute;e dans le format habituel utilis&eacute; par de nombreux serveurs
+ &quot;web&quot; et outils d'analyse.:</P>
+<UL>
+<PRE>
+H&ocirc;te Groupe Utilisateur Date/heure \&quot;M&eacute;thode Ressource Version\&quot; Etat Octets
+
+127.0.0.1 - - [20/May/1999:19:20:29 +0000] &quot;POST /admin/ HTTP/1.1&quot; 401 0
+127.0.0.1 - mike [20/May/1999:19:20:31 +0000] &quot;POST /admin/ HTTP/1.1&quot; 200 0
+</PRE>
+</UL>
+<P>Le champ<I> h&ocirc;te</I> ne devrait normalement &ecirc;tre qu'une adresse IP &agrave;
+ moins que vous n'activiez la directive <A HREF="#HostNameLookups"><CODE>
+HostNameLookups</CODE></A> dans le fichier<VAR> cupsd.conf</VAR>.</P>
+<P>Le champ<I> groupe</I> contient toujours &quot;-&quot; dans CUPS.</P>
+<P>Le champ<I> utilisateur</I> est le nom de l'utilisateur authentifi&eacute;
+ qui a &eacute;mis la requ&ecirc;te. Si aucun nom d'utilisateur et mot de passe n'est
+ fourni pour la requ&ecirc;te, alors ce champ contient &quot;-&quot;.</P>
+<P>Le champ<I> date/heure</I> contient la date et l'heure de la requ&ecirc;te
+ exprim&eacute;es dans le fuseau horaire local, et est structur&eacute; de la mani&egrave;re
+ suivante:</P>
+<UL>
+<PRE>
+[JJ/MMM/AAAA:HH:MM:SS +ZZZZ]
+</PRE>
+</UL>
+<P>o&ugrave;<I> ZZZZ</I> est le d&eacute;calage horaire entre le fuseau horaire local
+ et l'heure Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.) (NdT : en
+ r&eacute;alit&eacute; GMT est un abus de langage, il s'agit du temps UTC...)</P>
+<P>Le champ<I> m&eacute;thode</I> est la m&eacute;thode HTTP utilis&eacute;e (&quot;GET&quot;, &quot;PUT&quot;,
+ &quot;POST&quot;, etc.)</P>
+<P>Le champ<I> ressource</I> est le nom du fichier de la ressource
+ demand&eacute;e.</P>
+<P>Le champ<I> version</I> est la version du protocole HTTP employ&eacute; par
+ le client. Pour les clients CUPS, c'est toujours &quot;HTTP/1.1&quot;.</P>
+<P>Le champ<I> Etat</I> contient l'&eacute;tat du r&eacute;sultat HTTP de la requ&ecirc;te.
+ Habituellement, il s'agit de la valeur &quot;200&quot;, mais d'autres codes
+ d'&eacute;tat HTTP sont possibles. Par exemple, 401 est le code d'&eacute;tat pour
+ &quot;acc&egrave;s non autoris&eacute;&quot; dans l'exemple ci-dessus.</P>
+<P>Le champs<I> octets</I> contient le nombre d'octets contenus dans la
+ requ&ecirc;te. Pour les requ&ecirc;tes POST, le champ<I> octets</I> contient le
+ nombre d'octets re&ccedil;us du client.</P>
+<H3><A NAME="7_6_2">Le fichier error_log</A></H3>
+<P>Le fichier<VAR> error_log</VAR> liste les messages provenant de
+ l'ordonnanceur (erreurs, avertissements, etc.):</P>
+<UL>
+<PRE>
+Niveau Date/Heure Message
+
+I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
+</PRE>
+</UL>
+<P>Le champ<I> Niveau</I> contient le type du message:</P>
+<UL>
+<LI><CODE>E</CODE> - Une erreur est survenue.</LI>
+<LI><CODE>W</CODE> - Le serveur a &eacute;t&eacute; incapable d'effectuer une action.</LI>
+<LI><CODE>I</CODE> - Message d'information.</LI>
+<LI><CODE>D</CODE> - Message de d&eacute;bogage.</LI>
+</UL>
+<P>Le champ<I> Date/heure</I> contient la date et l'heure de d&eacute;but
+ d'impression de la page. Le format est identique &agrave; celui du champ<I>
+ Date/heure</I> dans le fichier<VAR> access_log</VAR>.</P>
+<P>Le champ<I> Message</I> contient un message textuel dont la forme est
+ libre.</P>
+<H3><A NAME="7_6_3">Le fichier page_log</A></H3>
+<P>Le fichier<VAR> page_log</VAR> liste chaque page qui est envoy&eacute;e &agrave;
+ une imprimante. Chaque ligne contient les informations suivantes:</P>
+<UL>
+<PRE>
+Imprimante Utilisateur N&deg;travail Date/heure N&deg;Page Nombre_copies Facturation_travail
+
+DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
+</PRE>
+</UL>
+<P>Le champ<I> imprimante</I> contient le nom de l'imprimante qui a
+ imprim&eacute; la page. Si vous envoyez un travail d'impression &agrave; une classe,
+ le champ contient le nom de l'imprimante &agrave; laquelle ce travail a &eacute;t&eacute;
+ affect&eacute;..</P>
+<P>Le champ<I> utilisateur</I> contient le nom de l'utilisateur
+ (l'attribut <CODE>requesting-user-name</CODE> de IPP) qui a envoy&eacute; le
+ fichier &agrave; l'impression.</P>
+<P>Le champ<I> N&deg;Travail</I> contient le n&deg; du travail correspondant &agrave;
+ la page en cours d'impression. Les n&deg; de travaux sont remis &agrave; 1 si le
+ serveur CUPS est red&eacute;marr&eacute;, donc ne le consid&eacute;rez pas comme un
+ identifiant unique !</P>
+<P>Le champ<I> Date/heure</I> contient la date et l'heure de d&eacute;marrage
+ de l'impression dans un format identique au champ<I> Date/heure</I> du
+ fichier<VAR> access_log</VAR>.</P>
+<P>Les champs<I> N&deg;Page</I> et<I> Nombre_copies</I> contiennent le n&deg; de
+ page imprim&eacute;e et le nombre de copies de cette page. Pour les
+ imprimantes qui ne peuvent pas produire de copies multiples de mani&egrave;re
+ autonome, le champ<I> Nombre_copies</I> est toujours &agrave; 1.</P>
+<P>Le champ<I> facturation_travail</I> contient une copie de l'attribut <CODE>
+job-billing</CODE> fourni dans les requ&ecirc;te IPP <CODE>create-job</CODE>
+ ou <CODE>print-job</CODE>. Si aucune valeur n'est fournie dans la
+ requ&ecirc;te, ce champ contient &quot;-&quot;.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="FILE_TYPING_FILTERING">Filtrage et d&eacute;termination des types
+ de fichiers</A></H2>
+<P>CUPS fournit un m&eacute;canisme de filtrage et de d&eacute;termination du type de
+ fichier bas&eacute; sur MIME, afin de convertir les fichiers dans un format
+ utilisable par chaque imprimante. Au d&eacute;marrage, le serveur CUPS lit les
+ fichiers de la base de donn&eacute;es MIME contenus dans le r&eacute;pertoire<VAR>
+ /etc/cups</VAR> (ou un r&eacute;pertoire indiqu&eacute; au moyen de la directive <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A>) afin de construire en m&eacute;moire une base de
+ donn&eacute;es de conversion et de types de fichiers. Ces fichiers de base de
+ donn&eacute;es sont de simples fichiers texte ASCII et peuvent &ecirc;tre modifi&eacute;s
+ au moyen de votre &eacute;diteur de texte pr&eacute;f&eacute;r&eacute;.</P>
+<P>Les fichiers<VAR> mime.types</VAR> et<VAR> mime.convs</VAR>
+ d&eacute;finissent les types de fichiers standards et les filtres qui sont
+ disponibles sur le syst&egrave;me.</P>
+<H3><A NAME="7_7_1">Le fichier mime.types</A></H3>
+<P>Le fichier<VAR> mime.types</VAR> d&eacute;finit les types de fichiers
+ connus. Chaque ligne d&eacute;bute par le type MIME et devrait &ecirc;tre suivi par
+ une ou plusieurs r&egrave;gles de reconnaissance de fichier. Par exemple, le
+ type de fichier <CODE>text/html</CODE> est d&eacute;fini de la mani&egrave;re
+ suivante:</P>
+<UL>
+<PRE>
+text/html html htm \
+ printable(0,1024) + \
+ (string(0,&quot;&lt;HTML&gt;&quot;) string(0,&quot;&lt;!DOCTYPE&quot;))
+</PRE>
+</UL>
+<P>Les deux premi&egrave;ress r&egrave;gles indiquent que tout fichier portant
+ l'extension<VAR> .html</VAR> ou<VAR> .htm</VAR> est un fichier HTML. La
+ troisi&egrave;me r&egrave;gle pr&eacute;cise que tout fichier dont les 1024 premiers
+ caract&egrave;res sont des caract&egrave;res imprimables et commencent par les
+ cha&icirc;nes <CODE>&lt;HTML&gt;</CODE> ou <CODE>&lt;!DOCTYPE</CODE> est &eacute;galement un
+ fichier HTML.</P>
+<P>Les deux premi&egrave;res r&egrave;gle traitent simplement du nom du fichier. Cela
+ est utile lorsque le nom du fichier original est connu, cependant pour
+ les fichiers d'impression le serveur ne dispose pas de nom de fichier.
+ La troisi&egrave;me r&egrave;gle prend garde &agrave; cette &eacute;ventualit&eacute; et d&eacute;termine
+ automatiquement le type du fichier en se basant plut&ocirc;t sur son contenu.</P>
+<P>Les test applicables sont les suivants:</P>
+<UL>
+<LI><CODE>( expr )</CODE> - Parenth&egrave;ses pour grouper les expressions</LI>
+<LI><CODE>+</CODE> - ET logique</LI>
+<LI><CODE>,</CODE> ou espace vide - OU logique</LI>
+<LI><CODE>!</CODE> - NON logique</LI>
+<LI><CODE>match(&quot;pattern&quot;)</CODE> - Recherche de motif sur le nom de
+ fichier</LI>
+<LI><CODE>extension</CODE> - Recherche de motif sur &quot;*.extension&quot;</LI>
+<LI><CODE>ascii(offset,length)</CODE> - Vrai si les octets sont des
+ caract&egrave;res ASCII imprimables (CR, NL, TAB, BS, 32-126)</LI>
+<LI><CODE>printable(offset,length)</CODE> - Vrai si les octets sont des
+ caract&egrave;res 8 bits imprimables (CR, NL, TAB, BS, 32-126, 160-254)</LI>
+<LI><CODE>string(offset,&quot;cha&icirc;ne&quot;)</CODE> - Vrai si les octets sont
+ identiques &agrave; la cha&icirc;ne</LI>
+<LI><CODE>contains(offset,range,&quot;cha&icirc;ne&quot;)</CODE> - Vrai si la plage
+ d'octets contient la cha&icirc;ne</LI>
+<LI><CODE>char(offset,value)</CODE> - Vrai si l'octet correspond</LI>
+<LI><CODE>short(offset,value)</CODE> - Vrai si l'entier sur 16 bits
+ correspond (ordre des octets : &quot;network&quot; ou &quot;big-endian&quot;)</LI>
+<LI><CODE>int(offset,value)</CODE> - Vrai si l'entier sur 32 bits
+ correspond (ordre des octets : &quot;network&quot; ou &quot;big-endian&quot;)</LI>
+<LI><CODE>locale(&quot;string&quot;)</CODE> - Vrai si la locale courante
+ correspond &agrave; la cha&icirc;ne</LI>
+</UL>
+<P>Toutes les valeurs num&eacute;riques peuvent &ecirc;tre exprim&eacute;es en d&eacute;cimal
+ (123), octal (0123), ou hexad&eacute;cimal (0x123) selon le cas.
+<!-- NEED 2.5in -->
+</P>
+<P>Les cha&icirc;nes de caract&egrave;res peuvent &ecirc;tre d&eacute;limit&eacute;es par des quotes,
+ sans quotes, sous forme d'une cha&icirc;ne de valeurs hexad&eacute;cimales ou toute
+ combinaison de ces &eacute;critures:</P>
+<UL>
+<PRE>
+&quot;cha&icirc;ne&quot;
+'cha&icirc;ne'
+cha&icirc;ne
+&lt;737472696e67&gt;
+&lt;7374&gt;ring
+</PRE>
+</UL>
+<P>Comme le montre l'exemple <CODE>text/html</CODE>, les r&egrave;gles peuvent
+ &ecirc;tre r&eacute;parties sur plusieurs lignes en utilisant le caract&egrave;re
+ &quot;backslash&quot; (&quot;\&quot;). Un exemple plus complexe est fourni par les r&egrave;gles
+ de d&eacute;termination du type <CODE>image/jpeg</CODE>:</P>
+<UL>
+<PRE>
+image/jpeg jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+</PRE>
+</UL>
+<P>Cette r&egrave;gle indique que tout fichier avec l'extension<VAR> .jpeg</VAR>
+,<VAR> .jpg</VAR>, ou<VAR> .jpe</VAR> est un fichier JPEG. De plus, tout
+ fichier commen&ccedil;ant par la cha&icirc;ne hexad&eacute;cimale <CODE>&lt;FFD8FF&gt;</CODE>
+ (JPEG Start-Of-Image) suivie d'un caract&egrave;re compris entre <CODE>0xe0</CODE>
+ et <CODE>0xef</CODE> (JPEG APPn markers) bornes comprises, est
+ &eacute;galement un fichier JPEG.</P>
+<H3><A NAME="7_7_2">Le fichier mime.convs</A></H3>
+<P>Le fichier<VAR> mime.convs</VAR> d&eacute;finit tous les programmes de
+ filtrage qui sont connus du syst&egrave;me. Chaque ligne est de la forme:</P>
+<UL>
+<PRE>
+Source Destination Co&ucirc;t Programme
+
+text/plain application/postscript 50 texttops
+application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
+image/* application/vnd.cups-postscript 50 imagetops
+image/* application/vnd.cups-raster 50 imagetoraster
+</PRE>
+</UL>
+<P>Le champ<I> Source</I> est un type MIME. Il peut &eacute;ventuellement
+ utiliser des m&eacute;ta caract&egrave;res (&quot;joker&quot;, &quot;wildcard&quot;) pour le sur-type ou
+ le sous-type (par exemple &quot;text/plain&quot;, &quot;image/*&quot;, &quot;*/postscript&quot;).</P>
+<P>Le champ<I> Destination</I> est un type MIME d&eacute;fini dans le fichier<VAR>
+ mime.types</VAR>.</P>
+<P>Le champ<I> Co&ucirc;t</I> d&eacute;finit un co&ucirc;t relatif pour l'op&eacute;ration de
+ filtrage, exprim&eacute; sous forme d'une valeur entre 1 et 100. Le co&ucirc;t est
+ utilis&eacute; pour choisir entre deux jeux de filtres lors de la conversion
+ d'un fichier. Par exemple, pour convertir <CODE>image/jpeg</CODE> en <CODE>
+application/vnd.cups-raster</CODE>, vous pourriez utiliser les filtres <CODE>
+imagetops</CODE> et <CODE>pstoraster</CODE> pour un co&ucirc;t total de 100,
+ ou le filtre <CODE>imagetoraster</CODE> pour un co&ucirc;t total de 50.</P>
+<P>Le champ<I> Programme</I> d&eacute;finit le programme de filtrage &agrave;
+ ex&eacute;cuter; le programme doit accepter les arguments standards de
+ filtrage et les variables d'environnement d&eacute;crits dans le &quot;Manuel de
+ conception d'interface&quot; ainsi que le &quot;Manuel du programmeur&quot;:</P>
+<UL>
+<PRE>
+Programme Travail Utilisateur Titre Options [nom_fichier]
+</PRE>
+</UL>
+<P>S'il est indiqu&eacute;, l'argument<I> nom_fichier</I> d&eacute;finit un fichier &agrave;
+ lire lors du filtrage, sinon le filtre doit lire l'entr&eacute;e standard.
+ Toutes les sorties du programme de filtrage doivent &ecirc;tre envoy&eacute;es &agrave; la
+ sortie standard.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="7_7_3">Ajouter des filtres et des types de fichiers</A></H3>
+<P>Ajouter un nouveau filtre ou type de fichier est relativement simple.
+ Plut&ocirc;t qu'ajouter le nouveau filtre ou type aux fichiers<VAR>
+ mime.types</VAR> et<VAR> mime.convs</VAR> qui sont &eacute;cras&eacute;s lorsque vous
+ mettez CUPS &agrave; jour avec une nouvelle version, vous devez simplement
+ cr&eacute;er de nouveaux fichiers avec les extensions<VAR> .types</VAR> et<VAR>
+ .convs</VAR> dans le r&eacute;pertoire<VAR> /etc/cups</VAR>. Nous recommandons
+ d'utiliser le nom du format ou du produit, par exemple:</P>
+<UL>
+<PRE>
+myproduct.types
+myproduct.convs
+</PRE>
+</UL>
+<P>Si vous installez un filtre pour un fichier ou une imprimante
+ courants, ajoutez le nom du fabricant ou de l'&eacute;diteur:</P>
+<UL>
+<PRE>
+acme-msword.types
+acme.msword.convs
+</PRE>
+</UL>
+<P>Cela aidera &agrave; &eacute;viter les conflits de noms si vous installez plusieurs
+ types de fichiers ou plusieurs filtres.</P>
+<P>Une fois choisis les noms pour ces fichiers, cr&eacute;ez-les au moyen de
+ votre &eacute;diteur de texte pr&eacute;f&eacute;r&eacute; comme d&eacute;crit pr&eacute;c&eacute;demment dans ce
+ chapitre. Une fois ces fichiers cr&eacute;&eacute;s, red&eacute;marrez le processus <CODE>
+cupsd</CODE> comme indiqu&eacute; pr&eacute;c&eacute;demment dans <A HREF="#RESTARTING">
+&quot;Red&eacute;marrage du serveur CUPS&quot;</A> .</P>
+<H3><A NAME="7_7_4">Pilotes d'imprimantes et fichiers PPD</A></H3>
+<P>Plusieurs pilotes d'imprimante CUPS utilisent un ou plusieurs filtres
+ sp&eacute;cifiques et un fichier PPD pour chaque mod&egrave;le d'imprimante. Les
+ filtres pilotes d'imprimante sont enregistr&eacute;s au moyen des attributs du
+ fichier <CODE>cupsFilter</CODE>:</P>
+<UL>
+<PRE>
+*cupsFilter: &quot;application/vnd.cups-raster 0 rastertohp&quot;
+</PRE>
+</UL>
+<P>Le filtre est indiqu&eacute; en utilisant seulement le type du fichier
+ source; le type du fichier destination est consid&eacute;r&eacute; comme &eacute;tant du
+ type <CODE>imprimante/nom</CODE> - convenable pour envoi &agrave;
+ l'imprimante.</P>
+<H3><A NAME="7_7_5">Ecrire vos propres filtres ou pilotes d'imprimantes</A>
+</H3>
+<P>CUPS prend en charge un nombre illimit&eacute; de filtres et de formats de
+ fichiers, et peut traiter avec toute imprimante. Si vous d&eacute;sirez &eacute;crire
+ un pilote ou un filtre pour votre imprimante pr&eacute;f&eacute;r&eacute;e, consultez le
+ &quot;Manuel du programmeur&quot; et suivez pas &agrave; pas les instructions qu'il
+ contient.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Imprimer depuis et vers
+ d'autres syst&egrave;mes</A></H1>
+<P>Ce chapitre d&eacute;crit comment imprimer depuis des syst&egrave;me clients qui
+ utilisent les protocoles d'impression LPD, Mac OS ou Windows.</P>
+<H2><A NAME="8_1">Les bases</A></H2>
+<P>CUPS est bas&eacute; sur le protocole IPP, ainsi tout autre syst&egrave;me prenant
+ en charge IPP peut automatiquement envoyer ou recevoir des travaux
+ d'impression vers ou depuis un syst&egrave;me utilisant CUPS. Cependant, tous
+ les syst&egrave;mes ne prennent pas encore en charge IPP. Ce chapitre vous
+ montrera comment connecter ces syst&egrave;mes &agrave; votre serveur CUPS, que ce
+ soit pour qu'ils puissent accepter des travaux provenant de celui-ci ou
+ pour lui en envoyer.</P>
+<H2><A NAME="8_2">Imprimer depuis des clients LPD</A></H2>
+<P>CUPS prend en charge un nombre limit&eacute; des fonctionnalit&eacute;s des clients
+ bas&eacute;s sur LPD. Avec LPD vous pouvez imprimer des fichiers vers des
+ imprimantes d&eacute;termin&eacute;es, voir l'&eacute;tat des files d'impression, etc.
+ Cependant, la configuration automatique des clients et des imprimantes
+ n'est pas prise en charge par le protocole LPD, donc vous devez
+ configurer manuellement chaque client pour les imprimantes auxquelles
+ il a besoin d'acc&eacute;der.</P>
+<P>Le programme <CODE>cups-lpd(8)</CODE> fournit la prise en charge pour
+ les clients LPD. Pour activer la prise en charge LPD sur votre serveur,
+ &eacute;ditez le contenu du fichier<VAR> /etc/inetd.conf</VAR> et ajoutez une
+ ligne:</P>
+<UL>
+<PRE>
+printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+</PRE>
+</UL>
+<P>Le chemin vers le programme <CODE>cups-lpd</CODE> peut varier en
+ fonction de l'installation de votre serveur.</P>
+<P>Une fois cette ligne ajout&eacute;e, envoyez un signal <CODE>HUP</CODE> au
+ processus <CODE>inetd(8)</CODE> ou red&eacute;marrez le syst&egrave;me (NdT : le
+ red&eacute;marrage du syst&egrave;me n'est pas des plus &eacute;l&eacute;gants...):</P>
+<UL>
+<PRE>
+<B>killall -HUP inetd ENTREE</B> [sur IRIX et quelques distributions GNU/Linux]
+<B>kill -HUP <I>pid</I> ENTREE [Autres syst&egrave;mes]</B>
+<B>reboot ENTREE [Pour tous les syst&egrave;mes si le signal HUP ne fonctionne pas (NdT : ...en DERNIER recours, uniquement...)]</B>
+</PRE>
+</UL>
+<H2><A NAME="8_3">Imprimer vers des serveurs LPD</A></H2>
+<P>CUPS fournit le programme d'arri&egrave;re-plan <CODE>lpd</CODE> pour
+ imprimer vers des serveurs et imprimantes utilisant LPD. Utilisez un
+ URI de p&eacute;riph&eacute;rique de la forme <CODE>lpd://serveur/nom</CODE> pour
+ imprimer ver une imprimante sur un serveur LPD, o&ugrave; <CODE>serveur</CODE>
+ est le nom d'h&ocirc;te ou l'adresse IP du serveur et <CODE>nom</CODE> est le
+ nom de la file d'impression.</P>
+<P>Microsoft Windows NT fournit un service LPD sous le nom &quot;Serveur
+ d'impression TCP/IP&quot;. Pour activer l'impression sur un syst&egrave;me Windows
+ NT, ouvrez le panneau de configuration puis &quot;Services&quot;, s&eacute;lectionnez le
+ service &quot;Serveur d'impression TCP/IP&quot; et cliquez sur le bouton
+ &quot;D&eacute;marrer&quot;. Toute imprimante partag&eacute;e devient alors accessible via le
+ protocole LPD.</P>
+<H2><A NAME="8_4">Imprimer depuis des client Mac OS</A></H2>
+<P><I>NdT : je ne suis pas sp&eacute;cialiste Mac et je ne dispose pas de ce
+ type de mat&eacute;riel. Il se peut qu'il y ait quelques impr&eacute;cisions ou
+ erreurs dans ce qui suit, fa&icirc;tes-moi l'amiti&eacute; de me les pardonner ET de
+ me les signaler. Merci par avance...</I></P>
+<P>CUPS ne fournit pas de prise en charge directe de Mac OS. Cependant,
+ il existe plusieurs logiciels libres ou commerciaux qui le font.</P>
+<H3><A NAME="8_4_1">Columbia Appletalk Package (CAP)</A></H3>
+<P>Etant donn&eacute; que le serveur CAP LaserWriter (<CODE>lwsrv(8)</CODE>) ne
+ prend pas en charge les sp&eacute;cifications des fichiers PPD, nous ne
+ recommandons pas l'utilisation de CAP avec CUPS. Cependant, vous pouvez
+ ex&eacute;cuter le programme <CODE>lpsrv</CODE> pour une prise en charge
+ limit&eacute;e de l'impression au moyen de la syntaxe suivante:</P>
+<UL>
+<PRE>
+lwsrv -n &quot;<I>Nom</I>&quot; -p <I>Imprimante</I> -a /usr/lib/adicts -f /usr/lib/LW+Fonts
+</PRE>
+</UL>
+<P>o&ugrave; <CODE>Nom</CODE> est le nom que vous voulez utiliser pour partager
+ l'imprimante et <CODE>imprimante</CODE> est le nom de la file
+ d'impression.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="8_4_2">XINET KA/Spool</A></H3>
+<P>Afin d'utiliser votre syst&egrave;me comme serveur d'impression pour des
+ clients Mac OS, configurez chaque imprimante en utilisant <CODE>
+papserver(8)</CODE> dans le fichier<VAR> /usr/adm/appletalk/services</VAR>
+, et en indiquant le fichier PPD correspondant dans le r&eacute;pertoire<VAR>
+/etc/cups/ppd</VAR>. Pour une imprimante appel&eacute;e <CODE>Mon_Imprimante</CODE>
+ la syntaxe serait de la forme suivante:</P>
+<UL>
+<PRE>
+/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/Mon_Imprimante.ppd \
+&quot;Printer Description&quot; Mon_Imprimante
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Entrez le texte ci-dessus sur une seule ligne sans le caract&egrave;re &quot;\&quot;.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="8_4_3">NetATalk</A></H3>
+<P>Pour utiliser votre syst&egrave;me comme serveur d'impression pour des
+ clients Mac OS, configurez chaque imprimante dans le fichier<VAR>
+ papd.conf</VAR>, en indiquant le fichier PPD correspondant dans le
+ r&eacute;pertoire<VAR> /etc/cups/ppd</VAR> pour chaque imprimante. Pour une
+ imprimante nomm&eacute;e <CODE>Mon_Imprimante</CODE> le texte serait de la
+ forme suivante:</P>
+<UL>
+<PRE>
+Printer Description:Mon_Imprimante@Mon_Serveur:\
+ :pr=|/usr/bin/lp -d Mon_Imprimante:\
+ :op=daemon:\
+ :pd=/etc/cups/ppd/Mon_Imprimante.ppd:
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H2><A NAME="8_5">Imprimer vers des serveurs d'impression Mac OS</A></H2>
+<P>Actuellement, CUPS ne fournit pas de programme d'arri&egrave;re-plan pour
+ communiquer avec un serveur Mac OS. Cependant, vous pouvez &eacute;crire et
+ installer un court script dans le r&eacute;pertoire<VAR> /usr/lib/cups/backend</VAR>
+ qui envoie un fichier d'impression en utilisant la commande appropri&eacute;e.
+ Le court script suivant ex&eacute;cutera la commande <CODE>papif</CODE>
+ fournie avec CAP.</P>
+<P>Apr&egrave;s avoir copi&eacute; le script dans<VAR> /usr/lib/cups/backend/cap</VAR>
+, indiquez un URI de p&eacute;riph&eacute;rique de la forme <CODE>
+cap://serveur/imprimante</CODE> pour utiliser ce script avec une file
+ d'impression.
+<!-- NEED 8in -->
+</P>
+<UL>
+<PRE>
+<I>&quot;/usr/lib/cups/backend/cap&quot;</I>
+#!/bin/sh
+#
+# Usage: cap job user title copies options [filename]
+#
+
+# No arguments means show available devices...
+
+if test ${#argv} = 0; then
+ echo &quot;network cap \&quot;Unknown\&quot; \&quot;Mac OS Printer via CAP\&quot;&quot;
+ exit 0
+fi
+
+# Collect arguments...
+
+user=$2
+copies=$4
+
+if test ${#argv} = 5; then
+ # Get print file from stdin; copies have already been handled...
+ file=/var/tmp/$$.prn
+ copies=1
+ cat &gt; $file
+else
+ # Print file is on command-line...
+ file=$6
+fi
+
+# Create a dummy cap.printers file for this printer based
+# upon a device URI of &quot;cap://server/printer&quot;...
+
+echo $PRINTER/$DEVICE_URI | \
+ awk -F/ '{print $1 &quot;=&quot; $5 &quot;:LaserWriter@&quot; $4}' &gt; /var/tmp/$$.cap
+
+CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
+
+# Send the file to the printer, once for each copy. This assumes that you
+# have properly initialized the cap.printers file...
+
+while [ $copies -gt 0 ]; do
+ papif -n $user &lt; $file
+
+ copies=`expr $copies - 1`
+done
+
+# Remove any temporary files...
+if test ${#argv} = 5; then
+ /bin/rm -f $file
+fi
+
+/bin/rm -f /var/tmp/$$.cap
+
+exit 0
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H2><A NAME="8_6">Imprimer depuis des clients Windows</A></H2>
+<P>Bien que CUPS ne fournisse directement pas de prise en charge de
+ Windows, le logiciel libre SAMBA le fait. La version 2.0.6 de SAMBA est
+ la premi&egrave;re qui prenne en charge CUPS. Vous pouvez t&eacute;l&eacute;charger SAMBA &agrave;
+ l'adresse :</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>Pour configurer SAMBA pour CUPS, &eacute;ditez le contenu du fichier<VAR>
+ smb.conf</VAR> et remplacez les commandes d'impression existantes par
+ les lignes:</P>
+<UL>
+<PRE>
+printing = cups
+printcap name = cups
+</PRE>
+</UL>
+<P>C'est tout ce qu'il y a &agrave; faire! Les utilisateurs distants pourront
+ d&eacute;sormais explorer les imprimantes de votre syst&egrave;me et leur envoyer des
+ travaux d'impression.</P>
+<H3><A NAME="8_6_1">Exporter les pilotes d'imprimantes</A></H3>
+<P>Vous pouvez &eacute;ventuellement exporter des pilotes d'imprimantes de
+ votre serveur CUPS en utilisant la commande <CODE>cupsaddsmb</CODE> et
+ le logiciel SAMBA 2.2.0 ou sup&eacute;rieur.</P>
+<P>Avant de pouvoir exporter les pilotes d'imprimantes, vous devez
+ t&eacute;l&eacute;charger les pilotes d'imprimantes actuels Adobe PostScript &agrave; partir
+ du site &quot;web&quot; Adobe (<A HREF="http://www.adobe.com/">
+http://www.adobe.com/</A>). Utilisez le logiciel libre <CODE>unzip</CODE>
+ pour extraire les fichiers des archives ZIP auto-extractibles contenant
+ les pilotes; vous aurez besoin des fichiers suivants:</P>
+<UL>
+<PRE>
+ADFONTS.MFM
+ADOBEPS4.DRV
+ADOBEPS4.HLP
+ADOBEPS5.DLL
+ADOBEPSU.DLL
+ADOBEPSU.HLP
+DEFPRTR2.PPD
+ICONLIB.DLL
+PSMON.DLL
+</PRE>
+</UL>
+<P>Copiez ces fichiers dans le r&eacute;pertoire<VAR> /usr/share/cups/drivers</VAR>
+ - vous pourriez avoir &agrave; renommer certains fichiers de sorte que tous
+ les noms soient compl&egrave;tement en majuscules.</P>
+<P>Ensuite, ajouter un partage d'imprimante <CODE>print$</CODE> pour les
+ pilotes d'imprimantes &agrave; votre fichier<VAR> smb.conf</VAR>:</P>
+<UL>
+<PRE>
+[print$]
+ comment = Pilotes d'imprimantes
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = root
+</PRE>
+</UL>
+<P>Le r&eacute;pertoire de vos pilotes d'imprimantes peut &ecirc;tre n'importe o&ugrave;
+ dans le syst&egrave;me; assurez-vous simplement qu'il est accessible en
+ &eacute;criture aux utilisateurs indiqu&eacute;s par la directive <CODE>write list</CODE>
+. Assurez-vous &eacute;galement que chaque utilisateur de la liste <CODE>write
+ list</CODE> poss&egrave;de un mot de passe SAMBA en utilisant la commande <CODE>
+smbpasswd(1)</CODE> sinon vous ne pourrez pas vous authentifier.</P>
+<P>Enfin, ex&eacute;cutez la commande <CODE>cupsaddsmb</CODE> pour exporter les
+ pilotes d'imprimantes pour une ou plusieurs files d'impression:</P>
+<UL>
+<PRE>
+<KBD>cupsaddsmb -U root printer1 ... printerN <I>ENTREE</I></KBD>
+</PRE>
+</UL>
+<P>Ex&eacute;cuter la commande <CODE>cupsaddsmb</CODE> avec l'option <CODE>-a</CODE>
+ exportera les imprimantes:</P>
+<UL>
+<PRE>
+<KBD>cupsaddsmb -U root -a <I>ENTREE</I></KBD>
+</PRE>
+</UL>
+<H2><A NAME="8_7">Imprimer vers des serveurs d'impression Windows</A></H2>
+<P>CUPS peut imprimer vers des serveurs Windows de deux fa&ccedil;ons. La
+ premi&egrave;re utilise le protocole LPD sur le syst&egrave;me CUPS et le service
+ &quot;Serveur d'impression TCP/IP&quot; sur le syst&egrave;me Windows NT. Vous pouvez
+ trouver plus d'information au sujet de la premi&egrave;re configuration dans
+ la section pr&eacute;c&eacute;dente <A HREF="#LPD">LPD</A> de ce chapitre.</P>
+<P>La seconde m&eacute;thode utilise le protocole SMB de Microsoft (&quot;Server
+ Message Block&quot;). La prise en charge de ce protocole est fournie par le
+ logiciel libre SAMBA. Vous pouvez t&eacute;l&eacute;charger SAMBA &agrave; l'adresse
+ suivante:</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>Pour configurer CUPS pour SAMBA, ex&eacute;cutez la commande suivante:</P>
+<UL>
+<PRE>
+<B>ln -s `which smbspool` /usr/lib/cups/backend/smb ENTREE</B>
+</PRE>
+</UL>
+<P>Le programme <CODE>smbspool(1)</CODE> est fourni avec SAMBA depuis la
+ version 2.0.6. Une fois que vous avez cr&eacute;&eacute; le lien vous pouvez
+ configurer vos imprimantes en utilisant l'un des URI de p&eacute;riph&eacute;rique
+ suivants:</P>
+<UL>
+<PRE>
+smb://groupe_de_travail_ou_domaine/serveur/nom_partage
+smb://serveur/nom_partage
+smb://utilisateur:mot_de_passe@groupe_de_travail_ou_domaine/serveur/nom_partage
+smb://utilisateur:mot_de_passe@serveur/nom_partage
+</PRE>
+</UL>
+<P>Le nom <CODE>groupe_de_travai_ou_domaine</CODE> doit &ecirc;tre indiqu&eacute; si
+ votre syst&egrave;me utilise un autre nom que la valeur standard de votre
+ r&eacute;seau. Les cha&icirc;nes <CODE>utilisateur:mot_de_passe</CODE> sont
+ n&eacute;cessaires si vous imprimez vers des serveurs Windows NT ou des
+ partages Windows 95/98 dont les mots de passe sont activ&eacute;s.</P>
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Licence d'utilisation du
+ logiciel</A></H1>
+<H2 ALIGN="CENTER"><A NAME="9_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P><I>(NdT : pour des raisons &eacute;videntes de droit, j'ai volontairement
+ gard&eacute; la licence d'utilisation du logiciel et la licence GPL en anglais
+ car une traduction de celles-ci pourrait donner lieu &agrave; des
+ interpr&eacute;tations erron&eacute;es... et en plus je ne suis pas juriste !)</I></P>
+<P ALIGN="CENTER">Copyright 1997-2003 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3111 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
+<H3><A NAME="9_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="9_1_2">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="9_1_3">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
+<BR> Director of Marketing
+<BR> Artifex Software Inc.
+<BR> 454 Las Gallinas Ave., Suite 108
+<BR> San Rafael, CA 94903 USA
+<BR> Voice: +1.415.492.9861
+<BR> Fax: +1.415.492.9862
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
+</P>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
+ Derek B. Noonburg
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="9_1_4">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com">http://www.easysw.com</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<PRE>
+
+</PRE>
+<H3><A NAME="9_2_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+</LI>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+</LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H3><A NAME="9_3_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.</LI>
+<P></P>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<P></P>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
+<P></P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
+<P></P>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
+<P></P>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.</LI>
+<P></P>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
+<P></P>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+<H1 ALIGN="RIGHT"><A NAME="COMMON_NETWORK">B - R&eacute;glages r&eacute;seau courants</A>
+</H1>
+<P>Cette annexe englobe de nombreux serveurs d'impression et interfaces
+ r&eacute;seau TCP/IP disponibles actuellement sur le march&eacute;.</P>
+<H2><A NAME="10_1">Configurer une interface r&eacute;seau</A></H2>
+<P>Lorsque vous installez votre imprimante r&eacute;seau ou votre serveur
+ d'impression pour la premi&egrave;re fois sur votre r&eacute;seau local (LAN), vous
+ devez configurer son adresse IP (&quot;Internet Protocol&quot;). Sur la plupart
+ des imprimantes r&eacute;seau pour groupe de travail, vous pouvez le faire
+ directement au moyen du panneau de contr&ocirc;le. Cependant, dans la plupart
+ des cas, vous pr&eacute;f&egrave;rerez assigner l'adresse IP &agrave; distance depuis votre
+ station de travail. Cela rend l'administration un peu plus simple et
+ &eacute;vite d'assigner accidentellement des adresses r&eacute;seau eu doublons.</P>
+<P>Pour configurer votre imprimante ou votre serveur d'impression pour
+ une assignation &agrave; distance de l'adresse r&eacute;seau, vous aurez besoin de
+ son adresse MAC (ethernet Media Access Control), &eacute;galement appel&eacute;e
+ adresse de noeud (&quot;node address&quot;) dans certains cas. Vous aurez
+ &eacute;galement besoin de conna&icirc;tre l'adresse IP que vous voulez utiliser
+ pour ce mat&eacute;riel. L'adresse MAC peut souvent &ecirc;tre trouv&eacute;e sur la page
+ de test de l'imprimante ou sur son panneau arri&egrave;re.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="10_1_1">Configuration de l'adresse IP utilisant ARP</A></H3>
+<P>La m&eacute;thode la plus simple pour installer l'adresse IP d'un mat&eacute;riel
+ r&eacute;seau est d'utiliser la commande <CODE>arp(8)</CODE>. La commande <CODE>
+arp</CODE> envoie un paquet ARP (&quot;Address Resolution Protocol&quot;) &agrave;
+ l'adresse MAC indiqu&eacute;e tout en lui indiquant son adresse IP:</P>
+<UL>
+<PRE>
+<B>arp -s adresse-ip adresse-mac ENTREE</B>
+<B>arp -s hote.domaine.com 08:00:69:00:12:34 ENTREE</B>
+<B>arp -s 192.0.2.2 08:00:69:00:12:34 ENTREE</B>
+</PRE>
+</UL>
+<H3><A NAME="10_1_2">Configuration de l'adresse IP utilisant RARP</A></H3>
+<P>La mani&egrave;re la plus souple d'assigner une adresse IP sous UNIX est
+ d'utiliser le protocole RARP (&quot;Reverse Address Resolution Protocol&quot;).
+ RARP permet &agrave; un mat&eacute;riel r&eacute;seau d'&eacute;mettre une requ&ecirc;te d'adresse IP en
+ utilisant sont adresse MAC, un ou plusieurs serveurs RARP sur le r&eacute;seau
+ r&eacute;pondront &agrave; cette requ&ecirc;te par un paquet ARP proposant une adresse IP
+ que le mat&eacute;riel r&eacute;seau peut utiliser.</P>
+<P>RARP devrait &ecirc;tre utilis&eacute; lorsque vous administrez de nombreuses
+ imprimantes ou serveurs d'impression, ou quand un mat&eacute;riel r&eacute;seau ne
+ peut se &quot;souvenir&quot; de son adresse IP apr&egrave;s chaque red&eacute;marrage. Si vous
+ n'avez qu'une seule imprimante ou serveur d'impression, la commande <CODE>
+arp</CODE> est la plus adapt&eacute;e.</P>
+<P>Certains syst&egrave;mes d'exploitation UNIX utilisent un programme nomm&eacute; <CODE>
+rarpd(8)</CODE> pour administrer RARP. Les autres, tels que GNU/Linux,
+ prennent en charge ce protocole &agrave; l'int&eacute;rieur du noyau. Pour les
+ syst&egrave;mes qui utilisent le programme <CODE>rarpd</CODE> vous aurez
+ besoin de le d&eacute;marrer avant que les requ&ecirc;tes RARP commencent:</P>
+<UL>
+<PRE>
+<B>rarpd ENTREE</B>
+</PRE>
+</UL>
+<P>Sous IRIX vous pouvez activer cette fonctionnalit&eacute; en standard en
+ utilisant la commande suivante:</P>
+<UL>
+<PRE>
+<B>chkconfig rarpd on ENTREE</B>
+</PRE>
+</UL>
+<P>Le programme <CODE>rarpd</CODE> et la version noyau de la prise en
+ charge RARP lisent toutes les deux une liste des adresses MAC et IP &agrave;
+ partir d'un fichier<VAR> /etc/ethers</VAR>. Chaque ligne comporte
+ l'adresse Ethernet suivie de l'adresse IP ou du nom d'h&ocirc;te:</P>
+<UL>
+<PRE>
+08:00:69:00:12:34 mon_imprimante.mon_domaine.com
+08:00:69:00:12:34 192.0.2.2
+</PRE>
+</UL>
+<P>Ajoutez une ligne &agrave; ce fichier et red&eacute;marrez l'imprimante ou le
+ serveur d'impression pour qu'elle/il r&eacute;cup&egrave;re son adresse IP.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="10_1_3">Configuration de l'adresse IP utilisant BOOTP</A></H3>
+<P>Le protocole BOOTP est utilis&eacute; quand vous avez besoin de fournir des
+ informations suppl&eacute;mentaires &agrave; l'interface r&eacute;seau telles que
+ l'emplacement du fichier de configuration. En utilisant le programme
+ standard <CODE>bootpd(8)</CODE> fourni sous UNIX, vous avez simplement
+ besoin d'ajouter la ligne suivante au fichier<VAR> /etc/bootptab</VAR>
+ pour IRIX:</P>
+<UL>
+<PRE>
+mon_imprimante 08:00:69:00:12:34 192.0.2.2 <VAR>mon_imprimante.boot</VAR>
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>Les versions plus r&eacute;centes de <CODE>bootpd</CODE> utilisent un format
+ diff&eacute;rent:</P>
+<UL>
+<PRE>
+mon_imprimante:ha=080069001234:ip=192.0.2.2:<VAR>t144=mon_imprimante.boot</VAR>
+</PRE>
+</UL>
+<P>Le fichier<VAR> mon_imprimante.boot</VAR> est situ&eacute; en standard dans
+ le r&eacute;pertoire<VAR> /usr/local/boot</VAR> Si vous n'avez pas besoin de
+ fournir un fichier de d&eacute;marrage, vous pouvez laisser vide la fin de la
+ ligne.
+<!-- NEED 2in -->
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Certaines versions d'UNIX n'activent pas le service BOOTP en
+ standard. Le fichier<VAR> /etc/inetd.conf</VAR> contient g&eacute;n&eacute;ralement
+ une ligne pour le service BOOTP. ELle peut &ecirc;tre d&eacute;comment&eacute;e si
+ n&eacute;cessaire.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="10_2">V&eacute;rifier la connexion de l'imprimante</A></H2>
+<P>Pour v&eacute;rifier que l'adresse IP a bien &eacute;t&eacute; assign&eacute;e et que
+ l'imprimante est correctement connect&eacute;e au r&eacute;seau local (LAN), tapez:</P>
+<UL>
+<PRE>
+<B>ping adresse-ip ENTREE</B>
+</PRE>
+</UL>
+<P>Si la connexion fonctionne correctement vous devriez voir appara&icirc;tre
+ quelque chose de la forme suivante :</P>
+<UL>
+<PRE>
+<B>ping mon_imprimante ENTREE</B>
+PING mon_imprimante (192.0.2.2): 56 data bytes
+64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
+64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
+</PRE>
+</UL>
+<P>Sinon, v&eacute;rifiez que que l'imprimante ou le serveur d'impression est
+ bien connect&eacute; au r&eacute;seau (NdT : v&eacute;rifiez ces @#*&curren;%&sect; c&acirc;bles !), qu'elle
+ est sous tension et que l'adresse IP est bonne. Vous pouvez &eacute;galement
+ voir la configuration r&eacute;seau en imprimant une page de test &agrave; partir du
+ panneau de contr&ocirc;le du mat&eacute;riel.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="10_3">R&eacute;glages d'interfaces r&eacute;seau et serveur d'impression
+ courants</A></H2>
+<P>Une fois que vous avez configur&eacute; l'adresse IP, vous pouvez acc&eacute;der &agrave;
+ l'imprimante ou au serveur d'impression en utilisant les programmes
+ d'arri&egrave;re-plan <CODE>ipp</CODE>, <CODE>lpd</CODE>, ou <CODE>socket</CODE>
+. La liste qui suit donne les interfaces r&eacute;seau et serveurs d'impression
+ courants ainsi que les r&eacute;glages que vous devriez utiliser dans CUPS:
+<CENTER>
+<TABLE BORDER="1">
+<TR ALIGN="LEFT" VALIGN="TOP"><TH>Mod&egrave;le / Fabricant</TH><TH>URI de
+ p&eacute;riph&eacute;rique</TH></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Apple LaserWriter</TD><TD>lpd://<I>
+ address</I>/PASSTHRU</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/o IPP
+<BR> <A HREF="#AXIS"> (voir instructions)</A></TD><TD>socket://<I>
+address</I> :9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/IPP</TD><TD>ipp://<I>address</I>
+ /LPT1
+<BR> ipp://<I>address</I>/LPT2
+<BR> ipp://<I>address</I>/COM1</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Castelle LANpress<SUP>TM</SUP></TD><TD>
+ lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>DPI NETPrint</TD><TD>lpd://<I>address</I>
+ /pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EFI&reg; Fiery&reg; RIP</TD><TD>lpd://<I>
+ address</I>/print</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EPSON&reg; Multiprotocol Ethernet
+ Interface Board</TD><TD>socket://<I>address</I></TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
+ lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/o IPP</TD><TD>
+ socket://<I>address</I>:9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/IPP</TD><TD>
+ ipp://<I>address</I>/ipp
+<BR> ipp://<I>address</I>/ipp/port1
+<BR> ipp://<I>address</I>/ipp/port2
+<BR> ipp://<I>address</I>/ipp/port3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Intel&reg; NetportExpress XL, PRO/100</TD><TD>
+ lpd://<I>address</I>/LPT1_PASSTHRU
+<BR> lpd://<I>address</I>/LPT2_PASSTHRU
+<BR> lpd://<I>address</I>/COM1_PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Lexmark<SUP>TM</SUP> MarkNet</TD><TD>
+ lpd://<I>address</I>/ps</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Linksys EtherFast&reg;
+<BR> <A HREF="#LINKSYS"> (voir instructions)</A></TD><TD>socket://<I>
+address</I> :4010
+<BR> socket://<I>address</I>:4020
+<BR> socket://<I>address</I>:4030</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Kodak&reg;</TD><TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>QMS&reg; CrownNet<SUP>TM</SUP></TD><TD>
+ lpd://<I>address</I>/ps</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Tektronix&reg; PhaserShare<SUP>TM</SUP></TD><TD>
+ socket://<I>address</I>:9100</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; 4512 NIC</TD><TD>lpd://<I>
+ address</I>/PORT1</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; XNIC</TD><TD>lpd://<I>address</I>
+ /PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; (most others)</TD><TD>socket://<I>
+ address</I>:5503</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="AXIS">Configuration de serveurs d'impression Axis</A></H2>
+<P>Les serveurs d'impression Axis peuvent &ecirc;tre configur&eacute;s en utilisant
+ ARP, RARP ou BOOTP. Cependant, sur certains mod&egrave;les ne prenant pas en
+ charge IPP, une configuration suppl&eacute;mentaire est n&eacute;cessaire pour
+ permettre au serveur de dialoguer avec CUPS.
+<!-- NEED 3in -->
+</P>
+<P>Chaque serveur d'impression poss&egrave;de une fichier de configuration
+ nomm&eacute;<VAR> config</VAR> qui contient la liste des param&egrave;tres r&eacute;seau &agrave;
+ utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord
+ le t&eacute;l&eacute;charger &agrave; partir du serveur d'impression en utilisant le
+ programme <CODE>ftp(1)</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp adresse-ip ENTREE</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTREE</B>
+331 User name ok, need password
+Password: <B>pass ENTREE</B> <I>(le mot de passe n'appara&icirc;t pas)</I>
+230 User logged in
+ftp&gt; <B>get config ENTREE</B>
+local: config remote: config
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2),
+(mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Ensuite, &eacute;ditez son contenu avec votre &eacute;diteur de texte pr&eacute;f&eacute;r&eacute; et
+ rep&eacute;rez les lignes commen&ccedil;ant par:</P>
+<UL>
+<PRE>
+RTN_OPT. : YES
+RTEL_PR1. : 0
+RTEL_PR2. : 0
+RTEL_PR3. : 0
+RTEL_PR4. : 0
+RTEL_PR5. : 0
+RTEL_PR6. : 0
+RTEL_PR7. : 0
+RTEL_PR8. : 0
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+ Changez la ligne <CODE>RTN_OPT</CODE> en:
+<UL>
+<PRE>
+RTN_OPT. : <B>NO</B>
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Cela d&eacute;sactive le protocole &quot;Reverse TELNET&quot; et active le protocole
+ standard TELNET sur le serveur d'impression. Ensuite, assignez un
+ num&eacute;ro de port pour chaque port parall&egrave;le ou s&eacute;rie sur le serveur,
+ comme suit:</P>
+<UL>
+<PRE>
+RTEL_PR1. : <B>9100</B>
+RTEL_PR2. : <B>9101</B>
+RTEL_PR3. : <B>9102</B>
+RTEL_PR4. : <B>9103</B>
+RTEL_PR5. : <B>9104</B>
+RTEL_PR6. : <B>9105</B>
+RTEL_PR7. : <B>9106</B>
+RTEL_PR8. : <B>9107</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>Cela a principalement pour effet de forcer le serveur Axis &agrave;
+ ressembler &agrave; un serveur d'impression Hewlett Packard JetDirect EX.
+ Sauvegardez le fichier et installez le sur le serveur d'impression dans
+ le fichier<VAR> config</VAR> au moyen de la commande <CODE>ftp</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp adresse-ip ENTREE</B>
+Connected to adresse-ip.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTREE</B>
+331 User name ok, need password
+Password: <B>pass ENTREE</B> <I>(le mot de passe n'est pas affich&eacute;)</I>
+230 User logged in
+ftp&gt; <B>put config CONFIG ENTREE</B>
+local: config remote: CONFIG
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2), (mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>get hardreset ENTREE</B>
+local: hardreset remote: hardreset
+200 PORT command successful.
+421 Axis NPS ### hard reset, closing connection.
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Votre serveur d'impression Axis est &agrave; pr&eacute;sent op&eacute;rationnel!</P>
+<H2><A NAME="LINKSYS">Configuration de serveurs d'impression Linksys</A></H2>
+<P>Les serveurs d'impression LinkSys peuvent &ecirc;tre configur&eacute;s au moyen de
+ ARP, RARP ou BOOTP. Comme certains serveurs d'impression Axis anciens,
+ une configuration suppl&eacute;mentaire TCP/IP est n&eacute;cessaire pour les faire
+ fonctionner avec CUPS
+<!-- NEED 3in -->
+</P>
+<P>Chaque serveur d'impression poss&egrave;de une fichier de configuration
+ nomm&eacute;<VAR> config</VAR> qui contient la liste des param&egrave;tres r&eacute;seau &agrave;
+ utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord
+ le t&eacute;l&eacute;charger &agrave; partir du serveur d'impression en utilisant le
+ programme <CODE>ftp(1)</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp -n adresse-ip ENTREE</B>
+Connected to adress-ip.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>get CONFIG ENTREE</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+WARNING! 68 bare linefeeds received in ASCII mode
+File may not have transferred correctly.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Ensuite, &eacute;ditez son contenu avec votre &eacute;diteur de texte pr&eacute;f&eacute;r&eacute; et
+ rep&eacute;rez les lignes commen&ccedil;ant par:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:P1
+0120 L2_PROUT:P1
+0140 L3_PROUT:P1
+</PRE>
+</UL>
+<P>Changez le num&eacute;ro de port pour chaque port parall&egrave;le et s&eacute;rie sur le
+ serveur, comme suit:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:<B>P1</B>
+0120 L2_PROUT:<B>P2</B>
+0140 L3_PROUT:<B>P3</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>Cela relie chaque imprimante virtuelle &agrave; un port physique.
+ Sauvegardez le fichier et installez le sur le serveur d'impression dans
+ le fichier<VAR> config</VAR> au moyen de la commande <CODE>ftp</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp -n adresse-ip ENTREE</B>
+Connected to adresse-ip.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>put CONFIG ENTREE</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Votre serveur d'impression SysLink est d&eacute;somais op&eacute;rationnel !</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_DRIVERS">C - Pilotes d'imprimantes</A>
+</H1>
+<P>Cette annexe dresse la liste des pilotes d'imprimantes qui sont
+ fournis avec CUSP.</P>
+<H2><A NAME="11_1">Pilotes d'imprimantes</A></H2>
+<P>CUPS inclut les pilotes d'imprimantes suivants:</P>
+<UL>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>,<VAR> epson9.ppd</VAR></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>,<VAR> epson24.ppd</VAR>
+</LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>,<VAR> stcolor.ppd</VAR></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>,<VAR> stphoto.ppd</VAR></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A>,<VAR> deskjet.ppd</VAR></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A>,<VAR> laserjet.ppd</VAR></LI>
+</UL>
+<H2><A NAME="EPSON9">EPSON 9-pin Dot Matrix</A></H2>
+<P>Le pilote EPSON 9-pin Dot Matrix (<VAR>epson9.ppd</VAR>) prend en
+ charge les imprimantes 9 aiguilles qui utilisent le jeu de commandes
+ ESC/P. Il fournit l'impression en noir et blanc dans les r&eacute;solutions
+ 60x72, 120x72, et 240x72 PPP (DPI).</P>
+<H2><A NAME="EPSON24">EPSON 24-pin Dot Matrix</A></H2>
+<P>Le pilote EPSON 24-pin Dot Matrix (<VAR>epson9.ppd</VAR>) prend en
+ charge les imprimantes 24 aiguilles qui utilisent le jeu de commandes
+ ESC/P. Il fournit l'impression en noir et blanc dans les r&eacute;solutions
+ 120x180, 180x180, 360x180, et 360x360 PPP (DPI).</P>
+<H2><A NAME="STCOLOR">EPSON Stylus Color</A></H2>
+<P>Le pilote EPSON Stylus Color (<VAR>stcolor.ppd</VAR>) prend en charge
+ les imprimantes EPSON Stylus Color qui utilisent le jeu de commandes
+ ESC/P2. Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et
+ blanc dans les r&eacute;solutions 180, 360, et 720 PPP (DPI).</P>
+<H2><A NAME="STPHOTO">EPSON Stylus Photo</A></H2>
+<P>Le pilote EPSON Stylus Photo (<VAR>stphoto.ppd</VAR>) prend en charge
+ les imprimantes EPSON Stylus Photo qui utilisent le jeu de commandes
+ ESC/P2. Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et
+ blanc dans les r&eacute;solutions 180, 360, et 720 PPP (DPI).</P>
+<H2><A NAME="DESKJET">HP DeskJet</A></H2>
+<P>Le pilote HP DeskJet (<VAR>deskjet.ppd</VAR>) prend en charge les
+ imprimantes HP DeskJet qui utilisent le jeu de commandes PCL. Il
+ fournit l'imrpession en couleur (CMYK) ainsi qu'en noir et blanc dans
+ les r&eacute;solutions 150, 300, et 600 PPP (DPI).</P>
+<P>Les imprimantes DeskJet qui utilisent le jeu de commandes HP-PPA
+ (720C, 722C, 820C, and 1100C)<B> ne sont pas</B> prises en charge du
+ fait de l'absence totale de documentation de la part de Hewlett
+ Packard.</P>
+<P>Le &quot;duplexer&quot; fourni avec les imprimantes de la s&eacute;rie d'imprimantes
+ HP DeskJet 900 n'est &eacute;galement pas pris en charge pour les m&ecirc;mes
+ raisons.</P>
+<H2><A NAME="LASERJET">HP LaserJet</A></H2>
+<P>Le pilote HP LaserJet (<VAR>laserjet.ppd</VAR>) prend en charge les
+ impriamntes HP LaserJet qui utilisent le jeu de commandes PCL. Il
+ fournit l'impression seulement en noir et blanc et prend en charge le
+ &quot;duplexer&quot; s'il est install&eacute;. Il prend en charge les r&eacute;solutions 150,
+ 300, et 600 PPP (DPI).</P>
+<P>Les imprimantes LaserJet qui n'utilisent pas le jeu de commandes PCL
+ (3100, 3150) ne sont pas prises en charge du fait d'une absence totale
+ de documentation de la part de Hewlett Packard.</P>
+<H1 ALIGN="RIGHT"><A NAME="FILES">D - Liste des fichiers</A></H1>
+<P>Cette annexe dresse la liste des fichiers et r&eacute;pertoire qui sont
+ install&eacute;s par CUPS
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR VALIGN="TOP"><TH>Chemin</TH><TH>Description</TH></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/certs/</TD><TD>Emplacement des fichiers
+ des certificats d'authentification pour les clients HTTP locaux.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/classes.conf</TD><TD>Fichiers de
+ configuration des classes d'imprimantes pour l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/cupsd.conf</TD><TD>Fichier de
+ configuration de l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/interfaces/</TD><TD>Emplacement des
+ scripts d'interface System V pour les imprimantes.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.convs</TD><TD>Liste des filtres de
+ fichiers standards inclus dans ESP Print Pro.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.types</TD><TD>Liste des types de
+ fichiers reconnus par ESP Print Pro.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/ppd/</TD><TD>Emplacement des fichiers PPD
+ (&quot;PostScript Printer Description&quot;) pour les imprimantes.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/printers.conf</TD><TD>Fichier de
+ configuration des imprimantes pour l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/cancel</TD><TD>La commande d'annulation de
+ travaux System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/disable</TD><TD>La commande de
+ d&eacute;sactivation d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/enable</TD><TD>La commande d'activation
+ d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lp</TD><TD>La commande d'impression System
+ V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpoptions</TD><TD>Jeu d'options
+ d'impression et de valeurs implicites personnalis&eacute;es par l'utiliseur.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lppasswd</TD><TD>Ajoute, modifie et retire
+ des mots de passe pour des comptes &quot;Digest&quot;.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpq</TD><TD>La commande d'&eacute;tat Berkeley.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpr</TD><TD>La commande d'impression
+ Berkeley.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lprm</TD><TD>La commande d'annulation de
+ travaux Berkeley.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpstat</TD><TD>La commande d'&eacute;tat System
+ V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/include/cups/</TD><TD>Fichiers d'en-t&ecirc;te de
+ l'API CUPS.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.a
+<BR> /usr/lib32/libcupsimage.a</TD><TD>Librairies statiques (IRIX 6.5)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.a
+<BR> /usr/lib/libcupsimage.a</TD><TD>Librairies statiques (tous les
+ autres syst&egrave;mes)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.sl.2
+<BR> /usr/lib/libcupsimage.sl.2</TD><TD>Librairies partag&eacute;es (HP-UX)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.so.2
+<BR> /usr/lib32/libcupsimage.so.2</TD><TD>Librairies partag&eacute;es (IRIX
+ 6.5)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.so.2
+<BR> /usr/lib/libcupsimage.so.2</TD><TD>Librairies partag&eacute;es (tous les
+ autres syst&egrave;mes)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/backend/</TD><TD>Programme
+ d'arri&egrave;re-plan pour connexion &agrave; diverses imprimantes.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/cgi-bin/</TD><TD>Programmes CGI pour
+ l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/daemon/</TD><TD>D&eacute;mons pour la
+ surveillance et pour la prise en charge LPD.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/filter/</TD><TD>Filtres pour divers
+ types de fichiers.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/locale/</TD><TD>Emplacement des fichiers
+ de messages sp&eacute;cifiques &agrave; chaque langue. (System V)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/nls/msg/</TD><TD>Emplacement des fichiers
+ de messages sp&eacute;cifiques &agrave; chaque langue. (Compaq Tru64 UNIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/locale/</TD><TD>Emplacement des fichiers
+ de messages sp&eacute;cifiques &agrave; chaque langue. (GNU/Linux, *BSD)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/accept</TD><TD>La commande d'acceptation
+ de travaux.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/cupsd</TD><TD>L'ordonnanceur CUPS.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpadmin</TD><TD>L'outil d'administration
+ d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpc</TD><TD>L'outil d'administration
+ d'imprimante Berkeley.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpinfo</TD><TD>Les commandes
+ &quot;get-devices&quot; et &quot;get-ppds&quot;.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpmove</TD><TD>La commande &quot;move-jobs&quot;.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/reject</TD><TD>La commande &quot;reject-jobs&quot;.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/share/catman/a_man/
+<BR> /usr/share/catman/u_man/</TD><TD>Pages de manuel (IRIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/man/</TD><TD>Pages de manuel (Compaq
+ Tru64 UNIX, HP-UX, Solaris)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/man/</TD><TD>Pages de manuel (tous les autres
+ syst&egrave;mes)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/</TD><TD>Emplacement des
+ fichiers de donn&eacute;es des filtres.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/testprint.ps</TD><TD>Fichier
+ de page de test PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/fonts/</TD><TD>Emplacement des
+ polices de caract&egrave;res PostScript pour le RIP PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/model/</TD><TD> Emplacement des
+ fichiers PPD (&quot;PostScript Printer Description&quot;) et des scripts
+ d'interface pouvant &ecirc;tre employ&eacute;s pour configurer une file
+ d'impression.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/</TD><TD> D'autres
+ fichiers d'initialisation du RIP PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/Fontmap</TD><TD> Le
+ fichier de conversion de polices (convertit des noms de fichiers en
+ noms de polices)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/templates/</TD><TD>Emplacement des
+ fichiers &quot;templates&quot; HTML pour l'interface &quot;web&quot;.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/doc/cups/</TD><TD>Documentation et
+ donn&eacute;es des pages &quot;web&quot; pour l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/log/cups/</TD><TD>Emplacement des fichiers de
+ suivi de l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/spool/cups/</TD><TD>Emplacement des fichiers
+ d'impression en attente de traitement.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 ALIGN="RIGHT"><A NAME="FAQ">E - R&eacute;soudre les probl&egrave;mes courants</A></H1>
+<P>Cette annexe couvre certains des probl&egrave;mes courants rencontr&eacute;s par
+ les utilisateurs lors de la premi&egrave;re installation / configuration /
+ utilisation de CUPS.</P>
+<P>Le support commercial de CUPS est disponible aupr&egrave;s d'Easy Software
+ Products. Pour plus d'informations, veuillez nous contacter:</P>
+<UL>
+<LI>WWW:<A HREF="http://www.easysw.com"> <CODE>http://www.easysw.com</CODE>
+</A></LI>
+<LI>EMail:<A HREF="mailto:info@easysw.com"> info@easysw.com</A></LI>
+<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600</LI>
+</UL>
+<H2><A NAME="13_1">Mes applications ne voient pas les imprimantes
+ disponibles</A></H2>
+<P>Beaucoup d'applications lisent le contenu du fichier<VAR>
+ /etc/printcap</VAR> pour obtenir la liste des imprimantes disponibles.</P>
+<P>La configuration standard de CUPS ne cr&eacute;e pas ce fichier<VAR>
+ /etc/printcap</VAR> automatiquement. Pour activer la cr&eacute;ation et la
+ mise &agrave; jour automatiques de ce fichier, utilisez la directive <A HREF="#Printcap">
+<CODE>Printcap</CODE></A>d&eacute;crite au <A HREF="#PRINTING_MANAGEMENT">
+Chapitre 6, &quot;Administration du syst&egrave;me d'impression&quot;</A>.</P>
+<H2><A NAME="13_2">CUPS ne reconna&icirc;t pas mon nom d'utilisateur et mon
+ mot de passe!</A></H2>
+<P>CUPS vous demandera un nom d'utilisateur UNIX et un mot de passe
+ lorsque vous effectuerez des t&acirc;ches d'administration &agrave; distance ou au
+ moyen d'un navigateur &quot;web&quot;. La configuration standard de CUPS
+ n&eacute;cessite que vous utilisiez le nom d'utilisateur <CODE>root</CODE> et
+ son mot de passe correspondant pour authentifier la requ&ecirc;te.</P>
+<P>Pour des raisons de s&eacute;curit&eacute;, CUPS ne vous autorise pas &agrave;
+ authentifier une requ&ecirc;te d'administration au moyen d'un compte d&eacute;pourvu
+ de mot de passe. Si vous n'avez pas de mot de passe pour le compte <CODE>
+root</CODE>, vous ne pourrez pas faire d'administration &agrave; distance ou
+ via un navigateur &quot;web&quot; !
+<!-- NEED 2in -->
+</P>
+<P>Pour d&eacute;sactiver l'authentification par mot de passe vous devez &eacute;diter
+ le contenu du fichier<VAR> /etc/cups/cupsd.conf</VAR> et commenter les
+ lignes:</P>
+<UL>
+<PRE>
+AuthType Basic
+AuthClass System
+</PRE>
+</UL>
+ pour l'emplacement<VAR> /admin</VAR>. Red&eacute;marrez alors le serveur CUPS
+ comme indiqu&eacute; dans le <A HREF="#PRINTING_MANAGEMENT">Chapitre 6,
+ &quot;Administration du serveur d'impression&quot;</A>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>D&eacute;sactiver les v&eacute;rifications de mot de passe autorisera tout
+ utilisateur local &agrave; modifier les imprimantes et les classes, mais
+ l'administration distante depuis un autre poste ne sera toujours pas
+ autoris&eacute;e.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H2><A NAME="ALLOW_REMOTE">Je ne peux pas effectuer de t&acirc;ches
+ d'administration depuis un poste distant!</A></H2>
+<P>La configuration standard de CUPS limite l'administration au poste
+ local. Pour ouvrir l'acc&egrave;s, &eacute;ditez le contenu du fichier<VAR>
+ /etc/cups/cupsd.conf</VAR> et commentez les lignes:</P>
+<UL>
+<PRE>
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+</PRE>
+</UL>
+ pour l'emplacement<VAR> /admin</VAR>. Red&eacute;marrez alors le serveur CUPS
+ comme indiqu&eacute; dans le <A HREF="#PRINTING_MANAGEMENT">Chapitre 6,
+ &quot;Administration du serveur d'impression&quot;</A>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Autoriser l'acc&egrave;s &agrave; l'administration pour tous les h&ocirc;tes pr&eacute;sente un
+ risque potentiel de s&eacute;curit&eacute;. Veuillez vous reporter au <A HREF="#PRINTING_MANAGEMENT">
+Chapitre 6, &quot;Administration du serveur d'impression&quot;</A> pour une
+ description de ces risques ainsi que des m&eacute;thodes pour les minimiser.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+<H2><A NAME="13_4">Je ne peux pas effectuer de t&acirc;ches d'administration
+ depuis mon navigateur &quot;web&quot;!</A></H2>
+<P>Ce probl&egrave;me est g&eacute;n&eacute;ralement d&ucirc;:</P>
+<OL>
+<LI>au fait de donner le mauvais mot de passe pour le compte root.</LI>
+<LI>au fait d'acc&eacute;der au serveur CUPS en utilisant le nom d'h&ocirc;te ou
+ l'adresse IP sans activer l'acc&egrave;s &agrave; distance pour les fonctions
+ d'administration. Cela peut &ecirc;tre corrig&eacute; en suivant les instructions
+ pr&eacute;sentes dans la section <A HREF="#ALLOW_REMOTE"> &quot;Je ne peux pas
+ effectuer de t&acirc;ches d'administration depuis un poste distant!&quot;</A>
+ &eacute;tudi&eacute;e pr&eacute;c&eacute;demment dans cette annexe.</LI>
+<LI>au fait de ne pas avoir de mot de passe pour le compte root. Pour
+ des raisons de s&eacute;curit&eacute;, CUPS n'authentifiera pas les comptes
+ utilisateur d&eacute;pourvus de mot de passe.</LI>
+<LI>au fait de s'authentifier au moyen d'un compte distinct de root mais
+ qui n'est pas membre du groupe system.</LI>
+<LI>au fait de configurer CUPS pour utiliser l'authentification &quot;Digest&quot;
+ et tenter d'y acc&eacute;der au moyen d'un navigateur &quot;web&quot; ne prenant pas en
+ charge ce type d'authentification.</LI>
+</OL>
+<H2><A NAME="13_5">Messages &quot;Connection Refused&quot;</A></H2>
+<P>Dans des circonstances normales, des messages &quot;connection refused&quot;
+ pour une imprimante r&eacute;seau peuvent &ecirc;tre rencontr&eacute;s de temps en temps.
+ La plupart des interfaces r&eacute;seau autorisent une unique connexion &agrave; un
+ instant donn&eacute; (un travail &agrave; la fois) et refuseront l'acc&egrave;s &agrave; tous les
+ autres syst&egrave;mes tant que la premi&egrave;re connexion sera active. CUPS
+ retente automatiquement de se connecter toutes les 30 secondes.</P>
+<P>Si le probl&egrave;me persiste et que vous ne pouvez imprimer aucun travail
+ sur l'imprimantes, v&eacute;rifiez qu'une autre machine ne maintient pas une
+ connexion avec l'imprimante, et que vous avez s&eacute;lectionn&eacute; le bon port
+ ou le bon nom d'imprimante.</P>
+<P>De m&ecirc;me, la plupart des serveurs d'impression externes refuseront les
+ connexions si une imprimante est hors tension ou hors ligne. V&eacute;rifiez
+ que l'imprimante affect&eacute;e est sous tension et en ligne.</P>
+<H2><A NAME="13_6">Message &quot;Write Error&quot;</A></H2>
+<P>Si vous obtenez des messages &quot;write error&quot; sur une file d'impression,
+ l'interface de l'imprimante (g&eacute;n&eacute;ralement une interface Hewlett Packard
+ JetDirect) a d&eacute;pass&eacute; le d&eacute;lai d'attente maximum et r&eacute;sili&eacute; la connexion
+ r&eacute;seau avec votre poste de travail.</P>
+<P>L'erreur est caus&eacute;e par le d&eacute;lai d'amor&ccedil;age qui existe entre
+ l'&eacute;tablissement initial de la connexion &agrave; l'imprimante et l'envoi
+ effectif des donn&eacute;es de la premi&egrave;re page imprim&eacute;e.
+<!-- NEED 3in -->
+</P>
+<P> Pour corriger le probl&egrave;me, chagez la valeur du d&eacute;lai d'attente de
+ l'interface et amenez sa valeur &agrave; un minimum de 180 secondes soit 3
+ minutes. Pour changer le d&eacute;lai sur une interface Hewlett Packard
+ JetDirect, tapez:</P>
+<UL>
+<PRE>
+<B>telnet adresse-ip ENTER</B>
+
+Trying adresse-ip...
+Connected to adresse-ip.
+Escape character is `^]'.
+
+Please type [Return] two times, to initialize telnet configuration
+For HELP type &quot;?&quot;
+&gt; <B>idle-timeout: 180 ENTREE</B>
+&gt; <B>quit ENTREE</B>
+</PRE>
+</UL>
+</BODY>
+</HTML>
diff --git a/doc/fr/sam.pdf b/doc/fr/sam.pdf
new file mode 100644
index 000000000..da98f1ef4
--- /dev/null
+++ b/doc/fr/sam.pdf
Binary files differ
diff --git a/doc/fr/sam.shtml b/doc/fr/sam.shtml
new file mode 100644
index 000000000..4c0a722bb
--- /dev/null
+++ b/doc/fr/sam.shtml
@@ -0,0 +1,4607 @@
+<HTML>
+ <HEAD>
+ <TITLE>CUPS - Manuel de l'administrateur CUPS</TITLE>
+ <META NAME="author" CONTENT="Easy Software Products">
+ <META NAME="translator" CONTENT="Marian REYT-LLABRES">
+ <META NAME="copyright" CONTENT="Copyright 1997-2003, All Rights Reserved">
+ <META NAME="docnumber" CONTENT="CUPS-SAM-1.1.14">
+</HEAD>
+<BODY BGCOLOR="#ffffff">
+
+<H1 ALIGN="RIGHT"><A NAME="1">Préface</A></H1>
+<P>Ce manuel de l'administrateur fournit les informations d'administration pour le
+système d'impression CUPS<SUP>TM</SUP> (Common UNIX Printing System<SUP>TM</SUP>) version 1.1.14.</P>
+
+<P><hr width="50%" size="1px" color="#000000"><I><b>Note du traducteur : </b>Amies lectrices, amis lecteurs, j'ai fait le choix de <b>ne pas traduire</b> l'expression anglaise <b>"default"</b> par la
+version française
+habituellent utilisée <b>"par défaut"</b> que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents".
+<br><br>
+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès",
+personnellement je cherche encore mon "imprimante par excès" !)
+mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en
+précise pas <b>explicitement</b> la valeur/nature/teneur".
+<br><br>
+Or la langue française possède justement un mot pout exprimer ce concept
+: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la
+conséquence nécessaire."). Dans la mesure du possible, j'utiliserai
+cet adjectif sauf dans les cas où son emploi n'est pas suffisamment <b>explicite</b> (sic !). Je lui
+préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard".
+<br><br>
+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable,
+je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le
+reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur !
+<br><br>
+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à
+l'amélioration constante de la qualité du présent manuel.
+<br><br>
+Bonne lecture !
+</I><hr width="50%" size="1px" color="#000000"></P>
+
+
+<H2><A NAME="1_1">Aperçu du système</A></H2>
+
+<P>CUPS fournit une couche d'impression portable pour les systèmes d'exploitation de
+type UNIX&reg;. Il a été développé par <A HREF="http://www.easysw.com">Easy
+ Software Products</A> pour promouvoir une solution d'impression standard pour
+tous les vendeurs et utilisateurs d'UNIX. CUPS fournit des interfaces en ligne de
+commande de type System V et Berkeley.
+</P>
+
+<P>CUPS utilise le protocol IPP (Internet Printing Protocol) comme base de l'administration
+des travaux et files d'impression. Les protocoles LPD ("Line Printer Daemon"), SMB
+("Server Message Block"), et AppSocket (JetDirect) sont également pris en charge avec
+des fontionnalités réduites. CUPS ajoute l'exploration réseau des imprimantes ("network
+printer browsing") et des options d'impression basées sur PPD ("PostScript Printer
+Definition") pour prendre en charge l'impression "dans le monde réel" sous UNIX.
+</P>
+
+<P>CUPS inclut également une version adaptée de GNU/Ghostscript (actuellement basée
+sur la version 5.50) et un module de rendu (RIP - Raster Image Processor) pour fichier image qui sont utilisés pour prendre
+en charge les imprimantes non-PostScript. Des pilotes d'exemple (incluant ces filtres)
+pour imprimantes HP et EPSON sont également inclus.
+</P>
+
+<!-- NEED 3in -->
+<H2><A NAME="1_2">Aperçu du document</A></H2>
+<P>
+Ce manuel de l'administrateur est organisé de la manière suivante:
+</P>
+
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Aperçu du système d'impression</A></LI>
+<LI><A HREF="#BUILDING_INSTALLING">2 - Construire et installer CUPS</A></LI>
+<LI><A HREF="#MANAGING_PRINTERS">3 - Administration des imprimantes</A></LI>
+<LI><A HREF="#PRINTER_CLASSES">4 - Classes d'imprimantes</A></LI>
+<LI><A HREF="#CLIENT_SETUP">5 - Configuration côté client</A></LI>
+<LI><A HREF="#PRINTING_MANAGEMENT">6 - Administration du système d'impression</A></LI>
+<LI><A HREF="#PRINTING_OTHER">7 - Imprimer depuis et vers d'autres système</A></LI>
+<LI><A HREF="#LICENSE">A - Licence d'utilisation du logiciel (NdT : en anglais)</A></LI>
+<LI><A HREF="#COMMON_NETWORK">B - Réglages réseau courants</A></LI>
+<LI><A HREF="#PRINTER_DRIVERS">C - Pilotes d'imprimantes</A></LI>
+<LI><A HREF="#FILES">D - Liste des fichiers</A></LI>
+<LI><A HREF="#FAQ">E - Résoudre les problèmes courants</A></LI>
+</UL>
+<H2><A NAME="1_3">Conventions d'écriture</A></H2>
+
+<P>
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abréviations</A></H2>
+ Les abréviations suivantes sont utilisées au cours de ce manuel:
+<UL>
+<DL>
+<DT>ko</DT>
+<DD>Kilo-octets, ou 1024 octets
+<BR>&nbsp;</DD>
+<DT>Mo</DT>
+<DD>Méga-octets, ou 1048576 octets
+<BR>&nbsp;</DD>
+<DT>Go</DT>
+<DD>Giga-octets, ou 1073741824 octets
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Autres références</A></H2>
+<UL>
+<DL>
+<DT>CUPS - Manuel du programmeur (en anglais)</DT>
+<DD>Un guide du programmeur pour interagir avec CUPS ou y ajouter des extensions.
+<BR>&nbsp;</DD>
+<DT>CUPS - Manuel de l'utilisateur</DT>
+<DD>Un guide d'utilisation pour l'utilisateur final du logiciel CUPS.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Aperçu du système d'impression</A></H1>
+<P>Ce chapitre fournit un aperçu de la manière dont CUPS fonctionne.</P>
+<H2><A NAME="2_1">Le problème d'impression</A></H2>
+<P>Depuis des années<I> le problème d'impression</I> a empoisonné le monde UNIX.
+Contrairement à Microsoft&reg; Windows&reg; ou Mac OS, UNIX n'a pas d'interface standard ou
+de système en place pour prendre en charge les imprimantes. Parmi les solutions actuellement
+disponibles, les systèmes Berkeley et System V sont prédominants.</P>
+
+<P>
+ Ces systèmes d'impressions prennent en charge les imprimantes de type matriciel texte ou les
+ imprimantes PostScript (texte et graphique), et avec quelques ajustements il peuvent prendre en
+ charge un grand nombre d'imprimantes et de formats de fichiers. Cependant, puisque chaque
+ version de système d'exploitation UNIX utilise un système d'impression différent de celui
+ de son voisin, il est extrêmement difficile de développer des pilotes d'imprimantes pour une
+ vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné au faible nombre de
+ clients pour chaque variante d'UNIX, a poussé les fabricants d'imprimantes à abandonner la prise en
+ charge globale de tous les UNIX.
+</P>
+
+<P>
+ CUPS est conçu pour éliminer <I>le problème d'impression</I>. Un système d'impression
+ commun peut être utilisé par toutes les variantes d'UNIX pour prendre en charge les
+ capacités d'impression dont les utilisateurs ont besoin. Les fabricants d'imprimantes peuvent
+ utiliser l'interface modulaire des filtres pour développer un unique pilote qui prend en charge une
+ large gamme de formats de fichiers et ce, sans presque aucun effort. Etant donné que CUPS fournit
+ une interface compatible avec les commandes Berkeley et System V, les utilisateurs (et les applications)
+ peuvent tirer bénéfice de cette nouvelle technologie sans avoir à faire de changements.
+</P>
+
+<H2><A NAME="2_2">La technologie</A></H2>
+
+<P>
+ CUPS est basé sur un standard émergeant d'Internet appelé IPP (Internet Printing Protocol). IPP a été adopté
+ par des douzaines de fabricants d'imprimantes et de serveurs d'impression et est pris en charge par
+ Microsoft Windows 2000.
+</P>
+
+<P>
+ IPP définit un protocole standard pour imprimer ainsi qu'administrer les travaux d'impression et les options
+ des imprimantes telles que la taille du support d'impression, la résolution, etc. Comme tout protocole de la pile
+ TCP/IP, IPP peut être utilisé localement ou à travers Internet pour atteindre des imprimantes éloignées de centaines
+ ou de milliers de kilomètres. Contrairement à d'autres protocoles de la pile TCP/IP, IPP prend en charge le
+ contrôle d'accès, l'authentification et l'encryptage, ce qui fait de lui une solution d'impression bien plus efficace
+ et sécurisée que ses ancêtres.
+</P>
+
+<P>
+ IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText Transport Protocol) qui est à la base
+ des serveurs "web" sur l'Internet. Ceci permet aux utilisateurs de lire la documentation, vérifier les informations
+ sur l'état des imprimantes ou du serveur, administrer les imprimantes, les classes d'imprimantes et les travaux
+ d'impression en utilisant leur navigateur "web".
+</P>
+
+<P>
+ CUPS fournit un système d'impression complet basé sur IPP/1.1 prenant en charge l'authentification
+ "Basic", "Digest" et par certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur,
+ le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une future version de CUPS.
+</P>
+
+<H2><A NAME="2_3">Travaux d'impression</A></H2>
+
+<P>
+ Tout fichier ou groupe de fichiers soumis à l'impression est appelé un <I>travail d'impression</I>. Les travaux
+ d'impression sont identifiés par un nombre unique en commençant à 1 et sont affectés à une destination particulière,
+ généralement une imprimante. Les travaux d'impression peuvent également inclure des options associées telles que la
+ taille du support d'impression, le nombre de copies et la priorité dans la file d'impression.
+</P>
+
+<H2><A NAME="2_4">Classes d'imprimantes</A></H2>
+
+<P>
+ CUPS prend en charge des collections d'imprimantes connues sous le nom de <I>classes</I>. Les travaux d'impression
+ transmis à une classe d'imprimantes sont envoyés à la première imprimante disponible dans la classe.
+</P>
+
+<H2><A NAME="2_5">Filtres</A></H2>
+
+<P>Les filtres permettent à un utilisateur ou une application d'imprimer de nombreux types de documents sans
+effort supplémentaire. Les travaux d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés à
+l'imprimante. Certains filtres convertissent les fichiers de travaux d'impression dans différents formats que
+l'imprimante peut comprendre. D'autres ne font que des sélections de page et des tris.
+</P>
+
+<P>CUPS fournit des filtres pour imprimer de nombreux types de fichiers image, des fichier HP-GL/2,
+fichiers PDF et texte. CUPS fournit également des filtres PostScript et RIP (Raster Image Processor) qui
+convertissent les fichiers PostScript ou image en format "bitmap" qui peut être envoyé à une
+imprimante de type "matriciel" (NdT : il s'agit ici, des imprimantes dont l'impression est générée au moyen d'une
+grille de points
+comme l'étaient les vénérables imprimantes à aiguilles de notre enfance, mais pas seulement elles puisque les
+imprimantes à jet
+d'encre actuelles sont également de type matriciel... par opposition aux imprimantes laser dont la méthode de génération
+d'impression est différente.)
+</P>
+
+<H2><A NAME="2_6">Programmes d'arrière-plan (Backends)</A></H2>
+
+<P>Les programmes d'arrière-plan effectuent le travail le plus important : ils envoient les données
+d'impression à l'imprimante.
+</P>
+
+<P>CUPS fournit des programmes d'arrière-plan pour imprimer via des ports de type parallèle, série, USB et à travers un
+réseau au moyen des protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des programmes d'arrière-plan
+additionnels sont disponibles sous forme de paquetage de service réseau comme le programme d'arrière_plan SMB
+inclus dans le célèbre logiciel SAMBA.
+</P>
+
+<P>Les programmes d'arrière-plan sont également utilisés pour déterminer les périphériques
+disponibles. Au démarrage, chaque programme d'arrière-plan est interrogé afin de déterminer la liste des
+périphériques qu'il prend en charge, ainsi que toute information disponible. Cela permet au programme d'arrière-plan
+de gestion du port parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 est branchée sur le port
+parallèle 1, par exemple.
+</P>
+
+<H2><A NAME="2_7">Pilotes d'imprimantes</A></H2>
+
+<P>Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs filtres spécifiques à une imprimante. CUPS inclut
+des pilotes d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet Hewlett-Packard et les imprimantes EPSON jet
+d'encre couleur Stylus Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien que ces pilotes ne produisent
+pas des impressions de qualité optimale pour les différents modèles d'imprimantes, ils fournissent une impression de
+base et démontrent comment vous pouvez écrire vos propres pilotes d'imprimantes et les incorporer dans CUPS.
+</P>
+
+<H2><A NAME="2_8">Réseau</A></H2>
+
+<P>Les imprimantes et classes d'imprimantes sur le système local sont automatiquement partagées avec les autres systèmes
+sur le réseau. Cela vous permet de configurer un système hôte pour tous les autres. Les utilisateurs pourront sélectionner
+une imprimante locale par son nom ou une imprimante à distance en utilisant la syntaxe &quot;nom_imprimante@serveur&quot;.
+</P>
+
+<P>CUPS fournit également des <I>classes d'imprimantes implicites</I> (NdT : le terme "implicite" est ici la traduction
+litérale du même mot anglais "implicit" et non celle de l'expression "default". cf. ma remarque dans la préface du présent manuel.
+De toute façon, CUPS ne prévoit pas de "default class" c'est-à-dire de "classe de base", donc aucune ambiguïté possible
+ici.), qui sont des collections d'imprimantes ou
+de classes d'imprimantes qui portent le même nom. Cela vous permet de configurer de multiples serveurs pointant vers
+la même imprimante réseau physique, par exemple, de sorte que vous ne dépendez pas d'un seul serveur pour pouvoir
+imprimer. Etant donné que cette méthode vous permet de travailler avec des classes d'imprimantes, vous pouvez configurer
+de multiples serveurs et imprimantes sans jamais vous soucier d'un simple point en panne tant que tous les autres serveurs
+ne tombent pas en panne en même temps.
+</P>
+
+<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Construire et installer CUPS</A></H1>
+
+<P>Ce chapitre décrit comment construire et installer CUPS. Si vous installez une distribution binaire (précompilée) du produit,
+veuillez vous reporter à la section,<A HREF="#BINARY"> Installer une distribution binaire</A>.
+</P>
+
+<H2><A NAME="3_1">Installer à partir d'une distribution du code source</A></H2>
+
+
+<P>Cette section décrit comment compiler et installer CUPS sur votre système à partir du code source du produit.</P>
+
+<H3><A NAME="REQUIREMENTS">Conditions nécessaires</A></H3>
+
+<P>Vous aurez besoin d'un compilateur C et C++ conforme à la norme ANSI pour construire CUPS sur votre système.
+Comme son nom l'indique, CUPS est conçu pour fonctionner sur le système d'exploitation UNIX, cependant la plupart des
+librairies, des filtres et des programmes d'arrière-plan devraient également se compiler et fonctionner sous Microsoft Windows.
+</P>
+
+ <P>Pour les filtres de fichiers image et PostScript, vous aurez besoin des librairies JPEG, PNG, TIFF et ZLIB. CUPS
+se construira sans elles mais avec des fonctionnalités singulièrement réduites. Easy Software Products maintient un
+miroir des versions actuelles de ces librairies à l'adresse:
+ </P>
+
+<UL>
+<PRE>
+<A HREF="ftp://ftp.easysw.com/pub/libraries">ftp://ftp.easysw.com/pub/libraries</A>
+</PRE>
+</UL>
+
+<P>Si vous faîtes des changements dans les pages de manuel vous aurez besoin de GNU groff ou d'un autre
+paquetage compatible nroff. GNU groff est disponible à l'adresse:
+</P>
+
+<UL>
+<PRE>
+<A HREF="ftp://ftp.gnu.org/pub/groff">ftp://ftp.gnu.org/pub/groff</A>
+</PRE>
+</UL>
+
+<P>La documentation est formatée en utilisant le programme HTMLDOC. Si vous voulez faire des changements, vous pouvez
+obtenir le programme HTMLDOC à l'adresse:
+<P>
+
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
+</PRE>
+</UL>
+
+<P>Enfin, vous aurez besoin d'un programme <CODE>make</CODE> qui comprend les directives <CODE>include</CODE> - les
+développeurs FreeBSD, NetBSD et OpenBSD devraient utiliser le programme <CODE>gmake</CODE>.
+</P>
+
+<H3><A NAME="COMPILING">Compiler CUPS</A></H3>
+
+<P>CUPS utilise GNU autoconf pour configurer les "makefiles" et le code source pour votre système. Tapez simplement la
+commande suivante pour configurer CUPS pour votre système:
+</P>
+
+<UL>
+<PRE>
+<B>./configure ENTREE</B>
+</PRE>
+</UL>
+
+<P>L'installation standard installera CUPS dans les répertoires <VAR>/etc</VAR>, <VAR>/usr</VAR>, et <VAR>/var</VAR>
+de votre système, ce qui écrasera toute commande d'impression existant déjà dans votre système. Utilisez l'option
+<CODE>--prefix</CODE> pour installer CUPS à un autre emplacement:
+</P>
+
+<UL>
+<PRE>
+<B>./configure --prefix=/autre/répertoire ENTREE</B>
+</PRE>
+</UL>
+
+<P>Si les librairies PNG, JPEG, TIFF, et ZLIB ne sont pas installées à un emplacement habituel du système (généralement
+il s'agit de <VAR>/usr/include</VAR> et <VAR>/usr/lib</VAR>) vous devrez définir les variables d'environnement <CODE>CFLAGS</CODE>,
+<CODE>CXXFLAGS</CODE>, et <CODE>LDFLAGS</CODE> avant d'exécuter la commande configure:
+</P>
+
+<UL>
+<PRE>
+<B>setenv CFLAGS &quot;-I/some/directory&quot; ENTREE</B>
+<B>setenv CXXFLAGS &quot;-I/some/directory&quot; ENTREE</B>
+<B>setenv LDFLAGS &quot;-L/some/directory&quot; ENTREE</B>
+<B>setenv DSOFLAGS &quot;-L/some/directory&quot; ENTREE</B>
+<B>./configure ... ENTREE</B>
+</PRE>
+</UL>
+<P>ou:</P>
+<UL>
+<PRE>
+<B>CFLAGS=&quot;-I/some/directory&quot;; export CFLAGS ENTREE</B>
+<B>CXXFLAGS=&quot;-I/some/directory&quot;; export CXXFLAGS ENTREE</B>
+<B>LDFLAGS=&quot;-L/some/directory&quot;; export LDFLAGS ENTREE</B>
+<B>DSOFLAGS=&quot;-L/some/directory&quot;; export DSOFLAGS ENTREE</B>
+<B>./configure ... ENTREE</B>
+</PRE>
+</UL>
+
+<P>Pour activer le support de l'encryptage, vous devrez également activer l'option &quot;--enable-ssl&quot;:
+</P>
+
+<UL>
+<PRE>
+./configure --enable-ssl
+</PRE>
+</UL>
+
+<P>La prise en charge SSL et TLS nécessite la librairie OpenSSL, disponible à l'adresse:
+</P>
+
+<UL>
+<PRE>
+<A HREF="http://www.openssl.org">http://www.openssl.org</A>
+</PRE>
+</UL>
+
+<P>Si les en-têtes et les librairies OpenSSL ne sont pas installées dans les répertoires standards, utilisez les
+options <CODE>--with-openssl-includes</CODE> et <CODE>--with-openssl-libs</CODE>:
+</P>
+
+<UL>
+<PRE>
+./configure --enable-ssl \
+ --with-openssl-includes=/foo/bar/include \
+ --with-openssl-libs=/foo/bar/lib
+</PRE>
+</UL>
+
+<P>Une fois que vous avez configuré toutes ces choses, tapez simplement:
+</P>
+
+<UL>
+<PRE>
+<B>make ENTER</B>
+</PRE>
+</UL>
+
+<P>pour compiler le logiciel.</P>
+
+<!-- NEED 4in -->
+</P>
+
+<H3><A NAME="INSTALLING">Installer le logiciel</A></H3>
+
+<P>Utilisez la cible &quot;install&quot; pour installer le logiciel:
+</P>
+
+<UL>
+<PRE>
+<B>make install ENTREE</B>
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> AVERTISSEMENT:</B>
+
+<P>Installer CUPS écrasera votre système d'impression précédent. Si vous rencontrez des difficultés avec le logiciel
+CUPS et devez revenir à votre ancien système d'impression, vous devrez réinstaller celui-ci à partir de CD originaux
+de votre système d'exploitation.
+</P>
+
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="RUNNING">Exécuter le logiciel</A></H3>
+
+<P>Une fois que vous avez installé le logiciel vous pouvez démarrer le serveur CUPS en tapant:
+</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/cupsd ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<H2><A NAME="BINARY">Installer une distribution binaire du logiciel</A></H2>
+
+<P>CUPS est fourni dans une variété de formats binaires. Easy Software Products fournit des binaires sous forme
+d'archives au format TAR avec des scripts d'installation et de désinstallation (distributiond dites &quot;portables&quot;),
+sous forme de format RPM et DPKG pour les distributions RedHat et Debian. Les distributions portables sont disponibles
+pour toutes les plateformes tandis que les distributions RPM et DPKG ne le sont que pour GNU/Linux
+</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> AVERTISSEMENT:</B>
+
+<P>Installer CUPS écrasera votre système d'impression précédent. Si vous rencontrez des difficultés avec le logiciel
+CUPS et devez revenir à votre ancien système d'impression, vous devrez réinstaller celui-ci à partir de CD originaux de
+votre système d'exploitation.
+</P>
+
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+
+<H3><A NAME="PORTABLE-BINARY">Installer une distribution portable</A></H3>
+
+<P>Pour installer le logiciel CUPS à partir d'une distribution portable vous devrez ouvrir une session en tant
+qu'utilisateur root; utiliser la commande <CODE>su</CODE> est suffisant. Une fois que vous êtes utilisateur root,
+lancer le script d'installation avec la commande:
+</P>
+
+<UL>
+<PRE>
+<B>./cups.install ENTREE</B>
+</PRE>
+</UL>
+
+<P>Après vous avoir posé quelques questions de type oui/non, le logiciel CUPS va s'installer et l'ordonnanceur sera
+démarré automatiquement.
+</P>
+
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="RPM-BINARY">Installer une distribution de type RPM</A></H3>
+<P>Pour installer le logiciel CUPS à partir d'une distribution RPM vous devez ouvrir une session en tant qu'utilisateur
+root; utiliser la commande <CODE>su</CODE> est suffisant. Une fois connecté en tant qu'utilisateur root, lancez simplement
+RPM au moyen de la commande:
+</P>
+
+<UL>
+<PRE>
+<B>rpm -e lpr</B>
+<B>rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTREE</B>
+</PRE>
+</UL>
+<P>Après un petit délai, le logiciel CUPS sera installé et l'ordonnanceur sera démarré automatiquement.</P>
+
+<H3><A NAME="DPKG-BINARY">Installer une distribution de type DEBIAN</A></H3>
+<P>Pour installer le logiciel CUPS à partir d'une distribution DEBIAN vous devez ouvrir une session en tant qu'utilisateur
+root; utiliser la commande <CODE>su</CODE> est suffisant. Une fois connecté en tant qu'utilisateur root, lancez simplement
+dpkg au moyen de la commande:
+</P>
+
+<UL>
+<PRE>
+<B>dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTREE</B>
+</PRE>
+</UL>
+
+<P>Après un court délai, le logiciel CUPS sera installé et l'ordonnanceur sera automatiquement démarré.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="MANAGING_PRINTERS">3 - Administration les imprimantes</A></H1>
+
+<P>Ce chapitre décrit comment ajouter votre première imprimante et comment administrer vos imprimantes.
+</P>
+
+<H2><A NAME="4_1">Les bases</A></H2>
+
+<P>Chaque file d'impression a un nom associé; le nom de l'imprimante doit commencer avec une lettre et peut comporter
+jusqu'à 127 lettres, des chiffres ou un caractère de soulignement "_" ("underscore"). La casse des caractères n'est pas
+significative, par exemple les chaînes de caractères &quot;IMPRIMANTE&quot;, &quot;Imprimante&quot; et
+&quot;imprimante&quot; sont considérées comme
+le même nom.
+</P>
+
+<P>Les files d'impression ont également un périphérique associé. Ce périphérique peut être un port parallèle, une
+interface réseau, etc. Les périphériques dans CUPS utilisent des URI (Uniform Resource Identifiers) qui sont une
+forme plus générale des URL (Uniform Resource Locator) qui sont utilisés par votre noavigateur "web". Par exemple,
+le premier port parallèle dans GNU/Linux est habituellement désigné par l'URI de périphérique <CODE>parallel:/dev/lp1</CODE>.
+</P>
+
+<!-- NEED 2.5in -->
+</P>
+
+<P>Vous pouvez voir une liste complète des périphériques pris en charge en lançant la commande <CODE>lpinfo(8)</CODE>:
+</P>
+
+<UL>
+<PRE>
+<B>lpinfo -v ENTREE</B>
+file file
+network socket
+network http
+network ipp
+network lpd
+direct parallel:/dev/lp1
+serial serial:/dev/ttyS1?baud=115200
+serial serial:/dev/ttyS2?baud=115200
+direct usb:/dev/usb/lp0
+network smb
+</PRE>
+</UL>
+
+<P>L'option <CODE>-v</CODE> indique que vous voulez la liste de tous les périphériques disponibles. Le premier
+mot de chaque ligne est le type de périphérique (direct, fichier, réseau, série) et est suivi par l'URI du périphérique
+ou le nom de la méthode d'accès à ce périphérique. Les périphériques de type fichier ont des URI de périphérique de la
+forme <CODE>file:/répertoire/nom_fichier</CODE> tandis que les périphériques réseau utilisent la forme plus familière
+ <CODE>methode://serveur</CODE> ou <CODE>méthode://serveur/chemin</CODE>.
+</P>
+
+<P>Enfin, les files d'impression ont généralement un fichier PPD (PostScript Printer Definition) associé. Les fichiers
+PPD décrivent les capacités de chaque imprimante, les tailles de support prises en charge, etc., et sont utilisés pour
+les imprimantes PostScript et non-PostScript. CUPS inclut des fichiers PPD pour les imprimantes HP LaserJet et Deskjet,
+EPSON Stylus, et EPSON 9 et 24 aiguilles.
+</P>
+
+<H2><A NAME="4_2">Ajouter votre première imprimante</A></H2>
+
+<P>CUPS fournit deux méthodes pour ajouter des imprimantes : un programme en ligne de commande nommé
+<CODE>lpadmin(8)</CODE> et une inteface "web". La commande <CODE>lpadmin</CODE> vous permet d'effectuer la plupart des
+tâches d'administration d'imprimantes à partir de la ligne de commande, elle est située dans le répertoire <VAR> /usr/sbin</VAR>.
+L'interface "web" est disponible à l'adresse:
+</P>
+
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>et vous quide pas à pas au travers des étapes de configuration d'imprimante. Si vous n'aimez pas les interfaces en
+ligne de commande, essayez plutôt <A HREF="#ADD_WEB">l'interface web</A>.
+</P>
+
+<H3><A NAME="4_2_1">Ajouter votre première imprimante depuis la ligne de commande</A></H3>
+
+<P>Exécutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-p</CODE> pour ajouter une imprimante à CUPS:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -E -v <I>périphérique</I> -m <I>ppd</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P>Pour une imprimante HP DeskJet connectée au port parallèle, la commande serait:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTREE</B>
+</PRE>
+</UL>
+<P>De la même manière, une imprimante HP LaserJet utilisant une interface réseau de type JetDirect à l'adresse IP 11.22.33.44
+serait ajoutée avec la commande:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTREE</B>
+</PRE>
+</UL>
+
+<P>Comme vous pouvez le voir, <CODE>deskjet.ppd</CODE> et <CODE>laserjet.ppd</CODE> sont les fichiers PPD pour les pilotes
+HP DeskJet et HP LaserJet inclus dans CUPS. Vous trouverez une liste complète des fichiers PPD ainsi que celle des imprimantes
+avec lesquelles ils fonctionnent dans l'<A HREF="#PRINTER_DRIVERS">Annexe C, &quot;Pilotes d'imprimantes&quot;</A>.
+</P>
+
+<P>Pour une imprimante matricielle à aiguilles connectée au port série, la commande serait:<P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft deskjet.ppd ENTREE</B>
+</PRE>
+</UL>
+
+<P>Ici, vous indiquez le port série (par exemple S0, S1, d0, s1), le taux de transfert en bauds (par exemple 9600, 19200,
+38400, 115200, etc.), le nombre de bits de partié, et le contrôle de flux. Si vous n'avez pas besoin de contrôle de flux,
+supprimez la partie &quot;+flow=soft&quot;.
+</P>
+
+<H3><A NAME="ADD_WEB">Ajouter votre première imprimante depuis l'interface "web"</A></H3>
+
+<P>Le serveur CUPS fournit une interface ergonomique sous forme d'un assistant ("wizard") pour ajouter les imprimantes.
+Plutôt que devoir déterminer quel URI de périphérique et quel fichier PPD utiliser, vous cliquez simplement sur l'option
+adéquate de la liste et vous remplissez quelques champs de formulaires avec des informations simples. Entrez l'adresse suivante
+dans votre navigateur "web" pour commencer:
+</P>
+
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+
+<P>Cliquez sur le bouton <VAR>Ajouter imprimante</VAR> pour en ajouter une.</P>
+
+<H2><A NAME="4_3">Administrer les imprimantes depuis la ligne de commande</A></H2>
+
+<P>La commande <CODE>lpadmin</CODE> vous permet d'effectuer la plupart des tâches d'administration d'imprimantes depuis la
+ligne de commande. Vous trouverez <CODE>lpadmin</CODE> dans le répertoire <VAR>/usr/bin</VAR>.
+</P>
+
+<H3><A NAME="4_3_1">Ajouter et modifier des imprimantes</A></H3>
+
+<P>Exécutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-p</CODE> pour ajouter ou modifier une imprimante.
+</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> <I>options</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P>Les arguments <I>options</I> peuvent être n'importe lesquels parmi:
+
+<UL>
+<DL>
+<DT>-c<I> classe</I></DT>
+<DD>Ajoute l'imprimante nommée à la classe d'imprimantes <VAR>classe</VAR>. Si la classe d'imprimantes n'existe
+pas alors elle est créée.</DD>
+<DT>-i<I> interface</I></DT>
+<DD>Copie le script pour l'<I>interface</I> vers l'imprimante. Les scripts d'interface sont utilisés par les pilotes d'imprimantes
+System V. Etant donné que tous les filtres sont désactivés lorsque les scripts d'interface sont employés, les scripts ne devraient
+normalement jamais être utilisés à moins qu'il n'y ait aucun autre pilote pour l'imprimante.</DD>
+
+<DT>-m<I> modèle</I></DT>
+<DD>Indique une pilote d'imprimante standard qui est généralement un fichier PPD. Une liste de tous les modèles disponibles peut
+être affichée au moyen de l'option <CODE>-m</CODE>. Une liste de tous les pilotes d'imprimantes inclus dans CUPS peut être
+consultée dans l'<A HREF="#PRINTER_DRIVERS">Annexe
+ C, &quot;Pilotes d'imprimantes&quot;</A>.</DD>
+
+<DT>-r<I> classe</I></DT>
+
+<DD>Retire l'imprimante spécifiée de la classe d'imprimantes <VAR>classe</VAR>. Si la classe qui en résulte est vide, elle est
+supprimée.</DD>
+
+<DT>-v<I> uri-périphérique</I></DT>
+<DD>Indique le périphérique à employer pour dialoguer avec l'imprimante. Si un travail d'impression est actuellement en
+cours d'édition sur l'imprimante spécifiée, il est relancé et envoyé au nouveau périphérique.</DD>
+
+<DT>-D<I> info</I></DT>
+
+<DD>Fournit une description textuelle de l'imprimante, par exemple &quot;Imprimante personnelle de Marcel&quot;.</DD>
+
+<DT>-E</DT>
+
+<DD>Active l'imprimante et accepte les travaux d'impression. Cette option équivaut à exécuter les commandes
+<CODE>enable(1)</CODE> et <CODE>accept(8)</CODE>.</DD>
+
+<DT>-L<I> emplacement</I></DT>
+<DD>Fournit une description textuelle de l'emplacement de l'imprimante, par exemple &quot;Salle informatique n°5&quot;.</DD>
+
+<DT>-P<I> fichier-ppd</I></DT>
+<DD>Indique un fichier PPD local pour le pilote d'imprimante.</DD>
+</DL>
+</UL>
+
+<H3><A NAME="4_3_2">Supprimer des imprimantes</A></H3>
+
+<P>Exécutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-x</CODE> pour supprimer une imprimante:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>printer</I> ENTREE</B>
+</PRE>
+</UL>
+
+<H3><A NAME="4_3_3">Choisir l'imprimante implicite</A></H3>
+
+<P>Exécutez la commande <CODE>lpadmin</CODE> avec l'option <CODE>-d</CODE> pour définir l'imprimante standard:
+</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -d <I>printer</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P>L'imprimante standard peut-être outrepassée par l'utilisateur au moyen de la commande <CODE>lpoptions(1)</CODE>.</P>
+
+<H3><A NAME="4_3_4">Démarrer et arrêter des imprimantes</A></H3>
+
+<P>Les commandes <CODE>enable</CODE> et <CODE>disable</CODE> démarrent et arrêtent les files d'impression, avec les syntaxes respectives suivantes :</P>
+
+<UL>
+<PRE>
+<B>/usr/bin/enable <I>imrimante</I> ENTREE</B>
+<B>/usr/bin/disable <I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P><i><b>Note du traducteur :</b> utilisateurs du shell BASH attention ! <CODE>enable</CODE> est une commande interne de celui-ci.
+Si vous tapez simplement <CODE>enable</CODE> vous
+obtiendrez un message d'erreur car c'est la version interne de BASH qui sera utilisée en standard. Pour effectivement utiliser la commande <CODE>enable</CODE> de CUPS
+vous <u>devez</u> faire précéder son nom du chemin d'accès complet : <CODE>/usr/bin/enable</CODE>.</i></P>
+
+<P>Les imprimantes qui sont désactivées peuvent toujours accepter les travaux d'impression mais n'en imprimeront effectivement
+aucun tant qu'elle ne seront pas réactivées. Cela est utile si une imprimante fonctionne mal et que vous avez besoin de corriger
+le problème (bourrage). Tout travail d'impression mis en file d'attente est imprimé dès que la l'imprimante est réactivée.</P>
+
+<H3><A NAME="4_3_5">Accepter et rejeter les travaux d'impression</A></H3>
+
+<P>Les commandes <CODE>accept</CODE> et <CODE>reject</CODE> permettent respectivement d'indiquer à une imprimante
+qu'elle doit accepter ou rejeter les nouveaux travaux d'impression:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/accept <I>imprimante</I> ENTREE</B>
+<B>/usr/sbin/reject <I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P>Comme indiqué ci-dessus, une imprimante peut être configurée pour ne plus accepter de nouveaux travaux d'impression.
+Une imprimante peut aussi rejeter les nouveaux travaux d'impression bien qu'elle soit en train de terminer le traitement
+de ceux qui ont été mis en file d'attente avant que celle-ci soit désactivée. Ceci est utile si vous avez besoin d'effectuer
+des opérations de maintenance sur l'imprimante et que vous ne voulez pas qu'elle soit disponible pour les utilisateurs pendante
+une longue période.</P>
+
+<H2><A NAME="4_4">Administrer les imprimantes depuis l'interface "web"</A></H2>
+
+<P>L'interface "web" est disponible à l'adresse:</P>
+
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+
+<P>Depuis celle-ci vous pouvez effectuer toutes les tâches d'administrations sur les imprimantes au moyen de
+quelques clics de souris.</P>
+
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_CLASSES">4 - Classes d'imprimantes</A></H1>
+
+<P>Ce chapitre décrit ce que sont les classes d'imprimantes et comment les administrer.</P>
+
+<H2><A NAME="5_1">Les bases</A></H2>
+
+<P>CUPS fournit des collections d'imprimantes appelées <I>classes d'imprimantes</I>. Les travaux soumis à une classe sont
+transmis à la première imprimante disponible de la classe. Les classes peuvent elles auusi être membres d'autres classes, ainsi
+il est possible que vous définissiez de grandes classes réparties afin de fournir un système d'impression à haute disponibilité.
+</P>
+
+<P>CUPS prend également en charge les <I>classe implicites</I>. Les classes implicites fonctionnent comme les classes d'imprimantes,
+mais elles sont créées automatiquement à partir des classes et imprimantes disponibles sur le réseau. Cela vous permet de
+configurer de multiples serveurs d'impression avec des configurations d'imprimantes identiques de sorte que les systèmes
+clients envoient des travaux d'impression au premier serveur disponible. Si un ou plusieurs serveurs deviennent indisponibles,
+les travaux d'impressions sont automatiquement redirigés vers les serveurs encore en fonctionnement, fournissant ainsi un
+système d'impression résistant aux pannes.</P>
+
+<H2><A NAME="5_2">Administrer les classes d'imprimantes depuis la ligne de commande</A></H2>
+<P>Exécutez la commande <CODE>lpadmin</CODE> avec les options <CODE>-p</CODE> et <CODE>
+-c</CODE> pour ajouter une classe d'imprimantes:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -c <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<P>La <I> classe</I> est créée automatiquement si elle n'existe pas.
+Pour retirer une imprimante d'une classe, utilisez l'option <CODE>-r</CODE>:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>imprimante</I> -r <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Pour enlever toute la classe, utilisez l'option <CODE>-x</CODE>:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>classe</I> ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Administrer les classes d'imprimante depuis l'interface "web"</A></H2>
+<P>L'interface "web" est disponible à l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>Les pages <VAR>Ajouter classe</VAR> et <VAR>Modifier classe</VAR> fournissent une liste des imprimantes disponibles.
+Cliquez sur la ou les imprimantes de votre choix pour les ajouter à la classe.</P>
+
+<H2><A NAME="5_4">Classes implicites</A></H2>
+
+<P>Comme indiqué auparavant, les classes implicites sont automatiquement créées à partir des imprimantes et des classes
+disponibles sur le réseau. Pour désactiver cette fonctionnalité,
+réglez la valeur de la directive <A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> sur <CODE>Off</CODE> dans
+le fichier <CODE>cupsd.conf</CODE>. Vous trouverez plus d'information sur la manière de faire cela dans le <A HREF="#PRINTING_MANAGEMENT">
+ Chapitre 6, &quot;Administration du système d'impression&quot;</A>.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="CLIENT_SETUP">5 - Configuration côté client</A></H1>
+
+<P>Ce chapitre expose diverses manières de configurer les clients CUPS pour pouvoir imprimer.</P>
+
+<H2><A NAME="6_1">Les bases</A></H2>
+
+<P>Un client est toute machine qui envoie des travaux d'impression à une autre machine pour édition finale. Les clients peuvent
+également être des serveurs s'il communiquent directement avec des imprimantes qui leur appartiennent.</P>
+
+<P>CUPS prend en charge plusieurs méthodes pour configurer les machines clientes:</P>
+
+<UL>
+<LI><A HREF="#CLIENT_MANUAL">Configuration manuelle des files d'impression.</A></LI>
+<LI><A HREF="#CLIENT_SERVER">Choix d'un serveur unique pour l'impression.</A>
+</LI>
+<LI><A HREF="#CLIENT_AUTO">Configuration automatique des files d'impression.</A></LI>
+<LI><A HREF="#CLIENT_POLL">Choix de plusieurs serveurs pour l'impression.</A></LI>
+</UL>
+<H3><A NAME="CLIENT_MANUAL">Configuration manuelle des files d'impression</A></H3>
+
+<P>La méthode la plus fastidieuse pour configurer les machines clientes est de configurer chaque file d'impression à distance
+à la main au moyen de la commande <CODE>lpadmin</CODE>:
+
+<UL>
+<PRE>
+<B>lpadmin -p <I>imprimante</I> -E -v ipp://<I>serveur</I>/printers/<I>imprimante</I> ENTREE</B>
+</PRE>
+</UL>
+
+<P>Le nom <I>imprimante</I> est le nom de l'imprimante sur la machine serveur. Le nom <CODE>serveur</CODE> est le nom
+d'hôte ou l'adresse IP de la machine serveur. Répètez la commande <CODE>lpadmin</CODE> pour chaque imprimante distante que
+vous désirez utilser.</P>
+
+<H3><A NAME="CLIENT_SERVER">Choix d'un serveur unique pour l'impression</A></H3>
+
+<P>CUPS peut être configuré pour fonctionnner sans file d'attente locale et envoyer tous les travaux d'impression à un serveur
+unique. Cependant, si ce serveur vient à tomber en panne, toute possibilité d'imprimer sera supprimée. Utilisez cette configuration
+uniquement lorsque c'est absolument nécessaire.</P>
+
+<P>Le serveur implicite est normalement &quot;localhost&quot;. Pour outrepasser ce réglage de base,
+créez un fichier nommé<VAR> /etc/cups/client.conf</VAR> et ajoutez une ligne:</P>
+
+
+<UL>
+<PRE>
+ServerName <I>serveur</I>
+</PRE>
+</UL>
+
+<P>au fichier. Le nom <VAR>serveur</VAR> peut être le nom d'hôte ou l'adresse IP du serveur implicite.</P>
+
+<P>Le serveur implicite peut également être adapté en fonction de l'utilisateur. Pour créer un réglage
+spécifique à l'utilisateur, créez un fichier nommé <VAR> ~/.cupsrc</VAR> et ajoutez une ligne:
+
+<UL>
+<PRE>
+ServerName <I>serveur</I>
+</PRE>
+</UL>
+<P>
+<P>au fichier. Le nom <VAR>serveur</VAR> peut être le nom d'hôte ou l'adresse IP du serveur implicite.</P>
+
+<H3><A NAME="CLIENT_AUTO">Configuration automatique des files d'impression</A></H3>
+
+<P>CUPS prend en charge la configuration automatique des clients pour les imprimantes sur le même sous-réseau. Pour
+configurer des imprimantes présentes sur le même sous-réseau, <I>ne faîtes rien</I>. Chaque client devrait voir
+automatiquement les imprimantes disponibles dans un délai de 30 secondes. Les listes des classes et des imprimantes
+sont automatiquement mises à jour chaque fois que des imprimantes et des serveurs sont ajoutés ou retirés.</P>
+
+<P>Si vous désirez également voir les imprimantes sur d'autres sous-réseau, utilisez la directive
+<A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A> comme indiqué ci-après.
+
+<H3><A NAME="CLIENT_POLL">Choix de plusieurs serveurs pour l'impression</A></H3>
+
+<P>Si vous disposez de plusieurs serveurs CUPS sur plusieurs sous-réseaux, vous devriez configurer CUPS pour
+surveiller ces serveurs. La surveillance fournit l'avantage d'automatiser singulièrement la configuration sur les clients, et
+plusieurs clients sur le même sous-réseau peuvent partager les mêmes informations de configuration.</P>
+
+<P>La surveillance est activée en indiquant une ou plusieurs directives
+<A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A> dans le fichier <VAR> /etc/cups/cupsd.conf</VAR>. Pour savoir comment
+faire ces changements, veuillez vous reporter au <A HREF="#PRINTING_MANAGEMENT">
+ Chapitre 6, &quot;Administration du système d'impression&quot;</A>.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Administration du système d'impression</A></H1>
+
+<P>Ce chapitre montre comment configurer le serveur CUPS.</P>
+
+<H2><A NAME="7_1">Les bases</A></H2>
+
+<P>Plusieurs fichiers texte sont utilisés pour configurer CUPS. Tous les fichiers de configuration du serveur sont
+placés dans le répertoire <VAR>/etc/cups</VAR>:</P>
+
+<UL>
+<DL>
+<!-- NEED 1in -->
+
+<DT>classes.conf</DT>
+<DD>Ce fichier contient les informations sur chaque classe d'imprimante. Normalement vous manipulez ce fichier en utilisant
+la commande <CODE>lpadmin</CODE> ou l'interface "web".
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>client.conf</DT>
+<DD>
+Ce fichier fournit le nom du serveur implicite pour les machines clientes. Veuillez vous reporter au
+<A HREF="#CLIENT_SETUP">Chapitre 5, &quot;Configuration côté client&quot;</A> pour de plus amples informations.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>cupsd.conf</DT>
+<DD>
+Ce fichier contrôle la manière de fonctionner sur serveur CUPS (<VAR>/usr/sbin/cupsd</VAR>) et est normalement édité à la main.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.convs</DT>
+<DD>Ce fichier contient une liste des filtres de base pour la conversion de fichier et leurs coûts respectifs.
+Normalement, vous n'éditerez pas ce fichier.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.types</DT>
+<DD>Ce fichier contient la liste des formats de fichiers standards et comment les reconnaître. Normalement, vous n'éditerez pas ce fichier.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>printers.conf</DT>
+<DD>
+Ce fichier contient des informations sur chaque imprimante. Normalement, vous manipulez ce fichier en utilisant la commande
+<CODE>lpadmin</CODE> ou l'interface "web".
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="RESTARTING">Redémarrer le serveur CUPS</A></H2>
+
+<P>Une fois que vous avez fait des changements au fichier de configuration, vous devez redémarrer le serveur CUPS en lui
+envoyant un signal <CODE>HUP</CODE> ou en utilisant le script d'initialisation adéquat. Les distributions de CUPS installent
+le script dans le répertoire <VAR>init.d</VAR> sous le nom <VAR>cups</VAR>. L'emplacement varie selon le système d'exploitation:
+</P>
+<UL>
+<PRE>
+<B>/etc/rc.d/init.d/cups restart ENTREE</B>
+<B>/etc/init.d/cups restart ENTREE</B>
+<B>/sbin/init.d/cups restart ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="7_3">Changer la configuration du serveur</A></H2>
+
+<P>Le fichier <VAR>/etc/cups/cupsd.conf</VAR> contient des <I>directives</I> de configuration qui contrôlent le
+fonctionnement du serveur. Chaque directive suivie de sa valeur est disposée seule sur une ligne.
+Les commentaires sont ouverts par le signe dièse (&quot;#&quot;) au début de la ligne. Etant donné que le fichier de
+configuration du serveur est un fichier texte, vous pouvez le modifier au moyen de votre éditeur de texte préféré.
+<!-- NEED 4in -->
+</P>
+
+<H2><A NAME="7_4">Directives de configuration du serveur</A></H2>
+
+<P>Le fichier<VAR> cupsd.conf</VAR> contient de nombreuses directives qui déterminent le comportement du serveur:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#AccessLog"><CODE>AccessLog</CODE></A></LI>
+<LI><A HREF="#Allow"><CODE>Allow</CODE></A></LI>
+<LI><A HREF="#AuthClass"><CODE>AuthClass</CODE></A></LI>
+<LI><A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A></LI>
+<LI><A HREF="#AuthType"><CODE>AuthType</CODE></A></LI>
+<LI><A HREF="#AutoPurgeJobs"><CODE>AutoPurgeJobs</CODE></A></LI>
+<LI><A HREF="#BrowseAddress"><CODE>BrowseAddress</CODE></A></LI>
+<LI><A HREF="#BrowseAllow"><CODE>BrowseAllow</CODE></A></LI>
+<LI><A HREF="#BrowseDeny"><CODE>BrowseDeny</CODE></A></LI>
+<LI><A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A></LI>
+<LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A></LI>
+<LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A></LI>
+<LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A></LI>
+<LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A></LI>
+<LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A></LI>
+<LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
+<LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
+<LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
+<LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
+<LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A></LI>
+<LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
+<LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
+<LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
+<LI><A HREF="#Deny"><CODE>Deny</CODE></A></LI>
+<LI><A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#Encryption"><CODE>Encryption</CODE></A></LI>
+<LI><A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A></LI>
+<LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A></LI>
+<LI><A HREF="#FontPath"><CODE>FontPath</CODE></A></LI>
+<LI><A HREF="#Group"><CODE>Group</CODE></A></LI>
+<LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A></LI>
+<LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A></LI>
+<LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A></LI>
+<LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A></LI>
+<LI><A HREF="#Include"><CODE>Include</CODE></A></LI>
+<LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A></LI>
+<LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A></LI>
+<LI><A HREF="#Limit"><CODE>Limit</CODE></A></LI>
+<LI><A HREF="#LimitExcept"><CODE>LimitExcept</CODE></A></LI>
+<LI><A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A></LI>
+<LI><A HREF="#Listen"><CODE>Listen</CODE></A></LI>
+<LI><A HREF="#Location"><CODE>Location</CODE></A></LI>
+<LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A></LI>
+<LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A></LI>
+<LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A></LI>
+<LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
+<LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
+<LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
+<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
+<LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
+<LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
+<LI><A HREF="#Printcap"><CODE>Printcap</CODE></A></LI>
+<LI><A HREF="#PrintcapFormat"><CODE>PrintcapFormat</CODE></A></LI>
+<LI><A HREF="#PrintcapGUI"><CODE>PrintcapGUI</CODE></A></LI>
+<LI><A HREF="#RemoteRoot"><CODE>RemoteRoot</CODE></A></LI>
+<LI><A HREF="#RequestRoot"><CODE>RequestRoot</CODE></A></LI>
+<LI><A HREF="#Require"><CODE>Require</CODE></A></LI>
+<LI><A HREF="#RIPCache"><CODE>RIPCache</CODE></A></LI>
+<LI><A HREF="#RunAsUser"><CODE>RunAsUser</CODE></A></LI>
+<LI><A HREF="#Satisfy"><CODE>Satisfy</CODE></A></LI>
+<LI><A HREF="#ServerAdmin"><CODE>ServerAdmin</CODE></A></LI>
+<LI><A HREF="#ServerBin"><CODE>ServerBin</CODE></A></LI>
+<LI><A HREF="#ServerCertificate"><CODE>ServerCertificate</CODE></A></LI>
+<LI><A HREF="#ServerKey"><CODE>ServerKey</CODE></A></LI>
+<LI><A HREF="#ServerName"><CODE>ServerName</CODE></A></LI>
+<LI><A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A></LI>
+<LI><A HREF="#SSLListen"><CODE>SSLListen</CODE></A></LI>
+<LI><A HREF="#SSLPort"><CODE>SSLPort</CODE></A></LI>
+<LI><A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A></LI>
+<LI><A HREF="#TempDir"><CODE>TempDir</CODE></A></LI>
+<LI><A HREF="#Timeout"><CODE>Timeout</CODE></A></LI>
+<LI><A HREF="#User"><CODE>User</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="AccessLog">AccessLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AccessLog /var/log/cups/access_log
+AccessLog /var/log/cups/access_log-%s
+AccessLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AccessLog</CODE> donne le nom du fichier de suivi d'accès ("access log"). Si le chemin d'accès au fichier n'est pas
+absolu, il est considéré comme relatif au répertoire<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>.
+Le fichier "access log" est stocké dans le format "log" habituel et peut aisément être utilisé par tout outil
+d'analyse d'accès "web" pour générer un rapport sur l'activité du serveur CUPS.</P>
+<P>Le nom du serveur peut être inclus dans le nom du fichier en utilisant <CODE>%s</CODE> dans le nom.</P>
+<P>Le nom spécial &quot;syslog&quot; peut être utilisé pour envoyer les informations d'accès au fichier de suivi système au lieu
+d'un simple fichier texte.</P>
+<P>Le fichier de suivi d'accès implicite est <VAR>/var/log/cups/access_log</VAR>.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="Allow">Allow</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Allow from All
+Allow from None
+Allow from *.domain.com
+Allow from .domain.com
+Allow from host.domain.com
+Allow from nnn.*
+Allow from nnn.nnn.*
+Allow from nnn.nnn.nnn.*
+Allow from nnn.nnn.nnn.nnn
+Allow from nnn.nnn.nnn.nnn/mm
+Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+</PRE>
+</UL>
+<H4>Description</H4>
+
+<P>La directive <CODE>Allow</CODE> indique un nom d'hôte, une adresse IP ou un réseau qui est autorisé à accéder au serveur.
+Les directives <CODE>Allow</CODE> se cumulent, ainsi plusieurs directives <CODE>Allow</CODE> peuvent être utilisées pour
+autoriser l'accès à de multiples hôtes et/ou réseaux. La notation <CODE>/mm</CODE> indique une notation de sous-réseau CIDR:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La directive <CODE>Allow</CODE> doit apparaître à l'intérieur d'une directive
+<A HREF="#Location"><CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthClass">AuthClass</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthClass Anonymous
+AuthClass User
+AuthClass System
+AuthClass Group
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthClass</CODE> définit le niveau d'authentification requis:</P>
+<UL>
+<LI><CODE>Anonymous</CODE> - Pas d'authentification nécessaire. C'est la valeur implicite</LI>
+<LI><CODE>User</CODE> - Un nom d'utilisateur et un mot de passe valides sont requis.</LI>
+<LI><CODE>System</CODE> - Un nom d'utilisateur et un mot de passe valides sont requis, et cet utilisateur doit être membre du
+groupe &quot;sys&quot;; cela peut être changé au moyen de la directive<A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A>.</LI>
+<LI><CODE>Group</CODE> - Un nom d'utilisateur et un mot de passe valides sont requis, et cet utilisateur doit être membre du
+groupe indiqué dans la directive <CODE>AuthGroupName</CODE>.</LI>
+</UL>
+<P>La directive <CODE>AuthClass</CODE> doit apparaître à l'intérieur d'une directive<A HREF="#Location">
+ <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthGroupName">AuthGroupName</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthGroupName mygroup
+AuthGroupName lp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthGroupName</CODE> définit le groupe à utiliser pour l'authentification de type <CODE>
+Group</CODE>.</P>
+<P>La directive <CODE>AuthGroupName</CODE> doit apparaître à l'intérieur d'une directive <A HREF="#Location">
+ <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthType">AuthType</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AuthType None
+AuthType Basic
+AuthType Digest
+AuthType BasicDigest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AuthType</CODE> définit le type d'authentification qui doit être effectuée:</P>
+<UL>
+<LI><CODE>None</CODE> - Pas d'authentification. C'est la valeur implicite</LI>
+<LI><CODE>Basic</CODE> - Une authentification "Basic" doit être effectuée en utilisant le fichier de mots de passe et de groupe d'UNIX.</LI>
+<LI><CODE>Digest</CODE> - Une authentification "Digest" doit être effectuée en utilisant le fichier <VAR>/etc/cups/passwd.md5</VAR>.</LI>
+<LI><CODE>BasicDigest</CODE> - Une authentification "Basic" doit être effectuée en utilisant le fichier <VAR>/etc/cups/passwd.md5</VAR>.</LI>
+</UL>
+<P>
+Lorsque vous utilisez <CODE>Basic</CODE>, <CODE>Digest</CODE>, ou
+<CODE>BasicDigest</CODE>, les clients se connectant en utilisant l'adresse
+<CODE>localhost</CODE> peuvent également le faire en utilisant les <A HREF="#CERTIFICATES">certificats</A>.
+</P>
+<P>La directive <CODE>AuthType</CODE> doit apparaître à l'intérieur d'une directive <A HREF="#Location">
+ <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AutoPurgeJobs">AutoPurgeJobs</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+AutoPurgeJobs Yes
+AutoPurgeJobs No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>AutoPurgeJobs</CODE> indique si oui ou non il faut purger les travaux d'impression lorsqu'ils ne sont
+plus nécessaires au vu des quotas. Cet option n'a aucun effet si les quotas ne sont pas activés.
+La valeur implicite est <CODE>No</CODE>.
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="BrowseAddress">BrowseAddress</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseAddress 255.255.255.255:631
+BrowseAddress 192.0.2.255:631
+BrowseAddress host.domain.com:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseAddress</CODE> indique une adresse à laquelle il faut envoyer les informations d'exploration.
+Plusieurs directives <CODE>BrowseAddress</CODE> peuvent être indiquées pour envoyer les informations d'exploration à différents
+systèmes ou réseaux.</P>
+
+<P>La valeur implicite de l'adresse est <CODE>255.255.255.255:631</CODE>
+ce qui diffusera les informations à tous les réseaux auxquels le serveur est connecté.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTA:</B>
+<P>Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est pas sur 24, 16 ou 8 bits,
+l'exploration des imprimantes (et en fait toute réception d'information diffusée) ne fonctionnera pas.
+Ce problème semble résolu dans HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseAllow">BrowseAllow</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseAllow from all
+BrowseAllow from none
+BrowseAllow from 192.0.2
+BrowseAllow from 192.0.2.0/24
+BrowseAllow from 192.0.2.0/255.255.255.0
+BrowseAllow from *.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseAllow</CODE> indique un système dont on accepte de recevoir des paquets d'exploration.
+Le comportement
+implicite est d'accepter des paquets d'exploration de n'importe quel hôte.</P>
+<P>Le contrôle sur la base du nom d'hôte et de domaine impose que vous activiez la directive
+<A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>.</P>
+<P>Le contrôle sur la base de l'adresse IP prend en charge les correspondances exactes, les adresses partielles qui
+correspondent à des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et
+ 255.255.255.0, ou des adresses réseau utilisant le masque indiqué.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseDeny">BrowseDeny</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseDeny from all
+BrowseDeny from none
+BrowseDeny from 192.0.2
+BrowseDeny from 192.0.2.0/24
+BrowseDeny from 192.0.2.0/255.255.255.0
+BrowseDeny from *.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseDeny</CODE> indique un système dont on refuse de recevoir des paquets d'exploration. Le comportement
+implicite est de ne refuser aucun paquet d'exploration d'aucun hôte.</P>
+<P>Le contrôle sur la base du nom d'hôte et de domaine impose que vous activiez la directive
+<A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>.</P>
+<P>Le contrôle sur la base de l'adresse IP prend en charge les correspondances exactes, les adresses partielles qui
+correspondent à des réseaux dont le masque est 255.0.0.0, 255.255.0.0, et
+ 255.255.255.0, ou des adresses réseau utilisant le masque indiqué.
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseOrder">BrowseOrder</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseOrder allow,deny
+BrowseOrder deny,allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseOrder</CODE>
+indique l'ordre de traitement accord/refus. L'ordre implicite est <CODE>deny,allow</CODE>:
+<UL>
+<LI><CODE>allow,deny</CODE> - Les paquets d'exploration sont acceptés à moins qu'ils ne soient explicitement refusés.</LI>
+<LI><CODE>deny,allow</CODE> - Les paquets d'exploration sont rejetés à moins qu'ils ne soient explicitement acceptés.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseInterval 0
+BrowseInterval 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseInterval</CODE> indique le délai maximum entre deux mises à jour de l'exploration.
+Le fait d'indiquer une valeur de 0 interdit de diffuser des mises à jour mais autorise néanmoins un serveur à recevoir
+des mises à jour en provenance d'autres hôtes.</P>
+
+<P>La valeur <CODE>BrowseInterval</CODE> devrait toujours être inférieure à la valeur <A
+HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A>.
+Sinon des imprimantes et des classes pourraient disparaître des système clients entre les mises à jour.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowsePoll">BrowsePoll</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowsePoll 192.0.2.2:631
+BrowsePoll host.domain.com:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowsePoll</CODE>
+collecte la liste des imprimantes disponibles sur un serveur une fois toutes les
+<A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> secondes.
+Plusieurs directives <CODE>BrowsePoll</CODE> peuvent être indiquées pour surveiller plusieurs serveurs.</P>
+<P>Si <CODE>BrowseInterval</CODE> est mis à 0 alors le serveur est surveillé une fois toutes les 30 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowsePort">BrowsePort</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowsePort 631
+BrowsePort 9999
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>
+La directive <CODE>BrowsePort</CODE> indique un numéro de port UDP à employer pour les échanges de paquets d'exploration. La
+valeur implicite est 631.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Vous devez choisir une valeur identique pour la directive <CODE>BrowsePort</CODE> sur tous les systèmes que vous voulez voir.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseProtocols</CODE> indique les protocoles à employer pour collecter et distribuer les informations
+sur les imprimantes partagées sur le réseau local. Le protocole implicite est <CODE>CUPS</CODE>, c'est un protocole
+basé sur la diffusion réseau ("broadcast").
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Lorsque vous utilisez le protocole <CODE>SLP</CODE>, vous devez avoir au moins un serveur "Directory Agent" (DA) sur votre
+réseau. A défaut, l'ordonnanceur CUPS (<CODE>cupsd</CODE>) ne répondra pas aux requêtes des clients pendant plusieurs secondes
+pendant qu'il sera en train d'explorer le réseau.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseRelay">BrowseRelay</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseRelay 193.0.2.1 192.0.2.255
+BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
+BrowseRelay 193.0.2.0/24 192.0.2.255
+BrowseRelay *.domain.com 192.0.2.255
+BrowseRelay host.domain.com 192.0.2.255
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>
+la directive indique des adresses source et destination pour relayer les informations d'exploration en provenance d'un
+hôte ou d'un réseau vers un autre. Plusieurs directives <CODE>BrowseRelay</CODE> peuvent être indiquées si nécessaire.</P>
+<P><CODE>BrowseRelay</CODE> est généralement utilisé sur des systèmes qui assurent la passerelle entre des réseaux multiples au
+moyen d'une ou plusieurs interfaces réseau. Elle peut également être utilisée pour relayer des informations sur les imprimantes
+provenant de serveurs surveillés, au moyen de la ligne:</P>
+<UL>
+<PRE>
+BrowseRelay 127.0.0.1 255.255.255.255
+</PRE>
+</UL>
+<P>Cela fournit un accès effectif aux imprimantes d'un WAN pour tous les clients d'un LAN.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseShortNames">BrowseShortNames</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseShortNames Yes
+BrowseShortNames No
+</PRE>
+</UL>
+<H4>Description</H4>
+
+<P>La directive <CODE>BrowseShortNames</CODE> indique s'il faut ou non utiliser les noms courts pour les imprimantes à
+distance. Les noms courts sont simplement composés du nom de l'imprimante, sans celui du serveur ("imprimante"). Si le
+système détecte plus d'une imprimante à distance portant le même nom, les imprimantes seront affichées avec les noms longs
+("imprimante@erveur1", "imprimante@erveur2")</P>
+<P>La valeur implicite de cette option est <CODE>Yes</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseTimeout">BrowseTimeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+BrowseTimeout 300
+BrowseTimeout 60
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>BrowseTimeout</CODE> fixe la durée de vie des informations reçues sous forme de paquets d'exploration et
+concernant les imprimantese et les classes. Une fois que les informations concernant une imprimante ou une classe dépassent ce
+délai, elles sont retirées de la liste des destinations disponibles.</P>
+
+<P>La valeur <CODE>BrowseTimeout</CODE> devrait toujours être supérieure à la valeur <A HREF="#BrowseInterval"> <CODE>BrowseInterval</CODE></A>.
+Sinon des imprimantes et des classes pourraient disparaîtres des systèmes clients entre les mises à jour.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Browsing">Browsing</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Browsing On
+Browsing Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Browsing</CODE> contrôle l'activation ou non de l'exploration réseau des imprimantes.
+La valeur implicite est <CODE>On</CODE>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Si vous utilisez HP-UX 10.20 sur un sous-réseau dont le masque n'est pas sur 24, 16 ou 8 bits,
+l'exploration des imprimantes (et en fait toute réception d'information diffusée) ne fonctionnera pas.
+Ce problème semble résolu dans HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Classification</CODE> fixe le niveau de classification sur le serveur. Lorsque cette option est activée
+au moins une des pages de garde est forcée à ce niveau et l'information de classification est placée sur chaque page imprimée.
+La valeur implicite est de n'avoir aucun niveau de classification.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ClassifyOverride</CODE> indique si les utilisateurs peuvent outrepasser le niveau de classification
+du serveur ou non. Lorsque la classification du serveur est activée, les utilisateurs peuvent changer la classification en
+employant l'option <CODE>job-sheets</CODE> et peuvent choisir de n'imprimer qu'une seule page de garde de sécurité avant ou
+après le travail d'impression. Si l'option <CODE>job-sheets</CODE> est positionnée à la valeur <CODE>none</CODE> alors
+le niveau de classification implicite du serveur est utilisé.</P>
+<P>La valeur implicite est de ne pas autoriser les utilisateurs à outrepasser la classification.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DataDir">DataDir</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DataDir /usr/share/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DataDir</CODE> fixe le répertoire à employer pour les fichiers de données.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultCharset">DefaultCharset</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DefaultCharset utf-8
+DefaultCharset iso-8859-1
+DefaultCharset windows-1251
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DefaultCharset</CODE> définit le jeu de caractères à utiliser pour les connexions avec les clients.
+Le jeu de caractère implicite est le jeu <CODE>utf-8</CODE> mais il est outrepassé par le jeu de caractères associé à la langue indiquée par le client ou par la directive
+<CODE>DefaultLanguage</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DefaultLanguage de
+DefaultLanguage en
+DefaultLanguage es
+DefaultLanguage fr
+DefaultLanguage it
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DefaultLanguage</CODE> définit le langage à utiliser pour les connexions avec les clients. Régler la langue
+règle également le jeu de caractères si un fichier de localisation existe pour celle-ci. La valeur implicite est &quot;en&quot; c'est-à-dire "anglais".
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="Deny">Deny</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Deny from All
+Deny from None
+Deny from *.domain.com
+Deny from .domain.com
+Deny from host.domain.com
+Deny from nnn.*
+Deny from nnn.nnn.*
+Deny from nnn.nnn.nnn.*
+Deny from nnn.nnn.nnn.nnn
+Deny from nnn.nnn.nnn.nnn/mm
+Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Deny</CODE> indique un nom d'hôte, une adresse IP ou un réseau qui n'est pas autorisé à accéder
+au serveur.
+Les directives <CODE>Deny</CODE> se cumulent, ainsi plusieurs directives <CODE>Deny</CODE> peuvent être utilisées pour
+interdire l'accès à de multiples hôtes et/ou réseaux. La notation <CODE>/mm</CODE> indique une notation de sous-réseau CIDR:
+
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La directive <CODE>Deny</CODE> doit apparaître à l'intérieur d'une directive <A HREF="#Location">
+ <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DocumentRoot">DocumentRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+DocumentRoot /usr/share/doc/cups
+DocumentRoot /foo/bar/doc/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>DocumentRoot</CODE> indique l'emplacement du contenu que le serveur HTTP de CUPS doit publier.
+Si un chemin absolu n'est pas indiqué, celui-ci est considéré comme relatif au répertoire
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>. La valeur implicite est <VAR>/usr/share/doc/cups</VAR>.</P>
+<P>Les documents sont d'abord recherchés dans un sous-répertoire correspondant à la langue demandée par le client (par exemple
+<VAR>/usr/share/doc/cups/fr/...</VAR>) et ensuite directement dans le répertoire <CODE>DocumentRoot</CODE> (par exemple
+<VAR>/usr/share/doc/cups/...</VAR>), ainsi il est possible de localiser le contenu "web" en fournissant des sous-répertoires pour chaque
+ langue nécessaire.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+Encryption Always
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Encryption</CODE> doit apparaître à l'intérieur d'une section
+<A HREF="#Location"><CODE>Location</CODE></A> et définit les réglages d'encryptage pour cet emplacement. Le réglage implicite est
+ <CODE>IfRequested</CODE> pour tous les emplacements.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ErrorLog">ErrorLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ErrorLog /var/log/cups/error_log
+ErrorLog /var/log/cups/error_log-%s
+ErrorLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ErrorLog</CODE> définit le nom du fichier de suivi d'erreurs ("error log"). Si le nom de fichier n'est pas un chemin
+absolu, il est considéré comme un chemin relatif au répertoire <A HREF="#ServerRoot"> <CODE>ServerRoot</CODE></A>. Le fichier standard est
+<VAR> /var/log/cups/error_log</VAR>.</P>
+<P>Le nom du serveur peut être inclus dans le nom du fichier en utilisant le nom <CODE>%s</CODE>.</P>
+<P>Le nom spécial &quot;syslog&quot; peut être utilisé pour envoyer les informations de suivi d'erreurs vers le fichier de suivi d'erreur
+système au lieu d'un fichier texte simple.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FilterLimit">FilterLimit</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+FilterLimit 0
+FilterLimit 200
+FilterLimit 1000
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>FilterLimit</CODE> définit le coût maximal de tous les filtres appliqués au travaux en cours de
+traitement. Elle peut
+être utilisée pour limiter le nombre de programmes de filtres qui son exécutés dans un serveur pour minimiser les problèmes de ressources disque,
+mémoire ou CPU. Une limite de 0 désactive la limitation des filtres.</P>
+
+<P>Le coût moyen d'une impression vers une imprimante non-PostScript nécessite une limitation de filtre aux alentours de 200. Une imprimante
+PostScript nécessite une limite d'environ la moitié (100). Positionner la limite en dessous de ces seuils va effectivement limiter l'ordonnanceur
+à l'impression d'un travail à la fois.</P>
+<P>La valeur implicite est 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FontPath">FontPath</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+FontPath /foo/bar/fonts
+FontPath /usr/share/cups/fonts:/foo/bar/fonts
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>FontPath</CODE> définit le chemin de recherche des polices de caractères à utiliser. La valeur
+implicite est <CODE>/usr/share/cups/fonts</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Group">Group</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Group sys
+Group system
+Group root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Group</CODE> définit le groupe UNIX sous l'identité duquel les programmes CGI et de filtrage fonctionnent.
+Le groupe implicite est <CODE>sys</CODE>, <CODE>system</CODE>, ou <CODE>root</CODE> selon le système d'exploitation.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>HideImplicitMembers</CODE> contrôle l'appartenance ou non d'imprimantes individuelles aux classes implicites qui sont
+montrées à l'utilisateur. La valeur standard est <CODE>No</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> doit être activée pour que cette directive ait un quelconque effet.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+HostNameLookups On
+HostNameLookups Off
+HostNameLookups Double
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>HostNameLookups</CODE> indique si CUPS doit ou non rechercher le nom d'hôte des clients qui se connectent. La clause
+<CODE>Double</CODE> force CUPS à vérifier que le nom d'hôte trouvé à partir de l'adresse correspond bien à l'une des adresses retournées pour
+ce nom d'hôte. Les recherches <CODE>Double</CODE> empêchent également que des clients ayant des adresses non enregistrées ne se connectent au
+serveur. La valeur implicite est <CODE>Off</CODE> pour éviter tout problème potentiel de performance du serveur du fait des résolutions de nom.
+Positionnez cette directive à la valeur <CODE>On</CODE> ou <CODE>Double</CODE> uniquement si nécessaire.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ImplicitClasses">ImplicitClasses</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ImplicitClasses On
+ImplicitClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ImplicitClasses</CODE> contrôle si les classes implicites sont créées sur la base des imprimantes et classes disponibles
+sur le réseau. La valeur implicite est <CODE>On</CODE> mais est automatiquement positionnée sur <CODE>Off</CODE> si <A HREF="#Browsing"><CODE>Browsing</CODE></A>
+est à la valeur <CODE>Off</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ImplicitAnyClasses</CODE> contrôle si oui ou non les classes implicites pour les imprimantes locales et à distance sont crées
+avec le nom <CODE>AnyPrinter</CODE>. La valeur implicite est <CODE>Off</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> doit être activée pour que cette directive ait un quelconque effet.</P>
+<!-- NEED 3in -->
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Include filename
+Include /foo/bar/filename
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Include</CODE> inclut le fichier indiqué dans le corps du fichier
+<CODE>cupsd.conf</CODE>. Si aucun chemin n'est indiqué, le fichier est considéré comme étant relatif au répertoire
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>.</P>
+<!-- NEED 3in -->
+<H3><A NAME="KeepAlive">KeepAlive</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+KeepAlive On
+KeepAlive Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>KeepAlive</CODE> contrôle la prise en charge ou non des connexions HTTP persitantes. La valeur
+implicite est <CODE>On</CODE>.</P>
+<P>Les clients HTTP/1.1 prennent automatiquement en charge les connexions persistantes, tandis que clients
+ HTTP/1.0 doivent spécifiquement les demander en utiliser l'attribut <CODE>Keep-Alive</CODE> attribute dans le champ
+ <CODE>Connection:</CODE> de chaque requête.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="KeepAliveTimeout">KeepAliveTimeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+KeepAliveTimeout 60
+KeepAliveTimeout 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>KeepAliveTimeout</CODE> contrôle combien de temps une connexion HTTP persistante restera ouverte
+après la dernière requête.
+La valeur implicite est de 60 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Limit">Limit</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;Limit GET POST&gt;
+...
+&lt;/Limit&gt;
+
+&lt;Limit ALL&gt;
+...
+&lt;/Limit&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Limit</CODE> groupe les directives de contrôle d'accès pour certains types spécifiques de requêtes HTTP et doit apparaître
+à l'intérieur d'une section <A HREF="#Location"><CODE>Location</CODE></A>.
+L'accès peut être limité à des types individuels de requêtes (<CODE>DELETE</CODE>, <CODE>GET</CODE>, <CODE>HEAD</CODE>
+, <CODE>OPTIONS</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE>, et
+<CODE>TRACE</CODE>) ou pour tous les types de requêtes (<CODE>ALL</CODE>). Les noms de types de requêtes sont dépendants de la casse pour des raisons
+de compatibilité avec Apache.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitExcept">LimitExcept</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;LimitExcept GET POST&gt;
+...
+&lt;/LimitExcept&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LimitExcept</CODE> groupe les directives de contrôle d'accès pour certains types spécifiques de requêtes HTTP et doit
+apparaître à l'intérieur d'une section <A HREF="#Location"> <CODE>Location</CODE></A>.
+Contrairement à la directive <A HREF="#Limit"><CODE>Limit</CODE></A>, <CODE>LimitExcept</CODE> restreint l'accès pour toutes les requêtes
+ <I>à l'exception</I> de celles listées dans la ligne <CODE>LimitExcept</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitRequestBody">LimitRequestBody</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+LimitRequestBody 10485760
+LimitRequestBody 10m
+LimitRequestBody 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LimitRequestBody</CODE> contrôle la taille maximale des fichiers d'impression, des requêtes IPP, et des données des formulaires
+HTML dans les requêtes HTTP POST. La limite implicite est de 0 ce qui désactive la vérification de la limite.</P>
+<P>Reportez-vous également à la directive similaire <A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Listen">Listen</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Listen 127.0.0.1:631
+Listen 192.0.2.1:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Listen</CODE> indique une adresse réseau et un port sur lequel écouter en attente de connexions. Plusieurs directives
+<CODE>Listen</CODE> peuvent être indiquées pour écouter sur de multiples adresses.</P>
+<P>La directive <CODE>Listen</CODE> est similaire à la directive <A HREF="#Port"><CODE>Port</CODE></A>
+mais vous permet de restreindre l'accès à des interfaces ou des réseaux spécifiques.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Location">Location</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+&lt;Location /&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /admin&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers/name&gt;
+...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Location</CODE> indique des options de contrôle d'accès et d'authentification pour le chemin ou
+la ressource HTTP indiquée.
+Des informations supplémentaires sont disponibles plus loin dans le chapitre dans la section
+<A HREF="#PRINTING_SECURITY">&quot;Sécurité du système d'impression&quot;</A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LogLevel">LogLevel</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+LogLevel none
+LogLevel emerg
+LogLevel alert
+LogLevel crit
+LogLevel error
+LogLevel warn
+LogLevel notice
+LogLevel info
+LogLevel debug
+LogLevel debug2
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>LogLevel</CODE> indique la quantité d'informations à consigner dans le fichier <A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A>.
+Les valeurs suivantes sont reconnues (chaque niveau inclut tout ce qui l'est dans les niveaux inférieurs):</P>
+<UL>
+<LI><CODE>none</CODE> - Ne consigne rien.</LI>
+<LI><CODE>emerg</CODE> - Consigne les conditions d'urgence qui empêchent le serveur de fonctionner.</LI>
+<LI><CODE>alert</CODE> - Consigne les alertes qui doivent être traitées immédiatement.</LI>
+<LI><CODE>crit</CODE> - Consigne les erreurs critiques qui n'empêchent pas le serveur de fonctionner.</LI>
+<LI><CODE>error</CODE> - Consigne les erreurs générales.</LI>
+<LI><CODE>warn</CODE> - Consigne les erreurs et les avertissements.</LI>
+<LI><CODE>notice</CODE> - Consigne les conditions d'erreurs temporaires.</LI>
+<LI><CODE>info</CODE> - Consigne toutes les requêtes de modifications et de changement d'état (valeur implicite).</LI>
+<LI><CODE>debug</CODE> - Consigne des informations basiques de débogage.</LI>
+<LI><CODE>debug2</CODE> - Consigne toutes les informations de débogage.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClients">MaxClients</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxClients 100
+MaxClients 1024
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxClients</CODE> contrôle le nombre maximum de clients simultanés qui seront autorisés par le serveur. La valeur implicite ("par défaut")
+est de 100 clients.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Etant donné que chaque travail d'impression demande un descripteur de fichier pour le tube de contrôle, le serveur CUPS limite de manière
+interne la valeur <CODE>MaxClients</CODE> au tiers des descripteurs de fichiers disponibles pour éviter les possibles problèmes lors de
+l'impression de nombreux travaux d'impression.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobs">MaxJobs</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobs 100
+MaxJobs 9999
+MaxJobs 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobs</CODE> contrôle le nombre maximum de travaux d'impression qui sont conservés en mémoire. Dès que le nombre de
+travaux atteint la limite, le plus ancien travail complété est automatiquement purgé du système pour libérer de l'espace pour le nouveau
+travail. Si tous les travaux connus sont toujours en attente de traitement ou actifs, alors le nouveau travail sera rejeté.</P>
+<P>Régler cette valeur sur 0 (valeur implicite) désactive cette fonctionnalité.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobsPerPrinter</CODE> contrôle le nombre maximum de travaux actifs qui sont autorisés pour chaque imprimante ou classe
+d'imprimantes. Dès que le nombre est atteint pour une imprimante ou une classe, les nouveaux travaux sont rejetés tant que l'un des travaux
+actifs n'est pas complété, arrêté, annulé ou abandonné.</P>
+<P>Régler le maximum sur la valeur 0 (valeur implicite) désactive cette fonctionnalité.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxJobsPerUser</CODE> contrôle le nombre maximum de travaux d'impression qui sont autorisés pour chaque utilisateur. Dès
+qu'un utilsateur atteint le maximum autorisé, tout nouveau travail sera rejeté avant qu'un des travaux actifs soit complété, arrêté, annulé ou
+abandonné.</P>
+<P>Régler le maximum sur 0 (valeur implicite) désactive cette fonctionnalité.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxLogSize 1048576
+MaxLogSize 1m
+MaxLogSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxLogSize</CODE> contrôle la taille maximum de chaque fichier de suivi ("log").
+Dès qu'un fichier atteint ou dépasse la limite il est fermé ou renommé en <VAR>filename.O</VAR>.
+Cela vous permet de mettre en place automatiquement une rotation des fichiers de suivi. La taille implicite
+est de 1048576 octets (1Mo).</P>
+<P>Régler le maximum sur 0 désactive la rotation de fichier de suivi.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxRequestSize">MaxRequestSize</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+MaxRequestSize 10485760
+MaxRequestSize 10m
+MaxRequestSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>MaxRequestSize</CODE> contrôle la taille maximum des fichiers d'impression, des requêtes IPP, et des données des
+formulaires HTML contenus dans les requêtes HTTP POST. La valeur implicite est 0, ce qui désactive cette vérification de limite.</P>
+<P>Reportez-vous également à la directive similaire <A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Order">Order</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Order Allow,Deny
+Order Deny,Allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Order</CODE> définit le type implicite de contrôle d'accès.
+Les valeurs suivantes sont prises en charge:</P>
+<UL>
+<LI><CODE>Allow,Deny</CODE> - Autorise les requêtes depuis tous les systèmes <I>à l'exception</I> de ceux listés dans une directive <CODE>Deny</CODE>.</LI>
+<LI><CODE>Deny,Allow</CODE> - Autorise les requêtes uniquement depuis les hôtes listés dans une directive <CODE>Allow</CODE>.</LI>
+</UL>
+<P>La directive <CODE>Order</CODE> doit apparaître à l'intérieur d'une directive <A HREF="#Location">
+ <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PageLog">PageLog</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PageLog /var/log/cups/page_log
+PageLog /var/log/cups/page_log-%s
+PageLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PageLog</CODE> définit le nom du fichier "page log".
+Si le nom du fichier n'est pas absolu, il est considéré comme étant relatif au répertoire <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>.
+Le fichier standard "page log" est <VAR>/var/log/cups/page_log</VAR>.</P>
+<P>Le nom du serveur peut être inclus dans le nom de fichier en utilisant le nom <CODE>%s</CODE>.</P>
+<P>Le nom spécial &quot;syslog&quot; peut être utilisé pour envoyer les informations de page vers le fichier de suivi système au lieu d'un
+simple fichier texte.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Port">Port</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Port 631
+Port 80
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Port</CODE> indique un port sur lequel écouter en attente de connexions.
+Plusieurs lignes <CODE>Port</CODE> peuvent être indiquées pour écouter sur plusieurs ports. La valeur implicite est 631.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobHistory">PreserveJobHistory</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PreserveJobHistory On
+PreserveJobHistory Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PreserveJobHistory</CODE> contrôle si l'historique des travaux complétés, annulés ou abandonnés est conservé sur disque ou non.</P>
+<P>Une valeur <CODE>On</CODE> (valeur implicite) conserve les informations concernant les travaux jusqu'à ce que l'administrateur
+les purge avec la commande <CODE>cancel</CODE>.</P>
+<P>Une valeur <CODE>Off</CODE> retire les informations concernant les travaux dès que ceux-ci sont complétés, annulés ou abandonnés.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobFiles">PreserveJobFiles</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PreserveJobFiles On
+PreserveJobFiles Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PreserveJobFiles</CODE> contrôle si les fichiers des documents complétés, annulés ou abandonnés sont stockés sur disque.</P>
+<P>La valeur <CODE>On</CODE> conserve les fichiers des travaux jusqu'à ce que l'administrateur les purge au moyen de la commande <CODE>cancel</CODE>.
+Les travaux peuvent être resoumis (réimprimés) jusqu'à ce qu'ils soient purgés.</P>
+<P>La valeur <CODE>Off</CODE> (valeur implicite) retire les fichiers des travaux dès ceux-ci sont complétés, annulés ou abandonnés.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Printcap">Printcap</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Printcap
+Printcap /etc/printcap
+Printcap /etc/printers.conf
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Printcap</CODE> contrôle si le fichier printcap est automatiquement généré et mis à jour ou non avec une liste des imprimantes
+disponibles. Si la directive est utilisée sans valeur, alors aucun fichier printcap ne sera généré. La valeur implicite est de
+générer un fichier nommé <VAR>/etc/printcap</VAR>.</P>
+<P>Quand un nom de fichier est indiqué (par exemple <VAR>/etc/printcap</VAR>),
+le fichier printcap est écrit dès qu'une imprimante est ajoutée ou supprimée.
+Le fichier printcap peut alors être utilisé par les applications dont l'utilisation du fichier printcap comme référence des imprimantes
+disponibles est codée en dur.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapFormat">PrintcapFormat</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+PrintcapFormat BSD
+PrintcapFormat Solaris
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PrintcapFormat</CODE> contrôle le format de sortie du fichier printcap.
+Le comportement implicite est de générer un fichier printcap de type BSD.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapGUI">PrintcapGUI</A></H3>
+<HR>
+<H4>Example</H4>
+<UL>
+<PRE>
+PrintcapGUI /usr/bin/glpoptions
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>PrintcapGUI</CODE> indique le programme à utiliser pour afficher le panneau d'options à partir d'une application
+IRIX qui utiliser l'API d'impression Impressario. Le programme implicite est le programme graphique &quot;glpoptions&quot; d'ESP Print Pro.</P>
+<P>Le programme doit accepter l'option <CODE>-d</CODE> pour indiquer l'imprimante et l'option <CODE>-o</CODE> pour indiquer une ou plusieurs
+options. Après avoir autorisé l'utilisateur à sélectionner/changer les options, le programme doit écrire la liste des options d'impression
+sans le <CODE>-o</CODE> sur la sortie standard.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RemoteRoot remroot
+RemoteRoot root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RemoteRoot</CODE> fixe le nom d'utilisateur à utiliser pour les requêtes root non authentifiées depuis des hôtes distants.
+Le nom d'utilisateur standard est <VAR>remroot</VAR>.
+Régler <CODE>RemoteRoot</CODE> sur <VAR>root</VAR> désactive effectivement ce mécanisme de sécurité.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RequestRoot">RequestRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RequestRoot /var/spool/cups
+RequestRoot /foo/bar/spool/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RequestRoot</CODE> définit le répertoire pour les requêtes entrantes IPP et les formulaires HTML.
+Si un chemin absolu n'est pas fourni alors il est considéré comme relatif au répertoire <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>. Le répertoire implicite est <VAR>/var/spool/cups</VAR>.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Require">Require</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Require group foo bar
+Require user john mary
+Require valid-user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Require</CODE> indique que l'authentification est nécessaire pour l'accès à la ressource considérée.
+Le mot clef <CODE>group</CODE> indique que l'utilisateur authentifié doit être membre d'un ou plusieurs des groupes qui suivent.</P>
+<P>Le mot clef <CODE>user</CODE> indique que l'utilisateur authentifié doit être l'un des utilisateurs dont les noms suivent.</P>
+<P>Le mot clef <CODE>valid-user</CODE> indique que tout utilisateur authentifié peut accéder à la ressource.</P>
+<P>Le comportement implicite ("par défaut") est de ne faire aucune authentification.
+Cette directive doit apparaître à l'intérieur d'une directive <A HREF="#Location"><CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RIPCache">RIPCache</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RIPCache 8m
+RIPCache 1g
+RIPCache 2048k
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RIPCache</CODE> définit la quantité de mémoire utilisée par les filtres RIP ("Raster Images Processor") tels que <CODE>
+imagetoraster</CODE> et <CODE>pstoraster</CODE>.
+La taille peut être suffixée par &quot;k&quot; pour kilo-octets, &quot;m&quot; pour méga-octets, ou &quot;g&quot; pour
+ giga-octets. La taille implicite est de &quot;8m&quot;, ou 8 méga-octets.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RunAsUser">RunAsUser</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+RunAsUser Yes
+RunAsUser No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>RunAsUser</CODE> contrôle si l'ordonnanceur fonctionne sous l'identité d'un compte utilisateur non privilégié
+(habituellement <CODE>lp</CODE>). La valeur implicite est <CODE>No</CODE> qui laisse l'utilisateur fonctionner
+en tant qu'utilisateur <CODE>root</CODE>.</P>
+<P><B>Note:</B> Faire fonctionner CUPS en tant qu'utilisateur non privilégié peut empêcher
+LPD et les imprimantes connectées localement de fonctionner correctement en raison de problèmes de permissions. Le programme d'arrière-plan
+ <CODE>lpd</CODE> utilisera automatiquement le mode non privilégié ce qui est 100% conforme à la RFC 1179. Les programmes d'arrière-plan
+<CODE>parallel</CODE>, <CODE>serial</CODE>, et <CODE>usb</CODE> auront besoin d'accès en écriture aux fichiers de périphériques correspondants.
+<!-- NEED 3in -->
+</P>
+
+<H3><A NAME="Satisfy">Satisfy</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Satisfy all
+Satisfy any
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Satisfy</CODE> indique si toutes les conditions doivent être satisfaites pour ouvrir l'accès à la ressource.
+Si la valeur est <CODE>all</CODE> alors toutes les conditions d'authentification et de contrôle d'accès doivent être satisfaites pour
+que l'accès soit autorisé.</P>
+<P>Régler <CODE>Satisfy</CODE> à la valeur <CODE>any</CODE> autorise un utilisateur à obtenir l'accès si l'authentification ou le contrôle d'accès
+est satisfait. Par exemple, vous pourriez exiger l'authentifiation pour l'accès à distance mais autoriser l'accès local sans elle.</P>
+<P>La valeur implicite est <CODE>all</CODE>. Cette directive doit apparaître à l'intérieur d'une directive <A
+HREF="#Location"> <CODE>Location</CODE></A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerAdmin">ServerAdmin</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerAdmin user@host
+ServerAdmin root@foo.bar.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerAdmin</CODE> identifie l'adresse de courriel de l'administrateur du système. La valeur implicite est <CODE>root@serveur</CODE>,
+où <CODE>server</CODE> est le nom du serveur.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerBin">ServerBin</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerBin /usr/lib/cups
+ServerBin /foo/bar/lib/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerBin</CODE> définit le répertoire contenant les fichiers exécutables du serveur.
+Si un chemin absolu n'est pas indiqué, il est considéré comme relatif au répertoire
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE>
+</A>. Le répertoire implicite est <VAR> /usr/lib/cups</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerCertificate">ServerCertificate</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerCertificate /etc/cups/ssl/server.crt
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerCertificate</CODE> définit l'emplacement du fichier de certificat SSL utilisé par le serveur
+lors de la négociation des connexions encryptées. Le certificat ne doit pas être encrypté (protégé par un mot de passe) car l'ordonnanceur fonctionne
+normalement en arrière-plan et et ne sera pas en mesure de demander un mot de passe. Le fichier standard de certificat est <VAR>
+ /etc/cups/ssl/server.crt</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerKey">ServerKey</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerKey /etc/cups/ssl/server.key
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerKey</CODE> indique l'emplacement du fichier de clé privée SSL utilisé par le serveur pour négocier les connexions
+encryptées. Le fichier standard de clé est <VAR> /etc/cups/ssl/server.crt</VAR>
+.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerName"></A>ServerName</H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerName foo.domain.com
+ServerName myserver.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerName</CODE> indique le nom d'hôte qui doit être envoyé aux clients. En standard, le nom du serveur est le nom d'hôte.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerRoot">ServerRoot</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+ServerRoot /etc/cups
+ServerRoot /foo/bar/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>ServerRoot</CODE> indique un chemin absolu pour les fichiers de configuration et d'état du serveur.
+Il est également utilisé pour interpréter les chemins relatifs présents dans le fichier <VAR>cupsd.conf</VAR> file.
+Le répertoire standard est <VAR>/etc/cups</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLListen">SSLListen</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SSLListen 127.0.0.1:443
+SSLListen 192.0.2.1:443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SSLListen</CODE> indique une adresse réseau et un port sur lequel écouter les tentatives de connexion sécurisées.
+Plusieurs directives <CODE>SSLListen</CODE> peuvent être fournies pour indiquer plusieurs adresses sur lesquelles écouter.</P>
+<P>La directive <CODE>SSLListen</CODE> est similaire à la directive
+<A HREF="#SSLPort"><CODE>SSLPort</CODE></A> mais vous permet de restreindre l'accès à certaines interfaces ou réseaux.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLPort">SSLPort</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SSLPort 443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SSLPort</CODE> indique le port sur lequel écouter les tentatives de connexions sécurisées.
+Plusieurs lignes <CODE>SSLPort</CODE> peuvent être indiquées pour écouter les connexions sur plusieurs ports.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SystemGroup">SystemGroup</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+SystemGroup sys
+SystemGroup system
+SystemGroup root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>SystemGroup</CODE> indique le groupe système d'aministration pour l'authentification de type <CODE>System</CODE>.
+Plus d'information peut être trouvée plus loin dans ce chapitre dans la section
+<A HREF="#PRINTING_SECURITY">&quot;Sécurité du système d'impression&quot;</A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="TempDir">TempDir</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+TempDir /var/tmp
+TempDir /foo/bar/tmp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>TempDir</CODE> indique un chemin absolu pour le répertoire à employer pour les fichiers temporaires.
+Le répertoire standard est <VAR>/var/tmp</VAR>.</P>
+<P>Les répertoires temporaires doivent être inscriptibles pour tous et devraient avoir le &quot;sticky&quot; bit activé
+de sorte que les utilisateurs ne puissent pas supprimer les fichiers temporaires de filtres.
+Les commandes suivantes créerons un répertoire temporaire approprié appelé <VAR>/foo/bar/tmp</VAR>:</P>
+<UL>
+<PRE>
+<B>mkdir /foo/bar/tmp ENTREE</B>
+<B>chmod a+rwxt /foo/bar/tmp ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Timeout">Timeout</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+Timeout 300
+Timeout 90
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>Timeout</CODE> définit le délai à attendre avant qu'une requête HTTP ou IPP active ne soit hors délai. La valeur implicite est de 300 secondes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="User">User</A></H3>
+<HR>
+<H4>Exemples</H4>
+<UL>
+<PRE>
+User lp
+User guest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>La directive <CODE>User</CODE> indique l'utilisateur UNIX sous l'identité duquel les programmes CGI et les filtres doivent fonctionner.
+La valeur implicite est <CODE>lp</CODE>.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="PRINTING_SECURITY">Sécurité du système d'impression</A></H2>
+
+<P>CUPS prend en charge le contrôle d'accès et l'authentification basée sur l'adresse, un certificat ou un mot de passe
+(mode "Basic" et "Digest"). Les authentifications par mot de passe et certificat fournissent des moyens de limiter l'accès
+à certaines personnes ou certains groupes.</P>
+
+<P>Le contrôle d'accès basé sur l'adresse vous permet de limiter l'accès à certains systèmes, réseaux ou domaines particuliers.
+Bien que cela ne soit pas de l'authentification, cela vous permet de restreindre efficacement le nombre potentiel d'utilisateurs
+de votre système.</P>
+
+<P>CUPS maintient à jour une liste des emplacements dont l'authentification et/ou le contrôle d'accès est/sont activé(e)(s).
+Ces emplacements sont indiqués en utilisant la directive
+<A HREF="#Location"><CODE>Location</CODE></A>:</P>
+<UL>
+<PRE>
+&lt;Location /ressource&gt;
+<A HREF="#AuthClass">AuthClass</A> ...
+<A HREF="#AuthGroupName">AuthGroupName</A> ...
+<A HREF="#AuthType">AuthType</A> ...
+
+<A HREF="#Order">Order</A> ...
+<A HREF="#Allow">Allow</A> from ...
+<A HREF="#Deny">Deny</A> from ...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>Les emplacements suivent généralement la structure arborescente du contenu du répertoire
+<A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A>, cependant CUPS possède de nombreux emplacements virtuels pour l'administration, les classes, les travaux
+d'impression et les imprimantes:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH>Emplacement</TH><TH>Description</TH></TR>
+<TR><TD>/admin</TD><TD>Le chemin pour toutes les opérations d'administration.</TD></TR>
+<TR><TD>/classes</TD><TD>Le chemin pour toutes les classes d'imprimantes.</TD></TR>
+<TR><TD>/classes/nom_classe</TD><TD>Les ressources pour la classe nommée <CODE>nom_classe</CODE>.</TD>
+</TR>
+<TR><TD>/jobs</TD><TD>Le chemin pour tous les travaux d'impression.</TD></TR>
+<TR><TD>/jobs/id</TD><TD>Les ressources pour le travail d'impression n°<CODE>id</CODE>.</TD></TR>
+<TR><TD>/printers</TD><TD>Le chemin pour toutes les imprimantes.</TD></TR>
+<TR><TD>/printers/nom_imprimante</TD><TD>Le chemin pour l'imprimante nommée <CODE>nom_imprimante</CODE>.</TD>
+</TR>
+<TR><TD>/printers/nom_imprimante.ppd</TD><TD>Le chemin du fichier PPD pour l'imprimante <CODE>nom_imprimante</CODE>.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="CERTIFICATES">Authentification basée sur les certificats</A></H3>
+
+<P>CUPS prend en charge une authentification locale basée sur les certificats qui peut être utilisée à la place des authentifications
+"Basic" et "Digest" pour les clients se connectant à l'interface <CODE>localhost</CODE>.
+L'authentification par certificats n'est ni prise en charge, ni permise pour les clients se connectant par le biais de toute
+autre interface.</P>
+
+<P>Les certificats sont des nombres aléatoires codés sur 128 bits qui font référence à un enregistrement interne
+d'authentification sur le serveur. Un client se connectant via l'interface <CODE>localhost</CODE> envoie une requête avec un en-tête d'autorisation:</P>
+<UL>
+<PRE>
+Authorization: Local 0123456789ABCDEF0123456789ABCDEF
+</PRE>
+</UL>
+
+<P>Le serveur vérifie alors le certificat local correspondant et authentifie le nom d'utilisateur qui y est associé.</P>
+
+<P>Les certificats sont automatiquement générés par le serveur et stockés dans le répertoire <VAR>/etc/cups/certs</VAR>
+en utilisant le n° de processus du programme CGI ("process ID") exécuté par le serveur. Les fichiers de certificats sont
+en lecture seule pour les utilisateurs <A HREF="#User"><CODE>User</CODE></A> et groupes
+<A HREF="#Group"><CODE>Group</CODE></A> définis dans le fichier <VAR> cupsd.conf</VAR>. Quand le programme CGI se termine, le certificat est retiré
+et rendu automatiquement invalide.</P>
+
+<P>Le fichier spécial <VAR>/etc/cups/certs/0</VAR> définit le <I>certificat de root</I> qui peut être utilisé par tout client
+fonctionnant sous l'identité du super-utilisateur et qui appartient au group défini par la directive
+<A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A>.
+Le certificat de root est automatiquement régénéré toutes les 5 minutes.</P>
+
+<H3><A NAME="7_5_2">Utilisation de l'authentification "Basic"</A></H3>
+
+<P>L'authentification "Basic" utilise les utilisateurs et mots de passe UNIX pour authentifier l'accès à des ressources
+telles que les imprimantes ou les classes et pour limiter l'accès aux fonctions d'administration.<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>L'authentification "Basic" transmet le nom d'utilisateur et le mot de passe en clair (encodage Base64) du client vers
+le serveur, donc elle n'offre aucune protection contre l'espionnage. Cela signifie qu'une utilisateur mal intentionné peut
+écouter les paquets réseau et découvrir ces informations. Il peut en résulter une sérieuse compromission de la sécurité de
+votre réseau. Utilisez l'authentification avec la plus grande prudence.
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>L'implémentation de l'authentification "Basic" dans CUPS ne permet pas l'accès en utilisant des comptes sans
+mot de passe. Si vous tentez d'authentifier un tel compte, l'accès sera immédiatement bloqué.</P>
+<P>Une fois le nom d'utilisateur et le mot de passe authentifiés par CUPS, les contraintes supplémentaires d'appartenance à des groupes sont vérifiées
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Pour CUPS, l'utilisateur root est considéré comme membre de tous les groupes.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 1in -->
+</P>
+<P>Utilisez la directive <CODE>AuthType</CODE> pour activer l'authentification "Basic":</P>
+<UL>
+<PRE>
+AuthType Basic
+</PRE>
+</UL>
+
+<!-- NEED 7in -->
+<H3><A NAME="7_5_3">Utilisation de l'authentification "Digest"</A></H3>
+
+<P>L'authentification "Digest" utilise des utilisateurs et mots de passe définis dans le fichier <VAR>/etc/cups/passwd.md5</VAR> pour authentifier l'accès aux ressources telles que les imprimantes et les classes et pour
+limiter l'accès aux fonctions d'administration.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+
+<P>Contrairement à l'authentification "Basic", "Digest" transmet une version codée du nom d'utilisateur et du mot de passe
+en utilisant le codage MD5 (en résumé, une somme de contrôle compliquée) au lieu de leur version en clair. De plus,
+l'authentification "Digest" n'utilise pas les utilisateurs et mots de passe UNIX, ainsi si un attaquant découvre le mot de
+passe original il est moins probable qu'il en résulte un problème de sécurité, pour peu que vous utilisiez un mot de passe
+"Digest" différent de celui stocké par UNIX.</P>
+
+<P>L'implémentation actuelle de l'authenfication "Digest" dans CUPS utilise le nom d'hôte du client ou son adresse IP comme
+valeur "nonce". La valeur "nonce" est une chaîne de caractères additionnelle ajoutée au nom d'utilisateur et au mot de passe
+pour rendre la découverte de ce dernier plus difficile. Le serveur vérifie que la valeur "nonce" correspond au nom d'hôte
+ou l'adresse IP du client et, si tel n'est pas le cas, rejette la somme MD5 proposée par celui-ci. Les prochaines versions
+de CUPS prendront en charge l'authentification "Digest" par "session" qui ajoutera les données de la requête à la somme
+MD5, fournissant ainsi une sécurité et une authentification encore meilleures.</P>
+
+<P>L'authentification "Digest" ne garantit pas qu'un attaquant ne peut pas obtenir un accès non autorisé mais elle est plus
+sûre que l'authentification "Basic" et devrait être utilisée à la place de celle-ci chaque fois que c'est possible.
+<B>La prise en charge de l'authentification "Digest" dans les navigateurs "web" n'est pas encore universellement disponible.</B></P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 2in -->
+</P>
+<P>La commande <CODE>lppasswd(1)</CODE> est utilisée pour ajouter, changer et retirer des comptes du fichier <VAR>passwd.md5</VAR>.
+Pour ajouter un utilisateur au groupe système standard, tapez:</P>
+<UL>
+<PRE>
+<B>lppasswd -a utilisateur ENTREE</B>
+Password: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Une fois ajouté, un utilisateur peut changer son mot de passe en tapant:</P>
+<UL>
+<PRE>
+<B>lppasswd ENTREE</B>
+Old Password: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+Password : <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>Pour retirer un utilisateur du fichier des mots de passe, tapez:</P>
+<UL>
+<PRE>
+<B>lppasswd -x utilisateur ENTREE</B>
+</PRE>
+</UL>
+<P>Une fois qu'un utilisateur et un mot de passe valides ont été authentifiés pas CUPS, celui-ci vérifie les
+contraintes supplémentaires d'appartenance à des groupes.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Pour CUPS, l'utilisateur root est membre de tous les groupes.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>Utilisez la directive <CODE>AuthType</CODE> pour activer l'authentification "Digest":</P>
+<UL>
+<PRE>
+AuthType Digest
+</PRE>
+</UL>
+<H3><A NAME="7_5_4">Authentifications "System" et "Group"</A></H3>
+<P>La directive <A HREF="#AuthClass"><CODE>AuthClass</CODE></A> contrôle le niveau d'authentification
+à effectuer. Les authentifications <CODE>System</CODE> et <CODE>Group</CODE>
+ajoutent à l'authentification normale basée sur l'utilisateur une contrainte d'appartenance à un groupe UNIX.
+Pour l'authentification <CODE>System</CODE>, chaque utilisateur doit être membre du groupe <CODE>sys</CODE>,
+<CODE>system</CODE>, ou <CODE>root</CODE>; le groupe réel dépend du système d'exploitation.</P>
+
+<P>Pour l'authentification <CODE>Group</CODE> l'utilisateur doit être membre du group indiqué par la directive
+<A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>:</P>
+<UL>
+<PRE>
+&lt;Location /path&gt;
+AuthType Digest
+AuthClass Group
+AuthGroupName mygroup
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>Le groupe indiqué doit être un groupe UNIX valide, habituellement défini dans les fichiers <VAR>/etc/group</VAR>
+ou <VAR>/etc/netgroup</VAR>. De plus, lors de l'utilisation de l'authentification "Digest", vous devez créer les comptes
+utilisateur avec le groupe indiqué:</P>
+<UL>
+<PRE>
+<B>lppasswd -g mon_groupe -a utilisateur ENTER</B>
+Password : <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+Password again: <B>(mot de passe) ENTREE</B> [le mot de passe n'est pas affiché]
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTER_ACCOUNTING">Suivi/facturation de travaux et d'imprimantes</A></H2>
+<P>ESP Print Pro maintient à jour un suivi ("log") de tous les accès, erreurs et pages qui sont imprimées. Les fichiers de
+suivi sont normalement stockés dans le répertoire <VAR>/var/log/cups</VAR>.
+Vous pouvez changer cela en éditant le fichier de configuration <VAR>/etc/cups/cupsd.conf</VAR>.</P>
+
+<H3><A NAME="7_6_1">Le fichier access_log</A></H3>
+<P>Le fichier <VAR>access_log</VAR> liste chaque ressource HTTP qui est utilisée par le serveur "web" ou un client CUPS/IPP.
+Chaque ligne est structurée dans le format habituel utilisé par de nombreux serveurs "web" et outils d'analyse.:</P>
+<UL>
+<PRE>
+Hôte Groupe Utilisateur Date/heure \&quot;Méthode Ressource Version\&quot; Etat Octets
+
+127.0.0.1 - - [20/May/1999:19:20:29 +0000] &quot;POST /admin/ HTTP/1.1&quot; 401 0
+127.0.0.1 - mike [20/May/1999:19:20:31 +0000] &quot;POST /admin/ HTTP/1.1&quot; 200 0
+</PRE>
+</UL>
+<P>Le champ <I>hôte</I> ne devrait normalement être qu'une adresse IP à moins que vous n'activiez la directive
+<A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A> dans le fichier <VAR>cupsd.conf</VAR>.</P>
+
+<P>Le champ <I>groupe</I> contient toujours &quot;-&quot; dans CUPS.</P>
+
+<P>Le champ <I>utilisateur</I> est le nom de l'utilisateur authentifié qui a émis la requête. Si aucun nom d'utilisateur et
+mot de passe n'est fourni pour la requête, alors ce champ contient &quot;-&quot;.</P>
+<P>Le champ <I>date/heure</I> contient la date et l'heure de la requête exprimées dans le fuseau horaire local, et est structuré
+ de la manière suivante:</P>
+<UL>
+<PRE>
+[JJ/MMM/AAAA:HH:MM:SS +ZZZZ]
+</PRE>
+</UL>
+<P>où <I>ZZZZ</I> est le décalage horaire entre le fuseau horaire local et l'heure Greenwich Mean Time (a.k.a. GMT a.k.a. ZULU.) (NdT : en réalité GMT est un abus de langage, il s'agit du temps UTC...)</P>
+<P>Le champ <I>méthode</I> est la méthode HTTP utilisée (&quot;GET&quot;, &quot;PUT&quot;,
+ &quot;POST&quot;, etc.)</P>
+<P>Le champ <I>ressource</I> est le nom du fichier de la ressource demandée.</P>
+<P>Le champ <I>version</I> est la version du protocole HTTP employé par le client.
+Pour les clients CUPS, c'est toujours &quot;HTTP/1.1&quot;.</P>
+<P>Le champ <I>Etat</I> contient l'état du résultat HTTP de la requête. Habituellement, il s'agit de la valeur &quot;200&quot;, mais
+d'autres codes d'état HTTP sont possibles.
+Par exemple, 401 est le code d'état pour &quot;accès non autorisé&quot; dans l'exemple ci-dessus.</P>
+<P>Le champs <I>octets</I> contient le nombre d'octets contenus dans la requête.
+Pour les requêtes POST, le champ <I>octets</I> contient le nombre d'octets reçus du client.</P>
+
+<H3><A NAME="7_6_2">Le fichier error_log</A></H3>
+
+<P>Le fichier <VAR>error_log</VAR> liste les messages provenant de l'ordonnanceur (erreurs, avertissements, etc.):</P>
+<UL>
+<PRE>
+Niveau Date/Heure Message
+
+I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
+</PRE>
+</UL>
+<P>Le champ <I>Niveau</I> contient le type du message:</P>
+<UL>
+<LI><CODE>E</CODE> - Une erreur est survenue.</LI>
+<LI><CODE>W</CODE> - Le serveur a été incapable d'effectuer une action.</LI>
+<LI><CODE>I</CODE> - Message d'information.</LI>
+<LI><CODE>D</CODE> - Message de débogage.</LI>
+</UL>
+<P>Le champ <I>Date/heure</I> contient la date et l'heure de début d'impression de la page.
+Le format est identique à celui du champ <I>Date/heure</I> dans le fichier <VAR>access_log</VAR>.</P>
+<P>Le champ <I>Message</I> contient un message textuel dont la forme est libre.</P>
+
+<H3><A NAME="7_6_3">Le fichier page_log</A></H3>
+
+<P>Le fichier <VAR>page_log</VAR> liste chaque page qui est envoyée à une imprimante.
+Chaque ligne contient les informations suivantes:</P>
+<UL>
+<PRE>
+Imprimante Utilisateur N°travail Date/heure N°Page Nombre_copies Facturation_travail
+
+DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123
+</PRE>
+</UL>
+<P>Le champ <I>imprimante</I> contient le nom de l'imprimante qui a imprimé la page.
+Si vous envoyez un travail d'impression à une classe, le champ contient le nom de l'imprimante
+à laquelle ce travail a été affecté..</P>
+<P>Le champ <I>utilisateur</I> contient le nom de l'utilisateur (l'attribut <CODE>requesting-user-name</CODE> de IPP)
+qui a envoyé le fichier à l'impression.</P>
+<P>Le champ <I>N°Travail</I> contient le n° du travail correspondant à la page en cours d'impression. Les n° de travaux sont
+remis à 1 si le serveur CUPS est redémarré, donc ne le considérez pas comme un identifiant unique !</P>
+<P>Le champ <I>Date/heure</I> contient la date et l'heure de démarrage de l'impression dans un format identique au champ
+<I>Date/heure</I> du fichier <VAR>access_log</VAR>.</P>
+<P>Les champs <I>N°Page</I> et <I>Nombre_copies</I> contiennent le n° de page imprimée et le nombre de copies de cette page.
+Pour les imprimantes qui ne peuvent pas produire de copies multiples de manière autonome, le champ <I>Nombre_copies</I> est toujours
+à 1.</P>
+<P>Le champ <I>facturation_travail</I> contient une copie de l'attribut <CODE>job-billing</CODE>
+ fourni dans les requête IPP <CODE>create-job</CODE> ou
+<CODE>print-job</CODE>. Si aucune valeur n'est fournie dans la requête, ce champ contient &quot;-&quot;.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="FILE_TYPING_FILTERING">Filtrage et détermination des types de fichiers</A></H2>
+
+<P>CUPS fournit un mécanisme de filtrage et de détermination du type de fichier basé sur MIME, afin de convertir les fichiers
+dans un format utilisable par chaque imprimante. Au démarrage, le serveur CUPS lit les fichiers de la base de données MIME
+contenus dans le répertoire <VAR>/etc/cups</VAR> (ou un répertoire indiqué au moyen de la directive <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>)
+afin de construire en mémoire une base de données de conversion et de types de fichiers.
+Ces fichiers de base de données sont de simples fichiers texte ASCII et peuvent être modifiés au moyen de votre éditeur de texte
+préféré.</P>
+<P>Les fichiers <VAR>mime.types</VAR> et <VAR>mime.convs</VAR> définissent les types de fichiers standards et les filtres qui
+sont disponibles sur le système.</P>
+
+<H3><A NAME="7_7_1">Le fichier mime.types</A></H3>
+
+<P>Le fichier <VAR>mime.types</VAR> définit les types de fichiers connus.
+Chaque ligne débute par le type MIME et devrait être suivi par une ou plusieurs règles de reconnaissance de fichier. Par exemple,
+le type de fichier <CODE>text/html</CODE> est défini de la manière suivante:</P>
+<UL>
+<PRE>
+text/html html htm \
+ printable(0,1024) + \
+ (string(0,&quot;&lt;HTML&gt;&quot;) string(0,&quot;&lt;!DOCTYPE&quot;))
+</PRE>
+</UL>
+<P>Les deux premièress règles indiquent que tout fichier portant l'extension <VAR>.html</VAR>
+ou <VAR>.htm</VAR> est un fichier HTML. La troisième règle précise que tout fichier dont les 1024 premiers caractères sont des
+caractères imprimables et commencent par les chaînes <CODE>&lt;HTML&gt;</CODE> ou <CODE>&lt;!DOCTYPE</CODE> est également un fichier HTML.</P>
+
+<P>Les deux premières règle traitent simplement du nom du fichier. Cela est utile lorsque le nom du fichier original est
+connu, cependant pour les fichiers d'impression le serveur ne dispose pas de nom de fichier. La troisième règle prend garde
+à cette éventualité et détermine automatiquement le type du fichier en se basant plutôt sur son contenu.</P>
+<P>Les test applicables sont les suivants:</P>
+<UL>
+<LI><CODE>( expr )</CODE> - Parenthèses pour grouper les expressions</LI>
+<LI><CODE>+</CODE> - ET logique</LI>
+<LI><CODE>,</CODE> ou espace vide - OU logique</LI>
+<LI><CODE>!</CODE> - NON logique</LI>
+<LI><CODE>match(&quot;pattern&quot;)</CODE> - Recherche de motif sur le nom de fichier</LI>
+<LI><CODE>extension</CODE> - Recherche de motif sur &quot;*.extension&quot;</LI>
+<LI><CODE>ascii(offset,length)</CODE> - Vrai si les octets sont des caractères ASCII imprimables (CR, NL, TAB, BS, 32-126)</LI>
+<LI><CODE>printable(offset,length)</CODE> - Vrai si les octets sont des caractères 8 bits imprimables (CR, NL, TAB, BS, 32-126, 160-254)</LI>
+<LI><CODE>string(offset,&quot;chaîne&quot;)</CODE> - Vrai si les octets sont identiques à la chaîne</LI>
+<LI><CODE>contains(offset,range,&quot;chaîne&quot;)</CODE> - Vrai si la plage d'octets contient la chaîne</LI>
+<LI><CODE>char(offset,value)</CODE> - Vrai si l'octet correspond</LI>
+<LI><CODE>short(offset,value)</CODE> - Vrai si l'entier sur 16 bits correspond (ordre des octets : "network" ou &quot;big-endian&quot;)</LI>
+<LI><CODE>int(offset,value)</CODE> - Vrai si l'entier sur 32 bits correspond (ordre des octets : "network" ou &quot;big-endian&quot;)</LI>
+<LI><CODE>locale(&quot;string&quot;)</CODE> - Vrai si la locale courante correspond à la chaîne</LI>
+</UL>
+<P>Toutes les valeurs numériques peuvent être exprimées en décimal (123), octal (0123), ou hexadécimal (0x123) selon le cas.
+<!-- NEED 2.5in -->
+</P>
+<P>Les chaînes de caractères peuvent être délimitées par des quotes, sans quotes, sous forme d'une chaîne de valeurs hexadécimales ou toute combinaison de ces écritures:</P>
+<UL>
+<PRE>
+&quot;chaîne&quot;
+'chaîne'
+chaîne
+&lt;737472696e67&gt;
+&lt;7374&gt;ring
+</PRE>
+</UL>
+<P>Comme le montre l'exemple <CODE>text/html</CODE>, les règles peuvent être réparties sur plusieurs lignes en utilisant le
+caractère "backslash" ("\"). Un exemple plus complexe est fourni par les règles de détermination du type <CODE>image/jpeg</CODE>:</P>
+<UL>
+<PRE>
+image/jpeg jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+</PRE>
+</UL>
+<P>Cette règle indique que tout fichier avec l'extension <VAR>.jpeg</VAR>, <VAR>
+.jpg</VAR>, ou <VAR>.jpe</VAR> est un fichier JPEG. De plus, tout fichier commençant par la chaîne hexadécimale <CODE>&lt;FFD8FF&gt;</CODE>
+ (JPEG Start-Of-Image) suivie d'un caractère compris entre <CODE>0xe0</CODE> et <CODE>0xef</CODE> (JPEG APPn markers) bornes comprises, est également
+un fichier JPEG.</P>
+
+<H3><A NAME="7_7_2">Le fichier mime.convs</A></H3>
+
+<P>Le fichier <VAR>mime.convs</VAR> définit tous les programmes de filtrage qui sont connus du système.
+Chaque ligne est de la forme:</P>
+<UL>
+<PRE>
+Source Destination Coût Programme
+
+text/plain application/postscript 50 texttops
+application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
+image/* application/vnd.cups-postscript 50 imagetops
+image/* application/vnd.cups-raster 50 imagetoraster
+</PRE>
+</UL>
+<P>Le champ <I>Source</I> est un type MIME. Il peut éventuellement utiliser des méta caractères ("joker", "wildcard")
+pour le sur-type ou le sous-type (par exemple &quot;text/plain&quot;, &quot;image/*&quot;,
+ &quot;*/postscript&quot;).</P>
+<P>Le champ <I>Destination</I> est un type MIME défini dans le fichier <VAR>mime.types</VAR>.</P>
+<P>Le champ <I>Coût</I> définit un coût relatif pour l'opération de filtrage, exprimé sous forme d'une valeur entre 1 et 100.
+Le coût est utilisé pour choisir entre deux jeux de filtres lors de la conversion d'un fichier. Par exemple, pour convertir
+<CODE>image/jpeg</CODE> en <CODE>application/vnd.cups-raster</CODE>, vous pourriez utiliser les filtres <CODE>imagetops</CODE>
+ et <CODE>pstoraster</CODE> pour un coût total de 100, ou le filtre
+<CODE>imagetoraster</CODE> pour un coût total de 50.</P>
+<P>Le champ <I>Programme</I> définit le programme de filtrage à exécuter; le programme doit accepter les arguments standards de
+filtrage et les variables d'environnement décrits dans le "Manuel de conception d'interface" ainsi que le "Manuel du programmeur":</P>
+<UL>
+<PRE>
+Programme Travail Utilisateur Titre Options [nom_fichier]
+</PRE>
+</UL>
+<P>S'il est indiqué, l'argument <I>nom_fichier</I> définit un fichier à lire lors du filtrage, sinon le filtre doit lire l'entrée
+standard. Toutes les sorties du programme de filtrage doivent être envoyées à la sortie standard.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="7_7_3">Ajouter des filtres et des types de fichiers</A></H3>
+
+<P>Ajouter un nouveau filtre ou type de fichier est relativement simple.
+Plutôt qu'ajouter le nouveau filtre ou type aux fichiers <VAR>mime.types</VAR> et
+<VAR>mime.convs</VAR> qui sont écrasés lorsque vous mettez CUPS à jour avec une nouvelle version,
+vous devez simplement créer de nouveaux fichiers avec les extensions <VAR>.types</VAR> et <VAR>.convs</VAR>
+dans le répertoire <VAR>/etc/cups</VAR>. Nous recommandons d'utiliser le nom du format ou du produit, par exemple:</P>
+<UL>
+<PRE>
+myproduct.types
+myproduct.convs
+</PRE>
+</UL>
+<P>Si vous installez un filtre pour un fichier ou une imprimante courants, ajoutez le nom du fabricant ou de l'éditeur:</P>
+<UL>
+<PRE>
+acme-msword.types
+acme.msword.convs
+</PRE>
+</UL>
+<P>Cela aidera à éviter les conflits de noms si vous installez plusieurs types de fichiers ou plusieurs filtres.</P>
+<P>Une fois choisis les noms pour ces fichiers, créez-les au moyen de votre éditeur de texte préféré comme décrit précédemment
+dans ce chapitre. Une fois ces fichiers créés, redémarrez le processus <CODE>cupsd</CODE> comme indiqué précédemment
+dans <A HREF="#RESTARTING">&quot;Redémarrage du serveur CUPS&quot;</A>
+.</P>
+<H3><A NAME="7_7_4">Pilotes d'imprimantes et fichiers PPD</A></H3>
+
+<P>Plusieurs pilotes d'imprimante CUPS utilisent un ou plusieurs filtres spécifiques et un fichier PPD pour chaque
+modèle d'imprimante. Les filtres pilotes d'imprimante sont enregistrés au moyen des attributs du fichier
+<CODE>cupsFilter</CODE>:</P>
+<UL>
+<PRE>
+*cupsFilter: &quot;application/vnd.cups-raster 0 rastertohp&quot;
+</PRE>
+</UL>
+<P>Le filtre est indiqué en utilisant seulement le type du fichier source;
+le type du fichier destination est considéré comme étant du type <CODE>imprimante/nom</CODE> -
+ convenable pour envoi à l'imprimante.</P>
+
+<H3><A NAME="7_7_5">Ecrire vos propres filtres ou pilotes d'imprimantes</A></H3>
+
+<P>CUPS prend en charge un nombre illimité de filtres et de formats de fichiers, et peut traiter avec toute imprimante.
+Si vous désirez écrire un pilote ou un filtre pour votre imprimante préférée, consultez le "Manuel du programmeur" et suivez
+pas à pas les instructions qu'il contient.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Imprimer depuis et vers d'autres systèmes</A></H1>
+
+<P>Ce chapitre décrit comment imprimer depuis des système clients qui utilisent les protocoles d'impression
+LPD, Mac OS ou Windows.</P>
+
+<H2><A NAME="8_1">Les bases</A></H2>
+
+<P>CUPS est basé sur le protocole IPP, ainsi tout autre système prenant en charge IPP peut automatiquement envoyer ou recevoir
+des travaux d'impression vers ou depuis un système utilisant CUPS. Cependant, tous les systèmes ne prennent pas encore en
+charge IPP. Ce chapitre vous montrera comment connecter ces systèmes à votre serveur CUPS, que ce soit pour qu'ils
+puissent accepter des travaux provenant de celui-ci ou pour lui en envoyer.</P>
+
+<H2><A NAME="8_2">Imprimer depuis des clients LPD</A></H2>
+
+<P>CUPS prend en charge un nombre limité des fonctionnalités des clients basés sur LPD. Avec LPD vous pouvez imprimer des
+fichiers vers des imprimantes déterminées, voir l'état des files d'impression, etc. Cependant, la configuration automatique
+des clients et des imprimantes n'est pas prise en charge par le protocole LPD, donc vous devez configurer manuellement chaque
+client pour les imprimantes auxquelles il a besoin d'accéder.</P>
+
+<P>Le programme <CODE>cups-lpd(8)</CODE> fournit la prise en charge pour les clients LPD.
+Pour activer la prise en charge LPD sur votre serveur, éditez le contenu du fichier
+<VAR>/etc/inetd.conf</VAR> et ajoutez une ligne:</P>
+<UL>
+<PRE>
+printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+</PRE>
+</UL>
+<P>Le chemin vers le programme <CODE>cups-lpd</CODE> peut varier en fonction de l'installation de votre serveur.</P>
+<P>Une fois cette ligne ajoutée, envoyez un signal <CODE>HUP</CODE> au processus <CODE>inetd(8)</CODE> ou redémarrez le
+système (NdT : le redémarrage du système n'est pas des plus élégants...):</P>
+<UL>
+<PRE>
+<B>killall -HUP inetd ENTREE</B> [sur IRIX et quelques distributions GNU/Linux]
+<B>kill -HUP <I>pid</I> ENTREE [Autres systèmes]</B>
+<B>reboot ENTREE [Pour tous les systèmes si le signal HUP ne fonctionne pas (NdT : ...en DERNIER recours, uniquement...)]</B>
+</PRE>
+</UL>
+<H2><A NAME="8_3">Imprimer vers des serveurs LPD</A></H2>
+
+<P>CUPS fournit le programme d'arrière-plan <CODE>lpd</CODE> pour imprimer vers des serveurs et imprimantes
+utilisant LPD. Utilisez un URI de périphérique de la forme <CODE>lpd://serveur/nom</CODE>
+pour imprimer ver une imprimante sur un serveur LPD, où <CODE>serveur</CODE>
+est le nom d'hôte ou l'adresse IP du serveur et <CODE>nom</CODE> est le nom de la file d'impression.</P>
+
+<P>Microsoft Windows NT fournit un service LPD sous le nom &quot;Serveur d'impression TCP/IP&quot;.
+Pour activer l'impression sur un système Windows NT, ouvrez le panneau de configuration puis "Services", sélectionnez
+le service &quot;Serveur d'impression TCP/IP&quot; et cliquez sur le bouton "Démarrer". Toute imprimante partagée
+devient alors accessible via le protocole LPD.</P>
+
+<H2><A NAME="8_4">Imprimer depuis des client Mac OS</A></H2>
+
+<P><i>NdT : je ne suis pas spécialiste Mac et je ne dispose pas de ce type de matériel. Il se peut qu'il y ait quelques imprécisions ou erreurs dans ce qui suit, faîtes-moi
+l'amitié de me les pardonner ET de me les signaler. Merci par avance...</i></P>
+
+<P>CUPS ne fournit pas de prise en charge directe de Mac OS. Cependant, il existe plusieurs logiciels libres ou commerciaux
+qui le font.</P>
+
+<H3><A NAME="8_4_1">Columbia Appletalk Package (CAP)</A></H3>
+
+<P>Etant donné que le serveur CAP LaserWriter (<CODE>lwsrv(8)</CODE>) ne prend pas en charge les spécifications des fichiers
+PPD, nous ne recommandons pas l'utilisation de CAP avec CUPS. Cependant, vous pouvez exécuter le programme <CODE>lpsrv</CODE>
+pour une prise en charge limitée de l'impression au moyen de la syntaxe suivante:</P>
+<UL>
+<PRE>
+lwsrv -n &quot;<I>Nom</I>&quot; -p <I>Imprimante</I> -a /usr/lib/adicts -f /usr/lib/LW+Fonts
+</PRE>
+</UL>
+<P>où <CODE>Nom</CODE> est le nom que vous voulez utiliser pour partager l'imprimante et <CODE>imprimante</CODE>
+est le nom de la file d'impression.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="8_4_2">XINET KA/Spool</A></H3>
+
+<P>Afin d'utiliser votre système comme serveur d'impression pour des clients Mac OS, configurez chaque imprimante en utilisant
+<CODE>papserver(8)</CODE> dans le fichier <VAR>/usr/adm/appletalk/services</VAR>, et en indiquant le fichier PPD correspondant
+dans le répertoire<VAR>/etc/cups/ppd</VAR>.
+Pour une imprimante appelée <CODE>Mon_Imprimante</CODE> la syntaxe serait de la forme suivante:</P>
+<UL>
+<PRE>
+/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/Mon_Imprimante.ppd \
+&quot;Printer Description&quot; Mon_Imprimante
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Entrez le texte ci-dessus sur une seule ligne sans le caractère "\".</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<H3><A NAME="8_4_3">NetATalk</A></H3>
+
+<P>Pour utiliser votre système comme serveur d'impression pour des clients Mac OS, configurez chaque imprimante dans le
+fichier <VAR>papd.conf</VAR>, en indiquant le fichier PPD correspondant dans le répertoire <VAR>/etc/cups/ppd</VAR> pour
+chaque imprimante. Pour une imprimante nommée <CODE>Mon_Imprimante</CODE> le texte serait de la forme suivante:</P>
+<UL>
+<PRE>
+Printer Description:Mon_Imprimante@Mon_Serveur:\
+ :pr=|/usr/bin/lp -d Mon_Imprimante:\
+ :op=daemon:\
+ :pd=/etc/cups/ppd/Mon_Imprimante.ppd:
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H2><A NAME="8_5">Imprimer vers des serveurs d'impression Mac OS</A></H2>
+
+<P>Actuellement, CUPS ne fournit pas de programme d'arrière-plan pour communiquer avec un serveur Mac OS. Cependant, vous
+pouvez écrire et installer un court script dans le répertoire <VAR>/usr/lib/cups/backend</VAR> qui envoie
+un fichier d'impression en utilisant la commande appropriée. Le court script suivant exécutera la commande
+<CODE>papif</CODE> fournie avec CAP.</P>
+<P>Après avoir copié le script dans <VAR>/usr/lib/cups/backend/cap</VAR>, indiquez un URI de périphérique de la forme
+<CODE>cap://serveur/imprimante</CODE> pour utiliser ce script avec une file d'impression.
+<!-- NEED 8in -->
+</P>
+<UL>
+<PRE>
+<I>&quot;/usr/lib/cups/backend/cap&quot;</I>
+#!/bin/sh
+#
+# Usage: cap job user title copies options [filename]
+#
+
+# No arguments means show available devices...
+
+if test ${#argv} = 0; then
+ echo &quot;network cap \&quot;Unknown\&quot; \&quot;Mac OS Printer via CAP\&quot;&quot;
+ exit 0
+fi
+
+# Collect arguments...
+
+user=$2
+copies=$4
+
+if test ${#argv} = 5; then
+ # Get print file from stdin; copies have already been handled...
+ file=/var/tmp/$$.prn
+ copies=1
+ cat &gt; $file
+else
+ # Print file is on command-line...
+ file=$6
+fi
+
+# Create a dummy cap.printers file for this printer based
+# upon a device URI of &quot;cap://server/printer&quot;...
+
+echo $PRINTER/$DEVICE_URI | \
+ awk -F/ '{print $1 &quot;=&quot; $5 &quot;:LaserWriter@&quot; $4}' &gt; /var/tmp/$$.cap
+
+CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
+
+# Send the file to the printer, once for each copy. This assumes that you
+# have properly initialized the cap.printers file...
+
+while [ $copies -gt 0 ]; do
+ papif -n $user &lt; $file
+
+ copies=`expr $copies - 1`
+done
+
+# Remove any temporary files...
+if test ${#argv} = 5; then
+ /bin/rm -f $file
+fi
+
+/bin/rm -f /var/tmp/$$.cap
+
+exit 0
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+
+<H2><A NAME="8_6">Imprimer depuis des clients Windows</A></H2>
+
+<P>Bien que CUPS ne fournisse directement pas de prise en charge de Windows, le logiciel libre SAMBA le fait. La version
+2.0.6 de SAMBA est la première qui prenne en charge CUPS. Vous pouvez télécharger SAMBA à l'adresse :</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>Pour configurer SAMBA pour CUPS, éditez le contenu du fichier <VAR>smb.conf</VAR>
+et remplacez les commandes d'impression existantes par les lignes:</P>
+<UL>
+<PRE>
+printing = cups
+printcap name = cups
+</PRE>
+</UL>
+<P>C'est tout ce qu'il y a à faire! Les utilisateurs distants pourront désormais explorer les imprimantes de votre système et
+leur envoyer des travaux d'impression.</P>
+
+<H3><A NAME="8_6_1">Exporter les pilotes d'imprimantes</A></H3>
+
+<P>Vous pouvez éventuellement exporter des pilotes d'imprimantes de votre serveur CUPS en utilisant la commande
+<CODE>cupsaddsmb</CODE> et le logiciel SAMBA 2.2.0 ou supérieur.</P>
+
+<P>Avant de pouvoir exporter les pilotes d'imprimantes, vous devez télécharger les pilotes d'imprimantes actuels Adobe PostScript
+à partir du site "web" Adobe
+(<A HREF="http://www.adobe.com/">http://www.adobe.com/</A>).
+Utilisez le logiciel libre <CODE>unzip</CODE> pour extraire les fichiers des archives ZIP auto-extractibles contenant
+les pilotes; vous aurez besoin des fichiers suivants:</P>
+<UL>
+<PRE>
+ADFONTS.MFM
+ADOBEPS4.DRV
+ADOBEPS4.HLP
+ADOBEPS5.DLL
+ADOBEPSU.DLL
+ADOBEPSU.HLP
+DEFPRTR2.PPD
+ICONLIB.DLL
+PSMON.DLL
+</PRE>
+</UL>
+<P>Copiez ces fichiers dans le répertoire <VAR>/usr/share/cups/drivers</VAR> - vous pourriez avoir à renommer certains fichiers
+de sorte que tous les noms soient complètement en majuscules.</P>
+<P>Ensuite, ajouter un partage d'imprimante <CODE>print$</CODE> pour les pilotes d'imprimantes à votre fichier
+<VAR>smb.conf</VAR>:</P>
+<UL>
+<PRE>
+[print$]
+ comment = Pilotes d'imprimantes
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = root
+</PRE>
+</UL>
+
+<P>Le répertoire de vos pilotes d'imprimantes peut être n'importe où dans le système; assurez-vous simplement qu'il est
+accessible en écriture aux utilisateurs indiqués par la directive <CODE>write list</CODE>.
+Assurez-vous également que chaque utilisateur de la liste <CODE>write list</CODE> possède un mot de passe SAMBA en utilisant
+la commande <CODE>smbpasswd(1)</CODE> sinon vous ne pourrez pas vous authentifier.</P>
+<P>Enfin, exécutez la commande <CODE>cupsaddsmb</CODE> pour exporter les pilotes d'imprimantes pour une ou plusieurs
+files d'impression:</P>
+<UL>
+<PRE>
+<KBD>cupsaddsmb -U root printer1 ... printerN <I>ENTREE</I></KBD>
+</PRE>
+</UL>
+<P>Exécuter la commande <CODE>cupsaddsmb</CODE> avec l'option <CODE>-a</CODE> exportera les imprimantes:</P>
+<UL>
+<PRE>
+<KBD>cupsaddsmb -U root -a <I>ENTREE</I></KBD>
+</PRE>
+</UL>
+<H2><A NAME="8_7">Imprimer vers des serveurs d'impression Windows</A></H2>
+
+<P>CUPS peut imprimer vers des serveurs Windows de deux façons. La première utilise le protocole LPD sur le système CUPS et
+le service "Serveur d'impression TCP/IP" sur le système Windows NT. Vous pouvez trouver plus d'information au sujet de la première
+configuration dans la section précédente <A HREF="#LPD">LPD</A> de ce chapitre.</P>
+
+<P>La seconde méthode utilise le protocole SMB de Microsoft ("Server Message Block"). La prise en charge de ce protocole est
+fournie par le logiciel libre SAMBA. Vous pouvez télécharger SAMBA à l'adresse suivante:</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>Pour configurer CUPS pour SAMBA, exécutez la commande suivante:</P>
+<UL>
+<PRE>
+<B>ln -s `which smbspool` /usr/lib/cups/backend/smb ENTREE</B>
+</PRE>
+</UL>
+<P>Le programme <CODE>smbspool(1)</CODE> est fourni avec SAMBA depuis la version 2.0.6. Une fois que vous avez créé le lien
+vous pouvez configurer vos imprimantes en utilisant l'un des URI de périphérique suivants:</P>
+<UL>
+<PRE>
+smb://groupe_de_travail_ou_domaine/serveur/nom_partage
+smb://serveur/nom_partage
+smb://utilisateur:mot_de_passe@groupe_de_travail_ou_domaine/serveur/nom_partage
+smb://utilisateur:mot_de_passe@serveur/nom_partage
+</PRE>
+</UL>
+<P>Le nom <CODE>groupe_de_travai_ou_domaine</CODE> doit être indiqué si votre système utilise un autre nom que la
+valeur standard de votre réseau. Les chaînes <CODE>utilisateur:mot_de_passe</CODE> sont nécessaires si vous imprimez
+vers des serveurs Windows NT ou des partages Windows 95/98 dont les mots de passe sont activés.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Licence d'utilisation du logiciel</A></H1>
+<H2 ALIGN="CENTER"><A NAME="9_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P><i>(NdT : pour des raisons évidentes de droit, j'ai volontairement gardé la licence d'utilisation du logiciel et la licence GPL en anglais car une traduction
+de celles-ci pourrait donner lieu à des interprétations erronées... et en plus je ne suis pas juriste !)</i></P>
+
+<P ALIGN="CENTER">Copyright 1997-2003 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3111 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
+<H3><A NAME="9_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="9_1_2">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="9_1_3">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
+<BR> Director of Marketing
+<BR> Artifex Software Inc.
+<BR> 454 Las Gallinas Ave., Suite 108
+<BR> San Rafael, CA 94903 USA
+<BR> Voice: +1.415.492.9861
+<BR> Fax: +1.415.492.9862
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
+</P>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
+ Derek B. Noonburg
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="9_1_4">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com">http://www.easysw.com</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<PRE>
+
+</PRE>
+<H4>Preamble</H4>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+</LI>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+</LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H4>Preamble</H4>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.</LI>
+<P></P>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<P></P>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
+<P></P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
+<P></P>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
+<P></P>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.</LI>
+<P></P>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
+<P></P>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+<H1 ALIGN="RIGHT"><A NAME="COMMON_NETWORK">B - Réglages réseau courants</A></H1>
+
+<P>Cette annexe englobe de nombreux serveurs d'impression et interfaces réseau TCP/IP disponibles actuellement sur le marché.</P>
+
+<H2><A NAME="10_1">Configurer une interface réseau</A></H2>
+
+<P>Lorsque vous installez votre imprimante réseau ou votre serveur d'impression pour la première fois sur votre réseau
+local (LAN), vous devez configurer son adresse IP ("Internet Protocol"). Sur la plupart des imprimantes réseau pour groupe
+de travail, vous pouvez le faire directement au moyen du panneau de contrôle. Cependant, dans la plupart des cas, vous
+préfèrerez assigner l'adresse IP à distance depuis votre station de travail. Cela rend l'administration un peu plus simple et
+évite d'assigner accidentellement des adresses réseau eu doublons.</P>
+
+<P>Pour configurer votre imprimante ou votre serveur d'impression pour une assignation à distance de l'adresse réseau, vous
+aurez besoin de son adresse MAC (ethernet Media Access Control), également appelée adresse de noeud ("node address") dans
+certains cas. Vous aurez également besoin de connaître l'adresse IP que vous voulez utiliser pour ce matériel. L'adresse MAC
+peut souvent être trouvée sur la page de test de l'imprimante ou sur son panneau arrière.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="10_1_1">Configuration de l'adresse IP utilisant ARP</A></H3>
+
+<P>La méthode la plus simple pour installer l'adresse IP d'un matériel réseau est d'utiliser la commande
+<CODE>arp(8)</CODE>. La commande <CODE>arp</CODE> envoie un paquet ARP ("Address Resolution Protocol") à l'adresse MAC indiquée
+tout en lui indiquant son adresse IP:</P>
+<UL>
+<PRE>
+<B>arp -s adresse-ip adresse-mac ENTREE</B>
+<B>arp -s hote.domaine.com 08:00:69:00:12:34 ENTREE</B>
+<B>arp -s 192.0.2.2 08:00:69:00:12:34 ENTREE</B>
+</PRE>
+</UL>
+<H3><A NAME="10_1_2">Configuration de l'adresse IP utilisant RARP</A></H3>
+
+<P>La manière la plus souple d'assigner une adresse IP sous UNIX est d'utiliser le protocole RARP
+("Reverse Address Resolution Protocol"). RARP permet à un matériel réseau d'émettre une requête d'adresse IP en utilisant
+sont adresse MAC, un ou plusieurs serveurs RARP sur le réseau répondront à cette requête par un paquet ARP proposant une
+adresse IP que le matériel réseau peut utiliser.</P>
+
+<P>RARP devrait être utilisé lorsque vous administrez de nombreuses imprimantes ou serveurs d'impression, ou quand un matériel
+réseau ne peut se "souvenir" de son adresse IP après chaque redémarrage. Si vous n'avez qu'une seule imprimante ou serveur
+d'impression, la commande <CODE>arp</CODE> est la plus adaptée.</P>
+
+<P>Certains systèmes d'exploitation UNIX utilisent un programme nommé <CODE>rarpd(8)</CODE> pour administrer RARP.
+Les autres, tels que GNU/Linux, prennent en charge ce protocole à l'intérieur du noyau. Pour les systèmes qui utilisent
+le programme <CODE>rarpd</CODE> vous aurez besoin de le démarrer avant que les requêtes RARP commencent:</P>
+<UL>
+<PRE>
+<B>rarpd ENTREE</B>
+</PRE>
+</UL>
+<P>Sous IRIX vous pouvez activer cette fonctionnalité en standard en utilisant la commande suivante:</P>
+<UL>
+<PRE>
+<B>chkconfig rarpd on ENTREE</B>
+</PRE>
+</UL>
+<P>Le programme <CODE>rarpd</CODE> et la version noyau de la prise en charge RARP lisent toutes les deux une liste des adresses
+MAC et IP à partir d'un fichier <VAR>/etc/ethers</VAR>. Chaque ligne comporte l'adresse Ethernet suivie de l'adresse IP ou
+du nom d'hôte:</P>
+<UL>
+<PRE>
+08:00:69:00:12:34 mon_imprimante.mon_domaine.com
+08:00:69:00:12:34 192.0.2.2
+</PRE>
+</UL>
+<P>Ajoutez une ligne à ce fichier et redémarrez l'imprimante ou le serveur d'impression pour qu'elle/il récupère son adresse IP.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="10_1_3">Configuration de l'adresse IP utilisant BOOTP</A></H3>
+
+<P>Le protocole BOOTP est utilisé quand vous avez besoin de fournir des informations supplémentaires à l'interface réseau
+telles que l'emplacement du fichier de configuration. En utilisant le programme standard <CODE>bootpd(8)</CODE>
+fourni sous UNIX, vous avez simplement besoin d'ajouter la ligne suivante au fichier <VAR>/etc/bootptab</VAR> pour IRIX:</P>
+<UL>
+<PRE>
+mon_imprimante 08:00:69:00:12:34 192.0.2.2 <VAR>mon_imprimante.boot</VAR>
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>Les versions plus récentes de <CODE>bootpd</CODE> utilisent un format différent:</P>
+<UL>
+<PRE>
+mon_imprimante:ha=080069001234:ip=192.0.2.2:<VAR>t144=mon_imprimante.boot</VAR>
+</PRE>
+</UL>
+<P>Le fichier <VAR>mon_imprimante.boot</VAR> est situé en standard dans le répertoire <VAR>/usr/local/boot</VAR>
+Si vous n'avez pas besoin de fournir un fichier de démarrage, vous pouvez laisser vide la fin de la ligne.
+<!-- NEED 2in -->
+
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Certaines versions d'UNIX n'activent pas le service BOOTP en standard. Le fichier
+<VAR>/etc/inetd.conf</VAR> contient généralement une ligne pour le service BOOTP. ELle peut être décommentée si nécessaire.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="10_2">Vérifier la connexion de l'imprimante</A></H2>
+
+<P>Pour vérifier que l'adresse IP a bien été assignée et que l'imprimante est correctement connectée au réseau local (LAN), tapez:</P>
+<UL>
+<PRE>
+<B>ping adresse-ip ENTREE</B>
+</PRE>
+</UL>
+<P>Si la connexion fonctionne correctement vous devriez voir apparaître quelque chose de la forme suivante :</P>
+<UL>
+<PRE>
+<B>ping mon_imprimante ENTREE</B>
+PING mon_imprimante (192.0.2.2): 56 data bytes
+64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
+64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
+</PRE>
+</UL>
+<P>Sinon, vérifiez que que l'imprimante ou le serveur d'impression est bien connecté au réseau (NdT : vérifiez ces @#*¤%§ câbles !),
+qu'elle est sous tension et que l'adresse IP est bonne. Vous pouvez également voir la configuration réseau en imprimant une
+page de test à partir du panneau de contrôle du matériel.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="10_3">Réglages d'interfaces réseau et serveur d'impression courants</A></H2>
+
+<P>Une fois que vous avez configuré l'adresse IP, vous pouvez accéder à l'imprimante ou au serveur d'impression
+en utilisant les programmes d'arrière-plan <CODE>ipp</CODE>, <CODE>lpd</CODE>, ou <CODE>socket</CODE>.
+La liste qui suit donne les interfaces réseau et serveurs d'impression courants ainsi que les réglages que vous devriez
+utiliser dans CUPS:
+<CENTER>
+<TABLE BORDER="1">
+<TR ALIGN="LEFT" VALIGN="TOP"><TH>Modèle / Fabricant</TH><TH>URI de périphérique</TH></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Apple LaserWriter</TD><TD>lpd://<I>
+address</I>/PASSTHRU</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/o IPP
+<BR><A HREF="#AXIS"> (voir instructions)</A></TD><TD>socket://<I>address</I>
+:9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/IPP</TD><TD>ipp://<I>address</I>
+/LPT1
+<BR> ipp://<I>address</I>/LPT2
+<BR> ipp://<I>address</I>/COM1</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Castelle LANpress<SUP>TM</SUP></TD><TD>
+lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>DPI NETPrint</TD><TD>lpd://<I>address</I>
+/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EFI&reg; Fiery&reg; RIP</TD><TD>lpd://<I>
+address</I>/print</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EPSON&reg; Multiprotocol Ethernet
+ Interface Board</TD><TD>socket://<I>address</I></TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
+lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/o IPP</TD><TD>
+socket://<I>address</I>:9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/IPP</TD><TD>
+ipp://<I>address</I>/ipp
+<BR> ipp://<I>address</I>/ipp/port1
+<BR> ipp://<I>address</I>/ipp/port2
+<BR> ipp://<I>address</I>/ipp/port3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Intel&reg; NetportExpress XL, PRO/100</TD><TD>
+lpd://<I>address</I>/LPT1_PASSTHRU
+<BR> lpd://<I>address</I>/LPT2_PASSTHRU
+<BR> lpd://<I>address</I>/COM1_PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Lexmark<SUP>TM</SUP> MarkNet</TD><TD>
+lpd://<I>address</I>/ps</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Linksys EtherFast&reg;
+<BR><A HREF="#LINKSYS"> (voir instructions)</A></TD><TD>socket://<I>address</I>
+:4010
+<BR> socket://<I>address</I>:4020
+<BR> socket://<I>address</I>:4030</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Kodak&reg;</TD><TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>QMS&reg; CrownNet<SUP>TM</SUP></TD><TD>
+lpd://<I>address</I>/ps</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Tektronix&reg; PhaserShare<SUP>TM</SUP></TD><TD>
+socket://<I>address</I>:9100</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; 4512 NIC</TD><TD>lpd://<I>
+address</I>/PORT1</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; XNIC</TD><TD>lpd://<I>address</I>
+/PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; (most others)</TD><TD>socket://<I>
+address</I>:5503</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="AXIS">Configuration de serveurs d'impression Axis</A></H2>
+
+<P>Les serveurs d'impression Axis peuvent être configurés en utilisant ARP, RARP ou BOOTP. Cependant, sur certains modèles
+ne prenant pas en charge IPP, une configuration supplémentaire est nécessaire pour permettre au serveur de dialoguer avec CUPS.
+<!-- NEED 3in -->
+</P>
+<P>Chaque serveur d'impression possède une fichier de configuration nommé <VAR>config</VAR>
+qui contient la liste des paramètres réseau à utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord le
+télécharger à partir du serveur d'impression en utilisant le programme <CODE>ftp(1)</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp adresse-ip ENTREE</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTREE</B>
+331 User name ok, need password
+Password: <B>pass ENTREE</B> <I>(le mot de passe n'apparaît pas)</I>
+230 User logged in
+ftp&gt; <B>get config ENTREE</B>
+local: config remote: config
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2),
+(mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Ensuite, éditez son contenu avec votre éditeur de texte préféré et repérez les lignes commençant par:</P>
+<UL>
+<PRE>
+RTN_OPT. : YES
+RTEL_PR1. : 0
+RTEL_PR2. : 0
+RTEL_PR3. : 0
+RTEL_PR4. : 0
+RTEL_PR5. : 0
+RTEL_PR6. : 0
+RTEL_PR7. : 0
+RTEL_PR8. : 0
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+Changez la ligne <CODE>RTN_OPT</CODE> en:
+<UL>
+<PRE>
+RTN_OPT. : <B>NO</B>
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Cela désactive le protocole "Reverse TELNET" et active le protocole standard TELNET sur le serveur d'impression.
+Ensuite, assignez un numéro de port pour chaque port parallèle ou série sur le serveur, comme suit:</P>
+<UL>
+<PRE>
+RTEL_PR1. : <B>9100</B>
+RTEL_PR2. : <B>9101</B>
+RTEL_PR3. : <B>9102</B>
+RTEL_PR4. : <B>9103</B>
+RTEL_PR5. : <B>9104</B>
+RTEL_PR6. : <B>9105</B>
+RTEL_PR7. : <B>9106</B>
+RTEL_PR8. : <B>9107</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>Cela a principalement pour effet de forcer le serveur Axis à ressembler à un serveur d'impression
+Hewlett Packard JetDirect EX. Sauvegardez le fichier et installez le sur le serveur d'impression dans le fichier
+<VAR>config</VAR> au moyen de la commande <CODE>ftp</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp adresse-ip ENTREE</B>
+Connected to adresse-ip.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTREE</B>
+331 User name ok, need password
+Password: <B>pass ENTREE</B> <I>(le mot de passe n'est pas affiché)</I>
+230 User logged in
+ftp&gt; <B>put config CONFIG ENTREE</B>
+local: config remote: CONFIG
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2), (mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>get hardreset ENTREE</B>
+local: hardreset remote: hardreset
+200 PORT command successful.
+421 Axis NPS ### hard reset, closing connection.
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Votre serveur d'impression Axis est à présent opérationnel!</P>
+
+<H2><A NAME="LINKSYS">Configuration de serveurs d'impression Linksys</A></H2>
+
+<P>Les serveurs d'impression LinkSys peuvent être configurés au moyen de ARP, RARP ou BOOTP. Comme certains serveurs
+d'impression Axis anciens, une configuration supplémentaire TCP/IP est nécessaire pour les faire fonctionner avec CUPS
+<!-- NEED 3in -->
+</P>
+<P>Chaque serveur d'impression possède une fichier de configuration nommé <VAR>config</VAR>
+qui contient la liste des paramètres réseau à utiliser par le serveur. Pour modifier ce fichier, vous devez d'abord le
+télécharger à partir du serveur d'impression en utilisant le programme <CODE>ftp(1)</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp -n adresse-ip ENTREE</B>
+Connected to adress-ip.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>get CONFIG ENTREE</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+WARNING! 68 bare linefeeds received in ASCII mode
+File may not have transferred correctly.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Ensuite, éditez son contenu avec votre éditeur de texte préféré et repérez les lignes commençant par:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:P1
+0120 L2_PROUT:P1
+0140 L3_PROUT:P1
+</PRE>
+</UL>
+<P>Changez le numéro de port pour chaque port parallèle et série sur le serveur, comme suit:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:<B>P1</B>
+0120 L2_PROUT:<B>P2</B>
+0140 L3_PROUT:<B>P3</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>Cela relie chaque imprimante virtuelle à un port physique. Sauvegardez le fichier et installez le sur le serveur d'impression dans le fichier
+<VAR>config</VAR> au moyen de la commande <CODE>ftp</CODE>:</P>
+<UL>
+<PRE>
+<B>ftp -n adresse-ip ENTREE</B>
+Connected to adresse-ip.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>put CONFIG ENTREE</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTREE</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Votre serveur d'impression SysLink est désomais opérationnel !</P>
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_DRIVERS">C - Pilotes d'imprimantes</A></H1>
+<P>Cette annexe dresse la liste des pilotes d'imprimantes qui sont fournis avec CUSP.</P>
+<H2><A NAME="11_1">Pilotes d'imprimantes</A></H2>
+<P>CUPS inclut les pilotes d'imprimantes suivants:</P>
+<UL>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>,<VAR> epson9.ppd</VAR></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>,<VAR> epson24.ppd</VAR>
+</LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>,<VAR> stcolor.ppd</VAR></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>,<VAR> stphoto.ppd</VAR></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A>,<VAR> deskjet.ppd</VAR></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A>,<VAR> laserjet.ppd</VAR></LI>
+</UL>
+<H2><A NAME="EPSON9">EPSON 9-pin Dot Matrix</A></H2>
+<P>Le pilote EPSON 9-pin Dot Matrix (<VAR>epson9.ppd</VAR>) prend en charge les imprimantes 9 aiguilles qui utilisent le jeu de commandes ESC/P.
+Il fournit l'impression en noir et blanc dans les résolutions 60x72, 120x72, et 240x72 PPP (DPI).</P>
+
+<H2><A NAME="EPSON24">EPSON 24-pin Dot Matrix</A></H2>
+<P>Le pilote EPSON 24-pin Dot Matrix (<VAR>epson9.ppd</VAR>) prend en charge les imprimantes 24 aiguilles qui utilisent le jeu de commandes ESC/P.
+Il fournit l'impression en noir et blanc dans les résolutions 120x180, 180x180, 360x180, et 360x360 PPP (DPI).</P>
+
+<H2><A NAME="STCOLOR">EPSON Stylus Color</A></H2>
+
+<P>Le pilote EPSON Stylus Color (<VAR>stcolor.ppd</VAR>) prend en charge les imprimantes EPSON
+ Stylus Color qui utilisent le jeu de commandes ESC/P2.
+Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 180, 360, et 720 PPP (DPI).</P>
+
+<H2><A NAME="STPHOTO">EPSON Stylus Photo</A></H2>
+
+<P>Le pilote EPSON Stylus Photo (<VAR>stphoto.ppd</VAR>) prend en charge les imprimantes EPSON
+ Stylus Photo qui utilisent le jeu de commandes ESC/P2.
+Il fournit l'impression en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 180, 360, et 720 PPP (DPI).</P>
+
+<H2><A NAME="DESKJET">HP DeskJet</A></H2>
+
+<P>Le pilote HP DeskJet (<VAR>deskjet.ppd</VAR>) prend en charge les imprimantes HP DeskJet
+qui utilisent le jeu de commandes PCL.
+Il fournit l'imrpession en couleur (CMYK) ainsi qu'en noir et blanc dans les résolutions 150, 300, et
+ 600 PPP (DPI).</P>
+
+<P>Les imprimantes DeskJet qui utilisent le jeu de commandes HP-PPA (720C,
+ 722C, 820C, and 1100C) <B>ne sont pas</B> prises en charge du fait de l'absence totale de documentation de la part de
+Hewlett Packard.</P>
+
+<P>Le "duplexer" fourni avec les imprimantes de la série d'imprimantes HP DeskJet 900 n'est également pas pris en charge pour les mêmes raisons.</P>
+
+<H2><A NAME="LASERJET">HP LaserJet</A></H2>
+
+<P>Le pilote HP LaserJet (<VAR>laserjet.ppd</VAR>) prend en charge les impriamntes HP LaserJet
+qui utilisent le jeu de commandes PCL.
+Il fournit l'impression seulement en noir et blanc et prend en charge le "duplexer" s'il est installé.
+Il prend en charge les résolutions 150, 300, et 600 PPP (DPI).</P>
+
+<P>Les imprimantes LaserJet qui n'utilisent pas le jeu de commandes PCL (3100, 3150) ne sont pas prises en charge
+du fait d'une absence totale de documentation de la part de Hewlett Packard.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="FILES">D - Liste des fichiers</A></H1>
+
+<P>Cette annexe dresse la liste des fichiers et répertoire qui sont installés par CUPS
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR VALIGN="TOP"><TH>Chemin</TH><TH>Description</TH></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/certs/</TD>
+<TD>Emplacement des fichiers des certificats d'authentification pour les clients HTTP locaux.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/classes.conf</TD>
+<TD>Fichiers de configuration des classes d'imprimantes pour l'ordonnanceur.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/cupsd.conf</TD>
+<TD>Fichier de configuration de l'ordonnanceur.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/interfaces/</TD>
+<TD>Emplacement des scripts d'interface System V pour les imprimantes.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/mime.convs</TD>
+<TD>Liste des filtres de fichiers standards inclus dans ESP Print Pro.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/mime.types</TD>
+<TD>Liste des types de fichiers reconnus par ESP Print Pro.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/ppd/</TD>
+<TD>Emplacement des fichiers PPD ("PostScript Printer Description") pour les imprimantes.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/etc/cups/printers.conf</TD>
+<TD>Fichier de configuration des imprimantes pour l'ordonnanceur.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/usr/bin/cancel</TD><TD>La commande d'annulation de travaux System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/disable</TD><TD>La commande de désactivation d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/enable</TD><TD>La commande d'activation d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lp</TD><TD>La commande d'impression System V.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/usr/bin/lpoptions</TD><TD>Jeu d'options d'impression et de valeurs implicites personnalisées par l'utiliseur.</TD></TR>
+
+<TR VALIGN="TOP"><TD>/usr/bin/lppasswd</TD><TD>Ajoute, modifie et retire des mots de passe pour des comptes "Digest".</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpq</TD><TD>La commande d'état Berkeley.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpr</TD><TD>La commande d'impression Berkeley.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lprm</TD><TD>La commande d'annulation de travaux Berkeley.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpstat</TD><TD>La commande d'état System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/include/cups/</TD><TD>Fichiers d'en-tête de l'API CUPS.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.a
+<BR> /usr/lib32/libcupsimage.a</TD><TD>Librairies statiques (IRIX 6.5)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.a<BR> /usr/lib/libcupsimage.a</TD>
+<TD>Librairies statiques (tous les autres systèmes)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.sl.2
+<BR> /usr/lib/libcupsimage.sl.2</TD><TD>Librairies partagées (HP-UX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.so.2
+<BR> /usr/lib32/libcupsimage.so.2</TD><TD>Librairies partagées (IRIX 6.5)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.so.2
+<BR> /usr/lib/libcupsimage.so.2</TD><TD>Librairies partagées (tous les autres systèmes)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/backend/</TD><TD>Programme d'arrière-plan pour connexion à diverses imprimantes.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/cgi-bin/</TD><TD>Programmes CGI pour l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/daemon/</TD><TD>Démons pour la surveillance et pour la prise en charge LPD.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/filter/</TD><TD>Filtres pour divers types de fichiers.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/locale/</TD><TD>Emplacement des fichiers de messages spécifiques à chaque langue. (System V)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/nls/msg/</TD><TD>Emplacement des fichiers de messages spécifiques à chaque langue. (Compaq Tru64 UNIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/locale/</TD><TD>Emplacement des fichiers de messages spécifiques à chaque langue. (GNU/Linux, *BSD)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/accept</TD><TD>La commande d'acceptation de travaux.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/cupsd</TD><TD>L'ordonnanceur CUPS.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpadmin</TD><TD>L'outil d'administration d'imprimante System V.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpc</TD><TD>L'outil d'administration d'imprimante Berkeley.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpinfo</TD><TD>Les commandes "get-devices" et "get-ppds".</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpmove</TD><TD>La commande "move-jobs".</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/reject</TD><TD>La commande "reject-jobs".</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/share/catman/a_man/
+<BR> /usr/share/catman/u_man/</TD><TD>Pages de manuel (IRIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/man/</TD><TD>Pages de manuel (Compaq Tru64
+ UNIX, HP-UX, Solaris)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/man/</TD><TD>Pages de manuel (tous les autres systèmes)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/</TD><TD>Emplacement des fichiers de données des filtres.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/testprint.ps</TD><TD>Fichier de page de test PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/fonts/</TD><TD>Emplacement des polices de caractères PostScript pour le RIP PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/model/</TD><TD>
+Emplacement des fichiers PPD ("PostScript Printer Description") et des scripts d'interface pouvant être employés pour configurer une file d'impression.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/</TD><TD>
+D'autres fichiers d'initialisation du RIP PostScript.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/Fontmap</TD><TD>
+Le fichier de conversion de polices (convertit des noms de fichiers en noms de polices)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/templates/</TD><TD>Emplacement des fichiers "templates" HTML pour l'interface "web".</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/doc/cups/</TD><TD>Documentation et données des pages "web" pour l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/log/cups/</TD><TD>Emplacement des fichiers de suivi de l'ordonnanceur.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/spool/cups/</TD><TD>Emplacement des fichiers d'impression en attente de traitement.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 ALIGN="RIGHT"><A NAME="FAQ">E - Résoudre les problèmes courants</A></H1>
+
+<P>Cette annexe couvre certains des problèmes courants rencontrés par les utilisateurs lors de la première
+installation / configuration / utilisation de CUPS.</P>
+<P>Le support commercial de CUPS est disponible auprès d'Easy Software Products.
+Pour plus d'informations, veuillez nous contacter:</P>
+<UL>
+<LI>WWW:<A HREF="http://www.easysw.com"> <CODE>http://www.easysw.com</CODE>
+</A></LI>
+<LI>EMail:<A HREF="mailto:info@easysw.com"> info@easysw.com</A></LI>
+<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600</LI>
+</UL>
+
+<H2><A NAME="13_1">Mes applications ne voient pas les imprimantes disponibles</A></H2>
+
+<P>Beaucoup d'applications lisent le contenu du fichier <VAR>/etc/printcap</VAR> pour obtenir la liste des imprimantes disponibles.</P>
+
+<P>La configuration standard de CUPS ne crée pas ce fichier <VAR>/etc/printcap</VAR> automatiquement. Pour activer la création
+et la mise à jour automatiques de ce fichier, utilisez la directive <A HREF="#Printcap"><CODE>Printcap</CODE></A>décrite au
+<A HREF="#PRINTING_MANAGEMENT">Chapitre 6, &quot;Administration du système d'impression&quot;</A>.</P>
+
+<H2><A NAME="13_2">CUPS ne reconnaît pas mon nom d'utilisateur et mon mot de passe!</A></H2>
+
+<P>CUPS vous demandera un nom d'utilisateur UNIX et un mot de passe lorsque vous effectuerez des tâches d'administration
+à distance ou au moyen d'un navigateur "web". La configuration standard de CUPS nécessite que vous utilisiez le nom d'utilisateur
+<CODE>root</CODE> et son mot de passe correspondant pour authentifier la requête.</P>
+
+<P>Pour des raisons de sécurité, CUPS ne vous autorise pas à authentifier une requête d'administration au moyen d'un compte dépourvu de mot de passe. Si vous n'avez pas de mot de passe pour le compte <CODE>root</CODE>, vous ne pourrez pas faire d'administration
+à distance ou via un navigateur "web" !
+<!-- NEED 2in -->
+</P>
+<P>Pour désactiver l'authentification par mot de passe vous devez éditer le contenu du fichier
+<VAR>/etc/cups/cupsd.conf</VAR> et commenter les lignes:</P>
+<UL>
+<PRE>
+AuthType Basic
+AuthClass System
+</PRE>
+</UL>
+pour l'emplacement <VAR>/admin</VAR>. Redémarrez alors le serveur CUPS comme indiqué dans le
+<A HREF="#PRINTING_MANAGEMENT">Chapitre 6, &quot;Administration du serveur d'impression&quot;</A>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Désactiver les vérifications de mot de passe autorisera tout utilisateur local à modifier les imprimantes et les classes,
+mais l'administration distante depuis un autre poste ne sera toujours pas autorisée.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H2><A NAME="ALLOW_REMOTE">Je ne peux pas effectuer de tâches d'administration depuis un poste distant!</A></H2>
+
+<P>La configuration standard de CUPS limite l'administration au poste local. Pour ouvrir l'accès, éditez le contenu du
+fichier <VAR>/etc/cups/cupsd.conf</VAR> et commentez les lignes:</P>
+<UL>
+<PRE>
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+</PRE>
+</UL>
+pour l'emplacement <VAR>/admin</VAR>. Redémarrez alors le serveur CUPS comme indiqué dans le
+<A HREF="#PRINTING_MANAGEMENT">Chapitre 6, &quot;Administration du serveur d'impression&quot;</A>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Autoriser l'accès à l'administration pour tous les hôtes présente un risque potentiel de sécurité. Veuillez vous reporter
+au <A HREF="#PRINTING_MANAGEMENT">Chapitre 6, &quot;Administration du serveur d'impression&quot;</A> pour une description de
+ces risques ainsi que des méthodes pour les minimiser.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+<H2><A NAME="13_4">Je ne peux pas effectuer de tâches d'administration depuis mon navigateur "web"!</A>
+</H2>
+<P>Ce problème est généralement dû:</P>
+<OL>
+<LI>au fait de donner le mauvais mot de passe pour le compte root.</LI>
+<LI>au fait d'accéder au serveur CUPS en utilisant le nom d'hôte ou l'adresse IP sans activer l'accès à distance pour les fonctions d'administration.
+Cela peut être corrigé en suivant les instructions présentes dans la section <A HREF="#ALLOW_REMOTE">
+ &quot;Je ne peux pas effectuer de tâches d'administration depuis un poste distant!&quot;</A> étudiée précédemment dans cette
+annexe.</LI>
+<LI>au fait de ne pas avoir de mot de passe pour le compte root. Pour des raisons de sécurité, CUPS n'authentifiera pas les comptes utilisateur dépourvus de mot de passe.</LI>
+<LI>au fait de s'authentifier au moyen d'un compte distinct de root mais qui n'est pas membre du groupe system.</LI>
+<LI>au fait de configurer CUPS pour utiliser l'authentification "Digest" et tenter d'y accéder au moyen d'un navigateur
+"web" ne prenant pas en charge ce type d'authentification.</LI>
+</OL>
+<H2><A NAME="13_5">Messages "Connection Refused"</A></H2>
+
+<P>Dans des circonstances normales, des messages &quot;connection refused&quot; pour une imprimante réseau peuvent être
+rencontrés de temps en temps. La plupart des interfaces réseau autorisent une unique connexion à un instant donné (un travail
+à la fois) et refuseront l'accès à tous les autres systèmes tant que la première connexion sera active. CUPS retente automatiquement
+de se connecter toutes les 30 secondes.</P>
+
+<P>Si le problème persiste et que vous ne pouvez imprimer aucun travail sur l'imprimantes, vérifiez qu'une autre machine
+ne maintient pas une connexion avec l'imprimante, et que vous avez sélectionné le bon port ou le bon nom d'imprimante.</P>
+
+<P>De même, la plupart des serveurs d'impression externes refuseront les connexions si une imprimante est hors tension
+ou hors ligne. Vérifiez que l'imprimante affectée est sous tension et en ligne.</P>
+
+<H2><A NAME="13_6">Message "Write Error"</A></H2>
+
+<P>Si vous obtenez des messages &quot;write error&quot; sur une file d'impression, l'interface de l'imprimante (généralement
+une interface Hewlett Packard JetDirect) a dépassé le délai d'attente maximum et résilié la connexion réseau avec votre poste
+de travail.</P>
+
+<P>L'erreur est causée par le délai d'amorçage qui existe entre l'établissement initial de la connexion à l'imprimante et
+l'envoi effectif des données de la première page imprimée.<!-- NEED 3in -->
+</P>
+<P>
+Pour corriger le problème, chagez la valeur du délai d'attente de l'interface et amenez sa valeur à un minimum de 180 secondes soit
+3 minutes. Pour changer le délai sur une interface Hewlett Packard JetDirect, tapez:</P>
+<UL>
+<PRE>
+<B>telnet adresse-ip ENTER</B>
+
+Trying adresse-ip...
+Connected to adresse-ip.
+Escape character is `^]'.
+
+Please type [Return] two times, to initialize telnet configuration
+For HELP type &quot;?&quot;
+&gt; <B>idle-timeout: 180 ENTREE</B>
+&gt; <B>quit ENTREE</B>
+</PRE>
+</UL>
+</BODY>
+</HTML>
+
diff --git a/doc/fr/sum.html b/doc/fr/sum.html
new file mode 100644
index 000000000..f48a016b2
--- /dev/null
+++ b/doc/fr/sum.html
@@ -0,0 +1,1776 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS - Manuel de l'utilisateur</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2003, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.14">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS - Manuel de l'utilisateur</H1></A><BR>
+CUPS-SUM-1.1.14<BR>
+Easy Software Products<BR>
+Copyright 1997-2003, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table des mati&egrave;res</A></H1>
+<BR>
+<BR><B><A HREF="#1">Pr&eacute;face</A></B>
+<UL>
+<LI><A HREF="#1_1">Aper&ccedil;u du syst&egrave;me</A></LI>
+<LI><A HREF="#1_2">Aper&ccedil;u du document</A></LI>
+<LI><A HREF="#1_3">Conventions d'&eacute;critures</A></LI>
+<LI><A HREF="#1_4">Abr&eacute;viations</A></LI>
+<LI><A HREF="#1_5">Autres r&eacute;f&eacute;rences</A></LI>
+</UL>
+<B><A HREF="#OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A></B>
+<UL>
+<LI><A HREF="#2_1">Le probl&egrave;me d'impression</A></LI>
+<LI><A HREF="#2_2">La technologie</A></LI>
+<LI><A HREF="#2_3">Travaux d'impression</A></LI>
+<LI><A HREF="#2_4">Classes d'imprimantes</A></LI>
+<LI><A HREF="#2_5">Filtres</A></LI>
+<LI><A HREF="#2_6">Programmes d'arri&egrave;re-plan (Backends)</A></LI>
+<LI><A HREF="#2_7">Pilotes d'imprimantes</A></LI>
+<LI><A HREF="#2_8">R&eacute;seau</A></LI>
+</UL>
+<B><A HREF="#USING_SYSTEM">2 - Utilisation du syst&egrave;me d'impression</A></B>
+<UL>
+<LI><A HREF="#3_1">Soumission de travaux &agrave; l'impression</A></LI>
+<LI><A HREF="#3_2">Choix d'une imprimante</A></LI>
+<LI><A HREF="#3_3">R&eacute;glage des options d'imprimante</A></LI>
+<LI><A HREF="#3_4">Impression de plusieurs copies</A></LI>
+<LI><A HREF="#3_5">V&eacute;rification de l'&eacute;tat d'une imprimante depuis la
+ ligne de commande</A></LI>
+<LI><A HREF="#3_6">V&eacute;rification de l'&eacute;tat d'un imprimante depuis
+ l'interface &quot;web&quot;</A></LI>
+<LI><A HREF="#3_7">Suppression d'un travail d'impression</A></LI>
+</UL>
+<B><A HREF="#STANDARD_OPTIONS">3 - Options standards d'imrimante</A></B>
+<UL>
+<LI><A HREF="#4_1">Options g&eacute;n&eacute;rales</A></LI>
+<UL>
+<LI><A HREF="#4_1_1">R&eacute;glage de l'orientation</A></LI>
+<LI><A HREF="#4_1_2">Choix du type, de la taille et de la source du
+ support d'impression</A></LI>
+<LI><A HREF="#4_1_3">Impression en recto/verso</A></LI>
+</UL>
+<LI><A HREF="#4_2">Options de pages de garde</A></LI>
+<UL>
+<LI><A HREF="#4_2_1">S&eacute;lection des pages de garde</A></LI>
+</UL>
+<LI><A HREF="#4_3">Options de document</A></LI>
+<UL>
+<LI><A HREF="#4_3_1">S&eacute;lection d'une s&eacute;rie de pages</A></LI>
+<LI><A HREF="#4_3_2">S&eacute;lection des pages paires et impaires</A></LI>
+<LI><A HREF="#4_3_3">Impression de plusieurs pages par face du support
+ (&quot;N-Up Printing&quot;)</A></LI>
+<LI><A HREF="#4_3_4">R&eacute;glage de la luminosit&eacute;</A></LI>
+<LI><A HREF="#4_3_5">R&eacute;glage de la correction Gamma</A></LI>
+</UL>
+<LI><A HREF="#4_4">Options de texte</A></LI>
+<UL>
+<LI><A HREF="#4_4_1">R&eacute;glage du nombre de caract&egrave;res par pouce</A></LI>
+<LI><A HREF="#4_4_2">R&eacute;glage du nombre de lignes par pouce</A></LI>
+<LI><A HREF="#4_4_3">R&eacute;glage du nombre de colonnes</A></LI>
+<LI><A HREF="#4_4_4">R&eacute;glage des marges de la page</A></LI>
+<LI><A HREF="#4_4_5">Impression am&eacute;lior&eacute;e</A></LI>
+</UL>
+<LI><A HREF="#4_5">Options d'image</A></LI>
+<UL>
+<LI><A HREF="#4_5_1">Positionnement de l'image</A></LI>
+<LI><A HREF="#4_5_2">Mise &agrave; l'&eacute;chelle de l'image</A></LI>
+<LI><A HREF="#4_5_3">Ajustement de la teinte (&quot;Hue&quot;, &quot;Tint&quot;) de l'image</A>
+</LI>
+<LI><A HREF="#4_5_4">Ajustement de la saturation de couleur de l'image</A>
+</LI>
+</UL>
+<LI><A HREF="#4_6">Options HP-GL/2</A></LI>
+<UL>
+<LI><A HREF="#4_6_1">Impression en noir</A></LI>
+<LI><A HREF="#4_6_2">Ajuster le trac&eacute; &agrave; la page</A></LI>
+<LI><A HREF="#4_6_3">R&eacute;glage de la largeur implicite de trac&eacute;</A></LI>
+</UL>
+<LI><A HREF="#4_7">Sortie brute ou non filtr&eacute;e</A></LI>
+</UL>
+<B><A HREF="#SAVING_OPTIONS">4 - Sauvegarder les options et valeurs
+ implicites des r&eacute;glages d'imprimante</A></B>
+<UL>
+<LI><A HREF="#5_1">Options d'imprimante</A></LI>
+<LI><A HREF="#5_2">R&eacute;glage des options pour une imprimante sp&eacute;cifique</A>
+</LI>
+<LI><A HREF="#5_3">Visualisation des r&eacute;glages implicites actuels</A></LI>
+<LI><A HREF="#5_4">Choix de l'imprimante implicite</A></LI>
+<LI><A HREF="#5_5">Instances d'imprimantes</A></LI>
+<LI><A HREF="#5_6">Retirer des instances d'imprimantes</A></LI>
+</UL>
+<B><A HREF="#LICENSE">A - Licence d'utilisation du logiciel (NdT : en
+ anglais)</A></B>
+<UL>
+<LI><A HREF="#6_1">Common UNIX Printing System License Agreement</A></LI>
+<UL>
+<LI><A HREF="#6_1_1">Introduction</A></LI>
+<LI><A HREF="#6_1_2">Trademarks</A></LI>
+<LI><A HREF="#6_1_3">Binary Distribution Rights</A></LI>
+<LI><A HREF="#6_1_4">Support</A></LI>
+</UL>
+<LI><A HREF="#6_2">GNU GENERAL PUBLIC LICENSE</A></LI>
+<UL>
+<LI><A HREF="#6_2_1">Preamble</A></LI>
+</UL>
+<LI><A HREF="#6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></LI>
+<UL>
+<LI><A HREF="#6_3_1">Preamble</A></LI>
+</UL>
+</UL>
+<HR NOSHADE>
+<H1 ALIGN="RIGHT"><A NAME="1">Pr&eacute;face</A></H1>
+<P>Ce manuel de l'utilisateur d&eacute;crit comment utiliser le logiciel CUPS<SUP>
+TM</SUP> (&quot;Common Unix Printing System<SUP>TM</SUP>&quot;) Version 1.1.14.</P>
+<P></P>
+<HR color="#000000" size="1px" width="50%"><I><B>Note du traducteur :</B>
+ Amies lectrices, amis lecteurs, j'ai fait le choix de<B> ne pas
+ traduire</B> l'expression anglaise<B> &quot;default&quot;</B> par la version
+ fran&ccedil;aise habituellent utilis&eacute;e<B> &quot;par d&eacute;faut&quot;</B> que l'on doit,
+ entre autres, &agrave; la documentation d'un c&eacute;l&egrave;bre syst&egrave;me d'exploitation
+ &quot;ouvert &agrave; tous vents&quot;.
+<BR>
+<BR> En effet, l'expression &quot;par d&eacute;faut&quot; est normalement utilis&eacute;e en
+ math&eacute;matiques (arrondi &quot;par d&eacute;faut&quot; ou &quot;par exc&egrave;s&quot;, personnellement je
+ cherche encore mon &quot;imprimante par exc&egrave;s&quot; !) mais elle est abusivement
+ employ&eacute;e en informatique pour signifier &quot;donn&eacute;e/comportement qui
+ s'applique si l'on n'en pr&eacute;cise pas<B> explicitement</B> la
+ valeur/nature/teneur&quot;.
+<BR>
+<BR> Or la langue fran&ccedil;aise poss&egrave;de justement un mot pout exprimer ce
+ concept : &quot;implicite&quot; (Larousse 1998 : &quot;Qui est contenu dans une
+ proposition sans &ecirc;tre exprim&eacute; en termes pr&eacute;cis formels; qui est la
+ cons&eacute;quence n&eacute;cessaire.&quot;). Dans la mesure du possible, j'utiliserai cet
+ adjectif sauf dans les cas o&ugrave; son emploi n'est pas suffisamment<B>
+ explicite</B> (sic !). Je lui pr&eacute;f&egrave;rerai alors l'expression &quot;... de
+ base ...&quot; ou l'adjectif &quot;standard&quot;.
+<BR>
+<BR> Ce choix est totalement personnel et le fait que j'ai fait l'effort
+ (non n&eacute;gligeable) de traduire ces lignes pour vos yeux d&eacute;licats suffit
+ &agrave; le justifier! Si, par malheur, ma prose vous est insupportable, je ne
+ vous emp&ecirc;che aucunement de vous reporter &agrave; la version originale o&ugrave; vous
+ retrouverez &quot;default&quot; entour&eacute; de tout le reste... en anglais, bien s&ucirc;r.
+ Enfin, si vous avez une meilleure traduction, je suis preneur !
+<BR>
+<BR> Malgr&eacute; les tr&egrave;s nombreuses relectures et corrections, certaines
+ fautes de frappe, d'orthographe ou de grammaire ont pu &eacute;chapper &agrave; ma
+ vigilance (ou &agrave; celles de mes relecteurs/correcteurs). Merci de me les
+ signaler afin de contribuer &agrave; l'am&eacute;lioration constante de la qualit&eacute; du
+ pr&eacute;sent manuel.
+<BR>
+<BR> Bonne lecture !</I>
+<HR color="#000000" size="1px" width="50%">
+<H2><A NAME="1_1">Aper&ccedil;u du syst&egrave;me</A></H2>
+<P>CUPS fournit une couche d'impression portable pour les syst&egrave;mes
+ d'exploitation de type UNIX&reg;. Il a &eacute;t&eacute; d&eacute;velopp&eacute; par <A HREF="http://www.easysw.com">
+Easy Software Products</A> pour promouvoir une solution d'impression
+ standard pour tous les vendeurs et utilisateurs d'UNIX. CUPS fournit
+ des interfaces en ligne de commande de type System V et Berkeley.</P>
+<P>CUPS utilise le protocol IPP (Internet Printing Protocol) comme base
+ de l'administration des travaux et files d'impression. Les protocoles
+ LPD (&quot;Line Printer Daemon&quot;), SMB (&quot;Server Message Block&quot;), et AppSocket
+ (JetDirect) sont &eacute;galement pris en charge avec des fontionnalit&eacute;s
+ r&eacute;duites. CUPS ajoute l'exploration r&eacute;seau des imprimantes (&quot;network
+ printer browsing&quot;) et des options d'impression bas&eacute;es sur PPD
+ (&quot;PostScript Printer Definition&quot;) pour prendre en charge l'impression
+ &quot;dans le monde r&eacute;el&quot; sous UNIX.</P>
+<P>CUPS inclut &eacute;galement une version adapt&eacute;e de GNU/Ghostscript
+ (actuellement bas&eacute;e sur la version 5.50) et un module de rendu (RIP -
+ Raster Image Processor) pour fichier image qui sont utilis&eacute;s pour
+ prendre en charge les imprimantes non-PostScript. Des pilotes d'exemple
+ (incluant ces filtres) pour imprimantes HP et EPSON sont &eacute;galement
+ inclus.</P>
+
+<!-- NEED 2in -->
+<H2><A NAME="1_2">Aper&ccedil;u du document</A></H2>
+<P>Le pr&eacute;sent manuel de l'utilisateur s'articule autour sections
+ suivantes:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A></LI>
+<LI><A HREF="#USING_SYSTEM">2 - Utilisation du syst&egrave;me d'impression</A></LI>
+<LI><A HREF="#STANDARD_OPTIONS">3 - Options standards pour imprimante</A>
+</LI>
+<LI><A HREF="#SAVING_OPTIONS">4 - Sauvegarde des options et valeurs
+ implicites des r&eacute;glages d'imprimante</A></LI>
+<LI><A HREF="#LICENSE">A - Licence d'utilisation du logiciel<I> (NdT :
+ en anglais)</I></A></LI>
+</UL>
+<H2><A NAME="1_3">Conventions d'&eacute;critures</A></H2>
+ Diverses conventions de polices de caract&egrave;res et de syntaxe sont
+ utilis&eacute;es dans ce guide. Des exemples et leur signification sont donn&eacute;s
+ ci-dessous:
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH>Exemple</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD> Les noms des commandes;
+ La premi&egrave;re r&eacute;f&eacute;rence faite &agrave; une commande ou une fonction dans un
+ chapitre est suivie par un num&eacute;ro de section de page de manuel.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><VAR>/var</VAR>
+<BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+ Noms de fichiers et de r&eacute;pertoires.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><TT>Request ID is Printer-123</TT></TD><TD>
+ &nbsp;&nbsp;&nbsp;</TD><TD>Affichage &eacute;cran.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d imprimante nom_fichier ENTREE</KBD>
+</TD><TD> &nbsp;&nbsp;&nbsp;</TD><TD>Frappe litt&eacute;rale de l'utilisateur; les touches
+ sp&eacute;ciales telles que <KBD>ENTREE</KBD> sont repr&eacute;sent&eacute;es en lettres
+ capitales.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD> Les nombres dans le texte
+ sont &eacute;crits avec un point symbolisant le s&eacute;parateur d&eacute;cimal.</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H2><A NAME="1_4">Abr&eacute;viations</A></H2>
+ Les abr&eacute;viations suivantes sont utilis&eacute;es au cours de ce manuel:
+<UL>
+<DL>
+<DT>ko</DT>
+<DD>Kilo-octets, ou 1024 octets
+<BR> &nbsp;</DD>
+<DT>Mo</DT>
+<DD>M&eacute;ga-octets, ou 1048576 octets
+<BR> &nbsp;</DD>
+<DT>Go</DT>
+<DD>Giga-octets, ou 1073741824 octets
+<BR> &nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Autres r&eacute;f&eacute;rences</A></H2>
+<UL>
+<DL>
+<DT>CUPS - Manuel de l'administrateur</DT>
+<DD>Un guide d'administration du logiciel CUPS.
+<BR> &nbsp;</DD>
+<DT>CUPS - Manuel du programmeur<I> (NdT : en anglais)</I></DT>
+<DD>Un guide du programmeur pour cr&eacute;er des programmes qui s'interfacent
+ avec et/ou &eacute;tendent le logiciels CUPS.
+<BR> &nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Aper&ccedil;u du syst&egrave;me d'impression</A>
+</H1>
+<P>Ce chapitre fournit un aper&ccedil;u du fonctionnement de CUPS.</P>
+<H2><A NAME="2_1">Le probl&egrave;me d'impression</A></H2>
+<P>Depuis des ann&eacute;es<I> le probl&egrave;me d'impression</I> a empoisonn&eacute; le
+ monde UNIX. Contrairement &agrave; Microsoft&reg; Windows&reg; ou Mac OS, UNIX n'a pas
+ d'interface standard ou de syst&egrave;me en place pour prendre en charge les
+ imprimantes. Parmi les solutions actuellement disponibles, les syst&egrave;mes
+ Berkeley et System V sont pr&eacute;dominants.</P>
+<P> Ces syst&egrave;mes d'impressions prennent en charge les imprimantes de
+ type matriciel texte ou les imprimantes PostScript (texte et
+ graphique), et avec quelques ajustements il peuvent prendre en charge
+ un grand nombre d'imprimantes et de formats de fichiers. Cependant,
+ puisque chaque version de syst&egrave;me d'exploitation UNIX utilise un
+ syst&egrave;me d'impression diff&eacute;rent de celui de son voisin, il est
+ extr&ecirc;mement difficile de d&eacute;velopper des pilotes d'imprimantes pour une
+ vaste gamme d'imprimantes et de syst&egrave;mes d'exploitation. Ceci, combin&eacute;
+ au faible nombre de clients pour chaque variante d'UNIX, a pouss&eacute; les
+ fabricants d'imprimantes &agrave; abandonner la prise en charge globale de
+ tous les UNIX.</P>
+<P> CUPS est con&ccedil;u pour &eacute;liminer<I> le probl&egrave;me d'impression</I>. Un
+ syst&egrave;me d'impression commun peut &ecirc;tre utilis&eacute; par toutes les variantes
+ d'UNIX pour prendre en charge les capacit&eacute;s d'impression dont les
+ utilisateurs ont besoin. Les fabricants d'imprimantes peuvent utiliser
+ l'interface modulaire des filtres pour d&eacute;velopper un unique pilote qui
+ prend en charge une large gamme de formats de fichiers et ce, sans
+ presque aucun effort. Etant donn&eacute; que CUPS fournit une interface
+ compatible avec les commandes Berkeley et System V, les utilisateurs
+ (et les applications) peuvent tirer b&eacute;n&eacute;fice de cette nouvelle
+ technologie sans avoir &agrave; faire de changements.</P>
+<H2><A NAME="2_2">La technologie</A></H2>
+<P> CUPS est bas&eacute; sur un standard &eacute;mergeant d'Internet appel&eacute; IPP
+ (Internet Printing Protocol). IPP a &eacute;t&eacute; adopt&eacute; par des douzaines de
+ fabricants d'imprimantes et de serveurs d'impression et est pris en
+ charge par Microsoft Windows 2000.</P>
+<P> IPP d&eacute;finit un protocole standard pour imprimer ainsi qu'administrer
+ les travaux d'impression et les options des imprimantes telles que la
+ taille du support d'impression, la r&eacute;solution, etc. Comme tout
+ protocole de la pile TCP/IP, IPP peut &ecirc;tre utilis&eacute; localement ou &agrave;
+ travers Internet pour atteindre des imprimantes &eacute;loign&eacute;es de centaines
+ ou de milliers de kilom&egrave;tres. Contrairement &agrave; d'autres protocoles de la
+ pile TCP/IP, IPP prend en charge le contr&ocirc;le d'acc&egrave;s,
+ l'authentification et l'encryptage, ce qui fait de lui une solution
+ d'impression bien plus efficace et s&eacute;curis&eacute;e que ses anc&ecirc;tres.</P>
+<P> IPP est une surcouche ajout&eacute;e au-dessus du protocole HTTP (HyperText
+ Transport Protocol) qui est &agrave; la base des serveurs &quot;web&quot; sur
+ l'Internet. Ceci permet aux utilisateurs de lire la documentation,
+ v&eacute;rifier les informations sur l'&eacute;tat des imprimantes ou du serveur,
+ administrer les imprimantes, les classes d'imprimantes et les travaux
+ d'impression en utilisant leur navigateur &quot;web&quot;.</P>
+<P> CUPS fournit un syst&egrave;me d'impression complet bas&eacute; sur IPP/1.1
+ prenant en charge l'authentification &quot;Basic&quot;, &quot;Digest&quot; et par
+ certificats locaux ainsi qu'un contr&ocirc;le d'acc&egrave;s bas&eacute; sur l'utilisateur,
+ le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une
+ future version de CUPS.</P>
+<H2><A NAME="2_3">Travaux d'impression</A></H2>
+<P> Tout fichier ou groupe de fichiers soumis &agrave; l'impression est appel&eacute;
+ un<I> travail d'impression</I>. Les travaux d'impression sont
+ identifi&eacute;s par un nombre unique en commen&ccedil;ant &agrave; 1 et sont affect&eacute;s &agrave;
+ une destination particuli&egrave;re, g&eacute;n&eacute;ralement une imprimante. Les travaux
+ d'impression peuvent &eacute;galement inclure des options associ&eacute;es telles que
+ la taille du support d'impression, le nombre de copies et la priorit&eacute;
+ dans la file d'impression.</P>
+<H2><A NAME="2_4">Classes d'imprimantes</A></H2>
+<P> CUPS prend en charge des collections d'imprimantes connues sous le
+ nom de<I> classes</I>. Les travaux d'impression transmis &agrave; une classe
+ d'imprimantes sont envoy&eacute;s &agrave; la premi&egrave;re imprimante disponible dans la
+ classe.</P>
+<H2><A NAME="2_5">Filtres</A></H2>
+<P>Les filtres permettent &agrave; un utilisateur ou une application d'imprimer
+ de nombreux types de documents sans effort suppl&eacute;mentaire. Les travaux
+ d'impressions envoy&eacute;s au serveur CUPS sont filtr&eacute;s avant d'&ecirc;tre envoy&eacute;s
+ &agrave; l'imprimante. Certains filtres convertissent les fichiers de travaux
+ d'impression dans diff&eacute;rents formats que l'imprimante peut comprendre.
+ D'autres ne font que des s&eacute;lections de page et des tris.</P>
+<P>CUPS fournit des filtres pour imprimer de nombreux types de fichiers
+ image, des fichier HP-GL/2, fichiers PDF et texte. CUPS fournit
+ &eacute;galement des filtres PostScript et RIP (Raster Image Processor) qui
+ convertissent les fichiers PostScript ou image en format &quot;bitmap&quot; qui
+ peut &ecirc;tre envoy&eacute; &agrave; une imprimante de type &quot;matriciel&quot; (NdT : il s'agit
+ ici, des imprimantes dont l'impression est g&eacute;n&eacute;r&eacute;e au moyen d'une
+ grille de points comme l'&eacute;taient les v&eacute;n&eacute;rables imprimantes &agrave; aiguilles
+ de notre enfance, mais pas seulement elles puisque les imprimantes &agrave;
+ jet d'encre actuelles sont &eacute;galement de type matriciel... par
+ opposition aux imprimantes laser dont la m&eacute;thode de g&eacute;n&eacute;ration
+ d'impression est diff&eacute;rente.)</P>
+<H2><A NAME="2_6">Programmes d'arri&egrave;re-plan (Backends)</A></H2>
+<P>Les programmes d'arri&egrave;re-plan effectuent le travail le plus important
+ : ils envoient les donn&eacute;es d'impression &agrave; l'imprimante.</P>
+<P>CUPS fournit des programmes d'arri&egrave;re-plan pour imprimer via des
+ ports de type parall&egrave;le, s&eacute;rie, USB et &agrave; travers un r&eacute;seau au moyen des
+ protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des
+ programmes d'arri&egrave;re-plan additionnels sont disponibles sous forme de
+ paquetage de service r&eacute;seau comme le programme d'arri&egrave;re_plan SMB
+ inclus dans le c&eacute;l&egrave;bre logiciel SAMBA.</P>
+<P>Les programmes d'arri&egrave;re-plan sont &eacute;galement utilis&eacute;s pour d&eacute;terminer
+ les p&eacute;riph&eacute;riques disponibles. Au d&eacute;marrage, chaque programme
+ d'arri&egrave;re-plan est interrog&eacute; afin de d&eacute;terminer la liste des
+ p&eacute;riph&eacute;riques qu'il prend en charge, ainsi que toute information
+ disponible. Cela permet au programme d'arri&egrave;re-plan de gestion du port
+ parall&egrave;re d'indiquer &agrave; CUPS qu'une imprimante EPSON Stylus Color 600
+ est branch&eacute;e sur le port parall&egrave;le 1, par exemple.</P>
+<H2><A NAME="2_7">Pilotes d'imprimantes</A></H2>
+<P>Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs
+ filtres sp&eacute;cifiques &agrave; une imprimante. CUPS inclut des pilotes
+ d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet
+ Hewlett-Packard et les imprimantes EPSON jet d'encre couleur Stylus
+ Color, Stylus Photo et les mod&egrave;les 9 et 24 aiguilles matricielles. Bien
+ que ces pilotes ne produisent pas des impressions de qualit&eacute; optimale
+ pour les diff&eacute;rents mod&egrave;les d'imprimantes, ils fournissent une
+ impression de base et d&eacute;montrent comment vous pouvez &eacute;crire vos propres
+ pilotes d'imprimantes et les incorporer dans CUPS.</P>
+<H2><A NAME="2_8">R&eacute;seau</A></H2>
+<P>Les imprimantes et classes d'imprimantes sur le syst&egrave;me local sont
+ automatiquement partag&eacute;es avec les autres syst&egrave;mes sur le r&eacute;seau. Cela
+ vous permet de configurer un syst&egrave;me h&ocirc;te pour tous les autres. Les
+ utilisateurs pourront s&eacute;lectionner une imprimante locale par son nom ou
+ une imprimante &agrave; distance en utilisant la syntaxe
+ &quot;nom_imprimante@serveur&quot;.</P>
+<P>CUPS fournit &eacute;galement des<I> classes d'imprimantes implicites</I>
+ (NdT : le terme &quot;implicite&quot; est ici la traduction lit&eacute;rale du m&ecirc;me mot
+ anglais &quot;implicit&quot; et non celle de l'expression &quot;default&quot;. cf. ma
+ remarque dans la pr&eacute;face du pr&eacute;sent manuel. De toute fa&ccedil;on, CUPS ne
+ pr&eacute;voit pas de &quot;default class&quot; c'est-&agrave;-dire de &quot;classe de base&quot;, donc
+ aucune ambigu&iuml;t&eacute; possible ici.), qui sont des collections d'imprimantes
+ ou de classes d'imprimantes qui portent le m&ecirc;me nom. Cela vous permet
+ de configurer de multiples serveurs pointant vers la m&ecirc;me imprimante
+ r&eacute;seau physique, par exemple, de sorte que vous ne d&eacute;pendez pas d'un
+ seul serveur pour pouvoir imprimer. Etant donn&eacute; que cette m&eacute;thode vous
+ permet de travailler avec des classes d'imprimantes, vous pouvez
+ configurer de multiples serveurs et imprimantes sans jamais vous
+ soucier d'un simple point en panne tant que tous les autres serveurs ne
+ tombent pas en panne en m&ecirc;me temps.</P>
+<H1 ALIGN="RIGHT"><A NAME="USING_SYSTEM">2 - Utilisation du syst&egrave;me
+ d'impression</A></H1>
+<P>Ce chapitre expose comment soumettre, lister et annuler les travaux
+ d'impression sur diff&eacute;rentes imprimantes.</P>
+<H2><A NAME="3_1">Soumission de travaux &agrave; l'impression</A></H2>
+<P>CUPS fournit les deux commandes d'impression System V (<CODE>lp(1)</CODE>
+) et Berkeley ( <CODE>lpr(1)</CODE>). Tapez la commande suivante pour
+ imprimer un fichier sur l'imprimante implicite du syst&egrave;me:</P>
+<UL>
+<PRE>
+<B>lp nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>ou:</P>
+<UL>
+<PRE>
+<B>lpr nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>CUPS sait directement interpr&eacute;ter diff&eacute;rents types de fichier, y
+ compris les fichiers PostScript et image. Cela vous permet d'imprimer
+ depuis vos applications ou depuis la ligne de commande, selon votre
+ pr&eacute;f&eacute;rence!</P>
+<H2><A NAME="3_2">Choix d'une imprimante</A></H2>
+<P>Beaucoup de syst&egrave;mes disposeront de plusieurs imprimantes &agrave; offrir &agrave;
+ l'utilisateur. Ces imprimantes peuvent &ecirc;tre reli&eacute;es au syst&egrave;me local
+ par un port parall&egrave;le, s&eacute;rie ou USB, ou accessibles &agrave; travers le
+ r&eacute;seau.</P>
+<P>Utilisez la commande <CODE>lpstat(1)</CODE> pour voir une liste des
+ imprimantes disponibles:</P>
+<UL>
+<PRE>
+<B>lpstat -p -d ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-p</CODE> indique que vous voulez voir la liste des
+ imprimantes et l'option <CODE>-d</CODE> provoque l'affichage de
+ l'imprimante ou classe d'imprimantes standard (implicite) du syst&egrave;me.</P>
+<P>Utilisez l'option <CODE>-d</CODE> avec la comamnde <CODE>lp</CODE>
+ pour imprimer vers une imprimante sp&eacute;cifique:</P>
+<UL>
+<PRE>
+<B>lp -d imprimante nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>ou l'option <CODE>-P</CODE> avec la commande <CODE>lpr</CODE>:</P>
+<UL>
+<PRE>
+<B>lpr -P imprimante nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="3_3">R&eacute;glage des options d'imprimante</A></H2>
+<P>Pour de nombreux types de fichiers, les options d'imprimante
+ implicites devraient satisfaire vos besoins. Cependant, il peut arriver
+ que vous ayez besoin de changer les options pour un fichier sp&eacute;cifique
+ que vous imprimez.</P>
+<P>Les commandes <CODE>lp</CODE> et <CODE>lpr</CODE> vous permettent de
+ passer des options d'imprimante en utilisant l'option <CODE>-o</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
+<B>lpr -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
+</B></B></PRE>
+</UL>
+<P>Les options d'imprimante disponibles varient en fonction de
+ l'imprimante. Les options standards sont d&eacute;crites dans le <A HREF="#STANDARD_OPTIONS">
+ Chapitre 3, &quot;Options standards d'imprimante&quot;</A>.</P>
+<H2><A NAME="3_4">Impression de plusieurs copies</A></H2>
+<P>Les deux commandes <CODE>lp</CODE> et <CODE>lpr</CODE> poss&egrave;dent des
+ options pour l'impression de plus d'une copie d'un fichier:</P>
+<UL>
+<PRE>
+<B>lp -n <I>nombre_copies</I> nom_fichier ENTREE</B>
+<B>lpr -#<I>nombre_copies</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les copies ne sont g&eacute;n&eacute;ralement<I> pas</I> assembl&eacute;es. Utilisez
+ l'option <CODE>-o Collate=True</CODE> pour obtenir des copies
+ assembl&eacute;es:</P>
+<UL>
+<PRE>
+<B>lp -n <I>nombre_copies</I> -o Collate=True nom_fichier ENTREE</B>
+<B>lpr -#<I>nombre_copies</I> -o Collate=True nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H2><A NAME="3_5">V&eacute;rification de l'&eacute;tat d'une imprimante depuis la
+ ligne de commande</A></H2>
+<P>La commande <CODE>lpstat</CODE> peut &ecirc;tre utilis&eacute;e pour v&eacute;rifier les
+ travaux que vous avez soumis &agrave; l'impression:</P>
+<UL>
+<PRE>
+<B>lpstat ENTREE</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+</PRE>
+</UL>
+<P>Les travaux sont list&eacute;s dans l'ordre dans lequel ils seront imprim&eacute;s.
+ Utilisez l'option <CODE>-p</CODE> pour voir les travaux actifs sur
+ l'imprimante:</P>
+<UL>
+<PRE>
+<B>lpstat -p ENTREE</B>
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Utilisez les options <CODE>-o</CODE> et <CODE>-p</CODE> ensemble pout
+ voir les &agrave; la fois les travaux et les imprimantes:</P>
+<UL>
+<PRE>
+<B>lpstat -o -p ENTREE</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+<H2><A NAME="3_6">V&eacute;rification de l'&eacute;tat d'un imprimante depuis
+ l'interface &quot;web&quot;</A></H2>
+<P>CUPS utilise le protocole IPP (Internet Printing Protocol), mais
+ c'est &eacute;galement un serveur &quot;web&quot; compl&egrave;tement fonctionnel. Pour
+ utiliser votre navigateur &quot;web&quot; pour surveiller les imprimantes sur
+ votre syst&egrave;me, ouvrez l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631">http://localhost:631</A>
+</PRE>
+</UL>
+<P>A partir de l&agrave;, vous pouvez voir l'&eacute;tat des classes, travaux, et
+ imprimantes par un simple clic de bouton!</P>
+<H2><A NAME="3_7">Suppression d'un travail d'impression</A></H2>
+<P>Les commandes <CODE>cancel(1)</CODE> et <CODE>lprm(1)</CODE>
+ suppriment un travail d'impression:</P>
+<UL>
+<PRE>
+<B>cancel <I>num&eacute;ro_travail</I> ENTREE</B>
+<B>lprm <I>num&eacute;ro_travail</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Le <CODE>num&eacute;ro_travail</CODE> est le nombre qui vous est fourni par
+ les commandes <CODE>lp</CODE> ou <CODE>lpstat</CODE>.</P>
+<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Options standards
+ d'imrimante</A></H1>
+<P>Ce chapitre d&eacute;crit les options standards d'imprimante qui sont
+ disponibles lors de l'impression au moyen des commandes <CODE>lp</CODE>
+ et <CODE>lpr</CODE>.</P>
+<H2><A NAME="4_1">Options g&eacute;n&eacute;rales</A></H2>
+<P>Les options suivantes s'appliquent lors de l'impression de tous les
+ types de fichiers.</P>
+<H3><A NAME="4_1_1">R&eacute;glage de l'orientation</A></H3>
+<P>L'option <CODE>-o landscape</CODE> tournera la sortie imprim&eacute;e de 90&deg;
+ pour imprimer en mode paysage:</P>
+<UL>
+<PRE>
+<B>lp -o landscape nom_fichier ENTREE</B>
+<B>lpr -o landscape nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H3><A NAME="4_1_2">Choix du type, de la taille et de la source du
+ support d'impression</A></H3>
+<P>L'option <CODE>-o media=xyz</CODE> d&eacute;finit la taille, le type et la
+ source du support d'impression:</P>
+<UL>
+<PRE>
+<B>lp -o media=Letter nom_fichier ENTREE</B>
+<B>lp -o media=Letter,MultiPurpose nom_fichier ENTREE</B>
+<B>lpr -o media=Letter,Transparency nom_fichier ENTREE</B>
+<B>lpr -o media=Letter,MultiPurpose,Transparency nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>Les tailles, types et sources de support d'impression disponibles
+ d&eacute;pendent de l'imprimante mais la plupart des mat&eacute;riels prennent en
+ charge les options suivantes (les plus courantes):</P>
+<UL>
+<LI><CODE>Letter</CODE> - US Letter (8.5x11 pouces, ou 216x279mm)</LI>
+<LI><CODE>Legal</CODE> - US Legal (8.5x14 pouces, ou 216x356mm)</LI>
+<LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 pouces, ou 210x297mm)</LI>
+<LI><CODE>COM10</CODE> - US #10 Enveloppe (9.5x4.125 pouces, ou
+ 241x105mm)</LI>
+<LI><CODE>DL</CODE> - ISO DL Enveloppe (8.66x4.33 pouces, ou 220x110mm)</LI>
+<LI><CODE>Transparency</CODE> - Type de support transparent ou source de
+ support transparent</LI>
+<LI><CODE>Upper</CODE> - Bac d'alimentation sup&eacute;rieur</LI>
+<LI><CODE>Lower</CODE> - Bac d'alimentation inf&eacute;rieur</LI>
+<LI><CODE>MultiPurpose</CODE> - Bac papier multi-usage</LI>
+<LI><CODE>LargeCapacity</CODE> - Bac d'alimentation de grande capacit&eacute;</LI>
+</UL>
+<P>Les options r&eacute;ellement prises en charge sont d&eacute;finies dans le fichier
+ PPD de l'imprimante au moyen des options <CODE>PageSize</CODE>, <CODE>
+InputSlot</CODE>, et <CODE>MediaType</CODE>.</P>
+<H3><A NAME="4_1_3">Impression en recto/verso</A></H3>
+<P>Les options <CODE>-o sides=two-sided-short-edge</CODE> et <CODE>-o
+ sides=two-sided-long-edge</CODE> activeront l'impression recto/verso si
+ l'imprimante la prend en charge. L'option <CODE>-o
+ sides=two-sided-short-edge</CODE> convient pour les pages orient&eacute;es en
+ paysage, tandis que l'option <CODE>-o sides=two-sided-long-edge</CODE>
+ convient pour celles orient&eacute;es en portrait:</P>
+<UL>
+<PRE>
+<B>lp -o sides=two-sided-short-edge nom_fichier ENTREE</B>
+<B>lp -o sides=two-sided-long-edge nom_fichier ENTREE</B>
+<B>lpr -o sides=two-sided-long-edge nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est d'imprimer en mode simple face
+ (&quot;single-sided&quot;):</P>
+<UL>
+<PRE>
+<B>lp -o sides=one-sided nom_fichier ENTREE</B>
+<B>lpr -o sides=one-sided nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="4_2">Options de pages de garde</A></H2>
+<P>Les options suivantes s'appliquent &agrave; l'impression de tous les types
+ de fichiers.</P>
+<H3><A NAME="4_2_1">S&eacute;lection des pages de garde</A></H3>
+<P>L'option <CODE>-o jobsheets=start,end</CODE> d&eacute;finit les pages de
+ garde pour un travail d'impression:</P>
+<UL>
+<PRE>
+<B>lp -o job-sheets=none nom_fichier ENTREE</B>
+<B>lp -o job-sheets=standard nom_fichier ENTREE</B>
+<B>lpr -o job-sheets=classified,classified nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Si seulement un fichier de page de garde est indiqu&eacute; il sera imprim&eacute;
+ avant le travail d'impression. Si un second fichier de page de garde
+ est indiqu&eacute;, il sera imprim&eacute; apr&egrave;s le travail d'impression..</P>
+<P>Les pages de garde disponibles d&eacute;pendent de la configuration du
+ syst&egrave;me local; CUPS inclut les fichiers de pages de garde suivants:</P>
+<UL>
+<LI><CODE>none</CODE> - Ne pas produire de page de garde.</LI>
+<LI><CODE>classified</CODE> - Une page de garde avec une inscription
+ &quot;classified&quot; en haut et en bas de page.</LI>
+<LI><CODE>confidential</CODE> - Une page de garde avec une inscription
+ &quot;confidential&quot; en haut et en bas de page.</LI>
+<LI><CODE>secret</CODE> - Une page de garde avec une inscription
+ &quot;secret&quot; en haut et en bas de page.</LI>
+<LI><CODE>standard</CODE> - Une page de garde sans inscription en haut
+ et en bas de page.</LI>
+<LI><CODE>topsecret</CODE> - Une page de garde avec une inscription
+ &quot;top-secret&quot; en haut et en bas de page.</LI>
+<LI><CODE>unclassified</CODE> - Une page de garde avec une inscription
+ &quot;unclassified&quot; en haut et en bas de page.</LI>
+</UL>
+<H2><A NAME="4_3">Options de document</A></H2>
+<P>Les options suivantes s'appliquent &agrave; l'impression de tous les types
+ de fichiers.</P>
+<H3><A NAME="4_3_1">S&eacute;lection d'une s&eacute;rie de pages</A></H3>
+<P>L'option <CODE>-o page-ranges=pages</CODE> s&eacute;lectionne une s&eacute;rie de
+ pages &agrave; imprimer:</P>
+<UL>
+<PRE>
+<B>lp -o page-ranges=1 nom_fichier ENTREE</B>
+<B>lp -o page-ranges=1-4 nom_fichier ENTREE</B>
+<B>lp -o page-ranges=1-4,7,9-12 nom_fichier ENTREE</B>
+<B>lpr -o page-ranges=1-4,7,9-12 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Comme indiqu&eacute; ci-dessus, la valeur <CODE>pages</CODE> peut &ecirc;tre une
+ page unique, un intervalle de num&eacute;ros de pages ou une collections de
+ num&eacute;ros de pages et d'intervalles s&eacute;par&eacute;s par des virgules. Les pages
+ seront imprim&eacute;es dans l'ordre croissant de leurs num&eacute;ros, sans tenir
+ compte de l'ordre dans lequel les valeurs ont &eacute;t&eacute; tap&eacute;es dans l'option <CODE>
+page-ranges</CODE>.</P>
+<P>Le comportement implicite est d'imprimer toutes les pages.</P>
+<H3><A NAME="4_3_2">S&eacute;lection des pages paires et impaires</A></H3>
+<P>Utilisez l'option <CODE>-o page-set=set</CODE> pour s&eacute;lectionner les
+ pages paires ou impaires:</P>
+<UL>
+<PRE>
+<B>lp -o page-set=odd nom_fichier ENTREE</B>
+<B>lp -o page-set=even nom_fichier ENTREE</B>
+<B>lpr -o page-set=even nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le comportement implicite est d'imprimer toutes les pages.</P>
+<H3><A NAME="4_3_3">Impression de plusieurs pages par face du support
+ (&quot;N-Up Printing&quot;)</A></H3>
+<P>L'option <CODE>-o number-up=value</CODE> s&eacute;lectionne l'impression de
+ plusieurs pages par face du support. Cela permet d'imprimer 1, 2 ou 4
+ pages du document d'origine sur une seule page physique en sortie:</P>
+<UL>
+<PRE>
+<B>lp -o number-up=1 nom_fichier ENTREE</B>
+<B>lp -o number-up=2 nom_fichier ENTREE</B>
+<B>lp -o number-up=4 nom_fichier ENTREE</B>
+<B>lpr -o number-up=4 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est 1.</P>
+<H3><A NAME="4_3_4">R&eacute;glage de la luminosit&eacute;</A></H3>
+<P>Vous pouvez contr&ocirc;ler la luminosit&eacute; globale de la sortie imprim&eacute;e en
+ utilisant l'option <CODE>-o brightness=percent</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o brightness=120 nom_fichier ENTREE</B>
+<B>lpr -o brightness=120 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les valeurs sup&eacute;rieures &agrave; 100 &eacute;claircissent l'impression, tandis que
+ les valeurs inf&eacute;rieures &agrave; 100 l'assombrissent.</P>
+<H3><A NAME="4_3_5">R&eacute;glage de la correction Gamma</A></H3>
+<P>Vous pouvez contr&ocirc;ler la correction gamma goblale de la sortie
+ imprim&eacute;e en utilsiant l'option <CODE>-o gamma=value</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o gamma=1700 nom_fichier ENTREE</B>
+<B>lpr -o gamma=1700 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les valeurs sup&eacute;rieures &agrave; 1000 &eacute;claircissent l'impression, tandis que
+ les valeurs inf&eacute;rieures &agrave; 1000 l'assombrissent. La valeur implicite est
+ 1000.</P>
+<H2><A NAME="4_4">Options de texte</A></H2>
+<P>Les options suivantes s'appliquent &agrave; l'impression de fichier texte.</P>
+<H3><A NAME="4_4_1">R&eacute;glage du nombre de caract&egrave;res par pouce</A></H3>
+<P>L'option <CODE>-o cpi=value</CODE> d&eacute;finit le nombre de caract&egrave;res
+ par pouce<I> (NdT : 1 pouce = 2,54 cm)</I>:</P>
+<UL>
+<PRE>
+<B>lp -o cpi=10 nom_fichier ENTREE</B>
+<B>lp -o cpi=12 nom_fichier ENTREE</B>
+<B>lpr -o cpi=17 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre implicite de caract&egrave;res par pouce est 10.</P>
+<H3><A NAME="4_4_2">R&eacute;glage du nombre de lignes par pouce</A></H3>
+<P>L'option <CODE>-o lpi=value</CODE> d&eacute;finit le nombre de lignes par
+ pouce:</P>
+<UL>
+<PRE>
+<B>lp -o lpi=6 nom_fichier ENTREE</B>
+<B>lpr -o lpi=8 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre implicite de lignes par pouces est 6.</P>
+<H3><A NAME="4_4_3">R&eacute;glage du nombre de colonnes</A></H3>
+<P>L'option <CODE>-o columns=value</CODE> d&eacute;finit le nombre de colonnes
+ de texte:</P>
+<UL>
+<PRE>
+<B>lp -o columns=2 nom_fichier ENTREE</B>
+<B>lpr -o columns=3 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre de colonnes implicite est 1.</P>
+<H3><A NAME="4_4_4">R&eacute;glage des marges de la page</A></H3>
+<P>Normalement, les marges de la page sont fix&eacute;es par les limites
+ physiques de l'imprimante. Utilisez les options <CODE>-o
+ page-left=value</CODE>, <CODE>-o page-right=value</CODE> , <CODE>-o
+ page-top=value</CODE>, et <CODE>-o page-bottom=value</CODE> pour
+ ajuster les marges:</P>
+<UL>
+<PRE>
+<B>lp -o page-left=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-right=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-top=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-bottom=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lpr -o page-bottom=<I>valeur</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'argument <CODE>valeur</CODE> est la marge en points; 1 point =
+ 1/72&egrave;me de pouce = 0.35mm.</P>
+<H3><A NAME="4_4_5">Impression am&eacute;lior&eacute;e</A></H3>
+<P>L'option <CODE>-o prettyprint</CODE> ajoute un en-t&ecirc;te en haut de
+ chaque page. Celui-ci comporte le num&eacute;ro de page, le titre du travail
+ d'impression (habituellement le nom du fichier), et la date. Les mots
+ clefs C, C++ et les lignes de commentaires sont &eacute;galement repr&eacute;sent&eacute;es
+ en italique:</P>
+<UL>
+<PRE>
+<B>lp -o prettyprint nom_fichier ENTREE</B>
+<B>lpr -o prettyprint nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="4_5">Options d'image</A></H2>
+<P>Les options suivantes s'appliquent lors de l'impression de fichiers
+ image.</P>
+<H3><A NAME="4_5_1">Positionnement de l'image</A></H3>
+<P>L'option <CODE>-o position=name</CODE> indique la position de l'image
+ dans la page:</P>
+<UL>
+<LI><CODE>center</CODE> - Centre l'image dans la page (valeur implicite)</LI>
+<LI><CODE>top</CODE> - Imprime l'image cal&eacute;e en haut de la page et
+ centr&eacute;e en largeur</LI>
+<LI><CODE>left</CODE> - Imprime l'image cal&eacute;e &agrave; gauche de la page et
+ centr&eacute;e en hauteur</LI>
+<LI><CODE>right</CODE> - Imprime l'image cal&eacute;e &agrave; droite de la page et
+ centr&eacute;e en hauteur</LI>
+<LI><CODE>top-left</CODE> - Imprime l'image cal&eacute;e dans le coin sup&eacute;rieur
+ gauche</LI>
+<LI><CODE>top-right</CODE> - Imprime l'image cal&eacute;e dans le coin
+ sup&eacute;rieur droit</LI>
+<LI><CODE>bottom</CODE> - Imprime l'image cal&eacute;e en bas de la page et
+ centr&eacute;e en largeur</LI>
+<LI><CODE>bottom-left</CODE> - Imprime l'image cal&eacute;e dans le coin
+ inf&eacute;rieur gauche</LI>
+<LI><CODE>bottom-right</CODE> - Imprime l'image cal&eacute;e dans le coin
+ inf&eacute;rieur droit</LI>
+</UL>
+<H3><A NAME="4_5_2">Mise &agrave; l'&eacute;chelle de l'image</A></H3>
+<P>Les options <CODE>-o scaling=percent</CODE>, <CODE>-o ppi=value</CODE>
+, et <CODE>-o natural-scaling=percent</CODE> changent la taille de
+ l'image imprim&eacute;e:</P>
+<UL>
+<PRE>
+<B>lp -o scaling=<I>percent</I> nom_fichier ENTREE</B>
+<B>lp -o ppi=<I>value</I> nom_fichier ENTREE</B>
+<B>lpr -o natural-scaling=<I>percent</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur <CODE>scaling=percent</CODE> est un nombre compris entre 1
+ et 800 indiquant la taille par rapport celle de la page (<I>pas celle
+ de l'image</I>). Un valeur de 100% va adapter l'image &agrave; la taille
+ maximale que permet la page (en fonction des contraintes impos&eacute;es par
+ le rapport hauteur/largeur de l'image). Une valeur de 200% imprimera
+ l'image r&eacute;partie sur 4 pages.</P>
+<P>La valeur <CODE>ppi=value</CODE> est un nombre compris entre 1 et
+ 1200 indiquant la r&eacute;solution de l'image en pixels par pouce. Une image
+ qui mesure 3000x2400 pixels s'imprimera sur le papier en 10x8 pouces &agrave;
+ une r&eacute;solution de 300 pixels par pouce (ppp ou, en anglais, dpi). Si la
+ r&eacute;solution indiqu&eacute;e donne une image plus grande que la page, plusieurs
+ pages sont imprim&eacute;es pour satisfaire la requ&ecirc;te.</P>
+<P>La valeur <CODE>natural-scaling=percent</CODE> est un nombre compris
+ entre 1 et 800 indiquant la taille d'impression de l'image relativement
+ &agrave; sa taille d'origine. Une valeur de 100% imprimera l'image dans sa
+ taille normale, tandis qu'une valeur de 50% donnera une taille moiti&eacute;
+ moins grande. Si la valeur indiqu&eacute;e donne une image plus grande que la
+ page, plusieurs pages sont imprim&eacute;es pour satisfaire la requ&ecirc;te.</P>
+<H3><A NAME="4_5_3">Ajustement de la teinte (&quot;Hue&quot;, &quot;Tint&quot;) de l'image</A>
+</H3>
+<P>La valeur <CODE>-o hue=value</CODE> ajustera la teinte (&quot;hue&quot;) de
+ l'image imprim&eacute;e, comme le r&eacute;glage de teinte de votre t&eacute;l&eacute;vision:</P>
+<UL>
+<PRE>
+<B>lp -o hue=<I>value</I> nom_fichier ENTREE</B>
+<B>lpr -o hue=<I>value</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>L'argument <CODE>value</CODE> est un nombre compris entre -360 et 360
+ repr&eacute;sentant une rotation de teinte. Le tableau suivant, r&eacute;sume les
+ changements que vous verrez avec diff&eacute;rentes couleurs:
+<CENTER>
+<TABLE BORDER="1" WIDTH="50%">
+<TR><TH>Original</TH><TH>hue=-45</TH><TH>hue=45</TH></TR>
+<TR><TD>Rouge</TD><TD>Pourpre</TD><TD>Jaune-orange</TD></TR>
+<TR><TD>Vert</TD><TD>Jaune-vert</TD><TD>Bleu-vert</TD></TR>
+<TR><TD>Jaune</TD><TD>Orange</TD><TD>Vert-Jaune</TD></TR>
+<TR><TD>Bleu</TD><TD>Bleu ciel</TD><TD>Pourpre</TD></TR>
+<TR><TD>Magenta</TD><TD>Indigo</TD><TD>Rouge cramoisi</TD></TR>
+<TR><TD>Cyan</TD><TD>Bleu-vert</TD><TD>Blue marine clair</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La valeur implicite de ce param&egrave;tre est 0.</P>
+<H3><A NAME="4_5_4">Ajustement de la saturation de couleur de l'image</A>
+</H3>
+<P>L'option <CODE>-o saturation=percent</CODE> ajuste la saturation des
+ couleurs de l'image, comme le bouton &quot;couleur&quot; de votre t&eacute;l&eacute;vision:</P>
+<UL>
+<PRE>
+<B>lp -o saturation=<I>percent</I> nom_fichier ENTREE</B>
+<B>lpr -o saturation=<I>percent</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'argument <CODE>percent</CODE> indique la saturation de couleur de 0
+ &agrave; 200. Une saturation de 0 produit une image en noir et blanc, tandis
+ qu'une valeur de 200 rend les couleurs extr&ecirc;mement intenses.</P>
+<P>La saturation implicite est de 100.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="4_6">Options HP-GL/2</A></H2>
+<P>Les options suivantes s'appliquent aux fichiers HP-GL/2.</P>
+<H3><A NAME="4_6_1">Impression en noir</A></H3>
+<P>L'option <CODE>-o blackplot</CODE> indique que tous les &quot;stylos&quot;
+ doivent &eacute;crire en noir:</P>
+<UL>
+<PRE>
+<B>lp -o blackplot nom_fichier ENTREE</B>
+<B>lpr -o blackplot nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est d'utiliser les couleurs d&eacute;finies dans le
+ fichier ou les couleurs standards de &quot;stylos&quot; d&eacute;finies dans le manuel
+ de r&eacute;f&eacute;rence HP-GL/2.</P>
+<H3><A NAME="4_6_2">Ajuster le trac&eacute; &agrave; la page</A></H3>
+<P>L'option <CODE>-o fitplot</CODE> indique que le trac&eacute; doit &ecirc;tre mis &agrave;
+ l'&eacute;chelle pour tenir sur la page:</P>
+<UL>
+<PRE>
+<B>lp -o fitplot nom_fichier ENTREE</B>
+<B>lpr -o fitplot nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le comportement implicite est d'utiliser les distances absolues
+ d&eacute;finies dans le fichier.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Cette fonctionnalit&eacute; d&eacute;pend d'une d&eacute;finition pr&eacute;cise de la commande
+ de taille de trac&eacute; (<CODE>PS</CODE>) dans le fichier HP-GL/2. Si aucune
+ taille de trac&eacute; n'est donn&eacute;e dans le fichier, alors le filtre HP-GL/2
+ consid&egrave;re que le trac&eacute; a une taille ANSI E.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_6_3">R&eacute;glage de la largeur implicite de trac&eacute;</A></H3>
+<P>L'option <CODE>-o penwidth=valeur</CODE> indique la valeur implicite
+ de largeur de trac&eacute; pour les fichiers HP-GL/2:</P>
+<UL>
+<PRE>
+<B>lp -o penwidth=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lpr -o penwidth=<I>valeur</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La <CODE>valeur</CODE> de largeur de trac&eacute; d&eacute;finit la largeur de
+ &quot;stylo&quot; en microm&egrave;tres. La valeur implicite de 1000 produit des lignes
+ de 1 millim&egrave;tre de large. Indiquer une largeur de &quot;stylo&quot; de 0 produit
+ un trac&eacute; d'un pixel de large.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Cette option est ignor&eacute;e si les largeurs de trac&eacute; sont d&eacute;finies dans
+ le fichier.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_7">Sortie brute ou non filtr&eacute;e</A></H2>
+<P>L'option <CODE>-o raw</CODE> vous permet d'envoyer directement des
+ fichiers &agrave; l'imprimante sans faire de filtrage. Cela est parfois
+ n&eacute;cessaire lors que vous imprimez depuis des applications qui
+ fournissent leur propres &quot;pilotes d'imprimantes&quot; pour votre imprimante:</P>
+<UL>
+<PRE>
+<B>lp -o raw nom_fichier ENTREE</B>
+<B>lpr -o raw nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-l</CODE> peut &eacute;galement &ecirc;tre utilis&eacute;e avec la
+ commande <CODE>lpr</CODE> pour envoyer directement des fichiers &agrave; une
+ imprimante:</P>
+<UL>
+<PRE>
+<B>lpr -l nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Sauvegarder les options
+ et valeurs implicites des r&eacute;glages d'imprimante</A></H1>
+<P>Ce chapitre d&eacute;crit comment sauvegarder les options pour votre
+ imprimante et d&eacute;finir votre propre imprimante implicite.</P>
+<H2><A NAME="5_1">Options d'imprimante</A></H2>
+<P>Chaque imprimante prend en charge un grand nombre d'options, que vous
+ avez d&eacute;couvertes dans le <A HREF="#STANDARD_OPTIONS"> Chapitre 3,
+ &quot;Options standards d'imprimante&quot;</A>. Plut&ocirc;t qu'indiquer ces options &agrave;
+ chaque fois que vous imprimez un fichier, CUPS vous permet de
+ sauvegarder comme &quot;implicites&quot; les options pour votre imprimante.</P>
+<P>La commande <CODE>lpoptions(1)</CODE> sauvegarde les options de vos
+ imprimantes. Comme les commandes <CODE>lp</CODE> et <CODE>lpr</CODE>,
+ elle accepte les options d'imprimantes en utilisant l'argument <CODE>-o</CODE>
+:</P>
+<UL>
+<PRE>
+<B>lpoptions -o media=A4 -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -o media=Legal -o scaling=100 ENTREE</B>
+</PRE>
+</UL>
+<P>Une fois sauvegard&eacute;es, toute commande <CODE>lp</CODE> ou <CODE>lpr</CODE>
+ les utilisera lorsque vous imprimerez.</P>
+<H2><A NAME="5_2">R&eacute;glage des options pour une imprimante sp&eacute;cifique</A></H2>
+<P>L'exemple pr&eacute;c&eacute;dent montre comment r&eacute;gler les options pour
+ l'imprimante implicite. L'option <CODE>-p imprimante</CODE> indique que
+ les options sont pour une autre imprimante:</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -p deskjet -o media=Legal -o scaling=100 ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Visualisation des r&eacute;glages implicites actuels</A></H2>
+<P>La commande <CODE>lpoptions</CODE> peut &eacute;galement &ecirc;tre utilis&eacute;e pour
+ afficher les options actuelles en n'indiquant aucune option sur la
+ ligne de commande:</P>
+<UL>
+<PRE>
+<B>lpoptions ENTREE</B>
+media=A4 sides=two-sided-long-edge
+<B>lpoptions -p deskjet ENTREE</B>
+media=Legal scaling=100
+</PRE>
+</UL>
+<H2><A NAME="5_4">Choix de l'imprimante implicite</A></H2>
+<P>L'administrateur d&eacute;finira g&eacute;n&eacute;ralement une imprimante implicite
+ valable pour tout le syst&egrave;me et qui sera utilis&eacute;e par tous. Utilisez
+ l'option <CODE>-d imprimante</CODE> pour d&eacute;finir votre propre
+ imprimante implicite:</P>
+<UL>
+<PRE>
+<B>lpoptions -d deskjet ENTREE</B>
+</PRE>
+</UL>
+<P>L'imprimante peut &ecirc;tre locale (<CODE>deskjet</CODE>) ou &agrave; distance (<CODE>
+deskjet@serveur</CODE>).</P>
+<H2><A NAME="5_5">Instances d'imprimantes</A></H2>
+<P>En plus de d&eacute;finir des r&eacute;glages pour chaque file d'impression, CUPS
+ prend en charge les<I> instances d'imprimantes</I> qui vous permettent
+ de d&eacute;finir diff&eacute;rents jeux d'options pour chaque imprimante. Vous
+ indiquez chaque instante en utilisant le caract&egrave;re &quot;slash&quot; (<CODE>/</CODE>
+):</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -p laserjet/legal -o media=Legal ENTREE</B>
+</PRE>
+</UL>
+<P>Les commandes <CODE>lp</CODE> et <CODE>lpr</CODE> comprennent
+ &eacute;galement la notation:</P>
+<UL>
+<PRE>
+<B>lp -d laserjet/duplex nom_fichier ENTREE</B>
+<B>lpr -P laserjet/legal nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_6">Retirer des instances d'imprimantes</A></H2>
+<P>Utilisez l'option <CODE>-x imprimante/instance</CODE> pour retirer
+ une instance d'imprimante dont vous n'avez plus besoin:</P>
+<UL>
+<PRE>
+<B>lpoptions -x laserjet ENTREE</B>
+<B>lpoptions -x laserjet/duplex ENTREE</B>
+<B>lpoptions -x laserjet/legal ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-x</CODE> ne retire que les options implicites pour
+ cette instance d'imprimante. la file d'impression d'origine demeurera
+ jusqu'&agrave; suppression au moyen de la commande <CODE>lpadmin(8)</CODE> par
+ l'administrateur.</P>
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Licence d'utilisation du
+ logiciel<I> (NdT : en anglais)</I></A></H1>
+<H2 ALIGN="CENTER"><A NAME="6_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P ALIGN="CENTER">Copyright 1997-2003 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3111 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
+<H3><A NAME="6_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="6_1_2">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="6_1_3">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
+<BR> Director of Marketing
+<BR> Artifex Software Inc.
+<BR> 454 Las Gallinas Ave., Suite 108
+<BR> San Rafael, CA 94903 USA
+<BR> Voice: +1.415.492.9861
+<BR> Fax: +1.415.492.9862
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
+</P>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
+ Derek B. Noonburg
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="6_1_4">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com">http://www.easysw.com</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<PRE>
+
+</PRE>
+<H3><A NAME="6_2_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+</LI>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+</LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H3><A NAME="6_3_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.</LI>
+<P></P>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<P></P>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
+<P></P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
+<P></P>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
+<P></P>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.</LI>
+<P></P>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
+<P></P>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+</BODY>
+</HTML>
diff --git a/doc/fr/sum.pdf b/doc/fr/sum.pdf
new file mode 100644
index 000000000..9d35017ce
--- /dev/null
+++ b/doc/fr/sum.pdf
Binary files differ
diff --git a/doc/fr/sum.shtml b/doc/fr/sum.shtml
new file mode 100644
index 000000000..412b45100
--- /dev/null
+++ b/doc/fr/sum.shtml
@@ -0,0 +1,1596 @@
+<HTML>
+<HEAD>
+ <TITLE>CUPS - Manuel de l'utilisateur</TITLE>
+ <META NAME="author" CONTENT="Easy Software Products">
+ <META NAME="copyright" CONTENT="Copyright 1997-2003, All Rights Reserved">
+ <META NAME="docnumber" CONTENT="CUPS-SUM-1.1.14">
+</HEAD>
+<BODY BGCOLOR="#ffffff">
+
+<H1 ALIGN="RIGHT"><A NAME="1">Préface</A></H1>
+<P>Ce manuel de l'utilisateur décrit comment utiliser le logiciel CUPS<SUP>TM</SUP> ("Common Unix Printing System<SUP>TM</SUP>") Version 1.1.14.</P>
+
+<P><hr width="50%" size="1px" color="#000000"><I><b>Note du traducteur : </b>Amies lectrices, amis lecteurs, j'ai fait le choix de <b>ne pas traduire</b> l'expression anglaise <b>"default"</b> par la
+version française
+habituellent utilisée <b>"par défaut"</b> que l'on doit, entre autres, à la documentation d'un célèbre système d'exploitation "ouvert à tous vents".
+<br><br>
+En effet, l'expression "par défaut" est normalement utilisée en mathématiques (arrondi "par défaut" ou "par excès",
+personnellement je cherche encore mon "imprimante par excès" !)
+mais elle est abusivement employée en informatique pour signifier "donnée/comportement qui s'applique si l'on n'en
+précise pas <b>explicitement</b> la valeur/nature/teneur".
+<br><br>
+Or la langue française possède justement un mot pout exprimer ce concept
+: "implicite" (Larousse 1998 : "Qui est contenu dans une proposition sans être exprimé en termes précis formels; qui est la
+conséquence nécessaire."). Dans la mesure du possible, j'utiliserai
+cet adjectif sauf dans les cas où son emploi n'est pas suffisamment <b>explicite</b> (sic !). Je lui
+préfèrerai alors l'expression "... de base ..." ou l'adjectif "standard".
+<br><br>
+Ce choix est totalement personnel et le fait que j'ai fait l'effort (non négligeable) de traduire ces lignes pour vos yeux délicats suffit à le justifier! Si, par malheur, ma prose vous est insupportable,
+je ne vous empêche aucunement de vous reporter à la version originale où vous retrouverez "default" entouré de tout le
+reste... en anglais, bien sûr. Enfin, si vous avez une meilleure traduction, je suis preneur !
+<br><br>
+Malgré les très nombreuses relectures et corrections, certaines fautes de frappe, d'orthographe ou de grammaire ont pu échapper à ma vigilance (ou à celles de mes relecteurs/correcteurs). Merci de me les signaler afin de contribuer à
+l'amélioration constante de la qualité du présent manuel.
+<br><br>
+Bonne lecture !
+</I><hr width="50%" size="1px" color="#000000"></P>
+
+<H2><A NAME="1_1">Aperçu du système</A></H2>
+
+<P>CUPS fournit une couche d'impression portable pour les systèmes d'exploitation de
+type UNIX&reg;. Il a été développé par <A HREF="http://www.easysw.com">Easy
+ Software Products</A> pour promouvoir une solution d'impression standard pour
+tous les vendeurs et utilisateurs d'UNIX. CUPS fournit des interfaces en ligne de
+commande de type System V et Berkeley.
+</P>
+
+<P>CUPS utilise le protocol IPP (Internet Printing Protocol) comme base de l'administration
+des travaux et files d'impression. Les protocoles LPD ("Line Printer Daemon"), SMB
+("Server Message Block"), et AppSocket (JetDirect) sont également pris en charge avec
+des fontionnalités réduites. CUPS ajoute l'exploration réseau des imprimantes ("network
+printer browsing") et des options d'impression basées sur PPD ("PostScript Printer
+Definition") pour prendre en charge l'impression "dans le monde réel" sous UNIX.
+</P>
+
+<P>CUPS inclut également une version adaptée de GNU/Ghostscript (actuellement basée
+sur la version 5.50) et un module de rendu (RIP - Raster Image Processor) pour fichier image qui sont utilisés pour prendre
+en charge les imprimantes non-PostScript. Des pilotes d'exemple (incluant ces filtres)
+pour imprimantes HP et EPSON sont également inclus.
+</P>
+
+<!-- NEED 2in -->
+<H2><A NAME="1_2">Aperçu du document</A></H2>
+<P>Le présent manuel de l'utilisateur s'articule autour sections suivantes:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Aperçu du système d'impression</A></LI>
+<LI><A HREF="#USING_SYSTEM">2 - Utilisation du système d'impression</A></LI>
+<LI><A HREF="#STANDARD_OPTIONS">3 - Options standards pour imprimante</A></LI>
+<LI><A HREF="#SAVING_OPTIONS">4 - Sauvegarde des options et valeurs implicites des réglages d'imprimante</A>
+</LI>
+<LI><A HREF="#LICENSE">A - Licence d'utilisation du logiciel <I>(NdT : en anglais)</I></A></LI>
+</UL>
+<H2><A NAME="1_3">Conventions d'écritures</A></H2>
+
+Diverses conventions de polices de caractères et de syntaxe sont utilisées dans ce guide.
+Des exemples et leur signification sont donnés ci-dessous:
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH>Exemple</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+Les noms des commandes; La première référence faite à une commande ou une fonction dans un
+chapitre est suivie par un numéro de section de page de manuel.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><VAR>/var</VAR>
+<BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+Noms de fichiers et de répertoires.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><TT>Request ID is Printer-123</TT></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Affichage écran.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d imprimante nom_fichier ENTREE</KBD></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Frappe littérale de l'utilisateur; les touches spéciales telles que <KBD>ENTREE</KBD>
+sont représentées en lettres capitales.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+Les nombres dans le texte sont écrits avec un point symbolisant le séparateur décimal.</TD></TR>
+</TABLE>
+</CENTER>
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abréviations</A></H2>
+ Les abréviations suivantes sont utilisées au cours de ce manuel:
+<UL>
+<DL>
+<DT>ko</DT>
+<DD>Kilo-octets, ou 1024 octets
+<BR>&nbsp;</DD>
+<DT>Mo</DT>
+<DD>Méga-octets, ou 1048576 octets
+<BR>&nbsp;</DD>
+<DT>Go</DT>
+<DD>Giga-octets, ou 1073741824 octets
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+
+<H2><A NAME="1_5">Autres références</A></H2>
+<UL>
+<DL>
+<DT>CUPS - Manuel de l'administrateur</DT>
+<DD>Un guide d'administration du logiciel CUPS.
+<BR>&nbsp;</DD>
+<DT>CUPS - Manuel du programmeur <i>(NdT : en anglais)</i></DT>
+<DD>Un guide du programmeur pour créer des programmes qui s'interfacent avec et/ou étendent le logiciels CUPS.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Aperçu du système d'impression</A></H1>
+<P>Ce chapitre fournit un aperçu du fonctionnement de CUPS.</P>
+<H2><A NAME="2_1">Le problème d'impression</A></H2>
+<P>Depuis des années<I> le problème d'impression</I> a empoisonné le monde UNIX.
+Contrairement à Microsoft&reg; Windows&reg; ou Mac OS, UNIX n'a pas d'interface standard ou
+de système en place pour prendre en charge les imprimantes. Parmi les solutions actuellement
+disponibles, les systèmes Berkeley et System V sont prédominants.</P>
+
+<P>
+ Ces systèmes d'impressions prennent en charge les imprimantes de type matriciel texte ou les
+ imprimantes PostScript (texte et graphique), et avec quelques ajustements il peuvent prendre en
+ charge un grand nombre d'imprimantes et de formats de fichiers. Cependant, puisque chaque
+ version de système d'exploitation UNIX utilise un système d'impression différent de celui
+ de son voisin, il est extrêmement difficile de développer des pilotes d'imprimantes pour une
+ vaste gamme d'imprimantes et de systèmes d'exploitation. Ceci, combiné au faible nombre de
+ clients pour chaque variante d'UNIX, a poussé les fabricants d'imprimantes à abandonner la prise en
+ charge globale de tous les UNIX.
+</P>
+
+<P>
+ CUPS est conçu pour éliminer <I>le problème d'impression</I>. Un système d'impression
+ commun peut être utilisé par toutes les variantes d'UNIX pour prendre en charge les
+ capacités d'impression dont les utilisateurs ont besoin. Les fabricants d'imprimantes peuvent
+ utiliser l'interface modulaire des filtres pour développer un unique pilote qui prend en charge une
+ large gamme de formats de fichiers et ce, sans presque aucun effort. Etant donné que CUPS fournit
+ une interface compatible avec les commandes Berkeley et System V, les utilisateurs (et les applications)
+ peuvent tirer bénéfice de cette nouvelle technologie sans avoir à faire de changements.
+</P>
+
+<H2><A NAME="2_2">La technologie</A></H2>
+
+<P>
+ CUPS est basé sur un standard émergeant d'Internet appelé IPP (Internet Printing Protocol). IPP a été adopté
+ par des douzaines de fabricants d'imprimantes et de serveurs d'impression et est pris en charge par
+ Microsoft Windows 2000.
+</P>
+
+<P>
+ IPP définit un protocole standard pour imprimer ainsi qu'administrer les travaux d'impression et les options
+ des imprimantes telles que la taille du support d'impression, la résolution, etc. Comme tout protocole de la pile
+ TCP/IP, IPP peut être utilisé localement ou à travers Internet pour atteindre des imprimantes éloignées de centaines
+ ou de milliers de kilomètres. Contrairement à d'autres protocoles de la pile TCP/IP, IPP prend en charge le
+ contrôle d'accès, l'authentification et l'encryptage, ce qui fait de lui une solution d'impression bien plus efficace
+ et sécurisée que ses ancêtres.
+</P>
+
+<P>
+ IPP est une surcouche ajoutée au-dessus du protocole HTTP (HyperText Transport Protocol) qui est à la base
+ des serveurs "web" sur l'Internet. Ceci permet aux utilisateurs de lire la documentation, vérifier les informations
+ sur l'état des imprimantes ou du serveur, administrer les imprimantes, les classes d'imprimantes et les travaux
+ d'impression en utilisant leur navigateur "web".
+</P>
+
+<P>
+ CUPS fournit un système d'impression complet basé sur IPP/1.1 prenant en charge l'authentification
+ "Basic", "Digest" et par certificats locaux ainsi qu'un contrôle d'accès basé sur l'utilisateur,
+ le domaine ou l'adresse IP. L'encryptage TLS sera disponible dans une future version de CUPS.
+</P>
+
+<H2><A NAME="2_3">Travaux d'impression</A></H2>
+
+<P>
+ Tout fichier ou groupe de fichiers soumis à l'impression est appelé un <I>travail d'impression</I>. Les travaux
+ d'impression sont identifiés par un nombre unique en commençant à 1 et sont affectés à une destination particulière,
+ généralement une imprimante. Les travaux d'impression peuvent également inclure des options associées telles que la
+ taille du support d'impression, le nombre de copies et la priorité dans la file d'impression.
+</P>
+
+<H2><A NAME="2_4">Classes d'imprimantes</A></H2>
+
+<P>
+ CUPS prend en charge des collections d'imprimantes connues sous le nom de <I>classes</I>. Les travaux d'impression
+ transmis à une classe d'imprimantes sont envoyés à la première imprimante disponible dans la classe.
+</P>
+
+<H2><A NAME="2_5">Filtres</A></H2>
+
+<P>Les filtres permettent à un utilisateur ou une application d'imprimer de nombreux types de documents sans
+effort supplémentaire. Les travaux d'impressions envoyés au serveur CUPS sont filtrés avant d'être envoyés à
+l'imprimante. Certains filtres convertissent les fichiers de travaux d'impression dans différents formats que
+l'imprimante peut comprendre. D'autres ne font que des sélections de page et des tris.
+</P>
+
+<P>CUPS fournit des filtres pour imprimer de nombreux types de fichiers image, des fichier HP-GL/2,
+fichiers PDF et texte. CUPS fournit également des filtres PostScript et RIP (Raster Image Processor) qui
+convertissent les fichiers PostScript ou image en format "bitmap" qui peut être envoyé à une
+imprimante de type "matriciel" (NdT : il s'agit ici, des imprimantes dont l'impression est générée au moyen d'une
+grille de points
+comme l'étaient les vénérables imprimantes à aiguilles de notre enfance, mais pas seulement elles puisque les
+imprimantes à jet
+d'encre actuelles sont également de type matriciel... par opposition aux imprimantes laser dont la méthode de génération
+d'impression est différente.)
+</P>
+
+<H2><A NAME="2_6">Programmes d'arrière-plan (Backends)</A></H2>
+
+<P>Les programmes d'arrière-plan effectuent le travail le plus important : ils envoient les données
+d'impression à l'imprimante.
+</P>
+
+<P>CUPS fournit des programmes d'arrière-plan pour imprimer via des ports de type parallèle, série, USB et à travers un
+réseau au moyen des protocoles IPP, JetDirect (AppSocket) et LPD (Line Printer Daemon). Des programmes d'arrière-plan
+additionnels sont disponibles sous forme de paquetage de service réseau comme le programme d'arrière_plan SMB
+inclus dans le célèbre logiciel SAMBA.
+</P>
+
+<P>Les programmes d'arrière-plan sont également utilisés pour déterminer les périphériques
+disponibles. Au démarrage, chaque programme d'arrière-plan est interrogé afin de déterminer la liste des
+périphériques qu'il prend en charge, ainsi que toute information disponible. Cela permet au programme d'arrière-plan
+de gestion du port parallère d'indiquer à CUPS qu'une imprimante EPSON Stylus Color 600 est branchée sur le port
+parallèle 1, par exemple.
+</P>
+
+<H2><A NAME="2_7">Pilotes d'imprimantes</A></H2>
+
+<P>Les pilotes d'imprimantes de CUPS consistent en un ou plusieurs filtres spécifiques à une imprimante. CUPS inclut
+des pilotes d'imprimantes d'exemple pour les imprimantes Deskjet et LaserJet Hewlett-Packard et les imprimantes EPSON jet
+d'encre couleur Stylus Color, Stylus Photo et les modèles 9 et 24 aiguilles matricielles. Bien que ces pilotes ne produisent
+pas des impressions de qualité optimale pour les différents modèles d'imprimantes, ils fournissent une impression de
+base et démontrent comment vous pouvez écrire vos propres pilotes d'imprimantes et les incorporer dans CUPS.
+</P>
+
+<H2><A NAME="2_8">Réseau</A></H2>
+
+<P>Les imprimantes et classes d'imprimantes sur le système local sont automatiquement partagées avec les autres systèmes
+sur le réseau. Cela vous permet de configurer un système hôte pour tous les autres. Les utilisateurs pourront sélectionner
+une imprimante locale par son nom ou une imprimante à distance en utilisant la syntaxe &quot;nom_imprimante@serveur&quot;.
+</P>
+
+<P>CUPS fournit également des <I>classes d'imprimantes implicites</I> (NdT : le terme "implicite" est ici la traduction
+litérale du même mot anglais "implicit" et non celle de l'expression "default". cf. ma remarque dans la préface du présent manuel.
+De toute façon, CUPS ne prévoit pas de "default class" c'est-à-dire de "classe de base", donc aucune ambiguïté possible
+ici.), qui sont des collections d'imprimantes ou
+de classes d'imprimantes qui portent le même nom. Cela vous permet de configurer de multiples serveurs pointant vers
+la même imprimante réseau physique, par exemple, de sorte que vous ne dépendez pas d'un seul serveur pour pouvoir
+imprimer. Etant donné que cette méthode vous permet de travailler avec des classes d'imprimantes, vous pouvez configurer
+de multiples serveurs et imprimantes sans jamais vous soucier d'un simple point en panne tant que tous les autres serveurs
+ne tombent pas en panne en même temps.
+</P>
+
+<H1 ALIGN="RIGHT"><A NAME="USING_SYSTEM">2 - Utilisation du système d'impression</A>
+</H1>
+<P>Ce chapitre expose comment soumettre, lister et annuler les travaux d'impression sur différentes imprimantes.</P>
+<H2><A NAME="3_1">Soumission de travaux à l'impression</A></H2>
+<P>CUPS fournit les deux commandes d'impression System V (<CODE>lp(1)</CODE>) et Berkeley (<CODE>
+lpr(1)</CODE>). Tapez la commande suivante pour imprimer un fichier sur l'imprimante implicite du système:</P>
+<UL>
+<PRE>
+<B>lp nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>ou:</P>
+<UL>
+<PRE>
+<B>lpr nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>CUPS sait directement interpréter différents types de fichier, y compris les fichiers PostScript et image.
+Cela vous permet d'imprimer depuis vos applications ou depuis la ligne de commande, selon votre préférence!</P>
+
+<H2><A NAME="3_2">Choix d'une imprimante</A></H2>
+
+<P>Beaucoup de systèmes disposeront de plusieurs imprimantes à offrir à l'utilisateur. Ces imprimantes peuvent être
+reliées au système local par un port parallèle, série ou USB, ou accessibles à travers le réseau.</P>
+
+<P>Utilisez la commande <CODE>lpstat(1)</CODE> pour voir une liste des imprimantes disponibles:</P>
+<UL>
+<PRE>
+<B>lpstat -p -d ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-p</CODE> indique que vous voulez voir la liste des imprimantes et l'option <CODE>-d</CODE>
+provoque l'affichage de l'imprimante ou classe d'imprimantes standard (implicite) du système.</P>
+
+<P>Utilisez l'option <CODE>-d</CODE> avec la comamnde <CODE>lp</CODE> pour imprimer vers une imprimante spécifique:</P>
+<UL>
+<PRE>
+<B>lp -d imprimante nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>ou l'option <CODE>-P</CODE> avec la commande <CODE>lpr</CODE>:</P>
+<UL>
+<PRE>
+<B>lpr -P imprimante nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<H2><A NAME="3_3">Réglage des options d'imprimante</A></H2>
+
+<P>Pour de nombreux types de fichiers, les options d'imprimante implicites devraient satisfaire vos besoins. Cependant,
+il peut arriver que vous ayez besoin de changer les options pour un fichier spécifique que vous imprimez.</P>
+
+
+<P>Les commandes <CODE>lp</CODE> et <CODE>lpr</CODE> vous permettent de passer des options d'imprimante en utilisant
+l'option <CODE>-o</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
+<B>lpr -o landscape -o scaling=75 -o media=A4 nom_fichier.jpg
+</B></B></PRE>
+</UL>
+
+<P>Les options d'imprimante disponibles varient en fonction de l'imprimante. Les options standards sont décrites dans le
+<A HREF="#STANDARD_OPTIONS"> Chapitre 3, &quot;Options standards d'imprimante&quot;</A>.</P>
+
+<H2><A NAME="3_4">Impression de plusieurs copies</A></H2>
+
+<P>Les deux commandes <CODE>lp</CODE> et <CODE>lpr</CODE> possèdent des options pour l'impression de plus d'une copie d'un fichier:</P>
+<UL>
+<PRE>
+<B>lp -n <I>nombre_copies</I> nom_fichier ENTREE</B>
+<B>lpr -#<I>nombre_copies</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les copies ne sont généralement <i>pas</i> assemblées. Utilisez l'option <CODE>-o Collate=True</CODE> pour obtenir des copies assemblées:</P>
+<UL>
+<PRE>
+<B>lp -n <I>nombre_copies</I> -o Collate=True nom_fichier ENTREE</B>
+<B>lpr -#<I>nombre_copies</I> -o Collate=True nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H2><A NAME="3_5">Vérification de l'état d'une imprimante depuis la ligne de commande</A></H2>
+
+<P>La commande <CODE>lpstat</CODE> peut être utilisée pour vérifier les travaux que vous avez soumis à l'impression:</P>
+<UL>
+<PRE>
+<B>lpstat ENTREE</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+</PRE>
+</UL>
+<P>Les travaux sont listés dans l'ordre dans lequel ils seront imprimés.
+Utilisez l'option <CODE>-p</CODE> pour voir les travaux actifs sur l'imprimante:</P>
+<UL>
+<PRE>
+<B>lpstat -p ENTREE</B>
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Utilisez les options <CODE>-o</CODE> et <CODE>-p</CODE> ensemble pout voir les à la fois les travaux et les imprimantes:</P>
+<UL>
+<PRE>
+<B>lpstat -o -p ENTREE</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+<H2><A NAME="3_6">Vérification de l'état d'un imprimante depuis l'interface "web"</A></H2>
+
+<P>CUPS utilise le protocole IPP (Internet Printing Protocol), mais c'est également un serveur "web" complètement fonctionnel.
+Pour utiliser votre navigateur "web" pour surveiller les imprimantes sur votre système, ouvrez l'adresse:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631">http://localhost:631</A>
+</PRE>
+</UL>
+<P>A partir de là, vous pouvez voir l'état des classes, travaux, et imprimantes par un simple clic de bouton!</P>
+
+<H2><A NAME="3_7">Suppression d'un travail d'impression</A></H2>
+
+<P>Les commandes <CODE>cancel(1)</CODE> et <CODE>lprm(1)</CODE> suppriment un travail d'impression:</P>
+<UL>
+<PRE>
+<B>cancel <I>numéro_travail</I> ENTREE</B>
+<B>lprm <I>numéro_travail</I> ENTREE</B>
+</PRE>
+</UL>
+<P>Le <CODE>numéro_travail</CODE> est le nombre qui vous est fourni par les commandes <CODE>lp</CODE> ou <CODE>lpstat</CODE>.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Options standards d'imrimante</A></H1>
+
+<P>Ce chapitre décrit les options standards d'imprimante qui sont disponibles lors de l'impression au moyen des commandes
+<CODE>lp</CODE> et <CODE>lpr</CODE>.</P>
+
+<H2><A NAME="4_1">Options générales</A></H2>
+<P>Les options suivantes s'appliquent lors de l'impression de tous les types de fichiers.</P>
+
+<H3><A NAME="4_1_1">Réglage de l'orientation</A></H3>
+
+<P>L'option <CODE>-o landscape</CODE> tournera la sortie imprimée de 90° pour imprimer en mode paysage:</P>
+<UL>
+<PRE>
+<B>lp -o landscape nom_fichier ENTREE</B>
+<B>lpr -o landscape nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H3><A NAME="4_1_2">Choix du type, de la taille et de la source du support d'impression</A></H3>
+<P>L'option <CODE>-o media=xyz</CODE> définit la taille, le type et la source du support d'impression:</P>
+<UL>
+<PRE>
+<B>lp -o media=Letter nom_fichier ENTREE</B>
+<B>lp -o media=Letter,MultiPurpose nom_fichier ENTREE</B>
+<B>lpr -o media=Letter,Transparency nom_fichier ENTREE</B>
+<B>lpr -o media=Letter,MultiPurpose,Transparency nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>Les tailles, types et sources de support d'impression disponibles dépendent de l'imprimante mais la plupart des matériels prennent en charge les options suivantes (les plus courantes):</P>
+<UL>
+<LI><CODE>Letter</CODE> - US Letter (8.5x11 pouces, ou 216x279mm)</LI>
+<LI><CODE>Legal</CODE> - US Legal (8.5x14 pouces, ou 216x356mm)</LI>
+<LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 pouces, ou 210x297mm)</LI>
+<LI><CODE>COM10</CODE> - US #10 Enveloppe (9.5x4.125 pouces, ou 241x105mm)</LI>
+<LI><CODE>DL</CODE> - ISO DL Enveloppe (8.66x4.33 pouces, ou 220x110mm)</LI>
+<LI><CODE>Transparency</CODE> - Type de support transparent ou source de support transparent</LI>
+<LI><CODE>Upper</CODE> - Bac d'alimentation supérieur</LI>
+<LI><CODE>Lower</CODE> - Bac d'alimentation inférieur</LI>
+<LI><CODE>MultiPurpose</CODE> - Bac papier multi-usage</LI>
+<LI><CODE>LargeCapacity</CODE> - Bac d'alimentation de grande capacité</LI>
+</UL>
+<P>Les options réellement prises en charge sont définies dans le fichier PPD de l'imprimante au moyen des options <CODE>PageSize</CODE>, <CODE>InputSlot</CODE>, et <CODE>MediaType</CODE>.</P>
+
+<H3><A NAME="4_1_3">Impression en recto/verso</A></H3>
+
+<P>Les options <CODE>-o sides=two-sided-short-edge</CODE> et <CODE>-o
+ sides=two-sided-long-edge</CODE> activeront l'impression recto/verso si l'imprimante la prend en charge. L'option <CODE>-o
+ sides=two-sided-short-edge</CODE> convient pour les pages orientées en paysage, tandis que l'option
+<CODE>-o sides=two-sided-long-edge</CODE> convient pour celles orientées en portrait:</P>
+<UL>
+<PRE>
+<B>lp -o sides=two-sided-short-edge nom_fichier ENTREE</B>
+<B>lp -o sides=two-sided-long-edge nom_fichier ENTREE</B>
+<B>lpr -o sides=two-sided-long-edge nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est d'imprimer en mode simple face ("single-sided"):</P>
+<UL>
+<PRE>
+<B>lp -o sides=one-sided nom_fichier ENTREE</B>
+<B>lpr -o sides=one-sided nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="4_2">Options de pages de garde</A></H2>
+
+<P>Les options suivantes s'appliquent à l'impression de tous les types de fichiers.</P>
+
+<H3><A NAME="4_2_1">Sélection des pages de garde</A></H3>
+
+<P>L'option <CODE>-o jobsheets=start,end</CODE> définit les pages de garde pour un travail d'impression:</P>
+<UL>
+<PRE>
+<B>lp -o job-sheets=none nom_fichier ENTREE</B>
+<B>lp -o job-sheets=standard nom_fichier ENTREE</B>
+<B>lpr -o job-sheets=classified,classified nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Si seulement un fichier de page de garde est indiqué il sera imprimé avant le travail d'impression.
+Si un second fichier de page de garde est indiqué, il sera imprimé après le travail d'impression..</P>
+
+<P>Les pages de garde disponibles dépendent de la configuration du système local;
+ CUPS inclut les fichiers de pages de garde suivants:</P>
+<UL>
+<LI><CODE>none</CODE> - Ne pas produire de page de garde.</LI>
+<LI><CODE>classified</CODE> - Une page de garde avec une inscription &quot;classified&quot; en haut et en bas de page.</LI>
+<LI><CODE>confidential</CODE> - Une page de garde avec une inscription &quot;confidential&quot; en haut et en bas de page.</LI>
+<LI><CODE>secret</CODE> - Une page de garde avec une inscription &quot;secret&quot; en haut et en bas de page.</LI>
+<LI><CODE>standard</CODE> - Une page de garde sans inscription en haut et en bas de page.</LI>
+<LI><CODE>topsecret</CODE> - Une page de garde avec une inscription &quot;top-secret&quot; en haut et en bas de page.</LI>
+<LI><CODE>unclassified</CODE> - Une page de garde avec une inscription &quot;unclassified&quot; en haut et en bas de page.</LI>
+</UL>
+<H2><A NAME="4_3">Options de document</A></H2>
+
+<P>Les options suivantes s'appliquent à l'impression de tous les types de fichiers.</P>
+
+<H3><A NAME="4_3_1">Sélection d'une série de pages</A></H3>
+
+<P>L'option <CODE>-o page-ranges=pages</CODE> sélectionne une série de pages à imprimer:</P>
+<UL>
+<PRE>
+<B>lp -o page-ranges=1 nom_fichier ENTREE</B>
+<B>lp -o page-ranges=1-4 nom_fichier ENTREE</B>
+<B>lp -o page-ranges=1-4,7,9-12 nom_fichier ENTREE</B>
+<B>lpr -o page-ranges=1-4,7,9-12 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Comme indiqué ci-dessus, la valeur <CODE>pages</CODE> peut être une page unique, un intervalle de numéros de pages ou une collections de numéros de pages et d'intervalles séparés par des virgules.
+Les pages seront imprimées dans l'ordre croissant de leurs numéros, sans tenir compte de l'ordre dans lequel les valeurs
+ont été tapées dans l'option <CODE>page-ranges</CODE>.</P>
+
+<P>Le comportement implicite est d'imprimer toutes les pages.</P>
+
+<H3><A NAME="4_3_2">Sélection des pages paires et impaires</A></H3>
+
+<P>Utilisez l'option <CODE>-o page-set=set</CODE> pour sélectionner les pages paires ou impaires:</P>
+<UL>
+<PRE>
+<B>lp -o page-set=odd nom_fichier ENTREE</B>
+<B>lp -o page-set=even nom_fichier ENTREE</B>
+<B>lpr -o page-set=even nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le comportement implicite est d'imprimer toutes les pages.</P>
+
+<H3><A NAME="4_3_3">Impression de plusieurs pages par face du support ("N-Up Printing")</A></H3>
+
+<P>L'option <CODE>-o number-up=value</CODE> sélectionne l'impression de plusieurs pages par face du support. Cela permet d'imprimer 1, 2 ou 4 pages du document d'origine sur une seule page physique en sortie:</P>
+<UL>
+<PRE>
+<B>lp -o number-up=1 nom_fichier ENTREE</B>
+<B>lp -o number-up=2 nom_fichier ENTREE</B>
+<B>lp -o number-up=4 nom_fichier ENTREE</B>
+<B>lpr -o number-up=4 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est 1.</P>
+
+<H3><A NAME="4_3_4">Réglage de la luminosité</A></H3>
+
+<P>Vous pouvez contrôler la luminosité globale de la sortie imprimée en utilisant l'option
+<CODE>-o brightness=percent</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o brightness=120 nom_fichier ENTREE</B>
+<B>lpr -o brightness=120 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les valeurs supérieures à 100 éclaircissent l'impression, tandis que les valeurs inférieures à 100 l'assombrissent.</P>
+
+<H3><A NAME="4_3_5">Réglage de la correction Gamma</A></H3>
+
+<P>Vous pouvez contrôler la correction gamma goblale de la sortie imprimée en utilsiant l'option
+<CODE>-o gamma=value</CODE>:</P>
+<UL>
+<PRE>
+<B>lp -o gamma=1700 nom_fichier ENTREE</B>
+<B>lpr -o gamma=1700 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Les valeurs supérieures à 1000 éclaircissent l'impression, tandis que les valeurs inférieures à 1000 l'assombrissent.
+La valeur implicite est 1000.</P>
+
+<H2><A NAME="4_4">Options de texte</A></H2>
+
+<P>Les options suivantes s'appliquent à l'impression de fichier texte.</P>
+
+<H3><A NAME="4_4_1">Réglage du nombre de caractères par pouce</A></H3>
+
+<P>L'option <CODE>-o cpi=value</CODE> définit le nombre de caractères par pouce <i>(NdT : 1 pouce = 2,54 cm)</i>:</P>
+<UL>
+<PRE>
+<B>lp -o cpi=10 nom_fichier ENTREE</B>
+<B>lp -o cpi=12 nom_fichier ENTREE</B>
+<B>lpr -o cpi=17 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre implicite de caractères par pouce est 10.</P>
+
+<H3><A NAME="4_4_2">Réglage du nombre de lignes par pouce</A></H3>
+
+<P>L'option <CODE>-o lpi=value</CODE> définit le nombre de lignes par pouce:</P>
+<UL>
+<PRE>
+<B>lp -o lpi=6 nom_fichier ENTREE</B>
+<B>lpr -o lpi=8 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre implicite de lignes par pouces est 6.</P>
+
+<H3><A NAME="4_4_3">Réglage du nombre de colonnes</A></H3>
+
+<P>L'option <CODE>-o columns=value</CODE> définit le nombre de colonnes de texte:</P>
+<UL>
+<PRE>
+<B>lp -o columns=2 nom_fichier ENTREE</B>
+<B>lpr -o columns=3 nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le nombre de colonnes implicite est 1.</P>
+
+<H3><A NAME="4_4_4">Réglage des marges de la page</A></H3>
+
+<P>Normalement, les marges de la page sont fixées par les limites physiques de l'imprimante.
+Utilisez les options <CODE>-o page-left=value</CODE>, <CODE>-o page-right=value</CODE>
+, <CODE>-o page-top=value</CODE>, et <CODE>-o page-bottom=value</CODE>
+ pour ajuster les marges:</P>
+<UL>
+<PRE>
+<B>lp -o page-left=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-right=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-top=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lp -o page-bottom=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lpr -o page-bottom=<I>valeur</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'argument <CODE>valeur</CODE> est la marge en points; 1 point = 1/72ème de pouce = 0.35mm.</P>
+
+<H3><A NAME="4_4_5">Impression améliorée</A></H3>
+
+<P>L'option <CODE>-o prettyprint</CODE> ajoute un en-tête en haut de chaque page. Celui-ci comporte le numéro de page,
+le titre du travail d'impression (habituellement le nom du fichier), et la date. Les mots clefs C, C++ et les lignes de commentaires sont également représentées en italique:</P>
+<UL>
+<PRE>
+<B>lp -o prettyprint nom_fichier ENTREE</B>
+<B>lpr -o prettyprint nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="4_5">Options d'image</A></H2>
+
+<P>Les options suivantes s'appliquent lors de l'impression de fichiers image.</P>
+
+<H3><A NAME="4_5_1">Positionnement de l'image</A></H3>
+
+<P>L'option <CODE>-o position=name</CODE> indique la position de l'image dans la page:</P>
+<UL>
+<LI><CODE>center</CODE> - Centre l'image dans la page (valeur implicite)</LI>
+<LI><CODE>top</CODE> - Imprime l'image calée en haut de la page et centrée en largeur</LI>
+<LI><CODE>left</CODE> - Imprime l'image calée à gauche de la page et centrée en hauteur</LI>
+<LI><CODE>right</CODE> - Imprime l'image calée à droite de la page et centrée en hauteur</LI>
+<LI><CODE>top-left</CODE> - Imprime l'image calée dans le coin supérieur gauche</LI>
+<LI><CODE>top-right</CODE> - Imprime l'image calée dans le coin supérieur droit</LI>
+<LI><CODE>bottom</CODE> - Imprime l'image calée en bas de la page et centrée en largeur</LI>
+<LI><CODE>bottom-left</CODE> - Imprime l'image calée dans le coin inférieur gauche</LI>
+<LI><CODE>bottom-right</CODE> - Imprime l'image calée dans le coin inférieur droit</LI>
+</UL>
+<H3><A NAME="4_5_2">Mise à l'échelle de l'image</A></H3>
+<P>Les options <CODE>-o scaling=percent</CODE>, <CODE>-o ppi=value</CODE>, et <CODE>
+-o natural-scaling=percent</CODE> changent la taille de l'image imprimée:</P>
+<UL>
+<PRE>
+<B>lp -o scaling=<I>percent</I> nom_fichier ENTREE</B>
+<B>lp -o ppi=<I>value</I> nom_fichier ENTREE</B>
+<B>lpr -o natural-scaling=<I>percent</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur <CODE>scaling=percent</CODE> est un nombre compris entre 1 et 800 indiquant la taille par rapport celle de la page
+(<I>pas celle de l'image</I>). Un valeur de 100% va adapter l'image à la taille maximale que permet la page (en fonction
+des contraintes imposées par le rapport hauteur/largeur de l'image). Une valeur de 200% imprimera l'image répartie sur
+4 pages.</P>
+
+<P>La valeur <CODE>ppi=value</CODE> est un nombre compris entre 1 et 1200 indiquant la résolution
+ de l'image en pixels par pouce. Une image qui mesure 3000x2400 pixels s'imprimera sur le papier
+ en 10x8 pouces à une résolution de 300 pixels par pouce (ppp ou, en anglais, dpi).
+ Si la résolution indiquée donne une image plus grande que la page, plusieurs pages sont imprimées pour satisfaire la
+ requête.</P>
+<P>La valeur <CODE>natural-scaling=percent</CODE> est un nombre compris entre 1 et 800 indiquant la taille d'impression
+de l'image relativement à sa taille d'origine. Une valeur de 100% imprimera l'image dans sa taille normale, tandis
+qu'une valeur de 50% donnera une taille moitié moins grande. Si la valeur indiquée donne une image plus grande que la page,
+plusieurs pages sont imprimées pour satisfaire la
+ requête.</P>
+
+<H3><A NAME="4_5_3">Ajustement de la teinte ("Hue", "Tint") de l'image</A></H3>
+<P>La valeur <CODE>-o hue=value</CODE> ajustera la teinte ("hue") de l'image imprimée, comme le réglage de teinte de
+votre télévision:</P>
+<UL>
+<PRE>
+<B>lp -o hue=<I>value</I> nom_fichier ENTREE</B>
+<B>lpr -o hue=<I>value</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>L'argument <CODE>value</CODE> est un nombre compris entre -360 et 360 représentant une rotation de teinte.
+Le tableau suivant, résume les changements que vous verrez avec différentes couleurs:
+<CENTER>
+<TABLE BORDER="1" WIDTH="50%">
+<TR><TH>Original</TH><TH>hue=-45</TH><TH>hue=45</TH></TR>
+<TR><TD>Rouge</TD><TD>Pourpre</TD><TD>Jaune-orange</TD></TR>
+<TR><TD>Vert</TD><TD>Jaune-vert</TD><TD>Bleu-vert</TD></TR>
+<TR><TD>Jaune</TD><TD>Orange</TD><TD>Vert-Jaune</TD></TR>
+<TR><TD>Bleu</TD><TD>Bleu ciel</TD><TD>Pourpre</TD></TR>
+<TR><TD>Magenta</TD><TD>Indigo</TD><TD>Rouge cramoisi</TD></TR>
+<TR><TD>Cyan</TD><TD>Bleu-vert</TD><TD>Blue marine clair</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>La valeur implicite de ce paramètre est 0.</P>
+
+<H3><A NAME="4_5_4">Ajustement de la saturation de couleur de l'image</A></H3>
+<P>L'option <CODE>-o saturation=percent</CODE> ajuste la saturation des couleurs de l'image, comme le bouton "couleur" de
+votre télévision:</P>
+<UL>
+<PRE>
+<B>lp -o saturation=<I>percent</I> nom_fichier ENTREE</B>
+<B>lpr -o saturation=<I>percent</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'argument <CODE>percent</CODE> indique la saturation de couleur de 0 à 200. Une saturation de 0 produit une
+image en noir et blanc, tandis qu'une valeur de 200 rend les couleurs extrêmement intenses.</P>
+<P>La saturation implicite est de 100.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="4_6">Options HP-GL/2</A></H2>
+
+<P>Les options suivantes s'appliquent aux fichiers HP-GL/2.</P>
+
+<H3><A NAME="4_6_1">Impression en noir</A></H3>
+<P>L'option <CODE>-o blackplot</CODE> indique que tous les "stylos" doivent écrire en noir:</P>
+<UL>
+<PRE>
+<B>lp -o blackplot nom_fichier ENTREE</B>
+<B>lpr -o blackplot nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La valeur implicite est d'utiliser les couleurs définies dans le fichier ou les couleurs standards de "stylos"
+définies dans le manuel de référence HP-GL/2.</P>
+
+<H3><A NAME="4_6_2">Ajuster le tracé à la page</A></H3>
+
+<P>L'option <CODE>-o fitplot</CODE> indique que le tracé doit être mis à l'échelle pour tenir sur la page:</P>
+<UL>
+<PRE>
+<B>lp -o fitplot nom_fichier ENTREE</B>
+<B>lpr -o fitplot nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>Le comportement implicite est d'utiliser les distances absolues définies dans le fichier.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Cette fonctionnalité dépend d'une définition précise de la commande de taille de tracé
+(<CODE>PS</CODE>) dans le fichier HP-GL/2. Si aucune taille de tracé n'est donnée dans le fichier, alors le filtre
+HP-GL/2 considère que le tracé a une taille ANSI E.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_6_3">Réglage de la largeur implicite de tracé</A></H3>
+<P>L'option <CODE>-o penwidth=valeur</CODE> indique la valeur implicite de largeur de tracé pour les fichiers
+HP-GL/2:</P>
+<UL>
+<PRE>
+<B>lp -o penwidth=<I>valeur</I> nom_fichier ENTREE</B>
+<B>lpr -o penwidth=<I>valeur</I> nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>La <CODE>valeur</CODE> de largeur de tracé définit la largeur de "stylo" en micromètres. La valeur
+implicite de 1000 produit des lignes de 1 millimètre de large. Indiquer une largeur de "stylo" de 0 produit un
+tracé d'un pixel de large.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Cette option est ignorée si les largeurs de tracé sont définies dans le fichier.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_7">Sortie brute ou non filtrée</A></H2>
+<P>L'option <CODE>-o raw</CODE> vous permet d'envoyer directement des fichiers à l'imprimante sans faire de filtrage.
+Cela est parfois nécessaire lors que vous imprimez depuis des applications qui fournissent leur propres "pilotes d'imprimantes"
+pour votre imprimante:</P>
+<UL>
+<PRE>
+<B>lp -o raw nom_fichier ENTREE</B>
+<B>lpr -o raw nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-l</CODE> peut également être utilisée avec la commande <CODE>lpr</CODE>
+ pour envoyer directement des fichiers à une imprimante:</P>
+<UL>
+<PRE>
+<B>lpr -l nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Sauvegarder les options et valeurs implicites des réglages d'imprimante</A></H1>
+<P>Ce chapitre décrit comment sauvegarder les options pour votre imprimante et définir votre propre imprimante implicite.</P>
+
+<H2><A NAME="5_1">Options d'imprimante</A></H2>
+
+<P>Chaque imprimante prend en charge un grand nombre d'options, que vous avez découvertes dans le
+<A HREF="#STANDARD_OPTIONS"> Chapitre 3, &quot;Options standards d'imprimante&quot;</A>.
+Plutôt qu'indiquer ces options à chaque fois que vous imprimez un fichier, CUPS vous permet de sauvegarder comme
+"implicites" les options pour votre imprimante.</P>
+
+<P>La commande <CODE>lpoptions(1)</CODE> sauvegarde les options de vos imprimantes.
+Comme les commandes <CODE>lp</CODE> et <CODE>lpr</CODE>, elle accepte les options d'imprimantes en utilisant l'argument
+<CODE>-o</CODE>:</P>
+<UL>
+<PRE>
+<B>lpoptions -o media=A4 -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -o media=Legal -o scaling=100 ENTREE</B>
+</PRE>
+</UL>
+<P>Une fois sauvegardées, toute commande <CODE>lp</CODE> ou <CODE>lpr</CODE> les utilisera lorsque vous imprimerez.</P>
+
+<H2><A NAME="5_2">Réglage des options pour une imprimante spécifique</A></H2>
+
+<P>L'exemple précédent montre comment régler les options pour l'imprimante implicite. L'option
+<CODE>-p imprimante</CODE> indique que les options sont pour une autre imprimante:</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -p deskjet -o media=Legal -o scaling=100 ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Visualisation des réglages implicites actuels</A></H2>
+<P>La commande <CODE>lpoptions</CODE> peut également être utilisée pour afficher les options actuelles en n'indiquant
+aucune option sur la ligne de commande:</P>
+<UL>
+<PRE>
+<B>lpoptions ENTREE</B>
+media=A4 sides=two-sided-long-edge
+<B>lpoptions -p deskjet ENTREE</B>
+media=Legal scaling=100
+</PRE>
+</UL>
+<H2><A NAME="5_4">Choix de l'imprimante implicite</A></H2>
+
+<P>L'administrateur définira généralement une imprimante implicite valable pour tout le système et qui sera utilisée par tous.
+Utilisez l'option <CODE>-d imprimante</CODE> pour définir votre propre imprimante implicite:</P>
+<UL>
+<PRE>
+<B>lpoptions -d deskjet ENTREE</B>
+</PRE>
+</UL>
+<P>L'imprimante peut être locale (<CODE>deskjet</CODE>) ou à distance (<CODE>deskjet@serveur</CODE>).</P>
+
+<H2><A NAME="5_5">Instances d'imprimantes</A></H2>
+
+<P>En plus de définir des réglages pour chaque file d'impression, CUPS prend en charge
+les <I>instances d'imprimantes</I> qui vous permettent de définir différents jeux d'options pour chaque imprimante.
+Vous indiquez chaque instante en utilisant le caractère "slash" (<CODE>/</CODE>):</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTREE</B>
+<B>lpoptions -p laserjet/legal -o media=Legal ENTREE</B>
+</PRE>
+</UL>
+<P>Les commandes <CODE>lp</CODE> et <CODE>lpr</CODE> comprennent également la notation:</P>
+<UL>
+<PRE>
+<B>lp -d laserjet/duplex nom_fichier ENTREE</B>
+<B>lpr -P laserjet/legal nom_fichier ENTREE</B>
+</PRE>
+</UL>
+<H2><A NAME="5_6">Retirer des instances d'imprimantes</A></H2>
+
+<P>Utilisez l'option <CODE>-x imprimante/instance</CODE> pour retirer une instance d'imprimante dont vous n'avez plus
+besoin:</P>
+<UL>
+<PRE>
+<B>lpoptions -x laserjet ENTREE</B>
+<B>lpoptions -x laserjet/duplex ENTREE</B>
+<B>lpoptions -x laserjet/legal ENTREE</B>
+</PRE>
+</UL>
+<P>L'option <CODE>-x</CODE> ne retire que les options implicites pour cette instance d'imprimante.
+la file d'impression d'origine demeurera jusqu'à suppression au moyen de la commande
+<CODE>lpadmin(8)</CODE> par l'administrateur.</P>
+
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Licence d'utilisation du logiciel <I>(NdT : en anglais)</I></A></H1>
+<H2 ALIGN="CENTER"><A NAME="6_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P ALIGN="CENTER">Copyright 1997-2003 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3111 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email:<A HREF="mailto:cups-info@cups.org"> cups-info@cups.org</A>
+<BR> WWW:<A HREF="http://www.cups.org"> http://www.cups.org</A></P>
+<H3><A NAME="6_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2. A copy of these
+ licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the
+ &quot;/usr/include/cups&quot; directory and &quot;libcups.a&quot;, &quot;libcups_s.a&quot;,
+ &quot;libcups.sl&quot;, or &quot;libcups.so&quot; files in the binary distributions.</P>
+<P>The GNU GPL applies to the remainder of the CUPS distribution,
+ including the &quot;pstoraster&quot; filter which is based upon GNU Ghostscript
+ 5.50 and the &quot;pdftops&quot; filter which is based upon Xpdf 0.93a.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="6_1_2">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. These names and logos may be used freely
+ in any direct port or binary distribution of CUPS. To use them in
+ derivative products, please contract Easy Software Products for written
+ permission. Our intention is to protect the value of these trademarks
+ and ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="6_1_3">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pstoraster&quot; filter that
+ utilizes the GNU GhostScript 5.50 core to convert PostScript files into
+ a stream of raster images. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Miles Jones
+<BR> Director of Marketing
+<BR> Artifex Software Inc.
+<BR> 454 Las Gallinas Ave., Suite 108
+<BR> San Rafael, CA 94903 USA
+<BR> Voice: +1.415.492.9861
+<BR> Fax: +1.415.492.9862
+<BR> EMail:<A HREF="mailto:info@arsoft.com"> info@arsoft.com</A></BLOCKQUOTE>
+</P>
+<P>The &quot;pdftops&quot; filter is based on the Xpdf 0.93a software. For binary
+ distribution licensing of this software, please contact:<BLOCKQUOTE>
+ Derek B. Noonburg
+<BR> Email:<A HREF="mailto:derekn@foolabs.com"> derekn@foolabs.com</A>
+<BR> WWW:<A HREF="http://www.foolabs.com/xpdf/">
+ http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="6_1_4">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com">http://www.easysw.com</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<PRE>
+
+</PRE>
+<H4>Preamble</H4>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.</LI>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.</LI>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+</LI>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+</LI>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.</LI>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.</LI>
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H4>Preamble</H4>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.</LI>
+<P></P>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<P></P>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.</LI>
+<P></P>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.</LI>
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)</LI>
+<P></P>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.</LI>
+<P></P>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.</LI>
+<P></P>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.</LI>
+<P></P>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+</BODY>
+</HTML>
diff --git a/doc/fr/system-overview.shtml b/doc/fr/system-overview.shtml
new file mode 100644
index 000000000..54b7df5e9
--- /dev/null
+++ b/doc/fr/system-overview.shtml
@@ -0,0 +1,19 @@
+<H2>System Overview</H2>
+
+<P>CUPS provides a portable printing layer for UNIX&reg;-based
+operating systems. It has been developed by
+<A HREF="http://www.easysw.com">Easy Software Products</A> to promote a
+standard printing solution for all UNIX vendors and users. CUPS
+provides the System V and Berkeley command-line interfaces.
+
+<P>CUPS uses the Internet Printing Protocol ("IPP") as the basis for
+managing print jobs and queues. The Line Printer Daemon ("LPD") Server
+Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are
+also supported with reduced functionality. CUPS adds network printer
+browsing and PostScript Printer Description ("PPD") based
+printing options to support real-world printing under UNIX.
+
+<P>CUPS also includes a customized version of GNU Ghostscript
+(currently based off GNU Ghostscript 5.50) and an image file RIP that
+are used to support non-PostScript printers. Sample drivers for HP and
+EPSON printers are included that use these filters.
diff --git a/doc/glossary.shtml b/doc/glossary.shtml
new file mode 100644
index 000000000..2cc0c1c89
--- /dev/null
+++ b/doc/glossary.shtml
@@ -0,0 +1,73 @@
+<H1 TYPE="A" VALUE="1">Glossary</H1>
+
+<H2>Terms</H2>
+
+<DL>
+
+ <DT>C
+ <DD>A computer language.
+
+ <DT>parallel
+ <DD>Sending or receiving data more than 1 bit at a time.
+
+ <DT>pipe
+ <DD>A one-way communications channel between two programs.
+
+ <DT>serial
+ <DD>Sending or receiving data 1 bit at a time.
+
+ <DT>socket
+ <DD>A two-way network communications channel.
+
+</DL>
+
+<H2>Acronyms</H2>
+
+<DL>
+
+ <DT>ASCII
+ <DD>American Standard Code for Information Interchange
+
+ <DT>CUPS
+ <DD>Common UNIX Printing System
+
+ <DT>ESC/P
+ <DD>EPSON Standard Code for Printers
+
+ <DT>FTP
+ <DD>File Transfer Protocol
+
+ <DT>HP-GL
+ <DD>Hewlett-Packard Graphics Language
+
+ <DT>HP-PCL
+ <DD>Hewlett-Packard Page Control Language
+
+ <DT>HP-PJL
+ <DD>Hewlett-Packard Printer Job Language
+
+ <DT>IETF
+ <DD>Internet Engineering Task Force
+
+ <DT>IPP
+ <DD>Internet Printing Protocol
+
+ <DT>ISO
+ <DD>International Standards Organization
+
+ <DT>LPD
+ <DD>Line Printer Daemon
+
+ <DT>MIME
+ <DD>Multimedia Internet Mail Exchange
+
+ <DT>PPD
+ <DD>PostScript Printer Description
+
+ <DT>SMB
+ <DD>Server Message Block
+
+ <DT>TFTP
+ <DD>Trivial File Transfer Protocol
+
+</DL>
diff --git a/doc/idd.html b/doc/idd.html
new file mode 100644
index 000000000..da66758a0
--- /dev/null
+++ b/doc/idd.html
@@ -0,0 +1,1145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Interface Design Description</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-IDD-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511" ALT="CUPS Interface Design Description"><BR>
+<H1>CUPS Interface Design Description</H1></A><BR>
+CUPS-IDD-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+</B><B><A HREF="#2">2 References</A>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+</B><B><A HREF="#3">3 Internal Interfaces</A>
+<UL>
+<LI><A HREF="#3_1">3.1 Character Set Files</A>
+<UL>
+<LI><A HREF="#3_1_1">3.1.1 8-Bit Character Set Files</A></LI>
+<LI><A HREF="#3_1_2">3.1.2 Unicode Character Set Files</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#3_2">3.2 Language Files</A></LI>
+<LI><A HREF="#3_3">3.3 MIME Files</A>
+<UL>
+<LI><A HREF="#3_3_1">3.3.1 mime.types</A></LI>
+<LI><A HREF="#3_3_2">3.3.2 mime.convs</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#3_4">3.4 Option Files</A></LI>
+<LI><A HREF="#3_5">3.5 PostScript Printer Description Files</A>
+<UL>
+<LI><A HREF="#3_5_1">3.5.1 PPD Specification</A></LI>
+<LI><A HREF="#3_5_2">3.5.2 CUPS Extensions to PPD Files</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#3_6">3.6 Scheduler Configuration Files</A>
+<UL>
+<LI><A HREF="#3_6_1">3.6.1 classes.conf</A></LI>
+<LI><A HREF="#3_6_2">3.6.2 cupsd.conf</A></LI>
+<LI><A HREF="#3_6_3">3.6.3 printers.conf</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#4">4 External Interfaces</A>
+<UL>
+<LI><A HREF="#4_1">4.1 AppSocket Protocol</A></LI>
+<LI><A HREF="#4_2">4.2 CUPS Browsing Protocol</A></LI>
+<LI><A HREF="#4_3">4.3 CUPS Form File</A>
+<UL>
+<LI><A HREF="#4_3_1">4.3.1 CUPS Form DTD</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_4">4.4 CUPS PostScript File</A></LI>
+<LI><A HREF="#4_5">4.5 CUPS Raster File</A></LI>
+<LI><A HREF="#4_6">4.6 CUPS Raw Files</A></LI>
+<LI><A HREF="#4_7">4.7 Internet Printing Protocol</A></LI>
+<LI><A HREF="#4_8">4.8 Line Printer Daemon Protocol</A></LI>
+<LI><A HREF="#4_9">4.9 Server Message Block Protocol</A></LI>
+</UL>
+</B><B><A HREF="#5">5 Directories</A></B>
+<BR>
+<BR><B><A HREF="#6">A Glossary</A>
+<UL>
+<LI><A HREF="#6_1">A.1 Terms</A></LI>
+<LI><A HREF="#6_2">A.2 Acronyms</A></LI>
+</UL>
+</B><HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This interface design description document provides detailed file
+ formats, message formats, and program conventions for the Common UNIX
+ Printing System (&quot;CUPS&quot;) Version 1.1.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This interface design description document is organized into the
+ following sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Internal Interfaces</LI>
+<LI>4 - External Interfaces</LI>
+<LI>5 - Directories</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Internal Interfaces</A></H1>
+<H2><A NAME="3_1">3.1 Character Set Files</A></H2>
+<P>The character set files define a mapping between 8-bit characters and
+ the Unicode character set, or between Unicode and printer fonts. They
+ are named using the IETF charset names defined in RFCnnnn. These files
+ are ASCII text, the content of which is described below. Comments can
+ be included by using the <TT>#</TT> character in the first column of a
+ line.</P>
+<H3><A NAME="3_1_1">3.1.1 8-Bit Character Set Files</A></H3>
+<P>8-bit character set files start with a line reading:</P>
+<UL>
+<PRE>
+charset 8bit
+</PRE>
+</UL>
+<P>Following this are lines that define the font information:</P>
+<UL>
+<PRE>
+first last direction width normal bold italic bold-italic
+</PRE>
+</UL>
+<P><VAR>First</VAR> and<VAR> last</VAR> are the first and last glyphs in
+ the font mapping that correspond to that font; a maximum of 256
+ characters can be mapped within each group, with a maximum of 256
+ mappings (this is a PostScript limitation.) The glyph values are
+ hexadecimal.</P>
+<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot;
+ indicating left-to-right, right-to-left, or right-to-left Arabic text.</P>
+<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means
+ that the glyphs are twice as wide as ASCII characters in the Courier
+ typeface.</P>
+<P><VAR>Normal, bold, italic</VAR>, and<VAR> bold-italic</VAR> are the
+ typefaces to use for each presentation. If characters are only
+ available in a single style then only one typeface should be listed
+ (e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded
+ if needed) when printing.</P>
+<P>The remaining lines define a character to Unicode glyph mapping for
+ the character set. The character and glyph values are hexadecimal:</P>
+<UL>
+<PRE>
+xx yyyy
+</PRE>
+</UL>
+<H3><A NAME="3_1_2">3.1.2 Unicode Character Set Files</A></H3>
+<P>Unicode character set files start with a line reading:</P>
+<UL>
+<PRE>
+charset encoding
+</PRE>
+</UL>
+<P><VAR>Encoding</VAR> is the encoding to use for the text; currently
+ only the string &quot;utf8&quot; is supported.</P>
+<P>Following this are lines defining the font information:</P>
+<UL>
+<PRE>
+first last direction width normal bold italic bold-italic
+</PRE>
+</UL>
+<P><VAR>First</VAR> and<VAR> last</VAR> are the first and last glyphs in
+ the font mapping that correspond to that font; a maximum of 256
+ characters can be mapped within each group, with a maximum of 256
+ mappings (this is a PostScript limitation.) The glyph values are
+ hexadecimal.</P>
+<P><VAR>Direction</VAR> is the string &quot;ltor&quot;, &quot;rtol&quot;, or &quot;rtola&quot;
+ indicating left-to-right, right-to-left, or right-to-left Arabic text.</P>
+<P><VAR>Width</VAR> is the string &quot;single&quot; or &quot;double&quot;; double means
+ that the glyphs are twice as wide as ASCII characters in the Courier
+ typeface.</P>
+<P><VAR>Normal, bold, italic</VAR>, and<VAR> bold-italic</VAR> are the
+ typefaces to use for each presentation. If characters are only
+ available in a single style then only one typeface should be listed
+ (e.g. &quot;Symbol&quot;.) Each font that is listed will be used (and downloaded
+ if needed) when printing.</P>
+<H2><A NAME="3_2">3.2 Language Files</A></H2>
+<P>The language files define the default character set and a collection
+ of text messages in that language. They are named by prefixing the
+ string &quot;cups_&quot; to the front of the language specifier (e.g. &quot;cups_en&quot;,
+ &quot;cups_fr&quot;, etc.) Each file consists of two or more lines of ASCII text.</P>
+<P>The first line identifies the character set to be used for the
+ messages. The currently recognized values are:</P>
+<UL>
+<LI>iso-8859-1</LI>
+<LI>iso-8859-2</LI>
+<LI>iso-8859-3</LI>
+<LI>iso-8859-4</LI>
+<LI>iso-8859-5</LI>
+<LI>iso-8859-6</LI>
+<LI>iso-8859-7</LI>
+<LI>iso-8859-8</LI>
+<LI>iso-8859-9</LI>
+<LI>iso-8859-10</LI>
+<LI>iso-8859-13</LI>
+<LI>iso-8859-14</LI>
+<LI>iso-8859-15</LI>
+<LI>us-ascii</LI>
+<LI>utf-8</LI>
+<LI>windows-874</LI>
+<LI>windows-1250</LI>
+<LI>windows-1251</LI>
+<LI>windows-1252</LI>
+<LI>windows-1253</LI>
+<LI>windows-1254</LI>
+<LI>windows-1255</LI>
+<LI>windows-1256</LI>
+<LI>windows-1257</LI>
+<LI>windows-1258</LI>
+<LI>koi8-r</LI>
+<LI>koi8-u</LI>
+</UL>
+<P>The second and succeeding lines define text messages. If the message
+ text is preceded by a number, then the current message number is
+ updated and the text after the number is used.</P>
+<H2><A NAME="3_3">3.3 MIME Files</A></H2>
+<P>CUPS uses two MIME files in its standard configuration.</P>
+<H3><A NAME="3_3_1">3.3.1 mime.types</A></H3>
+<P>The mime.types file defines the recognized file types and consists of
+ 1 or more lines of ASCII text. Comment lines start with the pound (&quot;#&quot;)
+ character. The backslash (&quot;\&quot;) character can be used at the end of a
+ line to continue that line to the next.</P>
+<P>Each non-blank line starts with a MIME type identifier (&quot;super/type&quot;)
+ as registered with the IANA. All text following the MIME type is
+ treated as a series of type recognition rules:</P>
+<UL>
+<PRE>
+mime-type := super &quot;/&quot; type { SP rule }*
+super := { &quot;a-z&quot; | &quot;A-Z&quot; }*
+type := { &quot;a-z&quot; | &quot;A-Z&quot; | &quot;-&quot; | &quot;.&quot; | &quot;0-9&quot; }*
+rule := { extension | match | operator | &quot;(&quot; rule &quot;)&quot; }*
+extension := { &quot;a-z&quot; | &quot;A-Z&quot; | &quot;0-9&quot; }*
+match := &quot;match(&quot; regexp &quot;)&quot; |
+ &quot;ascii(&quot; offset &quot;,&quot; length &quot;)&quot; |
+ &quot;printable(&quot; offset &quot;,&quot; length &quot;)&quot; |
+ &quot;string(&quot; offset &quot;,&quot; string &quot;)&quot; |
+ &quot;contains(&quot; offset &quot;,&quot; length &quot;,&quot; string &quot;)&quot; |
+ &quot;char(&quot; offset &quot;,&quot; value &quot;)&quot; |
+ &quot;short(&quot; offset &quot;,&quot; value &quot;)&quot; |
+ &quot;int(&quot; offset &quot;,&quot; value &quot;)&quot; |
+ &quot;locale(&quot; string &quot;)&quot;
+operator := &quot;+&quot; | [ logical AND ]
+ &quot;,&quot; | SP [ logical OR ]
+ &quot;!&quot; [ unary NOT ]
+</PRE>
+</UL>
+<P>The <CODE>int</CODE> and <CODE>short</CODE> rules match look for
+ integers in network byte order (a.k.a. big-endian) with the
+ most-significant byte first.</P>
+<H3><A NAME="3_3_2">3.3.2 mime.convs</A></H3>
+<P>The mime.types file defines the recognized file filters and consists
+ of 1 or more lines of ASCII text. Comment lines start with the pound
+ (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with two MIME type identifiers
+ (&quot;super/type&quot;) representing the source and destination types. Following
+ the MIME types are a cost value (0 to 100) and the filter program to
+ use. If the filter program is not specified using the full path then it
+ must reside in the CUPS filter directory:</P>
+<UL>
+<PRE>
+super/type SP super/type2 SP cost SP program
+</PRE>
+</UL>
+<H2><A NAME="3_4">3.4 Option Files</A></H2>
+<P>CUPS maintains user-defined printer and option files for each printer
+ and user on the system. The printers and options defined in the system
+ option file (<CODE>/etc/cups/lpoptions</CODE>) are loaded first,
+ followed by the user option file (<CODE>$HOME/.lpoptions</CODE>).
+ Options in the user file replace those defined in the system file for
+ the same destination. Each line in the files can be one of the
+ following:</P>
+<UL>
+<PRE>
+Dest name option=value option=value ... option=value
+Dest name/instance option=value option=value ... option=value
+Default name option=value option=value ... option=value
+Default name/instance option=value option=value ... option=value
+</PRE>
+</UL>
+<P>The line beginning with &quot;Default&quot; indicates the default destination
+ for print jobs; a default line in the user option file overrides the
+ default defined in the system option file.</P>
+<P><VAR>Name</VAR> is the name of a printer known to the local server.</P>
+<P><VAR>Instance</VAR> can be any string of letters, numbers, and the
+ underscore up to 127 characters in length.</P>
+<P>The remainder of the line contains a list of space-separated options
+ and their values.</P>
+<H2><A NAME="3_5">3.5 PostScript Printer Description Files</A></H2>
+<P>PostScript Printer Description (&quot;PPD&quot;) files describe the
+ capabilities of each printer and are used by CUPS to support
+ printer-specific features and intelligent filtering.</P>
+<H3><A NAME="3_5_1">3.5.1 PPD Specification</A></H3>
+<P>The PPD file format is described in <A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+ Adobe TechNote #5003: PostScript Printer Description File Format
+ Specification Version 4.3</A>.</P>
+<H3><A NAME="3_5_2">3.5.2 CUPS Extensions to PPD Files</A></H3>
+<P>CUPS adds several new attributes that are described below.</P>
+<H4>3.5.2.1 cupsFax</H4>
+<P>This optional boolean attributes specifies whether the printer should
+ be treated as a facsimile device, where failed jobs should be retried
+ according to the <TT>FaxRetryInterval</TT> and <TT>FaxRetryLimit</TT>
+ directives in the<VAR> cupsd.conf</VAR> file.</P>
+<H4>3.5.2.2 cupsFilter</H4>
+<P>This optional string attribute provides a conversion rule of the
+ form:</P>
+<UL>
+<PRE>
+source/type cost program
+</PRE>
+</UL>
+<P>The destination type is assumed to the printer's type. If a printer
+ supports the source type directly the special filter program &quot;-&quot; may be
+ specified.</P>
+<H4>3.5.2.3 cupsFlipDuplex</H4>
+<P>This optional boolean attribute notifies the RIP filters that the
+ destination printer requires an upside-down image for the back page.
+ The default value is false.</P>
+<H4>3.5.2.4 cupsManualCopies</H4>
+<P>This optional boolean attribute notifies the RIP filters that the
+ destination printer does not support copy generation in hardware. The
+ default value is false.</P>
+<H4>3.5.2.5 cupsModelNumber</H4>
+<P>This optional integer attribute specifies a printer-specific model
+ number. This number can be used by a filter program to adjust the
+ output for a specific model of printer.</P>
+<H4>3.5.2.6 cupsProfile</H4>
+<P>This optional string attribute specifies a color profile of the form:</P>
+<UL>
+<PRE>
+resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
+</PRE>
+</UL>
+<P>The<I> resolution</I> and<I> type</I> values may be &quot;-&quot; to act as a
+ wildcard. Otherwise they must match one of the <CODE>Resolution</CODE>
+ or <CODE>MediaType</CODE> attributes defined in the PPD file.</P>
+<P>The<I> density</I> and<I> gamma</I> values define gamma and density
+ adjustment function such that:</P>
+<UL>
+<PRE>
+f(x) = density * x<SUP>gamma</SUP>
+</PRE>
+</UL>
+<P>The<I> m00</I> through<I> m22</I> values define a 3x3 transformation
+ matrix for the CMY color values. The density function is applied<I>
+ after</I> the CMY transformation.</P>
+<H4>3.5.2.7 cupsProtocol</H4>
+<P>This optional attribute describes which binary communication protocol
+ to use when printing binary PostScript data. The strings &quot;None&quot;, &quot;BCP&quot;,
+ and &quot;TBCP&quot; are recognized, corresponding to no encoding, BCP, and TBCP
+ respectively.</P>
+<H4>3.5.2.8 cupsVersion</H4>
+<P>This required attribute describes which version of the CUPS IDD was
+ used for the PPD file extensions. Currently it must be the string &quot;1.0&quot;
+ or &quot;1.1&quot;.</P>
+<H2><A NAME="3_6">3.6 Scheduler Configuration Files</A></H2>
+<P>The scheduler reads three configuration files that define the
+ available printers, classes, and services:</P>
+<DL>
+<DT>classes.conf</DT>
+<DD>This file defines all of the printer classes known to the system.</DD>
+<DT>cupsd.conf</DT>
+<DD>This file defines the files, directories, passwords, etc. used by
+ the scheduler.</DD>
+<DT>printers.conf</DT>
+<DD>This file defines all of the printers known to the system.</DD>
+</DL>
+<H3><A NAME="3_6_1">3.6.1 classes.conf</A></H3>
+<P>The classes.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH WIDTH="25%">Directive</TH><TH>Description</TH></TR>
+<TR><TD>&lt;Class name&gt;
+<BR> &lt;/Class&gt;</TD><TD>Surrounds a class definition.</TD></TR>
+<TR><TD>&lt;DefaultClass name&gt;
+<BR> &lt;/Class&gt;</TD><TD>Surrounds a class definition for the default
+ destination.</TD></TR>
+<TR><TD>Accepting</TD><TD>Specifies whether the class is accepting new
+ jobs. May be the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
+<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed to
+ access the class.</TD></TR>
+<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before
+ other files in a job.</TD></TR>
+<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after
+ other files in a job.</TD></TR>
+<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not allowed
+ to access the class.</TD></TR>
+<TR><TD>Info</TD><TD>A textual description of the class.</TD></TR>
+<TR><TD>Location</TD><TD>A textual location of the class.</TD></TR>
+<TR><TD>Printer</TD><TD>Specifies a printer that is a member of the
+ class.</TD></TR>
+<TR><TD>State</TD><TD>Specifies the initial state of the class; can be
+ &quot;Idle&quot; or &quot;Stopped&quot;.</TD></TR>
+<TR><TD>StateMessage</TD><TD>Specifies a textual message for the current
+ class state.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="3_6_2">3.6.2 cupsd.conf</A></H3>
+<P>The cupsd.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH WIDTH="25%">Directive</TH><TH>Default</TH><TH>Description</TH></TR>
+<TR><TD>AccessLog</TD><TD>access_log</TD><TD>Specifies the location of
+ the access log file. The special name &quot;syslog&quot; can be used to send
+ access log information to the system log.</TD></TR>
+<TR><TD>Allow</TD><TD>-</TD><TD>Allows connections from the specified
+ host, network, or domain.</TD></TR>
+<TR><TD>AuthClass</TD><TD>-</TD><TD>Specifies what level of
+ authentication is required; may be &quot;User&quot;, &quot;System&quot;, or &quot;Group&quot;.</TD></TR>
+<TR><TD>AuthType</TD><TD>None</TD><TD>Specifies the type of
+ authentication to perform; may be &quot;None&quot;, &quot;Basic&quot;, or &quot;Digest&quot;.</TD></TR>
+<TR><TD>BrowseAddress</TD><TD>255.255.255.255</TD><TD>Specifies a
+ broadcast address to send CUPS browsing packets to.</TD></TR>
+<TR><TD>BrowseAllow</TD><TD>-</TD><TD>Specifies hosts or addresses from
+ which browsing information should be used.</TD></TR>
+<TR><TD>BrowseDeny</TD><TD>-</TD><TD>Specifies hosts or addresses from
+ which browsing information should not be used.</TD></TR>
+<TR><TD>BrowseInterval</TD><TD>30</TD><TD>Specifies the number of
+ seconds between browsing updates. A browse interval of 0 seconds
+ disables outgoing packets.</TD></TR>
+<TR><TD>BrowseOrder</TD><TD>Allow,Deny</TD><TD>Specifies the order of
+ BrowseAllow and BrowseDeny directive processing; can be &quot;Deny,Allow&quot; to
+ implicitly deny hosts unless they are allowed by a BrowseAllow line, or
+ &quot;Allow,Deny&quot; to implicitly allow hosts unless they are denied by a
+ BrowseDeny line.</TD></TR>
+<TR><TD>BrowsePoll</TD><TD>-</TD><TD>Specifies a server to poll for
+ available printers and classes.</TD></TR>
+<TR><TD>BrowsePort</TD><TD>631</TD><TD>Specifies the UDP port number to
+ use for browse packets.</TD></TR>
+<TR><TD>BrowseRelay</TD><TD>-</TD><TD>Specifies a source and destination
+ address for relaying browser information from one subnet to another.</TD>
+</TR>
+<TR><TD>BrowseShortNames</TD><TD>yes</TD><TD>Specifies whether or not to
+ provide short names (without the &quot;@server&quot; part) for remote printers.</TD>
+</TR>
+<TR><TD>BrowseTimeout</TD><TD>300</TD><TD>Specifies the number of
+ seconds to wait until remote destinations are removed from the local
+ destination list.</TD></TR>
+<TR><TD>Browsing</TD><TD>On</TD><TD>Specifies whether or not printer and
+ class browsing is enabled; can be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
+<TR><TD>DataDir</TD><TD>/usr/share/cups</TD><TD>Specifies the directory
+ where CUPS data files are stored.</TD></TR>
+<TR><TD>DefaultCharset</TD><TD>iso-8859-1</TD><TD>Specifies the default
+ character set.</TD></TR>
+<TR><TD>DefaultLanguage</TD><TD>current locale</TD><TD>Specifies the
+ default language.</TD></TR>
+<TR><TD>Deny</TD><TD>-</TD><TD>Refuses connections from the specified
+ host, network, or domain.</TD></TR>
+<TR><TD>DocumentRoot</TD><TD>/usr/share/doc/cups</TD><TD>Specifies the
+ document data root directory.</TD></TR>
+<TR><TD>ErrorLog</TD><TD>error_log</TD><TD>Specifies the error log file
+ location. The special name &quot;syslog&quot; can be used to send error log
+ information to the system log.</TD></TR>
+<TR><TD>Group</TD><TD>root, sys, system</TD><TD>Specifies the group name
+ or ID that is used when running external programs.</TD></TR>
+<TR><TD>HostNameLookups</TD><TD>Off</TD><TD>Specifies whether or not to
+ perform reverse IP address lookups to get the actual hostname; may be
+ &quot;On&quot; or &quot;Off&quot;. Hostname lookups can significantly degrade the
+ performance of the CUPS server if one or more DNS servers is not
+ functioning properly.</TD></TR>
+<TR><TD>ImplicitClasses</TD><TD>On</TD><TD>Specifies whether or not to
+ automatically create printer classes when more than one printer or
+ class of the same name is detected on the network; may be &quot;On&quot; or
+ &quot;Off&quot;.</TD></TR>
+<TR><TD>KeepAlive</TD><TD>On</TD><TD>Specifies whether or not to use the
+ HTTP Keep-Alive feature; may be &quot;On&quot; or &quot;Off&quot;.</TD></TR>
+<TR><TD>KeepAliveTimeout</TD><TD>30</TD><TD>Specifies the amount of time
+ to keep the HTTP connection alive before closing it.</TD></TR>
+<TR><TD>&lt;Location path&gt;
+<BR> &lt;/Location&gt;</TD><TD>-</TD><TD>Specifies a location to restrict
+ access to.</TD></TR>
+<TR><TD>LogLevel</TD><TD>info</TD><TD>Controls the amount of information
+ that is logged in the error log file. Can be one of &quot;debug&quot;, &quot;info&quot;,
+ &quot;warn&quot;, &quot;error&quot;, or &quot;none&quot;, in decreasing order or verbosity.</TD></TR>
+<TR><TD>MaxClients</TD><TD>100</TD><TD>Specifies the maximum number of
+ simultaneous active clients. This value is internally limited to 1/3 of
+ the total number of available file descriptors.</TD></TR>
+<TR><TD>MaxLogSize</TD><TD>0</TD><TD>Specifies the maximum size of the
+ access, error, and page log files in bytes. If set to 0 then no maximum
+ size is set. Log files are rotated automatically when this size is
+ exceeded.</TD></TR>
+<TR><TD>MaxRequestSize</TD><TD>0</TD><TD>Specifies the maximum size of
+ HTTP requests in bytes. If set to 0 then there is no maximum.</TD></TR>
+<TR><TD>Order</TD><TD>Allow,Deny</TD><TD>Specifies the order of Allow
+ and Deny directive processing; can be &quot;Deny,Allow&quot; to implicitly deny
+ hosts unless they are allowed by an Allow line, or &quot;Allow,Deny&quot; to
+ implicitly allow hosts unless they are denied by a Deny line.</TD></TR>
+<TR><TD>PageLog</TD><TD>page_log</TD><TD>Specifies the location of the
+ page log file. The special name &quot;syslog&quot; can be used to send page log
+ information to the system log.</TD></TR>
+<TR><TD>Port</TD><TD>631</TD><TD>Specifies a port number to listen to
+ for HTTP connections.</TD></TR>
+<TR><TD>Printcap</TD><TD>/etc/printcap</TD><TD>Specifies the location of
+ a Berkeley printcap file to update with a list of current printers and
+ classes. If no filename is supplied then this automatic generation is
+ disabled.</TD></TR>
+<TR><TD>RequestRoot</TD><TD>/var/spool/cups</TD><TD>Specifies the
+ location of request files.</TD></TR>
+<TR><TD>RIPCache</TD><TD>8m</TD><TD>Specifies the size of the memory
+ cache in bytes that is used by RIP filters.</TD></TR>
+<TR><TD>ServerAdmin</TD><TD>root@ServerName</TD><TD>Specifies the person
+ to contact with problems.</TD></TR>
+<TR><TD>ServerName</TD><TD>hostname</TD><TD>Specifies the hostname that
+ is supplied to HTTP clients. This is also used to determine the default
+ CUPS server for the CUPS IPP client applications.</TD></TR>
+<TR><TD>ServerRoot</TD><TD>/etc/cups</TD><TD>Specifies the root
+ directory for server configuration files.</TD></TR>
+<TR><TD>SystemGroup</TD><TD>root, sys, system</TD><TD>Specifies the
+ group name used for System class authentication.</TD></TR>
+<TR><TD>TempDir</TD><TD>/var/tmp</TD><TD>Specifies the temporary
+ directory to use.</TD></TR>
+<TR><TD>Timeout</TD><TD>300</TD><TD>The timeout in seconds before client
+ connections are closed in the middle of a request.</TD></TR>
+<TR><TD>User</TD><TD>lp</TD><TD>Specifies the user that is used when
+ running external programs.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="3_6_3">3.6.3 printers.conf</A></H3>
+<P>The printers.conf file consists of 1 or more lines of ASCII text.
+ Comment lines start with the pound (&quot;#&quot;) character.</P>
+<P>Each non-blank line starts with the name of a configuration directive
+ followed by its value. The following directives are understood:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH WIDTH="25%">Directive</TH><TH>Description</TH></TR>
+<TR><TD>Accepting</TD><TD>Specifies whether the printer is accepting new
+ jobs. May be the names &quot;Yes&quot; or &quot;No&quot;.</TD></TR>
+<TR><TD>&lt;DefaultPrinter name&gt;
+<BR> &lt;/Printer&gt;</TD><TD>Surrounds the printer definition for a default
+ destination.</TD></TR>
+<TR><TD>AllowUsers</TD><TD>Specifies a list of users that are allowed to
+ access the printer.</TD></TR>
+<TR><TD>BannerStart</TD><TD>Specifies the banner that is printed before
+ other files in a job.</TD></TR>
+<TR><TD>BannerEnd</TD><TD>Specifies the banner that is printed after
+ other files in a job.</TD></TR>
+<TR><TD>DenyUsers</TD><TD>Specifies a list of users that are not allowed
+ to access the printer.</TD></TR>
+<TR><TD>DeviceURI</TD><TD>Specifies the device-uri attribute for the
+ printer.</TD></TR>
+<TR><TD>Info</TD><TD>A textual description of the printer.</TD></TR>
+<TR><TD>Location</TD><TD>A textual location of the printer.</TD></TR>
+<TR><TD>&lt;Printer name&gt;
+<BR> &lt;/Printer&gt;</TD><TD>Surrounds the printer definition.</TD></TR>
+<TR><TD>State</TD><TD>Specifies the initial state of the printer; can be
+ &quot;Idle&quot; or &quot;Stopped&quot;.</TD></TR>
+<TR><TD>StateMessage</TD><TD>Specifies a textual message for the current
+ printer state.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1><A NAME="4">4 External Interfaces</A></H1>
+<H2><A NAME="4_1">4.1 AppSocket Protocol</A></H2>
+<P>The AppSocket protocol is an 8-bit clean TCP/IP socket connection.
+ The default IP service port is 9100. The URI method name is &quot;socket&quot;.</P>
+<P>The AppSocket protocol is used by the Hewlett Packard JetDirect
+ network interfaces and print servers, as well as many other vendors'
+ products. See the CUPS Software Administrators Manual for a list of
+ supported products.</P>
+<H2><A NAME="4_2">4.2 CUPS Browsing Protocol</A></H2>
+<P>The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By
+ default this service operates on IP service port 631.</P>
+<P>Each broadcast packet describes the state of a single printer or
+ class and is an ASCII text string of up to 1450 bytes ending with a
+ newline (0x0a). The string is formatted as follows:</P>
+<UL>
+<PRE>
+type SP state SP uri SP &quot;location&quot; SP &quot;info&quot; SP &quot;make-and-model&quot; NL
+</PRE>
+</UL>
+<P><VAR>State, uri, location, info</VAR>, and<VAR> make-and-model</VAR>,
+ correspond to the IPP <CODE>printer-state</CODE>, <CODE>
+printer-uri-supported</CODE>, <CODE>printer-location</CODE>, <CODE>
+printer-info</CODE>, and <CODE>printer-make-and-model</CODE> attributes.</P>
+<P><VAR>Type</VAR> is a hexadecimal number string representing
+ capability/type bits:
+<CENTER>
+<TABLE BORDER="1" WIDTH="40%">
+<TR><TH WIDTH="8%">Bit</TH><TH>Description</TH></TR>
+<TR><TD>0</TD><TD>0 = printer
+<BR> 1 = class</TD></TR>
+<TR><TD>1</TD><TD>0 = local
+<BR> 1 = remote
+<BR> (always 1)</TD></TR>
+<TR><TD>2</TD><TD>1 = can print B&amp;W</TD></TR>
+<TR><TD>3</TD><TD>1 = can print color</TD></TR>
+<TR><TD>4</TD><TD>1 = can duplex</TD></TR>
+<TR><TD>5</TD><TD>1 = can staple</TD></TR>
+<TR><TD>6</TD><TD>1 = can do fast copies</TD></TR>
+<TR><TD>7</TD><TD>1 = can do fast collating</TD></TR>
+<TR><TD>8</TD><TD>1 = can punch holes</TD></TR>
+<TR><TD>9</TD><TD>1 = can cover</TD></TR>
+<TR><TD>10</TD><TD>1 = can bind</TD></TR>
+<TR><TD>11</TD><TD>1 = can sort</TD></TR>
+<TR><TD>12</TD><TD>1 = can print up to 9x14 inches</TD></TR>
+<TR><TD>13</TD><TD>1 = can print up to 18x24 inches</TD></TR>
+<TR><TD>14</TD><TD>1 = can print up to 36x48 inches</TD></TR>
+<TR><TD>15</TD><TD>1 = can print variable sizes</TD></TR>
+<TR><TD>16</TD><TD>1 = is an implicit class (bit 1 must be 0)</TD></TR>
+<TR><TD>17</TD><TD>1 = is the default printer on the network</TD></TR>
+<TR><TD>18</TD><TD>1 = is a fax device</TD></TR>
+<TR><TD>19</TD><TD>1 = printer is rejecting new jobs</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_3">4.3 CUPS Form File</A></H2>
+<P>CUPS Form files are XML files used by the CUPS <CODE>formtops</CODE>
+ filter to produce dynamic banner pages and support preprinted forms.</P>
+<P>The MIME type for CUPS Form files is <CODE>application/vnd.cups-form</CODE>
+.</P>
+<H3><A NAME="4_3_1">4.3.1 CUPS Form DTD</A></H3>
+<P>The following DTD describes the available elements and attributes in
+ a CUPS Form file:
+<CENTER>
+<TABLE BORDER>
+<TR><TD>
+<PRE>
+&lt;!ENTITY % Angle &quot;CDATA&quot; -- angle in degrees --&gt;
+
+&lt;!ENTITY % Color &quot;CDATA&quot; -- a color using sRGB: #RRGGBB as Hex values --&gt;
+
+&lt;!ENTITY % Length &quot;CDATA&quot; -- nn for pixels or nn% for percentage length --&gt;
+
+&lt;!ENTITY % Lengths &quot;CDATA&quot; -- comma-separated Length values --&gt;
+
+&lt;!ENTITY % Text &quot;CDATA&quot;&gt;
+
+&lt;!ENTITY % heading &quot;H1|H2|H3|H4|H5|H6&quot;&gt;
+
+&lt;!ENTITY % preformatted &quot;PRE&quot;&gt;
+
+&lt;!ENTITY % i18n
+ &quot;lang %LanguageCode; #IMPLIED -- language code --
+ dir (ltr|rtl) #IMPLIED -- direction for weak/neutral text --&quot;
+ &gt;
+
+&lt;!ENTITY % attrs &quot;%i18n;&quot;&gt;
+
+&lt;!ENTITY % fontstyle
+ &quot;B | FONT | I | TT&quot;&gt;
+
+&lt;!ENTITY % graphics
+ &quot;BOX | RECT | LINE | POLY | ARC | PIE | TEXT&quot;&gt;
+
+&lt;!ENTITY % insert
+ &quot;IMG | VAR&quot;&gt;
+
+&lt;!-- %inline; covers inline or &quot;text-level&quot; elements --&gt;
+&lt;!ENTITY % inline &quot;#PCDATA | %fontstyle; | %graphics; | %insert;&quot;&gt;
+
+&lt;!ELEMENT (%fontstyle;) - - (%inline;)*&gt;
+&lt;!ATTLIST (%fontstyle;)
+ %attrs; -- %i18n --
+ &gt;
+
+&lt;!ELEMENT BR - O EMPTY -- forced line break --&gt;
+&lt;!ATTLIST BR
+ %attrs; -- %i18n --
+ &gt;
+
+&lt;!ENTITY % block
+ &quot;P | %heading; | %preformatted;&quot;&gt;
+
+&lt;!ENTITY % flow &quot;%block; | %inline;&quot;&gt;
+
+&lt;!ELEMENT PAGE O O (%flow;)+ -- document body --&gt;
+&lt;!ATTLIST PAGE
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ valign (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+ &gt;
+
+&lt;!ELEMENT P - O (%inline;)* -- paragraph --&gt;
+&lt;!ATTLIST P
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ &gt;
+
+&lt;!ELEMENT (%heading;) - - (%inline;)* -- heading --&gt;
+&lt;!ATTLIST (%heading;)
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ &gt;
+
+&lt;!ELEMENT PRE - - (%inline;)* -- preformatted text --&gt;
+&lt;!ATTLIST PRE
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ &gt;
+
+&lt;!ELEMENT BOX - O EMPTY -- unfilled box --&gt;
+&lt;!ATTLIST BOX
+ color %Color; #IMPLIED -- override color --
+ height %Length; #REQUIRED -- height of box --
+ thickness %Length; #IMPLIED -- override line thickness --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ &gt;
+
+&lt;!ELEMENT RECT - O EMPTY -- filled box --&gt;
+&lt;!ATTLIST RECT
+ color %Color; #IMPLIED -- override color --
+ height %Length; #REQUIRED -- height of box --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ &gt;
+
+&lt;!ELEMENT LINE - O EMPTY -- polyline --&gt;
+&lt;!ATTLIST LINE
+ color %Color; #IMPLIED -- override color --
+ thickness %Length; #IMPLIED -- override line thickness --
+ x %Lengths; #REQUIRED -- horizontal positions --
+ y %Lengths; #REQUIRED -- vertical positions --
+ &gt;
+
+&lt;!ELEMENT POLY - O EMPTY -- polygon (filled) --&gt;
+&lt;!ATTLIST POLY
+ color %Color; #IMPLIED -- override color --
+ x %Lengths; #REQUIRED -- horizontal positions --
+ y %Lengths; #REQUIRED -- vertical positions --
+ &gt;
+
+&lt;!ELEMENT ARC - O EMPTY -- unfilled arc --&gt;
+&lt;!ATTLIST ARC
+ color %Color; #IMPLIED -- override color --
+ end %Angle; #IMPLIED -- override end angle --
+ height %Length; #REQUIRED -- height of arc --
+ start %Angle; #IMPLIED -- override start angle --
+ thickness %Length; #IMPLIED -- override line thickness --
+ width %Length; #REQUIRED -- width of arc --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ &gt;
+
+&lt;!ELEMENT PIE - O EMPTY -- filled arc --&gt;
+&lt;!ATTLIST PIE
+ color %Color; #IMPLIED -- override color --
+ end %Angle; #IMPLIED -- override end angle --
+ height %Length; #REQUIRED -- height of arc --
+ start %Angle; #IMPLIED -- override start angle --
+ width %Length; #REQUIRED -- width of arc --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ &gt;
+
+&lt;!ELEMENT TEXT - - (%flow;)* -- text box --&gt;
+&lt;!ATTLIST RECT
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ height %Length; #REQUIRED -- height of box --
+ valign (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ &gt;
+
+
+&lt;!ELEMENT IMG - O EMPTY -- Embedded image --&gt;
+&lt;!ATTLIST IMG
+ %attrs; -- %coreattrs, %i18n, %events --
+ src %URI; #REQUIRED -- URI of image to embed --
+ height %Length; #IMPLIED -- override height --
+ width %Length; #IMPLIED -- override width --
+ &gt;
+
+&lt;!ELEMENT HEAD O O (DEFVAR)* -- document head --&gt;
+&lt;!ATTLIST HEAD
+ %i18n; -- lang, dir --
+ &gt;
+
+&lt;!ELEMENT DEFVAR - O EMPTY -- variable definition --&gt;
+&lt;!ATTLIST DEFVAR
+ name CDATA #REQUIRED -- name
+ value CDATA #REQUIRED -- value
+ &gt;
+
+
+&lt;!ENTITY % html.content &quot;HEAD, PAGE&quot;&gt;
+
+&lt;!ELEMENT CUPSFORM - - (HEAD) (PAGE)+ -- document root element --&gt;
+&lt;!ATTLIST CUPSFORM
+ %i18n; -- lang, dir --
+ &gt;
+</PRE>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_4">4.4 CUPS PostScript File</A></H2>
+<P>CUPS PostScript files are device-dependent Adobe PostScript program
+ files. The PostScript language is described in the <A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+ Adobe PostScript Language Reference Manual, Third Edition</A>.</P>
+<P>The MIME type for CUPS PostScript files is <CODE>
+application/vnd.cups-postscript</CODE>.</P>
+<H2><A NAME="4_5">4.5 CUPS Raster File</A></H2>
+<P>CUPS raster files are device-dependent raster image files that
+ contain a PostScript page device dictionary and device-dependent raster
+ imagery for each page in the document. These files are used to transfer
+ raster data from the PostScript and image file RIPs to device-dependent
+ filters that convert the raster data to a printable format.</P>
+<P>A raster file begins with a four byte synchronization word:
+ 0x52615374 (&quot;RaSt&quot;) for big-endian architectures and 0x74536152
+ (&quot;tSaR&quot;) for little-endian architectures. The writer of the raster file
+ will use the native word order, and the reader is responsible for
+ detecting a reversed word order file and swapping bytes as needed. The
+ CUPS Image Library raster functions perform this function
+ automatically.</P>
+<P>Following the synchronization word are a series of raster pages. Each
+ page starts with a page device dictionary header and is followed
+ immediately by the raster data for that page.
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR><TH WIDTH="10%">Bytes</TH><TH WIDTH="20%">Description</TH><TH>Values</TH>
+</TR>
+<TR><TD>0-63</TD><TD>MediaClass</TD><TD>Nul-terminated ASCII string</TD></TR>
+<TR><TD>64-127</TD><TD>MediaColor</TD><TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR><TD>128-191</TD><TD>MediaType</TD><TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR><TD>192-255</TD><TD>OutputType</TD><TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR><TD>256-259</TD><TD>AdvanceDistance</TD><TD>0 to 2<SUP>32</SUP> - 1
+ points</TD></TR>
+<TR><TD>260-263</TD><TD>AdvanceMedia</TD><TD>0 = Never advance roll
+<BR> 1 = Advance roll after file
+<BR> 2 = Advance roll after job
+<BR> 3 = Advance roll after set
+<BR> 4 = Advance roll after page</TD></TR>
+<TR><TD>264-267</TD><TD>Collate</TD><TD>0 = do not collate copies
+<BR> 1 = collate copies</TD></TR>
+<TR><TD>268-271</TD><TD>CutMedia</TD><TD>0 = Never cut media
+<BR> 1 = Cut roll after file
+<BR> 2 = Cut roll after job
+<BR> 3 = Cut roll after set
+<BR> 4 = Cut roll after page</TD></TR>
+<TR><TD>272-275</TD><TD>Duplex</TD><TD>0 = Print single-sided
+<BR> 1 = Print double-sided</TD></TR>
+<TR><TD>276-283</TD><TD>HWResolution</TD><TD>Horizontal and vertical
+ resolution in dots-per-inch.</TD></TR>
+<TR><TD>284-299</TD><TD>ImagingBoundingBox</TD><TD>Four integers giving
+ the left, bottom, right, and top positions of the page bounding box in
+ points</TD></TR>
+<TR><TD>300-303</TD><TD>InsertSheet</TD><TD>0 = Do not insert separator
+ sheets
+<BR> 1 = Insert separator sheets</TD></TR>
+<TR><TD>304-307</TD><TD>Jog</TD><TD>0 = Do no jog pages
+<BR> 1 = Jog pages after file
+<BR> 2 = Jog pages after job
+<BR> 3 = Jog pages after set</TD></TR>
+<TR><TD>308-311</TD><TD>LeadingEdge</TD><TD>0 = Top edge is first
+<BR> 1 = Right edge is first
+<BR> 2 = Bottom edge is first
+<BR> 3 = Left edge is first</TD></TR>
+<TR><TD>312-319</TD><TD>Margins</TD><TD>Left and bottom origin of image
+ in points</TD></TR>
+<TR><TD>320-323</TD><TD>ManualFeed</TD><TD>0 = Do not manually feed
+ media
+<BR> 1 = Manually feed media</TD></TR>
+<TR><TD>324-327</TD><TD>MediaPosition</TD><TD>Input slot position from 0
+ to N</TD></TR>
+<TR><TD>328-331</TD><TD>MediaWeight</TD><TD>Media weight in grams per
+ meter squared</TD></TR>
+<TR><TD>332-335</TD><TD>MirrorPrint</TD><TD>0 = Do not mirror prints
+<BR> 1 = Mirror prints</TD></TR>
+<TR><TD>336-339</TD><TD>NegativePrint</TD><TD>0 = Do not invert prints
+<BR> 1 = Invert prints</TD></TR>
+<TR><TD>340-343</TD><TD>NumCopies</TD><TD>1 to 2<SUP>32</SUP> - 1</TD></TR>
+<TR><TD>344-347</TD><TD>Orientation</TD><TD>0 = Do not rotate page
+<BR> 1 = Rotate page counter-clockwise
+<BR> 2 = Turn page upside down
+<BR> 3 = Rotate page clockwise</TD></TR>
+<TR><TD>348-351</TD><TD>OutputFaceUp</TD><TD>0 = Output face down
+<BR> 1 = Output face up</TD></TR>
+<TR><TD>352-359</TD><TD>PageSize</TD><TD>Width and length in points</TD></TR>
+<TR><TD>360-363</TD><TD>Separations</TD><TD>0 = Print composite image
+<BR> 1 = Print color separations</TD></TR>
+<TR><TD>364-367</TD><TD>TraySwitch</TD><TD>0 = Do not change trays if
+ selected tray is empty
+<BR> 1 = Change trays if selected tray is empty</TD></TR>
+<TR><TD>368-371</TD><TD>Tumble</TD><TD>0 = Do not rotate even pages when
+ duplexing
+<BR> 1 = Rotate even pages when duplexing</TD></TR>
+<TR><TD>372-375</TD><TD>cupsWidth</TD><TD>Width of page image in pixels</TD>
+</TR>
+<TR><TD>376-379</TD><TD>cupsHeight</TD><TD>Height of page image in
+ pixels</TD></TR>
+<TR><TD>380-383</TD><TD>cupsMediaType</TD><TD>Driver-specific 0 to 2<SUP>
+32</SUP> - 1</TD></TR>
+<TR><TD>384-387</TD><TD>cupsBitsPerColor</TD><TD>1, 2, 4, 8 bits</TD></TR>
+<TR><TD>388-391</TD><TD>cupsBitsPerPixel</TD><TD>1 to 32 bits</TD></TR>
+<TR><TD>392-395</TD><TD>cupsBytesPerLine</TD><TD>1 to 2<SUP>32</SUP> - 1
+ bytes</TD></TR>
+<TR><TD>396-399</TD><TD>cupsColorOrder</TD><TD>0 = chunky pixels (CMYK
+ CMYK CMYK)
+<BR> 1 = banded pixels (CCC MMM YYY KKK)
+<BR> 2 = planar pixels (CCC... MMM... YYY... KKK...)</TD></TR>
+<TR><TD>400-403</TD><TD>cupsColorSpace</TD><TD>0 = white
+<BR> 1 = RGB
+<BR> 2 = RGBA
+<BR> 3 = black
+<BR> 4 = CMY
+<BR> 5 = YMC
+<BR> 6 = CMYK
+<BR> 7 = YMCK
+<BR> 8 = KCMY
+<BR> 9 = KCMYcm
+<BR> 10 = GMCK
+<BR> 11 = GMCS
+<BR> 12 = WHITE
+<BR> 13 = GOLD
+<BR> 14 = SILVER
+<BR> 15 = CIE XYZ
+<BR> 16 = CIE Lab
+<BR> 32 = ICC1
+<BR> 33 = ICC2
+<BR> 34 = ICC3
+<BR> 35 = ICC4
+<BR> 36 = ICC5
+<BR> 37 = ICC6
+<BR> 38 = ICC7
+<BR> 39 = ICC8
+<BR> 40 = ICC9
+<BR> 41 = ICCA (10)
+<BR> 42 = ICCB (11)
+<BR> 43 = ICCC (12)
+<BR> 44 = ICCD (13)
+<BR> 45 = ICCE (14)
+<BR> 46 = ICCF (15)
+<BR></TD></TR>
+<TR><TD>404-407</TD><TD>cupsCompression</TD><TD>Driver-specific 0 to 2<SUP>
+32</SUP> - 1</TD></TR>
+<TR><TD>408-411</TD><TD>cupsRowCount</TD><TD>Driver-specific 0 to 2<SUP>
+32</SUP> - 1</TD></TR>
+<TR><TD>412-415</TD><TD>cupsRowFeed</TD><TD>Driver-specific 0 to 2<SUP>
+32</SUP> - 1</TD></TR>
+<TR><TD>416-419</TD><TD>cupsRowStep</TD><TD>Driver-specific 0 to 2<SUP>
+32</SUP> - 1</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>The MIME type for CUPS Raster files is <CODE>
+application/vnd.cups-raster</CODE>.</P>
+<H2><A NAME="4_6">4.6 CUPS Raw Files</A></H2>
+<P>Raw files are printer-dependent print files that are in a format
+ suitable to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The
+ MIME type for CUPS Raw files is <CODE>application/vnd.cups-raw</CODE>.</P>
+<H2><A NAME="4_7">4.7 Internet Printing Protocol</A></H2>
+<P>The Internet Printing Protocol and the CUPS extensions to it are
+ described in the CUPS Implementation of IPP document.</P>
+<H2><A NAME="4_8">4.8 Line Printer Daemon Protocol</A></H2>
+<P>The Line Printer Daemon (LPD) protocol is described by <A HREF="http://www.ietf.org/rfc/rfc1179.txt">
+RFC 1179: Line Printer Daemon Protocol</A>.</P>
+<P>The URI method name for LPD is &quot;lpd&quot;.</P>
+<H2><A NAME="4_9">4.9 Server Message Block Protocol</A></H2>
+<P>The Server Message Block (SMB) and related Common Internet File
+ System (CIFS) protocols are described at <A HREF="http://anu.samba.org/cifs">
+http://anu.samba.org/cifs</A>.</P>
+<P>The URI method name for SMB is &quot;smb&quot;. Support for this protocol is
+ provided via the SAMBA <CODE>smbspool(1)</CODE> program provided with
+ SAMBA 2.0.6 and higher.</P>
+<H1><A NAME="5">5 Directories</A></H1>
+<DL>
+<DT>/etc/cups</DT>
+<DD>The scheduler configuration and MIME files reside here.</DD>
+<DT>/etc/cups/certs</DT>
+<DD>The authentication certificates reside here.</DD>
+<DT>/etc/cups/interfaces</DT>
+<DD>System V interface scripts reside here.</DD>
+<DT>/etc/cups/ppd</DT>
+<DD>This directory contains PPD files for each printer.</DD>
+<DT>/usr/bin</DT>
+<DD>The <CODE>cancel</CODE>, <CODE>lp</CODE>, <CODE>lpq</CODE>, <CODE>
+lpr</CODE>, <CODE>lprm</CODE>, and <CODE>lpstat</CODE> commands reside
+ here.</DD>
+<DT>/usr/lib, /usr/lib32</DT>
+<DD>The shared libraries (DSOs) reside here.</DD>
+<DT>/usr/lib/cups/backend</DT>
+<DD>The backend filters reside here.</DD>
+<DT>/usr/lib/cups/cgi-bin</DT>
+<DD>The CGI programs reside here.</DD>
+<DT>/usr/lib/cups/daemon</DT>
+<DD>The polling and LPD daemons reside here.</DD>
+<DT>/usr/lib/cups/filter</DT>
+<DD>The file filters reside here.</DD>
+<DT>/usr/sbin</DT>
+<DD>The <CODE>accept</CODE>, <CODE>cupsd</CODE>, <CODE>lpadmin</CODE>, <CODE>
+lpc</CODE>, and <CODE>reject</CODE> commands reside here.</DD>
+<DT>/usr/share/cups</DT>
+<DD>This is the root directory of the CUPS static data.</DD>
+<DT>/usr/share/cups/charsets</DT>
+<DD>The character set files reside here.</DD>
+<DT>/usr/share/cups/data</DT>
+<DD>The filter data files reside here.</DD>
+<DT>/usr/share/cups/fonts</DT>
+<DD>The <CODE>pstoraster</CODE> font files reside here.</DD>
+<DT>/usr/share/cups/model</DT>
+<DD>The sample PPD files reside here.</DD>
+<DT>/usr/share/cups/pstoraster</DT>
+<DD>The <CODE>pstoraster</CODE> data files reside here.</DD>
+<DT>/usr/share/doc/cups</DT>
+<DD>The scheduler documentation files reside here.</DD>
+<DT>/var/log/cups</DT>
+<DD>The <CODE>access_log</CODE>, <CODE>error_log</CODE>, and <CODE>
+page_log</CODE> files reside here.</DD>
+<DT>/var/spool/cups</DT>
+<DD>This directory contains print job files.</DD>
+</DL>
+<H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
+<H2><A NAME="6_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="6_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/idd.pdf b/doc/idd.pdf
new file mode 100644
index 000000000..d55a5e5bd
--- /dev/null
+++ b/doc/idd.pdf
Binary files differ
diff --git a/doc/idd.shtml b/doc/idd.shtml
new file mode 100644
index 000000000..a3a431f4b
--- /dev/null
+++ b/doc/idd.shtml
@@ -0,0 +1,1493 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-IDD-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Interface Design Description</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This interface design description document provides detailed file
+formats, message formats, and program conventions for the Common UNIX
+Printing System ("CUPS") Version 1.1.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This interface design description document is organized into the following
+sections:
+
+<UL>
+ <LI>1 - Scope
+ <LI>2 - References
+ <LI>3 - Internal Interfaces
+ <LI>4 - External Interfaces
+ <LI>5 - Directories
+ <LI>A - Glossary
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Internal Interfaces</H1>
+
+<H2>Character Set Files</H2>
+
+<P>The character set files define a mapping between 8-bit characters
+and the Unicode character set, or between Unicode and printer fonts.
+They are named using the IETF charset names defined in RFCnnnn. These
+files are ASCII text, the content of which is described below. Comments
+can be included by using the <TT>#</TT> character in the first column
+of a line.
+
+<H3>8-Bit Character Set Files</H3>
+
+<P>8-bit character set files start with a line reading:
+
+<UL><PRE>
+charset 8bit
+</PRE></UL>
+
+<P>Following this are lines that define the font information:
+
+<UL><PRE>
+first last direction width normal bold italic bold-italic
+</PRE></UL>
+
+<P><VAR>First</VAR> and <VAR>last</VAR> are the first and last glyphs
+in the font mapping that correspond to that font; a maximum of 256
+characters can be mapped within each group, with a maximum of 256
+mappings (this is a PostScript limitation.) The glyph values are
+hexadecimal.
+
+<P><VAR>Direction</VAR> is the string "ltor", "rtol", or "rtola" indicating
+left-to-right, right-to-left, or right-to-left Arabic text.
+
+<P><VAR>Width</VAR> is the string "single" or "double"; double means that the
+glyphs are twice as wide as ASCII characters in the Courier typeface.
+
+<P><VAR>Normal, bold, italic</VAR>, and <VAR>bold-italic</VAR> are the
+typefaces to use for each presentation. If characters are only available in
+a single style then only one typeface should be listed (e.g. "Symbol".)
+Each font that is listed will be used (and downloaded if needed) when
+printing.
+
+<P>The remaining lines define a character to Unicode glyph mapping for the
+character set. The character and glyph values are hexadecimal:
+
+<UL><PRE>
+xx yyyy
+</PRE></UL>
+
+<H3>Unicode Character Set Files</H3>
+
+<P>Unicode character set files start with a line reading:
+
+<UL><PRE>
+charset encoding
+</PRE></UL>
+
+<P><VAR>Encoding</VAR> is the encoding to use for the text; currently only
+the string "utf8" is supported.
+
+<P>Following this are lines defining the font information:
+
+<UL><PRE>
+first last direction width normal bold italic bold-italic
+</PRE></UL>
+
+<P><VAR>First</VAR> and <VAR>last</VAR> are the first and last glyphs
+in the font mapping that correspond to that font; a maximum of 256
+characters can be mapped within each group, with a maximum of 256
+mappings (this is a PostScript limitation.) The glyph values are
+hexadecimal.
+
+<P><VAR>Direction</VAR> is the string "ltor", "rtol", or "rtola" indicating
+left-to-right, right-to-left, or right-to-left Arabic text.
+
+<P><VAR>Width</VAR> is the string "single" or "double"; double means that the
+glyphs are twice as wide as ASCII characters in the Courier typeface.
+
+<P><VAR>Normal, bold, italic</VAR>, and <VAR>bold-italic</VAR> are the
+typefaces to use for each presentation. If characters are only available in
+a single style then only one typeface should be listed (e.g. "Symbol".)
+Each font that is listed will be used (and downloaded if needed) when
+printing.
+
+<H2>Language Files</H2>
+
+<P>The language files define the default character set and a collection of
+text messages in that language. They are named by prefixing the string "cups_"
+to the front of the language specifier (e.g. "cups_en", "cups_fr", etc.) Each
+file consists of two or more lines of ASCII text.
+
+<P>The first line identifies the character set to be used for the messages.
+The currently recognized values are:
+
+<UL>
+ <LI>iso-8859-1
+ <LI>iso-8859-2
+ <LI>iso-8859-3
+ <LI>iso-8859-4
+ <LI>iso-8859-5
+ <LI>iso-8859-6
+ <LI>iso-8859-7
+ <LI>iso-8859-8
+ <LI>iso-8859-9
+ <LI>iso-8859-10
+ <LI>iso-8859-13
+ <LI>iso-8859-14
+ <LI>iso-8859-15
+ <LI>us-ascii
+ <LI>utf-8
+ <LI>windows-874
+ <LI>windows-1250
+ <LI>windows-1251
+ <LI>windows-1252
+ <LI>windows-1253
+ <LI>windows-1254
+ <LI>windows-1255
+ <LI>windows-1256
+ <LI>windows-1257
+ <LI>windows-1258
+ <LI>koi8-r
+ <LI>koi8-u
+</UL>
+
+<P>The second and succeeding lines define text messages. If the message text
+is preceded by a number, then the current message number is updated and the
+text after the number is used.
+
+<H2>MIME Files</H2>
+
+<P>CUPS uses two MIME files in its standard configuration.
+
+<H3>mime.types</H3>
+
+<P>The mime.types file defines the recognized file types and consists
+of 1 or more lines of ASCII text. Comment lines start with the pound
+("#") character. The backslash ("\") character can be used at the end
+of a line to continue that line to the next.
+
+<P>Each non-blank line starts with a MIME type identifier ("super/type")
+as registered with the IANA. All text following the MIME type is treated as
+a series of type recognition rules:
+
+<UL><PRE>
+mime-type := super "/" type { SP rule }*
+super := { "a-z" | "A-Z" }*
+type := { "a-z" | "A-Z" | "-" | "." | "0-9" }*
+rule := { extension | match | operator | "(" rule ")" }*
+extension := { "a-z" | "A-Z" | "0-9" }*
+match := "match(" regexp ")" |
+ "ascii(" offset "," length ")" |
+ "printable(" offset "," length ")" |
+ "string(" offset "," string ")" |
+ "contains(" offset "," length "," string ")" |
+ "char(" offset "," value ")" |
+ "short(" offset "," value ")" |
+ "int(" offset "," value ")" |
+ "locale(" string ")"
+operator := "+" | [ logical AND ]
+ "," | SP [ logical OR ]
+ "!" [ unary NOT ]
+</PRE></UL>
+
+<P>The <CODE>int</CODE> and <CODE>short</CODE> rules match look for integers
+in network byte order (a.k.a. big-endian) with the most-significant byte first.
+
+<H3>mime.convs</H3>
+
+<P>The mime.types file defines the recognized file filters and consists
+of 1 or more lines of ASCII text. Comment lines start with the pound
+("#") character.
+
+<P>Each non-blank line starts with two MIME type identifiers ("super/type")
+representing the source and destination types. Following the MIME types are
+a cost value (0 to 100) and the filter program to use. If the filter program
+is not specified using the full path then it must reside in the CUPS filter
+directory:
+
+<UL><PRE>
+super/type SP super/type2 SP cost SP program
+</PRE></UL>
+
+<H2>Option Files</H2>
+
+<P>CUPS maintains user-defined printer and option files for each
+printer and user on the system. The printers and options defined in the
+system option file (<CODE>/etc/cups/lpoptions</CODE>) are loaded first,
+followed by the user option file (<CODE>$HOME/.lpoptions</CODE>).
+Options in the user file replace those defined in the system file for
+the same destination. Each line in the files can be one of the
+following:
+
+<UL><PRE>
+Dest name option=value option=value ... option=value
+Dest name/instance option=value option=value ... option=value
+Default name option=value option=value ... option=value
+Default name/instance option=value option=value ... option=value
+</PRE></UL>
+
+<P>The line beginning with "Default" indicates the default destination for
+print jobs; a default line in the user option file overrides the default
+defined in the system option file.
+
+<P><VAR>Name</VAR> is the name of a printer known to the local server.
+
+<P><VAR>Instance</VAR> can be any string of letters, numbers, and the underscore
+up to 127 characters in length.
+
+<P>The remainder of the line contains a list of space-separated options
+and their values.
+
+<H2>PostScript Printer Description Files</H2>
+
+<P>PostScript Printer Description ("PPD") files describe the capabilities
+of each printer and are used by CUPS to support printer-specific features
+and intelligent filtering.
+
+<H3>PPD Specification</H3>
+
+<P>The PPD file format is described in
+<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe TechNote #5003: PostScript Printer Description File Format
+Specification Version 4.3</A>.
+
+<H3>CUPS Extensions to PPD Files</H3>
+
+<P>CUPS adds several new attributes that are described below.
+
+<H4>cupsFax</H4>
+
+<P>This optional boolean attributes specifies whether the
+printer should be treated as a facsimile device, where failed
+jobs should be retried according to the
+<TT>FaxRetryInterval</TT> and <TT>FaxRetryLimit</TT> directives
+in the <VAR>cupsd.conf</VAR> file.
+
+<H4>cupsFilter</H4>
+
+<P>This optional string attribute provides a conversion rule of the form:
+
+<UL><PRE>
+source/type cost program
+</PRE></UL>
+
+<P>The destination type is assumed to the printer's type. If a printer
+supports the source type directly the special filter program "-" may be
+specified.
+
+<H4>cupsFlipDuplex</H4>
+
+<P>This optional boolean attribute notifies the RIP filters that
+the destination printer requires an upside-down image for the
+back page. The default value is false.
+
+<H4>cupsManualCopies</H4>
+
+<P>This optional boolean attribute notifies the RIP filters that
+the destination printer does not support copy generation in
+hardware. The default value is false.
+
+<H4>cupsModelNumber</H4>
+
+<P>This optional integer attribute specifies a printer-specific
+model number. This number can be used by a filter program to
+adjust the output for a specific model of printer.
+
+<H4>cupsProfile</H4>
+
+<P>This optional string attribute specifies a color profile of
+the form:
+
+<UL><PRE>
+resolution/type density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22
+</PRE></UL>
+
+<P>The <I>resolution</I> and <I>type</I> values may be "-" to act as a
+wildcard. Otherwise they must match one of the <CODE>Resolution</CODE> or
+<CODE>MediaType</CODE> attributes defined in the PPD file.
+
+<P>The <I>density</I> and <I>gamma</I> values define gamma and density
+adjustment function such that:
+
+<UL><PRE>
+f(x) = density * x<SUP>gamma</SUP>
+</PRE></UL>
+
+<P>The <I>m00</I> through <I>m22</I> values define a 3x3 transformation
+matrix for the CMY color values. The density function is applied <I>after</I>
+the CMY transformation.
+
+<H4>cupsProtocol</H4>
+
+<P>This optional attribute describes which binary communication
+protocol to use when printing binary PostScript data. The
+strings "None", "BCP", and "TBCP" are recognized, corresponding
+to no encoding, BCP, and TBCP respectively.
+
+<H4>cupsVersion</H4>
+
+<P>This required attribute describes which version of the CUPS IDD was used
+for the PPD file extensions. Currently it must be the string "1.0" or "1.1".
+
+<H2>Scheduler Configuration Files</H2>
+
+<P>The scheduler reads three configuration files that define the available
+printers, classes, and services:
+
+<DL>
+
+ <DT>classes.conf
+ <DD>This file defines all of the printer classes known to the
+ system.
+
+ <DT>cupsd.conf
+ <DD>This file defines the files, directories, passwords, etc.
+ used by the scheduler.
+
+ <DT>printers.conf
+ <DD>This file defines all of the printers known to the system.
+
+</DL>
+
+<H3>classes.conf</H3>
+
+<P>The classes.conf file consists of 1 or more lines of ASCII text.
+Comment lines start with the pound ("#") character.
+
+<P>Each non-blank line starts with the name of a configuration directive
+followed by its value. The following directives are understood:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH WIDTH="25%">Directive</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>&lt;Class name&gt;<BR>
+ &lt;/Class&gt;</TD>
+ <TD>Surrounds a class definition.</TD>
+</TR>
+<TR>
+ <TD>&lt;DefaultClass name&gt;<BR>
+ &lt;/Class&gt;</TD>
+ <TD>Surrounds a class definition for the default destination.</TD>
+</TR>
+<TR>
+ <TD>Accepting</TD>
+ <TD>Specifies whether the class is accepting new jobs. May be
+ the names "Yes" or "No".</TD>
+</TR>
+<TR>
+ <TD>AllowUsers</TD>
+ <TD>Specifies a list of users that are allowed to access the class.</TD>
+</TR>
+<TR>
+ <TD>BannerStart</TD>
+ <TD>Specifies the banner that is printed before other files in a
+ job.</TD>
+</TR>
+<TR>
+ <TD>BannerEnd</TD>
+ <TD>Specifies the banner that is printed after other files in a
+ job.</TD>
+</TR>
+<TR>
+ <TD>DenyUsers</TD>
+ <TD>Specifies a list of users that are not allowed to access the
+ class.</TD>
+</TR>
+<TR>
+ <TD>Info</TD>
+ <TD>A textual description of the class.</TD>
+</TR>
+<TR>
+ <TD>Location</TD>
+ <TD>A textual location of the class.</TD>
+</TR>
+<TR>
+ <TD>Printer</TD>
+ <TD>Specifies a printer that is a member of the class.</TD>
+</TR>
+<TR>
+ <TD>State</TD>
+ <TD>Specifies the initial state of the class; can be "Idle" or
+ "Stopped".</TD>
+</TR>
+<TR>
+ <TD>StateMessage</TD>
+ <TD>Specifies a textual message for the current class state.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>cupsd.conf</H3>
+
+<P>The cupsd.conf file consists of 1 or more lines of ASCII text.
+Comment lines start with the pound ("#") character.
+
+<P>Each non-blank line starts with the name of a configuration directive
+followed by its value. The following directives are understood:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH WIDTH="25%">Directive</TH>
+ <TH>Default</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>AccessLog</TD>
+ <TD>access_log</TD>
+ <TD>Specifies the location of the access log file. The special name
+ "syslog" can be used to send access log information to the system
+ log.</TD>
+</TR>
+<TR>
+ <TD>Allow</TD>
+ <TD>-</TD>
+ <TD>Allows connections from the specified host, network, or
+ domain.</TD>
+</TR>
+<TR>
+ <TD>AuthClass</TD>
+ <TD>-</TD>
+ <TD>Specifies what level of authentication is required; may be
+ "User", "System", or "Group".</TD>
+</TR>
+<TR>
+ <TD>AuthType</TD>
+ <TD>None</TD>
+ <TD>Specifies the type of authentication to perform; may be
+ "None", "Basic", or "Digest".</TD>
+</TR>
+<TR>
+ <TD>BrowseAddress</TD>
+ <TD>255.255.255.255</TD>
+ <TD>Specifies a broadcast address to send CUPS browsing packets to.</TD>
+</TR>
+<TR>
+ <TD>BrowseAllow</TD>
+ <TD>-</TD>
+ <TD>Specifies hosts or addresses from which browsing information
+ should be used.</TD>
+</TR>
+<TR>
+ <TD>BrowseDeny</TD>
+ <TD>-</TD>
+ <TD>Specifies hosts or addresses from which browsing information
+ should not be used.</TD>
+</TR>
+<TR>
+ <TD>BrowseInterval</TD>
+ <TD>30</TD>
+ <TD>Specifies the number of seconds between browsing updates. A
+ browse interval of 0 seconds disables outgoing packets.</TD>
+</TR>
+<TR>
+ <TD>BrowseOrder</TD>
+ <TD>Allow,Deny</TD>
+ <TD>Specifies the order of BrowseAllow and BrowseDeny directive
+ processing; can be "Deny,Allow" to implicitly deny hosts unless
+ they are allowed by a BrowseAllow line, or "Allow,Deny" to
+ implicitly allow hosts unless they are denied by a BrowseDeny
+ line.</TD>
+</TR>
+<TR>
+ <TD>BrowsePoll</TD>
+ <TD>-</TD>
+ <TD>Specifies a server to poll for available printers and classes.</TD>
+</TR>
+<TR>
+ <TD>BrowsePort</TD>
+ <TD>631</TD>
+ <TD>Specifies the UDP port number to use for browse packets.</TD>
+</TR>
+<TR>
+ <TD>BrowseRelay</TD>
+ <TD>-</TD>
+ <TD>Specifies a source and destination address for relaying browser
+ information from one subnet to another.</TD>
+</TR>
+<TR>
+ <TD>BrowseShortNames</TD>
+ <TD>yes</TD>
+ <TD>Specifies whether or not to provide short names (without the
+ "@server" part) for remote printers.</TD>
+</TR>
+<TR>
+ <TD>BrowseTimeout</TD>
+ <TD>300</TD>
+ <TD>Specifies the number of seconds to wait until remote destinations
+ are removed from the local destination list.</TD>
+</TR>
+<TR>
+ <TD>Browsing</TD>
+ <TD>On</TD>
+ <TD>Specifies whether or not printer and class browsing is enabled; can
+ be "On" or "Off".</TD>
+</TR>
+<TR>
+ <TD>DataDir</TD>
+ <TD>/usr/share/cups</TD>
+ <TD>Specifies the directory where CUPS data files are stored.</TD>
+</TR>
+<TR>
+ <TD>DefaultCharset</TD>
+ <TD>iso-8859-1</TD>
+ <TD>Specifies the default character set.</TD>
+</TR>
+<TR>
+ <TD>DefaultLanguage</TD>
+ <TD>current locale</TD>
+ <TD>Specifies the default language.</TD>
+</TR>
+<TR>
+ <TD>Deny</TD>
+ <TD>-</TD>
+ <TD>Refuses connections from the specified host, network, or
+ domain.</TD>
+</TR>
+<TR>
+ <TD>DocumentRoot</TD>
+ <TD>/usr/share/doc/cups</TD>
+ <TD>Specifies the document data root directory.</TD>
+</TR>
+<TR>
+ <TD>ErrorLog</TD>
+ <TD>error_log</TD>
+ <TD>Specifies the error log file location. The special name
+ "syslog" can be used to send error log information to the system
+ log.</TD>
+</TR>
+<TR>
+ <TD>Group</TD>
+ <TD>root, sys, system</TD>
+ <TD>Specifies the group name or ID that is used when running
+ external programs.</TD>
+</TR>
+<TR>
+ <TD>HostNameLookups</TD>
+ <TD>Off</TD>
+ <TD>Specifies whether or not to perform reverse IP address lookups to
+ get the actual hostname; may be "On" or "Off". Hostname lookups can
+ significantly degrade the performance of the CUPS server if one or
+ more DNS servers is not functioning properly.</TD>
+</TR>
+<TR>
+ <TD>ImplicitClasses</TD>
+ <TD>On</TD>
+ <TD>Specifies whether or not to automatically create printer classes
+ when more than one printer or class of the same name is detected on
+ the network; may be "On" or "Off".</TD>
+</TR>
+<TR>
+ <TD>KeepAlive</TD>
+ <TD>On</TD>
+ <TD>Specifies whether or not to use the HTTP Keep-Alive feature; may
+ be "On" or "Off".</TD>
+</TR>
+<TR>
+ <TD>KeepAliveTimeout</TD>
+ <TD>30</TD>
+ <TD>Specifies the amount of time to keep the HTTP connection alive
+ before closing it.</TD>
+</TR>
+<TR>
+ <TD>&lt;Location path&gt;<BR>
+ &lt;/Location&gt;</TD>
+ <TD>-</TD>
+ <TD>Specifies a location to restrict access to.</TD>
+</TR>
+<TR>
+ <TD>LogLevel</TD>
+ <TD>info</TD>
+ <TD>Controls the amount of information that is logged in the
+ error log file. Can be one of "debug", "info", "warn", "error",
+ or "none", in decreasing order or verbosity.</TD>
+</TR>
+<TR>
+ <TD>MaxClients</TD>
+ <TD>100</TD>
+ <TD>Specifies the maximum number of simultaneous active clients.
+ This value is internally limited to 1/3 of the total number of
+ available file descriptors.</TD>
+</TR>
+<TR>
+ <TD>MaxLogSize</TD>
+ <TD>0</TD>
+ <TD>Specifies the maximum size of the access, error, and page
+ log files in bytes. If set to 0 then no maximum size is set.
+ Log files are rotated automatically when this size is
+ exceeded.</TD>
+</TR>
+<TR>
+ <TD>MaxRequestSize</TD>
+ <TD>0</TD>
+ <TD>Specifies the maximum size of HTTP requests in bytes. If set to 0
+ then there is no maximum.</TD>
+</TR>
+<TR>
+ <TD>Order</TD>
+ <TD>Allow,Deny</TD>
+ <TD>Specifies the order of Allow and Deny directive processing; can
+ be "Deny,Allow" to implicitly deny hosts unless they are allowed by
+ an Allow line, or "Allow,Deny" to implicitly allow hosts unless they
+ are denied by a Deny line.</TD>
+</TR>
+<TR>
+ <TD>PageLog</TD>
+ <TD>page_log</TD>
+ <TD>Specifies the location of the page log file. The special name
+ "syslog" can be used to send page log information to the system
+ log.</TD>
+</TR>
+<TR>
+ <TD>Port</TD>
+ <TD>631</TD>
+ <TD>Specifies a port number to listen to for HTTP connections.</TD>
+</TR>
+<TR>
+ <TD>Printcap</TD>
+ <TD>/etc/printcap</TD>
+ <TD>Specifies the location of a Berkeley printcap file to update
+ with a list of current printers and classes. If no filename is
+ supplied then this automatic generation is disabled.</TD>
+</TR>
+<TR>
+ <TD>RequestRoot</TD>
+ <TD>/var/spool/cups</TD>
+ <TD>Specifies the location of request files.</TD>
+</TR>
+<TR>
+ <TD>RIPCache</TD>
+ <TD>8m</TD>
+ <TD>Specifies the size of the memory cache in bytes that is used by
+ RIP filters.</TD>
+</TR>
+<TR>
+ <TD>ServerAdmin</TD>
+ <TD>root@ServerName</TD>
+ <TD>Specifies the person to contact with problems.</TD>
+</TR>
+<TR>
+ <TD>ServerName</TD>
+ <TD>hostname</TD>
+ <TD>Specifies the hostname that is supplied to HTTP clients. This
+ is also used to determine the default CUPS server for the CUPS IPP
+ client applications.</TD>
+</TR>
+<TR>
+ <TD>ServerRoot</TD>
+ <TD>/etc/cups</TD>
+ <TD>Specifies the root directory for server configuration files.</TD>
+</TR>
+<TR>
+ <TD>SystemGroup</TD>
+ <TD>root, sys, system</TD>
+ <TD>Specifies the group name used for System class authentication.</TD>
+</TR>
+<TR>
+ <TD>TempDir</TD>
+ <TD>/var/tmp</TD>
+ <TD>Specifies the temporary directory to use.</TD>
+</TR>
+<TR>
+ <TD>Timeout</TD>
+ <TD>300</TD>
+ <TD>The timeout in seconds before client connections are closed
+ in the middle of a request.</TD>
+</TR>
+<TR>
+ <TD>User</TD>
+ <TD>lp</TD>
+ <TD>Specifies the user that is used when running external programs.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>printers.conf</H3>
+
+<P>The printers.conf file consists of 1 or more lines of ASCII text.
+Comment lines start with the pound ("#") character.
+
+<P>Each non-blank line starts with the name of a configuration directive
+followed by its value. The following directives are understood:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH WIDTH="25%">Directive</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>Accepting</TD>
+ <TD>Specifies whether the printer is accepting new jobs. May be
+ the names "Yes" or "No".</TD>
+</TR>
+<TR>
+ <TD>&lt;DefaultPrinter name&gt;<BR>
+ &lt;/Printer&gt;</TD>
+ <TD>Surrounds the printer definition for a default destination.</TD>
+</TR>
+<TR>
+ <TD>AllowUsers</TD>
+ <TD>Specifies a list of users that are allowed to access the printer.</TD>
+</TR>
+<TR>
+ <TD>BannerStart</TD>
+ <TD>Specifies the banner that is printed before other files in a
+ job.</TD>
+</TR>
+<TR>
+ <TD>BannerEnd</TD>
+ <TD>Specifies the banner that is printed after other files in a
+ job.</TD>
+</TR>
+<TR>
+ <TD>DenyUsers</TD>
+ <TD>Specifies a list of users that are not allowed to access the
+ printer.</TD>
+</TR>
+<TR>
+ <TD>DeviceURI</TD>
+ <TD>Specifies the device-uri attribute for the printer.</TD>
+</TR>
+<TR>
+ <TD>Info</TD>
+ <TD>A textual description of the printer.</TD>
+</TR>
+<TR>
+ <TD>Location</TD>
+ <TD>A textual location of the printer.</TD>
+</TR>
+<TR>
+ <TD>&lt;Printer name&gt;<BR>
+ &lt;/Printer&gt;</TD>
+ <TD>Surrounds the printer definition.</TD>
+</TR>
+<TR>
+ <TD>State</TD>
+ <TD>Specifies the initial state of the printer; can be "Idle" or
+ "Stopped".</TD>
+</TR>
+<TR>
+ <TD>StateMessage</TD>
+ <TD>Specifies a textual message for the current printer state.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H1>External Interfaces</H1>
+
+<H2>AppSocket Protocol</H2>
+
+<P>The AppSocket protocol is an 8-bit clean TCP/IP socket connection.
+The default IP service port is 9100. The URI method name is "socket".
+
+<P>The AppSocket protocol is used by the Hewlett Packard JetDirect
+network interfaces and print servers, as well as many other vendors'
+products. See the CUPS Software Administrators Manual for a list of
+supported products.
+
+<H2>CUPS Browsing Protocol</H2>
+
+<P>The CUPS Browsing Protocol is a UDP/IP-based broadcast service. By default
+this service operates on IP service port 631.
+
+<P>Each broadcast packet describes the state of a single printer or class and
+is an ASCII text string of up to 1450 bytes ending with a newline (0x0a). The
+string is formatted as follows:
+
+<UL><PRE>
+type SP state SP uri SP "location" SP "info" SP "make-and-model" NL
+</PRE></UL>
+
+<P><VAR>State, uri, location, info</VAR>, and <VAR>make-and-model</VAR>,
+correspond to the IPP <CODE>printer-state</CODE>,
+<CODE>printer-uri-supported</CODE>, <CODE>printer-location</CODE>,
+<CODE>printer-info</CODE>, and <CODE>printer-make-and-model</CODE>
+attributes.
+
+<P><VAR>Type</VAR> is a hexadecimal number string representing
+capability/type bits:
+
+<CENTER><TABLE WIDTH="40%" BORDER="1">
+<TR>
+ <TH WIDTH="8%">Bit</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>0</TD>
+ <TD>0 = printer<BR>
+ 1 = class</TD>
+</TR>
+<TR>
+ <TD>1</TD>
+ <TD>0 = local<BR>
+ 1 = remote<BR>
+ (always 1)</TD>
+</TR>
+<TR>
+ <TD>2</TD>
+ <TD>1 = can print B&amp;W</TD>
+</TR>
+<TR>
+ <TD>3</TD>
+ <TD>1 = can print color</TD>
+</TR>
+<TR>
+ <TD>4</TD>
+ <TD>1 = can duplex</TD>
+</TR>
+<TR>
+ <TD>5</TD>
+ <TD>1 = can staple</TD>
+</TR>
+<TR>
+ <TD>6</TD>
+ <TD>1 = can do fast copies</TD>
+</TR>
+<TR>
+ <TD>7</TD>
+ <TD>1 = can do fast collating</TD>
+</TR>
+<TR>
+ <TD>8</TD>
+ <TD>1 = can punch holes</TD>
+</TR>
+<TR>
+ <TD>9</TD>
+ <TD>1 = can cover</TD>
+</TR>
+<TR>
+ <TD>10</TD>
+ <TD>1 = can bind</TD>
+</TR>
+<TR>
+ <TD>11</TD>
+ <TD>1 = can sort</TD>
+</TR>
+<TR>
+ <TD>12</TD>
+ <TD>1 = can print up to 9x14 inches</TD>
+</TR>
+<TR>
+ <TD>13</TD>
+ <TD>1 = can print up to 18x24 inches</TD>
+</TR>
+<TR>
+ <TD>14</TD>
+ <TD>1 = can print up to 36x48 inches</TD>
+</TR>
+<TR>
+ <TD>15</TD>
+ <TD>1 = can print variable sizes</TD>
+</TR>
+<TR>
+ <TD>16</TD>
+ <TD>1 = is an implicit class (bit 1 must be 0)</TD>
+</TR>
+<TR>
+ <TD>17</TD>
+ <TD>1 = is the default printer on the network</TD>
+</TR>
+<TR>
+ <TD>18</TD>
+ <TD>1 = is a fax device</TD>
+</TR>
+<TR>
+ <TD>19</TD>
+ <TD>1 = printer is rejecting new jobs</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>CUPS Form File</H2>
+
+<P>CUPS Form files are XML files used by the CUPS <CODE>formtops</CODE>
+filter to produce dynamic banner pages and support preprinted forms.
+
+<P>The MIME type for CUPS Form files is
+<CODE>application/vnd.cups-form</CODE>.
+
+<H3>CUPS Form DTD</H3>
+
+<P>The following DTD describes the available elements and attributes in
+a CUPS Form file:
+
+<CENTER><TABLE BORDER>
+<TR>
+<TD><PRE>
+&lt;!ENTITY % Angle "CDATA" -- angle in degrees -->
+
+&lt;!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+&lt;!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+
+&lt;!ENTITY % Lengths "CDATA" -- comma-separated Length values -->
+
+&lt;!ENTITY % Text "CDATA">
+
+&lt;!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+&lt;!ENTITY % preformatted "PRE">
+
+&lt;!ENTITY % i18n
+ "lang %LanguageCode; #IMPLIED -- language code --
+ dir (ltr|rtl) #IMPLIED -- direction for weak/neutral text --"
+ >
+
+&lt;!ENTITY % attrs "%i18n;">
+
+&lt;!ENTITY % fontstyle
+ "B | FONT | I | TT">
+
+&lt;!ENTITY % graphics
+ "BOX | RECT | LINE | POLY | ARC | PIE | TEXT">
+
+&lt;!ENTITY % insert
+ "IMG | VAR">
+
+&lt;!-- %inline; covers inline or "text-level" elements -->
+&lt;!ENTITY % inline "#PCDATA | %fontstyle; | %graphics; | %insert;">
+
+&lt;!ELEMENT (%fontstyle;) - - (%inline;)*>
+&lt;!ATTLIST (%fontstyle;)
+ %attrs; -- %i18n --
+ >
+
+&lt;!ELEMENT BR - O EMPTY -- forced line break -->
+&lt;!ATTLIST BR
+ %attrs; -- %i18n --
+ >
+
+&lt;!ENTITY % block
+ "P | %heading; | %preformatted;">
+
+&lt;!ENTITY % flow "%block; | %inline;">
+
+&lt;!ELEMENT PAGE O O (%flow;)+ -- document body -->
+&lt;!ATTLIST PAGE
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ valign (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+ >
+
+&lt;!ELEMENT P - O (%inline;)* -- paragraph -->
+&lt;!ATTLIST P
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ >
+
+&lt;!ELEMENT (%heading;) - - (%inline;)* -- heading -->
+&lt;!ATTLIST (%heading;)
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ >
+
+&lt;!ELEMENT PRE - - (%inline;)* -- preformatted text -->
+&lt;!ATTLIST PRE
+ %attrs; -- %i18n --
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ >
+
+&lt;!ELEMENT BOX - O EMPTY -- unfilled box -->
+&lt;!ATTLIST BOX
+ color %Color; #IMPLIED -- override color --
+ height %Length; #REQUIRED -- height of box --
+ thickness %Length; #IMPLIED -- override line thickness --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ >
+
+&lt;!ELEMENT RECT - O EMPTY -- filled box -->
+&lt;!ATTLIST RECT
+ color %Color; #IMPLIED -- override color --
+ height %Length; #REQUIRED -- height of box --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ >
+
+&lt;!ELEMENT LINE - O EMPTY -- polyline -->
+&lt;!ATTLIST LINE
+ color %Color; #IMPLIED -- override color --
+ thickness %Length; #IMPLIED -- override line thickness --
+ x %Lengths; #REQUIRED -- horizontal positions --
+ y %Lengths; #REQUIRED -- vertical positions --
+ >
+
+&lt;!ELEMENT POLY - O EMPTY -- polygon (filled) -->
+&lt;!ATTLIST POLY
+ color %Color; #IMPLIED -- override color --
+ x %Lengths; #REQUIRED -- horizontal positions --
+ y %Lengths; #REQUIRED -- vertical positions --
+ >
+
+&lt;!ELEMENT ARC - O EMPTY -- unfilled arc -->
+&lt;!ATTLIST ARC
+ color %Color; #IMPLIED -- override color --
+ end %Angle; #IMPLIED -- override end angle --
+ height %Length; #REQUIRED -- height of arc --
+ start %Angle; #IMPLIED -- override start angle --
+ thickness %Length; #IMPLIED -- override line thickness --
+ width %Length; #REQUIRED -- width of arc --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ >
+
+&lt;!ELEMENT PIE - O EMPTY -- filled arc -->
+&lt;!ATTLIST PIE
+ color %Color; #IMPLIED -- override color --
+ end %Angle; #IMPLIED -- override end angle --
+ height %Length; #REQUIRED -- height of arc --
+ start %Angle; #IMPLIED -- override start angle --
+ width %Length; #REQUIRED -- width of arc --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ >
+
+&lt;!ELEMENT TEXT - - (%flow;)* -- text box -->
+&lt;!ATTLIST RECT
+ align (left|center|right) #IMPLIED -- horizontal alignment --
+ height %Length; #REQUIRED -- height of box --
+ valign (top|middle|center|bottom) #IMPLIED -- vertical alignment --
+ width %Length; #REQUIRED -- width of box --
+ x %Length; #REQUIRED -- horizontal position --
+ y %Length; #REQUIRED -- vertical position --
+ >
+
+
+&lt;!ELEMENT IMG - O EMPTY -- Embedded image -->
+&lt;!ATTLIST IMG
+ %attrs; -- %coreattrs, %i18n, %events --
+ src %URI; #REQUIRED -- URI of image to embed --
+ height %Length; #IMPLIED -- override height --
+ width %Length; #IMPLIED -- override width --
+ >
+
+&lt;!ELEMENT HEAD O O (DEFVAR)* -- document head -->
+&lt;!ATTLIST HEAD
+ %i18n; -- lang, dir --
+ >
+
+&lt;!ELEMENT DEFVAR - O EMPTY -- variable definition -->
+&lt;!ATTLIST DEFVAR
+ name CDATA #REQUIRED -- name
+ value CDATA #REQUIRED -- value
+ >
+
+
+&lt;!ENTITY % html.content "HEAD, PAGE">
+
+&lt;!ELEMENT CUPSFORM - - (HEAD) (PAGE)+ -- document root element -->
+&lt;!ATTLIST CUPSFORM
+ %i18n; -- lang, dir --
+ >
+</PRE></TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>CUPS PostScript File</H2>
+
+<P>CUPS PostScript files are device-dependent Adobe PostScript program files.
+The PostScript language is described in the
+<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference Manual, Third Edition</A>.
+
+<P>The MIME type for CUPS PostScript files is
+<CODE>application/vnd.cups-postscript</CODE>.
+
+<H2>CUPS Raster File</H2>
+
+<P>CUPS raster files are device-dependent raster image files that contain a
+PostScript page device dictionary and device-dependent raster imagery for
+each page in the document. These files are used to transfer raster data
+from the PostScript and image file RIPs to device-dependent filters that
+convert the raster data to a printable format.
+
+<P>A raster file begins with a four byte synchronization word: 0x52615374
+("RaSt") for big-endian architectures and 0x74536152 ("tSaR") for little-endian
+architectures. The writer of the raster file will use the native word order,
+and the reader is responsible for detecting a reversed word order file and
+swapping bytes as needed. The CUPS Image Library raster functions perform
+this function automatically.
+
+<P>Following the synchronization word are a series of raster pages. Each page
+starts with a page device dictionary header and is followed immediately by the
+raster data for that page.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1">
+<TR>
+ <TH WIDTH="10%">Bytes</TH>
+ <TH WIDTH="20%">Description</TH>
+ <TH>Values</TH>
+</TR>
+<TR>
+ <TD>0-63</TD>
+ <TD>MediaClass</TD>
+ <TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR>
+ <TD>64-127</TD>
+ <TD>MediaColor</TD>
+ <TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR>
+ <TD>128-191</TD>
+ <TD>MediaType</TD>
+ <TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR>
+ <TD>192-255</TD>
+ <TD>OutputType</TD>
+ <TD>Nul-terminated ASCII string</TD>
+</TR>
+<TR>
+ <TD>256-259</TD>
+ <TD>AdvanceDistance</TD>
+ <TD>0 to 2<SUP>32</SUP> - 1 points</TD>
+</TR>
+<TR>
+ <TD>260-263</TD>
+ <TD>AdvanceMedia</TD>
+ <TD>0 = Never advance roll<BR>
+ 1 = Advance roll after file<BR>
+ 2 = Advance roll after job<BR>
+ 3 = Advance roll after set<BR>
+ 4 = Advance roll after page</TD>
+</TR>
+<TR>
+ <TD>264-267</TD>
+ <TD>Collate</TD>
+ <TD>0 = do not collate copies<BR>
+ 1 = collate copies</TD>
+</TR>
+<TR>
+ <TD>268-271</TD>
+ <TD>CutMedia</TD>
+ <TD>0 = Never cut media<BR>
+ 1 = Cut roll after file<BR>
+ 2 = Cut roll after job<BR>
+ 3 = Cut roll after set<BR>
+ 4 = Cut roll after page</TD>
+</TR>
+<TR>
+ <TD>272-275</TD>
+ <TD>Duplex</TD>
+ <TD>0 = Print single-sided<BR>
+ 1 = Print double-sided</TD>
+</TR>
+<TR>
+ <TD>276-283</TD>
+ <TD>HWResolution</TD>
+ <TD>Horizontal and vertical resolution in dots-per-inch.</TD>
+</TR>
+<TR>
+ <TD>284-299</TD>
+ <TD>ImagingBoundingBox</TD>
+ <TD>Four integers giving the left, bottom, right, and top positions
+ of the page bounding box in points</TD>
+</TR>
+<TR>
+ <TD>300-303</TD>
+ <TD>InsertSheet</TD>
+ <TD>0 = Do not insert separator sheets<BR>
+ 1 = Insert separator sheets</TD>
+</TR>
+<TR>
+ <TD>304-307</TD>
+ <TD>Jog</TD>
+ <TD>0 = Do no jog pages<BR>
+ 1 = Jog pages after file<BR>
+ 2 = Jog pages after job<BR>
+ 3 = Jog pages after set</TD>
+</TR>
+<TR>
+ <TD>308-311</TD>
+ <TD>LeadingEdge</TD>
+ <TD>0 = Top edge is first<BR>
+ 1 = Right edge is first<BR>
+ 2 = Bottom edge is first<BR>
+ 3 = Left edge is first</TD>
+</TR>
+<TR>
+ <TD>312-319</TD>
+ <TD>Margins</TD>
+ <TD>Left and bottom origin of image in points</TD>
+</TR>
+<TR>
+ <TD>320-323</TD>
+ <TD>ManualFeed</TD>
+ <TD>0 = Do not manually feed media<BR>
+ 1 = Manually feed media</TD>
+</TR>
+<TR>
+ <TD>324-327</TD>
+ <TD>MediaPosition</TD>
+ <TD>Input slot position from 0 to N</TD>
+</TR>
+<TR>
+ <TD>328-331</TD>
+ <TD>MediaWeight</TD>
+ <TD>Media weight in grams per meter squared</TD>
+</TR>
+<TR>
+ <TD>332-335</TD>
+ <TD>MirrorPrint</TD>
+ <TD>0 = Do not mirror prints<BR>
+ 1 = Mirror prints</TD>
+</TR>
+<TR>
+ <TD>336-339</TD>
+ <TD>NegativePrint</TD>
+ <TD>0 = Do not invert prints<BR>
+ 1 = Invert prints</TD>
+</TR>
+<TR>
+ <TD>340-343</TD>
+ <TD>NumCopies</TD>
+ <TD>1 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+<TR>
+ <TD>344-347</TD>
+ <TD>Orientation</TD>
+ <TD>0 = Do not rotate page<BR>
+ 1 = Rotate page counter-clockwise<BR>
+ 2 = Turn page upside down<BR>
+ 3 = Rotate page clockwise</TD>
+</TR>
+<TR>
+ <TD>348-351</TD>
+ <TD>OutputFaceUp</TD>
+ <TD>0 = Output face down<BR>
+ 1 = Output face up</TD>
+</TR>
+<TR>
+ <TD>352-359</TD>
+ <TD>PageSize</TD>
+ <TD>Width and length in points</TD>
+</TR>
+<TR>
+ <TD>360-363</TD>
+ <TD>Separations</TD>
+ <TD>0 = Print composite image<BR>
+ 1 = Print color separations</TD>
+</TR>
+<TR>
+ <TD>364-367</TD>
+ <TD>TraySwitch</TD>
+ <TD>0 = Do not change trays if selected tray is empty<BR>
+ 1 = Change trays if selected tray is empty</TD>
+</TR>
+<TR>
+ <TD>368-371</TD>
+ <TD>Tumble</TD>
+ <TD>0 = Do not rotate even pages when duplexing<BR>
+ 1 = Rotate even pages when duplexing</TD>
+</TR>
+<TR>
+ <TD>372-375</TD>
+ <TD>cupsWidth</TD>
+ <TD>Width of page image in pixels</TD>
+</TR>
+<TR>
+ <TD>376-379</TD>
+ <TD>cupsHeight</TD>
+ <TD>Height of page image in pixels</TD>
+</TR>
+<TR>
+ <TD>380-383</TD>
+ <TD>cupsMediaType</TD>
+ <TD>Driver-specific 0 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+<TR>
+ <TD>384-387</TD>
+ <TD>cupsBitsPerColor</TD>
+ <TD>1, 2, 4, 8 bits</TD>
+</TR>
+<TR>
+ <TD>388-391</TD>
+ <TD>cupsBitsPerPixel</TD>
+ <TD>1 to 32 bits</TD>
+</TR>
+<TR>
+ <TD>392-395</TD>
+ <TD>cupsBytesPerLine</TD>
+ <TD>1 to 2<SUP>32</SUP> - 1 bytes</TD>
+</TR>
+<TR>
+ <TD>396-399</TD>
+ <TD>cupsColorOrder</TD>
+ <TD>0 = chunky pixels (CMYK CMYK CMYK)<BR>
+ 1 = banded pixels (CCC MMM YYY KKK)<BR>
+ 2 = planar pixels (CCC... MMM... YYY... KKK...)</TD>
+</TR>
+<TR>
+ <TD>400-403</TD>
+ <TD>cupsColorSpace</TD>
+ <TD>0 = white<BR>
+ 1 = RGB<BR>
+ 2 = RGBA<BR>
+ 3 = black<BR>
+ 4 = CMY<BR>
+ 5 = YMC<BR>
+ 6 = CMYK<BR>
+ 7 = YMCK<BR>
+ 8 = KCMY<BR>
+ 9 = KCMYcm<BR>
+ 10 = GMCK<BR>
+ 11 = GMCS<BR>
+ 12 = WHITE<BR>
+ 13 = GOLD<BR>
+ 14 = SILVER<BR>
+ 15 = CIE XYZ<BR>
+ 16 = CIE Lab<BR>
+ 32 = ICC1<BR>
+ 33 = ICC2<BR>
+ 34 = ICC3<BR>
+ 35 = ICC4<BR>
+ 36 = ICC5<BR>
+ 37 = ICC6<BR>
+ 38 = ICC7<BR>
+ 39 = ICC8<BR>
+ 40 = ICC9<BR>
+ 41 = ICCA (10)<BR>
+ 42 = ICCB (11)<BR>
+ 43 = ICCC (12)<BR>
+ 44 = ICCD (13)<BR>
+ 45 = ICCE (14)<BR>
+ 46 = ICCF (15)<BR>
+ </TD>
+</TR>
+<TR>
+ <TD>404-407</TD>
+ <TD>cupsCompression</TD>
+ <TD>Driver-specific 0 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+<TR>
+ <TD>408-411</TD>
+ <TD>cupsRowCount</TD>
+ <TD>Driver-specific 0 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+<TR>
+ <TD>412-415</TD>
+ <TD>cupsRowFeed</TD>
+ <TD>Driver-specific 0 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+<TR>
+ <TD>416-419</TD>
+ <TD>cupsRowStep</TD>
+ <TD>Driver-specific 0 to 2<SUP>32</SUP> - 1</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>The MIME type for CUPS Raster files is
+<CODE>application/vnd.cups-raster</CODE>.
+
+<H2>CUPS Raw Files</H2>
+
+<P>Raw files are printer-dependent print files that are in a format suitable
+to the destination printer (e.g. HP-PCL, HP-RTL, etc.) The MIME type for CUPS
+Raw files is <CODE>application/vnd.cups-raw</CODE>.
+
+<H2>Internet Printing Protocol</H2>
+
+<P>The Internet Printing Protocol and the CUPS extensions to it are
+described in the CUPS Implementation of IPP document.
+
+<H2>Line Printer Daemon Protocol</H2>
+
+<P>The Line Printer Daemon (LPD) protocol is described by
+<A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179: Line Printer Daemon
+Protocol</A>.
+
+<P>The URI method name for LPD is "lpd".
+
+<H2>Server Message Block Protocol</H2>
+
+<P>The Server Message Block (SMB) and related Common Internet File
+System (CIFS) protocols are described at
+<A HREF="http://anu.samba.org/cifs">http://anu.samba.org/cifs</A>.
+
+<P>The URI method name for SMB is "smb". Support for this protocol is
+provided via the SAMBA <CODE>smbspool(1)</CODE> program provided with
+SAMBA 2.0.6 and higher.
+
+<H1>Directories</H1>
+
+<DL>
+
+ <DT>/etc/cups
+ <DD>The scheduler configuration and MIME files reside here.
+
+ <DT>/etc/cups/certs
+ <DD>The authentication certificates reside here.
+
+ <DT>/etc/cups/interfaces
+ <DD>System V interface scripts reside here.
+
+ <DT>/etc/cups/ppd
+ <DD>This directory contains PPD files for each printer.
+
+ <DT>/usr/bin
+ <DD>The <CODE>cancel</CODE>, <CODE>lp</CODE>, <CODE>lpq</CODE>,
+ <CODE>lpr</CODE>, <CODE>lprm</CODE>, and <CODE>lpstat</CODE> commands
+ reside here.
+
+ <DT>/usr/lib, /usr/lib32
+ <DD>The shared libraries (DSOs) reside here.
+
+ <DT>/usr/lib/cups/backend
+ <DD>The backend filters reside here.
+
+ <DT>/usr/lib/cups/cgi-bin
+ <DD>The CGI programs reside here.
+
+ <DT>/usr/lib/cups/daemon
+ <DD>The polling and LPD daemons reside here.
+
+ <DT>/usr/lib/cups/filter
+ <DD>The file filters reside here.
+
+ <DT>/usr/sbin
+ <DD>The <CODE>accept</CODE>, <CODE>cupsd</CODE>,
+ <CODE>lpadmin</CODE>, <CODE>lpc</CODE>, and <CODE>reject</CODE>
+ commands reside here.
+
+ <DT>/usr/share/cups
+ <DD>This is the root directory of the CUPS static data.
+
+ <DT>/usr/share/cups/charsets
+ <DD>The character set files reside here.
+
+ <DT>/usr/share/cups/data
+ <DD>The filter data files reside here.
+
+ <DT>/usr/share/cups/fonts
+ <DD>The <CODE>pstoraster</CODE> font files reside here.
+
+ <DT>/usr/share/cups/model
+ <DD>The sample PPD files reside here.
+
+ <DT>/usr/share/cups/pstoraster
+ <DD>The <CODE>pstoraster</CODE> data files reside here.
+
+ <DT>/usr/share/doc/cups
+ <DD>The scheduler documentation files reside here.
+
+ <DT>/var/log/cups
+ <DD>The <CODE>access_log</CODE>, <CODE>error_log</CODE>, and
+ <CODE>page_log</CODE> files reside here.
+
+ <DT>/var/spool/cups
+ <DD>This directory contains print job files.
+
+</DL>
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/images/accept-jobs.gif b/doc/images/accept-jobs.gif
new file mode 100644
index 000000000..9da7a0dce
--- /dev/null
+++ b/doc/images/accept-jobs.gif
Binary files differ
diff --git a/doc/images/add-class.gif b/doc/images/add-class.gif
new file mode 100644
index 000000000..0f43a6fcd
--- /dev/null
+++ b/doc/images/add-class.gif
Binary files differ
diff --git a/doc/images/add-printer.gif b/doc/images/add-printer.gif
new file mode 100644
index 000000000..90d17eb3f
--- /dev/null
+++ b/doc/images/add-printer.gif
Binary files differ
diff --git a/doc/images/cancel-job.gif b/doc/images/cancel-job.gif
new file mode 100644
index 000000000..3cc1e23bc
--- /dev/null
+++ b/doc/images/cancel-job.gif
Binary files differ
diff --git a/doc/images/classes.gif b/doc/images/classes.gif
new file mode 100644
index 000000000..ace15df98
--- /dev/null
+++ b/doc/images/classes.gif
Binary files differ
diff --git a/doc/images/config-printer.gif b/doc/images/config-printer.gif
new file mode 100644
index 000000000..22849db7d
--- /dev/null
+++ b/doc/images/config-printer.gif
Binary files differ
diff --git a/doc/images/continue.gif b/doc/images/continue.gif
new file mode 100644
index 000000000..ff774adb3
--- /dev/null
+++ b/doc/images/continue.gif
Binary files differ
diff --git a/doc/images/cups-block-diagram.gif b/doc/images/cups-block-diagram.gif
new file mode 100644
index 000000000..2fe505e44
--- /dev/null
+++ b/doc/images/cups-block-diagram.gif
Binary files differ
diff --git a/doc/images/cups-large.gif b/doc/images/cups-large.gif
new file mode 100644
index 000000000..fc66ef07c
--- /dev/null
+++ b/doc/images/cups-large.gif
Binary files differ
diff --git a/doc/images/cups-medium.gif b/doc/images/cups-medium.gif
new file mode 100644
index 000000000..c45ed6ab9
--- /dev/null
+++ b/doc/images/cups-medium.gif
Binary files differ
diff --git a/doc/images/cups-small.gif b/doc/images/cups-small.gif
new file mode 100644
index 000000000..6adb4a29f
--- /dev/null
+++ b/doc/images/cups-small.gif
Binary files differ
diff --git a/doc/images/delete-class.gif b/doc/images/delete-class.gif
new file mode 100644
index 000000000..81b1465ac
--- /dev/null
+++ b/doc/images/delete-class.gif
Binary files differ
diff --git a/doc/images/delete-printer.gif b/doc/images/delete-printer.gif
new file mode 100644
index 000000000..41ce85d78
--- /dev/null
+++ b/doc/images/delete-printer.gif
Binary files differ
diff --git a/doc/images/hold-job.gif b/doc/images/hold-job.gif
new file mode 100644
index 000000000..ebd448ae9
--- /dev/null
+++ b/doc/images/hold-job.gif
Binary files differ
diff --git a/doc/images/left.gif b/doc/images/left.gif
new file mode 100644
index 000000000..fd7b04104
--- /dev/null
+++ b/doc/images/left.gif
Binary files differ
diff --git a/doc/images/logo.gif b/doc/images/logo.gif
new file mode 100644
index 000000000..9999795ca
--- /dev/null
+++ b/doc/images/logo.gif
Binary files differ
diff --git a/doc/images/manage-classes.gif b/doc/images/manage-classes.gif
new file mode 100644
index 000000000..69d5b0147
--- /dev/null
+++ b/doc/images/manage-classes.gif
Binary files differ
diff --git a/doc/images/manage-jobs.gif b/doc/images/manage-jobs.gif
new file mode 100644
index 000000000..adaff856f
--- /dev/null
+++ b/doc/images/manage-jobs.gif
Binary files differ
diff --git a/doc/images/manage-printers.gif b/doc/images/manage-printers.gif
new file mode 100644
index 000000000..cd897291d
--- /dev/null
+++ b/doc/images/manage-printers.gif
Binary files differ
diff --git a/doc/images/modify-class.gif b/doc/images/modify-class.gif
new file mode 100644
index 000000000..58a0ead82
--- /dev/null
+++ b/doc/images/modify-class.gif
Binary files differ
diff --git a/doc/images/modify-printer.gif b/doc/images/modify-printer.gif
new file mode 100644
index 000000000..593b5f881
--- /dev/null
+++ b/doc/images/modify-printer.gif
Binary files differ
diff --git a/doc/images/navbar.gif b/doc/images/navbar.gif
new file mode 100644
index 000000000..c19f634c0
--- /dev/null
+++ b/doc/images/navbar.gif
Binary files differ
diff --git a/doc/images/navbar.xcf.gz b/doc/images/navbar.xcf.gz
new file mode 100644
index 000000000..28438a6bb
--- /dev/null
+++ b/doc/images/navbar.xcf.gz
Binary files differ
diff --git a/doc/images/print-test-page.gif b/doc/images/print-test-page.gif
new file mode 100644
index 000000000..807dca10e
--- /dev/null
+++ b/doc/images/print-test-page.gif
Binary files differ
diff --git a/doc/images/printer-idle.gif b/doc/images/printer-idle.gif
new file mode 100644
index 000000000..68d990c62
--- /dev/null
+++ b/doc/images/printer-idle.gif
Binary files differ
diff --git a/doc/images/printer-processing.gif b/doc/images/printer-processing.gif
new file mode 100644
index 000000000..a9a23f795
--- /dev/null
+++ b/doc/images/printer-processing.gif
Binary files differ
diff --git a/doc/images/printer-stopped.gif b/doc/images/printer-stopped.gif
new file mode 100644
index 000000000..76f45649b
--- /dev/null
+++ b/doc/images/printer-stopped.gif
Binary files differ
diff --git a/doc/images/reject-jobs.gif b/doc/images/reject-jobs.gif
new file mode 100644
index 000000000..6d938e308
--- /dev/null
+++ b/doc/images/reject-jobs.gif
Binary files differ
diff --git a/doc/images/release-job.gif b/doc/images/release-job.gif
new file mode 100644
index 000000000..a05cd9cc7
--- /dev/null
+++ b/doc/images/release-job.gif
Binary files differ
diff --git a/doc/images/restart-job.gif b/doc/images/restart-job.gif
new file mode 100644
index 000000000..a007efc5b
--- /dev/null
+++ b/doc/images/restart-job.gif
Binary files differ
diff --git a/doc/images/right.gif b/doc/images/right.gif
new file mode 100644
index 000000000..8ae8213ce
--- /dev/null
+++ b/doc/images/right.gif
Binary files differ
diff --git a/doc/images/set-as-default.gif b/doc/images/set-as-default.gif
new file mode 100644
index 000000000..1a5b8adca
--- /dev/null
+++ b/doc/images/set-as-default.gif
Binary files differ
diff --git a/doc/images/show-active.gif b/doc/images/show-active.gif
new file mode 100644
index 000000000..d232ef9f8
--- /dev/null
+++ b/doc/images/show-active.gif
Binary files differ
diff --git a/doc/images/show-completed.gif b/doc/images/show-completed.gif
new file mode 100644
index 000000000..efd206cd5
--- /dev/null
+++ b/doc/images/show-completed.gif
Binary files differ
diff --git a/doc/images/start-class.gif b/doc/images/start-class.gif
new file mode 100644
index 000000000..2b6f43fad
--- /dev/null
+++ b/doc/images/start-class.gif
Binary files differ
diff --git a/doc/images/start-printer.gif b/doc/images/start-printer.gif
new file mode 100644
index 000000000..017bb394a
--- /dev/null
+++ b/doc/images/start-printer.gif
Binary files differ
diff --git a/doc/images/stop-class.gif b/doc/images/stop-class.gif
new file mode 100644
index 000000000..5cb7adfd8
--- /dev/null
+++ b/doc/images/stop-class.gif
Binary files differ
diff --git a/doc/images/stop-printer.gif b/doc/images/stop-printer.gif
new file mode 100644
index 000000000..b3accf3df
--- /dev/null
+++ b/doc/images/stop-printer.gif
Binary files differ
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 000000000..582e32471
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,36 @@
+<HTML>
+<HEAD>
+ <TITLE>Common UNIX Printing System</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,10,50,20" HREF="http://www.easysw.com" ALT="Easy Software Products Home Page">
+ <AREA SHAPE="RECT" COORDS="82,10,196,20" HREF="/admin" ALT="Do Administration Tasks">
+ <AREA SHAPE="RECT" COORDS="216,10,280,20" HREF="/classes" ALT="Manage Printer Classes Status">
+ <AREA SHAPE="RECT" COORDS="300,10,336,20" HREF="/documentation.html" ALT="On-Line Help">
+ <AREA SHAPE="RECT" COORDS="356,10,394,20" HREF="/jobs" ALT="Manage Jobs">
+ <AREA SHAPE="RECT" COORDS="414,10,476,20" HREF="/printers" ALT="Manage Printers">
+ <AREA SHAPE="RECT" COORDS="496,10,568,20" HREF="http://www.cups.org" ALT="Download the Current CUPS Software">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="583" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1><A HREF="admin">Do Administration Tasks</A></H1>
+<H1><A HREF="classes">Manage Printer Classes</A></H1>
+<H1><A HREF="documentation.html">On-Line Help</A></H1>
+<H1><A HREF="jobs">Manage Jobs</A></H1>
+<H1><A HREF="printers">Manage Printers</A></H1>
+<H1><A HREF="http://www.cups.org">Download the Current CUPS Software</A></H1>
+
+<HR>
+
+<P>The Common UNIX Printing System, CUPS, and the CUPS logo are the
+trademark property of <A HREF="http://www.easysw.com">Easy Software
+Products</A>. CUPS is copyright 1997-2003 by Easy Software Products,
+All Rights Reserved.
+
+</BODY>
+</HTML>
diff --git a/doc/ipp.html b/doc/ipp.html
new file mode 100644
index 000000000..3801021f3
--- /dev/null
+++ b/doc/ipp.html
@@ -0,0 +1,1566 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Implementation of IPP</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004 All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-IPP-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Implementation of IPP</H1></A><BR>
+CUPS-IPP-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004 All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Overview</A></B>
+<UL>
+<LI><A HREF="#3_1">3.1 IPP URIs</A></LI>
+<LI><A HREF="#3_2">3.2 CUPS IPP Operations</A></LI>
+</UL>
+<B><A HREF="#4">4 Operations</A></B>
+<UL>
+<LI><A HREF="#4_1">4.1 Print-Job Operation</A></LI>
+<UL>
+<LI><A HREF="#4_1_1">4.1.1 Print-Job Request</A></LI>
+<LI><A HREF="#4_1_2">4.1.2 Print-Job Response</A></LI>
+</UL>
+<LI><A HREF="#4_2">4.2 Create-Job Operation</A></LI>
+<UL>
+<LI><A HREF="#4_2_1">4.2.1 Create-Job Request</A></LI>
+<LI><A HREF="#4_2_2">4.2.2 Create-Job Response</A></LI>
+</UL>
+<LI><A HREF="#4_3">4.3 Set-Job-Attributes Operation</A></LI>
+<UL>
+<LI><A HREF="#4_3_1">4.3.1 Set-Job-Attributes Request</A></LI>
+<LI><A HREF="#4_3_2">4.3.2 Set-Job-Attributes Response</A></LI>
+</UL>
+<LI><A HREF="#4_4">4.4 CUPS-Get-Default Operation</A></LI>
+<UL>
+<LI><A HREF="#4_4_1">4.4.1 CUPS-Get-Default Request</A></LI>
+<LI><A HREF="#4_4_2">4.4.2 CUPS-Get-Default Response</A></LI>
+</UL>
+<LI><A HREF="#4_5">4.5 CUPS-Get-Printers Operation</A></LI>
+<UL>
+<LI><A HREF="#4_5_1">4.5.1 CUPS-Get-Printers Request</A></LI>
+<LI><A HREF="#4_5_2">4.5.2 CUPS-Get-Printers Response</A></LI>
+</UL>
+<LI><A HREF="#4_6">4.6 CUPS-Add-Modify-Printer Operation</A></LI>
+<UL>
+<LI><A HREF="#4_6_1">4.6.1 CUPS-Add-Modify-Printer Request</A></LI>
+<LI><A HREF="#4_6_2">4.6.2 CUPS-Add-Modify-Printer Response</A></LI>
+</UL>
+<LI><A HREF="#4_7">4.7 CUPS-Delete-Printer Operation</A></LI>
+<UL>
+<LI><A HREF="#4_7_1">4.7.1 CUPS-Delete-Printer Request</A></LI>
+<LI><A HREF="#4_7_2">4.7.2 CUPS-Delete-Printer Response</A></LI>
+</UL>
+<LI><A HREF="#4_8">4.8 CUPS-Get-Classes Operation</A></LI>
+<UL>
+<LI><A HREF="#4_8_1">4.8.1 CUPS-Get-Classes Request</A></LI>
+<LI><A HREF="#4_8_2">4.8.2 CUPS-Get-Classes Response</A></LI>
+</UL>
+<LI><A HREF="#4_9">4.9 CUPS-Add-Modify-Class Operation</A></LI>
+<UL>
+<LI><A HREF="#4_9_1">4.9.1 CUPS-Add-Modify-Class Request</A></LI>
+<LI><A HREF="#4_9_2">4.9.2 CUPS-Add-Modify-Class Response</A></LI>
+</UL>
+<LI><A HREF="#4_10">4.10 CUPS-Delete-Class Operation</A></LI>
+<UL>
+<LI><A HREF="#4_10_1">4.10.1 CUPS-Delete-Class Request</A></LI>
+<LI><A HREF="#4_10_2">4.10.2 CUPS-Delete-Class Response</A></LI>
+</UL>
+<LI><A HREF="#4_11">4.11 CUPS-Accept-Jobs Operation</A></LI>
+<UL>
+<LI><A HREF="#4_11_1">4.11.1 CUPS-Accept-Jobs Request</A></LI>
+<LI><A HREF="#4_11_2">4.11.2 CUPS-Accept-Jobs Response</A></LI>
+</UL>
+<LI><A HREF="#4_12">4.12 CUPS-Reject-Jobs Operation</A></LI>
+<UL>
+<LI><A HREF="#4_12_1">4.12.1 CUPS-Reject-Jobs Request</A></LI>
+<LI><A HREF="#4_12_2">4.12.2 CUPS-Reject-Jobs Response</A></LI>
+</UL>
+<LI><A HREF="#4_13">4.13 CUPS-Set-Default Operation</A></LI>
+<UL>
+<LI><A HREF="#4_13_1">4.13.1 CUPS-Set-Default Request</A></LI>
+<LI><A HREF="#4_13_2">4.13.2 CUPS-Set-Default Response</A></LI>
+</UL>
+<LI><A HREF="#4_14">4.14 CUPS-Get-Devices Operation</A></LI>
+<UL>
+<LI><A HREF="#4_14_1">4.14.1 CUPS-Get-Devices Request</A></LI>
+<LI><A HREF="#4_14_2">4.14.2 CUPS-Get-Devices Response</A></LI>
+</UL>
+<LI><A HREF="#4_15">4.15 CUPS-Get-PPDs Operation</A></LI>
+<UL>
+<LI><A HREF="#4_15_1">4.15.1 CUPS-Get-PPDs Request</A></LI>
+<LI><A HREF="#4_15_2">4.15.2 CUPS-Get-PPDs Response</A></LI>
+</UL>
+<LI><A HREF="#4_16">4.16 CUPS-Move-Job Operation</A></LI>
+<UL>
+<LI><A HREF="#4_16_1">4.16.1 CUPS-Move-Job Request</A></LI>
+<LI><A HREF="#4_16_2">4.16.2 CUPS-Move-Job Response</A></LI>
+</UL>
+</UL>
+<B><A HREF="#5">5 Attributes</A></B>
+<UL>
+<LI><A HREF="#5_1">5.1 Device Attributes</A></LI>
+<UL>
+<LI><A HREF="#5_1_1">5.1.1 device-class (type2 keyword)</A></LI>
+<LI><A HREF="#5_1_2">5.1.2 device-info (text(127))</A></LI>
+<LI><A HREF="#5_1_3">5.1.3 device-make-and-model (text(127))</A></LI>
+<LI><A HREF="#5_1_4">5.1.4 device-uri (uri)</A></LI>
+</UL>
+<LI><A HREF="#5_2">5.2 Job Template Attributes</A></LI>
+<UL>
+<LI><A HREF="#5_2_1">5.2.1 blackplot (boolean)</A></LI>
+<LI><A HREF="#5_2_2">5.2.2 brightness (integer(0:200))</A></LI>
+<LI><A HREF="#5_2_3">5.2.3 columns (integer(1:4))</A></LI>
+<LI><A HREF="#5_2_4">5.2.4 cpi (type2 enum)</A></LI>
+<LI><A HREF="#5_2_5">5.2.5 fitplot (boolean)</A></LI>
+<LI><A HREF="#5_2_6">5.2.6 gamma (integer(1:10000))</A></LI>
+<LI><A HREF="#5_2_7">5.2.7 hue (integer(-180:180))</A></LI>
+<LI><A HREF="#5_2_8">5.2.8 job-billing (text(MAX))</A></LI>
+<LI><A HREF="#5_2_9">5.2.9 job-hold-until (keyword | name(MAX))</A></LI>
+<LI><A HREF="#5_2_10">5.2.10 job-sheets (1setof type3 keyword |
+ name(MAX))</A></LI>
+<LI><A HREF="#5_2_11">5.2.11 job-originating-host-name (name(MAX))</A></LI>
+<LI><A HREF="#5_2_12">5.2.12 lpi (type2 enum)</A></LI>
+<LI><A HREF="#5_2_13">5.2.13 mirror (boolean)</A></LI>
+<LI><A HREF="#5_2_14">5.2.14 natural-scaling (integer(1:1000))</A></LI>
+<LI><A HREF="#5_2_15">5.2.15 number-up-layout (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_16">5.2.16 page-border (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_17">5.2.17 page-bottom (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_18">5.2.18 page-label (text(MAX))</A></LI>
+<LI><A HREF="#5_2_19">5.2.19 page-left (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_20">5.2.20 page-right (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_21">5.2.21 page-set (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_22">5.2.22 page-top (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_23">5.2.23 penwidth (integer(0:MAX))</A></LI>
+<LI><A HREF="#5_2_24">5.2.24 position (type2 keyword)</A></LI>
+<LI><A HREF="#5_2_25">5.2.25 ppi (integer(1:MAX))</A></LI>
+<LI><A HREF="#5_2_26">5.2.26 prettyprint (boolean)</A></LI>
+<LI><A HREF="#5_2_27">5.2.27 saturation (integer(0:200))</A></LI>
+<LI><A HREF="#5_2_28">5.2.28 scaling (integer(1:1000))</A></LI>
+<LI><A HREF="#5_2_29">5.2.29 wrap (boolean)</A></LI>
+</UL>
+<LI><A HREF="#5_3">5.3 PPD Attributes</A></LI>
+<UL>
+<LI><A HREF="#5_3_1">5.3.1 ppd-natural-language (naturalLanguage)</A></LI>
+<LI><A HREF="#5_3_2">5.3.2 ppd-make (text(127))</A></LI>
+<LI><A HREF="#5_3_3">5.3.3 ppd-make-and-model (text(127))</A></LI>
+<LI><A HREF="#5_3_4">5.3.4 ppd-name (name(255))</A></LI>
+</UL>
+<LI><A HREF="#5_4">5.4 Printer Attributes</A></LI>
+<UL>
+<LI><A HREF="#5_4_1">5.4.1 job-k-limit (integer)</A></LI>
+<LI><A HREF="#5_4_2">5.4.2 job-page-limit (integer)</A></LI>
+<LI><A HREF="#5_4_3">5.4.3 job-quota-period (integer)</A></LI>
+<LI><A HREF="#5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword |
+ name(MAX))</A></LI>
+<LI><A HREF="#5_4_5">5.4.5 printer-type (type2 enum)</A></LI>
+<LI><A HREF="#5_4_6">5.4.6 printer-type-mask (type2 enum)</A></LI>
+<LI><A HREF="#5_4_7">5.4.7 requesting-user-name-allowed (1setof
+ name(127))</A></LI>
+<LI><A HREF="#5_4_8">5.4.8 requesting-user-name-denied (1setof
+ name(127))</A></LI>
+</UL>
+<LI><A HREF="#5_5">5.5 Printer Class Attributes</A></LI>
+<UL>
+<LI><A HREF="#5_5_1">5.5.1 member-names (1setof name(127))</A></LI>
+<LI><A HREF="#5_5_2">5.5.2 member-uris (1setof uri)</A></LI>
+</UL>
+</UL>
+<B><A HREF="#6">A Glossary</A></B>
+<UL>
+<LI><A HREF="#6_1">A.1 Terms</A></LI>
+<LI><A HREF="#6_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This document provides an overview of the Internet Printing Protocol
+ (&quot;IPP&quot;) version 1.1 as implemented in the Common UNIX Printing System
+ (&quot;CUPS&quot;) version 1.1.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This document is organized into the following sections:</P>
+<UL>
+<LI><A HREF="#1">1 - Scope</A></LI>
+<LI><A HREF="#2">2 - References</A></LI>
+<LI><A HREF="#3">3 - Overview</A></LI>
+<LI><A HREF="#4">4 - Operations</A></LI>
+<LI><A HREF="#5">5 - Attributes</A></LI>
+<LI><A HREF="#6">A - Glossary</A></LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Overview</A></H1>
+<P>CUPS 1.1 implements IPP/1.1 and the operations and attributes defined
+ in the &quot;IPP: Job and Printer Set Operations&quot;, &quot;IPP/1.1: Output-bin
+ Attribute Extension&quot;, and &quot;IPP/1.1: finishings 'fold',' trim', and
+ 'bale' attribute values extension&quot; specifications.</P>
+<P>CUPS also provides 13 new operations and many new attributes to
+ support multiple IPP printers and printer classes on a single host.</P>
+<H2><A NAME="3_1">3.1 IPP URIs</A></H2>
+<P>CUPS supports both the &quot;http&quot; and &quot;ipp&quot; methods. The following
+ resource names are used:</P>
+<DL>
+<DT>method://hostname:port/</DT>
+<DD>Can be used for all &quot;get&quot; operations.</DD>
+<DT>method://hostname:port/admin</DT>
+<DD>Used for all administrative operations.</DD>
+<DT>method://hostname:port/classes/name</DT>
+<DD>Specifies a printer class.</DD>
+<DT>method://hostname:port/jobs/id</DT>
+<DD>Specifies a job.</DD>
+<DT>method://hostname:port/printers/name</DT>
+<DD>Specifies a printer.</DD>
+</DL>
+<P>So a typical printer URI would be
+ &quot;ipp://foo.bar.com/printers/LaserJet&quot;.</P>
+<P>In addition, the CUPS server also supports normal browser access to
+ &quot;method://hostname:port/admin/&quot;, &quot;method://hostname:port/classes/&quot;,
+ &quot;method://hostname:port/jobs/&quot;, and &quot;method://hostname:port/printers/&quot;
+ to view and manage resources on the server dynamically.</P>
+<H2><A NAME="3_2">3.2 CUPS IPP Operations</A></H2>
+<P>CUPS provides 13 extension operations in addition to most of the
+ standard IPP and registered extension operations:
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH VALIGN="TOP">Operation Name</TH><TH VALIGN="TOP">CUPS</TH><TH VALIGN="TOP">
+Code</TH><TH VALIGN="TOP">Brief Description</TH></TR>
+<TR><TD VALIGN="TOP">Print-Job</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0002</TD><TD VALIGN="TOP">Print a file.</TD></TR>
+<TR><TD VALIGN="TOP">Validate-Job</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0004</TD><TD VALIGN="TOP">Validate job attributes.</TD></TR>
+<TR><TD VALIGN="TOP">Create-Job</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x0005</TD><TD VALIGN="TOP">Create a print job.</TD></TR>
+<TR><TD VALIGN="TOP">Send-Document</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x0006</TD><TD VALIGN="TOP">Send a file for a print job.</TD></TR>
+<TR><TD VALIGN="TOP">Cancel-Job</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0008</TD><TD VALIGN="TOP">Cancel a print job.</TD></TR>
+<TR><TD VALIGN="TOP">Get-Job-Attributes</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0009</TD><TD VALIGN="TOP">Get job attributes.</TD></TR>
+<TR><TD VALIGN="TOP">Get-Jobs</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x000A</TD><TD VALIGN="TOP">Get all jobs.</TD></TR>
+<TR><TD VALIGN="TOP">Get-Printer-Attributes</TD><TD VALIGN="TOP">1.0</TD><TD
+VALIGN="TOP">0x000B</TD><TD VALIGN="TOP">Get printer attributes.</TD></TR>
+<TR><TD VALIGN="TOP">Hold-Job</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x000C</TD><TD VALIGN="TOP">Hold a job for printing.</TD></TR>
+<TR><TD VALIGN="TOP">Release-Job</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x000D</TD><TD VALIGN="TOP">Release a job for printing.</TD></TR>
+<TR><TD VALIGN="TOP">Pause-Printer</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0010</TD><TD VALIGN="TOP">Pause printing on a printer.</TD></TR>
+<TR><TD VALIGN="TOP">Resume-Printer</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0011</TD><TD VALIGN="TOP">Resume printing on a printer.</TD></TR>
+<TR><TD VALIGN="TOP">Purge-Jobs</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x0012</TD><TD VALIGN="TOP">Purge all jobs.</TD></TR>
+<TR><TD VALIGN="TOP">Set-Job-Attributes</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x0014</TD><TD VALIGN="TOP">Set attributes for a pending or held job.</TD>
+</TR>
+<TR><TD VALIGN="TOP">CUPS-Get-Default</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4001</TD><TD VALIGN="TOP">Get the default destination.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Get-Printers</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4002</TD><TD VALIGN="TOP">Get all of the available printers.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Add-Modify-Printer</TD><TD VALIGN="TOP">1.0</TD><TD
+VALIGN="TOP">0x4003</TD><TD VALIGN="TOP">Add or modify a printer.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Delete-Printer</TD><TD VALIGN="TOP">1.0</TD><TD
+VALIGN="TOP">0x4004</TD><TD VALIGN="TOP">Delete a printer.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Get-Classes</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4005</TD><TD VALIGN="TOP">Get all of the available printer classes.</TD>
+</TR>
+<TR><TD VALIGN="TOP">CUPS-Add-Modify-Class</TD><TD VALIGN="TOP">1.0</TD><TD
+VALIGN="TOP">0x4006</TD><TD VALIGN="TOP">Add or modify a printer class.</TD>
+</TR>
+<TR><TD VALIGN="TOP">CUPS-Delete-Class</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4007</TD><TD VALIGN="TOP">Delete a printer class.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Accept-Jobs</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4008</TD><TD VALIGN="TOP">Accept jobs on a printer or printer class.</TD>
+</TR>
+<TR><TD VALIGN="TOP">CUPS-Reject-Jobs</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x4009</TD><TD VALIGN="TOP">Reject jobs on a printer or printer class.</TD>
+</TR>
+<TR><TD VALIGN="TOP">CUPS-Set-Default</TD><TD VALIGN="TOP">1.0</TD><TD VALIGN="TOP">
+0x400A</TD><TD VALIGN="TOP">Set the default destination.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Get-Devices</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x400B</TD><TD VALIGN="TOP">Get all of the available devices.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Get-PPDs</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x400C</TD><TD VALIGN="TOP">Get all of the available PPDs.</TD></TR>
+<TR><TD VALIGN="TOP">CUPS-Move-Job</TD><TD VALIGN="TOP">1.1</TD><TD VALIGN="TOP">
+0x400D</TD><TD VALIGN="TOP">Move a job to a different printer.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1><A NAME="4">4 Operations</A></H1>
+<P>The following sections describe the operations supported by CUPS. In
+ the interest of brevity, operations which use only the standard IPP
+ attributes are not described.</P>
+<H2><A NAME="4_1">4.1 Print-Job Operation</A></H2>
+<P>The Print-Job operation (0x0002) prints a file.</P>
+<H3><A NAME="4_1_1">4.1.1 Print-Job Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ Print-Job request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
+</UL>
+<P>Group 2: Job Template Attributes</P>
+<UL>
+<P>&quot;job-billing&quot; (text(MAX)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a billing string that is logged with
+ the page accounting information.</P>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
+ attribute value.</P>
+<P>Other Job Template Attributes</P>
+</UL>
+<P>The Print-Job request is followed by a file to be printed.</P>
+<H3><A NAME="4_1_2">4.1.2 Print-Job Response</A></H3>
+<P>The following groups of attributes are send as part of the Print-Job
+ Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Job Attributes</P>
+<UL>
+<P>Standard Job Attributes</P>
+</UL>
+<H2><A NAME="4_2">4.2 Create-Job Operation</A></H2>
+<P>The Create-Job operation (0x0005) creates a new, empty print job.</P>
+<H3><A NAME="4_2_1">4.2.1 Create-Job Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ Create-Job request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
+</UL>
+<P>Group 2: Job Template Attributes</P>
+<UL>
+<P>&quot;job-billing&quot; (text(MAX)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a billing string that is logged with
+ the page accounting information.</P>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
+ attribute value.</P>
+<P>Standard Job Template Attributes</P>
+</UL>
+<H3><A NAME="4_2_2">4.2.2 Create-Job Response</A></H3>
+<P>The following groups of attributes are send as part of the Create-Job
+ Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Job Attributes</P>
+<UL>
+<P>Standard Job Attributes</P>
+</UL>
+<H2><A NAME="4_3">4.3 Set-Job-Attributes Operation</A></H2>
+<P>The Set-Job-Attributes operation (0x0014) changes the attributes of
+ an active (not completed) job.</P>
+<H3><A NAME="4_3_1">4.3.1 Set-Job-Attributes Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ Set-Job-Attributes request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer)</P>
+<P><I>OR</I></P>
+<P>&quot;job-uri&quot;:</P>
+<P>The client MUST supply a URI for the specified printer and a job ID
+ number, or the job URI.</P>
+</UL>
+<P>Group 2: Job Template Attributes</P>
+<UL>
+<P>&quot;job-sheets&quot; (1setof type3 keyword | name(MAX)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies one or two banner pages that are
+ printed before and after any files in the print job. The name of &quot;none&quot;
+ is reserved to indicate that no banner page should be printed. If the
+ client does not specify this attribute then the value of the
+ &quot;job-sheets-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.</P>
+<P>&quot;media&quot; (1setof type3 keyword | name(MAX)):</P>
+<P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output media. If
+ the client does not specify this attribute then the value of the
+ &quot;media-default&quot; printer object attribute is used.</P>
+<P><B>Note:</B> Standard IPP only allows specification of a single media
+ attribute value.</P>
+<P>Other Job Template Attributes</P>
+</UL>
+<H3><A NAME="4_3_2">4.3.2 Set-Job-Attributes Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ Set-Job-Attributes Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_4">4.4 CUPS-Get-Default Operation</A></H2>
+<P>The CUPS-Get-Default operation (0x4001) returns the default printer
+ URI and attributes.</P>
+<H3><A NAME="4_4_1">4.4.1 CUPS-Get-Default Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Default request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
+</UL>
+<H3><A NAME="4_4_2">4.4.2 CUPS-Get-Default Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Default Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>The set of requested attributes and their current values.</P>
+</UL>
+<H2><A NAME="4_5">4.5 CUPS-Get-Printers Operation</A></H2>
+<P>The CUPS-Get-Printers operation (0x4002) returns the printer
+ attributes for every printer known to the system. This may include
+ printers that are not served directly by the server.</P>
+<H3><A NAME="4_5_1">4.5.1 CUPS-Get-Printers Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Printers request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ printers that are returned.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies this attribute to select which
+ printers are returned.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies this attribute to select which
+ printers are returned.</P>
+<P>&quot;printer-type&quot; (type2 enum):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a printer type enumeration to select
+ which printers are returned.</P>
+<P>&quot;printer-type-mask&quot; (type2 enum):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a printer type mask enumeration to
+ select which bits are used in the &quot;printer-type&quot; attribute.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
+</UL>
+<H3><A NAME="4_5_2">4.5.2 CUPS-Get-Printers Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Printers Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>The set of requested attributes and their current values for each
+ printer.</P>
+</UL>
+<H2><A NAME="4_6">4.6 CUPS-Add-Modify-Printer Operation</A></H2>
+<P>The CUPS-Add-Modify-Printer operation (0x4003) adds a new printer or
+ modifies an existing printer on the system.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_6_1">4.6.1 CUPS-Add-Modify-Printer Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Add-Modify-Printer request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>&quot;banner-end-default&quot; (name(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a banner page name that is printed
+ after files in a job. The reserved name &quot;none&quot; is used to specify that
+ no banner page should be printed.</P>
+<P>&quot;banner-start-default&quot; (name(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a banner page name that is printed
+ before files in a job. The reserved name &quot;none&quot; is used to specify that
+ no banner page should be printed.</P>
+<P>&quot;device-uri&quot; (uri):</P>
+<P>The client OPTIONALLY supplies a device URI for the specified
+ printer.</P>
+<P>&quot;ppd-name&quot; (name(127)):</P>
+<P>The client OPTIONALLY supplies a PPD name for the specified printer.</P>
+<P>&quot;printer-is-accepting-jobs&quot; (boolean):</P>
+<P>The client OPTIONALLY supplies this boolean attribute indicating
+ whether or not the printer object should accept new jobs.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the printer
+ information string.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ location of the printer.</P>
+<P>&quot;printer-more-info&quot; (uri):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a URI for
+ additional printer information.</P>
+<P>&quot;printer-state&quot; (type2 enum):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the printer. Only the &quot;idle&quot; and &quot;stopped&quot;
+ enumerations are recognized.</P>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current printer state.</P>
+<P>&quot;requesting-user-name-allowed&quot; (1setof name(127) | delete)</P>
+<P><I>OR</I></P>
+<P>&quot;requesting-user-name-denied&quot; (1setof name(127) | delete):</P>
+<P>The client OPTIONALLY supplies one of these attributes to specify an
+ access control list for incoming print jobs. To allow all users access
+ to a printer, use the delete tag for the attribute value.</P>
+</UL>
+<P>The CUPS-Add-Modify-Printer request can optionally be followed by a
+ PPD file or System V interface script to be used for the printer. The
+ &quot;ppd-name&quot; attribute overrides any file that is attached to the end of
+ the request with a local CUPS PPD file.</P>
+<H3><A NAME="4_6_2">4.6.2 CUPS-Add-Modify-Printer Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Add-Modify-Printer Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_7">4.7 CUPS-Delete-Printer Operation</A></H2>
+<P>The CUPS-Delete-Printer operation (0x4004) removes an existing
+ printer from the system.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_7_1">4.7.1 CUPS-Delete-Printer Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Delete-Printer request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer.</P>
+</UL>
+<H3><A NAME="4_7_2">4.7.2 CUPS-Delete-Printer Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Delete-Printer Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_8">4.8 CUPS-Get-Classes Operation</A></H2>
+<P>The CUPS-Get-Classes operation (0x4005) returns the printer
+ attributes for every printer class known to the system. This may
+ include printer classes that are not served directly by the server.</P>
+<H3><A NAME="4_8_1">4.8.1 CUPS-Get-Classes Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Classes request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ printer classes that are returned.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies this attribute to select which printer
+ classes are returned.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies this attribute to select which printer
+ classes are returned.</P>
+<P>&quot;printer-type&quot; (type2 enum):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a printer type enumeration to select
+ which printer classes are returned.</P>
+<P>&quot;printer-type-mask&quot; (type2 enum):</P>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The client OPTIONALLY supplies a printer type mask enumeration to
+ select which bits are used in the &quot;printer-type&quot; attribute.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
+</UL>
+<H3><A NAME="4_8_2">4.8.2 CUPS-Get-Classes Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Classes Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Printer Class Object Attributes</P>
+<UL>
+<P>The set of requested attributes and their current values for each
+ printer class.</P>
+</UL>
+<H2><A NAME="4_9">4.9 CUPS-Add-Modify-Class Operation</A></H2>
+<P>The CUPS-Add-Modify-Class operation (0x4006) adds a new printer class
+ or modifies and existing printer class on the system.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_9_1">4.9.1 CUPS-Add-Modify-Class Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Add-Modify-Class request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer class.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>&quot;member-uris&quot; (1setof uri):</P>
+<P>The client OPTIONALLY supplies the &quot;member-uris&quot; set specifying the
+ printers and printer classes that are part of the class.</P>
+<P>&quot;printer-is-accepting-jobs&quot; (boolean):</P>
+<P>The client OPTIONALLY supplies this boolean attribute indicating
+ whether or not the class object should accept new jobs.</P>
+<P>&quot;printer-info&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the printer
+ information string.</P>
+<P>&quot;printer-location&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ location of the class.</P>
+<P>&quot;printer-more-info&quot; (uri):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a URI for
+ additional class information.</P>
+<P>&quot;printer-state&quot; (type2 enum):</P>
+<P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the class. Only the &quot;idle&quot; and &quot;stopped&quot;
+ enumerations are recognized.</P>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current class state.</P>
+<P>&quot;requesting-user-name-allowed&quot; (1setof name(127))</P>
+<P><I>OR</I></P>
+<P>&quot;requesting-user-name-denied&quot; (1setof name(127)):</P>
+<P>The client OPTIONALLY supplies one of these attributes to specify an
+ access control list for incoming print jobs. To allow all users access
+ to a class, use the delete tag for the attribute value.</P>
+</UL>
+<H3><A NAME="4_9_2">4.9.2 CUPS-Add-Modify-Class Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Add-Modify-Class Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_10">4.10 CUPS-Delete-Class Operation</A></H2>
+<P>The CUPS-Delete-Class operation (0x4007) removes an existing printer
+ class from the system.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_10_1">4.10.1 CUPS-Delete-Class Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Delete-Class request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer class.</P>
+</UL>
+<H3><A NAME="4_10_2">4.10.2 CUPS-Delete-Class Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Delete-Class Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_11">4.11 CUPS-Accept-Jobs Operation</A></H2>
+<P>The CUPS-Accept-Jobs operation (0x4008) sets the
+ &quot;printer-is-accepting-jobs&quot; attribute to true for the specified printer
+ or printer class.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_11_1">4.11.1 CUPS-Accept-Jobs Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Accept-Jobs request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
+</UL>
+<H3><A NAME="4_11_2">4.11.2 CUPS-Accept-Jobs Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Accept-Jobs Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_12">4.12 CUPS-Reject-Jobs Operation</A></H2>
+<P>The CUPS-Reject-Jobs operation (0x4009) sets the
+ &quot;printer-is-accepting-jobs&quot; attribute to false for the specified
+ printer or printer class.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_12_1">4.12.1 CUPS-Reject-Jobs Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Reject-Jobs request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
+</UL>
+<P>Group 2: Printer Object Attributes</P>
+<UL>
+<P>&quot;printer-state-message&quot; (text(MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute indicating a textual
+ reason for the current printer state.</P>
+</UL>
+<H3><A NAME="4_12_2">4.12.2 CUPS-Reject-Jobs Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Reject-Jobs Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_13">4.13 CUPS-Set-Default Operation</A></H2>
+<P>The CUPS-Set-Default operation (0x400A) sets the default printer
+ destination for all clients.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>This operation requires administrative priviledges and must be POSTed
+ to &quot;/admin/&quot;. POSTs to other paths will result in a
+ client-error-not-authorized (IPP_NOT_AUTHORIZED) error.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_13_1">4.13.1 CUPS-Set-Default Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Set-Default request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri):</P>
+<P>The client MUST supply a URI for the specified printer or printer
+ class.</P>
+</UL>
+<H3><A NAME="4_13_2">4.13.2 CUPS-Set-Default Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Set-Default Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H2><A NAME="4_14">4.14 CUPS-Get-Devices Operation</A></H2>
+<P>The CUPS-Get-Devices operation (0x400B) returns all of the supported
+ device-uri's for the server (CUPS 1.1 and higher).</P>
+<H3><A NAME="4_14_1">4.14.1 CUPS-Get-Devices Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-Devices request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;device-class&quot; (type1 keyword):</P>
+<P>The client OPTIONALLY supplies a device class keyword to select which
+ devices are returned.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ devices that are returned.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
+</UL>
+<H3><A NAME="4_14_2">4.14.2 CUPS-Get-Devices Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-Devices Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: Device Object Attributes</P>
+<UL>
+<P>The set of requested attributes and their current values for each
+ device.</P>
+</UL>
+<H2><A NAME="4_15">4.15 CUPS-Get-PPDs Operation</A></H2>
+<P>The CUPS-Get-PPDs operation (0x400C) returns all of the locally
+ available PPD files on the system (CUPS 1.1 and higher).</P>
+<H3><A NAME="4_15_1">4.15.1 CUPS-Get-PPDs Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Get-PPDs request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;limit&quot; (integer (1:MAX)):</P>
+<P>The client OPTIONALLY supplies this attribute limiting the number of
+ PPDs that are returned.</P>
+<P>&quot;ppd-make&quot; (text(127)):</P>
+<P>The client OPTIONALLY supplies a printer manufacturer to select which
+ PPDs are returned.</P>
+<P>&quot;requested-attributes&quot; (1setOf keyword) :</P>
+<P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.</P>
+</UL>
+<H3><A NAME="4_15_2">4.15.2 CUPS-Get-PPDs Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Get-PPDs Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<P>Group 2: PPD Attributes</P>
+<UL>
+<P>The set of requested attributes and their current values for each PPD
+ file.</P>
+</UL>
+<H2><A NAME="4_16">4.16 CUPS-Move-Job Operation</A></H2>
+<P>The CUPS-Move-Job operation (0x400D) moves an active print job to a
+ different printer (CUPS 1.1 and higher).</P>
+<H3><A NAME="4_16_1">4.16.1 CUPS-Move-Job Request</A></H3>
+<P>The following groups of attributes are supplied as part of the
+ CUPS-Move-Job request:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.1 of the IPP Model and Semantics
+ document.</P>
+<P>&quot;printer-uri&quot; (uri) and &quot;job-id&quot; (integer)</P>
+<P><I>OR</I></P>
+<P>&quot;job-uri&quot;:</P>
+<P>The client MUST supply a URI for the specified printer and a job ID
+ number, or the job URI.</P>
+</UL>
+<P>Group 2: Job Template Attributes</P>
+<UL>
+<P>&quot;job-printer-uri&quot; (uri)</P>
+<P>The client MUST supply a URI for a printer on the same server.</P>
+</UL>
+<H3><A NAME="4_16_2">4.16.2 CUPS-Move-Job Response</A></H3>
+<P>The following groups of attributes are send as part of the
+ CUPS-Move-Job Response:</P>
+<P>Group 1: Operation Attributes</P>
+<UL>
+<P>Status Message:</P>
+<P>The standard response status message.</P>
+<P>Natural Language and Character Set:</P>
+<P>The &quot;attributes-charset&quot; and &quot;attributes-natural-language&quot; attributes
+ as described in section 3.1.4.2 of the IPP Model and Semantics
+ document.</P>
+</UL>
+<H1><A NAME="5">5 Attributes</A></H1>
+<P>CUPS provides many extension attributes to support multiple devices,
+ PPD files, standard job filters, printers, and printer classes.</P>
+<H2><A NAME="5_1">5.1 Device Attributes</A></H2>
+<P>Device attributes are returned by the CUPS-Get-Devices operation and
+ enumerate all of the available hardware devices and network protocols
+ that are supported by the server.</P>
+<H3><A NAME="5_1_1">5.1.1 device-class (type2 keyword)</A></H3>
+<P>The device-class attribute specifies the class of device and can be
+ one of the following:</P>
+<UL>
+<LI>&quot;file&quot; - a disk file.</LI>
+<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port, currently used
+ for Centronics, IEEE-1284, and USB printer ports.</LI>
+<LI>&quot;serial&quot; - a variable-rate serial port.</LI>
+<LI>&quot;network&quot; - a network connection, typically via AppSocket, HTTP,
+ IPP, LPD, or SMB/CIFS protocols.</LI>
+</UL>
+<H3><A NAME="5_1_2">5.1.2 device-info (text(127))</A></H3>
+<P>The device-info attribute specifies a human-readable string
+ describing the device, e.g. &quot;Parallel Port #1&quot;.</P>
+<H3><A NAME="5_1_3">5.1.3 device-make-and-model (text(127))</A></H3>
+<P>The device-makr-and-model attribute specifies a device identification
+ string provided by the printer connected to the device. If the device
+ or printer does not support identification then this attribute contains
+ the string &quot;unknown&quot;.</P>
+<H3><A NAME="5_1_4">5.1.4 device-uri (uri)</A></H3>
+<P>The device-uri attribute specifies a unique identifier for the
+ device. The actual format of the device-uri string depends on the value
+ of the device-class attribute:</P>
+<UL>
+<LI>&quot;file&quot; - The device-uri will be of the form
+ &quot;file:/path/to/filename&quot;.</LI>
+<LI>&quot;direct&quot; - The device-uri will be of the form
+ &quot;method:/dev/filename&quot;, where method may be &quot;parallel&quot; or &quot;usb&quot; in the
+ current implementation.</LI>
+<LI>&quot;serial&quot; - The device-uri will be of the form
+ &quot;serial:/dev/filename?baud=value+parity=value+flow=value&quot;. The baud
+ value is the data rate in bits per second; the supported values depend
+ on the underlying hardware. The parity value can be one of &quot;none&quot;,
+ &quot;even&quot;, or &quot;odd&quot;. The flow value can be one of &quot;none&quot;, &quot;soft&quot; (XON/XOFF
+ handshaking), &quot;hard&quot; or &quot;rts/cts&quot; (RTS/CTS handshaking), or &quot;dtrdsr&quot;
+ (DTR/DSR handshaking).
+<P>The URI returned by CUPS-Get-Devices will contain the maximum baud
+ rate supported by the device and the best type of flow control
+ available (&quot;soft&quot; or &quot;hard&quot;).</P>
+</LI>
+<LI>&quot;network&quot; - The device-uri will be of the form
+ &quot;method://[username:password@]hostname[:port]/[resource]&quot;, where method
+ may be &quot;http&quot;, &quot;ipp&quot;, &quot;lpd&quot;, &quot;smb&quot;, or &quot;socket&quot; in the current
+ implementation.
+<P>The URI returned by CUPS-Get-Devices will only contain the method
+ name followed by two slashes (&quot;method://&quot;). It is up to the client
+ application to add the appropriate host and other information when
+ adding a new printer.</P>
+<P>The URI returned by Get-Printer-Attributes and CUPS-Get-Printers has
+ any username and password information stripped; the information is
+ still stored and used by the server internally to perform any needed
+ authentication.</P>
+</LI>
+</UL>
+<H2><A NAME="5_2">5.2 Job Template Attributes</A></H2>
+<H3><A NAME="5_2_1">5.2.1 blackplot (boolean)</A></H3>
+<P>The blackplot attribute specifies whether HP-GL/2 plot files should
+ be rendered entirely in black ink (blackplot=true) or using the colors
+ and shades specified in the file (blackplot=false). The default value
+ is false.</P>
+<H3><A NAME="5_2_2">5.2.2 brightness (integer(0:200))</A></H3>
+<P>The brightness attribute specifies the overall brightness of the
+ printed output in percent. A brightness of 100 is normal, while 200 is
+ twice as bright and 50 is half as bright. The default value is 100.</P>
+<P>Brightness is applied to the Cyan, Magenta, Yellow, and Black values
+ using the function &quot;f(x) = brightness / 100 * x&quot;.</P>
+<H3><A NAME="5_2_3">5.2.3 columns (integer(1:4))</A></H3>
+<P>The columns attribute specifies the number of columns to generate
+ when printing text files. The default value is 1.</P>
+<H3><A NAME="5_2_4">5.2.4 cpi (type2 enum)</A></H3>
+<P>The cpi attribute specifies the number of characters per inch when
+ printing text files. Only the values 10, 12, and 17 are currently
+ supported. The default value is 10.</P>
+<H3><A NAME="5_2_5">5.2.5 fitplot (boolean)</A></H3>
+<P>The fitplot attribute specifies whether to scale HP-GL/2 plot files
+ to fit on the selected media (fitplot=true) or use the physical scale
+ specified in the plot file (fitplot=false). The default value is false.</P>
+<H3><A NAME="5_2_6">5.2.6 gamma (integer(1:10000))</A></H3>
+<P>The gamma attribute specifies the luminance correction for the
+ output. A value of 1000 specifies no correction, while values of 2000
+ and 500 will generate lighter and darker output, respectively. The
+ default value is 1000.</P>
+<P>Gamma is applied to the Red, Green, and Blue values (or luminance for
+ grayscale output) using the function &quot;f(x) = x<SUP>(1000/gamma)</SUP>&quot;.</P>
+<H3><A NAME="5_2_7">5.2.7 hue (integer(-180:180))</A></H3>
+<P>The hue attribute specifies a color hue rotation when printing image
+ files. The default value is 0.</P>
+<H3><A NAME="5_2_8">5.2.8 job-billing (text(MAX))</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-billing attribute provides a text value to associate with a
+ job for billing purposes.</P>
+<H3><A NAME="5_2_9">5.2.9 job-hold-until (keyword | name(MAX))</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-hold-until attribute specifies a hold time. In addition to
+ the standard IPP/1.1 keyword names, CUPS supports name values of the
+ form &quot;HH:MM&quot; and &quot;HH:MM:SS&quot; that specify a hold time. The hold time is
+ in Greenwich Mean Time (GMT) and<I> not</I> in the local time zone. If
+ the specified time is less than the current time, the job is held until
+ the next day.</P>
+<H3><A NAME="5_2_10">5.2.10 job-sheets (1setof type3 keyword |
+ name(MAX))</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-sheets attribute specifies one or two banner files that are
+ printed before and after a job. The reserved value of &quot;none&quot; disables
+ banner printing. The default value is stored in the job-sheets-default
+ attribute.</P>
+<P>If only one value is supplied, the banner file is printed before the
+ job. If two values are supplied, the first value is used as the
+ starting banner file and the second as the ending banner file.</P>
+<H3><A NAME="5_2_11">5.2.11 job-originating-host-name (name(MAX))</A></H3>
+<P><I>(CUPS 1.1.5 and higher)</I></P>
+<P>The job-originating-host-name attribute specifies the host from which
+ the job was queued. The value will be the hostname or IP address of the
+ client depending on whether hostname resolution is enabled. The
+ localhost address (127.0.0.1) is<B> always</B> resolved to the name
+ &quot;localhost&quot;.</P>
+<P>This attribute is read-only.</P>
+<H3><A NAME="5_2_12">5.2.12 lpi (type2 enum)</A></H3>
+<P>The lpi attribute specifies the number of lines per inch when
+ printing text files. Only the values 6 and 8 are currently supported.
+ The default value is 6.</P>
+<H3><A NAME="5_2_13">5.2.13 mirror (boolean)</A></H3>
+<P>The mirror attribute specifies whether pages are mirrored on their X
+ axis, which is useful for printing transfer images on special media.
+ The default value is false.</P>
+<H3><A NAME="5_2_14">5.2.14 natural-scaling (integer(1:1000))</A></H3>
+<P><I>(CUPS 1.1.9 and higher)</I></P>
+<P>The natural-scaling attribute specifies the scaling of image files
+ with respect to the natural image size. A value of 100 specifies that
+ the image file should exactly the natural size, while 50 is half the
+ natural size and 200 is twice the natural size. The default value is
+ 100.</P>
+<P>The ppi option can be used to override the natural resolution of the
+ image, which controls the natural size.</P>
+<H3><A NAME="5_2_15">5.2.15 number-up-layout (type2 keyword)</A></H3>
+<P><I>(CUPS 1.1.15 and higher)</I></P>
+<P>The number-up-layout attribute specifies the order each input page is
+ placed on each output page. The following keywords are presently
+ defined:</P>
+<UL>
+<LI><CODE>btlr</CODE> - Bottom to top, left to right</LI>
+<LI><CODE>btrl</CODE> - Bottom to top, right to left</LI>
+<LI><CODE>lrbt</CODE> - Left to right, bottom to top</LI>
+<LI><CODE>lrtb</CODE> - Left to right, top to bottom (default)</LI>
+<LI><CODE>rlbt</CODE> - Right to left, bottom to top</LI>
+<LI><CODE>rltb</CODE> - Right to left, top to bottom</LI>
+<LI><CODE>tblr</CODE> - Top to bottom, left to right</LI>
+<LI><CODE>tbrl</CODE> - Top to bottom, right to left</LI>
+</UL>
+<H3><A NAME="5_2_16">5.2.16 page-border (type2 keyword)</A></H3>
+<P><I>(CUPS 1.1.15 and higher)</I></P>
+<P>The page-border attribute specifies whether a border is draw around
+ each page. The following keywords are presently defined:</P>
+<UL>
+<LI><CODE>double</CODE> - Two hairline borders are drawn</LI>
+<LI><CODE>double-thick</CODE> - Two 1pt borders are drawn</LI>
+<LI><CODE>none</CODE> - No border is drawn (default)</LI>
+<LI><CODE>single</CODE> - A single hairline border is drawn</LI>
+<LI><CODE>single-thick</CODE> - A single 1pt border is drawn</LI>
+</UL>
+<H3><A NAME="5_2_17">5.2.17 page-bottom (integer(0:MAX))</A></H3>
+<P>The page-bottom attribute specifies the bottom margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_18">5.2.18 page-label (text(MAX))</A></H3>
+<P><I>(CUPS 1.1.7 and higher)</I></P>
+<P>The page-label attribute provides a text value to place in the header
+ and footer on each page. If a classification level is set on the
+ server, then this classification is printed before the page label.</P>
+<H3><A NAME="5_2_19">5.2.19 page-left (integer(0:MAX))</A></H3>
+<P>The page-left attribute specifies the left margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_20">5.2.20 page-right (integer(0:MAX))</A></H3>
+<P>The page-right attribute specifies the right margin in points (72
+ points equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_21">5.2.21 page-set (type2 keyword)</A></H3>
+<P>The page-set attribute specifies which pages to print in a file. The
+ supported keywords are &quot;all&quot;, &quot;even&quot;, and &quot;odd&quot;. The default value is
+ &quot;all&quot;.</P>
+<H3><A NAME="5_2_22">5.2.22 page-top (integer(0:MAX))</A></H3>
+<P>The page-top attribute specifies the top margin in points (72 points
+ equals 1 inch). The default value is the device physical margin.</P>
+<H3><A NAME="5_2_23">5.2.23 penwidth (integer(0:MAX))</A></H3>
+<P>The penwidth attribute specifies the default pen width in micrometers
+ when printing HP-GL/2 plot files. The default value is 1000 (1
+ millimeter).</P>
+<H3><A NAME="5_2_24">5.2.24 position (type2 keyword)</A></H3>
+<P>The position attribute specifies the location of image files on the
+ media. The following keyword values are recognized:</P>
+<UL>
+<LI><CODE>center</CODE> - Center the image on the page (default)</LI>
+<LI><CODE>top</CODE> - Print the image centered at the top of the page</LI>
+<LI><CODE>left</CODE> - Print the image centered on the left of page</LI>
+<LI><CODE>right</CODE> - Print the image centered on the right of the
+ page</LI>
+<LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page</LI>
+<LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page</LI>
+<LI><CODE>bottom</CODE> - Print the image centered at the bottom of the
+ page</LI>
+<LI><CODE>bottom-left</CODE> - Print the image at the bottom left corner
+ of the page</LI>
+<LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page</LI>
+</UL>
+<H3><A NAME="5_2_25">5.2.25 ppi (integer(1:MAX))</A></H3>
+<P>The ppi attribute specifies the resolution of an image file in pixels
+ per inch. The default value is the resolution included with the file or
+ 128 if no resolution information is available.</P>
+<H3><A NAME="5_2_26">5.2.26 prettyprint (boolean)</A></H3>
+<P>The prettyprint attribute specifies whether text files should be
+ printed with a shaded header and keyword highlighting
+ (prettyprint=true) or without additional formatting
+ (prettyprint=false). The default value is false.</P>
+<H3><A NAME="5_2_27">5.2.27 saturation (integer(0:200))</A></H3>
+<P>The saturation attribute specifies the color saturation when printing
+ image files. A saturation of 100 is normal, while values of 50 and 200
+ will be half and twice as colorful, respectively. The default value is
+ 100.</P>
+<H3><A NAME="5_2_28">5.2.28 scaling (integer(1:1000))</A></H3>
+<P>The scaling attribute specifies the scaling of image files with
+ respect to the selected media. A value of 100 specifies that the image
+ file should fit 100% of the page, or as much as possible given the
+ image dimensions. The default value is unspecified.</P>
+<P>The scaling attribute overrides the ppi attribute if specified.</P>
+<H3><A NAME="5_2_29">5.2.29 wrap (boolean)</A></H3>
+<P>The wrap attribute specifies whether long lines should be wrapped
+ (wrap=true) or not (wrap=false) when printing text files. The default
+ value is true.</P>
+<H2><A NAME="5_3">5.3 PPD Attributes</A></H2>
+<H3><A NAME="5_3_1">5.3.1 ppd-natural-language (naturalLanguage)</A></H3>
+<P>The ppd-natural-language attribute specifies the language encoding of
+ the PPD file (the LanguageVersion attribute in the PPD file). If the
+ language is unknown or undefined then &quot;en&quot; (English) is assumed.</P>
+<H3><A NAME="5_3_2">5.3.2 ppd-make (text(127))</A></H3>
+<P>The ppd-make attribute specifies the manufacturer of the printer (the
+ Manufacturer attribute in the PPD file). If the manufacturer is not
+ specified in the PPD file then an educated guess is made using the
+ NickName attribute in the PPD file.</P>
+<H3><A NAME="5_3_3">5.3.3 ppd-make-and-model (text(127))</A></H3>
+<P>The ppd-make-and-model attribute specifies the manufacturer and model
+ name of the PPD file (the NickName attribute in the PPD file). If the
+ make and model is not specified in the PPD file then the ModelName or
+ ShortNickName attributes are used instead.</P>
+<H3><A NAME="5_3_4">5.3.4 ppd-name (name(255))</A></H3>
+<P>The ppd-name attribute specifies the PPD filename on the server
+ relative to the model directory. The forward slash (/) is used to
+ delineate directories.</P>
+<H2><A NAME="5_4">5.4 Printer Attributes</A></H2>
+<H3><A NAME="5_4_1">5.4.1 job-k-limit (integer)</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-k-limit attribute specifies the maximum number of kilobytes
+ that may be printed by a user, including banner files. The default
+ value of 0 specifies that there is no limit.</P>
+<H3><A NAME="5_4_2">5.4.2 job-page-limit (integer)</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-page-limit attribute specifies the maximum number of pages
+ that may be printed by a user, including banner files. The default
+ value of 0 specifies that there is no limit.</P>
+<H3><A NAME="5_4_3">5.4.3 job-quota-period (integer)</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-quota-period attribute specifies the time period used for
+ quota calculations, in seconds. The default value of 0 specifies that
+ the limits apply to all jobs that have been printed by a user that are
+ still known to the system.</P>
+<H3><A NAME="5_4_4">5.4.4 job-sheets-supported (1setof type3 keyword |
+ name(MAX))</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The job-sheets-supported attribute specifies the available banner
+ files. There will always be at least one banner file available called
+ &quot;none&quot;.</P>
+<H3><A NAME="5_4_5">5.4.5 printer-type (type2 enum)</A></H3>
+<P>The printer-type attribute specifies printer type and capability bits
+ for the printer or class. The default value is computed from internal
+ state information and the PPD file for the printer. The following bits
+ are defined:
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Bit</TH><TH>Description</TH></TR>
+<TR><TD VALIGN="TOP">0x00000001</TD><TD VALIGN="TOP">Is a printer class.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000002</TD><TD VALIGN="TOP">Is a remote
+ destination.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000004</TD><TD VALIGN="TOP">Can print in black.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000008</TD><TD VALIGN="TOP">Can print in color.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000010</TD><TD VALIGN="TOP">Can print on both
+ sides of the page in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000020</TD><TD VALIGN="TOP">Can staple output.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000040</TD><TD VALIGN="TOP">Can do fast copies
+ in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000080</TD><TD VALIGN="TOP">Can do fast copy
+ collation in hardware.</TD></TR>
+<TR><TD VALIGN="TOP">0x00000100</TD><TD VALIGN="TOP">Can punch output.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000200</TD><TD VALIGN="TOP">Can cover output.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000400</TD><TD VALIGN="TOP">Can bind output.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00000800</TD><TD VALIGN="TOP">Can sort output.</TD>
+</TR>
+<TR><TD VALIGN="TOP">0x00001000</TD><TD VALIGN="TOP">Can handle media up
+ to US-Legal/A4.</TD></TR>
+<TR><TD VALIGN="TOP">0x00002000</TD><TD VALIGN="TOP">Can handle media
+ from US-Legal/A4 to ISO-C/A2.</TD></TR>
+<TR><TD VALIGN="TOP">0x00004000</TD><TD VALIGN="TOP">Can handle media
+ larger than ISO-C/A2.</TD></TR>
+<TR><TD VALIGN="TOP">0x00008000</TD><TD VALIGN="TOP">Can handle
+ user-defined media sizes.</TD></TR>
+<TR><TD VALIGN="TOP">0x00010000</TD><TD VALIGN="TOP">Is an implicit
+ (server-generated) class.</TD></TR>
+<TR><TD VALIGN="TOP">0x00020000</TD><TD VALIGN="TOP">Is a network
+ default printer.</TD></TR>
+<TR><TD VALIGN="TOP">0x00040000</TD><TD VALIGN="TOP">Is a facsimile
+ device.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="5_4_6">5.4.6 printer-type-mask (type2 enum)</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The printer-type-mask attribute is used to choose printers or classes
+ with the CUPS-Get-Printers and CUPS-Get-Classes operations. The bits
+ are defined identically to the printer-type attribute and default to
+ all 1's.</P>
+<H3><A NAME="5_4_7">5.4.7 requesting-user-name-allowed (1setof
+ name(127))</A></H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The requesting-user-name-allowed attribute lists all of the users
+ that are allowed to access a printer or class. Either this attribute or
+ the requesting-user-name-denied attribute will be defined, but not
+ both.</P>
+<H3><A NAME="5_4_8">5.4.8 requesting-user-name-denied (1setof name(127))</A>
+</H3>
+<P><I>(CUPS 1.1 and higher)</I></P>
+<P>The requesting-user-name-denied attribute lists all of the users that
+ are not allowed to access a printer or class. Either this attribute or
+ the requesting-user-name-allowed attribute will be defined, but not
+ both.</P>
+<H2><A NAME="5_5">5.5 Printer Class Attributes</A></H2>
+<H3><A NAME="5_5_1">5.5.1 member-names (1setof name(127))</A></H3>
+<P>The member-names attribute specifies each of the printer-name
+ attributes of the member printers and classes. Each name corresponds to
+ the same element of the member-uris attribute.</P>
+<H3><A NAME="5_5_2">5.5.2 member-uris (1setof uri)</A></H3>
+<P>The member-uris attribute specifies each of the printer-uri
+ attributes of the member printers and classes. Each URI corresponds to
+ the same element of the member-names attribute.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
+<H2><A NAME="6_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="6_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/ipp.pdf b/doc/ipp.pdf
new file mode 100644
index 000000000..d9ba2b39c
--- /dev/null
+++ b/doc/ipp.pdf
Binary files differ
diff --git a/doc/ipp.shtml b/doc/ipp.shtml
new file mode 100644
index 000000000..58331f9c7
--- /dev/null
+++ b/doc/ipp.shtml
@@ -0,0 +1,2085 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004 All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-IPP-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Implementation of IPP</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This document provides an overview of the Internet Printing Protocol
+("IPP") version 1.1 as implemented in the Common UNIX Printing System
+("CUPS") version 1.1.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This document is organized into the following sections:
+
+<UL>
+ <LI><A HREF="#1">1 - Scope</A>
+ <LI><A HREF="#2">2 - References</A>
+ <LI><A HREF="#3">3 - Overview</A>
+ <LI><A HREF="#4">4 - Operations</A>
+ <LI><A HREF="#5">5 - Attributes</A>
+ <LI><A HREF="#6">A - Glossary</A>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Overview</H1>
+
+<P>CUPS 1.1 implements IPP/1.1 and the operations and attributes
+defined in the "IPP: Job and Printer Set Operations",
+"IPP/1.1: Output-bin Attribute Extension", and "IPP/1.1: finishings
+'fold',' trim', and 'bale' attribute values extension" specifications.
+
+<P>CUPS also provides 13 new operations and many new attributes to
+support multiple IPP printers and printer classes on a single host.
+
+<H2>IPP URIs</H2>
+
+<P>CUPS supports both the "http" and "ipp" methods. The following
+resource names are used:
+
+<DL>
+
+ <DT>method://hostname:port/
+
+ <DD>Can be used for all "get" operations.
+
+ <DT>method://hostname:port/admin
+
+ <DD>Used for all administrative operations.
+
+ <DT>method://hostname:port/classes/name
+
+ <DD>Specifies a printer class.
+
+ <DT>method://hostname:port/jobs/id
+
+ <DD>Specifies a job.
+
+ <DT>method://hostname:port/printers/name
+
+ <DD>Specifies a printer.
+
+</DL>
+
+<P>So a typical printer URI would be "ipp://foo.bar.com/printers/LaserJet".
+
+<P>In addition, the CUPS server also supports normal browser access to
+"method://hostname:port/admin/", "method://hostname:port/classes/",
+"method://hostname:port/jobs/", and "method://hostname:port/printers/"
+to view and manage resources on the server dynamically.
+
+<H2>CUPS IPP Operations</H2>
+
+<P>CUPS provides 13 extension operations in addition to most of the
+standard IPP and registered extension operations:
+
+<CENTER><TABLE BORDER WIDTH="80%">
+<TR>
+ <TH VALIGN="TOP">Operation Name</TH>
+ <TH VALIGN="TOP">CUPS</TH>
+ <TH VALIGN="TOP">Code</TH>
+ <TH VALIGN="TOP">Brief Description</TH>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Print-Job</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0002</TD>
+ <TD VALIGN="TOP">Print a file.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Validate-Job</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0004</TD>
+ <TD VALIGN="TOP">Validate job attributes.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Create-Job</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x0005</TD>
+ <TD VALIGN="TOP">Create a print job.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Send-Document</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x0006</TD>
+ <TD VALIGN="TOP">Send a file for a print job.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Cancel-Job</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0008</TD>
+ <TD VALIGN="TOP">Cancel a print job.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Get-Job-Attributes</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0009</TD>
+ <TD VALIGN="TOP">Get job attributes.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Get-Jobs</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x000A</TD>
+ <TD VALIGN="TOP">Get all jobs.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Get-Printer-Attributes</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x000B</TD>
+ <TD VALIGN="TOP">Get printer attributes.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Hold-Job</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x000C</TD>
+ <TD VALIGN="TOP">Hold a job for printing.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Release-Job</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x000D</TD>
+ <TD VALIGN="TOP">Release a job for printing.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Pause-Printer</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0010</TD>
+ <TD VALIGN="TOP">Pause printing on a printer.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Resume-Printer</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0011</TD>
+ <TD VALIGN="TOP">Resume printing on a printer.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Purge-Jobs</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x0012</TD>
+ <TD VALIGN="TOP">Purge all jobs.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">Set-Job-Attributes</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x0014</TD>
+ <TD VALIGN="TOP">Set attributes for a pending or held job.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Get-Default</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4001</TD>
+ <TD VALIGN="TOP">Get the default destination.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Get-Printers</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4002</TD>
+ <TD VALIGN="TOP">Get all of the available printers.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Add-Modify-Printer</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4003</TD>
+ <TD VALIGN="TOP">Add or modify a printer.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Delete-Printer</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4004</TD>
+ <TD VALIGN="TOP">Delete a printer.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Get-Classes</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4005</TD>
+ <TD VALIGN="TOP">Get all of the available printer classes.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Add-Modify-Class</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4006</TD>
+ <TD VALIGN="TOP">Add or modify a printer class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Delete-Class</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4007</TD>
+ <TD VALIGN="TOP">Delete a printer class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Accept-Jobs</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4008</TD>
+ <TD VALIGN="TOP">Accept jobs on a printer or printer class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Reject-Jobs</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x4009</TD>
+ <TD VALIGN="TOP">Reject jobs on a printer or printer class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Set-Default</TD>
+ <TD VALIGN="TOP">1.0</TD>
+ <TD VALIGN="TOP">0x400A</TD>
+ <TD VALIGN="TOP">Set the default destination.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Get-Devices</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x400B</TD>
+ <TD VALIGN="TOP">Get all of the available devices.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Get-PPDs</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x400C</TD>
+ <TD VALIGN="TOP">Get all of the available PPDs.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">CUPS-Move-Job</TD>
+ <TD VALIGN="TOP">1.1</TD>
+ <TD VALIGN="TOP">0x400D</TD>
+ <TD VALIGN="TOP">Move a job to a different printer.</TD>
+</TR>
+</TABLE>
+</CENTER>
+
+<H1>Operations</H1>
+
+<P>The following sections describe the operations supported by CUPS.
+In the interest of brevity, operations which use only the standard
+IPP attributes are not described.
+
+<H2>Print-Job Operation</H2>
+
+<P>The Print-Job operation (0x0002) prints a file.
+
+<H3>Print-Job Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+Print-Job request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer.
+
+</UL>
+
+<P>Group 2: Job Template Attributes
+
+<UL>
+
+ <P>"job-billing" (text(MAX)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a billing string that is logged
+ with the page accounting information.
+
+ <P>"job-sheets" (1setof type3 keyword | name(MAX)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies one or two banner pages that
+ are printed before and after any files in the print job. The
+ name of "none" is reserved to indicate that no banner page
+ should be printed. If the client does not specify this
+ attribute then the value of the "job-sheets-default" printer
+ object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.
+
+ <P>"media" (1setof type3 keyword | name(MAX)):
+
+ <P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output
+ media. If the client does not specify this attribute then the
+ value of the "media-default" printer object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ media attribute value.
+
+ <P>Other Job Template Attributes
+
+</UL>
+
+<P>The Print-Job request is followed by a file to be printed.
+
+<H3>Print-Job Response</H3>
+
+<P>The following groups of attributes are send as part of the Print-Job
+Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Job Attributes
+
+<UL>
+
+ <P>Standard Job Attributes
+
+</UL>
+
+<H2>Create-Job Operation</H2>
+
+<P>The Create-Job operation (0x0005) creates a new, empty print job.
+
+<H3>Create-Job Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+Create-Job request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer.
+
+</UL>
+
+<P>Group 2: Job Template Attributes
+
+<UL>
+
+ <P>"job-billing" (text(MAX)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a billing string that is logged
+ with the page accounting information.
+
+ <P>"job-sheets" (1setof type3 keyword | name(MAX)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies one or two banner pages that
+ are printed before and after any files in the print job. The
+ name of "none" is reserved to indicate that no banner page
+ should be printed. If the client does not specify this
+ attribute then the value of the "job-sheets-default" printer
+ object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.
+
+ <P>"media" (1setof type3 keyword | name(MAX)):
+
+ <P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output
+ media. If the client does not specify this attribute then the
+ value of the "media-default" printer object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ media attribute value.
+
+ <P>Standard Job Template Attributes
+
+</UL>
+
+<H3>Create-Job Response</H3>
+
+<P>The following groups of attributes are send as part of the
+Create-Job Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Job Attributes
+
+<UL>
+
+ <P>Standard Job Attributes
+
+</UL>
+
+<H2>Set-Job-Attributes Operation</H2>
+
+<P>The Set-Job-Attributes operation (0x0014) changes the attributes of
+an active (not completed) job.
+
+<H3>Set-Job-Attributes Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+Set-Job-Attributes request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri) and "job-id" (integer)
+ <P><I>OR</I>
+ <P>"job-uri":
+
+ <P>The client MUST supply a URI for the specified printer and
+ a job ID number, or the job URI.
+
+</UL>
+
+<P>Group 2: Job Template Attributes
+
+<UL>
+
+ <P>"job-sheets" (1setof type3 keyword | name(MAX)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies one or two banner pages that
+ are printed before and after any files in the print job. The
+ name of "none" is reserved to indicate that no banner page
+ should be printed. If the client does not specify this
+ attribute then the value of the "job-sheets-default" printer
+ object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ job-sheets attribute value.
+
+ <P>"media" (1setof type3 keyword | name(MAX)):
+
+ <P>The client OPTIONALLY supplies one or more media attributes
+ specifying the size, type, source, and color of the output
+ media. If the client does not specify this attribute then the
+ value of the "media-default" printer object attribute is used.
+
+ <P><B>Note:</B> Standard IPP only allows specification of a single
+ media attribute value.
+
+ <P>Other Job Template Attributes
+
+</UL>
+
+<H3>Set-Job-Attributes Response</H3>
+
+<P>The following groups of attributes are send as part of the Set-Job-Attributes
+Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Get-Default Operation</H2>
+
+<P>The CUPS-Get-Default operation (0x4001) returns the default printer
+URI and attributes.
+
+<H3>CUPS-Get-Default Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Get-Default request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"requested-attributes" (1setOf keyword) :
+
+ <P>The client OPTIONALLY supplies a set of attribute names
+ and/or attribute group names in whose values the requester is
+ interested. If the client omits this attribute, the server
+ responds as if this attribute had been supplied with a value of
+ 'all'.
+
+</UL>
+
+<H3>CUPS-Get-Default Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Get-Default Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Printer Object Attributes
+
+<UL>
+
+ <P>The set of requested attributes and their current values.
+
+</UL>
+
+<H2>CUPS-Get-Printers Operation</H2>
+
+<P>The CUPS-Get-Printers operation (0x4002) returns the printer
+attributes for every printer known to the system. This may include
+printers that are not served directly by the server.
+
+<H3>CUPS-Get-Printers Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Get-Printers request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"limit" (integer (1:MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute limiting the
+ number of printers that are returned.
+
+ <P>"printer-info" (text(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies this attribute to
+ select which printers are returned.
+
+ <P>"printer-location" (text(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies this attribute to
+ select which printers are returned.
+
+ <P>"printer-type" (type2 enum):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a printer type enumeration to
+ select which printers are returned.
+
+ <P>"printer-type-mask" (type2 enum):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a printer type mask
+ enumeration to select which bits are used in the "printer-type"
+ attribute.
+
+ <P>"requested-attributes" (1setOf keyword) :
+
+ <P>The client OPTIONALLY supplies a set of attribute names
+ and/or attribute group names in whose values the requester is
+ interested. If the client omits this attribute, the server
+ responds as if this attribute had been supplied with a value of
+ 'all'.
+
+</UL>
+
+<H3>CUPS-Get-Printers Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Get-Printers Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Printer Object Attributes
+
+<UL>
+
+ <P>The set of requested attributes and their current values for
+ each printer.
+
+</UL>
+
+<H2>CUPS-Add-Modify-Printer Operation</H2>
+
+<P>The CUPS-Add-Modify-Printer operation (0x4003) adds a new printer or
+modifies an existing printer on the system.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Add-Modify-Printer Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Add-Modify-Printer request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer.
+
+</UL>
+
+<P>Group 2: Printer Object Attributes
+
+<UL>
+
+ <P>"banner-end-default" (name(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a banner page name that is
+ printed after files in a job. The reserved name "none" is used to
+ specify that no banner page should be printed.
+
+ <P>"banner-start-default" (name(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a banner page name that is
+ printed before files in a job. The reserved name "none" is used to
+ specify that no banner page should be printed.
+
+ <P>"device-uri" (uri):
+
+ <P>The client OPTIONALLY supplies a device URI for the
+ specified printer.
+
+ <P>"ppd-name" (name(127)):
+
+ <P>The client OPTIONALLY supplies a PPD name for the specified
+ printer.
+
+ <P>"printer-is-accepting-jobs" (boolean):
+
+ <P>The client OPTIONALLY supplies this boolean attribute
+ indicating whether or not the printer object should accept new jobs.
+
+ <P>"printer-info" (text(127)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating the
+ printer information string.
+
+ <P>"printer-location" (text(127)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ textual location of the printer.
+
+ <P>"printer-more-info" (uri):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ URI for additional printer information.
+
+ <P>"printer-state" (type2 enum):
+
+ <P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the printer. Only the "idle" and "stopped"
+ enumerations are recognized.
+
+ <P>"printer-state-message" (text(MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ textual reason for the current printer state.
+
+ <P>"requesting-user-name-allowed" (1setof name(127) | delete)
+ <P><I>OR</I>
+ <P>"requesting-user-name-denied" (1setof name(127) | delete):
+
+ <P>The client OPTIONALLY supplies one of these attributes to
+ specify an access control list for incoming print jobs. To allow
+ all users access to a printer, use the delete tag for the
+ attribute value.
+
+</UL>
+
+<P>The CUPS-Add-Modify-Printer request can optionally be followed by a PPD
+file or System V interface script to be used for the printer. The
+"ppd-name" attribute overrides any file that is attached to the end of
+the request with a local CUPS PPD file.
+
+<H3>CUPS-Add-Modify-Printer Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Add-Modify-Printer Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Delete-Printer Operation</H2>
+
+<P>The CUPS-Delete-Printer operation (0x4004) removes an existing
+printer from the system.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Delete-Printer Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Delete-Printer request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer.
+
+</UL>
+
+<H3>CUPS-Delete-Printer Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Delete-Printer Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Get-Classes Operation</H2>
+
+<P>The CUPS-Get-Classes operation (0x4005) returns the printer
+attributes for every printer class known to the system. This may
+include printer classes that are not served directly by the server.
+
+<H3>CUPS-Get-Classes Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Get-Classes request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"limit" (integer (1:MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute limiting the
+ number of printer classes that are returned.
+
+ <P>"printer-info" (text(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies this attribute to
+ select which printer classes are returned.
+
+ <P>"printer-location" (text(127)):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies this attribute to
+ select which printer classes are returned.
+
+ <P>"printer-type" (type2 enum):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a printer type enumeration to
+ select which printer classes are returned.
+
+ <P>"printer-type-mask" (type2 enum):
+
+ <P><I>(CUPS 1.1 and higher)</I>
+
+ <P>The client OPTIONALLY supplies a printer type mask
+ enumeration to select which bits are used in the "printer-type"
+ attribute.
+
+ <P>"requested-attributes" (1setOf keyword) :
+
+ <P>The client OPTIONALLY supplies a set of attribute names
+ and/or attribute group names in whose values the requester is
+ interested. If the client omits this attribute, the server responds as
+ if this attribute had been supplied with a value of 'all'.
+
+</UL>
+
+<H3>CUPS-Get-Classes Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Get-Classes Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Printer Class Object Attributes
+
+<UL>
+
+ <P>The set of requested attributes and their current values for
+ each printer class.
+
+</UL>
+
+<H2>CUPS-Add-Modify-Class Operation</H2>
+
+<P>The CUPS-Add-Modify-Class operation (0x4006) adds a new printer class or
+modifies and existing printer class on the system.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Add-Modify-Class Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Add-Modify-Class request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer class.
+
+</UL>
+
+<P>Group 2: Printer Object Attributes
+
+<UL>
+
+ <P>"member-uris" (1setof uri):
+
+ <P>The client OPTIONALLY supplies the "member-uris" set
+ specifying the printers and printer classes that are part of the class.
+
+ <P>"printer-is-accepting-jobs" (boolean):
+
+ <P>The client OPTIONALLY supplies this boolean attribute
+ indicating whether or not the class object should accept new jobs.
+
+ <P>"printer-info" (text(127)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating the
+ printer information string.
+
+ <P>"printer-location" (text(127)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ textual location of the class.
+
+ <P>"printer-more-info" (uri):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ URI for additional class information.
+
+ <P>"printer-state" (type2 enum):
+
+ <P>The client OPTIONALLY supplies this attribute indicating the
+ initial/current state of the class. Only the "idle" and "stopped"
+ enumerations are recognized.
+
+ <P>"printer-state-message" (text(MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ textual reason for the current class state.
+
+ <P>"requesting-user-name-allowed" (1setof name(127))
+ <P><I>OR</I>
+ <P>"requesting-user-name-denied" (1setof name(127)):
+
+ <P>The client OPTIONALLY supplies one of these attributes to
+ specify an access control list for incoming print jobs. To allow
+ all users access to a class, use the delete tag for the
+ attribute value.
+
+</UL>
+
+<H3>CUPS-Add-Modify-Class Response</H3>
+
+<P>The following groups of attributes are send as part of the CUPS-Add-Modify-Class Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Delete-Class Operation</H2>
+
+<P>The CUPS-Delete-Class operation (0x4007) removes an existing printer
+class from the system.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Delete-Class Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Delete-Class request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer class.
+
+</UL>
+
+<H3>CUPS-Delete-Class Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Delete-Class Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Accept-Jobs Operation</H2>
+
+<P>The CUPS-Accept-Jobs operation (0x4008) sets the
+"printer-is-accepting-jobs" attribute to true for the specified printer
+or printer class.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Accept-Jobs Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Accept-Jobs request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer or printer class.
+
+</UL>
+
+<H3>CUPS-Accept-Jobs Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Accept-Jobs Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Reject-Jobs Operation</H2>
+
+<P>The CUPS-Reject-Jobs operation (0x4009) sets the
+"printer-is-accepting-jobs" attribute to false for the specified
+printer or printer class.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Reject-Jobs Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Reject-Jobs request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer or printer class.
+
+</UL>
+
+<P>Group 2: Printer Object Attributes
+
+<UL>
+
+ <P>"printer-state-message" (text(MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute indicating a
+ textual reason for the current printer state.
+
+</UL>
+
+<H3>CUPS-Reject-Jobs Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Reject-Jobs Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Set-Default Operation</H2>
+
+<P>The CUPS-Set-Default operation (0x400A) sets the default printer
+destination for all clients.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>This operation requires administrative priviledges
+ and must be POSTed to "/admin/". POSTs to other paths
+ will result in a client-error-not-authorized
+ (IPP_NOT_AUTHORIZED) error.
+
+</TR>
+</TABLE></CENTER>
+
+<H3>CUPS-Set-Default Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Set-Default request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri):
+
+ <P>The client MUST supply a URI for the specified printer or
+ printer class.
+
+</UL>
+
+<H3>CUPS-Set-Default Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Set-Default Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H2>CUPS-Get-Devices Operation</H2>
+
+<P>The CUPS-Get-Devices operation (0x400B) returns all of the supported
+device-uri's for the server (CUPS 1.1 and higher).
+
+<H3>CUPS-Get-Devices Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Get-Devices request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"device-class" (type1 keyword):
+
+ <P>The client OPTIONALLY supplies a device class keyword to select
+ which devices are returned.
+
+ <P>"limit" (integer (1:MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute limiting the number of
+ devices that are returned.
+
+ <P>"requested-attributes" (1setOf keyword) :
+
+ <P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.
+
+</UL>
+
+<H3>CUPS-Get-Devices Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Get-Devices Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: Device Object Attributes
+
+<UL>
+
+ <P>The set of requested attributes and their current values for
+ each device.
+
+</UL>
+
+<H2>CUPS-Get-PPDs Operation</H2>
+
+<P>The CUPS-Get-PPDs operation (0x400C) returns all of the locally
+available PPD files on the system (CUPS 1.1 and higher).
+
+<H3>CUPS-Get-PPDs Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Get-PPDs request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"limit" (integer (1:MAX)):
+
+ <P>The client OPTIONALLY supplies this attribute limiting the number of
+ PPDs that are returned.
+
+ <P>"ppd-make" (text(127)):
+
+ <P>The client OPTIONALLY supplies a printer manufacturer to select
+ which PPDs are returned.
+
+ <P>"requested-attributes" (1setOf keyword) :
+
+ <P>The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is interested. If
+ the client omits this attribute, the server responds as if this
+ attribute had been supplied with a value of 'all'.
+
+</UL>
+
+<H3>CUPS-Get-PPDs Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Get-PPDs Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<P>Group 2: PPD Attributes
+
+<UL>
+
+ <P>The set of requested attributes and their current values for each
+ PPD file.
+
+</UL>
+
+<H2>CUPS-Move-Job Operation</H2>
+
+<P>The CUPS-Move-Job operation (0x400D) moves an active print job to a
+different printer (CUPS 1.1 and higher).
+
+<H3>CUPS-Move-Job Request</H3>
+
+<P>The following groups of attributes are supplied as part of the
+CUPS-Move-Job request:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1 of the IPP Model and
+ Semantics document.
+
+ <P>"printer-uri" (uri) and "job-id" (integer)
+ <P><I>OR</I>
+ <P>"job-uri":
+
+ <P>The client MUST supply a URI for the specified printer and
+ a job ID number, or the job URI.
+
+</UL>
+
+<P>Group 2: Job Template Attributes
+
+<UL>
+
+ <P>"job-printer-uri" (uri)
+
+ <P>The client MUST supply a URI for a printer on the same server.
+
+</UL>
+
+<H3>CUPS-Move-Job Response</H3>
+
+<P>The following groups of attributes are send as part of the
+CUPS-Move-Job Response:
+
+<P>Group 1: Operation Attributes
+
+<UL>
+
+ <P>Status Message:
+
+ <P>The standard response status message.
+
+ <P>Natural Language and Character Set:
+
+ <P>The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2 of the IPP Model and
+ Semantics document.
+
+</UL>
+
+<H1>Attributes</H1>
+
+<P>CUPS provides many extension attributes to support multiple devices,
+PPD files, standard job filters, printers, and printer classes.
+
+<H2>Device Attributes</H2>
+
+<P>Device attributes are returned by the CUPS-Get-Devices operation and
+enumerate all of the available hardware devices and network protocols
+that are supported by the server.
+
+<H3>device-class (type2 keyword)</H3>
+
+<P>The device-class attribute specifies the class of device and can be
+one of the following:
+
+<UL>
+
+ <LI>"file" - a disk file.
+
+ <LI>"direct" - a parallel or fixed-rate serial data port,
+ currently used for Centronics, IEEE-1284, and USB printer
+ ports.
+
+ <LI>"serial" - a variable-rate serial port.
+
+ <LI>"network" - a network connection, typically via AppSocket,
+ HTTP, IPP, LPD, or SMB/CIFS protocols.
+
+</UL>
+
+<H3>device-info (text(127))</H3>
+
+<P>The device-info attribute specifies a human-readable string describing
+the device, e.g. "Parallel Port #1".
+
+<H3>device-make-and-model (text(127))</H3>
+
+<P>The device-makr-and-model attribute specifies a device
+identification string provided by the printer connected to the device.
+If the device or printer does not support identification then this
+attribute contains the string "unknown".
+
+<H3>device-uri (uri)</H3>
+
+<P>The device-uri attribute specifies a unique identifier for the
+device. The actual format of the device-uri string depends on the value
+of the device-class attribute:
+
+<UL>
+
+ <LI>"file" - The device-uri will be of the form
+ "file:/path/to/filename".
+
+ <LI>"direct" - The device-uri will be of the form
+ "method:/dev/filename", where method may be "parallel" or "usb"
+ in the current implementation.
+
+ <LI>"serial" - The device-uri will be of the form
+ "serial:/dev/filename?baud=value+parity=value+flow=value".
+ The baud value is the data rate in bits per second; the
+ supported values depend on the underlying hardware.
+ The parity value can be one of "none", "even", or "odd".
+ The flow value can be one of "none", "soft" (XON/XOFF
+ handshaking), "hard" or "rts/cts" (RTS/CTS handshaking),
+ or "dtrdsr" (DTR/DSR handshaking).
+
+ <P>The URI returned by CUPS-Get-Devices will contain the
+ maximum baud rate supported by the device and the best
+ type of flow control available ("soft" or "hard").
+
+ <LI>"network" - The device-uri will be of the form
+ "method://[username:password@]hostname[:port]/[resource]",
+ where method may be "http", "ipp", "lpd", "smb", or
+ "socket" in the current implementation.
+
+ <P>The URI returned by CUPS-Get-Devices will only contain
+ the method name followed by two slashes ("method://").
+ It is up to the client application to add the appropriate
+ host and other information when adding a new printer.
+
+ <P>The URI returned by Get-Printer-Attributes and
+ CUPS-Get-Printers has any username and password information
+ stripped; the information is still stored and used by the
+ server internally to perform any needed authentication.
+
+</UL>
+
+<H2>Job Template Attributes</H2>
+
+<H3>blackplot (boolean)</H3>
+
+<P>The blackplot attribute specifies whether HP-GL/2 plot files should be
+rendered entirely in black ink (blackplot=true) or using the colors and shades
+specified in the file (blackplot=false). The default value is false.
+
+<H3>brightness (integer(0:200))</H3>
+
+<P>The brightness attribute specifies the overall brightness of the printed
+output in percent. A brightness of 100 is normal, while 200 is twice as
+bright and 50 is half as bright. The default value is 100.
+
+<P>Brightness is applied to the Cyan, Magenta, Yellow, and Black values using
+the function "f(x) = brightness / 100 * x".
+
+<H3>columns (integer(1:4))</H3>
+
+<P>The columns attribute specifies the number of columns to generate when
+printing text files. The default value is 1.
+
+<H3>cpi (type2 enum)</H3>
+
+<P>The cpi attribute specifies the number of characters per inch when
+printing text files. Only the values 10, 12, and 17 are currently
+supported. The default value is 10.
+
+<H3>fitplot (boolean)</H3>
+
+<P>The fitplot attribute specifies whether to scale HP-GL/2 plot files to
+fit on the selected media (fitplot=true) or use the physical scale specified
+in the plot file (fitplot=false). The default value is false.
+
+<H3>gamma (integer(1:10000))</H3>
+
+<P>The gamma attribute specifies the luminance correction for the output.
+A value of 1000 specifies no correction, while values of 2000 and 500 will
+generate lighter and darker output, respectively. The default value is
+1000.
+
+<P>Gamma is applied to the Red, Green, and Blue values (or luminance for
+grayscale output) using the function "f(x) = x<SUP>(1000/gamma)</SUP>".
+
+<H3>hue (integer(-180:180))</H3>
+
+<P>The hue attribute specifies a color hue rotation when printing image
+files. The default value is 0.
+
+<H3>job-billing (text(MAX))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-billing attribute provides a text value to associate with a job
+for billing purposes.
+
+<H3>job-hold-until (keyword | name(MAX))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-hold-until attribute specifies a hold time. In addition to the
+standard IPP/1.1 keyword names, CUPS supports name values of the form
+"HH:MM" and "HH:MM:SS" that specify a hold time. The hold time is in
+Greenwich Mean Time (GMT) and <I>not</I> in the local time zone. If the
+specified time is less than the current time, the job is held until the
+next day.
+
+<H3>job-sheets (1setof type3 keyword | name(MAX))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-sheets attribute specifies one or two banner files that are printed
+before and after a job. The reserved value of "none" disables banner printing.
+The default value is stored in the job-sheets-default attribute.
+
+<P>If only one value is supplied, the banner file is printed before the job.
+If two values are supplied, the first value is used as the starting banner
+file and the second as the ending banner file.
+
+<H3>job-originating-host-name (name(MAX))</H3>
+
+<P><I>(CUPS 1.1.5 and higher)</I>
+
+<P>The job-originating-host-name attribute specifies the host
+from which the job was queued. The value will be the hostname or
+IP address of the client depending on whether hostname
+resolution is enabled. The localhost address (127.0.0.1) is
+<B>always</B> resolved to the name "localhost".
+
+<P>This attribute is read-only.
+
+<H3>lpi (type2 enum)</H3>
+
+<P>The lpi attribute specifies the number of lines per inch when
+printing text files. Only the values 6 and 8 are currently supported.
+The default value is 6.
+
+<H3>mirror (boolean)</H3>
+
+<P>The mirror attribute specifies whether pages are mirrored on
+their X axis, which is useful for printing transfer images on
+special media. The default value is false.
+
+<H3>natural-scaling (integer(1:1000))</H3>
+
+<P><I>(CUPS 1.1.9 and higher)</I>
+
+<P>The natural-scaling attribute specifies the scaling of image files with
+respect to the natural image size. A value of 100 specifies that the image
+file should exactly the natural size, while 50 is half the natural size
+and 200 is twice the natural size. The default value is 100.
+
+<P>The ppi option can be used to override the natural resolution of the
+image, which controls the natural size.
+
+<H3>number-up-layout (type2 keyword)</H3>
+
+<P><I>(CUPS 1.1.15 and higher)</I>
+
+<P>The number-up-layout attribute specifies the order each input
+page is placed on each output page. The following keywords are
+presently defined:
+
+<UL>
+
+ <LI><CODE>btlr</CODE> - Bottom to top, left to right</LI>
+
+ <LI><CODE>btrl</CODE> - Bottom to top, right to left</LI>
+
+ <LI><CODE>lrbt</CODE> - Left to right, bottom to top</LI>
+
+ <LI><CODE>lrtb</CODE> - Left to right, top to bottom (default)</LI>
+
+ <LI><CODE>rlbt</CODE> - Right to left, bottom to top</LI>
+
+ <LI><CODE>rltb</CODE> - Right to left, top to bottom</LI>
+
+ <LI><CODE>tblr</CODE> - Top to bottom, left to right</LI>
+
+ <LI><CODE>tbrl</CODE> - Top to bottom, right to left</LI>
+
+</UL>
+
+<H3>page-border (type2 keyword)</H3>
+
+<P><I>(CUPS 1.1.15 and higher)</I>
+
+<P>The page-border attribute specifies whether a border is
+draw around each page. The following keywords are presently
+defined:
+
+<UL>
+
+ <LI><CODE>double</CODE> - Two hairline borders are drawn</LI>
+
+ <LI><CODE>double-thick</CODE> - Two 1pt borders are drawn</LI>
+
+ <LI><CODE>none</CODE> - No border is drawn (default)</LI>
+
+ <LI><CODE>single</CODE> - A single hairline border is drawn</LI>
+
+ <LI><CODE>single-thick</CODE> - A single 1pt border is drawn</LI>
+
+</UL>
+
+<H3>page-bottom (integer(0:MAX))</H3>
+
+<P>The page-bottom attribute specifies the bottom margin in points (72 points
+equals 1 inch). The default value is the device physical margin.
+
+<H3>page-label (text(MAX))</H3>
+
+<P><I>(CUPS 1.1.7 and higher)</I>
+
+<P>The page-label attribute provides a text value to place in
+the header and footer on each page. If a classification level is
+set on the server, then this classification is printed before
+the page label.
+
+<H3>page-left (integer(0:MAX))</H3>
+
+<P>The page-left attribute specifies the left margin in points (72 points
+equals 1 inch). The default value is the device physical margin.
+
+<H3>page-right (integer(0:MAX))</H3>
+
+<P>The page-right attribute specifies the right margin in points (72 points
+equals 1 inch). The default value is the device physical margin.
+
+<H3>page-set (type2 keyword)</H3>
+
+<P>The page-set attribute specifies which pages to print in a file. The
+supported keywords are "all", "even", and "odd". The default value is
+"all".
+
+<H3>page-top (integer(0:MAX))</H3>
+
+<P>The page-top attribute specifies the top margin in points (72 points
+equals 1 inch). The default value is the device physical margin.
+
+<H3>penwidth (integer(0:MAX))</H3>
+
+<P>The penwidth attribute specifies the default pen width in micrometers
+when printing HP-GL/2 plot files. The default value is 1000 (1 millimeter).
+
+<H3>position (type2 keyword)</H3>
+
+<P>The position attribute specifies the location of image files on the
+media. The following keyword values are recognized:
+
+<UL>
+
+ <LI><CODE>center</CODE> - Center the image on the page (default)
+
+ <LI><CODE>top</CODE> - Print the image centered at the top of the page
+
+ <LI><CODE>left</CODE> - Print the image centered on the left of page
+
+ <LI><CODE>right</CODE> - Print the image centered on the right of the page
+
+ <LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page
+
+ <LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page
+
+ <LI><CODE>bottom</CODE> - Print the image centered at the bottom of
+ the page
+
+ <LI><CODE>bottom-left</CODE> - Print the image at the bottom left
+ corner of the page
+
+ <LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page
+
+</UL>
+
+<H3>ppi (integer(1:MAX))</H3>
+
+<P>The ppi attribute specifies the resolution of an image file in pixels
+per inch. The default value is the resolution included with the file or
+128 if no resolution information is available.
+
+<H3>prettyprint (boolean)</H3>
+
+<P>The prettyprint attribute specifies whether text files should be printed
+with a shaded header and keyword highlighting (prettyprint=true) or without
+additional formatting (prettyprint=false). The default value is false.
+
+<H3>saturation (integer(0:200))</H3>
+
+<P>The saturation attribute specifies the color saturation when
+printing image files. A saturation of 100 is normal, while values of 50
+and 200 will be half and twice as colorful, respectively. The default
+value is 100.
+
+<H3>scaling (integer(1:1000))</H3>
+
+<P>The scaling attribute specifies the scaling of image files with
+respect to the selected media. A value of 100 specifies that the image
+file should fit 100% of the page, or as much as possible given the
+image dimensions. The default value is unspecified.
+
+<P>The scaling attribute overrides the ppi attribute if specified.
+
+<H3>wrap (boolean)</H3>
+
+<P>The wrap attribute specifies whether long lines should be wrapped
+(wrap=true) or not (wrap=false) when printing text files. The default
+value is true.
+
+<H2>PPD Attributes</H2>
+
+<H3>ppd-natural-language (naturalLanguage)</H3>
+
+<P>The ppd-natural-language attribute specifies the language encoding
+of the PPD file (the LanguageVersion attribute in the PPD file). If the
+language is unknown or undefined then "en" (English) is assumed.
+
+<H3>ppd-make (text(127))</H3>
+
+<P>The ppd-make attribute specifies the manufacturer of the printer
+(the Manufacturer attribute in the PPD file). If the manufacturer
+is not specified in the PPD file then an educated guess is made using
+the NickName attribute in the PPD file.
+
+<H3>ppd-make-and-model (text(127))</H3>
+
+<P>The ppd-make-and-model attribute specifies the manufacturer and model
+name of the PPD file (the NickName attribute in the PPD file). If the
+make and model is not specified in the PPD file then the ModelName or
+ShortNickName attributes are used instead.
+
+<H3>ppd-name (name(255))</H3>
+
+<P>The ppd-name attribute specifies the PPD filename on the server
+relative to the model directory. The forward slash (/) is used to
+delineate directories.
+
+<H2>Printer Attributes</H2>
+
+<H3>job-k-limit (integer)</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-k-limit attribute specifies the maximum number of kilobytes that
+may be printed by a user, including banner files. The default value of 0
+specifies that there is no limit.
+
+<H3>job-page-limit (integer)</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-page-limit attribute specifies the maximum number of pages that
+may be printed by a user, including banner files. The default value of 0
+specifies that there is no limit.
+
+<H3>job-quota-period (integer)</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-quota-period attribute specifies the time period used for quota
+calculations, in seconds. The default value of 0 specifies that the limits
+apply to all jobs that have been printed by a user that are still known to
+the system.
+
+<H3>job-sheets-supported (1setof type3 keyword | name(MAX))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The job-sheets-supported attribute specifies the available banner files.
+There will always be at least one banner file available called "none".
+
+<H3>printer-type (type2 enum)</H3>
+
+<P>The printer-type attribute specifies printer type and capability bits for
+the printer or class. The default value is computed from internal state
+information and the PPD file for the printer. The following bits are defined:
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Bit</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000001</TD>
+ <TD VALIGN="TOP">Is a printer class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000002</TD>
+ <TD VALIGN="TOP">Is a remote destination.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000004</TD>
+ <TD VALIGN="TOP">Can print in black.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000008</TD>
+ <TD VALIGN="TOP">Can print in color.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000010</TD>
+ <TD VALIGN="TOP">Can print on both sides of the page in hardware.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000020</TD>
+ <TD VALIGN="TOP">Can staple output.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000040</TD>
+ <TD VALIGN="TOP">Can do fast copies in hardware.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000080</TD>
+ <TD VALIGN="TOP">Can do fast copy collation in hardware.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000100</TD>
+ <TD VALIGN="TOP">Can punch output.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000200</TD>
+ <TD VALIGN="TOP">Can cover output.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000400</TD>
+ <TD VALIGN="TOP">Can bind output.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00000800</TD>
+ <TD VALIGN="TOP">Can sort output.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00001000</TD>
+ <TD VALIGN="TOP">Can handle media up to US-Legal/A4.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00002000</TD>
+ <TD VALIGN="TOP">Can handle media from US-Legal/A4 to ISO-C/A2.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00004000</TD>
+ <TD VALIGN="TOP">Can handle media larger than ISO-C/A2.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00008000</TD>
+ <TD VALIGN="TOP">Can handle user-defined media sizes.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00010000</TD>
+ <TD VALIGN="TOP">Is an implicit (server-generated) class.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00020000</TD>
+ <TD VALIGN="TOP">Is a network default printer.</TD>
+</TR>
+<TR>
+ <TD VALIGN="TOP">0x00040000</TD>
+ <TD VALIGN="TOP">Is a facsimile device.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>printer-type-mask (type2 enum)</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The printer-type-mask attribute is used to choose printers or classes with
+the CUPS-Get-Printers and CUPS-Get-Classes operations. The bits are defined
+identically to the printer-type attribute and default to all 1's.
+
+<H3>requesting-user-name-allowed (1setof name(127))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The requesting-user-name-allowed attribute lists all of the users that are
+allowed to access a printer or class. Either this attribute or the
+requesting-user-name-denied attribute will be defined, but not both.
+
+<H3>requesting-user-name-denied (1setof name(127))</H3>
+
+<P><I>(CUPS 1.1 and higher)</I>
+
+<P>The requesting-user-name-denied attribute lists all of the users that are
+not allowed to access a printer or class. Either this attribute or the
+requesting-user-name-allowed attribute will be defined, but not both.
+
+<H2>Printer Class Attributes</H2>
+
+<H3>member-names (1setof name(127))</H3>
+
+<P>The member-names attribute specifies each of the printer-name attributes of
+the member printers and classes. Each name corresponds to the same element of
+the member-uris attribute.
+
+<H3>member-uris (1setof uri)</H3>
+
+<P>The member-uris attribute specifies each of the printer-uri attributes of
+the member printers and classes. Each URI corresponds to the same element of
+the member-names attribute.
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/overview.html b/doc/overview.html
new file mode 100644
index 000000000..02d6759f0
--- /dev/null
+++ b/doc/overview.html
@@ -0,0 +1,500 @@
+<HTML>
+<HEAD>
+ <META NAME="Author" CONTENT="Michael Sweet">
+ <TITLE>An Overview of the Common UNIX Printing System</TITLE>
+ <LINK REL=STYLESHEET TYPE="text/css" HREF="cupsdoc.css">
+</HEAD>
+<BODY>
+<TABLE WIDTH="100%">
+<TR VALIGN=TOP>
+ <TD><IMG SRC="images/cups-large.gif" WIDTH="103" HEIGHT="120"></TD>
+ <TD><H1 ALIGN="RIGHT">An Overview of the<BR>
+ Common UNIX Printing System,<BR>
+ Version 1.1</H1>
+
+ <P ALIGN="RIGHT">July 10, 2000<BR>
+ Michael Sweet, Easy Software Products<BR>
+ Copyright 1998-2003, All Rights Reserved.</P>
+ </TD>
+</TR>
+</TABLE>
+
+<P>This whitepaper describes the Common UNIX Printing
+System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>"), a portable and extensible
+printing system for UNIX<SUP>&reg;</SUP>. CUPS is being developed by
+<A HREF="http://www.easysw.com">Easy Software Products</A>, a software
+firm located in Hollywood, Maryland that has been selling commercial
+software for UNIX since 1993 through more than 40 distributors serving
+over 80 countries worldwide.
+
+<P>Additional information on CUPS is available on the World Wide Web at
+"<A HREF="http://www.cups.org">http://www.cups.org</A>".
+
+<H2>Background</H2>
+
+<P>Printing within UNIX has historically been done using one of two
+printing systems - the Berkeley Line Printer Daemon ("LPD") [RFC1179]
+and the AT&amp;T Line Printer system. These printing systems were
+designed in the 70's for printing text to line printers; vendors have
+since added varying levels of support for other types of printers.
+
+<P>Replacements for these printing systems have emerged [LPRng,
+Palladin, PLP], however none of the replacements change the fundamental
+capabilities of these systems.
+
+<P>Over the last few years several attempts at developing a standard
+printing interface have been made, including the draft POSIX Printing
+standard developed by the Institute of Electrical and Electronics
+Engineers, Inc. ("IEEE") [IEEE-1387.4] and Internet Printing Protocol
+("IPP") developed by the Internet Engineering Task Force ("IETF")
+through the Printer Working Group ("PWG") [IETF-IPP]. The POSIX
+printing standard defines a common set of command-line tools as well as
+a C interface for printer administration and print jobs, but has been
+shelved by the IEEE.
+
+<P>The Internet Printing Protocol defines extensions to the HyperText
+Transport Protocol 1.1 [RFC2616] to provide support for remote printing
+services. IPP/1.0 was accepted by the IETF as an experimental Request
+For Comments [RFC] document in October of 1999. Since then the Printer
+Working Group has developed an updated set of specifications for
+IPP/1.1 which have been accepted by the IETF and are awaiting
+publication as proposed standards. Unlike POSIX Printing, IPP enjoys
+widespread industry support and is poised to become the standard
+network printing solution for all operating systems.
+
+<P>CUPS uses IPP/1.1 to provide a complete, modern printing system for
+UNIX that can be extended to support new printers, devices, and
+protocols while providing compatibility with existing UNIX
+applications. CUPS is free software provided under the terms of the
+GNU General Public License and GNU Library General Public License.
+
+<H2>History</H2>
+
+<P>The first production release of CUPS (based on IPP/1.0) was released
+in October of 1999. Since then, we have released several patch updates
+to the original CUPS 1.0 release that addressed security, portability,
+and bugs found, but no new functionality was added to improve the
+stability of the CUPS code.
+
+<P>CUPS 1.1 is based on IPP/1.1 and adds many of the functional
+enhancements that have been requested by our users. As with 1.0, CUPS
+1.1 will be followed by patch releases that address any problems found
+with the software but add no new features.
+
+<H2>Design Overview</H2>
+
+<P>Like most printing systems, CUPS is designed around a central print
+scheduling process that dispatches print jobs, processes administrative
+commands, provides printer status information to local and remote
+programs, and informs users as needed. Figure 1 shows the basic
+organization of CUPS.
+
+<CENTER><IMG SRC="images/cups-block-diagram.gif" WIDTH="470" HEIGHT="170"></CENTER>
+<P ALIGN="CENTER">Figure 1 - CUPS Block Diagram</P>
+
+<H3>Scheduler</H3>
+
+<P>The scheduler is a HTTP/1.1 server application that handles HTTP
+requests. Besides handling printer requests via IPP POST requests, the
+scheduler also acts as a full-featured web server for documentation,
+status monitoring, and administration.
+
+<P>The scheduler also manages a list of available printers on the LAN
+and dispatches print jobs as needed using the appropriate filters and
+backends.
+
+<H3>Configuration Files</H3>
+
+The configuration files consist of:
+
+<UL>
+
+ <LI>The HTTP server configuration file.
+
+ <LI>Printer and class definition files.
+
+ <LI>MIME type and conversion rule files.
+
+ <LI>PostScript Printer Description ("PPD") files.
+
+</UL>
+
+<P>The HTTP server configuration file is purposely similar to the
+Apache server configuration file and defines all of the access control
+properties for the server.
+
+<P>The printer and class definition files list the available printer
+queues and classes. Printer classes are collections of printers. Jobs
+sent to a class are forwarded to the first available printer in the
+class, round-robin fashion.
+
+<P>The MIME type files list the supported MIME types (text/plain,
+application/postscript, etc.) and "magic" rules for automatically
+detecting the format of a file. These are used by the HTTP server to
+determine the <I>Content-Type</I> field for <I>GET</I> and <I>HEAD</I>
+requests and by the IPP request handler to determine the file type
+when a <I>Print-Job</I> or <I>Send-File</I> request is received with a
+<I>document-format</I> of <I>application/octet-stream</I>.
+
+<P>The MIME conversion rule files list the available filters. The
+filters are used when a job is dispatched so that an application can
+send a convenient file format to the printing system which then
+converts the document into a printable format as needed. Each filter
+has a relative cost associated with it, and the filtering algorithm
+chooses the set of filters that will convert the file to the needed
+format with the lowest total "cost".
+
+<P>The PPD files describe the capabilities of all printers, not just
+PostScript printers. There is one PPD file for each printer. PPD files
+for non-PostScript printers define additional filters through
+<I>cupsFilter</I> attributes to support printer drivers.
+
+<H3>CUPS API</H3>
+
+<P>The CUPS API contains CUPS-specific convenience functions for queuing
+print jobs, getting printer information, accessing resources via HTTP
+and IPP, and manipulating PPD files. Unlike the rest of CUPS, the CUPS
+API is provided under the terms of the GNU LGPL so it may be used by
+non-GPL applications.
+
+<H3>Berkeley and System V Commands</H3>
+
+<P>CUPS provides the System V and Berkeley command-line interfaces for
+submitting jobs and checking the printer status. The
+<CODE>lpstat</CODE> and <CODE>lpc status</CODE> commands also show
+network printers ("printer@server") when printer browsing is enabled.
+
+<P>The System V administation commands are supplied for managing
+printers and classes. The Berkeley printer administration tool
+(<CODE>lpc</CODE>) is only supported in a "read-only" mode to check the
+current status of the printer queues and scheduler.
+
+<H3>Filters</H3>
+
+<P>A filter program reads from the standard input or from a file if a
+filename is supplied. All filters must support a common set of options
+including printer name, job ID, username, job title, number of copies,
+and job options. All output is sent to the standard output.
+
+<P>Filters are provided for many file formats and include image file
+and PostScript raster filters that support non-PostScript printers. Multiple
+filters are run in parallel to produce the required output format.
+
+<P>The PostScript raster filter is based on the GNU Ghostscript 5.50
+core. Instead of using the Ghostscript printer drivers and front-end,
+the CUPS filter uses a generic raster printer driver and CUPS-compliant
+front-end to support any kind of raster printer. This allows the same
+printer driver filter to be used for printing raster data from any
+filter.
+
+<H3>CUPS Imaging</H3>
+
+<P>The CUPS Imaging library provides functions for managing large
+images, doing colorspace conversion and color management, scaling
+images for printing, and managing raster page streams. It is used by
+the CUPS image file filters, the PostScript RIP, and all raster
+printers drivers.
+
+<H3>Backends</H3>
+
+<P>A backend program is a special filter that sends print data to a
+device or network connection. Backends for parallel, serial, USB, LPD, IPP,
+and AppSocket (JetDirect) connections are provided in CUPS 1.1.
+
+<P>SAMBA version 2.0.6 and higher includes a SMB backend
+(<CODE>smbspool(1)</CODE>) that can be used with CUPS 1.0 or 1.1 for
+printing to Windows.
+
+<H2>Network Printing</H2>
+
+<P>Traditionally, network printing has been one of the hardest things to
+get working under UNIX. One reason is because each vendor added their
+own extensions to the LPD protocol (the previous standard for network
+printing), making cross-platform printing difficult if not impossible.
+
+<P>Another reason is that you have to administer every network printer
+on every client machine. In some cases you can "clone" the printer
+configuration from a "master" client to each of the others, but even
+that can be time-consuming and error-prone. Something better is needed.
+
+<P>CUPS provides "printer browsing", which allows clients to
+automatically see and use printers from any server on a LAN. This means
+that you only need to configure the server and the clients will
+automatically see the printers and classes on it.
+
+<P>In addition, CUPS can automatically merge multiple identical network
+printers into "implicit classes". This allows clients to send jobs to
+the implicit class and have them print on the first available printer
+or server. In addition, failsafe and load-balancing functions are
+enabled simply by defining the same printer on multiple servers!
+
+<H2>New Features in CUPS 1.1</H2>
+
+<P>CUPS 1.1 includes many new features and capabilities:
+
+<OL>
+
+ <LI><A HREF="#BACKENDS">Backends</A>
+
+ <LI><A HREF="#BANNERS">Banner Page Support</A>
+
+ <LI><A HREF="#DIGEST">Digest Authentication</A>
+
+ <LI><A HREF="#DIRSVC">Directory Services</A>
+
+ <LI><A HREF="#FHS2">Directory Structure Changes</A>
+
+ <LI><A HREF="#DOCOS">Documentation</A>
+
+ <LI><A HREF="#DRIVERS">Drivers</A>
+
+ <LI><A HREF="#FILTERS">Filters</A>
+
+ <LI><A HREF="#IPP">IPP Support</A>
+
+ <LI><A HREF="#PERSISTENCE">Job Persistence</A>
+
+ <LI><A HREF="#LPD">LPD Client Support</A>
+
+ <LI><A HREF="#USEROPTS">User-Defined Printers and Options</A>
+
+ <LI><A HREF="#WEB">Web Administration Interface</A>
+
+</OL>
+
+<H3><A NAME="BACKENDS">1. Backends</A></H3>
+
+<P>CUPS 1.1 implements a new backend interface for retrieving a list of
+available devices for CUPS clients. This allows administration
+interfaces to query the CUPS scheduler for a list of available devices,
+automatically configure printers if the device identification
+information is available, and present the user with a list of available
+devices rather than relying on the user to know what devices are
+configured on the system.
+
+<P>The new release also includes a backend for USB printers under
+*BSD and Linux. Support for USB under Solaris 8 will be provided in
+a subsequent patch release.
+
+<H3><A NAME="BANNERS">2. Banner Page Support</A></H3>
+
+<P>CUPS 1.1 includes support for banner pages at the beginning and end
+of a job. Banner pages may be of any file format and support variable
+substitution for job titles, usernames, etc. Default banner pages are
+associated with each printer and can be overridden with command-line
+options by the user.
+
+<H3><A NAME="DIGEST">3. Digest Authentication</A></H3>
+
+<P>Digest authentication provides a more secure method of authenticating
+access to the printing system. Unlike Basic authentication, Digest
+authentication does not send passwords "in the clear" so it is more
+difficult to gain unauthorized access to your system.
+
+<P>CUPS 1.1 implements Digest authentication using a special MD5
+password file instead of the UNIX password file. This file is managed
+using the new <CODE>lppasswd</CODE> command.
+
+<H3><A NAME="DIRSVC">4. Directory Services</A></H3>
+
+<P>CUPS 1.1 adds new directory service ("printer browsing") features to
+make using CUPS on large LANs and WANs easier. You can now poll a
+remote server for printer information and relay it to the LAN as well
+as restrict what printer information is processed (e.g. to "hide"
+servers, domains, or networks that you don't want to see.)
+
+<H3><A NAME="FHS2">5. Directory Structure Changes</A></H3>
+
+<P>CUPS 1.1 now uses a directory structure that complies with the
+Filesystem Hierarchy Standard ("FHS"), version 2.0. This should make
+integration into existing Linux and *BSD distributions a lot easier.
+
+<H3><A NAME="DOCOS">6. Documentation</A></H3>
+
+<P>The CUPS 1.1 documentation has gone through many revisions,
+including a completely rewritten administrators manual, a new
+programmers manual, and an IPP implementation reference manual.
+
+<H3><A NAME="DRIVERS">7. Drivers</A></H3>
+
+<P>CUPS 1.1 includes drivers for EPSON dot-matrix and inkjet printers.
+As with the HP PCL drivers, the EPSON drivers don't necessarily provide
+the best possible output for each printer but should provide adequate
+printing quality for general day-to-day printing.
+
+<H3><A NAME="FILTERS">8. Filters</A></H3>
+
+<P>CUPS 1.1 includes new image, PostScript, PDF, and text filters. The image
+filters have been upgraded to support Windows BMP and Alias PIX files.
+
+<P>The PostScript filter is now based off GNU Ghostscript 5.50. The new
+filter provides much better performance with higher-resolution printers
+and supports most Level 3 PostScript language features.
+
+<P>The new PDF filter is based off the excellent Xpdf software from
+Derek Noonburg and supports automatic page scaling. The new filter is a
+faster, smaller, more reliable replacement for the GNU Ghostscript PDF
+filtering that was used in CUPS 1.0.
+
+<P>The new text filter now supports bidirectional text and can embed
+fonts as needed.
+
+<H3><A NAME="IPP">9. IPP Support</A></H3>
+
+<P>Probably the least visible portion of CUPS is the IPP support. CUPS
+1.1 implements all of the required IPP/1.1 operations and attributes
+and most of the optional ones. The optional Create-Job and Send-File
+operations are now implemented, allowing for better System V printing
+system compatibility (one job ID per <CODE>lp</CODE> command) and
+support for banner pages.
+
+<H3><A NAME="PERSISTENCE">10. Job Persistence</A></H3>
+
+<P>CUPS 1.1 supports job persistence. This means that jobs are preserved
+even after a reboot, a feature that was sorely missing from CUPS 1.0.
+
+<P>In addition, CUPS 1.1 allows you to keep job information after the
+job has printed. The basic post-job persistence mode provides a job
+history (number of pages printed, time job was printed, etc.) but does
+not preserve the actual job files. This can be changed to discard all
+information after a job is printed or keep the job files after printing
+so you can reprint a job at some later time.
+
+<H3><A NAME="LPD">11. LPD Client Support</A></H3>
+
+<P>By popular request, CUPS 1.1 supports LPD-based clients using a new
+mini-daemon that handles LPD requests and passes them on to the main
+server.
+
+<H3><A NAME="USEROPTS">12. User-Defined Printers and Options</A></H3>
+
+<P>CUPS 1.1 includes support for user-defined printers and options via
+a new <CODE>lpoptions</CODE> command. User-defined printers are special
+instances of the available printers (e.g. "printer/instance" or
+"printer@server/instance") that can have their own default options such
+as media size, resolution, and so forth. The <CODE>lpoptions</CODE>
+command can also be used to set a different default printer queue.
+
+<H3><A NAME="WEB">13. Web Administration Interface</A></H3>
+
+<P>CUPS 1.0 provided a simple class, job, and printer monitoring
+interface for web browsers. CUPS 1.1 replaces this interface with an
+enhanced administration interface that allows you to add, modify,
+delete, configure, and control classes, jobs, and printers.
+
+<H2>Software Using CUPS</H2>
+
+<P>A lot has happened since CUPS 1.0 came out, and many software packages
+are supporting CUPS. We have contributed code to the SAMBA team to support
+CUPS, and parts of that are already available in SAMBA 2.0.6 and 2.0.7.
+With any luck the final pieces that provide a complete integration with
+SAMBA will be available in the next release of SAMBA.
+
+<P>Two graphical interfaces have appeared on the scene that use CUPS as
+well. The KUPS project provides a KDE-based interface for CUPS and can be
+found at:
+
+<UL><PRE>
+<A HREF="http://kups.sourceforge.net">http://kups.sourceforge.net</A>
+</PRE></UL>
+
+<P>The X Printing Panel ("XPP") project provides a graphical printing
+panel for CUPS and can be found at:
+
+<UL><PRE>
+<A HREF="http://www.phy.uni-bayreuth.de/till/xpp">http://www.phy.uni-bayreuth.de/till/xpp/</A>
+</PRE></UL>
+
+<P>Numerous other filters, drivers, tutorials, etc. have been made available
+on the CUPS Links web page, available at:
+
+<UL><PRE>
+<A HREF="http://www.cups.org/links.php">http://www.cups.org/links.php</A>
+</PRE></UL>
+
+<P>Finally, our own ESP Print Pro software uses CUPS to provide drivers
+for thousands of printers and can be found at:
+
+<UL><PRE>
+<A HREF="http://www.easysw.com/printpro">http://www.easysw.com/printpro</A>
+</PRE></UL>
+
+<H2>Operating Systems Using CUPS</H2>
+
+<P>One of our goals has always been to get as many UNIX/Linux
+distributions using CUPS as possible. Debian is currently providing
+CUPS as part of its stable distribution, and many other distributions
+are considering it in their next releases.
+
+<H2>Summary</H2>
+
+<P>The Common UNIX Printing System provides a modern printing interface
+for UNIX applications that is both flexible and user-friendly. The
+software provides System V and Berkeley compatible command-line
+interfaces to ensure compatibility with existing applications. CUPS 1.1
+adds many new features that make it an even better choice for printing
+under UNIX.
+
+<H2>Who to Contact</H2>
+
+<P>For more information on CUPS please contact us at:
+
+<UL><PRE>
+Attn: CUPS Information
+Easy Software Products
+44141 Airport View Drive Suite 204
+Hollywood, Maryland 20636-3111 USA
+
++1.301.373.9600
+
+<A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
+</PRE></UL>
+
+<H2>References</H2>
+
+<DL>
+
+ <DT>IEEE-1387.4</DT>
+
+ <DD>System Administration - Part 4: Printing Interfaces (draft)</DD>
+
+ <DT><A HREF="http://www.pwg.org/ipp/index.html">IETF-IPP</A></DT>
+
+ <DD>Internet Printing Protocol/1.1</DD>
+
+ <DT><A HREF="http://www.astart.com/lprng.html">LPRng</A></DT>
+
+ <DD>An enhanced, extended, and portable implementation of the
+ Berkeley LPR print spooler functionality</DD>
+
+ <DT>Palladin</DT>
+
+ <DD>A printing system developed at the Massachussetts Institute
+ of Technology</DD>
+
+ <DT><A HREF="http://www-usa.iona.com//hyplan/jmason/plp.html">PLP</A></DT>
+
+ <DD>The Portable Line Printer spooler system</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC1179</A></DT>
+
+ <DD>Line Printer Daemon Protocol</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc2046.txt">RFC2046</A></DT>
+
+ <DD>Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types</DD>
+
+ <DT><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</A></DT>
+
+ <DD>Hypertext Transfer Protocol -- HTTP/1.1</DD>
+
+</DL>
+
+<H2>Trademarks</H2>
+
+<P>The Common UNIX Printing System, CUPS, and the CUPS logo are the
+trademark property of Easy Software Products. All other trademarks are
+the property of their respective owners.
+
+</BODY>
+</HTML>
diff --git a/doc/overview.pdf b/doc/overview.pdf
new file mode 100644
index 000000000..0ee01e324
--- /dev/null
+++ b/doc/overview.pdf
Binary files differ
diff --git a/doc/printing-overview.shtml b/doc/printing-overview.shtml
new file mode 100644
index 000000000..1682dae7f
--- /dev/null
+++ b/doc/printing-overview.shtml
@@ -0,0 +1,125 @@
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
+
+<P>This chapter provides an overview of how the Common UNIX Printing System
+works.
+
+<H2>The Printing Problem</H2>
+
+<P>For years <I>the printing problem</I> has plagued UNIX. Unlike
+Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or
+system in place for supporting printers. Among the solutions currently
+available, the Berkeley and System V printing systems are the most
+prevalent.
+
+<P>These printing systems support line printers (text only) or
+PostScript printers (text and graphics), and with some coaxing they can
+be made to support a full range of printers and file formats. However,
+because each varient of the UNIX operating system uses a different
+printing system than the next developing printer drivers for a wide
+range of printers and operating systems is extremely difficult. That
+combined with the limited volume of customers for each UNIX varient has
+forced most printer vendors to give up supporting UNIX entirely.
+
+<P>CUPS is designed to eliminate <I>the printing problem</I>. One
+common printing system can be used by all UNIX varients to support the
+printing needs of users. Printer vendors can use its modular filter
+interface to develop a single driver program that supports a wide range
+of file formats with little or no effort. Since CUPS provides both the
+System V and Berkeley printing commands, users (and applications) can
+reap the benefits of this new technology with no changes.
+
+<H2>The Technology</H2>
+
+<P>CUPS is based upon an emerging Internet standard called the Internet
+Printing Protocol. IPP has been embraced by dozens of printer and
+printer server manufacturers and is supported by Microsoft Windows
+2000.
+
+<P>IPP defines a standard protocol for printing as well as managing
+print jobs and printer options like media size, resolution, and so
+forth. Like all IP-based protocols, IPP can be used locally or over the
+Internet to printers hundreds or thousands of miles away. Unlike other
+protocols, however, IPP also supports access control, authentication,
+and encryption, making it a much more capable and secure printing
+solution than older ones.
+
+<P>IPP is layered on top of the Hyper-Text Transport Protocol ("HTTP")
+which is the basis of web servers on the Internet. This allows users
+to view documentation, check status information on a printer or server,
+and manage their printers, classes, and jobs using their web browser.
+
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+Basic, Digest, and local certificate authentication and user, domain,
+or IP-based access control. TLS encryption will be available in future
+versions of CUPS.
+
+<H2>Jobs</H2>
+
+<P>Each file or set of files that is submitted for printing is called a
+<I>job</I>. Jobs are identified by a unique number starting at 1 and
+are assigned to a particular destination, usually a printer. Jobs can
+also have options associated with them such as media size, number of
+copies, and priority.
+
+<H2>Classes</H2>
+
+<P>CUPS supports collections of printers known as <I>classes</I>. Jobs
+sent to a class are forwarded to the first available printer in the
+class.
+
+<H2>Filters</H2>
+
+<P>Filters allow a user or application to print many types of files
+without extra effort. Print jobs sent to a CUPS server are filtered
+before sending them to a printer. Some filters convert job files to
+different formats that the printer can understand. Others perform page
+selection and ordering tasks.
+
+<P>CUPS provides filters for printing many types of image files,
+HP-GL/2 files, PDF files, and text files. CUPS also supplies PostScript
+and image file Raster Image Processor ("RIP") filters that convert
+PostScript or image files into bitmaps that can be sent to a raster
+printer.
+
+<H2>Backends</H2>
+
+<P>Backends perform the most important task of all - they send the
+filtered print data to the printer.
+
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ports, and over the network via the IPP, JetDirect (AppSocket), and
+Line Printer Daemon ("LPD") protocols. Additional backends are
+available in network service packages such as the SMB backend
+included with the popular SAMBA software.
+
+<P>Backends are also used to determine the available devices. On
+startup each backend is asked for a list of devices it supports,
+and any information that is available. This allows the parallel
+backend to tell CUPS that an EPSON Stylus Color 600 printer is
+attached to parallel port 1, for example.
+
+<H2>Printer Drivers</H2>
+
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+printer. CUPS includes sample printer drivers for Hewlett-Packard
+LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+and Stylus Photo printers. While these drivers do not generate optimal
+output for the different printer models, they do provide basic printing
+and demonstrate how you can write your own printer drivers and
+incorporate them into CUPS.
+
+<H2>Networking</H2>
+
+<P>Printers and classes on the local system are automatically shared
+with other systems on the network. This allows you to setup one system
+to print to a printer and use this system as a printer server or spool
+host for all of the others. Users may then select a local printer by
+name or a remote printer using "name@server".
+
+<P>CUPS also provides <I>implicit classes</I>, which are collections of
+printers and/or classes with the same name. This allows you to setup
+multiple servers pointing to the same physical network printer, for
+example, so that you aren't relying on a single system for printing.
+Because this also works with printer classes, you can setup multiple
+servers and printers and never worry about a single point of failure
+unless all of the printers and servers go down!
diff --git a/doc/references.shtml b/doc/references.shtml
new file mode 100644
index 000000000..8bd979c76
--- /dev/null
+++ b/doc/references.shtml
@@ -0,0 +1,43 @@
+<H1>References</H1>
+
+<H2>CUPS Documentation</H2>
+
+<P>The following CUPS documentation is referenced by this document:
+
+<UL>
+ <LI>CUPS-CMP-1.1: CUPS Configuration Management Plan
+ <LI>CUPS-IDD-1.1: CUPS System Interface Design Description
+ <LI>CUPS-IPP-1.1: CUPS Implementation of IPP
+ <LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual
+ <LI>CUPS-SDD-1.1: CUPS Software Design Description
+ <LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual
+ <LI>CUPS-SSR-1.1: CUPS Software Security Report
+ <LI>CUPS-STP-1.1: CUPS Software Test Plan
+ <LI>CUPS-SUM-1.1.x: CUPS Software Users Manual
+ <LI>CUPS-SVD-1.1: CUPS Software Version Description
+</UL>
+
+<H2>Other Documents</H2>
+
+<P>The following non-CUPS documents are referenced by this document:
+
+<UL>
+ <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">Adobe
+ PostScript Printer Description File Format Specification,
+ Version 4.3.</A>
+ <LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">Adobe
+ PostScript Language Reference, Third Edition.</A>
+ <LI>IPP/1.1: Implementers Guide
+ <LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer Daemon Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals for an Internet Printing Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale for the Structure of the Model and Protocol
+ for the Internet Printing Protocol</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping between LPD and IPP Protocols</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP Authentication: Basic and Digest Access</A>
+ Authentication
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1: Encoding and Transport</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1: Model and Semantics</A>
+ <LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and Printer Set Operations</A>
+</UL>
diff --git a/doc/robots.txt b/doc/robots.txt
new file mode 100644
index 000000000..5f7af6ae1
--- /dev/null
+++ b/doc/robots.txt
@@ -0,0 +1,31 @@
+#
+# "$Id: robots.txt 4087 2004-02-25 20:14:54Z mike $"
+#
+# This file tells search engines not to index your CUPS server.
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+User-agent: *
+Disallow: /
+
+#
+# End of "$Id: robots.txt 4087 2004-02-25 20:14:54Z mike $".
+#
+
diff --git a/doc/sam.html b/doc/sam.html
new file mode 100644
index 000000000..bb26ea02f
--- /dev/null
+++ b/doc/sam.html
@@ -0,0 +1,6366 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Administrators Manual</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SAM-1.1.22">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511" ALT="CUPS Software Administrators Manual"><BR>
+<H1>CUPS Software Administrators Manual</H1></A><BR>
+CUPS-SAM-1.1.22<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">Preface</A>
+<UL>
+<LI><A HREF="#1_1">System Overview</A></LI>
+<LI><A HREF="#1_2">Document Overview</A></LI>
+<LI><A HREF="#1_3">Notation Conventions</A></LI>
+<LI><A HREF="#1_4">Abbreviations</A></LI>
+<LI><A HREF="#1_5">Other References</A></LI>
+</UL>
+</B><B><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+<UL>
+<LI><A HREF="#2_1">The Printing Problem</A></LI>
+<LI><A HREF="#2_2">The Technology</A></LI>
+<LI><A HREF="#2_3">Jobs</A></LI>
+<LI><A HREF="#2_4">Classes</A></LI>
+<LI><A HREF="#2_5">Filters</A></LI>
+<LI><A HREF="#2_6">Backends</A></LI>
+<LI><A HREF="#2_7">Printer Drivers</A></LI>
+<LI><A HREF="#2_8">Networking</A></LI>
+</UL>
+</B><B><A HREF="#BUILDING_INSTALLING">2 - Building and Installing CUPS</A>
+<UL>
+<LI><A HREF="#3_1">Installing a Source Distribution</A>
+<UL>
+<LI><A HREF="#REQUIREMENTS">Requirements</A></LI>
+<LI><A HREF="#COMPILING">Compiling CUPS</A></LI>
+<LI><A HREF="#INSTALLING">Installing the Software</A></LI>
+<LI><A HREF="#RUNNING">Running the Software</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#BINARY">Installing a Binary Distribution</A>
+<UL>
+<LI><A HREF="#PORTABLE-BINARY">Installing a Portable Distribution</A></LI>
+<LI><A HREF="#RPM-BINARY">Installing an RPM Distribution</A></LI>
+<LI><A HREF="#DPKG-BINARY">Installing an Debian Distribution</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#MANAGING_PRINTERS">3 - Managing Printers</A>
+<UL>
+<LI><A HREF="#4_1">The Basics</A></LI>
+<LI><A HREF="#4_2">Adding Your First Printer</A>
+<UL>
+<LI><A HREF="#4_2_1">Adding Your First Printer from the Command-Line</A></LI>
+<LI><A HREF="#ADD_WEB">Adding Your First Printer from the Web</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_3">Managing Printers from the Command-Line</A>
+<UL>
+<LI><A HREF="#4_3_1">Adding and Modifying Printers</A></LI>
+<LI><A HREF="#4_3_2">Deleting Printers</A></LI>
+<LI><A HREF="#4_3_3">Setting the Default Printer</A></LI>
+<LI><A HREF="#4_3_4">Starting and Stopping Printers</A></LI>
+<LI><A HREF="#4_3_5">Accepting and Rejecting Print Jobs</A></LI>
+<LI><A HREF="#4_3_6">Setting Quotas on a Printer</A></LI>
+<LI><A HREF="#4_3_7">Restricting User Access to a Printer</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_4">Managing Printers from the Web</A></LI>
+</UL>
+</B><B><A HREF="#PRINTER_CLASSES">4 - Printer Classes</A>
+<UL>
+<LI><A HREF="#5_1">The Basics</A></LI>
+<LI><A HREF="#5_2">Managing Printer Classes from the Command-Line</A></LI>
+<LI><A HREF="#5_3">Managing Printer Classes from the Web Interface</A></LI>
+<LI><A HREF="#5_4">Implicit Classes</A></LI>
+</UL>
+</B><B><A HREF="#CLIENT_SETUP">5 - Client Setup</A>
+<UL>
+<LI><A HREF="#6_1">The Basics</A>
+<UL>
+<LI><A HREF="#CLIENT_MANUAL">Manual Configuration of Print Queues</A></LI>
+<LI><A HREF="#CLIENT_SERVER">Specifying a Single Server for Printing</A></LI>
+<LI><A HREF="#CLIENT_AUTO">Automatic Configuration of Print Queues</A></LI>
+<LI><A HREF="#CLIENT_POLL">Specifying Multiple Servers for Printing</A></LI>
+<LI><A HREF="#CLIENT_RELAY">Relaying Printers to Other Clients</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#6_2">Load Balancing and Failsafe Operation</A></LI>
+</UL>
+</B><B><A HREF="#PRINTING_MANAGEMENT">6 - Printing System Management</A>
+<UL>
+<LI><A HREF="#7_1">The Basics</A></LI>
+<LI><A HREF="#RESTARTING">Restarting the CUPS Server</A></LI>
+<LI><A HREF="#7_3">Changing the Server Configuration</A></LI>
+<LI><A HREF="#7_4">Server Directives</A>
+<UL>
+<LI><A HREF="#AccessLog">AccessLog</A></LI>
+<LI><A HREF="#Allow">Allow</A></LI>
+<LI><A HREF="#AuthClass">AuthClass</A></LI>
+<LI><A HREF="#AuthGroupName">AuthGroupName</A></LI>
+<LI><A HREF="#AuthType">AuthType</A></LI>
+<LI><A HREF="#AutoPurgeJobs">AutoPurgeJobs</A></LI>
+<LI><A HREF="#BrowseAddress">BrowseAddress</A></LI>
+<LI><A HREF="#BrowseAllow">BrowseAllow</A></LI>
+<LI><A HREF="#BrowseDeny">BrowseDeny</A></LI>
+<LI><A HREF="#BrowseInterval">BrowseInterval</A></LI>
+<LI><A HREF="#BrowseOrder">BrowseOrder</A></LI>
+<LI><A HREF="#BrowsePoll">BrowsePoll</A></LI>
+<LI><A HREF="#BrowsePort">BrowsePort</A></LI>
+<LI><A HREF="#BrowseProtocols">BrowseProtocols</A></LI>
+<LI><A HREF="#BrowseRelay">BrowseRelay</A></LI>
+<LI><A HREF="#BrowseShortNames">BrowseShortNames</A></LI>
+<LI><A HREF="#BrowseTimeout">BrowseTimeout</A></LI>
+<LI><A HREF="#Browsing">Browsing</A></LI>
+<LI><A HREF="#Classification">Classification</A></LI>
+<LI><A HREF="#ClassifyOverride">ClassifyOverride</A></LI>
+<LI><A HREF="#ConfigFilePerm">ConfigFilePerm</A></LI>
+<LI><A HREF="#DataDir">DataDir</A></LI>
+<LI><A HREF="#DefaultCharset">DefaultCharset</A></LI>
+<LI><A HREF="#DefaultLanguage">DefaultLanguage</A></LI>
+<LI><A HREF="#Deny">Deny</A></LI>
+<LI><A HREF="#DocumentRoot">DocumentRoot</A></LI>
+<LI><A HREF="#Encryption">Encryption</A></LI>
+<LI><A HREF="#ErrorLog">ErrorLog</A></LI>
+<LI><A HREF="#FaxRetryInterval">FaxRetryInterval</A></LI>
+<LI><A HREF="#FaxRetryLimit">FaxRetryLimit</A></LI>
+<LI><A HREF="#FileDevice">FileDevice</A></LI>
+<LI><A HREF="#FilterLimit">FilterLimit</A></LI>
+<LI><A HREF="#FilterNice">FilterNice</A></LI>
+<LI><A HREF="#FontPath">FontPath</A></LI>
+<LI><A HREF="#Group">Group</A></LI>
+<LI><A HREF="#HideImplicitMembers">HideImplicitMembers</A></LI>
+<LI><A HREF="#HostNameLookups">HostNameLookups</A></LI>
+<LI><A HREF="#ImplicitAnyClasses">ImplicitAnyClasses</A></LI>
+<LI><A HREF="#ImplicitClasses">ImplicitClasses</A></LI>
+<LI><A HREF="#Include">Include</A></LI>
+<LI><A HREF="#KeepAlive">KeepAlive</A></LI>
+<LI><A HREF="#KeepAliveTimeout">KeepAliveTimeout</A></LI>
+<LI><A HREF="#Limit">Limit</A></LI>
+<LI><A HREF="#LimitExcept">LimitExcept</A></LI>
+<LI><A HREF="#LimitRequestBody">LimitRequestBody</A></LI>
+<LI><A HREF="#Listen">Listen</A></LI>
+<LI><A HREF="#Location">Location</A></LI>
+<LI><A HREF="#LogFilePerm">LogFilePerm</A></LI>
+<LI><A HREF="#LogLevel">LogLevel</A></LI>
+<LI><A HREF="#MaxClients">MaxClients</A></LI>
+<LI><A HREF="#MaxClientsPerHost">MaxClientsPerHost</A></LI>
+<LI><A HREF="#MaxCopies">MaxCopies</A></LI>
+<LI><A HREF="#MaxJobs">MaxJobs</A></LI>
+<LI><A HREF="#MaxJobsPerPrinter">MaxJobsPerPrinter</A></LI>
+<LI><A HREF="#MaxJobsPerUser">MaxJobsPerUser</A></LI>
+<LI><A HREF="#MaxLogSize">MaxLogSize</A></LI>
+<LI><A HREF="#MaxRequestSize">MaxRequestSize</A></LI>
+<LI><A HREF="#Order">Order</A></LI>
+<LI><A HREF="#PageLog">PageLog</A></LI>
+<LI><A HREF="#Port">Port</A></LI>
+<LI><A HREF="#PreserveJobFiles">PreserveJobFiles</A></LI>
+<LI><A HREF="#PreserveJobHistory">PreserveJobHistory</A></LI>
+<LI><A HREF="#Printcap">Printcap</A></LI>
+<LI><A HREF="#PrintcapFormat">PrintcapFormat</A></LI>
+<LI><A HREF="#PrintcapGUI">PrintcapGUI</A></LI>
+<LI><A HREF="#ReloadTimeout">ReloadTimeout</A></LI>
+<LI><A HREF="#RemoteRoot">RemoteRoot</A></LI>
+<LI><A HREF="#RequestRoot">RequestRoot</A></LI>
+<LI><A HREF="#Require">Require</A></LI>
+<LI><A HREF="#RIPCache">RIPCache</A></LI>
+<LI><A HREF="#RootCertDuration">RootCertDuration</A></LI>
+<LI><A HREF="#RunAsUser">RunAsUser</A></LI>
+<LI><A HREF="#Satisfy">Satisfy</A></LI>
+<LI><A HREF="#ServerAdmin">ServerAdmin</A></LI>
+<LI><A HREF="#ServerBin">ServerBin</A></LI>
+<LI><A HREF="#ServerCertificate">ServerCertificate</A></LI>
+<LI><A HREF="#ServerKey">ServerKey</A></LI>
+<LI><A HREF="#ServerName">ServerName</A></LI>
+<LI><A HREF="#ServerRoot">ServerRoot</A></LI>
+<LI><A HREF="#ServerTokens">ServerTokens</A></LI>
+<LI><A HREF="#SSLListen">SSLListen</A></LI>
+<LI><A HREF="#SSLPort">SSLPort</A></LI>
+<LI><A HREF="#SystemGroup">SystemGroup</A></LI>
+<LI><A HREF="#TempDir">TempDir</A></LI>
+<LI><A HREF="#Timeout">Timeout</A></LI>
+<LI><A HREF="#User">User</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#7_5">Changing the Client Configuration</A></LI>
+<LI><A HREF="#7_6">Client Directives</A>
+<UL>
+<LI><A HREF="#Encryption">Encryption</A></LI>
+<LI><A HREF="#ServerName">ServerName</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#7_7">Changing the Printer Configuration</A></LI>
+<LI><A HREF="#7_8">Printer Directives</A>
+<UL>
+<LI><A HREF="#Accepting">Accepting</A></LI>
+<LI><A HREF="#AllowUser">AllowUser</A></LI>
+<LI><A HREF="#DefaultPrinter">DefaultPrinter</A></LI>
+<LI><A HREF="#DenyUser">DenyUser</A></LI>
+<LI><A HREF="#DeviceURI">DeviceURI</A></LI>
+<LI><A HREF="#Info">Info</A></LI>
+<LI><A HREF="#JobSheets">JobSheets</A></LI>
+<LI><A HREF="#KLimit">KLimit</A></LI>
+<LI><A HREF="#PrinterLocation">Location</A></LI>
+<LI><A HREF="#PageLimit">PageLimit</A></LI>
+<LI><A HREF="#Printer">Printer</A></LI>
+<LI><A HREF="#QuotaPeriod">QuotaPeriod</A></LI>
+<LI><A HREF="#State">State</A></LI>
+<LI><A HREF="#StateMessage">StateMessage</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#7_9">Changing the Classes Configuration</A></LI>
+<LI><A HREF="#7_10">Classes Directives</A>
+<UL>
+<LI><A HREF="#ClassAccepting">Accepting</A></LI>
+<LI><A HREF="#ClassAllowUser">AllowUser</A></LI>
+<LI><A HREF="#Class">Class</A></LI>
+<LI><A HREF="#DefaultClass">DefaultClass</A></LI>
+<LI><A HREF="#ClassDenyUser">DenyUser</A></LI>
+<LI><A HREF="#ClassInfo">Info</A></LI>
+<LI><A HREF="#ClassJobSheets">JobSheets</A></LI>
+<LI><A HREF="#ClassKLimit">KLimit</A></LI>
+<LI><A HREF="#ClassLocation">Location</A></LI>
+<LI><A HREF="#ClassPageLimit">PageLimit</A></LI>
+<LI><A HREF="#ClassPrinter">Printer</A></LI>
+<LI><A HREF="#ClassQuotaPeriod">QuotaPeriod</A></LI>
+<LI><A HREF="#ClassState">State</A></LI>
+<LI><A HREF="#ClassStateMessage">StateMessage</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#PRINTING_SECURITY">Printing System Security</A>
+<UL>
+<LI><A HREF="#CERTIFICATES">Authentication Using Certificates</A></LI>
+<LI><A HREF="#7_11_2">Using Basic Authentication</A></LI>
+<LI><A HREF="#7_11_3">Using Digest Authentication</A></LI>
+<LI><A HREF="#7_11_4">System and Group Authentication</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#PRINTER_ACCOUNTING">Printer Accounting</A>
+<UL>
+<LI><A HREF="#7_12_1">The access_log File</A></LI>
+<LI><A HREF="#7_12_2">The error_log File</A></LI>
+<LI><A HREF="#7_12_3">The page_log File</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#FILE_TYPING_FILTERING">File Typing and Filtering</A>
+<UL>
+<LI><A HREF="#7_13_1">mime.types</A></LI>
+<LI><A HREF="#7_13_2">mime.convs</A></LI>
+<LI><A HREF="#7_13_3">Adding Filetypes and Filters</A></LI>
+<LI><A HREF="#7_13_4">Printer Drivers and PPD Files</A></LI>
+<LI><A HREF="#7_13_5">Writing Your Own Filter or Printer Driver</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#PRINTING_OTHER">7 - Printing with Other Systems</A>
+<UL>
+<LI><A HREF="#8_1">The Basics</A></LI>
+<LI><A HREF="#8_2">Printing from LPD Clients</A></LI>
+<LI><A HREF="#LPD">Printing to LPD Servers</A></LI>
+<LI><A HREF="#8_4">Printing from Mac OS 10.2 and Later Clients</A></LI>
+<LI><A HREF="#8_5">Printing from Mac OS 10.1 and Earlier Clients</A>
+<UL>
+<LI><A HREF="#8_5_1">Columbia Appletalk Package (CAP)</A></LI>
+<LI><A HREF="#8_5_2">XINET KA/Spool</A></LI>
+<LI><A HREF="#8_5_3">Netatalk</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_6">Printing to Mac OS 10.2 and Later Servers</A></LI>
+<LI><A HREF="#8_7">Printing to Mac OS 10.1 and Earlier Servers</A></LI>
+<LI><A HREF="#8_8">Printing from Windows Clients</A>
+<UL>
+<LI><A HREF="#8_8_1">Exporting Printer Drivers</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_9">Printing to Windows Servers</A></LI>
+</UL>
+</B><B><A HREF="#LICENSE">A - Software License Agreement</A>
+<UL>
+<LI><A HREF="#9_1">Common UNIX Printing System License Agreement</A>
+<UL>
+<LI><A HREF="#9_1_1">Introduction</A></LI>
+<LI><A HREF="#9_1_2">License Exceptions</A></LI>
+<LI><A HREF="#9_1_3">Trademarks</A></LI>
+<LI><A HREF="#9_1_4">Binary Distribution Rights</A></LI>
+<LI><A HREF="#9_1_5">Support</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#9_2">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#9_2_1">Preamble</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#9_3_1">Preamble</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#COMMON_NETWORK">B - Common Network Settings</A>
+<UL>
+<LI><A HREF="#10_1">Configuring a Network Interface</A>
+<UL>
+<LI><A HREF="#10_1_1">Configuring the IP Address Using ARP</A></LI>
+<LI><A HREF="#10_1_2">Configuring the IP Address Using RARP</A></LI>
+<LI><A HREF="#10_1_3">Configuring the IP Address Using BOOTP</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#10_2">Verifying the Printer Connection</A></LI>
+<LI><A HREF="#10_3">Common Network Interface Settings</A></LI>
+<LI><A HREF="#AXIS">Configuring Axis Print Servers</A></LI>
+<LI><A HREF="#LINKSYS">Configuring Linksys Print Servers</A></LI>
+<LI><A HREF="#LPD_OPTIONS">Configuring LPD Printing Options</A></LI>
+</UL>
+</B><B><A HREF="#PRINTER_DRIVERS">C - Printer Drivers</A>
+<UL>
+<LI><A HREF="#11_1">Printer Drivers</A></LI>
+<LI><A HREF="#DYMO">DYMO Label Printer</A></LI>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A></LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A></LI>
+</UL>
+</B><B><A HREF="#FILES">D - List of Files</A></B>
+<BR>
+<BR><B><A HREF="#FAQ">E - Troubleshooting Common Problems</A>
+<UL>
+<LI><A HREF="#13_1">My Applications Don't See the Available Printers</A></LI>
+<LI><A HREF="#13_2">CUPS Doesn't Recognize My Username or Password!</A></LI>
+<LI><A HREF="#ALLOW_REMOTE">I Can't Do Administration Tasks from Another
+ Machine!</A></LI>
+<LI><A HREF="#13_4">I Can't Do Administration Tasks from My Web Browser!</A>
+</LI>
+<LI><A HREF="#13_5">Connection Refused Messages</A></LI>
+<LI><A HREF="#13_6">Write Error Messages</A></LI>
+</UL>
+</B><HR NOSHADE>
+<H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
+<P>This software administrators manual provides printer administration
+ information for the Common UNIX Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>
+TM</SUP>&quot;), version 1.1.22.</P>
+<H2><A NAME="1_1">System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+
+<!-- NEED 3in -->
+<H2><A NAME="1_2">Document Overview</A></H2>
+<P>This software administrators manual is organized into the following
+ sections:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Printing System Overview</A></LI>
+<LI><A HREF="#BUILDING_INSTALLING">2 - Building and Installing CUPS</A></LI>
+<LI><A HREF="#MANAGING_PRINTERS">3 - Managing Printers</A></LI>
+<LI><A HREF="#PRINTER_CLASSES">4 - Printer Classes</A></LI>
+<LI><A HREF="#CLIENT_SETUP">5 - Client Setup</A></LI>
+<LI><A HREF="#PRINTING_MANAGEMENT">6 - Printing System Management</A></LI>
+<LI><A HREF="#PRINTING_OTHER">7 - Printing with Other Systems</A></LI>
+<LI><A HREF="#LICENSE">A - Software License Agreement</A></LI>
+<LI><A HREF="#COMMON_NETWORK">B - Common Network Settings</A></LI>
+<LI><A HREF="#PRINTER_DRIVERS">C - Printer Drivers</A></LI>
+<LI><A HREF="#FILES">D - List of Files</A></LI>
+<LI><A HREF="#FAQ">E - Troubleshooting Common Problems</A></LI>
+</UL>
+<H2><A NAME="1_3">Notation Conventions</A></H2>
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><VAR>/var</VAR>
+<BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+File and directory names.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><TT>Request ID is Printer-123</TT></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abbreviations</A></H2>
+ The following abbreviations are used throughout this manual:
+<UL>
+<DL>
+<DT>kb</DT>
+<DD>Kilobytes, or 1024 bytes
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
+<DD>Megabytes, or 1048576 bytes
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
+<DD>Gigabytes, or 1073741824 bytes
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Other References</A></H2>
+<UL>
+<DL>
+<DT>CUPS Software Programmers Manual</DT>
+<DD>A programmer guide for interfacing with and/or extending the CUPS
+ software.
+<BR>&nbsp;</DD>
+<DT>CUPS Software Users Manual</DT>
+<DD>An end-user guide for using the CUPS software.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
+<H2><A NAME="2_1">The Printing Problem</A></H2>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
+<H2><A NAME="2_2">The Technology</A></H2>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
+<H2><A NAME="2_3">Jobs</A></H2>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
+<H2><A NAME="2_4">Classes</A></H2>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
+<H2><A NAME="2_5">Filters</A></H2>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
+<H2><A NAME="2_6">Backends</A></H2>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
+<H2><A NAME="2_7">Printer Drivers</A></H2>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
+<H2><A NAME="2_8">Networking</A></H2>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
+<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Building and
+ Installing CUPS</A></H1>
+<P>This chapter shows how to build and install the Common UNIX Printing
+ System. If you are installing a binary distribution from the CUPS web
+ site, proceed to the section titled, <A HREF="#BINARY">Installing a
+ Binary Distribution</A>.</P>
+<H2><A NAME="3_1">Installing a Source Distribution</A></H2>
+<P>This section describes how to compile and install CUPS on your system
+ from the source code.</P>
+<H3><A NAME="REQUIREMENTS">Requirements</A></H3>
+<P>You'll need ANSI-compliant C and C++ compilers to build CUPS on your
+ system. As its name implies, CUPS is designed to run on the UNIX
+ operating system, however the CUPS interface library and most of the
+ filters and backends supplied with CUPS should also compile and run
+ under Microsoft Windows.</P>
+<P>For the image file filters and PostScript RIP, you'll need the JPEG,
+ PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with
+ significantly reduced functionality. Easy Software Products maintains a
+ mirror of the current versions of these libraries at:</P>
+<UL>
+<PRE>
+<A HREF="ftp://ftp.easysw.com/pub/libraries">ftp://ftp.easysw.com/pub/libraries</A>
+</PRE>
+</UL>
+<P>If you make changes to the man pages you'll need GNU groff or another
+ nroff-like package. GNU groff is available from:</P>
+<UL>
+<PRE>
+<A HREF="ftp://ftp.gnu.org/pub/groff">ftp://ftp.gnu.org/pub/groff</A>
+</PRE>
+</UL>
+<P>The documentation is formatted using the HTMLDOC software. If you
+ need to make changes you can get the HTMLDOC software from:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
+</PRE>
+</UL>
+<P>Finally, you'll need a <CODE>make</CODE> program that understands the
+ <CODE>include</CODE> directive - FreeBSD, NetBSD, and OpenBSD
+ developers should use the <CODE>gmake</CODE> program.</P>
+<H3><A NAME="COMPILING">Compiling CUPS</A></H3>
+<P>CUPS uses GNU autoconf to configure the makefiles and source code for
+ your system. Type the following command to configure CUPS for your
+ system:</P>
+<UL>
+<PRE>
+<B>./configure ENTER</B>
+</PRE>
+</UL>
+<P>The default installation will put the CUPS software in the<VAR> /etc</VAR>
+,<VAR> /usr</VAR>, and<VAR> /var</VAR> directories on your system, which
+ will overwrite any existing printing commands on your system. Use the <CODE>
+--prefix</CODE> option to install the CUPS software in another location:</P>
+<UL>
+<PRE>
+<B>./configure --prefix=/some/directory ENTER</B>
+</PRE>
+</UL>
+<P>If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a
+ system default location (typically<VAR> /usr/include</VAR> and<VAR>
+ /usr/lib</VAR>) you'll need to set the <CODE>CFLAGS</CODE>, <CODE>
+CXXFLAGS</CODE>, and <CODE>LDFLAGS</CODE> environment variables prior to
+ running configure:</P>
+<UL>
+<PRE>
+<B>setenv CFLAGS &quot;-I/some/directory&quot; ENTER</B>
+<B>setenv CXXFLAGS &quot;-I/some/directory&quot; ENTER</B>
+<B>setenv LDFLAGS &quot;-L/some/directory&quot; ENTER</B>
+<B>setenv DSOFLAGS &quot;-L/some/directory&quot; ENTER</B>
+<B>./configure ... ENTER</B>
+</PRE>
+</UL>
+<P>or:</P>
+<UL>
+<PRE>
+<B>CFLAGS=&quot;-I/some/directory&quot;; export CFLAGS ENTER</B>
+<B>CXXFLAGS=&quot;-I/some/directory&quot;; export CXXFLAGS ENTER</B>
+<B>LDFLAGS=&quot;-L/some/directory&quot;; export LDFLAGS ENTER</B>
+<B>DSOFLAGS=&quot;-L/some/directory&quot;; export DSOFLAGS ENTER</B>
+<B>./configure ... ENTER</B>
+</PRE>
+</UL>
+<P>To enable support for encryption, you'll also want to add the
+ &quot;--enable-ssl&quot; option:</P>
+<UL>
+<PRE>
+./configure --enable-ssl
+</PRE>
+</UL>
+<P>SSL and TLS support require the OpenSSL library, available at:</P>
+<UL>
+<PRE>
+<A HREF="http://www.openssl.org">http://www.openssl.org</A>
+</PRE>
+</UL>
+<P>If the OpenSSL headers and libraries are not installed in the
+ standard directories, use the <CODE>--with-openssl-includes</CODE> and <CODE>
+--with-openssl-libs</CODE> options:</P>
+<UL>
+<PRE>
+./configure --enable-ssl \
+ --with-openssl-includes=/foo/bar/include \
+ --with-openssl-libs=/foo/bar/lib
+</PRE>
+</UL>
+<P>Once you have configured things, just type:</P>
+<UL>
+<PRE>
+<B>make ENTER</B>
+</PRE>
+</UL>
+<P>to build the software.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="INSTALLING">Installing the Software</A></H3>
+<P>Use the &quot;install&quot; target to install the software:</P>
+<UL>
+<PRE>
+<B>make install ENTER</B>
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> WARNING:</B>
+<P>Installing CUPS will overwrite your existing printing system. If you
+ experience difficulties with the CUPS software and need to go back to
+ your old printing system, you will need to reinstall the old printing
+ system from your operating system CDs.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="RUNNING">Running the Software</A></H3>
+<P>Once you have installed the software you can start the CUPS server by
+ typing:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/cupsd ENTER</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<H2><A NAME="BINARY">Installing a Binary Distribution</A></H2>
+<P>CUPS comes in a variety of binary distribution formats. Easy Software
+ Products provides binaries in TAR format with installation and removal
+ scripts (&quot;portable&quot; distributions), and in RPM and DPKG formats for Red
+ Hat and Debian-based distributions. Portable distributions are
+ available for all platforms, while the RPM and DPKG distributions are
+ only available for Linux.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> WARNING:</B>
+<P>Installing CUPS will overwrite your existing printing system. If you
+ experience difficulties with the CUPS software and need to go back to
+ your old printing system, you will need to remove the CUPS software
+ with the provided script and/or reinstall the old printing system from
+ your operating system CDs.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="PORTABLE-BINARY">Installing a Portable Distribution</A></H3>
+<P>To install the CUPS software from a portable distribution you will
+ need to be logged in as root; doing an <CODE>su</CODE> is good enough.
+ Once you are the root user, run the installation script with:</P>
+<UL>
+<PRE>
+<B>./cups.install ENTER</B>
+</PRE>
+</UL>
+<P>After asking you a few yes/no questions the CUPS software will be
+ installed and the scheduler will be started automatically.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="RPM-BINARY">Installing an RPM Distribution</A></H3>
+<P>To install the CUPS software from an RPM distribution you will need
+ to be logged in as root; doing an <CODE>su</CODE> is good enough. Once
+ you are the root user, run RPM with:</P>
+<UL>
+<PRE>
+<B>rpm -e lpr</B>
+<B>rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER</B>
+</PRE>
+</UL>
+<P>After a short delay the CUPS software will be installed and the
+ scheduler will be started automatically.</P>
+<H3><A NAME="DPKG-BINARY">Installing an Debian Distribution</A></H3>
+<P>To install the CUPS software from a Debian distribution you will need
+ to be logged in as root; doing an <CODE>su</CODE> is good enough. Once
+ you are the root user, run dpkg with:</P>
+<UL>
+<PRE>
+<B>dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER</B>
+</PRE>
+</UL>
+<P>After a short delay the CUPS software will be installed and the
+ scheduler will be started automatically.</P>
+<H1 ALIGN="RIGHT"><A NAME="MANAGING_PRINTERS">3 - Managing Printers</A></H1>
+<P>This chapter describes how to add your first printer and how to
+ manage your printers.</P>
+<H2><A NAME="4_1">The Basics</A></H2>
+<P>Each printer queue has a name associated with it; the printer name
+ must start with any printable character except &quot; &quot;, &quot;/&quot;, and &quot;@&quot;. It
+ can contain up to 127 letters, numbers, and the underscore (_). Case is
+ not significant, e.g. &quot;PRINTER&quot;, &quot;Printer&quot;, and &quot;printer&quot; are
+ considered to be the same name.</P>
+<P>Printer queues also have a device associated with them. The device
+ can be a parallel port, a network interface, and so forth. Devices
+ within CUPS use Uniform Resource Identifiers (&quot;URIs&quot;) which are a more
+ general form of Uniform Resource Locators (&quot;URLs&quot;) that are used in
+ your web browser. For example, the first parallel port in Linux usually
+ uses a device URI of <CODE>parallel:/dev/lp1</CODE>.
+<!-- NEED 2.5in -->
+</P>
+<P>You can see a complete list of supported devices by running the <CODE>
+lpinfo(8)</CODE> command:</P>
+<UL>
+<PRE>
+<B>lpinfo -v ENTER</B>
+network socket
+network http
+network ipp
+network lpd
+direct parallel:/dev/lp1
+serial serial:/dev/ttyS1?baud=115200
+serial serial:/dev/ttyS2?baud=115200
+direct usb:/dev/usb/lp0
+network smb
+</PRE>
+</UL>
+<P>The <CODE>-v</CODE> option specifies that you want a list of
+ available devices. The first word in each line is the type of device
+ (direct, file, network, or serial) and is followed by the device URI or
+ method name for that device. File devices have device URIs of the form <CODE>
+file:/directory/filename</CODE> while network devices use the more
+ familiar <CODE>method://server</CODE> or <CODE>method://server/path</CODE>
+ format.</P>
+<P>Finally, printer queues usually have a PostScript Printer Description
+ (&quot;PPD&quot;) file associated with them. PPD files describe the capabilities
+ of each printer, the page sizes supported, etc., and are used for
+ PostScript and non-PostScript printers. CUPS includes PPD files for HP
+ LaserJet, HP DeskJet, EPSON 9-pin, EPSON 24-pin, and EPSON Stylus
+ printers.</P>
+<H2><A NAME="4_2">Adding Your First Printer</A></H2>
+<P>CUPS provides two methods for adding printers: a command-line program
+ called <CODE>lpadmin(8)</CODE> and a Web interface. The <CODE>lpadmin</CODE>
+ command allows you to perform most printer administration tasks from
+ the command-line and is located in<VAR> /usr/sbin</VAR>. The Web
+ interface is located at:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>and steps you through printer configuration. If you don't like
+ command-line interfaces, try the <A HREF="#ADD_WEB">Web interface</A>
+ instead.</P>
+<H3><A NAME="4_2_1">Adding Your First Printer from the Command-Line</A></H3>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option
+ to add a printer to CUPS:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -E -v <I>device</I> -m <I>ppd</I> ENTER</B>
+</PRE>
+</UL>
+<P>For a HP DeskJet printer connected to the parallel port this would
+ look like:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER</B>
+</PRE>
+</UL>
+<P>Similarly, a HP LaserJet printer using a JetDirect network interface
+ at IP address 11.22.33.44 would be added with the command:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER</B>
+</PRE>
+</UL>
+<P>As you can see, <CODE>deskjet.ppd</CODE> and <CODE>laserjet.ppd</CODE>
+ are the PPD files for the HP DeskJet and HP LaserJet drivers included
+ with CUPS. You'll find a complete list of PPD files and the printers
+ they will work with in <A HREF="#PRINTER_DRIVERS">Appendix C, &quot;Printer
+ Drivers&quot;</A>.</P>
+<P>For a dot matrix printer connected to the serial port, this might
+ look like:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -m epson9.ppd \
+ -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>Here you specify the serial port (e.g. S0,S1, d0, d1), baud rate
+ (e.g. 9600, 19200, 38400, 115200, etc.), number of bits, parity, and
+ flow control. If you do not need flow control, delete the &quot;+flow=soft&quot;
+ portion.</P>
+<H3><A NAME="ADD_WEB">Adding Your First Printer from the Web</A></H3>
+<P>The CUPS web server provides a user-friendly &quot;wizard&quot; interface for
+ adding your printers. Rather than figuring out which device URI and PPD
+ file to use, you can instead click on the appropriate listings and fill
+ in some simple information. Enter the following URL in your web browser
+ to begin:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>Click on the<VAR> Add Printer</VAR> button to add a printer.</P>
+<H2><A NAME="4_3">Managing Printers from the Command-Line</A></H2>
+<P>The <CODE>lpadmin</CODE> command enables you to perform most printer
+ administration tasks from the command-line. You'll find <CODE>lpadmin</CODE>
+ in the<VAR> /usr/sbin</VAR> directory.</P>
+<H3><A NAME="4_3_1">Adding and Modifying Printers</A></H3>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option
+ to add or modify a printer:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> <I>options</I> ENTER</B>
+</PRE>
+</UL>
+<P>The<I> options</I> arguments can be any of the following:</P>
+<UL>
+<DL>
+<DT>-c<I> class</I></DT>
+<DD>Adds the named printer to printer class<VAR> class</VAR>. If the
+ class does not exist then it is created.</DD>
+<DT>-i<I> interface</I></DT>
+<DD>Copies the named<VAR> interface</VAR> script to the printer.
+ Interface scripts are used by System V printer drivers. Since all
+ filtering is disabled when using an interface script, scripts generally
+ should not be used unless there is no other driver for a printer.</DD>
+<DT>-m<I> model</I></DT>
+<DD>Specifies a standard printer driver which is usually a PPD file.
+ PPD's are usually stored under the<VAR> /usr/share/cups/model/</VAR>
+ directory structure. A list of all available models can be displayed
+ using the <CODE>lpinfo</CODE> command with the <CODE>-m</CODE> option.
+ A list of printer drivers included with CUPS can be found in <A HREF="#PRINTER_DRIVERS">
+Appendix C, &quot;Printer Drivers&quot;</A>.</DD>
+<DT>-r<I> class</I></DT>
+<DD>Removes the named printer from printer class<VAR> class</VAR>. If
+ the resulting class becomes empty then it is removed.</DD>
+<DT>-v<I> device-uri</I></DT>
+<DD>Sets the device for communicating with the printer. If a job is
+ currently printing on the named printer then the job will be restarted
+ and sent to the new device.</DD>
+<DT>-D<I> info</I></DT>
+<DD>Provides a textual description of the printer, e.g. &quot;John's Personal
+ Printer&quot;.</DD>
+<DT>-E</DT>
+<DD>Enables the printer and accepts job. This option is equivalent to
+ running the <CODE>enable(1)</CODE> and <CODE>accept(8)</CODE> commands
+ on the printer.</DD>
+<DT>-L<I> location</I></DT>
+<DD>Provides a textual location for the printer, e.g. &quot;Computer Lab 5&quot;.</DD>
+<DT>-P<I> ppd-file</I></DT>
+<DD>Specifies a local PPD file for the printer driver.</DD>
+</DL>
+</UL>
+<H3><A NAME="4_3_2">Deleting Printers</A></H3>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-x</CODE> option
+ to delete a printer:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>printer</I> ENTER</B>
+</PRE>
+</UL>
+<H3><A NAME="4_3_3">Setting the Default Printer</A></H3>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-d</CODE> option
+ to set a default printer:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -d <I>printer</I> ENTER</B>
+</PRE>
+</UL>
+<P>The default printer can be overridden by the user using the <CODE>
+lpoptions(1)</CODE> command.</P>
+<H3><A NAME="4_3_4">Starting and Stopping Printers</A></H3>
+<P>The <CODE>enable</CODE> and <CODE>disable</CODE> commands start and
+ stop printer queues, respectively:</P>
+<UL>
+<PRE>
+<B>/usr/bin/enable <I>printer</I> ENTER</B>
+<B>/usr/bin/disable <I>printer</I> ENTER</B>
+</PRE>
+</UL>
+<P>Printers that are disabled may still accept jobs for printing, but
+ won't actually print any files until they are restarted. This is useful
+ if the printer malfunctions and you need time to correct the problem.
+ Any queued jobs are printed after the printer is enabled (started).</P>
+<H3><A NAME="4_3_5">Accepting and Rejecting Print Jobs</A></H3>
+<P>The <CODE>accept</CODE> and <CODE>reject</CODE> commands accept and
+ reject print jobs for the named printer, respectively:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/accept <I>printer</I> ENTER</B>
+<B>/usr/sbin/reject <I>printer</I> ENTER</B>
+</PRE>
+</UL>
+<P>As noted above, a printer can be stopped but accepting new print
+ jobs. A printer can also be rejecting new print jobs while it finishes
+ those that have been queued. This is useful for when you must perform
+ maintenance on the printer and will not have it available to users for
+ a long period of time.</P>
+<H3><A NAME="4_3_6">Setting Quotas on a Printer</A></H3>
+<P>CUPS supports page and size-based quotas for each printer. The quotas
+ are tracked individually for each user, but a single set of limits
+ applies to all users for a partiuclar printer. For example, you can
+ limit every user to 5 pages per day on an expensive printer, but you
+ cannot limit every user except Johnny.</P>
+<P>The<I> job-k-limit</I>,<I> job-page-limit</I>, and<I> job-quota-peiod</I>
+ options determine whether and how quotas are enforced for a printer.
+ The<I> job-quota-period</I> option determines the time interval for
+ quota tracking. The interval is expressed in seconds, so a day is
+ 86,400, a week is 604,800 and a month is 2,592,000 seconds. The<I>
+ job-k-limit</I> option specifies the job size limit in killobytes. The<I>
+ job-page-limit</I> option specifies the number of pages limit.</P>
+<P>For quotas to be enforced, the period and at least one of the limits
+ must be set to a non-zero value. The following options will enable
+ quotas:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -o job-quota-period=604800 \
+ -o job-k-limit=1024 <I>ENTER</I></B>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -o job-quota-period=604800 \
+ -o job-page-limit=100 <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>Or, you can combine all three options on the same line.</P>
+<H3><A NAME="4_3_7">Restricting User Access to a Printer</A></H3>
+<P>The <CODE>-u</CODE> option of the <CODE>lpadmin</CODE> command
+ controls which users can print to a printer. The default configuration
+ allows all users to print to a printer:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:all <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>CUPS supports allow and deny lists so that you can specify a list of
+ users who are allowed to print or not allowed to print. Along with your
+ list of users, you can specify whether they are allowed or not allowed
+ to use the printer:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:peter,paul,mary <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>This command allows peter, paul, and mary to print to the named
+ printer, but all other users cannot print. The command:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u deny:peter,paul,mary <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>has the opposite effect. All users except peter, paul, and mary will
+ be able to print to the named printer.</P>
+<P>You can control access by UNIX groups as well by placing an &quot;@&quot;
+ character before each group name. The command:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:peter,paul,mary,@printgods <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>allows the users peter, paul, and mary to print, as well as any user
+ in the printgods group to print.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>NOTE:</B>
+<P>The<I> allow</I> and<I> deny</I> options are not cummulative. That
+ is, you must provide the complete list of users to allow or deny each
+ time.</P>
+<P>Also, CUPS only maintains one list of users - the list can allow or
+ deny users from printing. If you specify an allow list and then specify
+ a deny list, the deny list will replace the allow list - only one list
+ is active at any time.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_4">Managing Printers from the Web</A></H2>
+<P>The Web interface is located at:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>From there you can perform all printer management tasks with a few
+ simple mouse clicks.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_CLASSES">4 - Printer Classes</A></H1>
+<P>This chapter describes what printer classes are and how to manage
+ them.</P>
+<H2><A NAME="5_1">The Basics</A></H2>
+<P>CUPS provides collections of printers called<I> printer classes</I>.
+ Jobs sent to a class are forwarded to the first available printer in
+ the class. Classes can themselves be members of other classes, so it is
+ possible for you to define very large, distributed printer classes for
+ high-availability printing.</P>
+<P>CUPS also supports<I> implicit classes</I>. Implicit classes work
+ just like printer classes, but they are created automatically based
+ upon the available printers and classes on the network. This allows you
+ to setup multiple print servers with identical printer configurations
+ and have the client machines send their print jobs to the first
+ available server. If one or more servers go down, the jobs are
+ automatically redirected to the servers that are running, providing
+ fail-safe printing.</P>
+<H2><A NAME="5_2">Managing Printer Classes from the Command-Line</A></H2>
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> and <CODE>
+-c</CODE> options to add a printer to a class:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -c <I>class</I> ENTER</B>
+</PRE>
+</UL>
+<P>The<I> class</I> is created automatically if it doesn't exist. To
+ remove a printer from a class use the <CODE>-r</CODE> option:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -r <I>class</I> ENTER</B>
+</PRE>
+</UL>
+<P>To remove the entire class just use the <CODE>-x</CODE> option:</P>
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -x <I>class</I> ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Managing Printer Classes from the Web Interface</A></H2>
+<P>The Web interface is located at:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE>
+</UL>
+<P>The<VAR> Add Class</VAR> and<VAR> Modify Class</VAR> interfaces
+ provide a list of available printers; click on the printers of interest
+ to add them to the class.</P>
+<H2><A NAME="5_4">Implicit Classes</A></H2>
+<P>A noted earlier, implicit classes are created automatically from the
+ available network printers and classes. To disable this functionality,
+ set the <A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+ directive to <CODE>Off</CODE> in the <CODE>cupsd.conf</CODE> file. You
+ will find more information on doing this in <A HREF="#PRINTING_MANAGEMENT">
+Chapter 6, &quot;Printing System Management&quot;</A>.</P>
+<H1 ALIGN="RIGHT"><A NAME="CLIENT_SETUP">5 - Client Setup</A></H1>
+<P>This chapter discusses several ways to configure CUPS clients for
+ printing.</P>
+<H2><A NAME="6_1">The Basics</A></H2>
+<P>A client is any machine that sends print jobs to another machine for
+ final printing. Clients can also be servers if they communicate
+ directly with any printers of their own.</P>
+<P>CUPS supports several methods of configuring client machines:</P>
+<UL>
+<LI><A HREF="#CLIENT_MANUAL">Manual configuration of print queues.</A></LI>
+<LI><A HREF="#CLIENT_SERVER">Specifying a single server for printing.</A>
+</LI>
+<LI><A HREF="#CLIENT_AUTO">Automatic configuration of print queues.</A></LI>
+<LI><A HREF="#CLIENT_POLL">Specifying multiple servers for printing.</A></LI>
+<LI><A HREF="#CLIENT_RELAY">Relaying printers to other clients.</A></LI>
+</UL>
+<H3><A NAME="CLIENT_MANUAL">Manual Configuration of Print Queues</A></H3>
+<P>The most tedious method of configuring client machines is to
+ configure each remote queue by hand using the <CODE>lpadmin</CODE>
+ command:</P>
+<UL>
+<PRE>
+<B>lpadmin -p <I>printer</I> -E -v ipp://<I>server</I>/printers/<I>printer</I> ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>printer</CODE> name is the name of the printer on the
+ server machine. The <CODE>server</CODE> name is the hostname or IP
+ address of the server machine. Repeat the <CODE>lpadmin</CODE> command
+ for each remote printer you wish to use.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Manual configuration of print queues is not recommended for large
+ numbers of client machines because of the administration nightmare it
+ creates. For busy networks, consider subnetting groups of clients and
+ polling and relaying printer information instead.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="CLIENT_SERVER">Specifying a Single Server for Printing</A></H3>
+<P>CUPS can be configured to run without a local spooler and send all
+ jobs to a single server. However, if that server goes down then all
+ printing will be disabled. Use this configuration only as absolutely
+ needed.</P>
+<P>The default server is normally &quot;localhost&quot;. To override the default
+ server create a file named<VAR> /etc/cups/client.conf</VAR> and add a
+ line reading:</P>
+<UL>
+<PRE>
+ServerName <I>server</I>
+</PRE>
+</UL>
+<P>to the file. The<VAR> server</VAR> name can be the hostname or IP
+ address of the default server.</P>
+<P>The default server can also be customized on a per-user basis. To set
+ a user-specific server create a file named<VAR> ~/.cupsrc</VAR> and add
+ a line reading:</P>
+<UL>
+<PRE>
+ServerName <I>server</I>
+</PRE>
+</UL>
+<P>to the file. The<VAR> server</VAR> name can be the hostname or IP
+ address of the default server.</P>
+<H3><A NAME="CLIENT_AUTO">Automatic Configuration of Print Queues</A></H3>
+<P>CUPS supports automatic client configuration of printers on the same
+ subnet. To configure printers on the same subnet,<I> do nothing</I>.
+ Each client should see the available printers within 30 seconds
+ automatically. The printer and class lists are updated automatically as
+ printers and servers are added or removed.</P>
+<P>If you want to see printers on other subnets as well, use the <A HREF="#BrowsePoll">
+<CODE>BrowsePoll</CODE></A> directive as described next.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>The<A HREF="#BrowseAddress"> <CODE>BrowseAddress</CODE></A> directive
+ enables broadcast traffic from your server. The default configuration
+ braodcasts printer information every 30 seconds. Although this printer
+ information does not use much bandwidth, typically about 80 bytes per
+ printer, it can add up with large numbers of servers and printers.</P>
+<P>Use the <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> and
+ <A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A> directives to
+ tune the amount of data that is added to your network load. In
+ addition, subnets can be used to minimize the amount of traffic that is
+ carried by the &quot;backbone&quot; of your large network.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="CLIENT_POLL">Specifying Multiple Servers for Printing</A></H3>
+<P>If you have CUPS servers on different subnets, then you should
+ configure CUPS to poll those servers. Polling provides the benefits of
+ automatic configuration without significant configuration on the
+ clients, and multiple clients on the same subnet can share the same
+ configuration information.</P>
+<P>Polling is enabled by specifying one or more <A HREF="#BrowsePoll"><CODE>
+BrowsePoll</CODE></A> directives in the<VAR> /etc/cups/cupsd.conf</VAR>
+ file. For information on making these changes, see <A HREF="#PRINTING_MANAGEMENT">
+Chapter 6, &quot;Printing System Management&quot;</A>.</P>
+<P>Multiple <A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A> lines can
+ be used to poll multiple CUPS servers. To limit the amount of polling
+ you do from client machines, you can have only one of the clients do
+ the polling and relay that information to the others on the same subnet
+ (described next).</P>
+<H3><A NAME="CLIENT_RELAY">Relaying Printers to Other Clients</A></H3>
+<P>When you have clients and servers spread across multiple subnets, the
+ polling method is inefficient. CUPS provides a <A HREF="#BrowseRelay"><CODE>
+BrowseRelay</CODE></A> directive that enables a single client to relay
+ (broadcast) the polled printer information to the local subnet.</P>
+<P>For example, Server A and Server B are on subnet 1 and subnet 2,
+ while the clients are on subnet 3. To provide printers to all of the
+ clients in subnet 3, client C will be configured with the following
+ directives in<VAR> /etc/cups/cupsd.conf</VAR>:</P>
+<UL>
+<PRE>
+# Poll the two servers
+<B>
+BrowsePoll ServerA
+BrowsePoll ServerB
+</B>
+
+# Relay the printers to the local subnet
+<B>
+BrowseRelay 127.0.0.1 192.168.3.255
+</B></PRE>
+</UL>
+<P>The <A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> line
+ specifies a source address and mask. Any browse packets coming from a
+ matching address wil be sent to the given broadcast address. In this
+ case, we want the packets from the local machine (127.0.0.1) relayed to
+ the other clients.</P>
+<P>As printers are found using polling, they are relayed from client C
+ to the rest of the clients through a broadcast on subnet 3. The rest of
+ the clients can use the standard<VAR> cupsd.conf</VAR> configuration.</P>
+<P>The <A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> directive can
+ also be used to relay browsing packets from one network interface to
+ another. For example, if client C in the previous example had network
+ interfaces attaches to both subnet 1 and subnet 2, it could use the <A HREF="#BrowseRelay">
+<CODE>BrowseRelay</CODE></A> directive exclusively:</P>
+<UL>
+<PRE>
+# Relay the printers from subnet 1 and 2 to subnet 3
+<B>
+BrowseRelay 192.168.1 192.168.3.255
+BrowseRelay 192.168.2 192.168.3.255
+</B></PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H2><A NAME="6_2">Load Balancing and Failsafe Operation</A></H2>
+<P>When using server polling or broadcasting, CUPS clients can
+ automatically merge identical printers on multiple servers into a
+ single<I> implicit class</I> queue. Clients assume that printers with
+ the same name on multiple servers are in fact the same printer or type
+ of printer being served by multiple machines.</P>
+<P>If you have two printers, LaserJet@ServerA and LaserJet@ServerB, a
+ third implicit class called<I> LaserJet</I> will be created
+ automatically on the client that refers to both printers. If the client
+ also has a local printer with the name LaserJet and the <A HREF="#ImplicitAnyClasses">
+<CODE>ImplicitAnyClasses</CODE></A> directive is enabled, then an
+ implicit class named<I> AnyLaserJet</I> will be created instead.
+ Otherwise, the local printer will prevent the creation of an implicit
+ class, since CUPS will assume that the local printer will always be
+ more available than a remote one.</P>
+<P>The client will alternate between servers and automatically stop
+ sending jobs to a server if it goes down, providing a load-balancing
+ effect and fail-safe operation with automatic switchover.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Note that implicit classes (<A HREF="#ImplicitClasses"><CODE>
+ImplicitClasses</CODE></A>) are enabled and implicit &quot;any&quot; classes (<A HREF="#ImplicitAnyClasses">
+<CODE>ImplicitAnyClasses</CODE></A>) are disabled by default.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Printing System
+ Management</A></H1>
+<P>This chapter shows how you can configure the CUPS server.</P>
+<H2><A NAME="7_1">The Basics</A></H2>
+<P>Several text files are used to configure CUPS. All of the server
+ configuration files are located in the<VAR> /etc/cups</VAR> directory:</P>
+<UL>
+<DL>
+<!-- NEED 1in -->
+<DT>classes.conf</DT>
+<DD>This file contains information on each printer class. Normally you
+ manipulate this file using the <CODE>lpadmin</CODE> command or the Web
+ interface.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>client.conf</DT>
+<DD>This file provides the default server name for client machines. See <A
+HREF="#CLIENT_SETUP">Chapter 5, &quot;Client Setup&quot;</A> for more information.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>cupsd.conf</DT>
+<DD>This file controls how the CUPS server (<VAR>/usr/sbin/cupsd</VAR>)
+ operates and is normally edited by hand.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.convs</DT>
+<DD>This file contains a list of standard file conversion filters and
+ their costs. You normally do not edit this file.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>mime.types</DT>
+<DD>This file contains a list of standard file formats and how to
+ recognize them. You normally do not edit this file.
+<BR>&nbsp;
+<!-- NEED 1in -->
+</DD>
+<DT>printers.conf</DT>
+<DD>This file contains information on each printer. Normally you
+ manipulate this file using the <CODE>lpadmin</CODE> command or the Web
+ Interface.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="RESTARTING">Restarting the CUPS Server</A></H2>
+<P>Once you have made a change to a configuration file you need to
+ restart the CUPS server by sending it a <CODE>HUP</CODE> signal or
+ using the supplied initialization script. The CUPS distributions
+ install the script in the<VAR> init.d</VAR> directory with the name<VAR>
+ cups</VAR>. The location varies based upon the operating system:</P>
+<UL>
+<PRE>
+<B>/etc/software/init.d/cups restart ENTER</B>
+<B>/etc/rc.d/init.d/cups restart ENTER</B>
+<B>/etc/init.d/cups restart ENTER</B>
+<B>/sbin/init.d/cups restart ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="7_3">Changing the Server Configuration</A></H2>
+<P>The<VAR> /etc/cups/cupsd.conf</VAR> file contains configuration<I>
+ directives</I> that control how the server functions. Each directive is
+ listed on a line by itself followed by its value. Comments are
+ introduced using the number sign (&quot;#&quot;) character at the beginning of a
+ line. Since the server configuration file consists of plain text, you
+ can use your favorite text editor to make changes to it.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="7_4">Server Directives</A></H2>
+<P>The<VAR> cupsd.conf</VAR> file contains many directives that
+ determine how the server operates:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#AccessLog"><CODE>AccessLog</CODE></A></LI>
+<LI><A HREF="#Allow"><CODE>Allow</CODE></A></LI>
+<LI><A HREF="#AuthClass"><CODE>AuthClass</CODE></A></LI>
+<LI><A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A></LI>
+<LI><A HREF="#AuthType"><CODE>AuthType</CODE></A></LI>
+<LI><A HREF="#AutoPurgeJobs"><CODE>AutoPurgeJobs</CODE></A></LI>
+<LI><A HREF="#BrowseAddress"><CODE>BrowseAddress</CODE></A></LI>
+<LI><A HREF="#BrowseAllow"><CODE>BrowseAllow</CODE></A></LI>
+<LI><A HREF="#BrowseDeny"><CODE>BrowseDeny</CODE></A></LI>
+<LI><A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A></LI>
+<LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A></LI>
+<LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A></LI>
+<LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A></LI>
+<LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A></LI>
+<LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A></LI>
+<LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
+<LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
+<LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
+<LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
+<LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A></LI>
+<LI><A HREF="#ConfigFilePerm"><CODE>ConfigFilePerm</CODE></A></LI>
+<LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
+<LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
+<LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
+<LI><A HREF="#Deny"><CODE>Deny</CODE></A></LI>
+<LI><A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A></LI>
+<LI><A HREF="#Encryption"><CODE>Encryption</CODE></A></LI>
+<LI><A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A></LI>
+<LI><A HREF="#FaxRetryInterval"><CODE>FaxRetryInterval</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#FaxRetryLimit"><CODE>FaxRetryLimit</CODE></A></LI>
+<LI><A HREF="#FileDevice"><CODE>FileDevice</CODE></A></LI>
+<LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A></LI>
+<LI><A HREF="#FilterNice"><CODE>FilterNice</CODE></A></LI>
+<LI><A HREF="#FontPath"><CODE>FontPath</CODE></A></LI>
+<LI><A HREF="#Group"><CODE>Group</CODE></A></LI>
+<LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A></LI>
+<LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A></LI>
+<LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A></LI>
+<LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A></LI>
+<LI><A HREF="#Include"><CODE>Include</CODE></A></LI>
+<LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A></LI>
+<LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A></LI>
+<LI><A HREF="#Limit"><CODE>Limit</CODE></A></LI>
+<LI><A HREF="#LimitExcept"><CODE>LimitExcept</CODE></A></LI>
+<LI><A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A></LI>
+<LI><A HREF="#Listen"><CODE>Listen</CODE></A></LI>
+<LI><A HREF="#Location"><CODE>Location</CODE></A></LI>
+<LI><A HREF="#LogFilePerm"><CODE>LogFilePerm</CODE></A></LI>
+<LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A></LI>
+<LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A></LI>
+<LI><A HREF="#MaxClientsPerHost"><CODE>MaxClientsPerHost</CODE></A></LI>
+<LI><A HREF="#MaxCopies"><CODE>MaxCopies</CODE></A></LI>
+<LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A></LI>
+<LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
+<LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
+<LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
+<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
+<LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
+<LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
+<LI><A HREF="#Printcap"><CODE>Printcap</CODE></A></LI>
+<LI><A HREF="#PrintcapFormat"><CODE>PrintcapFormat</CODE></A></LI>
+<LI><A HREF="#PrintcapGUI"><CODE>PrintcapGUI</CODE></A></LI>
+<LI><A HREF="#ReloadTimeout"><CODE>ReloadTimeout</CODE></A></LI>
+<LI><A HREF="#RemoteRoot"><CODE>RemoteRoot</CODE></A></LI>
+<LI><A HREF="#RequestRoot"><CODE>RequestRoot</CODE></A></LI>
+<LI><A HREF="#Require"><CODE>Require</CODE></A></LI>
+<LI><A HREF="#RIPCache"><CODE>RIPCache</CODE></A></LI>
+<LI><A HREF="#RootCertDuration"><CODE>RootCertDuration</CODE></A></LI>
+<LI><A HREF="#RunAsUser"><CODE>RunAsUser</CODE></A></LI>
+<LI><A HREF="#Satisfy"><CODE>Satisfy</CODE></A></LI>
+<LI><A HREF="#ServerAdmin"><CODE>ServerAdmin</CODE></A></LI>
+<LI><A HREF="#ServerBin"><CODE>ServerBin</CODE></A></LI>
+<LI><A HREF="#ServerCertificate"><CODE>ServerCertificate</CODE></A></LI>
+<LI><A HREF="#ServerKey"><CODE>ServerKey</CODE></A></LI>
+<LI><A HREF="#ServerName"><CODE>ServerName</CODE></A></LI>
+<LI><A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A></LI>
+<LI><A HREF="#ServerTokens"><CODE>ServerTokens</CODE></A></LI>
+<LI><A HREF="#SSLListen"><CODE>SSLListen</CODE></A></LI>
+<LI><A HREF="#SSLPort"><CODE>SSLPort</CODE></A></LI>
+<LI><A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A></LI>
+<LI><A HREF="#TempDir"><CODE>TempDir</CODE></A></LI>
+<LI><A HREF="#Timeout"><CODE>Timeout</CODE></A></LI>
+<LI><A HREF="#User"><CODE>User</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="AccessLog">AccessLog</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AccessLog /var/log/cups/access_log
+AccessLog /var/log/cups/access_log-%s
+AccessLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AccessLog</CODE> directive sets the name of the access log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+ access log file is stored in &quot;common log format&quot; and can be used by any
+ web access reporting tool to generate a report on CUPS server activity.</P>
+<P>The server name can be included in the filename by using <CODE>%s</CODE>
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the access information
+ to the system log instead of a plain file.</P>
+<P>The default access log file is<VAR> /var/log/cups/access_log</VAR>.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="Allow">Allow</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Allow from All
+Allow from None
+Allow from *.domain.com
+Allow from .domain.com
+Allow from host.domain.com
+Allow from nnn.*
+Allow from nnn.nnn.*
+Allow from nnn.nnn.nnn.*
+Allow from nnn.nnn.nnn.nnn
+Allow from nnn.nnn.nnn.nnn/mm
+Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+Allow from @LOCAL
+Allow from @IF(name)
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Allow</CODE> directive specifies a hostname, IP address, or
+ network that is allowed access to the server. <CODE>Allow</CODE>
+ directives are cummulative, so multiple <CODE>Allow</CODE> directives
+ can be used to allow access for multiple hosts or networks. The <CODE>
+/mm</CODE> notation specifies a CIDR netmask:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>The <CODE>@LOCAL</CODE> name will allow access from all local network
+ interfaces, but not remote point-to-point interfaces. The <CODE>
+@IF(name)</CODE> name will allow access from the named interface.</P>
+<P>The <CODE>Allow</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthClass">AuthClass</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AuthClass Anonymous
+AuthClass User
+AuthClass System
+AuthClass Group
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AuthClass</CODE> directive defines what level of
+ authentication is required:</P>
+<UL>
+<LI><CODE>Anonymous</CODE> - No authentication should be performed
+ (default.)</LI>
+<LI><CODE>User</CODE> - A valid username and password is required.</LI>
+<LI><CODE>System</CODE> - A valid username and password is required, and
+ the username must belong to the &quot;sys&quot; group; this can be changed using
+ the <A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A> directive.</LI>
+<LI><CODE>Group</CODE> - A valid username and password is required, and
+ the username must belong to the group named by the <CODE>AuthGroupName</CODE>
+ directive.</LI>
+</UL>
+<P>The <CODE>AuthClass</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AuthGroupName">AuthGroupName</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AuthGroupName mygroup
+AuthGroupName lp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AuthGroupName</CODE> directive sets the group to use for <CODE>
+Group</CODE> authentication.</P>
+<P>The <CODE>AuthGroupName</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="AuthType">AuthType</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AuthType None
+AuthType Basic
+AuthType Digest
+AuthType BasicDigest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AuthType</CODE> directive defines the type of
+ authentication to perform:</P>
+<UL>
+<LI><CODE>None</CODE> - No authentication should be performed (default.)</LI>
+<LI><CODE>Basic</CODE> - Basic authentication should be performed using
+ the UNIX password and group files.</LI>
+<LI><CODE>Digest</CODE> - Digest authentication should be performed
+ using the<VAR> /etc/cups/passwd.md5</VAR> file.</LI>
+<LI><CODE>BasicDigest</CODE> - Basic authentication should be performed
+ using the<VAR> /etc/cups/passwd.md5</VAR> file.</LI>
+</UL>
+<P>When using <CODE>Basic</CODE>, <CODE>Digest</CODE>, or <CODE>
+BasicDigest</CODE> authentication, clients connecting through the <CODE>
+localhost</CODE> interface can also authenticate using <A HREF="#CERTIFICATES">
+certificates</A>.</P>
+<P>The <CODE>AuthType</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AutoPurgeJobs">AutoPurgeJobs</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AutoPurgeJobs Yes
+AutoPurgeJobs No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AutoPurgeJobs</CODE> directive specifies whether or not to
+ purge completed jobs once they are no longer required for quotas. This
+ option has no effect if quotas are not enabled. The default setting is <CODE>
+No</CODE>.
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="BrowseAddress">BrowseAddress</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseAddress 255.255.255.255:631
+BrowseAddress 192.0.2.255:631
+BrowseAddress host.domain.com:631
+BrowseAddress @LOCAL
+BrowseAddress @IF(name)
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseAddress</CODE> directive specifies an address to send
+ browsing information to. Multiple <CODE>BrowseAddress</CODE> directives
+ can be specified to send browsing information to different networks or
+ systems.</P>
+<P>The <CODE>@LOCAL</CODE> name will broadcast printer information to
+ all local interfaces. The <CODE>@IF(name)</CODE> name will broadcast to
+ the named interface.</P>
+<P>No browse addresses are set by default.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>If you are using HP-UX 10.20 and a subnet that is not 24, 16, or 8
+ bits, printer browsing (and in fact all broadcast reception) will not
+ work. This problem appears to be fixed in HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+<H3><A NAME="BrowseAllow">BrowseAllow</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseAllow from all
+BrowseAllow from none
+BrowseAllow from 192.0.2
+BrowseAllow from 192.0.2.0/24
+BrowseAllow from 192.0.2.0/255.255.255.0
+BrowseAllow from *.domain.com
+BrowseAllow from @LOCAL
+BrowseAllow from @IF(name)
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseAllow</CODE> directive specifies a system or network
+ to accept browse packets from. The default is to accept browse packets
+ from all hosts.</P>
+<P>Host and domain name matching require that you enable the <A HREF="#HostNameLookups">
+<CODE>HostNameLookups</CODE></A> directive.</P>
+<P>IP address matching supports exact matches, partial addresses that
+ match networks using netmasks of 255.0.0.0, 255.255.0.0, and
+ 255.255.255.0, or network addresses using the specified netmask or bit
+ count.</P>
+<P>The <CODE>@LOCAL</CODE> name will allow browse data from all local
+ network interfaces, but not remote point-to-point interfaces. The <CODE>
+@IF(name)</CODE> name will allow browse data from the named interface.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="BrowseDeny">BrowseDeny</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseDeny from all
+BrowseDeny from none
+BrowseDeny from 192.0.2
+BrowseDeny from 192.0.2.0/24
+BrowseDeny from 192.0.2.0/255.255.255.0
+BrowseDeny from *.domain.com
+BrowseDeny from @LOCAL
+BrowseDeny from @IF(name)
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseDeny</CODE> directive specifies a system or network
+ to reject browse packets from. The default is to deny browse packets
+ from no hosts.</P>
+<P>Host and domain name matching require that you enable the <A HREF="#HostNameLookups">
+<CODE>HostNameLookups</CODE></A> directive.</P>
+<P>IP address matching supports exact matches, partial addresses that
+ match networks using netmasks of 255.0.0.0, 255.255.0.0, and
+ 255.255.255.0, or network addresses using the specified netmask or bit
+ count.</P>
+<P>The <CODE>@LOCAL</CODE> name will block browse data from all local
+ network interfaces, but not remote point-to-point interfaces. The <CODE>
+@IF(name)</CODE> name will block browse data from the named interface.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseInterval 0
+BrowseInterval 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseInterval</CODE> directive specifies the maximum
+ amount of time between browsing updates. Specifying a value of 0
+ seconds disables outgoing browse updates but allows a server to receive
+ printer information from other hosts.</P>
+<P>The <CODE>BrowseInterval</CODE> value should always be less than the <A
+HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A> value. Otherwise
+ printers and classes will disappear from client systems between
+ updates.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseOrder">BrowseOrder</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseOrder allow,deny
+BrowseOrder deny,allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseOrder</CODE> directive specifies the order of
+ allow/deny processing. The default order is <CODE>deny,allow</CODE>:</P>
+<UL>
+<LI><CODE>allow,deny</CODE> - Browse packets are accepted unless
+ specifically denied.</LI>
+<LI><CODE>deny,allow</CODE> - Browse packets are rejected unless
+ specifically allowed.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowsePoll">BrowsePoll</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowsePoll 192.0.2.2:631
+BrowsePoll host.domain.com:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowsePoll</CODE> directive polls a server for available
+ printers once every <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE>
+</A> seconds. Multiple <CODE>BrowsePoll</CODE> directives can be
+ specified to poll multiple servers.</P>
+<P>If <CODE>BrowseInterval</CODE> is set to 0 then the server is polled
+ once every 30 seconds.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowsePort">BrowsePort</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowsePort 631
+BrowsePort 9999
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowsePort</CODE> directive specifies the UDP port number
+ used for browse packets. The default port number is 631.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>You must set the <CODE>BrowsePort</CODE> to the same value on all of
+ the systems that you want to see.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseProtocols</CODE> directive specifies the protocols to
+ use when collecting and distributing shared printers on the local
+ network. The default protocol is <CODE>CUPS</CODE>, which is a
+ broadcast-based protocol.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>When using the <CODE>SLP</CODE> protocol, you must have at least one
+ Directory Agent (DA) server on your network. Otherwise the CUPS
+ scheduler (<CODE>cupsd</CODE>) will not respond to client requests for
+ several seconds while polling the network.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+<H3><A NAME="BrowseRelay">BrowseRelay</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseRelay 193.0.2.1 192.0.2.255
+BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
+BrowseRelay 193.0.2.0/24 192.0.2.255
+BrowseRelay *.domain.com 192.0.2.255
+BrowseRelay host.domain.com 192.0.2.255
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseRelay</CODE> directive specifies source and
+ destination addresses for relaying browsing information from one host
+ or network to another. Multiple <CODE>BrowseRelay</CODE> directives can
+ be specified as needed.</P>
+<P><CODE>BrowseRelay</CODE> is typically used on systems that bridge
+ multiple subnets using one or more network interfaces. It can also be
+ used to relay printer information from polled servers with the line:</P>
+<UL>
+<PRE>
+BrowseRelay 127.0.0.1 255.255.255.255
+</PRE>
+</UL>
+<P>This effectively provides access to printers on a WAN for all clients
+ on the LAN(s).
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseShortNames">BrowseShortNames</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseShortNames Yes
+BrowseShortNames No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseShortNames</CODE> directive specifies whether or not
+ short names are used for remote printers when possible. Short names are
+ just the remote printer name, without the server (&quot;printer&quot;). If more
+ than one remote printer is detected with the same name, the printers
+ will have long names (&quot;printer@server1&quot;, &quot;printer@server2&quot;.)</P>
+<P>The default value for this option is <CODE>Yes</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="BrowseTimeout">BrowseTimeout</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+BrowseTimeout 300
+BrowseTimeout 60
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>BrowseTimeout</CODE> directive sets the timeout for printer
+ or class information that is received in browse packets. Once a printer
+ or class times out it is removed from the list of available
+ destinations.</P>
+<P>The <CODE>BrowseTimeout</CODE> value should always be greater than
+ the <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> value.
+ Otherwise printers and classes will disappear from client systems
+ between updates.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Browsing">Browsing</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Browsing On
+Browsing Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Browsing</CODE> directive controls whether or not network
+ printer browsing is enabled. The default setting is <CODE>On</CODE>.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>If you are using HP-UX 10.20 and a subnet that is not 24, 16, or 8
+ bits, printer browsing (and in fact all broadcast reception) will not
+ work. This problem appears to be fixed in HP-UX 11.0.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Classification</CODE> directive sets the classification
+ level on the server. When this option is set, at least one of the
+ banner pages is forced to the classification level, and the
+ classification is placed on each page of output. The default is no
+ classification level.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ClassifyOverride</CODE> directive specifies whether users
+ can override the default classification level on the server. When the
+ server classification is set, users can change the classification using
+ the <CODE>job-sheets</CODE> option and can choose to only print one
+ security banner before or after the job. If the <CODE>job-sheets</CODE>
+ option is set to <CODE>none</CODE> then the server default
+ classification is used.</P>
+<P>The default is to not allow classification overrides.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ConfigFilePerm">ConfigFilePerm</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ConfigFilePerm 0644
+ConfigFilePerm 0600
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ConfigFilePerm</CODE> directive specifies the permissions
+ to use when writing configuration files. The default is 0600.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DataDir">DataDir</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DataDir /usr/share/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DataDir</CODE> directive sets the directory to use for data
+ files.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultCharset">DefaultCharset</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DefaultCharset utf-8
+DefaultCharset iso-8859-1
+DefaultCharset windows-1251
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DefaultCharset</CODE> directive sets the default character
+ set to use for client connections. The default character set is <CODE>
+utf-8</CODE> but is overridden by the character set for the language
+ specified by the client or the <CODE>DefaultLanguage</CODE> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DefaultLanguage de
+DefaultLanguage en
+DefaultLanguage es
+DefaultLanguage fr
+DefaultLanguage it
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DefaultLanguage</CODE> directive specifies the default
+ language to use for client connections. Setting the default language
+ also sets the default character set if a language localization file
+ exists for it. The default language is &quot;en&quot; for English.
+<!-- NEED 5in -->
+</P>
+<H3><A NAME="Deny">Deny</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Deny from All
+Deny from None
+Deny from *.domain.com
+Deny from .domain.com
+Deny from host.domain.com
+Deny from nnn.*
+Deny from nnn.nnn.*
+Deny from nnn.nnn.nnn.*
+Deny from nnn.nnn.nnn.nnn
+Deny from nnn.nnn.nnn.nnn/mm
+Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+Deny from @LOCAL
+Deny from @IF(name)
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Deny</CODE> directive specifies a hostname, IP address, or
+ network that is allowed access to the server. <CODE>Deny</CODE>
+ directives are cummulative, so multiple <CODE>Deny</CODE> directives
+ can be used to allow access for multiple hosts or networks. The <CODE>
+/mm</CODE> notation specifies a CIDR netmask:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="10%">mm</TH><TH WIDTH="20%">netmask</TH><TH WIDTH="10%">
+mm</TH><TH WIDTH="20%">netmask</TH></TR>
+<TR><TD ALIGN="CENTER">0</TD><TD ALIGN="CENTER">0.0.0.0</TD><TD ALIGN="CENTER">
+8</TD><TD ALIGN="CENTER">255.0.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">1</TD><TD ALIGN="CENTER">128.0.0.0</TD><TD ALIGN="CENTER">
+16</TD><TD ALIGN="CENTER">255.255.0.0</TD></TR>
+<TR><TD ALIGN="CENTER">2</TD><TD ALIGN="CENTER">192.0.0.0</TD><TD ALIGN="CENTER">
+24</TD><TD ALIGN="CENTER">255.255.255.0</TD></TR>
+<TR><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">...</TD><TD ALIGN="CENTER">
+32</TD><TD ALIGN="CENTER">255.255.255.255</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>The <CODE>@LOCAL</CODE> name will deny access from all local network
+ interfaces, but not remote point-to-point interfaces. The <CODE>
+@IF(name)</CODE> name will deny access from the named interface.</P>
+<P>The <CODE>Deny</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DocumentRoot">DocumentRoot</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DocumentRoot /usr/share/doc/cups
+DocumentRoot /foo/bar/doc/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DocumentRoot</CODE> directive specifies the location of web
+ content for the HTTP server in CUPS. If an absolute path is not
+ specified then it is assumed to be relative to the <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A> directory. The default directory is<VAR>
+ /usr/share/doc/cups</VAR>.</P>
+<P>Documents are first looked up in a sub-directory for the primary
+ language requested by the client (e.g.<VAR> /usr/share/doc/cups/fr/...</VAR>
+) and then directly under the <CODE>DocumentRoot</CODE> directory (e.g.<VAR>
+ /usr/share/doc/cups/...</VAR>), so it is possible to localize the web
+ content by providing subdirectories for each language needed.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Encryption</CODE> directive must appear instead a <A HREF="#Location">
+<CODE>Location</CODE></A> section and specifies the encryption settings
+ for that location. The default setting is <CODE>IfRequested</CODE> for
+ all locations.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ErrorLog">ErrorLog</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ErrorLog /var/log/cups/error_log
+ErrorLog /var/log/cups/error_log-%s
+ErrorLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ErrorLog</CODE> directive sets the name of the error log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+ default error log file is<VAR> /var/log/cups/error_log</VAR>.</P>
+<P>The server name can be included in the filename by using <CODE>%s</CODE>
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the error information
+ to the system log instead of a plain file.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="FaxRetryInterval">FaxRetryInterval</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FaxRetryInterval 300
+FaxRetryInterval 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FaxRetryInterval</CODE> directive determines how often fax
+ print jobs are retried when the backend is unable to send the fax. The
+ value is the number of seconds between tries.</P>
+<P>The default setting is <CODE>300</CODE> seconds.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="FaxRetryLimit">FaxRetryLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FaxRetryLimit 5
+FaxRetryLimit 100
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FaxRetryLimit</CODE> directive determines how many times a
+ fax job is retried before it is canceled.</P>
+<P>The default setting is <CODE>5</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FileDevice">FileDevice</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FileDevice Yes
+FileDevice No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FileDevice</CODE> directive determines whether the
+ scheduler allows new printers to be added using device URIs of the form
+ <CODE>file:/filename</CODE>. File devices are most often used to test
+ new printer drivers and do no support raw file printing.</P>
+<P>The default setting is <CODE>No</CODE>.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> Note:</B>
+<P>File devices are managed by the scheduler. Since the scheduler
+ normally runs as the root user, file devices can be used to overwrite
+ system files and potentially gain unauthorized access to the system. If
+ you must create printers using file devices, we recommend that you set
+ the <CODE>FileDevice</CODE> directive to <CODE>Yes</CODE> for only as
+ long as you need to add the printers to the system, and then reset the
+ directive to <CODE>No</CODE>.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FilterLimit">FilterLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FilterLimit 0
+FilterLimit 200
+FilterLimit 1000
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FilterLimit</CODE> directive sets the maximum cost of all
+ running job filters. It can be used to limit the number of filter
+ programs that are run on a server to minimize disk, memory, and CPU
+ resource problems. A limit of 0 disables filter limiting.</P>
+<P>An average print to a non-PostScript printer needs a filter limit of
+ about 200. A PostScript printer needs about half that (100). Setting
+ the limit below these thresholds will effectively limit the scheduler
+ to printing a single job at any time.</P>
+<P>The default limit is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FilterNice">FilterNice</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FilterNice 0
+FilterNice 39
+FilterNice -10
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FilterNice</CODE> directive sets the scheduling priority of
+ job filters. Values larger than 0 give filters a lower priority while
+ values smaller than 0 give filters a higher priority. The <CODE>
+FilterNice</CODE> value does not affect the priority of job backends.</P>
+<P>The default priority is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="FontPath">FontPath</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+FontPath /foo/bar/fonts
+FontPath /usr/share/cups/fonts:/foo/bar/fonts
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>FontPath</CODE> directive specifies the font path to use
+ when searching for fonts. The default font path is <CODE>
+/usr/share/cups/fonts</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Group">Group</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Group sys
+Group system
+Group root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Group</CODE> directive specifies the UNIX group that filter
+ and CGI programs run as. The default group is <CODE>sys</CODE>, <CODE>
+system</CODE>, or <CODE>root</CODE> depending on the operating system.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>HideImplicitMembers</CODE> directive controls whether the
+ individual printers in an implicit class are shown to the user. The
+ default is <CODE>No</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> must be
+ enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+HostNameLookups On
+HostNameLookups Off
+HostNameLookups Double
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>HostNameLookups</CODE> directive controls whether or not
+ CUPS looks up the hostname for connecting clients. The <CODE>Double</CODE>
+ setting causes CUPS to verify that the hostname resolved from the
+ address matches one of the addresses returned for that hostname. <CODE>
+Double</CODE> lookups also prevent clients with unregistered addresses
+ from connecting to your server. The default is <CODE>Off</CODE> to
+ avoid the potential server performance problems with hostname lookups.
+ Set this option to <CODE>On</CODE> or <CODE>Double</CODE> only if
+ absolutely required.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ImplicitAnyClasses</CODE> directive controls whether
+ implicit classes for local and remote printers are created with the
+ name <CODE>AnyPrinter</CODE>. The default setting is <CODE>Off</CODE>.</P>
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A> must be
+ enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ImplicitClasses">ImplicitClasses</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ImplicitClasses On
+ImplicitClasses Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ImplicitClasses</CODE> directive controls whether implicit
+ classes are created based upon the available network printers and
+ classes. The default setting is <CODE>On</CODE> but is automatically
+ turned <CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A>
+ is turned <CODE>Off</CODE>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Include filename
+Include /foo/bar/filename
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Include</CODE> directive includes the named file in the <CODE>
+cupsd.conf</CODE> file. If no leading path is provided, the file is
+ assumed to be relative to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE>
+</A> directory.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="KeepAlive">KeepAlive</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+KeepAlive On
+KeepAlive Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>KeepAlive</CODE> directive controls whether or not to
+ support persistent HTTP connections. The default is <CODE>On</CODE>.</P>
+<P>HTTP/1.1 clients automatically support persistent connections, while
+ HTTP/1.0 clients must specifically request them using the <CODE>
+Keep-Alive</CODE> attribute in the <CODE>Connection:</CODE> field of
+ each request.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="KeepAliveTimeout">KeepAliveTimeout</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+KeepAliveTimeout 60
+KeepAliveTimeout 30
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long a
+ persistent HTTP connection will remain open after the last request. The
+ default is 60 seconds.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Limit">Limit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;Limit GET POST&gt;
+...
+&lt;/Limit&gt;
+
+&lt;Limit ALL&gt;
+...
+&lt;/Limit&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Limit</CODE> directive groups access control directives for
+ specific types of HTTP requests and must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> section. Access can be limited for individual
+ request types (<CODE>DELETE</CODE>, <CODE>GET</CODE>, <CODE>HEAD</CODE>
+, <CODE>OPTIONS</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE>, and <CODE>
+TRACE</CODE>) or for all request types (<CODE>ALL</CODE>). The request
+ type names are case-sensitive for compatibility with Apache.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitExcept">LimitExcept</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;LimitExcept GET POST&gt;
+...
+&lt;/LimitExcept&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>LimitExcept</CODE> directive groups access control
+ directives for specific types of HTTP requests and must appear inside a
+ <A HREF="#Location"><CODE>Location</CODE></A> section. Unlike the <A HREF="#Limit">
+<CODE>Limit</CODE></A> directive, <CODE>LimitExcept</CODE> restricts
+ access for all requests<I> except</I> those listed on the <CODE>
+LimitExcept</CODE> line.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LimitRequestBody">LimitRequestBody</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+LimitRequestBody 10485760
+LimitRequestBody 10m
+LimitRequestBody 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>LimitRequestBody</CODE> directive controls the maximum size
+ of print files, IPP requests, and HTML form data in HTTP POST requests.
+ The default limit is 0 which disables the limit check.</P>
+<P>Also see the identical <A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE>
+</A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Listen">Listen</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Listen 127.0.0.1:631
+Listen 192.0.2.1:631
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Listen</CODE> directive specifies a network address and
+ port to listen for connections. Multiple <CODE>Listen</CODE> directives
+ can be provided to listen on multiple addresses.</P>
+<P>The <CODE>Listen</CODE> directive is similar to the <A HREF="#Port"><CODE>
+Port</CODE></A> directive but allows you to restrict access to specific
+ interfaces or networks.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Location">Location</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;Location /&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /admin&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers/name&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /classes&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /classes/name&gt;
+...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Location</CODE> directive specifies access control and
+ authentication options for the specified HTTP resource or path. The <A HREF="#Allow">
+<CODE>Allow</CODE></A>, <A HREF="#AuthClass"><CODE>AuthClass</CODE></A>,
+ <A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>, <A HREF="#AuthType">
+<CODE>AuthType</CODE></A>, <A HREF="#Deny"><CODE>Deny</CODE></A>, <A HREF="#Encryption">
+<CODE>Encryption</CODE></A>, <A HREF="#Limit"><CODE>Limit</CODE></A>, <A HREF="#LimitExcept">
+<CODE>LimitExcept</CODE></A>, <A HREF="#Order"><CODE>Order</CODE></A>, <A
+HREF="#Require"><CODE>Require</CODE></A>, and <A HREF="#Satisfy"><CODE>
+Satisfy</CODE></A> directives may all appear inside a location.
+<CENTER>
+<TABLE BORDER="1"><CAPTION>Locations on the Server.</CAPTION>
+<TR><TH>Location</TH><TH>Description</TH></TR>
+<TR><TD>/</TD><TD>The path for all get operations (get-printers,
+ get-jobs, etc.)</TD></TR>
+<TR><TD>/admin</TD><TD>The path for all administration operations
+ (add-printer, delete-printer, start-printer, etc.)</TD></TR>
+<TR><TD>/admin/conf</TD><TD>The path for access to the CUPS
+ configuration files (cupsd.conf, client.conf, etc.)</TD></TR>
+<TR><TD>/classes</TD><TD>The path for all classes</TD></TR>
+<TR><TD>/classes/name</TD><TD>The resource for class <CODE>name</CODE></TD>
+</TR>
+<TR><TD>/jobs</TD><TD>The path for all jobs (hold-job, release-job,
+ etc.)</TD></TR>
+<TR><TD>/jobs/id</TD><TD>The resource for job <CODE>id</CODE></TD></TR>
+<TR><TD>/printers</TD><TD>The path for all printers</TD></TR>
+<TR><TD>/printers/name</TD><TD>The path for printer <CODE>name</CODE></TD>
+</TR>
+<TR><TD>/printers/name.ppd</TD><TD>The PPD file path for printer <CODE>
+name</CODE></TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>Note that more specific resources override the less specific ones. So
+ the directives inside the <CODE>/printers/name</CODE> location will
+ override ones from <CODE>/printers</CODE>. Directives inside <CODE>
+/printers</CODE> will override ones from <CODE>/</CODE>. &nbsp; None of the
+ directives are inherited. More information can be found in section <A HREF="#PRINTING_SECURITY">
+&quot;Printing System Security&quot;</A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LogFilePerm">LogFilePerm</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+LogFilePerm 0644
+LogFilePerm 0600
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>LogFilePerm</CODE> directive specifies the permissions to
+ use when writing configuration files. The default is 0644.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="LogLevel">LogLevel</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+LogLevel none
+LogLevel emerg
+LogLevel alert
+LogLevel crit
+LogLevel error
+LogLevel warn
+LogLevel notice
+LogLevel info
+LogLevel debug
+LogLevel debug2
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>LogLevel</CODE> directive specifies the level of logging
+ for the <A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A> file. The
+ following values are recognized (each level logs everything under the
+ preceding levels):</P>
+<UL>
+<LI><CODE>none</CODE> - Log nothing.</LI>
+<LI><CODE>emerg</CODE> - Log emergency conditions that prevent the
+ server from running.</LI>
+<LI><CODE>alert</CODE> - Log alerts that must be handled immediately.</LI>
+<LI><CODE>crit</CODE> - Log critical errors that don't prevent the
+ server from running.</LI>
+<LI><CODE>error</CODE> - Log general errors.</LI>
+<LI><CODE>warn</CODE> - Log errors and warnings.</LI>
+<LI><CODE>notice</CODE> - Log temporary error conditions.</LI>
+<LI><CODE>info</CODE> - Log all requests and state changes (default).</LI>
+<LI><CODE>debug</CODE> - Log basic debugging information.</LI>
+<LI><CODE>debug2</CODE> - Log all debugging information.</LI>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClients">MaxClients</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxClients 100
+MaxClients 1024
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxClients</CODE> directive controls the maximum number of
+ simultaneous clients that will be allowed by the server. The default is
+ 100 clients.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Since each print job requires a file descriptor for the status pipe,
+ the CUPS server internally limits the <CODE>MaxClients</CODE> value to
+ 1/3 of the available file descriptors to avoid possible problems when
+ printing large numbers of jobs.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClientsPerHost">MaxClientsPerHost</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxClientsPerHost 0
+MaxClientsPerHost 10
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxClientsPerHost</CODE> directive controls the maximum
+ number of simultaneous clients that will be allowed from a single host
+ by the server. The default is the <CODE>MaxClients</CODE> value. A
+ value of 0 uses the automatic setting based on the <CODE>MaxClients</CODE>
+ value.</P>
+<P>This directive provides a small measure of protection against Denial
+ of Service attacks from a single host.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxCopies">MaxCopies</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxCopies 100
+MaxCopies 65535
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxCopies</CODE> directive controls the maximum number of
+ copies that a user can print of a job. The default is 100 copies.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Most HP PCL laser printers internally limit the number of copies to
+ 100.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxJobs">MaxJobs</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobs 100
+MaxJobs 9999
+MaxJobs 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobs</CODE> directive controls the maximum number of
+ jobs that are kept in memory. Once the number of jobs reaches the
+ limit, the oldest completed job is automatically purged from the system
+ to make room for the new one. If all of the known jobs are still
+ pending or active then the new job will be rejected.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 500.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum
+ number of active jobs that are allowed for each printer or class. Once
+ a printer or class reaches the limit, new jobs will be rejected until
+ one of the active jobs is completed, stopped, aborted, or cancelled.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum number
+ of active jobs that are allowed for each user. Once a user reaches the
+ limit, new jobs will be rejected until one of the active jobs is
+ completed, stopped, aborted, or cancelled.</P>
+<P>Setting the maximum to 0 disables this functionality. The default
+ setting is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxLogSize 1048576
+MaxLogSize 1m
+MaxLogSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxLogSize</CODE> directive controls the maximum size of
+ each log file. Once a log file reaches or exceeds the maximum size it
+ is closed and renamed to<VAR> filename.O</VAR>. This allows you to
+ rotate the logs automatically. The default size is 1048576 bytes (1MB).</P>
+<P>Setting the maximum size to 0 disables log rotation.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxRequestSize">MaxRequestSize</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxRequestSize 10485760
+MaxRequestSize 10m
+MaxRequestSize 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxRequestSize</CODE> directive controls the maximum size
+ of print files, IPP requests, and HTML form data in HTTP POST requests.
+ The default limit is 0 which disables the limit check.</P>
+<P>Also see the identical <A HREF="#LimitRequestBody"><CODE>
+LimitRequestBody</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Order">Order</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Order Allow,Deny
+Order Deny,Allow
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Order</CODE> directive defines the default access control.
+ The following values are supported:</P>
+<UL>
+<LI><CODE>Allow,Deny</CODE> - Allow requests from all systems<I> except</I>
+ for those listed in a <CODE>Deny</CODE> directive.</LI>
+<LI><CODE>Deny,Allow</CODE> - Allow requests only from those listed in
+ an <CODE>Allow</CODE> directive.</LI>
+</UL>
+<P>The <CODE>Order</CODE> directive must appear inside a <A HREF="#Location">
+<CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PageLog">PageLog</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PageLog /var/log/cups/page_log
+PageLog /var/log/cups/page_log-%s
+PageLog syslog
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PageLog</CODE> directive sets the name of the page log
+ file. If the filename is not absolute then it is assumed to be relative
+ to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+ default page log file is<VAR> /var/log/cups/page_log</VAR>.</P>
+<P>The server name can be included in the filename by using <CODE>%s</CODE>
+ in the name.</P>
+<P>The special name &quot;syslog&quot; can be used to send the page information to
+ the system log instead of a plain file.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Port">Port</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Port 631
+Port 80
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Port</CODE> directive specifies a port to listen on.
+ Multiple <CODE>Port</CODE> lines can be specified to listen on multiple
+ ports. The <CODE>Port</CODE> directive is equivalent to &quot;<CODE>Listen
+ *:nnn</CODE>&quot;. The default port is 631.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobFiles">PreserveJobFiles</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PreserveJobFiles On
+PreserveJobFiles Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PreserveJobFiles</CODE> directive controls whether the
+ document files of completed, cancelled, or aborted print jobs are
+ stored on disk.</P>
+<P>A value of <CODE>On</CODE> preserves job files until the
+ administrator purges them with the <CODE>cancel</CODE> command. Jobs
+ can be restarted (and reprinted) as desired until they are purged.</P>
+<P>A value of <CODE>Off</CODE> (the default) removes the job files as
+ soon as each job is completed, cancelled, or aborted.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PreserveJobHistory">PreserveJobHistory</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PreserveJobHistory On
+PreserveJobHistory Off
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PreserveJobHistory</CODE> directive controls whether the
+ history of completed, cancelled, or aborted print jobs is stored on
+ disk.</P>
+<P>A value of <CODE>On</CODE> (the default) preserves job information
+ until the administrator purges it with the <CODE>cancel</CODE> command.</P>
+<P>A value of <CODE>Off</CODE> removes the job information as soon as
+ each job is completed, cancelled, or aborted.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Printcap">Printcap</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Printcap
+Printcap /etc/printcap
+Printcap /etc/printers.conf
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Printcap</CODE> directive controls whether or not a
+ printcap file is automatically generated and updated with a list of
+ available printers. If specified with no value, then no printcap file
+ will be generated. The default is to generate a file named<VAR>
+ /etc/printcap</VAR>.</P>
+<P>When a filename is specified (e.g.<VAR> /etc/printcap</VAR>), the
+ printcap file is written whenever a printer is added or removed. The
+ printcap file can then be used by applications that are hardcoded to
+ look at the printcap file for the available printers.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapFormat">PrintcapFormat</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PrintcapFormat BSD
+PrintcapFormat Solaris
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PrintcapFormat</CODE> directive controls the output format
+ of the printcap file. The default is to generate a BSD printcap file.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="PrintcapGUI">PrintcapGUI</A></H3>
+<HR>
+<H4>Example</H4>
+<UL>
+<PRE>
+PrintcapGUI /usr/bin/glpoptions
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PrintcapGUI</CODE> directive sets the program to use when
+ displaying an option panel from an IRIX application that uses the
+ Impressario print API. The default program is the ESP Print Pro
+ &quot;glpoptions&quot; GUI.</P>
+<P>The program must accept the <CODE>-d</CODE> option to specify a
+ printer and the <CODE>-o</CODE> option to specify one or more options.
+ After allowing the user to select/change options, the program must then
+ write the list of printing options without the <CODE>-o</CODE> to the
+ standard output.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ReloadTimeout">ReloadTimeout</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ReloadTimeout 60
+ReloadTimeout 3600
+ReloadTimeout 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ReloadTimeout</CODE> directive sets how long the scheduler
+ waits for jobs to complete before reloading the server configuration.
+ The default timeout is 60 seconds.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+RemoteRoot remroot
+RemoteRoot root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>RemoteRoot</CODE> directive sets the username for
+ unauthenticated root requests from remote hosts. The default username
+ is<VAR> remroot</VAR>. Setting <CODE>RemoteRoot</CODE> to<VAR> root</VAR>
+ effectively disables this security mechanism.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RequestRoot">RequestRoot</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+RequestRoot /var/spool/cups
+RequestRoot /foo/bar/spool/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>RequestRoot</CODE> directive sets the directory for
+ incoming IPP requests and HTML forms. If an absolute path is not
+ provided then it is assumed to be relative to the <A HREF="#ServerRoot">
+<CODE>ServerRoot</CODE></A> directory. The default request directory is<VAR>
+ /var/spool/cups</VAR>.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="Require">Require</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Require group foo bar
+Require user john mary
+Require valid-user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Require</CODE> directive specifies that authentication is
+ required for the resource. The <CODE>group</CODE> keyword specifies
+ that the authenticated user must be a member of one or more of the
+ named groups that follow.</P>
+<P>The <CODE>user</CODE> keyword specifies that the authenticated user
+ must be one of the named users that follow.</P>
+<P>The <CODE>valid-user</CODE> keyword specifies that any authenticated
+ user may access the resource.</P>
+<P>The default is to do no authentication. This directive must appear
+ inside a <A HREF="#Location"><CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RIPCache">RIPCache</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+RIPCache 8m
+RIPCache 1g
+RIPCache 2048k
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>RIPCache</CODE> directive sets the size of the memory cache
+ used by Raster Image Processor (&quot;RIP&quot;) filters such as <CODE>
+imagetoraster</CODE> and <CODE>pstoraster</CODE>. The size can be
+ suffixed with a &quot;k&quot; for kilobytes, &quot;m&quot; for megabytes, or &quot;g&quot; for
+ gigabytes. The default cache size is &quot;8m&quot;, or 8 megabytes.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RootCertDuration">RootCertDuration</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+RootCertDuration 300
+RootCertDuration 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>RootCertDuration</CODE> directive controls the interval
+ between updates of the root authentication certificate. The default is <CODE>
+300</CODE> seconds which updates the root certificate approximately once
+ every 5 minutes. Set the interval to 0 to disable certificate updates
+ entirely.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="RunAsUser">RunAsUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+RunAsUser Yes
+RunAsUser No
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>RunAsUser</CODE> directive controls whether the scheduler
+ runs as the unpriviledged user account (usually <CODE>lp</CODE>). The
+ default is <CODE>No</CODE> which leaves the scheduler running as the <CODE>
+root</CODE> user.</P>
+<P><B>Note:</B> Running as a non-priviledged user may prevent LPD and
+ locally connected printers from working due to permission problems. The
+ <CODE>lpd</CODE> backend will automatically use a non-priviledged mode
+ that is not 100% compliant with RFC 1179. The <CODE>parallel</CODE>, <CODE>
+serial</CODE>, and <CODE>usb</CODE> backends will need write access to
+ the corresponding device files.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Satisfy">Satisfy</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Satisfy all
+Satisfy any
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Satisfy</CODE> directive specifies whether all conditions
+ must be satisfied to allow access to the resource. If set to <CODE>all</CODE>
+, then all authentication and access control conditions must be satified
+ to allow access.</P>
+<P>Setting <CODE>Satisfy</CODE> to <CODE>any</CODE> allows a user to
+ gain access if the authentication or access control requirements are
+ satisfied. For example, you might require authentication for remote
+ access, but allow local access without authentication.</P>
+<P>The default is <CODE>all</CODE>. This directive must appear inside a <A
+HREF="#Location"><CODE>Location</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerAdmin">ServerAdmin</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerAdmin user@host
+ServerAdmin root@foo.bar.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerAdmin</CODE> directive identifies the email address
+ for the administrator on the system. By default the administrator email
+ address is <CODE>root@server</CODE>, where <CODE>server</CODE> is the
+ server name.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerBin">ServerBin</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerBin /usr/lib/cups
+ServerBin /foo/bar/lib/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerBin</CODE> directive sets the directory for
+ server-run executables. If an absolute path is not provided then it is
+ assumed to be relative to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE>
+</A> directory. The default executable directory is<VAR> /usr/lib/cups</VAR>
+.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerCertificate">ServerCertificate</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerCertificate /etc/cups/ssl/server.crt
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerCertificate</CODE> directive specifies the location
+ of the SSL certificate file used by the server when negotiating
+ encrypted connections. The certificate must not be encrypted (password
+ protected) since the scheduler normally runs in the background and will
+ be unable to ask for a password. The default certificate file is<VAR>
+ /etc/cups/ssl/server.crt</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerKey">ServerKey</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerKey /etc/cups/ssl/server.key
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerKey</CODE> directive specifies the location of the
+ SSL private key file used by the server when negotiating encrypted
+ connections. The default key file is<VAR> /etc/cups/ssl/server.crt</VAR>
+.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerName"></A>ServerName</H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerName foo.domain.com
+ServerName myserver.domain.com
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerName</CODE> directive specifies the hostname that is
+ reported to clients. By default the server name is the hostname.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerRoot">ServerRoot</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerRoot /etc/cups
+ServerRoot /foo/bar/cups
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerRoot</CODE> directive specifies the absolute path to
+ the server configuration and state files. It is also used to resolve
+ relative paths in the<VAR> cupsd.conf</VAR> file. The default server
+ directory is<VAR> /etc/cups</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerTokens">ServerTokens</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerTokens None
+ServerTokens ProductOnly
+ServerTokens Major
+ServerTokens Minor
+ServerTokens Minimal
+ServerTokens OS
+ServerTokens Full
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerTokens</CODE> directive specifies the information
+ that is included in the Server header of HTTP responses. The default
+ value is <TT>Minor</TT> which generates &quot;CUPS/1.1&quot;.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLListen">SSLListen</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+SSLListen 127.0.0.1:443
+SSLListen 192.0.2.1:443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>SSLListen</CODE> directive specifies a network address and
+ port to listen for secure connections. Multiple <CODE>SSLListen</CODE>
+ directives can be provided to listen on multiple addresses.</P>
+<P>The <CODE>SSLListen</CODE> directive is similar to the <A HREF="#SSLPort">
+<CODE>SSLPort</CODE></A> directive but allows you to restrict access to
+ specific interfaces or networks.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SSLPort">SSLPort</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+SSLPort 443
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>SSLPort</CODE> directive specifies a port to listen on for
+ secure connections. Multiple <CODE>SSLPort</CODE> lines can be
+ specified to listen on multiple ports.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="SystemGroup">SystemGroup</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+SystemGroup sys
+SystemGroup system
+SystemGroup root
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>SystemGroup</CODE> directive specifies the system
+ administration group for <CODE>System</CODE> authentication. More
+ information can be found later in this chapter in <A HREF="#PRINTING_SECURITY">
+&quot;Printing System Security&quot;</A>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="TempDir">TempDir</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+TempDir /var/tmp
+TempDir /foo/bar/tmp
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>TempDir</CODE> directive specifies an absolute path for the
+ directory to use for temporary files. The default directory is<VAR>
+ /var/tmp</VAR>.</P>
+<P>Temporary directories must be world-writable and should have the
+ &quot;sticky&quot; permission bit enabled so that other users cannot delete
+ filter temporary files. The following commands will create an
+ appropriate temporary directory called<VAR> /foo/bar/tmp</VAR>:</P>
+<UL>
+<PRE>
+<B>mkdir /foo/bar/tmp ENTER</B>
+<B>chmod a+rwxt /foo/bar/tmp ENTER</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Timeout">Timeout</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Timeout 300
+Timeout 90
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Timeout</CODE> directive controls the amount of time to
+ wait before an active HTTP or IPP request times out. The default
+ timeout is 300 seconds.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="User">User</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+User lp
+User guest
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>User</CODE> directive specifies the UNIX user that filter
+ and CGI programs run as. The default user is <CODE>lp</CODE>.</P>
+<H2><A NAME="7_5">Changing the Client Configuration</A></H2>
+<P>The CUPS client application (<CODE>lp</CODE>, <CODE>lpr</CODE>, and
+ so forth) use the<VAR> /etc/cups/client.conf</VAR> file for default
+ settings. The client application also look in the user's home directory
+ for a file called<VAR> .cupsrc</VAR>. Each directive is listed on a
+ line by itself followed by its value. Comments are introduced using the
+ number sign (&quot;#&quot;) character at the beginning of a line.</P>
+<P>Since the client configuration file consists of plain text, you can
+ use your favorite text editor to make changes to it.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="7_6">Client Directives</A></H2>
+<P>The<VAR> client.conf</VAR> file contains two directives that
+ determine how the client behaves:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#Encryption"><CODE>Encryption</CODE></A></LI>
+<LI><A HREF="#ServerName"><CODE>ServerName</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+Encryption Always
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Encryption</CODE> directive specifies the default
+ encryption settings for the client. The default setting is<VAR>
+ IfRequested</VAR>.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ServerName">ServerName</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+ServerName foo.bar.com
+ServerName 11.22.33.44
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>ServerName</CODE> directive specifies sets the remote
+ server that is to be used for all client operations. That is, it
+ redirects all client requests to the remote server. The default is to
+ use the local server (&quot;<VAR>localhost</VAR>&quot;).
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="7_7">Changing the Printer Configuration</A></H2>
+<P>The CUPS scheduler (cupsd) uses the<VAR> /etc/cups/printers.conf</VAR>
+ file to store the list of available printers. This file contains only
+ locally defined printers, but not remote printers that are created
+ automatically. Each directive is listed on a line by itself followed by
+ its value. Comments are introduced using the number sign (&quot;#&quot;)
+ character at the beginning of a line.</P>
+<P>Since the printer configuration file consists of plain text, you can
+ use your favorite text editor to make changes to it.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="7_8">Printer Directives</A></H2>
+<P>The<VAR> printers.conf</VAR> file contains many directives that
+ determine how the printer behaves:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#Accepting"><CODE>Accepting</CODE></A></LI>
+<LI><A HREF="#AllowUser"><CODE>AllowUser</CODE></A></LI>
+<LI><A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A></LI>
+<LI><A HREF="#DenyUser"><CODE>DenyUser</CODE></A></LI>
+<LI><A HREF="#DeviceURI"><CODE>DeviceURI</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#Info"><CODE>Info</CODE></A></LI>
+<LI><A HREF="#JobSheets"><CODE>JobSheets</CODE></A></LI>
+<LI><A HREF="#KLimit"><CODE>KLimit</CODE></A></LI>
+<LI><A HREF="#PrinterLocation"><CODE>Location</CODE></A></LI>
+<LI><A HREF="#PageLimit"><CODE>PageLimit</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#Printer"><CODE>Printer</CODE></A></LI>
+<LI><A HREF="#QuotaPeriod"><CODE>QuotaPeriod</CODE></A></LI>
+<LI><A HREF="#State"><CODE>State</CODE></A></LI>
+<LI><A HREF="#StateMessage"><CODE>StateMessage</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Accepting">Accepting</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Accepting yes
+
+Accepting no
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Accepting</CODE> directive defines the initial Boolean
+ value for the<VAR> printer-is-accepting-job</VAR> attribute which can
+ be set by the <CODE>accept</CODE> and <CODE>reject</CODE> commands.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="AllowUser">AllowUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AllowUser foo_user
+AllowUser bar_user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AllowUser</CODE> directive adds a username to the<VAR>
+ requesting-user-name-allowed</VAR> attribute which can be set by the <CODE>
+lpadmin -u</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="DefaultPrinter">DefaultPrinter</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;DefaultPrinter name/&gt;
+...
+&lt;/Printer&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DefaultPrinter</CODE> directive begins a printer definition
+ for the default server destination. It can be added by the <CODE>
+lpadmin</CODE> command or if already defined, set as default by the <CODE>
+lpoptions -d</CODE> command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DenyUser">DenyUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DenyUser foo_user
+DenyUser bar_user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DenyUser</CODE> directive adds a username to the<VAR>
+ requesting-user-name-allowed</VAR> attribute which can be set by the <CODE>
+lpadmin -u</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DeviceURI">DeviceURI</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DeviceURI socket://foo.bar.com:9100
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DeviceURI</CODE> directive defines the value of the<VAR>
+ device-uri-attribute</VAR> attribute which can be set by the <CODE>
+lpadmin -v</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Info">Info</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Info My Printer
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Info</CODE> directive defines the string for the<VAR>
+ printer-info</VAR> attribute which can be set by the <CODE>lpadmin -D</CODE>
+ command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="JobSheets">JobSheets</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+JobSheets none,standard
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>JobSheets</CODE> directive specifies the default banner
+ pages to print before and after a print job. In the above example, only
+ a<VAR> standard</VAR> banner will print after each job.</P>
+<P>The <CODE>lpoptions -o job-sheets=</CODE> command can be used to set
+ banners. For example, the following command would produce the same
+ results of a<VAR> standard</VAR> banner at the end of each print job
+ for the default printer.</P>
+<UL><B> lpoptions -o job-sheets=none,standard</B></UL>
+<P>If only one banner file is specified, it will be printed before the
+ files in the job. If a second banner file is specified, it is printed
+ after the files in the job.</P>
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot;
+ label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top
+ and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and
+ bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot;
+ label at the top and bottom.</LI>
+</UL>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="KLimit">KLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+KLimit 1234
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>KLimit</CODE> directive defines the value of the<VAR>
+ job-k-limit</VAR> attribute which can be set by the <CODE>lpadmin -o
+ job-k-limit=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="PrinterLocation">Location</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Location Building 3321
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Location</CODE> directive defines the string for the<VAR>
+ printer-location</VAR> attribute which can be set by the <CODE>lpadmin
+ -L</CODE> command.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Do not confuse this <CODE>Location</CODE> directive with the one in
+ cupsd.conf. They are completely different.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="PageLimit">PageLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PageLimit 1234
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PageLimit</CODE> directive defines the value of the<VAR>
+ job-page-limit</VAR> attribute which can be set by the <CODE>lpadmin -o
+ job-page-limit=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="Printer">Printer</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;Printer name/&gt;
+...
+&lt;/Printer&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Printer</CODE> directive begins a printer definition. It
+ can be added by the <CODE>lpadmin</CODE> command.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="QuotaPeriod">QuotaPeriod</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+QuotaPeriod 604800
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>QuotaPeriod</CODE> directive defines the value of the<VAR>
+ job-quota-period</VAR> attribute which can be set by the <CODE>lpadmin
+ -o job-quota-period=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="State">State</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+State stopped
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>State</CODE> directive defines the initial value of the<VAR>
+ printer-state</VAR> attribute. The strings<VAR> idle</VAR> and<VAR>
+ stopped</VAR> correspond to the IPP enumeration values.</P>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="StateMessage">StateMessage</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+StateMessage Ready to print.
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>StateMessage</CODE> directive defines the initial string
+ for the<VAR> printer-state-message</VAR> attribute. The following are
+ some example messages:</P>
+<UL>
+<LI>Connected to<VAR> host_name</VAR>...</LI>
+<LI>Connecting to<VAR> printer_queue</VAR> on port<VAR> port_number</VAR>
+...</LI>
+<LI>Network host<VAR> host_name</VAR> is busy; will retry in 30
+ seconds...</LI>
+<LI>Printer busy; will retry in 10 seconds...</LI>
+<LI>Printer is busy; retrying print job...</LI>
+<LI>Print file accepted - job ID<VAR> id_number</VAR>.</LI>
+<LI>Ready to print.</LI>
+<LI>Waiting for job to complete</LI>
+</UL>
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE>
+</A> or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ directive.</P>
+
+<!-- NEW PAGE -->
+<H2><A NAME="7_9">Changing the Classes Configuration</A></H2>
+<P>The CUPS scheduler (cupsd) uses the<VAR> /etc/cups/classes.conf</VAR>
+ file to store the list of available classes. This file contains only
+ locally defined classes, but not remote or implicit classes that are
+ created automatically. Each directive is listed on a line by itself
+ followed by its value. Comments are introduced using the number sign
+ (&quot;#&quot;) character at the beginning of a line.</P>
+<P>Since the classes configuration file consists of plain text, you can
+ use your favorite text editor to make changes to it.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="7_10">Classes Directives</A></H2>
+<P>The<VAR> classes.conf</VAR> file contains many directives that
+ determine how the classes behaves:</P>
+<UL>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
+<TR><TD VALIGN="TOP">
+<LI><A HREF="#ClassAccepting"><CODE>Accepting</CODE></A></LI>
+<LI><A HREF="#ClassAllowUser"><CODE>AllowUser</CODE></A></LI>
+<LI><A HREF="#Class"><CODE>Class</CODE></A></LI>
+<LI><A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A></LI>
+<LI><A HREF="#ClassDenyUser"><CODE>DenyUser</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#ClassInfo"><CODE>Info</CODE></A></LI>
+<LI><A HREF="#ClassJobSheets"><CODE>JobSheets</CODE></A></LI>
+<LI><A HREF="#ClassKLimit"><CODE>KLimit</CODE></A></LI>
+<LI><A HREF="#ClassLocation"><CODE>Location</CODE></A></LI>
+<LI><A HREF="#ClassPageLimit"><CODE>PageLimit</CODE></A></LI>
+</TD><TD VALIGN="TOP"> &nbsp;&nbsp;&nbsp;</TD><TD VALIGN="TOP">
+<LI><A HREF="#ClassPrinter"><CODE>Printer</CODE></A></LI>
+<LI><A HREF="#ClassQuotaPeriod"><CODE>QuotaPeriod</CODE></A></LI>
+<LI><A HREF="#ClassState"><CODE>State</CODE></A></LI>
+<LI><A HREF="#ClassStateMessage"><CODE>StateMessage</CODE></A></LI>
+</TD></TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassAccepting">Accepting</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Accepting yes
+
+Accepting no
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Accepting</CODE> directive defines the initial Boolean
+ value for the<VAR> printer-is-accepting-job</VAR> attribute which can
+ be set by the <CODE>accept</CODE> and <CODE>reject</CODE> commands.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassAllowUser">AllowUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+AllowUser foo_user
+AllowUser bar_user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>AllowUser</CODE> directive adds a username to the<VAR>
+ requesting-user-name-allowed</VAR> attribute which can be set by the <CODE>
+lpadmin -u</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Class">Class</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;Class name/&gt;
+...
+&lt;/Class&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Class</CODE> directive begins a class definition. It can be
+ added by the <CODE>lpadmin -c</CODE> command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DefaultClass">DefaultClass</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+&lt;DefaultClass name/&gt;
+...
+&lt;/DefaultClass&gt;
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DefaultClass</CODE> directive begins a class definition for
+ the default server destination. It can be added by the <CODE>lpadmin -c</CODE>
+ command or if already defined, set as default by the <CODE>lpoptions -d</CODE>
+ command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassDenyUser">DenyUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+DenyUser foo_user
+DenyUser bar_user
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>DenyUser</CODE> directive adds a username to the<VAR>
+ requesting-user-name-allowed</VAR> attribute which can be set by the <CODE>
+lpadmin -u</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassInfo">Info</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Info My Printer
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Info</CODE> directive defines the string for the<VAR>
+ printer-info</VAR> attribute which can be set by the <CODE>lpadmin -D</CODE>
+ command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="ClassJobSheets">JobSheets</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+JobSheets none,standard
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>JobSheets</CODE> directive specifies the default banner
+ pages to print before and after a print job. In the above example, only
+ a<VAR> standard</VAR> banner will print after each job.</P>
+<P>The <CODE>lpoptions -o job-sheets=</CODE> command can be used to set
+ banners. For example, the following command would produce the same
+ results of a<VAR> standard</VAR> banner at the end of each print job
+ for the default class.</P>
+<UL><B> lpoptions -o job-sheets=none,standard</B></UL>
+<P>If only one banner file is specified, it will be printed before the
+ files in the job. If a second banner file is specified, it is printed
+ after the files in the job.</P>
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot;
+ label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top
+ and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and
+ bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot;
+ label at the top and bottom.</LI>
+</UL>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassKLimit">KLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+KLimit 1234
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>KLimit</CODE> directive defines the value of the<VAR>
+ job-k-limit</VAR> attribute which can be set by the <CODE>lpadmin -o
+ job-k-limit=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="ClassLocation">Location</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Location Building 3321
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Location</CODE> directive defines the string for the<VAR>
+ printer-location</VAR> attribute which can be set by the <CODE>lpadmin
+ -L</CODE> command.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Do not confuse this <CODE>Location</CODE> directive with the one in
+ cupsd.conf. They are completely different.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassPageLimit">PageLimit</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+PageLimit 1234
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>PageLimit</CODE> directive defines the value of the<VAR>
+ job-page-limit</VAR> attribute which can be set by the <CODE>lpadmin -o
+ job-page-limit=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassPrinter">Printer</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Printer foo
+Printer bar
+Printer foo@bar
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Printer</CODE> directive adds a printer to the class. It
+ can be added by the <CODE>lpadmin -c</CODE> command.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Do not confuse this <CODE>Printer</CODE> directive with the one in
+ printers.conf. They are completely different.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassQuotaPeriod">QuotaPeriod</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+QuotaPeriod 604800
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>QuotaPeriod</CODE> directive defines the value of the<VAR>
+ job-quota-period</VAR> attribute which can be set by the <CODE>lpadmin
+ -o job-quota-period=</CODE> command.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="ClassState">State</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+State stopped
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>State</CODE> directive defines the initial value of the<VAR>
+ printer-state</VAR> attribute. The strings<VAR> idle</VAR> and<VAR>
+ stopped</VAR> correspond to the IPP enumeration values.</P>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+<!-- NEED 6in -->
+</P>
+<H3><A NAME="ClassStateMessage">StateMessage</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+StateMessage Ready to print.
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>StateMessage</CODE> directive defines the initial string
+ for the<VAR> printer-state-message</VAR> attribute. The following are
+ some example messages:</P>
+<UL>
+<LI>Connected to<VAR> host_name</VAR>...</LI>
+<LI>Connecting to<VAR> class_queue</VAR> on port<VAR> port_number</VAR>
+...</LI>
+<LI>Network host<VAR> host_name</VAR> is busy; will retry in 30
+ seconds...</LI>
+<LI>Printer busy; will retry in 10 seconds...</LI>
+<LI>Printer is busy; retrying print job...</LI>
+<LI>Print file accepted - job ID<VAR> id_number</VAR>.</LI>
+<LI>Ready to print.</LI>
+<LI>Waiting for job to complete</LI>
+</UL>
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE>
+</A> or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.</P>
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTING_SECURITY">Printing System Security</A></H2>
+<P>CUPS provides support for address, certificate, and password (Basic
+ and Digest) based authentication and access control. Certificate and
+ password authentication provide ways to limit access to individual
+ people or groups.</P>
+<P>Address based access control allows you to limit access to specific
+ systems, networks, or domains. While this does not provide
+ authentication, it does allow you to limit the potential users of your
+ system efficiently.</P>
+<P>CUPS maintains a list of locations that have access control and/or
+ authentication enabled. Locations are specified using the <A HREF="#Location">
+<CODE>Location</CODE></A> directive:</P>
+<UL>
+<PRE>
+&lt;Location /resource&gt;
+<A HREF="#AuthClass">AuthClass</A> ...
+<A HREF="#AuthGroupName">AuthGroupName</A> ...
+<A HREF="#AuthType">AuthType</A> ...
+
+<A HREF="#Order">Order</A> ...
+<A HREF="#Allow">Allow</A> from ...
+<A HREF="#Deny">Deny</A> from ...
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>Locations generally follow the directory structure of the <A HREF="#DocumentRoot">
+<CODE>DocumentRoot</CODE></A> directory, however CUPS does have several
+ virtual locations for administration, classes, jobs, and printers:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH>Location</TH><TH>Description</TH></TR>
+<TR><TD>/admin</TD><TD>The path for all administration operations.</TD></TR>
+<TR><TD>/classes</TD><TD>The path for all classes.</TD></TR>
+<TR><TD>/classes/name</TD><TD>The resource for class <CODE>name</CODE>.</TD>
+</TR>
+<TR><TD>/jobs</TD><TD>The path for all jobs.</TD></TR>
+<TR><TD>/jobs/id</TD><TD>The resource for job <CODE>id</CODE>.</TD></TR>
+<TR><TD>/printers</TD><TD>The path for all printers.</TD></TR>
+<TR><TD>/printers/name</TD><TD>The path for printer <CODE>name</CODE>.</TD>
+</TR>
+<TR><TD>/printers/name.ppd</TD><TD>The PPD file path for printer <CODE>
+name</CODE>.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="CERTIFICATES">Authentication Using Certificates</A></H3>
+<P>CUPS supports a local certificate-based authentication scheme that
+ can be used in place of <CODE>Basic</CODE> or <CODE>Digest</CODE>
+ authentication by clients connecting through the <CODE>localhost</CODE>
+ interface. Certificate authentication is not supported or allowed from
+ clients on any other interface.</P>
+<P>Certificates are 128-bit random numbers that refer to an internal
+ authentication record in the server. A client connecting via the <CODE>
+localhost</CODE> interface sends a request with an authorization header
+ of:</P>
+<UL>
+<PRE>
+Authorization: Local 0123456789ABCDEF0123456789ABCDEF
+</PRE>
+</UL>
+<P>The server then looks up the local certificate and authenticates
+ using the username associated with it.</P>
+<P>Certificates are generated by the server automatically and stored in
+ the<VAR> /etc/cups/certs</VAR> directory using the process ID of the
+ CGI program started by the server. Certificate files are only readable
+ by the <A HREF="#User"><CODE>User</CODE></A> and <A HREF="#Group"><CODE>
+Group</CODE></A> defined in the<VAR> cupsd.conf</VAR> file. When the CGI
+ program ends the certificate is removed and invalidated automatically.</P>
+<P>The special file<VAR> /etc/cups/certs/0</VAR> defines the<I> root
+ certificate</I> which can be used by any client running as the
+ super-user or another user that is part of the group defined by the <A HREF="#SystemGroup">
+<CODE>SystemGroup</CODE></A> directive. The root certificate is
+ automatically regenerated every 5 minutes.</P>
+<H3><A NAME="7_11_2">Using Basic Authentication</A></H3>
+<P>Basic authentication uses UNIX users and passwords to authenticate
+ access to resources such as printers and classes, and to limit access
+ to administrative functions.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Basic authentication sends the username and password Base64 encoded
+ from the client to the server, so it offers no protection against
+ eavesdropping. This means that a malicious user can monitor network
+ packets and discover valid users and passwords that could result in a
+ serious compromise in network security. Use Basic authentication with
+ extreme care.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<P>The CUPS implementation of Basic authentication does not allow access
+ through user accounts without a password. If you try to authenticate
+ using an account without a password, your access will be immediately
+ blocked.</P>
+<P>Once a valid username and password is authenticated by CUPS, any
+ additional group membership requirements are checked.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>The root user is considered by CUPS to be a member of every group.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 1in -->
+<P>Use the <CODE>AuthType</CODE> directive to enable Basic
+ authentication:</P>
+<UL>
+<PRE>
+AuthType Basic
+</PRE>
+</UL>
+
+<!-- NEED 7in -->
+<H3><A NAME="7_11_3">Using Digest Authentication</A></H3>
+<P>Digest authentication uses users and passwords defined in the<VAR>
+ /etc/cups/passwd.md5</VAR> file to authenticate access to resources
+ such as printers and classes, and to limit access to administrative
+ functions.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Unlike Basic authentication, Digest passes the MD5 sum (basically a
+ complicated checksum) of the username and password instead of the
+ strings themselves. Also, Digest authentication does not use the UNIX
+ password file, so if an attacker does discover the original password it
+ is less likely to result in a serious security problem so long as you
+ use a different UNIX password than the corresponding Digest password.</P>
+<P>The current CUPS implementation of Digest authentication uses the
+ client's hostname or IP address for the &quot;nonce&quot; value. The nonce value
+ is an additional string added to the username and password to make
+ guessing the password more difficult. The server checks that the nonce
+ value matches the client's hostname or address and rejects the MD5 sum
+ if it doesn't. Future versions of CUPS will support Digest &quot;session&quot;
+ authentication which adds the request data to the MD5 sum, providing
+ even better authentication and security.</P>
+<P>Digest authentication does not guarantee that an attacker cannot gain
+ unauthorized access, but it is safer than Basic authentication and
+ should be used in place of Basic authentication whenever possible.<B>
+ Support for Digest authentication in web browsers is not yet
+ universally available.</B></P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 2in -->
+<P>The <CODE>lppasswd(1)</CODE> command is used to add, change, or
+ remove accounts from the<VAR> passwd.md5</VAR> file. To add a user to
+ the default system group, type:</P>
+<UL>
+<PRE>
+<B>lppasswd -a user ENTER</B>
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Once added, a user can change his/her password by typing:</P>
+<UL>
+<PRE>
+<B>lppasswd ENTER</B>
+Old password: <B>(password) ENTER</B> [password is not echoed]
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>To remove a user from the password file, type:</P>
+<UL>
+<PRE>
+<B>lppasswd -x user ENTER</B>
+</PRE>
+</UL>
+<P>Once a valid username and password is authenticated by CUPS, any
+ additional group membership requirements are checked.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>The root user is considered by CUPS to be a member of every group.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<P>Use the <CODE>AuthType</CODE> directive to enable Digest
+ authentication:</P>
+<UL>
+<PRE>
+AuthType Digest
+</PRE>
+</UL>
+<H3><A NAME="7_11_4">System and Group Authentication</A></H3>
+<P>The <A HREF="#AuthClass"><CODE>AuthClass</CODE></A> directive
+ controls the level of authentication to perform. <CODE>System</CODE>
+ and <CODE>Group</CODE> authentication extend the normal user-based
+ authentication to require membership in a UNIX group. For <CODE>System</CODE>
+ authentication each user must belong to the <CODE>sys</CODE>, <CODE>
+system</CODE>, or <CODE>root</CODE> group; the actual group depends on
+ the operating system.</P>
+<P>For <CODE>Group</CODE> authentication each user must belong to the
+ group named by the <A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>
+ directive:</P>
+<UL>
+<PRE>
+&lt;Location /path&gt;
+AuthType Digest
+AuthClass Group
+AuthGroupName mygroup
+&lt;/Location&gt;
+</PRE>
+</UL>
+<P>The named group must be a valid UNIX user group, usually defined in
+ the<VAR> /etc/group</VAR> or<VAR> /etc/netgroup</VAR> files.
+ Additionally, when using Digest authentication you need to create user
+ accounts with the named group:</P>
+<UL>
+<PRE>
+<B>lppasswd -g mygroup -a user ENTER</B>
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTER_ACCOUNTING">Printer Accounting</A></H2>
+<P>CUPS maintains a log of all accesses, errors, and pages that are
+ printed. The log files are normally stored in the<VAR> /var/log/cups</VAR>
+ directory. You can change this by editing the<VAR> /etc/cups/cupsd.conf</VAR>
+ configuration file.</P>
+<H3><A NAME="7_12_1">The access_log File</A></H3>
+<P>The<VAR> access_log</VAR> file lists each HTTP resource that is
+ accessed by a web browser or CUPS/IPP client. Each line is in the
+ so-called &quot;Common Log Format&quot; used by many web servers and web
+ reporting tools:</P>
+<UL>
+<PRE>
+host group user date-time \&quot;method resource version\&quot; status bytes
+
+127.0.0.1 - - [20/May/1999:19:20:29 +0000] &quot;POST /admin/ HTTP/1.1&quot; 401 0
+127.0.0.1 - mike [20/May/1999:19:20:31 +0000] &quot;POST /admin/ HTTP/1.1&quot; 200 0
+</PRE>
+</UL>
+<P>The<I> host</I> field will normally only be an IP address unless you
+ have enabled the <A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE>
+</A> directive in the<VAR> cupsd.conf</VAR> file.</P>
+<P>The<I> group</I> field always contains &quot;-&quot; in CUPS.</P>
+<P>The<I> user</I> field is the authenticated username of the requesting
+ user. If no username and password is supplied for the request then this
+ field contains &quot;-&quot;.</P>
+<P>The<I> date-time</I> field is the date and time of the request in
+ local time and is in the format:</P>
+<UL>
+<PRE>
+[DD/MON/YYYY:HH:MM:SS +ZZZZ]
+</PRE>
+</UL>
+<P>where<I> ZZZZ</I> is the timezone offset in hours and minutes from
+ coordinated universal time (UTC). UTC may sometimes be referred to as
+ GMT or ZULU on legacy systems.</P>
+<P>The<I> method</I> field is the HTTP method used (&quot;GET&quot;, &quot;PUT&quot;,
+ &quot;POST&quot;, etc.)</P>
+<P>The<I> resource</I> field is the filename of the requested resource.</P>
+<P>The<I> version</I> field is the HTTP specification version used by
+ the client. For CUPS clients this will always be &quot;HTTP/1.1&quot;.</P>
+<P>The<I> status</I> field contains the HTTP result status of the
+ request. Usually it is &quot;200&quot;, but other HTTP status codes are possible.
+ For example, 401 is the &quot;unauthorized access&quot; status in the example
+ above.</P>
+<P>The<I> bytes</I> field contains the number of bytes in the request.
+ For POST requests the<I> bytes</I> field contains the number of bytes
+ that was received from the client.</P>
+<H3><A NAME="7_12_2">The error_log File</A></H3>
+<P>The<VAR> error_log</VAR> file lists messages from the scheduler
+ (errors, warnings, etc.):</P>
+<UL>
+<PRE>
+level date-time message
+
+I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
+</PRE>
+</UL>
+<P>The<I> level</I> field contains the type of message:</P>
+<UL>
+<LI><CODE>E</CODE> - An error occurred.</LI>
+<LI><CODE>W</CODE> - The server was unable to perform some action.</LI>
+<LI><CODE>I</CODE> - Informational message.</LI>
+<LI><CODE>D</CODE> - Debugging message.</LI>
+</UL>
+<P>The<I> date-time</I> field contains the date and time of when the
+ page started printing. The format of this field is identical to the<I>
+ data-time</I> field in the<VAR> access_log</VAR> file.</P>
+<P>The<I> message</I> fields contains a free-form textual message.</P>
+<H3><A NAME="7_12_3">The page_log File</A></H3>
+<P>The<VAR> page_log</VAR> file lists each page that is sent to a
+ printer. Each line contains the following information:</P>
+<UL>
+<PRE>
+printer user job-id date-time page-number num-copies job-billing hostname
+
+DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123 localhost
+</PRE>
+</UL>
+<P>The<I> printer</I> field contains the name of the printer that
+ printed the page. If you send a job to a printer class, this field will
+ contain the name of the printer that was assigned the job.</P>
+<P>The<I> user</I> field contains the name of the user (the IPP <CODE>
+requesting-user-name</CODE> attribute) that submitted this file for
+ printing.</P>
+<P>The<I> job-id</I> field contains the job number of the page being
+ printed. Job numbers are reset to 1 whenever the CUPS server is
+ started, so don't depend on this number being unique!</P>
+<P>The<I> date-time</I> field contains the date and time of when the
+ page started printing. The format of this field is identical to the<I>
+ data-time</I> field in the<VAR> access_log</VAR> file.</P>
+<P>The<I> page-number</I> and<I> num-pages</I> fields contain the page
+ number and number of copies being printed of that page. For printer
+ that can not produce copies on their own, the<I> num-pages</I> field
+ will always be 1.</P>
+<P>The<I> job-billing</I> field contains a copy of the <CODE>job-billing</CODE>
+ attribute provided with the IPP <CODE>create-job</CODE> or <CODE>
+print-job</CODE> requests or &quot;-&quot; if none was provided.</P>
+<P>The<I> hostname</I> field contains the name of the host (the IPP <CODE>
+job-originating-host-name</CODE> attribute) that originated the print
+ job.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="FILE_TYPING_FILTERING">File Typing and Filtering</A></H2>
+<P>CUPS provides a MIME-based file typing and filtering mechanism to
+ convert files to a printable format for each printer. On startup the
+ CUPS server reads MIME database files from the<VAR> /etc/cups</VAR>
+ directory (or a directory specified by the <A HREF="#ServerRoot"><CODE>
+ServerRoot</CODE></A> directive) to build a file type and conversion
+ database in memory. These database files are plain ASCII text and can
+ be edited with your favorite text editor.</P>
+<P>The<VAR> mime.types</VAR> and<VAR> mime.convs</VAR> files define the
+ standard file types and filters that are available on the system.</P>
+<H3><A NAME="7_13_1">mime.types</A></H3>
+<P>The<VAR> mime.types</VAR> file defines the known file types. Each
+ line of the file starts with the MIME type and may be followed by one
+ or more file type recognition rules. For example, the <CODE>text/html</CODE>
+ file type is defined as:</P>
+<UL>
+<PRE>
+text/html html htm \
+ printable(0,1024) + \
+ (string(0,&quot;&lt;HTML&gt;&quot;) string(0,&quot;&lt;!DOCTYPE&quot;))
+</PRE>
+</UL>
+<P>The first two rules say that any file with an extension of<VAR> .html</VAR>
+ or<VAR> .htm</VAR> is a HTML file. The third rule says that any file
+ whose first 1024 characters are printable text and starts with the
+ strings <CODE>&lt;HTML&gt;</CODE> or <CODE>&lt;!DOCTYPE</CODE> is a HTML file as
+ well.</P>
+<P>The first two rules deal solely with the name of the file being
+ typed. This is useful when the original filename is known, however for
+ print files the server doesn't have a filename to work with. The third
+ rule takes care of this possibility and automatically figures out the
+ file type based upon the contents of the file instead.</P>
+<P>The available tests are:</P>
+<UL>
+<LI><CODE>( expr )</CODE> - Parenthesis for expression grouping</LI>
+<LI><CODE>+</CODE> - Logical AND</LI>
+<LI><CODE>,</CODE> or whitespace - Logical OR</LI>
+<LI><CODE>!</CODE> - Logical NOT</LI>
+<LI><CODE>match(&quot;pattern&quot;)</CODE> - Pattern match on filename</LI>
+<LI><CODE>extension</CODE> - Pattern match on &quot;*.extension&quot;</LI>
+<LI><CODE>ascii(offset,length)</CODE> - True if bytes are valid
+ printable ASCII (CR, NL, TAB, BS, 32-126)</LI>
+<LI><CODE>printable(offset,length)</CODE> - True if bytes are printable
+ 8-bit chars (CR, NL, TAB, BS, 32-126, 160-254)</LI>
+<LI><CODE>string(offset,&quot;string&quot;)</CODE> - True if bytes are identical
+ to string</LI>
+<LI><CODE>istring(offset,&quot;string&quot;)</CODE> - True if bytes are identical
+ to string after reducing both strings to lowercase</LI>
+<LI><CODE>contains(offset,range,&quot;string&quot;)</CODE> - True if the range of
+ bytes contains the string</LI>
+<LI><CODE>char(offset,value)</CODE> - True if byte is identical</LI>
+<LI><CODE>short(offset,value)</CODE> - True if 16-bit integer is
+ identical (network or &quot;big-endian&quot; byte order)</LI>
+<LI><CODE>int(offset,value)</CODE> - True if 32-bit integer is identical
+ (network or &quot;big-endian&quot; byte order)</LI>
+<LI><CODE>locale(&quot;string&quot;)</CODE> - True if current locale matches
+ string</LI>
+</UL>
+<P>All numeric values can be in decimal (123), octal (0123), or
+ hexadecimal (0x123) as desired.
+<!-- NEED 2.5in -->
+</P>
+<P>Strings can be in quotes, all by themselves, as a string of
+ hexadecimal values, or some combination:</P>
+<UL>
+<PRE>
+&quot;string&quot;
+'string'
+string
+&lt;737472696e67&gt;
+&lt;7374&gt;ring
+</PRE>
+</UL>
+<P>As shown in the <CODE>text/html</CODE> example, rules can continue on
+ multiple lines using the backslash (\) character. A more complex
+ example is the <CODE>image/jpeg</CODE> rules:</P>
+<UL>
+<PRE>
+image/jpeg jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+</PRE>
+</UL>
+<P>This rule states that any file with an extension of<VAR> .jpeg</VAR>,<VAR>
+ .jpg</VAR>, or<VAR> .jpe</VAR> is a JPEG file. In addition, any file
+ starting with the hexadecimal string <CODE>&lt;FFD8FF&gt;</CODE> (JPEG
+ Start-Of-Image) followed by a character between and including <CODE>
+0xe0</CODE> and <CODE>0xef</CODE> (JPEG APPn markers) is also a JPEG
+ file.</P>
+<H3><A NAME="7_13_2">mime.convs</A></H3>
+<P>The<VAR> mime.convs</VAR> file defines all of the filter programs
+ that are known to the system. Each line consists of:</P>
+<UL>
+<PRE>
+source destination cost program
+
+text/plain application/postscript 50 texttops
+application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
+image/* application/vnd.cups-postscript 50 imagetops
+image/* application/vnd.cups-raster 50 imagetoraster
+</PRE>
+</UL>
+<P>The<I> source</I> field is a MIME type, optionally using a wildcard
+ for the super-type or sub-type (e.g. &quot;text/plain&quot;, &quot;image/*&quot;,
+ &quot;*/postscript&quot;).</P>
+<P>The<I> destination</I> field is a MIME type defined in the<VAR>
+ mime.types</VAR> file.</P>
+<P>The<I> cost</I> field defines a relative cost for the filtering
+ operation from 1 to 100. The cost is used to choose between two
+ different sets of filters when converting a file. For example, to
+ convert from <CODE>image/jpeg</CODE> to <CODE>
+application/vnd.cups-raster</CODE>, you could use the <CODE>imagetops</CODE>
+ and <CODE>pstoraster</CODE> filters for a total cost of 100, or the <CODE>
+imagetoraster</CODE> filter for a total cost of 50.</P>
+<P>The<I> program</I> field defines the filter program to run; the
+ special program &quot;-&quot; can be used to make two file types equivalent. The
+ program must accept the standard filter arguments and environment
+ variables described in the CUPS Interface Design Description and CUPS
+ Software Programmers Manual:</P>
+<UL>
+<PRE>
+program job user title options [filename]
+</PRE>
+</UL>
+<P>If specified, the<I> filename</I> argument defines a file to read
+ when filtering, otherwise the filter must read from the standard input.
+ All filtered output must go to the standard output.
+<!-- NEED 4in -->
+</P>
+<H3><A NAME="7_13_3">Adding Filetypes and Filters</A></H3>
+<P>Adding a new file type or filter is fairly straight-forward. Rather
+ than adding the new type and filter to the<VAR> mime.types</VAR> and<VAR>
+ mime.convs</VAR> files which are overwritten when you upgrade to a new
+ version of CUPS, you simple need to create new files with<VAR> .types</VAR>
+ and<VAR> .convs</VAR> extensions in the<VAR> /etc/cups</VAR> directory.
+ We recommend that you use the product or format name, e.g.:</P>
+<UL>
+<PRE>
+myproduct.types
+myproduct.convs
+</PRE>
+</UL>
+<P>If you are providing a filter for a common file format or printer,
+ add the company or author name:</P>
+<UL>
+<PRE>
+acme-msword.types
+acme-msword.convs
+</PRE>
+</UL>
+<P>This will help to prevent name collisions if you install many
+ different file types and filters.</P>
+<P>Once you choose the names for these files, create them using your
+ favorite text editor as described earlier in this chapter. Once you
+ have created the files, restart the <CODE>cupsd</CODE> process as
+ described earlier in <A HREF="#RESTARTING">&quot;Restarting the CUPS Server&quot;</A>
+.</P>
+<H3><A NAME="7_13_4">Printer Drivers and PPD Files</A></H3>
+<P>Most CUPS printer drivers utilize one or more printer-specific
+ filters and a PPD file for each printer model. Printer driver filters
+ are registered via the PPD file using <CODE>cupsFilter</CODE>
+ attributes:</P>
+<UL>
+<PRE>
+*cupsFilter: &quot;application/vnd.cups-raster 0 rastertohp&quot;
+</PRE>
+</UL>
+<P>The filter is specified using the source file type only; the
+ destination file type is assumed to be <CODE>printer/name</CODE> -
+ suitable for sending to the printer.</P>
+<H3><A NAME="7_13_5">Writing Your Own Filter or Printer Driver</A></H3>
+<P>CUPS supports an unlimited number of file formats and filters, and
+ can handle any printer. If you'd like to write a filter or printer
+ driver for your favorite file format or printer, consult the CUPS
+ Software Programmers Manual for step-by-step instructions.</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Printing with Other
+ Systems</A></H1>
+<P>This chapter describes how to print from client systems that use the
+ LPD, Mac OS, or Windows printing protocols.</P>
+<H2><A NAME="8_1">The Basics</A></H2>
+<P>CUPS is based on the IPP protocol, so any system that supports IPP
+ can send jobs to and receive jobs from CUPS automatically. However, not
+ all systems support IPP yet. This chapter will show you how to connect
+ these systems to your CUPS server, either to accept jobs from your
+ server for printing, or to send jobs to your server.</P>
+<H2><A NAME="8_2">Printing from LPD Clients</A></H2>
+<P>CUPS supports limited functionality for LPD-based clients. With LPD
+ you can print files to specific printers, list the queue status, and so
+ forth. However, the automatic client configuration and printer options
+ are not supported by the LPD protocol, so you must manually configure
+ each client for the printers it needs to access.</P>
+<P>The <CODE>cups-lpd(8)</CODE> program provides support for LPD clients
+ and can be used from either the <CODE>inetd(8)</CODE> or <CODE>
+xinetd(8)</CODE> programs. Add the following line to the<VAR>
+ /etc/inetd.conf</VAR> file to enable LPD support on your server through
+ the <CODE>inetd</CODE> program:</P>
+<UL>
+<PRE>
+printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+</PRE>
+</UL>
+<P>The path to the <CODE>cups-lpd</CODE> may vary depending on your
+ installation.</P>
+<P>Once you have added this line, send the <CODE>inetd</CODE> process a <CODE>
+HUP</CODE> signal or reboot the system:</P>
+<UL>
+<PRE>
+<B>killall -HUP inetd ENTER</B> [IRIX and some versions of Linux]
+<B>kill -HUP <I>pid</I> ENTER [Others]</B>
+<B>reboot ENTER [For all systems if the HUP signal fails]</B>
+</PRE>
+</UL>
+<P>If you are using the <CODE>xinetd</CODE> program, create a file named<VAR>
+ /etc/xinetd.d/printer</VAR> containing the following lines:</P>
+<UL>
+<PRE>
+service printer
+{
+socket_type = stream
+protocol = tcp
+wait = no
+user = lp
+server = /usr/lib/cups/daemon/cups-lpd
+}
+</PRE>
+</UL>
+<P>The <CODE>xinetd</CODE> program automatically reads the new
+ configuration file and enables LPD printing support.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Warning:</B>
+<P><CODE>cups-lpd</CODE> currently does not perform any access control
+ based on the settings in<VAR> cupsd.conf</VAR> or in the<VAR>
+ hosts.allow</VAR> or<VAR> hosts.deny</VAR> files used by TCP wrappers.
+ Therefore, running <CODE>cups-lpd</CODE> on your server will allow any
+ computer on your network (and perhaps the entire Internet) to print to
+ your server.</P>
+<P>While <CODE>xinetd</CODE> has built-in access control support, you
+ should use the TCP wrappers package with <CODE>inetd</CODE> to limit
+ access to only those computers that should be able to print through
+ your server.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="LPD">Printing to LPD Servers</A></H2>
+<P>CUPS provides the <CODE>lpd</CODE> backend for printing to LPD-based
+ servers and printers. Use a device URI of <CODE>lpd://server/name</CODE>
+ to print to a printer on an LPD server, where <CODE>server</CODE> is
+ the hostname or IP address of the server and <CODE>name</CODE> is the
+ queue name. Additional options can be specified after the remote queue
+ name to control how the LPD requests are sent - consult <A HREF="#COMMON_NETWORK">
+Appendix B - Common Network Settings</A> for a complete description.</P>
+<P>Microsoft Windows NT provides an LPD service under the name &quot;TCP/IP
+ Printing Services&quot;. To enable LPD printing on NT, open the &quot;Services&quot;
+ control panel, select the &quot;TCP/IP Printing Services&quot; service, and click
+ on the &quot;Start&quot; button. Any shared printer will then be available via
+ the LPD protocol.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="8_4">Printing from Mac OS 10.2 and Later Clients</A></H2>
+<P>Since Mac OS 10.2 uses CUPS as its printing system, all CUPS printers
+ will be available to the clients automatically.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>Certain legacy MacOS X applications, including most Adobe
+ applications, produce PICT files with embedded PostScript. Since the
+ filter needed to convert these files to pure PostScript is only
+ available on MacOS X, you need to either use a MacOS X print server or
+ replace the MacOS X IPP backend with the standard CUPS IPP backend. The
+ CUPS IPP backend will detect and locally convert these print files to
+ PostScript prior to sending the job to the server.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="8_5">Printing from Mac OS 10.1 and Earlier Clients</A></H2>
+<P>CUPS does not provide support for Mac OS 10.1 and earlier directly.
+ However, there are several free and commercial software packages that
+ do.</P>
+<H3><A NAME="8_5_1">Columbia Appletalk Package (CAP)</A></H3>
+<P>Because the CAP LaserWriter server (<CODE>lwsrv(8)</CODE>) does not
+ support specification of PPD files, we do not recommend that you use
+ CAP with CUPS. However, you can run the <CODE>lpsrv</CODE> program for
+ limited printing with the command:</P>
+<UL>
+<PRE>
+lwsrv -n &quot;<I>Name</I>&quot; -p <I>printer</I> -a /usr/lib/adicts -f /usr/lib/LW+Fonts
+</PRE>
+</UL>
+<P>where <CODE>Name</CODE> is the name you want to use when sharing the
+ printer, and <CODE>printer</CODE> is the name of the CUPS print queue.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="8_5_2">XINET KA/Spool</A></H3>
+<P>To use your system as a print server for Mac OS clients, configure
+ each printer using a <CODE>papserver(8)</CODE> in the<VAR>
+ /usr/adm/appletalk/services</VAR> file, specifying the corresponding
+ PPD file in the<VAR> /etc/cups/ppd</VAR> directory for each printer.
+ For a printer named <CODE>MyPrinter</CODE> the entry would look like:</P>
+<UL>
+<PRE>
+/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
+&quot;Printer Description&quot; MyPrinter
+</PRE>
+</UL>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Enter the text above on a single line without the backslash (\)
+ character.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="8_5_3">Netatalk</A></H3>
+<P>To use your system as a print server for Mac OS clients, configure
+ each printer in the<VAR> papd.conf</VAR> file, specifying the
+ corresponding PPD file in the<VAR> /etc/cups/ppd</VAR> directory for
+ each printer. For a printer named <CODE>MyPrinter</CODE> the entry
+ would look like:</P>
+<UL>
+<PRE>
+Printer Name@Zone Name:\
+:pr=|/usr/bin/lp -d MyPrinter:\
+:op=daemon:\
+:pd=/etc/cups/ppd/MyPrinter.ppd:
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H2><A NAME="8_6">Printing to Mac OS 10.2 and Later Servers</A></H2>
+<P>Since MacOS 10.2 and later use CUPS, all you need to do is enable
+ printer sharing to allow CUPS clients to print to a Mac OS server. You
+ will need to download and install ESP Ghostscript on your server to
+ provide PostScript printing support for non-PostScript printers,
+ however.
+<!-- NEED 2in -->
+</P>
+<H2><A NAME="8_7">Printing to Mac OS 10.1 and Earlier Servers</A></H2>
+<P>CUPS currently does not provide a backend to communicate with a Mac
+ OS 10.1 and earlier server. However, you can write and install a short
+ shell script in the<VAR> /usr/lib/cups/backend</VAR> directory that
+ sends a print file using the appropriate command. The following is a
+ short script that will run the <CODE>papif</CODE> command provided with
+ CAP.</P>
+<P>After copying this script to<VAR> /usr/lib/cups/backend/cap</VAR>,
+ specify a device URI of <CODE>cap://server/printer</CODE> to use this
+ backend with a print queue.
+<!-- NEED 8in -->
+</P>
+<UL>
+<PRE>
+<I>&quot;/usr/lib/cups/backend/cap&quot;</I>
+#!/bin/sh
+#
+# Usage: cap job user title copies options [filename]
+#
+
+# No arguments means show available devices...
+
+if test ${#argv} = 0; then
+echo &quot;network cap \&quot;Unknown\&quot; \&quot;Mac OS Printer via CAP\&quot;&quot;
+exit 0
+fi
+
+# Collect arguments...
+
+user=$2
+copies=$4
+
+if test ${#argv} = 5; then
+# Get print file from stdin; copies have already been handled...
+file=/var/tmp/$$.prn
+copies=1
+cat &gt; $file
+else
+# Print file is on command-line...
+file=$6
+fi
+
+# Create a dummy cap.printers file for this printer based
+# upon a device URI of &quot;cap://server/printer&quot;...
+
+echo $PRINTER/$DEVICE_URI | \
+awk -F/ '{print $1 &quot;=&quot; $5 &quot;:LaserWriter@&quot; $4}' &gt; /var/tmp/$$.cap
+
+CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
+
+# Send the file to the printer, once for each copy. This assumes that you
+# have properly initialized the cap.printers file...
+
+while [ $copies -gt 0 ]; do
+papif -n $user &lt; $file
+
+copies=`expr $copies - 1`
+done
+
+# Remove any temporary files...
+if test ${#argv} = 5; then
+/bin/rm -f $file
+fi
+
+/bin/rm -f /var/tmp/$$.cap
+
+exit 0
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<H2><A NAME="8_8">Printing from Windows Clients</A></H2>
+<P>While CUPS does not provide Windows support directly, the free SAMBA
+ software package does. SAMBA version 2.0.6 is the first release of
+ SAMBA that supports CUPS. You can download SAMBA from:</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>To configure SAMBA for CUPS, edit the<VAR> smb.conf</VAR> file and
+ replace the existing printing commands and options with the line:</P>
+<UL>
+<PRE>
+printing = cups
+printcap name = cups
+</PRE>
+</UL>
+<P>That's all there is to it! Remote users will now be able to browse
+ and print to printers on your system.</P>
+<H3><A NAME="8_8_1">Exporting Printer Drivers</A></H3>
+<P>You can optionally export printer drivers from your CUPS server using
+ the <CODE>cupsaddsmb</CODE> command and the SAMBA 2.2.0 or higher
+ software.</P>
+<P>Before you can export the printers you must download the CUPS drivers
+ for Windows from the CUPS site (<A HREF="http://www.cups.org/">
+http://www.cups.org/</A>) or the current Adobe PostScript printer
+ drivers from the Adobe web site (<A HREF="http://www.adobe.com/">
+http://www.adobe.com/</A>). If you download the Adobe drivers, use the
+ free <CODE>unzip</CODE> software to extract the files from the
+ self-extracting ZIP file containing the drivers; you will need the
+ following files:</P>
+<UL>
+<PRE>
+ADFONTS.MFM
+ADOBEPS4.DRV
+ADOBEPS4.HLP
+ADOBEPS5.DLL
+ADOBEPSU.DLL
+ADOBEPSU.HLP
+DEFPRTR2.PPD
+ICONLIB.DLL
+PSMON.DLL
+</PRE>
+</UL>
+<P>Copy these files to the<VAR> /usr/share/cups/drivers</VAR> directory
+ - you may need to rename some of the files so the filenames are all
+ UPPERCASE.</P>
+<P>Next, configure SAMBA (via the<VAR> smb.conf</VAR> file) to support
+ printing through CUPS and provide a printer driver download share, as
+ follows:</P>
+<UL>
+<PRE>
+[global]
+load printers = yes
+printing = cups
+printcap name = cups
+
+[printers]
+comment = All Printers
+path = /var/spool/samba
+browseable = no
+public = yes
+guest ok = yes
+writable = no
+printable = yes
+printer admin = root
+
+[print$]
+comment = Printer Drivers
+path = /etc/samba/drivers
+browseable = yes
+guest ok = no
+read only = yes
+write list = root
+</PRE>
+</UL>
+<P>This configuration assumes a FHS-compliant installation of SAMBA;
+ adjust the [printers] and [print$] share paths accordingly on your
+ system as needed. That is, the directory for your printer drivers can
+ be anywhere on the system; just make sure it is writable by the users
+ specified by the <CODE>write list</CODE> directive plus readable and
+ executable by all users. Also, make sure that you have SAMBA passwords
+ defined for each user in the <CODE>write list</CODE> using SAMBA's <CODE>
+smbpasswd(1)</CODE> command. Otherwise you will not be able to
+ authenticate.</P>
+<P>Finally, run the <CODE>cupsaddsmb</CODE> command to export the
+ printer drivers for one or more queues:</P>
+<UL>
+<PRE>
+<B>cupsaddsmb -U root printer1 ... printerN <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>Running <CODE>cupsaddsmb</CODE> with the <CODE>-a</CODE> option will
+ export all printers:</P>
+<UL>
+<PRE>
+<B>cupsaddsmb -U root -a <I>ENTER</I></B>
+</PRE>
+</UL>
+<P>Notice in the above examples that the user <CODE>root</CODE> was used
+ which was defined in the <CODE>write list</CODE> of the<VAR> smb.conf</VAR>
+ file.</P>
+<H2><A NAME="8_9">Printing to Windows Servers</A></H2>
+<P>CUPS can print to Windows servers in one of two ways. The first way
+ uses the LPD protocol on the CUPS system and the &quot;TCP/IP Printing
+ Services&quot; on the Windows system. You can find out more about this
+ configuration in the <A HREF="#LPD">LPD</A> section earlier in this
+ chapter.</P>
+<P>The second way is through the Microsoft Server Message Block (&quot;SMB&quot;)
+ protocol. Support for this protocol is provided with the free SAMBA
+ software package. You can download SAMBA from:</P>
+<UL>
+<PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE>
+</UL>
+<P>To configure CUPS for SAMBA, run the following command:</P>
+<UL>
+<PRE>
+<B>ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>smbspool(1)</CODE> program is provided with SAMBA starting
+ with SAMBA 2.0.6. Once you have made the link you can configure your
+ printers with one of the following device URIs:</P>
+<UL>
+<PRE>
+smb://workgroup/server/sharename
+smb://server/sharename
+smb://user:pass@workgroup/server/sharename
+smb://user:pass@server/sharename
+</PRE>
+</UL>
+<P>The <CODE>workgroup</CODE> name need only be specified if your system
+ is using a different workgroup. The <CODE>user:pass</CODE> strings are
+ required when printing to Windows NT servers or to shares with
+ passwords enabled under Windows 95 and 98.</P>
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
+<H2 ALIGN="CENTER"><A NAME="9_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P ALIGN="CENTER">Copyright 1997-2004 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3142 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
+<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<H3><A NAME="9_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2, with exceptions for
+ Apple operating systems and the OpenSSL toolkit. A copy of the
+ exceptions and licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the &quot;cups&quot; include
+ directory and library files in the binary distributions. The GNU GPL
+ applies to the remainder of the CUPS distribution, including the
+ &quot;pdftops&quot; filter which is based upon Xpdf and the CUPS imaging library.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate. The only exceptions to this are the portions of
+ the CUPS software covered by the Apple operating system license
+ exceptions outlined later in this license agreement.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="9_1_2">License Exceptions</A></H3>
+<P>In addition, as the copyright holder of CUPS, Easy Software Products
+ grants the following special exceptions:</P>
+<OL>
+<LI><B>Apple Operating System Development License Exception</B>;
+<OL TYPE="a">
+<LI>Software that is developed by any person or entity for an Apple
+ Operating System (&quot;Apple OS-Developed Software&quot;), including but not
+ limited to Apple and third party printer drivers, filters, and backends
+ for an Apple Operating System, that is linked to the CUPS imaging
+ library or based on any sample filters or backends provided with CUPS
+ shall not be considered to be a derivative work or collective work
+ based on the CUPS program and is exempt from the mandatory source code
+ release clauses of the GNU GPL. You may therefore distribute linked
+ combinations of the CUPS imaging library with Apple OS-Developed
+ Software without releasing the source code of the Apple OS-Developed
+ Software. You may also use sample filters and backends provided with
+ CUPS to develop Apple OS-Developed Software without releasing the
+ source code of the Apple OS-Developed Software.</LI>
+<LI>An Apple Operating System means any operating system software
+ developed and/or marketed by Apple Computer, Inc., including but not
+ limited to all existing releases and versions of Apple's Darwin, Mac OS
+ X, and Mac OS X Server products and all follow-on releases and future
+ versions thereof.</LI>
+<LI>This exception is only available for Apple OS-Developed Software and
+ does not apply to software that is distributed for use on other
+ operating systems.</LI>
+<LI>All CUPS software that falls under this license exception have the
+ following text at the top of each source file:<BLOCKQUOTE>This file is
+ subject to the Apple OS-Developed Software exception.</BLOCKQUOTE></LI>
+</OL>
+</LI>
+<LI><B>OpenSSL Toolkit License Exception</B>;
+<OL TYPE="a">
+<LI>Easy Software Products explicitly allows the compilation and
+ distribution of the CUPS software with the OpenSSL Toolkit.</LI>
+</OL>
+</LI>
+</OL>
+<P>No developer is required to provide these exceptions in a derived
+ work.</P>
+<H3><A NAME="9_1_3">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. You may use these names and logos in any
+ direct port or binary distribution of CUPS. Please contact Easy
+ Software Products for written permission to use them in derivative
+ products. Our intention is to protect the value of these trademarks and
+ ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="9_1_4">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pdftops&quot; filter that is
+ based on the Xpdf software. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Derek B. Noonburg
+<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
+<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
+http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="9_1_5">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/">http://www.easysw.com/</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<H3><A NAME="9_2_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+</LI>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+</LI>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+</LI>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+</LI>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+</LI>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+</LI>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H3><A NAME="9_3_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.
+<P></P>
+</LI>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.
+<P></P>
+</LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.
+<P></P>
+</LI>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)
+<P></P>
+</LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.
+<P></P>
+</LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.
+<P></P>
+</LI>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.
+<P></P>
+</LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+<H1 ALIGN="RIGHT"><A NAME="COMMON_NETWORK">B - Common Network Settings</A>
+</H1>
+<P>This appendix covers many of the popular TCP/IP network interfaces
+ and printer servers available on the market today.</P>
+<H2><A NAME="10_1">Configuring a Network Interface</A></H2>
+<P>When you first install a network printer or print server on your LAN,
+ you need to set the Internet Protocol (&quot;IP&quot;) address. On most
+ higher-end &quot;workgroup&quot; printers, you can set the address through the
+ printer control panel. However, in most cases you will want to assign
+ the addresses remotely from your workstation. This makes administration
+ a bit easier and avoids assigning duplicate addresses accidentally.</P>
+<P>To setup your printer or print server for remote address assignment,
+ you'll need the Ethernet Media Access Control (&quot;MAC&quot;) address, also
+ sometimes called a node address, and the IP address you want to use for
+ the device. The Ethernet MAC address can often be found on the printer
+ test page or bottom of the print server.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="10_1_1">Configuring the IP Address Using ARP</A></H3>
+<P>The easiest way to set the IP address of a network device is to use
+ the <CODE>arp(8)</CODE> command. The <CODE>arp</CODE> sends an Address
+ Resolution Protocol (&quot;ARP&quot;) packet to the specified Ethernet MAC
+ address, setting the network device's IP address:</P>
+<UL>
+<PRE>
+<B>arp -s ip-address ethernet-address ENTER</B>
+<B>arp -s host.domain.com 08:00:69:00:12:34 ENTER</B>
+<B>arp -s 192.0.2.2 08:00:69:00:12:34 ENTER</B>
+</PRE>
+</UL>
+<H3><A NAME="10_1_2">Configuring the IP Address Using RARP</A></H3>
+<P>The most flexible way to remotely assign IP addresses under UNIX is
+ through the Reverse Address Resolution Protocol (&quot;RARP&quot;). RARP allows a
+ network device to request an IP address using its Ethernet MAC address,
+ and one or more RARP servers on the network will respond with an ARP
+ packet with the IP address the device can use.</P>
+<P>RARP should be used when you have to manage many printers or print
+ servers, or when you have a network device that does not remember its
+ IP address after a power cycle. If you just have a single printer or
+ print server, the <CODE>arp</CODE> command is the way to go.</P>
+<P>Some UNIX operating systems use a program called <CODE>rarpd(8)</CODE>
+ to manage RARP. Others, like Linux, support this protocol in the
+ kernel. For systems that provide the <CODE>rarpd</CODE> program you
+ will need to start it before RARP lookups will work:</P>
+<UL>
+<PRE>
+<B>rarpd ENTER</B>
+</PRE>
+</UL>
+<P>Under IRIX you can enable this functionality by default using:</P>
+<UL>
+<PRE>
+<B>chkconfig rarpd on ENTER</B>
+</PRE>
+</UL>
+<P>Both the <CODE>rarpd</CODE> program and kernel RARP support read a
+ list of Ethernet and IP addresses from the file<VAR> /etc/ethers</VAR>.
+ Each line contains the Ethernet address (colon delimited) followed by
+ an IP address or hostname like:</P>
+<UL>
+<PRE>
+08:00:69:00:12:34 myprinter.mydomain.com
+08:00:69:00:12:34 192.0.2.2
+</PRE>
+</UL>
+<P>Add a line to this file and cycle the power on the printer or print
+ server to set its address.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="10_1_3">Configuring the IP Address Using BOOTP</A></H3>
+<P>The BOOTP protocol is used when you need to provide additional
+ information such as the location of a configuration file to the network
+ interface. Using the standard <CODE>bootpd(8)</CODE> program supplied
+ with UNIX you simply need to add a line to the<VAR> /etc/bootptab</VAR>
+ file; for IRIX:</P>
+<UL>
+<PRE>
+myprinter 08:00:69:00:12:34 192.0.2.2 <VAR>myprinter.boot</VAR>
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+<P>Newer versions of <CODE>bootpd</CODE> use a different format:</P>
+<UL>
+<PRE>
+myprinter:ha=080069001234:ip=192.0.2.2:<VAR>t144=myprinter.boot</VAR>
+</PRE>
+</UL>
+<P>The<VAR> myprinter.boot</VAR> file resides in the<VAR>
+ /usr/local/boot</VAR> directory by default. If you do not need to
+ provide a boot file you may leave the last part of the line blank.</P>
+
+<!-- NEED 2in -->
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Some versions of UNIX do not enable the BOOTP service by default. The<VAR>
+ /etc/inetd.conf</VAR> usually contains a line for the BOOTP service
+ that can be uncommented if needed.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H2><A NAME="10_2">Verifying the Printer Connection</A></H2>
+<P>To test that the IP address has been successfully assigned and that
+ the printer is properly connected to your LAN, type:</P>
+<UL>
+<PRE>
+<B>ping ip-address ENTER</B>
+</PRE>
+</UL>
+<P>If the connection is working properly you will see something like:</P>
+<UL>
+<PRE>
+<B>ping myprinter ENTER</B>
+PING myprinter (192.0.2.2): 56 data bytes
+64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
+64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
+</PRE>
+</UL>
+<P>If not, verify that the printer or print server is connected to the
+ LAN, it is powered on, the LAN cabling is good, and the IP address is
+ set correctly. You can usually see the current IP address and network
+ status by printing a configuration or test page on the device.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="10_3">Common Network Interface Settings</A></H2>
+<P>Once you have set the IP address you can access the printer or print
+ server using the <CODE>ipp</CODE>, <CODE>lpd</CODE>, or <CODE>socket</CODE>
+ backends. The following is a list of common network interfaces and
+ printer servers and the settings you should use with CUPS:
+<CENTER>
+<TABLE BORDER="1">
+<TR ALIGN="LEFT" VALIGN="TOP"><TH>Model/Manufacturer</TH><TH>Device
+ URI(s)</TH></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Apple LaserWriter</TD><TD>lpd://<I>
+address</I>/PASSTHRU</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/o IPP
+<BR> <A HREF="#AXIS">(see directions)</A></TD><TD>socket://<I>address</I>
+:9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/IPP</TD><TD>ipp://<I>address</I>
+/LPT1
+<BR> ipp://<I>address</I>/LPT2
+<BR> ipp://<I>address</I>/COM1</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Castelle LANpress<SUP>TM</SUP></TD><TD>
+lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>DPI NETPrint</TD><TD>lpd://<I>address</I>
+/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EFI&reg; Fiery&reg; RIP</TD><TD>lpd://<I>
+address</I>/print</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>EPSON&reg; Multiprotocol Ethernet
+ Interface Board</TD><TD>socket://<I>address</I></TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
+lpd://<I>address</I>/pr1
+<BR> lpd://<I>address</I>/pr2
+<BR> lpd://<I>address</I>/pr3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/o IPP</TD><TD>
+socket://<I>address</I>:9100
+<BR> socket://<I>address</I>:9101
+<BR> socket://<I>address</I>:9102</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/IPP</TD><TD>
+ipp://<I>address</I>/ipp
+<BR> ipp://<I>address</I>/ipp/port1
+<BR> ipp://<I>address</I>/ipp/port2
+<BR> ipp://<I>address</I>/ipp/port3</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Intel&reg; NetportExpress XL, PRO/100</TD><TD>
+lpd://<I>address</I>/LPT1_PASSTHRU
+<BR> lpd://<I>address</I>/LPT2_PASSTHRU
+<BR> lpd://<I>address</I>/COM1_PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Lexmark<SUP>TM</SUP> MarkNet</TD><TD>
+lpd://<I>address</I>/ps</TD></TR>
+
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Linksys EtherFast&reg;
+<BR> <A HREF="#LINKSYS">(see directions)</A></TD><TD>socket://<I>address</I>
+:4010
+<BR> socket://<I>address</I>:4020
+<BR> socket://<I>address</I>:4030</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Kodak&reg;</TD><TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>QMS&reg; CrownNet<SUP>TM</SUP></TD><TD>
+lpd://<I>address</I>/ps</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>Tektronix&reg; PhaserShare<SUP>TM</SUP></TD><TD>
+socket://<I>address</I>:9100</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; 4512 NIC</TD><TD>lpd://<I>
+address</I>/PORT1</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; XNIC</TD><TD>lpd://<I>address</I>
+/PASSTHRU</TD></TR>
+<TR ALIGN="LEFT" VALIGN="TOP"><TD>XEROX&reg; (most others)</TD><TD>socket://<I>
+address</I>:5503</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="AXIS">Configuring Axis Print Servers</A></H2>
+<P>The Axis print servers can be configured using ARP, RARP, or BOOTP.
+ However, on models that do not provide IPP support an additional step
+ must be performed to configure the TCP/IP portion of the print server
+ for use with CUPS.
+<!-- NEED 3in -->
+</P>
+<P>Each print server contains a configuration file named<VAR> config</VAR>
+ that contains a list of network parameters used by the server. To
+ modify this file you must first download it from the print server using
+ the <CODE>ftp(1)</CODE> program:</P>
+<UL>
+<PRE>
+<B>ftp ip-address ENTER</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTER</B>
+331 User name ok, need password
+Password: <B>pass ENTER</B> <I>(this is not echoed)</I>
+230 User logged in
+ftp&gt; <B>get config ENTER</B>
+local: config remote: config
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2),
+(mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTER</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Next, edit the file with your favorite text editor and locate the
+ lines beginning with:</P>
+<UL>
+<PRE>
+RTN_OPT. : YES
+RTEL_PR1. : 0
+RTEL_PR2. : 0
+RTEL_PR3. : 0
+RTEL_PR4. : 0
+RTEL_PR5. : 0
+RTEL_PR6. : 0
+RTEL_PR7. : 0
+RTEL_PR8. : 0
+</PRE>
+</UL>
+
+<!-- NEED 1in -->
+ Change the <CODE>RTN_OPT</CODE> line to read:
+<UL>
+<PRE>
+RTN_OPT. : <B>NO</B>
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>This disables the Reverse TELNET protocol and enables the standard
+ TELNET protocol on the print server. Next, assign a port number for
+ each parallel and serial port on the server as follows:</P>
+<UL>
+<PRE>
+RTEL_PR1. : <B>9100</B>
+RTEL_PR2. : <B>9101</B>
+RTEL_PR3. : <B>9102</B>
+RTEL_PR4. : <B>9103</B>
+RTEL_PR5. : <B>9104</B>
+RTEL_PR6. : <B>9105</B>
+RTEL_PR7. : <B>9106</B>
+RTEL_PR8. : <B>9107</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>This essentially makes the Axis print server look like a Hewlett
+ Packard JetDirect EX print server. Save the file and then upload the
+ new<VAR> config</VAR> file using the <CODE>ftp</CODE> command:</P>
+<UL>
+<PRE>
+<B>ftp ip-address ENTER</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp&gt; <B>user root ENTER</B>
+331 User name ok, need password
+Password: <B>pass ENTER</B> <I>(this is not echoed)</I>
+230 User logged in
+ftp&gt; <B>put config CONFIG ENTER</B>
+local: config remote: CONFIG
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2), (mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>get hardreset ENTER</B>
+local: hardreset remote: hardreset
+200 PORT command successful.
+421 Axis NPS ### hard reset, closing connection.
+ftp&gt; <B>quit ENTER</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Your Axis print server is now ready for use!</P>
+<H2><A NAME="LINKSYS">Configuring Linksys Print Servers</A></H2>
+<P>The Linksys print servers can be configured using ARP, RARP, or
+ BOOTP. Like older Axis print servers, an additional step must be
+ performed to configure the TCP/IP portion of the print server for use
+ with CUPS.
+<!-- NEED 3in -->
+</P>
+<P>Each print server contains a configuration file named<VAR> CONFIG</VAR>
+ that contains a list of network parameters used by the server. To
+ modify this file you must first download it from the print server using
+ the <CODE>ftp(1)</CODE> program:</P>
+<UL>
+<PRE>
+<B>ftp -n ip-address ENTER</B>
+Connected to ip-address.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>get CONFIG ENTER</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+WARNING! 68 bare linefeeds received in ASCII mode
+File may not have transferred correctly.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTER</B>
+221 Goodbye.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Next, edit the file with your favorite text editor and locate the
+ lines beginning with:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:P1
+0120 L2_PROUT:P1
+0140 L3_PROUT:P1
+</PRE>
+</UL>
+<P>Change the port number for each parallel and serial port on the
+ server as follows:</P>
+<UL>
+<PRE>
+0100 L1_PROUT:<B>P1</B>
+0120 L2_PROUT:<B>P2</B>
+0140 L3_PROUT:<B>P3</B>
+</PRE>
+</UL>
+
+<!-- NEED 4in -->
+<P>This maps each virtual printer with a physical port. Save the file
+ and then upload the new<VAR> CONFIG</VAR> file using the <CODE>ftp</CODE>
+ command:</P>
+<UL>
+<PRE>
+<B>ftp -n ip-address ENTER</B>
+Connected to ip-address.
+220 Print Server Ready.
+Remote system type is Print.
+ftp&gt; <B>put CONFIG ENTER</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp&gt; <B>quit ENTER</B>
+221 Goodbye.
+</PRE>
+</UL>
+<P>Your Linksys print server is now ready for use!</P>
+<H2><A NAME="LPD_OPTIONS">Configuring LPD Printing Options</A></H2>
+<P>The LPD backend supports several options which are included in the
+ device URI, e.g.:</P>
+<PRE>
+ lpd://server/name?option1=value1+option2=value2+...+optionN=valueN
+</PRE>
+<P>The following table summarizes the options and values that are
+ supported:
+<!-- NEED 9in -->
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR><TH>Option=Value</TH><TH>Description</TH></TR>
+<TR><TD>banner=off
+<BR> banner=no
+<BR> banner=false</TD><TD VALIGN="TOP">Does not request a LPD banner
+ page for the job. (Default)</TD></TR>
+<TR><TD>banner=on
+<BR> banner=yes
+<BR> banner=true</TD><TD VALIGN="TOP">Requests a LPD banner page for the
+ job.</TD></TR>
+<TR><TD>format=c
+<BR> format=d
+<BR> format=f
+<BR> format=g
+<BR> format=l
+<BR> format=n
+<BR> format=o
+<BR> format=p
+<BR> format=r
+<BR> format=t
+<BR> format=v</TD><TD VALIGN="TOP">Specifies the LPD format code of the
+ print job. &quot;format=l&quot; is raw output, while &quot;format=o&quot; is PostScript.
+ (Default is &quot;format=l&quot; for raw output)</TD></TR>
+<TR><TD>manual_copies=off
+<BR> manual_copies=no
+<BR> manual_copies=false</TD><TD VALIGN="TOP">Specifies that the backend
+ should not send multiple copies of a print job in the print data file.</TD>
+</TR>
+<TR><TD>manual_copies=on
+<BR> manual_copies=yes
+<BR> manual_copies=true</TD><TD VALIGN="TOP">Specifies that the backend
+ should send multiple copies of a print job in the print data file to
+ print more than one copy. (Default)</TD></TR>
+<TR><TD>order=control,data</TD><TD VALIGN="TOP">Specifies that the LPD
+ control file should be sent before the print data file. (Default)</TD></TR>
+<TR><TD>order=data,control=</TD><TD VALIGN="TOP">Specifies that the
+ print data file should be sent before the LPD control file.</TD></TR>
+<TR><TD>reserve=off
+<BR> reserve=no
+<BR> reserve=false</TD><TD VALIGN="TOP">Specifies that the backend
+ should not reserve a priviledged source port as required by RFC 1179.</TD>
+</TR>
+<TR><TD>reserve=on
+<BR> reserve=yes
+<BR> reserve=true
+<BR> reserve=rfc1179</TD><TD VALIGN="TOP">Specifies that the backend
+ should reserve a priviledges source port from 721 to 731 inclusive as
+ required by RFC 1179. This option may cause reduced printing
+ performance when more than 11 LPD printers are defined on the server
+ due to port contention issues.</TD></TR>
+<TR><TD>reserve=any</TD><TD VALIGN="TOP">Specifies that the backend
+ should reserve a priviledges source port from 1 to 1023 inclusive. This
+ often works with LPD implementations that require a priviledged source
+ port but do not limit it to the range defined by RFC 1179, allowing for
+ more printers to be active at the same time. (Default)</TD></TR>
+<TR><TD>sanitize_title=off
+<BR> sanitize_title=no
+<BR> sanitize_title=false</TD><TD VALIGN="TOP">Specifies that the
+ backend should not sanitize the job title string. (Default on OSX)</TD></TR>
+<TR><TD>sanitize_title=on
+<BR> sanitize_title=yes
+<BR> sanitize_title=true</TD><TD VALIGN="TOP">Specifies that the backend
+ should sanitize the job title string. (Default on all but OSX)</TD></TR>
+<TR><TD>timeout=N</TD><TD VALIGN="TOP">Specifies the response timeout
+ for all LPD commands and transactions in seconds. (Default is 300
+ seconds)</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_DRIVERS">C - Printer Drivers</A></H1>
+<P>This appendix lists the printer drivers that are provided with CUPS.</P>
+<H2><A NAME="11_1">Printer Drivers</A></H2>
+<P>CUPS includes the following printer drivers:</P>
+<UL>
+<LI><A HREF="#DYMO">DYMO Label Printer</A>,<VAR> dymo.ppd</VAR></LI>
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>,<VAR> epson9.ppd</VAR></LI>
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>,<VAR> epson24.ppd</VAR>
+</LI>
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>,<VAR> stcolor.ppd</VAR></LI>
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>,<VAR> stphoto.ppd</VAR></LI>
+<LI><A HREF="#DESKJET">HP DeskJet</A>,<VAR> deskjet.ppd</VAR></LI>
+<LI><A HREF="#LASERJET">HP LaserJet</A>,<VAR> laserjet.ppd</VAR></LI>
+</UL>
+<H2><A NAME="DYMO">DYMO Label Printer</A></H2>
+<P>The DYMO Label Printer driver (<VAR>dymo.ppd</VAR>) supports the DYMO
+ LabelWriter 300 series (300/310/315/320/330/330 Turbo) thermal label
+ printers. It provides 136, 203, and 300 DPI output in black only.</P>
+<H2><A NAME="EPSON9">EPSON 9-pin Dot Matrix</A></H2>
+<P>The EPSON 9-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+ 9-pin dot matrix printers that implement the ESC/P command set. It
+ provides 60x72, 120x72, and 240x72 DPI output in black only.</P>
+<H2><A NAME="EPSON24">EPSON 24-pin Dot Matrix</A></H2>
+<P>The EPSON 24-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+ 24-pin dot matrix printers that implement the ESC/P command set. It
+ provides 120x180, 180x180, 360x180, and 360x360 DPI output in black
+ only.</P>
+<H2><A NAME="STCOLOR">EPSON Stylus Color</A></H2>
+<P>The EPSON Stylus Color driver (<VAR>stcolor.ppd</VAR>) supports EPSON
+ Stylus Color printers that implement the ESC/P2 command set. It
+ provides 180, 360, and 720 DPI output in black and color (CMYK).</P>
+<H2><A NAME="STPHOTO">EPSON Stylus Photo</A></H2>
+<P>The EPSON Stylus Photo driver (<VAR>stphoto.ppd</VAR>) supports EPSON
+ Stylus Photo printers that implement the ESC/P2 command set. It
+ provides 180, 360, and 720 DPI output in black and color (CMYKcm).</P>
+<H2><A NAME="DESKJET">HP DeskJet</A></H2>
+<P>The HP DeskJet driver (<VAR>deskjet.ppd</VAR>) supports HP DeskJet
+ printers that implement the PCL command set. It provides 150, 300, and
+ 600 DPI output in black and color (CMYK).</P>
+<P>The DeskJet printers that implement the HP-PPA command set (720C,
+ 722C, 820C, and 1100C) are<B> not</B> supported due to a complete lack
+ of documentation and support from Hewlett Packard.</P>
+<P>The duplexer provided with the HP DeskJet 900 series printers is also
+ not supported for similar reasons.</P>
+<H2><A NAME="LASERJET">HP LaserJet</A></H2>
+<P>The HP LaserJet driver (<VAR>laserjet.ppd</VAR>) supports HP LaserJet
+ printers that implement the PCL command set. It provides 150, 300, and
+ 600 DPI output in black only and supports the duplexer if installed.</P>
+<P>LaserJet printers that do not implement PCL (3100, 3150) are not
+ supported due to a complete lack of documentation and support from
+ Hewlett Packard.</P>
+<H1 ALIGN="RIGHT"><A NAME="FILES">D - List of Files</A></H1>
+<P>This appendix lists the files and directories that are installed for
+ the Common UNIX Printing System.
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR VALIGN="TOP"><TH>Pathname</TH><TH>Description</TH></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/certs/</TD><TD>The location of
+ authentication certificate files for local HTTP clients.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/classes.conf</TD><TD>The printer classes
+ configuration file for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/cupsd.conf</TD><TD>The scheduler
+ configuration file.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/interfaces/</TD><TD>The location of
+ System V interface scripts for printers.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.convs</TD><TD>The list of standard
+ file filters included with CUPS.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/mime.types</TD><TD>The list of recognized
+ file types for CUPS.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/ppd/</TD><TD>The location of PostScript
+ Printer Description (&quot;PPD&quot;) files for printers.</TD></TR>
+<TR VALIGN="TOP"><TD>/etc/cups/printers.conf</TD><TD>The printer
+ configuration file for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/cancel</TD><TD>The System V cancel job(s)
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/disable</TD><TD>The System V disable
+ printer command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/enable</TD><TD>The System V enable printer
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lp</TD><TD>The System V print command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpoptions</TD><TD>Sets user-defined
+ printing options and defaults.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lppasswd</TD><TD>Adds, changes, or removes
+ Digest password accounts.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpq</TD><TD>The Berkeley status command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpr</TD><TD>The Berkeley print command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lprm</TD><TD>The Berkeley cancel job(s)
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/bin/lpstat</TD><TD>The System V status
+ command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/include/cups/</TD><TD>CUPS API header files.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.a
+<BR> /usr/lib32/libcupsimage.a</TD><TD>Static libraries (IRIX 6.5)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.a
+<BR> /usr/lib/libcupsimage.a</TD><TD>Static libraries (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.sl.2
+<BR> /usr/lib/libcupsimage.sl.2</TD><TD>Shared libraries (HP-UX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib32/libcups.so.2
+<BR> /usr/lib32/libcupsimage.so.2</TD><TD>Shared libraries (IRIX 6.5)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/lib/libcups.so.2
+<BR> /usr/lib/libcupsimage.so.2</TD><TD>Shared libraries (all others)</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/libexec/cups/backend/</TD><TD>Backends for
+ various types of printer connections (*BSD and OSX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/backend/</TD><TD>Backends for various
+ types of printer connections (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/libexec/cups/cgi-bin/</TD><TD>CGI programs for
+ the scheduler (*BSD and OSX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/cgi-bin/</TD><TD>CGI programs for the
+ scheduler (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/libexec/cups/daemon/</TD><TD>Daemons for
+ polling and LPD support (*BSD and OSX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/daemon/</TD><TD>Daemons for polling
+ and LPD support (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/libexec/cups/filter/</TD><TD>Filters for
+ various types of files (*BSD and OSX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/cups/filter/</TD><TD>Filters for various
+ types of files (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/locale/</TD><TD>The location of
+ language-specific message files. (System V)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/lib/nls/msg/</TD><TD>The location of
+ language-specific message files. (Compaq Tru64 UNIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/locale/</TD><TD>The location of
+ language-specific message files. (Linux, *BSD)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/accept</TD><TD>The accept-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/cupsd</TD><TD>The CUPS print scheduler.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpadmin</TD><TD>The System V printer
+ administration tool.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpc</TD><TD>The Berkeley printer
+ administration tool.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpinfo</TD><TD>The get-devices and
+ get-ppds command.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/lpmove</TD><TD>The move-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/sbin/reject</TD><TD>The reject-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP"><TD>/usr/share/catman/a_man/
+<BR> /usr/share/catman/u_man/</TD><TD>Man pages (IRIX)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/man/</TD><TD>Man pages (Compaq Tru64
+ UNIX, HP-UX, Solaris)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/man/</TD><TD>Man pages (all others)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/</TD><TD>The location of
+ filter data files.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/data/testprint.ps</TD><TD>The
+ PostScript test page file.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/fonts/</TD><TD>The location of
+ PostScript fonts for the PostScript RIP.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/model/</TD><TD>The location of
+ PostScript Printer Description (&quot;PPD&quot;) files and interface scripts that
+ may be used to setup a printer queue.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/</TD><TD>Other
+ PostScript RIP initialization files.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/pstoraster/Fontmap</TD><TD>The font
+ mapping file (converts filenames to fontnames)</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/cups/templates/</TD><TD>The location of
+ HTML template files for the web interfaces.</TD></TR>
+<TR VALIGN="TOP"><TD>/usr/share/doc/cups/</TD><TD>Documentation and web
+ page data for the scheduler.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/log/cups/</TD><TD>The location of scheduler
+ log files.</TD></TR>
+<TR VALIGN="TOP"><TD>/var/spool/cups/</TD><TD>The location of print
+ files waiting to be printed.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 ALIGN="RIGHT"><A NAME="FAQ">E - Troubleshooting Common Problems</A></H1>
+<P>This appendix covers some of the common problems first-time users
+ encounter when installing and configuring CUPS.</P>
+<P>Commercial support for CUPS is available from Easy Software Products.
+ For more information please contact us at:</P>
+<UL>
+<LI>WWW: <A HREF="http://www.easysw.com/cups/"> <CODE>
+http://www.easysw.com/cups/</CODE></A></LI>
+<LI>EMail: <A HREF="mailto:info@easysw.com">info@easysw.com</A></LI>
+<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600</LI>
+</UL>
+<H2><A NAME="13_1">My Applications Don't See the Available Printers</A></H2>
+<P>Many applications read the<VAR> /etc/printcap</VAR> file to get a
+ list of available printers.</P>
+<P>The default CUPS configuration creates the<VAR> /etc/printcap</VAR>
+ file automatically. To enable or disable automatic creation and
+ updating of this file, use the <A HREF="#Printcap"><CODE>Printcap</CODE>
+</A> directive described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6,
+ &quot;Printing System Management&quot;</A>.</P>
+<H2><A NAME="13_2">CUPS Doesn't Recognize My Username or Password!</A></H2>
+<P>CUPS will ask you for a UNIX username and password when you perform
+ printer administration tasks remotely or via a web browser. The default
+ configuration requires that you use the <CODE>root</CODE> username and
+ the corresponding password to authenticate the request.</P>
+<P>CUPS does not allow you to authenticate an administration request
+ with an account that has no password for security reasons. If you do
+ not have a password on your <CODE>root</CODE> account then you won't be
+ able to add printers remotely or via the web interface!
+<!-- NEED 2in -->
+</P>
+<P>To disable password authentication you need to edit the<VAR>
+ /etc/cups/cupsd.conf</VAR> file and comment out the lines reading:</P>
+<UL>
+<PRE>
+AuthType Basic
+AuthClass System
+</PRE>
+</UL>
+<P>for the<VAR> /admin</VAR> location. Then restart the CUPS server as
+ described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, &quot;Printing System
+ Management&quot;</A>.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Disabling password checks will allow any local user to change your
+ printer and class configuration, but remote administration from another
+ machine will still not be allowed.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+<H2><A NAME="ALLOW_REMOTE">I Can't Do Administration Tasks from Another
+ Machine!</A></H2>
+<P>The default CUPS configuration limits administration to the local
+ machine. To open up access, edit the<VAR> /etc/cups/cupsd.conf</VAR>
+ and comment out the lines reading:</P>
+<UL>
+<PRE>
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+</PRE>
+</UL>
+<P>for the<VAR> /admin</VAR> location. Then restart the CUPS server as
+ described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, &quot;Printing System
+ Management&quot;</A>.</P>
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>Allowing administration access from all hosts is a potential security
+ risk. Please read <A HREF="#PRINTING_SECURITY">Chapter 6, &quot;Printing
+ System Management&quot;</A> for a description of these risks and ways to
+ minimize them.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 4in -->
+<H2><A NAME="13_4">I Can't Do Administration Tasks from My Web Browser!</A>
+</H2>
+<P>This problem is usually caused by:</P>
+<OL>
+<LI>not specifying the correct password for the root account.</LI>
+<LI>accessing the CUPS server using the hostname or IP address of the
+ server without enabling remote access for administration functions.
+ This can be corrected by following the instructions in the <A HREF="#ALLOW_REMOTE">
+&quot;I Can't Do Administration Tasks from Another Machine!&quot;</A> section
+ earlier in this appendix.</LI>
+<LI>not setting a password on the root account. CUPS will not
+ authenticate a user account that does not have a password for security
+ reasons.</LI>
+<LI>authenticating using an account other than root, but the account you
+ are using is not a member of the system group.</LI>
+<LI>configuring CUPS to use Digest authentication, but your web browser
+ does not support Digest authentication.</LI>
+</OL>
+<H2><A NAME="13_5">Connection Refused Messages</A></H2>
+<P>Under normal circumstances, &quot;connection refused&quot; messages for a
+ networked printer should be expected from time to time. Most network
+ interfaces only allow a single connection to be made at any given time
+ (one job at a time) and will refuse access to all other systems while
+ the first connection is active. CUPS automatically retries the
+ connection once every 30 seconds.</P>
+<P>If the problem persists and you are unable to print any jobs to the
+ printer, verify that another machine is not maintaining a connection
+ with the printer, and that you have selected the proper port or printer
+ name for the printer.</P>
+<P>Also, most external print servers will refuse connections if the
+ connected printer is turned off or is off-line. Verify that the
+ affected printer is turned on and is online.</P>
+<H2><A NAME="13_6">Write Error Messages</A></H2>
+<P>If you get &quot;write error&quot; messages on a printer queue the printer
+ interface (usually a Hewlett Packard JetDirect interface) has timed out
+ and reset the network connection from your workstation.</P>
+<P>The error is caused by that startup delay between the initial setup
+ of the printer or plotter and the first page of print data that is
+ sent.
+<!-- NEED 3in -->
+</P>
+<P>To correct the problem, change the idle timeout on the interface to
+ at least 180 seconds or 3 minutes. To change the timeout on a Hewlett
+ Packard JetDirect interface, type:</P>
+<UL>
+<PRE>
+<B>telnet ip-address ENTER</B>
+
+Trying ip-address...
+Connected to ip-address.
+Escape character is `^]'.
+
+Please type [Return] two times, to initialize telnet configuration
+For HELP type &quot;?&quot;
+&gt; <B>idle-timeout: 180 ENTER</B>
+&gt; <B>quit ENTER</B>
+</PRE>
+</UL>
+</BODY>
+</HTML>
diff --git a/doc/sam.pdf b/doc/sam.pdf
new file mode 100644
index 000000000..24eb98079
--- /dev/null
+++ b/doc/sam.pdf
Binary files differ
diff --git a/doc/sam.shtml b/doc/sam.shtml
new file mode 100644
index 000000000..dfe24864d
--- /dev/null
+++ b/doc/sam.shtml
@@ -0,0 +1,6265 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SAM-1.1.22">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Administrators Manual</TITLE>
+</HEAD>
+<BODY>
+
+<H1 ALIGN="RIGHT">Preface</H1>
+
+<P>This software administrators manual provides printer administration
+information for the Common UNIX Printing System<SUP>TM</SUP>
+("CUPS<SUP>TM</SUP>"), version 1.1.22.
+
+<EMBED SRC="system-overview.shtml">
+
+<!-- NEED 3in -->
+<H2>Document Overview</H2>
+
+<P>This software administrators manual is organized into the following sections:</P>
+
+<UL>
+ <LI><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+ <LI><A HREF="#BUILDING_INSTALLING">2 - Building and Installing CUPS</A>
+ <LI><A HREF="#MANAGING_PRINTERS">3 - Managing Printers</A>
+ <LI><A HREF="#PRINTER_CLASSES">4 - Printer Classes</A>
+ <LI><A HREF="#CLIENT_SETUP">5 - Client Setup</A>
+ <LI><A HREF="#PRINTING_MANAGEMENT">6 - Printing System Management</A>
+ <LI><A HREF="#PRINTING_OTHER">7 - Printing with Other Systems</A>
+ <LI><A HREF="#LICENSE">A - Software License Agreement</A>
+ <LI><A HREF="#COMMON_NETWORK">B - Common Network Settings</A>
+ <LI><A HREF="#PRINTER_DRIVERS">C - Printer Drivers</A>
+ <LI><A HREF="#FILES">D - List of Files</A>
+ <LI><A HREF="#FAQ">E - Troubleshooting Common Problems</A>
+</UL>
+
+<H2>Notation Conventions</H2>
+
+<P>Various font and syntax conventions are used in this guide. Examples and
+their meanings and uses are explained below:
+
+<CENTER><TABLE WIDTH="80%">
+<TR>
+ <TH>Example</TH>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TH>Description</TH>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><CODE>lpstat</CODE><BR>
+ <CODE>lpstat(1)</CODE></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>The names of commands; the first mention of a command or
+ function in a chapter is followed by a manual page section
+ number.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><VAR>/var</VAR><BR>
+ <VAR>/usr/share/cups/data/testprint.ps</VAR></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>File and directory names.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><TT>Request ID is Printer-123</TT></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Screen output.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD>12.3</TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Numbers in the text are written using the period (.) to indicate
+ the decimal point.</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H2>Abbreviations</H2>
+
+The following abbreviations are used throughout this manual:
+
+<UL>
+<DL>
+
+ <DT>kb
+ <DD>Kilobytes, or 1024 bytes<BR>&nbsp;
+
+ <DT>Mb
+ <DD>Megabytes, or 1048576 bytes<BR>&nbsp;
+
+ <DT>Gb
+ <DD>Gigabytes, or 1073741824 bytes<BR>&nbsp;
+
+</DL>
+</UL>
+
+<H2>Other References</H2>
+
+<UL>
+<DL>
+
+ <DT>CUPS Software Programmers Manual
+
+ <DD>A programmer guide for interfacing with and/or extending the CUPS
+ software.<BR>&nbsp;
+
+ <DT>CUPS Software Users Manual
+
+ <DD>An end-user guide for using the CUPS software.<BR>&nbsp;
+
+</DL>
+</UL>
+
+
+<EMBED SRC="printing-overview.shtml">
+
+
+<H1 ALIGN="RIGHT"><A NAME="BUILDING_INSTALLING">2 - Building and Installing CUPS</A></H1>
+
+<P>This chapter shows how to build and install the Common UNIX Printing System.
+If you are installing a binary distribution from the CUPS web site, proceed to
+the section titled, <A HREF="#BINARY">Installing a Binary Distribution</A>.
+
+<H2>Installing a Source Distribution</H2>
+
+<P>This section describes how to compile and install CUPS on your system
+from the source code.
+
+<H3><A NAME="REQUIREMENTS">Requirements</A></H3>
+
+<P>You'll need ANSI-compliant C and C++ compilers to build CUPS on your
+system. As its name implies, CUPS is designed to run on the UNIX
+operating system, however the CUPS interface library and most of the
+filters and backends supplied with CUPS should also compile and run
+under Microsoft Windows.
+
+<P>For the image file filters and PostScript RIP, you'll need the JPEG,
+PNG, TIFF, and ZLIB libraries. CUPS will build without these, but with
+significantly reduced functionality. Easy Software Products maintains a
+mirror of the current versions of these libraries at:
+
+<UL><PRE>
+<A HREF="ftp://ftp.easysw.com/pub/libraries">ftp://ftp.easysw.com/pub/libraries</A>
+</PRE></UL>
+
+<P>If you make changes to the man pages you'll need GNU groff or another
+nroff-like package. GNU groff is available from:
+
+<UL><PRE>
+<A HREF="ftp://ftp.gnu.org/pub/groff">ftp://ftp.gnu.org/pub/groff</A>
+</PRE></UL>
+
+<P>The documentation is formatted using the HTMLDOC software. If you need to
+make changes you can get the HTMLDOC software from:
+
+<UL><PRE>
+<A HREF="http://www.easysw.com/htmldoc">http://www.easysw.com/htmldoc</A>
+</PRE></UL>
+
+<P>Finally, you'll need a <CODE>make</CODE> program that
+understands the <CODE>include</CODE> directive - FreeBSD,
+NetBSD, and OpenBSD developers should use the <CODE>gmake</CODE>
+program.
+
+<H3><A NAME="COMPILING">Compiling CUPS</A></H3>
+
+<P>CUPS uses GNU autoconf to configure the makefiles and source code
+for your system. Type the following command to configure CUPS for your
+system:
+
+<UL><PRE>
+<B>./configure ENTER</B>
+</PRE></UL>
+
+<P>The default installation will put the CUPS software in the
+<VAR>/etc</VAR>, <VAR>/usr</VAR>, and <VAR>/var</VAR> directories on
+your system, which will overwrite any existing printing commands on
+your system. Use the <CODE>--prefix</CODE> option to install the CUPS
+software in another location:
+
+<UL><PRE>
+<B>./configure --prefix=/some/directory ENTER</B>
+</PRE></UL>
+
+<P>If the PNG, JPEG, TIFF, and ZLIB libraries are not installed in a
+system default location (typically <VAR>/usr/include</VAR> and
+<VAR>/usr/lib</VAR>) you'll need to set the <CODE>CFLAGS</CODE>,
+<CODE>CXXFLAGS</CODE>, and <CODE>LDFLAGS</CODE> environment variables
+prior to running configure:
+
+<UL><PRE>
+<B>setenv CFLAGS "-I/some/directory" ENTER</B>
+<B>setenv CXXFLAGS "-I/some/directory" ENTER</B>
+<B>setenv LDFLAGS "-L/some/directory" ENTER</B>
+<B>setenv DSOFLAGS "-L/some/directory" ENTER</B>
+<B>./configure ... ENTER</B>
+</PRE></UL>
+
+<P>or:
+
+<UL><PRE>
+<B>CFLAGS="-I/some/directory"; export CFLAGS ENTER</B>
+<B>CXXFLAGS="-I/some/directory"; export CXXFLAGS ENTER</B>
+<B>LDFLAGS="-L/some/directory"; export LDFLAGS ENTER</B>
+<B>DSOFLAGS="-L/some/directory"; export DSOFLAGS ENTER</B>
+<B>./configure ... ENTER</B>
+</PRE></UL>
+
+<P>To enable support for encryption, you'll also want to add the
+"--enable-ssl" option:
+
+<UL><PRE>
+./configure --enable-ssl
+</PRE></UL>
+
+<P>SSL and TLS support require the OpenSSL library, available at:
+
+<UL><PRE>
+<A HREF="http://www.openssl.org">http://www.openssl.org</A>
+</PRE></UL>
+
+<P>If the OpenSSL headers and libraries are not installed in the
+standard directories, use the <CODE>--with-openssl-includes</CODE>
+and <CODE>--with-openssl-libs</CODE> options:</P>
+
+<UL><PRE>
+./configure --enable-ssl \
+ --with-openssl-includes=/foo/bar/include \
+ --with-openssl-libs=/foo/bar/lib
+</PRE></UL>
+
+<P>Once you have configured things, just type:
+
+<UL><PRE>
+<B>make ENTER</B>
+</PRE></UL>
+
+<P>to build the software.
+
+<!-- NEED 4in -->
+<H3><A NAME="INSTALLING">Installing the Software</A></H3>
+
+<P>Use the "install" target to install the software:
+
+<UL><PRE>
+<B>make install ENTER</B>
+</PRE></UL>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" BGCOLOR="#cccccc" CELLPADDING="5">
+<TR>
+ <TD>
+ <B>WARNING:</B>
+
+ <P>Installing CUPS will overwrite your existing printing
+ system. If you experience difficulties with the CUPS software
+ and need to go back to your old printing system, you will need
+ to reinstall the old printing system from your operating system CDs.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="RUNNING">Running the Software</A></H3>
+
+<P>Once you have installed the software you can start the CUPS server by
+typing:
+
+<UL><PRE>
+<B>/usr/sbin/cupsd ENTER</B>
+</PRE></UL>
+
+<!-- NEED 4in -->
+<H2><A NAME="BINARY">Installing a Binary Distribution</A></H2>
+
+<P>CUPS comes in a variety of binary distribution formats. Easy
+Software Products provides binaries in TAR format with installation and
+removal scripts ("portable" distributions), and in RPM and DPKG formats
+for Red Hat and Debian-based distributions. Portable distributions are
+available for all platforms, while the RPM and DPKG distributions are
+only available for Linux.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" BGCOLOR="#cccccc" CELLPADDING="5">
+<TR>
+ <TD>
+ <B>WARNING:</B>
+
+ <P>Installing CUPS will overwrite your existing printing
+ system. If you experience difficulties with the CUPS software
+ and need to go back to your old printing system, you will need
+ to remove the CUPS software with the provided script and/or
+ reinstall the old printing system from your operating system CDs.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+
+<H3><A NAME="PORTABLE-BINARY">Installing a Portable Distribution</A></H3>
+
+<P>To install the CUPS software from a portable distribution you will
+need to be logged in as root; doing an <CODE>su</CODE> is good enough.
+Once you are the root user, run the installation script with:
+
+<UL><PRE>
+<B>./cups.install ENTER</B>
+</PRE></UL>
+
+<P>After asking you a few yes/no questions the CUPS software will be
+installed and the scheduler will be started automatically.
+
+<!-- NEED 2in -->
+<H3><A NAME="RPM-BINARY">Installing an RPM Distribution</A></H3>
+
+<P>To install the CUPS software from an RPM distribution you will need
+to be logged in as root; doing an <CODE>su</CODE> is good enough. Once
+you are the root user, run RPM with:
+
+<UL><PRE>
+<B>rpm -e lpr</B>
+<B>rpm -i cups-1.1-linux-M.m.n-intel.rpm ENTER</B>
+</PRE></UL>
+
+<P>After a short delay the CUPS software will be
+installed and the scheduler will be started automatically.
+
+<H3><A NAME="DPKG-BINARY">Installing an Debian Distribution</A></H3>
+
+<P>To install the CUPS software from a Debian distribution you will
+need to be logged in as root; doing an <CODE>su</CODE> is good enough.
+Once you are the root user, run dpkg with:
+
+<UL><PRE>
+<B>dpkg -i cups-1.1-linux-M.m.n-intel.deb ENTER</B>
+</PRE></UL>
+
+<P>After a short delay the CUPS software will be installed and the
+scheduler will be started automatically.
+
+
+<H1 ALIGN="RIGHT"><A NAME="MANAGING_PRINTERS">3 - Managing Printers</A></H1>
+
+<P>This chapter describes how to add your first printer and how to
+manage your printers.
+
+<H2>The Basics</H2>
+
+<P>Each printer queue has a name associated with it; the printer name
+must start with any printable character except " ", "/", and "@".
+It can contain up to 127 letters, numbers, and the underscore (_).
+Case is not significant, e.g. "PRINTER", "Printer",
+and "printer" are considered to be the same name.
+
+<P>Printer queues also have a device associated with them. The device can be
+a parallel port, a network interface, and so forth. Devices within CUPS use
+Uniform Resource Identifiers ("URIs") which are a more general form of
+Uniform Resource Locators ("URLs") that are used in your web browser. For
+example, the first parallel port in Linux usually uses a device URI of
+<CODE>parallel:/dev/lp1</CODE>.
+
+<!-- NEED 2.5in -->
+<P>You can see a complete list of supported devices by running the
+<CODE>lpinfo(8)</CODE> command:
+
+<UL><PRE>
+<B>lpinfo -v ENTER</B>
+network socket
+network http
+network ipp
+network lpd
+direct parallel:/dev/lp1
+serial serial:/dev/ttyS1?baud=115200
+serial serial:/dev/ttyS2?baud=115200
+direct usb:/dev/usb/lp0
+network smb
+</PRE></UL>
+
+<P>The <CODE>-v</CODE> option specifies that you want a list of available
+devices. The first word in each line is the type of device (direct, file,
+network, or serial) and is followed by the device URI or method name for
+that device. File devices have device URIs of the form
+<CODE>file:/directory/filename</CODE> while network devices use the more
+familiar <CODE>method://server</CODE> or <CODE>method://server/path</CODE>
+format.
+
+<P>Finally, printer queues usually have a PostScript Printer Description
+("PPD") file associated with them. PPD files describe the capabilities of
+each printer, the page sizes supported, etc., and are used for PostScript
+and non-PostScript printers. CUPS includes PPD files for HP LaserJet, HP
+DeskJet, EPSON 9-pin, EPSON 24-pin, and EPSON Stylus printers.
+
+<H2>Adding Your First Printer</H2>
+
+<P>CUPS provides two methods for adding printers: a command-line
+program called <CODE>lpadmin(8)</CODE> and a Web interface. The
+<CODE>lpadmin</CODE> command allows you to perform most printer
+administration tasks from the command-line and is located in
+<VAR>/usr/sbin</VAR>. The Web interface is located at:
+
+<UL><PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE></UL>
+
+<P>and steps you through printer configuration. If you don't like
+command-line interfaces, try the <A HREF="#ADD_WEB">Web interface</A> instead.
+
+<H3>Adding Your First Printer from the Command-Line</H3>
+
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option to add a
+printer to CUPS:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -E -v <I>device</I> -m <I>ppd</I> ENTER</B>
+</PRE></UL>
+
+<P>For a HP DeskJet printer connected to the parallel port this would look
+like:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p DeskJet -E -v parallel:/dev/lp1 -m deskjet.ppd ENTER</B>
+</PRE></UL>
+
+<P>Similarly, a HP LaserJet printer using a JetDirect network interface at
+IP address 11.22.33.44 would be added with the command:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p LaserJet -E -v socket://11.22.33.44 -m laserjet.ppd ENTER</B>
+</PRE></UL>
+
+<P>As you can see, <CODE>deskjet.ppd</CODE> and <CODE>laserjet.ppd</CODE> are
+the PPD files for the HP DeskJet and HP LaserJet drivers included with CUPS.
+You'll find a complete list of PPD files and the printers they will work with
+in <A HREF="#PRINTER_DRIVERS">Appendix C, "Printer Drivers"</A>.
+
+
+<P>For a dot matrix printer connected to the serial port, this might look like:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p DotMatrix -E -m epson9.ppd \
+ -v serial:/dev/ttyS0?baud=9600+size=8+parity=none+flow=soft <I>ENTER</I></B>
+</PRE></UL>
+
+<P>Here you specify the serial port (e.g. S0,S1, d0, d1), baud rate
+(e.g. 9600, 19200, 38400, 115200, etc.), number of bits, parity, and flow control.
+If you do not need flow control, delete the "+flow=soft" portion.
+
+
+<H3><A NAME="ADD_WEB">Adding Your First Printer from the Web</A></H3>
+
+<P>The CUPS web server provides a user-friendly "wizard" interface for
+adding your printers. Rather than figuring out which device URI and PPD file
+to use, you can instead click on the appropriate listings and fill in some
+simple information. Enter the following URL in your web browser to begin:
+
+<UL><PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE></UL>
+
+<P>Click on the <VAR>Add Printer</VAR> button to add a printer.
+
+<H2>Managing Printers from the Command-Line</H2>
+
+<P>The <CODE>lpadmin</CODE> command enables you to perform most printer
+administration tasks from the command-line. You'll find <CODE>lpadmin</CODE>
+in the <VAR>/usr/sbin</VAR> directory.
+
+<H3>Adding and Modifying Printers</H3>
+
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> option
+to add or modify a printer:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> <I>options</I> ENTER</B>
+</PRE></UL>
+
+<P>The <I>options</I> arguments can be any of the following:
+
+<UL>
+<DL>
+
+ <DT>-c <I>class</I>
+
+ <DD>Adds the named printer to printer class <VAR>class</VAR>.
+ If the class does not exist then it is created.
+
+ <DT>-i <I>interface</I>
+
+ <DD>Copies the named <VAR>interface</VAR> script to the printer.
+ Interface scripts are used by System V printer drivers. Since
+ all filtering is disabled when using an interface script, scripts
+ generally should not be used unless there is no other driver for
+ a printer.
+
+ <DT>-m <I>model</I>
+
+ <DD>Specifies a standard printer driver which is usually a PPD
+ file. PPD's are usually stored under the <VAR>/usr/share/cups/model/</VAR>
+ directory structure. A list of all available models can be displayed
+ using the <CODE>lpinfo</CODE> command with the <CODE>-m</CODE> option.
+ A list of printer drivers included with CUPS can be found in
+ <A HREF="#PRINTER_DRIVERS">Appendix C, "Printer Drivers"</A>.
+
+ <DT>-r <I>class</I>
+
+ <DD>Removes the named printer from printer class <VAR>class</VAR>.
+ If the resulting class becomes empty then it is removed.
+
+ <DT>-v <I>device-uri</I>
+
+ <DD>Sets the device for communicating with the printer. If a
+ job is currently printing on the named printer then the job
+ will be restarted and sent to the new device.
+
+ <DT>-D <I>info</I>
+
+ <DD>Provides a textual description of the printer, e.g.
+ "John's Personal Printer".
+
+ <DT>-E
+
+ <DD>Enables the printer and accepts job. This option is
+ equivalent to running the <CODE>enable(1)</CODE> and
+ <CODE>accept(8)</CODE> commands on the printer.
+
+ <DT>-L <I>location</I>
+
+ <DD>Provides a textual location for the printer, e.g.
+ "Computer Lab 5".
+
+ <DT>-P <I>ppd-file</I>
+
+ <DD>Specifies a local PPD file for the printer driver.
+
+</DL>
+</UL>
+
+<H3>Deleting Printers</H3>
+
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-x</CODE> option
+to delete a printer:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -x <I>printer</I> ENTER</B>
+</PRE></UL>
+
+<H3>Setting the Default Printer</H3>
+
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-d</CODE> option
+to set a default printer:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -d <I>printer</I> ENTER</B>
+</PRE></UL>
+
+<P>The default printer can be overridden by the user using the
+<CODE>lpoptions(1)</CODE> command.
+
+<H3>Starting and Stopping Printers</H3>
+
+<P>The <CODE>enable</CODE> and <CODE>disable</CODE> commands start and stop
+printer queues, respectively:
+
+<UL><PRE>
+<B>/usr/bin/enable <I>printer</I> ENTER</B>
+<B>/usr/bin/disable <I>printer</I> ENTER</B>
+</PRE></UL>
+
+<P>Printers that are disabled may still accept jobs for printing, but won't
+actually print any files until they are restarted. This is useful if the
+printer malfunctions and you need time to correct the problem. Any queued
+jobs are printed after the printer is enabled (started).
+
+<H3>Accepting and Rejecting Print Jobs</H3>
+
+<P>The <CODE>accept</CODE> and <CODE>reject</CODE> commands accept and reject
+print jobs for the named printer, respectively:
+
+<UL><PRE>
+<B>/usr/sbin/accept <I>printer</I> ENTER</B>
+<B>/usr/sbin/reject <I>printer</I> ENTER</B>
+</PRE></UL>
+
+<P>As noted above, a printer can be stopped but accepting new print
+jobs. A printer can also be rejecting new print jobs while it finishes
+those that have been queued. This is useful for when you must perform
+maintenance on the printer and will not have it available to users for
+a long period of time.
+
+<H3>Setting Quotas on a Printer</H3>
+
+<P>CUPS supports page and size-based quotas for each printer.
+The quotas are tracked individually for each user, but a single set of
+limits applies to all users for a partiuclar printer. For example, you
+can limit every user to 5 pages per day on an expensive printer, but
+you cannot limit every user except Johnny.</P>
+
+<P>The <I>job-k-limit</I>, <I>job-page-limit</I>, and <I>job-quota-peiod</I>
+options determine whether and how quotas are enforced for a printer.
+The <I>job-quota-period</I> option determines the time interval for
+quota tracking. The interval is expressed in seconds, so a day is
+86,400, a week is 604,800 and a month is 2,592,000 seconds. The
+<I>job-k-limit</I> option specifies the job size limit in killobytes. The
+<I>job-page-limit</I> option specifies the number of pages limit.</P>
+
+<P>For quotas to be enforced, the period and at least one of the limits
+must be set to a non-zero value. The following options will enable
+quotas:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -o job-quota-period=604800 \
+ -o job-k-limit=1024 <I>ENTER</I></B>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -o job-quota-period=604800 \
+ -o job-page-limit=100 <I>ENTER</I></B>
+</PRE>
+</UL>
+
+<P>Or, you can combine all three options on the same line.</P>
+
+<H3>Restricting User Access to a Printer</H3>
+
+<P>The <CODE>-u</CODE> option of the <CODE>lpadmin</CODE> command controls which users can
+print to a printer. The default configuration allows all users to print
+to a printer:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:all <I>ENTER</I></B>
+</PRE>
+</UL>
+
+<P>CUPS supports allow and deny lists so that you can specify a
+list of users who are allowed to print or not allowed to print. Along
+with your list of users, you can specify whether they are allowed or
+not allowed to use the printer:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:peter,paul,mary <I>ENTER</I></B>
+</PRE>
+</UL>
+
+<P>This command allows peter, paul, and mary to print to the named
+printer, but all other users cannot print. The command:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u deny:peter,paul,mary <I>ENTER</I></B>
+</PRE>
+</UL>
+
+<P>has the opposite effect. All users except peter, paul, and mary will
+be able to print to the named printer.</P>
+
+<P>You can control access by UNIX groups as well by placing an
+"@" character before each group name. The command:</P>
+
+<UL>
+<PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -u allow:peter,paul,mary,@printgods <I>ENTER</I></B>
+</PRE>
+</UL>
+
+<P>allows the users peter, paul, and mary to print, as well as
+any user in the printgods group to print.
+
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR>
+ <TD><B>NOTE:</B>
+
+ <P>The <I>allow</I> and <I>deny</I> options are not cummulative. That
+ is, you must provide the complete list of users to allow or deny each
+ time.</P>
+
+ <P>Also, CUPS only maintains one list of users - the list can
+ allow or deny users from printing. If you specify an allow list and
+ then specify a deny list, the deny list will replace the allow list -
+ only one list is active at any time.</P>
+
+ </TD>
+</TR>
+</TABLE>
+</CENTER>
+
+<H2>Managing Printers from the Web</H2>
+
+<P>The Web interface is located at:
+
+<UL><PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE></UL>
+
+<P>From there you can perform all printer management tasks with a few
+simple mouse clicks.
+
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_CLASSES">4 - Printer Classes</A></H1>
+
+<P>This chapter describes what printer classes are and how to manage them.
+
+<H2>The Basics</H2>
+
+<P>CUPS provides collections of printers called <I>printer classes</I>. Jobs
+sent to a class are forwarded to the first available printer in the class.
+Classes can themselves be members of other classes, so it is possible for
+you to define very large, distributed printer classes for high-availability
+printing.
+
+<P>CUPS also supports <I>implicit classes</I>. Implicit classes work just
+like printer classes, but they are created automatically based upon the
+available printers and classes on the network. This allows you to setup
+multiple print servers with identical printer configurations and have the
+client machines send their print jobs to the first available server. If
+one or more servers go down, the jobs are automatically redirected to the
+servers that are running, providing fail-safe printing.
+
+<H2>Managing Printer Classes from the Command-Line</H2>
+
+<P>Run the <CODE>lpadmin</CODE> command with the <CODE>-p</CODE> and <CODE>-c</CODE> options
+to add a printer to a class:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -c <I>class</I> ENTER</B>
+</PRE></UL>
+
+<P>The <I>class</I> is created automatically if it doesn't exist. To remove a
+printer from a class use the <CODE>-r</CODE> option:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -p <I>printer</I> -r <I>class</I> ENTER</B>
+</PRE></UL>
+
+<P>To remove the entire class just use the <CODE>-x</CODE> option:
+
+<UL><PRE>
+<B>/usr/sbin/lpadmin -x <I>class</I> ENTER</B>
+</PRE></UL>
+
+<H2>Managing Printer Classes from the Web Interface</H2>
+
+<P>The Web interface is located at:
+
+<UL><PRE>
+<A HREF="http://localhost:631/admin">http://localhost:631/admin</A>
+</PRE></UL>
+
+<P>The <VAR>Add Class</VAR> and <VAR>Modify Class</VAR> interfaces provide a
+list of available printers; click on the printers of interest to add them to
+the class.
+
+<H2>Implicit Classes</H2>
+
+<P>A noted earlier, implicit classes are created automatically from the
+available network printers and classes. To disable this functionality,
+set the <A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+directive to <CODE>Off</CODE> in the <CODE>cupsd.conf</CODE> file. You
+will find more information on doing this in
+<A HREF="#PRINTING_MANAGEMENT">Chapter 6, "Printing System
+Management"</A>.
+
+
+<H1 ALIGN="RIGHT"><A NAME="CLIENT_SETUP">5 - Client Setup</A></H1>
+
+<P>This chapter discusses several ways to configure CUPS clients for
+printing.
+
+<H2>The Basics</H2>
+
+<P>A client is any machine that sends print jobs to another machine for
+final printing. Clients can also be servers if they communicate directly with
+any printers of their own.
+
+<P>CUPS supports several methods of configuring client machines:
+
+<UL>
+ <LI><A HREF="#CLIENT_MANUAL">Manual configuration of print queues.</A>
+ <LI><A HREF="#CLIENT_SERVER">Specifying a single server for printing.</A>
+ <LI><A HREF="#CLIENT_AUTO">Automatic configuration of print queues.</A>
+ <LI><A HREF="#CLIENT_POLL">Specifying multiple servers for printing.</A>
+ <LI><A HREF="#CLIENT_RELAY">Relaying printers to other clients.</A>
+</UL>
+
+<H3><A NAME="CLIENT_MANUAL">Manual Configuration of Print Queues</A></H3>
+
+<P>The most tedious method of configuring client machines is to configure
+each remote queue by hand using the <CODE>lpadmin</CODE> command:
+
+<UL><PRE>
+<B>lpadmin -p <I>printer</I> -E -v ipp://<I>server</I>/printers/<I>printer</I> ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>printer</CODE> name is the name of the printer on the server
+machine. The <CODE>server</CODE> name is the hostname or IP address of the
+server machine. Repeat the <CODE>lpadmin</CODE> command for each remote
+printer you wish to use.</P>
+
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+ <TR>
+ <TD><B> NOTE:</B>
+ <P>Manual configuration of print queues is not recommended for large
+ numbers of client machines because of the administration nightmare it
+ creates. For busy networks, consider subnetting groups of clients and
+ polling and relaying printer information instead.</P>
+ </TD>
+ </TR>
+</TABLE>
+</CENTER>
+
+<H3><A NAME="CLIENT_SERVER">Specifying a Single Server for Printing</A></H3>
+
+<P>CUPS can be configured to run without a local spooler and send all
+jobs to a single server. However, if that server goes down then all
+printing will be disabled. Use this configuration only as absolutely needed.
+
+<P>The default server is normally "localhost". To override the default
+server create a file named <VAR>/etc/cups/client.conf</VAR> and add
+a line reading:
+
+<UL><PRE>
+ServerName <I>server</I>
+</PRE></UL>
+
+<P>to the file. The <VAR>server</VAR> name can be the hostname or IP address
+of the default server.
+
+<P>The default server can also be customized on a per-user basis. To set a
+user-specific server create a file named <VAR>~/.cupsrc</VAR> and add a line
+reading:
+
+<UL><PRE>
+ServerName <I>server</I>
+</PRE></UL>
+
+<P>to the file. The <VAR>server</VAR> name can be the hostname or IP
+address of the default server.
+
+<H3><A NAME="CLIENT_AUTO">Automatic Configuration of Print Queues</A></H3>
+
+<P>CUPS supports automatic client configuration of printers on the same
+subnet. To configure printers on the same subnet, <I>do nothing</I>.
+Each client should see the available printers within 30 seconds
+automatically. The printer and class lists are updated automatically as
+printers and servers are added or removed.
+
+<P>If you want to see printers on other subnets as well, use the
+<A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A>
+directive as described next.</P>
+
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+ <TR>
+ <TD><B> NOTE:</B>
+ <P>The<A HREF="#BrowseAddress"> <CODE>BrowseAddress</CODE></A> directive
+ enables broadcast traffic from your server. The default configuration
+ braodcasts printer information every 30 seconds. Although this printer
+ information does not use much bandwidth, typically about 80 bytes per
+ printer, it can add up with large numbers of servers and printers.</P>
+ <P>Use the <A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A>
+ and <A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A> directives to tune
+ the amount of data that is added to your network load. In addition,
+ subnets can be used to minimize the amount of traffic that is carried
+ by the &quot;backbone&quot; of your large network.</P>
+ </TD>
+ </TR>
+</TABLE>
+</CENTER>
+
+<H3><A NAME="CLIENT_POLL">Specifying Multiple Servers for Printing</A></H3>
+
+<P>If you have CUPS servers on different subnets, then you should configure
+CUPS to poll those servers. Polling provides the benefits of automatic
+configuration without significant configuration on the clients, and multiple
+clients on the same subnet can share the same configuration information.
+
+<P>Polling is enabled by specifying one or more
+<A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A>
+directives in the <VAR>/etc/cups/cupsd.conf</VAR> file.
+For information on making these changes, see
+<A HREF="#PRINTING_MANAGEMENT">Chapter 6, "Printing System Management"</A>.
+
+<P>Multiple <A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A> lines can
+be used to poll multiple CUPS servers. To limit the amount of
+polling you do from client machines, you can have only one of the
+clients do the polling and relay that information to the others on the
+same subnet (described next).</P>
+
+<H3><A NAME="CLIENT_RELAY">Relaying Printers to Other Clients</A></H3>
+
+<P>When you have clients and servers spread across multiple subnets, the
+polling method is inefficient. CUPS provides a
+<A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> directive that enables a
+single client to relay (broadcast) the polled printer information to the local subnet.</P>
+
+<P>For example, Server A and Server B are on subnet 1 and subnet 2,
+while the clients are on subnet 3.
+To provide printers to all of the clients in subnet 3,
+client C will be configured with the following directives in <VAR>/etc/cups/cupsd.conf</VAR>:</P>
+
+<UL><PRE>
+# Poll the two servers
+<B>
+BrowsePoll ServerA
+BrowsePoll ServerB
+</B>
+
+# Relay the printers to the local subnet
+<B>
+BrowseRelay 127.0.0.1 192.168.3.255
+</B></PRE></UL>
+
+<P>The <A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> line specifies a source address and mask.
+Any browse packets coming from a matching address wil be sent to the given broadcast address.
+In this case, we want the packets from the local machine (127.0.0.1) relayed to the other clients.</P>
+
+<P>As printers are found using polling,
+they are relayed from client C to the rest of the clients through a broadcast on subnet 3.
+The rest of the clients can use the standard <VAR>cupsd.conf</VAR> configuration.</P>
+
+<P>The <A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> directive can also be used to relay
+browsing packets from one network interface to another.
+For example, if client C in the previous example had network interfaces attaches to both
+subnet 1 and subnet 2, it could use the <A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A> directive exclusively:
+
+<UL><PRE>
+# Relay the printers from subnet 1 and 2 to subnet 3
+<B>
+BrowseRelay 192.168.1 192.168.3.255
+BrowseRelay 192.168.2 192.168.3.255
+</B></PRE></UL>
+
+<!-- NEED 3in -->
+<H2>Load Balancing and Failsafe Operation</H2>
+
+<P>When using server polling or broadcasting, CUPS clients can
+automatically merge identical printers on multiple servers into a
+single <I>implicit class</I> queue. Clients assume that printers with
+the same name on multiple servers are in fact the same printer or type
+of printer being served by multiple machines.</P>
+
+<P>If you have two printers, LaserJet@ServerA and
+LaserJet@ServerB, a third implicit class called <I>LaserJet</I>
+will be created automatically on the client that refers to both
+printers. If the client also has a local printer with the name
+LaserJet and the <A
+HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A>
+directive is enabled, then an implicit class named
+<I>AnyLaserJet</I> will be created instead. Otherwise, the local
+printer will prevent the creation of an implicit class, since
+CUPS will assume that the local printer will always be more
+available than a remote one.</P>
+
+<P>The client will alternate between servers and automatically stop
+sending jobs to a server if it goes down, providing a load-balancing
+effect and fail-safe operation with automatic switchover.</P>
+
+<CENTER><TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+ <TR>
+ <TD><B> NOTE:</B>
+ <P>Note that implicit classes (<A
+ HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>)
+ are enabled and implicit "any" classes (<A
+ HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A>)
+ are disabled by default.</P>
+ </TD>
+ </TR>
+</TABLE></CENTER>
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_MANAGEMENT">6 - Printing System Management</A></H1>
+
+<P>This chapter shows how you can configure the CUPS server.
+
+<H2>The Basics</H2>
+
+<P>Several text files are used to configure CUPS. All of the server
+configuration files are located in the <VAR>/etc/cups</VAR> directory:
+
+<UL>
+<DL>
+
+ <!-- NEED 1in -->
+ <DT>classes.conf
+
+ <DD>This file contains information on each printer class.
+ Normally you manipulate this file using the
+ <CODE>lpadmin</CODE> command or the Web interface.<BR>&nbsp;
+
+ <!-- NEED 1in -->
+ <DT>client.conf
+
+ <DD>This file provides the default server name for client
+ machines. See <A HREF="#CLIENT_SETUP">Chapter 5, "Client
+ Setup"</A> for more information.<BR>&nbsp;
+
+ <!-- NEED 1in -->
+ <DT>cupsd.conf
+
+ <DD>This file controls how the CUPS server
+ (<VAR>/usr/sbin/cupsd</VAR>) operates and is normally edited by
+ hand.<BR>&nbsp;
+
+ <!-- NEED 1in -->
+ <DT>mime.convs
+
+ <DD>This file contains a list of standard file conversion filters
+ and their costs. You normally do not edit this file.<BR>&nbsp;
+
+ <!-- NEED 1in -->
+ <DT>mime.types
+
+ <DD>This file contains a list of standard file formats and how to
+ recognize them. You normally do not edit this file.<BR>&nbsp;
+
+ <!-- NEED 1in -->
+ <DT>printers.conf
+
+ <DD>This file contains information on each printer. Normally
+ you manipulate this file using the <CODE>lpadmin</CODE> command
+ or the Web Interface.<BR>&nbsp;
+
+</DL>
+</UL>
+
+<H2><A NAME="RESTARTING">Restarting the CUPS Server</A></H2>
+
+<P>Once you have made a change to a configuration file you need to
+restart the CUPS server by sending it a <CODE>HUP</CODE> signal or using the
+supplied initialization script. The CUPS distributions install the
+script in the <VAR>init.d</VAR> directory with the name
+<VAR>cups</VAR>. The location varies based upon the operating system:
+
+<UL><PRE>
+<B>/etc/software/init.d/cups restart ENTER</B>
+<B>/etc/rc.d/init.d/cups restart ENTER</B>
+<B>/etc/init.d/cups restart ENTER</B>
+<B>/sbin/init.d/cups restart ENTER</B>
+</PRE></UL>
+
+<H2>Changing the Server Configuration</H2>
+
+<P>The <VAR>/etc/cups/cupsd.conf</VAR> file contains configuration
+<I>directives</I> that control how the server functions. Each directive
+is listed on a line by itself followed by its value. Comments are
+introduced using the number sign ("#") character at the beginning of a
+line. Since the server configuration file consists of plain text, you
+can use your favorite text editor to make changes to it.
+
+<!-- NEED 4in -->
+<H2>Server Directives</H2>
+
+<P>The <VAR>cupsd.conf</VAR> file contains many directives that
+determine how the server operates:
+
+<UL>
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#AccessLog"><CODE>AccessLog</CODE></A>
+ <LI><A HREF="#Allow"><CODE>Allow</CODE></A>
+ <LI><A HREF="#AuthClass"><CODE>AuthClass</CODE></A>
+ <LI><A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>
+ <LI><A HREF="#AuthType"><CODE>AuthType</CODE></A>
+ <LI><A HREF="#AutoPurgeJobs"><CODE>AutoPurgeJobs</CODE></A>
+ <LI><A HREF="#BrowseAddress"><CODE>BrowseAddress</CODE></A>
+ <LI><A HREF="#BrowseAllow"><CODE>BrowseAllow</CODE></A>
+ <LI><A HREF="#BrowseDeny"><CODE>BrowseDeny</CODE></A>
+ <LI><A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A>
+ <LI><A HREF="#BrowseOrder"><CODE>BrowseOrder</CODE></A>
+ <LI><A HREF="#BrowsePoll"><CODE>BrowsePoll</CODE></A>
+ <LI><A HREF="#BrowsePort"><CODE>BrowsePort</CODE></A>
+ <LI><A HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A>
+ <LI><A HREF="#BrowseRelay"><CODE>BrowseRelay</CODE></A>
+ <LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A>
+ <LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A>
+ <LI><A HREF="#Browsing"><CODE>Browsing</CODE></A>
+ <LI><A HREF="#Classification"><CODE>Classification</CODE></A>
+ <LI><A HREF="#ClassifyOverride"><CODE>ClassifyOverride</CODE></A>
+ <LI><A HREF="#ConfigFilePerm"><CODE>ConfigFilePerm</CODE></A>
+ <LI><A HREF="#DataDir"><CODE>DataDir</CODE></A>
+ <LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A>
+ <LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A>
+ <LI><A HREF="#Deny"><CODE>Deny</CODE></A>
+ <LI><A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A>
+ <LI><A HREF="#Encryption"><CODE>Encryption</CODE></A>
+ <LI><A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A>
+ <LI><A HREF="#FaxRetryInterval"><CODE>FaxRetryInterval</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#FaxRetryLimit"><CODE>FaxRetryLimit</CODE></A>
+ <LI><A HREF="#FileDevice"><CODE>FileDevice</CODE></A>
+ <LI><A HREF="#FilterLimit"><CODE>FilterLimit</CODE></A>
+ <LI><A HREF="#FilterNice"><CODE>FilterNice</CODE></A>
+ <LI><A HREF="#FontPath"><CODE>FontPath</CODE></A>
+ <LI><A HREF="#Group"><CODE>Group</CODE></A>
+ <LI><A HREF="#HideImplicitMembers"><CODE>HideImplicitMembers</CODE></A>
+ <LI><A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
+ <LI><A HREF="#ImplicitAnyClasses"><CODE>ImplicitAnyClasses</CODE></A>
+ <LI><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+ <LI><A HREF="#Include"><CODE>Include</CODE></A>
+ <LI><A HREF="#KeepAliveTimeout"><CODE>KeepAliveTimeout</CODE></A>
+ <LI><A HREF="#KeepAlive"><CODE>KeepAlive</CODE></A>
+ <LI><A HREF="#Limit"><CODE>Limit</CODE></A>
+ <LI><A HREF="#LimitExcept"><CODE>LimitExcept</CODE></A>
+ <LI><A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A>
+ <LI><A HREF="#Listen"><CODE>Listen</CODE></A>
+ <LI><A HREF="#Location"><CODE>Location</CODE></A>
+ <LI><A HREF="#LogFilePerm"><CODE>LogFilePerm</CODE></A>
+ <LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A>
+ <LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A>
+ <LI><A HREF="#MaxClientsPerHost"><CODE>MaxClientsPerHost</CODE></A>
+ <LI><A HREF="#MaxCopies"><CODE>MaxCopies</CODE></A>
+ <LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A>
+ <LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A>
+ <LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A>
+ <LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A>
+ <LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A>
+ <LI><A HREF="#Order"><CODE>Order</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#PageLog"><CODE>PageLog</CODE></A>
+ <LI><A HREF="#Port"><CODE>Port</CODE></A>
+ <LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A>
+ <LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A>
+ <LI><A HREF="#Printcap"><CODE>Printcap</CODE></A>
+ <LI><A HREF="#PrintcapFormat"><CODE>PrintcapFormat</CODE></A>
+ <LI><A HREF="#PrintcapGUI"><CODE>PrintcapGUI</CODE></A>
+ <LI><A HREF="#ReloadTimeout"><CODE>ReloadTimeout</CODE></A>
+ <LI><A HREF="#RemoteRoot"><CODE>RemoteRoot</CODE></A>
+ <LI><A HREF="#RequestRoot"><CODE>RequestRoot</CODE></A>
+ <LI><A HREF="#Require"><CODE>Require</CODE></A>
+ <LI><A HREF="#RIPCache"><CODE>RIPCache</CODE></A>
+ <LI><A HREF="#RootCertDuration"><CODE>RootCertDuration</CODE></A>
+ <LI><A HREF="#RunAsUser"><CODE>RunAsUser</CODE></A>
+ <LI><A HREF="#Satisfy"><CODE>Satisfy</CODE></A>
+ <LI><A HREF="#ServerAdmin"><CODE>ServerAdmin</CODE></A>
+ <LI><A HREF="#ServerBin"><CODE>ServerBin</CODE></A>
+ <LI><A HREF="#ServerCertificate"><CODE>ServerCertificate</CODE></A>
+ <LI><A HREF="#ServerKey"><CODE>ServerKey</CODE></A>
+ <LI><A HREF="#ServerName"><CODE>ServerName</CODE></A>
+ <LI><A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A>
+ <LI><A HREF="#ServerTokens"><CODE>ServerTokens</CODE></A>
+ <LI><A HREF="#SSLListen"><CODE>SSLListen</CODE></A>
+ <LI><A HREF="#SSLPort"><CODE>SSLPort</CODE></A>
+ <LI><A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A>
+ <LI><A HREF="#TempDir"><CODE>TempDir</CODE></A>
+ <LI><A HREF="#Timeout"><CODE>Timeout</CODE></A>
+ <LI><A HREF="#User"><CODE>User</CODE></A>
+
+</TD>
+</TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="AccessLog">AccessLog</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AccessLog /var/log/cups/access_log
+AccessLog /var/log/cups/access_log-%s
+AccessLog syslog
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AccessLog</CODE> directive sets the name of the access log
+file. If the filename is not absolute then it is assumed to be relative
+to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+access log file is stored in "common log format" and can be used by any
+web access reporting tool to generate a report on CUPS server activity.
+
+<P>The server name can be included in the filename by using
+<CODE>%s</CODE> in the name.
+
+<P>The special name "syslog" can be used to send the access information
+to the system log instead of a plain file.
+
+<P>The default access log file is <VAR>/var/log/cups/access_log</VAR>.
+
+<!-- NEED 6in -->
+<H3><A NAME="Allow">Allow</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Allow from All
+Allow from None
+Allow from *.domain.com
+Allow from .domain.com
+Allow from host.domain.com
+Allow from nnn.*
+Allow from nnn.nnn.*
+Allow from nnn.nnn.nnn.*
+Allow from nnn.nnn.nnn.nnn
+Allow from nnn.nnn.nnn.nnn/mm
+Allow from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+Allow from @LOCAL
+Allow from @IF(name)
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Allow</CODE> directive specifies a hostname, IP address,
+or network that is allowed access to the server. <CODE>Allow</CODE>
+directives are cummulative, so multiple <CODE>Allow</CODE> directives
+can be used to allow access for multiple hosts or networks. The
+<CODE>/mm</CODE> notation specifies a CIDR netmask:
+
+<CENTER><TABLE BORDER="1">
+<TR>
+ <TH WIDTH="10%">mm</TH>
+ <TH WIDTH="20%">netmask</TH>
+ <TH WIDTH="10%">mm</TH>
+ <TH WIDTH="20%">netmask</TH>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">0</TD>
+ <TD ALIGN="CENTER">0.0.0.0</TD>
+ <TD ALIGN="CENTER">8</TD>
+ <TD ALIGN="CENTER">255.0.0.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">1</TD>
+ <TD ALIGN="CENTER">128.0.0.0</TD>
+ <TD ALIGN="CENTER">16</TD>
+ <TD ALIGN="CENTER">255.255.0.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">2</TD>
+ <TD ALIGN="CENTER">192.0.0.0</TD>
+ <TD ALIGN="CENTER">24</TD>
+ <TD ALIGN="CENTER">255.255.255.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">...</TD>
+ <TD ALIGN="CENTER">...</TD>
+ <TD ALIGN="CENTER">32</TD>
+ <TD ALIGN="CENTER">255.255.255.255</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>The <CODE>@LOCAL</CODE> name will allow access from all local
+network interfaces, but not remote point-to-point interfaces. The
+<CODE>@IF(name)</CODE> name will allow access from the named
+interface.
+
+<P>The <CODE>Allow</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="AuthClass">AuthClass</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AuthClass Anonymous
+AuthClass User
+AuthClass System
+AuthClass Group
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AuthClass</CODE> directive defines what level of authentication
+is required:
+
+<UL>
+
+ <LI><CODE>Anonymous</CODE> - No authentication should be performed
+ (default.)
+
+ <LI><CODE>User</CODE> - A valid username and password is required.
+
+ <LI><CODE>System</CODE> - A valid username and password is
+ required, and the username must belong to the "sys" group; this
+ can be changed using the
+ <A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A> directive.
+
+ <LI><CODE>Group</CODE> - A valid username and password is
+ required, and the username must belong to the group named by
+ the <CODE>AuthGroupName</CODE> directive.
+
+</UL>
+
+<P>The <CODE>AuthClass</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="AuthGroupName">AuthGroupName</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AuthGroupName mygroup
+AuthGroupName lp
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AuthGroupName</CODE> directive sets the group to use for
+<CODE>Group</CODE> authentication.
+
+<P>The <CODE>AuthGroupName</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 4in -->
+<H3><A NAME="AuthType">AuthType</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AuthType None
+AuthType Basic
+AuthType Digest
+AuthType BasicDigest
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AuthType</CODE> directive defines the type of authentication to
+perform:
+
+<UL>
+
+ <LI><CODE>None</CODE> - No authentication should be performed
+ (default.)
+
+ <LI><CODE>Basic</CODE> - Basic authentication should be
+ performed using the UNIX password and group files.
+
+ <LI><CODE>Digest</CODE> - Digest authentication should be
+ performed using the <VAR>/etc/cups/passwd.md5</VAR> file.
+
+ <LI><CODE>BasicDigest</CODE> - Basic authentication should be
+ performed using the <VAR>/etc/cups/passwd.md5</VAR> file.
+
+</UL>
+
+<P>When using <CODE>Basic</CODE>, <CODE>Digest</CODE>, or
+<CODE>BasicDigest</CODE> authentication, clients connecting
+through the <CODE>localhost</CODE> interface can also
+authenticate using <A HREF="#CERTIFICATES">certificates</A>.
+
+<P>The <CODE>AuthType</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="AutoPurgeJobs">AutoPurgeJobs</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AutoPurgeJobs Yes
+AutoPurgeJobs No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AutoPurgeJobs</CODE> directive specifies whether or not to purge
+completed jobs once they are no longer required for quotas. This option has
+no effect if quotas are not enabled. The default setting is <CODE>No</CODE>.
+
+<!-- NEED 5in -->
+<H3><A NAME="BrowseAddress">BrowseAddress</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseAddress 255.255.255.255:631
+BrowseAddress 192.0.2.255:631
+BrowseAddress host.domain.com:631
+BrowseAddress @LOCAL
+BrowseAddress @IF(name)
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseAddress</CODE> directive specifies an address to
+send browsing information to. Multiple <CODE>BrowseAddress</CODE>
+directives can be specified to send browsing information to different
+networks or systems.
+
+<P>The <CODE>@LOCAL</CODE> name will broadcast printer
+information to all local interfaces. The <CODE>@IF(name)</CODE>
+name will broadcast to the named interface.
+
+<P>No browse addresses are set by default.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>If you are using HP-UX 10.20 and a subnet that is not 24,
+ 16, or 8 bits, printer browsing (and in fact all broadcast
+ reception) will not work. This problem appears to be fixed in
+ HP-UX 11.0.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 4in -->
+<H3><A NAME="BrowseAllow">BrowseAllow</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseAllow from all
+BrowseAllow from none
+BrowseAllow from 192.0.2
+BrowseAllow from 192.0.2.0/24
+BrowseAllow from 192.0.2.0/255.255.255.0
+BrowseAllow from *.domain.com
+BrowseAllow from @LOCAL
+BrowseAllow from @IF(name)
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseAllow</CODE> directive specifies a system or network
+to accept browse packets from. The default is to accept browse packets
+from all hosts.
+
+<P>Host and domain name matching require that you enable the
+<A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A> directive.
+
+<P>IP address matching supports exact matches, partial addresses that
+match networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0,
+or network addresses using the specified netmask or bit count.
+
+<P>The <CODE>@LOCAL</CODE> name will allow browse data from all
+local network interfaces, but not remote point-to-point
+interfaces. The <CODE>@IF(name)</CODE> name will allow browse
+data from the named interface.
+
+
+<!-- NEED 4in -->
+<H3><A NAME="BrowseDeny">BrowseDeny</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseDeny from all
+BrowseDeny from none
+BrowseDeny from 192.0.2
+BrowseDeny from 192.0.2.0/24
+BrowseDeny from 192.0.2.0/255.255.255.0
+BrowseDeny from *.domain.com
+BrowseDeny from @LOCAL
+BrowseDeny from @IF(name)
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseDeny</CODE> directive specifies a system or network
+to reject browse packets from. The default is to deny browse packets
+from no hosts.
+
+<P>Host and domain name matching require that you enable the
+<A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A> directive.
+
+<P>IP address matching supports exact matches, partial addresses that
+match networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0,
+or network addresses using the specified netmask or bit count.
+
+<P>The <CODE>@LOCAL</CODE> name will block browse data from all
+local network interfaces, but not remote point-to-point
+interfaces. The <CODE>@IF(name)</CODE> name will block browse
+data from the named interface.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseInterval 0
+BrowseInterval 30
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseInterval</CODE> directive specifies the maximum amount of
+time between browsing updates. Specifying a value of 0 seconds disables
+outgoing browse updates but allows a server to receive printer information
+from other hosts.
+
+<P>The <CODE>BrowseInterval</CODE> value should always be less than the
+<A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A> value. Otherwise
+printers and classes will disappear from client systems between updates.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseOrder">BrowseOrder</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseOrder allow,deny
+BrowseOrder deny,allow
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseOrder</CODE> directive specifies the order of allow/deny
+processing. The default order is <CODE>deny,allow</CODE>:
+
+<UL>
+
+ <LI><CODE>allow,deny</CODE> - Browse packets are accepted unless
+ specifically denied.
+
+ <LI><CODE>deny,allow</CODE> - Browse packets are rejected unless
+ specifically allowed.
+
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowsePoll">BrowsePoll</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowsePoll 192.0.2.2:631
+BrowsePoll host.domain.com:631
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowsePoll</CODE> directive polls a server for available
+printers once every
+<A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> seconds.
+Multiple <CODE>BrowsePoll</CODE> directives can be specified to poll
+multiple servers.
+
+<P>If <CODE>BrowseInterval</CODE> is set to 0 then the server is polled
+once every 30 seconds.
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowsePort">BrowsePort</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowsePort 631
+BrowsePort 9999
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowsePort</CODE> directive specifies the UDP port number
+used for browse packets. The default port number is 631.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>You must set the <CODE>BrowsePort</CODE> to the same value
+ on all of the systems that you want to see.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseProtocols">BrowseProtocols</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseProtocols CUPS
+BrowseProtocols SLP
+BrowseProtocols CUPS SLP
+BrowseProtocols all
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseProtocols</CODE> directive specifies the protocols to
+use when collecting and distributing shared printers on the local network.
+The default protocol is <CODE>CUPS</CODE>, which is a broadcast-based
+protocol.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>When using the <CODE>SLP</CODE> protocol, you must have at least
+ one Directory Agent (DA) server on your network. Otherwise the
+ CUPS scheduler (<CODE>cupsd</CODE>) will not respond to client
+ requests for several seconds while polling the network.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 4in -->
+<H3><A NAME="BrowseRelay">BrowseRelay</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseRelay 193.0.2.1 192.0.2.255
+BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
+BrowseRelay 193.0.2.0/24 192.0.2.255
+BrowseRelay *.domain.com 192.0.2.255
+BrowseRelay host.domain.com 192.0.2.255
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseRelay</CODE> directive specifies source and destination
+addresses for relaying browsing information from one host or network to
+another. Multiple <CODE>BrowseRelay</CODE> directives can be specified
+as needed.
+
+<P><CODE>BrowseRelay</CODE> is typically used on systems that bridge
+multiple subnets using one or more network interfaces. It can also be
+used to relay printer information from polled servers with the line:
+
+<UL><PRE>
+BrowseRelay 127.0.0.1 255.255.255.255
+</PRE></UL>
+
+<P>This effectively provides access to printers on a WAN for all clients
+on the LAN(s).
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseShortNames">BrowseShortNames</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseShortNames Yes
+BrowseShortNames No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseShortNames</CODE> directive specifies whether or not
+short names are used for remote printers when possible. Short names are
+just the remote printer name, without the server ("printer"). If more than
+one remote printer is detected with the same name, the printers will have
+long names ("printer@server1", "printer@server2".)
+
+<P>The default value for this option is <CODE>Yes</CODE>.
+
+<!-- NEED 3in -->
+<H3><A NAME="BrowseTimeout">BrowseTimeout</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+BrowseTimeout 300
+BrowseTimeout 60
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>BrowseTimeout</CODE> directive sets the timeout for
+printer or class information that is received in browse packets. Once a
+printer or class times out it is removed from the list of available
+destinations.
+
+<P>The <CODE>BrowseTimeout</CODE> value should always be greater than the
+<A HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> value. Otherwise
+printers and classes will disappear from client systems between updates.
+
+<!-- NEED 4in -->
+<H3><A NAME="Browsing">Browsing</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Browsing On
+Browsing Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Browsing</CODE> directive controls whether or not network printer
+browsing is enabled. The default setting is <CODE>On</CODE>.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>If you are using HP-UX 10.20 and a subnet that is not 24,
+ 16, or 8 bits, printer browsing (and in fact all broadcast
+ reception) will not work. This problem appears to be fixed in
+ HP-UX 11.0.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Classification</CODE> directive sets the classification level
+on the server. When this option is set, at least one of the banner pages
+is forced to the classification level, and the classification is placed
+on each page of output. The default is no classification level.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassifyOverride">ClassifyOverride</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ClassifyOverride Yes
+ClassifyOverride No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ClassifyOverride</CODE> directive specifies whether users
+can override the default classification level on the server. When the
+server classification is set, users can change the classification using
+the <CODE>job-sheets</CODE> option and can choose to only print one
+security banner before or after the job. If the <CODE>job-sheets</CODE>
+option is set to <CODE>none</CODE> then the server default classification
+is used.
+
+<P>The default is to not allow classification overrides.
+
+<!-- NEED 3in -->
+<H3><A NAME="ConfigFilePerm">ConfigFilePerm</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ConfigFilePerm 0644
+ConfigFilePerm 0600
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ConfigFilePerm</CODE> directive specifies the permissions
+to use when writing configuration files. The default is 0600.
+
+<!-- NEED 3in -->
+<H3><A NAME="DataDir">DataDir</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DataDir /usr/share/cups
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DataDir</CODE> directive sets the directory to use for data
+files.
+
+<!-- NEED 3in -->
+<H3><A NAME="DefaultCharset">DefaultCharset</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DefaultCharset utf-8
+DefaultCharset iso-8859-1
+DefaultCharset windows-1251
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DefaultCharset</CODE> directive sets the default character set
+to use for client connections. The default character set is
+<CODE>utf-8</CODE> but is overridden by the character set for the language
+specified by the client or the <CODE>DefaultLanguage</CODE> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DefaultLanguage de
+DefaultLanguage en
+DefaultLanguage es
+DefaultLanguage fr
+DefaultLanguage it
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DefaultLanguage</CODE> directive specifies the default language
+to use for client connections. Setting the default language also sets the
+default character set if a language localization file exists for it. The
+default language is "en" for English.
+
+<!-- NEED 5in -->
+<H3><A NAME="Deny">Deny</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Deny from All
+Deny from None
+Deny from *.domain.com
+Deny from .domain.com
+Deny from host.domain.com
+Deny from nnn.*
+Deny from nnn.nnn.*
+Deny from nnn.nnn.nnn.*
+Deny from nnn.nnn.nnn.nnn
+Deny from nnn.nnn.nnn.nnn/mm
+Deny from nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+Deny from @LOCAL
+Deny from @IF(name)
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Deny</CODE> directive specifies a hostname, IP address, or
+network that is allowed access to the server. <CODE>Deny</CODE>
+directives are cummulative, so multiple <CODE>Deny</CODE> directives
+can be used to allow access for multiple hosts or networks. The
+<CODE>/mm</CODE> notation specifies a CIDR netmask:
+
+<CENTER><TABLE BORDER="1">
+<TR>
+ <TH WIDTH="10%">mm</TH>
+ <TH WIDTH="20%">netmask</TH>
+ <TH WIDTH="10%">mm</TH>
+ <TH WIDTH="20%">netmask</TH>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">0</TD>
+ <TD ALIGN="CENTER">0.0.0.0</TD>
+ <TD ALIGN="CENTER">8</TD>
+ <TD ALIGN="CENTER">255.0.0.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">1</TD>
+ <TD ALIGN="CENTER">128.0.0.0</TD>
+ <TD ALIGN="CENTER">16</TD>
+ <TD ALIGN="CENTER">255.255.0.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">2</TD>
+ <TD ALIGN="CENTER">192.0.0.0</TD>
+ <TD ALIGN="CENTER">24</TD>
+ <TD ALIGN="CENTER">255.255.255.0</TD>
+</TR>
+<TR>
+ <TD ALIGN="CENTER">...</TD>
+ <TD ALIGN="CENTER">...</TD>
+ <TD ALIGN="CENTER">32</TD>
+ <TD ALIGN="CENTER">255.255.255.255</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>The <CODE>@LOCAL</CODE> name will deny access from all local
+network interfaces, but not remote point-to-point interfaces. The
+<CODE>@IF(name)</CODE> name will deny access from the named
+interface.
+
+<P>The <CODE>Deny</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="DocumentRoot">DocumentRoot</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DocumentRoot /usr/share/doc/cups
+DocumentRoot /foo/bar/doc/cups
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DocumentRoot</CODE> directive specifies the location of
+web content for the HTTP server in CUPS. If an absolute path is not
+specified then it is assumed to be relative to the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+default directory is <VAR>/usr/share/doc/cups</VAR>.
+
+<P>Documents are first looked up in a sub-directory for the primary
+language requested by the client (e.g. <VAR>/usr/share/doc/cups/fr/...</VAR>)
+and then directly under the <CODE>DocumentRoot</CODE> directory
+(e.g. <VAR>/usr/share/doc/cups/...</VAR>), so it is possible to localize
+the web content by providing subdirectories for each language needed.
+
+<!-- NEED 3in -->
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Encryption</CODE> directive must appear instead a
+<A HREF="#Location"><CODE>Location</CODE></A>
+section and specifies the encryption settings for that location.
+The default setting is <CODE>IfRequested</CODE> for all locations.
+
+<!-- NEED 3in -->
+<H3><A NAME="ErrorLog">ErrorLog</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ErrorLog /var/log/cups/error_log
+ErrorLog /var/log/cups/error_log-%s
+ErrorLog syslog
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ErrorLog</CODE> directive sets the name of the error log
+file. If the filename is not absolute then it is assumed to be relative
+to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+default error log file is <VAR>/var/log/cups/error_log</VAR>.
+
+<P>The server name can be included in the filename by using
+<CODE>%s</CODE> in the name.
+
+<P>The special name "syslog" can be used to send the error information
+to the system log instead of a plain file.
+
+
+<!-- NEED 2in -->
+<H3><A NAME="FaxRetryInterval">FaxRetryInterval</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FaxRetryInterval 300
+FaxRetryInterval 30
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FaxRetryInterval</CODE> directive determines how
+often fax print jobs are retried when the backend is unable to
+send the fax. The value is the number of seconds between tries.
+
+<P>The default setting is <CODE>300</CODE> seconds.
+
+
+<!-- NEED 2in -->
+<H3><A NAME="FaxRetryLimit">FaxRetryLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FaxRetryLimit 5
+FaxRetryLimit 100
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FaxRetryLimit</CODE> directive determines how many
+times a fax job is retried before it is canceled.
+
+<P>The default setting is <CODE>5</CODE>.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="FileDevice">FileDevice</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FileDevice Yes
+FileDevice No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FileDevice</CODE> directive determines whether the
+scheduler allows new printers to be added using device URIs of the
+form <CODE>file:/filename</CODE>. File devices are most often used
+to test new printer drivers and do no support raw file printing.
+
+<P>The default setting is <CODE>No</CODE>.
+
+<CENTER><TABLE WIDTH="80%" BGCOLOR="#cccccc" CELLPADDING="5" BORDER="1">
+<TR>
+ <TD>
+
+ <B>Note:</B>
+
+ <P>File devices are managed by the scheduler. Since the
+ scheduler normally runs as the root user, file devices
+ can be used to overwrite system files and potentially
+ gain unauthorized access to the system. If you must
+ create printers using file devices, we recommend that
+ you set the <CODE>FileDevice</CODE> directive to
+ <CODE>Yes</CODE> for only as long as you need to add the
+ printers to the system, and then reset the directive to
+ <CODE>No</CODE>.
+
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+
+<!-- NEED 3in -->
+<H3><A NAME="FilterLimit">FilterLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FilterLimit 0
+FilterLimit 200
+FilterLimit 1000
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FilterLimit</CODE> directive sets the maximum cost
+of all running job filters. It can be used to limit the number
+of filter programs that are run on a server to minimize disk,
+memory, and CPU resource problems. A limit of 0 disables filter
+limiting.
+
+<P>An average print to a non-PostScript printer needs a filter
+limit of about 200. A PostScript printer needs about half that
+(100). Setting the limit below these thresholds will effectively
+limit the scheduler to printing a single job at any time.
+
+<P>The default limit is 0.
+
+<!-- NEED 3in -->
+<H3><A NAME="FilterNice">FilterNice</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FilterNice 0
+FilterNice 39
+FilterNice -10
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FilterNice</CODE> directive sets the scheduling
+priority of job filters. Values larger than 0 give filters a
+lower priority while values smaller than 0 give filters a higher
+priority. The <CODE>FilterNice</CODE> value does not affect the
+priority of job backends.
+
+<P>The default priority is 0.
+
+<!-- NEED 3in -->
+<H3><A NAME="FontPath">FontPath</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+FontPath /foo/bar/fonts
+FontPath /usr/share/cups/fonts:/foo/bar/fonts
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>FontPath</CODE> directive specifies the font path to use when
+searching for fonts. The default font path is
+<CODE>/usr/share/cups/fonts</CODE>.
+
+<!-- NEED 3in -->
+<H3><A NAME="Group">Group</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Group sys
+Group system
+Group root
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Group</CODE> directive specifies the UNIX group that
+filter and CGI programs run as. The default group is <CODE>sys</CODE>,
+<CODE>system</CODE>, or <CODE>root</CODE> depending on the operating
+system.
+
+<!-- NEED 3in -->
+<H3><A NAME="HideImplicitMembers">HideImplicitMembers</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+HideImplicitMembers Yes
+HideImplicitMembers No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>HideImplicitMembers</CODE> directive controls
+whether the individual printers in an implicit class are shown
+to the user. The default is <CODE>No</CODE>.</P>
+
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+must be enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+HostNameLookups On
+HostNameLookups Off
+HostNameLookups Double
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>HostNameLookups</CODE> directive controls whether
+or not CUPS looks up the hostname for connecting clients. The
+<CODE>Double</CODE> setting causes CUPS to verify that the
+hostname resolved from the address matches one of the addresses
+returned for that hostname. <CODE>Double</CODE> lookups also
+prevent clients with unregistered addresses from connecting
+to your server.
+
+The default is <CODE>Off</CODE> to avoid the potential server
+performance problems with hostname lookups. Set this option to
+<CODE>On</CODE> or <CODE>Double</CODE> only if absolutely
+required.
+
+<!-- NEED 3in -->
+<H3><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ImplicitAnyClasses On
+ImplicitAnyClasses Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ImplicitAnyClasses</CODE> directive controls
+whether implicit classes for local and remote printers are
+created with the name <CODE>AnyPrinter</CODE>. The default
+setting is <CODE>Off</CODE>.</P>
+
+<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
+must be enabled for this directive to have any effect.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ImplicitClasses">ImplicitClasses</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ImplicitClasses On
+ImplicitClasses Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ImplicitClasses</CODE> directive controls whether implicit
+classes are created based upon the available network printers and classes.
+The default setting is <CODE>On</CODE> but is automatically turned
+<CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A> is
+turned <CODE>Off</CODE>.
+
+<!-- NEED 3in -->
+<H3><A NAME="Include">Include</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Include filename
+Include /foo/bar/filename
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Include</CODE> directive includes the named file in
+the <CODE>cupsd.conf</CODE> file. If no leading path is
+provided, the file is assumed to be relative to the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="KeepAlive">KeepAlive</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+KeepAlive On
+KeepAlive Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>KeepAlive</CODE> directive controls whether or not to support
+persistent HTTP connections. The default is <CODE>On</CODE>.
+
+<P>HTTP/1.1 clients automatically support persistent connections, while
+HTTP/1.0 clients must specifically request them using the
+<CODE>Keep-Alive</CODE> attribute in the <CODE>Connection:</CODE>
+field of each request.
+
+<!-- NEED 3in -->
+<H3><A NAME="KeepAliveTimeout">KeepAliveTimeout</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+KeepAliveTimeout 60
+KeepAliveTimeout 30
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long a
+persistent HTTP connection will remain open after the last request. The
+default is 60 seconds.
+
+<!-- NEED 3in -->
+<H3><A NAME="Limit">Limit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;Limit GET POST&gt;
+...
+&lt;/Limit&gt;
+
+&lt;Limit ALL&gt;
+...
+&lt;/Limit&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Limit</CODE> directive groups access control directives for
+specific types of HTTP requests and must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> section. Access can be limited
+for individual request types (<CODE>DELETE</CODE>, <CODE>GET</CODE>,
+<CODE>HEAD</CODE>, <CODE>OPTIONS</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE>,
+and <CODE>TRACE</CODE>) or for all request types (<CODE>ALL</CODE>). The
+request type names are case-sensitive for compatibility with Apache.
+
+<!-- NEED 3in -->
+<H3><A NAME="LimitExcept">LimitExcept</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;LimitExcept GET POST&gt;
+...
+&lt;/LimitExcept&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>LimitExcept</CODE> directive groups access control directives for
+specific types of HTTP requests and must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> section. Unlike the
+<A HREF="#Limit"><CODE>Limit</CODE></A> directive, <CODE>LimitExcept</CODE>
+restricts access for all requests <I>except</I> those listed on the
+<CODE>LimitExcept</CODE> line.
+
+<!-- NEED 3in -->
+<H3><A NAME="LimitRequestBody">LimitRequestBody</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+LimitRequestBody 10485760
+LimitRequestBody 10m
+LimitRequestBody 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>LimitRequestBody</CODE> directive controls the maximum size of
+print files, IPP requests, and HTML form data in HTTP POST requests. The
+default limit is 0 which disables the limit check.
+
+<P>Also see the identical
+<A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="Listen">Listen</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Listen 127.0.0.1:631
+Listen 192.0.2.1:631
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Listen</CODE> directive specifies a network address and port
+to listen for connections. Multiple <CODE>Listen</CODE> directives can be
+provided to listen on multiple addresses.
+
+<P>The <CODE>Listen</CODE> directive is similar to the
+<A HREF="#Port"><CODE>Port</CODE></A> directive but allows you to restrict
+access to specific interfaces or networks.
+
+<!-- NEED 3in -->
+<H3><A NAME="Location">Location</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;Location /&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /admin&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /printers/name&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /classes&gt;
+...
+&lt;/Location&gt;
+
+&lt;Location /classes/name&gt;
+...
+&lt;/Location&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Location</CODE> directive specifies access control and
+authentication options for the specified HTTP resource or path.
+The
+<A HREF="#Allow"><CODE>Allow</CODE></A>,
+<A HREF="#AuthClass"><CODE>AuthClass</CODE></A>,
+<A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>,
+<A HREF="#AuthType"><CODE>AuthType</CODE></A>,
+<A HREF="#Deny"><CODE>Deny</CODE></A>,
+<A HREF="#Encryption"><CODE>Encryption</CODE></A>,
+<A HREF="#Limit"><CODE>Limit</CODE></A>,
+<A HREF="#LimitExcept"><CODE>LimitExcept</CODE></A>,
+<A HREF="#Order"><CODE>Order</CODE></A>,
+<A HREF="#Require"><CODE>Require</CODE></A>, and
+<A HREF="#Satisfy"><CODE>Satisfy</CODE></A>
+directives may all appear inside a location.
+
+<CENTER><TABLE BORDER="1"><CAPTION>Locations on the Server.</CAPTION>
+<TR><TH>Location</TH><TH>Description</TH></TR>
+<TR><TD>/</TD><TD>The path for all get operations (get-printers, get-jobs, etc.)</TD></TR>
+<TR><TD>/admin</TD><TD>The path for all administration operations (add-printer, delete-printer, start-printer, etc.)</TD></TR>
+<TR><TD>/admin/conf</TD><TD>The path for access to the CUPS configuration files (cupsd.conf, client.conf, etc.)</TD></TR>
+<TR><TD>/classes</TD><TD>The path for all classes</TD></TR>
+<TR><TD>/classes/name</TD><TD>The resource for class <CODE>name</CODE></TD></TR>
+<TR><TD>/jobs</TD><TD>The path for all jobs (hold-job, release-job, etc.)</TD></TR>
+<TR><TD>/jobs/id</TD><TD>The resource for job <CODE>id</CODE></TD></TR>
+<TR><TD>/printers</TD><TD>The path for all printers</TD></TR>
+<TR><TD>/printers/name</TD><TD>The path for printer <CODE>name</CODE></TD></TR>
+<TR><TD>/printers/name.ppd</TD><TD>The PPD file path for printer <CODE>name</CODE></TD></TR>
+</TABLE></CENTER>
+
+<P>Note that more specific resources override the less specific ones.
+So the directives inside the <CODE>/printers/name</CODE> location will override ones from <CODE>/printers</CODE>.
+Directives inside <CODE>/printers</CODE> will override ones from <CODE>/</CODE>. &nbsp;
+None of the directives are inherited.
+More information can be found in section <A HREF="#PRINTING_SECURITY">"Printing System Security"</A>.
+
+<!-- NEED 3in -->
+<H3><A NAME="LogFilePerm">LogFilePerm</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+LogFilePerm 0644
+LogFilePerm 0600
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>LogFilePerm</CODE> directive specifies the permissions
+to use when writing configuration files. The default is 0644.
+
+<!-- NEED 3in -->
+<H3><A NAME="LogLevel">LogLevel</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+LogLevel none
+LogLevel emerg
+LogLevel alert
+LogLevel crit
+LogLevel error
+LogLevel warn
+LogLevel notice
+LogLevel info
+LogLevel debug
+LogLevel debug2
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>LogLevel</CODE> directive specifies the level of logging
+for the <A HREF="#ErrorLog"><CODE>ErrorLog</CODE></A> file. The
+following values are recognized (each level logs everything under the
+preceding levels):
+
+<UL>
+
+ <LI><CODE>none</CODE> - Log nothing.
+
+ <LI><CODE>emerg</CODE> - Log emergency conditions that prevent the
+ server from running.
+
+ <LI><CODE>alert</CODE> - Log alerts that must be handled immediately.
+
+ <LI><CODE>crit</CODE> - Log critical errors that don't prevent
+ the server from running.
+
+ <LI><CODE>error</CODE> - Log general errors.
+
+ <LI><CODE>warn</CODE> - Log errors and warnings.
+
+ <LI><CODE>notice</CODE> - Log temporary error conditions.
+
+ <LI><CODE>info</CODE> - Log all requests and state changes (default).
+
+ <LI><CODE>debug</CODE> - Log basic debugging information.
+
+ <LI><CODE>debug2</CODE> - Log all debugging information.
+
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClients">MaxClients</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxClients 100
+MaxClients 1024
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxClients</CODE> directive controls the maximum number of
+simultaneous clients that will be allowed by the server. The default is
+100 clients.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>Since each print job requires a file descriptor for the
+ status pipe, the CUPS server internally limits the
+ <CODE>MaxClients</CODE> value to 1/3 of the available file descriptors
+ to avoid possible problems when printing large numbers of jobs.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxClientsPerHost">MaxClientsPerHost</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxClientsPerHost 0
+MaxClientsPerHost 10
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxClientsPerHost</CODE> directive controls the
+maximum number of simultaneous clients that will be allowed from
+a single host by the server. The default is the
+<CODE>MaxClients</CODE> value. A value of 0 uses the automatic
+setting based on the <CODE>MaxClients</CODE> value.</P>
+
+<P>This directive provides a small measure of protection against
+Denial of Service attacks from a single host.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxCopies">MaxCopies</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxCopies 100
+MaxCopies 65535
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxCopies</CODE> directive controls the maximum
+number of copies that a user can print of a job. The default is
+100 copies.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>Most HP PCL laser printers internally limit the
+ number of copies to 100.
+
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxJobs">MaxJobs</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxJobs 100
+MaxJobs 9999
+MaxJobs 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxJobs</CODE> directive controls the maximum number of jobs
+that are kept in memory. Once the number of jobs reaches the limit, the
+oldest completed job is automatically purged from the system to make room
+for the new one. If all of the known jobs are still pending or active then
+the new job will be rejected.
+
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 500.
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum number of active jobs
+that are allowed for each printer or class. Once a printer or class reaches the limit, new jobs will be
+rejected until one of the active jobs is completed, stopped, aborted, or cancelled.
+
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 0.
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum number of active jobs
+that are allowed for each user. Once a user reaches the limit, new jobs will be
+rejected until one of the active jobs is completed, stopped, aborted, or cancelled.
+
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 0.
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxLogSize 1048576
+MaxLogSize 1m
+MaxLogSize 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxLogSize</CODE> directive controls the maximum size of each
+log file. Once a log file reaches or exceeds the maximum size it is closed
+and renamed to <VAR>filename.O</VAR>. This allows you to rotate the logs
+automatically. The default size is 1048576 bytes (1MB).
+
+<P>Setting the maximum size to 0 disables log rotation.
+
+<!-- NEED 3in -->
+<H3><A NAME="MaxRequestSize">MaxRequestSize</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+MaxRequestSize 10485760
+MaxRequestSize 10m
+MaxRequestSize 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>MaxRequestSize</CODE> directive controls the maximum size of
+print files, IPP requests, and HTML form data in HTTP POST requests. The
+default limit is 0 which disables the limit check.
+
+<P>Also see the identical
+<A HREF="#LimitRequestBody"><CODE>LimitRequestBody</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="Order">Order</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Order Allow,Deny
+Order Deny,Allow
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Order</CODE> directive defines the default access control.
+The following values are supported:
+
+<UL>
+
+ <LI><CODE>Allow,Deny</CODE> - Allow requests from all
+ systems <I>except</I> for those listed in a <CODE>Deny</CODE>
+ directive.
+
+ <LI><CODE>Deny,Allow</CODE> - Allow requests only from
+ those listed in an <CODE>Allow</CODE> directive.
+
+</UL>
+
+<P>The <CODE>Order</CODE> directive must appear inside a
+<A HREF="#Location"><CODE>Location</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="PageLog">PageLog</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PageLog /var/log/cups/page_log
+PageLog /var/log/cups/page_log-%s
+PageLog syslog
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PageLog</CODE> directive sets the name of the page log
+file. If the filename is not absolute then it is assumed to be relative
+to the <A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+default page log file is <VAR>/var/log/cups/page_log</VAR>.
+
+<P>The server name can be included in the filename by using
+<CODE>%s</CODE> in the name.
+
+<P>The special name "syslog" can be used to send the page information
+to the system log instead of a plain file.
+
+<!-- NEED 3in -->
+<H3><A NAME="Port">Port</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Port 631
+Port 80
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Port</CODE> directive specifies a port to listen
+on. Multiple <CODE>Port</CODE> lines can be specified to listen
+on multiple ports. The <CODE>Port</CODE> directive is equivalent
+to "<CODE>Listen *:nnn</CODE>". The default port is 631.
+
+<!-- NEED 3in -->
+<H3><A NAME="PreserveJobFiles">PreserveJobFiles</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PreserveJobFiles On
+PreserveJobFiles Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PreserveJobFiles</CODE> directive controls whether the
+document files of completed, cancelled, or aborted print jobs are
+stored on disk.
+
+<P>A value of <CODE>On</CODE> preserves job files until the
+administrator purges them with the <CODE>cancel</CODE> command. Jobs
+can be restarted (and reprinted) as desired until they are purged.
+
+<P>A value of <CODE>Off</CODE> (the default) removes the job files as
+soon as each job is completed, cancelled, or aborted.
+
+<!-- NEED 3in -->
+<H3><A NAME="PreserveJobHistory">PreserveJobHistory</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PreserveJobHistory On
+PreserveJobHistory Off
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PreserveJobHistory</CODE> directive controls whether
+the history of completed, cancelled, or aborted print jobs is stored
+on disk.
+
+<P>A value of <CODE>On</CODE> (the default) preserves job information
+until the administrator purges it with the <CODE>cancel</CODE>
+command.
+
+<P>A value of <CODE>Off</CODE> removes the job information as soon as
+each job is completed, cancelled, or aborted.
+
+<!-- NEED 3in -->
+<H3><A NAME="Printcap">Printcap</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Printcap
+Printcap /etc/printcap
+Printcap /etc/printers.conf
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Printcap</CODE> directive controls whether or not a
+printcap file is automatically generated and updated with a list
+of available printers. If specified with no value, then no
+printcap file will be generated. The default is to generate a
+file named <VAR>/etc/printcap</VAR>.
+
+<P>When a filename is specified (e.g. <VAR>/etc/printcap</VAR>), the
+printcap file is written whenever a printer is added or removed. The
+printcap file can then be used by applications that are hardcoded to
+look at the printcap file for the available printers.
+
+<!-- NEED 3in -->
+<H3><A NAME="PrintcapFormat">PrintcapFormat</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PrintcapFormat BSD
+PrintcapFormat Solaris
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PrintcapFormat</CODE> directive controls the output
+format of the printcap file. The default is to generate a BSD
+printcap file.
+
+<!-- NEED 3in -->
+<H3><A NAME="PrintcapGUI">PrintcapGUI</A></H3>
+<HR>
+
+<H4>Example</H4>
+
+<UL><PRE>
+PrintcapGUI /usr/bin/glpoptions
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PrintcapGUI</CODE> directive sets the program to
+use when displaying an option panel from an IRIX application
+that uses the Impressario print API. The default program is the
+ESP Print Pro "glpoptions" GUI.
+
+<P>The program must accept the <CODE>-d</CODE> option to specify
+a printer and the <CODE>-o</CODE> option to specify one or more
+options. After allowing the user to select/change options, the
+program must then write the list of printing options without the
+<CODE>-o</CODE> to the standard output.
+
+<!-- NEED 3in -->
+<H3><A NAME="ReloadTimeout">ReloadTimeout</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ReloadTimeout 60
+ReloadTimeout 3600
+ReloadTimeout 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ReloadTimeout</CODE> directive sets how long the
+scheduler waits for jobs to complete before reloading the server
+configuration. The default timeout is 60 seconds.
+
+<!-- NEED 3in -->
+<H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+RemoteRoot remroot
+RemoteRoot root
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>RemoteRoot</CODE> directive sets the username for
+unauthenticated root requests from remote hosts. The default
+username is <VAR>remroot</VAR>. Setting <CODE>RemoteRoot</CODE>
+to <VAR>root</VAR> effectively disables this security mechanism.
+
+<!-- NEED 3in -->
+<H3><A NAME="RequestRoot">RequestRoot</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+RequestRoot /var/spool/cups
+RequestRoot /foo/bar/spool/cups
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>RequestRoot</CODE> directive sets the directory for
+incoming IPP requests and HTML forms. If an absolute path is not
+provided then it is assumed to be relative to the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+default request directory is <VAR>/var/spool/cups</VAR>.
+
+<!-- NEED 4in -->
+<H3><A NAME="Require">Require</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Require group foo bar
+Require user john mary
+Require valid-user
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Require</CODE> directive specifies that
+authentication is required for the resource. The
+<CODE>group</CODE> keyword specifies that the authenticated user
+must be a member of one or more of the named groups that follow.
+
+<P>The <CODE>user</CODE> keyword specifies that the
+authenticated user must be one of the named users that follow.
+
+<P>The <CODE>valid-user</CODE> keyword specifies that any
+authenticated user may access the resource.
+
+<P>The default is to do no authentication. This directive must
+appear inside a <A HREF="#Location"><CODE>Location</CODE></A>
+directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="RIPCache">RIPCache</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+RIPCache 8m
+RIPCache 1g
+RIPCache 2048k
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>RIPCache</CODE> directive sets the size of the memory
+cache used by Raster Image Processor ("RIP") filters such as
+<CODE>imagetoraster</CODE> and <CODE>pstoraster</CODE>. The size can
+be suffixed with a "k" for kilobytes, "m" for megabytes, or
+"g" for gigabytes. The default cache size is "8m", or 8 megabytes.
+
+<!-- NEED 3in -->
+<H3><A NAME="RootCertDuration">RootCertDuration</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+RootCertDuration 300
+RootCertDuration 0
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>RootCertDuration</CODE> directive controls the
+interval between updates of the root authentication certificate.
+The default is <CODE>300</CODE> seconds which updates the root
+certificate approximately once every 5 minutes. Set the interval
+to 0 to disable certificate updates entirely.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="RunAsUser">RunAsUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+RunAsUser Yes
+RunAsUser No
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>RunAsUser</CODE> directive controls whether the
+scheduler runs as the unpriviledged user account (usually <CODE>lp</CODE>).
+The default is <CODE>No</CODE> which leaves the scheduler running as
+the <CODE>root</CODE> user.
+
+<P><B>Note:</B> Running as a non-priviledged user may prevent
+LPD and locally connected printers from working due to
+permission problems. The <CODE>lpd</CODE> backend will
+automatically use a non-priviledged mode that is not 100%
+compliant with RFC 1179. The <CODE>parallel</CODE>,
+<CODE>serial</CODE>, and <CODE>usb</CODE> backends will need
+write access to the corresponding device files.
+
+<!-- NEED 3in -->
+<H3><A NAME="Satisfy">Satisfy</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Satisfy all
+Satisfy any
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Satisfy</CODE> directive specifies whether all
+conditions must be satisfied to allow access to the resource. If
+set to <CODE>all</CODE>, then all authentication and access
+control conditions must be satified to allow access.
+
+<P>Setting <CODE>Satisfy</CODE> to <CODE>any</CODE> allows a user to
+gain access if the authentication or access control requirements are
+satisfied. For example, you might require authentication for remote
+access, but allow local access without authentication.
+
+<P>The default is <CODE>all</CODE>. This directive must appear
+inside a <A HREF="#Location"><CODE>Location</CODE></A>
+directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerAdmin">ServerAdmin</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerAdmin user@host
+ServerAdmin root@foo.bar.com
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerAdmin</CODE> directive identifies the email address for the
+administrator on the system. By default the administrator email address is
+<CODE>root@server</CODE>, where <CODE>server</CODE> is the server name.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerBin">ServerBin</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerBin /usr/lib/cups
+ServerBin /foo/bar/lib/cups
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerBin</CODE> directive sets the directory for
+server-run executables. If an absolute path is not provided then it is
+assumed to be relative to the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directory. The
+default executable directory is <VAR>/usr/lib/cups</VAR>.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerCertificate">ServerCertificate</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerCertificate /etc/cups/ssl/server.crt
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerCertificate</CODE> directive specifies the
+location of the SSL certificate file used by the server when
+negotiating encrypted connections. The certificate must not be
+encrypted (password protected) since the scheduler normally runs
+in the background and will be unable to ask for a password.
+The default certificate file is <VAR>/etc/cups/ssl/server.crt</VAR>.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerKey">ServerKey</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerKey /etc/cups/ssl/server.key
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerKey</CODE> directive specifies the location
+of the SSL private key file used by the server when negotiating
+encrypted connections. The default key file is
+<VAR>/etc/cups/ssl/server.crt</VAR>.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerName"></A>ServerName</H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerName foo.domain.com
+ServerName myserver.domain.com
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerName</CODE> directive specifies the hostname that is
+reported to clients. By default the server name is the hostname.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerRoot">ServerRoot</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerRoot /etc/cups
+ServerRoot /foo/bar/cups
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerRoot</CODE> directive specifies the absolute path to
+the server configuration and state files. It is also used to resolve
+relative paths in the <VAR>cupsd.conf</VAR> file. The default server
+directory is <VAR>/etc/cups</VAR>.
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerTokens">ServerTokens</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerTokens None
+ServerTokens ProductOnly
+ServerTokens Major
+ServerTokens Minor
+ServerTokens Minimal
+ServerTokens OS
+ServerTokens Full
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerTokens</CODE> directive specifies the information
+that is included in the Server header of HTTP responses. The default value
+is <tt>Minor</tt> which generates "CUPS/1.1".
+
+<!-- NEED 3in -->
+<H3><A NAME="SSLListen">SSLListen</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+SSLListen 127.0.0.1:443
+SSLListen 192.0.2.1:443
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>SSLListen</CODE> directive specifies a network
+address and port to listen for secure connections. Multiple
+<CODE>SSLListen</CODE> directives can be provided to listen on
+multiple addresses.
+
+<P>The <CODE>SSLListen</CODE> directive is similar to the
+<A HREF="#SSLPort"><CODE>SSLPort</CODE></A> directive but allows
+you to restrict access to specific interfaces or networks.
+
+<!-- NEED 3in -->
+<H3><A NAME="SSLPort">SSLPort</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+SSLPort 443
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>SSLPort</CODE> directive specifies a port to listen
+on for secure connections. Multiple <CODE>SSLPort</CODE> lines
+can be specified to listen on multiple ports.
+
+<!-- NEED 3in -->
+<H3><A NAME="SystemGroup">SystemGroup</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+SystemGroup sys
+SystemGroup system
+SystemGroup root
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>SystemGroup</CODE> directive specifies the system
+administration group for <CODE>System</CODE> authentication. More
+information can be found later in this chapter in
+<A HREF="#PRINTING_SECURITY">"Printing System Security"</A>.
+
+<!-- NEED 3in -->
+<H3><A NAME="TempDir">TempDir</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+TempDir /var/tmp
+TempDir /foo/bar/tmp
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>TempDir</CODE> directive specifies an absolute path for
+the directory to use for temporary files. The default directory is
+<VAR>/var/tmp</VAR>.
+
+<P>Temporary directories must be world-writable and should have the
+"sticky" permission bit enabled so that other users cannot delete
+filter temporary files. The following commands will create an
+appropriate temporary directory called <VAR>/foo/bar/tmp</VAR>:
+
+<UL><PRE>
+<B>mkdir /foo/bar/tmp ENTER</B>
+<B>chmod a+rwxt /foo/bar/tmp ENTER</B>
+</PRE></UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Timeout">Timeout</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Timeout 300
+Timeout 90
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Timeout</CODE> directive controls the amount of time to
+wait before an active HTTP or IPP request times out. The default
+timeout is 300 seconds.
+
+<!-- NEED 3in -->
+<H3><A NAME="User">User</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+User lp
+User guest
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>User</CODE> directive specifies the UNIX user that
+filter and CGI programs run as. The default user is <CODE>lp</CODE>.
+
+
+
+<H2>Changing the Client Configuration</H2>
+
+<P>The CUPS client application (<CODE>lp</CODE>, <CODE>lpr</CODE>, and so forth)
+use the <VAR>/etc/cups/client.conf</VAR> file for default settings.
+The client application also look in the user's home directory for a file called <VAR>.cupsrc</VAR>.
+Each directive is listed on a line by itself followed by its value. Comments are introduced
+using the number sign ("#") character at the beginning of a line.
+
+<P>Since the client configuration file consists of plain text, you can
+use your favorite text editor to make changes to it.
+
+<!-- NEED 4in -->
+<H2>Client Directives</H2>
+
+<P>The <VAR>client.conf</VAR> file contains two directives that
+determine how the client behaves:</P>
+
+<UL>
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#Encryption"><CODE>Encryption</CODE></A>
+ <LI><A HREF="#ServerName"><CODE>ServerName</CODE></A>
+
+</TD>
+</TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Encryption">Encryption</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Encryption Never
+Encryption IfRequested
+Encryption Required
+Encryption Always
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Encryption</CODE> directive specifies the default encryption settings for the client.
+The default setting is <VAR>IfRequested</VAR>.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="ServerName">ServerName</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+ServerName foo.bar.com
+ServerName 11.22.33.44
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>ServerName</CODE> directive specifies sets the remote server that is to be used
+for all client operations. That is, it redirects all client requests to the remote server.
+
+The default is to use the local server ("<VAR>localhost</VAR>").
+
+
+<!-- NEW PAGE -->
+<H2>Changing the Printer Configuration</H2>
+
+<P>The CUPS scheduler (cupsd) uses the <VAR>/etc/cups/printers.conf</VAR> file
+to store the list of available printers. This file contains only locally defined
+printers, but not remote printers that are created automatically. Each directive
+is listed on a line by itself followed by its value. Comments are introduced
+using the number sign ("#") character at the beginning of a line.
+
+<P>Since the printer configuration file consists of plain text, you can
+use your favorite text editor to make changes to it.
+
+<!-- NEED 4in -->
+<H2>Printer Directives</H2>
+
+<P>The <VAR>printers.conf</VAR> file contains many directives that
+determine how the printer behaves:</P>
+
+<UL>
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#Accepting"><CODE>Accepting</CODE></A>
+ <LI><A HREF="#AllowUser"><CODE>AllowUser</CODE></A>
+ <LI><A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A>
+ <LI><A HREF="#DenyUser"><CODE>DenyUser</CODE></A>
+ <LI><A HREF="#DeviceURI"><CODE>DeviceURI</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#Info"><CODE>Info</CODE></A>
+ <LI><A HREF="#JobSheets"><CODE>JobSheets</CODE></A>
+ <LI><A HREF="#KLimit"><CODE>KLimit</CODE></A>
+ <LI><A HREF="#PrinterLocation"><CODE>Location</CODE></A>
+ <LI><A HREF="#PageLimit"><CODE>PageLimit</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#Printer"><CODE>Printer</CODE></A>
+<LI><A HREF="#QuotaPeriod"><CODE>QuotaPeriod</CODE></A>
+<LI><A HREF="#State"><CODE>State</CODE></A>
+<LI><A HREF="#StateMessage"><CODE>StateMessage</CODE></A>
+
+</TD>
+</TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="Accepting">Accepting</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Accepting yes
+
+Accepting no
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Accepting</CODE> directive defines the initial Boolean
+value for the <VAR>printer-is-accepting-job</VAR> attribute which can
+be set by the <CODE>accept</CODE> and <CODE>reject</CODE> commands.
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="AllowUser">AllowUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AllowUser foo_user
+AllowUser bar_user
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AllowUser</CODE> directive adds a username to the
+<VAR>requesting-user-name-allowed</VAR> attribute which can be set
+by the <CODE>lpadmin -u</CODE> command.
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="DefaultPrinter">DefaultPrinter</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;DefaultPrinter name/&gt;
+...
+&lt;/Printer&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DefaultPrinter</CODE> directive begins a printer definition
+for the default server destination.
+It can be added by the <CODE>lpadmin</CODE> command or if already defined,
+set as default by the <CODE>lpoptions -d</CODE> command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DenyUser">DenyUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DenyUser foo_user
+DenyUser bar_user
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DenyUser</CODE> directive adds a username to the
+<VAR>requesting-user-name-allowed</VAR> attribute which can be set
+by the <CODE>lpadmin -u</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DeviceURI">DeviceURI</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DeviceURI socket://foo.bar.com:9100
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DeviceURI</CODE> directive defines the value of the
+<VAR>device-uri-attribute</VAR> attribute which can be set by
+the <CODE>lpadmin -v</CODE> command.
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="Info">Info</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Info My Printer
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Info</CODE> directive defines the string for the
+<VAR>printer-info</VAR> attribute which can be set by the
+<CODE>lpadmin -D</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="JobSheets">JobSheets</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+JobSheets none,standard
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>JobSheets</CODE> directive specifies the default banner pages
+to print before and after a print job.
+In the above example, only a <VAR>standard</VAR> banner will print after each job.</P>
+
+<P>The <CODE>lpoptions -o job-sheets=</CODE> command can be used to set banners.
+For example, the following command would produce the same results of a
+<VAR>standard</VAR> banner at the end of each print job for the default printer.</P>
+
+<UL><B>
+lpoptions -o job-sheets=none,standard
+</B></UL>
+
+<P>If only one banner file is specified, it will be printed before the
+files in the job. If a second banner file is specified, it is printed
+after the files in the job.</P>
+
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot; label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot; label at the top and bottom.</LI>
+</UL>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="KLimit">KLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+KLimit 1234
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>KLimit</CODE> directive defines the value of the
+<VAR>job-k-limit</VAR> attribute which can be set by the
+<CODE>lpadmin -o job-k-limit=</CODE> command.
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="PrinterLocation">Location</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Location Building 3321
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Location</CODE> directive defines the string for the
+<VAR>printer-location</VAR> attribute which can be set by the
+<CODE>lpadmin -L</CODE> command.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>Do not confuse this <CODE>Location</CODE> directive with the
+ one in cupsd.conf. They are completely different.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="PageLimit">PageLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PageLimit 1234
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PageLimit</CODE> directive defines the value of the
+<VAR>job-page-limit</VAR> attribute which can be set
+by the <CODE>lpadmin -o job-page-limit=</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="Printer">Printer</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;Printer name/&gt;
+...
+&lt;/Printer&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Printer</CODE> directive begins a printer definition.
+It can be added by the <CODE>lpadmin</CODE> command.
+
+<!-- NEED 3in -->
+<H3><A NAME="QuotaPeriod">QuotaPeriod</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+QuotaPeriod 604800
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>QuotaPeriod</CODE> directive defines the value of the
+<VAR>job-quota-period</VAR> attribute which can be set
+by the <CODE>lpadmin -o job-quota-period=</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="State">State</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+State stopped
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>State</CODE> directive defines the initial value of the
+<VAR>printer-state</VAR> attribute. The strings <VAR>idle</VAR> and
+<VAR>stopped</VAR> correspond to the IPP enumeration values.</P>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+<!-- NEED 6in -->
+<H3><A NAME="StateMessage">StateMessage</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+StateMessage Ready to print.
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>StateMessage</CODE> directive defines the initial string for the
+<VAR>printer-state-message</VAR> attribute.
+The following are some example messages:</P>
+
+<UL>
+<LI>Connected to <VAR>host_name</VAR>...
+<LI>Connecting to <VAR>printer_queue</VAR> on port <VAR>port_number</VAR>...
+<LI>Network host <VAR>host_name</VAR> is busy; will retry in 30 seconds...
+<LI>Printer busy; will retry in 10 seconds...
+<LI>Printer is busy; retrying print job...
+<LI>Print file accepted - job ID <VAR>id_number</VAR>.
+<LI>Ready to print.
+<LI>Waiting for job to complete
+</UL>
+
+<P>This directive must appear inside a <A HREF="#Printer"><CODE>Printer</CODE></A>
+or <A HREF="#DefaultPrinter"><CODE>DefaultPrinter</CODE></A> directive.</P>
+
+
+<!-- NEW PAGE -->
+<H2>Changing the Classes Configuration</H2>
+
+<P>The CUPS scheduler (cupsd) uses the <VAR>/etc/cups/classes.conf</VAR> file
+to store the list of available classes. This file contains only locally defined
+classes, but not remote or implicit classes that are created automatically.
+Each directive is listed on a line by itself followed by its value.
+Comments are introduced using the number sign ("#") character at the beginning of a line.
+
+<P>Since the classes configuration file consists of plain text, you can
+use your favorite text editor to make changes to it.
+
+<!-- NEED 4in -->
+<H2>Classes Directives</H2>
+
+<P>The <VAR>classes.conf</VAR> file contains many directives that
+determine how the classes behaves:</P>
+
+<UL>
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0">
+<TR>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#ClassAccepting"><CODE>Accepting</CODE></A>
+ <LI><A HREF="#ClassAllowUser"><CODE>AllowUser</CODE></A>
+ <LI><A HREF="#Class"><CODE>Class</CODE></A>
+ <LI><A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A>
+ <LI><A HREF="#ClassDenyUser"><CODE>DenyUser</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#ClassInfo"><CODE>Info</CODE></A>
+ <LI><A HREF="#ClassJobSheets"><CODE>JobSheets</CODE></A>
+ <LI><A HREF="#ClassKLimit"><CODE>KLimit</CODE></A>
+ <LI><A HREF="#ClassLocation"><CODE>Location</CODE></A>
+ <LI><A HREF="#ClassPageLimit"><CODE>PageLimit</CODE></A>
+
+</TD>
+<TD VALIGN="TOP">
+&nbsp;&nbsp;&nbsp;
+</TD>
+<TD VALIGN="TOP">
+
+ <LI><A HREF="#ClassPrinter"><CODE>Printer</CODE></A>
+ <LI><A HREF="#ClassQuotaPeriod"><CODE>QuotaPeriod</CODE></A>
+ <LI><A HREF="#ClassState"><CODE>State</CODE></A>
+ <LI><A HREF="#ClassStateMessage"><CODE>StateMessage</CODE></A>
+
+</TD>
+</TR>
+</TABLE>
+</UL>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassAccepting">Accepting</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Accepting yes
+
+Accepting no
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Accepting</CODE> directive defines the initial Boolean
+value for the <VAR>printer-is-accepting-job</VAR> attribute which can
+be set by the <CODE>accept</CODE> and <CODE>reject</CODE> commands.
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassAllowUser">AllowUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+AllowUser foo_user
+AllowUser bar_user
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>AllowUser</CODE> directive adds a username to the
+<VAR>requesting-user-name-allowed</VAR> attribute which can be set
+by the <CODE>lpadmin -u</CODE> command.
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+
+<!-- NEED 3in -->
+<H3><A NAME="Class">Class</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;Class name/&gt;
+...
+&lt;/Class&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Class</CODE> directive begins a class definition.
+It can be added by the <CODE>lpadmin -c</CODE> command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="DefaultClass">DefaultClass</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+&lt;DefaultClass name/&gt;
+...
+&lt;/DefaultClass&gt;
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DefaultClass</CODE> directive begins a class definition
+for the default server destination.
+It can be added by the <CODE>lpadmin -c</CODE> command or if already defined,
+set as default by the <CODE>lpoptions -d</CODE> command.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassDenyUser">DenyUser</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+DenyUser foo_user
+DenyUser bar_user
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>DenyUser</CODE> directive adds a username to the
+<VAR>requesting-user-name-allowed</VAR> attribute which can be set
+by the <CODE>lpadmin -u</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassInfo">Info</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Info My Printer
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Info</CODE> directive defines the string for the
+<VAR>printer-info</VAR> attribute which can be set by the
+<CODE>lpadmin -D</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 6in -->
+<H3><A NAME="ClassJobSheets">JobSheets</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+JobSheets none,standard
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>JobSheets</CODE> directive specifies the default banner pages
+to print before and after a print job.
+In the above example, only a <VAR>standard</VAR> banner will print after each job.</P>
+
+<P>The <CODE>lpoptions -o job-sheets=</CODE> command can be used to set banners.
+For example, the following command would produce the same results of a
+<VAR>standard</VAR> banner at the end of each print job for the default class.</P>
+
+<UL><B>
+lpoptions -o job-sheets=none,standard
+</B></UL>
+
+<P>If only one banner file is specified, it will be printed before the
+files in the job. If a second banner file is specified, it is printed
+after the files in the job.</P>
+
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot; label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot; label at the top and bottom.</LI>
+</UL>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassKLimit">KLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+KLimit 1234
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>KLimit</CODE> directive defines the value of the
+<VAR>job-k-limit</VAR> attribute which can be set by the
+<CODE>lpadmin -o job-k-limit=</CODE> command.
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 6in -->
+<H3><A NAME="ClassLocation">Location</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Location Building 3321
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Location</CODE> directive defines the string for the
+<VAR>printer-location</VAR> attribute which can be set by the
+<CODE>lpadmin -L</CODE> command.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>Do not confuse this <CODE>Location</CODE> directive with the
+ one in cupsd.conf. They are completely different.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassPageLimit">PageLimit</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+PageLimit 1234
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>PageLimit</CODE> directive defines the value of the
+<VAR>job-page-limit</VAR> attribute which can be set
+by the <CODE>lpadmin -o job-page-limit=</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassPrinter">Printer</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+Printer foo
+Printer bar
+Printer foo@bar
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>Printer</CODE> directive adds a printer to the class.
+It can be added by the <CODE>lpadmin -c</CODE> command.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>Do not confuse this <CODE>Printer</CODE> directive with the
+ one in printers.conf. They are completely different.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.</P>
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassQuotaPeriod">QuotaPeriod</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+QuotaPeriod 604800
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>QuotaPeriod</CODE> directive defines the value of the
+<VAR>job-quota-period</VAR> attribute which can be set
+by the <CODE>lpadmin -o job-quota-period=</CODE> command.</P>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 3in -->
+<H3><A NAME="ClassState">State</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+State stopped
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>State</CODE> directive defines the initial value of the
+<VAR>printer-state</VAR> attribute. The strings <VAR>idle</VAR> and
+<VAR>stopped</VAR> correspond to the IPP enumeration values.</P>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.
+
+<!-- NEED 6in -->
+<H3><A NAME="ClassStateMessage">StateMessage</A></H3>
+<HR>
+
+<H4>Examples</H4>
+
+<UL><PRE>
+StateMessage Ready to print.
+</PRE></UL>
+
+<H4>Description</H4>
+
+<P>The <CODE>StateMessage</CODE> directive defines the initial string for the
+<VAR>printer-state-message</VAR> attribute.
+The following are some example messages:</P>
+
+<UL>
+<LI>Connected to <VAR>host_name</VAR>...
+<LI>Connecting to <VAR>class_queue</VAR> on port <VAR>port_number</VAR>...
+<LI>Network host <VAR>host_name</VAR> is busy; will retry in 30 seconds...
+<LI>Printer busy; will retry in 10 seconds...
+<LI>Printer is busy; retrying print job...
+<LI>Print file accepted - job ID <VAR>id_number</VAR>.
+<LI>Ready to print.
+<LI>Waiting for job to complete
+</UL>
+
+<P>This directive must appear inside a <A HREF="#Class"><CODE>Class</CODE></A>
+or <A HREF="#DefaultClass"><CODE>DefaultClass</CODE></A> directive.</P>
+
+
+
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTING_SECURITY">Printing System Security</A></H2>
+
+<P>CUPS provides support for address, certificate, and password (Basic
+and Digest) based authentication and access control. Certificate and
+password authentication provide ways to limit access to individual
+people or groups.
+
+<P>Address based access control allows you to limit access to specific
+systems, networks, or domains. While this does not provide authentication,
+it does allow you to limit the potential users of your system efficiently.
+
+<P>CUPS maintains a list of locations that have access control and/or
+authentication enabled. Locations are specified using the
+<A HREF="#Location"><CODE>Location</CODE></A> directive:
+
+<UL><PRE>
+&lt;Location /resource&gt;
+<A HREF="#AuthClass">AuthClass</A> ...
+<A HREF="#AuthGroupName">AuthGroupName</A> ...
+<A HREF="#AuthType">AuthType</A> ...
+
+<A HREF="#Order">Order</A> ...
+<A HREF="#Allow">Allow</A> from ...
+<A HREF="#Deny">Deny</A> from ...
+&lt;/Location&gt;
+</PRE></UL>
+
+<P>Locations generally follow the directory structure of the
+<A HREF="#DocumentRoot"><CODE>DocumentRoot</CODE></A> directory, however
+CUPS does have several virtual locations for administration, classes, jobs,
+and printers:
+
+<CENTER><TABLE BORDER="1">
+<TR>
+<TH>Location</TH>
+<TH>Description</TH>
+</TR>
+<TR>
+<TD>/admin</TD>
+<TD>The path for all administration operations.</TD>
+</TR>
+<TR>
+<TD>/classes</TD>
+<TD>The path for all classes.</TD>
+</TR>
+<TR>
+<TD>/classes/name</TD>
+<TD>The resource for class <CODE>name</CODE>.</TD>
+</TR>
+<TR>
+<TD>/jobs</TD>
+<TD>The path for all jobs.</TD>
+</TR>
+<TR>
+<TD>/jobs/id</TD>
+<TD>The resource for job <CODE>id</CODE>.</TD>
+</TR>
+<TR>
+<TD>/printers</TD>
+<TD>The path for all printers.</TD>
+</TR>
+<TR>
+<TD>/printers/name</TD>
+<TD>The path for printer <CODE>name</CODE>.</TD>
+</TR>
+<TR>
+<TD>/printers/name.ppd</TD>
+<TD>The PPD file path for printer <CODE>name</CODE>.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="CERTIFICATES">Authentication Using Certificates</A></H3>
+
+<P>CUPS supports a local certificate-based authentication scheme that
+can be used in place of <CODE>Basic</CODE> or <CODE>Digest</CODE>
+authentication by clients connecting through the <CODE>localhost</CODE>
+interface. Certificate authentication is not supported or allowed from
+clients on any other interface.
+
+<P>Certificates are 128-bit random numbers that refer to an internal
+authentication record in the server. A client connecting via the
+<CODE>localhost</CODE> interface sends a request with an
+authorization header of:
+
+<UL><PRE>
+Authorization: Local 0123456789ABCDEF0123456789ABCDEF
+</PRE></UL>
+
+<P>The server then looks up the local certificate and authenticates
+using the username associated with it.
+
+<P>Certificates are generated by the server automatically and stored in
+the <VAR>/etc/cups/certs</VAR> directory using the process ID of the
+CGI program started by the server. Certificate files are only readable
+by the <A HREF="#User"><CODE>User</CODE></A> and
+<A HREF="#Group"><CODE>Group</CODE></A> defined in the
+<VAR>cupsd.conf</VAR> file. When the CGI program ends the certificate
+is removed and invalidated automatically.
+
+<P>The special file <VAR>/etc/cups/certs/0</VAR> defines the <I>root
+certificate</I> which can be used by any client running as the super-user
+or another user that is part of the group defined by the
+<A HREF="#SystemGroup"><CODE>SystemGroup</CODE></A> directive. The
+root certificate is automatically regenerated every 5 minutes.
+
+<H3>Using Basic Authentication</H3>
+
+<P>Basic authentication uses UNIX users and passwords to authenticate
+access to resources such as printers and classes, and to limit access
+to administrative functions.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Basic authentication sends the username and password Base64
+encoded from the client to the server, so it offers no
+protection against eavesdropping. This means that a malicious
+user can monitor network packets and discover valid users and
+passwords that could result in a serious compromise in network
+security. Use Basic authentication with extreme care.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>The CUPS implementation of Basic authentication does not allow access
+through user accounts without a password. If you try to authenticate
+using an account without a password, your access will be immediately
+blocked.
+
+<P>Once a valid username and password is authenticated by CUPS, any
+additional group membership requirements are checked.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>The root user is considered by CUPS to be a member of every
+group.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 1in -->
+<P>Use the <CODE>AuthType</CODE> directive to enable Basic authentication:
+
+<UL><PRE>
+AuthType Basic
+</PRE></UL>
+
+<!-- NEED 7in -->
+<H3>Using Digest Authentication</H3>
+
+<P>Digest authentication uses users and passwords defined in the
+<VAR>/etc/cups/passwd.md5</VAR> file to authenticate access to
+resources such as printers and classes, and to limit access to
+administrative functions.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Unlike Basic authentication, Digest passes the MD5 sum
+(basically a complicated checksum) of the username and password
+instead of the strings themselves. Also, Digest authentication
+does not use the UNIX password file, so if an attacker does
+discover the original password it is less likely to result in a
+serious security problem so long as you use a different UNIX
+password than the corresponding Digest password.
+
+<P>The current CUPS implementation of Digest authentication
+uses the client's hostname or IP address for the "nonce" value.
+The nonce value is an additional string added to the username
+and password to make guessing the password more difficult. The
+server checks that the nonce value matches the client's hostname
+or address and rejects the MD5 sum if it doesn't. Future versions
+of CUPS will support Digest "session" authentication which adds
+the request data to the MD5 sum, providing even better
+authentication and security.
+
+<P>Digest authentication does not guarantee that an attacker
+cannot gain unauthorized access, but it is safer than Basic
+authentication and should be used in place of Basic
+authentication whenever possible. <B>Support for Digest
+authentication in web browsers is not yet universally
+available.</B>
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 2in -->
+<P>The <CODE>lppasswd(1)</CODE> command is used to add, change, or
+remove accounts from the <VAR>passwd.md5</VAR> file. To add a
+user to the default system group, type:
+
+<UL><PRE>
+<B>lppasswd -a user ENTER</B>
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE></UL>
+
+<!-- NEED 2in -->
+<P>Once added, a user can change his/her password by typing:
+
+<UL><PRE>
+<B>lppasswd ENTER</B>
+Old password: <B>(password) ENTER</B> [password is not echoed]
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE></UL>
+
+<!-- NEED 1in -->
+<P>To remove a user from the password file, type:
+
+<UL><PRE>
+<B>lppasswd -x user ENTER</B>
+</PRE></UL>
+
+<P>Once a valid username and password is authenticated by CUPS, any
+additional group membership requirements are checked.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>The root user is considered by CUPS to be a member of every
+group.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>Use the <CODE>AuthType</CODE> directive to enable Digest authentication:
+
+<UL><PRE>
+AuthType Digest
+</PRE></UL>
+
+<H3>System and Group Authentication</H3>
+
+<P>The <A HREF="#AuthClass"><CODE>AuthClass</CODE></A> directive controls
+the level of authentication to perform. <CODE>System</CODE> and
+<CODE>Group</CODE> authentication extend the normal user-based authentication
+to require membership in a UNIX group. For <CODE>System</CODE> authentication
+each user must belong to the <CODE>sys</CODE>, <CODE>system</CODE>, or
+<CODE>root</CODE> group; the actual group depends on the operating system.
+
+<P>For <CODE>Group</CODE> authentication each user must belong to the
+group named by the <A HREF="#AuthGroupName"><CODE>AuthGroupName</CODE></A>
+directive:
+
+<UL><PRE>
+&lt;Location /path&gt;
+AuthType Digest
+AuthClass Group
+AuthGroupName mygroup
+&lt;/Location&gt;
+</PRE></UL>
+
+<P>The named group must be a valid UNIX user group, usually defined in the
+<VAR>/etc/group</VAR> or <VAR>/etc/netgroup</VAR> files. Additionally, when
+using Digest authentication you need to create user accounts with the named
+group:
+
+<UL><PRE>
+<B>lppasswd -g mygroup -a user ENTER</B>
+Password: <B>(password) ENTER</B> [password is not echoed]
+Password again: <B>(password) ENTER</B> [password is not echoed]
+</PRE></UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="PRINTER_ACCOUNTING">Printer Accounting</A></H2>
+
+<P>CUPS maintains a log of all accesses, errors, and
+pages that are printed. The log files are normally stored in the
+<VAR>/var/log/cups</VAR> directory. You can change this by
+editing the <VAR>/etc/cups/cupsd.conf</VAR> configuration file.
+
+<H3>The access_log File</H3>
+
+<P>The <VAR>access_log</VAR> file lists each HTTP resource that is accessed
+by a web browser or CUPS/IPP client. Each line is in the so-called "Common
+Log Format" used by many web servers and web reporting tools:
+
+<UL><PRE>
+host group user date-time \"method resource version\" status bytes
+
+127.0.0.1 - - [20/May/1999:19:20:29 +0000] "POST /admin/ HTTP/1.1" 401 0
+127.0.0.1 - mike [20/May/1999:19:20:31 +0000] "POST /admin/ HTTP/1.1" 200 0
+</PRE></UL>
+
+<P>The <I>host</I> field will normally only be an IP address unless you
+have enabled the <A HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
+directive in the <VAR>cupsd.conf</VAR> file.
+
+<P>The <I>group</I> field always contains "-" in CUPS.
+
+<P>The <I>user</I> field is the authenticated username of the requesting user.
+If no username and password is supplied for the request then this field
+contains "-".
+
+<P>The <I>date-time</I> field is the date and time of the request in local time
+and is in the format:
+
+<UL><PRE>
+[DD/MON/YYYY:HH:MM:SS +ZZZZ]
+</PRE></UL>
+
+<P>where <I>ZZZZ</I> is the timezone offset in hours and minutes
+from coordinated universal time (UTC). UTC may sometimes be
+referred to as GMT or ZULU on legacy systems.</P>
+
+<P>The <I>method</I> field is the HTTP method used ("GET", "PUT", "POST", etc.)
+
+<P>The <I>resource</I> field is the filename of the requested resource.
+
+<P>The <I>version</I> field is the HTTP specification version used by the
+client. For CUPS clients this will always be "HTTP/1.1".
+
+<P>The <I>status</I> field contains the HTTP result status of the
+request. Usually it is "200", but other HTTP status codes are possible.
+For example, 401 is the "unauthorized access" status in the example
+above.
+
+<P>The <I>bytes</I> field contains the number of bytes in the request.
+For POST requests the <I>bytes</I> field contains the number of bytes
+that was received from the client.
+
+<H3>The error_log File</H3>
+
+<P>The <VAR>error_log</VAR> file lists messages from the scheduler (errors,
+warnings, etc.):
+
+<UL><PRE>
+level date-time message
+
+I [20/May/1999:19:18:28 +0000] Job 1 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:21:02 +0000] Job 2 queued on 'DeskJet' by 'mike'.
+I [20/May/1999:19:22:24 +0000] Job 2 was cancelled by 'mike'.
+</PRE></UL>
+
+<P>The <I>level</I> field contains the type of message:
+
+<UL>
+
+<LI><CODE>E</CODE> - An error occurred.
+
+<LI><CODE>W</CODE> - The server was unable to perform some action.
+
+<LI><CODE>I</CODE> - Informational message.
+
+<LI><CODE>D</CODE> - Debugging message.
+
+</UL>
+
+<P>The <I>date-time</I> field contains the date and time of when the page
+started printing. The format of this field is identical to the <I>data-time</I>
+field in the <VAR>access_log</VAR> file.
+
+<P>The <I>message</I> fields contains a free-form textual message.
+
+<H3>The page_log File</H3>
+
+<P>The <VAR>page_log</VAR> file lists each page that is sent to a printer.
+Each line contains the following information:
+
+<UL><PRE>
+printer user job-id date-time page-number num-copies job-billing hostname
+
+DeskJet root 2 [20/May/1999:19:21:05 +0000] 1 0 acme-123 localhost
+</PRE></UL>
+
+<P>The <I>printer</I> field contains the name of the printer that
+printed the page. If you send a job to a printer class, this field will
+contain the name of the printer that was assigned the job.
+
+<P>The <I>user</I> field contains the name of the user (the IPP
+<CODE>requesting-user-name</CODE> attribute) that submitted this file for
+printing.
+
+<P>The <I>job-id</I> field contains the job number of the page being printed.
+Job numbers are reset to 1 whenever the CUPS server is started, so don't depend
+on this number being unique!
+
+<P>The <I>date-time</I> field contains the date and time of when the page
+started printing. The format of this field is identical to the <I>data-time</I>
+field in the <VAR>access_log</VAR> file.
+
+<P>The <I>page-number</I> and <I>num-pages</I> fields contain the page number
+and number of copies being printed of that page. For printer that can not
+produce copies on their own, the <I>num-pages</I> field will always be 1.
+
+<P>The <I>job-billing</I> field contains a copy of the
+<CODE>job-billing</CODE> attribute provided with the IPP
+<CODE>create-job</CODE> or <CODE>print-job</CODE> requests or "-" if none
+was provided.
+
+<P>The <I>hostname</I> field contains the name of the host (the
+IPP <CODE>job-originating-host-name</CODE> attribute) that
+originated the print job.
+
+<!-- NEW PAGE -->
+<H2><A NAME="FILE_TYPING_FILTERING">File Typing and Filtering</A></H2>
+
+<P>CUPS provides a MIME-based file typing and filtering mechanism to
+convert files to a printable format for each printer. On startup the
+CUPS server reads MIME database files from the <VAR>/etc/cups</VAR>
+directory (or a directory specified by the
+<A HREF="#ServerRoot"><CODE>ServerRoot</CODE></A> directive) to build
+a file type and conversion database in memory. These database files are
+plain ASCII text and can be edited with your favorite text editor.
+
+<P>The <VAR>mime.types</VAR> and <VAR>mime.convs</VAR> files define the
+standard file types and filters that are available on the system.
+
+<H3>mime.types</H3>
+
+<P>The <VAR>mime.types</VAR> file defines the known file types. Each line
+of the file starts with the MIME type and may be followed by one or
+more file type recognition rules. For example, the
+<CODE>text/html</CODE> file type is defined as:
+
+<UL><PRE>
+text/html html htm \
+ printable(0,1024) + \
+ (string(0,"&lt;HTML&gt;") string(0,"&lt;!DOCTYPE"))
+</PRE></UL>
+
+<P>The first two rules say that any file with an extension of
+<VAR>.html</VAR> or <VAR>.htm</VAR> is a HTML file. The third rule
+says that any file whose first 1024 characters are printable text and
+starts with the strings <CODE>&lt;HTML&gt;</CODE> or
+<CODE>&lt;!DOCTYPE</CODE> is a HTML file as well.
+
+<P>The first two rules deal solely with the name of the file being
+typed. This is useful when the original filename is known, however for
+print files the server doesn't have a filename to work with. The third
+rule takes care of this possibility and automatically figures out the
+file type based upon the contents of the file instead.
+
+<P>The available tests are:
+
+<UL>
+
+<LI><CODE>( expr )</CODE> - Parenthesis for expression grouping
+
+<LI><CODE>+</CODE> - Logical AND
+
+<LI><CODE>,</CODE> or whitespace - Logical OR
+
+<LI><CODE>!</CODE> - Logical NOT
+
+<LI><CODE>match("pattern")</CODE> - Pattern match on filename
+
+<LI><CODE>extension</CODE> - Pattern match on "*.extension"
+
+<LI><CODE>ascii(offset,length)</CODE> - True if bytes are valid
+printable ASCII (CR, NL, TAB, BS, 32-126)
+
+<LI><CODE>printable(offset,length)</CODE> - True if bytes are
+printable 8-bit chars (CR, NL, TAB, BS, 32-126, 160-254)
+
+<LI><CODE>string(offset,"string")</CODE> - True if bytes are
+identical to string
+
+<LI><CODE>istring(offset,"string")</CODE> - True if bytes are
+identical to string after reducing both strings to lowercase
+
+<LI><CODE>contains(offset,range,"string")</CODE> - True if the
+range of bytes contains the string
+
+<LI><CODE>char(offset,value)</CODE> - True if byte is identical
+
+<LI><CODE>short(offset,value)</CODE> - True if 16-bit integer
+is identical (network or "big-endian" byte order)
+
+<LI><CODE>int(offset,value)</CODE> - True if 32-bit integer is
+identical (network or "big-endian" byte order)
+
+<LI><CODE>locale("string")</CODE> - True if current locale
+matches string
+
+</UL>
+
+<P>All numeric values can be in decimal (123), octal (0123), or hexadecimal
+(0x123) as desired.
+
+<!-- NEED 2.5in -->
+<P>Strings can be in quotes, all by themselves, as a string
+of hexadecimal values, or some combination:
+
+<UL><PRE>
+"string"
+'string'
+string
+&lt;737472696e67&gt;
+&lt;7374&gt;ring
+</PRE></UL>
+
+<P>As shown in the <CODE>text/html</CODE> example, rules can continue on
+multiple lines using the backslash (\) character. A more complex example is
+the <CODE>image/jpeg</CODE> rules:
+
+<UL><PRE>
+image/jpeg jpeg jpg jpe string(0,&lt;FFD8FF&gt;) &amp;&amp;\
+ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\
+ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\
+ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\
+ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef))
+</PRE></UL>
+
+<P>This rule states that any file with an extension of
+<VAR>.jpeg</VAR>, <VAR>.jpg</VAR>, or <VAR>.jpe</VAR> is a JPEG file.
+In addition, any file starting with the hexadecimal string
+<CODE>&lt;FFD8FF&gt;</CODE> (JPEG Start-Of-Image) followed by a
+character between and including <CODE>0xe0</CODE> and <CODE>0xef</CODE>
+(JPEG APPn markers) is also a JPEG file.
+
+<H3>mime.convs</H3>
+
+<P>The <VAR>mime.convs</VAR> file defines all of the filter programs that
+are known to the system. Each line consists of:
+
+<UL><PRE>
+source destination cost program
+
+text/plain application/postscript 50 texttops
+application/vnd.cups-postscript application/vnd.cups-raster 50 pstoraster
+image/* application/vnd.cups-postscript 50 imagetops
+image/* application/vnd.cups-raster 50 imagetoraster
+</PRE></UL>
+
+<P>The <I>source</I> field is a MIME type, optionally using a wildcard for
+the super-type or sub-type (e.g. "text/plain", "image/*", "*/postscript").
+
+<P>The <I>destination</I> field is a MIME type defined in the
+<VAR>mime.types</VAR> file.
+
+<P>The <I>cost</I> field defines a relative cost for the filtering
+operation from 1 to 100. The cost is used to choose between two
+different sets of filters when converting a file. For example, to convert
+from <CODE>image/jpeg</CODE> to <CODE>application/vnd.cups-raster</CODE>,
+you could use the <CODE>imagetops</CODE> and <CODE>pstoraster</CODE>
+filters for a total cost of 100, or the <CODE>imagetoraster</CODE> filter
+for a total cost of 50.
+
+<P>The <I>program</I> field defines the filter program to run; the
+special program "-" can be used to make two file types equivalent. The
+program must accept the standard filter arguments and environment
+variables described in the CUPS Interface Design Description and CUPS
+Software Programmers Manual:
+
+<UL><PRE>
+program job user title options [filename]
+</PRE></UL>
+
+<P>If specified, the <I>filename</I> argument defines a file to read
+when filtering, otherwise the filter must read from the standard input.
+All filtered output must go to the standard output.
+
+<!-- NEED 4in -->
+<H3>Adding Filetypes and Filters</H3>
+
+<P>Adding a new file type or filter is fairly straight-forward. Rather
+than adding the new type and filter to the <VAR>mime.types</VAR> and
+<VAR>mime.convs</VAR> files which are overwritten when you upgrade to a
+new version of CUPS, you simple need to create new files with
+<VAR>.types</VAR> and <VAR>.convs</VAR> extensions in the
+<VAR>/etc/cups</VAR> directory. We recommend that you use the product
+or format name, e.g.:
+
+<UL><PRE>
+myproduct.types
+myproduct.convs
+</PRE></UL>
+
+<P>If you are providing a filter for a common file format or printer,
+add the company or author name:
+
+<UL><PRE>
+acme-msword.types
+acme-msword.convs
+</PRE></UL>
+
+<P>This will help to prevent name collisions if you install many
+different file types and filters.
+
+<P>Once you choose the names for these files, create them using your
+favorite text editor as described earlier in this chapter. Once you
+have created the files, restart the <CODE>cupsd</CODE> process as
+described earlier in <A HREF="#RESTARTING">"Restarting the CUPS Server"</A>.
+
+<H3>Printer Drivers and PPD Files</H3>
+
+<P>Most CUPS printer drivers utilize one or more printer-specific filters
+and a PPD file for each printer model. Printer driver filters are registered
+via the PPD file using <CODE>cupsFilter</CODE> attributes:
+
+<UL><PRE>
+*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+</PRE></UL>
+
+<P>The filter is specified using the source file type only; the destination
+file type is assumed to be <CODE>printer/name</CODE> - suitable for sending
+to the printer.
+
+<H3>Writing Your Own Filter or Printer Driver</H3>
+
+<P>CUPS supports an unlimited number of file formats and filters, and can
+handle any printer. If you'd like to write a filter or printer driver for
+your favorite file format or printer, consult the CUPS Software Programmers
+Manual for step-by-step instructions.
+
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTING_OTHER">7 - Printing with Other Systems</A></H1>
+
+<P>This chapter describes how to print from client systems that use the
+LPD, Mac OS, or Windows printing protocols.
+
+<H2>The Basics</H2>
+
+<P>CUPS is based on the IPP protocol, so any system that supports IPP
+can send jobs to and receive jobs from CUPS automatically. However, not
+all systems support IPP yet. This chapter will show you how to connect
+these systems to your CUPS server, either to accept jobs from your
+server for printing, or to send jobs to your server.
+
+<H2>Printing from LPD Clients</H2>
+
+<P>CUPS supports limited functionality for LPD-based clients. With LPD you can
+print files to specific printers, list the queue status, and so forth. However,
+the automatic client configuration and printer options are not supported by
+the LPD protocol, so you must manually configure each client for the printers
+it needs to access.
+
+<P>The <CODE>cups-lpd(8)</CODE> program provides support for LPD
+clients and can be used from either the <CODE>inetd(8)</CODE> or
+<CODE>xinetd(8)</CODE> programs. Add the following line to the
+<VAR>/etc/inetd.conf</VAR> file to enable LPD support on your
+server through the <CODE>inetd</CODE> program:
+
+<UL><PRE>
+printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+</PRE></UL>
+
+<P>The path to the <CODE>cups-lpd</CODE> may vary depending on your
+installation.
+
+<P>Once you have added this line, send the <CODE>inetd</CODE>
+process a <CODE>HUP</CODE> signal or reboot the system:
+
+<UL><PRE>
+<B>killall -HUP inetd ENTER</B> [IRIX and some versions of Linux]
+<B>kill -HUP <I>pid</I> ENTER [Others]</B>
+<B>reboot ENTER [For all systems if the HUP signal fails]</B>
+</PRE></UL>
+
+<P>If you are using the <CODE>xinetd</CODE> program, create a
+file named <VAR>/etc/xinetd.d/printer</VAR> containing the
+following lines:
+
+<UL><PRE>
+service printer
+{
+socket_type = stream
+protocol = tcp
+wait = no
+user = lp
+server = /usr/lib/cups/daemon/cups-lpd
+}
+</PRE></UL>
+
+<P>The <CODE>xinetd</CODE> program automatically reads the new
+configuration file and enables LPD printing support.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD><B>Warning:</B>
+
+<P><CODE>cups-lpd</CODE> currently does not perform any
+access control based on the settings in
+<VAR>cupsd.conf</VAR> or in the <VAR>hosts.allow</VAR>
+or <VAR>hosts.deny</VAR> files used by TCP wrappers.
+Therefore, running <CODE>cups-lpd</CODE> on your server
+will allow any computer on your network (and perhaps the
+entire Internet) to print to your server.
+
+<P>While <CODE>xinetd</CODE> has built-in access control
+support, you should use the TCP wrappers package with
+<CODE>inetd</CODE> to limit access to only those
+computers that should be able to print through your
+server.
+
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2><A NAME="LPD">Printing to LPD Servers</A></H2>
+
+<P>CUPS provides the <CODE>lpd</CODE> backend for printing to
+LPD-based servers and printers. Use a device URI of
+<CODE>lpd://server/name</CODE> to print to a printer on an LPD
+server, where <CODE>server</CODE> is the hostname or IP address
+of the server and <CODE>name</CODE> is the queue name.
+Additional options can be specified after the remote queue name
+to control how the LPD requests are sent - consult <A
+HREF="#COMMON_NETWORK">Appendix B - Common Network Settings</A>
+for a complete description.
+
+<P>Microsoft Windows NT provides an LPD service under the name "TCP/IP
+Printing Services". To enable LPD printing on NT, open the "Services"
+control panel, select the "TCP/IP Printing Services" service, and click
+on the "Start" button. Any shared printer will then be available via
+the LPD protocol.
+
+
+<!-- NEED 4in -->
+
+<H2>Printing from Mac OS 10.2 and Later Clients</H2>
+
+<P>Since Mac OS 10.2 uses CUPS as its printing system, all CUPS
+printers will be available to the clients automatically.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD><B>Note:</B>
+
+<P>Certain legacy MacOS X applications, including most Adobe
+applications, produce PICT files with embedded PostScript. Since
+the filter needed to convert these files to pure PostScript is
+only available on MacOS X, you need to either use a MacOS X
+print server or replace the MacOS X IPP backend with the
+standard CUPS IPP backend. The CUPS IPP backend will detect and
+locally convert these print files to PostScript prior to sending
+the job to the server.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+
+<!-- NEED 4in -->
+<H2>Printing from Mac OS 10.1 and Earlier Clients</H2>
+
+<P>CUPS does not provide support for Mac OS 10.1 and earlier
+directly. However, there are several free and commercial
+software packages that do.
+
+<H3>Columbia Appletalk Package (CAP)</H3>
+
+<P>Because the CAP LaserWriter server (<CODE>lwsrv(8)</CODE>) does
+not support specification of PPD files, we do not recommend that you
+use CAP with CUPS. However, you can run the <CODE>lpsrv</CODE> program
+for limited printing with the command:
+
+<UL><PRE>
+lwsrv -n "<I>Name</I>" -p <I>printer</I> -a /usr/lib/adicts -f /usr/lib/LW+Fonts
+</PRE></UL>
+
+<P>where <CODE>Name</CODE> is the name you want to use when sharing the
+printer, and <CODE>printer</CODE> is the name of the CUPS print queue.
+
+<!-- NEED 3in -->
+<H3>XINET KA/Spool</H3>
+
+<P>To use your system as a print server for Mac OS clients,
+configure each printer using a <CODE>papserver(8)</CODE> in the
+<VAR>/usr/adm/appletalk/services</VAR> file, specifying the
+corresponding PPD file in the <VAR>/etc/cups/ppd</VAR> directory for
+each printer. For a printer named <CODE>MyPrinter</CODE> the entry
+would look like:
+
+<UL><PRE>
+/usr/etc/appletalk/papserver -I -L -P /etc/cups/ppd/MyPrinter.ppd \
+"Printer Description" MyPrinter
+</PRE></UL>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Enter the text above on a single line without the backslash (\)
+character.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H3>Netatalk</H3>
+
+<P>To use your system as a print server for Mac OS clients,
+configure each printer in the <VAR>papd.conf</VAR> file, specifying the
+corresponding PPD file in the <VAR>/etc/cups/ppd</VAR> directory for
+each printer. For a printer named <CODE>MyPrinter</CODE> the entry
+would look like:
+
+<UL><PRE>
+Printer Name@Zone Name:\
+:pr=|/usr/bin/lp -d MyPrinter:\
+:op=daemon:\
+:pd=/etc/cups/ppd/MyPrinter.ppd:
+</PRE></UL>
+
+
+<!-- NEED 2in -->
+<H2>Printing to Mac OS 10.2 and Later Servers</H2>
+
+<P>Since MacOS 10.2 and later use CUPS, all you need to do is
+enable printer sharing to allow CUPS clients to print to a Mac
+OS server. You will need to download and install ESP Ghostscript
+on your server to provide PostScript printing support for
+non-PostScript printers, however.
+
+
+<!-- NEED 2in -->
+<H2>Printing to Mac OS 10.1 and Earlier Servers</H2>
+
+<P>CUPS currently does not provide a backend to communicate with
+a Mac OS 10.1 and earlier server. However, you can write and
+install a short shell script in the
+<VAR>/usr/lib/cups/backend</VAR> directory that sends a print
+file using the appropriate command. The following is a short
+script that will run the <CODE>papif</CODE> command provided
+with CAP.
+
+<P>After copying this script to
+<VAR>/usr/lib/cups/backend/cap</VAR>, specify a device URI of
+<CODE>cap://server/printer</CODE> to use this backend with a
+print queue.
+
+<!-- NEED 8in -->
+<UL>
+<PRE>
+<I>"/usr/lib/cups/backend/cap"</I>
+#!/bin/sh
+#
+# Usage: cap job user title copies options [filename]
+#
+
+# No arguments means show available devices...
+
+if test ${#argv} = 0; then
+echo "network cap \"Unknown\" \"Mac OS Printer via CAP\""
+exit 0
+fi
+
+# Collect arguments...
+
+user=$2
+copies=$4
+
+if test ${#argv} = 5; then
+# Get print file from stdin; copies have already been handled...
+file=/var/tmp/$$.prn
+copies=1
+cat &gt; $file
+else
+# Print file is on command-line...
+file=$6
+fi
+
+# Create a dummy cap.printers file for this printer based
+# upon a device URI of "cap://server/printer"...
+
+echo $PRINTER/$DEVICE_URI | \
+awk -F/ '{print $1 "=" $5 ":LaserWriter@" $4}' &gt; /var/tmp/$$.cap
+
+CAPPRINTERS=/var/tmp/$$.cap; export CAPPRINTERS
+
+# Send the file to the printer, once for each copy. This assumes that you
+# have properly initialized the cap.printers file...
+
+while [ $copies -gt 0 ]; do
+papif -n $user &lt; $file
+
+copies=`expr $copies - 1`
+done
+
+# Remove any temporary files...
+if test ${#argv} = 5; then
+/bin/rm -f $file
+fi
+
+/bin/rm -f /var/tmp/$$.cap
+
+exit 0
+</PRE></UL>
+
+<!-- NEED 2in -->
+<H2>Printing from Windows Clients</H2>
+
+<P>While CUPS does not provide Windows support directly, the free
+SAMBA software package does. SAMBA version 2.0.6 is the first release
+of SAMBA that supports CUPS. You can download SAMBA from:
+
+<UL><PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE></UL>
+
+<P>To configure SAMBA for CUPS, edit the <VAR>smb.conf</VAR> file and
+replace the existing printing commands and options with the line:
+
+<UL><PRE>
+printing = cups
+printcap name = cups
+</PRE></UL>
+
+<P>That's all there is to it! Remote users will now be able to browse and
+print to printers on your system.
+
+<H3>Exporting Printer Drivers</H3>
+
+<P>You can optionally export printer drivers from your CUPS
+server using the <CODE>cupsaddsmb</CODE> command and the SAMBA
+2.2.0 or higher software.
+
+<P>Before you can export the printers you must download the CUPS
+drivers for Windows from the CUPS site (<A
+HREF="http://www.cups.org/">http://www.cups.org/</A>) or the
+current Adobe PostScript printer drivers from the Adobe web site
+(<A HREF="http://www.adobe.com/">http://www.adobe.com/</A>). If
+you download the Adobe drivers, use the free <CODE>unzip</CODE>
+software to extract the files from the self-extracting ZIP file
+containing the drivers; you will need the following files:
+
+<UL><PRE>
+ADFONTS.MFM
+ADOBEPS4.DRV
+ADOBEPS4.HLP
+ADOBEPS5.DLL
+ADOBEPSU.DLL
+ADOBEPSU.HLP
+DEFPRTR2.PPD
+ICONLIB.DLL
+PSMON.DLL
+</PRE></UL>
+
+<P>Copy these files to the <VAR>/usr/share/cups/drivers</VAR>
+directory - you may need to rename some of the files so the
+filenames are all UPPERCASE.
+
+<P>Next, configure SAMBA (via the <VAR>smb.conf</VAR> file) to
+support printing through CUPS and provide a printer driver
+download share, as follows:
+
+<UL><PRE>
+[global]
+load printers = yes
+printing = cups
+printcap name = cups
+
+[printers]
+comment = All Printers
+path = /var/spool/samba
+browseable = no
+public = yes
+guest ok = yes
+writable = no
+printable = yes
+printer admin = root
+
+[print$]
+comment = Printer Drivers
+path = /etc/samba/drivers
+browseable = yes
+guest ok = no
+read only = yes
+write list = root
+</PRE></UL>
+
+<P>This configuration assumes a FHS-compliant installation of
+SAMBA; adjust the [printers] and [print$] share paths
+accordingly on your system as needed. That is, the directory for
+your printer drivers can be anywhere on the system; just make
+sure it is writable by the users specified by the <CODE>write
+list</CODE> directive plus readable and executable by all users.
+Also, make sure that you have SAMBA passwords defined for each
+user in the <CODE>write list</CODE> using SAMBA's
+<CODE>smbpasswd(1)</CODE> command. Otherwise you will not be
+able to authenticate.
+
+<P>Finally, run the <CODE>cupsaddsmb</CODE> command to export
+the printer drivers for one or more queues:
+
+<UL><PRE>
+<B>cupsaddsmb -U root printer1 ... printerN <I>ENTER</I></B>
+</PRE></UL>
+
+<P>Running <CODE>cupsaddsmb</CODE> with the <CODE>-a</CODE> option
+will export all printers:
+
+<UL><PRE>
+<B>cupsaddsmb -U root -a <I>ENTER</I></B>
+</PRE></UL>
+
+<P>Notice in the above examples that the user <CODE>root</CODE>
+was used which was defined in the <CODE>write list</CODE> of
+the <VAR>smb.conf</VAR> file.
+
+<H2>Printing to Windows Servers</H2>
+
+<P>CUPS can print to Windows servers in one of two ways. The first way uses
+the LPD protocol on the CUPS system and the "TCP/IP Printing Services" on
+the Windows system. You can find out more about this configuration in the
+<A HREF="#LPD">LPD</A> section earlier in this chapter.
+
+<P>The second way is through the Microsoft Server Message Block ("SMB")
+protocol. Support for this protocol is provided with the free SAMBA
+software package. You can download SAMBA from:
+
+<UL><PRE>
+<A HREF="http://www.samba.org">http://www.samba.org</A>
+</PRE></UL>
+
+<P>To configure CUPS for SAMBA, run the following command:
+
+<UL><PRE>
+<B>ln -s `which smbspool` /usr/lib/cups/backend/smb ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>smbspool(1)</CODE> program is provided with SAMBA starting
+with SAMBA 2.0.6. Once you have made the link you can configure your
+printers with one of the following device URIs:
+
+<UL><PRE>
+smb://workgroup/server/sharename
+smb://server/sharename
+smb://user:pass@workgroup/server/sharename
+smb://user:pass@server/sharename
+</PRE></UL>
+
+<P>The <CODE>workgroup</CODE> name need only be specified if your
+system is using a different workgroup. The <CODE>user:pass</CODE>
+strings are required when printing to Windows NT servers or to shares
+with passwords enabled under Windows 95 and 98.
+
+
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
+
+<EMBED SRC="../LICENSE.html">
+
+
+<H1 ALIGN="RIGHT"><A NAME="COMMON_NETWORK">B - Common Network Settings</A></H1>
+
+<P>This appendix covers many of the popular TCP/IP network interfaces
+and printer servers available on the market today.
+
+<H2>Configuring a Network Interface</H2>
+
+<P>When you first install a network printer or print server on your
+LAN, you need to set the Internet Protocol ("IP") address. On most
+higher-end "workgroup" printers, you can set the address through the
+printer control panel. However, in most cases you will want to assign
+the addresses remotely from your workstation. This makes administration
+a bit easier and avoids assigning duplicate addresses accidentally.
+
+<P>To setup your printer or print server for remote address assignment,
+you'll need the Ethernet Media Access Control ("MAC") address, also
+sometimes called a node address, and the IP address you want to use for
+the device. The Ethernet MAC address can often be found on the printer
+test page or bottom of the print server.
+
+<!-- NEED 3in -->
+<H3>Configuring the IP Address Using ARP</H3>
+
+<P>The easiest way to set the IP address of a network device is to use
+the <CODE>arp(8)</CODE> command. The <CODE>arp</CODE> sends an Address
+Resolution Protocol ("ARP") packet to the specified Ethernet MAC address,
+setting the network device's IP address:
+
+<UL><PRE>
+<B>arp -s ip-address ethernet-address ENTER</B>
+<B>arp -s host.domain.com 08:00:69:00:12:34 ENTER</B>
+<B>arp -s 192.0.2.2 08:00:69:00:12:34 ENTER</B>
+</PRE></UL>
+
+<H3>Configuring the IP Address Using RARP</H3>
+
+<P>The most flexible way to remotely assign IP addresses under UNIX
+is through the Reverse Address Resolution Protocol ("RARP"). RARP
+allows a network device to request an IP address using its Ethernet
+MAC address, and one or more RARP servers on the network will
+respond with an ARP packet with the IP address the device can use.
+
+<P>RARP should be used when you have to manage many printers or print
+servers, or when you have a network device that does not remember its
+IP address after a power cycle. If you just have a single printer or
+print server, the <CODE>arp</CODE> command is the way to go.
+
+<P>Some UNIX operating systems use a program called
+<CODE>rarpd(8)</CODE> to manage RARP. Others, like Linux, support this
+protocol in the kernel. For systems that provide the <CODE>rarpd</CODE>
+program you will need to start it before RARP lookups will work:
+
+<UL><PRE>
+<B>rarpd ENTER</B>
+</PRE></UL>
+
+<P>Under IRIX you can enable this functionality by default using:
+
+<UL><PRE>
+<B>chkconfig rarpd on ENTER</B>
+</PRE></UL>
+
+<P>Both the <CODE>rarpd</CODE> program and kernel RARP support read a
+list of Ethernet and IP addresses from the file <VAR>/etc/ethers</VAR>.
+Each line contains the Ethernet address (colon delimited) followed by
+an IP address or hostname like:
+
+<UL><PRE>
+08:00:69:00:12:34 myprinter.mydomain.com
+08:00:69:00:12:34 192.0.2.2
+</PRE></UL>
+
+<P>Add a line to this file and cycle the power on the printer or print
+server to set its address.
+
+<!-- NEED 2in -->
+<H3>Configuring the IP Address Using BOOTP</H3>
+
+<P>The BOOTP protocol is used when you need to provide additional information
+such as the location of a configuration file to the network interface. Using
+the standard <CODE>bootpd(8)</CODE> program supplied with UNIX you simply need to
+add a line to the <VAR>/etc/bootptab</VAR> file; for IRIX:
+
+<UL><PRE>
+myprinter 08:00:69:00:12:34 192.0.2.2 <VAR>myprinter.boot</VAR>
+</PRE></UL>
+
+<!-- NEED 1in -->
+<P>Newer versions of <CODE>bootpd</CODE> use a different format:
+
+<UL><PRE>
+myprinter:ha=080069001234:ip=192.0.2.2:<VAR>t144=myprinter.boot</VAR>
+</PRE></UL>
+
+<P>The <VAR>myprinter.boot</VAR> file resides in the <VAR>/usr/local/boot</VAR>
+directory by default. If you do not need to provide a boot file you may leave
+the last part of the line blank.</P>
+
+<!-- NEED 2in -->
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Some versions of UNIX do not enable the BOOTP service by
+default. The <VAR>/etc/inetd.conf</VAR> usually contains a
+line for the BOOTP service that can be uncommented if
+needed.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>Verifying the Printer Connection</H2>
+
+<P>To test that the IP address has been successfully assigned and that the
+printer is properly connected to your LAN, type:
+
+<UL><PRE>
+<B>ping ip-address ENTER</B>
+</PRE></UL>
+
+<P>If the connection is working properly you will see something like:
+
+<UL><PRE>
+<B>ping myprinter ENTER</B>
+PING myprinter (192.0.2.2): 56 data bytes
+64 bytes from 192.0.2.2: icmp_seq=0 ttl=15 time=5 ms
+64 bytes from 192.0.2.2: icmp_seq=1 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=2 ttl=15 time=3 ms
+64 bytes from 192.0.2.2: icmp_seq=3 ttl=15 time=3 ms
+</PRE></UL>
+
+<P>If not, verify that the printer or print server is connected to the
+LAN, it is powered on, the LAN cabling is good, and the IP address is
+set correctly. You can usually see the current IP address and network
+status by printing a configuration or test page on the device.
+
+<!-- NEED 4in -->
+<H2>Common Network Interface Settings</H2>
+
+<P>Once you have set the IP address you can access the printer or print
+server using the <CODE>ipp</CODE>, <CODE>lpd</CODE>, or
+<CODE>socket</CODE> backends. The following is a list of common network
+interfaces and printer servers and the settings you should use with
+CUPS:
+
+<CENTER><TABLE BORDER="1">
+<TR VALIGN="TOP" ALIGN="LEFT">
+<TH>Model/Manufacturer</TH>
+<TH>Device URI(s)</TH>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Apple LaserWriter</TD>
+<TD>lpd://<I>address</I>/PASSTHRU</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Axis w/o IPP<BR>
+<A HREF="#AXIS">(see directions)</A></TD>
+<TD>socket://<I>address</I>:9100<BR>
+socket://<I>address</I>:9101<BR>
+socket://<I>address</I>:9102</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Axis w/IPP</TD>
+<TD>ipp://<I>address</I>/LPT1<BR>
+ipp://<I>address</I>/LPT2<BR>
+ipp://<I>address</I>/COM1</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Castelle LANpress<SUP>TM</SUP></TD>
+<TD>lpd://<I>address</I>/pr1<BR>
+lpd://<I>address</I>/pr2<BR>
+lpd://<I>address</I>/pr3</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>DPI NETPrint</TD>
+<TD>lpd://<I>address</I>/pr1<BR>
+lpd://<I>address</I>/pr2<BR>
+lpd://<I>address</I>/pr3</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>EFI&reg; Fiery&reg; RIP</TD>
+<TD>lpd://<I>address</I>/print</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>EPSON&reg; Multiprotocol Ethernet Interface Board</TD>
+<TD>socket://<I>address</I></TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Extended System ExtendNET</TD>
+<TD>lpd://<I>address</I>/pr1<BR>
+lpd://<I>address</I>/pr2<BR>
+lpd://<I>address</I>/pr3</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Hewlett Packard JetDirect w/o IPP</TD>
+<TD>socket://<I>address</I>:9100<BR>
+socket://<I>address</I>:9101<BR>
+socket://<I>address</I>:9102</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Hewlett Packard JetDirect w/IPP</TD>
+<TD>ipp://<I>address</I>/ipp<BR>
+ipp://<I>address</I>/ipp/port1<BR>
+ipp://<I>address</I>/ipp/port2<BR>
+ipp://<I>address</I>/ipp/port3</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Intel® NetportExpress XL, PRO/100</TD>
+<TD>lpd://<I>address</I>/LPT1_PASSTHRU<BR>
+lpd://<I>address</I>/LPT2_PASSTHRU<BR>
+lpd://<I>address</I>/COM1_PASSTHRU</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Lexmark<SUP>TM</SUP> MarkNet</TD>
+<TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<!-- NEED 1in -->
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Linksys EtherFast&reg;<BR>
+<A HREF="#LINKSYS">(see directions)</A></TD>
+<TD>socket://<I>address</I>:4010<BR>
+socket://<I>address</I>:4020<BR>
+socket://<I>address</I>:4030</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Kodak&reg;</TD>
+<TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>QMS&reg; CrownNet<SUP>TM</SUP></TD>
+<TD>lpd://<I>address</I>/ps</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>Tektronix&reg; PhaserShare<SUP>TM</SUP></TD>
+<TD>socket://<I>address</I>:9100</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>XEROX&reg; 4512 NIC</TD>
+<TD>lpd://<I>address</I>/PORT1</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>XEROX&reg; XNIC</TD>
+<TD>lpd://<I>address</I>/PASSTHRU</TD>
+</TR>
+<TR ALIGN="LEFT" VALIGN="TOP">
+<TD>XEROX&reg; (most others)</TD>
+<TD>socket://<I>address</I>:5503</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2><A NAME="AXIS">Configuring Axis Print Servers</A></H2>
+
+<P>The Axis print servers can be configured using ARP, RARP, or BOOTP.
+However, on models that do not provide IPP support an additional step
+must be performed to configure the TCP/IP portion of the print server
+for use with CUPS.
+
+<!-- NEED 3in -->
+<P>Each print server contains a configuration file named
+<VAR>config</VAR> that contains a list of network parameters used by
+the server. To modify this file you must first download it from the
+print server using the <CODE>ftp(1)</CODE> program:
+
+<UL><PRE>
+<B>ftp ip-address ENTER</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp> <B>user root ENTER</B>
+331 User name ok, need password
+Password: <B>pass ENTER</B> <I>(this is not echoed)</I>
+230 User logged in
+ftp> <B>get config ENTER</B>
+local: config remote: config
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2),
+(mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp> <B>quit ENTER</B>
+221 Goodbye.
+</PRE></UL>
+
+<!-- NEED 2in -->
+<P>Next, edit the file with your favorite text editor and locate the
+lines beginning with:
+
+<UL><PRE>
+RTN_OPT. : YES
+RTEL_PR1. : 0
+RTEL_PR2. : 0
+RTEL_PR3. : 0
+RTEL_PR4. : 0
+RTEL_PR5. : 0
+RTEL_PR6. : 0
+RTEL_PR7. : 0
+RTEL_PR8. : 0
+</PRE></UL>
+
+<!-- NEED 1in -->
+Change the <CODE>RTN_OPT</CODE> line to read:
+
+<UL><PRE>
+RTN_OPT. : <B>NO</B>
+</PRE></UL>
+
+<!-- NEED 2in -->
+<P>This disables the Reverse TELNET protocol and enables the standard
+TELNET protocol on the print server. Next, assign a port number for
+each parallel and serial port on the server as follows:
+
+<UL><PRE>
+RTEL_PR1. : <B>9100</B>
+RTEL_PR2. : <B>9101</B>
+RTEL_PR3. : <B>9102</B>
+RTEL_PR4. : <B>9103</B>
+RTEL_PR5. : <B>9104</B>
+RTEL_PR6. : <B>9105</B>
+RTEL_PR7. : <B>9106</B>
+RTEL_PR8. : <B>9107</B>
+</PRE></UL>
+
+<!-- NEED 4in -->
+<P>This essentially makes the Axis print server look like a Hewlett
+Packard JetDirect EX print server. Save the file and then upload the
+new <VAR>config</VAR> file using the <CODE>ftp</CODE> command:
+
+<UL><PRE>
+<B>ftp ip-address ENTER</B>
+Connected to ip-address.
+220 Axis NPS ### FTP Printer Server V#.## MON DD YEAR ready.
+ftp> <B>user root ENTER</B>
+331 User name ok, need password
+Password: <B>pass ENTER</B> <I>(this is not echoed)</I>
+230 User logged in
+ftp> <B>put config CONFIG ENTER</B>
+local: config remote: CONFIG
+200 PORT command successful.
+150 Opening data connection for config (192,0,2,2), (mode ascii).
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp> <B>get hardreset ENTER</B>
+local: hardreset remote: hardreset
+200 PORT command successful.
+421 Axis NPS ### hard reset, closing connection.
+ftp> <B>quit ENTER</B>
+221 Goodbye.
+</PRE></UL>
+
+<P>Your Axis print server is now ready for use!
+
+<H2><A NAME="LINKSYS">Configuring Linksys Print Servers</A></H2>
+
+<P>The Linksys print servers can be configured using ARP, RARP, or
+BOOTP. Like older Axis print servers, an additional step must be
+performed to configure the TCP/IP portion of the print server for use
+with CUPS.
+
+<!-- NEED 3in -->
+<P>Each print server contains a configuration file named
+<VAR>CONFIG</VAR> that contains a list of network parameters used by
+the server. To modify this file you must first download it from the
+print server using the <CODE>ftp(1)</CODE> program:
+
+<UL><PRE>
+<B>ftp -n ip-address ENTER</B>
+Connected to ip-address.
+220 Print Server Ready.
+Remote system type is Print.
+ftp> <B>get CONFIG ENTER</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+WARNING! 68 bare linefeeds received in ASCII mode
+File may not have transferred correctly.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp> <B>quit ENTER</B>
+221 Goodbye.
+</PRE></UL>
+
+<!-- NEED 2in -->
+<P>Next, edit the file with your favorite text editor and locate the
+lines beginning with:
+
+<UL><PRE>
+0100 L1_PROUT:P1
+0120 L2_PROUT:P1
+0140 L3_PROUT:P1
+</PRE></UL>
+
+<P>Change the port number for
+each parallel and serial port on the server as follows:
+
+<UL><PRE>
+0100 L1_PROUT:<B>P1</B>
+0120 L2_PROUT:<B>P2</B>
+0140 L3_PROUT:<B>P3</B>
+</PRE></UL>
+
+<!-- NEED 4in -->
+<P>This maps each virtual printer with a physical port. Save the file and then upload the
+new <VAR>CONFIG</VAR> file using the <CODE>ftp</CODE> command:
+
+<UL><PRE>
+<B>ftp -n ip-address ENTER</B>
+Connected to ip-address.
+220 Print Server Ready.
+Remote system type is Print.
+ftp> <B>put CONFIG ENTER</B>
+local: CONFIG remote: CONFIG
+200 Command OK.
+150 Open ASCII Mode Connection.
+226 Transfer complete.
+##### bytes received in #.## seconds (##### Kbytes/s)
+ftp> <B>quit ENTER</B>
+221 Goodbye.
+</PRE></UL>
+
+<P>Your Linksys print server is now ready for use!
+
+<H2><A NAME="LPD_OPTIONS">Configuring LPD Printing Options</A></H2>
+
+<P>The LPD backend supports several options which are included in the
+device URI, e.g.:
+
+<PRE>
+ lpd://server/name?option1=value1+option2=value2+...+optionN=valueN
+</PRE>
+
+<P>The following table summarizes the options and values that are supported:
+
+<!-- NEED 9in -->
+<CENTER><TABLE BORDER="1" WIDTH="80%">
+<TR>
+ <TH>Option=Value</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>banner=off<BR>
+ banner=no<BR>
+ banner=false</TD>
+ <TD VALIGN="TOP">Does not request a LPD banner page for
+ the job. (Default)</TD>
+</TR>
+<TR>
+ <TD>banner=on<BR>
+ banner=yes<BR>
+ banner=true</TD>
+ <TD VALIGN="TOP">Requests a LPD banner page for the
+ job.</TD>
+</TR>
+<TR>
+ <TD>format=c<BR>
+ format=d<BR>
+ format=f<BR>
+ format=g<BR>
+ format=l<BR>
+ format=n<BR>
+ format=o<BR>
+ format=p<BR>
+ format=r<BR>
+ format=t<BR>
+ format=v</TD>
+ <TD VALIGN="TOP">Specifies the LPD format code of the
+ print job. "format=l" is raw output, while "format=o" is PostScript.
+ (Default is "format=l" for raw output)</TD>
+</TR>
+<TR>
+ <TD>manual_copies=off<BR>
+ manual_copies=no<BR>
+ manual_copies=false</TD>
+ <TD VALIGN="TOP">Specifies that the backend should not
+ send multiple copies of a print job in the print data
+ file.</TD>
+</TR>
+<TR>
+ <TD>manual_copies=on<BR>
+ manual_copies=yes<BR>
+ manual_copies=true</TD>
+ <TD VALIGN="TOP">Specifies that the backend should send
+ multiple copies of a print job in the print data file to
+ print more than one copy. (Default)</TD>
+</TR>
+<TR>
+ <TD>order=control,data</TD>
+ <TD VALIGN="TOP">Specifies that the LPD control file
+ should be sent before the print data file.
+ (Default)</TD>
+</TR>
+<TR>
+ <TD>order=data,control=</TD>
+ <TD VALIGN="TOP">Specifies that the print data file
+ should be sent before the LPD control file.</TD>
+</TR>
+<TR>
+ <TD>reserve=off<BR>
+ reserve=no<BR>
+ reserve=false</TD>
+ <TD VALIGN="TOP">Specifies that the backend should not
+ reserve a priviledged source port as required by RFC
+ 1179.</TD>
+</TR>
+<TR>
+ <TD>reserve=on<BR>
+ reserve=yes<BR>
+ reserve=true<BR>
+ reserve=rfc1179</TD>
+ <TD VALIGN="TOP">Specifies that the backend should
+ reserve a priviledges source port from 721 to 731
+ inclusive as required by RFC 1179. This option may cause
+ reduced printing performance when more than 11 LPD
+ printers are defined on the server due to port
+ contention issues.</TD>
+</TR>
+<TR>
+ <TD>reserve=any</TD>
+ <TD VALIGN="TOP">Specifies that the backend should
+ reserve a priviledges source port from 1 to 1023
+ inclusive. This often works with LPD implementations
+ that require a priviledged source port but do not
+ limit it to the range defined by RFC 1179, allowing
+ for more printers to be active at the same time. (Default)</TD>
+</TR>
+<TR>
+ <TD>sanitize_title=off<BR>
+ sanitize_title=no<BR>
+ sanitize_title=false</TD>
+ <TD VALIGN="TOP">Specifies that the backend should not
+ sanitize the job title string. (Default on OSX)</TD>
+</TR>
+<TR>
+ <TD>sanitize_title=on<BR>
+ sanitize_title=yes<BR>
+ sanitize_title=true</TD>
+ <TD VALIGN="TOP">Specifies that the backend should
+ sanitize the job title string. (Default on all but OSX)</TD>
+</TR>
+<TR>
+ <TD>timeout=N</TD>
+ <TD VALIGN="TOP">Specifies the response timeout for all LPD
+ commands and transactions in seconds. (Default is 300 seconds)</TD>
+</TR>
+</TABLE></CENTER>
+
+<H1 ALIGN="RIGHT"><A NAME="PRINTER_DRIVERS">C - Printer Drivers</A></H1>
+
+<P>This appendix lists the printer drivers that are provided with CUPS.
+
+<H2>Printer Drivers</H2>
+
+<P>CUPS includes the following printer drivers:
+
+<UL>
+
+<LI><A HREF="#DYMO">DYMO Label Printer</A>, <VAR>dymo.ppd</VAR>
+
+<LI><A HREF="#EPSON9">EPSON 9-pin Dot Matrix</A>, <VAR>epson9.ppd</VAR>
+
+<LI><A HREF="#EPSON24">EPSON 24-pin Dot Matrix</A>, <VAR>epson24.ppd</VAR>
+
+<LI><A HREF="#STCOLOR">EPSON Stylus Color</A>, <VAR>stcolor.ppd</VAR>
+
+<LI><A HREF="#STPHOTO">EPSON Stylus Photo</A>, <VAR>stphoto.ppd</VAR>
+
+<LI><A HREF="#DESKJET">HP DeskJet</A>, <VAR>deskjet.ppd</VAR>
+
+<LI><A HREF="#LASERJET">HP LaserJet</A>, <VAR>laserjet.ppd</VAR>
+
+</UL>
+
+<H2><A NAME="DYMO">DYMO Label Printer</A></H2>
+
+<P>The DYMO Label Printer driver (<VAR>dymo.ppd</VAR>) supports
+the DYMO LabelWriter 300 series (300/310/315/320/330/330 Turbo)
+thermal label printers. It provides 136, 203, and 300 DPI output
+in black only.
+
+<H2><A NAME="EPSON9">EPSON 9-pin Dot Matrix</A></H2>
+
+<P>The EPSON 9-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+9-pin dot matrix printers that implement the ESC/P command set. It
+provides 60x72, 120x72, and 240x72 DPI output in black only.
+
+<H2><A NAME="EPSON24">EPSON 24-pin Dot Matrix</A></H2>
+
+<P>The EPSON 24-pin Dot Matrix driver (<VAR>epson9.ppd</VAR>) supports
+24-pin dot matrix printers that implement the ESC/P command set. It
+provides 120x180, 180x180, 360x180, and 360x360 DPI output in black
+only.
+
+<H2><A NAME="STCOLOR">EPSON Stylus Color</A></H2>
+
+<P>The EPSON Stylus Color driver (<VAR>stcolor.ppd</VAR>) supports
+EPSON Stylus Color printers that implement the ESC/P2 command set. It
+provides 180, 360, and 720 DPI output in black and color (CMYK).
+
+<H2><A NAME="STPHOTO">EPSON Stylus Photo</A></H2>
+
+<P>The EPSON Stylus Photo driver (<VAR>stphoto.ppd</VAR>) supports
+EPSON Stylus Photo printers that implement the ESC/P2 command set. It
+provides 180, 360, and 720 DPI output in black and color (CMYKcm).
+
+<H2><A NAME="DESKJET">HP DeskJet</A></H2>
+
+<P>The HP DeskJet driver (<VAR>deskjet.ppd</VAR>) supports HP DeskJet
+printers that implement the PCL command set. It provides 150, 300, and
+600 DPI output in black and color (CMYK).
+
+<P>The DeskJet printers that implement the HP-PPA command set (720C,
+722C, 820C, and 1100C) are <B>not</B> supported due to a complete lack
+of documentation and support from Hewlett Packard.
+
+<P>The duplexer provided with the HP DeskJet 900 series printers is also
+not supported for similar reasons.
+
+<H2><A NAME="LASERJET">HP LaserJet</A></H2>
+
+<P>The HP LaserJet driver (<VAR>laserjet.ppd</VAR>) supports HP
+LaserJet printers that implement the PCL command set. It provides 150,
+300, and 600 DPI output in black only and supports the duplexer if
+installed.
+
+<P>LaserJet printers that do not implement PCL (3100, 3150) are not
+supported due to a complete lack of documentation and support from
+Hewlett Packard.
+
+
+<H1 ALIGN="RIGHT"><A NAME="FILES">D - List of Files</A></H1>
+
+<P>This appendix lists the files and directories that are installed for
+the Common UNIX Printing System.
+
+<CENTER><TABLE BORDER="1" WIDTH="80%">
+<TR VALIGN="TOP">
+<TH>Pathname</TH>
+<TH>Description</TH>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/certs/</TD>
+<TD>The location of authentication certificate files for local
+HTTP clients.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/classes.conf</TD>
+<TD>The printer classes configuration file for the scheduler.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/cupsd.conf</TD>
+<TD>The scheduler configuration file.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/interfaces/</TD>
+<TD>The location of System V interface scripts for printers.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/mime.convs</TD>
+<TD>The list of standard file filters included with CUPS.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/mime.types</TD>
+<TD>The list of recognized file types for CUPS.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/ppd/</TD>
+<TD>The location of PostScript Printer Description ("PPD") files for
+printers.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/etc/cups/printers.conf</TD>
+<TD>The printer configuration file for the scheduler.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/cancel</TD>
+<TD>The System V cancel job(s) command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/disable</TD>
+<TD>The System V disable printer command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/enable</TD>
+<TD>The System V enable printer command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lp</TD>
+<TD>The System V print command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lpoptions</TD>
+<TD>Sets user-defined printing options and defaults.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lppasswd</TD>
+<TD>Adds, changes, or removes Digest password accounts.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lpq</TD>
+<TD>The Berkeley status command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lpr</TD>
+<TD>The Berkeley print command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lprm</TD>
+<TD>The Berkeley cancel job(s) command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/bin/lpstat</TD>
+<TD>The System V status command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/include/cups/</TD>
+<TD>CUPS API header files.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib32/libcups.a<BR>
+/usr/lib32/libcupsimage.a</TD>
+<TD>Static libraries (IRIX 6.5)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/libcups.a<BR>
+/usr/lib/libcupsimage.a</TD>
+<TD>Static libraries (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/libcups.sl.2<BR>
+/usr/lib/libcupsimage.sl.2</TD>
+<TD>Shared libraries (HP-UX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib32/libcups.so.2<BR>
+/usr/lib32/libcupsimage.so.2</TD>
+<TD>Shared libraries (IRIX 6.5)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/libcups.so.2<BR>
+/usr/lib/libcupsimage.so.2</TD>
+<TD>Shared libraries (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/libexec/cups/backend/</TD>
+<TD>Backends for various types of printer connections (*BSD and OSX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/cups/backend/</TD>
+<TD>Backends for various types of printer connections (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/libexec/cups/cgi-bin/</TD>
+<TD>CGI programs for the scheduler (*BSD and OSX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/cups/cgi-bin/</TD>
+<TD>CGI programs for the scheduler (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/libexec/cups/daemon/</TD>
+<TD>Daemons for polling and LPD support (*BSD and OSX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/cups/daemon/</TD>
+<TD>Daemons for polling and LPD support (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/libexec/cups/filter/</TD>
+<TD>Filters for various types of files (*BSD and OSX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/cups/filter/</TD>
+<TD>Filters for various types of files (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/locale/</TD>
+<TD>The location of language-specific message files. (System V)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/lib/nls/msg/</TD>
+<TD>The location of language-specific message files. (Compaq Tru64 UNIX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/locale/</TD>
+<TD>The location of language-specific message files. (Linux, *BSD)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/accept</TD>
+<TD>The accept-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/cupsd</TD>
+<TD>The CUPS print scheduler.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/lpadmin</TD>
+<TD>The System V printer administration tool.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/lpc</TD>
+<TD>The Berkeley printer administration tool.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/lpinfo</TD>
+<TD>The get-devices and get-ppds command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/lpmove</TD>
+<TD>The move-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/sbin/reject</TD>
+<TD>The reject-jobs command.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/catman/a_man/<BR>
+/usr/share/catman/u_man/</TD>
+<TD>Man pages (IRIX)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/man/</TD>
+<TD>Man pages (Compaq Tru64 UNIX, HP-UX, Solaris)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/man/</TD>
+<TD>Man pages (all others)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/data/</TD>
+<TD>The location of filter data files.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/data/testprint.ps</TD>
+<TD>The PostScript test page file.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/fonts/</TD>
+<TD>The location of PostScript fonts for the PostScript RIP.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/model/</TD>
+<TD>The location of PostScript Printer Description ("PPD") files and
+interface scripts that may be used to setup a printer queue.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/pstoraster/</TD>
+<TD>Other PostScript RIP initialization files.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/pstoraster/Fontmap</TD>
+<TD>The font mapping file (converts filenames to fontnames)</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/cups/templates/</TD>
+<TD>The location of HTML template files for the web interfaces.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/usr/share/doc/cups/</TD>
+<TD>Documentation and web page data for the scheduler.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/var/log/cups/</TD>
+<TD>The location of scheduler log files.</TD>
+</TR>
+<TR VALIGN="TOP">
+<TD>/var/spool/cups/</TD>
+<TD>The location of print files waiting to be printed.</TD>
+</TR>
+</TABLE></CENTER>
+
+
+<H1 ALIGN="RIGHT"><A NAME="FAQ">E - Troubleshooting Common Problems</A></H1>
+
+<P>This appendix covers some of the common problems first-time users
+encounter when installing and configuring CUPS.
+
+<P>Commercial support for CUPS is available from Easy Software Products.
+For more information please contact us at:
+
+<UL>
+
+<LI>WWW: <A HREF="http://www.easysw.com/cups/">
+<CODE>http://www.easysw.com/cups/</CODE></A>
+
+<LI>EMail: <A HREF="mailto:info@easysw.com">info@easysw.com</A>
+
+<LI>Telephone (M-F, 9-5 EST): +1.301.373.9600
+
+</UL>
+
+<H2>My Applications Don't See the Available Printers</H2>
+
+<P>Many applications read the <VAR>/etc/printcap</VAR> file to
+get a list of available printers.
+
+<P>The default CUPS configuration creates the
+<VAR>/etc/printcap</VAR> file automatically. To enable or
+disable automatic creation and updating of this file, use the <A
+HREF="#Printcap"><CODE>Printcap</CODE></A> directive described
+in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, "Printing System
+Management"</A>.
+
+<H2>CUPS Doesn't Recognize My Username or Password!</H2>
+
+<P>CUPS will ask you for a UNIX username and password when you perform
+printer administration tasks remotely or via a web browser. The default
+configuration requires that you use the <CODE>root</CODE> username and
+the corresponding password to authenticate the request.
+
+<P>CUPS does not allow you to authenticate an administration request
+with an account that has no password for security reasons. If you do
+not have a password on your <CODE>root</CODE> account then you won't be
+able to add printers remotely or via the web interface!
+
+<!-- NEED 2in -->
+<P>To disable password authentication you need to edit the
+<VAR>/etc/cups/cupsd.conf</VAR> file and comment out the
+lines reading:
+
+<UL><PRE>
+AuthType Basic
+AuthClass System
+</PRE></UL>
+
+<P>for the <VAR>/admin</VAR> location. Then restart the CUPS server as
+described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, "Printing System
+Management"</A>.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Disabling password checks will allow any local user to
+change your printer and class configuration, but remote
+administration from another machine will still not be allowed.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2><A NAME="ALLOW_REMOTE">I Can't Do Administration Tasks from Another Machine!</A></H2>
+
+<P>The default CUPS configuration limits administration to the local
+machine. To open up access, edit the <VAR>/etc/cups/cupsd.conf</VAR>
+and comment out the lines reading:
+
+<UL><PRE>
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+</PRE></UL>
+
+<P>for the <VAR>/admin</VAR> location. Then restart the CUPS server as
+described in <A HREF="#PRINTING_MANAGEMENT">Chapter 6, "Printing System
+Management"</A>.</P>
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" CELLPADDING="5" BGCOLOR="#cccccc">
+<TR>
+<TD>
+<B>NOTE:</B>
+
+<P>Allowing administration access from all hosts is a potential
+security risk. Please read <A HREF="#PRINTING_SECURITY">Chapter
+6, "Printing System Management"</A> for a description of these
+risks and ways to minimize them.
+</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 4in -->
+<H2>I Can't Do Administration Tasks from My Web Browser!</H2>
+
+<P>This problem is usually caused by:
+
+<OL>
+
+<LI>not specifying the correct password for the
+root account.
+
+<LI>accessing the CUPS server using the hostname or IP
+address of the server without enabling remote access for
+administration functions. This can be corrected by following
+the instructions in the <A HREF="#ALLOW_REMOTE">"I Can't Do
+Administration Tasks from Another Machine!"</A> section earlier
+in this appendix.
+
+<LI>not setting a password on the root account. CUPS will not
+authenticate a user account that does not have a password for
+security reasons.
+
+<LI>authenticating using an account other than root, but the
+account you are using is not a member of the system group.
+
+<LI>configuring CUPS to use Digest authentication, but
+your web browser does not support Digest authentication.
+
+</OL>
+
+<H2>Connection Refused Messages</H2>
+
+<P>Under normal circumstances, "connection refused" messages for a
+networked printer should be expected from time to time. Most network
+interfaces only allow a single connection to be made at any given time
+(one job at a time) and will refuse access to all other systems while
+the first connection is active. CUPS automatically retries the
+connection once every 30 seconds.
+
+<P>If the problem persists and you are unable to print any jobs to the printer,
+verify that another machine is not maintaining a connection with the printer,
+and that you have selected the proper port or printer name for the printer.
+
+<P>Also, most external print servers will refuse connections if the connected
+printer is turned off or is off-line. Verify that the affected printer is
+turned on and is online.
+
+<H2>Write Error Messages</H2>
+
+<P>If you get "write error" messages on a printer queue the printer
+interface (usually a Hewlett Packard JetDirect interface) has timed out
+and reset the network connection from your workstation.
+
+<P>The error is caused by that startup delay between the initial setup
+of the printer or plotter and the first page of print data that is
+sent.
+
+<!-- NEED 3in -->
+<P>To correct the problem, change the idle timeout on the interface to at least
+180 seconds or 3 minutes. To change the timeout on a Hewlett Packard
+JetDirect interface, type:
+
+<UL><PRE>
+<B>telnet ip-address ENTER</B>
+
+Trying ip-address...
+Connected to ip-address.
+Escape character is `^]'.
+
+Please type [Return] two times, to initialize telnet configuration
+For HELP type "?"
+> <B>idle-timeout: 180 ENTER</B>
+> <B>quit ENTER</B>
+</PRE></UL>
+
+</BODY>
+</HTML>
+
diff --git a/doc/sdd.html b/doc/sdd.html
new file mode 100644
index 000000000..87c826576
--- /dev/null
+++ b/doc/sdd.html
@@ -0,0 +1,606 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Design Description</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SDD-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Design Description</H1></A><BR>
+CUPS-SDD-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Design Overview</A></B>
+<UL>
+<LI><A HREF="#3_1">3.1 Backends</A></LI>
+<UL>
+<LI><A HREF="#3_1_1">3.1.1 ipp</A></LI>
+<LI><A HREF="#3_1_2">3.1.2 lpd</A></LI>
+<LI><A HREF="#3_1_3">3.1.3 parallel</A></LI>
+<LI><A HREF="#3_1_4">3.1.4 serial</A></LI>
+<LI><A HREF="#3_1_5">3.1.5 socket</A></LI>
+<LI><A HREF="#3_1_6">3.1.6 usb</A></LI>
+</UL>
+<LI><A HREF="#3_2">3.2 Berkeley Commands</A></LI>
+<UL>
+<LI><A HREF="#3_2_1">3.2.1 lpc</A></LI>
+<LI><A HREF="#3_2_2">3.2.2 lpq</A></LI>
+<LI><A HREF="#3_2_3">3.2.3 lpr</A></LI>
+<LI><A HREF="#3_2_4">3.2.4 lprm</A></LI>
+</UL>
+<LI><A HREF="#3_3">3.3 CGI</A></LI>
+<UL>
+<LI><A HREF="#3_3_1">3.3.1 admin.cgi</A></LI>
+<LI><A HREF="#3_3_2">3.3.2 classes.cgi</A></LI>
+<LI><A HREF="#3_3_3">3.3.3 jobs.cgi</A></LI>
+<LI><A HREF="#3_3_4">3.3.4 printers.cgi</A></LI>
+</UL>
+<LI><A HREF="#3_4">3.4 CUPS Application Programmers Interface</A></LI>
+<UL>
+<LI><A HREF="#3_4_1">3.4.1 Convenience Functions</A></LI>
+<LI><A HREF="#3_4_2">3.4.2 HTTP Functions</A></LI>
+<LI><A HREF="#3_4_3">3.4.3 IPP Functions</A></LI>
+<LI><A HREF="#3_4_4">3.4.4 Language Functions</A></LI>
+<LI><A HREF="#3_4_5">3.4.5 PPD Functions</A></LI>
+</UL>
+<LI><A HREF="#3_5">3.5 CUPS Imaging Library</A></LI>
+<UL>
+<LI><A HREF="#3_5_1">3.5.1 Colorspace Conversion Functions</A></LI>
+<LI><A HREF="#3_5_2">3.5.2 Color Management Functions</A></LI>
+<LI><A HREF="#3_5_3">3.5.3 Image Management Functions</A></LI>
+<LI><A HREF="#3_5_4">3.5.4 Scaling Functions</A></LI>
+<LI><A HREF="#3_5_5">3.5.5 Image File Functions</A></LI>
+<LI><A HREF="#3_5_6">3.5.6 Raster Functions</A></LI>
+</UL>
+<LI><A HREF="#3_6">3.6 Daemons</A></LI>
+<UL>
+<LI><A HREF="#3_6_1">3.6.1 Line Printer Daemon</A></LI>
+<LI><A HREF="#3_6_2">3.6.2 Polling Daemon</A></LI>
+</UL>
+<LI><A HREF="#3_7">3.7 Filters</A></LI>
+<UL>
+<LI><A HREF="#3_7_1">3.7.1 hpgltops</A></LI>
+<LI><A HREF="#3_7_2">3.7.2 imagetops</A></LI>
+<LI><A HREF="#3_7_3">3.7.3 imagetoraster</A></LI>
+<LI><A HREF="#3_7_4">3.7.4 pdftops</A></LI>
+<LI><A HREF="#3_7_5">3.7.5 pstops</A></LI>
+<LI><A HREF="#3_7_6">3.7.6 pstoraster</A></LI>
+<LI><A HREF="#3_7_7">3.7.7 rastertoepson</A></LI>
+<LI><A HREF="#3_7_8">3.7.8 rastertohp</A></LI>
+<LI><A HREF="#3_7_9">3.7.9 texttops</A></LI>
+</UL>
+<LI><A HREF="#3_8">3.8 Scheduler</A></LI>
+<UL>
+<LI><A HREF="#3_8_1">3.8.1 Authorization</A></LI>
+<LI><A HREF="#3_8_2">3.8.2 Classes</A></LI>
+<LI><A HREF="#3_8_3">3.8.3 Client</A></LI>
+<LI><A HREF="#3_8_4">3.8.4 Configuration</A></LI>
+<LI><A HREF="#3_8_5">3.8.5 Devices</A></LI>
+<LI><A HREF="#3_8_6">3.8.6 Directory Services</A></LI>
+<LI><A HREF="#3_8_7">3.8.7 IPP</A></LI>
+<LI><A HREF="#3_8_8">3.8.8 Jobs</A></LI>
+<LI><A HREF="#3_8_9">3.8.9 Logging</A></LI>
+<LI><A HREF="#3_8_10">3.8.10 Main</A></LI>
+<LI><A HREF="#3_8_11">3.8.11 MIME</A></LI>
+<LI><A HREF="#3_8_12">3.8.12 PPDs</A></LI>
+<LI><A HREF="#3_8_13">3.8.13 Printers</A></LI>
+</UL>
+<LI><A HREF="#3_9">3.9 System V Commands</A></LI>
+<UL>
+<LI><A HREF="#3_9_1">3.9.1 accept</A></LI>
+<LI><A HREF="#3_9_2">3.9.2 cancel</A></LI>
+<LI><A HREF="#3_9_3">3.9.3 disable</A></LI>
+<LI><A HREF="#3_9_4">3.9.4 enable</A></LI>
+<LI><A HREF="#3_9_5">3.9.5 lp</A></LI>
+<LI><A HREF="#3_9_6">3.9.6 lpadmin</A></LI>
+<LI><A HREF="#3_9_7">3.9.7 lpinfo</A></LI>
+<LI><A HREF="#3_9_8">3.9.8 lpmove</A></LI>
+<LI><A HREF="#3_9_9">3.9.9 lpoptions</A></LI>
+<LI><A HREF="#3_9_10">3.9.10 lpstat</A></LI>
+<LI><A HREF="#3_9_11">3.9.11 reject</A></LI>
+</UL>
+</UL>
+<B><A HREF="#4">A Glossary</A></B>
+<UL>
+<LI><A HREF="#4_1">A.1 Terms</A></LI>
+<LI><A HREF="#4_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+ This software design description document provides general information
+ on the architecture and coding of the Common UNIX Printing System
+ (&quot;CUPS&quot;) Version 1.1.
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+ This software design description document is organized into the
+ following sections:
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Design Overview</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Design Overview</A></H1>
+ CUPS is composed of 9 software sub-systems that operate together to
+ perform common printing tasks:
+<UL>
+<LI>Backends</LI>
+<LI>Berkeley Commands</LI>
+<LI>CGI</LI>
+<LI>CUPS Application Programmers Interface</LI>
+<LI>CUPS Imaging Library</LI>
+<LI>Daemons</LI>
+<LI>Filters</LI>
+<LI>Scheduler</LI>
+<LI>System V Commands</LI>
+</UL>
+<H2><A NAME="3_1">3.1 Backends</A></H2>
+ The backends implement communications over a number of different
+ interfaces. All backends are called with a common set of arguments:
+<UL>
+<LI>Device URI - the Uniform Resource Identifier for the output device
+ (e.g. <CODE>parallel:/dev/plp</CODE>, <CODE>ipp://hostname/resource</CODE>
+).</LI>
+<LI>Job Identifier - the job identifier for this job (integer).</LI>
+<LI>User Name - the user associated with this job (name string).</LI>
+<LI>Title - the title/job-name associated with this job (name string).</LI>
+<LI>Copies - the number of copies required (integer).</LI>
+<LI>Options - the options associated with this job (space separated
+ option strings).</LI>
+<LI>Filename (optional) - the file to print; if this option is not
+ specified, the backend must read the print file from the standard
+ input.</LI>
+</UL>
+<P>Backends are named using the scheme of the URI, so a URI of
+ &quot;ipp://hostname/resource&quot; would be processed by the &quot;ipp&quot; backend.</P>
+<H3><A NAME="3_1_1">3.1.1 ipp</A></H3>
+<P>The ipp backend sends the specified job to a network printer or host
+ using the Internet Printing Protocol. The URI is as specified by the <CODE>
+printer-uri-supported</CODE> attribute from the printer or host.</P>
+<H3><A NAME="3_1_2">3.1.2 lpd</A></H3>
+<P>The lpd backend sends the specified job to a network printer or host
+ using the Line Printer Daemon protocol. The URI is of the form:</P>
+<UL>
+<PRE>lpd://hostname/queue
+</PRE>
+</UL>
+<H3><A NAME="3_1_3">3.1.3 parallel</A></H3>
+<P>The parallel backend sends the specified job to a local printer
+ connected via the specified parallel port device. The URI is of the
+ form:</P>
+<UL>
+<PRE>parallel:/dev/file
+</PRE>
+</UL>
+<H3><A NAME="3_1_4">3.1.4 serial</A></H3>
+<P>The serial backend sends the specified job to a local printer
+ connected via the specified serial port device. The URI is of the form:</P>
+<UL>
+<PRE>serial:/dev/file?option[+option+...]
+</PRE>
+</UL>
+ The options can be any combination of the following:
+<UL>
+<LI><CODE>baud=<I>rate</I></CODE> - Sets the baud rate for the device.</LI>
+<LI><CODE>bits=<I>7 or 8</I></CODE> - Sets the number of data bits.</LI>
+<LI><CODE>parity=<I>even</I></CODE> - Sets even parity checking.</LI>
+<LI><CODE>parity=<I>odd</I></CODE> - Sets odd parity checking.</LI>
+<LI><CODE>parity=<I>none</I></CODE> - Turns parity checking off.</LI>
+<LI><CODE>flow=dtrdsr<I></I></CODE> - Turns DTR/DSR (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=hard<I></I></CODE> - Turns RTS/CTS (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=none<I></I></CODE> - Turns flow control off.</LI>
+<LI><CODE>flow=rtscts<I></I></CODE> - Turns RTS/CTS (hardware) flow
+ control on.</LI>
+<LI><CODE>flow=xonxoff<I></I></CODE> - Turns XON/XOFF (software) flow
+ control on.</LI>
+</UL>
+<H3><A NAME="3_1_5">3.1.5 socket</A></H3>
+<P>The socket backend sends the specified job to a network host using
+ the AppSocket protocol commonly used by Hewlett-Packard and Tektronix
+ printers. The URI is of the form:</P>
+<UL>
+<PRE>socket://hostname[:port]
+</PRE>
+</UL>
+ The default port number is 9100.
+<H3><A NAME="3_1_6">3.1.6 usb</A></H3>
+<P>The usb backend sends the specified job to a local printer connected
+ via the specified usb port device. The URI is of the form:</P>
+<UL>
+<PRE>usb:/dev/file
+</PRE>
+</UL>
+<H2><A NAME="3_2">3.2 Berkeley Commands</A></H2>
+<P>The Berkeley commands provide a simple command-line interface to CUPS
+ to submit and control print jobs. It is provided for compatibility with
+ existing software that is hardcoded to use the Berkeley commands.</P>
+<H3><A NAME="3_2_1">3.2.1 lpc</A></H3>
+ The lpc command allows users and administrators to check the status and
+ control print queues. The version provided with CUPS supports the
+ following commands:
+<UL>
+<LI>quit - Quits the lpc command.</LI>
+<LI>status - Shows the status of printers and jobs in the queue.</LI>
+</UL>
+<H3><A NAME="3_2_2">3.2.2 lpq</A></H3>
+<P>The lpq command shows the current queue status.</P>
+<H3><A NAME="3_2_3">3.2.3 lpr</A></H3>
+<P>The lpr command submits a job for printing. The CUPS version of lpr
+ silently ignores the &quot;i&quot;, &quot;t&quot;, &quot;m&quot;, &quot;h&quot;, and &quot;s&quot; options.</P>
+<H3><A NAME="3_2_4">3.2.4 lprm</A></H3>
+<P>The lprm removes one or more print jobs.</P>
+<H2><A NAME="3_3">3.3 CGI</A></H2>
+<P>The Common Gateway Interface (CGI) programs provide a web-based
+ status interface to monitor the status of printers, classes, and jobs.
+ Each of the CGIs utilize HTML template files that can be customized to
+ provide alternate appearances.</P>
+<H3><A NAME="3_3_1">3.3.1 admin.cgi</A></H3>
+<P>The admin CGI provides administration interfaces for printers and
+ classes. The user can add, modify, delete, start, stop, and configure
+ printers and classes using &quot;wizard&quot; interfaces.</P>
+<H3><A NAME="3_3_2">3.3.2 classes.cgi</A></H3>
+<P>The classes CGI lists the available printer classes and any pending
+ jobs for the class. The user can click on individual classes to limit
+ the display and click on jobs to see the job status.</P>
+<H3><A NAME="3_3_3">3.3.3 jobs.cgi</A></H3>
+<P>The jobs CGI lists the queued print jobs in order of priority. The
+ list can be limited by printer or job.</P>
+<H3><A NAME="3_3_4">3.3.4 printers.cgi</A></H3>
+<P>The printers CGI lists the available printer queues and any pending
+ jobs for the printer. The user can click on individual printers to
+ limit the display and click on jobs to see the job status.</P>
+<H2><A NAME="3_4">3.4 CUPS Application Programmers Interface</A></H2>
+<P>The CUPS Application Programmers Interface (&quot;API&quot;) provides common
+ convenience, HTTP, IPP, language, and PPD functions used by the CUPS
+ software.</P>
+<H3><A NAME="3_4_1">3.4.1 Convenience Functions</A></H3>
+<P>Convenience functions are provided to submit an IPP request, send a
+ print file, cancel a job, get a list of available printers, get a list
+ of available classes, get the default printer or class, get the default
+ server name, get the local username, and get a password string.</P>
+<H3><A NAME="3_4_2">3.4.2 HTTP Functions</A></H3>
+<P>The HTTP functions provide functions to connect to HTTP servers,
+ issue requests, read data from a server, and write data to a server.</P>
+<H3><A NAME="3_4_3">3.4.3 IPP Functions</A></H3>
+<P>The IPP function provide functions to manage IPP request data and
+ attributes, read IPP responses from a server, and write IPP requests to
+ a server.</P>
+<H3><A NAME="3_4_4">3.4.4 Language Functions</A></H3>
+<P>The language functions provide a standard interface for retrieving
+ common textual messages for a particular locale and determining the
+ correct encoding (e.g. US ASCII, UTF-8, ISO-8859-1, etc.)</P>
+<H3><A NAME="3_4_5">3.4.5 PPD Functions</A></H3>
+<P>The PostScript Printer Description functions manage PPD files, select
+ options, check for option conflicts, and emit selected options in the
+ correct order.</P>
+<H2><A NAME="3_5">3.5 CUPS Imaging Library</A></H2>
+<P>The CUPS imaging library provides colorspace conversion, color
+ management, image management, scaling, image file, and raster functions
+ used by the CUPS raster filters.</P>
+<H3><A NAME="3_5_1">3.5.1 Colorspace Conversion Functions</A></H3>
+<P>The colorspace conversion functions handle conversion of grayscale
+ and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces.</P>
+<H3><A NAME="3_5_2">3.5.2 Color Management Functions</A></H3>
+<P>The color management functions handle gamut mapping and density
+ correction. These are integrated with the colorspace conversion
+ functions so that colorspace conversion and color management are
+ processed in a single step.</P>
+<H3><A NAME="3_5_3">3.5.3 Image Management Functions</A></H3>
+<P>The image management functions manage a tiled image database that is
+ swapped to/from disk as needed.</P>
+<H3><A NAME="3_5_4">3.5.4 Scaling Functions</A></H3>
+<P>The scaling functions provide image scaling services using
+ nearest-neighbor sampling and bilinear interpolation as appropriate.</P>
+<H3><A NAME="3_5_5">3.5.5 Image File Functions</A></H3>
+<P>The image file functions handle loading of all image file formats.</P>
+<H3><A NAME="3_5_6">3.5.6 Raster Functions</A></H3>
+<P>The raster functions manage streams of CUPS raster data (described in
+ the Interface Design Document) used by non-PostScript printer drivers
+ and raster filters.</P>
+<H2><A NAME="3_6">3.6 Daemons</A></H2>
+<P>The daemons provide additional network functions for the scheduler.
+ Currently only two daemons are provided with CUPS.</P>
+<H3><A NAME="3_6_1">3.6.1 Line Printer Daemon</A></H3>
+<P>The line printer daemon provides remote LPD client support and is run
+ by the <CODE>inetd(8)</CODE> daemon as needed.</P>
+<H3><A NAME="3_6_2">3.6.2 Polling Daemon</A></H3>
+<P>The polling daemon is used to poll a remote server for a list of
+ available printers and provide it to the scheduler for addition. A
+ separate polling daemon is run by the scheduler for every remote system
+ listed for polling in the scheduler configuration file.</P>
+<H2><A NAME="3_7">3.7 Filters</A></H2>
+<P>The filters implement file conversion services for CUPS. All filters
+ are called with a common set of arguments:</P>
+<UL>
+<LI>Printer name - the name of the destination printer (name string).</LI>
+<LI>Job Identifier - the job identifier for this job (integer).</LI>
+<LI>User Name - the user associated with this job (name string).</LI>
+<LI>Title - the title/job-name associated with this job (name string).</LI>
+<LI>Copies - the number of copies required (integer).</LI>
+<LI>Options - the options associated with this job (space separated
+ option strings).</LI>
+<LI>Filename (optional) - the file to print; if this option is not
+ specified, the filter must read the input file from the standard input.</LI>
+</UL>
+<P>Filters are added to the MIME conversion data file and implement all
+ necessary conversions from one file type to another.</P>
+<H3><A NAME="3_7_1">3.7.1 hpgltops</A></H3>
+<P>The hpgltops filter converts HP-GL/2 files into PostScript.</P>
+<H3><A NAME="3_7_2">3.7.2 imagetops</A></H3>
+<P>The imagetops filter converts image files into PostScript.</P>
+<H3><A NAME="3_7_3">3.7.3 imagetoraster</A></H3>
+<P>The imagetoraster filter converts image files into CUPS raster data.</P>
+<H3><A NAME="3_7_4">3.7.4 pdftops</A></H3>
+<P>The pdftops filter converts PDF files into PostScript.</P>
+<H3><A NAME="3_7_5">3.7.5 pstops</A></H3>
+<P>The pstops filter inserts printer-specific commands from PPD files
+ and performs page filtering as requested by the user.</P>
+<H3><A NAME="3_7_6">3.7.6 pstoraster</A></H3>
+<P>The pstoraster filter converts PostScript program data into CUPS
+ raster data.</P>
+<H3><A NAME="3_7_7">3.7.7 rastertoepson</A></H3>
+<P>The rastertoepson filter handles converting CUPS raster data to ESC/P
+ and supports both color and black-and-white printers.</P>
+<H3><A NAME="3_7_8">3.7.8 rastertohp</A></H3>
+<P>The rastertohp filter handles converting CUPS raster data to HP-PCL
+ and supports both color and black-and-white printers.</P>
+<H3><A NAME="3_7_9">3.7.9 texttops</A></H3>
+<P>The texttops filter converts text files into PostScript.</P>
+<H2><A NAME="3_8">3.8 Scheduler</A></H2>
+<P>The scheduler is a fully-functional HTTP/1.1 and IPP/1.1 server that
+ manages the printers, classes, and jobs in the system. It also handles
+ a simple broadcast-based directory service so that remote print queues
+ and classes can be accessed transparently from the local system.</P>
+<H3><A NAME="3_8_1">3.8.1 Authorization</A></H3>
+<P>The authorization module is responsible for performing access control
+ and authentication for all HTTP and IPP requests entering the system.</P>
+<H3><A NAME="3_8_2">3.8.2 Classes</A></H3>
+<P>The classes module is responsible for managing printer classes in the
+ system. Each class is a collection of local and/or remote printers. The
+ classes module also reads and writes the classes configuration file.</P>
+<H3><A NAME="3_8_3">3.8.3 Client</A></H3>
+<P>The client module is responsible for all HTTP client communications.
+ It handles listening on selected interfaces, accepting connections from
+ prospective clients, processing incoming HTTP requests, and sending
+ HTTP responses to those requests. The client module also is responsible
+ for executing the external CGI programs as needed to support web-based
+ printer, class, and job status monitoring and administration.</P>
+<P>Once authorized, all IPP requests are sent to the IPP module.</P>
+<H3><A NAME="3_8_4">3.8.4 Configuration</A></H3>
+<P>The configuration module is responsible for reading the CUPS
+ configuration file and initializing the appropriate data structures and
+ values. The configuration module also stops CUPS services before
+ reading the configuration file and restarts them after the
+ configuration file has been read.</P>
+<H3><A NAME="3_8_5">3.8.5 Devices</A></H3>
+<P>The devices module is responsible for managing the list of available
+ devices for the CUPS-Get-Devices operation.</P>
+<H3><A NAME="3_8_6">3.8.6 Directory Services</A></H3>
+<P>The directory services module sends and recieves printer state
+ information over a broadcast socket. Remote printers and classes are
+ automatically added to or removed from the local printer and class
+ lists as needed.</P>
+<P>The directory services module can only recieve printer state
+ information over a single UDP port, however it can broadcast to
+ multiple addresses and ports as needed.</P>
+<H3><A NAME="3_8_7">3.8.7 IPP</A></H3>
+<P>The IPP module handles IPP requests and acts accordingly. URI
+ validation is also performed here, as a client can post IPP data to any
+ URI on the server which might sidestep the access control or
+ authentication of the HTTP server.</P>
+<H3><A NAME="3_8_8">3.8.8 Jobs</A></H3>
+<P>The jobs module manages print jobs, starts filter and backend
+ processes for jobs to be printed, and monitors status messages from
+ those filters and backends.</P>
+<H3><A NAME="3_8_9">3.8.9 Logging</A></H3>
+<P>The logging module manages the access, error, and page log files that
+ are generated by the scheduler.</P>
+<H3><A NAME="3_8_10">3.8.10 Main</A></H3>
+<P>The main module is responsible for timing out and dispatching input
+ and output for client connections. It also watches for incoming <CODE>
+SIGHUP</CODE> and <CODE>SIGCHLD</CODE> signals, reloads the server
+ configuration files as needed, and handles child process errors and
+ exits.</P>
+<H3><A NAME="3_8_11">3.8.11 MIME</A></H3>
+<P>The Multimedia Internet Mail Exchange module manages a MIME type and
+ conversion database that supports file typing by extension and content
+ and least-cost file filtering from a source to a destination file type.</P>
+<H3><A NAME="3_8_12">3.8.12 PPDs</A></H3>
+<P>The PPDs module is responsible for managing the list of available PPD
+ files for the CUPS-Get-PPDs operation.</P>
+<H3><A NAME="3_8_13">3.8.13 Printers</A></H3>
+<P>The printers module is responsible for managing printers and PPD
+ files in the system. The printers module also reads and writes the
+ printers configuration file.</P>
+<H2><A NAME="3_9">3.9 System V Commands</A></H2>
+<P>The System V commands provide a robust command-line interface to CUPS
+ to submit and control printers and jobs.</P>
+<H3><A NAME="3_9_1">3.9.1 accept</A></H3>
+<P>The accept command tells the scheduler to accept new jobs for
+ specific printers.</P>
+<H3><A NAME="3_9_2">3.9.2 cancel</A></H3>
+<P>The cancel command tells the scheduler to cancel one or more jobs
+ that are queued for printing.</P>
+<H3><A NAME="3_9_3">3.9.3 disable</A></H3>
+<P>The disable command tells the scheduler to stop printing jobs on the
+ specified printers.</P>
+<H3><A NAME="3_9_4">3.9.4 enable</A></H3>
+<P>The enable command tells the scheduler to start printing jobs on the
+ specified printers.</P>
+<H3><A NAME="3_9_5">3.9.5 lp</A></H3>
+<P>The lp command submits submits files for printing. Unlike the
+ standard System V lp command, a single CUPS lp command will generate a
+ separate job ID for each file that is printed. Also, the Solaris &quot;f&quot;,
+ &quot;H&quot;, &quot;P&quot;, &quot;S&quot;, and &quot;y&quot; options are silently ignored.</P>
+<H3><A NAME="3_9_6">3.9.6 lpadmin</A></H3>
+<P>The lpadmin command manages printer queues and classes. The Solaris
+ &quot;A&quot;, &quot;F&quot;, &quot;I&quot;, &quot;M&quot;, &quot;P&quot;, &quot;Q&quot;, &quot;S&quot;, &quot;T&quot;, &quot;U&quot;, &quot;W&quot;, &quot;f&quot;, &quot;l&quot;, &quot;m&quot;, &quot;o&quot;,
+ &quot;s&quot;, &quot;t&quot;, and &quot;u&quot; options are not supported, and new options &quot;P&quot; (PPD
+ file) and &quot;E&quot; (enable and accept) are provided to configure
+ CUPS-specific features.</P>
+<H3><A NAME="3_9_7">3.9.7 lpinfo</A></H3>
+<P>The lpinfo command lists the available PPD files or devices as
+ selected by the user.</P>
+<H3><A NAME="3_9_8">3.9.8 lpmove</A></H3>
+<P>The lpmove command moves a print job to a new destination.</P>
+<H3><A NAME="3_9_9">3.9.9 lpoptions</A></H3>
+<P>The lpoptions command manages user-defined printers and options.</P>
+<H3><A NAME="3_9_10">3.9.10 lpstat</A></H3>
+<P>The lpstat command lists printers, classes, and jobs as requested by
+ the user.</P>
+<H3><A NAME="3_9_11">3.9.11 reject</A></H3>
+<P>The reject command tells the scheduler not to accept new jobs for
+ specific printers.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="4">A Glossary</A></H1>
+<H2><A NAME="4_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="4_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/sdd.pdf b/doc/sdd.pdf
new file mode 100644
index 000000000..e3913ddf7
--- /dev/null
+++ b/doc/sdd.pdf
Binary files differ
diff --git a/doc/sdd.shtml b/doc/sdd.shtml
new file mode 100644
index 000000000..71fb48ba9
--- /dev/null
+++ b/doc/sdd.shtml
@@ -0,0 +1,564 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SDD-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Design Description</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+This software design description document provides general information
+on the architecture and coding of the Common UNIX Printing System
+(&quot;CUPS&quot;) Version 1.1.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+This software design description document is organized into the
+following sections:
+
+<UL>
+
+ <LI>1 - Scope
+
+ <LI>2 - References
+
+ <LI>3 - Design Overview
+
+ <LI>A - Glossary
+
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Design Overview</H1>
+
+CUPS is composed of 9 software sub-systems that operate together to
+perform common printing tasks:
+
+<UL>
+
+ <LI>Backends
+
+ <LI>Berkeley Commands
+
+ <LI>CGI
+
+ <LI>CUPS Application Programmers Interface
+
+ <LI>CUPS Imaging Library
+
+ <LI>Daemons
+
+ <LI>Filters
+
+ <LI>Scheduler
+
+ <LI>System V Commands
+
+</UL>
+
+<H2>Backends</H2>
+
+The backends implement communications over a number of different interfaces.
+All backends are called with a common set of arguments:
+
+<UL>
+
+ <LI>Device URI - the Uniform Resource Identifier for the output device
+ (e.g. <CODE>parallel:/dev/plp</CODE>,
+ <CODE>ipp://hostname/resource</CODE>).
+
+ <LI>Job Identifier - the job identifier for this job (integer).
+
+ <LI>User Name - the user associated with this job (name string).
+
+ <LI>Title - the title/job-name associated with this job (name string).
+
+ <LI>Copies - the number of copies required (integer).
+
+ <LI>Options - the options associated with this job (space separated
+ option strings).
+
+ <LI>Filename (optional) - the file to print; if this option is not
+ specified, the backend must read the print file from the standard
+ input.
+
+</UL>
+
+<P>Backends are named using the scheme of the URI, so a URI of
+"ipp://hostname/resource" would be processed by the "ipp" backend.
+
+<H3>ipp</H3>
+
+<P>The ipp backend sends the specified job to a network printer or host using
+the Internet Printing Protocol. The URI is as specified by the
+<CODE>printer-uri-supported</CODE> attribute from the printer or host.
+
+<H3>lpd</H3>
+
+<P>The lpd backend sends the specified job to a network printer or host using
+the Line Printer Daemon protocol. The URI is of the form:
+
+<UL><PRE>lpd://hostname/queue
+</PRE></UL>
+
+<H3>parallel</H3>
+
+<P>The parallel backend sends the specified job to a local printer connected
+via the specified parallel port device. The URI is of the form:
+
+<UL><PRE>parallel:/dev/file
+</PRE></UL>
+
+<H3>serial</H3>
+
+<P>The serial backend sends the specified job to a local printer connected
+via the specified serial port device. The URI is of the form:
+
+<UL><PRE>serial:/dev/file?option[+option+...]
+</PRE></UL>
+
+The options can be any combination of the following:
+
+<UL>
+
+ <LI><CODE>baud=<I>rate</I></CODE> - Sets the baud rate for the device.
+
+ <LI><CODE>bits=<I>7 or 8</I></CODE> - Sets the number of data bits.
+
+ <LI><CODE>parity=<I>even</I></CODE> - Sets even parity checking.
+
+ <LI><CODE>parity=<I>odd</I></CODE> - Sets odd parity checking.
+
+ <LI><CODE>parity=<I>none</I></CODE> - Turns parity checking off.
+
+ <LI><CODE>flow=dtrdsr<I></I></CODE> - Turns DTR/DSR (hardware) flow
+ control on.
+
+ <LI><CODE>flow=hard<I></I></CODE> - Turns RTS/CTS
+ (hardware) flow control on.
+
+ <LI><CODE>flow=none<I></I></CODE> - Turns flow control off.
+
+ <LI><CODE>flow=rtscts<I></I></CODE> - Turns RTS/CTS
+ (hardware) flow control on.
+
+ <LI><CODE>flow=xonxoff<I></I></CODE> - Turns XON/XOFF
+ (software) flow control on.
+
+</UL>
+
+<H3>socket</H3>
+
+<P>The socket backend sends the specified job to a network host using the
+AppSocket protocol commonly used by Hewlett-Packard and Tektronix
+printers. The URI is of the form:
+
+<UL><PRE>socket://hostname[:port]
+</PRE></UL>
+
+The default port number is 9100.
+
+<H3>usb</H3>
+
+<P>The usb backend sends the specified job to a local printer connected
+via the specified usb port device. The URI is of the form:
+
+<UL><PRE>usb:/dev/file
+</PRE></UL>
+
+<H2>Berkeley Commands</H2>
+
+<P>The Berkeley commands provide a simple command-line interface to CUPS
+to submit and control print jobs. It is provided for compatibility with
+existing software that is hardcoded to use the Berkeley commands.
+
+<H3>lpc</H3>
+
+The lpc command allows users and administrators to check the status and
+control print queues. The version provided with CUPS supports the following
+commands:
+
+<UL>
+
+ <LI>quit - Quits the lpc command.
+
+ <LI>status - Shows the status of printers and jobs in the queue.
+
+</UL>
+
+<H3>lpq</H3>
+
+<P>The lpq command shows the current queue status.
+
+<H3>lpr</H3>
+
+<P>The lpr command submits a job for printing. The CUPS version of lpr silently
+ignores the "i", "t", "m", "h", and "s" options.
+
+<H3>lprm</H3>
+
+<P>The lprm removes one or more print jobs.
+
+<H2>CGI</H2>
+
+<P>The Common Gateway Interface (CGI) programs provide a web-based
+status interface to monitor the status of printers, classes, and jobs.
+Each of the CGIs utilize HTML template files that can be customized to
+provide alternate appearances.
+
+<H3>admin.cgi</H3>
+
+<P>The admin CGI provides administration interfaces for printers and
+classes. The user can add, modify, delete, start, stop, and configure
+printers and classes using "wizard" interfaces.
+
+<H3>classes.cgi</H3>
+
+<P>The classes CGI lists the available printer classes and any pending
+jobs for the class. The user can click on individual classes to limit
+the display and click on jobs to see the job status.
+
+<H3>jobs.cgi</H3>
+
+<P>The jobs CGI lists the queued print jobs in order of priority. The
+list can be limited by printer or job.
+
+<H3>printers.cgi</H3>
+
+<P>The printers CGI lists the available printer queues and any pending
+jobs for the printer. The user can click on individual printers to
+limit the display and click on jobs to see the job status.
+
+<H2>CUPS Application Programmers Interface</H2>
+
+<P>The CUPS Application Programmers Interface ("API") provides common
+convenience, HTTP, IPP, language, and PPD functions used by the CUPS
+software.
+
+<H3>Convenience Functions</H3>
+
+<P>Convenience functions are provided to submit an IPP request, send a
+print file, cancel a job, get a list of available printers, get a list
+of available classes, get the default printer or class, get the default
+server name, get the local username, and get a password string.
+
+<H3>HTTP Functions</H3>
+
+<P>The HTTP functions provide functions to connect to HTTP servers,
+issue requests, read data from a server, and write data to a server.
+
+<H3>IPP Functions</H3>
+
+<P>The IPP function provide functions to manage IPP request data and
+attributes, read IPP responses from a server, and write IPP requests to
+a server.
+
+<H3>Language Functions</H3>
+
+<P>The language functions provide a standard interface for retrieving
+common textual messages for a particular locale and determining the
+correct encoding (e.g. US ASCII, UTF-8, ISO-8859-1, etc.)
+
+<H3>PPD Functions</H3>
+
+<P>The PostScript Printer Description functions manage PPD files,
+select options, check for option conflicts, and emit selected options
+in the correct order.
+
+<H2>CUPS Imaging Library</H2>
+
+<P>The CUPS imaging library provides colorspace conversion, color
+management, image management, scaling, image file, and raster functions
+used by the CUPS raster filters.
+
+<H3>Colorspace Conversion Functions</H3>
+
+<P>The colorspace conversion functions handle conversion of grayscale
+and RGB colors to grayscale, RGB, K, CMY, CMYK, and CMYKcm colorspaces.
+
+<H3>Color Management Functions</H3>
+
+<P>The color management functions handle gamut mapping and density
+correction. These are integrated with the colorspace conversion
+functions so that colorspace conversion and color management are
+processed in a single step.
+
+<H3>Image Management Functions</H3>
+
+<P>The image management functions manage a tiled image database that is
+swapped to/from disk as needed.
+
+<H3>Scaling Functions</H3>
+
+<P>The scaling functions provide image scaling services using
+nearest-neighbor sampling and bilinear interpolation as appropriate.
+
+<H3>Image File Functions</H3>
+
+<P>The image file functions handle loading of all image file formats.
+
+<H3>Raster Functions</H3>
+
+<P>The raster functions manage streams of CUPS raster data (described
+in the Interface Design Document) used by non-PostScript printer
+drivers and raster filters.
+
+<H2>Daemons</H2>
+
+<P>The daemons provide additional network functions for the scheduler.
+Currently only two daemons are provided with CUPS.
+
+<H3>Line Printer Daemon</H3>
+
+<P>The line printer daemon provides remote LPD client support and is
+run by the <CODE>inetd(8)</CODE> daemon as needed.
+
+<H3>Polling Daemon</H3>
+
+<P>The polling daemon is used to poll a remote server for a list of
+available printers and provide it to the scheduler for addition. A
+separate polling daemon is run by the scheduler for every remote
+system listed for polling in the scheduler configuration file.
+
+<H2>Filters</H2>
+
+<P>The filters implement file conversion services for CUPS. All filters
+are called with a common set of arguments:
+
+<UL>
+
+ <LI>Printer name - the name of the destination printer (name string).
+
+ <LI>Job Identifier - the job identifier for this job (integer).
+
+ <LI>User Name - the user associated with this job (name string).
+
+ <LI>Title - the title/job-name associated with this job (name string).
+
+ <LI>Copies - the number of copies required (integer).
+
+ <LI>Options - the options associated with this job (space separated
+ option strings).
+
+ <LI>Filename (optional) - the file to print; if this option is not
+ specified, the filter must read the input file from the standard
+ input.
+
+</UL>
+
+<P>Filters are added to the MIME conversion data file and implement all
+necessary conversions from one file type to another.
+
+<H3>hpgltops</H3>
+
+<P>The hpgltops filter converts HP-GL/2 files into PostScript.
+
+<H3>imagetops</H3>
+
+<P>The imagetops filter converts image files into PostScript.
+
+<H3>imagetoraster</H3>
+
+<P>The imagetoraster filter converts image files into CUPS raster data.
+
+<H3>pdftops</H3>
+
+<P>The pdftops filter converts PDF files into PostScript.
+
+<H3>pstops</H3>
+
+<P>The pstops filter inserts printer-specific commands from PPD files and
+performs page filtering as requested by the user.
+
+<H3>pstoraster</H3>
+
+<P>The pstoraster filter converts PostScript program data into CUPS
+raster data.
+
+<H3>rastertoepson</H3>
+
+<P>The rastertoepson filter handles converting CUPS raster data to
+ESC/P and supports both color and black-and-white printers.
+
+<H3>rastertohp</H3>
+
+<P>The rastertohp filter handles converting CUPS raster data to HP-PCL
+and supports both color and black-and-white printers.
+
+<H3>texttops</H3>
+
+<P>The texttops filter converts text files into PostScript.
+
+<H2>Scheduler</H2>
+
+<P>The scheduler is a fully-functional HTTP/1.1 and IPP/1.1 server that
+manages the printers, classes, and jobs in the system. It also handles
+a simple broadcast-based directory service so that remote print queues
+and classes can be accessed transparently from the local system.
+
+<H3>Authorization</H3>
+
+<P>The authorization module is responsible for performing access
+control and authentication for all HTTP and IPP requests entering the
+system.
+
+<H3>Classes</H3>
+
+<P>The classes module is responsible for managing printer classes in
+the system. Each class is a collection of local and/or remote
+printers. The classes module also reads and writes the classes
+configuration file.
+
+<H3>Client</H3>
+
+<P>The client module is responsible for all HTTP client
+communications. It handles listening on selected interfaces, accepting
+connections from prospective clients, processing incoming HTTP
+requests, and sending HTTP responses to those requests. The client
+module also is responsible for executing the external CGI programs as
+needed to support web-based printer, class, and job status monitoring
+and administration.
+
+<P>Once authorized, all IPP requests are sent to the IPP module.
+
+<H3>Configuration</H3>
+
+<P>The configuration module is responsible for reading the CUPS
+configuration file and initializing the appropriate data structures and
+values. The configuration module also stops CUPS services before
+reading the configuration file and restarts them after the
+configuration file has been read.
+
+<H3>Devices</H3>
+
+<P>The devices module is responsible for managing the list of available
+devices for the CUPS-Get-Devices operation.
+
+<H3>Directory Services</H3>
+
+<P>The directory services module sends and recieves printer state
+information over a broadcast socket. Remote printers and classes are
+automatically added to or removed from the local printer and class
+lists as needed.
+
+<P>The directory services module can only recieve printer state information
+over a single UDP port, however it can broadcast to multiple addresses and
+ports as needed.
+
+<H3>IPP</H3>
+
+<P>The IPP module handles IPP requests and acts accordingly. URI
+validation is also performed here, as a client can post IPP data to any
+URI on the server which might sidestep the access control or
+authentication of the HTTP server.
+
+<H3>Jobs</H3>
+
+<P>The jobs module manages print jobs, starts filter and backend
+processes for jobs to be printed, and monitors status messages from
+those filters and backends.
+
+<H3>Logging</H3>
+
+<P>The logging module manages the access, error, and page log files
+that are generated by the scheduler.
+
+<H3>Main</H3>
+
+<P>The main module is responsible for timing out and dispatching input
+and output for client connections. It also watches for incoming
+<CODE>SIGHUP</CODE> and <CODE>SIGCHLD</CODE> signals, reloads the
+server configuration files as needed, and handles child process errors
+and exits.
+
+<H3>MIME</H3>
+
+<P>The Multimedia Internet Mail Exchange module manages a MIME type and
+conversion database that supports file typing by extension and content
+and least-cost file filtering from a source to a destination file type.
+
+<H3>PPDs</H3>
+
+<P>The PPDs module is responsible for managing the list of available
+PPD files for the CUPS-Get-PPDs operation.
+
+<H3>Printers</H3>
+
+<P>The printers module is responsible for managing printers and PPD
+files in the system. The printers module also reads and writes the
+printers configuration file.
+
+<H2>System V Commands</H2>
+
+<P>The System V commands provide a robust command-line interface to
+CUPS to submit and control printers and jobs.
+
+<H3>accept</H3>
+
+<P>The accept command tells the scheduler to accept new jobs for specific
+printers.
+
+<H3>cancel</H3>
+
+<P>The cancel command tells the scheduler to cancel one or more jobs that are
+queued for printing.
+
+<H3>disable</H3>
+
+<P>The disable command tells the scheduler to stop printing jobs on the
+specified printers.
+
+<H3>enable</H3>
+
+<P>The enable command tells the scheduler to start printing jobs on the
+specified printers.
+
+<H3>lp</H3>
+
+<P>The lp command submits submits files for printing. Unlike the standard
+System V lp command, a single CUPS lp command will generate a separate
+job ID for each file that is printed. Also, the Solaris "f", "H", "P", "S",
+and "y" options are silently ignored.
+
+<H3>lpadmin</H3>
+
+<P>The lpadmin command manages printer queues and classes. The Solaris
+"A", "F", "I", "M", "P", "Q", "S", "T", "U", "W", "f", "l", "m", "o",
+"s", "t", and "u" options are not supported, and new options "P" (PPD
+file) and "E" (enable and accept) are provided to configure
+CUPS-specific features.
+
+<H3>lpinfo</H3>
+
+<P>The lpinfo command lists the available PPD files or devices as selected
+by the user.
+
+<H3>lpmove</H3>
+
+<P>The lpmove command moves a print job to a new destination.
+
+<H3>lpoptions</H3>
+
+<P>The lpoptions command manages user-defined printers and options.
+
+<H3>lpstat</H3>
+
+<P>The lpstat command lists printers, classes, and jobs as requested by the
+user.
+
+<H3>reject</H3>
+
+<P>The reject command tells the scheduler not to accept new jobs for specific
+printers.
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/spm.html b/doc/spm.html
new file mode 100644
index 000000000..e496f99d9
--- /dev/null
+++ b/doc/spm.html
@@ -0,0 +1,9491 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Programmers Manual</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SPM-1.1.22">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511" ALT="CUPS Software Programmers Manual"><BR>
+<H1>CUPS Software Programmers Manual</H1></A><BR>
+CUPS-SPM-1.1.22<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">Preface</A>
+<UL>
+<LI><A HREF="#1_1">System Overview</A></LI>
+<LI><A HREF="#1_2">Document Overview</A></LI>
+<LI><A HREF="#1_3">Notation Conventions</A></LI>
+<LI><A HREF="#1_4">Abbreviations</A></LI>
+<LI><A HREF="#1_5">Other References</A></LI>
+</UL>
+</B><B><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+<UL>
+<LI><A HREF="#2_1">The Printing Problem</A></LI>
+<LI><A HREF="#2_2">The Technology</A></LI>
+<LI><A HREF="#2_3">Jobs</A></LI>
+<LI><A HREF="#2_4">Classes</A></LI>
+<LI><A HREF="#2_5">Filters</A></LI>
+<LI><A HREF="#2_6">Backends</A></LI>
+<LI><A HREF="#2_7">Printer Drivers</A></LI>
+<LI><A HREF="#2_8">Networking</A></LI>
+</UL>
+</B><B><A HREF="#CUPS_API">2 - The CUPS API</A>
+<UL>
+<LI><A HREF="#3_1">The CUPS API Library</A>
+<UL>
+<LI><A HREF="#3_1_1">Detecting the CUPS API Library in GNU Autoconf</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#3_2">Printing Services</A>
+<UL>
+<LI><A HREF="#3_2_1">Include Files</A></LI>
+<LI><A HREF="#3_2_2">Printing a File</A></LI>
+<LI><A HREF="#3_2_3">Printing Multiple Files</A></LI>
+<LI><A HREF="#3_2_4">Cancelling Jobs</A></LI>
+<LI><A HREF="#3_2_5">Getting the Available Printers and Classes</A></LI>
+<LI><A HREF="#3_2_6">Printing with Options</A></LI>
+<LI><A HREF="#3_2_7">Setting Printer Options</A></LI>
+<LI><A HREF="#3_2_8">Getting Errors</A></LI>
+<LI><A HREF="#3_2_9">Passwords and Authentication</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#3_3">PPD Services</A>
+<UL>
+<LI><A HREF="#3_3_1">Include Files</A></LI>
+<LI><A HREF="#3_3_2">Getting a PPD File for a Printer</A></LI>
+<LI><A HREF="#3_3_3">Loading a PPD File</A></LI>
+<LI><A HREF="#3_3_4">Freeing PPD File Information</A></LI>
+<LI><A HREF="#3_3_5">The PPD File Structure</A></LI>
+<LI><A HREF="#3_3_6">Marking Options</A></LI>
+<LI><A HREF="#3_3_7">Checking for Conflicts</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#WRITING_FILTERS">3 - Writing Filters</A>
+<UL>
+<LI><A HREF="#4_1">Overview</A>
+<UL>
+<LI><A HREF="#4_1_1">Security Considerations</A></LI>
+<LI><A HREF="#4_1_2">Users and Groups</A></LI>
+<LI><A HREF="#4_1_3">Temporary Files</A></LI>
+<LI><A HREF="#4_1_4">Sending Messages to the User</A></LI>
+<LI><A HREF="#4_1_5">Page Accounting</A></LI>
+<LI><A HREF="#4_1_6">Command-Line Arguments</A></LI>
+<LI><A HREF="#4_1_7">Copy Generation</A></LI>
+<LI><A HREF="#4_1_8">Environment Variables</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_2">Dissecting the HP-GL/2 Filter</A>
+<UL>
+<LI><A HREF="#4_2_1">Initializing the Filter</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_3">PostScript Output</A></LI>
+</UL>
+</B><B><A HREF="#WRITING_DRIVERS">4 - Writing Printer Drivers</A>
+<UL>
+<LI><A HREF="#5_1">Overview</A>
+<UL>
+<LI><A HREF="#5_1_1">CUPS Raster Data</A></LI>
+<LI><A HREF="#5_1_2">Page Accounting</A></LI>
+<LI><A HREF="#5_1_3">Color Management</A></LI>
+<LI><A HREF="#5_1_4">Device and Bitmap Variables</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#5_2">Dissecting the HP-PCL Driver</A>
+<UL>
+<LI><A HREF="#5_2_1">PPD Files</A></LI>
+<LI><A HREF="#5_2_2">Reading Raster Data</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#WRITING_BACKENDS">5 - Writing Backends</A>
+<UL>
+<LI><A HREF="#6_1">Overview</A>
+<UL>
+<LI><A HREF="#6_1_1">Security Considerations</A></LI>
+<LI><A HREF="#6_1_2">Command-Line Arguments</A></LI>
+<LI><A HREF="#6_1_3">Copy Generation</A></LI>
+<LI><A HREF="#6_1_4">Page Accounting</A></LI>
+<LI><A HREF="#6_1_5">Exclusive Access</A></LI>
+<LI><A HREF="#6_1_6">Retries</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#6_2">Dissecting the Serial Port Backend</A>
+<UL>
+<LI><A HREF="#6_2_1">Supporting Device Discovery</A></LI>
+<LI><A HREF="#6_2_2">Opening the Serial Port</A></LI>
+<LI><A HREF="#6_2_3">Writing Data to the Port</A></LI>
+<LI><A HREF="#6_2_4">Finishing Up</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#LICENSE">A - Software License Agreement</A>
+<UL>
+<LI><A HREF="#7_1">Common UNIX Printing System License Agreement</A>
+<UL>
+<LI><A HREF="#7_1_1">Introduction</A></LI>
+<LI><A HREF="#7_1_2">License Exceptions</A></LI>
+<LI><A HREF="#7_1_3">Trademarks</A></LI>
+<LI><A HREF="#7_1_4">Binary Distribution Rights</A></LI>
+<LI><A HREF="#7_1_5">Support</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#7_2">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#7_2_1">Preamble</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#7_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#7_3_1">Preamble</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#CONSTANTS">B - Constants</A>
+<UL>
+<LI><A HREF="#8_1">CUPS Constants</A>
+<UL>
+<LI><A HREF="#8_1_1">Version Number</A></LI>
+<LI><A HREF="#8_1_2">Printer Capabilities</A></LI>
+<LI><A HREF="#8_1_3">Encodings</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_2">HTTP Constants</A>
+<UL>
+<LI><A HREF="#8_2_1">Limits</A></LI>
+<LI><A HREF="#8_2_2">Status Codes</A></LI>
+<LI><A HREF="#8_2_3">Fields</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_3">IPP Constants</A>
+<UL>
+<LI><A HREF="#8_3_1">Limits</A></LI>
+<LI><A HREF="#8_3_2">Tags</A></LI>
+<LI><A HREF="#8_3_3">Resolution Units</A></LI>
+<LI><A HREF="#8_3_4">Finishings</A></LI>
+<LI><A HREF="#8_3_5">Orientations</A></LI>
+<LI><A HREF="#8_3_6">Qualities</A></LI>
+<LI><A HREF="#8_3_7">Job States</A></LI>
+<LI><A HREF="#8_3_8">Printer States</A></LI>
+<LI><A HREF="#8_3_9">Operations</A></LI>
+<LI><A HREF="#8_3_10">Status Codes</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_4">PPD Constants</A>
+<UL>
+<LI><A HREF="#8_4_1">PPD Format Version</A></LI>
+<LI><A HREF="#8_4_2">PPD User-Interface Types</A></LI>
+<LI><A HREF="#8_4_3">PPD Sections</A></LI>
+<LI><A HREF="#8_4_4">PPD Colorspaces</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#8_5">Raster Constants</A>
+<UL>
+<LI><A HREF="#8_5_1">Raster Sync Words</A></LI>
+<LI><A HREF="#8_5_2">Raster Stream Modes</A></LI>
+<LI><A HREF="#8_5_3">Raster Boolean Constants</A></LI>
+<LI><A HREF="#8_5_4">Raster Jog Values</A></LI>
+<LI><A HREF="#8_5_5">Raster Orientation Values</A></LI>
+<LI><A HREF="#8_5_6">Raster CutMedia Values</A></LI>
+<LI><A HREF="#8_5_7">Raster AdvanceMedia Values</A></LI>
+<LI><A HREF="#8_5_8">Raster LeadingEdge Values</A></LI>
+<LI><A HREF="#8_5_9">Raster Color Order Values</A></LI>
+<LI><A HREF="#8_5_10">Raster Colorspace Values</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#STRUCTURES">C - Structures</A>
+<UL>
+<LI><A HREF="#9_1">CUPS Structures</A>
+<UL>
+<LI><A HREF="#cups_dest_t">CUPS Destinations</A></LI>
+<LI><A HREF="#cups_job_t">CUPS Jobs</A></LI>
+<LI><A HREF="#cups_lang_t">CUPS Messages</A></LI>
+<LI><A HREF="#cups_option_t">CUPS Options</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#9_2">Networking Structures</A>
+<UL>
+<LI><A HREF="#http_t">HTTP State</A></LI>
+<LI><A HREF="#ipp_t">IPP State</A></LI>
+<LI><A HREF="#ipp_attribute_t">IPP Attribute</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#9_3">PPD Structures</A>
+<UL>
+<LI><A HREF="#ppd_file_t">PPD File</A></LI>
+<LI><A HREF="#ppd_choice_t">PPD Choice</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#9_4">Raster Structures</A>
+<UL>
+<LI><A HREF="#cups_raster_t">Raster Stream</A></LI>
+<LI><A HREF="#cups_raster_header_t">Raster Page Header</A></LI>
+</UL>
+</LI>
+</UL>
+</B><B><A HREF="#FUNCTIONS">D - Functions</A>
+<UL>
+<LI><A HREF="#cupsAddDest">cupsAddDest()</A>
+<UL>
+<LI><A HREF="#10_1_1">Usage</A></LI>
+<LI><A HREF="#10_1_2">Arguments</A></LI>
+<LI><A HREF="#10_1_3">Returns</A></LI>
+<LI><A HREF="#10_1_4">Description</A></LI>
+<LI><A HREF="#10_1_5">Example</A></LI>
+<LI><A HREF="#10_1_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsAddOption">cupsAddOption()</A>
+<UL>
+<LI><A HREF="#10_2_1">Usage</A></LI>
+<LI><A HREF="#10_2_2">Arguments</A></LI>
+<LI><A HREF="#10_2_3">Returns</A></LI>
+<LI><A HREF="#10_2_4">Description</A></LI>
+<LI><A HREF="#10_2_5">Example</A></LI>
+<LI><A HREF="#10_2_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsCancelJob">cupsCancelJob()</A>
+<UL>
+<LI><A HREF="#10_3_1">Usage</A></LI>
+<LI><A HREF="#10_3_2">Arguments</A></LI>
+<LI><A HREF="#10_3_3">Returns</A></LI>
+<LI><A HREF="#10_3_4">Description</A></LI>
+<LI><A HREF="#10_3_5">Example</A></LI>
+<LI><A HREF="#10_3_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsDoAuthentication">cupsDoAuthentication()</A>
+<UL>
+<LI><A HREF="#10_4_1">Usage</A></LI>
+<LI><A HREF="#10_4_2">Arguments</A></LI>
+<LI><A HREF="#10_4_3">Returns</A></LI>
+<LI><A HREF="#10_4_4">Description</A></LI>
+<LI><A HREF="#10_4_5">Example</A></LI>
+<LI><A HREF="#10_4_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsDoFileRequest">cupsDoFileRequest()</A>
+<UL>
+<LI><A HREF="#10_5_1">Usage</A></LI>
+<LI><A HREF="#10_5_2">Arguments</A></LI>
+<LI><A HREF="#10_5_3">Returns</A></LI>
+<LI><A HREF="#10_5_4">Description</A></LI>
+<LI><A HREF="#10_5_5">Example</A></LI>
+<LI><A HREF="#10_5_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsDoRequest">cupsDoRequest()</A>
+<UL>
+<LI><A HREF="#10_6_1">Usage</A></LI>
+<LI><A HREF="#10_6_2">Arguments</A></LI>
+<LI><A HREF="#10_6_3">Returns</A></LI>
+<LI><A HREF="#10_6_4">Description</A></LI>
+<LI><A HREF="#10_6_5">Example</A></LI>
+<LI><A HREF="#10_6_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsEncodeOptions">cupsEncodeOptions()</A>
+<UL>
+<LI><A HREF="#10_7_1">Usage</A></LI>
+<LI><A HREF="#10_7_2">Arguments</A></LI>
+<LI><A HREF="#10_7_3">Description</A></LI>
+<LI><A HREF="#10_7_4">Example</A></LI>
+<LI><A HREF="#10_7_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsEncryption">cupsEncryption()</A>
+<UL>
+<LI><A HREF="#10_8_1">Usage</A></LI>
+<LI><A HREF="#10_8_2">Returns</A></LI>
+<LI><A HREF="#10_8_3">Description</A></LI>
+<LI><A HREF="#10_8_4">Example</A></LI>
+<LI><A HREF="#10_8_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsFreeDests">cupsFreeDests()</A>
+<UL>
+<LI><A HREF="#10_9_1">Usage</A></LI>
+<LI><A HREF="#10_9_2">Arguments</A></LI>
+<LI><A HREF="#10_9_3">Description</A></LI>
+<LI><A HREF="#10_9_4">Example</A></LI>
+<LI><A HREF="#10_9_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsFreeJobs">cupsFreeJobs()</A>
+<UL>
+<LI><A HREF="#10_10_1">Usage</A></LI>
+<LI><A HREF="#10_10_2">Arguments</A></LI>
+<LI><A HREF="#10_10_3">Description</A></LI>
+<LI><A HREF="#10_10_4">Example</A></LI>
+<LI><A HREF="#10_10_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsFreeOptions">cupsFreeOptions()</A>
+<UL>
+<LI><A HREF="#10_11_1">Usage</A></LI>
+<LI><A HREF="#10_11_2">Arguments</A></LI>
+<LI><A HREF="#10_11_3">Description</A></LI>
+<LI><A HREF="#10_11_4">Example</A></LI>
+<LI><A HREF="#10_11_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetClasses">cupsGetClasses()</A>
+<UL>
+<LI><A HREF="#10_12_1">Usage</A></LI>
+<LI><A HREF="#10_12_2">Arguments</A></LI>
+<LI><A HREF="#10_12_3">Returns</A></LI>
+<LI><A HREF="#10_12_4">Description</A></LI>
+<LI><A HREF="#10_12_5">Example</A></LI>
+<LI><A HREF="#10_12_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetDefault">cupsGetDefault()</A>
+<UL>
+<LI><A HREF="#10_13_1">Usage</A></LI>
+<LI><A HREF="#10_13_2">Returns</A></LI>
+<LI><A HREF="#10_13_3">Description</A></LI>
+<LI><A HREF="#10_13_4">Example</A></LI>
+<LI><A HREF="#10_13_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetDest">cupsGetDest()</A>
+<UL>
+<LI><A HREF="#10_14_1">Usage</A></LI>
+<LI><A HREF="#10_14_2">Arguments</A></LI>
+<LI><A HREF="#10_14_3">Returns</A></LI>
+<LI><A HREF="#10_14_4">Description</A></LI>
+<LI><A HREF="#10_14_5">Example</A></LI>
+<LI><A HREF="#10_14_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetDests">cupsGetDests()</A>
+<UL>
+<LI><A HREF="#10_15_1">Usage</A></LI>
+<LI><A HREF="#10_15_2">Arguments</A></LI>
+<LI><A HREF="#10_15_3">Returns</A></LI>
+<LI><A HREF="#10_15_4">Description</A></LI>
+<LI><A HREF="#10_15_5">Example</A></LI>
+<LI><A HREF="#10_15_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetFd">cupsGetFd()</A>
+<UL>
+<LI><A HREF="#10_16_1">Usage</A></LI>
+<LI><A HREF="#10_16_2">Arguments</A></LI>
+<LI><A HREF="#10_16_3">Returns</A></LI>
+<LI><A HREF="#10_16_4">Description</A></LI>
+<LI><A HREF="#10_16_5">Example</A></LI>
+<LI><A HREF="#10_16_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetFile">cupsGetFile()</A>
+<UL>
+<LI><A HREF="#10_17_1">Usage</A></LI>
+<LI><A HREF="#10_17_2">Arguments</A></LI>
+<LI><A HREF="#10_17_3">Returns</A></LI>
+<LI><A HREF="#10_17_4">Description</A></LI>
+<LI><A HREF="#10_17_5">Example</A></LI>
+<LI><A HREF="#10_17_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetJobs">cupsGetJobs()</A>
+<UL>
+<LI><A HREF="#10_18_1">Usage</A></LI>
+<LI><A HREF="#10_18_2">Arguments</A></LI>
+<LI><A HREF="#10_18_3">Returns</A></LI>
+<LI><A HREF="#10_18_4">Description</A></LI>
+<LI><A HREF="#10_18_5">Example</A></LI>
+<LI><A HREF="#10_18_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetOption">cupsGetOption()</A>
+<UL>
+<LI><A HREF="#10_19_1">Usage</A></LI>
+<LI><A HREF="#10_19_2">Arguments</A></LI>
+<LI><A HREF="#10_19_3">Returns</A></LI>
+<LI><A HREF="#10_19_4">Description</A></LI>
+<LI><A HREF="#10_19_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetPassword">cupsGetPassword()</A>
+<UL>
+<LI><A HREF="#10_20_1">Usage</A></LI>
+<LI><A HREF="#10_20_2">Arguments</A></LI>
+<LI><A HREF="#10_20_3">Returns</A></LI>
+<LI><A HREF="#10_20_4">Description</A></LI>
+<LI><A HREF="#10_20_5">Example</A></LI>
+<LI><A HREF="#10_20_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetPPD">cupsGetPPD()</A>
+<UL>
+<LI><A HREF="#10_21_1">Usage</A></LI>
+<LI><A HREF="#10_21_2">Arguments</A></LI>
+<LI><A HREF="#10_21_3">Returns</A></LI>
+<LI><A HREF="#10_21_4">Description</A></LI>
+<LI><A HREF="#10_21_5">Example</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsGetPrinters">cupsGetPrinters()</A>
+<UL>
+<LI><A HREF="#10_22_1">Usage</A></LI>
+<LI><A HREF="#10_22_2">Arguments</A></LI>
+<LI><A HREF="#10_22_3">Returns</A></LI>
+<LI><A HREF="#10_22_4">Description</A></LI>
+<LI><A HREF="#10_22_5">Example</A></LI>
+<LI><A HREF="#10_22_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangDefault">cupsLangDefault()</A>
+<UL>
+<LI><A HREF="#10_23_1">Usage</A></LI>
+<LI><A HREF="#10_23_2">Returns</A></LI>
+<LI><A HREF="#10_23_3">Description</A></LI>
+<LI><A HREF="#10_23_4">Example</A></LI>
+<LI><A HREF="#10_23_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangEncoding">cupsLangEncoding()</A>
+<UL>
+<LI><A HREF="#10_24_1">Usage</A></LI>
+<LI><A HREF="#10_24_2">Arguments</A></LI>
+<LI><A HREF="#10_24_3">Returns</A></LI>
+<LI><A HREF="#10_24_4">Description</A></LI>
+<LI><A HREF="#10_24_5">Example</A></LI>
+<LI><A HREF="#10_24_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangFlush">cupsLangFlush()</A>
+<UL>
+<LI><A HREF="#10_25_1">Usage</A></LI>
+<LI><A HREF="#10_25_2">Description</A></LI>
+<LI><A HREF="#10_25_3">Example</A></LI>
+<LI><A HREF="#10_25_4">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangFree">cupsLangFree()</A>
+<UL>
+<LI><A HREF="#10_26_1">Usage</A></LI>
+<LI><A HREF="#10_26_2">Arguments</A></LI>
+<LI><A HREF="#10_26_3">Description</A></LI>
+<LI><A HREF="#10_26_4">Example</A></LI>
+<LI><A HREF="#10_26_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangGet">cupsLangGet()</A>
+<UL>
+<LI><A HREF="#10_27_1">Usage</A></LI>
+<LI><A HREF="#10_27_2">Arguments</A></LI>
+<LI><A HREF="#10_27_3">Returns</A></LI>
+<LI><A HREF="#10_27_4">Description</A></LI>
+<LI><A HREF="#10_27_5">Example</A></LI>
+<LI><A HREF="#10_27_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLangString">cupsLangString()</A>
+<UL>
+<LI><A HREF="#10_28_1">Usage</A></LI>
+<LI><A HREF="#10_28_2">Arguments</A></LI>
+<LI><A HREF="#10_28_3">Returns</A></LI>
+<LI><A HREF="#10_28_4">Description</A></LI>
+<LI><A HREF="#10_28_5">Example</A></LI>
+<LI><A HREF="#10_28_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsLastError">cupsLastError()</A>
+<UL>
+<LI><A HREF="#10_29_1">Usage</A></LI>
+<LI><A HREF="#10_29_2">Returns</A></LI>
+<LI><A HREF="#10_29_3">Description</A></LI>
+<LI><A HREF="#10_29_4">Example</A></LI>
+<LI><A HREF="#10_29_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsMarkOptions">cupsMarkOptions()</A>
+<UL>
+<LI><A HREF="#10_30_1">Usage</A></LI>
+<LI><A HREF="#10_30_2">Arguments</A></LI>
+<LI><A HREF="#10_30_3">Returns</A></LI>
+<LI><A HREF="#10_30_4">Description</A></LI>
+<LI><A HREF="#10_30_5">Example</A></LI>
+<LI><A HREF="#10_30_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsParseOptions">cupsParseOptions()</A>
+<UL>
+<LI><A HREF="#10_31_1">Usage</A></LI>
+<LI><A HREF="#10_31_2">Arguments</A></LI>
+<LI><A HREF="#10_31_3">Returns</A></LI>
+<LI><A HREF="#10_31_4">Description</A></LI>
+<LI><A HREF="#10_31_5">Example</A></LI>
+<LI><A HREF="#10_31_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsPrintFile">cupsPrintFile()</A>
+<UL>
+<LI><A HREF="#10_32_1">Usage</A></LI>
+<LI><A HREF="#10_32_2">Arguments</A></LI>
+<LI><A HREF="#10_32_3">Returns</A></LI>
+<LI><A HREF="#10_32_4">Description</A></LI>
+<LI><A HREF="#10_32_5">Example</A></LI>
+<LI><A HREF="#10_32_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsPrintFiles">cupsPrintFiles()</A>
+<UL>
+<LI><A HREF="#10_33_1">Usage</A></LI>
+<LI><A HREF="#10_33_2">Arguments</A></LI>
+<LI><A HREF="#10_33_3">Returns</A></LI>
+<LI><A HREF="#10_33_4">Description</A></LI>
+<LI><A HREF="#10_33_5">Example</A></LI>
+<LI><A HREF="#10_33_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsPutFd">cupsPutFd()</A>
+<UL>
+<LI><A HREF="#10_34_1">Usage</A></LI>
+<LI><A HREF="#10_34_2">Arguments</A></LI>
+<LI><A HREF="#10_34_3">Returns</A></LI>
+<LI><A HREF="#10_34_4">Description</A></LI>
+<LI><A HREF="#10_34_5">Example</A></LI>
+<LI><A HREF="#10_34_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsPutFile">cupsPutFile()</A>
+<UL>
+<LI><A HREF="#10_35_1">Usage</A></LI>
+<LI><A HREF="#10_35_2">Arguments</A></LI>
+<LI><A HREF="#10_35_3">Returns</A></LI>
+<LI><A HREF="#10_35_4">Description</A></LI>
+<LI><A HREF="#10_35_5">Example</A></LI>
+<LI><A HREF="#10_35_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterClose">cupsRasterClose()</A>
+<UL>
+<LI><A HREF="#10_36_1">Usage</A></LI>
+<LI><A HREF="#10_36_2">Arguments</A></LI>
+<LI><A HREF="#10_36_3">Description</A></LI>
+<LI><A HREF="#10_36_4">Example</A></LI>
+<LI><A HREF="#10_36_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterOpen">cupsRasterOpen()</A>
+<UL>
+<LI><A HREF="#10_37_1">Usage</A></LI>
+<LI><A HREF="#10_37_2">Arguments</A></LI>
+<LI><A HREF="#10_37_3">Returns</A></LI>
+<LI><A HREF="#10_37_4">Description</A></LI>
+<LI><A HREF="#10_37_5">Example</A></LI>
+<LI><A HREF="#10_37_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterReadHeader">cupsRasterReadHeader()</A>
+<UL>
+<LI><A HREF="#10_38_1">Usage</A></LI>
+<LI><A HREF="#10_38_2">Arguments</A></LI>
+<LI><A HREF="#10_38_3">Returns</A></LI>
+<LI><A HREF="#10_38_4">Description</A></LI>
+<LI><A HREF="#10_38_5">Example</A></LI>
+<LI><A HREF="#10_38_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterReadPixels">cupsRasterReadPixels()</A>
+<UL>
+<LI><A HREF="#10_39_1">Usage</A></LI>
+<LI><A HREF="#10_39_2">Arguments</A></LI>
+<LI><A HREF="#10_39_3">Returns</A></LI>
+<LI><A HREF="#10_39_4">Description</A></LI>
+<LI><A HREF="#10_39_5">Example</A></LI>
+<LI><A HREF="#10_39_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterWriteHeader">cupsRasterWriteHeader()</A>
+<UL>
+<LI><A HREF="#10_40_1">Usage</A></LI>
+<LI><A HREF="#10_40_2">Arguments</A></LI>
+<LI><A HREF="#10_40_3">Returns</A></LI>
+<LI><A HREF="#10_40_4">Description</A></LI>
+<LI><A HREF="#10_40_5">Example</A></LI>
+<LI><A HREF="#10_40_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsRasterWritePixels">cupsRasterWritePixels()</A>
+<UL>
+<LI><A HREF="#10_41_1">Usage</A></LI>
+<LI><A HREF="#10_41_2">Arguments</A></LI>
+<LI><A HREF="#10_41_3">Returns</A></LI>
+<LI><A HREF="#10_41_4">Description</A></LI>
+<LI><A HREF="#10_41_5">Example</A></LI>
+<LI><A HREF="#10_41_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsServer">cupsServer()</A>
+<UL>
+<LI><A HREF="#10_42_1">Usage</A></LI>
+<LI><A HREF="#10_42_2">Returns</A></LI>
+<LI><A HREF="#10_42_3">Description</A></LI>
+<LI><A HREF="#10_42_4">Example</A></LI>
+<LI><A HREF="#10_42_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsSetDests">cupsSetDests()</A>
+<UL>
+<LI><A HREF="#10_43_1">Usage</A></LI>
+<LI><A HREF="#10_43_2">Arguments</A></LI>
+<LI><A HREF="#10_43_3">Description</A></LI>
+<LI><A HREF="#10_43_4">Example</A></LI>
+<LI><A HREF="#10_43_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsSetEncryption">cupsSetEncryption()</A>
+<UL>
+<LI><A HREF="#10_44_1">Usage</A></LI>
+<LI><A HREF="#10_44_2">Arguments</A></LI>
+<LI><A HREF="#10_44_3">Description</A></LI>
+<LI><A HREF="#10_44_4">Example</A></LI>
+<LI><A HREF="#10_44_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsSetPasswordCB">cupsSetPasswordCB()</A>
+<UL>
+<LI><A HREF="#10_45_1">Usage</A></LI>
+<LI><A HREF="#10_45_2">Arguments</A></LI>
+<LI><A HREF="#10_45_3">Description</A></LI>
+<LI><A HREF="#10_45_4">Example</A></LI>
+<LI><A HREF="#10_45_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsSetServer">cupsSetServer()</A>
+<UL>
+<LI><A HREF="#10_46_1">Usage</A></LI>
+<LI><A HREF="#10_46_2">Arguments</A></LI>
+<LI><A HREF="#10_46_3">Description</A></LI>
+<LI><A HREF="#10_46_4">Example</A></LI>
+<LI><A HREF="#10_46_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsSetUser">cupsSetUser()</A>
+<UL>
+<LI><A HREF="#10_47_1">Usage</A></LI>
+<LI><A HREF="#10_47_2">Arguments</A></LI>
+<LI><A HREF="#10_47_3">Description</A></LI>
+<LI><A HREF="#10_47_4">Example</A></LI>
+<LI><A HREF="#10_47_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsTempFd">cupsTempFd()</A>
+<UL>
+<LI><A HREF="#10_48_1">Usage</A></LI>
+<LI><A HREF="#10_48_2">Arguments</A></LI>
+<LI><A HREF="#10_48_3">Returns</A></LI>
+<LI><A HREF="#10_48_4">Description</A></LI>
+<LI><A HREF="#10_48_5">Example</A></LI>
+<LI><A HREF="#10_48_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsTempFile">cupsTempFile()</A>
+<UL>
+<LI><A HREF="#10_49_1">Usage</A></LI>
+<LI><A HREF="#10_49_2">Arguments</A></LI>
+<LI><A HREF="#10_49_3">Returns</A></LI>
+<LI><A HREF="#10_49_4">Description</A></LI>
+<LI><A HREF="#10_49_5">Example</A></LI>
+<LI><A HREF="#10_49_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#cupsUser">cupsUser()</A>
+<UL>
+<LI><A HREF="#10_50_1">Usage</A></LI>
+<LI><A HREF="#10_50_2">Returns</A></LI>
+<LI><A HREF="#10_50_3">Description</A></LI>
+<LI><A HREF="#10_50_4">Example</A></LI>
+<LI><A HREF="#10_50_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpBlocking">httpBlocking()</A>
+<UL>
+<LI><A HREF="#10_51_1">Usage</A></LI>
+<LI><A HREF="#10_51_2">Arguments</A></LI>
+<LI><A HREF="#10_51_3">Description</A></LI>
+<LI><A HREF="#10_51_4">Example</A></LI>
+<LI><A HREF="#10_51_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpCheck">httpCheck()</A>
+<UL>
+<LI><A HREF="#10_52_1">Usage</A></LI>
+<LI><A HREF="#10_52_2">Arguments</A></LI>
+<LI><A HREF="#10_52_3">Returns</A></LI>
+<LI><A HREF="#10_52_4">Description</A></LI>
+<LI><A HREF="#10_52_5">Example</A></LI>
+<LI><A HREF="#10_52_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpClearFields">httpClearFields()</A>
+<UL>
+<LI><A HREF="#10_53_1">Usage</A></LI>
+<LI><A HREF="#10_53_2">Arguments</A></LI>
+<LI><A HREF="#10_53_3">Description</A></LI>
+<LI><A HREF="#10_53_4">Example</A></LI>
+<LI><A HREF="#10_53_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpClose">httpClose()</A>
+<UL>
+<LI><A HREF="#10_54_1">Usage</A></LI>
+<LI><A HREF="#10_54_2">Arguments</A></LI>
+<LI><A HREF="#10_54_3">Description</A></LI>
+<LI><A HREF="#10_54_4">Example</A></LI>
+<LI><A HREF="#10_54_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpConnect">httpConnect()</A>
+<UL>
+<LI><A HREF="#10_55_1">Usage</A></LI>
+<LI><A HREF="#10_55_2">Arguments</A></LI>
+<LI><A HREF="#10_55_3">Returns</A></LI>
+<LI><A HREF="#10_55_4">Description</A></LI>
+<LI><A HREF="#10_55_5">Example</A></LI>
+<LI><A HREF="#10_55_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpConnectEncrypt">httpConnectEncrypt()</A>
+<UL>
+<LI><A HREF="#10_56_1">Usage</A></LI>
+<LI><A HREF="#10_56_2">Arguments</A></LI>
+<LI><A HREF="#10_56_3">Returns</A></LI>
+<LI><A HREF="#10_56_4">Description</A></LI>
+<LI><A HREF="#10_56_5">Example</A></LI>
+<LI><A HREF="#10_56_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpDecode64">httpDecode64()</A>
+<UL>
+<LI><A HREF="#10_57_1">Usage</A></LI>
+<LI><A HREF="#10_57_2">Arguments</A></LI>
+<LI><A HREF="#10_57_3">Returns</A></LI>
+<LI><A HREF="#10_57_4">Description</A></LI>
+<LI><A HREF="#10_57_5">Example</A></LI>
+<LI><A HREF="#10_57_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpDelete">httpDelete()</A>
+<UL>
+<LI><A HREF="#10_58_1">Usage</A></LI>
+<LI><A HREF="#10_58_2">Arguments</A></LI>
+<LI><A HREF="#10_58_3">Returns</A></LI>
+<LI><A HREF="#10_58_4">Description</A></LI>
+<LI><A HREF="#10_58_5">Example</A></LI>
+<LI><A HREF="#10_58_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpEncode64">httpEncode64()</A>
+<UL>
+<LI><A HREF="#10_59_1">Usage</A></LI>
+<LI><A HREF="#10_59_2">Arguments</A></LI>
+<LI><A HREF="#10_59_3">Returns</A></LI>
+<LI><A HREF="#10_59_4">Description</A></LI>
+<LI><A HREF="#10_59_5">Example</A></LI>
+<LI><A HREF="#10_59_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpEncryption">httpEncryption()</A>
+<UL>
+<LI><A HREF="#10_60_1">Usage</A></LI>
+<LI><A HREF="#10_60_2">Arguments</A></LI>
+<LI><A HREF="#10_60_3">Returns</A></LI>
+<LI><A HREF="#10_60_4">Description</A></LI>
+<LI><A HREF="#10_60_5">Example</A></LI>
+<LI><A HREF="#10_60_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpError">httpError()</A>
+<UL>
+<LI><A HREF="#10_61_1">Usage</A></LI>
+<LI><A HREF="#10_61_2">Arguments</A></LI>
+<LI><A HREF="#10_61_3">Returns</A></LI>
+<LI><A HREF="#10_61_4">Description</A></LI>
+<LI><A HREF="#10_61_5">Example</A></LI>
+<LI><A HREF="#10_61_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpFlush">httpFlush()</A>
+<UL>
+<LI><A HREF="#10_62_1">Usage</A></LI>
+<LI><A HREF="#10_62_2">Arguments</A></LI>
+<LI><A HREF="#10_62_3">Description</A></LI>
+<LI><A HREF="#10_62_4">Example</A></LI>
+<LI><A HREF="#10_62_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGet">httpGet()</A>
+<UL>
+<LI><A HREF="#10_63_1">Usage</A></LI>
+<LI><A HREF="#10_63_2">Arguments</A></LI>
+<LI><A HREF="#10_63_3">Returns</A></LI>
+<LI><A HREF="#10_63_4">Description</A></LI>
+<LI><A HREF="#10_63_5">Example</A></LI>
+<LI><A HREF="#10_63_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGets">httpGets()</A>
+<UL>
+<LI><A HREF="#10_64_1">Usage</A></LI>
+<LI><A HREF="#10_64_2">Arguments</A></LI>
+<LI><A HREF="#10_64_3">Returns</A></LI>
+<LI><A HREF="#10_64_4">Description</A></LI>
+<LI><A HREF="#10_64_5">Example</A></LI>
+<LI><A HREF="#10_64_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetDateString">httpGetDateString()</A>
+<UL>
+<LI><A HREF="#10_65_1">Usage</A></LI>
+<LI><A HREF="#10_65_2">Arguments</A></LI>
+<LI><A HREF="#10_65_3">Returns</A></LI>
+<LI><A HREF="#10_65_4">Description</A></LI>
+<LI><A HREF="#10_65_5">Example</A></LI>
+<LI><A HREF="#10_65_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetDateTime">httpGetDateTime()</A>
+<UL>
+<LI><A HREF="#10_66_1">Usage</A></LI>
+<LI><A HREF="#10_66_2">Arguments</A></LI>
+<LI><A HREF="#10_66_3">Returns</A></LI>
+<LI><A HREF="#10_66_4">Description</A></LI>
+<LI><A HREF="#10_66_5">Example</A></LI>
+<LI><A HREF="#10_66_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetField">httpGetField()</A>
+<UL>
+<LI><A HREF="#10_67_1">Usage</A></LI>
+<LI><A HREF="#10_67_2">Arguments</A></LI>
+<LI><A HREF="#10_67_3">Returns</A></LI>
+<LI><A HREF="#10_67_4">Description</A></LI>
+<LI><A HREF="#10_67_5">Example</A></LI>
+<LI><A HREF="#10_67_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetHostByName">httpGetHostByName()</A>
+<UL>
+<LI><A HREF="#10_68_1">Usage</A></LI>
+<LI><A HREF="#10_68_2">Arguments</A></LI>
+<LI><A HREF="#10_68_3">Returns</A></LI>
+<LI><A HREF="#10_68_4">Description</A></LI>
+<LI><A HREF="#10_68_5">Example</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetLength">httpGetLength()</A>
+<UL>
+<LI><A HREF="#10_69_1">Usage</A></LI>
+<LI><A HREF="#10_69_2">Arguments</A></LI>
+<LI><A HREF="#10_69_3">Returns</A></LI>
+<LI><A HREF="#10_69_4">Description</A></LI>
+<LI><A HREF="#10_69_5">Example</A></LI>
+<LI><A HREF="#10_69_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpGetSubField">httpGetSubField()</A>
+<UL>
+<LI><A HREF="#10_70_1">Usage</A></LI>
+<LI><A HREF="#10_70_2">Arguments</A></LI>
+<LI><A HREF="#10_70_3">Returns</A></LI>
+<LI><A HREF="#10_70_4">Description</A></LI>
+<LI><A HREF="#10_70_5">Example</A></LI>
+<LI><A HREF="#10_70_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpHead">httpHead()</A>
+<UL>
+<LI><A HREF="#10_71_1">Usage</A></LI>
+<LI><A HREF="#10_71_2">Arguments</A></LI>
+<LI><A HREF="#10_71_3">Returns</A></LI>
+<LI><A HREF="#10_71_4">Description</A></LI>
+<LI><A HREF="#10_71_5">Example</A></LI>
+<LI><A HREF="#10_71_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpInitialize">httpInitialize()</A>
+<UL>
+<LI><A HREF="#10_72_1">Usage</A></LI>
+<LI><A HREF="#10_72_2">Description</A></LI>
+<LI><A HREF="#10_72_3">Example</A></LI>
+<LI><A HREF="#10_72_4">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpMD5">httpMD5()</A>
+<UL>
+<LI><A HREF="#10_73_1">Usage</A></LI>
+<LI><A HREF="#10_73_2">Arguments</A></LI>
+<LI><A HREF="#10_73_3">Returns</A></LI>
+<LI><A HREF="#10_73_4">Description</A></LI>
+<LI><A HREF="#10_73_5">Example</A></LI>
+<LI><A HREF="#10_73_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpMD5Final">httpMD5Final()</A>
+<UL>
+<LI><A HREF="#10_74_1">Usage</A></LI>
+<LI><A HREF="#10_74_2">Arguments</A></LI>
+<LI><A HREF="#10_74_3">Returns</A></LI>
+<LI><A HREF="#10_74_4">Description</A></LI>
+<LI><A HREF="#10_74_5">Example</A></LI>
+<LI><A HREF="#10_74_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpMD5String">httpMD5String()</A>
+<UL>
+<LI><A HREF="#10_75_1">Usage</A></LI>
+<LI><A HREF="#10_75_2">Arguments</A></LI>
+<LI><A HREF="#10_75_3">Returns</A></LI>
+<LI><A HREF="#10_75_4">Description</A></LI>
+<LI><A HREF="#10_75_5">Example</A></LI>
+<LI><A HREF="#10_75_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpOptions">httpOptions()</A>
+<UL>
+<LI><A HREF="#10_76_1">Usage</A></LI>
+<LI><A HREF="#10_76_2">Arguments</A></LI>
+<LI><A HREF="#10_76_3">Returns</A></LI>
+<LI><A HREF="#10_76_4">Description</A></LI>
+<LI><A HREF="#10_76_5">Example</A></LI>
+<LI><A HREF="#10_76_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpPost">httpPost()</A>
+<UL>
+<LI><A HREF="#10_77_1">Usage</A></LI>
+<LI><A HREF="#10_77_2">Arguments</A></LI>
+<LI><A HREF="#10_77_3">Returns</A></LI>
+<LI><A HREF="#10_77_4">Description</A></LI>
+<LI><A HREF="#10_77_5">Example</A></LI>
+<LI><A HREF="#10_77_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpPrintf">httpPrintf()</A>
+<UL>
+<LI><A HREF="#10_78_1">Usage</A></LI>
+<LI><A HREF="#10_78_2">Arguments</A></LI>
+<LI><A HREF="#10_78_3">Returns</A></LI>
+<LI><A HREF="#10_78_4">Description</A></LI>
+<LI><A HREF="#10_78_5">Example</A></LI>
+<LI><A HREF="#10_78_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpPut">httpPut()</A>
+<UL>
+<LI><A HREF="#10_79_1">Usage</A></LI>
+<LI><A HREF="#10_79_2">Arguments</A></LI>
+<LI><A HREF="#10_79_3">Returns</A></LI>
+<LI><A HREF="#10_79_4">Description</A></LI>
+<LI><A HREF="#10_79_5">Example</A></LI>
+<LI><A HREF="#10_79_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpRead">httpRead()</A>
+<UL>
+<LI><A HREF="#10_80_1">Usage</A></LI>
+<LI><A HREF="#10_80_2">Arguments</A></LI>
+<LI><A HREF="#10_80_3">Returns</A></LI>
+<LI><A HREF="#10_80_4">Description</A></LI>
+<LI><A HREF="#10_80_5">Example</A></LI>
+<LI><A HREF="#10_80_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpReconnect">httpReconnect()</A>
+<UL>
+<LI><A HREF="#10_81_1">Usage</A></LI>
+<LI><A HREF="#10_81_2">Arguments</A></LI>
+<LI><A HREF="#10_81_3">Returns</A></LI>
+<LI><A HREF="#10_81_4">Description</A></LI>
+<LI><A HREF="#10_81_5">Example</A></LI>
+<LI><A HREF="#10_81_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpSeparate">httpSeparate()</A>
+<UL>
+<LI><A HREF="#10_82_1">Usage</A></LI>
+<LI><A HREF="#10_82_2">Arguments</A></LI>
+<LI><A HREF="#10_82_3">Description</A></LI>
+<LI><A HREF="#10_82_4">Example</A></LI>
+<LI><A HREF="#10_82_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpSetField">httpSetField()</A>
+<UL>
+<LI><A HREF="#10_83_1">Usage</A></LI>
+<LI><A HREF="#10_83_2">Arguments</A></LI>
+<LI><A HREF="#10_83_3">Description</A></LI>
+<LI><A HREF="#10_83_4">Example</A></LI>
+<LI><A HREF="#10_83_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpStatus">httpStatus()</A>
+<UL>
+<LI><A HREF="#10_84_1">Usage</A></LI>
+<LI><A HREF="#10_84_2">Arguments</A></LI>
+<LI><A HREF="#10_84_3">Returns</A></LI>
+<LI><A HREF="#10_84_4">Description</A></LI>
+<LI><A HREF="#10_84_5">Example</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpTrace">httpTrace()</A>
+<UL>
+<LI><A HREF="#10_85_1">Usage</A></LI>
+<LI><A HREF="#10_85_2">Arguments</A></LI>
+<LI><A HREF="#10_85_3">Returns</A></LI>
+<LI><A HREF="#10_85_4">Description</A></LI>
+<LI><A HREF="#10_85_5">Example</A></LI>
+<LI><A HREF="#10_85_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpUpdate">httpUpdate()</A>
+<UL>
+<LI><A HREF="#10_86_1">Usage</A></LI>
+<LI><A HREF="#10_86_2">Arguments</A></LI>
+<LI><A HREF="#10_86_3">Returns</A></LI>
+<LI><A HREF="#10_86_4">Description</A></LI>
+<LI><A HREF="#10_86_5">Example</A></LI>
+<LI><A HREF="#10_86_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#httpWrite">httpWrite()</A>
+<UL>
+<LI><A HREF="#10_87_1">Usage</A></LI>
+<LI><A HREF="#10_87_2">Arguments</A></LI>
+<LI><A HREF="#10_87_3">Returns</A></LI>
+<LI><A HREF="#10_87_4">Description</A></LI>
+<LI><A HREF="#10_87_5">Example</A></LI>
+<LI><A HREF="#10_87_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddBoolean">ippAddBoolean()</A>
+<UL>
+<LI><A HREF="#10_88_1">Usage</A></LI>
+<LI><A HREF="#10_88_2">Arguments</A></LI>
+<LI><A HREF="#10_88_3">Returns</A></LI>
+<LI><A HREF="#10_88_4">Description</A></LI>
+<LI><A HREF="#10_88_5">Example</A></LI>
+<LI><A HREF="#10_88_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddBooleans">ippAddBooleans()</A>
+<UL>
+<LI><A HREF="#10_89_1">Usage</A></LI>
+<LI><A HREF="#10_89_2">Arguments</A></LI>
+<LI><A HREF="#10_89_3">Returns</A></LI>
+<LI><A HREF="#10_89_4">Description</A></LI>
+<LI><A HREF="#10_89_5">Example</A></LI>
+<LI><A HREF="#10_89_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddDate">ippAddDate()</A>
+<UL>
+<LI><A HREF="#10_90_1">Usage</A></LI>
+<LI><A HREF="#10_90_2">Arguments</A></LI>
+<LI><A HREF="#10_90_3">Returns</A></LI>
+<LI><A HREF="#10_90_4">Description</A></LI>
+<LI><A HREF="#10_90_5">Example</A></LI>
+<LI><A HREF="#10_90_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddInteger">ippAddInteger()</A>
+<UL>
+<LI><A HREF="#10_91_1">Usage</A></LI>
+<LI><A HREF="#10_91_2">Arguments</A></LI>
+<LI><A HREF="#10_91_3">Returns</A></LI>
+<LI><A HREF="#10_91_4">Description</A></LI>
+<LI><A HREF="#10_91_5">Example</A></LI>
+<LI><A HREF="#10_91_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddIntegers">ippAddIntegers()</A>
+<UL>
+<LI><A HREF="#10_92_1">Usage</A></LI>
+<LI><A HREF="#10_92_2">Arguments</A></LI>
+<LI><A HREF="#10_92_3">Returns</A></LI>
+<LI><A HREF="#10_92_4">Description</A></LI>
+<LI><A HREF="#10_92_5">Example</A></LI>
+<LI><A HREF="#10_92_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddRange">ippAddRange()</A>
+<UL>
+<LI><A HREF="#10_93_1">Usage</A></LI>
+<LI><A HREF="#10_93_2">Arguments</A></LI>
+<LI><A HREF="#10_93_3">Returns</A></LI>
+<LI><A HREF="#10_93_4">Description</A></LI>
+<LI><A HREF="#10_93_5">Example</A></LI>
+<LI><A HREF="#10_93_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddRanges">ippAddRanges()</A>
+<UL>
+<LI><A HREF="#10_94_1">Usage</A></LI>
+<LI><A HREF="#10_94_2">Arguments</A></LI>
+<LI><A HREF="#10_94_3">Returns</A></LI>
+<LI><A HREF="#10_94_4">Description</A></LI>
+<LI><A HREF="#10_94_5">Example</A></LI>
+<LI><A HREF="#10_94_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddResolution">ippAddResolution()</A>
+<UL>
+<LI><A HREF="#10_95_1">Usage</A></LI>
+<LI><A HREF="#10_95_2">Arguments</A></LI>
+<LI><A HREF="#10_95_3">Returns</A></LI>
+<LI><A HREF="#10_95_4">Description</A></LI>
+<LI><A HREF="#10_95_5">Example</A></LI>
+<LI><A HREF="#10_95_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddResolutions">ippAddResolutions()</A>
+<UL>
+<LI><A HREF="#10_96_1">Usage</A></LI>
+<LI><A HREF="#10_96_2">Arguments</A></LI>
+<LI><A HREF="#10_96_3">Returns</A></LI>
+<LI><A HREF="#10_96_4">Description</A></LI>
+<LI><A HREF="#10_96_5">Example</A></LI>
+<LI><A HREF="#10_96_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddSeparator">ippAddSeparator()</A>
+<UL>
+<LI><A HREF="#10_97_1">Usage</A></LI>
+<LI><A HREF="#10_97_2">Arguments</A></LI>
+<LI><A HREF="#10_97_3">Returns</A></LI>
+<LI><A HREF="#10_97_4">Description</A></LI>
+<LI><A HREF="#10_97_5">Example</A></LI>
+<LI><A HREF="#10_97_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddString">ippAddString()</A>
+<UL>
+<LI><A HREF="#10_98_1">Usage</A></LI>
+<LI><A HREF="#10_98_2">Arguments</A></LI>
+<LI><A HREF="#10_98_3">Returns</A></LI>
+<LI><A HREF="#10_98_4">Description</A></LI>
+<LI><A HREF="#10_98_5">Example</A></LI>
+<LI><A HREF="#10_98_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippAddStrings">ippAddStrings()</A>
+<UL>
+<LI><A HREF="#10_99_1">Usage</A></LI>
+<LI><A HREF="#10_99_2">Arguments</A></LI>
+<LI><A HREF="#10_99_3">Returns</A></LI>
+<LI><A HREF="#10_99_4">Description</A></LI>
+<LI><A HREF="#10_99_5">Example</A></LI>
+<LI><A HREF="#10_99_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippDateToTime">ippDateToTime()</A>
+<UL>
+<LI><A HREF="#10_100_1">Usage</A></LI>
+<LI><A HREF="#10_100_2">Arguments</A></LI>
+<LI><A HREF="#10_100_3">Returns</A></LI>
+<LI><A HREF="#10_100_4">Description</A></LI>
+<LI><A HREF="#10_100_5">Example</A></LI>
+<LI><A HREF="#10_100_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippDelete">ippDelete()</A>
+<UL>
+<LI><A HREF="#10_101_1">Usage</A></LI>
+<LI><A HREF="#10_101_2">Arguments</A></LI>
+<LI><A HREF="#10_101_3">Description</A></LI>
+<LI><A HREF="#10_101_4">Example</A></LI>
+<LI><A HREF="#10_101_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippErrorString">ippErrorString()</A>
+<UL>
+<LI><A HREF="#10_102_1">Usage</A></LI>
+<LI><A HREF="#10_102_2">Arguments</A></LI>
+<LI><A HREF="#10_102_3">Returns</A></LI>
+<LI><A HREF="#10_102_4">Description</A></LI>
+<LI><A HREF="#10_102_5">Example</A></LI>
+<LI><A HREF="#10_102_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippFindAttribute">ippFindAttribute()</A>
+<UL>
+<LI><A HREF="#10_103_1">Usage</A></LI>
+<LI><A HREF="#10_103_2">Arguments</A></LI>
+<LI><A HREF="#10_103_3">Returns</A></LI>
+<LI><A HREF="#10_103_4">Description</A></LI>
+<LI><A HREF="#10_103_5">Example</A></LI>
+<LI><A HREF="#10_103_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippFindNextAttribute">ippFindNextAttribute()</A>
+<UL>
+<LI><A HREF="#10_104_1">Usage</A></LI>
+<LI><A HREF="#10_104_2">Arguments</A></LI>
+<LI><A HREF="#10_104_3">Returns</A></LI>
+<LI><A HREF="#10_104_4">Description</A></LI>
+<LI><A HREF="#10_104_5">Example</A></LI>
+<LI><A HREF="#10_104_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippLength">ippLength()</A>
+<UL>
+<LI><A HREF="#10_105_1">Usage</A></LI>
+<LI><A HREF="#10_105_2">Arguments</A></LI>
+<LI><A HREF="#10_105_3">Returns</A></LI>
+<LI><A HREF="#10_105_4">Description</A></LI>
+<LI><A HREF="#10_105_5">Example</A></LI>
+<LI><A HREF="#10_105_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippNew">ippNew()</A>
+<UL>
+<LI><A HREF="#10_106_1">Usage</A></LI>
+<LI><A HREF="#10_106_2">Returns</A></LI>
+<LI><A HREF="#10_106_3">Description</A></LI>
+<LI><A HREF="#10_106_4">Example</A></LI>
+<LI><A HREF="#10_106_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippPort">ippPort()</A>
+<UL>
+<LI><A HREF="#10_107_1">Usage</A></LI>
+<LI><A HREF="#10_107_2">Returns</A></LI>
+<LI><A HREF="#10_107_3">Description</A></LI>
+<LI><A HREF="#10_107_4">Example</A></LI>
+<LI><A HREF="#10_107_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippRead">ippRead()</A>
+<UL>
+<LI><A HREF="#10_108_1">Usage</A></LI>
+<LI><A HREF="#10_108_2">Arguments</A></LI>
+<LI><A HREF="#10_108_3">Returns</A></LI>
+<LI><A HREF="#10_108_4">Description</A></LI>
+<LI><A HREF="#10_108_5">Example</A></LI>
+<LI><A HREF="#10_108_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippSetPort">ippSetPort()</A>
+<UL>
+<LI><A HREF="#10_109_1">Usage</A></LI>
+<LI><A HREF="#10_109_2">Arguments</A></LI>
+<LI><A HREF="#10_109_3">Description</A></LI>
+<LI><A HREF="#10_109_4">Example</A></LI>
+<LI><A HREF="#10_109_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippTimeToDate">ippTimeToDate()</A>
+<UL>
+<LI><A HREF="#10_110_1">Usage</A></LI>
+<LI><A HREF="#10_110_2">Arguments</A></LI>
+<LI><A HREF="#10_110_3">Returns</A></LI>
+<LI><A HREF="#10_110_4">Description</A></LI>
+<LI><A HREF="#10_110_5">Example</A></LI>
+<LI><A HREF="#10_110_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ippWrite">ippWrite()</A>
+<UL>
+<LI><A HREF="#10_111_1">Usage</A></LI>
+<LI><A HREF="#10_111_2">Arguments</A></LI>
+<LI><A HREF="#10_111_3">Returns</A></LI>
+<LI><A HREF="#10_111_4">Description</A></LI>
+<LI><A HREF="#10_111_5">Example</A></LI>
+<LI><A HREF="#10_111_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdClose">ppdClose()</A>
+<UL>
+<LI><A HREF="#10_112_1">Usage</A></LI>
+<LI><A HREF="#10_112_2">Arguments</A></LI>
+<LI><A HREF="#10_112_3">Description</A></LI>
+<LI><A HREF="#10_112_4">Example</A></LI>
+<LI><A HREF="#10_112_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdCollect">ppdCollect()</A>
+<UL>
+<LI><A HREF="#10_113_1">Usage</A></LI>
+<LI><A HREF="#10_113_2">Arguments</A></LI>
+<LI><A HREF="#10_113_3">Returns</A></LI>
+<LI><A HREF="#10_113_4">Description</A></LI>
+<LI><A HREF="#10_113_5">Example</A></LI>
+<LI><A HREF="#10_113_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdConflicts">ppdConflicts()</A>
+<UL>
+<LI><A HREF="#10_114_1">Usage</A></LI>
+<LI><A HREF="#10_114_2">Arguments</A></LI>
+<LI><A HREF="#10_114_3">Returns</A></LI>
+<LI><A HREF="#10_114_4">Description</A></LI>
+<LI><A HREF="#10_114_5">Example</A></LI>
+<LI><A HREF="#10_114_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdEmit">ppdEmit()</A>
+<UL>
+<LI><A HREF="#10_115_1">Usage</A></LI>
+<LI><A HREF="#10_115_2">Arguments</A></LI>
+<LI><A HREF="#10_115_3">Returns</A></LI>
+<LI><A HREF="#10_115_4">Description</A></LI>
+<LI><A HREF="#10_115_5">Example</A></LI>
+<LI><A HREF="#10_115_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdEmitFd">ppdEmitFd()</A>
+<UL>
+<LI><A HREF="#10_116_1">Usage</A></LI>
+<LI><A HREF="#10_116_2">Arguments</A></LI>
+<LI><A HREF="#10_116_3">Returns</A></LI>
+<LI><A HREF="#10_116_4">Description</A></LI>
+<LI><A HREF="#10_116_5">Example</A></LI>
+<LI><A HREF="#10_116_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdEmitJCL">ppdEmitJCL()</A>
+<UL>
+<LI><A HREF="#10_117_1">Usage</A></LI>
+<LI><A HREF="#10_117_2">Arguments</A></LI>
+<LI><A HREF="#10_117_3">Returns</A></LI>
+<LI><A HREF="#10_117_4">Description</A></LI>
+<LI><A HREF="#10_117_5">Example</A></LI>
+<LI><A HREF="#10_117_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdFindAttr">ppdFindAttr()</A>
+<UL>
+<LI><A HREF="#10_118_1">Usage</A></LI>
+<LI><A HREF="#10_118_2">Arguments</A></LI>
+<LI><A HREF="#10_118_3">Returns</A></LI>
+<LI><A HREF="#10_118_4">Description</A></LI>
+<LI><A HREF="#10_118_5">Example</A></LI>
+<LI><A HREF="#10_118_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdFindChoice">ppdFindChoice()</A>
+<UL>
+<LI><A HREF="#10_119_1">Usage</A></LI>
+<LI><A HREF="#10_119_2">Arguments</A></LI>
+<LI><A HREF="#10_119_3">Returns</A></LI>
+<LI><A HREF="#10_119_4">Description</A></LI>
+<LI><A HREF="#10_119_5">Example</A></LI>
+<LI><A HREF="#10_119_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdFindMarkedChoice">ppdFindMarkedChoice()</A>
+<UL>
+<LI><A HREF="#10_120_1">Usage</A></LI>
+<LI><A HREF="#10_120_2">Arguments</A></LI>
+<LI><A HREF="#10_120_3">Returns</A></LI>
+<LI><A HREF="#10_120_4">Description</A></LI>
+<LI><A HREF="#10_120_5">Example</A></LI>
+<LI><A HREF="#10_120_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdFindNextAttr">ppdFindNextAttr()</A>
+<UL>
+<LI><A HREF="#10_121_1">Usage</A></LI>
+<LI><A HREF="#10_121_2">Arguments</A></LI>
+<LI><A HREF="#10_121_3">Returns</A></LI>
+<LI><A HREF="#10_121_4">Description</A></LI>
+<LI><A HREF="#10_121_5">Example</A></LI>
+<LI><A HREF="#10_121_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdFindOption">ppdFindOption()</A>
+<UL>
+<LI><A HREF="#10_122_1">Usage</A></LI>
+<LI><A HREF="#10_122_2">Arguments</A></LI>
+<LI><A HREF="#10_122_3">Returns</A></LI>
+<LI><A HREF="#10_122_4">Description</A></LI>
+<LI><A HREF="#10_122_5">Example</A></LI>
+<LI><A HREF="#10_122_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdIsMarked">ppdIsMarked()</A>
+<UL>
+<LI><A HREF="#10_123_1">Usage</A></LI>
+<LI><A HREF="#10_123_2">Arguments</A></LI>
+<LI><A HREF="#10_123_3">Returns</A></LI>
+<LI><A HREF="#10_123_4">Description</A></LI>
+<LI><A HREF="#10_123_5">Example</A></LI>
+<LI><A HREF="#10_123_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdMarkDefaults">ppdMarkDefaults()</A>
+<UL>
+<LI><A HREF="#10_124_1">Usage</A></LI>
+<LI><A HREF="#10_124_2">Arguments</A></LI>
+<LI><A HREF="#10_124_3">Description</A></LI>
+<LI><A HREF="#10_124_4">Example</A></LI>
+<LI><A HREF="#10_124_5">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdMarkOption">ppdMarkOption()</A>
+<UL>
+<LI><A HREF="#10_125_1">Usage</A></LI>
+<LI><A HREF="#10_125_2">Arguments</A></LI>
+<LI><A HREF="#10_125_3">Returns</A></LI>
+<LI><A HREF="#10_125_4">Description</A></LI>
+<LI><A HREF="#10_125_5">Example</A></LI>
+<LI><A HREF="#10_125_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdOpen">ppdOpen()</A>
+<UL>
+<LI><A HREF="#10_126_1">Usage</A></LI>
+<LI><A HREF="#10_126_2">Arguments</A></LI>
+<LI><A HREF="#10_126_3">Returns</A></LI>
+<LI><A HREF="#10_126_4">Description</A></LI>
+<LI><A HREF="#10_126_5">Example</A></LI>
+<LI><A HREF="#10_126_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdOpenFd">ppdOpenFd()</A>
+<UL>
+<LI><A HREF="#10_127_1">Usage</A></LI>
+<LI><A HREF="#10_127_2">Arguments</A></LI>
+<LI><A HREF="#10_127_3">Returns</A></LI>
+<LI><A HREF="#10_127_4">Description</A></LI>
+<LI><A HREF="#10_127_5">Example</A></LI>
+<LI><A HREF="#10_127_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdOpenFile">ppdOpenFile()</A>
+<UL>
+<LI><A HREF="#10_128_1">Usage</A></LI>
+<LI><A HREF="#10_128_2">Arguments</A></LI>
+<LI><A HREF="#10_128_3">Returns</A></LI>
+<LI><A HREF="#10_128_4">Description</A></LI>
+<LI><A HREF="#10_128_5">Example</A></LI>
+<LI><A HREF="#10_128_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdPageLength">ppdPageLength()</A>
+<UL>
+<LI><A HREF="#10_129_1">Usage</A></LI>
+<LI><A HREF="#10_129_2">Arguments</A></LI>
+<LI><A HREF="#10_129_3">Returns</A></LI>
+<LI><A HREF="#10_129_4">Description</A></LI>
+<LI><A HREF="#10_129_5">Example</A></LI>
+<LI><A HREF="#10_129_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdPageSize">ppdPageSize()</A>
+<UL>
+<LI><A HREF="#10_130_1">Usage</A></LI>
+<LI><A HREF="#10_130_2">Arguments</A></LI>
+<LI><A HREF="#10_130_3">Returns</A></LI>
+<LI><A HREF="#10_130_4">Description</A></LI>
+<LI><A HREF="#10_130_5">Example</A></LI>
+<LI><A HREF="#10_130_6">See Also</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#ppdPageWidth">ppdPageWidth()</A>
+<UL>
+<LI><A HREF="#10_131_1">Usage</A></LI>
+<LI><A HREF="#10_131_2">Arguments</A></LI>
+<LI><A HREF="#10_131_3">Returns</A></LI>
+<LI><A HREF="#10_131_4">Description</A></LI>
+<LI><A HREF="#10_131_5">Example</A></LI>
+<LI><A HREF="#10_131_6">See Also</A></LI>
+</UL>
+</LI>
+</UL>
+</B><HR NOSHADE>
+<H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
+<P>This software programmers manual provides software programming
+ information for the Common UNIX Printing System (&quot;CUPS&quot;) Version
+ 1.1.22.</P>
+<H2><A NAME="1_1">System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+
+<!-- NEED 2in -->
+<H2><A NAME="1_2">Document Overview</A></H2>
+<P>This software programmers manual is organized into the following
+ sections:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Printing System Overview</A></LI>
+<LI><A HREF="#CUPS_API">2 - The CUPS API</A></LI>
+<LI><A HREF="#WRITING_FILTERS">3 - Writing Filters</A></LI>
+<LI><A HREF="#WRITING_DRIVERS">4 - Writing Printer Drivers</A></LI>
+<LI><A HREF="#WRITING_BACKENDS">5 - Writing Backends</A></LI>
+<LI><A HREF="#LICENSE">A - Software License Agreement</A></LI>
+<LI><A HREF="#CONSTANTS">B - Constants</A></LI>
+<LI><A HREF="#STRUCTURES">C - Structures</A></LI>
+<LI><A HREF="#FUNCTIONS">D - Functions</A></LI>
+</UL>
+<H2><A NAME="1_3">Notation Conventions</A></H2>
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><VAR>/var</VAR>
+<BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+File and directory names.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><TT>Request ID is Printer-123</TT></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abbreviations</A></H2>
+ The following abbreviations are used throughout this manual:
+<UL>
+<DL>
+<DT>kb</DT>
+<DD>Kilobytes, or 1024 bytes
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
+<DD>Megabytes, or 1048576 bytes
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
+<DD>Gigabytes, or 1073741824 bytes
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Other References</A></H2>
+<UL>
+<DL>
+<DT>CUPS Software Administrators Manual</DT>
+<DD>An administration guide for the CUPS software.
+<BR>&nbsp;</DD>
+<DT>CUPS Software Users Manual</DT>
+<DD>An end-user guide for using the CUPS software.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
+<H2><A NAME="2_1">The Printing Problem</A></H2>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
+<H2><A NAME="2_2">The Technology</A></H2>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
+<H2><A NAME="2_3">Jobs</A></H2>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
+<H2><A NAME="2_4">Classes</A></H2>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
+<H2><A NAME="2_5">Filters</A></H2>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
+<H2><A NAME="2_6">Backends</A></H2>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
+<H2><A NAME="2_7">Printer Drivers</A></H2>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
+<H2><A NAME="2_8">Networking</A></H2>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
+<H1 ALIGN="RIGHT"><A NAME="CUPS_API">2 - The CUPS API</A></H1>
+<P>This chapter describes the CUPS Application Programmers Interface
+ (&quot;API&quot;).</P>
+<H2><A NAME="3_1">The CUPS API Library</A></H2>
+<P>The CUPS library provides a whole collection of interfaces needed to
+ support the internal needs of the CUPS software as well as the needs of
+ applications, filters, printer drivers, and backends.</P>
+<P>Unlike the rest of CUPS, the CUPS API library is provided under the
+ GNU Library General Public License. This means that you can use the
+ CUPS API library in both proprietary and open-source programs.</P>
+<P>Programs that use the CUPS API library typically will include the <CODE>
+&lt;cups/cups.h&gt;</CODE> header file:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+jobid = cupsPrintFile(&quot;myprinter&quot;, &quot;filename.ps&quot;, &quot;title&quot;,
+ num_options, options);
+</PRE>
+</UL>
+<P>Use the <CODE>-lcups</CODE> compiler option when linking to the CUPS
+ API library:</P>
+<UL>
+<PRE>
+<B>cc -o program program.c -lcups ENTER</B>
+</PRE>
+</UL>
+<P>Additional options and libraries may be required depending on the
+ operating system and the location of the CUPS API library.</P>
+<H3><A NAME="3_1_1">Detecting the CUPS API Library in GNU Autoconf</A></H3>
+<P>GNU autoconf is a popular configuration tool used by many programs.
+ Add the following lines to your<VAR> configure.in</VAR> file to check
+ for the CUPS API library in your configuration script:</P>
+<UL>
+<PRE>
+AC_CHECK_LIB(socket,socket,
+if test &quot;$uname&quot; != &quot;IRIX&quot;; then
+ LIBS=&quot;-lsocket $LIBS&quot;
+else
+ echo &quot;Not using -lsocket since you are running IRIX.&quot;
+fi)
+AC_CHECK_LIB(nsl,gethostbyaddr,
+if test &quot;$uname&quot; != &quot;IRIX&quot;; then
+ LIBS=&quot;-lnsl $LIBS&quot;
+else
+ echo &quot;Not using -lnsl since you are running IRIX.&quot;
+fi)
+
+AC_CHECK_LIB(cups,httpConnect)
+</PRE>
+</UL>
+<H2><A NAME="3_2">Printing Services</A></H2>
+<P>The CUPS API library provides some basic printing services for
+ applications that need to print files.</P>
+<H3><A NAME="3_2_1">Include Files</A></H3>
+<P>The include file used by all of these functions is <CODE>
+&lt;cups/cups.h&gt;</CODE>:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+</PRE>
+</UL>
+<H3><A NAME="3_2_2">Printing a File</A></H3>
+<P>The CUPS API provides two functions for printing files. The first is <CODE>
+cupsPrintFile</CODE> which prints a single named file:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+
+...
+
+jobid = cupsPrintFile(&quot;<I>name</I>&quot;, &quot;<I>filename</I>&quot;, &quot;<I>title</I>&quot;, 0, NULL);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> string is the name of the printer or class to
+ print to. The <CODE>filename</CODE> string is the name of the file to
+ print. The <CODE>title</CODE> string is the name of the print job, e.g.
+ &quot;Acme Word Document&quot;.</P>
+<P>The return value is a unique ID number for the print job or 0 if
+ there was an error.</P>
+<H3><A NAME="3_2_3">Printing Multiple Files</A></H3>
+<P>The second printing function is <CODE>cupsPrintFiles</CODE>:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int num_files;
+const char *files[100];
+...
+
+jobid = cupsPrintFiles(&quot;name&quot;, <I>num_files</I>, <I>files</I>, &quot;title&quot;, 0, NULL);
+</PRE>
+</UL>
+<P>Instead of passing a filename string as with <CODE>cupsPrintFile()</CODE>
+ you pass a file count (<CODE>num_files</CODE>) and filename pointer
+ array (<CODE>files</CODE>) for each file that you want to print.</P>
+<P>As with <CODE>cupsPrintFile()</CODE> the return value is a unique ID
+ for the print job.</P>
+<H3><A NAME="3_2_4">Cancelling Jobs</A></H3>
+<P>The <CODE>cupsCancelJob()</CODE> function cancels a queued print job:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int status;
+...
+
+status = cupsCancelJob(&quot;<I>name</I>&quot;, <I>jobid</I>);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> string specifies the destination and is used to
+ determine the server to send the request to. The <CODE>jobid</CODE>
+ value is the integer returned from a previous <CODE>cupsPrintFile()</CODE>
+ or <CODE>cupsPrintFiles()</CODE> call.</P>
+<P><CODE>cupsCancelJob()</CODE> returns <CODE>1</CODE> if the job was
+ successfully cancelled and <CODE>0</CODE> if there was an error.</P>
+<H3><A NAME="3_2_5">Getting the Available Printers and Classes</A></H3>
+<P>The <CODE>cupsGetDests()</CODE> function can be used to get a list of
+ the available printers, classes, and instances that a user has defined:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_dests;
+cups_dest_t *dests;
+
+...
+
+num_dests = cupsGetDests(&amp;dests);
+</PRE>
+</UL>
+<P>Each destination is stored in a <CODE>cups_dest_t</CODE> structure
+ which defines the printer or class name, the instance name (if any), if
+ it is the default destination, and the default options the user has
+ defined for the destination:</P>
+<UL>
+<PRE>
+typedef struct /**** Destination ****/
+{
+ char *name, /* Printer or class name */
+ *instance; /* Local instance name or NULL */
+ int is_default; /* Is this printer the default? */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+} cups_dest_t;
+</PRE>
+</UL>
+<P>The destinations are sorted by name and instance for your
+ convenience. Once you have the list of available destinations, you can
+ lookup a specific destination using the <CODE>cupsGetDest()</CODE>
+ function:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_dests;
+cups_dest_t *dests;
+cups_dest_t *mydest;
+
+...
+
+mydest = cupsGetDest(&quot;<I>name</I>&quot;, &quot;<I>instance</I>&quot;, num_dests, dests);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> string is the printer or class name. You can
+ pass a value of <CODE>NULL</CODE> to get the default destination.</P>
+<P>The <CODE>instance</CODE> string is the user-defined instance name.
+ Pass <CODE>NULL</CODE> to select the default instance, e.g. &quot;name&quot;
+ instead of &quot;name/instance&quot;.</P>
+<H3><A NAME="3_2_6">Printing with Options</A></H3>
+<P>All of the previous printing examples have passed <CODE>0</CODE> and <CODE>
+NULL</CODE> for the last two arguments to the <CODE>cupsPrintFile()</CODE>
+ and <CODE>cupsPrintFiles()</CODE> functions. These last two arguments
+ are the number of options and a pointer to the option array:</P>
+<UL>
+<PRE>
+int cupsPrintFile(const char *name, const char *filename, const char *title,
+ int num_options, cups_option_t *options);
+int cupsPrintFiles(const char *name, int num_files, const char **files,
+ const char *title, int num_options,
+ cups_option_t *options);
+</PRE>
+</UL>
+<P>The <CODE>cups_option_t</CODE> structure holds each option and its
+ value. These are converted as needed and passed to the CUPS server when
+ printing a file.</P>
+<P>The simplest way of handling options is to use the <CODE>num_options</CODE>
+ and <CODE>options</CODE> members of the <CODE>cups_dest_t</CODE>
+ structure described earlier:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int num_dests;
+cups_dest_t *dests;
+cups_dest_t *mydest;
+
+...
+
+mydest = cupsGetDest(&quot;<I>name</I>&quot;, &quot;<I>instance</I>&quot;, num_dests, dests);
+
+jobid = cupsPrintFile(mydest-&gt;name, &quot;filename&quot;, &quot;title&quot;,
+ mydest-&gt;num_options, mydest-&gt;options);
+</PRE>
+</UL>
+<P>This effectively uses the options a user has previous selected
+ without a lot of code.</P>
+<H3><A NAME="3_2_7">Setting Printer Options</A></H3>
+<P>Options can also be set by your program using the <CODE>
+cupsAddOption()</CODE> function:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options = NULL;
+
+...
+
+num_options = cupsAddOption(&quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;, num_options, &amp;options);
+num_options = cupsAddOption(&quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;, num_options, &amp;options);
+num_options = cupsAddOption(&quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;, num_options, &amp;options);
+num_options = cupsAddOption(&quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;, num_options, &amp;options);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> string is the name of the option, and the <CODE>
+value</CODE> string is the value for that option.</P>
+<P>Each call to <CODE>cupsAddOption()</CODE> returns the new number of
+ options. Since adding two options with the same name overwrites the
+ first value with the second, do not assume that calling <CODE>
+cupsAddOptions()</CODE> 20 times will result in 20 options.</P>
+<P>Call <CODE>cupsFreeOptions</CODE> once you are done using the
+ options:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+</PRE>
+</UL>
+<H3><A NAME="3_2_8">Getting Errors</A></H3>
+<P>If any of the CUPS API printing functions returns an error, the
+ reason for that error can be found by calling <CODE>cupsLastError()</CODE>
+ and <CODE>ippErrorString()</CODE>. <CODE>cupsLastError()</CODE> returns
+ the last IPP error code that was encountered. <CODE>ippErrorString()</CODE>
+ converts the error code to a localized message string suitable for
+ presentation to the user:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+
+...
+
+if (jobid == 0)
+ puts(ippErrorString(cupsLastError()));
+</PRE>
+</UL>
+<H3><A NAME="3_2_9">Passwords and Authentication</A></H3>
+<P>CUPS supports authentication of any request, including submission of
+ print jobs. The default mechanism for getting the username and password
+ is to use the login user and a password from the console.</P>
+<P>To support other types of applications, in particular Graphical User
+ Interfaces (&quot;GUIs&quot;), the CUPS API provides functions to set the default
+ username and to register a callback function that returns a password
+ string.</P>
+<P>The <A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>
+ function is used to set a password callback in your program. Only one
+ function can be used at any time.</P>
+<P>The <A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A> function
+ sets the current username for authentication. This function can be
+ called by your password callback function to change the current
+ username as needed.</P>
+<P>The following example shows a simple password callback that gets a
+ username and password from the user:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *
+my_password_cb(const char *prompt)
+{
+ char user[65];
+
+
+ puts(prompt);
+
+ /* Get a username from the user */
+ printf(&quot;Username: &quot;);
+ if (fgets(user, sizeof(user), stdin) == NULL)
+ return (NULL);
+
+ /* Strip the newline from the string and set the user */
+ user[strlen(user) - 1] = '\0';
+
+ cupsSetUser(user);
+
+ /* Use getpass() to ask for the password... */
+ return (getpass(&quot;Password: &quot;));
+}
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+</PRE>
+</UL>
+<P>Similarly, a GUI interface could display the prompt string in a
+ window with input fields for the username and password. The username
+ should probably default to the value of <A HREF="#cupsUser"><CODE>
+cupsUser()</CODE></A> to make things easier on the user.</P>
+<H2><A NAME="3_3">PPD Services</A></H2>
+<P>CUPS includes functions to access and manipulate PostScript Printer
+ Description (&quot;PPD&quot;) files that are used with the printer drivers in
+ CUPS.</P>
+<P>Each PPD file enumerates the available features provided by a
+ printer, including conflict information for specific options (e.g.
+ can't duplex output on envelopes.)</P>
+<H3><A NAME="3_3_1">Include Files</A></H3>
+<P>Include the <CODE>&lt;cups/ppd.h&gt;</CODE> header file to use the PPD
+ functions:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+</PRE>
+</UL>
+<P>This header file is also included by the <CODE>&lt;cups/cups.h&gt;</CODE>
+ header file.</P>
+<H3><A NAME="3_3_2">Getting a PPD File for a Printer</A></H3>
+<P>The <CODE>cupsGetPPD()</CODE> function retrieves the PPD file for the
+ named printer or class:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+const char *filename;
+
+filename = cupsGetPPD(&quot;<I>name</I>&quot;);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> string is the name of the printer or class,
+ including the remote server name as appropriate (e.g.
+ &quot;printer@server&quot;.)</P>
+<P>The return value is a pointer to a filename in static storage; this
+ value is overwritten with each call to <CODE>cupsGetPPD()</CODE>. If
+ the printer or class does not exist, a <CODE>NULL</CODE> pointer will
+ be returned.</P>
+<H3><A NAME="3_3_3">Loading a PPD File</A></H3>
+<P>The <CODE>ppdOpenFile()</CODE> function &quot;opens&quot; a PPD file and loads
+ it into memory:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile(&quot;<I>filename</I>&quot;);
+</PRE>
+</UL>
+<P>The <CODE>filename</CODE> string is the name of the file to load,
+ such as the value returned by the <CODE>cupsGetPPD()</CODE> function.</P>
+<P>The return value is a pointer to a structure describing the contents
+ of the PPD file or NULL if the PPD file could not be read.</P>
+<H3><A NAME="3_3_4">Freeing PPD File Information</A></H3>
+<P>Once you are done using a PPD file, call the <CODE>ppdClose()</CODE>
+ function to free all memory that has been used:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+...
+
+ppdClose(ppd);
+</PRE>
+</UL>
+<H3><A NAME="3_3_5">The PPD File Structure</A></H3>
+<P>Each PPD file contains a number of capability attributes, printer
+ options, and conflict definitions. The page size options also include
+ the physical margins for the printer and the minimum and maximum sizes
+ for the printer. All of this information is stored in the <CODE>
+ppd_file_t</CODE> structure.</P>
+<H4>Capabilities</H4>
+<P>Each PPD file contains a number of informational attributes that
+ describe the capabilities of the printer. These are provided in the <CODE>
+ppd_file_t</CODE> structure in the following members:
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD><CODE>accurate_screens</CODE></TD><TD><CODE>int</CODE></TD><TD>1
+ = supports accurate screens</TD></TR>
+<TR><TD><CODE>color_device</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ color device</TD></TR>
+<TR><TD><CODE>colorspace</CODE></TD><TD><CODE>ppd_cs_t</CODE></TD><TD>
+Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY, PPD_CS_RGB,
+ PPD_CS_RGBK, PPD_CS_N</TD></TR>
+<TR><TD><CODE>contone_only</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ printer is continuous tone only</TD></TR>
+<TR><TD><CODE>num_emulations
+<BR> emulations</CODE></TD><TD><CODE>int
+<BR> ppd_emul_t *</CODE></TD><TD>Emulations supported by the printer</TD>
+</TR>
+<TR><TD><CODE>flip_duplex</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ need to flip odd pages when duplexing</TD></TR>
+<TR><TD><CODE>num_fonts
+<BR> fonts</CODE></TD><TD><CODE>int
+<BR> char **</CODE></TD><TD>The fonts available on the printer.</TD></TR>
+<TR><TD><CODE>jcl_begin
+<BR> jcl_ps
+<BR> jcl_end</CODE></TD><TD><CODE>char *</CODE></TD><TD>Job Control
+ Language commands for PostScript output</TD></TR>
+<TR><TD><CODE>landscape</CODE></TD><TD><CODE>int</CODE></TD><TD>
+Landscape orientation, -90 or 90 degrees</TD></TR>
+<TR><TD><CODE>lang_encoding</CODE></TD><TD><CODE>char *</CODE></TD><TD>
+The character used for the option strings</TD></TR>
+<TR><TD><CODE>lang_version</CODE></TD><TD><CODE>char *</CODE></TD><TD>
+The language used for the options strings (English, French, etc.)</TD></TR>
+<TR><TD><CODE>language_level</CODE></TD><TD><CODE>int</CODE></TD><TD>
+PostScript language level, 1 to 3</TD></TR>
+<TR><TD><CODE>manual_copies</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ Copies are done manually</TD></TR>
+<TR><TD><CODE>model_number</CODE></TD><TD><CODE>int</CODE></TD><TD>
+Driver-specific model number.</TD></TR>
+<TR><TD><CODE>patches</CODE></TD><TD><CODE>char *</CODE></TD><TD>Patch
+ commands to send to the printer</TD></TR>
+<TR><TD><CODE>manufacturer</CODE></TD><TD><CODE>char *</CODE></TD><TD>
+The Manufacturer attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>modelname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ ModelName attribute from the PPD file</TD></TR>
+<TR><TD><CODE>nickname</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ NickName attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>product</CODE></TD><TD><CODE>char *</CODE></TD><TD>The
+ Product attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>shortnickname</CODE></TD><TD><CODE>char *</CODE></TD><TD>
+The ShortNickName attribute from the PPD file, if any</TD></TR>
+<TR><TD><CODE>throughput</CODE></TD><TD><CODE>int</CODE></TD><TD>Number
+ of pages per minute</TD></TR>
+<TR><TD><CODE>ttrasterizer</CODE></TD><TD><CODE>char *</CODE></TD><TD>
+The TruType font rasterizer (Type42)</TD></TR>
+<TR><TD><CODE>variable_sizes</CODE></TD><TD><CODE>int</CODE></TD><TD>1 =
+ supports variable sizes</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H4>Options and Groups</H4>
+<P>PPD files support multiple options, which are stored in <CODE>
+ppd_option_t</CODE> and <CODE>ppd_choice_t</CODE> structures by the PPD
+ functions.</P>
+<P>Each option in turn is associated with a group stored in the <CODE>
+ppd_group_t</CODE> structure. Groups can be specified in the PPD file;
+ if an option is not associated with a group then it is put in a
+ &quot;General&quot; or &quot;Extra&quot; group depending on the option.</P>
+<P>Groups can also have sub-groups; CUPS currently limits the depth of
+ sub-groups to 1 level to reduce programming complexity.</P>
+<H4>Conflicts</H4>
+<P>PPD files support specification of conflict conditions between
+ different options. Conflicts are stored in <CODE>ppd_conflict_t</CODE>
+ structures which specify the options that conflict with each other.</P>
+<H4>Page Sizes</H4>
+<P>PPD files specify all of the available pages sizes and the physical
+ margins associated with them. These sizes are stored in <CODE>
+ppd_size_t</CODE> structures and are available in the <CODE>num_sizes</CODE>
+ and <CODE>sizes</CODE> members of the <CODE>ppd_file_t</CODE>
+ structure. You can lookup a particular page size with the <CODE>
+ppdPageWidth()</CODE>, <CODE>ppdPageLength()</CODE>, and <CODE>
+ppdPageSize()</CODE> functions:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+float width;
+float length;
+
+...
+
+size = ppdPageSize(ppd, &quot;<I>size</I>&quot;);
+width = ppdPageWidth(ppd, &quot;<I>size</I>&quot;);
+length = ppdPageLength(ppd, &quot;<I>size</I>&quot;);
+</PRE>
+</UL>
+<P>The <CODE>size</CODE> string is the named page size option. The width
+ and length are in points; there are 72 points per inch. The <CODE>
+ppd_size_t</CODE> structure contains the width, length, and margin
+ information:</P>
+<UL>
+<PRE>
+typedef struct /**** Page Sizes ****/
+{
+ int marked; /* Page size selected? */
+ char name[41]; /* Media size option */
+ float width, /* Width of media in points */
+ length, /* Length of media in points */
+ left, /* Left printable margin in points */
+ bottom, /* Bottom printable margin in points */
+ right, /* Right printable margin in points */
+ top; /* Top printable margin in points */
+} ppd_size_t;
+</PRE>
+</UL>
+<H4>Custom Page Sizes</H4>
+<P>Besides the standard page sizes listed in a PPD file, some printers
+ support variable or custom page sizes. If <CODE>variables_sizes</CODE>
+ is non-zero, the <CODE>custom_min</CODE>, <CODE>custom_max</CODE>, and <CODE>
+custom_margins</CODE> members of the <CODE>ppd_file_t</CODE> structure
+ define the limits of the variable sizes.</P>
+<P>To get the resulting media size, use a page size string of <CODE>
+Custom.<I>width</I>x<I>length</I></CODE>, where <CODE>width</CODE> and <CODE>
+length</CODE> are integer values in points:</P>
+<UL>
+<PRE>
+Custom.612x792 [8.5 inches wide, 11 inches long]
+Custom.1224x792 [17 inches wide, 11 inches long]
+</PRE>
+</UL>
+<H3><A NAME="3_3_6">Marking Options</A></H3>
+<P>Before marking any user-defined options, call the <CODE>
+ppdMarkDefaults()</CODE> function to mark the default options from the
+ PPD file:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+...
+
+ppdMarkDefaults(ppd);
+</PRE>
+</UL>
+<P>Then call the <CODE>ppdMarkOption()</CODE> function to mark
+ individual options:</P>
+<UL>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int conflicts;
+
+...
+
+conflicts = ppdMarkOption(ppd, &quot;<I>name</I>&quot;, &quot;<I>value</I>&quot;);
+</PRE>
+</UL>
+<P>The <CODE>name</CODE> and <CODE>value</CODE> strings choose a
+ particular option and choice, respectively. The return value is 0 if
+ there are not conflicts created by the selection.</P>
+<P>CUPS also provides a convenience function for marking all options in
+ the <CODE>cups_option_t</CODE> structure:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int num_options;
+cups_option_t *options;
+int conflicts;
+
+...
+
+conflicts = cupsMarkOptions(ppd, num_options, options);
+</PRE>
+</UL>
+<P>The <CODE>cupsMarkOptions()</CODE> function also handles mapping the
+ IPP job template attributes to PPD options. The return value is the
+ number of conflicts present.</P>
+<H3><A NAME="3_3_7">Checking for Conflicts</A></H3>
+<P>The <CODE>ppdMarkOption()</CODE> and <CODE>cupsMarkOptions()</CODE>
+ functions return the number of conflicts with the currently marked
+ options.</P>
+<P>Call the <CODE>ppdConflicts()</CODE> function to get the number of
+ conflicts after you have marked all of the options:</P>
+<UL>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int conflicts;
+
+...
+
+conflicts = ppdConflicts(ppd);
+</PRE>
+</UL>
+<P>The return value is the number of conflicting options, or 0 if there
+ are no conflicts.</P>
+<H1 ALIGN="RIGHT"><A NAME="WRITING_FILTERS">3 - Writing Filters</A></H1>
+<P>This chapter describes how to write a file filter for CUPS.</P>
+<H2><A NAME="4_1">Overview</A></H2>
+<P>File filters are programs that convert from one or more MIME types to
+ another type. Filters use a common command-line and environment
+ interface that allows them to be joined as needed to print files to any
+ type of printer.</P>
+<H3><A NAME="4_1_1">Security Considerations</A></H3>
+<P>Filters are normally run as a non-priviledged user, so the major
+ security consideration is resource utilization - filters should not
+ depend on unlimited amounts of memory and disk space.</P>
+<H3><A NAME="4_1_2">Users and Groups</A></H3>
+<P>The default CUPS configuration runs filters as user &quot;lp&quot; and group
+ &quot;other&quot;.</P>
+<H3><A NAME="4_1_3">Temporary Files</A></H3>
+<P>Temporary files should be created in the directory specified by the
+ &quot;TMPDIR&quot; environment variable. The <A HREF="#cupsTempFile"><CODE>
+cupsTempFile()</CODE></A> function can be used to safely choose
+ temporary files in this directory.</P>
+<H3><A NAME="4_1_4">Sending Messages to the User</A></H3>
+<P>The CUPS scheduler collects messages sent to the standard error file
+ by the filter. These messages are relayed to the user based upon the
+ scheduler <CODE>LogLevel</CODE> directive.</P>
+<P>The type of message is determined by an initial prefix sent on each
+ line:</P>
+<UL>
+<LI><CODE>DEBUG:</CODE> - a debug message</LI>
+<LI><CODE>INFO:</CODE> - an informational message</LI>
+<LI><CODE>WARNING:</CODE> - a warning message</LI>
+<LI><CODE>ERROR:</CODE> - an error message</LI>
+<LI><CODE>PAGE:</CODE> - a page accounting message</LI>
+</UL>
+<P>If the line of text does not begin with any of the above prefixes, it
+ is treated as a debug message. Text following the prefix is copied to
+ the <CODE>printer-state-message</CODE> attribute for the printer, and
+ also added to the<VAR> error_log</VAR> unless it is an informational or
+ page accounting message.</P>
+<H3><A NAME="4_1_5">Page Accounting</A></H3>
+<P>Page accounting messages are used to inform the server when one or
+ more pages are printed. Each line has the form:</P>
+<UL>
+<PRE>
+PAGE: page-number copy-count
+</PRE>
+</UL>
+<P>The<I> page-number</I> field is the current page number, starting at
+ 1. The<I> copy-count</I> field specifies the number of copies of that
+ page that was produced.</P>
+<P>Page account messages are added to the<VAR> page_log</VAR> file and
+ cause the <CODE>job-sheets-completed</CODE> attribute to be updated for
+ the job.</P>
+<H3><A NAME="4_1_6">Command-Line Arguments</A></H3>
+<P>Every filter accepts exactly 6 or 7 command-line arguments:</P>
+<UL>
+<PRE>
+printer job user title copies options [filename]
+</PRE>
+<LI><CODE>printer</CODE> - The name of the printer queue (normally this
+ is the name of the program being run)</LI>
+<LI><CODE>job</CODE> - The numeric job ID for the job being printed</LI>
+<LI><CODE>user</CODE> - The string from the <CODE>originating-user-name</CODE>
+ attribute</LI>
+<LI><CODE>title</CODE> - The string from the <CODE>job-name</CODE>
+ attribute</LI>
+<LI><CODE>copies</CODE> - The numeric value from the <CODE>number-copies</CODE>
+ attribute</LI>
+<LI><CODE>options</CODE> - String representations of the job template
+ attributes, separated by spaces. Boolean attributes are provided as
+ &quot;name&quot; for true values and &quot;noname&quot; for false values. All other
+ attributes are provided as &quot;name=value&quot; for single-valued attributes
+ and &quot;name=value1,value2,...,valueN&quot; for set attributes</LI>
+<LI><CODE>filename</CODE> - The request file</LI>
+</UL>
+<P>The<I> filename</I> argument is only provided to the first filter in
+ the chain; all filters<B> must</B> be prepared to read the print file
+ from the standard input if the<I> filename</I> argument is omitted.</P>
+<H3><A NAME="4_1_7">Copy Generation</A></H3>
+<P>The<I> copies</I> argument specifies the number of copies to produce
+ of the input file. In general, you should only generate copies if the<I>
+ filename</I> argument is supplied. The only exception to this are
+ filters that produce device-independent PostScript output (without any
+ printer commands from the printer's PPD file), since the PostScript
+ filter <CODE>pstops</CODE> is responsible for copy generation.</P>
+<H3><A NAME="4_1_8">Environment Variables</A></H3>
+<P>Every filter receives a fixed set of environment variables that can
+ be used by the filter:</P>
+<UL>
+<LI><CODE>CHARSET</CODE> - The character set used by the client for this
+ print file</LI>
+<LI><CODE>CONTENT_TYPE</CODE> - The original document type, such as
+ &quot;application/postscript&quot;</LI>
+<LI><CODE>CUPS_DATADIR</CODE> - The location of CUPS data files</LI>
+<LI><CODE>CUPS_SERVERROOT</CODE> - The location of CUPS configuration
+ files</LI>
+<LI><CODE>DEVICE_URI</CODE> - The output device URI</LI>
+<LI><CODE>LANG</CODE> - The language used by the client for this print
+ file</LI>
+<LI><CODE>PATH</CODE> - The execution path exported to the filter</LI>
+<LI><CODE>PPD</CODE> - The full filename of the printer's PPD file</LI>
+<LI><CODE>PRINTER</CODE> - The name of the printer queue</LI>
+<LI><CODE>RIP_CACHE</CODE> - The maximum amount of memory each filter
+ should use</LI>
+<LI><CODE>SOFTWARE</CODE> - The name of the CUPS software, typically
+ &quot;CUPS/1.1&quot;</LI>
+<LI><CODE>TZ</CODE> - The local timezone</LI>
+<LI><CODE>USER</CODE> - The name of the current user</LI>
+</UL>
+<H2><A NAME="4_2">Dissecting the HP-GL/2 Filter</A></H2>
+<P>The HP-GL/2 filter (<CODE>hpgltops</CODE>) provided with CUPS is a
+ complex program that converts HP-GL/2 files into device-independent
+ PostScript output. Since it produces device-independent PostScript
+ output, it does not need to handle copy generation or writing printer
+ options from the printer's PPD file.</P>
+<H3><A NAME="4_2_1">Initializing the Filter</A></H3>
+<P>The first task of any filter is to ensure that the correct number of
+ command-line arguments are present:</P>
+<UL>
+<PRE>
+if (argc &lt; 6 || argc &gt; 7)
+{
+ fputs(&quot;ERROR: hpgltops job-id user title copies options [file]\n&quot;, stderr);
+ return (1);
+}
+</PRE>
+</UL>
+<P>After this you open the print file or read from the standard input as
+ needed:</P>
+<UL>
+<PRE>
+FILE *fp;
+
+/*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+if (argc == 6)
+ fp = stdin;
+else
+{
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = fopen(argv[6], &quot;rb&quot;)) == NULL)
+ {
+ perror(&quot;ERROR: unable to open print file - &quot;);
+ return (1);
+ }
+}
+</PRE>
+</UL>
+<P>Once the print file has been opened, options can be processed using
+ the <A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A> and
+ <A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A> functions:</P>
+<UL>
+<PRE>
+int num_options;
+cups_option_t *options;
+const char *val;
+
+/*
+ * Process command-line options and write the prolog...
+ */
+
+options = NULL;
+num_options = cupsParseOptions(argv[5], 0, &amp;options);
+
+if ((val = cupsGetOption(&quot;blackplot&quot;, num_options, options)) != NULL)
+ shading = 0;
+
+if ((val = cupsGetOption(&quot;fitplot&quot;, num_options, options)) != NULL)
+ FitPlot = 1;
+
+if ((val = cupsGetOption(&quot;penwidth&quot;, num_options, options)) != NULL)
+ PenWidth = (float)atoi(val) * 0.001f;
+</PRE>
+</UL>
+<P>After the options have been processed, the filter writes PostScript
+ code to the standard output based on the print file, closes the print
+ file (as needed), and returns 0 to the scheduler.</P>
+<H2><A NAME="4_3">PostScript Output</A></H2>
+<P>Filters that produce PostScript output must generate output
+ conforming to the Adobe Document Structuring Conventions, 3.0. In
+ general this means the beginning of each file must begin with:</P>
+<UL>
+<PRE>
+%!PS-Adobe-3.0
+%%BoundingBox: left bottom right top
+%%Pages: (atend)
+%%EndComments
+</PRE>
+</UL>
+<P>The<I> left</I>,<I> bottom</I>,<I> right</I>, and<I> top</I> values
+ are integers in points from the lower-lefthand corner of the page.</P>
+<P>Pages must be surrounded by:</P>
+<UL>
+<PRE>
+%%Page: number number
+gsave
+...
+grestore
+showpage
+</PRE>
+</UL>
+<P>And the end of each file must contain:</P>
+<UL>
+<PRE>
+%%Trailer
+%%Pages: number-pages
+%%EOF
+</PRE>
+</UL>
+<P>These comments allow the PostScript filter to correctly perform page
+ accounting, copy generation, N-up printing, and so forth.</P>
+<H1 ALIGN="RIGHT"><A NAME="WRITING_DRIVERS">4 - Writing Printer Drivers</A>
+</H1>
+<P>This chapter discusses how to write a printer driver, which is a
+ special filter program that converts CUPS raster data into the
+ appropriate commands and data required for a printer.</P>
+<H2><A NAME="5_1">Overview</A></H2>
+<P>Raster printers utilitize PPD files that specify one or more
+ device-specific filters that handle converting print files for the
+ printer. The simplest raster printer drivers provide a single filter
+ that converts CUPS raster data to the printer's native format.</P>
+<H3><A NAME="5_1_1">CUPS Raster Data</A></H3>
+<P>CUPS raster data (<CODE>application/vnd.cups-raster</CODE>) consists
+ of a stream of raster page descriptions produced by one of the RIP
+ filters, such as <CODE>pstoraster</CODE> or <CODE>imagetoraster</CODE>.</P>
+<P>Each page of data begins with a page dictionary structure called <A HREF="#cups_raster_header_t">
+<CODE>cups_raster_header_t</CODE></A>. This structure contains the
+ colorspace, bits per color, media size, media type, hardware
+ resolution, and so forth.</P>
+<P>After the page dictionary comes the page data which is a
+ full-resolution, uncompressed bitmap representing the page in the
+ printer's output colorspace.</P>
+<H3><A NAME="5_1_2">Page Accounting</A></H3>
+<P>Printer drivers must handle all page accounting. This means they must
+ send &quot;PAGE:&quot; messages to the standard error file for each page (and in
+ many cases, copy) sent to the printer.</P>
+<H3><A NAME="5_1_3">Color Management</A></H3>
+<P>Printer drivers can implement their color management via the <CODE>
+cupsColorProfile</CODE> attributes in the PPD file or internally in the
+ driver from a device-independent colorspace. In general, color
+ management performed by the RIP filters is more efficient than that
+ performed inside printer drivers.</P>
+<P>For example, the <CODE>pstoraster</CODE> filter often only has to
+ perform a color conversion once each time the color is used for
+ multiple output pixels, while the raster filter must convert every
+ pixel on the page.</P>
+<H3><A NAME="5_1_4">Device and Bitmap Variables</A></H3>
+<P>Besides the standard PostScript page device dictionary variables
+ defined in the Adobe PostScript Level 3 reference manual, the CUPS
+ filters support additional variables that are passed in the page device
+ dictionary header for the page and in some cases control the type of
+ raster data that is generated:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Variable</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>cupsWidth</TD><TD>read-only integer</TD><TD>Width of bitmap in
+ pixels</TD></TR>
+<TR><TD>cupsHeight</TD><TD>read-only integer</TD><TD>Height of bitmap in
+ pixels</TD></TR>
+<TR><TD>cupsMediaType</TD><TD>read-write integer</TD><TD>Device-specific
+ media type code</TD></TR>
+<TR><TD>cupsBitsPerColor</TD><TD>read-write integer</TD><TD>Number of
+ bits per color; 1, 2, 4, and 8 are currently supported</TD></TR>
+<TR><TD>cupsBitsPerPixel</TD><TD>read-only integer</TD><TD>Number of
+ bits per pixel; 1 to 32</TD></TR>
+<TR><TD>cupsBytesPerLine</TD><TD>read-only integer</TD><TD>Number of
+ bytes per line of raster graphics</TD></TR>
+<TR><TD>cupsColorOrder</TD><TD>read-write enum</TD><TD>The order of
+ color values in the bitmap:
+<UL>
+<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK</LI>
+<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK</LI>
+<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...</LI>
+</UL>
+</TD></TR>
+<TR><TD>cupsColorSpace</TD><TD>read-write enum</TD><TD>The colorspace of
+ the bitmap:
+<UL>
+<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)</LI>
+<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue</LI>
+<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha</LI>
+<LI><CODE>CUPS_CSPACE_K</CODE> - Black</LI>
+<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan</LI>
+<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black</LI>
+<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta</LI>
+<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, metallic grey (silver)</LI>
+<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white
+ pigment)</LI>
+<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)</LI>
+<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)</LI>
+</UL>
+</TD></TR>
+<TR><TD>cupsCompression</TD><TD>read-write integer</TD><TD>
+Device-specific compression type code</TD></TR>
+<TR><TD>cupsRowCount</TD><TD>read-write integer</TD><TD>Device-specific
+ row count value</TD></TR>
+<TR><TD>cupsRowFeed</TD><TD>read-write integer</TD><TD>Device-specific
+ row feed value</TD></TR>
+<TR><TD>cupsRowStep</TD><TD>read-write integer</TD><TD>Device-specific
+ row step value</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm and more than 1 bit
+ per color are transmitted to the raster driver in KCMY colorspace; the
+ driver is responsible for producing the correct separation of normal
+ and light cyan and magenta inks.</P>
+<H2><A NAME="5_2">Dissecting the HP-PCL Driver</A></H2>
+<P>The HP-PCL driver provided with CUPS (<CODE>rastertohp</CODE>)
+ converts bitmap data from the raster filters into HP-PCL commands for
+ most PCL-compatible printers. The actual format of the raster data is
+ controlled by the PPD file being used -<VAR> deskjet.ppd</VAR> or<VAR>
+ laserjet.ppd</VAR>.</P>
+<H3><A NAME="5_2_1">PPD Files</A></H3>
+<P>PPD files play an important part of all raster printer drivers.
+ Options defined in the PPD file contain PostScript commands that
+ control the raster data that is sent to the printer driver.</P>
+<P>A typical CUPS printer driver will include <CODE>ColorModel</CODE>, <CODE>
+InputSlot</CODE>, <CODE>PageSize</CODE>, <CODE>PageRegion</CODE>, and <CODE>
+Resolution</CODE> options. Each option is shown using the standard PPD
+ format:</P>
+<UL>
+<PRE>
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: &quot;&lt;&lt;
+/PageSize [612 792]
+/ImagingBBox null
+&gt;&gt; setpagedevice&quot;
+*End
+*PageSize Legal/US Legal: &quot;&lt;&lt;
+/PageSize [612 1008]
+/ImagingBBox null
+&gt;&gt; setpagedevice&quot;
+*End
+*PageSize A4/A4: &quot;&lt;&lt;
+/PageSize [595 842]
+/ImagingBBox null
+&gt;&gt; setpagedevice&quot;
+*End
+*CloseUI: *PageSize
+</PRE>
+</UL>
+<P>The <CODE>OpenUI</CODE> keyword specifies the new option. The first
+ name is the option with an asterisk (*) in front of it. The first name
+ is usually followed by a slash (/) and a human-readable version of the
+ option name.</P>
+<P>Every option<B> must</B> have a default value, specified using the <CODE>
+Default<I>Option</I></CODE> keyword.</P>
+<P>Each option begins with the option name followed by the computer and
+ human-readable values. The PostScript commands follow these inside
+ double quotes. PostScript commands can be provided on a single line:</P>
+<UL>
+<PRE>
+*PageSize A4/A4: &quot;&lt;&lt;/PageSize[595 842]/ImagingBBox null&gt;&gt; setpagedevice&quot;
+</PRE>
+</UL>
+<P>or broken down on separate lines using the <CODE>End</CODE> keyword
+ to terminate them:</P>
+<UL>
+<PRE>
+*PageSize A4/A4: &quot;&lt;&lt;
+/PageSize [595 842]
+/ImagingBBox null
+&gt;&gt; setpagedevice&quot;
+*End
+</PRE>
+</UL>
+<P>The choice of the two formats is usually esthetic. However, each line
+ in a PPD file must not exceed 255 characters, so if your PostScript
+ commands are long you may need to break them up on separate lines.</P>
+<H3><A NAME="5_2_2">Reading Raster Data</A></H3>
+<P>As with any filter, your printer driver should handle raster data
+ from a filename specified on the command-line or from the standard
+ input. The <A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>
+ function opens a raster stream for printing:</P>
+<UL>
+<PRE>
+int fd; /* File descriptor */
+cups_raster_t *ras; /* Raster stream for printing */
+
+
+/*
+ * Check for valid arguments...
+ */
+
+if (argc &lt; 6 || argc &gt; 7)
+{
+ /*
+ * We don't have the correct number of arguments; write an error message
+ * and return.
+ */
+
+ fputs(&quot;ERROR: rastertopcl job-id user title copies options [file]\n&quot;, stderr);
+ return (1);
+}
+
+/*
+ * Open the page stream...
+ */
+
+if (argc == 7)
+{
+ if ((fd = open(argv[6], O_RDONLY)) == -1)
+ {
+ perror(&quot;ERROR: Unable to open raster file - &quot;);
+ sleep(1);
+ return (1);
+ }
+}
+else
+ fd = 0;
+
+ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
+</PRE>
+</UL>
+<P>Once you have opened the raster stream you just need to read each
+ page and print it:</P>
+<UL>
+<PRE>
+cups_raster_header_t header;
+int y;
+unsigned char data[8192];
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ... initialize the printer ...
+ for (y = header.cupsHeight; y &gt; 0; y ++)
+ {
+ cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
+ ... send raster line to printer ...
+ }
+}
+</PRE>
+</UL>
+<P>After you have processed all pages, close the raster stream and
+ return:</P>
+<UL>
+<PRE>
+cupsRasterClose(ras);
+
+return (0);
+</PRE>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="WRITING_BACKENDS">5 - Writing Backends</A></H1>
+<P>This chapter describes how to write a backend for CUPS. Backends
+ communicate directly with printers and allow printer drivers and
+ filters to send data using any type of connection transparently.</P>
+<H2><A NAME="6_1">Overview</A></H2>
+<P>Backends are special filters that communicate with printers directly.
+ They are treated slightly differently than filters, however, and have
+ some unique requirements.</P>
+<H3><A NAME="6_1_1">Security Considerations</A></H3>
+<P>Backends are run as the root user, so special care must be taken to
+ avoid potential security violations. In particular, remember that a
+ backend will be able to manipulate disk files, devices, and other
+ resources that potentially could damage a system or printer.</P>
+<H3><A NAME="6_1_2">Command-Line Arguments</A></H3>
+<P>Besides the standard filter arguments, backends are also run with no
+ arguments to get a list of available devices. This discovery process is
+ described later in this chapter.</P>
+<H3><A NAME="6_1_3">Copy Generation</A></H3>
+<P>Like filters, backends should send multiple copies of the print file
+ only if a filename is supplied on the command-line. Otherwise the
+ backend should assume that the upstream filter has already added the
+ necessary commands or data to produce the multiple copies.</P>
+<H3><A NAME="6_1_4">Page Accounting</A></H3>
+<P>Backend filters generally do not do page accounting, however they
+ should at a minimum produce a single page message for each copy that is
+ produced when a filename is present on the command-line. This is
+ because the user selected &quot;raw&quot; printing and no other accounting
+ information is possible.</P>
+<H3><A NAME="6_1_5">Exclusive Access</A></H3>
+<P>Backends that talk to local character or block devices should open
+ the device file in exclusive mode (<CODE>O_EXCL</CODE>) to cooperate
+ with other printers defined for the same device.</P>
+<H3><A NAME="6_1_6">Retries</A></H3>
+<P>All backends<B> must</B> retry connections to the device. This
+ includes backends that talk to local character or block devices, as the
+ user may define more than one printer queue pointing at the same
+ physical device.</P>
+<P>To prevent excess CPU utilitization, the backend should go to sleep
+ for an amount of time between retries; the CUPS-supplied backends retry
+ once every 30 seconds.</P>
+<H2><A NAME="6_2">Dissecting the Serial Port Backend</A></H2>
+<P>The serial port backend provides support for serial printers. Since
+ it does everything a good backend needs to do, it provides an excellent
+ example of what to do.</P>
+<H3><A NAME="6_2_1">Supporting Device Discovery</A></H3>
+<P>As previously noted, backends are special filter programs that talk
+ to printer devices. Another task a backend must perform is to list the
+ available devices it supports. The backend lists the available devices
+ when no additioanl arguments are supplied on the command-line (i.e.
+ just the command name...)</P>
+<P>The serial backend lists devices by looking at serial port files in
+ the<VAR> /dev</VAR> directory, by consulting a hardware inventory
+ (IRIX), and in some cases by trying to open the ports to see if they
+ actually exist.</P>
+<P>Once it finds a serial port it writes a single line for each port to
+ the standard output file. Each line looks like this:</P>
+<UL>
+<PRE>
+serial serial:/dev/ttyS0?baud=115200 &quot;Unknown&quot; &quot;Serial Port 1&quot;
+</PRE>
+</UL>
+<P>The first word &quot;serial&quot; is the<I> device class</I>; this identifies
+ the class of device which can be used to categorize it in user
+ interfaces. CUPS currently recognizes the following classes:</P>
+<UL>
+<LI>&quot;file&quot; - a disk file.</LI>
+<LI>&quot;direct&quot; - a parallel or fixed-rate serial data port, currently used
+ for Centronics, IEEE-1284, and USB printer ports.</LI>
+<LI>&quot;serial&quot; - a variable-rate serial port.</LI>
+<LI>&quot;network&quot; - a network connection, typically via AppSocket, HTTP,
+ IPP, LPD, or SMB/CIFS protocols.</LI>
+</UL>
+<P>After the device class is the<I> device URI</I>, in this case
+ &quot;serial:/dev/ttyS0?baud=115200&quot;. This is the URI that should be used by
+ the user to select this port. For serial ports, the &quot;baud=115200&quot;
+ specifies the maximum baud rate supported by the port - the actual
+ value will vary based on the speed the user selects for the printer.</P>
+<P>The last two strings are the model and description for the port. The
+ &quot;Unknown&quot; string means that the printer model is unknown - some devices
+ are able to provide a make and model such as &quot;HP DeskJet&quot; that allows
+ users and software to choose an appropriate printer driver more easily.
+ Both the model and description must be enclosed inside double quotes.</P>
+<H3><A NAME="6_2_2">Opening the Serial Port</A></H3>
+<P>As noted previously, all backends should open device files in
+ exclusive mode, and retry as needed until the port is available. The
+ serial port does this using a <CODE>do-while</CODE> loop:</P>
+<UL>
+<PRE>
+do
+{
+ if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
+ {
+ if (errno == EBUSY)
+ {
+ fputs(&quot;INFO: Serial port busy; will retry in 30 seconds...\n&quot;, stderr);
+ sleep(30);
+ }
+ else
+ {
+ perror(&quot;ERROR: Unable to open serial port device file&quot;);
+ return (1);
+ }
+ }
+}
+while (fd &lt; 0);
+</PRE>
+</UL>
+<P>If the port is busy or in use by another process, the backend will go
+ to sleep for 30 seconds and try again. If another error is detected a
+ message is sent to the user and the backend aborts the print job until
+ the problem can be corrected.</P>
+<H3><A NAME="6_2_3">Writing Data to the Port</A></H3>
+<P>Network and character devices pose an interesting problem when
+ writing data to the port - they may not be able to write all of the
+ bytes in your buffer before returning. To work around this problem you
+ must loop until all bytes have been written:</P>
+<UL>
+<PRE>
+while (nbytes &gt; 0)
+{
+ if ((wbytes = write(fd, bufptr, nbytes)) &lt; 0)
+ if (errno == ENOTTY)
+ wbytes = write(fd, bufptr, nbytes);
+
+ if (wbytes &lt; 0)
+ {
+ perror(&quot;ERROR: Unable to send print file to printer&quot;);
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+}
+</PRE>
+</UL>
+<P>The check for the <CODE>ENOTTY</CODE> error is needed on some
+ platforms to clear an error from a previous <CODE>ioctl()</CODE> call.</P>
+<H3><A NAME="6_2_4">Finishing Up</A></H3>
+<P>Once you have sent the print file, return 0 if the file printed
+ successfully or 1 if it did not. This will allow the scheduler to stop
+ the print job if there is a device error, preserving the print job for
+ later printing once the problem has been corrected.</P>
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
+<H2 ALIGN="CENTER"><A NAME="7_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P ALIGN="CENTER">Copyright 1997-2004 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3142 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
+<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<H3><A NAME="7_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2, with exceptions for
+ Apple operating systems and the OpenSSL toolkit. A copy of the
+ exceptions and licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the &quot;cups&quot; include
+ directory and library files in the binary distributions. The GNU GPL
+ applies to the remainder of the CUPS distribution, including the
+ &quot;pdftops&quot; filter which is based upon Xpdf and the CUPS imaging library.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate. The only exceptions to this are the portions of
+ the CUPS software covered by the Apple operating system license
+ exceptions outlined later in this license agreement.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="7_1_2">License Exceptions</A></H3>
+<P>In addition, as the copyright holder of CUPS, Easy Software Products
+ grants the following special exceptions:</P>
+<OL>
+<LI><B>Apple Operating System Development License Exception</B>;
+<OL TYPE="a">
+<LI>Software that is developed by any person or entity for an Apple
+ Operating System (&quot;Apple OS-Developed Software&quot;), including but not
+ limited to Apple and third party printer drivers, filters, and backends
+ for an Apple Operating System, that is linked to the CUPS imaging
+ library or based on any sample filters or backends provided with CUPS
+ shall not be considered to be a derivative work or collective work
+ based on the CUPS program and is exempt from the mandatory source code
+ release clauses of the GNU GPL. You may therefore distribute linked
+ combinations of the CUPS imaging library with Apple OS-Developed
+ Software without releasing the source code of the Apple OS-Developed
+ Software. You may also use sample filters and backends provided with
+ CUPS to develop Apple OS-Developed Software without releasing the
+ source code of the Apple OS-Developed Software.</LI>
+<LI>An Apple Operating System means any operating system software
+ developed and/or marketed by Apple Computer, Inc., including but not
+ limited to all existing releases and versions of Apple's Darwin, Mac OS
+ X, and Mac OS X Server products and all follow-on releases and future
+ versions thereof.</LI>
+<LI>This exception is only available for Apple OS-Developed Software and
+ does not apply to software that is distributed for use on other
+ operating systems.</LI>
+<LI>All CUPS software that falls under this license exception have the
+ following text at the top of each source file:<BLOCKQUOTE>This file is
+ subject to the Apple OS-Developed Software exception.</BLOCKQUOTE></LI>
+</OL>
+</LI>
+<LI><B>OpenSSL Toolkit License Exception</B>;
+<OL TYPE="a">
+<LI>Easy Software Products explicitly allows the compilation and
+ distribution of the CUPS software with the OpenSSL Toolkit.</LI>
+</OL>
+</LI>
+</OL>
+<P>No developer is required to provide these exceptions in a derived
+ work.</P>
+<H3><A NAME="7_1_3">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. You may use these names and logos in any
+ direct port or binary distribution of CUPS. Please contact Easy
+ Software Products for written permission to use them in derivative
+ products. Our intention is to protect the value of these trademarks and
+ ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="7_1_4">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pdftops&quot; filter that is
+ based on the Xpdf software. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Derek B. Noonburg
+<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
+<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
+http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="7_1_5">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/">http://www.easysw.com/</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="7_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<H3><A NAME="7_2_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+</LI>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+</LI>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+</LI>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+</LI>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+</LI>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+</LI>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="7_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H3><A NAME="7_3_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.
+<P></P>
+</LI>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.
+<P></P>
+</LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.
+<P></P>
+</LI>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)
+<P></P>
+</LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.
+<P></P>
+</LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.
+<P></P>
+</LI>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.
+<P></P>
+</LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+<H1 ALIGN="RIGHT"><A NAME="CONSTANTS">B - Constants</A></H1>
+<P>This appendix lists all of the constants that are defined by the CUPS
+ API.</P>
+<H2><A NAME="8_1">CUPS Constants</A></H2>
+<H3><A NAME="8_1_1">Version Number</A></H3>
+<P>The <CODE>CUPS_VERSION</CODE> constant is a floating-point number
+ representing the API version number. The current version number is
+ 1.0100 which represents CUPS version 1.1.0.</P>
+<H3><A NAME="8_1_2">Printer Capabilities</A></H3>
+<P>The <CODE>CUPS_PRINTER</CODE> constants represent capability bits for
+ printers and classes:</P>
+<UL>
+<LI><CODE>CUPS_PRINTER_LOCAL</CODE> - Is a local printer or class.</LI>
+<LI><CODE>CUPS_PRINTER_REMOTE</CODE> - Is a remote printer or class.</LI>
+<LI><CODE>CUPS_PRINTER_CLASS</CODE> - Is a class.</LI>
+<LI><CODE>CUPS_PRINTER_BW</CODE> - Printer prints in black and white.</LI>
+<LI><CODE>CUPS_PRINTER_COLOR</CODE> - Printer prints in color.</LI>
+<LI><CODE>CUPS_PRINTER_DUPLEX</CODE> - Printer can print double-sided.</LI>
+<LI><CODE>CUPS_PRINTER_STAPLE</CODE> - Printer can staple output.</LI>
+<LI><CODE>CUPS_PRINTER_COPIES</CODE> - Printer can produce multiple
+ copies on its own.</LI>
+<LI><CODE>CUPS_PRINTER_COLLATE</CODE> - Printer can collate copies.</LI>
+<LI><CODE>CUPS_PRINTER_PUNCH</CODE> - Printer can punch holes in output.</LI>
+<LI><CODE>CUPS_PRINTER_COVER</CODE> - Printer can put covers on output.</LI>
+<LI><CODE>CUPS_PRINTER_BIND</CODE> - Printer can bind output.</LI>
+<LI><CODE>CUPS_PRINTER_SORT</CODE> - Printer can sort output.</LI>
+<LI><CODE>CUPS_PRINTER_SMALL</CODE> - Printer can print on media up to
+ 9x14 inches.</LI>
+<LI><CODE>CUPS_PRINTER_MEDIUM</CODE> - Printer can print on media from
+ 9x14 to 18x24 inches.</LI>
+<LI><CODE>CUPS_PRINTER_LARGE</CODE> - Printer can print on media larger
+ than 18x24 inches.</LI>
+<LI><CODE>CUPS_PRINTER_VARIABLE</CODE> - Printer can print on variable
+ or custom media sizes.</LI>
+<LI><CODE>CUPS_PRINTER_IMPLICIT</CODE> - Is an implicit class.</LI>
+<LI><CODE>CUPS_PRINTER_OPTIONS</CODE> - All of the printer capability
+ and option bits.</LI>
+</UL>
+<H3><A NAME="8_1_3">Encodings</A></H3>
+<P>CUPS defines the following character set encoding constants:</P>
+<UL>
+<LI><CODE>CUPS_US_ASCII</CODE> - US ASCII character set.</LI>
+<LI><CODE>CUPS_UTF_8</CODE> - UTF-8 encoding of Unicode.</LI>
+<LI><CODE>CUPS_ISO8859_1</CODE> - ISO-8859-1 character set.</LI>
+<LI><CODE>CUPS_ISO8859_2</CODE> - ISO-8859-2 character set.</LI>
+<LI><CODE>CUPS_ISO8859_3</CODE> - ISO-8859-3 character set.</LI>
+<LI><CODE>CUPS_ISO8859_4</CODE> - ISO-8859-4 character set.</LI>
+<LI><CODE>CUPS_ISO8859_5</CODE> - ISO-8859-5 character set.</LI>
+<LI><CODE>CUPS_ISO8859_6</CODE> - ISO-8859-6 character set.</LI>
+<LI><CODE>CUPS_ISO8859_7</CODE> - ISO-8859-7 character set.</LI>
+<LI><CODE>CUPS_ISO8859_8</CODE> - ISO-8859-8 character set.</LI>
+<LI><CODE>CUPS_ISO8859_9</CODE> - ISO-8859-9 character set.</LI>
+<LI><CODE>CUPS_ISO8859_10</CODE> - ISO-8859-10 character set.</LI>
+<LI><CODE>CUPS_ISO8859_13</CODE> - ISO-8859-13 character set.</LI>
+<LI><CODE>CUPS_ISO8859_14</CODE> - ISO-8859-14 character set.</LI>
+<LI><CODE>CUPS_ISO8859_15</CODE> - ISO-8859-15 character set.</LI>
+<LI><CODE>CUPS_WINDOWS_874</CODE> - Windows code page 874.</LI>
+<LI><CODE>CUPS_WINDOWS_1250</CODE> - Windows code page 1250.</LI>
+<LI><CODE>CUPS_WINDOWS_1251</CODE> - Windows code page 1251.</LI>
+<LI><CODE>CUPS_WINDOWS_1252</CODE> - Windows code page 1252.</LI>
+<LI><CODE>CUPS_WINDOWS_1253</CODE> - Windows code page 1253.</LI>
+<LI><CODE>CUPS_WINDOWS_1254</CODE> - Windows code page 1254.</LI>
+<LI><CODE>CUPS_WINDOWS_1255</CODE> - Windows code page 1255.</LI>
+<LI><CODE>CUPS_WINDOWS_1256</CODE> - Windows code page 1256.</LI>
+<LI><CODE>CUPS_WINDOWS_1257</CODE> - Windows code page 1257.</LI>
+<LI><CODE>CUPS_WINDOWS_1258</CODE> - Windows code page 1258.</LI>
+<LI><CODE>CUPS_KOI8_R</CODE> - Russian code page koi8-r.</LI>
+<LI><CODE>CUPS_KOI8_U</CODE> - Ukrainian code page koi8-r.</LI>
+</UL>
+<H2><A NAME="8_2">HTTP Constants</A></H2>
+<H3><A NAME="8_2_1">Limits</A></H3>
+<P>The following constants define the limits for strings:</P>
+<UL>
+<LI><CODE>HTTP_MAX_BUFFER</CODE> - Size of socket buffer.</LI>
+<LI><CODE>HTTP_MAX_HOST</CODE> - Maximum length of hostname.</LI>
+<LI><CODE>HTTP_MAX_URI</CODE> - Maximum length of URI.</LI>
+<LI><CODE>HTTP_MAX_VALUE</CODE> - Maximum length of field values.</LI>
+</UL>
+<H3><A NAME="8_2_2">Status Codes</A></H3>
+<P>The following status codes can be returned by <CODE>httpUpdate()</CODE>
+:</P>
+<UL>
+<LI><CODE>HTTP_ERROR</CODE> - A network error occurred</LI>
+<LI><CODE>HTTP_CONTINUE</CODE> - Continue response from HTTP proxy</LI>
+<LI><CODE>HTTP_OK</CODE> - OPTIONS/GET/HEAD/POST/TRACE command was
+ successful</LI>
+<LI><CODE>HTTP_CREATED</CODE> - PUT command was successful</LI>
+<LI><CODE>HTTP_ACCEPTED</CODE> - DELETE command was successful</LI>
+<LI><CODE>HTTP_NOT_AUTHORITATIVE</CODE> - Information isn't
+ authoritative</LI>
+<LI><CODE>HTTP_NO_CONTENT</CODE> - Successful command</LI>
+<LI><CODE>HTTP_RESET_CONTENT</CODE> - Content was reset/recreated</LI>
+<LI><CODE>HTTP_PARTIAL_CONTENT</CODE> - Only a partial file was
+ recieved/sent</LI>
+<LI><CODE>HTTP_MULTIPLE_CHOICES</CODE> - Multiple files match request</LI>
+<LI><CODE>HTTP_MOVED_PERMANENTLY</CODE> - Document has moved permanently</LI>
+<LI><CODE>HTTP_MOVED_TEMPORARILY</CODE> - Document has moved temporarily</LI>
+<LI><CODE>HTTP_SEE_OTHER</CODE> - See this other link...</LI>
+<LI><CODE>HTTP_NOT_MODIFIED</CODE> - File not modified</LI>
+<LI><CODE>HTTP_USE_PROXY</CODE> - Must use a proxy to access this URI</LI>
+<LI><CODE>HTTP_BAD_REQUEST</CODE> - Bad request</LI>
+<LI><CODE>HTTP_UNAUTHORIZED</CODE> - Unauthorized to access host</LI>
+<LI><CODE>HTTP_PAYMENT_REQUIRED</CODE> - Payment required</LI>
+<LI><CODE>HTTP_FORBIDDEN</CODE> - Forbidden to access this URI</LI>
+<LI><CODE>HTTP_NOT_FOUND</CODE> - URI was not found</LI>
+<LI><CODE>HTTP_METHOD_NOT_ALLOWED</CODE> - Method is not allowed</LI>
+<LI><CODE>HTTP_NOT_ACCEPTABLE</CODE> - Not Acceptable</LI>
+<LI><CODE>HTTP_PROXY_AUTHENTICATION</CODE> - Proxy Authentication is
+ Required</LI>
+<LI><CODE>HTTP_REQUEST_TIMEOUT</CODE> - Request timed out</LI>
+<LI><CODE>HTTP_CONFLICT</CODE> - Request is self-conflicting</LI>
+<LI><CODE>HTTP_GONE</CODE> - Server has gone away</LI>
+<LI><CODE>HTTP_LENGTH_REQUIRED</CODE> - A content length or encoding is
+ required</LI>
+<LI><CODE>HTTP_PRECONDITION</CODE> - Precondition failed</LI>
+<LI><CODE>HTTP_REQUEST_TOO_LARGE</CODE> - Request entity too large</LI>
+<LI><CODE>HTTP_URI_TOO_LONG</CODE> - URI too long</LI>
+<LI><CODE>HTTP_UNSUPPORTED_MEDIATYPE</CODE> - The requested media type
+ is unsupported</LI>
+<LI><CODE>HTTP_SERVER_ERROR</CODE> - Internal server error</LI>
+<LI><CODE>HTTP_NOT_IMPLEMENTED</CODE> - Feature not implemented</LI>
+<LI><CODE>HTTP_BAD_GATEWAY</CODE> - Bad gateway</LI>
+<LI><CODE>HTTP_SERVICE_UNAVAILABLE</CODE> - Service is unavailable</LI>
+<LI><CODE>HTTP_GATEWAY_TIMEOUT</CODE> - Gateway connection timed out</LI>
+<LI><CODE>HTTP_NOT_SUPPORTED</CODE> - HTTP version not supported</LI>
+</UL>
+<H3><A NAME="8_2_3">Fields</A></H3>
+<P>The following fields are indices for each of the standard HTTP fields
+ in HTTP 1/1:</P>
+<UL>
+<LI><CODE>HTTP_FIELD_ACCEPT_LANGUAGE</CODE> - Accept-Language</LI>
+<LI><CODE>HTTP_FIELD_ACCEPT_RANGES</CODE> - Accept-Ranges</LI>
+<LI><CODE>HTTP_FIELD_AUTHORIZATION</CODE> - Authorization</LI>
+<LI><CODE>HTTP_FIELD_CONNECTION</CODE> - Connection</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_ENCODING</CODE> - Content-Encoding</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LANGUAGE</CODE> - Content-Language</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LENGTH</CODE> - Content-Length</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_LOCATION</CODE> - Content-Location</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_MD5</CODE> - Content-MD5</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_RANGE</CODE> - Content-Range</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_TYPE</CODE> - Content-Type</LI>
+<LI><CODE>HTTP_FIELD_CONTENT_VERSION</CODE> - Content-Version</LI>
+<LI><CODE>HTTP_FIELD_DATE</CODE> - Date</LI>
+<LI><CODE>HTTP_FIELD_HOST</CODE> - Host</LI>
+<LI><CODE>HTTP_FIELD_IF_MODIFIED_SINCE</CODE> - If-Modified-Since</LI>
+<LI><CODE>HTTP_FIELD_IF_UNMODIFIED_SINCE</CODE> - If-Unmodified-Since</LI>
+<LI><CODE>HTTP_FIELD_KEEP_ALIVE</CODE> - Keep-Alive</LI>
+<LI><CODE>HTTP_FIELD_LAST_MODIFIED</CODE> - Last-Modified</LI>
+<LI><CODE>HTTP_FIELD_LINK</CODE> - Link</LI>
+<LI><CODE>HTTP_FIELD_LOCATION</CODE> - Location</LI>
+<LI><CODE>HTTP_FIELD_RANGE</CODE> - Range</LI>
+<LI><CODE>HTTP_FIELD_REFERER</CODE> - Referer</LI>
+<LI><CODE>HTTP_FIELD_RETRY_AFTER</CODE> - Retry-After</LI>
+<LI><CODE>HTTP_FIELD_TRANSFER_ENCODING</CODE> - Transfer-Encoding</LI>
+<LI><CODE>HTTP_FIELD_UPGRADE</CODE> - Upgrade</LI>
+<LI><CODE>HTTP_FIELD_USER_AGENT</CODE> - User-Agent</LI>
+<LI><CODE>HTTP_FIELD_WWW_AUTHENTICATE</CODE> - WWW-Authenticate</LI>
+</UL>
+<H2><A NAME="8_3">IPP Constants</A></H2>
+<H3><A NAME="8_3_1">Limits</A></H3>
+<P>The following constants define array limits for IPP data:</P>
+<UL>
+<LI><CODE>IPP_MAX_NAME</CODE> - Maximum length of an attribute name</LI>
+<LI><CODE>IPP_MAX_VALUES</CODE> - Maximum number of set-of values that
+ can be read in a request.</LI>
+</UL>
+<H3><A NAME="8_3_2">Tags</A></H3>
+<UL>
+<LI><CODE>IPP_TAG_ZERO</CODE> - Wildcard tag value for searches; also
+ used to separate groups of attributes</LI>
+<LI><CODE>IPP_TAG_OPERATION</CODE> - Tag for values of type operation</LI>
+<LI><CODE>IPP_TAG_JOB</CODE> - Tag for values of type job</LI>
+<LI><CODE>IPP_TAG_END</CODE> - Tag for values of type end</LI>
+<LI><CODE>IPP_TAG_PRINTER</CODE> - Tag for values of type printer</LI>
+<LI><CODE>IPP_TAG_UNSUPPORTED_GROUP</CODE> - Tag for values of type
+ unsupported_group</LI>
+<LI><CODE>IPP_TAG_UNSUPPORTED_VALUE</CODE> - Tag for values of type
+ unsupported_value</LI>
+<LI><CODE>IPP_TAG_DEFAULT</CODE> - Tag for values of type default</LI>
+<LI><CODE>IPP_TAG_UNKNOWN</CODE> - Tag for values of type unknown</LI>
+<LI><CODE>IPP_TAG_NOVALUE</CODE> - Tag for values of type novalue</LI>
+<LI><CODE>IPP_TAG_NOTSETTABLE</CODE> - Tag for values of type
+ notsettable</LI>
+<LI><CODE>IPP_TAG_DELETEATTR</CODE> - Tag for values of type deleteattr</LI>
+<LI><CODE>IPP_TAG_ANYVALUE</CODE> - Tag for values of type anyvalue</LI>
+<LI><CODE>IPP_TAG_INTEGER</CODE> - Tag for values of type integer</LI>
+<LI><CODE>IPP_TAG_BOOLEAN</CODE> - Tag for values of type boolean</LI>
+<LI><CODE>IPP_TAG_ENUM</CODE> - Tag for values of type enum</LI>
+<LI><CODE>IPP_TAG_STRING</CODE> - Tag for values of type string</LI>
+<LI><CODE>IPP_TAG_DATE</CODE> - Tag for values of type date</LI>
+<LI><CODE>IPP_TAG_RESOLUTION</CODE> - Tag for values of type resolution</LI>
+<LI><CODE>IPP_TAG_RANGE</CODE> - Tag for values of type range</LI>
+<LI><CODE>IPP_TAG_COLLECTION</CODE> - Tag for values of type collection</LI>
+<LI><CODE>IPP_TAG_TEXTLANG</CODE> - Tag for values of type textlang</LI>
+<LI><CODE>IPP_TAG_NAMELANG</CODE> - Tag for values of type namelang</LI>
+<LI><CODE>IPP_TAG_TEXT</CODE> - Tag for values of type text</LI>
+<LI><CODE>IPP_TAG_NAME</CODE> - Tag for values of type name</LI>
+<LI><CODE>IPP_TAG_KEYWORD</CODE> - Tag for values of type keyword</LI>
+<LI><CODE>IPP_TAG_URI</CODE> - Tag for values of type uri</LI>
+<LI><CODE>IPP_TAG_URISCHEME</CODE> - Tag for values of type urischeme</LI>
+<LI><CODE>IPP_TAG_CHARSET</CODE> - Tag for values of type charset</LI>
+<LI><CODE>IPP_TAG_LANGUAGE</CODE> - Tag for values of type language</LI>
+<LI><CODE>IPP_TAG_MIMETYPE</CODE> - Tag for values of type mimetype</LI>
+</UL>
+<H3><A NAME="8_3_3">Resolution Units</A></H3>
+<P>The <CODE>IPP_RES_PER_INCH</CODE> and <CODE>IPP_RES_PER_CM</CODE>
+ constants specify dots per inch and dots per centimeter, respectively.</P>
+<H3><A NAME="8_3_4">Finishings</A></H3>
+<P>The finishing values specify special finishing operations to be
+ performed on the job.</P>
+<UL>
+<LI><CODE>IPP_FINISH_NONE</CODE> - Do no finishing</LI>
+<LI><CODE>IPP_FINISH_STAPLE</CODE> - Staple the job</LI>
+<LI><CODE>IPP_FINISH_PUNCH</CODE> - Punch the job</LI>
+<LI><CODE>IPP_FINISH_COVER</CODE> - Cover the job</LI>
+<LI><CODE>IPP_FINISH_BIND</CODE> - Bind the job</LI>
+</UL>
+<H3><A NAME="8_3_5">Orientations</A></H3>
+<P>The orientation values specify the orientation of the job.</P>
+<UL>
+<LI><CODE>IPP_PORTRAIT</CODE> - No rotation</LI>
+<LI><CODE>IPP_LANDSCAPE</CODE> - 90 degrees counter-clockwise</LI>
+<LI><CODE>IPP_REVERSE_LANDSCAPE</CODE> - 90 degrees clockwise</LI>
+<LI><CODE>IPP_REVERSE_PORTRAIT</CODE> - 180 degrees</LI>
+</UL>
+<H3><A NAME="8_3_6">Qualities</A></H3>
+<P>The quality values specify the desired quality of the print.</P>
+<UL>
+<LI><CODE>IPP_QUALITY_DRAFT</CODE> - Draft quality</LI>
+<LI><CODE>IPP_QUALITY_NORMAL</CODE> - Normal quality</LI>
+<LI><CODE>IPP_QUALITY_HIGH</CODE> - High quality</LI>
+</UL>
+<H3><A NAME="8_3_7">Job States</A></H3>
+<P>The job state values are used to represent the current job state.</P>
+<UL>
+<LI><CODE>IPP_JOB_PENDING</CODE> - Job is pending</LI>
+<LI><CODE>IPP_JOB_HELD</CODE> - Job is held</LI>
+<LI><CODE>IPP_JOB_PROCESSING</CODE> - Job is processing</LI>
+<LI><CODE>IPP_JOB_STOPPED</CODE> - Job is stopped</LI>
+<LI><CODE>IPP_JOB_CANCELLED</CODE> - Job is cancelled</LI>
+<LI><CODE>IPP_JOB_ABORTED</CODE> - Job is aborted</LI>
+<LI><CODE>IPP_JOB_COMPLETED</CODE> - Job is completed</LI>
+</UL>
+<H3><A NAME="8_3_8">Printer States</A></H3>
+<P>The printer state values are used to represent the current printer
+ state.</P>
+<UL>
+<LI><CODE>IPP_PRINTER_IDLE</CODE> - Printer is idle</LI>
+<LI><CODE>IPP_PRINTER_PROCESSING</CODE> - Printer is processing</LI>
+<LI><CODE>IPP_PRINTER_STOPPED</CODE> - Printer is stopped</LI>
+</UL>
+<H3><A NAME="8_3_9">Operations</A></H3>
+<P>The operation values represent the available IPP operations.</P>
+<UL>
+<LI><CODE>IPP_PRINT_JOB</CODE> - Print a file</LI>
+<LI><CODE>IPP_PRINT_URI</CODE> - Print a URI</LI>
+<LI><CODE>IPP_VALIDATE_JOB</CODE> - Validate job attributes</LI>
+<LI><CODE>IPP_CREATE_JOB</CODE> - Create a new job</LI>
+<LI><CODE>IPP_SEND_DOCUMENT</CODE> - Send a document to a job</LI>
+<LI><CODE>IPP_SEND_URI</CODE> - Send a URI to a job</LI>
+<LI><CODE>IPP_CANCEL_JOB</CODE> - Cancel a job</LI>
+<LI><CODE>IPP_GET_JOB_ATTRIBUTES</CODE> - Get job attributes</LI>
+<LI><CODE>IPP_GET_JOBS</CODE> - Get a list of all jobs</LI>
+<LI><CODE>IPP_GET_PRINTER_ATTRIBUTES</CODE> - Get printer attributes</LI>
+<LI><CODE>IPP_HOLD_JOB</CODE> - Hold a pending job</LI>
+<LI><CODE>IPP_RELEASE_JOB</CODE> - Release a held job</LI>
+<LI><CODE>IPP_RESTART_JOB</CODE> - Restart a completed job</LI>
+<LI><CODE>IPP_PAUSE_PRINTER</CODE> - Pause a printer</LI>
+<LI><CODE>IPP_RESUME_PRINTER</CODE> - Restart a paused printer</LI>
+<LI><CODE>IPP_PURGE_JOBS</CODE> - Purge jobs from the queue</LI>
+<LI><CODE>IPP_SET_PRINTER_ATTRIBUTES</CODE> - Set printer attributes</LI>
+<LI><CODE>IPP_SET_JOB_ATTRIBUTES</CODE> - Set job attributes</LI>
+<LI><CODE>IPP_GET_PRINTER_SUPPORTED_VALUES</CODE> - Get printer
+ supported values</LI>
+<LI><CODE>CUPS_GET_DEFAULT</CODE> - Get the default destination</LI>
+<LI><CODE>CUPS_GET_PRINTERS</CODE> - Get a list of all printers</LI>
+<LI><CODE>CUPS_ADD_PRINTER</CODE> - Add or modify a printer</LI>
+<LI><CODE>CUPS_DELETE_PRINTER</CODE> - Delete a printer</LI>
+<LI><CODE>CUPS_GET_CLASSES</CODE> - Get a list of all classes</LI>
+<LI><CODE>CUPS_ADD_CLASS</CODE> - Add or modify a class</LI>
+<LI><CODE>CUPS_DELETE_CLASS</CODE> - Delete a class</LI>
+<LI><CODE>CUPS_ACCEPT_JOBS</CODE> - Accept jobs on a printer or class</LI>
+<LI><CODE>CUPS_REJECT_JOBS</CODE> - Reject jobs on a printer or class</LI>
+<LI><CODE>CUPS_SET_DEFAULT</CODE> - Set the default destination</LI>
+<LI><CODE>CUPS_GET_DEVICES</CODE> - Get a list of all devices</LI>
+<LI><CODE>CUPS_GET_PPDS</CODE> - Get a list of all PPDs</LI>
+<LI><CODE>CUPS_MOVE_JOB</CODE> - Move a job to a new destination</LI>
+</UL>
+<H3><A NAME="8_3_10">Status Codes</A></H3>
+<P>Status codes are returned by all IPP requests.</P>
+<UL>
+<LI><CODE>IPP_OK</CODE> - Request completed with no errors</LI>
+<LI><CODE>IPP_OK_SUBST</CODE> - Request completed but some attribute
+ values were substituted</LI>
+<LI><CODE>IPP_OK_CONFLICT</CODE> - Request completed but some attributes
+ conflicted</LI>
+<LI><CODE>IPP_BAD_REQUEST</CODE> - The request was bad</LI>
+<LI><CODE>IPP_FORBIDDEN</CODE> - You don't have access to the resource</LI>
+<LI><CODE>IPP_NOT_AUTHENTICATED</CODE> - You are not authenticated for
+ the resource</LI>
+<LI><CODE>IPP_NOT_AUTHORIZED</CODE> - You not authorized to access the
+ resource</LI>
+<LI><CODE>IPP_NOT_POSSIBLE</CODE> - The requested operation cannot be
+ completed</LI>
+<LI><CODE>IPP_TIMEOUT</CODE> - A timeout occurred</LI>
+<LI><CODE>IPP_NOT_FOUND</CODE> - The resource was not found</LI>
+<LI><CODE>IPP_GONE</CODE> - The resource has gone away</LI>
+<LI><CODE>IPP_REQUEST_ENTITY</CODE> - The request was too large</LI>
+<LI><CODE>IPP_REQUEST_VALUE</CODE> - The request contained a value that
+ was unknown to the server</LI>
+<LI><CODE>IPP_DOCUMENT_FORMAT</CODE> - The document format is not
+ supported by the server</LI>
+<LI><CODE>IPP_ATTRIBUTES</CODE> - Required attributes are missing</LI>
+<LI><CODE>IPP_URI_SCHEME</CODE> - The URI scheme is not supported</LI>
+<LI><CODE>IPP_CHARSET</CODE> - The charset is not supported</LI>
+<LI><CODE>IPP_CONFLICT</CODE> - One or more attributes conflict</LI>
+<LI><CODE>IPP_COMPRESSION_NOT_SUPPORTED</CODE> - The specified
+ compression is not supported</LI>
+<LI><CODE>IPP_COMPRESSION_ERROR</CODE> - The compressed data contained
+ an error</LI>
+<LI><CODE>IPP_DOCUMENT_FORMAT_ERROR</CODE> - The document data contained
+ an error in it</LI>
+<LI><CODE>IPP_DOCUMENT_ACCESS_ERROR</CODE> - The remote document could
+ not be accessed</LI>
+<LI><CODE>IPP_INTERNAL_ERROR</CODE> - The server encountered an internal
+ error</LI>
+<LI><CODE>IPP_OPERATION_NOT_SUPPORTED</CODE> - The requested operation
+ is not supported</LI>
+<LI><CODE>IPP_SERVICE_UNAVAILABLE</CODE> - The requested service is
+ unavailable</LI>
+<LI><CODE>IPP_VERSION_NOT_SUPPORTED</CODE> - The IPP request version is
+ not supported</LI>
+<LI><CODE>IPP_DEVICE_ERROR</CODE> - The output device encountered an
+ error</LI>
+<LI><CODE>IPP_TEMPORARY_ERROR</CODE> - A temporary error occurred</LI>
+<LI><CODE>IPP_NOT_ACCEPTING</CODE> - The destination is not accepting
+ jobs</LI>
+<LI><CODE>IPP_PRINTER_BUSY</CODE> - The destination is busy</LI>
+<LI><CODE>IPP_ERROR_JOB_CANCELLED</CODE> - The requested job has been
+ cancelled</LI>
+<LI><CODE>IPP_MULTIPLE_JOBS_NOT_SUPPORTED</CODE> - The server does not
+ support multiple jobs</LI>
+</UL>
+<H2><A NAME="8_4">PPD Constants</A></H2>
+<H3><A NAME="8_4_1">PPD Format Version</A></H3>
+<P>The <CODE>PPD_VERSION</CODE> constant defines a floating point number
+ representing the newest format version that is supported by CUPS,
+ currently 4.3.</P>
+<H3><A NAME="8_4_2">PPD User-Interface Types</A></H3>
+<P>Each printer option has a type associated with it:</P>
+<UL>
+<LI><CODE>PPD_UI_BOOLEAN</CODE> - The user can turn this option on or
+ off</LI>
+<LI><CODE>PPD_UI_PICKONE</CODE> - The user can choose one option value
+ to use.</LI>
+<LI><CODE>PPD_UI_PICKMANY</CODE> - The user can choose zero or more
+ option values.</LI>
+</UL>
+<H3><A NAME="8_4_3">PPD Sections</A></H3>
+<P>Some options must be output before others, or in different sections
+ of the output document. The <CODE>ppd_section_t</CODE> enumeration
+ defines which section the option must be output in:</P>
+<UL>
+<LI><CODE>PPD_ORDER_ANY</CODE> - The option can be output in any of the
+ document, page, or prolog sections of the document</LI>
+<LI><CODE>PPD_ORDER_DOCUMENT</CODE> - The option must be output in the
+ DocumentSetup section of the document</LI>
+<LI><CODE>PPD_ORDER_EXIT</CODE> - The option must be output before the
+ document</LI>
+<LI><CODE>PPD_ORDER_JCL</CODE> - The option must be output in the job
+ control section of the document</LI>
+<LI><CODE>PPD_ORDER_PAGE</CODE> - The option must be output in the
+ PageSetup section of the document</LI>
+<LI><CODE>PPD_ORDER_PROLOG</CODE> - The option must be output in the
+ Prolog section of the document</LI>
+</UL>
+<H3><A NAME="8_4_4">PPD Colorspaces</A></H3>
+<P>Each printer has a default colorspace:</P>
+<UL>
+<LI><CODE>PPD_CS_CMYK</CODE> - The printer uses CMYK colors by default</LI>
+<LI><CODE>PPD_CS_CMY</CODE> - The printer uses CMY colors by default</LI>
+<LI><CODE>PPD_CS_GRAY</CODE> - The printer uses grayscale by default</LI>
+<LI><CODE>PPD_CS_RGB</CODE> - The printer uses RGB colors by default</LI>
+<LI><CODE>PPD_CS_RGBK</CODE> - The printer uses RGBK colors by default</LI>
+<LI><CODE>PPD_CS_N</CODE> - The printer uses a DeviceN colorspace by
+ default</LI>
+</UL>
+<H2><A NAME="8_5">Raster Constants</A></H2>
+<H3><A NAME="8_5_1">Raster Sync Words</A></H3>
+<P>The <CODE>CUPS_RASTER_SYNC</CODE> and <CODE>CUPS_RASTER_REVSYNC</CODE>
+ constants define the standard sync words at the beginning of each CUPS
+ raster file.</P>
+<H3><A NAME="8_5_2">Raster Stream Modes</A></H3>
+<P>The <CODE>CUPS_RASTER_READ</CODE> and <CODE>CUPS_RASTER_WRITE</CODE>
+ constants are used with the <A HREF="#cupsRasterOpen"><CODE>
+cupsRasterOpen()</CODE></A> function to specify a stream for reading or
+ writing.</P>
+<H3><A NAME="8_5_3">Raster Boolean Constants</A></H3>
+<P>The <CODE>CUPS_FALSE</CODE> and <CODE>CUPS_TRUE</CODE> constants
+ represent boolean values in the page header.</P>
+<H3><A NAME="8_5_4">Raster Jog Values</A></H3>
+<P>The <CODE>cups_jog_t</CODE> enumeration defines constants for the Jog
+ page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_JOG_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_JOG_FILE</CODE> - Jog pages after each file</LI>
+<LI><CODE>CUPS_JOG_JOB</CODE> - Jog pages after each job</LI>
+<LI><CODE>CUPS_JOG_SET</CODE> - Jog pages after each set of jobs</LI>
+</UL>
+<H3><A NAME="8_5_5">Raster Orientation Values</A></H3>
+<P>The <CODE>cups_orient_t</CODE> enumeration defines constants for the
+ Orientation page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_ORIENT_0</CODE> - Portrait orientation</LI>
+<LI><CODE>CUPS_ORIENT_90</CODE> - Landscape orientation</LI>
+<LI><CODE>CUPS_ORIENT_180</CODE> - Reverse-portrait orientation</LI>
+<LI><CODE>CUPS_ORIENT_270</CODE> - Reverse-landscape orientation</LI>
+</UL>
+<H3><A NAME="8_5_6">Raster CutMedia Values</A></H3>
+<P>The <CODE>cups_cut_t</CODE> enumeration defines constants for the
+ CutMedia page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_CUT_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_CUT_FILE</CODE> - Cut pages after each file</LI>
+<LI><CODE>CUPS_CUT_JOB</CODE> - Cut pages after each job</LI>
+<LI><CODE>CUPS_CUT_SET</CODE> - Cut pages after each set of jobs</LI>
+<LI><CODE>CUPS_CUT_PAGE</CODE> - Cut each page</LI>
+</UL>
+<H3><A NAME="8_5_7">Raster AdvanceMedia Values</A></H3>
+<P>The <CODE>cups_advance_t</CODE> enumeration defines constants for the
+ AdvanceMedia page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_ADVANCE_NONE</CODE> - Do no jogging</LI>
+<LI><CODE>CUPS_ADVANCE_FILE</CODE> - Advance media after each file</LI>
+<LI><CODE>CUPS_ADVANCE_JOB</CODE> - Advance media after each job</LI>
+<LI><CODE>CUPS_ADVANCE_SET</CODE> - Advance media after each set of jobs</LI>
+<LI><CODE>CUPS_ADVANCE_PAGE</CODE> - Advance media for each page</LI>
+</UL>
+<H3><A NAME="8_5_8">Raster LeadingEdge Values</A></H3>
+<P>The <CODE>cups_edge_t</CODE> enumeration defines constants for the
+ LeadingEdge page device dictionary variable:</P>
+<UL>
+<LI><CODE>CUPS_EDGE_TOP</CODE> - The top of the media is the leading
+ edge</LI>
+<LI><CODE>CUPS_EDGE_RIGHT</CODE> - The right of the media is the leading
+ edge</LI>
+<LI><CODE>CUPS_EDGE_BOTTOM</CODE> - The bottom of the media is the
+ leading edge</LI>
+<LI><CODE>CUPS_EDGE_LEFT</CODE> - The left of the media is the leading
+ edge</LI>
+</UL>
+<H3><A NAME="8_5_9">Raster Color Order Values</A></H3>
+<P>The <CODE>cups_order_t</CODE> enumeration defines the possible color
+ value orderings:</P>
+<UL>
+<LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK</LI>
+<LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK</LI>
+<LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...</LI>
+</UL>
+<H3><A NAME="8_5_10">Raster Colorspace Values</A></H3>
+<P>The <CODE>cups_cspace_t</CODE> enumeration defines the possible
+ colorspaces:</P>
+<UL>
+<LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)</LI>
+<LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue</LI>
+<LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha</LI>
+<LI><CODE>CUPS_CSPACE_K</CODE> - Black</LI>
+<LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan</LI>
+<LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black</LI>
+<LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow</LI>
+<LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta</LI>
+<LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, black</LI>
+<LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic
+ magenta, metallic cyan, metallic grey (silver)</LI>
+<LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white
+ pigment)</LI>
+<LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)</LI>
+<LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)</LI>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="STRUCTURES">C - Structures</A></H1>
+<P>This appendix describes all of the structures that are defined by the
+ CUPS API.</P>
+<H2><A NAME="9_1">CUPS Structures</A></H2>
+<H3><A NAME="cups_dest_t">CUPS Destinations</A></H3>
+<P>The CUPS destination structure (<CODE>cups_dest_t</CODE>) contains
+ information on a specific destination or instance:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>char *</TD><TD>The name of the printer or class.</TD>
+</TR>
+<TR><TD>instance</TD><TD>char *</TD><TD>The instance of the printer or
+ class; NULL for the primary instance.</TD></TR>
+<TR><TD>is_default</TD><TD>int</TD><TD>1 if the destination is set as
+ the default, 0 otherwise.</TD></TR>
+<TR><TD>num_options</TD><TD>int</TD><TD>The number of options associated
+ with this destination.</TD></TR>
+<TR><TD>options</TD><TD><A HREF="#cups_option_t">cups_option_t *</A></TD><TD>
+The options associated with this destination.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="cups_job_t">CUPS Jobs</A></H3>
+<P>The CUPS job structure (<CODE>cups_job_t</CODE>) contains information
+ on a specific job:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>id</TD><TD>int</TD><TD>The job ID for this job.</TD></TR>
+<TR><TD>dest</TD><TD>char *</TD><TD>The destination for this job
+ (printer or class name).</TD></TR>
+<TR><TD>title</TD><TD>char *</TD><TD>The job-name for this job (title).</TD>
+</TR>
+<TR><TD>user</TD><TD>char *</TD><TD>The job-originating-user-name for
+ this job (username).</TD></TR>
+<TR><TD>format</TD><TD>char *</TD><TD>The document-format for this job
+ (MIME type string).</TD></TR>
+<TR><TD>state</TD><TD>ipp_jstate</TD><TD>The current state of the job.</TD>
+</TR>
+<TR><TD>size</TD><TD>int</TD><TD>The size of this job in kilobytes.</TD></TR>
+<TR><TD>priority</TD><TD>int</TD><TD>The priority of this job from 1 to
+ 100 (50 is normal).</TD></TR>
+<TR><TD>completed_time</TD><TD>time_t</TD><TD>The time the job was
+ completed, or 0 if not yet completed.</TD></TR>
+<TR><TD>creation_time</TD><TD>time_t</TD><TD>The time the job was
+ queued.</TD></TR>
+<TR><TD>processing_time</TD><TD>time_t</TD><TD>The time the job started
+ printing.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="cups_lang_t">CUPS Messages</A></H3>
+<P>The CUPS messages structure (<CODE>cups_lang_t</CODE>) contains the
+ character set, locale name, and messages array:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>next</TD><TD>cups_lang_t *</TD><TD>Pointer to the next messages
+ structure in memory.</TD></TR>
+<TR><TD>used</TD><TD>int</TD><TD>The number of active users of this
+ messages structure.</TD></TR>
+<TR><TD>encoding</TD><TD>cups_encoding_t</TD><TD>The character encoding
+ of the message strings.</TD></TR>
+<TR><TD>language</TD><TD>char [16]</TD><TD>The language/locale name.</TD>
+</TR>
+<TR><TD>messages</TD><TD>char *[]</TD><TD>The array of message strings.</TD>
+</TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="cups_option_t">CUPS Options</A></H3>
+<P>The CUPS option structure (<CODE>cups_option_t</CODE>) contains the
+ option name and string value:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>char *</TD><TD>The name of the option.</TD></TR>
+<TR><TD>value</TD><TD>char *</TD><TD>The string value of the option.</TD>
+</TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="9_2">Networking Structures</A></H2>
+<H3><A NAME="http_t">HTTP State</A></H3>
+<P>The HTTP state structure (<CODE>http_t</CODE>) contains the current
+ state of a HTTP request or response:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>fd</TD><TD>int</TD><TD>The socket for the HTTP connection.</TD></TR>
+<TR><TD>blocking</TD><TD>int</TD><TD>1 if the HTTP functions should
+ block, 0 if not.</TD></TR>
+<TR><TD>error</TD><TD>int</TD><TD>The last OS error that occurred on the
+ socket.</TD></TR>
+<TR><TD>activity</TD><TD>time_t</TD><TD>The last time the HTTP
+ connection was used.</TD></TR>
+<TR><TD>state</TD><TD>http_state_t</TD><TD>The current HTTP
+ request/response state.</TD></TR>
+<TR><TD>status</TD><TD>int</TD><TD>The last HTTP status seen.</TD></TR>
+<TR><TD>version</TD><TD>http_version_t</TD><TD>The HTTP protocol version
+ in use.</TD></TR>
+<TR><TD>keep_alive</TD><TD>http_keep_alive_t</TD><TD>Whether or not to
+ use Keep-Alive</TD></TR>
+<TR><TD>hostaddr</TD><TD>struct sockaddr_in</TD><TD>The IPv4 address of
+ the HTTP server.</TD></TR>
+<TR><TD>hostname</TD><TD>char []</TD><TD>The hostname of the HTTP
+ server.</TD></TR>
+<TR><TD>fields</TD><TD>char [][]</TD><TD>The string values of all HTTP
+ request/response fields.</TD></TR>
+<TR><TD>data</TD><TD>char *</TD><TD>Current byte in data buffer.</TD></TR>
+<TR><TD>data_encoding</TD><TD>http_encoding_t</TD><TD>The transfer
+ encoding for the request/response.</TD></TR>
+<TR><TD>data_remaining</TD><TD>int</TD><TD>The number of bytes remaining
+ in the current request, response, or chunk.</TD></TR>
+<TR><TD>used</TD><TD>int</TD><TD>The number of bytes that are used in
+ the buffer.</TD></TR>
+<TR><TD>buffer</TD><TD>char []</TD><TD>The read/write buffer.</TD></TR>
+<TR><TD>auth_type</TD><TD>int</TD><TD>The type of authentication in use.</TD>
+</TR>
+<TR><TD>md5_state</TD><TD>md5_state_t</TD><TD>The current MD5 digest
+ state.</TD></TR>
+<TR><TD>nonce</TD><TD>char []</TD><TD>The nonce value for Digest
+ authentication.</TD></TR>
+<TR><TD>nonce_count</TD><TD>int</TD><TD>The nonce count value.</TD></TR>
+<TR><TD>tls</TD><TD>void *</TD><TD>A pointer to private encryption data.</TD>
+</TR>
+<TR><TD>encryption</TD><TD>http_encryption_t</TD><TD>The current
+ encryption mode.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="ipp_t">IPP State</A></H3>
+<P>The IPP state structure (<CODE>ipp_t</CODE>) contains the current
+ state of a IPP request or response:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD></TD><TD></TD><TD></TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="ipp_attribute_t">IPP Attribute</A></H3>
+<P>TODO</P>
+<H2><A NAME="9_3">PPD Structures</A></H2>
+<H3><A NAME="ppd_file_t">PPD File</A></H3>
+<P>TODO</P>
+<H3><A NAME="ppd_choice_t">PPD Choice</A></H3>
+<P>TODO</P>
+<H2><A NAME="9_4">Raster Structures</A></H2>
+<H3><A NAME="cups_raster_t">Raster Stream</A></H3>
+<P>TODO</P>
+<H3><A NAME="cups_raster_header_t">Raster Page Header</A></H3>
+<P>The raster page header (<CODE>cups_raster_header_t</CODE>) consists
+ of the PostScript page device dictionary for the page:
+<CENTER>
+<TABLE BORDER="1" WIDTH="90%">
+<TR><TH>Member</TH><TH>Type</TH><TH>Description</TH></TR>
+<TR><TD>MediaClass</TD><TD>char[64]</TD><TD>The media class name</TD></TR>
+<TR><TD>MediaColor</TD><TD>char[64]</TD><TD>The media color name</TD></TR>
+<TR><TD>MediaType</TD><TD>char[64]</TD><TD>The media type name</TD></TR>
+<TR><TD>OutputType</TD><TD>char[64]</TD><TD>The output type name</TD></TR>
+<TR><TD>AdvanceDistance</TD><TD>unsigned</TD><TD>The distance to advance
+ the media in points</TD></TR>
+<TR><TD>AdvanceMedia</TD><TD>cups_adv_t</TD><TD>When to advance the
+ media</TD></TR>
+<TR><TD>Collate</TD><TD>cups_bool_t</TD><TD>Whether or not to produce
+ collated copies</TD></TR>
+<TR><TD>CutMedia</TD><TD>cups_cut_t</TD><TD>When to cut the media</TD></TR>
+<TR><TD>Duplex</TD><TD>cups_bool_t</TD><TD>Whether or not to print on
+ both sides of the paper</TD></TR>
+<TR><TD>HWResolution</TD><TD>unsigned[2]</TD><TD>The resolution of the
+ page image in pixels per inch; the HWResolution[0] represents the
+ horizontal resolution and HWResolution[1] represents the vertical
+ resolution</TD></TR>
+<TR><TD>ImagingBoundingBox</TD><TD>unsigned[4]</TD><TD>The bounding box
+ for the page in points; the elements represent the left, bottom, right,
+ and top coordinates of the imaged area (if 0 then the whole page is
+ imaged)</TD></TR>
+<TR><TD>InsertSheet</TD><TD>cups_bool_t</TD><TD>Whether or not to insert
+ a sheet before this page</TD></TR>
+<TR><TD>Jog</TD><TD>cups_jog_t</TD><TD>When to jog copies of the page</TD>
+</TR>
+<TR><TD>LeadingEdge</TD><TD>cups_edge_t</TD><TD>The leading edge of the
+ page</TD></TR>
+<TR><TD>Margins</TD><TD>unsigned[2]</TD><TD>The lower-lefthand margin of
+ the page in points</TD></TR>
+<TR><TD>ManualFeed</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ manually feed the page</TD></TR>
+<TR><TD>MediaPosition</TD><TD>unsigned</TD><TD>The input slot number to
+ use</TD></TR>
+<TR><TD>MediaWeight</TD><TD>unsigned</TD><TD>The weight of the output
+ media in grams/m<SUP>2</SUP></TD></TR>
+<TR><TD>MirrorPrint</TD><TD>cups_bool_t</TD><TD>Whether or not to mirror
+ the print</TD></TR>
+<TR><TD>NegativePrint</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ invert the print</TD></TR>
+<TR><TD>NumCopies</TD><TD>unsigned</TD><TD>The number of copies to
+ produce</TD></TR>
+<TR><TD>Orientation</TD><TD>cups_orient_t</TD><TD>The orientation of the
+ page image</TD></TR>
+<TR><TD>OutputFaceUp</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ output the page face up</TD></TR>
+<TR><TD>PageSize</TD><TD>unsigned[2]</TD><TD>The width and height of the
+ page in points</TD></TR>
+<TR><TD>Separations</TD><TD>cups_bool_t</TD><TD>Whether or not to output
+ separations</TD></TR>
+<TR><TD>TraySwitch</TD><TD>cups_bool_t</TD><TD>Whether or not to
+ automatically switch trays for the requested media size/type</TD></TR>
+<TR><TD>Tumble</TD><TD>cups_bool_t</TD><TD>Whether or not to rotate the
+ back side of the page</TD></TR>
+<TR><TD>cupsWidth</TD><TD>unsigned</TD><TD>The width of the page image
+ in pixels</TD></TR>
+<TR><TD>cupsHeight</TD><TD>unsigned</TD><TD>The height of the page image
+ in pixels</TD></TR>
+<TR><TD>cupsMediaType</TD><TD>unsigned</TD><TD>The device-specific media
+ type code</TD></TR>
+<TR><TD>cupsBitsPerColor</TD><TD>unsigned</TD><TD>The number of bits per
+ color</TD></TR>
+<TR><TD>cupsBitsPerPixel</TD><TD>unsigned</TD><TD>The number of bits per
+ pixel</TD></TR>
+<TR><TD>cupsBytesPerLine</TD><TD>unsigned</TD><TD>The number of bytes
+ per line of image data</TD></TR>
+<TR><TD>cupsColorOrder</TD><TD>cups_order_t</TD><TD>The order of color
+ values</TD></TR>
+<TR><TD>cupsColorSpace</TD><TD>cups_cspace_t</TD><TD>The type of color
+ values</TD></TR>
+<TR><TD>cupsCompression</TD><TD>unsigned</TD><TD>The device-specific
+ compression code</TD></TR>
+<TR><TD>cupsRowCount</TD><TD>unsigned</TD><TD>The device-specific row
+ count</TD></TR>
+<TR><TD>cupsRowFeed</TD><TD>unsigned</TD><TD>The device-specific row
+ feed</TD></TR>
+<TR><TD>cupsRowStep</TD><TD>unsigned</TD><TD>The device-specific row
+ step</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 ALIGN="RIGHT"><A NAME="FUNCTIONS">D - Functions</A></H1>
+<P>This appendix provides a reference for all of the CUPS API functions.
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsAddDest">cupsAddDest()</A></H2>
+<H3><A NAME="10_1_1">Usage</A></H3>
+<PRE>
+int
+cupsAddDest(const char *name,
+ const char *instance,
+ int num_dests,
+ cups_dest_t **dests);
+</PRE>
+<H3><A NAME="10_1_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>The name of the destination.</TD></TR>
+<TR><TD>instance</TD><TD>The instance of the destination, or NULL for
+ the primary instance.</TD></TR>
+<TR><TD>num_dests</TD><TD>The number of destinations in the array.</TD></TR>
+<TR><TD>dest</TD><TD>A pointer to the destination array pointer.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_1_3">Returns</A></H3>
+<P>The new number of destinations in the array.</P>
+<H3><A NAME="10_1_4">Description</A></H3>
+<P><CODE>cupsAddDest()</CODE> adds the named destination to the
+ destination array if it does not already exist.</P>
+<H3><A NAME="10_1_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+
+
+num_dests = cupsAddDests(&quot;foo&quot;, &quot;bar&quot;, num_dests, &amp;dests);
+</PRE>
+<H3><A NAME="10_1_6">See Also</A></H3>
+<P> <A HREF="#cupsFreeDests"><CODE>cupsFreeDests()</CODE></A>, <A HREF="#cupsGetDest">
+<CODE>cupsGetDest()</CODE></A>, <A HREF="#cupsGetDests"><CODE>
+cupsGetDests()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsAddOption">cupsAddOption()</A></H2>
+<H3><A NAME="10_2_1">Usage</A></H3>
+<PRE>
+int
+cupsAddOption(const char *name,
+ const char *value,
+ int num_options,
+ cups_option_t **options);
+</PRE>
+<H3><A NAME="10_2_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>The name of the option.</TD></TR>
+<TR><TD>value</TD><TD>The value of the option.</TD></TR>
+<TR><TD>num_options</TD><TD>Number of options currently in the array.</TD>
+</TR>
+<TR><TD>options</TD><TD>Pointer to the options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_2_3">Returns</A></H3>
+<P>The new number of options.</P>
+<H3><A NAME="10_2_4">Description</A></H3>
+<P><CODE>cupsAddOption()</CODE> adds an option to the specified array.</P>
+<H3><A NAME="10_2_5">Example</A></H3>
+<PRE>
+#include &lt;cups.h&gt;
+
+...
+
+/* Declare the options array */
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+/* Initialize the options array */
+num_options = 0;
+options = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption(&quot;media&quot;, &quot;letter&quot;, num_options, &amp;options);
+num_options = cupsAddOption(&quot;resolution&quot;, &quot;300dpi&quot;, num_options, &amp;options);
+</PRE>
+<H3><A NAME="10_2_6">See Also</A></H3>
+ <A HREF="#cupsEncodeOptions"><CODE>cupsEncodeOptions()</CODE></A>, <A HREF="#cupsFreeOptions">
+<CODE>cupsFreeOptions()</CODE></A>, <A HREF="#cupsGetOption"><CODE>
+cupsGetOption()</CODE></A>, <A HREF="#cupsParseOptions"><CODE>
+cupsParseOptions()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="cupsCancelJob">cupsCancelJob()</A></H2>
+<H3><A NAME="10_3_1">Usage</A></H3>
+<PRE>
+int
+cupsCancelJob(const char *dest,
+ int job);
+</PRE>
+<H3><A NAME="10_3_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>dest</TD><TD>Printer or class name</TD></TR>
+<TR><TD>job</TD><TD>Job ID</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_3_3">Returns</A></H3>
+<P>1 on success, 0 on failure. On failure the error can be found by
+ calling <A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>.</P>
+<H3><A NAME="10_3_4">Description</A></H3>
+<P><CODE>cupsCancelJob()</CODE> cancels the specifies job.</P>
+<H3><A NAME="10_3_5">Example</A></H3>
+<PRE>
+#include &lt;cups.h&gt;
+
+cupsCancelJob(&quot;LaserJet&quot;, 1);
+</PRE>
+<H3><A NAME="10_3_6">See Also</A></H3>
+<P> <A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>, <A HREF="#cupsPrintFile">
+<CODE>cupsPrintFile()</CODE></A>, <A HREF="#cupsPrintFiles"><CODE>
+cupsPrintFiles()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsDoAuthentication">cupsDoAuthentication()</A></H2>
+<H3><A NAME="10_4_1">Usage</A></H3>
+<PRE>
+int
+cupsDoAuthentication(http_t *http,
+ const char *method,
+ const char *resource);
+</PRE>
+<H3><A NAME="10_4_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>HTTP connection to server.</TD></TR>
+<TR><TD>method</TD><TD>HTTP method name (&quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, etc.)</TD>
+</TR>
+<TR><TD>resource</TD><TD>HTTP resource name.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_4_3">Returns</A></H3>
+<P>0 if the authentication string was successfully generated, -1
+ otherwise.</P>
+<H3><A NAME="10_4_4">Description</A></H3>
+<P><CODE>cupsDoAuthentication()</CODE> generates an authentication
+ string for the given method and request. It supports Basic, Digest, and
+ CUPS local certificate authentication methods and uses the current user
+ and password callback to collect authentication information as needed.</P>
+<P>Applications using this function should set the <CODE>
+HTTP_FIELD_AUTHORIZATION</CODE> field to the <CODE>authstring</CODE>
+ value in the <CODE>http_t</CODE> structure prior to issuing a new
+ request.</P>
+<H3><A NAME="10_4_5">Example</A></H3>
+<PRE>
+#include &lt;cups.h&gt;
+
+http_t *http;
+char resource[HTTP_MAX_URI];
+http_status_t status;
+
+...
+
+do
+{
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http-&gt;authstring);
+
+ if (httpGet(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+
+ continue;
+ }
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ httpFlush(http);
+
+ if (cupsDoAuthentication(http, &quot;GET&quot;, resource))
+ break;
+
+ httpReconnect(http);
+ continue;
+ }
+}
+while (status == HTTP_UNAUTHORIZED);
+</PRE>
+<H3><A NAME="10_4_6">See Also</A></H3>
+<P> <A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>
+, <A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>, <A HREF="#cupsSetPasswordCB">
+<CODE>cupsSetPasswordCB()</CODE></A>, <A HREF="#cupsSetUser"><CODE>
+cupsSetUser()</CODE></A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsDoFileRequest">cupsDoFileRequest()</A></H2>
+<H3><A NAME="10_5_1">Usage</A></H3>
+<PRE>
+ipp_t *
+cupsDoFileRequest(http_t *http,
+ ipp_t *request,
+ const char *resource,
+ const char *filename);
+</PRE>
+<H3><A NAME="10_5_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>HTTP connection to server.</TD></TR>
+<TR><TD>request</TD><TD>IPP request data.</TD></TR>
+<TR><TD>resource</TD><TD>HTTP resource name for POST.</TD></TR>
+<TR><TD>filename</TD><TD>File to send with POST request (<CODE>NULL</CODE>
+ pointer if none.)</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_5_3">Returns</A></H3>
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On
+ failure the error can be found by calling <A HREF="#cupsLastError"><CODE>
+cupsLastError()</CODE></A>.</P>
+<H3><A NAME="10_5_4">Description</A></H3>
+<P><CODE>cupsDoFileRequest()</CODE> does a HTTP POST request and
+ provides the IPP request and optionally the contents of a file to the
+ IPP server. It also handles resubmitting the request and performing
+ password authentication as needed.</P>
+<H3><A NAME="10_5_5">Example</A></H3>
+<PRE>
+#include &lt;cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+<A HREF="#ipp_t">ipp_t</A> *request;
+ipp_t *response;
+
+...
+
+/* Get the default language */
+language = <A HREF="#cupsLangDefault">cupsLangDefault()</A>;
+
+/* Create a new IPP request */
+request = <A HREF="#ippNew">ippNew()</A>;
+
+request-&gt;request.op.operation_id = IPP_PRINT_FILE;
+request-&gt;request.op.request_id = 1;
+
+/* Add required attributes */
+<A HREF="#ippAddString">ippAddString</A>(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ &quot;attributes-charset&quot;, NULL, <A HREF="#cupsLangEncoding">cupsLangEncoding</A>(language));
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ &quot;attributes-natural-language&quot;, NULL,
+ language != NULL ? language-&gt;language : &quot;C&quot;);
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, &quot;printer-uri&quot;,
+ NULL, &quot;ipp://hostname/resource&quot;);
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, &quot;requesting-user-name&quot;,
+ NULL, <A HREF="#cupsUser">cupsUser()</A>);
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, &quot;/resource&quot;, &quot;filename.txt&quot;);
+</PRE>
+<H3><A NAME="10_5_6">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsUser"><CODE>
+cupsUser()</CODE></A>, <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+, <A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>, <A HREF="#ippNew">
+<CODE>ippNew()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsDoRequest">cupsDoRequest()</A></H2>
+<H3><A NAME="10_6_1">Usage</A></H3>
+<PRE>
+ipp_t *
+cupsDoRequest(http_t *http,
+ ipp_t *request,
+ const char *resource);
+</PRE>
+<H3><A NAME="10_6_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>HTTP connection to server.</TD></TR>
+<TR><TD>request</TD><TD>IPP request data.</TD></TR>
+<TR><TD>resource</TD><TD>HTTP resource name for POST.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_6_3">Returns</A></H3>
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On
+ failure the error can be found by calling <A HREF="#cupsLastError"><CODE>
+cupsLastError()</CODE></A>.</P>
+<H3><A NAME="10_6_4">Description</A></H3>
+<P><CODE>cupsDoRequest()</CODE> does a HTTP POST request and provides
+ the IPP request to the IPP server. It also handles resubmitting the
+ request and performing password authentication as needed.</P>
+<H3><A NAME="10_6_5">Example</A></H3>
+<PRE>
+#include &lt;cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+<A HREF="#ipp_t">ipp_t</A> *request;
+ipp_t *response;
+
+...
+
+/* Get the default language */
+language = <A HREF="#cupsLangDefault">cupsLangDefault()</A>;
+
+/* Create a new IPP request */
+request = <A HREF="#ippNew">ippNew()</A>;
+
+request-&gt;request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request-&gt;request.op.request_id = 1;
+
+/* Add required attributes */
+<A HREF="#ippAddString">ippAddString</A>(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ &quot;attributes-charset&quot;, NULL, <A HREF="#cupsLangEncoding">cupsLangEncoding</A>(language));
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ &quot;attributes-natural-language&quot;, NULL,
+ language != NULL ? language-&gt;language : &quot;C&quot;);
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, &quot;printer-uri&quot;,
+ NULL, &quot;ipp://hostname/resource&quot;);
+
+/* Do the request... */
+response = cupsDoRequest(http, request, &quot;/resource&quot;);
+</PRE>
+<H3><A NAME="10_6_6">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsUser"><CODE>
+cupsUser()</CODE></A>, <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+, <A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>, <A HREF="#ippNew">
+<CODE>ippNew()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsEncodeOptions">cupsEncodeOptions()</A></H2>
+<H3><A NAME="10_7_1">Usage</A></H3>
+<PRE>
+void
+cupsEncodeOptions(ipp_t *ipp,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_7_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options.</TD></TR>
+<TR><TD>options</TD><TD>The options.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_7_3">Description</A></H3>
+<P><CODE>cupsEncodeOptions()</CODE> encodes all of the options in the
+ specified array as IPP attributes and adds them to the IPP request.</P>
+<H3><A NAME="10_7_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+<A HREF="#ipp_t">ipp_t</A> *ipp;
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+
+cupsEncodeOptions(ipp, num_options, options);
+</PRE>
+<H3><A NAME="10_7_5">See Also</A></H3>
+<P> <A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>, <A HREF="#cupsParseOptions">
+<CODE>cupsParseOptions()</CODE></A>, <A HREF="#ippNew"><CODE>ippNew()</CODE>
+</A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsEncryption">cupsEncryption()</A></H2>
+<H3><A NAME="10_8_1">Usage</A></H3>
+<PRE>
+http_encryption_t
+cupsEncryption(void);
+</PRE>
+<H3><A NAME="10_8_2">Returns</A></H3>
+<P>The current encryption setting.</P>
+<H3><A NAME="10_8_3">Description</A></H3>
+<P><CODE>cupsEncryption()</CODE> returns the current encryption setting
+ for IPP requests such as printing.</P>
+<H3><A NAME="10_8_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+printf(&quot;The current encryption setting is %d.\n&quot;, cupsEncryption());
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+</PRE>
+<H3><A NAME="10_8_5">See Also</A></H3>
+<P> <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#httpConnectEncrypt">
+<CODE>httpConnectEncrypt()</CODE></A>, <A HREF="#ippPort"><CODE>
+ippPort()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsFreeDests">cupsFreeDests()</A></H2>
+<H3><A NAME="10_9_1">Usage</A></H3>
+<PRE>
+void
+cupsFreeDests(int num_dests,
+ cups_dest_t *dests);
+</PRE>
+<H3><A NAME="10_9_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>num_dests</TD><TD>The number of destinations in the array.</TD></TR>
+<TR><TD>dests</TD><TD>The destination array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_9_3">Description</A></H3>
+<P><CODE>cupsFreeDests()</CODE> frees a destination array that was
+ created using <CODE>cupsGetDests()</CODE>.</P>
+<H3><A NAME="10_9_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf(&quot;The default destination is %s\n&quot;, dest-&gt;name);
+else
+ puts(&quot;No default destination.&quot;);
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+<H3><A NAME="10_9_5">See Also</A></H3>
+<P> <A HREF="#cupsGetDest"><CODE>cupsGetDest()</CODE></A>, <A HREF="#cupsGetDests">
+<CODE>cupsGetDests()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsFreeJobs">cupsFreeJobs()</A></H2>
+<H3><A NAME="10_10_1">Usage</A></H3>
+<PRE>
+void
+cupsFreeJobs(int num_jobs,
+ cups_job_t *jobs);
+</PRE>
+<H3><A NAME="10_10_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>num_jobs</TD><TD>The number of jobs.</TD></TR>
+<TR><TD>jobs</TD><TD>The job array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_10_3">Description</A></H3>
+<P><CODE>cupsFreeJobs()</CODE> frees an array of print jobs created by
+ the <CODE>cupsGetJobs()</CODE> function.</P>
+<H3><A NAME="10_10_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_jobs;
+<A HREF="#cups_job_t">cups_job_t</A> *jobs;
+
+
+num_jobs = cupsGetJobs(&amp;jobs, NULL, 0, 0);
+
+printf(&quot;%d active job(s):\n&quot;, num_jobs);
+for (i = 0; i &lt; num_jobs; i ++)
+ printf(&quot;%-16.16s %-6d %-12.12s %s (%s)\n&quot;, jobs[i].dest, jobs[i].id,
+ jobs[i].user, jobs[i].title,
+ jobs[i].state != IPP_JOB_PENDING ? &quot;printing&quot; : &quot;pending&quot;);
+
+cupsFreeJobs(num_jobs, jobs);
+</PRE>
+<H3><A NAME="10_10_5">See Also</A></H3>
+<P> <A HREF="#cupsGetJobs"><CODE>cupsGetJobs()</CODE></A>, <A HREF="#cupsGetDests">
+<CODE>cupsGetDests()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsFreeOptions">cupsFreeOptions()</A></H2>
+<H3><A NAME="10_11_1">Usage</A></H3>
+<PRE>
+void
+cupsFreeOptions(int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_11_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>num_options</TD><TD>Number of options in array.</TD></TR>
+<TR><TD>options</TD><TD>Pointer to options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_11_3">Description</A></H3>
+<P><CODE>cupsFreeOptions()</CODE> frees all memory associated with the
+ option array specified.</P>
+<H3><A NAME="10_11_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+</PRE>
+<H3><A NAME="10_11_5">See Also</A></H3>
+<P> <A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>, <A HREF="#cupsEncodeOptions">
+<CODE>cupsEncodeOptions()</CODE></A>, <A HREF="#cupsGetOption"><CODE>
+cupsGetOption()</CODE></A>, <A HREF="#cupsMarkOptions"><CODE>
+cupsMarkOptions()</CODE></A>, <A HREF="#cupsParseOptions"><CODE>
+cupsParseOptions()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetClasses">cupsGetClasses()</A></H2>
+<H3><A NAME="10_12_1">Usage</A></H3>
+<PRE>
+int
+cupsGetClasses(char ***classes);
+</PRE>
+<H3><A NAME="10_12_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>classes</TD><TD>Pointer to character pointer array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_12_3">Returns</A></H3>
+<P>The number of printer classes available.</P>
+<H3><A NAME="10_12_4">Description</A></H3>
+<P><CODE>cupsGetClasses()</CODE> gets a list of the available printer
+ classes. The returned array should be freed using the <CODE>free()</CODE>
+ when it is no longer needed.</P>
+<H3><A NAME="10_12_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(&amp;classes);
+
+...
+
+if (num_classes &gt; 0)
+{
+ for (i = 0; i &lt; num_classes; i ++)
+ free(classes[i]);
+
+ free(classes);
+}
+</PRE>
+<H3><A NAME="10_12_6">See Also</A></H3>
+<P> <A HREF="#cupsGetDefault"><CODE>cupsGetDefault()</CODE></A>, <A HREF="#cupsGetPrinters">
+<CODE>cupsGetPrinters()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetDefault">cupsGetDefault()</A></H2>
+<H3><A NAME="10_13_1">Usage</A></H3>
+<PRE>
+const char *
+cupsGetDefault(void);
+</PRE>
+<H3><A NAME="10_13_2">Returns</A></H3>
+<P>A pointer to the default destination.</P>
+<H3><A NAME="10_13_3">Description</A></H3>
+<P><CODE>cupsGetDefault()</CODE> gets the default destination printer or
+ class. The default destination is stored in a static string and will be
+ overwritten (usually with the same value) after each call.</P>
+<H3><A NAME="10_13_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+printf(&quot;The default destination is %s\n&quot;, cupsGetDefault());
+</PRE>
+<H3><A NAME="10_13_5">See Also</A></H3>
+<P> <A HREF="#cupsGetClasses"><CODE>cupsGetClasses()</CODE></A>, <A HREF="#cupsGetPrinters">
+<CODE>cupsGetPrinters()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetDest">cupsGetDest()</A></H2>
+<H3><A NAME="10_14_1">Usage</A></H3>
+<PRE>
+cups_dest_t *
+cupsGetDest(const char *name,
+ const char *instance,
+ int num_dests,
+ cups_dest_t *dests);
+</PRE>
+<H3><A NAME="10_14_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>The name of the destination, or NULL for the
+ default destination.</TD></TR>
+<TR><TD>instance</TD><TD>The instance of the destination, or NULL for
+ the primary instance.</TD></TR>
+<TR><TD>num_dests</TD><TD>The number of destinations.</TD></TR>
+<TR><TD>dests</TD><TD>The destination array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_14_3">Returns</A></H3>
+<P>A pointer to the specified destination, or NULL if none exists.</P>
+<H3><A NAME="10_14_4">Description</A></H3>
+<P><CODE>cupsGetDest()</CODE> finds the specified destination in the
+ array of destinations created by the <CODE>cupsGetDests()</CODE>
+ function.</P>
+<H3><A NAME="10_14_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf(&quot;The default destination is %s\n&quot;, dest-&gt;name);
+else
+ puts(&quot;No default destination.&quot;);
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+<H3><A NAME="10_14_6">See Also</A></H3>
+<P> <A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>, <A HREF="#cupsGetJobs">
+<CODE>cupsGetJobs()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetDests">cupsGetDests()</A></H2>
+<H3><A NAME="10_15_1">Usage</A></H3>
+<PRE>
+int
+cupsGetDests(cups_dest_t **dests);
+</PRE>
+<H3><A NAME="10_15_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>dests</TD><TD>A pointer to a destination array pointer.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_15_3">Returns</A></H3>
+<P>The number of available destinations.</P>
+<H3><A NAME="10_15_4">Description</A></H3>
+<P><CODE>cupsGetDests()</CODE> creates an array of available
+ destinations that the user can print to. The array should be freed
+ using the <CODE>cupsFreeDests()</CODE> function.</P>
+<H3><A NAME="10_15_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf(&quot;The default destination is %s\n&quot;, dest-&gt;name);
+else
+ puts(&quot;No default destination.&quot;);
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+<H3><A NAME="10_15_6">See Also</A></H3>
+<P> <A HREF="#cupsFreeDests"><CODE>cupsFreeDests()</CODE></A>, <A HREF="#cupsGetDest">
+<CODE>cupsGetDest()</CODE></A>, <A HREF="#cupsGetJobs"><CODE>
+cupsGetJobs()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetFd">cupsGetFd()</A></H2>
+<H3><A NAME="10_16_1">Usage</A></H3>
+<PRE>
+http_status_t
+cupsGetFd(http_t *http,
+ const char *resource,
+ int fd);
+</PRE>
+<H3><A NAME="10_16_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection to the server.</TD></TR>
+<TR><TD>resource</TD><TD>The resource name on the server.</TD></TR>
+<TR><TD>fd</TD><TD>The file descriptor to write to.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_16_3">Returns</A></H3>
+<P>The HTTP status code associated with the request.</P>
+<H3><A NAME="10_16_4">Description</A></H3>
+<P><CODE>cupsGetFd()</CODE> gets a file from the given HTTP server and
+ writes it to the specified file descriptor, performing any
+ authentication or encryption as required.</P>
+<H3><A NAME="10_16_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+int fd;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+fd = cupsTempFd(filename, sizeof(filename));
+status = cupsGetFd(http, &quot;/admin/cupsd.conf&quot;, fd);
+
+...
+
+close(fd);
+unlink(filename);
+
+httpClose(http);
+</PRE>
+<H3><A NAME="10_16_6">See Also</A></H3>
+<P> <A HREF="#cupsGetFile"><CODE>cupsGetFile()</CODE></A>, <A HREF="#cupsPutFd">
+<CODE>cupsPutFd()</CODE></A>, <A HREF="#cupsPutFile"><CODE>cupsPutFile()</CODE>
+</A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetFile">cupsGetFile()</A></H2>
+<H3><A NAME="10_17_1">Usage</A></H3>
+<PRE>
+http_status_t
+cupsGetFile(http_t *http,
+ const char *resource,
+ const char *filename);
+</PRE>
+<H3><A NAME="10_17_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection to the server.</TD></TR>
+<TR><TD>resource</TD><TD>The resource name on the server.</TD></TR>
+<TR><TD>filename</TD><TD>The filename to write to.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_17_3">Returns</A></H3>
+<P>The HTTP status code associated with the request.</P>
+<H3><A NAME="10_17_4">Description</A></H3>
+<P><CODE>cupsGetFile()</CODE> gets a file from the given HTTP server and
+ writes it to the specified filename, performing any authentication or
+ encryption as required.</P>
+<H3><A NAME="10_17_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+cupsTempFile(filename, sizeof(filename));
+
+status = cupsGetFile(http, &quot;/admin/cupsd.conf&quot;, filename);
+
+...
+
+unlink(filename);
+
+httpClose(http);
+</PRE>
+<H3><A NAME="10_17_6">See Also</A></H3>
+<P> <A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>, <A HREF="#cupsPutFd">
+<CODE>cupsPutFd()</CODE></A>, <A HREF="#cupsPutFile"><CODE>cupsPutFile()</CODE>
+</A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetJobs">cupsGetJobs()</A></H2>
+<H3><A NAME="10_18_1">Usage</A></H3>
+<PRE>
+int
+cupsGetJobs(cups_job_t **jobs,
+ const char *dest,
+ int myjobs,
+ int completed);
+</PRE>
+<H3><A NAME="10_18_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>jobs</TD><TD>A pointer to the job array pointer.</TD></TR>
+<TR><TD>dest</TD><TD>The destination name, or NULL if jobs for all
+ destinations are requested.</TD></TR>
+<TR><TD>myjobs</TD><TD>1 if only those jobs submitted by the current <CODE>
+cupsUser()</CODE> should be returned, 0 for jobs submitted by all users.</TD>
+</TR>
+<TR><TD>completed</TD><TD>1 if only completed jobs should be returned, 0
+ if only pending/processing jobs should be returned.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_18_3">Returns</A></H3>
+<P>The number of jobs.</P>
+<H3><A NAME="10_18_4">Description</A></H3>
+<P><CODE>cupsGetJobs()</CODE> creates an array of print jobs based on
+ the arguments supplied in the function call. The returned array should
+ be freed using the <CODE>cupsFreeJobs()</CODE> function.</P>
+<H3><A NAME="10_18_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_jobs;
+<A HREF="#cups_job_t">cups_job_t</A> *jobs;
+
+
+num_jobs = cupsGetJobs(&amp;jobs, NULL, 0, 0);
+
+printf(&quot;%d active job(s):\n&quot;, num_jobs);
+for (i = 0; i &lt; num_jobs; i ++)
+ printf(&quot;%-16.16s %-6d %-12.12s %s (%s)\n&quot;, jobs[i].dest, jobs[i].id,
+ jobs[i].user, jobs[i].title,
+ jobs[i].state != IPP_JOB_PENDING ? &quot;printing&quot; : &quot;pending&quot;);
+
+cupsFreeJobs(num_jobs, jobs);
+</PRE>
+<H3><A NAME="10_18_6">See Also</A></H3>
+<P> <A HREF="#cupsFreeJobs"><CODE>cupsFreeJobs()</CODE></A>, <A HREF="#cupsGetDests">
+<CODE>cupsGetDests()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetOption">cupsGetOption()</A></H2>
+<H3><A NAME="10_19_1">Usage</A></H3>
+<PRE>
+const char *
+cupsGetOption(const char *name,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_19_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>The name of the option.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options in the array.</TD></TR>
+<TR><TD>options</TD><TD>The options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_19_3">Returns</A></H3>
+<P>A pointer to the option values or <CODE>NULL</CODE> if the option is
+ not defined.</P>
+<H3><A NAME="10_19_4">Description</A></H3>
+<P><CODE>cupsGetOption()</CODE> returns the first occurrence of the
+ named option. If the option is not included in the options array then a
+ <CODE>NULL</CODE> pointer is returned.</P>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+cups_option_t *options;
+const char *media;
+
+...
+
+media = cupsGetOption(&quot;media&quot;, num_options, options);
+</PRE>
+<H3><A NAME="10_19_5">See Also</A></H3>
+<P> <A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>, <A HREF="#cupsEncodeOptions">
+<CODE>cupsEncodeOptions()</CODE></A>, <A HREF="#cupsFreeOptions"><CODE>
+cupsFreeOptions()</CODE></A>, <A HREF="#cupsMarkOptions"><CODE>
+cupsMarkOptions()</CODE></A>, <A HREF="#cupsParseOptions"><CODE>
+cupsParseOptions()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetPassword">cupsGetPassword()</A></H2>
+<H3><A NAME="10_20_1">Usage</A></H3>
+<PRE>
+const char *
+cupsGetPassword(const char *prompt);
+</PRE>
+<H3><A NAME="10_20_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>prompt</TD><TD>The prompt to display to the user.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_20_3">Returns</A></H3>
+<P>A pointer to the password that was entered or <CODE>NULL</CODE> if no
+ password was entered.</P>
+<H3><A NAME="10_20_4">Description</A></H3>
+<P><CODE>cupsGetPassword()</CODE> displays the prompt string and asks
+ the user for a password. The password text is not echoed to the user.</P>
+<H3><A NAME="10_20_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char *password;
+
+...
+
+password = cupsGetPassword(&quot;Please enter a password:&quot;);
+</PRE>
+<H3><A NAME="10_20_6">See Also</A></H3>
+<P> <A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>
+, <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#cupsSetPasswordCB">
+<CODE>cupsSetPasswordCB()</CODE></A>, <A HREF="#cupsSetServer"><CODE>
+cupsSetServer()</CODE></A>, <A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE>
+</A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsGetPPD">cupsGetPPD()</A></H2>
+<H3><A NAME="10_21_1">Usage</A></H3>
+<PRE>
+const char *
+cupsGetPPD(const char *printer);
+</PRE>
+<H3><A NAME="10_21_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>printer</TD><TD>The name of the printer.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_21_3">Returns</A></H3>
+<P>The name of a temporary file containing the PPD file or <CODE>NULL</CODE>
+ if the printer cannot be located or does not have a PPD file.</P>
+<H3><A NAME="10_21_4">Description</A></H3>
+<P><CODE>cupsGetPPD()</CODE> gets a copy of the PPD file for the named
+ printer. The printer name can be of the form &quot;printer&quot; or
+ &quot;printer@hostname&quot;.</P>
+<P>You should remove (unlink) the PPD file after you are done using it.
+ The filename is stored in a static buffer and will be overwritten with
+ each call to <CODE>cupsGetPPD()</CODE>.</P>
+<H3><A NAME="10_21_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD(&quot;printer@hostname&quot;);
+
+...
+
+unlink(ppd);
+</PRE>
+
+<!-- NEW PAGE -->
+<H2><A NAME="cupsGetPrinters">cupsGetPrinters()</A></H2>
+<H3><A NAME="10_22_1">Usage</A></H3>
+<PRE>
+int
+cupsGetPrinters(char ***printers);
+</PRE>
+<H3><A NAME="10_22_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>printers</TD><TD>Pointer to character pointer array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_22_3">Returns</A></H3>
+<P>The number of printer printers available.</P>
+<H3><A NAME="10_22_4">Description</A></H3>
+<P><CODE>cupsGetPrinters()</CODE> gets a list of the available printers.
+ The returned array should be freed using the <CODE>free()</CODE> when
+ it is no longer needed.</P>
+<H3><A NAME="10_22_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(&amp;printers);
+
+...
+
+if (num_printers &gt; 0)
+{
+ for (i = 0; i &lt; num_printers; i ++)
+ free(printers[i]);
+
+ free(printers);
+}
+</PRE>
+<H3><A NAME="10_22_6">See Also</A></H3>
+<P> <A HREF="#cupsGetClasses"><CODE>cupsGetClasses()</CODE></A> <A HREF="#cupsGetDefault">
+<CODE>cupsGetDefault()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangDefault">cupsLangDefault()</A></H2>
+<H3><A NAME="10_23_1">Usage</A></H3>
+<PRE>
+const char *
+cupsLangDefault(void);
+</PRE>
+<H3><A NAME="10_23_2">Returns</A></H3>
+<P>A pointer to the default language structure.</P>
+<H3><A NAME="10_23_3">Description</A></H3>
+<P><CODE>cupsLangDefault()</CODE> returns a language structure for the
+ default language. The default language is defined by the <CODE>LANG</CODE>
+ environment variable. If the specified language cannot be located then
+ the POSIX (English) locale is used.</P>
+<P>Call <CODE>cupsLangFree()</CODE> to free any memory associated with
+ the language structure when you are done.</P>
+<H3><A NAME="10_23_4">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+</PRE>
+<H3><A NAME="10_23_5">See Also</A></H3>
+<P> <A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsLangFlush">
+<CODE>cupsLangFlush()</CODE></A>, <A HREF="#cupsLangFree"><CODE>
+cupsLangFree()</CODE></A>, <A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE>
+</A>, <A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangEncoding">cupsLangEncoding()</A></H2>
+<H3><A NAME="10_24_1">Usage</A></H3>
+<PRE>
+char *
+cupsLangEncoding(cups_lang_t *language);
+</PRE>
+<H3><A NAME="10_24_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>language</TD><TD>The language structure.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_24_3">Returns</A></H3>
+<P>A pointer to the encoding string.</P>
+<H3><A NAME="10_24_4">Description</A></H3>
+<P><CODE>cupsLangEncoding()</CODE> returns the language encoding used
+ for the specified language, e.g. &quot;iso-8859-1&quot;, &quot;utf-8&quot;, etc.</P>
+<H3><A NAME="10_24_5">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+char *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+</PRE>
+<H3><A NAME="10_24_6">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangFlush">
+<CODE>cupsLangFlush()</CODE></A>, <A HREF="#cupsLangFree"><CODE>
+cupsLangFree()</CODE></A>, <A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE>
+</A>, <A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangFlush">cupsLangFlush()</A></H2>
+<H3><A NAME="10_25_1">Usage</A></H3>
+<PRE>
+void
+cupsLangFlush(void);
+</PRE>
+<H3><A NAME="10_25_2">Description</A></H3>
+<P><CODE>cupsLangFlush()</CODE> frees all language structures that have
+ been allocated.</P>
+<H3><A NAME="10_25_3">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+...
+
+cupsLangFlush();
+</PRE>
+<H3><A NAME="10_25_4">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsLangFree"><CODE>
+cupsLangFree()</CODE></A>, <A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE>
+</A>, <A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangFree">cupsLangFree()</A></H2>
+<H3><A NAME="10_26_1">Usage</A></H3>
+<PRE>
+void
+cupsLangFree(cups_lang_t *language);
+</PRE>
+<H3><A NAME="10_26_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>language</TD><TD>The language structure to free.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_26_3">Description</A></H3>
+<P><CODE>cupsLangFree()</CODE> frees the specified language structure.</P>
+<H3><A NAME="10_26_4">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+...
+
+cupsLangFree(language);
+</PRE>
+<H3><A NAME="10_26_5">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsLangFlush"><CODE>
+cupsLangFlush()</CODE></A>, <A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE>
+</A>, <A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangGet">cupsLangGet()</A></H2>
+<H3><A NAME="10_27_1">Usage</A></H3>
+<PRE>
+cups_lang_t *
+cupsLangGet(const char *name);
+</PRE>
+<H3><A NAME="10_27_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>The name of the locale.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_27_3">Returns</A></H3>
+<P>A pointer to a language structure.</P>
+<H3><A NAME="10_27_4">Description</A></H3>
+<P><CODE>cupsLangGet()</CODE> returns a language structure for the
+ specified locale. If the locale is not defined then the POSIX (English)
+ locale is substituted.</P>
+<H3><A NAME="10_27_5">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+
+...
+
+language = cupsLangGet(&quot;fr&quot;);
+
+...
+
+cupsLangFree(language);
+</PRE>
+<H3><A NAME="10_27_6">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsLangFlush"><CODE>
+cupsLangFlush()</CODE></A>, <A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE>
+</A>, <A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLangString">cupsLangString()</A></H2>
+<H3><A NAME="10_28_1">Usage</A></H3>
+<PRE>
+char *
+cupsLangString(cups_lang_t *language,
+ int message);
+</PRE>
+<H3><A NAME="10_28_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>language</TD><TD>The language to query.</TD></TR>
+<TR><TD>message</TD><TD>The message number.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_28_3">Returns</A></H3>
+<P>A pointer to the message string or <CODE>NULL</CODE> if the message
+ is not defined.</P>
+<H3><A NAME="10_28_4">Description</A></H3>
+<P><CODE>cupsLangString()</CODE> returns a pointer to the specified
+ message string in the specified language.</P>
+<H3><A NAME="10_28_5">Example</A></H3>
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+char *s;
+...
+
+language = cupsLangGet(&quot;fr&quot;);
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+</PRE>
+<H3><A NAME="10_28_6">See Also</A></H3>
+<P> <A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>, <A HREF="#cupsLangEncoding">
+<CODE>cupsLangEncoding()</CODE></A>, <A HREF="#cupsLangFlush"><CODE>
+cupsLangFlush()</CODE></A>, <A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE>
+</A>, <A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsLastError">cupsLastError()</A></H2>
+<H3><A NAME="10_29_1">Usage</A></H3>
+<PRE>
+ipp_status_t
+cupsLastError(void);
+</PRE>
+<H3><A NAME="10_29_2">Returns</A></H3>
+<P>An enumeration containing the last IPP error.</P>
+<H3><A NAME="10_29_3">Description</A></H3>
+<P><CODE>cupsLastError()</CODE> returns the last IPP error that
+ occurred. If no error occurred then it will return <CODE>IPP_OK</CODE>
+ or <CODE>IPP_OK_CONFLICT</CODE>.</P>
+<H3><A NAME="10_29_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+</PRE>
+<H3><A NAME="10_29_5">See Also</A></H3>
+<P> <A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>, <A HREF="#cupsPrintFile">
+<CODE>cupsPrintFile()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsMarkOptions">cupsMarkOptions()</A></H2>
+<H3><A NAME="10_30_1">Usage</A></H3>
+<PRE>
+int
+cupsMarkOptions(ppd_file_t *ppd,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_30_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file to mark.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options in the options array.</TD>
+</TR>
+<TR><TD>options</TD><TD>A pointer to the options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_30_3">Returns</A></H3>
+<P>The number of conflicts found.</P>
+<H3><A NAME="10_30_4">Description</A></H3>
+<P><CODE>cupsMarkOptions()</CODE> marks options in the PPD file. It also
+ handles mapping of IPP option names and values to PPD option names.</P>
+<H3><A NAME="10_30_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+<A HREF="#ppd_file_t">ppd_file_t</A> *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+</PRE>
+<H3><A NAME="10_30_6">See Also</A></H3>
+<P> <A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>, <A HREF="#cupsFreeOptions">
+<CODE>cupsFreeOptions()</CODE></A>, <A HREF="#cupsGetOption"><CODE>
+cupsGetOption()</CODE></A>, <A HREF="#cupsParseOptions"><CODE>
+cupsParseOptions()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsParseOptions">cupsParseOptions()</A></H2>
+<H3><A NAME="10_31_1">Usage</A></H3>
+<PRE>
+int
+cupsParseOptions(const char *arg,
+ int num_options,
+ cups_option_t **options);
+</PRE>
+<H3><A NAME="10_31_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>arg</TD><TD>The string containing one or more options.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options in the options array.</TD>
+</TR>
+<TR><TD>options</TD><TD>A pointer to the options array pointer.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_31_3">Returns</A></H3>
+<P>The new number of options in the array.</P>
+<H3><A NAME="10_31_4">Description</A></H3>
+<P><CODE>cupsParseOptions()</CODE> parses the specifies string for one
+ or more options of the form &quot;name=value&quot;, &quot;name&quot;, or &quot;noname&quot;. It can
+ be called multiple times to combine the options from several strings.</P>
+<H3><A NAME="10_31_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+...
+
+num_options = 0;
+options = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &amp;options);
+</PRE>
+<H3><A NAME="10_31_6">See Also</A></H3>
+<P> <A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>, <A HREF="#cupsFreeOptions">
+<CODE>cupsFreeOptions()</CODE></A>, <A HREF="#cupsGetOption"><CODE>
+cupsGetOption()</CODE></A>, <A HREF="#cupsMarkOptions"><CODE>
+cupsMarkOptions()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsPrintFile">cupsPrintFile()</A></H2>
+<H3><A NAME="10_32_1">Usage</A></H3>
+<PRE>
+int
+cupsPrintFile(const char *printer,
+ const char *filename,
+ const char *title,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_32_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>printer</TD><TD>The printer or class to print to.</TD></TR>
+<TR><TD>filename</TD><TD>The file to print.</TD></TR>
+<TR><TD>title</TD><TD>The job title.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options in the options array.</TD>
+</TR>
+<TR><TD>options</TD><TD>A pointer to the options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_32_3">Returns</A></H3>
+<P>The new job ID number or 0 on error.</P>
+<H3><A NAME="10_32_4">Description</A></H3>
+<P><CODE>cupsPrintFile()</CODE> sends a file to the specified printer or
+ class for printing. If the job cannot be printed the error code can be
+ found by calling <CODE>cupsLastError()</CODE>.</P>
+<H3><A NAME="10_32_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+int jobid;
+
+...
+
+jobid = cupsPrintFile(&quot;printer@hostname&quot;, &quot;filename.ps&quot;, &quot;Job Title&quot;,
+ num_options, options);
+</PRE>
+<H3><A NAME="10_32_6">See Also</A></H3>
+<P> <A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>, <A HREF="#cupsLastError">
+<CODE>cupsLastError()</CODE></A>, <A HREF="#cupsPrintFiles"><CODE>
+cupsPrintFiles()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsPrintFiles">cupsPrintFiles()</A></H2>
+<H3><A NAME="10_33_1">Usage</A></H3>
+<PRE>
+int
+cupsPrintFiles(const char *printer,
+ int num_files,
+ const char **files,
+ const char *title,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+<H3><A NAME="10_33_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>printer</TD><TD>The printer or class to print to.</TD></TR>
+<TR><TD>num_files</TD><TD>The number of files to print.</TD></TR>
+<TR><TD>files</TD><TD>The files to print.</TD></TR>
+<TR><TD>title</TD><TD>The job title.</TD></TR>
+<TR><TD>num_options</TD><TD>The number of options in the options array.</TD>
+</TR>
+<TR><TD>options</TD><TD>A pointer to the options array.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_33_3">Returns</A></H3>
+<P>The new job ID number or 0 on error.</P>
+<H3><A NAME="10_33_4">Description</A></H3>
+<P><CODE>cupsPrintFiles()</CODE> sends multiple files to the specified
+ printer or class for printing. If the job cannot be printed the error
+ code can be found by calling <CODE>cupsLastError()</CODE>.</P>
+<H3><A NAME="10_33_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_files;
+const char *files[100];
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+int jobid;
+
+...
+
+jobid = cupsPrintFiles(&quot;printer@hostname&quot;, num_files, files,
+ &quot;Job Title&quot;, num_options, options);
+</PRE>
+<H3><A NAME="10_33_6">See Also</A></H3>
+<P> <A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>, <A HREF="#cupsLastError">
+<CODE>cupsLastError()</CODE></A>, <A HREF="#cupsPrintFile"><CODE>
+cupsPrintFile()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsPutFd">cupsPutFd()</A></H2>
+<H3><A NAME="10_34_1">Usage</A></H3>
+<PRE>
+http_status_t
+cupsPutFd(http_t *http,
+ const char *resource,
+ int fd);
+</PRE>
+<H3><A NAME="10_34_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection to the server.</TD></TR>
+<TR><TD>resource</TD><TD>The resource name on the server.</TD></TR>
+<TR><TD>fd</TD><TD>The file descriptor to read from.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_34_3">Returns</A></H3>
+<P>The HTTP status code associated with the request.</P>
+<H3><A NAME="10_34_4">Description</A></H3>
+<P><CODE>cupsPutFd()</CODE> puts a file to the given HTTP server,
+ reading it from the specified file descriptor and performing any
+ authentication or encryption as required.</P>
+<H3><A NAME="10_34_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+int fd;
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+status = cupsPutFd(http, &quot;/admin/cupsd.conf&quot;, fd);
+
+httpClose(http);
+</PRE>
+<H3><A NAME="10_34_6">See Also</A></H3>
+<P> <A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>, <A HREF="#cupsGetFile">
+<CODE>cupsGetFile()</CODE></A>, <A HREF="#cupsPutFile"><CODE>
+cupsPutFile()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsPutFile">cupsPutFile()</A></H2>
+<H3><A NAME="10_35_1">Usage</A></H3>
+<PRE>
+http_status_t
+cupsPutFile(http_t *http,
+ const char *resource,
+ const char *filename);
+</PRE>
+<H3><A NAME="10_35_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection to the server.</TD></TR>
+<TR><TD>resource</TD><TD>The resource name on the server.</TD></TR>
+<TR><TD>filename</TD><TD>The filename to read from.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_35_3">Returns</A></H3>
+<P>The HTTP status code associated with the request.</P>
+<H3><A NAME="10_35_4">Description</A></H3>
+<P><CODE>cupsPutFile()</CODE> puts a file on the given HTTP server,
+ reading it from the specified filename and performing any
+ authentication or encryption as required.</P>
+<H3><A NAME="10_35_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+status = cupsPutFile(http, &quot;/admin/cupsd.conf&quot;, filename);
+
+httpClose(http);
+</PRE>
+<H3><A NAME="10_35_6">See Also</A></H3>
+<P> <A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>, <A HREF="#cupsGetFile">
+<CODE>cupsGetFile()</CODE></A>, <A HREF="#cupsPutFd"><CODE>cupsPutFd()</CODE>
+</A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterClose">cupsRasterClose()</A></H2>
+<H3><A NAME="10_36_1">Usage</A></H3>
+<PRE>
+void
+cupsRasterClose(cups_raster_t *ras);
+</PRE>
+<H3><A NAME="10_36_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ras</TD><TD>The raster stream to close.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_36_3">Description</A></H3>
+<P><CODE>cupsRasterClose()</CODE> closes the specified raster stream.</P>
+<H3><A NAME="10_36_4">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+
+...
+
+cupsRasterClose(ras);
+</PRE>
+<H3><A NAME="10_36_5">See Also</A></H3>
+<P> <A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>, <A HREF="#cupsRasterReadHeader">
+<CODE>cupsRasterReadHeader()</CODE></A>, <A HREF="#cupsRasterReadPixels">
+<CODE>cupsRasterReadPixels()</CODE></A>, <A HREF="#cupsRasterWriteHeader">
+<CODE>cupsRasterWriteHeader()</CODE></A>, <A HREF="#cupsRasterWritePixels">
+<CODE>cupsRasterWritePixels()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterOpen">cupsRasterOpen()</A></H2>
+<H3><A NAME="10_37_1">Usage</A></H3>
+<PRE>
+cups_raster_t *
+cupsRasterOpen(int fd,
+ cups_mode_t mode);
+</PRE>
+<H3><A NAME="10_37_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>fd</TD><TD>The file descriptor to use.</TD></TR>
+<TR><TD>mode</TD><TD>The mode to use; <CODE>CUPS_RASTER_READ</CODE> or <CODE>
+CUPS_RASTER_WRITE</CODE>.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_37_3">Returns</A></H3>
+<P>A pointer to a raster stream or <CODE>NULL</CODE> if there was an
+ error.</P>
+<H3><A NAME="10_37_4">Description</A></H3>
+<P><CODE>cupsRasterOpen()</CODE> opens a raster stream for reading or
+ writing.</P>
+<H3><A NAME="10_37_5">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+</PRE>
+<H3><A NAME="10_37_6">See Also</A></H3>
+<P> <A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>, <A HREF="#cupsRasterReadHeader">
+<CODE>cupsRasterReadHeader()</CODE></A>, <A HREF="#cupsRasterReadPixels">
+<CODE>cupsRasterReadPixels()</CODE></A>, <A HREF="#cupsRasterWriteHeader">
+<CODE>cupsRasterWriteHeader()</CODE></A>, <A HREF="#cupsRasterWritePixels">
+<CODE>cupsRasterWritePixels()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterReadHeader">cupsRasterReadHeader()</A></H2>
+<H3><A NAME="10_38_1">Usage</A></H3>
+<PRE>
+unsigned
+cupsRasterReadHeader(cups_raster_t *ras,
+ cups_page_header_t *header);
+</PRE>
+<H3><A NAME="10_38_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ras</TD><TD>The raster stream to read from.</TD></TR>
+<TR><TD>header</TD><TD>A pointer to a page header structure to read
+ into.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_38_3">Returns</A></H3>
+<P>1 on success, 0 on EOF or error.</P>
+<H3><A NAME="10_38_4">Description</A></H3>
+<P><CODE>cupsRasterReadHeader()</CODE> reads a page header from the
+ specified raster stream.</P>
+<H3><A NAME="10_38_5">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ...
+
+ for (line = 0; line &lt; header.cupsHeight; line ++)
+ {
+ cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+ ...
+ }
+}
+</PRE>
+<H3><A NAME="10_38_6">See Also</A></H3>
+<P> <A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>, <A HREF="#cupsRasterOpen">
+<CODE>cupsRasterOpen()</CODE></A>, <A HREF="#cupsRasterReadPixels"><CODE>
+cupsRasterReadPixels()</CODE></A>, <A HREF="#cupsRasterWriteHeader"><CODE>
+cupsRasterWriteHeader()</CODE></A>, <A HREF="#cupsRasterWritePixels"><CODE>
+cupsRasterWritePixels()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterReadPixels">cupsRasterReadPixels()</A></H2>
+<H3><A NAME="10_39_1">Usage</A></H3>
+<PRE>
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+ unsigned char *pixels,
+ unsigned length);
+</PRE>
+<H3><A NAME="10_39_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ras</TD><TD>The raster stream to read from.</TD></TR>
+<TR><TD>pixels</TD><TD>The pointer to a pixel buffer.</TD></TR>
+<TR><TD>length</TD><TD>The number of bytes of pixel data to read.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_39_3">Returns</A></H3>
+<P>The number of bytes read or 0 on EOF or error.</P>
+<H3><A NAME="10_39_4">Description</A></H3>
+<P><CODE>cupsRasterReadPixels()</CODE> reads pixel data from the
+ specified raster stream.</P>
+<H3><A NAME="10_39_5">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ...
+
+ for (line = 0; line &lt; header.cupsHeight; line ++)
+ {
+ cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+ ...
+ }
+}
+</PRE>
+<H3><A NAME="10_39_6">See Also</A></H3>
+<P> <A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>, <A HREF="#cupsRasterOpen">
+<CODE>cupsRasterOpen()</CODE></A>, <A HREF="#cupsRasterReadHeader"><CODE>
+cupsRasterReadHeader()</CODE></A>, <A HREF="#cupsRasterWriteHeader"><CODE>
+cupsRasterWriteHeader()</CODE></A>, <A HREF="#cupsRasterWritePixels"><CODE>
+cupsRasterWritePixels()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterWriteHeader">cupsRasterWriteHeader()</A></H2>
+<H3><A NAME="10_40_1">Usage</A></H3>
+<PRE>
+unsigned
+cupsRasterWriteHeader(cups_raster_t *ras,
+ cups_page_header_t *header);
+</PRE>
+<H3><A NAME="10_40_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ras</TD><TD>The raster stream to write to.</TD></TR>
+<TR><TD>header</TD><TD>A pointer to the page header to write.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_40_3">Returns</A></H3>
+<P>1 on success, 0 on error.</P>
+<H3><A NAME="10_40_4">Description</A></H3>
+<P><CODE>cupsRasterWriteHeader()</CODE> writes the specified page header
+ to a raster stream.</P>
+<H3><A NAME="10_40_5">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &amp;header);
+
+for (line = 0; line &lt; header.cupsHeight; line ++)
+{
+ ...
+
+ cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+</PRE>
+<H3><A NAME="10_40_6">See Also</A></H3>
+<P> <A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>, <A HREF="#cupsRasterOpen">
+<CODE>cupsRasterOpen()</CODE></A>, <A HREF="#cupsRasterReadHeader"><CODE>
+cupsRasterReadHeader()</CODE></A>, <A HREF="#cupsRasterReadPixels"><CODE>
+cupsRasterReadPixels()</CODE></A>, <A HREF="#cupsRasterWritePixels"><CODE>
+cupsRasterWritePixels()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsRasterWritePixels">cupsRasterWritePixels()</A></H2>
+<H3><A NAME="10_41_1">Usage</A></H3>
+<PRE>
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+ unsigned char *pixels,
+ unsigned length);
+</PRE>
+<H3><A NAME="10_41_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ras</TD><TD>The raster stream to write to.</TD></TR>
+<TR><TD>pixels</TD><TD>The pixel data to write.</TD></TR>
+<TR><TD>length</TD><TD>The number of bytes to write.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_41_3">Returns</A></H3>
+<P>The number of bytes written.</P>
+<H3><A NAME="10_41_4">Description</A></H3>
+<P><CODE>cupsRasterWritePixels()</CODE> writes the specified pixel data
+ to a raster stream.</P>
+<H3><A NAME="10_41_5">Example</A></H3>
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &amp;header);
+
+for (line = 0; line &lt; header.cupsHeight; line ++)
+{
+ ...
+
+ cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+</PRE>
+<H3><A NAME="10_41_6">See Also</A></H3>
+<P> <A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>, <A HREF="#cupsRasterOpen">
+<CODE>cupsRasterOpen()</CODE></A>, <A HREF="#cupsRasterReadHeader"><CODE>
+cupsRasterReadHeader()</CODE></A>, <A HREF="#cupsRasterReadPixels"><CODE>
+cupsRasterReadPixels()</CODE></A>, <A HREF="#cupsRasterWriteHeader"><CODE>
+cupsRasterWriteHeader()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsServer">cupsServer()</A></H2>
+<H3><A NAME="10_42_1">Usage</A></H3>
+<PRE>
+const char *
+cupsServer(void);
+</PRE>
+<H3><A NAME="10_42_2">Returns</A></H3>
+<P>A pointer to the default server name.</P>
+<H3><A NAME="10_42_3">Description</A></H3>
+<P><CODE>cupsServer()</CODE> returns a pointer to the default server
+ name. The server name is stored in a static location and will be
+ overwritten with every call to <CODE>cupsServer()</CODE>.</P>
+<P>The default server is determined from the following locations:</P>
+<OL>
+<LI>The <CODE>CUPS_SERVER</CODE> environment variable,</LI>
+<LI>The <CODE>ServerName</CODE> directive in the<VAR> client.conf</VAR>
+ file,</LI>
+<LI>The default host, &quot;localhost&quot;.</LI>
+</OL>
+<H3><A NAME="10_42_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *server;
+
+server = cupsServer();
+</PRE>
+<H3><A NAME="10_42_5">See Also</A></H3>
+<P> <A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>, <A HREF="#cupsSetPasswordCB">
+<CODE>cupsSetPasswordCB()</CODE></A>, <A HREF="#cupsSetServer"><CODE>
+cupsSetServer()</CODE></A>, <A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE>
+</A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsSetDests">cupsSetDests()</A></H2>
+<H3><A NAME="10_43_1">Usage</A></H3>
+<PRE>
+void
+cupsSetDests(int num_dests,
+ cups_dest_t *dests);
+</PRE>
+<H3><A NAME="10_43_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>num_dests</TD><TD>Number of destinations.</TD></TR>
+<TR><TD>dests</TD><TD>Array of destinations.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_43_3">Description</A></H3>
+<P><CODE>cupsSetDests()</CODE> saves the destination array to disk. If
+ the current UID is 0, the destinations are saved in the<VAR>
+ /etc/cups/lpoptions</VAR> file, otherwise they are saved in the<VAR>
+ ~/.lpoptions</VAR> file. This function is typically used to save the
+ default options and instances that are set by the user.</P>
+<H3><A NAME="10_43_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+
+...
+
+cupsSetDests(num_dests, dests);
+</PRE>
+<H3><A NAME="10_43_5">See Also</A></H3>
+<P> <A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsSetEncryption">cupsSetEncryption()</A></H2>
+<H3><A NAME="10_44_1">Usage</A></H3>
+<PRE>
+void
+cupsSetEncryption(http_encryption_t encryption);
+</PRE>
+<H3><A NAME="10_44_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>encryption</TD><TD>The type of encryption to use.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_44_3">Description</A></H3>
+<P><CODE>cupsSetEncryption()</CODE> sets the default type of encryption
+ to use when connecting with the print server.</P>
+<H3><A NAME="10_44_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+</PRE>
+<H3><A NAME="10_44_5">See Also</A></H3>
+<P> <A HREF="#cupsEncryption"><CODE>cupsEncryption()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsSetPasswordCB">cupsSetPasswordCB()</A></H2>
+<H3><A NAME="10_45_1">Usage</A></H3>
+<PRE>
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+</PRE>
+<H3><A NAME="10_45_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>cb</TD><TD>The password callback function.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_45_3">Description</A></H3>
+<P><CODE>cupsSetPasswordCB()</CODE> sets the callback function to use
+ when asking the user for a password. The callback function must accept
+ a single character string pointer (the prompt string) and return <CODE>
+NULL</CODE> if the user did not enter a password string or a pointer to
+ the password string otherwise.</P>
+<H3><A NAME="10_45_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *
+my_password_cb(const char *prompt)
+{
+ return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword(&quot;Please enter a password:&quot;);
+</PRE>
+<H3><A NAME="10_45_5">See Also</A></H3>
+<P> <A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>
+, <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#cupsSetServer">
+<CODE>cupsSetServer()</CODE></A>, <A HREF="#cupsSetUser"><CODE>
+cupsSetUser()</CODE></A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsSetServer">cupsSetServer()</A></H2>
+<H3><A NAME="10_46_1">Usage</A></H3>
+<PRE>
+void
+cupsSetServer(const char *server);
+</PRE>
+<H3><A NAME="10_46_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>server</TD><TD>The default server to use.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_46_3">Description</A></H3>
+<P><CODE>cupsSetServer()</CODE> sets the default server to use for the
+ CUPS API. If the <CODE>server</CODE> argument is <CODE>NULL</CODE>, the
+ default server is used.</P>
+<H3><A NAME="10_46_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+cupsSetServer(&quot;foo.bar.com&quot;);
+</PRE>
+<H3><A NAME="10_46_5">See Also</A></H3>
+<P> <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#cupsSetPasswordCB">
+<CODE>cupsSetPasswordCB()</CODE></A>, <A HREF="#cupsSetUser"><CODE>
+cupsSetUser()</CODE></A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsSetUser">cupsSetUser()</A></H2>
+<H3><A NAME="10_47_1">Usage</A></H3>
+<PRE>
+void
+cupsSetUser(const char *user);
+</PRE>
+<H3><A NAME="10_47_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>user</TD><TD>The user name string to use.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_47_3">Description</A></H3>
+<P><CODE>cupsSetUser()</CODE> sets the default user name for
+ authentication. If the <CODE>user</CODE> argument is <CODE>NULL</CODE>
+ then the current login user is used.</P>
+<H3><A NAME="10_47_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+cupsSetUser(&quot;root&quot;);
+</PRE>
+<H3><A NAME="10_47_5">See Also</A></H3>
+<P> <A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>
+, <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#cupsSetPasswordCB">
+<CODE>cupsSetPasswordCB()</CODE></A>, <A HREF="#cupsSetServer"><CODE>
+cupsSetServer()</CODE></A>, <A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsTempFd">cupsTempFd()</A></H2>
+<H3><A NAME="10_48_1">Usage</A></H3>
+<PRE>
+int
+cupsTempFd(char *filename,
+ int length);
+</PRE>
+<H3><A NAME="10_48_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>filename</TD><TD>The character string to hold the temporary
+ filename.</TD></TR>
+<TR><TD>length</TD><TD>The size of the filename string in bytes.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_48_3">Returns</A></H3>
+<P>A file descriptor open for reading and writing.</P>
+<H3><A NAME="10_48_4">Description</A></H3>
+<P><CODE>cupsTempFd()</CODE> create a temporary filename in the<VAR>
+ /var/tmp</VAR> directory or the directory specified by the <CODE>TMPDIR</CODE>
+ environment variable.</P>
+<H3><A NAME="10_48_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int fd;
+char filename[256];
+
+fd = cupsTempFd(filename, sizeof(filename));
+</PRE>
+<H3><A NAME="10_48_6">See Also</A></H3>
+<P> <A HREF="#cupsTempFile"><CODE>cupsTempFile()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsTempFile">cupsTempFile()</A></H2>
+<H3><A NAME="10_49_1">Usage</A></H3>
+<PRE>
+char *
+cupsTempFile(char *filename,
+ int length);
+</PRE>
+<H3><A NAME="10_49_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>filename</TD><TD>The character string to hold the temporary
+ filename.</TD></TR>
+<TR><TD>length</TD><TD>The size of the filename string in bytes.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_49_3">Returns</A></H3>
+<P>A pointer to <CODE>filename</CODE>.</P>
+<H3><A NAME="10_49_4">Description</A></H3>
+<P><CODE>cupsTempFile()</CODE> creates a temporary filename in the<VAR>
+ /var/tmp</VAR> directory or the directory specified by the <CODE>TMPDIR</CODE>
+ environment variable.</P>
+<H3><A NAME="10_49_5">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+</PRE>
+<H3><A NAME="10_49_6">See Also</A></H3>
+<P> <A HREF="#cupsTempFd"><CODE>cupsTempFd()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="cupsUser">cupsUser()</A></H2>
+<H3><A NAME="10_50_1">Usage</A></H3>
+<PRE>
+const char *
+cupsUser(void);
+</PRE>
+<H3><A NAME="10_50_2">Returns</A></H3>
+<P>A pointer to the current username or <CODE>NULL</CODE> if the user ID
+ is undefined.</P>
+<H3><A NAME="10_50_3">Description</A></H3>
+<P><CODE>cupsUser()</CODE> returns the name associated with the current
+ user ID as reported by the <CODE>getuid()</CODE> system call.</P>
+<H3><A NAME="10_50_4">Example</A></H3>
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *user;
+
+user = cupsUser();
+</PRE>
+<H3><A NAME="10_50_5">See Also</A></H3>
+<P> <A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>
+, <A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>, <A HREF="#cupsServer">
+<CODE>cupsServer()</CODE></A>, <A HREF="#cupsSetServer"><CODE>
+cupsSetServer()</CODE></A>, <A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE>
+</A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpBlocking">httpBlocking()</A></H2>
+<H3><A NAME="10_51_1">Usage</A></H3>
+<PRE>
+void
+httpBlocking(http_t *http,
+ int blocking)
+</PRE>
+<H3><A NAME="10_51_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>blocking</TD><TD>0 if the connection should be non-blocking, 1
+ if it should be blocking</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_51_3">Description</A></H3>
+<P>The <CODE>httpBlocking()</CODE> function sets the blocking mode for
+ the HTTP connection. By default HTTP connections will block (stop) the
+ client program until data is available or can be sent to the server.</P>
+<H3><A NAME="10_51_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+http = httpConnect(&quot;server&quot;, port);
+httpBlocking(http, 0);
+</PRE>
+<H3><A NAME="10_51_5">See Also</A></H3>
+ <A HREF="#httpCheck"><CODE>httpCheck()</CODE></A>, <A HREF="#httpConnect">
+<CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpCheck">httpCheck()</A></H2>
+<H3><A NAME="10_52_1">Usage</A></H3>
+<PRE>
+int
+httpCheck(http_t *http);
+</PRE>
+<H3><A NAME="10_52_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_52_3">Returns</A></H3>
+<P>0 if there is no data pending, 1 otherwise.</P>
+<H3><A NAME="10_52_4">Description</A></H3>
+<P>The <CODE>httpCheck()</CODE> function checks to see if there is any
+ data pending on an HTTP connection.</P>
+<H3><A NAME="10_52_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+if (httpCheck(http))
+{
+ ... do something ...
+}
+</PRE>
+<H3><A NAME="10_52_6">See Also</A></H3>
+ <A HREF="#httpBlocking"><CODE>httpBlocking()</CODE></A>, <A HREF="#httpConnect">
+<CODE>httpConnect()</CODE></A>, <A HREF="#httpGets"><CODE>httpGets()</CODE>
+</A>, <A HREF="#httpRead"><CODE>httpRead()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpClearFields">httpClearFields()</A></H2>
+<H3><A NAME="10_53_1">Usage</A></H3>
+<PRE>
+void
+httpClearFields(http_t *http)
+</PRE>
+<H3><A NAME="10_53_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_53_3">Description</A></H3>
+<P>The <CODE>httpClearFields()</CODE> function clears all HTTP request
+ fields for the HTTP connection.</P>
+<H3><A NAME="10_53_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpClearFields(http);
+</PRE>
+<H3><A NAME="10_53_5">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpGetField">
+<CODE>httpGetField()</CODE></A>, <A HREF="#httpSetField"><CODE>
+httpSetField()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpClose">httpClose()</A></H2>
+<H3><A NAME="10_54_1">Usage</A></H3>
+<PRE>
+void
+httpClose(http_t *http);
+</PRE>
+<H3><A NAME="10_54_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_54_3">Description</A></H3>
+<P>The <CODE>httpClose()</CODE> function closes an active HTTP
+ connection.</P>
+<H3><A NAME="10_54_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpClose(http);
+</PRE>
+<H3><A NAME="10_54_5">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpConnect">httpConnect()</A></H2>
+<H3><A NAME="10_55_1">Usage</A></H3>
+<PRE>
+http_t *
+httpConnect(const char *hostname,
+ int port);
+</PRE>
+<H3><A NAME="10_55_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>hostname</TD><TD>The name or IP address of the server to connect
+ to</TD></TR>
+<TR><TD>port</TD><TD>The port number to use</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_55_3">Returns</A></H3>
+<P>A pointer to a HTTP connection structure or NULL if the connection
+ could not be made.</P>
+<H3><A NAME="10_55_4">Description</A></H3>
+<P>The <CODE>httpConnect()</CODE> function opens a HTTP connection to
+ the specified server and port.</P>
+<H3><A NAME="10_55_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+http = httpConnect(cupsServer(), ippPort());
+</PRE>
+<H3><A NAME="10_55_6">See Also</A></H3>
+ <A HREF="#httpClose"><CODE>httpClose()</CODE></A>, <A HREF="#httpConnectEncrypt">
+<CODE>httpConnectEncrypt()</CODE></A>, <A HREF="#httpGet"><CODE>
+httpGet()</CODE></A>, <A HREF="#httpGets"><CODE>httpGets()</CODE></A>, <A
+HREF="#httpPost"><CODE>httpPost()</CODE></A>, <A HREF="#httpRead"><CODE>
+httpRead()</CODE></A>, <A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpConnectEncrypt">httpConnectEncrypt()</A></H2>
+<H3><A NAME="10_56_1">Usage</A></H3>
+<PRE>
+http_t *
+httpConnectEncrypt(const char *hostname,
+ int port,
+ http_encryption_t encryption);
+</PRE>
+<H3><A NAME="10_56_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>hostname</TD><TD>The name or IP address of the server to connect
+ to</TD></TR>
+<TR><TD>port</TD><TD>The port number to use</TD></TR>
+<TR><TD>encryption</TD><TD>The level of encryption to use</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_56_3">Returns</A></H3>
+<P>A pointer to a HTTP connection structure or NULL if the connection
+ could not be made.</P>
+<H3><A NAME="10_56_4">Description</A></H3>
+<P>The <CODE>httpConnectEncrypt()</CODE> function opens a HTTP
+ connection to the specified server, port, and encryption.</P>
+<H3><A NAME="10_56_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+</PRE>
+<H3><A NAME="10_56_6">See Also</A></H3>
+ <A HREF="#httpClose"><CODE>httpClose()</CODE></A>, <A HREF="#httpConnect">
+<CODE>httpConnect()</CODE></A>, <A HREF="#httpGet"><CODE>httpGet()</CODE>
+</A>, <A HREF="#httpGets"><CODE>httpGets()</CODE></A>, <A HREF="#httpPost">
+<CODE>httpPost()</CODE></A>, <A HREF="#httpRead"><CODE>httpRead()</CODE></A>
+, <A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpDecode64">httpDecode64()</A></H2>
+<H3><A NAME="10_57_1">Usage</A></H3>
+<PRE>
+char *
+httpDecode64(char *out,
+ const char *in);
+</PRE>
+<H3><A NAME="10_57_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>out</TD><TD>The output string</TD></TR>
+<TR><TD>in</TD><TD>The input string</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_57_3">Returns</A></H3>
+<P>A pointer to the decoded string.</P>
+<H3><A NAME="10_57_4">Description</A></H3>
+<P>The <CODE>httpDecode64()</CODE> function decodes a base-64 encoded
+ string to the original string.</P>
+<H3><A NAME="10_57_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+</PRE>
+<H3><A NAME="10_57_6">See Also</A></H3>
+ <A HREF="#httpEncode64"><CODE>httpEncode64()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpDelete">httpDelete()</A></H2>
+<H3><A NAME="10_58_1">Usage</A></H3>
+<PRE>
+int
+httpDelete(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_58_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to delete</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_58_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_58_4">Description</A></H3>
+<P>The <CODE>httpDelete()</CODE> function sends a HTTP DELETE request to
+ the server.</P>
+<H3><A NAME="10_58_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpDelete(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_58_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpEncode64">httpEncode64()</A></H2>
+<H3><A NAME="10_59_1">Usage</A></H3>
+<PRE>
+char *
+httpEncode64(char *out,
+ const char *in);
+</PRE>
+<H3><A NAME="10_59_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>out</TD><TD>The output string</TD></TR>
+<TR><TD>in</TD><TD>The input string</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_59_3">Returns</A></H3>
+<P>A pointer to the encoded string.</P>
+<H3><A NAME="10_59_4">Description</A></H3>
+<P>The <CODE>httpEncode64()</CODE> function decodes a base-64 encoded
+ string to the original string.</P>
+<H3><A NAME="10_59_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+</PRE>
+<H3><A NAME="10_59_6">See Also</A></H3>
+ <A HREF="#httpDecode64"><CODE>httpDecode64()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpEncryption">httpEncryption()</A></H2>
+<H3><A NAME="10_60_1">Usage</A></H3>
+<PRE>
+int
+httpEncryption(http_t *http,
+ http_encryption_t encryption);
+</PRE>
+<H3><A NAME="10_60_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection.</TD></TR>
+<TR><TD>encryption</TD><TD>The desired level of encryption.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_60_3">Returns</A></H3>
+<P>0 on success, -1 on error.</P>
+<H3><A NAME="10_60_4">Description</A></H3>
+<P><CODE>httpEncryption()</CODE> sets the encryption level for the HTTP
+ connection.</P>
+<H3><A NAME="10_60_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+</PRE>
+<H3><A NAME="10_60_6">See Also</A></H3>
+<P> <A HREF="#httpConnectEncrypt"><CODE>httpConnectEncrypt()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpError">httpError()</A></H2>
+<H3><A NAME="10_61_1">Usage</A></H3>
+<PRE>
+int
+httpError(http_t *http);
+</PRE>
+<H3><A NAME="10_61_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_61_3">Returns</A></H3>
+<P>The last error that occurred or 0 if no error has occurred.</P>
+<H3><A NAME="10_61_4">Description</A></H3>
+<P>The <CODE>httpError()</CODE> function returns the last error that
+ occurred on the HTTP connection.</P>
+<H3><A NAME="10_61_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+if (httpError(http))
+{
+ ... show an error message ...
+}
+</PRE>
+<H3><A NAME="10_61_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpFlush">httpFlush()</A></H2>
+<H3><A NAME="10_62_1">Usage</A></H3>
+<PRE>
+void
+httpFlush(http_t *http);
+</PRE>
+<H3><A NAME="10_62_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_62_3">Description</A></H3>
+<P>The <CODE>httpFlush()</CODE> function flushes any remaining data left
+ from a GET or POST operation.</P>
+<H3><A NAME="10_62_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpFlush(http);
+</PRE>
+<H3><A NAME="10_62_5">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<!-- NEW PAGE -->
+<H2><A NAME="httpGet">httpGet()</A></H2>
+<H3><A NAME="10_63_1">Usage</A></H3>
+<PRE>
+int
+httpGet(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_63_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to get</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_63_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_63_4">Description</A></H3>
+<P>The <CODE>httpGet()</CODE> function sends a HTTP GET request to the
+ server.</P>
+<H3><A NAME="10_63_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+httpGet(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_63_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpGets">httpGets()</A></H2>
+<H3><A NAME="10_64_1">Usage</A></H3>
+<PRE>
+char *
+httpGets(char *line,
+ int length,
+ http_t *http)
+</PRE>
+<H3><A NAME="10_64_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>line</TD><TD>The string to fill with a line from the HTTP
+ connection</TD></TR>
+<TR><TD>length</TD><TD>The maximum length of the string</TD></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_64_3">Returns</A></H3>
+<P>A pointer to the string or NULL if no line could be retrieved.</P>
+<H3><A NAME="10_64_4">Description</A></H3>
+<P>The <CODE>httpGets()</CODE> function is used to read a request line
+ from the HTTP connection. It is not normally used by a client program.</P>
+<H3><A NAME="10_64_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+char line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+ ... process the line ...
+}
+</PRE>
+<H3><A NAME="10_64_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpUpdate">
+<CODE>httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpGetDateString">httpGetDateString()</A></H2>
+<H3><A NAME="10_65_1">Usage</A></H3>
+<PRE>
+const char *
+httpGetDateString(time_t time)
+</PRE>
+<H3><A NAME="10_65_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>time</TD><TD>The UNIX date/time value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_65_3">Returns</A></H3>
+<P>A pointer to a static string containing the HTTP date/time string for
+ the specified UNIX time value.</P>
+<H3><A NAME="10_65_4">Description</A></H3>
+<P>The <CODE>httpGetDateString()</CODE> function generates a date/time
+ string suitable for HTTP requests from a UNIX time value.</P>
+<H3><A NAME="10_65_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+puts(httpGetDateString(time(NULL)));
+</PRE>
+<H3><A NAME="10_65_6">See Also</A></H3>
+ <A HREF="#httpGetDateTime"><CODE>httpGetDateTime()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpGetDateTime">httpGetDateTime()</A></H2>
+<H3><A NAME="10_66_1">Usage</A></H3>
+<PRE>
+time_t
+httpGetDateTime(const char *date)
+</PRE>
+<H3><A NAME="10_66_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>date</TD><TD>The HTTP date/time string</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_66_3">Returns</A></H3>
+<P>A UNIX time value.</P>
+<H3><A NAME="10_66_4">Description</A></H3>
+<P>The <CODE>httpGetDateTime()</CODE> function converts a HTTP date/time
+ string to a UNIX time value.</P>
+<H3><A NAME="10_66_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+printf(&quot;%d\n&quot;, httpGetDateTime(&quot;Fri, 30 June 2000 12:34:56 GMT&quot;));
+</PRE>
+<H3><A NAME="10_66_6">See Also</A></H3>
+ <A HREF="#httpGetDateString"><CODE>httpGetDateString()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpGetField">httpGetField()</A></H2>
+<H3><A NAME="10_67_1">Usage</A></H3>
+<PRE>
+const char *
+httpGetField(http_t *http,
+ http_field_t field);
+</PRE>
+<H3><A NAME="10_67_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>field</TD><TD>The HTTP field</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_67_3">Returns</A></H3>
+<P>A pointer to the field value string.</P>
+<H3><A NAME="10_67_4">Description</A></H3>
+<P>The <CODE>httpGetField()</CODE> function returns the current value
+ for the specified HTTP field.</P>
+<H3><A NAME="10_67_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+httpGet(http, &quot;/some/uri&quot;);
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+</PRE>
+<H3><A NAME="10_67_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpGetSubField">
+<CODE>httpGetSubField()</CODE></A>, <A HREF="#httpSetField"><CODE>
+httpSetField()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpGetHostByName">httpGetHostByName()</A></H2>
+<H3><A NAME="10_68_1">Usage</A></H3>
+<PRE>
+struct hostent *
+httpGetHostByName(const char *name);
+</PRE>
+<H3><A NAME="10_68_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>name</TD><TD>Name or IP address to lookup.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_68_3">Returns</A></H3>
+<P>NULL if the host could not be found or a pointer to a host entry
+ containing one or more addresses.</P>
+<H3><A NAME="10_68_4">Description</A></H3>
+<P><CODE>httpGetHostByName()</CODE> is a portable wrapper around the <CODE>
+gethostbyname()</CODE> function which handles both hostnames and IP
+ addresses.</P>
+<H3><A NAME="10_68_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+struct hostent *hostaddr;
+
+hostaddr = httpGetHostByName(&quot;foo.bar.com&quot;);
+</PRE>
+
+<!-- NEW PAGE -->
+<H2><A NAME="httpGetLength">httpGetLength()</A></H2>
+<H3><A NAME="10_69_1">Usage</A></H3>
+<PRE>
+int
+httpGetLength(http_t *http);
+</PRE>
+<H3><A NAME="10_69_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_69_3">Returns</A></H3>
+<P>The content length of the response or MAX_INT if chunking is used.</P>
+<H3><A NAME="10_69_4">Description</A></H3>
+<P><CODE>httpGetLength()</CODE> returns the content length of a
+ response.</P>
+<H3><A NAME="10_69_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+printf(&quot;The length of the response is %d bytes.\n&quot;, httpGetLength(http));
+</PRE>
+<H3><A NAME="10_69_6">See Also</A></H3>
+<P> <A HREF="#httpGet"><CODE>httpGet()</CODE></A>, <A HREF="#httpPost"><CODE>
+httpPost()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpGetSubField">httpGetSubField()</A></H2>
+<H3><A NAME="10_70_1">Usage</A></H3>
+<PRE>
+const char *
+httpGetSubField(http_t *http,
+ http_field_t field,
+ const char *name,
+ char *value);
+</PRE>
+<H3><A NAME="10_70_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection.</TD></TR>
+<TR><TD>field</TD><TD>The HTTP field.</TD></TR>
+<TR><TD>name</TD><TD>The name of the subfield.</TD></TR>
+<TR><TD>value</TD><TD>The string to hold the subfield value.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_70_3">Returns</A></H3>
+<P>A pointer to the subfield value string or NULL if it does not exist.</P>
+<H3><A NAME="10_70_4">Description</A></H3>
+<P>The <CODE>httpGetSubField()</CODE> function returns a subfield value
+ from the specified HTTP field. The destination string buffer must be at
+ least <CODE>HTTP_MAX_VALUE</CODE> bytes in length.</P>
+<H3><A NAME="10_70_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+char value[HTTP_MAX_VALUE];
+
+httpGet(http, &quot;/some/uri&quot;);
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetSubField(http, HTTP_FIELD_CONTENT_TYPE, &quot;charset&quot;, value));
+</PRE>
+<H3><A NAME="10_70_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpGetField">
+<CODE>httpGetField()</CODE></A>, <A HREF="#httpSetField"><CODE>
+httpSetField()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpHead">httpHead()</A></H2>
+<H3><A NAME="10_71_1">Usage</A></H3>
+<PRE>
+int
+httpHead(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_71_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to head</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_71_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_71_4">Description</A></H3>
+<P>The <CODE>httpHead()</CODE> function sends a HTTP HEAD request to the
+ server.</P>
+<H3><A NAME="10_71_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpHead(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_71_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpInitialize">httpInitialize()</A></H2>
+<H3><A NAME="10_72_1">Usage</A></H3>
+<PRE>
+void httpInitialize(void);
+</PRE>
+<H3><A NAME="10_72_2">Description</A></H3>
+<P>The <CODE>httpInitialize()</CODE> function initializes the networking
+ code as needed by the underlying platform. It is called automatically
+ by the <CODE>httpConnect()</CODE> function.</P>
+<H3><A NAME="10_72_3">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+httpInitialize();
+</PRE>
+<H3><A NAME="10_72_4">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpMD5">httpMD5()</A></H2>
+<H3><A NAME="10_73_1">Usage</A></H3>
+<PRE>
+char *
+httpMD5(const char *username,
+ const char *realm,
+ const char *passwd,
+ char md5[33]);
+</PRE>
+<H3><A NAME="10_73_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>username</TD><TD>The authenticating user name.</TD></TR>
+<TR><TD>realm</TD><TD>The authenticating realm name.</TD></TR>
+<TR><TD>passwd</TD><TD>The authenticating password.</TD></TR>
+<TR><TD>md5</TD><TD>The MD5 sum string.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_73_3">Returns</A></H3>
+<P>A pointer to the MD5 sum string.</P>
+<H3><A NAME="10_73_4">Description</A></H3>
+<P><CODE>httpMD5()</CODE> computes the MD5 hash of the username, realm,
+ and password as required by the HTTP Digest specification.</P>
+<H3><A NAME="10_73_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char md5[33];
+
+...
+
+httpMD5(&quot;user&quot;, &quot;realm&quot;, &quot;password&quot;, md5);
+</PRE>
+<H3><A NAME="10_73_6">See Also</A></H3>
+<P> <A HREF="#httpMD5Final"><CODE>httpMD5Final()</CODE></A>, <A HREF="#httpMD5String">
+<CODE>httpMD5String()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpMD5Final">httpMD5Final()</A></H2>
+<H3><A NAME="10_74_1">Usage</A></H3>
+<PRE>
+char *
+httpMD5Final(const char *nonce,
+ const char *method,
+ const char *resource,
+ char md5[33]);
+</PRE>
+<H3><A NAME="10_74_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>nonce</TD><TD>The server nonce value.</TD></TR>
+<TR><TD>method</TD><TD>The HTTP method (GET, POST, etc.)</TD></TR>
+<TR><TD>resource</TD><TD>The resource path.</TD></TR>
+<TR><TD>md5</TD><TD>The MD5 sum string.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_74_3">Returns</A></H3>
+<P>The MD5 sum string.</P>
+<H3><A NAME="10_74_4">Description</A></H3>
+<P><CODE>httpMD5Final()</CODE> appends the nonce, method, and resource
+ to the specified MD5 sum.</P>
+<H3><A NAME="10_74_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char md5[33];
+
+...
+
+httpMD5Final(&quot;nonce&quot;, &quot;GET&quot;, &quot;/jobs&quot;, md5);
+</PRE>
+<H3><A NAME="10_74_6">See Also</A></H3>
+<P> <A HREF="#httpMD5"><CODE>httpMD5()</CODE></A>, <A HREF="#httpMD5String">
+<CODE>httpMD5String()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpMD5String">httpMD5String()</A></H2>
+<H3><A NAME="10_75_1">Usage</A></H3>
+<PRE>
+char *
+httpMD5String(const md5_byte_t *sum,
+ char md5[33]);
+</PRE>
+<H3><A NAME="10_75_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>sum</TD><TD>The raw MD5 sum data.</TD></TR>
+<TR><TD>md5</TD><TD>The MD5 sum string.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_75_3">Returns</A></H3>
+<P>The MD5 sum string.</P>
+<H3><A NAME="10_75_4">Description</A></H3>
+<P><CODE>httpMD5String()</CODE> converts the raw MD5 sum value to a
+ string.</P>
+<H3><A NAME="10_75_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+md5_byte_t sum[16];
+char md5[33];
+
+...
+
+httpMD5String(sum, md5);
+</PRE>
+<H3><A NAME="10_75_6">See Also</A></H3>
+<P> <A HREF="#httpMD5"><CODE>httpMD5()</CODE></A>, <A HREF="#httpMD5Final">
+<CODE>httpMD5Final()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="httpOptions">httpOptions()</A></H2>
+<H3><A NAME="10_76_1">Usage</A></H3>
+<PRE>
+int
+httpOptions(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_76_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to check for options</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_76_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_76_4">Description</A></H3>
+<P>The <CODE>httpOptions()</CODE> function sends a HTTP OPTIONS request
+ to the server.</P>
+<H3><A NAME="10_76_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpOptions(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_76_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpPost">httpPost()</A></H2>
+<H3><A NAME="10_77_1">Usage</A></H3>
+<PRE>
+int
+httpPost(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_77_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to post to</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_77_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_77_4">Description</A></H3>
+<P>The <CODE>httpPost()</CODE> function sends a HTTP POST request to the
+ server.</P>
+<H3><A NAME="10_77_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpPost(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_77_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpPrintf">httpPrintf()</A></H2>
+<H3><A NAME="10_78_1">Usage</A></H3>
+<PRE>
+int
+httpPrintf(http_t *http,
+ const char *format,
+ ...);
+</PRE>
+<H3><A NAME="10_78_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>format</TD><TD>A printf-style format string</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_78_3">Returns</A></H3>
+<P>The number of bytes written.</P>
+<H3><A NAME="10_78_4">Description</A></H3>
+<P>The <CODE>httpPrintf()</CODE> function sends a formatted string to
+ the HTTP connection. It is normally only used by the CUPS API and
+ scheduler.</P>
+<H3><A NAME="10_78_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpPrintf(http, &quot;GET / HTTP/1.1 \r\n&quot;);
+</PRE>
+<H3><A NAME="10_78_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpPut">httpPut()</A></H2>
+<H3><A NAME="10_79_1">Usage</A></H3>
+<PRE>
+int
+httpPut(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_79_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to put</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_79_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_79_4">Description</A></H3>
+<P>The <CODE>httpPut()</CODE> function sends a HTTP PUT request to the
+ server.</P>
+<H3><A NAME="10_79_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpDelete(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_79_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpRead">httpRead()</A></H2>
+<H3><A NAME="10_80_1">Usage</A></H3>
+<PRE>
+int
+httpRead(http_t *http,
+ char *buffer,
+ int length);
+</PRE>
+<H3><A NAME="10_80_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>buffer</TD><TD>The buffer to read into</TD></TR>
+<TR><TD>length</TD><TD>The number of bytes to read</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_80_3">Returns</A></H3>
+<P>The number of bytes read or -1 on error.</P>
+<H3><A NAME="10_80_4">Description</A></H3>
+<P>The <CODE>httpRead()</CODE> function reads data from the HTTP
+ connection, possibly the result of a GET or POST request.</P>
+<H3><A NAME="10_80_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+char buffer[1024];
+int bytes;
+
+httpGet(http, &quot;/&quot;);
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) &gt; 0)
+{
+ buffer[bytes] = '\0';
+ fputs(buffer, stdout);
+}
+</PRE>
+<H3><A NAME="10_80_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpWrite">
+<CODE>httpWrite()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpReconnect">httpReconnect()</A></H2>
+<H3><A NAME="10_81_1">Usage</A></H3>
+<PRE>
+int
+httpReconnect(http_t *http);
+</PRE>
+<H3><A NAME="10_81_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_81_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_81_4">Description</A></H3>
+<P>The <CODE>httpReconnect()</CODE> function reconnects to the HTTP
+ server. This is usually done automatically if the HTTP functions detect
+ that the server connection has terminated.</P>
+<H3><A NAME="10_81_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpReconnect(http);
+</PRE>
+<H3><A NAME="10_81_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpSeparate">httpSeparate()</A></H2>
+<H3><A NAME="10_82_1">Usage</A></H3>
+<PRE>
+void
+httpSeparate(const char *uri,
+ char *method,
+ char *username,
+ char *host,
+ int *port,
+ char *resource);
+</PRE>
+<H3><A NAME="10_82_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>uri</TD><TD>The URI to separate</TD></TR>
+<TR><TD>method</TD><TD>The method (scheme) of the URI</TD></TR>
+<TR><TD>username</TD><TD>The username (and password) portion of the URI,
+ if any</TD></TR>
+<TR><TD>host</TD><TD>The hostname portion of the URI, if any</TD></TR>
+<TR><TD>port</TD><TD>The port number for the URI, either as specified or
+ as default for the method/scheme</TD></TR>
+<TR><TD>resource</TD><TD>The resource string, usually a filename on the
+ server</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_82_3">Description</A></H3>
+<P>The <CODE>httpSeparate()</CODE> function separates the specified URI
+ into its component parts. The method, username, hostname, and resource
+ strings should be at least <CODE>HTTP_MAX_URI</CODE> characters long to
+ avoid potential buffer overflow problems.</P>
+<H3><A NAME="10_82_4">Example</A></H3>
+<PRE>
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int port;
+
+...
+
+httpSeparate(uri, method, username, host, &amp;port, resource);
+</PRE>
+<H3><A NAME="10_82_5">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpSetField">httpSetField()</A></H2>
+<H3><A NAME="10_83_1">Usage</A></H3>
+<PRE>
+void
+httpSetField(http_t *http,
+ http_field_t field,
+ const char *value);
+</PRE>
+<H3><A NAME="10_83_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>field</TD><TD>The HTTP field</TD></TR>
+<TR><TD>value</TD><TD>The string value for the field</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_83_3">Description</A></H3>
+<P>The <CODE>httpSetField()</CODE> function sets the current value for
+ the specified HTTP field.</P>
+<H3><A NAME="10_83_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, &quot;Basic dfdr34453454325&quot;));
+httpGet(http, &quot;/some/uri&quot;);
+while (httpUpdate(http) == HTTP_CONTINUE);
+</PRE>
+<H3><A NAME="10_83_5">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpGetField">
+<CODE>httpGetField()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpStatus">httpStatus()</A></H2>
+<H3><A NAME="10_84_1">Usage</A></H3>
+<PRE>
+const char *
+httpStatus(http_status_t status);
+</PRE>
+<H3><A NAME="10_84_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>status</TD><TD>The HTTP status code from the server.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_84_3">Returns</A></H3>
+<P>The standard HTTP status text associated with the status code.</P>
+<H3><A NAME="10_84_4">Description</A></H3>
+<P><CODE>httpStatus()</CODE> returns the standard HTTP status text
+ associated with the status code.</P>
+<H3><A NAME="10_84_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+puts(httpStatus(http-&gt;status));
+</PRE>
+
+<!-- NEW PAGE -->
+<H2><A NAME="httpTrace">httpTrace()</A></H2>
+<H3><A NAME="10_85_1">Usage</A></H3>
+<PRE>
+int
+httpTrace(http_t *http,
+ const char *uri);
+</PRE>
+<H3><A NAME="10_85_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>uri</TD><TD>The URI to trace</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_85_3">Returns</A></H3>
+<P>0 on success, non-zero on failure.</P>
+<H3><A NAME="10_85_4">Description</A></H3>
+<P>The <CODE>httpTrace()</CODE> function sends a HTTP TRACE request to
+ the server.</P>
+<H3><A NAME="10_85_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpTrace(http, &quot;/some/uri&quot;);
+</PRE>
+<H3><A NAME="10_85_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpSetField">
+<CODE>httpSetField()</CODE></A>, <A HREF="#httpUpdate"><CODE>
+httpUpdate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpUpdate">httpUpdate()</A></H2>
+<H3><A NAME="10_86_1">Usage</A></H3>
+<PRE>
+http_status_t
+httpUpdate(http_t *http);
+</PRE>
+<H3><A NAME="10_86_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_86_3">Returns</A></H3>
+<P>The HTTP status of the current request.</P>
+<H3><A NAME="10_86_4">Description</A></H3>
+<P>The <CODE>httpUpdate()</CODE> function updates the current request
+ status. It is used after any DELETE, GET, HEAD, OPTIONS, POST, PUT, or
+ TRACE request to finalize the HTTP request and retrieve the request
+ status.</P>
+<P>Since proxies and the current blocking mode can cause the request to
+ take longer, programs should continue calling <CODE>httpUpdate() <CODE>
+until the return status is not the constant value <CODE>HTTP_CONTINUE</CODE>
+.</CODE></CODE></P>
+<H3><A NAME="10_86_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, &quot;/some/uri&quot;);
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf(&quot;Request status is %d\n&quot;, status);
+</PRE>
+<H3><A NAME="10_86_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpDelete">
+<CODE>httpDelete()</CODE></A>, <A HREF="#httpGet"><CODE>httpGet()</CODE></A>
+, <A HREF="#httpHead"><CODE>httpHead()</CODE></A>, <A HREF="#httpOptions">
+<CODE>httpOptions()</CODE></A>, <A HREF="#httpPost"><CODE>httpPost()</CODE>
+</A>, <A HREF="#httpPut"><CODE>httpPut()</CODE></A>, <A HREF="#httpTrace">
+<CODE>httpTrace()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="httpWrite">httpWrite()</A></H2>
+<H3><A NAME="10_87_1">Usage</A></H3>
+<PRE>
+int
+httpWrite(http_t *http,
+ char *buffer,
+ int length);
+</PRE>
+<H3><A NAME="10_87_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>buffer</TD><TD>The buffer to read into</TD></TR>
+<TR><TD>length</TD><TD>The number of bytes to read</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_87_3">Returns</A></H3>
+<P>The number of bytes read or -1 on error.</P>
+<H3><A NAME="10_87_4">Description</A></H3>
+<P>The <CODE>httpWrite()</CODE> function reads data from the HTTP
+ connection, possibly the result of a GET or POST request.</P>
+<H3><A NAME="10_87_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int bytes;
+
+httpPost(http, &quot;/&quot;);
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) &gt; 0)
+ httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) &gt; 0)
+{
+ buffer[bytes] = '\0';
+ fputs(buffer, stdout);
+}
+</PRE>
+<H3><A NAME="10_87_6">See Also</A></H3>
+ <A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>, <A HREF="#httpRead">
+<CODE>httpRead()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddBoolean">ippAddBoolean()</A></H2>
+<H3><A NAME="10_88_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddBoolean(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ char value);
+</PRE>
+<H3><A NAME="10_88_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>value</TD><TD>The boolean value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_88_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_88_4">Description</A></H3>
+<P>The <CODE>ippAddBoolean()</CODE> function adds a single boolean
+ attribute value to the specified IPP request.</P>
+<H3><A NAME="10_88_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;my-jobs&quot;, 1);
+</PRE>
+<H3><A NAME="10_88_6">See Also</A></H3>
+ <A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate">
+<CODE>ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
+ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
+ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
+</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
+<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddBooleans">ippAddBooleans()</A></H2>
+<H3><A NAME="10_89_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddBooleans(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const char *values);
+</PRE>
+<H3><A NAME="10_89_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>num_values</TD><TD>The number of values</TD></TR>
+<TR><TD>values</TD><TD>The boolean values</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_89_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_89_4">Description</A></H3>
+<P>The <CODE>ippAddBooleans()</CODE> function adds one or more boolean
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
+ pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE>
+ false values is created.</P>
+<H3><A NAME="10_89_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;, 10, values);
+</PRE>
+<H3><A NAME="10_89_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddDate">
+<CODE>ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
+ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
+ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
+</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
+<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddDate">ippAddDate()</A></H2>
+<H3><A NAME="10_90_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddDate(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ ipp_uchar_t *value);
+</PRE>
+<H3><A NAME="10_90_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>value</TD><TD>The date value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_90_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_90_4">Description</A></H3>
+<P>The <CODE>ippAddDate()</CODE> function adds a single date-time
+ attribute value to the specified IPP request.</P>
+<H3><A NAME="10_90_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;,
+ ippTimeToDate(time(NULL));
+</PRE>
+<H3><A NAME="10_90_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddInteger"><CODE>
+ippAddInteger()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
+ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
+</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
+<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>, <A HREF="#ippTimeToDate"><CODE>
+ippTimeToDate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddInteger">ippAddInteger()</A></H2>
+<H3><A NAME="10_91_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddInteger(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int value);
+</PRE>
+<H3><A NAME="10_91_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or
+ IPP_TAG_ENUM)</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>value</TD><TD>The integer value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_91_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_91_4">Description</A></H3>
+<P>The <CODE>ippAddInteger()</CODE> function adds a single integer
+ attribute value to the specified IPP request.</P>
+<H3><A NAME="10_91_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, &quot;limit&quot;, 100);
+</PRE>
+<H3><A NAME="10_91_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddIntegers"><CODE>
+ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE>
+</A>, <A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution">
+<CODE>ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddIntegers">ippAddIntegers()</A></H2>
+<H3><A NAME="10_92_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddIntegers(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const int *values);
+</PRE>
+<H3><A NAME="10_92_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>tag</TD><TD>The type of integer value (IPP_TAG_INTEGER or
+ IPP_TAG_ENUM)</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>num_values</TD><TD>The number of values</TD></TR>
+<TR><TD>values</TD><TD>The integer values</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_92_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_92_4">Description</A></H3>
+<P>The <CODE>ippAddIntegers()</CODE> function adds one or more integer
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
+ pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE> 0
+ values is created.</P>
+<H3><A NAME="10_92_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, &quot;some-attribute&quot;, 100, values);
+</PRE>
+<H3><A NAME="10_92_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges">
+<CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddRange">ippAddRange()</A></H2>
+<H3><A NAME="10_93_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddRange(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int low,
+ int high);
+</PRE>
+<H3><A NAME="10_93_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>low</TD><TD>The lower value</TD></TR>
+<TR><TD>high</TD><TD>The higher value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_93_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_93_4">Description</A></H3>
+<P>The <CODE>ippAddRange()</CODE> function adds a single range attribute
+ value to the specified IPP request.</P>
+<H3><A NAME="10_93_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, &quot;page-ranges&quot;, 1, 10);
+</PRE>
+<H3><A NAME="10_93_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRanges">
+<CODE>ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddRanges">ippAddRanges()</A></H2>
+<H3><A NAME="10_94_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddRanges(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const int *lows,
+ const int *highs);
+</PRE>
+<H3><A NAME="10_94_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>num_values</TD><TD>The number of range values</TD></TR>
+<TR><TD>lows</TD><TD>The lower values</TD></TR>
+<TR><TD>highs</TD><TD>The higher values</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_94_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_94_4">Description</A></H3>
+<P>The <CODE>ippAddRanges()</CODE> function adds one or more range
+ attribute values to the specified IPP request. If the <CODE>values</CODE>
+ pointer is <CODE>NULL</CODE> then an array of <CODE>num_values</CODE>
+ 0,0 ranges is created.</P>
+<H3><A NAME="10_94_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, &quot;page-ranges&quot;, 2, lows, highs);
+</PRE>
+<H3><A NAME="10_94_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddResolution">ippAddResolution()</A></H2>
+<H3><A NAME="10_95_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddResolution(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int xres,
+ int yres,
+ ipp_res_t units);
+</PRE>
+<H3><A NAME="10_95_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>xres</TD><TD>The horizontal resolution</TD></TR>
+<TR><TD>yres</TD><TD>The vertical resolution</TD></TR>
+<TR><TD>units</TD><TD>The resolution units</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_95_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_95_4">Description</A></H3>
+<P>The <CODE>ippAddResolution()</CODE> function adds a single resolution
+ attribute value to the specified IPP request.</P>
+<H3><A NAME="10_95_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;printer-resolution&quot;,
+ 720, 720, IPP_RES_PER_INCH);
+</PRE>
+<H3><A NAME="10_95_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
+ippAddRanges()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddResolutions">ippAddResolutions()</A></H2>
+<H3><A NAME="10_96_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddResolutions(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const int *xres,
+ const int *yres,
+ const ipp_res_t *units);
+</PRE>
+<H3><A NAME="10_96_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>num_values</TD><TD>The number of resolution values</TD></TR>
+<TR><TD>xres</TD><TD>The horizontal resolutions</TD></TR>
+<TR><TD>yres</TD><TD>The vertical resolutions</TD></TR>
+<TR><TD>units</TD><TD>The resolution units</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_96_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_96_4">Description</A></H3>
+<P>The <CODE>ippAddResolutions()</CODE> function adds one or more
+ resolution attribute values to the specified IPP request. If the <CODE>
+values</CODE> pointer is <CODE>NULL</CODE> then an array of <CODE>
+num_values</CODE> 0,0 resolutions is created.</P>
+<H3><A NAME="10_96_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, &quot;printer-resolutions-supported&quot;,
+ 5, xres, yres, units);
+</PRE>
+<H3><A NAME="10_96_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
+ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddSeparator">ippAddSeparator()</A></H2>
+<H3><A NAME="10_97_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddSeparator(ipp_t *ipp);
+</PRE>
+<H3><A NAME="10_97_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_97_3">Returns</A></H3>
+<P>A pointer to the new separator or NULL if the separator could not be
+ created.</P>
+<H3><A NAME="10_97_4">Description</A></H3>
+<P>The <CODE>ippAddSeparator()</CODE> function adds a group separator to
+ the specified IPP request.</P>
+<H3><A NAME="10_97_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+</PRE>
+<H3><A NAME="10_97_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
+ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddString">ippAddString()</A></H2>
+<H3><A NAME="10_98_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddString(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ const char *charset,
+ const char *value);
+</PRE>
+<H3><A NAME="10_98_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>tag</TD><TD>The type of string value</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>charset</TD><TD>The character set for the string</TD></TR>
+<TR><TD>value</TD><TD>The string value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_98_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_98_4">Description</A></H3>
+<P>The <CODE>ippAddString()</CODE> function adds a single string
+ attribute value to the specified IPP request. For <CODE>
+IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the
+ charset value is provided with the string to identify the string
+ encoding used. Otherwise the charset value is ignored.</P>
+<H3><A NAME="10_98_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, &quot;job-name&quot;,
+ NULL, &quot;abc123&quot;);
+</PRE>
+<H3><A NAME="10_98_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
+ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddStrings"><CODE>
+ippAddStrings()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippAddStrings">ippAddStrings()</A></H2>
+<H3><A NAME="10_99_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippAddStrings(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const char *charset,
+ const char **values);
+</PRE>
+<H3><A NAME="10_99_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request</TD></TR>
+<TR><TD>group</TD><TD>The IPP group</TD></TR>
+<TR><TD>tag</TD><TD>The type of string value</TD></TR>
+<TR><TD>name</TD><TD>The name of attribute</TD></TR>
+<TR><TD>num_values</TD><TD>The number of strings</TD></TR>
+<TR><TD>charset</TD><TD>The character set for the strings</TD></TR>
+<TR><TD>values</TD><TD>The string values</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_99_3">Returns</A></H3>
+<P>A pointer to the new attribute or NULL if the attribute could not be
+ created.</P>
+<H3><A NAME="10_99_4">Description</A></H3>
+<P>The <CODE>ippAddStrings()</CODE> function adds one or more string
+ attribute values to the specified IPP request. For <CODE>
+IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE> strings, the
+ charset value is provided with the strings to identify the string
+ encoding used. Otherwise the charset value is ignored. If the <CODE>
+values</CODE> pointer is <CODE>NULL</CODE> then an array of <CODE>
+num_values</CODE> NULL strings is created.</P>
+<H3><A NAME="10_99_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+char *values[2] = { &quot;one&quot;, &quot;two&quot; };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, &quot;attr-name&quot;,
+ 2, NULL, values);
+</PRE>
+<H3><A NAME="10_99_6">See Also</A></H3>
+ <A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>, <A HREF="#ippAddBooleans">
+<CODE>ippAddBooleans()</CODE></A>, <A HREF="#ippAddDate"><CODE>
+ippAddDate()</CODE></A>, <A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE>
+</A>, <A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>, <A HREF="#ippAddRange">
+<CODE>ippAddRange()</CODE></A>, <A HREF="#ippAddRanges"><CODE>
+ippAddRanges()</CODE></A>, <A HREF="#ippAddResolution"><CODE>
+ippAddResolution()</CODE></A>, <A HREF="#ippAddResolutions"><CODE>
+ippAddResolutions()</CODE></A>, <A HREF="#ippAddSeparator"><CODE>
+ippAddSeparator()</CODE></A>, <A HREF="#ippAddString"><CODE>
+ippAddString()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippDateToTime">ippDateToTime()</A></H2>
+<H3><A NAME="10_100_1">Usage</A></H3>
+<PRE>
+time_t
+ippDateToTime(const ipp_uchar_t date[11]);
+</PRE>
+<H3><A NAME="10_100_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>date</TD><TD>The IPP date-time value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_100_3">Returns</A></H3>
+<P>A UNIX time value.</P>
+<H3><A NAME="10_100_4">Description</A></H3>
+<P>The <CODE>ippDateToTime()</CODE> function converts an IPP date-time
+ value to a UNIX time value.</P>
+<H3><A NAME="10_100_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_uchar_t date[11];
+
+printf(&quot;UNIX time is %d\n&quot;, ippDateToTime(date));
+</PRE>
+<H3><A NAME="10_100_6">See Also</A></H3>
+ <A HREF="#ippTimeToDate"><CODE>ippTimeToDate()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippDelete">ippDelete()</A></H2>
+<H3><A NAME="10_101_1">Usage</A></H3>
+<PRE>
+void
+ippDelete(ipp_t *ipp);
+</PRE>
+<H3><A NAME="10_101_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_101_3">Description</A></H3>
+<P>The <CODE>ippDelete()</CODE> function deletes all memory used by an
+ IPP request or response.</P>
+<H3><A NAME="10_101_4">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+</PRE>
+<H3><A NAME="10_101_5">See Also</A></H3>
+ <A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippErrorString">ippErrorString()</A></H2>
+<H3><A NAME="10_102_1">Usage</A></H3>
+<PRE>
+const char *
+ippErrorString(ipp_status_t error);
+</PRE>
+<H3><A NAME="10_102_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>error</TD><TD>IPP error code.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_102_3">Returns</A></H3>
+<P>The standard text representation of the IPP error code.</P>
+<H3><A NAME="10_102_4">Description</A></H3>
+<P><CODE>ippErrorString()</CODE> returns the standard text
+ representation of the IPP error code.</P>
+<H3><A NAME="10_102_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+puts(ippErrorString(IPP_OK));
+</PRE>
+<H3><A NAME="10_102_6">See Also</A></H3>
+<P> <A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="ippFindAttribute">ippFindAttribute()</A></H2>
+<H3><A NAME="10_103_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippFindAttribute(ipp_t *ipp,
+ const char *name,
+ ipp_tag_t tag);
+</PRE>
+<H3><A NAME="10_103_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+<TR><TD>name</TD><TD>The name of the attribute</TD></TR>
+<TR><TD>tag</TD><TD>The required value tag for the attribute or <CODE>
+IPP_TAG_ZERO</CODE> for any type of value.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_103_3">Returns</A></H3>
+<P>A pointer to the first occurrence of the requested attribute, or <CODE>
+NULL</CODE> if it was not found.</P>
+<H3><A NAME="10_103_4">Description</A></H3>
+<P><CODE>ippFindAttribute()</CODE> finds the first occurrence of the
+ named attribute. The <CODE>tag</CODE> parameter restricts the search to
+ a specific value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value
+ with the name.</P>
+<P>The value tags <CODE>IPP_TAG_NAME</CODE> and <CODE>IPP_TAG_TEXT</CODE>
+ match the name/text values with or without the language code.</P>
+<H3><A NAME="10_103_5">Example</A></H3>
+<PRE>
+<A HREF="#ipp_attribute_t">ipp_attribute_t</A> *attr;
+
+attr = ippFindAttribute(response, &quot;printer-state-message&quot;, IPP_TAG_TEXT);
+while (attr != NULL)
+{
+ puts(attr-&gt;values[0].string.text);
+
+ attr = ippFindNextAttribute(response, &quot;printer-state-message&quot;, IPP_TAG_TEXT);
+}
+</PRE>
+<H3><A NAME="10_103_6">See Also</A></H3>
+ <A HREF="#cupsDoFileRequest"><CODE>cupsDoFileRequest()</CODE></A>, <A HREF="#cupsDoRequest">
+<CODE>cupsDoRequest()</CODE></A>, <A HREF="#ippDelete"><CODE>ippDelete()</CODE>
+</A>, <A HREF="#ippFindNextAttribute"><CODE>ippFindNextAttribute()</CODE>
+</A>, <A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippFindNextAttribute">ippFindNextAttribute()</A></H2>
+<H3><A NAME="10_104_1">Usage</A></H3>
+<PRE>
+ipp_attribute_t *
+ippFindNextAttribute(ipp_t *ipp,
+ const char *name,
+ ipp_tag_t tag);
+</PRE>
+<H3><A NAME="10_104_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+<TR><TD>name</TD><TD>The name of the attribute</TD></TR>
+<TR><TD>tag</TD><TD>The required value tag for the attribute or <CODE>
+IPP_TAG_ZERO</CODE> for any type of value.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_104_3">Returns</A></H3>
+<P>A pointer to the next occurrence of the requested attribute, or <CODE>
+NULL</CODE> if it was not found.</P>
+<H3><A NAME="10_104_4">Description</A></H3>
+<P><CODE>ippFindNextAttribute()</CODE> finds the next occurrence of the
+ named attribute. The <CODE>tag</CODE> parameter restricts the search to
+ a specific value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value
+ with the name.</P>
+<P>The value tags <CODE>IPP_TAG_NAME</CODE> and <CODE>IPP_TAG_TEXT</CODE>
+ match the name/text values with or without the language code.</P>
+<H3><A NAME="10_104_5">Example</A></H3>
+<PRE>
+<A HREF="#ipp_attribute_t">ipp_attribute_t</A> *attr;
+
+attr = ippFindAttribute(response, &quot;printer-state-message&quot;, IPP_TAG_TEXT);
+while (attr != NULL)
+{
+ puts(attr-&gt;values[0].string.text);
+
+ attr = ippFindNextAttribute(response, &quot;printer-state-message&quot;, IPP_TAG_TEXT);
+}
+</PRE>
+<H3><A NAME="10_104_6">See Also</A></H3>
+ <A HREF="#cupsDoFileRequest"><CODE>cupsDoFileRequest()</CODE></A>, <A HREF="#cupsDoRequest">
+<CODE>cupsDoRequest()</CODE></A>, <A HREF="#ippDelete"><CODE>ippDelete()</CODE>
+</A>, <A HREF="#ippFindNextAttribute"><CODE>ippFindNextAttribute()</CODE>
+</A>, <A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippLength">ippLength()</A></H2>
+<H3><A NAME="10_105_1">Usage</A></H3>
+<PRE>
+int
+ippLength(ipp_t *ipp);
+</PRE>
+<H3><A NAME="10_105_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_105_3">Returns</A></H3>
+<P>The total encoded length of the IPP request or response in bytes.</P>
+<H3><A NAME="10_105_4">Description</A></H3>
+<P><CODE>ippLength()</CODE> returns the length of the IPP request or
+ response in bytes.</P>
+<H3><A NAME="10_105_5">Example</A></H3>
+<PRE>
+printf(&quot;The length of the response is %d bytes.\n&quot;, ippLength(response));
+</PRE>
+<H3><A NAME="10_105_6">See Also</A></H3>
+ <A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>, <A HREF="#ippNew"><CODE>
+ippNew()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippNew">ippNew()</A></H2>
+<H3><A NAME="10_106_1">Usage</A></H3>
+<PRE>
+ipp_t *
+ippNew(void);
+</PRE>
+<H3><A NAME="10_106_2">Returns</A></H3>
+<P>A pointer to a new IPP request or response.</P>
+<H3><A NAME="10_106_3">Description</A></H3>
+<P>The <CODE>ippNew()</CODE> function creates a new IPP request or
+ response.</P>
+<H3><A NAME="10_106_4">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_t *ipp;
+
+ipp = ippNew();
+</PRE>
+<H3><A NAME="10_106_5">See Also</A></H3>
+ <A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippPort">ippPort()</A></H2>
+<H3><A NAME="10_107_1">Usage</A></H3>
+<PRE>
+int
+ippPort(void);
+</PRE>
+<H3><A NAME="10_107_2">Returns</A></H3>
+<P>The default TCP/IP port number for IPP requests.</P>
+<H3><A NAME="10_107_3">Description</A></H3>
+<P>The <CODE>ippPort()</CODE> function returns the default IPP port
+ number for requests.</P>
+<H3><A NAME="10_107_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+#include &lt;cups/ipp.h&gt;
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+</PRE>
+<H3><A NAME="10_107_5">See Also</A></H3>
+ <A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>, <A HREF="#ippSetPort">
+<CODE>ippSetPort()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippRead">ippRead()</A></H2>
+<H3><A NAME="10_108_1">Usage</A></H3>
+<PRE>
+ipp_state_t
+ippRead(http_t *http,
+ ipp_t *ipp);
+</PRE>
+<H3><A NAME="10_108_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_108_3">Returns</A></H3>
+<P>The current read state.</P>
+<H3><A NAME="10_108_4">Description</A></H3>
+<P>The <CODE>ippRead()</CODE> function reads IPP attributes from the
+ specified HTTP connection. Programs should continue calling <CODE>
+ippRead()</CODE> until <CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE>
+ is returned.</P>
+<H3><A NAME="10_108_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+#include &lt;cups/ipp.h&gt;
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+ if (status == IPP_DATA)
+ break;
+
+if (status == IPP_DATA)
+{
+ ... read additional non-IPP data using httpRead() ...
+}
+</PRE>
+<H3><A NAME="10_108_6">See Also</A></H3>
+ <A HREF="#ippWrite"><CODE>ippWrite()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippSetPort">ippSetPort()</A></H2>
+<H3><A NAME="10_109_1">Usage</A></H3>
+<PRE>
+void
+ippSetPort(int port);
+</PRE>
+<H3><A NAME="10_109_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>port</TD><TD>The port number to use</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_109_3">Description</A></H3>
+<P>The <CODE>ippSetPort()</CODE> function sets the default IPP port
+ number for requests.</P>
+<H3><A NAME="10_109_4">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+#include &lt;cups/ipp.h&gt;
+
+...
+
+ippSetPort(8631);
+</PRE>
+<H3><A NAME="10_109_5">See Also</A></H3>
+ <A HREF="#ippPort"><CODE>ippPort()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippTimeToDate">ippTimeToDate()</A></H2>
+<H3><A NAME="10_110_1">Usage</A></H3>
+<PRE>
+ipp_uchar_t *
+ippTimeToDate(time_t time);
+</PRE>
+<H3><A NAME="10_110_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>time</TD><TD>The UNIX time value</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_110_3">Returns</A></H3>
+<P>A static pointer to an IPP date-time value.</P>
+<H3><A NAME="10_110_4">Description</A></H3>
+<P>The <CODE>ippTimeToDate()</CODE> function converts a UNIX time to an
+ IPP date-time value.</P>
+<H3><A NAME="10_110_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+</PRE>
+<H3><A NAME="10_110_6">See Also</A></H3>
+ <A HREF="#ippDateToTime"><CODE>ippDateToTime()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ippWrite">ippWrite()</A></H2>
+<H3><A NAME="10_111_1">Usage</A></H3>
+<PRE>
+ipp_state_t
+ippWrite(http_t *http,
+ ipp_t *ipp);
+</PRE>
+<H3><A NAME="10_111_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>http</TD><TD>The HTTP connection</TD></TR>
+<TR><TD>ipp</TD><TD>The IPP request or response</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_111_3">Returns</A></H3>
+<P>The current write state.</P>
+<H3><A NAME="10_111_4">Description</A></H3>
+<P>The <CODE>ippWrite()</CODE> function writes IPP attributes to the
+ specified HTTP connection. Programs should continue calling <CODE>
+ippWrite()</CODE> until <CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE>
+ is returned.</P>
+<H3><A NAME="10_111_5">Example</A></H3>
+<PRE>
+#include &lt;cups/http.h&gt;
+#include &lt;cups/ipp.h&gt;
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+ if (status == IPP_DATA)
+ break;
+
+if (status == IPP_DATA)
+{
+ ... read additional non-IPP data using httpWrite() ...
+}
+</PRE>
+<H3><A NAME="10_111_6">See Also</A></H3>
+ <A HREF="#ippRead"><CODE>ippRead()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdClose">ppdClose()</A></H2>
+<H3><A NAME="10_112_1">Usage</A></H3>
+<PRE>
+void
+ppdClose(ppd_file_t *ppd);
+</PRE>
+<H3><A NAME="10_112_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_112_3">Description</A></H3>
+<P>The <CODE>ppdClose()</CODE> function frees all memory associated with
+ the PPD file.</P>
+<H3><A NAME="10_112_4">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+</PRE>
+<H3><A NAME="10_112_5">See Also</A></H3>
+ <A HREF="#ppdOpen"><CODE>ppdOpen()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>
+ppdOpenFd()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE>
+</A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdCollect">ppdCollect()</A></H2>
+<H3><A NAME="10_113_1">Usage</A></H3>
+<PRE>
+int
+ppdCollect(ppd_file_t *ppd,
+ ppd_section_t section,
+ ppd_choice_t ***choices);
+</PRE>
+<H3><A NAME="10_113_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file.</TD></TR>
+<TR><TD>section</TD><TD>The document section to collect.</TD></TR>
+<TR><TD>choices</TD><TD>The array of option choices that are marked.</TD>
+</TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_113_3">Returns</A></H3>
+<P>The number of options collected.</P>
+<H3><A NAME="10_113_4">Description</A></H3>
+<P><CODE>ppdCollect()</CODE> collects all of the marked options in the
+ specified section, sorts them by their order dependency values, and
+ returns an array that can be used to emit option commands in the proper
+ order. It is normally used by the <CODE>ppdEmit*()</CODE> functions.</P>
+<H3><A NAME="10_113_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+<A HREF="#ppd_file_t">ppd_file_t</A> *ppd;
+int num_choices;
+<A HREF="#ppd_choice_t">ppd_choice_t</A> **choices;
+
+...
+
+num_choices = ppdCollect(ppd, PPD_ORDER_JCL, &amp;choices);
+</PRE>
+<H3><A NAME="10_113_6">See Also</A></H3>
+<P> <A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>, <A HREF="#ppdEmitFd"><CODE>
+ppdEmitFd()</CODE></A>, <A HREF="#ppdEmitJCL"><CODE>ppdEmitJCL()</CODE></A>
+<!-- NEW PAGE -->
+</P>
+<H2><A NAME="ppdConflicts">ppdConflicts()</A></H2>
+<H3><A NAME="10_114_1">Usage</A></H3>
+<PRE>
+int
+ppdConflicts(ppd_file_t *ppd);
+</PRE>
+<H3><A NAME="10_114_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_114_3">Returns</A></H3>
+<P>The number of option conflicts in the file.</P>
+<H3><A NAME="10_114_4">Description</A></H3>
+<P>The <CODE>ppdConflicts()</CODE> function returns the number of
+ conflicts with the currently selected options.</P>
+<H3><A NAME="10_114_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+printf(&quot;%d conflicts\n&quot;, ppdConflicts(ppd));
+</PRE>
+<H3><A NAME="10_114_6">See Also</A></H3>
+ <A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>, <A HREF="#ppdIsMarked">
+<CODE>ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
+ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+ppdMarkOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdEmit">ppdEmit()</A></H2>
+<H3><A NAME="10_115_1">Usage</A></H3>
+<PRE>
+int
+ppdEmit(ppd_file_t *ppd,
+ FILE *file,
+ ppd_section_t section);
+</PRE>
+<H3><A NAME="10_115_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>file</TD><TD>The file to write to</TD></TR>
+<TR><TD>section</TD><TD>The option section to write</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_115_3">Returns</A></H3>
+<P>0 on success, -1 on error.</P>
+<H3><A NAME="10_115_4">Description</A></H3>
+<P>The <CODE>ppdEmit()</CODE> function sends printer-specific option
+ commands to the specified file.</P>
+<H3><A NAME="10_115_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+</PRE>
+<H3><A NAME="10_115_6">See Also</A></H3>
+ <A HREF="#ppdEmitFd"><CODE>ppdEmitFd()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdEmitFd">ppdEmitFd()</A></H2>
+<H3><A NAME="10_116_1">Usage</A></H3>
+<PRE>
+int
+ppdEmitFd(ppd_file_t *ppd,
+ int fd,
+ ppd_section_t section);
+</PRE>
+<H3><A NAME="10_116_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>fd</TD><TD>The file descriptor to write to</TD></TR>
+<TR><TD>section</TD><TD>The option section to write</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_116_3">Returns</A></H3>
+<P>0 on success, -1 on error.</P>
+<H3><A NAME="10_116_4">Description</A></H3>
+<P>The <CODE>ppdEmitFd()</CODE> function sends printer-specific option
+ commands to the specified file descriptor.</P>
+<H3><A NAME="10_116_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+</PRE>
+<H3><A NAME="10_116_6">See Also</A></H3>
+ <A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>, <A HREF="#ppdEmitJCL"><CODE>
+ppdEmitJCL()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdEmitJCL">ppdEmitJCL()</A></H2>
+<H3><A NAME="10_117_1">Usage</A></H3>
+<PRE>
+int
+ppdEmitJCL(ppd_file_t *ppd,
+ FILE *file,
+ int job_id,
+ const char *user,
+ const char *title);
+</PRE>
+<H3><A NAME="10_117_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>file</TD><TD>The file to write to</TD></TR>
+<TR><TD>job_id</TD><TD>The job ID number</TD></TR>
+<TR><TD>user</TD><TD>The job user</TD></TR>
+<TR><TD>title</TD><TD>The job name</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_117_3">Returns</A></H3>
+<P>0 on success, -1 on error.</P>
+<H3><A NAME="10_117_4">Description</A></H3>
+<P>The <CODE>ppdEmitJCL()</CODE> function sends printer-specific job
+ control commands to the specified file. For printers that support the
+ HP Printer Job Language (PJL) job control language, the output also
+ contains a display string that usually appears on the printer's LCD.</P>
+<H3><A NAME="10_117_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdEmitJCL(ppd, stdout, job_id, user, title);
+</PRE>
+<H3><A NAME="10_117_6">See Also</A></H3>
+ <A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>, <A HREF="#ppdEmitFd"><CODE>
+ppdEmitFd()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdFindAttr">ppdFindAttr()</A></H2>
+<H3><A NAME="10_118_1">Usage</A></H3>
+<PRE>
+ppd_attr_t *
+ppdFindAttr(ppd_file_t *ppd,
+ const char *keyword,
+ const char *spec);
+</PRE>
+<H3><A NAME="10_118_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the attribute</TD></TR>
+<TR><TD>spec</TD><TD>The option keyword associated with the attribute or
+ NULL if you don't care.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_118_3">Returns</A></H3>
+<P>A pointer to the attribute data or NULL if the attribute does not
+ exist.</P>
+<H3><A NAME="10_118_4">Description</A></H3>
+<P>The <CODE>ppdFindAttr()</CODE> function returns a pointer to the
+ first occurrence of the attribute in the PPD file.</P>
+<H3><A NAME="10_118_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_attr_t *attr;
+
+attr = ppdFindAttr(ppd, &quot;RequiresPageRegion&quot;, &quot;Upper&quot;);
+</PRE>
+<H3><A NAME="10_118_6">See Also</A></H3>
+ <A HREF="#ppdFindNextAttr"><CODE>ppdFindNextAttr()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdFindChoice">ppdFindChoice()</A></H2>
+<H3><A NAME="10_119_1">Usage</A></H3>
+<PRE>
+ppd_choice_t *
+ppdFindChoice(ppd_option_t *option,
+ const char *choice);
+</PRE>
+<H3><A NAME="10_119_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>option</TD><TD>A pointer to the option</TD></TR>
+<TR><TD>choice</TD><TD>The name of the choice</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_119_3">Returns</A></H3>
+<P>A pointer to the choice data or NULL if the choice does not exist.</P>
+<H3><A NAME="10_119_4">Description</A></H3>
+<P>The <CODE>ppdFindChoice()</CODE> function returns a pointer to the
+ choice data for the specified option.</P>
+<H3><A NAME="10_119_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, &quot;PageSize&quot;);
+choice = ppdFindChoice(option, &quot;Letter&quot;);
+</PRE>
+<H3><A NAME="10_119_6">See Also</A></H3>
+ <A HREF="#ppdFindMarkedChoice"><CODE>ppdFindMarkedChoice()</CODE></A>, <A
+HREF="#ppdFindOption"><CODE>ppdFindOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdFindMarkedChoice">ppdFindMarkedChoice()</A></H2>
+<H3><A NAME="10_120_1">Usage</A></H3>
+<PRE>
+ppd_choice_t *
+ppdFindMarkedChoice(ppd_file_t *ppd,
+ const char *keyword);
+</PRE>
+<H3><A NAME="10_120_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the option</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_120_3">Returns</A></H3>
+<P>A pointer to the choice data or NULL if the choice does not exist or
+ is not marked.</P>
+<H3><A NAME="10_120_4">Description</A></H3>
+<P>The <CODE>ppdFindMarkedChoice()</CODE> function returns a pointer to
+ the marked choice data for the specified option.</P>
+<H3><A NAME="10_120_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, &quot;PageSize&quot;);
+</PRE>
+<H3><A NAME="10_120_6">See Also</A></H3>
+ <A HREF="#ppdFindChoice"><CODE>ppdFindChoice()</CODE></A>, <A HREF="#ppdFindOption">
+<CODE>ppdFindOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdFindNextAttr">ppdFindNextAttr()</A></H2>
+<H3><A NAME="10_121_1">Usage</A></H3>
+<PRE>
+ppd_attr_t *
+ppdFindNextAttr(ppd_file_t *ppd,
+ const char *keyword,
+ const char *spec);
+</PRE>
+<H3><A NAME="10_121_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>A pointer to the PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the attribute</TD></TR>
+<TR><TD>spec</TD><TD>The option keyword associated with the attribute or
+ NULL if you don't care.</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_121_3">Returns</A></H3>
+<P>A pointer to the attribute data or NULL if the attribute does not
+ exist.</P>
+<H3><A NAME="10_121_4">Description</A></H3>
+<P>The <CODE>ppdFindNextAttr()</CODE> function returns a pointer to the
+ next occurrence of the attribute in the PPD file.</P>
+<H3><A NAME="10_121_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_attr_t *attr;
+
+for (attr = ppdFindAttr(ppd, &quot;cupsICCProfile&quot;, NULL);
+ attr != NULL;
+ attr = ppdFindNextAttr(ppd, &quot;cupsICCProfile&quot;, NULL))
+{
+ printf(&quot;*%s %s/%s: \&quot;%s\&quot;\n&quot;,
+ attr-&gt;name, attr-&gt;spec, attr-&gt;text,
+ attr-&gt;value ? attr-&gt;value : &quot;(none)&quot;);
+}
+</PRE>
+<H3><A NAME="10_121_6">See Also</A></H3>
+ <A HREF="#ppdFindAttr"><CODE>ppdFindAttr()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdFindOption">ppdFindOption()</A></H2>
+<H3><A NAME="10_122_1">Usage</A></H3>
+<PRE>
+ppd_option_t *
+ppdFindOption(ppd_file_t *ppd,
+ const char *keyword);
+</PRE>
+<H3><A NAME="10_122_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the option</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_122_3">Returns</A></H3>
+<P>A pointer to the option data or NULL if the option does not exist.</P>
+<H3><A NAME="10_122_4">Description</A></H3>
+<P>The <CODE>ppdFindOption()</CODE> function returns a pointer to the
+ option data for the specified option.</P>
+<H3><A NAME="10_122_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, &quot;PageSize&quot;);
+</PRE>
+<H3><A NAME="10_122_6">See Also</A></H3>
+ <A HREF="#ppdFindChoice"><CODE>ppdFindChoice()</CODE></A>, <A HREF="#ppdFindMarkedChoice">
+<CODE>ppdFindMarkedChoice()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdIsMarked">ppdIsMarked()</A></H2>
+<H3><A NAME="10_123_1">Usage</A></H3>
+<PRE>
+int
+ppdIsMarked(ppd_file_t *ppd,
+ const char *keyword,
+ const char *choice);
+</PRE>
+<H3><A NAME="10_123_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the option</TD></TR>
+<TR><TD>choice</TD><TD>The name of the option choice</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_123_3">Returns</A></H3>
+<P>1 if the choice is marked, 0 otherwise.</P>
+<H3><A NAME="10_123_4">Description</A></H3>
+<P>The <CODE>ppdIsMarked()</CODE> function returns whether or not the
+ specified option choice is marked.</P>
+<H3><A NAME="10_123_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+printf(&quot;Letter size %s selected.\n&quot;,
+ ppdIsMarked(ppd, &quot;PageSize&quot;, &quot;Letter&quot;) ? &quot;is&quot; : &quot;is not&quot;);
+</PRE>
+<H3><A NAME="10_123_6">See Also</A></H3>
+ <A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
+<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
+ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
+ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+ppdMarkOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdMarkDefaults">ppdMarkDefaults()</A></H2>
+<H3><A NAME="10_124_1">Usage</A></H3>
+<PRE>
+void
+ppdMarkDefaults(ppd_file_t *ppd);
+</PRE>
+<H3><A NAME="10_124_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_124_3">Description</A></H3>
+<P>The <CODE>ppdMarkDefaults()</CODE> function marks all of the default
+ choices in the PPD file.</P>
+<H3><A NAME="10_124_4">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+</PRE>
+<H3><A NAME="10_124_5">See Also</A></H3>
+ <A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
+<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
+ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
+ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+ppdMarkOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdMarkOption">ppdMarkOption()</A></H2>
+<H3><A NAME="10_125_1">Usage</A></H3>
+<PRE>
+int
+ppdMarkOption(ppd_file_t *ppd,
+ const char *keyword,
+ const char *choice);
+</PRE>
+<H3><A NAME="10_125_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>keyword</TD><TD>The name of the option</TD></TR>
+<TR><TD>choice</TD><TD>The name of the choice</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_125_3">Returns</A></H3>
+<P>The number of conflicts in the PPD file.</P>
+<H3><A NAME="10_125_4">Description</A></H3>
+<P>The <CODE>ppdMarkOption()</CODE> function marks the specified option
+ choice.</P>
+<H3><A NAME="10_125_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, &quot;PageSize&quot;, &quot;Letter&quot;);
+</PRE>
+<H3><A NAME="10_125_6">See Also</A></H3>
+ <A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>, <A HREF="#ppdConflicts">
+<CODE>ppdConflicts()</CODE></A>, <A HREF="#ppdIsMarked"><CODE>
+ppdIsMarked()</CODE></A>, <A HREF="#ppdMarkDefaults"><CODE>
+ppdMarkDefaults()</CODE></A>, <A HREF="#ppdMarkOption"><CODE>
+ppdMarkOption()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdOpen">ppdOpen()</A></H2>
+<H3><A NAME="10_126_1">Usage</A></H3>
+<PRE>
+ppd_file_t *
+ppdOpen(FILE *file);
+</PRE>
+<H3><A NAME="10_126_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>file</TD><TD>The file to read from</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_126_3">Returns</A></H3>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
+<H3><A NAME="10_126_4">Description</A></H3>
+<P>The <CODE>ppdOpen()</CODE> function reads a PPD file from the
+ specified file into memory.</P>
+<H3><A NAME="10_126_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen(&quot;filename.ppd&quot;, &quot;rb&quot;);
+ppd = ppdOpen(file);
+fclose(file);
+</PRE>
+<H3><A NAME="10_126_6">See Also</A></H3>
+ <A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>
+ppdOpenFd()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE>
+</A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdOpenFd">ppdOpenFd()</A></H2>
+<H3><A NAME="10_127_1">Usage</A></H3>
+<PRE>
+ppd_file_t *
+ppdOpenFd(int fd);
+</PRE>
+<H3><A NAME="10_127_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>fd</TD><TD>The file descriptor to read from</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_127_3">Returns</A></H3>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
+<H3><A NAME="10_127_4">Description</A></H3>
+<P>The <CODE>ppdOpenFd()</CODE> function reads a PPD file from the
+ specified file descriptor into memory.</P>
+<H3><A NAME="10_127_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+int fd;
+
+fd = open(&quot;filename.ppd&quot;, O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+</PRE>
+<H3><A NAME="10_127_6">See Also</A></H3>
+ <A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>, <A HREF="#ppdOpen"><CODE>
+ppdOpen()</CODE></A>, <A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdOpenFile">ppdOpenFile()</A></H2>
+<H3><A NAME="10_128_1">Usage</A></H3>
+<PRE>
+ppd_file_t *
+ppdOpenFile(const char *filename);
+</PRE>
+<H3><A NAME="10_128_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>filename</TD><TD>The name of the file to read from</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_128_3">Returns</A></H3>
+<P>A pointer to a PPD file structure or NULL if the PPD file could not
+ be read.</P>
+<H3><A NAME="10_128_4">Description</A></H3>
+<P>The <CODE>ppdOpenFile()</CODE> function reads a PPD file from the
+ named file into memory.</P>
+<H3><A NAME="10_128_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile(&quot;filename.ppd&quot;);
+</PRE>
+<H3><A NAME="10_128_6">See Also</A></H3>
+ <A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>, <A HREF="#ppdOpen"><CODE>
+ppdOpen()</CODE></A>, <A HREF="#ppdOpenFd"><CODE>ppdOpenFd()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdPageLength">ppdPageLength()</A></H2>
+<H3><A NAME="10_129_1">Usage</A></H3>
+<PRE>
+float
+ppdPageLength(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+<H3><A NAME="10_129_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>name</TD><TD>The name of the page size</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_129_3">Returns</A></H3>
+<P>The length of the specified page size in points or 0 if the page size
+ does not exist.</P>
+<H3><A NAME="10_129_4">Description</A></H3>
+<P>The <CODE>ppdPageLength()</CODE> function returns the page length of
+ the specified page size.</P>
+<H3><A NAME="10_129_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+printf(&quot;Length = %.0f\n&quot;, ppdPageLength(ppd, &quot;Letter&quot;));
+</PRE>
+<H3><A NAME="10_129_6">See Also</A></H3>
+ <A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>, <A HREF="#ppdPageSize">
+<CODE>ppdPageSize()</CODE></A>, <A HREF="#ppdPageWidth"><CODE>
+ppdPageWidth()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdPageSize">ppdPageSize()</A></H2>
+<H3><A NAME="10_130_1">Usage</A></H3>
+<PRE>
+ppd_size_t *
+ppdPageSize(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+<H3><A NAME="10_130_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>name</TD><TD>The name of the page size</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_130_3">Returns</A></H3>
+<P>A pointer to the page size record of the specified page size in
+ points or NULL if the page size does not exist.</P>
+<H3><A NAME="10_130_4">Description</A></H3>
+<P>The <CODE>ppdPageSize()</CODE> function returns the page size record
+ for the specified page size.</P>
+<H3><A NAME="10_130_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, &quot;Letter&quot;);
+if (size != NULL)
+{
+ printf(&quot; Width = %.0f\n&quot;, size-&gt;width);
+ printf(&quot;Length = %.0f\n&quot;, size-&gt;length);
+ printf(&quot; Left = %.0f\n&quot;, size-&gt;left);
+ printf(&quot; Right = %.0f\n&quot;, size-&gt;right);
+ printf(&quot;Bottom = %.0f\n&quot;, size-&gt;bottom);
+ printf(&quot; Top = %.0f\n&quot;, size-&gt;top);
+}
+</PRE>
+<H3><A NAME="10_130_6">See Also</A></H3>
+ <A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>, <A HREF="#ppdPageWidth">
+<CODE>ppdPageWidth()</CODE></A>
+<!-- NEW PAGE -->
+<H2><A NAME="ppdPageWidth">ppdPageWidth()</A></H2>
+<H3><A NAME="10_131_1">Usage</A></H3>
+<PRE>
+float
+ppdPageWidth(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+<H3><A NAME="10_131_2">Arguments</A></H3>
+<CENTER>
+<TABLE BORDER WIDTH="80%">
+<TR><TH>Argument</TH><TH>Description</TH></TR>
+<TR><TD>ppd</TD><TD>The PPD file</TD></TR>
+<TR><TD>name</TD><TD>The name of the page size</TD></TR>
+</TABLE>
+</CENTER>
+<H3><A NAME="10_131_3">Returns</A></H3>
+<P>The width of the specified page size in points or 0 if the page size
+ does not exist.</P>
+<H3><A NAME="10_131_4">Description</A></H3>
+<P>The <CODE>ppdPageWidth()</CODE> function returns the page width of
+ the specified page size.</P>
+<H3><A NAME="10_131_5">Example</A></H3>
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+ppd_file_t *ppd;
+
+printf(&quot;Width = %.0f\n&quot;, ppdPageWidth(ppd, &quot;Letter&quot;));
+</PRE>
+<H3><A NAME="10_131_6">See Also</A></H3>
+ <A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>, <A HREF="#ppdPageSize">
+<CODE>ppdPageSize()</CODE></A></BODY>
+</HTML>
diff --git a/doc/spm.pdf b/doc/spm.pdf
new file mode 100644
index 000000000..e6a4a3d95
--- /dev/null
+++ b/doc/spm.pdf
Binary files differ
diff --git a/doc/spm.shtml b/doc/spm.shtml
new file mode 100644
index 000000000..56660f239
--- /dev/null
+++ b/doc/spm.shtml
@@ -0,0 +1,10799 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SPM-1.1.22">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Programmers Manual</TITLE>
+</HEAD>
+<BODY>
+
+<H1 ALIGN="RIGHT">Preface</H1>
+
+<P>This software programmers manual provides software
+programming information for the Common UNIX Printing System
+("CUPS") Version 1.1.22.
+
+<EMBED SRC="system-overview.shtml">
+
+<!-- NEED 2in -->
+<H2>Document Overview</H2>
+
+<P>This software programmers manual is organized into the following sections:
+
+<UL>
+ <LI><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+ <LI><A HREF="#CUPS_API">2 - The CUPS API</A>
+ <LI><A HREF="#WRITING_FILTERS">3 - Writing Filters</A>
+ <LI><A HREF="#WRITING_DRIVERS">4 - Writing Printer Drivers</A>
+ <LI><A HREF="#WRITING_BACKENDS">5 - Writing Backends</A>
+ <LI><A HREF="#LICENSE">A - Software License Agreement</A>
+ <LI><A HREF="#CONSTANTS">B - Constants</A>
+ <LI><A HREF="#STRUCTURES">C - Structures</A>
+ <LI><A HREF="#FUNCTIONS">D - Functions</A>
+</UL>
+
+<H2>Notation Conventions</H2>
+
+<P>Various font and syntax conventions are used in this guide. Examples and
+their meanings and uses are explained below:
+
+<CENTER><TABLE WIDTH="80%">
+<TR>
+ <TH>Example</TH>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TH>Description</TH>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><CODE>lpstat</CODE><BR>
+ <CODE>lpstat(1)</CODE></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>The names of commands; the first mention of a command or
+ function in a chapter is followed by a manual page section
+ number.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><VAR>/var</VAR><BR>
+ <VAR>/usr/share/cups/data/testprint.ps</VAR></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>File and directory names.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><TT>Request ID is Printer-123</TT></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Screen output.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD>12.3</TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Numbers in the text are written using the period (.) to indicate
+ the decimal point.</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H2>Abbreviations</H2>
+
+The following abbreviations are used throughout this manual:
+
+<UL>
+<DL>
+
+ <DT>kb
+ <DD>Kilobytes, or 1024 bytes<BR>&nbsp;
+
+ <DT>Mb
+ <DD>Megabytes, or 1048576 bytes<BR>&nbsp;
+
+ <DT>Gb
+ <DD>Gigabytes, or 1073741824 bytes<BR>&nbsp;
+
+</DL>
+</UL>
+
+<H2>Other References</H2>
+
+<UL>
+<DL>
+
+ <DT>CUPS Software Administrators Manual
+
+ <DD>An administration guide for the CUPS software.<BR>&nbsp;
+
+ <DT>CUPS Software Users Manual
+
+ <DD>An end-user guide for using the CUPS software.<BR>&nbsp;
+
+</DL>
+</UL>
+
+
+<EMBED SRC="printing-overview.shtml">
+
+
+<H1 ALIGN="RIGHT"><A NAME="CUPS_API">2 - The CUPS API</A></H1>
+
+<P>This chapter describes the CUPS Application Programmers Interface ("API").
+
+<H2>The CUPS API Library</H2>
+
+<P>The CUPS library provides a whole collection of interfaces needed to
+support the internal needs of the CUPS software as well as the needs of
+applications, filters, printer drivers, and backends.
+
+<P>Unlike the rest of CUPS, the CUPS API library is provided under the
+GNU Library General Public License. This means that you can use the
+CUPS API library in both proprietary and open-source programs.
+
+<P>Programs that use the CUPS API library typically will include the
+<CODE>&lt;cups/cups.h&gt;</CODE> header file:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+jobid = cupsPrintFile("myprinter", "filename.ps", "title",
+ num_options, options);
+</PRE></UL>
+
+<P>Use the <CODE>-lcups</CODE> compiler option when linking to the CUPS API
+library:
+
+<UL><PRE>
+<B>cc -o program program.c -lcups ENTER</B>
+</PRE></UL>
+
+<P>Additional options and libraries may be required depending on the
+operating system and the location of the CUPS API library.
+
+<H3>Detecting the CUPS API Library in GNU Autoconf</H3>
+
+<P>GNU autoconf is a popular configuration tool used by many programs.
+Add the following lines to your <VAR>configure.in</VAR> file to check
+for the CUPS API library in your configuration script:
+
+<UL><PRE>
+AC_CHECK_LIB(socket,socket,
+if test "$uname" != "IRIX"; then
+ LIBS="-lsocket $LIBS"
+else
+ echo "Not using -lsocket since you are running IRIX."
+fi)
+AC_CHECK_LIB(nsl,gethostbyaddr,
+if test "$uname" != "IRIX"; then
+ LIBS="-lnsl $LIBS"
+else
+ echo "Not using -lnsl since you are running IRIX."
+fi)
+
+AC_CHECK_LIB(cups,httpConnect)
+</PRE></UL>
+
+<H2>Printing Services</H2>
+
+<P>The CUPS API library provides some basic printing services for applications
+that need to print files.
+
+<H3>Include Files</H3>
+
+<P>The include file used by all of these functions is
+<CODE>&lt;cups/cups.h&gt;</CODE>:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+</PRE></UL>
+
+<H3>Printing a File</H3>
+
+<P>The CUPS API provides two functions for printing files. The first is
+<CODE>cupsPrintFile</CODE> which prints a single named file:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+
+...
+
+jobid = cupsPrintFile("<I>name</I>", "<I>filename</I>", "<I>title</I>", 0, NULL);
+</PRE></UL>
+
+<P>The <CODE>name</CODE> string is the name of the printer or class to
+print to. The <CODE>filename</CODE> string is the name of the file to
+print. The <CODE>title</CODE> string is the name of the print job, e.g.
+"Acme Word Document".
+
+<P>The return value is a unique ID number for the print job or 0 if there
+was an error.
+
+<H3>Printing Multiple Files</H3>
+
+<P>The second printing function is <CODE>cupsPrintFiles</CODE>:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int num_files;
+const char *files[100];
+...
+
+jobid = cupsPrintFiles("name", <I>num_files</I>, <I>files</I>, "title", 0, NULL);
+</PRE></UL>
+
+<P>Instead of passing a filename string as with <CODE>cupsPrintFile()</CODE>
+you pass a file count (<CODE>num_files</CODE>) and filename pointer array
+(<CODE>files</CODE>) for each file that you want to print.
+
+<P>As with <CODE>cupsPrintFile()</CODE> the return value is a unique ID for
+the print job.
+
+<H3>Cancelling Jobs</H3>
+
+<P>The <CODE>cupsCancelJob()</CODE> function cancels a queued print job:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int status;
+...
+
+status = cupsCancelJob("<I>name</I>", <I>jobid</I>);
+</PRE></UL>
+
+<P>The <CODE>name</CODE> string specifies the destination and is used
+to determine the server to send the request to. The <CODE>jobid</CODE>
+value is the integer returned from a previous <CODE>cupsPrintFile()</CODE>
+or <CODE>cupsPrintFiles()</CODE> call.
+
+<P><CODE>cupsCancelJob()</CODE> returns <CODE>1</CODE> if the job was
+successfully cancelled and <CODE>0</CODE> if there was an error.
+
+<H3>Getting the Available Printers and Classes</H3>
+
+<P>The <CODE>cupsGetDests()</CODE> function can be used to get a list
+of the available printers, classes, and instances that a user has defined:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_dests;
+cups_dest_t *dests;
+
+...
+
+num_dests = cupsGetDests(&amp;dests);
+</PRE></UL>
+
+<P>Each destination is stored in a <CODE>cups_dest_t</CODE> structure which
+defines the printer or class name, the instance name (if any), if it is the
+default destination, and the default options the user has defined for the
+destination:
+
+<UL><PRE>
+typedef struct /**** Destination ****/
+{
+ char *name, /* Printer or class name */
+ *instance; /* Local instance name or NULL */
+ int is_default; /* Is this printer the default? */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+} cups_dest_t;
+</PRE></UL>
+
+<P>The destinations are sorted by name and instance for your convenience.
+Once you have the list of available destinations, you can lookup a specific
+destination using the <CODE>cupsGetDest()</CODE> function:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_dests;
+cups_dest_t *dests;
+cups_dest_t *mydest;
+
+...
+
+mydest = cupsGetDest("<I>name</I>", "<I>instance</I>", num_dests, dests);
+</PRE></UL>
+
+<P>The <CODE>name</CODE> string is the printer or class name. You can pass
+a value of <CODE>NULL</CODE> to get the default destination.
+
+<P>The <CODE>instance</CODE> string is the user-defined instance name. Pass
+<CODE>NULL</CODE> to select the default instance, e.g. "name" instead of
+"name/instance".
+
+<H3>Printing with Options</H3>
+
+<P>All of the previous printing examples have passed <CODE>0</CODE> and
+<CODE>NULL</CODE> for the last two arguments to the <CODE>cupsPrintFile()</CODE>
+and <CODE>cupsPrintFiles()</CODE> functions. These last two arguments are the
+number of options and a pointer to the option array:
+
+<UL><PRE>
+int cupsPrintFile(const char *name, const char *filename, const char *title,
+ int num_options, cups_option_t *options);
+int cupsPrintFiles(const char *name, int num_files, const char **files,
+ const char *title, int num_options,
+ cups_option_t *options);
+</PRE></UL>
+
+<P>The <CODE>cups_option_t</CODE> structure holds each option and its value.
+These are converted as needed and passed to the CUPS server when printing a
+file.
+
+<P>The simplest way of handling options is to use the <CODE>num_options</CODE>
+and <CODE>options</CODE> members of the <CODE>cups_dest_t</CODE>
+structure described earlier:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+int num_dests;
+cups_dest_t *dests;
+cups_dest_t *mydest;
+
+...
+
+mydest = cupsGetDest("<I>name</I>", "<I>instance</I>", num_dests, dests);
+
+jobid = cupsPrintFile(mydest-&gt;name, "filename", "title",
+ mydest-&gt;num_options, mydest-&gt;options);
+</PRE></UL>
+
+<P>This effectively uses the options a user has previous selected without a
+lot of code.
+
+<H3>Setting Printer Options</H3>
+
+<P>Options can also be set by your program using the <CODE>cupsAddOption()</CODE>
+function:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_options;
+cups_option_t *options;
+
+...
+
+num_options = 0;
+options = NULL;
+
+...
+
+num_options = cupsAddOption("<I>name</I>", "<I>value</I>", num_options, &amp;options);
+num_options = cupsAddOption("<I>name</I>", "<I>value</I>", num_options, &amp;options);
+num_options = cupsAddOption("<I>name</I>", "<I>value</I>", num_options, &amp;options);
+num_options = cupsAddOption("<I>name</I>", "<I>value</I>", num_options, &amp;options);
+</PRE></UL>
+
+<P>The <CODE>name</CODE> string is the name of the option, and the
+<CODE>value</CODE> string is the value for that option.
+
+<P>Each call to <CODE>cupsAddOption()</CODE> returns the new number of
+options. Since adding two options with the same name overwrites the
+first value with the second, do not assume that calling
+<CODE>cupsAddOptions()</CODE> 20 times will result in 20 options.
+
+<P>Call <CODE>cupsFreeOptions</CODE> once you are done using the options:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int num_options;
+cups_option_t *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+</PRE></UL>
+
+<H3>Getting Errors</H3>
+
+<P>If any of the CUPS API printing functions returns an error, the reason for
+that error can be found by calling <CODE>cupsLastError()</CODE> and
+<CODE>ippErrorString()</CODE>. <CODE>cupsLastError()</CODE> returns the
+last IPP error code that was encountered. <CODE>ippErrorString()</CODE>
+converts the error code to a localized message string suitable for
+presentation to the user:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+int jobid;
+
+...
+
+if (jobid == 0)
+ puts(ippErrorString(cupsLastError()));
+</PRE></UL>
+
+<H3>Passwords and Authentication</H3>
+
+<P>CUPS supports authentication of any request, including
+submission of print jobs. The default mechanism for getting the
+username and password is to use the login user and a password
+from the console.
+
+<P>To support other types of applications, in particular
+Graphical User Interfaces ("GUIs"), the CUPS API provides
+functions to set the default username and to register a callback
+function that returns a password string.
+
+<P>The <A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>
+function is used to set a password callback in your program. Only one
+function can be used at any time.
+
+<P>The <A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A> function sets
+the current username for authentication. This function can be called by
+your password callback function to change the current username as needed.
+
+<P>The following example shows a simple password callback that gets a
+username and password from the user:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *
+my_password_cb(const char *prompt)
+{
+ char user[65];
+
+
+ puts(prompt);
+
+ /* Get a username from the user */
+ printf("Username: ");
+ if (fgets(user, sizeof(user), stdin) == NULL)
+ return (NULL);
+
+ /* Strip the newline from the string and set the user */
+ user[strlen(user) - 1] = '\0';
+
+ cupsSetUser(user);
+
+ /* Use getpass() to ask for the password... */
+ return (getpass("Password: "));
+}
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+</PRE></UL>
+
+<P>Similarly, a GUI interface could display the prompt string in a
+window with input fields for the username and password. The username
+should probably default to the value of
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A> to make things easier
+on the user.
+
+<H2>PPD Services</H2>
+
+<P>CUPS includes functions to access and manipulate PostScript Printer
+Description ("PPD") files that are used with the printer drivers in CUPS.
+
+<P>Each PPD file enumerates the available features provided by a
+printer, including conflict information for specific options (e.g.
+can't duplex output on envelopes.)
+
+<H3>Include Files</H3>
+
+<P>Include the <CODE>&lt;cups/ppd.h&gt;</CODE> header file to use the PPD
+functions:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+</PRE></UL>
+
+<P>This header file is also included by the
+<CODE>&lt;cups/cups.h&gt;</CODE> header file.
+
+<H3>Getting a PPD File for a Printer</H3>
+
+<P>The <CODE>cupsGetPPD()</CODE> function retrieves the PPD file for the
+named printer or class:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+const char *filename;
+
+filename = cupsGetPPD("<I>name</I>");
+</PRE></UL>
+
+<P>The <CODE>name</CODE> string is the name of the printer or class, including
+the remote server name as appropriate (e.g. "printer@server".)
+
+<P>The return value is a pointer to a filename in static storage; this value
+is overwritten with each call to <CODE>cupsGetPPD()</CODE>. If the printer
+or class does not exist, a <CODE>NULL</CODE> pointer will be returned.
+
+<H3>Loading a PPD File</H3>
+
+<P>The <CODE>ppdOpenFile()</CODE> function "opens" a PPD file and loads it
+into memory:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("<I>filename</I>");
+</PRE></UL>
+
+<P>The <CODE>filename</CODE> string is the name of the file to load, such as
+the value returned by the <CODE>cupsGetPPD()</CODE> function.
+
+<P>The return value is a pointer to a structure describing the contents of the
+PPD file or NULL if the PPD file could not be read.
+
+<H3>Freeing PPD File Information</H3>
+
+<P>Once you are done using a PPD file, call the <CODE>ppdClose()</CODE> function
+to free all memory that has been used:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+...
+
+ppdClose(ppd);
+</PRE></UL>
+
+<H3>The PPD File Structure</H3>
+
+<P>Each PPD file contains a number of capability attributes, printer options,
+and conflict definitions. The page size options also include the physical
+margins for the printer and the minimum and maximum sizes for the printer.
+All of this information is stored in the <CODE>ppd_file_t</CODE> structure.
+
+<H4>Capabilities</H4>
+
+<P>Each PPD file contains a number of informational attributes that
+describe the capabilities of the printer. These are provided in the
+<CODE>ppd_file_t</CODE> structure in the following members:
+
+<CENTER><TABLE WIDTH="80%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD><CODE>accurate_screens</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = supports accurate screens</TD>
+</TR>
+<TR>
+ <TD><CODE>color_device</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = color device</TD>
+</TR>
+<TR>
+ <TD><CODE>colorspace</CODE></TD>
+ <TD><CODE>ppd_cs_t</CODE></TD>
+ <TD>Default colorspace: PPD_CS_CMYK, PPD_CS_CMY, PPD_CS_GRAY,
+ PPD_CS_RGB, PPD_CS_RGBK, PPD_CS_N</TD>
+</TR>
+<TR>
+ <TD><CODE>contone_only</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = printer is continuous tone only</TD>
+</TR>
+<TR>
+ <TD><CODE>num_emulations<BR>
+ emulations</CODE></TD>
+ <TD><CODE>int<BR>
+ ppd_emul_t *</CODE></TD>
+ <TD>Emulations supported by the printer</TD>
+</TR>
+<TR>
+ <TD><CODE>flip_duplex</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = need to flip odd pages when duplexing</TD>
+</TR>
+<TR>
+ <TD><CODE>num_fonts<BR>
+ fonts</CODE></TD>
+ <TD><CODE>int<BR>
+ char **</CODE></TD>
+ <TD>The fonts available on the printer.</TD>
+</TR>
+<TR>
+ <TD><CODE>jcl_begin<BR>
+ jcl_ps<BR>
+ jcl_end</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>Job Control Language commands for PostScript output</TD>
+</TR>
+<TR>
+ <TD><CODE>landscape</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>Landscape orientation, -90 or 90 degrees</TD>
+</TR>
+<TR>
+ <TD><CODE>lang_encoding</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The character used for the option strings</TD>
+</TR>
+<TR>
+ <TD><CODE>lang_version</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The language used for the options strings (English, French, etc.)</TD>
+</TR>
+<TR>
+ <TD><CODE>language_level</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>PostScript language level, 1 to 3</TD>
+</TR>
+<TR>
+ <TD><CODE>manual_copies</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = Copies are done manually</TD>
+</TR>
+<TR>
+ <TD><CODE>model_number</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>Driver-specific model number.</TD>
+</TR>
+<TR>
+ <TD><CODE>patches</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>Patch commands to send to the printer</TD>
+</TR>
+<TR>
+ <TD><CODE>manufacturer</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The Manufacturer attribute from the PPD file, if any</TD>
+</TR>
+<TR>
+ <TD><CODE>modelname</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The ModelName attribute from the PPD file</TD>
+</TR>
+<TR>
+ <TD><CODE>nickname</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The NickName attribute from the PPD file, if any</TD>
+</TR>
+<TR>
+ <TD><CODE>product</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The Product attribute from the PPD file, if any</TD>
+</TR>
+<TR>
+ <TD><CODE>shortnickname</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The ShortNickName attribute from the PPD file, if any</TD>
+</TR>
+<TR>
+ <TD><CODE>throughput</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>Number of pages per minute</TD>
+</TR>
+<TR>
+ <TD><CODE>ttrasterizer</CODE></TD>
+ <TD><CODE>char *</CODE></TD>
+ <TD>The TruType font rasterizer (Type42)</TD>
+</TR>
+<TR>
+ <TD><CODE>variable_sizes</CODE></TD>
+ <TD><CODE>int</CODE></TD>
+ <TD>1 = supports variable sizes</TD>
+</TR>
+</TABLE></CENTER>
+
+<H4>Options and Groups</H4>
+
+<P>PPD files support multiple options, which are stored in
+<CODE>ppd_option_t</CODE> and <CODE>ppd_choice_t</CODE> structures by
+the PPD functions.
+
+<P>Each option in turn is associated with a group
+stored in the <CODE>ppd_group_t</CODE> structure. Groups can be
+specified in the PPD file; if an option is not associated with a group
+then it is put in a "General" or "Extra" group depending on the option.
+
+<P>Groups can also have sub-groups; CUPS currently limits the depth of
+sub-groups to 1 level to reduce programming complexity.
+
+<H4>Conflicts</H4>
+
+<P>PPD files support specification of conflict conditions between
+different options. Conflicts are stored in <CODE>ppd_conflict_t</CODE>
+structures which specify the options that conflict with each other.
+
+<H4>Page Sizes</H4>
+
+<P>PPD files specify all of the available pages sizes and the physical
+margins associated with them. These sizes are stored in
+<CODE>ppd_size_t</CODE> structures and are available in the
+<CODE>num_sizes</CODE> and <CODE>sizes</CODE> members of the
+<CODE>ppd_file_t</CODE> structure. You can lookup a particular page size
+with the <CODE>ppdPageWidth()</CODE>, <CODE>ppdPageLength()</CODE>, and
+<CODE>ppdPageSize()</CODE> functions:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+float width;
+float length;
+
+...
+
+size = ppdPageSize(ppd, "<I>size</I>");
+width = ppdPageWidth(ppd, "<I>size</I>");
+length = ppdPageLength(ppd, "<I>size</I>");
+</PRE></UL>
+
+<P>The <CODE>size</CODE> string is the named page size option. The
+width and length are in points; there are 72 points per inch. The
+<CODE>ppd_size_t</CODE> structure contains the width, length, and
+margin information:
+
+<UL><PRE>
+typedef struct /**** Page Sizes ****/
+{
+ int marked; /* Page size selected? */
+ char name[41]; /* Media size option */
+ float width, /* Width of media in points */
+ length, /* Length of media in points */
+ left, /* Left printable margin in points */
+ bottom, /* Bottom printable margin in points */
+ right, /* Right printable margin in points */
+ top; /* Top printable margin in points */
+} ppd_size_t;
+</PRE></UL>
+
+<H4>Custom Page Sizes</H4>
+
+<P>Besides the standard page sizes listed in a PPD file, some printers
+support variable or custom page sizes. If <CODE>variables_sizes</CODE>
+is non-zero, the <CODE>custom_min</CODE>, <CODE>custom_max</CODE>, and
+<CODE>custom_margins</CODE> members of the <CODE>ppd_file_t</CODE>
+structure define the limits of the variable sizes.
+
+<P>To get the resulting media size, use a page size string of
+<CODE>Custom.<I>width</I>x<I>length</I></CODE>, where <CODE>width</CODE>
+and <CODE>length</CODE> are integer values in points:
+
+<UL><PRE>
+Custom.612x792 [8.5 inches wide, 11 inches long]
+Custom.1224x792 [17 inches wide, 11 inches long]
+</PRE></UL>
+
+<H3>Marking Options</H3>
+
+<P>Before marking any user-defined options, call the <CODE>ppdMarkDefaults()</CODE>
+function to mark the default options from the PPD file:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+
+...
+
+ppdMarkDefaults(ppd);
+</PRE></UL>
+
+<P>Then call the <CODE>ppdMarkOption()</CODE> function to mark individual
+options:
+
+<UL><PRE>
+#include &lt;cups/ppd.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int conflicts;
+
+...
+
+conflicts = ppdMarkOption(ppd, "<I>name</I>", "<I>value</I>");
+</PRE></UL>
+
+<P>The <CODE>name</CODE> and <CODE>value</CODE> strings choose a
+particular option and choice, respectively. The return value is 0
+if there are not conflicts created by the selection.
+
+<P>CUPS also provides a convenience function for marking all options
+in the <CODE>cups_option_t</CODE> structure:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int num_options;
+cups_option_t *options;
+int conflicts;
+
+...
+
+conflicts = cupsMarkOptions(ppd, num_options, options);
+</PRE></UL>
+
+<P>The <CODE>cupsMarkOptions()</CODE> function also handles mapping the
+IPP job template attributes to PPD options. The return value is the number
+of conflicts present.
+
+<H3>Checking for Conflicts</H3>
+
+<P>The <CODE>ppdMarkOption()</CODE> and <CODE>cupsMarkOptions()</CODE>
+functions return the number of conflicts with the currently marked options.
+
+<P>Call the <CODE>ppdConflicts()</CODE> function to get the number of
+conflicts after you have marked all of the options:
+
+<UL><PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+ppd_file_t *ppd;
+int conflicts;
+
+...
+
+conflicts = ppdConflicts(ppd);
+</PRE></UL>
+
+<P>The return value is the number of conflicting options, or 0 if there
+are no conflicts.
+
+
+<H1 ALIGN="RIGHT"><A NAME="WRITING_FILTERS">3 - Writing Filters</A></H1>
+
+<P>This chapter describes how to write a file filter for CUPS.
+
+<H2>Overview</H2>
+
+<P>File filters are programs that convert from one or more MIME types to
+another type. Filters use a common command-line and environment interface
+that allows them to be joined as needed to print files to any type of
+printer.
+
+<H3>Security Considerations</H3>
+
+<P>Filters are normally run as a non-priviledged user, so the major
+security consideration is resource utilization - filters should not
+depend on unlimited amounts of memory and disk space.
+
+<H3>Users and Groups</H3>
+
+<P>The default CUPS configuration runs filters as user "lp" and group "other".
+
+<H3>Temporary Files</H3>
+
+<P>Temporary files should be created in the directory specified by the
+"TMPDIR" environment variable. The
+<A HREF="#cupsTempFile"><CODE>cupsTempFile()</CODE></A> function can be
+used to safely choose temporary files in this directory.
+
+<H3>Sending Messages to the User</H3>
+
+<P>The CUPS scheduler collects messages sent to the standard error file
+by the filter. These messages are relayed to the user based upon the
+scheduler <CODE>LogLevel</CODE> directive.
+
+<P>The type of message is determined by an initial prefix sent on each
+line:
+
+<UL>
+
+ <LI><CODE>DEBUG:</CODE> - a debug message
+
+ <LI><CODE>INFO:</CODE> - an informational message
+
+ <LI><CODE>WARNING:</CODE> - a warning message
+
+ <LI><CODE>ERROR:</CODE> - an error message
+
+ <LI><CODE>PAGE:</CODE> - a page accounting message
+
+</UL>
+
+<P>If the line of text does not begin with any of the above prefixes, it
+is treated as a debug message. Text following the prefix is copied to the
+<CODE>printer-state-message</CODE> attribute for the printer, and also
+added to the <VAR>error_log</VAR> unless it is an informational or page
+accounting message.
+
+<H3>Page Accounting</H3>
+
+<P>Page accounting messages are used to inform the server when one or more
+pages are printed. Each line has the form:
+
+<UL><PRE>
+PAGE: page-number copy-count
+</PRE></UL>
+
+<P>The <I>page-number</I> field is the current page number, starting at 1.
+The <I>copy-count</I> field specifies the number of copies of that page
+that was produced.
+
+<P>Page account messages are added to the <VAR>page_log</VAR> file and
+cause the <CODE>job-sheets-completed</CODE> attribute to be updated for
+the job.
+
+<H3>Command-Line Arguments</H3>
+
+<P>Every filter accepts exactly 6 or 7 command-line arguments:
+
+<UL><PRE>
+printer job user title copies options [filename]
+</PRE>
+
+ <LI><CODE>printer</CODE> - The name of the printer queue (normally
+ this is the name of the program being run)
+
+ <LI><CODE>job</CODE> - The numeric job ID for the job being
+ printed
+
+ <LI><CODE>user</CODE> - The string from the
+ <CODE>originating-user-name</CODE> attribute
+
+ <LI><CODE>title</CODE> - The string from the
+ <CODE>job-name</CODE> attribute
+
+ <LI><CODE>copies</CODE> - The numeric value from the
+ <CODE>number-copies</CODE> attribute
+
+ <LI><CODE>options</CODE> - String representations of the
+ job template attributes, separated by spaces. Boolean attributes
+ are provided as "name" for true values and "noname" for false
+ values. All other attributes are provided as "name=value" for
+ single-valued attributes and "name=value1,value2,...,valueN" for
+ set attributes
+
+ <LI><CODE>filename</CODE> - The request file
+
+</UL>
+
+<P>The <I>filename</I> argument is only provided to the first filter in the
+chain; all filters <B>must</B> be prepared to read the print file from
+the standard input if the <I>filename</I> argument is omitted.
+
+<H3>Copy Generation</H3>
+
+<P>The <I>copies</I> argument specifies the number of copies to produce
+of the input file. In general, you should only generate copies if the
+<I>filename</I> argument is supplied. The only exception to this are
+filters that produce device-independent PostScript output (without any
+printer commands from the printer's PPD file), since the PostScript
+filter <CODE>pstops</CODE> is responsible for copy generation.
+
+<H3>Environment Variables</H3>
+
+<P>Every filter receives a fixed set of environment variables that can
+be used by the filter:
+
+<UL>
+
+ <LI><CODE>CHARSET</CODE> - The character set used by the client for
+ this print file
+
+ <LI><CODE>CONTENT_TYPE</CODE> - The original document type, such as
+ "application/postscript"
+
+ <LI><CODE>CUPS_DATADIR</CODE> - The location of CUPS data files
+
+ <LI><CODE>CUPS_SERVERROOT</CODE> - The location of CUPS configuration
+ files
+
+ <LI><CODE>DEVICE_URI</CODE> - The output device URI
+
+ <LI><CODE>LANG</CODE> - The language used by the client for
+ this print file
+
+ <LI><CODE>PATH</CODE> - The execution path exported to the filter
+
+ <LI><CODE>PPD</CODE> - The full filename of the printer's PPD file
+
+ <LI><CODE>PRINTER</CODE> - The name of the printer queue
+
+ <LI><CODE>RIP_CACHE</CODE> - The maximum amount of memory each filter
+ should use
+
+ <LI><CODE>SOFTWARE</CODE> - The name of the CUPS software, typically
+ "CUPS/1.1"
+
+ <LI><CODE>TZ</CODE> - The local timezone
+
+ <LI><CODE>USER</CODE> - The name of the current user
+
+</UL>
+
+<H2>Dissecting the HP-GL/2 Filter</H2>
+
+<P>The HP-GL/2 filter (<CODE>hpgltops</CODE>) provided with CUPS is a
+complex program that converts HP-GL/2 files into device-independent PostScript
+output. Since it produces device-independent PostScript output, it does not
+need to handle copy generation or writing printer options from the printer's
+PPD file.
+
+<H3>Initializing the Filter</H3>
+
+<P>The first task of any filter is to ensure that the correct number of
+command-line arguments are present:
+
+<UL><PRE>
+if (argc &lt; 6 || argc > 7)
+{
+ fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
+ return (1);
+}
+</PRE></UL>
+
+<P>After this you open the print file or read from the standard input
+as needed:
+
+<UL><PRE>
+FILE *fp;
+
+/*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+if (argc == 6)
+ fp = stdin;
+else
+{
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = fopen(argv[6], "rb")) == NULL)
+ {
+ perror("ERROR: unable to open print file - ");
+ return (1);
+ }
+}
+</PRE></UL>
+
+<P>Once the print file has been opened, options can be processed using
+the <A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A> and
+<A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A> functions:
+
+<UL><PRE>
+int num_options;
+cups_option_t *options;
+const char *val;
+
+/*
+ * Process command-line options and write the prolog...
+ */
+
+options = NULL;
+num_options = cupsParseOptions(argv[5], 0, &amp;options);
+
+if ((val = cupsGetOption("blackplot", num_options, options)) != NULL)
+ shading = 0;
+
+if ((val = cupsGetOption("fitplot", num_options, options)) != NULL)
+ FitPlot = 1;
+
+if ((val = cupsGetOption("penwidth", num_options, options)) != NULL)
+ PenWidth = (float)atoi(val) * 0.001f;
+</PRE></UL>
+
+<P>After the options have been processed, the filter writes PostScript code
+to the standard output based on the print file, closes the print file (as
+needed), and returns 0 to the scheduler.
+
+<H2>PostScript Output</H2>
+
+<P>Filters that produce PostScript output must generate output conforming
+to the Adobe Document Structuring Conventions, 3.0. In general this means
+the beginning of each file must begin with:
+
+<UL><PRE>
+%!PS-Adobe-3.0
+%%BoundingBox: left bottom right top
+%%Pages: (atend)
+%%EndComments
+</PRE></UL>
+
+<P>The <I>left</I>, <I>bottom</I>, <I>right</I>, and <I>top</I> values
+are integers in points from the lower-lefthand corner of the page.
+
+<P>Pages must be surrounded by:
+
+<UL><PRE>
+%%Page: number number
+gsave
+...
+grestore
+showpage
+</PRE></UL>
+
+<P>And the end of each file must contain:
+
+<UL><PRE>
+%%Trailer
+%%Pages: number-pages
+%%EOF
+</PRE></UL>
+
+<P>These comments allow the PostScript filter to correctly perform page
+accounting, copy generation, N-up printing, and so forth.
+
+<H1 ALIGN="RIGHT"><A NAME="WRITING_DRIVERS">4 - Writing Printer Drivers</A></H1>
+
+<P>This chapter discusses how to write a printer driver, which is a
+special filter program that converts CUPS raster data into the
+appropriate commands and data required for a printer.
+
+<H2>Overview</H2>
+
+<P>Raster printers utilitize PPD files that specify one or more
+device-specific filters that handle converting print files for the
+printer. The simplest raster printer drivers provide a single filter
+that converts CUPS raster data to the printer's native format.
+
+<H3>CUPS Raster Data</H3>
+
+<P>CUPS raster data (<CODE>application/vnd.cups-raster</CODE>) consists of
+a stream of raster page descriptions produced by one of the RIP filters,
+such as <CODE>pstoraster</CODE> or <CODE>imagetoraster</CODE>.
+
+<P>Each page of data begins with a page dictionary structure called
+<A HREF="#cups_raster_header_t"><CODE>cups_raster_header_t</CODE></A>. This
+structure contains the colorspace, bits per color, media size, media type,
+hardware resolution, and so forth.
+
+<P>After the page dictionary comes the page data which is a full-resolution,
+uncompressed bitmap representing the page in the printer's output colorspace.
+
+<H3>Page Accounting</H3>
+
+<P>Printer drivers must handle all page accounting. This means they must
+send "PAGE:" messages to the standard error file for each page (and in many
+cases, copy) sent to the printer.
+
+<H3>Color Management</H3>
+
+<P>Printer drivers can implement their color management via the
+<CODE>cupsColorProfile</CODE> attributes in the PPD file or internally
+in the driver from a device-independent colorspace. In general, color
+management performed by the RIP filters is more efficient than that
+performed inside printer drivers.
+
+<P>For example, the <CODE>pstoraster</CODE> filter often only has to
+perform a color conversion once each time the color is used for
+multiple output pixels, while the raster filter must convert every
+pixel on the page.
+
+<H3>Device and Bitmap Variables</H3>
+
+<P>Besides the standard PostScript page device dictionary variables defined
+in the Adobe PostScript Level 3 reference manual, the CUPS filters support
+additional variables that are passed in the page device dictionary header for
+the page and in some cases control the type of raster data that is generated:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Variable</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>cupsWidth</TD>
+ <TD>read-only integer</TD>
+ <TD>Width of bitmap in pixels</TD>
+</TR>
+<TR>
+ <TD>cupsHeight</TD>
+ <TD>read-only integer </TD>
+ <TD>Height of bitmap in pixels</TD>
+</TR>
+<TR>
+ <TD>cupsMediaType</TD>
+ <TD>read-write integer</TD>
+ <TD>Device-specific media type code</TD>
+</TR>
+<TR>
+ <TD>cupsBitsPerColor</TD>
+ <TD>read-write integer</TD>
+ <TD>Number of bits per color; 1, 2, 4, and 8 are currently
+ supported</TD>
+</TR>
+<TR>
+ <TD>cupsBitsPerPixel</TD>
+ <TD>read-only integer </TD>
+ <TD>Number of bits per pixel; 1 to 32</TD>
+</TR>
+<TR>
+ <TD>cupsBytesPerLine</TD>
+ <TD>read-only integer</TD>
+ <TD>Number of bytes per line of raster graphics</TD>
+</TR>
+<TR>
+ <TD>cupsColorOrder</TD>
+ <TD>read-write enum</TD>
+ <TD>The order of color values in the bitmap:
+ <UL>
+ <LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK
+ <LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK
+ <LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...
+ </UL>
+ </TD>
+</TR>
+<TR>
+ <TD>cupsColorSpace</TD>
+ <TD>read-write enum</TD>
+ <TD>The colorspace of the bitmap:
+ <UL>
+ <LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)
+ <LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue
+ <LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha
+ <LI><CODE>CUPS_CSPACE_K</CODE> - Black
+ <LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow
+ <LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan
+ <LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black
+ <LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black
+ <LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow
+ <LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta
+ <LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic magenta,
+ metallic cyan, black
+ <LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic magenta,
+ metallic cyan, metallic grey (silver)
+ <LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white pigment)
+ <LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)
+ <LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)
+ </UL>
+ </TD>
+</TR>
+<TR>
+ <TD>cupsCompression</TD>
+ <TD>read-write integer</TD>
+ <TD>Device-specific compression type code</TD>
+</TR>
+<TR>
+ <TD>cupsRowCount</TD>
+ <TD>read-write integer</TD>
+ <TD>Device-specific row count value</TD>
+</TR>
+<TR>
+ <TD>cupsRowFeed</TD>
+ <TD>read-write integer</TD>
+ <TD>Device-specific row feed value</TD>
+</TR>
+<TR>
+ <TD>cupsRowStep</TD>
+ <TD>read-write integer</TD>
+ <TD>Device-specific row step value</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>Bitmaps with a colorspace of CUPS_CSPACE_KCMYcm and more than 1 bit per
+color are transmitted to the raster driver in KCMY colorspace; the driver
+is responsible for producing the correct separation of normal and light
+cyan and magenta inks.
+
+<H2>Dissecting the HP-PCL Driver</H2>
+
+<P>The HP-PCL driver provided with CUPS (<CODE>rastertohp</CODE>) converts
+bitmap data from the raster filters into HP-PCL commands for most
+PCL-compatible printers. The actual format of the raster data is controlled
+by the PPD file being used - <VAR>deskjet.ppd</VAR> or <VAR>laserjet.ppd</VAR>.
+
+<H3>PPD Files</H3>
+
+<P>PPD files play an important part of all raster printer drivers. Options
+defined in the PPD file contain PostScript commands that control the raster
+data that is sent to the printer driver.
+
+<P>A typical CUPS printer driver will include <CODE>ColorModel</CODE>,
+<CODE>InputSlot</CODE>, <CODE>PageSize</CODE>, <CODE>PageRegion</CODE>,
+and <CODE>Resolution</CODE> options. Each option is shown using the
+standard PPD format:
+
+<UL><PRE>
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "&lt;&lt;
+/PageSize [612 792]
+/ImagingBBox null
+>> setpagedevice"
+*End
+*PageSize Legal/US Legal: "&lt;&lt;
+/PageSize [612 1008]
+/ImagingBBox null
+>> setpagedevice"
+*End
+*PageSize A4/A4: "&lt;&lt;
+/PageSize [595 842]
+/ImagingBBox null
+>> setpagedevice"
+*End
+*CloseUI: *PageSize
+</PRE></UL>
+
+<P>The <CODE>OpenUI</CODE> keyword specifies the new option. The first
+name is the option with an asterisk (*) in front of it. The first name is
+usually followed by a slash (/) and a human-readable version of the
+option name.
+
+<P>Every option <B>must</B> have a default value, specified using the
+<CODE>Default<I>Option</I></CODE> keyword.
+
+<P>Each option begins with the option name followed by the computer and
+human-readable values. The PostScript commands follow these inside double
+quotes. PostScript commands can be provided on a single line:
+
+<UL><PRE>
+*PageSize A4/A4: "&lt;&lt;/PageSize[595 842]/ImagingBBox null>> setpagedevice"
+</PRE></UL>
+
+<P>or broken down on separate lines using the <CODE>End</CODE> keyword to
+terminate them:
+
+<UL><PRE>
+*PageSize A4/A4: "&lt;&lt;
+/PageSize [595 842]
+/ImagingBBox null
+>> setpagedevice"
+*End
+</PRE></UL>
+
+<P>The choice of the two formats is usually esthetic. However, each line in
+a PPD file must not exceed 255 characters, so if your PostScript commands are
+long you may need to break them up on separate lines.
+
+<H3>Reading Raster Data</H3>
+
+<P>As with any filter, your printer driver should handle raster data from
+a filename specified on the command-line or from the standard input. The
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A> function opens
+a raster stream for printing:
+
+<UL><PRE>
+int fd; /* File descriptor */
+cups_raster_t *ras; /* Raster stream for printing */
+
+
+/*
+ * Check for valid arguments...
+ */
+
+if (argc &lt; 6 || argc > 7)
+{
+ /*
+ * We don't have the correct number of arguments; write an error message
+ * and return.
+ */
+
+ fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr);
+ return (1);
+}
+
+/*
+ * Open the page stream...
+ */
+
+if (argc == 7)
+{
+ if ((fd = open(argv[6], O_RDONLY)) == -1)
+ {
+ perror("ERROR: Unable to open raster file - ");
+ sleep(1);
+ return (1);
+ }
+}
+else
+ fd = 0;
+
+ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
+</PRE></UL>
+
+<P>Once you have opened the raster stream you just need to read each
+page and print it:
+
+<UL><PRE>
+cups_raster_header_t header;
+int y;
+unsigned char data[8192];
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ... initialize the printer ...
+ for (y = header.cupsHeight; y > 0; y ++)
+ {
+ cupsRasterReadPixels(ras, data, header.cupsBytesPerLine);
+ ... send raster line to printer ...
+ }
+}
+</PRE></UL>
+
+<P>After you have processed all pages, close the raster stream and
+return:
+
+<UL><PRE>
+cupsRasterClose(ras);
+
+return (0);
+</PRE></UL>
+
+<H1 ALIGN="RIGHT"><A NAME="WRITING_BACKENDS">5 - Writing Backends</A></H1>
+
+<P>This chapter describes how to write a backend for CUPS. Backends
+communicate directly with printers and allow printer drivers and
+filters to send data using any type of connection transparently.
+
+<H2>Overview</H2>
+
+<P>Backends are special filters that communicate with printers directly.
+They are treated slightly differently than filters, however, and have some
+unique requirements.
+
+<H3>Security Considerations</H3>
+
+<P>Backends are run as the root user, so special care must be taken to
+avoid potential security violations. In particular, remember that a backend
+will be able to manipulate disk files, devices, and other resources that
+potentially could damage a system or printer.
+
+<H3>Command-Line Arguments</H3>
+
+<P>Besides the standard filter arguments, backends are also run with no
+arguments to get a list of available devices. This discovery process is
+described later in this chapter.
+
+<H3>Copy Generation</H3>
+
+<P>Like filters, backends should send multiple copies of the print file only
+if a filename is supplied on the command-line. Otherwise the backend should
+assume that the upstream filter has already added the necessary commands or
+data to produce the multiple copies.
+
+<H3>Page Accounting</H3>
+
+<P>Backend filters generally do not do page accounting, however they should
+at a minimum produce a single page message for each copy that is produced
+when a filename is present on the command-line. This is because the user
+selected "raw" printing and no other accounting information is possible.
+
+<H3>Exclusive Access</H3>
+
+<P>Backends that talk to local character or block devices should open the
+device file in exclusive mode (<CODE>O_EXCL</CODE>) to cooperate with other
+printers defined for the same device.
+
+<H3>Retries</H3>
+
+<P>All backends <B>must</B> retry connections to the device. This
+includes backends that talk to local character or block devices, as the
+user may define more than one printer queue pointing at the same
+physical device.
+
+<P>To prevent excess CPU utilitization, the backend should go to sleep
+for an amount of time between retries; the CUPS-supplied backends retry
+once every 30 seconds.
+
+<H2>Dissecting the Serial Port Backend</H2>
+
+<P>The serial port backend provides support for serial printers. Since
+it does everything a good backend needs to do, it provides an excellent
+example of what to do.
+
+<H3>Supporting Device Discovery</H3>
+
+<P>As previously noted, backends are special filter programs that talk
+to printer devices. Another task a backend must perform is to list the
+available devices it supports. The backend lists the available devices
+when no additioanl arguments are supplied on the command-line (i.e.
+just the command name...)
+
+<P>The serial backend lists devices by looking at serial port files in the
+<VAR>/dev</VAR> directory, by consulting a hardware inventory (IRIX), and
+in some cases by trying to open the ports to see if they actually exist.
+
+<P>Once it finds a serial port it writes a single line for each port to
+the standard output file. Each line looks like this:
+
+<UL><PRE>
+serial serial:/dev/ttyS0?baud=115200 "Unknown" "Serial Port 1"
+</PRE></UL>
+
+<P>The first word "serial" is the <I>device class</I>; this identifies the
+class of device which can be used to categorize it in user interfaces. CUPS
+currently recognizes the following classes:
+
+<UL>
+
+ <LI>"file" - a disk file.
+
+ <LI>"direct" - a parallel or fixed-rate serial data port,
+ currently used for Centronics, IEEE-1284, and USB printer
+ ports.
+
+ <LI>"serial" - a variable-rate serial port.
+
+ <LI>"network" - a network connection, typically via AppSocket,
+ HTTP, IPP, LPD, or SMB/CIFS protocols.
+
+</UL>
+
+<P>After the device class is the <I>device URI</I>, in this case
+"serial:/dev/ttyS0?baud=115200". This is the URI that should be used by
+the user to select this port. For serial ports, the "baud=115200"
+specifies the maximum baud rate supported by the port - the actual
+value will vary based on the speed the user selects for the printer.
+
+<P>The last two strings are the model and description for the port. The
+"Unknown" string means that the printer model is unknown - some devices
+are able to provide a make and model such as "HP DeskJet" that allows
+users and software to choose an appropriate printer driver more easily.
+Both the model and description must be enclosed inside double quotes.
+
+<H3>Opening the Serial Port</H3>
+
+<P>As noted previously, all backends should open device files in exclusive
+mode, and retry as needed until the port is available. The serial port does
+this using a <CODE>do-while</CODE> loop:
+
+<UL><PRE>
+do
+{
+ if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL)) == -1)
+ {
+ if (errno == EBUSY)
+ {
+ fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
+ sleep(30);
+ }
+ else
+ {
+ perror("ERROR: Unable to open serial port device file");
+ return (1);
+ }
+ }
+}
+while (fd &lt; 0);
+</PRE></UL>
+
+<P>If the port is busy or in use by another process, the backend will
+go to sleep for 30 seconds and try again. If another error is detected
+a message is sent to the user and the backend aborts the print job
+until the problem can be corrected.
+
+<H3>Writing Data to the Port</H3>
+
+<P>Network and character devices pose an interesting problem when writing
+data to the port - they may not be able to write all of the bytes in your
+buffer before returning. To work around this problem you must loop until
+all bytes have been written:
+
+<UL><PRE>
+while (nbytes > 0)
+{
+ if ((wbytes = write(fd, bufptr, nbytes)) &lt; 0)
+ if (errno == ENOTTY)
+ wbytes = write(fd, bufptr, nbytes);
+
+ if (wbytes &lt; 0)
+ {
+ perror("ERROR: Unable to send print file to printer");
+ break;
+ }
+
+ nbytes -= wbytes;
+ bufptr += wbytes;
+}
+</PRE></UL>
+
+<P>The check for the <CODE>ENOTTY</CODE> error is needed on some platforms
+to clear an error from a previous <CODE>ioctl()</CODE> call.
+
+<H3>Finishing Up</H3>
+
+<P>Once you have sent the print file, return 0 if the file printed
+successfully or 1 if it did not. This will allow the scheduler to stop
+the print job if there is a device error, preserving the print job for
+later printing once the problem has been corrected.
+
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
+
+<EMBED SRC="../LICENSE.html">
+
+
+<H1 ALIGN="RIGHT"><A NAME="CONSTANTS">B - Constants</A></H1>
+
+<P>This appendix lists all of the constants that are defined by the CUPS
+API.
+
+<H2>CUPS Constants</H2>
+
+<H3>Version Number</H3>
+
+<P>The <CODE>CUPS_VERSION</CODE> constant is a floating-point number
+representing the API version number. The current version number is
+1.0100 which represents CUPS version 1.1.0.
+
+<H3>Printer Capabilities</H3>
+
+<P>The <CODE>CUPS_PRINTER</CODE> constants represent capability bits for
+printers and classes:
+
+<UL>
+
+ <LI><CODE>CUPS_PRINTER_LOCAL</CODE> - Is a local printer or class.
+
+ <LI><CODE>CUPS_PRINTER_REMOTE</CODE> - Is a remote printer or class.
+
+ <LI><CODE>CUPS_PRINTER_CLASS</CODE> - Is a class.
+
+ <LI><CODE>CUPS_PRINTER_BW</CODE> - Printer prints in black and white.
+
+ <LI><CODE>CUPS_PRINTER_COLOR</CODE> - Printer prints in color.
+
+ <LI><CODE>CUPS_PRINTER_DUPLEX</CODE> - Printer can print double-sided.
+
+ <LI><CODE>CUPS_PRINTER_STAPLE</CODE> - Printer can staple output.
+
+ <LI><CODE>CUPS_PRINTER_COPIES</CODE> - Printer can produce multiple
+ copies on its own.
+
+ <LI><CODE>CUPS_PRINTER_COLLATE</CODE> - Printer can collate copies.
+
+ <LI><CODE>CUPS_PRINTER_PUNCH</CODE> - Printer can punch holes in output.
+
+ <LI><CODE>CUPS_PRINTER_COVER</CODE> - Printer can put covers on output.
+
+ <LI><CODE>CUPS_PRINTER_BIND</CODE> - Printer can bind output.
+
+ <LI><CODE>CUPS_PRINTER_SORT</CODE> - Printer can sort output.
+
+ <LI><CODE>CUPS_PRINTER_SMALL</CODE> - Printer can print on media up
+ to 9x14 inches.
+
+ <LI><CODE>CUPS_PRINTER_MEDIUM</CODE> - Printer can print on media
+ from 9x14 to 18x24 inches.
+
+ <LI><CODE>CUPS_PRINTER_LARGE</CODE> - Printer can print on media
+ larger than 18x24 inches.
+
+ <LI><CODE>CUPS_PRINTER_VARIABLE</CODE> - Printer can print on
+ variable or custom media sizes.
+
+ <LI><CODE>CUPS_PRINTER_IMPLICIT</CODE> - Is an implicit class.
+
+ <LI><CODE>CUPS_PRINTER_OPTIONS</CODE> - All of the printer capability
+ and option bits.
+
+</UL>
+
+<H3>Encodings</H3>
+
+<P>CUPS defines the following character set encoding constants:
+
+<UL>
+
+ <LI><CODE>CUPS_US_ASCII</CODE> - US ASCII character set.
+
+ <LI><CODE>CUPS_UTF_8</CODE> - UTF-8 encoding of Unicode.
+
+ <LI><CODE>CUPS_ISO8859_1</CODE> - ISO-8859-1 character set.
+
+ <LI><CODE>CUPS_ISO8859_2</CODE> - ISO-8859-2 character set.
+
+ <LI><CODE>CUPS_ISO8859_3</CODE> - ISO-8859-3 character set.
+
+ <LI><CODE>CUPS_ISO8859_4</CODE> - ISO-8859-4 character set.
+
+ <LI><CODE>CUPS_ISO8859_5</CODE> - ISO-8859-5 character set.
+
+ <LI><CODE>CUPS_ISO8859_6</CODE> - ISO-8859-6 character set.
+
+ <LI><CODE>CUPS_ISO8859_7</CODE> - ISO-8859-7 character set.
+
+ <LI><CODE>CUPS_ISO8859_8</CODE> - ISO-8859-8 character set.
+
+ <LI><CODE>CUPS_ISO8859_9</CODE> - ISO-8859-9 character set.
+
+ <LI><CODE>CUPS_ISO8859_10</CODE> - ISO-8859-10 character set.
+
+ <LI><CODE>CUPS_ISO8859_13</CODE> - ISO-8859-13 character set.
+
+ <LI><CODE>CUPS_ISO8859_14</CODE> - ISO-8859-14 character set.
+
+ <LI><CODE>CUPS_ISO8859_15</CODE> - ISO-8859-15 character set.
+
+ <LI><CODE>CUPS_WINDOWS_874</CODE> - Windows code page 874.
+
+ <LI><CODE>CUPS_WINDOWS_1250</CODE> - Windows code page 1250.
+
+ <LI><CODE>CUPS_WINDOWS_1251</CODE> - Windows code page 1251.
+
+ <LI><CODE>CUPS_WINDOWS_1252</CODE> - Windows code page 1252.
+
+ <LI><CODE>CUPS_WINDOWS_1253</CODE> - Windows code page 1253.
+
+ <LI><CODE>CUPS_WINDOWS_1254</CODE> - Windows code page 1254.
+
+ <LI><CODE>CUPS_WINDOWS_1255</CODE> - Windows code page 1255.
+
+ <LI><CODE>CUPS_WINDOWS_1256</CODE> - Windows code page 1256.
+
+ <LI><CODE>CUPS_WINDOWS_1257</CODE> - Windows code page 1257.
+
+ <LI><CODE>CUPS_WINDOWS_1258</CODE> - Windows code page 1258.
+
+ <LI><CODE>CUPS_KOI8_R</CODE> - Russian code page koi8-r.
+
+ <LI><CODE>CUPS_KOI8_U</CODE> - Ukrainian code page koi8-r.
+
+</UL>
+
+<H2>HTTP Constants</H2>
+
+<H3>Limits</H3>
+
+<P>The following constants define the limits for strings:
+
+<UL>
+
+ <LI><CODE>HTTP_MAX_BUFFER</CODE> - Size of socket buffer.
+
+ <LI><CODE>HTTP_MAX_HOST</CODE> - Maximum length of hostname.
+
+ <LI><CODE>HTTP_MAX_URI</CODE> - Maximum length of URI.
+
+ <LI><CODE>HTTP_MAX_VALUE</CODE> - Maximum length of field values.
+
+</UL>
+
+<H3>Status Codes</H3>
+
+<P>The following status codes can be returned by <CODE>httpUpdate()</CODE>:
+
+<UL>
+
+ <LI><CODE>HTTP_ERROR</CODE> - A network error occurred
+
+ <LI><CODE>HTTP_CONTINUE</CODE> - Continue response from HTTP proxy
+
+ <LI><CODE>HTTP_OK</CODE> - OPTIONS/GET/HEAD/POST/TRACE command was successful
+
+ <LI><CODE>HTTP_CREATED</CODE> - PUT command was successful
+
+ <LI><CODE>HTTP_ACCEPTED</CODE> - DELETE command was successful
+
+ <LI><CODE>HTTP_NOT_AUTHORITATIVE</CODE> - Information isn't authoritative
+
+ <LI><CODE>HTTP_NO_CONTENT</CODE> - Successful command
+
+ <LI><CODE>HTTP_RESET_CONTENT</CODE> - Content was reset/recreated
+
+ <LI><CODE>HTTP_PARTIAL_CONTENT</CODE> - Only a partial file was recieved/sent
+
+ <LI><CODE>HTTP_MULTIPLE_CHOICES</CODE> - Multiple files match request
+
+ <LI><CODE>HTTP_MOVED_PERMANENTLY</CODE> - Document has moved permanently
+
+ <LI><CODE>HTTP_MOVED_TEMPORARILY</CODE> - Document has moved temporarily
+
+ <LI><CODE>HTTP_SEE_OTHER</CODE> - See this other link...
+
+ <LI><CODE>HTTP_NOT_MODIFIED</CODE> - File not modified
+
+ <LI><CODE>HTTP_USE_PROXY</CODE> - Must use a proxy to access this URI
+
+ <LI><CODE>HTTP_BAD_REQUEST</CODE> - Bad request
+
+ <LI><CODE>HTTP_UNAUTHORIZED</CODE> - Unauthorized to access host
+
+ <LI><CODE>HTTP_PAYMENT_REQUIRED</CODE> - Payment required
+
+ <LI><CODE>HTTP_FORBIDDEN</CODE> - Forbidden to access this URI
+
+ <LI><CODE>HTTP_NOT_FOUND</CODE> - URI was not found
+
+ <LI><CODE>HTTP_METHOD_NOT_ALLOWED</CODE> - Method is not allowed
+
+ <LI><CODE>HTTP_NOT_ACCEPTABLE</CODE> - Not Acceptable
+
+ <LI><CODE>HTTP_PROXY_AUTHENTICATION</CODE> - Proxy Authentication is Required
+
+ <LI><CODE>HTTP_REQUEST_TIMEOUT</CODE> - Request timed out
+
+ <LI><CODE>HTTP_CONFLICT</CODE> - Request is self-conflicting
+
+ <LI><CODE>HTTP_GONE</CODE> - Server has gone away
+
+ <LI><CODE>HTTP_LENGTH_REQUIRED</CODE> - A content length or encoding is required
+
+ <LI><CODE>HTTP_PRECONDITION</CODE> - Precondition failed
+
+ <LI><CODE>HTTP_REQUEST_TOO_LARGE</CODE> - Request entity too large
+
+ <LI><CODE>HTTP_URI_TOO_LONG</CODE> - URI too long
+
+ <LI><CODE>HTTP_UNSUPPORTED_MEDIATYPE</CODE> - The requested media type is unsupported
+
+ <LI><CODE>HTTP_SERVER_ERROR</CODE> - Internal server error
+
+ <LI><CODE>HTTP_NOT_IMPLEMENTED</CODE> - Feature not implemented
+
+ <LI><CODE>HTTP_BAD_GATEWAY</CODE> - Bad gateway
+
+ <LI><CODE>HTTP_SERVICE_UNAVAILABLE</CODE> - Service is unavailable
+
+ <LI><CODE>HTTP_GATEWAY_TIMEOUT</CODE> - Gateway connection timed out
+
+ <LI><CODE>HTTP_NOT_SUPPORTED</CODE> - HTTP version not supported
+
+</UL>
+
+<H3>Fields</H3>
+
+<P>The following fields are indices for each of the standard HTTP fields in
+HTTP 1/1:
+
+<UL>
+
+ <LI><CODE>HTTP_FIELD_ACCEPT_LANGUAGE</CODE> - Accept-Language
+
+ <LI><CODE>HTTP_FIELD_ACCEPT_RANGES</CODE> - Accept-Ranges
+
+ <LI><CODE>HTTP_FIELD_AUTHORIZATION</CODE> - Authorization
+
+ <LI><CODE>HTTP_FIELD_CONNECTION</CODE> - Connection
+
+ <LI><CODE>HTTP_FIELD_CONTENT_ENCODING</CODE> - Content-Encoding
+
+ <LI><CODE>HTTP_FIELD_CONTENT_LANGUAGE</CODE> - Content-Language
+
+ <LI><CODE>HTTP_FIELD_CONTENT_LENGTH</CODE> - Content-Length
+
+ <LI><CODE>HTTP_FIELD_CONTENT_LOCATION</CODE> - Content-Location
+
+ <LI><CODE>HTTP_FIELD_CONTENT_MD5</CODE> - Content-MD5
+
+ <LI><CODE>HTTP_FIELD_CONTENT_RANGE</CODE> - Content-Range
+
+ <LI><CODE>HTTP_FIELD_CONTENT_TYPE</CODE> - Content-Type
+
+ <LI><CODE>HTTP_FIELD_CONTENT_VERSION</CODE> - Content-Version
+
+ <LI><CODE>HTTP_FIELD_DATE</CODE> - Date
+
+ <LI><CODE>HTTP_FIELD_HOST</CODE> - Host
+
+ <LI><CODE>HTTP_FIELD_IF_MODIFIED_SINCE</CODE> - If-Modified-Since
+
+ <LI><CODE>HTTP_FIELD_IF_UNMODIFIED_SINCE</CODE> - If-Unmodified-Since
+
+ <LI><CODE>HTTP_FIELD_KEEP_ALIVE</CODE> - Keep-Alive
+
+ <LI><CODE>HTTP_FIELD_LAST_MODIFIED</CODE> - Last-Modified
+
+ <LI><CODE>HTTP_FIELD_LINK</CODE> - Link
+
+ <LI><CODE>HTTP_FIELD_LOCATION</CODE> - Location
+
+ <LI><CODE>HTTP_FIELD_RANGE</CODE> - Range
+
+ <LI><CODE>HTTP_FIELD_REFERER</CODE> - Referer
+
+ <LI><CODE>HTTP_FIELD_RETRY_AFTER</CODE> - Retry-After
+
+ <LI><CODE>HTTP_FIELD_TRANSFER_ENCODING</CODE> - Transfer-Encoding
+
+ <LI><CODE>HTTP_FIELD_UPGRADE</CODE> - Upgrade
+
+ <LI><CODE>HTTP_FIELD_USER_AGENT</CODE> - User-Agent
+
+ <LI><CODE>HTTP_FIELD_WWW_AUTHENTICATE</CODE> - WWW-Authenticate
+
+
+</UL>
+
+<H2>IPP Constants</H2>
+
+<H3>Limits</H3>
+
+<P>The following constants define array limits for IPP data:
+
+<UL>
+
+ <LI><CODE>IPP_MAX_NAME</CODE> - Maximum length of an attribute name
+
+ <LI><CODE>IPP_MAX_VALUES</CODE> - Maximum number of set-of values
+ that can be read in a request.
+
+</UL>
+
+<H3>Tags</H3>
+
+<UL>
+
+ <LI><CODE>IPP_TAG_ZERO</CODE> - Wildcard tag value for searches; also
+ used to separate groups of attributes
+
+ <LI><CODE>IPP_TAG_OPERATION</CODE> - Tag for values of type operation
+
+ <LI><CODE>IPP_TAG_JOB</CODE> - Tag for values of type job
+
+ <LI><CODE>IPP_TAG_END</CODE> - Tag for values of type end
+
+ <LI><CODE>IPP_TAG_PRINTER</CODE> - Tag for values of type printer
+
+ <LI><CODE>IPP_TAG_UNSUPPORTED_GROUP</CODE> - Tag for values of type unsupported_group
+
+ <LI><CODE>IPP_TAG_UNSUPPORTED_VALUE</CODE> - Tag for values of type unsupported_value
+
+ <LI><CODE>IPP_TAG_DEFAULT</CODE> - Tag for values of type default
+
+ <LI><CODE>IPP_TAG_UNKNOWN</CODE> - Tag for values of type unknown
+
+ <LI><CODE>IPP_TAG_NOVALUE</CODE> - Tag for values of type novalue
+
+ <LI><CODE>IPP_TAG_NOTSETTABLE</CODE> - Tag for values of type notsettable
+
+ <LI><CODE>IPP_TAG_DELETEATTR</CODE> - Tag for values of type deleteattr
+
+ <LI><CODE>IPP_TAG_ANYVALUE</CODE> - Tag for values of type anyvalue
+
+ <LI><CODE>IPP_TAG_INTEGER</CODE> - Tag for values of type integer
+
+ <LI><CODE>IPP_TAG_BOOLEAN</CODE> - Tag for values of type boolean
+
+ <LI><CODE>IPP_TAG_ENUM</CODE> - Tag for values of type enum
+
+ <LI><CODE>IPP_TAG_STRING</CODE> - Tag for values of type string
+
+ <LI><CODE>IPP_TAG_DATE</CODE> - Tag for values of type date
+
+ <LI><CODE>IPP_TAG_RESOLUTION</CODE> - Tag for values of type resolution
+
+ <LI><CODE>IPP_TAG_RANGE</CODE> - Tag for values of type range
+
+ <LI><CODE>IPP_TAG_COLLECTION</CODE> - Tag for values of type collection
+
+ <LI><CODE>IPP_TAG_TEXTLANG</CODE> - Tag for values of type textlang
+
+ <LI><CODE>IPP_TAG_NAMELANG</CODE> - Tag for values of type namelang
+
+ <LI><CODE>IPP_TAG_TEXT</CODE> - Tag for values of type text
+
+ <LI><CODE>IPP_TAG_NAME</CODE> - Tag for values of type name
+
+ <LI><CODE>IPP_TAG_KEYWORD</CODE> - Tag for values of type keyword
+
+ <LI><CODE>IPP_TAG_URI</CODE> - Tag for values of type uri
+
+ <LI><CODE>IPP_TAG_URISCHEME</CODE> - Tag for values of type urischeme
+
+ <LI><CODE>IPP_TAG_CHARSET</CODE> - Tag for values of type charset
+
+ <LI><CODE>IPP_TAG_LANGUAGE</CODE> - Tag for values of type language
+
+ <LI><CODE>IPP_TAG_MIMETYPE</CODE> - Tag for values of type mimetype
+
+</UL>
+
+<H3>Resolution Units</H3>
+
+<P>The <CODE>IPP_RES_PER_INCH</CODE> and <CODE>IPP_RES_PER_CM</CODE> constants
+specify dots per inch and dots per centimeter, respectively.
+
+<H3>Finishings</H3>
+
+<P>The finishing values specify special finishing operations to be
+performed on the job.
+
+<UL>
+
+ <LI><CODE>IPP_FINISH_NONE</CODE> - Do no finishing
+
+ <LI><CODE>IPP_FINISH_STAPLE</CODE> - Staple the job
+
+ <LI><CODE>IPP_FINISH_PUNCH</CODE> - Punch the job
+
+ <LI><CODE>IPP_FINISH_COVER</CODE> - Cover the job
+
+ <LI><CODE>IPP_FINISH_BIND</CODE> - Bind the job
+
+</UL>
+
+<H3>Orientations</H3>
+
+<P>The orientation values specify the orientation of the job.
+
+<UL>
+
+ <LI><CODE>IPP_PORTRAIT</CODE> - No rotation
+
+ <LI><CODE>IPP_LANDSCAPE</CODE> - 90 degrees counter-clockwise
+
+ <LI><CODE>IPP_REVERSE_LANDSCAPE</CODE> - 90 degrees clockwise
+
+ <LI><CODE>IPP_REVERSE_PORTRAIT</CODE> - 180 degrees
+
+</UL>
+
+<H3>Qualities</H3>
+
+<P>The quality values specify the desired quality of the print.
+<UL>
+
+ <LI><CODE>IPP_QUALITY_DRAFT</CODE> - Draft quality
+
+ <LI><CODE>IPP_QUALITY_NORMAL</CODE> - Normal quality
+
+ <LI><CODE>IPP_QUALITY_HIGH</CODE> - High quality
+
+</UL>
+
+<H3>Job States</H3>
+
+<P>The job state values are used to represent the current job state.
+
+<UL>
+
+ <LI><CODE>IPP_JOB_PENDING</CODE> - Job is pending
+
+ <LI><CODE>IPP_JOB_HELD</CODE> - Job is held
+
+ <LI><CODE>IPP_JOB_PROCESSING</CODE> - Job is processing
+
+ <LI><CODE>IPP_JOB_STOPPED</CODE> - Job is stopped
+
+ <LI><CODE>IPP_JOB_CANCELLED</CODE> - Job is cancelled
+
+ <LI><CODE>IPP_JOB_ABORTED</CODE> - Job is aborted
+
+ <LI><CODE>IPP_JOB_COMPLETED</CODE> - Job is completed
+
+</UL>
+
+<H3>Printer States</H3>
+
+<P>The printer state values are used to represent the current printer
+state.
+
+<UL>
+
+ <LI><CODE>IPP_PRINTER_IDLE</CODE> - Printer is idle
+
+ <LI><CODE>IPP_PRINTER_PROCESSING</CODE> - Printer is processing
+
+ <LI><CODE>IPP_PRINTER_STOPPED</CODE> - Printer is stopped
+
+</UL>
+
+<H3>Operations</H3>
+
+<P>The operation values represent the available IPP operations.
+
+<UL>
+
+ <LI><CODE>IPP_PRINT_JOB</CODE> - Print a file
+
+ <LI><CODE>IPP_PRINT_URI</CODE> - Print a URI
+
+ <LI><CODE>IPP_VALIDATE_JOB</CODE> - Validate job attributes
+
+ <LI><CODE>IPP_CREATE_JOB</CODE> - Create a new job
+
+ <LI><CODE>IPP_SEND_DOCUMENT</CODE> - Send a document to a job
+
+ <LI><CODE>IPP_SEND_URI</CODE> - Send a URI to a job
+
+ <LI><CODE>IPP_CANCEL_JOB</CODE> - Cancel a job
+
+ <LI><CODE>IPP_GET_JOB_ATTRIBUTES</CODE> - Get job attributes
+
+ <LI><CODE>IPP_GET_JOBS</CODE> - Get a list of all jobs
+
+ <LI><CODE>IPP_GET_PRINTER_ATTRIBUTES</CODE> - Get printer attributes
+
+ <LI><CODE>IPP_HOLD_JOB</CODE> - Hold a pending job
+
+ <LI><CODE>IPP_RELEASE_JOB</CODE> - Release a held job
+
+ <LI><CODE>IPP_RESTART_JOB</CODE> - Restart a completed job
+
+ <LI><CODE>IPP_PAUSE_PRINTER</CODE> - Pause a printer
+
+ <LI><CODE>IPP_RESUME_PRINTER</CODE> - Restart a paused printer
+
+ <LI><CODE>IPP_PURGE_JOBS</CODE> - Purge jobs from the queue
+
+ <LI><CODE>IPP_SET_PRINTER_ATTRIBUTES</CODE> - Set printer attributes
+
+ <LI><CODE>IPP_SET_JOB_ATTRIBUTES</CODE> - Set job attributes
+
+ <LI><CODE>IPP_GET_PRINTER_SUPPORTED_VALUES</CODE> - Get printer supported values
+
+ <LI><CODE>CUPS_GET_DEFAULT</CODE> - Get the default destination
+
+ <LI><CODE>CUPS_GET_PRINTERS</CODE> - Get a list of all printers
+
+ <LI><CODE>CUPS_ADD_PRINTER</CODE> - Add or modify a printer
+
+ <LI><CODE>CUPS_DELETE_PRINTER</CODE> - Delete a printer
+
+ <LI><CODE>CUPS_GET_CLASSES</CODE> - Get a list of all classes
+
+ <LI><CODE>CUPS_ADD_CLASS</CODE> - Add or modify a class
+
+ <LI><CODE>CUPS_DELETE_CLASS</CODE> - Delete a class
+
+ <LI><CODE>CUPS_ACCEPT_JOBS</CODE> - Accept jobs on a printer or class
+
+ <LI><CODE>CUPS_REJECT_JOBS</CODE> - Reject jobs on a printer or class
+
+ <LI><CODE>CUPS_SET_DEFAULT</CODE> - Set the default destination
+
+ <LI><CODE>CUPS_GET_DEVICES</CODE> - Get a list of all devices
+
+ <LI><CODE>CUPS_GET_PPDS</CODE> - Get a list of all PPDs
+
+ <LI><CODE>CUPS_MOVE_JOB</CODE> - Move a job to a new destination
+
+</UL>
+
+<H3>Status Codes</H3>
+
+<P>Status codes are returned by all IPP requests.
+
+<UL>
+
+ <LI><CODE>IPP_OK</CODE> - Request completed with no errors
+
+ <LI><CODE>IPP_OK_SUBST</CODE> - Request completed but some attribute
+ values were substituted
+
+ <LI><CODE>IPP_OK_CONFLICT</CODE> - Request completed but some attributes
+ conflicted
+
+ <LI><CODE>IPP_BAD_REQUEST</CODE> - The request was bad
+
+ <LI><CODE>IPP_FORBIDDEN</CODE> - You don't have access to the resource
+
+ <LI><CODE>IPP_NOT_AUTHENTICATED</CODE> - You are not authenticated for
+ the resource
+
+ <LI><CODE>IPP_NOT_AUTHORIZED</CODE> - You not authorized to access
+ the resource
+
+ <LI><CODE>IPP_NOT_POSSIBLE</CODE> - The requested operation cannot be
+ completed
+
+ <LI><CODE>IPP_TIMEOUT</CODE> - A timeout occurred
+
+ <LI><CODE>IPP_NOT_FOUND</CODE> - The resource was not found
+
+ <LI><CODE>IPP_GONE</CODE> - The resource has gone away
+
+ <LI><CODE>IPP_REQUEST_ENTITY</CODE> - The request was too large
+
+ <LI><CODE>IPP_REQUEST_VALUE</CODE> - The request contained a value
+ that was unknown to the server
+
+ <LI><CODE>IPP_DOCUMENT_FORMAT</CODE> - The document format is not
+ supported by the server
+
+ <LI><CODE>IPP_ATTRIBUTES</CODE> - Required attributes are missing
+
+ <LI><CODE>IPP_URI_SCHEME</CODE> - The URI scheme is not supported
+
+ <LI><CODE>IPP_CHARSET</CODE> - The charset is not supported
+
+ <LI><CODE>IPP_CONFLICT</CODE> - One or more attributes conflict
+
+ <LI><CODE>IPP_COMPRESSION_NOT_SUPPORTED</CODE> - The specified
+ compression is not supported
+
+ <LI><CODE>IPP_COMPRESSION_ERROR</CODE> - The compressed data
+ contained an error
+
+ <LI><CODE>IPP_DOCUMENT_FORMAT_ERROR</CODE> - The document data
+ contained an error in it
+
+ <LI><CODE>IPP_DOCUMENT_ACCESS_ERROR</CODE> - The remote document
+ could not be accessed
+
+ <LI><CODE>IPP_INTERNAL_ERROR</CODE> - The server encountered an
+ internal error
+
+ <LI><CODE>IPP_OPERATION_NOT_SUPPORTED</CODE> - The requested operation
+ is not supported
+
+ <LI><CODE>IPP_SERVICE_UNAVAILABLE</CODE> - The requested service
+ is unavailable
+
+ <LI><CODE>IPP_VERSION_NOT_SUPPORTED</CODE> - The IPP request
+ version is not supported
+
+ <LI><CODE>IPP_DEVICE_ERROR</CODE> - The output device encountered
+ an error
+
+ <LI><CODE>IPP_TEMPORARY_ERROR</CODE> - A temporary error occurred
+
+ <LI><CODE>IPP_NOT_ACCEPTING</CODE> - The destination is not accepting
+ jobs
+
+ <LI><CODE>IPP_PRINTER_BUSY</CODE> - The destination is busy
+
+ <LI><CODE>IPP_ERROR_JOB_CANCELLED</CODE> - The requested job has been
+ cancelled
+
+ <LI><CODE>IPP_MULTIPLE_JOBS_NOT_SUPPORTED</CODE> - The server
+ does not support multiple jobs
+
+</UL>
+
+<H2>PPD Constants</H2>
+
+<H3>PPD Format Version</H3>
+
+<P>The <CODE>PPD_VERSION</CODE> constant defines a floating point number
+representing the newest format version that is supported by CUPS, currently
+4.3.
+
+<H3>PPD User-Interface Types</H3>
+
+<P>Each printer option has a type associated with it:
+
+<UL>
+
+ <LI><CODE>PPD_UI_BOOLEAN</CODE> - The user can turn this option on or off
+
+ <LI><CODE>PPD_UI_PICKONE</CODE> - The user can choose one option value
+ to use.
+
+ <LI><CODE>PPD_UI_PICKMANY</CODE> - The user can choose zero or more
+ option values.
+
+</UL>
+
+<H3>PPD Sections</H3>
+
+<P>Some options must be output before others, or in different sections of
+the output document. The <CODE>ppd_section_t</CODE> enumeration defines
+which section the option must be output in:
+
+<UL>
+
+ <LI><CODE>PPD_ORDER_ANY</CODE> - The option can be output in any of
+ the document, page, or prolog sections of the document
+
+ <LI><CODE>PPD_ORDER_DOCUMENT</CODE> - The option must be output in
+ the DocumentSetup section of the document
+
+ <LI><CODE>PPD_ORDER_EXIT</CODE> - The option must be output before
+ the document
+
+ <LI><CODE>PPD_ORDER_JCL</CODE> - The option must be output in the
+ job control section of the document
+
+ <LI><CODE>PPD_ORDER_PAGE</CODE> - The option must be output in the
+ PageSetup section of the document
+
+ <LI><CODE>PPD_ORDER_PROLOG</CODE> - The option must be output in the
+ Prolog section of the document
+
+</UL>
+
+<H3>PPD Colorspaces</H3>
+
+<P>Each printer has a default colorspace:
+
+<UL>
+
+ <LI><CODE>PPD_CS_CMYK</CODE> - The printer uses CMYK colors by default
+
+ <LI><CODE>PPD_CS_CMY</CODE> - The printer uses CMY colors by default
+
+ <LI><CODE>PPD_CS_GRAY</CODE> - The printer uses grayscale by default
+
+ <LI><CODE>PPD_CS_RGB</CODE> - The printer uses RGB colors by default
+
+ <LI><CODE>PPD_CS_RGBK</CODE> - The printer uses RGBK colors by default
+
+ <LI><CODE>PPD_CS_N</CODE> - The printer uses a DeviceN colorspace
+ by default
+
+</UL>
+
+<H2>Raster Constants</H2>
+
+<H3>Raster Sync Words</H3>
+
+<P>The <CODE>CUPS_RASTER_SYNC</CODE> and <CODE>CUPS_RASTER_REVSYNC</CODE>
+constants define the standard sync words at the beginning of each CUPS
+raster file.
+
+<H3>Raster Stream Modes</H3>
+
+<P>The <CODE>CUPS_RASTER_READ</CODE> and <CODE>CUPS_RASTER_WRITE</CODE>
+constants are used with the
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A> function to
+specify a stream for reading or writing.
+
+<H3>Raster Boolean Constants</H3>
+
+<P>The <CODE>CUPS_FALSE</CODE> and <CODE>CUPS_TRUE</CODE> constants
+represent boolean values in the page header.
+
+<H3>Raster Jog Values</H3>
+
+<P>The <CODE>cups_jog_t</CODE> enumeration defines constants for the
+Jog page device dictionary variable:
+
+<UL>
+
+ <LI><CODE>CUPS_JOG_NONE</CODE> - Do no jogging
+
+ <LI><CODE>CUPS_JOG_FILE</CODE> - Jog pages after each file
+
+ <LI><CODE>CUPS_JOG_JOB</CODE> - Jog pages after each job
+
+ <LI><CODE>CUPS_JOG_SET</CODE> - Jog pages after each set of jobs
+
+</UL>
+
+<H3>Raster Orientation Values</H3>
+
+<P>The <CODE>cups_orient_t</CODE> enumeration defines constants for the
+Orientation page device dictionary variable:
+
+<UL>
+
+ <LI><CODE>CUPS_ORIENT_0</CODE> - Portrait orientation
+
+ <LI><CODE>CUPS_ORIENT_90</CODE> - Landscape orientation
+
+ <LI><CODE>CUPS_ORIENT_180</CODE> - Reverse-portrait orientation
+
+ <LI><CODE>CUPS_ORIENT_270</CODE> - Reverse-landscape orientation
+
+</UL>
+
+<H3>Raster CutMedia Values</H3>
+
+<P>The <CODE>cups_cut_t</CODE> enumeration defines constants for the
+CutMedia page device dictionary variable:
+
+<UL>
+
+ <LI><CODE>CUPS_CUT_NONE</CODE> - Do no jogging
+
+ <LI><CODE>CUPS_CUT_FILE</CODE> - Cut pages after each file
+
+ <LI><CODE>CUPS_CUT_JOB</CODE> - Cut pages after each job
+
+ <LI><CODE>CUPS_CUT_SET</CODE> - Cut pages after each set of jobs
+
+ <LI><CODE>CUPS_CUT_PAGE</CODE> - Cut each page
+
+</UL>
+
+<H3>Raster AdvanceMedia Values</H3>
+
+<P>The <CODE>cups_advance_t</CODE> enumeration defines constants for the
+AdvanceMedia page device dictionary variable:
+
+<UL>
+
+ <LI><CODE>CUPS_ADVANCE_NONE</CODE> - Do no jogging
+
+ <LI><CODE>CUPS_ADVANCE_FILE</CODE> - Advance media after each file
+
+ <LI><CODE>CUPS_ADVANCE_JOB</CODE> - Advance media after each job
+
+ <LI><CODE>CUPS_ADVANCE_SET</CODE> - Advance media after each set of jobs
+
+ <LI><CODE>CUPS_ADVANCE_PAGE</CODE> - Advance media for each page
+
+</UL>
+
+<H3>Raster LeadingEdge Values</H3>
+
+<P>The <CODE>cups_edge_t</CODE> enumeration defines constants for the
+LeadingEdge page device dictionary variable:
+
+<UL>
+
+ <LI><CODE>CUPS_EDGE_TOP</CODE> - The top of the media is the leading
+ edge
+
+ <LI><CODE>CUPS_EDGE_RIGHT</CODE> - The right of the media is the leading
+ edge
+
+ <LI><CODE>CUPS_EDGE_BOTTOM</CODE> - The bottom of the media is the
+ leading edge
+
+ <LI><CODE>CUPS_EDGE_LEFT</CODE> - The left of the media is the leading
+ edge
+
+</UL>
+
+<H3>Raster Color Order Values</H3>
+
+<P>The <CODE>cups_order_t</CODE> enumeration defines the possible color
+value orderings:
+
+<UL>
+
+ <LI><CODE>CUPS_ORDER_CHUNKED</CODE> - CMYK&nbsp;CMYK&nbsp;CMYK
+
+ <LI><CODE>CUPS_ORDER_BANDED</CODE> - CCC&nbsp;MMM&nbsp;YYY&nbsp;KKK
+
+ <LI><CODE>CUPS_ORDER_PLANAR</CODE> - CCC&nbsp;...&nbsp;MMM&nbsp;...&nbsp;YYY&nbsp;...&nbsp;KKK&nbsp;...
+
+</UL>
+
+<H3>Raster Colorspace Values</H3>
+
+<P>The <CODE>cups_cspace_t</CODE> enumeration defines the possible colorspaces:
+
+<UL>
+
+ <LI><CODE>CUPS_CSPACE_W</CODE> - White (luminance)
+
+ <LI><CODE>CUPS_CSPACE_RGB</CODE> - Red, green, blue
+
+ <LI><CODE>CUPS_CSPACE_RGBA</CODE> - Red, green, blue, alpha
+
+ <LI><CODE>CUPS_CSPACE_K</CODE> - Black
+
+ <LI><CODE>CUPS_CSPACE_CMY</CODE> - Cyan, magenta, yellow
+
+ <LI><CODE>CUPS_CSPACE_YMC</CODE> - Yellow, magenta, cyan
+
+ <LI><CODE>CUPS_CSPACE_CMYK</CODE> - Cyan, magenta, yellow, black
+
+ <LI><CODE>CUPS_CSPACE_YMCK</CODE> - Yellow, magenta, cyan, black
+
+ <LI><CODE>CUPS_CSPACE_KCMY</CODE> - Black, cyan, magenta, yellow
+
+ <LI><CODE>CUPS_CSPACE_KCMYcm</CODE> - Black, cyan, magenta, yellow,
+ light cyan, light magenta
+
+ <LI><CODE>CUPS_CSPACE_GMCK</CODE> - Metallic yellow (gold), metallic magenta,
+ metallic cyan, black
+
+ <LI><CODE>CUPS_CSPACE_GMCS</CODE> - Metallic yellow (gold), metallic magenta,
+ metallic cyan, metallic grey (silver)
+
+ <LI><CODE>CUPS_CSPACE_WHITE</CODE> - White pigment (black as white pigment)
+
+ <LI><CODE>CUPS_CSPACE_GOLD</CODE> - Gold foil (black as gold foil)
+
+ <LI><CODE>CUPS_CSPACE_SILVER</CODE> - Silver foil (black as silver foil)
+
+</UL>
+
+<H1 ALIGN="RIGHT"><A NAME="STRUCTURES">C - Structures</A></H1>
+
+<P>This appendix describes all of the structures that are
+defined by the CUPS API.
+
+<H2>CUPS Structures</H2>
+
+<H3><A NAME="cups_dest_t">CUPS Destinations</A></H3>
+
+<P>The CUPS destination structure (<CODE>cups_dest_t</CODE>)
+contains information on a specific destination or instance:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>char *</TD>
+ <TD>The name of the printer or class.</TD>
+</TR>
+<TR>
+ <TD>instance</TD>
+ <TD>char *</TD>
+ <TD>The instance of the printer or class; NULL for the primary
+ instance.</TD>
+</TR>
+<TR>
+ <TD>is_default</TD>
+ <TD>int</TD>
+ <TD>1 if the destination is set as the default, 0 otherwise.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>int</TD>
+ <TD>The number of options associated with this destination.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD><A HREF="#cups_option_t">cups_option_t *</A></TD>
+ <TD>The options associated with this destination.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="cups_job_t">CUPS Jobs</A></H3>
+
+<P>The CUPS job structure (<CODE>cups_job_t</CODE>) contains
+information on a specific job:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>id</TD>
+ <TD>int</TD>
+ <TD>The job ID for this job.</TD>
+</TR>
+<TR>
+ <TD>dest</TD>
+ <TD>char *</TD>
+ <TD>The destination for this job (printer or class name).</TD>
+</TR>
+<TR>
+ <TD>title</TD>
+ <TD>char *</TD>
+ <TD>The job-name for this job (title).</TD>
+</TR>
+<TR>
+ <TD>user</TD>
+ <TD>char *</TD>
+ <TD>The job-originating-user-name for this job (username).</TD>
+</TR>
+<TR>
+ <TD>format</TD>
+ <TD>char *</TD>
+ <TD>The document-format for this job (MIME type string).</TD>
+</TR>
+<TR>
+ <TD>state</TD>
+ <TD>ipp_jstate</TD>
+ <TD>The current state of the job.</TD>
+</TR>
+<TR>
+ <TD>size</TD>
+ <TD>int</TD>
+ <TD>The size of this job in kilobytes.</TD>
+</TR>
+<TR>
+ <TD>priority</TD>
+ <TD>int</TD>
+ <TD>The priority of this job from 1 to 100 (50 is normal).</TD>
+</TR>
+<TR>
+ <TD>completed_time</TD>
+ <TD>time_t</TD>
+ <TD>The time the job was completed, or 0 if not yet completed.</TD>
+</TR>
+<TR>
+ <TD>creation_time</TD>
+ <TD>time_t</TD>
+ <TD>The time the job was queued.</TD>
+</TR>
+<TR>
+ <TD>processing_time</TD>
+ <TD>time_t</TD>
+ <TD>The time the job started printing.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="cups_lang_t">CUPS Messages</A></H3>
+
+<P>The CUPS messages structure (<CODE>cups_lang_t</CODE>)
+contains the character set, locale name, and messages array:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>next</TD>
+ <TD>cups_lang_t *</TD>
+ <TD>Pointer to the next messages structure in memory.</TD>
+</TR>
+<TR>
+ <TD>used</TD>
+ <TD>int</TD>
+ <TD>The number of active users of this messages structure.</TD>
+</TR>
+<TR>
+ <TD>encoding</TD>
+ <TD>cups_encoding_t</TD>
+ <TD>The character encoding of the message strings.</TD>
+</TR>
+<TR>
+ <TD>language</TD>
+ <TD>char [16]</TD>
+ <TD>The language/locale name.</TD>
+</TR>
+<TR>
+ <TD>messages</TD>
+ <TD>char *[]</TD>
+ <TD>The array of message strings.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="cups_option_t">CUPS Options</A></H3>
+
+<P>The CUPS option structure (<CODE>cups_option_t</CODE>)
+contains the option name and string value:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>char *</TD>
+ <TD>The name of the option.</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>char *</TD>
+ <TD>The string value of the option.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>Networking Structures</H2>
+
+<H3><A NAME="http_t">HTTP State</A></H3>
+
+<P>The HTTP state structure (<CODE>http_t</CODE>) contains the
+current state of a HTTP request or response:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>int</TD>
+ <TD>The socket for the HTTP connection.</TD>
+</TR>
+<TR>
+ <TD>blocking</TD>
+ <TD>int</TD>
+ <TD>1 if the HTTP functions should block, 0 if not.</TD>
+</TR>
+<TR>
+ <TD>error</TD>
+ <TD>int</TD>
+ <TD>The last OS error that occurred on the socket.</TD>
+</TR>
+<TR>
+ <TD>activity</TD>
+ <TD>time_t</TD>
+ <TD>The last time the HTTP connection was used.</TD>
+</TR>
+<TR>
+ <TD>state</TD>
+ <TD>http_state_t</TD>
+ <TD>The current HTTP request/response state.</TD>
+</TR>
+<TR>
+ <TD>status</TD>
+ <TD>int</TD>
+ <TD>The last HTTP status seen.</TD>
+</TR>
+<TR>
+ <TD>version</TD>
+ <TD>http_version_t</TD>
+ <TD>The HTTP protocol version in use.</TD>
+</TR>
+<TR>
+ <TD>keep_alive</TD>
+ <TD>http_keep_alive_t</TD>
+ <TD>Whether or not to use Keep-Alive</TD>
+</TR>
+<TR>
+ <TD>hostaddr</TD>
+ <TD>struct sockaddr_in</TD>
+ <TD>The IPv4 address of the HTTP server.</TD>
+</TR>
+<TR>
+ <TD>hostname</TD>
+ <TD>char []</TD>
+ <TD>The hostname of the HTTP server.</TD>
+</TR>
+<TR>
+ <TD>fields</TD>
+ <TD>char [][]</TD>
+ <TD>The string values of all HTTP request/response
+ fields.</TD>
+</TR>
+<TR>
+ <TD>data</TD>
+ <TD>char *</TD>
+ <TD>Current byte in data buffer.</TD>
+</TR>
+<TR>
+ <TD>data_encoding</TD>
+ <TD>http_encoding_t</TD>
+ <TD>The transfer encoding for the request/response.</TD>
+</TR>
+<TR>
+ <TD>data_remaining</TD>
+ <TD>int</TD>
+ <TD>The number of bytes remaining in the current request,
+ response, or chunk.</TD>
+</TR>
+<TR>
+ <TD>used</TD>
+ <TD>int</TD>
+ <TD>The number of bytes that are used in the buffer.</TD>
+</TR>
+<TR>
+ <TD>buffer</TD>
+ <TD>char []</TD>
+ <TD>The read/write buffer.</TD>
+</TR>
+<TR>
+ <TD>auth_type</TD>
+ <TD>int</TD>
+ <TD>The type of authentication in use.</TD>
+</TR>
+<TR>
+ <TD>md5_state</TD>
+ <TD>md5_state_t</TD>
+ <TD>The current MD5 digest state.</TD>
+</TR>
+<TR>
+ <TD>nonce</TD>
+ <TD>char []</TD>
+ <TD>The nonce value for Digest authentication.</TD>
+</TR>
+<TR>
+ <TD>nonce_count</TD>
+ <TD>int</TD>
+ <TD>The nonce count value.</TD>
+</TR>
+<TR>
+ <TD>tls</TD>
+ <TD>void *</TD>
+ <TD>A pointer to private encryption data.</TD>
+</TR>
+<TR>
+ <TD>encryption</TD>
+ <TD>http_encryption_t</TD>
+ <TD>The current encryption mode.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="ipp_t">IPP State</A></H3>
+
+<P>The IPP state structure (<CODE>ipp_t</CODE>) contains the
+current state of a IPP request or response:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD></TD>
+</TR>
+</TABLE></CENTER>
+
+<H3><A NAME="ipp_attribute_t">IPP Attribute</A></H3>
+
+<P>TODO</P>
+
+<H2>PPD Structures</H2>
+
+<H3><A NAME="ppd_file_t">PPD File</A></H3>
+
+<P>TODO</P>
+
+<H3><A NAME="ppd_choice_t">PPD Choice</A></H3>
+
+<P>TODO</P>
+
+<H2>Raster Structures</H2>
+
+<H3><A NAME="cups_raster_t">Raster Stream</A></H3>
+
+<P>TODO</P>
+
+<H3><A NAME="cups_raster_header_t">Raster Page Header</A></H3>
+
+<P>The raster page header (<CODE>cups_raster_header_t</CODE>)
+consists of the PostScript page device dictionary for the page:
+
+<CENTER><TABLE WIDTH="90%" BORDER="1">
+<TR>
+ <TH>Member</TH>
+ <TH>Type</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>MediaClass</TD>
+ <TD>char[64]</TD>
+ <TD>The media class name</TD>
+</TR>
+<TR>
+ <TD>MediaColor</TD>
+ <TD>char[64]</TD>
+ <TD>The media color name</TD>
+</TR>
+<TR>
+ <TD>MediaType</TD>
+ <TD>char[64]</TD>
+ <TD>The media type name</TD>
+</TR>
+<TR>
+ <TD>OutputType</TD>
+ <TD>char[64]</TD>
+ <TD>The output type name</TD>
+</TR>
+<TR>
+ <TD>AdvanceDistance</TD>
+ <TD>unsigned</TD>
+ <TD>The distance to advance the media in points</TD>
+</TR>
+<TR>
+ <TD>AdvanceMedia</TD>
+ <TD>cups_adv_t</TD>
+ <TD>When to advance the media</TD>
+</TR>
+<TR>
+ <TD>Collate</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to produce collated copies</TD>
+</TR>
+<TR>
+ <TD>CutMedia</TD>
+ <TD>cups_cut_t</TD>
+ <TD>When to cut the media</TD>
+</TR>
+<TR>
+ <TD>Duplex</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to print on both sides of the paper</TD>
+</TR>
+<TR>
+ <TD>HWResolution</TD>
+ <TD>unsigned[2]</TD>
+ <TD>The resolution of the page image in pixels per inch; the
+ HWResolution[0] represents the horizontal resolution and
+ HWResolution[1] represents the vertical resolution</TD>
+</TR>
+<TR>
+ <TD>ImagingBoundingBox</TD>
+ <TD>unsigned[4]</TD>
+ <TD>The bounding box for the page in points; the elements
+ represent the left, bottom, right, and top coordinates of the
+ imaged area (if 0 then the whole page is imaged)</TD>
+</TR>
+<TR>
+ <TD>InsertSheet</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to insert a sheet before this page</TD>
+</TR>
+<TR>
+ <TD>Jog</TD>
+ <TD>cups_jog_t</TD>
+ <TD>When to jog copies of the page</TD>
+</TR>
+<TR>
+ <TD>LeadingEdge</TD>
+ <TD>cups_edge_t</TD>
+ <TD>The leading edge of the page</TD>
+</TR>
+<TR>
+ <TD>Margins</TD>
+ <TD>unsigned[2]</TD>
+ <TD>The lower-lefthand margin of the page in points</TD>
+</TR>
+<TR>
+ <TD>ManualFeed</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to manually feed the page</TD>
+</TR>
+<TR>
+ <TD>MediaPosition</TD>
+ <TD>unsigned</TD>
+ <TD>The input slot number to use</TD>
+</TR>
+<TR>
+ <TD>MediaWeight</TD>
+ <TD>unsigned</TD>
+ <TD>The weight of the output media in grams/m<SUP>2</SUP></TD>
+</TR>
+<TR>
+ <TD>MirrorPrint</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to mirror the print</TD>
+</TR>
+<TR>
+ <TD>NegativePrint</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to invert the print</TD>
+</TR>
+<TR>
+ <TD>NumCopies</TD>
+ <TD>unsigned</TD>
+ <TD>The number of copies to produce</TD>
+</TR>
+<TR>
+ <TD>Orientation</TD>
+ <TD>cups_orient_t</TD>
+ <TD>The orientation of the page image</TD>
+</TR>
+<TR>
+ <TD>OutputFaceUp</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to output the page face up</TD>
+</TR>
+<TR>
+ <TD>PageSize</TD>
+ <TD>unsigned[2]</TD>
+ <TD>The width and height of the page in points</TD>
+</TR>
+<TR>
+ <TD>Separations</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to output separations</TD>
+</TR>
+<TR>
+ <TD>TraySwitch</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to automatically switch trays for the requested
+ media size/type</TD>
+</TR>
+<TR>
+ <TD>Tumble</TD>
+ <TD>cups_bool_t</TD>
+ <TD>Whether or not to rotate the back side of the page</TD>
+</TR>
+<TR>
+ <TD>cupsWidth</TD>
+ <TD>unsigned</TD>
+ <TD>The width of the page image in pixels</TD>
+</TR>
+<TR>
+ <TD>cupsHeight</TD>
+ <TD>unsigned</TD>
+ <TD>The height of the page image in pixels</TD>
+</TR>
+<TR>
+ <TD>cupsMediaType</TD>
+ <TD>unsigned</TD>
+ <TD>The device-specific media type code</TD>
+</TR>
+<TR>
+ <TD>cupsBitsPerColor</TD>
+ <TD>unsigned</TD>
+ <TD>The number of bits per color</TD>
+</TR>
+<TR>
+ <TD>cupsBitsPerPixel</TD>
+ <TD>unsigned</TD>
+ <TD>The number of bits per pixel</TD>
+</TR>
+<TR>
+ <TD>cupsBytesPerLine</TD>
+ <TD>unsigned</TD>
+ <TD>The number of bytes per line of image data</TD>
+</TR>
+<TR>
+ <TD>cupsColorOrder</TD>
+ <TD>cups_order_t</TD>
+ <TD>The order of color values</TD>
+</TR>
+<TR>
+ <TD>cupsColorSpace</TD>
+ <TD>cups_cspace_t</TD>
+ <TD>The type of color values</TD>
+</TR>
+<TR>
+ <TD>cupsCompression</TD>
+ <TD>unsigned</TD>
+ <TD>The device-specific compression code</TD>
+</TR>
+<TR>
+ <TD>cupsRowCount</TD>
+ <TD>unsigned</TD>
+ <TD>The device-specific row count</TD>
+</TR>
+<TR>
+ <TD>cupsRowFeed</TD>
+ <TD>unsigned</TD>
+ <TD>The device-specific row feed</TD>
+</TR>
+<TR>
+ <TD>cupsRowStep</TD>
+ <TD>unsigned</TD>
+ <TD>The device-specific row step</TD>
+</TR>
+</TABLE></CENTER>
+
+<H1 ALIGN="RIGHT"><A NAME="FUNCTIONS">D - Functions</A></H1>
+
+<P>This appendix provides a reference for all of the CUPS API functions.
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsAddDest">cupsAddDest()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsAddDest(const char *name,
+ const char *instance,
+ int num_dests,
+ cups_dest_t **dests);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the destination.</TD>
+</TR>
+<TR>
+ <TD>instance</TD>
+ <TD>The instance of the destination, or NULL for the primary instance.</TD>
+</TR>
+<TR>
+ <TD>num_dests</TD>
+ <TD>The number of destinations in the array.</TD>
+</TR>
+<TR>
+ <TD>dest</TD>
+ <TD>A pointer to the destination array pointer.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The new number of destinations in the array.
+
+<H3>Description</H3>
+
+<P><CODE>cupsAddDest()</CODE> adds the named destination to the destination
+array if it does not already exist.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+
+
+num_dests = cupsAddDests("foo", "bar", num_dests, &amp;dests);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsFreeDests"><CODE>cupsFreeDests()</CODE></A>,
+<A HREF="#cupsGetDest"><CODE>cupsGetDest()</CODE></A>,
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsAddOption">cupsAddOption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsAddOption(const char *name,
+ const char *value,
+ int num_options,
+ cups_option_t **options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the option.</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The value of the option.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>Number of options currently in the array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>Pointer to the options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The new number of options.
+
+<H3>Description</H3>
+
+<P><CODE>cupsAddOption()</CODE> adds an option to the specified array.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups.h&gt;
+
+...
+
+/* Declare the options array */
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+/* Initialize the options array */
+num_options = 0;
+options = (cups_option_t *)0;
+
+/* Add options using cupsAddOption() */
+num_options = cupsAddOption("media", "letter", num_options, &amp;options);
+num_options = cupsAddOption("resolution", "300dpi", num_options, &amp;options);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsEncodeOptions"><CODE>cupsEncodeOptions()</CODE></A>,
+<A HREF="#cupsFreeOptions"><CODE>cupsFreeOptions()</CODE></A>,
+<A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A>,
+<A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsCancelJob">cupsCancelJob()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsCancelJob(const char *dest,
+ int job);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>dest</TD>
+ <TD>Printer or class name</TD>
+</TR>
+<TR>
+ <TD>job</TD>
+ <TD>Job ID</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>1 on success, 0 on failure. On failure the error can be found by calling
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>.
+
+<H3>Description</H3>
+
+<P><CODE>cupsCancelJob()</CODE> cancels the specifies job.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups.h&gt;
+
+cupsCancelJob("LaserJet", 1);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>,
+<A HREF="#cupsPrintFile"><CODE>cupsPrintFile()</CODE></A>,
+<A HREF="#cupsPrintFiles"><CODE>cupsPrintFiles()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsDoAuthentication">cupsDoAuthentication()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsDoAuthentication(http_t *http,
+ const char *method,
+ const char *resource);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>HTTP connection to server.</TD>
+</TR>
+<TR>
+ <TD>method</TD>
+ <TD>HTTP method name ("GET", "POST", "PUT", etc.)</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>HTTP resource name.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 if the authentication string was successfully generated, -1 otherwise.
+
+<H3>Description</H3>
+
+<P><CODE>cupsDoAuthentication()</CODE> generates an
+authentication string for the given method and request. It
+supports Basic, Digest, and CUPS local certificate
+authentication methods and uses the current user and password
+callback to collect authentication information as needed.
+
+<P>Applications using this function should set the
+<CODE>HTTP_FIELD_AUTHORIZATION</CODE> field to the
+<CODE>authstring</CODE> value in the <CODE>http_t</CODE>
+structure prior to issuing a new request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups.h&gt;
+
+http_t *http;
+char resource[HTTP_MAX_URI];
+http_status_t status;
+
+...
+
+do
+{
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+
+ if (httpGet(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+
+ continue;
+ }
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ httpFlush(http);
+
+ if (cupsDoAuthentication(http, "GET", resource))
+ break;
+
+ httpReconnect(http);
+ continue;
+ }
+}
+while (status == HTTP_UNAUTHORIZED);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>,
+<A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>,
+<A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsDoFileRequest">cupsDoFileRequest()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_t *
+cupsDoFileRequest(http_t *http,
+ ipp_t *request,
+ const char *resource,
+ const char *filename);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>HTTP connection to server.</TD>
+</TR>
+<TR>
+ <TD>request</TD>
+ <TD>IPP request data.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>HTTP resource name for POST.</TD>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>File to send with POST request (<CODE>NULL</CODE> pointer if none.)</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On failure
+the error can be found by calling
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>.
+
+<H3>Description</H3>
+
+<P><CODE>cupsDoFileRequest()</CODE> does a HTTP POST request and provides the
+IPP request and optionally the contents of a file to the IPP server. It also
+handles resubmitting the request and performing password authentication as
+needed.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+<A HREF="#ipp_t">ipp_t</A> *request;
+ipp_t *response;
+
+...
+
+/* Get the default language */
+language = <A HREF="#cupsLangDefault">cupsLangDefault()</A>;
+
+/* Create a new IPP request */
+request = <A HREF="#ippNew">ippNew()</A>;
+
+request-&gt;request.op.operation_id = IPP_PRINT_FILE;
+request-&gt;request.op.request_id = 1;
+
+/* Add required attributes */
+<A HREF="#ippAddString">ippAddString</A>(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, <A HREF="#cupsLangEncoding">cupsLangEncoding</A>(language));
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language-&gt;language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://hostname/resource");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, <A HREF="#cupsUser">cupsUser()</A>);
+
+/* Do the request... */
+response = cupsDoFileRequest(http, request, "/resource", "filename.txt");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>,
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsDoRequest">cupsDoRequest()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_t *
+cupsDoRequest(http_t *http,
+ ipp_t *request,
+ const char *resource);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>HTTP connection to server.</TD>
+</TR>
+<TR>
+ <TD>request</TD>
+ <TD>IPP request data.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>HTTP resource name for POST.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>IPP response data or <CODE>NULL</CODE> if the request fails. On failure
+the error can be found by calling
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>.
+
+<H3>Description</H3>
+
+<P><CODE>cupsDoRequest()</CODE> does a HTTP POST request and provides
+the IPP request to the IPP server. It also handles resubmitting the
+request and performing password authentication as needed.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+<A HREF="#ipp_t">ipp_t</A> *request;
+ipp_t *response;
+
+...
+
+/* Get the default language */
+language = <A HREF="#cupsLangDefault">cupsLangDefault()</A>;
+
+/* Create a new IPP request */
+request = <A HREF="#ippNew">ippNew()</A>;
+
+request-&gt;request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+request-&gt;request.op.request_id = 1;
+
+/* Add required attributes */
+<A HREF="#ippAddString">ippAddString</A>(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, <A HREF="#cupsLangEncoding">cupsLangEncoding</A>(language));
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language-&gt;language : "C");
+
+ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://hostname/resource");
+
+/* Do the request... */
+response = cupsDoRequest(http, request, "/resource");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>,
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsEncodeOptions">cupsEncodeOptions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsEncodeOptions(ipp_t *ipp,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>The options.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsEncodeOptions()</CODE> encodes all of the options
+in the specified array as IPP attributes and adds them to the
+IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+<A HREF="#ipp_t">ipp_t</A> *ipp;
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+
+cupsEncodeOptions(ipp, num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>,
+<A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsEncryption">cupsEncryption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_encryption_t
+cupsEncryption(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>The current encryption setting.
+
+<H3>Description</H3>
+
+<P><CODE>cupsEncryption()</CODE> returns the current encryption setting
+for IPP requests such as printing.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+printf("The current encryption setting is %d.\n", cupsEncryption());
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#httpConnectEncrypt"><CODE>httpConnectEncrypt()</CODE></A>,
+<A HREF="#ippPort"><CODE>ippPort()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsFreeDests">cupsFreeDests()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsFreeDests(int num_dests,
+ cups_dest_t *dests);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>num_dests</TD>
+ <TD>The number of destinations in the array.</TD>
+</TR>
+<TR>
+ <TD>dests</TD>
+ <TD>The destination array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsFreeDests()</CODE> frees a destination array that was
+created using <CODE>cupsGetDests()</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf("The default destination is %s\n", dest->name);
+else
+ puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetDest"><CODE>cupsGetDest()</CODE></A>,
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsFreeJobs">cupsFreeJobs()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsFreeJobs(int num_jobs,
+ cups_job_t *jobs);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>num_jobs</TD>
+ <TD>The number of jobs.</TD>
+</TR>
+<TR>
+ <TD>jobs</TD>
+ <TD>The job array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsFreeJobs()</CODE> frees an array of print jobs created by
+the <CODE>cupsGetJobs()</CODE> function.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_jobs;
+<A HREF="#cups_job_t">cups_job_t</A> *jobs;
+
+
+num_jobs = cupsGetJobs(&amp;jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i &lt; num_jobs; i ++)
+ printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+ jobs[i].user, jobs[i].title,
+ jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetJobs"><CODE>cupsGetJobs()</CODE></A>,
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsFreeOptions">cupsFreeOptions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsFreeOptions(int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>Number of options in array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>Pointer to options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsFreeOptions()</CODE> frees all memory associated with the
+option array specified.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+...
+
+cupsFreeOptions(num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>,
+<A HREF="#cupsEncodeOptions"><CODE>cupsEncodeOptions()</CODE></A>,
+<A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A>,
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetClasses">cupsGetClasses()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsGetClasses(char ***classes);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>classes</TD>
+ <TD>Pointer to character pointer array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of printer classes available.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetClasses()</CODE> gets a list of the available printer classes.
+The returned array should be freed using the <CODE>free()</CODE> when it is
+no longer needed.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_classes;
+char **classes;
+
+...
+
+num_classes = cupsGetClasses(&amp;classes);
+
+...
+
+if (num_classes > 0)
+{
+ for (i = 0; i &lt; num_classes; i ++)
+ free(classes[i]);
+
+ free(classes);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetDefault"><CODE>cupsGetDefault()</CODE></A>,
+<A HREF="#cupsGetPrinters"><CODE>cupsGetPrinters()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetDefault">cupsGetDefault()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsGetDefault(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>A pointer to the default destination.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetDefault()</CODE> gets the default destination printer or class.
+The default destination is stored in a static string and will be overwritten
+(usually with the same value) after each call.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+printf("The default destination is %s\n", cupsGetDefault());
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetClasses"><CODE>cupsGetClasses()</CODE></A>,
+<A HREF="#cupsGetPrinters"><CODE>cupsGetPrinters()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetDest">cupsGetDest()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+cups_dest_t *
+cupsGetDest(const char *name,
+ const char *instance,
+ int num_dests,
+ cups_dest_t *dests);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the destination, or NULL for the default destination.</TD>
+</TR>
+<TR>
+ <TD>instance</TD>
+ <TD>The instance of the destination, or NULL for the primary instance.</TD>
+</TR>
+<TR>
+ <TD>num_dests</TD>
+ <TD>The number of destinations.</TD>
+</TR>
+<TR>
+ <TD>dests</TD>
+ <TD>The destination array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the specified destination, or NULL if none exists.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetDest()</CODE> finds the specified destination in the array
+of destinations created by the <CODE>cupsGetDests()</CODE> function.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf("The default destination is %s\n", dest->name);
+else
+ puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>,
+<A HREF="#cupsGetJobs"><CODE>cupsGetJobs()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetDests">cupsGetDests()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsGetDests(cups_dest_t **dests);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>dests</TD>
+ <TD>A pointer to a destination array pointer.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of available destinations.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetDests()</CODE> creates an array of available
+destinations that the user can print to. The array should be
+freed using the <CODE>cupsFreeDests()</CODE> function.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+cups_dest_t *dest;
+
+num_dests = cupsGetDests(&amp;dests);
+dest = cupsGetDest(NULL, NULL, num_dests, dests);
+
+if (dest)
+ printf("The default destination is %s\n", dest->name);
+else
+ puts("No default destination.");
+
+cupsFreeDests(num_dests, dests);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsFreeDests"><CODE>cupsFreeDests()</CODE></A>,
+<A HREF="#cupsGetDest"><CODE>cupsGetDest()</CODE></A>,
+<A HREF="#cupsGetJobs"><CODE>cupsGetJobs()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetFd">cupsGetFd()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_status_t
+cupsGetFd(http_t *http,
+ const char *resource,
+ int fd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection to the server.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource name on the server.</TD>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>The file descriptor to write to.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The HTTP status code associated with the request.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetFd()</CODE> gets a file from the given HTTP
+server and writes it to the specified file descriptor,
+performing any authentication or encryption as required.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+int fd;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+fd = cupsTempFd(filename, sizeof(filename));
+status = cupsGetFd(http, "/admin/cupsd.conf", fd);
+
+...
+
+close(fd);
+unlink(filename);
+
+httpClose(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetFile"><CODE>cupsGetFile()</CODE></A>,
+<A HREF="#cupsPutFd"><CODE>cupsPutFd()</CODE></A>,
+<A HREF="#cupsPutFile"><CODE>cupsPutFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetFile">cupsGetFile()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_status_t
+cupsGetFile(http_t *http,
+ const char *resource,
+ const char *filename);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection to the server.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource name on the server.</TD>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The filename to write to.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The HTTP status code associated with the request.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetFile()</CODE> gets a file from the given HTTP
+server and writes it to the specified filename, performing any
+authentication or encryption as required.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+cupsTempFile(filename, sizeof(filename));
+
+status = cupsGetFile(http, "/admin/cupsd.conf", filename);
+
+...
+
+unlink(filename);
+
+httpClose(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>,
+<A HREF="#cupsPutFd"><CODE>cupsPutFd()</CODE></A>,
+<A HREF="#cupsPutFile"><CODE>cupsPutFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetJobs">cupsGetJobs()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsGetJobs(cups_job_t **jobs,
+ const char *dest,
+ int myjobs,
+ int completed);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>jobs</TD>
+ <TD>A pointer to the job array pointer.</TD>
+</TR>
+<TR>
+ <TD>dest</TD>
+ <TD>The destination name, or NULL if jobs for all destinations are requested.</TD>
+</TR>
+<TR>
+ <TD>myjobs</TD>
+ <TD>1 if only those jobs submitted by the current
+ <CODE>cupsUser()</CODE> should be returned, 0 for jobs
+ submitted by all users.</TD>
+</TR>
+<TR>
+ <TD>completed</TD>
+ <TD>1 if only completed jobs should be returned, 0 if only
+ pending/processing jobs should be returned.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of jobs.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetJobs()</CODE> creates an array of print jobs based on the
+arguments supplied in the function call. The returned array should be freed
+using the <CODE>cupsFreeJobs()</CODE> function.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_jobs;
+<A HREF="#cups_job_t">cups_job_t</A> *jobs;
+
+
+num_jobs = cupsGetJobs(&amp;jobs, NULL, 0, 0);
+
+printf("%d active job(s):\n", num_jobs);
+for (i = 0; i &lt; num_jobs; i ++)
+ printf("%-16.16s %-6d %-12.12s %s (%s)\n", jobs[i].dest, jobs[i].id,
+ jobs[i].user, jobs[i].title,
+ jobs[i].state != IPP_JOB_PENDING ? "printing" : "pending");
+
+cupsFreeJobs(num_jobs, jobs);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsFreeJobs"><CODE>cupsFreeJobs()</CODE></A>,
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetOption">cupsGetOption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsGetOption(const char *name,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the option.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options in the array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>The options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the option values or <CODE>NULL</CODE> if the option is
+not defined.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetOption()</CODE> returns the first occurrence of the
+named option. If the option is not included in the options array then a
+<CODE>NULL</CODE> pointer is returned.
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+cups_option_t *options;
+const char *media;
+
+...
+
+media = cupsGetOption("media", num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>,
+<A HREF="#cupsEncodeOptions"><CODE>cupsEncodeOptions()</CODE></A>,
+<A HREF="#cupsFreeOptions"><CODE>cupsFreeOptions()</CODE></A>,
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetPassword">cupsGetPassword()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsGetPassword(const char *prompt);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>prompt</TD>
+ <TD>The prompt to display to the user.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the password that was entered or <CODE>NULL</CODE> if no
+password was entered.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetPassword()</CODE> displays the prompt string and asks the user
+for a password. The password text is not echoed to the user.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char *password;
+
+...
+
+password = cupsGetPassword("Please enter a password:");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>,
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>,
+<A HREF="#cupsSetServer"><CODE>cupsSetServer()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetPPD">cupsGetPPD()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsGetPPD(const char *printer);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>printer</TD>
+ <TD>The name of the printer.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The name of a temporary file containing the PPD file or <CODE>NULL</CODE>
+if the printer cannot be located or does not have a PPD file.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetPPD()</CODE> gets a copy of the PPD file for the named printer.
+The printer name can be of the form "printer" or "printer@hostname".
+
+<P>You should remove (unlink) the PPD file after you are done using it. The
+filename is stored in a static buffer and will be overwritten with each call
+to <CODE>cupsGetPPD()</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char *ppd;
+
+...
+
+ppd = cupsGetPPD("printer@hostname");
+
+...
+
+unlink(ppd);
+</PRE>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsGetPrinters">cupsGetPrinters()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsGetPrinters(char ***printers);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>printers</TD>
+ <TD>Pointer to character pointer array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of printer printers available.
+
+<H3>Description</H3>
+
+<P><CODE>cupsGetPrinters()</CODE> gets a list of the available printers.
+The returned array should be freed using the <CODE>free()</CODE> when it is
+no longer needed.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int i;
+int num_printers;
+char **printers;
+
+...
+
+num_printers = cupsGetPrinters(&amp;printers);
+
+...
+
+if (num_printers > 0)
+{
+ for (i = 0; i &lt; num_printers; i ++)
+ free(printers[i]);
+
+ free(printers);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetClasses"><CODE>cupsGetClasses()</CODE></A>
+<A HREF="#cupsGetDefault"><CODE>cupsGetDefault()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangDefault">cupsLangDefault()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsLangDefault(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>A pointer to the default language structure.
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangDefault()</CODE> returns a language structure for the default
+language. The default language is defined by the <CODE>LANG</CODE> environment
+variable. If the specified language cannot be located then the POSIX (English)
+locale is used.
+
+<P>Call <CODE>cupsLangFree()</CODE> to free any memory associated with the
+language structure when you are done.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+...
+
+language = cupsLangDefault();
+
+...
+
+cupsLangFree(language);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsLangFlush"><CODE>cupsLangFlush()</CODE></A>,
+<A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE></A>,
+<A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>,
+<A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangEncoding">cupsLangEncoding()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+cupsLangEncoding(cups_lang_t *language);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>language</TD>
+ <TD>The language structure.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the encoding string.
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangEncoding()</CODE> returns the language encoding used for the
+specified language, e.g. "iso-8859-1", "utf-8", etc.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+char *encoding;
+...
+
+language = cupsLangDefault();
+encoding = cupsLangEncoding(language);
+...
+
+cupsLangFree(language);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangFlush"><CODE>cupsLangFlush()</CODE></A>,
+<A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE></A>,
+<A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>,
+<A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangFlush">cupsLangFlush()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsLangFlush(void);
+</PRE>
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangFlush()</CODE> frees all language structures that have been
+allocated.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+...
+
+cupsLangFlush();
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE></A>,
+<A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>,
+<A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangFree">cupsLangFree()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsLangFree(cups_lang_t *language);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>language</TD>
+ <TD>The language structure to free.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangFree()</CODE> frees the specified language structure.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+...
+
+cupsLangFree(language);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsLangFlush"><CODE>cupsLangFlush()</CODE></A>,
+<A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>,
+<A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangGet">cupsLangGet()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+cups_lang_t *
+cupsLangGet(const char *name);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the locale.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a language structure.
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangGet()</CODE> returns a language structure for the specified
+locale. If the locale is not defined then the POSIX (English) locale is
+substituted.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+
+...
+
+language = cupsLangGet("fr");
+
+...
+
+cupsLangFree(language);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsLangFlush"><CODE>cupsLangFlush()</CODE></A>,
+<A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE></A>,
+<A HREF="#cupsLangString"><CODE>cupsLangString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLangString">cupsLangString()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+cupsLangString(cups_lang_t *language,
+ int message);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>language</TD>
+ <TD>The language to query.</TD>
+</TR>
+<TR>
+ <TD>message</TD>
+ <TD>The message number.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the message string or <CODE>NULL</CODE> if the message is
+not defined.
+
+<H3>Description</H3>
+
+<P><CODE>cupsLangString()</CODE> returns a pointer to the specified message
+string in the specified language.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/language.h&gt;
+
+<A HREF="#cups_lang_t">cups_lang_t</A> *language;
+char *s;
+...
+
+language = cupsLangGet("fr");
+
+s = cupsLangString(language, CUPS_MSG_YES);
+
+...
+
+cupsLangFree(language);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLangDefault"><CODE>cupsLangDefault()</CODE></A>,
+<A HREF="#cupsLangEncoding"><CODE>cupsLangEncoding()</CODE></A>,
+<A HREF="#cupsLangFlush"><CODE>cupsLangFlush()</CODE></A>,
+<A HREF="#cupsLangFree"><CODE>cupsLangFree()</CODE></A>,
+<A HREF="#cupsLangGet"><CODE>cupsLangGet()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsLastError">cupsLastError()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_status_t
+cupsLastError(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>An enumeration containing the last IPP error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsLastError()</CODE> returns the last IPP error that occurred.
+If no error occurred then it will return <CODE>IPP_OK</CODE> or
+<CODE>IPP_OK_CONFLICT</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+ipp_status_t status;
+
+...
+
+status = cupsLastError();
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>,
+<A HREF="#cupsPrintFile"><CODE>cupsPrintFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsMarkOptions">cupsMarkOptions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsMarkOptions(ppd_file_t *ppd,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file to mark.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options in the options array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>A pointer to the options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of conflicts found.
+
+<H3>Description</H3>
+
+<P><CODE>cupsMarkOptions()</CODE> marks options in the PPD file. It also
+handles mapping of IPP option names and values to PPD option names.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+<A HREF="#ppd_file_t">ppd_file_t</A> *ppd;
+
+...
+
+cupsMarkOptions(ppd, num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>,
+<A HREF="#cupsFreeOptions"><CODE>cupsFreeOptions()</CODE></A>,
+<A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A>,
+<A HREF="#cupsParseOptions"><CODE>cupsParseOptions()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsParseOptions">cupsParseOptions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsParseOptions(const char *arg,
+ int num_options,
+ cups_option_t **options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>arg</TD>
+ <TD>The string containing one or more options.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options in the options array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>A pointer to the options array pointer.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The new number of options in the array.
+
+<H3>Description</H3>
+
+<P><CODE>cupsParseOptions()</CODE> parses the specifies string for one
+or more options of the form "name=value", "name", or "noname". It can
+be called multiple times to combine the options from several strings.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+
+...
+
+num_options = 0;
+options = (cups_option_t *)0;
+num_options = cupsParseOptions(argv[5], num_options, &amp;options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsAddOption"><CODE>cupsAddOption()</CODE></A>,
+<A HREF="#cupsFreeOptions"><CODE>cupsFreeOptions()</CODE></A>,
+<A HREF="#cupsGetOption"><CODE>cupsGetOption()</CODE></A>,
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsPrintFile">cupsPrintFile()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsPrintFile(const char *printer,
+ const char *filename,
+ const char *title,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>printer</TD>
+ <TD>The printer or class to print to.</TD>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The file to print.</TD>
+</TR>
+<TR>
+ <TD>title</TD>
+ <TD>The job title.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options in the options array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>A pointer to the options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The new job ID number or 0 on error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsPrintFile()</CODE> sends a file to the specified printer or
+class for printing. If the job cannot be printed the error code can be
+found by calling <CODE>cupsLastError()</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+int jobid;
+
+...
+
+jobid = cupsPrintFile("printer@hostname", "filename.ps", "Job Title",
+ num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>,
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>,
+<A HREF="#cupsPrintFiles"><CODE>cupsPrintFiles()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsPrintFiles">cupsPrintFiles()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsPrintFiles(const char *printer,
+ int num_files,
+ const char **files,
+ const char *title,
+ int num_options,
+ cups_option_t *options);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>printer</TD>
+ <TD>The printer or class to print to.</TD>
+</TR>
+<TR>
+ <TD>num_files</TD>
+ <TD>The number of files to print.</TD>
+</TR>
+<TR>
+ <TD>files</TD>
+ <TD>The files to print.</TD>
+</TR>
+<TR>
+ <TD>title</TD>
+ <TD>The job title.</TD>
+</TR>
+<TR>
+ <TD>num_options</TD>
+ <TD>The number of options in the options array.</TD>
+</TR>
+<TR>
+ <TD>options</TD>
+ <TD>A pointer to the options array.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The new job ID number or 0 on error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsPrintFiles()</CODE> sends multiple files to the specified
+printer or class for printing. If the job cannot be printed the error
+code can be found by calling <CODE>cupsLastError()</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_files;
+const char *files[100];
+int num_options;
+<A HREF="#cups_option_t">cups_option_t</A> *options;
+int jobid;
+
+...
+
+jobid = cupsPrintFiles("printer@hostname", num_files, files,
+ "Job Title", num_options, options);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsCancelJob"><CODE>cupsCancelJob()</CODE></A>,
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>,
+<A HREF="#cupsPrintFile"><CODE>cupsPrintFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsPutFd">cupsPutFd()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_status_t
+cupsPutFd(http_t *http,
+ const char *resource,
+ int fd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection to the server.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource name on the server.</TD>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>The file descriptor to read from.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The HTTP status code associated with the request.
+
+<H3>Description</H3>
+
+<P><CODE>cupsPutFd()</CODE> puts a file to the given HTTP
+server, reading it from the specified file descriptor and
+performing any authentication or encryption as required.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+int fd;
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+status = cupsPutFd(http, "/admin/cupsd.conf", fd);
+
+httpClose(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>,
+<A HREF="#cupsGetFile"><CODE>cupsGetFile()</CODE></A>,
+<A HREF="#cupsPutFile"><CODE>cupsPutFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsPutFile">cupsPutFile()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_status_t
+cupsPutFile(http_t *http,
+ const char *resource,
+ const char *filename);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection to the server.</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource name on the server.</TD>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The filename to read from.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The HTTP status code associated with the request.
+
+<H3>Description</H3>
+
+<P><CODE>cupsPutFile()</CODE> puts a file on the given HTTP
+server, reading it from the specified filename and performing
+any authentication or encryption as required.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+http_t *http;
+char filename[1024];
+http_status_t status;
+...
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+status = cupsPutFile(http, "/admin/cupsd.conf", filename);
+
+httpClose(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetFd"><CODE>cupsGetFd()</CODE></A>,
+<A HREF="#cupsGetFile"><CODE>cupsGetFile()</CODE></A>,
+<A HREF="#cupsPutFd"><CODE>cupsPutFd()</CODE></A>
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterClose">cupsRasterClose()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsRasterClose(cups_raster_t *ras);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ras</TD>
+ <TD>The raster stream to close.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterClose()</CODE> closes the specified raster stream.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+
+...
+
+cupsRasterClose(ras);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>,
+<A HREF="#cupsRasterReadHeader"><CODE>cupsRasterReadHeader()</CODE></A>,
+<A HREF="#cupsRasterReadPixels"><CODE>cupsRasterReadPixels()</CODE></A>,
+<A HREF="#cupsRasterWriteHeader"><CODE>cupsRasterWriteHeader()</CODE></A>,
+<A HREF="#cupsRasterWritePixels"><CODE>cupsRasterWritePixels()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterOpen">cupsRasterOpen()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+cups_raster_t *
+cupsRasterOpen(int fd,
+ cups_mode_t mode);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>The file descriptor to use.</TD>
+</TR>
+<TR>
+ <TD>mode</TD>
+ <TD>The mode to use; <CODE>CUPS_RASTER_READ</CODE> or
+ <CODE>CUPS_RASTER_WRITE</CODE>.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a raster stream or <CODE>NULL</CODE> if there was an error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterOpen()</CODE> opens a raster stream for reading or writing.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+
+...
+
+ras = cupsRasterOpen(0, CUPS_RASTER_READ);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>,
+<A HREF="#cupsRasterReadHeader"><CODE>cupsRasterReadHeader()</CODE></A>,
+<A HREF="#cupsRasterReadPixels"><CODE>cupsRasterReadPixels()</CODE></A>,
+<A HREF="#cupsRasterWriteHeader"><CODE>cupsRasterWriteHeader()</CODE></A>,
+<A HREF="#cupsRasterWritePixels"><CODE>cupsRasterWritePixels()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterReadHeader">cupsRasterReadHeader()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+unsigned
+cupsRasterReadHeader(cups_raster_t *ras,
+ cups_page_header_t *header);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ras</TD>
+ <TD>The raster stream to read from.</TD>
+</TR>
+<TR>
+ <TD>header</TD>
+ <TD>A pointer to a page header structure to read into.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>1 on success, 0 on EOF or error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterReadHeader()</CODE> reads a page header from the specified
+raster stream.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ...
+
+ for (line = 0; line &lt; header.cupsHeight; line ++)
+ {
+ cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+ ...
+ }
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>,
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>,
+<A HREF="#cupsRasterReadPixels"><CODE>cupsRasterReadPixels()</CODE></A>,
+<A HREF="#cupsRasterWriteHeader"><CODE>cupsRasterWriteHeader()</CODE></A>,
+<A HREF="#cupsRasterWritePixels"><CODE>cupsRasterWritePixels()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterReadPixels">cupsRasterReadPixels()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+unsigned
+cupsRasterReadPixels(cups_raster_t *ras,
+ unsigned char *pixels,
+ unsigned length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ras</TD>
+ <TD>The raster stream to read from.</TD>
+</TR>
+<TR>
+ <TD>pixels</TD>
+ <TD>The pointer to a pixel buffer.</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The number of bytes of pixel data to read.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of bytes read or 0 on EOF or error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterReadPixels()</CODE> reads pixel data from the specified
+raster stream.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+while (cupsRasterReadHeader(ras, &amp;header))
+{
+ ...
+
+ for (line = 0; line &lt; header.cupsHeight; line ++)
+ {
+ cupsRasterReadPixels(ras, pixels, header.cupsBytesPerLine);
+
+ ...
+ }
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>,
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>,
+<A HREF="#cupsRasterReadHeader"><CODE>cupsRasterReadHeader()</CODE></A>,
+<A HREF="#cupsRasterWriteHeader"><CODE>cupsRasterWriteHeader()</CODE></A>,
+<A HREF="#cupsRasterWritePixels"><CODE>cupsRasterWritePixels()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterWriteHeader">cupsRasterWriteHeader()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+unsigned
+cupsRasterWriteHeader(cups_raster_t *ras,
+ cups_page_header_t *header);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ras</TD>
+ <TD>The raster stream to write to.</TD>
+</TR>
+<TR>
+ <TD>header</TD>
+ <TD>A pointer to the page header to write.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>1 on success, 0 on error.
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterWriteHeader()</CODE> writes the specified page header to
+a raster stream.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &amp;header);
+
+for (line = 0; line &lt; header.cupsHeight; line ++)
+{
+ ...
+
+ cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>,
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>,
+<A HREF="#cupsRasterReadHeader"><CODE>cupsRasterReadHeader()</CODE></A>,
+<A HREF="#cupsRasterReadPixels"><CODE>cupsRasterReadPixels()</CODE></A>,
+<A HREF="#cupsRasterWritePixels"><CODE>cupsRasterWritePixels()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsRasterWritePixels">cupsRasterWritePixels()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+unsigned
+cupsRasterWritePixels(cups_raster_t *ras,
+ unsigned char *pixels,
+ unsigned length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ras</TD>
+ <TD>The raster stream to write to.</TD>
+</TR>
+<TR>
+ <TD>pixels</TD>
+ <TD>The pixel data to write.</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The number of bytes to write.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of bytes written.
+
+<H3>Description</H3>
+
+<P><CODE>cupsRasterWritePixels()</CODE> writes the specified pixel data to a
+raster stream.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/raster.h&gt;
+
+int line;
+<A HREF="#cups_raster_t">cups_raster_t</A> *ras;
+<A HREF="#cups_raster_header_t">cups_raster_header_t</A> header;
+unsigned char pixels[8192];
+...
+
+cupsRasterWriteHeader(ras, &amp;header);
+
+for (line = 0; line &lt; header.cupsHeight; line ++)
+{
+ ...
+
+ cupsRasterWritePixels(ras, pixels, header.cupsBytesPerLine);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsRasterClose"><CODE>cupsRasterClose()</CODE></A>,
+<A HREF="#cupsRasterOpen"><CODE>cupsRasterOpen()</CODE></A>,
+<A HREF="#cupsRasterReadHeader"><CODE>cupsRasterReadHeader()</CODE></A>,
+<A HREF="#cupsRasterReadPixels"><CODE>cupsRasterReadPixels()</CODE></A>,
+<A HREF="#cupsRasterWriteHeader"><CODE>cupsRasterWriteHeader()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsServer">cupsServer()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsServer(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>A pointer to the default server name.
+
+<H3>Description</H3>
+
+<P><CODE>cupsServer()</CODE> returns a pointer to the default server name.
+The server name is stored in a static location and will be overwritten with
+every call to <CODE>cupsServer()</CODE>.
+
+<P>The default server is determined from the following locations:
+
+<OL>
+
+ <LI>The <CODE>CUPS_SERVER</CODE> environment variable,
+
+ <LI>The <CODE>ServerName</CODE> directive in the
+ <VAR>client.conf</VAR> file,
+
+ <LI>The default host, "localhost".
+
+</OL>
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *server;
+
+server = cupsServer();
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>,
+<A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>,
+<A HREF="#cupsSetServer"><CODE>cupsSetServer()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsSetDests">cupsSetDests()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsSetDests(int num_dests,
+ cups_dest_t *dests);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>num_dests</TD>
+ <TD>Number of destinations.</TD>
+</TR>
+<TR>
+ <TD>dests</TD>
+ <TD>Array of destinations.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsSetDests()</CODE> saves the destination array to
+disk. If the current UID is 0, the destinations are saved in the
+<VAR>/etc/cups/lpoptions</VAR> file, otherwise they are saved
+in the <VAR>~/.lpoptions</VAR> file. This function is typically used
+to save the default options and instances that are set by the user.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int num_dests;
+<A HREF="#cups_dest_t">cups_dest_t</A> *dests;
+
+...
+
+cupsSetDests(num_dests, dests);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsGetDests"><CODE>cupsGetDests()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsSetEncryption">cupsSetEncryption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsSetEncryption(http_encryption_t encryption);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>encryption</TD>
+ <TD>The type of encryption to use.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsSetEncryption()</CODE> sets the default type of encryption to
+use when connecting with the print server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsEncryption"><CODE>cupsEncryption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsSetPasswordCB">cupsSetPasswordCB()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsSetPasswordCB(const char *(*cb)(const char *prompt));
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>cb</TD>
+ <TD>The password callback function.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsSetPasswordCB()</CODE> sets the callback function to use when
+asking the user for a password. The callback function must accept a single
+character string pointer (the prompt string) and return <CODE>NULL</CODE>
+if the user did not enter a password string or a pointer to the password
+string otherwise.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *
+my_password_cb(const char *prompt)
+{
+ return (getpass(prompt));
+}
+
+...
+
+char *password;
+
+...
+
+cupsSetPasswordCB(my_password_cb);
+password = cupsGetPassword("Please enter a password:");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>,
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#cupsSetServer"><CODE>cupsSetServer()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsSetServer">cupsSetServer()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsSetServer(const char *server);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>server</TD>
+ <TD>The default server to use.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsSetServer()</CODE> sets the default server to use for
+the CUPS API. If the <CODE>server</CODE> argument is <CODE>NULL</CODE>,
+the default server is used.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+cupsSetServer("foo.bar.com");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsSetUser">cupsSetUser()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+cupsSetUser(const char *user);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>user</TD>
+ <TD>The user name string to use.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P><CODE>cupsSetUser()</CODE> sets the default user name for authentication.
+If the <CODE>user</CODE> argument is <CODE>NULL</CODE> then the current
+login user is used.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+...
+
+cupsSetUser("root");
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>,
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#cupsSetPasswordCB"><CODE>cupsSetPasswordCB()</CODE></A>,
+<A HREF="#cupsSetServer"><CODE>cupsSetServer()</CODE></A>,
+<A HREF="#cupsUser"><CODE>cupsUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsTempFd">cupsTempFd()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+cupsTempFd(char *filename,
+ int length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The character string to hold the temporary filename.</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The size of the filename string in bytes.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A file descriptor open for reading and writing.
+
+<H3>Description</H3>
+
+<P><CODE>cupsTempFd()</CODE> create a temporary filename in the
+<VAR>/var/tmp</VAR> directory or the directory specified by the
+<CODE>TMPDIR</CODE> environment variable.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+int fd;
+char filename[256];
+
+fd = cupsTempFd(filename, sizeof(filename));
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsTempFile"><CODE>cupsTempFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsTempFile">cupsTempFile()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+cupsTempFile(char *filename,
+ int length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The character string to hold the temporary filename.</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The size of the filename string in bytes.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to <CODE>filename</CODE>.
+
+<H3>Description</H3>
+
+<P><CODE>cupsTempFile()</CODE> creates a temporary filename in the
+<VAR>/var/tmp</VAR> directory or the directory specified by the
+<CODE>TMPDIR</CODE> environment variable.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+char filename[256];
+
+cupsTempFile(filename, sizeof(filename));
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsTempFd"><CODE>cupsTempFd()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="cupsUser">cupsUser()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+cupsUser(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>A pointer to the current username or <CODE>NULL</CODE> if the user ID is
+undefined.
+
+<H3>Description</H3>
+
+<P><CODE>cupsUser()</CODE> returns the name associated with the current
+user ID as reported by the <CODE>getuid()</CODE> system call.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/cups.h&gt;
+
+const char *user;
+
+user = cupsUser();
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsDoAuthentication"><CODE>cupsDoAuthentication()</CODE></A>,
+<A HREF="#cupsGetPassword"><CODE>cupsGetPassword()</CODE></A>,
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#cupsSetServer"><CODE>cupsSetServer()</CODE></A>,
+<A HREF="#cupsSetUser"><CODE>cupsSetUser()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpBlocking">httpBlocking()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpBlocking(http_t *http,
+ int blocking)
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>blocking</TD>
+ <TD>0 if the connection should be non-blocking, 1 if it should
+ be blocking</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpBlocking()</CODE> function sets the blocking mode for the
+HTTP connection. By default HTTP connections will block (stop) the client
+program until data is available or can be sent to the server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+http = httpConnect("server", port);
+httpBlocking(http, 0);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpCheck"><CODE>httpCheck()</CODE></A>,
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpCheck">httpCheck()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpCheck(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 if there is no data pending, 1 otherwise.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpCheck()</CODE> function checks to see if there is any data
+pending on an HTTP connection.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+if (httpCheck(http))
+{
+ ... do something ...
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpBlocking"><CODE>httpBlocking()</CODE></A>,
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGets"><CODE>httpGets()</CODE></A>,
+<A HREF="#httpRead"><CODE>httpRead()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpClearFields">httpClearFields()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpClearFields(http_t *http)
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpClearFields()</CODE> function clears all HTTP request fields
+for the HTTP connection.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpClearFields(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGetField"><CODE>httpGetField()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpClose">httpClose()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpClose(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpClose()</CODE> function closes an active HTTP connection.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpClose(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpConnect">httpConnect()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_t *
+httpConnect(const char *hostname,
+ int port);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>hostname</TD>
+ <TD>The name or IP address of the server to connect to</TD>
+</TR>
+<TR>
+ <TD>port</TD>
+ <TD>The port number to use</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a HTTP connection structure or NULL if the connection could
+not be made.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpConnect()</CODE> function opens a HTTP connection to the
+specified server and port.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+http = httpConnect(cupsServer(), ippPort());
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpClose"><CODE>httpClose()</CODE></A>,
+<A HREF="#httpConnectEncrypt"><CODE>httpConnectEncrypt()</CODE></A>,
+<A HREF="#httpGet"><CODE>httpGet()</CODE></A>,
+<A HREF="#httpGets"><CODE>httpGets()</CODE></A>,
+<A HREF="#httpPost"><CODE>httpPost()</CODE></A>,
+<A HREF="#httpRead"><CODE>httpRead()</CODE></A>,
+<A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpConnectEncrypt">httpConnectEncrypt()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_t *
+httpConnectEncrypt(const char *hostname,
+ int port,
+ http_encryption_t encryption);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>hostname</TD>
+ <TD>The name or IP address of the server to connect to</TD>
+</TR>
+<TR>
+ <TD>port</TD>
+ <TD>The port number to use</TD>
+</TR>
+<TR>
+ <TD>encryption</TD>
+ <TD>The level of encryption to use</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a HTTP connection structure or NULL if the connection could
+not be made.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpConnectEncrypt()</CODE> function opens a HTTP
+connection to the specified server, port, and encryption.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpClose"><CODE>httpClose()</CODE></A>,
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGet"><CODE>httpGet()</CODE></A>,
+<A HREF="#httpGets"><CODE>httpGets()</CODE></A>,
+<A HREF="#httpPost"><CODE>httpPost()</CODE></A>,
+<A HREF="#httpRead"><CODE>httpRead()</CODE></A>,
+<A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpDecode64">httpDecode64()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpDecode64(char *out,
+ const char *in);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>out</TD>
+ <TD>The output string</TD>
+</TR>
+<TR>
+ <TD>in</TD>
+ <TD>The input string</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the decoded string.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpDecode64()</CODE> function decodes a base-64 encoded string
+to the original string.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char encoded_string[255];
+char original_string[255];
+
+httpDecode64(original_string, encoded_string);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpEncode64"><CODE>httpEncode64()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpDelete">httpDelete()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpDelete(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to delete</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpDelete()</CODE> function sends a HTTP DELETE request to
+the server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpEncode64">httpEncode64()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpEncode64(char *out,
+ const char *in);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>out</TD>
+ <TD>The output string</TD>
+</TR>
+<TR>
+ <TD>in</TD>
+ <TD>The input string</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the encoded string.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpEncode64()</CODE> function decodes a base-64 encoded string
+to the original string.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char encoded_string[255];
+char original_string[255];
+
+httpEncode64(encoded_string, original_string);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpDecode64"><CODE>httpDecode64()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpEncryption">httpEncryption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpEncryption(http_t *http,
+ http_encryption_t encryption);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection.</TD>
+</TR>
+<TR>
+ <TD>encryption</TD>
+ <TD>The desired level of encryption.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, -1 on error.
+
+<H3>Description</H3>
+
+<P><CODE>httpEncryption()</CODE> sets the encryption level for the HTTP
+connection.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#httpConnectEncrypt"><CODE>httpConnectEncrypt()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpError">httpError()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpError(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The last error that occurred or 0 if no error has occurred.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpError()</CODE> function returns the last error that occurred
+on the HTTP connection.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+if (httpError(http))
+{
+ ... show an error message ...
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpFlush">httpFlush()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpFlush(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpFlush()</CODE> function flushes any remaining data left from
+a GET or POST operation.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpFlush(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGet">httpGet()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpGet(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to get</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGet()</CODE> function sends a HTTP GET request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+httpGet(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGets">httpGets()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpGets(char *line,
+ int length,
+ http_t *http)
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>line</TD>
+ <TD>The string to fill with a line from the HTTP connection</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The maximum length of the string</TD>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the string or NULL if no line could be retrieved.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGets()</CODE> function is used to read a request line from
+the HTTP connection. It is not normally used by a client program.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+char line[1024];
+
+if (httpGets(line, sizeof(line), http))
+{
+ ... process the line ...
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetDateString">httpGetDateString()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+httpGetDateString(time_t time)
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>time</TD>
+ <TD>The UNIX date/time value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a static string containing the HTTP date/time string for
+the specified UNIX time value.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGetDateString()</CODE> function generates a date/time string
+suitable for HTTP requests from a UNIX time value.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+puts(httpGetDateString(time(NULL)));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpGetDateTime"><CODE>httpGetDateTime()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetDateTime">httpGetDateTime()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+time_t
+httpGetDateTime(const char *date)
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>date</TD>
+ <TD>The HTTP date/time string</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A UNIX time value.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGetDateTime()</CODE> function converts a HTTP
+date/time string to a UNIX time value.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+printf("%d\n", httpGetDateTime("Fri, 30 June 2000 12:34:56 GMT"));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpGetDateString"><CODE>httpGetDateString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetField">httpGetField()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+httpGetField(http_t *http,
+ http_field_t field);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>field</TD>
+ <TD>The HTTP field</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the field value string.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGetField()</CODE> function returns the current value for
+the specified HTTP field.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetField(http, HTTP_FIELD_CONTENT_TYPE));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGetSubField"><CODE>httpGetSubField()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetHostByName">httpGetHostByName()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+struct hostent *
+httpGetHostByName(const char *name);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>Name or IP address to lookup.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>NULL if the host could not be found or a pointer to a host entry
+containing one or more addresses.
+
+<H3>Description</H3>
+
+<P><CODE>httpGetHostByName()</CODE> is a portable wrapper around the
+<CODE>gethostbyname()</CODE> function which handles both hostnames
+and IP addresses.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+struct hostent *hostaddr;
+
+hostaddr = httpGetHostByName("foo.bar.com");
+</PRE>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetLength">httpGetLength()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpGetLength(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The content length of the response or MAX_INT if chunking is used.
+
+<H3>Description</H3>
+
+<P><CODE>httpGetLength()</CODE> returns the content length of a response.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+printf("The length of the response is %d bytes.\n", httpGetLength(http));
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#httpGet"><CODE>httpGet()</CODE></A>,
+<A HREF="#httpPost"><CODE>httpPost()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpGetSubField">httpGetSubField()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+httpGetSubField(http_t *http,
+ http_field_t field,
+ const char *name,
+ char *value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection.</TD>
+</TR>
+<TR>
+ <TD>field</TD>
+ <TD>The HTTP field.</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the subfield.</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The string to hold the subfield value.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the subfield value string or NULL if it does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpGetSubField()</CODE> function returns a subfield value
+from the specified HTTP field. The destination string buffer must be at
+least <CODE>HTTP_MAX_VALUE</CODE> bytes in length.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+char value[HTTP_MAX_VALUE];
+
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+
+puts(httpGetSubField(http, HTTP_FIELD_CONTENT_TYPE, "charset", value));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGetField"><CODE>httpGetField()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpHead">httpHead()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpHead(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to head</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpHead()</CODE> function sends a HTTP HEAD request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpHead(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpInitialize">httpInitialize()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void httpInitialize(void);
+</PRE>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpInitialize()</CODE> function initializes the networking
+code as needed by the underlying platform. It is called automatically by
+the <CODE>httpConnect()</CODE> function.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+httpInitialize();
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpMD5">httpMD5()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpMD5(const char *username,
+ const char *realm,
+ const char *passwd,
+ char md5[33]);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>username</TD>
+ <TD>The authenticating user name.</TD>
+</TR>
+<TR>
+ <TD>realm</TD>
+ <TD>The authenticating realm name.</TD>
+</TR>
+<TR>
+ <TD>passwd</TD>
+ <TD>The authenticating password.</TD>
+</TR>
+<TR>
+ <TD>md5</TD>
+ <TD>The MD5 sum string.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the MD5 sum string.
+
+<H3>Description</H3>
+
+<P><CODE>httpMD5()</CODE> computes the MD5 hash of the username,
+realm, and password as required by the HTTP Digest specification.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char md5[33];
+
+...
+
+httpMD5("user", "realm", "password", md5);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#httpMD5Final"><CODE>httpMD5Final()</CODE></A>,
+<A HREF="#httpMD5String"><CODE>httpMD5String()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpMD5Final">httpMD5Final()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpMD5Final(const char *nonce,
+ const char *method,
+ const char *resource,
+ char md5[33]);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>nonce</TD>
+ <TD>The server nonce value.</TD>
+</TR>
+<TR>
+ <TD>method</TD>
+ <TD>The HTTP method (GET, POST, etc.)</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource path.</TD>
+</TR>
+<TR>
+ <TD>md5</TD>
+ <TD>The MD5 sum string.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The MD5 sum string.
+
+<H3>Description</H3>
+
+<P><CODE>httpMD5Final()</CODE> appends the nonce, method, and resource
+to the specified MD5 sum.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+char md5[33];
+
+...
+
+httpMD5Final("nonce", "GET", "/jobs", md5);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#httpMD5"><CODE>httpMD5()</CODE></A>,
+<A HREF="#httpMD5String"><CODE>httpMD5String()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpMD5String">httpMD5String()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+char *
+httpMD5String(const md5_byte_t *sum,
+ char md5[33]);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>sum</TD>
+ <TD>The raw MD5 sum data.</TD>
+</TR>
+<TR>
+ <TD>md5</TD>
+ <TD>The MD5 sum string.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The MD5 sum string.
+
+<H3>Description</H3>
+
+<P><CODE>httpMD5String()</CODE> converts the raw MD5 sum value to a string.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+md5_byte_t sum[16];
+char md5[33];
+
+...
+
+httpMD5String(sum, md5);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#httpMD5"><CODE>httpMD5()</CODE></A>,
+<A HREF="#httpMD5Final"><CODE>httpMD5Final()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpOptions">httpOptions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpOptions(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to check for options</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpOptions()</CODE> function sends a HTTP OPTIONS request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpOptions(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpPost">httpPost()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpPost(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to post to</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpPost()</CODE> function sends a HTTP POST request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpPost(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpPrintf">httpPrintf()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpPrintf(http_t *http,
+ const char *format,
+ ...);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>format</TD>
+ <TD>A printf-style format string</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of bytes written.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpPrintf()</CODE> function sends a formatted string to the
+HTTP connection. It is normally only used by the CUPS API and scheduler.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpPrintf(http, "GET / HTTP/1.1 \r\n");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpPut">httpPut()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpPut(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to put</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpPut()</CODE> function sends a HTTP PUT request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpDelete(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpRead">httpRead()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpRead(http_t *http,
+ char *buffer,
+ int length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>buffer</TD>
+ <TD>The buffer to read into</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The number of bytes to read</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of bytes read or -1 on error.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpRead()</CODE> function reads data from the HTTP connection,
+possibly the result of a GET or POST request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+char buffer[1024];
+int bytes;
+
+httpGet(http, "/");
+while (httpUpdate(http) != HTTP_CONTINUE);
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+ buffer[bytes] = '\0';
+ fputs(buffer, stdout);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpWrite"><CODE>httpWrite()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpReconnect">httpReconnect()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpReconnect(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpReconnect()</CODE> function reconnects to the HTTP server.
+This is usually done automatically if the HTTP functions detect that the
+server connection has terminated.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpReconnect(http);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpSeparate">httpSeparate()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpSeparate(const char *uri,
+ char *method,
+ char *username,
+ char *host,
+ int *port,
+ char *resource);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to separate</TD>
+</TR>
+<TR>
+ <TD>method</TD>
+ <TD>The method (scheme) of the URI</TD>
+</TR>
+<TR>
+ <TD>username</TD>
+ <TD>The username (and password) portion of the URI, if any</TD>
+</TR>
+<TR>
+ <TD>host</TD>
+ <TD>The hostname portion of the URI, if any</TD>
+</TR>
+<TR>
+ <TD>port</TD>
+ <TD>The port number for the URI, either as specified or as
+ default for the method/scheme</TD>
+</TR>
+<TR>
+ <TD>resource</TD>
+ <TD>The resource string, usually a filename on the server</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpSeparate()</CODE> function separates the specified URI into
+its component parts. The method, username, hostname, and resource strings should
+be at least <CODE>HTTP_MAX_URI</CODE> characters long to avoid potential
+buffer overflow problems.
+
+<H3>Example</H3>
+
+<PRE>
+char uri[HTTP_MAX_URI];
+char method[HTTP_MAX_URI];
+char username[HTTP_MAX_URI];
+char host[HTTP_MAX_URI];
+char resource[HTTP_MAX_URI];
+int port;
+
+...
+
+httpSeparate(uri, method, username, host, &amp;port, resource);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpSetField">httpSetField()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+httpSetField(http_t *http,
+ http_field_t field,
+ const char *value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>field</TD>
+ <TD>The HTTP field</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The string value for the field</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>httpSetField()</CODE> function sets the current value for
+the specified HTTP field.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpSetField(http, HTTP_FIELD_AUTHORIZATION, "Basic dfdr34453454325"));
+httpGet(http, "/some/uri");
+while (httpUpdate(http) == HTTP_CONTINUE);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpGetField"><CODE>httpGetField()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpStatus">httpStatus()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+httpStatus(http_status_t status);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>status</TD>
+ <TD>The HTTP status code from the server.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The standard HTTP status text associated with the status code.
+
+<H3>Description</H3>
+
+<P><CODE>httpStatus()</CODE> returns the standard HTTP status text
+associated with the status code.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+<A HREF="#http_t">http_t</A> *http;
+
+...
+
+puts(httpStatus(http->status));
+</PRE>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpTrace">httpTrace()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpTrace(http_t *http,
+ const char *uri);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>uri</TD>
+ <TD>The URI to trace</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, non-zero on failure.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpTrace()</CODE> function sends a HTTP TRACE request to the
+server.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+
+httpTrace(http, "/some/uri");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpSetField"><CODE>httpSetField()</CODE></A>,
+<A HREF="#httpUpdate"><CODE>httpUpdate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpUpdate">httpUpdate()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+http_status_t
+httpUpdate(http_t *http);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The HTTP status of the current request.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpUpdate()</CODE> function updates the current request status.
+It is used after any DELETE, GET, HEAD, OPTIONS, POST, PUT, or TRACE
+request to finalize the HTTP request and retrieve the request status.
+
+<P>Since proxies and the current blocking mode can cause the request to
+take longer, programs should continue calling <CODE>httpUpdate()<CODE>
+until the return status is not the constant value <CODE>HTTP_CONTINUE</CODE>.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+http_status_t status;
+
+httpGet(http, "/some/uri");
+while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+printf("Request status is %d\n", status);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpDelete"><CODE>httpDelete()</CODE></A>,
+<A HREF="#httpGet"><CODE>httpGet()</CODE></A>,
+<A HREF="#httpHead"><CODE>httpHead()</CODE></A>,
+<A HREF="#httpOptions"><CODE>httpOptions()</CODE></A>,
+<A HREF="#httpPost"><CODE>httpPost()</CODE></A>,
+<A HREF="#httpPut"><CODE>httpPut()</CODE></A>,
+<A HREF="#httpTrace"><CODE>httpTrace()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="httpWrite">httpWrite()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+httpWrite(http_t *http,
+ char *buffer,
+ int length);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>buffer</TD>
+ <TD>The buffer to read into</TD>
+</TR>
+<TR>
+ <TD>length</TD>
+ <TD>The number of bytes to read</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of bytes read or -1 on error.
+
+<H3>Description</H3>
+
+<P>The <CODE>httpWrite()</CODE> function reads data from the HTTP connection,
+possibly the result of a GET or POST request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h&gt;
+
+http_t *http;
+FILE *fp;
+char buffer[1024];
+int bytes;
+
+httpPost(http, "/");
+
+while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+ httpWrite(http, buffer, bytes);
+
+while (httpUpdate(http) != HTTP_CONTINUE);
+
+while ((bytes = httpRead(http, buffer, sizeof(buffer) - 1)) > 0)
+{
+ buffer[bytes] = '\0';
+ fputs(buffer, stdout);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#httpConnect"><CODE>httpConnect()</CODE></A>,
+<A HREF="#httpRead"><CODE>httpRead()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddBoolean">ippAddBoolean()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddBoolean(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ char value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The boolean value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddBoolean()</CODE> function adds a single boolean attribute
+value to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "my-jobs", 1);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddBooleans">ippAddBooleans()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddBooleans(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const char *values);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>num_values</TD>
+ <TD>The number of values</TD>
+</TR>
+<TR>
+ <TD>values</TD>
+ <TD>The boolean values</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddBooleans()</CODE> function adds one or more boolean
+attribute values to the specified IPP request. If the
+<CODE>values</CODE> pointer is <CODE>NULL</CODE> then an array of
+<CODE>num_values</CODE> false values is created.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+char values[10];
+
+ippAddBooleans(ipp, IPP_TAG_OPERATION, "some-attribute", 10, values);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddDate">ippAddDate()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddDate(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ ipp_uchar_t *value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The date value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddDate()</CODE> function adds a single date-time attribute
+value to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddDate(ipp, IPP_TAG_OPERATION, "some-attribute",
+ ippTimeToDate(time(NULL));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>,
+<A HREF="#ippTimeToDate"><CODE>ippTimeToDate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddInteger">ippAddInteger()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddInteger(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The integer value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddInteger()</CODE> function adds a single integer attribute
+value to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddInteger(ipp, IPP_TAG_OPERATION, "limit", 100);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddIntegers">ippAddIntegers()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddIntegers(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const int *values);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The type of integer value (IPP_TAG_INTEGER or IPP_TAG_ENUM)</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>num_values</TD>
+ <TD>The number of values</TD>
+</TR>
+<TR>
+ <TD>values</TD>
+ <TD>The integer values</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddIntegers()</CODE> function adds one or more integer
+attribute values to the specified IPP request. If the
+<CODE>values</CODE> pointer is <CODE>NULL</CODE> then an array of
+<CODE>num_values</CODE> 0 values is created.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+int values[100];
+
+ippAddIntegers(ipp, IPP_TAG_OPERATION, "some-attribute", 100, values);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddRange">ippAddRange()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddRange(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int low,
+ int high);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>low</TD>
+ <TD>The lower value</TD>
+</TR>
+<TR>
+ <TD>high</TD>
+ <TD>The higher value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddRange()</CODE> function adds a single range attribute
+value to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddRange(ipp, IPP_TAG_OPERATION, "page-ranges", 1, 10);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddRanges">ippAddRanges()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddRanges(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const int *lows,
+ const int *highs);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>num_values</TD>
+ <TD>The number of range values</TD>
+</TR>
+<TR>
+ <TD>lows</TD>
+ <TD>The lower values</TD>
+</TR>
+<TR>
+ <TD>highs</TD>
+ <TD>The higher values</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddRanges()</CODE> function adds one or more range
+attribute values to the specified IPP request. If the
+<CODE>values</CODE> pointer is <CODE>NULL</CODE> then an array of
+<CODE>num_values</CODE> 0,0 ranges is created.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+int lows[2];
+int highs[2];
+
+ippAddRanges(ipp, IPP_TAG_OPERATION, "page-ranges", 2, lows, highs);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddResolution">ippAddResolution()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddResolution(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int xres,
+ int yres,
+ ipp_res_t units);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>xres</TD>
+ <TD>The horizontal resolution</TD>
+</TR>
+<TR>
+ <TD>yres</TD>
+ <TD>The vertical resolution</TD>
+</TR>
+<TR>
+ <TD>units</TD>
+ <TD>The resolution units</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddResolution()</CODE> function adds a single resolution attribute
+value to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolution",
+ 720, 720, IPP_RES_PER_INCH);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddResolutions">ippAddResolutions()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddResolutions(ipp_t *ipp,
+ ipp_tag_t group,
+ const char *name,
+ int num_values,
+ const int *xres,
+ const int *yres,
+ const ipp_res_t *units);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>num_values</TD>
+ <TD>The number of resolution values</TD>
+</TR>
+<TR>
+ <TD>xres</TD>
+ <TD>The horizontal resolutions</TD>
+</TR>
+<TR>
+ <TD>yres</TD>
+ <TD>The vertical resolutions</TD>
+</TR>
+<TR>
+ <TD>units</TD>
+ <TD>The resolution units</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddResolutions()</CODE> function adds one or more
+resolution attribute values to the specified IPP request. If the
+<CODE>values</CODE> pointer is <CODE>NULL</CODE> then an array of
+<CODE>num_values</CODE> 0,0 resolutions is created.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+int xres[5];
+int yres[5];
+ipp_res_t units[5];
+
+ippAddBoolean(ipp, IPP_TAG_OPERATION, "printer-resolutions-supported",
+ 5, xres, yres, units);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddSeparator">ippAddSeparator()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddSeparator(ipp_t *ipp);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new separator or NULL if the separator could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddSeparator()</CODE> function adds a group separator
+to the specified IPP request.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddSeparator(ipp);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddString">ippAddString()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddString(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ const char *charset,
+ const char *value);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The type of string value</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>charset</TD>
+ <TD>The character set for the string</TD>
+</TR>
+<TR>
+ <TD>value</TD>
+ <TD>The string value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddString()</CODE> function adds a single string attribute
+value to the specified IPP request. For <CODE>IPP_TAG_NAMELANG</CODE> and
+<CODE>IPP_TAG_TEXTLANG</CODE> strings, the charset value is provided with
+the string to identify the string encoding used. Otherwise the charset value
+is ignored.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippAddString(ipp, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+ NULL, "abc123");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddStrings"><CODE>ippAddStrings()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippAddStrings">ippAddStrings()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippAddStrings(ipp_t *ipp,
+ ipp_tag_t group,
+ ipp_tag_t tag,
+ const char *name,
+ int num_values,
+ const char *charset,
+ const char **values);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request</TD>
+</TR>
+<TR>
+ <TD>group</TD>
+ <TD>The IPP group</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The type of string value</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of attribute</TD>
+</TR>
+<TR>
+ <TD>num_values</TD>
+ <TD>The number of strings</TD>
+</TR>
+<TR>
+ <TD>charset</TD>
+ <TD>The character set for the strings</TD>
+</TR>
+<TR>
+ <TD>values</TD>
+ <TD>The string values</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the new attribute or NULL if the attribute could not be
+created.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippAddStrings()</CODE> function adds one or more string
+attribute values to the specified IPP request. For
+<CODE>IPP_TAG_NAMELANG</CODE> and <CODE>IPP_TAG_TEXTLANG</CODE>
+strings, the charset value is provided with the strings to identify the
+string encoding used. Otherwise the charset value is ignored. If the
+<CODE>values</CODE> pointer is <CODE>NULL</CODE> then an array of
+<CODE>num_values</CODE> NULL strings is created.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+char *values[2] = { "one", "two" };
+
+ippAddStrings(ipp, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "attr-name",
+ 2, NULL, values);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippAddBoolean"><CODE>ippAddBoolean()</CODE></A>,
+<A HREF="#ippAddBooleans"><CODE>ippAddBooleans()</CODE></A>,
+<A HREF="#ippAddDate"><CODE>ippAddDate()</CODE></A>,
+<A HREF="#ippAddInteger"><CODE>ippAddInteger()</CODE></A>,
+<A HREF="#ippAddIntegers"><CODE>ippAddIntegers()</CODE></A>,
+<A HREF="#ippAddRange"><CODE>ippAddRange()</CODE></A>,
+<A HREF="#ippAddRanges"><CODE>ippAddRanges()</CODE></A>,
+<A HREF="#ippAddResolution"><CODE>ippAddResolution()</CODE></A>,
+<A HREF="#ippAddResolutions"><CODE>ippAddResolutions()</CODE></A>,
+<A HREF="#ippAddSeparator"><CODE>ippAddSeparator()</CODE></A>,
+<A HREF="#ippAddString"><CODE>ippAddString()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippDateToTime">ippDateToTime()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+time_t
+ippDateToTime(const ipp_uchar_t date[11]);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>date</TD>
+ <TD>The IPP date-time value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A UNIX time value.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippDateToTime()</CODE> function converts an IPP date-time value
+to a UNIX time value.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_uchar_t date[11];
+
+printf("UNIX time is %d\n", ippDateToTime(date));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippTimeToDate"><CODE>ippTimeToDate()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippDelete">ippDelete()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+ippDelete(ipp_t *ipp);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>ippDelete()</CODE> function deletes all memory used by an IPP
+request or response.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ippDelete(ipp);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippErrorString">ippErrorString()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+const char *
+ippErrorString(ipp_status_t error);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>error</TD>
+ <TD>IPP error code.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The standard text representation of the IPP error code.
+
+<H3>Description</H3>
+
+<P><CODE>ippErrorString()</CODE> returns the standard text representation
+of the IPP error code.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h&gt;
+
+puts(ippErrorString(IPP_OK));
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#cupsLastError"><CODE>cupsLastError()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippFindAttribute">ippFindAttribute()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippFindAttribute(ipp_t *ipp,
+ const char *name,
+ ipp_tag_t tag);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the attribute</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The required value tag for the attribute or
+ <CODE>IPP_TAG_ZERO</CODE> for any type of value.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the first occurrence of the requested attribute, or
+<CODE>NULL</CODE> if it was not found.
+
+<H3>Description</H3>
+
+<P><CODE>ippFindAttribute()</CODE> finds the first occurrence of the named
+attribute. The <CODE>tag</CODE> parameter restricts the search to a specific
+value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value with the name.
+
+<P>The value tags <CODE>IPP_TAG_NAME</CODE> and <CODE>IPP_TAG_TEXT</CODE>
+match the name/text values with or without the language code.
+
+<H3>Example</H3>
+
+<PRE>
+<A HREF="#ipp_attribute_t">ipp_attribute_t</A> *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+ puts(attr->values[0].string.text);
+
+ attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsDoFileRequest"><CODE>cupsDoFileRequest()</CODE></A>,
+<A HREF="#cupsDoRequest"><CODE>cupsDoRequest()</CODE></A>,
+<A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>,
+<A HREF="#ippFindNextAttribute"><CODE>ippFindNextAttribute()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippFindNextAttribute">ippFindNextAttribute()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_attribute_t *
+ippFindNextAttribute(ipp_t *ipp,
+ const char *name,
+ ipp_tag_t tag);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the attribute</TD>
+</TR>
+<TR>
+ <TD>tag</TD>
+ <TD>The required value tag for the attribute or
+ <CODE>IPP_TAG_ZERO</CODE> for any type of value.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the next occurrence of the requested attribute, or
+<CODE>NULL</CODE> if it was not found.
+
+<H3>Description</H3>
+
+<P><CODE>ippFindNextAttribute()</CODE> finds the next occurrence of the named
+attribute. The <CODE>tag</CODE> parameter restricts the search to a specific
+value type - use <CODE>IPP_TAG_ZERO</CODE> to find any value with the name.
+
+<P>The value tags <CODE>IPP_TAG_NAME</CODE> and <CODE>IPP_TAG_TEXT</CODE>
+match the name/text values with or without the language code.
+
+<H3>Example</H3>
+
+<PRE>
+<A HREF="#ipp_attribute_t">ipp_attribute_t</A> *attr;
+
+attr = ippFindAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+while (attr != NULL)
+{
+ puts(attr->values[0].string.text);
+
+ attr = ippFindNextAttribute(response, "printer-state-message", IPP_TAG_TEXT);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsDoFileRequest"><CODE>cupsDoFileRequest()</CODE></A>,
+<A HREF="#cupsDoRequest"><CODE>cupsDoRequest()</CODE></A>,
+<A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>,
+<A HREF="#ippFindNextAttribute"><CODE>ippFindNextAttribute()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippLength">ippLength()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ippLength(ipp_t *ipp);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The total encoded length of the IPP request or response in bytes.
+
+<H3>Description</H3>
+
+<P><CODE>ippLength()</CODE> returns the length of the IPP request or
+response in bytes.
+
+<H3>Example</H3>
+
+<PRE>
+printf("The length of the response is %d bytes.\n", ippLength(response));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>,
+<A HREF="#ippNew"><CODE>ippNew()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippNew">ippNew()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_t *
+ippNew(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>A pointer to a new IPP request or response.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippNew()</CODE> function creates a new IPP request or response.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_t *ipp;
+
+ipp = ippNew();
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippDelete"><CODE>ippDelete()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippPort">ippPort()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ippPort(void);
+</PRE>
+
+<H3>Returns</H3>
+
+<P>The default TCP/IP port number for IPP requests.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippPort()</CODE> function returns the default IPP port number
+for requests.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h>
+#include &lt;cups/ipp.h>
+
+http_t *http;
+
+http = httpConnect(cupsServer(), ippPort());
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsServer"><CODE>cupsServer()</CODE></A>,
+<A HREF="#ippSetPort"><CODE>ippSetPort()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippRead">ippRead()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_state_t
+ippRead(http_t *http,
+ ipp_t *ipp);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The current read state.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippRead()</CODE> function reads IPP attributes from the specified
+HTTP connection. Programs should continue calling <CODE>ippRead()</CODE> until
+<CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE> is returned.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h>
+#include &lt;cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+
+while ((status = ippRead(http, ipp)) != IPP_ERROR)
+ if (status == IPP_DATA)
+ break;
+
+if (status == IPP_DATA)
+{
+ ... read additional non-IPP data using httpRead() ...
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippWrite"><CODE>ippWrite()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippSetPort">ippSetPort()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+ippSetPort(int port);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>port</TD>
+ <TD>The port number to use</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>ippSetPort()</CODE> function sets the default IPP port number
+for requests.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h>
+#include &lt;cups/ipp.h>
+
+...
+
+ippSetPort(8631);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippPort"><CODE>ippPort()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippTimeToDate">ippTimeToDate()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_uchar_t *
+ippTimeToDate(time_t time);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>time</TD>
+ <TD>The UNIX time value</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A static pointer to an IPP date-time value.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippTimeToDate()</CODE> function converts a UNIX time to an IPP
+date-time value.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ipp.h>
+
+ipp_uchar_t *date;
+
+date = ippTimeToDate(time(NULL));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippDateToTime"><CODE>ippDateToTime()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ippWrite">ippWrite()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ipp_state_t
+ippWrite(http_t *http,
+ ipp_t *ipp);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>http</TD>
+ <TD>The HTTP connection</TD>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>The IPP request or response</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The current write state.
+
+<H3>Description</H3>
+
+<P>The <CODE>ippWrite()</CODE> function writes IPP attributes to the specified
+HTTP connection. Programs should continue calling <CODE>ippWrite()</CODE> until
+<CODE>IPP_ERROR</CODE> or <CODE>IPP_DATA</CODE> is returned.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/http.h>
+#include &lt;cups/ipp.h>
+
+http_t *http;
+ipp_t *ipp;
+ipp_state_t status;
+
+ipp = ippNew();
+... add attributes ...
+
+while ((status = ippWrite(http, ipp)) != IPP_ERROR)
+ if (status == IPP_DATA)
+ break;
+
+if (status == IPP_DATA)
+{
+ ... read additional non-IPP data using httpWrite() ...
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ippRead"><CODE>ippRead()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdClose">ppdClose()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+ppdClose(ppd_file_t *ppd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdClose()</CODE> function frees all memory associated with the
+PPD file.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdClose(ppd);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdOpen"><CODE>ppdOpen()</CODE></A>,
+<A HREF="#ppdOpenFd"><CODE>ppdOpenFd()</CODE></A>,
+<A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdCollect">ppdCollect()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdCollect(ppd_file_t *ppd,
+ ppd_section_t section,
+ ppd_choice_t ***choices);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file.</TD>
+</TR>
+<TR>
+ <TD>section</TD>
+ <TD>The document section to collect.</TD>
+</TR>
+<TR>
+ <TD>choices</TD>
+ <TD>The array of option choices that are marked.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of options collected.
+
+<H3>Description</H3>
+
+<P><CODE>ppdCollect()</CODE> collects all of the marked options in the
+specified section, sorts them by their order dependency values, and
+returns an array that can be used to emit option commands in the proper
+order. It is normally used by the <CODE>ppdEmit*()</CODE> functions.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h&gt;
+
+<A HREF="#ppd_file_t">ppd_file_t</A> *ppd;
+int num_choices;
+<A HREF="#ppd_choice_t">ppd_choice_t</A> **choices;
+
+...
+
+num_choices = ppdCollect(ppd, PPD_ORDER_JCL, &amp;choices);
+</PRE>
+
+<H3>See Also</H3>
+
+<P>
+<A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>,
+<A HREF="#ppdEmitFd"><CODE>ppdEmitFd()</CODE></A>,
+<A HREF="#ppdEmitJCL"><CODE>ppdEmitJCL()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdConflicts">ppdConflicts()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdConflicts(ppd_file_t *ppd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of option conflicts in the file.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdConflicts()</CODE> function returns the number of conflicts
+with the currently selected options.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("%d conflicts\n", ppdConflicts(ppd));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#ppdIsMarked"><CODE>ppdIsMarked()</CODE></A>,
+<A HREF="#ppdMarkDefaults"><CODE>ppdMarkDefaults()</CODE></A>,
+<A HREF="#ppdMarkOption"><CODE>ppdMarkOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdEmit">ppdEmit()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdEmit(ppd_file_t *ppd,
+ FILE *file,
+ ppd_section_t section);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>file</TD>
+ <TD>The file to write to</TD>
+</TR>
+<TR>
+ <TD>section</TD>
+ <TD>The option section to write</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, -1 on error.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdEmit()</CODE> function sends printer-specific option
+commands to the specified file.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdEmitFd"><CODE>ppdEmitFd()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdEmitFd">ppdEmitFd()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdEmitFd(ppd_file_t *ppd,
+ int fd,
+ ppd_section_t section);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>The file descriptor to write to</TD>
+</TR>
+<TR>
+ <TD>section</TD>
+ <TD>The option section to write</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, -1 on error.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdEmitFd()</CODE> function sends printer-specific option
+commands to the specified file descriptor.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitFd(ppd, 1, PPD_ORDER_PAGE);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>,
+<A HREF="#ppdEmitJCL"><CODE>ppdEmitJCL()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdEmitJCL">ppdEmitJCL()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdEmitJCL(ppd_file_t *ppd,
+ FILE *file,
+ int job_id,
+ const char *user,
+ const char *title);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>file</TD>
+ <TD>The file to write to</TD>
+</TR>
+<TR>
+ <TD>job_id</TD>
+ <TD>The job ID number</TD>
+</TR>
+<TR>
+ <TD>user</TD>
+ <TD>The job user</TD>
+</TR>
+<TR>
+ <TD>title</TD>
+ <TD>The job name</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>0 on success, -1 on error.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdEmitJCL()</CODE> function sends printer-specific
+job control commands to the specified file. For printers that
+support the HP Printer Job Language (PJL) job control language,
+the output also contains a display string that usually appears
+on the printer's LCD.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdEmitJCL(ppd, stdout, job_id, user, title);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdEmit"><CODE>ppdEmit()</CODE></A>,
+<A HREF="#ppdEmitFd"><CODE>ppdEmitFd()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdFindAttr">ppdFindAttr()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_attr_t *
+ppdFindAttr(ppd_file_t *ppd,
+ const char *keyword,
+ const char *spec);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the attribute</TD>
+</TR>
+<TR>
+ <TD>spec</TD>
+ <TD>The option keyword associated with the attribute or
+ NULL if you don't care.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the attribute data or NULL if the attribute does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdFindAttr()</CODE> function returns a pointer to
+the first occurrence of the attribute in the PPD file.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_attr_t *attr;
+
+attr = ppdFindAttr(ppd, "RequiresPageRegion", "Upper");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdFindNextAttr"><CODE>ppdFindNextAttr()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdFindChoice">ppdFindChoice()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_choice_t *
+ppdFindChoice(ppd_option_t *option,
+ const char *choice);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>option</TD>
+ <TD>A pointer to the option</TD>
+</TR>
+<TR>
+ <TD>choice</TD>
+ <TD>The name of the choice</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the choice data or NULL if the choice does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdFindChoice()</CODE> function returns a pointer to the choice
+data for the specified option.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+ppd_choice_t *choice;
+
+option = ppdFindOption(ppd, "PageSize");
+choice = ppdFindChoice(option, "Letter");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdFindMarkedChoice"><CODE>ppdFindMarkedChoice()</CODE></A>,
+<A HREF="#ppdFindOption"><CODE>ppdFindOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdFindMarkedChoice">ppdFindMarkedChoice()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_choice_t *
+ppdFindMarkedChoice(ppd_file_t *ppd,
+ const char *keyword);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the option</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the choice data or NULL if the choice does not exist or
+is not marked.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdFindMarkedChoice()</CODE> function returns a pointer to
+the marked choice data for the specified option.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_choice_t *choice;
+
+choice = ppdFindMarkedChoice(ppd, "PageSize");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdFindChoice"><CODE>ppdFindChoice()</CODE></A>,
+<A HREF="#ppdFindOption"><CODE>ppdFindOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdFindNextAttr">ppdFindNextAttr()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_attr_t *
+ppdFindNextAttr(ppd_file_t *ppd,
+ const char *keyword,
+ const char *spec);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>A pointer to the PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the attribute</TD>
+</TR>
+<TR>
+ <TD>spec</TD>
+ <TD>The option keyword associated with the attribute or
+ NULL if you don't care.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the attribute data or NULL if the attribute does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdFindNextAttr()</CODE> function returns a pointer to
+the next occurrence of the attribute in the PPD file.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_attr_t *attr;
+
+for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+ attr != NULL;
+ attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
+{
+ printf("*%s %s/%s: \"%s\"\n",
+ attr->name, attr->spec, attr->text,
+ attr->value ? attr->value : "(none)");
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdFindAttr"><CODE>ppdFindAttr()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdFindOption">ppdFindOption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_option_t *
+ppdFindOption(ppd_file_t *ppd,
+ const char *keyword);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the option</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the option data or NULL if the option does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdFindOption()</CODE> function returns a pointer to the option
+data for the specified option.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_option_t *option;
+
+option = ppdFindOption(ppd, "PageSize");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdFindChoice"><CODE>ppdFindChoice()</CODE></A>,
+<A HREF="#ppdFindMarkedChoice"><CODE>ppdFindMarkedChoice()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdIsMarked">ppdIsMarked()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdIsMarked(ppd_file_t *ppd,
+ const char *keyword,
+ const char *choice);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the option</TD>
+</TR>
+<TR>
+ <TD>choice</TD>
+ <TD>The name of the option choice</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>1 if the choice is marked, 0 otherwise.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdIsMarked()</CODE> function returns whether or not the
+specified option choice is marked.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Letter size %s selected.\n",
+ ppdIsMarked(ppd, "PageSize", "Letter") ? "is" : "is not");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#ppdConflicts"><CODE>ppdConflicts()</CODE></A>,
+<A HREF="#ppdIsMarked"><CODE>ppdIsMarked()</CODE></A>,
+<A HREF="#ppdMarkDefaults"><CODE>ppdMarkDefaults()</CODE></A>,
+<A HREF="#ppdMarkOption"><CODE>ppdMarkOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdMarkDefaults">ppdMarkDefaults()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+void
+ppdMarkDefaults(ppd_file_t *ppd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdMarkDefaults()</CODE> function marks all of the default
+choices in the PPD file.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkDefaults(ppd);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#ppdConflicts"><CODE>ppdConflicts()</CODE></A>,
+<A HREF="#ppdIsMarked"><CODE>ppdIsMarked()</CODE></A>,
+<A HREF="#ppdMarkDefaults"><CODE>ppdMarkDefaults()</CODE></A>,
+<A HREF="#ppdMarkOption"><CODE>ppdMarkOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdMarkOption">ppdMarkOption()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+int
+ppdMarkOption(ppd_file_t *ppd,
+ const char *keyword,
+ const char *choice);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>keyword</TD>
+ <TD>The name of the option</TD>
+</TR>
+<TR>
+ <TD>choice</TD>
+ <TD>The name of the choice</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The number of conflicts in the PPD file.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdMarkOption()</CODE> function marks the specified option
+choice.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppdMarkOption(ppd, "PageSize", "Letter");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#cupsMarkOptions"><CODE>cupsMarkOptions()</CODE></A>,
+<A HREF="#ppdConflicts"><CODE>ppdConflicts()</CODE></A>,
+<A HREF="#ppdIsMarked"><CODE>ppdIsMarked()</CODE></A>,
+<A HREF="#ppdMarkDefaults"><CODE>ppdMarkDefaults()</CODE></A>,
+<A HREF="#ppdMarkOption"><CODE>ppdMarkOption()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdOpen">ppdOpen()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_file_t *
+ppdOpen(FILE *file);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>file</TD>
+ <TD>The file to read from</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a PPD file structure or NULL if the PPD file could not be
+read.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdOpen()</CODE> function reads a PPD file from the specified
+file into memory.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+FILE *file;
+
+file = fopen("filename.ppd", "rb");
+ppd = ppdOpen(file);
+fclose(file);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>,
+<A HREF="#ppdOpenFd"><CODE>ppdOpenFd()</CODE></A>,
+<A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdOpenFd">ppdOpenFd()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_file_t *
+ppdOpenFd(int fd);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>fd</TD>
+ <TD>The file descriptor to read from</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a PPD file structure or NULL if the PPD file could not be
+read.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdOpenFd()</CODE> function reads a PPD file from the specified
+file descriptor into memory.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+int fd;
+
+fd = open("filename.ppd", O_RDONLY);
+ppd = ppdOpenFd(fd);
+close(fd);
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>,
+<A HREF="#ppdOpen"><CODE>ppdOpen()</CODE></A>,
+<A HREF="#ppdOpenFile"><CODE>ppdOpenFile()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdOpenFile">ppdOpenFile()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_file_t *
+ppdOpenFile(const char *filename);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>filename</TD>
+ <TD>The name of the file to read from</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to a PPD file structure or NULL if the PPD file could not be
+read.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdOpenFile()</CODE> function reads a PPD file from the named
+file into memory.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+ppd = ppdOpenFile("filename.ppd");
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdClose"><CODE>ppdClose()</CODE></A>,
+<A HREF="#ppdOpen"><CODE>ppdOpen()</CODE></A>,
+<A HREF="#ppdOpenFd"><CODE>ppdOpenFd()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdPageLength">ppdPageLength()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+float
+ppdPageLength(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the page size</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The length of the specified page size in points or 0 if the page size
+does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdPageLength()</CODE> function returns the page length of the
+specified page size.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Length = %.0f\n", ppdPageLength(ppd, "Letter"));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>,
+<A HREF="#ppdPageSize"><CODE>ppdPageSize()</CODE></A>,
+<A HREF="#ppdPageWidth"><CODE>ppdPageWidth()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdPageSize">ppdPageSize()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+ppd_size_t *
+ppdPageSize(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the page size</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>A pointer to the page size record of the specified page size in
+points or NULL if the page size does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdPageSize()</CODE> function returns the page size record for the
+specified page size.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+ppd_size_t *size;
+
+size = ppdPageSize(ppd, "Letter");
+if (size != NULL)
+{
+ printf(" Width = %.0f\n", size->width);
+ printf("Length = %.0f\n", size->length);
+ printf(" Left = %.0f\n", size->left);
+ printf(" Right = %.0f\n", size->right);
+ printf("Bottom = %.0f\n", size->bottom);
+ printf(" Top = %.0f\n", size->top);
+}
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>,
+<A HREF="#ppdPageWidth"><CODE>ppdPageWidth()</CODE></A>
+
+
+<!-- NEW PAGE --><H2><A NAME="ppdPageWidth">ppdPageWidth()</A></H2>
+
+<H3>Usage</H3>
+
+<PRE>
+float
+ppdPageWidth(ppd_file_t *ppd,
+ const char *name);
+</PRE>
+
+<H3>Arguments</H3>
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<TR>
+ <TH>Argument</TH>
+ <TH>Description</TH>
+</TR>
+<TR>
+ <TD>ppd</TD>
+ <TD>The PPD file</TD>
+</TR>
+<TR>
+ <TD>name</TD>
+ <TD>The name of the page size</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Returns</H3>
+
+<P>The width of the specified page size in points or 0 if the page size
+does not exist.
+
+<H3>Description</H3>
+
+<P>The <CODE>ppdPageWidth()</CODE> function returns the page width of the
+specified page size.
+
+<H3>Example</H3>
+
+<PRE>
+#include &lt;cups/ppd.h>
+
+ppd_file_t *ppd;
+
+printf("Width = %.0f\n", ppdPageWidth(ppd, "Letter"));
+</PRE>
+
+<H3>See Also</H3>
+
+<A HREF="#ppdPageLength"><CODE>ppdPageLength()</CODE></A>,
+<A HREF="#ppdPageSize"><CODE>ppdPageSize()</CODE></A>
+
+
+</BODY>
+</HTML>
diff --git a/doc/sps.html b/doc/sps.html
new file mode 100644
index 000000000..774f8e635
--- /dev/null
+++ b/doc/sps.html
@@ -0,0 +1,312 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Performance Specification</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SPS-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Performance Specification</H1></A><BR>
+CUPS-SPS-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Programs</A></B>
+<BR>
+<BR><B><A HREF="#4">4 Scheduler Objects</A></B>
+<BR>
+<BR><B><A HREF="#5">A Glossary</A></B>
+<UL>
+<LI><A HREF="#5_1">A.1 Terms</A></LI>
+<LI><A HREF="#5_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This software performance specification provides an analysis of the
+ memory, disk, and processor utilitization of each program in the Common
+ UNIX Printing System (&quot;CUPS&quot;) Version 1.1.</P>
+<P>For the purposes of comparison, all figures are for the Linux Intel
+ platform. Memory utilization on other platforms should be similar.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This software performance specification is organized into the
+ following sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Programs</LI>
+<LI>4 - Scheduler Objects</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Programs</A></H1>
+<P>The following table describes the average memory, disk, and CPU usage
+ of each program in CUPS.</P>
+<P>The base memory column shows the initial memory requirements for each
+ program, including any shared libraries that are provided by CUPS.</P>
+<P>The max memory column shows the maximum amount of memory that will be
+ used by the program based upon the default configuration settings
+ supplied with CUPS.</P>
+<P>The temp files column indicates whether any temporary files are
+ created.</P>
+<P>The CPU usage column specifies a relative CPU usage by the program
+ under normal conditions, either low, medium, or high. Low usage
+ indicates that the program will never use more than 33% of the
+ available CPU time. Medium usage indicates the program will use as much
+ as 66% of the available CPU time. High usage indicates the program uses
+ 66% or more of the available CPU time.
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR><TH COLSPAN="3">Backends</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>ipp</TD><TD>91k</TD><TD>256k</TD><TD>Up to size of print file</TD><TD>
+Low</TD></TR>
+<TR><TD>lpd</TD><TD>89k</TD><TD>89k</TD><TD>Up to size of print file</TD><TD>
+Low</TD></TR>
+<TR><TD>parallel</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print
+ file</TD><TD>Low</TD></TR>
+<TR><TD>serial</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
+Low</TD></TR>
+<TR><TD>socket</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
+Low</TD></TR>
+<TR><TD>usb</TD><TD>85k</TD><TD>85k</TD><TD>Up to size of print file</TD><TD>
+Low</TD></TR>
+<TR><TH COLSPAN="3">CGIs</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>admin.cgi</TD><TD>107k</TD><TD>256k</TD><TD>Up to size of PPD
+ file</TD><TD>Medium</TD></TR>
+<TR><TD>classes.cgi</TD><TD>95k</TD><TD>Size of class objects</TD><TD>
+None</TD><TD>Medium</TD></TR>
+<TR><TD>jobs.cgi</TD><TD>93k</TD><TD>Size of job objects</TD><TD>None</TD><TD>
+Medium</TD></TR>
+<TR><TD>printers.cgi</TD><TD>95k</TD><TD>Size of printer objects</TD><TD>
+None</TD><TD>Medium</TD></TR>
+<TR><TH COLSPAN="3">Command-Line Programs</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>accept</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>cancel</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>disable</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>enable</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lp</TD><TD>90k</TD><TD>256k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lpadmin</TD><TD>148k</TD><TD>256k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lpc</TD><TD>86k</TD><TD>Size of job and printer objects</TD><TD>
+None</TD><TD>Medium</TD></TR>
+<TR><TD>lpinfo</TD><TD>89k</TD><TD>Size of device and PPD objects</TD><TD>
+None</TD><TD>Medium</TD></TR>
+<TR><TD>lpmove</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lpoptions</TD><TD>89k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lppasswd</TD><TD>90k</TD><TD>90k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lpq</TD><TD>87k</TD><TD>Size of job objects</TD><TD>None</TD><TD>
+Medium</TD></TR>
+<TR><TD>lpr</TD><TD>87k</TD><TD>256k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lprm</TD><TD>84k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>lpstat</TD><TD>119k</TD><TD>Size of job, printer, and class
+ objects</TD><TD>None</TD><TD>Medium</TD></TR>
+<TR><TD>reject</TD><TD>88k</TD><TD>128k</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TH COLSPAN="3">Daemons</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>cups-lpd</TD><TD>92k</TD><TD>256k</TD><TD>One file per control
+ or data file from client</TD><TD>Low</TD></TR>
+<TR><TD>cupsd</TD><TD>308k</TD><TD>See Scheduler Requirements</TD><TD>
+See Scheduler Requirements</TD><TD>Medium</TD></TR>
+<TR><TD>cups-polld</TD><TD>84k</TD><TD>Size of printer and class objects</TD><TD>
+None</TD><TD>Low</TD></TR>
+<TR><TH COLSPAN="3">Filters</TH></TR>
+<TR><TH>Program</TH><TH>Base Memory</TH><TH>Max Memory</TH><TH>Temp
+ Files</TH><TH>CPU Usage</TH></TR>
+<TR><TD>hpgltops</TD><TD>263k</TD><TD>320k</TD><TD>None</TD><TD>Medium</TD>
+</TR>
+<TR><TD>imagetops</TD><TD>628k</TD><TD>10M</TD><TD>Swap file for
+ uncompressed image data</TD><TD>Medium</TD></TR>
+<TR><TD>imagetoraster</TD><TD>652k</TD><TD>10M</TD><TD>Swap file for
+ uncompressed image data</TD><TD>High</TD></TR>
+<TR><TD>pstops</TD><TD>775k</TD><TD>840k</TD><TD>Up to size of print
+ file</TD><TD>Medium</TD></TR>
+<TR><TD>pstoraster</TD><TD>4M</TD><TD>14M</TD><TD>Swap file for command
+ lists</TD><TD>High</TD></TR>
+<TR><TD>rastertoepson</TD><TD>693k</TD><TD>1M</TD><TD>None</TD><TD>Low</TD>
+</TR>
+<TR><TD>rastertohp</TD><TD>690k</TD><TD>1M</TD><TD>None</TD><TD>Low</TD></TR>
+<TR><TD>texttops</TD><TD>638k</TD><TD>4*cols*rows</TD><TD>None</TD><TD>
+Low</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1><A NAME="4">4 Scheduler Objects</A></H1>
+<P>The <CODE>cupsd</CODE> program is the CUPS scheduler process. It
+ manages many interdependent server objects that are used to manage and
+ print files to printers.</P>
+<P>The following table provides the memory and disk cost associated with
+ each server object.
+<CENTER>
+<TABLE BORDER="1" WIDTH="80%">
+<TR><TH>Object</TH><TH>Memory Per</TH><TH>Disk Per</TH></TR>
+<TR><TD>Browse ACL</TD><TD>1k</TD><TD>120</TD></TR>
+<TR><TD>Browse Poll</TD><TD>24</TD><TD>80</TD></TR>
+<TR><TD>Browse Relay</TD><TD>28</TD><TD>80</TD></TR>
+<TR><TD>Certificate</TD><TD>76</TD><TD>32</TD></TR>
+<TR><TD>Class</TD><TD>9k</TD><TD>200</TD></TR>
+<TR><TD>Client</TD><TD>13k</TD><TD>-</TD></TR>
+<TR><TD>Device</TD><TD>256</TD><TD>-</TD></TR>
+<TR><TD>Job</TD><TD>2k</TD><TD>1k + size of document files</TD></TR>
+<TR><TD>Location ACL</TD><TD>1k</TD><TD>120</TD></TR>
+<TR><TD>MIME Filter</TD><TD>268</TD><TD>80</TD></TR>
+<TR><TD>MIME Type</TD><TD>340</TD><TD>80</TD></TR>
+<TR><TD>PPD</TD><TD>200</TD><TD>656</TD></TR>
+<TR><TD>Printer</TD><TD>11k</TD><TD>32k</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
+<H2><A NAME="5_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="5_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/sps.pdf b/doc/sps.pdf
new file mode 100644
index 000000000..409d54d33
--- /dev/null
+++ b/doc/sps.pdf
Binary files differ
diff --git a/doc/sps.shtml b/doc/sps.shtml
new file mode 100644
index 000000000..6a7db3467
--- /dev/null
+++ b/doc/sps.shtml
@@ -0,0 +1,457 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SPS-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Performance Specification</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This software performance specification provides an analysis of the
+memory, disk, and processor utilitization of each program in the
+Common UNIX Printing System ("CUPS") Version 1.1.</P>
+
+<P>For the purposes of comparison, all figures are for the Linux Intel
+platform. Memory utilization on other platforms should be similar.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This software performance specification is organized into the
+following sections:</P>
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - Programs</LI>
+ <LI>4 - Scheduler Objects</LI>
+ <LI>A - Glossary</LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Programs</H1>
+
+<P>The following table describes the average memory, disk, and CPU usage of
+each program in CUPS.
+
+<P>The base memory column shows the initial memory requirements for each
+program, including any shared libraries that are provided by CUPS.
+
+<P>The max memory column shows the maximum amount of memory that will be
+used by the program based upon the default configuration settings supplied
+with CUPS.
+
+<P>The temp files column indicates whether any temporary files are created.
+
+<P>The CPU usage column specifies a relative CPU usage by the program under
+normal conditions, either low, medium, or high. Low usage indicates that
+the program will never use more than 33% of the available CPU time. Medium
+usage indicates the program will use as much as 66% of the available CPU
+time. High usage indicates the program uses 66% or more of the available CPU
+time.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1">
+<TR>
+ <TH COLSPAN="3">Backends</TH>
+</TR>
+<TR>
+ <TH>Program</TH>
+ <TH>Base Memory</TH>
+ <TH>Max Memory</TH>
+ <TH>Temp Files</TH>
+ <TH>CPU Usage</TH>
+</TR>
+<TR>
+ <TD>ipp</TD>
+ <TD>91k</TD>
+ <TD>256k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpd</TD>
+ <TD>89k</TD>
+ <TD>89k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>parallel</TD>
+ <TD>85k</TD>
+ <TD>85k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>serial</TD>
+ <TD>85k</TD>
+ <TD>85k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>socket</TD>
+ <TD>85k</TD>
+ <TD>85k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>usb</TD>
+ <TD>85k</TD>
+ <TD>85k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TH COLSPAN="3">CGIs</TH>
+</TR>
+<TR>
+ <TH>Program</TH>
+ <TH>Base Memory</TH>
+ <TH>Max Memory</TH>
+ <TH>Temp Files</TH>
+ <TH>CPU Usage</TH>
+</TR>
+<TR>
+ <TD>admin.cgi</TD>
+ <TD>107k</TD>
+ <TD>256k</TD>
+ <TD>Up to size of PPD file</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>classes.cgi</TD>
+ <TD>95k</TD>
+ <TD>Size of class objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>jobs.cgi</TD>
+ <TD>93k</TD>
+ <TD>Size of job objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>printers.cgi</TD>
+ <TD>95k</TD>
+ <TD>Size of printer objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TH COLSPAN="3">Command-Line Programs</TH>
+</TR>
+<TR>
+ <TH>Program</TH>
+ <TH>Base Memory</TH>
+ <TH>Max Memory</TH>
+ <TH>Temp Files</TH>
+ <TH>CPU Usage</TH>
+</TR>
+<TR>
+ <TD>accept</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>cancel</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>disable</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>enable</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lp</TD>
+ <TD>90k</TD>
+ <TD>256k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpadmin</TD>
+ <TD>148k</TD>
+ <TD>256k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpc</TD>
+ <TD>86k</TD>
+ <TD>Size of job and printer objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>lpinfo</TD>
+ <TD>89k</TD>
+ <TD>Size of device and PPD objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>lpmove</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpoptions</TD>
+ <TD>89k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lppasswd</TD>
+ <TD>90k</TD>
+ <TD>90k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpq</TD>
+ <TD>87k</TD>
+ <TD>Size of job objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>lpr</TD>
+ <TD>87k</TD>
+ <TD>256k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lprm</TD>
+ <TD>84k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>lpstat</TD>
+ <TD>119k</TD>
+ <TD>Size of job, printer, and class objects</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>reject</TD>
+ <TD>88k</TD>
+ <TD>128k</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TH COLSPAN="3">Daemons</TH>
+</TR>
+<TR>
+ <TH>Program</TH>
+ <TH>Base Memory</TH>
+ <TH>Max Memory</TH>
+ <TH>Temp Files</TH>
+ <TH>CPU Usage</TH>
+</TR>
+<TR>
+ <TD>cups-lpd</TD>
+ <TD>92k</TD>
+ <TD>256k</TD>
+ <TD>One file per control or data file from client</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>cupsd</TD>
+ <TD>308k</TD>
+ <TD>See Scheduler Requirements</TD>
+ <TD>See Scheduler Requirements</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>cups-polld</TD>
+ <TD>84k</TD>
+ <TD>Size of printer and class objects</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TH COLSPAN="3">Filters</TH>
+</TR>
+<TR>
+ <TH>Program</TH>
+ <TH>Base Memory</TH>
+ <TH>Max Memory</TH>
+ <TH>Temp Files</TH>
+ <TH>CPU Usage</TH>
+</TR>
+<TR>
+ <TD>hpgltops</TD>
+ <TD>263k</TD>
+ <TD>320k</TD>
+ <TD>None</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>imagetops</TD>
+ <TD>628k</TD>
+ <TD>10M</TD>
+ <TD>Swap file for uncompressed image data</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>imagetoraster</TD>
+ <TD>652k</TD>
+ <TD>10M</TD>
+ <TD>Swap file for uncompressed image data</TD>
+ <TD>High</TD>
+</TR>
+<TR>
+ <TD>pstops</TD>
+ <TD>775k</TD>
+ <TD>840k</TD>
+ <TD>Up to size of print file</TD>
+ <TD>Medium</TD>
+</TR>
+<TR>
+ <TD>pstoraster</TD>
+ <TD>4M</TD>
+ <TD>14M</TD>
+ <TD>Swap file for command lists</TD>
+ <TD>High</TD>
+</TR>
+<TR>
+ <TD>rastertoepson</TD>
+ <TD>693k</TD>
+ <TD>1M</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>rastertohp</TD>
+ <TD>690k</TD>
+ <TD>1M</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+<TR>
+ <TD>texttops</TD>
+ <TD>638k</TD>
+ <TD>4*cols*rows</TD>
+ <TD>None</TD>
+ <TD>Low</TD>
+</TR>
+</TABLE></CENTER>
+
+
+<H1>Scheduler Objects</H1>
+
+<P>The <CODE>cupsd</CODE> program is the CUPS scheduler process. It manages
+many interdependent server objects that are used to manage and print files
+to printers.
+
+<P>The following table provides the memory and disk cost associated with each
+server object.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1">
+<TR>
+ <TH>Object</TH>
+ <TH>Memory Per</TH>
+ <TH>Disk Per</TH>
+</TR>
+<TR>
+ <TD>Browse ACL</TD>
+ <TD>1k</TD>
+ <TD>120</TD>
+</TR>
+<TR>
+ <TD>Browse Poll</TD>
+ <TD>24</TD>
+ <TD>80</TD>
+</TR>
+<TR>
+ <TD>Browse Relay</TD>
+ <TD>28</TD>
+ <TD>80</TD>
+</TR>
+<TR>
+ <TD>Certificate</TD>
+ <TD>76</TD>
+ <TD>32</TD>
+</TR>
+<TR>
+ <TD>Class</TD>
+ <TD>9k</TD>
+ <TD>200</TD>
+</TR>
+<TR>
+ <TD>Client</TD>
+ <TD>13k</TD>
+ <TD>-</TD>
+</TR>
+<TR>
+ <TD>Device</TD>
+ <TD>256</TD>
+ <TD>-</TD>
+</TR>
+<TR>
+ <TD>Job</TD>
+ <TD>2k</TD>
+ <TD>1k + size of document files</TD>
+</TR>
+<TR>
+ <TD>Location ACL</TD>
+ <TD>1k</TD>
+ <TD>120</TD>
+</TR>
+<TR>
+ <TD>MIME Filter</TD>
+ <TD>268</TD>
+ <TD>80</TD>
+</TR>
+<TR>
+ <TD>MIME Type</TD>
+ <TD>340</TD>
+ <TD>80</TD>
+</TR>
+<TR>
+ <TD>PPD</TD>
+ <TD>200</TD>
+ <TD>656</TD>
+</TR>
+<TR>
+ <TD>Printer</TD>
+ <TD>11k</TD>
+ <TD>32k</TD>
+</TR>
+</TABLE></CENTER>
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/ssr.html b/doc/ssr.html
new file mode 100644
index 000000000..334e3215d
--- /dev/null
+++ b/doc/ssr.html
@@ -0,0 +1,289 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Security Report</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SSR-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Security Report</H1></A><BR>
+CUPS-SSR-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Local Access Risks</A></B>
+<UL>
+<LI><A HREF="#3_1">3.1 Security Breaches</A></LI>
+</UL>
+<B><A HREF="#4">4 Remote Access Risks</A></B>
+<UL>
+<LI><A HREF="#4_1">4.1 Denial of Service Attacks</A></LI>
+<LI><A HREF="#4_2">4.2 Security Breaches</A></LI>
+</UL>
+<B><A HREF="#5">A Glossary</A></B>
+<UL>
+<LI><A HREF="#5_1">A.1 Terms</A></LI>
+<LI><A HREF="#5_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This software security report provides an analysis of possible
+ security concerns for the Common UNIX Printing System (&quot;CUPS&quot;) Version
+ 1.1.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This software security report is organized into the following
+ sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Local Access Risks</LI>
+<LI>4 - Remote Access Risks</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Local Access Risks</A></H1>
+<P>Local access risks are those that can be exploited only with a local
+ user account. This section does not address issues related to
+ dissemination of the root password or other security issues associated
+ with the UNIX operating system.</P>
+<H2><A NAME="3_1">3.1 Security Breaches</A></H2>
+<P>There is one known security vulnerability with local access:</P>
+<OL>
+<LI>Device URIs are passed to backend filters in argv[0] and in an
+ environment variable. Since device URIs can contain usernames and
+ passwords it may be possible for a local user to gain access to a
+ remote resource.
+<P>We recommend that any password-protected accounts used for remote
+ printing have limited access priviledges so that the possible damages
+ can be minimized.</P>
+<P>The device URI is &quot;sanitized&quot; (the username and password are removed)
+ when sent to an IPP client so that a remote user cannot exploit this
+ vulnerability.</P>
+</LI>
+</OL>
+<H1><A NAME="4">4 Remote Access Risks</A></H1>
+<P>Remote access risks are those that can be exploited without a local
+ user account and/or from a remote system. This section does not address
+ issues related to network or firewall security.</P>
+<H2><A NAME="4_1">4.1 Denial of Service Attacks</A></H2>
+<P>Like all Internet services, the CUPS server is vulnerable to denial
+ of service attacks, including:</P>
+<OL>
+<LI>Establishing multiple connections to the server until the server
+ will accept no more.
+<P>Starting with CUPS 1.1.18, the <CODE>MaxClientsPerHost</CODE>
+ provides limited protection against DoS attacks, however it is not
+ effective against large-scale distributed attacks.</P>
+</LI>
+<LI>Repeatedly opening and closing connections to the server as fast as
+ possible.
+<P>There is no easy way of protecting against this in the CUPS software.
+ If the attack is coming from outside the local network it might be
+ possible to filter such an attack, however once the connection request
+ has been received by the server it must at least accept the connection
+ to find out who is connecting.</P>
+</LI>
+<LI>Flooding the network with broadcast packets on port 631.
+<P>It might be possible to disable browsing if this condition is
+ detected by the CUPS software, however if there are large numbers of
+ printers available on the network such an algorithm might think that an
+ attack was occurring when instead a valid update was being received.</P>
+</LI>
+<LI>Sending partial IPP requests; specifically, sending part of an
+ attribute value and then stopping transmission.
+<P>The current code is structured to read and write the IPP request data
+ on-the-fly, so there is no easy way to protect against this for large
+ attribute values.</P>
+</LI>
+<LI>Sending large/long print jobs to printers, preventing other users
+ from printing.
+<P>There are limited facilities for protecting against large print jobs
+ (the <CODE>MaxRequestSize</CODE> attribute), however this will not
+ protect printers from malicious users and print files that generate
+ hundreds or thousands of pages. In general, we recommend restricting
+ printer access to known hosts or networks, and adding user-level access
+ control as needed for expensive printers.</P>
+</LI>
+</OL>
+<H2><A NAME="4_2">4.2 Security Breaches</A></H2>
+<P>The current CUPS server supports Basic, Digest, and local certificate
+ authentication:</P>
+<OL>
+<LI>Basic authentication essentially places the clear text of the
+ username and password on the network. Since CUPS uses the UNIX username
+ and password account information, the authentication information could
+ be used to gain access to accounts (possibly priviledged accounts) on
+ the server.</LI>
+<LI>Digest authentication uses an MD5 checksum of the username,
+ password, and domain (&quot;CUPS&quot;), so the original username and password is
+ not sent over the network. However, the current implementation does not
+ authenticate the entire message and uses the client's IP address for
+ the nonce value, making it possible to launch &quot;man in the middle&quot; and
+ replay attacks from the same client. The next minor release of CUPS
+ will support Digest authentication of the entire message body,
+ effectively stopping these methods of attack.</LI>
+<LI>Local certificate authentication passes 128-bit &quot;certificates&quot; that
+ identify an authenticated user. Certificates are created on-the-fly
+ from random data and stored in files under <CODE>/etc/cups/certs</CODE>
+. They have restricted read permissions: root + system for the root
+ certificate, and lp + system for CGI certificates. Because certificates
+ are only available on the local system, the CUPS server does not accept
+ local authentication unless the client is connected to the localhost
+ address (127.0.0.1.)</LI>
+</OL>
+<P>The default CUPS configuration disables remote administration. We do
+ not recommend that remote administration be enabled for all hosts.
+ However, if you have a trusted network or subnet, access can be
+ restricted accordingly. Also, we highly recommend using Digest
+ authentication when possible. Unfortunately, most web browsers do not
+ support Digest authentication at this time.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
+<H2><A NAME="5_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="5_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/ssr.pdf b/doc/ssr.pdf
new file mode 100644
index 000000000..acf58fefc
--- /dev/null
+++ b/doc/ssr.pdf
Binary files differ
diff --git a/doc/ssr.shtml b/doc/ssr.shtml
new file mode 100644
index 000000000..b371dac7b
--- /dev/null
+++ b/doc/ssr.shtml
@@ -0,0 +1,165 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SSR-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Security Report</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This software security report provides an analysis of possible security
+concerns for the Common UNIX Printing System ("CUPS") Version 1.1.</P>
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This software security report is organized into the following sections:</P>
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - Local Access Risks</LI>
+ <LI>4 - Remote Access Risks</LI>
+ <LI>A - Glossary</LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Local Access Risks</H1>
+
+<P>Local access risks are those that can be exploited only with a local user
+account. This section does not address issues related to dissemination of the
+root password or other security issues associated with the UNIX operating
+system.
+
+<H2>Security Breaches</H2>
+
+<P>There is one known security vulnerability with local access:
+
+<OL>
+
+ <LI>Device URIs are passed to backend filters in argv[0] and in
+ an environment variable. Since device URIs can contain
+ usernames and passwords it may be possible for a local user to
+ gain access to a remote resource.
+
+ <P>We recommend that any password-protected accounts used for
+ remote printing have limited access priviledges so that the
+ possible damages can be minimized.
+
+ <P>The device URI is "sanitized" (the username and password are
+ removed) when sent to an IPP client so that a remote user
+ cannot exploit this vulnerability.
+
+</OL>
+
+<H1>Remote Access Risks</H1>
+
+<P>Remote access risks are those that can be exploited without a local user
+account and/or from a remote system. This section does not address issues
+related to network or firewall security.
+
+<H2>Denial of Service Attacks</H2>
+
+<P>Like all Internet services, the CUPS server is vulnerable to denial of
+service attacks, including:
+
+<OL>
+
+ <LI>Establishing multiple connections to the server until the server
+ will accept no more.
+
+ <P>Starting with CUPS 1.1.18, the <CODE>MaxClientsPerHost</CODE>
+ provides limited protection against DoS attacks, however it is
+ not effective against large-scale distributed attacks.
+
+ <LI>Repeatedly opening and closing connections to the server as fast
+ as possible.
+
+ <P>There is no easy way of protecting against this in the CUPS
+ software. If the attack is coming from outside the local
+ network it might be possible to filter such an attack, however
+ once the connection request has been received by the server it
+ must at least accept the connection to find out who is
+ connecting.
+
+ <LI>Flooding the network with broadcast packets on port 631.
+
+ <P>It might be possible to disable browsing if this condition
+ is detected by the CUPS software, however if there are large
+ numbers of printers available on the network such an algorithm
+ might think that an attack was occurring when instead a valid
+ update was being received.
+
+ <LI>Sending partial IPP requests; specifically, sending part of an
+ attribute value and then stopping transmission.
+
+ <P>The current code is structured to read and write the IPP
+ request data on-the-fly, so there is no easy way to protect
+ against this for large attribute values.
+
+ <LI>Sending large/long print jobs to printers, preventing other users
+ from printing.
+
+ <P>There are limited facilities for protecting against large print
+ jobs (the <CODE>MaxRequestSize</CODE> attribute), however this will
+ not protect printers from malicious users and print files that
+ generate hundreds or thousands of pages. In general, we recommend
+ restricting printer access to known hosts or networks, and adding
+ user-level access control as needed for expensive printers.
+
+</OL>
+
+<H2>Security Breaches</H2>
+
+<P>The current CUPS server supports Basic, Digest, and local certificate
+authentication:
+
+<OL>
+
+ <LI>Basic authentication essentially places the clear text of
+ the username and password on the network. Since CUPS uses the
+ UNIX username and password account information, the
+ authentication information could be used to gain access to
+ accounts (possibly priviledged accounts) on the server.
+
+ <LI>Digest authentication uses an MD5 checksum of the username,
+ password, and domain ("CUPS"), so the original username and
+ password is not sent over the network. However, the current
+ implementation does not authenticate the entire message and
+ uses the client's IP address for the nonce value, making it
+ possible to launch "man in the middle" and replay attacks from
+ the same client. The next minor release of CUPS will support
+ Digest authentication of the entire message body, effectively
+ stopping these methods of attack.
+
+ <LI>Local certificate authentication passes 128-bit
+ "certificates" that identify an authenticated user.
+ Certificates are created on-the-fly from random data and stored
+ in files under <CODE>/etc/cups/certs</CODE>. They have
+ restricted read permissions: root + system for the root
+ certificate, and lp + system for CGI certificates. Because
+ certificates are only available on the local system, the CUPS
+ server does not accept local authentication unless the client
+ is connected to the localhost address (127.0.0.1.)
+
+</OL>
+
+<P>The default CUPS configuration disables remote administration. We do
+not recommend that remote administration be enabled for all hosts.
+However, if you have a trusted network or subnet, access can be
+restricted accordingly.
+
+Also, we highly recommend using Digest authentication when possible.
+Unfortunately, most web browsers do not support Digest authentication
+at this time.
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/stp.html b/doc/stp.html
new file mode 100644
index 000000000..eb41656ec
--- /dev/null
+++ b/doc/stp.html
@@ -0,0 +1,277 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Test Plan</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-STP-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Test Plan</H1></A><BR>
+CUPS-STP-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Test Procedure</A></B>
+<BR>
+<BR><B><A HREF="#4">4 IPP Compliance Tests</A></B>
+<UL>
+<LI><A HREF="#4_1">4.1 Request Tests</A></LI>
+<LI><A HREF="#4_2">4.2 CUPS Printer Operation Tests</A></LI>
+<LI><A HREF="#4_3">4.3 Job Operation Tests</A></LI>
+</UL>
+<B><A HREF="#5">5 Command Tests</A></B>
+<UL>
+<LI><A HREF="#5_1">5.1 lpadmin</A></LI>
+<LI><A HREF="#5_2">5.2 lpc</A></LI>
+<LI><A HREF="#5_3">5.3 lpq</A></LI>
+<LI><A HREF="#5_4">5.4 lpstat</A></LI>
+<LI><A HREF="#5_5">5.5 lp</A></LI>
+<LI><A HREF="#5_6">5.6 lpr</A></LI>
+<LI><A HREF="#5_7">5.7 lprm</A></LI>
+<LI><A HREF="#5_8">5.8 cancel</A></LI>
+<LI><A HREF="#5_9">5.9 lpinfo</A></LI>
+</UL>
+<B><A HREF="#6">A Glossary</A></B>
+<UL>
+<LI><A HREF="#6_1">A.1 Terms</A></LI>
+<LI><A HREF="#6_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This software test plan provides detailed tests that are used to
+ evaluate the stability and compliance of the Common UNIX Printing
+ System (&quot;CUPS&quot;) Version 1.1.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This software test plan is organized into the following sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Test Procedure</LI>
+<LI>4 - IPP Compliance Tests</LI>
+<LI>5 - Command Tests</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Test Procedure</A></H1>
+<P>The test software and data files are located in the<VAR> test</VAR>
+ subdirectory of the source distribution. A script is provided to
+ compile the <CODE>ipptest</CODE> program and run all of the tests that
+ follow, producing a success/fail report.</P>
+<P>The <CODE>test</CODE> target of the top-level makefile can be used to
+ run this script:</P>
+<UL>
+<PRE>
+make test
+</PRE>
+</UL>
+<P>or you can run the test script directly:</P>
+<UL>
+<PRE>
+cd test
+./run-stp-tests
+</PRE>
+</UL>
+<P>A Software Test Report is stored in HTML and PDF files that are
+ generated using the <A HREF="http://www.easysw.com/htmldoc">HTMLDOC</A>
+ software.</P>
+<H1><A NAME="4">4 IPP Compliance Tests</A></H1>
+<P>This section describes the tests used to validate the IPP standards
+ compliance of the CUPS server.</P>
+<H2><A NAME="4_1">4.1 Request Tests</A></H2>
+<P>These tests verify that the CUPS scheduler only accepts valid IPP
+ requests that start with the <CODE>attributes-charset</CODE> and <CODE>
+attributes-natural-language</CODE> attributes and also contain a <CODE>
+printer-uri</CODE> or <CODE>job-uri</CODE> attribute.</P>
+<P>It also verifies that the CUPS scheduler always responds with <CODE>
+attributes-charset</CODE> and <CODE>attributes-natural-language</CODE>
+ attributes, using default values if they are not provided by the
+ client.</P>
+<H2><A NAME="4_2">4.2 CUPS Printer Operation Tests</A></H2>
+<P>These tests verify that the CUPS printer operations are supported and
+ function properly. Two printers called <CODE>Test1</CODE> and <CODE>
+Test2</CODE> are created, one as a PostScript printer and one as a
+ raster printer.</P>
+<H2><A NAME="4_3">4.3 Job Operation Tests</A></H2>
+<P>These test verify that the CUPS scheduler accepts print jobs for all
+ supported file formats and that the <CODE>cancel-job</CODE>, <CODE>
+hold-job</CODE>, and <CODE>resume-job</CODE> operations work.</P>
+<H1><A NAME="5">5 Command Tests</A></H1>
+<P>This section describes the tests used to validate the Berkeley and
+ System V commands included with CUPS.</P>
+<H2><A NAME="5_1">5.1 lpadmin</A></H2>
+<P>This test verifies that printers can be added, modified, and
+ defaulted using the <CODE>lpadmin</CODE> command.</P>
+<H2><A NAME="5_2">5.2 lpc</A></H2>
+<P>This test verifies that the <CODE>lpc</CODE> command can show the
+ current status of all print queues.</P>
+<H2><A NAME="5_3">5.3 lpq</A></H2>
+<P>This test verifies that the <CODE>lpq</CODE> command lists any jobs
+ in the queue.</P>
+<H2><A NAME="5_4">5.4 lpstat</A></H2>
+<P>This test verifies that the <CODE>lpstat</CODE> command works with
+ all reports using the &quot;<CODE>-t</CODE>&quot; option.</P>
+<H2><A NAME="5_5">5.5 lp</A></H2>
+<P>This test verifies that the <CODE>lp</CODE> command works with both
+ the default destination and a specific destination.</P>
+<H2><A NAME="5_6">5.6 lpr</A></H2>
+<P>This test verifies that the <CODE>lpr</CODE> command works with both
+ the default destination and a specific destination.</P>
+<H2><A NAME="5_7">5.7 lprm</A></H2>
+<P>This test verifies that the <CODE>lprm</CODE> command can properly
+ cancel a job.</P>
+<H2><A NAME="5_8">5.8 cancel</A></H2>
+<P>This test verifies that the <CODE>cancel</CODE> command can properly
+ cancel a job or all jobs.</P>
+<H2><A NAME="5_9">5.9 lpinfo</A></H2>
+<P>This test verifies that the <CODE>lpinfo</CODE> command returns a
+ list of available printer drivers and devices.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
+<H2><A NAME="6_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="6_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/stp.pdf b/doc/stp.pdf
new file mode 100644
index 000000000..6d9e0cc76
--- /dev/null
+++ b/doc/stp.pdf
Binary files differ
diff --git a/doc/stp.shtml b/doc/stp.shtml
new file mode 100644
index 000000000..2eab4babc
--- /dev/null
+++ b/doc/stp.shtml
@@ -0,0 +1,144 @@
+<HTML>
+<HEAD>
+ <META NAME="Description" CONTENT="Common UNIX Printing System Software Test Plan">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-STP-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Test Plan</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This software test plan provides detailed tests that are used
+to evaluate the stability and compliance of the Common UNIX
+Printing System ("CUPS") Version 1.1.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This software test plan is organized into the following sections:
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - Test Procedure</LI>
+ <LI>4 - IPP Compliance Tests</LI>
+ <LI>5 - Command Tests</LI>
+ <LI>A - Glossary</LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Test Procedure</H1>
+
+<P>The test software and data files are located in the <VAR>test</VAR>
+subdirectory of the source distribution. A script is provided to compile
+the <CODE>ipptest</CODE> program and run all of the tests that follow,
+producing a success/fail report.
+
+<P>The <CODE>test</CODE> target of the top-level makefile can be used to
+run this script:
+
+<UL><PRE>
+make test
+</PRE></UL>
+
+<P>or you can run the test script directly:
+
+<UL><PRE>
+cd test
+./run-stp-tests
+</PRE></UL>
+
+<P>A Software Test Report is stored in HTML and PDF files that
+are generated using the
+<A HREF="http://www.easysw.com/htmldoc">HTMLDOC</A> software.
+
+<H1>IPP Compliance Tests</H1>
+
+<P>This section describes the tests used to validate the IPP
+standards compliance of the CUPS server.
+
+<H2>Request Tests</H2>
+
+<P>These tests verify that the CUPS scheduler only accepts valid
+IPP requests that start with the <CODE>attributes-charset</CODE>
+and <CODE>attributes-natural-language</CODE> attributes and also
+contain a <CODE>printer-uri</CODE> or <CODE>job-uri</CODE> attribute.
+
+<P>It also verifies that the CUPS scheduler always responds with
+<CODE>attributes-charset</CODE> and
+<CODE>attributes-natural-language</CODE> attributes, using
+default values if they are not provided by the client.
+
+<H2>CUPS Printer Operation Tests</H2>
+
+<P>These tests verify that the CUPS printer operations are supported
+and function properly. Two printers called <CODE>Test1</CODE> and
+<CODE>Test2</CODE> are created, one as a PostScript printer and one
+as a raster printer.
+
+<H2>Job Operation Tests</H2>
+
+<P>These test verify that the CUPS scheduler accepts print jobs for
+all supported file formats and that the <CODE>cancel-job</CODE>,
+<CODE>hold-job</CODE>, and <CODE>resume-job</CODE> operations work.
+
+<H1>Command Tests</H1>
+
+<P>This section describes the tests used to validate the
+Berkeley and System V commands included with CUPS.
+
+<H2>lpadmin</H2>
+
+<P>This test verifies that printers can be added, modified, and
+defaulted using the <CODE>lpadmin</CODE> command.
+
+<H2>lpc</H2>
+
+<P>This test verifies that the <CODE>lpc</CODE> command can show
+the current status of all print queues.
+
+<H2>lpq</H2>
+
+<P>This test verifies that the <CODE>lpq</CODE> command lists
+any jobs in the queue.
+
+<H2>lpstat</H2>
+
+<P>This test verifies that the <CODE>lpstat</CODE> command works
+with all reports using the "<CODE>-t</CODE>" option.
+
+<H2>lp</H2>
+
+<P>This test verifies that the <CODE>lp</CODE> command works
+with both the default destination and a specific destination.
+
+<H2>lpr</H2>
+
+<P>This test verifies that the <CODE>lpr</CODE> command works
+with both the default destination and a specific destination.
+
+<H2>lprm</H2>
+
+<P>This test verifies that the <CODE>lprm</CODE> command can
+properly cancel a job.
+
+<H2>cancel</H2>
+
+<P>This test verifies that the <CODE>cancel</CODE> command can
+properly cancel a job or all jobs.
+
+<H2>lpinfo</H2>
+
+<P>This test verifies that the <CODE>lpinfo</CODE> command
+returns a list of available printer drivers and devices.
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/sum.html b/doc/sum.html
new file mode 100644
index 000000000..1bd94bbcf
--- /dev/null
+++ b/doc/sum.html
@@ -0,0 +1,1789 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Users Manual</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.22">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511" ALT="CUPS Software Users Manual"><BR>
+<H1>CUPS Software Users Manual</H1></A><BR>
+CUPS-SUM-1.1.22<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">Preface</A>
+<UL>
+<LI><A HREF="#1_1">System Overview</A></LI>
+<LI><A HREF="#1_2">Document Overview</A></LI>
+<LI><A HREF="#1_3">Notation Conventions</A></LI>
+<LI><A HREF="#1_4">Abbreviations</A></LI>
+<LI><A HREF="#1_5">Other References</A></LI>
+</UL>
+</B><B><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+<UL>
+<LI><A HREF="#2_1">The Printing Problem</A></LI>
+<LI><A HREF="#2_2">The Technology</A></LI>
+<LI><A HREF="#2_3">Jobs</A></LI>
+<LI><A HREF="#2_4">Classes</A></LI>
+<LI><A HREF="#2_5">Filters</A></LI>
+<LI><A HREF="#2_6">Backends</A></LI>
+<LI><A HREF="#2_7">Printer Drivers</A></LI>
+<LI><A HREF="#2_8">Networking</A></LI>
+</UL>
+</B><B><A HREF="#USING_SYSTEM">2 - Using the Printing System</A>
+<UL>
+<LI><A HREF="#3_1">Submitting Files for Printing</A></LI>
+<LI><A HREF="#3_2">Choosing a Printer</A></LI>
+<LI><A HREF="#3_3">Setting Printer Options</A></LI>
+<LI><A HREF="#3_4">Printing Multiple Copies</A></LI>
+<LI><A HREF="#3_5">Checking the Printer Status from the Command-Line</A></LI>
+<LI><A HREF="#3_6">Checking the Printer Status from the Web</A></LI>
+<LI><A HREF="#3_7">Canceling a Print Job</A></LI>
+</UL>
+</B><B><A HREF="#STANDARD_OPTIONS">3 - Standard Printer Options</A>
+<UL>
+<LI><A HREF="#4_1">General Options</A>
+<UL>
+<LI><A HREF="#4_1_1">Selecting the Media Size, Type, and Source</A></LI>
+<LI><A HREF="#4_1_2">Setting the Orientation</A></LI>
+<LI><A HREF="#4_1_3">Printing On Both Sides of the Paper</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_2">Banner Options</A>
+<UL>
+<LI><A HREF="#4_2_1">Selecting the Banner Page(s)</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_3">Document Options</A>
+<UL>
+<LI><A HREF="#4_3_1">Selecting a Range of Pages</A></LI>
+<LI><A HREF="#4_3_2">Selecting Even or Odd Pages</A></LI>
+<LI><A HREF="#4_3_3">Setting the Output Order</A></LI>
+<LI><A HREF="#4_3_4">N-Up Printing</A></LI>
+<LI><A HREF="#4_3_5">Mirroring Prints</A></LI>
+<LI><A HREF="#4_3_6">Setting the Brightness</A></LI>
+<LI><A HREF="#4_3_7">Setting the Gamma Correction</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_4">Text Options</A>
+<UL>
+<LI><A HREF="#4_4_1">Setting the Number of Characters Per Inch</A></LI>
+<LI><A HREF="#4_4_2">Setting the Number of Lines Per Inch</A></LI>
+<LI><A HREF="#4_4_3">Setting the Number of Columns</A></LI>
+<LI><A HREF="#4_4_4">Setting the Page Margins</A></LI>
+<LI><A HREF="#4_4_5">Pretty Printing</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_5">Image Options</A>
+<UL>
+<LI><A HREF="#4_5_1">Positioning the Image</A></LI>
+<LI><A HREF="#4_5_2">Scaling the Image</A></LI>
+<LI><A HREF="#4_5_3">Adjusting the Hue (Tint) of an Image</A></LI>
+<LI><A HREF="#4_5_4">Adjusting the Saturation (Color) of an Image</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_6">HP-GL/2 Options</A>
+<UL>
+<LI><A HREF="#4_6_1">Printing in Black</A></LI>
+<LI><A HREF="#4_6_2">Fitting the Plot on the Page</A></LI>
+<LI><A HREF="#4_6_3">Setting the Default Pen Width</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#4_7">Raw or Unfiltered Output</A></LI>
+</UL>
+</B><B><A HREF="#SAVING_OPTIONS">4 - Saving Printer Options and Defaults</A>
+<UL>
+<LI><A HREF="#5_1">Printer Options</A></LI>
+<LI><A HREF="#5_2">Setting Options for a Specific Printer</A></LI>
+<LI><A HREF="#5_3">Removing Options</A></LI>
+<LI><A HREF="#5_4">Viewing the Current Defaults</A></LI>
+<LI><A HREF="#5_5">Viewing Options for a Specific Printer</A></LI>
+<LI><A HREF="#5_6">Setting the Default Printer</A></LI>
+<LI><A HREF="#5_7">Printer Instances</A></LI>
+<LI><A HREF="#5_8">Removing Instances</A></LI>
+</UL>
+</B><B><A HREF="#LICENSE">A - Software License Agreement</A>
+<UL>
+<LI><A HREF="#6_1">Common UNIX Printing System License Agreement</A>
+<UL>
+<LI><A HREF="#6_1_1">Introduction</A></LI>
+<LI><A HREF="#6_1_2">License Exceptions</A></LI>
+<LI><A HREF="#6_1_3">Trademarks</A></LI>
+<LI><A HREF="#6_1_4">Binary Distribution Rights</A></LI>
+<LI><A HREF="#6_1_5">Support</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#6_2">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#6_2_1">Preamble</A></LI>
+</UL>
+</LI>
+<LI><A HREF="#6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A HREF="#6_3_1">Preamble</A></LI>
+</UL>
+</LI>
+</UL>
+</B><HR NOSHADE>
+<H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
+<P>This software users manual describes how to use the Common UNIX
+ Printing System<SUP>TM</SUP> (&quot;CUPS<SUP>TM</SUP>&quot;) Version 1.1.22.</P>
+<H2><A NAME="1_1">System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+
+<!-- NEED 2in -->
+<H2><A NAME="1_2">Document Overview</A></H2>
+<P>This software users manual is organized into the following sections:</P>
+<UL>
+<LI><A HREF="#OVERVIEW">1 - Printing System Overview</A></LI>
+<LI><A HREF="#USING_SYSTEM">2 - Using the Printing System</A></LI>
+<LI><A HREF="#STANDARD_OPTIONS">3 - Standard Printer Options</A></LI>
+<LI><A HREF="#SAVING_OPTIONS">4 - Saving Printer Options and Defaults</A>
+</LI>
+<LI><A HREF="#LICENSE">A - Software License Agreement</A></LI>
+</UL>
+<H2><A NAME="1_3">Notation Conventions</A></H2>
+<P>Various font and syntax conventions are used in this guide. Examples
+ and their meanings and uses are explained below:
+<CENTER>
+<TABLE WIDTH="80%">
+<TR><TH>Example</TH><TD>&nbsp;&nbsp;&nbsp;</TD><TH>Description</TH></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><CODE>lpstat</CODE>
+<BR> <CODE>lpstat(1)</CODE></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>The names of commands;
+ the first mention of a command or function in a chapter is followed by
+ a manual page section number.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD><VAR>/var</VAR>
+<BR><VAR> /usr/share/cups/data/testprint.ps</VAR></TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>
+File and directory names.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><TT>Request ID is Printer-123</TT></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Screen output.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD><TD>
+&nbsp;&nbsp;&nbsp;</TD><TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD></TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP"><TD>12.3</TD><TD>&nbsp;&nbsp;&nbsp;</TD><TD>Numbers in the text are
+ written using the period (.) to indicate the decimal point.</TD></TR>
+</TABLE>
+</CENTER>
+
+<!-- NEED 3in -->
+</P>
+<H2><A NAME="1_4">Abbreviations</A></H2>
+ The following abbreviations are used throughout this manual:
+<UL>
+<DL>
+<DT>kb</DT>
+<DD>Kilobytes, or 1024 bytes
+<BR>&nbsp;</DD>
+<DT>Mb</DT>
+<DD>Megabytes, or 1048576 bytes
+<BR>&nbsp;</DD>
+<DT>Gb</DT>
+<DD>Gigabytes, or 1073741824 bytes
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H2><A NAME="1_5">Other References</A></H2>
+<UL>
+<DL>
+<DT>CUPS Software Administrators Manual</DT>
+<DD>An administration guide for the CUPS software.
+<BR>&nbsp;</DD>
+<DT>CUPS Software Programmers Manual</DT>
+<DD>A programmer guide for interfacing with and/or extending the CUPS
+ software.
+<BR>&nbsp;</DD>
+</DL>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="OVERVIEW">1 - Printing System Overview</A></H1>
+<P>This chapter provides an overview of how the Common UNIX Printing
+ System works.</P>
+<H2><A NAME="2_1">The Printing Problem</A></H2>
+<P>For years<I> the printing problem</I> has plagued UNIX. Unlike
+ Microsoft&reg; Windows&reg; or Mac OS, UNIX has no standard interface or system
+ in place for supporting printers. Among the solutions currently
+ available, the Berkeley and System V printing systems are the most
+ prevalent.</P>
+<P>These printing systems support line printers (text only) or
+ PostScript printers (text and graphics), and with some coaxing they can
+ be made to support a full range of printers and file formats. However,
+ because each varient of the UNIX operating system uses a different
+ printing system than the next developing printer drivers for a wide
+ range of printers and operating systems is extremely difficult. That
+ combined with the limited volume of customers for each UNIX varient has
+ forced most printer vendors to give up supporting UNIX entirely.</P>
+<P>CUPS is designed to eliminate<I> the printing problem</I>. One common
+ printing system can be used by all UNIX varients to support the
+ printing needs of users. Printer vendors can use its modular filter
+ interface to develop a single driver program that supports a wide range
+ of file formats with little or no effort. Since CUPS provides both the
+ System V and Berkeley printing commands, users (and applications) can
+ reap the benefits of this new technology with no changes.</P>
+<H2><A NAME="2_2">The Technology</A></H2>
+<P>CUPS is based upon an emerging Internet standard called the Internet
+ Printing Protocol. IPP has been embraced by dozens of printer and
+ printer server manufacturers and is supported by Microsoft Windows
+ 2000.</P>
+<P>IPP defines a standard protocol for printing as well as managing
+ print jobs and printer options like media size, resolution, and so
+ forth. Like all IP-based protocols, IPP can be used locally or over the
+ Internet to printers hundreds or thousands of miles away. Unlike other
+ protocols, however, IPP also supports access control, authentication,
+ and encryption, making it a much more capable and secure printing
+ solution than older ones.</P>
+<P>IPP is layered on top of the Hyper-Text Transport Protocol (&quot;HTTP&quot;)
+ which is the basis of web servers on the Internet. This allows users to
+ view documentation, check status information on a printer or server,
+ and manage their printers, classes, and jobs using their web browser.</P>
+<P>CUPS provides a complete IPP/1.1 based printing system that provides
+ Basic, Digest, and local certificate authentication and user, domain,
+ or IP-based access control. TLS encryption will be available in future
+ versions of CUPS.</P>
+<H2><A NAME="2_3">Jobs</A></H2>
+<P>Each file or set of files that is submitted for printing is called a<I>
+ job</I>. Jobs are identified by a unique number starting at 1 and are
+ assigned to a particular destination, usually a printer. Jobs can also
+ have options associated with them such as media size, number of copies,
+ and priority.</P>
+<H2><A NAME="2_4">Classes</A></H2>
+<P>CUPS supports collections of printers known as<I> classes</I>. Jobs
+ sent to a class are forwarded to the first available printer in the
+ class.</P>
+<H2><A NAME="2_5">Filters</A></H2>
+<P>Filters allow a user or application to print many types of files
+ without extra effort. Print jobs sent to a CUPS server are filtered
+ before sending them to a printer. Some filters convert job files to
+ different formats that the printer can understand. Others perform page
+ selection and ordering tasks.</P>
+<P>CUPS provides filters for printing many types of image files, HP-GL/2
+ files, PDF files, and text files. CUPS also supplies PostScript and
+ image file Raster Image Processor (&quot;RIP&quot;) filters that convert
+ PostScript or image files into bitmaps that can be sent to a raster
+ printer.</P>
+<H2><A NAME="2_6">Backends</A></H2>
+<P>Backends perform the most important task of all - they send the
+ filtered print data to the printer.</P>
+<P>CUPS provides backends for printing over parallel, serial, and USB
+ ports, and over the network via the IPP, JetDirect (AppSocket), and
+ Line Printer Daemon (&quot;LPD&quot;) protocols. Additional backends are
+ available in network service packages such as the SMB backend included
+ with the popular SAMBA software.</P>
+<P>Backends are also used to determine the available devices. On startup
+ each backend is asked for a list of devices it supports, and any
+ information that is available. This allows the parallel backend to tell
+ CUPS that an EPSON Stylus Color 600 printer is attached to parallel
+ port 1, for example.</P>
+<H2><A NAME="2_7">Printer Drivers</A></H2>
+<P>Printer drivers in CUPS consist of one of more filters specific to a
+ printer. CUPS includes sample printer drivers for Hewlett-Packard
+ LaserJet and DeskJet printers and EPSON 9-pin, 24-pin, Stylus Color,
+ and Stylus Photo printers. While these drivers do not generate optimal
+ output for the different printer models, they do provide basic printing
+ and demonstrate how you can write your own printer drivers and
+ incorporate them into CUPS.</P>
+<H2><A NAME="2_8">Networking</A></H2>
+<P>Printers and classes on the local system are automatically shared
+ with other systems on the network. This allows you to setup one system
+ to print to a printer and use this system as a printer server or spool
+ host for all of the others. Users may then select a local printer by
+ name or a remote printer using &quot;name@server&quot;.</P>
+<P>CUPS also provides<I> implicit classes</I>, which are collections of
+ printers and/or classes with the same name. This allows you to setup
+ multiple servers pointing to the same physical network printer, for
+ example, so that you aren't relying on a single system for printing.
+ Because this also works with printer classes, you can setup multiple
+ servers and printers and never worry about a single point of failure
+ unless all of the printers and servers go down!</P>
+<H1 ALIGN="RIGHT"><A NAME="USING_SYSTEM">2 - Using the Printing System</A>
+</H1>
+<P>This chapter shows you how to submit, query, and cancel print jobs to
+ different printers.</P>
+<H2><A NAME="3_1">Submitting Files for Printing</A></H2>
+<P>CUPS provides both the System V (<CODE>lp(1)</CODE>) and Berkeley (<CODE>
+lpr(1)</CODE>) printing commands. Type the following command to print a
+ file to the default (or only) printer on the system:</P>
+<UL>
+<PRE>
+<B>lp filename ENTER</B>
+</PRE>
+</UL>
+<P>or:</P>
+<UL>
+<PRE>
+<B>lpr filename ENTER</B>
+</PRE>
+</UL>
+<P>CUPS understands many different types of files directly, including
+ PostScript and image files. This allows you to print from inside your
+ applications or at the command-line, whichever is most convenient!</P>
+<H2><A NAME="3_2">Choosing a Printer</A></H2>
+<P>Many systems will have more than one printer available to the user.
+ These printers can be attached to the local system via a parallel,
+ serial, or USB port, or available over the network.</P>
+<P>Use the <CODE>lpstat(1)</CODE> command to see a list of available
+ printers:</P>
+<UL>
+<PRE>
+<B>lpstat -p -d ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>-p</CODE> option specifies that you want to see a list of
+ printers, and the <CODE>-d</CODE> option reports the current default
+ printer or class.</P>
+<P>Use the <CODE>-d</CODE> option with the <CODE>lp</CODE> command to
+ print to a specific printer:</P>
+<UL>
+<PRE>
+<B>lp -d printer filename ENTER</B>
+</PRE>
+</UL>
+<P>or the <CODE>-P</CODE> option with the <CODE>lpr</CODE> command:</P>
+<UL>
+<PRE>
+<B>lpr -P printer filename ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="3_3">Setting Printer Options</A></H2>
+<P>For many types of files, the default printer options may be
+ sufficient for your needs. However, there may be times when you need to
+ change the options for a particular file you are printing.</P>
+<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands allow you to pass
+ printer options using the <CODE>-o</CODE> option:</P>
+<UL>
+<PRE>
+<B>lp -o landscape -o scaling=75 -o media=A4 filename.jpg ENTER</B>
+<B>lpr -o landscape -o scaling=75 -o media=A4 filename.jpg ENTER</B>
+</PRE>
+</UL>
+<P>The available printer options vary depending on the printer. The
+ standard options are described in <A HREF="#STANDARD_OPTIONS">Chapter
+ 3, &quot;Standard Printing Options&quot;</A>.</P>
+<H2><A NAME="3_4">Printing Multiple Copies</A></H2>
+<P>Both the <CODE>lp</CODE> and <CODE>lpr</CODE> commands have options
+ for printing more than one copy of a file:</P>
+<UL>
+<PRE>
+<B>lp -n <I>num-copies</I> filename ENTER</B>
+<B>lpr -#<I>num-copies</I> filename ENTER</B>
+</PRE>
+</UL>
+<P>Copies are normally<I> not</I> collated for you. Use the <CODE>-o
+ Collate=True</CODE> option to get collated copies :</P>
+<UL>
+<PRE>
+<B>lp -n <I>num-copies</I> -o Collate=True filename ENTER</B>
+<B>lpr -#<I>num-copies</I> -o Collate=True filename ENTER</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<H2><A NAME="3_5">Checking the Printer Status from the Command-Line</A></H2>
+<P>The <CODE>lpstat</CODE> command can be used to check for jobs that
+ you have submitted for printing:</P>
+<UL>
+<PRE>
+<B>lpstat ENTER</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+</PRE>
+</UL>
+<P>The jobs are listed in the order they will be printed. Use the <CODE>
+-p</CODE> option to see which files and printers are active:</P>
+<UL>
+<PRE>
+<B>lpstat -p ENTER</B>
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+
+<!-- NEED 2in -->
+<P>Use the <CODE>-o</CODE> and <CODE>-p</CODE> options together to show
+ the jobs and the printers:</P>
+<UL>
+<PRE>
+<B>lpstat -o -p ENTER</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+printer DeskJet now printing DeskJet-1.
+</PRE>
+</UL>
+<H2><A NAME="3_6">Checking the Printer Status from the Web</A></H2>
+<P>Since CUPS uses the Internet Printing Protocol, it is also a
+ fully-functional web server. To use your web browser to monitor the
+ printers on your system, open the URL:</P>
+<UL>
+<PRE>
+<A HREF="http://localhost:631">http://localhost:631</A>
+</PRE>
+</UL>
+<P>From there you can view the status of classes, jobs, and printers
+ with the click of a button!</P>
+<H2><A NAME="3_7">Canceling a Print Job</A></H2>
+<P>The <CODE>cancel(1)</CODE> and <CODE>lprm(1)</CODE> commands cancel a
+ print job:</P>
+<UL>
+<PRE>
+<B>cancel <I>job-id</I> ENTER</B>
+<B>lprm <I>job-id</I> ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>job-id</CODE> is the number that was reported to you by the
+ <CODE>lp</CODE> or <CODE>lpstat</CODE> commands.</P>
+<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Standard Printer
+ Options</A></H1>
+<P>This chapter describes the standard printer options that are
+ available when printing with the <CODE>lp</CODE> and <CODE>lpr</CODE>
+ commands.</P>
+<H2><A NAME="4_1">General Options</A></H2>
+<P>The following options apply when printing all types of files.
+<!-- NEED 2in -->
+</P>
+<H3><A NAME="4_1_1">Selecting the Media Size, Type, and Source</A></H3>
+<P>The <CODE>-o media=xyz</CODE> option sets the media size, type,
+ and/or source:</P>
+<UL>
+<PRE>
+<B>lp -o media=Letter filename ENTER</B>
+<B>lp -o media=Letter,MultiPurpose filename ENTER</B>
+<B>lpr -o media=Letter,Transparency filename ENTER</B>
+<B>lpr -o media=Letter,MultiPurpose,Transparency filename ENTER</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>The available media sizes, types, and sources depend on the printer,
+ but most support the following options (case is not significant):</P>
+<UL>
+<LI><CODE>Letter</CODE> - US Letter (8.5x11 inches, or 216x279mm)</LI>
+<LI><CODE>Legal</CODE> - US Legal (8.5x14 inches, or 216x356mm)</LI>
+<LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 inches, or 210x297mm)</LI>
+<LI><CODE>COM10</CODE> - US #10 Envelope (9.5x4.125 inches, or
+ 241x105mm)</LI>
+<LI><CODE>DL</CODE> - ISO DL Envelope (8.66x4.33 inches, or 220x110mm)</LI>
+<LI><CODE>Transparency</CODE> - Transparency media type or source</LI>
+<LI><CODE>Upper</CODE> - Upper paper tray</LI>
+<LI><CODE>Lower</CODE> - Lower paper tray</LI>
+<LI><CODE>MultiPurpose</CODE> - Multi-purpose paper tray</LI>
+<LI><CODE>LargeCapacity</CODE> - Large capacity paper tray</LI>
+</UL>
+<P>The actual options supported are defined in the printer's PPD file in
+ the <CODE>PageSize</CODE>, <CODE>InputSlot</CODE>, and <CODE>MediaType</CODE>
+ options.</P>
+<H3><A NAME="4_1_2">Setting the Orientation</A></H3>
+<P>The <CODE>-o landscape</CODE> option will rotate the page 90 degrees
+ to print in landscape orientation:</P>
+<UL>
+<PRE>
+<B>lp -o landscape filename ENTER</B>
+<B>lpr -o landscape filename ENTER</B>
+</PRE>
+</UL>
+<H3><A NAME="4_1_3">Printing On Both Sides of the Paper</A></H3>
+<P>The <CODE>-o sides=two-sided-short-edge</CODE> and <CODE>-o
+ sides=two-sided-long-edge</CODE> options will enable duplexing on the
+ printer, if the printer supports it. The <CODE>-o
+ sides=two-sided-short-edge</CODE> option is suitable for landscape
+ pages, while the <CODE>-o sides=two-sided-long-edge</CODE> option is
+ suitable for portrait pages:</P>
+<UL>
+<PRE>
+<B>lp -o sides=two-sided-short-edge filename ENTER</B>
+<B>lp -o sides=two-sided-long-edge filename ENTER</B>
+<B>lpr -o sides=two-sided-long-edge filename ENTER</B>
+</PRE>
+</UL>
+<P>The default is to print single-sided:</P>
+<UL>
+<PRE>
+<B>lp -o sides=one-sided filename ENTER</B>
+<B>lpr -o sides=one-sided filename ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="4_2">Banner Options</A></H2>
+<P>The following options apply when printing all types of files.</P>
+<H3><A NAME="4_2_1">Selecting the Banner Page(s)</A></H3>
+<P>The <CODE>-o jobsheets=start,end</CODE> option sets the banner
+ page(s) to use for a job:</P>
+<UL>
+<PRE>
+<B>lp -o job-sheets=none filename ENTER</B>
+<B>lp -o job-sheets=standard filename ENTER</B>
+<B>lpr -o job-sheets=classified,classified filename ENTER</B>
+</PRE>
+</UL>
+<P>If only one banner file is specified, it will be printed before the
+ files in the job. If a second banner file is specified, it is printed
+ after the files in the job.</P>
+<P>The available banner pages depend on the local system configuration;
+ CUPS includes the following banner files:</P>
+<UL>
+<LI><CODE>none</CODE> - Do not produce a banner page.</LI>
+<LI><CODE>classified</CODE> - A banner page with a &quot;classified&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>confidential</CODE> - A banner page with a &quot;confidential&quot;
+ label at the top and bottom.</LI>
+<LI><CODE>secret</CODE> - A banner page with a &quot;secret&quot; label at the top
+ and bottom.</LI>
+<LI><CODE>standard</CODE> - A banner page with no label at the top and
+ bottom.</LI>
+<LI><CODE>topsecret</CODE> - A banner page with a &quot;top secret&quot; label at
+ the top and bottom.</LI>
+<LI><CODE>unclassified</CODE> - A banner page with an &quot;unclassified&quot;
+ label at the top and bottom.</LI>
+</UL>
+<H2><A NAME="4_3">Document Options</A></H2>
+<P>The following options apply when printing all types of files.</P>
+<H3><A NAME="4_3_1">Selecting a Range of Pages</A></H3>
+<P>The <CODE>-o page-ranges=pages</CODE> option selects a range of pages
+ for printing:</P>
+<UL>
+<PRE>
+<B>lp -o page-ranges=1 filename ENTER</B>
+<B>lp -o page-ranges=1-4 filename ENTER</B>
+<B>lp -o page-ranges=1-4,7,9-12 filename ENTER</B>
+<B>lpr -o page-ranges=1-4,7,9-12 filename ENTER</B>
+</PRE>
+</UL>
+<P>As shown above, the <CODE>pages</CODE> value can be a single page, a
+ range of pages, or a collection of page numbers and ranges separated by
+ commas. The pages will always be printed in ascending order, regardless
+ of the order of the pages in the <CODE>page-ranges</CODE> option.</P>
+<P>The default is to print all pages.</P>
+<H3><A NAME="4_3_2">Selecting Even or Odd Pages</A></H3>
+<P>Use the <CODE>-o page-set=set</CODE> option to select the even or odd
+ pages:</P>
+<UL>
+<PRE>
+<B>lp -o page-set=odd filename ENTER</B>
+<B>lp -o page-set=even filename ENTER</B>
+<B>lpr -o page-set=even filename ENTER</B>
+</PRE>
+</UL>
+<P>The default is to print all pages.</P>
+<H3><A NAME="4_3_3">Setting the Output Order</A></H3>
+<P>The the <CODE>-o outputorder=order</CODE> option to set the output
+ order of all pages:</P>
+<UL>
+<PRE>
+<B>lp -o outputorder=normal filename ENTER</B>
+<B>lp -o outputorder=reverse filename ENTER</B>
+<B>lpr -o outputorder=reverse filename ENTER</B>
+</PRE>
+</UL>
+<H3><A NAME="4_3_4">N-Up Printing</A></H3>
+<P>The <CODE>-o number-up=value</CODE> option selects N-Up printing.
+ N-Up printing places multiple document pages on a single printed page.
+ CUPS supports 1, 2, 4, 6, 9, and 16-Up formats; the default format is
+ 1-Up:</P>
+<UL>
+<PRE>
+<B>lp -o number-up=1 filename ENTER</B>
+<B>lp -o number-up=2 filename ENTER</B>
+<B>lp -o number-up=4 filename ENTER</B>
+<B>lpr -o number-up=16 filename ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>-o page-border=value</CODE> option chooses the border to
+ draw around each page:</P>
+<UL>
+<LI><CODE>-o page-border=double</CODE>; draw two hairline borders around
+ each page</LI>
+<LI><CODE>-o page-border=double-thick</CODE>; draw two 1pt borders
+ around each page</LI>
+<LI><CODE>-o page-border=none</CODE>; do not draw a border (default)</LI>
+<LI><CODE>-o page-border=single</CODE>; draw one hairline border around
+ each page</LI>
+<LI><CODE>-o page-border=single-thick</CODE>; draw one 1pt border around
+ each page</LI>
+</UL>
+<P>The <CODE>-o number-up-layout=value</CODE> option chooses the layout
+ of the pages on each output page:</P>
+<UL>
+<LI><CODE>-o number-up-layout=btlr</CODE>; Bottom to top, left to right</LI>
+<LI><CODE>-o number-up-layout=btrl</CODE>; Bottom to top, right to left</LI>
+<LI><CODE>-o number-up-layout=lrbt</CODE>; Left to right, bottom to top</LI>
+<LI><CODE>-o number-up-layout=lrtb</CODE>; Left to right, top to bottom
+ (default)</LI>
+<LI><CODE>-o number-up-layout=rlbt</CODE>; Right to left, bottom to top</LI>
+<LI><CODE>-o number-up-layout=rltb</CODE>; Right to left, top to bottom</LI>
+<LI><CODE>-o number-up-layout=tblr</CODE>; Top to bottom, left to right</LI>
+<LI><CODE>-o number-up-layout=tbrl</CODE>; Top to bottom, right to left</LI>
+</UL>
+<H3><A NAME="4_3_5">Mirroring Prints</A></H3>
+<P>You can mirror a print using the <CODE>-o mirror</CODE> option:</P>
+<UL>
+<PRE>
+<B>lp -o mirror filename ENTER</B>
+<B>lpr -o mirror filename ENTER</B>
+</PRE>
+</UL>
+<P>This is useful for printing mirrored pages on transfer paper, for T
+ shirts, mugs, etc.</P>
+<H3><A NAME="4_3_6">Setting the Brightness</A></H3>
+<P>You can control the overall brightness of the printed output using
+ the <CODE>-o brightness=percent</CODE> option:</P>
+<UL>
+<PRE>
+<B>lp -o brightness=120 filename ENTER</B>
+<B>lpr -o brightness=120 filename ENTER</B>
+</PRE>
+</UL>
+<P>Values greater than 100 will lighten the print, while values less
+ than 100 will darken it.</P>
+<H3><A NAME="4_3_7">Setting the Gamma Correction</A></H3>
+<P>You can control the overall gamma correction of the printed output
+ using the <CODE>-o gamma=value</CODE> option:</P>
+<UL>
+<PRE>
+<B>lp -o gamma=1700 filename ENTER</B>
+<B>lpr -o gamma=1700 filename ENTER</B>
+</PRE>
+</UL>
+<P>Values greater than 1000 will lighten the print, while values less
+ than 1000 will darken it. The default gamma is 1000.</P>
+<H2><A NAME="4_4">Text Options</A></H2>
+<P>The following options apply when printing text files.</P>
+<H3><A NAME="4_4_1">Setting the Number of Characters Per Inch</A></H3>
+<P>The <CODE>-o cpi=value</CODE> option sets the number of characters
+ per inch:</P>
+<UL>
+<PRE>
+<B>lp -o cpi=10 filename ENTER</B>
+<B>lp -o cpi=12 filename ENTER</B>
+<B>lpr -o cpi=17 filename ENTER</B>
+</PRE>
+</UL>
+<P>The default characters per inch is 10.</P>
+<H3><A NAME="4_4_2">Setting the Number of Lines Per Inch</A></H3>
+<P>The <CODE>-o lpi=value</CODE> option sets the number of lines per
+ inch:</P>
+<UL>
+<PRE>
+<B>lp -o lpi=6 filename ENTER</B>
+<B>lpr -o lpi=8 filename ENTER</B>
+</PRE>
+</UL>
+<P>The default lines per inch is 6.</P>
+<H3><A NAME="4_4_3">Setting the Number of Columns</A></H3>
+<P>The <CODE>-o columns=value</CODE> option sets the number of text
+ columns:</P>
+<UL>
+<PRE>
+<B>lp -o columns=2 filename ENTER</B>
+<B>lpr -o columns=3 filename ENTER</B>
+</PRE>
+</UL>
+<P>The default number of columns is 1.</P>
+<H3><A NAME="4_4_4">Setting the Page Margins</A></H3>
+<P>Normally the page margins are set to the hard limits of the printer.
+ Use the <CODE>-o page-left=value</CODE>, <CODE>-o page-right=value</CODE>
+, <CODE>-o page-top=value</CODE>, and <CODE>-o page-bottom=value</CODE>
+ options to adjust the page margins:</P>
+<UL>
+<PRE>
+<B>lp -o page-left=<I>value</I> filename ENTER</B>
+<B>lp -o page-right=<I>value</I> filename ENTER</B>
+<B>lp -o page-top=<I>value</I> filename ENTER</B>
+<B>lp -o page-bottom=<I>value</I> filename ENTER</B>
+<B>lpr -o page-bottom=<I>value</I> filename ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>value</CODE> argument is the margin in points; each point
+ is 1/72 inch or 0.35mm.</P>
+<H3><A NAME="4_4_5">Pretty Printing</A></H3>
+<P>The <CODE>-o prettyprint</CODE> option puts a header at the top of
+ each page with the page number, job title (usually the filename), and
+ the date. Also, C and C++ keywords are highlighted, and comment lines
+ are italicized:</P>
+<UL>
+<PRE>
+<B>lp -o prettyprint filename ENTER</B>
+<B>lpr -o prettyprint filename ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="4_5">Image Options</A></H2>
+<P>The following options apply when printing image files.</P>
+<H3><A NAME="4_5_1">Positioning the Image</A></H3>
+<P>The <CODE>-o position=name</CODE> option specifies the position of
+ the image on the page:</P>
+<UL>
+<LI><CODE>center</CODE> - Center the image on the page (default)</LI>
+<LI><CODE>top</CODE> - Print the image centered at the top of the page</LI>
+<LI><CODE>left</CODE> - Print the image centered on the left of page</LI>
+<LI><CODE>right</CODE> - Print the image centered on the right of the
+ page</LI>
+<LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page</LI>
+<LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page</LI>
+<LI><CODE>bottom</CODE> - Print the image centered at the bottom of the
+ page</LI>
+<LI><CODE>bottom-left</CODE> - Print the image at the bottom left corner
+ of the page</LI>
+<LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page</LI>
+</UL>
+<H3><A NAME="4_5_2">Scaling the Image</A></H3>
+<P>The <CODE>-o scaling=percent</CODE>, <CODE>-o ppi=value</CODE>, and <CODE>
+-o natural-scaling=percent</CODE> options change the size of a printed
+ image:</P>
+<UL>
+<PRE>
+<B>lp -o scaling=<I>percent</I> filename ENTER</B>
+<B>lp -o ppi=<I>value</I> filename ENTER</B>
+<B>lpr -o natural-scaling=<I>percent</I> filename ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>scaling=percent</CODE> value is a number from 1 to 800
+ specifying the size in relation to the page (<I>not</I> the image.) A
+ scaling of 100 percent will fill the page as completely as the image
+ aspect ratio allows. A scaling of 200 percent will print on up to 4
+ pages.</P>
+<P>The <CODE>ppi=value</CODE> value is a number from 1 to 1200
+ specifying the resolution of the image in pixels per inch. An image
+ that is 3000x2400 pixels will print 10x8 inches at 300 pixels per inch,
+ for example. If the specified resolution makes the image larger than
+ the page, multiple pages will be printed to satisfy the request.</P>
+<P>The <CODE>natural-scaling=percent</CODE> value is a number from 1 to
+ 800 specifying the size in relation to the natural image size. A
+ scaling of 100 percent will print the image at its natural size, while
+ a scaling of 50 percent will print the image at half its natural size.
+ If the specified scaling makes the image larger than the page, multiple
+ pages will be printed to satisfy the request.</P>
+<H3><A NAME="4_5_3">Adjusting the Hue (Tint) of an Image</A></H3>
+<P>The <CODE>-o hue=value</CODE> option will adjust the hue of the
+ printed image, much like the tint control on your television:</P>
+<UL>
+<PRE>
+<B>lp -o hue=<I>value</I> filename ENTER</B>
+<B>lpr -o hue=<I>value</I> filename ENTER</B>
+</PRE>
+</UL>
+
+<!-- NEED 3in -->
+<P>The <CODE>value</CODE> argument is a number from -360 to 360 and
+ represents the color hue rotation. The following table summarizes the
+ change you'll see with different colors:
+<CENTER>
+<TABLE BORDER="1" WIDTH="50%">
+<TR><TH>Original</TH><TH>hue=-45</TH><TH>hue=45</TH></TR>
+<TR><TD>Red</TD><TD>Purple</TD><TD>Yellow-orange</TD></TR>
+<TR><TD>Green</TD><TD>Yellow-green</TD><TD>Blue-green</TD></TR>
+<TR><TD>Yellow</TD><TD>Orange</TD><TD>Green-yellow</TD></TR>
+<TR><TD>Blue</TD><TD>Sky-blue</TD><TD>Purple</TD></TR>
+<TR><TD>Magenta</TD><TD>Indigo</TD><TD>Crimson</TD></TR>
+<TR><TD>Cyan</TD><TD>Blue-green</TD><TD>Light-navy-blue</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<P>The default hue adjustment is 0.</P>
+<H3><A NAME="4_5_4">Adjusting the Saturation (Color) of an Image</A></H3>
+<P>The <CODE>-o saturation=percent</CODE> option adjusts the saturation
+ of the colors in an image, much like the color knob on your television:</P>
+<UL>
+<PRE>
+<B>lp -o saturation=<I>percent</I> filename ENTER</B>
+<B>lpr -o saturation=<I>percent</I> filename ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>percent</CODE> argument specifies the color saturation from
+ 0 to 200. A color saturation of 0 produces a black-and-white print,
+ while a value of 200 will make the colors extremely intense.</P>
+<P>The default saturation is 100.
+<!-- NEED 4in -->
+</P>
+<H2><A NAME="4_6">HP-GL/2 Options</A></H2>
+<P>The following options apply to HP-GL/2 files.</P>
+<H3><A NAME="4_6_1">Printing in Black</A></H3>
+<P>The <CODE>-o blackplot</CODE> option specifies that all pens should
+ plot in black:</P>
+<UL>
+<PRE>
+<B>lp -o blackplot filename ENTER</B>
+<B>lpr -o blackplot filename ENTER</B>
+</PRE>
+</UL>
+<P>The default is to use the colors defined in the plot file or the
+ standard pen colors defined in the HP-GL/2 reference manual from
+ Hewlett Packard.</P>
+<H3><A NAME="4_6_2">Fitting the Plot on the Page</A></H3>
+<P>The <CODE>-o fitplot</CODE> option specifies that the plot should be
+ scaled to fit on the page:</P>
+<UL>
+<PRE>
+<B>lp -o fitplot filename ENTER</B>
+<B>lpr -o fitplot filename ENTER</B>
+</PRE>
+</UL>
+<P>The default is to use the absolute distances specified in the plot
+ file.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>This feature depends upon an accurate plot size (<CODE>PS</CODE>)
+ command in the HP-GL/2 file. If no plot size is given in the file than
+ the HP-GL/2 filter assumes the plot is ANSI E size.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="4_6_3">Setting the Default Pen Width</A></H3>
+<P>The <CODE>-o penwidth=value</CODE> option specifies the default pen
+ width for HP-GL/2 files:</P>
+<UL>
+<PRE>
+<B>lp -o penwidth=<I>value</I> filename ENTER</B>
+<B>lpr -o penwidth=<I>value</I> filename ENTER</B>
+</PRE>
+</UL>
+<P>The pen width <CODE>value</CODE> specifies the pen width in
+ micrometers. The default value of 1000 produces lines that are 1
+ millimeter in width. Specifying a pen width of 0 produces lines that
+ are exactly 1 pixel wide.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" WIDTH="80%">
+<TR><TD><B> NOTE:</B>
+<P>This option is ignored when the pen widths are set in the plot file.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_7">Raw or Unfiltered Output</A></H2>
+<P>The <CODE>-o raw</CODE> option allows you to send files directly to a
+ printer without filtering. This is sometimes required when printing
+ from applications that provide their own &quot;printer drivers&quot; for your
+ printer:</P>
+<UL>
+<PRE>
+<B>lp -o raw filename ENTER</B>
+<B>lpr -o raw filename ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>-l</CODE> option can also be used with the <CODE>lpr</CODE>
+ command to send files directly to a printer:</P>
+<UL>
+<PRE>
+<B>lpr -l filename ENTER</B>
+</PRE>
+</UL>
+<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Saving Printer Options
+ and Defaults</A></H1>
+<P>This chapter describes how to save printer options for your printer
+ and set your own default printer.</P>
+<H2><A NAME="5_1">Printer Options</A></H2>
+<P>Each printer supports a large number of options, which you learned
+ about in <A HREF="#STANDARD_OPTIONS">Chapter 3, &quot;Standard Printer
+ Options&quot;</A>. Rather than specifying these options each time you print
+ a file, CUPS allows you to save them as &quot;default&quot; options for the
+ printer.</P>
+<P>The <CODE>lpoptions(1)</CODE> command saves the options for your
+ printers. Like the <CODE>lp</CODE> and <CODE>lpr</CODE> commands, it
+ accepts printer options using the <CODE>-o</CODE> argument:</P>
+<UL>
+<PRE>
+<B>lpoptions -o prettyprint ENTER</B>
+<B>lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -o media=Legal -o scaling=100 ENTER</B>
+</PRE>
+</UL>
+<P>Once saved, any <CODE>lp</CODE> or <CODE>lpr</CODE> command will use
+ them when you print.
+<CENTER>
+<TABLE BGCOLOR="#cccccc" BORDER="1" CELLPADDING="5" CELLSPACING="0" WIDTH="80%">
+<TR><TD><B>Note:</B>
+<P>Running the <CODE>lpoptions</CODE> command as the root user (or any
+ user with a UID of 0) will set the default options for all users. The
+ root account does not have its own set of default options.</P>
+</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="5_2">Setting Options for a Specific Printer</A></H2>
+<P>The previous example shows how to set the options for the default
+ printer. The <CODE>-p printer</CODE> option specifies the options are
+ for another printer:</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet -o prettyprint ENTER</B>
+<B>lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -p deskjet -o media=Legal -o scaling=100 ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="5_3">Removing Options</A></H2>
+<P>The previous two examples shows how to set options for the default
+ and a specific printer. Below, shows you how to remove the saved option
+ using the <CODE>-r</CODE> argument:</P>
+<UL>
+<PRE>
+<KBD>lpoptions -r prettyprint <I>ENTER</I></KBD>
+<KBD>lpoptions -p laserjet -r prettyprint <I>ENTER</I></KBD>
+</PRE>
+</UL>
+<H2><A NAME="5_4">Viewing the Current Defaults</A></H2>
+<P>The <CODE>lpoptions</CODE> command can also be used to show the
+ current options by not specifying any new options on the command-line:</P>
+<UL>
+<PRE>
+<B>lpoptions ENTER</B>
+media=A4 sides=two-sided-long-edge
+<B>lpoptions -p deskjet ENTER</B>
+media=Legal scaling=100
+</PRE>
+</UL>
+<H2><A NAME="5_5">Viewing Options for a Specific Printer</A></H2>
+<P>You can display the supported options using the <CODE>lpoptions</CODE>
+ command with the <CODE>-l</CODE> option, as follows:</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet -l ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="5_6">Setting the Default Printer</A></H2>
+<P>The administrator normally will set a system-wide default printer
+ that is normally used as the default printer by everyone. Use the <CODE>
+-d printer</CODE> option to set your own default printer:</P>
+<UL>
+<PRE>
+<B>lpoptions -d deskjet ENTER</B>
+</PRE>
+</UL>
+<P>The printer can be local (<CODE>deskjet</CODE>) or remote (<CODE>
+deskjet@server</CODE>).</P>
+<H2><A NAME="5_7">Printer Instances</A></H2>
+<P>Besides setting options for each print queue, CUPS supports<I>
+ printer instances</I> which allow you to define several different sets
+ of options for each printer. You specify a printer instance using the
+ slash (<CODE>/</CODE>) character:</P>
+<UL>
+<PRE>
+<B>lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -p laserjet/legal -o media=Legal ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands also understand
+ this notation:</P>
+<UL>
+<PRE>
+<B>lp -d laserjet/duplex filename ENTER</B>
+<B>lpr -P laserjet/legal filename ENTER</B>
+</PRE>
+</UL>
+<H2><A NAME="5_8">Removing Instances</A></H2>
+<P>Use the <CODE>-x printer/instance</CODE> option to remove a printer
+ instance that you no longer need:</P>
+<UL>
+<PRE>
+<B>lpoptions -x laserjet ENTER</B>
+<B>lpoptions -x laserjet/duplex ENTER</B>
+<B>lpoptions -x laserjet/legal ENTER</B>
+</PRE>
+</UL>
+<P>The <CODE>-x</CODE> option only removes the default options for that
+ printer and instance; the original print queue will remain until
+ deleted with the <CODE>lpadmin(8)</CODE> command by the administrator.</P>
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License Agreement</A></H1>
+<H2 ALIGN="CENTER"><A NAME="6_1">Common UNIX Printing System License
+ Agreement</A></H2>
+<P ALIGN="CENTER">Copyright 1997-2004 by Easy Software Products
+<BR> 44141 AIRPORT VIEW DR STE 204
+<BR> HOLLYWOOD, MARYLAND 20636-3142 USA
+<BR>
+<BR> Voice: +1.301.373.9600
+<BR> Email: <A HREF="mailto:cups-info@cups.org">cups-info@cups.org</A>
+<BR> WWW: <A HREF="http://www.cups.org">http://www.cups.org</A></P>
+<H3><A NAME="6_1_1">Introduction</A></H3>
+<P>The Common UNIX Printing System<SUP>TM</SUP>, (&quot;CUPS<SUP>TM</SUP>&quot;),
+ is provided under the GNU General Public License (&quot;GPL&quot;) and GNU
+ Library General Public License (&quot;LGPL&quot;), Version 2, with exceptions for
+ Apple operating systems and the OpenSSL toolkit. A copy of the
+ exceptions and licenses follow this introduction.</P>
+<P>The GNU LGPL applies to the CUPS API library, located in the &quot;cups&quot;
+ subdirectory of the CUPS source distribution and in the &quot;cups&quot; include
+ directory and library files in the binary distributions. The GNU GPL
+ applies to the remainder of the CUPS distribution, including the
+ &quot;pdftops&quot; filter which is based upon Xpdf and the CUPS imaging library.</P>
+<P>For those not familiar with the GNU GPL, the license basically allows
+ you to:</P>
+<UL>
+<LI>Use the CUPS software at no charge.</LI>
+<LI>Distribute verbatim copies of the software in source or binary form.</LI>
+<LI>Sell verbatim copies of the software for a media fee, or sell
+ support for the software.</LI>
+<LI>Distribute or sell printer drivers and filters that use CUPS so long
+ as source code is made available under the GPL.</LI>
+</UL>
+<P>What this license<B> does not</B> allow you to do is make changes or
+ add features to CUPS and then sell a binary distribution without source
+ code. You must provide source for any new drivers, changes, or
+ additions to the software, and all code must be provided under the GPL
+ or LGPL as appropriate. The only exceptions to this are the portions of
+ the CUPS software covered by the Apple operating system license
+ exceptions outlined later in this license agreement.</P>
+<P>The GNU LGPL relaxes the &quot;link-to&quot; restriction, allowing you to
+ develop applications that use the CUPS API library under other licenses
+ and/or conditions as appropriate for your application.</P>
+<H3><A NAME="6_1_2">License Exceptions</A></H3>
+<P>In addition, as the copyright holder of CUPS, Easy Software Products
+ grants the following special exceptions:</P>
+<OL>
+<LI><B>Apple Operating System Development License Exception</B>;
+<OL TYPE="a">
+<LI>Software that is developed by any person or entity for an Apple
+ Operating System (&quot;Apple OS-Developed Software&quot;), including but not
+ limited to Apple and third party printer drivers, filters, and backends
+ for an Apple Operating System, that is linked to the CUPS imaging
+ library or based on any sample filters or backends provided with CUPS
+ shall not be considered to be a derivative work or collective work
+ based on the CUPS program and is exempt from the mandatory source code
+ release clauses of the GNU GPL. You may therefore distribute linked
+ combinations of the CUPS imaging library with Apple OS-Developed
+ Software without releasing the source code of the Apple OS-Developed
+ Software. You may also use sample filters and backends provided with
+ CUPS to develop Apple OS-Developed Software without releasing the
+ source code of the Apple OS-Developed Software.</LI>
+<LI>An Apple Operating System means any operating system software
+ developed and/or marketed by Apple Computer, Inc., including but not
+ limited to all existing releases and versions of Apple's Darwin, Mac OS
+ X, and Mac OS X Server products and all follow-on releases and future
+ versions thereof.</LI>
+<LI>This exception is only available for Apple OS-Developed Software and
+ does not apply to software that is distributed for use on other
+ operating systems.</LI>
+<LI>All CUPS software that falls under this license exception have the
+ following text at the top of each source file:<BLOCKQUOTE>This file is
+ subject to the Apple OS-Developed Software exception.</BLOCKQUOTE></LI>
+</OL>
+</LI>
+<LI><B>OpenSSL Toolkit License Exception</B>;
+<OL TYPE="a">
+<LI>Easy Software Products explicitly allows the compilation and
+ distribution of the CUPS software with the OpenSSL Toolkit.</LI>
+</OL>
+</LI>
+</OL>
+<P>No developer is required to provide these exceptions in a derived
+ work.</P>
+<H3><A NAME="6_1_3">Trademarks</A></H3>
+<P>Easy Software Products has trademarked the Common UNIX Printing
+ System, CUPS, and CUPS logo. You may use these names and logos in any
+ direct port or binary distribution of CUPS. Please contact Easy
+ Software Products for written permission to use them in derivative
+ products. Our intention is to protect the value of these trademarks and
+ ensure that any derivative product meets the same high-quality
+ standards as the original.</P>
+<H3><A NAME="6_1_4">Binary Distribution Rights</A></H3>
+<P>Easy Software Products also sells rights to the CUPS source code
+ under a binary distribution license for vendors that are unable to
+ release source code for their drivers, additions, and modifications to
+ CUPS under the GNU GPL and LGPL. For information please contact us at
+ the address shown above.</P>
+<P>The Common UNIX Printing System provides a &quot;pdftops&quot; filter that is
+ based on the Xpdf software. For binary distribution licensing of this
+ software, please contact:<BLOCKQUOTE> Derek B. Noonburg
+<BR> Email: <A HREF="mailto:derekn@foolabs.com">derekn@foolabs.com</A>
+<BR> WWW: <A HREF="http://www.foolabs.com/xpdf/">
+http://www.foolabs.com/xpdf/</A></BLOCKQUOTE></P>
+<H3><A NAME="6_1_5">Support</A></H3>
+<P>Easy Software Products sells software support for CUPS as well as a
+ commercial printing product based on CUPS called ESP Print Pro. You can
+ find out more at our web site:</P>
+<UL>
+<PRE>
+<A HREF="http://www.easysw.com/">http://www.easysw.com/</A>
+</PRE>
+</UL>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_2">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim
+copies of this license document, but changing it is not allowed.
+</PRE>
+<H3><A NAME="6_2_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License is
+ intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users. This
+ General Public License applies to most of the Free Software
+ Foundation's software and to any other program whose authors commit to
+ using it. (Some other Free Software Foundation software is covered by
+ the GNU Library General Public License instead.) You can apply it to
+ your programs, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the software, or if you modify it.</P>
+<P>For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.</P>
+<P>We protect your rights with two steps: (1) copyright the software,
+ and (2) offer you this license which gives you legal permission to
+ copy, distribute and/or modify the software.</P>
+<P>Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on, we
+ want its recipients to know that what they have is not the original, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at all.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow.</P>
+<H4>GNU GENERAL PUBLIC LICENSE
+<BR> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<OL START="0">
+<LI>This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The &quot;Program&quot;, below,
+ refers to any such program or work, and a &quot;work based on the Program&quot;
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;.
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is
+ covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether that
+ is true depends on what the Program does.</P>
+</LI>
+<LI>You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+</LI>
+<LI>You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above, provided
+ that you also meet all of these conditions:
+<OL TYPE="a">
+<LI>You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.</LI>
+<LI>You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.</LI>
+<LI>if the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the most ordinary way, to print or display an announcement including
+ an appropriate copyright notice and a notice that there is no warranty
+ (or else, saying that you provide a warranty) and that users may
+ redistribute the program under these conditions, and telling the user
+ how to view a copy of this License. (Exception: if the Program itself
+ is interactive but does not normally print such an announcement, your
+ work based on the Program is not required to print an announcement.)</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Program,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Program, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Program with the Program (or with a work based on the Program) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+</LI>
+<LI>You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+<OL TYPE="a">
+<LI>Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,</LI>
+<LI>Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-readable
+ copy of the corresponding source code, to be distributed under the
+ terms of Sections 1 and 2 above on a medium customarily used for
+ software interchange; or,</LI>
+<LI>Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed only
+ for noncommercial distribution and only if you received the program in
+ object code or executable form with such an offer, in accord with
+ Subsection b above.)</LI>
+</OL>
+<P>The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that
+ is normally distributed (in either source or binary form) with the
+ major components (compiler, kernel, and so on) of the operating system
+ on which the executable runs, unless that component itself accompanies
+ the executable.</P>
+<P>If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent access
+ to copy the source code from the same place counts as distribution of
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+</LI>
+<LI>You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt otherwise
+ to copy, modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However,
+ parties who have received copies, or rights, from you under this
+ License will not have their licenses terminated so long as such parties
+ remain in full compliance.</LI>
+<LI>You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying the
+ Program or works based on it.</LI>
+<LI>Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.</LI>
+<LI>If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent license
+ would not permit royalty-free redistribution of the Program by all
+ those who receive copies directly or indirectly through you, then the
+ only way you could satisfy both it and this License would be to refrain
+ entirely from distribution of the Program.
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+</LI>
+<LI>If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License may
+ add an explicit geographical distribution limitation excluding those
+ countries, so that distribution is permitted only in or among countries
+ not thus excluded. In such case, this License incorporates the
+ limitation as if written in the body of this License.</LI>
+<LI>The Free Software Foundation may publish revised and/or new versions
+ of the General Public License from time to time. Such new versions will
+ be similar in spirit to the present version, but may differ in detail
+ to address new problems or concerns.
+<P>Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by
+ the Free Software Foundation.</P>
+</LI>
+<LI>If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by the
+ Free Software Foundation, write to the Free Software Foundation; we
+ sometimes make exceptions for this. Our decision will be guided by the
+ two goals of preserving the free status of all derivatives of our free
+ software and of promoting the sharing and reuse of software generally.</LI>
+</OL>
+<H4>NO WARRANTY</H4>
+<OL START="11">
+<LI>BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.</LI>
+<LI>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+ AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</LI>
+</OL>
+<H4>END OF TERMS AND CONDITIONS</H4>
+
+<!-- NEW PAGE -->
+<H2><A NAME="6_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
+<P>Version 2, June 1991</P>
+<PRE>
+Copyright (C) 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+</PRE>
+<H3><A NAME="6_3_1">Preamble</A></H3>
+<P>The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public Licenses
+ are intended to guarantee your freedom to share and change free
+ software--to make sure the software is free for all its users.</P>
+<P>This license, the Library General Public License, applies to some
+ specially designated Free Software Foundation software, and to any
+ other libraries whose authors decide to use it. You can use it for your
+ libraries, too.</P>
+<P>When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it in
+ new free programs; and that you know you can do these things.</P>
+<P>To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if you
+ distribute copies of the library, or if you modify it.</P>
+<P>For example, if you distribute copies of the library, whether gratis
+ or for a fee, you must give the recipients all the rights that we gave
+ you. You must make sure that they, too, receive or can get the source
+ code. If you link a program with the library, you must provide complete
+ object files to the recipients so that they can relink them with the
+ library, after making changes to the library and recompiling it. And
+ you must show them these terms so they know their rights.</P>
+<P>Our method of protecting your rights has two steps: (1) copyright the
+ library, and (2) offer you this license which gives you legal
+ permission to copy, distribute and/or modify the library.</P>
+<P>Also, for each distributor's protection, we want to make certain that
+ everyone understands that there is no warranty for this free library.
+ If the library is modified by someone else and passed on, we want its
+ recipients to know that what they have is not the original version, so
+ that any problems introduced by others will not reflect on the original
+ authors' reputations.</P>
+<P>Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that companies distributing free
+ software will individually obtain patent licenses, thus in effect
+ transforming the program into proprietary software. To prevent this, we
+ have made it clear that any patent must be licensed for everyone's free
+ use or not licensed at all.</P>
+<P>Most GNU software, including some libraries, is covered by the
+ ordinary GNU General Public License, which was designed for utility
+ programs. This license, the GNU Library General Public License, applies
+ to certain designated libraries. This license is quite different from
+ the ordinary one; be sure to read it in full, and don't assume that
+ anything in it is the same as in the ordinary license.</P>
+<P>The reason we have a separate public license for some libraries is
+ that they blur the distinction we usually make between modifying or
+ adding to a program and simply using it. Linking a program with a
+ library, without changing the library, is in some sense simply using
+ the library, and is analogous to running a utility program or
+ application program. However, in a textual and legal sense, the linked
+ executable is a combined work, a derivative of the original library,
+ and the ordinary General Public License treats it as such.</P>
+<P>Because of this blurred distinction, using the ordinary General
+ Public License for libraries did not effectively promote software
+ sharing, because most developers did not use the libraries. We
+ concluded that weaker conditions might promote sharing better.</P>
+<P>However, unrestricted linking of non-free programs would deprive the
+ users of those programs of all benefit from the free status of the
+ libraries themselves. This Library General Public License is intended
+ to permit developers of non-free programs to use free libraries, while
+ preserving your freedom as a user of such programs to change the free
+ libraries that are incorporated in them. (We have not seen how to
+ achieve this as regards changes in header files, but we have achieved
+ it as regards changes in the actual functions of the Library.) The hope
+ is that this will lead to faster development of free libraries.</P>
+<P>The precise terms and conditions for copying, distribution and
+ modification follow. Pay close attention to the difference between a
+ &quot;work based on the library&quot; and a &quot;work that uses the library&quot;. The
+ former contains code derived from the library, while the latter only
+ works together with the library.</P>
+<P>Note that it is possible for a library to be covered by the ordinary
+ General Public License rather than by this special one.</P>
+<H4>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</H4>
+<P><STRONG>0.</STRONG> This License Agreement applies to any software
+ library which contains a notice placed by the copyright holder or other
+ authorized party saying it may be distributed under the terms of this
+ Library General Public License (also called &quot;this License&quot;). Each
+ licensee is addressed as &quot;you&quot;.</P>
+<P>A &quot;library&quot; means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.</P>
+<P>The &quot;Library&quot;, below, refers to any such software library or work
+ which has been distributed under these terms. A &quot;work based on the
+ Library&quot; means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or translated
+ straightforwardly into another language. (Hereinafter, translation is
+ included without limitation in the term &quot;modification&quot;.)</P>
+<P>&quot;Source code&quot; for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code means
+ all the source code for all modules it contains, plus any associated
+ interface definition files, plus the scripts used to control
+ compilation and installation of the library.</P>
+<P>Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ a program using the Library is not restricted, and output from such a
+ program is covered only if its contents constitute a work based on the
+ Library (independent of the use of the Library in a tool for writing
+ it). Whether that is true depends on what the Library does and what the
+ program that uses the Library does.</P>
+<P><STRONG>1.</STRONG> You may copy and distribute verbatim copies of
+ the Library's complete source code as you receive it, in any medium,
+ provided that you conspicuously and appropriately publish on each copy
+ an appropriate copyright notice and disclaimer of warranty; keep intact
+ all the notices that refer to this License and to the absence of any
+ warranty; and distribute a copy of this License along with the Library.</P>
+<P>You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a fee.</P>
+<P><STRONG>2.</STRONG> You may modify your copy or copies of the Library
+ or any portion of it, thus forming a work based on the Library, and
+ copy and distribute such modifications or work under the terms of
+ Section 1 above, provided that you also meet all of these conditions:</P>
+<OL TYPE="a">
+<LI>The modified work must itself be a software library.
+<P></P>
+</LI>
+<LI>You must cause the files modified to carry prominent notices stating
+ that you changed the files and the date of any change.
+<P></P>
+</LI>
+<LI>You must cause the whole of the work to be licensed at no charge to
+ all third parties under the terms of this License.
+<P></P>
+</LI>
+<LI>If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses the
+ facility, other than as an argument passed when the facility is
+ invoked, then you must make a good faith effort to ensure that, in the
+ event an application does not supply such function or table, the
+ facility still operates, and performs whatever part of its purpose
+ remains meaningful.
+<P>(For example, a function in a library to compute square roots has a
+ purpose that is entirely well-defined independent of the application.
+ Therefore, Subsection 2d requires that any application-supplied
+ function or table used by this function must be optional: if the
+ application does not supply it, the square root function must still
+ compute square roots.)</P>
+</LI>
+</OL>
+<P>These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the Library,
+ and can be reasonably considered independent and separate works in
+ themselves, then this License, and its terms, do not apply to those
+ sections when you distribute them as separate works. But when you
+ distribute the same sections as part of a whole which is a work based
+ on the Library, the distribution of the whole must be on the terms of
+ this License, whose permissions for other licensees extend to the
+ entire whole, and thus to each and every part regardless of who wrote
+ it.</P>
+<P>Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Library.</P>
+<P>In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.</P>
+<P><STRONG>3.</STRONG> You may opt to apply the terms of the ordinary
+ GNU General Public License instead of this License to a given copy of
+ the Library. To do this, you must alter all the notices that refer to
+ this License, so that they refer to the ordinary GNU General Public
+ License, version 2, instead of to this License. (If a newer version
+ than version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not make any
+ other change in these notices.</P>
+<P>Once this change is made in a given copy, it is irreversible for that
+ copy, so the ordinary GNU General Public License applies to all
+ subsequent copies and derivative works made from that copy.</P>
+<P>This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.</P>
+<P><STRONG>4.</STRONG> You may copy and distribute the Library (or a
+ portion or derivative of it, under Section 2) in object code or
+ executable form under the terms of Sections 1 and 2 above provided that
+ you accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections 1
+ and 2 above on a medium customarily used for software interchange.</P>
+<P>If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy the
+ source code from the same place satisfies the requirement to distribute
+ the source code, even though third parties are not compelled to copy
+ the source along with the object code.</P>
+<P><STRONG>5.</STRONG> A program that contains no derivative of any
+ portion of the Library, but is designed to work with the Library by
+ being compiled or linked with it, is called a &quot;work that uses the
+ Library&quot;. Such a work, in isolation, is not a derivative work of the
+ Library, and therefore falls outside the scope of this License.</P>
+<P>However, linking a &quot;work that uses the Library&quot; with the Library
+ creates an executable that is a derivative of the Library (because it
+ contains portions of the Library), rather than a &quot;work that uses the
+ library&quot;. The executable is therefore covered by this License. Section
+ 6 states terms for distribution of such executables.</P>
+<P>When a &quot;work that uses the Library&quot; uses material from a header file
+ that is part of the Library, the object code for the work may be a
+ derivative work of the Library even though the source code is not.
+ Whether this is true is especially significant if the work can be
+ linked without the Library, or if the work is itself a library. The
+ threshold for this to be true is not precisely defined by law.</P>
+<P>If such an object file uses only numerical parameters, data structure
+ layouts and accessors, and small macros and small inline functions (ten
+ lines or less in length), then the use of the object file is
+ unrestricted, regardless of whether it is legally a derivative work.
+ (Executables containing this object code plus portions of the Library
+ will still fall under Section 6.)</P>
+<P>Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section 6.
+ Any executables containing that work also fall under Section 6, whether
+ or not they are linked directly with the Library itself.</P>
+<P><STRONG>6.</STRONG> As an exception to the Sections above, you may
+ also compile or link a &quot;work that uses the Library&quot; with the Library to
+ produce a work containing portions of the Library, and distribute that
+ work under terms of your choice, provided that the terms permit
+ modification of the work for the customer's own use and reverse
+ engineering for debugging such modifications.</P>
+<P>You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered by
+ this License. You must supply a copy of this License. If the work
+ during execution displays copyright notices, you must include the
+ copyright notice for the Library among them, as well as a reference
+ directing the user to the copy of this License. Also, you must do one
+ of these things:</P>
+<OL TYPE="a">
+<LI>Accompany the work with the complete corresponding machine-readable
+ source code for the Library including whatever changes were used in the
+ work (which must be distributed under Sections 1 and 2 above); and, if
+ the work is an executable linked with the Library, with the complete
+ machine-readable &quot;work that uses the Library&quot;, as object code and/or
+ source code, so that the user can modify the Library and then relink to
+ produce a modified executable containing the modified Library. (It is
+ understood that the user who changes the contents of definitions files
+ in the Library will not necessarily be able to recompile the
+ application to use the modified definitions.)
+<P></P>
+</LI>
+<LI>Accompany the work with a written offer, valid for at least three
+ years, to give the same user the materials specified in Subsection 6a,
+ above, for a charge no more than the cost of performing this
+ distribution.
+<P></P>
+</LI>
+<LI>If distribution of the work is made by offering access to copy from
+ a designated place, offer equivalent access to copy the above specified
+ materials from the same place.
+<P></P>
+</LI>
+<LI>Verify that the user has already received a copy of these materials
+ or that you have already sent this user a copy.</LI>
+</OL>
+<P>For an executable, the required form of the &quot;work that uses the
+ Library&quot; must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special exception,
+ the source code distributed need not include anything that is normally
+ distributed (in either source or binary form) with the major components
+ (compiler, kernel, and so on) of the operating system on which the
+ executable runs, unless that component itself accompanies the
+ executable.</P>
+<P>It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you cannot
+ use both them and the Library together in an executable that you
+ distribute.</P>
+<P><STRONG>7.</STRONG> You may place library facilities that are a work
+ based on the Library side-by-side in a single library together with
+ other library facilities not covered by this License, and distribute
+ such a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:</P>
+<OL TYPE="a">
+<LI>Accompany the combined library with a copy of the same work based on
+ the Library, uncombined with any other library facilities. This must be
+ distributed under the terms of the Sections above.
+<P></P>
+</LI>
+<LI>Give prominent notice with the combined library of the fact that
+ part of it is a work based on the Library, and explaining where to find
+ the accompanying uncombined form of the same work.</LI>
+</OL>
+<P><STRONG>8.</STRONG> You may not copy, modify, sublicense, link with,
+ or distribute the Library except as expressly provided under this
+ License. Any attempt otherwise to copy, modify, sublicense, link with,
+ or distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full compliance.</P>
+<P><STRONG>9.</STRONG> You are not required to accept this License,
+ since you have not signed it. However, nothing else grants you
+ permission to modify or distribute the Library or its derivative works.
+ These actions are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work based
+ on the Library), you indicate your acceptance of this License to do so,
+ and all its terms and conditions for copying, distributing or modifying
+ the Library or works based on it.</P>
+<P><STRONG>10.</STRONG> Each time you redistribute the Library (or any
+ work based on the Library), the recipient automatically receives a
+ license from the original licensor to copy, distribute, link with or
+ modify the Library subject to these terms and conditions. You may not
+ impose any further restrictions on the recipients' exercise of the
+ rights granted herein. You are not responsible for enforcing compliance
+ by third parties to this License.</P>
+<P><STRONG>11.</STRONG> If, as a consequence of a court judgment or
+ allegation of patent infringement or for any other reason (not limited
+ to patent issues), conditions are imposed on you (whether by court
+ order, agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this License. If
+ you cannot distribute so as to satisfy simultaneously your obligations
+ under this License and any other pertinent obligations, then as a
+ consequence you may not distribute the Library at all. For example, if
+ a patent license would not permit royalty-free redistribution of the
+ Library by all those who receive copies directly or indirectly through
+ you, then the only way you could satisfy both it and this License would
+ be to refrain entirely from distribution of the Library.</P>
+<P>If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply, and the section as a whole is intended to apply in other
+ circumstances.</P>
+<P>It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system which is implemented
+ by public license practices. Many people have made generous
+ contributions to the wide range of software distributed through that
+ system in reliance on consistent application of that system; it is up
+ to the author/donor to decide if he or she is willing to distribute
+ software through any other system and a licensee cannot impose that
+ choice.</P>
+<P>This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.</P>
+<P><STRONG>12.</STRONG> If the distribution and/or use of the Library is
+ restricted in certain countries either by patents or by copyrighted
+ interfaces, the original copyright holder who places the Library under
+ this License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only in or
+ among countries not thus excluded. In such case, this License
+ incorporates the limitation as if written in the body of this License.</P>
+<P><STRONG>13.</STRONG> The Free Software Foundation may publish revised
+ and/or new versions of the Library General Public License from time to
+ time. Such new versions will be similar in spirit to the present
+ version, but may differ in detail to address new problems or concerns.</P>
+<P>Each version is given a distinguishing version number. If the Library
+ specifies a version number of this License which applies to it and &quot;any
+ later version&quot;, you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Library does not specify a license
+ version number, you may choose any version ever published by the Free
+ Software Foundation.</P>
+<P><STRONG>14.</STRONG> If you wish to incorporate parts of the Library
+ into other free programs whose distribution conditions are incompatible
+ with these, write to the author to ask for permission. For software
+ which is copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free status
+ of all derivatives of our free software and of promoting the sharing
+ and reuse of software generally.</P>
+<P><STRONG>NO WARRANTY</STRONG></P>
+<P><STRONG>15.</STRONG> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE,
+ THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT
+ WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
+ OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU
+ ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</P>
+<P><STRONG>16.</STRONG> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
+ AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
+ MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGES.</P>
+<H4>END OF TERMS AND CONDITIONS</H4>
+</BODY>
+</HTML>
diff --git a/doc/sum.pdf b/doc/sum.pdf
new file mode 100644
index 000000000..8e5a76bef
--- /dev/null
+++ b/doc/sum.pdf
Binary files differ
diff --git a/doc/sum.shtml b/doc/sum.shtml
new file mode 100644
index 000000000..9ae4a01f4
--- /dev/null
+++ b/doc/sum.shtml
@@ -0,0 +1,969 @@
+<HTML>
+<HEAD>
+ <META NAME="Description" CONTENT="Common UNIX Printing System Software Users Manual">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.22">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Users Manual</TITLE>
+</HEAD>
+<BODY>
+
+<H1 ALIGN="RIGHT">Preface</H1>
+
+<P>This software users manual describes how to use the Common UNIX Printing
+System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.22.
+
+<EMBED SRC="system-overview.shtml">
+
+<!-- NEED 2in -->
+<H2>Document Overview</H2>
+
+<P>This software users manual is organized into the following sections:</P>
+
+<UL>
+ <LI><A HREF="#OVERVIEW">1 - Printing System Overview</A>
+ <LI><A HREF="#USING_SYSTEM">2 - Using the Printing System</A>
+ <LI><A HREF="#STANDARD_OPTIONS">3 - Standard Printer Options</A>
+ <LI><A HREF="#SAVING_OPTIONS">4 - Saving Printer Options and Defaults</A>
+ <LI><A HREF="#LICENSE">A - Software License Agreement</A>
+</UL>
+
+<H2>Notation Conventions</H2>
+
+<P>Various font and syntax conventions are used in this guide. Examples and
+their meanings and uses are explained below:
+
+<CENTER><TABLE WIDTH="80%">
+<TR>
+ <TH>Example</TH>
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+ <TH>Description</TH>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><CODE>lpstat</CODE><BR>
+ <CODE>lpstat(1)</CODE></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>The names of commands; the first mention of a command or
+ function in a chapter is followed by a manual page section
+ number.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD><VAR>/var</VAR><BR>
+ <VAR>/usr/share/cups/data/testprint.ps</VAR></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>File and directory names.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><TT>Request ID is Printer-123</TT></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Screen output.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD NOWRAP><KBD>lp -d printer filename ENTER</KBD></TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Literal user input; special keys like <KBD>ENTER</KBD> are
+ in ALL CAPS.</TD>
+</TR>
+<TR><TD>&nbsp;</TD></TR>
+<TR VALIGN="TOP">
+ <TD>12.3</TD>
+
+ <TD>&nbsp;&nbsp;&nbsp;</TD>
+
+ <TD>Numbers in the text are written using the period (.) to indicate
+ the decimal point.</TD>
+</TR>
+</TABLE></CENTER>
+
+<!-- NEED 3in -->
+<H2>Abbreviations</H2>
+
+The following abbreviations are used throughout this manual:
+
+<UL>
+<DL>
+
+ <DT>kb
+ <DD>Kilobytes, or 1024 bytes<BR>&nbsp;
+
+ <DT>Mb
+ <DD>Megabytes, or 1048576 bytes<BR>&nbsp;
+
+ <DT>Gb
+ <DD>Gigabytes, or 1073741824 bytes<BR>&nbsp;
+
+</DL>
+</UL>
+
+<H2>Other References</H2>
+
+<UL>
+<DL>
+
+ <DT>CUPS Software Administrators Manual
+
+ <DD>An administration guide for the CUPS software.<BR>&nbsp;
+
+ <DT>CUPS Software Programmers Manual
+
+ <DD>A programmer guide for interfacing with and/or extending the CUPS
+ software.<BR>&nbsp;
+
+</DL>
+</UL>
+
+
+<EMBED SRC="printing-overview.shtml">
+
+
+<H1 ALIGN="RIGHT"><A NAME="USING_SYSTEM">2 - Using the Printing System</A></H1>
+
+<P>This chapter shows you how to submit, query, and cancel print jobs to
+different printers.
+
+<H2>Submitting Files for Printing</H2>
+
+<P>CUPS provides both the System V (<CODE>lp(1)</CODE>) and Berkeley
+(<CODE>lpr(1)</CODE>) printing commands. Type the following command to
+print a file to the default (or only) printer on the system:
+
+<UL><PRE>
+<B>lp filename ENTER</B>
+</PRE></UL>
+
+<P>or:
+
+<UL><PRE>
+<B>lpr filename ENTER</B>
+</PRE></UL>
+
+<P>CUPS understands many different types of files directly, including
+PostScript and image files. This allows you to print from inside your
+applications or at the command-line, whichever is most convenient!
+
+<H2>Choosing a Printer</H2>
+
+<P>Many systems will have more than one printer available to the user. These
+printers can be attached to the local system via a parallel, serial, or USB
+port, or available over the network.
+
+<P>Use the <CODE>lpstat(1)</CODE> command to see a list of available printers:
+
+<UL><PRE>
+<B>lpstat -p -d ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>-p</CODE> option specifies that you want to see a
+list of printers, and the <CODE>-d</CODE> option reports the
+current default printer or class.
+
+<P>Use the <CODE>-d</CODE> option with the <CODE>lp</CODE> command to
+print to a specific printer:
+
+<UL><PRE>
+<B>lp -d printer filename ENTER</B>
+</PRE></UL>
+
+<P>or the <CODE>-P</CODE> option with the <CODE>lpr</CODE> command:
+
+<UL><PRE>
+<B>lpr -P printer filename ENTER</B>
+</PRE></UL>
+
+<H2>Setting Printer Options</H2>
+
+<P>For many types of files, the default printer options may be sufficient for
+your needs. However, there may be times when you need to change the options
+for a particular file you are printing.
+
+<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands allow you to pass
+printer options using the <CODE>-o</CODE> option:
+
+<UL><PRE>
+<B>lp -o landscape -o scaling=75 -o media=A4 filename.jpg ENTER</B>
+<B>lpr -o landscape -o scaling=75 -o media=A4 filename.jpg ENTER</B>
+</PRE></UL>
+
+<P>The available printer options vary depending on the printer. The standard
+options are described in <A HREF="#STANDARD_OPTIONS">Chapter 3, "Standard
+Printing Options"</A>.
+
+<H2>Printing Multiple Copies</H2>
+
+<P>Both the <CODE>lp</CODE> and <CODE>lpr</CODE> commands have options for
+printing more than one copy of a file:
+
+<UL><PRE>
+<B>lp -n <I>num-copies</I> filename ENTER</B>
+<B>lpr -#<I>num-copies</I> filename ENTER</B>
+</PRE></UL>
+
+<P>Copies are normally <I>not</I> collated for you. Use the <CODE>-o
+Collate=True</CODE> option to get collated copies :
+
+<UL><PRE>
+<B>lp -n <I>num-copies</I> -o Collate=True filename ENTER</B>
+<B>lpr -#<I>num-copies</I> -o Collate=True filename ENTER</B>
+</PRE></UL>
+
+<!-- NEED 3in -->
+<H2>Checking the Printer Status from the Command-Line</H2>
+
+<P>The <CODE>lpstat</CODE> command can be used to check for jobs that you
+have submitted for printing:
+
+<UL><PRE>
+<B>lpstat ENTER</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+</PRE></UL>
+
+<P>The jobs are listed in the order they will be printed. Use the
+<CODE>-p</CODE> option to see which files and printers are active:
+
+<UL><PRE>
+<B>lpstat -p ENTER</B>
+printer DeskJet now printing DeskJet-1.
+</PRE></UL>
+
+<!-- NEED 2in -->
+<P>Use the <CODE>-o</CODE> and <CODE>-p</CODE> options together to show
+the jobs and the printers:
+
+<UL><PRE>
+<B>lpstat -o -p ENTER</B>
+Printer-1 johndoe 4427776
+Printer-2 johndoe 15786
+Printer-3 johndoe 372842
+printer DeskJet now printing DeskJet-1.
+</PRE></UL>
+
+<H2>Checking the Printer Status from the Web</H2>
+
+<P>Since CUPS uses the Internet Printing Protocol, it is also a
+fully-functional web server. To use your web browser to monitor the
+printers on your system, open the URL:
+
+<UL><PRE>
+<A HREF="http://localhost:631">http://localhost:631</A>
+</PRE></UL>
+
+<P>From there you can view the status of classes, jobs, and printers
+with the click of a button!
+
+<H2>Canceling a Print Job</H2>
+
+<P>The <CODE>cancel(1)</CODE> and <CODE>lprm(1)</CODE> commands cancel
+a print job:
+
+<UL><PRE>
+<B>cancel <I>job-id</I> ENTER</B>
+<B>lprm <I>job-id</I> ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>job-id</CODE> is the number that was reported to you by
+the <CODE>lp</CODE> or <CODE>lpstat</CODE> commands.
+
+
+<H1 ALIGN="RIGHT"><A NAME="STANDARD_OPTIONS">3 - Standard Printer Options</A></H1>
+
+<P>This chapter describes the standard printer options that are available
+when printing with the <CODE>lp</CODE> and <CODE>lpr</CODE> commands.
+
+<H2>General Options</H2>
+
+<P>The following options apply when printing all types of files.
+
+<!-- NEED 2in -->
+<H3>Selecting the Media Size, Type, and Source</H3>
+
+<P>The <CODE>-o media=xyz</CODE> option sets the media size, type,
+and/or source:
+
+<UL><PRE>
+<B>lp -o media=Letter filename ENTER</B>
+<B>lp -o media=Letter,MultiPurpose filename ENTER</B>
+<B>lpr -o media=Letter,Transparency filename ENTER</B>
+<B>lpr -o media=Letter,MultiPurpose,Transparency filename ENTER</B>
+</PRE></UL>
+
+<!-- NEED 3in -->
+<P>The available media sizes, types, and sources depend on the printer, but
+most support the following options (case is not significant):
+
+<UL>
+
+ <LI><CODE>Letter</CODE> - US Letter (8.5x11 inches, or 216x279mm)
+
+ <LI><CODE>Legal</CODE> - US Legal (8.5x14 inches, or 216x356mm)
+
+ <LI><CODE>A4</CODE> - ISO A4 (8.27x11.69 inches, or 210x297mm)
+
+ <LI><CODE>COM10</CODE> - US #10 Envelope (9.5x4.125 inches, or
+ 241x105mm)
+
+ <LI><CODE>DL</CODE> - ISO DL Envelope (8.66x4.33 inches, or 220x110mm)
+
+ <LI><CODE>Transparency</CODE> - Transparency media type or source
+
+ <LI><CODE>Upper</CODE> - Upper paper tray
+
+ <LI><CODE>Lower</CODE> - Lower paper tray
+
+ <LI><CODE>MultiPurpose</CODE> - Multi-purpose paper tray
+
+ <LI><CODE>LargeCapacity</CODE> - Large capacity paper tray
+
+</UL>
+
+<P>The actual options supported are defined in the printer's PPD file
+in the <CODE>PageSize</CODE>, <CODE>InputSlot</CODE>, and
+<CODE>MediaType</CODE> options.
+
+<H3>Setting the Orientation</H3>
+
+<P>The <CODE>-o landscape</CODE> option will rotate the page 90 degrees
+to print in landscape orientation:
+
+<UL><PRE>
+<B>lp -o landscape filename ENTER</B>
+<B>lpr -o landscape filename ENTER</B>
+</PRE></UL>
+
+<H3>Printing On Both Sides of the Paper</H3>
+
+<P>The <CODE>-o sides=two-sided-short-edge</CODE> and <CODE>-o
+sides=two-sided-long-edge</CODE> options will enable duplexing on the
+printer, if the printer supports it. The <CODE>-o
+sides=two-sided-short-edge</CODE> option is suitable for landscape
+pages, while the <CODE>-o sides=two-sided-long-edge</CODE> option is
+suitable for portrait pages:
+
+<UL><PRE>
+<B>lp -o sides=two-sided-short-edge filename ENTER</B>
+<B>lp -o sides=two-sided-long-edge filename ENTER</B>
+<B>lpr -o sides=two-sided-long-edge filename ENTER</B>
+</PRE></UL>
+
+<P>The default is to print single-sided:
+
+<UL><PRE>
+<B>lp -o sides=one-sided filename ENTER</B>
+<B>lpr -o sides=one-sided filename ENTER</B>
+</PRE></UL>
+
+<H2>Banner Options</H2>
+
+<P>The following options apply when printing all types of files.
+
+<H3>Selecting the Banner Page(s)</H3>
+
+<P>The <CODE>-o jobsheets=start,end</CODE> option sets the banner page(s) to
+use for a job:
+
+<UL><PRE>
+<B>lp -o job-sheets=none filename ENTER</B>
+<B>lp -o job-sheets=standard filename ENTER</B>
+<B>lpr -o job-sheets=classified,classified filename ENTER</B>
+</PRE></UL>
+
+<P>If only one banner file is specified, it will be printed before the
+files in the job. If a second banner file is specified, it is printed after
+the files in the job.
+
+<P>The available banner pages depend on the local system configuration; CUPS
+includes the following banner files:
+
+<UL>
+
+ <LI><CODE>none</CODE> - Do not produce a banner page.
+
+ <LI><CODE>classified</CODE> - A banner page with a "classified"
+ label at the top and bottom.
+
+ <LI><CODE>confidential</CODE> - A banner page with a
+ "confidential" label at the top and bottom.
+
+ <LI><CODE>secret</CODE> - A banner page with a "secret" label
+ at the top and bottom.
+
+ <LI><CODE>standard</CODE> - A banner page with no label at the
+ top and bottom.
+
+ <LI><CODE>topsecret</CODE> - A banner page with a "top secret"
+ label at the top and bottom.
+
+ <LI><CODE>unclassified</CODE> - A banner page with an
+ "unclassified" label at the top and bottom.
+
+</UL>
+
+<H2>Document Options</H2>
+
+<P>The following options apply when printing all types of files.
+
+<H3>Selecting a Range of Pages</H3>
+
+<P>The <CODE>-o page-ranges=pages</CODE> option selects a range of
+pages for printing:
+
+<UL><PRE>
+<B>lp -o page-ranges=1 filename ENTER</B>
+<B>lp -o page-ranges=1-4 filename ENTER</B>
+<B>lp -o page-ranges=1-4,7,9-12 filename ENTER</B>
+<B>lpr -o page-ranges=1-4,7,9-12 filename ENTER</B>
+</PRE></UL>
+
+<P>As shown above, the <CODE>pages</CODE> value can be a single page, a
+range of pages, or a collection of page numbers and ranges separated by
+commas. The pages will always be printed in ascending order, regardless
+of the order of the pages in the <CODE>page-ranges</CODE> option.
+
+<P>The default is to print all pages.
+
+<H3>Selecting Even or Odd Pages</H3>
+
+<P>Use the <CODE>-o page-set=set</CODE> option to select the even or odd pages:
+
+<UL><PRE>
+<B>lp -o page-set=odd filename ENTER</B>
+<B>lp -o page-set=even filename ENTER</B>
+<B>lpr -o page-set=even filename ENTER</B>
+</PRE></UL>
+
+<P>The default is to print all pages.
+
+<H3>Setting the Output Order</H3>
+
+<P>The the <CODE>-o outputorder=order</CODE> option to set the output
+order of all pages:
+
+<UL><PRE>
+<B>lp -o outputorder=normal filename ENTER</B>
+<B>lp -o outputorder=reverse filename ENTER</B>
+<B>lpr -o outputorder=reverse filename ENTER</B>
+</PRE></UL>
+
+<H3>N-Up Printing</H3>
+
+<P>The <CODE>-o number-up=value</CODE> option selects N-Up printing.
+N-Up printing places multiple document pages on a single printed page.
+CUPS supports 1, 2, 4, 6, 9, and 16-Up formats; the default format is
+1-Up:
+
+<UL><PRE>
+<B>lp -o number-up=1 filename ENTER</B>
+<B>lp -o number-up=2 filename ENTER</B>
+<B>lp -o number-up=4 filename ENTER</B>
+<B>lpr -o number-up=16 filename ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>-o page-border=value</CODE> option chooses the border
+to draw around each page:
+
+<UL>
+ <LI><CODE>-o page-border=double</CODE>; draw two hairline borders around each page</LI>
+ <LI><CODE>-o page-border=double-thick</CODE>; draw two 1pt borders around each page</LI>
+ <LI><CODE>-o page-border=none</CODE>; do not draw a border (default)</LI>
+ <LI><CODE>-o page-border=single</CODE>; draw one hairline border around each page</LI>
+ <LI><CODE>-o page-border=single-thick</CODE>; draw one 1pt border around each page</LI>
+</UL>
+
+<P>The <CODE>-o number-up-layout=value</CODE> option chooses the layout
+of the pages on each output page:
+
+<UL>
+ <LI><CODE>-o number-up-layout=btlr</CODE>; Bottom to top, left to right</LI>
+ <LI><CODE>-o number-up-layout=btrl</CODE>; Bottom to top, right to left</LI>
+ <LI><CODE>-o number-up-layout=lrbt</CODE>; Left to right, bottom to top</LI>
+ <LI><CODE>-o number-up-layout=lrtb</CODE>; Left to right, top to bottom (default)</LI>
+ <LI><CODE>-o number-up-layout=rlbt</CODE>; Right to left, bottom to top</LI>
+ <LI><CODE>-o number-up-layout=rltb</CODE>; Right to left, top to bottom</LI>
+ <LI><CODE>-o number-up-layout=tblr</CODE>; Top to bottom, left to right</LI>
+ <LI><CODE>-o number-up-layout=tbrl</CODE>; Top to bottom, right to left</LI>
+</UL>
+
+<H3>Mirroring Prints</H3>
+
+<P>You can mirror a print using the <CODE>-o mirror</CODE> option:
+
+<UL><PRE>
+<B>lp -o mirror filename ENTER</B>
+<B>lpr -o mirror filename ENTER</B>
+</PRE></UL>
+
+<P>This is useful for printing mirrored pages on transfer paper, for
+T shirts, mugs, etc.
+
+<H3>Setting the Brightness</H3>
+
+<P>You can control the overall brightness of the printed output using the
+<CODE>-o brightness=percent</CODE> option:
+
+<UL><PRE>
+<B>lp -o brightness=120 filename ENTER</B>
+<B>lpr -o brightness=120 filename ENTER</B>
+</PRE></UL>
+
+<P>Values greater than 100 will lighten the print, while values less than
+100 will darken it.
+
+<H3>Setting the Gamma Correction</H3>
+
+<P>You can control the overall gamma correction of the printed output
+using the <CODE>-o gamma=value</CODE> option:
+
+<UL><PRE>
+<B>lp -o gamma=1700 filename ENTER</B>
+<B>lpr -o gamma=1700 filename ENTER</B>
+</PRE></UL>
+
+<P>Values greater than 1000 will lighten the print, while values less
+than 1000 will darken it. The default gamma is 1000.
+
+<H2>Text Options</H2>
+
+<P>The following options apply when printing text files.
+
+<H3>Setting the Number of Characters Per Inch</H3>
+
+<P>The <CODE>-o cpi=value</CODE> option sets the number of characters per inch:
+
+<UL><PRE>
+<B>lp -o cpi=10 filename ENTER</B>
+<B>lp -o cpi=12 filename ENTER</B>
+<B>lpr -o cpi=17 filename ENTER</B>
+</PRE></UL>
+
+<P>The default characters per inch is 10.
+
+<H3>Setting the Number of Lines Per Inch</H3>
+
+<P>The <CODE>-o lpi=value</CODE> option sets the number of lines per inch:
+
+<UL><PRE>
+<B>lp -o lpi=6 filename ENTER</B>
+<B>lpr -o lpi=8 filename ENTER</B>
+</PRE></UL>
+
+<P>The default lines per inch is 6.
+
+<H3>Setting the Number of Columns</H3>
+
+<P>The <CODE>-o columns=value</CODE> option sets the number of text columns:
+
+<UL><PRE>
+<B>lp -o columns=2 filename ENTER</B>
+<B>lpr -o columns=3 filename ENTER</B>
+</PRE></UL>
+
+<P>The default number of columns is 1.
+
+<H3>Setting the Page Margins</H3>
+
+<P>Normally the page margins are set to the hard limits of the printer.
+Use the <CODE>-o page-left=value</CODE>, <CODE>-o
+page-right=value</CODE>, <CODE>-o page-top=value</CODE>, and <CODE>-o
+page-bottom=value</CODE> options to adjust the page margins:
+
+<UL><PRE>
+<B>lp -o page-left=<I>value</I> filename ENTER</B>
+<B>lp -o page-right=<I>value</I> filename ENTER</B>
+<B>lp -o page-top=<I>value</I> filename ENTER</B>
+<B>lp -o page-bottom=<I>value</I> filename ENTER</B>
+<B>lpr -o page-bottom=<I>value</I> filename ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>value</CODE> argument is the margin in points; each point is 1/72 inch
+or 0.35mm.
+
+<H3>Pretty Printing</H3>
+
+<P>The <CODE>-o prettyprint</CODE> option puts a header at the top of each page with the
+page number, job title (usually the filename), and the date. Also, C and C++
+keywords are highlighted, and comment lines are italicized:
+
+<UL><PRE>
+<B>lp -o prettyprint filename ENTER</B>
+<B>lpr -o prettyprint filename ENTER</B>
+</PRE></UL>
+
+<H2>Image Options</H2>
+
+<P>The following options apply when printing image files.
+
+<H3>Positioning the Image</H3>
+
+<P>The <CODE>-o position=name</CODE> option specifies the position of the
+image on the page:
+
+<UL>
+
+ <LI><CODE>center</CODE> - Center the image on the page (default)
+
+ <LI><CODE>top</CODE> - Print the image centered at the top of the page
+
+ <LI><CODE>left</CODE> - Print the image centered on the left of page
+
+ <LI><CODE>right</CODE> - Print the image centered on the right of the page
+
+ <LI><CODE>top-left</CODE> - Print the image at the top left corner of
+ the page
+
+ <LI><CODE>top-right</CODE> - Print the image at the top right corner of
+ the page
+
+ <LI><CODE>bottom</CODE> - Print the image centered at the bottom of
+ the page
+
+ <LI><CODE>bottom-left</CODE> - Print the image at the bottom left
+ corner of the page
+
+ <LI><CODE>bottom-right</CODE> - Print the image at the bottom right
+ corner of the page
+
+</UL>
+
+<H3>Scaling the Image</H3>
+
+<P>The <CODE>-o scaling=percent</CODE>, <CODE>-o
+ppi=value</CODE>, and <CODE>-o natural-scaling=percent</CODE>
+options change the size of a printed image:
+
+<UL><PRE>
+<B>lp -o scaling=<I>percent</I> filename ENTER</B>
+<B>lp -o ppi=<I>value</I> filename ENTER</B>
+<B>lpr -o natural-scaling=<I>percent</I> filename ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>scaling=percent</CODE> value is a number from 1 to 800
+specifying the size in relation to the page (<I>not</I> the image.) A
+scaling of 100 percent will fill the page as completely as the image
+aspect ratio allows. A scaling of 200 percent will print on up to 4
+pages.
+
+<P>The <CODE>ppi=value</CODE> value is a number from 1 to 1200 specifying the
+resolution of the image in pixels per inch. An image that is 3000x2400
+pixels will print 10x8 inches at 300 pixels per inch, for example. If
+the specified resolution makes the image larger than the page, multiple
+pages will be printed to satisfy the request.
+
+<P>The <CODE>natural-scaling=percent</CODE> value is a number
+from 1 to 800 specifying the size in relation to the natural
+image size. A scaling of 100 percent will print the image at its
+natural size, while a scaling of 50 percent will print the image
+at half its natural size. If the specified scaling makes the
+image larger than the page, multiple pages will be printed to
+satisfy the request.
+
+<H3>Adjusting the Hue (Tint) of an Image</H3>
+
+<P>The <CODE>-o hue=value</CODE> option will adjust the hue of the
+printed image, much like the tint control on your television:
+
+<UL><PRE>
+<B>lp -o hue=<I>value</I> filename ENTER</B>
+<B>lpr -o hue=<I>value</I> filename ENTER</B>
+</PRE></UL>
+
+<!-- NEED 3in -->
+<P>The <CODE>value</CODE> argument is a number from -360 to 360 and represents the
+color hue rotation. The following table summarizes the change you'll see with
+different colors:
+
+<CENTER><TABLE WIDTH="50%" BORDER="1">
+<TR>
+ <TH>Original</TH>
+ <TH>hue=-45</TH>
+ <TH>hue=45</TH>
+</TR>
+<TR>
+ <TD>Red</TD>
+ <TD>Purple</TD>
+ <TD>Yellow-orange</TD>
+</TR>
+<TR>
+ <TD>Green</TD>
+ <TD>Yellow-green</TD>
+ <TD>Blue-green</TD>
+</TR>
+<TR>
+ <TD>Yellow</TD>
+ <TD>Orange</TD>
+ <TD>Green-yellow</TD>
+</TR>
+<TR>
+ <TD>Blue</TD>
+ <TD>Sky-blue</TD>
+ <TD>Purple</TD>
+</TR>
+<TR>
+ <TD>Magenta</TD>
+ <TD>Indigo</TD>
+ <TD>Crimson</TD>
+</TR>
+<TR>
+ <TD>Cyan</TD>
+ <TD>Blue-green</TD>
+ <TD>Light-navy-blue</TD>
+</TR>
+</TABLE></CENTER>
+
+<P>The default hue adjustment is 0.
+
+<H3>Adjusting the Saturation (Color) of an Image</H3>
+
+<P>The <CODE>-o saturation=percent</CODE> option adjusts the saturation
+of the colors in an image, much like the color knob on your television:
+
+<UL><PRE>
+<B>lp -o saturation=<I>percent</I> filename ENTER</B>
+<B>lpr -o saturation=<I>percent</I> filename ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>percent</CODE> argument specifies the color saturation
+from 0 to 200. A color saturation of 0 produces a black-and-white
+print, while a value of 200 will make the colors extremely intense.
+
+<P>The default saturation is 100.
+
+<!-- NEED 4in -->
+<H2>HP-GL/2 Options</H2>
+
+<P>The following options apply to HP-GL/2 files.
+
+<H3>Printing in Black</H3>
+
+<P>The <CODE>-o blackplot</CODE> option specifies that all pens should
+plot in black:
+
+<UL><PRE>
+<B>lp -o blackplot filename ENTER</B>
+<B>lpr -o blackplot filename ENTER</B>
+</PRE></UL>
+
+<P>The default is to use the colors defined in the plot file or the
+standard pen colors defined in the HP-GL/2 reference manual from
+Hewlett Packard.
+
+<H3>Fitting the Plot on the Page</H3>
+
+<P>The <CODE>-o fitplot</CODE> option specifies that the plot should be
+scaled to fit on the page:
+
+<UL><PRE>
+<B>lp -o fitplot filename ENTER</B>
+<B>lpr -o fitplot filename ENTER</B>
+</PRE></UL>
+
+<P>The default is to use the absolute distances specified in the plot
+file.
+
+<CENTER><TABLE WIDTH="80%" CELLPADDING="5" BORDER="1" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>This feature depends upon an accurate plot size (<CODE>PS</CODE>)
+ command in the HP-GL/2 file. If no plot size is given in the file
+ than the HP-GL/2 filter assumes the plot is ANSI E size.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Setting the Default Pen Width</H3>
+
+<P>The <CODE>-o penwidth=value</CODE> option specifies the default pen
+width for HP-GL/2 files:
+
+<UL><PRE>
+<B>lp -o penwidth=<I>value</I> filename ENTER</B>
+<B>lpr -o penwidth=<I>value</I> filename ENTER</B>
+</PRE></UL>
+
+<P>The pen width <CODE>value</CODE> specifies the pen width in micrometers.
+The default value of 1000 produces lines that are 1 millimeter in width.
+Specifying a pen width of 0 produces lines that are exactly 1 pixel wide.
+
+<CENTER><TABLE WIDTH="80%" CELLPADDING="5" BORDER="1" BGCOLOR="#cccccc">
+<TR>
+ <TD>
+ <B>NOTE:</B>
+
+ <P>This option is ignored when the pen widths are set in the
+ plot file.
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>Raw or Unfiltered Output</H2>
+
+<P>The <CODE>-o raw</CODE> option allows you to send files directly to
+a printer without filtering. This is sometimes required when printing
+from applications that provide their own "printer drivers" for your
+printer:
+
+<UL><PRE>
+<B>lp -o raw filename ENTER</B>
+<B>lpr -o raw filename ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>-l</CODE> option can also be used with the
+<CODE>lpr</CODE> command to send files directly to a printer:
+
+<UL><PRE>
+<B>lpr -l filename ENTER</B>
+</PRE></UL>
+
+
+<H1 ALIGN="RIGHT"><A NAME="SAVING_OPTIONS">4 - Saving Printer Options and Defaults</A></H1>
+
+<P>This chapter describes how to save printer options for your printer and
+set your own default printer.
+
+<H2>Printer Options</H2>
+
+<P>Each printer supports a large number of options, which you learned about
+in <A HREF="#STANDARD_OPTIONS">Chapter 3, "Standard Printer Options"</A>.
+Rather than specifying these options each time you print a file, CUPS allows
+you to save them as "default" options for the printer.
+
+<P>The <CODE>lpoptions(1)</CODE> command saves the options for your printers.
+Like the <CODE>lp</CODE> and <CODE>lpr</CODE> commands, it accepts printer
+options using the <CODE>-o</CODE> argument:
+
+<UL><PRE>
+<B>lpoptions -o prettyprint ENTER</B>
+<B>lpoptions -o media=A4 -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -o media=Legal -o scaling=100 ENTER</B>
+</PRE></UL>
+
+<P>Once saved, any <CODE>lp</CODE> or <CODE>lpr</CODE> command will
+use them when you print.
+
+<CENTER><TABLE WIDTH="80%" BORDER="1" BGCOLOR="#cccccc" CELLPADDING="5" CELLSPACING="0">
+<TR>
+ <TD><B>Note:</B>
+
+ <P>Running the <CODE>lpoptions</CODE> command as the
+ root user (or any user with a UID of 0) will set the
+ default options for all users. The root account does not
+ have its own set of default options.</P>
+
+ </TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>Setting Options for a Specific Printer</H2>
+
+<P>The previous example shows how to set the options for the default
+printer. The <CODE>-p printer</CODE> option specifies the options are
+for another printer:
+
+<UL><PRE>
+<B>lpoptions -p laserjet -o prettyprint ENTER</B>
+<B>lpoptions -p laserjet -o media=A4 -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -p deskjet -o media=Legal -o scaling=100 ENTER</B>
+</PRE></UL>
+
+<H2>Removing Options</H2>
+
+<P>The previous two examples shows how to set options for the default
+and a specific printer. Below, shows you how to remove the saved
+option using the <CODE>-r</CODE> argument:
+
+<UL><PRE>
+<KBD>lpoptions -r prettyprint <I>ENTER</I></KBD>
+<KBD>lpoptions -p laserjet -r prettyprint <I>ENTER</I></KBD>
+</PRE></UL>
+
+<H2>Viewing the Current Defaults</H2>
+
+<P>The <CODE>lpoptions</CODE> command can also be used to show the current
+options by not specifying any new options on the command-line:
+
+<UL><PRE>
+<B>lpoptions ENTER</B>
+media=A4 sides=two-sided-long-edge
+<B>lpoptions -p deskjet ENTER</B>
+media=Legal scaling=100
+</PRE></UL>
+
+<H2>Viewing Options for a Specific Printer</H2>
+
+<P>You can display the supported options using the <CODE>lpoptions</CODE>
+command with the <CODE>-l</CODE> option, as follows:
+
+<UL><PRE>
+<B>lpoptions -p laserjet -l ENTER</B>
+</PRE></UL>
+
+<H2>Setting the Default Printer</H2>
+
+<P>The administrator normally will set a system-wide default printer
+that is normally used as the default printer by everyone. Use the
+<CODE>-d printer</CODE> option to set your own default printer:
+
+<UL><PRE>
+<B>lpoptions -d deskjet ENTER</B>
+</PRE></UL>
+
+<P>The printer can be local (<CODE>deskjet</CODE>) or remote
+(<CODE>deskjet@server</CODE>).
+
+<H2>Printer Instances</H2>
+
+<P>Besides setting options for each print queue, CUPS supports
+<I>printer instances</I> which allow you to define several different
+sets of options for each printer. You specify a printer instance using
+the slash (<CODE>/</CODE>) character:
+
+<UL><PRE>
+<B>lpoptions -p laserjet/duplex -o sides=two-sided-long-edge ENTER</B>
+<B>lpoptions -p laserjet/legal -o media=Legal ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>lp</CODE> and <CODE>lpr</CODE> commands also understand
+this notation:
+
+<UL><PRE>
+<B>lp -d laserjet/duplex filename ENTER</B>
+<B>lpr -P laserjet/legal filename ENTER</B>
+</PRE></UL>
+
+<H2>Removing Instances</H2>
+
+<P>Use the <CODE>-x printer/instance</CODE> option to remove a printer
+instance that you no longer need:
+
+<UL><PRE>
+<B>lpoptions -x laserjet ENTER</B>
+<B>lpoptions -x laserjet/duplex ENTER</B>
+<B>lpoptions -x laserjet/legal ENTER</B>
+</PRE></UL>
+
+<P>The <CODE>-x</CODE> option only removes the default options for that
+printer and instance; the original print queue will remain until deleted
+with the <CODE>lpadmin(8)</CODE> command by the administrator.
+
+
+<H1 ALIGN="RIGHT"><A NAME="LICENSE">A - Software License
+Agreement</A></H1>
+
+<EMBED SRC="../LICENSE.html">
+
+</BODY>
+</HTML>
diff --git a/doc/svd.html b/doc/svd.html
new file mode 100644
index 000000000..0101d15b7
--- /dev/null
+++ b/doc/svd.html
@@ -0,0 +1,311 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Software Version Description</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 1997-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-SVD-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Version Description</H1></A><BR>
+CUPS-SVD-1.1<BR>
+Easy Software Products<BR>
+Copyright 1997-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Additions</A></B>
+<UL>
+<LI><A HREF="#3_1">3.1 Filters</A></LI>
+<UL>
+<LI><A HREF="#3_1_1">3.1.1 imagetoraster, imagetops</A></LI>
+<LI><A HREF="#3_1_2">3.1.2 pdftops</A></LI>
+<LI><A HREF="#3_1_3">3.1.3 pstoraster</A></LI>
+<LI><A HREF="#3_1_4">3.1.4 rastertoepson</A></LI>
+</UL>
+<LI><A HREF="#3_2">3.2 User-Defined Printers and Options</A></LI>
+<LI><A HREF="#3_3">3.3 Daemons</A></LI>
+<UL>
+<LI><A HREF="#3_3_1">3.3.1 cups-lpd</A></LI>
+<LI><A HREF="#3_3_2">3.3.2 cups-polld</A></LI>
+</UL>
+<LI><A HREF="#3_4">3.4 Commands</A></LI>
+<UL>
+<LI><A HREF="#3_4_1">3.4.1 lpoptions</A></LI>
+<LI><A HREF="#3_4_2">3.4.2 lpmove</A></LI>
+<LI><A HREF="#3_4_3">3.4.3 lpinfo</A></LI>
+</UL>
+<LI><A HREF="#3_5">3.5 IPP Implementation</A></LI>
+</UL>
+<B><A HREF="#4">4 Changes</A></B>
+<UL>
+<LI><A HREF="#4_1">4.1 Directory Structure</A></LI>
+<LI><A HREF="#4_2">4.2 IPP Implementation</A></LI>
+</UL>
+<B><A HREF="#5">A Glossary</A></B>
+<UL>
+<LI><A HREF="#5_1">A.1 Terms</A></LI>
+<LI><A HREF="#5_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+ This software version description document provides release information
+ for the Common UNIX Printing System (&quot;CUPS&quot;) Version 1.1.
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This software version description document is organized into the
+ following sections:</P>
+<UL>
+<LI><A HREF="#1">1 - Scope</A></LI>
+<LI><A HREF="#2">2 - References</A></LI>
+<LI><A HREF="#3">3 - Additions</A></LI>
+<LI><A HREF="#4">4 - Changes</A></LI>
+<LI><A HREF="#5">A - Glossary</A></LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Additions</A></H1>
+<P>CUPS 1.1 includes many new features from the 1.0.x releases.</P>
+<H2><A NAME="3_1">3.1 Filters</A></H2>
+<H3><A NAME="3_1_1">3.1.1 <CODE>imagetoraster</CODE>, <CODE>imagetops</CODE>
+</A></H3>
+<P>The image file filters have been upgraded to support conversion of
+ Microsoft Bitmap (&quot;BMP&quot;) and Alias PIX files.</P>
+<H3><A NAME="3_1_2">3.1.2 pdftops</A></H3>
+<P>A new pdftops filter has been developed that is based on the
+ excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is
+ faster, smaller, and considerably more reliable than the
+ Ghostscript-based filter in CUPS 1.0.</P>
+<H3><A NAME="3_1_3">3.1.3 pstoraster</A></H3>
+<P>The <CODE>pstoraster</CODE> filter has been integrated with GNU
+ GhostScript 5.50. The new RIP supports most Level 3 PostScript language
+ features.</P>
+<H3><A NAME="3_1_4">3.1.4 rastertoepson</A></H3>
+<P>The new <CODE>rastertoepson</CODE> filter supports EPSON printers
+ using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin,
+ 24-pin, Stylus Color, and Stylus Photo printers.</P>
+<H2><A NAME="3_2">3.2 User-Defined Printers and Options</A></H2>
+<P>The new <CODE>lpoptions</CODE> command allows users to configure
+ default document options and create additional &quot;instances&quot; of existing
+ printers, each with unique options.</P>
+<P>The <CODE>lp</CODE>, <CODE>lpr</CODE>, and <CODE>lpstat</CODE>
+ commands have been upgraded to use this option and printer instance
+ information automatically.</P>
+<H2><A NAME="3_3">3.3 Daemons</A></H2>
+<P>CUPS 1.1 includes two new daemons that provide enhanced network
+ printing support.</P>
+<H3><A NAME="3_3_1">3.3.1 cups-lpd</A></H3>
+<P>The <CODE>cups-lpd</CODE> daemon provides support for clients using
+ the Line Printer Daemon protocol.</P>
+<H3><A NAME="3_3_2">3.3.2 cups-polld</A></H3>
+<P>The <CODE>cups-polld</CODE> daemon provides remote polling services
+ for the scheduler.</P>
+<H2><A NAME="3_4">3.4 Commands</A></H2>
+<P>CUPS 1.1 includes several new printing commands.</P>
+<H3><A NAME="3_4_1">3.4.1 lpoptions</A></H3>
+<P>The <CODE>lpoptions</CODE> command provides user-defined printers and
+ options.</P>
+<H3><A NAME="3_4_2">3.4.2 lpmove</A></H3>
+<P>The <CODE>lpmove</CODE> command moves a print job to a new
+ destination.</P>
+<H3><A NAME="3_4_3">3.4.3 lpinfo</A></H3>
+<P>The <CODE>lpinfo</CODE> command lists the available PPD files or
+ devices.</P>
+<H2><A NAME="3_5">3.5 IPP Implementation</A></H2>
+<P>CUPS 1.1 adds support for the <CODE>set-job-attributes</CODE>
+ extension operation as well as two new CUPS-specific extension
+ operations to determine which devices and printer drivers are available
+ on the system.</P>
+<P>Further information on the CUPS implementation of IPP can be found in
+ CUPS-IPP-1.1.</P>
+<H1><A NAME="4">4 Changes</A></H1>
+<P>CUPS 1.1 includes many changes from the 1.0.x releases.</P>
+<H2><A NAME="4_1">4.1 Directory Structure</A></H2>
+<P>The directory structure in CUPS 1.1 has been modified to conform to
+ the Filesystem Hierarchy Standard, 2.0. The following table describes
+ the new file locations.
+<CENTER>
+<TABLE BORDER WIDTH="80%"><CAPTION> Table 1: Directory structure changes
+ from CUPS 1.0.x to 1.1.x.</CAPTION>
+<TR><TH>Description</TH><TH>CUPS 1.0.x</TH><TH>CUPS 1.1.x</TH></TR>
+<TR><TD>Backends</TD><TD>/var/cups/backend</TD><TD>/usr/lib/cups/backend</TD>
+</TR>
+<TR><TD>CGI programs</TD><TD>/var/cups/cgi-bin</TD><TD>
+/usr/lib/cups/cgi-bin</TD></TR>
+<TR><TD>Configuration files</TD><TD>/var/cups/conf</TD><TD>/etc/cups</TD>
+</TR>
+<TR><TD>Documentation</TD><TD>/usr/share/cups/doc</TD><TD>
+/usr/share/doc/cups</TD></TR>
+<TR><TD>Filter programs</TD><TD>/var/cups/filter</TD><TD>
+/usr/lib/cups/filter</TD></TR>
+<TR><TD>Interface scripts</TD><TD>/var/cups/interfaces</TD><TD>
+/etc/cups/interfaces</TD></TR>
+<TR><TD>Locale data</TD><TD>/usr/lib/locale</TD><TD>/usr/share/locale</TD>
+</TR>
+<TR><TD>Log files</TD><TD>/var/cups/logs</TD><TD>/var/log/cups</TD></TR>
+<TR><TD>PPD files</TD><TD>/var/cups/ppd</TD><TD>/etc/cups/ppd</TD></TR>
+<TR><TD>Request files</TD><TD>/var/cups/requests</TD><TD>/var/spool/cups</TD>
+</TR>
+</TABLE>
+</CENTER>
+</P>
+<H2><A NAME="4_2">4.2 IPP Implementation</A></H2>
+<P>CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol.</P>
+<P>The new scheduler supports the <CODE>create-job</CODE> and <CODE>
+send-document</CODE> operations. In addition, the <CODE>job-sheets</CODE>
+, <CODE>job-sheets-default</CODE>, and <CODE>job-sheets-supported</CODE>
+ attributes are now supported for banner pages.</P>
+<P>The <CODE>CUPS-get-printers</CODE> and <CODE>CUPS-get-classes</CODE>
+ operations have been upgraded to support limited filtering based upon
+ the <CODE>printer-type</CODE>, <CODE>printer-location</CODE>, <CODE>
+printer-info</CODE>, and <CODE>printer-make-and-model</CODE> attributes.</P>
+<P>The <CODE>CUPS-add-printer</CODE> operation now supports the <CODE>
+ppd-name</CODE> attribute to specify a locally-available PPD file rather
+ than sending the PPD file from the client with the request.</P>
+<P>Further information on the CUPS implementation of IPP can be found in
+ CUPS-IPP-1.1.</P>
+<H1 TYPE="A" VALUE="1"><A NAME="5">A Glossary</A></H1>
+<H2><A NAME="5_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="5_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/svd.pdf b/doc/svd.pdf
new file mode 100644
index 000000000..f078d8553
--- /dev/null
+++ b/doc/svd.pdf
Binary files differ
diff --git a/doc/svd.shtml b/doc/svd.shtml
new file mode 100644
index 000000000..94b792260
--- /dev/null
+++ b/doc/svd.shtml
@@ -0,0 +1,212 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SVD-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Version Description</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+This software version description document provides release information for the
+Common UNIX Printing System ("CUPS") Version 1.1.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This software version description document is organized into the following
+sections:</P>
+
+<UL>
+ <LI><A HREF="#1">1 - Scope</A></LI>
+ <LI><A HREF="#2">2 - References</A></LI>
+ <LI><A HREF="#3">3 - Additions</A></LI>
+ <LI><A HREF="#4">4 - Changes</A></LI>
+ <LI><A HREF="#5">A - Glossary</A></LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+<H1>Additions</H1>
+
+<P>CUPS 1.1 includes many new features from the 1.0.x releases.
+
+<H2>Filters</H2>
+
+<H3><CODE>imagetoraster</CODE>, <CODE>imagetops</CODE></H3>
+
+<P>The image file filters have been upgraded to support conversion of
+Microsoft Bitmap ("BMP") and Alias PIX files.
+
+<H3>pdftops</H3>
+
+<P>A new pdftops filter has been developed that is based on the
+excellent Xpdf 0.90 software from Derek B. Noonburg. The new filter is
+faster, smaller, and considerably more reliable than the
+Ghostscript-based filter in CUPS 1.0.
+
+<H3>pstoraster</H3>
+
+<P>The <CODE>pstoraster</CODE> filter has been integrated with GNU
+GhostScript 5.50. The new RIP supports most Level 3 PostScript language
+features.
+
+<H3>rastertoepson</H3>
+
+<P>The new <CODE>rastertoepson</CODE> filter supports EPSON printers
+using the ESC/P or ESC/P2 command sets. PPDs are supplied for 9-pin,
+24-pin, Stylus Color, and Stylus Photo printers.
+
+<H2>User-Defined Printers and Options</H2>
+
+<P>The new <CODE>lpoptions</CODE> command allows users to configure default
+document options and create additional "instances" of existing printers,
+each with unique options.
+
+<P>The <CODE>lp</CODE>, <CODE>lpr</CODE>, and <CODE>lpstat</CODE> commands
+have been upgraded to use this option and printer instance information
+automatically.
+
+<H2>Daemons</H2>
+
+<P>CUPS 1.1 includes two new daemons that provide enhanced network printing
+support.
+
+<H3>cups-lpd</H3>
+
+<P>The <CODE>cups-lpd</CODE> daemon provides support for clients using the
+Line Printer Daemon protocol.
+
+<H3>cups-polld</H3>
+
+<P>The <CODE>cups-polld</CODE> daemon provides remote polling services for
+the scheduler.
+
+<H2>Commands</H2>
+
+<P>CUPS 1.1 includes several new printing commands.
+
+<H3>lpoptions</H3>
+
+<P>The <CODE>lpoptions</CODE> command provides user-defined printers and
+options.
+
+<H3>lpmove</H3>
+
+<P>The <CODE>lpmove</CODE> command moves a print job to a new destination.
+
+<H3>lpinfo</H3>
+
+<P>The <CODE>lpinfo</CODE> command lists the available PPD files or devices.
+
+<H2>IPP Implementation</H2>
+
+<P>CUPS 1.1 adds support for the <CODE>set-job-attributes</CODE>
+extension operation as well as two new CUPS-specific extension
+operations to determine which devices and printer drivers are available
+on the system.
+
+<P>Further information on the CUPS implementation of IPP can be found
+in CUPS-IPP-1.1.
+
+
+<H1>Changes</H1>
+
+<P>CUPS 1.1 includes many changes from the 1.0.x releases.
+
+<H2>Directory Structure</H2>
+
+<P>The directory structure in CUPS 1.1 has been modified to conform to the
+Filesystem Hierarchy Standard, 2.0. The following table describes the
+new file locations.
+
+<CENTER><TABLE WIDTH="80%" BORDER>
+<CAPTION>Table 1: Directory structure changes from CUPS 1.0.x to 1.1.x.</CAPTION>
+<TR>
+ <TH>Description</TH>
+ <TH>CUPS 1.0.x</TH>
+ <TH>CUPS 1.1.x</TH>
+</TR>
+<TR>
+ <TD>Backends</TD>
+ <TD>/var/cups/backend</TD>
+ <TD>/usr/lib/cups/backend</TD>
+</TR>
+<TR>
+ <TD>CGI programs</TD>
+ <TD>/var/cups/cgi-bin</TD>
+ <TD>/usr/lib/cups/cgi-bin</TD>
+</TR>
+<TR>
+ <TD>Configuration files</TD>
+ <TD>/var/cups/conf</TD>
+ <TD>/etc/cups</TD>
+</TR>
+<TR>
+ <TD>Documentation</TD>
+ <TD>/usr/share/cups/doc</TD>
+ <TD>/usr/share/doc/cups</TD>
+</TR>
+<TR>
+ <TD>Filter programs</TD>
+ <TD>/var/cups/filter</TD>
+ <TD>/usr/lib/cups/filter</TD>
+</TR>
+<TR>
+ <TD>Interface scripts</TD>
+ <TD>/var/cups/interfaces</TD>
+ <TD>/etc/cups/interfaces</TD>
+</TR>
+<TR>
+ <TD>Locale data</TD>
+ <TD>/usr/lib/locale</TD>
+ <TD>/usr/share/locale</TD>
+</TR>
+<TR>
+ <TD>Log files</TD>
+ <TD>/var/cups/logs</TD>
+ <TD>/var/log/cups</TD>
+</TR>
+<TR>
+ <TD>PPD files</TD>
+ <TD>/var/cups/ppd</TD>
+ <TD>/etc/cups/ppd</TD>
+</TR>
+<TR>
+ <TD>Request files</TD>
+ <TD>/var/cups/requests</TD>
+ <TD>/var/spool/cups</TD>
+</TR>
+</TABLE></CENTER>
+
+<H2>IPP Implementation</H2>
+
+<P>CUPS 1.1 is based on version 1.1 of the Internet Printing Protocol.
+
+<P>The new scheduler supports the <CODE>create-job</CODE> and
+<CODE>send-document</CODE> operations. In addition, the
+<CODE>job-sheets</CODE>, <CODE>job-sheets-default</CODE>, and
+<CODE>job-sheets-supported</CODE> attributes are now supported for
+banner pages.
+
+<P>The <CODE>CUPS-get-printers</CODE> and <CODE>CUPS-get-classes</CODE>
+operations have been upgraded to support limited filtering based upon
+the <CODE>printer-type</CODE>, <CODE>printer-location</CODE>,
+<CODE>printer-info</CODE>, and <CODE>printer-make-and-model</CODE>
+attributes.
+
+<P>The <CODE>CUPS-add-printer</CODE> operation now supports the
+<CODE>ppd-name</CODE> attribute to specify a locally-available PPD file
+rather than sending the PPD file from the client with the request.
+
+<P>Further information on the CUPS implementation of IPP can be found
+in CUPS-IPP-1.1.
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/doc/system-overview.shtml b/doc/system-overview.shtml
new file mode 100644
index 000000000..5c17be91e
--- /dev/null
+++ b/doc/system-overview.shtml
@@ -0,0 +1,34 @@
+<H2>System Overview</H2>
+
+<P>CUPS provides a portable printing layer for UNIX&reg;-based
+operating systems. It has been developed by
+<A HREF="http://www.easysw.com">Easy Software Products</A> to promote a
+standard printing solution for all UNIX vendors and users. CUPS
+provides the System V and Berkeley command-line interfaces.
+
+<P>CUPS uses the Internet Printing Protocol ("IPP") as the basis for
+managing print jobs and queues. The Line Printer Daemon ("LPD") Server
+Message Block ("SMB"), and AppSocket (a.k.a. JetDirect) protocols are
+also supported with reduced functionality. CUPS adds network printer
+browsing and PostScript Printer Description ("PPD") based
+printing options to support real-world printing under UNIX.
+
+<P>CUPS includes an image file RIP that supports printing of
+image files to non-PostScript printers. A customized version of
+GNU Ghostscript 7.05 for CUPS called ESP Ghostscript is
+available separately to support printing of PostScript files
+within the CUPS driver framework. Sample drivers for Dymo,
+EPSON, HP, and OKIDATA printers are included that use these
+filters.
+
+<P>Drivers for thousands of printers are provided with our ESP
+Print Pro software, available at:
+
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+
+<P>CUPS is licensed under the GNU General Public License and GNU
+Library General Public License. Please contact Easy Software
+Products for commercial support and "binary distribution"
+rights.
diff --git a/doc/translation.html b/doc/translation.html
new file mode 100644
index 000000000..4e99a4ff3
--- /dev/null
+++ b/doc/translation.html
@@ -0,0 +1,620 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>CUPS Translation Guide</TITLE>
+<META NAME="author" CONTENT="Easy Software Products">
+<META NAME="copyright" CONTENT="Copyright 2001-2004, All Rights Reserved">
+<META NAME="docnumber" CONTENT="CUPS-TRANS-1.1">
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
+<STYLE TYPE="text/css"><!--
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
+--></STYLE>
+</HEAD>
+<BODY BGCOLOR="white">
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Translation Guide</H1></A><BR>
+CUPS-TRANS-1.1<BR>
+Easy Software Products<BR>
+Copyright 2001-2004, All Rights Reserved<BR>
+</CENTER>
+<HR NOSHADE>
+<H1 ALIGN="CENTER"><A NAME="CONTENTS">Table of Contents</A></H1>
+<BR>
+<BR><B><A HREF="#1">1 Scope</A></B>
+<UL>
+<LI><A HREF="#1_1">1.1 Identification</A></LI>
+<LI><A HREF="#1_2">1.2 System Overview</A></LI>
+<LI><A HREF="#1_3">1.3 Document Overview</A></LI>
+</UL>
+<B><A HREF="#2">2 References</A></B>
+<UL>
+<LI><A HREF="#2_1">2.1 CUPS Documentation</A></LI>
+<LI><A HREF="#2_2">2.2 Other Documents</A></LI>
+</UL>
+<B><A HREF="#3">3 Character Sets</A></B>
+<BR>
+<BR><B><A HREF="#4">4 Message Catalogs</A></B>
+<BR>
+<BR><B><A HREF="#5">5 Web Interfaces</A></B>
+<UL>
+<LI><A HREF="#5_1">5.1 Template Files</A></LI>
+<UL>
+<LI><A HREF="#5_1_1">5.1.1 Inserting Attributes and Values</A></LI>
+<LI><A HREF="#5_1_2">5.1.2 Array Substitutions</A></LI>
+<LI><A HREF="#5_1_3">5.1.3 Conditional Tests</A></LI>
+<LI><A HREF="#5_1_4">5.1.4 Template File List</A></LI>
+</UL>
+<LI><A HREF="#5_2">5.2 CGI Programs</A></LI>
+<UL>
+<LI><A HREF="#5_2_1">5.2.1 admin.cgi</A></LI>
+<LI><A HREF="#5_2_2">5.2.2 classes.cgi</A></LI>
+<LI><A HREF="#5_2_3">5.2.3 jobs.cgi</A></LI>
+<LI><A HREF="#5_2_4">5.2.4 printers.cgi</A></LI>
+</UL>
+</UL>
+<B><A HREF="#6">A Glossary</A></B>
+<UL>
+<LI><A HREF="#6_1">A.1 Terms</A></LI>
+<LI><A HREF="#6_2">A.2 Acronyms</A></LI>
+</UL>
+<HR NOSHADE>
+<H1><A NAME="1">1 Scope</A></H1>
+<H2><A NAME="1_1">1.1 Identification</A></H2>
+<P>This translation guide provides instructions for creating
+ translations of the CUPS message catalogs and web pages for the Common
+ UNIX Printing System (&quot;CUPS&quot;) Version 1.1 software.</P>
+<H2><A NAME="1_2">1.2 System Overview</A></H2>
+<P>CUPS provides a portable printing layer for UNIX&reg;-based operating
+ systems. It has been developed by <A HREF="http://www.easysw.com">Easy
+ Software Products</A> to promote a standard printing solution for all
+ UNIX vendors and users. CUPS provides the System V and Berkeley
+ command-line interfaces.</P>
+<P>CUPS uses the Internet Printing Protocol (&quot;IPP&quot;) as the basis for
+ managing print jobs and queues. The Line Printer Daemon (&quot;LPD&quot;) Server
+ Message Block (&quot;SMB&quot;), and AppSocket (a.k.a. JetDirect) protocols are
+ also supported with reduced functionality. CUPS adds network printer
+ browsing and PostScript Printer Description (&quot;PPD&quot;) based printing
+ options to support real-world printing under UNIX.</P>
+<P>CUPS includes an image file RIP that supports printing of image files
+ to non-PostScript printers. A customized version of GNU Ghostscript
+ 7.05 for CUPS called ESP Ghostscript is available separately to support
+ printing of PostScript files within the CUPS driver framework. Sample
+ drivers for Dymo, EPSON, HP, and OKIDATA printers are included that use
+ these filters.</P>
+<P>Drivers for thousands of printers are provided with our ESP Print Pro
+ software, available at:</P>
+<PRE>
+ <A HREF="http://www.easysw.com/printpro/">http://www.easysw.com/printpro/</A>
+</PRE>
+<P>CUPS is licensed under the GNU General Public License and GNU Library
+ General Public License. Please contact Easy Software Products for
+ commercial support and &quot;binary distribution&quot; rights.</P>
+<H2><A NAME="1_3">1.3 Document Overview</A></H2>
+<P>This translation guide is organized into the following sections:</P>
+<UL>
+<LI>1 - Scope</LI>
+<LI>2 - References</LI>
+<LI>3 - Character Sets</LI>
+<LI>4 - Message Catalogs</LI>
+<LI>5 - Web Interfaces</LI>
+<LI>A - Glossary</LI>
+</UL>
+<H1><A NAME="2">2 References</A></H1>
+<H2><A NAME="2_1">2.1 CUPS Documentation</A></H2>
+<P>The following CUPS documentation is referenced by this document:</P>
+<UL>
+<LI>CUPS-CMP-1.1: CUPS Configuration Management Plan</LI>
+<LI>CUPS-IDD-1.1: CUPS System Interface Design Description</LI>
+<LI>CUPS-IPP-1.1: CUPS Implementation of IPP</LI>
+<LI>CUPS-SAM-1.1.x: CUPS Software Administrators Manual</LI>
+<LI>CUPS-SDD-1.1: CUPS Software Design Description</LI>
+<LI>CUPS-SPM-1.1.x: CUPS Software Programming Manual</LI>
+<LI>CUPS-SSR-1.1: CUPS Software Security Report</LI>
+<LI>CUPS-STP-1.1: CUPS Software Test Plan</LI>
+<LI>CUPS-SUM-1.1.x: CUPS Software Users Manual</LI>
+<LI>CUPS-SVD-1.1: CUPS Software Version Description</LI>
+</UL>
+<H2><A NAME="2_2">2.2 Other Documents</A></H2>
+<P>The following non-CUPS documents are referenced by this document:</P>
+<UL>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5003.PPD_Spec_v4.3.pdf">
+Adobe PostScript Printer Description File Format Specification, Version
+ 4.3.</A></LI>
+<LI><A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf">
+Adobe PostScript Language Reference, Third Edition.</A></LI>
+<LI>IPP/1.1: Implementers Guide</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc1179.txt">RFC 1179, Line Printer
+ Daemon Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396, Uniform
+ Resource Identifiers (URI): Generic Syntax</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2567.txt">RFC 2567, Design Goals
+ for an Internet Printing Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2568.txt">RFC 2568, Rationale
+ for the Structure of the Model and Protocol for the Internet Printing
+ Protocol</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2569.txt">RFC 2569, Mapping
+ between LPD and IPP Protocols</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616, Hypertext
+ Transfer Protocol -- HTTP/1.1</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2617.txt">RFC 2617, HTTP
+ Authentication: Basic and Digest Access</A> Authentication</LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2910.txt">RFC 2910, IPP/1.1:
+ Encoding and Transport</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc2911.txt">RFC 2911, IPP/1.1:
+ Model and Semantics</A></LI>
+<LI><A HREF="http://www.ietf.org/rfc/rfc3380.txt">RFC 3380, IPP: Job and
+ Printer Set Operations</A></LI>
+</UL>
+<H1><A NAME="3">3 Character Sets</A></H1>
+<P>CUPS uses character set files to define the mapping of local
+ character sets to Unicode code points, as well as the fonts that should
+ be used for different ranges of characters.</P>
+<P>CUPS includes files for common 8-bit encodings as well as UTF-8 for
+ Unicode text. The format of these files is described in the CUPS
+ Interface Design Description (IDD) document. Current character sets are
+ enumerated in the CUPS API, so in order to add a new character set you
+ must patch the CUPS source as well as provide a new charset file.</P>
+<P>CUPS 1.1 supports the following character sets:</P>
+<UL>
+<LI>iso-8859-1</LI>
+<LI>iso-8859-2</LI>
+<LI>iso-8859-3</LI>
+<LI>iso-8859-4</LI>
+<LI>iso-8859-5</LI>
+<LI>iso-8859-6</LI>
+<LI>iso-8859-7</LI>
+<LI>iso-8859-8</LI>
+<LI>iso-8859-9</LI>
+<LI>iso-8859-10</LI>
+<LI>iso-8859-13</LI>
+<LI>iso-8859-14</LI>
+<LI>iso-8859-15</LI>
+<LI>koi8-r</LI>
+<LI>koi8-u</LI>
+<LI>us-ascii</LI>
+<LI>utf-8</LI>
+<LI>windows-874</LI>
+<LI>windows-1250</LI>
+<LI>windows-1251</LI>
+<LI>windows-1252</LI>
+<LI>windows-1253</LI>
+<LI>windows-1254</LI>
+<LI>windows-1255</LI>
+<LI>windows-1256</LI>
+<LI>windows-1257</LI>
+<LI>windows-1258</LI>
+</UL>
+<H1><A NAME="4">4 Message Catalogs</A></H1>
+<P>CUPS message catalogs are text files that identify the default
+ character set for the locale and a list of localized message strings
+ for the CUPS software. The format of the message catalog files is
+ described in the CUPS IDD.</P>
+<P>Message catalogs are named<VAR> cups_ll</VAR>,<VAR> cups_ll_CC</VAR>,
+ or<VAR> cups_ll_CC.charset</VAR>, where &quot;ll&quot; is the standard 2-letter
+ abbreviation for the language, &quot;CC&quot; is the standard 2-letter
+ abbreviation for the country, and &quot;charset&quot; is the charset name which
+ may differ from the list above.</P>
+<P>Each message catalog file is stored in a subdirectory named<VAR> ll</VAR>
+,<VAR> ll_CC</VAR>, or<VAR> ll_CC.charset</VAR> to match the trailing
+ portion of the message catalog filename.</P>
+<P>When translating a new message catalog, copy the<VAR> cups_C</VAR>
+ message catalog file to a new subdirectory; to translate the message
+ catalog to Canadian French, you would type the following commands:</P>
+<UL>
+<PRE>
+<KBD>cd locale <I>ENTER</I></KBD>
+<KBD>mkdir fr_CA <I>ENTER</I></KBD>
+<KBD>cp C/cups_C fr_CA/cups_fr_CA <I>ENTER</I></KBD>
+</PRE>
+</UL>
+<P>Alternatively, you could copy the existing<VAR> cups_fr</VAR> message
+ catalog and then make any changes necessary.</P>
+<P>Once you have make your copy of the file, edit it using your favorite
+ text editor to translate the text to the desired language. Be sure to
+ preserve any numbers starting in the first column, as they indicate a
+ new message number - you'll see this for the HTTP status messages.</P>
+<P>Finally, add your locale to the list of locales in the makefile and
+ run the following command to install it:</P>
+<UL>
+<PRE>
+<KBD>make install <I>ENTER</I></KBD>
+</PRE>
+</UL>
+<H1><A NAME="5">5 Web Interfaces</A></H1>
+<P>The CUPS scheduler provides a web interface that can be used to do
+ many common printing and administration tasks. The built-in web server
+ supports localization of web pages through the use of subdirectories
+ for each locale, e.g. &quot;fr&quot; for French, &quot;de&quot; for German, &quot;fr_ca&quot; for
+ French in Canada, and so forth.</P>
+<H2><A NAME="5_1">5.1 Template Files</A></H2>
+<P>Template files are HTML files with special formatting characters in
+ them that allow substition of variables and arrays. The CUPS CGI
+ programs (<CODE>admin.cgi</CODE>, <CODE>classes.cgi</CODE>, <CODE>
+jobs.cgi</CODE>, and <CODE>printers.cgi</CODE>) use these template file
+ to provide dynamic content for the web interface. Template files are
+ installed in the<VAR> /usr/share/cups/templates</VAR> directory by
+ default.</P>
+<P>Translated versions of the template files should be installed in the
+ appropriate subdirectories under<VAR> /usr/share/cups/templates</VAR>.
+ For example, Canadian French template files should be stored in the<VAR>
+ /usr/share/cups/templates/fr_CA</VAR> directory.</P>
+<H3><A NAME="5_1_1">5.1.1 Inserting Attributes and Values</A></H3>
+<P>Template files consist of HTML with variable substitutions for named
+ inside curley braces &quot;{name}&quot;. Variable names are generally the IPP
+ attribute names with the hyphen (&quot;-&quot;) replaced by the underscore (&quot;_&quot;)
+ character. For example, the <TT>job-printer-uri</TT> attribute is
+ renamed to <TT>job_printer_uri</TT>.</P>
+<P>Curley braces (&quot;{&quot; and &quot;}&quot;) to indicate substitutions, and the
+ backslash (&quot;\&quot;) character for quoting. To insert any of these special
+ characters as-is you need to use the HTML <CODE>&amp;name;</CODE> mechanism
+ or prefix each special character with the backslash (&quot;\&quot;.)</P>
+<P>You substitute the value of a variable using <CODE>{NAME}</CODE> in
+ your template file. If the variable is undefined then the <CODE>{NAME}</CODE>
+ string is output as-is.</P>
+<P>To substitute an empty string if the variable is undefined, use <CODE>
+{?NAME}</CODE> instead.</P>
+<H3><A NAME="5_1_2">5.1.2 Array Substitutions</A></H3>
+<P>The number of array elements can be inserted using <CODE>{#NAME}</CODE>
+. If the array is undefined then 0 is output. The current array element
+ (starting at 1) is inserted with <CODE>{#}</CODE>.</P>
+<P>Arrays are handled using <CODE>{[NAME]</CODE> at the beginning of a
+ section and <CODE>}</CODE> at the end. The information between the
+ closing bracket (&quot;]&quot;) and closing brace (&quot;}&quot;) is repeated for as many
+ elements as are in the named array. For example, the following template
+ will display a list of each job in the <CODE>job_id</CODE> array:</P>
+<UL>
+<PRE>
+&lt;TABLE&gt;
+&lt;TR&gt;
+ &lt;TH&gt;Job ID&lt;/TH&gt;
+ &lt;TH&gt;Destination&lt;/TH&gt;
+ &lt;TH&gt;Title&lt;/TH&gt;
+&lt;/TR&gt;
+
+{[job_id]
+&lt;TR&gt;
+ &lt;TD&gt;{?job_id}&lt;/TD&gt;
+ &lt;TD&gt;{?job_printer_name}&lt;/TD&gt;
+ &lt;TD&gt;{?job_name}&lt;/TD&gt;
+&lt;/TR&gt;
+}
+&lt;/TABLE&gt;
+</PRE>
+</UL>
+<P>Arrays can be nested, however all elements within the curley braces
+ (&quot;{&quot; and &quot;}&quot;) are indexed using the innermost array.</P>
+<H3><A NAME="5_1_3">5.1.3 Conditional Tests</A></H3>
+<P>Templates can also test variables against specific values and
+ conditionally include text in the template. The format is:</P>
+<UL>
+<PRE>
+{<I>variable</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>=<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>!<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>&lt;<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>&gt;<I>value</I>?<I>true</I>:<I>false</I>}
+</PRE>
+</UL>
+<P>where<VAR> true</VAR> is the text that is included if the condition
+ is true and<VAR> false</VAR> is the text that is included if the
+ condition is false. A value of <CODE>#</CODE> is replaced with the
+ current element number (starting at 1.)</P>
+<P>The character after the variable name specifies the condition to
+ test:
+<CENTER>
+<TABLE BORDER="1">
+<TR><TH WIDTH="5%">Char</TH><TH WIDTH="50%">Condition</TH></TR>
+<TR><TD>?</TD><TD>True if<VAR> variable</VAR> exists.</TD></TR>
+<TR><TD>=</TD><TD>True if<VAR> variable</VAR> is equal to<VAR> value</VAR>
+.</TD></TR>
+<TR><TD>!</TD><TD>True if<VAR> variable</VAR> is not equal to<VAR> value</VAR>
+.</TD></TR>
+<TR><TD>&lt;</TD><TD>True if<VAR> variable</VAR> is less than<VAR> value</VAR>
+.</TD></TR>
+<TR><TD>&gt;</TD><TD>True if<VAR> variable</VAR> is greater than<VAR> value</VAR>
+.</TD></TR>
+</TABLE>
+</CENTER>
+</P>
+<H3><A NAME="5_1_4">5.1.4 Template File List</A></H3>
+<P>The following template files are used by the web interface:</P>
+<DL>
+<DT>add-class.tmpl</DT>
+<DD>This is the initial form that is shown to add a new printer class.</DD>
+<DT>add-printer.tmpl</DT>
+<DD>This is the initial form that is shown to add a new printer.</DD>
+<DT>admin-op.tmpl</DT>
+<DD>This is the template that is used to display an error message when
+ the admin interface sees an undefined operation name.</DD>
+<DT>admin.tmpl</DT>
+<DD>This is the template that shows the initial menu of operations (add
+ a class, manage classes, etc.)</DD>
+<DT>choose-device.tmpl</DT>
+<DD>This is the form that shows the list of available devices.</DD>
+<DT>choose-make.tmpl</DT>
+<DD>This is the form that shows the list of available manufacturers.</DD>
+<DT>choose-members.tmpl</DT>
+<DD>This is the form that shows the list of available printers that can
+ be added to a class.</DD>
+<DT>choose-model.tmpl</DT>
+<DD>This is the form that shows the list of available printer
+ models/drivers.</DD>
+<DT>choose-serial.tmpl</DT>
+<DD>This is the form that allows the user to choose a serial port and
+ any options.</DD>
+<DT>choose-uri.tmpl</DT>
+<DD>This is the form that allows the user to enter a device URI for
+ network printers.</DD>
+<DT>class-added.tmpl</DT>
+<DD>This template shows the &quot;class added&quot; message.</DD>
+<DT>class-confirm.tmpl</DT>
+<DD>This is the template used to confirm the deletion of a class.</DD>
+<DT>class-deleted.tmpl</DT>
+<DD>This template shows the &quot;class deleted&quot; message.</DD>
+<DT>classes.tmpl</DT>
+<DD>This template shows one or more printer classes.</DD>
+<DT>class-modified.tmpl</DT>
+<DD>This template shows the &quot;class modified&quot; message.</DD>
+<DT>config-printer.tmpl</DT>
+<DD>This template starts the printer configuration form.</DD>
+<DT>config-printer2.tmpl</DT>
+<DD>This template ends the printer configuration form.</DD>
+<DT>error.tmpl</DT>
+<DD>This template displays a generic error message.</DD>
+<DT>header.tmpl</DT>
+<DD>This template is used as the standard header on all dynamic content.</DD>
+<DT>job-cancel.tmpl</DT>
+<DD>This template shows &quot;job cancelled&quot;.</DD>
+<DT>job-hold.tmpl</DT>
+<DD>This template shows &quot;job held&quot;.</DD>
+<DT>job-op.tmpl</DT>
+<DD>This is the template that is used to display an error message when
+ the job interface sees an undefined operation name.</DD>
+<DT>job-release.tmpl</DT>
+<DD>This template shows &quot;job released&quot;.</DD>
+<DT>job-restart.tmpl</DT>
+<DD>This template shows &quot;job restarted&quot;.</DD>
+<DT>jobs.tmpl</DT>
+<DD>This template is used to list the print jobs on a server, class, or
+ printer.</DD>
+<DT>modify-class.tmpl</DT>
+<DD>This template is used as the first form when modifying a class.</DD>
+<DT>modify-printer.tmpl</DT>
+<DD>This template is used as the first form when modifying a printer.</DD>
+<DT>option-boolean.tmpl</DT>
+<DD>This template is used to select a boolean PPD option.</DD>
+<DT>option-header.tmpl</DT>
+<DD>This template is used to start a PPD option group.</DD>
+<DT>option-pickmany.tmpl</DT>
+<DD>This template is used to select a multi-valued PPD option.</DD>
+<DT>option-pickone.tmpl</DT>
+<DD>This template is used to select a single-valued PPD option.</DD>
+<DT>option-trailer.tmpl</DT>
+<DD>This template is used to end a PPD option group.</DD>
+<DT>printer-accept.tmpl</DT>
+<DD>This template shows &quot;printer now accepting jobs&quot;.</DD>
+<DT>printer-added.tmpl</DT>
+<DD>This template shows &quot;printer added&quot;.</DD>
+<DT>printer-configured.tmpl</DT>
+<DD>This template shows &quot;printer configured&quot;.</DD>
+<DT>printer-confirm.tmpl</DT>
+<DD>This template asks the user to confirm the deletion of a printer.</DD>
+<DT>printer-deleted.tmpl</DT>
+<DD>This template shows &quot;printer deleted&quot;.</DD>
+<DT>printer-modified.tmpl</DT>
+<DD>This template shows &quot;printer modified&quot;.</DD>
+<DT>printer-purge.tmpl</DT>
+<DD>This template shows &quot;printer has been purged of all jobs&quot;.</DD>
+<DT>printer-reject.tmpl</DT>
+<DD>This template shows &quot;printer now rejecting jobs&quot;.</DD>
+<DT>printer-start.tmpl</DT>
+<DD>This template shows &quot;printer started&quot;.</DD>
+<DT>printers.tmpl</DT>
+<DD>This template is used to list information on one or more printers.</DD>
+<DT>printer-stop.tmpl</DT>
+<DD>This template shows &quot;printer stopped&quot;.</DD>
+<DT>test-page.tmpl</DT>
+<DD>This template shows &quot;test page printed&quot;.</DD>
+<DT>trailer.tmpl</DT>
+<DD>This template is used as the standard trailer on all dynamic
+ content.</DD>
+</DL>
+<H2><A NAME="5_2">5.2 CGI Programs</A></H2>
+<P>CUPS uses four CGI programs to manage the dynamic web interfaces:</P>
+<UL>
+<LI><CODE>admin.cgi</CODE></LI>
+<LI><CODE>classes.cgi</CODE></LI>
+<LI><CODE>jobs.cgi</CODE></LI>
+<LI><CODE>printers.cgi</CODE></LI>
+</UL>
+<H3><A NAME="5_2_1">5.2.1 admin.cgi</A></H3>
+<P>The <CODE>admin.cgi</CODE> program handles all of the printer and
+ class administration functions and is run for all direct accesses to
+ the<VAR> /admin</VAR> resource. For most operations it uses the <CODE>
+PRINTER_NAME</CODE> and <CODE>OP</CODE> form variables to specify the
+ action requested.</P>
+<P>The following <CODE>OP</CODE> values are supported:</P>
+<DL>
+<DT>accept-jobs</DT>
+<DD>Accepts jobs on the named destination.</DD>
+<DT>add-class</DT>
+<DD>Adds a new printer class. This operation also adds several other
+ form variables:
+<DL>
+<DT>MEMBER_URIS</DT>
+<DD>Sets the members of the class. Multiple <CODE>MEMBER_URIS</CODE>
+ values can be provided.</DD>
+<DT>PRINTER_INFO</DT>
+<DD>Sets the printer-info attribute for the printer class, which is
+ usually the printer description.</DD>
+<DT>PRINTER_LOCATION</DT>
+<DD>Sets the printer-location attribute for the printer class.</DD>
+</DL>
+</DD>
+<DT>add-printer</DT>
+<DD>Adds a new printer. This operation also adds several other form
+ variables:
+<DL>
+<DT>BAUDRATE</DT>
+<DD>Sets the baud rate for serial devices.</DD>
+<DT>BITS</DT>
+<DD>Sets the number of data bits for serial devices.</DD>
+<DT>DEVICE_URI</DT>
+<DD>Sets the device URI for the printer.</DD>
+<DT>FLOW</DT>
+<DD>Sets the flow control for serial devices.</DD>
+<DT>PARITY</DT>
+<DD>Sets the parity checking for serial devices.</DD>
+<DT>PPD_NAME</DT>
+<DD>Sets the driver name for the printer (&quot;raw&quot; for a raw queue.)</DD>
+<DT>PRINTER_INFO</DT>
+<DD>Sets the printer-info attribute for the printer, which is usually
+ the printer description.</DD>
+<DT>PRINTER_LOCATION</DT>
+<DD>Sets the printer-location attribute for the printer.</DD>
+</DL>
+</DD>
+<DT>config-printer</DT>
+<DD>Configures an existing printer. This operation uses form variables
+ of the same name as the options in the printer's PPD file.</DD>
+<DT>delete-class</DT>
+<DD>Deletes a printer class. The form variable <CODE>CONFIRM</CODE> may
+ be set to any value to bypass the confirmation page.</DD>
+<DT>delete-printer</DT>
+<DD>Deletes a printer. The form variable <CODE>CONFIRM</CODE> may be set
+ to any value to bypass the confirmation page.</DD>
+<DT>modify-class</DT>
+<DD>Modifies a printer class. See the add-class operation for a list of
+ form variables.</DD>
+<DT>modify-printer</DT>
+<DD>Modifies a printer. See the add-printer operation for a list of form
+ variables.</DD>
+<DT>purge-jobs</DT>
+<DD>Purges all jobs on the named destination.</DD>
+<DT>reject-jobs</DT>
+<DD>Rejects new jobs on the named destination.</DD>
+<DT>start-printer</DT>
+<DD>Starts the named destination.</DD>
+<DT>stop-printer</DT>
+<DD>Stops the named destination.</DD>
+</DL>
+<H3><A NAME="5_2_2">5.2.2 classes.cgi</A></H3>
+<P>The <CODE>classes.cgi</CODE> program is responsible for listing class
+ information, including jobs destined for that class. It is for all
+ direct accesses to the<VAR> /classes</VAR> resource and supports the
+ optional form variables <CODE>OP</CODE> and <CODE>WHICH_JOBS</CODE>. If
+ no form variables are supplied then the CGI lists all or a specific
+ class and the active jobs on each class.</P>
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:</P>
+<DL>
+<DT>completed</DT>
+<DD>Show only the completed jobs.</DD>
+<DT>not-completed</DT>
+<DD>Show only the active jobs.</DD>
+</DL>
+<P>The following <CODE>OP</CODE> values are supported:</P>
+<DL>
+<DT>print-test-page</DT>
+<DD>Print a PostScript test page.</DD>
+</DL>
+<H3><A NAME="5_2_3">5.2.3 jobs.cgi</A></H3>
+<P>The <CODE>jobs.cgi</CODE> program handles all of the job functions
+ and is run for all direct accesses to the<VAR> /jobs</VAR> resource.
+ For most operations it uses the <CODE>JOB_ID</CODE>, <CODE>OP</CODE>,
+ and <CODE>WHICH_JOBS</CODE> form variables to specify the action
+ requested.</P>
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:</P>
+<DL>
+<DT>completed</DT>
+<DD>Show only the completed jobs.</DD>
+<DT>not-completed</DT>
+<DD>Show only the active jobs.</DD>
+</DL>
+<P>The following <CODE>OP</CODE> values are supported:</P>
+<DL>
+<DT>job-cancel</DT>
+<DD>Cancels a job.</DD>
+<DT>job-hold</DT>
+<DD>Holds a job indefinitely.</DD>
+<DT>job-release</DT>
+<DD>Releases a job for printing.</DD>
+<DT>job-restart</DT>
+<DD>Restarts a stopped, cancelled, completed, or aborted print job.</DD>
+</DL>
+<H3><A NAME="5_2_4">5.2.4 printers.cgi</A></H3>
+<P>The <CODE>printers.cgi</CODE> program is responsible for listing
+ printer information, including jobs destined for that printer. It is
+ for all direct accesses to the<VAR> /printers</VAR> resource and
+ supports the optional form variables <CODE>OP</CODE> and <CODE>
+WHICH_JOBS</CODE>. If no form variables are supplied then the CGI lists
+ all or a specific printer and the active jobs on each printer.</P>
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:</P>
+<DL>
+<DT>completed</DT>
+<DD>Show only the completed jobs.</DD>
+<DT>not-completed</DT>
+<DD>Show only the active jobs.</DD>
+</DL>
+<P>The following <CODE>OP</CODE> values are supported:</P>
+<DL>
+<DT>print-test-page</DT>
+<DD>Print a PostScript test page.</DD>
+</DL>
+<H1 TYPE="A" VALUE="1"><A NAME="6">A Glossary</A></H1>
+<H2><A NAME="6_1">A.1 Terms</A></H2>
+<DL>
+<DT>C</DT>
+<DD>A computer language.</DD>
+<DT>parallel</DT>
+<DD>Sending or receiving data more than 1 bit at a time.</DD>
+<DT>pipe</DT>
+<DD>A one-way communications channel between two programs.</DD>
+<DT>serial</DT>
+<DD>Sending or receiving data 1 bit at a time.</DD>
+<DT>socket</DT>
+<DD>A two-way network communications channel.</DD>
+</DL>
+<H2><A NAME="6_2">A.2 Acronyms</A></H2>
+<DL>
+<DT>ASCII</DT>
+<DD>American Standard Code for Information Interchange</DD>
+<DT>CUPS</DT>
+<DD>Common UNIX Printing System</DD>
+<DT>ESC/P</DT>
+<DD>EPSON Standard Code for Printers</DD>
+<DT>FTP</DT>
+<DD>File Transfer Protocol</DD>
+<DT>HP-GL</DT>
+<DD>Hewlett-Packard Graphics Language</DD>
+<DT>HP-PCL</DT>
+<DD>Hewlett-Packard Page Control Language</DD>
+<DT>HP-PJL</DT>
+<DD>Hewlett-Packard Printer Job Language</DD>
+<DT>IETF</DT>
+<DD>Internet Engineering Task Force</DD>
+<DT>IPP</DT>
+<DD>Internet Printing Protocol</DD>
+<DT>ISO</DT>
+<DD>International Standards Organization</DD>
+<DT>LPD</DT>
+<DD>Line Printer Daemon</DD>
+<DT>MIME</DT>
+<DD>Multimedia Internet Mail Exchange</DD>
+<DT>PPD</DT>
+<DD>PostScript Printer Description</DD>
+<DT>SMB</DT>
+<DD>Server Message Block</DD>
+<DT>TFTP</DT>
+<DD>Trivial File Transfer Protocol</DD>
+</DL>
+</BODY>
+</HTML>
diff --git a/doc/translation.pdf b/doc/translation.pdf
new file mode 100644
index 000000000..8c9d3ee20
--- /dev/null
+++ b/doc/translation.pdf
Binary files differ
diff --git a/doc/translation.shtml b/doc/translation.shtml
new file mode 100644
index 000000000..c425cc017
--- /dev/null
+++ b/doc/translation.shtml
@@ -0,0 +1,734 @@
+<HTML>
+<HEAD>
+ <META NAME="COPYRIGHT" CONTENT="Copyright 2001-2004, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-TRANS-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Translation Guide</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This translation guide provides instructions for creating
+translations of the CUPS message catalogs and web pages for the
+Common UNIX Printing System ("CUPS") Version 1.1 software.
+
+<EMBED SRC="system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This translation guide is organized into the following
+sections:
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - Character Sets</LI>
+ <LI>4 - Message Catalogs</LI>
+ <LI>5 - Web Interfaces</LI>
+ <LI>A - Glossary</LI>
+</UL>
+
+<EMBED SRC="references.shtml">
+
+
+<H1>Character Sets</H1>
+
+<P>CUPS uses character set files to define the mapping of local
+character sets to Unicode code points, as well as the fonts that
+should be used for different ranges of characters.
+
+<P>CUPS includes files for common 8-bit encodings as well as
+UTF-8 for Unicode text. The format of these files is described
+in the CUPS Interface Design Description (IDD) document.
+Current character sets are enumerated in the CUPS API, so in
+order to add a new character set you must patch the CUPS source
+as well as provide a new charset file.
+
+<P>CUPS 1.1 supports the following character sets:
+
+<UL>
+
+ <LI>iso-8859-1
+ <LI>iso-8859-2
+ <LI>iso-8859-3
+ <LI>iso-8859-4
+ <LI>iso-8859-5
+ <LI>iso-8859-6
+ <LI>iso-8859-7
+ <LI>iso-8859-8
+ <LI>iso-8859-9
+ <LI>iso-8859-10
+ <LI>iso-8859-13
+ <LI>iso-8859-14
+ <LI>iso-8859-15
+ <LI>koi8-r
+ <LI>koi8-u
+ <LI>us-ascii
+ <LI>utf-8
+ <LI>windows-874
+ <LI>windows-1250
+ <LI>windows-1251
+ <LI>windows-1252
+ <LI>windows-1253
+ <LI>windows-1254
+ <LI>windows-1255
+ <LI>windows-1256
+ <LI>windows-1257
+ <LI>windows-1258
+
+</UL>
+
+<H1>Message Catalogs</H1>
+
+<P>CUPS message catalogs are text files that identify the
+default character set for the locale and a list of localized
+message strings for the CUPS software. The format of the
+message catalog files is described in the CUPS IDD.
+
+<P>Message catalogs are named <VAR>cups_ll</VAR>,
+<VAR>cups_ll_CC</VAR>, or <VAR>cups_ll_CC.charset</VAR>, where
+"ll" is the standard 2-letter abbreviation for the language,
+"CC" is the standard 2-letter abbreviation for the country, and
+"charset" is the charset name which may differ from the list
+above.
+
+<P>Each message catalog file is stored in a subdirectory named
+<VAR>ll</VAR>, <VAR>ll_CC</VAR>, or <VAR>ll_CC.charset</VAR> to
+match the trailing portion of the message catalog filename.
+
+<P>When translating a new message catalog, copy the <VAR>cups_C</VAR>
+message catalog file to a new subdirectory; to translate the
+message catalog to Canadian French, you would type the following
+commands:
+
+<UL><PRE>
+<KBD>cd locale <I>ENTER</I></KBD>
+<KBD>mkdir fr_CA <I>ENTER</I></KBD>
+<KBD>cp C/cups_C fr_CA/cups_fr_CA <I>ENTER</I></KBD>
+</PRE></UL>
+
+<P>Alternatively, you could copy the existing <VAR>cups_fr</VAR>
+message catalog and then make any changes necessary.
+
+<P>Once you have make your copy of the file, edit it using your
+favorite text editor to translate the text to the desired
+language. Be sure to preserve any numbers starting in the first
+column, as they indicate a new message number - you'll see this
+for the HTTP status messages.
+
+<P>Finally, add your locale to the list of locales in the
+makefile and run the following command to install it:
+
+<UL><PRE>
+<KBD>make install <I>ENTER</I></KBD>
+</PRE></UL>
+
+<H1>Web Interfaces</H1>
+
+<P>The CUPS scheduler provides a web interface that can be used
+to do many common printing and administration tasks. The built-in
+web server supports localization of web pages through the use of
+subdirectories for each locale, e.g. "fr" for French, "de" for
+German, "fr_ca" for French in Canada, and so forth.
+
+<H2>Template Files</H2>
+
+<P>Template files are HTML files with special formatting
+characters in them that allow substition of variables and
+arrays. The CUPS CGI programs (<CODE>admin.cgi</CODE>,
+<CODE>classes.cgi</CODE>, <CODE>jobs.cgi</CODE>, and
+<CODE>printers.cgi</CODE>) use these template file to provide
+dynamic content for the web interface. Template files are
+installed in the <VAR>/usr/share/cups/templates</VAR> directory
+by default.
+
+<P>Translated versions of the template files should be installed
+in the appropriate subdirectories under
+<VAR>/usr/share/cups/templates</VAR>. For example, Canadian
+French template files should be stored in the
+<VAR>/usr/share/cups/templates/fr_CA</VAR> directory.
+
+<H3>Inserting Attributes and Values</H3>
+
+<P>Template files consist of HTML with variable substitutions
+for named inside curley braces "{name}". Variable names are
+generally the IPP attribute names with the hyphen ("-") replaced
+by the underscore ("_") character. For example, the
+<TT>job-printer-uri</TT> attribute is renamed to
+<TT>job_printer_uri</TT>.
+
+<P>Curley braces ("{" and "}") to indicate substitutions, and
+the backslash ("\") character for quoting. To insert any of
+these special characters as-is you need to use the HTML
+<CODE>&amp;name;</CODE> mechanism or prefix each special
+character with the backslash ("\".)</P>
+
+<P>You substitute the value of a variable using
+<CODE>{NAME}</CODE> in your template file. If the variable is
+undefined then the <CODE>{NAME}</CODE> string is output
+as-is.</P>
+
+<P>To substitute an empty string if the variable is undefined, use
+<CODE>{?NAME}</CODE> instead.</P>
+
+<H3>Array Substitutions</H3>
+
+<P>The number of array elements can be inserted using
+<CODE>{#NAME}</CODE>. If the array is undefined then 0 is
+output. The current array element (starting at 1) is inserted
+with <CODE>{#}</CODE>.</P>
+
+<P>Arrays are handled using <CODE>{[NAME]</CODE> at the beginning of a
+section and <CODE>}</CODE> at the end. The information between the closing
+bracket ("]") and closing brace ("}") is repeated for as many elements as
+are in the named array. For example, the following template will display
+a list of each job in the <CODE>job_id</CODE> array:</P>
+
+<UL><PRE>
+&lt;TABLE&gt;
+&lt;TR&gt;
+ &lt;TH&gt;Job ID&lt;/TH&gt;
+ &lt;TH&gt;Destination&lt;/TH&gt;
+ &lt;TH&gt;Title&lt;/TH&gt;
+&lt;/TR&gt;
+
+{[job_id]
+&lt;TR&gt;
+ &lt;TD&gt;{?job_id}&lt;/TD&gt;
+ &lt;TD&gt;{?job_printer_name}&lt;/TD&gt;
+ &lt;TD&gt;{?job_name}&lt;/TD&gt;
+&lt;/TR&gt;
+}
+&lt;/TABLE&gt;
+</PRE></UL>
+
+<P>Arrays can be nested, however all elements within the curley
+braces ("{" and "}") are indexed using the innermost array.</P>
+
+<H3>Conditional Tests</H3>
+
+<P>Templates can also test variables against specific values and
+conditionally include text in the template. The format is:
+
+<UL><PRE>
+{<I>variable</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>=<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>!<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>&lt;<I>value</I>?<I>true</I>:<I>false</I>}
+{<I>variable</I>><I>value</I>?<I>true</I>:<I>false</I>}
+</PRE></UL>
+
+<P>where <VAR>true</VAR> is the text that is included if the
+condition is true and <VAR>false</VAR> is the text that is
+included if the condition is false. A value of <CODE>#</CODE> is
+replaced with the current element number (starting at 1.)
+
+<P>The character after the variable name specifies the condition
+to test:
+
+<CENTER><TABLE BORDER="1">
+<TR>
+ <TH WIDTH="5%">Char</TH>
+ <TH WIDTH="50%">Condition</TH>
+</TR>
+<TR>
+ <TD>?</TD>
+ <TD>True if <VAR>variable</VAR> exists.</TD>
+</TR>
+<TR>
+ <TD>=</TD>
+ <TD>True if <VAR>variable</VAR> is equal to <VAR>value</VAR>.</TD>
+</TR>
+<TR>
+ <TD>!</TD>
+ <TD>True if <VAR>variable</VAR> is not equal to <VAR>value</VAR>.</TD>
+</TR>
+<TR>
+ <TD>&lt;</TD>
+ <TD>True if <VAR>variable</VAR> is less than <VAR>value</VAR>.</TD>
+</TR>
+<TR>
+ <TD>></TD>
+ <TD>True if <VAR>variable</VAR> is greater than <VAR>value</VAR>.</TD>
+</TR>
+</TABLE></CENTER>
+
+<H3>Template File List</H3>
+
+<P>The following template files are used by the web interface:
+
+<DL>
+
+<DT>add-class.tmpl
+
+ <DD>This is the initial form that is shown to add a new
+ printer class.
+
+<DT>add-printer.tmpl
+
+ <DD>This is the initial form that is shown to add a new
+ printer.
+
+<DT>admin-op.tmpl
+
+ <DD>This is the template that is used to display an error
+ message when the admin interface sees an undefined
+ operation name.
+
+<DT>admin.tmpl
+
+ <DD>This is the template that shows the initial menu of
+ operations (add a class, manage classes, etc.)
+
+<DT>choose-device.tmpl
+
+ <DD>This is the form that shows the list of available
+ devices.
+
+<DT>choose-make.tmpl
+
+ <DD>This is the form that shows the list of available
+ manufacturers.
+
+<DT>choose-members.tmpl
+
+ <DD>This is the form that shows the list of available
+ printers that can be added to a class.
+
+<DT>choose-model.tmpl
+
+ <DD>This is the form that shows the list of available
+ printer models/drivers.
+
+<DT>choose-serial.tmpl
+
+ <DD>This is the form that allows the user to choose
+ a serial port and any options.
+
+<DT>choose-uri.tmpl
+
+ <DD>This is the form that allows the user to enter
+ a device URI for network printers.
+
+<DT>class-added.tmpl
+
+ <DD>This template shows the "class added" message.
+
+<DT>class-confirm.tmpl
+
+ <DD>This is the template used to confirm the
+ deletion of a class.
+
+<DT>class-deleted.tmpl
+
+ <DD>This template shows the "class deleted" message.
+
+<DT>classes.tmpl
+
+ <DD>This template shows one or more printer classes.
+
+<DT>class-modified.tmpl
+
+ <DD>This template shows the "class modified" message.
+
+<DT>config-printer.tmpl
+
+ <DD>This template starts the printer configuration form.
+
+<DT>config-printer2.tmpl
+
+ <DD>This template ends the printer configuration form.
+
+<DT>error.tmpl
+
+ <DD>This template displays a generic error message.
+
+<DT>header.tmpl
+
+ <DD>This template is used as the standard header on all dynamic
+ content.
+
+<DT>job-cancel.tmpl
+
+ <DD>This template shows "job cancelled".
+
+<DT>job-hold.tmpl
+
+ <DD>This template shows "job held".
+
+<DT>job-op.tmpl
+
+ <DD>This is the template that is used to display an
+ error message when the job interface sees an undefined
+ operation name.
+
+<DT>job-release.tmpl
+
+ <DD>This template shows "job released".
+
+<DT>job-restart.tmpl
+
+ <DD>This template shows "job restarted".
+
+<DT>jobs.tmpl
+
+ <DD>This template is used to list the print jobs on a server,
+ class, or printer.
+
+<DT>modify-class.tmpl
+
+ <DD>This template is used as the first form when modifying a
+ class.
+
+<DT>modify-printer.tmpl
+
+ <DD>This template is used as the first form when modifying a
+ printer.
+
+<DT>option-boolean.tmpl
+
+ <DD>This template is used to select a boolean PPD option.
+
+<DT>option-header.tmpl
+
+ <DD>This template is used to start a PPD option group.
+
+<DT>option-pickmany.tmpl
+
+ <DD>This template is used to select a multi-valued PPD option.
+
+<DT>option-pickone.tmpl
+
+ <DD>This template is used to select a single-valued PPD option.
+
+<DT>option-trailer.tmpl
+
+ <DD>This template is used to end a PPD option group.
+
+<DT>printer-accept.tmpl
+
+ <DD>This template shows "printer now accepting jobs".
+
+<DT>printer-added.tmpl
+
+ <DD>This template shows "printer added".
+
+<DT>printer-configured.tmpl
+
+ <DD>This template shows "printer configured".
+
+<DT>printer-confirm.tmpl
+
+ <DD>This template asks the user to confirm the deletion of a printer.
+
+<DT>printer-deleted.tmpl
+
+ <DD>This template shows "printer deleted".
+
+<DT>printer-modified.tmpl
+
+ <DD>This template shows "printer modified".
+
+<DT>printer-purge.tmpl
+
+ <DD>This template shows "printer has been purged of all jobs".
+
+<DT>printer-reject.tmpl
+
+ <DD>This template shows "printer now rejecting jobs".
+
+<DT>printer-start.tmpl
+
+ <DD>This template shows "printer started".
+
+<DT>printers.tmpl
+
+ <DD>This template is used to list information on one or more
+ printers.
+
+<DT>printer-stop.tmpl
+
+ <DD>This template shows "printer stopped".
+
+<DT>test-page.tmpl
+
+ <DD>This template shows "test page printed".
+
+<DT>trailer.tmpl
+
+ <DD>This template is used as the standard trailer on all dynamic
+ content.
+
+</DL>
+
+<H2>CGI Programs</H2>
+
+<P>CUPS uses four CGI programs to manage the dynamic web interfaces:
+
+<UL>
+
+ <LI><CODE>admin.cgi</CODE></LI>
+ <LI><CODE>classes.cgi</CODE></LI>
+ <LI><CODE>jobs.cgi</CODE></LI>
+ <LI><CODE>printers.cgi</CODE></LI>
+
+</UL>
+
+<H3>admin.cgi</H3>
+
+<P>The <CODE>admin.cgi</CODE> program handles all of the printer
+and class administration functions and is run for all direct
+accesses to the <VAR>/admin</VAR> resource. For most operations it uses the
+<CODE>PRINTER_NAME</CODE> and <CODE>OP</CODE> form variables to
+specify the action requested.
+
+<P>The following <CODE>OP</CODE> values are supported:
+
+<DL>
+
+<DT>accept-jobs</DT>
+
+ <DD>Accepts jobs on the named destination.</DD>
+
+<DT>add-class</DT>
+
+ <DD>Adds a new printer class. This operation also adds
+ several other form variables:
+
+ <DL>
+
+ <DT>MEMBER_URIS</DT>
+
+ <DD>Sets the members of the class. Multiple
+ <CODE>MEMBER_URIS</CODE> values can be
+ provided.</DD>
+
+ <DT>PRINTER_INFO</DT>
+
+ <DD>Sets the printer-info attribute for the
+ printer class, which is usually the printer
+ description.</DD>
+
+ <DT>PRINTER_LOCATION</DT>
+
+ <DD>Sets the printer-location attribute for the
+ printer class.</DD>
+
+ </DL>
+
+ </DD>
+
+<DT>add-printer</DT>
+
+ <DD>Adds a new printer. This operation also adds several other
+ form variables:
+
+ <DL>
+
+ <DT>BAUDRATE</DT>
+
+ <DD>Sets the baud rate for serial devices.</DD>
+
+ <DT>BITS</DT>
+
+ <DD>Sets the number of data bits for serial devices.</DD>
+
+ <DT>DEVICE_URI</DT>
+
+ <DD>Sets the device URI for the printer.</DD>
+
+ <DT>FLOW</DT>
+
+ <DD>Sets the flow control for serial devices.</DD>
+
+ <DT>PARITY</DT>
+
+ <DD>Sets the parity checking for serial devices.</DD>
+
+ <DT>PPD_NAME</DT>
+
+ <DD>Sets the driver name for the printer ("raw" for a
+ raw queue.)</DD>
+
+ <DT>PRINTER_INFO</DT>
+
+ <DD>Sets the printer-info attribute for the
+ printer, which is usually the printer
+ description.</DD>
+
+ <DT>PRINTER_LOCATION</DT>
+
+ <DD>Sets the printer-location attribute for the
+ printer.</DD>
+
+ </DL>
+
+ </DD>
+
+<DT>config-printer</DT>
+
+ <DD>Configures an existing printer. This operation uses
+ form variables of the same name as the options in the
+ printer's PPD file.</DD>
+
+<DT>delete-class</DT>
+
+ <DD>Deletes a printer class. The form variable <CODE>CONFIRM</CODE>
+ may be set to any value to bypass the confirmation page.</DD>
+
+<DT>delete-printer</DT>
+
+ <DD>Deletes a printer. The form variable <CODE>CONFIRM</CODE>
+ may be set to any value to bypass the confirmation page.</DD>
+
+<DT>modify-class</DT>
+
+ <DD>Modifies a printer class. See the add-class operation for a
+ list of form variables.</DD>
+
+<DT>modify-printer</DT>
+
+ <DD>Modifies a printer. See the add-printer operation for a
+ list of form variables.</DD>
+
+<DT>purge-jobs</DT>
+
+ <DD>Purges all jobs on the named destination.</DD>
+
+<DT>reject-jobs</DT>
+
+ <DD>Rejects new jobs on the named destination.</DD>
+
+<DT>start-printer</DT>
+
+ <DD>Starts the named destination.</DD>
+
+<DT>stop-printer</DT>
+
+ <DD>Stops the named destination.</DD>
+
+</DL>
+
+
+<H3>classes.cgi</H3>
+
+<P>The <CODE>classes.cgi</CODE> program is responsible for
+listing class information, including jobs destined for that
+class. It is for all direct accesses to the <VAR>/classes</VAR> resource
+and supports the optional form variables <CODE>OP</CODE> and
+<CODE>WHICH_JOBS</CODE>. If no form variables are supplied then
+the CGI lists all or a specific class and the active jobs on
+each class.
+
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:
+
+<DL>
+
+<DT>completed</DT>
+
+ <DD>Show only the completed jobs.</DD>
+
+<DT>not-completed</DT>
+
+ <DD>Show only the active jobs.</DD>
+
+</DL>
+
+<P>The following <CODE>OP</CODE> values are supported:
+
+<DL>
+
+<DT>print-test-page</DT>
+
+ <DD>Print a PostScript test page.</DD>
+
+</DL>
+
+<H3>jobs.cgi</H3>
+
+<P>The <CODE>jobs.cgi</CODE> program handles all of the job
+functions and is run for all direct accesses to the <VAR>/jobs</VAR>
+resource. For most operations it uses the
+<CODE>JOB_ID</CODE>, <CODE>OP</CODE>, and
+<CODE>WHICH_JOBS</CODE> form variables to specify the action
+requested.
+
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:
+
+<DL>
+
+<DT>completed</DT>
+
+ <DD>Show only the completed jobs.</DD>
+
+<DT>not-completed</DT>
+
+ <DD>Show only the active jobs.</DD>
+
+</DL>
+
+<P>The following <CODE>OP</CODE> values are supported:
+
+<DL>
+
+<DT>job-cancel</DT>
+
+ <DD>Cancels a job.</DD>
+
+<DT>job-hold</DT>
+
+ <DD>Holds a job indefinitely.</DD>
+
+<DT>job-release</DT>
+
+ <DD>Releases a job for printing.</DD>
+
+<DT>job-restart</DT>
+
+ <DD>Restarts a stopped, cancelled, completed, or aborted
+ print job.</DD>
+
+</DL>
+
+<H3>printers.cgi</H3>
+
+<P>The <CODE>printers.cgi</CODE> program is responsible for
+listing printer information, including jobs destined for that
+printer. It is for all direct accesses to the <VAR>/printers</VAR> resource
+and supports the optional form variables <CODE>OP</CODE> and
+<CODE>WHICH_JOBS</CODE>. If no form variables are supplied then
+the CGI lists all or a specific printer and the active jobs on
+each printer.
+
+<P>The following <CODE>WHICH_JOBS</CODE> values are supported:
+
+<DL>
+
+<DT>completed</DT>
+
+ <DD>Show only the completed jobs.</DD>
+
+<DT>not-completed</DT>
+
+ <DD>Show only the active jobs.</DD>
+
+</DL>
+
+<P>The following <CODE>OP</CODE> values are supported:
+
+<DL>
+
+<DT>print-test-page</DT>
+
+ <DD>Print a PostScript test page.</DD>
+
+</DL>
+
+
+<EMBED SRC="glossary.shtml">
+
+</BODY>
+</HTML>
diff --git a/filter/.cvsignore b/filter/.cvsignore
new file mode 100644
index 000000000..ad8218c39
--- /dev/null
+++ b/filter/.cvsignore
@@ -0,0 +1,16 @@
+gziptoany
+hpgltops
+images
+imagetops
+imagetoraster
+libcupsimage.2.dylib
+libcupsimage.a
+libcupsimage.dylib
+libcupsimage_s.a
+libcupsimage.sl.2
+libcupsimage.so.2
+pstops
+rastertodymo
+rastertoepson
+rastertohp
+texttops
diff --git a/filter/Dependencies b/filter/Dependencies
new file mode 100644
index 000000000..fcc94363b
--- /dev/null
+++ b/filter/Dependencies
@@ -0,0 +1,75 @@
+# DO NOT DELETE
+
+hpgl-attr.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+hpgl-attr.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+hpgl-attr.o: ../config.h
+hpgl-config.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
+hpgl-config.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+hpgl-config.o: ../cups/string.h ../config.h
+hpgl-main.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+hpgl-main.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+hpgl-main.o: ../config.h
+hpgl-prolog.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
+hpgl-prolog.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+hpgl-prolog.o: ../cups/string.h ../config.h
+hpgl-char.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+hpgl-char.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+hpgl-char.o: ../config.h
+hpgl-input.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+hpgl-input.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+hpgl-input.o: ../config.h
+hpgl-polygon.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
+hpgl-polygon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+hpgl-polygon.o: ../cups/string.h ../config.h
+hpgl-vector.o: hpgltops.h common.h ../cups/cups.h ../cups/ipp.h
+hpgl-vector.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+hpgl-vector.o: ../cups/string.h ../config.h
+image-bmp.o: image.h ../config.h raster.h
+image-colorspace.o: image.h ../config.h raster.h
+image-gif.o: image.h ../config.h raster.h
+image-jpeg.o: image.h ../config.h raster.h
+image-photocd.o: image.h ../config.h raster.h
+image-pix.o: image.h ../config.h raster.h
+image-png.o: image.h ../config.h raster.h
+image-pnm.o: image.h ../config.h raster.h
+image-sgi.o: image.h ../config.h raster.h image-sgi.h
+image-sgilib.o: image-sgi.h
+image-sun.o: image.h ../config.h raster.h
+image-tiff.o: image.h ../config.h raster.h
+image-zoom.o: image.h ../config.h raster.h
+image.o: image.h ../config.h raster.h ../cups/cups.h ../cups/ipp.h
+image.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h
+raster.o: raster.h
+form-main.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+form-main.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+form-main.o: ../config.h
+form-ps.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+form-ps.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+form-ps.o: ../config.h
+form-tree.o: form.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+form-tree.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+form-tree.o: ../config.h
+imagetops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+imagetops.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+imagetops.o: ../config.h image.h raster.h
+imagetoraster.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+imagetoraster.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h
+imagetoraster.o: ../cups/string.h ../config.h image.h raster.h
+common.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+common.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
+pstops.o: common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+pstops.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
+raster.o: raster.h
+rastertodymo.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+rastertodymo.o: ../cups/ppd.h ../cups/string.h ../config.h raster.h
+rastertoepson.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+rastertoepson.o: ../cups/ppd.h ../cups/ppd.h ../cups/string.h ../config.h
+rastertoepson.o: raster.h
+rastertohp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+rastertohp.o: ../cups/ppd.h ../cups/string.h ../config.h raster.h
+texttops.o: textcommon.h common.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+texttops.o: ../cups/md5.h ../cups/ppd.h ../cups/language.h ../cups/string.h
+texttops.o: ../config.h
+textcommon.o: textcommon.h common.h ../cups/cups.h ../cups/ipp.h
+textcommon.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
+textcommon.o: ../cups/string.h ../config.h
diff --git a/filter/Makefile b/filter/Makefile
new file mode 100644
index 000000000..7b182fe97
--- /dev/null
+++ b/filter/Makefile
@@ -0,0 +1,273 @@
+#
+# "$Id$"
+#
+# Filter makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+# This file is subject to the Apple OS-Developed Software exception.
+#
+
+include ../Makedefs
+
+FILTERS = gziptoany hpgltops texttops pstops imagetops imagetoraster \
+ rastertodymo rastertoepson rastertohp
+TARGETS = $(FILTERS)
+
+HPGLOBJS = hpgl-attr.o hpgl-config.o hpgl-main.o hpgl-prolog.o \
+ hpgl-char.o hpgl-input.o hpgl-polygon.o hpgl-vector.o
+IMAGEOBJS = image-bmp.o image-colorspace.o image-gif.o image-jpeg.o \
+ image-photocd.o image-pix.o image-png.o image-pnm.o \
+ image-sgi.o image-sgilib.o image-sun.o image-tiff.o \
+ image-zoom.o image.o raster.o
+FORMOBJS = form-attr.o form-main.o form-ps.o form-text.o form-tree.o
+OBJS = $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \
+ gziptoany.o imagetops.o imagetoraster.o common.o pstops.o \
+ rastertodymo.o rastertoepson.o rastertohp.o \
+ texttops.o textcommon.o
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS) $(LIBCUPSIMAGE) libcupsimage.a
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS) $(LIBCUPSIMAGE) libcupsimage.a
+ $(RM) `basename $(LIBCUPSIMAGE) .2` libcupsimage.dylib
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install: all installhdrs
+ $(INSTALL_DIR) $(SERVERBIN)/filter
+ for file in $(TARGETS); do \
+ $(INSTALL_BIN) $$file $(SERVERBIN)/filter; \
+ done
+ $(INSTALL_DIR) $(LIBDIR)
+ $(INSTALL_LIB) $(LIBCUPSIMAGE) $(LIBDIR)
+ -if test $(LIBCUPSIMAGE) = "libcupsimage.so.2" -o $(LIBCUPSIMAGE) = "libcupsimage.sl.2"; then \
+ $(RM) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \
+ $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \
+ fi
+ -if test $(LIBCUPSIMAGE) = "libcupsimage.2.dylib"; then \
+ $(STRIP) -x $(LIBDIR)/$(LIBCUPSIMAGE); \
+ $(RM) $(LIBDIR)/libcupsimage.dylib; \
+ $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/libcupsimage.dylib; \
+ fi
+ -if test $(LIBCUPSIMAGE) != "libcupsimage.a"; then \
+ $(INSTALL_LIB) libcupsimage.a $(LIBDIR); \
+ $(RANLIB) $(LIBDIR)/libcupsimage.a; \
+ fi
+
+installhdrs:
+ $(INSTALL_DIR) $(INCLUDEDIR)/cups
+ $(INSTALL_DATA) image.h $(INCLUDEDIR)/cups
+ $(INSTALL_DATA) raster.h $(INCLUDEDIR)/cups
+
+
+#
+# formtops
+#
+
+formtops: $(FORMOBJS) common.o ../Makedefs ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ $(FORMOBJS) common.o $(LIBS) -lm
+
+
+#
+# gziptoany
+#
+
+gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ gziptoany.o $(LIBZ) $(LIBS)
+
+
+#
+# hpgltops
+#
+
+hpgltops: $(HPGLOBJS) common.o ../Makedefs ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ $(HPGLOBJS) common.o $(LIBS) -lm
+
+
+#
+# libcupsimage.so.2, libcupsimage.sl.2
+#
+
+libcupsimage.so.2 libcupsimage.sl.2: $(IMAGEOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ $(IMAGEOBJS) $(DSOLIBS) -lm
+ $(RM) `basename $@ .2`
+ $(LN) $@ `basename $@ .2`
+
+
+#
+# libcupsimage.2.dylib
+#
+
+libcupsimage.2.dylib: $(IMAGEOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ \
+ -install_name $(libdir)/$@ \
+ -current_version 2.1.0 \
+ -compatibility_version 2.0.0 \
+ $(IMAGEOBJS) $(DSOLIBS) -L../cups $(LINKCUPS) -lm -lcc_dynamic
+ $(RM) libcupsimage.dylib
+ $(LN) $@ libcupsimage.dylib
+
+
+#
+# libcupsimage_s.a
+#
+
+libcupsimage_s.a: $(IMAGEOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -Wl,-berok -o libcupsimage_s.o $(IMAGEOBJS) \
+ $(DSOLIBS) -lm
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ libcupsimage_s.o
+
+
+#
+# libcupsimage.la
+#
+
+libcupsimage.la: $(IMAGEOBJS) ../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ $(IMAGEOBJS:.o=.lo) $(DSOLIBS) \
+ -rpath $(LIBDIR) -version-info 2:1
+
+
+#
+# libcupsimage.a
+#
+
+libcupsimage.a: $(IMAGEOBJS) ../Makedefs
+ echo Archiving $@...
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $(IMAGEOBJS)
+ $(RANLIB) $@
+
+
+#
+# testimage
+#
+
+testimage: testimage.o libcupsimage.a ../Makedefs
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ testimage.o libcupsimage.a \
+ $(IMGLIBS) $(DSOLIBS) $(LIBS)
+
+
+#
+# imagetops
+#
+
+imagetops: imagetops.o common.o $(LIBCUPSIMAGE) ../Makedefs \
+ ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ imagetops.o common.o $(LINKCUPSIMAGE) \
+ $(IMGLIBS) $(LIBS)
+
+
+#
+# imagetoraster
+#
+
+imagetoraster: imagetoraster.o common.o $(LIBCUPSIMAGE) ../Makedefs \
+ ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ imagetoraster.o common.o $(LINKCUPSIMAGE) \
+ $(IMGLIBS) $(LIBS)
+
+
+#
+# pstops
+#
+
+pstops: pstops.o common.o ../Makedefs ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS)
+
+
+#
+# rastertodymo
+#
+
+rastertodymo: rastertodymo.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ rastertodymo.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+
+
+#
+# rastertoepson
+#
+
+rastertoepson: rastertoepson.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ rastertoepson.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+
+
+#
+# rastertohp
+#
+
+rastertohp: rastertohp.o ../Makedefs ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+
+
+#
+# texttops
+#
+
+texttops: texttops.o textcommon.o common.o ../Makedefs \
+ ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ texttops.o textcommon.o common.o $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/filter/common.c b/filter/common.c
new file mode 100644
index 000000000..cd8f613ee
--- /dev/null
+++ b/filter/common.c
@@ -0,0 +1,471 @@
+/*
+ * "$Id$"
+ *
+ * Common filter routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * SetCommonOptions() - Set common filter options for media size,
+ * etc.
+ * UpdatePageVars() - Update the page variables for the orientation.
+ * WriteCommon() - Write common procedures...
+ * WriteLabelProlog() - Write the prolog with the classification
+ * and page label.
+ * WriteLabels() - Write the actual page labels.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+#include <locale.h>
+
+
+/*
+ * Globals...
+ */
+
+int Orientation = 0, /* 0 = portrait, 1 = landscape, etc. */
+ Duplex = 0, /* Duplexed? */
+ LanguageLevel = 1, /* Language level of printer */
+ ColorDevice = 1; /* Do color text? */
+float PageLeft = 18.0f, /* Left margin */
+ PageRight = 594.0f, /* Right margin */
+ PageBottom = 36.0f, /* Bottom margin */
+ PageTop = 756.0f, /* Top margin */
+ PageWidth = 612.0f, /* Total page width */
+ PageLength = 792.0f; /* Total page length */
+
+
+/*
+ * 'SetCommonOptions()' - Set common filter options for media size, etc.
+ */
+
+ppd_file_t * /* O - PPD file */
+SetCommonOptions(int num_options, /* I - Number of options */
+ cups_option_t *options, /* I - Options */
+ int change_size) /* I - Change page size? */
+{
+ ppd_file_t *ppd; /* PPD file */
+ ppd_size_t *pagesize; /* Current page size */
+ const char *val; /* Option value */
+
+
+#ifdef LC_TIME
+ setlocale(LC_TIME, "");
+#endif /* LC_TIME */
+
+ ppd = ppdOpenFile(getenv("PPD"));
+
+ ppdMarkDefaults(ppd);
+ cupsMarkOptions(ppd, num_options, options);
+
+ if ((pagesize = ppdPageSize(ppd, NULL)) != NULL)
+ {
+ PageWidth = pagesize->width;
+ PageLength = pagesize->length;
+ PageTop = pagesize->top;
+ PageBottom = pagesize->bottom;
+ PageLeft = pagesize->left;
+ PageRight = pagesize->right;
+
+ fprintf(stderr, "DEBUG: Page = %.0fx%.0f; %.0f,%.0f to %.0f,%.0f\n",
+ PageWidth, PageLength, PageLeft, PageBottom, PageRight, PageTop);
+ }
+
+ if (ppd != NULL)
+ {
+ ColorDevice = ppd->color_device;
+ LanguageLevel = ppd->language_level;
+ }
+
+ if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
+ {
+ if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 &&
+ strcasecmp(val, "false") != 0)
+ {
+ if (ppd && ppd->landscape > 0)
+ Orientation = 1;
+ else
+ Orientation = 3;
+ }
+ }
+ else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
+ {
+ /*
+ * Map IPP orientation values to 0 to 3:
+ *
+ * 3 = 0 degrees = 0
+ * 4 = 90 degrees = 1
+ * 5 = -90 degrees = 3
+ * 6 = 180 degrees = 2
+ */
+
+ Orientation = atoi(val) - 3;
+ if (Orientation >= 2)
+ Orientation ^= 1;
+ }
+
+ if ((val = cupsGetOption("page-left", num_options, options)) != NULL)
+ {
+ switch (Orientation & 3)
+ {
+ case 0 :
+ PageLeft = (float)atof(val);
+ break;
+ case 1 :
+ PageBottom = (float)atof(val);
+ break;
+ case 2 :
+ PageRight = PageWidth - (float)atof(val);
+ break;
+ case 3 :
+ PageTop = PageLength - (float)atof(val);
+ break;
+ }
+ }
+
+ if ((val = cupsGetOption("page-right", num_options, options)) != NULL)
+ {
+ switch (Orientation & 3)
+ {
+ case 0 :
+ PageRight = PageWidth - (float)atof(val);
+ break;
+ case 1 :
+ PageTop = PageLength - (float)atof(val);
+ break;
+ case 2 :
+ PageLeft = (float)atof(val);
+ break;
+ case 3 :
+ PageBottom = (float)atof(val);
+ break;
+ }
+ }
+
+ if ((val = cupsGetOption("page-bottom", num_options, options)) != NULL)
+ {
+ switch (Orientation & 3)
+ {
+ case 0 :
+ PageBottom = (float)atof(val);
+ break;
+ case 1 :
+ PageLeft = (float)atof(val);
+ break;
+ case 2 :
+ PageTop = PageLength - (float)atof(val);
+ break;
+ case 3 :
+ PageRight = PageWidth - (float)atof(val);
+ break;
+ }
+ }
+
+ if ((val = cupsGetOption("page-top", num_options, options)) != NULL)
+ {
+ switch (Orientation & 3)
+ {
+ case 0 :
+ PageTop = PageLength - (float)atof(val);
+ break;
+ case 1 :
+ PageRight = PageWidth - (float)atof(val);
+ break;
+ case 2 :
+ PageBottom = (float)atof(val);
+ break;
+ case 3 :
+ PageLeft = (float)atof(val);
+ break;
+ }
+ }
+
+ if (change_size)
+ UpdatePageVars();
+
+ if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "Duplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "JCLDuplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "JCLDuplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "EFDuplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "EFDuplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "KD03Duplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "KD03Duplex", "DuplexTumble"))
+ Duplex = 1;
+
+ return (ppd);
+}
+
+
+/*
+ * 'UpdatePageVars()' - Update the page variables for the orientation.
+ */
+
+void
+UpdatePageVars(void)
+{
+ float temp; /* Swapping variable */
+
+
+ switch (Orientation & 3)
+ {
+ case 0 : /* Portait */
+ break;
+
+ case 1 : /* Landscape */
+ temp = PageLeft;
+ PageLeft = PageBottom;
+ PageBottom = temp;
+
+ temp = PageRight;
+ PageRight = PageTop;
+ PageTop = temp;
+
+ temp = PageWidth;
+ PageWidth = PageLength;
+ PageLength = temp;
+ break;
+
+ case 2 : /* Reverse Portrait */
+ temp = PageWidth - PageLeft;
+ PageLeft = PageWidth - PageRight;
+ PageRight = temp;
+
+ temp = PageLength - PageBottom;
+ PageBottom = PageLength - PageTop;
+ PageTop = temp;
+ break;
+
+ case 3 : /* Reverse Landscape */
+ temp = PageWidth - PageLeft;
+ PageLeft = PageWidth - PageRight;
+ PageRight = temp;
+
+ temp = PageLength - PageBottom;
+ PageBottom = PageLength - PageTop;
+ PageTop = temp;
+
+ temp = PageLeft;
+ PageLeft = PageBottom;
+ PageBottom = temp;
+
+ temp = PageRight;
+ PageRight = PageTop;
+ PageTop = temp;
+
+ temp = PageWidth;
+ PageWidth = PageLength;
+ PageLength = temp;
+ break;
+ }
+}
+
+
+/*
+ * 'WriteCommon()' - Write common procedures...
+ */
+
+void
+WriteCommon(void)
+{
+ puts("% x y w h ESPrc - Clip to a rectangle.\n"
+ "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
+ "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath clip newpath}bind}ifelse put");
+ puts("% x y w h ESPrf - Fill a rectangle.\n"
+ "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
+ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath fill grestore}bind}ifelse put");
+ puts("% x y w h ESPrs - Stroke a rectangle.\n"
+ "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
+ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+ "neg 0 rlineto closepath stroke grestore}bind}ifelse put");
+}
+
+
+/*
+ * 'WriteLabelProlog()' - Write the prolog with the classification
+ * and page label.
+ */
+
+void
+WriteLabelProlog(const char *label, /* I - Page label */
+ float bottom, /* I - Bottom position in points */
+ float top, /* I - Top position in points */
+ float width) /* I - Width in points */
+{
+ const char *classification; /* CLASSIFICATION environment variable */
+ const char *ptr; /* Temporary string pointer */
+
+
+ /*
+ * First get the current classification...
+ */
+
+ if ((classification = getenv("CLASSIFICATION")) == NULL)
+ classification = "";
+ if (strcmp(classification, "none") == 0)
+ classification = "";
+
+ /*
+ * If there is nothing to show, bind an empty 'write labels' procedure
+ * and return...
+ */
+
+ if (!classification[0] && (label == NULL || !label[0]))
+ {
+ puts("userdict/ESPwl{}bind put");
+ return;
+ }
+
+ /*
+ * Set the classification + page label string...
+ */
+
+ printf("userdict");
+ if (strcmp(classification, "confidential") == 0)
+ printf("/ESPpl(CONFIDENTIAL");
+ else if (strcmp(classification, "classified") == 0)
+ printf("/ESPpl(CLASSIFIED");
+ else if (strcmp(classification, "secret") == 0)
+ printf("/ESPpl(SECRET");
+ else if (strcmp(classification, "topsecret") == 0)
+ printf("/ESPpl(TOP SECRET");
+ else if (strcmp(classification, "unclassified") == 0)
+ printf("/ESPpl(UNCLASSIFIED");
+ else
+ {
+ printf("/ESPpl(");
+
+ for (ptr = classification; *ptr; ptr ++)
+ if (*ptr < 32 || *ptr > 126)
+ printf("\\%03o", *ptr);
+ else if (*ptr == '_')
+ putchar(' ');
+ else
+ {
+ if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
+ putchar('\\');
+
+ putchar(*ptr);
+ }
+ }
+
+ if (label)
+ {
+ if (classification[0])
+ printf(" - ");
+
+ /*
+ * Quote the label string as needed...
+ */
+
+ for (ptr = label; *ptr; ptr ++)
+ if (*ptr < 32 || *ptr > 126)
+ printf("\\%03o", *ptr);
+ else
+ {
+ if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
+ putchar('\\');
+
+ putchar(*ptr);
+ }
+ }
+
+ puts(")put");
+
+ /*
+ * Then get a 14 point Helvetica-Bold font...
+ */
+
+ puts("userdict/ESPpf /Helvetica-Bold findfont 14 scalefont put");
+
+ /*
+ * Finally, the procedure to write the labels on the page...
+ */
+
+ puts("userdict/ESPwl{");
+ puts(" ESPpf setfont");
+ printf(" ESPpl stringwidth pop dup 12 add exch -0.5 mul %.0f add\n",
+ width * 0.5f);
+ puts(" 1 setgray");
+ printf(" dup 6 sub %.0f 3 index 20 ESPrf\n", bottom - 2.0);
+ printf(" dup 6 sub %.0f 3 index 20 ESPrf\n", top - 18.0);
+ puts(" 0 setgray");
+ printf(" dup 6 sub %.0f 3 index 20 ESPrs\n", bottom - 2.0);
+ printf(" dup 6 sub %.0f 3 index 20 ESPrs\n", top - 18.0);
+ printf(" dup %.0f moveto ESPpl show\n", bottom + 2.0);
+ printf(" %.0f moveto ESPpl show\n", top - 14.0);
+ puts("pop");
+ puts("}bind put");
+}
+
+
+/*
+ * 'WriteLabels()' - Write the actual page labels.
+ */
+
+void
+WriteLabels(int orient) /* I - Orientation of the page */
+{
+ float width, /* Width of page */
+ length; /* Length of page */
+
+
+ puts("gsave");
+
+ if ((orient ^ Orientation) & 1)
+ {
+ width = PageLength;
+ length = PageWidth;
+ }
+ else
+ {
+ width = PageWidth;
+ length = PageLength;
+ }
+
+ switch (orient & 3)
+ {
+ case 1 : /* Landscape */
+ printf("%.1f 0.0 translate 90 rotate\n", length);
+ break;
+ case 2 : /* Reverse Portrait */
+ printf("%.1f %.1f translate 180 rotate\n", width, length);
+ break;
+ case 3 : /* Reverse Landscape */
+ printf("0.0 %.1f translate -90 rotate\n", width);
+ break;
+ }
+
+ puts("ESPwl");
+ puts("grestore");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/common.h b/filter/common.h
new file mode 100644
index 000000000..110707c27
--- /dev/null
+++ b/filter/common.h
@@ -0,0 +1,92 @@
+/*
+ * "$Id$"
+ *
+ * Common filter definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/string.h>
+
+
+/*
+ * C++ magic...
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*
+ * Globals...
+ */
+
+extern int Orientation, /* 0 = portrait, 1 = landscape, etc. */
+ Duplex, /* Duplexed? */
+ LanguageLevel, /* Language level of printer */
+ ColorDevice; /* Do color text? */
+extern float PageLeft, /* Left margin */
+ PageRight, /* Right margin */
+ PageBottom, /* Bottom margin */
+ PageTop, /* Top margin */
+ PageWidth, /* Total page width */
+ PageLength; /* Total page length */
+
+
+/*
+ * Prototypes...
+ */
+
+extern ppd_file_t *SetCommonOptions(int num_options, cups_option_t *options,
+ int change_size);
+extern void UpdatePageVars(void);
+extern void WriteCommon(void);
+extern void WriteLabelProlog(const char *label, float bottom,
+ float top, float width);
+extern void WriteLabels(int orient);
+
+
+/*
+ * C++ magic...
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/form-main.c b/filter/form-main.c
new file mode 100644
index 000000000..d802347f1
--- /dev/null
+++ b/filter/form-main.c
@@ -0,0 +1,62 @@
+/*
+ * "$Id$"
+ *
+ * CUPS form main entry for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Load the specified form file and output PostScript.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "form.h"
+
+
+/*
+ * Globals...
+ */
+
+int NumOptions; /* Number of command-line options */
+cups_option_t *Options; /* Command-line options */
+ppd_file_t *PPD; /* PPD file */
+
+
+/*
+ * 'main()' - Load the specified form file and output PostScript.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/form-ps.c b/filter/form-ps.c
new file mode 100644
index 000000000..352f577de
--- /dev/null
+++ b/filter/form-ps.c
@@ -0,0 +1,49 @@
+/*
+ * "$Id$"
+ *
+ * CUPS form PostScript routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "form.h"
+
+
+/*
+ * 'formWrite()' - Write PostScript output for the given form document.
+ */
+
+void
+formWrite(tree_t *t) /* I - Document tree to write */
+{
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/form-tree.c b/filter/form-tree.c
new file mode 100644
index 000000000..cc36bcccf
--- /dev/null
+++ b/filter/form-tree.c
@@ -0,0 +1,624 @@
+/*
+ * "$Id$"
+ *
+ * CUPS form document tree routines for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "form.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_attr(attr_t *a0, attr_t *a1);
+static int compare_elements(char **e0, char **e1);
+static int parse_attr(tree_t *t, FILE *fp);
+static int parse_element(tree_t *t, FILE *fp);
+
+
+/*
+ * Local globals...
+ */
+
+static char *elements[] =
+ {
+ "",
+ "!--",
+ "ARC",
+ "BOX",
+ "BR",
+ "B",
+ "CUPSFORM",
+ "DEFVAR",
+ "FONT",
+ "H1",
+ "H2",
+ "H3",
+ "H4",
+ "H5",
+ "H6",
+ "HEAD",
+ "IMG",
+ "I",
+ "LINE",
+ "PAGE",
+ "PIE",
+ "POLY",
+ "PRE",
+ "P",
+ "RECT",
+ "TEXT",
+ "TT",
+ "VAR"
+ };
+
+
+/*
+ * 'formDelete()' - Delete a node and its children.
+ */
+
+void
+formDelete(tree_t *t) /* I - Tree node */
+{
+}
+
+
+/*
+ * 'formGetAttr()' - Get a node attribute value.
+ */
+
+char * /* O - Value or NULL */
+formGetAttr(tree_t *t, /* I - Tree node */
+ const char *name) /* I - Name of attribute */
+{
+}
+
+
+/*
+ * 'formNew()' - Create a new form node.
+ */
+
+tree_t * /* O - New tree node */
+formNew(tree_t *p) /* I - Parent node */
+{
+ tree_t *t; /* New tree node */
+
+
+ /*
+ * Allocate the new node...
+ */
+
+ if ((t = (tree_t *)calloc(sizeof(tree_t), 1)) == NULL)
+ return (NULL);
+
+ /*
+ * Set/copy attributes...
+ */
+
+ if (p == NULL)
+ {
+ t->bg[0] = 1.0;
+ t->bg[1] = 1.0;
+ t->bg[2] = 1.0;
+ t->halign = HALIGN_LEFT;
+ t->valign = VALIGN_MIDDLE;
+ t->typeface = "Courier";
+ t->size = 12.0;
+ }
+ else
+ {
+ memcpy(t, p, sizeof(tree_t));
+
+ t->prev = NULL;
+ t->next = NULL;
+ t->child = NULL;
+ t->last_child = NULL;
+ t->parent = NULL;
+ t->num_attrs = 0;
+ t->attrs = NULL;
+ t->data = NULL;
+ }
+
+ /*
+ * Return the new node...
+ */
+
+ return (t);
+}
+
+
+/*
+ * 'formRead()' - Read a form tree from a file.
+ */
+
+tree_t * /* O - New form tree */
+formRead(FILE *fp, /* I - File to read from */
+ tree_t *p) /* I - Parent node */
+{
+ int ch, /* Character from file */
+ closech, /* Closing character */
+ have_whitespace; /* Leading whitespace? */
+ static char s[10240]; /* String from file */
+ uchar *ptr, /* Pointer in string */
+ glyph[16], /* Glyph name (&#nnn;) */
+ *glyphptr; /* Pointer in glyph string */
+ tree_t *tree, /* "top" of this tree */
+ *t, /* New tree node */
+ *prev, /* Previous tree node */
+ *temp; /* Temporary looping var */
+ uchar *face, /* Typeface for FONT tag */
+ *color, /* Color for FONT tag */
+ *size; /* Size for FONT tag */
+
+
+ /*
+ * Start off with no previous tree node...
+ */
+
+ prev = NULL;
+ tree = NULL;
+
+ /*
+ * Parse data until we hit end-of-file...
+ */
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ /*
+ * Ignore leading whitespace...
+ */
+
+ have_whitespace = 0;
+ closech = '/';
+
+ if (p == NULL || !p->preformatted)
+ {
+ while (isspace(ch & 255))
+ {
+ have_whitespace = 1;
+ ch = getc(fp);
+ }
+
+ if (ch == EOF)
+ break;
+ }
+
+ /*
+ * Allocate a new tree node - use calloc() to get zeroed data...
+ */
+
+ t = formNew(p);
+
+ /*
+ * See what the character was...
+ */
+
+ if (ch == '<')
+ {
+ /*
+ * Markup char; grab the next char to see if this is a /...
+ */
+
+ ch = getc(fp);
+ if (ch == ' ')
+ {
+ /*
+ * Illegal lone "<"! Ignore it...
+ */
+
+ free(t);
+ continue;
+ }
+
+ if (ch != '/')
+ ungetc(ch, fp);
+
+ if (parse_element(t, fp) < 0)
+ {
+ free(t);
+ break;
+ }
+
+ if ((closech = getc(fp)) == '/')
+ getc(fp);
+
+ /*
+ * If this is the matching close mark, or if we are starting the same
+ * element, or if we've completed a list, we're done!
+ */
+
+ if (ch == '/')
+ {
+ /*
+ * Close element; find matching element...
+ */
+
+ for (temp = p; temp != NULL; temp = temp->p)
+ if (temp->element == t->element)
+ break;
+
+ free(t);
+
+ if (temp != NULL)
+ break;
+ else
+ continue;
+ }
+ }
+ else if (t->preformatted)
+ {
+ /*
+ * Read a pre-formatted string into the current tree node...
+ */
+
+ ptr = s;
+ while (ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
+ {
+ if (ch == '&')
+ {
+ for (glyphptr = glyph;
+ (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
+ glyphptr ++)
+ if (!isalnum(ch & 255))
+ break;
+ else
+ *glyphptr = ch;
+
+ *glyphptr = '\0';
+ if (atoi(glyph) > 0)
+ ch = atoi(glyph);
+ else if (strcmp(glyph, "lt") == 0)
+ ch = '<';
+ else if (strcmp(glyph, "gt") == 0)
+ ch = '>';
+ else if (strcmp(glyph, "quot") == 0)
+ ch = '\'';
+ else if (strcmp(glyph, "nbsp") == 0)
+ ch = ' ';
+ else
+ ch = '&';
+ }
+
+ if (ch != 0)
+ *ptr++ = ch;
+
+ if (ch == '\n')
+ break;
+
+ ch = getc(fp);
+ }
+
+ *ptr = '\0';
+
+ if (ch == '<')
+ ungetc(ch, fp);
+
+ t->element = ELEMENT_FRAGMENT;
+ t->data = strdup(s);
+ }
+ else
+ {
+ /*
+ * Read the next string fragment...
+ */
+
+ ptr = s;
+ if (have_whitespace)
+ *ptr++ = ' ';
+
+ while (!isspace(ch & 255) && ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
+ {
+ if (ch == '&')
+ {
+ for (glyphptr = glyph;
+ (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
+ glyphptr ++)
+ if (!isalnum(ch & 255))
+ break;
+ else
+ *glyphptr = ch;
+
+ *glyphptr = '\0';
+ if (atoi(glyph) > 0)
+ ch = atoi(glyph);
+ else if (strcmp(glyph, "lt") == 0)
+ ch = '<';
+ else if (strcmp(glyph, "gt") == 0)
+ ch = '>';
+ else if (strcmp(glyph, "quot") == 0)
+ ch = '\'';
+ else if (strcmp(glyph, "nbsp") == 0)
+ ch = ' ';
+ else
+ ch = '&';
+ }
+
+ if (ch != 0)
+ *ptr++ = ch;
+
+ ch = getc(fp);
+ }
+
+ if (isspace(ch & 255))
+ *ptr++ = ' ';
+
+ *ptr = '\0';
+
+ if (ch == '<')
+ ungetc(ch, fp);
+
+ t->element = ELEMENT_FRAGMENT;
+ t->data = strdup(s);
+ }
+
+ /*
+ * If the p tree pointer is not NULL and this is the first
+ * entry we've read, set the child pointer...
+ */
+
+ if (p != NULL && prev == NULL)
+ p->child = t;
+
+ if (p != NULL)
+ p->last_child = t;
+
+ /*
+ * Do the prev/next links...
+ */
+
+ t->parent = p;
+ t->prev = prev;
+ if (prev != NULL)
+ prev->next = t;
+ else
+ tree = t;
+
+ prev = t;
+
+ /*
+ * Do child stuff as needed...
+ */
+
+ if (closech == '>')
+ t->child = formRead(t, fp);
+ }
+
+ return (tree);
+}
+
+
+/*
+ * 'formSetAttr()' - Set a node attribute.
+ */
+
+void
+formSetAttr(tree_t *t, /* I - Tree node */
+ const char *name, /* I - Attribute name */
+ const char *value) /* I - Attribute value */
+{
+}
+
+
+/*
+ * 'compare_attr()' - Compare two attributes.
+ */
+
+static int /* O - -1 if a0 < a1, etc. */
+compare_attr(attr_t *a0, /* I - First attribute */
+ attr_t *a1) /* I - Second attribute */
+{
+ return (strcasecmp(a0->name, a1->name));
+}
+
+
+/*
+ * 'compare_elements()' - Compare two elements.
+ */
+
+static int /* O - -1 if e0 < e1, etc. */
+compare_elements(char **e0, /* I - First element */
+ char **e1) /* I - Second element */
+{
+ return (strcasecmp(*e0, *e1));
+}
+
+
+/*
+ * 'parse_attr()' - Parse an element attribute string.
+ */
+
+static int /* O - -1 on error, 0 on success */
+parse_attr(tree_t *t, /* I - Current tree node */
+ FILE *fp) /* I - Input file */
+{
+ char name[1024], /* Name of attr */
+ value[10240], /* Value of attr */
+ *ptr; /* Temporary pointer */
+ int ch; /* Character from file */
+
+
+ ptr = name;
+ while ((ch = getc(fp)) != EOF)
+ if (isalnum(ch & 255))
+ {
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = ch;
+ }
+ else
+ break;
+
+ *ptr = '\0';
+
+ while (isspace(ch & 255) || ch == '\r')
+ ch = getc(fp);
+
+ switch (ch)
+ {
+ default :
+ ungetc(ch, fp);
+ return (formSetAttr(t, name, NULL));
+ case EOF :
+ return (-1);
+ case '=' :
+ ptr = value;
+ ch = getc(fp);
+
+ while (isspace(ch & 255) || ch == '\r')
+ ch = getc(fp);
+
+ if (ch == EOF)
+ return (-1);
+
+ if (ch == '\'')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\'')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ }
+ else if (ch == '\"')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\"')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ }
+ else
+ {
+ *ptr++ = ch;
+ while ((ch = getc(fp)) != EOF)
+ if (isspace(ch & 255) || ch == '>' || ch == '/' || ch == '\r')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ if (ch == '>' || ch == '/')
+ ungetc(ch, fp);
+ }
+
+ return (formSetAttr(t, name, value));
+ }
+}
+
+
+/*
+ * 'parse_element()' - Parse an element.
+ */
+
+static int /* O - -1 on error or ELEMENT_nnnn */
+parse_element(tree_t *t, /* I - Current tree node */
+ FILE *fp) /* I - Input file */
+{
+ int ch; /* Character from file */
+ char element[255], /* Element string... */
+ *eptr, /* Current character... */
+ comment[10240], /* Comment string */
+ *cptr, /* Current char... */
+ **temp; /* Element variable entry */
+
+
+ eptr = element;
+
+ while ((ch = getc(fp)) != EOF && eptr < (element + sizeof(element) - 1))
+ if (ch == '>' || ch == '/' || isspace(ch & 255))
+ break;
+ else
+ *eptr++ = ch;
+
+ *eptr = '\0';
+
+ if (ch == EOF)
+ return (ELEMENT_ERROR);
+
+ eptr = element;
+ temp = bsearch(&mptr, elements, sizeof(elements) / sizeof(elements[0]),
+ sizeof(elements[0]),
+ (int (*)(const void *, const void *))compare_elements);
+
+ if (temp == NULL)
+ {
+ /*
+ * Unrecognized element stuff...
+ */
+
+ t->element = ELEMENT_COMMENT;
+ strcpy(comment, element);
+ cptr = comment + strlen(comment);
+ }
+ else
+ {
+ t->element = (element_t)((char **)temp - elements);
+ cptr = comment;
+ }
+
+ if (t->element == ELEMENT_COMMENT)
+ {
+ while (ch != EOF && ch != '>' && cptr < (comment + sizeof(comment) - 1))
+ {
+ *cptr++ = ch;
+ ch = getc(fp);
+ }
+
+ *cptr = '\0';
+ t->data = strdup(comment);
+ }
+ else
+ {
+ while (ch != EOF && ch != '>' && ch != '/')
+ {
+ if (!isspace(ch & 255))
+ {
+ ungetc(ch, fp);
+ parse_variable(t, fp);
+ }
+
+ ch = getc(fp);
+ }
+
+ if (ch != EOF)
+ ungetc(ch, fp);
+ }
+
+ return (t->element);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/form.h b/filter/form.h
new file mode 100644
index 000000000..a4b9fcdb7
--- /dev/null
+++ b/filter/form.h
@@ -0,0 +1,177 @@
+/*
+ * "$Id$"
+ *
+ * CUPS form header file for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+
+
+/*
+ * Form elements...
+ */
+
+typedef enum
+{
+ ELEMENT_FILE = -1, /* Pseudo element, not in file, but above */
+ ELEMENT_FRAGMENT, /* Text fragment */
+ ELEMENT_COMMENT, /* <!-- .... --> */
+ ELEMENT_ARC,
+ ELEMENT_BOX,
+ ELEMENT_BR,
+ ELEMENT_B,
+ ELEMENT_CUPSFORM,
+ ELEMENT_DEFVAR,
+ ELEMENT_FONT,
+ ELEMENT_H1,
+ ELEMENT_H2,
+ ELEMENT_H3,
+ ELEMENT_H4,
+ ELEMENT_H5,
+ ELEMENT_H6,
+ ELEMENT_HEAD,
+ ELEMENT_IMG,
+ ELEMENT_I,
+ ELEMENT_LINE,
+ ELEMENT_PAGE,
+ ELEMENT_PIE,
+ ELEMENT_POLY,
+ ELEMENT_PRE,
+ ELEMENT_P,
+ ELEMENT_RECT,
+ ELEMENT_TEXT,
+ ELEMENT_TT,
+ ELEMENT_VAR
+} element_t;
+
+
+/*
+ * Font styles...
+ */
+
+typedef enum
+{
+ STYLE_NORMAL,
+ STYLE_BOLD,
+ STYLE_ITALIC,
+ STYLE_BOLD_ITALIC
+} style_t;
+
+
+/*
+ * Text alignments...
+ */
+
+typedef enum
+{
+ HALIGN_LEFT,
+ HALIGN_CENTER,
+ HALIGN_RIGHT
+} halign_t;
+
+typedef enum
+{
+ VALIGN_BOTTOM,
+ VALIGN_CENTER,
+ VALIGN_TOP
+} valign_t;
+
+
+/*
+ * Text directions...
+ */
+
+typedef enun
+{
+ DIR_LEFT_TO_RIGHT,
+ DIR_RIGHT_TO_LEFT
+} dir_t;
+
+
+/*
+ * Attribute structure...
+ */
+
+typedef struct
+{
+ char *name, /* Name of attribute */
+ *value; /* Value of attribute */
+} attr_t;
+
+
+/*
+ * Form document tree structure...
+ */
+
+typedef struct tree_str
+{
+ struct tree_str *prev, /* Previous tree node */
+ *next, /* Next tree node */
+ *parent, /* Parent tree node */
+ *child, /* First child node */
+ *last_child; /* Last child node */
+ element_t element; /* Element type */
+ float x, y, w, h; /* Position and size in points */
+ float bg[3], fg[3]; /* Colors of element */
+ float thickness; /* Thickness of lines */
+ int preformatted; /* Preformatted text? */
+ float size; /* Height of text in points */
+ char *typeface; /* Typeface of text */
+ style_t style; /* Style of text */
+ halign_t halign; /* Horizontal alignment */
+ valign_t valign; /* Vertical alignment */
+ dir_t dir; /* Direction of text */
+ int num_attrs; /* Number of attributes */
+ attr_t *attrs; /* Attributes */
+ void *data; /* Text fragment data */
+} tree_t;
+
+
+/*
+ * Globals...
+ */
+
+extern int NumOptions; /* Number of command-line options */
+extern cups_option_t *Options; /* Command-line options */
+extern ppd_file_t *PPD; /* PPD file */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void formDelete(tree_t *t);
+extern char *formGetAttr(tree_t *t, const char *name);
+extern tree_t *formNew(tree_t *p);
+extern tree_t *formRead(FILE *fp, tree_t *p);
+extern void formSetAttr(tree_t *t, const char *name, const char *value);
+extern void formWrite(tree_t *p);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/gziptoany.c b/filter/gziptoany.c
new file mode 100644
index 000000000..986fa0110
--- /dev/null
+++ b/filter/gziptoany.c
@@ -0,0 +1,131 @@
+/*
+ * "$Id$"
+ *
+ * GZIP pre-filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Uncompress gzip'd files and send them to stdout...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_LIBZ
+# include <zlib.h>
+#endif /* HAVE_LIBZ */
+
+
+/*
+ * 'main()' - Uncompress gzip'd files and send them to stdout...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+#ifdef HAVE_LIBZ
+ gzFile fp; /* GZIP'd file */
+ char buffer[8192]; /* Data buffer */
+ int bytes; /* Number of bytes read/written */
+ int copies; /* Number of copies */
+ const char *content_type; /* Content type for file... */
+
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc != 7)
+ {
+ fputs("ERROR: gziptoany job-id user title copies options file\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Get the copy count; if the MIME type is "application/vnd.cups-raw" then
+ * make copies since the file is going straight to a backend...
+ */
+
+ if ((content_type = getenv("CONTENT_TYPE")) != NULL &&
+ !strcasecmp(content_type, "application/vnd.cups-raw"))
+ copies = atoi(argv[4]);
+ else
+ copies = 1;
+
+ /*
+ * Open the gzip file...
+ */
+
+ if ((fp = gzopen(argv[6], "rb")) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to open GZIP file: %s\n", strerror(errno));
+ return (1);
+ }
+
+ /*
+ * Copy the gzip file to stdout...
+ */
+
+ setbuf(stdout, NULL);
+
+ while (copies > 0)
+ {
+ gzrewind(fp);
+
+ while ((bytes = gzread(fp, buffer, sizeof(buffer))) > 0)
+ if (fwrite(buffer, 1, bytes, stdout) < bytes)
+ {
+ fprintf(stderr, "ERROR: Unable to write uncompressed document data: %s\n",
+ strerror(ferror(stdout)));
+ gzclose(fp);
+
+ return (1);
+ }
+
+ copies --;
+ }
+
+ /*
+ * Close the file and return...
+ */
+
+ gzclose(fp);
+
+ return (0);
+#else
+ fputs("INFO: Hint: recompile CUPS with ZLIB.\n", stderr);
+ fputs("ERROR: GZIP compression support not compiled in!\n", stderr);
+ return (1);
+#endif /* HAVE_LIBZ */
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-attr.c b/filter/hpgl-attr.c
new file mode 100644
index 000000000..51d737d49
--- /dev/null
+++ b/filter/hpgl-attr.c
@@ -0,0 +1,454 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 attribute processing for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * CR_color_range() - Set the range for color values.
+ * AC_anchor_corner() - Set the anchor corner.
+ * FT_fill_type() - Set the fill type or pattern.
+ * LA_line_attributes() - Set the line drawing attributes.
+ * LT_line_type() - Set the line type (style)...
+ * NP_number_pens() - Set the number of pens to be used.
+ * PC_pen_color() - Set the pen color...
+ * PW_pen_width() - Set the pen width.
+ * RF_raster_fill() - Set the raster fill pattern.
+ * SM_symbol_mode() - Set where symbols are drawn.
+ * SP_select_pen() - Select a pen for drawing.
+ * UL_user_line_type() - Set a user-defined line type.
+ * WU_width_units() - Set the units used for pen widths.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+
+
+/*
+ * 'CR_color_range()' - Set the range for color values.
+ */
+
+void
+CR_color_range(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ {
+ /*
+ * Default to 0 to 255 for all color values.
+ */
+
+ ColorRange[0][0] = 0.0;
+ ColorRange[0][1] = 255.0;
+ ColorRange[1][0] = 0.0;
+ ColorRange[1][1] = 255.0;
+ ColorRange[2][0] = 0.0;
+ ColorRange[2][1] = 255.0;
+ }
+ else if (num_params == 6)
+ {
+ /*
+ * Set the range based on the parameters...
+ */
+
+ ColorRange[0][0] = params[0].value.number;
+ ColorRange[0][1] = params[1].value.number - params[0].value.number;
+ ColorRange[1][0] = params[2].value.number;
+ ColorRange[1][1] = params[3].value.number - params[2].value.number;
+ ColorRange[2][0] = params[4].value.number;
+ ColorRange[2][1] = params[5].value.number - params[4].value.number;
+ }
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'CR\' command with invalid number of parameters (%d)!\n",
+ num_params);
+}
+
+
+/*
+ * 'AC_anchor_corner()' - Set the anchor corner.
+ */
+
+void
+AC_anchor_corner(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'FT_fill_type()' - Set the fill type or pattern.
+ *
+ * Note:
+ *
+ * This needs to be updated to support non-solid fill.
+ */
+
+void
+FT_fill_type(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0 ||
+ params[0].value.number == 1 ||
+ params[0].value.number == 2)
+ {
+ /**** SOLID PATTERN ****/
+ }
+}
+
+
+/*
+ * 'LA_line_attributes()' - Set the line drawing attributes.
+ */
+
+void
+LA_line_attributes(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+
+
+ if (num_params == 0)
+ {
+ MiterLimit = 3.0f;
+ LineCap = 0;
+ LineJoin = 0;
+ }
+ else for (i = 0; i < (num_params - 1); i += 2)
+ switch ((int)params[i].value.number)
+ {
+ case 1 :
+ LineCap = params[i + 1].value.number == 1 ? 0 :
+ params[i + 1].value.number == 4 ? 1 : 2;
+ break;
+ case 2 :
+ switch ((int)params[i + 1].value.number)
+ {
+ case 1 :
+ case 2 :
+ case 3 :
+ LineJoin = 0;
+ break;
+ case 5 :
+ LineJoin = 2;
+ break;
+ default :
+ LineJoin = 1;
+ break;
+ }
+ break;
+ case 3 :
+ MiterLimit = 1.0 + 0.5 * (params[i + 1].value.number - 1.0);
+ break;
+ }
+
+ if (PageDirty)
+ {
+ printf("%.1f setmiterlimit\n", MiterLimit);
+ printf("%d setlinecap\n", LineCap);
+ printf("%d setlinejoin\n", LineJoin);
+ }
+}
+
+
+/*
+ * 'LT_line_type()' - Set the line type (style)...
+ *
+ * Note:
+ *
+ * This needs to be updated to support line types.
+ */
+
+void
+LT_line_type(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'NP_number_pens()' - Set the number of pens to be used.
+ */
+
+void
+NP_number_pens(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+
+
+ if (num_params == 0)
+ PenCount = 8;
+ else if (num_params == 1 && params[0].value.number <= 1024)
+ PenCount = (int)params[0].value.number;
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'NP\' command with invalid number of parameters (%d)!\n",
+ num_params);
+
+ for (i = 0; i <= PenCount; i ++)
+ Pens[i].width = PenWidth;
+
+ PC_pen_color(0, NULL);
+}
+
+
+/*
+ * 'PC_pen_color()' - Set the pen color...
+ */
+
+void
+PC_pen_color(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+ static float standard_colors[8][3] = /* Standard colors for first 8 pens */
+ {
+ { 1.0, 1.0, 1.0 }, /* White */
+ { 0.0, 0.0, 0.0 }, /* Black */
+ { 1.0, 0.0, 0.0 }, /* Red */
+ { 0.0, 1.0, 0.0 }, /* Green */
+ { 1.0, 1.0, 0.0 }, /* Yellow */
+ { 0.0, 0.0, 1.0 }, /* Blue */
+ { 1.0, 0.0, 1.0 }, /* Magenta */
+ { 0.0, 1.0, 1.0 } /* Cyan */
+ };
+
+
+ if (num_params == 0)
+ {
+ for (i = 0; i <= PenCount; i ++)
+ if (i < 8)
+ {
+ Pens[i].rgb[0] = standard_colors[i][0];
+ Pens[i].rgb[1] = standard_colors[i][1];
+ Pens[i].rgb[2] = standard_colors[i][2];
+ }
+ else
+ {
+ Pens[i].rgb[0] = 0.0f;
+ Pens[i].rgb[1] = 0.0f;
+ Pens[i].rgb[2] = 0.0f;
+ }
+
+ if (PageDirty)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ }
+ else if (num_params == 1 || num_params == 4)
+ {
+ i = (int)params[0].value.number;
+
+ if (num_params == 1)
+ {
+ Pens[i].rgb[0] = standard_colors[i & 7][0];
+ Pens[i].rgb[1] = standard_colors[i & 7][1];
+ Pens[i].rgb[2] = standard_colors[i & 7][2];
+ }
+ else
+ {
+ Pens[i].rgb[0] = (params[1].value.number - ColorRange[0][0]) /
+ (ColorRange[0][1] - ColorRange[0][0]);
+ Pens[i].rgb[1] = (params[2].value.number - ColorRange[1][0]) /
+ (ColorRange[1][1] - ColorRange[1][0]);
+ Pens[i].rgb[2] = (params[3].value.number - ColorRange[2][0]) /
+ (ColorRange[2][1] - ColorRange[2][0]);
+
+ fprintf(stderr, "DEBUG: Pen %d %.0f %.0f %.0f = %.3f %.3f %.3f\n",
+ i, params[1].value.number, params[2].value.number,
+ params[3].value.number, Pens[i].rgb[0], Pens[i].rgb[1],
+ Pens[i].rgb[2]);
+ }
+
+ if (PageDirty && i == PenNumber)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ }
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'PC\' command with invalid number of parameters (%d)!\n",
+ num_params);
+}
+
+
+/*
+ * 'PW_pen_width()' - Set the pen width.
+ */
+
+void
+PW_pen_width(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int pen; /* Pen number */
+ float w; /* Width value */
+
+
+ if (WidthUnits == 0)
+ {
+ /*
+ * Metric...
+ */
+
+ if (num_params == 0)
+ w = 0.35f / 25.4f * 72.0f;
+ else
+ w = params[0].value.number / 25.4f * 72.0f;
+ }
+ else
+ {
+ /*
+ * Relative...
+ */
+
+ w = (float)hypot(PlotSize[0], PlotSize[1]) / 1016.0f * 72.0f;
+
+ if (num_params == 0)
+ w *= 0.01f;
+ else
+ w *= params[0].value.number;
+ }
+
+ if (num_params == 2)
+ {
+ pen = (int)params[1].value.number;
+
+ Pens[pen].width = w;
+
+ if (PageDirty && pen == PenNumber)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ }
+ else if (num_params < 2)
+ {
+ /*
+ * Set width for all pens...
+ */
+
+ for (pen = 0; pen <= PenCount; pen ++)
+ Pens[pen].width = w;
+
+ if (PageDirty)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ }
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'PW\' command with invalid number of parameters (%d)!\n",
+ num_params);
+}
+
+
+/*
+ * 'RF_raster_fill()' - Set the raster fill pattern.
+ *
+ * Note:
+ *
+ * This needs to be implemented.
+ */
+
+void
+RF_raster_fill(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SM_symbol_mode()' - Set where symbols are drawn.
+ */
+
+void
+SM_symbol_mode(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SP_select_pen()' - Select a pen for drawing.
+ */
+
+void
+SP_select_pen(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ PenNumber = 1;
+ else if (params[0].value.number <= PenCount)
+ PenNumber = (int)params[0].value.number;
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'SP\' command with invalid number or value of parameters (%d, %d)!\n",
+ num_params, (int)params[0].value.number);
+
+ if (PageDirty)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+}
+
+
+/*
+ * 'UL_user_line_type()' - Set a user-defined line type.
+ */
+
+void
+UL_user_line_type(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'WU_width_units()' - Set the units used for pen widths.
+ */
+
+void
+WU_width_units(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ WidthUnits = 0;
+ else if (num_params == 1)
+ WidthUnits = (int)params[0].value.number;
+ else
+ fprintf(stderr, "WARNING: HP-GL/2 \'WU\' command with invalid number of parameters (%d)!\n",
+ num_params);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-char.c b/filter/hpgl-char.c
new file mode 100644
index 000000000..cc4889277
--- /dev/null
+++ b/filter/hpgl-char.c
@@ -0,0 +1,640 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 character processing for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * AD_define_alternate() - Define the alternate font.
+ * CF_character_fill() - Set whether or not to fill or outline
+ * characters.
+ * CP_character_plot() - Move the current pen position for the given
+ * number of columns and rows.
+ * DI_absolute_direction() - Set the direction vector for text.
+ * DR_relative_direction() - Set the relative direction vector for text.
+ * DT_define_label_term() - Set the label string terminator.
+ * DV_define_variable_path() - Define a path for text.
+ * ES_extra_space() - Set extra spacing (kerning) between characters.
+ * LB_label() - Display a label string.
+ * LO_label_origin() - Set the label origin.
+ * SA_select_alternate() - Select the alternate font.
+ * SD_define_standard() - Define the standard font...
+ * SI_absolute_size() - Set the absolute size of text.
+ * SL_character_slant() - Set the slant of text.
+ * SR_relative_size() - Set the relative size of text.
+ * SS_select_standard() - Select the standard font for text.
+ * TD_transparent_data() - Send transparent print data.
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+
+
+/*
+ * 'define_font()' - Define the specified font...
+ */
+
+void
+define_font(int f) /* I - Font number */
+{
+ font_t *font; /* Font */
+ const char *fstring; /* Font string - SA or SS */
+ float xform[2][2]; /* Transform matrix */
+
+
+ /*
+ * Get the correct font data...
+ */
+
+ if (f)
+ {
+ font = &AlternateFont;
+ fstring = "SA";
+ }
+ else
+ {
+ font = &StandardFont;
+ fstring = "SS";
+ }
+
+ /*
+ * Compute the font matrix, accounting for any rotation...
+ */
+
+ switch (Rotation)
+ {
+ default :
+ case 0 :
+ xform[0][0] = font->xpitch * font->x * font->height;
+ xform[0][1] = font->xpitch * font->y * font->height;
+ xform[1][0] = -font->y * font->height;
+ xform[1][1] = font->x * font->height;
+ break;
+
+ case 90 :
+ xform[0][0] = -font->xpitch * font->y * font->height;
+ xform[0][1] = font->xpitch * font->x * font->height;
+ xform[1][0] = -font->x * font->height;
+ xform[1][1] = -font->y * font->height;
+ break;
+
+ case 180 :
+ xform[0][0] = -font->xpitch * font->x * font->height;
+ xform[0][1] = -font->xpitch * font->y * font->height;
+ xform[1][0] = font->y * font->height;
+ xform[1][1] = -font->x * font->height;
+ break;
+
+ case 270 :
+ xform[0][0] = font->xpitch * font->y * font->height;
+ xform[0][1] = -font->xpitch * font->x * font->height;
+ xform[1][0] = font->x * font->height;
+ xform[1][1] = font->y * font->height;
+ break;
+ }
+
+ /*
+ * Send the font definition...
+ */
+
+ printf("/%s {\n"
+ " /%s%s%s%s findfont\n"
+ " [ %f %f %f %f 0.0 0.0 ] makefont\n"
+ " setfont\n"
+ "} bind def\n",
+ fstring, font->spacing ? "Helvetica" : "Courier",
+ (font->weight > 0 || font->posture) ? "-" : "",
+ font->weight > 0 ? "Bold" : "",
+ font->posture ? "Oblique" : "",
+ xform[0][0], xform[0][1], xform[1][0], xform[1][1]);
+
+ if (f == CharFont)
+ printf("%s\n", fstring);
+}
+
+
+/*
+ * 'AD_define_alternate()' - Define the alternate font.
+ */
+
+void
+AD_define_alternate(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Set default font attributes...
+ */
+
+ AlternateFont.symbol_set = 277;
+ AlternateFont.spacing = 0;
+ AlternateFont.pitch = 9;
+ AlternateFont.height = 11.5;
+ AlternateFont.posture = 0;
+ AlternateFont.weight = 0;
+ AlternateFont.typeface = 48;
+ AlternateFont.x = 1.0;
+ AlternateFont.y = 0.0;
+
+ /*
+ * Loop through parameter value pairs...
+ */
+
+ for (i = 0; i < (num_params - 1); i += 2)
+ switch ((int)params[i].value.number)
+ {
+ case 1 : /* Symbol Set */
+ AlternateFont.symbol_set = (int)params[i + 1].value.number;
+ break;
+ case 2 : /* Font Spacing */
+ AlternateFont.spacing = (int)params[i + 1].value.number;
+ break;
+ case 3 : /* Pitch */
+ AlternateFont.pitch = params[i + 1].value.number;
+ break;
+ case 4 : /* Height */
+ AlternateFont.height = params[i + 1].value.number;
+ break;
+ case 5 : /* Posture */
+ AlternateFont.posture = (int)params[i + 1].value.number;
+ break;
+ case 6 : /* Stroke Weight */
+ AlternateFont.weight = (int)params[i + 1].value.number;
+ break;
+ case 7 : /* Typeface */
+ AlternateFont.typeface = (int)params[i + 1].value.number;
+ break;
+ }
+
+ if (AlternateFont.spacing)
+ {
+ /*
+ * Set proportional spacing font...
+ */
+
+ AlternateFont.xpitch = 1.0f;
+ }
+ else
+ {
+ /*
+ * Set fixed-spaced font...
+ */
+
+ AlternateFont.xpitch = 0.6f * AlternateFont.height / AlternateFont.pitch;
+ }
+
+ /*
+ * Define the font...
+ */
+
+ if (PageDirty)
+ {
+ printf("%% AD");
+ for (i = 0; i < num_params; i ++)
+ if (i)
+ printf(",%g", params[i].value.number);
+ else
+ printf("%g", params[i].value.number);
+ puts(";");
+
+ define_font(1);
+ }
+
+ CharHeight[1] = AlternateFont.height;
+}
+
+
+/*
+ * 'CF_character_fill()' - Set whether or not to fill or outline characters.
+ */
+
+void
+CF_character_fill(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ CharFillMode = 0;
+ else
+ CharFillMode = (int)params[0].value.number;
+
+ if (num_params == 2)
+ CharPen = (int)params[1].value.number;
+}
+
+
+/*
+ * 'CP_character_plot()' - Move the current pen position for the given number
+ * of columns and rows.
+ */
+
+void
+CP_character_plot(int num_params,
+ param_t *params)
+{
+ if (num_params < 2)
+ return;
+
+ switch (Rotation)
+ {
+ case 0:
+ PenPosition[0] += params[0].value.number * 1.2f / CharHeight[CharFont];
+ PenPosition[1] += params[1].value.number * CharHeight[CharFont];
+ break;
+ case 90:
+ PenPosition[0] -= params[1].value.number * 1.2f / CharHeight[CharFont];
+ PenPosition[1] += params[0].value.number * CharHeight[CharFont];
+ break;
+ case 180:
+ PenPosition[0] -= params[0].value.number * 1.2f / CharHeight[CharFont];
+ PenPosition[1] -= params[1].value.number * CharHeight[CharFont];
+ break;
+ case 270:
+ PenPosition[0] += params[1].value.number * 1.2f / CharHeight[CharFont];
+ PenPosition[1] -= params[0].value.number * CharHeight[CharFont];
+ break;
+ }
+}
+
+
+/*
+ * 'DI_absolute_direction()' - Set the direction vector for text.
+ */
+
+void
+DI_absolute_direction(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params != 2)
+ return;
+
+ if (CharFont)
+ {
+ AlternateFont.x = params[0].value.number;
+ AlternateFont.y = params[1].value.number;
+ }
+ else
+ {
+ StandardFont.x = params[0].value.number;
+ StandardFont.y = params[1].value.number;
+ }
+
+ if (PageDirty)
+ {
+ printf("%% DI%g,%g\n", params[0].value.number, params[1].value.number);
+
+ define_font(CharFont);
+ }
+}
+
+
+/*
+ * 'DR_relative_direction()' - Set the relative direction vector for text.
+ */
+
+void
+DR_relative_direction(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'DT_define_label_term()' - Set the label string terminator.
+ */
+
+void
+DT_define_label_term(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ StringTerminator = '\003';
+ else
+ StringTerminator = params[0].value.string[0];
+}
+
+
+/*
+ * 'DV_define_variable_path()' - Define a path for text.
+ */
+
+void
+DV_define_variable_path(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'ES_extra_space()' - Set extra spacing (kerning) between characters.
+ */
+
+void
+ES_extra_space(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'LB_label()' - Display a label string.
+ */
+
+void
+LB_label(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ char *s; /* Pointer into string */
+
+
+ if (num_params == 0)
+ return;
+
+ Outputf("gsave\n");
+ Outputf("currentmiterlimit 1.0 setmiterlimit\n");
+ Outputf("MP\n");
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ PenValid = 1;
+
+ Outputf("(");
+ for (s = params[0].value.string; *s != '\0'; s ++)
+ if (strchr("()\\", *s) != NULL)
+ Outputf("\\%c", *s);
+ else
+ Outputf("%c", *s);
+ Outputf(") true charpath\n");
+
+ if (CharFillMode != 1)
+ Outputf("FI\n");
+ if (CharFillMode == 1 || CharFillMode == 3)
+ {
+ Outputf("%.3f %.3f %.3f %.2f SP ST\n", Pens[CharPen].rgb[0],
+ Pens[CharPen].rgb[CharPen], Pens[CharPen].rgb[2],
+ Pens[CharPen].width * PenScaling);
+ Outputf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ }
+
+ Outputf("setmiterlimit\n");
+ Outputf("grestore\n");
+}
+
+
+/*
+ * 'LO_label_origin()' - Set the label origin.
+ */
+
+void
+LO_label_origin(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SA_select_alternate()' - Select the alternate font.
+ */
+
+void
+SA_select_alternate(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ if (PageDirty)
+ puts("SA");
+
+ CharFont = 1;
+}
+
+
+/*
+ * 'SD_define_standard()' - Define the standard font...
+ */
+
+void
+SD_define_standard(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Set default font attributes...
+ */
+
+ StandardFont.symbol_set = 277;
+ StandardFont.spacing = 0;
+ StandardFont.pitch = 9;
+ StandardFont.height = 11.5;
+ StandardFont.posture = 0;
+ StandardFont.weight = 0;
+ StandardFont.typeface = 48;
+ StandardFont.x = 1.0;
+ StandardFont.y = 0.0;
+
+ /*
+ * Loop through parameter value pairs...
+ */
+
+ for (i = 0; i < (num_params - 1); i += 2)
+ switch ((int)params[i].value.number)
+ {
+ case 1 : /* Symbol Set */
+ StandardFont.symbol_set = (int)params[i + 1].value.number;
+ break;
+ case 2 : /* Font Spacing */
+ StandardFont.spacing = (int)params[i + 1].value.number;
+ break;
+ case 3 : /* Pitch */
+ StandardFont.pitch = params[i + 1].value.number;
+ break;
+ case 4 : /* Height */
+ StandardFont.height = params[i + 1].value.number;
+ break;
+ case 5 : /* Posture */
+ StandardFont.posture = (int)params[i + 1].value.number;
+ break;
+ case 6 : /* Stroke Weight */
+ StandardFont.weight = (int)params[i + 1].value.number;
+ break;
+ case 7 : /* Typeface */
+ StandardFont.typeface = (int)params[i + 1].value.number;
+ break;
+ }
+
+ if (StandardFont.spacing || StandardFont.pitch <= 0.0)
+ {
+ /*
+ * Set proportional spacing font...
+ */
+
+ StandardFont.xpitch = 1.0f;
+ }
+ else
+ {
+ /*
+ * Set fixed-spaced font...
+ */
+
+ StandardFont.xpitch = 0.6f * StandardFont.height / StandardFont.pitch;
+ }
+
+ /*
+ * Define the font...
+ */
+
+ if (PageDirty)
+ {
+ printf("%% SD");
+ for (i = 0; i < num_params; i ++)
+ if (i)
+ printf(",%g", params[i].value.number);
+ else
+ printf("%g", params[i].value.number);
+ puts(";");
+
+ define_font(0);
+ }
+
+ CharHeight[0] = StandardFont.height;
+}
+
+
+/*
+ * 'SI_absolute_size()' - Set the absolute size of text.
+ */
+
+void
+SI_absolute_size(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float xsize, ysize; /* Font size... */
+
+
+ if (num_params != 2)
+ return;
+
+ /*
+ * The "SI" values are supposed to be cm, but they appear to be inches
+ * when tested on real HP devices...
+ */
+
+ xsize = params[0].value.number * 72.0f;
+ ysize = params[1].value.number * 72.0f * 0.6f;
+
+ if (CharFont)
+ {
+ AlternateFont.xpitch = xsize / ysize;
+ AlternateFont.height = ysize;
+ }
+ else
+ {
+ StandardFont.xpitch = xsize / ysize;
+ StandardFont.height = ysize;
+ }
+
+ if (PageDirty)
+ {
+ printf("%% SI%g,%g\n", params[0].value.number, params[1].value.number);
+
+ define_font(CharFont);
+ }
+}
+
+
+/*
+ * 'SL_character_slant()' - Set the slant of text.
+ */
+
+void
+SL_character_slant(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SR_relative_size()' - Set the relative size of text.
+ */
+
+void
+SR_relative_size(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SS_select_standard()' - Select the standard font for text.
+ */
+
+void
+SS_select_standard(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ if (PageDirty)
+ puts("SS");
+
+ CharFont = 0;
+}
+
+
+/*
+ * 'TD_transparent_data()' - Send transparent print data.
+ */
+
+void
+TD_transparent_data(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-config.c b/filter/hpgl-config.c
new file mode 100644
index 000000000..c7c57ceec
--- /dev/null
+++ b/filter/hpgl-config.c
@@ -0,0 +1,645 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 configuration routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * update_transform() - Update the page transformation matrix as needed.
+ * BP_begin_plot() - Start a plot...
+ * DF_default_values() - Set all state info to the default values.
+ * IN_initialize() - Initialize the plotter.
+ * IP_input_absolute() - Set P1 and P2 values for the plot.
+ * IR_input_relative() - Update P1 and P2.
+ * IW_input_window() - Setup an input window.
+ * PG_advance_page() - Eject the current page.
+ * PS_plot_size() - Set the plot size.
+ * RO_rotate() - Rotate the plot.
+ * RP_replot() - Replot the current page.
+ * SC_scale() - Set user-defined scaling.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+
+#define max(a,b) ((a) < (b) ? (b) : (a))
+
+
+/*
+ * 'update_transform()' - Update the page transformation matrix as needed.
+ */
+
+void
+update_transform(void)
+{
+ float page_width, /* Actual page width */
+ page_height; /* Actual page height */
+ float scaling; /* Scaling factor */
+ float left, right, /* Scaling window */
+ bottom, top;
+ float width, height; /* Scaling width and height */
+ float iw1[2], iw2[2]; /* Clipping window */
+
+
+ /*
+ * Get the page and input window sizes...
+ */
+
+ if (FitPlot)
+ {
+ page_width = PageRight - PageLeft;
+ page_height = PageTop - PageBottom;
+ }
+ else
+ {
+ page_width = (P2[0] - P1[0]) * 72.0f / 1016.0f;
+ page_height = (P2[1] - P1[1]) * 72.0f / 1016.0f;
+ }
+
+ fprintf(stderr, "DEBUG: page_width = %.0f, page_height = %.0f\n",
+ page_width, page_height);
+
+ if (page_width == 0 || page_height == 0)
+ return;
+
+ /*
+ * Set the scaling window...
+ */
+
+ switch (ScalingType)
+ {
+ default : /* No user scaling */
+ left = P1[0];
+ bottom = P1[1];
+ right = P2[0];
+ top = P2[1];
+ break;
+
+ case 0 : /* Anisotropic (non-uniform) scaling */
+ left = Scaling1[0];
+ bottom = Scaling1[1];
+ right = Scaling2[0];
+ top = Scaling2[1];
+ break;
+
+ case 1 : /* Isotropic (uniform) scaling */
+ left = Scaling1[0];
+ bottom = Scaling1[1];
+ right = Scaling2[0];
+ top = Scaling2[1];
+
+ width = right - left;
+ height = top - bottom;
+
+ if (width == 0 || height == 0)
+ return;
+
+ if ((width * page_height) != (height * page_width))
+ {
+ scaling = height * page_width / page_height;
+ if (width < scaling)
+ {
+ width = scaling;
+ left = 0.5f * (left + right - width);
+ right = left + width;
+ }
+ else
+ {
+ height = width * page_height / page_width;
+ bottom = 0.5f * (bottom + top - height);
+ top = bottom + height;
+ }
+ }
+ break;
+
+ case 2 :
+ left = Scaling1[0];
+ bottom = Scaling1[1];
+ right = left + page_width * Scaling2[0] * 1016.0f / 72.0f;
+ top = bottom + page_height * Scaling2[1] * 1016.0f / 72.0f;
+ break;
+ }
+
+ width = right - left;
+ height = top - bottom;
+
+ if (width == 0 || height == 0)
+ return;
+
+ /*
+ * Scale the plot as needed...
+ */
+
+ if (Rotation == 0 || Rotation == 180)
+ scaling = page_width / width;
+ else
+ scaling = page_width / height;
+
+ if (FitPlot)
+ scaling *= max(page_width, page_height) / max(PlotSize[1], PlotSize[0]);
+
+ /*
+ * Offset for the current P1 location...
+ */
+
+ if (FitPlot)
+ {
+ left = 0;
+ bottom = 0;
+ }
+ else
+ {
+ left = P1[0] * 72.0f / 1016.0f;
+ bottom = P1[1] * 72.0f / 1016.0f;
+ }
+
+ /*
+ * Generate a new transformation matrix...
+ */
+
+ switch (Rotation)
+ {
+ default :
+ case 0 :
+ Transform[0][0] = scaling;
+ Transform[0][1] = 0.0;
+ Transform[0][2] = -left;
+ Transform[1][0] = 0.0;
+ Transform[1][1] = scaling;
+ Transform[1][2] = -bottom;
+ break;
+
+ case 90 :
+ Transform[0][0] = 0.0;
+ Transform[0][1] = -scaling;
+ Transform[0][2] = PageLength - left;
+ Transform[1][0] = scaling;
+ Transform[1][1] = 0.0;
+ Transform[1][2] = -bottom;
+ break;
+
+ case 180 :
+ Transform[0][0] = -scaling;
+ Transform[0][1] = 0.0;
+ Transform[0][2] = PageLength - left;
+ Transform[1][0] = 0.0;
+ Transform[1][1] = -scaling;
+ Transform[1][2] = PageWidth - bottom;
+ break;
+
+ case 270 :
+ Transform[0][0] = 0.0;
+ Transform[0][1] = scaling;
+ Transform[0][2] = -left;
+ Transform[1][0] = -scaling;
+ Transform[1][1] = 0.0;
+ Transform[1][2] = PageWidth - bottom;
+ break;
+ }
+
+ fprintf(stderr, "DEBUG: Transform = [ %.3f %.3f\n"
+ "DEBUG: %.3f %.3f\n"
+ "DEBUG: %.3f %.3f ]\n",
+ Transform[0][0], Transform[1][0], Transform[0][1],
+ Transform[1][1], Transform[0][2], Transform[1][2]);
+
+ if (FitPlot)
+ {
+ if (Rotation == 0 || Rotation == 180)
+ PenScaling = page_width / PlotSize[1];
+ else
+ PenScaling = page_width / PlotSize[0];
+ }
+ else
+ PenScaling = 1.0;
+
+ if (PenScaling < 0.0)
+ PenScaling = -PenScaling;
+
+ if (PageDirty)
+ {
+ printf("%.2f setlinewidth\n", Pens[PenNumber].width * PenScaling);
+
+ if (IW1[0] != IW2[0] && IW1[1] != IW2[1])
+ {
+ iw1[0] = IW1[0] * 72.0f / 1016.0f;
+ iw1[1] = IW1[1] * 72.0f / 1016.0f;
+ iw2[0] = IW2[0] * 72.0f / 1016.0f;
+ iw2[1] = IW2[1] * 72.0f / 1016.0f;
+
+ printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n",
+ iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]);
+ }
+ }
+}
+
+
+/*
+ * 'BP_begin_plot()' - Start a plot...
+ */
+
+void
+BP_begin_plot(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'DF_default_values()' - Set all state info to the default values.
+ */
+
+void
+DF_default_values(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ NP_number_pens(0, NULL);
+ AC_anchor_corner(0, NULL);
+ AD_define_alternate(0, NULL);
+ SD_define_standard(0, NULL);
+ CF_character_fill(0, NULL);
+ DI_absolute_direction(0, NULL);
+ DT_define_label_term(0, NULL);
+ DV_define_variable_path(0, NULL);
+ ES_extra_space(0, NULL);
+ FT_fill_type(0, NULL);
+ IW_input_window(0, NULL);
+ LA_line_attributes(0, NULL);
+ LO_label_origin(0, NULL);
+ LT_line_type(0, NULL);
+ PA_plot_absolute(0, NULL);
+ PolygonMode = 0;
+ RF_raster_fill(0, NULL);
+ SC_scale(0, NULL);
+ SM_symbol_mode(0, NULL);
+ SS_select_standard(0, NULL);
+ TD_transparent_data(0, NULL);
+ UL_user_line_type(0, NULL);
+}
+
+
+/*
+ * 'IN_initialize()' - Initialize the plotter.
+ */
+
+void
+IN_initialize(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ DF_default_values(0, NULL);
+ PU_pen_up(0, NULL);
+ RO_rotate(0, NULL);
+ PS_plot_size(0, NULL);
+ WU_width_units(0, NULL);
+ PW_pen_width(0, NULL);
+
+ PenWidth = 1;
+
+ PenPosition[0] = PenPosition[1] = 0.0;
+}
+
+
+/*
+ * 'IP_input_absolute()' - Set P1 and P2 values for the plot.
+ */
+
+void
+IP_input_absolute(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ {
+ P1[0] = PageLeft / 72.0f * 1016.0f;
+ P1[1] = PageBottom / 72.0f * 1016.0f;
+ P2[0] = PageRight / 72.0f * 1016.0f;
+ P2[1] = PageTop / 72.0f * 1016.0f;
+ }
+ else if (num_params == 2)
+ {
+ P2[0] -= P1[0];
+ P2[1] -= P1[1];
+ P1[0] = params[0].value.number;
+ P1[1] = params[1].value.number;
+ P2[0] += P1[0];
+ P2[1] += P1[1];
+ }
+ else if (num_params == 4)
+ {
+ P1[0] = params[0].value.number;
+ P1[1] = params[1].value.number;
+ P2[0] = params[2].value.number;
+ P2[1] = params[3].value.number;
+ }
+
+ IW1[0] = 0.0;
+ IW1[1] = 0.0;
+ IW2[0] = 0.0;
+ IW2[1] = 0.0;
+
+ if (ScalingType < 0)
+ {
+ Scaling1[0] = P1[0];
+ Scaling1[0] = P1[1];
+ Scaling2[0] = P2[0];
+ Scaling2[1] = P2[1];
+ }
+
+ update_transform();
+}
+
+
+/*
+ * 'IR_input_relative()' - Update P1 and P2.
+ */
+
+void
+IR_input_relative(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ {
+ P1[0] = PageLeft / 72.0f * 1016.0f;
+ P1[1] = PageBottom / 72.0f * 1016.0f;
+ P2[0] = PageRight / 72.0f * 1016.0f;
+ P2[1] = PageTop / 72.0f * 1016.0f;
+ }
+ else if (num_params == 2)
+ {
+ P2[0] -= P1[0];
+ P2[1] -= P1[1];
+ P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
+ P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
+ P2[0] += P1[0];
+ P2[1] += P1[1];
+ }
+ else if (num_params == 4)
+ {
+ P1[0] = params[0].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
+ P1[1] = params[1].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
+ P2[0] = params[2].value.number * PlotSize[0] / 72.0f * 1016.0f / 100.0f;
+ P2[1] = params[3].value.number * PlotSize[1] / 72.0f * 1016.0f / 100.0f;
+ }
+
+ IW1[0] = 0.0;
+ IW1[1] = 0.0;
+ IW2[0] = 0.0;
+ IW2[1] = 0.0;
+
+ if (ScalingType < 0)
+ {
+ Scaling1[0] = P1[0];
+ Scaling1[0] = P1[1];
+ Scaling2[0] = P2[0];
+ Scaling2[1] = P2[1];
+ }
+
+ update_transform();
+}
+
+
+/*
+ * 'IW_input_window()' - Setup an input window.
+ */
+
+void
+IW_input_window(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ {
+ IW1[0] = PageLeft / 72.0f * 1016.0f;
+ IW1[1] = PageBottom / 72.0f * 1016.0f;
+ IW2[0] = PageRight / 72.0f * 1016.0f;
+ IW2[1] = PageTop / 72.0f * 1016.0f;
+ }
+ else if (num_params == 4)
+ {
+
+ if (ScalingType < 0)
+ {
+ IW1[0] = params[0].value.number;
+ IW1[1] = params[1].value.number;
+ IW2[0] = params[2].value.number;
+ IW2[1] = params[3].value.number;
+ }
+ else
+ {
+ IW1[0] = (Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ Transform[0][2]) / 72.0f * 1016.0f;
+ IW1[1] = (Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ Transform[1][2]) / 72.0f * 1016.0f;
+ IW2[0] = (Transform[0][0] * params[2].value.number +
+ Transform[0][1] * params[3].value.number +
+ Transform[0][2]) / 72.0f * 1016.0f;
+ IW2[1] = (Transform[1][0] * params[2].value.number +
+ Transform[1][1] * params[3].value.number +
+ Transform[1][2]) / 72.0f * 1016.0f;
+ }
+
+ fprintf(stderr, "DEBUG: IW%.0f,%.0f,%.0f,%.0f = [ %.0f %.0f %.0f %.0f ]\n",
+ params[0].value.number, params[1].value.number,
+ params[2].value.number, params[3].value.number,
+ IW1[0], IW1[1], IW2[0], IW2[1]);
+ }
+
+
+ update_transform();
+}
+
+
+/*
+ * 'PG_advance_page()' - Eject the current page.
+ */
+
+void
+PG_advance_page(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ if (PageDirty)
+ {
+ puts("grestore");
+ puts("showpage");
+
+ PageDirty = 0;
+ }
+}
+
+
+/*
+ * 'PS_plot_size()' - Set the plot size.
+ */
+
+void
+PS_plot_size(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ switch (num_params)
+ {
+ case 0 : /* PS ; */
+ if (Rotation == 0 || Rotation == 180)
+ {
+ PlotSize[0] = PageWidth;
+ PlotSize[1] = PageLength;
+ }
+ else
+ {
+ PlotSize[0] = PageLength;
+ PlotSize[1] = PageWidth;
+ }
+
+ PlotSizeSet = 0;
+ break;
+ case 1 : /* PS length ; */
+ if (Rotation == 0 || Rotation == 180)
+ {
+ PlotSize[1] = 72.0f * params[0].value.number / 1016.0f;
+ PlotSize[0] = 0.75f * PlotSize[1];
+ }
+ else
+ {
+ PlotSize[0] = 72.0f * params[0].value.number / 1016.0f;
+ PlotSize[1] = 0.75f * PlotSize[0];
+ }
+
+ PlotSizeSet = 1;
+ break;
+ case 2 : /* PS length, width ; */
+ /*
+ * Unfortunately, it appears that NO application correctly
+ * sends a two-argument PS command as documented in the
+ * HP-GL/2 Reference Manual from HP. Instead, applications
+ * send the width before the length, which causes all sorts
+ * of problems when scaling.
+ *
+ * Rather than fight it, we now look for them as width,length
+ * instead of length,width.
+ *
+ * Don't like it? Send mail to the folks that make Ideas, Pro/E,
+ * AutoCAD, etc.
+ */
+
+ if (Rotation == 0 || Rotation == 180)
+ {
+ PlotSize[0] = 72.0f * params[0].value.number / 1016.0f;
+ PlotSize[1] = 72.0f * params[1].value.number / 1016.0f;
+ }
+ else
+ {
+ PlotSize[0] = 72.0f * params[1].value.number / 1016.0f;
+ PlotSize[1] = 72.0f * params[0].value.number / 1016.0f;
+ }
+
+ PlotSizeSet = 1;
+ break;
+ }
+
+ /*
+ * This is required for buggy files that don't set the input window.
+ */
+
+ IP_input_absolute(0, NULL);
+}
+
+
+/*
+ * 'RO_rotate()' - Rotate the plot.
+ */
+
+void
+RO_rotate(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ Rotation = 0;
+ else
+ Rotation = (int)params[0].value.number;
+
+ update_transform();
+}
+
+
+/*
+ * 'RP_replot()' - Replot the current page.
+ */
+
+void
+RP_replot(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+}
+
+
+/*
+ * 'SC_scale()' - Set user-defined scaling.
+ */
+
+void
+SC_scale(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0)
+ {
+ ScalingType = -1;
+ Scaling1[0] = P1[0];
+ Scaling1[0] = P1[1];
+ Scaling2[0] = P2[0];
+ Scaling2[1] = P2[1];
+ }
+ else if (num_params > 3)
+ {
+ Scaling1[0] = params[0].value.number;
+ Scaling2[0] = params[1].value.number;
+ Scaling1[1] = params[2].value.number;
+ Scaling2[1] = params[3].value.number;
+
+ if (num_params > 4)
+ ScalingType = (int)params[4].value.number;
+ else
+ ScalingType = 1;
+ }
+
+ update_transform();
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-input.c b/filter/hpgl-input.c
new file mode 100644
index 000000000..38ed8a5e2
--- /dev/null
+++ b/filter/hpgl-input.c
@@ -0,0 +1,252 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 input processing for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ParseCommand() - Parse an HPGL/2 command.
+ * FreeParameters() - Free all string parameter values.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+#include <ctype.h>
+
+#define MAX_PARAMS 16384
+
+
+/*
+ * 'ParseCommand()' - Parse an HPGL/2 command.
+ *
+ * Returns the number of parameters seen or -1 on EOF.
+ */
+
+int /* O - -1 on EOF, # params otherwise */
+ParseCommand(FILE *fp, /* I - File to read from */
+ char *name, /* O - Name of command */
+ param_t **params) /* O - Parameter list */
+{
+ int num_params, /* Number of parameters seen */
+ ch, /* Current char */
+ done, /* Non-zero when the current command is read */
+ i; /* Looping var */
+ char buf[262144], /* String buffer */
+ *bufptr; /* Pointer into buffer */
+ static param_t p[MAX_PARAMS]; /* Parameter buffer */
+
+
+ num_params = 0;
+ done = 0;
+
+ do
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (strchr(" \t\r\n,;", ch) == NULL)
+ break;
+
+ if (ch == EOF)
+ return (-1);
+
+ if (ch == 0x1b)
+ switch (getc(fp))
+ {
+ case '.' : /* HP-GL/2 job control */
+ i = getc(fp);
+
+ if (strchr(")Z", i) != NULL)
+ {
+ /*
+ * 'Printer Off' command - look for next 'Printer On' command...
+ */
+
+ for (;;)
+ {
+ while ((i = getc(fp)) != EOF && i != 0x1b);
+
+ if (i == EOF)
+ return (-1);
+
+ if (getc(fp) != '.')
+ continue;
+
+ if ((i = getc(fp)) == '(' ||
+ i == 'Y')
+ break;
+ }
+ }
+ else if (strchr("@HIMNTI\003", i) != NULL)
+ {
+ while ((i = getc(fp)) != EOF && i != ':');
+ }
+ break;
+
+ case '%' : /* PJL command? */
+ if (getc(fp) == '-')
+ {
+ /*
+ * Yes, dump everything up to the "ENTER LANGUAGE" line...
+ */
+
+ while (fgets(buf, sizeof(buf), fp) != NULL)
+ if (strstr(buf, "ENTER") && strstr(buf, "LANGUAGE"))
+ break;
+ break;
+ }
+
+ default : /* HP RTL/PCL control */
+ while ((i = getc(fp)) != EOF && !isupper(i & 255));
+ break;
+ }
+ } while (ch < ' ');
+
+ name[0] = ch;
+ name[1] = getc(fp);
+ name[2] = '\0';
+
+ if (strcasecmp(name, "LB") == 0)
+ {
+ bufptr = buf;
+ while ((ch = getc(fp)) != StringTerminator)
+ if (bufptr < (buf + sizeof(buf) - 1))
+ *bufptr++ = ch;
+ *bufptr = '\0';
+
+ p[num_params].type = PARAM_STRING;
+ p[num_params].value.string = strdup(buf);
+ num_params ++;
+ }
+ else if (strcasecmp(name, "SM") == 0)
+ {
+ buf[0] = getc(fp);
+ buf[1] = '\0';
+ p[num_params].type = PARAM_STRING;
+ p[num_params].value.string = strdup(buf);
+ num_params ++;
+ }
+ else if (strcasecmp(name, "DT") == 0)
+ {
+ if ((buf[0] = getc(fp)) != ';')
+ {
+ buf[1] = '\0';
+ p[num_params].type = PARAM_STRING;
+ p[num_params].value.string = strdup(buf);
+ num_params ++;
+ }
+ }
+ else if (strcasecmp(name, "PE") == 0)
+ {
+ bufptr = buf;
+ while ((ch = getc(fp)) != ';')
+ if (bufptr < (buf + sizeof(buf) - 1))
+ *bufptr++ = ch;
+ *bufptr = '\0';
+
+ p[num_params].type = PARAM_STRING;
+ p[num_params].value.string = strdup(buf);
+ num_params ++;
+ }
+
+ while (!done)
+ switch (ch = getc(fp))
+ {
+ case ',' :
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ break;
+
+ case '\"' :
+ fscanf(fp, "%262143[^\"]\"", buf);
+ if (num_params < MAX_PARAMS)
+ {
+ p[num_params].type = PARAM_STRING;
+ p[num_params].value.string = strdup(buf);
+ num_params ++;
+ };
+ break;
+
+ case '-' :
+ case '+' :
+ ungetc(ch, fp);
+ fscanf(fp, "%f", &(p[num_params].value.number));
+ if (num_params < MAX_PARAMS)
+ {
+ p[num_params].type = PARAM_RELATIVE;
+ num_params ++;
+ }
+ break;
+ case '0' :
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' :
+ case '5' :
+ case '6' :
+ case '7' :
+ case '8' :
+ case '9' :
+ case '.' :
+ ungetc(ch, fp);
+ fscanf(fp, "%f", &(p[num_params].value.number));
+ if (num_params < MAX_PARAMS)
+ {
+ p[num_params].type = PARAM_ABSOLUTE;
+ num_params ++;
+ }
+ break;
+ default :
+ ungetc(ch, fp);
+ done = 1;
+ break;
+ }
+
+ *params = p;
+ return (num_params);
+}
+
+
+/*
+ * 'FreeParameters()' - Free all string parameter values.
+ */
+
+void
+FreeParameters(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameter values */
+{
+ int i; /* Looping var */
+
+
+ for (i = 0; i < num_params; i ++)
+ if (params[i].type == PARAM_STRING)
+ free(params[i].value.string);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-main.c b/filter/hpgl-main.c
new file mode 100644
index 000000000..f9e0f6ca7
--- /dev/null
+++ b/filter/hpgl-main.c
@@ -0,0 +1,274 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 filter main entry for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry for HP-GL/2 filter.
+ * compare_names() - Compare two command names.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+/*#define DEBUG*/
+#define _HPGL_MAIN_C_
+#include "hpgltops.h"
+
+
+/*
+ * HP-GL/2 command table...
+ */
+
+typedef struct
+{
+ char name[4]; /* Name of command */
+ void (*func)(int, param_t *); /* Function to call */
+} name_t;
+
+static name_t commands[] =
+{
+ { "BP", BP_begin_plot },
+ { "DF", DF_default_values },
+ { "IN", IN_initialize },
+ { "IP", IP_input_absolute },
+ { "IR", IR_input_relative },
+ { "IW", IW_input_window },
+ { "PG", PG_advance_page },
+ { "RO", RO_rotate },
+ { "RP", RP_replot },
+ { "SC", SC_scale },
+ { "AA", AA_arc_absolute },
+ { "AR", AR_arc_relative },
+ { "AT", AT_arc_absolute3 },
+ { "CI", CI_circle },
+ { "PA", PA_plot_absolute },
+ { "PD", PD_pen_down },
+ { "PE", PE_polyline_encoded },
+ { "PR", PR_plot_relative },
+ { "PS", PS_plot_size },
+ { "PU", PU_pen_up },
+ { "RT", RT_arc_relative3 },
+ { "EA", EA_edge_rect_absolute },
+ { "EP", EP_edge_polygon },
+ { "ER", ER_edge_rect_relative },
+ { "EW", EW_edge_wedge },
+ { "FP", FP_fill_polygon },
+ { "PM", PM_polygon_mode },
+ { "RA", RA_fill_rect_absolute },
+ { "RR", RR_fill_rect_relative },
+ { "WG", WG_fill_wedge },
+ { "AD", AD_define_alternate },
+ { "CF", CF_character_fill },
+ { "CP", CP_character_plot },
+ { "DI", DI_absolute_direction },
+ { "DR", DR_relative_direction },
+ { "DT", DT_define_label_term },
+ { "DV", DV_define_variable_path },
+ { "ES", ES_extra_space },
+ { "LB", LB_label },
+ { "LO", LO_label_origin },
+ { "SA", SA_select_alternate },
+ { "SD", SD_define_standard },
+ { "SI", SI_absolute_size },
+ { "SL", SL_character_slant },
+ { "SR", SR_relative_size },
+ { "SS", SS_select_standard },
+ { "TD", TD_transparent_data },
+ { "AC", AC_anchor_corner },
+ { "FT", FT_fill_type },
+ { "LA", LA_line_attributes },
+ { "LT", LT_line_type },
+ { "NP", NP_number_pens },
+ { "PC", PC_pen_color },
+ { "CR", CR_color_range },
+ { "PW", PW_pen_width },
+ { "RF", RF_raster_fill },
+ { "SM", SM_symbol_mode },
+ { "SP", SP_select_pen },
+ { "UL", UL_user_line_type },
+ { "WU", WU_width_units }
+};
+#define NUM_COMMANDS (sizeof(commands) / sizeof(name_t))
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_names(const void *p1, const void *p2);
+
+
+/*
+ * 'main()' - Main entry for HP-GL/2 filter.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ FILE *fp; /* Input file */
+ int num_params; /* Number of parameters */
+ param_t *params; /* Command parameters */
+ name_t *command, /* Command */
+ name; /* Name of command */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ const char *val; /* Option value */
+ int shading; /* -1 = black, 0 = grey, 1 = color */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ fputs("ERROR: hpgltops job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ fp = stdin;
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = fopen(argv[6], "rb")) == NULL)
+ {
+ perror("ERROR: unable to open print file - ");
+ return (1);
+ }
+ }
+
+ /*
+ * Process command-line options and write the prolog...
+ */
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ PPD = SetCommonOptions(num_options, options, 1);
+
+ PlotSize[0] = PageWidth;
+ PlotSize[1] = PageLength;
+
+ shading = 1;
+ PenWidth = 1.0;
+
+ if ((val = cupsGetOption("blackplot", num_options, options)) != NULL &&
+ strcasecmp(val, "no") && strcasecmp(val, "off") &&
+ strcasecmp(val, "false"))
+ shading = 0;
+
+ if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
+ strcasecmp(val, "no") && strcasecmp(val, "off") &&
+ strcasecmp(val, "false"))
+ FitPlot = 1;
+
+ if ((val = cupsGetOption("penwidth", num_options, options)) != NULL)
+ PenWidth = (float)atoi(val) * 0.001f;
+
+ /*
+ * Write the PostScript prolog and initialize the plotting "engine"...
+ */
+
+ OutputProlog(argv[3], argv[2], shading);
+
+ IP_input_absolute(0, NULL);
+
+ /*
+ * Sort the command array...
+ */
+
+ qsort(commands, NUM_COMMANDS, sizeof(name_t),
+ (int (*)(const void *, const void *))compare_names);
+
+ /*
+ * Read commands until we reach the end of file.
+ */
+
+ while ((num_params = ParseCommand(fp, name.name, &params)) >= 0)
+ {
+ Outputf("%% %s(%d)\n", name.name, num_params);
+
+#ifdef DEBUG
+ {
+ int i;
+ fprintf(stderr, "DEBUG: %s(%d)", name.name, num_params);
+ for (i = 0; i < num_params; i ++)
+ if (params[i].type == PARAM_STRING)
+ fprintf(stderr, " \'%s\'", params[i].value.string);
+ else
+ fprintf(stderr, " %f", params[i].value.number);
+ fputs("\n", stderr);
+ }
+#endif /* DEBUG */
+
+ if ((command = bsearch(&name, commands, NUM_COMMANDS, sizeof(name_t),
+ (int (*)(const void *, const void *))compare_names)) != NULL)
+ (*command->func)(num_params, params);
+
+ FreeParameters(num_params, params);
+ }
+
+ OutputTrailer();
+
+ if (fp != stdin)
+ fclose(fp);
+
+ return (0);
+}
+
+
+/*
+ * 'compare_names()' - Compare two command names.
+ */
+
+static int /* O - Result of strcasecmp() on names */
+compare_names(const void *p1, /* I - First name */
+ const void *p2) /* I - Second name */
+{
+ return (strcasecmp(((name_t *)p1)->name, ((name_t *)p2)->name));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-polygon.c b/filter/hpgl-polygon.c
new file mode 100644
index 000000000..4901c5025
--- /dev/null
+++ b/filter/hpgl-polygon.c
@@ -0,0 +1,394 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 polygon routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * EA_edge_rect_absolute() - Draw a rectangle.
+ * EP_edge_polygon() - Stroke the edges of a polygon.
+ * ER_edge_rect_relative() - Draw a rectangle relative to the current
+ * EW_edge_wedge() - Draw a pie wedge.
+ * FP_fill_polygon() - Fill a polygon.
+ * PM_polygon_mode() - Set the polygon drawing mode.
+ * RA_fill_rect_absolute() - Fill a rectangle.
+ * RR_fill_rect_relative() - Fill a rectangle relative to the current
+ * WG_fill_wedge() - Fill a pie wedge.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+
+
+/*
+ * 'EA_edge_rect_absolute()' - Draw a rectangle.
+ */
+
+void
+EA_edge_rect_absolute(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+
+
+ if (num_params < 2)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ Transform[0][2];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ Transform[1][2];
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ Outputf("%.3f %.3f LI\n", PenPosition[0], y);
+ Outputf("%.3f %.3f LI\n", x, y);
+ Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'EP_edge_polygon()' - Stroke the edges of a polygon.
+ */
+
+void
+EP_edge_polygon(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'ER_edge_rect_relative()' - Draw a rectangle relative to the current
+ * pen position.
+ */
+
+void
+ER_edge_rect_relative(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+
+
+ if (num_params < 2)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ PenPosition[0];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ PenPosition[1];
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ Outputf("%.3f %.3f LI\n", PenPosition[0], y);
+ Outputf("%.3f %.3f LI\n", x, y);
+ Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'EW_edge_wedge()' - Draw a pie wedge.
+ */
+
+void
+EW_edge_wedge(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+ float start, end, /* Start and end of arc */
+ theta, /* Current angle */
+ dt, /* Step between points */
+ radius; /* Radius of arc */
+
+
+ if (num_params < 3)
+ return;
+
+ radius = params[0].value.number;
+ start = params[1].value.number;
+ end = start + params[2].value.number;
+
+ if (num_params > 3)
+ dt = (float)fabs(params[3].value.number);
+ else
+ dt = 5.0f;
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ if (start < end)
+ for (theta = start + dt; theta < end; theta += dt)
+ {
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
+
+ Outputf("%.3f %.3f LI\n", x, y);
+ }
+ else
+ for (theta = start - dt; theta > end; theta -= dt)
+ {
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
+
+ Outputf("%.3f %.3f LI\n", x, y);
+ }
+
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * end / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * end / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * end / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * end / 180.0) * Transform[1][1]);
+ Outputf("%.3f %.3f LI\n", x, y);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'FP_fill_polygon()' - Fill a polygon.
+ */
+
+void
+FP_fill_polygon(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ (void)num_params;
+ (void)params;
+
+ Outputf("FI\n");
+}
+
+
+/*
+ * 'PM_polygon_mode()' - Set the polygon drawing mode.
+ */
+
+void
+PM_polygon_mode(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params == 0 ||
+ params[0].value.number == 0)
+ {
+ Outputf("MP\n");
+ PenValid = 0;
+ PolygonMode = 1;
+ }
+ else if (params[0].value.number == 2)
+ PolygonMode = 0;
+}
+
+
+/*
+ * 'RA_fill_rect_absolute()' - Fill a rectangle.
+ */
+
+void
+RA_fill_rect_absolute(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+
+
+ if (num_params < 2)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ Transform[0][2];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ Transform[1][2];
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ Outputf("%.3f %.3f LI\n", PenPosition[0], y);
+ Outputf("%.3f %.3f LI\n", x, y);
+ Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("FI\n");
+}
+
+
+/*
+ * 'RR_fill_rect_relative()' - Fill a rectangle relative to the current
+ * pen position.
+ */
+
+void
+RR_fill_rect_relative(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+
+
+ if (num_params < 2)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ PenPosition[0];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ PenPosition[1];
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ Outputf("%.3f %.3f LI\n", PenPosition[0], y);
+ Outputf("%.3f %.3f LI\n", x, y);
+ Outputf("%.3f %.3f LI\n", x, PenPosition[1]);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("FI\n");
+}
+
+
+/*
+ * 'WG_fill_wedge()' - Fill a pie wedge.
+ */
+
+void
+WG_fill_wedge(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+ float start, end, /* Start and end angles */
+ theta, /* Current angle */
+ dt, /* Step between points */
+ radius; /* Radius of arc */
+
+
+ if (num_params < 3)
+ return;
+
+ radius = params[0].value.number;
+ start = params[1].value.number;
+ end = start + params[2].value.number;
+
+ if (num_params > 3)
+ dt = (float)fabs(params[3].value.number);
+ else
+ dt = 5.0;
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ if (start < end)
+ for (theta = start + dt; theta < end; theta += dt)
+ {
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
+
+ Outputf("%.3f %.3f LI\n", x, y);
+ }
+ else
+ for (theta = start - dt; theta > end; theta -= dt)
+ {
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
+
+ Outputf("%.3f %.3f LI\n", x, y);
+ }
+
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * end / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * end / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * end / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * end / 180.0) * Transform[1][1]);
+ Outputf("%.3f %.3f LI\n", x, y);
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("FI\n");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-prolog.c b/filter/hpgl-prolog.c
new file mode 100644
index 000000000..9eb2ca67a
--- /dev/null
+++ b/filter/hpgl-prolog.c
@@ -0,0 +1,377 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 prolog routines for for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * OutputProlog() - Output the PostScript prolog...
+ * OutputTrailer() - Output the PostScript trailer...
+ * Outputf() - Write a formatted string to the output file, creating the
+ * page header as needed...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+#include <stdarg.h>
+
+
+/*
+ * 'OutputProlog()' - Output the PostScript prolog...
+ */
+
+void
+OutputProlog(char *title, /* I - Job title */
+ char *user, /* I - Username */
+ int shading) /* I - Type of shading */
+{
+ FILE *prolog; /* Prolog file */
+ char line[255]; /* Line from prolog file */
+ const char *datadir; /* CUPS_DATADIR environment variable */
+ char filename[1024]; /* Name of prolog file */
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+
+
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+
+ puts("%!PS-Adobe-3.0");
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+ PageLeft, PageBottom, PageRight, PageTop);
+ puts("%%Pages: (atend)");
+ printf("%%%%LanguageLevel: %d\n", LanguageLevel);
+ puts("%%DocumentData: Clean7Bit");
+ puts("%%DocumentSuppliedResources: procset hpgltops 1.1 0");
+ puts("%%DocumentNeededResources: font Courier Helvetica");
+ puts("%%Creator: hpgltops/" CUPS_SVERSION);
+ strftime(line, sizeof(line), CUPS_STRFTIME_FORMAT, curtm);
+ printf("%%%%CreationDate: %s\n", line);
+ printf("%%%%Title: %s\n", title);
+ printf("%%%%For: %s\n", user);
+ printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
+ puts("%%EndComments");
+ puts("%%BeginProlog");
+ printf("/DefaultPenWidth %.2f def\n", PenWidth * 72.0 / 25.4);
+ if (!shading) /* Black only */
+ puts("/setrgbcolor { pop pop pop } bind def");
+ else if (!ColorDevice) /* Greyscale */
+ puts("/setrgbcolor { 0.08 mul exch 0.61 mul add exch 0.31 mul add setgray } bind def\n");
+
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+ datadir = CUPS_DATADIR;
+
+ snprintf(filename, sizeof(filename), "%s/data/HPGLprolog", datadir);
+
+ if ((prolog = fopen(filename, "r")) == NULL)
+ {
+ fprintf(stderr, "ERROR: Unable to open HPGL prolog \"%s\" for reading - %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+
+ while (fgets(line, sizeof(line), prolog) != NULL)
+ fputs(line, stdout);
+
+ fclose(prolog);
+
+ puts("%%EndProlog");
+
+ IN_initialize(0, NULL);
+}
+
+
+/*
+ * 'OutputTrailer()' - Output the PostScript trailer...
+ */
+
+void
+OutputTrailer(void)
+{
+ if (PageDirty)
+ PG_advance_page(0, NULL);
+
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", PageCount);
+ puts("%%EOF");
+}
+
+
+/*
+ * 'Outputf()' - Write a formatted string to the output file, creating the
+ * page header as needed...
+ */
+
+int /* O - Number of bytes written */
+Outputf(const char *format, /* I - Printf-style string */
+ ...) /* I - Additional args as needed */
+{
+ va_list ap; /* Argument pointer */
+ int bytes; /* Number of bytes written */
+ float iw1[2], iw2[2]; /* Clipping window */
+ int i; /* Looping var */
+ ppd_size_t *size; /* Page size */
+ ppd_option_t *option; /* Page size option */
+ ppd_choice_t *choice; /* Page size choice */
+ float width, length; /* Page dimensions */
+ int landscape; /* Rotate for landscape orientation? */
+
+
+ /*
+ * Write the page header as needed...
+ */
+
+ if (!PageDirty)
+ {
+ PageDirty = 1;
+ PageCount ++;
+
+ printf("%%%%Page: %d %d\n", PageCount, PageCount);
+
+ landscape = 0;
+
+ if (!FitPlot && PlotSizeSet)
+ {
+ /*
+ * Set the page size for this page...
+ */
+
+ if (PageRotation == 0 || PageRotation == 180)
+ {
+ width = PlotSize[0];
+ length = PlotSize[1];
+ }
+ else
+ {
+ width = PlotSize[1];
+ length = PlotSize[0];
+ }
+
+ fprintf(stderr, "DEBUG: hpgltops setting page size (%.0f x %.0f)\n",
+ width, length);
+
+ if (PPD != NULL)
+ {
+ fputs("DEBUG: hpgltops has a PPD file!\n", stderr);
+
+ /*
+ * Lookup the closest PageSize and set it...
+ */
+
+ for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++)
+ if ((fabs(length - size->length) < 36.0 && size->width >= width) ||
+ (fabs(length - size->width) < 36.0 && size->length >= width))
+ break;
+
+ if (i == 0 && PPD->variable_sizes)
+ {
+ for (i = PPD->num_sizes, size = PPD->sizes; i > 0; i --, size ++)
+ if (strcasecmp(size->name, "custom") == 0)
+ break;
+ }
+
+ if (i > 0)
+ {
+ /*
+ * Found a matching size...
+ */
+
+ option = ppdFindOption(PPD, "PageSize");
+ choice = ppdFindChoice(option, size->name);
+
+ puts("%%BeginPageSetup");
+ printf("%%%%BeginFeature: PageSize %s\n", size->name);
+
+ if (strcasecmp(size->name, "custom") == 0)
+ {
+ PageLeft = PPD->custom_margins[0];
+ PageRight = width - PPD->custom_margins[2];
+ PageWidth = width;
+ PageBottom = PPD->custom_margins[1];
+ PageTop = length - PPD->custom_margins[3];
+ PageLength = length;
+
+ printf("%.0f %.0f 0 0 0\n", width, length);
+
+ if (choice->code == NULL)
+ {
+ /*
+ * This can happen with certain buggy PPD files that don't include
+ * a CustomPageSize command sequence... We just use a generic
+ * Level 2 command sequence...
+ */
+
+ puts("pop pop pop");
+ puts("<</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice\n");
+ }
+ else
+ {
+ /*
+ * Use the vendor-supplied command...
+ */
+
+ printf("%s\n", choice->code);
+ }
+ }
+ else
+ {
+ if (choice->code)
+ printf("%s\n", choice->code);
+
+ if (fabs(length - size->width) < 36.0)
+ {
+ /*
+ * Do landscape orientation...
+ */
+
+ PageLeft = size->bottom;
+ PageRight = size->top;
+ PageWidth = size->length;
+ PageBottom = size->left;
+ PageTop = size->right;
+ PageLength = size->width;
+
+ landscape = 1;
+ }
+ else
+ {
+ /*
+ * Do portrait orientation...
+ */
+
+ PageLeft = size->left;
+ PageRight = size->right;
+ PageWidth = size->width;
+ PageBottom = size->bottom;
+ PageTop = size->top;
+ PageLength = size->length;
+ }
+ }
+
+ puts("%%EndFeature");
+ puts("%%EndPageSetup");
+ }
+ }
+ else
+ {
+ fputs("DEBUG: hpgltops does not have a PPD file!\n", stderr);
+
+ puts("%%BeginPageSetup");
+ printf("%%%%BeginFeature: PageSize w%.0fh%.0f\n", width, length);
+ printf("<</PageSize[%.0f %.0f]/ImageBBox null>>setpagedevice\n",
+ width, length);
+ puts("%%EndFeature");
+ puts("%%EndPageSetup");
+
+ PageLeft = 0.0;
+ PageRight = width;
+ PageWidth = width;
+ PageBottom = 0.0;
+ PageTop = length;
+ PageLength = length;
+ }
+ }
+
+ define_font(0);
+ define_font(1);
+
+ printf("%.1f setmiterlimit\n", MiterLimit);
+ printf("%d setlinecap\n", LineCap);
+ printf("%d setlinejoin\n", LineJoin);
+
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[1].rgb[0], Pens[1].rgb[1],
+ Pens[1].rgb[2], Pens[1].width * PenScaling);
+
+ puts("gsave");
+
+ if (Duplex && (PageCount & 1) == 0)
+ switch ((PageRotation / 90 + landscape) & 3)
+ {
+ case 0 :
+ printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
+ break;
+ case 1 :
+ printf("%.0f 0 translate 90 rotate\n", PageLength);
+ printf("%.1f %.1f translate\n", PageLength - PageTop,
+ PageWidth - PageRight);
+ break;
+ case 2 :
+ printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
+ printf("%.1f %.1f translate\n", PageLeft, PageLength - PageTop);
+ break;
+ case 3 :
+ printf("0 %.0f translate -90 rotate\n", PageWidth);
+ printf("%.1f %.1f translate\n", PageBottom, PageLeft);
+ break;
+ }
+ else
+ switch ((PageRotation / 90 + landscape) & 3)
+ {
+ case 0 :
+ printf("%.1f %.1f translate\n", PageLeft, PageBottom);
+ break;
+ case 1 :
+ printf("%.0f 0 translate 90 rotate\n", PageLength);
+ printf("%.1f %.1f translate\n", PageBottom, PageWidth - PageRight);
+ break;
+ case 2 :
+ printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
+ printf("%.1f %.1f translate\n", PageWidth - PageRight,
+ PageLength - PageTop);
+ break;
+ case 3 :
+ printf("0 %.0f translate -90 rotate\n", PageWidth);
+ printf("%.1f %.1f translate\n", PageLength - PageTop, PageLeft);
+ break;
+ }
+
+ if (IW1[0] != IW2[0] && IW1[1] != IW2[1])
+ {
+ iw1[0] = IW1[0] * 72.0f / 1016.0f;
+ iw1[1] = IW1[1] * 72.0f / 1016.0f;
+ iw2[0] = IW2[0] * 72.0f / 1016.0f;
+ iw2[1] = IW2[1] * 72.0f / 1016.0f;
+
+ printf("initclip MP %.3f %.3f MO %.3f %.3f LI %.3f %.3f LI %.3f %.3f LI CP clip\n",
+ iw1[0], iw1[1], iw1[0], iw2[1], iw2[0], iw2[1], iw2[0], iw1[1]);
+ }
+ }
+
+ /*
+ * Write the string to the output file...
+ */
+
+ va_start(ap, format);
+ bytes = vprintf(format, ap);
+ va_end(ap);
+
+ return (bytes);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgl-vector.c b/filter/hpgl-vector.c
new file mode 100644
index 000000000..3271102e5
--- /dev/null
+++ b/filter/hpgl-vector.c
@@ -0,0 +1,775 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 vector routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * AA_arc_absolute() - Draw an arc.
+ * AR_arc_relative() - Draw an arc relative to the current pen
+ * AT_arc_absolute3() - Draw an arc using 3 points.
+ * CI_circle() - Draw a circle.
+ * PA_plot_absolute() - Plot a line using absolute coordinates.
+ * PD_pen_down() - Start drawing.
+ * PE_polygon_encoded() - Draw an encoded polyline.
+ * PR_plot_relative() - Plot a line using relative coordinates.
+ * PU_pen_up() - Stop drawing.
+ * RT_arc_relative3() - Draw an arc through 3 points relative to the
+ * decode_number() - Decode an encoded number.
+ * plot_points() - Plot the specified points.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "hpgltops.h"
+
+
+/*
+ * Local functions...
+ */
+
+static double decode_number(unsigned char **, int, double);
+static void plot_points(int, param_t *);
+
+
+/*
+ * 'AA_arc_absolute()' - Draw an arc.
+ */
+
+void
+AA_arc_absolute(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y, /* Transformed coordinates */
+ dx, dy; /* Distance from current pen */
+ float start, end, /* Start and end angles */
+ theta, /* Current angle */
+ dt, /* Step between points */
+ radius; /* Radius of arc */
+
+
+ if (num_params < 3)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ Transform[0][2];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ Transform[1][2];
+
+ dx = PenPosition[0] - x;
+ dy = PenPosition[1] - y;
+
+ start = (float)(180.0 * atan2(dy, dx) / M_PI);
+ if (start < 0.0)
+ start += 360.0f;
+
+ end = start + params[2].value.number;
+ radius = (float)hypot(dx, dy);
+
+ if (PenDown)
+ {
+ if (num_params > 3 && params[3].value.number > 0.0)
+ dt = (float)fabs(params[3].value.number);
+ else
+ dt = 5.0;
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ if (start < end)
+ for (theta = start + dt; theta < end; theta += dt)
+ {
+ PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+ else
+ for (theta = start - dt; theta > end; theta -= dt)
+ {
+ PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+ }
+
+ PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
+
+ if (PenDown)
+ {
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+
+ if (!PolygonMode)
+ Outputf("ST\n");
+ }
+}
+
+
+/*
+ * 'AR_arc_relative()' - Draw an arc relative to the current pen
+ * position.
+ */
+
+void
+AR_arc_relative(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y, /* Transformed coordinates */
+ dx, dy; /* Distance from current pen */
+ float start, end, /* Start and end angles */
+ theta, /* Current angle */
+ dt, /* Step between points */
+ radius; /* Radius of arc */
+
+
+ if (num_params < 3)
+ return;
+
+ x = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ PenPosition[0];
+ y = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ PenPosition[1];
+
+ dx = PenPosition[0] - x;
+ dy = PenPosition[1] - y;
+
+ start = (float)(180.0 * atan2(dy, dx) / M_PI);
+ if (start < 0.0)
+ start += 360.0f;
+
+ end = start + params[2].value.number;
+ radius = (float)hypot(dx, dy);
+
+ if (PenDown)
+ {
+ if (num_params > 3 && params[3].value.number > 0.0)
+ dt = (float)fabs(params[3].value.number);
+ else
+ dt = 5.0;
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ if (start < end)
+ for (theta = start + dt; theta < end; theta += dt)
+ {
+ PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+ else
+ for (theta = start - dt; theta > end; theta -= dt)
+ {
+ PenPosition[0] = (float)(x + radius * cos(M_PI * theta / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * theta / 180.0));
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+ }
+
+ PenPosition[0] = (float)(x + radius * cos(M_PI * end / 180.0));
+ PenPosition[1] = (float)(y + radius * sin(M_PI * end / 180.0));
+
+ if (PenDown)
+ {
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+
+ if (!PolygonMode)
+ Outputf("ST\n");
+ }
+}
+
+
+/*
+ * 'AT_arc_absolute3()' - Draw an arc using 3 points.
+ *
+ * Note:
+ *
+ * Currently this only draws two line segments through the
+ * specified points.
+ */
+
+void
+AT_arc_absolute3(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params < 4)
+ return;
+
+ if (PenDown)
+ {
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ PenPosition[0] = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ Transform[0][2];
+ PenPosition[1] = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ Transform[1][2];
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+
+ PenPosition[0] = Transform[0][0] * params[2].value.number +
+ Transform[0][1] * params[3].value.number +
+ Transform[0][2];
+ PenPosition[1] = Transform[1][0] * params[2].value.number +
+ Transform[1][1] * params[3].value.number +
+ Transform[1][2];
+
+ if (PenDown)
+ {
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+
+ if (!PolygonMode)
+ Outputf("ST\n");
+ }
+}
+
+
+/*
+ * 'CI_circle()' - Draw a circle.
+ */
+
+void
+CI_circle(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ float x, y; /* Transformed coordinates */
+ float theta, /* Current angle */
+ dt, /* Step between points */
+ radius; /* Radius of circle */
+
+
+ if (num_params < 1)
+ return;
+
+ if (!PenDown)
+ return;
+
+ radius = params[0].value.number;
+
+ if (num_params > 1)
+ dt = (float)fabs(params[1].value.number);
+ else
+ dt = 5.0;
+
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ for (theta = 0.0; theta < 360.0; theta += dt)
+ {
+ x = (float)(PenPosition[0] +
+ radius * cos(M_PI * theta / 180.0) * Transform[0][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[0][1]);
+ y = (float)(PenPosition[1] +
+ radius * cos(M_PI * theta / 180.0) * Transform[1][0] +
+ radius * sin(M_PI * theta / 180.0) * Transform[1][1]);
+
+ Outputf("%.3f %.3f %s\n", x, y, theta == 0.0 ? "MO" : "LI");
+ }
+
+ Outputf("CP\n");
+ if (!PolygonMode)
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'PA_plot_absolute()' - Plot a line using absolute coordinates.
+ */
+
+void
+PA_plot_absolute(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ PenMotion = 0;
+
+ if (num_params > 1)
+ plot_points(num_params, params);
+}
+
+
+/*
+ * 'PD_pen_down()' - Start drawing.
+ */
+
+void
+PD_pen_down(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ PenDown = 1;
+
+ if (num_params > 1)
+ plot_points(num_params, params);
+}
+
+
+/*
+ * 'PE_polygon_encoded()' - Draw an encoded polyline.
+ */
+
+void
+PE_polyline_encoded(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ unsigned char *s; /* Pointer into string */
+ int temp, /* Temporary value */
+ base_bits, /* Data bits per byte */
+ draw, /* Draw or move */
+ abscoords; /* Use absolute coordinates */
+ double tx, ty, /* Transformed coordinates */
+ x, y, /* Raw coordinates */
+ frac_bits; /* Multiplier for encoded number */
+
+
+ base_bits = 6;
+ frac_bits = 1.0;
+ draw = PenDown;
+ abscoords = 0;
+
+ if (num_params == 0)
+ return;
+
+ if (!PolygonMode)
+ {
+ Outputf("MP\n");
+ PenValid = 0;
+ }
+
+ if (!PenValid)
+ {
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+ PenValid = 1;
+ }
+
+ for (s = (unsigned char *)params[0].value.string; *s != '\0';)
+ switch (*s)
+ {
+ case '7' :
+ s ++;
+ base_bits = 5;
+
+#ifdef DEBUG
+ fputs("DEBUG: 7-bit\n", stderr);
+#endif /* DEBUG */
+
+ Outputf("%% PE: 7-bit\n");
+ break;
+ case ':' : /* Select pen */
+ s ++;
+ PenNumber = (int)decode_number(&s, base_bits, 1.0);
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG: set pen #%d\n", PenNumber);
+#endif /* DEBUG */
+
+ Outputf("%% PE: set pen #%d\n", PenNumber);
+
+ if (PageDirty)
+ printf("%.3f %.3f %.3f %.2f SP\n", Pens[PenNumber].rgb[0],
+ Pens[PenNumber].rgb[1], Pens[PenNumber].rgb[2],
+ Pens[PenNumber].width * PenScaling);
+ break;
+ case '<' : /* Next coords are a move-to */
+ draw = 0;
+ s ++;
+
+#ifdef DEBUG
+ fputs("DEBUG: moveto\n", stderr);
+#endif /* DEBUG */
+
+ Outputf("%% PE: moveto\n");
+ break;
+ case '>' : /* Set fractional bits */
+ s ++;
+ temp = (int)decode_number(&s, base_bits, 1.0);
+ frac_bits = 1.0 / (1 << temp);
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG: set fractional bits %d\n", temp);
+#endif /* DEBUG */
+
+ Outputf("%% PE: set fractional bits %d\n", temp);
+ break;
+ case '=' : /* Next coords are absolute */
+ s ++;
+ abscoords = 1;
+
+#ifdef DEBUG
+ fputs("DEBUG: absolute\n", stderr);
+#endif /* DEBUG */
+
+ Outputf("%% PE: absolute\n");
+ break;
+ default :
+ if (*s >= 63)
+ {
+ /*
+ * Coordinate...
+ */
+
+ x = decode_number(&s, base_bits, frac_bits);
+ y = decode_number(&s, base_bits, frac_bits);
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG: coords %.3f %.3f\n", x, y);
+#endif /* DEBUG */
+
+ Outputf("%% PE: coords %.3f %.3f\n", x, y);
+
+ if (abscoords)
+ {
+ tx = Transform[0][0] * x + Transform[0][1] * y +
+ Transform[0][2];
+ ty = Transform[1][0] * x + Transform[1][1] * y +
+ Transform[1][2];
+ }
+ else if (x == 0.0 && y == 0.0)
+ {
+ draw = 1;
+ continue;
+ }
+ else
+ {
+ tx = Transform[0][0] * x + Transform[0][1] * y +
+ PenPosition[0];
+ ty = Transform[1][0] * x + Transform[1][1] * y +
+ PenPosition[1];
+ }
+
+ if (draw)
+ {
+ if (fabs(PenPosition[0] - tx) > 0.001 ||
+ fabs(PenPosition[1] - ty) > 0.001)
+ Outputf("%.3f %.3f LI\n", tx, ty);
+ }
+ else
+ Outputf("%.3f %.3f MO\n", tx, ty);
+
+ PenPosition[0] = (float)tx;
+ PenPosition[1] = (float)ty;
+
+ draw = 1;
+ abscoords = 0;
+ }
+ else
+ {
+ /*
+ * Junk - ignore...
+ */
+
+ if (*s != '\n' && *s != '\r')
+ fprintf(stderr, "WARNING: ignoring illegal PE char \'%c\'...\n", *s);
+ s ++;
+ }
+ break;
+ }
+
+ if (!PolygonMode)
+ Outputf("ST\n");
+}
+
+
+/*
+ * 'PR_plot_relative()' - Plot a line using relative coordinates.
+ */
+
+void
+PR_plot_relative(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ PenMotion = 1;
+
+ if (num_params > 1)
+ plot_points(num_params, params);
+}
+
+
+/*
+ * 'PU_pen_up()' - Stop drawing.
+ */
+
+void
+PU_pen_up(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ PenDown = 0;
+
+ if (num_params > 1)
+ plot_points(num_params, params);
+}
+
+
+/*
+ * 'RT_arc_relative3()' - Draw an arc through 3 points relative to the
+ * current pen position.
+ *
+ * Note:
+ *
+ * This currently only draws two line segments through the specified
+ * points.
+ */
+
+void
+RT_arc_relative3(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ if (num_params < 4)
+ return;
+
+ if (PenDown)
+ {
+ if (!PolygonMode)
+ Outputf("MP\n");
+
+ PenValid = 1;
+
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ PenPosition[0] = Transform[0][0] * params[0].value.number +
+ Transform[0][1] * params[1].value.number +
+ PenPosition[0];
+ PenPosition[1] = Transform[1][0] * params[0].value.number +
+ Transform[1][1] * params[1].value.number +
+ PenPosition[1];
+
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+ }
+
+ PenPosition[0] = Transform[0][0] * params[2].value.number +
+ Transform[0][1] * params[3].value.number +
+ PenPosition[0];
+ PenPosition[1] = Transform[1][0] * params[2].value.number +
+ Transform[1][1] * params[3].value.number +
+ PenPosition[1];
+
+ if (PenDown)
+ {
+ Outputf("%.3f %.3f LI\n", PenPosition[0], PenPosition[1]);
+
+ if (!PolygonMode)
+ Outputf("ST\n");
+ }
+}
+
+
+/*
+ * 'decode_number()' - Decode an encoded number.
+ */
+
+static double /* O - Value */
+decode_number(unsigned char **s, /* IO - String to decode */
+ int base_bits, /* I - Number of data bits per byte */
+ double frac_bits) /* I - Multiplier for fractional data */
+{
+ double temp, /* Current value */
+ shift; /* Multiplier */
+ int sign; /* Sign of result */
+
+
+ sign = 0;
+
+ if (base_bits == 5)
+ {
+ for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
+ if (**s >= 95 && **s < 127)
+ {
+ if (sign == 0)
+ {
+ if ((**s - 95) & 1)
+ sign = -1;
+ else
+ sign = 1;
+
+ temp += ((**s - 95) & ~1) * shift;
+ }
+ else
+ temp += (**s - 95) * shift;
+ break;
+ }
+ else if (**s < 63)
+ {
+ if (**s != '\r' && **s != '\n')
+ fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
+
+ continue;
+ }
+ else
+ {
+ if (sign == 0)
+ {
+ if ((**s - 63) & 1)
+ sign = -1;
+ else
+ sign = 1;
+
+ temp += ((**s - 63) & ~1) * shift;
+ }
+ else
+ temp += (**s - 63) * shift;
+
+ shift *= 32.0;
+ }
+ }
+ else
+ {
+ for (temp = 0.0, shift = frac_bits * 0.5; **s != '\0'; (*s) ++)
+ if (**s >= 191 && **s < 255)
+ {
+ if (sign == 0)
+ {
+ if ((**s - 191) & 1)
+ sign = -1;
+ else
+ sign = 1;
+
+ temp += ((**s - 191) & ~1) * shift;
+ }
+ else
+ temp += (**s - 191) * shift;
+ break;
+ }
+ else if (**s < 63)
+ {
+ if (**s != '\r' && **s != '\n')
+ fprintf(stderr, "ERROR: Bad PE character 0x%02X!\n", **s);
+
+ continue;
+ }
+ else
+ {
+ if (sign == 0)
+ {
+ if ((**s - 63) & 1)
+ sign = -1;
+ else
+ sign = 1;
+
+ temp += ((**s - 63) & ~1) * shift;
+ }
+ else
+ temp += (**s - 63) * shift;
+
+ shift *= 64.0;
+ }
+ }
+
+ (*s) ++;
+
+ return (temp * sign);
+}
+
+
+/*
+ * 'plot_points()' - Plot the specified points.
+ */
+
+static void
+plot_points(int num_params, /* I - Number of parameters */
+ param_t *params) /* I - Parameters */
+{
+ int i; /* Looping var */
+ float x, y; /* Transformed coordinates */
+
+
+ if (PenDown)
+ {
+ if (!PolygonMode)
+ {
+ Outputf("MP\n");
+ Outputf("%.3f %.3f MO\n", PenPosition[0], PenPosition[1]);
+
+ PenValid = 1;
+ }
+ }
+
+ for (i = 0; i < num_params; i += 2)
+ {
+ if (PenMotion == 0)
+ {
+ x = Transform[0][0] * params[i + 0].value.number +
+ Transform[0][1] * params[i + 1].value.number +
+ Transform[0][2];
+ y = Transform[1][0] * params[i + 0].value.number +
+ Transform[1][1] * params[i + 1].value.number +
+ Transform[1][2];
+ }
+ else
+ {
+ x = Transform[0][0] * params[i + 0].value.number +
+ Transform[0][1] * params[i + 1].value.number +
+ PenPosition[0];
+ y = Transform[1][0] * params[i + 0].value.number +
+ Transform[1][1] * params[i + 1].value.number +
+ PenPosition[1];
+ }
+
+ if (PenDown)
+ {
+ if (PolygonMode && i == 0)
+ Outputf("%.3f %.3f MO\n", x, y);
+ else if (fabs(PenPosition[0] - x) > 0.001 ||
+ fabs(PenPosition[1] - y) > 0.001)
+ Outputf("%.3f %.3f LI\n", x, y);
+ }
+
+ PenPosition[0] = x;
+ PenPosition[1] = y;
+ }
+
+ if (PenDown)
+ {
+ if (!PolygonMode)
+ Outputf("ST\n");
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/hpgltops.dsp b/filter/hpgltops.dsp
new file mode 100644
index 000000000..3f678523d
--- /dev/null
+++ b/filter/hpgltops.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="hpgltops" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=hpgltops - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "hpgltops.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "hpgltops.mak" CFG="hpgltops - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "hpgltops - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "hpgltops - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "hpgltops - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"hpgltops.exe"
+
+!ELSEIF "$(CFG)" == "hpgltops - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "hpgltops___Win32_Debug"
+# PROP BASE Intermediate_Dir "hpgltops___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../cups/cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"hpgltopsd.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "hpgltops - Win32 Release"
+# Name "hpgltops - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=".\hpgl-attr.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-char.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-config.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-input.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-main.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-polygon.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-prolog.c"
+# End Source File
+# Begin Source File
+
+SOURCE=".\hpgl-vector.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\hpgltops.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/filter/hpgltops.h b/filter/hpgltops.h
new file mode 100644
index 000000000..c68a04c6c
--- /dev/null
+++ b/filter/hpgltops.h
@@ -0,0 +1,241 @@
+/*
+ * "$Id$"
+ *
+ * HP-GL/2 to PostScript filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+#include <math.h>
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif /* M_PI */
+
+/*
+ * Parameter value structure...
+ */
+
+typedef struct
+{
+ int type;
+ union
+ {
+ float number;
+ char *string;
+ } value;
+} param_t;
+
+#define PARAM_ABSOLUTE 0
+#define PARAM_RELATIVE 1
+#define PARAM_STRING 2
+
+
+/*
+ * Font information...
+ */
+
+typedef struct
+{
+ int symbol_set, /* Symbol set */
+ spacing, /* Spacing (0 = fixed, 1 = proportional) */
+ posture, /* Posture number */
+ weight, /* Weight number */
+ typeface; /* Typeface number */
+ float pitch, /* Characters per inch */
+ height, /* Height/size of font */
+ xpitch; /* X pitch scaling value */
+ float x, y; /* X and Y direction/scaling */
+} font_t;
+
+
+/*
+ * Pen information...
+ */
+
+typedef struct
+{
+ float rgb[3]; /* Pen color */
+ float width; /* Pen width */
+} pen_t;
+
+
+/*
+ * Globals...
+ */
+
+#ifdef _HPGL_MAIN_C_
+# define VAR
+# define VALUE(x) =x
+# define VALUE2(x,y) ={x,y}
+#else
+# define VAR extern
+# define VALUE(x)
+# define VALUE2(x,y)
+#endif /* _HPGL_MAIN_C_ */
+
+VAR ppd_file_t *PPD VALUE(NULL); /* PPD file */
+
+VAR float P1[2], /* Lower-lefthand physical limit */
+ P2[2], /* Upper-righthand physical limit */
+ IW1[2], /* Window lower-lefthand limit */
+ IW2[2]; /* Window upper-righthand limit */
+VAR int Rotation VALUE(0); /* Page rotation */
+VAR int ScalingType VALUE(-1); /* Type of scaling (-1 for none) */
+VAR float Scaling1[2], /* Lower-lefthand user limit */
+ Scaling2[2]; /* Upper-righthand user limit */
+VAR float Transform[2][3]; /* Transform matrix */
+VAR int PageRotation VALUE(0); /* Page/plot rotation */
+
+VAR char StringTerminator VALUE('\003'); /* Terminator for labels */
+VAR font_t StandardFont, /* Standard font */
+ AlternateFont; /* Alternate font */
+VAR float PenPosition[2] VALUE2(0.0f, 0.0f),
+ /* Current pen position */
+ PenScaling VALUE(1.0f), /* Pen width scaling factor */
+ PenWidth VALUE(1.0f); /* Default pen width */
+VAR pen_t Pens[1024]; /* State of each pen */
+VAR int PenMotion VALUE(0), /* 0 = absolute, 1 = relative */
+ PenValid VALUE(0), /* 1 = valid position, 0 = undefined */
+ PenNumber VALUE(1), /* Current pen number */
+ PenCount VALUE(8), /* Number of pens */
+ PenDown VALUE(0), /* 0 = pen up, 1 = pen down */
+ PolygonMode VALUE(0), /* Drawing polygons? */
+ PageCount VALUE(0), /* Number of pages in plot */
+ PageDirty VALUE(0), /* Current page written on? */
+ WidthUnits VALUE(0); /* 0 = mm, 1 = proportionate */
+VAR float PlotSize[2] VALUE2(2592.0f, 3456.0f);
+ /* Plot size */
+VAR int PlotSizeSet VALUE(0); /* Plot size set? */
+VAR int CharFillMode VALUE(0), /* Where to draw labels */
+ CharPen VALUE(0), /* Pen to use for labels */
+ CharFont VALUE(0); /* Font to use for labels */
+VAR float CharHeight[2] VALUE2(11.5f,11.5f);
+ /* Size of font for labels */
+VAR int FitPlot VALUE(0); /* 1 = fit to page */
+VAR float ColorRange[3][2] /* Range of color values */
+#ifdef _HPGL_MAIN_C_
+ = {
+ { 0.0, 255.0 },
+ { 0.0, 255.0 },
+ { 0.0, 255.0 }
+ }
+#endif /* _HPGL_MAIN_C_ */
+;
+
+VAR int LineCap VALUE(0); /* Line capping */
+VAR int LineJoin VALUE(0); /* Line joining */
+VAR float MiterLimit VALUE(3.0f); /* Miter limit at joints */
+
+
+/*
+ * Prototypes...
+ */
+
+/* hpgl-input.c */
+extern int ParseCommand(FILE *fp, char *name, param_t **params);
+extern void FreeParameters(int num_params, param_t *params);
+
+/* hpgl-config.c */
+extern void update_transform(void);
+extern void BP_begin_plot(int num_params, param_t *params);
+extern void DF_default_values(int num_params, param_t *params);
+extern void IN_initialize(int num_params, param_t *params);
+extern void IP_input_absolute(int num_params, param_t *params);
+extern void IR_input_relative(int num_params, param_t *params);
+extern void IW_input_window(int num_params, param_t *params);
+extern void PG_advance_page(int num_params, param_t *params);
+extern void PS_plot_size(int num_params, param_t *params);
+extern void RO_rotate(int num_params, param_t *params);
+extern void RP_replot(int num_params, param_t *params);
+extern void SC_scale(int num_params, param_t *params);
+
+/* hpgl-vector.c */
+extern void AA_arc_absolute(int num_params, param_t *params);
+extern void AR_arc_relative(int num_params, param_t *params);
+extern void AT_arc_absolute3(int num_params, param_t *params);
+extern void CI_circle(int num_params, param_t *params);
+extern void PA_plot_absolute(int num_params, param_t *params);
+extern void PD_pen_down(int num_params, param_t *params);
+extern void PE_polyline_encoded(int num_params, param_t *params);
+extern void PR_plot_relative(int num_params, param_t *params);
+extern void PU_pen_up(int num_params, param_t *params);
+extern void RT_arc_relative3(int num_params, param_t *params);
+
+/* hpgl-polygon.c */
+extern void EA_edge_rect_absolute(int num_params, param_t *params);
+extern void EP_edge_polygon(int num_params, param_t *params);
+extern void ER_edge_rect_relative(int num_params, param_t *params);
+extern void EW_edge_wedge(int num_params, param_t *params);
+extern void FP_fill_polygon(int num_params, param_t *params);
+extern void PM_polygon_mode(int num_params, param_t *params);
+extern void RA_fill_rect_absolute(int num_params, param_t *params);
+extern void RR_fill_rect_relative(int num_params, param_t *params);
+extern void WG_fill_wedge(int num_params, param_t *params);
+
+/* hpgl-char.c */
+extern void define_font(int f);
+extern void AD_define_alternate(int num_params, param_t *params);
+extern void CF_character_fill(int num_params, param_t *params);
+extern void CP_character_plot(int num_params, param_t *params);
+extern void DI_absolute_direction(int num_params, param_t *params);
+extern void DR_relative_direction(int num_params, param_t *params);
+extern void DT_define_label_term(int num_params, param_t *params);
+extern void DV_define_variable_path(int num_params, param_t *params);
+extern void ES_extra_space(int num_params, param_t *params);
+extern void LB_label(int num_params, param_t *params);
+extern void LO_label_origin(int num_params, param_t *params);
+extern void SA_select_alternate(int num_params, param_t *params);
+extern void SD_define_standard(int num_params, param_t *params);
+extern void SI_absolute_size(int num_params, param_t *params);
+extern void SL_character_slant(int num_params, param_t *params);
+extern void SR_relative_size(int num_params, param_t *params);
+extern void SS_select_standard(int num_params, param_t *params);
+extern void TD_transparent_data(int num_params, param_t *params);
+
+/* hpgl-attr.c */
+extern void AC_anchor_corner(int num_params, param_t *params);
+extern void CR_color_range(int num_params, param_t *params);
+extern void FT_fill_type(int num_params, param_t *params);
+extern void LA_line_attributes(int num_params, param_t *params);
+extern void LT_line_type(int num_params, param_t *params);
+extern void NP_number_pens(int num_params, param_t *params);
+extern void PC_pen_color(int num_params, param_t *params);
+extern void PW_pen_width(int num_params, param_t *params);
+extern void RF_raster_fill(int num_params, param_t *params);
+extern void SM_symbol_mode(int num_params, param_t *params);
+extern void SP_select_pen(int num_params, param_t *params);
+extern void UL_user_line_type(int num_params, param_t *params);
+extern void WU_width_units(int num_params, param_t *params);
+
+/* hpgl-prolog.c */
+extern void OutputProlog(char *title, char *user, int shading);
+extern void OutputTrailer(void);
+extern int Outputf(const char *format, ...);
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-bmp.c b/filter/image-bmp.c
new file mode 100644
index 000000000..b98a837dd
--- /dev/null
+++ b/filter/image-bmp.c
@@ -0,0 +1,539 @@
+/*
+ * "$Id$"
+ *
+ * BMP image routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadBMP() - Read a BMP image file.
+ * read_word() - Read a 16-bit unsigned integer.
+ * read_dword() - Read a 32-bit unsigned integer.
+ * read_long() - Read a 32-bit signed integer.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * Constants for the bitmap compression...
+ */
+
+# define BI_RGB 0 /* No compression - straight BGR data */
+# define BI_RLE8 1 /* 8-bit run-length compression */
+# define BI_RLE4 2 /* 4-bit run-length compression */
+# define BI_BITFIELDS 3 /* RGB bitmap with RGB masks */
+
+
+/*
+ * Local functions...
+ */
+
+static unsigned short read_word(FILE *fp);
+static unsigned int read_dword(FILE *fp);
+static int read_long(FILE *fp);
+
+
+/*
+ * 'ImageReadBMP()' - Read a BMP image file.
+ */
+
+int /* O - Read status */
+ImageReadBMP(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int offset, /* Offset to bitmap data */
+ info_size, /* Size of info header */
+ planes, /* Number of planes (always 1) */
+ depth, /* Depth of image (bits) */
+ compression, /* Type of compression */
+ image_size, /* Size of image in bytes */
+ colors_used, /* Number of colors used */
+ colors_important, /* Number of important colors */
+ bpp, /* Bytes per pixel */
+ x, y, /* Looping vars */
+ color, /* Color of RLE pixel */
+ count, /* Number of times to repeat */
+ temp, /* Temporary color */
+ align; /* Alignment bytes */
+ ib_t bit, /* Bit in image */
+ byte; /* Byte in image */
+ ib_t *in, /* Input pixels */
+ *out, /* Output pixels */
+ *ptr; /* Pointer into pixels */
+ ib_t colormap[256][4]; /* Colormap */
+
+
+ (void)secondary;
+
+ /*
+ * Get the header...
+ */
+
+ getc(fp); /* Skip "BM" sync chars */
+ getc(fp);
+ read_dword(fp); /* Skip size */
+ read_word(fp); /* Skip reserved stuff */
+ read_word(fp);
+ offset = read_dword(fp);
+
+ fprintf(stderr, "DEBUG: offset = %d\n", offset);
+
+ if (offset < 0)
+ {
+ fprintf(stderr, "ERROR: Bad BMP offset %d\n", offset);
+ fclose(fp);
+ return (1);
+ }
+
+ /*
+ * Then the bitmap information...
+ */
+
+ info_size = read_dword(fp);
+ img->xsize = read_long(fp);
+ img->ysize = read_long(fp);
+ planes = read_word(fp);
+ depth = read_word(fp);
+ compression = read_dword(fp);
+ image_size = read_dword(fp);
+ img->xppi = read_long(fp) * 0.0254 + 0.5;
+ img->yppi = read_long(fp) * 0.0254 + 0.5;
+ colors_used = read_dword(fp);
+ colors_important = read_dword(fp);
+
+ if (img->xsize == 0 || img->xsize > IMAGE_MAX_WIDTH ||
+ img->ysize == 0 || img->ysize > IMAGE_MAX_HEIGHT ||
+ (depth != 1 && depth != 4 && depth != 8 && depth != 24))
+ {
+ fprintf(stderr, "ERROR: Bad BMP dimensions %ux%ux%d\n",
+ img->xsize, img->ysize, depth);
+ fclose(fp);
+ return (1);
+ }
+
+ if (colors_used < 0 || colors_used > 256)
+ {
+ fprintf(stderr, "ERROR: Bad BMP colormap size %d\n", colors_used);
+ fclose(fp);
+ return (1);
+ }
+
+ if (img->xppi == 0 || img->yppi == 0)
+ {
+ fprintf(stderr, "ERROR: Bad BMP resolution %dx%d PPI.\n",
+ img->xppi, img->yppi);
+ img->xppi = img->yppi = 128;
+ }
+
+ /*
+ * Make sure the resolution info is valid...
+ */
+
+ fprintf(stderr, "info_size = %d, xsize = %d, ysize = %d, planes = %d, depth = %d\n",
+ info_size, img->xsize, img->ysize, planes, depth);
+ fprintf(stderr, "compression = %d, image_size = %d, xppi = %d, yppi = %d\n",
+ compression, image_size, img->xppi, img->yppi);
+ fprintf(stderr, "colors_used = %d, colors_important = %d\n", colors_used,
+ colors_important);
+
+ if (info_size > 40)
+ for (info_size -= 40; info_size > 0; info_size --)
+ getc(fp);
+
+ /*
+ * Get colormap...
+ */
+
+ if (colors_used == 0 && depth <= 8)
+ colors_used = 1 << depth;
+
+ if (colors_used > 0)
+ fread(colormap, colors_used, 4, fp);
+
+ /*
+ * Setup image and buffers...
+ */
+
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+
+ ImageSetMaxTiles(img, 0);
+
+ in = malloc(img->xsize * 3);
+ bpp = ImageGetDepth(img);
+ out = malloc(img->xsize * bpp);
+
+ /*
+ * Read the image data...
+ */
+
+ color = 0;
+ count = 0;
+ align = 0;
+
+ for (y = img->ysize - 1; y >= 0; y --)
+ {
+ if (img->colorspace == IMAGE_RGB)
+ ptr = out;
+ else
+ ptr = in;
+
+ switch (depth)
+ {
+ case 1 : /* Bitmap */
+ for (x = img->xsize, bit = 128, byte = 0; x > 0; x --)
+ {
+ if (bit == 128)
+ byte = getc(fp);
+
+ if (byte & bit)
+ {
+ *ptr++ = colormap[1][2];
+ *ptr++ = colormap[1][1];
+ *ptr++ = colormap[1][0];
+ }
+ else
+ {
+ *ptr++ = colormap[0][2];
+ *ptr++ = colormap[0][1];
+ *ptr++ = colormap[0][0];
+ }
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ bit = 128;
+ }
+
+ /*
+ * Read remaining bytes to align to 32 bits...
+ */
+
+ for (temp = (img->xsize + 7) / 8; temp & 3; temp ++)
+ getc(fp);
+ break;
+
+ case 4 : /* 16-color */
+ for (x = img->xsize, bit = 0xf0, temp = 0; x > 0; x --)
+ {
+ /*
+ * Get a new count as needed...
+ */
+
+ if (compression != BI_RLE4 && count == 0)
+ {
+ count = 2;
+ color = -1;
+ }
+
+ if (count == 0)
+ {
+ while (align > 0)
+ {
+ align --;
+ getc(fp);
+ }
+
+ if ((count = getc(fp)) == 0)
+ {
+ if ((count = getc(fp)) == 0)
+ {
+ /*
+ * End of line...
+ */
+
+ x ++;
+ continue;
+ }
+ else if (count == 1)
+ {
+ /*
+ * End of image...
+ */
+
+ break;
+ }
+ else if (count == 2)
+ {
+ /*
+ * Delta...
+ */
+
+ count = getc(fp) * getc(fp) * img->xsize;
+ color = 0;
+ }
+ else
+ {
+ /*
+ * Absolute...
+ */
+
+ color = -1;
+ align = ((4 - (count & 3)) / 2) & 1;
+ }
+ }
+ else
+ color = getc(fp);
+ }
+
+ /*
+ * Get a new color as needed...
+ */
+
+ count --;
+
+ if (bit == 0xf0)
+ {
+ if (color < 0)
+ temp = getc(fp);
+ else
+ temp = color;
+
+ /*
+ * Copy the color value...
+ */
+
+ *ptr++ = colormap[temp >> 4][2];
+ *ptr++ = colormap[temp >> 4][1];
+ *ptr++ = colormap[temp >> 4][0];
+ bit = 0x0f;
+ }
+ else
+ {
+ /*
+ * Copy the color value...
+ */
+
+ *ptr++ = colormap[temp & 15][2];
+ *ptr++ = colormap[temp & 15][1];
+ *ptr++ = colormap[temp & 15][0];
+ bit = 0xf0;
+ }
+ }
+ break;
+
+ case 8 : /* 256-color */
+ for (x = img->xsize; x > 0; x --)
+ {
+ /*
+ * Get a new count as needed...
+ */
+
+ if (compression != BI_RLE8)
+ {
+ count = 1;
+ color = -1;
+ }
+
+ if (count == 0)
+ {
+ while (align > 0)
+ {
+ align --;
+ getc(fp);
+ }
+
+ if ((count = getc(fp)) == 0)
+ {
+ if ((count = getc(fp)) == 0)
+ {
+ /*
+ * End of line...
+ */
+
+ x ++;
+ continue;
+ }
+ else if (count == 1)
+ {
+ /*
+ * End of image...
+ */
+
+ break;
+ }
+ else if (count == 2)
+ {
+ /*
+ * Delta...
+ */
+
+ count = getc(fp) * getc(fp) * img->xsize;
+ color = 0;
+ }
+ else
+ {
+ /*
+ * Absolute...
+ */
+
+ color = -1;
+ align = (2 - (count & 1)) & 1;
+ }
+ }
+ else
+ color = getc(fp);
+ }
+
+ /*
+ * Get a new color as needed...
+ */
+
+ if (color < 0)
+ temp = getc(fp);
+ else
+ temp = color;
+
+ count --;
+
+ /*
+ * Copy the color value...
+ */
+
+ *ptr++ = colormap[temp][2];
+ *ptr++ = colormap[temp][1];
+ *ptr++ = colormap[temp][0];
+ }
+ break;
+
+ case 24 : /* 24-bit RGB */
+ for (x = img->xsize; x > 0; x --, ptr += 3)
+ {
+ ptr[2] = getc(fp);
+ ptr[1] = getc(fp);
+ ptr[0] = getc(fp);
+ }
+
+ /*
+ * Read remaining bytes to align to 32 bits...
+ */
+
+ for (temp = img->xsize * 3; temp & 3; temp ++)
+ getc(fp);
+ break;
+ }
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(out, img->xsize, saturation, hue);
+ }
+ else
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+
+ fclose(fp);
+ free(in);
+ free(out);
+
+ return (0);
+}
+
+
+/*
+ * 'read_word()' - Read a 16-bit unsigned integer.
+ */
+
+static unsigned short /* O - 16-bit unsigned integer */
+read_word(FILE *fp) /* I - File to read from */
+{
+ unsigned char b0, b1; /* Bytes from file */
+
+ b0 = getc(fp);
+ b1 = getc(fp);
+
+ return ((b1 << 8) | b0);
+}
+
+
+/*
+ * 'read_dword()' - Read a 32-bit unsigned integer.
+ */
+
+static unsigned int /* O - 32-bit unsigned integer */
+read_dword(FILE *fp) /* I - File to read from */
+{
+ unsigned char b0, b1, b2, b3; /* Bytes from file */
+
+ b0 = getc(fp);
+ b1 = getc(fp);
+ b2 = getc(fp);
+ b3 = getc(fp);
+
+ return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
+}
+
+
+/*
+ * 'read_long()' - Read a 32-bit signed integer.
+ */
+
+static int /* O - 32-bit signed integer */
+read_long(FILE *fp) /* I - File to read from */
+{
+ unsigned char b0, b1, b2, b3; /* Bytes from file */
+
+ b0 = getc(fp);
+ b1 = getc(fp);
+ b2 = getc(fp);
+ b3 = getc(fp);
+
+ return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-colorspace.c b/filter/image-colorspace.c
new file mode 100644
index 000000000..68b8b2b3f
--- /dev/null
+++ b/filter/image-colorspace.c
@@ -0,0 +1,1544 @@
+/*
+ * "$Id$"
+ *
+ * Colorspace conversions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageSetProfile() - Set the device color profile.
+ * ImageWhiteToWhite() - Convert luminance colors to device-dependent
+ * ImageWhiteToRGB() - Convert luminance data to RGB.
+ * ImageWhiteToBlack() - Convert luminance colors to black.
+ * ImageWhiteToCMY() - Convert luminance colors to CMY.
+ * ImageWhiteToCMYK() - Convert luminance colors to CMYK.
+ * ImageRGBToBlack() - Convert RGB data to black.
+ * ImageRGBToCMY() - Convert RGB colors to CMY.
+ * ImageRGBToCMYK() - Convert RGB colors to CMYK.
+ * ImageRGBToWhite() - Convert RGB colors to luminance.
+ * ImageRGBToRGB() - Convert RGB colors to device-dependent RGB.
+ * ImageCMYKToBlack() - Convert CMYK data to black.
+ * ImageCMYKToCMY() - Convert CMYK colors to CMY.
+ * ImageCMYKToCMYK() - Convert CMYK colors to CMYK.
+ * ImageCMYKToWhite() - Convert CMYK colors to luminance.
+ * ImageCMYKToRGB() - Convert CMYK colors to device-dependent RGB.
+ * ImageLut() - Adjust all pixel values with the given LUT.
+ * ImageRGBAdjust() - Adjust the hue and saturation of the given RGB
+ * colors.
+ * huerotate() - Rotate the hue, maintaining luminance.
+ * ident() - Make an identity matrix.
+ * mult() - Multiply two matrices.
+ * saturate() - Make a saturation matrix.
+ * xform() - Transform a 3D point using a matrix...
+ * xrotate() - Rotate about the x (red) axis...
+ * yrotate() - Rotate about the y (green) axis...
+ * zrotate() - Rotate about the z (blue) axis...
+ * zshear() - Shear z using x and y...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+#include <math.h>
+
+
+/*
+ * Define some math constants that are required...
+ */
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif /* !M_PI */
+
+#ifndef M_SQRT2
+# define M_SQRT2 1.41421356237309504880
+#endif /* !M_SQRT2 */
+
+#ifndef M_SQRT1_2
+# define M_SQRT1_2 0.70710678118654752440
+#endif /* !M_SQRT1_2 */
+
+
+/*
+ * Lookup table structure...
+ */
+
+typedef int cups_clut_t[3][256];
+
+
+/*
+ * Local globals...
+ */
+
+static int ImageHaveProfile = 0;
+ /* Do we have a color profile? */
+static int *ImageDensity; /* Ink/marker density LUT */
+static cups_clut_t *ImageMatrix; /* Color transform matrix LUT */
+static cups_cspace_t ImageColorSpace = CUPS_CSPACE_RGB;
+ /* Destination colorspace */
+
+
+/*
+ * Local functions...
+ */
+
+static float cielab(float x, float xn);
+static void rgb_to_xyz(ib_t *val);
+static void rgb_to_lab(ib_t *val);
+
+static void huerotate(float [3][3], float);
+static void ident(float [3][3]);
+static void mult(float [3][3], float [3][3], float [3][3]);
+static void saturate(float [3][3], float);
+static void xform(float [3][3], float, float, float, float *, float *, float *);
+static void xrotate(float [3][3], float, float);
+static void yrotate(float [3][3], float, float);
+static void zrotate(float [3][3], float, float);
+static void zshear(float [3][3], float, float);
+
+
+/*
+ * 'ImageSetColorSpace()' - Set the destination colorspace.
+ */
+
+void
+ImageSetColorSpace(cups_cspace_t cs) /* I - Destination colorspace */
+{
+ /*
+ * Set the destination colorspace...
+ */
+
+ ImageColorSpace = cs;
+
+ /*
+ * Don't use color profiles in colorimetric colorspaces...
+ */
+
+ if (cs >= CUPS_CSPACE_CIEXYZ)
+ ImageHaveProfile = 0;
+}
+
+
+/*
+ * 'ImageSetProfile()' - Set the device color profile.
+ */
+
+void
+ImageSetProfile(float d, /* I - Ink/marker density */
+ float g, /* I - Ink/marker gamma */
+ float matrix[3][3]) /* I - Color transform matrix */
+{
+ int i, j, k; /* Looping vars */
+ float m; /* Current matrix value */
+ int *im; /* Pointer into ImageMatrix */
+
+
+ /*
+ * Allocate memory for the profile data...
+ */
+
+ if (ImageMatrix == NULL)
+ ImageMatrix = calloc(3, sizeof(cups_clut_t));
+
+ if (ImageMatrix == NULL)
+ return;
+
+ if (ImageDensity == NULL)
+ ImageDensity = calloc(256, sizeof(int));
+
+ if (ImageDensity == NULL)
+ return;
+
+ /*
+ * Populate the profile lookup tables...
+ */
+
+ ImageHaveProfile = 1;
+
+ for (i = 0, im = ImageMatrix[0][0]; i < 3; i ++)
+ for (j = 0; j < 3; j ++)
+ for (k = 0, m = matrix[i][j]; k < 256; k ++)
+ *im++ = (int)(k * m + 0.5);
+
+ for (k = 0, im = ImageDensity; k < 256; k ++)
+ *im++ = 255.0 * d * pow((float)k / 255.0, g) + 0.5;
+}
+
+
+/*
+ * 'ImageWhiteToWhite()' - Convert luminance colors to device-dependent
+ * luminance.
+ */
+
+void
+ImageWhiteToWhite(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ *out++ = 255 - ImageDensity[255 - *in++];
+ count --;
+ }
+ else if (in != out)
+ memcpy(out, in, count);
+}
+
+
+/*
+ * 'ImageWhiteToRGB()' - Convert luminance data to RGB.
+ */
+
+void
+ImageWhiteToRGB(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ {
+ while (count > 0)
+ {
+ out[0] = 255 - ImageDensity[255 - *in++];
+ out[1] = out[0];
+ out[2] = out[0];
+ out += 3;
+ count --;
+ }
+ }
+ else
+ {
+ while (count > 0)
+ {
+ *out++ = *in;
+ *out++ = *in;
+ *out++ = *in++;
+
+ if (ImageColorSpace >= CUPS_CSPACE_CIELab)
+ rgb_to_lab(out - 3);
+ else if (ImageColorSpace == CUPS_CSPACE_CIEXYZ)
+ rgb_to_xyz(out - 3);
+
+ count --;
+ }
+ }
+}
+
+
+/*
+ * 'ImageWhiteToBlack()' - Convert luminance colors to black.
+ */
+
+void
+ImageWhiteToBlack(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ *out++ = ImageDensity[255 - *in++];
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ *out++ = 255 - *in++;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageWhiteToCMY()' - Convert luminance colors to CMY.
+ */
+
+void
+ImageWhiteToCMY(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ out[0] = ImageDensity[255 - *in++];
+ out[1] = out[0];
+ out[2] = out[0];
+ out += 3;
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ *out++ = 255 - *in;
+ *out++ = 255 - *in;
+ *out++ = 255 - *in++;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageWhiteToCMYK()' - Convert luminance colors to CMYK.
+ */
+
+void
+ImageWhiteToCMYK(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = ImageDensity[255 - *in++];
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = 0;
+ *out++ = 255 - *in++;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageRGBToBlack()' - Convert RGB data to black.
+ */
+
+void
+ImageRGBToBlack(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ *out++ = ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100];
+ in += 3;
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ *out++ = 255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100;
+ in += 3;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageRGBToCMY()' - Convert RGB colors to CMY.
+ */
+
+void
+ImageRGBToCMY(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ int c, m, y, k; /* CMYK values */
+ int cc, cm, cy; /* Calibrated CMY values */
+
+
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ c = 255 - *in++;
+ m = 255 - *in++;
+ y = 255 - *in++;
+ k = min(c, min(m, y));
+ c -= k;
+ m -= k;
+ y -= k;
+
+ cc = ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y] + k;
+ cm = ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y] + k;
+ cy = ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y] + k;
+
+ if (cc < 0)
+ *out++ = 0;
+ else if (cc > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cc];
+
+ if (cm < 0)
+ *out++ = 0;
+ else if (cm > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cm];
+
+ if (cy < 0)
+ *out++ = 0;
+ else if (cy > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cy];
+
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ c = 255 - in[0];
+ m = 255 - in[1];
+ y = 255 - in[2];
+ k = min(c, min(m, y));
+
+ *out++ = (255 - in[1] / 4) * (c - k) / 255 + k;
+ *out++ = (255 - in[2] / 4) * (m - k) / 255 + k;
+ *out++ = (255 - in[0] / 4) * (y - k) / 255 + k;
+ in += 3;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageRGBToCMYK()' - Convert RGB colors to CMYK.
+ */
+
+void
+ImageRGBToCMYK(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count)/* I - Number of pixels */
+{
+ int c, m, y, k, /* CMYK values */
+ km; /* Maximum K value */
+ int cc, cm, cy; /* Calibrated CMY values */
+
+
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ c = 255 - *in++;
+ m = 255 - *in++;
+ y = 255 - *in++;
+ k = min(c, min(m, y));
+
+ if ((km = max(c, max(m, y))) > k)
+ k = k * k * k / (km * km);
+
+ c -= k;
+ m -= k;
+ y -= k;
+
+ cc = (ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y]);
+ cm = (ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y]);
+ cy = (ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y]);
+
+ if (cc < 0)
+ *out++ = 0;
+ else if (cc > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cc];
+
+ if (cm < 0)
+ *out++ = 0;
+ else if (cm > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cm];
+
+ if (cy < 0)
+ *out++ = 0;
+ else if (cy > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cy];
+
+ *out++ = ImageDensity[k];
+
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ c = 255 - *in++;
+ m = 255 - *in++;
+ y = 255 - *in++;
+ k = min(c, min(m, y));
+
+ if ((km = max(c, max(m, y))) > k)
+ k = k * k * k / (km * km);
+
+ c -= k;
+ m -= k;
+ y -= k;
+
+ *out++ = c;
+ *out++ = m;
+ *out++ = y;
+ *out++ = k;
+
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageRGBToWhite()' - Convert RGB colors to luminance.
+ */
+
+void
+ImageRGBToWhite(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ if (ImageHaveProfile)
+ {
+ while (count > 0)
+ {
+ *out++ = 255 - ImageDensity[255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100];
+ in += 3;
+ count --;
+ }
+ }
+ else
+ {
+ while (count > 0)
+ {
+ *out++ = (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100;
+ in += 3;
+ count --;
+ }
+ }
+}
+
+
+/*
+ * 'ImageRGBToRGB()' - Convert RGB colors to device-dependent RGB.
+ */
+
+void
+ImageRGBToRGB(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ int c, m, y, k; /* CMYK values */
+ int cr, cg, cb; /* Calibrated RGB values */
+
+
+ if (ImageHaveProfile)
+ {
+ while (count > 0)
+ {
+ c = 255 - *in++;
+ m = 255 - *in++;
+ y = 255 - *in++;
+ k = min(c, min(m, y));
+ c -= k;
+ m -= k;
+ y -= k;
+
+ cr = ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y] + k;
+ cg = ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y] + k;
+ cb = ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y] + k;
+
+ if (cr < 0)
+ *out++ = 255;
+ else if (cr > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cr];
+
+ if (cg < 0)
+ *out++ = 255;
+ else if (cg > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cg];
+
+ if (cb < 0)
+ *out++ = 255;
+ else if (cb > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cb];
+
+ count --;
+ }
+ }
+ else
+ {
+ if (in != out)
+ memcpy(out, in, count * 3);
+
+ if (ImageColorSpace >= CUPS_CSPACE_CIEXYZ)
+ {
+ while (count > 0)
+ {
+ if (ImageColorSpace >= CUPS_CSPACE_CIELab)
+ rgb_to_lab(out);
+ else
+ rgb_to_xyz(out);
+
+ out += 3;
+ count --;
+ }
+ }
+ }
+}
+
+
+/*
+ * 'ImageCMYKToBlack()' - Convert CMYK data to black.
+ */
+
+void
+ImageCMYKToBlack(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ int k; /* Black value */
+
+
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ k = (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100 + in[3];
+
+ if (k < 255)
+ *out++ = ImageDensity[k];
+ else
+ *out++ = ImageDensity[255];
+
+ in += 4;
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ k = (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100 + in[3];
+
+ if (k < 255)
+ *out++ = k;
+ else
+ *out++ = 255;
+
+ in += 4;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageCMYKToCMY()' - Convert CMYK colors to CMY.
+ */
+
+void
+ImageCMYKToCMY(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count)/* I - Number of pixels */
+{
+ int c, m, y, k; /* CMYK values */
+ int cc, cm, cy; /* Calibrated CMY values */
+
+
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ c = *in++;
+ m = *in++;
+ y = *in++;
+ k = *in++;
+
+ cc = ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y] + k;
+ cm = ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y] + k;
+ cy = ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y] + k;
+
+ if (cc < 0)
+ *out++ = 0;
+ else if (cc > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cc];
+
+ if (cm < 0)
+ *out++ = 0;
+ else if (cm > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cm];
+
+ if (cy < 0)
+ *out++ = 0;
+ else if (cy > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cy];
+
+ count --;
+ }
+ else
+ while (count > 0)
+ {
+ c = *in++;
+ m = *in++;
+ y = *in++;
+ k = *in++;
+
+ c += k;
+ m += k;
+ y += k;
+
+ if (c < 255)
+ *out++ = c;
+ else
+ *out++ = 255;
+
+ if (m < 255)
+ *out++ = y;
+ else
+ *out++ = 255;
+
+ if (y < 255)
+ *out++ = y;
+ else
+ *out++ = 255;
+
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageCMYKToCMYK()' - Convert CMYK colors to CMYK.
+ */
+
+void
+ImageCMYKToCMYK(const ib_t *in, /* I - Input pixels */
+ ib_t *out,/* I - Output pixels */
+ int count)/* I - Number of pixels */
+{
+ int c, m, y, k; /* CMYK values */
+ int cc, cm, cy; /* Calibrated CMY values */
+
+
+ if (ImageHaveProfile)
+ while (count > 0)
+ {
+ c = *in++;
+ m = *in++;
+ y = *in++;
+ k = *in++;
+
+ cc = (ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y]);
+ cm = (ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y]);
+ cy = (ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y]);
+
+ if (cc < 0)
+ *out++ = 0;
+ else if (cc > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cc];
+
+ if (cm < 0)
+ *out++ = 0;
+ else if (cm > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cm];
+
+ if (cy < 0)
+ *out++ = 0;
+ else if (cy > 255)
+ *out++ = ImageDensity[255];
+ else
+ *out++ = ImageDensity[cy];
+
+ *out++ = ImageDensity[k];
+
+ count --;
+ }
+ else if (in != out)
+ {
+ while (count > 0)
+ {
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = *in++;
+ *out++ = *in++;
+
+ count --;
+ }
+ }
+}
+
+
+/*
+ * 'ImageCMYKToWhite()' - Convert CMYK colors to luminance.
+ */
+
+void
+ImageCMYKToWhite(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count) /* I - Number of pixels */
+{
+ int w; /* White value */
+
+
+ if (ImageHaveProfile)
+ {
+ while (count > 0)
+ {
+ w = 255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100 - in[3];
+
+ if (w > 0)
+ *out++ = ImageDensity[w];
+ else
+ *out++ = ImageDensity[0];
+
+ in += 4;
+ count --;
+ }
+ }
+ else
+ {
+ while (count > 0)
+ {
+ w = 255 - (31 * in[0] + 61 * in[1] + 8 * in[2]) / 100 - in[3];
+
+ if (w > 0)
+ *out++ = w;
+ else
+ *out++ = 0;
+
+ in += 4;
+ count --;
+ }
+ }
+}
+
+
+/*
+ * 'ImageCMYKToRGB()' - Convert CMYK colors to device-dependent RGB.
+ */
+
+void
+ImageCMYKToRGB(const ib_t *in, /* I - Input pixels */
+ ib_t *out, /* I - Output pixels */
+ int count)/* I - Number of pixels */
+{
+ int c, m, y, k; /* CMYK values */
+ int cr, cg, cb; /* Calibrated RGB values */
+
+
+ if (ImageHaveProfile)
+ {
+ while (count > 0)
+ {
+ c = *in++;
+ m = *in++;
+ y = *in++;
+ k = *in++;
+
+ cr = ImageMatrix[0][0][c] +
+ ImageMatrix[0][1][m] +
+ ImageMatrix[0][2][y] + k;
+ cg = ImageMatrix[1][0][c] +
+ ImageMatrix[1][1][m] +
+ ImageMatrix[1][2][y] + k;
+ cb = ImageMatrix[2][0][c] +
+ ImageMatrix[2][1][m] +
+ ImageMatrix[2][2][y] + k;
+
+ if (cr < 0)
+ *out++ = 255;
+ else if (cr > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cr];
+
+ if (cg < 0)
+ *out++ = 255;
+ else if (cg > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cg];
+
+ if (cb < 0)
+ *out++ = 255;
+ else if (cb > 255)
+ *out++ = 255 - ImageDensity[255];
+ else
+ *out++ = 255 - ImageDensity[cb];
+
+ count --;
+ }
+ }
+ else
+ {
+ while (count > 0)
+ {
+ c = 255 - *in++;
+ m = 255 - *in++;
+ y = 255 - *in++;
+ k = *in++;
+
+ c -= k;
+ m -= k;
+ y -= k;
+
+ if (c > 0)
+ *out++ = c;
+ else
+ *out++ = 0;
+
+ if (m > 0)
+ *out++ = m;
+ else
+ *out++ = 0;
+
+ if (y > 0)
+ *out++ = y;
+ else
+ *out++ = 0;
+
+ if (ImageColorSpace >= CUPS_CSPACE_CIELab)
+ rgb_to_lab(out - 3);
+ else if (ImageColorSpace == CUPS_CSPACE_CIEXYZ)
+ rgb_to_xyz(out - 3);
+
+ count --;
+ }
+ }
+}
+
+
+/*
+ * 'ImageLut()' - Adjust all pixel values with the given LUT.
+ */
+
+void
+ImageLut(ib_t *pixels, /* IO - Input/output pixels */
+ int count, /* I - Number of pixels/bytes to adjust */
+ const ib_t *lut) /* I - Lookup table */
+{
+ while (count > 0)
+ {
+ *pixels = lut[*pixels];
+ pixels ++;
+ count --;
+ }
+}
+
+
+/*
+ * 'ImageRGBAdjust()' - Adjust the hue and saturation of the given RGB colors.
+ */
+
+void
+ImageRGBAdjust(ib_t *pixels, /* IO - Input/output pixels */
+ int count, /* I - Number of pixels to adjust */
+ int saturation, /* I - Color saturation (%) */
+ int hue) /* I - Color hue (degrees) */
+{
+ int i, j, k; /* Looping vars */
+ float mat[3][3]; /* Color adjustment matrix */
+ static int last_sat = 100, /* Last saturation used */
+ last_hue = 0; /* Last hue used */
+ static cups_clut_t *lut = NULL; /* Lookup table for matrix */
+
+
+ if (saturation != last_sat ||
+ hue != last_hue)
+ {
+ /*
+ * Build the color adjustment matrix...
+ */
+
+ ident(mat);
+ saturate(mat, saturation * 0.01);
+ huerotate(mat, (float)hue);
+
+ /*
+ * Allocate memory for the lookup table...
+ */
+
+ if (lut == NULL)
+ lut = calloc(3, sizeof(cups_clut_t));
+
+ if (lut == NULL)
+ return;
+
+ /*
+ * Convert the matrix into a 3x3 array of lookup tables...
+ */
+
+ for (i = 0; i < 3; i ++)
+ for (j = 0; j < 3; j ++)
+ for (k = 0; k < 256; k ++)
+ lut[i][j][k] = mat[i][j] * k + 0.5;
+
+ /*
+ * Save the saturation and hue to compare later...
+ */
+
+ last_sat = saturation;
+ last_hue = hue;
+ }
+
+ /*
+ * Adjust each pixel in the given buffer.
+ */
+
+ while (count > 0)
+ {
+ i = lut[0][0][pixels[0]] +
+ lut[1][0][pixels[1]] +
+ lut[2][0][pixels[2]];
+ if (i < 0)
+ pixels[0] = 0;
+ else if (i > 255)
+ pixels[0] = 255;
+ else
+ pixels[0] = i;
+
+ i = lut[0][1][pixels[0]] +
+ lut[1][1][pixels[1]] +
+ lut[2][1][pixels[2]];
+ if (i < 0)
+ pixels[1] = 0;
+ else if (i > 255)
+ pixels[1] = 255;
+ else
+ pixels[1] = i;
+
+ i = lut[0][2][pixels[0]] +
+ lut[1][2][pixels[1]] +
+ lut[2][2][pixels[2]];
+ if (i < 0)
+ pixels[2] = 0;
+ else if (i > 255)
+ pixels[2] = 255;
+ else
+ pixels[2] = i;
+
+ count --;
+ pixels += 3;
+ }
+}
+
+
+/*
+ * Convert from RGB to CIE XYZ or Lab...
+ */
+
+#define D65_X (0.412453 + 0.357580 + 0.180423)
+#define D65_Y (0.212671 + 0.715160 + 0.072169)
+#define D65_Z (0.019334 + 0.119193 + 0.950227)
+
+
+/*
+ * 'cielab()' - Map CIE Lab transformation...
+ */
+
+static float /* O - Adjusted color value */
+cielab(float x, /* I - Raw color value */
+ float xn) /* I - Whitepoint color value */
+{
+ float x_xn; /* Fraction of whitepoint */
+
+
+ x_xn = x / xn;
+
+ if (x_xn > 0.008856)
+ return (cbrt(x_xn));
+ else
+ return (7.787 * x_xn + 16.0 / 116.0);
+}
+
+
+/*
+ * 'rgb_to_xyz()' - Convert an RGB color to CIE XYZ.
+ */
+
+static void
+rgb_to_xyz(ib_t *val) /* IO - Color value */
+{
+ float r, /* Red value */
+ g, /* Green value */
+ b, /* Blue value */
+ ciex, /* CIE X value */
+ ciey, /* CIE Y value */
+ ciez; /* CIE Z value */
+
+
+ /*
+ * Convert sRGB to linear RGB...
+ */
+
+ r = pow(val[0] / 255.0, 0.58823529412);
+ g = pow(val[1] / 255.0, 0.58823529412);
+ b = pow(val[2] / 255.0, 0.58823529412);
+
+ /*
+ * Convert to CIE XYZ...
+ */
+
+ ciex = 0.412453 * r + 0.357580 * g + 0.180423 * b;
+ ciey = 0.212671 * r + 0.715160 * g + 0.072169 * b;
+ ciez = 0.019334 * r + 0.119193 * g + 0.950227 * b;
+
+ /*
+ * Output 8-bit values...
+ */
+
+ if (ciex < 0.0)
+ val[0] = 0;
+ else if (ciex < 255.0)
+ val[0] = (int)ciex;
+ else
+ val[0] = 255;
+
+ if (ciey < 0.0)
+ val[1] = 0;
+ else if (ciey < 255.0)
+ val[1] = (int)ciey;
+ else
+ val[1] = 255;
+
+ if (ciez < 0.0)
+ val[2] = 0;
+ else if (ciez < 255.0)
+ val[2] = (int)ciez;
+ else
+ val[2] = 255;
+}
+
+
+/*
+ * 'rgb_to_lab()' - Convert an RGB color to CIE Lab.
+ */
+
+static void
+rgb_to_lab(ib_t *val) /* IO - Color value */
+{
+ float r, /* Red value */
+ g, /* Green value */
+ b, /* Blue value */
+ ciex, /* CIE X value */
+ ciey, /* CIE Y value */
+ ciez, /* CIE Z value */
+ ciey_yn, /* Normalized luminance */
+ ciel, /* CIE L value */
+ ciea, /* CIE a value */
+ cieb; /* CIE b value */
+
+
+ /*
+ * Convert sRGB to linear RGB...
+ */
+
+ r = pow(val[0] / 255.0, 0.58823529412);
+ g = pow(val[1] / 255.0, 0.58823529412);
+ b = pow(val[2] / 255.0, 0.58823529412);
+
+ /*
+ * Convert to CIE XYZ...
+ */
+
+ ciex = 0.412453 * r + 0.357580 * g + 0.180423 * b;
+ ciey = 0.212671 * r + 0.715160 * g + 0.072169 * b;
+ ciez = 0.019334 * r + 0.119193 * g + 0.950227 * b;
+
+ /*
+ * Normalize and convert to CIE Lab...
+ */
+
+ ciey_yn = ciey / D65_Y;
+
+ if (ciey_yn > 0.008856)
+ ciel = 116 * cbrt(ciey_yn) - 16;
+ else
+ ciel = 903.3 * ciey_yn;
+
+ ciel = ciel;
+ ciea = 500 * (cielab(ciex, D65_X) - cielab(ciey, D65_Y));
+ cieb = 200 * (cielab(ciey, D65_Y) - cielab(ciez, D65_Z));
+
+ /*
+ * Scale the L value and bias the a and b values by 128 so that all
+ * numbers are from 0 to 255.
+ */
+
+ ciel *= 2.55;
+ ciea += 128;
+ cieb += 128;
+
+ /*
+ * Output 8-bit values...
+ */
+
+ if (ciel < 0.0)
+ val[0] = 0;
+ else if (ciel < 255.0)
+ val[0] = (int)ciel;
+ else
+ val[0] = 255;
+
+ if (ciea < 0.0)
+ val[1] = 128;
+ else if (ciea < 255.0)
+ val[1] = (int)ciea;
+ else
+ val[1] = 255;
+
+ if (cieb < 0.0)
+ val[2] = 128;
+ else if (cieb < 255.0)
+ val[2] = (int)cieb;
+ else
+ val[2] = 255;
+}
+
+
+/*
+ * The color saturation/hue matrix stuff is provided thanks to Mr. Paul
+ * Haeberli at "http://www.sgi.com/grafica/matrix/index.html".
+ */
+
+/*
+ * 'huerotate()' - Rotate the hue, maintaining luminance.
+ */
+
+static void
+huerotate(float mat[3][3], /* I - Matrix to append to */
+ float rot) /* I - Hue rotation in degrees */
+{
+ float hmat[3][3]; /* Hue matrix */
+ float lx, ly, lz; /* Luminance vector */
+ float xrs, xrc; /* X rotation sine/cosine */
+ float yrs, yrc; /* Y rotation sine/cosine */
+ float zrs, zrc; /* Z rotation sine/cosine */
+ float zsx, zsy; /* Z shear x/y */
+
+
+ /*
+ * Load the identity matrix...
+ */
+
+ ident(hmat);
+
+ /*
+ * Rotate the grey vector into positive Z...
+ */
+
+ xrs = M_SQRT1_2;
+ xrc = M_SQRT1_2;
+ xrotate(hmat,xrs,xrc);
+
+ yrs = -1.0 / sqrt(3.0);
+ yrc = -M_SQRT2 * yrs;
+ yrotate(hmat,yrs,yrc);
+
+ /*
+ * Shear the space to make the luminance plane horizontal...
+ */
+
+ xform(hmat, 0.3086, 0.6094, 0.0820, &lx, &ly, &lz);
+ zsx = lx / lz;
+ zsy = ly / lz;
+ zshear(hmat, zsx, zsy);
+
+ /*
+ * Rotate the hue...
+ */
+
+ zrs = sin(rot * M_PI / 180.0);
+ zrc = cos(rot * M_PI / 180.0);
+
+ zrotate(hmat, zrs, zrc);
+
+ /*
+ * Unshear the space to put the luminance plane back...
+ */
+
+ zshear(hmat, -zsx, -zsy);
+
+ /*
+ * Rotate the grey vector back into place...
+ */
+
+ yrotate(hmat, -yrs, yrc);
+ xrotate(hmat, -xrs, xrc);
+
+ /*
+ * Append it to the current matrix...
+ */
+
+ mult(hmat, mat, mat);
+}
+
+
+/*
+ * 'ident()' - Make an identity matrix.
+ */
+
+static void
+ident(float mat[3][3]) /* I - Matrix to identify */
+{
+ mat[0][0] = 1.0;
+ mat[0][1] = 0.0;
+ mat[0][2] = 0.0;
+ mat[1][0] = 0.0;
+ mat[1][1] = 1.0;
+ mat[1][2] = 0.0;
+ mat[2][0] = 0.0;
+ mat[2][1] = 0.0;
+ mat[2][2] = 1.0;
+}
+
+
+/*
+ * 'mult()' - Multiply two matrices.
+ */
+
+static void
+mult(float a[3][3], /* I - First matrix */
+ float b[3][3], /* I - Second matrix */
+ float c[3][3]) /* I - Destination matrix */
+{
+ int x, y; /* Looping vars */
+ float temp[3][3]; /* Temporary matrix */
+
+
+ /*
+ * Multiply a and b, putting the result in temp...
+ */
+
+ for (y = 0; y < 3; y ++)
+ for (x = 0; x < 3; x ++)
+ temp[y][x] = b[y][0] * a[0][x] +
+ b[y][1] * a[1][x] +
+ b[y][2] * a[2][x];
+
+ /*
+ * Copy temp to c (that way c can be a pointer to a or b).
+ */
+
+ memcpy(c, temp, sizeof(temp));
+}
+
+
+/*
+ * 'saturate()' - Make a saturation matrix.
+ */
+
+static void
+saturate(float mat[3][3], /* I - Matrix to append to */
+ float sat) /* I - Desired color saturation */
+{
+ float smat[3][3]; /* Saturation matrix */
+
+
+ smat[0][0] = (1.0 - sat) * 0.3086 + sat;
+ smat[0][1] = (1.0 - sat) * 0.3086;
+ smat[0][2] = (1.0 - sat) * 0.3086;
+ smat[1][0] = (1.0 - sat) * 0.6094;
+ smat[1][1] = (1.0 - sat) * 0.6094 + sat;
+ smat[1][2] = (1.0 - sat) * 0.6094;
+ smat[2][0] = (1.0 - sat) * 0.0820;
+ smat[2][1] = (1.0 - sat) * 0.0820;
+ smat[2][2] = (1.0 - sat) * 0.0820 + sat;
+
+ mult(smat, mat, mat);
+}
+
+
+/*
+ * 'xform()' - Transform a 3D point using a matrix...
+ */
+
+static void
+xform(float mat[3][3], /* I - Matrix */
+ float x, /* I - Input X coordinate */
+ float y, /* I - Input Y coordinate */
+ float z, /* I - Input Z coordinate */
+ float *tx, /* O - Output X coordinate */
+ float *ty, /* O - Output Y coordinate */
+ float *tz) /* O - Output Z coordinate */
+{
+ *tx = x * mat[0][0] + y * mat[1][0] + z * mat[2][0];
+ *ty = x * mat[0][1] + y * mat[1][1] + z * mat[2][1];
+ *tz = x * mat[0][2] + y * mat[1][2] + z * mat[2][2];
+}
+
+
+/*
+ * 'xrotate()' - Rotate about the x (red) axis...
+ */
+
+static void
+xrotate(float mat[3][3], /* I - Matrix */
+ float rs, /* I - Rotation angle sine */
+ float rc) /* I - Rotation angle cosine */
+{
+ float rmat[3][3]; /* I - Rotation matrix */
+
+
+ rmat[0][0] = 1.0;
+ rmat[0][1] = 0.0;
+ rmat[0][2] = 0.0;
+
+ rmat[1][0] = 0.0;
+ rmat[1][1] = rc;
+ rmat[1][2] = rs;
+
+ rmat[2][0] = 0.0;
+ rmat[2][1] = -rs;
+ rmat[2][2] = rc;
+
+ mult(rmat, mat, mat);
+}
+
+
+/*
+ * 'yrotate()' - Rotate about the y (green) axis...
+ */
+
+static void
+yrotate(float mat[3][3], /* I - Matrix */
+ float rs, /* I - Rotation angle sine */
+ float rc) /* I - Rotation angle cosine */
+{
+ float rmat[3][3]; /* I - Rotation matrix */
+
+
+ rmat[0][0] = rc;
+ rmat[0][1] = 0.0;
+ rmat[0][2] = -rs;
+
+ rmat[1][0] = 0.0;
+ rmat[1][1] = 1.0;
+ rmat[1][2] = 0.0;
+
+ rmat[2][0] = rs;
+ rmat[2][1] = 0.0;
+ rmat[2][2] = rc;
+
+ mult(rmat,mat,mat);
+}
+
+
+/*
+ * 'zrotate()' - Rotate about the z (blue) axis...
+ */
+
+static void
+zrotate(float mat[3][3], /* I - Matrix */
+ float rs, /* I - Rotation angle sine */
+ float rc) /* I - Rotation angle cosine */
+{
+ float rmat[3][3]; /* I - Rotation matrix */
+
+
+ rmat[0][0] = rc;
+ rmat[0][1] = rs;
+ rmat[0][2] = 0.0;
+
+ rmat[1][0] = -rs;
+ rmat[1][1] = rc;
+ rmat[1][2] = 0.0;
+
+ rmat[2][0] = 0.0;
+ rmat[2][1] = 0.0;
+ rmat[2][2] = 1.0;
+
+ mult(rmat,mat,mat);
+}
+
+
+/*
+ * 'zshear()' - Shear z using x and y...
+ */
+
+static void
+zshear(float mat[3][3], /* I - Matrix */
+ float dx, /* I - X shear */
+ float dy) /* I - Y shear */
+{
+ float smat[3][3]; /* Shear matrix */
+
+
+ smat[0][0] = 1.0;
+ smat[0][1] = 0.0;
+ smat[0][2] = dx;
+
+ smat[1][0] = 0.0;
+ smat[1][1] = 1.0;
+ smat[1][2] = dy;
+
+ smat[2][0] = 0.0;
+ smat[2][1] = 0.0;
+ smat[2][2] = 1.0;
+
+ mult(smat, mat, mat);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-gif.c b/filter/image-gif.c
new file mode 100644
index 000000000..84482909b
--- /dev/null
+++ b/filter/image-gif.c
@@ -0,0 +1,694 @@
+/*
+ * "$Id$"
+ *
+ * GIF image routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadGIF() - Read a GIF image file.
+ * gif_read_cmap() - Read the colormap from a GIF file...
+ * gif_get_block() - Read a GIF data block...
+ * gif_get_code() - Get a LZW code from the file...
+ * gif_read_lzw() - Read a byte from the LZW stream...
+ * gif_read_image() - Read a GIF image stream...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * GIF definitions...
+ */
+
+#define GIF_INTERLACE 0x40
+#define GIF_COLORMAP 0x80
+
+typedef ib_t gif_cmap_t[256][4];
+typedef short gif_table_t[4096];
+
+
+/*
+ * Local globals...
+ */
+
+static int gif_eof = 0; /* Did we hit EOF? */
+
+
+/*
+ * Local functions...
+ */
+
+static int gif_read_cmap(FILE *fp, int ncolors, gif_cmap_t cmap,
+ int *gray);
+static int gif_get_block(FILE *fp, unsigned char *buffer);
+static int gif_get_code (FILE *fp, int code_size, int first_time);
+static int gif_read_lzw(FILE *fp, int first_time, int input_code_size);
+static int gif_read_image(FILE *fp, image_t *img, gif_cmap_t cmap,
+ int interlace);
+
+
+/*
+ * 'ImageReadGIF()' - Read a GIF image file.
+ */
+
+int /* O - Read status */
+ImageReadGIF(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ unsigned char buf[1024]; /* Input buffer */
+ gif_cmap_t cmap; /* Colormap */
+ int i, /* Looping var */
+ bpp, /* Bytes per pixel */
+ gray, /* Grayscale image? */
+ ncolors, /* Bits per pixel */
+ transparent; /* Transparent color index */
+
+
+ /*
+ * GIF files are either grayscale or RGB - no CMYK...
+ */
+
+ if (primary == IMAGE_RGB_CMYK)
+ primary = IMAGE_RGB;
+
+ /*
+ * Read the header; we already know it is a GIF file...
+ */
+
+ fread(buf, 13, 1, fp);
+
+ img->xsize = (buf[7] << 8) | buf[6];
+ img->ysize = (buf[9] << 8) | buf[8];
+ ncolors = 2 << (buf[10] & 0x07);
+ gray = primary == IMAGE_BLACK || primary == IMAGE_WHITE;
+
+ if (buf[10] & GIF_COLORMAP)
+ if (gif_read_cmap(fp, ncolors, cmap, &gray))
+ {
+ fclose(fp);
+ return (-1);
+ }
+
+ transparent = -1;
+
+ for (;;)
+ {
+ switch (getc(fp))
+ {
+ case ';' : /* End of image */
+ fclose(fp);
+ return (-1); /* Early end of file */
+
+ case '!' : /* Extension record */
+ buf[0] = getc(fp);
+ if (buf[0] == 0xf9) /* Graphic Control Extension */
+ {
+ gif_get_block(fp, buf);
+ if (buf[0] & 1) /* Get transparent color index */
+ transparent = buf[3];
+ }
+
+ while (gif_get_block(fp, buf) != 0);
+ break;
+
+ case ',' : /* Image data */
+ fread(buf, 9, 1, fp);
+
+ if (buf[8] & GIF_COLORMAP)
+ {
+ ncolors = 2 << (buf[8] & 0x07);
+ gray = primary == IMAGE_BLACK || primary == IMAGE_WHITE;
+
+ if (gif_read_cmap(fp, ncolors, cmap, &gray))
+ {
+ fclose(fp);
+ return (-1);
+ }
+ }
+
+ if (transparent >= 0)
+ {
+ /*
+ * Make transparent color white...
+ */
+
+ cmap[transparent][0] = 255;
+ cmap[transparent][1] = 255;
+ cmap[transparent][2] = 255;
+ }
+
+ if (gray)
+ {
+ switch (secondary)
+ {
+ case IMAGE_CMYK :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageWhiteToCMYK(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_CMY :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageWhiteToCMY(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_BLACK :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageWhiteToBlack(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_WHITE :
+ break;
+ case IMAGE_RGB :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageWhiteToRGB(cmap[i], cmap[i], 1);
+ break;
+ }
+
+ img->colorspace = secondary;
+ }
+ else
+ {
+ if (hue != 0 || saturation != 100)
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageRGBAdjust(cmap[i], 1, saturation, hue);
+
+ switch (primary)
+ {
+ case IMAGE_CMYK :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageRGBToCMYK(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_CMY :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageRGBToCMY(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_BLACK :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageRGBToBlack(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_WHITE :
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageRGBToWhite(cmap[i], cmap[i], 1);
+ break;
+ case IMAGE_RGB :
+ break;
+ }
+
+ img->colorspace = primary;
+ }
+
+ if (lut)
+ {
+ bpp = ImageGetDepth(img);
+
+ for (i = ncolors - 1; i >= 0; i --)
+ ImageLut(cmap[i], bpp, lut);
+ }
+
+ img->xsize = (buf[5] << 8) | buf[4];
+ img->ysize = (buf[7] << 8) | buf[6];
+
+ /*
+ * Check the dimensions of the image; since the dimensions are
+ * a 16-bit integer we just need to check for 0...
+ */
+
+ if (img->xsize == 0 || img->ysize == 0)
+ {
+ fprintf(stderr, "ERROR: Bad GIF image dimensions: %dx%d\n",
+ img->xsize, img->ysize);
+ fclose(fp);
+ return (1);
+ }
+
+ i = gif_read_image(fp, img, cmap, buf[8] & GIF_INTERLACE);
+ fclose(fp);
+ return (i);
+ }
+ }
+}
+
+
+/*
+ * 'gif_read_cmap()' - Read the colormap from a GIF file...
+ */
+
+static int /* O - -1 on error, 0 on success */
+gif_read_cmap(FILE *fp, /* I - File to read from */
+ int ncolors, /* I - Number of colors in file */
+ gif_cmap_t cmap, /* O - Colormap information */
+ int *gray) /* IO - Is the image grayscale? */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Read the colormap...
+ */
+
+ for (i = 0; i < ncolors; i ++)
+ if (fread(cmap[i], 3, 1, fp) < 1)
+ return (-1);
+
+ /*
+ * Check to see if the colormap is a grayscale ramp...
+ */
+
+ for (i = 0; i < ncolors; i ++)
+ if (cmap[i][0] != cmap[i][1] || cmap[i][1] != cmap[i][2])
+ break;
+
+ if (i == ncolors)
+ {
+ *gray = 1;
+ return (0);
+ }
+
+ /*
+ * If this needs to be a grayscale image, convert the RGB values to
+ * luminance values...
+ */
+
+ if (*gray)
+ for (i = 0; i < ncolors; i ++)
+ cmap[i][0] = (cmap[i][0] * 31 + cmap[i][1] * 61 + cmap[i][2] * 8) / 100;
+
+ return (0);
+}
+
+
+/*
+ * 'gif_get_block()' - Read a GIF data block...
+ */
+
+static int /* O - Number characters read */
+gif_get_block(FILE *fp, /* I - File to read from */
+ unsigned char *buf) /* I - Input buffer */
+{
+ int count; /* Number of character to read */
+
+
+ /*
+ * Read the count byte followed by the data from the file...
+ */
+
+ if ((count = getc(fp)) == EOF)
+ {
+ gif_eof = 1;
+ return (-1);
+ }
+ else if (count == 0)
+ gif_eof = 1;
+ else if (fread(buf, 1, count, fp) < count)
+ {
+ gif_eof = 1;
+ return (-1);
+ }
+ else
+ gif_eof = 0;
+
+ return (count);
+}
+
+
+/*
+ * 'gif_get_code()' - Get a LZW code from the file...
+ */
+
+static int /* O - LZW code */
+gif_get_code(FILE *fp, /* I - File to read from */
+ int code_size, /* I - Size of code in bits */
+ int first_time) /* I - 1 = first time, 0 = not first time */
+{
+ unsigned i, j, /* Looping vars */
+ ret; /* Return value */
+ int count; /* Number of bytes read */
+ static unsigned char buf[280]; /* Input buffer */
+ static unsigned curbit, /* Current bit */
+ lastbit, /* Last bit in buffer */
+ done, /* Done with this buffer? */
+ last_byte; /* Last byte in buffer */
+ static const unsigned char bits[8] = /* Bit masks for codes */
+ {
+ 0x01, 0x02, 0x04, 0x08,
+ 0x10, 0x20, 0x40, 0x80
+ };
+
+
+ if (first_time)
+ {
+ /*
+ * Just initialize the input buffer...
+ */
+
+ curbit = 0;
+ lastbit = 0;
+ last_byte = 0;
+ done = 0;
+
+ return (0);
+ }
+
+ if ((curbit + code_size) >= lastbit)
+ {
+ /*
+ * Don't have enough bits to hold the code...
+ */
+
+ if (done)
+ return (-1); /* Sorry, no more... */
+
+ /*
+ * Move last two bytes to front of buffer...
+ */
+
+ if (last_byte > 1)
+ {
+ buf[0] = buf[last_byte - 2];
+ buf[1] = buf[last_byte - 1];
+ last_byte = 2;
+ }
+ else if (last_byte == 1)
+ {
+ buf[0] = buf[last_byte - 1];
+ last_byte = 1;
+ }
+
+ /*
+ * Read in another buffer...
+ */
+
+ if ((count = gif_get_block (fp, buf + last_byte)) <= 0)
+ {
+ /*
+ * Whoops, no more data!
+ */
+
+ done = 1;
+ return (-1);
+ }
+
+ /*
+ * Update buffer state...
+ */
+
+ curbit = (curbit - lastbit) + 8 * last_byte;
+ last_byte += count;
+ lastbit = last_byte * 8;
+ }
+
+ ret = 0;
+ for (ret = 0, i = curbit + code_size - 1, j = code_size;
+ j > 0;
+ i --, j --)
+ ret = (ret << 1) | ((buf[i / 8] & bits[i & 7]) != 0);
+
+ curbit += code_size;
+
+ return ret;
+}
+
+
+/*
+ * 'gif_read_lzw()' - Read a byte from the LZW stream...
+ */
+
+static int /* I - Byte from stream */
+gif_read_lzw(FILE *fp, /* I - File to read from */
+ int first_time, /* I - 1 = first time, 0 = not first time */
+ int input_code_size) /* I - Code size in bits */
+{
+ int i, /* Looping var */
+ code, /* Current code */
+ incode; /* Input code */
+ static short fresh = 0, /* 1 = empty buffers */
+ code_size, /* Current code size */
+ set_code_size, /* Initial code size set */
+ max_code, /* Maximum code used */
+ max_code_size, /* Maximum code size */
+ firstcode, /* First code read */
+ oldcode, /* Last code read */
+ clear_code, /* Clear code for LZW input */
+ end_code, /* End code for LZW input */
+ *stack = NULL, /* Output stack */
+ *sp; /* Current stack pointer */
+ static gif_table_t *table = NULL; /* String table */
+
+
+ if (first_time)
+ {
+ /*
+ * Setup LZW state...
+ */
+
+ set_code_size = input_code_size;
+ code_size = set_code_size + 1;
+ clear_code = 1 << set_code_size;
+ end_code = clear_code + 1;
+ max_code_size = 2 * clear_code;
+ max_code = clear_code + 2;
+
+ /*
+ * Allocate memory for buffers...
+ */
+
+ if (table == NULL)
+ table = calloc(2, sizeof(gif_table_t));
+
+ if (table == NULL)
+ return (-1);
+
+ if (stack == NULL)
+ stack = calloc(8192, sizeof(short));
+
+ if (stack == NULL)
+ return (-1);
+
+ /*
+ * Initialize input buffers...
+ */
+
+ gif_get_code(fp, 0, 1);
+
+ /*
+ * Wipe the decompressor table...
+ */
+
+ fresh = 1;
+
+ for (i = 0; i < clear_code; i ++)
+ {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+
+ for (; i < 4096; i ++)
+ table[0][i] = table[1][0] = 0;
+
+ sp = stack;
+
+ return (0);
+ }
+ else if (fresh)
+ {
+ fresh = 0;
+
+ do
+ firstcode = oldcode = gif_get_code(fp, code_size, 0);
+ while (firstcode == clear_code);
+
+ return (firstcode);
+ }
+
+ if (sp > stack)
+ return (*--sp);
+
+ while ((code = gif_get_code (fp, code_size, 0)) >= 0)
+ {
+ if (code == clear_code)
+ {
+ for (i = 0; i < clear_code; i ++)
+ {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+
+ for (; i < 4096; i ++)
+ table[0][i] = table[1][i] = 0;
+
+ code_size = set_code_size + 1;
+ max_code_size = 2 * clear_code;
+ max_code = clear_code + 2;
+
+ sp = stack;
+
+ firstcode = oldcode = gif_get_code(fp, code_size, 0);
+
+ return (firstcode);
+ }
+ else if (code == end_code)
+ {
+ unsigned char buf[260];
+
+
+ if (!gif_eof)
+ while (gif_get_block(fp, buf) > 0);
+
+ return (-2);
+ }
+
+ incode = code;
+
+ if (code >= max_code)
+ {
+ *sp++ = firstcode;
+ code = oldcode;
+ }
+
+ while (code >= clear_code)
+ {
+ *sp++ = table[1][code];
+ if (code == table[0][code])
+ return (255);
+
+ code = table[0][code];
+ }
+
+ *sp++ = firstcode = table[1][code];
+ code = max_code;
+
+ if (code < 4096)
+ {
+ table[0][code] = oldcode;
+ table[1][code] = firstcode;
+ max_code ++;
+
+ if (max_code >= max_code_size && max_code_size < 4096)
+ {
+ max_code_size *= 2;
+ code_size ++;
+ }
+ }
+
+ oldcode = incode;
+
+ if (sp > stack)
+ return (*--sp);
+ }
+
+ return (code);
+}
+
+
+/*
+ * 'gif_read_image()' - Read a GIF image stream...
+ */
+
+static int /* I - 0 = success, -1 = failure */
+gif_read_image(FILE *fp, /* I - Input file */
+ image_t *img, /* I - Image pointer */
+ gif_cmap_t cmap, /* I - Colormap */
+ int interlace) /* I - Non-zero = interlaced image */
+{
+ unsigned char code_size; /* Code size */
+ ib_t *pixels, /* Pixel buffer */
+ *temp; /* Current pixel */
+ int xpos, /* Current X position */
+ ypos, /* Current Y position */
+ pass; /* Current pass */
+ int pixel; /* Current pixel */
+ int bpp; /* Bytes per pixel */
+ static const int xpasses[4] = /* X interleaving */
+ { 8, 8, 4, 2 },
+ ypasses[5] = /* Y interleaving */
+ { 0, 4, 2, 1, 999999 };
+
+
+ bpp = ImageGetDepth(img);
+ pixels = calloc(bpp, img->xsize);
+ xpos = 0;
+ ypos = 0;
+ pass = 0;
+ code_size = getc(fp);
+
+ if (gif_read_lzw(fp, 1, code_size) < 0)
+ return (-1);
+
+ temp = pixels;
+ while ((pixel = gif_read_lzw(fp, 0, code_size)) >= 0)
+ {
+ switch (bpp)
+ {
+ case 4 :
+ temp[3] = cmap[pixel][3];
+ case 3 :
+ temp[2] = cmap[pixel][2];
+ case 2 :
+ temp[1] = cmap[pixel][1];
+ default :
+ temp[0] = cmap[pixel][0];
+ }
+
+ xpos ++;
+ temp += bpp;
+ if (xpos == img->xsize)
+ {
+ ImagePutRow(img, 0, ypos, img->xsize, pixels);
+
+ xpos = 0;
+ temp = pixels;
+
+ if (interlace)
+ {
+ ypos += xpasses[pass];
+
+ if (ypos >= img->ysize)
+ {
+ pass ++;
+
+ ypos = ypasses[pass];
+ }
+ }
+ else
+ ypos ++;
+ }
+
+ if (ypos >= img->ysize)
+ break;
+ }
+
+ free(pixels);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-jpeg.c b/filter/image-jpeg.c
new file mode 100644
index 000000000..8a1bb0d26
--- /dev/null
+++ b/filter/image-jpeg.c
@@ -0,0 +1,315 @@
+/*
+ * "$Id$"
+ *
+ * JPEG image routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadJPEG() - Read a JPEG image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+#ifdef HAVE_LIBJPEG
+# include <jpeglib.h> /* JPEG/JFIF image definitions */
+
+
+/*
+ * 'ImageReadJPEG()' - Read a JPEG image file.
+ */
+
+int /* O - Read status */
+ImageReadJPEG(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ struct jpeg_decompress_struct cinfo; /* Decompressor info */
+ struct jpeg_error_mgr jerr; /* Error handler info */
+ ib_t *in, /* Input pixels */
+ *out; /* Output pixels */
+ char header[16];
+ /* Photoshop JPEG header */
+ int psjpeg; /* Non-zero if Photoshop JPEG */
+ static const char *cspaces[] =
+ { /* JPEG colorspaces... */
+ "JCS_UNKNOWN",
+ "JCS_GRAYSCALE",
+ "JCS_RGB",
+ "JCS_YCbCr",
+ "JCS_CMYK",
+ "JCS_YCCK"
+ };
+
+
+ /*
+ * Read the first 16 bytes to determine if this is a Photoshop JPEG file...
+ */
+
+ fread(header, sizeof(header), 1, fp);
+ rewind(fp);
+
+ psjpeg = memcmp(header + 6, "Photoshop ", 10) == 0;
+
+ /*
+ * Read the JPEG header...
+ */
+
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+ jpeg_stdio_src(&cinfo, fp);
+ jpeg_read_header(&cinfo, 1);
+
+ cinfo.quantize_colors = 0;
+
+ fprintf(stderr, "DEBUG: num_components = %d\n", cinfo.num_components);
+ fprintf(stderr, "DEBUG: jpeg_color_space = %s\n",
+ cspaces[cinfo.jpeg_color_space]);
+
+ if (cinfo.num_components == 1)
+ {
+ fputs("DEBUG: Converting image to grayscale...\n", stderr);
+
+ cinfo.out_color_space = JCS_GRAYSCALE;
+ cinfo.out_color_components = 1;
+ cinfo.output_components = 1;
+
+ img->colorspace = secondary;
+ }
+ else if (cinfo.num_components == 4)
+ {
+ fputs("DEBUG: Converting image to CMYK...\n", stderr);
+
+ cinfo.out_color_space = JCS_CMYK;
+ cinfo.out_color_components = 4;
+ cinfo.output_components = 4;
+
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_CMYK : primary;
+ }
+ else
+ {
+ fputs("DEBUG: Converting image to RGB...\n", stderr);
+
+ cinfo.out_color_space = JCS_RGB;
+ cinfo.out_color_components = 3;
+ cinfo.output_components = 3;
+
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+ }
+
+ jpeg_calc_output_dimensions(&cinfo);
+
+ if (cinfo.output_width <= 0 || cinfo.output_width > IMAGE_MAX_WIDTH ||
+ cinfo.output_height <= 0 || cinfo.output_height > IMAGE_MAX_HEIGHT)
+ {
+ fprintf(stderr, "ERROR: Bad JPEG dimensions %dx%d!\n",
+ cinfo.output_width, cinfo.output_height);
+
+ jpeg_destroy_decompress(&cinfo);
+
+ fclose(fp);
+ return (1);
+ }
+
+ img->xsize = cinfo.output_width;
+ img->ysize = cinfo.output_height;
+
+ if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
+ {
+ if (cinfo.density_unit == 1)
+ {
+ img->xppi = cinfo.X_density;
+ img->yppi = cinfo.Y_density;
+ }
+ else
+ {
+ img->xppi = (int)((float)cinfo.X_density * 2.54);
+ img->yppi = (int)((float)cinfo.Y_density * 2.54);
+ }
+
+ if (img->xppi == 0 || img->yppi == 0)
+ {
+ fprintf(stderr, "ERROR: Bad JPEG image resolution %dx%d PPI.\n",
+ img->xppi, img->yppi);
+ img->xppi = img->yppi = 128;
+ }
+ }
+
+ fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n",
+ img->xsize, img->ysize, cinfo.output_components,
+ img->xppi, img->yppi);
+
+ ImageSetMaxTiles(img, 0);
+
+ in = malloc(img->xsize * cinfo.output_components);
+ out = malloc(img->xsize * ImageGetDepth(img));
+
+ jpeg_start_decompress(&cinfo);
+
+ while (cinfo.output_scanline < cinfo.output_height)
+ {
+ jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1);
+
+ if (psjpeg && cinfo.output_components == 4)
+ {
+ /*
+ * Invert CMYK data from Photoshop...
+ */
+
+ ib_t *ptr; /* Pointer into buffer */
+ int i; /* Looping var */
+
+
+ for (ptr = in, i = img->xsize * 4; i > 0; i --, ptr ++)
+ *ptr = 255 - *ptr;
+ }
+
+ if ((saturation != 100 || hue != 0) && cinfo.output_components == 3)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if ((img->colorspace == IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) ||
+ (img->colorspace == IMAGE_RGB && cinfo.out_color_space == JCS_RGB) ||
+ (img->colorspace == IMAGE_CMYK && cinfo.out_color_space == JCS_CMYK))
+ {
+#ifdef DEBUG
+ int i, j;
+ ib_t *ptr;
+
+
+ fputs("DEBUG: Direct Data...\n", stderr);
+
+ fputs("DEBUG:", stderr);
+
+ for (i = 0, ptr = in; i < img->xsize; i ++)
+ {
+ putc(' ', stderr);
+ for (j = 0; j < cinfo.output_components; j ++, ptr ++)
+ fprintf(stderr, "%02X", *ptr & 255);
+ }
+
+ putc('\n', stderr);
+#endif /* DEBUG */
+
+ if (lut)
+ ImageLut(in, img->xsize * ImageGetDepth(img), lut);
+
+ ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in);
+ }
+ else if (cinfo.out_color_space == JCS_GRAYSCALE)
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * ImageGetDepth(img), lut);
+
+ ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
+ }
+ else if (cinfo.out_color_space == JCS_RGB)
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * ImageGetDepth(img), lut);
+
+ ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
+ }
+ else /* JCS_CMYK */
+ {
+ fputs("DEBUG: JCS_CMYK\n", stderr);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageCMYKToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageCMYKToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageCMYKToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_RGB :
+ ImageCMYKToRGB(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * ImageGetDepth(img), lut);
+
+ ImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
+ }
+ }
+
+ free(in);
+ free(out);
+
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ fclose(fp);
+
+ return (0);
+}
+
+
+#endif /* HAVE_LIBJPEG */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-photocd.c b/filter/image-photocd.c
new file mode 100644
index 000000000..66944631c
--- /dev/null
+++ b/filter/image-photocd.c
@@ -0,0 +1,325 @@
+/*
+ * "$Id$"
+ *
+ * PhotoCD routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadPhotoCD() - Read a PhotoCD image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * PhotoCD support is currently limited to the 768x512 base image, which
+ * is only YCC encoded. Support for the higher resolution images will
+ * require a lot of extra code...
+ */
+
+/*
+ * 'ImageReadPhotoCD()' - Read a PhotoCD image file.
+ */
+
+int /* O - Read status */
+ImageReadPhotoCD(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int x, y; /* Looping vars */
+ int xdir, /* X direction */
+ xstart; /* X starting point */
+ int bpp; /* Bytes per pixel */
+ int pass; /* Pass number */
+ int rotation; /* 0 for 768x512, 1 for 512x768 */
+ int temp, /* Adjusted luminance */
+ temp2, /* Red, green, and blue values */
+ cb, cr; /* Adjusted chroma values */
+ ib_t *in, /* Input (YCC) pixels */
+ *iy, /* Luminance */
+ *icb, /* Blue chroma */
+ *icr, /* Red chroma */
+ *rgb, /* RGB */
+ *rgbptr, /* Pointer into RGB data */
+ *out; /* Output pixels */
+
+
+ (void)secondary;
+
+ /*
+ * Get the image orientation...
+ */
+
+ fseek(fp, 72, SEEK_SET);
+ rotation = (getc(fp) & 63) != 8;
+
+ /*
+ * Seek to the start of the base image...
+ */
+
+ fseek(fp, 0x30000, SEEK_SET);
+
+ /*
+ * Allocate and initialize...
+ */
+
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+ img->xppi = 128;
+ img->yppi = 128;
+
+ if (rotation)
+ {
+ img->xsize = 512;
+ img->ysize = 768;
+ }
+ else
+ {
+ img->xsize = 768;
+ img->ysize = 512;
+ }
+
+ ImageSetMaxTiles(img, 0);
+
+ bpp = ImageGetDepth(img);
+ in = malloc(768 * 3);
+ out = malloc(768 * bpp);
+
+ if (bpp > 1)
+ rgb = malloc(768 * 3);
+ else
+ rgb = NULL;
+
+ if (rotation)
+ {
+ xstart = 767 * bpp;
+ xdir = -2 * bpp;
+ }
+ else
+ {
+ xstart = 0;
+ xdir = 0;
+ }
+
+ /*
+ * Read the image file...
+ */
+
+ for (y = 0; y < 512; y += 2)
+ {
+ /*
+ * Grab the next two scanlines:
+ *
+ * YYYYYYYYYYYYYYY...
+ * YYYYYYYYYYYYYYY...
+ * CbCbCb...CrCrCr...
+ */
+
+ if (fread(in, 1, 768 * 3, fp) < (768 * 3))
+ {
+ /*
+ * Couldn't read a row of data - return an error!
+ */
+
+ free(in);
+ free(out);
+
+ return (-1);
+ }
+
+ /*
+ * Process the two scanlines...
+ */
+
+ for (pass = 0, iy = in; pass < 2; pass ++)
+ {
+ if (bpp == 1)
+ {
+ /*
+ * Just extract the luminance channel from the line and put it
+ * in the image...
+ */
+
+ if (primary == IMAGE_BLACK)
+ {
+ if (rotation)
+ {
+ for (rgbptr = out + xstart, x = 0; x < 768; x ++)
+ *rgbptr-- = 255 - *iy++;
+
+ if (lut)
+ ImageLut(out, 768, lut);
+
+ ImagePutCol(img, 511 - y - pass, 0, 768, out);
+ }
+ else
+ {
+ ImageWhiteToBlack(iy, out, 768);
+
+ if (lut)
+ ImageLut(out, 768, lut);
+
+ ImagePutRow(img, 0, y + pass, 768, out);
+ iy += 768;
+ }
+ }
+ else if (rotation)
+ {
+ for (rgbptr = out + xstart, x = 0; x < 768; x ++)
+ *rgbptr-- = 255 - *iy++;
+
+ if (lut)
+ ImageLut(out, 768, lut);
+
+ ImagePutCol(img, 511 - y - pass, 0, 768, out);
+ }
+ else
+ {
+ if (lut)
+ ImageLut(iy, 768, lut);
+
+ ImagePutRow(img, 0, y + pass, 768, iy);
+ iy += 768;
+ }
+ }
+ else
+ {
+ /*
+ * Convert YCbCr to RGB... While every pixel gets a luminance
+ * value, adjacent pixels share chroma information.
+ */
+
+ cb = cr = 0.0f;
+
+ for (x = 0, rgbptr = rgb + xstart, icb = in + 1536, icr = in + 1920;
+ x < 768;
+ x ++, iy ++, rgbptr += xdir)
+ {
+ if (!(x & 1))
+ {
+ cb = (float)(*icb - 156);
+ cr = (float)(*icr - 137);
+ }
+
+ temp = 92241 * (*iy);
+
+ temp2 = (temp + 86706 * cr) / 65536;
+ if (temp2 < 0)
+ *rgbptr++ = 0;
+ else if (temp2 > 255)
+ *rgbptr++ = 255;
+ else
+ *rgbptr++ = temp2;
+
+ temp2 = (temp - 25914 * cb - 44166 * cr) / 65536;
+ if (temp2 < 0)
+ *rgbptr++ = 0;
+ else if (temp2 > 255)
+ *rgbptr++ = 255;
+ else
+ *rgbptr++ = temp2;
+
+ temp2 = (temp + 133434 * cb) / 65536;
+ if (temp2 < 0)
+ *rgbptr++ = 0;
+ else if (temp2 > 255)
+ *rgbptr++ = 255;
+ else
+ *rgbptr++ = temp2;
+
+ if (x & 1)
+ {
+ icb ++;
+ icr ++;
+ }
+ }
+
+ /*
+ * Adjust the hue and saturation if needed...
+ */
+
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(rgb, 768, saturation, hue);
+
+ /*
+ * Then convert the RGB data to the appropriate colorspace and
+ * put it in the image...
+ */
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(rgb, 768 * 3, lut);
+
+ if (rotation)
+ ImagePutCol(img, 511 - y - pass, 0, 768, rgb);
+ else
+ ImagePutRow(img, 0, y + pass, 768, rgb);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_CMY :
+ ImageRGBToCMY(rgb, out, 768);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(rgb, out, 768);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, 768 * bpp, lut);
+
+ if (rotation)
+ ImagePutCol(img, 511 - y - pass, 0, 768, out);
+ else
+ ImagePutRow(img, 0, y + pass, 768, out);
+ }
+ }
+ }
+ }
+
+ /*
+ * Free memory and return...
+ */
+
+ free(in);
+ free(out);
+ if (bpp > 1)
+ free(rgb);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-pix.c b/filter/image-pix.c
new file mode 100644
index 000000000..f663f1421
--- /dev/null
+++ b/filter/image-pix.c
@@ -0,0 +1,240 @@
+/*
+ * "$Id$"
+ *
+ * Alias PIX image routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadPIX() - Read a PIX image file.
+ * read_short() - Read a 16-bit integer.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * Local functions...
+ */
+
+static short read_short(FILE *fp);
+
+
+/*
+ * 'ImageReadPIX()' - Read a PIX image file.
+ */
+
+int /* O - Read status */
+ImageReadPIX(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ short width, /* Width of image */
+ height, /* Height of image */
+ depth; /* Depth of image (bits) */
+ int count, /* Repetition count */
+ bpp, /* Bytes per pixel */
+ x, y; /* Looping vars */
+ ib_t r, g, b; /* Red, green/gray, blue values */
+ ib_t *in, /* Input pixels */
+ *out, /* Output pixels */
+ *ptr; /* Pointer into pixels */
+
+
+ /*
+ * Get the image dimensions and setup the image...
+ */
+
+ width = read_short(fp);
+ height = read_short(fp);
+ read_short(fp);
+ read_short(fp);
+ depth = read_short(fp);
+
+ /*
+ * Check the dimensions of the image. Since the short values used for the
+ * width and height cannot exceed IMAGE_MAX_WIDTH or IMAGE_MAX_HEIGHT, we
+ * just need to verify they are positive integers.
+ */
+
+ if (width <= 0 || height <= 0 ||
+ (depth != 8 && depth != 24))
+ {
+ fprintf(stderr, "ERROR: Bad PIX image dimensions %dx%dx%d\n",
+ width, height, depth);
+ fclose(fp);
+ return (1);
+ }
+
+ if (depth == 8)
+ img->colorspace = secondary;
+ else
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+
+ img->xsize = width;
+ img->ysize = height;
+
+ ImageSetMaxTiles(img, 0);
+
+ in = malloc(img->xsize * (depth / 8));
+ bpp = ImageGetDepth(img);
+ out = malloc(img->xsize * bpp);
+
+ /*
+ * Read the image data...
+ */
+
+ if (depth == 8)
+ {
+ for (count = 0, y = 0, g = 0; y < img->ysize; y ++)
+ {
+ if (img->colorspace == IMAGE_WHITE)
+ ptr = out;
+ else
+ ptr = in;
+
+ for (x = img->xsize; x > 0; x --, count --)
+ {
+ if (count == 0)
+ {
+ count = getc(fp);
+ g = getc(fp);
+ }
+
+ *ptr++ = g;
+ }
+
+ if (img->colorspace != IMAGE_WHITE)
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ else
+ {
+ for (count = 0, y = 0, r = 0, g = 0, b = 0; y < img->ysize; y ++)
+ {
+ if (img->colorspace == IMAGE_RGB)
+ ptr = out;
+ else
+ ptr = in;
+
+ for (x = img->xsize; x > 0; x --, count --)
+ {
+ if (count == 0)
+ {
+ count = getc(fp);
+ b = getc(fp);
+ g = getc(fp);
+ r = getc(fp);
+ }
+
+ *ptr++ = r;
+ *ptr++ = g;
+ *ptr++ = b;
+ }
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(out, img->xsize, saturation, hue);
+ }
+ else
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+
+ fclose(fp);
+ free(in);
+ free(out);
+
+ return (0);
+}
+
+
+/*
+ * 'read_short()' - Read a 16-bit integer.
+ */
+
+static short /* O - Value from file */
+read_short(FILE *fp) /* I - File to read from */
+{
+ int ch; /* Character from file */
+
+
+ ch = getc(fp);
+ return ((ch << 8) | getc(fp));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-png.c b/filter/image-png.c
new file mode 100644
index 000000000..7de2a9d82
--- /dev/null
+++ b/filter/image-png.c
@@ -0,0 +1,270 @@
+/*
+ * "$Id$"
+ *
+ * PNG image routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadPNG() - Read a PNG image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+#include <png.h> /* Portable Network Graphics (PNG) definitions */
+
+
+/*
+ * 'ImageReadPNG()' - Read a PNG image file.
+ */
+
+int /* O - Read status */
+ImageReadPNG(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int y; /* Looping var */
+ png_structp pp; /* PNG read pointer */
+ png_infop info; /* PNG info pointers */
+ int bpp; /* Bytes per pixel */
+ int pass, /* Current pass */
+ passes; /* Number of passes required */
+ ib_t *in, /* Input pixels */
+ *inptr, /* Pointer into pixels */
+ *out; /* Output pixels */
+ png_color_16 bg; /* Background color */
+
+
+ /*
+ * Setup the PNG data structures...
+ */
+
+ pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info = png_create_info_struct(pp);
+
+ /*
+ * Initialize the PNG read "engine"...
+ */
+
+ png_init_io(pp, fp);
+
+ /*
+ * Get the image dimensions and load the output image...
+ */
+
+ png_read_info(pp, info);
+
+ fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n",
+ info->width, info->height, info->bit_depth, info->color_type,
+ (info->color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE",
+ (info->color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "",
+ (info->color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : "");
+
+ if (info->color_type & PNG_COLOR_MASK_PALETTE)
+ png_set_expand(pp);
+ else if (info->bit_depth < 8)
+ {
+ png_set_packing(pp);
+ png_set_expand(pp);
+ }
+ else if (info->bit_depth == 16)
+ png_set_strip_16(pp);
+
+ if (info->color_type & PNG_COLOR_MASK_COLOR)
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+ else
+ img->colorspace = secondary;
+
+ if (info->width == 0 || info->width > IMAGE_MAX_WIDTH ||
+ info->height == 0 || info->height > IMAGE_MAX_HEIGHT)
+ {
+ fprintf(stderr, "ERROR: PNG image has invalid dimensions %ux%u!\n",
+ (unsigned)info->width, (unsigned)info->height);
+ fclose(fp);
+ return (1);
+ }
+
+ img->xsize = info->width;
+ img->ysize = info->height;
+
+ if (info->valid & PNG_INFO_pHYs &&
+ info->phys_unit_type == PNG_RESOLUTION_METER)
+ {
+ img->xppi = (int)((float)info->x_pixels_per_unit * 0.0254);
+ img->yppi = (int)((float)info->y_pixels_per_unit * 0.0254);
+
+ if (img->xppi == 0 || img->yppi == 0)
+ {
+ fprintf(stderr, "ERROR: PNG image has invalid resolution %dx%d PPI\n",
+ img->xppi, img->yppi);
+
+ img->xppi = img->yppi = 128;
+ }
+ }
+
+ ImageSetMaxTiles(img, 0);
+
+ passes = png_set_interlace_handling(pp);
+
+ /*
+ * Handle transparency...
+ */
+
+ if (png_get_valid(pp, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(pp);
+
+ bg.red = 65535;
+ bg.green = 65535;
+ bg.blue = 65535;
+
+ png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+ if (passes == 1)
+ {
+ /*
+ * Load one row at a time...
+ */
+
+ if (info->color_type == PNG_COLOR_TYPE_GRAY ||
+ info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ in = malloc(img->xsize);
+ else
+ in = malloc(img->xsize * 3);
+ }
+ else
+ {
+ /*
+ * Interlaced images must be loaded all at once...
+ */
+
+ if (info->color_type == PNG_COLOR_TYPE_GRAY ||
+ info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ in = malloc(img->xsize * img->ysize);
+ else
+ in = malloc(img->xsize * img->ysize * 3);
+ }
+
+ bpp = ImageGetDepth(img);
+ out = malloc(img->xsize * bpp);
+
+ /*
+ * Read the image, interlacing as needed...
+ */
+
+ for (pass = 1; pass <= passes; pass ++)
+ for (inptr = in, y = 0; y < img->ysize; y ++)
+ {
+ png_read_row(pp, (png_bytep)inptr, NULL);
+
+ if (pass == passes)
+ {
+ /*
+ * Output this row...
+ */
+
+ if (info->color_type & PNG_COLOR_MASK_COLOR)
+ {
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(inptr, img->xsize, saturation, hue);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(inptr, out, img->xsize);
+ break;
+ case IMAGE_RGB :
+ memcpy(out, inptr, img->xsize * 3);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(inptr, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(inptr, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(inptr, out, img->xsize);
+ break;
+ }
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ memcpy(out, inptr, img->xsize);
+ break;
+ case IMAGE_RGB :
+ ImageWhiteToRGB(inptr, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(inptr, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(inptr, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(inptr, out, img->xsize);
+ break;
+ }
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+
+ if (passes > 1)
+ {
+ if (info->color_type & PNG_COLOR_MASK_COLOR)
+ inptr += img->xsize * 3;
+ else
+ inptr += img->xsize;
+ }
+ }
+
+ png_read_end(pp, info);
+ png_read_destroy(pp, info, NULL);
+
+ fclose(fp);
+ free(in);
+ free(out);
+
+ return (0);
+}
+
+
+#endif /* HAVE_LIBPNG && HAVE_LIBZ */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-pnm.c b/filter/image-pnm.c
new file mode 100644
index 000000000..982be63ae
--- /dev/null
+++ b/filter/image-pnm.c
@@ -0,0 +1,306 @@
+/*
+ * "$Id$"
+ *
+ * Portable Any Map file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadPNM() - Read a PNM image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+#include <ctype.h>
+
+
+/*
+ * 'ImageReadPNM()' - Read a PNM image file.
+ */
+
+int /* O - Read status */
+ImageReadPNM(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int x, y; /* Looping vars */
+ int bpp; /* Bytes per pixel */
+ ib_t *in, /* Input pixels */
+ *inptr, /* Current input pixel */
+ *out, /* Output pixels */
+ *outptr, /* Current output pixel */
+ bit; /* Bit in input line */
+ char line[255], /* Input line */
+ *lineptr; /* Pointer in line */
+ int format, /* Format of PNM file */
+ val, /* Pixel value */
+ maxval; /* Maximum pixel value */
+
+
+ /*
+ * Read the file header in the format:
+ *
+ * Pformat
+ * # comment1
+ * # comment2
+ * ...
+ * # commentN
+ * width
+ * height
+ * max sample
+ */
+
+ lineptr = fgets(line, sizeof(line), fp);
+ lineptr ++;
+
+ format = atoi(lineptr);
+ while (isdigit(*lineptr & 255))
+ lineptr ++;
+
+ while (lineptr != NULL && img->xsize == 0)
+ {
+ if (*lineptr == '\0' || *lineptr == '#')
+ lineptr = fgets(line, sizeof(line), fp);
+ else if (isdigit(*lineptr & 255))
+ {
+ img->xsize = atoi(lineptr);
+ while (isdigit(*lineptr & 255))
+ lineptr ++;
+ }
+ else
+ lineptr ++;
+ }
+
+ while (lineptr != NULL && img->ysize == 0)
+ {
+ if (*lineptr == '\0' || *lineptr == '#')
+ lineptr = fgets(line, sizeof(line), fp);
+ else if (isdigit(*lineptr & 255))
+ {
+ img->ysize = atoi(lineptr);
+ while (isdigit(*lineptr & 255))
+ lineptr ++;
+ }
+ else
+ lineptr ++;
+ }
+
+ if (format != 1 && format != 4)
+ {
+ maxval = 0;
+
+ while (lineptr != NULL && maxval == 0)
+ {
+ if (*lineptr == '\0' || *lineptr == '#')
+ lineptr = fgets(line, sizeof(line), fp);
+ else if (isdigit(*lineptr & 255))
+ {
+ maxval = atoi(lineptr);
+ while (isdigit(*lineptr & 255))
+ lineptr ++;
+ }
+ else
+ lineptr ++;
+ }
+ }
+ else
+ maxval = 1;
+
+ if (img->xsize == 0 || img->xsize > IMAGE_MAX_WIDTH ||
+ img->ysize == 0 || img->ysize > IMAGE_MAX_HEIGHT)
+ {
+ fprintf(stderr, "ERROR: Bad PNM dimensions %dx%d!\n",
+ img->xsize, img->ysize);
+ fclose(fp);
+ return (1);
+ }
+
+ if (maxval == 0)
+ {
+ fprintf(stderr, "ERROR: Bad PNM max value %d!\n", maxval);
+ fclose(fp);
+ return (1);
+ }
+
+ if (format == 1 || format == 2 || format == 4 || format == 5)
+ img->colorspace = secondary;
+ else
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+
+ ImageSetMaxTiles(img, 0);
+
+ bpp = ImageGetDepth(img);
+ in = malloc(img->xsize * 3);
+ out = malloc(img->xsize * bpp);
+
+ /*
+ * Read the image file...
+ */
+
+ for (y = 0; y < img->ysize; y ++)
+ {
+ switch (format)
+ {
+ case 1 :
+ case 2 :
+ for (x = img->xsize, inptr = in; x > 0; x --, inptr ++)
+ if (fscanf(fp, "%d", &val) == 1)
+ *inptr = 255 * val / maxval;
+ break;
+
+ case 3 :
+ for (x = img->xsize, inptr = in; x > 0; x --, inptr += 3)
+ {
+ if (fscanf(fp, "%d", &val) == 1)
+ inptr[0] = 255 * val / maxval;
+ if (fscanf(fp, "%d", &val) == 1)
+ inptr[1] = 255 * val / maxval;
+ if (fscanf(fp, "%d", &val) == 1)
+ inptr[2] = 255 * val / maxval;
+ }
+ break;
+
+ case 4 :
+ fread(out, (img->xsize + 7) / 8, 1, fp);
+ for (x = img->xsize, inptr = in, outptr = out, bit = 128;
+ x > 0;
+ x --, inptr ++)
+ {
+ if (*outptr & bit)
+ *inptr = 255;
+ else
+ *inptr = 0;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ inptr ++;
+ }
+ }
+ break;
+
+ case 5 :
+ fread(in, img->xsize, 1, fp);
+ break;
+
+ case 6 :
+ fread(in, img->xsize, 3, fp);
+ break;
+ }
+
+ switch (format)
+ {
+ case 1 :
+ case 2 :
+ case 4 :
+ case 5 :
+ if (img->colorspace == IMAGE_WHITE)
+ {
+ if (lut)
+ ImageLut(in, img->xsize, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ break;
+
+ default :
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ break;
+ }
+ }
+
+ free(in);
+ free(out);
+
+ fclose(fp);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-sgi.c b/filter/image-sgi.c
new file mode 100644
index 000000000..d4509a5d3
--- /dev/null
+++ b/filter/image-sgi.c
@@ -0,0 +1,285 @@
+/*
+ * "$Id$"
+ *
+ * SGI image file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadSGI() - Read a SGI image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+#include "image-sgi.h"
+
+
+/*
+ * 'ImageReadSGI()' - Read a SGI image file.
+ */
+
+int /* O - Read status */
+ImageReadSGI(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int i, y; /* Looping vars */
+ int bpp; /* Bytes per pixel */
+ sgi_t *sgip; /* SGI image file */
+ ib_t *in, /* Input pixels */
+ *inptr, /* Current input pixel */
+ *out; /* Output pixels */
+ unsigned short *rows[4], /* Row pointers for image data */
+ *red,
+ *green,
+ *blue,
+ *gray,
+ *alpha;
+
+
+ /*
+ * Setup the SGI file...
+ */
+
+ sgip = sgiOpenFile(fp, SGI_READ, 0, 0, 0, 0, 0);
+
+ /*
+ * Get the image dimensions and load the output image...
+ */
+
+ /*
+ * Check the image dimensions; since xsize and ysize are unsigned shorts,
+ * just check if they are 0 since they can't exceed IMAGE_MAX_WIDTH or
+ * IMAGE_MAX_HEIGHT...
+ */
+
+ if (sgip->xsize == 0 || sgip->ysize == 0 ||
+ sgip->zsize == 0 || sgip->zsize > 4)
+ {
+ fprintf(stderr, "ERROR: Bad SGI image dimensions %ux%ux%u!\n",
+ sgip->xsize, sgip->ysize, sgip->zsize);
+ sgiClose(sgip);
+ fclose(fp);
+ return (1);
+ }
+
+ if (sgip->zsize < 3)
+ img->colorspace = secondary;
+ else
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+
+ img->xsize = sgip->xsize;
+ img->ysize = sgip->ysize;
+
+ ImageSetMaxTiles(img, 0);
+
+ bpp = ImageGetDepth(img);
+ in = malloc(img->xsize * sgip->zsize);
+ out = malloc(img->xsize * bpp);
+
+ rows[0] = calloc(img->xsize * sgip->zsize, sizeof(unsigned short));
+ for (i = 1; i < sgip->zsize; i ++)
+ rows[i] = rows[0] + i * img->xsize;
+
+ /*
+ * Read the SGI image file...
+ */
+
+ for (y = 0; y < img->ysize; y ++)
+ {
+ for (i = 0; i < sgip->zsize; i ++)
+ sgiGetRow(sgip, rows[i], img->ysize - 1 - y, i);
+
+ switch (sgip->zsize)
+ {
+ case 1 :
+ if (sgip->bpp == 1)
+ for (i = img->xsize - 1, gray = rows[0], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = *gray++;
+ }
+ else
+ for (i = img->xsize - 1, gray = rows[0], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = (*gray++) / 256 + 128;
+ }
+ break;
+ case 2 :
+ if (sgip->bpp == 1)
+ for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = (*gray++) * (*alpha++) / 255;
+ }
+ else
+ for (i = img->xsize - 1, gray = rows[0], alpha = rows[1], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = ((*gray++) / 256 + 128) * (*alpha++) / 32767;
+ }
+ break;
+ case 3 :
+ if (sgip->bpp == 1)
+ for (i = img->xsize - 1, red = rows[0], green = rows[1],
+ blue = rows[2], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = *red++;
+ *inptr++ = *green++;
+ *inptr++ = *blue++;
+ }
+ else
+ for (i = img->xsize - 1, red = rows[0], green = rows[1],
+ blue = rows[2], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = (*red++) / 256 + 128;
+ *inptr++ = (*green++) / 256 + 128;
+ *inptr++ = (*blue++) / 256 + 128;
+ }
+ break;
+ case 4 :
+ if (sgip->bpp == 1)
+ for (i = img->xsize - 1, red = rows[0], green = rows[1],
+ blue = rows[2], alpha = rows[3], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = (*red++) * (*alpha) / 255;
+ *inptr++ = (*green++) * (*alpha) / 255;
+ *inptr++ = (*blue++) * (*alpha++) / 255;
+ }
+ else
+ for (i = img->xsize - 1, red = rows[0], green = rows[1],
+ blue = rows[2], alpha = rows[3], inptr = in;
+ i >= 0;
+ i --)
+ {
+ *inptr++ = ((*red++) / 256 + 128) * (*alpha) / 32767;
+ *inptr++ = ((*green++) / 256 + 128) * (*alpha) / 32767;
+ *inptr++ = ((*blue++) / 256 + 128) * (*alpha++) / 32767;
+ }
+ break;
+ }
+
+ if (sgip->zsize < 3)
+ {
+ if (img->colorspace == IMAGE_WHITE)
+ {
+ if (lut)
+ ImageLut(in, img->xsize, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ else
+ {
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+
+ free(in);
+ free(out);
+ free(rows[0]);
+
+ sgiClose(sgip);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-sgi.h b/filter/image-sgi.h
new file mode 100644
index 000000000..ea125d75b
--- /dev/null
+++ b/filter/image-sgi.h
@@ -0,0 +1,96 @@
+/*
+ * "$Id$"
+ *
+ * SGI image file format library definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _SGI_H_
+# define _SGI_H_
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+/*
+ * Constants...
+ */
+
+# define SGI_MAGIC 474 /* Magic number in image file */
+
+# define SGI_READ 0 /* Read from an SGI image file */
+# define SGI_WRITE 1 /* Write to an SGI image file */
+
+# define SGI_COMP_NONE 0 /* No compression */
+# define SGI_COMP_RLE 1 /* Run-length encoding */
+# define SGI_COMP_ARLE 2 /* Agressive run-length encoding */
+
+
+/*
+ * Image structure...
+ */
+
+typedef struct
+{
+ FILE *file; /* Image file */
+ int mode, /* File open mode */
+ bpp, /* Bytes per pixel/channel */
+ comp; /* Compression */
+ unsigned short xsize, /* Width in pixels */
+ ysize, /* Height in pixels */
+ zsize; /* Number of channels */
+ long firstrow, /* File offset for first row */
+ nextrow, /* File offset for next row */
+ **table, /* Offset table for compression */
+ **length; /* Length table for compression */
+ unsigned short *arle_row; /* Advanced RLE compression buffer */
+ long arle_offset, /* Advanced RLE buffer offset */
+ arle_length; /* Advanced RLE buffer length */
+} sgi_t;
+
+
+/*
+ * Prototypes...
+ */
+
+extern int sgiClose(sgi_t *sgip);
+extern int sgiGetRow(sgi_t *sgip, unsigned short *row, int y, int z);
+extern sgi_t *sgiOpen(char *filename, int mode, int comp, int bpp,
+ int xsize, int ysize, int zsize);
+extern sgi_t *sgiOpenFile(FILE *file, int mode, int comp, int bpp,
+ int xsize, int ysize, int zsize);
+extern int sgiPutRow(sgi_t *sgip, unsigned short *row, int y, int z);
+
+# ifdef __cplusplus
+}
+# endif
+#endif /* !_SGI_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-sgilib.c b/filter/image-sgilib.c
new file mode 100644
index 000000000..b9de062e4
--- /dev/null
+++ b/filter/image-sgilib.c
@@ -0,0 +1,859 @@
+/*
+ * "$Id$"
+ *
+ * SGI image file format library routines for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * sgiClose() - Close an SGI image file.
+ * sgiGetRow() - Get a row of image data from a file.
+ * sgiOpen() - Open an SGI image file for reading or writing.
+ * sgiOpenFile() - Open an SGI image file for reading or writing.
+ * sgiPutRow() - Put a row of image data to a file.
+ * getlong() - Get a 32-bit big-endian integer.
+ * getshort() - Get a 16-bit big-endian integer.
+ * putlong() - Put a 32-bit big-endian integer.
+ * putshort() - Put a 16-bit big-endian integer.
+ * read_rle8() - Read 8-bit RLE data.
+ * read_rle16() - Read 16-bit RLE data.
+ * write_rle8() - Write 8-bit RLE data.
+ * write_rle16() - Write 16-bit RLE data.
+ */
+
+#include "image-sgi.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int getlong(FILE *);
+static int getshort(FILE *);
+static int putlong(long, FILE *);
+static int putshort(unsigned short, FILE *);
+static int read_rle8(FILE *, unsigned short *, int);
+static int read_rle16(FILE *, unsigned short *, int);
+static int write_rle8(FILE *, unsigned short *, int);
+static int write_rle16(FILE *, unsigned short *, int);
+
+
+/*
+ * 'sgiClose()' - Close an SGI image file.
+ */
+
+int
+sgiClose(sgi_t *sgip) /* I - SGI image */
+{
+ int i; /* Return status */
+ long *offset; /* Looping var for offset table */
+
+
+ if (sgip == NULL)
+ return (-1);
+
+ if (sgip->mode == SGI_WRITE && sgip->comp != SGI_COMP_NONE)
+ {
+ /*
+ * Write the scanline offset table to the file...
+ */
+
+ fseek(sgip->file, 512, SEEK_SET);
+
+ for (i = sgip->ysize * sgip->zsize, offset = sgip->table[0];
+ i > 0;
+ i --, offset ++)
+ if (putlong(offset[0], sgip->file) < 0)
+ return (-1);
+
+ for (i = sgip->ysize * sgip->zsize, offset = sgip->length[0];
+ i > 0;
+ i --, offset ++)
+ if (putlong(offset[0], sgip->file) < 0)
+ return (-1);
+ }
+
+ if (sgip->table != NULL)
+ {
+ free(sgip->table[0]);
+ free(sgip->table);
+ }
+
+ if (sgip->length != NULL)
+ {
+ free(sgip->length[0]);
+ free(sgip->length);
+ }
+
+ if (sgip->comp == SGI_COMP_ARLE)
+ free(sgip->arle_row);
+
+ i = fclose(sgip->file);
+ free(sgip);
+
+ return (i);
+}
+
+
+/*
+ * 'sgiGetRow()' - Get a row of image data from a file.
+ */
+
+int
+sgiGetRow(sgi_t *sgip, /* I - SGI image */
+ unsigned short *row, /* O - Row to read */
+ int y, /* I - Line to read */
+ int z) /* I - Channel to read */
+{
+ int x; /* X coordinate */
+ long offset; /* File offset */
+
+
+ if (sgip == NULL ||
+ row == NULL ||
+ y < 0 || y >= sgip->ysize ||
+ z < 0 || z >= sgip->zsize)
+ return (-1);
+
+ switch (sgip->comp)
+ {
+ case SGI_COMP_NONE :
+ /*
+ * Seek to the image row - optimize buffering by only seeking if
+ * necessary...
+ */
+
+ offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp;
+ if (offset != ftell(sgip->file))
+ fseek(sgip->file, offset, SEEK_SET);
+
+ if (sgip->bpp == 1)
+ {
+ for (x = sgip->xsize; x > 0; x --, row ++)
+ *row = getc(sgip->file);
+ }
+ else
+ {
+ for (x = sgip->xsize; x > 0; x --, row ++)
+ *row = getshort(sgip->file);
+ }
+ break;
+
+ case SGI_COMP_RLE :
+ offset = sgip->table[z][y];
+ if (offset != ftell(sgip->file))
+ fseek(sgip->file, offset, SEEK_SET);
+
+ if (sgip->bpp == 1)
+ return (read_rle8(sgip->file, row, sgip->xsize));
+ else
+ return (read_rle16(sgip->file, row, sgip->xsize));
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'sgiOpen()' - Open an SGI image file for reading or writing.
+ */
+
+sgi_t *
+sgiOpen(char *filename, /* I - File to open */
+ int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */
+ int comp, /* I - Type of compression */
+ int bpp, /* I - Bytes per pixel */
+ int xsize, /* I - Width of image in pixels */
+ int ysize, /* I - Height of image in pixels */
+ int zsize) /* I - Number of channels */
+{
+ sgi_t *sgip; /* New SGI image file */
+ FILE *file; /* Image file pointer */
+
+
+ if (mode == SGI_READ)
+ file = fopen(filename, "rb");
+ else
+ file = fopen(filename, "wb+");
+
+ if (file == NULL)
+ return (NULL);
+
+ if ((sgip = sgiOpenFile(file, mode, comp, bpp, xsize, ysize, zsize)) == NULL)
+ fclose(file);
+
+ return (sgip);
+}
+
+
+/*
+ * 'sgiOpenFile()' - Open an SGI image file for reading or writing.
+ */
+
+sgi_t *
+sgiOpenFile(FILE *file, /* I - File to open */
+ int mode, /* I - Open mode (SGI_READ or SGI_WRITE) */
+ int comp, /* I - Type of compression */
+ int bpp, /* I - Bytes per pixel */
+ int xsize, /* I - Width of image in pixels */
+ int ysize, /* I - Height of image in pixels */
+ int zsize) /* I - Number of channels */
+{
+ int i, j; /* Looping var */
+ char name[80]; /* Name of file in image header */
+ short magic; /* Magic number */
+ sgi_t *sgip; /* New image pointer */
+
+
+ if ((sgip = calloc(sizeof(sgi_t), 1)) == NULL)
+ return (NULL);
+
+ sgip->file = file;
+
+ switch (mode)
+ {
+ case SGI_READ :
+ sgip->mode = SGI_READ;
+
+ magic = getshort(sgip->file);
+ if (magic != SGI_MAGIC)
+ {
+ free(sgip);
+ return (NULL);
+ }
+
+ sgip->comp = getc(sgip->file);
+ sgip->bpp = getc(sgip->file);
+ getshort(sgip->file); /* Dimensions */
+ sgip->xsize = getshort(sgip->file);
+ sgip->ysize = getshort(sgip->file);
+ sgip->zsize = getshort(sgip->file);
+ getlong(sgip->file); /* Minimum pixel */
+ getlong(sgip->file); /* Maximum pixel */
+
+ if (sgip->comp)
+ {
+ /*
+ * This file is compressed; read the scanline tables...
+ */
+
+ fseek(sgip->file, 512, SEEK_SET);
+
+ sgip->table = calloc(sgip->zsize, sizeof(long *));
+ sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
+ for (i = 1; i < sgip->zsize; i ++)
+ sgip->table[i] = sgip->table[0] + i * sgip->ysize;
+
+ for (i = 0; i < sgip->zsize; i ++)
+ for (j = 0; j < sgip->ysize; j ++)
+ sgip->table[i][j] = getlong(sgip->file);
+ }
+ break;
+
+ case SGI_WRITE :
+ if (xsize < 1 ||
+ ysize < 1 ||
+ zsize < 1 ||
+ bpp < 1 || bpp > 2 ||
+ comp < SGI_COMP_NONE || comp > SGI_COMP_ARLE)
+ {
+ free(sgip);
+ return (NULL);
+ }
+
+ sgip->mode = SGI_WRITE;
+
+ putshort(SGI_MAGIC, sgip->file);
+ putc((sgip->comp = comp) != 0, sgip->file);
+ putc(sgip->bpp = bpp, sgip->file);
+ putshort(3, sgip->file); /* Dimensions */
+ putshort(sgip->xsize = xsize, sgip->file);
+ putshort(sgip->ysize = ysize, sgip->file);
+ putshort(sgip->zsize = zsize, sgip->file);
+ if (bpp == 1)
+ {
+ putlong(0, sgip->file); /* Minimum pixel */
+ putlong(255, sgip->file); /* Maximum pixel */
+ }
+ else
+ {
+ putlong(-32768, sgip->file); /* Minimum pixel */
+ putlong(32767, sgip->file); /* Maximum pixel */
+ }
+ putlong(0, sgip->file); /* Reserved */
+
+ memset(name, 0, sizeof(name));
+ fwrite(name, sizeof(name), 1, sgip->file);
+
+ for (i = 0; i < 102; i ++)
+ putlong(0, sgip->file);
+
+ switch (comp)
+ {
+ case SGI_COMP_NONE : /* No compression */
+ /*
+ * This file is uncompressed. To avoid problems with sparse files,
+ * we need to write blank pixels for the entire image...
+ */
+
+ if (bpp == 1)
+ {
+ for (i = xsize * ysize * zsize; i > 0; i --)
+ putc(0, sgip->file);
+ }
+ else
+ {
+ for (i = xsize * ysize * zsize; i > 0; i --)
+ putshort(0, sgip->file);
+ }
+ break;
+
+ case SGI_COMP_ARLE : /* Aggressive RLE */
+ sgip->arle_row = calloc(xsize, sizeof(unsigned short));
+ sgip->arle_offset = 0;
+
+ case SGI_COMP_RLE : /* Run-Length Encoding */
+ /*
+ * This file is compressed; write the (blank) scanline tables...
+ */
+
+ for (i = 2 * ysize * zsize; i > 0; i --)
+ putlong(0, sgip->file);
+
+ sgip->firstrow = ftell(sgip->file);
+ sgip->nextrow = ftell(sgip->file);
+ sgip->table = calloc(sgip->zsize, sizeof(long *));
+ sgip->table[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
+ for (i = 1; i < sgip->zsize; i ++)
+ sgip->table[i] = sgip->table[0] + i * sgip->ysize;
+ sgip->length = calloc(sgip->zsize, sizeof(long *));
+ sgip->length[0] = calloc(sgip->ysize * sgip->zsize, sizeof(long));
+ for (i = 1; i < sgip->zsize; i ++)
+ sgip->length[i] = sgip->length[0] + i * sgip->ysize;
+ break;
+ }
+ break;
+
+ default :
+ free(sgip);
+ return (NULL);
+ }
+
+ return (sgip);
+}
+
+
+/*
+ * 'sgiPutRow()' - Put a row of image data to a file.
+ */
+
+int
+sgiPutRow(sgi_t *sgip, /* I - SGI image */
+ unsigned short *row, /* I - Row to write */
+ int y, /* I - Line to write */
+ int z) /* I - Channel to write */
+{
+ int x; /* X coordinate */
+ long offset; /* File offset */
+
+
+ if (sgip == NULL ||
+ row == NULL ||
+ y < 0 || y >= sgip->ysize ||
+ z < 0 || z >= sgip->zsize)
+ return (-1);
+
+ switch (sgip->comp)
+ {
+ case SGI_COMP_NONE :
+ /*
+ * Seek to the image row - optimize buffering by only seeking if
+ * necessary...
+ */
+
+ offset = 512 + (y + z * sgip->ysize) * sgip->xsize * sgip->bpp;
+ if (offset != ftell(sgip->file))
+ fseek(sgip->file, offset, SEEK_SET);
+
+ if (sgip->bpp == 1)
+ {
+ for (x = sgip->xsize; x > 0; x --, row ++)
+ putc(*row, sgip->file);
+ }
+ else
+ {
+ for (x = sgip->xsize; x > 0; x --, row ++)
+ putshort(*row, sgip->file);
+ }
+ break;
+
+ case SGI_COMP_ARLE :
+ if (sgip->table[z][y] != 0)
+ return (-1);
+
+ /*
+ * First check the last row written...
+ */
+
+ if (sgip->arle_offset > 0)
+ {
+ for (x = 0; x < sgip->xsize; x ++)
+ if (row[x] != sgip->arle_row[x])
+ break;
+
+ if (x == sgip->xsize)
+ {
+ sgip->table[z][y] = sgip->arle_offset;
+ sgip->length[z][y] = sgip->arle_length;
+ return (0);
+ }
+ }
+
+ /*
+ * If that didn't match, search all the previous rows...
+ */
+
+ fseek(sgip->file, sgip->firstrow, SEEK_SET);
+
+ if (sgip->bpp == 1)
+ {
+ for (;;)
+ {
+ sgip->arle_offset = ftell(sgip->file);
+ if ((sgip->arle_length = read_rle8(sgip->file, sgip->arle_row, sgip->xsize)) < 0)
+ {
+ x = 0;
+ break;
+ }
+
+ if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0)
+ {
+ x = sgip->xsize;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ sgip->arle_offset = ftell(sgip->file);
+ if ((sgip->arle_length = read_rle16(sgip->file, sgip->arle_row, sgip->xsize)) < 0)
+ {
+ x = 0;
+ break;
+ }
+
+ if (memcmp(row, sgip->arle_row, sgip->xsize * sizeof(unsigned short)) == 0)
+ {
+ x = sgip->xsize;
+ break;
+ }
+ }
+ }
+
+ if (x == sgip->xsize)
+ {
+ sgip->table[z][y] = sgip->arle_offset;
+ sgip->length[z][y] = sgip->arle_length;
+ return (0);
+ }
+ else
+ fseek(sgip->file, 0, SEEK_END); /* Clear EOF */
+
+ case SGI_COMP_RLE :
+ if (sgip->table[z][y] != 0)
+ return (-1);
+
+ offset = sgip->table[z][y] = sgip->nextrow;
+
+ if (offset != ftell(sgip->file))
+ fseek(sgip->file, offset, SEEK_SET);
+
+ if (sgip->bpp == 1)
+ x = write_rle8(sgip->file, row, sgip->xsize);
+ else
+ x = write_rle16(sgip->file, row, sgip->xsize);
+
+ if (sgip->comp == SGI_COMP_ARLE)
+ {
+ sgip->arle_offset = offset;
+ sgip->arle_length = x;
+ memcpy(sgip->arle_row, row, sgip->xsize * sizeof(unsigned short));
+ }
+
+ sgip->nextrow = ftell(sgip->file);
+ sgip->length[z][y] = x;
+
+ return (x);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'getlong()' - Get a 32-bit big-endian integer.
+ */
+
+static int
+getlong(FILE *fp) /* I - File to read from */
+{
+ unsigned char b[4];
+
+
+ fread(b, 4, 1, fp);
+ return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
+}
+
+
+/*
+ * 'getshort()' - Get a 16-bit big-endian integer.
+ */
+
+static int
+getshort(FILE *fp) /* I - File to read from */
+{
+ unsigned char b[2];
+
+
+ fread(b, 2, 1, fp);
+ return ((b[0] << 8) | b[1]);
+}
+
+
+/*
+ * 'putlong()' - Put a 32-bit big-endian integer.
+ */
+
+static int
+putlong(long n, /* I - Long to write */
+ FILE *fp) /* I - File to write to */
+{
+ if (putc(n >> 24, fp) == EOF)
+ return (EOF);
+ if (putc(n >> 16, fp) == EOF)
+ return (EOF);
+ if (putc(n >> 8, fp) == EOF)
+ return (EOF);
+ if (putc(n, fp) == EOF)
+ return (EOF);
+ else
+ return (0);
+}
+
+
+/*
+ * 'putshort()' - Put a 16-bit big-endian integer.
+ */
+
+static int
+putshort(unsigned short n, /* I - Short to write */
+ FILE *fp) /* I - File to write to */
+{
+ if (putc(n >> 8, fp) == EOF)
+ return (EOF);
+ if (putc(n, fp) == EOF)
+ return (EOF);
+ else
+ return (0);
+}
+
+
+/*
+ * 'read_rle8()' - Read 8-bit RLE data.
+ */
+
+static int
+read_rle8(FILE *fp, /* I - File to read from */
+ unsigned short *row, /* O - Data */
+ int xsize) /* I - Width of data in pixels */
+{
+ int i, /* Looping var */
+ ch, /* Current character */
+ count, /* RLE count */
+ length; /* Number of bytes read... */
+
+
+ length = 0;
+
+ while (xsize > 0)
+ {
+ if ((ch = getc(fp)) == EOF)
+ return (-1);
+ length ++;
+
+ count = ch & 127;
+ if (count == 0)
+ break;
+
+ if (ch & 128)
+ {
+ for (i = 0; i < count; i ++, row ++, xsize --, length ++)
+ *row = getc(fp);
+ }
+ else
+ {
+ ch = getc(fp);
+ length ++;
+ for (i = 0; i < count; i ++, row ++, xsize --)
+ *row = ch;
+ }
+ }
+
+ return (xsize > 0 ? -1 : length);
+}
+
+
+/*
+ * 'read_rle16()' - Read 16-bit RLE data.
+ */
+
+static int
+read_rle16(FILE *fp, /* I - File to read from */
+ unsigned short *row, /* O - Data */
+ int xsize)/* I - Width of data in pixels */
+{
+ int i, /* Looping var */
+ ch, /* Current character */
+ count, /* RLE count */
+ length; /* Number of bytes read... */
+
+
+ length = 0;
+
+ while (xsize > 0)
+ {
+ if ((ch = getshort(fp)) == EOF)
+ return (-1);
+ length ++;
+
+ count = ch & 127;
+ if (count == 0)
+ break;
+
+ if (ch & 128)
+ {
+ for (i = 0; i < count; i ++, row ++, xsize --, length ++)
+ *row = getshort(fp);
+ }
+ else
+ {
+ ch = getshort(fp);
+ length ++;
+ for (i = 0; i < count; i ++, row ++, xsize --)
+ *row = ch;
+ }
+ }
+
+ return (xsize > 0 ? -1 : length * 2);
+}
+
+
+/*
+ * 'write_rle8()' - Write 8-bit RLE data.
+ */
+
+static int
+write_rle8(FILE *fp, /* I - File to write to */
+ unsigned short *row, /* I - Data */
+ int xsize)/* I - Width of data in pixels */
+{
+ int length,
+ count,
+ i,
+ x;
+ unsigned short *start,
+ repeat;
+
+
+ for (x = xsize, length = 0; x > 0;)
+ {
+ start = row;
+ row += 2;
+ x -= 2;
+
+ while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0]))
+ {
+ row ++;
+ x --;
+ }
+
+ row -= 2;
+ x += 2;
+
+ count = row - start;
+ while (count > 0)
+ {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ if (putc(128 | i, fp) == EOF)
+ return (-1);
+ length ++;
+
+ while (i > 0)
+ {
+ if (putc(*start, fp) == EOF)
+ return (-1);
+ start ++;
+ i --;
+ length ++;
+ }
+ }
+
+ if (x <= 0)
+ break;
+
+ start = row;
+ repeat = row[0];
+
+ row ++;
+ x --;
+
+ while (x > 0 && *row == repeat)
+ {
+ row ++;
+ x --;
+ }
+
+ count = row - start;
+ while (count > 0)
+ {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ if (putc(i, fp) == EOF)
+ return (-1);
+ length ++;
+
+ if (putc(repeat, fp) == EOF)
+ return (-1);
+ length ++;
+ }
+ }
+
+ length ++;
+
+ if (putc(0, fp) == EOF)
+ return (-1);
+ else
+ return (length);
+}
+
+
+/*
+ * 'write_rle16()' - Write 16-bit RLE data.
+ */
+
+static int
+write_rle16(FILE *fp, /* I - File to write to */
+ unsigned short *row, /* I - Data */
+ int xsize)/* I - Width of data in pixels */
+{
+ int length,
+ count,
+ i,
+ x;
+ unsigned short *start,
+ repeat;
+
+
+ for (x = xsize, length = 0; x > 0;)
+ {
+ start = row;
+ row += 2;
+ x -= 2;
+
+ while (x > 0 && (row[-2] != row[-1] || row[-1] != row[0]))
+ {
+ row ++;
+ x --;
+ }
+
+ row -= 2;
+ x += 2;
+
+ count = row - start;
+ while (count > 0)
+ {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ if (putshort(128 | i, fp) == EOF)
+ return (-1);
+ length ++;
+
+ while (i > 0)
+ {
+ if (putshort(*start, fp) == EOF)
+ return (-1);
+ start ++;
+ i --;
+ length ++;
+ }
+ }
+
+ if (x <= 0)
+ break;
+
+ start = row;
+ repeat = row[0];
+
+ row ++;
+ x --;
+
+ while (x > 0 && *row == repeat)
+ {
+ row ++;
+ x --;
+ }
+
+ count = row - start;
+ while (count > 0)
+ {
+ i = count > 126 ? 126 : count;
+ count -= i;
+
+ if (putshort(i, fp) == EOF)
+ return (-1);
+ length ++;
+
+ if (putshort(repeat, fp) == EOF)
+ return (-1);
+ length ++;
+ }
+ }
+
+ length ++;
+
+ if (putshort(0, fp) == EOF)
+ return (-1);
+ else
+ return (2 * length);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-sun.c b/filter/image-sun.c
new file mode 100644
index 000000000..1b9b820b6
--- /dev/null
+++ b/filter/image-sun.c
@@ -0,0 +1,399 @@
+/*
+ * "$Id$"
+ *
+ * Sun Raster image file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadSunRaster() - Read a SunRaster image file.
+ * read_unsigned() - Read a 32-bit unsigned integer.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+#define RAS_MAGIC 0x59a66a95
+
+ /* Sun supported ras_type's */
+#define RT_OLD 0 /* Raw pixrect image in 68000 byte order */
+#define RT_STANDARD 1 /* Raw pixrect image in 68000 byte order */
+#define RT_BYTE_ENCODED 2 /* Run-length compression of bytes */
+#define RT_FORMAT_RGB 3 /* XRGB or RGB instead of XBGR or BGR */
+#define RT_EXPERIMENTAL 0xffff /* Reserved for testing */
+
+ /* Sun registered ras_maptype's */
+#define RMT_RAW 2
+ /* Sun supported ras_maptype's */
+#define RMT_NONE 0 /* ras_maplength is expected to be 0 */
+#define RMT_EQUAL_RGB 1 /* red[ras_maplength/3],green[],blue[] */
+
+#define RAS_RLE 0x80
+
+/*
+ * NOTES:
+ * Each line of the image is rounded out to a multiple of 16 bits.
+ * This corresponds to the rounding convention used by the memory pixrect
+ * package (/usr/include/pixrect/memvar.h) of the SunWindows system.
+ * The ras_encoding field (always set to 0 by Sun's supported software)
+ * was renamed to ras_length in release 2.0. As a result, rasterfiles
+ * of type 0 generated by the old software claim to have 0 length; for
+ * compatibility, code reading rasterfiles must be prepared to compute the
+ * true length from the width, height, and depth fields.
+ */
+
+/*
+ * Local functions...
+ */
+
+static unsigned read_unsigned(FILE *fp);
+
+
+/*
+ * 'ImageReadSunRaster()' - Read a SunRaster image file.
+ */
+
+int /* O - Read status */
+ImageReadSunRaster(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary,/* I - Secondary choice for colorspace */
+ int saturation,/* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ int i, x, y,
+ bpp, /* Bytes per pixel */
+ scanwidth,
+ run_count,
+ run_value;
+ ib_t *in,
+ *out,
+ *scanline,
+ *scanptr,
+ *p,
+ bit;
+ unsigned ras_depth, /* depth (1, 8, or 24 bits) of pixel */
+ ras_type, /* type of file; see RT_* below */
+ ras_maplength; /* length (bytes) of following map */
+ unsigned char cmap[3][256]; /* colormap */
+
+
+ /*
+ * Read the header; we already know that this is a raster file (ImageOpen
+ * checks this) so we don't need to check the magic number again.
+ */
+
+ fputs("DEBUG: Reading Sun Raster image...\n", stderr);
+
+ read_unsigned(fp); /* Skip magic */
+ img->xsize = read_unsigned(fp);
+ img->ysize = read_unsigned(fp);
+ ras_depth = read_unsigned(fp);
+ /* ras_length */read_unsigned(fp);
+ ras_type = read_unsigned(fp);
+ /* ras_maptype*/read_unsigned(fp);
+ ras_maplength = read_unsigned(fp);
+
+ fprintf(stderr, "DEBUG: ras_width=%d, ras_height=%d, ras_depth=%d, ras_type=%d, ras_maplength=%d\n",
+ img->xsize, img->ysize, ras_depth, ras_type, ras_maplength);
+
+ if (ras_maplength > 768 ||
+ img->xsize == 0 || img->xsize > IMAGE_MAX_WIDTH ||
+ img->ysize == 0 || img->ysize > IMAGE_MAX_HEIGHT ||
+ ras_depth == 0 || ras_depth > 32)
+ {
+ fputs("ERROR: Raster image cannot be loaded!\n", stderr);
+ return (1);
+ }
+
+ if (ras_maplength > 0)
+ {
+ memset(cmap[0], 255, sizeof(cmap[0]));
+ memset(cmap[1], 0, sizeof(cmap[1]));
+ memset(cmap[2], 0, sizeof(cmap[2]));
+
+ fread(cmap[0], 1, ras_maplength / 3, fp);
+ fread(cmap[1], 1, ras_maplength / 3, fp);
+ fread(cmap[2], 1, ras_maplength / 3, fp);
+ }
+
+ /*
+ * Compute the width of each line and allocate memory as needed...
+ */
+
+ scanwidth = (img->xsize * ras_depth + 7) / 8;
+ if (scanwidth & 1)
+ scanwidth ++;
+
+ if (ras_depth < 24 && ras_maplength == 0)
+ {
+ img->colorspace = secondary;
+ in = malloc(img->xsize + 1);
+ }
+ else
+ {
+ img->colorspace = (primary == IMAGE_RGB_CMYK) ? IMAGE_RGB : primary;
+ in = malloc(img->xsize * 3 + 1);
+ }
+
+ bpp = ImageGetDepth(img);
+ out = malloc(img->xsize * bpp);
+ scanline = malloc(scanwidth);
+ run_count = 0;
+ run_value = 0;
+
+ fprintf(stderr, "DEBUG: bpp=%d, scanwidth=%d\n", bpp, scanwidth);
+
+ for (y = 0; y < img->ysize; y ++)
+ {
+ if (ras_depth != 8 || ras_maplength > 0)
+ p = scanline;
+ else
+ p = in;
+
+ if (ras_type != RT_BYTE_ENCODED)
+ fread(p, scanwidth, 1, fp);
+ else
+ {
+ for (i = scanwidth; i > 0; i --, p ++)
+ {
+ if (run_count > 0)
+ {
+ *p = run_value;
+ run_count --;
+ }
+ else
+ {
+ run_value = getc(fp);
+
+ if (run_value == RAS_RLE)
+ {
+ run_count = getc(fp);
+ if (run_count == 0)
+ *p = RAS_RLE;
+ else
+ run_value = *p = getc(fp);
+ }
+ else
+ *p = run_value;
+ }
+ }
+ }
+
+ if (ras_depth == 1 && ras_maplength == 0)
+ {
+ /*
+ * 1-bit B&W image...
+ */
+
+ for (x = img->xsize, bit = 128, scanptr = scanline, p = in;
+ x > 0;
+ x --, p ++)
+ {
+ if (*scanptr & bit)
+ *p = 255;
+ else
+ *p = 0;
+
+ if (bit > 1)
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ else
+ bit >>= 1;
+ }
+ }
+ else if (ras_depth == 1)
+ {
+ /*
+ * 1-bit colormapped image...
+ */
+
+ for (x = img->xsize, bit = 128, scanptr = scanline, p = in;
+ x > 0;
+ x --)
+ {
+ if (*scanptr & bit)
+ {
+ *p++ = cmap[0][1];
+ *p++ = cmap[1][1];
+ *p++ = cmap[2][1];
+ }
+ else
+ {
+ *p++ = cmap[0][0];
+ *p++ = cmap[1][0];
+ *p++ = cmap[2][0];
+ }
+
+ if (bit > 1)
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ else
+ bit >>= 1;
+ }
+ }
+ else if (ras_depth == 8 && ras_maplength > 0)
+ {
+ /*
+ * 8-bit colormapped image.
+ */
+
+ for (x = img->xsize, scanptr = scanline, p = in;
+ x > 0;
+ x --)
+ {
+ *p++ = cmap[0][*scanptr];
+ *p++ = cmap[1][*scanptr];
+ *p++ = cmap[2][*scanptr++];
+ }
+ }
+ else if (ras_depth == 24 && ras_type != RT_FORMAT_RGB)
+ {
+ /*
+ * Convert BGR to RGB...
+ */
+
+ for (x = img->xsize, scanptr = scanline, p = in;
+ x > 0;
+ x --, scanptr += 3)
+ {
+ *p++ = scanptr[2];
+ *p++ = scanptr[1];
+ *p++ = scanptr[0];
+ }
+ }
+
+ if (ras_depth <= 8 && ras_maplength == 0)
+ {
+ if (img->colorspace == IMAGE_WHITE)
+ {
+ if (lut)
+ ImageLut(in, img->xsize, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ else
+ {
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (saturation != 100 || hue != 0)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+
+ free(scanline);
+ free(in);
+ free(out);
+
+ fclose(fp);
+
+ return (0);
+}
+
+
+/*
+ * 'read_unsigned()' - Read a 32-bit unsigned integer.
+ */
+
+static unsigned /* O - Integer from file */
+read_unsigned(FILE *fp) /* I - File to read from */
+{
+ unsigned v; /* Integer from file */
+
+
+ v = getc(fp);
+ v = (v << 8) | getc(fp);
+ v = (v << 8) | getc(fp);
+ v = (v << 8) | getc(fp);
+
+ return (v);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-tiff.c b/filter/image-tiff.c
new file mode 100644
index 000000000..e3a6a6937
--- /dev/null
+++ b/filter/image-tiff.c
@@ -0,0 +1,1743 @@
+/*
+ * "$Id$"
+ *
+ * TIFF file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageReadTIFF() - Read a TIFF image file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+#ifdef HAVE_LIBTIFF
+# include <tiff.h> /* TIFF image definitions */
+# include <tiffio.h>
+# include <unistd.h>
+
+
+/*
+ * 'ImageReadTIFF()' - Read a TIFF image file.
+ */
+
+int /* O - Read status */
+ImageReadTIFF(image_t *img, /* IO - Image */
+ FILE *fp, /* I - Image file */
+ int primary, /* I - Primary choice for colorspace */
+ int secondary, /* I - Secondary choice for colorspace */
+ int saturation, /* I - Color saturation (%) */
+ int hue, /* I - Color hue (degrees) */
+ const ib_t *lut) /* I - Lookup table for gamma/brightness */
+{
+ TIFF *tif; /* TIFF file */
+ uint32 width, height; /* Size of image */
+ uint16 photometric, /* Colorspace */
+ compression, /* Type of compression */
+ orientation, /* Orientation */
+ resunit, /* Units for resolution */
+ samples, /* Number of samples/pixel */
+ bits, /* Number of bits/pixel */
+ inkset, /* Ink set for color separations */
+ numinks; /* Number of inks in set */
+ float xres, /* Horizontal resolution */
+ yres; /* Vertical resolution */
+ uint16 *redcmap, /* Red colormap information */
+ *greencmap, /* Green colormap information */
+ *bluecmap; /* Blue colormap information */
+ int c, /* Color index */
+ num_colors, /* Number of colors */
+ bpp, /* Bytes per pixel */
+ x, y, /* Current x & y */
+ row, /* Current row in image */
+ xstart, ystart, /* Starting x & y */
+ xdir, ydir, /* X & y direction */
+ xcount, ycount, /* X & Y counters */
+ pstep, /* Pixel step (= bpp or -2 * bpp) */
+ scanwidth, /* Width of scanline */
+ r, g, b, k, /* Red, green, blue, and black values */
+ alpha; /* Image includes alpha? */
+ ib_t *in, /* Input buffer */
+ *out, /* Output buffer */
+ *p, /* Pointer into buffer */
+ *scanline, /* Scanline buffer */
+ *scanptr, /* Pointer into scanline buffer */
+ bit, /* Current bit */
+ pixel, /* Current pixel */
+ zero, /* Zero value (bitmaps) */
+ one; /* One value (bitmaps) */
+
+
+ /*
+ * Open the TIFF file and get the required parameters...
+ */
+
+ lseek(fileno(fp), 0, SEEK_SET); /* Work around "feature" in some stdio's */
+
+ if ((tif = TIFFFdOpen(fileno(fp), "", "r")) == NULL)
+ {
+ fputs("ERROR: TIFFFdOpen() failed!\n", stderr);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width))
+ {
+ fputs("ERROR: No image width tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
+ {
+ fputs("ERROR: No image height tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
+ {
+ fputs("ERROR: No photometric tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression))
+ {
+ fputs("ERROR: No compression tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples))
+ samples = 1;
+
+ if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
+ bits = 1;
+
+ /*
+ * Get the image orientation...
+ */
+
+ if (!TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation))
+ orientation = 0;
+
+ /*
+ * Get the image resolution...
+ */
+
+ if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) &&
+ TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) &&
+ TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit))
+ {
+ if (resunit == RESUNIT_INCH)
+ {
+ img->xppi = xres;
+ img->yppi = yres;
+ }
+ else if (resunit == RESUNIT_CENTIMETER)
+ {
+ img->xppi = xres * 2.54;
+ img->yppi = yres * 2.54;
+ }
+ else
+ {
+ img->xppi = 128;
+ img->yppi = 128;
+ }
+
+ if (img->xppi == 0 || img->yppi == 0)
+ {
+ fputs("ERROR: Bad TIFF resolution.\n", stderr);
+ img->xppi = img->yppi = 128;
+ }
+
+ fprintf(stderr, "DEBUG: TIFF resolution = %fx%f, units=%d\n",
+ xres, yres, resunit);
+ fprintf(stderr, "DEBUG: Stored resolution = %dx%d PPI\n",
+ img->xppi, img->yppi);
+ }
+
+ /*
+ * See if the image has an alpha channel...
+ */
+
+ if (samples == 2 || (samples == 4 && photometric == PHOTOMETRIC_RGB))
+ alpha = 1;
+ else
+ alpha = 0;
+
+ /*
+ * Check the size of the image...
+ */
+
+ if (width == 0 || width > IMAGE_MAX_WIDTH ||
+ height == 0 || height > IMAGE_MAX_HEIGHT ||
+ (bits != 1 && bits != 2 && bits != 4 && bits != 8) ||
+ samples < 1 || samples > 4)
+ {
+ fprintf(stderr, "ERROR: Bad TIFF dimensions %ux%ux%ux%u!\n",
+ (unsigned)width, (unsigned)height, (unsigned)bits,
+ (unsigned)samples);
+ TIFFClose(tif);
+ fclose(fp);
+ return (1);
+ }
+
+ /*
+ * Setup the image size and colorspace...
+ */
+
+ img->xsize = width;
+ img->ysize = height;
+ if (photometric == PHOTOMETRIC_MINISBLACK ||
+ photometric == PHOTOMETRIC_MINISWHITE)
+ img->colorspace = secondary;
+ else if (photometric == PHOTOMETRIC_SEPARATED && primary == IMAGE_RGB_CMYK)
+ img->colorspace = IMAGE_CMYK;
+ else if (primary == IMAGE_RGB_CMYK)
+ img->colorspace = IMAGE_RGB;
+ else
+ img->colorspace = primary;
+
+ fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
+
+ bpp = ImageGetDepth(img);
+
+ ImageSetMaxTiles(img, 0);
+
+ /*
+ * Set the X & Y start and direction according to the image orientation...
+ */
+
+ switch (orientation)
+ {
+ case ORIENTATION_TOPRIGHT :
+ fputs("DEBUG: orientation = top-right\n", stderr);
+ break;
+ case ORIENTATION_RIGHTTOP :
+ fputs("DEBUG: orientation = right-top\n", stderr);
+ break;
+ default :
+ case ORIENTATION_TOPLEFT :
+ fputs("DEBUG: orientation = top-left\n", stderr);
+ break;
+ case ORIENTATION_LEFTTOP :
+ fputs("DEBUG: orientation = left-top\n", stderr);
+ break;
+ case ORIENTATION_BOTLEFT :
+ fputs("DEBUG: orientation = bottom-left\n", stderr);
+ break;
+ case ORIENTATION_LEFTBOT :
+ fputs("DEBUG: orientation = left-bottom\n", stderr);
+ break;
+ case ORIENTATION_BOTRIGHT :
+ fputs("DEBUG: orientation = bottom-right\n", stderr);
+ break;
+ case ORIENTATION_RIGHTBOT :
+ fputs("DEBUG: orientation = right-bottom\n", stderr);
+ break;
+ }
+
+ switch (orientation)
+ {
+ case ORIENTATION_TOPRIGHT :
+ case ORIENTATION_RIGHTTOP :
+ xstart = img->xsize - 1;
+ xdir = -1;
+ ystart = 0;
+ ydir = 1;
+ break;
+ default :
+ case ORIENTATION_TOPLEFT :
+ case ORIENTATION_LEFTTOP :
+ xstart = 0;
+ xdir = 1;
+ ystart = 0;
+ ydir = 1;
+ break;
+ case ORIENTATION_BOTLEFT :
+ case ORIENTATION_LEFTBOT :
+ xstart = 0;
+ xdir = 1;
+ ystart = img->ysize - 1;
+ ydir = -1;
+ break;
+ case ORIENTATION_BOTRIGHT :
+ case ORIENTATION_RIGHTBOT :
+ xstart = img->xsize - 1;
+ xdir = -1;
+ ystart = img->ysize - 1;
+ ydir = -1;
+ break;
+ }
+
+ /*
+ * Allocate a scanline buffer...
+ */
+
+ scanwidth = TIFFScanlineSize(tif);
+ scanline = _TIFFmalloc(scanwidth);
+
+ /*
+ * Allocate input and output buffers...
+ */
+
+ if (orientation < ORIENTATION_LEFTTOP)
+ {
+ if (samples > 1 || photometric == PHOTOMETRIC_PALETTE)
+ pstep = xdir * 3;
+ else
+ pstep = xdir;
+
+ in = malloc(img->xsize * 3 + 3);
+ out = malloc(img->xsize * bpp);
+ }
+ else
+ {
+ if (samples > 1 || photometric == PHOTOMETRIC_PALETTE)
+ pstep = ydir * 3;
+ else
+ pstep = ydir;
+
+ in = malloc(img->ysize * 3 + 3);
+ out = malloc(img->ysize * bpp);
+ }
+
+ /*
+ * Read the image. This is greatly complicated by the fact that TIFF
+ * supports literally hundreds of different colorspaces and orientations,
+ * each which must be handled separately...
+ */
+
+ fprintf(stderr, "DEBUG: photometric = %d\n", photometric);
+ fprintf(stderr, "DEBUG: compression = %d\n", compression);
+
+ switch (photometric)
+ {
+ case PHOTOMETRIC_MINISWHITE :
+ case PHOTOMETRIC_MINISBLACK :
+ if (photometric == PHOTOMETRIC_MINISWHITE)
+ {
+ zero = 255;
+ one = 0;
+ }
+ else
+ {
+ zero = 0;
+ one = 255;
+ }
+
+ if (orientation < ORIENTATION_LEFTTOP)
+ {
+ /*
+ * Row major order...
+ */
+
+ for (y = ystart, ycount = img->ysize, row = 0;
+ ycount > 0;
+ ycount --, y += ydir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 128;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (*scanptr & bit)
+ *p = one;
+ else
+ *p = zero;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 0xc0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ pixel = *scanptr & bit;
+ while (pixel > 3)
+ pixel >>= 2;
+ *p = (255 * pixel / 3) ^ zero;
+
+ if (bit > 3)
+ bit >>= 2;
+ else
+ {
+ bit = 0xc0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart, bit = 0xf0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (bit == 0xf0)
+ {
+ *p = (255 * ((*scanptr & 0xf0) >> 4) / 15) ^ zero;
+ bit = 0x0f;
+ }
+ else
+ {
+ *p = (255 * (*scanptr & 0x0f) / 15) ^ zero;
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (xdir < 0 || zero || alpha)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ if (alpha)
+ {
+ if (zero)
+ {
+ for (xcount = img->xsize, p = in + xstart, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 2)
+ *p = (scanptr[1] * (255 - scanptr[0]) +
+ (255 - scanptr[1]) * 255) / 255;
+ }
+ else
+ {
+ for (xcount = img->xsize, p = in + xstart, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 2)
+ *p = (scanptr[1] * scanptr[0] +
+ (255 - scanptr[1]) * 255) / 255;
+ }
+ }
+ else
+ {
+ if (zero)
+ {
+ for (xcount = img->xsize, p = in + xstart, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr ++)
+ *p = 255 - *scanptr;
+ }
+ else
+ {
+ for (xcount = img->xsize, p = in + xstart, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr ++)
+ *p = *scanptr;
+ }
+ }
+ }
+ else
+ TIFFReadScanline(tif, in, row, 0);
+
+ if (img->colorspace == IMAGE_WHITE)
+ {
+ if (lut)
+ ImageLut(in, img->xsize, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Column major order...
+ */
+
+ for (x = xstart, xcount = img->xsize, row = 0;
+ xcount > 0;
+ xcount --, x += xdir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 128;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ if (*scanptr & bit)
+ *p = one;
+ else
+ *p = zero;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 0xc0;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ pixel = *scanptr & 0xc0;
+ while (pixel > 3)
+ pixel >>= 2;
+
+ *p = (255 * pixel / 3) ^ zero;
+
+ if (bit > 3)
+ bit >>= 2;
+ else
+ {
+ bit = 0xc0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart, bit = 0xf0;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ if (bit == 0xf0)
+ {
+ *p = (255 * ((*scanptr & 0xf0) >> 4) / 15) ^ zero;
+ bit = 0x0f;
+ }
+ else
+ {
+ *p = (255 * (*scanptr & 0x0f) / 15) ^ zero;
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (ydir < 0 || zero || alpha)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ if (alpha)
+ {
+ if (zero)
+ {
+ for (ycount = img->ysize, p = in + ystart, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += ydir, scanptr += 2)
+ *p = (scanptr[1] * (255 - scanptr[0]) +
+ (255 - scanptr[1]) * 255) / 255;
+ }
+ else
+ {
+ for (ycount = img->ysize, p = in + ystart, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += ydir, scanptr += 2)
+ *p = (scanptr[1] * scanptr[0] +
+ (255 - scanptr[1]) * 255) / 255;
+ }
+ }
+ else
+ {
+ if (zero)
+ {
+ for (ycount = img->ysize, p = in + ystart, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += ydir, scanptr ++)
+ *p = 255 - *scanptr;
+ }
+ else
+ {
+ for (ycount = img->ysize, p = in + ystart, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += ydir, scanptr ++)
+ *p = *scanptr;
+ }
+ }
+ }
+ else
+ TIFFReadScanline(tif, in, row, 0);
+
+ if (img->colorspace == IMAGE_WHITE)
+ {
+ if (lut)
+ ImageLut(in, img->ysize, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_RGB :
+ ImageWhiteToRGB(in, out, img->ysize);
+ break;
+ case IMAGE_BLACK :
+ ImageWhiteToBlack(in, out, img->ysize);
+ break;
+ case IMAGE_CMY :
+ ImageWhiteToCMY(in, out, img->ysize);
+ break;
+ case IMAGE_CMYK :
+ ImageWhiteToCMYK(in, out, img->ysize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->ysize * bpp, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, out);
+ }
+ }
+ }
+ break;
+
+ case PHOTOMETRIC_PALETTE :
+ if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &redcmap, &greencmap, &bluecmap))
+ {
+ fputs("ERROR: No colormap tag in the file!\n", stderr);
+ fclose(fp);
+ return (-1);
+ }
+
+ num_colors = 1 << bits;
+
+ for (c = 0; c < num_colors; c ++)
+ {
+ redcmap[c] >>= 8;
+ greencmap[c] >>= 8;
+ bluecmap[c] >>= 8;
+ }
+
+ if (orientation < ORIENTATION_LEFTTOP)
+ {
+ /*
+ * Row major order...
+ */
+
+ for (y = ystart, ycount = img->ysize, row = 0;
+ ycount > 0;
+ ycount --, y += ydir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline,
+ p = in + xstart * 3, bit = 128;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (*scanptr & bit)
+ {
+ p[0] = redcmap[1];
+ p[1] = greencmap[1];
+ p[2] = bluecmap[1];
+ }
+ else
+ {
+ p[0] = redcmap[0];
+ p[1] = greencmap[0];
+ p[2] = bluecmap[0];
+ }
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline,
+ p = in + xstart * 3, bit = 0xc0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ pixel = *scanptr & bit;
+ while (pixel > 3)
+ pixel >>= 2;
+
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+
+ if (bit > 3)
+ bit >>= 2;
+ else
+ {
+ bit = 0xc0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline,
+ p = in + 3 * xstart, bit = 0xf0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (bit == 0xf0)
+ {
+ pixel = (*scanptr & 0xf0) >> 4;
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+ bit = 0x0f;
+ }
+ else
+ {
+ pixel = *scanptr++ & 0x0f;
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+ bit = 0xf0;
+ }
+ }
+ }
+ else
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ for (xcount = img->xsize, p = in + 3 * xstart, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ p[0] = redcmap[*scanptr];
+ p[1] = greencmap[*scanptr];
+ p[2] = bluecmap[*scanptr++];
+ }
+ }
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Column major order...
+ */
+
+ for (x = xstart, xcount = img->xsize, row = 0;
+ xcount > 0;
+ xcount --, x += xdir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline,
+ p = in + 3 * ystart, bit = 128;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ if (*scanptr & bit)
+ {
+ p[0] = redcmap[1];
+ p[1] = greencmap[1];
+ p[2] = bluecmap[1];
+ }
+ else
+ {
+ p[0] = redcmap[0];
+ p[1] = greencmap[0];
+ p[2] = bluecmap[0];
+ }
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline,
+ p = in + 3 * ystart, bit = 0xc0;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ pixel = *scanptr & 0xc0;
+ while (pixel > 3)
+ pixel >>= 2;
+
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+
+ if (bit > 3)
+ bit >>= 2;
+ else
+ {
+ bit = 0xc0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline,
+ p = in + 3 * ystart, bit = 0xf0;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ if (bit == 0xf0)
+ {
+ pixel = (*scanptr & 0xf0) >> 4;
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+ bit = 0x0f;
+ }
+ else
+ {
+ pixel = *scanptr++ & 0x0f;
+ p[0] = redcmap[pixel];
+ p[1] = greencmap[pixel];
+ p[2] = bluecmap[pixel];
+ bit = 0xf0;
+ }
+ }
+ }
+ else
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ for (ycount = img->ysize, p = in + 3 * ystart, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += ydir)
+ {
+ p[0] = redcmap[*scanptr];
+ p[1] = greencmap[*scanptr];
+ p[2] = bluecmap[*scanptr++];
+ }
+ }
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->ysize * 3, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->ysize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->ysize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->ysize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->ysize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->ysize * bpp, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, out);
+ }
+ }
+ }
+ break;
+
+ case PHOTOMETRIC_RGB :
+ if (orientation < ORIENTATION_LEFTTOP)
+ {
+ /*
+ * Row major order...
+ */
+
+ for (y = ystart, ycount = img->ysize, row = 0;
+ ycount > 0;
+ ycount --, y += ydir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (*scanptr & bit & 0x88)
+ p[0] = 255;
+ else
+ p[0] = 0;
+
+ if (*scanptr & bit & 0x44)
+ p[1] = 255;
+ else
+ p[1] = 0;
+
+ if (*scanptr & bit & 0x22)
+ p[2] = 255;
+ else
+ p[2] = 0;
+
+ if (bit == 0xf0)
+ bit = 0x0f;
+ else
+ {
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3;
+ xcount > 0;
+ xcount --, p += pstep, scanptr ++)
+ {
+ pixel = *scanptr >> 2;
+ p[0] = 255 * (pixel & 3) / 3;
+ pixel >>= 2;
+ p[1] = 255 * (pixel & 3) / 3;
+ pixel >>= 2;
+ p[2] = 255 * (pixel & 3) / 3;
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3;
+ xcount > 0;
+ xcount -= 2, p += 2 * pstep, scanptr += 3)
+ {
+ pixel = scanptr[0];
+ p[1] = 255 * (pixel & 15) / 15;
+ pixel >>= 4;
+ p[0] = 255 * (pixel & 15) / 15;
+ pixel = scanptr[1];
+ p[2] = 255 * ((pixel >> 4) & 15) / 15;
+
+ if (xcount > 1)
+ {
+ p[pstep + 0] = 255 * (pixel & 15) / 15;
+ pixel = scanptr[2];
+ p[pstep + 2] = 255 * (pixel & 15) / 15;
+ pixel >>= 4;
+ p[pstep + 1] = 255 * (pixel & 15) / 15;
+ }
+ }
+ }
+ else if (xdir < 0 || alpha)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ if (alpha)
+ {
+ for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 4)
+ {
+ p[0] = (scanptr[0] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ p[1] = (scanptr[1] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ p[2] = (scanptr[2] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ }
+ }
+ else
+ {
+ for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 3)
+ {
+ p[0] = scanptr[0];
+ p[1] = scanptr[1];
+ p[2] = scanptr[2];
+ }
+ }
+ }
+ else
+ TIFFReadScanline(tif, in, row, 0);
+
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * bpp, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Column major order...
+ */
+
+ for (x = xstart, xcount = img->xsize, row = 0;
+ xcount > 0;
+ xcount --, x += xdir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3, bit = 0xf0;
+ ycount > 0;
+ ycount --, p += pstep)
+ {
+ if (*scanptr & bit & 0x88)
+ p[0] = 255;
+ else
+ p[0] = 0;
+
+ if (*scanptr & bit & 0x44)
+ p[1] = 255;
+ else
+ p[1] = 0;
+
+ if (*scanptr & bit & 0x22)
+ p[2] = 255;
+ else
+ p[2] = 0;
+
+ if (bit == 0xf0)
+ bit = 0x0f;
+ else
+ {
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3;
+ ycount > 0;
+ ycount --, p += pstep, scanptr ++)
+ {
+ pixel = *scanptr >> 2;
+ p[0] = 255 * (pixel & 3) / 3;
+ pixel >>= 2;
+ p[1] = 255 * (pixel & 3) / 3;
+ pixel >>= 2;
+ p[2] = 255 * (pixel & 3) / 3;
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + ystart * 3;
+ ycount > 0;
+ ycount -= 2, p += 2 * pstep, scanptr += 3)
+ {
+ pixel = scanptr[0];
+ p[1] = 255 * (pixel & 15) / 15;
+ pixel >>= 4;
+ p[0] = 255 * (pixel & 15) / 15;
+ pixel = scanptr[1];
+ p[2] = 255 * ((pixel >> 4) & 15) / 15;
+
+ if (ycount > 1)
+ {
+ p[pstep + 0] = 255 * (pixel & 15) / 15;
+ pixel = scanptr[2];
+ p[pstep + 2] = 255 * (pixel & 15) / 15;
+ pixel >>= 4;
+ p[pstep + 1] = 255 * (pixel & 15) / 15;
+ }
+ }
+ }
+ else if (ydir < 0 || alpha)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ if (alpha)
+ {
+ for (ycount = img->ysize, p = in + ystart * 3, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += pstep, scanptr += 4)
+ {
+ p[0] = (scanptr[0] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ p[1] = (scanptr[1] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ p[2] = (scanptr[2] * scanptr[3] + 255 * (255 - scanptr[3])) / 255;
+ }
+ }
+ else
+ {
+ for (ycount = img->ysize, p = in + ystart * 3, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += pstep, scanptr += 3)
+ {
+ p[0] = scanptr[0];
+ p[1] = scanptr[1];
+ p[2] = scanptr[2];
+ }
+ }
+ }
+ else
+ TIFFReadScanline(tif, in, row, 0);
+
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->ysize, saturation, hue);
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->ysize * 3, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, in);
+ }
+ else
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->ysize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->ysize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->ysize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->ysize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->ysize * bpp, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, out);
+ }
+ }
+ }
+ break;
+
+ case PHOTOMETRIC_SEPARATED :
+ inkset = INKSET_CMYK;
+ numinks = 4;
+
+#ifdef TIFFTAG_NUMBEROFINKS
+ if (!TIFFGetField(tif, TIFFTAG_INKSET, &inkset) &&
+ !TIFFGetField(tif, TIFFTAG_NUMBEROFINKS, &numinks))
+#else
+ if (!TIFFGetField(tif, TIFFTAG_INKSET, &inkset))
+#endif /* TIFFTAG_NUMBEROFINKS */
+ {
+ fputs("WARNING: No inkset or number-of-inks tag in the file!\n", stderr);
+ }
+
+ if (inkset == INKSET_CMYK || numinks == 4)
+ {
+ if (orientation < ORIENTATION_LEFTTOP)
+ {
+ /*
+ * Row major order...
+ */
+
+ for (y = ystart, ycount = img->ysize, row = 0;
+ ycount > 0;
+ ycount --, y += ydir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0;
+ xcount > 0;
+ xcount --, p += pstep)
+ {
+ if (*scanptr & bit & 0x11)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ if (*scanptr & bit & 0x88)
+ p[0] = 0;
+ else
+ p[0] = 255;
+
+ if (*scanptr & bit & 0x44)
+ p[1] = 0;
+ else
+ p[1] = 255;
+
+ if (*scanptr & bit & 0x22)
+ p[2] = 0;
+ else
+ p[2] = 255;
+ }
+
+ if (bit == 0xf0)
+ bit = 0x0f;
+ else
+ {
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3;
+ xcount > 0;
+ xcount --, p += pstep, scanptr ++)
+ {
+ pixel = *scanptr;
+ k = 255 * (pixel & 3) / 3;
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ pixel >>= 2;
+ b = 255 - 255 * (pixel & 3) / 3 - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+
+ pixel >>= 2;
+ g = 255 - 255 * (pixel & 3) / 3 - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ pixel >>= 2;
+ r = 255 - 255 * (pixel & 3) / 3 - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (xcount = img->xsize, scanptr = scanline, p = in + xstart * 3;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 2)
+ {
+ pixel = scanptr[1];
+ k = 255 * (pixel & 15) / 15;
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ pixel >>= 4;
+ b = 255 - 255 * (pixel & 15) / 15 - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+
+ pixel = scanptr[0];
+ g = 255 - 255 * (pixel & 15) / 15 - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ pixel >>= 4;
+ r = 255 - 255 * (pixel & 15) / 15 - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+ }
+ }
+ }
+ else if (img->colorspace == IMAGE_CMYK)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ ImagePutRow(img, 0, y, img->xsize, scanline);
+ }
+ else
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ for (xcount = img->xsize, p = in + xstart * 3, scanptr = scanline;
+ xcount > 0;
+ xcount --, p += pstep, scanptr += 4)
+ {
+ k = scanptr[3];
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ r = 255 - scanptr[0] - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+
+ g = 255 - scanptr[1] - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ b = 255 - scanptr[2] - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+ }
+ }
+ }
+
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->xsize, saturation, hue);
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, in);
+ }
+ else if (img->colorspace == IMAGE_WHITE)
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->xsize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->xsize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->xsize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->xsize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->xsize * 3, lut);
+
+ ImagePutRow(img, 0, y, img->xsize, out);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Column major order...
+ */
+
+ for (x = xstart, xcount = img->xsize, row = 0;
+ xcount > 0;
+ xcount --, x += xdir, row ++)
+ {
+ if (bits == 1)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3, bit = 0xf0;
+ ycount > 0;
+ ycount --, p += pstep)
+ {
+ if (*scanptr & bit & 0x11)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ if (*scanptr & bit & 0x88)
+ p[0] = 0;
+ else
+ p[0] = 255;
+
+ if (*scanptr & bit & 0x44)
+ p[1] = 0;
+ else
+ p[1] = 255;
+
+ if (*scanptr & bit & 0x22)
+ p[2] = 0;
+ else
+ p[2] = 255;
+ }
+
+ if (bit == 0xf0)
+ bit = 0x0f;
+ else
+ {
+ bit = 0xf0;
+ scanptr ++;
+ }
+ }
+ }
+ else if (bits == 2)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3;
+ ycount > 0;
+ ycount --, p += pstep, scanptr ++)
+ {
+ pixel = *scanptr;
+ k = 255 * (pixel & 3) / 3;
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ pixel >>= 2;
+ b = 255 - 255 * (pixel & 3) / 3 - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+
+ pixel >>= 2;
+ g = 255 - 255 * (pixel & 3) / 3 - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ pixel >>= 2;
+ r = 255 - 255 * (pixel & 3) / 3 - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+ }
+ }
+ }
+ else if (bits == 4)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ for (ycount = img->ysize, scanptr = scanline, p = in + xstart * 3;
+ ycount > 0;
+ ycount --, p += pstep, scanptr += 2)
+ {
+ pixel = scanptr[1];
+ k = 255 * (pixel & 15) / 15;
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ pixel >>= 4;
+ b = 255 - 255 * (pixel & 15) / 15 - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+
+ pixel = scanptr[0];
+ g = 255 - 255 * (pixel & 15) / 15 - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ pixel >>= 4;
+ r = 255 - 255 * (pixel & 15) / 15 - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+ }
+ }
+ }
+ else if (img->colorspace == IMAGE_CMYK)
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+ ImagePutCol(img, x, 0, img->ysize, scanline);
+ }
+ else
+ {
+ TIFFReadScanline(tif, scanline, row, 0);
+
+ for (ycount = img->ysize, p = in + xstart * 3, scanptr = scanline;
+ ycount > 0;
+ ycount --, p += pstep, scanptr += 4)
+ {
+ k = scanptr[3];
+ if (k == 255)
+ {
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ }
+ else
+ {
+ r = 255 - scanptr[0] - k;
+ if (r < 0)
+ p[0] = 0;
+ else if (r < 256)
+ p[0] = r;
+ else
+ p[0] = 255;
+
+ g = 255 - scanptr[1] - k;
+ if (g < 0)
+ p[1] = 0;
+ else if (g < 256)
+ p[1] = g;
+ else
+ p[1] = 255;
+
+ b = 255 - scanptr[2] - k;
+ if (b < 0)
+ p[2] = 0;
+ else if (b < 256)
+ p[2] = b;
+ else
+ p[2] = 255;
+ }
+ }
+ }
+
+ if ((saturation != 100 || hue != 0) && bpp > 1)
+ ImageRGBAdjust(in, img->ysize, saturation, hue);
+
+ if (img->colorspace == IMAGE_RGB)
+ {
+ if (lut)
+ ImageLut(in, img->ysize * 3, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, in);
+ }
+ else if (img->colorspace == IMAGE_WHITE)
+ {
+ switch (img->colorspace)
+ {
+ case IMAGE_WHITE :
+ ImageRGBToWhite(in, out, img->ysize);
+ break;
+ case IMAGE_BLACK :
+ ImageRGBToBlack(in, out, img->ysize);
+ break;
+ case IMAGE_CMY :
+ ImageRGBToCMY(in, out, img->ysize);
+ break;
+ case IMAGE_CMYK :
+ ImageRGBToCMYK(in, out, img->ysize);
+ break;
+ }
+
+ if (lut)
+ ImageLut(out, img->ysize * bpp, lut);
+
+ ImagePutCol(img, x, 0, img->ysize, out);
+ }
+ }
+ }
+
+ break;
+ }
+
+ default :
+ _TIFFfree(scanline);
+ free(in);
+ free(out);
+
+ TIFFClose(tif);
+ fputs("ERROR: Unknown TIFF photometric value!\n", stderr);
+ return (-1);
+ }
+
+ /*
+ * Free temporary buffers, close the TIFF file, and return.
+ */
+
+ _TIFFfree(scanline);
+ free(in);
+ free(out);
+
+ TIFFClose(tif);
+ return (0);
+}
+
+
+#endif /* HAVE_LIBTIFF */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image-zoom.c b/filter/image-zoom.c
new file mode 100644
index 000000000..eb3c84880
--- /dev/null
+++ b/filter/image-zoom.c
@@ -0,0 +1,335 @@
+/*
+ * "$Id$"
+ *
+ * Image zoom routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageZoomAlloc() - Allocate a pixel zoom record...
+ * ImageZoomFill() - Fill a zoom record with image data utilizing bilinear
+ * interpolation.
+ * ImageZoomQFill() - Fill a zoom record quickly using nearest-neighbor
+ * sampling.
+ * ImageZoomFree() - Free a zoom record...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * 'ZoomAlloc()' - Allocate a pixel zoom record...
+ */
+
+izoom_t *
+ImageZoomAlloc(image_t *img, /* I - Image to zoom */
+ int x0, /* I - Upper-lefthand corner */
+ int y0, /* I - ... */
+ int x1, /* I - Lower-righthand corner */
+ int y1, /* I - ... */
+ int xsize, /* I - Final width of image */
+ int ysize, /* I - Final height of image */
+ int rotated) /* I - Non-zero if image is rotated 90 degs */
+{
+ izoom_t *z; /* New zoom record */
+ int flip; /* Flip on X axis? */
+
+
+ if (xsize > IMAGE_MAX_WIDTH ||
+ ysize > IMAGE_MAX_HEIGHT ||
+ (x1 - x0) > IMAGE_MAX_WIDTH ||
+ (y1 - y0) > IMAGE_MAX_HEIGHT)
+ return (NULL); /* Protect against integer overflow */
+
+ if ((z = (izoom_t *)calloc(1, sizeof(izoom_t))) == NULL)
+ return (NULL);
+
+ z->img = img;
+ z->row = 0;
+ z->depth = ImageGetDepth(img);
+ z->rotated = rotated;
+
+ if (xsize < 0)
+ {
+ flip = 1;
+ xsize = -xsize;
+ }
+ else
+ {
+ flip = 0;
+ }
+
+ if (rotated)
+ {
+ z->xorig = x1;
+ z->yorig = y0;
+ z->width = y1 - y0 + 1;
+ z->height = x1 - x0 + 1;
+ z->xsize = xsize;
+ z->ysize = ysize;
+ z->xmod = z->width % z->xsize;
+ z->xstep = z->width / z->xsize;
+ z->xincr = 1;
+ z->ymod = z->height % z->ysize;
+ z->ystep = z->height / z->ysize;
+ z->yincr = 1;
+ z->instep = z->xstep * z->depth;
+ z->inincr = z->xincr * z->depth;
+
+ if (z->width < img->ysize)
+ z->xmax = z->width;
+ else
+ z->xmax = z->width - 1;
+
+ if (z->height < img->xsize)
+ z->ymax = z->height;
+ else
+ z->ymax = z->height - 1;
+ }
+ else
+ {
+ z->xorig = x0;
+ z->yorig = y0;
+ z->width = x1 - x0 + 1;
+ z->height = y1 - y0 + 1;
+ z->xsize = xsize;
+ z->ysize = ysize;
+ z->xmod = z->width % z->xsize;
+ z->xstep = z->width / z->xsize;
+ z->xincr = 1;
+ z->ymod = z->height % z->ysize;
+ z->ystep = z->height / z->ysize;
+ z->yincr = 1;
+ z->instep = z->xstep * z->depth;
+ z->inincr = z->xincr * z->depth;
+
+ if (z->width < img->xsize)
+ z->xmax = z->width;
+ else
+ z->xmax = z->width - 1;
+
+ if (z->height < img->ysize)
+ z->ymax = z->height;
+ else
+ z->ymax = z->height - 1;
+ }
+
+ if (flip)
+ {
+ z->instep = -z->instep;
+ z->inincr = -z->inincr;
+ }
+
+ if ((z->rows[0] = (ib_t *)malloc(z->xsize * z->depth)) == NULL)
+ {
+ free(z);
+ return (NULL);
+ }
+
+ if ((z->rows[1] = (ib_t *)malloc(z->xsize * z->depth)) == NULL)
+ {
+ free(z->rows[0]);
+ free(z);
+ return (NULL);
+ }
+
+ if ((z->in = (ib_t *)malloc(z->width * z->depth)) == NULL)
+ {
+ free(z->rows[0]);
+ free(z->rows[1]);
+ free(z);
+ return (NULL);
+ }
+
+ return (z);
+}
+
+
+/*
+ * 'ImageZoomFill()' - Fill a zoom record with image data utilizing bilinear
+ * interpolation.
+ */
+
+void
+ImageZoomFill(izoom_t *z, /* I - Zoom record to fill */
+ int iy) /* I - Zoom image row */
+{
+ ib_t *r, /* Row pointer */
+ *inptr; /* Pixel pointer */
+ int xerr0, /* X error counter */
+ xerr1; /* ... */
+ int ix,
+ x,
+ count,
+ z_depth,
+ z_xstep,
+ z_xincr,
+ z_instep,
+ z_inincr,
+ z_xmax,
+ z_xmod,
+ z_xsize;
+
+
+ if (iy > z->ymax)
+ iy = z->ymax;
+
+ z->row ^= 1;
+
+ z_depth = z->depth;
+ z_xsize = z->xsize;
+ z_xmax = z->xmax;
+ z_xmod = z->xmod;
+ z_xstep = z->xstep;
+ z_xincr = z->xincr;
+ z_instep = z->instep;
+ z_inincr = z->inincr;
+
+ if (z->rotated)
+ ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
+ else
+ ImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
+
+ if (z_inincr < 0)
+ inptr = z->in + (z->width - 1) * z_depth;
+ else
+ inptr = z->in;
+
+ for (x = z_xsize, xerr0 = z_xsize, xerr1 = 0, ix = 0, r = z->rows[z->row];
+ x > 0;
+ x --)
+ {
+ if (ix < z_xmax)
+ {
+ for (count = 0; count < z_depth; count ++)
+ *r++ = (inptr[count] * xerr0 + inptr[z_depth + count] * xerr1) / z_xsize;
+ }
+ else
+ {
+ for (count = 0; count < z_depth; count ++)
+ *r++ = inptr[count];
+ }
+
+ ix += z_xstep;
+ inptr += z_instep;
+ xerr0 -= z_xmod;
+ xerr1 += z_xmod;
+
+ if (xerr0 <= 0)
+ {
+ xerr0 += z_xsize;
+ xerr1 -= z_xsize;
+ ix += z_xincr;
+ inptr += z_inincr;
+ }
+ }
+}
+
+
+/*
+ * 'ImageZoomQFill()' - Fill a zoom record quickly using nearest-neighbor sampling.
+ */
+
+void
+ImageZoomQFill(izoom_t *z, /* I - Zoom record to fill */
+ int iy) /* I - Zoom image row */
+{
+ ib_t *r, /* Row pointer */
+ *inptr; /* Pixel pointer */
+ int xerr0; /* X error counter */
+ int ix,
+ x,
+ count,
+ z_depth,
+ z_xstep,
+ z_xincr,
+ z_instep,
+ z_inincr,
+ z_xmod,
+ z_xsize;
+
+
+ if (iy > z->ymax)
+ iy = z->ymax;
+
+ z->row ^= 1;
+
+ z_depth = z->depth;
+ z_xsize = z->xsize;
+ z_xmod = z->xmod;
+ z_xstep = z->xstep;
+ z_xincr = z->xincr;
+ z_instep = z->instep;
+ z_inincr = z->inincr;
+
+ if (z->rotated)
+ ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
+ else
+ ImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
+
+ if (z_inincr < 0)
+ inptr = z->in + (z->width - 1) * z_depth;
+ else
+ inptr = z->in;
+
+ for (x = z_xsize, xerr0 = z_xsize, ix = 0, r = z->rows[z->row];
+ x > 0;
+ x --)
+ {
+ for (count = 0; count < z_depth; count ++)
+ *r++ = inptr[count];
+
+ ix += z_xstep;
+ inptr += z_instep;
+ xerr0 -= z_xmod;
+
+ if (xerr0 <= 0)
+ {
+ xerr0 += z_xsize;
+ ix += z_xincr;
+ inptr += z_inincr;
+ }
+ }
+}
+
+
+/*
+ * 'ImageZoomFree()' - Free a zoom record...
+ */
+
+void
+ImageZoomFree(izoom_t *z) /* I - Zoom record to free */
+{
+ free(z->rows[0]);
+ free(z->rows[1]);
+ free(z->in);
+ free(z);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image.c b/filter/image.c
new file mode 100644
index 000000000..4a52a9ff0
--- /dev/null
+++ b/filter/image.c
@@ -0,0 +1,775 @@
+/*
+ * "$Id$"
+ *
+ * Base image support for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * ImageOpen() - Open an image file and read it into memory.
+ * ImageClose() - Close an image file.
+ * ImageSetMaxTiles() - Set the maximum number of tiles to cache.
+ * ImageGetCol() - Get a column of pixels from an image.
+ * ImageGetRow() - Get a row of pixels from an image.
+ * ImagePutCol() - Put a column of pixels to an image.
+ * ImagePutRow() - Put a row of pixels to an image.
+ * get_tile() - Get a cached tile.
+ * flush_tile() - Flush the least-recently-used tile in the cache.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+#include <unistd.h>
+#include <ctype.h>
+#include <math.h>
+#include <cups/cups.h>
+
+
+/*
+ * Local functions...
+ */
+
+static ib_t *get_tile(image_t *img, int x, int y);
+static void flush_tile(image_t *img);
+
+
+/*
+ * 'ImageOpen()' - Open an image file and read it into memory.
+ */
+
+image_t * /* O - New image */
+ImageOpen(char *filename, /* I - Filename of image */
+ int primary, /* I - Primary colorspace needed */
+ int secondary, /* I - Secondary colorspace if primary no good */
+ int saturation,/* I - Color saturation level */
+ int hue, /* I - Color hue adjustment */
+ const ib_t *lut) /* I - RGB gamma/brightness LUT */
+{
+ FILE *fp; /* File pointer */
+ unsigned char header[16], /* First 16 bytes of file */
+ header2[16]; /* Bytes 2048-2064 (PhotoCD) */
+ image_t *img; /* New image buffer */
+ int status; /* Status of load... */
+
+
+ fprintf(stderr, "DEBUG: ImageOpen(\"%s\", %d, %d, %d, %d, %p)\n",
+ filename ? filename : "(null)", primary, secondary,
+ saturation, hue, lut);
+
+ /*
+ * Range check...
+ */
+
+ if (filename == NULL)
+ {
+ fputs("ERROR: Image filename == NULL!\n", stderr);
+ return (NULL);
+ }
+
+ /*
+ * Figure out the file type...
+ */
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ {
+ perror("ERROR: Unable to open image file");
+ return (NULL);
+ }
+
+ if (fread(header, 1, sizeof(header), fp) == 0)
+ {
+ perror("ERROR: Unable to read image file header");
+
+ fclose(fp);
+ return (NULL);
+ }
+
+ fseek(fp, 2048, SEEK_SET);
+ memset(header2, 0, sizeof(header2));
+ fread(header2, 1, sizeof(header2), fp);
+ fseek(fp, 0, SEEK_SET);
+
+ /*
+ * Allocate memory...
+ */
+
+ img = calloc(sizeof(image_t), 1);
+
+ if (img == NULL)
+ {
+ perror("ERROR: Unable to allocate memory for image file");
+ fclose(fp);
+ return (NULL);
+ }
+
+ /*
+ * Load the image as appropriate...
+ */
+
+ img->max_ics = TILE_MINIMUM;
+ img->xppi = 128;
+ img->yppi = 128;
+
+ if (memcmp(header, "GIF87a", 6) == 0 ||
+ memcmp(header, "GIF89a", 6) == 0)
+ status = ImageReadGIF(img, fp, primary, secondary, saturation, hue, lut);
+ else if (memcmp(header, "BM", 2) == 0)
+ status = ImageReadBMP(img, fp, primary, secondary, saturation, hue, lut);
+ else if (header[0] == 0x01 && header[1] == 0xda)
+ status = ImageReadSGI(img, fp, primary, secondary, saturation, hue, lut);
+ else if (header[0] == 0x59 && header[1] == 0xa6 &&
+ header[2] == 0x6a && header[3] == 0x95)
+ status = ImageReadSunRaster(img, fp, primary, secondary, saturation, hue, lut);
+ else if (header[0] == 'P' && header[1] >= '1' && header[1] <= '6')
+ status = ImageReadPNM(img, fp, primary, secondary, saturation, hue, lut);
+ else if (memcmp(header2, "PCD_IPI", 7) == 0)
+ status = ImageReadPhotoCD(img, fp, primary, secondary, saturation, hue, lut);
+ else if (memcmp(header + 8, "\000\010", 2) == 0 ||
+ memcmp(header + 8, "\000\030", 2) == 0)
+ status = ImageReadPIX(img, fp, primary, secondary, saturation, hue, lut);
+#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
+ else if (memcmp(header, "\211PNG", 4) == 0)
+ status = ImageReadPNG(img, fp, primary, secondary, saturation, hue, lut);
+#endif /* HAVE_LIBPNG && HAVE_LIBZ */
+#ifdef HAVE_LIBJPEG
+ else if (memcmp(header, "\377\330\377", 3) == 0 && /* Start-of-Image */
+ header[3] >= 0xe0 && header[3] <= 0xef) /* APPn */
+ status = ImageReadJPEG(img, fp, primary, secondary, saturation, hue, lut);
+#endif /* HAVE_LIBJPEG */
+#ifdef HAVE_LIBTIFF
+ else if (memcmp(header, "MM", 2) == 0 ||
+ memcmp(header, "II", 2) == 0)
+ status = ImageReadTIFF(img, fp, primary, secondary, saturation, hue, lut);
+#endif /* HAVE_LIBTIFF */
+ else
+ {
+ fputs("ERROR: Unknown image file format!\n", stderr);
+ fclose(fp);
+ status = -1;
+ }
+
+ if (status)
+ {
+ free(img);
+ return (NULL);
+ }
+ else
+ return (img);
+}
+
+
+/*
+ * 'ImageClose()' - Close an image file.
+ */
+
+void
+ImageClose(image_t *img) /* I - Image to close */
+{
+ ic_t *current, /* Current cached tile */
+ *next; /* Next cached tile */
+
+
+ /*
+ * Wipe the tile cache file (if any)...
+ */
+
+ if (img->cachefile != NULL)
+ {
+ fprintf(stderr, "DEBUG: Closing and removing swap file \"%s\"...\n",
+ img->cachename);
+
+ fclose(img->cachefile);
+ unlink(img->cachename);
+ }
+
+ /*
+ * Free the image cache...
+ */
+
+ fputs("DEBUG: Freeing memory...\n", stderr);
+
+ for (current = img->first, next = NULL; current != NULL; current = next)
+ {
+ fprintf(stderr, "DEBUG: Freeing cache (%p, next = %p)...\n",
+ current, next);
+
+ next = current->next;
+ free(current);
+ }
+
+ /*
+ * Free the rest of memory...
+ */
+
+ if (img->tiles != NULL)
+ {
+ fprintf(stderr, "DEBUG: Freeing tiles (%p)...\n", img->tiles[0]);
+
+ free(img->tiles[0]);
+
+ fprintf(stderr, "DEBUG: Freeing tile pointers (%p)...\n", img->tiles);
+
+ free(img->tiles);
+ }
+
+ free(img);
+}
+
+
+/*
+ * 'ImageSetMaxTiles()' - Set the maximum number of tiles to cache.
+ *
+ * If the "max_tiles" argument is 0 then the maximum number of tiles is
+ * computed from the image size or the RIP_CACHE environment variable.
+ */
+
+void
+ImageSetMaxTiles(image_t *img, /* I - Image to set */
+ int max_tiles) /* I - Number of tiles to cache */
+{
+ int cache_size, /* Size of tile cache in bytes */
+ min_tiles, /* Minimum number of tiles to cache */
+ max_size; /* Maximum cache size in bytes */
+ char *cache_env, /* Cache size environment variable */
+ cache_units[255]; /* Cache size units */
+
+
+ min_tiles = max(TILE_MINIMUM,
+ 1 + max((img->xsize + TILE_SIZE - 1) / TILE_SIZE,
+ (img->ysize + TILE_SIZE - 1) / TILE_SIZE));
+
+ if (max_tiles == 0)
+ max_tiles = ((img->xsize + TILE_SIZE - 1) / TILE_SIZE) *
+ ((img->ysize + TILE_SIZE - 1) / TILE_SIZE);
+
+ cache_size = max_tiles * TILE_SIZE * TILE_SIZE * ImageGetDepth(img);
+
+ if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL)
+ {
+ switch (sscanf(cache_env, "%d%254s", &max_size, cache_units))
+ {
+ case 0 :
+ max_size = 32 * 1024 * 1024;
+ break;
+ case 1 :
+ max_size *= 4 * TILE_SIZE * TILE_SIZE;
+ break;
+ case 2 :
+ if (tolower(cache_units[0] & 255) == 'g')
+ max_size *= 1024 * 1024 * 1024;
+ else if (tolower(cache_units[0] & 255) == 'm')
+ max_size *= 1024 * 1024;
+ else if (tolower(cache_units[0] & 255) == 'k')
+ max_size *= 1024;
+ else if (tolower(cache_units[0] & 255) == 't')
+ max_size *= 4 * TILE_SIZE * TILE_SIZE;
+ break;
+ }
+ }
+ else
+ max_size = 32 * 1024 * 1024;
+
+ if (cache_size > max_size)
+ max_tiles = max_size / TILE_SIZE / TILE_SIZE / ImageGetDepth(img);
+
+ if (max_tiles < min_tiles)
+ max_tiles = min_tiles;
+
+ img->max_ics = max_tiles;
+
+ fprintf(stderr, "DEBUG: max_ics=%d...\n", img->max_ics);
+}
+
+
+/*
+ * 'ImageGetCol()' - Get a column of pixels from an image.
+ */
+
+int /* O - -1 on error, 0 on success */
+ImageGetCol(image_t *img, /* I - Image */
+ int x, /* I - Column */
+ int y, /* I - Start row */
+ int height, /* I - Column height */
+ ib_t *pixels) /* O - Pixel data */
+{
+ int bpp, /* Bytes per pixel */
+ twidth, /* Tile width */
+ count; /* Number of pixels to get */
+ const ib_t *ib; /* Pointer into tile */
+
+
+ if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize)
+ return (-1);
+
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((y + height) > img->ysize)
+ height = img->ysize - y;
+
+ if (height < 1)
+ return (-1);
+
+ bpp = ImageGetDepth(img);
+ twidth = bpp * (TILE_SIZE - 1);
+
+ while (height > 0)
+ {
+ ib = get_tile(img, x, y);
+
+ if (ib == NULL)
+ return (-1);
+
+ count = TILE_SIZE - (y & (TILE_SIZE - 1));
+ if (count > height)
+ count = height;
+
+ y += count;
+ height -= count;
+
+ for (; count > 0; count --, ib += twidth)
+ switch (bpp)
+ {
+ case 4 :
+ *pixels++ = *ib++;
+ case 3 :
+ *pixels++ = *ib++;
+ *pixels++ = *ib++;
+ case 1 :
+ *pixels++ = *ib++;
+ break;
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'ImageGetRow()' - Get a row of pixels from an image.
+ */
+
+int /* O - -1 on error, 0 on success */
+ImageGetRow(image_t *img, /* I - Image */
+ int x, /* I - Start column */
+ int y, /* I - Row */
+ int width, /* I - Width of row */
+ ib_t *pixels) /* O - Pixel data */
+{
+ int bpp, /* Bytes per pixel */
+ count; /* Number of pixels to get */
+ const ib_t *ib; /* Pointer to pixels */
+
+
+ if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize)
+ return (-1);
+
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+
+ if ((x + width) > img->xsize)
+ width = img->xsize - x;
+
+ if (width < 1)
+ return (-1);
+
+ bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace;
+
+ while (width > 0)
+ {
+ ib = get_tile(img, x, y);
+
+ if (ib == NULL)
+ return (-1);
+
+ count = TILE_SIZE - (x & (TILE_SIZE - 1));
+ if (count > width)
+ count = width;
+ memcpy(pixels, ib, count * bpp);
+ pixels += count * bpp;
+ x += count;
+ width -= count;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'ImagePutCol()' - Put a column of pixels to an image.
+ */
+
+int /* O - -1 on error, 0 on success */
+ImagePutCol(image_t *img, /* I - Image */
+ int x, /* I - Column */
+ int y, /* I - Start row */
+ int height, /* I - Column height */
+ const ib_t *pixels) /* I - Pixels to put */
+{
+ int bpp, /* Bytes per pixel */
+ twidth, /* Width of tile */
+ count; /* Number of pixels to put */
+ int tilex, /* Column within tile */
+ tiley; /* Row within tile */
+ ib_t *ib; /* Pointer to pixels in tile */
+
+
+ if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize)
+ return (-1);
+
+ if (y < 0)
+ {
+ height += y;
+ y = 0;
+ }
+
+ if ((y + height) > img->ysize)
+ height = img->ysize - y;
+
+ if (height < 1)
+ return (-1);
+
+ bpp = ImageGetDepth(img);
+ twidth = bpp * (TILE_SIZE - 1);
+ tilex = x / TILE_SIZE;
+ tiley = y / TILE_SIZE;
+
+ while (height > 0)
+ {
+ ib = get_tile(img, x, y);
+
+ if (ib == NULL)
+ return (-1);
+
+ img->tiles[tiley][tilex].dirty = 1;
+ tiley ++;
+
+ count = TILE_SIZE - (y & (TILE_SIZE - 1));
+ if (count > height)
+ count = height;
+
+ y += count;
+ height -= count;
+
+ for (; count > 0; count --, ib += twidth)
+ switch (bpp)
+ {
+ case 4 :
+ *ib++ = *pixels++;
+ case 3 :
+ *ib++ = *pixels++;
+ *ib++ = *pixels++;
+ case 1 :
+ *ib++ = *pixels++;
+ break;
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'ImagePutRow()' - Put a row of pixels to an image.
+ */
+
+int /* O - -1 on error, 0 on success */
+ImagePutRow(image_t *img, /* I - Image */
+ int x, /* I - Start column */
+ int y, /* I - Row */
+ int width, /* I - Row width */
+ const ib_t *pixels) /* I - Pixel data */
+{
+ int bpp, /* Bytes per pixel */
+ count; /* Number of pixels to put */
+ int tilex, /* Column within tile */
+ tiley; /* Row within tile */
+ ib_t *ib; /* Pointer to pixels in tile */
+
+
+ if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize)
+ return (-1);
+
+ if (x < 0)
+ {
+ width += x;
+ x = 0;
+ }
+
+ if ((x + width) > img->xsize)
+ width = img->xsize - x;
+
+ if (width < 1)
+ return (-1);
+
+ bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace;
+ tilex = x / TILE_SIZE;
+ tiley = y / TILE_SIZE;
+
+ while (width > 0)
+ {
+ ib = get_tile(img, x, y);
+
+ if (ib == NULL)
+ return (-1);
+
+ img->tiles[tiley][tilex].dirty = 1;
+
+ count = TILE_SIZE - (x & (TILE_SIZE - 1));
+ if (count > width)
+ count = width;
+ memcpy(ib, pixels, count * bpp);
+ pixels += count * bpp;
+ x += count;
+ width -= count;
+ tilex ++;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'get_tile()' - Get a cached tile.
+ */
+
+static ib_t * /* O - Pointer to tile or NULL */
+get_tile(image_t *img, /* I - Image */
+ int x, /* I - Column in image */
+ int y) /* I - Row in image */
+{
+ int bpp, /* Bytes per pixel */
+ tilex, /* Column within tile */
+ tiley, /* Row within tile */
+ xtiles, /* Number of tiles horizontally */
+ ytiles; /* Number of tiles vertically */
+ ic_t *ic; /* Cache pointer */
+ itile_t *tile; /* Tile pointer */
+
+
+ if (x >= img->xsize || y >= img->ysize)
+ {
+ fprintf(stderr, "ERROR: Internal image RIP error - %d,%d is outside of %dx%d\n",
+ x, y, img->xsize, img->ysize);
+ return (NULL);
+ }
+
+ if (img->tiles == NULL)
+ {
+ xtiles = (img->xsize + TILE_SIZE - 1) / TILE_SIZE;
+ ytiles = (img->ysize + TILE_SIZE - 1) / TILE_SIZE;
+
+ fprintf(stderr, "DEBUG: Creating tile array (%dx%d)\n", xtiles, ytiles);
+
+ img->tiles = calloc(sizeof(itile_t *), ytiles);
+ tile = calloc(sizeof(itile_t), xtiles * ytiles);
+
+ for (tiley = 0; tiley < ytiles; tiley ++)
+ {
+ img->tiles[tiley] = tile;
+ for (tilex = xtiles; tilex > 0; tilex --, tile ++)
+ tile->pos = -1;
+ }
+ }
+
+ bpp = ImageGetDepth(img);
+ tilex = x / TILE_SIZE;
+ tiley = y / TILE_SIZE;
+ x &= (TILE_SIZE - 1);
+ y &= (TILE_SIZE - 1);
+
+ tile = img->tiles[tiley] + tilex;
+
+ if ((ic = tile->ic) == NULL)
+ {
+ if (img->num_ics < img->max_ics)
+ {
+ ic = calloc(sizeof(ic_t) + bpp * TILE_SIZE * TILE_SIZE, 1);
+ ic->pixels = ((ib_t *)ic) + sizeof(ic_t);
+
+ img->num_ics ++;
+
+ fprintf(stderr, "DEBUG: Allocated cache tile %d (%p)...\n",
+ img->num_ics, ic);
+ }
+ else
+ {
+ fprintf(stderr, "DEBUG: Flushing old cache tile (%p)...\n",
+ img->first);
+
+ flush_tile(img);
+ ic = img->first;
+ }
+
+ ic->tile = tile;
+ tile->ic = ic;
+
+ if (tile->pos >= 0)
+ {
+ fprintf(stderr, "DEBUG: Loading cache tile from file position %ld...\n",
+ tile->pos);
+
+ if (ftell(img->cachefile) != tile->pos)
+ if (fseek(img->cachefile, tile->pos, SEEK_SET))
+ perror("get_tile:");
+
+ fread(ic->pixels, bpp, TILE_SIZE * TILE_SIZE, img->cachefile);
+ }
+ else
+ {
+ fputs("DEBUG: Clearing cache tile...\n", stderr);
+
+ memset(ic->pixels, 0, bpp * TILE_SIZE * TILE_SIZE);
+ }
+ }
+
+ if (ic == img->first)
+ {
+ if (ic->next != NULL)
+ ic->next->prev = NULL;
+
+ img->first = ic->next;
+ ic->next = NULL;
+ ic->prev = NULL;
+ }
+ else if (img->first == NULL)
+ img->first = ic;
+
+ if (ic != img->last)
+ {
+ /*
+ * Remove the cache entry from the list...
+ */
+
+ if (ic->prev != NULL)
+ ic->prev->next = ic->next;
+ if (ic->next != NULL)
+ ic->next->prev = ic->prev;
+
+ /*
+ * And add it to the end...
+ */
+
+ if (img->last != NULL)
+ img->last->next = ic;
+
+ ic->prev = img->last;
+ img->last = ic;
+ }
+
+ ic->next = NULL;
+
+ return (ic->pixels + bpp * (y * TILE_SIZE + x));
+}
+
+
+/*
+ * 'flush_tile()' - Flush the least-recently-used tile in the cache.
+ */
+
+static void
+flush_tile(image_t *img) /* I - Image */
+{
+ int fd; /* Cache file descriptor */
+ int bpp; /* Bytes per pixel */
+ itile_t *tile; /* Pointer to tile */
+
+
+ bpp = ImageGetDepth(img);
+ tile = img->first->tile;
+
+ if (!tile->dirty)
+ {
+ tile->ic = NULL;
+ return;
+ }
+
+ if (img->cachefile == NULL)
+ {
+ if ((fd = cupsTempFd(img->cachename, sizeof(img->cachename))) < 0)
+ {
+ perror("ERROR: Unable to create image swap file");
+ tile->ic = NULL;
+ tile->dirty = 0;
+ return;
+ }
+
+ fprintf(stderr, "DEBUG: Created swap file \"%s\"...\n", img->cachename);
+
+ if ((img->cachefile = fdopen(fd, "wb+")) == NULL)
+ {
+ perror("ERROR: Unable to create image swap file");
+ close(fd);
+ unlink(img->cachename);
+ tile->ic = NULL;
+ tile->dirty = 0;
+ return;
+ }
+ }
+
+ if (tile->pos >= 0)
+ {
+ if (ftell(img->cachefile) != tile->pos)
+ if (fseek(img->cachefile, tile->pos, SEEK_SET))
+ {
+ perror("ERROR: Unable to seek in swap file");
+ tile->ic = NULL;
+ tile->dirty = 0;
+ return;
+ }
+ }
+ else
+ {
+ if (fseek(img->cachefile, 0, SEEK_END))
+ {
+ perror("ERROR: Unable to append to swap file");
+ tile->ic = NULL;
+ tile->dirty = 0;
+ return;
+ }
+
+ tile->pos = ftell(img->cachefile);
+ }
+
+
+ if (fwrite(tile->ic->pixels, bpp, TILE_SIZE * TILE_SIZE, img->cachefile) < 1)
+ perror("ERROR: Unable to write tile to swap file");
+ else
+ fprintf(stderr, "DEBUG: Wrote tile at position %ld...\n", tile->pos);
+
+ tile->ic = NULL;
+ tile->dirty = 0;
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/image.h b/filter/image.h
new file mode 100644
index 000000000..e9df75e67
--- /dev/null
+++ b/filter/image.h
@@ -0,0 +1,249 @@
+/*
+ * "$Id$"
+ *
+ * Image library definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _IMAGE_H_
+# define _IMAGE_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <errno.h>
+# include <config.h>
+# include "raster.h"
+
+
+/*
+ * Maximum image dimensions that we can handle...
+ */
+
+# define IMAGE_MAX_WIDTH 0x07ffffff /* 2^27-1 to allow for 15-channel data */
+# define IMAGE_MAX_HEIGHT 0x7fffffff /* 2^31-1 */
+
+/*
+ * Colorspaces...
+ */
+
+# define IMAGE_CMYK -4 /* Cyan, magenta, yellow, and black */
+# define IMAGE_CMY -3 /* Cyan, magenta, and yellow */
+# define IMAGE_BLACK -1 /* Black */
+# define IMAGE_WHITE 1 /* White (luminance) */
+# define IMAGE_RGB 3 /* Red, green, and blue */
+# define IMAGE_RGB_CMYK 4 /* Use RGB or CMYK */
+
+/*
+ * Tile definitions...
+ */
+
+# define TILE_SIZE 256 /* 256x256 pixel tiles */
+# define TILE_MINIMUM 10 /* Minimum number of tiles */
+
+/*
+ * min/max/abs macros...
+ */
+
+#ifndef max
+# define max(a,b) ((a) > (b) ? (a) : (b))
+#endif /* !max */
+#ifndef min
+# define min(a,b) ((a) < (b) ? (a) : (b))
+#endif /* !min */
+#ifndef abs
+# define abs(a) ((a) < 0 ? -(a) : (a))
+#endif /* !abs */
+
+
+/*
+ * Image byte type...
+ */
+
+typedef unsigned char ib_t;
+
+/*
+ * Tile cache structure...
+ */
+
+typedef struct ic_str
+{
+ struct ic_str *prev, /* Previous tile in cache */
+ *next; /* Next tile in cache */
+ void *tile; /* Tile this is attached to */
+ ib_t *pixels; /* Pixel data */
+} ic_t;
+
+/*
+ * Tile structure...
+ */
+
+typedef struct
+{
+ int dirty; /* True if tile is dirty */
+ long pos; /* Position of tile on disk (-1 if not written) */
+ ic_t *ic; /* Pixel data */
+} itile_t;
+
+/*
+ * Image structure...
+ */
+
+typedef struct
+{
+ int colorspace; /* Colorspace of image */
+ unsigned xsize, /* Width of image in pixels */
+ ysize, /* Height of image in pixels */
+ xppi, /* X resolution in pixels-per-inch */
+ yppi, /* Y resolution in pixels-per-inch */
+ num_ics, /* Number of cached tiles */
+ max_ics; /* Maximum number of cached tiles */
+ itile_t **tiles; /* Tiles in image */
+ ic_t *first, /* First cached tile in image */
+ *last; /* Last cached tile in image */
+ FILE *cachefile; /* Tile cache file */
+ char cachename[256]; /* Tile cache filename */
+} image_t;
+
+/*
+ * Image row zooming structure...
+ */
+
+typedef struct
+{
+ image_t *img; /* Image to zoom */
+ unsigned xorig,
+ yorig,
+ width, /* Width of input area */
+ height, /* Height of input area */
+ depth, /* Number of bytes per pixel */
+ rotated, /* Non-zero if image needs to be rotated */
+ xsize, /* Width of output image */
+ ysize, /* Height of output image */
+ xmax, /* Maximum input image X position */
+ ymax, /* Maximum input image Y position */
+ xmod, /* Threshold for Bresenheim rounding */
+ ymod; /* ... */
+ int xstep, /* Amount to step for each pixel along X */
+ xincr,
+ instep, /* Amount to step pixel pointer along X */
+ inincr,
+ ystep, /* Amount to step for each pixel along Y */
+ yincr,
+ row; /* Current row */
+ ib_t *rows[2], /* Horizontally scaled pixel data */
+ *in; /* Unscaled input pixel data */
+} izoom_t;
+
+
+/*
+ * Basic image functions...
+ */
+
+extern image_t *ImageOpen(char *filename, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern void ImageClose(image_t *img);
+extern void ImageSetColorSpace(cups_cspace_t cs);
+extern void ImageSetMaxTiles(image_t *img, int max_tiles);
+extern void ImageSetProfile(float d, float g, float matrix[3][3]);
+
+#define ImageGetDepth(img) ((img)->colorspace < 0 ? -(img)->colorspace : (img)->colorspace)
+extern int ImageGetCol(image_t *img, int x, int y, int height, ib_t *pixels);
+extern int ImageGetRow(image_t *img, int x, int y, int width, ib_t *pixels);
+extern int ImagePutCol(image_t *img, int x, int y, int height, const ib_t *pixels);
+extern int ImagePutRow(image_t *img, int x, int y, int width, const ib_t *pixels);
+
+/*
+ * File formats...
+ */
+
+extern int ImageReadBMP(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadFPX(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadGIF(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadJPEG(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadPIX(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadPNG(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadPNM(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadPhotoCD(image_t *img, FILE *fp, int primary,
+ int secondary, int saturation, int hue,
+ const ib_t *lut);
+extern int ImageReadSGI(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+extern int ImageReadSunRaster(image_t *img, FILE *fp, int primary,
+ int secondary, int saturation, int hue,
+ const ib_t *lut);
+extern int ImageReadTIFF(image_t *img, FILE *fp, int primary, int secondary,
+ int saturation, int hue, const ib_t *lut);
+
+/*
+ * Colorspace conversions...
+ */
+
+extern void ImageWhiteToWhite(const ib_t *in, ib_t *out, int count);
+extern void ImageWhiteToRGB(const ib_t *in, ib_t *out, int count);
+extern void ImageWhiteToBlack(const ib_t *in, ib_t *out, int count);
+extern void ImageWhiteToCMY(const ib_t *in, ib_t *out, int count);
+extern void ImageWhiteToCMYK(const ib_t *in, ib_t *out, int count);
+
+extern void ImageRGBToWhite(const ib_t *in, ib_t *out, int count);
+extern void ImageRGBToRGB(const ib_t *in, ib_t *out, int count);
+extern void ImageRGBToBlack(const ib_t *in, ib_t *out, int count);
+extern void ImageRGBToCMY(const ib_t *in, ib_t *out, int count);
+extern void ImageRGBToCMYK(const ib_t *in, ib_t *out, int count);
+
+extern void ImageCMYKToWhite(const ib_t *in, ib_t *out, int count);
+extern void ImageCMYKToRGB(const ib_t *in, ib_t *out, int count);
+extern void ImageCMYKToBlack(const ib_t *in, ib_t *out, int count);
+extern void ImageCMYKToCMY(const ib_t *in, ib_t *out, int count);
+extern void ImageCMYKToCMYK(const ib_t *in, ib_t *out, int count);
+
+extern void ImageRGBAdjust(ib_t *pixels, int count, int saturation, int hue);
+
+extern void ImageLut(ib_t *pixels, int count, const ib_t *lut);
+
+/*
+ * Image scaling operations...
+ */
+
+extern izoom_t *ImageZoomAlloc(image_t *img, int x0, int y0, int x1, int y1,
+ int xsize, int ysize, int rotated);
+extern void ImageZoomFill(izoom_t *z, int iy);
+extern void ImageZoomQFill(izoom_t *z, int iy);
+extern void ImageZoomFree(izoom_t *z);
+
+
+#endif /* !_IMAGE_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/imagetops.c b/filter/imagetops.c
new file mode 100644
index 000000000..2ada2b27c
--- /dev/null
+++ b/filter/imagetops.c
@@ -0,0 +1,1031 @@
+/*
+ * "$Id$"
+ *
+ * Image file to PostScript filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry...
+ * ps_hex() - Print binary data as a series of hexadecimal numbers.
+ * ps_ascii85() - Print binary data as a series of base-85 numbers.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+#include "image.h"
+#include <math.h>
+
+
+/*
+ * Globals...
+ */
+
+int Flip = 0, /* Flip/mirror pages */
+ XPosition = 0, /* Horizontal position on page */
+ YPosition = 0, /* Vertical position on page */
+ Collate = 0, /* Collate copies? */
+ Copies = 1; /* Number of copies */
+
+
+/*
+ * Local functions...
+ */
+
+static void ps_hex(ib_t *, int, int);
+static void ps_ascii85(ib_t *, int, int);
+
+
+/*
+ * 'main()' - Main entry...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ image_t *img; /* Image to print */
+ float xprint, /* Printable area */
+ yprint,
+ xinches, /* Total size in inches */
+ yinches;
+ float xsize, /* Total size in points */
+ ysize,
+ xsize2,
+ ysize2;
+ float aspect; /* Aspect ratio */
+ int xpages, /* # x pages */
+ ypages, /* # y pages */
+ xpage, /* Current x page */
+ ypage, /* Current y page */
+ page; /* Current page number */
+ int x0, y0, /* Corners of the page in image coords */
+ x1, y1;
+ ib_t *row; /* Current row */
+ int y; /* Current Y coordinate in image */
+ int colorspace; /* Output colorspace */
+ int out_offset, /* Offset into output buffer */
+ out_length; /* Length of output buffer */
+ ppd_file_t *ppd; /* PPD file */
+ ppd_choice_t *choice; /* PPD option choice */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ const char *val; /* Option value */
+ int slowcollate; /* Collate copies the slow way */
+ float g; /* Gamma correction value */
+ float b; /* Brightness factor */
+ float zoom; /* Zoom facter */
+ int xppi, yppi; /* Pixels-per-inch */
+ int hue, sat; /* Hue and saturation adjustment */
+ int realcopies; /* Real copies being printed */
+ float left, top; /* Left and top of image */
+ char filename[1024]; /* Name of file to print */
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+ char curdate[255]; /* Current date string */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ fputs("ERROR: imagetops job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
+
+ /*
+ * Copy stdin as needed...
+ */
+
+ if (argc == 6)
+ {
+ int fd; /* File to write to */
+ char buffer[8192]; /* Buffer to read into */
+ int bytes; /* # of bytes to read */
+
+
+ if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
+ {
+ perror("ERROR: Unable to copy image file");
+ return (1);
+ }
+
+ fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
+ filename);
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ write(fd, buffer, bytes);
+
+ close(fd);
+ }
+ else
+ strlcpy(filename, argv[6], sizeof(filename));
+
+ /*
+ * Process command-line options and write the prolog...
+ */
+
+ zoom = 0.0;
+ xppi = 0;
+ yppi = 0;
+ hue = 0;
+ sat = 100;
+ g = 1.0;
+ b = 1.0;
+
+ Copies = atoi(argv[4]);
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ ppd = SetCommonOptions(num_options, options, 0);
+
+ if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
+ {
+ /*
+ * This IPP attribute is unnecessarily complicated...
+ *
+ * single-document, separate-documents-collated-copies, and
+ * single-document-new-sheet all require collated copies.
+ *
+ * separate-documents-uncollated-copies allows for uncollated copies.
+ */
+
+ Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
+ }
+
+ if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
+ strcasecmp(val, "True") == 0)
+ Collate = 1;
+
+ if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+ g = atoi(val) * 0.001f;
+
+ if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
+ b = atoi(val) * 0.01f;
+
+ if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
+ zoom = atoi(val) * 0.01;
+
+ if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
+ if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
+ yppi = xppi;
+
+ if ((val = cupsGetOption("position", num_options, options)) != NULL)
+ {
+ if (strcasecmp(val, "center") == 0)
+ {
+ XPosition = 0;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "top") == 0)
+ {
+ XPosition = 0;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "left") == 0)
+ {
+ XPosition = -1;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "right") == 0)
+ {
+ XPosition = 1;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "top-left") == 0)
+ {
+ XPosition = -1;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "top-right") == 0)
+ {
+ XPosition = 1;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "bottom") == 0)
+ {
+ XPosition = 0;
+ YPosition = -1;
+ }
+ else if (strcasecmp(val, "bottom-left") == 0)
+ {
+ XPosition = -1;
+ YPosition = -1;
+ }
+ else if (strcasecmp(val, "bottom-right") == 0)
+ {
+ XPosition = 1;
+ YPosition = -1;
+ }
+ }
+
+ if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
+ sat = atoi(val);
+
+ if ((val = cupsGetOption("hue", num_options, options)) != NULL)
+ hue = atoi(val);
+
+ if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
+ strcasecmp(val, "True") == 0)
+ Flip = 1;
+
+ /*
+ * Open the input image to print...
+ */
+
+ colorspace = ColorDevice ? IMAGE_RGB_CMYK : IMAGE_WHITE;
+
+ img = ImageOpen(filename, colorspace, IMAGE_WHITE, sat, hue, NULL);
+
+ if (argc == 6)
+ unlink(filename);
+
+ if (img == NULL)
+ {
+ fputs("ERROR: Unable to open image file for printing!\n", stderr);
+ ppdClose(ppd);
+ return (1);
+ }
+
+ colorspace = img->colorspace;
+
+ /*
+ * Scale as necessary...
+ */
+
+ if (zoom == 0.0 && xppi == 0)
+ {
+ xppi = img->xppi;
+ yppi = img->yppi;
+ }
+
+ if (yppi == 0)
+ yppi = xppi;
+
+ fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
+ xppi, yppi, zoom);
+
+ if (xppi > 0)
+ {
+ /*
+ * Scale the image as neccesary to match the desired pixels-per-inch.
+ */
+
+ if (Orientation & 1)
+ {
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ }
+
+ fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
+ xprint, yprint);
+
+ xinches = (float)img->xsize / (float)xppi;
+ yinches = (float)img->ysize / (float)yppi;
+
+ fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
+ xinches, yinches);
+
+ if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
+ {
+ xinches = xinches * atoi(val) / 100;
+ yinches = yinches * atoi(val) / 100;
+ }
+
+ if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+ cupsGetOption("landscape", num_options, options) == NULL)
+ {
+ /*
+ * Rotate the image if it will fit landscape but not portrait...
+ */
+
+ fputs("DEBUG: Auto orientation...\n", stderr);
+
+ if ((xinches > xprint || yinches > yprint) &&
+ xinches <= yprint && yinches <= xprint)
+ {
+ /*
+ * Rotate the image as needed...
+ */
+
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ Orientation = (Orientation + 1) & 3;
+ xsize = yprint;
+ yprint = xprint;
+ xprint = xsize;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Scale percentage of page size...
+ */
+
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ aspect = (float)img->yppi / (float)img->xppi;
+
+ fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
+ xprint, yprint);
+
+ fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
+ img->xppi, img->yppi, aspect);
+
+ xsize = xprint * zoom;
+ ysize = xsize * img->ysize / img->xsize / aspect;
+
+ if (ysize > (yprint * zoom))
+ {
+ ysize = yprint * zoom;
+ xsize = ysize * img->xsize * aspect / img->ysize;
+ }
+
+ xsize2 = yprint * zoom;
+ ysize2 = xsize2 * img->ysize / img->xsize / aspect;
+
+ if (ysize2 > (xprint * zoom))
+ {
+ ysize2 = xprint * zoom;
+ xsize2 = ysize2 * img->xsize * aspect / img->ysize;
+ }
+
+ fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
+ fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
+
+ if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+ cupsGetOption("landscape", num_options, options) == NULL)
+ {
+ /*
+ * Choose the rotation with the largest area, but prefer
+ * portrait if they are equal...
+ */
+
+ fputs("DEBUG: Auto orientation...\n", stderr);
+
+ if ((xsize * ysize) < (xsize2 * xsize2))
+ {
+ /*
+ * Do landscape orientation...
+ */
+
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ Orientation = 1;
+ xinches = xsize2;
+ yinches = ysize2;
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ /*
+ * Do portrait orientation...
+ */
+
+ fputs("DEBUG: Using portrait orientation...\n", stderr);
+
+ Orientation = 0;
+ xinches = xsize;
+ yinches = ysize;
+ }
+ }
+ else if (Orientation & 1)
+ {
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ xinches = xsize2;
+ yinches = ysize2;
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ fputs("DEBUG: Using portrait orientation...\n", stderr);
+
+ xinches = xsize;
+ yinches = ysize;
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ }
+ }
+
+ /*
+ * Compute the number of pages to print and the size of the image on each
+ * page...
+ */
+
+ xpages = ceil(xinches / xprint);
+ ypages = ceil(yinches / yprint);
+
+ xprint = xinches / xpages;
+ yprint = yinches / ypages;
+
+ fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
+ xpages, xprint, ypages, yprint);
+
+ /*
+ * Update the page size for custom sizes...
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
+ strcasecmp(choice->choice, "Custom") == 0)
+ {
+ float width, /* New width in points */
+ length; /* New length in points */
+ char s[255]; /* New custom page size... */
+
+
+ /*
+ * Use the correct width and length for the current orientation...
+ */
+
+ if (Orientation & 1)
+ {
+ width = yprint * 72.0;
+ length = xprint * 72.0;
+ }
+ else
+ {
+ width = xprint * 72.0;
+ length = yprint * 72.0;
+ }
+
+ /*
+ * Add margins to page size...
+ */
+
+ width += ppd->custom_margins[0] + ppd->custom_margins[2];
+ length += ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Enforce minimums...
+ */
+
+ if (width < ppd->custom_min[0])
+ width = ppd->custom_min[0];
+
+ if (length < ppd->custom_min[1])
+ length = ppd->custom_min[1];
+
+ fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
+ width / 72.0, length / 72.0);
+
+ /*
+ * Set the new custom size...
+ */
+
+ sprintf(s, "Custom.%.0fx%.0f", width, length);
+ ppdMarkOption(ppd, "PageSize", s);
+
+ /*
+ * Update page variables...
+ */
+
+ PageWidth = width;
+ PageLength = length;
+ PageLeft = ppd->custom_margins[0];
+ PageRight = width - ppd->custom_margins[2];
+ PageBottom = ppd->custom_margins[1];
+ PageTop = length - ppd->custom_margins[3];
+ }
+
+ /*
+ * See if we need to collate, and if so how we need to do it...
+ */
+
+ if (xpages == 1 && ypages == 1)
+ Collate = 0;
+
+ slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
+
+ if (Copies > 1 && !slowcollate)
+ {
+ realcopies = Copies;
+ Copies = 1;
+ }
+ else
+ realcopies = 1;
+
+ /*
+ * Write any "exit server" options that have been selected...
+ */
+
+ ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
+
+ /*
+ * Write any JCL commands that are needed to print PostScript code...
+ */
+
+ ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
+
+ /*
+ * Start sending the document with any commands needed...
+ */
+
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+
+ puts("%!PS-Adobe-3.0");
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
+ PageRight, PageTop);
+ printf("%%%%LanguageLevel: %d\n", LanguageLevel);
+ printf("%%%%Pages: %d\n", xpages * ypages * Copies);
+ puts("%%DocumentData: Clean7Bit");
+ puts("%%DocumentNeededResources: font Helvetica-Bold");
+ puts("%%Creator: imagetops/" CUPS_SVERSION);
+ strftime(curdate, sizeof(curdate), CUPS_STRFTIME_FORMAT, curtm);
+ printf("%%%%CreationDate: %s\n", curdate);
+ printf("%%%%Title: %s\n", argv[3]);
+ printf("%%%%For: %s\n", argv[2]);
+ if (Orientation & 1)
+ puts("%%Orientation: Landscape");
+ else
+ puts("%%Orientation: Portrait");
+ puts("%%EndComments");
+ puts("%%BeginProlog");
+
+ if (ppd != NULL && ppd->patches != NULL)
+ puts(ppd->patches);
+
+ ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
+ ppdEmit(ppd, stdout, PPD_ORDER_ANY);
+ ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
+
+ if (g != 1.0 || b != 1.0)
+ printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
+ "ifelse %.3f mul } bind settransfer\n", g, b);
+
+ WriteCommon();
+ switch (Orientation)
+ {
+ case 0 :
+ WriteLabelProlog(cupsGetOption("page-label", num_options, options),
+ PageBottom, PageTop, PageWidth);
+ break;
+
+ case 1 :
+ WriteLabelProlog(cupsGetOption("page-label", num_options, options),
+ PageLeft, PageRight, PageLength);
+ break;
+
+ case 2 :
+ WriteLabelProlog(cupsGetOption("page-label", num_options, options),
+ PageLength - PageTop, PageLength - PageBottom,
+ PageWidth);
+ break;
+
+ case 3 :
+ WriteLabelProlog(cupsGetOption("page-label", num_options, options),
+ PageWidth - PageRight, PageWidth - PageLeft,
+ PageLength);
+ break;
+ }
+
+ if (realcopies > 1)
+ {
+ if (ppd == NULL || ppd->language_level == 1)
+ printf("/#copies %d def\n", realcopies);
+ else
+ printf("<</NumCopies %d>>setpagedevice\n", realcopies);
+ }
+
+ puts("%%EndProlog");
+
+ /*
+ * Output the pages...
+ */
+
+ row = malloc(img->xsize * abs(colorspace) + 3);
+
+ fprintf(stderr, "DEBUG: XPosition=%d, YPosition=%d, Orientation=%d\n",
+ XPosition, YPosition, Orientation);
+ fprintf(stderr, "DEBUG: xprint=%.0f, yprint=%.0f\n", xprint, yprint);
+ fprintf(stderr, "DEBUG: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f\n",
+ PageLeft, PageRight, PageWidth);
+ fprintf(stderr, "DEBUG: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f\n",
+ PageBottom, PageTop, PageLength);
+
+ switch (Orientation)
+ {
+ case 0 :
+ switch (XPosition)
+ {
+ case -1 :
+ left = PageLeft;
+ break;
+ default :
+ left = (PageRight + PageLeft - xprint * 72) / 2;
+ break;
+ case 1 :
+ left = PageRight - xprint * 72;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case -1 :
+ top = PageBottom + yprint * 72;
+ break;
+ default :
+ top = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case 1 :
+ top = PageTop;
+ break;
+ }
+ break;
+
+ case 1 :
+ switch (XPosition)
+ {
+ case -1 :
+ left = PageBottom;
+ break;
+ default :
+ left = (PageTop + PageBottom - xprint * 72) / 2;
+ break;
+ case 1 :
+ left = PageTop - xprint * 72;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case -1 :
+ top = PageLeft + yprint * 72;
+ break;
+ default :
+ top = (PageRight + PageLeft + yprint * 72) / 2;
+ break;
+ case 1 :
+ top = PageRight;
+ break;
+ }
+ break;
+
+ case 2 :
+ switch (XPosition)
+ {
+ case 1 :
+ left = PageLeft;
+ break;
+ default :
+ left = (PageRight + PageLeft - xprint * 72) / 2;
+ break;
+ case -1 :
+ left = PageRight - xprint * 72;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case 1 :
+ top = PageBottom + yprint * 72;
+ break;
+ default :
+ top = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case -1 :
+ top = PageTop;
+ break;
+ }
+ break;
+
+ case 3 :
+ switch (XPosition)
+ {
+ case 1 :
+ left = PageBottom;
+ break;
+ default :
+ left = (PageTop + PageBottom - xprint * 72) / 2;
+ break;
+ case -1 :
+ left = PageTop - xprint * 72;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case 1 :
+ top = PageLeft + yprint * 72;
+ break;
+ default :
+ top = (PageRight + PageLeft + yprint * 72) / 2;
+ break;
+ case -1 :
+ top = PageRight;
+ break;
+ }
+ break;
+ }
+
+ fprintf(stderr, "DEBUG: left=%.2f, top=%.2f\n", left, top);
+
+ for (page = 1; Copies > 0; Copies --)
+ for (xpage = 0; xpage < xpages; xpage ++)
+ for (ypage = 0; ypage < ypages; ypage ++, page ++)
+ {
+ if (ppd && ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
+
+ fprintf(stderr, "INFO: Printing page %d...\n", page);
+
+ printf("%%%%Page: %d %d\n", page, page);
+
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ puts("gsave");
+
+ if (Flip)
+ printf("%.0f 0 translate -1 1 scale\n", PageWidth);
+
+ switch (Orientation)
+ {
+ case 1 : /* Landscape */
+ printf("%.0f 0 translate 90 rotate\n", PageWidth);
+ break;
+ case 2 : /* Reverse Portrait */
+ printf("%.0f %.0f translate 180 rotate\n", PageWidth, PageLength);
+ break;
+ case 3 : /* Reverse Landscape */
+ printf("0 %.0f translate -90 rotate\n", PageLength);
+ break;
+ }
+
+ puts("gsave");
+
+ x0 = img->xsize * xpage / xpages;
+ x1 = img->xsize * (xpage + 1) / xpages - 1;
+ y0 = img->ysize * ypage / ypages;
+ y1 = img->ysize * (ypage + 1) / ypages - 1;
+
+ printf("%.1f %.1f translate\n", left, top);
+
+ printf("%.3f %.3f scale\n\n",
+ xprint * 72.0 / (x1 - x0 + 1),
+ yprint * 72.0 / (y1 - y0 + 1));
+
+ if (LanguageLevel == 1)
+ {
+ printf("/picture %d string def\n", (x1 - x0 + 1) * abs(colorspace));
+ printf("%d %d 8[1 0 0 -1 0 1]", (x1 - x0 + 1), (y1 - y0 + 1));
+
+ if (colorspace == IMAGE_WHITE)
+ puts("{currentfile picture readhexstring pop} image");
+ else
+ printf("{currentfile picture readhexstring pop} false %d colorimage\n",
+ abs(colorspace));
+
+ for (y = y0; y <= y1; y ++)
+ {
+ ImageGetRow(img, x0, y, x1 - x0 + 1, row);
+ ps_hex(row, (x1 - x0 + 1) * abs(colorspace), y == y1);
+ }
+ }
+ else
+ {
+ switch (colorspace)
+ {
+ case IMAGE_WHITE :
+ puts("/DeviceGray setcolorspace");
+ break;
+ case IMAGE_RGB :
+ puts("/DeviceRGB setcolorspace");
+ break;
+ case IMAGE_CMYK :
+ puts("/DeviceCMYK setcolorspace");
+ break;
+ }
+
+ printf("<<"
+ "/ImageType 1"
+ "/Width %d"
+ "/Height %d"
+ "/BitsPerComponent 8",
+ x1 - x0 + 1, y1 - y0 + 1);
+
+ switch (colorspace)
+ {
+ case IMAGE_WHITE :
+ fputs("/Decode[0 1]", stdout);
+ break;
+ case IMAGE_RGB :
+ fputs("/Decode[0 1 0 1 0 1]", stdout);
+ break;
+ case IMAGE_CMYK :
+ fputs("/Decode[0 1 0 1 0 1 0 1]", stdout);
+ break;
+ }
+
+ fputs("/DataSource currentfile /ASCII85Decode filter", stdout);
+
+ if (((x1 - x0 + 1) / xprint) < 100.0)
+ fputs("/Interpolate true", stdout);
+
+ puts("/ImageMatrix[1 0 0 -1 0 1]>>image");
+
+ for (y = y0, out_offset = 0; y <= y1; y ++)
+ {
+ ImageGetRow(img, x0, y, x1 - x0 + 1, row + out_offset);
+
+ out_length = (x1 - x0 + 1) * abs(colorspace) + out_offset;
+ out_offset = out_length & 3;
+
+ ps_ascii85(row, out_length, y == y1);
+
+ if (out_offset > 0)
+ memcpy(row, row + out_length - out_offset, out_offset);
+ }
+ }
+
+ puts("grestore");
+ WriteLabels(0);
+ puts("grestore");
+ puts("showpage");
+ }
+
+ puts("%%EOF");
+
+ /*
+ * End the job with the appropriate JCL command or CTRL-D otherwise.
+ */
+
+ if (ppd != NULL && ppd->jcl_end)
+ fputs(ppd->jcl_end, stdout);
+ else
+ putchar(0x04);
+
+ /*
+ * Close files...
+ */
+
+ ImageClose(img);
+ ppdClose(ppd);
+
+ return (0);
+}
+
+
+/*
+ * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
+ */
+
+static void
+ps_hex(ib_t *data, /* I - Data to print */
+ int length, /* I - Number of bytes to print */
+ int last_line) /* I - Last line of raster data? */
+{
+ static int col = 0; /* Current column */
+ static char *hex = "0123456789ABCDEF";
+ /* Hex digits */
+
+
+ while (length > 0)
+ {
+ /*
+ * Put the hex chars out to the file; note that we don't use printf()
+ * for speed reasons...
+ */
+
+ putchar(hex[*data >> 4]);
+ putchar(hex[*data & 15]);
+
+ data ++;
+ length --;
+
+ col += 2;
+ if (col > 78)
+ {
+ putchar('\n');
+ col = 0;
+ }
+ }
+
+ if (last_line && col)
+ {
+ putchar('\n');
+ col = 0;
+ }
+}
+
+
+/*
+ * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
+ */
+
+static void
+ps_ascii85(ib_t *data, /* I - Data to print */
+ int length, /* I - Number of bytes to print */
+ int last_line) /* I - Last line of raster data? */
+{
+ unsigned b; /* Binary data word */
+ unsigned char c[5]; /* ASCII85 encoded chars */
+ static int col = 0; /* Current column */
+
+
+ while (length > 3)
+ {
+ b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
+
+ if (b == 0)
+ {
+ putchar('z');
+ col ++;
+ }
+ else
+ {
+ c[4] = (b % 85) + '!';
+ b /= 85;
+ c[3] = (b % 85) + '!';
+ b /= 85;
+ c[2] = (b % 85) + '!';
+ b /= 85;
+ c[1] = (b % 85) + '!';
+ b /= 85;
+ c[0] = b + '!';
+
+ fwrite(c, 5, 1, stdout);
+ col += 5;
+ }
+
+ data += 4;
+ length -= 4;
+
+ if (col >= 75)
+ {
+ putchar('\n');
+ col = 0;
+ }
+ }
+
+ if (last_line)
+ {
+ if (length > 0)
+ {
+ memset(data + length, 0, 4 - length);
+ b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
+
+ c[4] = (b % 85) + '!';
+ b /= 85;
+ c[3] = (b % 85) + '!';
+ b /= 85;
+ c[2] = (b % 85) + '!';
+ b /= 85;
+ c[1] = (b % 85) + '!';
+ b /= 85;
+ c[0] = b + '!';
+
+ fwrite(c, length + 1, 1, stdout);
+ }
+
+ puts("~>");
+ col = 0;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/imagetoraster.c b/filter/imagetoraster.c
new file mode 100644
index 000000000..f79c961f2
--- /dev/null
+++ b/filter/imagetoraster.c
@@ -0,0 +1,4598 @@
+/*
+ * "$Id$"
+ *
+ * Image file to raster filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry...
+ * exec_code() - Execute PostScript setpagedevice commands as
+ * appropriate.
+ * format_CMY() - Convert image data to CMY.
+ * format_CMYK() - Convert image data to CMYK.
+ * format_K() - Convert image data to black.
+ * format_KCMY() - Convert image data to KCMY.
+ * format_KCMYcm() - Convert image data to KCMYcm.
+ * format_RGBA() - Convert image data to RGBA.
+ * format_W() - Convert image data to luminance.
+ * format_YMC() - Convert image data to YMC.
+ * format_YMCK() - Convert image data to YMCK.
+ * make_lut() - Make a lookup table given gamma and brightness values.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+#include "image.h"
+#include "raster.h"
+#include <unistd.h>
+#include <math.h>
+
+
+/*
+ * Globals...
+ */
+
+int Flip = 0, /* Flip/mirror pages */
+ XPosition = 0, /* Horizontal position on page */
+ YPosition = 0, /* Vertical position on page */
+ Collate = 0, /* Collate copies? */
+ Copies = 1; /* Number of copies */
+int Floyd16x16[16][16] = /* Traditional Floyd ordered dither */
+ {
+ { 0, 128, 32, 160, 8, 136, 40, 168,
+ 2, 130, 34, 162, 10, 138, 42, 170 },
+ { 192, 64, 224, 96, 200, 72, 232, 104,
+ 194, 66, 226, 98, 202, 74, 234, 106 },
+ { 48, 176, 16, 144, 56, 184, 24, 152,
+ 50, 178, 18, 146, 58, 186, 26, 154 },
+ { 240, 112, 208, 80, 248, 120, 216, 88,
+ 242, 114, 210, 82, 250, 122, 218, 90 },
+ { 12, 140, 44, 172, 4, 132, 36, 164,
+ 14, 142, 46, 174, 6, 134, 38, 166 },
+ { 204, 76, 236, 108, 196, 68, 228, 100,
+ 206, 78, 238, 110, 198, 70, 230, 102 },
+ { 60, 188, 28, 156, 52, 180, 20, 148,
+ 62, 190, 30, 158, 54, 182, 22, 150 },
+ { 252, 124, 220, 92, 244, 116, 212, 84,
+ 254, 126, 222, 94, 246, 118, 214, 86 },
+ { 3, 131, 35, 163, 11, 139, 43, 171,
+ 1, 129, 33, 161, 9, 137, 41, 169 },
+ { 195, 67, 227, 99, 203, 75, 235, 107,
+ 193, 65, 225, 97, 201, 73, 233, 105 },
+ { 51, 179, 19, 147, 59, 187, 27, 155,
+ 49, 177, 17, 145, 57, 185, 25, 153 },
+ { 243, 115, 211, 83, 251, 123, 219, 91,
+ 241, 113, 209, 81, 249, 121, 217, 89 },
+ { 15, 143, 47, 175, 7, 135, 39, 167,
+ 13, 141, 45, 173, 5, 133, 37, 165 },
+ { 207, 79, 239, 111, 199, 71, 231, 103,
+ 205, 77, 237, 109, 197, 69, 229, 101 },
+ { 63, 191, 31, 159, 55, 183, 23, 151,
+ 61, 189, 29, 157, 53, 181, 21, 149 },
+ { 254, 127, 223, 95, 247, 119, 215, 87,
+ 253, 125, 221, 93, 245, 117, 213, 85 }
+ };
+int Floyd8x8[8][8] =
+ {
+ { 0, 32, 8, 40, 2, 34, 10, 42 },
+ { 48, 16, 56, 24, 50, 18, 58, 26 },
+ { 12, 44, 4, 36, 14, 46, 6, 38 },
+ { 60, 28, 52, 20, 62, 30, 54, 22 },
+ { 3, 35, 11, 43, 1, 33, 9, 41 },
+ { 51, 19, 59, 27, 49, 17, 57, 25 },
+ { 15, 47, 7, 39, 13, 45, 5, 37 },
+ { 63, 31, 55, 23, 61, 29, 53, 21 }
+ };
+int Floyd4x4[4][4] =
+ {
+ { 0, 8, 2, 10 },
+ { 12, 4, 14, 6 },
+ { 3, 11, 1, 9 },
+ { 15, 7, 13, 5 }
+ };
+
+ib_t OnPixels[256], /* On-pixel LUT */
+ OffPixels[256]; /* Off-pixel LUT */
+int Planes[] = /* Number of planes for each colorspace */
+ {
+ 1, /* CUPS_CSPACE_W */
+ 3, /* CUPS_CSPACE_RGB */
+ 4, /* CUPS_CSPACE_RGBA */
+ 1, /* CUPS_CSPACE_K */
+ 3, /* CUPS_CSPACE_CMY */
+ 3, /* CUPS_CSPACE_YMC */
+ 4, /* CUPS_CSPACE_CMYK */
+ 4, /* CUPS_CSPACE_YMCK */
+ 4, /* CUPS_CSPACE_KCMY */
+ 6, /* CUPS_CSPACE_KCMYcm */
+ 4, /* CUPS_CSPACE_GMCK */
+ 4, /* CUPS_CSPACE_GMCS */
+ 1, /* CUPS_CSPACE_WHITE */
+ 1, /* CUPS_CSPACE_GOLD */
+ 1, /* CUPS_CSPACE_SILVER */
+ 3, /* CUPS_CSPACE_CIEXYZ */
+ 3, /* CUPS_CSPACE_CIELab */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 0, /* ... reserved ... */
+ 3, /* CUPS_CSPACE_ICC1 */
+ 3, /* CUPS_CSPACE_ICC2 */
+ 3, /* CUPS_CSPACE_ICC3 */
+ 3, /* CUPS_CSPACE_ICC4 */
+ 3, /* CUPS_CSPACE_ICC5 */
+ 3, /* CUPS_CSPACE_ICC6 */
+ 3, /* CUPS_CSPACE_ICC7 */
+ 3, /* CUPS_CSPACE_ICC8 */
+ 3, /* CUPS_CSPACE_ICC9 */
+ 3, /* CUPS_CSPACE_ICCA */
+ 3, /* CUPS_CSPACE_ICCB */
+ 3, /* CUPS_CSPACE_ICCC */
+ 3, /* CUPS_CSPACE_ICCD */
+ 3, /* CUPS_CSPACE_ICCE */
+ 3 /* CUPS_CSPACE_ICCF */
+ };
+
+
+/*
+ * Local functions...
+ */
+
+static void exec_code(cups_page_header_t *header, const char *code);
+static void format_CMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_CMYK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_K(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_KCMYcm(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_KCMY(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+#define format_RGB format_CMY
+static void format_RGBA(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_W(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_YMC(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void format_YMCK(cups_page_header_t *header, unsigned char *row, int y, int z, int xsize, int ysize, int yerr0, int yerr1, ib_t *r0, ib_t *r1);
+static void make_lut(ib_t *, int, float, float);
+
+
+/*
+ * 'main()' - Main entry...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ image_t *img; /* Image to print */
+ float xprint, /* Printable area */
+ yprint,
+ xinches, /* Total size in inches */
+ yinches;
+ float xsize, /* Total size in points */
+ ysize,
+ xsize2,
+ ysize2;
+ float aspect; /* Aspect ratio */
+ int xpages, /* # x pages */
+ ypages, /* # y pages */
+ xpage, /* Current x page */
+ ypage, /* Current y page */
+ xtemp, /* Bitmap width in pixels */
+ ytemp, /* Bitmap height in pixels */
+ page; /* Current page number */
+ int x0, y0, /* Corners of the page in image coords */
+ x1, y1;
+ ppd_file_t *ppd; /* PPD file */
+ ppd_choice_t *choice, /* PPD option choice */
+ **choices; /* List of marked choices */
+ int count; /* Number of marked choices */
+ char *resolution, /* Output resolution */
+ *media_type; /* Media type */
+ ppd_profile_t *profile; /* Color profile */
+ ppd_profile_t userprofile; /* User-specified profile */
+ cups_raster_t *ras; /* Raster stream */
+ cups_page_header_t header; /* Page header */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ const char *val; /* Option value */
+ int slowcollate, /* Collate copies the slow way */
+ slowcopies; /* Make copies the "slow" way? */
+ float g; /* Gamma correction value */
+ float b; /* Brightness factor */
+ float zoom; /* Zoom facter */
+ int xppi, yppi; /* Pixels-per-inch */
+ int hue, sat; /* Hue and saturation adjustment */
+ izoom_t *z; /* ImageZoom buffer */
+ int primary, /* Primary image colorspace */
+ secondary; /* Secondary image colorspace */
+ ib_t *row, /* Current row */
+ *r0, /* Top row */
+ *r1; /* Bottom row */
+ int y, /* Current Y coordinate on page */
+ iy, /* Current Y coordinate in image */
+ last_iy, /* Previous Y coordinate in image */
+ yerr0, /* Top Y error value */
+ yerr1, /* Bottom Y error value */
+ blank; /* Blank value */
+ ib_t lut[256]; /* Gamma/brightness LUT */
+ int plane, /* Current color plane */
+ num_planes; /* Number of color planes */
+ char filename[1024]; /* Name of file to print */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ fputs("ERROR: imagetoraster job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ fprintf(stderr, "INFO: %s %s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5], argv[6] ? argv[6] : "(null)");
+
+ /*
+ * See if we need to use the imagetops and pstoraster filters instead...
+ */
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ if (getenv("CLASSIFICATION") ||
+ cupsGetOption("page-label", num_options, options))
+ {
+ /*
+ * Yes, fork a copy of pstoraster and then transfer control to imagetops...
+ */
+
+ int mypipes[2]; /* New pipes for imagetops | pstoraster */
+ int pid; /* PID of pstoraster */
+
+
+ cupsFreeOptions(num_options, options);
+
+ if (pipe(mypipes))
+ {
+ perror("ERROR: Unable to create pipes for imagetops | pstoraster");
+ return (errno);
+ }
+
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child process for pstoraster... Assign new pipe input to pstoraster...
+ */
+
+ close(0);
+ dup(mypipes[0]);
+ close(mypipes[0]);
+ close(mypipes[1]);
+
+ execlp("pstoraster", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ NULL);
+ perror("ERROR: Unable to exec pstoraster");
+ return (errno);
+ }
+ else if (pid < 0)
+ {
+ /*
+ * Error!
+ */
+
+ perror("ERROR: Unable to fork pstoraster");
+ return (errno);
+ }
+
+ /*
+ * Update stdout so it points at the new pstoraster...
+ */
+
+ close(1);
+ dup(mypipes[1]);
+ close(mypipes[0]);
+ close(mypipes[1]);
+
+ /*
+ * Run imagetops to get the classification or page labelling that was
+ * requested...
+ */
+
+ execlp("imagetops", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
+ argv[6], NULL);
+ perror("ERROR: Unable to exec imagetops");
+ return (errno);
+ }
+
+ /*
+ * Copy stdin as needed...
+ */
+
+ if (argc == 6)
+ {
+ int fd; /* File to write to */
+ char buffer[8192]; /* Buffer to read into */
+ int bytes; /* # of bytes to read */
+
+
+ if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
+ {
+ perror("ERROR: Unable to copy image file");
+ return (1);
+ }
+
+ fprintf(stderr, "DEBUG: imagetoraster - copying to temp print file \"%s\"\n",
+ filename);
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ write(fd, buffer, bytes);
+
+ close(fd);
+ }
+ else
+ strlcpy(filename, argv[6], sizeof(filename));
+
+ /*
+ * Process command-line options and write the prolog...
+ */
+
+ zoom = 0.0;
+ xppi = 0;
+ yppi = 0;
+ hue = 0;
+ sat = 100;
+ g = 1.0;
+ b = 1.0;
+
+ Copies = atoi(argv[4]);
+
+ ppd = SetCommonOptions(num_options, options, 0);
+
+ if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
+ {
+ /*
+ * This IPP attribute is unnecessarily complicated...
+ *
+ * single-document, separate-documents-collated-copies, and
+ * single-document-new-sheet all require collated copies.
+ *
+ * separate-documents-collated-copies allows for uncollated copies.
+ */
+
+ Collate = strcasecmp(val, "separate-documents-collated-copies") != 0;
+ }
+
+ if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
+ strcasecmp(val, "True") == 0)
+ Collate = 1;
+
+ if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+ g = atoi(val) * 0.001f;
+
+ if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
+ b = atoi(val) * 0.01f;
+
+ if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
+ zoom = atoi(val) * 0.01;
+
+ if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
+ if (sscanf(val, "%dx%d", &xppi, &yppi) < 2)
+ yppi = xppi;
+
+ if ((val = cupsGetOption("position", num_options, options)) != NULL)
+ {
+ if (strcasecmp(val, "center") == 0)
+ {
+ XPosition = 0;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "top") == 0)
+ {
+ XPosition = 0;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "left") == 0)
+ {
+ XPosition = -1;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "right") == 0)
+ {
+ XPosition = 1;
+ YPosition = 0;
+ }
+ else if (strcasecmp(val, "top-left") == 0)
+ {
+ XPosition = -1;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "top-right") == 0)
+ {
+ XPosition = 1;
+ YPosition = 1;
+ }
+ else if (strcasecmp(val, "bottom") == 0)
+ {
+ XPosition = 0;
+ YPosition = -1;
+ }
+ else if (strcasecmp(val, "bottom-left") == 0)
+ {
+ XPosition = -1;
+ YPosition = -1;
+ }
+ else if (strcasecmp(val, "bottom-right") == 0)
+ {
+ XPosition = 1;
+ YPosition = -1;
+ }
+ }
+
+ if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
+ sat = atoi(val);
+
+ if ((val = cupsGetOption("hue", num_options, options)) != NULL)
+ hue = atoi(val);
+
+ if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
+ strcasecmp(val, "True") == 0)
+ Flip = 1;
+
+ /*
+ * Set the needed options in the page header...
+ */
+
+ memset(&header, 0, sizeof(header));
+ header.HWResolution[0] = 100;
+ header.HWResolution[1] = 100;
+ header.cupsBitsPerColor = 1;
+ header.cupsColorOrder = CUPS_ORDER_CHUNKED;
+ header.cupsColorSpace = CUPS_CSPACE_K;
+
+ if (ppd && ppd->patches)
+ exec_code(&header, ppd->patches);
+
+ if ((count = ppdCollect(ppd, PPD_ORDER_DOCUMENT, &choices)) > 0)
+ for (i = 0; i < count; i ++)
+ exec_code(&header, choices[i]->code);
+
+ if ((count = ppdCollect(ppd, PPD_ORDER_ANY, &choices)) > 0)
+ for (i = 0; i < count; i ++)
+ exec_code(&header, choices[i]->code);
+
+ if ((count = ppdCollect(ppd, PPD_ORDER_PROLOG, &choices)) > 0)
+ for (i = 0; i < count; i ++)
+ exec_code(&header, choices[i]->code);
+
+ if ((count = ppdCollect(ppd, PPD_ORDER_PAGE, &choices)) > 0)
+ for (i = 0; i < count; i ++)
+ exec_code(&header, choices[i]->code);
+
+ /*
+ * Get the media type and resolution that have been chosen...
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "MediaType")) != NULL)
+ media_type = choice->choice;
+ else
+ media_type = "";
+
+ if ((choice = ppdFindMarkedChoice(ppd, "Resolution")) != NULL)
+ resolution = choice->choice;
+ else
+ resolution = "";
+
+ /*
+ * Choose the appropriate colorspace...
+ */
+
+ switch (header.cupsColorSpace)
+ {
+ case CUPS_CSPACE_W :
+ primary = IMAGE_WHITE;
+ secondary = IMAGE_WHITE;
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ break;
+
+ default :
+ case CUPS_CSPACE_RGB :
+ case CUPS_CSPACE_RGBA :
+ primary = IMAGE_RGB;
+ secondary = IMAGE_RGB;
+
+ /*
+ * Ensure that colorimetric colorspaces use at least 8 bits per
+ * component...
+ */
+
+ if (header.cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
+ header.cupsBitsPerColor < 8)
+ header.cupsBitsPerColor = 8;
+
+ if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
+ {
+ if (header.cupsBitsPerColor >= 8)
+ header.cupsBitsPerPixel = header.cupsBitsPerColor * 3;
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
+ }
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ break;
+
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ primary = IMAGE_BLACK;
+ secondary = IMAGE_BLACK;
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ break;
+
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ primary = IMAGE_CMYK;
+ secondary = IMAGE_CMYK;
+
+ if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
+ header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ break;
+
+ case CUPS_CSPACE_CMY :
+ case CUPS_CSPACE_YMC :
+ primary = IMAGE_CMY;
+ secondary = IMAGE_CMY;
+
+ if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
+ {
+ if (header.cupsBitsPerColor >= 8)
+ header.cupsBitsPerPixel = 24;
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
+ }
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ break;
+
+ case CUPS_CSPACE_KCMYcm :
+ if (header.cupsBitsPerPixel == 1)
+ {
+ primary = IMAGE_CMY;
+ secondary = IMAGE_CMY;
+
+ if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
+ header.cupsBitsPerPixel = 8;
+ else
+ header.cupsBitsPerPixel = 1;
+ }
+ else
+ {
+ primary = IMAGE_CMYK;
+ secondary = IMAGE_CMYK;
+
+ if (header.cupsColorOrder == CUPS_ORDER_CHUNKED)
+ header.cupsBitsPerPixel = header.cupsBitsPerColor * 4;
+ else
+ header.cupsBitsPerPixel = header.cupsBitsPerColor;
+ }
+ break;
+ }
+
+ /*
+ * Find a color profile matching the current options...
+ */
+
+ if ((val = cupsGetOption("profile", num_options, options)) != NULL)
+ {
+ profile = &userprofile;
+ sscanf(val, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
+ &(userprofile.density), &(userprofile.gamma),
+ userprofile.matrix[0] + 0, userprofile.matrix[0] + 1,
+ userprofile.matrix[0] + 2,
+ userprofile.matrix[1] + 0, userprofile.matrix[1] + 1,
+ userprofile.matrix[1] + 2,
+ userprofile.matrix[2] + 0, userprofile.matrix[2] + 1,
+ userprofile.matrix[2] + 2);
+
+ userprofile.density *= 0.001f;
+ userprofile.gamma *= 0.001f;
+ userprofile.matrix[0][0] *= 0.001f;
+ userprofile.matrix[0][1] *= 0.001f;
+ userprofile.matrix[0][2] *= 0.001f;
+ userprofile.matrix[1][0] *= 0.001f;
+ userprofile.matrix[1][1] *= 0.001f;
+ userprofile.matrix[1][2] *= 0.001f;
+ userprofile.matrix[2][0] *= 0.001f;
+ userprofile.matrix[2][1] *= 0.001f;
+ userprofile.matrix[2][2] *= 0.001f;
+ }
+ else if (ppd != NULL)
+ {
+ fprintf(stderr, "DEBUG: Searching for profile \"%s/%s\"...\n",
+ resolution, media_type);
+
+ for (i = 0, profile = ppd->profiles; i < ppd->num_profiles; i ++, profile ++)
+ {
+ fprintf(stderr, "DEBUG: \"%s/%s\" = ", profile->resolution,
+ profile->media_type);
+
+ if ((strcmp(profile->resolution, resolution) == 0 ||
+ profile->resolution[0] == '-') &&
+ (strcmp(profile->media_type, media_type) == 0 ||
+ profile->media_type[0] == '-'))
+ {
+ fputs("MATCH!\n", stderr);
+ break;
+ }
+ else
+ fputs("no.\n", stderr);
+ }
+
+ /*
+ * If we found a color profile, use it!
+ */
+
+ if (i >= ppd->num_profiles)
+ profile = NULL;
+ }
+ else
+ profile = NULL;
+
+ if (profile)
+ ImageSetProfile(profile->density, profile->gamma, profile->matrix);
+
+ ImageSetColorSpace(header.cupsColorSpace);
+
+ /*
+ * Create a gamma/brightness LUT...
+ */
+
+ make_lut(lut, primary, g, b);
+
+ /*
+ * Open the input image to print...
+ */
+
+ fputs("INFO: Loading image file...\n", stderr);
+
+ img = ImageOpen(filename, primary, secondary, sat, hue, lut);
+
+ if (argc == 6)
+ unlink(filename);
+
+ if (img == NULL)
+ {
+ fputs("ERROR: Unable to open image file for printing!\n", stderr);
+ ppdClose(ppd);
+ return (1);
+ }
+
+ /*
+ * Scale as necessary...
+ */
+
+ if (zoom == 0.0 && xppi == 0)
+ {
+ xppi = img->xppi;
+ yppi = img->yppi;
+ }
+
+ if (yppi == 0)
+ yppi = xppi;
+
+ fprintf(stderr, "DEBUG: Before scaling: xppi=%d, yppi=%d, zoom=%.2f\n",
+ xppi, yppi, zoom);
+
+ if (xppi > 0)
+ {
+ /*
+ * Scale the image as neccesary to match the desired pixels-per-inch.
+ */
+
+ if (Orientation & 1)
+ {
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ }
+
+ fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
+ xprint, yprint);
+
+ xinches = (float)img->xsize / (float)xppi;
+ yinches = (float)img->ysize / (float)yppi;
+
+ fprintf(stderr, "DEBUG: Image size is %.1f x %.1f inches...\n",
+ xinches, yinches);
+
+ if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
+ {
+ xinches = xinches * atoi(val) / 100;
+ yinches = yinches * atoi(val) / 100;
+ }
+
+ if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+ cupsGetOption("landscape", num_options, options) == NULL)
+ {
+ /*
+ * Rotate the image if it will fit landscape but not portrait...
+ */
+
+ fputs("DEBUG: Auto orientation...\n", stderr);
+
+ if ((xinches > xprint || yinches > yprint) &&
+ xinches <= yprint && yinches <= xprint)
+ {
+ /*
+ * Rotate the image as needed...
+ */
+
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ Orientation = (Orientation + 1) & 3;
+ xsize = yprint;
+ yprint = xprint;
+ xprint = xsize;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Scale percentage of page size...
+ */
+
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ aspect = (float)img->yppi / (float)img->xppi;
+
+ fprintf(stderr, "DEBUG: Before scaling: xprint=%.1f, yprint=%.1f\n",
+ xprint, yprint);
+
+ fprintf(stderr, "DEBUG: img->xppi = %d, img->yppi = %d, aspect = %f\n",
+ img->xppi, img->yppi, aspect);
+
+ xsize = xprint * zoom;
+ ysize = xsize * img->ysize / img->xsize / aspect;
+
+ if (ysize > (yprint * zoom))
+ {
+ ysize = yprint * zoom;
+ xsize = ysize * img->xsize * aspect / img->ysize;
+ }
+
+ xsize2 = yprint * zoom;
+ ysize2 = xsize2 * img->ysize / img->xsize / aspect;
+
+ if (ysize2 > (xprint * zoom))
+ {
+ ysize2 = xprint * zoom;
+ xsize2 = ysize2 * img->xsize * aspect / img->ysize;
+ }
+
+ fprintf(stderr, "DEBUG: Portrait size is %.2f x %.2f inches\n", xsize, ysize);
+ fprintf(stderr, "DEBUG: Landscape size is %.2f x %.2f inches\n", xsize2, ysize2);
+
+ if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+ cupsGetOption("landscape", num_options, options) == NULL)
+ {
+ /*
+ * Choose the rotation with the largest area, but prefer
+ * portrait if they are equal...
+ */
+
+ fputs("DEBUG: Auto orientation...\n", stderr);
+
+ if ((xsize * ysize) < (xsize2 * xsize2))
+ {
+ /*
+ * Do landscape orientation...
+ */
+
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ Orientation = 1;
+ xinches = xsize2;
+ yinches = ysize2;
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ /*
+ * Do portrait orientation...
+ */
+
+ fputs("DEBUG: Using portrait orientation...\n", stderr);
+
+ Orientation = 0;
+ xinches = xsize;
+ yinches = ysize;
+ }
+ }
+ else if (Orientation & 1)
+ {
+ fputs("DEBUG: Using landscape orientation...\n", stderr);
+
+ xinches = xsize2;
+ yinches = ysize2;
+ xprint = (PageTop - PageBottom) / 72.0;
+ yprint = (PageRight - PageLeft) / 72.0;
+ }
+ else
+ {
+ fputs("DEBUG: Using portrait orientation...\n", stderr);
+
+ xinches = xsize;
+ yinches = ysize;
+ xprint = (PageRight - PageLeft) / 72.0;
+ yprint = (PageTop - PageBottom) / 72.0;
+ }
+ }
+
+ /*
+ * Compute the number of pages to print and the size of the image on each
+ * page...
+ */
+
+ xpages = ceil(xinches / xprint);
+ ypages = ceil(yinches / yprint);
+
+ xprint = xinches / xpages;
+ yprint = yinches / ypages;
+
+ fprintf(stderr, "DEBUG: xpages = %dx%.2fin, ypages = %dx%.2fin\n",
+ xpages, xprint, ypages, yprint);
+
+ /*
+ * Compute the bitmap size...
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
+ strcasecmp(choice->choice, "Custom") == 0)
+ {
+ float width, /* New width in points */
+ length; /* New length in points */
+
+
+ /*
+ * Use the correct width and length for the current orientation...
+ */
+
+ if (Orientation & 1)
+ {
+ width = yprint * 72.0;
+ length = xprint * 72.0;
+ }
+ else
+ {
+ width = xprint * 72.0;
+ length = yprint * 72.0;
+ }
+
+ /*
+ * Add margins to page size...
+ */
+
+ width += ppd->custom_margins[0] + ppd->custom_margins[2];
+ length += ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Enforce minimums...
+ */
+
+ if (width < ppd->custom_min[0])
+ width = ppd->custom_min[0];
+
+ if (length < ppd->custom_min[1])
+ length = ppd->custom_min[1];
+
+ fprintf(stderr, "DEBUG: Updated custom page size to %.2f x %.2f inches...\n",
+ width / 72.0, length / 72.0);
+
+ /*
+ * Set the new custom size...
+ */
+
+ header.PageSize[0] = width + 0.5;
+ header.PageSize[1] = length + 0.5;
+
+ /*
+ * Update page variables...
+ */
+
+ PageWidth = width;
+ PageLength = length;
+ PageLeft = ppd->custom_margins[0];
+ PageRight = width - ppd->custom_margins[2];
+ PageBottom = ppd->custom_margins[1];
+ PageTop = length - ppd->custom_margins[3];
+
+ /*
+ * Remove margins from page size...
+ */
+
+ width -= ppd->custom_margins[0] + ppd->custom_margins[2];
+ length -= ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Set the bitmap size...
+ */
+
+ header.cupsWidth = width * header.HWResolution[0] / 72.0;
+ header.cupsHeight = length * header.HWResolution[1] / 72.0;
+ }
+ else
+ {
+ header.cupsWidth = (PageRight - PageLeft) * header.HWResolution[0] / 72.0;
+ header.cupsHeight = (PageTop - PageBottom) * header.HWResolution[1] / 72.0;
+ header.PageSize[0] = PageWidth;
+ header.PageSize[1] = PageLength;
+ }
+
+ header.Margins[0] = PageLeft;
+ header.Margins[1] = PageBottom;
+
+ fprintf(stderr, "DEBUG: PageSize = [%d %d]\n", header.PageSize[0],
+ header.PageSize[1]);
+
+ switch (Orientation)
+ {
+ case 0 :
+ switch (XPosition)
+ {
+ case -1 :
+ header.ImagingBoundingBox[0] = PageLeft;
+ header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
+ header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
+ break;
+ case 1 :
+ header.ImagingBoundingBox[0] = PageRight - xprint * 72;
+ header.ImagingBoundingBox[2] = PageRight;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case -1 :
+ header.ImagingBoundingBox[1] = PageBottom;
+ header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
+ header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case 1 :
+ header.ImagingBoundingBox[1] = PageTop - yprint * 72;
+ header.ImagingBoundingBox[3] = PageTop;
+ break;
+ }
+ break;
+
+ case 1 :
+ switch (XPosition)
+ {
+ case -1 :
+ header.ImagingBoundingBox[0] = PageBottom;
+ header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
+ header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case 1 :
+ header.ImagingBoundingBox[0] = PageTop - yprint * 72;
+ header.ImagingBoundingBox[2] = PageTop;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case -1 :
+ header.ImagingBoundingBox[1] = PageLeft;
+ header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
+ header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
+ break;
+ case 1 :
+ header.ImagingBoundingBox[1] = PageRight - xprint * 72;
+ header.ImagingBoundingBox[3] = PageRight;
+ break;
+ }
+ break;
+
+ case 2 :
+ switch (XPosition)
+ {
+ case 1 :
+ header.ImagingBoundingBox[0] = PageLeft;
+ header.ImagingBoundingBox[2] = PageLeft + xprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[0] = (PageRight + PageLeft - xprint * 72) / 2;
+ header.ImagingBoundingBox[2] = (PageRight + PageLeft + xprint * 72) / 2;
+ break;
+ case -1 :
+ header.ImagingBoundingBox[0] = PageRight - xprint * 72;
+ header.ImagingBoundingBox[2] = PageRight;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case 1 :
+ header.ImagingBoundingBox[1] = PageBottom;
+ header.ImagingBoundingBox[3] = PageBottom + yprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[1] = (PageTop + PageBottom - yprint * 72) / 2;
+ header.ImagingBoundingBox[3] = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case -1 :
+ header.ImagingBoundingBox[1] = PageTop - yprint * 72;
+ header.ImagingBoundingBox[3] = PageTop;
+ break;
+ }
+ break;
+
+ case 3 :
+ switch (XPosition)
+ {
+ case 1 :
+ header.ImagingBoundingBox[0] = PageBottom;
+ header.ImagingBoundingBox[2] = PageBottom + yprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[0] = (PageTop + PageBottom - yprint * 72) / 2;
+ header.ImagingBoundingBox[2] = (PageTop + PageBottom + yprint * 72) / 2;
+ break;
+ case -1 :
+ header.ImagingBoundingBox[0] = PageTop - yprint * 72;
+ header.ImagingBoundingBox[2] = PageTop;
+ break;
+ }
+
+ switch (YPosition)
+ {
+ case 1 :
+ header.ImagingBoundingBox[1] = PageLeft;
+ header.ImagingBoundingBox[3] = PageLeft + xprint * 72;
+ break;
+ default :
+ header.ImagingBoundingBox[1] = (PageRight + PageLeft - xprint * 72) / 2;
+ header.ImagingBoundingBox[3] = (PageRight + PageLeft + xprint * 72) / 2;
+ break;
+ case -1 :
+ header.ImagingBoundingBox[1] = PageRight - xprint * 72;
+ header.ImagingBoundingBox[3] = PageRight;
+ break;
+ }
+ break;
+ }
+
+ switch (header.cupsColorOrder)
+ {
+ default :
+ header.cupsBytesPerLine = (header.cupsBitsPerPixel *
+ header.cupsWidth + 7) / 8;
+ num_planes = 1;
+ break;
+
+ case CUPS_ORDER_BANDED :
+ if (header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
+ header.cupsBitsPerColor > 1)
+ header.cupsBytesPerLine = (header.cupsBitsPerPixel *
+ header.cupsWidth + 7) / 8 * 4;
+ else
+ header.cupsBytesPerLine = (header.cupsBitsPerPixel *
+ header.cupsWidth + 7) / 8 *
+ Planes[header.cupsColorSpace];
+ num_planes = 1;
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ header.cupsBytesPerLine = (header.cupsBitsPerPixel *
+ header.cupsWidth + 7) / 8;
+ num_planes = Planes[header.cupsColorSpace];
+ break;
+ }
+
+ /*
+ * See if we need to collate, and if so how we need to do it...
+ */
+
+ if (xpages == 1 && ypages == 1)
+ Collate = 0;
+
+ slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
+ if (ppd != NULL)
+ slowcopies = ppd->manual_copies;
+ else
+ slowcopies = 1;
+
+ if (Copies > 1 && !slowcollate && !slowcopies)
+ {
+ header.Collate = (cups_bool_t)Collate;
+ header.NumCopies = Copies;
+
+ Copies = 1;
+ }
+ else
+ header.NumCopies = 1;
+
+ /*
+ * Create the dithering lookup tables...
+ */
+
+ OnPixels[0] = 0x00;
+ OnPixels[255] = 0xff;
+ OffPixels[0] = 0x00;
+ OffPixels[255] = 0xff;
+
+ switch (header.cupsBitsPerColor)
+ {
+ case 2 :
+ for (i = 1; i < 255; i ++)
+ {
+ OnPixels[i] = 0x55 * (i / 85 + 1);
+ OffPixels[i] = 0x55 * (i / 64);
+ }
+ break;
+ case 4 :
+ for (i = 1; i < 255; i ++)
+ {
+ OnPixels[i] = 17 * (i / 17 + 1);
+ OffPixels[i] = 17 * (i / 16);
+ }
+
+ OnPixels[255] = OffPixels[255] = 0xff;
+ break;
+ }
+
+ /*
+ * Output the pages...
+ */
+
+ fprintf(stderr, "DEBUG: cupsWidth = %d\n", header.cupsWidth);
+ fprintf(stderr, "DEBUG: cupsHeight = %d\n", header.cupsHeight);
+ fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header.cupsBitsPerColor);
+ fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header.cupsBitsPerPixel);
+ fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header.cupsBytesPerLine);
+ fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header.cupsColorOrder);
+ fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header.cupsColorSpace);
+ fprintf(stderr, "DEBUG: img->colorspace = %d\n", img->colorspace);
+
+ row = malloc(2 * header.cupsBytesPerLine);
+ ras = cupsRasterOpen(1, CUPS_RASTER_WRITE);
+ blank = img->colorspace < 0 ? 0 : ~0;
+
+ for (i = 0, page = 1; i < Copies; i ++)
+ for (xpage = 0; xpage < xpages; xpage ++)
+ for (ypage = 0; ypage < ypages; ypage ++, page ++)
+ {
+ fprintf(stderr, "INFO: Formatting page %d...\n", page);
+
+ if (Orientation & 1)
+ {
+ x0 = img->xsize * ypage / ypages;
+ x1 = img->xsize * (ypage + 1) / ypages - 1;
+ y0 = img->ysize * xpage / xpages;
+ y1 = img->ysize * (xpage + 1) / xpages - 1;
+
+ xtemp = header.HWResolution[0] * yprint;
+ ytemp = header.HWResolution[1] * xprint;
+ }
+ else
+ {
+ x0 = img->xsize * xpage / xpages;
+ x1 = img->xsize * (xpage + 1) / xpages - 1;
+ y0 = img->ysize * ypage / ypages;
+ y1 = img->ysize * (ypage + 1) / ypages - 1;
+
+ xtemp = header.HWResolution[0] * xprint;
+ ytemp = header.HWResolution[1] * yprint;
+ }
+
+ cupsRasterWriteHeader(ras, &header);
+
+ for (plane = 0; plane < num_planes; plane ++)
+ {
+ /*
+ * Initialize the image "zoom" engine...
+ */
+
+ if (Flip)
+ z = ImageZoomAlloc(img, x0, y0, x1, y1, -xtemp, ytemp,
+ Orientation & 1);
+ else
+ z = ImageZoomAlloc(img, x0, y0, x1, y1, xtemp, ytemp,
+ Orientation & 1);
+
+ /*
+ * Write leading blank space as needed...
+ */
+
+ if (header.cupsHeight > z->ysize && YPosition <= 0)
+ {
+ memset(row, blank, header.cupsBytesPerLine);
+
+ y = header.cupsHeight - z->ysize;
+ if (YPosition == 0)
+ y /= 2;
+
+ for (; y > 0; y --)
+ {
+ if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
+ header.cupsBytesPerLine)
+ {
+ fputs("ERROR: Unable to write raster data to driver!\n", stderr);
+ ImageClose(img);
+ exit(1);
+ }
+ }
+ }
+
+ /*
+ * Then write image data...
+ */
+
+ for (y = z->ysize, yerr0 = 0, yerr1 = z->ysize, iy = 0, last_iy = -2;
+ y > 0;
+ y --)
+ {
+ if (iy != last_iy)
+ {
+ if (header.cupsBitsPerColor >= 8)
+ {
+ /*
+ * Do bilinear interpolation for 8+ bpp images...
+ */
+
+ if ((iy - last_iy) > 1)
+ ImageZoomFill(z, iy);
+
+ ImageZoomFill(z, iy + z->yincr);
+ }
+ else
+ {
+ /*
+ * Just do nearest-neighbor sampling for < 8 bpp images...
+ */
+
+ ImageZoomQFill(z, iy);
+ }
+
+ last_iy = iy;
+ }
+
+ /*
+ * Format this line of raster data for the printer...
+ */
+
+ memset(row, blank, header.cupsBytesPerLine);
+
+ r0 = z->rows[z->row];
+ r1 = z->rows[1 - z->row];
+
+ switch (header.cupsColorSpace)
+ {
+ case CUPS_CSPACE_W :
+ format_W(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ default :
+ case CUPS_CSPACE_RGB :
+ format_RGB(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_RGBA :
+ format_RGBA(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ format_K(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_CMY :
+ format_CMY(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_YMC :
+ format_YMC(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_CMYK :
+ format_CMYK(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ format_YMCK(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_KCMY :
+ format_KCMY(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ case CUPS_CSPACE_KCMYcm :
+ format_KCMYcm(&header, row, y, plane, z->xsize, z->ysize,
+ yerr0, yerr1, r0, r1);
+ break;
+ }
+
+ /*
+ * Write the raster data to the driver...
+ */
+
+ if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
+ header.cupsBytesPerLine)
+ {
+ fputs("ERROR: Unable to write raster data to driver!\n", stderr);
+ ImageClose(img);
+ exit(1);
+ }
+
+ /*
+ * Compute the next scanline in the image...
+ */
+
+ iy += z->ystep;
+ yerr0 += z->ymod;
+ yerr1 -= z->ymod;
+ if (yerr1 <= 0)
+ {
+ yerr0 -= z->ysize;
+ yerr1 += z->ysize;
+ iy += z->yincr;
+ }
+ }
+
+ /*
+ * Write trailing blank space as needed...
+ */
+
+ if (header.cupsHeight > z->ysize && YPosition >= 0)
+ {
+ memset(row, blank, header.cupsBytesPerLine);
+
+ y = header.cupsHeight - z->ysize;
+ if (YPosition == 0)
+ y = y - y / 2;
+
+ for (; y > 0; y --)
+ {
+ if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) <
+ header.cupsBytesPerLine)
+ {
+ fputs("ERROR: Unable to write raster data to driver!\n", stderr);
+ ImageClose(img);
+ exit(1);
+ }
+ }
+ }
+
+ /*
+ * Free memory used for the "zoom" engine...
+ */
+
+ ImageZoomFree(z);
+ }
+ }
+
+ /*
+ * Close files...
+ */
+
+ free(row);
+ cupsRasterClose(ras);
+ ImageClose(img);
+ ppdClose(ppd);
+
+ return (0);
+}
+
+
+/*
+ * 'exec_code()' - Execute PostScript setpagedevice commands as appropriate.
+ */
+
+static void
+exec_code(cups_page_header_t *header, /* I - Page header */
+ const char *code) /* I - Option choice to execute */
+{
+ char *ptr, /* Pointer into name/value string */
+ name[255], /* Name of pagedevice entry */
+ value[1024]; /* Value of pagedevice entry */
+
+
+ for (; *code != '\0';)
+ {
+ /*
+ * Search for the start of a dictionary name...
+ */
+
+ while (*code != '/' && *code != '\0')
+ code ++;
+
+ if (*code == '\0')
+ break;
+
+ /*
+ * Get the name...
+ */
+
+ code ++;
+ for (ptr = name; isalnum(*code & 255) && (ptr - name) < (sizeof(name) - 1);)
+ *ptr++ = *code++;
+ *ptr = '\0';
+
+ /*
+ * The parse the value as needed...
+ */
+
+ while (isspace(*code & 255))
+ code ++;
+
+ if (*code == '\0')
+ break;
+
+ if (*code == '[')
+ {
+ /*
+ * Read array of values...
+ */
+
+ code ++;
+ for (ptr = value;
+ *code != ']' && *code != '\0' &&
+ (ptr - value) < (sizeof(value) - 1);)
+ *ptr++ = *code++;
+ *ptr = '\0';
+ }
+ else if (*code == '(')
+ {
+ /*
+ * Read string value...
+ */
+
+ code ++;
+ for (ptr = value;
+ *code != ')' && *code != '\0' &&
+ (ptr - value) < (sizeof(value) - 1);)
+ if (*code == '\\')
+ {
+ code ++;
+ if (isdigit(*code & 255))
+ *ptr++ = (char)strtol(code, (char **)&code, 8);
+ else
+ *ptr++ = *code++;
+ }
+ else
+ *ptr++ = *code++;
+
+ *ptr = '\0';
+ }
+ else if (isdigit(*code & 255) || *code == '-')
+ {
+ /*
+ * Read single number...
+ */
+
+ for (ptr = value;
+ (isdigit(*code & 255) || *code == '-') &&
+ (ptr - value) < (sizeof(value) - 1);)
+ *ptr++ = *code++;
+ *ptr = '\0';
+ }
+ else
+ {
+ /*
+ * Read a single name...
+ */
+
+ for (ptr = value;
+ (isalnum(*code & 255) || *code == '_') &&
+ (ptr - value) < (sizeof(value) - 1);)
+ *ptr++ = *code++;
+ *ptr = '\0';
+ }
+
+ /*
+ * Assign the value as needed...
+ */
+
+ if (!strcmp(name, "MediaClass"))
+ strlcpy(header->MediaClass, value, sizeof(header->MediaClass));
+ else if (!strcmp(name, "MediaColor"))
+ strlcpy(header->MediaColor, value, sizeof(header->MediaColor));
+ else if (!strcmp(name, "MediaType"))
+ strlcpy(header->MediaType, value, sizeof(header->MediaType));
+ else if (!strcmp(name, "OutputType"))
+ strlcpy(header->OutputType, value, sizeof(header->OutputType));
+ else if (!strcmp(name, "AdvanceDistance"))
+ header->AdvanceDistance = atoi(value);
+ else if (!strcmp(name, "AdvanceMedia"))
+ header->AdvanceMedia = atoi(value);
+ else if (!strcmp(name, "Collate"))
+ header->Collate = !strcmp(value, "true");
+ else if (!strcmp(name, "CutMedia"))
+ header->CutMedia = (cups_cut_t)atoi(value);
+ else if (!strcmp(name, "Duplex"))
+ header->Duplex = !strcmp(value, "true");
+ else if (!strcmp(name, "HWResolution"))
+ sscanf(value, "%d%d", header->HWResolution + 0, header->HWResolution + 1);
+ else if (!strcmp(name, "InsertSheet"))
+ header->InsertSheet = !strcmp(value, "true");
+ else if (!strcmp(name, "Jog"))
+ header->Jog = atoi(value);
+ else if (!strcmp(name, "LeadingEdge"))
+ header->LeadingEdge = atoi(value);
+ else if (!strcmp(name, "Margins"))
+ sscanf(value, "%d%d", header->Margins + 0, header->Margins + 1);
+ else if (!strcmp(name, "ManualFeed"))
+ header->ManualFeed = !strcmp(value, "true");
+ else if (!strcmp(name, "cupsMediaPosition") || /* Compatibility */
+ !strcmp(name, "MediaPosition"))
+ header->MediaPosition = atoi(value);
+ else if (!strcmp(name, "MediaWeight"))
+ header->MediaWeight = atoi(value);
+ else if (!strcmp(name, "MirrorPrint"))
+ header->MirrorPrint = !strcmp(value, "true");
+ else if (!strcmp(name, "NegativePrint"))
+ header->NegativePrint = !strcmp(value, "true");
+ else if (!strcmp(name, "Orientation"))
+ header->Orientation = atoi(value);
+ else if (!strcmp(name, "OutputFaceUp"))
+ header->OutputFaceUp = !strcmp(value, "true");
+ else if (!strcmp(name, "Separations"))
+ header->Separations = !strcmp(value, "true");
+ else if (!strcmp(name, "TraySwitch"))
+ header->TraySwitch = !strcmp(value, "true");
+ else if (!strcmp(name, "Tumble"))
+ header->Tumble = !strcmp(value, "true");
+ else if (!strcmp(name, "cupsMediaType"))
+ header->cupsMediaType = atoi(value);
+ else if (!strcmp(name, "cupsBitsPerColor"))
+ header->cupsBitsPerColor = atoi(value);
+ else if (!strcmp(name, "cupsColorOrder"))
+ header->cupsColorOrder = (cups_order_t)atoi(value);
+ else if (!strcmp(name, "cupsColorSpace"))
+ header->cupsColorSpace = (cups_cspace_t)atoi(value);
+ else if (!strcmp(name, "cupsCompression"))
+ header->cupsCompression = atoi(value);
+ else if (!strcmp(name, "cupsRowCount"))
+ header->cupsRowCount = atoi(value);
+ else if (!strcmp(name, "cupsRowFeed"))
+ header->cupsRowFeed = atoi(value);
+ else if (!strcmp(name, "cupsRowStep"))
+ header->cupsRowStep = atoi(value);
+ }
+}
+
+
+/*
+ * 'format_CMY()' - Convert image data to CMY.
+ */
+
+static void
+format_CMY(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 3;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 64 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 64;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[1]]);
+
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr++ ^= (0x03 & OnPixels[r0[2]]);
+ else
+ *ptr++ ^= (0x03 & OffPixels[r0[2]]);
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[0]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[0]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[1]]);
+
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[2]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[2]]);
+ }
+ break;
+
+ case 8 :
+ for (x = xsize * 3; x > 0; x --, r0 ++, r1 ++)
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ cptr = ptr;
+ mptr = ptr + bandwidth;
+ yptr = ptr + 2 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ switch (z)
+ {
+ case 0 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 1 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ r0 += z;
+ r1 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_CMYK()' - Convert image data to CMYK.
+ */
+
+static void
+format_CMYK(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ *kptr, /* Pointer into black */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 4;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 128 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 128;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr ^= (0xc0 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0xc0 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[1]]);
+
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[2]]);
+
+ if ((r0[3] & 63) > dither[x & 7])
+ *ptr++ ^= (0x03 & OnPixels[r0[3]]);
+ else
+ *ptr++ ^= (0x03 & OffPixels[r0[3]]);
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[1]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[1]]);
+
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[2]]);
+
+ if ((r0[3] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[3]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[3]]);
+ }
+ break;
+
+ case 8 :
+ for (x = xsize * 4; x > 0; x --, r0 ++, r1 ++)
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ cptr = ptr;
+ mptr = ptr + bandwidth;
+ yptr = ptr + 2 * bandwidth;
+ kptr = ptr + 3 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *kptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[3] == r1[3])
+ *kptr++ = r0[3];
+ else
+ *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (*r0 > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ r0 += z;
+ r1 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_K()' - Convert image data to black.
+ */
+
+static void
+format_K(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ (void)z;
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 ++, r1 ++)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_KCMY()' - Convert image data to KCMY.
+ */
+
+static void
+format_KCMY(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ *kptr, /* Pointer into black */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 4;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 128 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if (r0[3] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 128;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[3] & 63) > dither[x & 7])
+ *ptr ^= (0xc0 & OnPixels[r0[3]]);
+ else
+ *ptr ^= (0xc0 & OffPixels[r0[3]]);
+
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[1]]);
+
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr++ ^= (0x03 & OnPixels[r0[2]]);
+ else
+ *ptr++ ^= (0x03 & OffPixels[r0[2]]);
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[3] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[3]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[3]]);
+
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[0]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[0]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[1]]);
+
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[2]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[2]]);
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[3] == r1[3])
+ *ptr++ = r0[3];
+ else
+ *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+
+ if (r0[0] == r1[0])
+ *ptr++ = r0[0];
+ else
+ *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *ptr++ = r0[1];
+ else
+ *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *ptr++ = r0[2];
+ else
+ *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ kptr = ptr;
+ cptr = ptr + bandwidth;
+ mptr = ptr + 2 * bandwidth;
+ yptr = ptr + 3 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *kptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[3] == r1[3])
+ *kptr++ = r0[3];
+ else
+ *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+ if (z == 0)
+ r0 += 3;
+ else
+ r0 += z - 1;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (*r0 > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ if (z == 0)
+ r0 += 3;
+ else
+ r0 += z - 1;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ if (z == 0)
+ r0 += 3;
+ else
+ r0 += z - 1;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ if (z == 0)
+ {
+ r0 += 3;
+ r1 += 3;
+ }
+ else
+ {
+ r0 += z - 1;
+ r1 += z - 1;
+ }
+
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_KCMYcm()' - Convert image data to KCMYcm.
+ */
+
+static void
+format_KCMYcm(cups_page_header_t *header,/* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ int pc, pm, py, pk; /* Cyan, magenta, yellow, and black values */
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ *kptr, /* Pointer into black */
+ *lcptr, /* Pointer into light cyan */
+ *lmptr, /* Pointer into light magenta */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ if (header->cupsBitsPerColor == 1)
+ bandwidth = header->cupsBytesPerLine / 6;
+ else
+ bandwidth = header->cupsBytesPerLine / 4;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --)
+ {
+ pc = *r0++ > dither[x & 15];
+ pm = *r0++ > dither[x & 15];
+ py = *r0++ > dither[x & 15];
+ pk = *r0++ > dither[x & 15];
+
+ if (pk)
+ *ptr++ ^= 32; /* Black */
+ else if (pc && pm)
+ *ptr++ ^= 17; /* Blue (cyan + light magenta) */
+ else if (pc && py)
+ *ptr++ ^= 6; /* Green (light cyan + yellow) */
+ else if (pm && py)
+ *ptr++ ^= 12; /* Red (magenta + yellow) */
+ else if (pc)
+ *ptr++ ^= 16;
+ else if (pm)
+ *ptr++ ^= 8;
+ else if (py)
+ *ptr++ ^= 4;
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[3] == r1[3])
+ *ptr++ = r0[3];
+ else
+ *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+
+ if (r0[0] == r1[0])
+ *ptr++ = r0[0];
+ else
+ *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *ptr++ = r0[1];
+ else
+ *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *ptr++ = r0[2];
+ else
+ *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ kptr = ptr;
+ cptr = ptr + bandwidth;
+ mptr = ptr + 2 * bandwidth;
+ yptr = ptr + 3 * bandwidth;
+ lcptr = ptr + 4 * bandwidth;
+ lmptr = ptr + 5 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ pc = *r0++ > dither[x & 15];
+ pm = *r0++ > dither[x & 15];
+ py = *r0++ > dither[x & 15];
+ pk = *r0++ > dither[x & 15];
+
+ if (pk)
+ *kptr ^= bitmask; /* Black */
+ else if (pc && pm)
+ {
+ *cptr ^= bitmask; /* Blue (cyan + light magenta) */
+ *lmptr ^= bitmask;
+ }
+ else if (pc && py)
+ {
+ *lcptr ^= bitmask; /* Green (light cyan + yellow) */
+ *yptr ^= bitmask;
+ }
+ else if (pm && py)
+ {
+ *mptr ^= bitmask; /* Red (magenta + yellow) */
+ *yptr ^= bitmask;
+ }
+ else if (pc)
+ *cptr ^= bitmask;
+ else if (pm)
+ *mptr ^= bitmask;
+ else if (py)
+ *yptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ lcptr ++;
+ lmptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[3] == r1[3])
+ *kptr++ = r0[3];
+ else
+ *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ switch (z)
+ {
+ case 0 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[3] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 1 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[0] > dither[x & 15] &&
+ r0[2] < dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[1] > dither[x & 15] &&
+ (r0[0] < dither[x & 15] ||
+ r0[2] > dither[x & 15]))
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 3 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[2] > dither[x & 15] &&
+ (r0[0] < dither[x & 15] ||
+ r0[1] < dither[x & 15]))
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[0] > dither[x & 15] &&
+ r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 5 :
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (r0[0] > dither[x & 15] &&
+ r0[1] > dither[x & 15] &&
+ r0[2] < dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 8 :
+ if (z == 0)
+ {
+ r0 += 3;
+ r1 += 3;
+ }
+ else
+ {
+ r0 += z - 1;
+ r1 += z - 1;
+ }
+
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_RGBA()' - Convert image data to RGBA.
+ */
+
+static void
+format_RGBA(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 4;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 128 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 2)
+ {
+ *ptr ^= 16;
+ bitmask >>= 2;
+ }
+ else
+ {
+ bitmask = 128;
+ *ptr++ ^= 1;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr ^= (0xc0 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0xc0 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[1]]);
+
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[2]]);
+
+ *ptr++ ^= 0x03;
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[0]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[1]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[1]]);
+
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[2]]);
+
+ *ptr++ ^= 0x0f;
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (r0[0] == r1[0])
+ *ptr++ = r0[0];
+ else
+ *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *ptr++ = r0[1];
+ else
+ *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *ptr++ = r0[2];
+ else
+ *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ *ptr++ = 255;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ cptr = ptr;
+ mptr = ptr + bandwidth;
+ yptr = ptr + 2 * bandwidth;
+
+ memset(ptr + 3 * bandwidth, 255, bandwidth);
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ if (z == 3)
+ {
+ memset(row, 255, header->cupsBytesPerLine);
+ break;
+ }
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ switch (z)
+ {
+ case 0 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 1 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ r0 += z;
+ r1 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_W()' - Convert image data to luminance.
+ */
+
+static void
+format_W(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ (void)z;
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 ++, r1 ++)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_YMC()' - Convert image data to YMC.
+ */
+
+static void
+format_YMC(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 3;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 64 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 64;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[2]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[1]]);
+
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr++ ^= (0x03 & OnPixels[r0[0]]);
+ else
+ *ptr++ ^= (0x03 & OffPixels[r0[0]]);
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 3)
+ {
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[2]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[2]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[1]]);
+
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[0]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[0]]);
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (r0[2] == r1[2])
+ *ptr++ = r0[2];
+ else
+ *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *ptr++ = r0[1];
+ else
+ *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[0] == r1[0])
+ *ptr++ = r0[0];
+ else
+ *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ yptr = ptr;
+ mptr = ptr + bandwidth;
+ cptr = ptr + 2 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ switch (z)
+ {
+ case 2 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 1 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 0 :
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ z = 2 - z;
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ z = 2 - z;
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ z = 2 - z;
+ r0 += z;
+ r1 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 3, r1 += 3)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'format_YMCK()' - Convert image data to YMCK.
+ */
+
+static void
+format_YMCK(cups_page_header_t *header, /* I - Page header */
+ unsigned char *row, /* IO - Bitmap data for device */
+ int y, /* I - Current row */
+ int z, /* I - Current plane */
+ int xsize, /* I - Width of image data */
+ int ysize, /* I - Height of image data */
+ int yerr0, /* I - Top Y error */
+ int yerr1, /* I - Bottom Y error */
+ ib_t *r0, /* I - Primary image data */
+ ib_t *r1) /* I - Image data for interpolation */
+{
+ ib_t *ptr, /* Pointer into row */
+ *cptr, /* Pointer into cyan */
+ *mptr, /* Pointer into magenta */
+ *yptr, /* Pointer into yellow */
+ *kptr, /* Pointer into black */
+ bitmask; /* Current mask for pixel */
+ int bitoffset; /* Current offset in line */
+ int bandwidth; /* Width of a color band */
+ int x, /* Current X coordinate on page */
+ *dither; /* Pointer into dither array */
+
+
+ switch (XPosition)
+ {
+ case -1 :
+ bitoffset = 0;
+ break;
+ default :
+ bitoffset = header->cupsBitsPerPixel * ((header->cupsWidth - xsize) / 2);
+ break;
+ case 1 :
+ bitoffset = header->cupsBitsPerPixel * (header->cupsWidth - xsize);
+ break;
+ }
+
+ ptr = row + bitoffset / 8;
+ bandwidth = header->cupsBytesPerLine / 4;
+
+ switch (header->cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 128 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if (r0[2] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[1] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[0] > dither[x & 15])
+ *ptr ^= bitmask;
+ bitmask >>= 1;
+
+ if (r0[3] > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 128;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[2] & 63) > dither[x & 7])
+ *ptr ^= (0xc0 & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0xc0 & OffPixels[r0[2]]);
+
+ if ((r0[1] & 63) > dither[x & 7])
+ *ptr ^= (0x30 & OnPixels[r0[1]]);
+ else
+ *ptr ^= (0x30 & OffPixels[r0[1]]);
+
+ if ((r0[0] & 63) > dither[x & 7])
+ *ptr ^= (0x0c & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0x0c & OffPixels[r0[0]]);
+
+ if ((r0[3] & 63) > dither[x & 7])
+ *ptr++ ^= (0x03 & OnPixels[r0[3]]);
+ else
+ *ptr++ ^= (0x03 & OffPixels[r0[3]]);
+ }
+ break;
+
+ case 4 :
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize ; x > 0; x --, r0 += 4)
+ {
+ if ((r0[2] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[2]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[2]]);
+
+ if ((r0[1] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[1]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[1]]);
+
+ if ((r0[0] & 15) > dither[x & 3])
+ *ptr ^= (0xf0 & OnPixels[r0[0]]);
+ else
+ *ptr ^= (0xf0 & OffPixels[r0[0]]);
+
+ if ((r0[3] & 15) > dither[x & 3])
+ *ptr++ ^= (0x0f & OnPixels[r0[3]]);
+ else
+ *ptr++ ^= (0x0f & OffPixels[r0[3]]);
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[2] == r1[2])
+ *ptr++ = r0[2];
+ else
+ *ptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *ptr++ = r0[1];
+ else
+ *ptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[0] == r1[0])
+ *ptr++ = r0[0];
+ else
+ *ptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[3] == r1[3])
+ *ptr++ = r0[3];
+ else
+ *ptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_BANDED :
+ yptr = ptr;
+ mptr = ptr + bandwidth;
+ cptr = ptr + 2 * bandwidth;
+ kptr = ptr + 3 * bandwidth;
+
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if (*r0++ > dither[x & 15])
+ *cptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *mptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *yptr ^= bitmask;
+ if (*r0++ > dither[x & 15])
+ *kptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 63) > dither[x & 7])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+
+ for (x = xsize; x > 0; x --)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *cptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *cptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *mptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *mptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *yptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *yptr ^= (bitmask & OffPixels[*r0++]);
+
+ if ((*r0 & 15) > dither[x & 3])
+ *kptr ^= (bitmask & OnPixels[*r0++]);
+ else
+ *kptr ^= (bitmask & OffPixels[*r0++]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (r0[0] == r1[0])
+ *cptr++ = r0[0];
+ else
+ *cptr++ = (r0[0] * yerr0 + r1[0] * yerr1) / ysize;
+
+ if (r0[1] == r1[1])
+ *mptr++ = r0[1];
+ else
+ *mptr++ = (r0[1] * yerr0 + r1[1] * yerr1) / ysize;
+
+ if (r0[2] == r1[2])
+ *yptr++ = r0[2];
+ else
+ *yptr++ = (r0[2] * yerr0 + r1[2] * yerr1) / ysize;
+
+ if (r0[3] == r1[3])
+ *kptr++ = r0[3];
+ else
+ *kptr++ = (r0[3] * yerr0 + r1[3] * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ switch (header->cupsBitsPerColor)
+ {
+ case 1 :
+ bitmask = 0x80 >> (bitoffset & 7);
+ dither = Floyd16x16[y & 15];
+
+ if (z < 3)
+ r0 += 2 - z;
+ else
+ r0 += z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if (*r0 > dither[x & 15])
+ *ptr ^= bitmask;
+
+ if (bitmask > 1)
+ bitmask >>= 1;
+ else
+ {
+ bitmask = 0x80;
+ ptr ++;
+ }
+ }
+ break;
+
+ case 2 :
+ bitmask = 0xc0 >> (bitoffset & 7);
+ dither = Floyd8x8[y & 7];
+ if (z == 3)
+ r0 += 3;
+ else
+ r0 += 2 - z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 63) > dither[x & 7])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask > 3)
+ bitmask >>= 2;
+ else
+ {
+ bitmask = 0xc0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 4 :
+ bitmask = 0xf0 >> (bitoffset & 7);
+ dither = Floyd4x4[y & 3];
+ if (z == 3)
+ r0 += 3;
+ else
+ r0 += 2 - z;
+
+ for (x = xsize; x > 0; x --, r0 += 4)
+ {
+ if ((*r0 & 15) > dither[x & 3])
+ *ptr ^= (bitmask & OnPixels[*r0]);
+ else
+ *ptr ^= (bitmask & OffPixels[*r0]);
+
+ if (bitmask == 0xf0)
+ bitmask = 0x0f;
+ else
+ {
+ bitmask = 0xf0;
+
+ ptr ++;
+ }
+ }
+ break;
+
+ case 8 :
+ if (z == 3)
+ {
+ r0 += 3;
+ r1 += 3;
+ }
+ else
+ {
+ r0 += 2 - z;
+ r1 += 2 - z;
+ }
+
+ for (x = xsize; x > 0; x --, r0 += 4, r1 += 4)
+ {
+ if (*r0 == *r1)
+ *ptr++ = *r0;
+ else
+ *ptr++ = (*r0 * yerr0 + *r1 * yerr1) / ysize;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+
+/*
+ * 'make_lut()' - Make a lookup table given gamma and brightness values.
+ */
+
+static void
+make_lut(ib_t *lut, /* I - Lookup table */
+ int colorspace, /* I - Colorspace */
+ float g, /* I - Image gamma */
+ float b) /* I - Image brightness */
+{
+ int i; /* Looping var */
+ int v; /* Current value */
+
+
+ g = 1.0 / g;
+ b = 1.0 / b;
+
+ for (i = 0; i < 256; i ++)
+ {
+ if (colorspace < 0)
+ v = 255.0 * b * (1.0 - pow(1.0 - (float)i / 255.0, g)) + 0.5;
+ else
+ v = 255.0 * (1.0 - b * (1.0 - pow((float)i / 255.0, g))) + 0.5;
+
+ if (v < 0)
+ *lut++ = 0;
+ else if (v > 255)
+ *lut++ = 255;
+ else
+ *lut++ = v;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/pstops.c b/filter/pstops.c
new file mode 100644
index 000000000..c52015db7
--- /dev/null
+++ b/filter/pstops.c
@@ -0,0 +1,1900 @@
+/*
+ * "$Id$"
+ *
+ * PostScript filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry...
+ * check_range() - Check to see if the current page is selected for
+ * copy_bytes() - Copy bytes from the input file to stdout...
+ * do_prolog() - Send the necessary document prolog commands...
+ * do_setup() - Send the necessary document setup commands...
+ * end_nup() - End processing for N-up printing...
+ * psbcp() - Enable the binary communications protocol on the printer.
+ * psgets() - Get a line from a file.
+ * pswrite() - Write data from a file.
+ * start_nup() - Start processing for N-up printing...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+
+
+/*
+ * Constants...
+ */
+
+#define MAX_PAGES 10000
+
+#define BORDER_NONE 0 /* No border or hairline border */
+#define BORDER_THICK 1 /* Think border */
+#define BORDER_SINGLE 2 /* Single-line hairline border */
+#define BORDER_SINGLE2 3 /* Single-line thick border */
+#define BORDER_DOUBLE 4 /* Double-line hairline border */
+#define BORDER_DOUBLE2 5 /* Double-line thick border */
+
+#define LAYOUT_LRBT 0 /* Left to right, bottom to top */
+#define LAYOUT_LRTB 1 /* Left to right, top to bottom */
+#define LAYOUT_RLBT 2 /* Right to left, bottom to top */
+#define LAYOUT_RLTB 3 /* Right to left, top to bottom */
+#define LAYOUT_BTLR 4 /* Bottom to top, left to right */
+#define LAYOUT_TBLR 5 /* Top to bottom, left to right */
+#define LAYOUT_BTRL 6 /* Bottom to top, right to left */
+#define LAYOUT_TBRL 7 /* Top to bottom, right to left */
+
+#define LAYOUT_NEGATEY 1 /* The bits for the layout */
+#define LAYOUT_NEGATEX 2 /* definitions above... */
+#define LAYOUT_VERTICAL 4
+
+#define PROT_STANDARD 0 /* Adobe standard protocol */
+#define PROT_BCP 1 /* Adobe BCP protocol */
+#define PROT_TBCP 2 /* Adobe TBCP protocol */
+
+
+/*
+ * Globals...
+ */
+
+int NumPages = 0; /* Number of pages in file */
+long Pages[MAX_PAGES]; /* Offsets to each page */
+const char *PageRanges = NULL; /* Range of pages selected */
+const char *PageSet = NULL; /* All, Even, Odd pages */
+int Order = 0, /* 0 = normal, 1 = reverse pages */
+ Flip = 0, /* Flip/mirror pages */
+ NUp = 1, /* Number of pages on each sheet (1, 2, 4) */
+ Collate = 0, /* Collate copies? */
+ Copies = 1, /* Number of copies */
+ UseESPsp = 0, /* Use ESPshowpage? */
+ Border = BORDER_NONE, /* Border around pages */
+ Layout = LAYOUT_LRTB, /* Layout of N-up pages */
+ NormalLandscape = 0, /* Normal rotation for landscape? */
+ Protocol = PROT_STANDARD;
+ /* Transmission protocol to use */
+
+
+/*
+ * Local functions...
+ */
+
+static int check_range(int page);
+static void copy_bytes(FILE *fp, size_t length);
+static void do_prolog(ppd_file_t *ppd);
+static void do_setup(ppd_file_t *ppd, int copies, int collate,
+ int slowcollate, float g, float b);
+static void end_nup(int number);
+#define is_first_page(p) (NUp == 1 || (((p)+1) % NUp) == 1)
+#define is_last_page(p) (NUp > 1 && (((p)+1) % NUp) == 0)
+#define is_not_last_page(p) (NUp > 1 && ((p) % NUp) != 0)
+static void psbcp(ppd_file_t *ppd);
+static char *psgets(char *buf, size_t *bytes, FILE *fp);
+static size_t pswrite(const char *buf, size_t bytes, FILE *fp);
+static void start_nup(int number, int show_border);
+
+
+/*
+ * 'main()' - Main entry...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ FILE *fp; /* Print file */
+ ppd_file_t *ppd; /* PPD file */
+ ppd_attr_t *attr; /* Attribute in PPD file */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ const char *val; /* Option value */
+ char tempfile[255]; /* Temporary file name */
+ FILE *temp; /* Temporary file */
+ int tempfd; /* Temporary file descriptor */
+ int number; /* Page number */
+ int slowcollate; /* 1 if we need to collate manually */
+ int sloworder; /* 1 if we need to order manually */
+ int slowduplex; /* 1 if we need an even number of pages */
+ char line[8192]; /* Line buffer */
+ size_t len; /* Length of line buffer */
+ float g; /* Gamma correction value */
+ float b; /* Brightness factor */
+ int level; /* Nesting level for embedded files */
+ int nbytes, /* Number of bytes read */
+ tbytes; /* Total bytes to read for binary data */
+ int page; /* Current page sequence number */
+ int real_page; /* "Real" page number in document */
+ int page_count; /* Page count for NUp */
+ int basepage; /* Base page number */
+ int subpage; /* Sub-page number */
+ int copy; /* Current copy */
+ int saweof; /* Did we see a %%EOF tag? */
+ int sent_espsp, /* Did we send the ESPshowpage commands? */
+ sent_prolog, /* Did we send the prolog commands? */
+ sent_setup; /* Did we send the setup commands? */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ fputs("ERROR: pstops job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ fp = stdin;
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = fopen(argv[6], "rb")) == NULL)
+ {
+ fprintf(stderr, "ERROR: unable to open print file \"%s\" - %s\n",
+ argv[6], strerror(errno));
+ return (1);
+ }
+ }
+
+ /*
+ * Process command-line options and write the prolog...
+ */
+
+ g = 1.0;
+ b = 1.0;
+
+ Copies = atoi(argv[4]);
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ ppd = SetCommonOptions(num_options, options, 1);
+
+ if (ppd && ppd->landscape > 0)
+ NormalLandscape = 1;
+
+ if ((val = cupsGetOption("page-ranges", num_options, options)) != NULL)
+ PageRanges = val;
+
+ if ((val = cupsGetOption("page-set", num_options, options)) != NULL)
+ PageSet = val;
+
+ if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
+ {
+ /*
+ * This IPP attribute is unnecessarily complicated...
+ *
+ * single-document, separate-documents-collated-copies, and
+ * single-document-new-sheet all require collated copies.
+ *
+ * separate-documents-uncollated-copies allows for uncollated copies.
+ */
+
+ Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
+ }
+
+ if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
+ (!strcasecmp(val, "true") ||!strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes")))
+ Collate = 1;
+
+ if ((val = cupsGetOption("OutputOrder", num_options, options)) != NULL &&
+ !strcasecmp(val, "Reverse"))
+ Order = 1;
+
+ if ((val = cupsGetOption("number-up", num_options, options)) != NULL)
+ NUp = atoi(val);
+
+ if ((val = cupsGetOption("page-border", num_options, options)) != NULL)
+ {
+ if (!strcasecmp(val, "none"))
+ Border = BORDER_NONE;
+ else if (!strcasecmp(val, "single"))
+ Border = BORDER_SINGLE;
+ else if (!strcasecmp(val, "single-thick"))
+ Border = BORDER_SINGLE2;
+ else if (!strcasecmp(val, "double"))
+ Border = BORDER_DOUBLE;
+ else if (!strcasecmp(val, "double-thick"))
+ Border = BORDER_DOUBLE2;
+ }
+
+ if ((val = cupsGetOption("number-up-layout", num_options, options)) != NULL)
+ {
+ if (!strcasecmp(val, "lrtb"))
+ Layout = LAYOUT_LRTB;
+ else if (!strcasecmp(val, "lrbt"))
+ Layout = LAYOUT_LRBT;
+ else if (!strcasecmp(val, "rltb"))
+ Layout = LAYOUT_RLTB;
+ else if (!strcasecmp(val, "rlbt"))
+ Layout = LAYOUT_RLBT;
+ else if (!strcasecmp(val, "tblr"))
+ Layout = LAYOUT_TBLR;
+ else if (!strcasecmp(val, "tbrl"))
+ Layout = LAYOUT_TBRL;
+ else if (!strcasecmp(val, "btlr"))
+ Layout = LAYOUT_BTLR;
+ else if (!strcasecmp(val, "btrl"))
+ Layout = LAYOUT_BTRL;
+ }
+
+ if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+ g = atoi(val) * 0.001f;
+
+ if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
+ b = atoi(val) * 0.01f;
+
+ if ((val = cupsGetOption("mirror", num_options, options)) != NULL &&
+ (!strcasecmp(val, "true") ||!strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes")))
+ Flip = 1;
+
+ /*
+ * See if we have to filter the fast or slow way...
+ */
+
+ if (ppd && ppd->manual_copies && Duplex && Copies > 1)
+ {
+ /*
+ * Force collated copies when printing a duplexed document to
+ * a non-PS printer that doesn't do hardware copy generation.
+ * Otherwise the copies will end up on the front/back side of
+ * each page. Also, set the "slowduplex" option to make sure
+ * that we output an even number of pages...
+ */
+
+ Collate = 1;
+ slowduplex = 1;
+ }
+ else
+ slowduplex = 0;
+
+ if (ppdFindOption(ppd, "Collate") == NULL && Collate && Copies > 1)
+ slowcollate = 1;
+ else
+ slowcollate = 0;
+
+ if (ppdFindOption(ppd, "OutputOrder") == NULL && Order)
+ sloworder = 1;
+ else
+ sloworder = 0;
+
+ /*
+ * If we need to filter slowly, then create a temporary file for page data...
+ *
+ * If the temp file can't be created, then we'll ignore the collating/output
+ * order options...
+ */
+
+ if (sloworder || slowcollate)
+ {
+ tempfd = cupsTempFd(tempfile, sizeof(tempfile));
+ if (tempfd < 0)
+ {
+ perror("ERROR: Unable to open temp file");
+ temp = NULL;
+ }
+ else
+ temp = fdopen(tempfd, "wb+");
+
+ if (temp == NULL)
+ slowcollate = sloworder = 0;
+ }
+ else
+ temp = NULL;
+
+ /*
+ * See if we should use a binary transmission protocol...
+ */
+
+ if ((attr = ppdFindAttr(ppd, "cupsProtocol", NULL)) != NULL &&
+ attr->value != NULL)
+ {
+ if (!strcasecmp(attr->value, "TBCP"))
+ Protocol = PROT_TBCP;
+ else if (!strcasecmp(attr->value, "BCP"))
+ {
+ Protocol = PROT_BCP;
+
+ psbcp(ppd);
+ }
+ }
+
+ /*
+ * Write any "exit server" options that have been selected...
+ */
+
+ ppdEmit(ppd, stdout, PPD_ORDER_EXIT);
+
+ /*
+ * Write any JCL commands that are needed to print PostScript code...
+ */
+
+ ppdEmitJCL(ppd, stdout, atoi(argv[1]), argv[2], argv[3]);
+
+ /*
+ * Read the first line to see if we have DSC comments...
+ */
+
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ {
+ fputs("ERROR: Empty print file!\n", stderr);
+ ppdClose(ppd);
+ return (1);
+ }
+
+ /*
+ * Handle leading PJL fun...
+ */
+
+ while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
+ {
+ /*
+ * Yup, we have leading PJL fun, so skip it until we hit the line
+ * with "ENTER LANGUAGE"...
+ */
+
+ fputs("DEBUG: Skipping PJL header...\n", stderr);
+
+ while (strstr(line, "ENTER LANGUAGE") == NULL)
+ {
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+ }
+
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+ }
+
+ /*
+ * Switch to TBCP mode as needed...
+ */
+
+ if (Protocol == PROT_TBCP)
+ fputs("\001M", stdout);
+
+ /*
+ * Start sending the document with any commands needed...
+ */
+
+ fwrite(line, 1, len, stdout);
+
+ saweof = 0;
+ sent_espsp = 0;
+ sent_prolog = 0;
+ sent_setup = 0;
+
+ if (Copies != 1 && (!Collate || !slowcollate))
+ {
+ /*
+ * Tell the document processor the copy and duplex options
+ * that are required...
+ */
+
+ printf("%%%%Requirements: numcopies(%d)%s%s\n", Copies,
+ Collate ? " collate" : "",
+ Duplex ? " duplex" : "");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
+
+ printf("%%RBINumCopies: %d\n", Copies);
+ }
+ else
+ {
+ /*
+ * Tell the document processor the duplex option that is required...
+ */
+
+ if (Duplex)
+ puts("%%Requirements: duplex");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
+
+ puts("%RBINumCopies: 1");
+ }
+
+ /*
+ * Figure out if we should use ESPshowpage or not...
+ */
+
+ val = cupsGetOption("page-label", num_options, options);
+
+ if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1 ||
+ Border || strstr(line, "EPS") != NULL)
+ {
+ /*
+ * Yes, use ESPshowpage...
+ */
+
+ UseESPsp = 1;
+ }
+
+ fprintf(stderr, "DEBUG: slowcollate=%d, slowduplex=%d, sloworder=%d\n",
+ slowcollate, slowduplex, sloworder);
+
+ if (!strncmp(line, "%!PS-Adobe-", 11) && !strstr(line, "EPSF"))
+ {
+ /*
+ * OK, we have DSC comments and this isn't an EPS file; read until we
+ * find a %%Page comment...
+ */
+
+ puts("%%Pages: (atend)");
+
+ level = 0;
+
+ while (!feof(fp))
+ {
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+
+ if (!strncmp(line, "%%", 2))
+ fprintf(stderr, "DEBUG: %d %s", level, line);
+ else if (line[0] != '%' && line[0] && !sent_espsp && UseESPsp)
+ {
+ /*
+ * Send ESPshowpage stuff...
+ */
+
+ sent_espsp = 1;
+
+ puts("userdict/ESPshowpage/showpage load put\n"
+ "userdict/showpage{}put");
+ }
+
+ if (!strncmp(line, "%%BeginDocument:", 16) ||
+ !strncmp(line, "%%BeginDocument ", 16)) /* Adobe Acrobat BUG */
+ {
+ fputs(line, stdout);
+ level ++;
+ }
+ else if (!strncmp(line, "%%EndDocument", 13) && level > 0)
+ {
+ fputs(line, stdout);
+ level --;
+ }
+ else if (!strncmp(line, "%cupsRotation:", 14) && level == 0)
+ {
+ /*
+ * Reset orientation of document?
+ */
+
+ int orient = (atoi(line + 14) / 90) & 3;
+
+ if (orient != Orientation)
+ {
+ Orientation = (4 - Orientation + orient) & 3;
+ UpdatePageVars();
+ Orientation = orient;
+ }
+ }
+ else if (!strncmp(line, "%%BeginProlog", 13) && level == 0)
+ {
+ /*
+ * Write the existing comment line, and then follow with patches
+ * and prolog commands...
+ */
+
+ fputs(line, stdout);
+
+ if (!sent_prolog)
+ {
+ sent_prolog = 1;
+ do_prolog(ppd);
+ }
+ }
+ else if (!strncmp(line, "%%BeginSetup", 12) && level == 0)
+ {
+ /*
+ * Write the existing comment line, and then follow with document
+ * setup commands...
+ */
+
+ fputs(line, stdout);
+
+ if (!sent_prolog)
+ {
+ sent_prolog = 1;
+ do_prolog(ppd);
+ }
+
+ if (!sent_setup)
+ {
+ sent_setup = 1;
+ do_setup(ppd, Copies, Collate, slowcollate, g, b);
+ }
+ }
+ else if (!strncmp(line, "%%Page:", 7) && level == 0)
+ break;
+ else if (!strncmp(line, "%%BeginBinary:", 14) ||
+ (!strncmp(line, "%%BeginData:", 12) &&
+ !strstr(line, "ASCII") && !strstr(line, "Hex")))
+ {
+ /*
+ * Copy binary data...
+ */
+
+ tbytes = atoi(strchr(line, ':') + 1);
+ fputs(line, stdout);
+
+ while (tbytes > 0)
+ {
+ if (tbytes > sizeof(line))
+ nbytes = fread(line, 1, sizeof(line), fp);
+ else
+ nbytes = fread(line, 1, tbytes, fp);
+
+ if (nbytes < 1)
+ {
+ perror("ERROR: Early end-of-file while reading binary data");
+ return (1);
+ }
+
+ pswrite(line, nbytes, stdout);
+ tbytes -= nbytes;
+ }
+ }
+ else if (strncmp(line, "%%Pages:", 8) != 0)
+ pswrite(line, len, stdout);
+ }
+
+ /*
+ * Make sure we have the prolog and setup commands written...
+ */
+
+ if (!sent_prolog)
+ {
+ puts("%%BeginProlog");
+
+ sent_prolog = 1;
+ do_prolog(ppd);
+
+ puts("%%EndProlog");
+ }
+
+ if (!sent_setup)
+ {
+ puts("%%BeginSetup");
+
+ sent_setup = 1;
+ do_setup(ppd, Copies, Collate, slowcollate, g, b);
+
+ puts("%%EndSetup");
+ }
+
+ if (!sent_espsp && UseESPsp)
+ {
+ /*
+ * Send ESPshowpage stuff...
+ */
+
+ sent_espsp = 1;
+
+ puts("userdict/ESPshowpage/showpage load put\n"
+ "userdict/showpage{}put");
+ }
+
+ /*
+ * Write the page and label prologs...
+ */
+
+ if (NUp == 2 || NUp == 6)
+ {
+ /*
+ * For 2- and 6-up output, rotate the labels to match the orientation
+ * of the pages...
+ */
+
+ if (Orientation & 1)
+ WriteLabelProlog(val, PageBottom, PageWidth - PageLength + PageTop,
+ PageLength);
+ else
+ WriteLabelProlog(val, PageLeft, PageRight, PageLength);
+ }
+ else
+ WriteLabelProlog(val, PageBottom, PageTop, PageWidth);
+
+ /*
+ * Then read all of the pages, filtering as needed...
+ */
+
+ for (page = 1, real_page = 1;;)
+ {
+ if (!strncmp(line, "%%", 2))
+ fprintf(stderr, "DEBUG: %d %s", level, line);
+
+ if (!strncmp(line, "%%BeginDocument:", 16) ||
+ !strncmp(line, "%%BeginDocument ", 16)) /* Adobe Acrobat BUG */
+ level ++;
+ else if (!strncmp(line, "%%EndDocument", 13) && level > 0)
+ level --;
+ else if (!strcmp(line, "\004") && len == 1)
+ break;
+ else if (!strncmp(line, "%%EOF", 5) && level == 0)
+ {
+ fputs("DEBUG: Saw EOF!\n", stderr);
+ saweof = 1;
+ break;
+ }
+ else if (!strncmp(line, "%%Page:", 7) && level == 0)
+ {
+ if (!check_range(real_page))
+ {
+ while (!feof(fp))
+ {
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+
+ if (!strncmp(line, "%%", 2))
+ fprintf(stderr, "DEBUG: %d %s", level, line);
+
+ if (!strncmp(line, "%%BeginDocument:", 16) ||
+ !strncmp(line, "%%BeginDocument ", 16)) /* Adobe Acrobat BUG */
+ level ++;
+ else if (!strncmp(line, "%%EndDocument", 13) && level > 0)
+ level --;
+ else if (!strncmp(line, "%%Page:", 7) && level == 0)
+ {
+ real_page ++;
+ break;
+ }
+ else if (!strncmp(line, "%%BeginBinary:", 14) ||
+ (!strncmp(line, "%%BeginData:", 12) &&
+ !strstr(line, "ASCII") && !strstr(line, "Hex")))
+ {
+ /*
+ * Skip binary data...
+ */
+
+ tbytes = atoi(strchr(line, ':') + 1);
+
+ while (tbytes > 0)
+ {
+ if (tbytes > sizeof(line))
+ nbytes = fread(line, 1, sizeof(line), fp);
+ else
+ nbytes = fread(line, 1, tbytes, fp);
+
+ if (nbytes < 1)
+ {
+ perror("ERROR: Early end-of-file while reading binary data");
+ return (1);
+ }
+
+ tbytes -= nbytes;
+ }
+ }
+ }
+
+ continue;
+ }
+
+ if (!sloworder && NumPages > 0)
+ end_nup(NumPages - 1);
+
+ if (slowcollate || sloworder)
+ Pages[NumPages] = ftell(temp);
+
+ if (!sloworder)
+ {
+ if (is_first_page(NumPages))
+ {
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies);
+
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+ }
+
+ start_nup(NumPages, 1);
+ }
+
+ NumPages ++;
+ real_page ++;
+ }
+ else if (!strncmp(line, "%%BeginBinary:", 14) ||
+ (!strncmp(line, "%%BeginData:", 12) &&
+ !strstr(line, "ASCII") && !strstr(line, "Hex")))
+ {
+ /*
+ * Copy binary data...
+ */
+
+ tbytes = atoi(strchr(line, ':') + 1);
+
+ if (!sloworder)
+ fputs(line, stdout);
+ if (slowcollate || sloworder)
+ fputs(line, temp);
+
+ while (tbytes > 0)
+ {
+ if (tbytes > sizeof(line))
+ nbytes = fread(line, 1, sizeof(line), fp);
+ else
+ nbytes = fread(line, 1, tbytes, fp);
+
+ if (nbytes < 1)
+ {
+ perror("ERROR: Early end-of-file while reading binary data");
+ return (1);
+ }
+
+ if (!sloworder)
+ pswrite(line, nbytes, stdout);
+
+ if (slowcollate || sloworder)
+ fwrite(line, 1, nbytes, temp);
+
+ tbytes -= nbytes;
+ }
+ }
+ else if (!strncmp(line, "%%Trailer", 9) && level == 0)
+ {
+ fputs("DEBUG: Saw Trailer!\n", stderr);
+ break;
+ }
+ else
+ {
+ if (!sloworder)
+ pswrite(line, len, stdout);
+
+ if (slowcollate || sloworder)
+ fwrite(line, 1, len, temp);
+ }
+
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+ }
+
+ if (!sloworder)
+ {
+ end_nup(NumPages - 1);
+
+ if (is_not_last_page(NumPages))
+ {
+ start_nup(NUp - 1, 0);
+ end_nup(NUp - 1);
+ }
+
+ if (Duplex && !(page & 1))
+ {
+ /*
+ * Make sure we have an even number of pages...
+ */
+
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page, slowcollate ? 1 : Copies);
+
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ start_nup(NUp - 1, 0);
+ puts("showpage");
+ end_nup(NUp - 1);
+ }
+ }
+
+ if (slowcollate || sloworder)
+ {
+ Pages[NumPages] = ftell(temp);
+
+ if (!sloworder)
+ {
+ while (Copies > 1)
+ {
+ rewind(temp);
+
+ for (number = 0; number < NumPages; number ++)
+ {
+ if (is_first_page(number))
+ {
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d 1\n", page);
+
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+ }
+
+ start_nup(number, 1);
+ copy_bytes(temp, Pages[number + 1] - Pages[number]);
+ end_nup(number);
+ }
+
+ if (is_not_last_page(NumPages))
+ {
+ start_nup(NUp - 1, 0);
+ end_nup(NUp - 1);
+ }
+
+ if (Duplex && !(page & 1))
+ {
+ /*
+ * Make sure we have an even number of pages...
+ */
+
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d 1\n", page);
+
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ start_nup(NUp - 1, 0);
+ puts("showpage");
+ end_nup(NUp - 1);
+ }
+
+ Copies --;
+ }
+ }
+ else
+ {
+ page_count = (NumPages + NUp - 1) / NUp;
+ copy = 0;
+
+ fprintf(stderr, "DEBUG: page_count=%d\n", page_count);
+
+ do
+ {
+ if (Duplex && (page_count & 1))
+ basepage = page_count;
+ else
+ basepage = page_count - 1;
+
+ for (; basepage >= 0; basepage --)
+ {
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page,
+ slowcollate ? 1 : Copies);
+
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ if (basepage >= page_count)
+ {
+ start_nup(NUp - 1, 0);
+ puts("showpage");
+ end_nup(NUp - 1);
+ }
+ else
+ {
+ for (subpage = 0, number = basepage * NUp;
+ subpage < NUp && number < NumPages;
+ subpage ++, number ++)
+ {
+ start_nup(number, 1);
+ fseek(temp, Pages[number], SEEK_SET);
+ copy_bytes(temp, Pages[number + 1] - Pages[number]);
+ end_nup(number);
+ }
+
+ if (is_not_last_page(number))
+ {
+ start_nup(NUp - 1, 0);
+ end_nup(NUp - 1);
+ }
+ }
+ }
+
+ copy ++;
+ }
+ while (copy < Copies && slowcollate);
+ }
+ }
+
+ /*
+ * Copy the trailer, if any...
+ */
+
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", page - 1);
+
+ if (UseESPsp)
+ puts("userdict/showpage/ESPshowpage load put\n");
+
+ while (!feof(fp))
+ {
+ len = sizeof(line);
+ if (psgets(line, &len, fp) == NULL)
+ break;
+
+ if (!(!strcmp(line, "\004") && len == 1) &&
+ strncmp(line, "%%Pages:", 8) != 0)
+ pswrite(line, len, stdout);
+
+ if (!strncmp(line, "%%EOF", 5))
+ {
+ fputs("DEBUG: Saw EOF!\n", stderr);
+ saweof = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * No DSC comments - write any page commands and then the rest of the file...
+ */
+
+ if (slowcollate && Copies > 1)
+ printf("%%%%Pages: %d\n", Copies);
+ else
+ puts("%%Pages: 1");
+
+ if (UseESPsp)
+ puts("userdict/ESPshowpage/showpage load put\n"
+ "userdict/showpage{}put");
+
+ puts("%%BeginProlog");
+ WriteLabelProlog(val, PageBottom, PageTop, PageWidth);
+ do_prolog(ppd);
+ puts("%%EndProlog");
+
+ puts("%%BeginSetup");
+ do_setup(ppd, Copies, Collate, slowcollate, g, b);
+ puts("%%EndSetup");
+
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: 1 %d\n", slowcollate ? 1 : Copies);
+
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+
+ saweof = 1;
+
+ while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0)
+ {
+ pswrite(line, nbytes, stdout);
+
+ if (slowcollate)
+ fwrite(line, 1, nbytes, temp);
+ }
+
+ if (UseESPsp)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+
+ if (slowcollate)
+ {
+ while (Copies > 1)
+ {
+ if (ppd == NULL || ppd->num_filters == 0)
+ fputs("PAGE: 1 1\n", stderr);
+
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
+ rewind(temp);
+ copy_bytes(temp, 0);
+ Copies --;
+
+ if (UseESPsp)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+ }
+ }
+ }
+
+ /*
+ * Send %%EOF if needed...
+ */
+
+ if (!saweof)
+ puts("%%EOF");
+
+ /*
+ * End the job with the appropriate JCL command or CTRL-D otherwise.
+ */
+
+ if (ppd != NULL)
+ {
+ if (ppd->jcl_end)
+ fputs(ppd->jcl_end, stdout);
+ else
+ {
+ if (ppd->num_filters == 0)
+ putchar(0x04);
+
+ if (Protocol == PROT_TBCP)
+ fputs("\033%-12345X", stdout);
+ }
+ }
+
+ /*
+ * Close files and remove the temporary file if needed...
+ */
+
+ if (slowcollate || sloworder)
+ {
+ fclose(temp);
+ unlink(tempfile);
+ }
+
+ ppdClose(ppd);
+
+ if (fp != stdin)
+ fclose(fp);
+
+ return (0);
+}
+
+
+/*
+ * 'check_range()' - Check to see if the current page is selected for
+ * printing.
+ */
+
+static int /* O - 1 if selected, 0 otherwise */
+check_range(int page) /* I - Page number */
+{
+ const char *range; /* Pointer into range string */
+ int lower, upper; /* Lower and upper page numbers */
+
+
+ if (PageSet != NULL)
+ {
+ /*
+ * See if we only print even or odd pages...
+ */
+
+ if (!strcasecmp(PageSet, "even") && ((page - 1) % (NUp << 1)) < NUp)
+ return (0);
+ if (!strcasecmp(PageSet, "odd") && ((page - 1) % (NUp << 1)) >= NUp)
+ return (0);
+ }
+
+ if (PageRanges == NULL)
+ return (1); /* No range, print all pages... */
+
+ for (range = PageRanges; *range != '\0';)
+ {
+ if (*range == '-')
+ {
+ lower = 1;
+ range ++;
+ upper = strtol(range, (char **)&range, 10);
+ }
+ else
+ {
+ lower = strtol(range, (char **)&range, 10);
+
+ if (*range == '-')
+ {
+ range ++;
+ if (!isdigit(*range & 255))
+ upper = 65535;
+ else
+ upper = strtol(range, (char **)&range, 10);
+ }
+ else
+ upper = lower;
+ }
+
+ if (page >= lower && page <= upper)
+ return (1);
+
+ if (*range == ',')
+ range ++;
+ else
+ break;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'copy_bytes()' - Copy bytes from the input file to stdout...
+ */
+
+static void
+copy_bytes(FILE *fp, /* I - File to read from */
+ size_t length) /* I - Length of page data */
+{
+ char buffer[8192]; /* Data buffer */
+ size_t nbytes, /* Number of bytes read */
+ nleft; /* Number of bytes left/remaining */
+
+
+ nleft = length;
+
+ while (nleft > 0 || length == 0)
+ {
+ if (nleft > sizeof(buffer) || length == 0)
+ nbytes = sizeof(buffer);
+ else
+ nbytes = nleft;
+
+ if ((nbytes = fread(buffer, 1, nbytes, fp)) < 1)
+ return;
+
+ nleft -= nbytes;
+
+ pswrite(buffer, nbytes, stdout);
+ }
+}
+
+
+/*
+ * 'do_prolog()' - Send the necessary document prolog commands...
+ */
+
+static void
+do_prolog(ppd_file_t *ppd) /* I - PPD file */
+{
+ /*
+ * Send the document prolog commands...
+ */
+
+ if (ppd != NULL && ppd->patches != NULL)
+ {
+ puts("%%BeginFeature: *JobPatchFile 1");
+ puts(ppd->patches);
+ puts("%%EndFeature");
+ }
+
+ ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
+}
+
+
+/*
+ * 'do_setup()' - Send the necessary document setup commands...
+ */
+
+static void
+do_setup(ppd_file_t *ppd, /* I - PPD file */
+ int copies, /* I - Number of copies */
+ int collate, /* I - Collate output? */
+ int slowcollate, /* I - Slow collate */
+ float g, /* I - Gamma value */
+ float b) /* I - Brightness value */
+{
+ /*
+ * Send all the printer-specific setup commands...
+ */
+
+ ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
+ ppdEmit(ppd, stdout, PPD_ORDER_ANY);
+
+ /*
+ * Set the number of copies for the job...
+ */
+
+ if (copies != 1 && (!collate || !slowcollate))
+ {
+ printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", copies);
+ printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse{1 dict begin"
+ "/NumCopies exch def currentdict end "
+ "setpagedevice}{userdict/#copies 3 -1 roll put}ifelse\n", copies);
+ printf("%%RBIEndNonPPDFeature\n");
+ }
+
+ /*
+ * Changes to the transfer function must be made AFTER any
+ * setpagedevice code...
+ */
+
+ if (g != 1.0 || b != 1.0)
+ printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
+ "ifelse %.3f mul } bind settransfer\n", g, b);
+
+ /*
+ * Make sure we have rectclip and rectstroke procedures of some sort...
+ */
+
+ WriteCommon();
+}
+
+
+/*
+ * 'end_nup()' - End processing for N-up printing...
+ */
+
+static void
+end_nup(int number) /* I - Page number */
+{
+ puts("");
+
+ if (Flip || Orientation || NUp > 1)
+ puts("userdict /ESPsave get restore");
+
+ switch (NUp)
+ {
+ case 1 :
+ if (UseESPsp)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+ break;
+
+ case 2 :
+ case 6 :
+ if (is_last_page(number) && UseESPsp)
+ {
+ if (Orientation & 1)
+ {
+ /*
+ * Rotate the labels back to portrait...
+ */
+
+ WriteLabels(Orientation - 1);
+ }
+ else if (Orientation == 0)
+ {
+ /*
+ * Rotate the labels to landscape...
+ */
+
+ WriteLabels(NormalLandscape ? 1 : 3);
+ }
+ else
+ {
+ /*
+ * Rotate the labels to landscape...
+ */
+
+ WriteLabels(NormalLandscape ? 3 : 1);
+ }
+
+ puts("ESPshowpage");
+ }
+ break;
+
+ default :
+ if (is_last_page(number) && UseESPsp)
+ {
+ WriteLabels(Orientation);
+ puts("ESPshowpage");
+ }
+ break;
+ }
+
+ fflush(stdout);
+}
+
+
+/*
+ * 'psbcp()' - Enable the binary communications protocol on the printer.
+ */
+
+static void
+psbcp(ppd_file_t *ppd) /* I - PPD file */
+{
+ if (ppd->jcl_begin)
+ fputs(ppd->jcl_begin, stdout);
+ if (ppd->jcl_ps)
+ fputs(ppd->jcl_ps, stdout);
+
+ if (ppd->language_level == 1)
+ {
+ /*
+ * Use setsoftwareiomode for BCP mode...
+ */
+
+ fputs("%!PS-Adobe-3.0 ExitServer\n", stdout);
+ fputs("%%Title: (BCP - Level 1)\n", stdout);
+ fputs("%%EndComments\n", stdout);
+ fputs("%%BeginExitServer: 0\n", stdout);
+ fputs("serverdict begin 0 exitserver\n", stdout);
+ fputs("%%EndExitServer\n", stdout);
+ fputs("statusdict begin\n", stdout);
+ fputs("/setsoftwareiomode known {100 setsoftwareiomode}\n", stdout);
+ fputs("end\n", stdout);
+ fputs("%EOF\n", stdout);
+ }
+ else
+ {
+ /*
+ * Use setdevparams for BCP mode...
+ */
+
+ fputs("%!PS-Adobe-3.0\n", stdout);
+ fputs("%%Title: (BCP - Level 2)\n", stdout);
+ fputs("%%EndComments\n", stdout);
+ fputs("currentsysparams\n", stdout);
+ fputs("/CurInputDevice 2 copy known {\n", stdout);
+ fputs("get\n", stdout);
+ fputs("<</Protocol /Binary>> setdevparams\n", stdout);
+ fputs("}{\n", stdout);
+ fputs("pop pop\n", stdout);
+ fputs("} ifelse\n", stdout);
+ fputs("%EOF\n", stdout);
+ }
+
+ if (ppd->jcl_end)
+ fputs(ppd->jcl_end, stdout);
+ else if (ppd->num_filters == 0)
+ putchar(0x04);
+}
+
+
+/*
+ * 'psgets()' - Get a line from a file.
+ *
+ * Note:
+ *
+ * This function differs from the gets() function in that it
+ * handles any combination of CR, LF, or CR LF to end input
+ * lines.
+ */
+
+static char * /* O - String or NULL if EOF */
+psgets(char *buf, /* I - Buffer to read into */
+ size_t *bytes, /* IO - Length of buffer */
+ FILE *fp) /* I - File to read from */
+{
+ char *bufptr; /* Pointer into buffer */
+ int ch; /* Character from file */
+ size_t len; /* Max length of string */
+
+
+ len = *bytes - 1;
+ bufptr = buf;
+ ch = EOF;
+
+ while ((bufptr - buf) < len)
+ {
+ if ((ch = getc(fp)) == EOF)
+ break;
+
+ if (ch == '\r')
+ {
+ /*
+ * Got a CR; see if there is a LF as well...
+ */
+
+ ch = getc(fp);
+
+ if (ch != EOF && ch != '\n')
+ {
+ ungetc(ch, fp); /* Nope, save it for later... */
+ ch = '\r';
+ }
+ else
+ *bufptr++ = '\r';
+ break;
+ }
+ else if (ch == '\n')
+ break;
+ else
+ *bufptr++ = ch;
+ }
+
+ /*
+ * Add a trailing newline if it is there...
+ */
+
+ if (ch == '\n' || ch == '\r')
+ {
+ if ((bufptr - buf) < len)
+ *bufptr++ = ch;
+ else
+ ungetc(ch, fp);
+ }
+
+ /*
+ * Nul-terminate the string and return it (or NULL for EOF).
+ */
+
+ *bufptr = '\0';
+ *bytes = bufptr - buf;
+
+ if (ch == EOF && bufptr == buf)
+ return (NULL);
+ else
+ return (buf);
+}
+
+
+/*
+ * 'pswrite()' - Write data from a file.
+ */
+
+static size_t /* O - Number of bytes written */
+pswrite(const char *buf, /* I - Buffer to write */
+ size_t bytes, /* I - Bytes to write */
+ FILE *fp) /* I - File to write to */
+{
+ size_t count; /* Remaining bytes */
+
+
+ switch (Protocol)
+ {
+ case PROT_STANDARD :
+ return (fwrite(buf, 1, bytes, fp));
+
+ case PROT_BCP :
+ for (count = bytes; count > 0; count --, buf ++)
+ switch (*buf)
+ {
+ case 0x01 : /* CTRL-A */
+ case 0x03 : /* CTRL-C */
+ case 0x04 : /* CTRL-D */
+ case 0x05 : /* CTRL-E */
+ case 0x11 : /* CTRL-Q */
+ case 0x13 : /* CTRL-S */
+ case 0x14 : /* CTRL-T */
+ case 0x1c : /* CTRL-\ */
+ putchar(0x01);
+ putchar(*buf ^ 0x40);
+ break;
+
+ default :
+ putchar(*buf);
+ break;
+ }
+ return (bytes);
+
+ case PROT_TBCP :
+ for (count = bytes; count > 0; count --, buf ++)
+ switch (*buf)
+ {
+ case 0x01 : /* CTRL-A */
+ case 0x03 : /* CTRL-C */
+ case 0x04 : /* CTRL-D */
+ case 0x05 : /* CTRL-E */
+ case 0x11 : /* CTRL-Q */
+ case 0x13 : /* CTRL-S */
+ case 0x14 : /* CTRL-T */
+ case 0x1b : /* CTRL-[ (aka ESC) */
+ case 0x1c : /* CTRL-\ */
+ putchar(0x01);
+ putchar(*buf ^ 0x40);
+ break;
+
+ default :
+ putchar(*buf);
+ break;
+ }
+ return (bytes);
+ }
+
+ return (fwrite(buf, 1, bytes, fp));
+}
+
+
+/*
+ * 'start_nup()' - Start processing for N-up printing...
+ */
+
+static void
+start_nup(int number, /* I - Page number */
+ int show_border) /* I - Show the page border? */
+{
+ int pos; /* Position on page */
+ int x, y; /* Relative position of subpage */
+ float w, l, /* Width and length of subpage */
+ tx, ty; /* Translation values for subpage */
+ float pw, pl; /* Printable width and length of full page */
+
+
+ if (Flip || Orientation || NUp > 1)
+ puts("userdict/ESPsave save put");
+
+ if (Flip)
+ printf("%.1f 0.0 translate -1 1 scale\n", PageWidth);
+
+ pos = number % NUp;
+ pw = PageRight - PageLeft;
+ pl = PageTop - PageBottom;
+
+ fprintf(stderr, "DEBUG: pw = %.1f, pl = %.1f\n", pw, pl);
+ fprintf(stderr, "DEBUG: PageLeft = %.1f, PageRight = %.1f\n", PageLeft, PageRight);
+ fprintf(stderr, "DEBUG: PageTop = %.1f, PageBottom = %.1f\n", PageTop, PageBottom);
+ fprintf(stderr, "DEBUG: PageWidth = %.1f, PageLength = %.1f\n", PageWidth, PageLength);
+
+ switch (Orientation)
+ {
+ case 1 : /* Landscape */
+ printf("%.1f 0.0 translate 90 rotate\n", PageLength);
+ break;
+ case 2 : /* Reverse Portrait */
+ printf("%.1f %.1f translate 180 rotate\n", PageWidth, PageLength);
+ break;
+ case 3 : /* Reverse Landscape */
+ printf("0.0 %.1f translate -90 rotate\n", PageWidth);
+ break;
+ }
+
+ if (Duplex && NUp > 1 && ((number / NUp) & 1))
+ printf("%.1f %.1f translate\n", PageWidth - PageRight, PageBottom);
+ else if (NUp > 1)
+ printf("%.1f %.1f translate\n", PageLeft, PageBottom);
+
+ switch (NUp)
+ {
+ default :
+ w = PageWidth;
+ l = PageLength;
+ break;
+
+ case 2 :
+ if (Orientation & 1)
+ {
+ x = pos & 1;
+
+ if (Layout & LAYOUT_NEGATEY)
+ x = 1 - x;
+
+ w = pl;
+ l = w * PageLength / PageWidth;
+
+ if (l > (pw * 0.5))
+ {
+ l = pw * 0.5;
+ w = l * PageWidth / PageLength;
+ }
+
+ tx = 0.5 * (pw * 0.5 - l);
+ ty = 0.5 * (pl - w);
+
+ if (NormalLandscape)
+ printf("0.0 %.1f translate -90 rotate\n", pl);
+ else
+ printf("%.1f 0.0 translate 90 rotate\n", pw);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n",
+ ty, tx + l * x, w / PageWidth, l / PageLength);
+ }
+ else
+ {
+ x = pos & 1;
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 1 - x;
+
+ l = pw;
+ w = l * PageWidth / PageLength;
+
+ if (w > (pl * 0.5))
+ {
+ w = pl * 0.5;
+ l = w * PageLength / PageWidth;
+ }
+
+ tx = 0.5 * (pl * 0.5 - w);
+ ty = 0.5 * (pw - l);
+
+ if (NormalLandscape)
+ printf("%.1f 0.0 translate 90 rotate\n", pw);
+ else
+ printf("0.0 %.1f translate -90 rotate\n", pl);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n",
+ tx + w * x, ty, w / PageWidth, l / PageLength);
+ }
+ break;
+
+ case 4 :
+ if (Layout & LAYOUT_VERTICAL)
+ {
+ x = (pos / 2) & 1;
+ y = pos & 1;
+ }
+ else
+ {
+ x = pos & 1;
+ y = (pos / 2) & 1;
+ }
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 1 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 1 - y;
+
+ w = pw * 0.5;
+ l = w * PageLength / PageWidth;
+
+ if (l > (pl * 0.5))
+ {
+ l = pl * 0.5;
+ w = l * PageWidth / PageLength;
+ }
+
+ tx = 0.5 * (pw * 0.5 - w);
+ ty = 0.5 * (pl * 0.5 - l);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
+ w / PageWidth, l / PageLength);
+ break;
+
+ case 6 :
+ if (Orientation & 1)
+ {
+ if (Layout & LAYOUT_VERTICAL)
+ {
+ x = pos / 3;
+ y = pos % 3;
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 1 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 2 - y;
+ }
+ else
+ {
+ x = pos & 1;
+ y = pos / 2;
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 1 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 2 - y;
+ }
+
+ w = pl * 0.5;
+ l = w * PageLength / PageWidth;
+
+ if (l > (pw * 0.333))
+ {
+ l = pw * 0.333;
+ w = l * PageWidth / PageLength;
+ }
+
+ tx = 0.5 * (pl - 2 * w);
+ ty = 0.5 * (pw - 3 * l);
+
+ if (NormalLandscape)
+ printf("0.0 %.1f translate -90 rotate\n", pl);
+ else
+ printf("%.1f 0.0 translate 90 rotate\n", pw);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n",
+ tx + x * w, ty + y * l, w / PageWidth, l / PageLength);
+ }
+ else
+ {
+ if (Layout & LAYOUT_VERTICAL)
+ {
+ x = pos / 2;
+ y = pos & 1;
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 2 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 1 - y;
+ }
+ else
+ {
+ x = pos % 3;
+ y = pos / 3;
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 2 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 1 - y;
+ }
+
+ l = pw * 0.5;
+ w = l * PageWidth / PageLength;
+
+ if (w > (pl * 0.333))
+ {
+ w = pl * 0.333;
+ l = w * PageLength / PageWidth;
+ }
+
+ tx = 0.5 * (pl - 3 * w);
+ ty = 0.5 * (pw - 2 * l);
+
+ if (NormalLandscape)
+ printf("%.1f 0.0 translate 90 rotate\n", pw);
+ else
+ printf("0.0 %.1f translate -90 rotate\n", pl);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n",
+ tx + w * x, ty + l * y, w / PageWidth, l / PageLength);
+ }
+ break;
+
+ case 9 :
+ if (Layout & LAYOUT_VERTICAL)
+ {
+ x = (pos / 3) % 3;
+ y = pos % 3;
+ }
+ else
+ {
+ x = pos % 3;
+ y = (pos / 3) % 3;
+ }
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 2 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 2 - y;
+
+ w = pw * 0.333;
+ l = w * PageLength / PageWidth;
+
+ if (l > (pl * 0.333))
+ {
+ l = pl * 0.333;
+ w = l * PageWidth / PageLength;
+ }
+
+ tx = 0.5 * (pw * 0.333 - w);
+ ty = 0.5 * (pl * 0.333 - l);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
+ w / PageWidth, l / PageLength);
+ break;
+
+ case 16 :
+ if (Layout & LAYOUT_VERTICAL)
+ {
+ x = (pos / 4) & 3;
+ y = pos & 3;
+ }
+ else
+ {
+ x = pos & 3;
+ y = (pos / 4) & 3;
+ }
+
+ if (Layout & LAYOUT_NEGATEX)
+ x = 3 - x;
+
+ if (Layout & LAYOUT_NEGATEY)
+ y = 3 - y;
+
+ w = pw * 0.25;
+ l = w * PageLength / PageWidth;
+
+ if (l > (pl * 0.25))
+ {
+ l = pl * 0.25;
+ w = l * PageWidth / PageLength;
+ }
+
+ tx = 0.5 * (pw * 0.25 - w);
+ ty = 0.5 * (pl * 0.25 - l);
+
+ printf("%.1f %.1f translate %.3f %.3f scale\n", tx + x * w, ty + y * l,
+ w / PageWidth, l / PageLength);
+ break;
+ }
+
+ /*
+ * Draw borders as necessary...
+ */
+
+ if (Border && show_border)
+ {
+ int rects; /* Number of border rectangles */
+ float fscale, /* Scaling value for points */
+ margin; /* Current margin for borders */
+
+
+ rects = (Border & BORDER_DOUBLE) ? 2 : 1;
+ fscale = PageWidth / w;
+ margin = 2.25 * fscale;
+
+ /*
+ * Set the line width and color...
+ */
+
+ puts("gsave");
+ printf("%.3f setlinewidth 0 setgray newpath\n",
+ (Border & BORDER_THICK) ? 0.5 * fscale : 0.24 * fscale);
+
+ /*
+ * Draw border boxes...
+ */
+
+ for (; rects > 0; rects --, margin += 2 * fscale)
+ if (NUp > 1)
+ printf("%.1f %.1f %.1f %.1f ESPrs\n",
+ margin,
+ margin,
+ PageWidth - 2 * margin,
+ PageLength - 2 * margin);
+ else
+ printf("%.1f %.1f %.1f %.1f ESPrs\n",
+ PageLeft + margin,
+ PageBottom + margin,
+ PageRight - PageLeft - 2 * margin,
+ PageTop - PageBottom - 2 * margin);
+
+ /*
+ * Restore pen settings...
+ */
+
+ puts("grestore");
+ }
+
+ if (NUp > 1)
+ {
+ /*
+ * Clip the page that follows to the bounding box of the page...
+ */
+
+ printf("0 0 %.1f %.1f ESPrc\n", PageWidth, PageLength);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/pstops.dsp b/filter/pstops.dsp
new file mode 100644
index 000000000..956c8ab65
--- /dev/null
+++ b/filter/pstops.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="pstops" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=pstops - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "pstops.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "pstops.mak" CFG="pstops - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "pstops - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "pstops - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pstops - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"pstops.exe"
+
+!ELSEIF "$(CFG)" == "pstops - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "pstops___Win32_Debug"
+# PROP BASE Intermediate_Dir "pstops___Win32_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"pstopsd.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "pstops - Win32 Release"
+# Name "pstops - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\pstops.c
+
+!IF "$(CFG)" == "pstops - Win32 Release"
+
+!ELSEIF "$(CFG)" == "pstops - Win32 Debug"
+
+# ADD CPP /Zi
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/filter/raster.c b/filter/raster.c
new file mode 100644
index 000000000..d2ff6e4c9
--- /dev/null
+++ b/filter/raster.c
@@ -0,0 +1,258 @@
+/*
+ * "$Id$"
+ *
+ * Raster file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights for the CUPS Raster source
+ * files are outlined in the GNU Library General Public License, located
+ * in the "pstoraster" directory. If this file is missing or damaged
+ * please contact Easy Software Products at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This code and any derivative of it may be used and distributed
+ * freely under the terms of the GNU General Public License when
+ * used with GNU Ghostscript or its derivatives. Use of the code
+ * (or any derivative of it) with software other than GNU
+ * GhostScript (or its derivatives) is governed by the CUPS license
+ * agreement.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsRasterClose() - Close a raster stream.
+ * cupsRasterOpen() - Open a raster stream.
+ * cupsRasterReadHeader() - Read a raster page header.
+ * cupsRasterReadPixels() - Read raster pixels.
+ * cupsRasterWriteHeader() - Write a raster page header.
+ * cupsRasterWritePixels() - Write raster pixels.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "raster.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * 'cupsRasterClose()' - Close a raster stream.
+ */
+
+void
+cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
+{
+ if (r != NULL)
+ free(r);
+}
+
+
+/*
+ * 'cupsRasterOpen()' - Open a raster stream.
+ */
+
+cups_raster_t * /* O - New stream */
+cupsRasterOpen(int fd, /* I - File descriptor */
+ cups_mode_t mode) /* I - Mode */
+{
+ cups_raster_t *r; /* New stream */
+
+
+ if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
+ return (NULL);
+
+ r->fd = fd;
+ r->mode = mode;
+
+ if (mode == CUPS_RASTER_READ)
+ {
+ /*
+ * Open for read - get sync word...
+ */
+
+ if (read(fd, &(r->sync), sizeof(r->sync)) < sizeof(r->sync))
+ {
+ free(r);
+ return (NULL);
+ }
+
+ if (r->sync != CUPS_RASTER_SYNC &&
+ r->sync != CUPS_RASTER_REVSYNC)
+ {
+ free(r);
+ return (NULL);
+ }
+ }
+ else
+ {
+ /*
+ * Open for write - put sync word...
+ */
+
+ r->sync = CUPS_RASTER_SYNC;
+ if (write(fd, &(r->sync), sizeof(r->sync)) < sizeof(r->sync))
+ {
+ free(r);
+ return (NULL);
+ }
+ }
+
+ return (r);
+}
+
+
+/*
+ * 'cupsRasterReadHeader()' - Read a raster page header.
+ */
+
+unsigned /* O - 1 on success, 0 on fail */
+cupsRasterReadHeader(cups_raster_t *r, /* I - Raster stream */
+ cups_page_header_t *h) /* I - Pointer to header data */
+{
+ int len; /* Number of words to swap */
+ union swap_s /* Swapping structure */
+ {
+ unsigned char b[4];
+ unsigned v;
+ } *s;
+
+
+ if (r == NULL || r->mode != CUPS_RASTER_READ)
+ return (0);
+
+ if (cupsRasterReadPixels(r, (unsigned char *)h, sizeof(cups_page_header_t)) <
+ sizeof(cups_page_header_t))
+ return (0);
+
+ if (r->sync == CUPS_RASTER_REVSYNC)
+ for (len = (sizeof(cups_page_header_t) - 256) / 4,
+ s = (union swap_s *)&(h->AdvanceDistance);
+ len > 0;
+ len --, s ++)
+ s->v = (((((s->b[0] << 8) | s->b[1]) << 8) | s->b[2]) << 8) | s->b[3];
+
+ return (1);
+}
+
+
+/*
+ * 'cupsRasterReadPixels()' - Read raster pixels.
+ */
+
+unsigned /* O - Number of bytes read */
+cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */
+ unsigned char *p, /* I - Pointer to pixel buffer */
+ unsigned len) /* I - Number of bytes to read */
+{
+ int bytes; /* Bytes read */
+ unsigned remaining; /* Bytes remaining */
+
+
+ if (r == NULL || r->mode != CUPS_RASTER_READ)
+ return (0);
+
+ remaining = len;
+
+ while (remaining > 0)
+ {
+ bytes = read(r->fd, p, remaining);
+
+ if (bytes == 0)
+ return (0);
+ else if (bytes < 0)
+ {
+ if (errno != EINTR)
+ return (0);
+ else
+ continue;
+ }
+
+ remaining -= bytes;
+ p += bytes;
+ }
+
+ return (len);
+}
+
+
+/*
+ * 'cupsRasterWriteHeader()' - Write a raster page header.
+ */
+
+unsigned
+cupsRasterWriteHeader(cups_raster_t *r,
+ cups_page_header_t *h)
+{
+ if (r == NULL || r->mode != CUPS_RASTER_WRITE)
+ return (0);
+
+ return (cupsRasterWritePixels(r, (unsigned char *)h,
+ sizeof(cups_page_header_t)) ==
+ sizeof(cups_page_header_t));
+}
+
+
+/*
+ * 'cupsRasterWritePixels()' - Write raster pixels.
+ */
+
+unsigned /* O - Number of bytes written */
+cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */
+ unsigned char *p, /* I - Bytes to write */
+ unsigned len)/* I - Number of bytes to write */
+{
+ int bytes; /* Bytes read */
+ unsigned remaining; /* Bytes remaining */
+
+
+ if (r == NULL || r->mode != CUPS_RASTER_WRITE)
+ return (0);
+
+ remaining = len;
+
+ while (remaining > 0)
+ {
+ bytes = write(r->fd, p, remaining);
+
+ if (bytes == 0)
+ return (0);
+ else if (bytes < 0)
+ {
+ if (errno != EINTR)
+ return (0);
+ else
+ continue;
+ }
+
+ remaining -= bytes;
+ p += bytes;
+ }
+
+ return (len);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/raster.h b/filter/raster.h
new file mode 100644
index 000000000..b7216e16d
--- /dev/null
+++ b/filter/raster.h
@@ -0,0 +1,263 @@
+/*
+ * "$Id$"
+ *
+ * Raster file definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights for the CUPS Raster source
+ * files are outlined in the GNU Library General Public License, located
+ * in the "pstoraster" directory. If this file is missing or damaged
+ * please contact Easy Software Products at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This code and any derivative of it may be used and distributed
+ * freely under the terms of the GNU General Public License when
+ * used with GNU Ghostscript or its derivatives. Use of the code
+ * (or any derivative of it) with software other than GNU
+ * GhostScript (or its derivatives) is governed by the CUPS license
+ * agreement.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+#ifndef _CUPS_RASTER_H_
+# define _CUPS_RASTER_H_
+
+# ifdef __cplusplus
+extern "C" {
+# endif /* __cplusplus */
+
+/*
+ * Every non-PostScript printer driver that supports raster images should
+ * use the application/vnd.cups-raster image file format. Since both the
+ * PostScript RIP (pstoraster, based on GNU Ghostscript) and Image RIP
+ * (imagetoraster, located in the filter directory) use it, using this format
+ * saves you a lot of work. Also, the PostScript RIP passes any printer
+ * options that are in a PS file to your driver this way as well...
+ */
+
+/*
+ * Constants...
+ */
+
+# define CUPS_RASTER_SYNC 0x52615374 /* RaSt */
+# define CUPS_RASTER_REVSYNC 0x74536152 /* tSaR */
+
+
+/*
+ * The following definition can be used to determine if the
+ * colorimetric colorspaces (CIEXYZ, CIELAB, and ICCn) are
+ * defined...
+ */
+
+# define CUPS_RASTER_HAVE_COLORIMETRIC 1
+
+
+/*
+ * Types...
+ */
+
+typedef enum
+{
+ CUPS_RASTER_READ, /* Open stream for reading */
+ CUPS_RASTER_WRITE /* Open stream for writing */
+} cups_mode_t;
+
+typedef enum
+{
+ CUPS_FALSE, /* Logical false */
+ CUPS_TRUE /* Logical true */
+} cups_bool_t;
+
+typedef enum
+{
+ CUPS_JOG_NONE, /* Never move pages */
+ CUPS_JOG_FILE, /* Move pages after this file */
+ CUPS_JOG_JOB, /* Move pages after this job */
+ CUPS_JOG_SET /* Move pages after this set */
+} cups_jog_t;
+
+typedef enum
+{
+ CUPS_ORIENT_0, /* Don't rotate the page */
+ CUPS_ORIENT_90, /* Rotate the page counter-clockwise */
+ CUPS_ORIENT_180, /* Turn the page upside down */
+ CUPS_ORIENT_270 /* Rotate the page clockwise */
+} cups_orient_t;
+
+typedef enum
+{
+ CUPS_CUT_NONE, /* Never cut the roll */
+ CUPS_CUT_FILE, /* Cut the roll after this file */
+ CUPS_CUT_JOB, /* Cut the roll after this job */
+ CUPS_CUT_SET, /* Cut the roll after this set */
+ CUPS_CUT_PAGE /* Cut the roll after this page */
+} cups_cut_t;
+
+typedef enum
+{
+ CUPS_ADVANCE_NONE, /* Never advance the roll */
+ CUPS_ADVANCE_FILE, /* Advance the roll after this file */
+ CUPS_ADVANCE_JOB, /* Advance the roll after this job */
+ CUPS_ADVANCE_SET, /* Advance the roll after this set */
+ CUPS_ADVANCE_PAGE /* Advance the roll after this page */
+} cups_adv_t;
+
+typedef enum
+{
+ CUPS_EDGE_TOP, /* Leading edge is the top of the page */
+ CUPS_EDGE_RIGHT, /* Leading edge is the right of the page */
+ CUPS_EDGE_BOTTOM, /* Leading edge is the bottom of the page */
+ CUPS_EDGE_LEFT /* Leading edge is the left of the page */
+} cups_edge_t;
+
+typedef enum
+{
+ CUPS_ORDER_CHUNKED, /* CMYK CMYK CMYK ... */
+ CUPS_ORDER_BANDED, /* CCC MMM YYY KKK ... */
+ CUPS_ORDER_PLANAR /* CCC ... MMM ... YYY ... KKK ... */
+} cups_order_t;
+
+typedef enum
+{
+ CUPS_CSPACE_W, /* Luminance */
+ CUPS_CSPACE_RGB, /* Red, green, blue */
+ CUPS_CSPACE_RGBA, /* Red, green, blue, alpha */
+ CUPS_CSPACE_K, /* Black */
+ CUPS_CSPACE_CMY, /* Cyan, magenta, yellow */
+ CUPS_CSPACE_YMC, /* Yellow, magenta, cyan */
+ CUPS_CSPACE_CMYK, /* Cyan, magenta, yellow, black */
+ CUPS_CSPACE_YMCK, /* Yellow, magenta, cyan, black */
+ CUPS_CSPACE_KCMY, /* Black, cyan, magenta, yellow */
+ CUPS_CSPACE_KCMYcm, /* Black, cyan, magenta, yellow, *
+ * light-cyan, light-magenta */
+ CUPS_CSPACE_GMCK, /* Gold, magenta, yellow, black */
+ CUPS_CSPACE_GMCS, /* Gold, magenta, yellow, silver */
+ CUPS_CSPACE_WHITE, /* White ink (as black) */
+ CUPS_CSPACE_GOLD, /* Gold foil */
+ CUPS_CSPACE_SILVER, /* Silver foil */
+
+ CUPS_CSPACE_CIEXYZ, /* CIE XYZ */
+ CUPS_CSPACE_CIELab, /* CIE Lab */
+
+ CUPS_CSPACE_ICC1 = 32, /* ICC-based, 1 color */
+ CUPS_CSPACE_ICC2, /* ICC-based, 2 colors */
+ CUPS_CSPACE_ICC3, /* ICC-based, 3 colors */
+ CUPS_CSPACE_ICC4, /* ICC-based, 4 colors */
+ CUPS_CSPACE_ICC5, /* ICC-based, 5 colors */
+ CUPS_CSPACE_ICC6, /* ICC-based, 6 colors */
+ CUPS_CSPACE_ICC7, /* ICC-based, 7 colors */
+ CUPS_CSPACE_ICC8, /* ICC-based, 8 colors */
+ CUPS_CSPACE_ICC9, /* ICC-based, 9 colors */
+ CUPS_CSPACE_ICCA, /* ICC-based, 10 colors */
+ CUPS_CSPACE_ICCB, /* ICC-based, 11 colors */
+ CUPS_CSPACE_ICCC, /* ICC-based, 12 colors */
+ CUPS_CSPACE_ICCD, /* ICC-based, 13 colors */
+ CUPS_CSPACE_ICCE, /* ICC-based, 14 colors */
+ CUPS_CSPACE_ICCF /* ICC-based, 15 colors */
+} cups_cspace_t;
+
+
+/*
+ * The page header structure contains the standard PostScript page device
+ * dictionary, along with some CUPS-specific parameters that are provided
+ * by the RIPs...
+ */
+
+typedef struct
+{
+ /**** Standard Page Device Dictionary String Values ****/
+ char MediaClass[64]; /* MediaClass string */
+ char MediaColor[64]; /* MediaColor string */
+ char MediaType[64]; /* MediaType string */
+ char OutputType[64]; /* OutputType string */
+
+ /**** Standard Page Device Dictionary Integer Values ****/
+ unsigned AdvanceDistance; /* AdvanceDistance value in points */
+ cups_adv_t AdvanceMedia; /* AdvanceMedia value (see above) */
+ cups_bool_t Collate; /* Collated copies value */
+ cups_cut_t CutMedia; /* CutMedia value (see above) */
+ cups_bool_t Duplex; /* Duplexed (double-sided) value */
+ unsigned HWResolution[2]; /* Resolution in dots-per-inch */
+ unsigned ImagingBoundingBox[4]; /* Pixel region that is painted (points) */
+ cups_bool_t InsertSheet; /* InsertSheet value */
+ cups_jog_t Jog; /* Jog value (see above) */
+ cups_edge_t LeadingEdge; /* LeadingEdge value (see above) */
+ unsigned Margins[2]; /* Lower-lefthand margins in points */
+ cups_bool_t ManualFeed; /* ManualFeed value */
+ unsigned MediaPosition; /* MediaPosition value */
+ unsigned MediaWeight; /* MediaWeight value in grams/m^2 */
+ cups_bool_t MirrorPrint; /* MirrorPrint value */
+ cups_bool_t NegativePrint; /* NegativePrint value */
+ unsigned NumCopies; /* Number of copies to produce */
+ cups_orient_t Orientation; /* Orientation value (see above) */
+ cups_bool_t OutputFaceUp; /* OutputFaceUp value */
+ unsigned PageSize[2]; /* Width and length of page in points */
+ cups_bool_t Separations; /* Separations value */
+ cups_bool_t TraySwitch; /* TraySwitch value */
+ cups_bool_t Tumble; /* Tumble value */
+
+ /**** CUPS Page Device Dictionary Values ****/
+ unsigned cupsWidth; /* Width of page image in pixels */
+ unsigned cupsHeight; /* Height of page image in pixels */
+ unsigned cupsMediaType; /* Media type code */
+ unsigned cupsBitsPerColor; /* Number of bits for each color */
+ unsigned cupsBitsPerPixel; /* Number of bits for each pixel */
+ unsigned cupsBytesPerLine; /* Number of bytes per line */
+ cups_order_t cupsColorOrder; /* Order of colors */
+ cups_cspace_t cupsColorSpace; /* True colorspace */
+ unsigned cupsCompression; /* Device compression to use */
+ unsigned cupsRowCount; /* Rows per band */
+ unsigned cupsRowFeed; /* Feed between bands */
+ unsigned cupsRowStep; /* Spacing between lines */
+} cups_page_header_t;
+
+
+/*
+ * The raster structure maintains information about a raster data
+ * stream...
+ */
+
+typedef struct
+{
+ unsigned sync; /* Sync word from start of stream */
+ int fd; /* File descriptor */
+ cups_mode_t mode; /* Read/write mode */
+} cups_raster_t;
+
+
+/*
+ * Prototypes...
+ */
+
+extern void cupsRasterClose(cups_raster_t *r);
+extern cups_raster_t *cupsRasterOpen(int fd, cups_mode_t mode);
+extern unsigned cupsRasterReadHeader(cups_raster_t *r,
+ cups_page_header_t *h);
+extern unsigned cupsRasterReadPixels(cups_raster_t *r,
+ unsigned char *p, unsigned len);
+extern unsigned cupsRasterWriteHeader(cups_raster_t *r,
+ cups_page_header_t *h);
+extern unsigned cupsRasterWritePixels(cups_raster_t *r,
+ unsigned char *p, unsigned len);
+
+# ifdef __cplusplus
+}
+# endif /* __cplusplus */
+
+#endif /* !_CUPS_RASTER_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/rastertodymo.c b/filter/rastertodymo.c
new file mode 100644
index 000000000..1844ba3eb
--- /dev/null
+++ b/filter/rastertodymo.c
@@ -0,0 +1,597 @@
+/*
+ * "$Id$"
+ *
+ * Label printer filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2001-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * Setup() - Prepare the printer for printing.
+ * StartPage() - Start a page of graphics.
+ * EndPage() - Finish a page of graphics.
+ * Shutdown() - Shutdown the printer.
+ * CancelJob() - Cancel the current job...
+ * OutputLine() - Output a line of graphics.
+ * main() - Main entry and processing of driver.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include "raster.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+
+/*
+ * This driver filter currently supports Dymo and Zebra label printers.
+ *
+ * The Dymo portion of the driver has been tested with the 300, 330,
+ * and 330 Turbo label printers; it may also work with older models.
+ * The Dymo printers support printing at 136, 203, and 300 DPI.
+ *
+ * The Zebra portion of the driver has been tested with the LP-2844Z label
+ * printer; it may also work with other models. The driver supports both
+ * EPL and ZPL as defined in Zebra's on-line developer documentation.
+ */
+
+/*
+ * Model number constants...
+ */
+
+#define DYMO_3x0 0 /* Dymo Labelwriter 300/330/330 Turbo */
+
+#define ZEBRA_EPL_LINE 0x10 /* Zebra EPL line mode printers */
+#define ZEBRA_EPL_PAGE 0x11 /* Zebra EPL page mode printers */
+#define ZEBRA_ZPL 0x12 /* Zebra ZPL-based printers */
+
+
+/*
+ * Globals...
+ */
+
+unsigned char *Buffer; /* Output buffer */
+int ModelNumber, /* cupsModelNumber attribute */
+ Page, /* Current page */
+ Feed, /* Number of lines to skip */
+ Canceled; /* Non-zero if job is canceled */
+
+
+/*
+ * Prototypes...
+ */
+
+void Setup(void);
+void StartPage(cups_page_header_t *header);
+void EndPage(cups_page_header_t *header);
+void CancelJob(int sig);
+void OutputLine(cups_page_header_t *header, int y);
+
+
+/*
+ * 'Setup()' - Prepare the printer for printing.
+ */
+
+void
+Setup(void)
+{
+ int i; /* Looping var */
+ ppd_file_t *ppd; /* PPD file */
+
+
+ /*
+ * Get the model number from the PPD file...
+ */
+
+ if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
+ {
+ ModelNumber = ppd->model_number;
+ ppdClose(ppd);
+ }
+
+ /*
+ * Initialize based on the model number...
+ */
+
+ switch (ModelNumber)
+ {
+ case DYMO_3x0 :
+ /*
+ * Clear any remaining data...
+ */
+
+ for (i = 0; i < 100; i ++)
+ putchar(0x1b);
+
+ /*
+ * Reset the printer...
+ */
+
+ fputs("\033@", stdout);
+ break;
+
+ case ZEBRA_EPL_LINE :
+ break;
+
+ case ZEBRA_EPL_PAGE :
+ break;
+
+ case ZEBRA_ZPL :
+ break;
+ }
+}
+
+
+/*
+ * 'StartPage()' - Start a page of graphics.
+ */
+
+void
+StartPage(cups_page_header_t *header) /* I - Page header */
+{
+ int length; /* Actual label length */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Register a signal handler to eject the current page if the
+ * job is canceled.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, CancelJob);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = CancelJob;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, CancelJob);
+#endif /* HAVE_SIGSET */
+
+ switch (ModelNumber)
+ {
+ case DYMO_3x0 :
+ /*
+ * Setup printer/job attributes...
+ */
+
+ length = header->PageSize[1] * header->HWResolution[1] / 72;
+
+ printf("\033L%c%c", length >> 8, length);
+ printf("\033D%c", header->cupsBytesPerLine);
+
+ printf("\033%c", header->cupsCompression + 'c'); /* Darkness */
+ break;
+
+ case ZEBRA_EPL_LINE :
+ /*
+ * Set darkness...
+ */
+
+ printf("D%d", 7 * header->cupsCompression / 100);
+
+ /*
+ * Start buffered output...
+ */
+
+ putchar('B');
+ break;
+
+ case ZEBRA_EPL_PAGE :
+ /*
+ * Set darkness...
+ */
+
+ printf("D%d", 15 * header->cupsCompression / 100);
+
+ /*
+ * Set label size...
+ */
+
+ printf("q%d\n", header->cupsWidth);
+ break;
+
+ case ZEBRA_ZPL :
+ /*
+ * Set darkness...
+ */
+
+ printf("~SD%02d\n", 30 * header->cupsCompression / 100);
+
+ /*
+ * Start bitmap graphics...
+ */
+
+ printf("~DGR:CUPS.GRF,%d,%d,\n",
+ header->cupsHeight * header->cupsBytesPerLine,
+ header->cupsBytesPerLine);
+ break;
+ }
+
+ /*
+ * Allocate memory for a line of graphics...
+ */
+
+ Buffer = malloc(header->cupsBytesPerLine);
+ Feed = 0;
+}
+
+
+/*
+ * 'EndPage()' - Finish a page of graphics.
+ */
+
+void
+EndPage(cups_page_header_t *header) /* I - Page header */
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ switch (ModelNumber)
+ {
+ case DYMO_3x0 :
+ /*
+ * Eject the current page...
+ */
+
+ fputs("\033E", stdout);
+ break;
+
+ case ZEBRA_EPL_LINE :
+ /*
+ * End buffered output, eject the label...
+ */
+
+ putchar('E');
+ break;
+
+ case ZEBRA_EPL_PAGE :
+ /*
+ * Print the label...
+ */
+
+ puts("P1");
+ break;
+
+ case ZEBRA_ZPL :
+ if (Canceled)
+ {
+ /*
+ * Cancel bitmap download...
+ */
+
+ puts("~DN");
+ break;
+ }
+
+ /*
+ * Start label, set origin to 1/8,1/16", and set length...
+ */
+
+ puts("^XA");
+ printf("^LH%d,%d\n", header->HWResolution[0] / 8,
+ header->HWResolution[1] / 16);
+ printf("^LL%d\n", header->cupsHeight);
+
+ /*
+ * Cut labels if requested...
+ */
+
+ if (header->CutMedia)
+ puts("^MMC");
+ else
+ puts("^MMT");
+
+ /*
+ * Display the label image...
+ */
+
+ puts("~FO0,0^XGR:CUPS.GRF,1,1^FS");
+
+ /*
+ * End the label and eject...
+ */
+
+ puts("^XZ");
+ break;
+ }
+
+ fflush(stdout);
+
+ /*
+ * Unregister the signal handler...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Free memory...
+ */
+
+ free(Buffer);
+}
+
+
+/*
+ * 'CancelJob()' - Cancel the current job...
+ */
+
+void
+CancelJob(int sig) /* I - Signal */
+{
+ /*
+ * Tell the main loop to stop...
+ */
+
+ (void)sig;
+
+ Canceled = 1;
+}
+
+
+/*
+ * 'OutputLine()' - Output a line of graphics...
+ */
+
+void
+OutputLine(cups_page_header_t *header, /* I - Page header */
+ int y) /* I - Line number */
+{
+ int i; /* Looping var */
+ unsigned char *ptr; /* Pointer into buffer */
+
+
+ switch (ModelNumber)
+ {
+ case DYMO_3x0 :
+ /*
+ * See if the line is blank; if not, write it to the printer...
+ */
+
+ if (Buffer[0] ||
+ memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1))
+ {
+ if (Feed)
+ {
+ while (Feed > 255)
+ {
+ printf("\033f\001%c", 255);
+ Feed -= 255;
+ }
+
+ printf("\033f\001%c", Feed);
+ Feed = 0;
+ }
+
+ putchar(0x16);
+ fwrite(Buffer, header->cupsBytesPerLine, 1, stdout);
+ fflush(stdout);
+
+#ifdef __sgi
+ /*
+ * This hack works around a bug in the IRIX serial port driver when
+ * run at high baud rates (e.g. 115200 baud)... This results in
+ * slightly slower label printing, but at least the labels come
+ * out properly.
+ */
+
+ sginap(1);
+#endif /* __sgi */
+ }
+ else
+ Feed ++;
+ break;
+
+ case ZEBRA_EPL_LINE :
+ printf("g%03d", header->cupsBytesPerLine);
+ fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
+ fflush(stdout);
+ break;
+
+ case ZEBRA_EPL_PAGE :
+ printf("GW0,%d,%d,1", y, header->cupsBytesPerLine);
+ fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
+ putchar('\n');
+ fflush(stdout);
+ break;
+
+ case ZEBRA_ZPL :
+ for (i = header->cupsBytesPerLine, ptr = Buffer; i > 0; i --, ptr ++)
+ if (!*ptr && (i == 1 || !memcmp(ptr, ptr + 1, i - 1)))
+ {
+ putchar(',');
+ break;
+ }
+ else
+ printf("%02X", *ptr);
+
+ putchar('\n');
+ break;
+ }
+}
+
+
+/*
+ * 'main()' - Main entry and processing of driver.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int fd; /* File descriptor */
+ cups_raster_t *ras; /* Raster stream for printing */
+ cups_page_header_t header; /* Page header from file */
+ int y; /* Current line */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ /*
+ * We don't have the correct number of arguments; write an error message
+ * and return.
+ */
+
+ fputs("ERROR: rastertodymo job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Open the page stream...
+ */
+
+ if (argc == 7)
+ {
+ if ((fd = open(argv[6], O_RDONLY)) == -1)
+ {
+ perror("ERROR: Unable to open raster file - ");
+ sleep(1);
+ return (1);
+ }
+ }
+ else
+ fd = 0;
+
+ ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
+
+ /*
+ * Initialize the print device...
+ */
+
+ Setup();
+
+ /*
+ * Process pages as needed...
+ */
+
+ Page = 0;
+ Canceled = 0;
+
+ while (cupsRasterReadHeader(ras, &header))
+ {
+ /*
+ * Write a status message with the page number and number of copies.
+ */
+
+ Page ++;
+
+ fprintf(stderr, "PAGE: %d 1\n", Page);
+
+ /*
+ * Start the page...
+ */
+
+ StartPage(&header);
+
+ /*
+ * Loop for each line on the page...
+ */
+
+ for (y = 0; y < header.cupsHeight && !Canceled; y ++)
+ {
+ /*
+ * Let the user know how far we have progressed...
+ */
+
+ if ((y & 15) == 0)
+ fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page,
+ 100 * y / header.cupsHeight);
+
+ /*
+ * Read a line of graphics...
+ */
+
+ if (cupsRasterReadPixels(ras, Buffer, header.cupsBytesPerLine) < 1)
+ break;
+
+ /*
+ * Write it to the printer...
+ */
+
+ OutputLine(&header, y);
+ }
+
+ /*
+ * Eject the page...
+ */
+
+ EndPage(&header);
+
+ if (Canceled)
+ break;
+ }
+
+ /*
+ * Close the raster stream...
+ */
+
+ cupsRasterClose(ras);
+ if (fd != 0)
+ close(fd);
+
+ /*
+ * If no pages were printed, send an error message...
+ */
+
+ if (Page == 0)
+ fputs("ERROR: No pages found!\n", stderr);
+ else
+ fputs("INFO: Ready to print.\n", stderr);
+
+ return (Page == 0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c
new file mode 100644
index 000000000..1329e6908
--- /dev/null
+++ b/filter/rastertoepson.c
@@ -0,0 +1,1152 @@
+/*
+ * "$Id$"
+ *
+ * EPSON ESC/P and ESC/P2 filter for the Common UNIX Printing System
+ * (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * Setup() - Prepare the printer for printing.
+ * StartPage() - Start a page of graphics.
+ * EndPage() - Finish a page of graphics.
+ * Shutdown() - Shutdown the printer.
+ * CompressData() - Compress a line of graphics.
+ * OutputLine() - Output a line of graphics.
+ * main() - Main entry and processing of driver.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/ppd.h>
+#include <cups/string.h>
+#include "raster.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+
+/*
+ * Model numbers...
+ */
+
+#define EPSON_9PIN 0
+#define EPSON_24PIN 1
+#define EPSON_COLOR 2
+#define EPSON_PHOTO 3
+#define EPSON_ICOLOR 4
+#define EPSON_IPHOTO 5
+
+
+/*
+ * Macros...
+ */
+
+#define pwrite(s,n) fwrite((s), 1, (n), stdout)
+
+
+/*
+ * Globals...
+ */
+
+unsigned char *Planes[6], /* Output buffers */
+ *CompBuffer, /* Compression buffer */
+ *LineBuffers[2]; /* Line bitmap buffers */
+int Model, /* Model number */
+ NumPlanes, /* Number of color planes */
+ Feed, /* Number of lines to skip */
+ EjectPage; /* Eject the page when done? */
+int DotBit, /* Bit in buffers */
+ DotBytes, /* # bytes in a dot column */
+ DotColumns, /* # columns in 1/60 inch */
+ LineCount, /* # of lines processed */
+ EvenOffset, /* Offset into 'even' buffers */
+ OddOffset, /* Offset into 'odd' buffers */
+ Shingling; /* Shingle output? */
+
+
+/*
+ * Prototypes...
+ */
+
+void Setup(void);
+void StartPage(const ppd_file_t *ppd, const cups_page_header_t *header);
+void EndPage(const cups_page_header_t *header);
+void Shutdown(void);
+
+void CancelJob(int sig);
+void CompressData(const unsigned char *line, int length, int plane,
+ int type, int xstep, int ystep);
+void OutputLine(const cups_page_header_t *header);
+void OutputRows(const cups_page_header_t *header, int row);
+
+
+/*
+ * 'Setup()' - Prepare the printer for printing.
+ */
+
+void
+Setup(void)
+{
+ const char *device_uri; /* The device for the printer... */
+
+
+ /*
+ * EPSON USB printers need an additional command issued at the
+ * beginning of each job to exit from "packet" mode...
+ */
+
+ if ((device_uri = getenv("DEVICE_URI")) != NULL &&
+ strncmp(device_uri, "usb:", 4) == 0 && Model >= EPSON_ICOLOR)
+ pwrite("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29);
+}
+
+
+/*
+ * 'StartPage()' - Start a page of graphics.
+ */
+
+void
+StartPage(const ppd_file_t *ppd, /* I - PPD file */
+ const cups_page_header_t *header) /* I - Page header */
+{
+ int n, t; /* Numbers */
+ int plane; /* Looping var */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Register a signal handler to eject the current page if the
+ * job is cancelled.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, CancelJob);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = CancelJob;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, CancelJob);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Send a reset sequence.
+ */
+
+ if (ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL)
+ printf("\033{A"); /* Set EPSON emulation mode */
+
+ printf("\033@");
+
+ /*
+ * See which type of printer we are using...
+ */
+
+ EjectPage = header->Margins[0] || header->Margins[1];
+
+ switch (ppd->model_number)
+ {
+ case EPSON_9PIN :
+ case EPSON_24PIN :
+ printf("\033P\022"); /* Set 10 CPI */
+
+ if (header->HWResolution[0] == 360 || header->HWResolution[0] == 240)
+ {
+ printf("\033x1"); /* LQ printing */
+ printf("\033U1"); /* Unidirectional */
+ }
+ else
+ {
+ printf("\033x0"); /* Draft printing */
+ printf("\033U0"); /* Bidirectional */
+ }
+
+ printf("\033l%c\033Q%c", 0, /* Side margins */
+ (int)(10.0 * header->PageSize[0] / 72.0 + 0.5));
+ printf("\033C%c%c", 0, /* Page length */
+ (int)(header->PageSize[1] / 72.0 + 0.5));
+ printf("\033N%c", 0); /* Bottom margin */
+ printf("\033O"); /* No perforation skip */
+
+ /*
+ * Setup various buffer limits...
+ */
+
+ DotBytes = header->cupsRowCount / 8;
+ DotColumns = header->HWResolution[0] / 60;
+ Shingling = 0;
+
+ if (ppd->model_number == EPSON_9PIN)
+ printf("\033\063\030"); /* Set line feed */
+ else
+ switch (header->HWResolution[0])
+ {
+ case 60:
+ case 120 :
+ case 240 :
+ printf("\033\063\030"); /* Set line feed */
+ break;
+
+ case 180 :
+ case 360 :
+ Shingling = 1;
+
+ if (header->HWResolution[1] == 180)
+ printf("\033\063\010");/* Set line feed */
+ else
+ printf("\033+\010"); /* Set line feed */
+ break;
+ }
+ break;
+
+ default :
+ /*
+ * Set graphics mode...
+ */
+
+ pwrite("\033(G\001\000\001", 6); /* Graphics mode */
+
+ /*
+ * Set the media size...
+ */
+
+ if (Model < EPSON_ICOLOR)
+ {
+ pwrite("\033(U\001\000", 5); /* Resolution/units */
+ putchar(3600 / header->HWResolution[1]);
+ }
+ else
+ {
+ pwrite("\033(U\005\000", 5);
+ putchar(1440 / header->HWResolution[1]);
+ putchar(1440 / header->HWResolution[1]);
+ putchar(1440 / header->HWResolution[0]);
+ putchar(0xa0); /* n/1440ths... */
+ putchar(0x05);
+ }
+
+ n = header->PageSize[1] * header->HWResolution[1] / 72.0;
+
+ pwrite("\033(C\002\000", 5); /* Page length */
+ putchar(n);
+ putchar(n >> 8);
+
+ t = (ppd->sizes[1].length - ppd->sizes[1].top) *
+ header->HWResolution[1] / 72.0;
+
+ pwrite("\033(c\004\000", 5); /* Top & bottom margins */
+ putchar(t);
+ putchar(t >> 8);
+ putchar(n);
+ putchar(n >> 8);
+
+ if (header->HWResolution[1] == 720)
+ {
+ pwrite("\033(i\001\000\001", 6); /* Microweave */
+ pwrite("\033(e\002\000\000\001", 7); /* Small dots */
+ }
+
+ pwrite("\033(V\002\000\000\000", 7); /* Set absolute position 0 */
+
+ DotBytes = 0;
+ DotColumns = 0;
+ Shingling = 0;
+ break;
+ }
+
+ /*
+ * Set other stuff...
+ */
+
+ if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+ NumPlanes = 3;
+ else if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ NumPlanes = 4;
+ else if (header->cupsColorSpace == CUPS_CSPACE_KCMYcm)
+ NumPlanes = 6;
+ else
+ NumPlanes = 1;
+
+ Feed = 0; /* No blank lines yet */
+
+ /*
+ * Allocate memory for a line/row of graphics...
+ */
+
+ Planes[0] = malloc(header->cupsBytesPerLine);
+ for (plane = 1; plane < NumPlanes; plane ++)
+ Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
+
+ if (header->cupsCompression || DotBytes)
+ CompBuffer = calloc(2, header->cupsWidth);
+ else
+ CompBuffer = NULL;
+
+ if (DotBytes)
+ {
+ LineBuffers[0] = calloc(DotBytes, header->cupsWidth * (Shingling + 1));
+ LineBuffers[1] = LineBuffers[0] + DotBytes * header->cupsWidth;
+ DotBit = 128;
+ LineCount = 0;
+ EvenOffset = 0;
+ OddOffset = 0;
+ }
+}
+
+
+/*
+ * 'EndPage()' - Finish a page of graphics.
+ */
+
+void
+EndPage(const cups_page_header_t *header) /* I - Page header */
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ if (DotBytes && header)
+ {
+ /*
+ * Flush remaining graphics as needed...
+ */
+
+ if (!Shingling)
+ {
+ if (DotBit < 128 || EvenOffset)
+ OutputRows(header, 0);
+ }
+ else if (OddOffset > EvenOffset)
+ {
+ OutputRows(header, 1);
+ OutputRows(header, 0);
+ }
+ else
+ {
+ OutputRows(header, 0);
+ OutputRows(header, 1);
+ }
+ }
+
+ /*
+ * Eject the current page...
+ */
+
+ if (EjectPage)
+ putchar(12); /* Form feed */
+ fflush(stdout);
+
+ /*
+ * Unregister the signal handler...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Free memory...
+ */
+
+ free(Planes[0]);
+
+ if (CompBuffer)
+ free(CompBuffer);
+
+ if (DotBytes)
+ free(LineBuffers[0]);
+}
+
+
+/*
+ * 'Shutdown()' - Shutdown the printer.
+ */
+
+void
+Shutdown(void)
+{
+ /*
+ * Send a reset sequence.
+ */
+
+ printf("\033@");
+}
+
+
+/*
+ * 'CancelJob()' - Cancel the current job...
+ */
+
+void
+CancelJob(int sig) /* I - Signal */
+{
+ int i; /* Looping var */
+
+
+ (void)sig;
+
+ /*
+ * Send out lots of NUL bytes to clear out any pending raster data...
+ */
+
+ if (DotBytes)
+ i = DotBytes * 360 * 8;
+ else
+ i = 720;
+
+ for (; i > 0; i --)
+ putchar(0);
+
+ /*
+ * End the current page and exit...
+ */
+
+ EndPage(NULL);
+ Shutdown();
+
+ exit(0);
+}
+
+
+/*
+ * 'CompressData()' - Compress a line of graphics.
+ */
+
+void
+CompressData(const unsigned char *line, /* I - Data to compress */
+ int length,/* I - Number of bytes */
+ int plane, /* I - Color plane */
+ int type, /* I - Type of compression */
+ int xstep, /* I - X resolution */
+ int ystep) /* I - Y resolution */
+{
+ const unsigned char *line_ptr, /* Current byte pointer */
+ *line_end, /* End-of-line byte pointer */
+ *start; /* Start of compression sequence */
+ unsigned char *comp_ptr, /* Pointer into compression buffer */
+ temp; /* Current byte */
+ int count; /* Count of bytes for output */
+ static int ctable[6] = { 0, 2, 1, 4, 18, 17 };
+ /* KCMYcm color values */
+
+
+ /*
+ * Setup pointers...
+ */
+
+ line_ptr = line;
+ line_end = line + length;
+
+ /*
+ * Do depletion for 720 DPI printing...
+ */
+
+ if (ystep == 5)
+ {
+ for (comp_ptr = (unsigned char *)line; comp_ptr < line_end;)
+ {
+ /*
+ * Grab the current byte...
+ */
+
+ temp = *comp_ptr;
+
+ /*
+ * Check adjacent bits...
+ */
+
+ if ((temp & 0xc0) == 0xc0)
+ temp &= 0xbf;
+ if ((temp & 0x60) == 0x60)
+ temp &= 0xdf;
+ if ((temp & 0x30) == 0x30)
+ temp &= 0xef;
+ if ((temp & 0x18) == 0x18)
+ temp &= 0xf7;
+ if ((temp & 0x0c) == 0x0c)
+ temp &= 0xfb;
+ if ((temp & 0x06) == 0x06)
+ temp &= 0xfd;
+ if ((temp & 0x03) == 0x03)
+ temp &= 0xfe;
+
+ *comp_ptr++ = temp;
+
+ /*
+ * Check the last bit in the current byte and the first bit in the
+ * next byte...
+ */
+
+ if ((temp & 0x01) && comp_ptr < line_end && *comp_ptr & 0x80)
+ *comp_ptr &= 0x7f;
+ }
+ }
+
+ switch (type)
+ {
+ case 0 :
+ /*
+ * Do no compression...
+ */
+ break;
+
+ case 1 :
+ /*
+ * Do TIFF pack-bits encoding...
+ */
+
+ comp_ptr = CompBuffer;
+
+ while (line_ptr < line_end)
+ {
+ if ((line_ptr + 1) >= line_end)
+ {
+ /*
+ * Single byte on the end...
+ */
+
+ *comp_ptr++ = 0x00;
+ *comp_ptr++ = *line_ptr++;
+ }
+ else if (line_ptr[0] == line_ptr[1])
+ {
+ /*
+ * Repeated sequence...
+ */
+
+ line_ptr ++;
+ count = 2;
+
+ while (line_ptr < (line_end - 1) &&
+ line_ptr[0] == line_ptr[1] &&
+ count < 127)
+ {
+ line_ptr ++;
+ count ++;
+ }
+
+ *comp_ptr++ = 257 - count;
+ *comp_ptr++ = *line_ptr++;
+ }
+ else
+ {
+ /*
+ * Non-repeated sequence...
+ */
+
+ start = line_ptr;
+ line_ptr ++;
+ count = 1;
+
+ while (line_ptr < (line_end - 1) &&
+ line_ptr[0] != line_ptr[1] &&
+ count < 127)
+ {
+ line_ptr ++;
+ count ++;
+ }
+
+ *comp_ptr++ = count - 1;
+
+ memcpy(comp_ptr, start, count);
+ comp_ptr += count;
+ }
+ }
+
+ line_ptr = CompBuffer;
+ line_end = comp_ptr;
+ break;
+ }
+
+ putchar(0x0d); /* Move print head to left margin */
+
+ if (Model < EPSON_ICOLOR)
+ {
+ /*
+ * Do graphics the "old" way...
+ */
+
+ if (NumPlanes > 1)
+ {
+ /*
+ * Set the color...
+ */
+
+ if (plane > 3)
+ printf("\033(r%c%c%c%c", 2, 0, 1, ctable[plane] & 15);
+ /* Set extended color */
+ else if (NumPlanes == 3)
+ printf("\033r%c", ctable[plane + 1]);
+ /* Set color */
+ else
+ printf("\033r%c", ctable[plane]); /* Set color */
+ }
+
+ /*
+ * Send a raster plane...
+ */
+
+ length *= 8;
+ printf("\033."); /* Raster graphics */
+ putchar(type);
+ putchar(ystep);
+ putchar(xstep);
+ putchar(1);
+ putchar(length);
+ putchar(length >> 8);
+ }
+ else
+ {
+ /*
+ * Do graphics the "new" way...
+ */
+
+ printf("\033i");
+ putchar(ctable[plane]);
+ putchar(type);
+ putchar(1);
+ putchar(length & 255);
+ putchar(length >> 8);
+ putchar(1);
+ putchar(0);
+ }
+
+ pwrite(line_ptr, line_end - line_ptr);
+ fflush(stdout);
+}
+
+
+/*
+ * 'OutputLine()' - Output a line of graphics.
+ */
+
+void
+OutputLine(const cups_page_header_t *header) /* I - Page header */
+{
+ if (header->cupsRowCount)
+ {
+ int width;
+ unsigned char *tempptr,
+ *evenptr,
+ *oddptr;
+ register int x;
+ unsigned char bit;
+ const unsigned char *pixel;
+ unsigned char *temp;
+
+
+ /*
+ * Collect bitmap data in the line buffers and write after each buffer.
+ */
+
+ for (x = header->cupsWidth, bit = 128, pixel = Planes[0],
+ temp = CompBuffer;
+ x > 0;
+ x --, temp ++)
+ {
+ if (*pixel & bit)
+ *temp |= DotBit;
+
+ if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ bit = 128;
+ pixel ++;
+ }
+ }
+
+ if (DotBit > 1)
+ DotBit >>= 1;
+ else
+ {
+ /*
+ * Copy the holding buffer to the output buffer, shingling as necessary...
+ */
+
+ if (Shingling && LineCount != 0)
+ {
+ /*
+ * Shingle the output...
+ */
+
+ if (LineCount & 1)
+ {
+ evenptr = LineBuffers[1] + OddOffset;
+ oddptr = LineBuffers[0] + EvenOffset + DotBytes;
+ }
+ else
+ {
+ evenptr = LineBuffers[0] + EvenOffset;
+ oddptr = LineBuffers[1] + OddOffset + DotBytes;
+ }
+
+ for (width = header->cupsWidth, tempptr = CompBuffer;
+ width > 0;
+ width -= 2, tempptr += 2, oddptr += DotBytes * 2,
+ evenptr += DotBytes * 2)
+ {
+ evenptr[0] = tempptr[0];
+ oddptr[0] = tempptr[1];
+ }
+ }
+ else
+ {
+ /*
+ * Don't shingle the output...
+ */
+
+ for (width = header->cupsWidth, tempptr = CompBuffer,
+ evenptr = LineBuffers[0] + EvenOffset;
+ width > 0;
+ width --, tempptr ++, evenptr += DotBytes)
+ *evenptr = tempptr[0];
+ }
+
+ if (Shingling && LineCount != 0)
+ {
+ EvenOffset ++;
+ OddOffset ++;
+
+ if (EvenOffset == DotBytes)
+ {
+ EvenOffset = 0;
+ OutputRows(header, 0);
+ }
+
+ if (OddOffset == DotBytes)
+ {
+ OddOffset = 0;
+ OutputRows(header, 1);
+ }
+ }
+ else
+ {
+ EvenOffset ++;
+
+ if (EvenOffset == DotBytes)
+ {
+ EvenOffset = 0;
+ OutputRows(header, 0);
+ }
+ }
+
+ DotBit = 128;
+ LineCount ++;
+
+ memset(CompBuffer, 0, header->cupsWidth);
+ }
+ }
+ else
+ {
+ int plane; /* Current plane */
+ int bytes; /* Bytes per plane */
+ int xstep, ystep; /* X & Y resolutions */
+
+
+ /*
+ * Write a single line of bitmap data as needed...
+ */
+
+ xstep = 3600 / header->HWResolution[0];
+ ystep = 3600 / header->HWResolution[1];
+ bytes = header->cupsBytesPerLine / NumPlanes;
+
+ for (plane = 0; plane < NumPlanes; plane ++)
+ {
+ /*
+ * Skip blank data...
+ */
+
+ if (!Planes[plane][0] &&
+ memcmp(Planes[plane], Planes[plane] + 1, bytes - 1) == 0)
+ continue;
+
+ /*
+ * Output whitespace as needed...
+ */
+
+ if (Feed > 0)
+ {
+ pwrite("\033(v\002\000", 5); /* Relative vertical position */
+ putchar(Feed);
+ putchar(Feed >> 8);
+
+ Feed = 0;
+ }
+
+ CompressData(Planes[plane], bytes, plane, header->cupsCompression, xstep,
+ ystep);
+ }
+
+ Feed ++;
+ }
+}
+
+
+/*
+ * 'OutputRows()' - Output 8, 24, or 48 rows.
+ */
+
+void
+OutputRows(const cups_page_header_t *header, /* I - Page image header */
+ int row) /* I - Row number (0 or 1) */
+{
+ unsigned i, n; /* Looping vars */
+ int dot_count, /* Number of bytes to print */
+ dot_min; /* Minimum number of bytes */
+ unsigned char *dot_ptr, /* Pointer to print data */
+ *ptr; /* Current data */
+
+
+ dot_min = DotBytes * DotColumns;
+
+ if (LineBuffers[row][0] != 0 ||
+ memcmp(LineBuffers[row], LineBuffers[row] + 1,
+ header->cupsWidth * DotBytes - 1))
+ {
+ /*
+ * Skip leading space...
+ */
+
+ i = 0;
+ dot_count = header->cupsWidth * DotBytes;
+ dot_ptr = LineBuffers[row];
+
+ while (dot_count >= dot_min && dot_ptr[0] == 0 &&
+ memcmp(dot_ptr, dot_ptr + 1, dot_min - 1) == 0)
+ {
+ i ++;
+ dot_ptr += dot_min;
+ dot_count -= dot_min;
+ }
+
+ /*
+ * Skip trailing space...
+ */
+
+ while (dot_count >= dot_min && dot_ptr[dot_count - dot_min] == 0 &&
+ memcmp(dot_ptr + dot_count - dot_min,
+ dot_ptr + dot_count - dot_min + 1, dot_min - 1) == 0)
+ dot_count -= dot_min;
+
+ /*
+ * Position print head for printing...
+ */
+
+ if (i == 0)
+ putchar('\r');
+ else
+ {
+ putchar(0x1b);
+ putchar('$');
+ putchar(i & 255);
+ putchar(i >> 8);
+ }
+
+ /*
+ * Start bitmap graphics for this line...
+ */
+
+ printf("\033*"); /* Select bit image */
+ switch (header->HWResolution[0])
+ {
+ case 60 : /* 60x60/72 DPI gfx */
+ putchar(0);
+ break;
+ case 120 : /* 120x60/72 DPI gfx */
+ putchar(1);
+ break;
+ case 180 : /* 180 DPI gfx */
+ putchar(39);
+ break;
+ case 240 : /* 240x72 DPI gfx */
+ putchar(3);
+ break;
+ case 360 : /* 360x180/360 DPI gfx */
+ if (header->HWResolution[1] == 180)
+ {
+ if (Shingling && LineCount != 0)
+ putchar(40); /* 360x180 fast */
+ else
+ putchar(41); /* 360x180 slow */
+ }
+ else
+ {
+ if (Shingling && LineCount != 0)
+ putchar(72); /* 360x360 fast */
+ else
+ putchar(73); /* 360x360 slow */
+ }
+ break;
+ }
+
+ n = (unsigned)dot_count / DotBytes;
+ putchar(n & 255);
+ putchar(n / 256);
+
+ /*
+ * Write the graphics data...
+ */
+
+ if (header->HWResolution[0] == 120 ||
+ header->HWResolution[0] == 240)
+ {
+ /*
+ * Need to interleave the dots to avoid hosing the print head...
+ */
+
+ for (n = dot_count / 2, ptr = dot_ptr; n > 0; n --, ptr += 2)
+ {
+ putchar(*ptr);
+ putchar(0);
+ }
+
+ /*
+ * Move the head back and print the odd bytes...
+ */
+
+ if (i == 0)
+ putchar('\r');
+ else
+ {
+ putchar(0x1b);
+ putchar('$');
+ putchar(i & 255);
+ putchar(i >> 8);
+ }
+
+ if (header->HWResolution[0] == 120)
+ printf("\033*\001"); /* Select bit image */
+ else
+ printf("\033*\003"); /* Select bit image */
+
+ n = (unsigned)dot_count / DotBytes;
+ putchar(n & 255);
+ putchar(n / 256);
+
+ for (n = dot_count / 2, ptr = dot_ptr + 1; n > 0; n --, ptr += 2)
+ {
+ putchar(0);
+ putchar(*ptr);
+ }
+ }
+ else
+ pwrite(dot_ptr, dot_count);
+ }
+
+ /*
+ * Feed the paper...
+ */
+
+ putchar('\n');
+
+ if (Shingling && row == 1)
+ {
+ if (header->HWResolution[1] == 360)
+ printf("\n\n\n\n");
+ else
+ printf("\n");
+ }
+
+ fflush(stdout);
+
+ /*
+ * Clear the buffer...
+ */
+
+ memset(LineBuffers[row], 0, header->cupsWidth * DotBytes);
+}
+
+
+/*
+ * 'main()' - Main entry and processing of driver.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int fd; /* File descriptor */
+ cups_raster_t *ras; /* Raster stream for printing */
+ cups_page_header_t header; /* Page header from file */
+ ppd_file_t *ppd; /* PPD file */
+ int page; /* Current page */
+ int y; /* Current line */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ /*
+ * We don't have the correct number of arguments; write an error message
+ * and return.
+ */
+
+ fputs("ERROR: rastertoepson job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Open the page stream...
+ */
+
+ if (argc == 7)
+ {
+ if ((fd = open(argv[6], O_RDONLY)) == -1)
+ {
+ perror("ERROR: Unable to open raster file - ");
+ sleep(1);
+ return (1);
+ }
+ }
+ else
+ fd = 0;
+
+ ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
+
+ /*
+ * Initialize the print device...
+ */
+
+ ppd = ppdOpenFile(getenv("PPD"));
+ if (ppd)
+ Model = ppd->model_number;
+
+ Setup();
+
+ /*
+ * Process pages as needed...
+ */
+
+ page = 0;
+
+ while (cupsRasterReadHeader(ras, &header))
+ {
+ /*
+ * Write a status message with the page number and number of copies.
+ */
+
+ page ++;
+
+ fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies);
+
+ /*
+ * Start the page...
+ */
+
+ StartPage(ppd, &header);
+
+ /*
+ * Loop for each line on the page...
+ */
+
+ for (y = 0; y < header.cupsHeight; y ++)
+ {
+ /*
+ * Let the user know how far we have progressed...
+ */
+
+ if ((y & 127) == 0)
+ fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page,
+ 100 * y / header.cupsHeight);
+
+ /*
+ * Read a line of graphics...
+ */
+
+ if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1)
+ break;
+
+ /*
+ * Write it to the printer...
+ */
+
+ OutputLine(&header);
+ }
+
+ /*
+ * Eject the page...
+ */
+
+ EndPage(&header);
+ }
+
+ /*
+ * Shutdown the printer...
+ */
+
+ Shutdown();
+
+ ppdClose(ppd);
+
+ /*
+ * Close the raster stream...
+ */
+
+ cupsRasterClose(ras);
+ if (fd != 0)
+ close(fd);
+
+ /*
+ * If no pages were printed, send an error message...
+ */
+
+ if (page == 0)
+ fputs("ERROR: No pages found!\n", stderr);
+ else
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
+ return (page == 0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/rastertohp.c b/filter/rastertohp.c
new file mode 100644
index 000000000..6bf663aec
--- /dev/null
+++ b/filter/rastertohp.c
@@ -0,0 +1,888 @@
+/*
+ * "$Id$"
+ *
+ * Hewlett-Packard Page Control Language filter for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * Setup() - Prepare the printer for printing.
+ * StartPage() - Start a page of graphics.
+ * EndPage() - Finish a page of graphics.
+ * Shutdown() - Shutdown the printer.
+ * CancelJob() - Cancel the current job...
+ * CompressData() - Compress a line of graphics.
+ * OutputLine() - Output a line of graphics.
+ * main() - Main entry and processing of driver.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include "raster.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+
+/*
+ * Globals...
+ */
+
+unsigned char *Planes[4], /* Output buffers */
+ *CompBuffer, /* Compression buffer */
+ *BitBuffer; /* Buffer for output bits */
+int NumPlanes, /* Number of color planes */
+ ColorBits, /* Number of bits per color */
+ Feed, /* Number of lines to skip */
+ Duplex, /* Current duplex mode */
+ Page; /* Current page number */
+
+
+/*
+ * Prototypes...
+ */
+
+void Setup(void);
+void StartPage(ppd_file_t *ppd, cups_page_header_t *header);
+void EndPage(void);
+void Shutdown(void);
+
+void CancelJob(int sig);
+void CompressData(unsigned char *line, int length, int plane, int type);
+void OutputLine(cups_page_header_t *header);
+
+
+/*
+ * 'Setup()' - Prepare the printer for printing.
+ */
+
+void
+Setup(void)
+{
+ /*
+ * Send a PCL reset sequence.
+ */
+
+ putchar(0x1b);
+ putchar('E');
+}
+
+
+/*
+ * 'StartPage()' - Start a page of graphics.
+ */
+
+void
+StartPage(ppd_file_t *ppd, /* I - PPD file */
+ cups_page_header_t *header) /* I - Page header */
+{
+ int plane; /* Looping var */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Register a signal handler to eject the current page if the
+ * job is cancelled.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, CancelJob);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = CancelJob;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, CancelJob);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Show page device dictionary...
+ */
+
+ fprintf(stderr, "DEBUG: StartPage...\n");
+ fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
+ fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
+ fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType);
+ fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType);
+
+ fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
+ fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
+ fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate);
+ fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia);
+ fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
+ fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0],
+ header->HWResolution[1]);
+ fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
+ header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
+ header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
+ fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet);
+ fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog);
+ fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
+ fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0],
+ header->Margins[1]);
+ fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
+ fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
+ fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight);
+ fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
+ fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint);
+ fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
+ fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
+ fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
+ fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0],
+ header->PageSize[1]);
+ fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations);
+ fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch);
+ fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble);
+ fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
+ fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
+ fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
+ fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
+ fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
+ fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
+ fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
+ fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
+ fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
+
+ /*
+ * Setup printer/job attributes...
+ */
+
+ Duplex = header->Duplex;
+ ColorBits = header->cupsBitsPerColor;
+
+ if ((!Duplex || (Page & 1)) && header->MediaPosition)
+ printf("\033&l%dH", /* Set media position */
+ header->MediaPosition);
+
+ if (Duplex && ppd && ppd->model_number == 2)
+ {
+ /*
+ * Handle duplexing on new DeskJet printers...
+ */
+
+ printf("\033&l-2H"); /* Load media */
+
+ if (Page & 1)
+ printf("\033&l2S"); /* Set duplex mode */
+ }
+
+ if (!Duplex || (Page & 1) || (ppd && ppd->model_number == 2))
+ {
+ /*
+ * Set the media size...
+ */
+
+ printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */
+ printf("\033&l0O"); /* Set portrait orientation */
+
+ switch (header->PageSize[1])
+ {
+ case 540 : /* Monarch Envelope */
+ printf("\033&l80A"); /* Set page size */
+ break;
+
+ case 624 : /* DL Envelope */
+ printf("\033&l90A"); /* Set page size */
+ break;
+
+ case 649 : /* C5 Envelope */
+ printf("\033&l91A"); /* Set page size */
+ break;
+
+ case 684 : /* COM-10 Envelope */
+ printf("\033&l81A"); /* Set page size */
+ break;
+
+ case 709 : /* B5 Envelope */
+ printf("\033&l100A"); /* Set page size */
+ break;
+
+ case 756 : /* Executive */
+ printf("\033&l1A"); /* Set page size */
+ break;
+
+ case 792 : /* Letter */
+ printf("\033&l2A"); /* Set page size */
+ break;
+
+ case 842 : /* A4 */
+ printf("\033&l26A"); /* Set page size */
+ break;
+
+ case 1008 : /* Legal */
+ printf("\033&l3A"); /* Set page size */
+ break;
+
+ case 1191 : /* A3 */
+ printf("\033&l27A"); /* Set page size */
+ break;
+
+ case 1224 : /* Tabloid */
+ printf("\033&l6A"); /* Set page size */
+ break;
+ }
+
+ printf("\033&l%dP", /* Set page length */
+ header->PageSize[1] / 12);
+ printf("\033&l0E"); /* Set top margin to 0 */
+ }
+
+ if (!Duplex || (Page & 1))
+ {
+ /*
+ * Set other job options...
+ */
+
+ printf("\033&l%dX", header->NumCopies); /* Set number copies */
+
+ if (header->cupsMediaType &&
+ (!ppd || ppd->model_number != 2 || header->HWResolution[0] == 600))
+ printf("\033&l%dM", /* Set media type */
+ header->cupsMediaType);
+
+ if (!ppd || ppd->model_number != 2)
+ {
+ if (header->Duplex)
+ printf("\033&l%dS", /* Set duplex mode */
+ header->Duplex + header->Tumble);
+
+ printf("\033&l0L"); /* Turn off perforation skip */
+ }
+ }
+ else if (!ppd || ppd->model_number != 2)
+ printf("\033&a2G"); /* Set back side */
+
+ /*
+ * Set graphics mode...
+ */
+
+ if (ppd->model_number == 2)
+ {
+ /*
+ * Figure out the number of color planes...
+ */
+
+ if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ NumPlanes = 4;
+ else
+ NumPlanes = 1;
+
+ /*
+ * Set the resolution and top-of-form...
+ */
+
+ printf("\033&u%dD", header->HWResolution[0]);
+ /* Resolution */
+ printf("\033&l0e0L"); /* Reset top and don't skip */
+ printf("\033*p0Y\033*p0X"); /* Set top of form */
+
+ /*
+ * Send 26-byte configure image data command with horizontal and
+ * vertical resolutions as well as a color count...
+ */
+
+ printf("\033*g26W");
+ putchar(2); /* Format 2 */
+ putchar(NumPlanes); /* Output planes */
+
+ putchar(header->HWResolution[0] >> 8); /* Black resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of black levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Cyan resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of cyan levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Magenta resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of magenta levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Yellow resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of yellow levels */
+
+ printf("\033&l0H"); /* Set media position */
+ }
+ else
+ {
+ printf("\033*t%dR", header->HWResolution[0]);
+ /* Set resolution */
+
+ if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ {
+ NumPlanes = 4;
+ printf("\033*r-4U"); /* Set KCMY graphics */
+ }
+ else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+ {
+ NumPlanes = 3;
+ printf("\033*r-3U"); /* Set CMY graphics */
+ }
+ else
+ NumPlanes = 1; /* Black&white graphics */
+
+ /*
+ * Set size and position of graphics...
+ */
+
+ printf("\033*r%dS", header->cupsWidth); /* Set width */
+ printf("\033*r%dT", header->cupsHeight); /* Set height */
+
+ printf("\033&a0H"); /* Set horizontal position */
+
+ if (ppd)
+ printf("\033&a%.0fV", /* Set vertical position */
+ 10.0 * (ppd->sizes[0].length - ppd->sizes[0].top));
+ else
+ printf("\033&a0V"); /* Set top-of-page */
+ }
+
+ printf("\033*r1A"); /* Start graphics */
+
+ if (header->cupsCompression)
+ printf("\033*b%dM", /* Set compression */
+ header->cupsCompression);
+
+ Feed = 0; /* No blank lines yet */
+
+ /*
+ * Allocate memory for a line of graphics...
+ */
+
+ Planes[0] = malloc(header->cupsBytesPerLine);
+ for (plane = 1; plane < NumPlanes; plane ++)
+ Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
+
+ if (ColorBits > 1)
+ BitBuffer = malloc(ColorBits * ((header->cupsWidth + 7) / 8));
+ else
+ BitBuffer = NULL;
+
+ if (header->cupsCompression)
+ CompBuffer = malloc(header->cupsBytesPerLine * 2);
+ else
+ CompBuffer = NULL;
+}
+
+
+/*
+ * 'EndPage()' - Finish a page of graphics.
+ */
+
+void
+EndPage(void)
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Eject the current page...
+ */
+
+ if (NumPlanes > 1)
+ {
+ printf("\033*rC"); /* End color GFX */
+
+ if (!(Duplex && (Page & 1)))
+ printf("\033&l0H"); /* Eject current page */
+ }
+ else
+ {
+ printf("\033*r0B"); /* End GFX */
+
+ if (!(Duplex && (Page & 1)))
+ printf("\014"); /* Eject current page */
+ }
+
+ fflush(stdout);
+
+ /*
+ * Unregister the signal handler...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Free memory...
+ */
+
+ free(Planes[0]);
+
+ if (BitBuffer)
+ free(BitBuffer);
+
+ if (CompBuffer)
+ free(CompBuffer);
+}
+
+
+/*
+ * 'Shutdown()' - Shutdown the printer.
+ */
+
+void
+Shutdown(void)
+{
+ /*
+ * Send a PCL reset sequence.
+ */
+
+ putchar(0x1b);
+ putchar('E');
+}
+
+
+/*
+ * 'CancelJob()' - Cancel the current job...
+ */
+
+void
+CancelJob(int sig) /* I - Signal */
+{
+ int i; /* Looping var */
+
+
+ (void)sig;
+
+ /*
+ * Send out lots of NUL bytes to clear out any pending raster data...
+ */
+
+ for (i = 0; i < 600; i ++)
+ putchar(0);
+
+ /*
+ * End the current page and exit...
+ */
+
+ EndPage();
+ Shutdown();
+
+ exit(0);
+}
+
+
+/*
+ * 'CompressData()' - Compress a line of graphics.
+ */
+
+void
+CompressData(unsigned char *line, /* I - Data to compress */
+ int length, /* I - Number of bytes */
+ int plane, /* I - Color plane */
+ int type) /* I - Type of compression */
+{
+ unsigned char *line_ptr, /* Current byte pointer */
+ *line_end, /* End-of-line byte pointer */
+ *comp_ptr, /* Pointer into compression buffer */
+ *start; /* Start of compression sequence */
+ int count; /* Count of bytes for output */
+
+
+ switch (type)
+ {
+ default :
+ /*
+ * Do no compression...
+ */
+
+ line_ptr = line;
+ line_end = line + length;
+ break;
+
+ case 1 :
+ /*
+ * Do run-length encoding...
+ */
+
+ line_end = line + length;
+ for (line_ptr = line, comp_ptr = CompBuffer;
+ line_ptr < line_end;
+ comp_ptr += 2, line_ptr += count)
+ {
+ for (count = 1;
+ (line_ptr + count) < line_end &&
+ line_ptr[0] == line_ptr[count] &&
+ count < 256;
+ count ++);
+
+ comp_ptr[0] = count - 1;
+ comp_ptr[1] = line_ptr[0];
+ }
+
+ line_ptr = CompBuffer;
+ line_end = comp_ptr;
+ break;
+
+ case 2 :
+ /*
+ * Do TIFF pack-bits encoding...
+ */
+
+ line_ptr = line;
+ line_end = line + length;
+ comp_ptr = CompBuffer;
+
+ while (line_ptr < line_end)
+ {
+ if ((line_ptr + 1) >= line_end)
+ {
+ /*
+ * Single byte on the end...
+ */
+
+ *comp_ptr++ = 0x00;
+ *comp_ptr++ = *line_ptr++;
+ }
+ else if (line_ptr[0] == line_ptr[1])
+ {
+ /*
+ * Repeated sequence...
+ */
+
+ line_ptr ++;
+ count = 2;
+
+ while (line_ptr < (line_end - 1) &&
+ line_ptr[0] == line_ptr[1] &&
+ count < 127)
+ {
+ line_ptr ++;
+ count ++;
+ }
+
+ *comp_ptr++ = 257 - count;
+ *comp_ptr++ = *line_ptr++;
+ }
+ else
+ {
+ /*
+ * Non-repeated sequence...
+ */
+
+ start = line_ptr;
+ line_ptr ++;
+ count = 1;
+
+ while (line_ptr < (line_end - 1) &&
+ line_ptr[0] != line_ptr[1] &&
+ count < 127)
+ {
+ line_ptr ++;
+ count ++;
+ }
+
+ *comp_ptr++ = count - 1;
+
+ memcpy(comp_ptr, start, count);
+ comp_ptr += count;
+ }
+ }
+
+ line_ptr = CompBuffer;
+ line_end = comp_ptr;
+ break;
+ }
+
+ /*
+ * Set the length of the data and write a raster plane...
+ */
+
+ printf("\033*b%d%c", (int)(line_end - line_ptr), plane);
+ fwrite(line_ptr, line_end - line_ptr, 1, stdout);
+}
+
+
+/*
+ * 'OutputLine()' - Output a line of graphics.
+ */
+
+void
+OutputLine(cups_page_header_t *header) /* I - Page header */
+{
+ int plane, /* Current plane */
+ bytes, /* Bytes to write */
+ count; /* Bytes to convert */
+ unsigned char bit, /* Current plane data */
+ bit0, /* Current low bit data */
+ bit1, /* Current high bit data */
+ *plane_ptr, /* Pointer into Planes */
+ *bit_ptr; /* Pointer into BitBuffer */
+
+
+ /*
+ * Output whitespace as needed...
+ */
+
+ if (Feed > 0)
+ {
+ printf("\033*b%dY", Feed);
+ Feed = 0;
+ }
+
+ /*
+ * Write bitmap data as needed...
+ */
+
+ bytes = (header->cupsWidth + 7) / 8;
+
+ for (plane = 0; plane < NumPlanes; plane ++)
+ if (ColorBits == 1)
+ {
+ /*
+ * Send bits as-is...
+ */
+
+ CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+ header->cupsCompression);
+ }
+ else
+ {
+ /*
+ * Separate low and high bit data into separate buffers.
+ */
+
+ for (count = header->cupsBytesPerLine / NumPlanes,
+ plane_ptr = Planes[plane], bit_ptr = BitBuffer;
+ count > 0;
+ count -= 2, plane_ptr += 2, bit_ptr ++)
+ {
+ bit = plane_ptr[0];
+
+ bit0 = ((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4);
+ bit1 = (bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3);
+
+ if (count > 1)
+ {
+ bit = plane_ptr[1];
+
+ bit0 |= (bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3);
+ bit1 |= ((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4);
+ }
+
+ bit_ptr[0] = bit0;
+ bit_ptr[bytes] = bit1;
+ }
+
+ /*
+ * Send low and high bits...
+ */
+
+ CompressData(BitBuffer, bytes, 'V', header->cupsCompression);
+ CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+ header->cupsCompression);
+ }
+
+ fflush(stdout);
+}
+
+
+/*
+ * 'main()' - Main entry and processing of driver.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int fd; /* File descriptor */
+ cups_raster_t *ras; /* Raster stream for printing */
+ cups_page_header_t header; /* Page header from file */
+ int y; /* Current line */
+ ppd_file_t *ppd; /* PPD file */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ /*
+ * We don't have the correct number of arguments; write an error message
+ * and return.
+ */
+
+ fputs("ERROR: rastertopcl job-id user title copies options [file]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Open the page stream...
+ */
+
+ if (argc == 7)
+ {
+ if ((fd = open(argv[6], O_RDONLY)) == -1)
+ {
+ perror("ERROR: Unable to open raster file - ");
+ sleep(1);
+ return (1);
+ }
+ }
+ else
+ fd = 0;
+
+ ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
+
+ /*
+ * Initialize the print device...
+ */
+
+ ppd = ppdOpenFile(getenv("PPD"));
+
+ Setup();
+
+ /*
+ * Process pages as needed...
+ */
+
+ Page = 0;
+
+ while (cupsRasterReadHeader(ras, &header))
+ {
+ /*
+ * Write a status message with the page number and number of copies.
+ */
+
+ Page ++;
+
+ fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies);
+
+ /*
+ * Start the page...
+ */
+
+ StartPage(ppd, &header);
+
+ /*
+ * Loop for each line on the page...
+ */
+
+ for (y = 0; y < header.cupsHeight; y ++)
+ {
+ /*
+ * Let the user know how far we have progressed...
+ */
+
+ if ((y & 127) == 0)
+ fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page,
+ 100 * y / header.cupsHeight);
+
+ /*
+ * Read a line of graphics...
+ */
+
+ if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1)
+ break;
+
+ /*
+ * See if the line is blank; if not, write it to the printer...
+ */
+
+ if (Planes[0][0] ||
+ memcmp(Planes[0], Planes[0] + 1, header.cupsBytesPerLine - 1))
+ OutputLine(&header);
+ else
+ Feed ++;
+ }
+
+ /*
+ * Eject the page...
+ */
+
+ EndPage();
+ }
+
+ /*
+ * Shutdown the printer...
+ */
+
+ Shutdown();
+
+ if (ppd)
+ ppdClose(ppd);
+
+ /*
+ * Close the raster stream...
+ */
+
+ cupsRasterClose(ras);
+ if (fd != 0)
+ close(fd);
+
+ /*
+ * If no pages were printed, send an error message...
+ */
+
+ if (Page == 0)
+ fputs("ERROR: No pages found!\n", stderr);
+ else
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
+ return (Page == 0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/testimage.c b/filter/testimage.c
new file mode 100644
index 000000000..cf282ca8c
--- /dev/null
+++ b/filter/testimage.c
@@ -0,0 +1,101 @@
+/*
+ * "$Id$"
+ *
+ * Image library test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "image.h"
+
+
+/*
+ * 'main()' - Main entry...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ image_t *img; /* Image to print */
+ int primary; /* Primary image colorspace */
+ FILE *out; /* Output PPM/PGM file */
+ ib_t *line; /* Line from file */
+ int y; /* Current line */
+
+
+ if (argc != 3)
+ {
+ puts("Usage: testimage filename.ext filename.[ppm|pgm]");
+ return (1);
+ }
+
+ if (strstr(argv[2], ".ppm") != NULL)
+ primary = IMAGE_RGB;
+ else
+ primary = IMAGE_WHITE;
+
+ img = ImageOpen(argv[1], primary, IMAGE_WHITE, 100, 0, NULL);
+
+ if (!img)
+ {
+ perror(argv[1]);
+ return (1);
+ }
+
+ out = fopen(argv[2], "wb");
+
+ if (!out)
+ {
+ perror(argv[2]);
+ ImageClose(img);
+ return (1);
+ }
+
+ line = calloc(img->xsize, img->colorspace);
+
+ fprintf(out, "P%d\n%d\n%d\n255\n", img->colorspace == IMAGE_WHITE ? 5 : 6,
+ img->xsize, img->ysize);
+
+ for (y = 0; y < img->ysize; y ++)
+ {
+ ImageGetRow(img, 0, y, img->xsize, line);
+ fwrite(line, img->xsize, img->colorspace, out);
+ }
+
+ ImageClose(img);
+ fclose(out);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/textcommon.c b/filter/textcommon.c
new file mode 100644
index 000000000..5caea4597
--- /dev/null
+++ b/filter/textcommon.c
@@ -0,0 +1,1187 @@
+/*
+ * "$Id$"
+ *
+ * Common text filter routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * TextMain() - Standard main entry for text filters.
+ * compare_keywords() - Compare two C/C++ keywords.
+ * getutf8() - Get a UTF-8 encoded wide character...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "textcommon.h"
+
+
+/*
+ * Globals...
+ */
+
+int WrapLines = 1, /* Wrap text in lines */
+ SizeLines = 60, /* Number of lines on a page */
+ SizeColumns = 80, /* Number of columns on a line */
+ PageColumns = 1, /* Number of columns on a page */
+ ColumnGutter = 0, /* Number of characters between text columns */
+ ColumnWidth = 80, /* Width of each column */
+ PrettyPrint = 0, /* Do pretty code formatting */
+ Copies = 1; /* Number of copies */
+lchar_t **Page = NULL; /* Page characters */
+int NumPages = 0; /* Number of pages in document */
+float CharsPerInch = 10; /* Number of character columns per inch */
+float LinesPerInch = 6; /* Number of lines per inch */
+int UTF8 = 0; /* Use UTF-8 encoding? */
+int NumKeywords = 0; /* Number of known keywords */
+char **Keywords = NULL; /* List of known keywords */
+
+
+/*
+ * Local globals...
+ */
+
+static char *code_keywords[] = /* List of known C/C++ keywords... */
+ {
+ "and",
+ "and_eq",
+ "asm",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "class",
+ "compl",
+ "const",
+ "const_cast",
+ "continue",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "else",
+ "enum",
+ "explicit",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "goto",
+ "if",
+ "inline",
+ "int",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "not",
+ "not_eq",
+ "operator",
+ "or",
+ "or_eq",
+ "private",
+ "protected",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "short",
+ "signed",
+ "sizeof",
+ "static",
+ "static_cast",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typename",
+ "union",
+ "unsigned",
+ "virtual",
+ "void",
+ "volatile",
+ "while",
+ "xor",
+ "xor_eq"
+ },
+ *sh_keywords[] = /* List of known Boure/Korn/zsh/bash keywords... */
+ {
+ "alias",
+ "bg",
+ "break",
+ "case",
+ "cd",
+ "command",
+ "continue",
+ "do",
+ "done",
+ "echo",
+ "elif",
+ "else",
+ "esac",
+ "eval",
+ "exec",
+ "exit",
+ "export",
+ "fc",
+ "fg",
+ "fi",
+ "for",
+ "function",
+ "getopts",
+ "if",
+ "in",
+ "jobs",
+ "kill",
+ "let",
+ "limit",
+ "newgrp",
+ "print",
+ "pwd",
+ "read",
+ "readonly",
+ "return",
+ "select",
+ "set",
+ "shift",
+ "test",
+ "then",
+ "time",
+ "times",
+ "trap",
+ "typeset",
+ "ulimit",
+ "umask",
+ "unalias",
+ "unlimit",
+ "unset",
+ "until",
+ "wait",
+ "whence"
+ "while",
+ },
+ *csh_keywords[] = /* List of known csh/tcsh keywords... */
+ {
+ "alias",
+ "aliases",
+ "bg",
+ "bindkey",
+ "break",
+ "breaksw",
+ "builtins",
+ "case",
+ "cd",
+ "chdir",
+ "complete",
+ "continue",
+ "default",
+ "dirs",
+ "echo",
+ "echotc",
+ "else",
+ "end",
+ "endif",
+ "eval",
+ "exec",
+ "exit",
+ "fg",
+ "foreach",
+ "glob",
+ "goto",
+ "history",
+ "if",
+ "jobs",
+ "kill",
+ "limit",
+ "login",
+ "logout",
+ "ls",
+ "nice",
+ "nohup",
+ "notify",
+ "onintr",
+ "popd",
+ "pushd",
+ "pwd",
+ "rehash",
+ "repeat",
+ "set",
+ "setenv",
+ "settc",
+ "shift",
+ "source",
+ "stop",
+ "suspend",
+ "switch",
+ "telltc",
+ "then",
+ "time",
+ "umask",
+ "unalias",
+ "unbindkey",
+ "unhash",
+ "unlimit",
+ "unset",
+ "unsetenv",
+ "wait",
+ "where",
+ "which",
+ "while"
+ },
+ *perl_keywords[] = /* List of known perl keywords... */
+ {
+ "abs",
+ "accept",
+ "alarm",
+ "and",
+ "atan2",
+ "bind",
+ "binmode",
+ "bless",
+ "caller",
+ "chdir",
+ "chmod",
+ "chomp",
+ "chop",
+ "chown",
+ "chr",
+ "chroot",
+ "closdir",
+ "close",
+ "connect",
+ "continue",
+ "cos",
+ "crypt",
+ "dbmclose",
+ "dbmopen",
+ "defined",
+ "delete",
+ "die",
+ "do",
+ "dump",
+ "each",
+ "else",
+ "elsif",
+ "endgrent",
+ "endhostent",
+ "endnetent",
+ "endprotoent",
+ "endpwent",
+ "endservent",
+ "eof",
+ "eval",
+ "exec",
+ "exists",
+ "exit",
+ "exp",
+ "fcntl",
+ "fileno",
+ "flock",
+ "for",
+ "foreach",
+ "fork",
+ "format",
+ "formline",
+ "getc",
+ "getgrent",
+ "getgrgid",
+ "getgrnam",
+ "gethostbyaddr",
+ "gethostbyname",
+ "gethostent",
+ "getlogin",
+ "getnetbyaddr",
+ "getnetbyname",
+ "getnetent",
+ "getpeername",
+ "getpgrp",
+ "getppid",
+ "getpriority",
+ "getprotobyname",
+ "getprotobynumber",
+ "getprotoent",
+ "getpwent",
+ "getpwnam",
+ "getpwuid",
+ "getservbyname",
+ "getservbyport",
+ "getservent",
+ "getsockname",
+ "getsockopt",
+ "glob",
+ "gmtime",
+ "goto",
+ "grep",
+ "hex",
+ "if",
+ "import",
+ "index",
+ "int",
+ "ioctl",
+ "join",
+ "keys",
+ "kill",
+ "last",
+ "lc",
+ "lcfirst",
+ "length",
+ "link",
+ "listen",
+ "local",
+ "localtime",
+ "log",
+ "lstat",
+ "map",
+ "mkdir",
+ "msgctl",
+ "msgget",
+ "msgrcv",
+ "msgsend",
+ "my",
+ "next",
+ "no",
+ "not",
+ "oct",
+ "open",
+ "opendir",
+ "or",
+ "ord",
+ "pack",
+ "package",
+ "pipe",
+ "pop",
+ "pos",
+ "print",
+ "printf",
+ "push",
+ "quotemeta",
+ "rand",
+ "read",
+ "readdir",
+ "readlink",
+ "recv",
+ "redo",
+ "ref",
+ "rename",
+ "require",
+ "reset",
+ "return",
+ "reverse",
+ "rewinddir",
+ "rindex",
+ "rmdir",
+ "scalar",
+ "seek",
+ "seekdir",
+ "select",
+ "semctl",
+ "semget",
+ "semop",
+ "send",
+ "setgrent",
+ "sethostent",
+ "setnetent",
+ "setpgrp",
+ "setpriority",
+ "setprotoent",
+ "setpwent",
+ "setservent",
+ "setsockopt",
+ "shift",
+ "shmctl",
+ "shmget",
+ "shmread",
+ "shmwrite",
+ "shutdown",
+ "sin",
+ "sleep",
+ "socket",
+ "socketpair",
+ "sort",
+ "splice",
+ "split",
+ "sprintf",
+ "sqrt",
+ "srand",
+ "stat",
+ "study",
+ "sub",
+ "substr",
+ "symlink",
+ "syscall",
+ "sysread",
+ "sysseek",
+ "system",
+ "syswrite",
+ "tell",
+ "telldir",
+ "tie",
+ "tied",
+ "time",
+ "times"
+ "times",
+ "truncate",
+ "uc",
+ "ucfirst",
+ "umask",
+ "undef",
+ "unless",
+ "unlink",
+ "unpack",
+ "unshift",
+ "untie",
+ "until",
+ "use",
+ "utime",
+ "values",
+ "vec",
+ "wait",
+ "waitpid",
+ "wantarray",
+ "warn",
+ "while",
+ "write"
+ };
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_keywords(const void *, const void *);
+static int getutf8(FILE *fp);
+
+
+/*
+ * 'TextMain()' - Standard main entry for text filters.
+ */
+
+int /* O - Exit status */
+TextMain(const char *name, /* I - Name of filter */
+ int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ FILE *fp; /* Print file */
+ ppd_file_t *ppd; /* PPD file */
+ int i, /* Looping var */
+ ch, /* Current char from file */
+ lastch, /* Previous char from file */
+ attr, /* Current attribute */
+ line, /* Current line */
+ column, /* Current column */
+ page_column; /* Current page column */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ const char *val; /* Option value */
+ char keyword[64], /* Keyword string */
+ *keyptr; /* Pointer into string */
+ int keycol; /* Column where keyword starts */
+ int ccomment; /* Inside a C-style comment? */
+ int cstring; /* Inside a C string */
+
+
+ /*
+ * Make sure status messages are not buffered...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc < 6 || argc > 7)
+ {
+ fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n",
+ name);
+ return (1);
+ }
+
+ /*
+ * If we have 7 arguments, print the file named on the command-line.
+ * Otherwise, send stdin instead...
+ */
+
+ if (argc == 6)
+ fp = stdin;
+ else
+ {
+ /*
+ * Try to open the print file...
+ */
+
+ if ((fp = fopen(argv[6], "rb")) == NULL)
+ {
+ perror("ERROR: unable to open print file - ");
+ return (1);
+ }
+ }
+
+ /*
+ * Process command-line options and write the prolog...
+ */
+
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL &&
+ strcasecmp(val, "no") && strcasecmp(val, "off") &&
+ strcasecmp(val, "false"))
+ {
+ PageLeft = 72.0f;
+ PageRight = PageWidth - 36.0f;
+ PageBottom = PageBottom > 36.0f ? PageBottom : 36.0f;
+ PageTop = PageLength - 36.0f;
+ CharsPerInch = 12;
+ LinesPerInch = 8;
+
+ if ((val = getenv("CONTENT_TYPE")) == NULL)
+ {
+ PrettyPrint = PRETTY_CODE;
+ NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
+ Keywords = code_keywords;
+ }
+ else if (strcasecmp(val, "application/x-cshell") == 0)
+ {
+ PrettyPrint = PRETTY_SHELL;
+ NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]);
+ Keywords = csh_keywords;
+ }
+ else if (strcasecmp(val, "application/x-perl") == 0)
+ {
+ PrettyPrint = PRETTY_PERL;
+ NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]);
+ Keywords = perl_keywords;
+ }
+ else if (strcasecmp(val, "application/x-shell") == 0)
+ {
+ PrettyPrint = PRETTY_SHELL;
+ NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]);
+ Keywords = sh_keywords;
+ }
+ else
+ {
+ PrettyPrint = PRETTY_CODE;
+ NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
+ Keywords = code_keywords;
+ }
+ }
+
+ ppd = SetCommonOptions(num_options, options, 1);
+
+ if ((val = cupsGetOption("wrap", num_options, options)) == NULL)
+ WrapLines = 1;
+ else
+ WrapLines = !strcasecmp(val, "true") || !strcasecmp(val, "on") ||
+ !strcasecmp(val, "yes");
+
+ if ((val = cupsGetOption("columns", num_options, options)) != NULL)
+ PageColumns = atoi(val);
+
+ if ((val = cupsGetOption("cpi", num_options, options)) != NULL)
+ CharsPerInch = atof(val);
+
+ if ((val = cupsGetOption("lpi", num_options, options)) != NULL)
+ LinesPerInch = atof(val);
+
+ if (PrettyPrint)
+ PageTop -= 216.0f / LinesPerInch;
+
+ Copies = atoi(argv[4]);
+
+ WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
+ cupsGetOption("page-label", num_options, options), ppd);
+
+ /*
+ * Read text from the specified source and print it...
+ */
+
+ lastch = 0;
+ column = 0;
+ line = 0;
+ page_column = 0;
+ attr = 0;
+ keyptr = keyword;
+ keycol = 0;
+ ccomment = 0;
+ cstring = 0;
+
+ while ((ch = getutf8(fp)) >= 0)
+ {
+ /*
+ * Control codes:
+ *
+ * BS Backspace (0x08)
+ * HT Horizontal tab; next 8th column (0x09)
+ * LF Line feed; forward full line (0x0a)
+ * VT Vertical tab; reverse full line (0x0b)
+ * FF Form feed (0x0c)
+ * CR Carriage return (0x0d)
+ * ESC 7 Reverse full line (0x1b 0x37)
+ * ESC 8 Reverse half line (0x1b 0x38)
+ * ESC 9 Forward half line (0x1b 0x39)
+ */
+
+ switch (ch)
+ {
+ case 0x08 : /* BS - backspace for boldface & underline */
+ if (column > 0)
+ column --;
+
+ keyptr = keyword;
+ keycol = column;
+ break;
+
+ case 0x09 : /* HT - tab to next 8th column */
+ if (PrettyPrint && keyptr > keyword)
+ {
+ *keyptr = '\0';
+ keyptr = keyword;
+
+ if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
+ compare_keywords))
+ {
+ /*
+ * Put keywords in boldface...
+ */
+
+ i = page_column * (ColumnWidth + ColumnGutter);
+
+ while (keycol < column)
+ {
+ Page[line][keycol + i].attr |= ATTR_BOLD;
+ keycol ++;
+ }
+ }
+ }
+
+ column = (column + 8) & ~7;
+
+ if (column >= ColumnWidth && WrapLines)
+ { /* Wrap text to margins */
+ line ++;
+ column = 0;
+
+ if (line >= SizeLines)
+ {
+ page_column ++;
+ line = 0;
+
+ if (page_column >= PageColumns)
+ {
+ WritePage();
+ page_column = 0;
+ }
+ }
+ }
+
+ keycol = column;
+ break;
+
+ case 0x0d : /* CR */
+#ifndef __APPLE__
+ /*
+ * All but MacOS/Darwin treat CR as was intended by ANSI
+ * folks, namely to move to column 0/1. Some programs still
+ * use this to do boldfacing and underlining...
+ */
+
+ column = 0;
+ break;
+#else
+ /*
+ * MacOS/Darwin still need to treat CR as a line ending.
+ */
+
+ {
+ int nextch;
+ if ((nextch = getc(fp)) != 0x0a)
+ ungetc(nextch, fp);
+ else
+ ch = nextch;
+ }
+#endif /* !__APPLE__ */
+
+ case 0x0a : /* LF - output current line */
+ if (PrettyPrint && keyptr > keyword)
+ {
+ *keyptr = '\0';
+ keyptr = keyword;
+
+ if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
+ compare_keywords))
+ {
+ /*
+ * Put keywords in boldface...
+ */
+
+ i = page_column * (ColumnWidth + ColumnGutter);
+
+ while (keycol < column)
+ {
+ Page[line][keycol + i].attr |= ATTR_BOLD;
+ keycol ++;
+ }
+ }
+ }
+
+ line ++;
+ column = 0;
+ keycol = 0;
+
+ if (!ccomment && !cstring)
+ attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
+
+ if (line >= SizeLines)
+ {
+ page_column ++;
+ line = 0;
+
+ if (page_column >= PageColumns)
+ {
+ WritePage();
+ page_column = 0;
+ }
+ }
+ break;
+
+ case 0x0b : /* VT - move up 1 line */
+ if (line > 0)
+ line --;
+
+ keyptr = keyword;
+ keycol = column;
+
+ if (!ccomment && !cstring)
+ attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
+ break;
+
+ case 0x0c : /* FF - eject current page... */
+ if (PrettyPrint && keyptr > keyword)
+ {
+ *keyptr = '\0';
+ keyptr = keyword;
+
+ if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
+ compare_keywords))
+ {
+ /*
+ * Put keywords in boldface...
+ */
+
+ i = page_column * (ColumnWidth + ColumnGutter);
+
+ while (keycol < column)
+ {
+ Page[line][keycol + i].attr |= ATTR_BOLD;
+ keycol ++;
+ }
+ }
+ }
+
+ page_column ++;
+ column = 0;
+ keycol = 0;
+ line = 0;
+
+ if (!ccomment && !cstring)
+ attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
+
+ if (page_column >= PageColumns)
+ {
+ WritePage();
+ page_column = 0;
+ }
+ break;
+
+ case 0x1b : /* Escape sequence */
+ ch = getutf8(fp);
+ if (ch == '7')
+ {
+ /*
+ * ESC 7 Reverse full line (0x1b 0x37)
+ */
+
+ if (line > 0)
+ line --;
+ }
+ else if (ch == '8')
+ {
+ /*
+ * ESC 8 Reverse half line (0x1b 0x38)
+ */
+
+ if ((attr & ATTR_RAISED) && line > 0)
+ {
+ attr &= ~ATTR_RAISED;
+ line --;
+ }
+ else if (attr & ATTR_LOWERED)
+ attr &= ~ATTR_LOWERED;
+ else
+ attr |= ATTR_RAISED;
+ }
+ else if (ch == '9')
+ {
+ /*
+ * ESC 9 Forward half line (0x1b 0x39)
+ */
+
+ if ((attr & ATTR_LOWERED) && line < (SizeLines - 1))
+ {
+ attr &= ~ATTR_LOWERED;
+ line ++;
+ }
+ else if (attr & ATTR_RAISED)
+ attr &= ~ATTR_RAISED;
+ else
+ attr |= ATTR_LOWERED;
+ }
+ break;
+
+ default : /* All others... */
+ if (ch < ' ')
+ break; /* Ignore other control chars */
+
+ if (PrettyPrint)
+ {
+ /*
+ * Do highlighting of C/C++ keywords, preprocessor commands,
+ * and comments...
+ */
+
+ if ((ch == ' ' || ch == '\t') && (attr & ATTR_BOLD))
+ {
+ /*
+ * Stop bolding preprocessor command...
+ */
+
+ attr &= ~ATTR_BOLD;
+ }
+ else if (!(isalnum(ch & 255) || ch == '_') && keyptr > keyword)
+ {
+ /*
+ * Look for a keyword...
+ */
+
+ *keyptr = '\0';
+ keyptr = keyword;
+
+ if (!(attr & ATTR_ITALIC) &&
+ bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
+ compare_keywords))
+ {
+ /*
+ * Put keywords in boldface...
+ */
+
+ i = page_column * (ColumnWidth + ColumnGutter);
+
+ while (keycol < column)
+ {
+ Page[line][keycol + i].attr |= ATTR_BOLD;
+ keycol ++;
+ }
+ }
+ }
+ else if ((isalnum(ch & 255) || ch == '_') && !ccomment && !cstring)
+ {
+ /*
+ * Add characters to the current keyword (if they'll fit).
+ */
+
+ if (keyptr == keyword)
+ keycol = column;
+
+ if (keyptr < (keyword + sizeof(keyword) - 1))
+ *keyptr++ = ch;
+ }
+ else if (ch == '\"' && lastch != '\\' && !ccomment && !cstring)
+ {
+ /*
+ * Start a C string constant...
+ */
+
+ cstring = -1;
+ attr |= ATTR_BLUE;
+ }
+ else if (ch == '*' && lastch == '/' && !cstring &&
+ PrettyPrint != PRETTY_SHELL)
+ {
+ /*
+ * Start a C-style comment...
+ */
+
+ ccomment = 1;
+ attr |= ATTR_ITALIC | ATTR_GREEN;
+ }
+ else if (ch == '/' && lastch == '/' && !cstring &&
+ PrettyPrint == PRETTY_CODE)
+ {
+ /*
+ * Start a C++-style comment...
+ */
+
+ attr |= ATTR_ITALIC | ATTR_GREEN;
+ }
+ else if (ch == '#' && !cstring && PrettyPrint != PRETTY_CODE)
+ {
+ /*
+ * Start a shell-style comment...
+ */
+
+ attr |= ATTR_ITALIC | ATTR_GREEN;
+ }
+ else if (ch == '#' && column == 0 && !ccomment && !cstring &&
+ PrettyPrint == PRETTY_CODE)
+ {
+ /*
+ * Start a preprocessor command...
+ */
+
+ attr |= ATTR_BOLD | ATTR_RED;
+ }
+ }
+
+ if (column >= ColumnWidth && WrapLines)
+ { /* Wrap text to margins */
+ column = 0;
+ line ++;
+
+ if (line >= SizeLines)
+ {
+ page_column ++;
+ line = 0;
+
+ if (page_column >= PageColumns)
+ {
+ WritePage();
+ page_column = 0;
+ }
+ }
+ }
+
+ /*
+ * Add text to the current column & line...
+ */
+
+ if (column < ColumnWidth)
+ {
+ i = column + page_column * (ColumnWidth + ColumnGutter);
+
+ if (PrettyPrint)
+ Page[line][i].attr = attr;
+ else if (ch == ' ' && Page[line][i].ch)
+ ch = Page[line][i].ch;
+ else if (ch == Page[line][i].ch)
+ Page[line][i].attr |= ATTR_BOLD;
+ else if (Page[line][i].ch == '_')
+ Page[line][i].attr |= ATTR_UNDERLINE;
+ else if (ch == '_')
+ {
+ Page[line][i].attr |= ATTR_UNDERLINE;
+
+ if (Page[line][i].ch)
+ ch = Page[line][i].ch;
+ }
+ else
+ Page[line][i].attr = attr;
+
+ Page[line][i].ch = ch;
+ }
+
+ if (PrettyPrint)
+ {
+ if ((ch == '{' || ch == '}') && !ccomment && !cstring &&
+ column < ColumnWidth)
+ {
+ /*
+ * Highlight curley braces...
+ */
+
+ Page[line][column].attr |= ATTR_BOLD;
+ }
+ else if ((ch == '/' || ch == '*') && lastch == '/' &&
+ column < ColumnWidth && PrettyPrint != PRETTY_SHELL)
+ {
+ /*
+ * Highlight first comment character...
+ */
+
+ Page[line][column - 1].attr = attr;
+ }
+ else if (ch == '\"' && lastch != '\\' && !ccomment && cstring > 0)
+ {
+ /*
+ * End a C string constant...
+ */
+
+ cstring = 0;
+ attr &= ~ATTR_BLUE;
+ }
+ else if (ch == '/' && lastch == '*' && ccomment)
+ {
+ /*
+ * End a C-style comment...
+ */
+
+ ccomment = 0;
+ attr &= ~(ATTR_ITALIC | ATTR_GREEN);
+ }
+
+ if (cstring < 0)
+ cstring = 1;
+ }
+
+ column ++;
+ break;
+ }
+
+ /*
+ * Save this character for the next cycle.
+ */
+
+ lastch = ch;
+ }
+
+ /*
+ * Write any remaining page data...
+ */
+
+ if (line > 0 || page_column > 0 || column > 0)
+ WritePage();
+
+ /*
+ * Write the epilog and return...
+ */
+
+ WriteEpilogue();
+
+ if (ppd != NULL)
+ ppdClose(ppd);
+
+ return (0);
+}
+
+
+/*
+ * 'compare_keywords()' - Compare two C/C++ keywords.
+ */
+
+static int /* O - Result of strcmp */
+compare_keywords(const void *k1, /* I - First keyword */
+ const void *k2) /* I - Second keyword */
+{
+ return (strcmp(*((const char **)k1), *((const char **)k2)));
+}
+
+
+/*
+ * 'getutf8()' - Get a UTF-8 encoded wide character...
+ */
+
+static int /* O - Character or -1 on error */
+getutf8(FILE *fp) /* I - File to read from */
+{
+ int ch; /* Current character value */
+ int next; /* Next character from file */
+
+
+ /*
+ * Read the first character and process things accordingly...
+ *
+ * UTF-8 maps 16-bit characters to:
+ *
+ * 0 to 127 = 0xxxxxxx
+ * 128 to 2047 = 110xxxxx 10yyyyyy (xxxxxyyyyyy)
+ * 2048 to 65535 = 1110xxxx 10yyyyyy 10zzzzzz (xxxxyyyyyyzzzzzz)
+ *
+ * We also accept:
+ *
+ * 128 to 191 = 10xxxxxx
+ *
+ * since this range of values is otherwise undefined unless you are
+ * in the middle of a multi-byte character...
+ *
+ * This code currently does not support anything beyond 16-bit
+ * characters, in part because PostScript doesn't support more than
+ * 16-bit characters...
+ */
+
+ if ((ch = getc(fp)) == EOF)
+ return (EOF);
+
+ if (ch < 0xc0 || !UTF8) /* One byte character? */
+ return (ch);
+ else if ((ch & 0xe0) == 0xc0)
+ {
+ /*
+ * Two byte character...
+ */
+
+ if ((next = getc(fp)) == EOF)
+ return (EOF);
+ else
+ return (((ch & 0x1f) << 6) | (next & 0x3f));
+ }
+ else if ((ch & 0xf0) == 0xe0)
+ {
+ /*
+ * Three byte character...
+ */
+
+ if ((next = getc(fp)) == EOF)
+ return (EOF);
+
+ ch = ((ch & 0x0f) << 6) | (next & 0x3f);
+
+ if ((next = getc(fp)) == EOF)
+ return (EOF);
+ else
+ return ((ch << 6) | (next & 0x3f));
+ }
+ else
+ {
+ /*
+ * More than three bytes... We don't support that...
+ */
+
+ return (EOF);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/textcommon.h b/filter/textcommon.h
new file mode 100644
index 000000000..6924f7c09
--- /dev/null
+++ b/filter/textcommon.h
@@ -0,0 +1,122 @@
+/*
+ * "$Id$"
+ *
+ * Common text filter definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+
+
+/*
+ * C++ magic...
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*
+ * Constants...
+ */
+
+#define ATTR_NORMAL 0x00
+#define ATTR_BOLD 0x01
+#define ATTR_ITALIC 0x02
+#define ATTR_BOLDITALIC 0x03
+#define ATTR_FONT 0x03
+
+#define ATTR_UNDERLINE 0x04
+#define ATTR_RAISED 0x08
+#define ATTR_LOWERED 0x10
+#define ATTR_RED 0x20
+#define ATTR_GREEN 0x40
+#define ATTR_BLUE 0x80
+
+#define PRETTY_OFF 0
+#define PRETTY_CODE 1
+#define PRETTY_SHELL 2
+#define PRETTY_PERL 3
+#define PRETTY_HTML 4
+
+
+/*
+ * Structures...
+ */
+
+typedef struct /**** Character/attribute structure... ****/
+{
+ unsigned short ch, /* Character */
+ attr; /* Any attributes */
+} lchar_t;
+
+
+/*
+ * Globals...
+ */
+
+extern int WrapLines, /* Wrap text in lines */
+ SizeLines, /* Number of lines on a page */
+ SizeColumns, /* Number of columns on a line */
+ PageColumns, /* Number of columns on a page */
+ ColumnGutter, /* Number of characters between text columns */
+ ColumnWidth, /* Width of each column */
+ PrettyPrint, /* Do pretty code formatting? */
+ Copies; /* Number of copies to produce */
+extern lchar_t **Page; /* Page characters */
+extern int NumPages; /* Number of pages in document */
+extern float CharsPerInch, /* Number of character columns per inch */
+ LinesPerInch; /* Number of lines per inch */
+extern int UTF8, /* Use UTF-8 encoding? */
+ NumKeywords; /* Number of known keywords */
+extern char **Keywords; /* List of known keywords... */
+
+
+/*
+ * Required functions...
+ */
+
+extern int TextMain(const char *name, int argc, char *argv[]);
+extern void WriteEpilogue(void);
+extern void WritePage(void);
+extern void WriteProlog(const char *title, const char *user,
+ const char *classification, const char *label,
+ ppd_file_t *ppd);
+
+
+/*
+ * C++ magic...
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/texttops.c b/filter/texttops.c
new file mode 100644
index 000000000..432c37dee
--- /dev/null
+++ b/filter/texttops.c
@@ -0,0 +1,1311 @@
+/*
+ * "$Id$"
+ *
+ * Text to PostScript filter for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry for text to PostScript filter.
+ * WriteEpilogue() - Write the PostScript file epilogue.
+ * WritePage() - Write a page of text.
+ * WriteProlog() - Write the PostScript file prolog with options.
+ * write_line() - Write a row of text.
+ * write_string() - Write a string of text.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "textcommon.h"
+
+
+/*
+ * Globals...
+ */
+
+char *Glyphs[65536]; /* PostScript glyphs for Unicode */
+int NumFonts; /* Number of fonts to use */
+char *Fonts[256][4]; /* Fonts to use */
+unsigned short Chars[65536]; /* 0xffcc (ff = font, cc = char) */
+unsigned short Codes[65536]; /* Unicode glyph mapping to fonts */
+int Widths[256]; /* Widths of each font */
+int Directions[256];/* Text directions for each font */
+
+
+/*
+ * Local functions...
+ */
+
+static void write_line(int row, lchar_t *line);
+static void write_string(int col, int row, int len, lchar_t *s);
+static void write_text(const char *s);
+
+
+/*
+ * 'main()' - Main entry for text to PostScript filter.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ return (TextMain("texttops", argc, argv));
+}
+
+
+/*
+ * 'WriteEpilogue()' - Write the PostScript file epilogue.
+ */
+
+void
+WriteEpilogue(void)
+{
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", NumPages);
+ puts("%%EOF");
+
+ free(Page[0]);
+ free(Page);
+}
+
+
+/*
+ * 'WritePage()' - Write a page of text.
+ */
+
+void
+WritePage(void)
+{
+ int line; /* Current line */
+
+
+ NumPages ++;
+ printf("%%%%Page: %d %d\n", NumPages, NumPages);
+
+ puts("gsave");
+
+ if (PrettyPrint)
+ printf("%d H\n", NumPages);
+
+ for (line = 0; line < SizeLines; line ++)
+ write_line(line, Page[line]);
+
+ puts("grestore");
+ puts("showpage");
+
+ memset(Page[0], 0, sizeof(lchar_t) * SizeColumns * SizeLines);
+}
+
+
+/*
+ * 'WriteProlog()' - Write the PostScript file prolog with options.
+ */
+
+void
+WriteProlog(const char *title, /* I - Title of job */
+ const char *user, /* I - Username */
+ const char *classification, /* I - Classification */
+ const char *label, /* I - Page label */
+ ppd_file_t *ppd) /* I - PPD file info */
+{
+ int i, j, k; /* Looping vars */
+ char *charset; /* Character set string */
+ char filename[1024]; /* Glyph filenames */
+ FILE *fp; /* Glyph files */
+ const char *datadir; /* CUPS_DATADIR environment variable */
+ char line[1024], /* Line from file */
+ *lineptr, /* Pointer into line */
+ *valptr; /* Pointer to value in line */
+ int ch, unicode; /* Character values */
+ int start, end; /* Start and end values for range */
+ char glyph[64]; /* Glyph name */
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+ char curdate[255]; /* Current date (text format) */
+ int num_fonts; /* Number of unique fonts */
+ char *fonts[1024]; /* Unique fonts */
+ static char *names[] = /* Font names */
+ {
+ "cupsNormal",
+ "cupsBold",
+ "cupsItalic"
+ };
+
+
+ /*
+ * Get the data directory...
+ */
+
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+ datadir = CUPS_DATADIR;
+
+ /*
+ * Adjust margins as necessary...
+ */
+
+ if (classification || label)
+ {
+ /*
+ * Leave room for labels...
+ */
+
+ PageBottom += 36;
+ PageTop -= 36;
+ }
+
+ /*
+ * Allocate memory for the page...
+ */
+
+ SizeColumns = (PageRight - PageLeft) / 72.0 * CharsPerInch;
+ SizeLines = (PageTop - PageBottom) / 72.0 * LinesPerInch;
+
+ Page = calloc(sizeof(lchar_t *), SizeLines);
+ Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines);
+ for (i = 1; i < SizeLines; i ++)
+ Page[i] = Page[0] + i * SizeColumns;
+
+ if (PageColumns > 1)
+ {
+ ColumnGutter = CharsPerInch / 2;
+ ColumnWidth = (SizeColumns - ColumnGutter * (PageColumns - 1)) /
+ PageColumns;
+ }
+ else
+ ColumnWidth = SizeColumns;
+
+ /*
+ * Output the DSC header...
+ */
+
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+ strftime(curdate, sizeof(curdate), CUPS_STRFTIME_FORMAT, curtm);
+
+ puts("%!PS-Adobe-3.0");
+ printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth, PageLength);
+ printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
+ puts("%%Creator: texttops/" CUPS_SVERSION);
+ printf("%%%%CreationDate: %s\n", curdate);
+ printf("%%%%Title: %s\n", title);
+ printf("%%%%For: %s\n", user);
+ puts("%%Pages: (atend)");
+
+ /*
+ * Initialize globals...
+ */
+
+ NumFonts = 0;
+ memset(Fonts, 0, sizeof(Fonts));
+ memset(Glyphs, 0, sizeof(Glyphs));
+ memset(Chars, 0, sizeof(Chars));
+ memset(Codes, 0, sizeof(Codes));
+
+ /*
+ * Load the PostScript glyph names and the corresponding character
+ * set definition...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/data/psglyphs", datadir);
+
+ if ((fp = fopen(filename, "r")) != NULL)
+ {
+ while (fscanf(fp, "%x%63s", &unicode, glyph) == 2)
+ Glyphs[unicode] = strdup(glyph);
+
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", filename,
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * Get the output character set...
+ */
+
+ charset = getenv("CHARSET");
+ if (charset != NULL && strcmp(charset, "us-ascii") != 0)
+ {
+ snprintf(filename, sizeof(filename), "%s/charsets/%s", datadir, charset);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ {
+ /*
+ * Can't open charset file!
+ */
+
+ fprintf(stderr, "ERROR: Unable to open %s: %s\n", filename,
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * Opened charset file; now see if this is really a charset file...
+ */
+
+ if (fgets(line, sizeof(line), fp) == NULL)
+ {
+ /*
+ * Bad/empty charset file!
+ */
+
+ fclose(fp);
+ fprintf(stderr, "ERROR: Bad/empty charset file %s\n", filename);
+ exit(1);
+ }
+
+ if (strncmp(line, "charset", 7) != 0)
+ {
+ /*
+ * Bad format/not a charset file!
+ */
+
+ fclose(fp);
+ fprintf(stderr, "ERROR: Bad charset file %s\n", filename);
+ exit(1);
+ }
+
+ /*
+ * See if this is an 8-bit or UTF-8 character set file...
+ */
+
+ line[strlen(line) - 1] = '\0'; /* Drop \n */
+ for (lineptr = line + 7; isspace(*lineptr & 255); lineptr ++); /* Skip whitespace */
+
+ if (strcmp(lineptr, "8bit") == 0)
+ {
+ /*
+ * 8-bit text...
+ */
+
+ UTF8 = 0;
+ NumFonts = 0;
+
+ /*
+ * Read the font description(s)...
+ */
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Skip comment and blank lines...
+ */
+
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /*
+ * Read the font descriptions that should look like:
+ *
+ * first last direction width normal [bold italic bold-italic]
+ */
+
+ lineptr = line;
+
+ start = strtol(lineptr, &lineptr, 16);
+ end = strtol(lineptr, &lineptr, 16);
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ if (!*lineptr)
+ break; /* Must be a font mapping */
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (strcmp(valptr, "ltor") == 0)
+ Directions[NumFonts] = 1;
+ else if (strcmp(valptr, "rtol") == 0)
+ Directions[NumFonts] = -1;
+ else
+ {
+ fprintf(stderr, "ERROR: Bad text direction %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Got the direction, now get the width...
+ */
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (strcmp(valptr, "single") == 0)
+ Widths[NumFonts] = 1;
+ else if (strcmp(valptr, "double") == 0)
+ Widths[NumFonts] = 2;
+ else
+ {
+ fprintf(stderr, "ERROR: Bad text width %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Get the fonts...
+ */
+
+ for (i = 0; *lineptr && i < 4; i ++)
+ {
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (*lineptr)
+ *lineptr++ = '\0';
+
+ if (lineptr > valptr)
+ Fonts[NumFonts][i] = strdup(valptr);
+ }
+
+ /*
+ * Fill in remaining fonts as needed...
+ */
+
+ for (j = i; j < 4; j ++)
+ Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
+
+ /*
+ * Define the character mappings...
+ */
+
+ for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
+ Chars[i] = j;
+
+ NumFonts ++;
+ }
+
+ /*
+ * Read encoding lines...
+ */
+
+ do
+ {
+ /*
+ * Skip comment and blank lines...
+ */
+
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /*
+ * Grab the character and unicode glyph number.
+ */
+
+ if (sscanf(line, "%x%x", &ch, &unicode) == 2 && ch < 256)
+ Codes[Chars[ch]] = unicode;
+ }
+ while (fgets(line, sizeof(line), fp) != NULL);
+
+ fclose(fp);
+ }
+ else if (strcmp(lineptr, "utf8") == 0)
+ {
+ /*
+ * UTF-8 (Unicode) text...
+ */
+
+ UTF8 = 1;
+
+ /*
+ * Read the font descriptions...
+ */
+
+ NumFonts = 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Skip comment and blank lines...
+ */
+
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /*
+ * Read the font descriptions that should look like:
+ *
+ * start end direction width normal [bold italic bold-italic]
+ */
+
+ lineptr = line;
+
+ start = strtol(lineptr, &lineptr, 16);
+ end = strtol(lineptr, &lineptr, 16);
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (strcmp(valptr, "ltor") == 0)
+ Directions[NumFonts] = 1;
+ else if (strcmp(valptr, "rtol") == 0)
+ Directions[NumFonts] = -1;
+ else
+ {
+ fprintf(stderr, "ERROR: Bad text direction %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Got the direction, now get the width...
+ */
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ fprintf(stderr, "ERROR: bad font description line: %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (strcmp(valptr, "single") == 0)
+ Widths[NumFonts] = 1;
+ else if (strcmp(valptr, "double") == 0)
+ Widths[NumFonts] = 2;
+ else
+ {
+ fprintf(stderr, "ERROR: Bad text width %s\n", valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Get the fonts...
+ */
+
+ for (i = 0; *lineptr && i < 4; i ++)
+ {
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (*lineptr)
+ *lineptr++ = '\0';
+
+ if (lineptr > valptr)
+ Fonts[NumFonts][i] = strdup(valptr);
+ }
+
+ /*
+ * Fill in remaining fonts as needed...
+ */
+
+ for (j = i; j < 4; j ++)
+ Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
+
+ /*
+ * Define the character mappings...
+ */
+
+ for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
+ {
+ Chars[i] = j;
+ Codes[j] = i;
+ }
+
+ /*
+ * Move to the next font, stopping if needed...
+ */
+
+ NumFonts ++;
+ if (NumFonts >= 256)
+ break;
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Bad charset type %s\n", lineptr);
+ fclose(fp);
+ exit(1);
+ }
+ }
+ else
+ {
+ /*
+ * Standard ASCII output just uses Courier, Courier-Bold, and
+ * possibly Courier-Oblique.
+ */
+
+ NumFonts = 1;
+
+ Fonts[0][ATTR_NORMAL] = strdup("Courier");
+ Fonts[0][ATTR_BOLD] = strdup("Courier-Bold");
+ Fonts[0][ATTR_ITALIC] = strdup("Courier-Oblique");
+ Fonts[0][ATTR_BOLDITALIC] = strdup("Courier-BoldOblique");
+
+ Widths[0] = 1;
+ Directions[0] = 1;
+
+ /*
+ * Define US-ASCII characters...
+ */
+
+ for (i = 32; i < 127; i ++)
+ {
+ Chars[i] = i;
+ Codes[i] = i;
+ }
+ }
+
+ /*
+ * Generate a list of unique fonts to use...
+ */
+
+ for (i = 0, num_fonts = 0; i < NumFonts; i ++)
+ for (j = PrettyPrint ? 2 : 1; j >= 0; j --)
+ {
+ for (k = 0; k < num_fonts; k ++)
+ if (strcmp(Fonts[i][j], fonts[k]) == 0)
+ break;
+
+ if (k >= num_fonts)
+ {
+ /*
+ * Add new font...
+ */
+
+ fonts[num_fonts] = Fonts[i][j];
+ num_fonts ++;
+ }
+ }
+
+ /*
+ * List the fonts that will be used...
+ */
+
+ for (i = 0; i < num_fonts; i ++)
+ if (i == 0)
+ printf("%%%%DocumentNeededResources: font %s\n", fonts[i]);
+ else
+ printf("%%%%+ font %s\n", fonts[i]);
+
+ puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
+
+ for (i = 0; i < num_fonts; i ++)
+ {
+ if (ppd != NULL)
+ {
+ fprintf(stderr, "DEBUG: ppd->num_fonts = %d\n", ppd->num_fonts);
+
+ for (j = 0; j < ppd->num_fonts; j ++)
+ {
+ fprintf(stderr, "DEBUG: ppd->fonts[%d] = %s\n", j, ppd->fonts[j]);
+
+ if (strcmp(fonts[i], ppd->fonts[j]) == 0)
+ break;
+ }
+ }
+ else
+ j = 0;
+
+ if ((ppd != NULL && j >= ppd->num_fonts) ||
+ strncmp(fonts[i], "Courier", 7) == 0 ||
+ strcmp(fonts[i], "Symbol") == 0)
+ {
+ /*
+ * Need to embed this font...
+ */
+
+ printf("%%%%+ font %s\n", fonts[i]);
+ }
+ }
+
+ puts("%%EndComments");
+
+ puts("%%BeginProlog");
+
+ /*
+ * Download any missing fonts...
+ */
+
+ for (i = 0; i < num_fonts; i ++)
+ {
+ if (ppd != NULL)
+ {
+ for (j = 0; j < ppd->num_fonts; j ++)
+ if (strcmp(fonts[i], ppd->fonts[j]) == 0)
+ break;
+ }
+ else
+ j = 0;
+
+ if ((ppd != NULL && j >= ppd->num_fonts) ||
+ strncmp(fonts[i], "Courier", 7) == 0 ||
+ strcmp(fonts[i], "Symbol") == 0)
+ {
+ /*
+ * Need to embed this font...
+ */
+
+ printf("%%%%BeginResource: font %s\n", fonts[i]);
+
+ /**** MRS: Need to use CUPS_FONTPATH env var! ****/
+ /**** Also look for Fontmap file or name.pfa, name.pfb... ****/
+ snprintf(filename, sizeof(filename), "%s/fonts/%s", datadir, fonts[i]);
+ if ((fp = fopen(filename, "rb")) != NULL)
+ {
+ while ((j = fread(line, 1, sizeof(line), fp)) > 0)
+ fwrite(line, 1, j, stdout);
+
+ fclose(fp);
+ }
+
+ puts("\n%%EndResource");
+ }
+ }
+
+ /*
+ * Write the encoding array(s)...
+ */
+
+ puts("% character encoding(s)");
+
+ for (i = 0; i < NumFonts; i ++)
+ {
+ printf("/cupsEncoding%02x [\n", i);
+
+ for (ch = 0; ch < 256; ch ++)
+ {
+ if (Glyphs[Codes[i * 256 + ch]])
+ printf("/%s", Glyphs[Codes[i * 256 + ch]]);
+ else if (Codes[i * 256 + ch] > 255)
+ printf("/uni%04X", Codes[i * 256 + ch]);
+ else
+ printf("/.notdef");
+
+ if ((ch & 7) == 7)
+ putchar('\n');
+ }
+
+ puts("] def");
+ }
+
+ /*
+ * Create the fonts...
+ */
+
+ if (NumFonts == 1)
+ {
+ /*
+ * Just reencode the named fonts...
+ */
+
+ puts("% Reencode fonts");
+
+ for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
+ {
+ printf("/%s findfont\n", Fonts[0][i]);
+ puts("dup length 1 add dict begin\n"
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
+ " /Encoding cupsEncoding00 def\n"
+ " currentdict\n"
+ "end");
+ printf("/%s exch definefont pop\n", names[i]);
+ }
+ }
+ else
+ {
+ /*
+ * Construct composite fonts... Start by reencoding the base fonts...
+ */
+
+ puts("% Reencode base fonts");
+
+ for (i = 1 + PrettyPrint; i >= 0; i --)
+ for (j = 0; j < NumFonts; j ++)
+ {
+ printf("/%s findfont\n", Fonts[j][i]);
+ printf("dup length 1 add dict begin\n"
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
+ " /Encoding cupsEncoding%02x def\n"
+ " currentdict\n"
+ "end\n", j);
+ printf("/%s%02x exch definefont /%s%02x exch def\n", names[i], j,
+ names[i], j);
+ }
+
+ /*
+ * Then merge them into composite fonts...
+ */
+
+ puts("% Create composite fonts...");
+
+ for (i = 1 + PrettyPrint; i >= 0; i --)
+ {
+ puts("8 dict begin");
+ puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding[");
+ for (j = 0; j < NumFonts; j ++)
+ if (j == (NumFonts - 1))
+ printf("%d", j);
+ else if ((j & 15) == 15)
+ printf("%d\n", j);
+ else
+ printf("%d ", j);
+ puts("]def/FDepVector[");
+ for (j = 0; j < NumFonts; j ++)
+ if (j == (NumFonts - 1))
+ printf("%s%02x", names[i], j);
+ else if ((j & 3) == 3)
+ printf("%s%02x\n", names[i], j);
+ else
+ printf("%s%02x ", names[i], j);
+ puts("]def currentdict end");
+ printf("/%s exch definefont pop\n", names[i]);
+ }
+ }
+
+ /*
+ * Output the texttops procset...
+ */
+
+ puts("%%BeginResource: procset texttops 1.1 0");
+
+ puts("% Define fonts");
+
+ printf("/FN /cupsNormal findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
+ 120.0 / CharsPerInch, 68.0 / LinesPerInch);
+ printf("/FB /cupsBold findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
+ 120.0 / CharsPerInch, 68.0 / LinesPerInch);
+ if (PrettyPrint)
+ printf("/FI /cupsItalic findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
+ 120.0 / CharsPerInch, 68.0 / LinesPerInch);
+
+ puts("% Common procedures");
+
+ puts("/N { FN setfont moveto } bind def");
+ puts("/B { FB setfont moveto } bind def");
+ printf("/U { gsave 0.5 setlinewidth 0 %.3f rmoveto "
+ "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch);
+
+ if (PrettyPrint)
+ {
+ if (ColorDevice)
+ {
+ puts("/S { 0.0 setgray show } bind def");
+ puts("/r { 0.5 0.0 0.0 setrgbcolor show } bind def");
+ puts("/g { 0.0 0.5 0.0 setrgbcolor show } bind def");
+ puts("/b { 0.0 0.0 0.5 setrgbcolor show } bind def");
+ }
+ else
+ {
+ puts("/S { 0.0 setgray show } bind def");
+ puts("/r { 0.2 setgray show } bind def");
+ puts("/g { 0.2 setgray show } bind def");
+ puts("/b { 0.2 setgray show } bind def");
+ }
+
+ puts("/I { FI setfont moveto } bind def");
+
+ puts("/n {");
+ puts("\t20 string cvs % convert page number to string");
+ if (NumFonts > 1)
+ {
+ /*
+ * Convert a number to double-byte chars...
+ */
+
+ puts("\tdup length % get length");
+ puts("\tdup 2 mul string /P exch def % P = string twice as long");
+ puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
+ puts("\t\tdup 3 index exch get % get character N from the page number");
+ puts("\t\texch 2 mul dup % compute offset in P");
+ puts("\t\tP exch 0 put % font 0");
+ puts("\t\t1 add P exch 2 index put % character");
+ puts("\t\tpop % discard character");
+ puts("\t} for % do for loop");
+ puts("\tpop pop % discard string and length");
+ puts("\tP % put string on stack");
+ }
+ puts("} bind def");
+
+ printf("/T");
+ write_text(title);
+ puts("def");
+
+ printf("/D");
+ write_text(curdate);
+ puts("def");
+
+ puts("/H {");
+ puts("\tgsave");
+ puts("\t0.9 setgray");
+
+ if (Duplex)
+ {
+ puts("\tdup 2 mod 0 eq {");
+ printf("\t\t%.3f %.3f translate } {\n",
+ PageWidth - PageRight, PageTop + 72.0f / LinesPerInch);
+ printf("\t\t%.3f %.3f translate } ifelse\n",
+ PageLeft, PageTop + 72.0f / LinesPerInch);
+ }
+ else
+ printf("\t%.3f %.3f translate\n",
+ PageLeft, PageTop + 72.0f / LinesPerInch);
+
+ printf("\t0 0 %.3f %.3f rectfill\n", PageRight - PageLeft,
+ 144.0f / LinesPerInch);
+
+ puts("\tFB setfont");
+ puts("\t0 setgray");
+
+ if (Duplex)
+ {
+ puts("\tdup 2 mod 0 eq {");
+ printf("\t\tT stringwidth pop neg %.3f add %.3f } {\n",
+ PageRight - PageLeft - 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ printf("\t\t%.3f %.3f } ifelse\n", 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ }
+ else
+ printf("\t%.3f %.3f\n", 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+
+ puts("\tmoveto T show");
+
+ printf("\tD dup stringwidth pop neg 2 div %.3f add %.3f\n",
+ (PageRight - PageLeft) * 0.5,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ puts("\tmoveto show");
+
+ if (Duplex)
+ {
+ puts("\tdup n exch 2 mod 0 eq {");
+ printf("\t\t%.3f %.3f } {\n", 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ printf("\t\tdup stringwidth pop neg %.3f add %.3f } ifelse\n",
+ PageRight - PageLeft - 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ }
+ else
+ printf("\tn dup stringwidth pop neg %.3f add %.3f\n",
+ PageRight - PageLeft - 36.0f / LinesPerInch,
+ (0.5f + 0.157f) * 72.0f / LinesPerInch);
+
+ puts("\tmoveto show");
+ puts("\tgrestore");
+ puts("} bind def");
+ }
+ else
+ puts("/S { show } bind def");
+
+ puts("%%EndResource");
+
+ puts("%%EndProlog");
+}
+
+
+/*
+ * 'write_line()' - Write a row of text.
+ */
+
+static void
+write_line(int row, /* I - Row number (0 to N) */
+ lchar_t *line) /* I - Line to print */
+{
+ int i; /* Looping var */
+ int col; /* Current column */
+ int attr; /* Current attribute */
+ int font, /* Font to use */
+ lastfont, /* Last font */
+ mono; /* Monospaced? */
+ lchar_t *start; /* First character in sequence */
+
+
+ for (col = 0, start = line; col < SizeColumns;)
+ {
+ while (col < SizeColumns && (line->ch == ' ' || line->ch == 0))
+ {
+ col ++;
+ line ++;
+ }
+
+ if (col >= SizeColumns)
+ break;
+
+ if (NumFonts == 1)
+ {
+ /*
+ * All characters in a single font - assume monospaced...
+ */
+
+ attr = line->attr;
+ start = line;
+
+ while (col < SizeColumns && line->ch != 0 && attr == line->attr)
+ {
+ col ++;
+ line ++;
+ }
+
+ write_string(col - (line - start), row, line - start, start);
+ }
+ else
+ {
+ /*
+ * Multiple fonts; break up based on the font...
+ */
+
+ attr = line->attr;
+ start = line;
+ lastfont = Chars[line->ch] / 256;
+ mono = strncmp(Fonts[lastfont][0], "Courier", 7) == 0;
+ col ++;
+ line ++;
+
+ if (mono)
+ {
+ while (col < SizeColumns && line->ch != 0 && attr == line->attr)
+ {
+ font = Chars[line->ch] / 256;
+ if (strncmp(Fonts[font][0], "Courier", 7) != 0 ||
+ font != lastfont)
+ break;
+
+ col ++;
+ line ++;
+ }
+ }
+
+ if (Directions[lastfont] > 0)
+ write_string(col - (line - start), row, line - start, start);
+ else
+ {
+ /*
+ * Do right-to-left text...
+ */
+
+ while (col < SizeColumns && line->ch != 0 && attr == line->attr)
+ {
+ if (Directions[Chars[line->ch] / 256] > 0 &&
+ !ispunct(line->ch & 255) && !isspace(line->ch & 255))
+ break;
+
+ col ++;
+ line ++;
+ }
+
+ for (i = 1; start < line; i ++, start ++)
+ if (!isspace(start->ch & 255))
+ write_string(col - i, row, 1, start);
+ }
+ }
+ }
+}
+
+
+/*
+ * 'write_string()' - Write a string of text.
+ */
+
+static void
+write_string(int col, /* I - Start column */
+ int row, /* I - Row */
+ int len, /* I - Number of characters */
+ lchar_t *s) /* I - String to print */
+{
+ int ch; /* Current character */
+ float x, y; /* Position of text */
+ unsigned attr; /* Character attributes */
+
+
+ /*
+ * Position the text and set the font...
+ */
+
+ if (Duplex && (NumPages & 1) == 0)
+ {
+ x = PageWidth - PageRight;
+ y = PageTop;
+ }
+ else
+ {
+ x = PageLeft;
+ y = PageTop;
+ }
+
+ x += (float)col * 72.0f / (float)CharsPerInch;
+ y -= (float)(row + 0.843) * 72.0f / (float)LinesPerInch;
+
+ attr = s->attr;
+
+ if (attr & ATTR_RAISED)
+ y += 36.0 / (float)LinesPerInch;
+ else if (attr & ATTR_LOWERED)
+ y -= 36.0 / (float)LinesPerInch;
+
+ if (x == (int)x)
+ printf("%.0f ", x);
+ else
+ printf("%.3f ", x);
+
+ if (y == (int)y)
+ printf("%.0f ", y);
+ else
+ printf("%.3f ", y);
+
+ if (attr & ATTR_BOLD)
+ putchar('B');
+ else if (attr & ATTR_ITALIC)
+ putchar('I');
+ else
+ putchar('N');
+
+ if (attr & ATTR_UNDERLINE)
+ printf(" %.3f U", (float)len * 72.0 / (float)CharsPerInch);
+
+ if (NumFonts > 1)
+ {
+ /*
+ * Write a hex string...
+ */
+
+ putchar('<');
+
+ while (len > 0)
+ {
+ printf("%04x", Chars[s->ch]);
+
+ len --;
+ s ++;
+ }
+
+ putchar('>');
+ }
+ else
+ {
+ /*
+ * Write a quoted string...
+ */
+
+ putchar('(');
+
+ while (len > 0)
+ {
+ ch = Chars[s->ch];
+
+ if (ch < 32 || ch > 126)
+ {
+ /*
+ * Quote 8-bit and control characters...
+ */
+
+ printf("\\%03o", ch);
+ }
+ else
+ {
+ /*
+ * Quote the parenthesis and backslash as needed...
+ */
+
+ if (ch == '(' || ch == ')' || ch == '\\')
+ putchar('\\');
+
+ putchar(ch);
+ }
+
+ len --;
+ s ++;
+ }
+
+ putchar(')');
+ }
+
+ if (PrettyPrint)
+ {
+ if (attr & ATTR_RED)
+ puts("r");
+ else if (attr & ATTR_GREEN)
+ puts("g");
+ else if (attr & ATTR_BLUE)
+ puts("b");
+ else
+ puts("S");
+ }
+ else
+ puts("S");
+}
+
+
+/*
+ * 'write_text()' - Write a text string, quoting/encoding as needed.
+ */
+
+static void
+write_text(const char *s) /* I - String to write */
+{
+ int ch; /* Actual character value (UTF8) */
+ const unsigned char *utf8; /* UTF8 text */
+
+
+ if (NumFonts > 1)
+ {
+ /*
+ * 8/8 encoding...
+ */
+
+ putchar('<');
+
+ utf8 = (const unsigned char *)s;
+
+ while (*utf8)
+ {
+ if (*utf8 < 0xc0 || !UTF8)
+ ch = *utf8 ++;
+ else if ((*utf8 & 0xe0) == 0xc0)
+ {
+ /*
+ * Two byte character...
+ */
+
+ ch = ((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f);
+ utf8 += 2;
+ }
+ else
+ {
+ /*
+ * Three byte character...
+ */
+
+ ch = ((((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f)) << 6) |
+ (utf8[2] & 0x3f);
+ utf8 += 3;
+ }
+
+ printf("%04x", Chars[ch]);
+ }
+
+ putchar('>');
+ }
+ else
+ {
+ /*
+ * Standard 8-bit encoding...
+ */
+
+ putchar('(');
+
+ while (*s)
+ {
+ if (*s < 32 || *s > 126)
+ printf("\\%03o", *s);
+ else
+ {
+ if (*s == '(' || *s == ')' || *s == '\\')
+ putchar('\\');
+
+ putchar(*s);
+ }
+
+ s ++;
+ }
+
+ putchar(')');
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/filter/texttops.dsp b/filter/texttops.dsp
new file mode 100644
index 000000000..12b7cc6be
--- /dev/null
+++ b/filter/texttops.dsp
@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="texttops" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=texttops - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "texttops.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "texttops.mak" CFG="texttops - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "texttops - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "texttops - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "texttops - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W1 /GX /O2 /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../cups/cups.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"texttops.exe"
+
+!ELSEIF "$(CFG)" == "texttops - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W1 /Gm /GX /Zi /Od /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../cups/cupsd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"texttopsd.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "texttops - Win32 Release"
+# Name "texttops - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\texttops.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# End Target
+# End Project
diff --git a/fonts/Courier b/fonts/Courier
new file mode 100644
index 000000000..5ec263dbe
--- /dev/null
+++ b/fonts/Courier
@@ -0,0 +1,1494 @@
+%!PS-AdobeFont-1.0: Courier 1.05
+%%CreationDate: Wed Dec 22 1999
+% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development
+% (URW)++,Copyright 1999 by (URW)++ Design & Development
+% See the file COPYING (GNU General Public License) for license conditions.
+% As a special exception, permission is granted to include this font
+% program in a Postscript or PDF file that consists of a document that
+% contains text to be displayed or printed using this font, regardless
+% of the conditions or license applying to the document itself.
+12 dict begin
+/FontInfo 10 dict dup begin
+/version (1.05) readonly def
+/Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file COPYING (GNU General Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def
+/Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def
+/FullName (Courier) readonly def
+/FamilyName (Courier) readonly def
+/Weight (Regular) readonly def
+/ItalicAngle 0.0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/FontName /Courier def
+/PaintType 0 def
+/WMode 0 def
+/FontBBox {-12 -237 650 811} readonly def
+/FontType 1 def
+/FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def
+/Encoding StandardEncoding def
+/UniqueID 5020945 def
+currentdict end
+currentfile eexec
+e98d09d760a3c22cf119f9dc699a22c35b5b35ed6aa23593c76d54cabb5e
+942bf7d6dd84f1664b89699c74b472de9f8e6df925f6c4f204e9f1c639b4
+dba988ed2ac419ff2b2bde605b8ee3264edd66412d4f21c64ac522bdfc7c
+5502f9c3f3e5592b3b2093d33c9bfaedd2d49e89aabaa832e23f062e91a2
+5032519d1868816e44b4e0747795003d7930299d6e1e2a5bfe0d595dc97e
+140989ce81d8d7f852ff9cdc7a1b1b598c69131dee005b415805a16d8a12
+3e6a2261c63c769d2f4b60fa2c438ad7d199d8e45f7e7c9a605c8ca14e21
+fcd81c9a515fb8db6f99604534d06ea9d87fe0faa852899c9d0595c7a97e
+6c55f79fac45cd38e87b10d210ce7501e88c8fcd3444354365fb893a12f5
+96ae2c1e70d5819ee0d087d10bf8da96f3dabd5405d28c4228c6c31ba405
+2464859640933feefd8071c0c84cdd829a9b1d0ba01f25a4d50ee2ea2b45
+160ca6333b2d2800306ed2befdfe155e9d9f9342eb8d5b0adbf2460ccc98
+643fb1287ccd28aba7b5cab92ec39ee2e918990372b16f8487eba30eae88
+708b6cf33b6c015d8096c7cfe2f139f52052e3925c0d50fd64ce68236d59
+cb83ef56bfc584150ec38065059f3308ad6f9a99f83ef4e6cb13855c8175
+e31417d190d036b387d3952344a950f4d8c7781b307a094df1ecaee4d2c2
+fd747bc6f7f9c6bd0e90c19294f96c8c5cfe88fb34c477574a1b1630b8cc
+591529e59b20794da32e61decda8abbd1ae956cf74012aa01d42ee01e861
+b0aa6897c864788ae59def43c493246fdb1aca554c12594bc7b33657a9ec
+c9e3d1472ef826073f632be540c35ff6fb40566773f3bb2204d3a579a08c
+cbc844c14b18c350f003b9da23a570c362d6003893ca32f86f59b829c78e
+e3188b6e3f7fa81d7f622825c639638dfb78b7af1f500f5b450fa54dbfa5
+cba277c794ece93275a3de0b452fdc8ddc2993baa42f28a636008cdcb03e
+bf71bdcaf35019778993443f88412ad2ad0d7155a3944606463266322dbc
+0244b07da1e9c27a27b59664e8566d7a54cc03e995aad008b0a17e2c3ef6
+1f720ce7f7788599c4e44c709cd5c31b11107f16ad70b17b9afe2e8cd922
+a7428dac171427ffaf51067307fab0adb530e701fd22da22c4cd3064067b
+d4f6089c4b2c87937dd426e4e9d2f60e608288bac9056554d04947e69200
+61e379cf5e81bfd32fd37efac1f61cebee551b0851516471a7472c60df89
+daa9eb1dc5a67e4797453e69b9e22baf4e3cca4192d603295b018c4ab69d
+18de52dfdf15e96b557f290a4b8c5b1e7a6caca81f2351b97adfc36995ab
+a43803a6e5ac04a3c93495f6d38106b8b144449c07d1358210f9176e1565
+72363cfbde576bfdf99fa329dd1346e83f79e06cf68250ca57a68931bc7f
+342ad295d0cba17aa95bb8eeb53ea6e8e660b814e9f857cecb14f44a4328
+8b69a9e7908d55bf19e844359879d28caef1c38a36420185d20dfb32c2e0
+02202800e8ef3d67c5d50e919657ca958b538d537d503444865331d79bfc
+40312068d72364503bd0cc84b5f30a74d8b5b6a26af2db764564fb65a6ba
+8f9051ae2b4ea458d46a4569f30c6e77dc097356770362e6cf3f16610747
+78ebb44ff7d1e3b64ff75e77e11fe525bb121c6546cfd13300ca1f02d571
+b82a5825e6226d14fdcf27f06d87452a8b6c5dca658535cee2a795e58137
+d48e566b69d53a0c3b766e84c51eaa221c46999cc8065adb2f129d5b630f
+ab1814c0c33b5aea0efbb6e994d80941b53079af96d90a0b924f9b0e319b
+ed9836b8f9053f868363d3ca554cbb181863301f8cb940872ed5fa7bd18c
+e39218b5ad8ac57d0f752d941076b1c64d99be0db86d7a6d96510d772eb2
+4c587f11779bd21cfe5bde1f29c1ef9022b2b8bcd7f91153c84590672247
+7829c40111d810480f3cf62de8dba7fd86cd236e656618caf6fc46827fbc
+4898ea7672f8c9971afe43e0e01ec8b77d4af48cbf1210e98c1db15c16d1
+49bff58ab0270cf015b107a3a50f5dc8f37ffb92eec8cb6778ddb7ce4aab
+c464c4aff654223006a550eb52485a23d2b4aa7198d3cd54418102f1e9a4
+fbde37b841e56f5c2c53966db9b66b000e4588282e3fb80c2c519339f000
+2d2f83c979edc5827a3b3c8ef8810a0f9dacb6b9998e9af6551f56313dc4
+011904cb979aa2d32b11a811bc248141e4b9734d9fb7982a5671002d8279
+cab93abe057474628defc95d43890db1ed34cfa8a20bdc3d874e7679a396
+158e522ed0ab969a4e3ec7e4474e192590504d54deb7b260b7935c4e5654
+8a7d121ac1f741f8cdf259ea1b5813175a77a1d2d30ba26f65eb765a04c0
+9ed51f69f41551adf399e6aa2fc09788137bea4913f17b8eb838c38fb272
+1fdcb55fd65697ff0b850e7d3d1ce266bf90f7ec06a9a0876bdfe767d3a9
+18b092fc78c775f945cf1f96e859c03dbf630d9a940939654c3549d8f792
+1cb94ee23d5a0535de9df31ea0f937f860b4f220a99addfc343d7cf7bfa0
+b803c12c26403f0dcffc8ea786d0d8a8d9c367419ca8ae41190ce93a8086
+583a1e6c9d70b612c84d87d2eeaa71ec2dc12f4cde6a821303d5f6a9bbdb
+7eedcd289e80fa3b75f47f481b50719dcf4a142069393593b9af9cceeaec
+56a35b8787193d7c88113e9e1e221d151e093b019ef89f6118bec4735103
+cc8003cc5ad1b6727b3226cd44c497da7052dd681695dbec3397f9598c91
+77701c73bf0594ce93f23d50ec5bee2fb9da1fc966df148b27b28ee3c895
+26dd6625e2887f9fa0767c127c609ee315626bc14d274fbea56528dc06a2
+7b2d476d46e9e7916590b156a5df04a6cb15e36245d77021767b6e5bdfcc
+679670263fd891446c3371b11bb6e1df60f960aab4149d7753e6a5c33810
+c42c8bff4e935003388506f8278bd7cb672f132e065ae684dca0b9064d01
+dd620e7ffdfe04f14277efe8e60159ba0fca3fe2f28b902d4ac275d19f0a
+c6971ebe827c4a232d87650d2688345bca78f879077114f0463c5f058107
+b669566f8171e4e284d278405580f04bffc9902784216e0c9a17aa9b2935
+e66e18a783f723be044389b7e9d62aa36818ff2ea406c3c1a9d2f3436f3e
+e7db8be86afa8daa6a4b1b84611350d8d27605509612b515e16aa843164d
+5d0805e36a2b9ef74c5f6a0b9d59a04b5569712327f4b1b30e9587cd1033
+37639967cbdc655aa46e80d2cfd24beb50815b5338e522b3a7afe8362ab4
+f05d8bc52bba9c5089ada8c89529b0275af422eb540d31a938b874086075
+6325b966b36817115213faaf92de63f6bae1e0064bfbc5588098b61eb83c
+71f1c2082436d37daf1acbe186fedc4be7c1233b6f18bec5f99002d21cb7
+864e4811f7ab3c03003e1e4490ad1ac793bd28fcd5ef0e6cc30ef39a08c5
+2f71939b0cef620dc69e31e39d6db969049031b0c92ef2db653d97f37014
+1456a52985076b268652fa2648c792780bad637c4d7581fb2d62011d57e2
+93719487cf2d1f013cfaa532e1c2d39178d51272a6af041440bca174b5cc
+902bd7390c7d3695056cb4bd7791f9fb6d88e7a70def2c97869f5dbc5bd8
+23c517c7b7c39d624df627dc9653ea5347bfda80b723f05f6dbb4c9ea501
+d862ace05b9dbdf21b7056fbcd8c6d4b85873dcee6166c8b5adc0316ca12
+d9639f361b15a42f00e1d62edbca1111972fa0f45758becb31db38316f3c
+dfe1b41748c93ed58b67e9b57abbed5924a6d53e99fbc9a994a6489a8bdf
+13eb685548b4dc6d62da7426c22227d4d43b6ffc7b5ea91c896730253e89
+41afee588359c2becf6ffc415b9eb6d31ccb0f6c7f85853e6449fa6d627a
+97a3ce8303f148393adcccdfa2fe085c6908be5c3c05af00a6f02840206c
+3253a559ac5c049bddfd11ad9b118403b84da10ae3c470cb9a9a2d1d7b73
+2f59f5fe146deda60ae750f551aac934621b4470e1bc324c436303e25f81
+d0dc3188be0d6fec5414c20e4cb18952e12cb6423df7124627acde145500
+d77a97a8bfd9cb50d1faa008e2ce2b2505a4749f1ebbb092c34702371405
+5a9b63353af9e7fee05bb54c9843698101f79888a91531773830c2c967b5
+88d3acd2192883d5ce3962d51084fc653eae2c5fb2da41dacefb5c76812d
+2edb5b109677289cd1998d457fb1023a19ac67295bbc1a9a20a426b06a36
+8df3c5dd083cb1180d287f5500f2c635ede157eefceec5503447382d15c7
+48c1e35f68753992e5c90f900de54d18f8e1b355d1076adfb1f3590135fa
+d1a36f028e44f48abb149b80ca9a54614d467f8d71cb310bbc7ac7100261
+092db8c5bfd39e0ac6bc2c9d6cbc3a8c05ff8a74cb21608ec4a4cfe4cbaa
+2d056dba14206106044decf59f957ef8a9cade4c9b19d8d30dd4fde6a954
+8e50db51aca73330142153fc36b69c1c8d5b26d0c689b7040e81ac2c864f
+d7c097c99be5953843e172c97ab5684f35fb03a725a89dbf371f08ddf40a
+1531fc1b676db0e1543aec6e97d3d2e4aa3d5831d8b3c952abbfa1123528
+14fb6fab61a0d680e6640f6aec8426200cf61286f7422cb2f78c61ebaa36
+d47ec16d7faf8b4af31d090cdfa255d9d7c61d46cfb22a7d6e1758e71ed5
+67e00cbd8e8f468ddfb477f091a2f915627f22ff47b876544bc1f03b6bbb
+98385f009c20bb1aa2a7a78674692b8eac2e3c8069b79e679338da57f729
+76810f845beb6b9add32b95d78e5e60f16dd16689c05fd82d36a3115be8e
+d494a74dd211d58a2cdf983fcb9cdc29bf7f0e29988fa23560edf514bc1d
+183f3b2a22c09fb179b47e05adef48df02f31c29875d1915037b19407764
+a4292fe44e741651a8e3beb5f0d972b6327090f664417c84f84ffbf0afff
+8b1d85c822d90730ab4140c42a51aa8b1dbe43984ea8566040eb8b341cce
+23fd3f69dd235a080ba5c69aecb9bc732bc2d7d40617dda6b79fb6ee40c3
+556c7df9b23dad89e94054b1345db8402ae679fc4655a4a776c0150463f8
+db2bfc0608ea1f124e221ddae6026b5e5d007a7e4a0d6b3b0cf3a2669e67
+c5e4f01551966a7bc48f2f4b6a87e740d8095e63f77c7a027f26b52f2299
+de5b8a2f6209bcf3d31cb0235f998f781e5cc81e31dc424e008d46ec0920
+2951e5684804a0592ea47d6c788a20487bea2ec8f2e6c1d7f378b62db43c
+a43c4b366f8b4319631cfe9854f0e10321cfa3b01c873584863bbefc23c7
+2c05e695b56e8a52e89aa2dab543834d34dcac5fed08dc51825c5257ae59
+850d101d84f4caa1d29fc932f9e0effbf7a9a7f3685f61f0490cd3cc8988
+2db52a757a6af4c4e67b407bd2316b1c0ffe7dc54e43c87b874f57e49033
+34e2140b011484863cdcaca331175f2cf3d72e0042855983aaf8853d3015
+e870ff0807014c31d55060df3fe1fce1573244812744ab51322444632f9a
+fda6706e320ffe82b8cbe242a19df00ce73ee48e25ff49d5871bd3e60652
+298fe3e8d400609e232e0ddc794c0579acef89e841b2edca50d51151f65e
+8c1cc3b01ef1870558f0bf5743718c3e068617e81bfe120c6ca16e0924bf
+c2541177d53671caa3ab641c41557dcdae1a346147b5e999c4541b08b4af
+cbc187afd653d5b5f8386df6ad8fe69e21bd0567df494f736c6a184fa4de
+48dc9f347787ca96e2e00a296c2da05c2ad9bc423e9ca428d7f1fa12dc93
+53a302fb8c529af8688cbb543b45b2717ebf8f6c497935f4f3bffd285e04
+02ab7544b3ca4643ae5a8b5250ed987a95fc1f275b9707acd0641bd0ee2a
+e9758494f8d8a51dce408a38ac20eaf0852d72d84d0c6be973326793aeb9
+55eac6fe0a2813a355dcd22f6f2ce56588d1c055cddfa98878bceb6a018d
+b22922d2b600a20f81842e665df41013ca0947c4237c2bd60a75e2fd1a3f
+b8c8fa19485730b87461ad466acb02df8ca240914fb090b3d2b41eb6b8ff
+05e1a59d9fd668af70ba5bb72778953ba55fc5f9f626043450e1d09bc83d
+8605098abef884639a37809a32565cbefb3ff39ee53d6c18c58c272bb928
+e4410e361e59a50f242d69747a032617c52debbf62364ab5a96efaf642d9
+d82ba679b1d70fac10a4eb62fa5cfc308e86368aaad7e75948f43598cd1c
+544a0d4091374d7e88d4522cbe902391641327e888e7748fa889dce67ade
+61699e7d77763681caee9b1ca8837b2f7ef9c18cbcc538c465c8e2dd3461
+6953ccb6030a222c728b834911c1a179e2c770289407ab28b303e724d97f
+747d6134b425216a64c6e0b60f633e2b85300047e4c90339ce030a0fae31
+e830c8aba5ab3386a3b69267351a7bfdd66356ae5e57fb2994452993e90d
+e7c4e260abab93c37831856a650d56e44172feca01d6c7c380f250b82473
+960d2a2a5fb6b4da668f46e624acf7fa0fd4490f485d640a3adfc9f8652e
+7a38ce5799f770c3606db4b8b947f93967f779e3a3c0572f13a5a187d31d
+7bd12a5c7be23cb6ed6192086241b76c5ba6983db9c93e4b208d707d3760
+f03cd6272ef3a4ce89b8e52e6ac5871a3d03eb975759ab4be239e5ec7842
+cbb333e692cc607c722e185d3c39164dd320c6945629c70ff66a5237c0a9
+520a1fad6eb9816069351ab0f135d90cc0982b147d2294ae4a38a527ee40
+be9cde2512aaebb590e134388bb171d0956a7c4566d65a9a041be6c4f883
+6b3ec3d2ed1b48b566a783292b15b6127920d247d494f070bb20beff6064
+0b11b276ddeee49706e8b2b21bb40b7f00aafc594c492c25dca774e0b80d
+82e927448de2e74a9d0dc7ac9260096eaf187b6cd6aeaa6d1dc4205b4411
+122751a5b22688404ea7c5861730371ffac10f5afd4727a0e402ab5ea757
+606b75eb86a05e8f774d6e430a1a3fe2a37ebb06700474239fb1cfa05ee4
+4b91b82244c575b52e7faf934b04eeb0d933feb57ebe326d75821c8b23ea
+a85b583aed4320b7f04b9f2dc591091216fde52e064baaa9c2c9d9714b95
+a4558c21f3cebe624b5403b31508f178581af6863083ed762f1e2e34a45c
+fdd71660d626ff8648f5d6c5e580d4765a67fb6159ec8077a9f0a88038c8
+d3d7c77ff0926e2123be874f7bcaf129d55a5b5960f824bd1728abcfcc51
+d23936de9a25c408d786e44c3a2bafa4423177ad060d21d38e15e23eb6ff
+c0b4120e814695d423eefc2744a1fc81b4df89d76f0a6803d8b14e75538c
+aad03a72517b86514f6952f6fd619d9e910d980f00964db325318c045bdf
+79647f453d4a5cf4e61dd5359782827229310405fbcf6107c3ad9ddef9a9
+a339d5d5a6eb2e7838a0a43221bd62cbdf732db0a638a52016fb35ba7761
+aec846a023d3bf2d1bb183543e81eb7cac1e5970cdc6f068c5ea118c7aae
+528d1396e6dc939112da4460c890ead5c01bdc438f5bb734218ba6270add
+0dc1778fd8ab16831d6a302b814a1a44b07edc65956c9e6cf4875df521f3
+ce5b422f71081b6d69bd270f739095c9e81c0377934a8bc6390c420c4e4c
+dd9cf7e32544c68d884e15aca3bcc07fc8c132d8fb9d752c15d75c52c288
+57e2ea461a6fcad90c56843513f74461f18d7164bc597a28ae4ba7c86ee1
+703535a9b9ed5012262771fc12f102e800e0e1af7bb46681bd2b14b614ce
+a91b7b2aaa35235de76c0e113c92688f8ec81277d58c3406778e1ec1cc15
+f1cd9a137c8ffdaab99ace3bfc782916f1a877170589a92dc921e6740a22
+b84dc6bacdabcc76e64c79e3a588d80f8f4d376e1b426f15751cf7391102
+102f0afafd8b22dfdeb548aeb5f30b1673023d22054a13391a0ec08de6e7
+b685a0d031aabf20b7c62187c0284892d5eaadf121ba28263eb863d5e36e
+a9c06a77ccfc0e17f593961591f84d82af823efe41044c8d606fef83ccc7
+b0e961e7994df8a3cc36b209d953e250adab8d22d7f2b4e2c9ca39efa2d9
+3e56195c1560e30a5190cc5b17faefcf250df79f6b624a4b917e11c33222
+2fccfec4f6a47bd9e75da9854fc3f7ae554e91edde144d7aef38a0e3edb5
+e5a5626374db94f022c8cf549093041de00d7269b7ce544e748439ba2870
+718c08e58fb4a77d93ebc04b7957d272ae1601d41bf85a2badaa0df73b0d
+3841d4839c85677fb2e15f1d6ce592669ff4bbc9c69dba334dc37706f2f6
+be83d5863e8cd6a30c08640aac4c233684e66b4fe6b62d4a8be9d531e47b
+ef5640d9b5c27d990092be1597f6995c8a77be9c18aae6c1cf130775ddac
+41d34438fc7ad8e042cb56cbf2944932eba7d053e9376ff398367450e35a
+1945fe23e05c921096a15454721ffd0f429a3e06dc3ed36f1c170be79c66
+996ef8337aff85b90c5d3a4a94455ae9fa32e2117a63e59001f052d5f622
+3125bfafa40901e98960adf7bb886729dca82fc3b8cc52b37ff2517299e1
+d769057f8154fb95582f02cb0becc873a9c71796adbd3e91324faa94f2c4
+1cf57c30b5897d031c02d256c909e080e70bfd1f32e69ef67031138c2ddc
+d1a8e4b65e485c23c3e450abdd9815512d6f34a84b9db715db2c7a93bfb4
+24316e1aa44397749cb01088428f149a3b4324737ed9957fd388248462ac
+1b2610d72bf5c073eca567e7385cc959e37cac7e05470160ffa5a9f63b8e
+9b082937e911586ea165374938f492edf28ce6020953a5b5ccec7737f9d9
+cc8538c4339567aaed3794aba3b9f4eae65466e8e326f6c399b36355935f
+bdcb9972f10b13494dc25097fcec5a6398f275c8c151558e74c5175f7baf
+4155e36b733f75cf9d5c5979b0764f14d8306e06ba24bf791141e404c69f
+3f8fccd91b9c58c2c671aae7d4f9e5d6414e46ed633a5f78aa5bf04e6522
+46a066ead9e582b181cc196ea2d3cfaa383b5d0e4cac9336e119c08cc6ac
+55cbfbae147c623b400453bbf447e96de036fc025624384359eed7c7d5f7
+858dc0521377cf647a157fc3f188de5eef094dba125510fde34c570d7be7
+6ab5df0a28bf45ddaadbea7eeedb936332dfe93081e0afd3fdd46bed08d6
+914b2efcfdc41662a33b90b03d76d34f48d30fc6bbbb600e90e6ac7243fd
+f026762a44b4d6e4ecbef48c9d7b696af29eee063e557d8fcf0f09e0136f
+45d17e608da36e59f2aecf8493f8d62536119b5f7e1554dfe3f6e8d7c9a2
+c6f557d18b4af92c9f6e050975c3b5c54f9b5f4e39d600b6fa2cd6de203a
+174028cbb2a201af126d1013c229bb82cfd013ed199d01e51ee2780fe896
+e01c63c655087a3e61a7f1029fa5e97ea1872f1b45f22282ddc317e17926
+7368cb52da9444f6055a3c653659cad2a1d8712bc2b1b32c1dc6906d957f
+b88524ee066156ed6bdeb8d832f9338f9912e29a250a8c4674e667c1c278
+b677aec9972be83cba3fb779893fcb8f81a323ac91474ba2a2334a07bb56
+28e905c518e634f6761a3289056f83d5dd7b3890987eee1c18fb2d379cc1
+905f1aeb3b3d2ad578f0d6c845d2d40c4bcee3f71c90e68e5417bb8cddd8
+78d83ba80ad8485f4067e5c3cabf28ab56cbb219c0aab8ffc6c7e192bec8
+cbca1459ae4450afcc81b9548f40ce2622e5a7c281f74dcc02dad57efd92
+d072318ddf05bf42f1ea8163071e23949b0179cf7de64677ca99b23cb926
+b3e294194ec13397ea1dc9a5e1cdcd828156cd71f81b64167d4fb01e6002
+713bd8ac6f82b20cd3699c6ca4704dc5c65a2d66eb155b7af1c9bb464694
+16fb49c1c7e17a30a5f045271d7df3fff2f42c6b470701c381e3456a500c
+6bb3d0e47b4d91c5f34b49bb6272f1f8698b307d89eda3a1565dad1c0864
+627560cf922dcf5b34c67860352390b282f95394aa2cde0e97ce3ed39546
+a6af1c52bfcf81a29be82c47c99e8050e4889e4575b75f39e662f2db7420
+673797e2ed3d67cda7ae2c15d0a0a794d57d168ebe13214e89e0209ab2c0
+eb7784e9491aefa3c02d0df3ae5365a0fc4ae023cab528162c7a1b173664
+9dfaddaca8da5fa18b7d6489e4229e9e24d38a620464a744a5c60f6f9d33
+4b908706b738aed186698a8b278341fa4d65a0a88680ba484694921512f7
+de93337fc1c02bbe6e64af2dad07603279d873291d1f4d39c1dd6d89c90f
+65240f4808f6f1115ca55b88e242565e59f3bbf1f10ec7b88872e9ae61d4
+4cae185463edfaf7df63de4d2207d307afb61501892965170d2945846fcf
+5973a1d458607f50c15e06e5bec715e0c156259aaa6c735593e5564f65f4
+43b78cc7512ec35a56f126df9d30974a40872e4265e1ae5fd483cfcbbba2
+6dee426cdc4721f19c3fda86ed7ad4fa1120f63669befe7002b128ceafd8
+c63e8ac09943b6cbdfb3d2476a026c00a8ff81b1f651b97f310c82aba5f3
+88cc1db5afcff5996d5252a6a42fa4d972e41ee56088f78cb966f9051171
+c472c774879aecfff08bfd9cea40d7c298922ace64f28c14e0b81f4dcade
+81d71de3983d87d905192ef13cee71b2d3ff1a88aec671ec318917df98a3
+c9054e372d22a3cec82fcc217f47319a40900312f6e32b536b9e7a7fa083
+7ec65ccdb5fb0d41437117596cb39d9382262de6e65379d3a9709b2cfbab
+f5fc5d5b352425f06f88cd31012a2a4147b112f0c1c0accc808cd625e022
+8eef66661f70af96d3dcfecd402700e4f6522ac9a856da466d55c84f65be
+2810a1565163872d62eb81333a698ed7b68352cacca2d7ad38ab55c19e4f
+5582f75818302f5fdadf1dced09d94872f2d48fb636c8e38c7563c72c771
+a08c6b1f041f3532bdb39006c89a33c09be1e3e603622d891f98010bf1de
+5355f557a1e09448d486adef565705277b31b8bf2b86761e32631e3435b6
+88b79d566f1747ba456ddb43cd239fb47ff7b425eaa4c657c8eec26ee01a
+ed07cf916e77d53634c137aeea009c6b515b6342c54be2c7b95955b1a9da
+277a0abcda2346e88018c726f481f71d6011aa42f8852f2e5749518fe3b3
+ab668213fe1a05c10a1c53953d75312631d6bbba01d418199dfeff8cf548
+6109b099fe8e2f606165fe30f532c03567785d5362aa873c9d3eeceb20f1
+945d55f49b0ccac8496759fcc7292e46938943c262d78f3212d3f9d0f7b1
+03157f423d71b1ed54b2a603f4c269029918f238ec6828ffcec66009db9c
+9e59534eabb183f31d7ad4c57b1bdf0bd2ce5a421882bc10cc1bce6a970e
+2b586bb221567cca483989dd0b8dec424c1d1ff042dcb7834423cf244eda
+28d2d969b17440caeaf024a6119db010ce366821afa424d1b8299609c041
+48275ae6e5257a7acb3c766c747ce99cba2d703cf19b7cf301b634d8b613
+ddc4afe4633a4d77bff8e00cfb5e289ebbcac90a24307e7941ec1685cbae
+400cadd876fcef7f6557eee167d2035a05120293527700dc510b038a496b
+e1d5cbaef24ed39f74211a93aadf22214ed606a80582485afe358e3a46d0
+671148998a3b3be209467009b43400870359d4189a8ceb4d5866ab52d16d
+9ceb1eab71c07e6caa34b70e3096bf7604c22c40d5fbfeea616da3babd59
+dcdb97d883fc8742b8267a16a99b7953225f7144568d566e64542c92e538
+ac140c851e5d295528eb7cbb49909b1caf6409c9bcceb325468fa0b5f7cb
+2987382616b477ccfe4f4ac79e4a6f7165363543f04de5b6f6e1c2e910cd
+c3cdd6c4c92737198f892337dcb6647bd226c820ac99c65d8e7772bbb74f
+e65dcaa8a22c33bc168bf48e40a82700a3a7668c5a9a71e397acdfee7d55
+6c5c19467b7aa69c260b727407ac837bdb7d67dec055c1f45d8bac61048c
+45bc9fb3cefe7549eaa2992d2edc126ff7a05eae58613332a2bc1465b2bc
+0429162b907d65f793d236eddd8d35405866d71b25f62dc4a7e06d4dee82
+840accaabc0774f8a63e9c0f7fc980b3583e7a8b01c46590e3bc04eba565
+c2ea94f057d964a78a90ea9f52abfd70f84e44e434bd10a42e98c7940657
+24341f907e35d3cb257161e01c7084e3a0166d15ced65da7ba87dbb2ea33
+d39bd99afb93d3548358d08330e807f8552cecf63c84f805205491ba3a1a
+622e70c232fadf3bf2dcfd6f0539158d3306506f150b0518371912a25eb9
+6163d73e9eeed42edc84d688bc7f7708d9dca348fab4df62e5809bd09484
+2d0a31dbb7c4b41f94d946810c5ec10b69aabc2c91a59500b2e5d37f4755
+ddfb7ae4abf757f4c5bcf77c7f95e6a616646456fe8f18407080bcabbfa5
+7704287ad26222df91ab2613951e2d679472f8adf06ea2a20205ec199722
+99a78bac52114334470c5f5890c2f846b4c6042d73945127f2e3910eca1c
+4cd7a16efe4b4be38a15aaa710682c3836a8ca83fd384970139d8b46fb0a
+ebb002dd224199672ffa02250fbcfa4e649e335428fc71f50f45e498419e
+db0e970f46894a48f65580881c9c4250fcef65c9b28699408e18b26fe6db
+7f1cbdb767564e73cb5954c6d639ce33220c894f36e70f71c9f9aa3fe2ae
+0aa0e3f2e304ec5abc661675cde2e70519e4220ae26fbacbd01d5169eb84
+4750753e6ced53e3678fdcd08ab93e10067e9c64f38b40b76d99b6cd92bd
+f4155a1ea5cc824998b59aad06e09e5f15ebb2288d66ea71b296616734fe
+f2796f07ff0d8b047074a1111d68b99c2b70fc56e74a51b062f4998acc85
+b1943c9477e436e5cd7ab18dbc898d21bb93475a623bdda71d7b895ba2d4
+c10f4b90bf335126f4fd57d73afa50170f6b3c364922e551d40e35da75fa
+891762fa23401d39260f2e92c7807c746f13bb35cef9dbf2e76e66a72fef
+f095da482a4de8a420917065736cf4de904fb52e649a32255e2030a7b31b
+686353492f31c064a3c4b0448c4bfd44b8e15384fd809b8761ee26a7dfa1
+758d57ce4f0bc376eb2b3833534b15a83436ba553955acb5a7a66796ac5b
+92db5388bc53efa27508b08e82821e5cf669bce52bb860780f749b4f38ac
+df5ff12726bf3ec2743f01014cde96fe6b4c40a034e9eafca2a35ccc776c
+2669e6ad138070a40f48ed79136d7ff57e993e09b81c543fbadd350ff5b5
+f7a46f060f88e30fe2d8233832d18b6c323ee017ebc1df5c838321cdc8a8
+4cabcab20b60a1a3aa028f36ea6e87c850af8af7cd50aa6359038bfa8818
+821d02cee8f51dab8c05f7ae9797814d97f3db8ccdde45b21dbb15cee292
+faa534a5f317b357f4091f3da357325b8b9f5edb45865415973c143e5e5b
+aa483fbf2d06cdd4246675ec58b84c6ae65ca743117ff00f229243772561
+31a7f2ba26a9115afd96c18216cfdf41b7220ed0cb3fcc26c36380007b38
+2a02aeae428887dc8be5fdd630ac57ee3dc156c7b8b29e687f24442e35ce
+10ba4087295a641f7139c831f7ccda6cceb5dafe537cc1a97c5a337d3c48
+a6ae947f58a30dc08cc7b58dbbb4737ad52783c573fc1e9408f55495a80e
+7fda61f0b9c4f090158f1a416249ebba936c27befdef19d1bfb839eb7057
+6a010706d8b95657b2189c2ae04c11ef9e57fe09880273761fb4302c388b
+d608fa0c7f00f033c9c00f4e3d5ce2d903e0da52e69c7745ee9fa75e2ad9
+3dc6cb5ccfcd3782a699b807afc36ad1f62b05856d5dfd6f88831b90eb3d
+cd523582a49732e3fd7253126d39e8afb8458b5f7ad7f94a8dac13365f43
+3c857af4a42c0a08c4db9887c4957259ed22d13cfdf5995da957ea5a0f62
+0b0214fbfe08ab6d552dbf048d62cef6eff12f153511eca7833e0e3e95f8
+5e6ac0f95438ac4c126e1f1ecf336ed31cca7eb216d279877123fd9fcd8f
+b5e52b587cffc4428456ddca816819a8a4a211d8f1629e5d42ba4c5c356e
+580c8a22c61d987552faa97893816da73d423686e4ebd44375c257f03131
+8865a20f22115e72bf1eb9f93aaa169c140a33a06c35bd4526a38be79cf4
+0ad1efa10411e8f3300a8a8b97ab140ee6734e1bee6c8ee443d698d34159
+97649c6f10f20acd80236422e215e146d744a262da3fc88dc0d86ff66512
+f49d3f957d3c5cffeb424823509f33f155057a4c6f37b52f4667767ba94f
+6b8b62856b553f307e5d230c44cbfdc9a97a45b139ffb2f2565eb0e22026
+972fad0fb7b9576fb6f368b61979943a398773600e7ee1dfefbf26d45d40
+bda66ebb96a56ee9cae0b2420c5dd83e24dba9ff885bb844bf3d2bf93b07
+325dff60c0cb5fdcca0ac8fb5a2e119d5af26e53ab8e3b428481c2871dda
+26ef0b621cd8572b3c664bc7aac01a1d05b98f791a7080d294be81099bda
+7982432f3dff4775c44d23f4f1b2e0162b61a8b2cb5ee8564bf98e2ed403
+2219085fe6194c19dac98a421826caed7f1ab1477ab32750601021728389
+4235d7dbfc1153d5ecc48aa7293f19592b4d7e95fe55151889bcd1d7fa7d
+c2370d2dfe11d7e4ea34b5c7a8e73bd3a348fd389ef45b6167fb90ba44c2
+3e912f9a4f2fc0427ed070592f7110183bfdb2c400393ba7569058227926
+351f07fed4f33633ba03a72aa2dc6b598e49b96021dd868dad0f352e5722
+fb714f667c15c68d49c03d822d82677edfe86fe9668e537da284068c9b0a
+ed83074c92a5b939296d505b837e6a9ddab1aeab7455a08a114c2222b339
+284674b74bf4ca9ee0c020bf2a148b439c71c6be51a94cb64fbe4a7eb295
+5a455047cf5cb348b062ed4f6471cbc3e9add9be9b96879ac7bc71bce02f
+d02f17c6063985a5e8983d205aa1489da13c408990aba1c54f2f501aa172
+f530480d789c848118c0a74ef98d5f607a067baff6030d887ac6a6497f9a
+0b38f9705f328aad4bfbb634f739386177b07f22d5771282444e5ee17335
+b4d0ec86117c697e79a5f4f65fdc08e4904daedab20067eae2448fd43018
+49e456d085f392dd13167adf75ccfdb723e2904a9c0c976d6b84ddef9d92
+b0e15fb246c3ecc2d0bf314cfb957757b3a3e8e5801f520644e4601d291d
+a0f7507c06f3b9bb36fc1c70eaa444e14e56c0cff06c7f853df36da9d8b6
+af2544b853dfff535a7e5c6fc145250cdda229956019659d0d253a19a7b5
+1a4e538bdc01f74d77049949c2c97c7ec6392c2e61ccc0992b66daf1ab08
+551063e53180d2a67de496716ccbaa45462d9f91b66a22545962ddab1205
+11ff08627131b95e5deeb8b4dd9643e7b2af65c0fdce11f5f1e8dd468da1
+8d41c8c4f00ea73836f4f70ec50fc3ec6d358c0658a4261c6d15a582a2c7
+c994e7882e661855b352014576858a265ffbc425160669ce159d07edac04
+d060b44e5800a7aae8e339c29b929aa81d2f515c46229d2080d5917ab20a
+b6b34fdca8e4af64ed660a3173786fb1a1d005d575c2a5187d3f7cfdc94c
+cc44a38c5cd523e9da726d8efa6da7b6131dff3435fee838b2c7d6b97934
+295f06202d307ff78d906699cb9c5bbb10d1d4dea5fda5bfb094e7046070
+83b646d37f5da1fc7ad21b813f44d8c1afeab66655aaa19703bea2e77df3
+bf350e17c74b3447a452235919452b5175570a006c7680ac05e8950a62e1
+1d7e3aca35a397d1e19630d094a86807593c97f4c484e4e06bcff708b6dc
+a972e3a0009e1cac0ea4141530f5c1b8aef5e1b933f37fddbc4be22b74fe
+346d1a3f5fec0818f8e61765568a2ac04713e828f98c449d9a1cce52d10d
+61dd8bfd084c8d099a75d89dea64d5a7cc68bd5b0593d97953dada976383
+f5015915618aec56d71d1dcd55b89736395c609b315a3f1e1255432fdbd3
+7f38cc43c354fb4b7c44f1a7318b0b7e99c3c08c33b953727b6a63280517
+83a0a33e3cd9e498346a3ca6a77b517096edd52ae443b87643a646c3a7bb
+97f742888d33f9b3127e61942f4103c1dbdcd8eac8f9e259773066736ca6
+53ce57e8822651261d847c131321bb9d6626a1ac50d047c0ba47b411df2a
+995545bd68ec0287cc9b31d5ddca8755ebeb10accb3903ab0fd5788e9842
+20443b8459e7c078da4289f1350905881ad6dfdec47302b0acb0d4af8cae
+d02b4b70df3cf8fec118f0fc2d3dde3e494cd160e676e300bc464bd4400d
+b50ee43b314e0517037bf971acd7cd327cb2134893b8a0410e68ddc518f5
+dec966c7884cf5fdfe74723177f20dedc039d879056caab4bf045062d390
+4f615c5cfe109ac7a35599c94024b41019b9afd404a80acaa4837929f5c9
+317680a13d157a03b59a5588df79d2e113f5f51021d6f6f90e8bbba2c252
+fd10651be80bafd59c53a3367ba3c28db6eb9dabf1ea99f47b503f627e15
+dcf3fd645fc52c5d5d0f2f07db4c25c0d1e1c00146e1c4d973e613ccdbd3
+f9450cc0f5343d79f05e9492e86a1bb889adf40503bd7f3e754343685918
+4a5b20bd8a172f350d846b7570803990adaa48d4b9155a2b4c4bfbef1e1a
+065c08e03928559735bdd442ff1e83e1fa20a5da57d8bdb2ff5427c034cf
+0128af111e6e73099e046e0c240e80a73d7be72b87834e45898d475521ca
+3306707631f5c6136199f354632d1a085f12a1c7c473868b62e534d15f54
+84323e63d0574196a19ef175214eb35a90873efcfb92d6cf68761d45e37e
+aa61e1a1979a82009507ca193e44b36a806486665cedbcf387053aceab97
+9bd35d30978fc7659abbe844f4ecab3303318ece80777a5fa5a9dd91b3d0
+6804c4b4e9b4efcf07eb89866d0dd8ca390cfd1598651417114d78776b1a
+1d36b4ba17746d6be7fc123d473ef1efed1c3bc1d555f914536869fd5b0c
+35f9c83f65b0e6bf7a627b9202d787d72c600ddb6bcce613d88492e13ca0
+aaab196e8a49928c62cea4ffe2d0208eda334acf47f20bd793124d2c5546
+c03f4a364369a76a0425262f9d9118af54e37d32e33ab25dd533a49df5fb
+f1baf4ceac2d9d378cdcd13b00fda432d9042f623da41afb80699b5538a2
+5403b0b3eabec9e8efcf42fef3ea9f91766902cd206b0787c187d5370b60
+ad6dcd002de2de8dcdc0b4719a797c5e26baa67665016da0d967fa1346f9
+588aeda174ca001b31213617fe19ea218ec2359779d979e2663166489c06
+993230b0d07973a117c4e3f4a4c93cf8428248dd5389414d679c69644142
+67c7fea17e35b0cee456667a9b1875c81b2302bddea2818d6019fc1622a8
+2051f60584abc904cd918676305dc03ffbcc64fddac8d8aa9ce2ea00d6c9
+7bc63c8a617dedfc0e40775649438e9f61afd1795e3b20560b01be5e0983
+f136cf48ab206954e41dee0d9ddd953dfd01caeb569151d6bc0dfef29d70
+fae3e198e7edd8922c0e0bcb8bccf1c016142c1a8b337afa7a05a9d7534b
+184bf3bf827f371e9bd19a71244eca1ba73d484cd2fad54db2f0eefbd54b
+536ebcb5094e6bc2f5b2aae41f05b4b311115876ed42c34f8e643b53372e
+3f6350db8a38445822ea9a33e27fb0cc42cedcd1fe2fdf723fc47c996ee3
+56c402112f24d0af899b2d00bea1cfd427998bd22b2a09046d6737814448
+acfb10d387547d7009fb384af0562c85694c071584236d0f1f3d3fcd0cfb
+38b77c81889061e668ba7ab37aa60f58a3967de26f939b79cbf10a9dcc42
+852561d8d6754f1b660d216aab1e133fbaa321c56e2584be5c9bae20ccf0
+0e8dbe6d9c2fcebebad945c3c04101d2387351f132628786f6d9d4cab834
+19288d31f9bc600d966412e6aa457ce6cad26a4c0671097b98c2384c81dd
+8b9a3222d4f4bbda7017895c3edc26662779aee740d9d7e24185fb821970
+b0a3a94041a69e4805ec88ee1ee521981536f2844fb8f5ef645f67d42ce5
+148e2dde43ad5aef200edb3a2c7866c98458a92666e5f9e070178bcc39f6
+5a893102a10564af4e8caaa5075d2f8cd7fab0401c03af299ea3515cc930
+66744eb5af7cf0ed06675bf049a6e3c211a89e16de5bf0445a7cca6ee8eb
+0347454950485d884606651e5887fe8b24323e2aa16de22fc1fc8c4f06a8
+2a1fde5758976024068197e1f4506e4d3d8a16d40461a4586338b374a592
+dc60334402f76388ad6a457dc3f54e6169cf7ae3959676e966a456096210
+55ec3af80e182633300a4418e34a66ddfa6b569e5a13c9115b5fd3ec1ceb
+e50fba247f60803aa83976f00117536342dc3d9890c49b2ac701d370e43a
+955118967827760f7091469c5406f08f18d7e3548148cf0e312b1dc71df6
+7a5e7a1656cf2f47f3aff3dd50ffc2fcdab7177285b29c17ca43019f62ac
+6fba52d1493ed7c427526470acc8389bae8277594958908f517b2863b832
+92eb5ab3f57fffb08393ca610fb1fe905d88a0a16ac395e2a2a6dd033d6a
+0d68992f830b2e1b95fe357bf672716e88ffb92ffc3d62945d1ead22bc68
+c51ee0e10a43011db94c44685a5c4576f6ef44cbfb45f2a4bf110a01657d
+b51fd499767e78058199b31dfd60813f1a344f86289f9378231d5b151c92
+385e3650b4feb1dc91018eab8474cbf69fdc1496a4d078d2c351c8196451
+247a9dcf8117e5b637371d8e22e248c64d999015c3fd2311e9950b8ee092
+2fbdd3d7bff766bfe9e7ce0be12f318ff2a7b5a9c6d00a54401609304ed2
+c55f5c1eac3d4b38355bbd85d66d61636fa6e30c2e82829376bec979a6fe
+ee040e452359768ecf90cc539a546f17ae906c76f14f86ff697797322b05
+1eb311a759fe260c1eee5dacf383816aaf1294cffa7bf87a4d9bc595ee8f
+2c2f86feee11ad959d86f22fdaf4cec098942a57e57813a0fa99239e994f
+ff353c1e781d666b8928cfc648fcf0869fc68468bdbda7d280dfab8b0b3a
+4ca35b074b686de8d372c61fb32305169a1a9912f6541da16cd6316a6ea4
+51524757be5cf6e820011be3859fb8b8578c100ff029680e05f0e0bf11d3
+3fe19460c85ea5e4c0ef28e29407c8ae6be01cfa0d5022bf9fb01416fff7
+22a784dfc8fce330ec95737a854471d334fdc58fab42867a7b62836a8b56
+466e9a6c1247d46ebaffb905cd4321970f59fb8d6ff65fddd34bf913ad32
+2e68455c5ff2d23c1a5eae687f259bc982b6a384d35440f7c693cf50b9ec
+ac0b5578caee87588b562eb6b7f42034c9f2e545ec866316552354eb3728
+c7d26527ed75174eaf635e048b08dc5d23e88981070ad5641a652f234495
+6e9cf4c16e652a99f4a644d1787d6d36537489da4d74e61b2fc4dfdf1d1d
+9d58f9c26c5eb63200526afd168ac57d5611ade4d4a382fc28bb60f9e7d6
+26a6c67afbccd1183c5e3cf2ef210d0bf5cfa7bb10fa3887bdd4cd96eeea
+a8f9219aa2f10abc0a960c3b57c0ec0313ae10ccff1f522124cfc8d2d49b
+fbb0c193eaffc5b48fb3ff30b21cb76f0a4c0f1377c9223145bb0468a5d7
+1b9bc25873ea12e1c60334571c67385c00d0b570d3ffc6c7ff0de62c183c
+76aeeb12dffee1459e0fc818c621b8d12fa1357e2b55d48935d70bf140b4
+cffe8813defd479350b20dc2eb1d3cbb1a2d3dc6ee975d58c89d61fc50e6
+a0197da9a586b72255023de47dabefb11e8aa02414c2ff6258a281219b9d
+ddfe41ba7d7977d0d6f18224fe22f7d4e9355fdb35bf7ed3418f4f68d093
+ac48f7d8fe4194feb6c80b9dc1f74e023c604dea27089f98c3973ff9f4ad
+7bf7bae601db89b08d5d8139b95edcf6c885ffa8b3e4b0477e7040225733
+826bacfd1ec4a0dd72dc41734856ab9fb700df83ca2ce812913bd142d84c
+5c83c0b2583768198af9e885f2ba74877a414233207234aa5f18840557ca
+11682aabde89935338877c6d404bde4153c9827eb16d66c1d73a8143c8a2
+d3604ff72ce579faa3c5224bac48ea83ba8484299472007de96466b5b29a
+cc7c03b05dcaa38a48bff9f214de43146ae4e04fa705421917f99bc54533
+f0ebc01849e396216b9f0794e6f6c6b61b52ef1b1950c0fb609895c3c55f
+f574163fc8b6b09e66abaed1810e698ff37cc1f926b2cda3b48c7d77790e
+bd2d514b6f385d397f713ec3ad3954ea9c8461586031d369e8b99e53408a
+79d64c34eb5a56de8a67de91837960e98a66fc04dfa0ebde21db003234bb
+78665b039d0a469a0221bd541af7149a2a659c300132c14581ef766fffbe
+cba8b58a5eb3f95446def49af863a8113d17b2e7e6ecdeafc3834d4df900
+e3475596e86fbb4e2974c090db4ad61a737d611d92b4535ac291c56ad8b1
+c031d2f9b505bb77517b737d70ab3723db52ae2accd5dd2f617423ed3cc3
+9ca882ef41757bf7151806a9b8b0f312808863e3673fb54de939b35cdeca
+7fbc4dc3bdf5a5f47d35e345916c39366c8b4f439ce1c6f1835c320bd1e6
+7375b03b5de18c93256f251761a4c8cec01019c068e34447bcc503b9571f
+e8000627a6b3dad5854cbc0a2d69e5a8f46bc78f6a7b1422334ec7a98abe
+fe9b83e01dcf3c6c9273b346f3240ea225ae4a4083cc7b0ea141a0773fde
+940768358eb4b13d82aa304a1386d450c1c0c6a7d5a8fd2bd313f78f8524
+8b5196241e31e5595f3bc01f37700a2dd3d4a0ee2dd01a36569cd507130e
+8f5b1e96cb560bb7da15560ccadf3b2c9804a11d9e8055c9ec70e48c1d21
+3eb756a1376f2edcb7189d78cd3d6ca5865537eec31c17d801605efd860b
+0b629472690588d0257502c6f7a75b9a1c1b397781329832cf3ec43c09f1
+559cd562c48fa9500295cd3b0a790dd3fcd4684a7c7ac49ac9bfff36b39a
+9fb148bc28d37907433943cbbf0cbdab46d3ea86dc8f81c859c52d15302b
+94a9b51c199b7104deec9d769c2634cecf8b700ce9c04152cc59c9326bda
+cbec4312deed92dd087a1c4840868d9f97cac046581f762f75e8d24d6445
+370a3f1e0ae74a6478d9dac37e7fa5bebec0a1e081af89c1bbf7f51e3e2e
+22c8c405e8671ba85f1bf0df79a465dac7ec07f731e00632e017d190a99d
+83e27e5c2e63d7dabba23b2e88334c63721ac5a4cbc5d45f4c177259f34c
+2eade01fa008af65ebc601d8dd16436d86aa94c99f3cc0a2f87134e73bf2
+2f108b825a8963b49c6c685474afe4a542c8641dc0375d7efe9ac1168d97
+00459be52d0da399023e141969f25c0dac4668534b6647ec85454be945e8
+26b26de6e3c4584b97a38e2b40a0d23481bca78084fe80e00a71a790bf31
+df468a435ecc88e60a57860bbca3d65930186e9917cbd209c230e8f8255a
+7abc7d3f043ae4d7ad63d9980bedf062b7d5c298c40225b6d03f29a0339e
+0fca02138e526f06b9ef47f5e7a8068a846cfde2bfdebd24f5a73a66c079
+18662aec80b43246284fa4e2ee0d9aab172b1e59a6cc46b801149d8c0df6
+dec9a55d8e1b0efd9d302ff618075944cccb6831d336b11617107b0530d0
+9885e5ca11a5f1fcc8d69d603da16bea51116d42cab1aa1e4d7b9b4d7999
+3f2bfe53eac904feb70b2d330a89780eac10d12cc0c35b8399f218ac2976
+e57a26bad20ce2fa2ae2363d3fd2a8a971747556f2959da74a8963c20b50
+4711ae1cb0d0c02457ff2e9bf696b159af031dd5155f21c0f5549b0471a3
+c5dc8918b675cebcb23e29322b959abc05283a702e878de8ef25ea760f3c
+5c7b7b49d398283de2ed837fd59f7c22d62c58fe4448b1049fdebfc8787e
+67d7dafe9774979bb3802254da59bcc0219f98c219f84d995ca768b8b5d9
+d4a32525dfece003675ee4bd5d8dffc11025af2b468f9207b5b2b42349b9
+8232bac0759758c1f4a283405815bd7145c93fa08f3ed2826655053a3c25
+59073d8acd199dea2c5ba5f616a2e48548b4370ec73493ba07e197165dca
+774438b0766867819c1154d1959fe6e01e6312e0ab91fc2e2bd240fc8652
+a2d456a1de7f34ef372a53794d4c4e050bf3ca5b7bd2f1b8de93b4c80024
+85cb219ad2d029739fd3c81cc6e78edf387235761a57143eede5cc887f28
+2fecd261f6a25d0a7e154ecdf5dc38e426811be86aaa458577e5e0c5f0f7
+5aafa9c41e5d1dc9d91ecd79b514f8cdf7a5f1a189470d35fdf4f9b87888
+79ccbd91b427822ed658389e981e0ee5f7fb87692a3e3e931df8a1d1573e
+3b0166204240b7080089a09ef7487c9aee2d665f5a82f94c877fb5b0dc53
+1cebf1e71c6592cea2401e4b5122e5091df03d203df979b9a6efba12e2f6
+b422fdf15d49ac0914d372d21e871de65cbecd105fd4a3e4714b9cca5c68
+03fa39dbb015ea8a88be7913502e562e5b170b87bfc8572dc9df49ad6369
+4311ef1334444bdf0b4ca3245271c1f7a4d7faf1703e3aa0e1ea8d5c6e82
+1b28707ee0c9b4f22f23796fe87356c58ae2cadc191f4c58e1fb58da03b4
+5a25ac95dbae13a293474217bdb214742b9d9d6af35f70fed2891942eace
+3e625e55ffb820543fbb250a062d3d395bc0f219ecfe0d76686ac148bc41
+476a887bc494ddbd396be200fd3e03cfa12ec9af6b934a283c42aa05589a
+a6b4a8d16946bb51f50419cabeceaec5aef9085c9989289e9b46bafb6fb2
+782d84de2b068f91a9744aab237ceb1ba513e57e4c307108e993c972a3e0
+a898d5a8d27833155031fdb98863c3be7fef3004cbaa5cb60a1f2e3eb4d7
+290ff5fafa088b1ceccb6cf51a58daad998f08396cdfd68f5abc9c1ccb8f
+6514107773c69c26873e889d1f79d10e866910e4684186fcd71c965adf62
+39ba3418b313a27ad632300969b6f284519366ed85e7cd968d64823f8c59
+b5911a72d0a20eb72b603a61e36f52f256ffcdf706b4560b4dfa5d918fbc
+530d83a4b3c01bdd3cb4572e24242d141bf9e77536693a0407d002e09cda
+5b195bf1ccf430ae9824c07928a050d0b460f2704be8f9e647a4884c4567
+0a81eacf7cc038643eb0ff18a376ff6f32b6fe4f197273327fbbdec6443a
+299cad4b26f7778a99f65a11bde047153e764039edb251936aa43dee50dd
+fdf8856519056aafc4c5ae6f2051af0579a9acd41d00775d7dbe70022cc2
+63dca5e0a25b9c7c4f5c418587666b2fe24816b1e0ec92f9074f1403bb83
+afc3f1d52ca79c387bdef864366e34c90be52f7aa09935373a07e4e02622
+4e76f9ec3cb9e7ede50defda48248d61f3cec880a3b8843306375d9711e5
+8645f3625bdb8e87052da67f9794ef4af8db0bcfe00677c3a26907dc651b
+c838c40ec39e2b5a5dc0dbd345944a6c32226089d63c52490fa10b215ae7
+03cfb663eb8a47793b84ce7364da1c4e7fce32dfef09490121222774915b
+a59c78c2275f829d15cf4d8686b095c38c731b83d48738c25f40b8add487
+c350a2ebe846c3916ae384cb1050f9f5dfe09fcbd9129c6270fd86d55a45
+9618fdfa4f907e6b4746196bb717865ab378414029017551161a52e9d24b
+e4f7eed553a927933d4abc8f25df607779a717909cb4d810de8f57625819
+00e224e4b91598149ba471cf8068abe8744356b261600bfcc57fb8be4503
+6cf6571d9b2a95304933bd4f17215f8ef53f8e081af61fa7f9583c34eb56
+55cb0ecb82246959f09091f36989ebdd646bedca614b9a61ab7696b3ff18
+1058a150fa6ec1be2ebc7f64357a3ff2a2b0491d2f4e0b970de5b7788b46
+7ca678039b5ef55c88a384578d427fd2cb16c87b0bf0a3d37ce8ed43e0f0
+49af2436344d5f47c948c632c94a2875092825616c64c5d262fe5b24916f
+fee982a69a6ccf888bd01d62ea591eec51f4b7ddfaffbeea93fe08d736c2
+0129e345d06b10246a5f57151c198d407730713f32299638efbdc01367e2
+3eb59aad42a83ab41b432db462652e29813740f4680a5d4bd47b18328fae
+6bdf4200cfa4ce3773809b45e8887c9b2e4236989f6c48d64f5986f563d9
+a7538a8716082f81936aebd0461e6f4bd470436d8b7656f0fdf89108e6dd
+02abdef907731d458d690bc608ea9ced09eb1e6e64c0790c7a2378201ce9
+97ffe0317679ee1d4ee9f91157449323e53b4ada8096cd628b5861bf7945
+43a98f2fa2ab54ff0f25a13dad43daf9394329b95aa53ca32749fecb0b2b
+c035dd1ebd53ff9fb5ad8bce06cd89e5568091c1cc314cfb1d9821d7f9ac
+7c55f55e0a16e39a87d43148201b928f3c42b110fc056189def183745f3b
+637441de8bd4c3c7ef12f4258e306b2877adaec63441010750db4e6269a4
+c78a0ac01bb3603c386651fe814031cb5d8c1f149eeaff652a53e57bbd4c
+8c0ce36a84a319a53bc1e5fd3f1ed1ee72f4c1a9bf264b594062fcafb22c
+c1fde3f2e3d3c17dd3f7fe0e15ebd812d550227c06d01127385374a11438
+abd50048e17255fcd2bb85122a6fb9b7da9d5e9de8a747fae0da45a1fcef
+e92b9e70a5b2cac668d4d07527a5c1403267d823048be671f725cfc7474b
+44fc5aaa348420b2d7c23c6ca066666fd6f2208e329878d90cef1c2e77ed
+22d3bebb9d547810b189f08920a27e7107f208591a84d463ce2576c70c3d
+fe6643e4ea93f4e1daeb41d46f0e2f56fc10c69ad5034fc9859d31cf27a3
+a1ee256c93111f81c11acf1fc0ce20b90bac9aa327a5c85a7985b951519f
+d4b03c40be637162af41b2fda68f0d1e9b7602fe2659d3d75955c579ac51
+df6a552eb9581ac3f712f083f19b52a6c4f560f36c59ceeb0c996aaf1728
+a2aa45dcad79bd7b23ab388d5b0b64a2b95154b6259b730b0f4a72c8c7f7
+cc93c7d64d9d8810d1f63ff8abd4db89824e2d264fdee916c41e299211db
+1a53256e1db5cdd04862f034d9404b73183a99d3d13d642a663f129b6d16
+7095beb4eaefd03df2ff2f0b6b594c1ee90fdb203da89facee23f1ba3901
+fecc75fe1811bd701259343011262b6a0a9707aaa6316bc3c17f787bb80a
+c8da5aac942d90f80c5a3bb59e47ec767244aa95c63e50bf809998957936
+d3bf6abc24b0a397258f9eb4dc8f65692cb023d9091fb180c69498cd0c08
+bbebadc84a7e0016e8f8bea325d924eb0df82e75d2cc2ccbf039b1193436
+3d4332c5fbc5ec556be85ee4e707cc2753ccc43d2ed50558e51a104221c9
+323cdcb0199b7b83454de3fdc810d0f362c0299f5dd981b31d8e3dda284f
+ef9dc8f9c8de138d3065437a7fe8c30572ad06d62e8527ad37ae39aab0b2
+25f76a25f6c6505241ed73ba494cf923e919f688ddebf193e188f8c4c154
+f21631080763b4d091e8ad1d2fd6649e0cd9360e8d1a67a5b5fafc67547c
+a31c95a5ea8d4eb5d68b9f6d6532db9b545847359558542a2ae58c09f3bd
+2918efbe1699e9c8f2c2a11ea4d224c726d2acd4a8d8abaedc6588cf2ae5
+66528b94f55b823a2a1f7be19000f3e7579d094e047075df18c8c8687602
+95533b26eb3ed90635b129c17aca679c3e88b06998ce5a7a2544b700229f
+5a6a504bd3e45b276471959c8a3f81917a53428739b5ef9e3d463b3ba731
+8448e2a3e79520d2d245a2a72f31ff7070b6e4624e3a5e216bd103640c8d
+f387e49d732529c611f8b971073f17ebd2f6eb18f9b74a67e1997926df17
+8d4c9eded435b9682f1a279c81bb9f60dafe125845a2ff3b02979e5481c7
+8a45c479befb9fef3ce2ba9bc46c77b50b03e48da6d17b76f06f3ad11837
+1adc69e178c52b5fb4b261c9311874ed07dd6d5b3226a005fdd7a6d53848
+09e7063f036cdea41619122635e835d2d74cbb6aa9b38caa4d819c26e951
+15fe0dbab4198fc5838f2c91b7a87b07d734c6d4f4f83444c1e90aa9bfc9
+08a2bac4b3def9157afca5248f2da31ca87bd363ac25e9e77f741d4b2c6e
+02f04987a6f49d30e9038cefc41ba172dd675aed8b392164411144e5b738
+f3210b0e66b17a13cb9631c33d44484e792a7c082dd0a5382f34c5637653
+261b1eb6d2035b08b4d91fa9ab770caf40a103629511f7b43f2743d7e583
+433decfb19c21fd4fd0afcc22a4119e77c87bfe6fe50068b22479015be5a
+9f06beab4d37412e062a45e0cbcd7bb39fee747e96306f79fc4f2e8942df
+5d9da0e55aaccda547da19d30b8404fa121298b44c9cce198c708c69a8d6
+bf17591c5c50d3fc5be6961f7aba8f366dae957a1c3730da4a5b4f035a92
+74675ee3bbf0ca8ce9d8349f50cabb1c3ea4948abe6f9f143592f1ea9540
+4e6909a909168e3279a957ae1924245c356331a75e7008bee92beaa304ba
+40b7c3f48f74d9018b3247df50ebd7ce541da48eccb1b0be51a455c3c13c
+279d4d8676078c3ebe4308748d52c9b041d3e7244c745b1f2f742d010a9e
+60695f3ec4fdc1050ac082b905d6a57e8f407a3b472f731011a5798965b7
+b1a307e252fe02c8f79ceeddeb6e165f1a94d7fff18ddbdf79477f14e9e9
+3981abd200fe7771b29d1d2d120ee79d28b9543818527039ac74085eaff2
+41b56d08220c958b5d9c87c0c04a14d52afd475b542d391bc54ff33def8d
+9484aff6873beed32dda4b371112b523b6ce22b40d1b416b64c9370f1cdf
+2c548f4ccbe9e12e21c36cc3ea52da232dcfb65f66b22b5e2ec04852510d
+5e264ee939bb67aec4764b87062aeb7f680b40bcee04ad45c7519eb3b619
+9c9e0e332661463647f2fb7edf303efef84891cebcf0fac5f723a9d0476c
+3f8c092604c87fc69c7a90f4d64ae45a478ee8ba2df50fb93f55a3546123
+f0b0e2c1c40c98eaae9f0f26b8f80ffe6e6b94b7e27d2884d58b8a119662
+2df6be608c5569d7864bb756df2edd184b90812b44ed4a32d001c31383a4
+0aeee9743651f795084615c48e402dbc01c818d477eac0347795cb2792e9
+c11e8fd4a02e194eed1c919d4598fec003b6d9a8a0bc7d456047a1c05794
+53fc1d7cb2d158d466939a23d7a7b8abed7e2777ec7487973e73f2266d9c
+250ce30729e3c5223ad93b9ae8443b35711e446a3dc660123ed45ce1942a
+1a2ad0610467e081ce2c8b92a6c82f0b17b5d2429e99f1a6268072c6b5aa
+aa6eb6283a872c54d3694cd825eb2926e57dbbc7c1663075e687a144e4d6
+1c225781d80fcae1497b442342b4a3f1cd6bdb50e31791cc3928c30835fe
+f845b6be5e2d7e3f2f5f085aa3faeb45cad0d76bcbb1ed859a9cebb9f745
+7036f0bc3f195cb1a98c9c8648f6583cdbb23894bc719d68c2dbd8003b10
+d08c8caa40bce784d7bfb4eec9ea5359ac056e57b8b0f2ebcb1f4ce40c87
+fc7861180133e0cb6ce2fc4fe690756d327a2b5ae063e3021c0c0bd420d0
+56f0b941e6b36088a55ba11d0c35fd0132d5f48e5d9673572347171b4328
+d4807b972831c0d74cffa5638c145b89c989e6ec942148207d6db8225758
+5958034d9f9d4221c7c9f7013790dbd130f277e0bc88bb179dd09e270623
+79ed06f25eea8b7fb33c35861a0034776e3813d2e9e5c10e227cc569ab36
+cb2d9df2e7b7b44758f9dc4ffad7a24ac7e9f47aa850c221048c3cb35a37
+ce8ea75632ae65fe3212175146fecd6334ae3d3c5f492f067f795e1e8ff3
+86ba198cb74f0bb4dc0000da383bc4cc3f070de17721431988d69c8b1a5a
+fdccc83c22e16a87e01c6d3e79dc7afa3db0371b0866efb8b6f88900472a
+fef1c4a878243c52d4e02e82658979731c841c489a6b97e271c4c93800ec
+7d91f93eb9b9c659a554e1fce42a5ec65ac39190ef4b66deaf6fc0569a00
+0a9e1495f42f706fbea4d32eb7ef11a6489102596a65cf899c2f322f5679
+c6d123469192a9bf1a7f1f2c81c554adb97bd19adb746a4f81a4d5559e60
+ab94c483dbabf6ce2f28cdb412d50ff3fcfa3b3daaacc6a83cfed910ccb3
+b8d2c19590aff4d753034a6ce7f4156896a13808e0dfeac547e69d3c8866
+91728e4a35acd575b40d721e8fcc5385a2eb28d708101dc50811529528f5
+cb0c009ba7e3c88468e37768fb0d83895ab54db2dd5426562af9d8af304b
+f6eda54e9c92643df926f5c3578269750120302a37cb140a18ba56ba0110
+8d4acace8feae640a6c6958ef156b588adb0ea5f3b0f37bba12b7bcb221c
+811415387b024b7076fa4403a3ad6ebb5d9c26efebdb7ade7c60b444ab9f
+90ea493b658b7767ae2be649bdbb3fe85f460f1ed137c61bd95f7cd3d8b0
+15ce45138538930ab62aa0e54b4ce1a5ec5fec0a2b28b345b67089a4e4ae
+14d2e1f5a9c8848da688ca298f93860649ec3aafef3e820d86988c8e3e5a
+4d4bb937791827994aa3e81d0bb3ee115ec36d5fb9a392d09e79af514d11
+c7b3a03c9f9c13355ce79e119a19177ffdca34704d38118a8976d1ee5aa0
+2d14feb1414419f5e85244adc5c0a765a522eef36170064bb19fee3b5f7b
+441e4db967dae0bac2c48fc6a836e0ef5a69f073bee1699f55e9c757ebd6
+fd8b514e2b49d6333815b7dbd1e0694695fca3d21320a0c4b852d9706dad
+d8369a95fdd917328be93dd33818954dbd2c212d2ca81560ed5bc284eb04
+7a5f389e24e43f4fa8c97fecf46589fa7341076555cf55b1c21b28e0c1cb
+b00ab8b6f67472f27bc0d11148f407824b0159b5188d4bb7386fbdbf1c0f
+af34721b7bcb5c0fcb7c4010dcb6a1284e9d78839e3c2111a05d29ab7997
+073b590a81c6168020f1d48951bc7d8476d5ba593f4f23cac1f9bb0e091e
+84b4e99e5c584d1370dd12dee8df16af8bc6b7b23e2feabdb7f32779af8e
+2b5094a6e9b7a7225f24c43a8e5d2b977e1e19e633c26771e23017ed233d
+bb02c64f8cf03992c6484528d0c8464b46f24f9e8380f385d5d01b8893c6
+7fc103498983cf939432aa380ca576d09030cd52fd99bdc3be16c7204cdc
+3365bf76294a83a1fc14a236f5fe5321904e779b13232a76f8fe521f4255
+62678436359c2461bea5ab27209541f557ae2aa60009c9ca0a9fc7898c14
+306ce35a50017badefdecbbf94ee2905220706dc806409ef87db1d73eab0
+698ad2db72cdcdb293e7fb13c94d9fc87e74502e6927a212f0d7d2f2d194
+64f7a66ac07872e18cb1dde8f11835dcbc5c4ef039333fffc0fc1456daad
+e7dae3ec2ee0d3415b0cabb69fc5006f4d14a4ee1a5ca99ad4d5e629c0dd
+1e0f097b5b93de2dd001a8c418234c9c45e8c13d1ae04e9466dab8cf1ecb
+88a4e059c111a6468d2dabb90da79c7c79e94db28f6968b1a632f8c57d9e
+565ff91c6916026ffac0661856b9fb8de9c81661816221b1fc159cfef175
+1e7e403f5f2ce32529dd540792fc17a12a3dcd7c50d38eeaadbd10adbf5d
+8a82442aa900ce6150eb7a4639dd9fb6e385b2fd093493dccd9014b23eb1
+72e21aa89643a6cad1093343d85d81261972de0acb16a4c6b5f0be4c978b
+fa12d3caf0134f9ea49f6e9687c8f99a456745ea252f0ba9968c7f9586e3
+dd841aa92dc7705bdd682dae41518a09df0e209f321d7fa3417202f4ba76
+a984da3addbc58136885362f02f0a24ebc439b3dbbdacffd8498ebd29f88
+f016b1feabc10785438eac860b554525f3266097a675299aa0967bd3b7a0
+eeee3fc578d1be99d3533bd91571aed904bfc9da1a1451fdc5406e1cd614
+e0c7fbc733563cd6ce6cc31e9237ca153f1f0411114361d731636bcf9855
+5abf12848ad109371a42b63675a4130b81e97c2a2ee2bb5d8fae26401560
+01af0f55d9d5df8ff23c8aefe14f120000f14149a36e5c94cd9081dec277
+c2c34870d05011f99d48b0875a5ff542f067f7e9880109f586bcf2b50522
+a1f23ece44349e539e70f84e207dc9bec7cdf856a046f1a03226aa41f541
+719ad1af88ff211e57dd0c1275dd0b7b47440da089b98c6ee92a7d94700b
+83cebe19eaedd8a615f6587587ba8bba3ce3aa5e8eafb1fb0f486be3609b
+169efb178a4292f4c0378afe5d24eed1caab514ddc66c696d8e37f294a65
+79131ddf5488e9436609acd750c3db0a940c84fe022b22adc2676f62e91e
+8f891225f891fba537679b24547bbbf35f04915d20b11739f620d18b5b21
+6921d222f15044368569aa302980b9225bb839f494588481b94b0c724352
+b2df600a22b062561d86cb8f81514fbdaa4f8a043a0265f992fab71fc912
+4a45b8475e1ef3df6b6de35cf329777d45f08325e8505ec0d979f542807a
+e77e57e453525f23bc59a50740371efa98678aee6c425374aeb745b99ddb
+5d8d908fdb551fbc0db15832107bbecc4e11a1a8dec69358a574a2ed46cc
+31d564549eff23102d92bfdcbb2bb985f78f36033e34f59c0ebafa3bdd71
+338736464cefdba9139833995eda4207bfd4a9867d32e867fbeb7de60d13
+2803ef9347cb17bd91315484ef6570892297dd8b7d966103339535e28a00
+cb1eeca4a9775f60a9f5fc9bd8b06d78fe8e6318c31da2e847e3f9ca587c
+b01ae2ba0a2ebde308314413f4f230a758184ed60d4f71f6cec22a93a01b
+6c54e0449a3860fca8954a347b7588329a80974ecbecda1070fbc0556663
+75229f13dd995e99265df870bc8b8cc6347fadbc1a6af64599271a475b91
+23493d46bec41289beeb67eb97a8ded7a9c9730d37c65164cfbdc22e5ca5
+89d2e7954c7136ef4e084c43a6c7f361a3e96989239bddb9a593cc2a80ba
+16de9ee90e95cd39393c212ab22eecb677fd36d34deb46c4ad0d21bf7e6d
+7cbd0c8083842fcd87b18fea7cecf939987e99ba34c214e44dd84c176c9c
+c5a4cea76d380cb316bb4ef9de73d73b4afd4adb54451591def86621d138
+d5a0a29441502bf6c2ade671cec3cb5cab903a657eb2d70c943f976c110e
+46c5d9d29bc00a875f2738e5d22496a43e096e009c5d3cb724b4cabb3283
+8dbe527f83b18cb457e57b092c302ee557fd4f00db9c56e66c9fdf4ec9ff
+aab85f60d02ba79694faba476a199a0331c30a78a92e10417ba236e23364
+8174c826331dc1bab87c5f95027846130c6a2b4027930ebf9a97ba1b039d
+386fc51c302648e25980212f6a582cde2778c677a01fbfb3c5d1b8a374ad
+af6adbf7dc94075f25ed66d440b3922c5f255fb23fd8f6e21ea65b1d93bb
+225684b50f11310e242b087575973345b229ba62c1e2c35bdaec04d10148
+f5b2f3bcf7399bdfdf1f3f79119714aea697245bc647316ea157484ecb95
+1be367234fd02e8b1f091aac3d29bf282dff4011bc0cba8e55234d943db3
+017cc7a766720bbc29b2d097a956c0f1067177f012d42adcb473cde8d1ba
+35b4030757fa1d8211989df3bd22ce5d501c21ef8708fb3449df47d88650
+9ff7b59b76c0dbae443f336fee2d615d7eed1c284f14335bc8a26bf4621e
+10de9611fb2f1dbd52e4b7565d8c65b54ea36d508bcf0c578a49a2665227
+cde1f9768efe847f9d94f1bbb7db83701c2321985c7283d47b2e40b27a26
+8428aaefe75f6b2f8764a8494e5827573758cb9ca46fa93208836bccc8b5
+564a69f5ad882052af1c1417c3fa7f580569528682c77080f3688b65e7fc
+24d2a3aeb61574b4a3215927281544ddd7a6ee0a3e9388f8f631ce725172
+4df70726e5912ddccc8c652dd6c9608f8462303d867f589de0f2f71711b3
+5142ee6ef93b64d6326c4dd7dc83278e057100ee772082e6ba368ed91a55
+53ecfe2293a481e42f83bc8f9148c70eace91f7b7d9cb8a72415bdb3af66
+f68ea733a17abe9db0053bf148629132969589f38d30eabfa96a01fac726
+50b5a6ff3935670198a1ea33810a9b11e330eb8b451f24f93544263436f6
+69ab5a90a53b16cceeac36b1445574efa7e802de73522be725e68704822c
+b7d3912717333367895bbfbe06966a5cc653aab5e9b3596702086bf00100
+85b900711932a95acf15ca4dc45a754ea334e9eb84d6fc8e3fc4f897456b
+ed64bb93b593549ff0d5352275d8e417172a6664c5e0eced1019494a7ed4
+9ab0b965bec1a82e5873766bb38d7d856049cce2fca65aaf61e961b60634
+e2a69ef059754c9d8163d87f928c222772d070d83fec6fa5ac734af65e40
+bfde521f7d9cb1650fdf64754bff21ea3ff0af7611a93d525ec9b28c51af
+ecb04e7fc8323dd6c9b0d8539a34fc3cd8ceb7958e8ebbfed4313c77ed46
+9c199552a9ff70ba5423b03b6148d4eaae17b71c5b39dc436ac53d6ba8a7
+ad81aa8b02335a8b2b11e9f4fa913159a725b8ab60f52f1a2ea50eaf4d56
+656e615bf382cc68a690bf83dff24fe986570adc0290ed1a37c1c2ad469c
+e789e0ea0bb5ce01020100e729721af3b5badd33a2daa6c33eb8f9064f52
+92f715f820b4bbfdd56f76d42e7a1a068c1cbdce4640082f6e7d582d1939
+990ce6ee8d270015a2c461798b37dcb5798ee9f7512168b76d26c28be4a4
+9a1bf96c89d235f21a1db6a96e5da474d0b19b808d13d7a11bf39ea86474
+99c410ed9894a1adf33d41b6fc2e614d8087f4c84e437b136f3cb32db839
+3c49177a0675a0c9e7eecef448a97afdbe840fa01fc7e5f2e8fecedc1884
+84c312e8635cd79195475ddbfdd4d38d5a0246de2c7f21608f8d2c0da137
+1d302e941572e5792a3cf4e51a33228b93a814d03fd4fc223c314cf3714b
+b3a34bd4f7ed6348577feed9deb082c4049e57b5d3cdb7f26629e9f3ba36
+893e09e3c7463d02a22d7056be76b87763260e46e48bb832b7ee13f8dc05
+37ec8e81e9bdfead8c27ebdf1ad706933efd11131e12814f236ebb01be85
+b7f1b2d627413b324918d247604f56ec128909873fec3857028bef76a349
+4364c2a7002d104d486236c30b48e2b75d851c34ea50ba7ffeb4e1919089
+8ae21768c157c0cac628a2181a32796fbc1a7271d2473cd88e5395ddbdb1
+fc3aa8df0f3d588637f19a8b833afdeb5f655a8838eecd684e2315b72c75
+ceefbcef94344ace8d6adbe355008ec72fe7ceeab01363a895f4e73f8676
+39be0a0be67333848816b05b419221be8f9066c362c23fe85b7f392930bf
+e4c12b9526ff2fdec38f23a159ed61a0718e7115c24597d849fa76369153
+54a40c965d4d72ec94da61a03766ab39aab684e134fd1407a5b1b19bfeba
+52aa0da5d99cbe5c82dbaa663711e6deba180e1d4a39c320516a4350d296
+bc19bf1be054859a0889c7e9727a021f3176fe620fb0c837e4141fece531
+a950c03d319e3255703220b7185bd20fe5dba673f8129ab211efcf36ee39
+4c7e00eb0876624bc840fa86e58b2f584754cb6bfdfd76810e300741ebe4
+544e5ac17413adeb21c62f66ca4f075c32381796ba709782de34a675b717
+a2c7f6d88104cb924fde5df775b4f0b68e0e2e5c2f788bbdeaf06d8e1fc2
+105ccbbd5827c0b03fd6cd64f0d073f3192d5f94839644e5ec6c5185badc
+f04112a65f49a8c83174a9ae958e76a2f5af469e8b76c833782c5ffb8bd7
+b1bbbb3ea0cb7c9786c3be2ade5e7afa8c8f20892659a59bc421e28845a1
+08e34ee17864042ef587a6d67decdfb3f510eb40d2229585347a0035670f
+cc76c2837a4e4d68304fe113c539b35c1f0234b5079b8e32934546982978
+c5e4df955a454ea263c3ca5d7101f31a318d82a3f9fcb5a8afd7a6520966
+3b0fc9da400b26f285ef46d0e1eaf8acb1f1cb805e3986d04bc585073fc6
+4895e4dae1ccb749bb439cb32ea91176d5c39c3650d10afb9c9884d5fb90
+183424cee67ef2175d01d2478d67511ec9f54f88763c152697b06d948bed
+49240096eee3d06ab4575e8e8b2cb8263b5bcf4fa1608720f52b67530983
+3071879df52c3ec2871d20f398b5cac8f8a4d41d0f1d47584dd90dcdaea4
+a1cf160c4b3bf1aab890b5ceb6cb3488672aa68fbd938281dbc1d8bcfe92
+fbf514da5358443cb6e0147254e91b38ce6787b2bb0dedd2d38f5938737a
+977b5ea42892520c58f8fbb53c994b57382379e9490f0d6970b980e1bdf8
+cf9f4c3c5e0a18f66e86ee93ffe7fe546de50f41364bcb3721b637072571
+fa1779f1d672fad260c16d7f13cbdf3e4376e7ff56d2a710ac5ac35fcbdb
+ce2c9c17e523bbe6218617b13c1fa6679b308979ae7c61da6e68369324c6
+cbc7ddec364e5a86707266c0b459ee7b2c03fe584e529bffdce98c90a2f3
+d9305aa74d3ed8430dbf3a49fe2ecfd9c4bc9fefd22618fe9c8a973ad072
+ab6f713e4df02dcda7ac5359b2d652013e131b76b3ed6c75fd53ba58d862
+846264627f6b9e70d8800f6d9b32242b747a67bb2b45675840d34f852aa8
+062fa6b01e31ed24dae02f6cf788a17f7b9368175195db0072259cce0ffb
+2c1035c1d26e1777cca3d56a827c3242069e76d6dd69b653768614b9acff
+16567fea61508d51454bc02f6c60f755aef6afae3536bbfa1823f8e1a53c
+41124de983e51cec92aef4f99785d554488a51c20885346d1f761da79017
+940a0c557d93f1db6b3d00ffd61d08e96ff3afce5fedf545cc9f47a2b1bb
+26713431d6d1e47fd6bd6e3c668b0368241f0ebb5fa9c991df79890e52e8
+3a3675ee699b61baf869de91f67278f510061c6fe41de2d883f48cd0e068
+e2a652b244128d82e5cd52f35f210ddae3054691ed55a7d99088aae8fb04
+f525c2084ac09f5edf80a4efafe981f74c0de9d194320709b3464f3ff2c0
+f6aaea6d973d9c323f53de3d741f698fbf01036716bbd62957cb32cd81d3
+a2674560ffbc5bdc5c6e4f547e589ad0b1cfe14f5e17fed1c4a8abe4e67c
+cf8a49f32c4c6044f1431e1cc382e7758722a6d0df9ed23e51f8ad14d11d
+7b6428e27443715eba4e9c05d6f238378f9498aef0e7ee4fe6856622cc8e
+6ed141ee5f109e343cb6695c4be1e0f66601c27975983bf557c04acfc192
+27a1ad7e6c44c00529fc7edd7f886d24b7e029b9c395260088bbfb969721
+99a7b32796d27257de83a7402291c14fecdf7998c5c96b1edade0280f856
+8a8f5007852eed303969180b3329917973c2d32c080c9765b6bab0673bc7
+ecfdbbfbea980c26384339b7f1052591d91667d4fee413afc23de2d4b9da
+742f4269c6c939f5fc32a38040730a018155ad733f231e4d5b9d01c03a58
+eae7b5f590ccfaf25edc8552cfc8d95c60ebae1837d7a97ca137e9d4a4bd
+2cd34aefd68d64b3f4f62326ac429921d7fb3c235184fe0899690a0b775f
+1a566ec29d5830d323726526f7e7f5afdd71b77e07613ddc4fc63edf4905
+1aeb59e6337ac0a4b6dd872e776c9cd0ccb861305322d816732124f5978a
+86c186bf0a0f88e733ce38e4d7c1ba5378c5629b1efc97806059990ed42c
+5cd183bad7e94070e4058569da2e51831ffe0d080301aeab4350ba290318
+aec582c78d05dd92e5afb4424ea808629bc972e68f4ff2489c245593f075
+55ca6a2b25964794cf31cbd3ae5c229ab9b8c29806c01d116ebd0ff0f159
+ed2d3d7dfc73eab4910bff5b0b0b587cd9ea6e6fc45d63c09766224d8346
+1f0588140b258b1729f70bae7962189b1554483392988cf230af4077193e
+53330519394dd99ba1356d4730ab221dc6a66019bfae564893ddad7b177d
+add16add21d396cfa6c3dc818052e2f71149fd594a16de0c2ffdd366c99b
+486c55a6e991e4d22ccb15843f0c3363676af2f5b2d1b7ef66ccf2f12dc5
+0d63776bffb058d70a9c76dce96c754872d72c82a0c33f90d49c935402cd
+d26b6d743b1f43bed5d8b539424849c1495dae73044e885a7d0f307f1816
+df6244a6f2d97bfd4e200e93f69b08af39ea21e6e347a47ceebf803f73b9
+78adbfcf056789bb8e6e2563de87dd9a8c877157b934102dcedac54d487a
+1bb2694f0034093c48f10a17d32e2bdd0c723caf59addd1be373af8c9beb
+4415aa5af36310c31f24354a53c0b962573148bef91d994fe3f3d8450dd4
+d686725799f53c373a0a3e3c060c2e1a3e8005049f26d716e1f381b9f831
+25e4683264a07e2d8938f605978e2513dd2050b3d8a1012797cba8961632
+bed260916338a812ae751c7b657e086a0c7ddcd3bfddff3e48b847519257
+36d1310c4910fc114387f3ed7fe163f91895ebf55fcb425cef5729d99bd8
+f2c072e36c310523e75cd8e5de49c031c42634109d56e91a46c8c8e89fd9
+2012a00c33d0dec52597b5c6933291a7bdc5ceda95dcda5600f9ae1c8250
+54e7ee1067458ccb66610704c58e4a4fc0cb5fc933d0322a716b2cd430a3
+ad48dab3d4cbe9d23f2d092368cfc4e1f5495c133a92942ec62118d45c17
+723646e69407b4a89dcdfd2ab3ffc099a21d9d29741d68270629aa3a414f
+e58658dc9170c247b6e23f35c4bc5ff83009f462f2eef4dbac5fd158a658
+57f9b6dc1f5192dfb169dcb65621cab2f1b07bd22f4155a8e9e2b6388d43
+0fde5ec1c834d22ea035c52e1e34482eadc36b4cae902aae89a7284e62b3
+c84b608d6bd05f75bc31310b2dd3b2c08a00e0737f104f03a41989d5f6b9
+a2c38b22f1d1803ee5d7a4d8de44e4abd496a1de0c0e12c4bc96d0122846
+3f0ea9ce9509fee987139f3dd3f9d0df4313f555be85433718f6d05f197c
+41a9d9c7a8b0d274019682d49f58dd5f66b12a6520d9f226d1df1f1b65cd
+fa261f980ca25a92645b86b64606293f8bfde364c47d2af2c709bbe77a70
+a5712f2cc26f3d66f5be2c307a48e6f887f681d30121e32bbd87271b5dc4
+615d28c309f15ad263fb37424e56dda6e17b998b45be6c7fc6c28e3394a8
+764c9eb2df5c06626593b5c665d550d4600172791cd208ae9f37bc082b0b
+242b0a504b751b18f4d7495172b697ee217834a8a4fb7cc16d6f9e8bb400
+be8aeb0850960283dce725249fcc4de97d9886745ab6066c3e2f64dd8ab7
+9aa11667f11188d7965dc11eb760b772e282dbf13249f31986ac6898febf
+e23e3e8b8d2c33e00ea6fc493850ecb2e6d831d1efca3c2ec8ee2e394599
+091ed58bede97d7a43b6f739eb0f845eac1df6b1ebfe876009cc5d804b15
+ed4b56761b3ce1af59c07b49dc798a44532297ad73d5101ed47f36a3678f
+818297cc27f6aaa2aaccc9aa9b6f5459911d8c56cf499e390ae607f37904
+50b2b9c9be0f006eda0c715b5ca0481734cfb0597478e7602b0d2c1e4f78
+f03c68c17c70e4b42d7d2d3c95cf40f73488b3718e2cb05a549944d86944
+d78724e266c3319af89ae430e777e95f0d792b1c654306e421f3d63a26b2
+1e74b6e8b21b2e2b9dc596d013cda16d08e65e8f24a84b12b2badc653e6e
+1110de2e709c1c1bed13707b70a421b384f20ca7a9a9d20324dd383f28b2
+d3c7a9c53f5d4c6b7c378d26df11cf55238be1b24fa70dcc178dad3d3567
+0fe4919085eb1cd905971d76a368fdfcf9d2f0a23739851a3a6d2e02d65d
+54dee69ed5d81315d3ea5e356f94ef256dd267fd1e1a9edc9cd63e743f29
+9bcc4a4506233b8dd7652ca067f741603f93250c087d368f9e9cc4cc1a6d
+ed567487c05baa992b0056a77f630a72008e394615a9db24fe56a956650e
+c9de90a6c2259189440247970541ca198748928215c0e132a81aa13208d8
+63c1fe817f70ca573b54577d10b73100af8ea088208a44fb92aca314ae58
+79706180788c17bb1d0b81b6b95a1c4e0f9ea66f9b39bfe12444a6446691
+a7bdb03e0f03d9f07a10a7598f2166f108529f34cd90e601ffed3479abcf
+cbde8f051c348e48c61d95b00c59ea1287423f05666c3d36288844067e83
+e14f6b5210842c742b89f13acd126b9fc50abe2ca7d7ed513d43b6ac7f41
+eeda416bfffcc5c844ab2d23d4dc09b2d510504ce98d02e72020d9e669dd
+aa344c63a1b75632f912a1c0da3885da4af7e243e4a4c6493d6595bb6d56
+b0359106957259e59e336baaf35bd1cec5cde735272ebccae8d4904aebd2
+b32610c6fea2b69941d6542ecb44d71092a3cf067708a3d087ae99ff2967
+1ab7dd8758759b971a08ae1bad78270d2fbee37aa2dcb119d72f6c7b0c85
+09018a70d0b0be2c6830ef8e0b24b1ce1141ef873a4d7dcc501f808bfd94
+e4dc0f2915aa023076bcc8006490a43685ea25aafc187302ebde7fe1965a
+04a5a398985d29f08e085127b56b057334d88eb638a4dde64afd204974c3
+939536b1b66a54b4db81151853915718f70813f096cc1b0ea25e363b4926
+4c2ad17158a4489f91453fbedbde15d7b74d7f98e81df23251785d58295b
+a297f295aa6248a912cdd4f1111e6b628eecbb5139709e76ea4ab743cec8
+26621d08e6bc64691cc90b3c3c1778931a28d3d5b1e20e96c643316613fc
+487c9b604c43463fa4533bca1236286e6f5a6eeb2f1d9c34bdde4595495a
+365f88055d9268541cf1654acf478d384a5496a8772ea1402751a093582a
+6625a0a44816b5fdbe166835d598644296249b92cc90aa3fd6445c9a19bf
+27f59cb0616c7306070f33c7df4e1de64ac8c5bb2ffac1ef2b1b30e5a027
+5e6004cf64bbe2c6710edcfc3aa4add60106334708862ffa6652825bc848
+42736e47ae6917180365c75b27505eed3c6108e9898a780e20c3f606a860
+229ac46d0471aca0187d6d539a1b8820f620f72b41ad1d3bf3834bf48ca2
+afea8bf535af74c4562deadcb63d2f5c7585722b77c989342d190ff926c8
+a5263b4f25286f99cf6fc62ee6e2ad61c82b29d82468ac10fd27764278e5
+558ce8b41ba111cb2f040914451a480c93084237cac8f66bb7c6689f340b
+8abf0150e06d5b1177278a4c08742fe22f42c28680f190900344adfa486d
+59718c25d37275bce4df981aac35d2c7e85c72a0188b8953cfa516fd545a
+ee0bf4b8ba301cfde2144241fbdf3d204e3d2823301572e23f204c97305a
+82401660e12926ee7ba6ea1a81ff5c007933afc73266fac4c134ed818a48
+e7da01c71a46335c845f9da5e960b25339d551582b375814148d94cfb781
+fc56093827b78578a73d4ff67b6b87f40cfa5e3f4325d9108cdb64bd0642
+7b88c84105187316fa2990b4e3e8edb6c78abf164f4a9717d523794b2fe7
+72a04dabbe688cca977090979b5f47ceb90a1dbc167d305eab231c9f4260
+c4ad10889cb785169902fc0bed78da15b8417453bb65856ea0bea5245ba0
+573f623d215f6c0cf801851c305b355d26b52b0b343645fe25c78a352684
+1eda480919a1bbe5f56fc10abeaa3e1fcca7c43ee560f067f1aa2afd642f
+769d1ace8e2aaaf38850f0d757cd808c921d716e96fbc07da7860dfa70ce
+ae2888c0ed3cbf9586443532b68daed9a926655c157a416c383a53d8f283
+2a4e67468112a09adc837ed8ec95f70852921f50d4417239fc42ee3624ca
+97f682745cc5e76cc7c67bd99f2180f8c0b7fb49539c8cc474c25c0dde49
+1671ff329e51bcfa779346d4686835a3ad6633fcb5e0f67e0ca9ced8f215
+bef4d240453eb2edd6adb22278aa5b985fa140c9834d38753df2014f8c0e
+e6dad19e8fc54c03c1f6cb0f858986691d99592562cad95fa0a5b2abe4a8
+b54b457d42e8c33a2d1951c0419a72fb94fda78ecd92bd2a1416459e9dec
+a9469f35e4c47db531726dee8f203d7042edb32f025df3d582547bb1d45f
+7a5b70d317df4ebb16e36b0d798e0932fd2a85b04fd67143e4b287a50416
+2c1f5a037ccd780088c5476385af8168e12d97d44b0630621759173c8f1e
+3006b5b1c6d7138b7eefc3cc5f54e24b2c3ca7b41aacfd25e554880aaf40
+6ea4c3c6e21d3b550b040fb1952598a7e8e6488fe38288b2aeb6c4718338
+598a2bfe4d2b9d14c65732da304c16ff3e1f8f03046ef095b65fd609da87
+ec24a69278bfe65c905cd0329f6a486b8525b7eea4f7ae56c2633cd83543
+269e8acd6d71f500d82fdfbde7f7f7b1aee67328549232e26ca55085b6e8
+4d9e2e7f74068f93a90c4654f2f396e57c5f76f7e61cbbe523dbfba6e766
+38bba3064da025a79e3a294fe7f1cc28a3b4c57dd6fdc48e541a85534b25
+e1bc11b4f78019457239eaefd4be9007d205f1d985f389db22400b279c10
+948551a6b4a17fbda0ffc9428b18b43dc76efb15fc2182216f1b60b4e344
+a03ad6c00f141ef99f89f24c819c3e32877a927d84c2d006940f39ca8b71
+e5951673ea9bfd1749923219de38929ecaa9ce43b06cfa7da1bbedfda56c
+61ff6c24f40e59b13870d5fdeb82d981154fae5d6d5152de69339359461a
+41a9713b6bbe47e868c933cd74c75db71d13bae4dec85e02faa14ead6c0a
+253b16c79514657b15e68ccff9ee6aa385cff9e2c53d9ae40f85c793e4e8
+ff50b2b7420f4fe69807bc5f37c3e300e6b3c3549d1d3246a2e70f091054
+1135bdf805e0a698e236b6496702d061241687b7b8d1a0e517df0476da09
+d89667a7ab375fd2672dcbab8124e511502ddbd08ba04d941df1cebdccf7
+ed48405cbcc33774a68c5212fc6f132641ff413c984f8b43bdfd7b1a2a34
+35f15af07ef4970d3e4a0bb947c181e9ca27cc14a35bd1bd096875b45873
+8ca244f88c28728b74e25cb8c4fc1095a56ca75e4569ad3082ef194add11
+350db3b74b96761d4538596ff7243b1e1b724716a144106e080d42036444
+fd472998460ce9abbd05b42af9389ac452bdbba3a13a96890025789f16b9
+d92251fd3b3beb2c61eddb370a20456e3bfe5f4039e2557c451c524f8087
+015baf3ff05f51869fb97512968bdb2b49589c1c7af1e085250a47657465
+f480b7023e24c76731ac0eab6704123d77977d3a2c4c56b691346ebe589c
+619c04515d34f81fc6a17527d5d8319013c5d4ff27cc3925e24c99231ac7
+fb9eaf0bba482d3b75807ac85d03cd09de5d9ae0b07b7a813f0449786500
+0ae8a7e00080300f0ab8c399057eddba273dd2e1b2a0dcefad3b332e6d4a
+c1ffad846167dfd70e0346daf84af292d4f424256ed5ac4e104f80697050
+d50844a708eac9e7f7784fd01646f3bd0c595ca51ee6bd607d254e78addc
+5e15c3b6ac4940ec865a5c23105b6be09ea09f2c05d6d76960a843b81ee4
+33977faac3cbda85cdd2f4db7c28293a77825635992af8f3b38b4480d9a1
+39b1662345a8abe1634a77496c3f57597d2985e9e54717ab2e99ca357894
+41bcddede9a9e2106b401d9684adbefe40d607f075c179e9cc03e59e6543
+0db70b441d43df03f2aa6ff06f224b6e455b01c64fb89eec9103e48453a9
+749b4d602808c7e408a8903091d85e06aaf635d0d529c3cdd1b8479ac0f4
+208c284bb678a547f2bd77bb17c86d4560434f7ad1937760a6aa55b614cf
+a9ff8c9c96561ae6c8f2121c4e20237428bc51df2099b6c49e3efa18e6d4
+39e6e6981e746ebb1dc461259d8ea0f8099c47cca27b2d982b72c9a07cf2
+1b3c05d6e26e6e286e348b8944078e24809f9c5f3d014b4cba02533f5621
+bfba1f0edb776c634746703c9f73ba89b1960a496420c68f54e5b901a6d7
+33d7acc79f275fffb253f389aa480084468bb34da1e797e43b7f6e8caf5e
+8c93069a3a2730e57ec39b677bb73e3f07c2055599f7062e53b37a5f0099
+907d2ed87ff7a82c95fbaeb888033bdfd67ba3a6031a4cdc56cb1e4cf5b0
+6b46e16d988beccefacb9e1c037023d7bf5ccf5d65aa66a17ab361be7981
+f132a578f3abfb97960a6034f052d9d5afdc0679782ec90f240f943a5f9a
+3d969ed7399254ff67d89df668f7c56fcea1ffdcf20481474ac8495d3af4
+b6d7ee093e369c057f0b70858220693b398acf8e8143558132e4391405e3
+0a73937c53402e459f4aa3539cf7a99a3f51c0307d045df8b77757e92ea2
+f51bf0bb4f77d3904dd355665870c2b59f1ed7f84fc71fdd7f0b6c5d3182
+db77827ca6a2060d2b8c83c4ea4a432ef43a4d0a952cc6cbbe52a9f0cd66
+1a538973de41ffe9c5cf55f2506b9efee51fbae5e63bdcf5528499a47c03
+1163c88d3022606784de2f46a9c9235aee3d4f71d4959b0cfdc5b7e78c8c
+0a8f9dc99440c2263dbacb343c5c648577f5610b50eab1cf7fd02419ef39
+41c7ca0b0e64ebad4b2cb05a0793dbc38f1946d44767bd287f5e9779c611
+ca0daaa1e7393dbe0683c8d3455cdfebc0e64b54b737e298dda605227c0c
+4bba87aa3ec7fa6ebaec39e6ef2537d5974391d31739d9fc42983d81aee4
+4711c823f35f8e2321ac74943871739d2dbe9748fe68592263e7713f27e0
+d49b9b5cb7a4e55de54e6b800d15856450ffd3ae5f287b12ae4f438b20ae
+9e27e6caa00f3eaeadbe08432684fdf9931e925544a680182602a3c1997d
+e5d0630bd5a010535e66e1c123013d23966b3545c7431c39b97295bfa409
+9d14461004c42c85095eeacb9b47c593bc6db863533a8619bae09095de8e
+ca432d4ddd49aa600d277e75dc3f5c6631e2a05382cb007825fadb77438d
+cfa78e252d79b6a196d5164c2feb85d75eca25ff80b1d97fe10e87960ca0
+fc47c41d3a213bf141b48bc3aaa93fa86245064668394665bfd52d12c3be
+4ce39efd8111754398a944c3fd1afa98ec337baaaf899d35e804cf416ad7
+fe45fff13fc6354007501043f98fe8428de8013901ba6a28711a2ca85a27
+0bb135b72f1d5026e8217581860729e94f2f1878a0e96c59e9f62714fb5f
+8f25003dfc7347e990078a9a331cb3a6a535bc61866f02513deb982c4a13
+adbfbac3ff70a7335f40d5489e48e5ededef16191973d932479c62183b0e
+25ee8c4f76d4f1ae45daea4a12aedd9ef81d248e8d19f8c8a5becdd1ea1e
+98783eb7a38149170851b1942c96c53de06def80913bfc04e539ec67c110
+498d15b78268853e5c72f485f8a27b768569e54241f6115875e2973292cf
+48ff91d45ebed627ae9f0766d22201b20afdd40e5b17cf337f2999e0bd15
+b86e46eb3c18fc12b7dcadcf9dd50c6c7e3f37e615a892db3f57e250a072
+a49f7277dd6a2c8042698233d35a699b17eca5dbda6d250ed4a16fcc893b
+f0dc2e33fb1ebd7dedea3c1c39603c8b7e1a5a833a8fcdd5570bd088749b
+b232615366687962c7e56ed089cd7b092505cafa5a80f503c4cf337f07ad
+f0d106937e25670839d491f7bff7a523db609d126328c16113ecbcbf9c40
+04904427a108618ae5d4ed809f8ccaf72251104c94ec5bee21f91b179d31
+dba79ceee5ec7ff698eb84ab1d2d1a624f58b3622a78844ce51498b2cef3
+8eafe259d22c7ba61104651a862008bc1ddda58cc45f663eb26428daa85e
+7785363a69d2790996ef5d9621d53042f42f794962fea46e46f37b8ad1fb
+76fc8d5cf2146843f8cc625139c75fb42dda71a752bac48f294e4c0c8289
+fc46da5efd9c91bda6d027518b7e81e8b21f755a9615627d5812aca674d1
+527a1185eed4e3c628196e7d0759b1cae6b9b7e901e9599a65230f1ee469
+cd33b9bd9c104c44e3c1ab966c9678bd0ad78111a4e0f2d07a01a038cede
+7036d0534d684a1562a17ad64a00f279200c0371b1cba61747671d2a21d3
+f9646ca290f6b82418a96fa177c6278277504b7fba936325f5fa124ab018
+a15dc18d2c5e8f93cdeea52beedb78a57828d81a3e6c38b9faf3dc4eb727
+3ece3ea4482a1c6242a335862c2c3717f9c9ed95f77b140c4e1569b2192f
+c7dcf702d0bc9a50428ec406f8bd0caf886b4d979320d3e429816d88f7c7
+146d960ac12e70f2cb7a9f4e3e366665ab3f1b4b6440f55eea26dc9ee009
+6bb7763731740a537766490c8c174723bf0eb40c53701aad12b21d436adc
+e22203c1053a9dc4e9f17ae617888c4b4e6f3a720e4e6366ba628221a387
+d8ab15e04ad69387c310d3528bd2faa5b22bff3fa494f5fbfac4f771c9c7
+402b95580c5ac4bb3af692a70cb2c851fa5cf1173eec3ec29b5a05a0b728
+bbbb51d3b7ad8b0af17a1563e82fafd93f8b71181fb7afe352874f4ec6d3
+34ab6747519ab8e847b7bced33eb5458a828e074e74ba621bdcd03fea604
+7f7b6abda01fc7514ba1aff0d4d0c0cb8f4e42d5a87e395d9acdd02ccc22
+0c157153422018725846009a3acd8c8cddb66bc6836b4026fd9f526aa275
+d06c813179e5924f26a25094e7bda8bd26afc4ceb41d8964d4fc4af1dfb0
+595bc5d6714c32f15dc7194e9a3a73013c45d8fa55cc0550a12d9aae8e9f
+f199fa28efc2426d8d1defb93a65717af3ea8e2d5b4aa8ef0ef38e9600f7
+d4e7d9f1d67a2e63ece4789fa74b159bfe2f91c19b0378ba52e93df12830
+d99553b6618645e26126842ab70262d96e35e5e750eca0ce3458b3e51bee
+2f21191136dfdbca39bdc07939e521e4f492f392debd029c1ea237bd89af
+76bc89f618d530160ab16269fa6b693cf14bdc4ec7c630025703c5337f61
+458fa09104eb15c7cb20aa4c9bdb7cef3a09f25bc7f3149951a7cd753729
+93b80cd2112f7674cefd6afa764aa3486730d2c1897a264d82a91709fec4
+a21e30d812f558451804ee6f3dee2c4c437846bcbda07c5b6cba1d94af02
+9163b7383cac6e088ab1dc14ed3743ee77e26ea7ad3119a76c0b5f925c4d
+e305cd7bb3a09a4539475b9bd79be28fc462d8718ce05f9d94caf3387ba5
+5e6e447bf81a9eddd3a34e17be66bc52b0c0bb6f86f6f008829173816d20
+5182ed2eced319864a796ab65d4e3950288bada94fa32b6f453afdfc6c39
+a4fcfe60353a64627e2057d4b379d3240012b3bb0ed0c7876cb83c1ba5ef
+b6e2a03f340c2b576731f848f762a7e1ccaf267ee06d621bc33fc245d0e1
+547adc12cc0eb58b26babdb8eae9cbfbab93836fff22bda1831dd01b7346
+ad377aa298d84628bf1c07433284b0a90fc89f5aeb2651ba2cea405d4f52
+ddc0e74b871d43f71eb4ace0d2b401f9348eac3a2ef0ad295036bf6cf6f8
+70d58e00b619d50ea7dd77bc28def91d805cd527dcbcfdc16c042bf9b874
+e3b1567eba4c1e70744b9e7e5bd1fda6a5ff6e101613fbe58dc46cfac1a6
+5adaf65e49757e9304e2ac9a91e0588600c709a61d4231730073a36d473f
+518a145e141d0a5a494441b9ea99ac23f60f54f8127b477e1ce698bb4129
+b4b1dfeedf10d9e665c247a62f112f5ca30b0ae5dbf3e495ff06eb28eb43
+8ce8aaad84d5f50fb56a3af002c23bcf66abc2707ac233fc0f2723db99d2
+cfe7d3b3667732a531f5dc315ce74edb9050bf75d29e6430f57cb6778b2a
+cbd57dfcef896e6766c8fc5c9f9fbd701cd62cacf33ee0fc95e78dadd205
+b5f42cc63024624baa0ab4dd447832b4e1dba77bdfadd223989f8e958c8d
+759aaa37930664c6efec708116248a2a7af3d656ddeafd009b7f53338546
+08e67e5e588a857167adf9225cf6c641f5e19c3e08678a281199eddac831
+b57223b1beeadfdcbc8f6f25d32fca2336c808162e8f381656e847fb6cb1
+3969572425aa05ac830c33de6e030f86a3a85d2a66a77f103c7042c97205
+526dc882ea9a00eb8bd5519847eb424c15f808a91652a6cc89b66a573112
+6debade123c63d88a2e550facdeb3886ff98646000c64b3a91078012ca30
+904b71737cef6becabd43dd702880538f5a70085e6cc6015d2163681067c
+3d513a8c66032c34a0fe17a58ad4bc97ca69bf41f11d5e910fdfe9729652
+d3ea21f8dd8cc19160a8fc77573b1e9cef4e790a79d8ad6723b6804e9616
+466c935303e063dee29caa6c3baebf278b818c2ec2f13ed645ab452397bf
+00db8b26e115026e256746cd0c78a959364fde6deddcd0f441a61a1eba32
+c7bc172bb09512148d1ebac9e791b7d51b71cad2dc9b83b2f99b3726607d
+9cbe58b499a13753ce87fcdce21c0ad0528ed0efb9b2c927f57c78c62624
+8aa2b835a0791244c5896686a66173ec9f802c4c633a42b086334d2a4878
+0e53d00809247be64e529f96ad2f8b3922a6097d414dde1ec76f9552f9b8
+d58b8e34f359ad792b2be50c26db05035e7497162e7c49c38d3cd9b98d62
+0aa67492be5afca3a81a7080185c7f0b5105223f1fa77805502a2e8c5fee
+a27699858d84a95842c5f2fb68686d59fe24091fcdde139b6463bc6c7b1e
+0e90d20a83651af00c85797bb9f53ecec1675c7ee636d0d9e77dbd8f8967
+0f855ee4d4800ff3f6950eff09bbf8a0daf6b8242840cfa5ba73beb95115
+f4a78bcc02d85ecce0c0f2ef6f328ad1dd6cc0495a3315b414a4d61da50d
+a46d7acceff6ee56451805d26b0359af193531f95f6589cead6fa041af15
+3067f88a0a2fecd135c56682db2b45a71d1fa737c064ee9a4f404bb72a70
+b3af0330359393247ec781512482579865240a23cd8479f21c2c44a119eb
+c4e81b308dd8aa86e60c3dd8ada50e0dfe8308eb1a7f201ede8dcfda405a
+efb47e0e6ca7ddb376dcb21d37f7acc4d3e9f26b03a8de0e8940ca3a9e75
+963a389df8038d2c486072f61c0ceaf500753c7a6352b1cd0338d9212b42
+a4d3da23d5bdf44c27c94b88a415a3242ffe2e1b332477a21d2b9ce075ee
+479c6e657a4d8874a8c53964229310e01ed4f3c686fef5258edf3b464dd6
+ffd7f1caf473bbe722d60fb14ab4918e93878a8ae4773930b8cee110f476
+7f42a52d9304c55be12846c911a10ab9b2e036bf9dfd597f5348d4223331
+5fa80d0f563c388bc2532103f05e90dbf1923f229f980a2f4585c7a37351
+1372d07dcbaca583099ea972c03e5aa67e6638826db134564db993ceeb6e
+7a6659c7c5c05c310267d5f8a24eec2d5cc3e3f3c808e6d6068d1a57646b
+37fabd98ecb7baf99e7d9ac4414a491a73ca34c52f394352f6b5a15f0fc4
+d88622dac694699c246484adac3b1d366afede2a2cd2042c90516a666a19
+a91c80248b11224beddf1a320e230739e755d098b6a67315535f4c187cfa
+67ed817a035056353fc859bf286317996fffb478a2248b908ff12abde705
+402224a3ee5f463dd3d243875c84e02db968eca1cc52c75171ea50d6a88c
+a91327a7aa5795019f36c0a19c093a1c9d3723c7568f9d41f2e4ffb712fd
+47f897703d7a620b586b81936c84aaed61d84332b3bebc4f95b796b93ef7
+a1f565c494f8a65edb21e2ee18dc025522ef8e599887ca2836069cddd889
+88e5862977b7472584303198cce97ef9f9e1446d1f1f5ed1cfc666a8a0c3
+a03e1792efb60a9b406549e0dedf6accdbd98742568b4735a747d8e5de21
+e630125ae0c691d054e42199c15b1f80cafa6e7bb2005f374a9a5f9900ab
+b7409ccd50c3afccab1214e6a856f7c7eba89bc3291801e1343da9dad2c6
+ed075c8eca1423b43e587aec67e6145272814b3f191b3c285639f9e2d6e1
+48a02dc2cbc0e054d6295cd05dbac1950400a9189316f0265b86a732d302
+c5bee8ed233768f237c62600cbaaff3a110d5efb6cc7ca3b92d965ca7c5e
+8d3e64ecf239fe2507fc797fdbe54c1112b28d4da44c60ab09d994c5ba78
+d663a2591934cc052bc70cd1dca3325c66c9cb982e2039f5db70c848d3dc
+ef655b1c2cd0cec8865fe8e1c0a267be4f707ece6f5a3dfca3cc1edf92c7
+60439f51aa69a4c1801e96ca4d6ea4ad980258f3d15c893913abce091019
+84c61b91d603053e49a97cb82fba707dae8af1d579fd69c8481cb7b712cb
+cddb4d287be995e32c02b399602a08b9dd849039b5673f1930bec7bf366e
+b082d2ca5db2385c8cc45be3fc0e31820191a814eba7c4f23b1938e6c4d8
+00732787cd2cb97f762dfc85d4b798809b5f2254d826ca42b32695428d12
+0298b44cf38494e56240b75df1e41e46e53c44dc505452256dfec819408d
+605ff14d6c1f3f152f2fea96ea0ab3b472d8704e06be9f8c3e8395caadd0
+6d6da033e81ade5dc3b83daff743c6e9e48716003d358df63cd7fd3e2f72
+7d1f2d0c29962f76d5c95ed44b6f08d052025a665785f264a3d5f5593677
+b630e628b5ea81fb37cffd7a30b7fad226b6fdc82b0878af4c0ec4f4243a
+807b9839ea62bcbdf7c2e9b30a623876e632e084ebf4a21eda04fc88a1c0
+7021d0c72ec3e969d449feb08e5826ec20e55b21ea71ea59f6e3b0710b0d
+dab3261b4a2029ecab68c19add5174e55d5e984a4e5f38f592a302fee6ec
+e732dde841a28672c620cc5d687455a5c06fa9fe688394a04f96312ed025
+b7aa6fbce2925f3ae559cc1886beecdb70822e2e5ca3f732a87404b1536a
+ac469989e9610cfa440ace43875a70ca51f36cb6f629d9424c1e35a88f92
+d5da3cd8cbae6e8425a36968e21f4f30349749e0205bff8d552837d6fc39
+532525370bbac833f75f1854c93fc533a4aa53adf7008173a70d94a4ebf5
+38ea9e62bcda7c20e0a073bee2efac34d2ef1d03babd5147659e50b55704
+5b2eb89db303749b04d3f54b43fed612fcc68206e001a7afe90230d9c12f
+74a32c7edb5d0241dc3a5d51481fd7c8fae08fee263fbced7c7d911b3a30
+3c835af5fadfd218f61a9d6de80485abca88200047b094441f7767b97a24
+e8c612590fa2407bab1e8b56c71914eef2355dd97cfafcc192bc06fce063
+d3d9d1a629aadc75e3bf207234c208e7e30663edd691043065c9cbc473d9
+7c6d4dd3dff59d6a9abcdd4412c3128f603160aad8f81c6e7a4dcaf35f3a
+99b4ea10a34375b477c2bf846521a7eabd4d28078e9340452a198f3f5acc
+3db7e3908939ff6e3709c6a3fd9889439a4ae3e10b618cc92e14b68429a3
+ad2c80940a1079452ec266f254657be7d79a2a24084af73f6df71fbcd32b
+f6913a3fab25f977787f7bb0c3a3e8bab38d7a2db0b4826950643dd1e03b
+d7dd1fb149a33862a89226b7cb454daf613128c2075470e42e70a9444a8e
+6eca526345ab48e6f5160ba23b5bddfda6049ec44ed1461c7e0dd514b16e
+2fb285f72039de3c7982efd40d7f6c8e8f4cf35ac71b467bfc578002e8d2
+239a2fd2c4bccdd8af3d7db1f4ae7f2d2e0811df9d0155ba6ede50b5f052
+f14f6ab884fff244d8806c07ebcb49ed22d85df696995991a954aa97a1ec
+d86acd76e061b7541e87997fef0657a826bd88ef3a4a5920462c6595e7a1
+56f453291ca044ced810860c3b0149bce73beca713040664ad0591304106
+129600af71317b0d2907839ceac99515d357e980b1937b6e1200aacada20
+5421001f1b2f91753e80d2263c56aa164a74701a8d5fd28e46480b0dd963
+a683a1f355d7fb4463c7347c94ea5e2ca40b60b56297cb22d972c5bb10e5
+6715a955605256c1541d9f3bc5768a6f355cd3b863f0fa1a781edb49368f
+51b29481cbb41d4aeb07af9dbe8f52c5d0ff75f7fb6431d37d6aed84d78c
+778871cb0f715b4f07580f23b586c969c81b471ff6a6c7276f7e141e02a8
+584d4b9ab00e7bd643d2c3faaa299b1f1e25048461952ea42d4882768a70
+de46b213a287f8d31ac46d5436f22a796c05d1fe50a9bc2a928066627a0d
+87dd57a3ad91db446404b41557d1457873482005ea20916bbe46c613f456
+c849d46ba79d20627b446b2f49e3fa309ae14f8c420cfd94922cbc0fb9d3
+5a0f7dbef577f1849a1a80e0011da8ac082a8c6f61658e65ad177abdf23e
+e17c8cf0d26b9fa3a6e94837eb9e930336889767a8d7ea3ce980a8ea9552
+8b004957be6067cd9bd8e02a0f23cc1762cca656d33412ff45e917fd4a03
+eb6e8c1f43fdb0a8965a33b4fd26bc24a20b304ca817e88495ba9b361a3e
+933717ffb0271f7f70c5d3cba1e86d0f51bf3aba194daf32c35c796627d0
+0c7b2271ace2463e37e97b3c826cf3db60028f240f9452cbe08f7ebcc5fd
+b1bcbb3c327a9f450b9e5671916101d6e3e5e458ca31f04d12f592f83bad
+a2c3683d3886aa3b403963ab5dbe220fec00037a745839f67a3635dfd3bf
+f08f367482962ded88ecf6322852d643a54d5d303eb04bfddee9bba1ebcc
+ba7c653b3a613a8e719adebe3ce1bd7e754e5f4977e863e3c2d388a65227
+b451d4f3a4f94e06513cba4ac1f2f511613ff035611684ccc461599000e5
+46e4d972ca6960e095a526e4735a23421a4c9b597ece08afa2753592bd16
+ded93255a1e33deece3c5eb77b94670e8137f2a4a4b98ac193258e7dea5d
+b8408a806188f2d1ddc440ccf0e9a6e2f0c78fdbd7b68dd4939d2458c196
+5bf8bed4564b32462fff3ec892c03b11d3ea813fab4cfbe8d3016329c5b7
+e3dfed0f08284d44aa0b7a2f6bc96ea4503e8ef52a64c22bed6b452581ae
+8ff8917d53976471941a9116a2d878fb2541b561767abd4e31ccd8a590ca
+03494c62affd64ea0a1bc779173dad84999c7a8d844eb1259de7bb5b25cd
+023537a474a524ebe4660b22568949e624d8fea0ad37f4ce1ec75955eefa
+49c6bf1803be87e9c9865ff3f6b8525b8c15fe8835ca153d27e6c0ff0ca5
+1029a7a9185d25f0f14d86fc797dcc1f99ee97e2054b9c2a2e06fdbeb8de
+f6cdd368bf23a858d9f8c1defdceaf1b4a8de5eafc604ceccf0d285be00a
+a912eab66eff4d37ad2efe34853bbfd87ce09b18749b489943eecae7887b
+006fb827d10191dad18466cd1f86505879310a8b171f902ea0c26a388e13
+b53c700272cee2bfb47acb58247c13449c6bb9d01232c32517358f1a3de0
+64d43c18f8827d53789ccf3ce2ebe78949a6abfa1a6b8414ce360a5e22af
+b7d1dce6f5a06182c3b984b4f9bb1a905a9d5a1483750a1de0a857cd5c06
+945eb7d4a2a6bf1237f32a154fdc06d51a703d44fe052fd3c53e9e8f417b
+35d1c851f9203a8997521529f21ad8498f96930aa77ebaf82ee02a57bc77
+c792d9f220294b45f48ea8fd94e01cd25645d36d168923562f3fdc93cb79
+dd4760da0c103c2675722d7a1b79fcb4245ed12fa0db52492c9cce58b333
+cfee822812f7dca68e802c451b5cfaebac608b950386b6c58239d1c62d62
+4dd5d15782fc552222cca06ddf387b373e32c3c2864c63c768350c372837
+60f3515a5b0afd66c48ab522eb3e808c061f5cd6bd96cd18c9839d30508e
+7d4edb88e8f11e31e10919b16b7971f06d7877a058d8a4944c84fc6caedf
+3341b48b6e0d3c7b85d710e0c35f5b5053cf4b4798b3778cc28b2dc7ae0d
+f3a49f9f3bcd8e95d746c35c3f47d68b8aa35d97aa08e711b5fbe70d1a62
+3c82541ebdc51a827d0a69e6c049087ad26f256eb7577f58ccffbccba5a9
+5d093dc29464c9a38de95bc6b1853963b2deb0b57ad1248d6f1625e115ee
+b9510b5772aae4e3c866657db0b3bf0e0ac345e116f8d4976b770876ffe3
+748c36165522991f46a36f193dd1a1c94713673c7e4c81582391b636c72d
+e94ce6254374f99b623e5686c13d8a8322e83e11bb0b0a896c6a8c2c4f75
+6c5385cd7017f26d23f7c3ee97372c868c8c915581723bb6b76b4c3ce899
+8e4fa6ca40b633dfdaa59ba902a4952da90ec4fc3cf0f2676acfa7f76f78
+236fa2de10fd3545357215246bb7e527f277c28b353cc6d79dcef21bcc8f
+77603cdd58a2ccddbe3a9802f941ced8e035313875319548c41992a2be93
+9a17cc109426e33825ae59bcd17cb19f50d972ffcbe7d9b4b0bb095303d9
+dc9d406696c2508d6ce99e11cf00f6461147e97449ed5f486d480a86d3a7
+acecb7e9a945984724efc21c5079b1fd03ed803c2deafce3327d2d782771
+5fd65d9506216c88b0fa26935e95c64114a51919d419038b1a7e9c1e829f
+bfb53275093752df19891a97f3cbf7719c1fd6cb17019a6d2d25360eca80
+4c4b35172662cc4769d2b785c6c87e5a4ecce31704e59f71263b7c3caec8
+acb4c7426ec25f11a0042323ee6c3eeb04284dbae2c770bc419dce79bd45
+60aea41571c3b595f52560191dc7a8fbf63d413a77a0905e517441b16c2b
+501ea2f9e99cc38d052679f288fdf1894542e3a66989a0090185eb2e7513
+4bfa3d9147c3db8a621d9d35e37786853779e157b47f71626d6b3e633005
+9159c17596c1b87fe2b4ff47ed9d78fa4c2160077276c8b58cef5dc030b4
+a5d83cf257096c047fe64de307c598b815058e72d5f57df5c369e664e137
+de29349e2f9dcd8c9f4eba6e765b6327d7a20dfcb20711273fd8091cba60
+5c4c494248076f7e03df65a6a50164980bbbb708741e5bf6056e6f996dc0
+7fff408c5b8eab8dcec315e92873228c805d4440a6470e3ee3983758dd21
+1c9cecdbfaa4c9300cba00608a4b2404a3c7af017a3b7e67f39f0b51acf9
+50d3e75cc7bc2b8d3480202fa958e8ee0b2405015232ee0d264c7ca02c18
+ca45cb3c2de322d3eb7f00f9455db6c5b1f4e59c3e95520ec36d7d903cbb
+625d70b54bf6f8255e412604bbb29fee026cc660577f91db1db4a613eeef
+b20cf7ae3cd89d565ac838416b01b5de4ffa5550d17fb51fbbebe21cf1d5
+6038863ee931b90dec2e211ed42ba92ec244d4ce2c4ec5ca87a026992772
+dc2af754fc982b94f36ea7b7bf75e0ece90cbb2a6aa1a012e8898bd679c2
+3cb3827c35d5d02f0569c7aa82615d4aa67518ecf668d3b57d6ef1a80134
+24ac2268ba0d9a74d58879edcf6382a89d397864940303eaec45a38304ba
+8b1cb198967ae23eb81054be74b16909a405e8a7799cee3c270fe2a6dc50
+bd7370b6b2c8fdb9a87d88d5d40348d3984e39c693b6f4486d994778607a
+80a3122872dd65e40492107c71c3cf708a9717e9eefafbddc239c53aa964
+5b711038e59c8b861b37411ab2039bedf9cfd00f08d9c5d76154427ff5dd
+39878cecc5d7bfb3f1f035087185c0981f3c2139be84872ffad3408531c4
+ea9387b89f5e3ec779e8850d50992dfdcf9132bc551e985943b07618ac10
+d1150451f0844c0dc41d6e17eb508dc8689ec726400d5a7f6feb3cc7bce0
+5f09228b7cb2c5393664d8dd9a4b96b1020ef25d70aa2d91cae93afb5f2b
+f0aa18ca5c599fa1a708ef35bf8f7ffec9afc1f242870d028b2b1459063b
+493943ef1283829783e1010242e5cf4da39d93d506f3892936e7d6cf1124
+70a521d397438733d053944cff12d6ffae8246f20618684f263715aa98e1
+5d72a526383e05c23214b78338e5b476f0981d90056e6e5d0db66b1df229
+8e597b2abe1d817e18beb056e65edb4234342d9600470b1420c9210419d8
+34e431b82f58608c87ac361a02d0f1fe4b470a3d71e0d21bb87e1023d428
+e23d596cb9e1a2184403a16e36e644bccf9bbde27290485057e62827283e
+7380af786bf395b3961ba5ea469c315763fa59e0f176ef81985f38b882de
+56a74d128e256d1b89939728e55a92aba21a6b7844fac1ba7bbdd8b34a18
+194a2984b000380fe9f672e83efdbf276fe797a325815b0f25cc95c97a9d
+acf56d583486305d7c9e51a7e337d14e3b900333eb38fd93a99587da2341
+b10c059c71ce080fe7533c0f059fa40e560af9c4a41a4be6fb45846ff8f7
+8165e10b4ad40f264bcf5596a1e8ef8cb6ea4b1a3a5c69059ab156384367
+9ecb2511a90e8898f54295649cb73d277760d8d04abacc7bcc6e777a0530
+e2067ccbc08673f9c8c178f9d672ac8a15e5367f0c5651b53e75e0cfa57c
+931746ae1a679c246d7c9417f1cd89dddbd1173c2f880b7b3847cbccebf9
+9f7122e832d7c9bafe2b54cbaa1ed48158de3f36238b76b0e67644a28aea
+996ddc006f6ac0242e4b667639e7523cbc90a0561193c1af34481c2ef402
+ee43a82e1ebf4e3d601bb36b2d95cd93550d61cee7a94e72f6d30c32c8f9
+1a61e964b1f66acfc3987f95d4028f116e9a9a8474aa29c1c1a984be0e39
+3bdc41dcef6a6f1018db60d52024899d8eb5d55d324d73f39bfa47377b9e
+15b3b06a7585589fcf52a54684173e5183367e7b0952dc4bc2767c4c6247
+b1d6103e52bc7b7ea6298f454c5d97ac575f19c10acdff4e10c7d3755cfa
+b4200cac545269ff1d8db0d607c7ad47f40ddf257ab4e7d0750577003c13
+e4941960c3dd7b0774ddac18e8abaf8f53e03cbef6d57b44f24cf821014c
+064278fd51b3427593d17694b4abce81f49cbb984c5878cdf0c38d1ed7fd
+99b0b9a3bd8d8ff6219588b3b8fa59d0cdd1d9b2f65122ab45e48f175746
+7b9204926140e3c350c5a927a2e700173053ec35d3f1da2d7258714c97fa
+a857f0898917bd94625c6d1e2d77138efcaaaf517b17fe187a2212c24a88
+1a2c6a647def6376ed80ae4175c5ee80921f001995b44e49f0d33dd9075a
+cf33bb03671c0bcc34ad5784ad1cdfed3a6d9ba103b3ddc1cc2de74dbb57
+6a0277715275218cd19ca8899209125266d8bf1286f881dcc2c383749d1e
+768d670f4099f7de959edfe852583183c91116012881a56a24aaf020ea45
+cd5f39660debce30ac1c7b8cfc60387b1b0c3e361be612fdfa9f01b7e4b4
+a18839a2c7e0e393ebc5ad9a8a4ebc316a740c1c295d9ef5f4dffa0667f9
+582c0bb837b142c4cfc6b1798e9476d0631111033b8ba75a10fdc800e2ab
+1e0e829632f869cfe4737be9e2800759ee0831dc7d1195eaf80555771981
+dd6dc6606812d92cb8ef86447f5f6c6f626d0e265c67e52a6319189ee349
+d48e49dfe6a9e98f76c414a1e3217ae0a215a17e54aa498f4ecdc50242ac
+c7e2322f63bb2ff2189d057e7354e32a3ed1803116176b9b9d0129930f91
+9e2fec280b2c8924e49e7bb75768a2ee1da8adbed4e3589906df1b923aef
+84c1bd327438b731012e69bb0d43a1842cb88bb54ea4516477f704cfeb28
+6e3ea483445ad4d74586fcf32e96d366901084365f693a53c5fb532fbfe7
+bc0cadc404c4985042d68dbb90a6dcda3531ee324d558a214f935cd9fcc9
+a0cebe9b5fb0323f4b3820529599ef48ee068b5ace85004fea2984f0a86f
+5ac9d56163bbfe1142b774148f1eb0a4dc89c3349052533a7de66729db24
+41b82f8f7360111dacf69293c9b281a0534f3e9e9224a75c49a832f28b2e
+497262475507b6ddfa9f01ca0a6696e3f5ac7ea68595eba0c2eb8a47813f
+f936d84ac1b23eca7aa2862b793ccbb0df9fdd4931bef354cec12fbf4785
+59fec29f81adf4452e83963e56541d31f3691c93a50f0bba5e9552c4f2a2
+3a6e53060729854a3dd71cc4308b91957db19e66aaa18fa67055a950f1c2
+cff78a03bc1a588cf624696068068719afb1001c4581ee072113882d9052
+b21e355d401ed8cd24d067b99e616bda5a0a5a9336fc499632b79ff2fd0d
+efb096ef46b75e2d4e0f48daea239719fec4d9a29818f5875fc5041a9edb
+d26caf0ace14cc80ba49bba59e918eb3d8f1e541aa16026585a2f72df7d8
+3541816de46981fb3efd0c30e458cfad04c79421ab7c4925e23aea07f9f0
+18431c790002596d26bd9663b51b699df53e4882cbc34ede88eb55045b88
+9b6062e35fd1e018bce785157b85ec3b9ca6c85d4b16238275385b8285db
+012d8fb7c9f5b946a41d7a0fb878ff72c39683144d8a007cff631b43748f
+2d5fc690300f9bc0c837006b92ecebe0605e8c3a4a400e18ae8997d1b45f
+ee10068e247c647cf82c6dfbe5e881d511ffa687b7aeb78546bfd07d5f7e
+c242dcef4930d8aaad8c6152b6642aac325963fd147f236bb850a9966573
+9d06cdbd7ca79a527dcf461e33f22bc9c5db00da2bd3dddd8c99d99793bc
+98282aa8872ff96c394285d82d9419eb78b6ae37a5f519397700f75d624a
+09bd255b576e955a323e784e8fc31131f003b0e3024a4f58fef2a6c04379
+6201fc425482e1155e229d1b2d43ef7b0d22322b22ef5c9a1be026a1c3d3
+75edaff99597e1e5477952a4e8d2acf5d014bc00dc2a272fa62b6983e27d
+228881e2ef2b8b95a681cbe90c5fde16331c85222fe2a16f0a3c3000a63e
+2e21666c0c119f8af89a543d37977069a5acf1556324f05204ce8cad50ff
+4fb630d9cbbfc324deda584aa56a99d3a76ff55bdc2c2ea3a021361ccd4a
+83c7a5e2768d210fa6de889fd48a39d679c94ec3c99a8d33ff11377da7f6
+f1b71a2a05b302ecde954f26773f39ac881542f0d0969c3995c3519a8ef7
+0b4220d86bf01beecc6462855e7b686e1aff1ca91fb8fd8b4a69e10ee0c2
+ad94add44449506f9b6ef43641f2026eff6e605c670560c2b74706fb949a
+a7e8cc6a2d0d6207e457e7fd87ec1b9092dc68b9143947cc8ed14afddcbf
+8fdda228a76847f96802e561f67ceefde45ae587673983fc04c96744dbaa
+83f2dc838d633943c75dcb9e6410474eb27b348f26e505f0ab90878940e8
+46c5e9f3c5fe8c3558c3236b1b88c405716949b8506841cabe1717474bb7
+c30db91cdee33b0f844811762faec535bdcf84c1c747cef9b1fa61d2afb5
+a81335bc42c06a94d7d59b7ede55bcf6f9867aee107555cdd084b7684c2c
+87087475a39a9da6347be281ce5635a4d07865ba98ce26c1465b1ab0343f
+49ff37b4d0ca9f3bb693d78dc3b21925cb996a038dcc172527fe57c07460
+ef39c07d4396e7fa970d9f22abd21a9c794b64ad96762c7428f59a8757c3
+6d6c4ffb23216195a04c2a2c2e7b10ef7193931544d782fee4b91e01119c
+5553bbc6252270a8d8c56dd62d448f5ad8dc69ccb45e1f17f0aa1e445129
+dd00f000005b23d38de93a3be55a4c041947f36b4e4536e307d0180553f9
+2e46b743881cb5d5386c48c7d5f84c2bcd06b9c501f78c7ee61fa2351679
+1fcf4db278af688a2e6010a56692ad92008497487edfe4bd5fa083fa5441
+38b20d6940020887e35d46e093b71f7a04a67460dc8116b4d4839625d7ca
+6959d6831cd93f81ac4ea2709036dd738364fde71113bf22ebf13dfe1642
+e564701e6f0ffe7511edf03fe448c2b28c64fb7d54b94ca576e481fa56b2
+b18af10c71f699b6bfd47459cde1869d0fd306bf489a6f42e5b2f05ccf55
+bb6b9526973d19cb134ca7f13f1db3716f8cc21773a832568c16250b5cdb
+16df24bf81d49f5b37018bd310262ea7078107868ab0216cec83cefcab1e
+9f2c665a31585ca04dc01879caa79aaa5ab201b516f7052b01b16bee5606
+098393b0e5d9f9e5e3f4eb20f63c958e796df41cf28839f5c62a04316487
+45d7837b519f3aa36bc6c08ef040ccf53d9b6d8c0c7d1a84d707ec57a3c6
+ac9a62ab37251a01a5ed40fdec6f5be6e34c6a91d058319439778a2ee5d0
+363e2e1f33463c33327d05ffc0cbf08d5bc457c7230448972fb9b4d0d782
+ba7dbf10d3ffef8bf5236ec16d4dd6d0d870d9d5eb5c64c9a46a4f583d4f
+831fee74b0e5b33a09abfd4444929bd8f638cd72eab99cf2e9551df42768
+3964a592e49d186f285258c5d5f62196a98532421d73e3495f82695feec6
+e1952c562d546b28618ffaeebeff03a57f4d855021f85b0c7bc37fcc6da9
+aeca099b646b99d4189609d3ff2d56422f8c37e97640293ec7c90e338088
+7836f4938fbf495cac14fba5648d89282d8d49d91af73ed36581139d8bd4
+2551e263e830ea3c6eb381d85c42d74c50db0ccaec03f535ade92128a016
+0e811c34748309af7604919b66cd43eb5ca975302dcb6076feb6bdd6ff55
+976fe990fb0ce9abb11b195403fb26e3d6c6a0de1c5be79e171a61e21f79
+ee8dbe7a832519813ef6b33ea098c2c32adea219ab2aac8b093f40000995
+539d1276d5f2ef84ccd099b71fe4269bdbdb6a8d59c86f7d2e3fbccf8773
+d0fae97640bc1ad43cb4b992bfadfb09dbd0caaeb8cd9da264187c4f9730
+0e9a6c9deed5525479e605c65ae336cbbdf4e5d7f79ad098f977285e0655
+79b748feaa97f2a753e1f962fcab68d72baa8ee4ff6691c23e31bc0f3e98
+1a96fb440404856ae1ab32a7205b17d411d8f21c8c93b704d07ec594422a
+bc368cda2b1610ce6a973f4474e12b78b532666797f5755d269772c9f540
+0b3bfc6c58395d38527e2cccf29b56123f7dcef3bde5dc1dfc5b0293bb12
+5085b1d2d929bc3ee84f4fad571a4991c3dee03f2db3a3097e52b1a7d5c7
+3ccb6148eac62e8e36de9a71c57638c6e4d5d9ded18174e8c390e50b4a5b
+913c074eeaebe390b214b3a68f02862b9a296db4b409769649e51d738cbb
+dfb7702e15c73c2afc6bc37ce15171f4e822cf20efe55d9f061aa43e6489
+89628ff79e65932390cbb15d8e621333b18b11c3bdf96f841d7434e01ad5
+01fea964a75b248a35cd9df9a37e48a1e5a09c624b93ce44f0042fa00d7f
+9ee89b9f7ab785e9c718cf6e7228f743271c2c9bba17e5208b920e44e765
+d99d86650eb454b0faaa112753aa1bd3a24239e9c5fc47eeb1547ac9d237
+31b8dc48b9707830daec60c8d3790bba1120f7764efac542cffbcd5c05f9
+510b27b2534b704ecd36c8b041fd49a96881302fff5b0163a2dd09c751d6
+d6afea9170a4f4c4ab8d46e62f763fe1bda51dd1ce4a27e772f3a2869155
+f762ff26b7aa6fcfa4f1292e56f03aab6322bf867e7710c34d43b5d85b45
+aa68014ad7879eed051b1933e491496e3e26d9aa8b80a07bf2b94f1077e8
+4a9726f08199887d66de7a307bf33c30dd9cf3da188088c03b2bad09a217
+6b110db2c868b53da9a66c85737ba66c93c58a259860e294ad0191e3a72c
+73f40b0bd98699aa08daf03587b78f391f3a4313c58d9f29b53c70785637
+bd0c58310109c54091ab0a34cbb0c478613a7ac0fb8f0a8b4645ac966395
+d8ba775262cd291136affddf01c1d83dd4eb3b59ccad18057fe7d92a8cd4
+a58f22508d9fd7cf356571f701bbb23e749bddcbf8a317fda0aefd952bb1
+8545610ffad3ac143d351b8db3f66293375e0e50235f0d0466932181d377
+edd32a5f0ffa4e22b5a0cb4f343d9a7e4a342e9d09dff6c697630cd39718
+02c277a5590b8ca94bde6b38446c794d072bbccb724d5bc208eef1b018d7
+39373bb910d668882caa779c2d686081de6a2606417b54d7c20e0e7f7226
+48d893e4edbae8f00d6a6da3712f91ae860c756d1127d133ab828e9d8002
+3b50b162c5a1c5cdf70ccb3fdd7ea060ed20838be1e50c4094c9e79e1a01
+87cdf780caf45a725964f004253e034c5be46bbf89d94631f1a33baa35b8
+4fa2a9d08481c6674126cd96ed05dce48bda069d902d6836d5dfba701dc0
+f98a863e64f0e312145d8dc0b77f25b43aec729a1243b45b08ca228dd610
+1caa2ac5adcc8eff84a4ca3f254176c2cc711ee6c273835d0fd3528eca2a
+976b88e51fe347fdb60f32370b66d338931d6581630ed586f349c638960c
+31ae4204e89521a96e1219e696b913deb2aab7a3b022d06f34fdfcb810a0
+4e60a4febe284c2f063e0ae9edf87704921ccfa193bdc912b747e1357006
+6223a49f1f6e2af0d4d65da04ca876ff7a462ffc9c0ba2cc545c3bd36dbe
+762f32b2d6be5867c59f479195c92440dc165098b74ea5c3ad93cdf2d410
+b04c16bc7801e7956f4e5107450787aa592493171c3628e6b8f49d4f8429
+eb98dc52ef025f001387bc1a7093f7a99f10b5d2d7dd8bbb393bf6e56f08
+f4f7fa1a343f220d5a1eae7168c74d41be1dc1a83bd65b72b982f4f7b34f
+24f97f9ec9a91011064031facff2a14921a32024385f4e061cd07d152e74
+1bf97156d951a342488fa7f5ef934ccad13e2753a0ab7a1f565c2f7f6b34
+9df03bbc25bbd972a9adf809bb5c5048a8ccef9297b2ed3324d18867f293
+cc66e88b3a39d107b610dfe79a3b4e83a96d3d52a17fe8a62c9fdd271130
+148366942c9ce57558d023da5f7501319ebfa33de9e6d1e76d7c20db8a09
+b657839da99f3d8143f1ee6253a3295c9651fa4366547893c2dc7abcbf4b
+b7609de5d001e0a36d9ffbe01f7d0903b3208ae8547e2e5f14ec1af4c253
+5ca8f4ea37e3f3ce172c7a1e8308995b1cc23e6e81190246bcab6e755bf8
+68d449bb02a2aa87c44c9cc0f571adc72547ceecbe104bb274b8ac16dcb7
+5d5f458d356466b921acdeeae384e2eb1df6ef393b41b9747f0a4faeb4af
+1928d9ad6fb7e06fdc621e4c6fc98cfb43f88584bd55d9b97cc9549093ed
+e586912161931162b1b1d52d0443260daba02af2b4432100d5506546013d
+a703573fa8013685cc798ce501960093ded713ffccf89ca2b9106390198c
+29a00864108cdcc1984a8bab53919028c01b26ecc7925e38cbe6cca8978e
+e21c2b06e7b3e48fba978e2a7d186e563c088f84aa23178b60e4729ee87d
+67b1091f3b6973676c1cbfe6530eb773c62e2c2497014ab0e8b71a1f4e86
+a378aa26591511bee3cf3d64c94848582e1354e1605b6457823f2c5e640a
+d3802946bb2e7e8e594e8c04b430c2385dd40746ce8534f50842e74d7115
+f3db0c72d1c9c607c6573b094aeb73b7a79876cffc3e2f8c9feaaa07d3bf
+ce05b61f7749a8793be90ccceca2d7077f25e899d3331fe161a7e86c8424
+95d584c6e4a0880b2951d8a13b88c4672080a0b1be36bf47c3ace7288cfe
+41a8c1baa6f0814a947fbd6b3aa72b6c73a8c578ca51ccc96f2352316c46
+7bb960e981f2b6485bfb44b577e71efda16e7405954bc7c9f0759f5a9f1e
+bcd2fa9cc9648d5831a68887f41b15081a204c24b4b992a231def9e698d4
+c3a25b6f5474f5be6a601f2d337a58a0d21ff37fd91eb86d1d738893a03a
+69f0cd743f611cdffe69db2c6ed0e4611d56f803bb0dc06e7fe85a303839
+612707647b1be9faf8d684122ca9e5cb8bde2936d3f4ff254d31529d7538
+bbd4d35539489f9e7316f24214b996bcdcf1818e749a71cf0e8845aa1e2a
+58aa62a48e02ba4564625d20aa220ee719608521d7d7a7fca0bd8904a401
+9819d371f3f59d46c1354e5fc1a6e5f79b20cf4aca2bf0f2de73da193a6f
+9acbfe0b4731c4bcebe6d96fe822965de965232282a3a130361f188b3aab
+da95a8a2790d9240be008b6a6de4bbfcada05b6786b9bb8e0dfa0c30043a
+3b07ed46277e07b9808422c8ed16758b9c396f4ea929d769785b2c9568e5
+70a83b989b25ce200f1727d41e2b702e7f88f1784f4c83fa60a74eb26b2d
+a95126e508ed519a61cc151db6804f61826c5f86d8fa89d06e526fed97a0
+db88edb432ff32c1acc9b622eedf601081af7b963c9cfc1d13e4a9c74fea
+0a1c8e3d8653cd92a944d4ca6b0d306619afd503506d77732d6514f604be
+4610c2560931bde0b40939bc1d126b0e97f72ae1b4a9252123b54f7a27e0
+cfa4425b4546526fd741ca77952b10d13e0ac2e32006a903808ff0cd013f
+936238c74cc75fd915244c56a8412f37f0134840347699508d6f3d7f3203
+a25b7c70100719582cd588590ee34b3ab13e255b613a6d00386a0104cc5e
+d2c646f09a88888d3751651d5646c5227a3c80e8da1b0a331121dd2429f1
+f4775d30564dff47d01bbe2c6c72ce4d1fd9a2077c04d2b0274b8916f6a9
+d1a4a6964a534f47cf241d5a8e34b23f85be9acffc2fea961f277539f215
+f8728d6788f67beaf45502839bcf23d8763c3949352f00c579a9a4fc408e
+c625e310dae61512dfe6844e82d36a2f81709e1f05b38ae9c222ed62c961
+ee63593ced7aaf73ce2ed3667740c77b309b93eefe1b4ba65d48575a66be
+86743dc9e5d3c2ff418d11f7f211b86e827ee1dfc3613e7498030f070505
+24536d1f8a94ddb6698be7b963c55cb3f74b676cd815a7b3df4b1a0ea2be
+1b0b9a11ffbfd5b1fa49668aee14629316af436a0821c20beef7b3480847
+934a99f6d85b68f4ddf8859a754e009428af89a90d1852c220a607ff0806
+e8080726edc94d691d214b4521c147c4273aebddbb4a697ef16448cd9b2f
+c95293305858decfd406b89b9f3fdae2ac579e80cf321ebae5701fb2f7ca
+d8ed04b4a63115886d45d6120f69aef1a21d80ad3c2d35d2899f1902242b
+96cd349e0aaada40f7a11282b6b52bdd97708e58dc5e2d22d1153e5fa3f3
+b300bcdfaf98dec2f4e3c82a1c85f985735f39874f557579f422664e07cb
+e19da680efb0fc82c323ec5c4644c51709ac8d674608a8043c91e6c7988d
+430f10ba6ce1fc7fc0604fcd8f723895250aec36cc35b3fa14fe2a0d2409
+5dcc30b2093f2298f5f0a97676a0be66c3dc9adacfe2fc0f721a20e945af
+c1096a619075d5e9a264c796ec6c90ef1aeea8dc089b44ffc13d27cb2370
+070a52d4416c53f364393e46edd7ede00799960ce6e0d57e4909e88add64
+bdd2b0ebe2d73fa6acf8b40280daa0637e705c65aabd523b8815f22f23e9
+ff81e7829c7e4bc980c9143aebe1a04dc0d253396bbb7268bd5aeea356b6
+10d5dcee03135e00ae34388251f31714a1c40e182652c48cda2211a22cb6
+f02490e69a44cecb169754c53b16028d352e0119f5d5fae0bd7ea1cda647
+12a6147374b64244e21e9ec9f0d1381ad22d5b6212b26c3f9aa5f6045f25
+dd9f5eb4489ea39b1945331ac70510c5752557de21d0a6cfc1eb10a98fa8
+67b76da6e4249469f591fd154d39e89364a43db007aa0d7a911cfae6ce2b
+557997fbc44f55a27f622bd7b8b10ec9f5d10f2649a646fd964ae1b111b3
+5b46a252c4dee44e7426eb5739f24e8a390694597db3a1fe7800c97e5955
+8322f0e49a0cce2ad94b1e2d1026afa771723e3f523916f55ed866c9fb4a
+2f759651c613a2cff362028cdf9d38f05d4c7c6024c533e930b64b099fb1
+af04b01f5fb9ca6867e6eff55a772c5391831059987e10cbf987e3f378e0
+1329f73d54dc0484177d3c3c06f67397955ff1ca4ef8ad1606b70455255d
+631a7d6eb92bfdba14a0ff28b2ace7e81ad666ea9b3a0f5a6ba3b5dfe350
+44fa4b3d8ed956009c60e98cc132f2e84967f4a98a67b336d5ee7caf7dd1
+f74d1fa08619941361fa7312cf225d89cef97e864c8369eafab94d97f056
+5505d825972b754f6729596eea91210b75dd8f645382ace36de60819a02b
+3b48dd00f5485f9264f9fa926d732e2c267b0be8ca98526f124f97efdb86
+132c5ef16b103908172fc51f286ffe45ff253512e0033f037ff182ba536a
+9eb2df2d1db257d9c86c46e1b002fb32ac70ca9462e6eb48994752cebce3
+9f08abd4f4b0889283e55500702185a841e328
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/fonts/Courier-Bold b/fonts/Courier-Bold
new file mode 100644
index 000000000..b9f5f82ef
--- /dev/null
+++ b/fonts/Courier-Bold
@@ -0,0 +1,1652 @@
+%!PS-AdobeFont-1.0: Courier-Bold 1.05
+%%CreationDate: Wed Dec 22 1999
+% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development
+% (URW)++,Copyright 1999 by (URW)++ Design & Development
+% See the file COPYING (GNU General Public License) for license conditions.
+% As a special exception, permission is granted to include this font
+% program in a Postscript or PDF file that consists of a document that
+% contains text to be displayed or printed using this font, regardless
+% of the conditions or license applying to the document itself.
+12 dict begin
+/FontInfo 10 dict dup begin
+/version (1.05) readonly def
+/Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file COPYING (GNU General Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def
+/Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def
+/FullName (Courier Bold) readonly def
+/FamilyName (Courier) readonly def
+/Weight (Bold) readonly def
+/ItalicAngle 0.0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/FontName /Courier-Bold def
+/PaintType 0 def
+/WMode 0 def
+/FontBBox {-43 -278 681 871} readonly def
+/FontType 1 def
+/FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def
+/Encoding StandardEncoding def
+/UniqueID 5020946 def
+currentdict end
+currentfile eexec
+e98d09d760a3c22cf119f9dc699a22c35b5b35ed6aa23593c76d54cabb5e
+942bf7d6dd84f1664b89699c74b472de9f8e6df925f6c4f204e9f1c639b4
+dba988ed2ac419ff2b2bde605b8ee3264edd66412d4f21c64ac522bdfc7c
+5502f9c3f3e5592b3b2093d33c9bfaedd2d49e89aabaa832e23f062e91a2
+5032519d1868816e44b4e0747795003d7930299d6e1e2a5bfe0d595dc97e
+140989ce81d8d7f852ff9cdc7a1b1b598c69131dee005b415805a16d8a12
+3e6a2153daae5ac3449a45325631b26884c3dba4cc4f3aee0dad2907757c
+38746c947e2279cf35bf77cb28bda80e2a1ad4b7a8760262b6922d445d70
+152e2bc1747c734a8c63557dd042f7dfdf15714500691c843a6cab7d419e
+81febaad7a6fc0a5d78bf6cca52de83b6b9f297caaadf2318311eabb9d4f
+b4904e2037862be8eef5101f8723cb1f0e5a1d822d32210c6c742311d9c4
+5c5ab9c69dd641bf3b15ec3cd3f7bbd331caa9324279943c53fe43dba9bf
+08b854f97c47c79b6c241fa72fc1b6b667ee8c41a4e49e903110ff9aefb7
+5e10e007be387d5641c74ec987aef698b77eb9de14aada1850e45b854a2a
+5c1d9446910aa12bb3612a19b2bde6dca1f480b787ed5ff230ff40c3e1aa
+0c0b7a26ec3507d303403057d4b029565a0d0e0f8a3171aa88fb796e21d3
+f94cefd66479640c3bb43d915bfa3af6f3916f2aaae39dd4317563c226e3
+61ee0dcd828f688724bfb2a5ffadd07d1049440df6068a7d75caf8b11bf4
+d52c71c4bc22856d50956b3b892e2435d0d826801540d2b89383e14dd586
+03ebd7ead33174da5f0cd69391c18c79cee94a2f66bc5d3251a8ab9725f0
+196c6cda25a23e260eac31c9e8589fa4c03a4a98e41c2d53f2a0139f29f8
+b72f59fd64170f0271c2cfe03b618252daec5cb272e0db98566c34a6e93c
+421b92eaf5552d4ec6d08432407d44468b5c5aef4dd72ba63e738eca67bf
+bf4bff93864e589f73bc24737c044bba551a41c94ed39cef3f9292dd8b9e
+5fab031e7b392f802611b72aaa6a0cf1dbb35482650bdefa7ae93b4bd621
+0b8b429e9a5e53d1c1c1e4306f83ca3660abfb71018b1dd39ad40f821f88
+6fb4496e31dac11cdee15ada9fa87468c4a4e9840d9d4f5ee6cef4ca0722
+38452546db208efc3ce27356df02f47b22c92eab5b6d69870502c2214d01
+4d6c3d6e4595795b2fefec32348dabf6da6ce51a95c73b4008f0487abc25
+b2d9c6f82a9042d07cf523663083de6aa22a99e11f21127b9c618240f2af
+8e4f5297effb39182faa66e1e357891bfc37df032792d3c7de5a16f43940
+71bb4c54afa190c5b3fb36e7a809c6b65e03f1f1d6db9e485e0dc5a90d60
+9425a985fba03731a0fa9297b4dd5359f8e7ca7146a6eeade722b025d10b
+9fcc045b2e8afac2990da3a112217f9f10866856d9ce093f659ce5eb1066
+36de5a60831a6103a50105c562bd6612c741d529c5c10f6f3e230253164c
+6f65de8b784a9d6a848939ad7580ff0e077ebae7e92450a25490e0a100ad
+eac5225ef45f9a69da534dd649cabf392010cfd8b1dfac4fc1da6fd8ec70
+82c97b30acdc76cb55352057d6893081e9be58c33dab65c69e1aaf0f0da2
+0c3f4013056832a6b0a96f888719e9c6f899b491dc190f74896a4417b9f6
+6703de1fa0ccc70882bf613bd9e362de9f9085c5bf5d8edf64b9f77dce25
+33f64ec53c6d7dce54ae812c0426f70268229bf8f3dc54d583f1605d4e95
+10d2452aacf63bfcb630d796357c6a3bd7ab83a4c661e8e1b63d0b014b3d
+1bd1712e1fbdcc739ebbf35b81e2b32d0517eca9adaa1c504fac1d374b5b
+97c6a8adc41eaf81ef6581c6a8522c2cd145be35c8758391abefb4504e5a
+85858019428dc2fb59d25c95792da6bf1c6e0dd74fba9dd74ddebd475e71
+e625f9db53600369c23f69fcff80ff39767bcd55d308291d32a0697175e1
+1750ce440e80fac6526465a5814897382ee44fac82aedf8e3b035dd4ab9f
+fec2f70e9f744fbe8041d456e3b8f7b12af06bbeae2dc2419871bb8c7cc1
+3edffee6b27e517147c9849d74c89f5dcae2cc2b9330891078393906217c
+2ae704845ee7e519052da05798d73988d2c77ee471d72fb10def97e1353c
+ef2633e1855a2ef29c3848d170590443793248b8b84ee36a33c307fee7e8
+e4c02897557062e32da79c001050f22e9c9e8acafb45d7afff506cf43357
+aa85a689d62942b7cd3910f4538f9a5c52b9614639ee4d72389630091f30
+f85e275d4f08f395887ce66ccdb6e380a93b0519e271339b1c993b74e760
+42fd697b818baf83ae980eaf3ae0b8065557aeff5178d73e25e8b728e94e
+dac70539048fb10e6c7304978eadc4a5d3090a3837fc31b03fbb96d7ed4a
+e3c0948b27c0122c7fa4d6c8095296c3162eddea27a9997e75237691555a
+8a575e542e2d40dc1e20f66bf28c3b09bc1d4612b97310630d01c326d8c7
+2efeebec8dc24fdeb0b8d5c9945385a47543e6c4960a02aacf0cf5b01f8a
+66c7cafef4b88111ee5c79a76b0c949c0391e2c870b30f3a59ce06c52f95
+f6eb7e5aeec243c01b50d159a1b817dda7f6de559e13d63196e81e753264
+2e0834f9b13dd10ca06a91943b36afdbd7a4a26181dfed9cc73752982ecf
+c5bca1513cee9710990be028151445f2e2057457a2baf7e7b321885fd591
+cf4281992533ae0e4d4fdcbbce6539a4f26f4ef00e06d57884c77a9003c2
+16c0b65c04da36d68cc569edc075eadf9d7079e0f7485f32e0e54627db15
+39d4493a5fbbbec8ee69ec7f852822c51584a2f52c77bbba6752ceef68f7
+497f61e4a2aae33e5a630c0674bb6dc4c31d58e12d3f95cd3383d49b7bac
+e7a13694f8ff6ab5a7a683a94e9804c20bfe70740f600e2c5af0ab835c73
+a55f7f681d4292e57cf66198f1f3af82cf336c331f091a85796a72943a13
+0c3466b4229d4800d7f60f439a327f32afd0fcbe141f653dca1c3bffdb05
+509ecf1e419d045c56ac3a90f52700763b9309d2e86e0ad21a368d84ef4c
+077899ee5cf201365d3d90de7091ffab2252869ede93fcce320c47fdfab2
+311285d5b263140089a9b382f33ca61bc587a57d906c5db91e7a675898ee
+240eaede53b28bbac103e0c76df8b12c62a3937fc1aea81ffc30d69793b4
+6bbf32e1f05f540e2af2d7d54a77ef02ba9e5133c2ea31d78b041a1ba75c
+2d6a7ae1a2352b6101347851164360f1451db5e3e91fea53000210505cc0
+221c7c5190a436ac8b81e9a40ee834cd0fde045b0d46aaa4693df0370a98
+04ae7643d1de813cfd75cb785884d68687e8849422504e4a4f014ce400da
+6c65eebc9d9886dbe502ccef99a7088fe363a185bb75f70b022311917c2a
+63e2e41f3e9542cf2e4b35a7b42e2503d6725e7139c1cfa31c3c54c8420b
+0ff0e17d2f52b84216ab127e7c10e058ce02192aed9157198dd471f401d2
+2ad5efcc80c26a76f1babb2e40a4b8257ffc80a71e61cb8db7ba3fe036b6
+a70a9d58fd59bcc1696fba1668191f45835f703175c2cc58a5f190a1c7eb
+8e481b9a7d0d52b907b266a3041d20617c2c980809386de78261b9cc8c95
+188ed585256db375d9c16150d181e2f6365a6384d6f05d13d485f287c45a
+0fffee0c8147f02b65128c59f7d34973c6d5598dbc3d3bdd3614aa4d28f3
+3181ef9aa67b791a884ae0fb62437ecd42d1766f45dba8239f7b220558a8
+94548653cf8009e774ca4fc93237ee9a79ec3f58870313a0f8ab0c9984a3
+d00ceba8dbf3dff581753f75c4baba662175c52e5313e68533c26ac08da9
+888699ce6d34e311f71724e39b6b7e7092ff901b94257831d83921875794
+cfb5c62c42b8b0b2975aaf8854373f9718877da7a9bbb3dd0279a2bfeae3
+55e68a113859646560131d7e8ecbea885694acb6501713ab38b1c20d59f9
+0b8325e2c9e1792ea3ccc740d18e89d54fa6327ec913e4094304b197ff22
+80c6a3169ac17909a5bb002ac783d567d51da8b77ba223982c816bae1ece
+bbb77f871a2d205d8a1e74082afedf6b662fb4159326da561465d1848fcb
+7fdb8a0b33723525184e1069987c23e4c41ae224a0e4a338fd33d9f4eb5d
+718d237af05bea5d867f3b16472aa34e9f705b5463a09154dfbc633d3ecf
+a46b9986361bbdd5bcd3a8e94880555efc481985d6dc64c77d05ed0aa826
+490a079ae4d1ee011ef86bd83f7f9e65433a48dbf124f15ac3da0d5faa6c
+6daac1c4feb7db8b844307160e2281ff7a2d2bc6add43b354454d349a334
+141b4b1e29536e88f289e5448e5b26813ce07432632b5253393f66796833
+2387a1bccb98503f43ab4cc90b12e10f8d7c6435aacd62fc8ef32fb37d13
+fa0b0ff18ae20a6f2f2fd6394d55a8faff09ff91abc226412b0051c282b4
+b49c558ab001d2496dbab68e6653dbb74d210302a78457eb26ecafcbec89
+6fa58f0448387d17608d7a2313c222b413d3f32ed29b683d9dec7927fd93
+a8cb0da06b2e17940d195f7cafc6e5edcb31a8e00187900312ee9bb10205
+6c15ea233e2d43b7c6abbde44ddad3a1f2cbcd730eb5be1f3691aaaf2efe
+94a4736e6c4c753afbe1c005149918a4e5446b31ce005a99d64125c9601c
+b016a54d3241ab21eeb505c4f1cff6178366b3cbc0cbca2772db7d5b3a76
+5dc6db8b7116109f5df210a820aeae41636745344d07cf9ae1ab05a564a6
+a9c5eed8130780e93e0fcb2df9ee1b8587d8facbdc4e1927315df3a8816c
+955f19417bf508ae0524cd04ac53af19619cd938495e4c7f02c26b69a091
+f2f9815e4f8e3b95a610c3ba14a6d7724b88392e6b5edb8e9c333e262ed6
+82f249e9df395b94e7db994369ebf559103f9bde51eaabde3854ad5e6705
+1fbba7eae4d5968d82538732d640739e1f09d5c0d3d6196b7f39990aee1a
+43cfe9872ef0e98bcb8de9377416255ff057188d9f157313cd650451faac
+8a1fae3d00814a6aa4adc548177998cba4d0f1fbb0c7f6b3773260e6001c
+76b681675f5ec4884a166db439eb25f5d5f59a7124f0b2ed99160e3e779c
+b63ae2a7f118e90b180b45d097bfdc0bc95bc790fc8d7b32266b2fe22f76
+87502d6da4e351a7778cbccd31b3c83250c3d21b0151b77a05792ab50a5f
+635b2d932c312eab4b1c06bdff13cc6068e141b03ee8d8638e57d59ca1d8
+b8ccadeac057ceff070ff7fd2765b08576774c3ff51d885aa8694e14dc5b
+ff792430d9298b474e0e1cdbbd4b092341fbda48d12dbfd98bc237e1aff1
+8dfa7935261b40906e20738bfdca16b5842e2a1405b22e4990020448bc4b
+930912e4bec58028d9d86e7e15a64cfe183a94f81e2088ffdcdf5326bd86
+83b303ee08450941ba40646585043d863dd7d4cf0b74e6fcf96976dfef5d
+2616577636a468eaa1f41bae3d82f70160d02b28b318aaa9bb74567460a8
+cd4306667786f6967f39bdb9f210b5a8068e167b6ee194b0ffc9492ec4ef
+e96625fd470039a59551b282844c561b26851b9af6b3f3a6fe9aef52d42a
+81265004bb64dad894a7d6d0436729330762585664e8e78e4cfbf809919b
+ae3e4ec70b61444f8e68af00a419ebb7b5aaf66866a7dbe06a5106e9e63f
+6f19b0417abf32ab22b02bcf0c27af0e898533115fae686eafca9628bad2
+6318f254dd54e876736cebce827de16fd34f2df6afc7a9f39f5ac50164b5
+0013f26dda832d091ee0f772d9199d315ebf589507658cd7fcf22989718f
+2c31ecc18209d32bea2b29bd1a88202a7fbbcdca2023c79d07b886b675b0
+cf820450d6599af701c1f23ac1ab264d9c62352a2cf2db6885ab1b771aa2
+f2d037833454d0c6e6ab9e7884bad12959f9d693583432515e9c4e8e1785
+1f292b5859762dc093fac6d1c4d75f83e6c47cf73b5fe390a161ef0a2942
+640e8683c33cbee292aae8cbce89e2c1e8dc99dd4bcc9a511a7f00455381
+9d85c390eacc9596e67103cce2c2e86a4db07462396620c11b6e391652bb
+358f82401a7b47fc5693b898df7eb1f7a7df06be166864b82498e7a4a52e
+5d78e2b4e379cce4ef1aeddf8093671378edb46ab0f1aa7b79fa1c0e0a12
+4711cae6fbe2b56a74010ee3696d112969b81f3aecf99bab36fa9317fd9a
+2e590a8d1cc447cd24c42995d7b04454a8fde2e589252027392343a11785
+780ade0b3eeb8bb20b63d1bd61be223c44bb8e1353d0d3e37c122aeabe22
+45fb231783396f758c9e4d09058b8f63937468b8648c2764a90b5785a729
+1600ea0699edde3fce774c77a4e8388cb3ae99570ecbd9811ee8f973a6dc
+ed78343d1104f0a10a9bc869ea473da3005d36865d01598e1a6909b711c3
+77a4b4bc536a581655a1b2c2b995e6632434cfa8ef7a794a0e808e6b53d2
+ce9831c720ca03f28c7f0753aae26f5d6a6cb086ea57c92589e9583aa6bc
+3c119436870043247073287061f44efd734ae7102c9a090907e3b61b9dd2
+527cabc63f2f8515e3f8ec022ad88c6844a731d163af292c8f30ec988735
+8f197190cc6933745070799581b7a94f0eac5c9356799ea0f201bd54d1b7
+2aa0f4a50b2851d69e6a2642b762a88870319a684e9eaa9a1b064a3bd2e1
+1ad4dcdf3a977257b6ad3683d4e9f4f678efe74d4a4488274ed980ee6efc
+072708b5358a1da39464757670c3a12f2bcb2505d8bcb8d46ae5a8c88b9f
+1754896d8d7eea8b1d76d8e7dedb88d67f796f76c96b2eb6e0e7a8d10cdd
+d649ff25850fa3834852623e99f264a8daa93ed145f1b6512a75a3ee49d0
+ebf73f90eb6bc75ecc057465af931b300389073f54e5e0a5e1340670393b
+8333548fb4c94404b16d0813a8481425e9ad09be5d8a4f3eec6239f7b141
+a03b428d45b6e3c981c3ee32a065f2d162e25b6bb79e9d46e1838aa510df
+9d8c71f3dee637a97c453c0c26ea8af68e3c004c8de997a6f5a0e2713af2
+7d8f98031233c6bf5ef5c103e5af0862ce6ea9d598abbd08350b18d9ea84
+738d7565cfcfec7f9743b5de7e9de5495555390b0ad89ce01a5a05d6c53a
+235aa3d89cf329b2f4350b0d98da4d4973cb5954c6d639ce367e68776d5b
+a8df9e793c52f381570e909db6121be93919c354722827fbc24aeff4bc70
+fcfc4fb7f49759a6cf27dd5f54efdfd060abdc33d0d1f8ce051c0c026e31
+17309e09471b463deacd1cd12a345fe382b8ac4ecca1feca0814a4f74bde
+a00d08e65288b8d05dd0c6d8b2a323c545e646ac06e52f5bfe40e25a7604
+fb2bf49b2bf6527cc4f1fa7dbc9e6edcc63a3e5bd951a25eb13ff3bd2446
+c8ed32670a19f7d1706994fad9bb9ff448668951ca02edbd950b8233005b
+aff1768a1cc2a44da8e0125e637a6bcb51bb64af227f6a3f7c7ebe4efa39
+5965d49b13b8aa5f1d41fae2904d82092c6c2588b38182891a39d72f1eb2
+50827963d6ce5dc80493b3ababb911189a6b73ec0a74d9de15f0dd992fe1
+1ade383677d02792a720b83ea21ab3c631c9f7058e69749306a4095eafbd
+82b8df219e53243f7cf2efb3c67e169f766302a2084d6ab6dacbdd12a67c
+a369aaa02d22621481c03a8d43763d62d2be3262d1afba823cfda91992ec
+f80cdd3656505c5399118ca13502d03b122c20a2bbbf80aa6642773a6255
+5fb7cee5debbae611eb2d443f2edc24bb153dc634cb6d6b3724972445ba3
+adf97ab075af2a95d2f1bb74cfb2db1e435130296cee19bb8c157eb8db70
+bf5cfc1e791f3531d3ae33554a4edf16070a731bc8b7c74a84bb3be0f2bf
+45560cda74b4c12dd718c62803fb4f4aba5fe89d6f7cbaafcfe4bb518031
+dacdea2ae6c8d0c03bf60a9b060ccebb4858e4cfe1271e316bf7afb05714
+c26cfa91bd96d0622da31ed625533b2502064eec23257b4785f4f0132f3f
+44b0c2b83bb642dd8852ee7f3777956e984735f5d16175c4a27e9282a4e4
+ff0cab7938d921d33dc7e8b62ae24a90b12646b3a5fe88fd944d8309411f
+6eb3031abb67fc9bb2889aec45821020561c1519243773b448d65bbdadc1
+5a5e155b8d1b368cbd97b756a8952b428a358c398630b46e8afdae238593
+c3fd589ec46b77b8d82ec7e1ec5a50cbc77ed54bc1e2426c61d23a08581e
+c1d71c0908f7759d1da9241b087618e9f756bfb86023daf9a7ca0c4eff0d
+45aa95cfde5aac1977911ec6b202bb47547e3b5bf3327e95f7e1a4863e5b
+904af4b37a527e34282cb659a22f85ba406bccbe3070ea53f65a876b9d1b
+9a1096412fef8706be743153d4dcac1681a40a2c265a729121f2d3fc9efe
+0b5c18e002626f3023a5ea705b47ce1a5c537122e7c35af7bf31f66d05e1
+aa3362e68c1d259fcacd0079fca7ef501654744e294e6818ca3badcbaeb8
+8d44319fba9042e25a8250599a8eed5e1c0cbd9f739b7db31c3b18128176
+50e72c970d3090f8325e5ca01fc85e5310787db8dba0ca26d77f403c062a
+647f9f998246f26422374859de43542076b459b7fa829d27182324262532
+99fd3886ac0448ba12726ccab47af3cdc60fb69dda6513c83e0d1277ab88
+4d45ff3976536a13adf80939cf1a1db0a6347f9a4f76ac2674ad49a46ef1
+d47ee4fa717c493131e0a5212c3d4ba134a7a6ccaff9982abe9f792a9179
+87e59dcd1984b5994c8c89b3f9f0878cc3177489a3b9b41e44673bb253ec
+deb2083f4293ed9d24223cbfef26cce564499158482912879082806d048f
+1ea999ab3cb216a5c27d6027468b8aff4b55fb319fded4ee2d308c0f8c96
+fb7feca02b7188bac0ddd4bee03a577e91d258eabad887be25e74c296f63
+bfda0da6709aa66b814189443c8b942be557f260606e0e2c5c0822ad4a5b
+33facd2b90ac826a768ccc37d2591dd28f1e016032bae587b12849d2f9e5
+60e3f8c07cc50f256ff209c9cfb36cf921713e79cf02283e14e52cdc3ada
+d81e2d2adbfa6f1a2c2ca81cf97fb68d61f8c51f8c2d70c59a940dbc31a1
+c0401d41b9c1e5906e6f9d2d4446da96d36a0d4cc8977e665aae5c431657
+39b2226ba59807a4e54fe9901d9e3dfaf531ef2b29398d2d10c24fd2529c
+474469ca0fc17c2c06f670348545826112e834654bec7f039d11990dc823
+c479caf0b9ff71f983457be488a36a54d9dce40b832882eef4b698bb1758
+5ab2c981b5b42d99a546a9c50b56227e76786dbcc6a5728009a707a5c8c3
+9f65bc6d10474296a93833fee38992deda4cee623ab3e672737be803e984
+2003e729a97cffa1a122d9ab0bfa587da67ba7005f51278e3a06a752f86d
+5a8b2f0d7a871ea29a2c3b7260fb62017aa44a696d3c4566b179c9eef15b
+67ed2961683b8417500b6136815823d50eb25f68363adcdde84ab6560227
+69e776795bd5a97122755091c2353598b5e0e5ab0d368fa34cc903993089
+a4fb5539f5da5c59babcf26470065e6fb8df09ef54475a3651550331faf5
+093f96cee0b9c0e94a894acd650d429672e1d66ad6a0027b7d24e1df6bb5
+6e9092928508f4e356275f668ea61dfacc1bd86fe40d9629b8ea84e4c337
+88ce61a3fbdef32603ed42a31c12817dfd57561a1ca265fa093b5942881c
+2a61d2c536bb7d6941879ef6371e1aca84fbeddfd0712f6bfbdd69020265
+aa13bfc463e3fe44558fbd405c69db3cbf18b5ace6a111767f766b8a730d
+8b0705cd5e46544446ff78213f9b2844076110f1717cfefbbfef27c2c17e
+19bd949688b30f0b4f3f23208331fe6e384d4b4f9bf47290f5941df19888
+f78271ed4545b076b96b4e21fd07ca410186f4cb4d723f1ed2cc6c172819
+c346f547e74f99c1cf2bdef1df01afd3fad2381035d516d1f02c650105e8
+092702a8becd50cc295803140ed1ead5bd6fe180816cce1608a582787ff1
+bd66a511b044ad430b97227b61a4177e90f928dcf9c2db0521163be22b5f
+faf3300ac9c039aa436df8654eabb946f64b6a2c4e5b8cc7fa9c11d2cb20
+9b20b92c6e77ab808d474af0041eb80f0b6e635a5f322dd58e1194676999
+2a8e58791e2a08bb0dcda337e882ee421947382a10676c69404e420f3dca
+b6b6cba7bbbd806848fc80ca03eb3a6fdfdf5ebe800f17729f74d72f4e6c
+dd5ddddb891b3690554c04694d39e05f5e2a1dec0100cdc8f2fa39486353
+37d906db314a739f6ddbb748d048e59759c0e5bb93ed6f8313d3aeabf523
+545691769560b501f46f622962be61881ec339ecc24ef0d5a3a66a03d31c
+48be641406539cf845c3dcf4d8adab1ccf6ea04a642644dbe77ccfff9e9c
+e5546eeca7b5d11959dc32a1c09f9e499346b2ebf36c91554ee265da452d
+7b6479c7cb2474113d050fcec2b826a1b6103a1fdb4aed700586aa0b36ad
+df8fdfb4006beec2b075cdb86ad3bb56adde2e7063a3996dbb6b763c034e
+77ba04142e741592191eab60df5e6913ba69ad04963cce6efad86f260d9a
+ae0959be0496413c5299ba27f0c96dffbf5a20135a828dfa5bd116f1aef4
+075d1c4ba49eb90105bf16686869e6da641e3c2bb4b4deb164817616ba7b
+e9f1062f85384c1475185b342f8d10ce389b82e97803700e5090007d7521
+68bee8e937971e94c01cdea21364c05b37f60b86429005750c6d5272296f
+9c3be508d85078c98ed33cbff0411cfc16ee632034fce12ea9c060ec7a12
+f843c69f62779c779a1b514a2808f54572756bb8aa743312bfcb0130a6ac
+0d4c21f790369847adecf452ba675bf9b863bae1e494bfe82a76ba37e951
+7e5ac3418b7f817056fd84906a296c794f77fb8e266ab32f1fb546c9e97e
+435588b749c3d279995886f136b2515acf4dd303647a13f142b70652f7e1
+b587873fb85dbfb6b8c0eff6d40cea9a4c735a7e0a796b3892a40f6cef4b
+bf8f98c14811e2b5f72c20fd2d8d13acdd45728be6efd29abdca3774844e
+1e1c85291a52ccd541d1842fe987dcfae7aea6b546be6508baac4d1e1f88
+c3772f632197600522e10a08771012b39fd2be0dcd415cd93e59c6ee91a1
+3000355b9234cc603033dd74577297100892fb8c7745df45d125034fb268
+4bd4d46476e437656370e13537114b23575da9ab9c57cd0e7c43865049c3
+fbea9b2ad3587da4b5b021384115867408666c11c1bc7e345af1dd4a2593
+b76335451f57fc0621e2712fa23112c4ecfcaf3cdc5871d392fc2b3f09ed
+b5b87105b6de4bf26548925cbf4595bb072429b347586bfa436c10d254e4
+cd1542adc1f72c0a15ee0eb3e21de33ed4192fbce905d16fba1202e45c00
+7bd1ba5a5bf4f456a40d22d0326f3fa5f57fe5335f7bd2d74c3c62f33d1b
+2fb3c3754928f3bbb73396d1e64fc4f9cbf1a57bd2513014c4b49ff68be4
+162d8173ad1425afdf02a2aa32003db6103861c935e54655ed11aefdf7fe
+421d3e46c2324d0940a6dfd0667dc4c483be82abf8e5eddbde02f5b1a11b
+1ec4f2201ca9fda9077aa5be2a637baae83a18e0d07aca462fe53fab3248
+4c4d7929f830b6efd789b22311b6141aa20792c29698c0c0c9683827874c
+80b97e6c8fafc623f8e2776f34356a32c0e7613ebf491bcfaaadc476ec2e
+b904c52e3a65d61fcf4d3baaf68dd8a2df3b6b9958ad606dbc16653b1304
+f03bac8ee4993492879393dec1c3b9930f0edcba5542c22af1aa4d754f65
+3dc8e4f76a9298e0ae859c6c13f8ab24b3349c0abecec29e895516859d5e
+276c73fc3804d194ec154caa7fb3803809c6d669d86cb75a0109a25fd481
+24be0f89ccd2479961fa11144db0d626e32fee84aafe9ff793254c2c28cc
+3208e4c13bf3feef165de8433cd6300fc97ed20e0b482efa38267e0c19a8
+02a795c602a0f34d3274dedfc3928949f16dd15b811f61d682ff303c0be3
+c9b142e434897e2c25c96b9b313b4642e6295881a5a2660dae267240e8fd
+e3a4b58dfaa10caa5de3a730486727a40307b4470b94624512485ceecda1
+9c9d9ebb68825297aca37aa3e5bec4c497b35dc10e86bbb932d5e6a03f95
+0bf45cb19a9f5cf7234f897e163491d733b5510790eb101855b42d82d233
+de4656e4ccc15c70d3c19a367c7e8cd97712520831ff302e59c66bd66081
+92c29b17f125876a4d00f8404c745f36b87abaafb41b20854b8a71417a45
+be9a6d9dff71ac4935e79d30e6657e777bff19363d6c588829af564b1b27
+784bf9c5169817ed2183b0cbd4be72575dd484bf6dc8a9234f54bf079d59
+d5b82796cee38efdbc30d9f39d0f500582f25a729a1f86021ddc17e00174
+d842d05f21c4d6f5d0777c99fd99f5bd7aeb4a8f8997b6aea54a3c336c8e
+68585ab5f654648ef3056012f35bd4b322897777806026a0d405f0eaab93
+61d8d6754f1b660eee091695f39b8fa5f6fba1d55b33381a567447906bde
+e9892b2bf755353f893cd9d912bb8ccf1e0d30cca1c6f2d3ff552f56ac75
+c3c6e892282910da2df650723f375a68dc9eb64ca74a512741c4a652b223
+db2d25ca29d272ed2419944c2f33769926d69f291d2a462d105c53dee439
+9172c11aa0763d48401552ecbd9c8babe6b4da26e7f9623355e430768284
+fa9b53667ab67b06216c05ee54165892d5cc4435a0e5fe3db1690b8c7043
+26def9e9e31a659ae206f8c60cfd663f91688581a0179c9b7b9dab97e1bf
+5f24fda6ed339433afb20839458d18bed5491be9fb118bcd3361cdcf03dd
+f67d11767f7f7a421346dacf711d375bf519fc93753331e1a091fdf603ca
+b41f0e6c48e100e78157e07eb10b30c6f350a146cec0d3d1d0e944a69e85
+2092909fa54f1b4377ad4768fbebdf5334c8f1e326ecb154ee06858342a2
+6f3b58a9e0141d57c20df8c4766be3203ced1e6b24fa2a98bca391b85b7f
+572d49ac38e4482733726f56d5ef42d3c952db9db82d9129dcc30b4b2fcd
+d20fca70364907701bd19028622a3aed72569cd8307e23e48e6a9df04da2
+4bc0460cf88b75dee4379a7c003a6cba112415385c43058a46899d6302ab
+560536e59c67f462528a81213d9c9009fd3975a3b601410e989efe3a68e1
+65fa0ae6dd9c0361e0626f1851077e8ed9fc4cd766291c7f3df8e51e2eb3
+b8e9274798f32e2dfa3d5a08abb61061d4caf45cc837309747df9b0d565b
+34d0c04a2f9ecd64f0df422c7308ed27a7b5fb8a5e5d71c3003914643d25
+8895a0e2f136c02e5fc6659dee6c7822dac93f8e0aa4b5a52f09c2f49d7b
+9a7192a22fe8efc8f5142d3791d3e11b88fa8c9afc2fc568df02c40a109a
+b94e59cd467b9b0bd9f94003b21f522cb5c8b191a372ef5583e66f5217a6
+5d3c7baa1375d59bbd54dd9af7139501b74a2ba74b87db29ac78f1afa21b
+81072b58cac2df329f5a7f3edd6c42839db170cbfbfc575ef172b39c1859
+87141f257d0d6d909c1a95fe10d313b8c0846b80c07ed5124adf1d36ad7a
+f729dec052b2e6c61609211ee576454a86a0c2e6ca0c6c0ff1dabab49143
+8b326088d16ea1ff32e69871cd3f5a5cef3848b734ee20e2510c97c5753b
+2629b9eb302c488319e384166c59257eb0454af6961b87a7569a5c82e1d9
+f1bcd84379a590b4b41166a67ecff44890c105d16f3bc899b652fe115045
+983ac7f6b7d63b5339fa99cef588f822516e135ab40fcfaee90577bd878f
+92ec143bdb5fe5ffae78390ddc3f7d8361759dfb3996aa5dfd331d9ba36f
+2901c65f5e4a6c95a9400d6316ad745e680cf8729f23bfe0b11b148c74b6
+0c36c2fed2eb71ec5faf4d05ae962133c1b8776d1d57bbf46fba30a15f33
+344f26dd85411b16546e1c9dd963f1b334026cdb09ab973d1fa615381847
+1cd310d73575d3e03902f0bdf0048ff5efd1beb2e857f82084b743e10091
+d3374593ba944d05ee97bf0ad7568b45a95a24f49f0ba2d93714857665ea
+9ac457a90a63577f7293fcc0d5bdccdf610aa823f7db43119263fd591a20
+f3f6d2612412bfb5783db3c0865eecd1e7c2ca50d9dea0ba8a50a4a69ee6
+7899bfa6b11bc58b31c98a6b8cd63633dd6ba6e41aff7de644496942b7e8
+c33320c23f0aaa081098d555df9bf66b4af6cba3a71fc9fdb0a19497ea00
+17dfa473bff4ad6badbc6d971157ce98fe123ca2a5711ef9360feaa0f40c
+6069d15b5b224f32f74965d97fd48105f43ad74d08b0b2beefbcb3d301da
+be707da228e802c22734254ece98ad73c080dafa09df15b9340b84154a2d
+1ba6992fed3674aa9a9e002c4d40353bdf87edb73e61318aa003ae7b388f
+e9f8656fdf575e190509727d8385e50b871ccdfcd4fd1813801bfdfd7387
+48042133087e98a8c64083a4b908594dec38ac9c6efdd26f1e13cc59a203
+abd3887fff0638c51082d32a328c3aacca59e173d56d3b3bf27976c6bc95
+4572890d8092e93e35f188e2255d4c223d5d9fca45bdf433121f5f8bdbc3
+84f1c0ebef83a8ce7fa186d413d7fbde7a9d2818eee5a305a57afb635b8f
+f6635f17cb030b0d29ebd19ce29cd932034a3c0c0922c7202288f2a3a13d
+1bbe38506a74046dcbacf7d89a2001785f12f3d885871f9950ae34ed028a
+98b5373403bc1322d1f2c583a8dc11824b4283c233c8744fd56cb20fd6bf
+0ddf76fef1d0eca5a8755a2f15df0329d098033283664aefe0c59eda92bb
+25e4681182e20c008c73f9c736711fdf3c5ca41acc70f320949d0a32e5bd
+0bf4829de9484836c8183542f12bec32fceb5a3bfdbb1a193831cb7539fc
+12f181fab95ba610379821a9a02791dba3b2f154d13788bd248d3b9469df
+01bb9ffd8d69c10e347773c781559ba77f50c172e32dd77ade64202ea88f
+9b22ccff86f1f221741c4c9de7ee719c223860446539488e6ecf7eec8c71
+f82b2a3b54dad191dc7972eec0a571e839c733aebe2c557beeb5a69bffa2
+64d60f3f6d1af9fae5e6da55f9b5e54e29c978a6868c02f936b89c8b11ca
+876d6595861d293fe9a250e723a09716167f20c00f40a3ffab37b236cdb3
+691edafe967e72a69b87f69db6e98d32c976f9448575464c16f43666ce44
+76840b89c880acc159e7ea9623c9c49c4cae911baddaf128e4e336e41b5c
+76d4df9464f7a66ac0787280f27b2ea2cc03637d6a9e2ac6d28bcada2c5d
+cb425f99a0b7b7677b2b79c4f59478c1e0bfd24aef199621b2211783ccc1
+b4dc56da241203b399cfbc46a80cd1d172c25a76b55d0a070c00a17d9e22
+0019121cf06cee286d3582fa02f14b6c0ed78ae52b960f67d6d5331c4e6f
+29c51a14b401714874d0dfe0fb24d264e9f705812bc67b634ad558ec2347
+35566203199dd558fe5297cf1cf5cd5492c93056c5e0a71226481fe13e5b
+ba28b11394fced2131ee45efb37e12f0638352ea688cc6881bd182d9094c
+88552111bf87f88ebba5ae9679354cda6c8888b172d46635220fb98495b2
+6469002cb0575a6360c4b6909672ac06f70ec588df117bea075ec89e865e
+577a0def15804badb8d42ef5c6d6fb70ebfd3f49a5b218be90dacb7ab625
+353bd54e687c4617fc10a5d5010758c64ea0d6581f4f3d4fccb7b90ca9c8
+85b028d29f838a52ad11523310a83d61a73e72a9b12ee941c37906e37b5e
+3f5a2aab32f410561f3682a81ccf959ec63d96b89fdf96a78ab04b236e50
+05bacc7974f7c62eeaa245ac41958ca8fea6ad3fce5339e1739a53127964
+2ceba426ee4ddaf922271152084c4cd08edef50edbfa399de4972844fba6
+8287df1a1d98783774f70ba7655a9f89d64bab11ad3b55459db4ab7663e2
+ad5dfc78bee42e887a2e76b511a159812e489159acca2f0a249a412b1ee4
+a90a46dc9ff832525a9b0913244ac3ce5993e17674d1660563c6d54d66b5
+dde6b64aa76f003ff3533a46ee56bb913b6efe0e9da6fa4e5319b607d53e
+9d7d9636805cf8c3b3947bf195ea25cde547b4450a9eb8ac84146ef54d76
+93213061897bc96ed821fa57c0bda3244fe4a1eea3def679f45ef9f67e10
+b5decdd3e4bec89701f553bb4bcc6d4d1e0fb8c9090b9661196059b1bf1a
+bf1be04d6b74a5cc57e40971884911f452c33b58cb04f2c6fe3e1d71bf5c
+b13e7537d9fa6d65ea935ed5e96ef72363bf78322a8f87bf7a118a9deb71
+b7f246aa676cda52240974e6e9da44d622e4f2a43d7511b83a0126b2b92d
+0bf1b02876e523d9d0a492b5a63d96b1f47e962ee7aca6fb9d3f9aec47ad
+c522dae8aa718bc540cf5d7031a7d3d16f0f6ff33a9768290a90a5fc5e68
+95cff9dbab42a770bd11b787b5078db3de917f923c2eb6ea11e76136a8be
+e36eb784788ea3e2b9d7be95e6d4243b166c494c4b754c6dd160206dbaf3
+99ae4902d3dca7424f6d1e7c455d562023465d0aa9de460b1866d7a52b5a
+f74e923d2fbb49c4470a9e18497bd332f3658806ed19c6077f046c5dc0d0
+bccc1d40ddd20d1dd36627d5394f9d38159c84751b355a8e48754c6dd160
+206dbaf399ae469b9cc7bd8e3d141479a7012a045ff72d51a448fdff39d7
+8be6ffc046e5cf07644c7ed0a1b85cc2398d0f3ad542d1103d2de1f3b341
+bec7d28674961f6b7d313b85f908f24f4d18080ab2c46c61f215557c0d81
+fda6767552c20b037eb4c97e39dd51300a54cf301af3ae93dd0f958d422a
+58e668e91eb14fb295d6923ffd65a2da9a88fa3fe7f9ade3d733f9eeb54a
+127a12f0c791d09fb12fd026e09a8232cabec89a8ff39084fe111795518e
+c8beabcb9e2949d3c58456ff16dd187bc906ed19de8f6d6a2a639e1fd66b
+020c5ca8e69adeb77fc55c84ad5826b2919e09bdd99a537f5c92437aa9ad
+187ece2d245d29a9a0d54ff6ec7841bbe6d39d1e06b6ce3b19ea98823e0c
+31a18bc564dde218b924e38baf75299220b281cabe0c940b404dbcf54d19
+ecd6f22e99e9ecbfcd8a5e225d29d4535b20e4fb69b6662a3af13ec34c1b
+58b8684aa0c7ce8d84f6e711534861328a5e4673d4bd6cd059a16abfd8e1
+573b096a3aaaea3274474fb3a97d7ffb167837a37df2bb69f4d5c31a1bc9
+0f07b0458ef6c85e51cf6163a409d01f67513c5808c5772f8502dd958987
+ed822784d7be448240dbc2c6a9fb7f6885e34e0b842667c15908ce0fb4e5
+ecb4966369ba752e6fc2f39e15caf1a41e441a27d0bd5175e8f50cb46042
+5bdb499d75ffcbaa6606e892b21400db3becbf3aa38ee38da4c333c4263d
+a152f71dc4baff702ea1363a0940a5363ea9b51b1f2a71a1b9a4fdd19152
+7fed7e2516c95ebff0e7c2ce92c50399e18386ed3ee39a48b2da92501389
+cbc1f6501841e867f8b915a334a0abb7a92b2be3af10de37cba4823f932c
+2779c3b008afb65ec03edcec847e412af7787f70c79ac84c58014e8d0e41
+6446b36a50c9e6175726468d9f399a1861431a8bd311ff0567723aa35fbb
+650b173663ba31bff558375f740346216bffd472986ff37bee4aa3675645
+a83eabe1853aa061fb3614b78cc780a471c3c0f5da378ca90ce67f21247b
+c105a3bd4e4afff439fc158b9aa90fd0e850b1508355bf0152225a2c22af
+9e5dedf038f28a11a2a553128c945086e84b4a146617e905a3a16faa485d
+6a5749a7067aec3d2def0aada7436fb1e185bc66d0e30a7bb33af458e605
+ec978d14b6181d8d7e9debe27751a6f5fac11594f6605cbe638d9a98ab6c
+1c3f6c3125a57dc55158dba2bd4d36febe0a8590e80afcbb1340c5553a66
+8ef2d6f5b4305a9d8d38afbd5759209f9eb9cd1cee0fbece6de7ad2aaf09
+6dbe472f83389d743f0d7aadc6743f7646f7bf3a9f73a23a43f37d471a3d
+6d12de84e83d2cf5b41e84f1acc0cbc4cd52d0cec7388f34ead47b45692a
+4918b365eb9f6e813d9223a95fec8de3d3ed7ec85227f8217212bec21893
+053f74e652bae9299e709fd25b9bcb82e860c0c56bce1f787129628e2499
+130fe6ef76418eda7cc648d769c6f54984dea92af4776ebadbe161d180da
+9e5f3d65cac4a7a40ec3a3a7c253581597b69e7526f3e10d619e614f0c2d
+c4f6feba37c1952518fec11b39fbd13ddc21fdeccaaf95ca8fb8d7d6089e
+1bcf9b574d9d8fe5c25a82a0b68b90f140b934eb585af7bcf8c88f9c1c1a
+dd745b02a7e19db4407738a4ed928c83718005a401b77a56622b6c8dcb3b
+26cb5f05ec5fba7f85b0a6a81a0d8e75880ef357d7ad551292d37c7eeabd
+7220af71edf267760571cd3e39af320bbf13c9ddd8053ef41cc81e425b32
+db025cc66649055ae1c6bc468bdcd6d69d3ce334d0b78c45785dfb709ff9
+a77a46a8c660f684d61b3643b2bc838b6e983d4950ae20436173e93db372
+1721546fcea7a2439024051300067137313b2424e1627e053532bdb9caee
+519e9d23ed670d2d5ef3674f225d51e1ed8e082c5fc9f5f9b934c0238cf6
+5b3dd364b466b2aeaea3d3241c59c9cbd3ebf9ea9a7dfa2eea9b7ee86f0f
+7e256ced10993751286150e663580abb541147835b9f14b21f528999160d
+492d9e74b01b55dab2c2e2643f5f20b0f4ec4e8a3a2df47a38fa1d36d755
+2ffb34c1d4c8152e29b7235508e01f79d41e1f2dba807e4cf4a5fc87aef5
+98ec07f4321a2c17dbcb23748bba86a2acdae6b93086a2e26d52b0a10f83
+ff41cd291ad0471f09e62a79bb75e18e680be66da6f3b2a56a8f61cdc1df
+9c7fadd0814370dd82648db161d85f8b2a9a0e51deba297a1250deca1af6
+944d89b7fba2f313ef3d61757dfb7c2801778f393b2383989f16176eee1a
+695f967efe7e04ee79ed936aa121ab47afc0f0809911a290a0fcafd2b0fb
+6cfc059ed1b7f70513a49410232413c1dcb607a668cc18043762ef224dcd
+d7b5d6211ac228650e4607367d4fb15959b8126dec175061a3ca7f7b01db
+2dd72dfb56756ece79fa61a7c845336ac412bda4347c582a6f5e25c9cecb
+66b6d028528f61f0b77f1bc603d20dc104c9462fcdeb290a5bf9633fe6a2
+92b52098f8503bed17548c05d836543f7329dcddb5cad7f89bf26ddefeb4
+912d2c1b3bd40f92aab21ae60fe8c375b960f99e499ae14cb92a5ddab808
+7ef4d41f4450a680c4549f33f2b650dabb0e06f418fb62bb234c2877ea7c
+566e3017b08cb4c381caf984191ba7dfa4e9784ab4543c20a1832e63d0f3
+62448cd2ee72f9a45a0cd74801dfb32c6df28b83c2183d13d37a21fe8f55
+354e420ad334e5e36ca113a1ff16bd3d142751b50c122254e3bbdce4ff28
+85d2c5e4d6a57a37b34a2593f51d6ad89cc225df6b8465f57b6cd034ce66
+e5e86ffe880d507d72933ce7c93964becf15481def7e649e4a1cf96d0e78
+17357dfa81bac3b335e5eb95be5f0e27aa51bed0bb47d556417fd0079d64
+ba1454ff9531c9b090eb6456a8e52544c1bf84a84187671f6c18f7269162
+bd002385dd60dcbde7c5fe69c34d004b2a284564a9cde4e3887ea78d5698
+ba791a710fbe92c7988b361a335265c707c2f00e4baa3855793fe2798ee5
+f3c1af717279ed9d860664996b26095506bd99c8a72ae7ebb45ad74af44d
+6ba45a2401c195e44f1aee76743407a12ed6bb80701e68a2ea02f0dd1af6
+320b59eca2c51a38f1ce6b8d1cdade6d9a745c219a311d646a3b069c44dc
+d226f4ec07cc1b249f651f1a3aaded284ddfc8b8f8eb33371a522823fe2b
+9275e2ec0f4721522a0704760205e8b924ef1c2df09e43e3985ac4d3d496
+0ef19cbc76a77a76ab47e41be9ccd032ed70813c2d4af60f916c510f9df1
+7c5bb577ffd1cd9c3f583e8bc0528b87874638621285df554d1f8b16c4d1
+183e71a22c772c362dbd1427980c002c3c0112061e8ee485d19a020c6f0c
+ae75194d3847585efacd14e2a1f5cd1c8d0e9f435edbc06db63f1dcc42b6
+b8f381d22191fb0f74e34f73b1be39b61d231fe723315de7074133b1e452
+090331eca04f6c383eab1307cd9022ab21e97643c5ff3296613bc3ccd860
+1f406578b6797a228acf6663797b7a7592b665fdb2832898c95b5b814fb3
+e45f678e37b709a23a5d88c999b8ee47348d60e358f7cf8ee72069a523d6
+c74e7c1692dd17ed1cc4535a42636f534f2be5c3b2b15942997a9b12ddfc
+28d44f215db9142e31f198c5e6b0d25fb2ea77bc0f9c8ca42d6ff67cb402
+33e8396ed168b90a3ae58027944665049e54f29164673c4bfcb602890fae
+dd938622e099b93f0939b2cad4da410e69c54259286c8ccf3f77384c4e22
+fc432b44391bcb5be60a6642970357b89191ccb4e5a85ba87be5ceaf2712
+ca6577a55419430c32bdd28b0cd7a6179e833712c0e17f700c31228ff8ea
+7446440dc3fd05fda08c17ada33296fcfb38cc26225ce290adea1d4e26b5
+361ad604d8b08a80636f5d0ea79e16cca7e1a3f3c59cbacf59d252d989a2
+49752d58ce58480dccad56aeeb0a5c75b89a8a6670b7dbf324c0887d3295
+d982cbf0e2c4212c697d91fa63d676d3042c68c1b19797b07591050ec23a
+ff48f141a6a7f3869dd3d9dc93f35ec26b388f43ad1bf2d106e11b35eac1
+c20cd5389511ac69973964c761d32c80e5b64e17c1072c8fc219286320ab
+0eccb5d6c5e2865c998eac3519359e41b2f4afbc30123bc2d0a0de19ee06
+d42dd254db2040e2a2594475fb01b90a52a4178f403bbcd9782c20c8f18d
+b6d72f9c6442f1d0c41b94036ad8bdf9bfedea0b96117a93f04c3c4206a6
+bbe324a255a7f18841d09f976085737b87bb897a984dad2cec5a44c38306
+48e373096da6ffe8e637671b820a62d31dcebb108b5a2b62374c746da5fe
+380bca1e486c3daeb1b9034abe8980b89e0a466dade7a0eff5c8364df55d
+25943937d78fd23bb599fc4d241c7ca6c23f337355d846c3fce08c82e21e
+e124db9e9f1b416e958d91ed2c21e26c3b6720d18154b8f3c41a0b9d035b
+99eb5671d93dd6d366322e15a5bf740c261ad4ed24e89a6df117a414ea0c
+1392691a58b068ca538685c646ff893029357fb8e567855720e803528dd6
+0040c6f061113d9546f2dba4fa83edf6732c6dca4338e14d3d577291b696
+02980b2bd8cfba079e11db2228e473600ed550ae05cd85a1cfcffb645e68
+5654ddcf891b8e4ed4545708f683f57fbc680a18992752f5cf2ec471ced0
+a16bc4363217f9767b684589803f3e6e9efe5e51e9eb0be493de3ee91c45
+61b92a057fb03ed4f0df610ee47f89efd4b1b0e1869dffe2cd55f0e0513c
+738a024c9e514db72c6d387dd63f36dbec694179a70bfe8c740ee2a13a95
+0601f003b83f07bbd035f8809ae347e589302c1f9e3f3863d66ff1f980c4
+8224591a762132041176334ec86f846fbda4db22ea5c4e13c9a80195d4c3
+a8379516f766c8078cb77f67467e2c11a90c5d287ba70e9197f9a2cf81d1
+34e2d939410940a6dfd0667dc491ec1a705b2d1433ac0ddd052b5d1520de
+a8d313bed949de251d7090c1efb589d8c7c4460df3f453a88fd966801a24
+4249b996ead5d21d7294f4c4b9920252b60b0e8959edd9bbc4cfd971a6cc
+e8b402eed87bac510d721956f7200e7b6eccc684774e471fc7777463e74a
+e1e0742f3a9f4110514726ad5d81150234358c95735248e06086770fce74
+9cf6034db5e3071af9ee634140303466baa467e5d5716263dd9291b4cfe8
+56f352334acd0af4c7d27582b3894d294ab287d3ca49b788d7fdf9dbaca6
+34f1a709eb39c3dc65ff732a3dc5b318c9e52dc0b1af189101f02498a1b7
+8f3db2ce24f0003f20957a676a67ecaa25f57adf4f1e22c48c66fd6ad0ce
+33611a35ff2e1fb51fbf4f8a4e19ea7f4cda91cbd64937a1679789b90baa
+549047bee22b3741e3a04d423e041c09afc847156f96d9452bb8e18785d8
+c78313e8aba3852ca8dccfc8c8a69d42fc9eb366296ef9f33b42582beb9c
+7f021bc6c9d27cd19ad3d88e19e8b8303c550ae07ad8fed1519ff5ca68b0
+7e9b97695fe76ba74d04a8101077620ee5a154d1e3d1caa090cb2b50756d
+ba0bf5c9fedaaa3e7869b8272fcb27b1cafdceb940d825f9b7beb7eaa516
+70dbcc38de9ee3b28792e30d2131c8f2f47f79db6ca4b1b5e2f3063e686a
+6d6126707eff0a60a8b7ca850b9f8f91414069354ff0ca285743b3fb3e70
+aa3f3e58cec9d01cbab862d1856d2cc659d1b8502a64b3f9892d018d700c
+3d92030b114b520ee285ff1766db12c1fdc5601c15345c6d33a3c4a994e3
+6b427acc7332662596f2d36f24ae18c15820d0fc53e165926f701599a391
+26331278e31f5dd3dddf8b0b504a6e4dbdd453630beacce725de85ee0c2d
+d759444a157f5e75c65188ad0dec71d7ca53fa5d8f6d1a3ff6486340d81e
+37d8cdd0400f54faaa350cbc232e62c7953a35495730dba62869a27ca03e
+85ec5a01b90848a5adcc9575fb0e60c3d26ade2d72886ceb3561af2b3bb1
+2f2eff9358d313cdce228a468da566f95a61987000720c62abd67fb7b9cd
+2cb5d5f74be8e0919dcb60a5364b1735d31fb3fdb59f9c22f0622f8df391
+294c0c2fed3bcd185c9d932f097bcb2c066b6f2b54613f30ee99cfe0b3b7
+08cfdd0565badf6e1e7b2041cf016e3b3ad1a5c03be3316033da091c0da1
+7473925e79e78f8a3f48ee2348b2a51cee6bdbe2a22244b3ffd8e2f1f6eb
+21a3af001d14e8954e80598937ecaad0fe81a030269f9aeb134350836da4
+2df81f22bf35544daf3d62ff87014d3d62ea58686e5e182d930a2dc3fac2
+588b49b660a22c3a55bf8c99dec4369d1d678210db13535c0fb346f0cb9a
+8c35b29652e763300876287ed1bd8ee4408d586f2c27f3c11c7cae9eb111
+3b01d521a91b24c52ed8f9e5e122b159fa7247af419a2378ea09a59d7214
+7396372a7d1e6d7d533d0a0939cec9a27c6bacc94bf8eba620a10483b09c
+a310ca41a6c2606e2029f3ec1e612afcd9e5302680d1fc088ea26d835531
+f157e9d4530cc97cac29d0de3bb879970eb3d781a222b006b0fae97e6233
+fc47d71f1ab194e672cc5163c4052eeb88a31ab3a3f9a59f8215cc729e27
+1e5db50036b810cd95cfd9826884ae6b1d9e9774747a0a9df039a77c7ac8
+3406b9d23af796412550524df48b18ac8a24e3c79c464a253fe332a3c183
+99fbacf4e2a0c66f152c9f89957a628b359070c773eb7c7b08745028825a
+fab05b092089a598ceeb34a1f40bcc61e05270be279e50ed9103f313a0ea
+b820f053b53669330e8f6eef4504a05d08178355f2c5162c0106a46617cd
+0b424fc04e3dad6ea66bf3f3aabcc63cd504a4797a7698a486eaf5220445
+7f0d1496d62d27a05717b23bab14f37a8082bf9b90b8bc82b19fd98404d9
+ac23ac738af0e624808613538d34f0011ae775adb361e330db975713b672
+e106228daa1c672eee1883b3a489e9f375143e9563d68d1775ba1513e779
+0a7ca7468011420dbe03f372339a5e354aee018dfea076dc8962dffbb443
+3506a5bfc44b0512e8a8eb7d0ba0f81f5b123171a69b2d42ff5cf8a81e89
+a831e006ff5218daf44f25f7e046c6b06bb1b077778652dcf6855253129a
+41884f86db912e57d7c4e06d7dc8a116ce65b628399cb21bf5dd8f9402a5
+a116548c5653a3083e412b537fd8324e6db3f15df83e0185cb8d4c5f132d
+df1f8811e574029f3efa0828f9223e318c0a838b2f9203f707f2254e649b
+7b78757e94056d90f65df04c47e73bd7f5cc5772c1253f1f141567ef5435
+87add907f206187b611235c634c97761e4834077e659b60ee0f9d37af855
+6018cf054eaa400a820d87b72f33137eb2fa3b8c3f8f0e6f21c281cb940c
+0fa9fa00589243d32795125aaedad9d7ceba399ba151f8af63bb3820bcf5
+e59c2bac5eb8a453c8eba8106a05e6c84603d2f91628878a94810ebc9c75
+d951cb4916b4a4c8d471bb739d26984c7e0a0dadcf44aacbf5983a54d979
+9b20298c242166c447b82e7552014a615d21091f33961b5b084cf7670a60
+cee6af1919e4d128a4e15509607caa802093c5668be1d5fd5403b9cc135d
+2ea6c2d9182835e4be3ed5c484b91448aab3ca396f4cbab5b6d2943d7a04
+7f51addf7dc9bec7ee4f952bcb09059b2da0b1ad56ba99994bad26ebda9a
+a2626b6cd881c6b7ca7dc96e7985d7a49c7ee9d035bbdd013ff89bdb181c
+1c2d078159d9059fd4459dc967af31310195a3cf9bbde2422338773f5cb4
+bbf7fb3723133bd398a39fcdfbcb88acb00080cde1eadb8019f151e3b1fa
+e7681447c9987afb4df465344590f47d20e47ec4285c5bf828fa3ba2e3a3
+3ebeb484f413fe1a0fa6aad97f900e27416302a6aff179260a206999db72
+035222b1bcd1ee30f6d202e25599b536dcb10ce7b0c283f2543cb7695726
+741d1a477e0c0db1d1ec085f58e6a8ea91e05eda30f0f66ed6f3a7be7117
+0643cd058ea61f649bcfd9db22a05e8c0e264ccdb0de198ab6e629ac4c40
+43280269f0be430d6adf70b881f56ed5112857fa0ea08ca2bf9e20989c12
+4a54c7498bef5b8d627bf0b42d5d03cc063f8eaecd3932956769367c720d
+4043d64b68aa996282eee296c7f441a226ed8159b166e1aa996d24aca65e
+ce80b674e97d6f7e392ad6bf593ab4f38a3b206ca0cc3128d847845873bd
+11b4293043a22952dab798352d72cefef8ffe015192ca8f60c90d314a8ab
+238a13610382f9f8ec1d8c1fcafad7c2160d7ce47ef373c0c55d7bae9b21
+148701f7a8c0e7cc82de5f26d7363d95163de187a5709820e37bbead6e14
+80246152f5cc865b819d29512b967a90447d98f971f4c4c28c2979d07cb0
+e6ec8d4029dc64aae3dbef8eba571236212600ce0acea3ea444e410c53e9
+e5f1d9d52215aa05e690fa3483cbd5451f4311cd0fd23f39d4e106e69d68
+1565ac01a60824243990cd9b034d3ed1fdb5c0752b5e64e2e417c6b64d23
+c8e45af1b45896ec877c2d87f88f4f4a85d0a407b1d1137f53650c134669
+649806886c2eb049edd7f3b676f52345fa6ef9ab4a418066e08a815302f3
+aa8ffb5fbb75d12cc3bac7d9ddabbac644c2944a44696f69d130e3278d9a
+e457c39c9965e27dce8a47966dab125de8e110d266b7fcd6eef2d820c029
+fa60dd328084faf8ae3b6bd0f570855bfc557e154c7d4931ba6d2e4aaba5
+27e0d098334ca38c9a78edddc086cd1f03bbb8e5ac740d6140f67d749605
+54afe94dda9e1bd3a55c4d591c34ecc27277fbd621ab9dab7c9699c11c88
+010ec97bc46dd1aad64f0df42c25607b55b88544455aa872819232372508
+516f71cfcb5c72b4efdf280fbee2819822cdbbea4caf86273a82d3f050e1
+42e1e0b8b628e34f28f43d57f70718498f4690dbb3e2cffed13b81758457
+541868a14d0c73b9da8f433ad8a7ff1d1ee38348ce1a6d95f625c8c87287
+8c46d87c20e9cd3d2c4222d45bb54d3ebfeb30e53cfa6717b52a9025925c
+efd17f795f78df3babda2beae6b2c1995751c334fadecba5981755bebdd7
+6034871e1445171a71f60282e6785059cb4046ad0bac98d5a1e5668a2fc7
+fcca3b915875fcd0d529a635d64cb34387cd90947d3c909f3d32c4eb40a6
+0f30c3e1f819bd8aa2a035dbc3ddb269c26270244c224c3a93ba4350316c
+664b2ce7153b09ead7d39bc49d6ef04c83703e8b74e6a0232c41a02a7de0
+5afe0e94dada8b1fe6208f12b87e00ef8c65d58b02466ff697d6467f66a0
+3f34284e6342b211a00225a607a556ab1d4c8c42a101ff675d951d0f5a75
+2f2479ce3ed7a4f84488d39f622ee53a54c3202d4e6017832708d41e5338
+13a8d67076421fc76eb25c6b6373f413f67b01d6fbc1a86d381efbd14485
+c715984a13189d77f70af8035c8df5d1d23bf2535245617911a4bd580689
+41e006e7d36650fce069048bb0bcf831d3606f3e730ded0b87a8d3282ccc
+5ff5f8f0dc71c4e0f702dc5b8a8eb71825e09b692adae6793f0bd6dcd92f
+5ec371159f0d61b7e174977766910a5d2013af40264e55351de8f7b7077b
+058918bbddec5e4dc7fd54b83b0af45f11a71ae59646935341bd381b72b1
+c64b82472cc9561f1ed5ad6b5df940884f6574d0304e5b9dcc28875a8ae9
+7ef3fe34068e2e36fa46aa5cbd3dd87f92ee8b5639941300a1034f50fad4
+60024e46c2710dbcff25e3d17a9c0c7697e318b144a77f0a39b1fbe910cc
+a9a8d8632c0ef2c285d5ab8d014d0b2dce8d7b0689af0449d1a22875cb7a
+a6d8c03b544e872ba804ade461c9ebff87461641bb7b9e1e68d13adc8f41
+13e2e08e79b0dc30d59765814a47a64b6a33143b9994d42b767e000e44a1
+a77e5241dc5a9464872b1193df3187c690274520b46c4d2c04d04284b58d
+05e7378d471e34444eed398747dae91728b8b1f3099ab3688d4ce7d82705
+a6a3df49e761f4c59e071e3e1d771ca1b8a60c359bf076e8061d148a6dd8
+04813a596c54149faf1bd2e25dc44ec458af5e2619a418c53b7eaf9cc75f
+c21387ad8b7f8e5e98483cae7e86853890d74588c87078c58237ec97dbfe
+8aab8488138402cbda5c876b43c280efb357342178217879909dfef65a21
+979caff8306759d8b475c3dfd7185074c185e4222deb781fca1c2e7b65e3
+d7bc788eabd2a74551c5bcd2d07695107673c8b38c53cb425e03e426e1d9
+88c4726e6fbb988ea28bdaca5156393213a9cb1c26eaae7b9534e2d25083
+37f2bfa574504a4f7a79467e97511ee052586288b2e095c41920ce77034d
+52ea9d07dfdbf3f094d7d15f0f3dbdaf3fddf1d44a1f51d470ec0f6723f8
+2bc0e874bd5c8d1e5f0530f65e6b675ffab3cd19f1e3bf6a226e3ecfd2b5
+018590395fbfbbe588621cdf2e52e1483794c44c6548206079f1b998bf31
+11772db5cbb8caf6930f225373d891e19a4fe62cf8a4309561274a329a3b
+eba8f589bff6cbc5a5d62d2ce038d3b64bef960b4185796f506c9adb0714
+f47738c76c30ecca61a019424d6ad5ed46bed1320b665c4840b514692f9a
+6bd0f93c53fd71ca297b3f00d9e7ec849a256e63a647fe3164dd2e3ea365
+af25a5c1eb26b13b130cae81be1623a0c8db75ecd68806219b7db3acf4e5
+5d504212e473044465a6f8bb66f730f28241f3159953ea3ca4af93395bbe
+9f1b5a1c3221107ed4cce1c509f522bb17279049041d75eed831a0f6a676
+286db0739f5d9efa13a81c3d38cdec6df61eec011451338db2bc6e5c1688
+605fab1ccfeb842de110d2047cc89138774a45b3c2b174a4241b9959ab39
+d6378d2a1bdd02d200290cff70a5fc3ccabfa166381c47f73e3ef81c359d
+35610fe000371e6cd4f38e525aee9c02fca862c8cc0cc548a846928b50e4
+a1a5af19a7cab7dd540d59eaa930bfff69cd67294d470bdb0e01090f7d07
+11ff287aec4c95f54ecebbef45ae68e07b20e6c9666fb2355a971deaaf5d
+0e77114787d579734e39c222a01456756f7d05a079e7c728d8aed34e28b4
+faedb5e44b28d3def6f351d4abe40a2b02878a4747b1ad064bb43ac2948c
+9d62e3bd6d3ca32c8e062552ab41688e108fd838c969db1ce8435f173349
+a96e2f0b156b9c7dc2b1d9a3d5796a664ebf0b6155e5208d976a95c6da4a
+80ca7cae016e466fb4ce4ecbc9cfcc9f46f389464ba21e51480286fef055
+318d74da79a0612ff316db41855794559ea733ccf0f964626da329b20149
+652408ad37595fd2a7869ad30752421110d0f31b395620b82b32e4db7928
+0455adf028a57c60cce7323e7024023fe9cb11c4563925c1e69392929faf
+046c16813b00516ec1f55fd6544595d1ea9529015a17cc8106709241e35b
+69586c1f00555f0fddfa746a26764fd1fecf101f63c4f25a75b2649200fc
+5c77003d852501153afba3d2a5b90d44852e14e6b6827e6f714481bdefec
+7a68b232bd483565d3a31de86176b2ddf0a42fc9700c643ca6693890127b
+842ba5099908bed877d2a2bf21b69e1f9acafe691fa684f40efa7f297f0f
+49b9b28e64fdb378e0e66ee7567142969c5cb92fe90fa1905b0a5c354a14
+edf705b62ea069248b6d3e7eef1b7b26d2657561a4da5cb3d27ca9be8c28
+3e23a0531cbc9992ea589d3a39a629a94dcfda7bfa0347c852a3ada2d631
+a2f74dd19a7f96a23d61a73e72a9b12ebe45f3c051f7a100517d5f1ed43c
+0a0ac5961fcbc0987f9191fa178acb9d15fd971740952e68eaccbdd70839
+6b6b6b3995976fd8a571e5253ee8cf1cc31af523dd223d13d4ae62e93226
+d83479d64352d7a51773bc123a58a24fc1190b3a02cc5ebd2d34a40240b1
+dd775ab4dd9041592604ec01d5a96de6120b37cf672aa912422003ff4f93
+8ee571b98d190c9a43613b11279d586f9d40a0bf94025161363af525a243
+023eed308423d27bd6246077ae64d38625443fd13e78915f88e284021009
+568b9e2a09d9f750b92eb5b48a60d1d9ae227ba47cb6fe49b1c51bff5a79
+7d087fe6c8458465cd3358bbdbb54fd6263c1abac697ac380f7417dfe253
+6602f0a76fac74c2492e524fb743fb614cc49f82bf59fee542a6de34c33e
+bd135318680ec14b77bd72b0a5792f0d505198133884e346d3d3a8da1747
+a5e3413563ac750d6d2d633a5c90ab136bf0f4c41e1900e1da555570796d
+d7c66f4fbc0fdeef00e7754490d589cc4cc257fc437706cc104e00903428
+1da81e74fbcd8c2dde3559a5eb59a67192bca9ed49ffc49b605a9daca194
+ea025c51c5ecbcb3a7900a3fbf4d1c2b9740fa767704ed75c3b58c7b93a5
+35bf43fa7b0e1e0e696b6c3bf8fc8905f4e5eed80c239bd19c9534922c27
+86c2f9ff1801d2e1e0890e1a6e61918a4c904ad8f8b79e297cf2beaec87a
+fbaca9515dc987e2dddc40f21c5a70d2a93d8d0a626e6e6184a2cfe85f86
+630b03d237d15295c3c5046f7bd5a24f59a8bcae80909b96ebefdf6ce2c5
+823b1352f5a76adfb86a6693cc2cb654ad09cfaba68e2338f5ce117604fc
+5c037512857e43ac097fb024cc5146294ea0c753145ea5c2f16a18fc75f6
+8d0362d4475a1e902fc341a3c82ee30744179d39c3e529b96b112de50711
+954a42ff30ec777feaa3d7c23e0f4da5d0a53bedabd6e46457aa6292585d
+3a148a31f0559e85556414bf2e9e0b62c20ab24ae5382a6d25c24a5d54b2
+672c5689c3ff74358a6d211f4d44e185c64b9e952ac2d60e6d9c816d5e19
+d662d6ef1d18b380935b2ccca31066fd7890f9b4d3c39d7d4a116c16d895
+3737edfcf511e94910f1bcc3a53109c6a21e177ad241ba16f5d09c711ede
+5943009c7b8b6a02976c33c38d43b873029097dc5a93841898122608fc4c
+f3acdcca3a2cb082d8aa4539d8243dbf363cfbdee338879da264292edf7e
+df7776a8d12bf4953f1fe319760a0c6b6275db4ed1b27135132062eb4b7a
+cfb2bda8b2dd2ba97f524d9103c43e81fc0ef9e08af1acbcf0eee058ec5b
+ecb04a1cade9c23d5e50dff7a8fb2c813f4f921fe202a9648207e95cb905
+8d76c6e34b13ea3c56c1ec3f3bebf98963fc566ae80810bedf064e32b75a
+9dcb51426697093f3571af3618619fe007d0c52bf9da695aaf1c2aacdbce
+03e88f208a050a02c7eaa946f41acbf5fefc03e790d08867e255e687b664
+a130c9f2f7537feaab9a431ff78bd2f70f4e3d39ace81e68a83877e62623
+05742e7d16dc3795c6003fabf015ca563916ab7b60fb7f6efceebe4f9f7a
+05f120b9638e9d77801ce319d199a1f15dafaf49b53ec272ea1f3629d013
+0d31eb4854375f171268866da5ec2ec7fe612bb9f8308c2e0df3481cdb4f
+97f8d526eb04dc57d9a84403902967516b7d6ba894583e74c5c9a24623ce
+a44df1772e2acabb5c0e1fdec582b1430a73587fd5f16b784682c0d02a80
+112e2044ffaeab3580f3e4000a25741d0899814832457290be7651b8efd7
+2b485f95d405c6515eccedc45b9bbc76b20676a5f6a91a58501e68f96cb0
+be65def662cd1db19ea8031feefbcf40353b7059476aafa33ba26af93b60
+956aea6d789ff3d80ed3000f266a2d8773eeac7fefd3776da65ed01acf9b
+43175602c26a538b1df061bb3b524f2a6ae4dd052e9ba288b2d35feed1a2
+f325c203072257db68404dd5b9aeb63d441e41ad385f170ddd4aa559296a
+cf4266c7e3bbca5b936e6028ab1bba4a44c79b4700b29fa2ed65d8274b8f
+54c17de9f4f151ed08c5774c1ac53644777fe675355dab5e54b131d64bbb
+aa811dac7925e002f62bbda978c6ece9b7c51c22573702bb08bd218606f2
+a7c9c8abab1b262b923c483730b4e6235607378a6b770a59845efb645312
+9cebc86eb8302e45fcdbdebc88c8b5b3115925044520195a42dc010ad771
+b320083a839a7149433f59442a24eec08286051516e97aaf096c4e87ee8e
+89365b9d4cc7c81c71e000b153a27e74e0515ff30e401252114dc7d4b1c0
+1fae5ef32620d74d9d4c61b63c5d753b3223a9c7267dd516d1cd18f7fe5f
+a60f8fdbaaa8778d79a87ab8901927ac870d580b3f9900b6eba38e830455
+8990ec4a85fda0ca6b3cdf97573e4d0736adbfcf366596f5e34f59f9ea15
+d38e4cc24ef808066457986399d309ce2cb7fe2c1d1ba921f1198a91766e
+1de4531980f5477770783dace9dec59922614b1fd88988007c6adf10ccee
+e138efc2346390fc88d1adf8617e4e56ffa72092913c1b263584089b4e1e
+214213f56af447678a4573091e3edc3b6438c00539d003006bb17aba98f5
+e7b9cbccadff6803b31e6ad941990462fe1b935c67ff9e4aa4b615b2855a
+d28841b296841a9f1a3bf86f9e3b1659d7e77b4b6e07da31af84c1f57e50
+20cf8c5b352fd4124e13117f3456d1ea3fffbe24a86971b712525505104f
+44e260553d10d65978a5ebf7ee66c7ac6603e7be95d2b9e8126931ba1389
+6987f97caea5b7ebe1c54069dea74b6157f19bfcbea2e59ad575103291eb
+36923f31341b9d12c4cedc3ed0383f19e6ddf36ba52652dee81e225691a0
+0b49aa3fa21b5d1a3b70663345263fb59bf0d71667a278394d71616312e1
+f8b2331572b7902fa2968d69ad3d42a938d7e6f9e9f26309443a6d977c64
+613501839d09870f02d282d91027738c17d164384bf49edfbe5859017052
+483a385f3d6c23c8ec31ee9e07c5761d85d6702be4231b95fe357bf67271
+454d8ba54104291df51c2092823d58d7d450c992eedc2b59a720c7195790
+44dae147b760ba9c83f66e2774c36352ca242d4bc6dfb07d15896edf5d07
+62a1b9491bc4f4a2ece2a0c44eb8f3a4e206be87c857f3c3ba01e7c1b329
+d7553a2f5b8c17ee6e339e5c32c75a914ed933c601676dce75f19f769737
+5650fc71a01feb7c88cf93b0870889df962d949ac0c672ca5a63fb9b6e9f
+731b075c02bab9297ed2318099bdc3d2eb26821cf90a2f388a6962c12108
+9bf34d08e3ce5109992f30b9f8e8b5202ad03d03d0e0001285cc4647d919
+b32846ec23fbc8c9106bba7a493c81b3a58bb13dd5d7a43bb6622ad68c84
+1d7f1136f895b1d49496887ac7adc49444803a164a0a1faec299da1c1ab9
+64fb75314bb9d7d4aa04ffb3575641f77bdd0f7e780eb7cdc17a88218c18
+e710e0f8296ade21fbdf35ba06e80aa6bec89f1b2a03076c6daf3f0fba84
+5a5b881402d2c0335b687b4030409688963f6dac5445094d66d33d78a763
+b6f500fd4c9bc8804d40f52cf4baebc6d35da9cdee7a30b70fded0f18587
+a17e08154070b0a38de000351a89f44b6cd66608d8a86844f90d88cb257a
+4af9c67f155036e833d5f5d0fc781dc98b1fc1b74c42822e747653d06600
+67daa7aa765471929ed4e38d9cd69bddb4707fb1d11d1237b3a5064cf8c1
+c628e23de9ee9dfecc4bde42978db529752a3a84b912467569ea3f9d6f40
+978896b86417c11424cda3083447f5c2df66c25c5502ea424e3a6ddcd230
+e649ffc82b3bc0168bb999bc51081b36bfe61177aeab6cc744d9947bc5a8
+938162c79a268e6945c3842dfd87b77d148f9c7941cc629d53547da93086
+30eb7bd3e1c0f27f8ac28ccce80ba0aa0060f26bbab71d175707ab60902f
+fbd9c99c38d852f114f012789673189b246eb64e098c5e9dd197abf6269e
+e1b4adfcf68c1c7b3e5231780f4dab3d4305a18a898ae3d3fe4053905248
+c4ce72a10153702987e2cbfb01cfeef86a19ed5fd00666ff93f1f47846cc
+bf216d42439218abbc95e456c07491a7c1e46f1d201c2d806649fcd234df
+122f89b3b6c0d864053ac7126861a71f40cb271c1499e4651e52a49411be
+51c646d59ddd91dde8736a0297885a0e0281432f254408acaaec81a374c5
+060d0f077677aa42a06b4dbc477b460f8d661789ff0cfeb829abecd6c06f
+a1adb76f27fe5381bb009bd05bab346a2d652d2478b0a8c76aa6c998c972
+6e87cbda66f9bc62fc440eba14c7347014b26e84f30556b8724bea81bf76
+d34263f8e45aea56841ebb601852c082016d5705a7300e8be1276b93c11e
+6bff846f1cb5f37734c467bfa64e935897b789d5985ce3da9a8eb80b9736
+5df25e5e875ed16584566afa3929d869a3fa9cd7aaf47b78939812fbe18f
+2921b393d788f75bf0f0c62a5bd25124cc98844e0e4edecc25d937df5670
+0965787fc4d191a33db8c24ffb2ff5504a4e6108e5fb5f6612db56bbd7d2
+f433fee1b8f0d780ec4f7640b4ffc01f352eb398b7c4116ff43f93a118e0
+56d6d820bf3b41a7c09ead1cc4ff9052421769c56b4599387eb08f750d6a
+6937b06cca4352a3f4961616eb1239ef592d72f7a7801295a1ee3e9782bc
+95ea6832f1b2715ef1aea0f4722e8516fdad1bf4145cd261032108e7892a
+8d040771f86ce98994e1b4b5688d59d6047a513233d86d3608ac4da4cce4
+cad778e366271c1609ddc506304c65b750b8bdb935ce9f0e0db5337d2e50
+715a21d1dd04920afdbadb6a416932bdc697aae5ccf32e9970ff05a18ec7
+6684d125607e26d371ef6e69172bf066f7eb6f527178a09b4077aefe0590
+a8bf000a9f2d483689b75cfd02571453435209ec995e6c072c788cb3687d
+6306d79f771ccff4214df3e63c74e83dbf2baecd472cb129fab760663a5a
+642910713187b42763e8a366c5170a81a2336e9881f5166fd9e0a6ff6c04
+b3b76c3562e0f1df47075ca1be9a79d58cb392f9d9f6b55c49054a35ace1
+b3ce3e8d3c81ba1959c167823375626eda6ca3f9d64c23de7a9f2e23bd32
+15bf3e65830cd8a364fc533ceca8b67b466172d70a891e4b3fe35adcf61e
+3e1f77717fa3924b7bbe8043b9815f9777a4f007792d6d6f9942d02445c2
+b0dc07b4510ca3352359aa3162320d3470d0147b1568b8a914e0df108c2e
+5a76d2bd7d58c8c2d7403e755fe896aa7522053b4cb846bda0a4e9b56b97
+a9d089e3e7416e6b1dd014229b90fd319a45fe161a0e3092e604be24125b
+51f3e7161c64fffbd2ed9eb48bd14342cac1e3030c633fbd6b87d28529fa
+29a5456799bec81d581c3ce827fcda2101419b119a4af6801c945c314f80
+f4d7abf36f73e3e75279530636fe09344e98c368240b9e4366d9e66a6105
+74ebee6f31cc111e83e0544ad321cf2f62f8c530beccfa91c5f3c5645d62
+0ecb35de6fa3dad76964db3a8307e8928c9a18bcb72d919fee70f1b97588
+db5c18e16bc7453597a1f20d7a9d9131b002a56d4c368d6bf69e8bad4e0a
+445c76fbe0af2af7c74db79ab8f767fdeceffab00c620d038fde8341ad14
+6887045489489d680e104129293a3f27e5fcce7529bb4a2772e504054157
+2c22532bf50aa2fc7d4b4db9a6b38e2668ced8fd5fb34b26f7ed5f29df43
+a5b17f9f1fe1f93304e31a2e17ccd8f25560f16074b1dca25c11e086363d
+3ebd6139d32594cd59a2d8b600ac9ee7c020d22b4ace7662b349824c926d
+29aa5fdc9c1dc4fc1718b01d7a04ff71fb10181b05cd613ffba439285862
+973a020895586a0543281cb6e94ab185d3fee9c8caefdffc959ee7ed5101
+8d527b21dca5ba42ba2e3a8a77dba86e64ce0ab27e9b5db014001bddc890
+db7f61e0900459821a7c7063db65136e8af05a68d26f6421fa86e4ae6265
+3c6577ac9187f3d6410bdbd7c8109c9d244376afd4b783ca00473e2797b3
+85c8585c1672932e1547d2183d84adf7e6f8cf420d03a4e78ad171ac8d52
+f443c76989ef51a0774c13711143eb00ec544a2b7421728b79502e8bfa2a
+394cd0cc15af713b5ce0bb78e716891802a281bb8fe6c5f2145b66e64dff
+6509313f3503282460e4c94ccf85569b1ce5840fd638ef514fda9de8b1b1
+e877579cd47b8785b991641a481ba0ef4603580c8edb944e27f4e92935ee
+027e2a55fbaff992f79e03f7b24268bf93b24ba6c604352d147ea9b337d0
+8e02dbc75fec7f50ad4841ae655106764153e6e08c84a2264f2a180c2225
+fa1e39ac081f3c4a3e3383bb9d5107ecd076edc61a7a80d9ae7f55975b60
+76e245f08ec36445d8f05dd13748995af65fffe75597e98683e688a24053
+011bc71b699ae161dcda835a2aadcdf4d9a82750958a39ae685058ce74f8
+91626e99497bc82d62d235494dd83f87e46a3756823e23434d47ae4f35a2
+dee83146805fb5e28af9e2df7812497ef6a45bad66df7b29e495128031cd
+96564323c75a88b98e7333f6f8de1c8e7526fb5f8c1110ffae4bccfe32e5
+32f1228f7a094f67b3518e00a071897f4edb688bf9975123cbe1de0895ea
+0a88277a69a5d7694c44b15ae4b592cf3a176ab6e9693d80d9b1b89bd35c
+d888b764920e865e7e9ad0e8266f17044ed652518d87ffee1dc364422f57
+621afea9160a8c795d44a6ce0c22623aa8af5a08cb2319f335e7364e1070
+6d6c357dfdf082d3ebe3b0503f0648b74aaddd538f5805b11eed58d6e50f
+7d7e6e1a631e89c81e321f6ba32e13a2b72e249ab2dc31e73a23bae59615
+36f1637d1a1ec1f9f777c755e72510df4e86c0acb8fbda3fa87084fd7153
+6ced250a8f31851f0c9b4149a4ff19506ee0d6b5706557b831e09c687bab
+ce784dcab017c4a62cf39df2bf8b25e81b29f8e11cb5a1f4f3eb0014560f
+bf1b8e47319677e83064657dc222f4b89f5ecd066f0ef92c1993d16247ce
+71aee7c8b464772213ffa7b8ecc9b4fc0bc307832deb605e685f6ee7d54a
+d064424e1279e2a1ec2d42b1d293e396ee0d8432a5a0dc32e5299aa79113
+201aa5d2207af42b4b2e617d80a5aa4b28ba84d0e572ecff34fdc202b672
+63b2900e5b8a204af2272fb388c0c1c1c23a8a821b6fb3353bf66c5c01a9
+068afe1e8d70107dc1b88461af7412400ea89be6d9ee48b306629683621f
+af5ad5f9f87b8db31d792108412e4e317b0a4fa1f80fa197315232dc5d4d
+d2a3a3b16c8767fa33e2f227ccb7e75fbe989d1d51e2322426bae35ae94c
+a87356c5cf217dde81adf0625386e8104fca2178217879909dfeaf3c4b49
+22ff0df7b742fd8e53ff06ce37ce7ab7da7a6bd83e753314b4a5db582300
+1d7ae54e696f0fce5006491f9d9fbb4f415f32c6cbaca1e0ece08e6f3536
+1ba4cbd36ab700e7d65c9e7e6828c7a05ef347ec2a433f4d14eed7e00669
+5638f8c3eb83436d5d47dd655803c25fa1acae75067071cc968969647250
+cb082aebfe199d763f534850ad7becc6119c88c36ae5de4dc01631c74b23
+bfc0be2062dca0f40c36b986d06f756a8f6ad3ee511b73b94a21653201a8
+230c66de11afc5dd11f0c7bbca6eda4e20239610d1b7c39758395577a5d8
+34ce808c8175d741d834b184c865c3d8a65c787313a9fb607f977751526a
+7384c153d94b6a929db265128ee0eb7da9ceb15f793384790317c87a4a2b
+18e765518e928dc5cd257d1734efd5f156134530af79e72004c7b3ef05d0
+e1fbcf09213699489e67aaeb39598b718baad866303b5601ea56c178042c
+25b5cb585ec12a336bf74bb3e655959e6f859e6312ec1872eac58fe94966
+fb2c68e160b4901a6fe701da607eb6e371e2a23d2ea43754178f3bdd6da3
+e0dab513f2cc03dde85de5f667a74627dbc8c9324a325ccc52c2ced30c66
+15bd70bf7f59869cc9a2d5757b6a14bc8d2596b949be75c3e6a338edf1b1
+3cef3fe2a02de729df56cc07b5cf2576e971584a9727b84eae6ed9d353f5
+42094c3b11fc9a0751c986f30b10d35a5add9e3102d08c00dda48f942447
+a2015d96c78b011ef763d5d44de2ab8c95bb380e74138a936e03e1b8c5b6
+bab711c995fedfb910b637145fea1767c9283dc78925142f3e870e0d1399
+54b8df666423e5261cb20cafc2898eceb2720cee92aa6277f11282729067
+ef3dfee0aa9d4abb321902c457447661ba78526174124f7c9d5566fdab5d
+df4fb6c08a0cb7808c59bb42de49c87fadd4f75935a0ced714b8f3b5f684
+8ae7a605960db4b2bcb477976264e2a84a43cf6854b82844d5096e422a39
+0211aff3a6f6271c03c4bdbdb5631767f345d09cce4b4fa0e9c2f9cf36a7
+ffb12f2c8ea3136945c087f9c2bde97e5aa7e0781e144ce7bf5efafa7150
+d703505bf7412bb932091f92b371539ce444723eac99aa508399d3eddebf
+4f4ca90564bba44abe73a50e62ec268b2aee66726ffce232dd4868cd1981
+85816064b6316eaed2f4fdbbd4cb75145fda87396baa6e5878154cda0b6d
+8bc799ae07d22a85f4b3eadd0501051c0f46c69cc26a68738bb20acb2698
+15f97cab493969fc16f0714e37629c835132683b4f5e4d7fcf2b78b6c8f2
+f209c4ef075f83ee77d532d6aa7098c893e6f14b0a777abf7c01e9884cee
+55066937178356bdf97f9c1b589de16194fc3b152b22bc06e4842ecfde68
+47dbe695df25ba700dd75c0e2ec2cc9716dfe2a4e75c558e0e5e521e70d7
+305e5379bdb0f5ac30f091a77c64b7bbd94fcd0448865d866f4d241e1921
+ef5291c414ae73824607d9965ca185c3005b25838462b937c91ed9c3a649
+d52cdbcd20cf6a1d8a30325c97a0f8331af0c41a2365f0e374830346ef9d
+895fe924531098876e44079140bc4d7627208b1d09e4662aa45b9796aca2
+5e3ff8624f14ee127c6a86377996a4fa8ebd4be5322fecd2f1ff85645a9a
+11445dc7328a7a69bff5263ac3b77f968f695e4aa381b8581df3f8faa2ce
+465987b1f25689d8b4ff6f79d376a3eae3aac7c8cc6436e5713a61adc6d5
+8e8a9e9e9789938bf39dde35f3ad5d2f619d07b6bb5d35277d27d00d15bc
+34ab44ee8febc29935f4d78f7183471b32fc327a631cb87697db1bf9ea35
+ba099761235bd0fb08c9ecedc02a56f2013280bef6c57c9daccf1cfe2e64
+796d4185edc469a71d96889e6446c40c7005399b895ff1e5bcf46ac23010
+01791fbf7e895fbf64870937ee66725f2c56712da4d480b8a6382c317eef
+a0268211664837c0ae48e66886e0490cf8650c136deae13628fa3b01340e
+7ed17aee48e3f832409690bbe4ee1e4e30f9d7930fb54ef72ef06fbde9d7
+ae68fdae5f146e7adc44b899643cc207c53e14c766075cea41321406abc8
+916ad2f763f268886136ab2651125da29348b6bb4d1721203e60f8504935
+ce98b7781cece00065b6a2469902026e20fc30ef28ada452f82097ed5da4
+874fd5409f7056a02e501895c0f5617682ad95a74013d95fcfc7bf203b5f
+efe8aded7f2713750bd224b8361d3be7b4eff6ec72c4e484556a5d7d62de
+c61e7f4f902cb7d15add2d7cf5b9655371384ceca736ae87848d97541ec6
+45fc0de7ded4e3c8ba4b8a99716e767a2f4242028b61fa2ac2e810fdca21
+ad07a28ea5aba532cd615d0847926c44e7d4fd6bf46063ae725477bbe9ff
+d01cca116c5d2e35cb91436ba0d713e96e81e188217cbc603c3a1ec453f8
+3e958063053c7af403de39a9ed4753db3a876f6da5d7190074c7ce479efd
+c41bf3448bf859a2dfb482eed009fc38c548abfc54288419ec3b7249b66f
+15f5359c461cdd6d77b96e9def3eaec6d526d19f096547061ee7c4cb5a0c
+71bc5ddf090c363a8de648d44cb771665259e50573ff945b52291e822522
+c0dd255ad3ad4247658ac1bdf71e2c8bb62f43c2f3994411b89884821fbf
+963cafa4589a410f8e61317f04cbf9b87ef236724c850a42f9af2f36a850
+72bb16911d7810ce35b58a6b3a978c6eeeb379be4451f6260123a56b73fe
+54dbbc4f1934fd185fb374a2f4b205ed7838c22477f8eb4cd102c53b4ca5
+ad74789a4468cfa7cfddddd23db22ba4315c703763d6b3da578edc4ec040
+d4f0484278eff6b2f4b1e318a575dc53bdadb24be8c5a81f48fc9704c963
+5a57f2bc8b87921f2b3f5cabe517b7909f6fac3bb85a4ff60d5127e45d9b
+38d76620e6ed901ad20fee55a99aec87995f54809f22617b289f303ac768
+9719ce10f9d5456f7a4804115abe4cdb5cfe2cc715941a95b8b187b53f74
+c2b82eaadca96bd8b902c58e17d1bb5e8e87bb0aa354cbed83753aefde1d
+1bf54e3246aa1485f796fe3be9cd5db6992c2647e4d32ba14bfd5ef0cb5f
+b1f77f0e5d13d70154be1e2be0ea6c6ca71a5024dd4c8092c465913019cc
+b8d949e2dd5cd87a196640bdf64024ccf38dcab7f022a688b9c670e6b4fb
+fb0d3c6fc506aa5aa6b9cca0ff2bfdb20a9f876040db7fb7ec2ccbc5304a
+152206cf00f98315ea1aa8fa8a4699c26af04ad9455ab67e60cc95b9ff26
+30cc7721e80fb4c17e0f9a1b7aafb5cde08a489e47689d5138c6d65297f9
+3337b5c6d9917e2d98c65e7328e55b6935e6b81314f88457485f9dc22d69
+daa5f7fbee8940521ee723292bafdf69b9172998b7951967001c8c6919f4
+3e7aa54f352df65b8130a45d5fefe672291e15f34f8fb865600931d1c751
+abd8dca8cc6ec3c7e735a3accb6b407e28ba941276bcd2e221f06aa2e180
+20c88a75e02c8751505800a1d8e8dda4c417c48fafd7b285f8771989d0e8
+4f89adca1d965ffb37c74f63e08f9e5acb085a66c85b84ad8c3e85354d17
+e05494bfaf92dd4e91efa6fc53fe92b7c2cbd93ce69b35cf44bacaa33a59
+de80d50046a1240309e261f1fb355e49f9b15b56ca50327a2c62c0b944ef
+7d448b62fb75805665a50ddb309cdfc7cb7368172a7542fab7eb9d386019
+8874930d428f3751d85c228ac66ca19f3f7b5f2bb93303b2dd1532bf27e6
+8639762b9cb525f916d0478ea7ed6ee9735e7681291e17b2d32cae4159cc
+fe773d9acc97260e721af0943e2bccb8ccbf17077ff7ffd389dcf006064f
+8d89e421a2e8d8098f72be9e286c3e824ea0604f895789866cdb26ea01da
+d4b46faf3804f4ac97ff2a626bc0f059d2143ab05aad944589acb5e15413
+2c9392d823c072aa8799940d5c98386a0fd6b4d0b536525e305699f41773
+2421bb58a75568ad4edb53268c8168f914be852c86ea02d369315dd59236
+3915dc469729f01ef1bffaf4a5d29ee70da632b9e63dd383eecd4ea32114
+642c3c4be801265a9e9594ea6dcef082bc99d2cc7e92333aefa43a33d3c4
+696a1ce363c9b3915aa8563eb616c897b795d29361f8253c267dcb652f60
+5a96d6492ddcac2b13bf904e88c90fd75ec77f7364bb75ae200b61361526
+044a94c7e033bb86d44597ed39b1ad3b7bce8e10659cadbf9e07b3fb041c
+f1a8adc4b74c39306a8590d58d3636ed87299c47cc12a847120ca9f77182
+606f86b724792908367255677d56495f22aa1275b2ffaf1cefda123a8984
+c607d438cd7c00b769497b9af62194895c6c79819357264c7d0b4ce7a259
+dd1696e773cd0722e28a5beafe26c7d04ad867886ac5d9d1f83dfe97f670
+1c200007ce81859e8da06505468f25e77cbd0be59194700ec5b39c300018
+1398248b39e650376b2fbd9750bb27457fb4cae1615d167b6ade44d5d4b9
+b08492e7d2122af169ba8d1f201e0e8333769bf901862ad46ecc9d58b8f7
+2b58fec61bdd691cc14aef8f5d7a34113f9b0d08eaa4fbbfd530b73c15f0
+feef4c45a7c8c7b68e5310e093667282475da5db6765ff566069215bc09d
+d0a8e5186cc2c11e3577b56eb13aea6035d2dc3add1d137ae15f8f9aa9b5
+0b64c7b7c1dfd5815bdbffacc75b84254804b8be1449b32f45ae3b774cb6
+0f3a9ba3450e08a4432ff2527686e3cd04a7f035471bb4bddf4e4ed9309e
+708be043539d298106cb4c6e78267b568221cf6458f5a2ee17ce08cba821
+d9b872b5b985ee939c10a45db0cbb3a09432bdac2d10b73c29990fdade4a
+c161a5df44c1bc8d60dfcce175b9fca5fedc347fcf7a9c897b37857f7d8c
+b1e7af13f4586a23bfc9860b88a28b5cdda25b74b4bb2553e8ed796b0323
+13e5c61ff414bb6eee4d9e5f3e8b4b7811d5809a2be4a609e39a0c8facbb
+ab96619a34df96aaf42ec5bb0f16c92e104b95250ce203aa9c062a409a04
+089d02966f454b8fc5f0272ca0f472aa3bff2d55734f9e3e93c9ef83d7c3
+0f53b334cc0ae1e8b0ca1cd4c74f5993cab7274fdcdfe86bdbbbf3ea762e
+568d9379ddf41f095a5424337277f8e4f110bfdb6544bc603c6a153c2e13
+084d333f6aadca51e7b45003d4459478b9510b48d708e12e30c7ae7e4a1f
+1f872d31ee76df3204aec196b8365c8f3b6d3f386aa63a149e923c205d78
+d7d4c1515782b961927de098c019c865d90c59a24bb2fe821538287cdb9a
+b703acb82892558b3b1321a31620ebe974dc1a12746a047a5ec793e57c09
+1026e8cc0ed07cbf90cf19f792629e55a5a6b7d94e667c870153ca440a72
+2f39401aaa9c3ae417e94e2116d97630c289ea43e026b51d0265d38a8488
+5800099b144bf37188cfb3e59cd846871d524372a3acc721f9ba5659052c
+dc2b78f26192b057945495fd2456089c3df9c543a643f39dbc26d532c88a
+a4fa6936e7579cddc8df83138adaecb0b7096b520ac4d97cef76022200f9
+6542100717c47cc0c59e48dc57f8028c453d8d4508ffcd5b3fff8f09a64d
+a18d08a5f91eb696f169758e35732216736f122192a765b5043a7187c473
+0edb5e11c167dbc62fb78cc6d478c79d41645c2012a067a8c895d746c77f
+d106fe34c2c888020fdc90547dfaf6036027324bfad10157483a0dfa92d5
+77102b892e9ad3ce666ce138f8f32d86cba1ed1f3dbd5b46a9b83d7ddeaa
+57dc7de7ebd5cedc8804410f6df6dad36706754f0796db56e4f7fd86b603
+d68d269004701f81310413a2f78d1e765329c26b37647bb0aae4aeb1d8a2
+53bdac2da74790f5020cb9cc18373f145ced54c39a41ad08a31756366bed
+27e1c358d61008ec2b666d348d50f3b6db72bc68740e8cab62e172aa9332
+27ea0b2b6692ca80d5244e2700de3c5a23f36705efacc566eec594c0fdeb
+319b05e48f25aa6b5cbf5f71343fee2932dddbf8bcfe62a38d8302d0d287
+529dc0383e8efda45177beb4b1a09e3b6121db5f0a25dec3b8a16889b0d2
+dac7ce9ee7339031b5dd48b2e217224cce666a5b218dfaedab6bb9dba36b
+6b588ed0ed3804040785f8672ea17a6b2620f653d98e65876452caacebd4
+f8d399e8581eea899c59e5f50832dcba0c17141c08a609f47047f33aa20b
+815531d7dc90722a2622b03b7e82cf4cfc871f45f7b7f040bf20f2a0db10
+0bf9f352233acb1050d142ba5be8a957f1b2af4f3e651b1ab3083f0c7fba
+cc934863d2845e5071fae1e3989ef2280c56a82f79eee05aa4ebdf6b61c2
+5918d704d7f76d0c0d7dbc1b883f614f3544e025499c16967bc66dd59fc7
+1efefd9bad3ec24945bc6fe1b58849a819bc544c60d4df10201b2be4b765
+9d4c44bbc2bc310105b867c6e8237af12628536c7d4287e7cb3bfc60fdc8
+446f310c6aad457f1b420aa61eda74926dc969d752d0b7cf6f36add88ac6
+67bf4912a237184bc20d38fca2e50cf9698f9713fb1542759b21024109d0
+6d5df512663444ec40b58d828722f0fa752854a4fa27f2e17a3d9d5b6676
+96a8871cf2fcee25855233b670e78e401ea8046510a6cdb7f3492e8abc4d
+23f5f1189ae5b15bb14307c2aabcde0b398bcdc8cb339ee3fa48bb2fc5b1
+a636b30884b342c4d165ba0929eaa8d411f87ab8b36b50a51ba2305e6868
+0f7a5b4bc8555052354a1da9a6fda6a2b37bb248237e7418216c388a2a6a
+18f27888bd2d5715b26463b3bd2924a319981e687c15dd47e4ea71ebc87f
+d75c72453b7288c8c5780062b3182b0babb9ce6bd6ede56327d337ba1c3c
+7f069932292d77eaa0b515d3ebe13b5bb70e17c6665863ac034feb834c55
+d8cd1c078304871bf7d1a782a423b915f670a59cdb30ecc94d2a004f4fb3
+9463a2815bcb1a96817b5d105a8d1ca1a81197a3a83cd64bb15cc9bf31cd
+7d174d1ea78c95757a607a6d3ce4de004e840ffe790cb98f4000520da3aa
+75e0c511567d8d0927e7b0c2cac2de17209481edae918d5d5a76ca6abf5f
+f352f11a3dec26db4ac6b7286ba45d4de5eddd3862ade7f6bc1374ff5623
+fc2749ec4b5fd8e8dec48210511b49ff88aa67a7697a41b75578a6600354
+ab3ff8df60ef834a06e0a88f6a9b5050e3dd3224b511797ef82bb0cc72a3
+77298a714d0380ec24a66463e8d120ca66bdc4bff401718b89890a4c03e2
+a34aad9949db6694aee7d63b32798124e54cdc35aa4ef8fdb748d2c68185
+e4222dfcf0b03d3c121558438956292450e7bc60e00c36f3ba5a2558c153
+b3a7b3e5b6789941f8c83f65b0e6bf7a626824b0e93008c9909b6d6c7210
+f348c72584a67e862d8434840105b28113b5b51e8648e283aa62e60ce215
+0467033bde24acb17606e1ed9c15f9d46439dd00cf5b20e8384da2baeec4
+8d3cfb0763ff3783a005b9a4e7ec0bf36af1755ffb082c69f0e8f4807a29
+87d7a38ce50e1b7fff3d6914dfe2b19ad4b8a4c3582ff4a4a383b15eb15f
+e5f36134b906b18f6b231eacf47abd1b52ab570ac964141997d84e8754ac
+b59de5bc277370ef2e203c661d32213b2620e911e5f02c4b2d99ef88271e
+5c772ccd6c72487ddf5ade79c61f414c4c20bc55be8e887a577ddb0d8129
+49ee3ee14468d2c5e6c2325d25c3a1790eb0dda0d88861a77fd043912065
+f06e7292904d964bca5483959f6fd43702d7ef13e046fc674d8fdbf3b9f4
+ad11d2b14c1f120ae522ae0b69b01eb1de89b3a794b5feb4d6464bd13802
+dd617ab53aa8f1bb962452593456316cf6a9ad6a04c89330bda58ce2ad5b
+30cb368fdc8e2b62845e117c965bf052eed29c02c43a88b04460445f3b2d
+4935ce4d46f92c9949894661a92c241d088d26a74414400beff55c1ba2c0
+ec680d05c5412e753a10566e7c8db2d2303db5161d5f33177105d6ba7cf4
+8faccb3a4eaca923d5a123f2951fc37df94a861a70305464567469d54722
+fb82a31fe18a65056cad43a872963de7b4085005db0be6978b0284e513a8
+9887bad0d8f38bbaa572f6660c7cc52654c706f0b8e198296cc2c6ee6561
+7b383a3f491d562746fcbd014db726a50d4f4410e64ed60f10d5e4f5889d
+741ededad290c03b9d9ca995f49e260442e7307d7ccd36eacbd507601d66
+aaeb232605601aa2b9905f6e7c59453f0e5d6ce8450b8adb3a372b40b765
+0b7e81b0980f095209e8dab194014c299d659144afef2cdf5f12c05f3101
+c73944d76e9ee2fd92906b25b62857b492b23a66ccff19080c55955fa167
+b7aa7e13bf5fa873116695518341a70aa41844ef03c481c2a36f64161d72
+5c150e869e280425996038477fc5a6db064b8d2fd9bed3119b8d93d19cfb
+e418b95d6483bbf8d3047cb788e3b5d3eb2e220eec7b48367a916df77264
+59bb90464c6096029d2f781d30502889ac2c9344b8fa45ecfb1f5099551f
+3c6dec6357580727e277747e62b757d0ac7232b7dccaa2fd8b20379d1645
+799a691c64d47cfc9531451deab72664558a2ae06d90e45e537dbfa1b8f7
+f14ff7619310fd5365036abf9f29492eeaa418e1cc87e53ff3e982b9976d
+adc5f23461dc54d13864bc8bf5fe0e9752870a399d7a9ab81587705ae019
+01a66b4d89b39511ea03e144f56ecb2fac87a5337e8fbdc2cc7d53b62edd
+53d3cd77f8d8a3be417809c7e27900d1fc4bfc89d3e2185816ba2824bbb0
+5de4f0e5781c29ea8262e689c525bb73e7448252fb8573e01b855590bf4a
+baa076adee94fe895a2c51e57e54bc13f6e3a38d6139711165f5a9e30454
+7dd0d41d9304739c4ddec27c07c74c4aa03cedabfe7564b14a65acdabc7c
+9862b13e58004b27c0e489fe7ec5ea6d0dfce31c1b500680607372bed66a
+e33db1ae66a215ef573b52dd07299db401eed536ee4b0b587b910ccc3d51
+72b4ac15489098a6ecbdcbeff2c968d26edc339acdfb7c30e4b13e9b5362
+40264bcc2a34a2eabd641c9e9aed706f266c491b6ac618c022b23fdf20e5
+809f5caf0198876ba92b577b128f81d80affc4b6aa9b8ca747b7832e510f
+404cbeb63939b5d8a77f3d7da7f23fb276d5500959a394a2a854da1a361b
+8e40d1a0f41fc67d51340d687c2bebcda5bba418694cc392301e28e3c2c2
+3e07aeaaf44970e0db8f2e44e67f9f372aff67f735b1df1a228be4dfd3eb
+c0922df5bece2cb1bc8e784331aa2d405f472bb9edb41b80c784f5a7a7f3
+bbda8568b7b2eacba10cfa5728f5a6609ac2a590b74883160cb1f12d1dd3
+6e0b54ce388c5c8f3034f885a29979599fe6d59e93739ff98b2eac79785f
+f9564224d6b454fcc2084320d28c900302379475b911dfd9951b075e4f14
+2686a37a437aef3e158140df71353e0f932546ff92b9fbb7c44db1537060
+e94a421164e814de32d1f3d408d4345626b8bee38896ff335046aa293185
+49ccc78b7ecb2d17d6fc255b69c92781f9a561ddd8bde09f04c4374c0225
+7c98e24e2ee407741a8f02b86022d9dcc449b730960fcf1b9b8d65af9e0f
+10af8edf7bd3f1cdaa9d5e150416b6334089dc862e3fde6633fad940bf88
+5c976185ad5667991e75a2593038fc8c5edac82f06c213b0da990c702244
+9b767a619bbee9c29e65d9ca53ce96016d0cd40aaa188aa7c60bce101426
+5efd9206ddabb6c0abbe54f1890c4045485d1d4fa003874b1052147cd269
+552b663460931b5ef7824cecb7d7b85f6664a7bfec448a7e591daf6891f8
+f8b0c5f8c824d506072c9ef683bc85be1e7f4e240ee40bb1e23d4e8f6f8a
+31f464f1a5d13989456404ff3a50cde14956db3b24e06af7bdb5527a000f
+2a853e9535914d4624cd39ea90a4efdcacae7811370c81309ef360021d0c
+79f656bfd42ceef8f2a7ac6f6647482444f58787706be9c7ab844428aabb
+6679e4b89827af8cf9550093b0f7ea78a53ca24b8c896709ae2213308520
+2c5b5c3e4933092b6c5a2d4ef88cd24697294cd74a7a30571e143277708f
+540f4cee7dd8540ac16ec5f4ded4d43dce5f238d2b607d7728a37a4cd110
+879325f583c1b370d16ebfba95806ab62bf0fe931ca58e68fc101057cce1
+be648ba99d6af6f4f288a81a3e75c2263dc32aab93d4ed052cd9f97f2dd9
+127dd32f895a7e760b6c04bca804ec286c31d58850acb783e4227e8fe6a5
+5eb50f6bb9aaa25fe46421169a1088c3a60c3f8391ac822c57a4d83f018e
+d339d5a7f91b2a47c951eea90a736803932641837100c5cd4cb6ceffdf15
+7a9835855f53d8bfe1e54a9854d8f7584ed4e97730635497604a9df15642
+bb7bbe854c871575556f0bfb3ccf3c8a7ef1aeaff371875ad23014e0e5cf
+a1d1ecce5ac42bb72ff463333cefb2377be4cd71cc06547dce74827a60bb
+3d2c920d918f65b0f4ed436c3a39987965203499728d7f0ba4a3de62b38a
+2168914b279c9455959c51f2dc490581312d26f39113e42cfc81787cd39e
+d884198675298c9970ce6b07a439ae17d346f1a1c4c5417f00d3a285f59b
+08be23018072608e8d2103dd6eb5282535246c78c06abee28e8981682319
+6f6da9f6d1552ebad2a28633acf3f26b86de651f5a3534923bf54758f394
+46fd8c960bc108ff9020c88ad0bf94f24f8c444961bf1742dedf34839a4e
+869651294c8c9a8383291a5b460416a6c30fc8b26d74744d3b0699bc7d7d
+f9af19e6c297032ed61cd9be041d42e1a85272d981176a8d3d028346d2b3
+fd6cf3bfeb759a76149f3c83a372b16aa17d8d13275351901e55bef3477d
+d1440ed8509a565cfe0b4b5d83253a7382b9ea5baed8303b7ab5215a4cd3
+acbbd28a3fc24fd8e6eb59003e083c55bab0ace88797a6174208d9adbe6e
+e313712a611bdddf09fa5d05b9ab89ad94681b536ec836f330dae407625f
+5f7fe3edff500507cd28d86d0f7477ecbbd1085c83a849e50aec49759c5c
+193a79b8b1e03e808347eac949ce187fa816f69e6ede6eb795f910dbfc5d
+85c9f581621b5b7ea982abbf59e7e01eb665695355486d46a3222dccf79e
+fa05254209034eabb0147bc5e21dbb361296aeb014e2a6247166d27e5643
+bfc06ac4b138c0bbdd0aedd15c468eaef74324651aca67c0f7be421226db
+7fbf04b2baedaf2fe6752f13d9df1f5e306e539451de6d708e58328d19b8
+24e8ef308d3044f8552b5ba5b31eb1faed15dc9a99f0d46e5130b5e63d77
+c63d407d277491fb9da2671d24e5cdc15a38b267231914223ffb455f7df8
+bb21f965438c3747b7c1f04f8c5a9f7dabe1ea430514733338232567c4a1
+234aa8af98e445e267d39af70e9eb8c2a660a2153cce33abe475b3a894e2
+3c31fb10c0f0ab994c689b5fdc2b6d07a70f9af7fb4ff8b3e34c5f1de296
+8969f1bd834bab5a2626f1f25b196927c680b9438f795e4f1f31c41eabf1
+ede62ebc46ba5246d086acd10d32492a129eed911a18a4b3df792a4dbfc8
+e44fbc6b71d7dcd6de9156f2030928c7d7c1584ff4f534f221377d8b2e74
+df80cb2abdcc685734ab8466efb981a361dfdd859ca67301840f76491f21
+c63dd556d47b513aa6bf56dc427ca6cac22809671af909f87c2748bee4c7
+ac4dba40239094306f2b40e28dcdbf90cfb22e127cd5f27c1d543ca0c549
+963e94d95ca07ff0fa6d1f4afdfeea5289e7a33ab1a3eeaed32bbc576df1
+d587aa9c24af350ee5349f1e1ef906adfcddeb97a8af555619b45a8b7c71
+420ace89fade1f980797909257083e26232c0cfe0d387e18d4d4d10022a0
+01bf7a265012715b0d9cac530d6d6edf2591fecd9ebb19ea15a931f5814c
+6e83d63e36cc36521960fbfe697685556376661e354dfecfd153fc87b601
+bacd03b1ca8537cc788c4627a47301175aba9d24a606fa5915967e0c47b1
+23a5a6552e8f0bfd748ea73f22fe5b5de2efc0251da7d2917c60cdedcaec
+63e34d2d16bc177a9e3b2e9be7f25663de708b7492eb9daa0e9c7a7a8c51
+17461471a3f8a9d704fdfc6848956f6033e98006d0fb5331453edc8d3854
+143ca54940dd26db56c904839af1ce8f7fb2970308a4d16974163c8c86e0
+a2b3b5eeaa1f4eab594577b76cf35a1dda9469eb319c2668ba7c57b4ec7b
+80c413a384127ba4b9291826d4815a63d987657f9ea870c763cc23cb7401
+03ff300a50bbbb30c29a8df5b081d3efd3d8cf64126ba36084fa7cef3f4d
+5d4f2d8b26011f854c37774770a6c34ffd0086a50d6b61cec6e25ed85c36
+776ad1d522f0069c6f6fb120f3191b0f4a06c0ba50c29a4283c7d876233e
+23c1efa55760ca46491b69a30c8e638279a4385b3359ceb5bc4a616a3e1e
+cebee2ab4279c5ccb2aa5b7576d0777215217cac3f16db73fb1526c4c95b
+db662448cff24b480b224834f8b2b3e49e42e7b668d95428621411653b40
+6bffbd7cd5feaebe10dade204c86bfd3a3c00c12ab790a59d9e47e7798e5
+8071ddbbb583e2c96c27876dfd40f6ad8e0821267e4f0a574d8e5e684c9a
+45a70f999e3ede8b00c1506b5ef0001c28334aefd1f6309cf290ef58fb07
+5379da9fc609c31b1fd0bd33dfae5de4a704e02886a3fda22c0554bde2c7
+1f65880362badfea1471b54c064b2dde0361b586b9071554d77e5c45d704
+ae13f654a34a9d34c198ce8f56be3f99d3c6a3cda12a6f488baac8ff82b7
+ce2b2a341a1eb6d321fce0a1feefb4c1a124a9123f6280db7efef0434fdd
+9c1f570c3d1f70855c166b76fcdf37237ec06df0ba289710b1a1467142a3
+22ca1412c96b41beb0003b12f6423fa92a4460259bada3702c21e2bb799e
+703eac3e7875f673afc8a75293ea9da16f1f87465a8f0984e4457e967ba7
+c5d265f2d997eefc517e2766382144673162d6f937bc6d075a79e8f54723
+9bd8a42e80a4657c0c927d3e7a71cdb8d49534ce254c1f0b161c6f498766
+d11b7e40bb4700ec8ec6f6282535c78ace3fde539ff76d85440cacfe0702
+265163de0fed12f3ccd1d5fd5d5404292c5137f389da4e05b751c32197dc
+6dfe5ccb4d8016dda6c924815d6d80fdbfd04e1357922ae931293a92559e
+6122e0f9a1ab493a4f82ac6290f420c18d24287fec4cd41c226cc06f0512
+12fe8e4e33f3e9d53d37e0fc7819ce859f2963e2bebcc47aef3b877df83a
+d2e7a1e3bec754079ed7f330f684dc53cd2389fea725d1002530f55c4d72
+ae385b6e836a38d306e764ea1cc46ca00b06c4a901bdd45cd76e45dc6f7c
+cc02cee158eae31970bbedc31dabd5fb0dc2e51ff855e53143c726106f38
+084affef8cec7ead3de194dcffaf7758390a21ae63bbfcb18c4db3913843
+5492781247e29fe2089af2c6cc99fad2af2000f0c1f4b5944e15cc402f99
+d7e9eaee03f5a96d4198bdd3dc5140b3abd0b5300db7b40d1a3986d7abdf
+b59934d7dd00ea54c9867805ba6a29f60efd9873d7ad8ff52399daf45311
+c6ddbd2963b3dbe5ade0260209f9fc81ea3a88b4024cb17fb8bcf05e6906
+fd95fbc50439daacb2866759e8c8212d0e67a7eb4aadd6bc5d94f8e97f67
+05730c3cd2bbd303d6c1714c7ba641eada96dd89cb6fe1d655f4b67354a1
+708ff15bc6a45245d57695cd52377e7fd3e38f94a9c4da0a7a921b3a687c
+5ee8d0bd2b725c95e8dcb582f79ea5d5a728c6691ea47950614c78c4c377
+19defbc6e50bad8165f1ed0dcc0208afd12365e70948d44b14f91bf90cfd
+e82296c021aa112364369457567bf58497ece9a36f4058c8eb1713969274
+d29816680623704d034eaf900c52e04975556b58c3ea63e5447c1974248d
+713988c58d1b666321d535be0c5f90e061a2a2f7c36c1e058fb2c01f4d76
+7538a6e41ecae22854b83a77101bf865d6dd442f89cfcace8cbda39321ef
+bc2b79da45fbb39f2d448b03757310283bfb73b97eeb5d160dc002d178eb
+3868a293be770fe4b63c014c1b0bbfdf1af1913cd5480d96d09080225183
+38f18ae7c3961e1d87cba5b6a4254d225a2c9caf5d976f1764a14276eab0
+ff47688a5940c300851424ea934cd53c59869dec2ed89139fed0a1e44037
+9059968726cf1c380890796b0e598e5b1e3fe5998a63224905cb8dbe7d95
+5ee9e9759e0d8195239a359e8e4da5c783ea2d19d0794692f0d59bf50905
+73f7cbdc635429f853f55b75bde37dfb5c1d5642b58f5873d079be65d004
+7b01296394aacd4c4ce242d3c0c37427765a7b1cbbe19f4f9153703613bb
+cc8aa6e1c616df576ff5153c1ebcf9f5d202f42c628e70137837e3a33883
+e9fa8f0476e5414cf337650d94b533aa2cb45b7c473f90aa1824c69a2120
+5db7f301e8d2d6652685db61513cc3ad11c44900084623958d419f0752c6
+7d881df7d20300748f0f53e410d534664c6d13b4c96b49cb991ac1eda4f4
+25ad27510d96fe350b9168a536ae9ec6c50be8de32e2ee7fe9f2db8eeca5
+db7a80ceedc96d5a0b96f91930dbc00d2cc75069f1590c81d75bb6f7e6aa
+720307776f25867fb62e78cdfbaa13eba1fe184efed5f7091c4fa08baca0
+86bff83086334332b8a75892a5bdc514b75118222bc71b8f8fdacf984edd
+d3be4ccd556cc8f30f6a80c2b20c167f577eeee593323e2207694732587a
+0e5b016b6ade30be2887b8ed026d2df4c539d1a0308b0b09770be61ddba0
+fb20926f07399ae6c9c937401e1e160d0375a89e870917de3cf496597d22
+a8ac67138d4313507841ae24ba2c0cf8fc1efc1ac5b8bb51ef6b50b34086
+2017759ee174b4bcca9087f5c463198407f41df40eadbfbdd7d73759cc41
+a9a43c50b1a0f17deafe0fa93669cb5b11a17bc07667c357b4a22b638592
+b721fbf505d8de6c7d69496752cff0317194a3eba37f42627126fa395596
+f5c0585cd5e6964a1ef53ca1b8d886f29df91782cb4201f873a7f93a479f
+c62ef2013e503bea26d1edbed3ff450c9ad21fc04f4f69f6717ed89e0ef9
+67620edb859bb0d7efa3b0ed2ba5e4d5ba200e51d987b0502ca4b21f6efe
+c5d2f471684fae7130eae3e4ed9006ee5cb14e6b9883622872b1be55e09b
+e1e49f3bb6bf07630c58c59856f23d1f60d44589e7c959210719f7e920fa
+067ad3433fdd490f28c9048cd9fa4aa43d134e3058137a09184ee4ff4412
+cfc204ff4a9975b96af8be17031ffe148304af1c4e012d72fa65baaa96ee
+579ab548ec22d8a40e8fcb2c2efab52984c707730953f866bffc31a81e40
+427dcec529a3be22f7772e26ec0fbc26ebc4a3b561ef75e92c777684ea7b
+38d33d99d8f7ce4ebbe1ef36cec712605921e0cc42210f738b72b8b06e2c
+699d6a786379a2fecea0799175569fe77600fd3fa661f5e9d8e62604f59c
+3318cf53e2fafd68fce5448f2f04c3a55b84aee7f2bb12953004aa3b68f8
+12ce7f25cf2f8a0902d38d735a0b9efc4752aa3fe822223a72272763d649
+6a4e82634b8d5d666c22c8f36d3fa25cb49cd8cb57a6ac7b48d697905780
+1e5de91b50dd5fad9999997b63863b73bb9694598dbfe25705b1dd466891
+0955a5e6128769448d35dc0ed21fb4c017d10cdcd5d24b386c41e2d06f3e
+3c105edadefda6a5ff6e101613be39ba5ef511793e96a5aaecd41ee1bf4b
+85a144e147edecc36dfdec820c54bc5ae17b138bfff4a30b5d10b30763cd
+944935bf7d3ec0ae8396f1bdf068b51951d2a7deacaade053d0a3c6a3508
+1f20c1baf4b76838f98b157d9ccd9ffa669302e92886340a8e0032144968
+a3201ec7d3c87d8e5545992b082252acf496eb3eaec509d27d326d5562c6
+862a03829660ae967eca18eb4bfe04191ddba3e03fb6dbab09ecc01c66a4
+4bfa077433a048b741d98a04f7ea5e7d3104e4d6b1b42cf38f5f4821eb67
+32c6def7e2b067c9ee2cb4ac023ca4c329d381a1a7511ecc33b4bb4bd326
+7391ba5e4a88d84829c541382d4ec4eee3a4683f7c0bad3f219a3ab5d0f5
+a7dc3be313ddd434255d12990a7629c712a55b732ec7651b5fa61fbc6c35
+e3f2b7e2c3b62b72c83c67397413d88ae67393e2d8c77eda593f19fbd9a2
+5f69ee9883e02ae7e66dec74f7ec9920252281a580374e478beb58118cc5
+a11c1c20adc018d0706aa360cabb190d3a9a7dce6ee8c68da7a784358791
+850015a3241691dc125436a8c0cb959356f0c32b4ceafe39fc111e6299db
+8068bdd8564b1200a62c15856dd8804da7ecf34f7d135cf45614a243cd34
+b4e8531da69a62538e6724ad4e3f7a1e2b2c71e77fc686738a4f1d2f51f9
+770684fa270a94ceee7c5d5804ca49220a463e7df0a63aace3a2c73f0940
+9d002d83115af1347b9909d08c0d547b6643466d119f4296094f4cef0a10
+0eb23cbd1cdc7cf6e8bf2363a042c64d8234beb4bbdd329d620c99a65c56
+04277780c343b51f842908ef1e66b125b65387885bc152b50566da9c8b71
+ce360f7d724821c5a06f98b3d5408c01217e483d2d40063bd2be7c447fbe
+b398e050e608d2dbfc8ae8b7516d56a85785a6a63ba1d559976e8c699938
+631b10b5e314493a46edd7df429a7f7529101e32c57f08bba5bb6e980651
+0cc39e14ce46ddb626fd4a5b0e89444409b42334e7d6a587836d1cb0c096
+293b0dcfec87d73dc4e9f90ddc2c312a021af05b95f32bdc4b9616fb6db1
+44d76a2a29e8cde277a703362088a76db6413c840661b3aae45ee5623158
+6c21f8ffe87c30c2f00b6b95537094973f54a5c15375e6549fe45e2e020b
+6fc5f624e8c3a9b30d73d0a397e5a32de1920a15997b220276ba3b9d7019
+255a884555b77bc27c1241af0af4d61d6c8a4ecdbb158d86e21eede3cc6b
+28900b71ac5c945e596c9a8546ab01125f8ab5fb17c9ccf75a8a334aabd7
+705a2df1165c97c17ed678a1aa40fde4f4a62b503099727fef5afc32807c
+051866ca6f27ac4729ac0191edf00281a914846ea08526ec0d6973012851
+e87530591b168b6cd69b0f44a45088ee2ced5d53e05e1ba563351c992222
+f23a58a26be2dcec43ce16e281f79184fda1c9e406044127091d5728d7d4
+0d6906e0f528e12d8f82a6b175e39bbab45a9653b2b4bbe4681da493b3c1
+6a20e5647686be5b07e7f41049a2644befe28a100e4ff5ee34105f736e21
+6fe3e81a1e7d2ab8ad823bd537c4b6c2bd9ee406167117c8b3afd2caaa36
+595fe353af33d30606db992f4dcc8c74e1c1b5ea0eb4722f6c9d0ab7aa4e
+44e61d64ea9cc3ef637aae540d2d0ac7d9cb2dabb1a3be34633601a52d20
+6db35f74f1481a54cdeef2ff63bb310283619dcd7b2d52087cfe957b931e
+7926efb5c47bed864f5dd8e7e5583ad66b34ee5133dfd7b88c9655f196d4
+d5c2d06f478c895c46a27f1ef802f5126477fa407f80d4d2cb55119b8cd8
+72272f0ae88ec5c315aa469e37cb7af969d8886851426ae3e6ed5bc44813
+5fcc58282fb238672563a96f20c2d38d6b6e431af706efe5944f675cd169
+9ecc46444589b0b4ab41c5387b1ae844399ccbafe4cd7772d97448eaa402
+cbdf9f7df550aab54d47e2f67d75f2c364318fad9d08e47d1538c7af06d6
+01f0c31ca9295849f809e6ea17a113883b5e192ba7eb3f9a0c6b55159e67
+c0c085fe7ce9cdee489fbca0662d2ff1a6d55f8a1ee87d0cac3b46bb4f8f
+b58dfb2cf046f530732af1cb20ebbda80adbb95dff7ec28b57355ffdd42b
+aa7bb36b277e6c76f1b1da390c3788e42fddd3931785626db52e9406d887
+adcceec2ac6ee736bcf3454a8b510718fd0f429a3e06dc3ec9de047bd9e6
+0186657b1252647cbf3725767b143ff9bdc0a7b58ada9d94745e75b04cbc
+dd755e2c1e26b0d6f8a723a04e04bac494b36591aea5c8c7a8388fb83e24
+6f983f509a0e9117da0bd21078c3bff245b5e478a2b7331e4f3cbddef0d2
+0020081187c2c9dd0a591a380bf3f6956d7b8d65dc13a2d586da84713ae5
+5b745853aa09b3f3b53de393c03d4c8fddd829d8409c41e967b65a00690f
+9528cb18b3fb94b559c86a820f1792e58bbc45aedc02ebbfa0840c8e7298
+1ecca6988b7beb9312e863064b58618eb1cff26b4ddb52a56ac4c364e30e
+fc20211d6f102622a5378cff950b1b38b8852423ebae51a605487551e4ce
+99484df76277917bee1933a1226fa1026b6d7457bd36928079c5fc2bcc28
+aec99667d1018da53c906f22b71c52c9ee3dc4e72439155717a6d44510ca
+2ba6144601bfa675c5253a4443e18350c6b7a9bc074e8ac973e4b619562a
+43a13be8d31e34af31da70cf8bc39909ab80c03e0dc7e8425b1fdfba898e
+352aaa0a1c4c38c711b3c3ac60a7725e958c0974908fa30d06200bfb840b
+9089e9caba0f3d9b00232516adcf252ea6b73c178e6258eb6a450d29be8c
+f6f66e21d5309f0b75b49fe6abab4ab07e48ddf778e4fbe197481246d680
+e9667c7dd1e420257db762dffe7876f6f8e305d668cf4456b9a0b8ecc6e0
+1ff973144f5527a1e6065d2f6797fc3accb88e5e52dde221464fd77823ce
+f7a0592a408cc0eb37725bb339eea0f792105788b2ff981484d6948d15ba
+51efe3eac600c402b6ace16d145f96ee75324a69a77cf8dc43267a56cbdf
+a156903d2392393a8f12f33ef33f9b9aa7a9d95adf7f2368a34d2c47bacc
+93b2a3a90a1260fc3a334218bfeccded1d7f4182ccaa9879f6e006f2fb70
+20e1d1915d4fb12cf20695075276d27ece002865faf6061edb14d15bb434
+e07197a4a142ea659c24098088be777eafbbe50f2902c12f6fa8fdb57ce4
+852442bfe16a25a3ae9a1bf32486cc0448532f53f82179ebcf0fdcd7eb36
+ea8b7abcbd95a6e67aee38823dc6323862294473982eeef3fb3eb510183a
+7e17e3f87b012c485eb8eb8760007bbd1deaec08106cdab59032ce18aa0e
+81efbe09c87a9dfa03e6764fbbae08e72021aa9aea46a48040ea48e66a02
+86747dc4636f680606aaf29bcc51943fb09b805caf1534a65be267b94f14
+89ad6e8101b9101bedbaca870fc959ce28a2f84e02a88471eeb503d306b1
+1ffcd998ca3e4391c188f6d2c7cc6e82475aa5c375d2d1582f98fba2168c
+4bf25dc8e2ab69a52fa5114b519d1599fcdf521bb4008acdc91c6164cf3f
+e4cb77b79ec74b62053e5d546ce1fcfc380e3c0cadcfd0120b5e6c359fdc
+2a4189d6954ec7d35510eb09d5d305c96e482431505c91734b965d773e9e
+37797951ce86d4e2db76075774bc94da133540d566470e678d8e92cbc97f
+567c8e3da28f9e720c807d92475ea4b5a8b08a7b4ea42e77a979b0380eb9
+d168735406795ce1470a0eb315e9945afc15e8005a27304799434b75b606
+6d051e712b9b92d82ab3fb8907c5cadb75eb597330fa7eedd1645270a80c
+602a2aeea063a0af3054d28cab345e25c6171da1f0600a4b7bb1fd40e4ae
+eaac89416009e991b9c549ce3d9e28fa3c611a79a74592a4f48e5d51ca4b
+b19415e2031e6d3f5b6279ba838d9c82ed40326aa42d67a89f5555cfd429
+9d5d99131ce2bedb3c449989214adadd8989c4905e22475bdbb813e7eef4
+794878a7a538d1e0f831d75e7654b981cae483b8c90f5eb8548f76684796
+ed8ecf0141d598d029de8aa959f9218a862a10cab525ff8dfe060d197450
+965dd3990f96833e583302f20235ab7c04d94d0646b1ee4b2858cf9797a2
+83a9f0b2c9b3695faf00845d7da408f5cd55734ad74d160e97432d3d0598
+1478ed7361754488a5cc4e3f7ae1a373fc2bb30320aeb8baf42864ed7fcb
+4022afa9082a7f0d407b17a7d35e4f7e770b7ffc03ff4091ee9a9d4fef2e
+8c745f32358d89f02782b2e50b265c68455c71282b980c51fec4fa7e85ad
+61909862295cd90f0ca7efc0833d9e70361f69a83a5325cae0132c90076e
+fb416fda2645f347f9e29f7e3b200980dc3213bebc6ffd5c459b8cadd0ee
+530340f8347db627c7a06e682047a84c364d074a330fa91aa3203b1ec8f8
+a96cc9c50b36bf7516b8b3dfb6fcfe504ffb37422a5d2baf01ce5297c38b
+0bc1a7ec3e3570c1dec08aec7991ba2c8907d20972278d2edb052e40efff
+9538cfaa17fca6a50c22cde6a29c3add743a7200a4d8997624e1f7732c81
+3546f4bff9f01c5a9404e86a2b18f7b6759b2878aa4f8a8ff55b36a471be
+7f05d5884aa0bf088b87665901ccf35e8ccdce86811c5c4e4f55ca26ce2f
+10b667dfd50e6063e9914d8340d9533bc0ccc8ebce39f45d3e442eea4a99
+a73e5b54e88969d9d7ef02298c40f600bba274a911cf19532cd01447f05d
+1e424ce654458661d98d4cdc1a747224e90e609c3faf44bb29cbdd1e9a97
+5b475e25ef46447f43809ba72292540cf81de6cc751aa965142705082524
+6291840e4f1a9c6a452bda7ce29d9ef68d0007e7217dfda8cccb40053081
+c4e912ab4a7bc5642f898567fc1604c95f35d8852b7fe5f87caaf247623e
+b6aa53342d231a5047d82dcd33c96b9197b5a41d82acf553f3186fab015e
+9fb21c681ac874d236c9382f13fe672ddee53309b5a46a9eff196b426e21
+ddd39784aca3f8b90588ac9b04b993533483acb6e3125a5d8e95650b858d
+4dd01704388890b26f1e707cc1178f545dc4a3cdf21a9730d3e6d29b6000
+66310e49be5018136fbabcb028799b74f7f15c47afbe30e14bc413352450
+b3fc874184c5e128032918845b039bf2dfe29ba87a2f25a61e6bef64f2d0
+64b1cd13dca3d385443df6d66ddbcbf9ad9774abfdffc05f1227159b8acc
+8daf7cc7713e7f763ac899b066683a3fd14ed9c78e1815fe88a7926a8d3b
+e34481b91febb4c2af569e870da8f964a78b462a52c9a971cff4560a9a46
+2f95d49f759772ef75cc1469fcc61c9ddd6c90e68273e1b02493bf38ff9c
+114d75e7b84925249861275e2508856a86df8e23f590f2e5a1d2fb10db73
+ffa35dddbf1abb002c937ba96effcb828c7bad6eba66ae9337ac5210378c
+3447d9b358a6c449ca1ca82712c422173893b9605a3f1faa92946eda7fb2
+b8dd8ed5f4e5c60efcdf38a92739e16ce182ff777729514b353265ce21fb
+b4871033830431ee72422084a67dea902e0eef97ddf955925113eff9548c
+9f956325a1ef9dc75d0570f42ad14f7dbd09b2578332bc70b0ee8a675d8c
+00e2457576aa2a28d82686773ccc7c89423caa6411fa59ffe01e04f04b97
+b322081105bdaa7e09ff85f9e7cf33756d4a7e2542950ce2ae3acaa62c5b
+4f1072462370676c25c413b1388890cbf64cc9e21a5844e30791e9cf854d
+bf6dc8952f6a629ec08cec95dc9fa1eb166a50d13503cc94b4d9be0fa1f9
+0d8c914f83fe726806be5492837abd211c18f82ee4edf985e12df873d90b
+50d46f1bde2eba9d1823b48e8c67f8e3452600466be39c9b0ab5ea55a9b6
+d513b025e199ceb3d3eed9f7b12d4816c1376180f5e3527b326cf112d138
+bc925c67b4079832dc086e2c539de03f72fab6f09c92b8e8accf2ed76a5f
+055241c205f112686449494de69d6dd01300269b1b054456703c2e82d839
+0bc7d46b87c2f02e65ae4a1d4748bf0f01cde328bd0befbd31c3bf30ca09
+fb3c18524bc7f61cf2e97cec85045bf8ea9609f3644ee77ef01bf5f3d8dc
+1e7ff01370c4d007fcd06e7b0b0d1fa190784e9c5e4c93324cf4fe5eed78
+11962ad08a13ef0fd2990737fe01cda020105153609116ce605674d0470b
+438d73f3dd61f3b0059f71a291f32cf463c30ae38c20d2f4cd52bf2fded7
+4c59f19d7cdb97a0dbfcd13877ae4023cf7ff1db8d7655fde46f3aabf95f
+5c4a3050c3f9c35635925f06e820e35899839043fa416b4fc284ec3e6dcf
+d8b305666b93a072e263d0d2b1dd85593a6742019b9aaa989b7307afbdfe
+eeb6e1c2429668c177aaa0aa2f4e27495b18188eb77b93f37348e5e9f1c3
+de961b5b67b109305d84b1178d35769af4ab928c2ff5773fa7bd00ec7435
+87da5c4cbc19bd3cbc4f7c15460213c9103bf7e1bcfd8f3899422f83461f
+7a8c0b9d111f64661955f4bdba28783409f6cf5d54f8c6218e0797a03470
+2068423a4bfc1b19d0be336d990044f084466a2b2d4198476eecd1309e2c
+30e33e8db6202fd31c1484f531056816cd25b80c4b6ed9b1ffde608ddd16
+84450eaaf45d813caaf938e4ddf3ede924a22c8014a2633155d90ee23acd
+02ccd37f0e991080180191079eb3303ec6c685685debe2ed67efd2461abd
+702402a4277fd06381f9165b872f3c77a8468413a5a2dd02a61fcde44538
+376f3f6d3cf72d11fbdba81c400f83e7ea6f4386911b3874557af334c774
+0a070d3c19767476ef21dbd9ca66b74672371a6541a9f3f30ca4dc3afabc
+ee30997fe15ea3000f497b4456d219f8492ccdff2b0a8f7b6c865cb890fc
+075f715f82b6fb531cbc68d344cae08ec83ed8773be6d2632b239763e463
+2307b3207859b2bb1ca39d13bc2763d127339ef4ae22e91adb9cb0b6c614
+7ceea07996afaafa19e0bfdfdf9eb0ac43f73d80af7245d80c5b03047e4e
+0560fcb832ee1f8ef02d4054e72879a3fd64feebfcad750abc6575585ad5
+9d7a21681ee427052ab95ccb1283d2f750bdcfcaf1e66e69c9900514126b
+90abc69efe5c976166b8c4c0e18f94ccb014a303c61b80298c661a6642f3
+af81766e7dc6d699a7780f93a538863349dff728a0557f30f95cc2b313df
+c4c8f12e2a94c9e3f324be1b98142b106f190e30783b0858aa51e9ca230d
+d649883b6f7c2a8dbae39908b34b60a67b147350bf8ae770619f34f9c604
+c70086c8aee426ce5a92fa9227fb52ba82fb17cfad27eeb2b5efd0c706f1
+462d012447ae3f6837311283d7abc3e866fc68957d3cb4f86175c924218a
+a95f7593c4277a7d0938869c2e07f10446f2d45ea9a2849721de54105611
+b086988dbd56ff72e85c4d01addbaac1b053f9a47dda22ddc6f01ec98df4
+0c74743f59d149eb35b71e55e74b5babd36c0e4a24ef5afdb7dd3823d725
+e294986a66bd545ccecc5010f8a6ef2eb6047a74e68cf2623b6ce84e6a0b
+37933fd249991b018b0b6217975032700c81aae0722f5d915654cb9991c8
+0a61625b3742e76c692a042ae42fb7f4ed355f6c3fcffd2acc794de9e08e
+9dbbd39559620d2819a23e85f7498f0076b6230b7f93de99264428ade3ff
+3272bacfd3b52ffd92280e1d1937971e7243eff8038483de1ac2cc000fb3
+94315c35da446f098ce72e8a3f892a71514426abbe6baef9eced76ff16bf
+b30e8647f0e6ca67a987353c5f8848e036b54999b10d6c7899809ffc6611
+76892d7ffd143dc1b0978ad2e6816fcc5edefe51b609f1364a691cd8807b
+4e96348e9842ee5c2457e266318d5362d78c17b303d4cda2f8dc91715f0d
+de5b76c38636605a1a15d1be95d9f23f12fab5e480ded3fed2594a53f852
+1b022aff4c1ab2b44b1fbb6c00286c69375e9e0be730676687ff60d6f2f5
+6f8a75395e15ce545a0a1e5fb68dcc2ddb647fe9db6169af984829859bc4
+2273a34a6806b81d7ca4ded3922cb3e90d9c699d576904132d84c69ef793
+097bc90c59a103249ac49fea69300402e5db75b1d6e36ede739d91bc6d83
+042db4ecaf5e68e78bfe009a6a6549bfb7d538fa5ac80e27163680d951a4
+8aa5420935d71b66244bbdf4b265869761c7aed028429823f530138cf17e
+851fd33eefcf1cb7e3a55798f149595f946dae333f37ab8cea8846ab80b0
+fd354404b5e5eac4cfe7e6c3e7a66311aa8d8b94e8c59a1e0ce7e3495b17
+6f8ee8ed14c1e033fede44f86b1a3017b820d60d76de408b6b01041c49b6
+9c715c484aa6add4dc3147ec63e3172bfc2380535e2639d41537b053a880
+e99de5c5bdd8c9672a2c384ea8604454b6056492cc866c2fe2f1f9556930
+edff9c6db7f08d70addf50b736c927fcbe4397a572d9aea57a07c4dd6a7e
+a02402fbf21d7281fdecd10faa6cc51965fa70cbd682834227e45cffd154
+99aa79774c99c0aa9a3141a222e4db99fc4a91e54980ec9c2b10ba3dde47
+3c402dd71dc879782a29c0f75c1b954c8fecd5c181cfcc5bacb3edc38b71
+ac74f098fa0a1f0003297ac9209e4ffdde948f0a2350cc846eac61707b07
+871590855e555d395efb168a4011c969ae12f90dc87a38e5449fd300f611
+1a50af202f1d5ad3a62c71cbf636d82c27c35cb4f703e7773ca334b5c7bc
+6a95cadadcb55e9ce68d716bd77083855d0b2a672a29249740977b7d848a
+34ad833a1d9ddd4bd81e7b118a62e30da770bd8b2eec33ad1994a581c836
+ec81f99243a9ab233b9e2a0f1b10623797600b82cd0569a2da414ab651c8
+d6f47c0a81959886555a46204d74cbe4f27de08a4211ad764b9a330e5b6f
+ecc9482c391ae086e7544ebf566ba40ef67a6ab4526ddfa4cb98733cca0a
+589903e2b5d7b82364b5714d7b70e3d94eee6bc2786653cf6591f9feb6a6
+d29b3892f33014f2b0227706136b31ec68ac6cd68d556023c8054d8f0863
+32df1ff38c028101ed2db0b41b610640cb59921ba2e251bf8d6bdb3c8eac
+81892c19e354f74eae8ce11d62ae12dc2a3ea97551467907d10381e4df58
+47ffd1046ee994902a4c425ba917f8704ca654cbe93bd04c68b40cf79109
+dd2bb3720404239f5a76119b63b397252fc6ac606fdcb408bfba0031ccd2
+0ad3e6467a09fe11788d91e0805912389fe2689cbca103e7d10bd3784540
+7965f250afde72323921fccb7bdb1196d81fd49f3e99a875e301e683a37a
+9a9d95762613561f41ba1c5b7c64362a508a177247ebcd63b618577d252c
+b442801c379ff346236f4d41a83a1adc16274ffaa4b2f95344116e710b11
+9f0f0a1d66f84d0fc97c6060f94ad6e72c4b821d6d7810a24ab2eb94db25
+e4cde3b5813cf90da162659effcdd3486f8e451dbdc433e48bea1c5541b5
+cb35d5db507b69397bbbfb0e12cd481f21d100b95d20bf3042a9475c9c9d
+d90d8c4eb78350c96dd2911d15edfab3b465c7a76963aedc862ba628556a
+993b335739ce074305e6dea405fdf5d867587b750e401ad170fcbadf948a
+b92f5924fbca8dd8659fb8d88fcf1044095b3d3ecbb88f4b77070236c514
+386c6492334528dbf986efc85f9f8e971790d275e0c7aaf0bafce2f470ad
+039413ecf2b39d846949c932346a1b04452ca11f6ce36ef32866ecb65012
+55c1daca015bf142bf33956d30098388c817517df95d8d5e51062bf2af3f
+aa3a8f0ac463725058f1eb6943d6d0a178d690eb13a9ef87fb1f85b0fadb
+8b6b2709aedcbbcb58ff7ae6c58370209aa60b152feee0a747b60f0b4252
+2526c78231d792f83bce107ecc4e8322597511c7fafd5aba8b3ab0f51902
+2adeed89c0e61c899eaf7e509a3dabb399a6f4c5d7ff9a68b50afbdb67b8
+9e4c7f39d6574fca0d64c4fcb0e54c1589cef927f983940372f6e21b083b
+7bf5a85fe09992677eb32c9fd46277c50fd992c478c292af7e05a3549f71
+2c66bd2818b827bbfde2c481bf489737a71e886f37082afc5a8c0b02b7bf
+a7fc894d8849987758a4fbac084708a62969d7192463538cc4cd31eec7de
+061b00da5a09cb1eb97e3c9a2c2041024a620d7ae2baa99cb070fc01bcbf
+b1243ffd06a4c9ea6a4d4df42f8738fe52a7252cde570a7296aeb5ed351c
+d4b2f6438812cd61910a4d55d772a881cb186d3a3743cc132b27306bdf60
+c3ab4d755e3eff8e10c2ca2431a50f4f4b3bcf60a5112a8ff91bd51eb0c2
+c144aee9e927858826e203226987b292c1d7f8fee533b57a9b055084cac6
+15915ac3a5a827ee04d91fa9e9e267e3ae44ef1101491a27a07129219e9b
+4e20792f1eed42d5ca89c4c49753af7078b6eb6e7a56fff7cecab396b839
+8afdd733ad2884f7bcff5b42f64b4b056a709d656b0d5eb40a76a5f665a6
+9bdb25e0238aac35c5c0caff832b98e64829319aefb07fb974036e0da982
+6129db7ac52292770facaf02bd6afba8862152bf4762425ebbb22d7b6f08
+d29928a53b11aa35516eaea9d249509063c539acfe3954e1f965d2714b86
+257e9fce32cceb0a50661f875926ad7e57ea55aa202f62f88d51a13e6b91
+19391b0753987a5713d7cd96506cd2bc9d9a549e6b6ec7da0d24de9784ff
+7538dcf32ca736754cce162d2008a41fa1c7999c2a8f72da2c517e06f0f0
+77bd88a2ff890db0586228842a011420efe3e910024492161eb477fbdaff
+af1e73d24b75ba72be5c14358c455d538585754e9f6816a226f60e6d17c6
+6c941f516c1f05a618c022c1a7a8874cb0d3f7acfb6fd79d7601ad6dda61
+1d31037f3739bd128616278e7025ca836708c855dee5e3b449c6c5904b95
+caf4c2eb09519564c48af781fbcc49f0dede6cb2be8718c515c05608549f
+d5e54831372076250be22a0fbcdee17fb5849d30205e347e63b8841d1ae5
+71b2c372fd9634e9f16b4823f94dfb807b7c09840f92409ed8041b1515db
+9df22187451f3e3b42737a11611a4a942dec953cfbf9875d36a363e3a2d5
+05d96b6f8f03b7ea1c251bab2ff79dd8cdb28796d1fd364b1103da119bea
+64ac34659023685fb8d5b2755ce523b32f8532845e4c3058036f0862cbd7
+b7d4dc2020f7d29640b5007a78af6d931512aa015585bf80da89fddce137
+02efaaea51c51c856d7c8a7f285a997d749ef5fddb3eb145f51b1071843a
+ff486c7ade3943ca2ce5387215faadda2db4143311617f6281fbc3f8d261
+0272cf235564703f832e85167cb444ed147fae675654fe08945694f9e63e
+3f1fc2f6a64f6e36c0ba774a8b20bad6115ac54450e32d35031e7555481d
+cc0229df599951e758a654282dc75e6242e141a3156a5c98c533228e8b51
+1801c716665dfa23fec5aa20f3fba6ba37fc88258dec647c3b4c85b663c8
+30d763aaf568bda38558e4314b6b510d974d9f21c783c4498eed62c8db29
+bca222f27910b3d196c0e8502b234a739da32a0f6414bfc5e4c9cc167989
+48f996f1b30d1765fc99751beb12168832b5f7f91a7df5940eb763731f69
+939db425ed380c3ffe2b415a7e960055bbb7ab436e6b8cd66a12a6662cf8
+8df26c3890beac4b2b6bc3c075716614d2045a180905eb9270db0f8e42c6
+c4114f285927bb03e92c3d9301710dcc17190a1f78151388d70aec38540f
+031e376d8f31da955938b22196ae56776826c7a658822582a538aa4752b9
+694a5e814ef39c1df410b75d00cb9069cd47b8bf1838f92ef5a1b91daca0
+2d8798c1df839c2430e8d0284e1d16ef72b363670ef519d0d06afe326f37
+ea048fd2e09c151103117879c2efa268645584ff4a1cd478536493adbcb3
+e49e42e7b668d9f0e77ac5a321fd7f339caafdc93267144f9467b605c869
+04c3d1b86bc0e1707b47c3a4c1bf991ca356fbc32e635623f44276cc7358
+da5441438b5fcb4a675bd60bd112cddb4c8357595f7af082af0924123e67
+3a1e74214e7e4198fde4aef1e85e129b6a78a1e975978ef2450c63232588
+6da46521b93748413e02185ee061648cdfff10ca5249d19faad78619783f
+c10cb77554bb502a640e5b243c9e90ff169a855b65d29d25b4d30de4e53a
+139e8a20059cdb796369ec40057f74b7dc4b5a4d3dd463c66be4e8a0026d
+ed6f0110c45baf21f197b649026aee565f47c27a4abc1553790303bc2b34
+adb7c6e54723794eefaac4dc7145a7c3ae16c6bb635a704efcb2b9bb6516
+7654245ae5d466b436232a47d9a2247c3a5a4ee9a7e6f29b83fcb9d7082f
+aec5caf6b48976b000ad92199df65742cd8de4af0541461fdf07f44e9117
+8e8ff2423e01074704dae7370df7080d1745190cc29435f187afea37e30a
+a2c5dfd9c4076e15c1d80b688acaee8ac7f4f6f5b5a2eab3978da7c77958
+719c696d9a545be2d44b884eb94e873942cef0ff497450fb0ab21c392ea6
+4cbec0ab283283ea4b739e36f2fc145fa57eff433e36fbdf217db34f8efd
+02f7a15b77311a506749478551f11e1cf0c984ebd27eec2197babc950624
+2f7c425bc0bb35a1d332c3d7442433ba809a15a50a6487a1cee900a9b604
+747c6821512b934578bebbed7d35d92c35be3ca128dece0dd8e6d61572b5
+6c60a75a230932f6c8f13a0c82475d819d419849c046beb618ffd2ba9b4e
+35593ece10ebba2a923648ae9d921255277b6e8152837d74782b33ff5ad6
+a07d8c6c1e59132d3e5e1f1cce864fad1f7963b5017c7ebb3d29f2af65b0
+dd7322dd6e94e812f0ed2770466a41cc40a6cb57453ee0de32a633a867d5
+fa5ba2b86736a2d2c7cd94af3dbc925dfc2ddfeb04f40481507a287e1ced
+bf35ebfba94429ce54e6b636c33d8821708cfec3a450e15c393b5d5bf7cc
+848c9c5780dd966d01b34db5f9c3137fa0096368f2ae8883e62cdbfc6132
+f7687fd1e9614779274f6b92a12a6d4a8c415f59510913cddef67685cb4f
+97fe0f7b8ce990cae9d8b152b1fc223360fa5480e23d62bfa69df11d97ef
+8b9d4f8f047301f5db7ee34b4f3996a6e226b8b932a195cc8ecdfbeb34cf
+2bc204769a1a1ab2e6be18d156d3c1b0b867ce4ac4e57203585f98ad8ad4
+a1c2cd9823f609af8be966f7cc89e787435f312b7c67c2f9efa22f169a5e
+81c8f3de74afd45675b477ae9df1983de2474729ec80fd5646058051d8f0
+9b253e57be5540ba0b7e9c2a588879d45dac2e94941b47052295ba2909b9
+1db7313ba5d3c780113ee736ef57d7a9aa88031ae61411f32ed3ab2cb97a
+978abb27b822c44282ef5168148fc32ec991f705288c8cfd6c838a37da4e
+2a5dba5d215739005fec9ac00c546884f860db130cfcc1f181cc5f913f78
+9bfe610099cde584d5dbb15604665617d1359d611049eff679aed936aae7
+c27fcde30555f0ee39edb8512bde5007aa9b1bff6a4b6b56e883bd284e21
+3602dfb4465d3111682d4e2b3e339fbb0e0455557281788a6b55eaa5881e
+62ad1cbc65d0ebaad4a5600899b9320a0fc98e8ca2e7967c6c2ce48910d1
+80bdcf2f616e7536f72797e3b1bf7d4fddd08179f5f3429bc3885307089b
+9f4dafb2feaadc8a761f6b41f9d7e6ce750d5d8ffe999da55dc239933bca
+1524aa0078ee24881e120d774b293f1593621230fd5294428653eb453fbf
+97b275bfea389bac5e8ecae12389b15f64338a59131f6abafe3f632c215e
+38f97abe80d3fc93352d0e27702bf83306a03faed8f89160416f1c3ef5f5
+388f2831370b64bf7cb737af5ca95a8023815a222be811b4b85cf52beb04
+6f0c4587643fc0da77810a69bfac4c0a4a71dfd0c0ab2d5635020d264958
+8a8ad4e825478651950a83d5f0f2bd8cc31e825074404d16c05354d18730
+fcd42cccd51437a2f2a90a6a9e294d30a5f5e53f18e53ed4b60f0e0f6159
+4fea136f2ed0c8af5ef7cae946b33a18d9e2d0c8b8ad3ff0e1908d30ffcd
+ab58a28e59fb12d1f28e783ed58e344e9105d9bdba8ecfb7b0df61cb7f43
+7924ff7160563be7094c769f36fab8dc74207bc789eec011e34ef81e3747
+8cc4c9d5a1118ac0a685d25136f7e295b84c060f4fb63ae4cc8af1b96ada
+4b183b054df7ef8ca30aefc9b0cd2345b728a622e2424ae0aa578c065e58
+e8c34ebd2b6df648a9780dea293977946a9a3cd8ec4779f30f8a4b51000a
+55dbefb328e2d5098dbc3f9859d49a463fd24cd8c28ec426088245b09080
+c79ba43fc46dd55f2ba2c190f8c13b0d883fb6737bc0f9acb5f0ac3bfa4e
+8c346ef5d0a9a617bfb9e2fd9fbc68e39401d5978319fe5279108675e8e7
+68f42e01a0b8c133db1c8be7e0a553ed1c1676ed488b0583a3317f233f7a
+4335b7b4ee205d1d324957204a51a0b37241938fe2a54d8aec4a81493384
+590432d5afadc3a84b4e08771be80f2648acf9fbc777a51b530f0ca34fa7
+a8a8a1cb391d0db8f09f10bdfc1935204231718494dba12bddc6fffe20d4
+f3b7062feec978a0797804898db2f14279363b72708d6e7fdaef71aaa495
+ed16db39e5ccea3090cf20c2c0d66eb908ec814daf3f54b4465956efcdfa
+46071a0eae7ab79a2e227f8b2819c1c5ca018646106b35303ecbe73d4923
+8cc10f3bbbc943bfb7d547132c4debc1923df4e8120a3226cb99eb8ef162
+5468ab720065d6baccca3bf4cdfb2f92b61428b033f26b985e8411820ca0
+cd4b5304516465f29c894a6c1bad8942dee1382421a6c06076dd06451ae5
+83b9e7abe0e273365247fa24cd68e9b220f2bfa35adbd60259f5a0de4b66
+0b0241841e2ff4585c658683dd9e6dc847000b238225990820c1faeef4e7
+39789b9e44ab037730dc4f6c60db05e7847360e44b0c14e59af478cf54a9
+670ca35d4ee3e3f81ebfc58043478199aa0e35da74b4ee11c01178e44235
+2eee2f57a651fb1be5123acc973848dd79b1bf5b69dfc2186662c9a54817
+c33cb1a6b589eb64a5885ae8ed5e8ffce9cbc9f1d04faafd0274d5702c22
+09ef9e52b357e22f458bd3beb244fe88c36d088dda229e501227caaa72c5
+8a7d5a95fb1d7e380819daaba59d2eebdc5f7cc2bcc042e73f13f2dfb19e
+f5ba70d00e74bed0ad73726dcccd7b3ecd016dc010185bc34aac6722927e
+c4cfc8d40d5b88cd5f01f20d1bee72b715b9d4931d81dc972c59b3124ca3
+5e773612673e4393de8b93b9b3c6b37860330700514cd31919f42a28f9b7
+c81431ac8912adcae98269d6a64f82228f0edbc59de4f69066c476fe351f
+9869a4bbdbecf649a2e35d019e90a1d280a1fe55bcf528158ffb01facf46
+d9f6eb0266149ed40307d9b070ca8c5e434cb7a555b74d18a6069784896e
+2f250369fc6b6fc426773c64f33497abae8096e2499bc1f5b087f086dcd3
+c5bf9b76d0f50fd3267b319b8363f14a342a90cf0236e8bd8ae8f084af23
+7d04e56efbbba1e86d352ff817c67baa3be98fe63fc4d04c7c18a76573b2
+c66b347f7548d79607b84d90899dadbaaeb9fcd37b1bff2ca865baf35c8f
+3e4be98064e0fe57b8c9d5caab1aa997afe6fb62530ac8833236d5ac7fcd
+65dc18e1e02d059179ee02c33cfc6f5dbd06091d08942f420d359753ff2c
+9edbe16cc23a97cc6b66d32be0b41e0dcb983aa1cbb6534a16e8f6e8b242
+2a95b880c61351a76e1d53e5bfa9aac679b60a7f9b2dfdec878ebb0ad30e
+9b6febd33f986526f03e43ddce13ad5264521a8971752c01cae738ec3bd4
+e556dc6bee76a8850f0ef738980274448a00d8681787a314dc6b1cfb81e8
+3825f3b04ae252ec698187d0a242389eefe1eafc054c9bc0c303a8ec23c0
+63307b21b2a98034f6e7c4758be50cd35474eabf2b7c4bae6ea1cd50883d
+62a38a22819cd666ac6d2f39b1fad6fa4034416c03d9795e4caf59215672
+f2ae88619f172c311a2b7b301f30cc312530762aa42361dbdb7640342928
+98955bff38fc2cf6c716ab525118bf0b7257317c8118e9253a1aea6c878b
+c6377d6428e8ce5fb78544930a46d02b4b08081befc78402ca444c742c20
+3dd1fa3dbc351df112dda778b1e5c3984b03ce9e7eab15dc48ddc469c7ef
+3543f8e19533ac32a3f6b8b12103582303cb46086d7eb69917b9e22f92b0
+7f794b80f5b3a32e44d88d2e66c9e41dc9d60e346e0c99ab6604bbea550f
+be4a1d9656d3d85cd9b8d632a1354b76dea1d876148d9bfc6d7108aa1b12
+6c17dd16a3913fa263fb94274a2aa4ce87a122d72770f3d0afedaccaa121
+bfc2f42f7a0ad1787bc858c3f6ab8cdae76d868aa3bbabd1e166a7ea0560
+8e5eb1068d4cf2d77264218da1ba33e4f1cc3d24868768747fc08cdcaf57
+c67b2498246d7ff6f33acb2f83a970b6b67aee0b2fc0b76c2b4bddbb9b98
+6c5a0d2323416dd954f7036237b18cac8a1ceafe4e6fa1d2396b487a03b9
+b3301ca9b795626fedb3293b364fcbe29b8e606f35863284322d82bb2075
+737e8062454891e245e0f1ec7743f1997b3b36d24d94f69be4ba218a9436
+466b79d816e6a72c7306e3c2711849e9a941983cc589e2f19ed18ddff751
+36e253edaebf57b674134684d1faa21e014b9d5475ae815f56b606ab62f9
+ae1c32315a1448ddd4151d06f4aa1347444d3240df4f82f9fc5dc8709112
+938acf9bb25e7a4b0fef0dd2515b15dfb40d174048ed2a3d841bd0e6c821
+e07c5e959c17d6f2ba659d792c9767b9172453ae9c415a6aa818f3999167
+790321df7695fbea76ec20fb60b516f84d59bfdd09a2fca1bd5eb3ece33e
+51ed225a30c349fde4336163d79ba2053343ed04eccdf8453b33f9bf033e
+ad5bf59225856d7a691657cdfe29eeafb146f41d4cc9c8d4ae0d2d287a93
+c16dc85f7308390929bef532aeef8770b9af6ea7fa5e6e968d211d1f0cee
+98a09a4547ad609f62dc6b5ba70b9a29ddb3faa15102a56a017b9fdacba8
+955f687e2d4ebac571937740f1c6a3e5d9584ec9d7758fd27a467b273e5c
+5d2b49a10f4c935f76a0718347ae59f9f5e29e8f2695664cef0a10112636
+48d486e5ee9c313b8b2f0ed6e9c9a6a5ae154e1f1db95164fda121feac07
+7861c85a765929a69e157e13d25e5e053bd57d16079119329396e4b3ac48
+fde80e0954b665d61b7d3beb0e7b3800b4fe7eccc741581bd4ebe45f1d09
+0ff8a13ff6ecff9b76ef312ebf48775e6600e8261d57dc898edbec1ce72f
+9806ac5a9ab585332133af60ff2ac31b6e97d28bd232a50d28231595d2b2
+c21b253a27a7d430a778ff0dd446bbf93c37c1a4fb1ab70ad1c6615b515d
+72462d81535145ff27630debb40f8439e093c90fec7ebd04ad81866390ef
+8df9d4d4aa47b8da9ff7f5ba3a3a6cc61918639901f4c58c86fd1844c05f
+e795ecf8824e5ff579b339e18cf298786806e9159bc98694cb45a3c33c51
+976a86deacb2abf0ba891471a846ee9f0240ea834f1df61bd439ab8a04f2
+35514a667bca49982cbb4afd0f0b0d9042130b4376a8cdc353ee7846cc80
+d13b38ff7dc0f722e241eb37e015f2c3c449ae1ac99086ab4d09e359b4e0
+cb40fd539c3d95a177fd1b2b6f827dda8f4f37db4d2eb5c9cc0c05ce664a
+e275272d1f131afe30c97e4c1ae8e40245757cecdda343fbf57f633ff29c
+cddd45c54eb21a3e8d11356f26c4d6dfc4cc24d14db7d1f569dd504458d6
+421241a9460b760cc89182a3be4d5e274fba17b0c66a73a31244f94e0e25
+a89a4349fe03bb7b2b76d5087fcf01e23ab8a946541295fe3b8158c19fd5
+281982794babd4d8814b278218e89e9338c7031473cb0670c0010c62ecb8
+d0c37abb74a68f5532ba49f479dfa276b91dfd95d4689f7553de743227aa
+96b674dcec8186556ba8af629a79c624de297c19eaa86e274b4ccb3a6cef
+807469a797eae637909c19232f2801b5bfad8a6bdc6565bfc0c217004854
+dc654c7d98697831a625b3ee7ce24f5f05b0aa6ae0187c98c221820c5a23
+a27533ded30354c4caad3aad261ebb5c0053721407d9eb6bd55380930840
+7de038d2c6a6acd77fef74cfb5d961dcbeaa2da6b8deeca64e4adda73672
+56c1361c7ea99a6b95503fe901d056267f6e36db78d165b74483576e36ab
+a19e6801a33e9e0bc21eae2a0e8e56943f4c2fbf9467afed079849635579
+ea81fde7e07a1c9bd12c72eb2ffc2250030bedf8d8542ffc4b8ed5268925
+c56bff45b33e0bb0f94e12ee694dcfd34a57724cf3b9d347d7a845a0c58d
+a803b999da53cbc1e3955ead076ce86f62085985c9d9fcfdab90b2d26c73
+d767084eba703a13ae41ffdb2a980f3ea0f0b67ed5a0aff4b4186bdcf217
+ff575b1508434dfce67a20e40968257359d0c210b28dff561b8ea85aa74f
+b443daa56f4cc37ac6f5cd3951591acbb84d036170156a6640000982e7aa
+aea636f726609982cc39cf9f0c42868a69a3a54d180400b29094c43e624f
+bcb7a087b54cc2ea930f8740828b6b6d7219ac2237838f63df73fb99f4c5
+1de03e578cf7047bcba4f08a7c56e008284e95cc
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/fonts/Courier-BoldOblique b/fonts/Courier-BoldOblique
new file mode 100644
index 000000000..e6ad560d4
--- /dev/null
+++ b/fonts/Courier-BoldOblique
@@ -0,0 +1,1686 @@
+%!PS-AdobeFont-1.0: Courier-BoldOblique 1.05
+%%CreationDate: Wed Dec 22 1999
+% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development
+% (URW)++,Copyright 1999 by (URW)++ Design & Development
+% See the file COPYING (GNU General Public License) for license conditions.
+% As a special exception, permission is granted to include this font
+% program in a Postscript or PDF file that consists of a document that
+% contains text to be displayed or printed using this font, regardless
+% of the conditions or license applying to the document itself.
+12 dict begin
+/FontInfo 10 dict dup begin
+/version (1.05) readonly def
+/Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file COPYING (GNU General Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def
+/Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def
+/FullName (Courier Bold Oblique) readonly def
+/FamilyName (Courier) readonly def
+/Weight (Bold) readonly def
+/ItalicAngle -12.0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/FontName /Courier-BoldOblique def
+/PaintType 0 def
+/WMode 0 def
+/FontBBox {-61 -278 840 871} readonly def
+/FontType 1 def
+/FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def
+/Encoding StandardEncoding def
+/UniqueID 5020948 def
+currentdict end
+currentfile eexec
+e98d09d760a3c22cf119f9dc699a22c35b5b35ed6aa23593c76d54cabb5e
+942bf7d6dd84f1664b89699c74b472de9f8e6df925f6c4f204e9f1c639b4
+dba988ed2ac419ff2b2bde605b8ee3264edd66412d4f21c64ac522bdfc7c
+5502f9c3f3e5592b3b2093d33c9bfaedd2d49e89aabaa832e23f062e91a2
+5032519d1868816e44b4e0747795003d7930299d6e1e2a5bfe0d595dc97e
+140989ce81d8d7f852ff9cdc7a1b1b598c69131dee005b415805a16d8a12
+3e6a2f9dbf9f3f34a085f42fe63acd931cd846b57d30dbe2d6b4b42ba7b3
+841204cf185aaeea797b0d16df1d60060bebe83fbdd4931af1827b449bef
+2eab8879ebefe5590120effb8f783be00e602fa76e53ee4e20e9a55189be
+e40ecb842d3838dcc54fbf7423229ad68b98e033813b1a3e460f4a9baea1
+8760d05d85984b0b3e161f130d92ab90a1f47416b3f21d7797d284422bbf
+3f185bff2b2de126046d090be44f9a5d8e6c800defd3a53944fff17566aa
+b69c8f5e58cd7e26c105bb2ca8ac07b6ff104375a98e23e4ef5f370311ee
+aa1954169cdec1a823b51f1da93e50a6c032630f0ed2f0109824f7aeb6b3
+850ec9d1c2a9bee7dbd8c787f78a9402f96c7fd756f9c63151ca0f742b8a
+1ee50d127ea8605c1c1fe194833218e91e06261cbf154e7ce4cecbb941d7
+659f6da4bd998df9fd184e6f6cb0583c8ba18a7d26c9e8cda7f79784f053
+243684693700a482a8f2182c9142114f25533cbf9ba2b43d833aa0fc1d7a
+95ee86cdb19921b4e27b487e2e353c8b942bfdcd06974b8115fa20291f25
+71fa63555110b9fd8ee1bc9467ebdcd4145b372ccad7e9f93460449f2433
+1a6030294c172bc918b1266271e8c39e52850d83d2a78d8fd2636d3eb927
+7275f14498245fdf262d54ab22c919876d3ab407f07fec8e23d28acb2d3d
+413757ed4fbaf2d03dbaaee70345f62672a238589a03b28b03a3a1ab6b3b
+970d28d2f747facb07bef7e8cbc0a847898f00e6a27320cf51db2e143935
+f16e2c6da9d1eb5481f6e75852c3bc7cbdbbdeb5b27a299e1a4003b08965
+6a96de26fb54d3fde40b8dd64d01e330da29486b752890a2e0802fc871ca
+86cb8eb4037a72fe7350e8a87bdcaeaf182333a6bb929b7d202bd5e4d1ac
+9ed69d15f816e39d45089dbd9ed2340302f639496d60181c00c3c8401715
+85c34d9791fcf040f1285874367e125be582088c01dcf773775039237da5
+33e679fe7dfb9b7221b04f2d69add19ecfda0b94bf53dc389fd0666e7fc2
+92383995518fb78173248d9ee7f0fe79ca89ad014a1916da267aee3ce701
+055bc88c4cc0053d8d7e09ca072a04f15b1871a3c1113b29df7fa0c1a608
+8ddb6b2f97e03d829f6de8fb1c51d4e3448730fc94af5d62b69e2afb843a
+e2a8b12d5046e7bfe9fbfc2404bc6232e352b25a128e8a501d6fecf02571
+9e1e1ad7890b40ffffb006dcd42a65402df37d8b2b91ccff1bed30b8e192
+b5f2f53d263ade0798f2fc94d19693734b16ab45ae0d000dee662b209db9
+3c541fda6d822a4e2349f3fd199a654bb931cc36f56bb2f5ec563398d385
+459f964fd343d9b253db726e9d16fb240a84f39bddb76aa7edbaecc0124c
+253cdce59227216a0c74cef8e44ea7fc0dda7433a3b0fa92a0f6a00c43de
+f2f079668ed3e9929056dc1185dd78c663097fe8153aba6410dce819eb69
+d06da03fae4798505301235d725ab2601d935d80daef960061a6c420a696
+a2a1096619f8f0894c659a61c4076664e0ff1e8542acef3376b8e2b48975
+f8f546b1ca4ce7bc9e31fab84df061fb7452459c6c7b68616c8c3c53d4d7
+5830e418fa8cf6e0f25ecf30a3c9048d6635ad9e9f4ff04ab84c2ca1b4da
+a9278de5fd299872b1e57dd7de2478a2b21b2eb96896ba53690a7be8a0c1
+2a8e020dec6f3fc741998fce007033f9959c1328b2785c1a8b26351bc740
+40b30fa99c4c8c7bd3c52aaf8c7ddbfb0dad72d8953e25ad54afc3b53f15
+25a4bbb12ea7ecd712b1a4029742985a2d57223762d6d83688457515d90c
+a3ffe21d9099979e4ebc79bfac708da0adc420c676ad5971288aaf2b8dac
+4a74715cfc76b1e6d52501e0f776b65065458e63e16dc2c6d6ce18adc8ba
+94130d2a90780a127c9b3d878e9426ce14967f8e65e4bfd9f47582ef2c37
+c361c1008db7fe245a6dd6c5bf8a84ccca05cd96cd1aeae072c09856b336
+563e66415b727d58d62e9dcb7382c21bc7e4503c30346ce2bcf4baa2c87b
+70f1a713ea26fd7793b114e3b77104d5f1c5ee8c282bc01e591c068973f8
+53c5788119d0cf53ae213c1770abdb1cf3fbf80a3e77f7db59f9302ea55b
+bb16e9f775d04f3242cad88e2a1cece807db59daec7cf7e89cccf7360ec6
+11deccfd50431d67fbe30e80843ab28cc0e3e9e1374c24c15567453e8e92
+8e7305fe9eeab4e3c8b1bd92140bb0d4d40f80bce763c25bb90f35a6e907
+759e574c7e9d342a2c78b1b78b68cd9301075e6aa6583a4e18528bf066bc
+84375210a973dd1a60a693b45eff6c51ff890946ad331ac05ef80bba6084
+24a582968548d1c5640cb8285786fde01cf8fb15c5b821c5577f7abe9683
+c164ba9a691906709ac46d664b833aa7fe5a3fadb67ad3bd82ae43087ce7
+0212b469cea0e28bfccec30496f803d3ec1fca366ca925ba3f20be9c34d8
+2d0d7215199e829f4d0d7b4e9630879da68ca05161e431b36510804d97ab
+c1891cb76ca24bfb7a897835e67f2c2ad7d0971dbbd6814eb6542f7e4fa3
+06fc97a058406098c53564efbf4689dc448fb69080a08a54c3602b55a681
+09d3ad3fb83eeda6ddeda6ddea4ea424553ec22fbddef65254488f91ad4e
+d38ef195c418428eea7fe850c62dbac2f9e3c9cfc86542153d0d5caf94c7
+89160cee1fc009d0ce68951a7ae1b666e4abbe82a1c6a3e95859352e8400
+e1f33c55626a04c3818aa8a917c3f5755e2eebcb9f3151e2a02339bde457
+4d1a65af690685ad8dc4a64029ea5bc1ea733546d0b0f8871cbb56aac6d1
+f2637c420a5cece2e4229d4473af7ab23a7f6a33514ebba57453ae38d6e9
+3bd8183507acdb9547a6fc5cc68cc72575bdbf27db2a2ad634657dbb1e1c
+4eefd59b0127998b7b12269a61ab02990a59e7c8ac9ab84d07c9de30bb68
+4b29637429604a9f02d9d8923ee27f4e0680bab37e3eb4220de2e271738a
+05c3333f07d04441a4c77e5cb0fedd062f3d0c93d0267644f56b21b1efda
+d3b65e8cc0d2cc526459cf239119f0da1bfdd81f7a2fc15de8658ceac01f
+a7f87e6028a8f25ce711f2706842981edea8c667f98b2e1a446398ee1aaf
+311aa911ed16df089193bb58614df7bf5963112fc14c00dd188fcd6ffda5
+12dc8fd71c300adc8661af41cffb7f70ba702dfadd1a701c1e74abd07e80
+f9314c3ea606aca7574f4d1dddeb4b3508c78cbb376677db4830435894a6
+01c8b3c79fdb04aa048d7e0e5ae3a5db490459b142668f8481262e3d49ea
+ebaa8637ce0211735cfd5bf298bc2274a35577b95bd69dc5af099f64f3c1
+1d64d6457d9dadf22d52f14a50d7d0d87b2db6b1e19224f72030888e2441
+0f04c89aad7ef45574eef2036e3e9e798d02102f63c6b8bb018a915e5af6
+2ab7bc7db9b4da2809bdbe25e57516e8d188e19868bd2ae02af609eeda35
+8829689f61d8115dcae38bcd8ef8615d562a83cffe5e97e2f017e0b78957
+56986913e1bf885786e5543c46671f6325f04d7a78c53af15910e9c0fd27
+af28dfcd149d285f44c14b6f1633da9ddfe683d7139c9f5baf89a154d46c
+6e4d672452a43cd6a55bd1f27c4a3ff0d14a86193ffad59c5b31ad8807da
+065a8190de638c984b971d580a7cc9561b4ff039a2705f6bea4b53403629
+0246bf9fd12d766dbce0ddb5ad42fd48b82f4841144e5b06e3d889c0c7cb
+bdb2cc2b353c392c7d740446b36a8126503c93150922d97e926ce96a20e3
+e698ea1972e36eda0f9aa7693c53cc2994a16db61e5e4316b0f882afbb43
+b8ae94f7f28eb7eabee5f9f3364ffc1aa9342d1777427796db0bf7d7bad7
+1ee2f4e209dbb15254391987fa678905f233a241e77f26a42a1e2f66186e
+1d048a94be60cfbf61d5c5bb361dd4d1c92833cad203c6dfbfc2453c885b
+bf4683a234fa558bbef71c2fe0f0e8ccd545cc3175a31bc100dd087e7321
+932c2779c3b008afdc61117d6a1661ca320cb34770f4d1b490722ce19fe3
+698da34ce35b1345951ad982aec69a78279dc4522edcbb01f9cc4b8cc52f
+9267b527fe427885d67cb62f2fc7709de4ad29c7e6e1aa6dce99a30ca2fc
+fc6c523c90cce6062e25a581fadb1b892cbf35eb20abc4068a73be3488ae
+a12b50635b70cb66d9ab795c487a9d76c2b01ccf27c4df1007ad3b68e3c1
+367def56f2380db21da81a46d9189fecef680f15d22b30ba3596e4fab3a9
+188f0f11bac53df5b71f454996c9613b3edd464d9c9e9844cd357afb858b
+fc28575ba3e350e88bba2a045be02edc0a24bc3ff21f98e318d84cf23ba7
+2931aa278ee21a479375e0d50193d8f8aadfe254619cfd825a559f9639f1
+98ceb491bad5520f1199332ea0cfaa2bcb8faa7d00f97fdc6ba2e11f15d3
+00a9676a12f0e451f92d2ed547e2df0d5b8bbd40bb5aa2df66ffbe68537e
+823da67c29361d9c89c1fd191d9bab91309eff5e0c5758d9ea0b9b1997cc
+101f7db3788bd9ff8e01e1cf1ba032ec90dd5952858726df33cfb6a00b25
+497cd5144edaf481490f26c802a0a3d2e9e8114f23b3f0ff23fee24d1aad
+bc36492e0edfabec0d4fa57c034c47d2e8acb5e9ff5ec486da2ac3ed51a3
+b36933d502044bcec7caeebd3857d383ddc28f976322aa26315e3fd7779a
+5031ab41ef0efbb295afe066e7c1e8083671e51628ec799a549bde48a502
+f879f1361af8c177b122fe8eac38668d8882a46e7d20587bd561b34486da
+d36c2915c24fc446d2bbc41e256af4ea7edd28914a0191ee4116961f339b
+b85bdd38c1417669b345d46f6b6ea2e3209812ac61d080731d0dc89623c9
+a28566a726a6665a05c70c7bd2e1e757c0a03bf89be801063e40d6b64927
+9cf4fcce655cc6cb2a2d95c846d6048853d654286d5c2c2d8eea94fefb67
+62fc17cd93ee1fbac2dffef877c74bdace7163b654982d864b688139dbf4
+7c7ad4f38cdab42bca53eea14d4262da8328b75cc8a342570c7303c053b4
+c507ec2e3ccd2ca8def551ebccc4f6fb925ba2ac8f7cafbed0b0bfae20a2
+7eeccedaf790eb9052fcb6a254a3ed51374c9255cb4448f99e418770987a
+192802766417dbf6929fed937bb340568e826277e8dc38f4dced644e23b8
+f298b7505b11b37bff8864a718821d517dc7af2d9baa66195e7beb2a6cf3
+0a20cb7a7281c13b1e95396706eb3d588f93d2172dc5d01658cc2a46228f
+2f6457ae884e11815930e90de7ef66ec7e56d539a41b7390b4c13b29cd54
+b43e04ef1076d442abd41bad91f6bd2b5236669e5f0b83375a363db705ac
+d528803e445b2032f410a6aa9bfcc1c704d9b9364dc7ed9fb34c3cbc291c
+1a6948cbe72bd0b860f43bd43ffcab6c190a94559830786a58ebeb4b8867
+73a24cef543b06b9def306e868dfb69f80dd18b077606efaa288f3a5fcc5
+ad3dd1d1a38e22e8abee50a7a6c5cb4407cb9dc339fc04ffdad6e48185bb
+e2e396fe1c39860f942bc50aa4ccdb02e5f961f8441dae54353169cf2086
+74a99eaef76c99c4ac8a6c0c74508c7e47702ec17f90e40247493ac906f2
+88deab608ff6a5e6efa260e04852e7dbc79cadc19ae8bf33bde20f7bdd11
+c600e8369e0da03b877cb4a08f719102d3c3f2f58ab4b0a3afc2a91090bf
+6aa5ea74ac07cf30503cf515a1bed7d594bfecbf6fa5cc4361279f607cbc
+7ace2224ae4fdb898397c500631e6f2bfc537f457f863e9d8ea51534adac
+d7a1ea08f44d8ae882eda411b07f25abed54fc52843fefe2fe03c7bc2cfc
+c95eada5276315bd138397102f056529ec7f3e12add6a290cc96dac9a467
+8788c06355c623059485221c5f0321533cfd004b4fd79c4792086d64588c
+2abdc034771fd02c7c42c5e14c7622cfb21934ce02113ebfe71c9e3614e7
+2f1cdebd4e604e67094e5694129704a229d205f116b43c1c76cbed409e1d
+210ef1a405f70f61c30b24afc073a3a5b822eb217db46188767fe33ad18e
+9b0e59456db4d33adc0f189ba48649e84d6c099bbec78c24f48704c6a934
+ddb1a96e5866f389f03b3635758a9dff6f639bc64561a5ab17aa3f1b4bdf
+b0c0059d33e04946e9a5da4de3fd55107f9da9a971ddb14da8f37572e852
+b554db6a88806f4661b0ae234234e15b99a6c416ab21d368df2d1ca65e9a
+3fb736da74068843220d91631b57d7b00fcf5f246ca92bb8389d951b9baf
+507087226da9b5306277be1f528f03dc61168113ee5647a72cdd686c74d7
+2e13a077c406eb58894c571ec9d58c73a4482c30022ae383dabb4415de7e
+758ad9f69244eabfe52e8be1e1429c1ae59b31fc24a540a31b9114abb675
+8c43096e6fa3e714f7c2a423a671dd42d56a5303228f6823d5ba62e1adec
+028b00c438969c2ed5c1c25b9e8f2b5a69f89c9bfe8bbf50c4fc6bef8c8b
+b7d6f3b4858dc52c5a8a90e5b17dfbabfa38eaf53f5171ac6e29af9a64c1
+3d676edb7fe8555661bf426b71fb80f984a37708965e7198133d64ba3eb4
+65988e71f5910ec10b0e3db681e7ecbac9bd9991e6bed1c3c75a8a0d9806
+76dd592bda679a37cfee4d4df2fa84e01c98500771cdefd3e5d7c8fe5435
+e39056c032e5f4994c8ef1f5799ca70a3b3312679b2daeb33afb89252468
+67f710a7ed78aff3298bdfd5bbf5f430c9c159c56d05c65ef4404f4c5255
+1ebd7ce648ad2a44b6bef6d18ebfeb550296c20bdae04628743d7ffaffcb
+8d473eb871b6fb4ed94c8cbbb03dd69b1f5bb4050ab4f0920e88ac9ead11
+4bc532dab69814f5c002004a959ca630bdb063be03bc0d35732aa580237a
+055ebae9a00ca10db283f6e19399d9fb9bd66c86253bd0d3dc730b5fc898
+bfa550885c4e3cbd6b72f43b9e2a0b1d362d630167d52695f07752052a37
+b6552aa290d1e73023bb66a4ae1506a3c9a0dce0a58cea5623686322a8fe
+6e88f218020125257284f152ccee92313428eb653355437459e15ad374e6
+86aca66e737fdfb7c287bea41420019b69b6a30d0a0c65b6d4b0608aaf9a
+b456e564a8ca2dbeed7ee6ba9c4ab1066ca03c4e8acc36b58dd6d7ccccd3
+cd58e6d0bd984c5b3fede36297d9787a7bf16a899f05b2eecd9896946ca2
+a3d857d8a83257866aed94fb753b65a89b976561cb05540ff9738ce0c2d1
+84224882b315c1ca09860d6f04d116b7e7605eb04496fe7df29c9c4f98fa
+fd33b21b302228670549bd5d89433c05906f48a1d4c31497285ea9a759d2
+7bb39afdcfdc9cfbbf7d2c5de03ce66f5217738826e365ea2e28a53d2635
+a33caeb8ae66297824d8fd7cf7cf7c51d000dc0982f064c8c397b385e83d
+2cf5b41e84f1261b101b77d85c908712dd1adc5f6682c94370b360d245d7
+655e10642367ac53a52c23a1d840a0072e0f960de20391d1363a86f22c82
+559eeb01e95e7ca605528ea81a47d7a9c43a2cb63d8350829ef0c260a2f2
+0f5a75965eeabc20b39b8fe45438406736152d6a118f2aff6abc2e97a7aa
+dbccea9970261680af87fcc02a68b9d95d6b04a7d3e83600d77acce0fb16
+23841695ff1dd207d1fa8d89411690ae22f99e8021e075d1ff1f90f7809e
+b1dd8873e8fda2c8451df3f6c5d12cb930472b04c55ebaf709d727b64cd2
+49bee11f10f509856a1f63351fa4850bbe42c8f06c15605fd3473aab9931
+7b8b2a2552443b0e331d9f0e9d91a9ee1f6f67a0d65d9f2ac166c4f38050
+92b7f7e569855a58a71606aaecc7283757a69cf37cd61894eae10209a69c
+d3d10c3f37287851e0b6fc5784c0618c7e155d2d622b23f00abfd601e436
+1ec59a0575f6f85a7d90f83815fc3482954b8cf71966c47f95305ee3553c
+ac77ce96e7c33f2696c49389ff0abfc865d7edaf368dd7871ba72a097446
+fe8db83789cc43b31a74e997fd7edf298c10d61cc0976e7b41a7a41d83ba
+890a68e6cee7d79493369ef2d8812a1ced1880a8fd4765097539a7cf1ed1
+e1ca04bf92b714b6c71f406733e7452c826c5ac226dc16a18a9de3ddf126
+bc419642f9e1fd36d162ce7832c85b5558863d262855fd6267a154211c96
+73670fcb8bb9354820650f25ac9fb6e636833211e9d41c794c2a6c21d59c
+53f7bf5f264f0ceb82632679bd0a0d598f69fb3e983597014e2986b0d9f6
+88908a43eeac604bcf9a0b3ca60aba155f4a03565ac9f9fcc5611fbf0597
+084431d37d97a9152e517ef0f6ac30c7af14ca490b4c76c3a8c8403611f2
+4a2714bbf952a4ef7767518bf0b69737b65b7b6aea2d68acb1f82c5e966b
+e6ab8bb38ab1823775bb35d60b1ec01e1a956e75ad8ff63e90d7c3a09798
+cb1ac0e1235742753c4f0ffaed9d9912d6b9ba310172a100c2e8daded966
+84ca97ad4b0285760e541bd121493403ac952c9f148a4be07a857fbcfa93
+ec60b19d89d9f437a22fb9eb16595efae7bfe2fbe62d3273bab8ed6c8518
+8864e5e2293818bab1864d85aaed9e32cbfcaa68dac5b52db3bd943c70ac
+a81c1720ac0428fea9aea324213166215542b68948f41273af3e7985087e
+727e13934fb13782e7191cc062832406a8bc38c576b5d96c3ff125fb925d
+71f217d7e60775c0c636601937b7b5d7bb35b6ae08f1745a1f7b42dd3f3d
+c1599a2b89760af234d0ca557df5f3be13d9e7cedd2c3e9827f29f4667e4
+a55e8bac85bacf33716f7354ea6b96776c26bf74f8c6dc18814103cf416c
+82b2226785db86e66edde45da8e5aa738934d084ed3f8bab45c5a46940ed
+d326106ee1aa6c8b240a98f1ec8284bcac022fefbe973885a2c5fe025a44
+8ef2ec64c57ac06998aaf24f702b70ead862f4327467dc5558b521b5a475
+fae859534d2deff36b8ff289c9c055076dbe472f83389d74306aa635a7d3
+738f09005fa73bd903a93fa98f5ada485a644a115bed74a7fc0c90febce2
+2ac7ce0ad8e64143301a671e980ac335a90fa735172d9843f65e4c0f267f
+49697564f842ce349ddaac386b317222a0136521c6ecae276b63beb2c192
+7d04886178ec3ed9783ddf414ee134d8b14e923ffe1e5a4f1e267e7553e3
+b021ee27e536bd4963c69455318e5c1deda0bb4faf814cd4998a6a4a7034
+ef0da8c64f30ef18c6ab164e6223233e6183419f53a81d9221a9643c528d
+a4843c88531a41b02e710927b30c748ed2eec921bf1caeae0d4856f3585a
+232ef7b6df214461bc60013d432cab8b6f17148d0efbf763d695d94ca94c
+426c5ab28c18b869579cac5a728c8dc94ad33710040a95a9ea70e953de9f
+45c0a320ada611ccd65ab7ef6423e70bbdc1ae898c9cb50278b5ac3b3f79
+03f6f5aa9a634b5bd103287cf2b25a4e52e70e7e762f00bf3e68dd39588a
+7e9a38fc072a96812c8c517eead56f3610584686ce912505d5fa81cc1de9
+5c7b9c96c1c73ea76970b2c343ca86530e7d1bec56f0bc4307c6a4aad326
+ad3296971877a629480afa1a9b602a6820f21c6520bc9cdefc01a7c48db7
+9caff6cfcc2b9f0bca69d41125476f2d372e1c8b6b499dab943e1130a764
+6dd17f6ebae2be1fad75784b5006f2d713ae30a4cbabcd50d0da9afa4cf3
+380358e575b769c6228b3874430db68aa0411e11621871d357e25bc39947
+e2573cc68bfc532ccf26068391dc516928f8e732d208e5482ad3c73e255d
+1ae8a93700962a56c0f83abe63089f2c9c6c42162729d74dfe84bf720206
+d42d82d2022df238182cd33dc4bc0013c030a92921c4f943cc8f1342f35a
+c1ddd2a6ff37b92ce6c953a9788ee8c4ca60328c76fc37df3b5cbfb7bee8
+d1a0f5934e353b329ec69b9100c41f52a03e80bf3fae5190af63177bccee
+ab2b445dff1b0cfa372020c89ffe21108166e6cb3383592ba4043c32386e
+17ab84d59a463230a1e3bdb428f3a0624cb02eda2fdbcf6b106b72d9a33f
+0bf20ef7e46544894c0f958d9d21a5beaa95dc9ca8b3afd30398861d41e8
+d1f0523ecff60dc3995adf84a464da4611c6f4567f174f93c689ab72cd38
+c921577a0a137281055c5b8bbddb702dcae5533508124f62c6b6ae947ef8
+88df84400b91f15d2d22af9f36860e8efd8d31cd1d507c2a93481b522e32
+f8063f81f68ece985c35ecb0d87ccda2bfda49a7451bf83f4ffb45db63b6
+715d4e11614e0b5add3f90137968abb33945a53679c4a375c64a27e772f3
+a28691c5064b133519aa12970938c3bc47260d8d3b1e06bf6a393015e369
+6db909ea8a80ef0437592e881060be810af96fc113da386ba760f5df40fa
+219e14a11ba6a5bc7d6c54abf59e71f3e8eb5eb02f088194ac3a02de6b89
+bfd576826b14e22534251f63f89f4ca05ab6c728748adffd02e6b21d2197
+e87e0acf1c081b65539083cee95a47e26dd8f848c24225756d9b2502e5fc
+f4820176f519e1feb87549f96a0038b797806874d67631b341dccf5a8414
+e86578839d7ec32968c57e2b70387b4f1ba21197ac8df1cac6175ef0a6f4
+6865c8acbbeb12abfb83d34f4b525eacc12d2733c29df3cc4a28a7e03092
+2609e0398565ffa55b0118a904a4cb0fed5af585c938a809e1573f63d829
+1bcfaac2bb1dec564a94d390223697323ba9d58ac74d28e37032af6f24f6
+076ce4e919b7b85679e228c7432230a85d3505d6f659be33b4697e4c0b6b
+6ee20a512adc3a1d0276c069e46b8b68e81e4893fcf91c64b84e631e92a5
+2ba97daeccf4c352a778225965f29aca689f74c1575a50c3fe6e90be0e1d
+b16a6e473d679e5ad5f422bfb0a4baf02981b0a140a35021d2a93c450516
+a8211e62f1345423ac48c167e7cd60932499251bb8db8190c0bf8290f09c
+1954fef141cbd5703e9176d347363ea768b701a40dc768d5535e1860612b
+84198effd00aa7bc09f3067a716b24dde04d30b73fc9fb783515c62d0391
+c82cf8b3bf0b79962db0bbb699295f324f69095f1a43083d3f7436a5f496
+50bafb86d2d6adee2c9753dfbec512bdc51ef2549ecf376ec05f6b3aa309
+d9c79be20c359ddce0f1bf4f1277de8564a22024e28822e734770c717f70
+c72bc399faf5d8b6805c3a7c6bade9f16d37d5e7eda4d7576a45a9ada1e9
+996a994022b777be0a1c6d9cb58b0987319dee76e0d3709794c05d15ad4a
+ef240b02cdba3dd5ad38ae5bcb9c0df2342b7277a0e241aa5dc4b7c0b5d6
+c66ae3c81cc758d9071c779f714f328befff3ebe0c7e7e6c4eeb16c27585
+a8b22d6791b34d4e2eb9c80ad925469b03706d9996020e298e930190eb9a
+30f56a62389fb49b00d1f91a6af2fa86d85fab4f9b89dbd076a0364053e7
+1a913c88756e305450c4a820c87323e40a615b7158d89312f8472673ce23
+728aaed24d04baee21591aee77258e573f765c432d1cd4221a7ce52339b7
+ba59a1ac2bacf152fbec0158e7876d4120137695a8beadb58a100763a5ed
+959b9ca89f481d9d9e226f7b609a599b30a6a4694bc166eefff954e187d5
+3987868e4d9f1112388eb12b9e5017e3566801fb27a0101227849d150a64
+fbb6104ec6d1e7c354a1baf425c583fc47dbdb958b8f5eb653b5a045fef9
+9279a4a76d0948121f4d37c0343109311513e8235f717948337d777c080d
+13301777ab8987b3d64d0eaf70fe28e957a1e92a7ffe9382a570237b3d3b
+d37910da2e51bcf04b566cadca226ae0b8c62105738f26bf57ed4f6ef0f4
+fe164145db590286d16b2ca36b3f77a0b4d243478c59cb34494b09209ea1
+4d4fe024f373877af88793eda29357fd908195a1952507b726138e377b57
+26d28447562df58e02663b86cbfdf2740d34a0cfb1c514523ea1b7b20601
+9713ce97943ff86e79ed7f3dbb59a6fd96680264e693f06b03e950e4a2c3
+ed234db50ca2a65594c8905c674a9bef1fdfae8a068850af662cd00429af
+4f41a8a95dbcbba1bd7e2b5421a1fa237cf31bc52f736aeddb1814f5a229
+a1e81a0316c6f70d177243adc4813f8429ad874d9efa0b9279975dc15bc1
+41dd3fa2c5696c6a642fde4eea6e54764da50910e51e74506d5f007d1b19
+46ac61f4b5467ae9449192d3f3736740704d28df25a018a681c24dca1862
+cf1989f1179c80edf7ea97eb48b72513a2f5f9410ad33b1e67af4a9b84b7
+03c64c9148a456405a6bde4bef9e20d33b91b921632515d9b7d07fbfe402
+d16179e91101af1ebe99df71582fbcc1aaeba137cf37777db59369eb36eb
+8b88fd6c0d71b89f34fd1df00dcf0f1d584c12cd998b8d3179f95ae3c1da
+483543bd1977d88310b76690d556546b30c573641d1b6310d3f3c9e8c398
+ca6d1b048c629d143584f6b51177a8cae324705be0751b1d769c4f7a80ff
+e810f076d007e01a4d8d2bb80e06a1dd0bc6a79a2db1ff51276880352b0c
+a2aa2a7399918bd9115091072892149e51d7083a471c0835a5f5957f2247
+4b49ebc6ec7d6ae0ef5cde3634b878544099c58c3125496cdeb98874335b
+f1c756b8f6cc7b0aa49d93c048451a6e48377aeef2ef2edd3ffd1d5efe84
+e23aaa143884d60f06f36b3d5fa950c3737105cd80bf383caf1e1c460ee9
+30e4240123b34b83307acb0a02a382fd279316c90fa69c1fdc171f4c7f30
+f645d4fb8879399030521af4ee5c225e6cefd3f1210550193785e2177ae5
+cd7c130e254df39b4de53a7b4b4bea3e747de45707032333b21e13621cd6
+ab912fc701e722d7fac26e92c9d779b6d6bb4912e3c8497fda5048d4c856
+1ca5e83475457986a8aa25869e8329c5afc2be7850ef12c4555310fbf424
+ec5568ffe92ed1ea2396055181565d4b11f98c72189abe6f204918004691
+db14118193c5e291e07d35c45ceafa1b3c3155c4c2c9a91a7baa9b110a97
+a0946827e252dc68d6a1959288ffb63eb6721fdca03e1e72c0d37ca7dc7f
+3deabe15f4e804cbb7f5650a143bdff5e86de36f9f826c4fc05d5667ea4a
+df5d08a31cd4f0d2fc95f5eccd874a40c0847b02cf4f9c4b047c27e5c702
+0a23e2f4504a3c2fb6c310265eca0fe289ea8c9f62804b0040167589f05e
+f21139b321c662b5ccc314a92dacc92664a65cc9f804a751e4eabe11a9ad
+cc08a3808397b68b6510fe49ed4861755386979c858a43c5105383a948b1
+6ef0eb9d79ab162f1c56e08f14e3614cc683ab383d655f5fcdb616f45fda
+9b3ea1b7a4514af796bcdd859421124582605417da88f96bd9bd0a44f6a1
+0352f31be38861eec03d5ef4349c62678171bcbb25c789cfa650ea76716a
+d99f9ef4a361467d0f4bdd305b1656c8e226bc61993e98fe31dc936c9002
+f69caf89e0aad3a215685a82275357fce725877b527eec56a74e4aa352a0
+7fcec7b66d025ad720c760ec5dcd46cb180c7aec171a3200c2bf697fd3bc
+f78447054dc8c38cd443964b27280554a6b3a878ea93b995ba0acb74a4e9
+6118b25dae2f67abe2ee5e580b0c0b2eeb8a0d730978e97205277823411f
+1c04beca7c2ba588631ab10270708ba72eb0c9d76472e90f5c733997031d
+5288c06c2449edea82b0cf653cf1dc5afd64c10bbded31a2c3a2c7a00bf7
+b688c77888d6e6175d8c20994382eaaec14df3783d4b3bc97f1cc3ee6113
+d50bbbc2fb1b82dafc127c466d5909db3a7c2c5b31a17dd588f15b8b5211
+df314fb334c4f5412fb23808bb1a7bb3f85762a0881765b0d5b8cc8a6ca8
+228f29e7e73b496b73160ee8f91b5dc4a50c0a093d28c01850336c56a12e
+95c0b53b39c875f86a646f149241aa070fed7d6ad42eff3fec7e039c36a3
+7aa3e5bec4c497b1f51d07057bf4e9bd067209850f23a614b05ee5993d5b
+61234f9456fe76748acad8016dc2fe48eb5b4dc7f2f6987304764c48a74a
+50621cabc3d8528dd08aad4d4b55aab3a04efa8e69c3f59ef92e3a81c8be
+23be1436758c1ac357426c3558ebf67ac9677551da53638a95f165320e2c
+31de3d9dad7aafc99ae3d4140bd690ba987da161e8951c67a9a74948c350
+4d1b07d5c7694c4c817414d05793081170d387beed9fcb5a7d09a6c5068a
+ef0f3b74e35560d21593ecfc51b9123da0da1143ca1be60448096a663987
+4f355b2825a4c86135d375e88313478861f1b9aaf83f39e2e18a9da3eef7
+944c984de54adf4224d61ffbb85fdc067ccb6c37f81687a5086704356650
+d487678fa2384f48e9e40359cc6efa0f579f8a181dbb8aa01fffceae9e1a
+9766e602aafafc42459c5cc59709cfd3c7c7b7235b9d9f26a50b21c113db
+401fa1e99468e5bf429ddf946fef6a6f26aa0f75d77262119e30eb5529b9
+5c8ca528af78de86a40ed5dbae0f1c36625a60422be9e6f77d5672565ebc
+80e3997b15ddd5903d85f35cbf76b38884080605faa1c17d3fdcdc5f657b
+c4ab3867e917c98ce6c3500a7659d322c981e3b2e0602b4662d2106e1f26
+0d64a894aa1ed38e681a1d0164307af81fa19c1c8ed262075df3e978a1e2
+5fd5a8955f09eb5c8ec79ce0230966ec2b90198ac6961edf4a0b9d7c5926
+d1b5556256fd15ebde50a4756aa163b70918e697ad9b08793adee1a5bf9d
+2ed8069fb5650bb6a215b15c80a2764ebbd65587e368fa510f3f250b3002
+f9256fa6c21b14443505b203c7e1f0e0b6482de317bd56b44630b1a6c836
+a2e398ec36db92a9a3186d55202a7ee88f981f14368c4447a172619c4f9c
+9e747ad286d01fd223b55103c1e0672c9708042f63ba74bdd0d5799503b6
+429b70c9a4925481f634087dbd5dc869da8d57fc7601552edb51b9918709
+bbec37658392a287f5074a8c01ccfb49cc7d833a4501ccefb4e9a982ed89
+0d1807cb287b9ddb8e7e2f43f2fdfdd1b4174b45ac4b20cafc24e25f871b
+60bc4192b2e6431dd24bfa8a3fada89410d0bb68b865f3e43b897ba4f98f
+2fb3da2c322822bc80a55effa49890f1920cb824a16d67d19a33d8cda986
+c8045cc839e20ef94077d191f62dd4a8af82c2f4e95a64e1af8d882dad32
+03ff0f863528db72ef20a1bdf8d998aa85011b3174c0efa0ca6378d488de
+30960140f9df850b36bd310d1a184cf47b70d76654a39d2c5d50ca56bbc9
+a16675482ab01d1425fffa264cfb849b7bb6a60dd4ddfc4395eda9f7dbac
+1f9bd167fcb3e2a5c75e581482862b6572c5ab185f1304fbc90109216561
+c53a766baeef42811a6b27cfe73425a873c6f23313ce98a155a67af59451
+b85af8af514f1ebb9c8b55fbbf174faac6a1151540e59d11185ae7304683
+8380e384b234a76fed74da8fe2dfb16fe8800561eaa8bef5201a23c3c162
+f115207e1f708c252f0c80ebc0102fa1859d1d14d6376f6ca393e1b75e59
+e96786e443ccfa7cffa5d5a532ea301d1a3b11dca3e9524889bb4731fa73
+e3c7106de30a0b103b22a03ff91031f8b305849a122c181496f86b39efc0
+a3c3f03601fb3bea641e049a6b6a5b94c3d2fc4325be8b60d57076e6c6b3
+c919d0e9ac9a352e62c5a18bc174f4400917567e5ab85da35a4a00b99db2
+d0a04395b532a58983b7e1d9ca6ec1b358e0d52ffb82e0a2b61b381865c9
+13aa54ac09bc7b90dc93068183459b1e9ca74be62718eb1a33c0385b0db5
+11df9cde03003ee8a0af0a5de005d9c8d10a96c054a1d47568cc3a1869be
+48305e5a5eb27d67a4e9931f28981fc482c0519e331babc2b016d44eb1d5
+68918235ed02349884de2eda440fe7b98bc02dead0eaf76f5fa85d2a6c38
+4b6974c8b1ecdede290e81397532da1c514fe30a3449ca33faa20d24a47d
+3dddc44e03070eb944b441495ef2ae383bd2b9b656bb0015d7d80e813e33
+886fbadb1ce08fcbecef193456ec9e2e9ce0fb7b8eb71534d6ec565b0950
+cb0b9d921b4a6980f6390d4faa16cf466a02ae2a55146541a20c5a9996c5
+ff61450887b5da72aace428340d9886becbd7d8b0721269883201ffa28d1
+a1ba32af7798aebc064ccf0a22fc9f2d450b9f0d26fe023099a95791c731
+79baaf846e9f1002a930c50862d5e49f27d469f67d948580877e8583c4cd
+0fd48ed98501e3f6d094aa00145091cf3373b7ad6c5050b90762a98d2184
+3d1df31293e5b8a5f25391213bd3f8ef78f1ed91a52c50089c3440e7855f
+315c3ce3c5d02da21a1710555cbeada8d406e0f644bfc2649c6b059ae09e
+a3ce3fdf553eb6298e6968f06c1f3e78a3dadbf80e7dfeb2bd7b87620083
+95b624e0ccbc0fab6ec0279b951c0791b6056ea7e06dd3a7eac13c9390ab
+d98ea4272c99de1a65345b6400549ed0c8adf4ebbb46f05262e2f5c4fae6
+2a279d5be639785d7f26a8158a77607612cf5cf9b6cb3539cd255d9b9427
+af0665ad63c1e8df8cc93cff8db23ac53d16f61f6dc271488b0088e5274d
+1f3f3ec8f8f28c85238345542ba4d538ff2a4b08af29640c5fa7cc8cd89a
+47a083db93096ea8d4b9923a0c069a20e00020dc296f583710279eb6f404
+162da338313fb4db5055f0b5f6dd4b0ecd6e6ae4be65f4cb8ec6b1f70ade
+49702456a001312fec560bd2bb0687d61add0ef2e278a13452736f77814e
+277b153af6fd4fd99e9adc65269a9ef9cddea98953892444e1f49d3a6a33
+75ed9acbd9a9f11070359e8e8d97527fc874059b5ea3b0a82fd7d9265de7
+153eff41b28e397767e9d0932261f839dda7b359b03d4ddf2821a8398fe7
+221640e035e49e371b5594b61adacfa5dee8389dbda04ee349072ae506c5
+19ef43cd8c1bc90fc87777d9bf6fef2650880e0ecc17c4d48d1c7e31db5f
+450581eeee7af65f665ce472da87bc90d322c0fd878f812ebd66c9eaa033
+d5d9622f8f754936102fd51489aba37b725365bcc3dcf1023000061bab41
+8737901cc01500e0dcb2b3bc196e89d164622daba26d31efc6b62951b1d2
+6e15fd1b1448d7dc675031b90ca135e42570b0a948e34e1ed7e0e306636d
+4760fb5535207502fe96cac6b9b0a52db7f04c4140eaa826b0f6849688c4
+a353ad76d780d0ba8aaaaad6d47a3fd77647c9159af91e9b74cbfd38ee17
+88cf37dd6c9cb721a9763064935ace2a941b65d5b11ca2ec06cd700e40dd
+a97d5373c5d4d3a96bda1703c208cfa235909ec79dfcffea284e743b7f04
+88e7cb68fcc3e6c4f7a49f945d859889442748607acf89e8d2b21e76deff
+12df3c6f84868c110ae964b5cb3dde29c671286588442e61075815345252
+ed1174d840c7c7f89255bf99a466d64c780fd13144ab2074400b404c64e2
+20bf46849bd76801fb0ea28e460e89af2101d8cf911dba146ab8e9063a26
+0d77ad509df4f6756eab156a31022dbd4763b23e177cb5b712f0385f328f
+65d238ab8a0edcf6d6b8eda3b222da5422c026db7102375f78323e84fa86
+6f1e2e51c513721d666c17a489a2e00ac5add0ae6ce4d44fdefd65df435c
+49457ec14191351c05443f349e41b6b6eb4675c06f82bb5584522bf8f316
+85481922ac7a1bd51b86243a97dc5c270f07c72b9c5a807a6aa7c36f3f13
+f44c46491f216cb10f3b5d1bc0e84d2cc95bdda64619d8e9e0f2b9d1b3a5
+e8a9aa18d4eb4187239e1010566b561ef613fa582a4b66149c1b1eeded7d
+bad6c2dcec39315f735ad2c30dfb76a9e42b73912d018d3f19f2c77eb7f9
+3ce2433309d7d802949d9ed4fa7ff6cde73577c91bb2b065ea389c0e2104
+57987f9814679b3da6c4da8510cdd4462e249aa37048320cdd48bacb6fc8
+296f12aa3160297ad9e36c01ac7807b6990ee7d646d8ad8d655763a2d685
+ae56af110099ec774ac86df2bc8c23d404da3e04277a14d291c60400163d
+564272b105c61725bfec1b1ee7f5dcfd7a10b14e0184978e123e3f26590b
+3288771243fc11a4252b0af02db678eb84621648e25bfc32e94206c98b7a
+4adf3af635d5b590c606b472996e7ffd26b7f0554b975142473333a061eb
+f79867341bd06a5b05761c595087f20349eeea6845c87785e79117c3a95d
+471eae9d5347970ecc47331cf6a9043c2883f498787b90e6949c8ef311e3
+c97d58e6dd5deb00c88c47e391283a9a50bd006fe5a10a3ad04120437393
+e80a5cca595bce1b7ae05e0685dc003fac9a8e5d860e2c2325a568f4222a
+f2fb7f51463fc3051aa643b3c306ebd9864e08d34de7a9b49bb69dcf69db
+0ad504078638033b143cf2b730d598790c4af2676694ec0ffaef3d3c580f
+477c3c5dc7478609d043bafc6ed8d06b450bd4eb09141d757962cfae60c5
+ad7222fb12c34dee17a0b8cbb97044b401cd632a1797ff022f7bf5d2d9e9
+1e96722ff3d0b51f78f8a2b834f6304c966107416edc93a91e9d914304c2
+98138fbee34f8bcfde736c7f5703daeea23532fe7fb770e8c22e087fcf80
+ed2ecda99c1547a41b7672591fdd5e26dacb333b524dc0de8ded5ce60389
+76ca254bfd62b1c066059053edf8c3a4fccc29386254de895994dd7069fd
+1a9c2c7fa492043abe9e158110fe80a9330ce05063cd7023aa5605beeaee
+eb033229e3cd2c2c3a67d91449cd67578f50c63f1c5329e4217473aeb977
+3971dc69408b48ddc5980329a197531aabf6a92e68c54e2e19290c1de361
+fbe91a6c386d4a1279c82f128c70baba069733957087ea021a8f9c69f0ae
+79e88276f15a7b2cbe6744d41ca32141091cc9c5e1b857205605d99f411b
+4e3da6a647fe14bc94c068911995d3f15be218174c69ca1834f49176743b
+ceb20a385dd2ec01bf6da68c5659e636eba5545196490079a63c49fac2da
+3c1fffc6d21f2d9f38ef7f560701bb71c1c0909a5577161ac0b9e6ab21f2
+2777b7a721b34d5a6f6f1e8994aa89c8cf9ab96e81fbf780bdfb4cb4b6f8
+9c05624f89b86bd8db430ae67f09e20bed731d124a4bb210c46fd61b24d2
+28772e247c2eba3cb6b8acc0814d59b5d04138f601fce20230ba26a8fe1d
+351bea6a77f49ff461620e3b78b4af7825436b2d28b29b2cad0ef79c0794
+654ce86ff755ecf4dfc235480ad6496686d7c54020caf417f57ed100ec0b
+30716ba13b3f9a7084322ece5e140163a228ae8e86ca4f699d94abddb39a
+4cf3ea50ccb58c0bf82fd81fa36466a813c56e16847048a8612242fbf4d6
+6cf9533dfd8ff7d1cd58cbb40b6a2361049e0e5842457629e3893c3d2270
+f7802c6d36a16327474b2c81fc0ceb4ecce7be67bd8c707999c25573239b
+da35c2cda50bdd2a99141b84c9337360ca82e048bf0a460277a2810e9be9
+f19f121d6c32844948b93a98b4b16893d978861a7e35579dada4dbc12b4a
+8f9256f3d6c26eb9d7e6ecc1de7c8948cbe619d5ec751d1b0b3f17af2f11
+6331406de106362ab12953130048abf09f8f3970cc170b31223a6c7d7fa4
+bb2bcf5a6eee4ce50b9dc1c65188f60d2790a561dc552e60f03c536b439f
+1d6b7c90fd5d406b79c512df6868c175413000d38fe1542c873b52139aa7
+c28102bfd0e48771d46eb5f38c174ef7140b2b82af2bdffd879b281210d5
+bb9ecffc4cb8aa09891208a3ec0f3d150514c806be501488e649234e0c27
+fc13f2198553068987deb79b8da835ced758e4957bcee7c623ccba1a4af9
+6916f467bc15b013d49497de3b80b5e70ff1e459a868089d02ad433a57e2
+fc9e474764efabfe35d0e6929b0b2fab129cd92dd5b1a2db3a5f45b657db
+b6f7f929b2fa42c483f80a4c3fb8da8a017d2151aef8811c66028a8fcab5
+3cec7d285ab284be4d97ca882b93d9beace601f6c80c9efeb043d295e95a
+3335266d3f49c6c0c90deb2c0676d525129ccd6191e3364964fa26a487e9
+136aa70c96f9668fc8e420e9270f94f8fcc812c30fa4007f9abab5572a6a
+9d0269edda9ee4c05339f38c4a513458c60bf8c4f399e0e85150ec4ffbac
+3026f3fad2be387f0bbfcdbc9d289d2caf3499f7470f7557ad5912579352
+4bc777b64033fee4f8ff8689e818f86722b447f5378b37f05d53f77ea10e
+26c00282a5088eea8840dc80294a7e806d5025b8ae5a4d0bcb305452ad99
+4083f1fdfe2cc8a3bcce756688b37fb857f3c195955f31f49c113d1a14f6
+d75cb2aff8169007358b0fa8299515ff1f03bef4c6dd6f3ff70d527f8964
+ceb2ba3644fed417e0ce550a1512759e1d76163dc74c53e7f41fce443961
+892afd6f34fbc58e8347dda64fcc52c9a1ae0a817fd5d1d14658125f579d
+32ce165d8531cc34fe44edcd73d85ba8cad4d71cf5ce80510f8e4323d91d
+96fbfb0daefe8af4d57559a9e303551d38a65500f2e02d4c7f65f4a91aa6
+81241d10de140a703a641e0f6233e98fd9ff71699e62cbbc839de8a31a17
+260e657a84e6829d00b54ab85977c8053be31049111e569ba6fb8e29282f
+a5bfa5ccae62aa7ce0b0ee23fe7f429e566f3aacdb4d13945c9616a2e4c9
+02c64d42bab63f25afbb4623475a0846e314c7a7f47cf531bd3f753cd7d4
+14d51199d34da94286647ab5b616569cf61c68e87568a844eea05f9d22fc
+1c51150857aee8868c88b38ac004f1d86d1b6536041772091b3548b82669
+6af82096753e9d6e0445940eac5a902b304b5de5c0b9de23eb298f3774b1
+775394a26c8963bd7e07204b8175b7f2c5073227a16dca74e4bb24ca63c8
+6fa65e6d5121a7290d58a11e0c7b98ca7eb65fd636b20ef56156be14038a
+42d51c873d52a656b1a57d8bdbde43053dd096dff8ec222bde65776c2c46
+a0d64d927d8ffab4ea1e9ef177a711a81f7fc666d30a681996f194e4d5c5
+33c403a93271068b01996f0e250e01c2ee63fd1d0a9163bf8b670f970a6d
+d416b2aebbc96deb02d27e0a83de3c87781edac6aaa5a0d1fd7877222897
+94d3056bc74f5c899f64988a25dc67c3f14da8871d69fc5d8cf6b0e7bc70
+e398694276c69b77a48019989b93755340e000ccc4fa98cfcaaaf1593055
+13a56f8987758c979b5fbc8794cade876d81e4ecf0495f329a3ec2927e95
+9aec2d26c1ad32a3d111d01d0c932624b904da42123d44421c84bc71307a
+d13d0041308fab8d0ee6f9de746400aa041a7c6a99a72300a9b911fd73f0
+cf2e0d41921232f243eca86727776890bdf9d138752bb927b6485c1b45b9
+416d1078a7034ba2b9fb1c7f9cb55734f87d4e1f081d7c4a66b524b2427a
+baba5e91c1318923699ae3820657e89ac8c75322f04017439c7ec53e1891
+28882e761b0363938b7faa0e6440e1b697db26de4fc2b2f3e1752d000758
+978292da03c7fdddf12b5f11606798a4016b756270c1ea095fca04ef36b1
+a72aa27da04d2dc9f30843137834a4b3397eb87f107631bbab8e724f0014
+2091b558357a0753bdd88598877b4a506078292186a852f36e38e606b12e
+ad12002f0273108c594d86d04279282427edd49fc3325d7cde76e9e50e17
+c3ead48da0b5b3409df1e7b711de6ac9cd1a48b907e0e6fab8df98782fdf
+48dc44433148424304699242cecf9bb4d699114a950d53c7d8166018b08a
+b5246d836a0633045a6c0fdf7340ab739e04ab8928ff7ce64875682bc514
+2618c221ce7b6c38633c5afec9e0ff4ca14743d21be4ef5630ba42389f99
+3ace05eab6b06cd8413a4894a3ac685af3b9e8c134970390af3b8d3ad582
+eb2c948b529d1fe2dc23c8919fdd29a295d5088662b9d50c247a7b0450ef
+0c6b4c8564393dceb5a1b670d2b77876a5927969fae71403c719f4200820
+12741fe56d8bf8ffbb2ff70a7b1b7e95478b8500eb356f25ec9d85578e23
+cc4ad1fd61cc16b18d556c0e6021cc7c6317aad2523d1f14eeef767ba598
+2b683bf24fe0cf493cc39c7117379f41028a7cf9a95a970fe5e447b6f815
+da7f0aa455ea915116e94281bbd7300ae58873444d3019acb2c734e114ee
+fec3b05f84fc994070dfcb82999bf421b51f7430bbcbf0275c157ff4ebdf
+d35103fd111a0281e8d52b73bd42360b532f46f830c3a78d44db18d238f3
+21189d7fbe4be34a67787594d440e012e39a439f48267cb383d7a8bfabf9
+08d6fe86abf91c967c1a2c45943dd7fe6cade43d95bc722c896495ff9f0b
+5e85dfd604187857d6cc0eca1aa46ac549fe0e4d99a93d7ce0f712db3ca7
+8a157c1e3065190401e13dd84b504a20b9b1814024528099dc401b6b568e
+ffa0eaf97cce9bd173ac9be0d1c0a56ee21ea0f94e0ec204461ff5930f6b
+01e2af0fb5fb368db5ae44bb9861515088aeabd158e1f4e8617f5b688c08
+513a96299dc88f74f56714844b19ea7416afe963c3a0919f8942124980f4
+9cd1adac4d1d49f9ffcea28ff611090163b5e07129b900304292df6134ae
+eb52bd7b44d0ddf0c06d55d65886a78d3a1e0fa480ea21119d21989605d9
+749ec25026a04026c91c3882d2ebf341603dd84fb0c138a1271dd6c27cea
+2d329de5d810f761212c71bd92da4c9f15592658c9d81211b90763ea857b
+53ab18b7b18f2026ece8841a248c5cc92dc6b6df59e3fdfd04aea5cad5f3
+60f718609d5ac00683bed6d743942cf10371ccde82ca656ec31b6bc726b2
+156c2d5606304fa59ef82e2bd2f212c6e86a9eadc31830f5de8e76679eac
+a9f21b48ff6f41f54cc057ad2c02b030ca376105dc8324bee6d380f82672
+531eae8e4a2dd9c80a01716ace85092dbec6563e7f055b77265b75d416e1
+559133c4b9119bf69c405732b61bc669ba6b6fbbeac9298cee1fcef26b41
+89499086d2db96c8afb534ebcff7494177252aece0b1b9689b7f28493923
+a6016dcfa0ee015025f8bfc4ea2a29293a7c5b8342f444db215a9e765270
+9a67b19fa0bda6a289a394397d543a444ce477e54341435f4e63f9d158d8
+12b434f9f5ec1e9f8e1d5342a28c9be494b49501c6f9ef349cf2c0d24a62
+44a3652b9079a1289ba7031d4d97de225df6ec42a8dcf13ed3a37571d600
+99d5df67769bee27a1b218198a3665932efeb7fe217b4314d3a4d7991bef
+6aa5ff8b8019a5f30a609f27998045a20708b9660ae827d5acca04e94c00
+49e0ec57aae4c0e65cccbba8528867a186368971657d5796c1cb1c0a3d2c
+53d8e215e00dad145328238997a71baaae73c21afc81c5b719eb10dd8b9e
+e8f3ecb779a39405741bfc078bcc995a4fc26eb9d9698f06a0f83f0c0054
+2c85b7b4827b7220b071c88194d0331a35319b638a66edd7be30e86aa1bf
+f1d29b0ebcafb968c68f6ac51766b70480f15b4be0301ac69fc8459c39bf
+dd40155c141faf8fb1123b6dc23a74f7cb863524b971eaea1574c67c0fd7
+bfbcbed4b99473e07d8d41481129fd55b57791886b626f0b1c5dcd3e0500
+861a272095b1eac096bec7f2dd53b1e4891ddef5410a63ce5bf7485dfe80
+fb961594a833c81ca8a581e65777180e5670307c9b79ca97ff38bcbf0629
+95bdadbe5ddb4d0a90a5de1f3547d8cfa9ec142485aba94d597d1387b937
+395f136e3e934b73649dc4bd587c785048373b4936e737724aaf6c407fc5
+7b8a1be3f723fa4f4a68511df9f7b71c6b7065c13c15fd11ff74697647db
+29dcddb07658274959e8b511a9b35e446541d39cffe121329ab2d94c2709
+e08c1389ff7afad2756350bf2ccb35f34228c4eec4eee5656941e2e867ad
+1d285475939c6950929b33cbfb30c50cd4b32bdf6bb25690f32ecabe1a71
+932ddd6f19a3b629173d1a3a24308396244c8507e472f63955cba693fa6e
+18b1c61e80d5fe79a0266831458a37e4390d44276494dc03cef7de44933f
+1db94bb1958d8c77cb65b756af4b87b1ad13c6439e4f9803bdb264d65fce
+9416890b7d054eb3d44c224d52db95d803d1cf2b557c003c453d48e3ee23
+b20d343ef22981faff7e9d7a43b78b2182aed25b5825b03794948946d30b
+30cac8274380ad33065d14ed4a030ae00533c0e0728590efee415cacce63
+e814a0fd54bf98b25cddd41212617f0d39884c8625cb1905ae42da701b03
+6f60680711ee85e5f47dc056045890156b146969422e20f8a2a66cc4a6f6
+fabd063a168f3bef11d6a369f1418b84143d71d30c6d965f18ab4fc08987
+482f83138cdd6fb4226a4908fc091f229c6265171f0cb523286080779320
+b30d4bd678603ecc9161ad8cb5a501833287ba067c97036080c9c93bcc12
+d69013702302c705dac256d764fe6f1d1d57b0c58e806eb45fa42dac9f67
+a79df2b4e9e3ef2e779d00a77f7923d8660a70253a3f58edbe1d4bd6b9e8
+606e9ee90cca725db85221628749c02dddc1b29b64ee0d7e2c4649d972f5
+047f9b376e498b7ac28ac6d90d1e34483c24f1746361b61276f10d6fc383
+5b47e2fef143bf9500b9b8324639a7ae78b2df882457c4d399e5fe605a96
+c9f6db5de2cb22c7119aec39be3dc6c208ed1fe6fae4e11dd8905570eca9
+7c438acd5eb741fd8b355564e369714965a62e86f91df8106e4445d4d959
+a7b90c2dccdf3df61c9f040cffc7bde8c4df505054242bb01e98b057c64b
+f660334a7a01dfb2f143606c072fd1b46a054c9e6256767c4d8a93f061ad
+cafd450c487bd8e60d6b0255f588c804dfef128b4d8dcc6bdcfc54da55e1
+e3db0dcdd83c1a9473ddf625b04ef8cabfe7ff79d7adec16cfb8365ab874
+f0da37b9c793291bcd7b2b9f3541b18510cb7ade212076226ab000bdebc4
+ee22bcdd9cfe6c14af1ae4b53ba27eba3c85616a80865e7afd5fcb87f5a6
+21678a5583d69a74c51a61e64c4aa8792456cc9d28a4aeeca9fe4764f982
+e526724a70773824f9dcbb913d87ab5c451fd858154f3cec4d683fb1a1f3
+d72274f43db4b0a9fb32e1e3edc5b2ab4d19010fec11e349cc961ef016ab
+bd3681d6b8f3749d2f6e19abba2e2d8bc2a64e926e5a54d1bd86b59a5409
+d58947bb01759777e8924507aeee61bbe36ebabc7bced4269352bde9da07
+c9b0551452f2027af01c13218e9afec7c684f8a86b11d4e303e1e984758d
+7487bfd59653ee8699a97c570ae0914fc2a9457e251a9afba94d4157279c
+2626025bc79b1893543d1a35c866ff5bc3c021241e0d1684cb16b3885af9
+d2f0a20ab75bc56aed522d4e32286aaefcc802402d6cc60b2129ba3e06a7
+5c7226bdd46bedb2b55962b586378f168ba9fa4a09e6a910a35f57fe7080
+e53290537a830708504050d779d6d6a746e8f2f0aedacc3b2eb034175790
+59ceede73b3b0c611f57ca4d102eadeae2b4f9611270969a4543b3473169
+ce8b22d2fe62b241f661e07671d8c2d95d5444b905615ba5b4c2cc794889
+2a2c6a0d77271cb6f28407eabad0202e25d8400f006ee3f241f5be1f48ec
+004775469717653b7a236f876b2edd88d433d4b8ed2f47f73d964a9bab03
+8c3e414000c750ecbe3fbd3902f8d24fd6ca52d447227053e3549ccdc49f
+ea46ec7e3578ec7247f77dfa265a007a1b889d36e505f7bf8fab3b68e76d
+9bc00e54dabd29b1b3d907748ca134f067230a6f8a079c8daa81b2bd21a7
+ab19995a447f6eee35e6d8c503cccf679b6c8fcfac07c3a8eec2ca9d512f
+5af7ac7da28c391fa171153a39ca6e470ca72c813b842efcdab632f3a35d
+278e48786adf30c671a500df993b4c27d78fe6677c27a589ba7b52d01c0f
+89ae3ca69441d0cf32513d62e653908c00fe25a24a0c4dceb1ff98b0a4b7
+a2f5092cad028fc216b71e3bd49914c655811b468869853838c9cb0cae5a
+9569cc9789db7d5291f2093f6f02c2aafebafe8f6b6027ae043f7e9a06e5
+e0c74ae9c1792f8877670ff1ddbdc4d332b86f628158f6f0d976d56a1273
+7b219e5615790169d20aa7caa676a8f17b6925b136bd18ed234c2b96e993
+34c0dc04026b579c5aa40788130aa804340e62df9c85ec996e35c4a9f9f4
+9b81d5c87c224611a2d9d5182ef85d01eb2a7f9a2f9f96d45d538afcefae
+ac72e2361bba5c4ac161ae12f1652d1fd84256af1a2596e4cb227d5be574
+8150f1371daa0e04a7855ff191e6c2e4521f5650806f5445465614af801e
+4face7a7a14989551b6a00495935ed1ff4172abf5e78f5a0c31ea6b77fb9
+30d58d808f47305a6a0c987cd6b2d93b017ecbfa57070151f108554cfbbc
+069b9d51cd372f6dbb0b7ef78e650446b0e716f09abb1ff0cc1f81466429
+74afc5ed85e5e87bc9b022c1a14d72fb593b9eb7e4f099850eb8abbfec11
+8a69ad3e178e8b28bc2b0af9ba3a8ba6c415fb55d1fca117b837e4c2659e
+8639789cc35859e14e320fdbc399db88fba095ad29b0fba78fec3da253e5
+48726d96ac280d98b7f45dfaa31bc53d2fdcbbad1063ad462c44eab2aa7c
+c832ec1f5cad70e2409dfb3a487dddfd3b36504c1c85ad04d1b4103ebb92
+a3f801c8afb7685755b266742e72aafa3f877c47c572bc969a18a7fb804b
+16430a5ead8b2f7fdf9f26ac922884906cc1eb171586dcb792b274b2134c
+04f7599d8717b0ee057a3989a721ebca30aa85d31ab943797023065c5f64
+46a8911d7da276e6ecb4569a9ebe5d6f18b1296716da7b47db14c32e3983
+3d361eccc811521394cc38b47d269b6bb04f0bd8bffb63cd0b255c96c98a
+0a0c460565c9a088900051fbc66234013245c12fa47e5c6559c5c1902a3a
+3c1935ce9a78e40fcd17863dc693ee726fb7884c7b7de5a6761c69424bf9
+2243779ff6a9e566ae5372ad5a4a4d0e8ceda90ea12d22579b015f6c6e9d
+5445fb555b45bf280c03f5049d3db36821711c8a7dd5e7a2c1cde2b37c80
+4f50feddaeaa2b8a029bf47b4e917d593418a2e7213840e79fd2d16100d8
+2b76956922fb93ef5cb7a16afe18ccca6bc89c2b6403b3a1ce8abc2768d8
+9230053cb2c13e39322ca4e4682ce1f3eb9ca5dd6428b9ba1c0c573b9bac
+afdf8aa129cdff321adfd514b2596a7ee73671d8cfdffa6014df71a14bcf
+7c246fcac11954c469a5085bcb5865455e7844f8a4113aea74982d1ec5e0
+6bc88b0656aa6dce6ff19491d0331b9e12d348622f1189743e974c190304
+28d9224321063c40455d1420617ee056572e2072ab254af4339bc975f95e
+66b093fbe3ce5d6bd5c601a7ec41bea52349f90f585fc52e57db9fed41c6
+106e15724c8d25e9a92a976047e14c0283981cd53220560c4c477985e5ff
+09dd5786a3d6b20337ea06e40ddd150aeda6e7416f439bb818e267a970a5
+4fbd46088ea02c1e8b689df81ed517a237230df2369acf7ee9ce06c3e24e
+83a5620ce47047c725fb6f57a126d55781406c670ba0dde4cedbb7b28c3d
+a928b6b828efda00f21bdc87638a6bb59b129f50aa79ffef05cddbe7f36b
+599788d9b81380573783dbdeddd08b57aa600a8cf8a294fdda952d6d1d60
+980feaddb0905117f5502198186e8a57019de97ed3369c29d217fa2cae7d
+94a82acddc8a32bcfebfdb167d552ea840b9e8b2689b03724907be1a8f97
+ba4ed0e0fd9825795fdc5464a45d3677fc7b146f6f5c66d87a0757df35d1
+5ead8cad4ccfe98659b6c5811de82cf5644e00434bcb8bdcdac7cfc517cd
+c42e8b758494b6939becc2d6426602f17607feb9a71836b10a59805ec430
+fb6efc49175010cb9ab1953e906cf66fcde4d252a683cfbac8f41e0d221e
+35fda9067decaa71da1d439380339245090df4e21d81845b233f64ad60dd
+6d4046b1a257db23e682d0665c552fd3ac6e9565a73f8f913d84d86273c5
+7f2514b289bf51528798ef4c390cb227a567c1b016e71f02bf7bf0ae8949
+9de53d074c4ae495582317a59cf5947fc469054648b881753b22f63ab936
+c862ece5abfafc01e0abdb4cf163267911229c36dd1df042acf932f1c587
+3b0591c26f576cadcc6a53ad637eb11c8c2ee6cc84e1204025a928907a59
+1a0e086e354cf1f583054953aaebcf4ef89c4eb2c3f01f409efef375cfd8
+ed932d6ec34ac9ab6b0d95842263259f21df66de5d5ae771885d8574349b
+895974407de469058c94cc5d5ecf949954f0801e5be8dedbacba7e893f9a
+14e211e25eb9a8d426ddd692669f78054417baf8dc282aabd7efb148de94
+15b56346e55a8fc3e5296d739e83769731c48a95318d95eb493d0054b9d5
+887c35cf2e4c380e50e1be6690c5f6e9e7018cda116d0d8a983d43ee2464
+565bf8c1fb5661b75838d1c1823eaecbd2ed2721fcc353516e94f5ca4013
+9b8c69f69abf489fd3e0d7066c5a722cf5ca763073041bae3fe9ffac261f
+75457ba5d0f546eec5741a770058b2e8b76958abe5a27cded4a8d190ad7c
+5c53b51e32c105f4773daf259e6d1b25e95d8cb00180523b5180753a18e7
+faac7c47fe9c4aa719ea216efadaec522d1df90632e54f8cca66963a5db7
+8452df426945798b0f9151a929571525995e15ee2638c74bda75e8140161
+1aa448e93614d4841a0b5be40198a44c058ddf14089881673f63268201c1
+99de50eb482a0e2687f02ed99de1af7b2c40ef8ae43e84f79923bed8dca6
+132d7602bb1ea23b10469628c6c263acbafb2f1b9ae53d0fc9ecdc64f3b9
+d513615e1bae542dd407c668d38bcf1f290c822304aa49251ed252f03650
+ee62280ed4e16902ca2eddb24d71e4b16617f447c6bc907db187a01e9be9
+1a4724816136be46ee38a4cf3c64a85ad44e1f2baeaa3b56ffe3f71d41a4
+24c7d9b3f5d17d6e2cf35951bcc0ffe285af2de6f41eca1654b4cf0f8699
+d059919740222a57333140acf73fdaaf99678221244b5245ee90d14e1727
+1c2e22c0afcf1d1b036d2e69b02fce335bc64ac55417b6f53bedfdde7900
+d8861700c282ec1bc90822fd93925d75f0edc3e5a0d4df89a5bc4b31e292
+0ba4009bf1a263b0f752247825d79f9f7f8d62ffb38b4ef51d08c76d10a3
+13803a82a4bbb76881f41a48d3723c47516048d7a57b0c129462c1e02ac4
+a3230c53557111e7451597cb5c005a2aede03d9d632e0c9f09983d67ec24
+2c70fd67c384f01cd52e27b685d4bb9526440c1ac397172e2e2f57cd13af
+cc0d777e15170d431187d7bfd6bae72ea57cb378f900f83da6b0ed75d322
+22fa8bc634de08716904b8d1a114e9417505228076b7e1d3a33fb06af851
+da3449b9b9d7ae4f9d78839e3c2111a05d1dce9f24314d86db842f0906b3
+94fea407f6454c30dd97c6c0bb81a57a4996f557cec7573e91cff5f46a3c
+1995c1d3fe171607787ee048f64a17eae6af9023e9576fb4ca2ceed45d91
+956510b84e077bc62dda487776a2a26965d16f31d1ea5b0fc15701388916
+802b8453501007d6cee79532bc26c3daa5a2e05d8a17f44fa7fd4c02665e
+d14b939e8b853b303822bc1b3ec52dbb8c88850207eaede917663bb751e0
+57b6904968ca5b8685c584c11b9c98eda0c7cfa531a3409fc0c7664c954b
+2d7b7ceddf9bb4bcdf14a341a810ff4982d9a43adb40314d5659fdc2c790
+511cc08557e35011ef1c00050e9382c570d7161980c0e353fb1785cf9cb6
+a2a4e6b5822065ac84912a3130a1a8627f986a954701f8a47e8a9da12d27
+4ee95e51dcbe6dce622ebff358e63d419ded06afffd7147661567b685b32
+e1c17f293d79175ed1df33d10082e30f51cd8bc85c7e817dbaba0ea60341
+d3e0ab20bec2873fd3d15bbae37b4ba1fd32d00c1323be6aa6cd8526ccb2
+fa6018e0221b8442e1e186f42f49e748666b1a67dd612369c19afecb598f
+1f461d45d4acf5b6fbd01240c46fe35bf9f96019fb2822ae4da1ac3c768f
+4f0e6f671c4808e6c19e15f16672d98e44564e4aee08a08bdbe5ffb51503
+d2fbe78c1b077686387bbcb1ebcc145052de95451c5f77e6581c52b13d17
+8dea432dbdf0c97e9fb089c5e44e26fea6ab9a4ea072d59ceb63338d5274
+1c43f684dcbc44d107bd5030cf4390e02322b1fdedf5911722e59c7e8e93
+4ed3846560f4b0c4032a98003b7ad1c86d7f8e1f2143aae7669a8378b38f
+991943e49afdc73ca53c0fe9024eac2a37a1b76bde80ef26303a5ed29efe
+6d664dc5e51788476cf8d0a838b0c49cc4ba6c879b49ff38422a37854e73
+601f7f19945ff1c46d5e685764f653d795d5c93814fedb0c3e88e6d9a5a4
+234c9284318477bb52b00612953a9a8ebb22bb74ec37b9e34b2671cf85eb
+561bb29fc84ea3d8b84a92cdc6310bcf9e5643f4b4ec558fd6ab4faee1aa
+1556387116c82cfd9f7b5e366aafbd365b1e291352f5a77cd13f4f32038f
+c865be940292a3114d3170201a2e1af005e1d176ec573f33e0343f665679
+6e1f02167acd81378cbc03f18699b535ff635b80bcc4b449380da83060fb
+7f7703d94e19941acfec2ae9dd11abf85da49d99f38da1e76d572991aa89
+0a8b6cb7f9174f1445c5926a466666fa8e2abaae5d7a16df2e91dc03f07e
+2e4b901731d69b7f843aa41fd2a7dc029c43510ef3f7d6b82072bbbc4def
+972b4cc2fee6769910e251672af8febe017ba76db5c21b5769b6cab61314
+5652fa6e577c20e34426c2c902c53984f23a6b56f43020001c390a6fd655
+0267378fe8094baa648b722688ffaadfb08cf330d096983f6e43408533b5
+ea3a520f89443e0b8819b7c11867050189b659115a9a19e8f5bb28f27d6d
+ee19fe63fcbea06f3f1ded2e81fc4f493dbe06e26742ab961dba195ddfe8
+6e49390d7094008ac5214d31c4feaa246abf1a285365ed3e65042ad9284a
+b85486433408b9ad90f2457a3b62b6fd99073f0b3a116be3bb6a568ec27b
+abab5a5a37d1a15f97e9e075e1ffa1a9be38bff64e366b5653d0f2901a38
+dcfa9b7a95a9a661bef4dfee91e68dd6a747c712963415309f9512a75fcc
+b68e2b53b4ffe5aa14c49a4346dae193efe95253463790d3075902142022
+71c469ae3c6bd625f93c62783bbabf4231c1c9551a64fe3d13ca1dc32f78
+f506e42d22af63b0e2fce3f5c9677a63479f4b3dbf93bb83136a5a2731e7
+38e5d3c9b4a218549203af2a1fd06f8c1c03deb6de61d18f2884079464ca
+ac1e8bc7ff15aa770ee581d7b5e33b2e9313077f2fd3bf9f76e6e359123a
+62549e51d55540bb2ee0f496d25d84d8cdd6eb58bc23d09310c72047257e
+f9f8a60481dd7d307f7654568519f6011f2d96e56d1f3ae856bdba5f0a13
+c5e45f58df9f9fb757f12405c78a71dcc5fc5e258285ab105ce64d1964db
+b93811c52edaf26f2b2bcb98be05966f245bffb7847cc2c67ab196e5afbf
+2c8f12e725366a72b8e0bcac99317489123cc1fc4d693dfb84990efc45a8
+89fa7aa93026d43db1f4fa85c35261d08e4dc63a06db06bd509adbe77f43
+d6a83330583667db9789ab88b5373ad587cc48e38d522183f4d8b7663d1c
+5d147a53aa70bcd4f4ee824df2824eb837691ebc7f46e876ca6ee19ee1c3
+38023b3554721f1aa857f1a4bbe4ff2142e1764f273972e184f08ed35658
+e07f6e189debe065264c8e9446e904d82aee35d8e2c0f1061ec6fdd5cc18
+c569df3cd3c053f618ad59b6721e464064c9d4712f2129458fa813f84081
+94724fbc297b2f2e1e1bbcc7b6286bd93bc112b7e2a322b5886e676ff362
+88218e94b483212dc4301a3dd2d55c14853c21227ec300c49f3450f08a2f
+61151d77527044e59369e6160bddf601497466bc37468e307e1bc2fc4687
+25f29df7d9be742e6a4f4f4626a30647a44e5271ae1e781347a7e29bb052
+5bc5ff0bc7ee0ecb33354c1a0e9fdafa255a4e46dc00fd5f6f1725aec2b5
+5a88fe79eb9eb272c4fb7c4f537fe9ccdeba60ecebbd820865dbd15a08c6
+482fa4247ba6c1e21b9c71f05bcd3796e94a3fbd9e2e67c4df10a1df9aab
+c8e14eacec97d44f113f4281f70f6d8b662ab85340c1ee716b78c0522360
+4af01b5f46c7f9a3d0f7e59c19bd8c32d8d35d127f45c2824f57b2f205b8
+e46f947bf69322c02fca611eae1563e3ed4cf524203f45e135699d26e303
+3eb5dc1d3ba6666188e5e129a843f97b84a3d8ccfc84c15777b8d7dbd5e3
+f75f087e068857173f795b644a6a4ff0e127460d150cf0225322ddc0de2f
+2011373e64991546394dd27ed68b8182fd7e9885cc6b0507157a8a7f05ec
+99b7443180fca4a174b7aab110d9eae5606ebfb56ff53582bda01228d95b
+38a4d87bd8aee6df9e95d64bbbac35841a478694531e014327020c126d04
+06c0466d56b63409e77a9dafaed155452171651988f0f6ef1c357d9b0bde
+c9b4a3eb25671498cb6bf5d572030baf3eb637cbeda764f750431c226aa9
+90ab7bf1d1593d0243c1d4da652b6450af330130c3bc49008ec4094a12a1
+d83b5f45114121aef163209e39213326d35f380824b80e8041d2e98b6c7e
+631067a43a05f5eaf6018eda387d8ef342a37b08ba5fc5c861d8bf70480c
+6edf82f9c973ba0a8c1ba3a7639615452b07390069b078832343082096e4
+da3b0885960e8ec671513abc733afb947381242f4c207e134191c7707ffc
+e833cab39b31e4b67097123daa326ab006ddc77d2685f7bb9b1235eaeaf8
+0433bcd7424bcad8c6b26171f74638ac2b07fcdb3f8aafdc5f50b803c01b
+aef58089b007b8aa3022728c057b1a71343dacc41c5eac4fc4438a8254f5
+aa932e415b496ec9cb16ba608fde83419d2a1ddf556fe8d603606ceb24a5
+81288c450a62ecf77755fbfa986fa0b0de13347b2f90a8cdb7e235dc597a
+ea9ee287650b4869ab58c97ea5597beafe42535a8c6a345b97af14b69ce6
+369125518cb6f7a8968291c6a6b16160193d5a218702b7523ad35710efcf
+4c5c8e9a2a30d995dceb13eae7173a23b4aaaef58574a266305ea7ac5aae
+801c2c17045a0e25195db4a85fe78cf842fa7e39a203842d2f7481603059
+43c36d4510f3fd829dd1e481d6dd88a15145a9dde88a2dbf272ba516da28
+e41408d65e9a3e502f610a2321e9714ad06c425e96d13d50eb8d4ff154c1
+7a854efecb9cc72927a542b87c80c485621debb530443e9aeca23fe2ff9f
+eba32a4d8c96bfe797913b086becc4ea17dd74c28b4f7fca43f431bfb688
+f1fcdae565aa6b7d1401392092307bf35fb5bb3837e885f765f1c4ef3148
+776857f1c184626a9ca19892b1c702b72cf9b4a698a88f3baafba2577874
+822f4b647b3ef96da58e45890fc9a0566163f4ca43e1c5e2a862a761da31
+f897c50ee5d0ef12406dab7247513cacc1bebf84020dd0ca2302f3458210
+95042120812080eafb7f2e94c67c881bef05da597e4b5fc797441a290a3b
+5aebcca1b9f237f2b92335c8dc10b08e29aed74229abbaf575ab5aedb944
+11c5d1f83715139e61aa9a56276d48633dcdeb7f5a9fff32c9957168ee9c
+b16a99a46be0d6c027c1fa51b0ccf485b79ff065a3a574ab421153de39e4
+19d66d124378c3831944967bc1719cdf900c147e5feae77d6a0d5f65cd57
+c860da06d87cb87d55b97304fd77a66e2865f470a41d8660541f3187cdac
+e346515478fbe50582b9ceb26e9409bc294a43b41d8d2eea2e33a9dce83d
+1faec4b0af9dab677237b0d442e07ee79c25dcebb8faa958ed898ef991d1
+6634bd80db743c07f0708102141c9c3249e09999483aad5fd7e06abfa59c
+ded8f5ae6af64ec5f6e6c25e101b76580bc4a776dd5e909ce92c5cc23241
+fb72bacf5ec93550b6ba3013554ca9088cced45a8cc60029f3a7ecc53be5
+eafb169059ab4b73500668600dc145c92a63c93c47a00c4a6bb050630d3f
+09bbf0a56fb590ea0f3264010097f2c755a7f47587c46c0e8f48def4ba1c
+0d1792d73abaff05f2efa723ced107231f1ea2dd28c5ebfb2a2c1dc8829f
+557adf120cec34a9eb62e36d03175564999fcbf6d74d2396dcc632998884
+69ec81b3ca10bf1c51e819396959e76d1e7a7b71c546e9169d885af04a80
+1e05222aefc8ccb775cbf6991569a1a5226271271599189a83f21cbab3ed
+bf359eafcc058eade8388d360532c962078867b4a024fc2453e29fea95fc
+859a0cec970180796f5b481f8375d7184418e26fc03ebd4d1bc9a902bcd9
+52a0db1296355a2fe09a65f7fc344a52e20b5191305fff4ccc97325e2fff
+56334af2a34f2474fde3674032387c08fceec52f19c4f73246dd303af997
+1ca8c27b6fde3cd2b6d3267ec82dd369beaa19c08beb2e02113cc7e93e39
+88cbd6657b210d6fe796f0325ecc3105f46d06364385e609475b967e52db
+4e4348e39d519ceac21357600893199a01d7359c8e454c102ec69744b07b
+87fe539f0471a474a66ba6025b12688b4da26561ac6d074a2d3c8559a00e
+9b8e26cd64afbaf673b83a89c87eddf46226ae4173af0964b5dc3d917eb2
+45629537828d8eb0b2a6adc511d268db029b1c42cd36e61ba324894ae433
+6f3febd08bae3234e3751c1f216b22c5234c814cdcd5a5f09f5c7a0ab02e
+6ad3d02ee4025f63f9139ee70ab5f5d2985ce11b38e0143add025ee46f0c
+2a1db3ddcaa1f85c068903458541ce7ea038aa238cc6f40085659dda05c9
+f3e59ef16e4b140777cec06ba3890634f766b44f450b98c3323381e79b4a
+bceef7852bc584cfa32115c193d207940a8f0dd10081068188fb47877bc5
+7209e4818917d5d619b7a71620f9f5694f8159f114b6bb9fb357b9c50637
+97ce14b0dc6a763e80baf1e2478599beef699e9f2b7c03b867a59e615ad4
+3ddd1eabc5ca3cd49cfb895d38ee79a292554cd41d16066b06b0c962e64e
+aeec8c3869537215c567fee6f356cd461024bf044af06007ca6c07271780
+51eae2b5eb297ade5673aeae031a8dc7bfa4238b4948b2bdb8a7ad2c8999
+825b4dbb7e5ef34b3365dcc71c6c44cb7a6cc01b65a8171f0bdc4a4a76b0
+579aba33c438cf7f10b09e546ba21ef3fb29cb387bc8e9c7f6239801bfb5
+7052eed5c7ad75ed51690ee5914d367ccea4269d955c27f1f0f64d1e4f16
+9bdb8621918617433cf82d7080cfe820e4f28dc5cb2f9cb6e789928407dd
+afc4270d7d5e34e4c0cbd3e1822b4986916fac9fb6d5df23bfef93db2d7a
+2e8916c4239a13f19cf63892f045d065bcf5c8403d335ac0fe41d4286f00
+c3d89adc24e17420f797ee45749c72718bea13c243a91eb76c2159dd85bb
+b6a7a9233a03d5dbed7cf7a7d204cb61a40cb657886d18a29470509bc67d
+5afc33894746efbd5c68e491788f1783b9a176ab9b4835803b9b519098d4
+ca52deb18c099bba120185f86254aa8c5e42eb9a6c344924f5bcd62ae45d
+3c490e2de6e57d3bd2407faf5549fb7bdab9252d2e9caa0ff0b7561046b5
+ea7174db13068e596dc52d6b9fef5249839cbd4320f118654a90eb1c9df0
+0e07d9526c5c7a1ed71fb258b47ac6d2638db0757812a271f5e20b6dcecf
+c0b09ce8d92e63719281f666906c8785873935fe88852564ebdf1cc8235c
+c3f5950cb7478cd3c41eee53fe028d963a48eb599426fbb6bbde891e8d4b
+9de69a4fb790a4f97887497bb36432e49f83862d6c75567381d2dd409438
+6c01d0cbb429187bc0bb3e32523dadaddbc00c390875fbf5893a05d0685a
+02a4bcfb0b7b86d5b5231b0418717379417d027f30d3717a2301cadedf99
+c73738abf2e90d1632e60239e75ac1421b5dfd09da8f0f6cfe3c9144974e
+1ef3923d52e2fb968abe3b3de27865f2d929cf844f9cd60de0e17b10de17
+713350a859ceea437629fa3121fcc1860c404beaac5e66a9e915b305fcfa
+6d4f04c30a7cb5f935c6678d3cd3feafa1cb6ea8603d3474d92d670400ba
+0940a09033a3dc382340473c57461561b8477d175699e6582f7b80a527ba
+3f664b3795404b69867e449e6accbe2a76006b3f94ac73127538944340c8
+370747d89df000db870a15e455b8208d3467a726dbc6d723fdeab51af860
+adea1f8d7460c464873800cb36ef56fe58e0ac3c65083ff6150739d15526
+a9c26c47c38890a0736dca6516cf1ea4846d4cc05b4c2a06d0568d8bc40d
+95d3dbb3e05797f697ff00121c8e76377717d4fafaa7c22d42ad04262546
+ea908c3f2dec39d0dd73ae3ff7cf1eb0dff7d1f8911d5e1a1e82b5c743d9
+2138caec847731416d6c47683f9a02295057a3bd338fca0b115daa7c4631
+e4f60c1aaab81a796a579ff1ac9dfa8a63e1c46f20fec5c2c1f682c9985a
+23b1f5c3e8db57e4ddb241f29dcf7dbeb4205f9282d042b9bb11d770bd85
+bc13b4dc753d6353c3d5c4b678d5050b768e060668b7e6f860b38d611575
+8805dac2319d6244baf0f52f76a3054929e3410b477f7652639a516fe7f3
+5499fbe072ffea5f14cbc63226e82b1f9721fbf042887fdddc63d72be1b6
+ce103589a17ff220b0928ba0398b2b3005ecc42837b019cd3db3fe583bf1
+4209f4d6cb18b44a97fa259ab5d5d50a6b51056255f39df783e160bdbd52
+1f62dc07868df941db96e4de54dd85e689eb7fd041097102290386ea422e
+4e3ae3377d05348c8afb7f0f7bcc256916c49537ffc3dd9af81a4ab070d3
+ee23e07881182a9e455cf5fe9c73ee5f64e18887cd987959967bcae04045
+e11809812a7c8e76cee5a4b24d9d22d647eeafc86a0e178d76bdf7c0f29e
+b5eecdaf8734ab4acae5d94471d281bbb350d87a77342abc9f04d335e562
+2c73d348560a95112e778fa0bdcfa887a4100b2c71ea6f42abb43b701b68
+1e2513bdaf1b21ab8baed2288bd2fcf86fa76a235c907002c5b07eba85f1
+60892ab89dd92f184a9090568a3b4878b86c96ecc0d4fe1d6c696b6123ca
+55f5945eeb19420cee8e6b900d1c31d2145b01aa152bbe93ed98231dc9fb
+59bc09f17b678ae6eb13c5830c6dd9858c4fbfd8ecb043269c87829755d4
+30ec0e47e38e374de01977c1c86c97281e1f953681ccd9df78b958a442dd
+eeed85815839dd05f4ae5dc5960d7f1e3bb89240c64a696910de05bc8bd3
+437670bfe89cedfb9f22b6234cbe21f9414d3a4fba3e64d5a480518efb63
+59bc32a53912e08cc1c848ddb9e8fc23e1d287a8882fd833b8849f0021fc
+cea764bcecc059d22b71300318e52e6531810153b5d3f12b8202ecd58fa2
+0da6276164e443eacc3421f57ddfb57d45dbedbf0808293df296881e2621
+9f270a468ea69591d5ee5fae92a913e2905f011bcd0dc7b794cc8b1c8d16
+6ef115e4a0f3678e9e53c936c9825e30e3ed62e689c67f6c31bf282a714f
+41d988a0f35a0a01b8c7d0a3deba0d947d0a7ca5a321e379837b2b0175fc
+6cd46d2dd2b0c6642ddd1496792c4b1dfae6011af1651499027a7cd1e5ab
+4f52ebaac9c600bef926f955c9d8da1a5eaf4698a71fc0fc709530365f02
+5a558747e11a40c121a130a01303f668532386d0c9a576937c198547b4dd
+4f33c252cbfe9d906fc940c56eeaa242c08a5ec3b44f7d8f42b3d94fb53b
+5a4a8c9cb11f6bb46b153f00b6d58ca6a0314cb16e4b65d5b71c739c0d42
+59bd30a21345abb5d78573a8fb0709945e5f536d30689663b31e64309843
+28e76309ec9d0b816dff6696d34a564f694b2e8b0ad62d54fc97d2d09ca9
+457975bd86493f306be8ae6256f58ffd06b1d9066a4b3ad2646e4943fda6
+f13163cabcff581f8b92d5f33edf512bc80abc2c843552d7c7dc2364bdee
+fadfee5f842c1009817f1153bf092b3191eeaba2099136265052ca1992f7
+93a85b1fe1c1acd6d6b5ab7b169c05bc65bba8a8d47d01f5c4b0147a97ca
+156cee70d33abb5e58aa24669b240540fd1de6671ef067a3fcc2da39337f
+fd87e67d34fd042424a4b35a1f893de8976976fa6a28f378665f0c51237f
+5b83294b9e898523be5bd0920f1457c480dc88b97f25105a04aec0d09c6a
+ad915de6b2d5b8f001ef68d322bf421c98205483b22f7b62797e1236debe
+0196be1a423b34da6cc41a1508dde499b5ba7be07bde225a657888033e08
+134bf424c539ea2666b3c13202b5065dde064d644c13a51a6e0983d04273
+23084c00bcab73201f74ccdae02e951de42dd44039891601fab4457b4b00
+5551607910d221380656b1ecdb91f49a963e9f90f4a84668f2da5ee97aec
+5daafed5d1b76ec9f2b663d3ff10b350fba44bc4208388cf3084a26d2a72
+00a0f9e59330b873e582614ed9625f33b15c32e54f0f26c8c4b272612ced
+73b705f081438218b9ebe6a934a443b8667726fdc4ac2a1d3e250c257c6f
+b7f525b577852262be1c11e65c99b065fa49df1658e2246c6579c2c3d440
+86786f5df550f75c97dcd42299d3ff4fe369dafc86c6ffb8b4bb0ed255f0
+899042b4a5a20e34480706fb57c6aa3c66633fc98f1726ee1ed94ebe80c9
+b80b083bebe029669ab2a9aab869f8bbab90f2e6b3e8118091fc8ec6e4a7
+42e03b9697feac3bd484f8e54d535f2bbf369a35b903366fc07d51797d63
+431f966540ce46e0fa1f4fa96fd80d41cfaab0564869925d4c6661883998
+6ec2d39a3f31d27b59b3f89ff50ad87cf6d246e961813d6cda8eacb063a5
+7071d27b6894f0b6261bdd3dba107819e8b0069b95ac6df2825827fe2a6c
+008894d586edda33d4e4bb73a197fc0e04da8d91e5e58a4a8e79be380e4f
+88f66faffbfb92d4187777c3ac11641c0ee6bbc12f9e25d2e02d73c8be72
+13edb765d4df3a6926ea2365c3077b5eec405f8c8522955900656be71840
+6bf141e7880d3272fa6853247fc1bc7850b88cf77167b147c90a2b33dca0
+217ef653dbadbe88d3ccaba4f125d7abce5e1e255cb65510ed58ef42abe3
+96846e6a35afd0296943d1c3be501f4d4969a088cc28b9e34734430fdc9a
+3a2d5d9246e6b74345112a0168e1b4475a22efe028137d3a8531b1f7b290
+544ca21c9369cfc0ccf0f223ad60480dcd7de406d3a435d47d31032a05df
+9925720f5d75a8b0fdb3ddc452181b9365941f774f8cb12f064b3c2a0104
+677b77bd9ed44f3362220e6c14f71fd42860f931703db69b9eb225f56be5
+1dded349993c82c9ac54c58f516cec603395433d7c1f91ac0477c9d291ce
+c2d7408a67846ac08e5fa57f50e7dddffafb856335620e3111ee5f8e7833
+3e070845aab51c52a4aabe1a4fccd28478709b6fb7827aa068ba2081409a
+396dabd3b0b7fef9adebbf21be845c7ea7eaa6a08a444a133cb40e5eca88
+bf5ceff2df181e75499514cb883772e46a6a88fedf8f42a8df053f379e89
+da985d1baf955d9c2180c61fe8d389d2f783c6ec4742b97ecf86dbd8df35
+a1b8b32bc3babd586f130fc78d0a458a9236dd38cfef1b5fd99d36c64c67
+b226214cd24e236d2185a83dc7c17de1fa7b5ef4a829739aa99e2c4df22f
+7a9725c98ff1ef497ad9df4e23a07f6c0e13217ce2bbcea3abee7719d140
+37b7aeff5a8cd2a14f96270c2575010ddff8544fe3fdb7b2919438fa2e82
+c61020ce4f53b6bc089f350e33dcf757ce8ae30fc87e2f521983ee484aae
+9b1780e303c281760cb7011ae14542977434e7d4ebf847e89b9d7fe480a4
+4e560371ecd82280f5ab4730e067ef1dd2458e67e5d5a688cb59376e46db
+ea7f6d01a4f79a1bbd8f74166479ce63d79ea021ae3f978734d32b4af080
+3c193d584b40127a3517ff31a18a13be94b639b600b015975dbf25fa6337
+0777e1d4aaef381da47d2fe453b23dfbec0c427a274651972cd32d6aec68
+8f022334b0cc1b1e20fe5ace2ff5b8428a80323074545bbb66e9a06aa07a
+635fc77f98c1b3a36fdfb6ebb598c122d8170ea4664a5313496c705ad1ff
+7f8cee9e4cd242ac1d6e5feaf05665605fa6f4f66919c7f17bc4cedb736c
+46e8e814b129c358040ea8b2bcd87c537d7a72ea5ccd322f7133360aee10
+8cb788aef19077cbfede0424d7490a9b9c095aa5208b2eb17be00b2932d1
+5be57b0fc0332b9c0718fddee1ec98fd592d9ff45206a8c5fe3893d921e3
+65786061ab3e3f3eecab58eea5daff02758fb7acbd8fbedb5e7ed25a19cd
+2e8030b8b60670f919b0ef0d0f77d426fc228944465a8cc147e5fe684007
+c5961f2350ab38e031b37788add075c99a4d8517394b5f007d93bf7d4f6e
+26d0ca16818e1bd015c951ceea444af836f3e54e5a717d154262e2e94c13
+ac246670c6e6a2ccf5574abb752a70f54c36dc938a1cd193ad898bdbbffb
+0686077a0d76b96ee02aa45ed3e3f1d7d8726515d5dcc296ed1eaa36b436
+b9404df2ee1edfcb0762e3c9c3b3a9713b485f276e6adc283fb31a8f0c8e
+30b12c9fb01bc2848f2b87e76a934ad5583fccb0be2077bf6805e7bfa2b3
+226375c2c1c57e58f83c85cc394068a7798612dc47fc420f10a6131f0bb5
+29c8c7f1ce725a9c2d63108116b3f486066bf441be65580d0f7357b39203
+414ad2e1edc5de3f8bc89e35d40bbf4343dd7f794f71c23bb1f544dc3df7
+1b271ea1a04936481c06dba58e0c14a3b4c765311e6f9a525dda70fcd36a
+500e9592a2d09a724f58b1bdcb9f6bee2202c5c34bd4dab4fda371b263c6
+380baa85887025b1b3f82ee02cb9df0a358f469131cc6a7c7d1090184998
+5cc05234cd313da57093c2b05339ea4a33efcbae7c6fea6e83b675e628aa
+e9ee04d93aa05002dbdfac3ec439134741d3b5832ec59b2ed54cdc010ab3
+f2f775cffa46a7f1ad148b85122ced80c71bda3609d646de4fcfa6eea599
+9a2d7253a2a2935b8190ea39fd8b8b23337b3ba3d2b7b28c974bdcbae3ce
+23742143bf744e6d3bfa0c6b0de3a329ae49972cdc2a5a54cfedd4c37622
+3ae6fb11566d346be71c4d942e47cc0587bb1dfdf5d4dbd2c0db44b1404a
+a3652d2c49cb00779dfcb3b9723a6cd46048b1c5d6fd1c6264d9c1ce8e55
+b7f5314c2ad4764d690d6c6f67c80c87e3ba1831876e4602c2eccdfa3fc1
+f5e38630316cf4b1a78c8c19012a7c42f955736074758a50949f7fe56ff2
+0c75007f00ef89167908246b636a499d1067be560dd538982c0b432dce25
+150d9cf51b3e2b376e428bec1355d42d3418fdd8cdcf153213fba77c0211
+aeaf3bb5bf9d8aecaa2be9fc22bf59ab04b9b8727570033a31c796f81825
+91a972ebf01b0f58b27cda24dc4d3ebe9614b5396f3fab6760b7a47abb28
+c639dc7675e27f8984bb07ad370be631eee6c6bff903f27646a5b12b2c9f
+8fc2446ed6d29afbe34d52a0b5aa0cd25c15e65416031bb91f2cf9a842dc
+b6dc7756423dfd187d624ee3fcb3eca3bd9e64ccd5293a4ed62ab25ef0d3
+f4653d94dd4a12913ecf5819b1992d22810cf648949d26bf4b752e1d8f70
+ab4240cdc4a30790a98fa8a7b80e8ebabe343fdaeba41a10d0554c250182
+d04beacdccdcfb6f779b88926fed7116eebc9f9e0e6910d3b3a480785a21
+17314bf06bd22256baaab66a2ce4bb0a4d585b2d52f8ac37445d78fba186
+0fe594bbda1207c72cf7a37d14a5ea9b9503279771af9c74bd7375e55172
+adf6d8abcc525f1bb199f8255961d075020c0ac6abf4be0ae65e2123faf1
+c9beb33832e08df28b0e25e9dc6dc8b86965998c259c3e1dd05996c030bd
+203680588ddd680de3fc7dcd6bdd329ec679597e4408d248d610778bc286
+8e9aa3ffb1b40b8d3891cd03e726b1ea1d7e6e59157df0bdd85a67b35c5c
+e671ac595d95fb5a9906d73e24e5e04c6ed089747163585c7a89596a37ef
+aaca6a7eefc794fc65800be79f5e0824afb0c43030b3bdb342a9b4f05463
+66d93f2b36998dedb85a8ce186a78bb32fb484cabe8674dafa05dabda180
+fbc38eaa84d4e37b4d17e7717a29233a296e95ef26b04bcde0c0196f96bd
+deae6febc60e9ef06fa12faa16dae0178d04527c596c35ab31125cf17b23
+aeb68f840da1465205e482faa17388f63d18c8f656ba94a1a8e8c74ba8b0
+bbc8ba454d3b42e85bbcbf8d22fb008be86e9dd22c95d13cf0a471c207b2
+25a4226265d68c8aaa1746e4eeea667f5f6aea68fdcc91de8abd883386d2
+a1a8de7b79535db2aff83c13af40e46fae1f9229e9a07b504b3ad1a3cfd9
+24c0b7b0f80c59d9cfcd0019b10bf8000401155bb62145d56118b3de28fa
+5a980a9c5aa1dfdb7c9921d72145fd64fa623cf7f821229e2f5642a66ef5
+21f3d73e111761eee04638ebd933f3b1afcf9a14cdf8e39a956c1bad533c
+c9bdb0c15dfeaae14032839079ab552ad647685826ac145195576c184fcd
+ae44fc524d74d34b5b43bb9885b8e3f0ed130a708760e92650f868682140
+4479a88ab16cc0fa2ed5bb2cd3bcc0b3bbc37644ec846b5fa08d533a4b3a
+730dd4b6e94171526b29b7f89d0501accd6ff70a20451877fd5c0f0ad691
+51be0d127502db63841b29e96cb3cdf00ba2e4d43c494be2d97319a0009d
+a3112ca70713ac18562f8e1f08c787edd1346c0f43c1045d3fb5c67ca494
+8f1a4b3b120d3f8cf0aa18a7e642c5e3bf38e960f207859a922e4df90c39
+a0d213aa61b31e7d389f6c6ed525a1b5088913134fb8670291e624622c1e
+3365e85925f58b68cc55038a1ddfe30b6e1c7f91138911622179bd2294aa
+ee3b46bb141271e11e059abe673e1d7c76577ee1ea7e991c88a191ca1a98
+7a2ced3be8c70bc5f9b263b756721e1e3e2a850c4682a16a7b4610780a2b
+ded9da273cb7443cb59a6d7a0159c254012c4b6231fff238ce4e11eff921
+41366e8c25cfa8c8af0c80a809adb56233ed205de8b00c233a1d666c0820
+4244c0f0d225e38c85344f9247e1ac59d465b74109ba18fd044912315a3a
+b58c807c22a3e2f07ddd4c78c51f4e68f1a85a1ab47d180ae37394316ee5
+13e32f8b3a9416bf9648d5556791e5d4fde3d1f9f1e4a0135c649de3e730
+8933dbbab840f5e7aca82f962619688d9d92fc10f01ab5e461689b163de8
+530869a733eded113c1b4bd50663f34e2f12ed35797cc6457f90456fd5d2
+4f66cbc0d73a5c01a21892518fff09a31c5d0a69283a671fd0ed0aa9bd8f
+5b9000e0de5d46e7510352c45a663b418d5f5ff9ef32088417e05c668628
+6dd141316ebef48bbbb11a7fd97bfeaae428263ec2c852f248935c174969
+b043671376a3e9fef9d477cc78533d6c6eed5249454e5d70ce3b2884ddd4
+0f9e7079ac840a59bad2770a04a74625e3fc5f609e903feba616554da424
+3bb389351b55923a7132b0465fe4bdf29347b091e3dd790e49f9ab22efc4
+174582994879f2d6cb5c0fcb7c075d4ad35ca15c50cd05b5125028fb01b1
+0a946e47907ee7dfee9816a4baacf58c6c267586592927bb42f798215c07
+cbb8705900d00a6cb771e0b50394307f5afc0e696bae7ceb275825cf4bd2
+72cdc83e4c92c1a74ba4e49f36b665f22558e50bf2508d47d00a3db176d0
+74a97ac384bf912f15a11d79a1d834765f4ba678c00acd9ba9f2fed3ba0a
+824a76b91594fc57517667a28ab6ecb370a9c99e79a6c1e26ac0512fa455
+11a188dea762acdb3b4c1d00238545cd8f66845444b9389b3386cd1a4a99
+28c199bc903895b40f7a4770117ba88994d3b0bda82918ac4c657a45626b
+cfb3c22da3855d3774f75051b3d743afefd9d759140c9509d7cab68497a0
+9f2ac7856ffa0befd13e74bcc5e3dd8ed7f0b5f31ad45068284be0898f44
+65dc13bf17e4ad69e2b8e490ec2670e184ab81b1e96663cedf9533257cbe
+cb29ebf27089f6478f17d12ab93e521f8a31c3f631d18dd3506a00019e86
+6112a6239fe5bbdaf15e88c1fec877a8bd8d1d02038f28159a7b18fc04d9
+15053b84a9d1a8568c44ac1b25ace3dbe913410bc340f13200e05892bd23
+efd7888ba0f8a19f71b025cba05f1c52d84e7af93cff7aeee6692c08aec4
+4a3ae446e27048b4dff167a4d1270493a28c84e72f8c915bd95cb67d5e07
+ac855ef06750225071764e1f85a46a62b0778fa0d16edf3bb714c5a0e259
+aec71c6d9bf808356bce7219ace6bc8750658903d58ba77d787c4130e12e
+fedd4eadc9dcf60758ca4f6d1804d36e3e8dcce451522535be0a136231b2
+8b60ca7285d9573cf125991a07e1b9b747b0c27f816dfdd391c44610b58e
+575b415e722e4b2983d05b1952e878a4ac1666c9ed613de46fcf148b14de
+c380b11f8061f3de38b92015878a504cda1238679db31911fe82a0b8d48b
+8c1b7258afdd18261966ae42b93079e9fba683a957188f096a9e219b7fed
+e7bfd55f4ce5ae3c57f5ad7314278a17858eb68766b2383c69de620cf450
+40936e9d2e1317ed4a711ca32da934d1e00d2c54792bd7720d5a5439758e
+2e9307c94255f8e33be837f43768c85c2ff0774dfe18a1f3cb4d8544e4aa
+8fc72aecb801df075f22773dbc8c7aec5635bc4750d0a2392307dad6bbf5
+84d065774dfc0725d4c56fba356eda94ea9538639f01bdf8e5963fc665c0
+159a3117e345acb1eb6a4a3699c54cf096bf369782c8ebf62de423c8235b
+4db3ff59cf130c6f9c856912022441946d703baff74848cf0bbb16edf93d
+0351de8d9a7240d3429ae4f1268be3ae553983c415cfc43226fb5c813f17
+2f440922e73cffbe4201add64f01c37ffc36e9b746b85466566649fc71bb
+2db6f88a1241e9b072980d136bd8baf9be30fcf86e5a66e64daf98f03379
+8d8f0c19db4aa3de7300996b11292c7bb67b88eb3dbd9a9c5c2b9f37e13d
+7c1c8d66e6df212ab2ac7dde58ba5897bf3a6e4a607ef1ac00b062bcad0a
+20da8dd0557726496bb7c55137f373531c620ff7822d0d2cda8ec4aa2b5c
+70a01d39be75a40e7e7dd4868905a358461fd451d650a6c48367dcb60d5f
+884425b4c4eab84749646810c829924dee4a8fdb49e084d013037e2f9fa7
+eefcd4ab8c7315791f6e77c3ac749ace6216ae55576c2b7f6138c7d10940
+c805be36c488efa5442769118afbba36fe78acb2b702eccc44a5de3f20eb
+0a6c3a3ee947e8fee213f034adb2195b84cdfa089063eaef5e489583c42e
+9475cc5dfaed3b90aac4f809cf9fe52a68a52f57c329b7d5b191bb4d7503
+88398011eaf81116cf82102af320c92a8f4523f808d208cefe1cd7c4c1e3
+6af03028dc7bcf6129e82ebe328c62e8b851775bb4dbb99314bc4b0c4b4a
+0668d6e891f4b5cafee3cca709b50efbdc63a6e4f0b645c24129567e4aa9
+76fedf285abec1b21a94e1abe140f54f1605a05c3d432a316fe92f742e99
+0d16396288a812a9951114d8cb688ee94b7c4977e398e24f0da3674610de
+6b834adf3ba0d324a395857f1f6b613251da72e557e0b501566b40a6ba2f
+c33e327de7ee6ec6306370fe89d1068b6e21d3fd16c643e75e8daef9e21d
+4c4d1ad5ebc20b59a4ec8d4871aaf61afbe61249b9a7c98cb11713f757bd
+7cc495e990c8f4c02f167643226fc7bc519b6ad13c108d0fcf6011526211
+287149179cb3a365beabd956988b7427a6c99e3138cfca940bd9a100cc42
+29a4e39394f13170e020f0201d3e12fd8733db20d6429397162fa80cf651
+8df73293fcf713c0718f4cee898e4458d20fcabd7df1d515160dea8ee657
+ba23b9cfa04b77e9735ea8a28630f4b59c6c0c880454d83163276d15a44c
+54954e0db01ab948e5d43dc3d9c35188b5985f90d3836e98391cb158e077
+dfa96ac6327cff10098b0bd0251c3f8d6b52a30df2057ee7e7ef476df08d
+a94f6d7205db461c59a53746295d972453d35259ae58e9c84aba5ce78edc
+9dc3a3bbbf9a8476fed3dc7fb0caeea41e4f9133df0f6fdfca03fc0a0929
+b8c9aae471306e8f5d6a4acffaf9cad054ba131f95480d9c39ac587d772a
+42a5eb6804e1949034bb2797d26dafd17869bfcb6ef7ebc86534cfc47285
+0a387e630adf1f44ef3030414a043d1a470b4243df8f4f2167ad1d41fc46
+4ff6a2dde946a45c40b22dfbd0d695e4a4e23c33df35a63131d52cea49c3
+8b6c2af7ff8661188fad07c1b9b60a8abd8c58654a6c7f1569095744b6b5
+eaadebb9bb84f3ea89691699132d550b035f290d98d0912d733b4953b84c
+8c0ce36a84a319d73ed69ada4710e2a10e0ad59217c7168ed9dbb99e52db
+af904e5ab280122b7d9294970ad8f0c502540b15db3a7c92be004cd2ac7f
+b671a76002cad472e75ee188cfbd6a5296b2b5bafea24be23df32c373699
+f39640cedd846f0d3c179cb02e1cdbee87fc0a64840510d3533f7b73c95c
+6cd25cf46d53dc8f75166e2a8e54bbd82af532c519c3e53dd5c6544e9737
+300121fe0c63d4373cc944fdba943736a104c657c0bfe84c06985241e11c
+beacac70c1378ab30ba5d3a5c93f04b0626f5a0e055efc1ed8720900e6d4
+a4914c7d0630e9ed0e6bf98a72eb9381a3d93e7200742fb65bae28852212
+72beecbe7b24775f44bdc9a3708e84bb691732af1f39f7243d600cf7ee9b
+25c5a2a52b0f1abe0e6a984590c7e430ccfc8524fa7f1e20c92ee10d7763
+d096b5b792d4086c8dd2bafea15ad19ab754c08a2f8119cd0733c33d47ea
+1d84794fc47a2f83439ac4a65eae7525de8745b2971bee811686073e55b1
+8708945e0445d695dedaab56f5aa1fa29b46575f995bf604fc45ae5dc043
+11952cccde3c99e2fa68704fc47308add2fc3f83cb63b2b873c213eb2e0f
+23548de52b3908cd31473213c9eb64550ee1908ab3c2f134014df33c3453
+6c17d812906af49c7550904e59902edb5153d3e86e649e372940e9223d32
+95ccde0807c959565b5426ca1ba959dd3a64b6357a0789de5473ba1175d6
+7a53d9db968d9682febd4c2a01cf28e6bd7e5a1411f488f9bc571de02100
+3d988de831a3d6f1e51faecc90029b527befd59da843e58ba9f4d0ac47d7
+9e91c56cc48c5ad0075911df2c7f74c3826fa7dcab6f66f4923a19e4389d
+c4e8f0a2004824482a4a4cb96fa431d251a51f035258b90d8ce3651914b3
+c9d955b77f36b2ce03f8cbdd0793f1f2eb7116f24035f333f3d1a6097a1a
+eb710546a09c9babee2881eb44a09cd2d19251ca8044b78cf31c6d8ace83
+c55800bf5c3b1041a654be76ae2720b22900315e0ad2e933be9945e47e6c
+a6b7477a94cc9582274e5c894aecd1b544856b68c72c574e506002519545
+32bd9ec00aae146bb1048dfc0a06ffe8a2f2c0a2807a6954b455be078c28
+9b5af21cdf2dee0368b6b88590edf81357c3cc4ee316523c1c0f6edce339
+3a5acadafc56dc6565ef554b8ccbdef6954385165b8647af8c7cf267845d
+d42e2a8df493f56f534500c7d82149ca21c6a2944ec91c1730c63d4329e5
+0fbe42508116deb021753abb64ab752c45e00ad697d99c0ddff09eafaa8d
+b9189f5ae7fd4cfc58f9098d0f67ecc489714a7d7684e85b02c0a5b8d598
+ef32a79137e11a12c8c14cfcc0bda0effa2f2c2398b0cdd5eafc0966b1cc
+6cb0aa51f225fd25c49949fe9f78b189fe698e4fd37f755b1e9ad12d807e
+16cbfd671e37494ddc407630db77f07156023b5b47f0a4799b9649028c56
+0216750a6a7c89c7c3cc0a2fad201113acb18eb0ba31bce9b0631abc96a5
+84f4d4f78c0d7082f743e899b1c012ecec31e499963ebbbdfb97d92c99e5
+63c8e95d8d3702e4ed816989191ecc46d155c285bdbdfc7b283c29b0e5c8
+00345dd40bccc07abdff173e1596170734a3d91d892509e08a948fc127e2
+c5de525778b2fd0fc0841626f81e25c0de7473fa627427ef0e6a20e39124
+8cd9cf3100209bb173d56daf8c452a388f30d8d9615276e47620acc19431
+67404aaeb2fe696c36489e21878187df01b45a888f34045e61114a4946e2
+9c16a2036d7789b8e46c2437754fb1027cbd105a8a5cb1b6efe2b660dcc9
+7b43c72b08c633f968bb54996ee8452b8ad93b2e73a8ed46e1e173e6f7c4
+51bbccdd56e83ca7aee834d0fa12a459d472c15a53a15dd753f93c25731e
+9d653820fb3eea99577aaa86761cb9bcb4b0400aa7f8ff4339c4f0be3880
+5e2f1a4685319aad1a882532b7df962483d6ec9a47b8ae11084513f49816
+caaf4decaa70460031e7ff9fbbc13fba3c12b63aec3285b7467fbc399ce6
+5820a7bd0238f314fd15b1f9b0d28a5ef043e5b27aa4b3e7434fc40a923c
+5b23debee9613a09c48ebb05b8106c9b5fceff7aa93871fb90016bd72ae8
+c59bcd5f5e8e912faf1894906ffcbcc0fe34a67f2b0905c56740858105d4
+8ea5f5e2ede29c596acb85a60c5a6c058504812fa90fb05211cb6de6d95d
+0098c0cbcd8fd37951de11a16750db13323eb4b961a4dbf93bae3232471d
+654a4e3b7a0a9fc87686fc22c89b06f3ed5d7fae5d0615b334a7fe5b95cb
+03c748b2f02dcbdd253c944243115882318e4b74da5c4c5ac663bdce9580
+3f6741cf50432b1c5564107dd05ee0b6b7ad112080fc65c480253d38b2a5
+cb086bc8fa2e362e3593d4f070cb16ee0cfde3c50c39d5689d2cf5cd5657
+804641d8525edc36eb9fab819ff549270f16a74f6ebbd8a97922aeb99982
+dff05d3223222d04fc9a9c385db246f41449532a1be9041a646bcd72f4d3
+a2e6820a83292c7d47484110cc62f14e5c08cd42af83f7bc2d64a0956e0e
+bd7015ba7aa3bcec0fcd5885308af509aed402f1396c7a25e47eb25920cf
+e88f95b7ff66d6d50a9eefc2d66f3d1392cc12cba26378f05a53a4c47d44
+b8006c6aa31931bd8f442c13a0c21e48c5868a1c275a3e84ad5f27a2c9ff
+e16ed8ea7d2b3725e2fc31b07dfbe9bf04a07dc8228619785077d99137b4
+f7cde57aa7490cc258c2b2d1c4c920f33fd155a6fd1bc79c26548be69d8e
+2f50e52f43760fd522fc605ab356a0e1b88bd2a6dad4fd981e59063dc76b
+ea561592660425ce3950a1a8ae22a82304bc1ea0542a943528773a55b4db
+a01a24ab34fb45021d9799bf29656b2d708982c70f68b5942594d9e7d9c4
+b8fc7d16f31fa7da05209f4b32c75b2ef4d1cb485bf83339b4dd4a3b06b5
+61780dabdb959024204d1b10c21af5b53ccf11576a5bed494153051ec6fc
+896be696600dee78061f661fa00d32020cbeeedab18e432dc785fac8b07f
+47d0c5ac0d6553f5628eb560902806d4132bba6e0c22003060ea45d43740
+26d0009e231be79e948299076c3a020d3ccf8a96e6f5b781027d75490b10
+ea64067692cc1742295ff01e173bd3d92fedb3a5256e81341b608919e4fb
+9035390372d560849bf0134db57d43e245f9726a8d3bf16edc36c9945772
+9cc21eb0d636b393890d51c696b6234c04d4a709bdd848174c26de3a1029
+0ae7e3e0e00ad67f2c47c097465d4f9fb72ae2cd781781d876cc4fad8f4d
+d32487481c1258b272b9457621680d67a0dfde705b92de4c9027a2159cf3
+95d1518c1fb970fa566c3eaccbe5bebbc67eea26b01c8c3e763ca3402054
+4eb3efb615e184287d005bf513d83f5059b451184950bc33725cd383921f
+1101263af8f68ae528f0b8fd58b23ff4e33377ff4cd42b7bb862c4f24cf3
+5b78c1a06a5991092be70afbe763d988584ca8e27a45f202ea76c5bbad75
+eba84a8e687701d2ffa6ebdb8b892fe0b7d2f6bb22a9e63d01db96f48afa
+536cdb363d3294c6b912bc8393afe6cd0933c2fb69c3bb9b0247a69c9ce9
+2ccbb86a319cbafe871d86eb1beff057df1740d5d78943b71eedfb5d10be
+a9c9b5f5b256428f8483bdfb74446f01e19704bb63ff46b89ac1ad1ea9e6
+b8167740d92824b70d10e62bf91e5f195d3c5b34c89ebb76dd0c3ae81583
+e62b30fa89bc91505ddde2ba491c88b2cb4fe1ffe969fa639c731cdf8bc4
+f4026c95877683dffa4ca845cf3ec817262482bb4027bb7e5b90c2c56153
+529f62fc54d2b56c951cda1dae3bd3c9b168bc93cb7508c95bc0b9681f91
+661d8d201f655701572e90de07ce20b27f5f91c66216e66a89a39c0d7080
+5dcda7789d3e4bb292e193464737d7254bc70b93a5c9b4c49bfeef3df5fa
+2d333eef22d067df635e6264d151137948e44cbffce8b7a2f85ecf808e3f
+4f8f1eae3cc3df13da3e92911910e92b5ff641155180be4c77f5ec0ccf0a
+d2e7395faba6b848b3883d2d07573fbd446b5f9718ea09d1918bab4487b8
+195b5436c81767635525ba753ca7423a9783ffea585e9932fcbbf6efaaed
+d1f9f1e4a0135c64e8cec283876678cd568f75a116ac9c757528625176a3
+a8bc8b63b7b9e8cd06a9b60d00c5c21f6a1dab66c7802110737b3e1ce8ab
+a5d14061b604c18d7fcf6dca718c594259bd74547250c0d47b30e3297dbb
+05c50f4128b83f58fa96321e6c1fe34d5296e11bfb4cc550cd80a1214d82
+1c04be92b7aeee3ef4e4b70e627635617d5496dc3281fb474718e5497303
+199bdcbc3318423e0c2227795ff34923772c7f53e6cd0811da7d2c231018
+47541e5d6a2439b2313f7ecf5f12d731d0de9db8bd45b08e1ab129eec0d4
+eab8ec632d0e5176ad67ea81c681b9203a4988d22db6b6059f3fd8870889
+664e1f888265ed3b316219dfbe24a7d4254cc2f4981ae42bd78c73326019
+c504eda3a4d3fd181a70dd5085883c11637c78b82b5fc78e27878b53208c
+5593a52114d83c37026041f801d950a69bf9cbc9b75b12813eadd695e65c
+1583254b25d17403fa4d59f518c572f8ac90a386c9b63cb662f50d092cdf
+374e5c14bd92e50ff46e4fef2d8a9e3da367e7d3f3ba17400d5445463992
+74fbc801c11e85e8d10450ac0bea7a468f1ba990b4d959292e40bbc11d25
+30e42e65356719a85c76efcc6ea9a36029411ca1225b11448115c16d510c
+0456ecca598ecdc3eded05152b669d0e7ff3e80372f23e098c6d02eb9e5a
+fb256359405bfc81cc9a927550e4994c9dee0815afffaf2d0a5fd3ece4f9
+057bc6fe048761f74d81057eef2b4fbed38f8cf6df765975d3cc5131093f
+757c390e1e324c159a70472d784e49e6ccb75af3f303f9ca91e2eca0664a
+4b4ddd83256e22753f1fbf2b5b1e73779390c8c582e1113acfdb212c1a9a
+a7537ddb197c3c36c642657a5c7242b6d25976bd15e1ac607db186bc2ffb
+480b1c95b1f71faf1903c864e036ddb42a681f2318dc212b1be3a8fd781d
+ba69daf6390ebe299a5d57d596e24b737c529e48d7d8ae8f29d897eddd5c
+fd970a7502efe9dff7a8def548d07dfcad7cf7171f14464ed185ca1ca7f8
+12647d82f37267f9340b4b8138471099bc9947ffe8836a5fca145d246298
+fa6a16a220c4957dc09e1f7db803a488bd9e23e9b06a948f46327a0174f3
+8564f5aab476c38781bd01240031dcbad5f3ea380bd1da2a57d5833a2804
+f3385741d1062fbec7f2dcb99029f671e73d200cde3c6c22e56be77ad640
+e00e418ba9c5b55f32033e77132d1a3f105050d4ece20e315042ec670355
+52a327e5d2134355b65872fc7043d796e4552c360adeecd58ffce6ebc142
+6d3604163e8736d658b52d0eb31f61e7da24ce6083494e103b0138084258
+1f745984d95cdb80a5b318651f0d969e88b6a192d8fb6833c8edc1721346
+512e30dd5638d4bfa4cc6d6ae59546d32261fb0da92490c81f486af1222f
+b5b8a8beff009a7533be98aee67c751502e811e6d80ace82316e10872ec0
+38f3ba8db28844e6226bf76fb4dd1d533e32dd98afad08686ed7ac5f22d2
+3ac3efc4ca3c8807963329d4c5e5445e483b31feb1b665e81efa14e50016
+cf6ad2c9902bbb09c1169cc0987c8965e17ffda6ef44209c580e87e21435
+9ff2f1658f602c21469e861fa93a6922fb81173edc3087d967c29861b5ac
+4b8bf09a80a39a719bbbef195833a535b795155d31d2c514ef77b63fafea
+0d3e65fd3d036d347f9b131644172d1d05b14b58e0a3d05e1eb3c63cb59c
+9921465766ab68033fd268c305a484cf5ec0fc57ab818734b6facc6c5377
+6a27e1eaabdf22bc862fefae9a5ad864afcb2e1025b92e42b8f7fc360fdc
+84384a5b85e5d3dcb8bb5a8c0a71aef443fabe70f61f25485dce3b5d1309
+5f83463dfed9d1e6f076ea41f6458415d65fa5f1fc7e10e71bc5538050b4
+1fe27d3fc52a0111ff111cbea421a963cb8913b53cc9e2e9f5f6a1202b0b
+1ffebe8afd7c8e3805c631028e15a3bce7227c6e2f554fb6d82db30455d5
+74ec84fdbd4e589ec093e7a9f2687a30a0709da926aa83660e19ac331029
+3b93b6b7614d7c8b941435268bf88d7daa8f413cfaa4bcdade3b06e0a4af
+b63e66cdbfce3fff5da6668c7c4b8c09f36470315f9fbd6c41917b4beffe
+85c2fe8789c26cf07eae1eb5f51213ec4188a4298d6a7eca9dbdb35334ee
+727a393e779392106de99423bfa78eaedaff42e719ef1e430015dc4aed0f
+66db1bc722d1ce5022ed01ec6160b9c6a1e059006a634cf1c81738aa735b
+1b8adf3b53f0381c921d3e1db16797d935a90d7100dad04932134098cfbe
+f607d493b1c2858f4bbfd59fd711861e7fc8d3c39275137209e878b54927
+eb538fbc1b7570d94ec72a417c7c93b97e64ffa489feaa8e448f60bd7198
+eb87700c55af20c26b30b74117948d3a2c8e63f551dfa1597e1151fd036b
+450ed365dceb627a8276ae186b63cdfdc9bfeecfab49e24cfcc88e336f28
+7209ad7c19ed66735525382582d34a1c427fcac42eea2e2bb2bca3b889f2
+f94c17889af17b8527fa8c98db89a62ffbd0e7d74af803672ef0ac1a4f8a
+b730dfaa7e39279dbea0b7eb15943309dacf9ae8d7ea5530bf423e8b09ba
+f591b7fcb0bf32be49fce97cf65278b3a078e693ab4009e8991edd66df5f
+6517d1cb896c23c958260268b7a10343744c83361a7d4c0f58d2a3b147f8
+6aa96105b68a2a68fb84750acd807efc2b43e75aaf3f69110f4007f0dad9
+be64c51774a90e76f59f7ba21c4e213b9e036e8fd95b7149ede827c895a7
+c935d004aeaa657d8e89808b943517aae13b98b7fa25bb2c050b2bf3d2aa
+94d03660870ebc3313df28b019dc87a834aff78dd233d329b6307abde48f
+7b33136591af9fdc1526a3b290c074701a93fd4e2d23e80c25452a46844f
+6751b18e383c69be5182a1ca0b1829d491b2ff2763ff8bd8c219a9b40550
+f83e3c7e657b622df0b55c12fd92c6966db54cc7ce9872d381d9f3337161
+eb3ef659164d2db7b3c0ae5c1b8fbb5c6f325873c3469c42ea7849ddb54a
+b86da499e3870699a349ba1f2a882bbdec2a2defebd80a91e20f580c355f
+99d2c1c17657b2210507a615026b58eb1159468bbac06bacd1840b3e9e4a
+2fedbd3db9b3da6aa5935857c2f35a8a07f89934f03f1ac4179bdf2deaca
+cd37dd60596890d56ac5de35d346f05ccbeb01af776f6c6b78c7ffea773d
+9fb02638a27a1572e88506627bdf29461b4ea9757d3dc4b4881c23afdae1
+b3e6ea7890e5791a05ac9be14bfe5031a5e7759fe0a77a2c433c5f4abd2d
+6dd24c455a61ba4bbdbfb879954c301c87cb83a65571abb4ed0d12b38247
+a122e6ed2529a3e9f303cc50334ff66633913474ef5b3944f431727817c3
+3f99961c8fae4a9fad6f7fcea2ca3dcd7ff630e1dd1a2b1b2e7702d45b90
+022e3b986f8ac02ae7337d881aae3b5ed5ff6589982c0376f7e0184e2677
+6f4910f5764a9e87c0a011c4826884b733a7c94081502fd642f9d01ef2f0
+d13b8c3202b0c65017dc52c6bb896a2d5d6a6eb7186595395c1761fba3ba
+78533adde3cc35cbc61f5e3049235872217f858600c7d9dc5446689e2fdc
+4bc18bae0dc69a6b9538899a72eb972da71bcf204be2a1bd4f3b41ff4e88
+0a474e78b3cd9787255ed129ff5fdb1971bde1a628f3d0031c9c07729465
+3a805069b0737c56f13cad9a7712c5a89c08364ea2a7ec47459f01eb1e79
+b1ebaedf65b74d2f04112943e925c77353b85bf4284d44f9e035f98eb381
+04de862cdb67588bdc7a01ed46e3b4021a365c143eb8f2a289ea8cb86c26
+0e2b68079858cd80d7d01062c777cc5509102ca78f35a14b371228d9f3be
+79c260bb444bf12f229e6d734f455f4777d344c4adf4e3bea74b3fabbef4
+ff6f50810c9ba2cc4ceb642045c50475e0519dca6f80dbaa84bb3d52993b
+7c64eda507d3fa96233782b7460616fc479bcc66f1fa45da506e6841734c
+04197afdf22e4948fbe46321f240aa99c9567b623edef4001964022942a1
+04a3ed4ded4b0752ce877d4132970adadf6a3707e5e999eb9083731ed70a
+4c4d3ca516e1f2a2cc21e7a3335bea3f2998598776ca3cab0c495a595f08
+b14d6d047088271a42de0cd894fa2ef40321e655fa94934d56dea79fb009
+e18011e64f0d712b853c13061d9bf18d2449102dd6b76d026cb41bf188a4
+48d758c8d61111ecc664a1577c90baeef21970e1f796ec34ba758968c061
+f4d3a0f4c6f2967f33e6ad2c296293beeeeb78244c37be4924f888806dd8
+a2623e7afeae2b3f3b7fb25c2ca5f9dba9f6847f21a5d2350e09ea9fcf3a
+7b3471c70f0bba2f4ce96afe288670d8876188aee1c0b9477f645b3d4d9e
+f81fab33af3f6cd10bbe7949a51efcb189f8d7bdfd18cb0ff37f5295f617
+bd21422c088ebe9ae34859728bf8e2260f0556ff6cf266be35330bf2183a
+46b0f2e02be6735260fd8e32994bc9ebb66da8172178c0a5d2a46ebf81d5
+33dc0e8d85f9da009d9cebe0e5123c5943e805ba8ca03feab7eb753933aa
+dd88df02b74e0c3eb9b3c2b4cd0178998350c87afa4f8bf9b1d4c88f1446
+f3bd28b7f7e6a123536504746ecde5360c6eac798c6b8effb282a930806e
+559e5c6147f75b3a9bfb6f80dd672076f99d8ebb064801196dc13c837fe2
+506d523fdbe6871cf3cd286f553c6432bba9a1e6915cc4857a5e499c3157
+e8532ebb1b3f605ae39e52e47e8d2d72aded3475a22d612111212bae39e5
+e53c53294115cb01446379d9c65efc4e9751d2510df8a8f5d05999d321ae
+cdf6a8f0c6bef3adf0a5f07ecc76a07c5a3e3743b2c29656f8622bf507fd
+994d1a2cbf0b6252a1676802e41aac858fc8c05f3b0f9bd7f5659daf2635
+bc654f2d4ec5840476df5bbe92c94f6dfe01b053817bd11e98293c1d82d4
+2618ff76b7d7477cf44a55a05e6267c780288497538773c45e7c005465be
+3706cfeda1a768e34b16529130151c81c21cb79b5ca2613118dc99801056
+fb20ddfb772af8f6c058d291bb60d1bf0e24f1090cfe102dbcfcdf3ebe9c
+2be95830bc74254fb33c5ee961173d7f192c77e9f3cf560a6acfae216537
+8f8ec20794bc2fe89be5fd2cc4cb7bc64b180e316d6c7a8aec02cd3ba489
+ea1bc7290d443f2017db5c9f56d3c01f60aac361dfbb21391d4631e1ce7d
+caaf8b7147424d2e280401552eb8d28ea29a2e3ae8d497899b0a9ab07572
+8943e310b6f119f7f4745fbf157679fcafeca4b489b2c989169572d9eea4
+ea4a268ad55c09e5f935e581fb3c3bdf7a19cbca4e31c2f11c7f94041c17
+20f4afaeb34297d0d443ea15f45047d428e170be83e949a747f2b0eb1114
+adfe5816e4c6dce2e15fa5c04cbfc35eefb2ff31e7e8249a68dc182bea5c
+38d94cc14d4fba937bf7dd6d0d7e97e886dab9cabc1065152f0eea63490d
+8ff3fceded7c66b94b432164faceecd537e8dd7d764f9c723300f677cbf9
+62f512e0c2bd926aedceced203219b44c6a33eb81f68a80874692f0ba475
+e151735c02f37c7f827b7c18a50f403c60b26ba07598a2340079ec79870f
+dcf1d0a10f95b4917ae9ba414fbba00dd561fff7e3669a840d5637a670b9
+c7603f950be19410da99280f836d316578627ed4060e8aad11975142bc93
+1efbb553216411d2a3ee089e0435d256cf6c27134f97426be3fd8a6ae9a0
+b7b6b7d660e4bdbe8baf5ea8d81f4249f03fa53a4ad8c49fa79a5c346f6d
+73384af34d6ba5733650794b840bbc12c2d1e693e6a2de9ff5b317468381
+44bdac7ecb57847f26c1807beea229a7ef033292df577c4fa8df7125c95f
+beb9d3c9a67a95ea90f975a93ccff6684a4076367d6df13f403673c13098
+ef55e1c5957349548ce21775c7428dd33904ffc4aae249cb65c05c2ac6fe
+643fb75a2f4aa279392013513a6a908ed6bc2bb5c56a38a69a5a5a0aa07e
+84ae5895a20adda2ca292145d12ed42648092f9d7e79ee6cec978e1a3548
+5ef3222e3e9dd4f9c24d0fa75189308ad03819b4252840afd44e87e4f457
+fc7b8ef67cad28c1242bebe3760b5a90e3752ed20fa3b447e577d6b2c490
+eb76f5b357c0a6181208a8f99549a2809b7c4ffe37e229e3e01d5e7bd67c
+6f82114fa9436a79bf0d3d6fb88f272792670b0f6b22d14c5f2193d9ed7f
+12f6f1c7f336f597d2f10b5941635350ee6b462353c2f211d01810491556
+dae168530350e99421b509105a6e550bcf9e2843605b95a89c93ab24b9d9
+b7ed3a9965b6fca21ab95c560b02e763202f7c55461419984edb144d0ebb
+ef6436aaa3c68959b0869b58e5bcbc54436c238ac93aaf882e5bc014e03f
+5eaeb671ac3cc090ebcbfb2aac69186cf36746f535736a2c8bd703aabb7a
+b8c9df63d73191b98ee4279473dca298c41a6f67983ef91b2e56ef59b933
+59d405b42f5a30ac8117cf7be52f01022137441efa08549bcadb2efb90ad
+4ccd93a6022a8424a86ed4a48c213326737bd968e627f6f8a8e806676bfc
+d6a6517e623b84204a5d8dfa46eae6abe89870ff3bb19c6452ffa3a5abd0
+e0cd418ffd2ff221827bd313d753a63434ea1bf9822aa9d7f2e839e9a0de
+bbeaadd3a4ea4746dcb2814b98a52fa00db4c1c71bd7687049b5faeaf564
+9507c2303513f1b3a6f4f7de783bccf85aea628b1afd8f473076e95195d1
+e8af64a05d05a661e2b2f77779144905a2c5601df0eef0c8812b8d9a5165
+489396ac9de54d715250a3acceff5659b1f51ad7a7239d9a8bc7631a35df
+244e9cf1a3d080de8fdf09052dafb200b907e8da5bb2404efab14e5d3500
+7710f369d3dce9654d0332bb19a5bc9bcf10c2ae8a12d97831bfd0c06881
+bef8cac8a9bdeb42a264593254ad8d72fa97f189901a857830cf52cf137f
+cb6d46b9b934b98e52a251b029422ddaeee26aaa89a57e3bc0c40e95bcdc
+9d9aa36a34805520a647a1dd5de148d7d50dc9ead70d923c9c78db90f8ba
+02d68c3cec9f5fd771c33140b93b82ec063c8da7d96444beb4fd1f9438c0
+0b1c747d8833dd0a1e12fe2036bf38b4aea8f8708bd3e3e289425abbe7a6
+ce0a9b3a4eb6d6cf021a03a40b32a6fb27f714ab28b1a8d0a7be38e3585c
+fbdf46ac0906b0656599998331baeb24e94effc3d56b37a6f33695c847b4
+5eae4abe907128987e7bc61c9c2cbc35b8edb6c4d00004d36dd05fe001fe
+25a044bb325117ffcd3ae307684029c29ed0ceda734d1b9685da4cda79c5
+53eefb7e26d3e31caa1b815e31d0718b190be691abff96c3c89ad3ab8669
+a6912149e59eeb566ec95113895f17d5ae021e1ee285d0c49e054153944e
+63e019fbbb0863dace341b53cd5b976f7b61ed082f6423dcb631494d2e6d
+4685bcea79f5dcd4db9e4e323c4badc4fab74487d059351b7f301e8c0cea
+9163871789ef9c71d2366f65ee95a84efc738faecfd1f72bff12abfa9f51
+afa6e0b40d6c70005e60aaf92a68ec136c4169f429c705d51aa86c841fa6
+8a4c44e92bceb6605732d355dc995d5a9ee4c078c0bbf80de0351af8ba35
+0d24c5191cd1094a7399cb946132469c3034c6b125c8edd52f8fd240a5a1
+4e945431a1b8505b9436e2e07f19e2be43b6a7eb616dbaf95a7335778a47
+9b2e659e623bc0b6db8f4abb16f269cf3550de6ba58f2be5c3e9cda1387f
+0afb3a1f52330675440c89e329b3253a143c4bf1fe2485b5e402b2c11ece
+38ae8987c19facbd48b9209e3781fb2cc48b0fbb3e5b38c73910d8c945b0
+59c36e26211956e67659bc13ac100ae8bfbc297a8c4c8985fb5fb4227237
+52856e39d5713557e4eb3f14c5e15f822d2204ef14a91c6ab8136c6ccbf9
+04beab720daaac5775a4ad27362986eb78d995b7eb70913519f0b0d29591
+624f159285880ca18b183240410cbd0e9a293f2220c6ffc289668ca820cc
+6e3f8c6e24c437280e067379bebb7dcd7bfee73a804de04866c102488a72
+1dc5c19f64c17b1ba6f543fd024a2bddf2b43d27185b7355ece2fa7b9f36
+7d5d56cf40e8c861039b7026b465d40ac264bdf4d43bb59e451a152f0219
+80df72ac89ca53fff8dd2a7849877bd8ff0ed654254ce9037925d3c0747d
+23dedef33f9510a6730c9537503a4612c76b36698e4bb1297a3ff72caa98
+7bfd0fb801544fa5b04753780faeea75a567ea18098f2ae84f226220df46
+42a70b6f0557772d7ba1f13bef7ce9d9c1f3254f373ba0fcfc44c0063fcf
+f3c2d7b48b1cdded8f78a1ec7c06695ce889670b6921f98d986547fb75ff
+3fafbe090a2d33c41a1f5fecdd2c21e5ef808d7cd4a7195b7715766521c0
+0815f524e75d1b554816fada08b6c246d1b66cdec4bf1909d40d48d5a25b
+0b1615523fbac1eec49f404dd72247b2c07cefb405faaa273973e8714b13
+ae5e763d62d077f15fbb15030d7b4062275335987bc5ed9bce2473baacc9
+fe39ea65d5a7ff0e3767123c69238eaf663975233dd6e9845ccbf2df9399
+285c8dea6175f2215257f0022403092ba7dbccfbd2c2da8778f3833952b5
+9d2019d11b63c7fb0d1344ff0c5b8e8a55636399f3611b062e803e39af3b
+4a6a369569b9d8757fd054cc0d6b62ee29cd6cf2fcbc6a8d57a2f9c6a504
+bab41004df5292dafaec65a2861b432dc41a368136117b746553777f1fa0
+f7b2e3faf253a0bf40d392b4e046cf697abf4d8b3268e4f2648439ade9d2
+e45524f3c0e052076bf35400cbdd16e70f88239dea74cd27633275ccede4
+9c6b7c237fb7bd201b3dfa9b7794555961414d80fd5c32032a3310b6b32d
+46a6e744934f9d680c5ffd81f331991d1c997eb3e4ce241916174da8bfb5
+06b0ff918c6117576a6fcdf4bd9dd90c9b5273331c5bf07e5897e9f02aa3
+296cc05cf47e48b55886b8826f2822140cc84f54b8b9d6477d9893ee74fe
+73e39297bf414e0179bdb25166e8836d49b2add6274aff33c82361197968
+fdfacca49b85772de9a148e017a8ffc62a38a30be5850513071727f3ba34
+dd644ce08bf3fd2a550809730a5c3591d60c3b0e3ed24eaf57817d4c84a4
+66c5f03794e6aeb3e1846ab2e93a5dcc3ef835664ae013464937451180ab
+b91d54cc81967cf85ee6b9d75c14a77f737fa6b414ed667fcaba82ded665
+3b8d6649cfe57b4672c44e0f0bfe5ad630c48ccf549b7cd2deae9c5527d0
+4783ec5319bb9ef7d750d87ba3c6b9b819545ca242d41f76fcd3df2f8842
+fa5714aff9e5139bd2908a003d5c0e6263a2bbe4105c510087db0ecd7c4b
+57cc3af64dbaaac5de21bcab8a58003225efe67be7f9a6709eee25d359fc
+1aebc969130f3050c0ebb6d8b74859ad54865f400863d769e91db9edeb43
+8525a7c7caa68b0d198475a449f5f87b5ebb495ebbd0dce87bbf35408679
+302b4dc66d893f4b4158e1b53054ab9b197c6ecb07792ba9c8c5b9c900af
+c5a05cc9c31b5078427a1c7d74449b9eb8617b3f0098eff3c586744dbd27
+5a117d0aa14a042c51b7506130de59694db9e45d48f39a31411b656512a3
+2d3cd96686806a73ca7f46dcf9a4872c0334c89ffc2948a2bd98bb2f003a
+85834c049877a4729f3cf001b1385814a17baf20a0ef75708ddf0f4b656d
+4122e30d794da048d83b201a252c92c8c92809cc3027150ad65ecc94cb14
+69c5db56965a42b367ca27015b161acb2318686bc3451e03a299f67de0ad
+bde7f33807213565cfaab7a5ad04a442fd3cb710a6d4b78a62c318815ff2
+d9e14b9357e8bbd13faabe9d9ea43c0c39bf4976ff03d1573b1571e3013c
+fed9bfaa0c42017ecf25d7c12d70410e7a0d79e37d5d505d11da9696e2b1
+13019e10355aff4967c56ea86d4362a89b42cc01f3abf0dea5f029ef0c2f
+d3f33bfd58e31a652040ac6179585f9bb03e0bf8f1e94da93240f5637fa6
+21687bb4b7edc3a2f5f89fd1434412333aa9b97bd0c1d362285ab643f426
+f75dd854f116a0d8bbdcdb80ce513cc45650945b546f72ca69dd9d2707eb
+7b5bdd9501febac3c4476852a1d21d6cec9a25e4d1671dcdbbb67b6fb02a
+78daabb55f140eec157eb91075e1f5cfbc2aa8d8d3fe990f47429bc573b6
+52d0da673909f36bf15852a7ffd991d927e99a6c956f33408a8f5edc6d7b
+200ef63dceb2cfb8da9475d34528238f4d5a7aacb905e6a769662a31ddad
+4e75795f11f3332bee039bea7eb9a9295a93e8f05a0978d88173c2f48a7a
+403daaf47c0444ac49e3544a2aa319176d51911b49da0c034f3e9c3384f9
+063d449eadde60491ed22c3bb5c0bac31fc564bb75cf75597c977bd9abf9
+05993bdec686728b1c3bce5d0f6302b3e034e556e43fbe1851b2d137cf73
+8a277fc4ce3f289c1b6aca82f97401eac80ea9a7682cdc9a588ab100c844
+8b60ac0b360f1af03ab5525536c34351dc7d1169193e71fa12892ee79a9e
+41552f5deee05e9b714587288852de794d16c571a4d61c2a41dfb1c5e0c0
+e6e2e9dc4ec7927fb76b52ec0bd581f6982969c8dd2400377428fc757010
+ad039cc3c917421a7e20d261034b9f86c69723e9823a2648d648879e13ba
+aa98bc59e45180ecd907804c0132b14f5a90705869a8c3b06b1a60303836
+4029f3801ef74c8f798f712beb2aeb55a917e4e15907e16070a0f9b52928
+92a05082b8cc5a51aacb34e227fa8b389c08245bda3f03570f04c1a06462
+4c8929938e966bcd981c11f70509bc65be7d3d1825a918a73c9c3479cd93
+24cc604e0b38bdd77beb802d4fe0c6c75dc1494f6816dd520f295c1a23d0
+0c8ec16e45d9d3aa9e5b6c138b7669be34f62b7250fb016034fc3d459fac
+491bb407501f99ff6915f17ba0587f17d19f05e4011a8260c6d9ea10cfe8
+4db4cdac6f5cb8f8a8c19d71a8b51c803fecaa5e78d0900e717e6db0f16d
+b5e3fd766b221033d64c4695127399ca9e5559374bbe717c772746ff02be
+0d9cda0216a202489aa5872d200e9c96a70c6f3709264c4047847a606353
+fc3eab0995cbe4dc9209cd53d2f869e8fb49952d2507c28d978a444848cf
+7d40200e56a1dd0eca3dd2cd861ab8029e8fed1e2ea8a4b457514a0c118c
+6c64b3ffdeafd9fa3fbf92dc132dc4acb1dd082ed5ef10e1c85bd4601a3e
+f2a6b5083ded55f5d9d2c575d0eba89700b4806dbcc6e5d2a2ad26c72cb5
+502eaf92ce02eb0769b552f7b372edc1d14ebc12545545d55e1be0cace86
+0ea950c891f47a066e334fda3afa5fcce5cb58a121c70a646e8fcf3b6b3d
+2bddbd3bb137ab4b1b3056343439432df4aa089b70b47511cfec8ff6bc3e
+97b320f8bee6fb49981dd5b411207ee7f4bcaa5d17e9ae30fb79ca887c04
+20c8024cb1445137e243d42fcbfea96f6259ddd05d335b390ed2580dc82d
+0abaee5e669d537e766e7ec16c512a8b47aae6380d8994c87d00dfed9f5d
+85232a84e3d3cb3ea5b307c16cbb2f962effa16cae18a2b6f8b1ef0420e0
+4b1e8658f368b7d94d949aea27aca6ad429007363ce870cde7573dcab8e9
+813ddb3181634525744118220890a4c17249ce7ae314a9adcde389949f14
+64976b4a819e87b7588aaaf4ee1a501c03a1c7e928c3b4401ebeb2eb5ec5
+b65d06d61c11831a50e59124ee7fda18fc49cafa2ae407af526d1a94a305
+96e5aa91e7991ef4c05cb0ff348e86942c706cfcd879b527c8e5f00ccd36
+20f2e1118317172c0ef4cda072faf995d0d8db0b835cc9df1921fa42bcd2
+613d38b149a9ffc4514e727b453c7c8dedecf45e1e6c15b7f2d5e841b28e
+73e6298ed645aa91337a07021879c9c3c80618372242f0c6d4206e57fcb6
+0e426dacc9ebe8319ccdc3a6ab7d074b85fbfaa94b2135790ae82fb3a489
+3b44f2414e3f9f3da85a8308417f197b92810c2d6c80b2fb8d725a69a5df
+6e197cd82a77dfac7d82ed903a49e81d27e6256a726858a6f47eeffcac83
+aed170e22059c41aae419c1397430677b1e38d4d10ea1d73d59b836dc1a0
+32f5ff3c5fcb37b151ca33de6fedb9b6732470965ec19547e1cf2a717a1d
+858a0c6ff05a74fcc9b512e4f504e9de2bda922a254ed810b0ca0a352c3e
+6db3e08ec0afd82391697f3818bd50a9cc03aa1ad62a9ddbe42f5ab7f4bc
+c14e5ef46a23750f8b09959c0b4afdd79f7bfd8f9ba0dde92ae631ac520c
+676454657047ed18a0723244e9aacf6394c7d1dfe20c52efded832b1aae4
+dd0215271fc46ef5b90de2514fb118396a7a6069bb49b95bb240616d4115
+9be72b5fb37d4f2037c39a4163180379e5e91adc987003b0a1cd676ccb8c
+f6e44f523c3b74d543d55eb3cc465463440720be08ee3f85a60b9398673d
+7e4900c4583979887c6e22d3f27c0db0359a7305b5465274d09f7bcb3b7b
+04893b2c9cb576e8e570b49efc409ce5054548ffb1b19dd3098029958360
+b0d936b7b107ce046648ba437befa9bef67b8cbddecb82cd9c4b1bcdc7fc
+6af26075f3cb2924dfacf5f1c4160d1f96f2d7592b57edb1cad20ef93953
+71d6aac1791e98bf4bc84bfd81b92a5c2b40dbfee3d50ee9269df632a68c
+9f6ef75d69939e764a1b4f527e4993097a1bf28c6e5690ab9e32c73b29d0
+275e10f9559ba7f96bf7c701694ce13133e6fba2276c125b83f43a84cf3e
+8aba4a86b180f66842267e70f5c794303689962ae067290e2cf87e3fdd77
+4ed173f91fa1fbb0f6eba3ef1a34e826604961d2cb47b40b260d79b9b2fd
+1de584ea79329dc8ec75e84dbcd90b888c59e8f7e5e90f4e2cf7ad8cc5d6
+ac6a42bb0aba27236ee4d68e994a1fa5e5ec15a55c15b0306297a637d669
+6e1933d8c0e9c4e81a4625f427aa47b7e8553b580a45c1685e60267e563e
+9a3785a9c16e32dfa66a55ffccc8ebce3956c1e9778b64258e09695fae08
+6b493e3d2fcc4cf6904e2ab22b4ba631c50527a56801737bfcd881bf0499
+1b7677662f0bc6709b981e6dd9dfa90cd3672ea00e00bf2649163c3d20c6
+baeaf3fa2cf56cdc5ecc24628936bdc5a30910cee7afb97edd4f1a38fab7
+fa3a5cad31bbb821ea103b67f99d0b74d7c157a351144b9d755b36e250fd
+a96d686bf4d69d7b6fd6bf5808f715fc393de15b86a6e4b1e878ad83115e
+90eda05354fc1cbc1734a024607c081fc229ad35770030d77dd164c8e255
+3e9745ed40d9bce5427536793af013665a394cf966f2535713ed2c4a3ff8
+16f50c2bc9c9dcbfe53223d06a009268da596bf894ce9580ef23f4eee7db
+887770709f7ea8909ef744ba0ea85267e62573dba51c25f77528870ad317
+f1ed63b2802fc54d81d149a2121762dcca760e5ea5e7ac32a1d48191d63c
+bf1e049b78dfa7bb2b2237a9d52f714859f5ea6c92d44c17b64efd507e2c
+9820575ca9ba46026fbcc25efbca849abc4a9c385520e5d7d64a787dfd23
+229bfaca0785aa219f310d6f0210e4aafd5f75033ed560f123964476972b
+db2a8087df61d0ff47fef572009a81809c7021d62dba53f6b6a26b976d53
+94eff109b3af588cf8deb44bb00763526423d8077836d5e3bce10378ce95
+cf14d8732ccab691ddd13f9a00d285f2d63fa8e7b16136b1a8edfb44a462
+254de6d3a5ec710b9184c2bf8b23eb1aadc2d40bcb53822dd29f4e5cb045
+3e863c11aa73e1bbfc28e336bdb59ce3e88065ea9d8b79991461bc3a0d5c
+97febab06079f7a1defb82bca12f28329c063ab726ab7c6a2dacdac6e1da
+46e58285015695a4b206d9e0a4df7093033a9e42dd097c6ac0ad87fdf42b
+8d453936731448ddd3870a490cd48fce942bae6a88cc0f8525788e222239
+a38476946060a8feb6959613b28a01090293a9f5895f7b509985e3643ee4
+7752ebad364d54437ef2ce6c3fe86a4d2be12812577b126df132cc7d602d
+c5ec6ceed3041af208b69b7e98ccad48b2e6d99ab607bbb33a19ea0ad941
+6b31e145d3939e04e9b4afbcc2504c82d879dee54455c0f5d01c028d4648
+bd3d3b9cd2036537764102007df035a9ed9660123faeda255a7385adab5f
+13e3fdc490503d9b631c537f1c4447a4fd4fe3f1cbb242705431a9858a0c
+60fa8a836c307497698053cd8c62f21aad03ab06aca920bcad87f68afc45
+39f39d9d6759b7c04e15ede59bbcc04f528a277a927152ec89409192f2e5
+26f79921a4e76fece2373f3375c3c0a36ae1d6f3bd1b70586ab9461f65df
+c1c5654b5b5aec5f92d6387a11bb28b81d2366fe463a5ea0f8198a1fd8df
+e0889a281e1016d72188023de9c0244764e480b801f83381360bff7a3509
+5609a6e61174b0274c2b7293509f9c4e4eec290e2c538c02adb877c8b21f
+62c070f58cea8bb436d3b34706de6a6fe8dae931caafba634aca1948da44
+c2cef4d8be6b194d3c41d0c584c82f6f48c67ddeac49b17a692ec941895a
+c203310de514f325c7e70d6e1048ffd7f31682da946fcbaa2f5a50535f0a
+ff3dc0eedf67fdf9898e759b929b447593edc1fb8c5b77062e19bfbf2fb6
+c4b8b7d695e24cf6470608ab635002afc38d755592a0c723730a042ac5dc
+4b74436dbf5eb8dac79ea9e6b7f21ed831f33b6b8c3141c98134e2a69af8
+fc7572bc08aa0ebe9deb04ee9aa794d2afb9bc0e97c60f93a7a72d15556d
+36ca0b58c60fc42b6adca84658447da164fb558ae1c856f4c3aa6fd30c26
+7ee9a8668426a3d742e6b8e130c523e1d8340ccd3d3f741be49ce3935b24
+aa20443b6049d0b136a36c1f13176048d69d4150af8cefd458fa78a2859a
+8a2f7c58bdbb92191a7dfc1a3cedc12ff91b26b6828d38784a5f829973e9
+d103739a1d8cb4366edc151e396c415fa51c740e0d81c18eca84798f80b3
+5344f2c5c7dbda319d6d50821f236d1d678930cfa18259a97496df61ae7e
+ab1c06abe785cd887259a7f08e79915ff96cd781d91435f5b5e4da140c2c
+6c0136dca6c57c7df01f9e87fbb0edf55f80dce3a544b7992800d8966f07
+e1297af93114a9efa7eb21baf2583055770eff67b5d21f64c5c2a11b4147
+9e314762bd6409dc5a73a8b32664b55691a01bde6f95d5f1c1065c81b129
+45e5b63d7e845b3ac1f16f760345f886eaf7b091c4c56cf0d0c2a9360f7c
+4e546630b93a2aaad80b4ca35d46350095286ef840123cec13dc12e0648b
+69d17a43aefe796a02dfe7de3eb520b5e247af46f31ee8507deb1774ab72
+81a32bd0fd6e6439fee6e94a49a8567e68d3156cb34212ea86b6e97f2866
+4dadacf5173e64c7d39237d0744b315fab7b6b85a6a2955a8f45ebffbd87
+9bda5f7cb3285c7241500278ed4574e464adb3d3f07f5a63560873aba6e7
+f9f3f5afc580d06fe0254bcea4da8af4dfad93b9225d636b0cad7a4466d3
+0e6c378b5d2e15e54a0d2686f971b8a3a04bd412ea4d59784bf73b7b8215
+7e398056a48fd391677420dd5c85c3aed14709871fa319b5677889022e1b
+3b9e27172dee5df9aa604c98307c576e292bbd17836bef068be34136538e
+a77ad4a000894fd8251e9950fcc41b70c2be9368150056bcd41badb91d89
+4da2f98d599bf224120fc5a57028c8dd55148c788a24f8feb19da237fca4
+93a9a0e313e37bae205a00829c9f7d0b790369f6cf5b1c54f4efe3917851
+e9f67a29dd264d2ba0b1bdb05de9c6894b30cf8d5b2d37a960b24b14ac52
+e93421da5d3f2e4484d870f333ce9544a9f578edee46de93125bd65e0584
+3d475c64b2fc036c699eecd9a1b54b5ca8c37c02365dfe7afe918204f6e4
+09d24ef92e8af22d1325f84bd31716add00d5323d34da177b1dd377b77a5
+0a08d86f13000039ba4e1501edab6ddb0073ba7843e22f49f93c80bb7d7e
+09a12c0e9c2af050fa39a83ecf87e60672257a62af6f3686aa17b0f246fc
+f1a109cc2f7a2a74ecd62849c741d45d92beb3864b6377f648585a7292f2
+98cc3c44b5755dd907e1c3a12f6c152926d30455c3c74e1501eda8e5c295
+7c64c587108f18db3ecc698a96f4c839edc7495f50b3244c59ed2a313509
+e26132ec29067092c12578715104dff4cc0e30ec1da6c13961b9f8b68a88
+65fcab289d5cba904d8891aa7fec7bd57cb4183cef55ad7cbda701d2cf0a
+3878c52a77e1e22cfcb4bf8ff5e3e0833f4dde59f2e8a6dc5eb9b625f05a
+6575445cf98267e442061d2ad99b52cc789d1d8f6988433c5c0d1d4b4f51
+0f8c73f6bba8e929362ebf38d26c9be8aecaec33f268e2725d3f51cd327c
+48d2abc52e265be63a2a2fc87454ae42003eb5a28d6ca5da2d7e8abbb9e8
+439b683e8e631f2e6da1f4b85c04d8bbb1730f2caa091f1b1eef31e08fa4
+df9a9b9eb8c6421cd5bcc0f6ded67fd19617213a80d18024ab79f408f7cf
+e3684483819c85a061c53b4fe853e382a3a7778fa471a196f24e124b1436
+29926a24620037e5f73ee2930195e2ecf4ecd53461b5b73c686578d48124
+c8878e0ae2cd2cb654cf98ea3d238dcb37ae7bc18bd0d21b323c959fe82a
+99842575f35bb6f286f5b3578413938ef1cdedf1469878f28d0f9ed53100
+c991598f7aeada761e896998a42b10fd186dd494e9ca575e984138469d98
+d4fab45dbd1ee3c2f61b877b9da3660aacd8774dba08bc31ae8e73cfbd3c
+fff34ac4047df0776d0db02306024adf7c9efe019128f2488d22883a4eff
+f3b5af9fc7552f70a78955d4854a32b3281ddda5dcf15f915b90bd584c40
+e7bfe27697ff9c6a9870d329a63a45d35b7d5c87060ca3960accae323beb
+e22f909f71d9ce8f4e59f87698954cc5468b9fa31eec9a1723665de649d4
+9d1f4d8e6b96c4bf83e02806d4d9bde12c1a598f801e2169afaef48cb6b8
+d5040f2be6901dc81c691776b45321a8959939a90b6099446e8cd50576fe
+da3c0809294c8cb309ea895075d2eef2a0f2b019e3f2e5941b5863004868
+d81b733cfffdff18b54df5ecb4d3230d0d82f091283ec5aa46c060541366
+3f46eced8a3e98334b9c2ab430f435f792176874df89f2f1675c5d350fa2
+1724a0d2f19a6b24f86f858d0af6934d8fb84016cfff258ba15935a2612d
+4fa06dc5579534c7193324b282a8f5a67a8c77eee35ecf2fc7005a3d8d5d
+6ed4a4e19d385848a8b95aa6454573815d0182f4c93a3face72d7c2c33ce
+e19499d1232adfb742e6212a6c93666bc1dac3a4275c1228ab98b9779850
+ea291edda7bbf14b5e2c68aa26f1b877920aff9ca30788348798b4423b39
+4fad935b35e3d5e71277ec32b142a386a96fece14fb96d3b31fb36b36440
+a71c2d83c5da38c9fedf38148f7cd58748bb2612be4b4895b02e8eb09a5b
+0e7548cde6c939ce8880eb89b19b3e26f354cb21ad2a31f8db6b49683fc7
+fd7850a81f4b801bb9f108688435a2b8ff617607c570defce9c4586abd5d
+a7cd2a81c93c9e53c3ecc79d637be3d0d9f8b0b08214af29b7c525c6415b
+89e0759c5c6389bf00d01e884d9ff86b1bd35ba5d679e80f93d259e88588
+c5ef5e81d89a29b4814ef4a54cb37750182f50662db8fbc27a03ffb3d0bc
+eba5cca63c454b12960451ce170828efeb66bc5397c2f0603472cf10a18f
+321a4a55eec51dd5a63a4de376ac65f858cbe20ad56395c7b1123cdaa942
+c558cf95faf70c57cbcc724aa11cb7f141e0db8cfb173d518f0da1bee461
+42a05de5108677f5b14dacb79782b2010bf7c5806dbdd67811cc136c0c0a
+f869d8dd9df0ece29b581c55c60339948e044da340cc704dd18f8884a6d3
+c851e6113d77742d6dc05365ddc5806b9beba531037aaeae23aff0b19737
+443e8105d57c2c246b09222b25926d5368e62728acb1b98ff51eb1fe6a13
+8e660361caf8f3074de12b7137db4819bca2b39409636c8ff8368c07cc46
+5451818e7e726f02c9dc803e1e53fa04de26cc59b24b5d86cd16a1ab7ea7
+303af8cbb2ad7ce30256052cd4c3b086446db5bd8677a6c8fdc13bfc7824
+23e9694c7a60501ade93a3c867a594c04cc0fb1626fde284b566ea1e4f6f
+7b79f4f22fe9c586d25d8b40c0a4147b7a2be24a83afa65f2adff816d656
+19052d81c9cc87be737233aa0916b9cc41736ea4630f4d10c0867aae059f
+22ecbc3868edd11f4cc97dc44581c52ef5a5879da40e356281bc0e1e72c0
+5e0f039a679f0c13955e6f577fb6e78c94810ebc9c75d9519a7868d474b3
+2d8a2c62d7e82630059325a9cd33d2ca35d0369bd45cd6f17d83c2c30172
+1bd3c9c34c68b0e709dfe50b428a4f051786ab64f707dd4e4d8a075e0657
+22d5b68e5e9095c5184cd7c01246cfc418f75914f0a01b088ffffadf85c8
+499cb1408f7396b0d94b0b5dfe84e9a619c55e87240a81af16ee893984fe
+331f15f597cd3c9415533f9b53563e478d8c6a159e428a806d33f4616ffd
+8103ad221a19845547097bd9f1b234c1fedcdcfa0d8ffec356130515c5c5
+11fe5c5ba8d25ff61e6368741cc466592cd920696e964cfc0bde1c5e0b1f
+bada15b871d8ee1ad94bc4a42cba6af0526a061d1535d8f3fb4cfcf249ad
+f9672e73a4af5ae352b191015de331dbff2a889839c40ea4d315813604f4
+4f6f51144d0014fb69fbc5d4d64d9486b7285d7533a746503920212f1ee2
+8b61b9b44f79e15dcc51fbfedcb91b9eab18bf942525df15e67644bd4d05
+29fe44333175ed909c06d6ec35280ff1354bdcfb509295ff3123e2a53108
+79760e6e7af5b0d6fd44c14f82ca4ca89fc41771745e1290ac86909dcd89
+4a360b9c549939522c7e54ab92d1cf0b5bdc4cf8e9c8b9fd49b5f246b6bb
+51fbb881eb6a1184b2383acfa9c8907dd73c8be9a200e555f674c73de70d
+9c171eb3a2133fc8058c1a44adf8b143acb43b394d142eed9fbea7b0cc3b
+e960e0384ef1dcf4094a22e0b3b4b73b88ec0e5183b2996fd906b9bf3d12
+a818c817b16afb99bf7c0de191eef8aeed90fa137fd2ab84dc9d27e49793
+5ec1be47d5b2555e98d1580687ff82cbf0b9b76fe073620ce33a2450095c
+e859a89e68a94d96fd9c8ae07bb9d0608a67c17dc15ca273c013c816150e
+ed83d03f502e7dbf208b7748117ad59b24187c60e4a44fac5c9d53ca11a2
+f5426d2e50372727c576042647485f3f06a779c11a398eb91440c74d8566
+54871042a976cd54f8f3e771ac35226a8bddb87884a1d73a888019e11845
+495d6f354e24af23a9cdafeeba7d517cafd89c7a3796eefc2076467e5b2e
+f4a244d269fad741b24b4ddea4d52374ae5655457fa30f4b8b1b22110a68
+bb9011f55edff5478382cfc3ff17c3e52a376be295d3547920127c96247c
+9c2d069ea9f10a41d206e45b228901d8ec47f261544c4bd1974692ec5195
+839a638de49102290fd09f831a1b5b6398ee8c2337b18ba47e29d3a228cc
+3cf1447df2de3160b2f2ea11ebd3430d44d176c13a5a876c6bf13765fb2f
+4aa9e7e0ad311a3a832e7d4ec3d04a154c04c50bdd7e08c329c0c682c566
+69fd704da7b4c4a56a50f50f60adc6a30f31542706f8092fdf406035167b
+dafef98111e39d3d8be13f057e44562c1b033115c8c4adcaba90b7f7265b
+7267952c5164e68a4434b7684178a1ae46e7bf10e344ab99799461abae9e
+3d4e424de0bd99a66cd3b0facf3c6948c00860f64dc81f71aee12245787a
+82e040f0fd0b5dd075475574f7a60d157cef30d0400ccdb5da27604a975c
+2db600d55acbd7c16e329d5c7c8d073d46723e29ef8248918331076ec458
+a85f98cbb0fc0a78630e99db7ab0f178c629bb726c511825cb722514ca36
+7dcdd067a731c8ed72324e5cf715a12602f6a49f921f0632175f615e1d93
+bb225684b50f39b26d65a0110e9ea45fab51763fb785e505942b4b0e0d8d
+e21356d58c5d87ef69457dd47944b34e4b29293cd535f7c25a762bf24233
+2f12955daa0b04af9b0f1ae4bbcb2d4abf16374038566d419e71d8b9d91a
+af8b2838c3f69d7802d91001837eea69be47f595f864ee03fe2270e05556
+680c719a0f33e24953f7bbe30d03c31f88125a888a9fc47406578c79dd69
+9a9e73aec17997374ec94e9f0147007806407df213edf9fae457f396e403
+9291c23e0a54e6d07c28652374a367404c3a8c50a74eaa4ceeaea98a05ec
+220003a80f3565ad05100a397c89dede629ba9af67cdf1608b08ba01f653
+44bd44b5d8a655e1fbd2521b0fac160bfb4628296c6f712d98efefd28cbe
+2631dc4d53bd915483586c9619c7a665ea243877b4d34c550d473a36f9c1
+ddaba89a7c727a2625f76cc3d8734efe913f04bf6a9aba435ab32ce26f21
+2499cb4c4e97da602b4b51c35b237f933ef51e091beacb8e0ac275b14339
+e13299374378ffb3a0f25691dd7f2beea5edb9bd152adc86d01fa3e9acee
+f2eec45bd016e255dc58df2a9c5cd64a07b4bc410b37a137210dcf214c30
+27d1876726567d9c50926ff4550391079a02c7b4087c1108c509d88f56df
+ce7ac59788ea14a42fc69419882a869c6254618843790f987143a6ba0060
+829739cbe213e30194f21d012dced304470847ed0c2b8f597f0fd570eb04
+41c3a15384309dd83f2eefd3d27609dd090c0557391a04bbf9110afdd00d
+d584bebbcb4250174d7503d8610beca0ae95aaba34a30abb7ecef68e1076
+6adac81a2814051b4f484478c66b39348436687670185f1717f84da062d4
+8fe0772c986713eec9fb5af2df8dda8dbd76aacb89821761f76f70bc34c9
+37766f16f00e5898ea1531e8b4b4ff65ea0189a8eab73a03089e205e791a
+65534ac99113f975ea5223b4388841e3
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/fonts/Courier-Oblique b/fonts/Courier-Oblique
new file mode 100644
index 000000000..2c02e5cac
--- /dev/null
+++ b/fonts/Courier-Oblique
@@ -0,0 +1,1448 @@
+%!PS-AdobeFont-1.0: Courier-Oblique 1.05
+%%CreationDate: Wed Dec 22 1999
+% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development
+% (URW)++,Copyright 1999 by (URW)++ Design & Development
+% See the file COPYING (GNU General Public License) for license conditions.
+% As a special exception, permission is granted to include this font
+% program in a Postscript or PDF file that consists of a document that
+% contains text to be displayed or printed using this font, regardless
+% of the conditions or license applying to the document itself.
+12 dict begin
+/FontInfo 10 dict dup begin
+/version (1.05) readonly def
+/Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file COPYING (GNU General Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def
+/Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def
+/FullName (Courier Oblique) readonly def
+/FamilyName (Courier) readonly def
+/Weight (Regular) readonly def
+/ItalicAngle -12.0 def
+/isFixedPitch false def
+/UnderlinePosition -100 def
+/UnderlineThickness 50 def
+end readonly def
+/FontName /Courier-Oblique def
+/PaintType 0 def
+/WMode 0 def
+/FontBBox {-61 -237 774 811} readonly def
+/FontType 1 def
+/FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def
+/Encoding StandardEncoding def
+/UniqueID 5020947 def
+currentdict end
+currentfile eexec
+e98d09d760a3c22cf119f9dc699a22c35b5b35ed6aa23593c76d54cabb5e
+942bf7d6dd84f1664b89699c74b472de9f8e6df925f6c4f204e9f1c639b4
+dba988ed2ac419ff2b2bde605b8ee3264edd66412d4f21c64ac522bdfc7c
+5502f9c3f3e5592b3b2093d33c9bfaedd2d49e89aabaa832e23f062e91a2
+5032519d1868816e44b4e0747795003d7930299d6e1e2a5bfe0d595dc97e
+140989ce81d8d7f852ff9cdc7a1b1b598c69131dee005b415805a16d8a12
+3e6a208511c6d0c255b9a5bb2fdedb4d399c6cf194ffac236883767c0f68
+f4ef84ee696b677de704ec3b097384f2e673a1f51692b7b260693738c211
+9f7d90ffdb21eb715fd5b8134fc87dba320ee54c2cec6a4d6bb350555eaf
+f2ec4f84365ccc0802dbb3bd0e3f0d9f858647dd637725c2caf9557fdf84
+2a0da6a0ca0f1b442ef8ee6cbf2b03858468a466ac5883cbbd3815b28334
+3b39205803c02c917d06825c09e2bb14609fa32c28d720c0e14a4b12d4f1
+25ff6281ff324da33a56fc49987ac7d3aa206540f8127273ffe9a3dacffe
+2b1c269d3db9a811578ac7d532c2efc18376f473fbb2b32ef642b19cdec1
+d6de83643723e3c6dfc87f97a7007b6081894bbc45c955b7001eb36211b2
+6ad7a3d07459cfb33f9c54a40a360cb802fd202c8e93d4db888b325ce246
+d02d1220abf55ce646dfb45f07cb848406e470362f80ce4c02d98dd84518
+9877732744cc16c7f5669f77ef096ea55aff98aa103eeaefb971731ebf37
+82e6ab725d4e9e35b2968689e8007c038cf25b6ae69451a4731e79ac22bd
+268f56942a233e52d71873e83e00a1874e04d3b22e72fb2d0671af81c698
+53c389b51f4a257373aebf4de2da1e4da5e2ca88941f81eae0e32d982064
+c8afdd7a9a600d56d73605b9463c6240606b3361baf22af74ef89ac804a5
+793bd512da2d13f4bb1b73efca1e621ed2a65d665aad0ad228b3b7e3d90d
+bdb6061e172b686e92355a7c7459d83199040a368b5697ddc3b81ddad341
+6ff4405e1096b1240edc18a0e9985ca55a0d697972bb11e9f1bc30765d67
+75bb68c69704be200eef4e11b78addb6229d8fa49a6b1525adadf17122c0
+fff51a08aa7aed158724ac4352ebb91ed0c157e24281bdc1fd610195f495
+e87062a8c38e0d046da4067ee16e81bc5f87e583315b973184e474064482
+9b2a52e0d37e249bab31988b906f891ac904d1bb8901f0673aece60acede
+97b8db7935c6488ade8dfd898027424aa85a11a3da494498b084133b8570
+17a6d507d70a3421235486eb3cf7613c59139fd4dcb92eadc60bb6225d9c
+d0599779217bdaf4813a453989b2e56903f4dbb83d83df4837c86bb4c3d3
+ccf98f07a23ebbf7ab5687c3e1e6792e40f92a7a466de352294064537505
+eef3f9c308c9eb94506db02cfae289f10005a6e42d2dce43731a7ae36856
+4b2983038dad6987f67062199018395bc0fcaf287a2b040c71f7325fa1e9
+a9808979b2fef19096b98b8a0a728eb98f2ba3d33b49e3c20be992822c7a
+1bcca5b4e4d1099d456d8d7d83c57ecba0ff21428024f7572a1470317cb8
+cbc8679a974e13d88c681338c68c9ac9557f97784f4e1c8c2e61f26023ac
+f46232cbbdf3c0bcc5583b935fe9fa09a562129a8927ae73988db0f7e733
+c6561ca7c9716dca9b88208a715166f2fae6d5eff289a9b2edce813403a4
+16f243f1b57eede7d81e10c2da4065a3082bc92a38b2457368eec9c3c172
+96cb09819e9e642d7365f9a6ef430fc7dd611ea5fdbdedfa72634ab599eb
+666a5dc178b0a0bd1fab042792115ef3b6222c1241dce36cb38b738f68b1
+b3cb489fed9e53315553f3c5c3bbce40451e47b7ea53fd3d3aba6ce0ad22
+5daee734bdfa3bf1d81c1b42c6d856a05d0924e03f7627c5eb24d7fbea3b
+d85716207f961b56803dbe046e81ed5fdc378f9ca52c14fd8544ca7c5392
+01bee06487ebdc30ff3b28e8264ec7fd5da7e08065b0a9147344ce28da51
+82335875e9f8b2347a44e33dfaa167232a5c3e69e8c5b58b7c7216537827
+c936f5741b87fc68753eb0d4a466961d0050db59df3195bd3379f5647f8c
+fed35da952d7cf2ded45eb442dbfe992711d22eb228bddf36b8d7dba2706
+2d60d2271ea8e8412f4290b58f5be26ff06f0559872f9de4deaaba015eab
+4904ba1f509f6d517c6e897312ddd571d769bc474fd378af4360e8b1f103
+aa75f48721b9e0ba589319e15d74ac0b03d730c3ef708c7c504787483f13
+4ea6297097b46d2680ff8aa50b7a255563c88d594b912f5574564a137146
+3674793e4834af11d14c7991e7fdb3a6abf8529e1a4f10cae79c60d37429
+579093dbd041ecaf03824df9c007e96f45595a524b27ef8774a83aeebd3a
+7134ab4435c80944deff5c1cba921b0a41b9651968581da4834b3c0e6d4d
+e13c1e792fceed26a72adc4d9e3903661d8803ddb58eb2b929ce31fc9f50
+a694116b00ac9f3eef53ffdb1aca3394bf11161038f39917b022394c75a0
+d467d64b89a44e5505ded7d9c6b8ba6ba098f140c9c00e09200eb4828356
+a2d6be9ec1d5524b09c06d9c6fcb5e2808050a339b5e5fd4dd6c2035a48f
+e9674520901edcad107f67ac8c8e508e6003011978d77ed225f361bc0f86
+a98b6120eeafb73f7377db1e7213e02d12c330f5492511b4dde08558d75d
+5b8aa2d56a3111dccd257ee96e3446ef1c76f000c8916c4ce261425ed9d1
+5b58ced128daa6c1300466e7b152bcfb5e6faab2519b8a98f26b29f98133
+af886a0aa7e586a090bda1dc6120dbb5640885c609a8bdadeefe5de0da5b
+75a8a29e92515e86e7e66bb29581e5aff8cb6551d8d1103df60d558e7987
+e6f56126a13db2c9a04886c655064e68a0a20d1b7de24dad22bbfee1b7c3
+c208d4fd6a58de78d6a0a6126efdee3b1a9713dee94069a9f0a2b392a2f3
+91c4c75327803b53f252cc9ef0323f84929ba4716c50385681ff5b4ed549
+29821594f9026b7c1297941b178c3f8a704ce09760533dbc6cf4b18afbcb
+ad039ecb2ebdc7838a9410e7b227924bed7123944675a5dbca388b710f8a
+f6048b03dfb713f881ea0f3b191a5cd989ea150b979059c8aade40385581
+5d8f7980ce6288f47eaa37c1097d33f13776f08779063c5217d7408d9835
+aacbe5c071ea40c9ae6df685f4a9827b828815d8f3a672e73a418e5cb156
+84eb6c6fe0998a386e124d76620446907f993be16fe5afcec681f585601e
+18182edcfd3024062a3082af97e803c47d32229d0a24596cf7e03f18229f
+a631175699e2f0d60fc09c4f1954c5d12d03bfb4395f0e5eb6c687708380
+7d91d93ca4177a6b5a8d2aa500131fcb670e711873f8a3c77575ec93a3ac
+ba37ea117db268cf10d04ad0f079484db124f6dc14a50ad3b0294f7157d0
+837d8f9a6060fbcb385606066401708c041594e0396a0be4b8b66fea141c
+ce4bd29366a986adb98d9a6935c49c57f8cd415e93ff8ae0df75e463e02a
+ac68df064c1b789b685f84e15e512404e065a39e9e8f5568a7d97671ae16
+02605fc7e4933975189837586fb1a55007fbb0e91382a629277c36a190bc
+85af49ef3f0f38d4add2b5dee09916b79690ec83473c63e92cf617617a66
+df472a49641da10654e3ad3880d060b02a4a6c75b51e4e9917a2b6d8efda
+12d59de5a8e222dc7e82f02f23a9d3dbf637154f719b14114dbb102be5eb
+76b441d7e9990ef6420c2e80942c8aed5a1d0b19bce115b5929ab9e145f1
+496753dd6b1798324f5ec1d0c7f26fc3045d7bb46a14110c99ba07a45ec1
+6002cb754c0bae7a1a88eb387bb345fa70b0a38ab4d532c2de49274d4f86
+f2582728a2cc54b4c09d26c0cdeb8fee6a42885c6207d74953cfcc583ed8
+2dd7c0f29d35bdae5bb251b8a2d4b1dc97e2264dce035e359dfbadde84f7
+37ea6a59c23d1a64d963e635769233624f7682ea34636b595ccd064aaff3
+887d916867475731bfcbf7f96d5e5e1fbe6aabf454c2f504ea4e8eb38291
+1560195295c87793d5f7739ad7ec7176e126413cd4d1058ebd7d6ebee14b
+b94a1ecf28b686411d91e07373e891f78c4c0a05d2e8d90a8ae2614f7fc2
+63a762d0f43485473a54c31726f8547701d4a38d20565ed1707847aed9c8
+05780f062b847e668e15565cba07a72b0ba99f03fb57d26fa26ff579c30e
+ed0aab6fec1b5dbea81aa88f16f0c9be869505be18c1cb79657d91d6706e
+2a3f0be9920655b93ebbae2b4d0b5df6be622c951f2cfa42aedbf7ae649e
+2150fe87cdbf5c2685ef36051080bf39d864573a45ae2648ad97662b1f69
+787031b9bc43511fb84155ecdc3d91e2475d072bde6a5207acea1e0d2ecb
+1da8a1bc4beec335a5c7102963e84b97be741c4458acc3d72a7e53b1f08c
+955f33edc3a0dc3e7308270c0f7ff814b111459985733c62e8863625a551
+837952f3cbf32adcfd9f345e14b585b23ecc440775310654daf7f41e56ff
+45f89701292019a94bf30eb2d65e14b1a1d6bf89d4cc43187adadf3f6e03
+a90ed01e5d876bd3aa56e5ee84dbaa4dad9824de9984bd45af96fb8a56c0
+10b3c3a3c6139d58e9d69d9109db18561b55ead6452497840b9ae90c749c
+155b6329716f0152a7ad52dbd0b8a25b9995e1416681f38fdbdfa443879b
+5c4c25aa29e0dcc07de8bb161c36d76ef286ec88d57c74bf44dbcb4feff7
+71d3bd82c8f4e233357c48e516efe3db9e60ef168e2c45b54651df9a5acb
+5f1790f7929bcb16ce5e9f6a43919ad287dbc8e12d9f9e97e5dbaa592879
+1a5a02d39d259f3ce273a870906a643cc18d86e23f115d2a35de6926053d
+8c84b940b362e7db183c4905060316b269223dad309eb5ac96deba757bea
+45fa3100f77f4765334edf3d659e09bd1a5552da492be9174dd406f8353a
+059ecfee3709422940a8c369919ee1f22f7c02412c995fe93dc4559d32a3
+155dd22d3526d89b16d9addc30cb7ada6e52d62c5f2dfd142d4d7b6e0666
+71ebad08f54917e317041f410cfd8a3243f8b39459c418b7b7c6494551c6
+f6753a94072d09e0d812351d62916383c6e061f35ed864923002007e6260
+89772d269b298dca2cc1f25d9be43fd8ad62d554c16afeb7ef6e5dda66d0
+5a810f003cddcfd2c02fff02bb61344968091f67d3862c1499409ecca137
+b9a2a9be314995b818accdae27ed4ad583be29dde4e8c2400c5f8152c857
+09ad2a4737bac768feb70ce81a92c9657dddb2d0bcf9169d272a063c75c1
+50addfcbc2f5f2503de3d13231aa8cfb396db38e80197a605f6bc20efa1e
+de40cf424cf221218d51beace64a3dc88377e4f3efe43db4f4fc0803bf61
+764104cff0b618c9031198b094e20b0facfb94240b438b67ba298e31d3f4
+e31fd190e48bfce27b1be29d36e765e7d295e96edce09094fac43b87e294
+818fde9363fc7dc5ea36a1497ee25762d02dfa00a9be53f87abe62e52ed6
+f59818fdfca643042ec13d670ded1980413950ee43372d31ae2694b83dda
+42e1fbb049f7e7b7e69c93ffa3195a2462423dd2c022e5141783ffa07e19
+2aebc5070f08b23aec9142eed56da74f93bdb50478da55ddd0a9987fea13
+1e4cca0efc51064e4b37632728261369c3fedaca100f1aa78fb718ece7a9
+f56296c5fb43781e63f36b0e1d34bb748eff35e1953941f94d1a9b0fa474
+fd68b47183f2ac53a63f9f1d30b9b89c5fe54c3765b43db403d57994701c
+133e42b950d9bb1ca202f15b5e590ee75598fae43d5cf1546572770bba9a
+6373f100cdc61db4e5ebbe0a93e0e51c86005e333f69110b1c8e492f2bf2
+52cadd5b73e7d3ebb53e759353f1ef3c9b8b39c230d13ab7158a5d92ee4c
+452f81f6dfc18803280aa023832fd0dcb482ce5af615c952bc3f7e58f641
+7d69775fc7c0d5b405aac632857736acf32b2ee0f2a2c0f3b3cad483c614
+505be94706322f2a2830fc5ab592907d0291ed1873377e7a6158140c2cdb
+1b0e27eec9ca50176102200992308045ccb5a169b61ea0546778b8d28073
+7319046716604945a21f2a1cb9e15e3a5db31e0fb5a3b0afdfdf6f3424b7
+536d473f9756ca3694dee4301fb1ab1ae47128f8d2b461c051c1b999dbb0
+10e78dd13afcbba6f7d5226d540527f17881a18f551b3eef76a7e28b4fdd
+879381a2217ef2ff9f9982e9ea70ad2003b862d7c36d57c5ff9fbeaab560
+40fee973efc3b34d83191960010110ba10694c17b7635ae03cc1cd087c0b
+05522a7a791f0ca34022a3f5860b536d9551bdfdbf560a07f63aa4e68740
+7e5e48584e689591f1b52671213e430a708c06a34d2e1d51cfa6b328a122
+007c81b5eb263b967746961bcfc8772f8502dd95898724abf369b0877f33
+13a167f3f714023c229c5757d4d46fcd9b4afecd093dcabe52b78132ce9a
+b6225c9a344c4bf8d96f2c50c4272cb9aa0d606f013b2642f8c880e08ea2
+822c8cf5097d2cdb64932fe195abd5fdf36d3be123aedd8ba2f82a8a628d
+be3ed6129dc0fdc4be50d5574ae4fecc65062e70f4703bfecb35eade1962
+94fe173ea57938679dba6d15448ff44c0d1a903b202439da93c0b0e61211
+0068f8079219aa89f435e44d0464f54833beb338670bd820d941df4b31f5
+1b895bedf833f9c43cb7616db80f988ce72fd3c12c7d49f740cf85b4766c
+0ed398eb837695d102dec16e24b7475a0f5dde88fbf2d6b94f126417c811
+e8362b9ccc52d8891c13c10937aacc228d621d4712cb9de0bab60ede2a97
+e9292be04e42e6d3425594df56931a61e1f961726af6e6891d63b240e6e7
+9e5bf30c052091d681ba1102409874cfd8edc3ee2be331676e31ac00f807
+91d1019bb789ca4f5907f4823b002af3581448c352bb67d80fdffcd1c5be
+ef60523330aa2c0456008f62deb55e69ac2f86369fab1ecc90d2487954e6
+1117a90d9269a65dfbdf297ebd29c3dd1f62755f8f289c42a534f5965068
+5f8576ea2fc5d26b99b8e3dcd3f1feec73131000f99aa9868ea9bac0b56d
+ae2cf46da6cc1d18c0ab8d77becff7b89992175cba2e22779c13db9df53f
+f5b1c8fe95e164997d94202c37175e562c8622989b075cdcde173452c064
+274354d5db8f7d5a78d48ad4a103b9e47500d08edc7c51c1f3cfa7f43c36
+86a3c24a7eb5018b0f419961564f87e212ce0a0741ac68d6822c7ab9fd68
+85f5d0b2ac249cb7f50e2353cc4b0a6a24562f564fbbc7090c3fdf1284ab
+0ec615e0b3fbe132f31570c8a65c814f93910aa4bb80d516cb70d2e1d119
+69238e6f022d628fa2f33a0a15c4ef0ce7f753df80a8ad9494885a1b9ada
+e6c38ac9da6fb0a61696ad3a502630252ad7b574c841117d34bd20bd6581
+217d977b35f5d04e02b933e1e84f5c090f6615af484d63265d28517ba74b
+ea8876fda332a84aea12e6cd82b94ae10a778cd3a216abc08495ef319f06
+ad6ff8add237d911f846a514fdbfaa8a1ec8e0aa9f80f11f1ce615519a4b
+044f3d1cf1a17d7f3d2174222a5ffa8b39f20197ff6caf250b6adbdbf519
+1c525070c8d38220fb501c223f493d80f498621a02ebccd6efe914f16b2a
+435d60c0a1a453e288a53d818fe1edca7d55a26a017f2ee47a816e90d6c3
+fcdf0035eea307dfb06d2bcce43458a67354a4edb6e5c57233de4fbe41ed
+07ee5ec77a5dfadc4032138da9e1b74428cad02a913e40152f8063a774d4
+fdd4070e4b8a6c089f199af7c529c277e902195db760d81ec655dffd1bb2
+83f3c5aa8bb58f2476bc797b2892e94414abbe96d4db93e280cf7de23eb8
+52e7ca954d6682a6f1a4be0507884c2a05ac863d2ba73f3b54668397b6c5
+4dc2f4183130ab414875f3c3d8792bf7e5fc4d228df87748bf0b14178db7
+e3ffb7891d700a1e9520d778b095da80e4801f53442d5c073edeb706a5db
+8466ffe7e701aba9c364a37169f585c883a83713a61c9c3bd9336a667ea4
+e3db5f4df6bc6a552be8d3ef093639ec67e5ff718959f9902477f5aa894e
+d2d1cd312ed82ee417d95c49c96671b23fb0e1738e892adffe62ec1c3d4c
+beb6cd089c98de8d247df7ed17dfa2959d3662f105e8386d75ad30848053
+6959f8e6cf8f2c6937b09f2e8137c811327d6b165abe46c51834a955fe83
+06d10033f8c2a34667f13a8ba831ccf52c7a21c13db92f3e77b55ce291f6
+190bb1d194a33fd73151c3f61abd2d8a0c9bde90e796bd996d2d0094db2b
+e98657e751bdeefe8a43ee4501b98f0cc6d80805189438872a60047a8caa
+9039893530a3e5f6bd75bb466b25165737c939aff3ea59bff4a7db09c2a5
+b36b8a1f0c6c5e5870c7c9412589877ef44f84284b8a53b5b74315ce72d2
+eafc631bc4cc2e5b71dc958b5a6350cb5f615c3a4502e973622e3e18193b
+69572def1d02303a375ed60aba1bc8a179faa0f221a49078fe15ae133835
+85fb45ff4d5f3bb3d0f6d8bf62e9bd6bab3c9a7d38c8a5ab0be57acdadcb
+d02b1dc7952d73aef702d406f62719922bea96b8fdc9b879708e794891c7
+a0a42f2ccd6812c3f4db030b5178e3a627c3e77621d312ce4ebe815cd387
+7208fad92761a5396b67e835222609f823728b1c987857cfeaae21f2ad5e
+a9d841212993508091a4a2c268bf1d8da1c650f6ab93995e7c13a3f84db5
+5748c626fd09c0da1e3325ccb0bf091e996245bf51eb486680162bae63b6
+513c74ce83b92359938439921950d713c69324a87bce67b45a030c9cf10a
+dfa0a82781d49ff224ac57a23c6cb321f95915c5e14e41fa852f66e1e204
+4a9e7b1dc3be9e818515d28b2c4d2f2210098c39557067062ba4239f2aae
+28816d999955910298a450741947a9a1aabcbd8aff3530626089978c87df
+c73618c044731b6db8007739a9699abc354a6f985e03c11d750b8b9e9ae0
+5436205faad1b895b159e2c90562b82a62ea1a7ffb501767dce2b11c51d5
+5a17529ef5adf0a0ee9a96d0e7e89f68e50eed813836531b4b46e9071e84
+aa413f4135cc882ce832bf78ecfa7cab0c9f64eb92c86dfcd1152bb7d4ab
+33831aa0c139b555967f6346068d5c3351a7a4368eebd2933e6b9f789daf
+37ef536fcf965c397af1b7f98af864b301f3f440b7acf704b59540453678
+fd6c15045194818938123e2f47b265ec4f5cf2172d394543d84cd4281165
+cbeb11349b315a85deb2d1699507b0c8c110c72662ea2959c4962ff093aa
+5ee6f21f89b3ccb0149cefef1855b9a48d28bb363416c015a1f4ea1975c3
+d8807f616c5817c8162536176f464a198ebee6c97029f15f414275a39b82
+19128b8c8542e94835507fc2d3908bb0ec375771280b9ebe87e827811418
+ef93e52ef70546891bfc0fb34969fd7dea4ce7524d9eeff2b46bed908c0f
+b2e02efc1d1624642eaea1cac1eb4841e020532e88e59ac890e6c3f44734
+b99722e9816402d1d0fdf8045c5481ec055100836ebfb48e9fbc39214303
+2c909853c9ba38a19363141bed09daf02fdf4e7cc9808321cd0708a1b452
+70bffcc3a0d7c27f7e781713d5dece82c72ed30386b02d14575a1a644754
+7ecc7faac1bdff332c92984758e242256c054656cdd2c45d46e67aec6f83
+9f95d74e222a6eae12efaab723a7c816d4e42d4ed2725a794743f67597f3
+db8ccdde45baabc25726b851e02e56341ebe69e4d91f2a233583ec816f18
+a1decbda4ab69320f55e730617360fcfb8ac2d2b737675b406297f7f8c4b
+c370cb084c22bfec5fef02e9ab290282f7b153f0a4b1ae569f1e52371a43
+46a748dde09336cad1f5337fc3d7cf0677091e59480ab15021e023e356b0
+e1bac6c6471ad53625c70206c338536f4d0d40733ab217e2297f86b59371
+7c61458b6c93a16027cc886a8cfdc01ef19c34c9a608b95a84b6a2e31454
+bc03c10fa55cdcb7b1eb7dc16ac1e93981a46decd7e7f00638dcac568744
+69a2d9b45cbc81398727e4ed3db5db31965f358d8179cbf934ee2c4d652c
+9cc211807f070c80e3a8222b4c31ffec8dfb9ee07a94c973462254bc1b15
+81903ee6f9ad91524a787129a63fce048b45bbe6855826750c586b6b23b8
+05fec3e7aaac079576949a06f422fc2c826bdb78ae96135e9e2c20c2b2ef
+f6171d610b2eb8635acab7c5c5ed9c9ffc26cd54d2fd4cb9e4294e178cec
+a1e16cc8e3fc06518bd16f4d63ae2b435753538834cdd9d8ae7de624006c
+e688938031336351a6578c304c2e5480a3fcb43a8bee4953dabc30558b77
+90c6e7a6f0f9ffa557c50417407ac6a0dda1e736f7070bc89455fc293453
+3db004aa9070734c8c2608a07330e421a0220dab99f8a77489132f6413ad
+b9ea637f3b75948050e667276a55beb09d4153dc126bbdbe0db9298ac799
+a943d72afb769bfa1488d311beb86a907ec9385aae4f77835dffe4389e3d
+9aded1b08bbc2b1ed6084b3d1074a326ccbf38e06bd026919107bd03bd9c
+30470db779508dfe0dc82dffd2ded749e872eb7eb9ddf509d5319865070d
+d76846c34e4e43691af429aa40db4bf2cdd50b275589987d8081f7c5a046
+1aa5d1455a660178a94a0ba0dcb69c3cebf5ee0426d6534f6f919d9795ad
+6a0e1a1f452af3b4cb2ea54d6011fa809132421d111efc51174e223ab6a1
+3596411a9723079231b050cedae7659cf168c39aea9c6902c2cd37d25492
+cee00096edd63dc7643b667fdfde5b595dc54f0a72c2650e1e46990584c7
+8a5cef9bfc3c5f88cfb0c49cd6cadd9dba675177d601927d75c6902b55aa
+ed0e9e3cb52a577c887d581b3ce6201a1c77c9546cee5a13b92963337f17
+070e2bf9f5c5e86b84225863874618aa50f4de855de567bf2ab7163944ed
+43dbd7f4bbc0e16231807c43dcb47b2eb694e6fedcfbe26194d2d9943a1b
+fe32aa1e5305f5e341ea021f91532162978dd1b8c5295a5e7551e2dee46d
+c2347c6b32197af430af3bb676a53bca9bd1ea88678377dc0a9a86e2ab6d
+e29e3e261bfd5573c66fb5687ba9c0544d894a759866b066e1db5c66e60a
+e071cc3a1c4ae40197cde4ec723f7b80137619dedc99af57a5497d6e03c1
+c9e672e74f48f6c213a3cfacf2699cae72345a51c71c1d69348de5bc5f44
+3ec0eade1e76a8a33066922cf3869e3c1d26a3b34e540dc08ea4da2dde3e
+eb17c16790da4ef1a3a76d71d34b788a87838bf2a5a3db8176f9c097d232
+0050a79ea6c4a94926da11abcdcd26dba09fd33f30aeed977e8b5ad928f3
+967f607628859429dcb4ecec7da3411be35a03851017b535985632639d37
+8cdcd13b00fe537a49fd9eb6df1e3aaf5c41ebe35721fa6833c2fe08aa3c
+ffc3477e7fcebf9ef9f4dae62ff78f319481c3f1e72999c8a493ec6ee295
+316b58a5cd62ffab62c896e521b678342f04bce1613cf7f6778cbf5227ba
+20504500d743270771953acbd5c6586432f3fa6c0987bad33b88bc6c15d2
+9c4b3cc54a9dd72a2357aa5baeb2cb057cdce72dc80cc98c62b16ac50b4c
+6a7641379b766cddf990dbb2fc7f9cdbba755b6e3dea438fd6699c30a99a
+8b3178e6d613aa938120835e517431d28114bca1ab745c11fe6e52adb82b
+9d3d53a33bcc49740c93017d9531ecf43831359c5c93cb0e926db440b139
+e3125cc2e069b1cf6d96ef68407f32db517242c3ae0bc6723e560b0f45fc
+7f87a5e44e1751c8b7f9f669c24ad5cf16f84fb03ba121b86b0694234d8f
+2c9c947269af96fca08a78f736e4e04acea44c5baafde360fcd8ba6a5972
+4ca86160a5527fd564468123d302db45173c1b216b01dc5b6d3415b13fbd
+bbd3121a5493374b3357efb131cabfe5087aa1d2c7472b0377066b3632c8
+2073c6a846285cc953a8f28e131cf587b35217ee498d9a1db57b063ce068
+daf55d8cc1771c0c30999ca4fdc5d67be4e7e69418f6334bc6149000821b
+89a7437ccdf9a6a0ed702d5968f1e04f7e4fe9fec9d1e994885cb624035b
+bc5426cb8edf0456828f8eee75be491b45fac192a405eba25caa4f4c66c0
+dc234d7b417628da5276c08260be512b2432256c401a66e3b583e69d23e9
+fd278cd5f2178544d05416b9b4f61a88a4728af2ceed07c08e207f31d644
+e8e3ba1e4e2f9d8e30936bcb9c6aeb54e37db46bd64f2ecc1021336d0564
+df0f18e5a6b6ba470233d8d41fdd9d1079706ea685b6d8a740570bfb78e3
+984bb155c3155c69bcccb41cb51975eea1c1b4294cb546cfb03dc31bf86e
+c3bcb1977e8f94a771cab09de12a82f1d6c791fa7800e5a21df81c9c8fcd
+a78622abe75b54aeea747aa4f26d563200992e337231a430137c720a17d4
+4f3ad6cffe63b2de12d3184bd3e151f955786b8ddcccb290c42718f3a219
+1759df76371c2fc177544a6c425cab14aaab31628a9cf9d71b5257aff0d5
+9843989cf0d747375a26dc9ed29b66ac2147da0168306c48c2484c70ca92
+f33c0c138f92f276f5eaf5ea3082a8a1cb12db661633c2f71e3b69918f50
+9060ac949fcd52c36498a2abb77d139df1eb33e3b846a7c1bbdcef5deeca
+4ef0ad250cea9c2751e13ef7681e8fae0491cfa6c144dbac1fc39d39e76e
+b12d3ee9ca159aa77d2794f0c433345b135ba632f544082bbdc9471e9fa3
+aed3a7d465ab7158e8ac97f68b1fbc8d368e235045c18efccadee98778d8
+94d96301f903283c5ae355a863bb0dc5809158f7e108662d04a5c1234915
+e7bd5b4c30f9efa55e702e54f87fca06fb321507bc57a1e55cc117e21aa4
+e3a4dfb77c1a949efe366d93f2bd827ef8cc16d387ca82ac039f77fe995b
+e6d9aefc87f8d809e90c1017803bcfa1c737dad5f1a631ebe6894ad20c70
+791665e7bc71f21c2c3f4462f60fde75c8a377cf49be99314663c6ecb538
+b1bf021b2f2174d2b22cf6fad115eb0ece8a2e64097a5fb0a2af666e1ee1
+3276aec59fd0c9d4bff23f71e835984e5eeee36490c54e077ad7355dbc98
+bdd37df29b3ddf8c55480b7349c4d17322418705796a8c521fff920dd117
+73fc44fc631c7d6e9b420d7965d7f62ec7385f2be30a51e2d796483134f8
+40aec71fa19ed1272c27f98f2cdc9c7e54dab585ac1703ed08f5f9e82556
+4902efd08edf99dfd49444c21fa6be16cb8a1b6d0c8a5abf80a50bb8d055
+483176fd0aa07ebaead88fd694f96febd60751e5c4d8f9bc747d4f4030bc
+df9b0370b7a5e0a6923ff60dea16ef47f886f10ccee6956ecf41a21f7c59
+6f3bc78299a9657266807e01762b2b2878e551914ca312c2a68d34cd91e4
+f5115ea1fbe801346e14ae529049089b6b0273e258785773a9ce8e4b6c42
+11cb7c2767319576758f811cbaf3a3ffb41b31306c49f3798b698a47bfa2
+e3ca0251c4d90c0b02aca28c611744526906791d9e157e54ce4e1bcf5b68
+6990ba8ab7897d624ef00eab92cbac255ae9177da9f0d86447d35b452cd2
+f337147b5d3ebbf2b95235778a72914eb3707ea78294b3a3bc4acb19fe87
+c72aa1d982e4b822f07b115cadf4d3e7ee3d1ba708653bec6f0a352a0c33
+252ed0630e7274961896d461ee8bf523d5911bac1c8ac763e5fb11fdd217
+4e1f129675969c195476c7a5e18a81bf9a11ed9f2336d5301e3bd32174ed
+5c933e8c85d6272ea21852a6f7e2aab174e0965f73e0ef89e906bafb181d
+bcf8b1f5aa0c12d12c6272753c016afec2ec9f9541b8757874d6f2e061ab
+be8b29281677246305b3c41e90418426c575baa216cee3c5ec29b2fdee1c
+77c14fdf940792f48a56ae80aa33e370b037cb28a7373f882022af378f26
+b6006a049fd3b35074a865c97d153352acc156992c00de26ad21c982c71f
+0edcfeb61593bb40fa5f2cebf23c4ff34a4f4bdb73ca273c269242d1c611
+7262b7c47771f2619fe5710855134a80fa8f92bb2425cf88940ca3450f81
+234abf2b11775929b12cff86442b2aa0f4243d324a5983e5d1829775b3c7
+a111d5622d1c4e2b2a2f982fc8a95f789881416dcb34950a393f4f1720d2
+212f3d343a17683060182355de9e4718506d76c9184f8dac55788d7e603c
+faf4907dde965a49c323dff425fe88c09aa4a4d16283f9b14ab9ef1bb885
+a954034710b4a9da4c88a8a0932b18d139a687303ee562ec9f656f12f3e8
+f27daa9c75db0fa946fd0e1a982bb58e040bfc0a49a4ad8cd668493fcb57
+3c849ec5474049a693cbebd4d79ac7515047cc347a9a7570c90861f3ecfb
+57b9f53ab9c0d6b05c8c570a8f3c04d58555a45524c98ff091b8f8a422f2
+e0e9e5a7b7ff69f1cefc13e42f1ca276bcd584516d266ba6838d5e9ca9e9
+854f50c7d92caed61aacaf758a7c7be59c3baa82bf32b691aca3e8eb171e
+08ad22c39fbe586a54e6e4de2cd86b31138546bb8da5834b2c6e4838547a
+1b67e651964e43988c8036931088904bbb589ca901e7ebbc094c0da81e09
+1915d9e46828ad8596fd0fca39ff12a6c27a359337f973809e81b2e9e3d4
+3b3146f2516667e607ffeb9ac80fc95a7b7d4ded551fee0f3561c70db2d6
+9aba96673e39e3397f1c3f8fe5f48bab8ad6e0ed8901f90f6cff24e80cb5
+dcac498506c4d01033e497c1241e413b022227a3264da68bc3f91b35781f
+a2d018475c199f43cba7d3a0d5697b45321bad2c394b207136e1e16b4179
+4975e8903ef2b2e1c33f87cf72c325c11ec0b92fd3890acdf60b521da325
+96763bdfcdca837adc6f26f129b23ca32f9cd39b33e64576970df3c05b8d
+ca4bfe2f17e6c5678b84d69494f1dba9fe0446ae6afeaa1ff245c07916c7
+b7569e6267c42b459435a1d116cec665b311e404171774c0acc8dde96b0d
+9167c8cc7d99c42405592d745c4428755500eb4719340d2fc6bc215b6782
+3f69fa949c08b5ec985d7aa87c9ac1f9bcc8994c6cbce6027b7d1e0c22a8
+3a5de61dba05d4af6884c95f46ba7f253e0b2337e312916e163caf9db2ec
+56c5425990fe73ee53e42b3bcca1cf642f02b0c5abd529b568e9adff865b
+9dc190240ad78ad226ed884bed3c285b4cb0e3929e805c67f1318d186504
+d92085764b70de6ab5ab6990f181bda50fc31262348d980ec76608cf0817
+6c2502e065ac2d8ea5cf9e2d44e2b70a7ddc7b922047c471df8a0b2087d1
+106b5bd8a830ec0e53223ce3c96ef56e5541191167860eea58d696ec357e
+c55799438c90156bbf2b13a0d5c9ee93227746654ed73ea5b9cab61dac5b
+c690f89c87fecaf9ad03bd39e438f43b81d39e07e0422f94e8b096ab38c8
+8bc2e1a043811d8141c1a35dd3a6dbe41620e83c8ed3a379cd80d4f9bc30
+41bb44b933daca7c5d4427ae94a176829f24b5968b713431cb8bd9f53080
+832c6b784cea9b515687f121983eb9d9c9ce8bd4fa3bec48afe64e643b7b
+d86d8383d07521fe5d091392be124ccc911136043824b686988e7c83aebf
+406d2da88fd952d0fa9327f4ad04c55fedbfbfa76ecae8a176c516479ae1
+467125b7eb3c9e7c5b103bc0c470946346df271f8ee19df7e3ff7478c35e
+e059297f4bf21a5c7b95993be6202e897776952a7ed0613a5cacafa731ff
+c633cab62963150e86edac796026ce02eb235b9f7a54e0b0c5281567138a
+612bafe409a818c216da8eac5edf9d1e3a1e3514ae50735a111b4d2aa083
+4ec6c11e290d58ff340f82f0e079f1c7b3566f2336eaa45bf72bcf885699
+88db5f65d4c1e59b50f341e45a899656a0b522847ed567b49cd5284fe50e
+5f8652cdac1c076804f2b2185f6a51ed19dd49412e65a0d2dbc844b75e2d
+f71b009776d9f97a4c6f786effeb87a307fb6b912bb659dc2bcc6d509a9f
+bde87de8d716040a8551b6ccfb7743978ad992d14d2b85ca052e87326138
+db196c24593f8f7ecd6f486f85d1666b9de2aca6c7900044ee369d223524
+664a2790b773f9ea26e0a4cdfd709942a44298b8249506eb9b77bc887dc0
+ef947dddc7cb3cfc6b48f060dbf032a11884e6c226d9d447a5a458cba325
+d57e144c6dc295262763e7bb8ff6a0ca473eb7661c12e0e8e23ea37e8ab3
+387b9e54686f3e57765d4067e521bc1afae52394227793c737c19208803f
+2f2da920b553e2aaf94eb992ab17e31b58c15cc4aa8a1b444df5b3e7cd93
+7cf03e1f7fac63342731b4589f16939d16e8e497a74cde5686f529e9495e
+1603d74875288cf53271db9313a4511b104f80b179fcf213558970a002e9
+45281bf3ae51e668dd6d13d9e85152747f562ca0b75ddec8fe9fe31f8d05
+b0f59e802888a7a4f19b29954a31108d2f041367debd6aa1cad856bdd142
+7e9efe89956fe28d500cdc6a0cb80a76902a08d0bc6705583243f1dd8020
+749b257edf4803bcaa653f7fd6d8b91690995ba5ea3ee92fcd367c11601c
+6b8adcedce67b16c596c5d200693ac5fa15d4cc6ce9df7a71c8a925e99f5
+085313d60fad25c1bbaad28d4ac2b69062d68f390530a976319a3904cee4
+4dc9451e441aab4780425440f8c499b81460b5d3e268974145117ed843b1
+71bb14aa84c3a084a7d8e07b9979260675d5ce6534dc176ddb60dde90f6a
+3674f67462ef78195f8dff74fb5882b079dee31fe92816f16ce1a70d0775
+2ea25faf5000adf79bbe7d17eb1bd2f9bf6cdbb6f078caf97986442680a8
+fc4121866f9ce86c385de34e30d8b9768a0136d9eef79a4b38ee99cbb9a4
+d32316564c9d56996e2595753ea71bef684834fd030d38bb100e2332b026
+b046316a53270a96dab2182e994e91262fb03d1affbad623f16892284098
+84f91dba153030870a7beb2c7ee2dec51875b13733b7929041f8d23a9490
+4bd54dd4bc9b432dd0c78dd81639f46d686ffad39aafbd1b6c1a37e248ce
+48f23e12464d5379b4aed0d50b5a41577e6ecb75270e9ad3ea7d0fc09dab
+271fb18b51dcfc0069f15d72546e6c51049f3425ad005f88fd7f02042dab
+e9f097f9d6a076b30d8cd777b1ec12bd163fdaba5972eaa61e3c87e9ac00
+7a052b1a3ffe14d7d43c7a0adc89b1dd4cb4f9c762a84a6c0701494b2d8c
+4e4e1a9245738be4111805c2f153a20ed9fecf2dcf4c8f7c3baf84d60454
+a7403d4f5f81c6404173a7ba81bb0ceaecfd493d877465dc5735d43e3102
+cec57b8a589182fc65a4704661a9e351fccbc7315a87e62f65d24eeb9cee
+979c6e10dbcf5c162adb926ec8cc9bffe381f6b8a3ac0a19d1631bea2938
+731afc99e8eaa39bc75ddb3a39d01ad8f0bc1838f4d674b9bee9f6f7be4d
+9c8bd97e8d171eff330c15b76614a1ffd25b3be19e4a201bcc850f926ed5
+1616318c965ad2f0e56f9433b1247c6d5b72edf3d408a3e0674a509bf30b
+e813a5e669d72b978794683ca8b85e3469eacb167c30f7666db5e081b81e
+e99ecfbc1704b9646b1a29e4a4ce5654ca8409add60145dfc54225bdb848
+5e39cc98cbc3f38fd0a797e5dfc2099452a2418c6636bd2d5f6b24345acf
+a65f4e7dbd2d0aa0c1776a4920b4466c509bb5bc7d6627946c4dcb38a270
+98b7b5beedc2b3ba18f927077f71e38644597719652037621bb350bb5369
+dccc073954026e6438fd8393ddb3630c4473f06d9fb9e422e435566c396b
+12fdcd5605dfea232171cd8ef298786806e9159b84599c26d4c7d8c3bb06
+4665cdd072e2083190372aa808b2268b3fec8878b6420ca829bcf995dc20
+e067ee6b8e44d2869d51ba3aedd1763f7f8d2cfb8ec41e6e9e0129de5343
+1457960cc51d546b10b8b6ce08a1c2b79fba448df9783d815608a16c55e5
+89dcd8ef6b04c66232f47a473973a35618000d79b8173258b7365c9691dd
+fe47b16eeb08b28f881828b946fb5d6fe10ecc6afc4ea1f762e90b332040
+3382e42af4885b183aa48db5e4dfc9a54e0b4ffbf7c26eb17a4f13b4bb93
+12234434fff05549e7587ba0373acb3e31418bfaf400d8938fc6466b9427
+3d1735306ab912aab13e31da3541c1733e2a7e4da5b82767d37f3084aa7a
+7c488cdca7abef77d19e42b4448abbd346e9bc288abc4540c0a1cfd0bf46
+c5bc7454b25e27e9906a3e6cbf678bfecad1b19b4e42398a210cd567ec35
+fb115d5c0df0eeece593982056b0e1d14c292f70b3e049984f8881c8b477
+956ad3140b4aa22256daac0d11c4126808b5b9f922bcc5f24a77ff352e2c
+621a3941ac07a20e550a69c49b1b87d116ee6f2f970918f0f1a501166ac4
+423fc212e4ec8039ac7f9c212d864f418cbb92948fbd588228108fac1ad1
+837070512305c110f0fc3fafe6e1529c2bd0dde868a9ebe5137dfdfc5c12
+a3d08014bf0ee27b108002aad6b607f5c5c0f1b1eed3c552919c9a2e9720
+4a8127f97b1066607ecfb47ba95ef2b51f007c293b2f6a63041a9c1120d9
+cfcd5357222e5b02dfc73cf94cf9b5cb00eaf073e9bf253e30e09b50341e
+57bf245a746ea31bffd0b00201c34cf0881bbd1006bc9ba7d420a48e5368
+6b598bedb3449924eba58d5db1b1b01ae2ba281d5758c99efe38adce18f7
+b182fbd0d0622a6ea497a4e7c00c7d17299a2765efd8de376c214d01a218
+19451fc04a0277ec84a151ff93903d61c78ab7886911e36e12526ed855ab
+43f6289c1890222602b8efbf15782b374ac1e580b6e963403d6d15a051db
+8558f2e61c0b9476c6de5d4861585cf515ce951732f20d32969f39192fbf
+1690d242ac04d47e0c53d467d0fe4656b9526c0f7f852348b0437737cb0f
+29ecf9b54a5e17185236dd0c16349c3496f3aba569ea20e343f6d771210c
+39dc932dc65ecef94575c6e76902cdf6c8c8361f9c757a2577da535187fd
+526699917cfe0ad438c2a758727b306bc7979547e68b94e87ed820614bdb
+c649d469ef6b4e4e3dd2eaeb5f80b22fe576ced256495467c76a75f58946
+0061e03f3a1b065121a5abe3e2c51148b3ddc9f624c97889aaf7fb84b158
+c015eda5670746c6359d27b0c2bd65144f2b88a64331816da904572be398
+e015a9924218b3eef95123aabfc3ac8217b7b4f691219a1c9dd0a3edd5c0
+4e63acbde71b423522532561f4b71b7028415c3437e346be728a415596ab
+749015c1d59bd8328e39a850cb98085b34b57fb52dd1d154f98fec49b3ae
+bfcb1672762e4d2a1ecf02787f59df1ebf2625c3631bed849b298c6d226b
+e4e6ea2ab66a287d2ba92a6c9c612a5f849b3cb3c25f17164be286f6e4f5
+e7e4c9eb17bc68aa5ef0190b64696a570442e1d9bdd1a30e7692524e30e4
+b4c3df84481dcec6e10e7308e65de9d90099f3fabb3f4f766bb86cc98594
+6d2003e21287761a7386cd8461615b570bda015f5efa23d18e83c325ee44
+4ec166a1a32d9818c2a65a092d44156c06d3fd079b92450b8a491cbb3529
+ddac7d95afe8eaf33777fbb265feb8a4b9aff2cecefff49afbdcf6c41974
+97d3b448866d70ef28d8e4b17e7ce95f43f64bb48c4a73eb84b26650f62d
+3e5199d64db0b5b87702650ed0b850fd5d16c848d096e4c7e61bc63b2a3e
+cfc099cd713e12c91a6577a88d6f55d348617c7a49890a86ea8fe2045704
+b5ed529db128c9b19ee129e5fe6498cc97087f6bde96007c9d01ce9caf75
+646e5a5b32bfead9362a52223d746943a2d09c536cfaf78e601bc2d2f0b7
+63ad722e3a7ae7069d65f9f2bded7278511d0120f5ea071d41a69f8c2a2d
+720d3b24b4be61c83ffbeffae21b0560a6fd1a44e53e42e0d10e0e93f421
+a8a7e167bb65f0d7f1dde2809fa3cdfd931ccc69b119c83238c1c00ec100
+d8e7ab1c7fb02ede97073c8a5860371a8132be391eb1c397b61f93876feb
+438c288ef2e38ddcd182a5cfbba994a94a1bf818312cd8234215fccd7c24
+0a15ac01a885e1179e5d7d6305dc2f534baa141f25ea6a5f356486e5fa0a
+e3c6980a9f5e8e99e7ae5b95ac429775109702454fc951e4319ae4b1ddc9
+b07d0998372c0a95aba6985a4dbe6dc633154faa30ace689d36a7f17011b
+f29cedc58a6692a8b3b0a5742e6cec2f69b255bceda762dee72f125eba98
+891cff4d88aac14188a18d81424979c9079e44890d94ee094d4caddc1c7a
+c5f6791fab8849cc0240a579abd800efe3aa4ee2f78119a3c2806c05c2b1
+f17940be73984982d1c0065433a9bd658ea31ac819da9a11b87475bb565c
+c294b6f302fe3f7752ed9b963c5279b5f1196762d0e12e6da46ff9a0cade
+3876d7df695d8965cb4b47b351fa3f759811269376b2c3134403633fde27
+c9b024f6ba81f3e1699cf64a426618428ba6c3266bf016c5daa5fa4cc82f
+b6dc23ff2d742160518cd3a65adb38e53f1067076ca1625466e0c64670a1
+564a54ce14dc5c57d24a12283fbcbffd0fd594ac2a56ee58b552f7586825
+e4fb1ec23f8221711692c8c56f42272b87ebff3865191f1c11943bb76d8c
+0cfc53ed452ae49404d2c8193ecc2a7bb8cfbf24870aba38d2ccf7869e93
+63dc0ad94facaed5922b324dc3b6fe83e7b34fe29abc1ead62b49ffbcb81
+1adbb5148d5ac2743e3a058386036fadab6ff071bc1c3b8023f908b6ff48
+db0ab1c9c67487c35211d40995e1892c8b66ad6c9c6203f6f8b513b11117
+b10da8725ab45b4437b5a88a96af3178d856d601196e8162868a83da64e4
+08fddebd14d6591881ea652032cf2f88b3fd6c0479c8f89ac68d14d01af0
+ceafd95ad146e68fae01a07f39e7a0c5e4ffa6d6a91d710827ca5acfe7d1
+f946a8d7b67621d60f5341f32c12a6efb03ae5ac5373a382c044a276f6b4
+1c173d0aaaae0c1de4c3cc71ec2637225ccbfbd45eab92bf39357c57195b
+410f74283585b12b926438ac72afadaad2d0fa2cca728c8e86bd3fe75d47
+b8beb96ab13b5480f7a3d5741eb51e3e40c21ff2ed7d9221d9877c7d1a8c
+ecf394e4023fcf8c4efdb38b839499ff5cd96a46ab4fdb46f35d3b48b917
+57c0159328120e93cf1f2739e936e28908fb19471d3ad7f6f1ad2bd1ec36
+4986a411cc1b547d0ca104fbc10b1ca7b638a60e75485574034561db345d
+da68415146aac632dfa34769b6ed7d7d4694e92cbff4efb16b5549590810
+2e85e827fc623cf1bbe6a13cbf64e878e1a2a159948b5529b75e071744a5
+f0e50df18c110b0af117ce7f33f8c959d4c98ced5a9d492ae6f56da57b0f
+17495dacb130660bcefb064fd8309d965abe8d2be98f6898c1b7a39cbbe3
+e75da0ffef6cc3945ce76da3be915546fe8a5310130ae0acaa9ab73c7e04
+1c00533b4bc7724657aa649b9388b791aac5eabfcdddea2cc67a0fd0ae9b
+e37df9ad40636538ee55a83f60e9e026c64fbd8b220ceb46e67410144a52
+0fceaca252e8165448f84d8ea083c793ad09b90b3ee83b73fefc3365c729
+e3c738894b8c01c2f8aee0cc8b114e1175efb44cc4c6cef5c8754b1cc7ce
+c200ad8bf1189d741cb75bca4e88be959e32216ad33f674f49ab20a354cf
+3969f1611a95d3934e148831ae7c81a7ebe3c5244f743e66a82e10d16cc0
+9f8194ea7a596bc5981d833318ab4f7dbf2abce543e410b649d18d146f01
+486159683df61a3f880f9b21ebfab77e908c6cfc79f89ba5f51114f0bf7c
+3ccec7bf0f3b057c3195cfba6908e31e0df10df69163c9da7babc00e9a58
+0fa7fac202910615bd479bbf76fb8068630d1ec21cd2926d351e869e16c2
+cf1e023cf04d4fc61607daefeeedff5593e6023492f00029e2ae4b4a2c14
+50954efa2792f32b4934a768f892171245a1e2f034e2b9f39833f1b331a1
+9a386baacfec8c929ba6b67cd8922bbc9dc005ec3976575d5b0508d0717c
+6bf11123ea36d8fd37fa77a6f1f5aa84d4ad8d25b2c11d1877a6e2f9b74f
+3b5829faefd4f7209ce9785aa6fde68672554a6f29d8bf03fe108ed90a7f
+58690fac399a8ad3a26899072b832874ddb629581a51b3325cd9edfd49e8
+90ea8959db937dab83c777f2a426b967af5888c33a3635b78d647ad6ba44
+1e222c958ea58d61945f781d7ef409771b89b20242ad7d07c2ef592cbf41
+3c5fc89ec30fc9ebee4bc63709ae33b65ee3091cecbe610b847e12c556a2
+79c8b114c3e460822d3330adfd72bd69f54c08a81848c2002a08326cf3b0
+9b1305490d35aee5917908e1604ece75bbe811a715ae8af7ea9c371b322d
+0428edf4c893fdea607e70e1b6f6614947326101eaef18e29be0557d2a92
+cf1fc1505e8b434bc368ce07ccaabc0774f8a63e1073fbbceb3f4052462a
+a9008a1e53f188c9eae339faba74afd6d60f47282cd9ff721f64bd51787f
+3c13b5a6c5a5f78611710111f5e0471e206d72520f1dfa465f4a23c71dcf
+99a04ceef11b0e3bdfc35b7461a60753d3ac26dc50a5956c9195a4f52263
+88e0953ddd03af128a98f03bdfa0602cbbaa20ab9eccdf7255962a332e16
+d4380762e498fda4885c64ff5f9b480da487c58e78943df62616e6e2c69e
+ec8836dfcfa9ebf58938a878f3e792e8bd8c5d6df557a5d82018dbae1ca9
+c64ba5af8e21be1b6680fc5db22422220b776e9ba0bf1ed2b7212f8bf111
+ec8c8c77b223c05eb5e5f1cfabd2d037f4ba0f9503e2cd83f4519d180476
+63f09e308883f5da5228f83045ff41214d2273b2fe0a9017d5e0557bc2a1
+98c35d1e7e81f79654445760cba1d3f05ea4b90658e53fdf0823bdb1501e
+d51da75c47395073d8980d1e3504e3f67db3259e4ee73a87cfd96f84e221
+796573958d364a51e635fc55478c9cbf9aea16b7d8c25f2115cfe4b7f598
+54e24968833ba0d64d1d332a666dfa2a3fd71b05a26bab7da382907b13de
+0b80871df184d3622b623d7e09bc32a4f6ea2e6da450a906ead36d53fdec
+7f83e101fef32f4faec581b000686d86a0d3861c1e67f18a4c4647f51f97
+8484d9e3100b37be9d20ae84c085461c1fbf929c669e936659050c2627ac
+1b019837baa75757f5b0a82e8ae9cf2111931a38bfc94744e2fde3f87103
+42ac615286e4ace7f269743aa05463af537d9416230ecca859d8c99b7c6e
+70be7fe11db698589be9e11900c8e9582a4ef5ea94b5f62820c90dbc022a
+620ec536e06cb8be7526a789996d0e741aad980880a33800a6fe92286ccd
+02c9cb407eb31fb95d9c9f4aff38b37087ac582c1f7b64a7c3d2202bdd62
+e9aeb31bca85c4cf323f03da9d318b91f78fdc0d266630f7444ed068b55c
+05461c97552366a82c2e743cec353d51028fdcf5403b3b74d379b82eb69c
+4380ed40239e15a86b2e5c860891e26781cc111fb5705e3b7c7af1946006
+54b5fa1b5fc54fd0ba43666e7babd2c91c859f393ed49f7123edfb648a3d
+6152f2c17f7e438c0a638968ac06b4fb3f77f64f358ae063820bd33f0213
+c85c40e4d97ed100ec2da1c2e1ea258bf107af675a9d995f60bfa37222b9
+c2b325c0052bb8537d2b27dd43a129c7e8ff42757b3ac9b447703d382108
+da520b8b3bb3e8c7295b776b44ed28f863b8e1f81b0bd1daee8a171525d0
+9d2620c04dd3219d880c2ecc79282dd7b1772a9cbbca706909ae8bc7798e
+6ec7375189b6cfce8a875849176e5913b85a18fb197a33ca4b5b4058603c
+f1fa79a56856b43d538e9ece117d99afa73b57e307364f553644de01edb4
+6234efac13046b6e047ecc8f63942f20097ad7acf0a45c0501a95263de94
+39a880d6b5c5214d29180a54d7fe9b2e627ef49e189b59fcc78745e878e4
+5b46c0a648955d3ea8c935113d94f92ec963f66cf3cf3a526ba71cdf3cd4
+ca69efab08b7389e3390716892a4872bd29dc1e0889a42d7ffb4190e9a8d
+05d84eb9c5741be6b02716bc75e0106f5f94bd3778be985e03860d27e440
+88c3cb2a059debc420dce3a8f4087a9548485e616c409ac400dd1c411ce4
+b6a229d091b253eb68f06e43511ec5aa6eca4d6e4818d6aa2068da1aefca
+377611bfa816b5215182432d5683294d67a7c1fd76c52233087ca44943ec
+7280005e93145f5e7ae50100c18364e1b36741e9647c4dc1f68a58ec4409
+5920fdcf05532f60371780f78420077ef5c24d63e26040cddff8dfd65d87
+1db943f50cde84900c1372ef33fd8ab9889c82f94f61a0e6842219a0f39e
+c7b232cbf802c4a744f33159432e827006c7ca77e480a48a9b0e6a876158
+8a3102e3f98a77bbd62a3a23150fd140d3941773bf7cbba2338ff37b9eb6
+40558a2313e8824e8e620331568a9b76f4897198a709f9313f4ac40827d8
+c3a71f2abff02bfd57d30d0b14012fb5c39b85af540dda0adc27a85b3169
+4e8d7b61f9d9b476571022d98f2d768246550a877293f3ff6ed918a498d6
+a600223e1a61890c49acfb60265867ce9464f9c32c59e94f7641c3873fb4
+fa6eb237f8ed94579957270d6fd640bd9543e683f2372ccd7b60aad269e0
+3a72c5cdb732b128818d41a6ddd2bc139f7d3911f48e1b1d263dd4ae8e4c
+e1a686f3a00a2cbf48978631cd243566e22e68f8d7397134a3530ea3745e
+4f1eacb4d6a5fd84c3011094f37573f7f9902305020c53926716d4780c6b
+0a257bf711ad94c83f1d41a02c1c7dd203a3e6e4b14eda2fdbb36b063a3e
+074495f626b0eea146d22ac33457f44f416759676d2a0566ec2b726d2f05
+40abf225339f02f406d4e7a62e5233ddf20ae7c86ca0cdd561f33c422654
+bf2dc3685ca91bb9d4b09ac8b15a24a99ff56e2894f11f7bb4728fe8f0f5
+b799f74f475d2d01f61b7e9e0e541f7feb8a557486d7df2ce50927515d83
+3bcaa1cd9bf7a650bee9e003a5951c98ed147c4c52f64f692ab281984ee6
+5a47e44a4a5fa93d6f18d276d3b01c5e5f6135ac6940524cd713df4077fb
+4943e8ac927a68489ea52acf7a854393cd027eb52ea2dc6234ef034f3dc7
+42d6db5a67fc21d22b97146b9c268ba97c30161ce01edc69a6a1f05efb0e
+06f22644e1a368f0e2c0c6c1c832878e0614b74bd645f5cb293cfdb7618b
+837fff14a1210aa061c8c81867244305b80daa73cb25a417228e9559e7bd
+52c119b0ccdb7c4dce7e1b9f7e8ebbcb575e5bd213bdd6db88769dacb05e
+5870232f0ef82f448559187423409eef756ba6247493be24cb1879b5dd82
+2e03d0adea1edbdd83d3fc46759c679b921f0616f27212903f728ab44c17
+84e8a7dced0df5625a7d3f48a20fca34008184cecd145ccd98e31b79e174
+cf107e8f35c40c19d86b40baee6164353408801edf75a619ffc5b6faf3f3
+a95f64795cc40c1f89634fd8c13852d265fbcef834c800ab46e3e8167476
+b23cdd8aff6e2f997c99a86a9cb30ef8c853154d0d89eee9b9cdc1b4f27b
+da32432a4173b55ca8d9fb50acb2d886ad8e5862ffd5dff224ba13c8b8a5
+4a7f1a9f987fbbdbc5a3c3d762a5be309d5d926ae5093c40aa47b3b1bd82
+8797cbb9bc9fec9d19eea73d2a39764816113a8edc6cfa6e605ad578fc8e
+30abd600658a49abcd5ac54655d29c50fdb72070169d1b389f114b7c71ef
+95a80d82ab537ac8c165d47371fc142a51625029a990a577eb1618480d72
+6da93c98e5c5f24f622a850cdd94badaea91d4bc32cd50ce69e9f00e77de
+a8ec1d37916398fb7092402605359df08afe7b99c76c2a7c70383f28a7c0
+00c696f45291bb8f074791798197caff1544c76ceea8c9e6d76edcbd92a8
+6df889481f3bbff0865442264f0ea40d3caa69ae467a08003f9c30ff7f2b
+77e767580575398462d5b1171dd441d8986f33bc7bda17d413ebb6b7a326
+42e33f20b284bf3eded002352fc66c6f7741a542155f4a159cd778be56b9
+492cd95115c1a06189a216cfd2e6725965a13de973765a05114d9a5a4be0
+615af8bf6a5eaff84468b849954d15beae1cdd57c435788b331905c01421
+b50f20b184506a0bef746330bc98e9c89aaa8f9d102f158043beb6a68205
+9a1c8b8cf67b2f3d7af4d8bbe086254cde53765e3226ba2f95ae8063649f
+9f94bd9519411daf8a0287307335668190638806e29484a4ffbc1e46b180
+0e03b162c23b1dc0b4c0dd3c7abed2f00762972ef06eeb9bcdc7b3f39c70
+be32789d366f073ac3280c273dff2979507671b3e1e7685a9a4f0fd3867f
+96dd675bf05f25ed986a79249b75f182fd73cda2a6a66d693e4cc5afe340
+2431b2c816da1486c34bc9dca4e2d51c868688a7787cd10abb9aca14b718
+1369de89913cd8fab58fc84519ea2aa14e54b7a8ce474f213e07cf2de2e8
+88093deec937526816b71c96ed75fa9e2edc0f9e6e84569c12bb8e39aaed
+bf546630745553d6084ff9524fec6a7264f88ceb7ec3358e923b392474e3
+a48865564431662988fea768ce555ab0da48bd526a84b0cb17b4584066c1
+640c1023d91f7869ef0c4d701be121a6e3c832010427490758aed7a2b30d
+6028f2215aa44e86d852fdc67da5ccba79eea863bac9edc2535b66ab0e54
+ec4d4411390fdeb8d1fbc1743f15c3b68dc92a8659e7a892d5e53872ea51
+ee8ca7ef51103e87c29a2714e907c79db9cf37441785d2f73a1ee5855011
+1a4d9bccbebf2e39cd3b93dca300fac3ed1add8215301e5766c30c8cf296
+75746c5a77bf1fe3cd75d25cf193de8d9af02af8f7a6e8f84b548058cdd3
+c6998ed13463fade739126d83d3ce2c7201f955382832e32c10dcbcca358
+35985b9a93f8e3b0208be6e92428787c47d3808a0f77b8f1d76e6bf6a17f
+f81cdb065180e03809d03638307bd7bf5cedbf64904e918fc805ac905379
+928b816480f6e3bdee47042cba98539da0e113b1a5f23eaf1a3210bd1856
+1985e6436eab90395da477c7a6d7888d2377b3fc4169368357d880ce041e
+1f7c875e956600db7d9b35d1ee66be476e9dd8064cc02230276829c2c0a0
+98f051502e828a0cc505afd8c3df293da1508ac4d25866beee6bbd5a230e
+9c2dcdd4f06883936381f476ddcd86ccfe15c2ce3c3243e148cbe603b851
+3a7ce7a6910a66a90b7089e5ccd4368befff2bcf8e918bfe0a1b069ab2a9
+14ca7bb91a0ac3b3c0b060fa1a0316f6135e890ee549315897c8464496cc
+6dea0f7e3af43ffa4c3281156067582ca255b1d2e80f999a3ac0402bbd17
+01824c3bb524130f5b82a45275807bc2f3a0655ea208f968b297f98c3691
+92c8aca26beba7dc4506fbd1305e2efa4dbe5375281a88ee2d6fc88fc0a7
+55e72934b4b58f6dd3bdaf7171a4a3c7765767352492bfa9a7758504750a
+b7f38754683b70e9e293cb1cd7b23ba62bd7397abb84d7edb22ef6c3f58b
+3eeaf656e361747ed04020163253d1cf3f905b5e85f83fff30ab2778cae4
+3781667c0f65c8fd404d6b9202a99ea76af9ae1236631550b66b06384718
+0b6dca832ea8dc4a6efdb674b5a26552a7c7d54c2799c7d4e03c24f661a9
+1103086de3a90a774a6988347656344cfba06065ab22476bb09fb68f9928
+c0045f2764af643cfef0516d87fde6dbf93bae2829b176cb507bb99835e0
+1bad5e55c2f8798c93fa35eb3fef02cfa31d3d21b030547f86d27b9448d6
+8e2b155a65c742bd2999daa0c3aed64447b9cc67f7af33b63afaf25f3cf7
+ef86657fe8f952288ca4b691d369e8f1935cda44a180a6767560c2ed3f2f
+cc38b6bd7991d4170c7c566d690a8a25be03212a80871108d18cceff2466
+23e653107631f29227d64754b2208d19f84e547799e691ca473780ddd56a
+e620cd953d5133d135e3d51f237078feebb7371454ee633cfe238aea63f9
+999e32850e6c197687a0ec4e5908d2a18c5349627e336ab5e3185b218228
+603a4b1852069f5ee849d571b8387dce1f8f8e9fe94fadef128ba83bdd24
+5f8c1c27c11f2ed1a8ab2d6d601726842cee744ee7aac6b6fa16ccaa39db
+f5b3b1d47339f31dfa562671a9cf7dde6915fef9f19b3e068a464dd350a3
+ad146d1a241673b5112a4a8768f976723e6e184790c0604506c46591bef2
+106c40789b733331a80740d59abed39868f80becc2aa21c400a0bd0cc326
+d186fff9eb37680f1edc32ac78f9059280d07b5ff2e354fed545129fa5fa
+8f3d4317ff21e027602fdb2522f049bb545ff4da60248130f81f4e348373
+142f3148ded038afba818f26d5b49fc02de9800d894e9239c88ee0ede431
+f8083697cb0be3b497473473e5714717c914a1a926730c249413fea2615e
+f72bdb0906933387a892370f77eebf62d26cd583ee643b02e323821379c0
+dc966407d36ae3cdf646b95dedc7d7fd0f28e95078f12dfc0d6400b327b7
+43c548a0a3517a175a7ed963ed756b1e107ae7087e2446ba702cd4e26e2d
+cdc1a8b697108b5b5e81e9f03105f220c72d4aebc57665887c8c7964089f
+be9424120efdb14d76eef8c6f7a30b13e1ae90cb9d93d2e14bde47f4a1d0
+5ed5b18d32aa39911b92d24c93976aceb7ef597a75161923a73b2cc76178
+5493d0eedc08b5afe95f3c006b41438a0785c962b070de2bd096cb63b847
+c87539880aa3d3fc5c345e0992d7be77c6cff4948617fdda784cc5565219
+2b0ed775129c4ea4245a41bcf3875be319da0ee2dafefae920cd2b6c6c20
+01762f88c0c5c05053025c0349db17104360fce15d7f3a8e30ed13155a74
+faf91dc77b8aabdd6fbd5a1eaf255db209d7f2b90822296b5603fb5e2cc9
+5cbc5f7a6044058b8044adce73acfd896177f1f70ead2f6534dc3ad755ab
+2ba87126d63ca2e9c441df0965bddd6be494e58d6b5057a561d1e31bd38e
+92cb73c1465af6b9c001f7229059bca4104847d1639e124e082f7364b565
+48bf8112d0eb461b316b2449049f6a476d36d6b7c0c1126c08f2e9a1246a
+3b5b21e7c8fac6e23b82e33a7783e4f31f0240e96e69c9444e7d7a928636
+cfd086475df1e0a2846481387bb2010655b9f81a0744121699b4905aaedc
+c84bc5d5ab3674601dbbb651ede7b5df05c8a463dab41f79706d285c4f90
+63997f7ac8cef35cad51fbe5f5bb1b3fa6da2c3abf2b3e925581349728d6
+da0d59c1ef6444539742ee9a23a5727f20cf9377f4f84dea420607015a30
+fb14632d084a2dd181bb02fc3a84fc499b318156b675b9ca3ccabd87fdb2
+497c6705fa70eba43addb6cf961b30e8f6ab9f84e1dd8d6db3314b34b7f7
+aa3bbe19d5bdc75ecadfd8eae19e07b387a1fc586f0f30db695926764b54
+0d89f1d854b0ff86528ad9523caf56371e29498c11afb2f4d5202670c834
+e930103f039d1334882416a49bf93b84fd3cf1209eef7d4994c8302436c0
+794497461c11f5b8ba152bacbcc08af8a15f4a4df3effb7227ca97fc21d2
+d0356c93390c749cbe9750b821f1a7bcfae2c8bc6d9a27f844d8ad088320
+79abf0ead8ecd4ea72846dfeed021857f33c1ace4c07bec90398b629814c
+498d33beb375b9a53da0f926fe6e89e70322c72cb2ddbfb16b13ef7a4f50
+df783316584c6ac2bd7d9029124933133b2229bf74a228868ab30ea5c3e8
+7c78c3f0962199480dbcadbef53bdde45849da857a4fd85b96682f1edeb8
+5384929dee4afaf84c51a09f5d572705673d885070303fdb47dc898f874e
+103a9e7c1e894115dfddad81549c7375d4aedcce2e52c13e5130b47f206f
+7c5afaf1f9ee83da8188d70b473269ca280a6a02de85300b93d8a4f6b402
+fb5df58f1327470ce11cc63ecef2efaa396a6680a6746a20382d9529b58e
+7ce684b39ac00f7086bcb47c2230df0343bed9b9152a61c9826aef9e00a1
+452d91305cf05490d4bc0badc9c6fcbfa93fad52c3a80705a19568904975
+57c0873ebdcf61ccdd2219354a4f5621ab33b11932065c1d990a9b688583
+31ee7875cac855f98563b14ef9e1060bea90f195afff94728ae935453438
+dab35123d0e2699475884ddafc7307a5cc06920f35341728d85965f5ba86
+f261cffcb1e29b429f976970d42d10e6af6c4b792b4384122aef2448e22a
+58d3aa007743c71324ea08d06819fed14ac1f22a4f0be4787bc8738e1cef
+240677571c65804ed3e748d72e89c94b6f310be748faea31ee246859caf7
+a1ea17ccb5b246c87eab771e2ac5d378650191081514ddc2c66878e3766c
+b20dc49f630f2743a7faecbe9dbe9e815a3cb57dadf2bff5ef2fce23a562
+98a30a2e052feaefbd698101f9db992613706693cb0efaf6f60c8bb5e7d0
+a50b3392b9831ef3a304a846cd4af431e9f018fcd3a5b16387552d55daea
+683d36257418aaa0e7bf8a03ed7bab114d7c15119e6c71c1946bd7903c1c
+42e115e954619051b853bf05ae316e15e619a7dee498f771e809d9435969
+c1056402725ef40c0200e083f3ec6e0ec27b8ed38dfe32ea0e5e156ac36c
+4bb9ac5ed111a11678339703f1b9299345aeb1f251fcefa11fb3101cc499
+907dc862b4463d5523b9b25c5b69f70ab6b29cfc1df1ecab8227eb3ed1f8
+82e90b12080ee003714d403ec43b7b54491446b6a3dd6eb641efbfef060c
+45e873e7398025b1cb7065441f1753028f6f8c49a96801c0d598e098eadc
+96a21117f817b6fd6e6947642f93e22425a00e8f6b592ad50b317b69c0f9
+4047386a45e5ebc9504fe55451a01eb29ddf9a41d4bad85fc84ce280971e
+834f06cef49c8c20ed2ceac889f158cb14a8c070900478804cff1d1637cc
+880c81aa287d8382837ffa8f41ff3c9df2f22cb20044c171e4815d0d0f6c
+22d19a52114e780cecd71daf63427782e85e463dcb333789f496340e8cff
+885a9d9a4250118b439c71c6be51a9338be29251aa794edc67deec6337fa
+63ca9b03c1c9f75e733a4a918646e7bc9792486cb5a4bcc5f84fbabdfe33
+8c3792254a3eea3d88903c2c47b91e076259dccc8bd3dca90eccc832c09c
+45141c6242026bfe309029a562c3ee0fccdcd40e5cf265ed9c3de582884e
+0e14819db98b3af734b1b3276ac41d43384ebe73003d15ce39ffcc041095
+83390e470f431b4407f98550e138f96c4564b494e5480f47c853bdd237e2
+7301f55e42a3bed18fada152572b7b465a581dbfe7db2619365cf16d71bf
+8f091862b9fcf04bf8d0859a76f46e7b5712f2757edce332d3213b8a30ac
+2ce7d7797eef6f30904906b0805dfa7ca36d32a20d989858497a66ce7249
+1393dd79332003d55c095a5ab5df761c4be5c041fa8407263d604e53091f
+7b6b15496245dbbee96a63f10fc2978d99e6573128689366fe8b0bada48b
+50185b861bad03e3600f22bad4274f2542b635f6c7944befc3bc741bdef1
+1a8dd659038cb40fef2e16ad1ae7ebedb7d9ba15fdcf26355331505a386d
+d7399fb999535d6061eabc61dd76ef3eb457446f29d0bb6ec2fc0aabac20
+b27a3c123c27bc27a76336d0a0a6d456da0703674d959a4afe428e2206a5
+11bfc80039ecd56e75f69786da0a8084d81a66644dd98b6018681f1d70ad
+e09bd9bf3d16d68dd5d0a03ae26dcf1552549e459fe190b310a8776b2c84
+68c14ca8b1b9a7af2956507a3b705ad75a17a0eea7fe089273353cecd07b
+b8563465ec8deca0eb42f43fe3664eb5f31e1d1324185539b28d508bcd06
+5ed576d8814ed3fd637d576f027927162344afb0255a91ffc616948e4e35
+8867e9fc76a9affacaebffe110808c1532a2bbb0dbef3f010e45ffc73f22
+8d28f12e98478b27397d8f456781ed9e19711df2e9eecbc3fe61f7493fdf
+1a59124668a91be51f122f93dca4bbd22deea339e6eda3d6ebee03df9581
+13e1ca49c8398d2c59da6764882ee3663f62a55ae50a7e91b4fead1b11fe
+0d50accc5d75f1a515f0c53616a500f1491381dfd0e2477e402ab0cf9f67
+d501a442629c8593ed5d25a72edb9746b02f2b0f0759cc9cdcb4c9d8b451
+9c8c617e569b432f0cf6890372aa879ca7de46e110d95e230a4f0e52cf65
+811c54365df4a3e40d819e2fd379b47da3233d0def0efbce04ad8baa3888
+4f6a69fe5c373e38ae0fd0241480f2be7ccd18af85916d2703a049779fe7
+398fc47d348454cf03f22eb3fecc064606957898b5643464845445c25c0c
+7d685c8db042af5d5882174374ace90081c686789bca96ac602eb41d317b
+d652293ee628951875641661ec86a2c40a42e8f0813a861d41a0f5178e55
+43651ca0e99150462db5ee0010f00de6d55b0d7fd7ec5baea24ed3e90a7d
+6a0589761922b91a6a913a7feddd3b68254d89ecf767ce8e27f966426a8b
+4fb1b4085384fd09d63e288405b78a646f44c87eee22c8596b1318808547
+9f75f63d3d97a28f9c8306fd207dbfd38dedf0ffeb7dd80b2a3292dfbf1e
+d605adf1b33e85b010309e3ec058fcd922b1325fee71eff2dbbc2e68db52
+d513e024c01d47cf657bb61c9734649a4ab63c0af4720ec3efcd82dd3ca6
+e80bb63bcf1b8de810a0c6c517c63b76fe68c0b286867be102424fc31c49
+37048b6f323d039618586fc21731005d949e7d802a430df8d2f0ce99f2a2
+376c2953efc4184355e4d12f422c9e1e25c4df38dea334dbc89b540e14c6
+1a7769d77115ce8968fb76b27d0863cea2496783114c24d4cc816da884d9
+53da3f9b9d3af8938bc607bf26a071956ca07e6a5509ea2f5d80e5cbeb98
+041b197fac760976ee75b470dc20aa023ba3f63c2876eb281ff5173bb490
+d6815604517aa1b1fa0631401b3c1a04ca103e2ca4eccd83874d9cfc8abc
+134cc0f9141d9afa56848bf222342016c556c14b3482482dce5d0b6ef1ab
+522aa1812bdd8dd3397e05327ec12748fc4808429b97202e24e1de0c7c0d
+272c046ba73b37d30930c5de5a47d96955cb0f5ded8f3ad929a8b42d2839
+0458f5910a0f93610f79eddb27078943dfe17c716d65f96589769349f3b6
+6ab7b8c004ccc59ef6881f745ec7129865a76f9c2d029d4660ccfb4d5f9d
+412ba3372a27cb175e9d65f759575cf14a5899a8d31ff039ac02dbd8391c
+3397428ac0d5717c005200790785354813c8859be90e0e17914f6cb9c674
+f1e9a9648657b54e5e1f52756c4f982df74e73f6e4d40718c71d1d0e2420
+fb7462fec9e457c0414a96e475c6be2c10437096fca0c942e995a9ada789
+ab637b648781d32dfb68e62e91c2ce7e13680f8d31ecf8c824885fa76189
+81cd05fb335aa111b409c59ee337df4e5f9dcc920a5fc0d620dc07f20dad
+63f4ff5e0ee5a2f390af1c32122ba7780f210229e5a5e3ed97bc1c3cdddd
+456e739ca782edbf4b810552368e9c734b0c78b0b8e3f8b2dd782862b743
+18871bb1ef087828cc173d7b049811fcf598b8efde4d9bc5447f4848c980
+29c854f3ae461b9d46ddad8ce67a521f3c811a81a396cb0f80f3c8d8ec88
+30532fb7f9624f7cae0f8c6df875073333deb28aaa90aaf486ab8c932553
+ce697b885e71ec8e40c7835cd5d59a2c695db9e51216ff9b77a15b0da637
+17ff25b05b939e45cf7fbe490e51e9344213b32e115c2de14d76dfd58450
+88de645b0e75042a61d82fb1753c445ad0a956a1263e5a096b681d3bc51a
+9ff32ebafff7eca8b59d40f0937eeff38312ae57462c7bf3b1fe24d2ba8d
+fe84515270e09063ce3c80df4935e409f62eb4f54af16a186d4329972b9b
+df15fb08461b688ed49928429226cad9f67c9d636d1375cbb7b08a563195
+6b7fe29cc9efa8d75c9e4919c8c2c54f401d2e0d7bfba40c50cae214d210
+c6f3ea5802339f63fc4c1c1995787617f3ec2c806ce44cf8e29f76606cd5
+836f6e5a2e423cd791becd3f112f25657dfed9366fc4adf90b685cce4a56
+98e5fe16d7542b913fbc01b288dd13f43db2b1ed8ccb80159dbdc90a8132
+125df8df547c4851ca609d1f6f4d647741260e845b457937787827a89e37
+cda06bb191669ac84b8608eae132d10177f3fc384980f3a6e439b048a38d
+0d6b9cef09f3f2d732aa71bd058169d6d0f8c9d146d9da046774027559a8
+b3843f6116b418427e78476ad8f0f81e8a6b12098060ff7dd686503f972d
+6c42fd6cc29c083ac3d72e3751f21d2e44a572eec80e81ee44c90faa7afa
+bcd3eceb98fd4068f6c3a4ded0e6cec523c9a0054d1fc2a8d61a4a26f9bc
+250b8f302416924ab22e722297888b85b9c12f8dfd2a744cbd143f9b2514
+c1cbe988d9cb4e77d90b2efd5c2a528355a35f7c4af039c7d1d756305967
+b847d4acbb81263d4992c001e2a262b9fee2d1f5022be5b15e1d8f1d67bc
+52227344ee912c018cb73e5f47ced54fd202627777bb77aacf3ee6b22706
+fb2fa9062bee87e22cd2802e7706322648daa0c624ea885430175f746e1f
+536f9a8e1c610c4a761d07248426db63c9319a88a3fa449c3fb8ac94c600
+3c745e6bad717a3b2ea3862d1e08512a98e57772a62f85f1e2ffba40e2ee
+43aec11203da9ce5afbf673436f2db6af85bbe89d802f7a9e5fa25a408db
+69e51f0577dd26f94cf2ba2fc53eddd6fbeb534af15f74f66ef8d14e7ff7
+7d8a5d284c8202dd5a6053ceaa606bf9259923825ef4effaa8d878652a4c
+af2ee43ed26bf3590402686c876f86c1ae95046e527617cdd3c429bd4cc3
+f9654d2c76dd4102471ff746fa9fa379b16df96bfe3836d43fcc0b8e9512
+0c27370049aca4ac313e1d50d72d1814f2566b8b29fa9c9c20d048874372
+2a766436776783b939171fffa00e04805a8b58214d4f114f7b9c3c17ce74
+86aea2bcc895ecde809502bde57981318a93f23016f056a421b733c4590e
+34ab08bb348da4a48f19b6befaa1ddd2a49a6c440443028333cdd48c85cd
+698adaf3fd8676739e44400a98b575be02350576f96cfa54d4184ba47555
+b8d12374b86d038d085f7fa51ff4be2ff5981408999b48b2faf305212ed5
+4b2e371f5a0074cf68d1b0e5cd279bbc8bbaef694a89a6c43f518d01bb4e
+8402aadf34e96e9b3fccab4cbea2741d3fd9adf7af32388f7771845af999
+65a6078f4da335efa436be36903e33a743c112c0267309f266dd44fa998c
+9a139704e400b89dab952eecfe2ac09c82d9f4975371ccc27da37890ec84
+123193314d8a7a707c217ffc951a547ee5b6d1b7c8ed85bebd9d3f4b9b09
+6a78e5f7df88c931e3f396973974454e59340ca51dbfea1a00de084b6463
+0e26c6d6a3593b828814e27db0186bf2a87eef268aa1b135ac09b52cfe53
+051cbcc88cec5657bd47f603c8e1a6249161684fd9084ac279f57a4f9bbd
+0a546a87e147b62ac860911969a29b8aa20e3aaad0079d64e6bf1b0f2ce8
+f0c54c9019207e1b403358253c2fa93a662f63b9380b65c5173c198d86a3
+d0dc1800d1f5378da39ce8523eb62c6afad8a0d7ad1629f2cecad82b8fde
+38975303768c7d3a08b91478edb3c45a8c6b7725ea8596a8ed50b8355fb8
+52fb8966479d12e1086223b1e6523a65fba81dd106fe254f7309718768ab
+009ff7714a8c363b09dda73cd3f81bf9c0cd3b0c806cf3b7bbfab73e46fa
+cad2480eeba97ae68ec94d3d79aa01ecc22067858effa9d7b7f997abd2ce
+5aaa8781e5499e8580c405681cc63eea53bb47e55ecc5ba2a7a3c5472df0
+34b022f455c60fff971b01583a29e211a87f7163187b190b0c1083d696b5
+86e9438fd8baa45101a5edcd1be5ab9a585511089ddac8df1b1fdbe582ab
+d945e67f99adc4452988a9859e39c90ef794c5c4e62997085b7a16a0d901
+07d08610ba175ad66377345662da7da4d8fef847ee5d57e3ac54b928a095
+7cc1c944e7ff14658fe4a641cd26c61105c0f136a75950764b69ca17509e
+3c19351d456b22c87c55e8dcc4acd3e150d936333ff36499ad6b02b6403d
+e0f12901301ecb2eba10324ba72b58206a13b8f37b0aeb12115d0c12879c
+8ea8a2eb70e85c95434564ba3dff481c8972587eff74eebbbab14fb32b8a
+84b8fc42ebeca65d25e8c32c19ca5962832bf45dfda4e871508aec318495
+0d6dbe89019cea29e40484c36e33d76b756255531add1db24c03b2a64a47
+bd8fba3fdcb1f5b96f8eecb60d5834ab001a70740498720afb6ec03445cc
+35b51f7987109618c6c78cbe3041bedc69b6fb128142cec5c8683b558afe
+3024eff7a12d04ef59a72e156df11d33aba08a8eeb16259dd9529cd003ad
+4ef4137b6ff1654236473dfb93f597331a5e26c7796f528f65c94fe07b3b
+4f4dd49034fa0cc189dfcdff70c2f1c6d3df30ae103e2ac5cff20664ab93
+4ce5c19693292071c93bd590383e0a1931e04d1ddd18071dafb628f5d747
+2e457bf81d6064edfa8debff91701c5038cb30865d6122076a336732dbcd
+b0a625548773d0013648a76f07bbdc9c16284d158ec7a105ae37a6227941
+9c3a2f360d0c7a74d6fdd0e36dca2a8bd59945a4196598f690878f84c894
+852c1811afea4be3b9f6a5219e6628c66669dbd8fa9a0cfc2dde7716a356
+fc4fb271d8a2cddc8d4684de447355bc7a287dc56852a638c5777826eb6e
+b72faccc86f80beddd0d649a883cfeef4d74750172a90b5dd8252592fcfe
+19ffaad868e99562daeae70514f5de296ef7b57e6f193737abb6aa317956
+584423817e11664a67389197ad9f8f771ea5955198c9ee40a0761639e638
+ce9d890df468642670235f1373d3ac6b1f43b5777fc0a91a96e095e89bb9
+fd62614de456ce7afd6b855112367573fd9fcbbd4a4f9c676e672d62ddd3
+4a9bfe8311b6175a003cd143c0df15e4c0b48c735404086e48aeed6b6fa2
+1fd9f40b84215dff287f0677904e2ddfda774a4019df45cc877f553e95a1
+c65df1d67bc0c60e0bba4d205c0da3da80229fdd71859f65ad04506b308c
+2b783839f31cfe4425263224f08c5c7e98a2c9d3dc8ea5ac1920f4e39541
+3262e0836bc019a092a0deca104eb2df6b63392ae8e2136379140de5fc98
+b0b69860fe8e31dab5c5df7807d19bea34ac14e0abc6f6519c51247b104d
+e7d912c5bf6ef11b48fc6df84512e9f5febb48f72ff1b722bdc3bb2e835b
+2e7cc6324bee84893996b8dc2d4dc2793a4f69c18e63daf04a7bb5c0a907
+6e2d5a343e134cc3c89c4712900656ffc202e1988526d80c7fd9281fe47f
+ba8ab5d025e63a84051f6b13167bec15b346212cbd051afe7a98be3a2491
+f3c469718a58e783ed91f90e274fb4978f8719e92a99a1e8f142ea7e1f2c
+46aff0a2fb50f4d105130ce8ea309b0e480dc8f80d506172b609ea4bb4e2
+bbae98d8882814fb273e690da990b60a9cda20a2418246bd10ae67d846a0
+fa815ac25858145adda106a6778a11877fe59a2abe300d7db9bbab31cb5b
+960b7e4ef91d4600886d8795dc361cbdddde05ebd54b1941f426f7fa8399
+270d2f54c998be92d146227270a8e89af90c48bafc4eccca01e6322afc16
+5743475e752f39bdaec49297290510ffa264342a0afe2985f85deec66c36
+eb4a1d46683ee7c591a89b81569a8566afbca26810ddb0970577a76ec8a0
+66622606b08315db0f2e6c671f3259c73637d773d1a180aad66adada2a65
+95b5f481e5f59e51cba876fa06d21e1d674cfab46a02d267e20234324d08
+91e7847c13c69bfceea3ac55f2eaf753726bceb0de1eecf42ada964bf9e4
+75953302c2fca804b70b779482dc9319b40381e09c0096460ae113c19a2d
+c9157fa138cf0e7758f71008e71d0f7599744d647b09b16e3c795c56ee5b
+d14d8d63e7a512900d67487975ec9ceaef69572fc3c2342ac5d365e8a4bc
+f462006b5268ecc1575494cad9a9e7a9e8d9affe49af647c017743ec7cfd
+5e66f4e4d845a6bbc836849274fbd270cbf263f167df7e26ba91f21c60f9
+6257c07523ac37a2193010e976965cbd75751e312817c0564e1c5ae0cba8
+bd12b01122d07020a0852120680985a8ac987bc33be863eec52af13435b6
+e4048d951f5bce36526e07a8661cf2538f69d1f223bc53bf5896437d1bd4
+6f57d9698f642f0e99c7392d8ee47134e34dce94d392949b418d9821e12c
+afa8337323e8469dac24dadc6aad4a0dadd7ff65694ba3a27964d28d8eb4
+1179458f91cd3f83b8f119bf5e76184dd29cc4c0718cf7945dcecc993a7a
+78739363136cec7f2fb495eea8cedb3ebf14373a058758c442939d367744
+35554851e9519b6f09c31ef26b6cd997dafa11da91fa9759f17b7079164c
+5b47b99ccb7a876fbab1d0d5d1e1a2683cd6914e6b3b755939cef1c9168d
+30b2738c4349650cf86c90d2542fc9b90f36a494c035a1c86dd716014aa1
+6e6b9ec7aa03b16554bec436511dd3097fab1fd0cd49edab96f74e8fd264
+00fc748cbd9ee1eeaee24da30db6f8734b52818b3a5e510aa5c14e420608
+98033e7e36cba9a64042cf94a74e4b52e37ac027c0dc69bac4944cce12e7
+ad81aedce642ec34ca23e3ff07b8cd35dff19f33c8d4dbb56a52534f8a82
+7be47ad4aedcad83b27338409fd1101c4dff3f12d3df79ad1fce65b2f419
+451dd059c88bf066413e23de27d3621dac2dcc8f9f3620dad0f4b1a6e8c9
+e6e8adb552e1eb2c4b2a3b73986ad53ed9ed8911f82f750df05cd2eba3e1
+b0df208a87fb5ed44c3296b803881c1d9776d13350cd29c3f716f0b5a8b8
+557812024ba70069be6589aa579eadb1f657712df2570843d7c5ff7f4009
+d4d232d3547dc8b92ed5c4db77b76255e661ff8b163c6f3856de5651b597
+ec7c78b84f0c6c1d6ea3a82286f1d3bb45f708d564e139e81f473c705ab2
+56346328daa64d1ea8645dc10fd449092e0634d9d7344b2aec3c75f6b6cd
+8b3f3867ff3cbb0f556b186ee9a7c26bd2d17c8a773055d9d5013bd2f937
+d697a770c57bdb36d922cb911cd14e7fa14160be19c1a052e297b1a2d682
+d4bbc9f1d2493bcd7cad2fa75d904c5f5479179daf7dc6a4e0d269baca2c
+4f2430b4c8cf1572fbdc750a05dcd5b09fa3a9cd6f2f2a386e2b3d4d8e25
+7bd43a783b38e63bcee503ea96ff2c373181744a607f0cb8d281d7db1a6f
+4076aa3e2c61914bd796ef8a0873f79f964fde28b792ba99a20c3f1f5ed1
+fd189fb1867c84dcd6af43d49420c8b1f3dce7dbae71deb17fe45644db24
+4f44b1011c7c768ebb7254f4daca64e9ba87aa7cd0f0c4b2228ffb9ebdcf
+3dde4dced39399ffeb348811547d025320a88b480943a339e2cd2fa3605a
+aae87939b1d7901465a1879bcb4c5be1a179e7e371f1ba2e0844f88afbae
+9b78dcca47ae8aedf5bd3d458c7d4a7a08accbf880d1f1dc69c636628df1
+ebdc5c42ff88ff8b66351f3f72d703e52f3ce91e4e00759753a599fdd863
+788e99858498b66b93e5083bc3501c39a9ba928b0d763c28826fd237e949
+ef0ba85cca9aa20c405db6d5612db718f7b4ad31d253ae306e4d7cb615c5
+9ae668d347a4e60fff7b103f8bd0e7cbdb142a763be88ab40eef6b8fc200
+458d728930ad0f94fe52acbf0657c4907cc7942710ab1fd8bd149a9c9def
+6b8dca7db9062aa7b1b011abb5aae8b77893a023f9eeeed4a20fbc30f922
+282a7ae2f1acff64151013d6b8ac2eaae58171a10f80bc18c3bbb5de1e22
+ebe6033bf83040629023d74ccbab3f1923cfa4a6735e1dfa8a1b261fbf1c
+397e26f3ba9c2629cfda84dfa3d1087ebb19dda7e2d76e30dc2e15b8821d
+5291da1dfd73940e5560a8a6dc91be0075e3ed8d9e8cac85ac20768d868c
+d2dc45deadcc8b59aabe6ee5b2f891e0d7cbae820f83479332bf97074866
+98fe196c72ef72b52f54314329fc498171782bf160e1110a19b8208fc591
+ef0f0da71af657b43a7cc649a8488b759f7b69134b4f9dcf79daebc1ce52
+cc8015f324c9d46320f44e1551eda6d86139dfd1db814cf38a22a89fabb4
+f75fb896b00e769820f763486e86668253cc466c1529a5a924cc337c4844
+8851a381dcef63a0a302b65203d6571a1dd1fb9dc0c3bd6aef4891497033
+109ceb5a481bfe442249940ec54096f1d0f2436d9e60495d0acff967a741
+b30467d24ac6b003221318666b951efd45324987b10bef4aaa0ff1df6887
+377a7f70f555dfb9ff1001c67438a167a00b05d2c37065655173a7ed9ae3
+42dfa1497fb1f2fed6098901249a085d31b66dbb6ac25ef16c106b0a6ff3
+47cdf66434dc3f0012daade80b942d522cd59af4c31c1c062157b3d000b9
+cb86e2aa7b4a5bf316058a0d5a148eaa2c67977faa0966e4c3454e08df14
+c2498ad76e389af65d2c139a6d8675298c46aceb7dbe6904c373c06e5f71
+399b2eda0b40ab96e8be991ddc39f92f1d24797f9ec9f2fae25669b43754
+e2498e8ea5c44b176c3fb3e8f7a7a1481275a461f2549afc4cc73e28417b
+d8c5212c13105eab967daa679ae822b9b75b372a99c7e82d6bd83aa2ba00
+314da4ac51b9caa30d80507505be24bad0a87c5d5d7336edf60cca4cec82
+01d243c3932f74d171e2409d789aad0d04a7bb22fb6dc3ab92ae33ffea89
+7c484d741039f38c317ea396a0fbb9f15a27d87fcbe007558799bab73212
+b6e5faf2080ba074724eac87d88166dbc1464cf5d41b99428851ff1d9924
+6944511cf42c3f9248513e9e51593f253d89c604388ad7132d6a169e9dd8
+88e020ac1f8ba606f2e1ebb97977e505d8c40853653d8f398f71cc9f8f9c
+540c22a1e6195ba578ae7262fc845fccf77b33f33eef266489af8b81a615
+d6a13464bca58bec16c23f31d678f14a938bec31272dac3ccb1b2dae577a
+26bed852fc59843176a5fcfcfa0ab7fb00d2309de55c82cb9049f44fa61f
+1e313205a76317c4cf529a4456019d970624129681f46a9cd7950b8b5c40
+61853040113c8115319e68b37f88d864c6957df813b305d09e6a1716b10f
+26f2ef5c727fc77aabba73e12b5ae6416ab19f6563ce14046b715bd4cb2b
+1e4d315f42d10f74cdede82bcdd524a1a54609219084cf1cdabfe72cc837
+5478b41614bc18a914903596d6fc2f361ee519f875385f4ecb50f7053127
+4ebdeb14a5dbd906a60817246042e3799bb3ac647cda7244b7998ae4f3bf
+be5c767fd2142e48518a4217599e0ec2cf5e86c8c270ff8b02f949ee001d
+6a439bcb4bc7d7f7c8167c3ae0a7e59687fb8bf6f37beaa164541b8eafd9
+2e9d152e3fd0f413c99ccc34fcd8aa455a0b55dec846a5874b94fc95cff1
+bb386b2a1e22cd1c3914264b6d5bd1746972857c9235052d77a6c0dd3019
+f8a307fbee63a3ef12b039b224108276ffa84021f1ac5b745c54690b3ff5
+87b4b1710ac3533a67bcefc503adf1f4b62b2910b31965e364eec9cc437c
+c40181a7320cd52be9c546b8f1dc824312216c2fd8232e2bb8d40ee2e314
+54c09772a387f9520e331456c269f51a078e6abd9fb6a68bfd5f557215b0
+bbd2227b8959cbd1bd4aeeab094dd18e891c61fb00933c0a0d76174d169c
+0b6445d34c00dc9e06d85eb086c18f3be27df734ebb9cf078aff65144385
+49cbe92a0c0d25efe4a527d86f158b4e9d8870c7ac5d6c059643a3298079
+cc20398324ca87273b86ed801057d797d91bc3cf2f96c650ee1566cd3cf8
+656cc577d38b830201be718dc9a494268177a5019546eeedbf101996be59
+3631654b638c75a6baa648cd1e7aa9ac1ea60f4cd604071c89dccff8b3e4
+30a57ed6de11c5837e78956ed991058f3646219beae94e4d9381a33d48ca
+9b8ff12b54a73ff869d0eeed7e098d80152295e6016cdd809173c57d1f5f
+ce908a37010ad4c4471a53451de9b4363b63437c374c598f548f145d3d28
+8f42531fcf36a9cdf72521f1c0868fceeeb1857ea983f6b75ce245d875be
+ad1bcb8819e5464518e04717b78bd6e335f0ad77b832af5682062a1e2ac7
+7cd5edd5dc372ee456c96d38bf8bf348dac2b4ebbb2440f2ce97b4b337f2
+e23247e3e8423bfa9237ca6ceb6fb93f960cad894a96f0371168a3322205
+2de9b3be04b022ab95c0c243486e35197721fc55311dc55f87bc72d09b6c
+940ca36e6640aeb66c394a5949a604e7f15dce3a008bb41b0eef2840a357
+f348443b4dce064b4c15e5ec52e448c985faa1c3d6526270b1cc69100995
+9a7620c9a6202619a19be410ff7bd535a8b2640aaa459dfdcb8f2bb35112
+626497e8a397d4f9e04788322a738dc8907cb64315cf63c95809e90d06ef
+02f72ab04aa61fe02eccf7e9049ff9f3ef2258a75656178aaac9f3c2a26c
+001341862d526cc14e92a81bd63502f959066e0bcd659cb9b5a45606153d
+d77039b8c5d5b13565f00d95a41937cf97089f3938e39659a64dc3d6046d
+0e9ef66544caf8a206635df49926a3eef3fdbc9dccea2886ec855f1821c4
+b9ce1d02a19a11bbbef43a7d4d536715548a62802f64af30bbcbea8c7e55
+ad56c801d8a569c8183615a78cd393ca42c103f155941e845712c335f4ac
+fc7807202b92a983111aed241bbb8501f15560e8f2157c29752bdcdb2740
+08137277920053d6d7dcdc626a574a82a8a34f1e77b2fc8cf7c1a7322f22
+dfcb450259eb450c52b70df3584a7c54c813db41e3dd81253a03b02bc252
+346af0160716355797b6f8210c453dd7e1e756ff08c7e6a5f4f87605e1df
+f35a130d79148a57b7ad12d94a129fe3f055cf974eba09a2b13deeca2e02
+ea818a58b81e8743004646c7746110bc61b86adf2d5d8c45a6a5461eb344
+97fccd09e711f47bfa742c73f87b257b53f30cb68d151424dc3c210d3e8a
+c67c2495a8236ea2d7985a5e1deac699d7b700e6d38eee2e93b191baa5a8
+a2c916d206c63fe63427aaafed2b5784276fc21eeff2d70e47c8540dccc3
+e00134642b703795cd3702631ae2a90e063a218b61e5b89bbcfff84f567e
+37a31a9b349717a8cdb9c9377215ba838ff7469bc486b64ef2b6d92519c0
+bf0826e3652903f40e400689f5749df86fe3de178e21e20edf9053081f65
+10d8f19acd021cba481c484d30ead3b84ed0190087ee478a17154b243346
+c3938fdd5340cf6e47b185e64abdf44f8cbcdb8294492b91929bfeb9da2b
+033c3acee554f0f1a7f8a56df7c06a3583c1e9c5ca458d40e550fdf3e2f2
+e7be8312d5fee98543388edc8a04ca29f1b82b7ab4adabba3f2c331eff35
+21b2b92f99c4377ab827a989b423750d36addd2e286e7f3b694e29b8bc40
+3693c6f7cab5fe34f1e48c8d41b47831e8c3f5be5ed5142e3c44acf5180c
+d41fda149b1f4aed36812e42bc184227f5034220f74f67830255e1caec12
+66defa358a87d2e3b4b4e7ef30181570d0b2b43072ee0311c2c157d32ee2
+bea8ea4251b59f6b61d2b4fdeb654deb67aa3dff4ad65b727f0d6b7d6152
+3e4b44d99ba5cd33540f340a35ddd466abea4e72e504fc9baae51d231c33
+a8ce7dc2970de4c1fb5b096a3d9c641ef77dc9039886831ddd01c4f21e6e
+168e38bbdda5f4308c959c7bbf36a42d042da6862937eb20d4fa2e592774
+1a58da5cbffd9553beffbd92e6d64871d8b25d9049f4e71970a8ff5557d1
+de83dd24286d6c3e4770ee00f9a1a0b0063c99994aec75e84d6f9c488434
+d1f3dcfd0a8bee9ed8257ca97e75e8b1285747184d6d2228ef95d4a0b8da
+252318abd35c8398fc6568b294d90ab308a7675f9f160140f0a08c88ad0c
+a1ca2cf85e4d031cfa3b87635f1398eb7dbc666a259f02db6741d13e11b2
+30025dd6dd64c438409af109090058151e4dfb8c0e9cd65935c4cc063cc6
+100fde70896e23e3661c7fc1b8228b26a55903e997f80207edd8863fa074
+ee4ff23be585baf708040c9f8cfdeb42fb8eb71d4cb6d7757e973e4d8c9d
+dd082712c23f868e1135ecd91250bb4335958b07c12fda75eeb56be19d16
+44c1f76a8811c021122619f751cbbfeb1d3dc912999017fa163672a1ef75
+4c5cb78962baab76ec48461b492fa88f9897170de857cc8374c8bae417d4
+c78a56047024731f4a45145f0393a27cab614a7ff747bbc28e6880d4d01c
+0a6cf317a1de5bb5adfa4b5fbfe0c57598c79f25ae57bb797a489d51f85a
+9b9cf8bea64293f8fcc43b0d5484df99dbe19152692ce756f6fbe8ce5831
+cf4b8a5af47524e272c45c62acbfbdfe7e60b05bb1a1a6af0e9210012014
+69b3dbb49ec7b23a363fa68417b7118dcea71d4aca2e36f88c6ddefb7020
+5df3ab7c74cf65cfd01ff85faf99f172689737331d4c6cff7a29029772f4
+87fbf625f17bdad89b4ac076948277b4ed687840301016c2b7ad4c6d02f8
+1e88c75b7a04d724e234e38a38269351582245e361a42c75b8256afd5624
+b558ada2190f960a896bbae7a8c57e76da10dc29e69bbf3aa86214c001a2
+7b39c1d17c548da5601e86a5cf53e7b1896bf003aae9387aba9b102eb1e9
+002dd3754a378f3e49f2c6eecf47eb1bac2cfce11ac0c5cb063672d32733
+563f3e1e891b6073739bc53aaa0043fc45e90e413dfbd4548dd320b681ed
+70a7443a233d79e3f038d26975586e5cdd2115aa614727b1f6dd4024b85c
+ccfc79d10b7b6afa789db37bd0e8c423c1a4a8681b5ff3a9fa1f61a46e46
+c4b1836d1aa41a89264a7f4b1c259e4b10ecdf375bd26a1f412fe01fbdc0
+3368fcaf48aa0ec28b1bd603a6a0d0dade66d14c9b7285569230fab76803
+35be104305e4b748fa99fa31f23991608dfdd2097da292551136f255051c
+9f7eef3fb7c7fdb4e651c3d03a4ca357b587245236f4ff3252563f6be08e
+f8a3ec09be2bf27b9120f7d37801f6999efb1c8ad1a08698cc59ceae2cfc
+dbf6bd8f94dec94f7ebf33af05f52c85760c63950b455510c6ab9398d09a
+c288efa09e8f631a59b03fbbc75bbdafd675ffacccf8adf71e815a4a49f1
+4bf70e42db0b7347b5284e234c24010e2177dbbd57648e398fa6b54571a3
+7ba8c989503594d03c6e60871a7f96459902215402ba168b8d1d2685f5cf
+8645d5e11a1769473027f42564c2966c10c0dee1ee1b6975852a4870d492
+83a470e623337544a7cda5c16fe2855ba2a548511fb4d4ff2e3e78d108e4
+c734f64ee2f12cc9562cbdf363efaf5201b673ad00583ff108aff6b68055
+a5f299452d176eaafb92c84f114c8c22a05ead6564a3371420ea9e646308
+de97d40705e1638df08704fc90249cbc0d2d3e884a4562cc27370b1a9738
+9d8efd237e644a7370b8b38ed1c377f522c75f981d878a5e87101e621df9
+d85c7207bbe5a87ccb607f93a2e52f660e05c83a7a6ce6d01ab4b62a1ef8
+da47cf97d4bba0fa8effa9c0f61a325a97ada69445f23ab1fe27a66c2716
+39f839203040d44b11ecc6e805fbe88843b34c4fd52d1d3c6c70ffed433f
+c04501fc20536abdffa429b8dc8192b2d45dd9d646049cbf40719c3d6747
+73f9676f9fcf32817dcb55402a72c56d74aa4ce4035687c730b6b44a9cc6
+14bca5a3fd17c170ed949e588ee45e89e18b07662a6327fb9e8475c43e5d
+a1b0af07c23774b19c9ef59281f5d884990d6194170d8293a86db52a0fe1
+7e88da82209a00a16bd29b8b2f13fd60aa25fcfa9745f57c8216283c1d6e
+a1c119cb9b8d57c004195210ffbd56395a3ec2d3098ed38f389efc0324fd
+0e55ea339b3892568229d8d3e205a821e8219fcb1a7713fcf3450f8bef97
+6ca0beca47376a8ca73df85b340c67efe4534d459617996526b5e5d3d19e
+17cc5449e5ef2b82b2c4c2131ff8a19fcfe6a186a9840d872d85c40665a7
+a04e67ee26b8bc9206c35b44c8f8a1afc3867d96dc6d48bd45063be25b88
+2e9bc0d0948c18dc870e6925818e1fe17d336217f174eb4481f5c0ed37a3
+beafaf4d46f857811b6728bec461ae6468d87a736572f4ff95b58b04564a
+9d3c22754587df15495a319d822b838461764b73483c1f7cb930eecc6f74
+24841ee10e4087e951202fe88a391375c96bec4480328a54740213f74110
+5b12a39f19808f3823507b88115d468c61b212a8abae7480e39ba52390a1
+892c7ec50271156b4e8076fc3ada222695df372385da7b117a29e04cd2b8
+0a320f186d61c963fbdafe9224e537057c49e82e405196aab621b5fe4011
+e1782a747ef935ed8bb11bda39a141cc0ba42d04ae123383bc95a1d03a85
+a9440010c3b9613064ffeca76197e10919ba5006f35837ed9bcd7de5e6d9
+68aacb6fc91178091fa467ef6fdeb728e17293dc89dde5a5261faa95a2b0
+000fc750e7073900d4d88247da464613adc2b3903a6132d96ac0e1c56438
+5ffbf6249dea76bea2a99160632dd2fc2b99133e9f2f470f72b45d6f18b4
+5020f604b06cd9174ba3805db60eb9c5e6a9c789ace76ae9c79c1bd34434
+e95e501bc968633af93ff4883c6a596776254c0c74993710327086b2886b
+02fd3e42a725a03459cb36ee34a094139af5fcf487d3dfe63fad20bf0dfb
+60deeda2acca3510e963189d1256eabd81253f7ff9d11263fdbc1dcfda3d
+1ea2e52005ce3c605c993231258a717423f64bfeebc34684efa676358b9b
+543c2042bef954829fe3246a879845b30ebacb43d8dd7a20fcfedf763ad2
+c5d20a798b69e08722dce6a5762e249ace3055b650d9e110599ea30de5c4
+fe7200d5a8da9e1fe2686350d0df334877d0b9f6524c552d0b6dffae125e
+c4c18f7547bd51c14288e4abb7f8a1a00458596c390aeee6fa308ac1f788
+fae30d7f8928afc91d4de6352d20b19d8d8ab122b7378cb379c5be7e3ce2
+922fe667ea057b5d7b3f0b51c7bf0c85f87ac2f360d82c38964f4dabcc91
+04b32f0fb8802235e8e8d9a5997d392259074c00af2ce1d2bf7b8e90e2e2
+ac34185c68a03bab8b267778292b227245d7ff8670786e3f746f86b9d4d1
+7190db859a0e144b2a61e6ac9254de5dbaef20e2e9db0b2ff654b996e962
+f55e465dd238bd1643ce59dc2b5a58b1e6e4ae2ddc2d74d79aff3c34e4e5
+93e051fda236b79cc0db268d2a89b1878051223bb8f33ff99ba87a4811c0
+b3bcc01171d0a731eb732ecd8749d27952c27886b252f9c3d190419fd290
+0987a0a255b9753fb7aa70c37462134c467a2c4b7920bed9f9e86f8f98b9
+6d00af8b05a4bd5f14c2a0d914a9a84160d554fd0718f50ecb5df5e76623
+065852daa74c9ad6da07a119df12c3577fe276ae551d48b1c5cd8a50e84d
+ec9cb0840520d78fa7f9a7c2071e28cd20ec7649b991f3818cde295cdb60
+85f24fcf93147e9f4dd084fbd32525326d2ea147ecd5b6c9d9f4a7166663
+ad18bf234e9cb92ff72138a8a49e73e527e9a6488a4ca808aecabc94d693
+cd2c0c357d285f65006fa2f9197f61fbca6ef07b013e2b558ab531d2fd27
+0cee7fa8e467fab885e90c5884843aa08e2bbfea0aa575643727ba18acc4
+99ff34e3438645be2aa71ea491e54687cd305e12bbc94faec848311ae816
+495b013bc5075a2d2ae54a7ad7c9105b64356cb51f18c2c28e3a83b9d81a
+4554dbec9bea9a660cf7e1ba89e6d4dfb3eec6a3de3fcded9b2d614156ed
+ae8cfdad5ff0efee31da3e6a54d94ce9453a1caad9756d91be85315f6514
+bafbc821ee810bb5d8e1b8f05f64f3f72c4b35d424f7e4dc3ab581b74ade
+b6d6297cde7aa8278909f269fed79b7dfd39b1c0338e01d556c4db9ca3a8
+578ace3ec3d743ed4b9c0145e4525e8c315f7a1b98584b975c70f0d41570
+8c8ccc13f848b1d36ac8249b73638f95de0cd27c7efb52bed4339ebda481
+2564d7a77416ddf4cc88cfb52d07a252d89353c6826ca1832a153242979b
+6cee783abde65c8b40cf4ea7b42b8dbcc0e02423dd693108006f6a4aebf0
+53b666c3cb63d1861f86eaacd43bb9bb6f2c3a17293c189331d253b44775
+7ee7cbf4518babb73a1d44874d7f0625e6a013c608e991b4ad17a9adb367
+40d25e3e35b459b422f7370b134cdfff3f3bcc4c32b4e9ebf6a2478013f6
+6933a1fa9403a2f1161ec632f1f04edf95ed0f33dad9665d54dd9db2564e
+51da7b65978cab50d6dc1568976e83b056eb0e3a6758518b6e17e9ebfe49
+b72eb148b472ba144bdc2ac95744c9bf1258f0a2e47470ab0eff90e190a4
+1108914ab8c1ed6b11e0681778521870e80c16af2afc723cad8719adb62d
+3939d3bc8cc1d8a4e07e9d734f54eca33d936d2c39d5c8055739c33e5335
+9bd40e576c11e93b4b4c122bdbc9b1bbf44243af4f0bcdbdfade68c526b5
+cd74e29ce3f70d62ba83c489034111fe8e4daea2f01f9d938abb532deeac
+0e329f42453ff5c15dec2aea8c198323c9e8fea55b3f5dc4751d2e2e16b6
+154e7f2add46860e9ca71dc114c99d80e7ea1dab51e925de161cedd678ee
+6282aff38e3cd0e659549c970613209955a3f581e1abe485e56402a3db0d
+1e9b8a9dfd05c4b0b7f97fc6d0eed0b69ad6f182b1d028add2f24463834b
+13f5c1307f91d363891824e81108e57cfd5211f86400d3e96b107f3b1fe8
+9c4908649d04a46dc3cee0de66af03a7ff9f4dafecdd6df4d93784cc899b
+527784dbe0718050fce185bde3f39debcdd660b2488d23ab1cff87b0546d
+02b48e7b7724c9e87b71bf34b5d6640e0f6ece47b182d41c89461f712849
+c6cfdb7e3f5ebc1acdd12d65a422ba362a8fd6caac5104ccc5ab5fc04a46
+e4309acac83d659ddda256ccddd1bff9ab3622450c4fbc89c82214f00c42
+fb0311bcb1b722a691ed839caf9024fb1671f18e4639c96d84718c663a43
+41dec037175c6bbd288bbf5a0478298ca726567a9b74c32a527339c666a2
+94a17f6821cbf243d13ea4b1603c292953308b566653423e7301a032e5d5
+e2b93f1c1434893633dd19501ad12728b5a1d9d36635b589fa2e151140b5
+43d7c5e469afae8e80c4fc1d9cb6c3823cc1bb7ee40aecb58cbc14657922
+26b19e0fe79235115f6a3afe19f98c5db63d372dd7c041cd940f4f79f247
+4d9ceea0334fa04a97dc9773064895cf11cf73f11b4684f06e48f4469f6a
+1aeb2cbbc52994dfab3319dce3a0c8c2efa9627496f8cc84d3df3bdc4ffc
+b61672780f294f453278aeb9262e66486856d37b7647141a82e049364ed3
+d03f925284a3f1fa3ddf4c0b48b3fe22e7df9aba239d33cd300ffa8fd4b9
+6192bd568fb18d325caa8e1f1fd4b27527417b034841fd49e4a77f217062
+3cc8b22101166d80361eb15fa9020d24f61007b0a8274df9dfcd8e97c855
+68e76d34ad5db1779b02f034a69ccf9d4ebaa188eb3017eef5b22a0a5526
+96a574907f695098bd8a4849d5c8311f129447cd7a3cf88b8191aec0aff3
+0a38a9ab8135608a7829207a7d242f6e1fa7dda19f5e4c28560d42db4405
+77cc0c5f5803eee897103eca0bd944e320ac26553bee7852eaa733bd13df
+760056b2f5bd1243bedabc3c1ea0531017d74b47e18f801a60074d6df849
+fd0532234545e5b5e112d1e7385341d39a89551c80dc2deaed5d5da2a4be
+5015d297324e92be64c68428132e6ec654dd4bdcc6640c68835ff8a05e09
+9604b8cd43d3af2b2fe10c8afedec5a70af8509d12f662338cbf166d9452
+cd36331758ac4f4cbd7edd52139ad27dc52569877fe709f297444c4f3189
+9d1945c81b14abdecbf31dc463a4148f04ec4fb9703c158216c0fbe65ccd
+450043abfd4e65bf8b28cc148252e9f3e797ea0b57b8721c94cbc2ea602d
+f2c57e87938c887a382d2659226463bc7d6a1da87f4a341a59bea458177d
+3f18d1213539dc0e301f6efe0111fcf6921368be17ccbb7428127e0c059c
+2c5adb2a3f0197f0ceab77ff7f3c027a8ec3ee76cf5c986eb47cb60561c7
+73b3a2da47b5a35394e29373dbd5c3ff4c9213a89aed77cc4f3fcfc49ef6
+ec7557c521979a546983c106b3627b5fd2d71cc5f08a32bf49332a89c5da
+71afbfb94c949a91220ab1f885c981423af93f73bc1ca4d92d9dbae3efe6
+a76e2de3d0f74fd3255820636e3f1a6b7c18530623c12af90cdcd2c0a728
+521e9b639eb6345d1de8fffc3b19c72e7a93823dfe3115e9e7bbbeb28cb7
+3db121aed8920d47d8cc08ea2e472e39a4cad5881b5c4204f2b732af9d51
+89d25abf413cc78714cb01b1d8ca5565169a919dc481f6d2e67f1d490aeb
+c5cc62a8f62c1a323ebb55ed35aa5c8d6f8b970e93205c2701cf4817bda9
+94fc16197b469ecc5f5e9ddf0fa05640c2e571849571cbd26402b1eb1e80
+3fcf423345007b9b52b13e3b034e8cb3984b925ebffe719ed4f39f3d0e33
+43316a6fdc26bdbea88c4366d3b2f851d2b244cc4408251ae2c77348cce9
+dd8bb9c89800b572d38c5d1cc34c740beebb5ddb0a8bb251655fb989840d
+23205d16311a9fccf7c85f6dffea9704492a4e7a8f6c0bdc29745aac2abf
+aeba02b0e7aefeb92ba63ab0df844eb09d505c3dfc1058ce42cdd8043b76
+398401e1db862ff9f76c05e8bc6260a4443cf494bc1755913d51745bf45a
+df2f8c7a9546d7ef4fb11e9d94e4539632c2a39606d04480ee459408d7a2
+a869807a4c01881c1bb21c296a402b5e6e07093d833c3dff075f4dd426eb
+87b1b8de16c146de79f52f5943015331eeb852809cbb8e1d6460ac4d176f
+e96f8d19f6ccb22abbbaa27c4497d91312c3cfb5bb913b314e43d2ec6ab6
+897ba7c34cf2caa6db4bd69eb5dfcee0aa917d6950e36a68a4c22a60dcc6
+9379d47544a58d640eb10dfe120fca843b588ca8b94f7869f97609a6fe03
+ac86ec1f7cead2ec8e81977d1b946e459dfcfefe65a7bff67e66f5f78a45
+d8df65af0146df74e024fc042328886cc1dd7779f49cdbb750345cf83cd6
+78a6a8897577299deb38ad665dc4f21ce1892a18c256f318107dd3e9245c
+1ad3bc93cef7b7bf057e33ec9a3f953251261aa3d1a8347261e70a46f777
+3a84f3d4d1a0df6dd22a96429349de0d180310e17955b10fbf53220ef648
+3d03c650a8d5c16d63daf65c21adcd6c2d0b5d4adeb2f5526aacf7cf42f9
+a8bf4832fb2d4f73f3d5ffd984b572232f87bd3e59133ed3d2fa19f7856a
+d812515c74f7d851574019c532c25f8e163e595fc9c83e3e820c3cbf690d
+a62578a980fc0803eb6db9b1e90e3256bd4650816abe5ea86ce65c2eb418
+d0adda5f3ea04e17aa8c4536cc471ac20236e66eca3619f161dfefa48538
+6c30ebb86a7ad930fd0aadf2da69dcaf26c0f677206e2030e3b15b3662c0
+ad03dbc1636ebfad1f2f2c37f5fa9856b0198c5b1d80b69c5effd94ce071
+5135c649c26b9ba1266b0a5b270cd08a706166c0b320915c87b27de21deb
+5d7e4806f6e700b7a06a4e29b629cb40761983e9ca8e34e869abd04dda19
+0bfe5a6ee8b22d7e511b84ea584a84211f27af8918dc5af8a1ff2d360b6b
+e3ca8e66ba4cd2ce6a25e7e89406684da83ffbccccbfd0844fe3becd7de6
+7764c59c022db1168d585fe25073fe00e30218d1dfe115ca1fc606afcb04
+f2a082ef91788b6bd09684dea31f20034a91ab9d971366f97b5009fefbf1
+ef0ad941654081b1e8f0b2ea495069a1ddf11dc56857d29533dc857958b4
+9d1a0779732819fd22e437084bd9f3c4f2cda4d12ca14431937ab63a03f9
+c040af1d801f367abdca7302e18a9050d6026fba5a5a7fad44e31593173c
+df277cd737d1cef59fe9684252bc0ddd00a80e023b88222494c1c8c08842
+30ab11d1083225afdcdbc1e24d4ad5fab396d2e370e44a7571b230660d51
+0a5076d8e35f7db72c0566dfc119ee1b8ac3c0406950a3c4a4da36bde297
+040a27f70753a87e6cd593dc6be9962261a99ae5949340c5d45c94a9aa3d
+d636ce8b497bbb8123457c824f443a53b3ee595c38983fe3e07dbdc6acd5
+5cae8be1081afd4857a5f52a3c925143507a3c37f1992cf72ed0d4c48d94
+ae6caddc3bc87ac3a3ef035e02181f78449e4b063b0835e827644051551c
+1603e2eab5875f28fc77beba6923428d5521c698c6b7f133b0f689f105fd
+bac30a8ed2f29f0255ddf8a037b81f04edf004cbe639c8db0f94d0c5db92
+d34d66c2fed66cf8b895afc4e659d08388ea44eae83ce459e5be306750a6
+82b627802990037157339bf142bcb9c08fafdc3c3fb16dc3544f62c6c7e3
+3e20cc4fc7ca21e2c3f6c546cd78dee348f1a4c8cb548ef20c0496789167
+71d83acc9b7b22784ad8580134471a3c79bc86b5d6d0d305c32e62042743
+51c94f9df45d9b2ad5b5087a89f90d6aa033e4b1d1bed022f36147c7abd2
+b73134dffd50907258e610c3b20949e141172b1c6a76db238c375021cba6
+645cdc26b717428b5a9b4d3f32a4b1e22feff3bb93fd889e1def8087718d
+5e3e650fe4a3330da9c37e9eb499df5a342d8ba4c0a033c3347cb25a31be
+143ecbf91384f2381e323e7fd3a82a3197c189053200ae2c86b9d01ab0b2
+89841ea7e9e9a26966e0def54de0b85d8df084b8c590081e444baf1e1f60
+670fa12ab97159318624f2af1b5ec7dd83c1073a99398d2143a52d10a13c
+201fb356bc9e90c63bb0bc2d4c42af4a8b9c8c4d58a1b32e0597c63b3f8b
+3e893bd3be8c60231838f1bc78e73a6c8cdd5e7f2907f897fc8ee99bffda
+7338bcefb5aef950e5549adfd207aeb15846b509fc57989883642498a381
+1b8e5cde69c05924efaec232fa4cef302ee3251366ecaef57d25cfa3b4a9
+e6397d996f421c900bebcf73b038fe7b16fd0a1172ac2f40d19ce0b02fce
+b8bc47da5344cb933c7fec950184f78acb32d3e5e290e84be753b9e7a7bf
+c4416ccf29d023760c06cddef2505806a65e1508990529245059afd301db
+669d41bd72bf7a80a9df66b876b3553fdf4dd38d15289af7a1afbc53ffff
+135a6348dd784ab42a6c0d6aa330b069607e2df3cbefce79d6f63e274c9e
+73a33eb85246d5ebb986bfa923df68b2b8cf82af6c33e785f35b25b1d1d6
+14de85a4f4510adfe42d75b5fa5408a59abe53859e28b3d000eb9c6a7d2f
+67c91dd14c895ba87b9cb57b851e5193fcc2a443af85fe28df6f39537f23
+a058bcf81dd8c04cb2c25040300f4c55975e856dcb4e21e2b5481bdcc056
+01942fb25bb8a6b6f93e2c2a33cd478b44655657c557ebb080179ee5d98c
+5cebe0b25bfdd952ffeb258014d7a5bc4bca4f1a23bba73c454b12960451
+ce1752401b0151cb2e01d5c72595095eae91d8d3bd55a54a2aea89239fa1
+76fa7cd6f16bb0733ef6ce6e77763a23aac77da88c8efa7bbb2991e472ff
+2075fb25a75acfa70a04c28764f4ae4c12051b25b120cad2e3044da35c1f
+94135dbd69b10de147321cbbdc814ce99982ac1d76ce3d3330e41ab31f3c
+76bf89b95eab81af3464c732d5b1411d97db36c9063537f64756f205b16e
+d7058e2cb1d6946c00a1a0cda9ebbe924bda6c7d7b605c514a98133907b7
+93c74ca858e82da3519188cd974b34daa74265db5bc8550d5f0b1173aceb
+87458bce2ab1f96996c811699a0fe4a9b849d39023725e2b1ee7e426d30a
+6c5c75ae6bcea6db41e4eb2035f7f924e6b9f0dcd00eb2bb014222e55fe3
+87fbf5b9b7c04f4688d5ae3529fdacb38b5eb0af5c3a874c1aa6b17cda8d
+1e22eee05a3da88449200d3d0d002db86f6c51b337c8e19f338e7bfa01e1
+202612d50e210140947d5f350e84f790286c3f679a5d7e43bcdc337265c2
+631527fd62d598b7ca1f5835c0441881b97f5197901ecdc4f195bc665a84
+6823d2e41417373f8639567b228fe7b73d781f07a361aa49c3e9d80fe5b2
+a32c4c1e575d194e841967b08d10405fa44eee2847db9372c5cc931e5046
+9532f1baf577f680bab4e30b7e1cffa8574abb679789f69a8a1bac07b7c6
+4ef5ce5eb00e97b36fbeaca9bba4a13b0293d34bdbc77ad1ff88e5744af0
+09823bc262511c4724dd585e7e17d90f230f7a5861b0dfc42f0b4e49a04e
+e0ee4dadb908479def8372f334c53d2ba5d855cb39dc7c9550f9d0f7f77e
+82d5a59fbbf34bffe92dc9e6668b68feeaa4f20053433d6749162bbac5d0
+d428dcf2d58d49b127fa2e674edc7d3613b1342f4d0abd7f4c5b049fbf78
+e804d5f16505ae7edcbf4d6fa08d72890f5d55199034572ab4b0c9a7e7f6
+f5a403198864adf113caff5bf9d4ab5b16f81d0fc2188fc80875e10034d1
+2e30c0364f8f72797f1aed525a2712a40d44210b813df5a29c84e9f6d51b
+1d60a5f6f938faabf878d29e6ab252d95d05fc1adf5d4ce1c9e585219112
+112bc6cd5c766411fbd22731794b5de0a27ac57d3c57926807469c360372
+be529098c350efe2154b87f1205a57a0b04c5206cc4fa66b8793bbbe492c
+c3271fb4f90a28d0066e0d7f63b8dd01549a05afa5482c29560abd628568
+75cac16100087540162473498c14087b29b86b7bfad693e81765cec781f3
+fc80e9c7b410e9b55b88114191a1703c638dfbb469ed1dd8254b1407003a
+319ce74ad419b077f17047a01f0bc0ac8507191bf72d77d9333c9da8c9da
+733efb5305f49cb8c7bc451321add7d896395d269dcdfdd084eb3aa70338
+6c0697e962929651164135c094d9bb1c9b949d5eebd3bb17f02c98c813cc
+bfb23c2c26218a2f4c639a8b9dff2c29406037f91938a5e1227310728428
+b56f48108cdeb33bd3191eca89f947271983db776b2bc897a30eecf2601e
+e3b2a6f0e135397622aac1f2df523ce6e6bc720e13cb530cef4ab9c8273b
+d3d81563ac8a8e6c44a195112daf824bc7a72fcdc4e129a480717beb0108
+5dee65ee4344d0b41ec0bcdf842566b1d9f5353b1f6a063ffa6cdb06ef63
+4c8bd5a7a63f991d178f56eaca653dd67685ce49e98c7554745a4ac53321
+7662d23e1d6937135d13bc2208eb8d50560a2baac319dfae478b6ba4ca5e
+da20222f0e9bdb0806320ed1665b54a347de0c42e9f77842de4d188e7e82
+4eb2f0d7ad163f05480a7fa99c5a603bbc5dbc843774ca66e889b945054c
+0ed0b1a4bb14324ef901b023c208cb95dfce928489789690cc45bab97be4
+49f8e2f5aa9276c0571303e9788c46e7f789555bfcdc3fa9ed8da8ad9ba4
+8b3ae09404664391e63a989ef1e24bb464043aa099e4f2d796e352eb2771
+06d8d81baf2f8562ef46bcfd1e0047e8018cbd973021dc1c1d821af03f08
+3f0b088a62ebcf2bf6c5b0fcfa441aad1625fdb834f943dd47a5a42eb3e9
+a5b49641f797c288b799a64897f1346070461b6d535e0c4ed099199c387a
+3176aedc7da7e7d9e118e55565092a36f7c74abf281720c0147f4e4f37d4
+9436466c61ff12764e3043d8a6d027e70537164f0e7942f4aca42bb2cb13
+6177ef7197e76f49ab403f741c0ef902febc471ad6c627424320a8c3a1f0
+4c310c511b3f91c3937d9acf459999c18a33f2c852ec38ca806599c728c5
+43714018c65e2c5f430f6270af52ad71ed38813b60440779455f9529a4a1
+623cb9f5422b9216f9cdba913b9a1cd95da225e254e81012160850206605
+09d03a034b5d7e32e3db5e5962a9a27711d4c3e29cd84057f7d0d7e80009
+47afe896f8523253391d2e11fffe523366b05c532d5629a90741eab3d4a7
+31d3f6d4f03ff93233ddf88bb1913aba22eb9aa6311e3144381dae29bcc8
+639958eee59accfa06f35dccc63e0609f542f3ee5dfb1cf718ca3f328455
+726f8f65e23acd970e4049225998371b63e35ae98dc54d8329b8db0901fa
+a63129ede21b158776981d4d094013c096e9cd020315d123c03deba21e97
+e4b584b4bc0af25f5dce53c2dc0f3e61f99becab40799478be7f5afd7f68
+e23ef50ad6645c967ee11206b6e791769428acdc370d64e4f2b3972e0e4f
+442297199350663d6e772fc6777a9b9de215273d082cce4e8678fe9948dc
+8d5b0e459cd02f1645ac5620f3571a40b4d5a17df5cff48b6c843ddeab5e
+bf58fe13d7da08e8aa7902119248b3b151da583101cf80853b0150fe05bd
+edbfb50a7fb0f65728c93b9df48ce8af1df1fac25c1d58e1ad30274a00eb
+54cf2f16029e1ac0a0919c0655474b9a6936aee0fb74bd185fe7d70bb847
+86997d34a40326a74356a4afaee67b6b26d1c1a7bcff8697b55c816ccd77
+312c332a55315dc54f9bc0a0f12500e0a76b3936292a3da2ddf5aa8cbb9b
+5dc32edacc4827d684d274e65b8b76fb2c2b19f7d5607523fa953e34bb39
+032c05b1c1244304606c55660d3ca8607e764ea5b03db7fcab5cf7788c6e
+60ec8c449bcafd90bcaba4132b6cbccff16784fb59b36b77cf0a9ea572e4
+ca0a01c725a6cf2e4500cddf5baccb9094d48925434f044118cfdc2696af
+5fc0cab3884107ed17b9bde0c0104b1292a1f8c99b06fc4a6360b24480bd
+59df0488641899b0f42b1311b582717ba7ecfee14143654b5371c8b9b2d8
+0685ad38d897ad1e64875c28c7020a84fbb3a3bbee16617dcb9bc822b7c5
+9c5a18c0cf7e80163adfb7aa03b7cde8497c1697d90f2ed90f813095c5b9
+1657fc294ef0e341db3392ed860cb2e0aa09293d0f99ae9eb54c761ca2db
+1e51e1ceaeab276c7bd916c68510d72d9a67468b09b3c39a7815628fb126
+cdfd5eff59cc8184c0d35a5b5960f824bd175495dd3eb12a4e96008cb13b
+8c5745303e66cf8608ff27c4709c1d854eb79608e52f068fec0151a74c12
+5edeaea555c198fc08027bbbb802835e1d435077ae4b1ccdbf722354f6c5
+72beb1376d3e342195fa80ac9722eb2f46e44de05f5a227b731b8d4a4b6e
+def04af2c5dec2eef8ff48c5b18710ade3dbfa0c956505b6da9ccb7cbb83
+4db6cc754948855d833670ff0ac42a4773fea8322becee04ca74ac2d6685
+5132d11a51524488c54771b5b7a512796d7d7ae0f9c1fbc9cbdba0831074
+f4d200349d0ca40537b92496692766f020ac43ac01db8b2aa2efa9d21732
+be3a315f6caa402bb2e61d40ddebde11276d90c2c601a935c168be600464
+76aded15087d54a14c68eecbbbb590927c1e10d291c9285334cb0c80edbd
+392bde4d535eb61f8e7641f58ac1df5b1c5a5d91e3e27e05caf7ec97ecf0
+c85b6425197aa856521ed701e5aeb82a7f52a8bd7dc97d5b3fb5c99a5df8
+4d1baff89072922509d76bc6edb15ce5f9eb8f4154bee1e82020240283bd
+c83a8e49aa9a2649b7955d5c058f2818a63bd0bfe7eaced4a49063c489a6
+26277ae1246f721c9926e2a2b6c31045fbcd235f3cc58bc4dd6c57fe998e
+bd1e9fa5154652be3a1685bcd2efaa079a3293f78142a6473822fab62792
+7eaccd61b3e99c3077103d2d19382bc7ee15bad0fde489602d055a01dbbc
+f91a566974559d1b477c209416887053169c3f8f59955be4de82b60558cc
+9ae15602a93f029f6b4329e0e62a03982db32f5229714efa1491a7b24aef
+e18febc2c93dfe50b3f641b51bdd33da38871bf5243c17502d00aea2d9e9
+734e80a96788d4cf5bc12a42bc386162fc88a7435ee13200c1c2c6ccc5d2
+1a03941007b4c4291bdb711446ceaf27148104bb240357d5eda0ea5a5ce2
+7d4a83909d75bfc05d75f10aa74a6de37d7de15c1dda3ac3045da6cd4832
+3d904e716b445e5e096fcb379353ed70cf4b6fac102c762711079efaf13f
+b74c9b47af75f3f6bda2a4647d2ab47ecab64da6cc01479f618e8d2d0a36
+45445e8744683cbbc560d47c98078b84206e90eb839b02d37c852b8e2844
+63d4e4d890203c3d5b20352110034ead6bd7f41456b807e1db1631a9d499
+e52e9d9853d86728b1a2e511f40f8ca1e4724a0d17ecd640b52ff6c66e28
+693d89765fc391612e5889e77423ec85cbd0a038b6ba98b607701dc0c4b6
+6b3b28c7790a1f1eb8d051dc98276dd9cfefab3f65c1c928e48a060c992b
+392a43e56eaa6ded896debce71f8245be4687f2f1b8fc0f43ece8db0bd0a
+b0811c5ce73cbe336023a0d66168b34a95b4b0a750b3bf1d197e3c042c79
+14fa731d7831af798e9429571cbb977e6258244e84701e5ff91d608f98fc
+3d68a4ee5b81d5ff38b6c184f6118b875f022b4ce207dc7b37e1452dfdc5
+91a3e506ae82c7e7bff0011b0a3dbd616a993fbf878fb03b6c9f2055a2b0
+95d29361f8253c2623653687fe0ab98078f6aee5fc2c2bde0405eabedb3a
+33eb7f04cb6837176245f190c6bbbcd64522b12fe7f9cdcf201a1aa8a19a
+7bbc4ac064b4958f44aa0f8dda23835ad28a1fd0ea105de2f395385dccfb
+e2261dc5a89a23af606a3985e5038706b1fe0910400e16bf008f250f3bde
+3ad806c735495d499f16f99275010478fd2127bf7cedd6b5bd505fbe9bd0
+065b4a7090c9d27cd5b36c3ad33e1b31eb6d44e375003b51b909da50bd18
+218418b3cd22b43278b144be78406eaf16c7df6b6c1c6238004aab73736b
+38e168441dc16f9a5cf60793a18633bc43d78674d12d38cc979f7caada6e
+fe807cea499cb9fe616496682a66e04bbdace1dc112b2156b9b0b20a58a8
+cb43ff0eedb99805234b9a5789762ac7d65f5a319c33f4f7438cd15e06bb
+80a7a97e976e8cec23f4c646a5821880a82b2f1dc27767f090997e91488b
+fa15064b702f864fce6505d6cef87d2a0a12b55ba189af269811e3b8b850
+c8401f3906c080d32618d9698a766732a40a9fc5a94e5bdda3d028d823d6
+b603b6d17dd046de181fd989ea0f80b4ca62f7973e4df5e032a31fe6bc8f
+5cda678d4a72787eb8253ea5882c337cdf9aa3e1e7d9536dd09b047cd896
+2e773f72f6418a3aef5a289b3406c152a50ce7bd4b493fffc27f6aa52f79
+ea67e362fd92559aa4f94a2f787f6c735dfadcf2f08aaf98b80c53ca5607
+a94f25f04aa65a70a75937840e73055b3d65fb054c63e2e48e68488c9315
+a13ee949e03e46723c11cc759d222cbfad2e1a87cad779b23d38f7e2f660
+de1388eaf1cf4d18994d75c6cc63f187fdb949940c18b537a0afb12ac5f6
+7b0283ca5efe2e764c4369104b9d3b06490d1244c41d6085c85f1106082e
+c9db84586230511c05c82412d2cdf3dafbf4759a775628878f997415296b
+c416ac8352a6c6988691fcb831cf95c10bae691adb3ba2918b35924bd5c3
+acad8b137397b10af82b479800fe16d472cd0cdbdaab4f882a0649cf5610
+04b8cb7ca32ec129d0a415be6cb91da2b65f44e80d138808a127e851a7fc
+f927e99daa0ea2d626b77a16c72e37f058a3b882fc4955dc8cb6312434bd
+3bced75780b13590bf4fe8d64acf0371f9fb1d361b05025852aab9eda1a0
+c997cfa58052c454fd451e6c1f194f4d363114e312f6dc35bbaf357a32cd
+200a3dd9654155134259887d677acc44f89aa401ca27282df7dc3f2f04a1
+08cbef2558dcce28bac2d87b8d5b7181ea927f61977764f882626d4ab338
+d95c9477c54e9c36012a3cffbe199ec8120a99d2d70a21f9d9a0354e4eac
+7947990e8a6e0601796aaf6f14e758cabcabdfbd8204a8e748a3e5feba57
+0d36e2bf474c0083229a63f96114182321b2ebe1bc76dd193724c4588c1d
+39d184c332faeaf4c629f2b3b2f49996e46aa6c9f497428bea52d58876b0
+dc07b460248bc85cc16773a5dac36cde8b152d96057f4efaaf8b1dc10022
+038577368057699b3a37178a9f1f6c6cc60bae820b7add0717911bd23a6d
+cdadafa32473491aa80cfe90f2a77e24ce2826ff77b18b869c33fa292fe0
+1d6477765044c7d14a548b28b1360125c6933f05c58b0889390537cdd16f
+8e967e0b38579449dfc1e07389b7069aa8594c5103465d5041cc929268de
+863fadb6925b350aa94a27d421fb7fcc81c6b35f906f12246b7a5140511a
+97211ba9bd6831a508e963fe8be961332f557808488f06ead75e86d60de3
+fa2425ae8439ecb9112bc3e4d73747c1c8e87a649919827049832db0bf6d
+a8c85c9a2592ac002809070900ecad52a56f1bfd456afe066509694eac07
+5788456b0b0bdd7c192d321e9fb6aadcaef00f570f22cd4a5322fbce8fa9
+8faeb681940895426270bb4319c11da67d88552a7373398aec5da7c9caa9
+f3b34581c6e968daaab2751cc012199dd897b448986cffbae4d412bf9ecb
+f46742715a9569932516259d3b3a5431cd7028e42fc751c434e2b714c718
+202bf02caf9b8a2075de922322ea7cfa605c8376fa958b8fbe43031e1026
+fbe6126a3775f643ea67ebbd97f239fb3c43552675cd08b19ca5ebf53b40
+d728556b4481c7f73ec71cab0f89e34d60c69b272fadc22e8e7bdc6210db
+09fdd913e209f49fd28e8712b8508904620250746ca3b21b026edae60a28
+22f59e912e626b93e0d2bfb3230dfd0e54e91a1dba25a609b64d41abd897
+a5d21764c351e85f9e87beab9e645149ad32aeebb3b1161032c701647115
+f98c1c2aaece871862d91d321ab90f3e923b1fdee00d927f897aa9812373
+6536e2e0700f10053d7e6c589bf66029d794883eae4c8228941ce96565b5
+0d48887b5314a2e5537959638222a6ca54c77cbabd460dac11b063519ae4
+f50d93de41763ba7cfbf4c7724360e750478eb628921daa065858341958e
+4f3eb5966c6dd77c05eeecdf4b5f6cf19ab507589b4219377959bd258ec9
+21c34fe1db003f7d0fea3e2fd6f5ddb0a2d62ca5a2cd3c7ab457dff25094
+efe04a9e1b9ce7ae3f30026b1cb039228d309a22899f6e9b9bff922e1171
+23347967d7c62c670e2c74579c35989925603022c17b1dce378031abc9b4
+b437c7b6e64620932e93189754c01d4b280b8b08699b2ca953ae4823bb9e
+e34133c5c95b3290e1bf010705ad852c72be87291e1034b09f44a95b6a2f
+83fee8841dcf661770af44d0ac7f9cdb280939fc5d953d525e0b41b7be18
+8d5c794687330cd770d24d9cd53b895a253004e18a31be4e82b384
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/fonts/Makefile b/fonts/Makefile
new file mode 100644
index 000000000..eff533a20
--- /dev/null
+++ b/fonts/Makefile
@@ -0,0 +1,62 @@
+#
+# "$Id$"
+#
+# Fonts makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# Font files...
+#
+
+FONTS = Courier Courier-Bold Courier-BoldOblique Courier-Oblique \
+ Symbol
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/fonts
+ for file in $(FONTS); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/fonts; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/fonts/Symbol b/fonts/Symbol
new file mode 100644
index 000000000..926391db8
--- /dev/null
+++ b/fonts/Symbol
@@ -0,0 +1,1150 @@
+%!PS-AdobeFont-1.0: Symbol 001.005
+%%CreationDate: Thu Oct 21 1999
+% Copyright URW Software, Copyright 1997 by URW
+% URW Software, Copyright 1997 by URW
+% See the file COPYING (GNU General Public License) for license conditions.
+% As a special exception, permission is granted to include this font
+% program in a Postscript or PDF file that consists of a document that
+% contains text to be displayed or printed using this font, regardless
+% of the conditions or license applying to the document itself.
+12 dict begin
+/FontInfo 10 dict dup begin
+/version (001.005) readonly def
+/Notice (URW Software, Copyright 1997 by URW. See the file COPYING (GNU General Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def
+/Copyright (Copyright URW Software, Copyright 1997 by URW) readonly def
+/FullName (Symbol) readonly def
+/FamilyName (Symbol) readonly def
+/Weight (Regular) readonly def
+/ItalicAngle 0.0 def
+/isFixedPitch false def
+/UnderlinePosition -229 def
+/UnderlineThickness 46 def
+end readonly def
+/FontName /Symbol def
+/PaintType 0 def
+/WMode 0 def
+/FontBBox {-180 -293 1090 1010} readonly def
+/FontType 1 def
+/FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /universal put
+dup 35 /numbersign put
+dup 36 /existential put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /suchthat put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asteriskmath put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /minus put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /congruent put
+dup 65 /Alpha put
+dup 66 /Beta put
+dup 67 /Chi put
+dup 68 /Delta put
+dup 69 /Epsilon put
+dup 70 /Phi put
+dup 71 /Gamma put
+dup 72 /Eta put
+dup 73 /Iota put
+dup 74 /theta1 put
+dup 75 /Kappa put
+dup 76 /Lambda put
+dup 77 /Mu put
+dup 78 /Nu put
+dup 79 /Omicron put
+dup 80 /Pi put
+dup 81 /Theta put
+dup 82 /Rho put
+dup 83 /Sigma put
+dup 84 /Tau put
+dup 85 /Upsilon put
+dup 86 /sigma1 put
+dup 87 /Omega put
+dup 88 /Xi put
+dup 89 /Psi put
+dup 90 /Zeta put
+dup 91 /bracketleft put
+dup 92 /therefore put
+dup 93 /bracketright put
+dup 94 /perpendicular put
+dup 95 /underscore put
+dup 96 /radicalex put
+dup 97 /alpha put
+dup 98 /beta put
+dup 99 /chi put
+dup 100 /delta put
+dup 101 /epsilon put
+dup 102 /phi put
+dup 103 /gamma put
+dup 104 /eta put
+dup 105 /iota put
+dup 106 /phi1 put
+dup 107 /kappa put
+dup 108 /lambda put
+dup 109 /mu put
+dup 110 /nu put
+dup 111 /omicron put
+dup 112 /pi put
+dup 113 /theta put
+dup 114 /rho put
+dup 115 /sigma put
+dup 116 /tau put
+dup 117 /upsilon put
+dup 118 /omega1 put
+dup 119 /omega put
+dup 120 /xi put
+dup 121 /psi put
+dup 122 /zeta put
+dup 123 /braceleft put
+dup 124 /bar put
+dup 125 /braceright put
+dup 126 /similar put
+dup 161 /Upsilon1 put
+dup 160 /Euro put
+dup 162 /minute put
+dup 163 /lessequal put
+dup 164 /fraction put
+dup 165 /infinity put
+dup 166 /florin put
+dup 167 /club put
+dup 168 /diamond put
+dup 169 /heart put
+dup 170 /spade put
+dup 171 /arrowboth put
+dup 172 /arrowleft put
+dup 173 /arrowup put
+dup 174 /arrowright put
+dup 175 /arrowdown put
+dup 176 /degree put
+dup 177 /plusminus put
+dup 178 /second put
+dup 179 /greaterequal put
+dup 180 /multiply put
+dup 181 /proportional put
+dup 182 /partialdiff put
+dup 183 /bullet put
+dup 184 /divide put
+dup 185 /notequal put
+dup 186 /equivalence put
+dup 187 /approxequal put
+dup 188 /ellipsis put
+dup 189 /arrowvertex put
+dup 190 /arrowhorizex put
+dup 191 /carriagereturn put
+dup 192 /aleph put
+dup 193 /Ifraktur put
+dup 194 /Rfraktur put
+dup 195 /weierstrass put
+dup 196 /circlemultiply put
+dup 197 /circleplus put
+dup 198 /emptyset put
+dup 199 /intersection put
+dup 200 /union put
+dup 201 /propersuperset put
+dup 202 /reflexsuperset put
+dup 203 /notsubset put
+dup 204 /propersubset put
+dup 205 /reflexsubset put
+dup 206 /element put
+dup 207 /notelement put
+dup 208 /angle put
+dup 209 /gradient put
+dup 210 /registerserif put
+dup 211 /copyrightserif put
+dup 212 /trademarkserif put
+dup 213 /product put
+dup 214 /radical put
+dup 215 /dotmath put
+dup 216 /logicalnot put
+dup 217 /logicaland put
+dup 218 /logicalor put
+dup 219 /arrowdblboth put
+dup 220 /arrowdblleft put
+dup 221 /arrowdblup put
+dup 222 /arrowdblright put
+dup 223 /arrowdbldown put
+dup 224 /lozenge put
+dup 225 /angleleft put
+dup 226 /registersans put
+dup 227 /copyrightsans put
+dup 228 /trademarksans put
+dup 229 /summation put
+dup 230 /parenlefttp put
+dup 231 /parenleftex put
+dup 232 /parenleftbt put
+dup 233 /bracketlefttp put
+dup 234 /bracketleftex put
+dup 235 /bracketleftbt put
+dup 236 /bracelefttp put
+dup 237 /braceleftmid put
+dup 238 /braceleftbt put
+dup 239 /braceex put
+dup 241 /angleright put
+dup 242 /integral put
+dup 243 /integraltp put
+dup 244 /integralex put
+dup 245 /integralbt put
+dup 246 /parenrighttp put
+dup 247 /parenrightex put
+dup 248 /parenrightbt put
+dup 249 /bracketrighttp put
+dup 250 /bracketrightex put
+dup 251 /bracketrightbt put
+dup 252 /bracerighttp put
+dup 253 /bracerightmid put
+dup 254 /bracerightbt put
+readonly def
+/UniqueID 5021339 def
+currentdict end
+currentfile eexec
+e98d09d760a3c22cf119f9dc699a22c35b5b35ed6aa23593c76d54cabb5e
+942bf7d6dd84f1664b89699c74b472de9f8e6df925f6c4f204e9f1c639b4
+dba988ed2ac419ff2b2bde605b8ee3264edd66412d4f21c64ac522bdfc7c
+5502f9c3f3e5592b3b2093d33c9bfaedd2d49e89aabaa832e23f062e91a2
+5032519d1868816e44b4e0747795003d7930299d6e1e2a5bfe0d595dc97e
+140989ce81d8d7f852ff9cdc7a1b1b598c69131dee005b415805a16d8a13
+e5927617ae7f247a71ce0c7d56afd75d85ed2d9f20ff9a6c38e8d5205197
+d08780180cca9c35522b1609b501724d4d6400169b91bceb6a4de00afc78
+1cf8873012b3117d22a18587895543dbc2a1ffc7752376decd4c92a69122
+4258e8f8f113f2a5cb3d8da10fe823c6656a8800cbc7ffd018a28ac2885f
+35e22ef9fb549b00e23d31bba304dd9c28df02a8c370ce49c58a40c9f673
+ad61f5abee9d62ebac590b5a44f2babd96e137464db066b602a5d8d43ed0
+41b780f0fb98f9952f20ad8084199adfee9ecb193c018772e63a5a83bb06
+00962fe724f63351b4b7a16412743ad14a38418877768af423e3348d48ed
+773c2e87624cfef777a15b6872f54488e42c4849ae6d54cb857dc0972e1b
+57c88f40b89928ea43c18dbc73182f69b52f0bd66b7133881676616ab669
+723240f17d5eaaa27c8e295862288dc30918d00008c9592a51f39e30ddc4
+62f6287654eccc13fb9525f6eac5709e952fb237e8cb0870cac5ddc13da5
+8dbd060d3193fc92e6c4cef3bcfd81ce6b3679bfc5855796cdfa8a26d63a
+659a2ff7a1a7e318a7f76ff80e846a2d647d38e827ffaf54bd5a9221eeb4
+16a475eabf4ef0409b3cc15077e01f742c46ed43ca72924c32e48a786224
+63396680cac363406c524a9b3b768cd5a6892643f78b7cd65c610ebfebd1
+058dfeea67d8a9b9afd9bf39033a56856537c06f75bab0a47079dff64cf7
+343cd6e7fe7bb1fbcee32749c91435cb86f7550d505c81deffbe1e3a1f63
+04dd03cd20842b335d7fce6eb31f175724d51c184800c3756db044e2fe04
+bf53e995fb425aac96fcef384c930334b5f384536cb3abd98447844babf0
+4ca767edb70786132c796cc2f6530852275ab4df0c8b4d2eae01380ed24e
+62f5a85dc8345d556c67f00f622d32dd66fe18219169daca3744a819cfac
+c305fca9471a0de5936e270e3b2d4e1211d9da8de26e790c6f56c2ce8b19
+e175256e8bf85b8e52db7da8c44fe52e57af48de9b771658139b6b81b360
+92ece2b629c0f64d31d62dc7d422c2a204bc0414cc6f78f4e975bf8f27a1
+7cc3b35b31ed313b5274f487a92ebb33b02af472ebd84c4b1b4006e5c522
+8a6f7222dab490259de2223f4cbcdd006a6549f08085eaeae51e4d7b08ac
+c8b08e8f98dbf79ed4220132a755c007366600fc27e0badd73c875074b6f
+211da05ff1454730f3ddfe96d36ca12f8249cbe74c82a940f1d60205cd96
+24aeb7824d5b0a1578eb3fd45ffdb97e66bf0faa27bc25e631c20674e7d6
+db5e4cc7b10f3a77731aa3a53a187e5211da39f2e97c0236e36f8714c49d
+630e6e1fb42206cad9361794a9e002369ccc6587f9a4cbce5cfde26656dd
+8a36663ca82efc1e93cc58863e3a290090906220923f544e8ca05e5c8377
+24afc674e6008278fcc696462cd7986aa3b884ed5c17f9d035b9a1a169d9
+f8f28875f7e5d7bab34668b61d026f77e37277d53e9e0467152f6ac7ab56
+ae9206f15177732ead7b2a003799862772b241d65818c0d2d6c53fd0945c
+aa1719db446f7ce5c383f28bb1f419f023f3def204e895b8057407648efe
+1973dc8f7b8c17abaa1716ab69f3bf0575f564c3400fb55bc430f455b266
+871e7569c39a81bdb082fa5134239272f9d69d2f5be493292555a5115a0d
+bdf30da71bdda418cd5875bf2c0ccf00e236f2c97056b102e8e014c2c118
+a76cf79c10fe2921d32022b8f96443bfa1b34189e5c5abcfec51ad20cc45
+08ac5376690bcfe01dc8f924fa190a6f1295c15c74ddad5e9c4047ad0145
+76858a265ffce0be9e77e763e911bb662359df98dd767367dae1b686eede
+cae1f0c9cbc54bc4cd46e51471256bd340b338c38dcbd6d327fe6d2348b4
+eb2a1c95bf082f2e4a1bdadbe349fb331ae9ea002c602097746265455a5c
+60a7c0bbd2f407c8a7e5fe9fbea4bd8ec9962542e2e3021a0ca40f3b3ffd
+b790592167afb21dbbb9eca9012d06086f1de6749ff3c63be36e0a55a9a1
+03406d8ccc095975872fe895b8c43a2a445afa5e03c7902489d4f4c4a9ac
+829121e532c6604c059c355652fc9c2f16a553d5368ba0752dfdca4c0e9b
+944bd1c2d115c25e4421ebe412b171290ab0d0e5b0b2c42bbe58a4eb39ea
+61c710496dd8a4f0de76759f5d55f557224a4b9549cea21b8fe277fc5848
+8fc369d9c0f1a3dc52b8542125bb42561b594bdf33be43aef93f00ee5c60
+274affc05484b0011d8c465f56bb9d04feb88b6de54fc2104b07dc5ec8cd
+419d9f597e5f4ddfc0bbb0e920629fdf06492bec78c970c1e6653d4bbf92
+d3f1cabdc4fbae380b22f1db6e8aa9b050e33a384d5cad9543a3adbf91a4
+a94059705d20d906fc7ceb2577ca5004339ecbd2a3679f29eb43c89247fa
+11350bad35ebc938bbd745f774727de92eb78bfcbdb109c54022ad09c21e
+85600dcb70cb1b51aeeab9cce57b8b14c54eeb1e956a8c39617472165808
+22c531bea4051318283a3cf1f612360b4d3ed785ec76c59ea475c15b15e9
+e19314bfc6a12892491cd9d7cb3afd9020bd28b685129ef9e2c151c59599
+f1e8e13eea8fb5746cce8ae317691a28d263c77714e5f401f9edaef085b7
+2a86a9cf5dfd56739e3bfcab4929679ef111d23378a443440cf9523d3bf2
+3f9bdcdcd7f2c40d75099f3777e66f6e3f1ae4def3d5b062ffbb2fbda4b9
+38f80f74b6be3032bba77f99501878567f48a64eb09f1684f095f8b4e407
+a78c964825abdb71faadb42aab7c41e146ffd21ac742574049dca257e9f3
+d4ce46d200f776ed7915eea1915e321177963dedb2a24c8701d70a265856
+8cf1313fdc4166e6ea59a4bd300930911c13b7bf4e72012fc99cccda3b8c
+6d07febf15c0a15c01b220a6dfbb1d80ceed73812be525e5b7b35bad9b67
+72c6673ca1f580fff16f3c96b9b9b7f041aed50cdfcf7246db20787436c9
+e2b8706d38591372badac219b83ddb3bfa1af853aa3a7da41b16bdf5e42c
+8277c2cc73c1c9f668931e66ad5523d435dbe68071d056cb8fe1de179c52
+44cc511d40bba8311d976a2120a6c46e85b939291f60394c911e30a214ad
+03bfe58a03e92fc67bfe81b828028e263650d27b064558e3eb72f01b40ca
+4cf029b6f1c1843193fb23721f1f6f19922f821c28ecd4340f10e96eb38b
+788c589cb8815bb708b0c46c378e8c16eacc72ccf9ca0b9ebdb0b4906af5
+8fc5cb8e7d62191f1c11943bb76d82251258c4b251aa9561d42adcf0a5f9
+18491e063b6a88cdf4e0c8d41c968d57c6e3fbcd6bc618d139a687303ee1
+2a6b31bbf23a04f19590540468bb12bc46c3e69f4bab7d195a1fe7db4098
+09f5a6b0178a77a4792f69c23489f5034379b4a7668cc1c9369a36f8951b
+e8c85e23d2e47dedf3718c0a2adf816acbfbda1d46ae86293448abc732db
+99c17a6e747dfe204cb1161c9430ada3787bdb924556234f9e2cfae7571f
+9542fc06c7b7cc06f630d43c04a454c2dbd1b23549311b03d8bace01fead
+8e0f4967f514ad83472957cb2fd7661bd18215af416609669e878c72e1b8
+f692c44911958cb98bcac7c3087956e5369e6f41f1603ed496f4766fd351
+7e88680d37104f5455d00b7769aa1eb0497d65b9c53952b4ceca60add156
+d91f86c60c6e683de2d67fd900e00aff558004a66e12a9c1b94b2eac6162
+c89610943e65de52fc63a8ff04c6e0b80cbfe53e15f94647c5ea40ecc42a
+6bdbbe981cc27fed8df21369c37012087ce77408b77866ecb381f0a1dd65
+1772728b8e07728bc82ad72225c94c86b2451d891c1e1bf843067d38ec94
+23a269daaa3d71eba07fb7f5982bd73ccf01c615ce12b396f656d86e0e4c
+62bff0305566cbc839b1843046cae4b57993f86cb5d5ee8a5381c33f136e
+01b779492e3d0c86787943046324887eb4e927307678f2c8c8af15d5af78
+7584254e99baf1e3345d89eeca11846cccd62bf08b6c3937f7a3d816ca6e
+d30c71999a392d34f04e502e01934f2df047410e72b50a53f11079103502
+080e75e0314bddaa9640887fd0b2d248b73e8ea80bd8cf69627f0d345a73
+791f257bb59b3b0a76243bb06bd0b1fca3448ef08f012fe7d6960d592923
+b13a6962b0ebeff6ee814b6cb369cad2399a3b3e39ad7f0dd9c32fc7eaab
+819eecc9b3fd971231a833d00bcf78ce224933c40f1fd31ab11d89932ed5
+6046d87bebeb0d04dfaba88f20070745a4fa25cdc7f482f6a29e32d5cfcd
+50fce23a1281cc914d9d2fa2d62114e00293e2e74e25e99ce2db0696de78
+b67bcb47ae793721e6958c6da47368536a5c9f9fbc134ddd4d08bf5c0b2d
+3bb4f863eb2c0e88e8699645a41ade9ce5bfc877d7c3c7bcab236fb508e5
+c8fb6a1c33179670e294a7a068199581965c0ffd8b1121f4632088bc9693
+14d1319246e8c9e4564bc6bbb723698edd949d12560b33f770fbecbea8c2
+3beddd57e08c9165420caf1b354852b07b6af70f0352ffbcc71c9172d62d
+85c67bcd90cbd733491ecf747cca756250fe5093a9b8457f0fab6fb3f365
+cd1640e30073d6f3596f896e55d1c0639573284be2be1ca00db036d4d055
+274e620ec875c5d16f2689b20865bae0f14b1453cffefcac59fe0f76be88
+d16d5faf229149767916eee5d37e4b2b060a3a3735fcbd078705fce3e795
+443568c6b74b1ed8f40c7126610bea528083349c2bb60ad9c15edcd2588c
+09c71e5399c0df7ee8e51c4bf67891ee652533564d7e5af2d8910a9879dc
+a382ee62378e2a3c7edf7437b5f639b633ffd5afd3455a7b1da9c4c7fe0c
+03ca927bc933d8821e2f9b7962b8e775717629e24bc980be517eabee67ce
+87203d0423e856f10e4a5b7016952f6928a1d3080aac0e25630b19abd7b4
+bbbe3ec959d60343ff4df715455ea45b5fe5a6e3fcc77ea118037919b2a2
+b1deda705afd532431be9ad75309ecf826af7d63eda6c1434b06bc5e9acb
+43ee209e7b6bc20167028ca785d393ba779ce7a174a8988c2f7623ccf2ce
+9ac3c8982c865120740bd7494ccae328bb37aa4873ffd99c46d20059c1c5
+bcb9aca5e0fa9e1200d12545df876c580e1ecd188295a790e039729ef939
+2117044e157051ce87ef3fe59bfff2557c7138d4c630680f93f31dc51b87
+cd7fd8d2142e16b89b3abffda36ef051b5643c4f533eeb1f8ac18df70072
+9300d3fa5abef49b53a887fadb0dcd5b3e0b22d988c2d607dd2c9f5106f8
+3a521e755684abf21960a0f9033066d573df043adf95f7c8e9f822cb1fbd
+5eed34d0550f44fabf736a5e6338ab99cd0ced9c8a27090c85b498199c3e
+b567f2e92567fe87b20899a3b6843d71d43b28b1c20de059c102c0580254
+642f24efd11ec8ac2819ddabf1ad4b1cd9afe92cc0e46e194865b980b28c
+d543df06ac23efc9c64cbee9d921c29c696f47bd8e700b6d7c1d052e75f7
+597c5d513c76ee9fde2951cd86703ff6824d2f42d4837893d2bf82349260
+038d21e9e0fa96ebeec822f6e91ec01f214aa9d1b83f0b732cee3974019f
+feee359a25bd36b0b8e8250dbe1935bc0ce2c33bbcc6d1e7023630c885ae
+fa7a770fd3b1992ecd9aad06a13dc58f18fe545671e54c71b8f5e66d076d
+1901ac6bf8e874ca84054815a145a7bceff0787367b58c668e22028216f6
+27267f83f279656f6b4fdd61fb071241cc883b0060fb9b8d74313be9c271
+fa13ea9640adc53564f2d2a85e4d1799b2e5d04b67f13a30914bca5597a7
+2d1456eb9f228f56ea95d1abdf5b4332df7892b23c571be72ce474a56854
+88e3b3eb489b6de3f5e3fd5435e3cc6bce8071126261d2b9255417a050cf
+5a286bdac485a678009cb3f7b4be9a245270c08f92f339b57fa9cc899b8a
+df5f73361198781480c3b4d6a2d8c65a60749a47cff15e761a0352c5ab72
+d1df98ef57cae899dfa9d8cc7fdf02c4fa66fb90a68b8569c277d99376ba
+317c9e6e59d7971b3fe53daefb91fd05e32fdd517b0b22a636524b4bc23d
+7464bbfa592b4385d006a495c0f74684fab0d2aa4046b8721cf503e16e6c
+6a65b54d929212a796134ac6ebe6283b722286b8cd869c99a5b7f9b3506e
+ad333ebf2e6b9c97f15f0cb8046f0980b0796857621626ebc802d5f3198e
+d91ec321522d6fa84fc3bc752f6a6f47fc2c051ad193ad4e406ca0150a9a
+77de9371f832d3aca7a84ca8c3f7d97dc5e9485c4f2a77ef071919cc90be
+7fe13618a4a9bd73870a968cb8ba24688708f485c15872888220e73aa662
+368f410ef76b34655663c54aaefee827b7c553abc82543fa8e8dde1323c6
+040fb8f24fc213a188f1949a4701b73c0464ad9657a7535440307897d816
+b3e4b6daca7684f92a4b74262d772969dee711e4ed9ee115fb7f91bd9d1a
+3d40325f135b2e037350a36b43cf5a4cadea68aca368f99278fa5ecdff0d
+10ed1517489c3e59568cf5676015d06d296e7a26013d1282b0be1aed1e1b
+0b72a9bdf8e8d7bcc14633875c07cf5cca202965c0ab8dcf250c33990073
+26ca40b0e3b45a9f82e601b0f69d362cc9352defafb017f76710f829dee9
+f4badfcf550c83868b5100ac893517a84e0dd8ca2c0dbf356e0a7a533080
+ed1b39de69d1a31f0d2fc4d80cf09e75a82401b9e205953571c2988cc68a
+e61e0c986e7631b822ff448098f015a925fa9589d4da4f0b47413218a6c4
+542d45ae8f328318eb676944d9cd0611263ce4f1bec8470d1b8646de66d3
+51646200b5a3e8c7a76940544cffcd6fdc9824275ba4095ef08f5b43cf24
+db7d8b1a0b196e255bd6098dbc3f9859d49a159c692284b52eded6320230
+6487c99740dee252eeb2ce6a53479eaf7fcd6057346b6a83ad3578e65218
+ee3bfa52f9fd7052dbb3b3f841887cab19395f64779f64d3f9b4a3fe3947
+b6a501b68bc288c6ef892f34f8e20a94605b6c42df84d61edcd000dbab26
+f4a1e7bb2da0a926ba762b2112bc10921b387e100d9db20905e27d47f0db
+3c7cc67f29e4efeb6f179f144b83ae9493f724ab589e94bffbdcda86fe2b
+b33e6158bf1547321015d46e1667a22fcc7c56d3c60ca255105cec8b03e8
+8bfa66950424e879d6db2c4ffd9d6df35ab3ecc8d5da69916784e274bd3f
+c32077d6636ed73403105506fe86c7393d6da5c0f43a8847efd46d2999c2
+a662b2caee14ad13e48f1487f534b666bd3882d5ad91ded50023840c3137
+5ee1bfb540190f11c953c3c86c0f66139e57ec50aad8fe9b0aa154250f73
+c0e12b85b42b52f46b7dc85ec0610ccdd08c2f3f7a535fd609897e472be4
+a4228e451693921ed1f6fd9bfdab638da15123f3552dc8be0530c8a76e85
+f59e13d95b5ae41d3171f8c3aa8dad0a02c3749e2090c6a795d53605340c
+4e9b596818aab10ca126e84f9023c81bf23cc73f61ddc66199e562780ade
+bd2e903547098a5915fc7268198af301c501d59b90f5bc507da3b2fae272
+8746cbc4ecdadf62aeb3ff1952d7d9f1042ac5448a77f360b34da1e782f3
+f10194b3d43436b4117694575f7611d1e3427f7f7814d94af7f5c1fe268a
+fd82c2e7e9e3f6e0b8b5fd827db4e7b47e131793c6e29b33c9b0857435e4
+d57f515ebc299023a438e174150403c894aef50c25ac5aaf7f872055faf3
+c1ed0144a6c1028e252c3af250a181bec8730283a087845eb774d9d64fb8
+e73b3770b41e7505e4a502ff355e3f7582f329702508549d5e0751124455
+8145d9c457df485615592593827f8e16e0c392019e9bb9afa29d2ec37e28
+f55f1d812d3f552dd43e9a707fb23652e944967b3da009453d8418c0d709
+021b3d6036133611532664e92eb7cc78a0aaea7ec83ed8353551b6d7ed45
+71e466e55c00da0929645b998c12f2969d76a27d56ee94d981feec5b957a
+0ca637a04a3f0ae1bef57d8a83d1a1593fe04da296482291409185f0e2ae
+09fe4c2439e2f4579f54c784c5a53d3897b6af8b095b9a98054bf89febaf
+16c481f356753c8bb80195bd24445a802a0517ae0944eec6307996f8381b
+2d974d7965e3f3e92296be91de6c548630e726236c658d9861cab98b2572
+79432fa474854f9216ec7b6d27a1321a7b670ade7265c10b6aa509bfd3ad
+fa44cc3a1d33dc82dc4c1b139d95ddd7a2316bfa26c608b40a36ba9bf92f
+441ebbc83a5d0b4627c568f65d5c05372841627a8d8e3059d8737519935c
+2215be69d4c5f60d4dff230a09e72431c1f0ac9885920574775a1224c3c5
+59b0f340085302d07ad4016200443b3bb065cb076e898381faf87af0ab61
+1a55a41b92ed6d9510951751c0ed0bcfbceea792ff6b87979489791dc83b
+88e74770c07df34e782bbd14377b0399025b011c7db92ca2db7d08099a68
+e395e9f282f8d7169e4138dce2824e053ee76f6de8b58296ba38b0d9d273
+e3a4616f60f291dbf4346848e7dc0af3b63a76d83f06abcf2175550a55b6
+cb4a3168f0d33fae389e0484ee677bdde16c106f39bffb37f90d8912ab66
+74a631a3e12efb2e0391bce42a1db09812dbd0fb0bb01abb134ebd0b6eca
+134a7ea7e0ee66f809c46e5fadb70085d7f0c8f7d78fa864f241ea501bdc
+dfb8fb1d2496d96ac23337156cb63f9921bf84b06a7f9de424edb09070d0
+9efcfcd32a7061c990bfa088174ec45a0f4a385803c664c22eab041b71cc
+959d9f3cf8fcb27e6be9d7e13618482c30de5425382fb964a3bd82e7426a
+8ca0ac81a8c09b6c0b416f33c54a45c4f57bbf1026a12c5baa1a5540e7db
+5e954ee101c36a703623a7290ce302753ec158b65f810f7c46c55c7f9f12
+7aa3945fe2a320a6aa49323125c85e174a828c559783107edd7e3967bb1f
+5c6163b9a15b8c9d2be84419fd9c0f36018bde462b7bee204af15eaee3e4
+f5fe39a269742ba5398bc6dcdbacfd346699a28b8d708e8b09ef00c4ffe6
+fc8be121ce97ae6d92b042895344492ad9a66932913563025c0beb65ca34
+3fbcdd121e126c49692d52ab4bcb715f52db80680c0f55a2201b22c2f263
+d38a89cc8981c56bcdb245805347a797d0d71e02a11b8238fbc242456250
+01ec6890cfb1a0939937aab82ff635de52e47d62cbb38d4c89523556125d
+761efbee56916f2ed351a8c8bedeb375b400a5499ef7cc7db0d9d7f60647
+c3416ce1d505293ec1289cc0181479b28a71acccd35d1c497f628443fd33
+291a48f7afa1d6a675ae2baac9fbc4a189fc04a4420b91e3d51ed1ba42c2
+aca67cddab41638c82236f66a8f2cef2c66a33d54253b5609989168e1cb5
+e92e9a46256a87104f0fa8390dbbfb8148d7f900b9634a3e67b0f761bff5
+f4160b2db21528d0a4d55874eea9f015d952cb8ff88f3afe834fc1ea1de2
+73b9c0048e45e3e2aa57e4c092618b50b3c1f51521d03e9ba74389ab4613
+b0337d2c74785f28eee574f18178c167e6a3b5a5f6613fbe58b584a35322
+2458b6e54ac8aa08f31ab0761e1567265fff40cb3e750963f8179d495c22
+6284125367d1ac5d188f5ca6a9fe0f25125f30353df54e96e1f6c511c938
+e100be0c1b4ae68d4e3333794f0bc95d9ae9bb517e0d183cfe88e0483bca
+95780fb6437cd3c2bc3af965bc6bc58d845d3046ce5d12ec9285c1fdde31
+4660a960af7e4a7f07f90f950f06c77be9f26fa91f14fac8dd904eae790e
+d216e7cc22ff475f8f462e1a46bcda71a9d65d07dedc038d00f493b3886f
+674983dcfdd7d760fbde7baacd78ac12f18def55886938f88b99ad4fc8a4
+20cbd6003615d4e31ff2942b35f72c1a1fb13c2b22625273f715e5d89a4d
+fe43e2047562f77e9c8e5c2929bdc7674ee9beaa8c7ce8021d28492d5c54
+768c002a366a862bba99390be487e4781513b80a7bcd5d47dc23541c9a55
+b9455c53e9325d0d77fb0390cd7e12ce2e4e34581a4ab524a6a91fd3bdb9
+e07953447116c7e4f429a99ff6c4c11b1ced99e51127c30904bdf3ed12d7
+261c31aa4833ac725f5597b3c1170a4892c3ccc765f02129442d491b1227
+0413a46c92c9b83d41eadb08c78037a1c8630599695f00bd7c8b29841540
+3aec630237432f7e6f753851cb3588e229ac8a0ee375d815ac0c02250061
+09bdf8e0b496dedd2aa9cfaa16286a4662e256778b125cb4db05d252aa66
+dada5d161ef6a5971e9ed85c913d1befa7d862aab7e16bc95e03956460e1
+f55aa7594800600d5f0d1433ee8f0f0be4cec403cfedca52734645826eb6
+961af0c4e1dffa69f1930e19681539960eb58bc386fe31f266f5e10b13be
+4d4f46a29ba95403e705ca8dbcdcc03c273509d9a8bded6e6118daf7fbc3
+63c7e784f8306f8eeb7749cc6d855ed29f99c7ea8b43378c12738fb813fb
+825cdead8a664e1fadf11f7ab84fa7e4257bd1ef7fcbc31e2da8a8582f43
+be6ae0fca66760484c5122cb38176951449919341a9eb60093edceea347f
+f83a16278c37a9ff38202b27a4f75c066fe443a241b630149c585750e2d8
+15f627a1254276dbeae8182270f2699ac1e78c6a09767e296a646e5eded4
+843d2eb8a68673ac5b81e06510db64872547a92a4bc851e768f43da053a6
+bb3be89cbef166e8a3419eede1b97df88a698c0f5f864d81b5c4f7ad97eb
+f78b4ee82ccd71a34c398dd3f74609c555b7653ce27e78be0de7caa11de7
+8fcac0e0293101a2a8c5545941291c56d4957fcd65e36ccc57c8c9dccc07
+407a11f5c9cb214ff508a5f617ff24f0b617004d6787eaca97296108b8b0
+0276f3b7e28af1db998c36ef517c38d96dbcaf33deb899a344a6c047cdd2
+662a02b94f39ac528a21ffaafe364770bcfb995f62eb0c6d076f12241f72
+e4b284f085a3c6fe9263f879af8c049979f51ebf49314dd0331e935f94f2
+a58a107906c2265e3bd6d644ea75c928ee81268e7db0d2b61775cbdcfce7
+43ef1ae9784c4a9b2d4eb0d5bc2651d79f108306722670399d2a90e45364
+67c00de86ff4a4f4a51176ed721ea3a1c72cee354c54f62db4982a566307
+cfd320d6245bc3108a054f44b3f4f61fde2c84ab416d1816454430b6468c
+57d86c155218c6f05fae1fe22a7da461e960c210ec6e44bd7fea797c1cc6
+b63f5f93e75bf6ce42dd559eb1e97a8cd01daad4e9af2a544896f6e597ed
+16d6847e48539d0fe0c1df99298630ec2b465dd037ca7617ead304993972
+4bb3d428e9137dda6709dde2e72e16c80cc960cb85f1727bf30845fa51fc
+a8d52b6099a65a0cdd444daa35534782ae347cfa7d849ad3a93749db9041
+03e597f6dd56e032025f59f7b724d1c947358099ff3b336e6d688b72bd11
+5b86d6d0c54dd457b7bce443524cb0718a82d6661fbb05673b86a3ef66d1
+981788039a1e26597f2f6c51d055b1de1d32145d39b244c91eb3efd23c3d
+4b785b96296acb8ce21882b4814ca4d25ed88a3b6729890cca8843c1e2f7
+46289b4e3bf5196e268c5c08e52670e875aeed4e9cef6f45a70d6f944aa9
+518c2ec860d163131b66e61be344aafa0fcd4b5af24830da2e9811c4024c
+b807af29ce56a577666bb8a6ae62dd780f3ed028352dee9b6aef748349f0
+71f151b9b33a5c707d690cacacdc1fbc8eaab920d11c4ebf406827329303
+32a7542c002ed0e4ef2d3cc5a611a48585fc0097426f9710d6dea70f1ffc
+a65b3d39c875369a91c045ae73d2de28b548f6bd8d0d76e874655e7ab6ef
+5bf9a4e08e12a1ad867ff1b70cb0f2ac3d198d5f70c3a251058291d7f537
+e66af56c87c11916390b7705821107c658d2a403cf1c6cac79137505d904
+a6e31f34ef23045f923ac40aa9335058ad760dcddf43aa9b516652fb81fd
+e901d29cc3d2ea99c42fb8cbb10a5cfc0403c5db7256c7d3ad11934d3fcd
+cbde7b87e11966fd3361210cc511459cd82b61ca45e208a92edc040cd58b
+2828fad652ab3846c0415fbbc503c9251d7fa661fb8e5fd167fd3e9df8bb
+17a52d2301c21f974b16340ac7e431272b48895f837687cb41ee7595a826
+315338d997fba43a9f8a0a9067229537c85caaabc2667000e6961f5ca11d
+60d3cb970d0e059e7446f1b42166292d96abae83a185ddeeabbff0d9da54
+ced5cb12e782a26b7128f0da66ebbcba7f45b6d4522a3baafa39d764b7c8
+3efda777dd173720d41e0c494949372f9be61de175bae4ad0bf8d788b3d5
+032bc46e95821290cb6c665122220ccd6cff2544b3ad1e11ddee3c0c6531
+81abe20f6a66a4e898eb48636a8d6087fb79477aaa5419b785dad54f49ca
+a8c3427f2973a49a5b064767afc3b028fa53ca96401d912a71514abedb68
+e6a41b2dc619041ae1b798c1d6d064478ba17c0d040f73f1d158c72fef16
+0d30b80a9ee8054ba8860f69f2241a6926737a040e06fe294544a393fba3
+8e9d850adaaec2ae183b12fb776c82cb3460db4ceeffacfaba629c7a0edc
+662d8fc48b59db18e8c5908d491359a9c1dabe1418b46978924cd0028f1e
+19399904737f41ad8de10d4214d05d6a4db485cbfcf4df0921e4e629ab83
+4a695c317b791baaf902ec59231b856e3e646868ce13fbd5cc41b6fdf3e4
+d918a02efaa20aab7d526a04edcb2eb388a2ccbceedb9d0b0df1343e1831
+7f46a6054c2bbb14201a92afbc452c760f16e12cf94c8a901f50f1263e01
+9308c5aad246ca64570b122032948bbcfe1152937c2c32b764f78bc24817
+4a72a706fce7487ee6c605d48eafc229c9206077a3f0fe0868ad5fedab9a
+9b07a7d7d973fdaab891509a8c8c3cb9862bbfe04cd0c3505df3ea8a4b51
+981705b38ff503abc17fd88230bf242fd737314b9d7b613989438d9e0f71
+d5cbec77f1d93a517d9fe08e0aa138d3aa55c232f493ccc1f13ec45f2e07
+5bb3a95f0d4a32d5dd2176a06bcbccfa8d0ff2e2200ad6f2cb91d325ee48
+40ae4a27c8709eecede5682c0fd5d94d570790e304b9b4fbff08852d9895
+f7faa0464f625e7d51f3fb5424ee25e89da33936de5f313d13f3a5c565e3
+3ede87b22cad211eb58b70f671f5a8c473a15898ef3d35c0d496c62b01dd
+a1963999d313b475dbe8aa888a4d66cfe1af9c86707d86267ab18fbfede6
+8848bbb9dd5af6a5817b5594c6a74dae1cb83ebed616f7bde4a43c6a3811
+a7f0b6ffcc08894d118f53828d5c55060eb0acfd818cf991796a9439f733
+9482c925946a5e5d7b55ec7c9f0f31de88caf20686ff27415eb83022c7b7
+299f23cebf34a766a4bf842de6c113c39db711a6291ee66abc42e4021dfc
+43d91aec3aec56ffa48fe9d555d9c435ee363533fe2195111b9483eaeace
+96281b83962fa3f7e0c57a2c3cf955ddd8774a263ee61b2d43ad97b0cc58
+d4657bc27aef767215cfe5c9f7a87df9d439cecf6124baf26e619e7d7a0a
+ffb678df6eb3d663bc9f77aacd75fabad0b41622c3d5ac9a78a432595715
+5f36c9dbe2d1dfa81bf0e11e0512978bc8e74d30b73fc9fb783539a1c132
+1b893b4ff9787084185280967b2d2df72690339994563b8abd371ffbb832
+3c4105d304ba0a184568dd1f32d88aa56724286535c33182fb59830f88e2
+d878822b1c0202b3d34fa70a1525e5f06bb08844abe54e98ca304fafdc6d
+c9522871eb5e6c838476cf5c15a43c694d7ac26b04f8c0deaf7f0cb0e44b
+0448e958e31374de9fe5397530ed700e78e09edeaba6d006b5e82566c399
+afdd754ee2638ecc0a2f59a1557a084502ffefdcb7e9b32ac98eb2750038
+bae5487dc255d76461273fa3708b8a1af0397a2c985f45a26af331286e27
+dbc1e5624c7eb27d87a94a8bbc5e2a67f78e9b202c2298ee390f8cc3581d
+407f555d2699e827058940d1c1c69ae67209d354da032287f55668fb6034
+f5b96919fe361fe6870ef24c914a6a1e98c9b1bdc745c71ce5d6111e67cd
+d5b809b8f789151baf3a208e949c8c7f69bbbd5bdda2958e444d960746bf
+955ffbbc82e88724e54a0bbb4e86085e079d60472b7d9e2e38b58206d7eb
+32bf5459005ba2839a007cc41d41c019713f17b1e209da9a2cccac58a9b0
+e39bbdba1c0e4aa0ea12349b64271e965fd0b5f5d49955034e635645e76d
+cef521cacf68df4ca06557d0900699c52ca3286f682215811fea8c8e7569
+bde853033e165bf1670f1b181988da996262bb0326ef9591bccdb4d48076
+86451d5842d7a79d5e5f5104528c89178e286a4115b9ecdd36cc3b1a08f3
+1c54a2943027de0114ee35d096379c1697ff60336155741cb4669b3ca41c
+6ead258f7d29ea3b4c932511f697eeda22b90c000ed5df8170f0e189b110
+13e3852953c2fa2fb21907c5e19b8343fe43529f7219fecfa8b4a7bb3e01
+fc74eb2dc148940e332d1f53f4f7226c78b158cadf82d756b21e96718db7
+7ba7aca31fd5279d19b1cf40690cf3f7a3624611bab4a7b0ee77b4e30a10
+9bbc1549d0a6f9b6f7363f73226ad19b9295824c1523a8ca0efd878cdf81
+e8df64156d7f5f068730eb304abee1344a9f8d366d0540e913d8f79e9da8
+044de90066a639796fe62569c78ad5e52da7853b5cd251737fced1e17e75
+73b5341ae6927ef38bb57a84370ccaa506bf9656ea00c7d65afc6a7c6253
+42f369bd932745fd4ec25a5afb57c9bc0c8c82de8e9e7390b16064efffbd
+151d9e169f42bbf5ec9df52cf88289ea9d829a29a561b03ccb14bc6a0cc6
+277cd53524e94c0aa173d4b72d3ed2fd7d7dc7a25b7cb9b768310b885a99
+480337ce2c11fe903d7fc5b59376c93d6c169d25b9e8a2cec8b5d971f77f
+0029b61d36d9c46a5fea7d49ffe0320c3b83f5a7dda48ee4a5e15721f778
+12c5f618784670c92d7236cd1d19248fc8c90e6c0bc876a1d9e3b53857fd
+3ee7790f486e7ec4dd3da944967d62f7e8d706a9f6ebff86b38a5300df6f
+5444148978453351bf8d230215d35257bb54a702efebb4ba90f53cd13469
+09329e92e064710259ff8a33f1a9cca5ae5bfdea62876539c0aa79b2dbd9
+5f0b80ac51842edfac8ba6c79aa9f0914113ca29565384571b885aed9ff1
+e2df3bdd667514a78ee26b59f96261b6268b7afb245de6ee930943c3d52c
+238ebb6def8f6777dc9840d0c220ae81755c742c3cf42f6cf3c33a2c6a4f
+abca01ea12c37b2cd899ce780e434592f23c7fe96f878aa5f196d9a70bb3
+d544247a5f295042842181d78f1dd58af09d99d25f4647bfef59e133d425
+7aa689bdcf248532556e6a4cfdf558bfc1af8d0991889ad61d8ba10da576
+d1366be4f6b0203899f9a02fab34e921e9a7b09c2d06f8c6600b9ffcb187
+d95c1facf73d1ecdb28bd4f5143bacae5e193dc0d196e16ab2e4d3168a76
+24de988e1b25e56406f12b6846c66d7ee0771e71be78e2aba637364df774
+f91bd43e6608359b8540bdf22e28c34bae81ae5bfe50d754553cb6858a8c
+2fb7dfe840421b702b99f22b221455d28ac55f2b8b01e5c6ed897d42fe45
+a36d396f2b263fe51663f898fd747630dea134d758954d52a44e36c743dc
+d5831f732a23d4aaf49acf6bcbb3884a21063cf0a007e2516bfa71683e34
+b361d4456f5353e72c1db7c693c9d0357ae8179a644f2f373d5c763f5e6c
+8c8b487288fb8377112784fc50b31e39dd5d69d14aa893b55534374cecf6
+19a98b47eef81c8cd20bd3b1838654f308fcaf94504fd5fd8e93f07a4760
+c182651145778990122e2afa7b5623061ec3f4d7d9f061f2b7a7a09a3ccd
+c33cb1602093369acff1eb1c6dfd73dfd67a4aa978ba1ba496bc17efdfe7
+a8f533486c3b69df01bc5a20230235454f3c41b0584d28f6e8a019db4cc7
+8d5ddc5d9d8a867b7dbf3e39f7ac68ca55a40d9a05e2e385835c888288c2
+4cd9fc51ad2250493122e0302655c463cd7e1188b5081387c4674bf16edd
+2c1f1e49b26899db5e1a4cb1bf6afe14dd24400877f8c8657ba4d3227c76
+7c1971bd33ef70472c2542b60148fc4ae31035240bf578e3ba4ce8a479fe
+b4ab2d06ca63f8b80cb0b592b2e6977db02bd2d9f81335f13f803f5c5cae
+420236e8c5c11dc4d67c210cf2694b47e7d71b47c29c280061b9ca2e4fd8
+a303ba12aef815503b67955f62bfcd7b2a2ea4e31f799987bdad5d028b29
+eb1d91bf894a8cc7f4751d15d11f80c40c0eaa38af5a9cf69d8942a21352
+e3657c3657d92b40985edc1ebfa807c5285a74c47dfdff79c41aaa22826e
+c0161e3a4e6249664f7b7f52161d0ed4630ca4cfdd6d68fe2b4b7a4d64d7
+051b2c12cd0e4dae0f66932d7881d601fb62f3eeac552e654c2de5bdaf65
+178efac1d91ddadf43980b1a23d5c3b5d38a39115548b7124b8bc5fc8f45
+e15f32f506ef0d7dcf45c93d2925829133a732a858cd6f26a3546a613bc1
+024a8d31276e529322d8075bfc9e970415940f96ef9be114aa3c97fcc08a
+6e67971a6854f4cfdf8f6b43a8d9fce53cdeaa81ac6f97a3545f9188596d
+78b6a33476dfb838fd6c4fa785747203133d4518aee00c184ae0fdf5db85
+0326ad9fdcdb244bb4f659b66e3319334f59ea2088e4957477a5defca2d4
+a5fa3e37fbfed1384500784e08ffa2f5aa417795a1d2fe54822e10cb2845
+15b6f394e7681fd911510bd68efa22957930608625775a64a48d0c2492be
+b3ebfe2f85bb6ebe4a5e409fc7f14a98f9239306c5eb3e6d04d741bf3dfc
+478bd03ccffff848e0ed18e47becb6c55c39a4662283f3c4e2dfb76caef1
+6c4fab8944c1ff6243e22715af0b4de2fd6a442ea56a5c88a6b93c36ebe5
+22b5c46014bc03e86167481d599bc3feee0564a090e43571b0dbe0961148
+2d69a250626dcb909668f145f9b626f9a7907f4a1778e8ac066af5b9ee02
+5172917726ccf4164b1e0c7e7c94e3b7df8516c78b1c72f6fd57ca0aed0e
+419f2c5dd1ff24f47438c0e0473edf9b5fcf277c84d500a4ff055566ee7e
+cbf5707262fdcd3c7a28f1d04a4333374b6108c540c64a0cc773cc90d588
+3b7adbbe0668a38ea57cd2292ec92602cf4a0a70ca7bfddb955d71c02aa1
+2effb4c365f7af85f2e379b2a5e80bcf653cfde715c7db2fb98f3cd3af72
+a94de7ab989f2d38441a893934d396c2a418998a0f515aa26914447e3a9c
+025e8169717dcc63fc878b3e825faf7da165662751e0811304ecc1a7c73f
+f806380dac5d61611388f37d7a92dda1c535a3365a82227f999e3f3dde8b
+bd72a5232b3332e0cb275312cd28f4c840c95de6366e02817028782ce6ee
+7c56a004d6de4a2786060fcb6b6d05afddc743c210f6f0458603382c1be8
+3e61e9a03835c2f6bba1a4760564635be899f75bd23bf6f636371bd2238b
+72331220156fdaf0a5d932d24829ea054b6b7910a738c03c231d1dbc9caf
+0165d4091a31350da275976924f83cb4187e618917b56fd9b881bb25a8d7
+f8741b407a89ab26719db257d9e6b60c3c25878c5896094dffc58891fc7c
+a3eaea6ae4876ce36b3d3282c4d1dab373534c261104d235ca94c08a9daa
+039540650fbb97ba61d5d907244be0b6ae1ae2c315fc7a13fd194960922e
+5d54c8528e8ae6651e9b36d7266ac9058ae97ee0af5b27b4c045aec4d2be
+d7c42cab914e1068cc8538861aecee6243b3d38f60ae09cd655da05a2bcb
+1a15f914a4b819d1e173c4abf8d25f3f29b45c4bcdcdcbff3e24add7e76a
+ea86675fd8e8774948a1625dbd5ee5fec0d512de9f2ca7e91b97afdf4a4b
+f242499b6d8f04766b0b8e7522cf8848a4bcbe382c39cbb3bf393ef10347
+f18a2e6dfaa6842e31cb9eeee419c762debfcaf49cd7bf5874f992a78703
+0817e9da9981b0d90ecdc538ebb1812b88c96b6e93b350b327ea5d737887
+7aac9d7129c150c571ecdd4808f02479bbfc87f1df80df86ed6b573339b6
+9bcdec24fb9df93c871a6aab8fa236b3d39abaa1404321d9032971499238
+99dfb447021b9510420441b9fd8ae89e2667441d7670b4061439cfd8767d
+30d2d298ea15c1ab2dd7b25fa514bab9f714176c8ae5a204bb167cdb335b
+132a35f6bd14b70ffd7031cebc7e180924f24fc5417199cf211ee8e6a55e
+094afb5637334e8d42168da0dbcda3b25336705988c929efe68a56ffdb15
+6eac310cce0d067dc6b564634a71d6cbd6f9ca9f868fd2ae88778d2ac52a
+e78ddbb7fa9c939dba897d3dcde0acf6e04d59653df22bcb70f9fbfcfec1
+ee703e923b07e0d41370c4e4cf70ff63f8c79c5c6438f86725a50e49e3ee
+e18687ea324e651dabad022e8a783c4c10cf84f0ab482e5c977d4880bc99
+adff1c8a4c5e9e643ff55128c306cb16eb9d23c7bffd19d55ef59a6f3608
+dead9db7dc3931c48771b9ac55368e5f8a857e6d5c118de26d1a1f383a8a
+5bb9a2a4b4c0958c0437fc96f264ad36d1a0acc37500c0ad72ea86330e77
+c8518a74de75eedc0f3834f03860e2c26169b8c02752dcc5824b02876525
+5026506b2dffec0a1578cdc55f15d471c6481c08a757ea55686352d2a7b6
+9c3eef57c630f12e9b2aff398671240dc216a29c5ec17d44e05f1a8dde90
+76de92456e969c8055b85a3c04041365ec35d79f2c05abd075f14eb26eee
+478deff3d12fcf9937dd3901d509b695f8c1fa590d977d78db84b2849562
+c460659842a7b90f8b21c2cc27d642586872c49b534d299b3fb7e14d70a8
+68138371550f9e021a74d2a6e0f67d90d53ec408502c40d8dc51eaabbe86
+fbf5572a2a7f121bea99be0b0045d2c516d10c9beb813e16f440825a77d4
+dede2c8b49c4ac5b71c11ebd8f8fc4cd73a62e47f7eb212ff0572281b427
+96332f70728d9205ce38570c96bd89b3f2a3edf498ca83a37acb4027b561
+de28ba37b9199d04a56e14716ceb4a4633007637b216b9f6ba2a4eca8a2d
+e0cd63ff0944dc63059befef0dfb53a48ef62f54f15bc0355356787923ed
+729a782d962b4d78235de8dcb31892638f51000f8981b86bfbd853b28929
+f896a0530b72f075cc0bfac799631f2e51f474ac2f98e6e2fab89c2b3890
+007913bb9841969b44ed76d4e888d9b3d9841dfac5d41459dbe7233745bb
+4e79fc22fd7e466601153efe3cd7700aa86acad07b0692ceaa6b00b20d76
+8c5e6052894c5915607e9cbc49f8fe4f6f3c33045fb4f0ec20a3c948af28
+e80fb67f379ccc1bd019b339532191cdb803ca9676977ed9ca01bb039553
+48175f8caa95a0714327d59b82444df22ac4ee8f5049c91473f226d4f27c
+e402bbea6f406cf21872b15b19af6c0cdb798f806994ec1aa9056637b139
+12effa08dc015bb67f3ca7a4c82c5e34d39d88cdd5287c3044ba95f2f75f
+6b6db9f1d60a41fa9034d91bd9cbecfc7ce7d76f4048206f5fab0901f7cd
+d639ed068cc82be17c35f6dbb8d85995a63ff69e52bc0a01261662153ec3
+40fd4027eaad5b1b811fad9e16663918e46e983b02a3ad97ee543c4754f9
+e9b6238295e6477f0e8133fa12360b5fe5adb0389778f4300c11a26fe4c9
+bac6e234ad26f855bca28b49a3bd95c0758587e98fb123c1c80f82573fb4
+583e578bf6599e79a9090f35be2c9fde410ebff05ea76120c7d52b3c4769
+0264e1dd276b6ab08abf52b30b91735b3c84659115bfef8b88c12a7dd1bb
+0898fc1d5782edd9f371379a8c9796cf3616a93193a06152dd3c8da6effd
+03386e580b8011d2de3db70458d957ecd0a2db427058fc80522028c7d203
+904913b0e63d26d60fc42a2c1e9c53b41bb206b324121347c6fc55e99390
+86cf26b3de1933c0586abc166bf9f312754704645d4d29dfef978d8ab341
+1eb295c500446d3e2a62d6738b1b4a9f20ee6b3a7c1c0641b5502d52a28d
+95dd07da8fc8eb96a234565fb0b9d82cbb263450f929c9155d3d29ae2a75
+ebe893d1eb74b6f0628f5bca4c90a7dd943db0e99b178a0d83524800b361
+0d651475905983e84f5905f49b0ef12d880cee222e913b5ba51bc5532afa
+722f8ef9254c49f7f62f744d580bfbdee17d40ff9a04ac2bf64016d4673a
+4538a66e52238b4f4c1d37ac94f1f65c7beda2468a10b0dfa321b18c84e3
+78cdd2555c453d62c92c4293ba0aed6733aafcadfb488dfbe545de91e412
+c8a1ad04d959c75262e92a37c4d1bb48dcdca4c8f6d9fb07a9180b6f9c56
+efa9ad9ab9fe48ed61d59c5a4b0fc284351d439e7e503e9235a30863408f
+a5a99aaa693cb8aebba6eb8476009234be914ce235bc206d093200d35937
+43eae9db40f639eab16fd3a7d049005fbf938696948d82bc25674c69d1d7
+edd0b6d51438183c30769ca3104eb378b82bcb5e605d1e065a11e17892e0
+a32eb07fa974d3c6f70c0b657384ae839f74c622656efbd3878a7aff1a01
+a2933e47f366953bd28773878c6c999f39abb27048e53970a5c88a137c75
+e49c91a53316c5f9044464e40c1eeb3eba35762a490a3ffe8fc886d299e9
+ecfcfe553dbf334913b30e03e5bfbd3de06207bf47cdaaea4cfc8147bbfa
+154d6295bd46af68ad298b5c02fb0569b6ca521361427c55d456ff6d8083
+417f3bb3ee883a957dd0e453a889d389bdf574516be147499cb02d9d760b
+62dde4eeeb70a7fdc12338abd01d709ccd256ffa5f62a7f4aa6d3c7f235d
+ae276553da64993147b5b86f62c473d0d3ed14883ed0de74f1c623f3e624
+9d6af1571dc177d27e2c1f0bff7ed9dcce8fcbd37bea8501aea6c6d7b259
+420bdfb804e3bfa4e339708d19fca748d8ed84050439ba7f5a088da4802f
+dc46b95a99959e95f18407abe239701a6fba7d6e2094641c509da66fe556
+747a21b0d73e3e7e157ba4018295eee683d0fbdbfd52437ef581b00ef2dd
+582661a4a99b02f6685cb183ac801f038e3237eb22f9508c54b34e06a1aa
+fdb4fc6addac5110d2569d4921ef8b43c6ce363e642951badf00ad01b56d
+262cb0796e6bc3500fb760ace1e7c9fe44d6816c84063b7aff0ea04d918d
+048dc193fc07bad3bb8e7a178f8720b68a80027e9ff2fe4bf8f601de48b4
+c863ae6a0f5cc9fca4614fb487a0d7e42cc17ec429e1094c06718a4c01c5
+32cd08503eed35bef2a83c86e85a8e74cb9364a01d7aa51af9a7ad59e93b
+78e3d119e400ed46c608c71e33facd29e424123626b535a7ec87cf2c12d1
+96e378986732c89481d88f14fcf9507dcd50834110c071b68860090e128c
+b525eac3b519c2191dcc7d39d587e56fb33ac6bb2312eb217d08bdf9c9eb
+34ce910a07477031d4edc8226e71421f6ae90bfc43c7398928dc2fdf62a5
+48324c99e740b5815cbac9157f2f5b51a46a1cf6ecb6a03753e7fd49cb4a
+04e5e8ab19c4ac2fb50618bd9f1417faf34225523a6af9f9b23ef982831c
+5f1946460795e0b5970b383bf8addeb045c54e9c593f5e1f9daaef7dc58b
+da2819209f05aeac4ff234e3bf47ec5f496c75322417a96de3b70c509693
+2dd0026384c3d15260446292ba7a0cc570a29a6b31b7a37596db015ec084
+6bfd0a664cda0329e8a452241cbc7443b4cfcbec48b94a1fb2bad1073268
+afd3231bb21ac37602dbf5653780215e4108e2d4f7164b12e74824397373
+c405184888673573b1f2263dbbcdc07ceadb2d2202a18ad03652f0355fab
+f0df08c30278496290306f93be7e42f663b51e4f0f7e49d3292370c92b45
+bbb7660748cdad641b1c2d24bdc33ddd9272c8bc6c4c80fdb1d6476aa6a1
+7d0e35b43ef7d3fbc7828f0209d6f83b04af1df350ce10a3af84855bb90a
+2fdec60f796d5a20eee1b323edfde3d69950ce90894184246dce29499c3e
+87effd5630aabe1442e2399f0393f21beb96708b6cf0b6b207e47273bbe3
+03a35024cf49899328c87191bfbfffef9500611bebeedb27933b1f53d6bc
+805ed7c3271fe94dcc7ffa9f2f53810cd3d08949d5ab0b144a8fac533ba3
+ee72bce2be5cd88034c6303c7d323fef2432edc947cad4af6b1c38be9bd1
+48caca12323f66eb57c3096c72f8268e746cffd4ef80df5ecbcf522d85aa
+41166fddedfe8d843cb25b9975908b5de7c4dab8fff7b98b8c24ec1e8477
+1270ea877b2a5edce15539685991971922f50404b14bbf10e66264fd8207
+cf050c7c0311d387c62b78aaac2b969d315f4a7963a79f8e724f5efa0190
+25e7790e6a5c902b7da857438e84a9bff679409dedf5a4a0f670ae4536f0
+5023a9e13c71978ca70490706cac13d790ed4481ebbd8952f759a038d821
+bd0027e057837754bacbb838eecdf781299a2c349e34578b032250842cb3
+7f3726a67bbc8a8c229262ecc0cdf375ef7469bd85327b8735550f942cc5
+5ce679a0af078126540bd2d4f9581707e67eafe4a1ebcde24a2ad06535ce
+001fb7d2e5f59c2e6b8e3bb16eb2c863dbba5e781c80e5c80fd9d2e7ad5d
+11e809b842f13450f4075c59648f4f59e1b5b8d133bd28ec16d32b6230cf
+626e4d8c76f1e46974703abb1934d3720a9b16ad752b34c0155c2412e3b0
+b4e917cf5111c0a986c361bde767c6262d8ab6520c7f540c75c2c92b134f
+1dfdd0807d3bfff5674e376ce4513ca149bbd53d0ec109d2a8b7ece2f6cd
+76e9b07a249bfe81cb1af012de457337786a7ea8853745e001e3a07aa41f
+b4cf2d0dc29a779ee9ded63df1251dee748a69d71596e1feb5082d14044e
+3b74aedbc2ef7a288c671e7a7b7c43e0d8f3acc76505875855debceb7ded
+992273ca741cbb7073c9fe6182865cad971a7196610134c314826f2f12cc
+4f2835f269cec7b8a046dbc7568b2cbc56cec08095fc771a9b093a4dbd3b
+6e7e71b1ae183bb5428bdf018193ea62a99ad8adf581bb60295874cbea14
+de08f9a9d86c5efc49aa30acbac07f637b2c1a022978383d063e12f17fa4
+a20f18140ff565088be1714bc19701a15166de32429ab505903ba52e1ef0
+72a304d1448755ce00dc7082df7d990635574c9a5b66daad0a45605903d7
+3179e0ed9e2630f43861e22354ea16418cecdfdca05201e2f75ab6f7b3ea
+e336c4ebf7e3851cc097e2105beaed2111444de983c6b82f11b32fdd61ea
+b45331f7ebc1f93cef31f223fce6a349d8969651ab627a481314fba2a3aa
+950327257f8f50e69e1a20943816ef41225ae1b76811c5af88976c4b4e02
+74b43a58f63a27ea8958a3f5d875448cb57abbeb4859668a115108976861
+01542a0830ac31f076c5ed6626ecd9eed04ad3e762e9318c7bab07ad3204
+831f57b4f10deeed0895e24668aadcbeba9257f1ec419111e7257fca098d
+3ca89a1ded16094d10231bbcdcafac1166c08a7007749748e8c4f500b9b8
+7b84e8117042575a5b0d50652355df6cc61cd2c785b1c6811db2e9b9b7b4
+7266b4a1084be1f3f7d188fbd9494cec5116fa627c8069950113f7090936
+f10de3d71de1b70afc56b61ee245ef7278860b64113233a8a7817a0ca23e
+5f08370cd48548e4757478b057a0ae59e9ce81a4ed7ff3ac3d2117354cb0
+a98623705deafad89ce0c5b5196776cb5d437920bb5c72a8a718ae629b25
+e253c75501555420621480afa2b91b756e967c7f24e3005462cd1496fb58
+f34a42a9d59a10d6d68bb3c42566161059dfbbcba569a089d9c1dbaebde6
+51b2275d59df0933dc21d0a902f21c5f5037299c6e8fb9541691ed13c0e3
+6a5af58d7b8bb360e8bdd2a77b24138b88a5aa2938066ff6b098326c2b43
+853800eaa4a304102281325ecdfbb2bb1400f09edee97ae812728cc153f7
+eabc4a7cf7619a74b495fc82b5a89a9e0246f98322c2266bf838bd1defb5
+16c7a371d91bf573de96f05001ec48fdcb9e9045ab1fc910f6b9344adb49
+c38eb75023016e2398846602e2fe7a07a90ca86376fc125d8bed1956b897
+781def6eb4298204e4b551eec3ce13b1fee5711f10c0c8232ccd533f8231
+7027a87c30b91bc14d91e14ad3ac92177830435c27fa8b8f8dbc75c04cab
+0181455eab3d1e101b14974a6f4fb99c87ed435f380f2087438b4b371d1e
+6113bd6519afbfd9244f0384dae185025aea6457401f54545e3494120105
+9ce756cf7fab4fa583f986a8b4d559e834ef331a6833971c89f96c58cd5f
+b3be135cb06f658fe2627509c8cdfa91edeb439eb386e3bf9bc4dc4e7290
+a2ffea0ec25c0b9c021285abcc821befa442c87cedb0a6c2342c933dd461
+16ca786dfa3ee43a7f3aeaca49e4f3a1d404e59eb35611cfc68ebfb5321e
+e4d871b206ac8692930c892dd7cdc7b31baea9a439fffbc5f9d3cba3e71f
+5638dc6dcb8c64f763e254c327f77352297bd706f3a9b4ecf045b1f132ef
+78c2967e393100be57aea4b6a5a8cd51b68bc114ad91e1e43512b8079834
+464e4a9231ce839825cecd400f71dea1b4da2010d89f3fa8506f26888f25
+564f6f0b5864768abe3d3e857bc265fb6b99e9546495e4be3f7b3bd616ed
+a6fca19f05b84df96a2b7174cd315029082ec03d74e9b16fde55e6c51c86
+b0e6c0a1875275fbc8f24e08eff26ba23f0a963f7a40c359df33a2731f13
+fe2c905f6f60acb43d4d03cc63725c85a406108089c33d82e1aa107ccf7f
+0517beba564376c21cc2589dda7994cd35739722509c630c4f8895bf3687
+bb8abae73b5e1c42915994c614e9876b7a1dc571c06ef000d7ec59deb528
+19ae24516aaf054bb91545310116f9c46af65343853f896668dcee475899
+d08f4bc405efbdc9d455d2b48cd23d1dd4e40b8948fbf834132b83bf7b95
+0e2f83a0915cc277d4951b1d9bf8c9d7c2900ed222ca89e7aab7e64d28b0
+d90adf9c470ac90afa395a63964604653936a618dbbee33caa4474ed522a
+cee561047dc163c784d5b8a26e04256b16f96c63eeba3b63dd8cb056834d
+f7f846fa32e32f0ffc14f074f03891816de860f201028060c3043b391fe9
+858cf29622d55418d67f5e6e6c718f1fc2e62daf1dd4cf79eb95a16d9c3f
+eccdedf261f9f41905f8b8c39b9bffb2c0e8d65ee4f9cbae52b55fb3bbe1
+07c08c3abd668e91601c849af2e034b99de6891224a561b7449aec3d0be4
+75991f52211b9d1668311aaa7ac9185e78f90fd31a324b6c820f7f8e189e
+952cd15e57d475430e1beaf7537cf6649e80e35df16fc03a71ea162a19b7
+d29617bd5af341e7ec81ddc338606fe0507649bf761eca6f72dcd2b21797
+32baeb51d65779019e678cc846f184baae95550fc430d6c4e315c1a66193
+2e5a8c4d3d81acb445e2b0b807771e2aad8465847fbfdefd7209d10dbfa7
+faf2c3041a678c70a1c807a6f82eb448688c8e9a6c968f7f9f4cbfa88505
+997572ce6aa228cac0a80f49964957017e9090bee36c566c06e79bebedc2
+de9a7902750e1d25f2b4a51e10221b4ef82d8f1fbfaddce9f9682f3843a5
+81eb10b55cea4a8ea1e2f7c84b6394e04ea4b6bc9d9ad344c41477724a19
+6f73d92b9c4358f73a3f882f4452045c22555127bf9caaf52777c200d679
+86227cb17f94a118ba663428ab3fdda95c359a353b4aae31f94b04d84a9c
+0c699407caafb272ae58ef328e9065b57c33bc9bd75b35e4f7d2a69affb2
+137a0947573d52972b014a28f14700f0fc2af0afb71fa3c038a4fb5fc2ee
+2fc6512596b42d3b72a612b86263862bd3b2dd4333758611077474fac0a7
+22e1d9199d66510a1a86f807aa0de71c13920d5bd7328874bf1a0e2b80c6
+d07638f261ac24dcf7485301c5d5cf0a8b62d6468817d57b9eb835a3f996
+6ebf73223cb5909a1ae2a85bc90f012ee26b484a40c8a998ada321a0fa95
+05d9a09c8f61d708e80c7b5f47599d12e020fe79d63bcbb6227e4158acfd
+41870941fd774f6525b78a6781fb50519ad9240ec7f31c1b85aad48745ea
+2e58ef88b890bf9c5cc5910148aed529f2694f1cec8b0e2c30952a4dd922
+1d53ba846cbbaa2d67d64ec25db97fef8973d51207930fe5584cde28a273
+468ed7713cf2e8865dec285e20f49ad3e6ca4e43908a9116df1bae41bfdb
+724b3bf2cbfd255e0eb69560b329b7eea14bbcdfd0398c663ab9c13cfc78
+98c674bfa207018cd1c85281c4bc995b16eec777f51b0d1929100553532c
+4c3e8e71acc6daf2193471704d3fb92de494e89f81bbf7bb700d0fe46d9a
+21f9cc6bf251ae31f40334c66bd40f801d02ed63b52c3ec6a1303d659ede
+330cd53de8502899ebc6dda655de3d583104e01e123001bca6fb3ba5ffd4
+f1e506cf7ed59fe3f991808b2272b1197210e5ea213b3bf7d6a2177cca3b
+0483447bdb44ad2c80e04cf5e368525f8d6b9ba6b114a4145c2c8a693113
+21c8d5ce682f2e13ee4720e0568efd8488faf57760a93722dfda8489ef49
+63f2e65978adfab8b9c9c8d9146180b92b3c84c725e1f50ea135004b6479
+7ca6c6a87c95952e8f5d68958b644276d106e3706af153ca270f159f6f8a
+d76f0b9f4be493574ff549ad6ab909d42e5718424001d8aa17567dfec66a
+3e0cdaf98c89e56a4692f0d585b13e8c8e1dd4a5801b1eee8b3a333b63d4
+4e65a2c50a1b46615afc550390c1668ea06ab0f6f9a175e408b1568bb470
+f73a9babc7f82795ad940615701ef5e2046887414770ffbe9c86becbef31
+da6f294faed8e4f9ca084a61915d2f7194ad578fd5b9e01f4c23027708ad
+d4326fd70b48d0cbf9b42df2860784859dd9cbc707020c3917d1920ce164
+a671d5e09d268545dfb9d2555a1c7b820ac802007c54b403e1a6f9553e6c
+d52c64816e788e6115ebe9520d57aa5d0278c1e6940fb80959941af78bdd
+96877279cab45c9ef7e47d90d24b5b3e0869b769d3a0fb03dcda79ee3a52
+349f3fe89204afe517b97455ea1b056f87cd846202593cb7768dd89321af
+3dbdc0c188da25b9699cde6e0b1928cb4060f09b4f6a6c2b68700bc14eb9
+fe2890fecb5e389e7606186d4417f5f5a6babdf43c1352f4feb43a99698e
+ca73c7d7eb93ff5d38ebfe6d102cfd0d986af39184b4e007bf65131b6a2d
+abd1593020e2fdba559e939daf7f6cbace2176489d45ab860fa4a05930cd
+77189c67d4b72df03fe8cf482419972621de5f2f0143ea14f5dc08463b30
+2be1f4bd73cd1f6c5b17c74d7740c802cf197ab3f412b697c2bc8f41743e
+b2be55e238dcdc6a0253a72e63479dbf563e6a161935f77f0e5bc5372dd1
+f92ae1763e05e019b47967809d42709324eade06cecd85daabc456d9e903
+e0083d3a74d5cd2df30bf1db1477a6a71a55a52359f4940f2c339bdb6edb
+aade3e614d4c7c36fa2b26accbf520579df89a7239ec627869aec628e7f4
+ac09ea132f7e2d030408dc91f2596c954a9c026fadcc416f1e061b484372
+21b50d8a4b735c91d6e8d2937e4454b0e8d1f553b84a35c43e1101f497f5
+e429d6e0852f011213e7068d53e4dc696f6f7ff9637d3ac5ed28b0f8b55b
+aababfe8e9aa7fa60172450bd17b615b1b89048fcfee829552077abc1d30
+615c9b5725701cb39e6675404c8230ba27395ac8b5444f318600dde103d3
+039cdef4650e68a9f1280ca84aa8cf87c652aeb45cceafd1a21793385a17
+4d4a5a5830700593cdd94d61374ff4eb563eeaee80b761230ed61d06be11
+fa574de0ae6c3452583aa53768238a25f570eff0af5f5ebfdeea98c85afd
+a53319182611e3e6285659ec99d27a718ac5a1cd7cd80f2c97bfe9bbedf6
+912a41a171ec583a0eaa4ac571b495ac78b275bed49eb32a0202a07f1ebc
+b0a89fd2d1cb6ec43631e8e26869aa6abd775f31e1cae5158f904a0c14a4
+ef72d51e20503ff7814c717a0f9b28ae19897a448d8905725da4e40f17f6
+d7978538095add5e820e80de9f261ace43d77d4bf97510f774860e45037c
+793c28915b01cfbf7c6388b2e9225b0e2721cf5fbb52ba2da6bfbc11d515
+3ed1423fabc05624b54a1a60235ee26e908f63c52826315f1ad84fc79de2
+3ed793cc756578475900e7a9ba8a812e06d2b9721556483fce01ecdb7f83
+190b4a6f2eb8728f5bf941a5934c960548e4a8c0d17f6708386607a0502a
+1ceb0cf8ee2ba70d0e0b350019baf415a66ee50ea8a8ceef78ad242421d7
+397c06caf762f6b4bb54bb3b8484f398000f0571f3c9111e96164af8420a
+7aaad2b6b5056ec35d0bd02b46a7e007e24e1cdd1631d343856da9a4b66e
+f36561844b16e6beb6f08b0dc8de04b04364335d6657ff916495c3f9aa5d
+87a2e455428a2d489f70c2aae03b64390a6e083094e925f75f7f2ea29a44
+c76ebb50d62d91fd78c3035cf4bbe13d3d7205daa28ebbb258456e2838c6
+41ab51e1652594c92f592ff8d31d90c6f179e067747e9d499a5e0fccf5c1
+6753bfb70a3201fdee641c9f45ccffad879e477963c8d89162195474ef98
+4f1ed3d69369905a3d55ca6703889213fd8cfd7b029a3be8adaabf620111
+675f6f65df5f5b05c635ebffd9d6c573b0d6217448c881a4d25262cefdf4
+9083e775589a406ed03f8b0038dc7c47e1b484ddff035994f4a6200923c8
+5edc8236d20e46b0d3e617a8b026cf7070ced14b3340e6dc34fef020a9be
+702e17f4bcbc738770e76f47ffd849614e24207dfa5e6f8d2aaab20451d4
+412546e40e8cbf56da8d121f364e03ee310ce1cb7f6fa51c6bcede9fc198
+b66d39d57b23eccd3441460593f44ec22cb4335bf19e09ddd89184dc0f09
+f682dca18763ea72db6c8e32faaa8f002d49f9023d27b508395ab751be5b
+02b5db309dc9a51b40e77552bee48e379fe478bf337e039defcd992afc2f
+712a5b0f646ef0902b593d8e9f03bd9eb512ee344e115f84671f21e5b5d0
+3b0ac0548481a9a07292f79bf74c41772e16611d15cf15ec079814eca31d
+f380ee3f56e9bdb39e0028b15793670aa6d1ebee19603071ee3ca517fda6
+f8c5763c9c97d11ef62cd19542412b55d55058027494143f217df42ff2de
+1c529e533d0ddd46ebfa886ddcb9072d299c13266d7c07a2ce9f5b76addb
+44ee6513244d7d4d55be1aad98821431280e334889718b60b3e58929a1b7
+197d4be03753e22a5bea21669a4ee78ab070a41f2eb01a30f200619fcdb7
+5cff898152f0c44b2fa25508cb346661f4fe7846928d52014ae28981d803
+ea0eb8525e6a2318cd2ed96f7386a22ac36025027c5d9d50186b5a2830de
+062b07ef56ba35883ae1a0c76be54a0986eba08fc4640b5d18bd247f2cad
+7d9f950b698d11eb11aae9f847f9253e91ad4cb56a1b8dc50d19b81362d1
+e1b04661e58fc86b016503bcffb63b3deef03c5dfdfdb7cf2c732d77a0d5
+5ff77d2f6a7ae2a896bc1184c9de0be31924e087e0828628427e0e61f564
+1475c066cc66db890c417df5879f3c6db72d36132e1d87a88cca57c99aa8
+f5f38e5b6911048e5fc827d4170c35f3298ee937f79c7e0f51727ac94602
+191d21bb621246161a5c2cf5260b7e42932b779fcbbb32a391599cf96b46
+2826ddb8c2acb70c4bcc6d8bdb4bfac2691a48bb0d6b7699321352ac3104
+a0bdf7da836a84116f8a52d924fa8db025c37f39dc8af563441c51e317a1
+c2f5242ae9bb32eca30bdd7e304e95d1527b7526992a1279acb46fba73fa
+bf5f038b6081deabb5d2966cee770030d726315080c371aec87cb96ab3d9
+c0858e4fbca3feefc066dc6ca8387326a9eab6e03d1a56e5c5a2ba7254fa
+a91986f2e51a767e8a4b8009ebc6c8cbb6c9024eae983e115bf5d52b9bca
+03bb482da239372f4af2dc92acf7272a35cf622cf6251218df39d9b3d044
+4d36c8b7ef7db3f7eb57df365ced86f4a92d48782c219400b13a0a96ab32
+e09e124b8aa085bc508c44e299b7d5689dbd7ce0981c2127d6853bc099e4
+37ca0592af681ce6ff71a2dd24807997288afa1a407602342d18f0695f44
+2241c897500432fd73529eea55948ca77e86c3f6d4e875aed4dcc5377d05
+5a08cec70057e4133240c63ba28c1ca90623beb512e89f4f3fca56239ad0
+c57a7fa9cc6d4ebc7effb427496fc36d05c395cdeafb5a21dd430c98fd80
+943ec41e7b41a641a28fc257924692a592c1aea49712dfa7baa46f8c5562
+6a1f30fd01105d2f9f460bdffa8342ccad277ba5d11d815b45adad5be5f7
+3bd73eb5e2e5fccc20883bb5a1b5d5d569c9935b0be71e7fb82fb2d1b4c2
+a8dce24236f65d2b8fbff5066fa300f667a4d2b6f150a9b1c2c6e50d6b6f
+642faf0fdb850c6d7efd955f8582384f1a937a9a32dd35747403ba93de7c
+f7ede437edb83e84e9dbaffc0e45f901511dfc3e651434bd58f0fc52c28f
+6cac352eb7ace4ed61f49df8cebfbe0c0964e484d2ca8ca5f1fbc839b907
+f8c2b5a420cca06582868827e9115301faa2bb434e5bc9cc1978217ff5a9
+9a3038acf13a9d8ff87ea545e49da1e9ddd0e953f39ce7fea2b0672b4433
+1d85a03a3015399e4f2d03eb72da4693f733a34bfa872978060e65dc4e42
+894f341473eeed60431ce8fe1f2cfc3e5746c1ead96e228ccd12030bba67
+4bd3efc3db7bc76f56b758a391d44bd6e93a4b65c1b109da98811b08ff4a
+1c98190b24feb0fda2107ff837bb3b29c31afb2ddebc3593ed6d0ff0e88b
+85322230aca6f9cb82d641a67e602c3a0b40a695ac1b7265538a53b04dd2
+2b5439546e8c4ef96070b64469860b82ba4fb73b424f6812cb580e177150
+6a891c678df4851784eb30caa4d3dfe140e518622f8737b86f4d9cffd870
+7132e2b15be6b987dd30a3be8433e7dffde4d62afc8e6ddfcfd68d07b2fd
+e94e4253b75501d2c8e9f556420e14c88993322a24c31f6e37d45ba1a2e0
+34b3f749d3705e43cef545d47af86948448dd0b886cc3a98a1c1b8399bee
+a86ba1f3a69fd5a4ef2cedb670f5b9249e176897e406149ae0c6063da49a
+cafb1dbff711b977dc7f5d4a67366e93c7b7d2cfe461e8faa4d169109c08
+3e6cdd1564e5940d3bcf6421ab684f833c6e53bf76bc7b0b1bf85b0e6d35
+76cc4e86f06a86a241f22e12e5199ce07dfa7460e9f27366ef0f670984ba
+93612d1e68501e5eb5f97a588f71179aa2325cae91456d2a6096c1dda493
+3527dcaa9d23c893408e6b3abd7048b17cb58484cc2c381d3a4decdbd963
+839c343e8ab2165bcf6ec6d3a93de2bd06291b6c04f8658785a2f71a4ccf
+286abb902766a45e9725f0de564d71cf9d514a0d88a2facb119c7f6077d9
+5716e5ac935439b47fa0208e9e5fd9666179f45a21efc417b82e110d6c2c
+b5d724c3fc1032dd5b24644ca4918d4cb4df0b3d8ecddcb2e13baa967d76
+d4abcc2439205e04c93b11240cae025c456de5da2534a524afd87e4e60d6
+2eb1ab7d1d54e23e629dd88754c056e78f057ef66c497d993af61f9b6654
+4a3ca699dfb2edee722219199d4962cb72d34e6f7b5fc4bc45efd1240bf4
+a87a2b88355caa3fbcfbdf6159bc1c72db4489bca279507e8dbe67b168db
+9e6b3ee1e024e42e02cb076ab71ee609f88a109bf00ff75fc91a53d49151
+f1f84fd15f9903f1d3a3c66618c4c00721875f84a9b255466673df7bfefd
+193ab00d239497d5aefa6f78705934f1aaad9b6a51513bae7349cc4f5215
+4c43e03616bcdcdaaa9dbd168dced676bc680ffc6a0ccd9c2f6efe807cf6
+ab5d82d2ba75dca1c2d7e08d25bffd648cd35b1e038274aad7cfc271ffef
+eba50d76d6d22927b4d7931fbbc3cf4aec101e07434cd8baa28d7a344f2b
+4b2755a6f746a66368ccda78a0c40af1c1aef1813213bc1bbd17151ba773
+2dfb8b590378bec84266a3daa34871669db997b178f799c05d310da0d97d
+3ed2f4b31e33e4f134b179818b6faae80ddc1599d04dc8fd1892a95ebb12
+8e719cfb885e13fdbfab96bed732637e75a4237b030990acf70964bc3f16
+b095690c8b54d16270b90045637e0e50947b5b6c0ec4383cf47af58a7771
+22117b1d93912e1d9390d364e7653f920f295fbd79c635a112481583bb78
+1844e3eff4c8667c1f8aabbd6d74f6378611faa1b09175ba98effc02f9ce
+27d66c7d180ce4e8a76da7cdb89901260d72af79f852947f89db2993dd1d
+11ced6202f70b9a6caec7a8213c84eee04363bd2d60bc9bbe93689fafea0
+ede575d489a031519818ae508c599a7b143b1b5fe2ae164a82637b77cbe4
+36d7cd5d1840f1bec3e4d6fabeb3deeabb570cde270070b1417e2c723f85
+3e00a1d1d12a2ec6ca23aa78e136b17c07e7b69a29160d61ba545783a386
+4b1da08942fe40cd220ac3808afc6f69f11c8bc8e2761a74d8738cd41be9
+44fc505b25c3a784e15dbcec050999c8e1f55749c832d64dfe1af119e5dd
+4a05325ecc662bcf7f6a70df6f2b6131ba3d95f0d3563f7f43a678eb9c44
+f7f5aa50a8061a6c16d04e09b8ac05827809beec451af1e2c2530f492a2c
+af5cf38001f2a61686c24c6a1113e9098b2c49f992d32ac4a8f06974ef9f
+974b241121915ece38334c4182780f9e32d4205f7484c033d597c0910d47
+bc3764006d4b5fc28a4615bd27b46e5bb9bb8483b5461933dc9e08693e09
+c267baeb17500d763edefb5036f820081c1ad0c731123206de774fa464b9
+df19e2be494b3b30e29a0b8aad263602357ed11a666272bbb114a1e49043
+1d838be19a268ea96a8d646edc15598038598524796b89a857b0259353d0
+c2560f2b39b6de8383cbb6ca4d0ffb235a2b761ba3f794d067f16fd0e651
+71182614c8c82883bd9203318f38e1279ac713e68ee393efae4c0bef1d4f
+509d19f5404592f0689053d407f1706a3f61eef0ce1d6ebcff4901d87715
+63b0e4fb078597f9c59024b0c67aef020157c09451effb5fba75a9c2780d
+87a865745d0ce8d1f535dd07fe0a17d574bb1457b5d1ee9dc5dc41ec418a
+a318320e5abc070b2b675d1c463f77d727531c787cebb466072d0fdaf224
+a1903f18df46e98bb4cc5288f11f886f570d770b346be00598f99209ebc5
+f2cc5ed4af88a96d6c6324c46e9649b2fc37b56b0a072badb2c7f8af4be1
+ca5978d9db9a45c99d416901cf8c30902d3d4fd413695f18043445888e91
+a76bd572cc4c3ed8eabff296fe8a8ed3320527ee0c9882edf49c6eb839a1
+aafacb82acdb87d4a140970a6a603cdfe8bee72d8a75510e43d169001adb
+292cc6b62d069352c4cff9066e12d8226c14362a30a6288e38515937fc54
+1d1d5ecab8a3291098d33cfaf89339c43844f84ee3c57f1715354fd2ab8f
+efa10d3e04f431b66747e91aee2c935f67d2556beb4b16418b3ca818c8b8
+5f83b592ca9915d341141dc52a66764db0bb74104088d93159c8cf315583
+34e0bfd4c01a122e5ab06f35b751f7fea64f3f07e10643814f38357033b3
+4d82e71cf99e9481bd44f05c9b3ab0ddd0c9028d5b251ef3bc167d6dc137
+75871cad29da1fd91e460150f51506b4fe130454f2e7a3e4c9a4a2d7e6c4
+3291f7d9418d8772f5755660610fa4909b545d594d0bf908c8109279399c
+eb2933d1ecbbddb185b84172610f5b0be712da7e324f9338ba7c56644449
+0f832932fdb33fd09e397be06a0d0ec06e946ff06773a338ede4e3be9fc8
+acf98bc981e1af0c412fc0bd7358932436bddc43b07c061909d929682e7d
+e9872afb6d9b57e96def7ff9ddbe4a64ef21d14189f7005a64d213607abe
+48c67022980cb3681741d633dcc15d5fd3484caceaf5066bafdd863e3eae
+64b6826ed7d74874abacaf28ce9622b1b8d4342a2d833608775f97d0a559
+ce4233008c412fb0117e72e45307b099c64724141506b2a9c565ed541d47
+8f49ae5d98cc9a9b751103efcbb9f09799fa874fd3c9beab0e597ce6eb42
+5f93f4b83560db87f75182a755cca3ddddb8707665a8be010a40ec611704
+6c91e5337fb7ca377ec96f063ba5e1f97bfe1c1214717103606cd3738536
+26fd460620130db020b05f4ea1d3644b2a8da11cdd2c6c2a065117278098
+630bc70fdce0651bc51685841d824fa42df0eab5427c408198db0927c911
+66b46c9d89a760eedb9308a5150c7675bc05ecccbc0051ea8da1fde8132c
+c06412f1d6dce02bc76ffceeb8870564078620f9fa7fda867811a3304f00
+a4169d96e5cfec2ebfa90d81dde07949659d313ff7f8402bdb1eea4ce016
+63e3bec00400aa33f6b816696a13c8dbc338aa192fcc3e06c45b76ea41ef
+156b3645bfc3ee5f1f2b15ef8fef7622007196f9d8279097919a225431e6
+683bb3cabb71dff8d8a579d174b2063f48d63b7fe16a9c83dff1ffaebfd3
+3e9ca293a8c3e6f9501e73900b0f3f5c6986eb2e7a74307b6d86b8480627
+c39c2d01215c4f95baed042305d720dde7116b93190e87d5f5050aa0dbd0
+e8d6988a982e7d2a1b70b3b7f5f8b806f49d3626dd1e5cb70338035df553
+abdb4ce6be4b5f977db8722899ce46c3d0aa8331438f1c22e1697983b82a
+3a6b128f2ae513509fc66d8a56f4f74955716d00081e4f1dcfda34408ffc
+05ca4681379725188378343f875e734bf5ddce99186c9532999800cd4b42
+63105ef314b8ce102a3ec7b5ec0838e6618cc016d8dab5c45976f491cfc1
+f542b6020c907d64f822bb626aa03f04344804da444de14de255853277dd
+1678afaaf82ab3851aafd2c8ffb6b7a25eb5a1165936ac02a53fca5b6a24
+c5b0c9884d01b54895cdc6e64c4f3061d2ea76a7b4f7b0164faf03accd3f
+be9bce7a12d2a37af3f44c2e864fbe8422d461ab553c101f9e21a50bbdcb
+6ddf394e2f80f94a2c721ffdba037688f016c9bec8dc1bbb69ca91b04823
+caa2fd07aa0b1f1071213251d24753fc7a8e152628e23f5bbfcbaecb0f61
+cac8dcc6a8ffca0311483d2798450c4af21f5798763f5b4ec54e99cc25cc
+f0019e95c7b89967eff0e002f576583bf8ffa66850006e9feb0f46183c41
+186476ffc10e193c6912ff8517ac215ccbbf210762c4d3318a83a08947b7
+f3807217fa8d155a3eab3bf2a8cd65cfe9764e8d9998b1d972cacf112738
+d7804c4d2f545529031f81306f5fbbe974063935754c8d8a55ccce35fef8
+0dbb6319a40c2484da95c777d9ab30de56f071ec3298e3163358c5f2d7d0
+b8968ca4df727b8c7c7e571236b7fc308d6c9aed824a7ea3527fccf2626e
+ead5810d45df801ab75cd958cb42a00ff9734ae6a9d870a4392d6249962f
+81bb145d623f5f380406025d4e3a491509439ca5c95579386162aa02d457
+4080aaafda2003a2cc680165749fd5dceaa91bf47bd838f16a21e116a396
+e9e6f758d41df50d3f1610f7d8a65257ae00f2cede6cab0ada9b16d9addc
+30cb7a068b358e247ab5c1810922a70e23d60fcb5d3c67089dd4024c5b9c
+bbaeab1ce8847671732026ec1a6043e38ae228cfc27b0b5b27b2304ee1ad
+b7bc8289edba34935bca94f680fa5eec2dd45f10cf13732b8698d84aa2bb
+5f5db833d672cd7506da8fa396b0845d8994b9be69a515b9a099f3149247
+8f824413a40dd76c862830f89db2f21531141d5ead597fa5d816bb015cc8
+ee87ba594bcf0c717544f32eb695e911f585f593af6852cd27ae6b25e063
+29e7576a9855d0d7cf76e81dc8b6a42a3196d178112ec5b62994af67ffb9
+db4526c76f049b43a251f82426a002d760ea17104cc5702cf5c0dd20454f
+b833d247d38352c951e412d4d5688c1991e4e570ddc3f514218dd1d5ea64
+36a094f14a96983e13b5e5997cb2d115abdd35c8d8d64ec1ba0c0b1da86f
+c40bb1a456c03d79be63a870e9a882c235950bebab733b5a50adb07c35bd
+8c7f8807f603fd0734b496e1a783e518a9069bc22ce8f48f29b905a18f11
+0fda8ee43acf22bedf99b2ebb1e607d1ab920dc290e30d041c468a0cf27d
+948351d50c7205755264dc6add5279ca172abf27ba1b93a623f2e4796409
+592ce84c1ae4102e4b9221c6a8c8466319e6bfe089759d68dd58f74c19b3
+df9e140aa31ac26b7544a8497365507b35f85586b6025581b80f6647fff7
+1339acdd01c2fe36c6b7e615ca23304a828fb79d891545ab8cf5d15129b9
+75aa66132b89bd18e89a9106b7a95de04a3bb4f0802571886c5c38d05ad0
+9a3be3bb2960128bf22b70a8102a2c2063834c969cf050a5af3c050a3347
+358e00fdb0391dc3e0befdb1e52178243a0dde5dc83fc7a854eba1982ce7
+ff65e750b9c4dd86ddb7ff4ae7b72702d3cbc7a0b369102d247cae19677d
+998f7b550f901ada79a82319f24e1806f44dd825326d7f5df6a9c0bb9546
+eb28e1d6dbdb2cc18ba3d463abd838b208419c168a2de68f252825faf425
+fe397f852fbfb4d379696e73b84b9a876458f526a623a5a0238a210cd5bb
+715c33d3a8b48352902c2d83d18952c55fa749885132ab6b7e6db794b159
+88b9d511438124d8dde3678a74654f9253d0b8b5703bd0d35b3f7ea294fd
+d9b44601a8e73ccb3fdbd980c2391d4c7928b41b46e9ad163886acc2b68c
+5c4c2a06911a7fb36ecc544b7d886c75dacb52308ee0efea5e3f16a11028
+a53929f7b495389601bdca158609b9d8be1a5d68e5ce3827189a0f4a7e18
+2db0eb81fa0dcd6c587098f264a3d0e2049f84c8a4e8ff503a68e8102b43
+6a4bc956eb9081143cf2cb903aba73070f8b3c4721c361fd398f7d17b363
+dfffdfce66c02f2a7b110a9626a8fd9b7f053b286a7d7ac4d57ac019b77f
+9051ff0972190fdc0968f8d527afc6d8e70d9c638c33bfea751e62d1d449
+0027c64e60cbe9c5aeb395bc6d692796dda167bd5bbbd233ed01ce57a8df
+6faebf95c6c7539339f31397c1582d47fa00a40e236b7bca3a3bdaa06e53
+350f664c12e10f4b174195986e94c98699bafbd3105aff22a82f8d54e1a4
+88e44842bc58dedbbace508e3a69dd35dba1f0f0d69e34651bb078232519
+dbeed3b29d2dcee4b449be5f39a41d2e0c84ab52609f8bb0b3b85d0cbcfe
+85a9ddd9bce5f1636b4dd7e7c77cdf6a025fcc206b9104ead365d8b52f42
+77d64ad3ec49aca1bb60b87b9f39d40678e3b2c8ad69d1b5d3fa6d0991bf
+f3faadc1225617411fb4ba6b79b3eff8f3e0802d0092567f1c3d43118ed3
+0d3d90807474808a9bb5f07f31371f3a4cae9ede2f758875145f1f4be72e
+8c7a8f1a733f91c761039025275d15f76daa677fb447795ca639a5c9f9e4
+bcf3c2c06bbe0202187ccc5f2cffbbc208641a52da611d40b08908500375
+829b8ceb8c93c7398389264b3821de6d37acca04fcbcd02499847b4297fd
+cdb15ca26fbf868d5e335a3e0f3980ceb288149424968bc10ab2466a15ce
+dbdf550eea623c162a3a7963d657ced119101602898b23d7cb99618b5b3d
+59868f5ac31ce289ef1df56ba4c5c398068d5a928a4aa53325d95bd1c774
+f0d1d503628ba1546f464303e0f454cc6aca98d032acf05872da95a9188d
+0f224b875c05157c2fc993d65521a770e6962407a22c0f2a14b80064bbc7
+4f496c61b44255c40c51bdf60dbfa7900f77296d59abf61f964fefb6aff3
+f5dccdd7a812fb5ec30c6dc8063bd828f6adead242dc0a6e72b100a694ac
+24089d150b8729de5a322ad77d84e7f4a62570a178f0a9ec0dd32a7b9091
+78d9a544430cff30e2e570dbbb649d9e19554b39546713047ee0861b8a0d
+960f690d2e2e160f24f152f6f0a93f6b13b1eb2477a416fbf3c15296ddb1
+3a3d09f771d8618a85dec2362f88d117f1bb174e829f96f9be965b175321
+a3bb0746376b95260b82cf34134d29ba6425d9b86e764791d699784151bf
+26d4dc5b01cc0f88261df88e3cabb371d334e1a2f5f60952ec7038403f20
+45f70925e9d8b49ecc330bd90f563d3894b15ce629e686e3bae594e5c251
+2f7982eab95fd43cd595d8ec5fdf962f5e5277e416a91c279178bd98d082
+ced5655015c9f425c048aec135f5bf41260dea74fc1c16984c3db8deaa0a
+65c1426b7a5e91ac5f67e222905efcdd297c1caa1dfc17fa1a3de462d320
+0a1491d41b26f799475daed3d6e3b1fe923d3cac505823a1e77ce6b07c0c
+2efec207347a8e44d3c5d196376c7b7edce7c9bed0519da191a63fab427a
+b930c1156f51c8d5ac5bd9d062e0e04089355df1619450c40d0050becf10
+37bdc9b62d7d4c90b76219991d215a37b31091cfd832d6a95669dd02b904
+0ac2b60419dcf064aa70a3c91a10e5e4087093246fb95645828a758d835f
+51dcc7ab133b360dbb003ceeaaa1102dfc07931f0ee238273d9dc4c9c8b8
+ff089232bf823ffdd7a33d0d7e142070f240d078fdf590dafd88b89629b0
+275af422eb54bc1285eae58cad06bc2b12d5a0c2bfe51c4d1082aa23eaaf
+334271c0523e3193d6aa4b6a30bcca62edb662d30d93f5f553a211612cc2
+ea7da1d19112cb981727edf44136ef358eda02444649008a8e9db0985ace
+34a56bccd493378138af3f1632cd885259f01f97a38b185443e3b4408aaa
+06c09529403545dc768be1f6e4b4e85ec2f094ab06d4ed78620489de9014
+ed3d4a76af19a75c3d65c73cf8b3aeda993e97289bba416758d561d6dc12
+23f3a5a740c2a64fe4aa02a8af2efff0a3fd8c0dacc5b6a9f0eae8833359
+bf6bef10d03bd931f05bea5cc117e21aa4e3a486845357a256af1ac28296
+7169745bce4592b4501cf410e4045a8ac47bf72f802ce93e562948b00848
+73f33f872340b4930954a97ae25e9c74677117ebbacc18e5cf9da28961e6
+442c545f7ee10d0689cad67b5e7e9abcbad934672e013a622bcde541a2ba
+ea62f957c199fc3eeb1bb8091ed8ac159f5afb61d35893afbaa5883c5a97
+b0dab2b2c4ba2ff7a30935882011248f8d9e6d23b4a3d91a71df66c0398c
+65be4cc71cba58bd19cbc9d5f7bdb30dfe9fa814c9d8b505b2bc3098a220
+4c5d35f353e66576e032fc0d23d2a2d49ed27d4ea0e4e0c17e6cfce3cc97
+470e9292faeda13b6647da7c64c7a717620980de1323c6040fb8f22e2537
+240422e2248bef0dcce6fc223b8720fc9dfe3c47809b31fddf8079d638f8
+690f441eea511b9cf818fbe872ff3e2a0a2950f9acdbb88d48b9d7648091
+5b0dd985074c0429e9f4ec356c6d1f418096ead18cb7669dce76e8b21a6b
+0cf19dbaf1e79e2c70a1888ffcae76174518c355c3f733b6d051d9371b79
+6908c09ba1cb9fe3c7e16e4529912126b5253eff6acecda3c37fccc761f9
+d781f0c75eb7075c121c68540706958e26166e19e1c0b29ee08d2c2382f9
+9ac70ee4ee4a6296a4ffec552f3db6471aa42d3b38857223fe511d0aa35a
+84b1c1205a304b2d0bfc95fffbd603e8e6f42e60017a2808babe00c270ce
+ba6f93b83bb9c41c7787992734171fc2a4f0b46f06c6f029c82ccc985b7c
+3c84ea655478ff79e8ab8fe6cce591ecb39c353a
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
diff --git a/install-sh b/install-sh
new file mode 100755
index 000000000..398a88e14
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ :
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=$mkdirprog
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ :
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ :
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ :
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+ '
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ :
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ :
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/locale/C/cups_C b/locale/C/cups_C
new file mode 100644
index 000000000..cd4a5bca0
--- /dev/null
+++ b/locale/C/cups_C
@@ -0,0 +1,135 @@
+iso-8859-1
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Color
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Color Saturation:
+Color Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Options Installed
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/Makefile b/locale/Makefile
new file mode 100644
index 000000000..cf0523c07
--- /dev/null
+++ b/locale/Makefile
@@ -0,0 +1,76 @@
+#
+# "$Id$"
+#
+# Locale file makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# Locales...
+#
+
+LOCALES = C be cs de en en_US es fr he it ru_RU sv uk uk_UA zh_CN
+
+
+#
+# Make everything...
+#
+
+all: translate
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(LOCALEDIR)
+ for dir in $(LOCALES) ; do \
+ $(INSTALL_DIR) $(LOCALEDIR)/$$dir ; \
+ $(INSTALL_DATA) $$dir/cups_$$dir $(LOCALEDIR)/$$dir ; \
+ done
+
+
+#
+# translate - a simple utility to use Bablefish to translate the POSIX message
+# file to one of several languages.
+#
+# translate outfile language
+#
+
+translate: translate.o ../cups/$(LIBCUPS)
+ echo Linking $<...
+ $(CC) $(LDFLAGS) -o translate translate.o $(LIBS)
+
+translate.o: ../cups/http.h
+
+
+#
+# End of "$Id$".
+#
diff --git a/locale/be/cups_be b/locale/be/cups_be
new file mode 100644
index 000000000..ca7e7da42
--- /dev/null
+++ b/locale/be/cups_be
@@ -0,0 +1,134 @@
+utf-8
+Добра
+ÐдмÑніць
+Даведка
+ВыйÑьці
+Зачыніць
+Так
+Ðе
+Уключыць
+Выключыць
+Захавць
+Ðдкінуць
+Дапомна
+Выбары
+Больш зьвеÑтак
+Чорны
+КалÑровы
+Cyan
+Magenta
+Жоўты
+ÐўтарÑÐºÑ–Ñ Ð¿Ñ€Ð°Ð²Ñ‹ Ñž 1993-2004 гадох належаць Easy Software Products. УÑе правы абаронены.
+ÐгульныÑ
+Друкаркі
+ВідарыÑ
+HP-GL/2
+ДадатковыÑ
+ДакумÑнт
+Іншае
+Друк Ñтаронак:
+УвеÑÑŒ дакумÑнт
+Прамежак Ñтаронак:
+Ðдваротны парадак:
+Фармат Ñтаронак:
+ 1-Up
+ 2-Up
+ 4-Up
+РаÑьцÑгваньне відарыÑаў:
+ВыкарыÑтоўваць Ñапраўдны памер відарыÑаў
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+ÐаÑычанаÑьць колеру:
+Ðдценне колеру:
+РаÑьцÑгнуць да памераў Ñтаронкі:
+Shading:
+Ð¨Ñ‹Ñ€Ñ‹Ð½Ñ Ð°Ñадкі:
+Выпраўленьне гамы:
+ЗыркаÑьць:
+Дадаць
+Выдаліць
+ЗьмÑніць
+URI друкаркі
+Ðазва друкаркі
+Знаходжаньне друкаркі
+ЗьвеÑткі пра друкарку
+Вытворца Ñ– мадÑль друкаркі
+URI прылады
+Фарматаваньне Ñтаронкі
+Друк Ñтаронкі
+ІніцыÑÐ»Ñ–Ð·Ð°Ñ†Ñ‹Ñ Ð´Ñ€ÑƒÐºÐ°Ñ€ÐºÑ–
+Стан друкаркі
+Прыймае заданьні
+Ðе прыймае заданьні
+Друк заданьнÑÑž
+КлÑÑÑ‹
+ÐœÑÑцоваÑ
+ÐддаленаÑ
+Здвоены друк
+Stapling
+Ð¥ÑƒÑ‚ÐºÑ–Ñ ÐºÐ¾Ð¿Ñ–Ñ–
+Collated Copies
+Hole Punching
+Covering
+Binding
+Упарадкаваньне
+Маленькі (да 9.5x14 цалÑÑž)
+СÑÑ€Ñдні (ад 9.5x14 цалÑÑž да 13x19 цалÑÑž)
+Ð’Ñлікі (ад 13x19 цалÑÑž Ñ– больш)
+ÐдмыÑловы памер
+БÑзьдзейнічае
+Друкуе
+Спынена
+УÑе
+ÐÑцотны
+Цотны
+ЦÑмней СьвÑтлей
+Памеры аркушаў
+Від аркушаў
+Крыніца аркушаў
+СпаглÑданьне:
+Ð’Ñртыкальнае
+Гарызантальнае
+Стан заданьнÑ
+Ðазва заданьнÑ
+Уліковае імÑ
+ПрыÑрытÑÑ‚
+Копіі
+Памер файла
+Pending
+РÑжым вываду
+Разрозьненьне
+ТÑкÑÑ‚
+Прыгожы друк
+Палі
+Левае
+Правае
+ВерхнÑе
+ÐіжнÑе
+Ðазва(Ñ‹) файла(Ñž)
+Ðадрукаваць
+УÑталÑÐ²Ð°Ð½Ñ‹Ñ Ð·Ñ€ÑƒÑ‡Ð½Ð°Ñьці
+Ðўтаматычна
+400 Ваш вандроўнік даÑлаў запыт, Ñкі гÑÑ‚Ñ‹ паÑлужнік Ð½Ñ Ð¼Ð¾Ð¶Ð° зразумець.
+ПаÑлужнік Ð½Ñ Ð¼Ð¾Ð¶Ð° ўпÑўніцца, што вы аўтарызаваны на доÑтуп да гÑтага раÑурÑа.
+Ð’Ñ‹ муÑіце плаціць за доÑтуп на гÑÑ‚Ñ‹ паÑлужнік.
+Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў каб атрымаць доÑтуп да раÑурÑа на гÑтым паÑлужніке.
+Запатрабаваны раÑÑƒÑ€Ñ Ð½Ñ Ð±Ñ‹Ñž адшуканы на гÑтым паÑлужніке.
+Запатрабаваны мÑтад не дазволены Ð´Ð»Ñ Ñ€Ð°ÑурÑа.
+Ðдпаведнае форма Ð´Ð»Ñ Ð³Ñтага раÑурÑа не была знойдзена на на гÑтым паÑлужніке.
+Ð’Ñ‹ Ð½Ñ Ð¼Ð°ÐµÑ†Ðµ правоў, каб выкарыÑтоўваць гÑÑ‚Ñ‹ паÑлужнік у ÑкаÑьці паўнамоцнага вузла.
+Запыт займе вельмі шмат чаÑу, таму ён быў пÑÑ€Ñрваны.
+Запатрабаваны раÑÑƒÑ€Ñ Ð¼Ð°Ðµ больш чым адно значÑньне.
+Запатрабаваны раÑÑƒÑ€Ñ ÑкончыўÑÑ Ð¹ Ð½Ñ Ð±ÑƒÐ´Ð·Ðµ заменены.
+Запатрабаваны мÑтад патрабуе Ñ€ÑчаіÑнае значÑньне Content-Length.
+The precondition on the request evaluated to false.
+Запыт занадта вÑлікі, каб апрацаваць Ñго на гÑтым паÑлужніке.
+Запатрабаваны URI занадта вÑлікі Ð´Ð»Ñ Ð³Ñтага паÑлужніка каб апрацаваць Ñго.
+Запатрабаваны фармат зьÑўлÑецца незразумелым Ð´Ð»Ñ Ð³Ñтага паÑлужніка.
+500 ГÑÑ‚Ñ‹ паÑлужнік знайшоў невыправімую памылку й Ð½Ñ Ð¼Ð¾Ð¶Ð° апазаваць ваш запыт.
+Запатрабаваны мÑтад не ажыцьцÑўлÑецца гÑтым паÑлужнікам.
+Паўнамоцны паÑлужнік атрымаў нерÑчаіÑны адказ ад вышÑйÑтаÑчага паÑлужніка.
+Запатрабаваны раÑÑƒÑ€Ñ Ñƒ бÑгучы момант недаÑтупны на гÑтым паÑлужніке.
+Паўнамоцны паÑлужнік зашмат чаÑу дае адказ гÑтаму паÑлужніку.
+ГÑÑ‚Ñ‹ паÑлужнік не падтрымлівае вÑÑ€ÑÑ‹ÑŽ HTTP, Ñкую патрабуе ваш вандроўнік.
diff --git a/locale/cs/cups_cs b/locale/cs/cups_cs
new file mode 100644
index 000000000..8526c4d6f
--- /dev/null
+++ b/locale/cs/cups_cs
@@ -0,0 +1,135 @@
+iso-8859-2
+OK
+Zru¹it
+Nápovìda
+Ukonèit
+Zavøít
+Ano
+Ne
+Zap
+Vyp
+UloŸit
+Zahodit
+Výchozí
+MoŸnosti
+Více informací
+Èerná
+Barva
+Azurová
+Purpurová
+®lutá
+Copyright 1993-2004 by Easy Software Products, v¹echna práva vyhrazena.
+Obecné
+Tiskárna
+Obrázek
+HP-GL/2
+Extra
+Dokument
+Ostatní
+Vytisknout stránky:
+Celý dokument
+Rozsah stránek:
+Obrácené poøadí:
+Formát stránky:
+ 1-Up
+ 2-Up
+ 4-Up
+Zvìt¹ení obrázku:
+PouŸít pøirozenou velikost
+Zvìt¹it podle procent
+Zvìt¹it podle PPI
+Zrcadlit obrázek:
+Barevné nasycení:
+Svìtlost:
+Pøizpùsobit stránce:
+Stínování:
+©íøka pera:
+Gamma korekce:
+Jas:
+Pøidat
+Smazat
+Zmìnit
+URI tiskárny
+Název tiskárny
+Umístìní tiskárny
+Info o tiskárnì
+Model tiskárny
+URI zaøízení
+Formátuji stránku
+Tisknu stránku
+Inicializuji tiskárnu
+Stav tiskárny
+Pøijímá úlohy
+Nepøijímá úlohy
+Vytisknout úlohy
+Tøída
+Lokální
+Vzdálená
+Duplexní
+Se¹ití
+Rychlé kopie
+Srovnané kopie
+Dìrování
+Obal
+Vazba
+Tøídìní
+Malé (aŸ do 9.5x14in)
+Støední (od 9.5x14in do 13x19in)
+Velké (13x19in a vìt¹í)
+Vlastní velikost
+Neèinná
+Probíhá zpracování
+Zastaveno
+V¹e
+Liché
+Sudé
+Svìtlej¹í Tmavìj¹í
+Velikost média
+Typ média
+Zdroj média
+Orientace:
+Portrét
+Krajina
+Stav úlohy
+Název úlohy
+UŸivatelské jméno
+Priorita
+Kopie
+Velikost souboru
+Nevyøízená
+Výstupní reŸim
+Rozli¹ení
+Text
+Hezký tisk
+Okraje
+Vlevo
+Vpravo
+Dole
+Nahoøe
+Soubor(y)
+Tisk
+Options Installed
+Auto
+400 Vá¹ prohlíŸeè odeslal poŸadavek, kterému tento server nerozumí.
+Server nemohl ovìøit, zda máte oprávnìní pøistupovat k tomuto zdroji.
+Pøístup k tomuto serveru je placený.
+Nemáte oprávnìní pøistupovat k tomuto zdroji.
+PoŸadovaný zdroj nebyl nalezen na tomto serveru.
+PoŸadovaná metoda není pøípustná.
+Odpovídající reprezentace zdroje nebyla nalezena.
+Nemáte oprávnìní pouŸívat tento server jako proxy hostitele.
+PoŸadavek zabral pøíli¹ mnoho èasu a byl pøeru¹en.
+PoŸadovaný zdroj má více neŸ jednu hodnotu.
+PoŸadovaný zdroj byl zru¹en bez náhrady.
+PoŸadovaná metoda vyŸaduje platné pole Content-Length.
+Podmínka tohoto poŸadavku byla vyhodnocena zápornì.
+PoŸadavek je pro tento server pøíli¹ velký ke zpracování.
+URI poŸadavku je pro tento server pøíli¹ velké ke zpracování.
+Formát poŸadavku nebyl serverem pochopen.
+426 Je vyŸadována aktualizace na zabezpeèený protokol. Vidíte-li tuto zprávu ve WWW prohlíŸeèi, znamená to, Ÿe není podporován.
+500 Server narazil na kritickou chybu a nemùŸe pokraèovat ve zpracování poŸadavku.
+PoŸadovaná metoda není implementována.
+Proxy server obdrŸel neplatnou odpovìï od nadøazeného serveru.
+PoŸadovaný zdroj je momentálnì nedostupný.
+Proxy server zabral pøíli¹ mnoho èasu na odpovìï tomuto serveru.
+Tento server nepodporuje HTTP ve verzi, kterou poŸaduje vá¹ prohlíŸeè.
diff --git a/locale/de/cups_de b/locale/de/cups_de
new file mode 100644
index 000000000..9c8092859
--- /dev/null
+++ b/locale/de/cups_de
@@ -0,0 +1,136 @@
+iso-8859-15
+Okay
+Abbrechen
+Hilfe
+Beenden
+Schließen
+Ja
+Nein
+An
+Aus
+Speichern
+Verwerfen
+Default
+Optionen
+Mehr Info
+Schwarz
+Farbe
+Cyan
+Magenta
+Gelb
+Copyright 1993-2002 durch Easy Software Products, alle Rechte vorbehalten.
+Allgemein
+Drucker
+Bild
+HP-GL/2
+Speziell
+Dokument
+Andere
+Druckbereich:
+Gesamtes Dokument
+Seitenbereich:
+Umgedrehte Reihenfolge:
+Seitenformat:
+ normal
+ 2 auf 1
+ 4 auf 1
+Bild-Skalierung:
+Natürliche Bildgröße
+Zoom in Prozent
+Zoom in PPI
+Gespiegelte Ausgabe:
+Farbsättigung:
+Farbton:
+Auf Seite anpassen:
+Schattiert:
+Strichstärke:
+Gamma-Korrektur:
+Helligkeit:
+Hinzufügen
+Löschen
+Ändern
+Drucker-URI
+Drucker-Name
+Drucker-Standort
+Drucker-Info
+Drucker-Modell
+Device-URI
+Formatiere Seite
+Drucke Seite
+Initialisiere Drucker
+Drucker-Zustand
+Bereit
+Nicht bereit
+Druckaufträge
+Klasse
+Lokal
+Remote
+Duplex
+Hefter
+Schnellkopien
+Sortieren/Gruppieren
+Locher
+Deckblatt
+Bindung
+Sortieren
+Klein (bis 14x35cm)
+Medium (14x35cm bis 33x48cm)
+Groß (33x48cm und größer)
+Benutzerspezifische Größe
+Leerlauf
+In Arbeit
+Gestoppt
+Alles
+Ungerade
+Gerade
+Dunkler Heller
+Medien-Größe
+Medium
+Medien-Quelle
+Ausrichtung:
+Hochformat
+Querformat
+Job-Status
+Job-Name
+Benutzername
+Priorität
+Kopien
+Dateigröße
+In Warteposition
+Ausgabe-Modus
+Auflösung
+Text
+Spezieller Druck
+Seitenränder
+Links
+Recht
+Unterseite
+Oberseite
+Dateiname(n)
+Drucker
+Installierte Optionen
+Automatisch
+400 Der Server versteht die Anfrage Ihres Browsers nicht.
+Der Server konnte nicht Ihre Berechtigung überprüfen, diese Ressource zu benutzen.
+Sie müssen bezahlen, um auf diesen Server zuzugreifen.
+Sie sind nicht berechtigt, auf diese Ressource des Servers zuzugreifen.
+Die gewünschte Ressource wurde auf diesem Server nicht gefunden.
+Die gewünschte Methode ist mit dieser Ressource nicht erlaubt.
+Eine passende Art der Ressource wurde auf diesem Server nicht gefunden.
+Sie können diesen Server nicht als Proxy-Server verwenden.
+Der Auftrag brauchte zu lang zur Beendigung und wurde abgebrochen.
+Die gewünschte Ressource besitzt mehr als einen Wert.
+Die gewünschte Ressource existiert nicht mehr und wurde nicht ersetzt.
+Die gewünschte Methode benötigt eine gültige Länge des Inhalts.
+Die Voraussetzungen für den Auftrag sind nicht erfüllt.
+Der Auftrag ist zu groß, um auf diesem Server verarbeitet zu werden.
+Die URI des Auftrags ist zu groß, um auf diesem Server verarbeitet zu werden.
+Das Format des Auftrags wird von diesem Server nicht verstanden.
+426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.
+500 Der Server hat einen nicht behebbaren Fehler entdeckt und kann Ihren Auftrag nicht verarbeiten.
+Die gewünschte Methode ist auf diesen Server nicht implementiert.
+Der Proxy-Server empfing eine unzulässige Antwort von einem höheren Server.
+Die gewünschte Ressource ist aktuell auf diesem Server nicht verfügbarr.
+Der Proxy-Server braucht zu lang, um auf diesen Server zu reagieren.
+Dieser Server unterstützt nicht die HTTP-Version, die Ihr Browser benötigt.
+
diff --git a/locale/en/cups_en b/locale/en/cups_en
new file mode 100644
index 000000000..059e62b2b
--- /dev/null
+++ b/locale/en/cups_en
@@ -0,0 +1,135 @@
+iso-8859-15
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Colour
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Colour Saturation:
+Colour Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Options Installed
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/en_US/cups_en_US b/locale/en_US/cups_en_US
new file mode 100644
index 000000000..cd4a5bca0
--- /dev/null
+++ b/locale/en_US/cups_en_US
@@ -0,0 +1,135 @@
+iso-8859-1
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Color
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Color Saturation:
+Color Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Options Installed
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/es/cups_es b/locale/es/cups_es
new file mode 100644
index 000000000..4b8f7854d
--- /dev/null
+++ b/locale/es/cups_es
@@ -0,0 +1,135 @@
+iso-8859-15
+OK
+Cancelar
+Ayuda
+Salir
+Cerrar
+Si
+No
+On
+Off
+Guardar
+Descartar
+Predeterminado
+Opciones
+Más información
+Negro
+Color
+Cian
+Magenta
+Amarillo
+El copyright 1993-2004 es de Easy Software Products. Todos los derechos reservados.
+General
+Impresora
+Imagen
+HP-GL/2
+Extra
+Documento
+Otro
+Imprime páginas:
+Todo el documento
+Rango de páginas:
+Orden inverso:
+Formato de página:
+ 1-Arriba
+ 2-Arriba
+ 4-Arriba
+Escalado de imagen:
+Usar tamaño natural de la imagen
+Zoom por porcentaje
+Zoom por PPI
+Imagen espejo:
+Saturación del color:
+Tonalidad del color:
+Ajustar a la página:
+Sombreando:
+Anchura de pluma:
+Corrección gamma:
+Brillo:
+Añadir
+Borrar
+Modificar
+URI de la impresora
+Nombre de la impresora
+Ubicación de la impresora
+Información de la impresora
+Fabricante y modelo de la impresora
+URI de la conexión
+Formateando página
+Imprimiendo página
+Inicializando impresora
+Estado de la impresora
+Aceptando trabajos
+No aceptando trabajos
+Imprimiendo trabajos
+Clase
+Local
+Remota
+Desdoblando
+Grapando
+Copias rápidas
+Copias cotejadas
+Agujereando
+Cubriendo
+Encuadernando
+Ordenando
+Pequeño (hasta 9.5x14 pulgadas)
+Medio (9.5x14 a 13x19 pulgadas)
+Grande (13x19 pulgadas y mayor)
+Tamaño personalizado
+Inactivo
+Procesando
+Parado
+Todo
+Impar
+Par
+Más oscuro Más claro
+Tamaño del papel
+Tipo de papel
+Origen del papel
+Orientación:
+Retrato
+Apaisado
+Estado del trabajo
+Nombre del trabajo
+Nombre de usuario
+Prioridad
+Copias
+Tamaño del archivo
+Pendiente
+Modo de salida
+Resolución
+Texto
+Impresión especial
+Márgenes
+Izquierda
+Derecha
+Abajo
+Arriba
+Nombre(s) de archivo
+Imprimir
+Opciones instaladas
+Auto
+400 Su navegador envió una petición que este servidor no entiende.
+Este servidor no puede verificar que esté autorizado a acceder al recurso.
+Debe pagar para acceder a este servidor.
+No tiene permiso para acceder al recurso en este servidor.
+El recurso solicitado no fue encontrado en este servidor.
+El método solicitado no se permite con el recurso.
+Una representación adecuada del recurso no se ha encontrado en este servidor.
+No tiene permiso para usar este servidor como proxy.
+La petición lleva mucho tiempo sin ser completada y ha sido cancelada.
+El recurso solicitado tiene más de un valor.
+El recurso solicitado ya no está y no ha sido reemplazado.
+El método solicitado requiere un 'Content-Length' válido.
+La condición previa de la solicitud se evaluó como falsa.
+La solicitud es demasiado larga para ser procesada por este servidor.
+La URI solicitada es demasiado larga para ser procesada por este servidor.
+Este servidor no entiende el formato solicitado.
+426 Se requiere una actualización a una conexión segura. Si está viendo este mensaje en su navegador, entonces éste no soporta actualizaciones de encriptación HTTP.
+500 El servidor ha detectado un error irrecuperable y no puede procesar su solicitud.
+El método solicitado no está implementado en este servidor.
+El servidor proxy recibió una respuesta incorrecta de un servidor anterior.
+El recurso solicitado no está disponible actualmente en este servidor.
+El servidor proxy tarda mucho en responder a este servidor.
+Este servidor no soporta la versión HTTP requerida por su navegador.
diff --git a/locale/fr/cups_fr b/locale/fr/cups_fr
new file mode 100644
index 000000000..5418f01ad
--- /dev/null
+++ b/locale/fr/cups_fr
@@ -0,0 +1,135 @@
+iso-8859-15
+OK
+Annulation
+Aide
+Quitter
+Fermer
+Oui
+Non
+Oui
+Non
+Sauver
+Quitter
+Standard
+Options
+Plus d'informations
+Noir
+Couleur
+Cyan
+Magenta
+Jaune
+Copyright 1993-2002 par Easy Software Products, tous droits réservés.
+Général
+Imprimante
+Image
+HP-GL/2
+Options supplémentaires
+Document
+Autre
+Pages d'impression:
+Document entier
+Plage de pages
+Ordre inverse:
+Pages par feuille:
+ 1
+ 2
+ 4
+Echelle de l'image:
+Utiliser taille normale d'image
+Pourcentage zoom
+Zoom par PPI
+Retournement image:
+Saturation de couleur:
+Teinte:
+Adapter à la page:
+Shading:
+Largeur de tracé:
+Correction Gamma:
+Luminosité:
+Ajouter
+Effacer
+Modifier
+URI de l'imprimante
+Nom de l'imprimante
+Emplacement de l'imprimante
+Information de l'imprimante
+Type et modèle de l'imprimante
+URI de périphérique
+Formatage de la page
+Impression de la page
+Initialisation de l'imprimante
+Etat de l'imprimante
+Accepte les travaux
+Rejette les Travaux
+Travaux d'impression
+Classes
+Locale
+A distance
+Recto-verso
+Agrafage
+Copies rapides
+Copies assemblées
+Perforation
+Couverture
+Reliure
+Tri
+Petit (jusqu'à 9.5x1pouce)
+Moyen (9.5x1pouce à 13x19pouce)
+Grand (13x19pouce et plus grand)
+Taille personnalisée
+Au repos
+En fonctionnement
+Arrêté
+Tout
+Impair
+Pair
+Plus foncé Plus clair
+Dimensions du support
+Type de support
+Source des supports
+Orientation:
+Portrait
+Paysage
+État du travail
+Nom du travail
+Nom de l'utilisateur
+Priorité
+Copies
+Taille du fichier
+En attente de traitement
+Mode de sortie
+Résolution
+Texte
+Impression améliorée
+Marge
+Gauche
+Droite
+Bas
+Haut
+Nom fichier(s)
+Imprimer
+Options installées
+Automatique
+400 Votre navigateur a envoyé une demande que ce serveur ne pouvait pas comprendre.
+Ce serveur n'a pas pu vérifier que vous êtes autorisé(e) à utiliser la ressource.
+Vous devez payer pour accéder à ce serveur.
+Vous n'avez pas la permission d'utiliser la ressource sur ce serveur.
+La ressource demandée n'a pas été trouvée sur ce serveur.
+La méthode demandée n'est pas autorisée avec cette ressource.
+Une représentation appropriée pour la ressource n'a pas été trouvée sur ce serveur.
+Vous n'avez pas la permission d'utiliser ce serveur comme serveur d'impression mandataire (proxy).
+La demande a mis trop de temps à se terminer et a été interrompue.
+La ressource demandée a plus d'une valeur.
+La ressource demandée a disparu et n'a pas été remplacée.
+La méthode demandée exige un attribut Content-Length contenant une valeur correcte.
+La condition préalable sur la demande a donné un résultat à la valeur "faux".
+La demande est trop grosse pour ce serveur.
+L'Uri de demande est trop grande pour être traitée par ce serveur.
+Le format de demande n'est pas compris par ce serveur.
+426 Une mise à jour de connexion sécurisée est nécessaire, si vous voyez ce message dans votre navigateur "web", celui-ci ne prend pas en charge les mises à jour d'encryptage HTTP.
+500 Le serveur a détecté une erreur irrémédiable et ne peut pas traiter votre demande.
+La méthode demandée n'est pas prise en charge par ce serveur.
+Le serveur mandataire (proxy) a reçu une réponse incorrecte d'un serveur ascendant.
+La ressource demandée est actuellement indisponible sur ce serveur.
+Le serveur mandataire (proxy) a pris trop longtemps pour répondre à ce serveur.
+Ce serveur ne supporte pas la version de HTTP exigée par votre navigateur.
diff --git a/locale/he/cups_he b/locale/he/cups_he
new file mode 100644
index 000000000..4823b71aa
--- /dev/null
+++ b/locale/he/cups_he
@@ -0,0 +1,135 @@
+iso-8859-8
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Colour
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Colour Saturation:
+Colour Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Options Installed
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+426 An upgrade to a secure connection is required. If you are seeing this message in a web browser then it does not support HTTP encryption upgrades.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/it/cups_it b/locale/it/cups_it
new file mode 100644
index 000000000..fc5e46161
--- /dev/null
+++ b/locale/it/cups_it
@@ -0,0 +1,135 @@
+iso-8859-15
+Continua
+Annulla
+Aiuto
+Esci
+Chiudi
+Sì
+No
+Attivo
+Inattivo
+Salva
+Abbandona
+Predefinito
+Opzioni
+Maggiori informazioni
+Nero
+Colore
+Ciano
+Fucsia
+Giallo
+Copyright 1993-2004 by Easy Software Products, tutti i diritti riservati.
+Generale
+Stampante
+Immagini
+HP-GL/2
+Extra
+Documento
+Altro
+Stampa delle pagine:
+Intero Documento
+Stampa intervallo:
+Ordine inverso:
+Formato della pagina:
+ 1-Up
+ 2-Up
+ 4-Up
+Dimensione dell'immagine:
+Usa dimensione originale dell'immagine
+Zoom in percentuale
+Zoom in PPI
+Immagine riflessa:
+Saturazione del colore:
+Tonalità del colore:
+Adatta alla pagina:
+Ombreggiatura:
+Larghezza della penna:
+Correzione gamma:
+Luminosità:
+Aggiungi
+Cancella
+Modifica
+URI della stampante
+Nome della stampante
+Collocazione della stampante
+Informazioni sulla stampante
+Produttore e modello della stampante
+URI del dispositivo
+Preparazione della pagina
+Stampa della pagina
+Inizializzazione della stampante
+Stato della stampante
+Accettazione dei lavori di stampa abilitata
+Accettazione dei lavori di stampa disabilitata
+Richieste di stampa
+Categoria
+Locale
+Remoto
+Fronte-retro
+Spillatura in corso
+Copie veloci
+Copie fascicolate
+Perforazione delle pagine (per fascicolatura)
+Inserimento copertina in corso
+Fascicolatura in corso
+Ordinamento in corso
+Piccolo (fino a 9.5x14")
+Medio (da 9.5x14" a 13x19")
+Grande (13x19" o maggiore)
+Formato personalizzato
+In attesa
+In elaborazione
+Fermo
+Tutto
+Dispari
+Pari
+Più scuro Più chiaro
+Formato del supporto
+Tipo del supporto
+Sorgente del supporto
+Orientamento:
+Verticale
+Orizzontale
+Stato del processo
+Nome del processo
+Nome dell'utente
+Priorità
+Copie
+Dimensioni del file
+In attesa
+Modo stampa
+Risoluzione
+Testo
+Stampa di qualità
+Margini
+Sinistro
+Destro
+Inferiore
+Superiore
+Nome/i file
+Stampa
+Opzioni installate
+Automatico
+400 Il vostro browser ha inviato una richiesta che non può essere eseguita su questo server.
+Questo server non ha potuto verificare la vostra autorizzazione ad accedere alla risorsa.
+L'accesso a questo servizio è a pagamento.
+Non avete il permesso di accedere alla risorsa richiesta su questo server.
+La risorsa richiesta non è disponibile su questo server.
+Il metodo richiesto non è consentito con la risorsa selezionata.
+Una rappresentazione adatta per la risorsa non è disponibile su questo server.
+Non avete il permesso utilizzare questo server come proxy.
+La richiesta ha impiegato troppo tempo per essere completata ed è stata annullata.
+La risorsa richiesta ha più di un valore.
+La risorsa richiesta non è più disponibile e non è stata ancora sostituita.
+Il metodo chiesto richiede un campo "Content-Length" valido.
+I prerequisiti per la richiesta non possono essere soddisfatti.
+La richiesta è troppo grande per essere eseguita da questo server.
+L'URI richiesta è troppo grande per essere eseguita da questo server.
+Il formato della richiesta non è valido su questo server.
+426 È richiesto il passaggio ad una connessione sicura. Se state leggendo questo messaggio nella finestra del vostro browser web vuol dire che non è in grado di supportare il funzionamento con HTTP crittografato.
+500 Il server ha rilevato un errore non recuperabile e non può eseguire la vostra richiesta.
+Il metodo richiesto non è implementato da questo server.
+Il proxy server ha ricevuto una risposta non valida da un server di livello superiore.
+La risorsa richiesta non è attualmente disponibile su questo server.
+Il proxy server ha impiegato troppo tempo per rispondere a questo server.
+Questo server non supporta la versione HTTP richiesta dal vostro browser.
diff --git a/locale/locale.txt b/locale/locale.txt
new file mode 100644
index 000000000..f9abe72d6
--- /dev/null
+++ b/locale/locale.txt
@@ -0,0 +1,32 @@
+This directory contains the message strings used by CUPS for various
+languages. Each subdirectory corresponds to a different locale, and
+the cups_xx and cups_xx_YY files contain the messages for the locales
+named "xx" or "xx_YY".
+
+Each message file starts with a character set identifier, which can be
+one of the following:
+
+ us-ascii
+ iso-8859-1
+ iso-8859-2
+ iso-8859-3
+ iso-8859-4
+ iso-8859-5
+ iso-8859-6
+ iso-8859-7
+ iso-8859-8
+ iso-8859-9
+ utf-8
+
+After that, all non-blank lines are treated as messages, with any
+leading whitespace removed. If a line starts with a number then the
+message index is updated to the number. Otherwise, the next message
+number is used.
+
+The message indices are defined in the include file <cups/language.h>.
+The HTTP status messages use the status codes defined in <cups/http.h>.
+
+If you would like to contribute a new message file for your locale, or
+have corrections to the current ones, please send them to:
+
+ cups-support@cups.org
diff --git a/locale/ru_RU/cups_ru_RU b/locale/ru_RU/cups_ru_RU
new file mode 100644
index 000000000..81e510a6d
--- /dev/null
+++ b/locale/ru_RU/cups_ru_RU
@@ -0,0 +1,134 @@
+windows-1251
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Colour
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Colour Saturation:
+Colour Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Options Installed
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/sv/cups_sv b/locale/sv/cups_sv
new file mode 100644
index 000000000..71c811234
--- /dev/null
+++ b/locale/sv/cups_sv
@@ -0,0 +1,135 @@
+iso-8859-1
+OK
+Avbryt
+Hjälp
+Sluta
+Stäng
+Ja
+Nej
+Till
+Från
+Spara
+Släng
+Default
+Alternativ
+Mera info
+Svart
+Färg
+Cyan
+Magenta
+Gul
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+Generellt
+Skrivare
+Bild
+HP-GL/2
+Extra
+Dokument
+Andra
+Skriv sidorna:
+Hela dokumentet
+Inkl. sidorna:
+Omvänd sidordning:
+Sidformat:
+ 1 sida/sida
+ 2 sidor/sida
+ 4 sidor/sida
+Bildskalning:
+Naturlig bildstorlek
+Procentuell zoom
+PPI-zoom
+Spegelvänd bild:
+Färgmättnad:
+Färgnyans:
+Fit to Page:
+Skuggning:
+Linjebredd:
+Gammakorrektion:
+Ljushet:
+Lägg till
+Ta bort
+Modifiera
+Skrivarens URI
+Skrivarens Namn
+Skrivarens Placering
+Skrivarens Info
+Skrivarens Fabrikat och Modell
+Enhetens URI
+Formaterar sida
+Skriver sida
+Initialiserar Skrivare
+Skrivarens tillstånd
+Accepterar jobb
+Accepterar inte jobb
+Utskriftsjobb
+Klass
+Lokalt
+Fjärr
+Dubbelsidigt
+Häftning
+Snabbkopior
+Hopsorterade kopior
+Hålslagning
+Omslag
+Inbindning
+Sortering
+Små (upp till 9.5x14")
+Medium (9.5x14" till 13x19")
+Stora (13x19" och större)
+Specificerad storlek
+Tomgång
+Arbetar...
+Avbruten
+Alla
+Udda
+Jämna
+Mörkare Ljusare
+Mediastorlek
+Mediatyp
+Mediakälla
+Orientering:
+Stående
+Liggande
+Jobbtillstånd
+Jobbnam
+Användarnamn
+Prioritet
+Kopior
+Filstorlek
+Pågående
+Utskriftsmod
+Upplösning
+Text
+Skönutskrift
+Marginaler
+Vänster
+Höger
+Nertill
+Upptill
+Filnamn
+Print
+Options Installed
+Auto
+400 Din bläddrare skickade en begäran som den här tjänstehanteraren inte förstår.
+Den här tjänstehanteraren kan inte verifiera att du har tillstånd att använda tjänsten.
+Du måste betala för att använda denna tjänst.
+Du har inte tillstånd att använda denna resurs.
+Kan inte hitta den efterfrågade resursen.
+Du tillåts inte använda den efterfrågade metoden med den här resursen.
+An appropriate representation for the resource was not found on this server.
+Du tillåts inte använda den här tjänstehanteraren som en proxy-värd.
+Din förfrågan har tagit för lång tid att hantera och har därför avbrutits.
+Den efterfrågade resursen har mer än ett värde.
+Den efterfrågade resursen är borta och har inte ersatts.
+Den efterfrågade metoden behöver ett giltigt "Content-Length".
+Förvillkoren till förfrågan evaluerades till FALSKT.
+Förfrågan var för stor för att hanteras av denna tjänstehanterare.
+URI i förfrågan var för stor för att hanteras av denna tjänstehanterare.
+Tjänstehanteraren förstod inte formatet på förfrågan.
+426 Det är nödvändigt att byta till en säker förbindelse. Ser du detta meddelande i en nätbläddrare så understödjer den inte byte till krypterad HTTP-förbindelse.
+500 Tjänstehanteraren har upptäckt ett allvarligt fel och kan inte hantera din begäran.
+Den efterfrågade metoden är inte implementerad av denna tjänstehanterare.
+Proxy-servern mottog ett otillåtet svar från en tjänstehanterare.
+Den efterfrågade resursen är inte tillgänglig på denna tjänstehanterare.
+Proxy-servern har inte svarat fort nog till denna tjänstehanterare.
+Denna tjänstehanterare tillhandahåller inte den version av HTTP som din bläddrare kräver.
diff --git a/locale/translate.c b/locale/translate.c
new file mode 100644
index 000000000..e56690be6
--- /dev/null
+++ b/locale/translate.c
@@ -0,0 +1,259 @@
+/*
+ * "$Id$"
+ *
+ * HTTP-based translation program for the Common UNIX Printing System (CUPS).
+ *
+ * This program uses AltaVista's "babelfish" page to translate the POSIX
+ * message file (C/cups_C) to several different languages. The translation
+ * isn't perfect, but it's a good start (better than working from scratch.)
+ *
+ * Copyright 1997-1999 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44145 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <cups/http.h>
+
+
+/*
+ * 'main()' - Main entry.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* HTTP connection */
+ http_status_t status; /* Status of GET command */
+ char line[1024], /* Line from file */
+ *lineptr, /* Pointer into line */
+ buffer[2048], /* Input/output buffer */
+ *bufptr, /* Pointer into buffer */
+ length[16]; /* Content length */
+ int bytes; /* Number of bytes read */
+ FILE *in, /* Input file */
+ *out; /* Output file */
+
+
+ if (argc != 3)
+ {
+ fputs("Usage: translate outfile language\n", stderr);
+ return (1);
+ }
+
+ if ((in = fopen("C/cups_C", "r")) == NULL)
+ {
+ perror("translate: Unable to open input file");
+ return (1);
+ }
+
+ if ((out = fopen(argv[1], "w")) == NULL)
+ {
+ perror("translate: Unable to create output file");
+ fclose(in);
+ return (1);
+ }
+
+ /*
+ * Do character set...
+ */
+
+ fgets(line, sizeof(line), in);
+ fputs("iso-8859-1\n", out); /* Right now that's all that Babelfish does */
+
+ /*
+ * Then strings...
+ */
+
+ while (fgets(line, sizeof(line), in) != NULL)
+ {
+ /*
+ * Strip trailing newline if necessary...
+ */
+
+ lineptr = line + strlen(line) - 1;
+ if (*lineptr == '\n')
+ *lineptr = '\0';
+
+ /*
+ * Skip leading numbers and whitespace...
+ */
+
+ lineptr = line;
+ while (isdigit(*lineptr))
+ putc(*lineptr++, out);
+
+ while (isspace(*lineptr))
+ putc(*lineptr++, out);
+
+ if (*lineptr == '\0')
+ {
+ putc('\n', out);
+ continue;
+ }
+
+ /*
+ * Encode the line into the buffer...
+ */
+
+ sprintf(buffer, "doit=done&lp=en_%s&urltext=[", argv[2]);
+ bufptr = buffer + strlen(buffer);
+
+ while (*lineptr)
+ {
+ if (*lineptr == ' ')
+ *bufptr++ = '+';
+ else if (*lineptr < ' ' || *lineptr == '%')
+ {
+ sprintf(bufptr, "%%%02X", *lineptr & 255);
+ bufptr += 3;
+ }
+ else
+ *bufptr++ = *lineptr;
+
+ lineptr ++;
+ }
+
+ *bufptr++ = '&';
+ *bufptr = '\0';
+
+ sprintf(length, "%d", bufptr - buffer);
+
+ /*
+ * Send the request...
+ */
+
+ if ((http = httpConnect("dns.easysw.com", 80)) == NULL)
+ {
+ perror("translate: Unable to contact proxy server");
+ fclose(in);
+ fclose(out);
+ return (1);
+ }
+
+ lineptr = line;
+ while (isdigit(*lineptr))
+ lineptr ++;
+ while (isspace(*lineptr))
+ lineptr ++;
+
+ printf("%s = ", lineptr);
+ fflush(stdout);
+
+ http->version = HTTP_1_0;
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_CONTENT_TYPE,
+ "application/x-www-form-urlencoded");
+ httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
+ if (httpPost(http, "http://babelfish.altavista.digital.com/cgi-bin/translate?"))
+ httpPost(http, "http://babelfish.altavista.digital.com/cgi-bin/translate?");
+
+ httpWrite(http, buffer, bufptr - buffer);
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_OK)
+ {
+ int sawparen = 0;
+ int skipws = 1;
+ int sawbracket = 0;
+
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ {
+ buffer[bytes] = '\0';
+
+ for (bufptr = buffer; *bufptr; bufptr ++)
+ {
+ if (*bufptr == '>')
+ sawbracket = 0;
+ else if (*bufptr == '<')
+ {
+ sawbracket = 1;
+ if (sawparen)
+ break;
+ }
+ else if (*bufptr == '[' && !sawbracket)
+ sawparen = 1;
+ else if (sawparen)
+ {
+ if (skipws)
+ {
+ if (!isspace(*bufptr))
+ {
+ skipws = 0;
+ *bufptr = toupper(*bufptr);
+ }
+ }
+
+ if (!skipws)
+ {
+ if (*bufptr == '\n')
+ {
+ putc(' ', out);
+ putchar(' ');
+ }
+ else
+ {
+ putc(*bufptr, out);
+ putchar(*bufptr);
+ }
+ }
+ }
+ }
+
+ if (sawparen && sawbracket)
+ break;
+ }
+
+ httpFlush(http);
+ putc('\n', out);
+ putchar('\n');
+ }
+ else
+ {
+ printf("HTTP error %d\n", status);
+
+ fprintf(out, "%s\n", lineptr);
+ httpFlush(http);
+ }
+
+ httpClose(http);
+ }
+
+ fclose(in);
+ fclose(out);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/locale/uk/cups_uk b/locale/uk/cups_uk
new file mode 100644
index 000000000..6fc57559a
--- /dev/null
+++ b/locale/uk/cups_uk
@@ -0,0 +1,134 @@
+koi8-u
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Colour
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Colour Saturation:
+Colour Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Installed Options
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/uk_UA/cups_uk_UA b/locale/uk_UA/cups_uk_UA
new file mode 100644
index 000000000..6548349fe
--- /dev/null
+++ b/locale/uk_UA/cups_uk_UA
@@ -0,0 +1,134 @@
+windows-1251
+OK
+Cancel
+Help
+Quit
+Close
+Yes
+No
+On
+Off
+Save
+Discard
+Default
+Options
+More Info
+Black
+Colour
+Cyan
+Magenta
+Yellow
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+General
+Printer
+Image
+HP-GL/2
+Extra
+Document
+Other
+Print Pages:
+Entire Document
+Page Range:
+Reverse Order:
+Page Format:
+ 1-Up
+ 2-Up
+ 4-Up
+Image Scaling:
+Use Natural Image Size
+Zoom by Percent
+Zoom by PPI
+Mirror Image:
+Colour Saturation:
+Colour Hue:
+Fit to Page:
+Shading:
+Pen Width:
+Gamma Correction:
+Brightness:
+Add
+Delete
+Modify
+Printer URI
+Printer Name
+Printer Location
+Printer Info
+Printer Make and Model
+Device URI
+Formatting Page
+Printing Page
+Initializing Printer
+Printer State
+Accepting Jobs
+Not Accepting Jobs
+Print Jobs
+Class
+Local
+Remote
+Duplexing
+Stapling
+Fast Copies
+Collated Copies
+Hole Punching
+Covering
+Binding
+Sorting
+Small (up to 9.5x14in)
+Medium (9.5x14in to 13x19in)
+Large (13x19in and larger)
+Custom Size
+Idle
+Processing
+Stopped
+All
+Odd
+Even
+Darker Lighter
+Media Size
+Media Type
+Media Source
+Orientation:
+Portrait
+Landscape
+Job State
+Job Name
+User Name
+Priority
+Copies
+File Size
+Pending
+Output Mode
+Resolution
+Text
+Pretty Print
+Margins
+Left
+Right
+Bottom
+Top
+Filename(s)
+Print
+Installed Options
+Auto
+400 Your browser sent a request that this server could not understand.
+This server could not verify that you are authorized to access the resource.
+You must pay to access this server.
+You don't have permission to access the resource on this server.
+The requested resource was not found on this server.
+The requested method is not allowed with the resource.
+An appropriate representation for the resource was not found on this server.
+You don't have permission to use this server as a proxy host.
+The request has taken too long to complete and has been aborted.
+The requested resource has more than one value.
+The requested resource is gone and has not been replaced.
+The requested method requires a valid Content-Length.
+The precondition on the request evaluated to false.
+The request is too large for this server to process.
+The request URI is too large for this server to process.
+The request format is not understood by this server.
+500 The server has detected an unrecoverable error and cannot process your request.
+The requested method is not implemented by this server.
+The proxy server received an invalid response from an upstream server.
+The requested resource is currently unavailable on this server.
+The proxy server has taken too long to respond to this server.
+This server does not support the HTTP version required by your browser.
diff --git a/locale/zh_CN/cups_zh_CN b/locale/zh_CN/cups_zh_CN
new file mode 100644
index 000000000..a00517049
--- /dev/null
+++ b/locale/zh_CN/cups_zh_CN
@@ -0,0 +1,135 @@
+utf-8
+确认
+å–消
+帮助
+退出
+关闭
+是
+ä¸
+打开
+关闭
+ä¿å­˜
+放弃
+默认
+选项
+更多信æ¯
+黑色
+颜色
+é’色
+洋红
+黄色
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+常规
+打å°æœº
+图åƒ
+HP-GL/2
+Extra
+文档
+其它
+打å°é¡µé¢ï¼š
+整个文档
+页é¢èŒƒå›´ï¼š
+åå‘:
+页é¢æ ¼å¼ï¼š
+ 1-Up
+ 2-Up
+ 4-Up
+图åƒç¼©æ”¾ï¼š
+使用图åƒæœ¬èº«çš„大å°
+按百分比缩放
+按 PPI 缩放
+é•œåƒå›¾åƒï¼š
+颜色饱和度:
+色度:
+适åˆé¡µé¢ï¼š
+阴影:
+笔宽:
+Gamma 校正:
+亮度:
+添加
+删除
+修改
+打å°æœº URI
+打å°æœºå称
+打å°æœºä½ç½®
+打å°æœºä¿¡æ¯
+打å°æœºåˆ¶é€ å’Œåž‹å·
+设备 URI
+正在格å¼åŒ–页é¢
+正在打å°é¡µé¢
+正在åˆå§‹åŒ–打å°æœº
+打å°æœºçŠ¶æ€
+正在接å—任务
+没有接å—任务
+打å°ä»»åŠ¡
+类别
+本地
+远程
+åŒå·¥
+正在分类
+快速å¤åˆ¶
+核对å¤åˆ¶
+正在打孔
+正在打å°å°é¢
+正在装订
+正在整ç†
+å°(24.1x35.6厘米)
+中(24.1x35.6厘米至33.0x48.3厘米)
+大(33.0x48.3厘米或更大)
+定制尺寸
+空闲
+正在处ç†
+åœæ­¢
+全部
+奇数页
+å¶æ•°é¡µ
+æ›´æ·± æ›´æµ…
+媒质大å°
+媒质类型
+媒质æ¥æº
+æ–¹å‘:
+纵å‘
+横å‘
+任务状æ€
+任务å
+用户å
+优先级
+å°æ•°
+文件大å°
+等待
+输出模å¼
+分辨率
+文字
+良好质é‡
+è¾¹è·
+å·¦
+å³
+下
+上
+文件å
+打å°
+Options Installed
+Auto
+400 您的æµè§ˆå™¨å‘é€äº†ä¸€ä¸ªæœ¬æœåŠ¡å™¨ä¸ç†è§£çš„请求。
+本æœåŠ¡å™¨æ— æ³•ç¡®è®¤æ‚¨æœ‰æƒè®¿é—®è¯¥èµ„æºã€‚
+您必须付费æ¥è®¿é—®æœ¬æœåŠ¡å™¨ã€‚
+您没有æƒé™è®¿é—®æœ¬æœåŠ¡å™¨ä¸Šçš„该资æºã€‚
+本æœåŠ¡å™¨ä¸Šæ²¡æœ‰è¦æ±‚的资æºã€‚
+请求的方法在该资æºä¸Šä¸å…许。
+本æœåŠ¡å™¨ä¸Šæ²¡æœ‰è¯¥èµ„æºçš„正确表示。
+您没有æƒé™å°†æœ¬æœåŠ¡å™¨ä½œä¸ºä»£ç†æœåŠ¡å™¨ã€‚
+请求过长时间没有完æˆï¼Œå·²ç»è¢«ä¸­æ­¢ã€‚
+请求的资æºæœ‰å¤šäºŽä¸€ä¸ªå€¼ã€‚
+请求的资æºå·²ç»ç”¨å®Œï¼Œä¸”没有被更æ¢ã€‚
+请求的方法需è¦æœ‰æ•ˆçš„ Content-Length 标识。
+请求的å‰æ为å‡ã€‚
+请求过长,本æœåŠ¡å™¨æ— æ³•å¤„ç†ã€‚
+请求的 URI 过长,本æœåŠ¡å™¨æ— æ³•å¤„ç†ã€‚
+本æœåŠ¡å™¨æ— æ³•è¯†åˆ«è¯¥è¯·æ±‚çš„æ ¼å¼ã€‚
+426 需è¦å®‰å…¨çš„连接。如果您在æµè§ˆå™¨ä¸­çœ‹åˆ°æœ¬ä¿¡æ¯ï¼Œæ‚¨çš„æµè§ˆå™¨ä¸æ”¯æŒ HTTP 加密。
+500 æœåŠ¡å™¨æ£€æµ‹åˆ°ä¸€ä¸ªæ— æ³•æ¢å¤çš„错误,无法处ç†æ‚¨çš„请求。
+本æœåŠ¡å™¨æ²¡æœ‰å®žçŽ°æ‰€è¯·æ±‚的方法。
+代ç†æœåŠ¡å™¨æ”¶åˆ°æ¥è‡ªä¸Šæ¸¸æœåŠ¡å™¨çš„无效应答。
+请求的资æºåœ¨æœ¬æœåŠ¡å™¨ä¸Šä¸å¯ç”¨ã€‚
+代ç†æœåŠ¡å™¨é•¿æ—¶é—´æ²¡æœ‰åº”答本æœåŠ¡å™¨ã€‚
+本æœåŠ¡å™¨ä¸æ”¯æŒæ‚¨çš„æµè§ˆå™¨æ‰€éœ€è¦çš„ HTTP 版本。
diff --git a/man/.cvsignore b/man/.cvsignore
new file mode 100644
index 000000000..5b12a6fc7
--- /dev/null
+++ b/man/.cvsignore
@@ -0,0 +1,7 @@
+*.0
+*.1
+*.1m
+*.3
+*.5
+*.8
+*.z
diff --git a/man/Makefile b/man/Makefile
new file mode 100644
index 000000000..32bef85d5
--- /dev/null
+++ b/man/Makefile
@@ -0,0 +1,121 @@
+#
+# "$Id$"
+#
+# Man page makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+include Makefile.common
+
+
+#
+# Other languages...
+#
+
+LANGDIRS = es fr
+
+
+#
+# Make everything...
+#
+
+all: $(CAT1) $(CAT5) $(CAT8)
+ for dir in $(LANGDIRS); do \
+ echo "Making all in man/$$dir..."; \
+ (cd $$dir; $(MAKE) $(MFLAGS) all); \
+ done
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+ $(RM) $(CAT1) $(CAT5) $(CAT8)
+ for dir in $(LANGDIRS); do \
+ echo "Cleaning all in man/$$dir..."; \
+ (cd $$dir; $(MAKE) $(MFLAGS) clean); \
+ done
+
+
+#
+# Dummy depend target...
+#
+
+depend:
+
+
+#
+# Install files...
+#
+
+install: all
+ $(INSTALL_DIR) $(MANDIR)/man1
+ for file in $(MAN1); do \
+ echo Installing $$file in $(MANDIR)/man1...; \
+ $(INSTALL_MAN) $$file $(MANDIR)/man1/`basename $$file man`1; \
+ done
+ $(RM) $(MANDIR)/man1/cancel.1
+ $(LN) lp.1 $(MANDIR)/man1/cancel.1
+ $(INSTALL_DIR) $(MANDIR)/man5
+ for file in $(MAN5); do \
+ echo Installing $$file in $(MANDIR)/man5...; \
+ $(INSTALL_MAN) $$file $(MANDIR)/man5/`basename $$file man`5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/man$(MAN8EXT)
+ for file in $(MAN8); do \
+ echo Installing $$file in $(AMANDIR)/man$(MAN8EXT)...; \
+ $(INSTALL_MAN) $$file $(AMANDIR)/man$(MAN8EXT)/`basename $$file man`$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(LN) accept.$(MAN8EXT) $(AMANDIR)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(RM) $(AMANDIR)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(LN) enable.$(MAN8EXT) $(AMANDIR)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(INSTALL_DIR) $(MANDIR)/cat1
+ for file in $(CAT1); do \
+ echo Installing $$file in $(MANDIR)/cat1...; \
+ $(INSTALL_MAN) $$file $(MANDIR)/cat1; \
+ done
+ $(RM) $(MANDIR)/cat1/cancel.$(CAT1EXT)
+ $(LN) lp.$(CAT1EXT) $(MANDIR)/cat1/cancel.$(CAT1EXT)
+ $(INSTALL_DIR) $(MANDIR)/cat5
+ for file in $(CAT5); do \
+ echo Installing $$file in $(MANDIR)/cat5...; \
+ $(INSTALL_MAN) $$file $(MANDIR)/cat5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/cat$(MAN8EXT)
+ for file in $(CAT8); do \
+ echo Installing $$file in $(AMANDIR)/cat$(MAN8EXT)...; \
+ $(INSTALL_MAN) $$file $(AMANDIR)/cat$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(LN) accept.$(CAT8EXT) $(AMANDIR)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(RM) $(AMANDIR)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+ $(LN) enable.$(CAT8EXT) $(AMANDIR)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+ for dir in $(LANGDIRS); do \
+ echo "Installing all in man/$$dir..."; \
+ (cd $$dir; $(MAKE) $(MFLAGS) install); \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/man/Makefile.common b/man/Makefile.common
new file mode 100644
index 000000000..b5b92bf05
--- /dev/null
+++ b/man/Makefile.common
@@ -0,0 +1,86 @@
+#
+# "$Id: Makefile.common 4191 2004-05-27 18:51:30Z mike $"
+#
+# Man pages definitions for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2003 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+#
+# Man pages...
+#
+
+MAN1 = backend.man \
+ cups-config.man \
+ cupstestppd.man \
+ filter.man \
+ lp.man \
+ lpoptions.man \
+ lppasswd.man \
+ lpq.man \
+ lprm.man \
+ lpr.man \
+ lpstat.man
+MAN5 = classes.conf.man \
+ cupsd.conf.man \
+ mime.convs.man \
+ mime.types.man \
+ printers.conf.man
+MAN8 = accept.man \
+ cupsaddsmb.man \
+ cups-lpd.man \
+ cups-polld.man \
+ cupsd.man \
+ enable.man \
+ lpadmin.man \
+ lpinfo.man \
+ lpmove.man \
+ lpc.man
+
+CAT1 = backend.$(CAT1EXT) \
+ cups-config.$(CAT1EXT) \
+ cupstestppd.$(CAT1EXT) \
+ filter.$(CAT1EXT) \
+ lp.$(CAT1EXT) \
+ lpoptions.$(CAT1EXT) \
+ lppasswd.$(CAT1EXT) \
+ lpq.$(CAT1EXT) \
+ lprm.$(CAT1EXT) \
+ lpr.$(CAT1EXT) \
+ lpstat.$(CAT1EXT)
+CAT5 = classes.conf.$(CAT5EXT) \
+ cupsd.conf.$(CAT5EXT) \
+ mime.convs.$(CAT5EXT) \
+ mime.types.$(CAT5EXT) \
+ printers.conf.$(CAT5EXT)
+CAT8 = accept.$(CAT8EXT) \
+ cupsaddsmb.$(CAT8EXT) \
+ cups-lpd.$(CAT8EXT) \
+ cups-polld.$(CAT8EXT) \
+ cupsd.$(CAT8EXT) \
+ enable.$(CAT8EXT) \
+ lpadmin.$(CAT8EXT) \
+ lpinfo.$(CAT8EXT) \
+ lpmove.$(CAT8EXT) \
+ lpc.$(CAT8EXT)
+
+
+#
+# End of "$Id: Makefile.common 4191 2004-05-27 18:51:30Z mike $".
+#
diff --git a/man/accept.man b/man/accept.man
new file mode 100644
index 000000000..d307ef563
--- /dev/null
+++ b/man/accept.man
@@ -0,0 +1,60 @@
+.\"
+.\" "$Id: accept.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" accept/reject man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH accept 8 "Common UNIX Printing System" "23 January 2001" "Easy Software Products"
+.SH NAME
+accept/reject \- accept/reject jobs sent to a destination
+.SH SYNOPSIS
+.B accept
+destination(s)
+.br
+.B reject
+[ -E ] [ -h
+.I server
+] [ -r
+.I reason
+]
+destination(s)
+.SH DESCRIPTION
+\fIaccept\fR instructs the printing system to accept print jobs to the
+specified destinations.
+.LP
+\fIreject\fR instructs the printing system to reject print jobs to the
+specified destinations. The \fI-r\fR option sets the reason for rejecting
+print jobs. If not specified the reason defaults to "Reason Unknown".
+.LP
+The \fI-E\fR option forces encryption when connecting to the server.
+.SH COMPATIBILITY
+The CUPS versions of \fIaccept\fR and \fIreject\fR may ask the user for an
+access password depending on the printing system configuration. This differs
+from the System V versions which require the root user to execute these
+commands.
+.SH SEE ALSO
+cancel(1), disable(8), enable(8), lp(1), lpadmin(8), lpstat(1),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: accept.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/backend.man b/man/backend.man
new file mode 100644
index 000000000..66d1775c4
--- /dev/null
+++ b/man/backend.man
@@ -0,0 +1,122 @@
+.\"
+.\" "$Id: backend.man 4432 2004-10-08 20:29:58Z mike $"
+.\"
+.\" backend man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH backend 1 "Common UNIX Printing System" "8 October 2004" "Easy Software Products"
+.SH NAME
+backend \- cups backend transmission interfaces
+.SH SYNOPSIS
+.B backend
+job user title num-copies options [
+.I filename
+]
+.SH DESCRIPTION
+The CUPS backend interface provides a standard method for sending document
+files to different physical interfaces.
+.LP
+Backends must be capable of reading from a filename on the command-line
+or from the standard input, copying the standard input to a temporary file
+if required by the physical interface.
+.LP
+The command name (argv[0]) is set to the device URI of the
+destination printer. Starting with CUPS 1.1.22, any
+authentication information in argv[0] will be removed, so
+backend developers are urged to use the DEVICE_URI environment
+variable whenever authentication information is required.
+.SH ENVIRONMENT VARIABLES
+The following environment variables are defined by the CUPS server when
+executing the backend:
+.TP 5
+CHARSET
+.br
+The default text character set (typically us-ascii or iso-8859-1).
+.TP 5
+CLASS
+.br
+When a job is submitted to a printer class, contains the name of
+the destination printer class. Otherwise this environment
+variable will not be set.
+.TP 5
+CONTENT_TYPE
+.br
+The MIME type associated with the file (e.g. application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+The directory where data files can be found.
+.TP 5
+CUPS_SERVERROOT
+.br
+The root directory of the server.
+.TP 5
+DEVICE_URI
+.br
+The device-uri associated with the printer; this is provided for
+shell scripts which may not be able to get the passed argv[0]
+string and for backends that require any authentication
+information which is not included in argv[0].
+.TP 5
+LANG
+.br
+The default language locale (typically C or en).
+.TP 5
+PATH
+.br
+The standard execution path for external programs that may be run by
+the backend.
+.TP 5
+PPD
+.br
+The full pathname of the PostScript Printer Description (PPD) file for
+this printer.
+.TP 5
+PRINTER
+.br
+The name of the printer.
+.TP 5
+RIP_CACHE
+.br
+The recommended amount of memory to use for Raster Image Processors (RIPs).
+.TP 5
+SOFTWARE
+.br
+The name and version number of the server (typically CUPS/1.1).
+.TP 5
+TZ
+.br
+The timezone of the server.
+.TP 5
+USER
+.br
+The user executing the backend, typically root; consult the cupsd.conf file for
+the current setting.
+.SH SEE ALSO
+cupsd(8), filter(1)
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: backend.man 4432 2004-10-08 20:29:58Z mike $".
+.\"
diff --git a/man/classes.conf.man b/man/classes.conf.man
new file mode 100644
index 000000000..df950fa53
--- /dev/null
+++ b/man/classes.conf.man
@@ -0,0 +1,72 @@
+.\"
+.\" "$Id: classes.conf.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" classes.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH classes.conf 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NAME
+classes.conf \- class configuration file for cups
+.SH DESCRIPTION
+The \fIclasses.conf\fR file defines the local printer classes that are
+available. It is normally located in the \fI/etc/cups\fR directory and
+is generated automatically by the \fIcupsd(8)\fR program when printer
+classes are added or deleted.
+.LP
+Each line in the file can be a configuration directive, a blank line,
+or a comment. Comment lines start with the # character.
+.SH DIRECTIVES
+.TP 5
+<Class name> ... </Class>
+.br
+Defines a specific printer class.
+.TP 5
+Accepting
+.br
+Specifies whether or not the printer class is accepting new jobs.
+.TP 5
+Info
+.br
+Specifies human-readable text describing the printer class.
+.TP 5
+Location
+.br
+Specifies human-readable text describing the location of the printer class.
+.TP 5
+Printer
+.br
+Specifies a printer that is a member of the printer class.
+.TP 5
+State
+.br
+Specifies the initial state of the printer class (Idle or Stopped)
+.TP 5
+StateMessage
+.br
+Specifies the message associated with the state.
+.SH SEE ALSO
+cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: classes.conf.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/cups-config.man b/man/cups-config.man
new file mode 100644
index 000000000..7cc5b5d89
--- /dev/null
+++ b/man/cups-config.man
@@ -0,0 +1,95 @@
+.\"
+.\" "$Id: cups-config.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" cups-config man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-config 1 "Common UNIX Printing System" "27 May 2004" "Easy Software Products"
+.SH NAME
+cups-config \- get cups api, compiler, directory, and link information.
+.SH SYNOPSIS
+.B cups-config
+--api-version
+.br
+.B cups-config
+--cflags
+.br
+.B cups-config
+--datadir
+.br
+.B cups-config
+--help
+.br
+.B cups-config
+--ldflags
+.br
+.B cups-config
+[
+.I --image
+] [
+.I --static
+] --libs
+.br
+.B cups-config
+--serverbin
+.br
+.B cups-config
+--serverroot
+.br
+.B cups-config
+--version
+.br
+.SH DESCRIPTION
+\fBcups-config\fR is the CUPS program configuration utility. It should be
+used by application developers to determine the necessary command-line
+options for the compiler and linker, as well as determining installation
+directories for filters, configuration files, and drivers.
+.LP
+The \fI--api-version\fR command displays the current API version (major.minor).
+.LP
+The \fI--cflags\fR command displays the necessary compiler options.
+.LP
+The \fI--datadir\fR command displays the default CUPS data directory.
+.LP
+The \fI--help\fR command displays the program usage message.
+.LP
+The \fI--ldflags\fR command displays the necessary linker options.
+.LP
+The \fI--libs\fR command displays the necessary librarys to link to.
+The \fI--image\fR option adds the CUPS imaging library to the list.
+The \fI--static\fR option shows the static libraries instead of the
+default (shared) libraries.
+.LP
+The \fI--serverbin\fR command displays the default CUPS binary directory,
+where filters and backends are stored.
+.LP
+The \fI--serverroot\fR command displays the default CUPS configuration
+file directory.
+.LP
+The \fI--version\fR command displays the full version number of the
+CUPS installation (major.minor.patch).
+.SH SEE ALSO
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cups-config.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/cups-lpd.man b/man/cups-lpd.man
new file mode 100644
index 000000000..8300f2ea3
--- /dev/null
+++ b/man/cups-lpd.man
@@ -0,0 +1,125 @@
+.\"
+.\" "$Id: cups-lpd.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" cups-lpd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-lpd 8 "Common UNIX Printing System" "11 August 2004" "Easy Software Products"
+.SH NAME
+cups-lpd \- receive print jobs and report printer status to lpd clients
+.SH SYNOPSIS
+.B cups-lpd
+[ -o
+.I option=value
+]
+.SH DESCRIPTION
+\fBcups-lpd\fR is the CUPS Line Printer Daemon ("LPD") mini-server that
+supports legacy client systems that use the LPD protocol.
+\fBcups-lpd\fR does not act as a standalone network daemon but instead
+operates using the Internet "super-server" \fBinetd(8)\fR. Add the
+following line to the \fBinetd.conf\fR file to enable the
+\fBcups-lpd\fR daemon:
+.br
+.nf
+
+ printer stream tcp nowait lp /path/to/cups/daemon/cups-lpd cups-lpd -o document-format=application/octet-stream
+.fi
+.LP
+If you are using the newer \fIxinetd(8)\fR daemon, add the following
+lines to the \fBxinetd.conf\fR file:
+.br
+.nf
+
+ service printer
+ {
+ socket_type = stream
+ protocol = tcp
+ wait = no
+ user = lp
+ group = sys
+ passenv =
+ server = /path/to/cups/daemon/cups-lpd
+ server_args = -o document-format=application/octet-stream
+ }
+.fi
+.LP
+The /path/to/cups/daemon is usually /usr/lib/cups/daemon or
+/usr/libexec/cups/daemon, depending on the operating system.
+Consult the cupsd.conf file for the local setting.
+.SH OPTIONS
+The \fI-o\fR option to \fBcups-lpd\fR inserts options for all print queues.
+Most often this is used to disable the "l" filter so that remote print jobs
+are filtered as needed for printing:
+.br
+.nf
+
+ printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd \
+ -o document-format=application/octet-stream
+
+ server = /usr/lib/cups/daemon/cups-lpd
+ server_args = -o document-format=application/octet-stream
+.fi
+.LP
+The example shown resets the document format to be
+\fIapplication/octet-stream\fR, which forces auto-detection of the print
+file type.
+.SH PERFORMANCE
+\fBcups-lpd\fR performs well with small numbers of clients and
+printers. However, since a new process is created for each
+connection and since each process must query the printing system
+before each job submission, it does not scale to larger
+configurations. We highly recommend that large configurations
+use the native IPP support provided by CUPS instead.
+.SH SECURITY
+\fBcups-lpd\fR currently does not perform any access control
+based on the settings in \fIcupsd.conf(5)\fR or in the
+\fIhosts.allow(5)\fR or \fIhosts.deny\fR files used by TCP
+wrappers. Therefore, running \fBcups-lpd\fR on your server will
+allow any computer on your network (and perhaps the entire
+Internet) to print to your server.
+.LP
+While \fIxinetd\fR has built-in access control support, you
+should use the TCP wrappers package with \fIinetd\fR to limit
+access to only those computers that should be able to print
+through your server.
+.LP
+\fBcups-lpd\fR is not enabled by the standard CUPS distribution.
+Please consult with your operating system vendor to determine
+whether it is enabled in their distributions.
+.SH COMPATIBILITY
+\fBcups-lpd\fR does not enforce the restricted source port
+number specified in RFC 1179, as using restricted ports does not
+prevent users from submitting print jobs. While this behavior is
+different than standard Berkeley LPD implementations, it should
+not affect normal client operations.
+.LP
+The output of the status requests follows RFC 2569, Mapping
+between LPD and IPP Protocols. Since many LPD implementations
+stray from this definition, remote status reporting to LPD
+clients may be unreliable.
+.SH SEE ALSO
+cupsd(8), inetd(8), xinetd(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cups-lpd.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/cups-polld.man b/man/cups-polld.man
new file mode 100644
index 000000000..9b6b8450e
--- /dev/null
+++ b/man/cups-polld.man
@@ -0,0 +1,46 @@
+.\"
+.\" "$Id: cups-polld.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" cups-polld man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-polld 8 "Common UNIX Printing System" "10 May 2000" "Easy Software Products"
+.SH NAME
+cups-polld \- cups printer polling daemon
+.SH SYNOPSIS
+.B cups-polld
+.I address ipp-port interval browse-port
+.SH DESCRIPTION
+\fBcups-polld\fR polls remote servers for a list of available printers
+and printer classes every \fIinterval\fR seconds. Printer and class
+information is then broadcast to the localhost interface (127.0.0.1)
+for reception by \fBcupsd(8)\fR.
+.PP
+This program is started automatically by \fBcupsd\fR for each
+BrowsePoll directive found in the \fBcupsd.conf\fR file.
+.SH SEE ALSO
+cupsd.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cups-polld.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/cupsaddsmb.man b/man/cupsaddsmb.man
new file mode 100644
index 000000000..76202cfef
--- /dev/null
+++ b/man/cupsaddsmb.man
@@ -0,0 +1,185 @@
+.\"
+.\" "$Id: cupsaddsmb.man 4380 2004-08-19 21:02:47Z mike $"
+.\"
+.\" cupsaddsmb man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsaddsmb 8 "Common UNIX Printing System" "19 August 2004" "Easy Software Products"
+.SH NAME
+cupsaddsmb \- export printers to samba for windows clients
+.SH SYNOPSIS
+.B cupsaddsmb
+[ -H
+.I samba-server
+] [ -U
+.I samba-user
+] [ -h
+.I cups-server
+] [ -v ] -a
+.br
+.B cupsaddsmb
+[ -H
+.I samba-server
+] [ -U
+.I samba-user
+] [ -h
+.I cups-server
+] [ -v ] printer [ ... printer ]
+.SH DESCRIPTION
+\fIcupsaddsmb\fR exports printers to the SAMBA software (version
+2.2.0 or higher) for use with Windows clients. Depending on the
+SAMBA configuration, you may need to provide a password to
+export the printers. This program requires the Windows printer
+driver files described below.
+.LP
+The \fI-H\fR option specifies the SAMBA server which defaults
+to the CUPS server.
+.LP
+The \fI-U\fR option specifies the SAMBA print admin username which defaults
+to your current username.
+.LP
+The \fI-a\fR option exports all known printers. Otherwise only
+the named printers are exported.
+.LP
+The \fI-h\fR option specifies a different CUPS server to use.
+.LP
+The \fI-v\fR option specifies that verbose information should be
+shown and is useful for debugging SAMBA configuration problems.
+.SH SAMBA CONFIGURATION
+\fIcupsaddsmb\fR uses the new RPC-based printing support in
+SAMBA 2.2.x to provide printer drivers and PPD files to Windows
+client machines. In order to use this functionality, you must
+first configure SAMBA (via the smb.conf file) to support
+printing through CUPS and provide a printer driver download
+share, as follows:
+.nf
+
+ [global]
+ load printers = yes
+ printing = cups
+ printcap name = cups
+
+ [printers]
+ comment = All Printers
+ path = /var/spool/samba
+ browseable = no
+ public = yes
+ guest ok = yes
+ writable = no
+ printable = yes
+ printer admin = root
+
+ [print$]
+ comment = Printer Drivers
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = root
+.fi
+.LP
+This configuration assumes a FHS-compliant installation of
+SAMBA; adjust the [printers] and [print$] share paths
+accordingly on your system as needed.
+
+.SH MICROSOFT POSTSCRIPT DRIVERS FOR WINDOWS
+The base driver for Windows 2000 and higher is the Microsoft
+PostScript driver, which is available on any system running
+Windows 2000 or higher in the
+%WINDOWS%\\SYSTEM32\\SPOOL\\DRIVERS\\W32X86\\3 folder.
+.LP
+The CUPS printer driver is preferred over the Microsoft driver
+since it supports the page-label, job-billing, and
+job-hold-until options fully on all printers. However, currently
+only Windows 2000 and higher is supported by the Microsoft
+driver, so you will also need to get the Adobe driver to support
+Windows 95, 98, and Me clients. The Adobe and Microsoft drivers
+for Windows 2000 are identical.
+.LP
+Once you have extracted the driver files, create a "drivers"
+directory in the CUPS data directory (usually /usr/share/cups)
+and copy the files exactly as named below:
+.nf
+
+ [Windows 2000 and higher]
+ ps5ui.dll
+ pscript.hlp
+ pscript.ntf
+ pscript5.dll
+.fi
+
+.SH CUPS POSTSCRIPT DRIVERS FOR WINDOWS
+\fIcupsaddsmb\fR can use the CUPS v6 PostScript printer driver
+for Windows, which is available for download from the CUPS web
+site.
+.LP
+The CUPS printer driver is preferred over the Adobe and
+Microsoft drivers since it supports the page-label, job-billing,
+and job-hold-until options fully on all printers. However,
+currently only Windows 2000 and higher is supported by the CUPS
+driver, so you will also need to get the Adobe driver to support
+Windows 95, 98, and Me clients.
+.LP
+Once you have extracted the driver files, create a "drivers"
+directory in the CUPS data directory (usually /usr/share/cups)
+and copy the files exactly as named below:
+.nf
+
+ [Windows 2000 and higher]
+ cupsui6.dll
+ cupsdrv6.dll
+ ps5ui.dll
+ pscript.hlp
+ pscript.ntf
+ pscript5.dll
+.fi
+
+.SH ADOBE POSTSCRIPT DRIVERS FOR WINDOWS
+\fIcupsaddsmb\fR can use the Adobe PostScript printer driver for
+Windows, which are available for download from the Adobe web
+site (http://www.adobe.com).
+.LP
+The CUPS printer driver is preferred over the Adobe drivers
+since they support the page-label, job-billing, and
+job-hold-until options fully on all printers. You can use the
+Adobe drivers for Windows 9x and the CUPS drivers for Windows
+2000 and higher. The Adobe and Microsoft drivers for Windows 2000
+are identical.
+.LP
+Once you have extracted the driver files, create a "drivers"
+directory in the CUPS data directory (usually /usr/share/cups)
+and copy the files exactly as named below:
+.nf
+
+ [Windows 95, 98, and Me]
+ ADFONTS.MFM
+ ADOBEPS4.DRV
+ ADOBEPS4.HLP
+ ICONLIB.DLL
+ PSMON.DLL
+.fi
+.SH SEE ALSO
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cupsaddsmb.man 4380 2004-08-19 21:02:47Z mike $".
+.\"
diff --git a/man/cupsd.conf.man b/man/cupsd.conf.man
new file mode 100644
index 000000000..3fb77c19f
--- /dev/null
+++ b/man/cupsd.conf.man
@@ -0,0 +1,411 @@
+.\"
+.\" "$Id: cupsd.conf.man 4370 2004-08-18 17:57:53Z mike $"
+.\"
+.\" cupsd.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsd.conf 5 "Common UNIX Printing System" "18 August 2004" "Easy Software Products"
+.SH NAME
+cupsd.conf \- server configuration file for cups
+.SH DESCRIPTION
+The \fIcupsd.conf\fR file configures the CUPS scheduler, \fIcupsd(8)\fR. It
+is normally located in the \fI/etc/cups\fR directory.
+.LP
+Each line in the file can be a configuration directive, a blank line,
+or a comment. Comment lines start with the # character. The
+configuration directives are intentionally similar to those used by the
+popular Apache web server software and are described below.
+.SH DIRECTIVES
+The following directives are understood by \fIcupsd\fR. Consult the CUPS
+Software Administrators Manual for a detailed description:
+.TP 5
+AccessLog
+.br
+Defines the access log filename.
+.TP 5
+Allow
+.br
+Allows access from the named hosts or addresses.
+.TP 5
+AuthClass
+.br
+Specifies the authentication class (User, Group, System)
+.TP 5
+AuthGroupName
+.br
+Specifies the authentication group.
+.TP 5
+AuthType
+.br
+Specifies the authentication type (None, Basic, Digest)
+.TP 5
+AutoPurgeJobs
+.br
+Specifies whether to purge job history data automatically when
+it is no longer required for quotas.
+.TP 5
+BrowseAddress
+.br
+Specifies a broadcast address for outgoing printer information packets.
+.TP 5
+BrowseAllow
+.br
+Allows incoming printer information packets from the named host or address.
+.TP 5
+BrowseDeny
+.br
+Denies incoming printer information packets from the named host or address.
+.TP 5
+BrowseInterval
+.br
+Specifies the maximum interval between printer information broadcasts.
+.TP 5
+BrowseOrder
+.br
+Specifies the order of printer information access control (allow,deny or deny,allow)
+.TP 5
+BrowsePoll
+.br
+Specifies a server to poll for printer information.
+.TP 5
+BrowsePort
+.br
+Specifies the port to listen to for printer information packets.
+.TP 5
+BrowseProtocols
+.br
+Specifies the protocols to use for printer browsing.
+.TP 5
+BrowseRelay
+.br
+Specifies that printer information packets should be relayed from one host or
+network to another.
+.TP 5
+BrowseShortNames
+.br
+Specifies whether remote printers will use short names ("printer") or not
+("printer@server"). This option is ignored if more than one remote printer
+exists with the same name.
+.TP 5
+BrowseTimeout
+.br
+Specifies the maximum interval between printer information updates before
+remote printers will be removed from the list of available printers.
+.TP 5
+Browsing
+.br
+Specifies whether or not remote printer browsing should be enabled.
+.TP 5
+Classification
+.br
+Specifies the security classification of the server.
+.TP 5
+ClassifyOverride
+.br
+Specifies whether to allow users to override the classification
+of individual print jobs.
+.TP 5
+ConfigFilePerm
+.br
+Specifies the permissions for all configuration files that the scheduler
+writes.
+.TP 5
+DataDir
+.br
+Specified the directory where data files can be found.
+.TP 5
+DefaultCharset
+.br
+Specifies the default character set to use for text.
+.TP 5
+DefaultLanguage
+.br
+Specifies the default language to use for text and web content.
+.TP 5
+Deny
+.br
+Denies access to the named host or address.
+.TP 5
+DocumentRoot
+.br
+Specifies the root directory for the internal web server documents.
+.TP 5
+Encryption
+.br
+Specifies the level of encryption that is required for a particular
+location.
+.TP 5
+ErrorLog
+.br
+Specifies the error log filename.
+.TP 5
+FaxRetryInterval
+.br
+Specifies the interval between retries of fax jobs in seconds.
+.TP 5
+FaxRetryLimit
+.br
+Specifies the number of retries that are done for fax jobs.
+.TP 5
+FileDevice
+.br
+Specifies whether the file pseudo-device can be used for new
+printer queues.
+.TP 5
+FilterLimit
+.br
+Specifies the maximum cost of filters that are run concurrently.
+.TP 5
+FilterNice
+.br
+Specifies the scheduling priority ("nice" value) of filters that
+are run to print a job.
+.TP 5
+FontPath
+.br
+Specifies the search path for fonts.
+.TP 5
+Group
+.br
+Specifies the group name or ID that will be used when executing
+external programs.
+.TP 5
+HideImplicitMembers
+.br
+Specifies whether to hide members of implicit classes.
+.TP 5
+HostNameLookups
+.br
+Specifies whether or not to do reverse lookups on client addresses.
+.TP 5
+ImplicitAnyClasses
+.br
+Specifies whether or not to create implicit classes for local and
+remote printers, e.g. "AnyPrinter" from "Printer", "Printer@server1",
+and "Printer@server2".
+.TP 5
+ImplicitClasses
+.br
+Specifies whether or not to create implicit classes from identical
+remote printers.
+.TP 5
+Include
+.br
+Includes the named file.
+.TP 5
+KeepAlive
+.br
+Specifies whether or not to support HTTP Keep-Alive.
+.TP 5
+KeepAliveTimeout
+.br
+Specifies the connection timeout for HTTP Keep-Alive.
+.TP 5
+<Limit methods> ... </Limit>
+.TP 5
+<LimitExcept methods> ... </LimitExcept>
+.br
+Specifies the HTTP methods that are being limited inside a location.
+.TP 5
+LimitRequestBody
+.br
+Specifies the maximum size of any print job request.
+.TP 5
+Listen
+.br
+Listens to the specified address and port.
+.TP 5
+<Location /path> ... </Location>
+.br
+Specifies access control for the named location.
+.TP 5
+LogFilePerm
+.br
+Specifies the permissions for all log files that the scheduler writes.
+.TP 5
+LogLevel
+.br
+Specifies the logging level (none, warn, error, info, debug, or debug2)
+.TP 5
+MaxClients
+.br
+Specifies the maximum number of simultaneous clients to support.
+.TP 5
+MaxClientsPerHost
+.br
+Specifies the maximum number of simultaneous clients to support from a
+single address.
+.TP 5
+MaxCopies
+.br
+Specifies the maximum number of copies that a user can print of each job.
+.TP 5
+MaxJobs
+.br
+Specifies the maximum number of simultaneous jobs to support.
+.TP 5
+MaxJobsPerPrinter
+.br
+Specifies the maximum number of simultaneous jobs per printer to support.
+.TP 5
+MaxJobsPerUser
+.br
+Specifies the maximum number of simultaneous jobs per user to support.
+.TP 5
+MaxLogSize
+.br
+Specifies the maximum size of the log files before they are
+rotated (0 to disable rotation)
+.TP 5
+MaxRequestSize
+.br
+Specifies the maximum request/file size in bytes (0 for no limit)
+.TP 5
+Order
+.br
+Specifies the order of HTTP access control (allow,deny or deny,allow)
+.TP 5
+PageLog
+.br
+Specifies the page log filename.
+.TP 5
+Port
+.br
+Specifies a port number to listen to for HTTP requests.
+.TP 5
+PreserveJobFiles
+.br
+Specifies whether or not to preserve job files after they are printed.
+.TP 5
+PreserveJobHistory
+.br
+Specifies whether or not to preserve the job history after they are
+printed.
+.TP 5
+Printcap
+.br
+Specifies the filename for a printcap file that is updated automatically
+with a list of available printers (needed for legacy applications)
+.TP 5
+PrintcapFormat
+.br
+Specifies the format of the printcap file.
+.TP 5
+PrintcapGUI
+.br
+Specifies whether to generate option panel definition files on some
+operating systems.
+.TP 5
+ReloadTimeout
+.br
+Specifies the amount of time to wait for job completion before
+restarting the scheduler.
+.TP 5
+RemoteRoot
+.br
+Specifies the username that is associated with unauthenticated root
+accesses.
+.TP 5
+RequestRoot
+.br
+Specifies the directory to store print jobs and other HTTP request
+data.
+.TP 5
+Require
+.br
+Specifies that user or group authentication is required.
+.TP 5
+RIPCache
+.br
+Specifies the maximum amount of memory to use when converting images
+and PostScript files to bitmaps for a printer.
+.TP 5
+RunAsUser
+.br
+Specifies that the scheduler should run as the unpriviledged user
+set with the User directive.
+.TP 5
+Satisfy
+.br
+Specifies whether all or any limits set for a Location must be
+satisfied to allow access.
+.TP 5
+ServerAdmin
+.br
+Specifies the email address of the server administrator.
+.TP 5
+ServerBin
+.br
+Specifies the directory where backends, CGIs, daemons, and filters may
+be found.
+.TP 5
+ServerCertificate
+.br
+Specifies the encryption certificate to use.
+.TP 5
+ServerKey
+.br
+Specifies the encryption key to use.
+.TP 5
+ServerName
+.br
+Specifies the fully-qualified hostname of the server.
+.TP 5
+ServerRoot
+.br
+Specifies the directory where the server configuration files can be found.
+.TP 5
+ServerTokens
+.br
+Specifies what information is included in the Server header of HTTP
+responses.
+.TP 5
+SSLListen
+.br
+Listens on the specified address and port for encrypted connections.
+.TP 5
+SSLPort
+.br
+Listens on the specified port for encrypted connections.
+.TP 5
+SystemGroup
+.br
+Specifies the group to use for System class authentication.
+.TP 5
+TempDir
+.br
+Specifies the directory where temporary files are stored.
+.TP 5
+Timeout
+.br
+Specifies the HTTP request timeout in seconds.
+.TP 5
+User
+.br
+Specifies the user name or ID that is used when running external programs.
+.SH SEE ALSO
+classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cupsd.conf.man 4370 2004-08-18 17:57:53Z mike $".
+.\"
diff --git a/man/cupsd.man b/man/cupsd.man
new file mode 100644
index 000000000..5fd6dca9e
--- /dev/null
+++ b/man/cupsd.man
@@ -0,0 +1,61 @@
+.\"
+.\" "$Id: cupsd.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" cupsd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsd 8 "Common UNIX Printing System" "18 July 2002" "Easy Software Products"
+.SH NAME
+cupsd \- common unix printing system daemon
+.SH SYNOPSIS
+.B cupsd
+[ \-c
+.I config-file
+] [ \-f ] [ \-F ]
+.SH DESCRIPTION
+\fIcupsd\fR is the scheduler for the Common UNIX Printing System. It
+implements a printing system based upon the Internet Printing Protocol,
+version 1.1. If no options are specified on the command-line then the
+default configuration file (usually \fI/etc/cups/cupsd.conf\fR) will be
+used.
+.PP
+The \fI-f\fR option forces \fIcupsd\fR to run in the foreground; the
+default is to run in the background as a "daemon".
+.PP
+The \fI-F\fR option forces \fIcupsd\fR to run in the foreground
+but detaches the process from the controlling terminal and
+current directory. This is useful for running \fIcupsd\fR from
+\fIinit\fR.
+.SH COMPATIBILITY
+\fIcupsd\fR implements all of the required IPP/1.1 attributes and
+operations. It also implements several CUPS-specific administration
+operations.
+.SH SEE ALSO
+backend(1), classes.conf(5), cupsd.conf(5), filter(1), mime.convs(5),
+mime.types(5), printers.conf(5),
+CUPS Implementation of IPP,
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cupsd.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/cupstestppd.man b/man/cupstestppd.man
new file mode 100644
index 000000000..10a622148
--- /dev/null
+++ b/man/cupstestppd.man
@@ -0,0 +1,105 @@
+.\"
+.\" "$Id: cupstestppd.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" cupstestppd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupstestppd 1 "Common UNIX Printing System" "1 August 2003" "Easy Software Products"
+.SH NAME
+cupstestppd \- test conformance of ppd files
+.SH SYNOPSIS
+.B cupstestppd
+[ -q ] [-r] [ -v[v] ] filename.ppd[.gz] [ ... filenameN.ppd[.gz] ]
+.br
+.B cupstestppd
+[ -q ] [-r] [ -v[v] ] -
+.SH DESCRIPTION
+\fIcupstestppd\fR tests the conformance of PPD files to the
+Adobe PostScript Printer Description file format specification
+version 4.3. It can also be used to list the supported options
+and available fonts in a PPD file. The results of testing and
+any other output are sent to the standard output.
+.LP
+The first form of \fIcupstestppd\fR tests one or more PPD files
+on the command-line. The second form tests the PPD file provided
+on the standard input.
+.LP
+The \fI-q\fR option specifies that no information should be displayed.
+.LP
+The \fI-r\fR option relaxes the PPD conformance requirements so
+that common whitespace, control character, and formatting
+problems are not treated as hard errors.
+.LP
+The \fI-v\fR option specifies that detailed conformance testing
+results should be displayed rather than the concise PASS/FAIL/ERROR
+status.
+.LP
+The \fI-vv\fR option specifies that all information in the PPD
+file should be displayed in addition to the detailed conformance
+testing results.
+.LP
+The \fI-q\fR, \fI-v\fR, and \fI-vv\fR options are mutually exclusive.
+.SH EXIT STATUS
+\fIcupstestppd\fR returns zero on success and non-zero on error. The
+error codes are as follows:
+.TP 5
+1
+.br
+Bad command-line arguments or missing PPD filename.
+.TP 5
+2
+.br
+Unable to open or read PPD file.
+.TP 5
+3
+.br
+The PPD file contains format errors that cannot be skipped.
+.TP 5
+4
+.br
+The PPD file does not conform to the Adobe PPD specification.
+.SH EXAMPLES
+The following command will test all PPD files under the current
+directory and print the names of each file that does not
+conform:
+.nf
+
+ find . -name \\*.ppd \\! -exec cupstestppd -q '{}' \\; -print
+
+.fi
+The next command tests all PPD files under the current directory
+and print detailed conformance testing results for the files
+that do not conform:
+.nf
+
+ find . -name \\*.ppd \\! -exec cupstestppd -q '{}' \\; \\
+ -exec cupstestppd -v '{}' \\;
+
+.fi
+.SH SEE ALSO
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html,
+Adobe PostScript Printer Description File Format Specification, Version 4.3.
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cupstestppd.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/enable.man b/man/enable.man
new file mode 100644
index 000000000..46dc7e6d5
--- /dev/null
+++ b/man/enable.man
@@ -0,0 +1,67 @@
+.\"
+.\" "$Id: enable.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" enable/disable man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH enable 8 "Common UNIX Printing System" "23 January 2001" "Easy Software Products"
+.SH NAME
+disable, enable \- stop/start printers and classes
+.SH SYNOPSIS
+.B disable
+[ -E ] [ \-c ] [ -h
+.I server
+] [ \-r
+.I reason
+] destination(s)
+.br
+.B enable
+[ -E ] destination(s)
+.SH DESCRIPTION
+\fIenable\fR starts the named printers or classes.
+.LP
+\fIdisable\fR stops the named printers or classes. The following options may
+be used:
+.TP 5
+\-c
+.br
+Cancels all jobs on the named destination.
+.TP 5
+\-r [ \fIreason\fR ]
+.br
+Sets the message associated with the stopped state. If no reason is specified
+then the message is set to "Reason Unknown".
+.LP
+The \fI-E\fR option forces encryption when connecting to the server.
+.SH COMPATIBILITY
+The CUPS versions of \fIdisable\fR and \fIenable\fR may ask the user for an
+access password depending on the printing system configuration. This differs
+from the System V versions which require the root user to execute these
+commands.
+.SH SEE ALSO
+accept(8), cancel(1), lp(1), lpadmin(8), lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+
+.\"
+.\" End of "$Id: enable.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/es/Makefile b/man/es/Makefile
new file mode 100644
index 000000000..35924d5ad
--- /dev/null
+++ b/man/es/Makefile
@@ -0,0 +1,103 @@
+#
+# "$Id$"
+#
+# Spanish man page makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+include ../Makefile.common
+
+
+#
+# This is the Spanish manpage makefile...
+#
+
+LANGUAGE = es
+
+
+#
+# Make everything...
+#
+
+all: $(CAT1) $(CAT5) $(CAT8)
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+ $(RM) $(CAT1) $(CAT5) $(CAT8)
+
+
+#
+# Dummy depend target...
+#
+
+depend:
+
+
+#
+# Install files...
+#
+
+install: all
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/man1
+ for file in $(MAN1); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/man1/`basename $$file man`1; \
+ done
+ $(RM) $(MANDIR)/$(LANGUAGE)/man1/cancel.1
+ $(LN) lp.1 $(MANDIR)/$(LANGUAGE)/man1/cancel.1
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/man5
+ for file in $(MAN5); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/man5/`basename $$file man`5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)
+ for file in $(MAN8); do \
+ $(INSTALL_MAN) $$file $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/`basename $$file man`$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(LN) accept.$(MAN8EXT) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(RM) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(LN) enable.$(MAN8EXT) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/cat1
+ for file in $(CAT1); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/cat1; \
+ done
+ $(RM) $(MANDIR)/$(LANGUAGE)/cat1/cancel.$(CAT1EXT)
+ $(LN) lp.$(CAT1EXT) $(MANDIR)/$(LANGUAGE)/cat1/cancel.$(CAT1EXT)
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/cat5
+ for file in $(CAT5); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/cat5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)
+ for file in $(CAT8); do \
+ $(INSTALL_MAN) $$file $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(LN) accept.$(CAT8EXT) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(RM) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+ $(LN) enable.$(CAT8EXT) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+
+
+#
+# End of "$Id$".
+#
diff --git a/man/es/accept.man b/man/es/accept.man
new file mode 100644
index 000000000..37c87256e
--- /dev/null
+++ b/man/es/accept.man
@@ -0,0 +1,57 @@
+.\"
+.\" "$Id: accept.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" accept/reject man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "accept" "8" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+accept/reject \- acepta/rechaza los trabajos enviados a un determinado destino
+.SH "SINOPSIS"
+.B accept
+destino(s)
+.br
+.B reject
+[ \-E ] [ \-h
+.I servidor
+] [ \-r
+.I razón
+]
+destino(s)
+.SH "DESCRIPCIÓN"
+\fIaccept\fR da la orden al sistema de impresión para que acepte los trabajos de impresión enviados hacia el destino especificado.
+.LP
+\fIreject\fR da la orden al sistema de impresión para que rechace los trabajos de impresión enviados hacia el destino especificado. La opción \fI\-r\fR permite especificar la razón por la que se deben rechazar los trabajos de impresión. Si no se especifica, la razón predeterminada es "Razón desconocida".
+.LP
+La opción \fI\-E\fR hace que se use encriptación en la conexión con el servidor.
+.SH "COMPATIBILIDAD"
+La versión de CUPS de \fIaccept\fR y \fIreject\fR puede que pregunten al usuario una palabra de acceso dependiendo de la configuración del sistema de impresión. Esto difiere de las versiones System V que requieren que sea el usuario root el que ejecute estos comandos.
+
+.SH "VÉASE TAMBIÉN"
+cancel(1), disable(8), enable(8), lp(1), lpadmin(8), lpstat(1),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: accept.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/backend.man b/man/es/backend.man
new file mode 100644
index 000000000..599592e66
--- /dev/null
+++ b/man/es/backend.man
@@ -0,0 +1,108 @@
+.\"
+.\" "$Id: backend.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" backend man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "backend" "1" "Common UNIX Printing System" "8 de Octubre de 2004" "Easy Software Products"
+.SH "NOMBRE"
+backend \- programa de transmisión de cups
+.SH "SINOPSIS"
+.B backend
+trabajo usuario título num\-copias opciones [
+.I nombre_archivo
+]
+.SH "DESCRIPCIÓN"
+El programa de transmisión de CUPS proporciona un método estándar de envío de archivos de documentos a diferentes interfaces físicas.
+.LP
+Estos programas deben de ser capaces de leer desde un archivo de la línea de comandos o de la entrada estándar, copiando ésta a un archivo temporal si es requerido por la interfaz física.
+.LP
+El nombre del comando (argv[0]) es la URI de la impresora destino. A partir de la versión de CUPS 1.1.22, cualquier información de autentificación en argv[0] será eliminada, por lo que a los desarrolladores de programas de transmisión se les insta a usar la variable de entorno DEVICE_URI siempre que se requiera información de autentificación.
+.SH "VARIABLES DE ENTORNO"
+Las siguientes variables de entorno son definidas por el servidor CUPS cuando se ejecuta el programa de transmisión:
+.TP 5
+CHARSET
+.br
+El juego de caracteres de texto predeterminado (normalmente us\-ascii o iso\-8859\-1).
+.TP 5
+CLASS
+.br
+Cuando se envía un trabajo a una clase de impresora, contiene el nombre de la clase de impresora destino. Esta variable no se define si el destino no es una clase.
+.TP 5
+CONTENT_TYPE
+.br
+El tipo MIME asociado con el archivo (p. ej. application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+El directorio donde se encuentran los archivos de datos.
+.TP 5
+CUPS_SERVERROOT
+.br
+El directorio raíz del servidor.
+.TP 5
+DEVICE_URI
+.br
+La URI de la impresora; esto se proporciona para los guiones del intérprete de comandos que no pueden leer el argumento argv[0] y para los programas de transmisión que requieran información de autentificación que no está incluida en argv[0].
+.TP 5
+LANG
+.br
+EL idioma predeterminado (normalmente C o en).
+.TP 5
+PATH
+.br
+El directorio de ejecución predeterminado para los programas externos que puedan ser ejecutados por el programa de transmisión.
+.TP 5
+PPD
+.br
+El camino completo del archivo PPD (PostScript Printer Description) para esta impresora.
+.TP 5
+PRINTER
+.br
+El nombre de la impresora.
+.TP 5
+RIP_CACHE
+.br
+La cantidad de memoria recomendada para usar RIPs (Raster Image Processors).
+.TP 5
+SOFTWARE
+.br
+El nombre y la versión del servidor (normalmente CUPS/1.1).
+.TP 5
+TZ
+.br
+La zona horaria (timezone) del servidor.
+.TP 5
+USER
+.br
+El usuario con el que se ejecuta el programa de transmisión, normalmente root; lo establecido actualmente se encuentra en el archivo cupsd.conf.
+.SH "VÉASE TAMBIÉN"
+cupsd(8), filter(1)
+Descripción del diseño de la interface de CUPS,
+Manual de administrador de CUPS,
+Manual del programador de software de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: backend.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/classes.conf.man b/man/es/classes.conf.man
new file mode 100644
index 000000000..72acabe6b
--- /dev/null
+++ b/man/es/classes.conf.man
@@ -0,0 +1,70 @@
+.\"
+.\" "$Id: classes.conf.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" classes.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.TH "classes.conf" "5" "Common UNIX Printing System" "22 de Junio de 2000" "Easy Software Products"
+.SH "NOMBRE"
+classes.conf \- archivo de configuración de clases para cups
+.SH "DESCRIPCIÓN"
+El archivo \fIclasses.conf\fR define las clases de impresoras locales disponibles. Normalmente se encuentra en el directorio \fI/etc/cups\fR y es generado automáticamente por el programa \fIcupsd(8)\fR cuando se añaden o borran clases de impresora.
+.LP
+Cada línea del archivo puede ser o una directiva de configuración, o una línea en blanco, o un comentario. Las líneas de comentario comienzan con el caracter #.
+
+.SH "DIRECTIVAS"
+.TP 5
+<Class name> ... </Class>
+.br
+Define una clase de impresora específica.
+.TP 5
+Accepting
+.br
+Especifica si la clase de impresora acepta o no nuevos trabajos.
+.TP 5
+Info
+.br
+Especifica una descripción para la clase de impresora.
+.TP 5
+Location
+.br
+Especifica una descripción de la ubicación de la clase de impresora.
+.TP 5
+Printer
+.br
+Especifica una impresora que es miembro de la clase de impresora.
+.TP 5
+State
+.br
+Especifica el estado inicial de la clase de impresora: Idle (inactiva) o Stopped (parada).
+.TP 5
+StateMessage
+.br
+Especifica el mensaje asociado con el estado.
+.SH "VÉASE TAMBIÉN"
+cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: classes.conf.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cups-config.man b/man/es/cups-config.man
new file mode 100644
index 000000000..d08cb7d9d
--- /dev/null
+++ b/man/es/cups-config.man
@@ -0,0 +1,91 @@
+.\"
+.\" "$Id: cups-config.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cups-config man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cups-config" "1" "Common UNIX Printing System" "27 de Mayo de 2004" "Easy Software Products"
+.SH "NOMBRE"
+cups\-config \- recupera la información de la api de cups, compilador, directorio, e información de enlace.
+.SH "SINOPSIS"
+.B cups\-config
+\-\-api\-version
+.br
+.B cups\-config
+\-\-cflags
+.br
+.B cups\-config
+\-\-datadir
+.br
+.B cups\-config
+\-\-help
+.br
+.B cups\-config
+\-\-ldflags
+.br
+.B cups\-config
+[
+.I \-\-image
+] [
+.I \-\-static
+] \-\-libs
+.br
+.B cups\-config
+\-\-serverbin
+.br
+.B cups\-config
+\-\-serverroot
+.br
+.B cups\-config
+\-\-version
+.br
+.SH "DESCRIPCIÓN"
+\fBcups\-config\fR es la utilidad de configuración del programa CUPS. Debe ser usada por desarrolladores de aplicaciones para determinar las opciones necesarias de la línea de comandos para el compilador y el enlazador (linker), así como los directorios de instalación de los filtros, los ficheros de configuración y los controladores.
+.LP
+El comando \fI\-\-api\-version\fR visualiza la versión actual de la API (mayor.menor).
+.LP
+El comando \fI\-\-cflags\fR visualiza las opciones necesarias de compilación.
+.LP
+El comando \fI\-\-datadir\fR visualiza el directorio de datos predeterminado de CUPS.
+.LP
+El comando \fI\-\-help\fR visualiza las opciones de uso del programa.
+.LP
+El comando \fI\-\-ldflags\fR visualiza las opciones necesarias del enlazador (linker).
+.LP
+El comando \fI\-\-libs\fR visualiza las bibliotecas necesarias para el enlazado (link).
+La opción \fI\-\-image\fR añade la biblioteca de imágenes de CUPS a la lista.
+La opción \fI\-\-static\fR muestra las bibliotecas estáticas en vez de las bibliotecas predeterminadas (compartidas).
+.LP
+El comando \fI\-\-serverbin\fR visualiza el directorio predeterminado donde se encuentran los filtros y los programas de enlace.
+.LP
+El comando \fI\-\-serverroot\fR visualiza el directorio predeterminado del archivo de configuración de CUPS.
+.LP
+El comando \fI\-\-version\fR visualiza el número completo de la versión de la instalación de CUPS (mayor.menor.revisión).
+.SH "VÉASE TAMBIÉN"
+Manual del programador de software de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cups-config.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cups-lpd.man b/man/es/cups-lpd.man
new file mode 100644
index 000000000..dfc229cff
--- /dev/null
+++ b/man/es/cups-lpd.man
@@ -0,0 +1,100 @@
+.\"
+.\" "$Id: cups-lpd.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cups-lpd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cups-lpd" "8" "Common UNIX Printing System" "11 de Agosto de 2004" "Easy Software Products"
+.SH "NOMBRE"
+cups\-lpd \- recibe los trabajos de impresión e informa del estado de la impresora a los clientes lpd
+.SH "SINOPSIS"
+.B cups\-lpd
+[ \-o
+.I opción=valor
+]
+.SH "DESCRIPCIÓN"
+\fBcups\-lpd\fR es el mini\-servidor Line Printer Daemon ("LPD") que soporta los clientes que usan el protocolo LPD.
+\fBcups\-lpd\fR no actúa como un demonio de red solitario sino que funciona usando el "super\-servidor" de Internet \fBinetd(8)\fR. Añada la siguiente línea al archivo \fBinetd.conf\fR para activar el demonio \fBcups\-lpd\fR:
+.br
+.nf
+
+ printer stream tcp nowait lp /camino/a/demonio/cups/cups\-lpd cups\-lpd \-o document\-format=application/octet\-stream
+.fi
+.LP
+Si está usando el nuevo demonio \fIxinetd(8)\fR, añada las siguientes líneas al archivo \fBxinetd.conf\fR:
+.br
+.nf
+
+ service printer
+ {
+ socket_type = stream
+ protocol = tcp
+ wait = no
+ user = lp
+ group = sys
+ passenv =
+ server = /camino/a/demonio/cups/cups\-lpd
+ server_args = \-o document\-format=application/octet\-stream
+ }
+.fi
+.LP
+El /camino/a/demonio/cups es normalmente /usr/lib/cups/daemon o
+/usr/libexec/cups/daemon, dependiendo del sistema operativo.
+Consulte el archivo cupsd.conf para lo establecido localmente.
+.SH "OPCIONES"
+La opción \fI\-o\fR de \fBcups\-lpd\fR añade opciones para todas las colas de impresión.
+La mayoría de las veces se usa para deshabilitar el filtro "l" para que los trabajos de impresión remotos sean filtrados correctamente:
+.br
+.nf
+
+ printer stream tcp nowait lp /usr/lib/cups/daemon/cups\-lpd cups\-lpd \
+ \-o document\-format=application/octet\-stream
+
+ server = /usr/lib/cups/daemon/cups\-lpd
+ server_args = \-o document\-format=application/octet\-stream
+.fi
+.LP
+En el ejemplo se muestra como el formato del documento es reinicializado a
+\fIapplication/octet\-stream\fR, lo que fuerza la auto detección del tipo de archivo a imprimir.
+.SH "RENDIMIENTO"
+\fBcups\-lpd\fR funciona bien con un número pequeño de clientes e impresoras. Sin embargo, ya que se crea un nuevo proceso con cada conexión y que cada proceso debe hacer peticiones al sistema de impresión antes de cada envío de un trabajo, no funciona bien con configuraciones grandes. Recomendamos que las configuraciones grandes usen el soporte nativo IPP que proporciona CUPS.
+.SH "SEGURIDAD"
+\fBcups\-lpd\fR actualmente no realiza ningún control de acceso basado en lo establecido en los archivos \fIcupsd.conf(5)\fR o en \fIhosts.allow(5)\fR o en \fIhosts.deny\fR usados por los envoltorios TCP. Por lo tanto, la ejecución de \fBcups\-lpd\fR en su servidor permitirá imprimir a cualquier ordenador de su red (y quizás de todo Internet).
+.LP
+Aunque \fIxinetd\fR incorpora soporte de control de acceso, debería usar el paquete de envoltorios TCP junto a \fIinetd\fR para permitir el acceso sólamente a aquellos ordenadores que tengan permiso para imprimir en su servidor.
+.LP
+\fBcups\-lpd\fR no está activado en la distribución estandar de CUPS.
+Por favor consulte al vendedor de su sistema operativo para saber si está activado en su distribución.
+.SH "COMPATIBILIDAD"
+\fBcups\-lpd\fR no cumple el uso restringido de números de puerto especificado en RFC 1179, ya que éste uso restringido no impide a los usuarios que envíen trabajos de impresión. Aunque este comportamiento es diferente de la implementación estandar de LPD Berkeley, ésto no debería afectar a las operaciones normales de los clientes.
+.LP
+La salida de las peticiones de estado cumplen RFC 2569, mapeando entre los protocolos LPD e IPP. Ya que muchas implementaciones de LPD se alejan de esta definición, la información del estado remoto a clientes LPD puede ser poco fiable.
+.SH "VÉASE TAMBIÉN"
+cupsd(8), inetd(8), xinetd(8),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cups-lpd.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
+
diff --git a/man/es/cups-polld.man b/man/es/cups-polld.man
new file mode 100644
index 000000000..a94080858
--- /dev/null
+++ b/man/es/cups-polld.man
@@ -0,0 +1,46 @@
+.\"
+.\" "$Id: cups-polld.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cups-polld man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cups-polld" "8" "Common UNIX Printing System" "10 de Mayo de 2000" "Easy Software Products"
+.SH "NOMBRE"
+cups\-polld \- demonio de interrogación de impresoras cups
+.SH "SINOPSIS"
+.B cups\-polld
+.I dirección puerto\-ipp intervalo puerto\-navegación
+.SH "DESCRIPCIÓN"
+\fBcups\-polld\fR interroga a los servidores remotos por la lista de impresoras y clases de impresora disponibles cada \fIintervalo\fR segundos. La información sobre las impresoras y las clases es entonces reenviada a la interfaz localhost (127.0.0.1)
+para que sea recibida por \fBcupsd(8)\fR.
+.PP
+Este programa es arrancado automáticamente por \fBcupsd\fR para cada una de las directivas BrowsePoll encontradas en al archivo \fBcupsd.conf\fR.
+.SH "VÉASE TAMBIÉN"
+cupsd.conf(5),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cups-polld.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cupsaddsmb.man b/man/es/cupsaddsmb.man
new file mode 100644
index 000000000..9dd64eb66
--- /dev/null
+++ b/man/es/cupsaddsmb.man
@@ -0,0 +1,149 @@
+.\"
+.\" "$Id: cupsaddsmb.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cupsaddsmb man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cupsaddsmb" "8" "Common UNIX Printing System" "19 de Agosto de 2004" "Easy Software Products"
+.SH "NOMBRE"
+cupsaddsmb \- exporta impresoras a samba para clientes windows
+.SH "SINOPSIS"
+.B cupsaddsmb
+[ \-H
+.I servidor\-samba
+] [ \-U
+.I usuario\-samba
+] [ \-h
+.I servidor\-cups
+] [ \-v ] \-a
+.br
+.B cupsaddsmb
+[ \-H
+.I servidor\-samba
+] [ \-U
+.I usuario\-samba
+] [ \-h
+.I servidor\-cups
+] [ \-v ] impresora [ ... impresora ]
+.SH "DESCRIPCIÓN"
+\fIcupsaddsmb\fR exporta impresoras al programa SAMBA (version
+2.2.0 o superior) para que puedan ser usadas por clientes Windows. Dependiendo de la configuración de SAMBA, puede que se necesite dar una palabra de acceso para exportar las impresoras. Este programa necesita los controladores de las impresoras Windows descritos más abajo.
+.LP
+La opción \fI\-H\fR especifica el servidor SAMBA, que por omisión es el servidor CUPS.
+.LP
+La opción \fI\-U\fR especifica el nombre de usuario administrador de impresión de SAMBA, que por omisión es su usuario actual.
+.LP
+La opción \fI\-a\fR exporta todas las impresoras conocidas. De otra forma, solo se exportan las impresoras especificadas.
+.LP
+La opción \fI\-h\fR especifica que se use otro servidor CUPS diferente.
+.LP
+La opción \fI\-v\fR especifica que se debe mostrar información detallada, lo cual es útil para depurar problemas de configuración de SAMBA.
+.SH "CONFIGURACIÓN DE SAMBA"
+\fIcupsaddsmb\fR usa el nuevo soporte de impresión basado en RPC de
+SAMBA 2.2.x para proporcionar controladores de impresora y archivos PPD a las máquinas clientes Windows. Para poder usar esta funcionalidad, primero debe configurar SAMBA (mediante el archivo smb.conf) para que soporte la impresión por mediación de CUPS y proporcionar un recurso compartido de descarga de controladores de impresora, de la forma siguiente:
+.nf
+
+ [global]
+ load printers = yes
+ printing = cups
+ printcap name = cups
+
+ [printers]
+ comment = Todas las impresoras
+ path = /var/spool/samba
+ browseable = no
+ public = yes
+ guest ok = yes
+ writable = no
+ printable = yes
+ printer admin = root
+
+ [print$]
+ comment = Controladores de impresoras
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = root
+.fi
+.LP
+Esta configuración da por sentado una instalación de SAMBA conforme al estandar FHS; cambie los directorios (path) compartidos de [printers] y [print$] de acuerdo a las necesidades de su sistema.
+
+.SH "CONTROLADORES POSTSCRIPT DE MICROSOFT PARA WINDOWS"
+El controlador base para Windows 2000 y versiones posteriores es el controlador
+PostScript de Microsoft, que está disponible en cualquier sistema que ejecute
+Windows 2000 o versiones posteriores en la carpeta
+%WINDOWS%\\SYSTEM32\\SPOOL\\DRIVERS\\W32X86\\3.
+.LP
+Es preferible el controlador de impresión CUPS sobre el de Microsoft, ya que soporta completamente las opciones de etiquetado de página, facturación de trabajos, y espera de trabajo, en todas las impresoras. Sin embargo, actualmente el controlador de Microsoft sólo soporta Windows 2000 y versiones posteriores, por lo que necesita conseguir el controlador de Adobe para soportar clientes Windows 95, 98, and Me. Los controladores de Adobe y Microsoft para Windows 2000 son idénticos.
+.LP
+Una vez extraídos los archivos del controlador, cree un directorio "drivers" en el directorio de datos de CUPS (normalmente /usr/share/cups) y copie los archivos exactamente como se nombran a continuación:
+.nf
+
+ [Windows 2000 y versiones posteriores]
+ ps5ui.dll
+ pscript.hlp
+ pscript.ntf
+ pscript5.dll
+.fi
+
+.SH "CONTROLADORES POSTSCRIPT DE CUPS PARA WINDOWS"
+\fIcupsaddsmb\fR puede usar la versión 6 del controlador de impresoras PostScript de CUPS para Windows, que está disponible para ser descargado de la página web de CUPS.
+.LP
+El controlador de impresoras de CUPS se prefiere sobre los controladores de Adobe y Microsoft ya que soporta completamente las opciones de etiquetado de página, facturación de trabajos, y espera de trabajo, en todas las impresoras. Sin embargo, actualmente el controlador de CUPS sólo soporta Windows 2000 y versiones posteriores, por lo que necesita conseguir el controlador de Adobe para soportar clientes Windows 95, 98, and Me.
+.LP
+Una vez extraídos los archivos del controlador, cree un directorio "drivers" en el directorio de datos de CUPS (normalmente /usr/share/cups) y copie los archivos exactamente como se nombran a continuación:
+.nf
+
+ [Windows 2000 y versiones posteriores]
+ cupsui6.dll
+ cupsdrv6.dll
+ ps5ui.dll
+ pscript.hlp
+ pscript.ntf
+ pscript5.dll
+.fi
+
+.SH "CONTROLADORES POSTSCRIPT DE ADOBE PARA WINDOWS"
+\fIcupsaddsmb\fR puede usar el controlador de impresoras PostScript de Adobe para Windows, que está disponible para ser descargado de la página web de Adobe (http://www.adobe.com).
+.LP
+El controlador de impresoras de CUPS se prefiere sobre los controladores de Adobe ya que soporta completamente las opciones de etiquetado de página, facturación de trabajos, y espera de trabajo, en todas las impresoras. Puede usar los controladores de Adobe para Windows 9x y los controladores de CUPS para Windows 2000 y versiones posteriores. Los controladores de Adobe y Microsoft para Windows 2000 son idénticos.
+.LP
+Una vez extraídos los archivos del controlador, cree un directorio "drivers" en el directorio de datos de CUPS (normalmente /usr/share/cups) y copie los archivos exactamente como se nombran a continuación:
+.nf
+
+ [Windows 95, 98, y Me]
+ ADFONTS.MFM
+ ADOBEPS4.DRV
+ ADOBEPS4.HLP
+ ICONLIB.DLL
+ PSMON.DLL
+.fi
+.SH "VÉASE TAMBIÉN"
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cupsaddsmb.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cupsd.conf.man b/man/es/cupsd.conf.man
new file mode 100644
index 000000000..b520add4e
--- /dev/null
+++ b/man/es/cupsd.conf.man
@@ -0,0 +1,383 @@
+.\"
+.\" "$Id: cupsd.conf.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cupsd.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cupsd.conf" "5" "Common UNIX Printing System" "18 de Agosto de 2004" "Easy Software Products"
+.SH "NOMBRE"
+cupsd.conf \- archivo de configuración del servidor cups
+.SH "DESCRIPCIÓN"
+El archivo \fIcupsd.conf\fR configura el programa planificador de tareas de CUPS, \fIcupsd(8)\fR. Normalmente se encuentra en el directorio \fI/etc/cups\fR.
+.LP
+Cada línea del archivo puede ser o una directiva de configuración, o una línea en blanco, o un comentario. Las líneas de comentario comienzan por el carácter #. Las directivas de configuración son intencionadamente similares a las usadas por el popular servidor de páginas web Apache, como se describe más adelante.
+.SH "DIRECTIVAS"
+\fIcupsd\fR reconoce las siguientes directivas. Consulte el manual de administrador de CUPS si necesita una descripción detallada:
+.TP 5
+AccessLog
+.br
+Define el nombre del archivo de registro de los accesos.
+.TP 5
+Allow
+.br
+Indica desde que equipos o direcciones se permite el acceso.
+.TP 5
+AuthClass
+.br
+Especifica la clase de autentificación: User (usuario), Group (grupo), System (sistema)
+.TP 5
+AuthGroupName
+.br
+Especifica el grupo de autentificación.
+.TP 5
+AuthType
+.br
+Especifica el tipo de autentificación: None (ninguna), Basic (básica), Digest (resumida)
+.TP 5
+AutoPurgeJobs
+.br
+Especifica si se purgan automáticamente los datos del historial de trabajos cuando ya no son necesarios para el establecimiento de cuotas.
+.TP 5
+BrowseAddress
+.br
+Especifica una dirección para el envío de paquetes de información de impresora.
+.TP 5
+BrowseAllow
+.br
+Permite la llegada de paquetes de información de impresora desde el ordenador o dirección especificados.
+.TP 5
+BrowseDeny
+.br
+No permite la llegada de paquetes de información de impresora desde el ordenador o dirección especificados.
+.TP 5
+BrowseInterval
+.br
+Especifica el intervalo de tiempo máximo entre peticiones de información a las impresoras.
+.TP 5
+BrowseOrder
+.br
+Especifica el orden del control de acceso a la información de las impresoras: allow,deny (permitir, denegar) o deny,allow (denegar, permitir)
+.TP 5
+BrowsePoll
+.br
+Especifica el servidor que recuperará la información de las impresoras.
+.TP 5
+BrowsePort
+.br
+Especifica el puerto de escucha de los paquetes de información de las impresoras.
+.TP 5
+BrowseProtocols
+.br
+Especifica el protocolo a usar para las peticiones a las impresoras.
+.TP 5
+BrowseRelay
+.br
+Especifica los paquetes de información de impresoras que deben ser transmitidos desde un ordenador o red a otro ordenador o red.
+.TP 5
+BrowseShortNames
+.br
+Especifica si impresoras remotas usarán nombres cortos ("impresora") o no
+("impresora@servidor"). Esta opción es ignorada si existe más de una impresora remota con el mismo nombre.
+.TP 5
+BrowseTimeout
+.br
+Especifica el máximo intervalo de tiempo entre actualizaciones de la información de las impresoras antes de que las impresoras remotas sean borradas de la lista de impresoras disponibles.
+.TP 5
+Browsing
+.br
+Especifica si se buscan o no impresoras remotas.
+.TP 5
+Classification
+.br
+Especifica la clasificación de seguridad del servidor.
+.TP 5
+ClassifyOverride
+.br
+Especifica si se permite a usuarios individuales no hacer caso de la clasificación de trabajos individuales de impresión.
+.TP 5
+ConfigFilePerm
+.br
+Especifica los permisos para todos los archivos de configuración que escriba el programa de planificación de tareas.
+.TP 5
+DataDir
+.br
+Especifica el directorio de los archivos de datos.
+.TP 5
+DefaultCharset
+.br
+Especifica el juego de caracteres predeterminado a ser usado en el texto.
+.TP 5
+DefaultLanguage
+.br
+Especifica el idioma predeterminado a ser usado en el texto y en las páginas web.
+.TP 5
+Deny
+.br
+Especifica a qué ordenadores o direcciones deniega el acceso.
+.TP 5
+DocumentRoot
+.br
+Especifica el directorio raíz de los documentos del servidor web interno.
+.TP 5
+Encryption
+.br
+Especifica el nivel de encriptación requerido para un lugar determinado.
+.TP 5
+ErrorLog
+.br
+Especifica el nombre del archivo de registro de errores.
+.TP 5
+FaxRetryInterval
+.br
+Especifica el tiempo, en segundos, entre reintentos de trabajos de fax.
+.TP 5
+FaxRetryLimit
+.br
+Especifica el número de reintentos que se pueden hacer para trabajos de fax.
+.TP 5
+FileDevice
+.br
+Especifica si se puede usar para nuevas colas de impresora el archivo pseudo\-dispositivo.
+.TP 5
+FilterLimit
+.br
+Especifica el coste máximo de filtros que pueden ser ejecutados concurrentemente.
+.TP 5
+FilterNice
+.br
+Especifica la prioridad (valor "nice") de los filtros ejecutados para imprimir un archivo.
+.TP 5
+FontPath
+.br
+Especifica el camino de búsqueda de las fuentes.
+.TP 5
+Group
+.br
+Especifica el nombre del grupo o ID que será usado cuando se ejecuten programas externos.
+.TP 5
+HideImplicitMembers
+.br
+Especifica si se deben ocultar miembros de clases implícitas.
+.TP 5
+HostNameLookups
+.br
+Especifica si se hacen o no averiguaciones inversas de direcciones de clientes.
+.TP 5
+ImplicitAnyClasses
+.br
+Especifica si se deben crear o no clases implícitas para impresoras locales y remotas, p.e. "UnaImpresora" para "Impresora", "Impresora@servidor1",
+e "Impresora@servidor2".
+.TP 5
+ImplicitClasses
+.br
+Especifica si se deben crear clases implícitas de impresoras remotas idénticas.
+.TP 5
+Include
+.br
+Incluye el archivo especificado.
+.TP 5
+KeepAlive
+.br
+Especifica si funciona la característica "HTTP Keep\-Alive".
+.TP 5
+KeepAliveTimeout
+.br
+Especifica el tiempo de espera máximo para la característica "HTTP Keep\-Alive".
+.TP 5
+<Limit methods> ... </Limit>
+.TP 5
+<LimitExcept methods> ... </LimitExcept>
+.br
+Especifica los métodos HTTP limitados en un lugar determinado.
+.TP 5
+LimitRequestBody
+.br
+Especifica el tamaño máximo de cualquier petición de impresión de un trabajo.
+.TP 5
+Listen
+.br
+Escucha en la dirección y puerto especificado.
+.TP 5
+<Location /path> ... </Location>
+.br
+Especifica el control de acceso para el lugar especificado.
+.TP 5
+LogFilePerm
+.br
+Especifica los permisos para todos los archivos de registro que escriba el programa planificador de tareas.
+.TP 5
+LogLevel
+.br
+Especifica el nivel de registro: none (ninguno), warn (avisos), error (errores), info (información), debug (depuración), or debug2 (depuración2).
+.TP 5
+MaxClients
+.br
+Especifica el número máximo de clientes simultáneos a mantener.
+.TP 5
+MaxClientsPerHost
+.br
+Especifica el número máximo de clientes simultáneos a mantener desde una única dirección.
+.TP 5
+MaxCopies
+.br
+Especifica el número máximo de copias que un usuario puede imprimir de cada trabajo.
+.TP 5
+MaxJobs
+.br
+Especifica el número máximo de trabajos simultáneos a mantener.
+.TP 5
+MaxJobsPerPrinter
+.br
+Especifica el número máximo de trabajos simultáneos por impresora a mantener.
+.TP 5
+MaxJobsPerUser
+.br
+Especifica el número máximo de trabajos simultáneos por usuario a mantener.
+.TP 5
+MaxLogSize
+.br
+Especifica el tamaño máximo de los archivos de registro antes de que se empiecen a rotar (0 deshabilita la rotación).
+.TP 5
+MaxRequestSize
+.br
+Especifica el tamaño máximo del archivo o petición en bytes (0 indica sin límite)
+.TP 5
+Order
+.br
+Especifica el orden del control de acceso HTTP: allow,deny (permitir, denegar) o deny,allow (denegar, permitir).
+.TP 5
+PageLog
+.br
+Especifica el nombre del archivo de registro de páginas.
+.TP 5
+Port
+.br
+Especifica un número de puerto para la escucha de peticiones HTTP.
+.TP 5
+PreserveJobFiles
+.br
+Especifica se se guardan los archivos de trabajos después de ser impresos.
+.TP 5
+PreserveJobHistory
+.br
+Especifica si se guarda el historial de impresión de trabajos después de que éstos hayan sido impresos.
+.TP 5
+Printcap
+.br
+Especifica el nombre de un archivo printcap que se actualiza automáticamente con una lista de impresoras disponibles (necesario para aplicaciones heredadas).
+.TP 5
+PrintcapFormat
+.br
+Especifica el formato del archivo printcap.
+.TP 5
+PrintcapGUI
+.br
+Especifica si se deben generar archivos de definición de panel de opciones en algunos sistemas operativos.
+.TP 5
+ReloadTimeout
+.br
+Especifica la cantidad de tiempo que se debe esperar a que se imprima un trabajo antes de reinicializar el programa planificador de tareas.
+.TP 5
+RemoteRoot
+.br
+Especifica el nombre de usuario asociado con accesos no autentificados del usuario root.
+.TP 5
+RequestRoot
+.br
+Especifica el directorio donde se guardan los trabajos de impresión y otros datos de peticiones HTTP.
+.TP 5
+Require
+.br
+Especifica que se necesita tal usuario o grupo.
+.TP 5
+RIPCache
+.br
+Especifica la máxima cantidad de memoria a usar cuando se convierten imágenes y archivos PostScript a mapas de bits para una impresora.
+.TP 5
+RunAsUser
+.br
+Especifica que el programa planificador de tareas debe ser ejecutado como el usuario sin privilegios especificado con la directiva User.
+.TP 5
+Satisfy
+.br
+Especifica si todos o cualquier límite especificado para un lugar debe ser satisfecho para permitir el acceso.
+.TP 5
+ServerAdmin
+.br
+Especifica la dirección de correo del administrador del servidor.
+.TP 5
+ServerBin
+.br
+Especifica el directorio donde se encuentran los programas de transmisión, los CGIs, los demonios y los filtros.
+.TP 5
+ServerCertificate
+.br
+Especifica el certificado de encriptación a usar.
+.TP 5
+ServerKey
+.br
+Especifica la llave de encriptación a usar.
+.TP 5
+ServerName
+.br
+Especifica el nombre completo del servidor.
+.TP 5
+ServerRoot
+.br
+Especifica el directorio donde se encuentran los archivos de configuración del servidor.
+.TP 5
+ServerTokens
+.br
+Especifica la información que es incluida en la cabecera de las respuestas HTTP del servidor.
+.TP 5
+SSLListen
+.br
+Escucha en la dirección y puerto especificados para las conexiones encriptadas.
+.TP 5
+SSLPort
+.br
+Escucha en el puerto especificado para las conexiones encriptadas.
+.TP 5
+SystemGroup
+.br
+Especifica el grupo a usar para la autentificación de clases del sistema.
+.TP 5
+TempDir
+.br
+Especifica el directorio donde se almacenan los archivos temporales.
+.TP 5
+Timeout
+.br
+Especifica el tiempo de espera máximo en segundos en las peticiones HTTP.
+.TP 5
+User
+.br
+Especifica el nombre de usuario o ID a usar cuando se ejecuten programas externos.
+.SH "VÉASE TAMBIÉN"
+classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cupsd.conf.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cupsd.man b/man/es/cupsd.man
new file mode 100644
index 000000000..0e895f408
--- /dev/null
+++ b/man/es/cupsd.man
@@ -0,0 +1,54 @@
+.\"
+.\" "$Id: cupsd.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cupsd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cupsd" "8" "Common UNIX Printing System" "18 de Julio de 2002" "Easy Software Products"
+.SH "NOMBRE"
+cupsd \- demonio de CUPS (common unix printing system)
+.SH "SINOPSIS"
+.B cupsd
+[ \-c
+.I archivo\-configuración
+] [ \-f ] [ \-F ]
+.SH "DESCRIPCIÓN"
+\fIcupsd\fR es el programa planificador de tareas del "Sistema de impresión común de UNIX" (CUPS). Implementa un sistema de impresión basado en el "Protocolo de impresión de Internet" (IPP) versión 1.1. Si no se especifican opciones en la línea de comandos, se usa el archivo de configuración predeterminado (normalmente \fI/etc/cups/cupsd.conf\fR).
+.PP
+La opción \fI\-f\fR fuerza a que \fIcupsd\fR sea ejecutado en primer plano; por omisión es ejecutado en segundo plano como un "demonio".
+.PP
+La opción \fI\-F\fR fuerza a que \fIcupsd\fR sea ejecutado en primer plano, pero separa el proceso del terminal de control y del directorio actual. Esto es útil para poder ejecutar \fIcupsd\fR desde \fIinit\fR.
+.SH "COMPATIBILIDAD"
+\fIcupsd\fR implementa todos los atributos y operaciones requeridos por IPP/1.1. También implementa varias operaciones de administración específicas de CUPS.
+.SH "VÉASE TAMBIÉN"
+backend(1), classes.conf(5), cupsd.conf(5), filter(1), mime.convs(5),
+mime.types(5), printers.conf(5),
+La implementación de CUPS de IPP,
+Descripción del diseño de la interface de CUPS,
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cupsd.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/cupstestppd.man b/man/es/cupstestppd.man
new file mode 100644
index 000000000..616697648
--- /dev/null
+++ b/man/es/cupstestppd.man
@@ -0,0 +1,90 @@
+.\"
+.\" "$Id: cupstestppd.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" cupstestppd man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "cupstestppd" "1" "Common UNIX Printing System" "1 de Agosto de 2003" "Easy Software Products"
+.SH "NOMBRE"
+cupstestppd \- test de conformidad de archivos ppd
+.SH "SINOPSIS"
+.B cupstestppd
+[ \-q ] [\-r] [ \-v[v] ] archivo.ppd[.gz] [ ... archivoN.ppd[.gz] ]
+.br
+.B cupstestppd
+[ \-q ] [\-r] [ \-v[v] ] \-
+.SH "DESCRIPCIÓN"
+\fIcupstestppd\fR prueba la conformidad de archivos PPD según la especificación del formato de archivo de descripción de impresora PostScript de Adobe, versión 4.3. También puede ser usado para listar las opciones implementadas y las fuentes disponibles en un archivo PPD. El resultado del test y cualquier otra salida se envían a la salida estandar.
+.LP
+La primera forma de \fIcupstestppd\fR prueba uno o más archivos PPD desde la línea de comandos. La segunda forma prueba el archivo PPD proporcionado en la entrada estandar.
+.LP
+La opción \fI\-q\fR especifica que no se debe visualizar ninguna información.
+.LP
+La opción \fI\-r\fR rebaja los requerimientos de conformidad PPD para que espacios en blanco comunes, caracteres de control y problemas de formato no sean tratados como errores críticos.
+.LP
+La opción \fI\-v\fR especifica que los resultados detallados de la prueba de conformidad deben ser visualizados en vez de la forma más concisa de PASS/FAIL/ERROR (PASA/FALLO/ERROR).
+.LP
+La opción \fI\-vv\fR especifica que toda la información del archivo PPD debe ser visualizada más los resultados detallados del test de conformidad.
+.LP
+Las opciones \fI\-q\fR, \fI\-v\fR, y \fI\-vv\fR son mutuamente excluyentes.
+.SH "ESTADO DE SALIDA"
+\fIcupstestppd\fR devuelve cero si todo ha ido bien y un valor distinto de cero en caso de error. Estos son los códigos de error:
+.TP 5
+1
+.br
+Argumentos de la línea de comandos incorrectos o falta el nombre del archivo PPD.
+.TP 5
+2
+.br
+No se ha podido abrir o leer el archivo PPD.
+.TP 5
+3
+.br
+El archivo PPD contiene errores de formato que no pueden ser ignorados.
+.TP 5
+4
+.br
+El archivo PPD no es conforme a la especificación PPD de Adobe.
+.SH "EJEMPLOS"
+El comando siguiente prueba todos los archivos PPD que se encuentren bajo el directorio actual e imprime los nombres de los archivos que no son conformes a la especificación:
+.nf
+
+ find . \-name \\*.ppd \\! \-exec cupstestppd \-q '{}' \\; \-print
+
+.fi
+El comando siguiente prueba todos los archivos PPD que se encuentren bajo el directorio actual e imprime el resultado de la prueba de conformidad para los archivos que no son conformes a la especificación:
+.nf
+
+ find . \-name \\*.ppd \\! \-exec cupstestppd \-q '{}' \\; \\
+ \-exec cupstestppd \-v '{}' \\;
+
+.fi
+.SH "VÉASE TAMBIÉN"
+Manual de administrador de CUPS,
+Manual del programador de software de CUPS,
+http://localhost:631/documentation.html,
+Especificación del formato del archivo de descripción de impresora PostScript de Adobe, versión 4.3.
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: cupstestppd.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/enable.man b/man/es/enable.man
new file mode 100644
index 000000000..1e4cfd6fe
--- /dev/null
+++ b/man/es/enable.man
@@ -0,0 +1,64 @@
+.\"
+.\" "$Id: enable.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" enable/disable man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "enable" "8" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+disable, enable \- detiene/inicia impresoras y clases
+.SH "SINOPSIS"
+.B disable
+[ \-E ] [ \-c ] [ \-h
+.I servidor
+] [ \-r
+.I razón
+] destino(s)
+.br
+.B enable
+[ \-E ] destino(s)
+.SH "DESCRIPCIÓN"
+\fIenable\fR inicia la impresora o clase especificada.
+.LP
+\fIdisable\fR detiene la impresora o clase especificada. Se pueden usar las siguientes opciones:
+.TP 5
+\-c
+.br
+Cancela todos los trabajos en el destino especificado.
+.TP 5
+\-r [ \fIrazón\fR ]
+.br
+Selecciona el mensaje asociado con el estado de la detención. Si no se especifica ninguna razón, entonces el mensaje usado es "Razón desconocida".
+.LP
+La opción \fI\-E\fR hace que se use encriptación en la conexión con el servidor.
+.SH "COMPATIBILIDAD"
+La versión de CUPS de \fIdisable\fR y \fIenable\fR puede que pregunten al usuario una palabra de acceso dependiendo de la configuración del sistema de impresión. Esto difiere de las versiones System V que requieren que sea el usuario root el que ejecute estos comandos.
+
+.SH "VÉASE TAMBIÉN"
+accept(8), cancel(1), lp(1), lpadmin(8), lpstat(1), reject(8),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: enable.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/filter.man b/man/es/filter.man
new file mode 100644
index 000000000..9f2b13f7b
--- /dev/null
+++ b/man/es/filter.man
@@ -0,0 +1,110 @@
+.\"
+.\" "$Id: filter.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" filter man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "filter" "1" "Common UNIX Printing System" "22 de Junio de 2000" "Easy Software Products"
+.SH "NOMBRE"
+filter \- interfaces de filtros para la conversión de archivos de cups
+.SH "SINOPSIS"
+.B filter
+trabajo usuario título num\-copias opciones [
+.I archivo
+]
+.SH "DESCRIPCIÓN"
+La interface de filtro de CUPS proporciona un método estandar para poder añadir que se puedan usar nuevos tipos de documentos en CUPS. Cada filtro es capaz de convertir desde uno o más formatos de entrada a otro formato que puede ser directamente impreso o, mediante una tubería (pipe), introducido en otro filtro para conseguir un formato imprimible.
+.LP
+Los filtros deben ser capaces de leer desde un archivo especificado en la línea de comandos o desde la entrada estandar, copiando ésta a un archivo temporal si es requerido por el formato del archivo. Todas las salidas deben ser enviadas a la salida estandar.
+.LP
+El nombre del comando (argv[0]) es el nombre de la impresora destino.
+.SH "VARIABLES DE ENTORNO"
+Las siguientes variables de entorno son definidas por el servidor CUPS cuando se ejecuta cada filtro:
+.TP 5
+CHARSET
+.br
+El juego de caracteres predeterminado (normalmente us\-ascii o iso\-8859\-1).
+.TP 5
+CLASS
+.br
+Cuando se envía un trabajo a una clase de impresora, contiene el nombre de la clase de impresora destino. Esta variable no se define si el destino no es una clase.
+.TP 5
+CONTENT_TYPE
+.br
+El tipo MIME asociado con el archivo (p. ej. application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+El directorio donde se pueden encontrar los archivos de datos.
+.TP 5
+CUPS_SERVERROOT
+.br
+El directorio raíz del servidor.
+.TP 5
+DEVICE_URI
+.br
+La URI del dispositivo asociada con la impresora
+.TP 5
+LANG
+.br
+EL idioma predeterminado (normalmente C o en).
+.TP 5
+PATH
+.br
+El directorio de ejecución predeterminado para los programas externos que puedan ser ejecutados por el filtro.
+.TP 5
+PPD
+.br
+El camino completo del archivo PPD (PostScript Printer Description) para esta impresora.
+.TP 5
+PRINTER
+.br
+El nombre de la impresora; esto sirve para guiones del intérprete de comandos que no pueden leer el argumento argv[0].
+.TP 5
+RIP_CACHE
+.br
+La cantidad de memoria recomendada para usar RIPs (Raster Image Processors).
+.TP 5
+SOFTWARE
+.br
+El nombre y la versión del servidor (normalmente CUPS/1.1).
+.TP 5
+TZ
+.br
+La zona horaria (timezone) del servidor.
+.TP 5
+USER
+.br
+El usuario con el que se ejecuta el filtro, normalmente lp; lo establecido actualmente se encuentra en el archivo cupsd.conf.
+.SH "COMPATIBILIDAD"
+Aunque la interfaz del filtro es compatible con la interfaz de los guiones System V, sólo funcionará con éstos como un filtro único. Normalmente el guión de interfaz se obtiene con el comando \fBlpadmin(8)\fR usando la opción \fI\-i\fR.
+.SH "VÉASE TAMBIÉN"
+backend(1), cupsd(8),
+Descripción del diseño de la interface de CUPS,
+Manual de administrador de CUPS,
+Manual del programador de software de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: filter.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lp.man b/man/es/lp.man
new file mode 100644
index 000000000..9a1d4e522
--- /dev/null
+++ b/man/es/lp.man
@@ -0,0 +1,165 @@
+.\"
+.\" "$Id: lp.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lp/cancel man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lp" "1" "Common UNIX Printing System" "1 de Mayo de 2003" "Easy Software Products"
+.SH "NOMBRE"
+lp \- imprime archivos
+.br
+cancel \- cancela trabajos
+.SH "SINOPSIS"
+.B lp
+[ \-E ] [ \-c ] [ \-d
+.I destino
+] [ \-h
+.I servidor
+] [ \-m ] [ \-n
+.I num\-copias
+[ \-o
+.I opción
+] [ \-q
+.I prioridad
+] [ \-s ] [ \-t
+.I título
+] [ \-H
+.I manejo
+] [ \-P
+.I lista\-páginas
+] [
+.I archivos(s)
+]
+.br
+.B lp
+[ \-E ] [ \-c ] [ \-h
+.I servidor
+] [ \-i
+.I id\-trabajo
+] [ \-n
+.I num\-copias
+[ \-o
+.I opción
+] [ \-q
+.I prioridad
+] [ \-t
+.I título
+] [ \-H
+.I manejo
+] [ \-P
+.I lista\-páginas
+]
+.br
+.B cancel
+[ \-a ] [ \-h
+.I servidor
+] [ \-u
+.I usuario
+] [
+.I id
+] [
+.I destino
+] [
+.I id\-destino
+]
+.SH "DESCRIPCIÓN"
+\fBlp\fR realiza la impresión de un archivo o modifica un trabajo de impresión pendiente. Use el nombre de archivo "\-" para imprimir desde la entrada estandar.
+.LP
+\fBcancel\fR cancela los trabajos de impresión existentes. La opción \fI\-a\fR cancela todos los trabajos del destino especificado.
+.SH "OPCIONES"
+\fBlp\fR reconoce las siguientes opciones:
+.TP 5
+\-E
+.br
+Hace que se use encriptación en la conexión con el servidor.
+.TP 5
+\-c
+.br
+Esta opción funciona sólamente por motivos de compatibilidad. En sistemas que la soportan, obliga a que el archivo de impresión se copie al directorio spool antes de ser impreso. En CUPS, los archivos impresos se envían siempre al planificador de tareas via IPP, lo cual tiene el mismo efecto.
+.TP 5
+\-d \fIdestino\fR
+.br
+Imprime archivos en la impresora especificada.
+.TP 5
+\-h \fIservidor\fR
+.br
+Especifica el nombre del servidor de impresión. Por omisión es "localhost" o el valor de la variable de entorno CUPS_SERVER.
+.TP 5
+\-i \fIid\-trabajo\fR
+.br
+Especifica el trabajo existente que se va a modificar.
+.TP 5
+\-m
+.br
+Envía un correo cuando se ha impreso el trabajo (no soportado en CUPS 1.1.)
+.TP 5
+\-n \fIcopias\fR
+.br
+Especifica el número de copias a imprimir de 1 a 100.
+.TP 5
+\-o \fIopción\fR
+.br
+Especifica una opción para el trabajo.
+.TP 5
+\-q \fIprioridad\fR
+.br
+Especifica la prioridad del trabajo de 1 (la más baja) a 100 (la más alta). La prioridad predeterminada es 50.
+.TP 5
+\-s
+.br
+No informa del ID del trabajo resultante (modo silencioso).
+.TP 5
+\-t \fInombre\fR
+.br
+Especifica el nombre del trabajo.
+.TP 5
+\-u \fIusuario\fR
+.br
+Cancela los trabajos pertenecientes a \fIusuario\fR.
+.TP 5
+\-H \fImanejo\fR
+.br
+Especifica cuando debe ser impreso el trabajo. Un valor de
+\fIimmediate\fR imprimirá el archivo inmediatamente, un valor de
+\fIhold\fR retendrá el trabajo indefinidamente, y un valor de tiempo
+(HH:MM) retendrá el trabajo hasta la hora especificada. Use el valor de \fIresume\fR con la opción \fI\-i\fR para reanudar un trabajo retenido. Use un valor de \fIrestart\fR con la opción \fI\-i\fR para reiniciar un trabajo completado.
+.TP 5
+\-P \fIlista\-páginas\fR
+.br
+Especifica qué páginas imprimir del documento. La lista puede contener una lista de números y rangos (#\-#) separados por comas (p.e. 1,3\-5,16).
+.SH "COMPATIBILIDAD"
+A diferencia del sistema de impresión System V, CUPS permite que los nombres de impresoras contengan cualquier carácter imprimible excepto ESPACIO y TAB. También, en los nombres de clases e impresoras \fBno\fR hay distinción entre mayúsculas y minúsculas.
+.LP
+La opción "m" no funciona en CUPS 1.1.
+.LP
+La opción "q" acepta un rango diferente de valores que el comando lp de Solaris, igualando los valores de prioridad de IPP (1\-100) en vez de los valores de Solaris (0\-39).
+.SH "NOTAS"
+Los administradores que deseen impedir cancelaciones no autorizadas de trabajos mediante la opción \fI\-u\fR deben proteger con una palabra de acceso el directorio donde se almacenan los trabajos (véase la opción en \fIcupsd.conf(5)\fR).
+.SH "VÉASE TAMBIÉN"
+lpstat(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lp.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpadmin.man b/man/es/lpadmin.man
new file mode 100644
index 000000000..054d51e13
--- /dev/null
+++ b/man/es/lpadmin.man
@@ -0,0 +1,138 @@
+.\"
+.\" "$Id: lpadmin.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpadmin" "8" "Common UNIX Printing System" "21 de Octubre de 2002" "Easy Software Products"
+.SH "NOMBRE"
+lpadmin \- configura las impresoras y clases cups
+.SH "SINOPSIS"
+.B lpadmin
+[ \-E ] [ \-h
+.I servidor
+] \-d
+.I destino
+.br
+.B lpadmin
+[ \-E ] [ \-h
+.I servidor
+] \-p
+.I impresora
+.I opcion(es)
+.br
+.B lpadmin
+[ \-E ] [ \-h
+.I servidor
+] \-x
+.I destino
+.SH "DESCRIPCIÓN"
+\fIlpadmin\fR configura las colas de las clases e impresoras proporcionadas por CUPS. También se puede usar para poner la clase o impresora predeterminada del servidor.
+.LP
+Cuando se usa la opción \fI\-E\fR antes de las opciones \fI\-d\fR, \fI\-p\fR, o \fI\-x\fR, hace que se use encriptación en la conexión con el servidor.
+.LP
+La primera forma del comando pone como clase o impresora predeterminada a \fIdestino\fR. Los trabajos de impresión enviados posteriormente mediante el comando \fIlp(1)\fR o
+\fIlpr(1)\fR utilizarán este destino a menos que el usuario especifique otra cosa con el comando \fIlpoptions(1)\fR.
+.LP
+La segunda forma del comando configura la impresora especificada. Las opciones adicionales se describen a continuación.
+.LP
+La tercera forma del comando borra la clase o impresora \fIdestino\fR.
+Cualquier trabajo pendiente para este destino será borrado y cualquier trabajo en proceso de impresión será cancelado.
+.SH "OPCIONES DE CONFIGURACIÓN"
+Estas son las opciones reconocidas cuando se configura una cola de impresora:
+.TP 5
+\-c \fIclase\fR
+.br
+Añade la \fIimpresora\fR especificada a la \fIclase\fR. Si \fIclase\fR no existe, se crea automáticamente.
+.TP 5
+\-i \fIinterfaz\fR
+.br
+Establece para la impresora un guión (script) de interfaz estilo System V. Esta opción no puede ser especificada con la opción \fI\-P\fR (archivo PPD) y está pensada para dar soporte a controladores de impresora legados.
+.TP 5
+\-m \fImodelo\fR
+.br
+Establece un guión (script) de interfaz estandar System V o archivo PPD desde el directorio modelo.
+.TP 5
+\-o \fInombre=valor\fR
+.br
+Establece una opción del servidor o PPD para la impresora. Se pueden listar las opciones PPD usando la opción \fI\-l\fR con el comando \fIlpoptions(1)\fR.
+.TP 5
+\-o \fIjob\-k\-limit=valor\fR
+.br
+Establece un límite en kilobytes para las cuotas por usuario. El valor es un número entero de kilobytes; un kilobyte son 1024 bytes.
+.TP 5
+\-o \fIjob\-page\-limit=valor\fR
+.br
+Establece el límite de páginas para las cuotas por usuario. El valor es un número entero con el número de páginas que pueden ser impresas; páginas por las dos caras se cuentan como dos páginas.
+.TP 5
+\-o \fIjob\-quota\-period=valor\fR
+.br
+Establece el periodo de contabilidad para las cuotas por usuario. El valor es un número entero de segundos; un día tiene 86.400 segundos.
+.TP 5
+\-o \fIprotocol=nombre\fR
+.br
+Establece el protocolo de comunicaciones binario a usar cuando se imprime, None (ninguno), BCP, o TBCP. El protocolo predeterminado es None (ninguno).
+.TP 5
+\-r \fIclase\fR
+.br
+Elimina la \fIimpresora\fR especificada de la \fIclase\fR. Si la clase resultante no tiene más impresoras, se borra.
+.TP 5
+\-u \fIallow:usuario,usuario,@grupo\fR
+\-u \fIdeny:usuario,usuario,@grupo\fR
+\-u \fIallow:all\fR
+\-u \fIdeny:none\fR
+.br
+Establece el control de acceso a nivel de usuario en una impresora. Los nombres que comiencen con "@" se interpretan como grupos UNIX. Las dos últimas formas desactivan el control de acceso a nivel de usuario.
+.TP 5
+\-v \fIuri\-dispositivo\fR
+.br
+Establece el atributo de \fIuri\-dispositivo\fR de la cola de impresión. Si \fIuri\-dispositivo\fR es un nombre de archivo, automáticamente es convertido a la forma \fBfile:/nombre/archivo\fR.
+.TP 5
+\-D \fIinfo\fR
+.br
+Proporciona una descripción de la impresora.
+.TP 5
+\-E
+.br
+Activa la impresora y hace que acepte trabajos; es lo mismo que ejecutar los programas \fIaccept(8)\fR y \fIenable(8)\fR en la impresora.
+.TP 5
+\-L \fIubicación\fR
+.br
+Proporciona una ubicación de la impresora.
+.TP 5
+\-P \fIarchivo\-ppd\fR
+.br
+Especifica un archivo de descripción de impresora PostScript (PPD) para usar con la impresora. Si se especifica este archivo, esta opción anula la opción \fI\-i\fR (guión de interfaz).
+.SH "COMPATIBILIDAD"
+A diferencia del sistema de impresión System V, CUPS permite que los nombres de impresoras contengan cualquier carácter imprimible excepto ESPACIO y TAB. También, en los nombres de clases e impresoras \fIno\fR hay distinción entre mayúsculas y minúsculas. Finalmente, la versión de CUPS de \fIlpadmin\fR puede pedir al usuario una palabra de acceso dependiendo de la configuración del sistema de impresión. Esto es diferente de la versión System V que requiere que sea el usuario root el que ejecute este comando.
+.SH "LIMITACIONES"
+La versión de CUPS de \fIlpadmin\fR no soporta todas las opciones de configuración del sistema de impresión System V o Solaris.
+.SH "VÉASE TAMBIÉN"
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpstat(1), reject(8),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpadmin.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
+
diff --git a/man/es/lpc.man b/man/es/lpc.man
new file mode 100644
index 000000000..5bb9847cc
--- /dev/null
+++ b/man/es/lpc.man
@@ -0,0 +1,75 @@
+.\"
+.\" "$Id: lpc.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpc man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpc" "8" "Common UNIX Printing System" "22 de Septiembre de 1999" "Easy Software Products"
+.SH "NOMBRE"
+lpc \- programa de control de impresora
+.SH "SINOPSIS"
+.B lpc
+[
+.I comando
+[
+.I parámetro(s)
+] ]
+.SH "DESCRIPCIÓN"
+\fIlpc\fR proporciona un control limitado sobre colas de impresoras y clases proporcionadas por CUPS. También puede ser usado para conocer el estado de las colas.
+.LP
+Si no se especifica ningún comando en la línea de comandos, \fRlpc\fR visualizará un indicador y aceptará comandos de la entrada estandar.
+.SH "COMANDOS"
+El programa \fIlpc\fR acepta un subconjunto de los comandos aceptados por el programa del mismo nombre de Berkeley:
+.TP 5
+\fIexit
+.br
+Sale del intérprete de comandos.
+.TP 5
+help \fI[comando]\fR
+.br
+Visualiza un breve mensaje de ayuda.
+.TP 5
+quit
+.br
+Sale del intérprete de comandos.
+.TP 5
+status \fI[cola]\fR
+.br
+Visualiza el estado de una o más colas de clases o impresoras.
+.TP 5
+? \fI[comando]\fR
+.br
+Visualiza un breve mensaje de ayuda.
+.SH "LIMITACIONES"
+Ya que \fIlpc\fR está hecho para el sistema de impresión de Berkeley, no se puede usar \fIlpc\fR para configurar las colas de clases o impresoras proporcionadas por CUPS. Para ello debe usar el comando \fIlpadmin(8)\fR u otro cliente compatible CUPS con esa funcionalidad.
+.SH "COMPATIBILIDAD"
+La versión de CUPS de \fIlpc\fR no implementa todos los comandos estandar de Berkeley.
+.SH "VÉASE TAMBIÉN"
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpr(1), lprm(1),
+lpstat(1), reject(8),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpc.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpinfo.man b/man/es/lpinfo.man
new file mode 100644
index 000000000..f8173dc0b
--- /dev/null
+++ b/man/es/lpinfo.man
@@ -0,0 +1,61 @@
+.\"
+.\" "$Id: lpinfo.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpinfo man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpinfo" "8" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lpinfo \- muestra los dispositivos o controladores disponibles
+.SH "SINOPSIS"
+.B lpinfo
+[ \-E ] [ \-l ] [ \-m ] [ \-v ]
+.SH "DESCRIPCIÓN"
+\fBlpinfo\fR lista los dispositivos disponibles o los controladores conocidos por el servidor CUPS. Para conseguir algo, se debe especificar una de las opciones \fI\-m\fR o \fI\-v\fR:
+.TP 5
+\-E
+.br
+Hace que se use encriptación en la conexión con el servidor.
+.TP 5
+\-l
+.br
+Muestra un listado "amplio" de dispositivos o controladores.
+.TP 5
+\-m
+.br
+Muestra los controladores de impresoras disponibles en el sistema.
+.TP 5
+\-v
+.br
+Muestra los dispositivos de impresoras disponibles en el sistema.
+.SH "COMPATIBILIDAD"
+El comando \fBlpinfo\fR es específico de CUPS.
+.SH "VÉASE TAMBIÉN"
+lpadmin(8),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpinfo.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpmove.man b/man/es/lpmove.man
new file mode 100644
index 000000000..d9641396b
--- /dev/null
+++ b/man/es/lpmove.man
@@ -0,0 +1,54 @@
+.\"
+.\" "$Id: lpmove.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpmove man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpmove" "8" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lpmove \- mueve un trabajo a un nuevo destino
+.SH "SINOPSIS"
+.B lpmove
+[ \-E ]
+.I trabajo destino
+.SH "DESCRIPCIÓN"
+\fBlpmove\fR mueve el \fItrabajo\fR especificado a \fIdestino\fR. \fItrabajo\fR puede ser el número ID del trabajo o el destino antiguo y el número ID del trabajo:
+.br
+.nf
+
+ lpmove 123 impresora_nueva
+ lpmove impresora_antigua\-123 impresora_nueva
+.fi
+.LP
+La opción \fI\-E\fR hace que se use encriptación en la conexión con el servidor.
+.SH "COMPATIBILIDAD"
+La versión de System V de este comando también permite mover todos los trabajos de una cola a otra. CUPS no soporta actualmente esta funcionalidad.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpmove.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpoptions.man b/man/es/lpoptions.man
new file mode 100644
index 000000000..062906b0c
--- /dev/null
+++ b/man/es/lpoptions.man
@@ -0,0 +1,119 @@
+.\"
+.\" "$Id: lpoptions.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpoptions man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpoptions" "1" "Common UNIX Printing System" "21 de Octubre de 2002" "Easy Software Products"
+.SH "NOMBRE"
+lpoptions \- Visualiza o establece las opciones de las impresoras y los valores predeterminados
+.SH "SINOPSIS"
+.B lpoptions
+[ \-h
+.I servidor
+] \-d
+.I dest[/copia]
+[ \-o
+.I opción=valor
+] ... [ \-o
+.I opción=valor
+.br
+.B lpoptions
+[ \-h
+.I servidor
+] [ \-E ] [ \-p
+.I dest[/copia]
+] \-l
+.br
+.B lpoptions
+[ \-h
+.I servidor
+] [ \-E ] [ \-o
+.I opción=valor
+] ... [ \-o
+.I opción=valor
+] [ \-p
+.I dest[/copia]
+] \-r
+.I opción
+.br
+.B lpoptions
+[ \-h
+.I servidor
+] [ \-E ] \-x
+.I dest[/copia]
+.SH "DESCRIPCIÓN"
+\fBlpoptions\fR visualiza o establece las opciones de las impresoras y los valores predeterminados.
+\fBlpoptions\fR muestra las opciones predeterminadas cuando se ejecuta sin argumentos. Otras opciones:
+.TP 5
+\-E
+.br
+Hace que se use encriptación en la conexión con el servidor CUPS.
+.TP 5
+\-d \fIdest[/copia]\fR
+.br
+Establece que \fIdest\fR sea la impresora predeterminada. Si se pone \fIcopia\fR, entonces se usa esa copia en particular. Esta opción tiene preferencia sobre la impresora predeterminada del sistema para el usuario actual.
+.TP 5
+\-h \fIservidor\fR
+.br
+Especifica el servidor CUPS con el que se va a comunicar.
+.TP 5
+\-l
+.br
+Lista las opciones especificas de la impresora y sus valores actuales.
+.TP 5
+\-o \fIopción=valor\fR
+.br
+Especifica una nueva opción para el destino especificado.
+.TP 5
+\-p \fIdest[/copia]\fR
+.br
+Establece el destino y la copia, si se especifica, para cualquiera de las opciones que siguen. Si la copia especificada no existe, se crea.
+.TP 5
+\-r \fIopción\fR
+.br
+Elimina la opción del destino especificado.
+.TP 5
+\-x \fIdest[/copia]\fR
+.br
+Elimina la opción del destino especificado y de la copia, si se especifica. Si la copia especificada no existe, no hace nada.
+.LP
+Si no se especifican opciones usando la opción \fI\-o\fR, se listan en la salida estandar las opciones actuales de la impresora especificada.
+.LP
+Las opciones establecidas con el comando \fBlpoptions\fR son usadas por los comandos \fBlp(1)\fR y \fBlpr(1)\fR cuando se realiza la impresión de trabajos.
+.SH "OPCIONES DE LA CUENTA ROOT"
+Cuando es ejecutado por el usuario root, \fBlpoptions\fR lee y establece las opciones predeterminadas y copias para \fItodos los usuarios\fR en el archivo /etc/cups/lpoptions.
+.SH "COMPATIBILIDAD"
+El comando \fBlpoptions\fR es específico de CUPS.
+.SH "ARCHIVOS"
+~/.lpoptions \- valores predeterminados y copias creadas por usuarios que no sean root.
+.br
+/etc/cups/lpoptions \- valores predeterminados para todo el sistema y copias creadas por el usuario root.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpoptions.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lppasswd.man b/man/es/lppasswd.man
new file mode 100644
index 000000000..bfc0db919
--- /dev/null
+++ b/man/es/lppasswd.man
@@ -0,0 +1,52 @@
+.\"
+.\" "$Id: lppasswd.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lppasswd" "1" "Common UNIX Printing System" "7 de Junio de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lppasswd \- añade, cambia, o borra las palabras de acceso
+.SH "SINOPSIS"
+.B lppasswd
+[ \-a ] [ \-g
+.I nombre_grupo
+] [ \-x ] [
+.I nombre_usuario
+]
+.SH "DESCRIPCIÓN"
+\fIlppasswd\fR añade, cambia, o borra palabras de acceso en el archivo de palabras de acceso de CUPS \fIpasswd.md5\fR. Cuando es ejecutado por un usuario normal, \fIlppasswd\fR pedirá la palabra de acceso antigua y la nueva. Cuando es ejecutado por el super\-usuario, \fIlppasswd\fR puede añadir nuevas cuentas (\fI\-a nombre_usuario\fR), cambiar cuentas existentes (\fInombre_usuario\fR), o borrar cuentas (\fI\-x nombre_usuario\fR) en el archivo de palabras de acceso. Los nombre de usuario no tienen por qué coincidir con los nombres de usuario locales de UNIX, pero con los programas clientes de CUPS (\fIlp(1)\fR, \fIlpr(1)\fR, etc.) sólo funcionan nombres de usuario de UNIX.
+.LP
+La opción \fI\-g\fR especifica otro grupo diferente del grupo de sistema \- "sys",
+"system", o "root", dependiendo del sistema operativo.
+.SH "PROBLEMAS DE SEGURIDAD"
+El comando \fIlppasswd\fR se instala con "setuid" a root. Aunque cada intento se hace para asegurarlo contra cualquier usuario sin privilegios que quiera conseguir privilegios de super\-usuario, administradores de sistema paranoicos pueden querer deshabilitar o cambiar el propietario del programa a una cuenta sin privilegios.
+.SH "VÉASE TAMBIÉN"
+lp(1), lpr(1),
+Manual de administrador de CUPS,
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lppasswd.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpq.man b/man/es/lpq.man
new file mode 100644
index 000000000..8fbb39c69
--- /dev/null
+++ b/man/es/lpq.man
@@ -0,0 +1,55 @@
+.\"
+.\" "$Id: lpq.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpq man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpq" "1" "Common UNIX Printing System" "13 de Febrero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lpq \- muestra el estado de la cola de impresión
+.SH "SINOPSIS"
+.B lpq
+[ \-E ] [ \-P
+.I dest
+] [ \-a ] [ \-l ] [
+.I +intervalo
+]
+.SH "DESCRIPCIÓN"
+\fIlpq\fR muestra el estado actual de la cola de impresión de la impresora especificada. Se muestran los trabajos en cola en el destino predeterminado si no se especifica ni impresora ni clase de impresora en la línea de comandos.
+.LP
+La opción \fIintervalo\fR permite listar continuamente los trabajos en la cola hasta que ésta esté vacía; este listado se muestra una vez cada \fIintervalo\fR segundos.
+.LP
+La opción \fI\-E\fR hace que se use encriptación en la conexión con el servidor.
+.LP
+La opción \fI\-a\fR lista los trabajos de todas las impresoras.
+.LP
+La opción \fI\-l\fR hace que se use un formato de listado más detallado.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1), lpr(1), lprm(1), lpstat(1)
+.br
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpq.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpr.man b/man/es/lpr.man
new file mode 100644
index 000000000..a16e25052
--- /dev/null
+++ b/man/es/lpr.man
@@ -0,0 +1,96 @@
+.\"
+.\" "$Id: lpr.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpr man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpr" "1" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lpr \- imprime archivos
+.SH "SINOPSIS"
+.B lpr
+[ \-E ] [ \-P
+.I destino
+] [ \-#
+.I num\-copias
+[ \-l ] [ \-o
+.I opción
+] [ \-p] [ \-r ] [ \-C/J/T
+.I título
+] [
+.I archivos(s)
+]
+.SH "DESCRIPCIÓN"
+\fBlpr\fR realiza la impresión de archivos. Los archivos especificados en la línea de comandos se envían a la impresora especificada (o a la predeterminada si no se ha especificado destino). Si no se especifican archivos en la línea de comandos, entonces \fBlpr\fR lee el archivo a imprimir desde la entrada estandar.
+.SH "OPCIONES"
+Estas son las opciones reconocidas por \fBlpr\fR:
+.TP 5
+\-E
+.br
+Hace que se use encriptación en la conexión con el servidor.
+.TP 5
+\-P \fIdestino\fR
+.br
+Imprime archivos a la impresora especificada.
+.TP 5
+\-# \fIcopias\fR
+.br
+Establece el número de copias a imprimir de 1 a 100.
+.TP 5
+\-C \fInombre\fR
+.br
+Establece el nombre del trabajo.
+.TP 5
+\-J \fInombre\fR
+.br
+Establece el nombre del trabajo.
+.TP 5
+\-T \fInombre\fR
+.br
+Establece el nombre del trabajo.
+.TP 5
+\-l
+.br
+Especifica que el archivo a imprimir ya tiene el formato adecuado para el destino y debe ser enviado sin aplicar ningún filtro. Esta opción es equivalente a "\-oraw".
+.TP 5
+\-o \fIopción\fR
+.br
+Establece una opción del trabajo.
+.TP 5
+\-p
+.br
+Especifica que el archivo a imprimir debe ser formateado con una cabecera que contenga la fecha, la hora, el nombre del trabajo, y el número de página. Esta opción es equivalente a "\-oprettyprint" y sólo es útil cuando se imprimen archivos de texto.
+.TP 5
+\-r
+.br
+Especifica que los archivos a imprimir deben ser borrados tras ser impresos.
+.SH "COMPATIBILIDAD"
+Las opciones "c", "d", "f", "g", "i", "m", "n", "t", "v", y "w" no funcionan en CUPS y producirán un mensaje de aviso si se usan.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1), lpstat(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpr.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lprm.man b/man/es/lprm.man
new file mode 100644
index 000000000..84ac98d0e
--- /dev/null
+++ b/man/es/lprm.man
@@ -0,0 +1,52 @@
+.\"
+.\" "$Id: lprm.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lprm man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lprm" "1" "Common UNIX Printing System" "23 de Enero de 2001" "Easy Software Products"
+.SH "NOMBRE"
+lprm \- cancela trabajos de impresión
+.SH "SINOPSIS"
+.B lprm
+[ \-E ] [ \- ] [ \-P
+.I destino
+] [
+.I ID trabajo(s)
+]
+.SH "DESCRIPCIÓN"
+\fBlprm\fR cancela trabajos de impresión que han sido puestos en cola para ser impresos. La opción \fI\-P\fR especifica la impresora o clase destino.
+.LP
+Si no se especifican argumentos, se cancela el trabajo actual en el destino predeterminado. Puede especificar uno o más número ID de trabajos para que sean cancelados, o usar la opción \fI\-\fR para cancelar todos los trabajos.
+.LP
+La opción \fI\-E\fR hace que se use encriptación en la conexión con el servidor.
+.SH "COMPATIBILIDAD"
+La versión de CUPS de \fIlprm\fR es compatible con el comando estandar \fIlprm\fR de Berkeley.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1), lpstat(1), lpr(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lprm.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/lpstat.man b/man/es/lpstat.man
new file mode 100644
index 000000000..852d0a02a
--- /dev/null
+++ b/man/es/lpstat.man
@@ -0,0 +1,126 @@
+.\"
+.\" "$Id: lpstat.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" lpstat man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "lpstat" "1" "Common UNIX Printing System" "3 de Enero de 2003" "Easy Software Products"
+.SH "NOMBRE"
+lpstat \- imprime la información de estado de cups
+.SH "SINOPSIS"
+.B lpstat
+[ \-E ] [ \-h
+.I servidor
+] [ \-l ] [ \-W
+.I que\-trabajos
+] [ \-a [
+.I destino(s)
+] ] [ \-c [
+.I clase(s)
+] [ \-d ] [ \-o [
+.I destino(s)
+] ] [ \-p [
+.I impresora(s)
+] ] [ \-r ] [ \-R ] [ \-s ] [ \-t ] [ \-u [
+.I usuario(s)
+] ] [ \-v [
+.I impresora(s)
+] ]
+.SH "DESCRIPCIÓN"
+\fBlpstat\fR visualiza la información de estado sobre las clases, trabajos, e impresoras actuales. Cuando es ejecutado sin argumentos, \fBlpstat\fR listará los trabajos puestos en cola por el usuario. Otras opciones son:
+.TP 5
+\-E
+.br
+Hace que se use encriptación en la conexión con el servidor.
+.TP 5
+\-a [\fIimpresora(s)\fR]
+.br
+Muestra el estado de aceptación de las colas de las impresoras. Si no se especifican impresoras, se listan todas.
+.TP 5
+\-c [\fIclase(s)\fR]
+.br
+Muestra las clases de impresoras y las impresoras que pertenecen a ella. Si no se especifican clases, se listan todas.
+.TP 5
+\-d
+.br
+Muestra el destino predeterminado actual.
+.TP 5
+\-h \fIservidor\fR
+.br
+Especifica el servidor CUPS con el que comunicar.
+.TP 5
+\-l
+.br
+Muestra un listado detallado de impresoras, clases o trabajos.
+.TP 5
+\-o [\fIdestino(s)\fR]
+.br
+Muestra la cola de trabajos en los destinos especificados. Si no se especifica destino, se muestran todos los trabajos.
+.TP 5
+\-p [\fIimpresora(s)\fR]
+.br
+Muestra las impresoras y si están activas para imprimir. Si no se especifican impresoras, se listan todas.
+.TP 5
+\-r
+.br
+Muestra si el servidor CUPS está en funcionamiento.
+.TP 5
+\-R
+.br
+Muestra la clasificación de los trabajos de impresión.
+.TP 5
+\-s
+.br
+Muestra un resúmen de estado, incluyendo el destino predeterminado, una lista de clases y las impresoras miembros que las forman, y una lista de impresoras y sus dispositivos asociados. Esto es equivalente a usar las opciones "\-d", "\-c",
+y "\-p".
+.TP 5
+\-t
+.br
+Muestra toda la información de estado. Es equivalente a usar las opciones "\-r",
+"\-d", "\-c", "\-d", "\-v", "\-a", "\-p", y "\-o".
+.TP 5
+\-u [\fIusuario(s)\fR]
+.br
+Muestra una lista de trabajos de impresión puestos en cola por los usuarios especificados. Si no se especifican usuarios, lista los trabajos puestos en cola por el usuario actual.
+.TP 5
+\-v [\fIimpresora(s)\fR]
+.br
+Muestra las impresoras y los dispositivos a los que están conectadas. Si no se especifican impresoras, se listan todas.
+.TP 5
+\-W [\fIque\-trabajos\fR]
+.br
+Especifica qué trabajos mostrar, \fIcompleted\fR (completados) o \fInot\-completed\fR (no completados) (predeterminado). Esta opción \fBdebe\fR aparecer antes de la opción \fI\-o\fR y/o de cualquier nombre de impresora, porque si no el valor predeterminado (not\-completed) será usado en la petición al planificador de tareas.
+.SH "COMPATIBILIDAD"
+A diferencia del sistema de impresión System V, CUPS permite que los nombres de impresoras contengan cualquier carácter imprimible excepto ESPACIO y TAB. También, en los nombres de clases e impresoras \fIno\fR hay distinción entre mayúsculas y minúsculas.
+.LP
+Las opciones "\-h" y "\-W" son exclusivas de CUPS.
+.LP
+Las opciones "\-f", "\-P", y "\-S" de Solaris se ignoran silenciosamente.
+.SH "VÉASE TAMBIÉN"
+cancel(1), lp(1),
+Manual de usuario de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: lpstat.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/mime.convs.man b/man/es/mime.convs.man
new file mode 100644
index 000000000..e9fa3faf0
--- /dev/null
+++ b/man/es/mime.convs.man
@@ -0,0 +1,49 @@
+.\"
+.\" "$Id: mime.convs.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" mime.convs man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "mime.convs" "5" "Common UNIX Printing System" "22 de Junio de 2000" "Easy Software Products"
+.SH "NOMBRE"
+mime.convs \- archivo de conversión de tipos mime para cups
+.SH "DESCRIPCIÓN"
+El archivo \fImime.convs\fR define los filtros disponibles para convertir archivos de un formato a otro. Los filtros estandar funcionan con archivos de texto, PDF, PostScript, HP\-GL/2, y muchos tipos de archivos de imágenes.
+.LP
+Se pueden añadir filtros adicionales al archivo \fImime.convs\fR o a otros archivos en el directorio de configuración (\fB/etc/cups\fR) con la extensión ".convs".
+.LP
+Cada línea del archivo \fImime.convs\fR puede ser un comentario, una línea en blanco o una línea de filtro. Las líneas de comentario comienzan con el carácter #. Las líneas de filtro especifican los tipos MIME de la fuente y del destino junto con un coste relativo asociado con el filtro, y el filtro a ejecutar:
+.br
+.nf
+
+super/tipo super/tipo coste filtro
+application/postscript application/vnd.cups\-raster 50 pstoraster
+.fi
+.SH "VÉASE TAMBIÉN"
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), printers.conf(5),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: mime.convs.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/mime.types.man b/man/es/mime.types.man
new file mode 100644
index 000000000..bdbab32e5
--- /dev/null
+++ b/man/es/mime.types.man
@@ -0,0 +1,93 @@
+.\"
+.\" "$Id: mime.types.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" mime.types man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "mime.types" "5" "Common UNIX Printing System" "22 de Junio de 2000" "Easy Software Products"
+.SH "NOMBRE"
+mime.types \- archivo de descripción de tipos mime para cups
+.SH "DESCRIPCIÓN"
+El archivo \fImime.types\fR define los tipos de archivo reconocidos.
+.LP
+Se pueden añadir tipos de archivo adicionales a \fImime.types\fR o a archivos adicionales en el directorio de configuración \fB/etc/cups\fR con la extensión ".types".
+.LP
+Cada línea en el archivo \fImime.types\fR puede ser un comentario, una línea en blanco o una línea con una regla. Las líneas de comentario comienzan con el carácter #. Las líneas con una regla comienzan con el nombre del tipo MIME y opcionalmente sigue una serie de reglas de reconocimiento de archivos que se usan para identificar automáticamente los archivos de impresión y de páginas web:
+.br
+.nf
+
+ super/tipo regla [ ... reglaN]
+.fi
+Las reglas pueden ser agrupadas usando paréntesis, unidas usando "+" para hacer un AND (Y) lógico y "," o espacio en blanco para un OR (O) lógico, y negadas usando "!".
+.SH "REGLAS"
+Las reglas tienen dos formas \- una extensión de archivo por si misma y funciones con valores de prueba entre paréntesis. Están disponibles las siguientes funciones:
+.TP 5
+match("patrón")
+.br
+El patrón coincide con el nombre de archivo
+.TP 5
+ascii(desplazamiento,longitud)
+.br
+Verdadero si los bytes son caracteres imprimibles ASCII (CR, NL, TAB, BS, 32\-126)
+.TP 5
+printable(desplazamiento,longitud)
+.br
+Verdadero si los bytes son caracteres imprimibles de 8\-bits (CR, NL, TAB, BS, 32\-126, 128\-254)
+.TP 5
+string(desplazamiento,"cadena")
+.br
+Verdadero si los bytes son identicos a cadena
+.TP 5
+istring(desplazamiento,"cadena")
+.br
+Verdadero si una comparación, sin distinción de mayúsculas y minúsculas, de los bytes es idéntica
+.TP 5
+char(desplazamiento,valor)
+.br
+Verdadero si byte es idéntico
+.TP 5
+short(desplazamiento,valor)
+.br
+Verdadero si el número entero de 16\-bits es idéntico
+.TP 5
+int(desplazamiento,valor)
+.br
+Verdadero si el número entero de 32\-bits es idéntico
+.TP 5
+locale("cadena")
+.br
+Verdadero si la ubicacion actual coincide con cadena
+.TP 5
+contains(desplazamiento,rango,"cadena")
+.br
+Verdadero si el rango contiene la cadena
+.SH "CADENAS DE CARACTERES"
+Las constantes de cadenas de caracteres que contengan espacios en blanco, pueden ser especificadas entre comillas ("") y paréntesis de ángulo (<>) para cadenas hexadecimales.
+.SH "VÉASE TAMBIÉN"
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), printers.conf(5),
+Manual de administrador de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: mime.types.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/es/printers.conf.man b/man/es/printers.conf.man
new file mode 100644
index 000000000..58b09cb6b
--- /dev/null
+++ b/man/es/printers.conf.man
@@ -0,0 +1,71 @@
+.\"
+.\" "$Id: printers.conf.man 4444 2004-10-20 18:00:54Z mike $"
+.\"
+.\" printers.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH "printers.conf" "5" "Common UNIX Printing System" "22 de Junio de 2000" "Easy Software Products"
+.SH "NOMBRE"
+printers.conf \- archivo de configuración de impresoras de cups
+.SH "DESCRIPCIÓN"
+El archivo \fIprinters.conf\fR define las impresoras locales disponibles. Normalmente está en el directorio \fI/etc/cups\fR y es generado automáticamente por el programa \fIcupsd(8)\fR cuando se añaden o borran impresoras.
+.LP
+Cada línea del archivo puede ser una directiva de configuración, una línea en blanco o un comentario. Las líneas de comentario comienzan con el carácter #.
+.SH "DIRECTIVAS"
+.TP 5
+Accepting
+.br
+Especifica si la impresora acepta o no nuevos trabajos.
+.TP 5
+Info
+.br
+Especifica un texto legible describiendo la impresora.
+.TP 5
+Location
+.br
+Especifica un texto legible describiendo la ubicación de la impresora.
+.TP 5
+DeviceURI
+.br
+Especifica la URI de dispositivo de una impresora.
+.TP 5
+<Nombre impresora> ... </Printer>
+.br
+Define una impresora específica.
+.TP 5
+State
+.br
+Especifica el estado inicial de la impresora: Idle (inactiva) o Stopped (parada)
+.TP 5
+StateMessage
+.br
+Especifica el mensaje asociado con el estado.
+.SH "VÉASE TAMBIÉN"
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5),
+Manual de administrador de CUPS,
+Descripción del diseño de la interface de CUPS,
+http://localhost:631/documentation.html
+.SH "DERECHOS DE COPIA"
+Los derechos de copia 1993\-2004 son de Easy Software Products. Todos los derechos reservados.
+.SH "TRADUCCIÓN"
+Juan Pablo González Riopedre <riopedre@tiscali.es>
+.\"
+.\" End of "$Id: printers.conf.man 4444 2004-10-20 18:00:54Z mike $".
+.\"
diff --git a/man/filter.man b/man/filter.man
new file mode 100644
index 000000000..545a248d0
--- /dev/null
+++ b/man/filter.man
@@ -0,0 +1,123 @@
+.\"
+.\" "$Id: filter.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" filter man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH filter 1 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NAME
+filter \- cups file conversion filter interfaces
+.SH SYNOPSIS
+.B filter
+job user title num-copies options [
+.I filename
+]
+.SH DESCRIPTION
+The CUPS filter interface provides a standard method for adding support for
+new document types to CUPS. Each filter is capable of converting from one
+or more input formats to another format that can either be printed directly
+or piped into another filter to get it to a printable format.
+.LP
+Filters must be capable of reading from a filename on the command-line
+or from the standard input, copying the standard input to a temporary
+file as required by the file format. All output must be sent to the
+standard output.
+.LP
+The command name (argv[0]) is set to the name of the destination printer.
+.SH ENVIRONMENT VARIABLES
+The following environment variables are defined by the CUPS server when
+executing each filter:
+.TP 5
+CHARSET
+.br
+The default text character set (typically us-ascii or iso-8859-1).
+.TP 5
+CLASS
+.br
+When a job is submitted to a printer class, contains the name of
+the destination printer class. Otherwise this environment
+variable will not be set.
+.TP 5
+CONTENT_TYPE
+.br
+The MIME type associated with the file (e.g. application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+The directory where data files can be found.
+.TP 5
+CUPS_SERVERROOT
+.br
+The root directory of the server.
+.TP 5
+DEVICE_URI
+.br
+The device-uri associated with the printer.
+.TP 5
+LANG
+.br
+The default language locale (typically C or en).
+.TP 5
+PATH
+.br
+The standard execution path for external programs that may be run by the filter.
+.TP 5
+PPD
+.br
+The full pathname of the PostScript Printer Description (PPD) file for
+this printer.
+.TP 5
+PRINTER
+.br
+The name of the printer; this is provided for shell scripts which may not be
+able to get the passed argv[0] string.
+.TP 5
+RIP_CACHE
+.br
+The recommended amount of memory to use for Raster Image Processors (RIPs).
+.TP 5
+SOFTWARE
+.br
+The name and version number of the server (typically CUPS/1.1).
+.TP 5
+TZ
+.br
+The timezone of the server.
+.TP 5
+USER
+.br
+The user executing the filter, typically lp; consult the cupsd.conf file for
+the current setting.
+.SH COMPATIBILITY
+While the filter interface is compatible with System V interface
+scripts, it will only work with the System V interface script as the
+only filter. Typically the interface script will be provided via the
+\fBlpadmin(8)\fR command using the \fI-i\fR option.
+.SH SEE ALSO
+backend(1), cupsd(8),
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: filter.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/fr/.cvsignore b/man/fr/.cvsignore
new file mode 100644
index 000000000..5b12a6fc7
--- /dev/null
+++ b/man/fr/.cvsignore
@@ -0,0 +1,7 @@
+*.0
+*.1
+*.1m
+*.3
+*.5
+*.8
+*.z
diff --git a/man/fr/Makefile b/man/fr/Makefile
new file mode 100644
index 000000000..1c4a2d346
--- /dev/null
+++ b/man/fr/Makefile
@@ -0,0 +1,103 @@
+#
+# "$Id$"
+#
+# French man page makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+include ../Makefile.common
+
+
+#
+# This is the French manpage makefile...
+#
+
+LANGUAGE = fr
+
+
+#
+# Make everything...
+#
+
+all: $(CAT1) $(CAT5) $(CAT8)
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+ $(RM) $(CAT1) $(CAT5) $(CAT8)
+
+
+#
+# Dummy depend target...
+#
+
+depend:
+
+
+#
+# Install files...
+#
+
+install: all
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/man1
+ for file in $(MAN1); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/man1/`basename $$file man`1; \
+ done
+ $(RM) $(MANDIR)/$(LANGUAGE)/man1/cancel.1
+ $(LN) lp.1 $(MANDIR)/$(LANGUAGE)/man1/cancel.1
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/man5
+ for file in $(MAN5); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/man5/`basename $$file man`5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)
+ for file in $(MAN8); do \
+ $(INSTALL_MAN) $$file $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/`basename $$file man`$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(LN) accept.$(MAN8EXT) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/reject.$(MAN8EXT)
+ $(RM) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(LN) enable.$(MAN8EXT) $(AMANDIR)/$(LANGUAGE)/man$(MAN8EXT)/disable.$(MAN8EXT)
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/cat1
+ for file in $(CAT1); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/cat1; \
+ done
+ $(RM) $(MANDIR)/$(LANGUAGE)/cat1/cancel.$(CAT1EXT)
+ $(LN) lp.$(CAT1EXT) $(MANDIR)/$(LANGUAGE)/cat1/cancel.$(CAT1EXT)
+ $(INSTALL_DIR) $(MANDIR)/$(LANGUAGE)/cat5
+ for file in $(CAT5); do \
+ $(INSTALL_MAN) $$file $(MANDIR)/$(LANGUAGE)/cat5; \
+ done
+ $(INSTALL_DIR) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)
+ for file in $(CAT8); do \
+ $(INSTALL_MAN) $$file $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT); \
+ done
+ $(RM) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(LN) accept.$(CAT8EXT) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/reject.$(CAT8EXT)
+ $(RM) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+ $(LN) enable.$(CAT8EXT) $(AMANDIR)/$(LANGUAGE)/cat$(MAN8EXT)/disable.$(CAT8EXT)
+
+
+#
+# End of "$Id$".
+#
diff --git a/man/fr/accept.man b/man/fr/accept.man
new file mode 100644
index 000000000..62e377827
--- /dev/null
+++ b/man/fr/accept.man
@@ -0,0 +1,63 @@
+.\"
+.\" "$Id: accept.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" accept/reject man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.7
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH accept 8 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+accept/reject \- Accepte/refuse les travaux d'impression envoyés à une destination
+.SH SYNOPSIS
+.B accept
+destination(s)
+.br
+.B reject
+[ -E ] [ -h
+.I serveur
+] [ -r
+.I raison
+]
+destination(s)
+.SH DESCRIPTION
+\fIaccept\fR envoie l'ordre au système d'impression d'accepter les
+travaux d'impression vers les destinations spécifiées.
+.LP
+\fIreject\fR envoie l'ordre au système d'impression de refuser les
+travaux d'impression vers les destinations spécifiées. L'option \fI-r\fR
+permet de spécifier la raison du rejet des travaux d'impression. Si cette
+raison n'est pas fournie, la raison par défaut est «\ Raison inconnue\ ».
+.LP
+L'option \fI-E\fR force le cryptage lors de la connexion au serveur.
+.SH COMPATIBILITÉ
+Les versions CUPS d'\fIaccept\fR et \fIreject\fR peuvent demander à
+l'utilisateur de s'identifier suivant la configuration du système d'impression,
+à la différence des versions System V, qui demandent le mot de passe root.
+.SH VOIR AUSSI
+cancel(1), disable(8), enable(8), lp(1), lpadmin(8), lpstat(1),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: accept.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/backend.man b/man/fr/backend.man
new file mode 100644
index 000000000..fbb378b82
--- /dev/null
+++ b/man/fr/backend.man
@@ -0,0 +1,118 @@
+.\"
+.\" "$Id: backend.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" backend man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.11
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH backend 1 "Common UNIX Printing System" "22 Juin 2000" "Easy Software Products"
+.SH NOM
+backend \- Programme de transmission de CUPS
+.SH SYNOPSIS
+.B backend
+travail utilisateur titre nb-copies options [
+.I fichier
+]
+.SH DESCRIPTION
+Les programmes de transmission de CUPS fournissent une méthode standard
+d'envoi des fichiers aux différentes interfaces physiques.
+.LP
+Ces programmes doivent être capable de lire un fichier de la ligne de
+commande ou via l'entrée standard, si besoin est en recopiant son contenu
+dans un fichier temporaire.
+.LP
+Le nom de la commande (argv[0]) est l'URI de l'imprimante.
+.SH VARIABLES D'ENVIRONNEMENT
+Les variables d'environnement suivantes sont définies par le serveur CUPS
+lors de l'exécution d'un programme de transmission\ :
+.TP 5
+CHARSET
+.br
+Le jeu de caractères par défaut (généralement us-ascii ou iso-8859-1).
+.TP 5
+CLASS
+.br
+Contient le nom de la classe lorsqu'un travail d'impression est envoyé à une classe d'imprimante. Cette variable n'est pas définie si le travail d'impression n'est pas envoyé à une classe.
+.TP 5
+CONTENT_TYPE
+.br
+Le type MIME associé au fichier (ex\ : application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+Le répertoire où se trouvent les données.
+.TP 5
+CUPS_SERVERROOT
+.br
+Le répertoire racine du serveur.
+.TP 5
+DEVICE_URI
+.br
+L'URI de l'imprimante, ceci pour les scripts shells qui ne sont pas
+toujours capables de récupérer l'argument argv[0].
+.TP 5
+LANG
+.br
+La langue (généralement C ou en).
+.TP 5
+PATH
+.br
+La liste des chemins où chercher les programmes pouvant être exécutés
+par le programme.
+.TP 5
+PPD
+.br
+Le chemin complet d'accès au fichier PPD (PostScript Printer Description)
+de l'imprimante.
+.TP 5
+PRINTER
+.br
+Le nom de l'imprimante.
+.TP 5
+RIP_CACHE
+.br
+La quantité de mémoire recommandée pour l'utilisation du RIP (Raster Image
+Processors).
+.TP 5
+SOFTWARE
+.br
+Le nom et le numéro de version du serveur (généralement CUPS/1.1).
+.TP 5
+TZ
+.br
+Le fuseau horaire du serveur.
+.TP 5
+USER
+.br
+L'utilisateur exécutant le programme (généralement root). Vous pouvez
+trouver cette information dans le fichier cupsd.conf.
+.SH VOIR AUSSI
+cupsd(8), filter(1)
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: backend.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/classes.conf.man b/man/fr/classes.conf.man
new file mode 100644
index 000000000..35db32a0b
--- /dev/null
+++ b/man/fr/classes.conf.man
@@ -0,0 +1,75 @@
+.\"
+.\" "$Id: classes.conf.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" classes.conf man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH classes.conf 5 "Common UNIX Printing System" "22 Juin 2000" "Easy Software Products"
+.SH NOM
+classes.conf \- Fichier de configuration des classes de CUPS
+.SH DESCRIPTION
+Le fichier \fIclasses.conf\fR définit les classes d'imprimantes disponibles. Il est
+habituellement situé dans le répertoire \fI/etc/cups\fR et est généré automatiquement
+par le programme \fIcupsd(8)\fR lorsque des classes d'imprimantes sont créées ou
+supprimées.
+.LP
+Chaque ligne de ce fichier est une directive de configuration, une ligne vide ou
+un commentaire. Les commentaires commencent par le symbole #.
+.SH DIRECTIVES
+.TP 5
+<Class name> ... </Class>
+.br
+Définit une classe d'imprimantes.
+.TP 5
+Accepting
+.br
+Définit si la classe d'imprimante accepte les travaux d'impression ou non.
+.TP 5
+Info
+.br
+Définit une information à destination des utilisateurs pour la classe d'imprimantes.
+.TP 5
+Location
+.br
+Définit la localisation physique de la classe d'imprimantes à destination des utilisateurs.
+.TP 5
+Printer
+.br
+Associe une imprimante à une classe.
+.TP 5
+State
+.br
+Définit l'état initial de la classe d'imprimante (Idle ou Stopped).
+.TP 5
+StateMessage
+.br
+Définit le message associé à l'état.
+.SH VOIR AUSSI
+cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: classes.conf.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/cups-config.man b/man/fr/cups-config.man
new file mode 100644
index 000000000..53208b5c8
--- /dev/null
+++ b/man/fr/cups-config.man
@@ -0,0 +1,97 @@
+.\"
+.\" "$Id: cups-config.man 4182 2004-05-27 15:37:35Z mike $"
+.\"
+.\" cups-config man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.3
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-config 1 "Common UNIX Printing System" "27 May 2004" "Easy Software Products"
+.SH NOM
+cups-config \- Récupère les informations concernant les API, la compilation, les répertoires et les liens de CUPS
+.SH SYNOPSIS
+.B cups-config
+--api-version
+.br
+.B cups-config
+--cflags
+.br
+.B cups-config
+--datadir
+.br
+.B cups-config
+--help
+.br
+.B cups-config
+--ldflags
+.br
+.B cups-config
+[
+.I --image
+] [
+.I --static
+] --libs
+.br
+.B cups-config
+--serverbin
+.br
+.B cups-config
+--serverroot
+.br
+.B cups-config
+--version
+.br
+.SH DESCRIPTION
+\fBcups-config\fR est le programme de visualisation de la configuration de CUPS. Il doit être
+utilisé par les développeurs pour déterminer les options du compilateur et du linkeur,
+ainsi que l'endroit où ont été installés les filtres,
+fichiers de configuration et pilotes.
+.LP
+La commande \fI--api-version\fR affiche la version de l'API (majeur.mineur).
+.LP
+La commande \fI--cflags\fR affiche les options indispensables de compilation.
+.LP
+La commande \fI--datadir\fR affiche le répertoire par défaut des données CUPS.
+.LP
+La commande \fI--help\fR affiche le message d'utilisation de ce programme.
+.LP
+La commande \fI--ldflags\fR affiche les options indispensables pour l'édition des liens.
+.LP
+La commande \fI--libs\fR affiche les bibliothèques nécessaires pour l'édition des liens.
+L'option \fI--image\fR ajoute à la liste les bibliothèque pour les images.
+L'option \fI--static\fR affiche les bibliothèques statiques au lieu des bibliothèques
+dynamiques.
+.LP
+La commande \fI--serverbin\fR affiche le répertoire par défaut où
+les programmes de filtres et backends CUPS sont stockés.
+.LP
+La commande \fI--serverroot\fR affiche le fichier de configuration par défaut de CUPS.
+.LP
+La commande \fI--version\fR affiche le numéro complet de version de CUPS
+(majeur.mineur.révision).
+.SH VOIR AUSSI
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cups-config.man 4182 2004-05-27 15:37:35Z mike $".
+.\"
diff --git a/man/fr/cups-lpd.man b/man/fr/cups-lpd.man
new file mode 100644
index 000000000..8ea9b2559
--- /dev/null
+++ b/man/fr/cups-lpd.man
@@ -0,0 +1,112 @@
+.\"
+.\" "$Id: cups-lpd.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" cups-lpd man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.10
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-lpd 8 "Common UNIX Printing System" "13 Février 2001" "Easy Software Products"
+.SH NOM
+cups-lpd \- Reçoit les travaux d'impression et renvoie le statut des imprimantes aux clients lpd
+.SH SYNOPSIS
+.B cups-lpd
+[ -o
+.I option=valeur
+]
+.SH DESCRIPTION
+\fBcups-lpd\fR est un mini serveur Line Printer Daemon («\ LPD\ ») qui
+gère les client génériques utilisant le protocole LPD.
+\fBcups-lpd\fR ne fonctionne pas comme un démon réseau solitaire, mais
+utilise le super-serveur \fBinetd(8)\fR. Ajoutez la ligne suivante au fichier
+\fBinetd.conf\fR pour activer le démon \fBcups-lpd\fR\ :
+.br
+.nf
+
+ printer stream tcp nowait lp /path/to/cups/daemon/cups-lpd cups-lpd
+.fi
+.LP
+Si vous utilisez le super-serveur \fIxinetd(8)\fR, ajoutez la ligne suivante au fichier
+\fBxinetd.conf\fR\ :
+.br
+.nf
+
+ service printer
+ {
+ socket_type = stream
+ protocol = tcp
+ wait = no
+ user = lp
+ server = /path/to/cups/daemon/cups-lpd
+ }
+.fi
+.LP
+/path/to/cups/daemon est habituellement /usr/lib/cups/daemon ou
+/usr/libexec/cups/daemon, suivant votre système d'exploitation. Vous
+pouvez trouver cette information dans le fichier cupsd.conf.
+.SH SÉCURITÉ
+\fBcups-lpd\fR n'applique pour le moment aucun des contrôles d'accès définis
+dans les fichiers \fIcupsd.conf(5)\fR, \fIhosts.allow(5)\fR ou
+\fIhosts.deny(5)\fR utilisés par les wrappers TCP. L'exécution de
+\fBcups-lpd\fR sur un serveur permet donc le lancement d'impressions depuis
+n'importe quel ordinateur de votre réseau, voire même de n'importe quel
+ordinateur sur Terre.
+.LP
+Bien que \fIxinetd\fR possède un contrôle d'accès intégré, il est recommandé
+d'utiliser le wrapper TCP fourni avec \fIinetd\fR pour limiter les accès aux
+ordinateurs pouvant lancer des impressions sur un serveur.
+.SH OPTIONS
+L'option \fI-o\fR ajoute des options à tous les travaux d'impression.
+Cette option est souvent utilisée pour désactiver le filtre «\ l\ » de manière
+à ce que les travaux passant par le réseau soient filtrés correctement.
+.br
+.nf
+
+ printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd \
+ -o document-format=application/octet-stream
+
+ server = /usr/lib/cups/daemon/cups-lpd
+ server_args = -o document-format=application/octet-stream
+.fi
+.LP
+Dans cet exemple, le format du document est réinitialisé à la valeur
+\fIapplication/octet-stream\fR, ce qui force l'auto-détection du type de
+fichier.
+.SH COMPATIBILITÉ
+\fBcups-lpd\fR ne se conforme pas à la RFC 1179 concernant l'utilisation
+des ports systèmes (1 à 1\|024), car l'utilisation de ces ports n'empêche pas
+un utilisateur d'envoyer un travail d'impression. Bien que ce comportement
+soit différent de celui des implémentations LPD Berkeley, il ne devrait pas
+affecter le déroulement correct des impressions.
+.LP
+Le format de sortie des demandes d'état se conforme à la RFC 2569, Mapping
+between LPD and IPP Protocols. Comme bon nombre d'implémentations LPD ne suivent
+pas cette définition, la récupération d'état par un client LPD peut être
+erronée.
+.SH VOIR AUSSI
+inetd(8), xinetd(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cups-lpd.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/cups-polld.man b/man/fr/cups-polld.man
new file mode 100644
index 000000000..8109377e4
--- /dev/null
+++ b/man/fr/cups-polld.man
@@ -0,0 +1,49 @@
+.\"
+.\" "$Id: cups-polld.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" cups-polld man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.5
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cups-polld 8 "Common UNIX Printing System" "10 Mai 2000" "Easy Software Products"
+.SH NOM
+cups-polld \- Démon d'interrogation des imprimantes CUPS
+.SH SYNOPSIS
+.B cups-polld
+.I adresse port-ipp intervalle port-de-navigation
+.SH DESCRIPTION
+\fBcups-polld\fR interroge des serveurs distants afin d'obtenir la
+liste des imprimantes et classes d'imprimantes disponibles toutes
+les \fIintervalle\fR secondes. Les informations sont alors renvoyées
+vers l'interface locale (127.0.0.1) pour être récupérées par \fBcupsd(8)\fR.
+.PP
+Ce programme est démarré automatiquement par \fBcupsd\fR pour chaque
+directive «\ BrowsePoll\ » trouvée dans le fichier \fBcupsd.conf\fR.
+.SH VOIR AUSSI
+cupsd.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cups-polld.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/cupsaddsmb.man b/man/fr/cupsaddsmb.man
new file mode 100644
index 000000000..79b4e1f28
--- /dev/null
+++ b/man/fr/cupsaddsmb.man
@@ -0,0 +1,151 @@
+.\"
+.\" "$Id: cupsaddsmb.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" cupsaddsmb man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsaddsmb 8 "Common UNIX Printing System" "27 septembre 2002" "Easy Software Products"
+.SH NOM
+cupsaddsmb \- Exportation d'imprimantes vers Samba pour les clients Windows
+.SH SYNOPSIS
+.B cupsaddsmb
+[ -a ] [ -U
+.I utilisateur
+] [ -v ]
+.br
+.B cupsaddsmb
+[ -u
+.I utilisateur
+] [ -v ] [ imprimante1 ... imprimanteN ]
+.SH DESCRIPTION
+\fIcupsaddsmb\fR permet l'export d'imprimantes vers SAMBA (version 2.2.0
+ou supérieure) pour l'utilisation par des clients Windows. Suivant
+la configuration de SAMBA, il est possible qu'un mot de passe soit
+demandé pour l'export. Ce programme requiert les fichiers du driver
+d'imprimante Adobe PostScript ou CUPS, comme indiqué plus bas.
+.LP
+L'option \fI-a\fR exporte toutes les imprimantes connues. Sinon,
+seules les imprimantes fournies dans la ligne de commande sont
+exportées.
+.LP
+L'option \fI-U\fR spécifie le nom d'utilisateur de l'administrateur
+d'impression. C'est par défaut votre nom d'utilisateur.
+.LP
+L'option \fI-v\fR spécifie que des informations détaillées doivent
+être affichées. Ceci peut être utile pour le débogage des configurations
+de SAMBA.
+.SH CONFIGURATION DE SAMBA
+\fIcupsaddsmb\fR utilise le nouveau mode d'impression RPC de
+SAMBA pour fournir aux clients Windows les drivers d'impression et les
+fichiers PPD. Pour utiliser cette fonctionnalité, vous devez configurer
+SAMBA (via le fichier smb.conf) pour qu'il utilise l'impression via CUPS, et
+fournir un driver à télécharger. Ceci est fait de la manière suivante\ :
+.nf
+
+ [global]
+ load printers = yes
+ printing = cups
+ printcap name = cups
+
+ [printers]
+ comment = All Printers
+ path = /var/spool/samba
+ browseable = no
+ public = yes
+ guest ok = yes
+ writable = no
+ printable = yes
+ printer admin = root
+
+ [print$]
+ comment = Printer Drivers
+ path = /etc/samba/drivers
+ browseable = yes
+ guest ok = no
+ read only = yes
+ write list = root
+.fi
+.LP
+Cette configuration suppose une installation de SAMBA conforme au
+standard FHS. Modifiez les chemins dans [printers] et [print$] suivant
+votre installation.
+.SH PILOTES POSTSCRIPT CUPS POUR WINDOWS
+\fIcupsaddsmb\fR peut utiliser les pilotes d'impression CUPS PostScript pour
+Windows, disponibles sur le site Internet de CUPS.
+.LP
+Il est recommandé d'utiliser ces pilotes CUPS car ils permettent le comptage
+du nombre de pages, les pages de garde et les labels sur tous les types
+d'imprimantes. Ces pilotes ne sont cependant disponibles que pour les
+plates-formes Windows NT, 2000 et XP. Pour des plates-formes Windows 95, 98 et Me,
+il est nécessaire d'utiliser les pilotes Adobe.
+.LP
+Après décompression des fichiers, créer un répertoire «\ drivers\ » dans le
+répertoire de données de CUPS (habituellement /usr/share/cups) et copiez
+les fichiers CUPS en utilisant des noms de fichiers en MINUSCULES, comme
+ci-dessous\ :
+.nf
+ [Windows NT, 2000, and XP]
+ cups.hlp
+ cupsdrvr.dll
+ cupsui.dll
+.fi
+
+.SH LES PILOTES ADOBE POSTSCRIPT POUR WINDOWS
+\fIcupsaddsmb\fR peut utiliser les pilotes Adobe PostScript pour Windows,
+disponibles en téléchargement sur le site web d'Adobe (http://www.adobe.com).
+.LP
+Il est recommandé d'utiliser ces pilotes CUPS car ils permettent le comptage
+du nombre de pages, les pages de garde et les labels sur tous les types
+d'imprimantes. Ces pilotes ne sont cependant disponibles que pour les
+plates-formes Windows NT, 2000 et XP. Pour des plates-formes Windows 95, 98 et Me,
+il est nécessaire d'utiliser les pilotes Adobe.
+.LP
+Une fois les fichiers décompressés, créez un répertoire «\ drivers\ » dans
+le répertoire de données de CUPS (habituellement /usr/share/cups) et
+copiez les fichiers Adobe en utilisant des noms de fichiers en MAJUSCULES,
+comme ci-dessous\ :
+.nf
+
+ [Windows 95, 98, and Me]
+ ADFONTS.MFM
+ ADOBEPS4.DRV
+ ADOBEPS4.HLP
+ DEFPRTR2.PPD
+ ICONLIB.DLL
+ PSMON.DLL
+
+ [Windows NT, 2000, and XP]
+ cups.hlp
+ cupsdrvr.dll
+ cupsui.dll
+.fi
+.LP
+Les deux jeux de pilotes sont utilisables indépendemment.
+.SH VOIR AUSSI
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cupsaddsmb.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/cupsd.conf.man b/man/fr/cupsd.conf.man
new file mode 100644
index 000000000..6f7408409
--- /dev/null
+++ b/man/fr/cupsd.conf.man
@@ -0,0 +1,359 @@
+.\"
+.\" "$Id: cupsd.conf.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" cupsd.conf man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.10
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsd.conf 5 "Common UNIX Printing System" "12 août 2002" «Easy Software Products»
+.SH NOM
+cupsd.conf \- Fichier de configuration du serveur CUPS
+.SH DESCRIPTION
+Le fichier \fIcupsd.conf\fR configure l'ordonnanceur CUPS, \fIcupsd(8)\fR. Il est
+généralement situé dans le répertoire \fI/etc/cups\fR.
+.LP
+Chaque ligne de ce fichier est soit une directive de configuration, une ligne vide, ou
+un commentaire. Les lignes de commentaire commencent par le caractère #. Les directives
+de configuration sont volontairement similaires à celles utilisées par le serveur web
+Apache, et sont décrites ci-dessous.
+.SH DIRECTIVES
+Les directives suivantes sont interprétées par \fIcupsd\fR. Veuillez vous reporter au
+Manuel d'administration CUPS pour une description plus détaillée.
+.TP 5
+AccessLog
+.br
+Définit le fichier traçant les accès.
+.TP 5
+Allow
+.br
+Permet l'accès à CUPS depuis des machines nommées ou des adresses IP.
+.TP 5
+AuthClass
+.br
+Définit la classe d'identification (User, Group, System)
+.TP 5
+AuthType
+.br
+Définit le type d'identification (None, Basic, Digest)
+.TP 5
+AutoPurgeJobs
+.br
+Définit s'il faut purger automatiquement l'historique des travaux lorsque les données ne sont plus nécessaires pour l'application des quotas.
+.TP 5
+BrowseAddress
+.br
+Définit une adresse où broadcaster les informations sur les imprimantes.
+.TP 5
+BrowseAllow
+.br
+Accepte les paquets arrivant de machines nommées ou d'adresses IP.
+.TP 5
+BrowseDeny
+.br
+Refuse les paquets de demande d'informations sur les imprimantes arrivant
+de machines nommées ou d'adresses IP.
+.TP 5
+BrowseInterval
+.br
+Définit l'intervalle maximum entre les demandes d'information sur les
+imprimantes.
+.TP 5
+BrowseOrder
+.br
+Définit le contrôle d'accès aux informations des imprimantes (allow,deny ou deny,allow).
+.TP 5
+BrowsePoll
+.br
+Définit un serveur récupérant les informations sur les imprimantes.
+.TP 5
+BrowsePort
+.br
+Définit le port utilisé pour les demandes d'informations sur les imprimantes.
+.TP 5
+BrowseProtocols
+.br
+Définit les protocoles réseaux à utiliser pour la recherche d'imprimantes.
+.TP 5
+BrowseRelay
+.br
+Les paquets de demande d'information peuvent être relayés depuis une machine ou
+un réseau vers un autre.
+.TP 5
+BrowseShortNames
+.br
+Définit si les imprimantes distantes utilisent les noms abrégés («\ imprimante\ »)
+ou non («\ imprimante@serveur\ »). Cette option est ignorée si plus d'une imprimante
+distante a le même nom.
+.TP 5
+BrowseTimeout
+.br
+Définit l'intervalle maximum de temps entre deux mises à jour d'informations
+des imprimantes distantes avant que celles-ci ne soient supprimées de la liste
+des imprimantes disponibles.
+.TP 5
+Browsing
+.br
+Définit si la récupération des informations des imprimantes distantes doit être activée.
+.TP 5
+Classification
+.br
+Définit le niveau de sécurité du serveur
+.TP 5
+ClassifyOverride
+.br
+Définit s'il faut autoriser les utilisateurs à modifier la classification de leurs travaux d'impression.
+.TP 5
+ConfigFilePerm
+.br
+Définit les permissions UNIX à utiliser pour les fichiers de configuration utilisés par l'ordonnanceur.
+.TP 5
+DataDir
+.br
+Définit le répertoire où se trouvent les fichiers de données.
+.TP 5
+DefaultCharset
+.br
+Définit le jeu de caractères par défaut à utiliser pour les textes.
+.TP 5
+DefaultLanguage
+.br
+Définit la langue par défaut à utiliser pour les textes et le site web.
+.TP 5
+Deny
+.br
+Interdit l'accès à une machine nommée ou à une adresse IP.
+.TP 5
+DocumentRoot
+.br
+Définit le répertoire racine des documents du serveur web interne.
+.TP 5
+Encryption
+.br
+Définit le niveau de cryptage nécessaire pour un lieu.
+.TP 5
+ErrorLog
+.br
+Définit le nom du fichier traçant les erreurs.
+.TP 5
+FilterLimit
+.br
+Définit le coût maximum des filtres lancés simultanément.
+.TP 5
+FilterNice
+.br
+Définit la priorité (valeur «\ nice\ ») des filtres exécutés pour une impression.
+.TP 5
+FontPath
+.br
+Définit le chemin de recherche des polices.
+.TP 5
+Group
+.br
+Définit le nom du groupe ou l'ID qui sera utilisé lors de l'exécution de
+programmes externes.
+.TP 5
+HideImplicitMembers
+.br
+Définit s'il faut cacher ou non les membres des classes implicites.
+.TP 5
+HostNameLookups
+.br
+Définit s'il faut effectuer ou non des recherches de noms à partir des adresses
+des clients.
+.TP 5
+ImplicitAnyClasses
+.br
+Définit s'il faut créer ou non des classes implicites pour les imprimantes
+locales et distantes (par exemple «\ UneImprimante\ » pour «\ Imprimante\ »,
+«\ Imprimante@serveur1\ » et «\ Imprimante@serveur2\ »).
+.TP 5
+ImplicitClasses
+.br
+Définit s'il faut créer ou non une classe implicite pour les imprimants distantes
+identiques.
+.TP 5
+KeepAlive
+.br
+Définit s'il faut utiliser HTTP-Keep-Alive.
+.TP 5
+KeepAliveTimeout
+.br
+Définit le timeout pour HTTP-Keep-Alive.
+.TP 5
+<Limit methods> ... </Limit>
+.TP 5
+<LimitExcept methods> ... </LimitExcept>
+.br
+Définit les méthodes HTTP interdites pour un lieu donné.
+.TP 5
+LimitRequestBody
+.br
+Définit la taille maximale des demandes de travaux d'impression.
+.TP 5
+<Location /path> ... </Location>
+.br
+Définit les contrôles d'accès à une destination donnée.
+.TP 5
+LogFilePerm
+.br
+Définit les permissions UNIX des fichiers de trace écrits par l'ordonnanceur.
+.TP 5
+LogLevel
+.br
+Définit le niveau de trace (none, warn, error, info, debug ou debug2).
+.TP 5
+MaxClients
+.br
+Définit le nombre maximum de clients simultanés.
+.TP 5
+MaxCopies
+.br
+Définit le nombre maximum de copies qu'un utilisateur peut effectuer pour un travail d'impression.
+.TP 5
+MaxJobs
+.br
+Définit le nombre maximum de travaux simultanés.
+.TP 5
+MaxJobsPerPrinter
+.br
+Définit le nombre maximum de travaux simultanés par imprimante.
+.TP 5
+MaxJobsPerUser
+.br
+Définit le nombre maximum de travaux simultanés par utilisateur.
+.TP 5
+MaxLogSize
+.br
+Définit la taille maximale des fichiers de trace. Au-delà de cette taille, les fichiers
+sont recyclés (on ne garde que les entrées les plus récentes pour supprimer les plus vieilles).
+Indiquer 0 pour supprimer la rotation des fichiers.
+.TP 5
+MaxRequestSize
+.br
+Définit la taille maximale des fichiers et des requêtes à imprimer. La taille
+est exprimée en octets (0 indique qu'il n'y a pas de limite).
+.TP 5
+Order
+.br
+Définit le contrôle d'accès HTTP (allow,deny ou deny,allow).
+.TP 5
+PageLog
+.br
+Définit le fichier de trace des pages web visitées.
+.TP 5
+Port
+.br
+Définit le numéro du port où écouter les requêtes HTTP.
+.TP 5
+PreserveJobFiles
+.br
+Définit s'il faut conserver ou non les fichiers de travail après impression.
+.TP 5
+PreserveJobHistory
+.br
+Définit s'il faut conserver ou non l'historique des demandes d'impression
+une fois qu'elles sont terminées.
+.TP 5
+Printcap
+.br
+Définit l'emplacement du fichier printcap, contenant la liste des imprimantes,
+et qui est mis à jour automatiquement. Ce fichier est indispensable aux
+applications externes.
+.TP 5
+PrintcapGUI
+.br
+Définit s'il faut générer ou non les fichiers du panneau d'options sur certains systèmes d'exploitation.
+.TP 5
+RemoteRoot
+.br
+Définit le nom d'utilisateur associé aux accès root non identifié.
+.TP 5
+RequestRoot
+.br
+Définit le répertoire où sont stockés les fichiers de travail et les données des requêtes HTTP.
+.TP 5
+Require
+.br
+Définit qu'une identification par utilisateur ou par groupe est nécessaire.
+.TP 5
+RIPCache
+.br
+Définit la taille maximale de mémoire à utiliser lors de la conversion d'images
+ou de fichiers PostScript en fichier bitmap pour une imprimante.
+.TP 5
+RunAsUser
+.br
+Définit si l'ordonnanceur doit être lancé en tant qu'utilisateur, dont le nom doit être défini par la directive «\ User\ ».
+.TP 5
+Satisfy
+.br
+Définit si tout ou partie des limites définies pour un lieu donné doivent être satisfaites pour permettre l'accès.
+.TP 5
+ServerAdmin
+.br
+Définit l'adresse électronique de l'administrateur du serveur.
+.TP 5
+ServerBin
+.br
+Définit le répertoire où les applications frontales, les CGI, les démons et
+les filtres sont stockés.
+.TP 5
+ServerCertificate
+.br
+Définit le certificat de cryptage à utiliser.
+.TP 5
+ServerKey
+.br
+Définit la clé de cryptage à utiliser.
+.TP 5
+ServerName
+.br
+Définit le nom complet du serveur.
+.TP 5
+ServerRoot
+.br
+Définit le répertoire où les fichiers de configuration du serveur sont stockés.
+.TP 5
+SystemGroup
+.br
+Définit le groupe à utiliser pour les identifications système.
+.TP 5
+TempDir
+.br
+Définit le répertoire où les fichiers temporaires sont stockés.
+.TP 5
+Timeout
+.br
+Définit le timeout des requêtes HTTP (en secondes).
+.TP 5
+User
+.br
+Définit le nom ou l'identifiant de l'utilisateur utilisé lors du lancement de programmes externes.
+.SH VOIR AUSSI
+classes.conf(5), cupsd(8), mime.convs(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cupsd.conf.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/cupsd.man b/man/fr/cupsd.man
new file mode 100644
index 000000000..df8d67907
--- /dev/null
+++ b/man/fr/cupsd.man
@@ -0,0 +1,52 @@
+.\"
+.\" "$Id: cupsd.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" cupsd man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.8
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupsd 8 "Common UNIX Printing System" "18 juillet 2002" "Easy Software Products"
+.SH NOM
+cupsd \- common unix printing system daemon
+.SH SYNOPSIS
+.B cupsd
+[ \-c
+.I config-file
+] [ \-f ] [ \-F ]
+.SH DESCRIPTION
+\fIcupsd\fR est un programmateur pour le système Common UNIX Printing System. Il fournit des outils pour un système d'impression de base sous le Internet Printing Protocol, version 1.1. Si aucune option n'est spécifiée dans la ligne de commande, alors le fichier de configuration par défaut (habituellement \fI/etc/cups/cupsd.conf\fR) sera utilisé.
+.PP
+L'option \fI-f\fR force \fIcupsd\fR à tourner en avant-plan\ ; par défaut, cupsd tourne en arrière-plan comme «\ démon\ ».
+.PP
+L'option \fI-F\fR force \fIcupsd\fR à tourner en avant-plan, mais détache le processus du terminal et du répertoire de travail. Cette option est utile pour lancer \fIcupsd\fR depuis \fIinit\fR.
+.SH COMPATIBILITÉ
+\fIcupsd\fR fournit tous les attributs et opération de IPP/1.1. Il implémente aussi plusieurs opérations d'administration spécifiques à CUPS
+.SH VOIR AUSSI
+backend(1), classes.conf(5), cupsd.conf(5), filter(1), mime.convs(5),
+mime.types(5), printers.conf(5),
+CUPS Implementation of IPP,
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: cupsd.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/cupstestppd.man b/man/fr/cupstestppd.man
new file mode 100644
index 000000000..a9b1ebb62
--- /dev/null
+++ b/man/fr/cupstestppd.man
@@ -0,0 +1,102 @@
+.\"
+.\" "$Id: cupstestppd.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" cupstestppd man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.4
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH cupstestppd 1 "Common UNIX Printing System" "14 Février 2003" "Easy Software Products"
+.SH NOM
+cupstestppd \- Teste la conformité des fichiers PPD
+.SH SYNOPSIS
+.B cupstestppd
+[ -q ] [ -v[v] ] nom_fichier.ppd[.gz] [ ... nom_fichierN.ppd[.gz] ]
+.br
+.B cupstestppd
+[ -v[v] ] -
+.SH DESCRIPTION
+\fIcupstestppd\fR teste la conformité des fichiers PPD envers la
+spécification de format de fichier édictée par Adobe, dans sa version
+4.3. Cette commande peut également être utilisée pour voir la
+liste des options reconnues et des polices disponibles d'un
+fichier PPD. Toutes les sorties sont effectuées sur la sortie standard.
+.LP
+Le premier mode d'appel de \fIcupstestppd\fR nécessite la présence
+d'un ou plusieurs fichiers PPD dans la ligne de commandes. Le second
+mode d'appel affiche les caractéristiques des fichiers PPD fournis sur
+l'entrée standard.
+.LP
+L'option \fB-q\fR indique qu'aucune information ne doit être affichée
+à l'écran.
+.LP
+L'option \fI-v\fR indique qu'il faut afficher toutes les informations d'un fichier
+PPD à la place du statut PASS/FAILED/ERROR (conforme/non conforme/erreur).
+.LP
+L'option \fI-vv\fR indique qu'il faut afficher toutes les informations d'un fichier
+PPD en plus du résultat des tests de conformité.
+.LP
+Les options \fB-q\fR, \fI-v\fR et \fI-vv\fR sont mutuellement exclusives.
+.SH CODE DE RETOUR
+\fIcupstestppd\fR renvoie 0 en cas de réussite aux tests et une valeur différente de 0
+en cas d'échec. Les codes d'erreur sont les suivants\ :
+.TP 5
+1
+.br
+Arguments de la ligne de commandes incorrects ou fichier PPD non trouvé.
+.TP 5
+2
+.br
+Impossible d'ouvrir ou de lire le fichier PPD.
+.TP 5
+3
+.br
+Le fichier PPD contient des erreurs de format ne pouvant être ignorées.
+.TP 5
+4
+.br
+Le fichier PPD n'est pas conforme à la spécification Adobe.
+.SH EXEMPLES
+La commande suivante teste tous les fichiers PPD du répertoire courant, et
+affiche le nom de tous les fichiers non conformes\ :
+.nf
+
+ find . -name \\*.ppd \\! -exec cupstestppd -q '{}' \\; print
+
+.fi
+La commande suivante teste tous les fichiers PPD du répertoire courant, et
+affiche les résultats détaillées des fichiers non conformes\ :
+.nf
+
+ find . -name \\*.ppd \\! -exec cupstestppd -q '{}' \\; \\
+ -exec cupstestppd -v '{}' \\;
+
+.fi
+.SH VOIR AUSSI
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html,
+Spécification du format de fichier Adobe Postscript Printer, version 4.3
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, All Rights Reserved.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: cupstestppd.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/enable.man b/man/fr/enable.man
new file mode 100644
index 000000000..699b42823
--- /dev/null
+++ b/man/fr/enable.man
@@ -0,0 +1,68 @@
+.\"
+.\" "$Id: enable.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" enable/disable man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.7
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH enable 8 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+disable, enable \- active/désactive les imprimantes et classes
+.SH SYNOPSIS
+.B disable
+[ -E ] [ \-c ] [ -h
+.I serveur
+] [ \-r
+.I motif
+] destination(s)
+.br
+.B enable
+[ -E ] destination(s)
+.SH DESCRIPTION
+\fIenable\fR démarre l'imprimante ou la classe fournie dans la ligne de commande.
+.LP
+\fIdisable\fR arrête l'imprimante ou la classe fournie dans la ligne de commande.
+Les options suivantes peuvent être utilisées\ :
+.TP 5
+\-c
+.br
+Annule les travaux en cours.
+.TP 5
+\-r [ \fImotif\fR ]
+.br
+Associe le message à l'arrêt de la classe ou de l'imprimante. Si aucun motif n'est
+donné, le message est «\ Raison inconnue\ ».
+.LP
+L'option \fI-E\fR force le cryptage lors de la communication au serveur.
+.SH COMPATIBILITÉ
+Les versions CUPS de \fIdisable\fR et \fIenable\fR peuvent demander un mot de
+passe à l'utilisateur suivant la configuration du système d'impression, à la
+différence des versions System V qui demandent le mot de passe root.
+.SH VOIR AUSSI
+accept(8), cancel(1), lp(1), lpadmin(8), lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: enable.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/filter.man b/man/fr/filter.man
new file mode 100644
index 000000000..86bee82d8
--- /dev/null
+++ b/man/fr/filter.man
@@ -0,0 +1,127 @@
+.\"
+.\" "$Id: filter.man 3671 2003-04-28 01:42:07Z mike $"
+.\"
+.\" filter man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.10
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH filter 1 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NOM
+filter \- Interface des filtres de conversion de fichier de CUPS
+.SH SYNOPSIS
+.B filter
+travail utilisateur titre nb_copies options [
+.I nom_de_fichier
+]
+.SH DESCRIPTION
+Les filtres CUPS sont une méthode standard de reconnaissance de nouveaux
+formats de fichier. Un filtre doit être capable de convertir un ou plusieurs
+formats en entrée, et générer un fichier en sortie, dont le format est soit directement
+compréhensible par CUPS, soit retraité par un autre filtre pour obtenir
+un format imprimable.
+.LP
+Ces programmes doivent être capables de lire un fichier de la ligne de
+commande ou via l'entrée standard, si besoin est en recopiant son contenu
+dans un fichier temporaire. Toute sortie doit être faite sur la sortie standard.
+.LP
+Le nom de la commande (argv[0]) est l'URI de l'imprimante.
+.SH VARIABLES D'ENVIRONNEMENT
+Les variables d'environnement suivantes sont définies par le serveur CUPS
+lors de l'exécution d'un filtre\ :
+.TP 5
+CHARSET
+.br
+Le jeu de caractères par défaut (généralement us-ascii ou iso-8859-1).
+.TP 5
+CLASS
+.br
+Contient le nom de la classe lorsqu'un travail d'impression est envoyé à une cla
+sse d'imprimantes. Cette variable n'est pas définie si le travail d'impression n'
+est pas envoyé à une classe.
+.TP 5
+CONTENT_TYPE
+.br
+Le type MIME associé au fichier (ex\ : application/postscript).
+.TP 5
+CUPS_DATADIR
+.br
+Le répertoire où se trouvent les données.
+.TP 5
+CUPS_SERVERROOT
+.br
+Le répertoire racine du serveur.
+.TP 5
+DEVICE_URI
+.br
+L'URI de l'imprimante.
+.TP 5
+LANG
+.br
+La langue (généralement C ou en).
+.TP 5
+PATH
+.br
+La liste des chemins où chercher les programmes pouvant être exécutés
+par le filtre.
+.TP 5
+PPD
+.br
+Le chemin complet d'accès au fichier PPD (PostScript Printer Description)
+de l'imprimante.
+.TP 5
+PRINTER
+.br
+Le nom de l'imprimante, ceci pour les scripts shells qui ne sont pas
+toujours capables de récupérer l'argument argv[0].
+.TP 5
+RIP_CACHE
+.br
+La quantité de mémoire recommandée pour l'utilisation du RIP (Raster Image
+Processors).
+.TP 5
+SOFTWARE
+.br
+Le nom et le numéro de version du serveur (généralement CUPS/1.1).
+.TP 5
+TZ
+.br
+Le fuseau horaire du serveur.
+.TP 5
+USER
+.br
+L'utilisateur exécutant le programme (généralement lp). Vous pouvez
+trouver cette information dans le fichier cupsd.conf.
+.SH COMPATIBILITÉ
+Bien que l'interface des filtres soit compatible avec les scripts System V,
+ceci ne fonctionnera qu'avec le script System V fourni via la commande
+\fBlpadmin(8)\fR avec l'option \fI-i\fR.
+.SH VOIR AUSSI
+backend(1), cupsd(8),
+CUPS Interface Design Description,
+CUPS Software Administrators Manual,
+CUPS Software Programmers Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: filter.man 3671 2003-04-28 01:42:07Z mike $".
+.\"
diff --git a/man/fr/lp.man b/man/fr/lp.man
new file mode 100644
index 000000000..fbc81aacf
--- /dev/null
+++ b/man/fr/lp.man
@@ -0,0 +1,184 @@
+.\"
+.\" "$Id: lp.man 3623 2003-04-16 19:03:38Z mike $"
+.\"
+.\" lp/cancel man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.12
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lp 1 "Common UNIX Printing System" "24 janvier 2003" "Easy Software Products"
+.SH NOM
+lp \- Imprime des fichiers
+.br
+cancel \- Annule des travaux d'impression
+.SH SYNOPSIS
+.B lp
+[ -E ] [ \-c ] [ \-d
+.I destination
+] [ \-h
+.I serveur
+] [ \-m ] [ \-n
+.I nb-copies
+[ \-o
+.I option
+] [ \-q
+.I priorité
+] [ \-s ] [ \-t
+.I titre
+] [ \-H
+.I méthode
+] [ \-P
+.I liste-de-pages
+] [
+.I fichier(s)
+]
+.br
+.B lp
+[ -E ] [ \-c ] [ \-h
+.I serveur
+] [ \-i
+.I numéro-de-travail
+] [ \-n
+.I nb-copies
+[ \-o
+.I option
+] [ \-q
+.I priorité
+] [ \-t
+.I titre
+] [ \-H
+.I méthode
+] [ \-P
+.I liste-de-pages
+]
+.br
+.B cancel
+[ \-a ] [ -h
+.I serveur
+] [ -u
+.I utilisateur
+] [
+.I id
+] [
+.I destination
+] [
+.I destination-id
+]
+.SH DESCRIPTION
+\fBlp\fR demande l'impression d'un fichier ou modifie un travail d'impression
+en attente.
+.LP
+\fBcancel\fR annule un travail d'impression. L'option \fI-a\fR supprime tous
+les travaux d'impression d'une destination.
+.SH OPTIONS
+Les options suivantes sont reconnues par \fBlp\fR\ :
+.TP 5
+\-E
+.br
+Force le cryptage des données lors de la connexion au serveur.
+.TP 5
+\-c
+.br
+Cette option n'est fournie que pour des raisons de compatibilité avec les
+précédentes versions. Sur les systèmes le permettant, force la copie du fichier
+d'impression dans le répertoire spool avant impression. Avec CUPS, les fichiers
+d'impression sont envoyés à l'ordonnanceur via IPP. Le résultat est le même
+dans les deux cas.
+.TP 5
+\-d \fIdestination\fR
+.br
+Imprime les fichiers sur l'imprimante donnée.
+.TP 5
+\-h \fInom-de-machine\fR
+.br
+Demande l'impression sur un serveur d'impression donné. C'est par défaut
+«\ localhost\ » ou le contenu de la variable d'environnement CUPS_SERVER si
+celle-ci existe.
+.TP 5
+\-i \fInuméro-de-travail\fR
+.br
+Donne le numéro du travail d'impression à modifier.
+.TP 5
+\-m
+.br
+Envoie un courrier électronique lorsque l'impression est terminée.
+Cette option n'est pas gérée par CUPS 1.1.
+.TP 5
+\-n \fInb-copies\fR
+.br
+Nombre de copies à effectuer (de 1 à 100).
+.TP 5
+\-o \fIoption\fR
+.br
+Définit une option pour le travail d'impression.
+.TP 5
+\-q \fIpriorité\fR
+.br
+Définit la priorité du travail d'impression, de 1 (minimale) à 100 (maximale).
+La priorité par défaut est 50.
+.TP 5
+\-s
+.br
+N'affiche pas le numéro du travail (mode silencieux).
+.TP 5
+\-t \fInom\fR
+.br
+Définit le nom du travail.
+.TP 5
+\-u \fInom_utilisateur\fR
+.br
+Annule les travaux d'impression de l'utilisateur \fInom_utilisateur\fR.
+.TP 5
+\-H \fIméthode\fR
+.br
+Définit quand l'impression doit être effectuée. La valeur \fIimmediate\fR effectue
+l'impression immédiatement, la valeur \fIhold\fR suspend l'impression indéfiniment,
+une valeur, une heure suspend l'impression jusqu'à l'heure donnée. Utilisez la valeur
+\fIresume\fR avec l'option \fI-i\fR pour reprendre un travail suspendu. Utilisez la
+valeur \fIrestart\fR avec l'option \fI-i\fR pour relancer un travail terminé.
+.TP 5
+\-P \fIliste-de-pages\fR
+.br
+Définit quelles sont les pages à imprimer. Cette liste ne peut contenir que des numéros
+ou des portions (#-#), séparés par des virgules (ex\ : 1,3-5,16).
+.SH COMPATIBILITÉ
+Contrairement au système d'impression System V, les imprimantes peuvent contenir n'importe
+quel caractère imprimable sauf ESPACE et TABULATION. De même, les noms d'imprimantes et de
+classes ne sont pas sensibles à la casse.
+.LP
+L'option «\ m\ » n'est pas opérationnelle dans CUPS 1.1.
+.LP
+L'option «\ q\ » accepte des valeurs de 1 à 100, contrairement au lp de Solaris qui
+utilise des valeurs de 0 à 39.
+.SH NOTES
+Les administrateurs désirant empêcher les annulations de travaux d'impression
+d'autres utilisateurs via l'option \fI-u\fR doivent protéger par mot de passe
+l'endroit où sont stockés les travaux d'impression (voir la section
+<Location\ /jobs> dans le fichier \fIcupsd.conf(5)\fR.
+.SH VOIR AUSSI
+lpstat(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lp.man 3623 2003-04-16 19:03:38Z mike $".
+.\"
diff --git a/man/fr/lpadmin.man b/man/fr/lpadmin.man
new file mode 100644
index 000000000..78b807bbd
--- /dev/null
+++ b/man/fr/lpadmin.man
@@ -0,0 +1,168 @@
+.\"
+.\" "$Id: lpadmin.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.11
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpadmin 8 "Common UNIX Printing System" "21 octobre 2002" "Easy Software Products"
+.SH NOM
+lpadmin \- Configure les imprimantes et classes d'imprimantes de CUPS
+.SH SYNOPSIS
+.B lpadmin
+[ -E ] [ -h
+.I serveur
+] \-d
+.I destination
+.br
+.B lpadmin
+[ -E ] [ -h
+.I serveur
+] \-p
+.I imprimante
+.I option(s)
+.br
+.B lpadmin
+[ -E ] [ -h
+.I serveur
+] \-x
+.I destination
+.SH DESCRIPTION
+\fIlpadmin\fR configure les imprimantes et classes d'imprimantes de CUPS.
+Il est également utilisé pour définir l'imprimante ou classe d'imprimante
+par défaut.
+.LP
+Lorsque l'option \fI-E\fR est spécifiée avant les options \fI-d\fR, \fI-p\fR,
+ou \fI-x\fR, la communication avec le serveur est cryptée.
+.LP
+La première méthode d'utilisation de la commande définit l'imprimante ou la classe
+par défaut. Les impressions futures demandées par les
+commandes \fIlp(1)\fR ou \fIlpr(1)\fR utiliseront cette destination sauf avis
+contraire de l'utilisateur par l'utilisation de la commande \fIlptions(1)\fR.
+.LP
+La seconde méthode configure une imprimante. Les options disponibles
+sont décrites plus loin.
+.LP
+La troisième méthode supprime l'imprimante ou classe
+\fIdestination\fR. Tous les travaux d'impression en attente sont supprimés,
+et les travaux en cours d'impression sont arrêtés.
+.SH OPTIONS DE CONFIGURATION
+Les options suivantes sont reconnues par la commande \fIlpadmin\fR\ :
+.TP 5
+\-c \fIclasse\fR
+.br
+Ajoute l'imprimante \fIimprimante\fR à la classe \fIclasse\fR. Si la classe
+n'existe pas encore, elle est créée automatiquement.
+.TP 5
+\-i \fIinterface\fR
+.br
+Crée un script d'interface System V pour l'imprimante. Cette option ne
+peut être utilisée en même temps que \fI\-P\fR (fichier PPD) et est destinée
+au support des imprimantes de base.
+.TP 5
+\-m \fImodèle\fR
+.br
+Définit un script d'interface System V ou un fichier PPD à utiliser.
+.TP 5
+\-o \fIname=value\fR
+.br
+Définit une option PPD ou serveur pour une imprimante. La liste des options
+PPD peut être obtenue en utilisant la commande \fIlpoptions -l\fR.
+.TP 5
+\-o \fIjob-k-limit=valeur\fR
+.br
+Définit les quotas par utilisateur en kilo-octets. La valeur est un nombre
+entier de kilo-octets (valant 1\ 024 octets).
+.TP 5
+\-o \fIjob-page-limit=valeur\fR
+.br
+Définit les quotas par utilisateur en nombre de pages. La valeur est un nombre
+entier de pages pouvant être imprimées. Les recto-verso comptent pour deux
+pages.
+.TP 5
+\-o \fIjob-quota-period=valeur\fR
+.br
+Définit les quotas par utilisateur en impressions par intervalle de temps. La
+valeur est un nombre entier définissant le nombre de secondes entre chaque
+impression. Une journée contient 86\ 400 secondes.
+.TP 5
+\-o \fIprotocol=nom\fR
+Définit le protocole à utiliser lors des communications binaires pour les
+impressions. Les protocoles sont None (Aucun), BCP et TBCP. Le protocole
+par défaut est None.
+.TP 5
+\-r \fIclasse\fR
+.br
+Supprime \fIl'imprimante\fR de la \fIclasse\fR. Si la classe d'imprimante devient
+vide, celle-ci est supprimée.
+.TP 5
+\-u \fIallow:utilisateur,utilisateur,@groupe\fR
+\-u \fIdeny:utilisateur,utilisateur,@groupe\fR
+\-u \fIallow:all\fR
+\-u \fIdeny:none\fR
+.br
+Définit les accès par utilisateur sur une imprimante. Les noms commençant par le symbole
+@ sont des noms de groupes UNIX. Les deux dernières expressions
+suppriment les contrôles d'accès par utilisateur.
+.TP 5
+\-v \fIdevice-uri\fR
+.br
+Définit l'attribut \fIdevice-uri\fR de la file d'attente de l'imprimante. Si \fIdevice-uri\fR
+est un nom de fichier, il est converti automatiquement en la forme \fBfile:/fichier/nom\fR.
+.TP 5
+\-D \fIinfo\fR
+.br
+Définit une description de l'imprimante.
+.TP 5
+\-E
+.br
+Active l'imprimante et lui fait accepter les travaux d'impression. Ceci peut
+également être effectué en lançant les commandes \fIaccept(8)\fR et \fIenable(8)\fR
+sur l'imprimante.
+.TP 5
+\-L \fIlieufR
+.br
+Définit le lieu de l'imprimante.
+.TP 5
+\-P \fIfichier-ppd\fR
+.br
+Définit le fichier PPD (Postscript Printer Description) à utiliser avec cette
+imprimante. Si cette option est spécifiée, elle annule l'option \fI-i\fR
+(script d'interface).
+.SH COMPATIBILITÉ
+Contrairement au système d'impression System V, CUPS permet des noms d'imprimantes
+contenant tout caractère imprimable sauf ESPACE et TABULATION. De plus, les noms
+d'imprimante et de classe ne sont pas sensibles à la casse. De plus, la version
+CUPS peut demander un mot de passe, suivant la configuration du système, à la
+différence de la version System V qui demande le mot de passe root.
+.SH LIMITATIONS
+La version CUPS de \fIlpadmin\fR ne reconnaît pas toutes les options de configuration
+disponibles dans les versions System V ou Solaris.
+.SH VOIR AUSSI
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpadmin.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/lpc.man b/man/fr/lpc.man
new file mode 100644
index 000000000..385fe8326
--- /dev/null
+++ b/man/fr/lpc.man
@@ -0,0 +1,82 @@
+.\"
+.\" "$Id: lpc.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpc man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.5
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpc 8 "Common UNIX Printing System" "22 Septembre 1999" "Easy Software Products"
+.SH NOM
+lpc \- Programme de contrôle de l'imprimante
+.SH SYNOPSIS
+.B lpc
+[
+.I commande
+[
+.I paramètre(s)
+] ]
+.SH DESCRIPTION
+\fIlpc\fR permet de contrôler partiellement des imprimantes et classes d'imprimantes
+de CUPS. Il est également utilisé pour récupérer l'état des files d'attente.
+.LP
+Si aucune option n'est donnée dans la ligne de commande, \fRlpc\fR affichera une
+invite et prendra ses commandes depuis l'entrée standard.
+.SH COMMANDES
+\fIlpc\fR reconnaît un sous-ensemble des commandes reconnues le programme \fIlpc\fR
+de Berkeley\ :
+.TP 5
+\fIexit
+.br
+Quitte l'interpréteur de commandes.
+.TP 5
+help \fI[commande]\fR
+.br
+Affiche un message d'aide.
+.TP 5
+quit
+.br
+Quitte l'interpréteur de commandes.
+.TP 5
+status \fI[file-attente]\fR
+.br
+Affiche l'état des files d'attente d'une ou plusieurs classes ou imprimantes.
+.TP 5
+? \fI[commande]\fR
+.br
+Affiche un message d'aide.
+.SH LIMITATIONS
+Étant donné que \fIlpc\fR est spécifique au système d'impression de Berkeley, il
+est impossible de l'utiliser pour configurer les files d'attente de CUPS. Pour cela,
+vous devez utiliser le programme \fIlpadmin(8)\fR ou tout autre client compatible
+avec CUPS remplissant ces fonctions.
+.SH COMPATIBILITÉ
+La version CUPS de \fIlpc\fR n'implémente pas toutes les commandes de la version Berkeley.
+.SH VOIR AUSSI
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpr(1), lprm(1),
+lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpc.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpinfo.man b/man/fr/lpinfo.man
new file mode 100644
index 000000000..7580c7582
--- /dev/null
+++ b/man/fr/lpinfo.man
@@ -0,0 +1,63 @@
+.\"
+.\" "$Id: lpinfo.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpinfo man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.7
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpinfo 8 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+lpinfo \- Affiche les périphériques et pilotes disponibles
+.SH SYNOPSIS
+.B lpinfo
+[ -E ] [ -l ] [ -m ] [ -v ]
+.SH DESCRIPTION
+\fBlpinfo\fR affiche la liste des périphériques ou pilotes connus par le
+serveur CUPS. Il est impératif d'utiliser une des options \fI-m\fR ou \fI-v\fR
+pour obtenir quelque chose en sortie.
+.TP 5
+\-E
+.br
+Force le cryptage lors de la connexion au serveur.
+.TP 5
+\-l
+.br
+Affiche une liste détaillée des périphériques et pilotes disponibles.
+.TP 5
+\-m
+.br
+Affiche les périphériques disponibles.
+.TP 5
+\-v
+.br
+Affiche les pilotes disponibles.
+.SH COMPATIBILITÉ
+La commande \fBlpinfo\fR est spécifique à CUPS.
+.SH VOIR AUSSI
+lpadmin(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpinfo.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpmove.man b/man/fr/lpmove.man
new file mode 100644
index 000000000..80cfbaf51
--- /dev/null
+++ b/man/fr/lpmove.man
@@ -0,0 +1,58 @@
+.\"
+.\" "$Id: lpmove.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpmove man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.7
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpmove 8 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+lpmove \- Déplace un travail d'impression vers une nouvelle destination
+.SH SYNOPSIS
+.B lpmove
+[ -E ]
+.I ID_du_travail destination
+.SH DESCRIPTION
+\fBlpmove\fR déplace les \fItravaux d'impression\fR vers une nouvelle
+\fIdestination\fR. On peut spécifier le travail sous deux formes\ :
+soit l'ID du travail d'impression, soit ancienne destination et ID du travail.
+Exemple\ :
+.br
+.nf
+
+ lpmove 123 NouvelleImprimante
+ lpmove AncienneImprimante-123 NouvelleImprimante
+.fi
+.LP
+L'option \fI-E\fR force le cryptage des données lors de la connexion au serveur.
+.SH COMPATIBILITÉ
+La version System V de \fBlpmove \fR permet de déplacer tous les travaux d'impression
+d'une file d'attente vers une autre. Cette fonctionnalité n'est pas gérée par CUPS.
+.SH VOIR AUSSI
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpmove.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpoptions.man b/man/fr/lpoptions.man
new file mode 100644
index 000000000..08a455c59
--- /dev/null
+++ b/man/fr/lpoptions.man
@@ -0,0 +1,127 @@
+.\"
+.\" "$Id: lpoptions.man 3664 2003-04-26 17:09:56Z mike $"
+.\"
+.\" lpoptions man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.11
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpoptions 1 "Common UNIX Printing System" "21 octobre 2002" "Easy Software Products"
+.SH NOM
+lpoptions \- Affiche et définit les options et paramètres par défaut d'une imprimante
+.SH SYNOPSIS
+.B lpoptions
+[ -h
+.I serveur
+] -d
+.I destination[/instance]
+[ -o
+.I option=valeur
+] ... [ -o
+.I option=valeur
+]
+.br
+.B lpoptions
+[ -h
+.I serveur
+] [ -E ] [ -p
+.I destination[/instance]
+] -l
+.br
+.B lpoptions
+[ -h
+.I serveur
+] [ -E ] [ -o
+.I option=valeur
+] ... [ -o
+.I option=valeur
+] [ -p
+.I dest[/instance]
+] -r
+.I option
+.br
+.B lpoptions
+[ -h
+.I serveur
+] [ -E] -x
+.I destination[/instance]
+.SH DESCRIPTION
+Lorsqu'il est lancé sans arguments, \fBlpoptions\fR affiche les options
+par défaut. Les paramètres pouvant être fournis sont\ :
+.TP 5
+\-E
+.br
+Crypte les données lors de la communication avec le serveur CUPS.
+.TP 5
+\-d \fIdestination[/instance]\fR
+.br
+Définit \fIdestination\fR comme imprimante par défaut. Il est également
+possible de fournir une \fIinstance\fR. Cette option redéfinit
+l'imprimante par défaut de l'utilisateur en cours.
+.TP 5
+\-h \fIserveur\fR
+.br
+Définit le serveur CUPS avec lequel communiquer.
+.TP 5
+\-l
+.br
+Affiche les options spécifiques d'une imprimante et ses paramétrages.
+.TP 5
+\-o \fIoption=valeur\fR
+.br
+Définit une nouvelle option pour une destination.
+.TP 5
+\-p \fIdestination[/instance]\fR
+.br
+Définit les options d'une destination ou instance. Si l'instance n'existe
+pas, celle-ci est créée.
+.TP 5
+\-r \fIoption\fR
+.br
+Supprime une option de la destination fournie en paramètre.
+.TP 5
+\-x \fIdestination[/instance]\fR
+.br
+Supprime toutes les options de la destination ou instance fournie en
+paramètre. Si l'instance n'existe pas, la commande n'a pas d'effet.
+.LP
+Si aucune option n'est fournie dans la ligne de commande, les options
+de l'imprimante fournie en paramètre sont affichées sur la sortie standard.
+.LP
+Les options définies par la commande \fBlpoptions\fR sont utilisées par les
+commandes \fBlp(1)\fR et \fBlpr(1)\fR lors de l'envoi de travaux d'impression.
+.SH UTILISATION DU COMPTE ROOT
+Lorsque la commande \fBlpoptions\fR est lancée par l'utilisateur root, les options sont lues et sauvegardées pour \fItous les utilisateurs\fR dans le fichier
+/etc/cups/lpoptions.
+.SH COMPATIBILITÉ
+La commande \fBlpoptions\fR est spécifique à CUPS.
+.SH FICHIERS
+~/.lpoptions - fichier créé par utilisateur et contenant ses options.
+/etc/cups/lpoptions - fichier global de configuration créé par l'utilisateur root.
+.SH VOIR AUSSI
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpoptions.man 3664 2003-04-26 17:09:56Z mike $".
+.\"
diff --git a/man/fr/lppasswd.man b/man/fr/lppasswd.man
new file mode 100644
index 000000000..f34b1093d
--- /dev/null
+++ b/man/fr/lppasswd.man
@@ -0,0 +1,64 @@
+.\"
+.\" "$Id: lppasswd.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.3
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lppasswd 1 "Common UNIX Printing System" "7 Juin 2001" "Easy Software Products"
+.SH NOM
+lppasswd \- Ajoute, modifie ou supprime des mots de passe
+.SH SYNOPSIS
+.B lppasswd
+[ -a ] [ -g
+.I groupe
+] [ -x ] [
+.I utilisateur
+]
+.SH DESCRIPTION
+\fIlppasswd\fR ajoute, modifie ou supprime des mots de passe du fichier
+\fIpasswd.md5\fR. Lorsque ce programme est lancé par un utlisateur non privilégié,
+il demande l'ancien et le nouveau mot de passe. Lorsque ce programme est lancé par
+un super-utilisateur, il peut créer de nouveaux comptes utilisateurs (\fI-a utilisateur\fR),
+modifier des comptes existants (\fIutilisateur\fR), ou supprimer des comptes
+(\fI-x utilisateur\fR). Les noms d'utilisateurs ne doivent pas forcément correspondre
+à des noms d'utilisateurs UNIX. Cependant, seuls les utilisateurs UNIX sont gérés
+par les programmes clients CUPS (\fIlp(1)\fR, \fIlpr(1)\fR, etc.)
+.LP
+L'option \fI-g\fR définit un groupe autre que le groupe système -\ «\ sys\ »,
+«\ system\ », «\ root\ », suivant le système d'exploitation.
+.SH PROBLÈMES DE SÉCURITÉ
+La commande \fIlppasswd\fR est installée avec le bit setuid activé. Toutes les précautions
+ont été prises pour empêcher les exploits permettant l'accès aux privilèges du
+super-utilisateur par un utilisateur non privilégié. Cependant, certains administrateurs
+systèmes (paranoïaques) peuvent vouloir désactiver ce programme ou en modifier le
+propriétaire par un utilisateur non privilégié.
+.SH VOIR AUSSI
+lp(1), lpr(1),
+CUPS Software Administrators Manual,
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lppasswd.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpq.man b/man/fr/lpq.man
new file mode 100644
index 000000000..a14d9f7b1
--- /dev/null
+++ b/man/fr/lpq.man
@@ -0,0 +1,60 @@
+.\"
+.\" "$Id: lpq.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpq man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.7
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpq 1 "Common UNIX Printing System" "13 Février 2001" "Easy Software Products"
+.SH NOM
+lpq \- Affiche les travaux en attente d'une imprimante
+.SH SYNOPSIS
+.B lpq
+[ -E ] [ \-P
+.I destination
+] [ \-a ] [ \-l ] [
+.I +intervalle
+]
+.SH DESCRIPTION
+\fIlpq\fR affiche les travaux en attente d'une imprimante. Si aucune imprimante
+ou classe n'est donnée dans la ligne de commande, les travaux en attente
+sur la destination par défaut seront affichés.
+.LP
+L'option \fIintervalle\fR permet d'afficher les travaux en attente en continu
+jusqu'à ce qu'il n'y en ait plus. La liste est réaffichée toutes les \fIintervalle\fR
+secondes.
+.LP
+L'option \fI-E\fR force le cryptage lors de la connexion au serveur.
+.LP
+L'option \fI-a\fR affiche les travaux de toutes les imprimantes.
+.LP
+L'option \fI-l\fR affiche les travaux dans un format verbeux.
+.SH VOIR AUSSI
+cancel(1), lp(1), lpr(1), lprm(1), lpstat(1)
+.br
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpq.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpr.man b/man/fr/lpr.man
new file mode 100644
index 000000000..7c18d1749
--- /dev/null
+++ b/man/fr/lpr.man
@@ -0,0 +1,107 @@
+.\"
+.\" "$Id: lpr.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpr man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpr 1 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+lpr \- Imprime des fichiers
+.SH SYNOPSIS
+.B lpr
+[ -E ] [ \-P
+.I destination
+] [ \-#
+.I nombre de copies
+[ \-l ] [ \-o
+.I option
+] [ \-p] [ \-r ] [ \-C/J/T
+.I titre
+] [
+.I fichier(s)
+]
+.SH DESCRIPTION
+\fBlpr\fR demande l'impression de fichiers. Si des fichiers sont donnés dans la
+ligne de commande, ceux-ci sont envoyés à la destination donnée (ou la destination
+par défaut si aucune n'est fournie).
+Si aucun fichier n'est donné dans la ligne de commande, \fBlpr\fR lit les fichiers
+sur l'entrée standard.
+.SH OPTIONS
+Les options suivantes sont reconnues par \fBlpr\fR\ :
+.TP 5
+\-E
+.br
+Force le cryptage lors de la connexion au serveur.
+.TP 5
+\-P \fIdestination\fR
+.br
+Imprime les fichiers vers l'imprimante donnée.
+.TP 5
+\-# \fInombre de copies\fR
+.br
+Définit le nombre de copies (de 1 à 100).
+.TP 5
+\-C \fInom\fR
+.br
+Définit le nom du travail d'impression.
+.TP 5
+\-J \fInom\fR
+.br
+Définit le nom du travail d'impression.
+.TP 5
+\-T \fInom\fR
+.br
+Définit le nom du travail d'impression.
+.TP 5
+\-l
+.br
+Spécifie que le fichier est déjà formaté pour la destination, et qu'aucun
+filtre n'a besoin d'être appliqué. Cette option est équivalente à «\ -oraw\ ».
+.TP 5
+\-o \fIoption\fR
+.br
+Définit une option pour le travail d'impression.
+.TP 5
+\-p
+.br
+Spécifie que chaque page du fichier à imprimer doit avoir un en-tête ombré,
+contenant la date, l'heure, le nom du travail d'impression et le numéro de page.
+Cette option est équivalente à «\ -oprettyprint\ » et n'est utile que dans le cas de
+fichiers texte.
+.TP 5
+\-r
+.br
+Spécifie que les fichiers doivent être effacés après impression.
+.SH COMPATIBILITÉ
+Les options «\ c\ », «\ d\ », «\ f\ », «\ g\ », «\ i\ », «\ m\ », «\ n\ »,
+«\ t\ », «\ v\ » et «\ w\ » ne sont pas supportées par CUPS et donnent un
+message d'avertissement lorsqu'elles sont utilisées.
+.SH VOIR AUSSI
+cancel(1), lp(1), lpstat(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lpr.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lprm.man b/man/fr/lprm.man
new file mode 100644
index 000000000..675ea85e8
--- /dev/null
+++ b/man/fr/lprm.man
@@ -0,0 +1,57 @@
+.\"
+.\" "$Id: lprm.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lprm man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lprm 1 "Common UNIX Printing System" "23 Janvier 2001" "Easy Software Products"
+.SH NOM
+lprm \- Annule des travaux d'impression
+.SH SYNOPSIS
+.B lprm
+[ -E ] [ - ] [ -P
+.I destination
+] [
+.I ID(s) des travaux d'impression
+]
+.SH DESCRIPTION
+\fBlprm\fR annule des travaux d'impression en attente. L'option \fI-P\fR spécifie
+l'imprimante ou la classe de destination.
+.LP
+Si aucun argument n'est fourni, c'est le travail en cours sur la destination par
+défaut qui est annulé. Il est possible de fournir un ou plusieurs ID de travaux
+d'impression à annuler, ou utiliser l'option \fI\-\fR pour annuler tous les
+travaux.
+.LP
+L'option \fI-E\fR force le cryptage lors de la connexion au serveur.
+.SH COMPATIBILITÉ
+La version CUPS de \fIlprm\fR est compatible avec la version standard Berkeley.
+.SH VOIR AUSSI
+cancel(1), lp(1), lpstat(1), lpr(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: lprm.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/lpstat.man b/man/fr/lpstat.man
new file mode 100644
index 000000000..3f916bff9
--- /dev/null
+++ b/man/fr/lpstat.man
@@ -0,0 +1,144 @@
+.\"
+.\" "$Id: lpstat.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" lpstat man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.10
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpstat 1 "Common UNIX Printing System" "3 Janvier 2003" "Easy Software Products"
+.SH NOM
+lpstat \- Affiche l'état de CUPS
+.SH SYNOPSIS
+.B lpstat
+[ -E ] [ -h
+.I serveur
+] [ -l ] [ -W
+.I quels_travaux
+] [ -a [
+.I destination(s)
+] ] [ -c [
+.I classe(s)
+] [ -d ] [ -o [
+.I destination(s)
+] ] [ -p [
+.I imprimante(s)
+] ] [ -r ] [ -R ] [ -s ] [ -t ] [ -u [
+.I utilisateur(s)
+] ] [ -v [
+.I imprimante(s)
+] ]
+.SH DESCRIPTION
+\fBlpstat\fR affiche l'état des classes, travaux et imprimantes.
+Quand \fBlpstat\fR est lancé sans arguments, la liste des travaux en attente
+de l'utilisateur est affichée. Les autres options sont\ :
+.TP 5
+\-E
+.br
+Force le cryptage lors de la connexion au serveur.
+.TP 5
+\-a [\fIimprimante(s)\fR]
+.br
+Vérifie si les files d'attente des imprimantes acceptent les travaux d'impression.
+Si aucune imprimante n'est fournie dans la ligne de commande, toutes les imprimantes
+sont affichées.
+.TP 5
+\-c [\fIclasse(s)\fR]
+.br
+Affiche la classe d'imprimantes et ses imprimantes associées. Si aucune classe n'est
+fournie dans la ligne de commande, toutes les classes sont affichées.
+.TP 5
+\-d
+.br
+Affiche la destination par défaut.
+.TP 5
+\-h \fIserver\fR
+.br
+Définit le serveur CUPS où envoyer la requête.
+.TP 5
+\-l
+.br
+Affiche une liste détaillée des imprimantes, classes et travaux d'impression.
+.TP 5
+\-o [\fIdestination(s)\fR]
+.br
+Affiche la file d'attente des travaux sur les destinations spécifiées. Si aucune
+destination n'est fournie dans la ligne de commande, tous les travaux sont affichés.
+.TP 5
+\-p [\fIimprimante(s)\fR]
+.br
+Affiche les imprimantes et si elles sont prêtes ou non à l'impression. Si aucune
+imprimante n'est fournie dans la ligne de commande, toutes les imprimantes sont affichées.
+.TP 5
+\-r
+.br
+Affiche si le serveur CUPS est actif.
+.TP 5
+\-R
+.br
+Affiche le rang des travaux d'impressions.
+.TP 5
+\-s
+.br
+Affiche l'état détaillé, comprenant la destination par défaut, la liste
+des classes et leurs imprimantes associées, la liste des imprimantes et leur
+périphérique. Ceci peut être effectué en utilisant les options "-d", "-c" et "-p".
+.TP 5
+\-t
+.br
+Affiche toutes les informations. Ceci peut être effectué en utilisant les options
+"-r", "-d", "-c", "-d", "-v", "-a", "-p", et "-o".
+.TP 5
+\-u [\fIutilisateur(s)\fR]
+.br
+Affiche les travaux d'impression en attente d'un utilisateur. Si aucun utilisateur
+n'est fourni dans la ligne de commande, affiche les travaux de l'utilisateur qui lance
+la commande.
+.TP 5
+\-v [\fIimprimante(s)\fR]
+.br
+Affiche les imprimantes et à quel matériel elles sont rattachées. Si aucune imprimante
+n'est fournie dans
+la ligne de commande, toutes les imprimantes sont affichées.
+.TP 5
+\-W [\fiquels-travaux\fR]
+.br
+Définit quels sont les travaux à afficher, terminés («\ \fIcompleted\fR\ ») ou en cours («\ \fInot-completed\fR\ »),
+qui est l'option par défaut. Cette option \fBdoit\fR doit se trouver dans la ligne de commandes avant
+l'option \fI-o\fR et tout nom d'imprimante. Dans le cas contraire, la valeur par défaut («\ \fInot-completed\fR\ »)
+sera envoyée à l'ordonnanceur.
+.SH COMPATIBILITÉ
+Contrairement au système d'impression System V, CUPS permet des noms d'imprimantes
+contenant tout caractère imprimable sauf ESPACE et TABULATION. De plus, les noms
+d'imprimante et de classe ne sont pas sensibles à la casse.
+.LP
+Les options «\ -h\ » et «\ -W\ » sont spécifiques à CUPS.
+.LP
+Les options «\ -f\ », «\ -P\ » et «\ -S\ » de Solaris sont ignorées.
+.SH VOIR AUSSI
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" "$Id: lpstat.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
diff --git a/man/fr/mime.convs.man b/man/fr/mime.convs.man
new file mode 100644
index 000000000..4a3a2cad2
--- /dev/null
+++ b/man/fr/mime.convs.man
@@ -0,0 +1,59 @@
+.\"
+.\" "$Id: mime.convs.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" mime.convs man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH mime.convs 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NOM
+mime.convs \- Fichier de conversion des types MIME de CUPS
+.SH DESCRIPTION
+Le fichier \fImime.convs\fR définit les filtres disponibles pour
+convertir des fichiers d'un format vers un autre. Les filtres
+standards concernent les fichiers textes, PDF, PostScript, HP-GL/2
+ainsi que plusieurs formats graphiques.
+.LP
+Des filtres supplémentaires peuvent être ajoutés dans le fichier
+\fImime.convs\fR ou dans d'autres fichiers portant l'extension
+«\ .convs\ » dans le répertoire de configuration de CUPS (généralement
+\fB/etc/cups\fR).
+.LP
+Chaque ligne du fichier \fImime.convs\fR est un commentaire,
+une ligne vide ou une définition de filtre. Les commentaires commencent
+par le caractère #. Les lignes contenant un filtre spécifient les types
+MIME source et cible, le coût du filtre, puis le filtre lui-même\ :
+.br
+.nf
+
+super/type super/type coût filtre
+application/postscript application/vnd.cups-raster 50 pstoraster
+.fi
+.SH VOIR AUSSI
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: mime.convs.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/mime.types.man b/man/fr/mime.types.man
new file mode 100644
index 000000000..eb11975f2
--- /dev/null
+++ b/man/fr/mime.types.man
@@ -0,0 +1,104 @@
+.\"
+.\" "$Id: mime.types.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" mime.types man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH mime.types 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NOM
+mime.types \- Fichier de description des types MIME de CUPS
+.SH DESCRIPTION
+Le fichier \fImime.types\fR définit les types de fichier reconnus par CUPS.
+.LP
+D'autres types de fichiers peuvent être ajoutés au fichier \fImime.types\fR
+ou à d'autres fichier dans le répertoire \fB/etc/cups\fR. Ceux-ci doivent
+porter l'extension «\ .types\ ».
+.LP
+Chaque ligne du fichier \fImime.types\fR est soit une règle, soit
+une ligne vide, soit un commentaire (ligne commençant par le caractère
+#). Chaque ligne définissant une règle commence par le nom du type MIME,
+et peut être suivi par une liste de règle des reconnaissance utilisées
+pour déterminer le type du fichier\ :
+.br
+.nf
+
+ super/type règle [ ... règleN]
+.fi
+Ces règles doivent être mises entre parenthèses, liées par un "+" pour
+exprimer un ET logique, "," ou une espace pour exprimer un OU logique.
+Elles sont précédées de "!" pour exprimer un NON logique.
+.SH RÈGLES
+Les règles sont composées de deux parties\ : une extension de fichier et des
+fonctions de tests entre parenthèses. Les fonctions suivantes peuvent être
+utilisées\ :
+.TP 5
+match("motif")
+.br
+Reconnaissance d'un motif sur le nom du fichier
+.TP 5
+ascii(début, longueur)
+.br
+Vrai si tous les octets de la portion de document sont des caractères ASCII
+imprimables (CR, NL, TAB, BS, 32-126)
+.TP 5
+printable(début, longueur)
+.br
+Vrai si tous les octets de la portion de document sont des caractères 8 bits
+imprimables (CR, NL, TAB, BS, 32-126, 128-254)
+.TP 5
+string(début, "chaîne")
+.br
+Vrai si les octets sont identiques à "chaîne"
+.TP 5
+char(début, valeur)
+.br
+Vrai si les octets sont identiques
+.TP 5
+short(début, valeur)
+.br
+Vrai si les nombres entiers (16 bits) sont identiques
+.TP 5
+int(début, valeur)
+.br
+Vrai si les nombres entiers (32 bits) sont identiques
+.TP 5
+locale("chaîne")
+.br
+Vrai si les définitions de langage sont identiques
+.TP 5
+contains(début, portée, "chaîne")
+.br
+Vrai si la chaîne est trouvée dans la portion de document
+.SH CHAÎNES DE CARACTÈRES
+Les chaînes de caractères peuvent être définies entre guillemets ("")
+pour des chaînes contenant des espaces ou entre crochets (<>) pour des
+chaînes en hexadécimal.
+.SH VOIR AUSSI
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: mime.types.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/fr/printers.conf.man b/man/fr/printers.conf.man
new file mode 100644
index 000000000..d1040a12e
--- /dev/null
+++ b/man/fr/printers.conf.man
@@ -0,0 +1,76 @@
+.\"
+.\" "$Id: printers.conf.man 3456 2003-03-12 20:41:43Z mike $"
+.\"
+.\" printers.conf man page for the Common UNIX Printing System (CUPS).
+.\" Based on cvs revision 1.6
+.\"
+.\" Copyright 1997-2003 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3111 USA
+.\"
+.\" Voice: (301) 373-9603
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH printers.conf 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NOM
+printers.conf \- Fichier de configuration des imprimantes CUPS
+.SH DESCRIPTION
+Le fichier \fIprinters.conf\fR définit les imprimantes locales
+de la machine. Il est habituellement situé dans le répertoire \fI/etc/cups\fR
+et est généré automatiquement par le programme \fIcupsd(8)\fR lors
+de l'ajout ou de la suppression d'imprimantes.
+.LP
+Chaque ligne du fichier est une directive de configuration, une ligne
+vide ou un commentaire (ligne commençant par la caractère #).
+.SH DIRECTIVES
+.TP 5
+Accepting
+.br
+Définit si l'imprimante accepte ou non les travaux d'impression.
+.TP 5
+Info
+.br
+Définit un commentaire de description de l'imprimante.
+.TP 5
+Location
+.br
+Définit un commentaire concernant la localisation physique de l'imprimante.
+.TP 5
+DeviceURI
+.br
+Définit l'URI de l'imprimante.
+.TP 5
+<Printer name> ... </Printer>
+.br
+Définit une imprimante.
+.TP 5
+State
+.br
+Définit l'état initial de l'imprimante (Idle ou Stopped).
+.TP 5
+StateMessage
+.br
+Définit le message associé à cet état.
+.SH VOIR AUSSI
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5),
+CUPS Software Administrators Manual,
+CUPS Interface Design Description,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2003 Easy Software Products, Tous droits réservés.
+.SH TRADUCTION
+Gilles QUERRET <gilles.querret@nerim.net>
+.\"
+.\" End of "$Id: printers.conf.man 3456 2003-03-12 20:41:43Z mike $".
+.\"
diff --git a/man/lp.man b/man/lp.man
new file mode 100644
index 000000000..88efc5d5d
--- /dev/null
+++ b/man/lp.man
@@ -0,0 +1,181 @@
+.\"
+.\" "$Id: lp.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lp/cancel man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lp 1 "Common UNIX Printing System" "1 May 2003" "Easy Software Products"
+.SH NAME
+lp \- print files
+.br
+cancel \- cancel jobs
+.SH SYNOPSIS
+.B lp
+[ -E ] [ \-c ] [ \-d
+.I destination
+] [ \-h
+.I server
+] [ \-m ] [ \-n
+.I num-copies
+[ \-o
+.I option
+] [ \-q
+.I priority
+] [ \-s ] [ \-t
+.I title
+] [ \-H
+.I handling
+] [ \-P
+.I page-list
+] [
+.I file(s)
+]
+.br
+.B lp
+[ -E ] [ \-c ] [ \-h
+.I server
+] [ \-i
+.I job-id
+] [ \-n
+.I num-copies
+[ \-o
+.I option
+] [ \-q
+.I priority
+] [ \-t
+.I title
+] [ \-H
+.I handling
+] [ \-P
+.I page-list
+]
+.br
+.B cancel
+[ \-a ] [ -h
+.I server
+] [ -u
+.I username
+] [
+.I id
+] [
+.I destination
+] [
+.I destination-id
+]
+.SH DESCRIPTION
+\fBlp\fR submits files for printing or alters a pending job. Use
+a filename of "-" to force printing from the standard input.
+.LP
+\fBcancel\fR cancels existing print jobs. The \fI-a\fR option will remove
+all jobs from the specified destination.
+.SH OPTIONS
+The following options are recognized by \fBlp\fR:
+.TP 5
+\-E
+.br
+Forces encryption when connecting to the server.
+.TP 5
+\-c
+.br
+This option is provided for backwards-compatibility only. On
+systems that support it, this option forces the print file to be
+copied to the spool directory before printing. In CUPS, print
+files are always sent to the scheduler via IPP which has the
+same effect.
+.TP 5
+\-d \fIdestination\fR
+.br
+Prints files to the named printer.
+.TP 5
+\-h \fIhostname\fR
+.br
+Specifies the print server hostname. The default is "localhost" or the value
+of the CUPS_SERVER environment variable.
+.TP 5
+\-i \fIjob-id\fR
+.br
+Specifies an existing job to modify.
+.TP 5
+\-m
+.br
+Send email when the job is completed (not supported CUPS 1.1.)
+.TP 5
+\-n \fIcopies\fR
+.br
+Sets the number of copies to print from 1 to 100.
+.TP 5
+\-o \fIoption\fR
+.br
+Sets a job option.
+.TP 5
+\-q \fIpriority\fR
+.br
+Sets the job priority from 1 (lowest) to 100 (highest). The
+default priority is 50.
+.TP 5
+\-s
+.br
+Do not report the resulting job IDs (silent mode.)
+.TP 5
+\-t \fIname\fR
+.br
+Sets the job name.
+.TP 5
+\-u \fIusername\fR
+.br
+Cancels jobs owned by \fIusername\fR.
+.TP 5
+\-H \fIhandling\fR
+.br
+Specifies when the job should be printed. A value of
+\fIimmediate\fR will print the file immediately, a value of
+\fIhold\fR will hold the job indefinitely, and a time value
+(HH:MM) will hold the job until the specified time. Use a value
+of \fIresume\fR with the \fI-i\fR option to resume a held job.
+Use a value of \fIrestart\fR with the \fI-i\fR option to restart
+a completed job.
+.TP 5
+\-P \fIpage-list\fR
+.br
+Specifies which pages to print in the document. The list can contain a
+list of numbers and ranges (#-#) separated by commas (e.g. 1,3-5,16).
+.SH COMPATIBILITY
+Unlike the System V printing system, CUPS allows printer names to contain
+any printable character except SPACE and TAB. Also, printer and class names are
+\fBnot\fR case-sensitive.
+.LP
+The "m" option is not functional in CUPS 1.1.
+.LP
+The "q" option accepts a different range of values than the
+Solaris lp command, matching the IPP job priority values (1-100)
+instead of the Solaris values (0-39).
+.SH NOTES
+Administrators wishing to prevent unauthorized cancellation of
+jobs via the \fI-u\fR option should password-protect the /jobs
+location in \fIcupsd.conf(5)\fR.
+.SH SEE ALSO
+lpstat(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lp.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpadmin.man b/man/lpadmin.man
new file mode 100644
index 000000000..f05cf6ec1
--- /dev/null
+++ b/man/lpadmin.man
@@ -0,0 +1,163 @@
+.\"
+.\" "$Id: lpadmin.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpadmin 8 "Common UNIX Printing System" "21 October 2002" "Easy Software Products"
+.SH NAME
+lpadmin \- configure cups printers and classes
+.SH SYNOPSIS
+.B lpadmin
+[ -E ] [ -h
+.I server
+] \-d
+.I destination
+.br
+.B lpadmin
+[ -E ] [ -h
+.I server
+] \-p
+.I printer
+.I option(s)
+.br
+.B lpadmin
+[ -E ] [ -h
+.I server
+] \-x
+.I destination
+.SH DESCRIPTION
+\fIlpadmin\fR configures printer and class queues provided by
+CUPS. It can also be used to set the server default printer or
+class.
+.LP
+When specified before the \fI-d\fR, \fI-p\fR, or \fI-x\fR options,
+the \fI-E\fR option forces encryption when connecting to the server.
+.LP
+The first form of the command sets the default printer or class to
+\fIdestination\fR. Subsequent print jobs submitted via the \fIlp(1)\fR or
+\fIlpr(1)\fR commands will use this destination unless the user specifies
+otherwise with the \fIlpoptions(1)\fR command.
+.LP
+The second form of the command configures the named printer. The additional
+options are described below.
+.LP
+The third form of the command deletes the printer or class \fIdestination\fR.
+Any jobs that are pending for the destination will be removed and any job that
+is currently printed will be aborted.
+.SH CONFIGURATION OPTIONS
+The following options are recognized when configuring a printer queue:
+.TP 5
+\-c \fIclass\fR
+.br
+Adds the named \fIprinter\fR to \fIclass\fR. If \fIclass\fR does not
+exist it is created automatically.
+.TP 5
+\-i \fIinterface\fR
+.br
+Sets a System V style interface script for the printer. This option cannot
+be specified with the \fI\-P\fR option (PPD file) and is intended for
+providing support for legacy printer drivers.
+.TP 5
+\-m \fImodel\fR
+.br
+Sets a standard System V interface script or PPD file from the model
+directory.
+.TP 5
+\-o \fIname=value\fR
+.br
+Sets a PPD or server option for the printer. PPD options can be listed
+using the \fI-l\fR option with the \fIlpoptions(1)\fR command.
+.TP 5
+\-o \fIjob-k-limit=value\fR
+.br
+Sets the kilobyte limit for per-user quotas. The value is an integer number
+of kilobytes; one kilobyte is 1024 bytes.
+.TP 5
+\-o \fIjob-page-limit=value\fR
+.br
+Sets the page limit for per-user quotas. The value is the integer number of
+pages that can be printed; double-sided pages are counted as two pages.
+.TP 5
+\-o \fIjob-quota-period=value\fR
+.br
+Sets the accounting period for per-user quotas. The value is an integer number
+of seconds; 86,400 seconds are in one day.
+.TP 5
+\-o \fIprotocol=name\fR
+.br
+Sets the binary communications protocol to use when printing,
+None, BCP, or TBCP. The default protocol is None.
+.TP 5
+\-r \fIclass\fR
+.br
+Removes the named \fIprinter\fR from \fIclass\fR. If the resulting class
+becomes empty it is removed.
+.TP 5
+\-u \fIallow:user,user,@group\fR
+\-u \fIdeny:user,user,@group\fR
+\-u \fIallow:all\fR
+\-u \fIdeny:none\fR
+.br
+Sets user-level access control on a printer. Names starting with
+"@" are interpreted as UNIX groups. The latter two forms turn
+user-level access control off.
+.TP 5
+\-v \fIdevice-uri\fR
+.br
+Sets the \fIdevice-uri\fR attribute of the printer queue. If \fIdevice-uri\fR
+is a filename it is automatically converted to the form \fBfile:/file/name\fR.
+.TP 5
+\-D \fIinfo\fR
+.br
+Provides a textual description of the printer.
+.TP 5
+\-E
+.br
+Enables the printer and accepts jobs; this is the same as running the
+\fIaccept(8)\fR and \fIenable(8)\fR programs on the printer.
+.TP 5
+\-L \fIlocation\fR
+.br
+Provides a textual location of the printer.
+.TP 5
+\-P \fIppd-file\fR
+.br
+Specifies a PostScript Printer Description file to use with the printer. If
+specified, this option overrides the \fI-i\fR option (interface script).
+.SH COMPATIBILITY
+Unlike the System V printing system, CUPS allows printer names to contain
+any printable character except SPACE and TAB. Also, printer and class names are
+\fBnot\fR case-sensitive. Finally, the CUPS version of \fIlpadmin\fR may ask the
+user for an access password depending on the printing system configuration.
+This differs from the System V version which requires the root user to execute
+this command.
+.SH LIMITATIONS
+The CUPS version of \fIlpadmin\fR does not support all of the System V or
+Solaris printing system configuration options.
+.SH SEE ALSO
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpadmin.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpc.man b/man/lpc.man
new file mode 100644
index 000000000..a8a082722
--- /dev/null
+++ b/man/lpc.man
@@ -0,0 +1,80 @@
+.\"
+.\" "$Id: lpc.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpc man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpc 8 "Common UNIX Printing System" "22 September 1999" "Easy Software Products"
+.SH NAME
+lpc \- line printer control program
+.SH SYNOPSIS
+.B lpc
+[
+.I command
+[
+.I parameter(s)
+] ]
+.SH DESCRIPTION
+\fIlpc\fR provides limited control over printer and class queues provided by
+CUPS. It can also be used to query the state of queues.
+.LP
+If no command is specified on the command-line, \fRlpc\fR will display a
+prompt and accept commands from the standard input.
+.SH COMMANDS
+The \fIlpc\fR program accepts a subset of commands accepted by the Berkeley
+\fIlpc\fR program of the same name:
+.TP 5
+\fIexit
+.br
+Exits the command interpreter.
+.TP 5
+help \fI[command]\fR
+.br
+Displays a short help message.
+.TP 5
+quit
+.br
+Exits the command interpreter.
+.TP 5
+status \fI[queue]\fR
+.br
+Displays the status of one or more printer or class queues.
+.TP 5
+? \fI[command]\fR
+.br
+Display a short help message.
+.SH LIMITATIONS
+Since \fIlpc\fR is geared towards the Berkeley printing system, it is impossible
+to use \fIlpc\fR to configure printer or class queues provided by CUPS. To
+configure printer or class queues you must use the \fIlpadmin(8)\fR command
+or another CUPS-compatible client with that functionality.
+.SH COMPATIBILITY
+The CUPS version of \fIlpc\fR does not implement all of the standard Berkeley
+commands.
+.SH SEE ALSO
+accept(8), cancel(1), disable(8), enable(8), lp(1), lpr(1), lprm(1),
+lpstat(1), reject(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpc.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpinfo.man b/man/lpinfo.man
new file mode 100644
index 000000000..36ba75e75
--- /dev/null
+++ b/man/lpinfo.man
@@ -0,0 +1,60 @@
+.\"
+.\" "$Id: lpinfo.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpinfo man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpinfo 8 "Common UNIX Printing System" "23 January 2001" "Easy Software Products"
+.SH NAME
+lpinfo \- show available devices or drivers
+.SH SYNOPSIS
+.B lpinfo
+[ -E ] [ -l ] [ -m ] [ -v ]
+.SH DESCRIPTION
+\fBlpinfo\fR lists the available devices or drivers known to the CUPS
+server. One of the \fI-m\fR or \fI-v\fR options must be specified to
+get any output:
+.TP 5
+\-E
+.br
+Forces encryption when connecting to the server.
+.TP 5
+\-l
+.br
+Shows a "long" listing of devices or drivers.
+.TP 5
+\-m
+.br
+Shows the available printer drivers on the system.
+.TP 5
+\-v
+.br
+Shows the available printer devices on the system.
+.SH COMPATIBILITY
+The \fBlpinfo\fR command is unique to CUPS.
+.SH SEE ALSO
+lpadmin(8),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpinfo.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpmove.man b/man/lpmove.man
new file mode 100644
index 000000000..de0e9b84e
--- /dev/null
+++ b/man/lpmove.man
@@ -0,0 +1,53 @@
+.\"
+.\" "$Id: lpmove.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpmove man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpmove 8 "Common UNIX Printing System" "23 January 2001" "Easy Software Products"
+.SH NAME
+lpmove \- move a job to a new destination
+.SH SYNOPSIS
+.B lpmove
+[ -E ]
+.I job destination
+.SH DESCRIPTION
+\fBlpmove\fR moves the specified \fIjob\fR to \fIdestination\fR. \fIjob\fR
+can be the job ID number or the old destination and job ID:
+.br
+.nf
+
+ lpmove 123 newprinter
+ lpmove oldprinter-123 newprinter
+.fi
+.LP
+The \fI-E\fR option forces encryption when connecting to the server.
+.SH COMPATIBILITY
+The System V version of this command also allows moving of all jobs from one
+queue to another. This functionality is currently not supported by CUPS.
+.SH SEE ALSO
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpmove.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpoptions.man b/man/lpoptions.man
new file mode 100644
index 000000000..9100213f1
--- /dev/null
+++ b/man/lpoptions.man
@@ -0,0 +1,128 @@
+.\"
+.\" "$Id: lpoptions.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpoptions man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpoptions 1 "Common UNIX Printing System" "21 October 2002" "Easy Software Products"
+.SH NAME
+lpoptions \- display or set printer options and defaults
+.SH SYNOPSIS
+.B lpoptions
+[ -h
+.I server
+] -d
+.I dest[/instance]
+[ -o
+.I option=value
+] ... [ -o
+.I option=value
+]
+.br
+.B lpoptions
+[ -h
+.I server
+] [ -E ] [ -p
+.I dest[/instance]
+] -l
+.br
+.B lpoptions
+[ -h
+.I server
+] [ -E ] [ -o
+.I option=value
+] ... [ -o
+.I option=value
+] [ -p
+.I dest[/instance]
+] -r
+.I option
+.br
+.B lpoptions
+[ -h
+.I server
+] [ -E ] -x
+.I dest[/instance]
+.SH DESCRIPTION
+\fBlpoptions\fR displays or sets printer options and defaults.
+\fBlpoptions\fR shows the default printer options when run with no
+arguments. Other options include:
+.TP 5
+\-E
+.br
+Enables encryption when communicating with the CUPS server.
+.TP 5
+\-d \fIdest[/instance]\fR
+.br
+Sets the default printer to \fIdest\fR. If \fIinstance\fR is supplied then
+that particular instance is used. This option overrides the system default
+printer for the current user.
+.TP 5
+\-h \fIserver\fR
+.br
+Specifies the CUPS server to communicate with.
+.TP 5
+\-l
+.br
+Lists the printer specific options and their current settings.
+.TP 5
+\-o \fIoption=value\fR
+.br
+Specifies a new option for the named destination.
+.TP 5
+\-p \fIdest[/instance]\fR
+.br
+Sets the destination and instance, if specified, for any options that follow.
+If the named instance does not exist then it is created.
+.TP 5
+\-r \fIoption\fR
+.br
+Removes the specified option for the named destination.
+.TP 5
+\-x \fIdest[/instance]\fR
+.br
+Removes the options for the named destination and instance, if specified.
+If the named instance does not exist then this does nothing.
+.LP
+If no options are specified using the \fI-o\fR option then the current
+options for the named printer are reported on the standard output.
+.LP
+Options set with the \fBlpoptions\fR command are used by the \fBlp(1)\fR
+and \fBlpr(1)\fR commands when submitting jobs.
+.SH ROOT ACCOUNT OPTIONS
+When run by the root user, \fBlpoptions\fR gets and sets default
+options and instances for \fIall users\fR in the
+/etc/cups/lpoptions file.
+.SH COMPATIBILITY
+The \fBlpoptions\fR command is unique to CUPS.
+.SH FILES
+~/.lpoptions - user defaults and instances created by non-root users.
+.br
+/etc/cups/lpoptions - system-wide defaults and instances created by the root
+user.
+.SH SEE ALSO
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpoptions.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lppasswd.man b/man/lppasswd.man
new file mode 100644
index 000000000..c0c772534
--- /dev/null
+++ b/man/lppasswd.man
@@ -0,0 +1,61 @@
+.\"
+.\" "$Id: lppasswd.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpadmin man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lppasswd 1 "Common UNIX Printing System" "7 June 2001" "Easy Software Products"
+.SH NAME
+lppasswd \- add, change, or delete digest passwords.
+.SH SYNOPSIS
+.B lppasswd
+[ -a ] [ -g
+.I groupname
+] [ -x ] [
+.I username
+]
+.SH DESCRIPTION
+\fIlppasswd\fR adds, changes, or deletes passwords in the CUPS digest
+password file, \fIpasswd.md5\fR. When run by a normal user, \fIlppasswd\fR
+will prompt for the old and new passwords. When run by the super-user,
+\fIlppasswd\fR can add new accounts (\fI-a username\fR), change existing
+accounts (\fIusername\fR), or delete accounts (\fI-x username\fR) in the
+digest password file. Digest usernames do not have to match local UNIX
+usernames, but only UNIX usernames are supported by the CUPS client programs
+(\fIlp(1)\fR, \fIlpr(1)\fR, etc.)
+.LP
+The \fI-g\fR option specifies a group other than the system group - "sys",
+"system", or "root", depending on the operating system.
+.SH SECURITY ISSUES
+The \fIlppasswd\fR command is installed setuid to root. While every attempt
+has been made to make it secure against exploits that could grant super-user
+priviledges to unpriviledged users, paranoid system administrators may wish
+to disable or change the ownership of the program to an unpriviledged
+account.
+.SH SEE ALSO
+lp(1), lpr(1),
+CUPS Software Administrators Manual,
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lppasswd.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpq.man b/man/lpq.man
new file mode 100644
index 000000000..b64ddcb52
--- /dev/null
+++ b/man/lpq.man
@@ -0,0 +1,57 @@
+.\"
+.\" "$Id: lpq.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" lpq man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpq 1 "Common UNIX Printing System" "13 February 2001" "Easy Software Products"
+.SH NAME
+lpq \- show printer queue status
+.SH SYNOPSIS
+.B lpq
+[ -E ] [ \-P
+.I dest
+] [ \-a ] [ \-l ] [
+.I +interval
+]
+.SH DESCRIPTION
+\fIlpq\fR shows the current print queue status on the named printer.
+Jobs queued on the default destination will be shown if no printer or
+class is specified on the command-line.
+.LP
+The \fIinterval\fR option allows you to continuously report the jobs
+in the queue until the queue is empty; the list of jobs is show one
+every \fIinterval\fR seconds.
+.LP
+The \fI-E\fR option forces encryption when connecting to the server.
+.LP
+The \fI-a\fR option reports jobs on all printers.
+.LP
+The \fI-l\fR option requests a more verbose (long) reporting format.
+.SH SEE ALSO
+cancel(1), lp(1), lpr(1), lprm(1), lpstat(1)
+.br
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpq.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/lpr.man b/man/lpr.man
new file mode 100644
index 000000000..f4afb9d42
--- /dev/null
+++ b/man/lpr.man
@@ -0,0 +1,107 @@
+.\"
+.\" "$Id: lpr.man 4475 2004-12-16 20:03:12Z mike $"
+.\"
+.\" lpr man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpr 1 "Common UNIX Printing System" "16 December 2004" "Easy Software Products"
+.SH NAME
+lpr \- print files
+.SH SYNOPSIS
+.B lpr
+[ -E ] [ \-P
+.I destination
+] [ \-U
+.I username
+] [ \-#
+.I num-copies
+[ \-l ] [ \-o
+.I option
+] [ \-p] [ \-r ] [ \-C/J/T
+.I title
+] [
+.I file(s)
+]
+.SH DESCRIPTION
+\fBlpr\fR submits files for printing. Files named on the command line are sent
+to the named printer (or the system default destination if no destination is
+specified). If no files are listed on the command-line \fBlpr\fR reads the
+print file from the standard input.
+.SH OPTIONS
+The following options are recognized by \fBlpr\fR:
+.TP 5
+\-E
+.br
+Forces encryption when connecting to the server.
+.TP 5
+\-P \fIdestination\fR
+.br
+Prints files to the named printer.
+.TP 5
+\-# \fIcopies\fR
+.br
+Sets the number of copies to print from 1 to 100.
+.TP 5
+\-C \fIname\fR
+.br
+Sets the job name.
+.TP 5
+\-J \fIname\fR
+.br
+Sets the job name.
+.TP 5
+\-T \fIname\fR
+.br
+Sets the job name.
+.TP 5
+\-U \fIusername\fR
+.br
+Sets the user name.
+.TP 5
+\-l
+.br
+Specifies that the print file is already formatted for the destination and
+should be sent without filtering. This option is equivalent to "-oraw".
+.TP 5
+\-o \fIoption\fR
+.br
+Sets a job option.
+.TP 5
+\-p
+.br
+Specifies that the print file should be formatted with a shaded header with
+the date, time, job name, and page number. This option is equivalent to
+"-oprettyprint" and is only useful when printing text files.
+.TP 5
+\-r
+.br
+Specifies that the named print files should be deleted after printing them.
+.SH COMPATIBILITY
+The "c", "d", "f", "g", "i", "m", "n", "t", "v", and "w" options are not
+supported by CUPS and will produce a warning message if used.
+.SH SEE ALSO
+cancel(1), lp(1), lpstat(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpr.man 4475 2004-12-16 20:03:12Z mike $".
+.\"
diff --git a/man/lprm.man b/man/lprm.man
new file mode 100644
index 000000000..1f1b31e4b
--- /dev/null
+++ b/man/lprm.man
@@ -0,0 +1,54 @@
+.\"
+.\" "$Id: lprm.man 4475 2004-12-16 20:03:12Z mike $"
+.\"
+.\" lprm man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lprm 1 "Common UNIX Printing System" "16 December 2004" "Easy Software Products"
+.SH NAME
+lprm \- cancel print jobs
+.SH SYNOPSIS
+.B lprm
+[ -E ] [ -P
+.I destination
+] [ - ] [
+.I job ID(s)
+]
+.SH DESCRIPTION
+\fBlprm\fR cancels print jobs that have been queued for printing. The \fI-P\fR
+option specifies the destination printer or class.
+.LP
+If no arguments are supplied, the current job on the default destination is
+cancelled. You can specify one or more job ID numbers to cancel those jobs,
+or use the \fI\-\fR option to cancel all jobs.
+.LP
+The \fI-E\fR option forces encryption when connecting to the server.
+.SH COMPATIBILITY
+The CUPS version of \fIlprm\fR is compatible with the standard Berkeley
+\fIlprm\fR command.
+.SH SEE ALSO
+cancel(1), lp(1), lpstat(1), lpr(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lprm.man 4475 2004-12-16 20:03:12Z mike $".
+.\"
diff --git a/man/lpstat.man b/man/lpstat.man
new file mode 100644
index 000000000..92a5fcd59
--- /dev/null
+++ b/man/lpstat.man
@@ -0,0 +1,140 @@
+.\"
+.\" "$Id: lpstat.man 4456 2004-10-29 13:44:10Z mike $"
+.\"
+.\" lpstat man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH lpstat 1 "Common UNIX Printing System" "29 October 2004" "Easy Software Products"
+.SH NAME
+lpstat \- print cups status information
+.SH SYNOPSIS
+.B lpstat
+[ -E ] [ -h
+.I server
+] [ -l ] [ -W
+.I which-jobs
+] [ -a [
+.I destination(s)
+] ] [ -c [
+.I class(es)
+] [ -d ] [ -o [
+.I destination(s)
+] ] [ -p [
+.I printer(s)
+] ] [ -r ] [ -R ] [ -s ] [ -t ] [ -u [
+.I user(s)
+] ] [ -v [
+.I printer(s)
+] ]
+.SH DESCRIPTION
+\fBlpstat\fR displays status information about the current classes, jobs, and
+printers. When run with no arguments, \fBlpstat\fR will list jobs queued by
+the user. Other options include:
+.TP 5
+\-E
+.br
+Forces encryption when connecting to the server.
+.TP 5
+\-a [\fIprinter(s)\fR]
+.br
+Shows the accepting state of printer queues. If no printers are
+specified then all printers are listed.
+.TP 5
+\-c [\fIclass(es)\fR]
+.br
+Shows the printer classes and the printers that belong to them. If no
+classes are specified then all classes are listed.
+.TP 5
+\-d
+.br
+Shows the current default destination.
+.TP 5
+\-h \fIserver\fR
+.br
+Specifies the CUPS server to communicate with.
+.TP 5
+\-l
+.br
+Shows a long listing of printers, classes, or jobs.
+.TP 5
+\-o [\fIdestination(s)\fR]
+.br
+Shows the jobs queue on the specified destinations. If no destinations are
+specified all jobs are shown.
+.TP 5
+\-p [\fIprinter(s)\fR]
+.br
+Shows the printers and whether or not they are enabled for printing. If
+no printers are specified then all printers are listed.
+.TP 5
+\-r
+.br
+Shows whether or not the CUPS server is running.
+.TP 5
+\-R
+.br
+Shows the ranking of print jobs.
+.TP 5
+\-s
+.br
+Shows a status summary, including the default destination, a
+list of classes and their member printers, and a list of printers and
+their associated devices. This is equivalent to using the "-d", "-c",
+and "-v" options.
+.TP 5
+\-t
+.br
+Shows all status information. This is equivalent to using the "-r",
+"-d", "-c", "-d", "-v", "-a", "-p", and "-o" options.
+.TP 5
+\-u [\fIuser(s)\fR]
+.br
+Shows a list of print jobs queued by the specified users. If no users
+are specified, lists the jobs queued by the current user.
+.TP 5
+\-v [\fIprinter(s)\fR]
+.br
+Shows the printers and what device they are attached to. If no printers
+are specified then all printers are listed.
+.TP 5
+\-W [\fIwhich-jobs\fR]
+.br
+Specifies which jobs to show, \fIcompleted\fR or
+\fInot-completed\fR (the default). This option \fBmust\fR appear
+before the \fI-o\fR option and/or any printer names, otherwise
+the default (not-completed) value will be used in the request to
+the scheduler.
+.SH COMPATIBILITY
+Unlike the System V printing system, CUPS allows printer names
+to contain any printable character except SPACE and TAB. Also,
+printer and class names are \fBnot\fR case-sensitive.
+.LP
+The "-h" and "-W" options are unique to CUPS.
+.LP
+The Solaris "-f", "-P", and "-S" options are silently ignored.
+.SH SEE ALSO
+cancel(1), lp(1),
+CUPS Software Users Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: lpstat.man 4456 2004-10-29 13:44:10Z mike $".
+.\"
diff --git a/man/mime.convs.man b/man/mime.convs.man
new file mode 100644
index 000000000..e07f58a1c
--- /dev/null
+++ b/man/mime.convs.man
@@ -0,0 +1,54 @@
+.\"
+.\" "$Id: mime.convs.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" mime.convs man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH mime.convs 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NAME
+mime.convs \- mime type conversion file for cups
+.SH DESCRIPTION
+The \fImime.convs\fR file defines the filters that are available for
+converting files from one format to another. The standard filters
+support text, PDF, PostScript, HP-GL/2, and many types of image files.
+.LP
+Additional filters can be added to the \fImime.convs\fR file or to
+other files in the configuration directory (\fB/etc/cups\fR) with
+the extension ".convs".
+.LP
+Each line in the \fImime.types\fR file is a comment, blank, or filter
+line. Comment lines start with the # character. Filter lines specify
+the source and destination MIME types along with a relative cost
+associated with the filter and the filter to run:
+.br
+.nf
+
+super/type super/type cost filter
+application/postscript application/vnd.cups-raster 50 pstoraster
+.fi
+.SH SEE ALSO
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.types(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: mime.convs.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/mime.types.man b/man/mime.types.man
new file mode 100644
index 000000000..d86578f00
--- /dev/null
+++ b/man/mime.types.man
@@ -0,0 +1,102 @@
+.\"
+.\" "$Id: mime.types.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" mime.types man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH mime.types 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NAME
+mime.types \- mime type description file for cups
+.SH DESCRIPTION
+The \fImime.types\fR file defines the recognized file types.
+.LP
+Additional file types can be added to \fImime.types\fR or in additional
+files in the configuration directory \fB/etc/cups\fR with the extension
+".types".
+.LP
+Each line in the \fImime.types\fR file is a comment, blank, or rule
+line. Comment lines start with the # character. Rule lines start with
+the MIME type name and are optionally followed by a series of file
+recognition rules that are used to automatically identify print and web
+files:
+.br
+.nf
+
+ super/type rule [ ... ruleN]
+.fi
+The rules may be grouped using parenthesis, joined using "+" for a
+logical AND and "," or whitespace for a logical OR, and negated using
+"!".
+.SH RULES
+Rules take two forms - a filename extension by itself and functions with test
+values inside parenthesis. The following functions are available:
+.TP 5
+match("pattern")
+.br
+Pattern match on filename
+.TP 5
+ascii(offset,length)
+.br
+True if bytes are valid printable ASCII (CR, NL, TAB, BS, 32-126)
+.TP 5
+printable(offset,length)
+.br
+True if bytes are printable 8-bit chars (CR, NL, TAB, BS, 32-126, 128-254)
+.TP 5
+string(offset,"string")
+.br
+True if bytes are identical to string
+.TP 5
+istring(offset,"string")
+.br
+True if a case-insensitive comparison of the bytes is identical
+.TP 5
+char(offset,value)
+.br
+True if byte is identical
+.TP 5
+short(offset,value)
+.br
+True if 16-bit integer is identical
+.TP 5
+int(offset,value)
+.br
+True if 32-bit integer is identical
+.TP 5
+locale("string")
+.br
+True if current locale matches string
+.TP 5
+contains(offset,range,"string")
+.br
+True if the range contains the string
+.SH STRING CONSTANTS
+String constants can be specified inside quotes ("") for strings
+containing whitespace and angle brackets (<>) for hexadecimal
+strings.
+.SH SEE ALSO
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), printers.conf(5),
+CUPS Software Administrators Manual,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: mime.types.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/man/printers.conf.man b/man/printers.conf.man
new file mode 100644
index 000000000..e164d4347
--- /dev/null
+++ b/man/printers.conf.man
@@ -0,0 +1,73 @@
+.\"
+.\" "$Id: printers.conf.man 4354 2004-08-11 13:48:15Z mike $"
+.\"
+.\" printers.conf man page for the Common UNIX Printing System (CUPS).
+.\"
+.\" Copyright 1997-2004 by Easy Software Products.
+.\"
+.\" These coded instructions, statements, and computer programs are the
+.\" property of Easy Software Products and are protected by Federal
+.\" copyright law. Distribution and use rights are outlined in the file
+.\" "LICENSE.txt" which should have been included with this file. If this
+.\" file is missing or damaged please contact Easy Software Products
+.\" at:
+.\"
+.\" Attn: CUPS Licensing Information
+.\" Easy Software Products
+.\" 44141 Airport View Drive, Suite 204
+.\" Hollywood, Maryland 20636-3142 USA
+.\"
+.\" Voice: (301) 373-9600
+.\" EMail: cups-info@cups.org
+.\" WWW: http://www.cups.org
+.\"
+.TH printers.conf 5 "Common UNIX Printing System" "22 June 2000" "Easy Software Products"
+.SH NAME
+printers.conf \- printer configuration file for cups
+.SH DESCRIPTION
+The \fIprinters.conf\fR file defines the local printers that are
+available. It is normally located in the \fI/etc/cups\fR directory and
+is generated automatically by the \fIcupsd(8)\fR program when printers
+are added or deleted.
+.LP
+Each line in the file can be a configuration directive, a blank line,
+or a comment. Comment lines start with the # character.
+.SH DIRECTIVES
+.TP 5
+Accepting
+.br
+Specifies whether or not the printer is accepting new jobs.
+.TP 5
+Info
+.br
+Specifies human-readable text describing the printer.
+.TP 5
+Location
+.br
+Specifies human-readable text describing the location of the printer.
+.TP 5
+DeviceURI
+.br
+Specifies the device URI for a printer.
+.TP 5
+<Printer name> ... </Printer>
+.br
+Defines a specific printer.
+.TP 5
+State
+.br
+Specifies the initial state of the printer (Idle or Stopped)
+.TP 5
+StateMessage
+.br
+Specifies the message associated with the state.
+.SH SEE ALSO
+classes.conf(5), cupsd(8), cupsd.conf(5), mime.convs(5), mime.types(5),
+CUPS Software Administrators Manual,
+CUPS Interface Design Description,
+http://localhost:631/documentation.html
+.SH COPYRIGHT
+Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+.\"
+.\" End of "$Id: printers.conf.man 4354 2004-08-11 13:48:15Z mike $".
+.\"
diff --git a/pdftops/.cvsignore b/pdftops/.cvsignore
new file mode 100644
index 000000000..3c3f724b2
--- /dev/null
+++ b/pdftops/.cvsignore
@@ -0,0 +1 @@
+pdftops
diff --git a/pdftops/Annot.cxx b/pdftops/Annot.cxx
new file mode 100644
index 000000000..10bfd6c5b
--- /dev/null
+++ b/pdftops/Annot.cxx
@@ -0,0 +1,134 @@
+//========================================================================
+//
+// Annot.cc
+//
+// Copyright 2000-2002 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "Object.h"
+#include "Gfx.h"
+#include "Annot.h"
+
+//------------------------------------------------------------------------
+// Annot
+//------------------------------------------------------------------------
+
+Annot::Annot(XRef *xrefA, Dict *dict) {
+ Object apObj, asObj, obj1, obj2;
+ double t;
+
+ ok = gFalse;
+ xref = xrefA;
+
+ if (dict->lookup("AP", &apObj)->isDict()) {
+ if (dict->lookup("AS", &asObj)->isName()) {
+ if (apObj.dictLookup("N", &obj1)->isDict()) {
+ if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
+ obj2.copy(&appearance);
+ ok = gTrue;
+ }
+ obj2.free();
+ }
+ obj1.free();
+ } else {
+ if (apObj.dictLookupNF("N", &obj1)->isRef()) {
+ obj1.copy(&appearance);
+ ok = gTrue;
+ }
+ obj1.free();
+ }
+ asObj.free();
+ }
+ apObj.free();
+
+ if (dict->lookup("Rect", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ //~ should check object types here
+ obj1.arrayGet(0, &obj2);
+ xMin = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ yMin = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ xMax = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ yMax = obj2.getNum();
+ obj2.free();
+ if (xMin > xMax) {
+ t = xMin; xMin = xMax; xMax = t;
+ }
+ if (yMin > yMax) {
+ t = yMin; yMin = yMax; yMax = t;
+ }
+ } else {
+ //~ this should return an error
+ xMin = yMin = 0;
+ xMax = yMax = 1;
+ }
+ obj1.free();
+}
+
+Annot::~Annot() {
+ appearance.free();
+}
+
+void Annot::draw(Gfx *gfx) {
+ Object obj;
+
+ if (appearance.fetch(xref, &obj)->isStream()) {
+ gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
+ }
+ obj.free();
+}
+
+//------------------------------------------------------------------------
+// Annots
+//------------------------------------------------------------------------
+
+Annots::Annots(XRef *xref, Object *annotsObj) {
+ Annot *annot;
+ Object obj1;
+ int size;
+ int i;
+
+ annots = NULL;
+ size = 0;
+ nAnnots = 0;
+
+ if (annotsObj->isArray()) {
+ for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
+ if (annotsObj->arrayGet(i, &obj1)->isDict()) {
+ annot = new Annot(xref, obj1.getDict());
+ if (annot->isOk()) {
+ if (nAnnots >= size) {
+ size += 16;
+ annots = (Annot **)grealloc(annots, size * sizeof(Annot *));
+ }
+ annots[nAnnots++] = annot;
+ } else {
+ delete annot;
+ }
+ }
+ obj1.free();
+ }
+ }
+}
+
+Annots::~Annots() {
+ int i;
+
+ for (i = 0; i < nAnnots; ++i) {
+ delete annots[i];
+ }
+ gfree(annots);
+}
diff --git a/pdftops/Annot.h b/pdftops/Annot.h
new file mode 100644
index 000000000..b82eb1f06
--- /dev/null
+++ b/pdftops/Annot.h
@@ -0,0 +1,69 @@
+//========================================================================
+//
+// Annot.h
+//
+// Copyright 2000-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef ANNOT_H
+#define ANNOT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+class XRef;
+class Gfx;
+
+//------------------------------------------------------------------------
+// Annot
+//------------------------------------------------------------------------
+
+class Annot {
+public:
+
+ Annot(XRef *xrefA, Dict *dict);
+ ~Annot();
+ GBool isOk() { return ok; }
+
+ void draw(Gfx *gfx);
+
+ // Get appearance object.
+ Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ Object appearance; // a reference to the Form XObject stream
+ // for the normal appearance
+ double xMin, yMin, // annotation rectangle
+ xMax, yMax;
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// Annots
+//------------------------------------------------------------------------
+
+class Annots {
+public:
+
+ // Extract non-link annotations from array of annotations.
+ Annots(XRef *xref, Object *annotsObj);
+
+ ~Annots();
+
+ // Iterate through list of annotations.
+ int getNumAnnots() { return nAnnots; }
+ Annot *getAnnot(int i) { return annots[i]; }
+
+private:
+
+ Annot **annots;
+ int nAnnots;
+};
+
+#endif
diff --git a/pdftops/Array.cxx b/pdftops/Array.cxx
new file mode 100644
index 000000000..f665773b1
--- /dev/null
+++ b/pdftops/Array.cxx
@@ -0,0 +1,73 @@
+//========================================================================
+//
+// Array.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include "gmem.h"
+#include "Object.h"
+#include "Array.h"
+
+//------------------------------------------------------------------------
+// Array
+//------------------------------------------------------------------------
+
+Array::Array(XRef *xrefA) {
+ xref = xrefA;
+ elems = NULL;
+ size = length = 0;
+ ref = 1;
+}
+
+Array::~Array() {
+ int i;
+
+ for (i = 0; i < length; ++i)
+ elems[i].free();
+ gfree(elems);
+}
+
+void Array::add(Object *elem) {
+ if (length == size) {
+ if (length == 0) {
+ size = 8;
+ } else {
+ size *= 2;
+ }
+ elems = (Object *)grealloc(elems, size * sizeof(Object));
+ }
+ elems[length] = *elem;
+ ++length;
+}
+
+Object *Array::get(int i, Object *obj) {
+ if (i < 0 || i >= length) {
+#ifdef DEBUG_MEM
+ abort();
+#else
+ return obj->initNull();
+#endif
+ }
+ return elems[i].fetch(xref, obj);
+}
+
+Object *Array::getNF(int i, Object *obj) {
+ if (i < 0 || i >= length) {
+#ifdef DEBUG_MEM
+ abort();
+#else
+ return obj->initNull();
+#endif
+ }
+ return elems[i].copy(obj);
+}
diff --git a/pdftops/Array.h b/pdftops/Array.h
new file mode 100644
index 000000000..d369e8143
--- /dev/null
+++ b/pdftops/Array.h
@@ -0,0 +1,58 @@
+//========================================================================
+//
+// Array.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+
+class XRef;
+
+//------------------------------------------------------------------------
+// Array
+//------------------------------------------------------------------------
+
+class Array {
+public:
+
+ // Constructor.
+ Array(XRef *xrefA);
+
+ // Destructor.
+ ~Array();
+
+ // Reference counting.
+ int incRef() { return ++ref; }
+ int decRef() { return --ref; }
+
+ // Get number of elements.
+ int getLength() { return length; }
+
+ // Add an element.
+ void add(Object *elem);
+
+ // Accessors.
+ Object *get(int i, Object *obj);
+ Object *getNF(int i, Object *obj);
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ Object *elems; // array of elements
+ int size; // size of <elems> array
+ int length; // number of elements in array
+ int ref; // reference count
+};
+
+#endif
diff --git a/pdftops/BuiltinFont.cxx b/pdftops/BuiltinFont.cxx
new file mode 100644
index 000000000..415281230
--- /dev/null
+++ b/pdftops/BuiltinFont.cxx
@@ -0,0 +1,65 @@
+//========================================================================
+//
+// BuiltinFont.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "gmem.h"
+#include "FontEncodingTables.h"
+#include "BuiltinFont.h"
+
+//------------------------------------------------------------------------
+
+BuiltinFontWidths::BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA) {
+ int i, h;
+
+ size = sizeA;
+ tab = (BuiltinFontWidth **)gmalloc(size * sizeof(BuiltinFontWidth *));
+ for (i = 0; i < size; ++i) {
+ tab[i] = NULL;
+ }
+ for (i = 0; i < sizeA; ++i) {
+ h = hash(widths[i].name);
+ widths[i].next = tab[h];
+ tab[h] = &widths[i];
+ }
+}
+
+BuiltinFontWidths::~BuiltinFontWidths() {
+ gfree(tab);
+}
+
+GBool BuiltinFontWidths::getWidth(const char *name, Gushort *width) {
+ int h;
+ BuiltinFontWidth *p;
+
+ h = hash(name);
+ for (p = tab[h]; p; p = p->next) {
+ if (!strcmp(p->name, name)) {
+ *width = p->width;
+ return gTrue;
+ }
+ }
+ return gFalse;
+}
+
+int BuiltinFontWidths::hash(const char *name) {
+ const char *p;
+ unsigned int h;
+
+ h = 0;
+ for (p = name; *p; ++p) {
+ h = 17 * h + (int)(*p & 0xff);
+ }
+ return (int)(h % size);
+}
diff --git a/pdftops/BuiltinFont.h b/pdftops/BuiltinFont.h
new file mode 100644
index 000000000..3bae15db5
--- /dev/null
+++ b/pdftops/BuiltinFont.h
@@ -0,0 +1,57 @@
+//========================================================================
+//
+// BuiltinFont.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef BUILTINFONT_H
+#define BUILTINFONT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+struct BuiltinFont;
+class BuiltinFontWidths;
+
+//------------------------------------------------------------------------
+
+struct BuiltinFont {
+ const char *name;
+ const char **defaultBaseEnc;
+ short ascent;
+ short descent;
+ short bbox[4];
+ BuiltinFontWidths *widths;
+};
+
+//------------------------------------------------------------------------
+
+struct BuiltinFontWidth {
+ const char *name;
+ Gushort width;
+ BuiltinFontWidth *next;
+};
+
+class BuiltinFontWidths {
+public:
+
+ BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA);
+ ~BuiltinFontWidths();
+ GBool getWidth(const char *name, Gushort *width);
+
+private:
+
+ int hash(const char *name);
+
+ BuiltinFontWidth **tab;
+ int size;
+};
+
+#endif
diff --git a/pdftops/BuiltinFontTables.cxx b/pdftops/BuiltinFontTables.cxx
new file mode 100644
index 000000000..5115b7bcf
--- /dev/null
+++ b/pdftops/BuiltinFontTables.cxx
@@ -0,0 +1,4284 @@
+//========================================================================
+//
+// BuiltinFontTables.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+#include <stdlib.h>
+#include "FontEncodingTables.h"
+#include "BuiltinFontTables.h"
+
+static BuiltinFontWidth courierWidthsTab[] = {
+ { "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
+ { "comma", 600, NULL },
+ { "cedilla", 600, NULL },
+ { "plusminus", 600, NULL },
+ { "circumflex", 600, NULL },
+ { "dotaccent", 600, NULL },
+ { "edotaccent", 600, NULL },
+ { "asciitilde", 600, NULL },
+ { "colon", 600, NULL },
+ { "onehalf", 600, NULL },
+ { "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
+ { "ntilde", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
+ { "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
+ { "yen", 600, NULL },
+ { "space", 600, NULL },
+ { "Omacron", 600, NULL },
+ { "questiondown", 600, NULL },
+ { "emdash", 600, NULL },
+ { "Agrave", 600, NULL },
+ { "three", 600, NULL },
+ { "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
+ { "A", 600, NULL },
+ { "B", 600, NULL },
+ { "C", 600, NULL },
+ { "aogonek", 600, NULL },
+ { "D", 600, NULL },
+ { "E", 600, NULL },
+ { "onequarter", 600, NULL },
+ { "F", 600, NULL },
+ { "G", 600, NULL },
+ { "H", 600, NULL },
+ { "I", 600, NULL },
+ { "J", 600, NULL },
+ { "K", 600, NULL },
+ { "iogonek", 600, NULL },
+ { "L", 600, NULL },
+ { "backslash", 600, NULL },
+ { "periodcentered", 600, NULL },
+ { "M", 600, NULL },
+ { "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
+ { "O", 600, NULL },
+ { "P", 600, NULL },
+ { "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
+ { "R", 600, NULL },
+ { "Aacute", 600, NULL },
+ { "caron", 600, NULL },
+ { "S", 600, NULL },
+ { "T", 600, NULL },
+ { "U", 600, NULL },
+ { "agrave", 600, NULL },
+ { "V", 600, NULL },
+ { "W", 600, NULL },
+ { "equal", 600, NULL },
+ { "question", 600, NULL },
+ { "X", 600, NULL },
+ { "Y", 600, NULL },
+ { "Z", 600, NULL },
+ { "four", 600, NULL },
+ { "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
+ { "b", 600, NULL },
+ { "c", 600, NULL },
+ { "d", 600, NULL },
+ { "e", 600, NULL },
+ { "f", 600, NULL },
+ { "g", 600, NULL },
+ { "bullet", 600, NULL },
+ { "h", 600, NULL },
+ { "i", 600, NULL },
+ { "Oslash", 600, NULL },
+ { "dagger", 600, NULL },
+ { "j", 600, NULL },
+ { "k", 600, NULL },
+ { "l", 600, NULL },
+ { "m", 600, NULL },
+ { "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
+ { "o", 600, NULL },
+ { "ordfeminine", 600, NULL },
+ { "ring", 600, NULL },
+ { "p", 600, NULL },
+ { "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
+ { "r", 600, NULL },
+ { "twosuperior", 600, NULL },
+ { "aacute", 600, NULL },
+ { "s", 600, NULL },
+ { "OE", 600, NULL },
+ { "t", 600, NULL },
+ { "divide", 600, NULL },
+ { "u", 600, NULL },
+ { "Ccaron", 600, NULL },
+ { "v", 600, NULL },
+ { "w", 600, NULL },
+ { "x", 600, NULL },
+ { "y", 600, NULL },
+ { "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
+ { "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
+ { "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
+ { "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
+ { "Scaron", 600, NULL },
+ { "Lslash", 600, NULL },
+ { "semicolon", 600, NULL },
+ { "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
+ { "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
+ { "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
+ { "trademark", 600, NULL },
+ { "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
+ { "macron", 600, NULL },
+ { "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
+ { "ellipsis", 600, NULL },
+ { "scaron", 600, NULL },
+ { "AE", 600, NULL },
+ { "Ucircumflex", 600, NULL },
+ { "lslash", 600, NULL },
+ { "quotedblleft", 600, NULL },
+ { "hyphen", 600, NULL },
+ { "guilsinglright", 600, NULL },
+ { "quotesingle", 600, NULL },
+ { "eight", 600, NULL },
+ { "exclamdown", 600, NULL },
+ { "endash", 600, NULL },
+ { "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
+ { "ecircumflex", 600, NULL },
+ { "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
+ { "Egrave", 600, NULL },
+ { "slash", 600, NULL },
+ { "Edieresis", 600, NULL },
+ { "otilde", 600, NULL },
+ { "Idieresis", 600, NULL },
+ { "parenleft", 600, NULL },
+ { "one", 600, NULL },
+ { "emacron", 600, NULL },
+ { "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
+ { "bracketleft", 600, NULL },
+ { "Ugrave", 600, NULL },
+ { "quoteright", 600, NULL },
+ { "Udieresis", 600, NULL },
+ { "perthousand", 600, NULL },
+ { "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
+ { "Eacute", 600, NULL },
+ { "adieresis", 600, NULL },
+ { "egrave", 600, NULL },
+ { "edieresis", 600, NULL },
+ { "idieresis", 600, NULL },
+ { "Eth", 600, NULL },
+ { "ae", 600, NULL },
+ { "asterisk", 600, NULL },
+ { "odieresis", 600, NULL },
+ { "Uacute", 600, NULL },
+ { "ugrave", 600, NULL },
+ { "five", 600, NULL },
+ { "nine", 600, NULL },
+ { "udieresis", 600, NULL },
+ { "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
+ { "threequarters", 600, NULL },
+ { "guillemotright", 600, NULL },
+ { "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
+ { "tilde", 600, NULL },
+ { "at", 600, NULL },
+ { "eacute", 600, NULL },
+ { "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
+ { "zero", 600, NULL },
+ { "multiply", 600, NULL },
+ { "eth", 600, NULL },
+ { "Scedilla", 600, NULL },
+ { "Racute", 600, NULL },
+ { "Ograve", 600, NULL },
+ { "partialdiff", 600, NULL },
+ { "uacute", 600, NULL },
+ { "braceleft", 600, NULL },
+ { "Thorn", 600, NULL },
+ { "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
+ { "ccedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
+ { "scedilla", 600, NULL },
+ { "Oacute", 600, NULL },
+ { "Ocircumflex", 600, NULL },
+ { "ogonek", 600, NULL },
+ { "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
+ { "thorn", 600, NULL },
+ { "degree", 600, NULL },
+ { "registered", 600, NULL },
+ { "radical", 600, NULL },
+ { "Aring", 600, NULL },
+ { "percent", 600, NULL },
+ { "six", 600, NULL },
+ { "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
+ { "two", 600, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
+ { "ocircumflex", 600, NULL },
+ { "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
+ { "asciicircum", 600, NULL },
+ { "aring", 600, NULL },
+ { "grave", 600, NULL },
+ { "uogonek", 600, NULL },
+ { "bracketright", 600, NULL },
+ { "ampersand", 600, NULL },
+ { "Iacute", 600, NULL },
+ { "lacute", 600, NULL },
+ { "igrave", 600, NULL },
+ { "Ncaron", 600, NULL },
+ { "plus", 600, NULL },
+ { "uring", 600, NULL },
+ { "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
+ { "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
+ { "threesuperior", 600, NULL },
+ { "acute", 600, NULL },
+ { "section", 600, NULL },
+ { "dieresis", 600, NULL },
+ { "quotedblbase", 600, NULL },
+ { "iacute", 600, NULL },
+ { "ncaron", 600, NULL },
+ { "florin", 600, NULL },
+ { "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
+ { "fi", 600, NULL },
+ { "fl", 600, NULL },
+ { "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
+ { "Icircumflex", 600, NULL },
+ { "guillemotleft", 600, NULL },
+ { "germandbls", 600, NULL },
+ { "seven", 600, NULL },
+ { "Amacron", 600, NULL },
+ { "Sacute", 600, NULL },
+ { "ordmasculine", 600, NULL },
+ { "dotlessi", 600, NULL },
+ { "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
+ { "acircumflex", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
+ { "braceright", 600, NULL },
+ { "icircumflex", 600, NULL },
+ { "quotedblright", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
+ { "cent", 600, NULL },
+ { "currency", 600, NULL },
+ { "logicalnot", 600, NULL },
+ { "zdotaccent", 600, NULL },
+ { "Atilde", 600, NULL },
+ { "breve", 600, NULL },
+ { "bar", 600, NULL },
+ { "fraction", 600, NULL },
+ { "less", 600, NULL },
+ { "ecaron", 600, NULL },
+ { "guilsinglleft", 600, NULL },
+ { "exclam", 600, NULL },
+ { "period", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
+ { "greater", 600, NULL },
+ { "atilde", 600, NULL },
+ { "brokenbar", 600, NULL },
+ { "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
+ { "onesuperior", 600, NULL }
+};
+
+static BuiltinFontWidth courierBoldWidthsTab[] = {
+ { "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
+ { "comma", 600, NULL },
+ { "cedilla", 600, NULL },
+ { "plusminus", 600, NULL },
+ { "circumflex", 600, NULL },
+ { "dotaccent", 600, NULL },
+ { "edotaccent", 600, NULL },
+ { "asciitilde", 600, NULL },
+ { "colon", 600, NULL },
+ { "onehalf", 600, NULL },
+ { "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
+ { "ntilde", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
+ { "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
+ { "yen", 600, NULL },
+ { "space", 600, NULL },
+ { "Omacron", 600, NULL },
+ { "questiondown", 600, NULL },
+ { "emdash", 600, NULL },
+ { "Agrave", 600, NULL },
+ { "three", 600, NULL },
+ { "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
+ { "A", 600, NULL },
+ { "B", 600, NULL },
+ { "C", 600, NULL },
+ { "aogonek", 600, NULL },
+ { "D", 600, NULL },
+ { "E", 600, NULL },
+ { "onequarter", 600, NULL },
+ { "F", 600, NULL },
+ { "G", 600, NULL },
+ { "H", 600, NULL },
+ { "I", 600, NULL },
+ { "J", 600, NULL },
+ { "K", 600, NULL },
+ { "iogonek", 600, NULL },
+ { "backslash", 600, NULL },
+ { "L", 600, NULL },
+ { "periodcentered", 600, NULL },
+ { "M", 600, NULL },
+ { "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
+ { "O", 600, NULL },
+ { "P", 600, NULL },
+ { "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
+ { "R", 600, NULL },
+ { "Aacute", 600, NULL },
+ { "caron", 600, NULL },
+ { "S", 600, NULL },
+ { "T", 600, NULL },
+ { "U", 600, NULL },
+ { "agrave", 600, NULL },
+ { "V", 600, NULL },
+ { "W", 600, NULL },
+ { "X", 600, NULL },
+ { "question", 600, NULL },
+ { "equal", 600, NULL },
+ { "Y", 600, NULL },
+ { "Z", 600, NULL },
+ { "four", 600, NULL },
+ { "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
+ { "b", 600, NULL },
+ { "c", 600, NULL },
+ { "d", 600, NULL },
+ { "e", 600, NULL },
+ { "f", 600, NULL },
+ { "g", 600, NULL },
+ { "bullet", 600, NULL },
+ { "h", 600, NULL },
+ { "i", 600, NULL },
+ { "Oslash", 600, NULL },
+ { "dagger", 600, NULL },
+ { "j", 600, NULL },
+ { "k", 600, NULL },
+ { "l", 600, NULL },
+ { "m", 600, NULL },
+ { "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
+ { "o", 600, NULL },
+ { "ordfeminine", 600, NULL },
+ { "ring", 600, NULL },
+ { "p", 600, NULL },
+ { "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
+ { "r", 600, NULL },
+ { "twosuperior", 600, NULL },
+ { "aacute", 600, NULL },
+ { "s", 600, NULL },
+ { "OE", 600, NULL },
+ { "t", 600, NULL },
+ { "divide", 600, NULL },
+ { "u", 600, NULL },
+ { "Ccaron", 600, NULL },
+ { "v", 600, NULL },
+ { "w", 600, NULL },
+ { "x", 600, NULL },
+ { "y", 600, NULL },
+ { "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
+ { "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
+ { "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
+ { "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
+ { "Scaron", 600, NULL },
+ { "Lslash", 600, NULL },
+ { "semicolon", 600, NULL },
+ { "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
+ { "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
+ { "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
+ { "trademark", 600, NULL },
+ { "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
+ { "macron", 600, NULL },
+ { "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
+ { "ellipsis", 600, NULL },
+ { "scaron", 600, NULL },
+ { "AE", 600, NULL },
+ { "Ucircumflex", 600, NULL },
+ { "lslash", 600, NULL },
+ { "quotedblleft", 600, NULL },
+ { "guilsinglright", 600, NULL },
+ { "hyphen", 600, NULL },
+ { "quotesingle", 600, NULL },
+ { "eight", 600, NULL },
+ { "exclamdown", 600, NULL },
+ { "endash", 600, NULL },
+ { "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
+ { "ecircumflex", 600, NULL },
+ { "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
+ { "Egrave", 600, NULL },
+ { "slash", 600, NULL },
+ { "Edieresis", 600, NULL },
+ { "otilde", 600, NULL },
+ { "Idieresis", 600, NULL },
+ { "parenleft", 600, NULL },
+ { "one", 600, NULL },
+ { "emacron", 600, NULL },
+ { "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
+ { "bracketleft", 600, NULL },
+ { "Ugrave", 600, NULL },
+ { "quoteright", 600, NULL },
+ { "Udieresis", 600, NULL },
+ { "perthousand", 600, NULL },
+ { "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
+ { "Eacute", 600, NULL },
+ { "adieresis", 600, NULL },
+ { "egrave", 600, NULL },
+ { "edieresis", 600, NULL },
+ { "idieresis", 600, NULL },
+ { "Eth", 600, NULL },
+ { "ae", 600, NULL },
+ { "asterisk", 600, NULL },
+ { "odieresis", 600, NULL },
+ { "Uacute", 600, NULL },
+ { "ugrave", 600, NULL },
+ { "nine", 600, NULL },
+ { "five", 600, NULL },
+ { "udieresis", 600, NULL },
+ { "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
+ { "threequarters", 600, NULL },
+ { "guillemotright", 600, NULL },
+ { "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
+ { "tilde", 600, NULL },
+ { "at", 600, NULL },
+ { "eacute", 600, NULL },
+ { "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
+ { "multiply", 600, NULL },
+ { "zero", 600, NULL },
+ { "eth", 600, NULL },
+ { "Scedilla", 600, NULL },
+ { "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
+ { "uacute", 600, NULL },
+ { "braceleft", 600, NULL },
+ { "Thorn", 600, NULL },
+ { "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
+ { "ccedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
+ { "Ocircumflex", 600, NULL },
+ { "Oacute", 600, NULL },
+ { "scedilla", 600, NULL },
+ { "ogonek", 600, NULL },
+ { "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
+ { "thorn", 600, NULL },
+ { "degree", 600, NULL },
+ { "registered", 600, NULL },
+ { "radical", 600, NULL },
+ { "Aring", 600, NULL },
+ { "percent", 600, NULL },
+ { "six", 600, NULL },
+ { "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
+ { "two", 600, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
+ { "ocircumflex", 600, NULL },
+ { "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
+ { "asciicircum", 600, NULL },
+ { "aring", 600, NULL },
+ { "grave", 600, NULL },
+ { "uogonek", 600, NULL },
+ { "bracketright", 600, NULL },
+ { "Iacute", 600, NULL },
+ { "ampersand", 600, NULL },
+ { "igrave", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
+ { "plus", 600, NULL },
+ { "uring", 600, NULL },
+ { "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
+ { "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
+ { "threesuperior", 600, NULL },
+ { "acute", 600, NULL },
+ { "section", 600, NULL },
+ { "dieresis", 600, NULL },
+ { "iacute", 600, NULL },
+ { "quotedblbase", 600, NULL },
+ { "ncaron", 600, NULL },
+ { "florin", 600, NULL },
+ { "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
+ { "fi", 600, NULL },
+ { "fl", 600, NULL },
+ { "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
+ { "Icircumflex", 600, NULL },
+ { "guillemotleft", 600, NULL },
+ { "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
+ { "seven", 600, NULL },
+ { "Sacute", 600, NULL },
+ { "ordmasculine", 600, NULL },
+ { "dotlessi", 600, NULL },
+ { "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
+ { "acircumflex", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
+ { "icircumflex", 600, NULL },
+ { "braceright", 600, NULL },
+ { "quotedblright", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
+ { "cent", 600, NULL },
+ { "currency", 600, NULL },
+ { "logicalnot", 600, NULL },
+ { "zdotaccent", 600, NULL },
+ { "Atilde", 600, NULL },
+ { "breve", 600, NULL },
+ { "bar", 600, NULL },
+ { "fraction", 600, NULL },
+ { "less", 600, NULL },
+ { "ecaron", 600, NULL },
+ { "guilsinglleft", 600, NULL },
+ { "exclam", 600, NULL },
+ { "period", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
+ { "greater", 600, NULL },
+ { "atilde", 600, NULL },
+ { "brokenbar", 600, NULL },
+ { "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
+ { "onesuperior", 600, NULL }
+};
+
+static BuiltinFontWidth courierBoldObliqueWidthsTab[] = {
+ { "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
+ { "comma", 600, NULL },
+ { "cedilla", 600, NULL },
+ { "plusminus", 600, NULL },
+ { "circumflex", 600, NULL },
+ { "dotaccent", 600, NULL },
+ { "edotaccent", 600, NULL },
+ { "asciitilde", 600, NULL },
+ { "colon", 600, NULL },
+ { "onehalf", 600, NULL },
+ { "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
+ { "ntilde", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
+ { "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
+ { "yen", 600, NULL },
+ { "space", 600, NULL },
+ { "Omacron", 600, NULL },
+ { "questiondown", 600, NULL },
+ { "emdash", 600, NULL },
+ { "Agrave", 600, NULL },
+ { "three", 600, NULL },
+ { "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
+ { "A", 600, NULL },
+ { "B", 600, NULL },
+ { "C", 600, NULL },
+ { "aogonek", 600, NULL },
+ { "D", 600, NULL },
+ { "E", 600, NULL },
+ { "onequarter", 600, NULL },
+ { "F", 600, NULL },
+ { "G", 600, NULL },
+ { "H", 600, NULL },
+ { "I", 600, NULL },
+ { "J", 600, NULL },
+ { "K", 600, NULL },
+ { "iogonek", 600, NULL },
+ { "backslash", 600, NULL },
+ { "L", 600, NULL },
+ { "periodcentered", 600, NULL },
+ { "M", 600, NULL },
+ { "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
+ { "O", 600, NULL },
+ { "P", 600, NULL },
+ { "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
+ { "R", 600, NULL },
+ { "Aacute", 600, NULL },
+ { "caron", 600, NULL },
+ { "S", 600, NULL },
+ { "T", 600, NULL },
+ { "U", 600, NULL },
+ { "agrave", 600, NULL },
+ { "V", 600, NULL },
+ { "W", 600, NULL },
+ { "X", 600, NULL },
+ { "question", 600, NULL },
+ { "equal", 600, NULL },
+ { "Y", 600, NULL },
+ { "Z", 600, NULL },
+ { "four", 600, NULL },
+ { "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
+ { "b", 600, NULL },
+ { "c", 600, NULL },
+ { "d", 600, NULL },
+ { "e", 600, NULL },
+ { "f", 600, NULL },
+ { "g", 600, NULL },
+ { "bullet", 600, NULL },
+ { "h", 600, NULL },
+ { "i", 600, NULL },
+ { "Oslash", 600, NULL },
+ { "dagger", 600, NULL },
+ { "j", 600, NULL },
+ { "k", 600, NULL },
+ { "l", 600, NULL },
+ { "m", 600, NULL },
+ { "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
+ { "o", 600, NULL },
+ { "ordfeminine", 600, NULL },
+ { "ring", 600, NULL },
+ { "p", 600, NULL },
+ { "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
+ { "r", 600, NULL },
+ { "twosuperior", 600, NULL },
+ { "aacute", 600, NULL },
+ { "s", 600, NULL },
+ { "OE", 600, NULL },
+ { "t", 600, NULL },
+ { "divide", 600, NULL },
+ { "u", 600, NULL },
+ { "Ccaron", 600, NULL },
+ { "v", 600, NULL },
+ { "w", 600, NULL },
+ { "x", 600, NULL },
+ { "y", 600, NULL },
+ { "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
+ { "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
+ { "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
+ { "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
+ { "Scaron", 600, NULL },
+ { "Lslash", 600, NULL },
+ { "semicolon", 600, NULL },
+ { "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
+ { "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
+ { "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
+ { "trademark", 600, NULL },
+ { "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
+ { "macron", 600, NULL },
+ { "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
+ { "ellipsis", 600, NULL },
+ { "scaron", 600, NULL },
+ { "AE", 600, NULL },
+ { "Ucircumflex", 600, NULL },
+ { "lslash", 600, NULL },
+ { "quotedblleft", 600, NULL },
+ { "guilsinglright", 600, NULL },
+ { "hyphen", 600, NULL },
+ { "quotesingle", 600, NULL },
+ { "eight", 600, NULL },
+ { "exclamdown", 600, NULL },
+ { "endash", 600, NULL },
+ { "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
+ { "ecircumflex", 600, NULL },
+ { "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
+ { "Egrave", 600, NULL },
+ { "slash", 600, NULL },
+ { "Edieresis", 600, NULL },
+ { "otilde", 600, NULL },
+ { "Idieresis", 600, NULL },
+ { "parenleft", 600, NULL },
+ { "one", 600, NULL },
+ { "emacron", 600, NULL },
+ { "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
+ { "bracketleft", 600, NULL },
+ { "Ugrave", 600, NULL },
+ { "quoteright", 600, NULL },
+ { "Udieresis", 600, NULL },
+ { "perthousand", 600, NULL },
+ { "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
+ { "Eacute", 600, NULL },
+ { "adieresis", 600, NULL },
+ { "egrave", 600, NULL },
+ { "edieresis", 600, NULL },
+ { "idieresis", 600, NULL },
+ { "Eth", 600, NULL },
+ { "ae", 600, NULL },
+ { "asterisk", 600, NULL },
+ { "odieresis", 600, NULL },
+ { "Uacute", 600, NULL },
+ { "ugrave", 600, NULL },
+ { "nine", 600, NULL },
+ { "five", 600, NULL },
+ { "udieresis", 600, NULL },
+ { "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
+ { "threequarters", 600, NULL },
+ { "guillemotright", 600, NULL },
+ { "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
+ { "tilde", 600, NULL },
+ { "at", 600, NULL },
+ { "eacute", 600, NULL },
+ { "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
+ { "multiply", 600, NULL },
+ { "zero", 600, NULL },
+ { "eth", 600, NULL },
+ { "Scedilla", 600, NULL },
+ { "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
+ { "uacute", 600, NULL },
+ { "braceleft", 600, NULL },
+ { "Thorn", 600, NULL },
+ { "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
+ { "ccedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
+ { "Ocircumflex", 600, NULL },
+ { "Oacute", 600, NULL },
+ { "scedilla", 600, NULL },
+ { "ogonek", 600, NULL },
+ { "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
+ { "thorn", 600, NULL },
+ { "degree", 600, NULL },
+ { "registered", 600, NULL },
+ { "radical", 600, NULL },
+ { "Aring", 600, NULL },
+ { "percent", 600, NULL },
+ { "six", 600, NULL },
+ { "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
+ { "two", 600, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
+ { "ocircumflex", 600, NULL },
+ { "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
+ { "asciicircum", 600, NULL },
+ { "aring", 600, NULL },
+ { "grave", 600, NULL },
+ { "uogonek", 600, NULL },
+ { "bracketright", 600, NULL },
+ { "Iacute", 600, NULL },
+ { "ampersand", 600, NULL },
+ { "igrave", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
+ { "plus", 600, NULL },
+ { "uring", 600, NULL },
+ { "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
+ { "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
+ { "threesuperior", 600, NULL },
+ { "acute", 600, NULL },
+ { "section", 600, NULL },
+ { "dieresis", 600, NULL },
+ { "iacute", 600, NULL },
+ { "quotedblbase", 600, NULL },
+ { "ncaron", 600, NULL },
+ { "florin", 600, NULL },
+ { "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
+ { "fi", 600, NULL },
+ { "fl", 600, NULL },
+ { "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
+ { "Icircumflex", 600, NULL },
+ { "guillemotleft", 600, NULL },
+ { "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
+ { "seven", 600, NULL },
+ { "Sacute", 600, NULL },
+ { "ordmasculine", 600, NULL },
+ { "dotlessi", 600, NULL },
+ { "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
+ { "acircumflex", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
+ { "icircumflex", 600, NULL },
+ { "braceright", 600, NULL },
+ { "quotedblright", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
+ { "cent", 600, NULL },
+ { "currency", 600, NULL },
+ { "logicalnot", 600, NULL },
+ { "zdotaccent", 600, NULL },
+ { "Atilde", 600, NULL },
+ { "breve", 600, NULL },
+ { "bar", 600, NULL },
+ { "fraction", 600, NULL },
+ { "less", 600, NULL },
+ { "ecaron", 600, NULL },
+ { "guilsinglleft", 600, NULL },
+ { "exclam", 600, NULL },
+ { "period", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
+ { "greater", 600, NULL },
+ { "atilde", 600, NULL },
+ { "brokenbar", 600, NULL },
+ { "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
+ { "onesuperior", 600, NULL }
+};
+
+static BuiltinFontWidth courierObliqueWidthsTab[] = {
+ { "Ntilde", 600, NULL },
+ { "rcaron", 600, NULL },
+ { "kcommaaccent", 600, NULL },
+ { "Ncommaaccent", 600, NULL },
+ { "Zacute", 600, NULL },
+ { "comma", 600, NULL },
+ { "cedilla", 600, NULL },
+ { "plusminus", 600, NULL },
+ { "circumflex", 600, NULL },
+ { "dotaccent", 600, NULL },
+ { "edotaccent", 600, NULL },
+ { "asciitilde", 600, NULL },
+ { "colon", 600, NULL },
+ { "onehalf", 600, NULL },
+ { "dollar", 600, NULL },
+ { "Lcaron", 600, NULL },
+ { "ntilde", 600, NULL },
+ { "Aogonek", 600, NULL },
+ { "ncommaaccent", 600, NULL },
+ { "minus", 600, NULL },
+ { "Iogonek", 600, NULL },
+ { "zacute", 600, NULL },
+ { "yen", 600, NULL },
+ { "space", 600, NULL },
+ { "Omacron", 600, NULL },
+ { "questiondown", 600, NULL },
+ { "emdash", 600, NULL },
+ { "Agrave", 600, NULL },
+ { "three", 600, NULL },
+ { "numbersign", 600, NULL },
+ { "lcaron", 600, NULL },
+ { "A", 600, NULL },
+ { "B", 600, NULL },
+ { "C", 600, NULL },
+ { "aogonek", 600, NULL },
+ { "D", 600, NULL },
+ { "E", 600, NULL },
+ { "onequarter", 600, NULL },
+ { "F", 600, NULL },
+ { "G", 600, NULL },
+ { "H", 600, NULL },
+ { "I", 600, NULL },
+ { "J", 600, NULL },
+ { "K", 600, NULL },
+ { "iogonek", 600, NULL },
+ { "backslash", 600, NULL },
+ { "L", 600, NULL },
+ { "periodcentered", 600, NULL },
+ { "M", 600, NULL },
+ { "N", 600, NULL },
+ { "omacron", 600, NULL },
+ { "Tcommaaccent", 600, NULL },
+ { "O", 600, NULL },
+ { "P", 600, NULL },
+ { "Q", 600, NULL },
+ { "Uhungarumlaut", 600, NULL },
+ { "R", 600, NULL },
+ { "Aacute", 600, NULL },
+ { "caron", 600, NULL },
+ { "S", 600, NULL },
+ { "T", 600, NULL },
+ { "U", 600, NULL },
+ { "agrave", 600, NULL },
+ { "V", 600, NULL },
+ { "W", 600, NULL },
+ { "X", 600, NULL },
+ { "question", 600, NULL },
+ { "equal", 600, NULL },
+ { "Y", 600, NULL },
+ { "Z", 600, NULL },
+ { "four", 600, NULL },
+ { "a", 600, NULL },
+ { "Gcommaaccent", 600, NULL },
+ { "b", 600, NULL },
+ { "c", 600, NULL },
+ { "d", 600, NULL },
+ { "e", 600, NULL },
+ { "f", 600, NULL },
+ { "g", 600, NULL },
+ { "bullet", 600, NULL },
+ { "h", 600, NULL },
+ { "i", 600, NULL },
+ { "Oslash", 600, NULL },
+ { "dagger", 600, NULL },
+ { "j", 600, NULL },
+ { "k", 600, NULL },
+ { "l", 600, NULL },
+ { "m", 600, NULL },
+ { "n", 600, NULL },
+ { "tcommaaccent", 600, NULL },
+ { "o", 600, NULL },
+ { "ordfeminine", 600, NULL },
+ { "ring", 600, NULL },
+ { "p", 600, NULL },
+ { "q", 600, NULL },
+ { "uhungarumlaut", 600, NULL },
+ { "r", 600, NULL },
+ { "twosuperior", 600, NULL },
+ { "aacute", 600, NULL },
+ { "s", 600, NULL },
+ { "OE", 600, NULL },
+ { "t", 600, NULL },
+ { "divide", 600, NULL },
+ { "u", 600, NULL },
+ { "Ccaron", 600, NULL },
+ { "v", 600, NULL },
+ { "w", 600, NULL },
+ { "x", 600, NULL },
+ { "y", 600, NULL },
+ { "z", 600, NULL },
+ { "Gbreve", 600, NULL },
+ { "commaaccent", 600, NULL },
+ { "hungarumlaut", 600, NULL },
+ { "Idotaccent", 600, NULL },
+ { "Nacute", 600, NULL },
+ { "quotedbl", 600, NULL },
+ { "gcommaaccent", 600, NULL },
+ { "mu", 600, NULL },
+ { "greaterequal", 600, NULL },
+ { "Scaron", 600, NULL },
+ { "Lslash", 600, NULL },
+ { "semicolon", 600, NULL },
+ { "oslash", 600, NULL },
+ { "lessequal", 600, NULL },
+ { "lozenge", 600, NULL },
+ { "parenright", 600, NULL },
+ { "ccaron", 600, NULL },
+ { "Ecircumflex", 600, NULL },
+ { "gbreve", 600, NULL },
+ { "trademark", 600, NULL },
+ { "daggerdbl", 600, NULL },
+ { "nacute", 600, NULL },
+ { "macron", 600, NULL },
+ { "Otilde", 600, NULL },
+ { "Emacron", 600, NULL },
+ { "ellipsis", 600, NULL },
+ { "scaron", 600, NULL },
+ { "AE", 600, NULL },
+ { "Ucircumflex", 600, NULL },
+ { "lslash", 600, NULL },
+ { "quotedblleft", 600, NULL },
+ { "guilsinglright", 600, NULL },
+ { "hyphen", 600, NULL },
+ { "quotesingle", 600, NULL },
+ { "eight", 600, NULL },
+ { "exclamdown", 600, NULL },
+ { "endash", 600, NULL },
+ { "oe", 600, NULL },
+ { "Abreve", 600, NULL },
+ { "Umacron", 600, NULL },
+ { "ecircumflex", 600, NULL },
+ { "Adieresis", 600, NULL },
+ { "copyright", 600, NULL },
+ { "Egrave", 600, NULL },
+ { "slash", 600, NULL },
+ { "Edieresis", 600, NULL },
+ { "otilde", 600, NULL },
+ { "Idieresis", 600, NULL },
+ { "parenleft", 600, NULL },
+ { "one", 600, NULL },
+ { "emacron", 600, NULL },
+ { "Odieresis", 600, NULL },
+ { "ucircumflex", 600, NULL },
+ { "bracketleft", 600, NULL },
+ { "Ugrave", 600, NULL },
+ { "quoteright", 600, NULL },
+ { "Udieresis", 600, NULL },
+ { "perthousand", 600, NULL },
+ { "Ydieresis", 600, NULL },
+ { "umacron", 600, NULL },
+ { "abreve", 600, NULL },
+ { "Eacute", 600, NULL },
+ { "adieresis", 600, NULL },
+ { "egrave", 600, NULL },
+ { "edieresis", 600, NULL },
+ { "idieresis", 600, NULL },
+ { "Eth", 600, NULL },
+ { "ae", 600, NULL },
+ { "asterisk", 600, NULL },
+ { "odieresis", 600, NULL },
+ { "Uacute", 600, NULL },
+ { "ugrave", 600, NULL },
+ { "nine", 600, NULL },
+ { "five", 600, NULL },
+ { "udieresis", 600, NULL },
+ { "Zcaron", 600, NULL },
+ { "Scommaaccent", 600, NULL },
+ { "threequarters", 600, NULL },
+ { "guillemotright", 600, NULL },
+ { "Ccedilla", 600, NULL },
+ { "ydieresis", 600, NULL },
+ { "tilde", 600, NULL },
+ { "at", 600, NULL },
+ { "eacute", 600, NULL },
+ { "underscore", 600, NULL },
+ { "Euro", 600, NULL },
+ { "Dcroat", 600, NULL },
+ { "multiply", 600, NULL },
+ { "zero", 600, NULL },
+ { "eth", 600, NULL },
+ { "Scedilla", 600, NULL },
+ { "Ograve", 600, NULL },
+ { "Racute", 600, NULL },
+ { "partialdiff", 600, NULL },
+ { "uacute", 600, NULL },
+ { "braceleft", 600, NULL },
+ { "Thorn", 600, NULL },
+ { "zcaron", 600, NULL },
+ { "scommaaccent", 600, NULL },
+ { "ccedilla", 600, NULL },
+ { "Dcaron", 600, NULL },
+ { "dcroat", 600, NULL },
+ { "Ocircumflex", 600, NULL },
+ { "Oacute", 600, NULL },
+ { "scedilla", 600, NULL },
+ { "ogonek", 600, NULL },
+ { "ograve", 600, NULL },
+ { "racute", 600, NULL },
+ { "Tcaron", 600, NULL },
+ { "Eogonek", 600, NULL },
+ { "thorn", 600, NULL },
+ { "degree", 600, NULL },
+ { "registered", 600, NULL },
+ { "radical", 600, NULL },
+ { "Aring", 600, NULL },
+ { "percent", 600, NULL },
+ { "six", 600, NULL },
+ { "paragraph", 600, NULL },
+ { "dcaron", 600, NULL },
+ { "Uogonek", 600, NULL },
+ { "two", 600, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 600, NULL },
+ { "Lacute", 600, NULL },
+ { "ocircumflex", 600, NULL },
+ { "oacute", 600, NULL },
+ { "Uring", 600, NULL },
+ { "Lcommaaccent", 600, NULL },
+ { "tcaron", 600, NULL },
+ { "eogonek", 600, NULL },
+ { "Delta", 600, NULL },
+ { "Ohungarumlaut", 600, NULL },
+ { "asciicircum", 600, NULL },
+ { "aring", 600, NULL },
+ { "grave", 600, NULL },
+ { "uogonek", 600, NULL },
+ { "bracketright", 600, NULL },
+ { "Iacute", 600, NULL },
+ { "ampersand", 600, NULL },
+ { "igrave", 600, NULL },
+ { "lacute", 600, NULL },
+ { "Ncaron", 600, NULL },
+ { "plus", 600, NULL },
+ { "uring", 600, NULL },
+ { "quotesinglbase", 600, NULL },
+ { "lcommaaccent", 600, NULL },
+ { "Yacute", 600, NULL },
+ { "ohungarumlaut", 600, NULL },
+ { "threesuperior", 600, NULL },
+ { "acute", 600, NULL },
+ { "section", 600, NULL },
+ { "dieresis", 600, NULL },
+ { "iacute", 600, NULL },
+ { "quotedblbase", 600, NULL },
+ { "ncaron", 600, NULL },
+ { "florin", 600, NULL },
+ { "yacute", 600, NULL },
+ { "Rcommaaccent", 600, NULL },
+ { "fi", 600, NULL },
+ { "fl", 600, NULL },
+ { "Acircumflex", 600, NULL },
+ { "Cacute", 600, NULL },
+ { "Icircumflex", 600, NULL },
+ { "guillemotleft", 600, NULL },
+ { "germandbls", 600, NULL },
+ { "Amacron", 600, NULL },
+ { "seven", 600, NULL },
+ { "Sacute", 600, NULL },
+ { "ordmasculine", 600, NULL },
+ { "dotlessi", 600, NULL },
+ { "sterling", 600, NULL },
+ { "notequal", 600, NULL },
+ { "Imacron", 600, NULL },
+ { "rcommaaccent", 600, NULL },
+ { "Zdotaccent", 600, NULL },
+ { "acircumflex", 600, NULL },
+ { "cacute", 600, NULL },
+ { "Ecaron", 600, NULL },
+ { "icircumflex", 600, NULL },
+ { "braceright", 600, NULL },
+ { "quotedblright", 600, NULL },
+ { "amacron", 600, NULL },
+ { "sacute", 600, NULL },
+ { "imacron", 600, NULL },
+ { "cent", 600, NULL },
+ { "currency", 600, NULL },
+ { "logicalnot", 600, NULL },
+ { "zdotaccent", 600, NULL },
+ { "Atilde", 600, NULL },
+ { "breve", 600, NULL },
+ { "bar", 600, NULL },
+ { "fraction", 600, NULL },
+ { "less", 600, NULL },
+ { "ecaron", 600, NULL },
+ { "guilsinglleft", 600, NULL },
+ { "exclam", 600, NULL },
+ { "period", 600, NULL },
+ { "Rcaron", 600, NULL },
+ { "Kcommaaccent", 600, NULL },
+ { "greater", 600, NULL },
+ { "atilde", 600, NULL },
+ { "brokenbar", 600, NULL },
+ { "quoteleft", 600, NULL },
+ { "Edotaccent", 600, NULL },
+ { "onesuperior", 600, NULL }
+};
+
+static BuiltinFontWidth helveticaWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 278, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 584, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
+ { "asciitilde", 584, NULL },
+ { "colon", 278, NULL },
+ { "onehalf", 834, NULL },
+ { "dollar", 556, NULL },
+ { "Lcaron", 556, NULL },
+ { "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
+ { "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
+ { "yen", 556, NULL },
+ { "space", 278, NULL },
+ { "Omacron", 778, NULL },
+ { "questiondown", 611, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 667, NULL },
+ { "three", 556, NULL },
+ { "numbersign", 556, NULL },
+ { "lcaron", 299, NULL },
+ { "A", 667, NULL },
+ { "B", 667, NULL },
+ { "C", 722, NULL },
+ { "aogonek", 556, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 834, NULL },
+ { "F", 611, NULL },
+ { "G", 778, NULL },
+ { "H", 722, NULL },
+ { "I", 278, NULL },
+ { "J", 500, NULL },
+ { "K", 667, NULL },
+ { "iogonek", 222, NULL },
+ { "backslash", 278, NULL },
+ { "L", 556, NULL },
+ { "periodcentered", 278, NULL },
+ { "M", 833, NULL },
+ { "N", 722, NULL },
+ { "omacron", 556, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 778, NULL },
+ { "P", 667, NULL },
+ { "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 722, NULL },
+ { "Aacute", 667, NULL },
+ { "caron", 333, NULL },
+ { "S", 667, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 556, NULL },
+ { "V", 667, NULL },
+ { "W", 944, NULL },
+ { "X", 667, NULL },
+ { "question", 556, NULL },
+ { "equal", 584, NULL },
+ { "Y", 667, NULL },
+ { "Z", 611, NULL },
+ { "four", 556, NULL },
+ { "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
+ { "b", 556, NULL },
+ { "c", 500, NULL },
+ { "d", 556, NULL },
+ { "e", 556, NULL },
+ { "f", 278, NULL },
+ { "g", 556, NULL },
+ { "bullet", 350, NULL },
+ { "h", 556, NULL },
+ { "i", 222, NULL },
+ { "Oslash", 778, NULL },
+ { "dagger", 556, NULL },
+ { "j", 222, NULL },
+ { "k", 500, NULL },
+ { "l", 222, NULL },
+ { "m", 833, NULL },
+ { "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
+ { "o", 556, NULL },
+ { "ordfeminine", 370, NULL },
+ { "ring", 333, NULL },
+ { "p", 556, NULL },
+ { "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
+ { "r", 333, NULL },
+ { "twosuperior", 333, NULL },
+ { "aacute", 556, NULL },
+ { "s", 500, NULL },
+ { "OE", 1000, NULL },
+ { "t", 278, NULL },
+ { "divide", 584, NULL },
+ { "u", 556, NULL },
+ { "Ccaron", 722, NULL },
+ { "v", 500, NULL },
+ { "w", 722, NULL },
+ { "x", 500, NULL },
+ { "y", 500, NULL },
+ { "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 355, NULL },
+ { "gcommaaccent", 556, NULL },
+ { "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 667, NULL },
+ { "Lslash", 556, NULL },
+ { "semicolon", 278, NULL },
+ { "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 500, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 556, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 556, NULL },
+ { "nacute", 556, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 500, NULL },
+ { "AE", 1000, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 222, NULL },
+ { "quotedblleft", 333, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 191, NULL },
+ { "eight", 556, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 556, NULL },
+ { "oe", 944, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 556, NULL },
+ { "Adieresis", 667, NULL },
+ { "copyright", 737, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 556, NULL },
+ { "Idieresis", 278, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 556, NULL },
+ { "emacron", 556, NULL },
+ { "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
+ { "bracketleft", 278, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 222, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 667, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 556, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 556, NULL },
+ { "egrave", 556, NULL },
+ { "edieresis", 556, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 889, NULL },
+ { "asterisk", 389, NULL },
+ { "odieresis", 556, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 556, NULL },
+ { "nine", 556, NULL },
+ { "five", 556, NULL },
+ { "udieresis", 556, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
+ { "threequarters", 834, NULL },
+ { "guillemotright", 556, NULL },
+ { "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
+ { "tilde", 333, NULL },
+ { "at", 1015, NULL },
+ { "eacute", 556, NULL },
+ { "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 584, NULL },
+ { "zero", 556, NULL },
+ { "eth", 556, NULL },
+ { "Scedilla", 667, NULL },
+ { "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 476, NULL },
+ { "uacute", 556, NULL },
+ { "braceleft", 334, NULL },
+ { "Thorn", 667, NULL },
+ { "zcaron", 500, NULL },
+ { "scommaaccent", 500, NULL },
+ { "ccedilla", 500, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
+ { "Ocircumflex", 778, NULL },
+ { "Oacute", 778, NULL },
+ { "scedilla", 500, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 556, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 556, NULL },
+ { "degree", 400, NULL },
+ { "registered", 737, NULL },
+ { "radical", 453, NULL },
+ { "Aring", 667, NULL },
+ { "percent", 889, NULL },
+ { "six", 556, NULL },
+ { "paragraph", 537, NULL },
+ { "dcaron", 643, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 556, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 278, NULL },
+ { "Lacute", 556, NULL },
+ { "ocircumflex", 556, NULL },
+ { "oacute", 556, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 317, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
+ { "asciicircum", 469, NULL },
+ { "aring", 556, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 556, NULL },
+ { "bracketright", 278, NULL },
+ { "Iacute", 278, NULL },
+ { "ampersand", 667, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 222, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 584, NULL },
+ { "uring", 556, NULL },
+ { "quotesinglbase", 222, NULL },
+ { "lcommaaccent", 222, NULL },
+ { "Yacute", 667, NULL },
+ { "ohungarumlaut", 556, NULL },
+ { "threesuperior", 333, NULL },
+ { "acute", 333, NULL },
+ { "section", 556, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 333, NULL },
+ { "ncaron", 556, NULL },
+ { "florin", 556, NULL },
+ { "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
+ { "fi", 500, NULL },
+ { "fl", 500, NULL },
+ { "Acircumflex", 667, NULL },
+ { "Cacute", 722, NULL },
+ { "Icircumflex", 278, NULL },
+ { "guillemotleft", 556, NULL },
+ { "germandbls", 611, NULL },
+ { "Amacron", 667, NULL },
+ { "seven", 556, NULL },
+ { "Sacute", 667, NULL },
+ { "ordmasculine", 365, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 556, NULL },
+ { "cacute", 500, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 334, NULL },
+ { "quotedblright", 333, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 500, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 556, NULL },
+ { "currency", 556, NULL },
+ { "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
+ { "Atilde", 667, NULL },
+ { "breve", 333, NULL },
+ { "bar", 260, NULL },
+ { "fraction", 167, NULL },
+ { "less", 584, NULL },
+ { "ecaron", 556, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 278, NULL },
+ { "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 667, NULL },
+ { "greater", 584, NULL },
+ { "atilde", 556, NULL },
+ { "brokenbar", 260, NULL },
+ { "quoteleft", 222, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 333, NULL }
+};
+
+static BuiltinFontWidth helveticaBoldWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 278, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 584, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
+ { "asciitilde", 584, NULL },
+ { "colon", 333, NULL },
+ { "onehalf", 834, NULL },
+ { "dollar", 556, NULL },
+ { "Lcaron", 611, NULL },
+ { "ntilde", 611, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 611, NULL },
+ { "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
+ { "yen", 556, NULL },
+ { "space", 278, NULL },
+ { "Omacron", 778, NULL },
+ { "questiondown", 611, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 722, NULL },
+ { "three", 556, NULL },
+ { "numbersign", 556, NULL },
+ { "lcaron", 400, NULL },
+ { "A", 722, NULL },
+ { "B", 722, NULL },
+ { "C", 722, NULL },
+ { "aogonek", 556, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 834, NULL },
+ { "F", 611, NULL },
+ { "G", 778, NULL },
+ { "H", 722, NULL },
+ { "I", 278, NULL },
+ { "J", 556, NULL },
+ { "K", 722, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 611, NULL },
+ { "periodcentered", 278, NULL },
+ { "M", 833, NULL },
+ { "N", 722, NULL },
+ { "omacron", 611, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 778, NULL },
+ { "P", 667, NULL },
+ { "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 722, NULL },
+ { "Aacute", 722, NULL },
+ { "caron", 333, NULL },
+ { "S", 667, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 556, NULL },
+ { "V", 667, NULL },
+ { "W", 944, NULL },
+ { "X", 667, NULL },
+ { "question", 611, NULL },
+ { "equal", 584, NULL },
+ { "Y", 667, NULL },
+ { "Z", 611, NULL },
+ { "four", 556, NULL },
+ { "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
+ { "b", 611, NULL },
+ { "c", 556, NULL },
+ { "d", 611, NULL },
+ { "e", 556, NULL },
+ { "f", 333, NULL },
+ { "g", 611, NULL },
+ { "bullet", 350, NULL },
+ { "h", 611, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 778, NULL },
+ { "dagger", 556, NULL },
+ { "j", 278, NULL },
+ { "k", 556, NULL },
+ { "l", 278, NULL },
+ { "m", 889, NULL },
+ { "n", 611, NULL },
+ { "tcommaaccent", 333, NULL },
+ { "o", 611, NULL },
+ { "ordfeminine", 370, NULL },
+ { "ring", 333, NULL },
+ { "p", 611, NULL },
+ { "q", 611, NULL },
+ { "uhungarumlaut", 611, NULL },
+ { "r", 389, NULL },
+ { "twosuperior", 333, NULL },
+ { "aacute", 556, NULL },
+ { "s", 556, NULL },
+ { "OE", 1000, NULL },
+ { "t", 333, NULL },
+ { "divide", 584, NULL },
+ { "u", 611, NULL },
+ { "Ccaron", 722, NULL },
+ { "v", 556, NULL },
+ { "w", 778, NULL },
+ { "x", 556, NULL },
+ { "y", 556, NULL },
+ { "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 474, NULL },
+ { "gcommaaccent", 611, NULL },
+ { "mu", 611, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 667, NULL },
+ { "Lslash", 611, NULL },
+ { "semicolon", 333, NULL },
+ { "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 556, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 611, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 556, NULL },
+ { "nacute", 611, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 556, NULL },
+ { "AE", 1000, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 500, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 238, NULL },
+ { "eight", 556, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 556, NULL },
+ { "oe", 944, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 556, NULL },
+ { "Adieresis", 722, NULL },
+ { "copyright", 737, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 611, NULL },
+ { "Idieresis", 278, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 556, NULL },
+ { "emacron", 556, NULL },
+ { "Odieresis", 778, NULL },
+ { "ucircumflex", 611, NULL },
+ { "bracketleft", 333, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 278, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 667, NULL },
+ { "umacron", 611, NULL },
+ { "abreve", 556, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 556, NULL },
+ { "egrave", 556, NULL },
+ { "edieresis", 556, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 889, NULL },
+ { "asterisk", 389, NULL },
+ { "odieresis", 611, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 611, NULL },
+ { "nine", 556, NULL },
+ { "five", 556, NULL },
+ { "udieresis", 611, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
+ { "threequarters", 834, NULL },
+ { "guillemotright", 556, NULL },
+ { "Ccedilla", 722, NULL },
+ { "ydieresis", 556, NULL },
+ { "tilde", 333, NULL },
+ { "dbldaggerumlaut", 556, NULL },
+ { "at", 975, NULL },
+ { "eacute", 556, NULL },
+ { "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 584, NULL },
+ { "zero", 556, NULL },
+ { "eth", 611, NULL },
+ { "Scedilla", 667, NULL },
+ { "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
+ { "uacute", 611, NULL },
+ { "braceleft", 389, NULL },
+ { "Thorn", 667, NULL },
+ { "zcaron", 500, NULL },
+ { "scommaaccent", 556, NULL },
+ { "ccedilla", 556, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 611, NULL },
+ { "Ocircumflex", 778, NULL },
+ { "Oacute", 778, NULL },
+ { "scedilla", 556, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 611, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 611, NULL },
+ { "degree", 400, NULL },
+ { "registered", 737, NULL },
+ { "radical", 549, NULL },
+ { "Aring", 722, NULL },
+ { "percent", 889, NULL },
+ { "six", 556, NULL },
+ { "paragraph", 556, NULL },
+ { "dcaron", 743, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 556, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 278, NULL },
+ { "Lacute", 611, NULL },
+ { "ocircumflex", 611, NULL },
+ { "oacute", 611, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 389, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
+ { "asciicircum", 584, NULL },
+ { "aring", 556, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 611, NULL },
+ { "bracketright", 333, NULL },
+ { "Iacute", 278, NULL },
+ { "ampersand", 722, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 584, NULL },
+ { "uring", 611, NULL },
+ { "quotesinglbase", 278, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 667, NULL },
+ { "ohungarumlaut", 611, NULL },
+ { "threesuperior", 333, NULL },
+ { "acute", 333, NULL },
+ { "section", 556, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 500, NULL },
+ { "ncaron", 611, NULL },
+ { "florin", 556, NULL },
+ { "yacute", 556, NULL },
+ { "Rcommaaccent", 722, NULL },
+ { "fi", 611, NULL },
+ { "fl", 611, NULL },
+ { "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
+ { "Icircumflex", 278, NULL },
+ { "guillemotleft", 556, NULL },
+ { "germandbls", 611, NULL },
+ { "Amacron", 722, NULL },
+ { "seven", 556, NULL },
+ { "Sacute", 667, NULL },
+ { "ordmasculine", 365, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 556, NULL },
+ { "cacute", 556, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 389, NULL },
+ { "quotedblright", 500, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 556, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 556, NULL },
+ { "currency", 556, NULL },
+ { "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
+ { "Atilde", 722, NULL },
+ { "breve", 333, NULL },
+ { "bar", 280, NULL },
+ { "fraction", 167, NULL },
+ { "less", 584, NULL },
+ { "ecaron", 556, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 333, NULL },
+ { "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 722, NULL },
+ { "greater", 584, NULL },
+ { "atilde", 556, NULL },
+ { "brokenbar", 280, NULL },
+ { "quoteleft", 278, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 333, NULL }
+};
+
+static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 278, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 584, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
+ { "asciitilde", 584, NULL },
+ { "colon", 333, NULL },
+ { "onehalf", 834, NULL },
+ { "dollar", 556, NULL },
+ { "Lcaron", 611, NULL },
+ { "ntilde", 611, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 611, NULL },
+ { "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
+ { "yen", 556, NULL },
+ { "space", 278, NULL },
+ { "Omacron", 778, NULL },
+ { "questiondown", 611, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 722, NULL },
+ { "three", 556, NULL },
+ { "numbersign", 556, NULL },
+ { "lcaron", 400, NULL },
+ { "A", 722, NULL },
+ { "B", 722, NULL },
+ { "C", 722, NULL },
+ { "aogonek", 556, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 834, NULL },
+ { "F", 611, NULL },
+ { "G", 778, NULL },
+ { "H", 722, NULL },
+ { "I", 278, NULL },
+ { "J", 556, NULL },
+ { "K", 722, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 611, NULL },
+ { "periodcentered", 278, NULL },
+ { "M", 833, NULL },
+ { "N", 722, NULL },
+ { "omacron", 611, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 778, NULL },
+ { "P", 667, NULL },
+ { "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 722, NULL },
+ { "Aacute", 722, NULL },
+ { "caron", 333, NULL },
+ { "S", 667, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 556, NULL },
+ { "V", 667, NULL },
+ { "W", 944, NULL },
+ { "X", 667, NULL },
+ { "question", 611, NULL },
+ { "equal", 584, NULL },
+ { "Y", 667, NULL },
+ { "Z", 611, NULL },
+ { "four", 556, NULL },
+ { "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
+ { "b", 611, NULL },
+ { "c", 556, NULL },
+ { "d", 611, NULL },
+ { "e", 556, NULL },
+ { "f", 333, NULL },
+ { "g", 611, NULL },
+ { "bullet", 350, NULL },
+ { "h", 611, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 778, NULL },
+ { "dagger", 556, NULL },
+ { "j", 278, NULL },
+ { "k", 556, NULL },
+ { "l", 278, NULL },
+ { "m", 889, NULL },
+ { "n", 611, NULL },
+ { "tcommaaccent", 333, NULL },
+ { "o", 611, NULL },
+ { "ordfeminine", 370, NULL },
+ { "ring", 333, NULL },
+ { "p", 611, NULL },
+ { "q", 611, NULL },
+ { "uhungarumlaut", 611, NULL },
+ { "r", 389, NULL },
+ { "twosuperior", 333, NULL },
+ { "aacute", 556, NULL },
+ { "s", 556, NULL },
+ { "OE", 1000, NULL },
+ { "t", 333, NULL },
+ { "divide", 584, NULL },
+ { "u", 611, NULL },
+ { "Ccaron", 722, NULL },
+ { "v", 556, NULL },
+ { "w", 778, NULL },
+ { "x", 556, NULL },
+ { "y", 556, NULL },
+ { "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 474, NULL },
+ { "gcommaaccent", 611, NULL },
+ { "mu", 611, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 667, NULL },
+ { "Lslash", 611, NULL },
+ { "semicolon", 333, NULL },
+ { "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 556, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 611, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 556, NULL },
+ { "nacute", 611, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 556, NULL },
+ { "AE", 1000, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 500, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 238, NULL },
+ { "eight", 556, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 556, NULL },
+ { "oe", 944, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 556, NULL },
+ { "Adieresis", 722, NULL },
+ { "copyright", 737, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 611, NULL },
+ { "Idieresis", 278, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 556, NULL },
+ { "emacron", 556, NULL },
+ { "Odieresis", 778, NULL },
+ { "ucircumflex", 611, NULL },
+ { "bracketleft", 333, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 278, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 667, NULL },
+ { "umacron", 611, NULL },
+ { "abreve", 556, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 556, NULL },
+ { "egrave", 556, NULL },
+ { "edieresis", 556, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 889, NULL },
+ { "asterisk", 389, NULL },
+ { "odieresis", 611, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 611, NULL },
+ { "nine", 556, NULL },
+ { "five", 556, NULL },
+ { "udieresis", 611, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
+ { "threequarters", 834, NULL },
+ { "guillemotright", 556, NULL },
+ { "Ccedilla", 722, NULL },
+ { "ydieresis", 556, NULL },
+ { "tilde", 333, NULL },
+ { "at", 975, NULL },
+ { "eacute", 556, NULL },
+ { "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 584, NULL },
+ { "zero", 556, NULL },
+ { "eth", 611, NULL },
+ { "Scedilla", 667, NULL },
+ { "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
+ { "uacute", 611, NULL },
+ { "braceleft", 389, NULL },
+ { "Thorn", 667, NULL },
+ { "zcaron", 500, NULL },
+ { "scommaaccent", 556, NULL },
+ { "ccedilla", 556, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 611, NULL },
+ { "Ocircumflex", 778, NULL },
+ { "Oacute", 778, NULL },
+ { "scedilla", 556, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 611, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 611, NULL },
+ { "degree", 400, NULL },
+ { "registered", 737, NULL },
+ { "radical", 549, NULL },
+ { "Aring", 722, NULL },
+ { "percent", 889, NULL },
+ { "six", 556, NULL },
+ { "paragraph", 556, NULL },
+ { "dcaron", 743, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 556, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 278, NULL },
+ { "Lacute", 611, NULL },
+ { "ocircumflex", 611, NULL },
+ { "oacute", 611, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 389, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
+ { "asciicircum", 584, NULL },
+ { "aring", 556, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 611, NULL },
+ { "bracketright", 333, NULL },
+ { "Iacute", 278, NULL },
+ { "ampersand", 722, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 584, NULL },
+ { "uring", 611, NULL },
+ { "quotesinglbase", 278, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 667, NULL },
+ { "ohungarumlaut", 611, NULL },
+ { "threesuperior", 333, NULL },
+ { "acute", 333, NULL },
+ { "section", 556, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 500, NULL },
+ { "ncaron", 611, NULL },
+ { "florin", 556, NULL },
+ { "yacute", 556, NULL },
+ { "Rcommaaccent", 722, NULL },
+ { "fi", 611, NULL },
+ { "fl", 611, NULL },
+ { "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
+ { "Icircumflex", 278, NULL },
+ { "guillemotleft", 556, NULL },
+ { "germandbls", 611, NULL },
+ { "Amacron", 722, NULL },
+ { "seven", 556, NULL },
+ { "Sacute", 667, NULL },
+ { "ordmasculine", 365, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 556, NULL },
+ { "cacute", 556, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 389, NULL },
+ { "quotedblright", 500, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 556, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 556, NULL },
+ { "currency", 556, NULL },
+ { "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
+ { "Atilde", 722, NULL },
+ { "breve", 333, NULL },
+ { "bar", 280, NULL },
+ { "fraction", 167, NULL },
+ { "less", 584, NULL },
+ { "ecaron", 556, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 333, NULL },
+ { "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 722, NULL },
+ { "greater", 584, NULL },
+ { "atilde", 556, NULL },
+ { "brokenbar", 280, NULL },
+ { "quoteleft", 278, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 333, NULL }
+};
+
+static BuiltinFontWidth helveticaObliqueWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 278, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 584, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 556, NULL },
+ { "asciitilde", 584, NULL },
+ { "colon", 278, NULL },
+ { "onehalf", 834, NULL },
+ { "dollar", 556, NULL },
+ { "Lcaron", 556, NULL },
+ { "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
+ { "minus", 584, NULL },
+ { "Iogonek", 278, NULL },
+ { "zacute", 500, NULL },
+ { "yen", 556, NULL },
+ { "space", 278, NULL },
+ { "Omacron", 778, NULL },
+ { "questiondown", 611, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 667, NULL },
+ { "three", 556, NULL },
+ { "numbersign", 556, NULL },
+ { "lcaron", 299, NULL },
+ { "A", 667, NULL },
+ { "B", 667, NULL },
+ { "C", 722, NULL },
+ { "aogonek", 556, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 834, NULL },
+ { "F", 611, NULL },
+ { "G", 778, NULL },
+ { "H", 722, NULL },
+ { "I", 278, NULL },
+ { "J", 500, NULL },
+ { "K", 667, NULL },
+ { "iogonek", 222, NULL },
+ { "backslash", 278, NULL },
+ { "L", 556, NULL },
+ { "periodcentered", 278, NULL },
+ { "M", 833, NULL },
+ { "N", 722, NULL },
+ { "omacron", 556, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 778, NULL },
+ { "P", 667, NULL },
+ { "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 722, NULL },
+ { "Aacute", 667, NULL },
+ { "caron", 333, NULL },
+ { "S", 667, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 556, NULL },
+ { "V", 667, NULL },
+ { "W", 944, NULL },
+ { "X", 667, NULL },
+ { "question", 556, NULL },
+ { "equal", 584, NULL },
+ { "Y", 667, NULL },
+ { "Z", 611, NULL },
+ { "four", 556, NULL },
+ { "a", 556, NULL },
+ { "Gcommaaccent", 778, NULL },
+ { "b", 556, NULL },
+ { "c", 500, NULL },
+ { "d", 556, NULL },
+ { "e", 556, NULL },
+ { "f", 278, NULL },
+ { "g", 556, NULL },
+ { "bullet", 350, NULL },
+ { "h", 556, NULL },
+ { "i", 222, NULL },
+ { "Oslash", 778, NULL },
+ { "dagger", 556, NULL },
+ { "j", 222, NULL },
+ { "k", 500, NULL },
+ { "l", 222, NULL },
+ { "m", 833, NULL },
+ { "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
+ { "o", 556, NULL },
+ { "ordfeminine", 370, NULL },
+ { "ring", 333, NULL },
+ { "p", 556, NULL },
+ { "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
+ { "r", 333, NULL },
+ { "twosuperior", 333, NULL },
+ { "aacute", 556, NULL },
+ { "s", 500, NULL },
+ { "OE", 1000, NULL },
+ { "t", 278, NULL },
+ { "divide", 584, NULL },
+ { "u", 556, NULL },
+ { "Ccaron", 722, NULL },
+ { "v", 500, NULL },
+ { "w", 722, NULL },
+ { "x", 500, NULL },
+ { "y", 500, NULL },
+ { "z", 500, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 278, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 355, NULL },
+ { "gcommaaccent", 556, NULL },
+ { "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 667, NULL },
+ { "Lslash", 556, NULL },
+ { "semicolon", 278, NULL },
+ { "oslash", 611, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 500, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 556, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 556, NULL },
+ { "nacute", 556, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 500, NULL },
+ { "AE", 1000, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 222, NULL },
+ { "quotedblleft", 333, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 191, NULL },
+ { "eight", 556, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 556, NULL },
+ { "oe", 944, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 556, NULL },
+ { "Adieresis", 667, NULL },
+ { "copyright", 737, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 556, NULL },
+ { "Idieresis", 278, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 556, NULL },
+ { "emacron", 556, NULL },
+ { "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
+ { "bracketleft", 278, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 222, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 667, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 556, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 556, NULL },
+ { "egrave", 556, NULL },
+ { "edieresis", 556, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 889, NULL },
+ { "asterisk", 389, NULL },
+ { "odieresis", 556, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 556, NULL },
+ { "nine", 556, NULL },
+ { "five", 556, NULL },
+ { "udieresis", 556, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 667, NULL },
+ { "threequarters", 834, NULL },
+ { "guillemotright", 556, NULL },
+ { "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
+ { "tilde", 333, NULL },
+ { "at", 1015, NULL },
+ { "eacute", 556, NULL },
+ { "underscore", 556, NULL },
+ { "Euro", 556, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 584, NULL },
+ { "zero", 556, NULL },
+ { "eth", 556, NULL },
+ { "Scedilla", 667, NULL },
+ { "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 476, NULL },
+ { "uacute", 556, NULL },
+ { "braceleft", 334, NULL },
+ { "Thorn", 667, NULL },
+ { "zcaron", 500, NULL },
+ { "scommaaccent", 500, NULL },
+ { "ccedilla", 500, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
+ { "Ocircumflex", 778, NULL },
+ { "Oacute", 778, NULL },
+ { "scedilla", 500, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 556, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 556, NULL },
+ { "degree", 400, NULL },
+ { "registered", 737, NULL },
+ { "radical", 453, NULL },
+ { "Aring", 667, NULL },
+ { "percent", 889, NULL },
+ { "six", 556, NULL },
+ { "paragraph", 537, NULL },
+ { "dcaron", 643, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 556, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 278, NULL },
+ { "Lacute", 556, NULL },
+ { "ocircumflex", 556, NULL },
+ { "oacute", 556, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 317, NULL },
+ { "eogonek", 556, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
+ { "asciicircum", 469, NULL },
+ { "aring", 556, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 556, NULL },
+ { "bracketright", 278, NULL },
+ { "Iacute", 278, NULL },
+ { "ampersand", 667, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 222, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 584, NULL },
+ { "uring", 556, NULL },
+ { "quotesinglbase", 222, NULL },
+ { "lcommaaccent", 222, NULL },
+ { "Yacute", 667, NULL },
+ { "ohungarumlaut", 556, NULL },
+ { "threesuperior", 333, NULL },
+ { "acute", 333, NULL },
+ { "section", 556, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 333, NULL },
+ { "ncaron", 556, NULL },
+ { "florin", 556, NULL },
+ { "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
+ { "fi", 500, NULL },
+ { "fl", 500, NULL },
+ { "Acircumflex", 667, NULL },
+ { "Cacute", 722, NULL },
+ { "Icircumflex", 278, NULL },
+ { "guillemotleft", 556, NULL },
+ { "germandbls", 611, NULL },
+ { "Amacron", 667, NULL },
+ { "seven", 556, NULL },
+ { "Sacute", 667, NULL },
+ { "ordmasculine", 365, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 556, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 278, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 556, NULL },
+ { "cacute", 500, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 334, NULL },
+ { "quotedblright", 333, NULL },
+ { "amacron", 556, NULL },
+ { "sacute", 500, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 556, NULL },
+ { "currency", 556, NULL },
+ { "logicalnot", 584, NULL },
+ { "zdotaccent", 500, NULL },
+ { "Atilde", 667, NULL },
+ { "breve", 333, NULL },
+ { "bar", 260, NULL },
+ { "fraction", 167, NULL },
+ { "less", 584, NULL },
+ { "ecaron", 556, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 278, NULL },
+ { "period", 278, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 667, NULL },
+ { "greater", 584, NULL },
+ { "atilde", 556, NULL },
+ { "brokenbar", 260, NULL },
+ { "quoteleft", 222, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 333, NULL }
+};
+
+static BuiltinFontWidth symbolWidthsTab[] = {
+ { "bracketleftex", 384, NULL },
+ { "alpha", 631, NULL },
+ { "union", 768, NULL },
+ { "infinity", 713, NULL },
+ { "comma", 250, NULL },
+ { "copyrightsans", 790, NULL },
+ { "plusminus", 549, NULL },
+ { "arrowup", 603, NULL },
+ { "apple", 790, NULL },
+ { "parenleftbt", 384, NULL },
+ { "notelement", 713, NULL },
+ { "colon", 278, NULL },
+ { "beta", 549, NULL },
+ { "braceleftbt", 494, NULL },
+ { "Lambda", 686, NULL },
+ { "Phi", 763, NULL },
+ { "minus", 549, NULL },
+ { "space", 250, NULL },
+ { "Sigma", 592, NULL },
+ { "approxequal", 549, NULL },
+ { "minute", 247, NULL },
+ { "circleplus", 768, NULL },
+ { "Omicron", 722, NULL },
+ { "three", 500, NULL },
+ { "numbersign", 500, NULL },
+ { "lambda", 549, NULL },
+ { "phi", 521, NULL },
+ { "aleph", 823, NULL },
+ { "Tau", 611, NULL },
+ { "spade", 753, NULL },
+ { "logicaland", 603, NULL },
+ { "sigma", 603, NULL },
+ { "propersuperset", 713, NULL },
+ { "omicron", 549, NULL },
+ { "question", 444, NULL },
+ { "equal", 549, NULL },
+ { "Epsilon", 611, NULL },
+ { "emptyset", 823, NULL },
+ { "diamond", 753, NULL },
+ { "four", 500, NULL },
+ { "Mu", 889, NULL },
+ { "parenlefttp", 384, NULL },
+ { "club", 753, NULL },
+ { "bullet", 460, NULL },
+ { "Omega", 768, NULL },
+ { "tau", 439, NULL },
+ { "Upsilon", 690, NULL },
+ { "bracelefttp", 494, NULL },
+ { "heart", 753, NULL },
+ { "divide", 549, NULL },
+ { "epsilon", 439, NULL },
+ { "logicalor", 603, NULL },
+ { "parenleftex", 384, NULL },
+ { "greaterequal", 549, NULL },
+ { "mu", 576, NULL },
+ { "Nu", 722, NULL },
+ { "therefore", 863, NULL },
+ { "notsubset", 713, NULL },
+ { "omega", 686, NULL },
+ { "semicolon", 278, NULL },
+ { "element", 713, NULL },
+ { "upsilon", 576, NULL },
+ { "existential", 549, NULL },
+ { "integralbt", 686, NULL },
+ { "lessequal", 549, NULL },
+ { "phi1", 603, NULL },
+ { "lozenge", 494, NULL },
+ { "trademarkserif", 890, NULL },
+ { "parenright", 333, NULL },
+ { "reflexsuperset", 713, NULL },
+ { "sigma1", 439, NULL },
+ { "nu", 521, NULL },
+ { "Gamma", 603, NULL },
+ { "angleright", 329, NULL },
+ { "ellipsis", 1000, NULL },
+ { "Rho", 556, NULL },
+ { "parenrightbt", 384, NULL },
+ { "radicalex", 500, NULL },
+ { "eight", 500, NULL },
+ { "angleleft", 329, NULL },
+ { "arrowdbldown", 603, NULL },
+ { "congruent", 549, NULL },
+ { "Theta", 741, NULL },
+ { "intersection", 768, NULL },
+ { "Pi", 768, NULL },
+ { "slash", 278, NULL },
+ { "registerserif", 790, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 500, NULL },
+ { "gamma", 411, NULL },
+ { "bracketleft", 333, NULL },
+ { "rho", 549, NULL },
+ { "circlemultiply", 768, NULL },
+ { "Chi", 722, NULL },
+ { "theta", 521, NULL },
+ { "pi", 549, NULL },
+ { "integraltp", 686, NULL },
+ { "Eta", 722, NULL },
+ { "product", 823, NULL },
+ { "nine", 500, NULL },
+ { "five", 500, NULL },
+ { "propersubset", 713, NULL },
+ { "bracketrightbt", 384, NULL },
+ { "trademarksans", 786, NULL },
+ { "dotmath", 250, NULL },
+ { "integralex", 686, NULL },
+ { "chi", 549, NULL },
+ { "parenrighttp", 384, NULL },
+ { "eta", 603, NULL },
+ { "underscore", 500, NULL },
+ { "Euro", 750, NULL },
+ { "multiply", 549, NULL },
+ { "zero", 500, NULL },
+ { "partialdiff", 494, NULL },
+ { "angle", 768, NULL },
+ { "arrowdblleft", 987, NULL },
+ { "braceleft", 480, NULL },
+ { "parenrightex", 384, NULL },
+ { "Rfraktur", 795, NULL },
+ { "Zeta", 611, NULL },
+ { "braceex", 494, NULL },
+ { "arrowdblup", 603, NULL },
+ { "arrowdown", 603, NULL },
+ { "Ifraktur", 686, NULL },
+ { "degree", 400, NULL },
+ { "Iota", 333, NULL },
+ { "perpendicular", 658, NULL },
+ { "radical", 549, NULL },
+ { "asteriskmath", 500, NULL },
+ { "percent", 833, NULL },
+ { "zeta", 494, NULL },
+ { "six", 500, NULL },
+ { "two", 500, NULL },
+ { "weierstrass", 987, NULL },
+ { "summation", 713, NULL },
+ { "bracketrighttp", 384, NULL },
+ { "carriagereturn", 658, NULL },
+ { "suchthat", 439, NULL },
+ { "arrowvertex", 603, NULL },
+ { "Delta", 612, NULL },
+ { "iota", 329, NULL },
+ { "arrowhorizex", 1000, NULL },
+ { "bracketrightex", 384, NULL },
+ { "bracketright", 333, NULL },
+ { "ampersand", 778, NULL },
+ { "plus", 549, NULL },
+ { "proportional", 713, NULL },
+ { "delta", 494, NULL },
+ { "copyrightserif", 790, NULL },
+ { "bracerightmid", 494, NULL },
+ { "arrowleft", 987, NULL },
+ { "second", 411, NULL },
+ { "arrowdblboth", 1042, NULL },
+ { "florin", 500, NULL },
+ { "Psi", 795, NULL },
+ { "bracerightbt", 494, NULL },
+ { "bracketleftbt", 384, NULL },
+ { "seven", 500, NULL },
+ { "braceleftmid", 494, NULL },
+ { "notequal", 549, NULL },
+ { "psi", 686, NULL },
+ { "equivalence", 549, NULL },
+ { "universal", 713, NULL },
+ { "arrowdblright", 987, NULL },
+ { "braceright", 480, NULL },
+ { "reflexsubset", 713, NULL },
+ { "Xi", 645, NULL },
+ { "theta1", 631, NULL },
+ { "logicalnot", 713, NULL },
+ { "Kappa", 722, NULL },
+ { "similar", 549, NULL },
+ { "bar", 200, NULL },
+ { "fraction", 167, NULL },
+ { "less", 549, NULL },
+ { "registersans", 790, NULL },
+ { "omega1", 713, NULL },
+ { "exclam", 333, NULL },
+ { "Upsilon1", 620, NULL },
+ { "bracerighttp", 494, NULL },
+ { "xi", 493, NULL },
+ { "period", 250, NULL },
+ { "Alpha", 722, NULL },
+ { "arrowright", 987, NULL },
+ { "greater", 549, NULL },
+ { "bracketlefttp", 384, NULL },
+ { "kappa", 549, NULL },
+ { "gradient", 713, NULL },
+ { "integral", 274, NULL },
+ { "arrowboth", 1042, NULL },
+ { "Beta", 667, NULL }
+};
+
+static BuiltinFontWidth timesBoldWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 444, NULL },
+ { "kcommaaccent", 556, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 667, NULL },
+ { "comma", 250, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 570, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
+ { "asciitilde", 520, NULL },
+ { "colon", 333, NULL },
+ { "onehalf", 750, NULL },
+ { "dollar", 500, NULL },
+ { "Lcaron", 667, NULL },
+ { "ntilde", 556, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 556, NULL },
+ { "minus", 570, NULL },
+ { "Iogonek", 389, NULL },
+ { "zacute", 444, NULL },
+ { "yen", 500, NULL },
+ { "space", 250, NULL },
+ { "Omacron", 778, NULL },
+ { "questiondown", 500, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 722, NULL },
+ { "three", 500, NULL },
+ { "numbersign", 500, NULL },
+ { "lcaron", 394, NULL },
+ { "A", 722, NULL },
+ { "B", 667, NULL },
+ { "C", 722, NULL },
+ { "aogonek", 500, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 750, NULL },
+ { "F", 611, NULL },
+ { "G", 778, NULL },
+ { "H", 778, NULL },
+ { "I", 389, NULL },
+ { "J", 500, NULL },
+ { "K", 778, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 667, NULL },
+ { "periodcentered", 250, NULL },
+ { "M", 944, NULL },
+ { "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 667, NULL },
+ { "O", 778, NULL },
+ { "P", 611, NULL },
+ { "Q", 778, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 722, NULL },
+ { "Aacute", 722, NULL },
+ { "caron", 333, NULL },
+ { "S", 556, NULL },
+ { "T", 667, NULL },
+ { "U", 722, NULL },
+ { "agrave", 500, NULL },
+ { "V", 722, NULL },
+ { "W", 1000, NULL },
+ { "X", 722, NULL },
+ { "question", 500, NULL },
+ { "equal", 570, NULL },
+ { "Y", 722, NULL },
+ { "Z", 667, NULL },
+ { "four", 500, NULL },
+ { "a", 500, NULL },
+ { "Gcommaaccent", 778, NULL },
+ { "b", 556, NULL },
+ { "c", 444, NULL },
+ { "d", 556, NULL },
+ { "e", 444, NULL },
+ { "f", 333, NULL },
+ { "g", 500, NULL },
+ { "bullet", 350, NULL },
+ { "h", 556, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 778, NULL },
+ { "dagger", 500, NULL },
+ { "j", 333, NULL },
+ { "k", 556, NULL },
+ { "l", 278, NULL },
+ { "m", 833, NULL },
+ { "n", 556, NULL },
+ { "tcommaaccent", 333, NULL },
+ { "o", 500, NULL },
+ { "ordfeminine", 300, NULL },
+ { "ring", 333, NULL },
+ { "p", 556, NULL },
+ { "q", 556, NULL },
+ { "uhungarumlaut", 556, NULL },
+ { "r", 444, NULL },
+ { "twosuperior", 300, NULL },
+ { "aacute", 500, NULL },
+ { "s", 389, NULL },
+ { "OE", 1000, NULL },
+ { "t", 333, NULL },
+ { "divide", 570, NULL },
+ { "u", 556, NULL },
+ { "Ccaron", 722, NULL },
+ { "v", 500, NULL },
+ { "w", 722, NULL },
+ { "x", 500, NULL },
+ { "y", 500, NULL },
+ { "z", 444, NULL },
+ { "Gbreve", 778, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 389, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 555, NULL },
+ { "gcommaaccent", 500, NULL },
+ { "mu", 556, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 556, NULL },
+ { "Lslash", 667, NULL },
+ { "semicolon", 333, NULL },
+ { "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 500, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 500, NULL },
+ { "nacute", 556, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 778, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 389, NULL },
+ { "AE", 1000, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 500, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 278, NULL },
+ { "eight", 500, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 500, NULL },
+ { "oe", 722, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 444, NULL },
+ { "Adieresis", 722, NULL },
+ { "copyright", 747, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 500, NULL },
+ { "Idieresis", 389, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 500, NULL },
+ { "emacron", 444, NULL },
+ { "Odieresis", 778, NULL },
+ { "ucircumflex", 556, NULL },
+ { "bracketleft", 333, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 333, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 722, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 500, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 500, NULL },
+ { "egrave", 444, NULL },
+ { "edieresis", 444, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 722, NULL },
+ { "asterisk", 500, NULL },
+ { "odieresis", 500, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 556, NULL },
+ { "nine", 500, NULL },
+ { "five", 500, NULL },
+ { "udieresis", 556, NULL },
+ { "Zcaron", 667, NULL },
+ { "Scommaaccent", 556, NULL },
+ { "threequarters", 750, NULL },
+ { "guillemotright", 500, NULL },
+ { "Ccedilla", 722, NULL },
+ { "ydieresis", 500, NULL },
+ { "tilde", 333, NULL },
+ { "at", 930, NULL },
+ { "eacute", 444, NULL },
+ { "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 570, NULL },
+ { "zero", 500, NULL },
+ { "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
+ { "Ograve", 778, NULL },
+ { "Racute", 722, NULL },
+ { "partialdiff", 494, NULL },
+ { "uacute", 556, NULL },
+ { "braceleft", 394, NULL },
+ { "Thorn", 611, NULL },
+ { "zcaron", 444, NULL },
+ { "scommaaccent", 389, NULL },
+ { "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 556, NULL },
+ { "Ocircumflex", 778, NULL },
+ { "Oacute", 778, NULL },
+ { "scedilla", 389, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 500, NULL },
+ { "racute", 444, NULL },
+ { "Tcaron", 667, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 556, NULL },
+ { "degree", 400, NULL },
+ { "registered", 747, NULL },
+ { "radical", 549, NULL },
+ { "Aring", 722, NULL },
+ { "percent", 1000, NULL },
+ { "six", 500, NULL },
+ { "paragraph", 540, NULL },
+ { "dcaron", 672, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 500, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 389, NULL },
+ { "Lacute", 667, NULL },
+ { "ocircumflex", 500, NULL },
+ { "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 667, NULL },
+ { "tcaron", 416, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 778, NULL },
+ { "asciicircum", 581, NULL },
+ { "aring", 500, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 556, NULL },
+ { "bracketright", 333, NULL },
+ { "Iacute", 389, NULL },
+ { "ampersand", 833, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 570, NULL },
+ { "uring", 556, NULL },
+ { "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 722, NULL },
+ { "ohungarumlaut", 500, NULL },
+ { "threesuperior", 300, NULL },
+ { "acute", 333, NULL },
+ { "section", 500, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 500, NULL },
+ { "ncaron", 556, NULL },
+ { "florin", 500, NULL },
+ { "yacute", 500, NULL },
+ { "Rcommaaccent", 722, NULL },
+ { "fi", 556, NULL },
+ { "fl", 556, NULL },
+ { "Acircumflex", 722, NULL },
+ { "Cacute", 722, NULL },
+ { "Icircumflex", 389, NULL },
+ { "guillemotleft", 500, NULL },
+ { "germandbls", 556, NULL },
+ { "Amacron", 722, NULL },
+ { "seven", 500, NULL },
+ { "Sacute", 556, NULL },
+ { "ordmasculine", 330, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 389, NULL },
+ { "rcommaaccent", 444, NULL },
+ { "Zdotaccent", 667, NULL },
+ { "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 394, NULL },
+ { "quotedblright", 500, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 500, NULL },
+ { "currency", 500, NULL },
+ { "logicalnot", 570, NULL },
+ { "zdotaccent", 444, NULL },
+ { "Atilde", 722, NULL },
+ { "breve", 333, NULL },
+ { "bar", 220, NULL },
+ { "fraction", 167, NULL },
+ { "less", 570, NULL },
+ { "ecaron", 444, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 333, NULL },
+ { "period", 250, NULL },
+ { "Rcaron", 722, NULL },
+ { "Kcommaaccent", 778, NULL },
+ { "greater", 570, NULL },
+ { "atilde", 500, NULL },
+ { "brokenbar", 220, NULL },
+ { "quoteleft", 333, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 300, NULL }
+};
+
+static BuiltinFontWidth timesBoldItalicWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 250, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 570, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
+ { "asciitilde", 570, NULL },
+ { "colon", 333, NULL },
+ { "onehalf", 750, NULL },
+ { "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
+ { "ntilde", 556, NULL },
+ { "Aogonek", 667, NULL },
+ { "ncommaaccent", 556, NULL },
+ { "minus", 606, NULL },
+ { "Iogonek", 389, NULL },
+ { "zacute", 389, NULL },
+ { "yen", 500, NULL },
+ { "space", 250, NULL },
+ { "Omacron", 722, NULL },
+ { "questiondown", 500, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 667, NULL },
+ { "three", 500, NULL },
+ { "numbersign", 500, NULL },
+ { "lcaron", 382, NULL },
+ { "A", 667, NULL },
+ { "B", 667, NULL },
+ { "C", 667, NULL },
+ { "aogonek", 500, NULL },
+ { "D", 722, NULL },
+ { "E", 667, NULL },
+ { "onequarter", 750, NULL },
+ { "F", 667, NULL },
+ { "G", 722, NULL },
+ { "H", 778, NULL },
+ { "I", 389, NULL },
+ { "J", 500, NULL },
+ { "K", 667, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 611, NULL },
+ { "periodcentered", 250, NULL },
+ { "M", 889, NULL },
+ { "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 722, NULL },
+ { "P", 611, NULL },
+ { "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 667, NULL },
+ { "Aacute", 667, NULL },
+ { "caron", 333, NULL },
+ { "S", 556, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 500, NULL },
+ { "V", 667, NULL },
+ { "W", 889, NULL },
+ { "X", 667, NULL },
+ { "question", 500, NULL },
+ { "equal", 570, NULL },
+ { "Y", 611, NULL },
+ { "Z", 611, NULL },
+ { "four", 500, NULL },
+ { "a", 500, NULL },
+ { "Gcommaaccent", 722, NULL },
+ { "b", 500, NULL },
+ { "c", 444, NULL },
+ { "d", 500, NULL },
+ { "e", 444, NULL },
+ { "f", 333, NULL },
+ { "g", 500, NULL },
+ { "bullet", 350, NULL },
+ { "h", 556, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 722, NULL },
+ { "dagger", 500, NULL },
+ { "j", 278, NULL },
+ { "k", 500, NULL },
+ { "l", 278, NULL },
+ { "m", 778, NULL },
+ { "n", 556, NULL },
+ { "tcommaaccent", 278, NULL },
+ { "o", 500, NULL },
+ { "ordfeminine", 266, NULL },
+ { "ring", 333, NULL },
+ { "p", 500, NULL },
+ { "q", 500, NULL },
+ { "uhungarumlaut", 556, NULL },
+ { "r", 389, NULL },
+ { "twosuperior", 300, NULL },
+ { "aacute", 500, NULL },
+ { "s", 389, NULL },
+ { "OE", 944, NULL },
+ { "t", 278, NULL },
+ { "divide", 570, NULL },
+ { "u", 556, NULL },
+ { "Ccaron", 667, NULL },
+ { "v", 444, NULL },
+ { "w", 667, NULL },
+ { "x", 500, NULL },
+ { "y", 444, NULL },
+ { "z", 389, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 389, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 555, NULL },
+ { "gcommaaccent", 500, NULL },
+ { "mu", 576, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 556, NULL },
+ { "Lslash", 611, NULL },
+ { "semicolon", 333, NULL },
+ { "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 494, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
+ { "Ecircumflex", 667, NULL },
+ { "gbreve", 500, NULL },
+ { "trademark", 1000, NULL },
+ { "daggerdbl", 500, NULL },
+ { "nacute", 556, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 722, NULL },
+ { "Emacron", 667, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 389, NULL },
+ { "AE", 944, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 500, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 278, NULL },
+ { "eight", 500, NULL },
+ { "exclamdown", 389, NULL },
+ { "endash", 500, NULL },
+ { "oe", 722, NULL },
+ { "Abreve", 667, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 444, NULL },
+ { "Adieresis", 667, NULL },
+ { "copyright", 747, NULL },
+ { "Egrave", 667, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 667, NULL },
+ { "otilde", 500, NULL },
+ { "Idieresis", 389, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 500, NULL },
+ { "emacron", 444, NULL },
+ { "Odieresis", 722, NULL },
+ { "ucircumflex", 556, NULL },
+ { "bracketleft", 333, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 333, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 611, NULL },
+ { "umacron", 556, NULL },
+ { "abreve", 500, NULL },
+ { "Eacute", 667, NULL },
+ { "adieresis", 500, NULL },
+ { "egrave", 444, NULL },
+ { "edieresis", 444, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 722, NULL },
+ { "asterisk", 500, NULL },
+ { "odieresis", 500, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 556, NULL },
+ { "nine", 500, NULL },
+ { "five", 500, NULL },
+ { "udieresis", 556, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 556, NULL },
+ { "threequarters", 750, NULL },
+ { "guillemotright", 500, NULL },
+ { "Ccedilla", 667, NULL },
+ { "ydieresis", 444, NULL },
+ { "tilde", 333, NULL },
+ { "at", 832, NULL },
+ { "eacute", 444, NULL },
+ { "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 570, NULL },
+ { "zero", 500, NULL },
+ { "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
+ { "Ograve", 722, NULL },
+ { "Racute", 667, NULL },
+ { "partialdiff", 494, NULL },
+ { "uacute", 556, NULL },
+ { "braceleft", 348, NULL },
+ { "Thorn", 611, NULL },
+ { "zcaron", 389, NULL },
+ { "scommaaccent", 389, NULL },
+ { "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
+ { "Ocircumflex", 722, NULL },
+ { "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 500, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 667, NULL },
+ { "thorn", 500, NULL },
+ { "degree", 400, NULL },
+ { "registered", 747, NULL },
+ { "radical", 549, NULL },
+ { "Aring", 667, NULL },
+ { "percent", 833, NULL },
+ { "six", 500, NULL },
+ { "paragraph", 500, NULL },
+ { "dcaron", 608, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 500, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 389, NULL },
+ { "Lacute", 611, NULL },
+ { "ocircumflex", 500, NULL },
+ { "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 366, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
+ { "asciicircum", 570, NULL },
+ { "aring", 500, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 556, NULL },
+ { "bracketright", 333, NULL },
+ { "Iacute", 389, NULL },
+ { "ampersand", 778, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 570, NULL },
+ { "uring", 556, NULL },
+ { "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 611, NULL },
+ { "ohungarumlaut", 500, NULL },
+ { "threesuperior", 300, NULL },
+ { "acute", 333, NULL },
+ { "section", 500, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 500, NULL },
+ { "ncaron", 556, NULL },
+ { "florin", 500, NULL },
+ { "yacute", 444, NULL },
+ { "Rcommaaccent", 667, NULL },
+ { "fi", 556, NULL },
+ { "fl", 556, NULL },
+ { "Acircumflex", 667, NULL },
+ { "Cacute", 667, NULL },
+ { "Icircumflex", 389, NULL },
+ { "guillemotleft", 500, NULL },
+ { "germandbls", 500, NULL },
+ { "Amacron", 667, NULL },
+ { "seven", 500, NULL },
+ { "Sacute", 556, NULL },
+ { "ordmasculine", 300, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 389, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 667, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 348, NULL },
+ { "quotedblright", 500, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 500, NULL },
+ { "currency", 500, NULL },
+ { "logicalnot", 606, NULL },
+ { "zdotaccent", 389, NULL },
+ { "Atilde", 667, NULL },
+ { "breve", 333, NULL },
+ { "bar", 220, NULL },
+ { "fraction", 167, NULL },
+ { "less", 570, NULL },
+ { "ecaron", 444, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 389, NULL },
+ { "period", 250, NULL },
+ { "Rcaron", 667, NULL },
+ { "Kcommaaccent", 667, NULL },
+ { "greater", 570, NULL },
+ { "atilde", 500, NULL },
+ { "brokenbar", 220, NULL },
+ { "quoteleft", 333, NULL },
+ { "Edotaccent", 667, NULL },
+ { "onesuperior", 300, NULL }
+};
+
+static BuiltinFontWidth timesItalicWidthsTab[] = {
+ { "Ntilde", 667, NULL },
+ { "rcaron", 389, NULL },
+ { "kcommaaccent", 444, NULL },
+ { "Ncommaaccent", 667, NULL },
+ { "Zacute", 556, NULL },
+ { "comma", 250, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 675, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
+ { "asciitilde", 541, NULL },
+ { "colon", 333, NULL },
+ { "onehalf", 750, NULL },
+ { "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
+ { "ntilde", 500, NULL },
+ { "Aogonek", 611, NULL },
+ { "ncommaaccent", 500, NULL },
+ { "minus", 675, NULL },
+ { "Iogonek", 333, NULL },
+ { "zacute", 389, NULL },
+ { "yen", 500, NULL },
+ { "space", 250, NULL },
+ { "Omacron", 722, NULL },
+ { "questiondown", 500, NULL },
+ { "emdash", 889, NULL },
+ { "Agrave", 611, NULL },
+ { "three", 500, NULL },
+ { "numbersign", 500, NULL },
+ { "lcaron", 300, NULL },
+ { "A", 611, NULL },
+ { "B", 611, NULL },
+ { "C", 667, NULL },
+ { "aogonek", 500, NULL },
+ { "D", 722, NULL },
+ { "E", 611, NULL },
+ { "onequarter", 750, NULL },
+ { "F", 611, NULL },
+ { "G", 722, NULL },
+ { "H", 722, NULL },
+ { "I", 333, NULL },
+ { "J", 444, NULL },
+ { "K", 667, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 556, NULL },
+ { "periodcentered", 250, NULL },
+ { "M", 833, NULL },
+ { "N", 667, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 556, NULL },
+ { "O", 722, NULL },
+ { "P", 611, NULL },
+ { "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 611, NULL },
+ { "Aacute", 611, NULL },
+ { "caron", 333, NULL },
+ { "S", 500, NULL },
+ { "T", 556, NULL },
+ { "U", 722, NULL },
+ { "agrave", 500, NULL },
+ { "V", 611, NULL },
+ { "W", 833, NULL },
+ { "X", 611, NULL },
+ { "question", 500, NULL },
+ { "equal", 675, NULL },
+ { "Y", 556, NULL },
+ { "Z", 556, NULL },
+ { "four", 500, NULL },
+ { "a", 500, NULL },
+ { "Gcommaaccent", 722, NULL },
+ { "b", 500, NULL },
+ { "c", 444, NULL },
+ { "d", 500, NULL },
+ { "e", 444, NULL },
+ { "f", 278, NULL },
+ { "g", 500, NULL },
+ { "bullet", 350, NULL },
+ { "h", 500, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 722, NULL },
+ { "dagger", 500, NULL },
+ { "j", 278, NULL },
+ { "k", 444, NULL },
+ { "l", 278, NULL },
+ { "m", 722, NULL },
+ { "n", 500, NULL },
+ { "tcommaaccent", 278, NULL },
+ { "o", 500, NULL },
+ { "ordfeminine", 276, NULL },
+ { "ring", 333, NULL },
+ { "p", 500, NULL },
+ { "q", 500, NULL },
+ { "uhungarumlaut", 500, NULL },
+ { "r", 389, NULL },
+ { "twosuperior", 300, NULL },
+ { "aacute", 500, NULL },
+ { "s", 389, NULL },
+ { "OE", 944, NULL },
+ { "t", 278, NULL },
+ { "divide", 675, NULL },
+ { "u", 500, NULL },
+ { "Ccaron", 667, NULL },
+ { "v", 444, NULL },
+ { "w", 667, NULL },
+ { "x", 444, NULL },
+ { "y", 444, NULL },
+ { "z", 389, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 333, NULL },
+ { "Nacute", 667, NULL },
+ { "quotedbl", 420, NULL },
+ { "gcommaaccent", 500, NULL },
+ { "mu", 500, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 500, NULL },
+ { "Lslash", 556, NULL },
+ { "semicolon", 333, NULL },
+ { "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
+ { "Ecircumflex", 611, NULL },
+ { "gbreve", 500, NULL },
+ { "trademark", 980, NULL },
+ { "daggerdbl", 500, NULL },
+ { "nacute", 500, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 722, NULL },
+ { "Emacron", 611, NULL },
+ { "ellipsis", 889, NULL },
+ { "scaron", 389, NULL },
+ { "AE", 889, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 556, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 214, NULL },
+ { "eight", 500, NULL },
+ { "exclamdown", 389, NULL },
+ { "endash", 500, NULL },
+ { "oe", 667, NULL },
+ { "Abreve", 611, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 444, NULL },
+ { "Adieresis", 611, NULL },
+ { "copyright", 760, NULL },
+ { "Egrave", 611, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 611, NULL },
+ { "otilde", 500, NULL },
+ { "Idieresis", 333, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 500, NULL },
+ { "emacron", 444, NULL },
+ { "Odieresis", 722, NULL },
+ { "ucircumflex", 500, NULL },
+ { "bracketleft", 389, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 333, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 556, NULL },
+ { "umacron", 500, NULL },
+ { "abreve", 500, NULL },
+ { "Eacute", 611, NULL },
+ { "adieresis", 500, NULL },
+ { "egrave", 444, NULL },
+ { "edieresis", 444, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 667, NULL },
+ { "asterisk", 500, NULL },
+ { "odieresis", 500, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 500, NULL },
+ { "nine", 500, NULL },
+ { "five", 500, NULL },
+ { "udieresis", 500, NULL },
+ { "Zcaron", 556, NULL },
+ { "Scommaaccent", 500, NULL },
+ { "threequarters", 750, NULL },
+ { "guillemotright", 500, NULL },
+ { "Ccedilla", 667, NULL },
+ { "ydieresis", 444, NULL },
+ { "tilde", 333, NULL },
+ { "at", 920, NULL },
+ { "eacute", 444, NULL },
+ { "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 675, NULL },
+ { "zero", 500, NULL },
+ { "eth", 500, NULL },
+ { "Scedilla", 500, NULL },
+ { "Ograve", 722, NULL },
+ { "Racute", 611, NULL },
+ { "partialdiff", 476, NULL },
+ { "uacute", 500, NULL },
+ { "braceleft", 400, NULL },
+ { "Thorn", 611, NULL },
+ { "zcaron", 389, NULL },
+ { "scommaaccent", 389, NULL },
+ { "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
+ { "Ocircumflex", 722, NULL },
+ { "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 500, NULL },
+ { "racute", 389, NULL },
+ { "Tcaron", 556, NULL },
+ { "Eogonek", 611, NULL },
+ { "thorn", 500, NULL },
+ { "degree", 400, NULL },
+ { "registered", 760, NULL },
+ { "radical", 453, NULL },
+ { "Aring", 611, NULL },
+ { "percent", 833, NULL },
+ { "six", 500, NULL },
+ { "paragraph", 523, NULL },
+ { "dcaron", 544, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 500, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 333, NULL },
+ { "Lacute", 556, NULL },
+ { "ocircumflex", 500, NULL },
+ { "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 556, NULL },
+ { "tcaron", 300, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
+ { "asciicircum", 422, NULL },
+ { "aring", 500, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 500, NULL },
+ { "bracketright", 389, NULL },
+ { "Iacute", 333, NULL },
+ { "ampersand", 778, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 667, NULL },
+ { "plus", 675, NULL },
+ { "uring", 500, NULL },
+ { "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 556, NULL },
+ { "ohungarumlaut", 500, NULL },
+ { "threesuperior", 300, NULL },
+ { "acute", 333, NULL },
+ { "section", 500, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 556, NULL },
+ { "ncaron", 500, NULL },
+ { "florin", 500, NULL },
+ { "yacute", 444, NULL },
+ { "Rcommaaccent", 611, NULL },
+ { "fi", 500, NULL },
+ { "fl", 500, NULL },
+ { "Acircumflex", 611, NULL },
+ { "Cacute", 667, NULL },
+ { "Icircumflex", 333, NULL },
+ { "guillemotleft", 500, NULL },
+ { "germandbls", 500, NULL },
+ { "Amacron", 611, NULL },
+ { "seven", 500, NULL },
+ { "Sacute", 500, NULL },
+ { "ordmasculine", 310, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 333, NULL },
+ { "rcommaaccent", 389, NULL },
+ { "Zdotaccent", 556, NULL },
+ { "acircumflex", 500, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 611, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 400, NULL },
+ { "quotedblright", 556, NULL },
+ { "amacron", 500, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 500, NULL },
+ { "currency", 500, NULL },
+ { "logicalnot", 675, NULL },
+ { "zdotaccent", 389, NULL },
+ { "Atilde", 611, NULL },
+ { "breve", 333, NULL },
+ { "bar", 275, NULL },
+ { "fraction", 167, NULL },
+ { "less", 675, NULL },
+ { "ecaron", 444, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 333, NULL },
+ { "period", 250, NULL },
+ { "Rcaron", 611, NULL },
+ { "Kcommaaccent", 667, NULL },
+ { "greater", 675, NULL },
+ { "atilde", 500, NULL },
+ { "brokenbar", 275, NULL },
+ { "quoteleft", 333, NULL },
+ { "Edotaccent", 611, NULL },
+ { "onesuperior", 300, NULL }
+};
+
+static BuiltinFontWidth timesRomanWidthsTab[] = {
+ { "Ntilde", 722, NULL },
+ { "rcaron", 333, NULL },
+ { "kcommaaccent", 500, NULL },
+ { "Ncommaaccent", 722, NULL },
+ { "Zacute", 611, NULL },
+ { "comma", 250, NULL },
+ { "cedilla", 333, NULL },
+ { "plusminus", 564, NULL },
+ { "circumflex", 333, NULL },
+ { "dotaccent", 333, NULL },
+ { "edotaccent", 444, NULL },
+ { "asciitilde", 541, NULL },
+ { "colon", 278, NULL },
+ { "onehalf", 750, NULL },
+ { "dollar", 500, NULL },
+ { "Lcaron", 611, NULL },
+ { "ntilde", 500, NULL },
+ { "Aogonek", 722, NULL },
+ { "ncommaaccent", 500, NULL },
+ { "minus", 564, NULL },
+ { "Iogonek", 333, NULL },
+ { "zacute", 444, NULL },
+ { "yen", 500, NULL },
+ { "space", 250, NULL },
+ { "Omacron", 722, NULL },
+ { "questiondown", 444, NULL },
+ { "emdash", 1000, NULL },
+ { "Agrave", 722, NULL },
+ { "three", 500, NULL },
+ { "numbersign", 500, NULL },
+ { "lcaron", 344, NULL },
+ { "A", 722, NULL },
+ { "B", 667, NULL },
+ { "C", 667, NULL },
+ { "aogonek", 444, NULL },
+ { "D", 722, NULL },
+ { "E", 611, NULL },
+ { "onequarter", 750, NULL },
+ { "F", 556, NULL },
+ { "G", 722, NULL },
+ { "H", 722, NULL },
+ { "I", 333, NULL },
+ { "J", 389, NULL },
+ { "K", 722, NULL },
+ { "iogonek", 278, NULL },
+ { "backslash", 278, NULL },
+ { "L", 611, NULL },
+ { "periodcentered", 250, NULL },
+ { "M", 889, NULL },
+ { "N", 722, NULL },
+ { "omacron", 500, NULL },
+ { "Tcommaaccent", 611, NULL },
+ { "O", 722, NULL },
+ { "P", 556, NULL },
+ { "Q", 722, NULL },
+ { "Uhungarumlaut", 722, NULL },
+ { "R", 667, NULL },
+ { "Aacute", 722, NULL },
+ { "caron", 333, NULL },
+ { "S", 556, NULL },
+ { "T", 611, NULL },
+ { "U", 722, NULL },
+ { "agrave", 444, NULL },
+ { "V", 722, NULL },
+ { "W", 944, NULL },
+ { "X", 722, NULL },
+ { "question", 444, NULL },
+ { "equal", 564, NULL },
+ { "Y", 722, NULL },
+ { "Z", 611, NULL },
+ { "four", 500, NULL },
+ { "a", 444, NULL },
+ { "Gcommaaccent", 722, NULL },
+ { "b", 500, NULL },
+ { "c", 444, NULL },
+ { "d", 500, NULL },
+ { "e", 444, NULL },
+ { "f", 333, NULL },
+ { "g", 500, NULL },
+ { "bullet", 350, NULL },
+ { "h", 500, NULL },
+ { "i", 278, NULL },
+ { "Oslash", 722, NULL },
+ { "dagger", 500, NULL },
+ { "j", 278, NULL },
+ { "k", 500, NULL },
+ { "l", 278, NULL },
+ { "m", 778, NULL },
+ { "n", 500, NULL },
+ { "tcommaaccent", 278, NULL },
+ { "o", 500, NULL },
+ { "ordfeminine", 276, NULL },
+ { "ring", 333, NULL },
+ { "p", 500, NULL },
+ { "q", 500, NULL },
+ { "uhungarumlaut", 500, NULL },
+ { "r", 333, NULL },
+ { "twosuperior", 300, NULL },
+ { "aacute", 444, NULL },
+ { "s", 389, NULL },
+ { "OE", 889, NULL },
+ { "t", 278, NULL },
+ { "divide", 564, NULL },
+ { "u", 500, NULL },
+ { "Ccaron", 667, NULL },
+ { "v", 500, NULL },
+ { "w", 722, NULL },
+ { "x", 500, NULL },
+ { "y", 500, NULL },
+ { "z", 444, NULL },
+ { "Gbreve", 722, NULL },
+ { "commaaccent", 250, NULL },
+ { "hungarumlaut", 333, NULL },
+ { "Idotaccent", 333, NULL },
+ { "Nacute", 722, NULL },
+ { "quotedbl", 408, NULL },
+ { "gcommaaccent", 500, NULL },
+ { "mu", 500, NULL },
+ { "greaterequal", 549, NULL },
+ { "Scaron", 556, NULL },
+ { "Lslash", 611, NULL },
+ { "semicolon", 278, NULL },
+ { "oslash", 500, NULL },
+ { "lessequal", 549, NULL },
+ { "lozenge", 471, NULL },
+ { "parenright", 333, NULL },
+ { "ccaron", 444, NULL },
+ { "Ecircumflex", 611, NULL },
+ { "gbreve", 500, NULL },
+ { "trademark", 980, NULL },
+ { "daggerdbl", 500, NULL },
+ { "nacute", 500, NULL },
+ { "macron", 333, NULL },
+ { "Otilde", 722, NULL },
+ { "Emacron", 611, NULL },
+ { "ellipsis", 1000, NULL },
+ { "scaron", 389, NULL },
+ { "AE", 889, NULL },
+ { "Ucircumflex", 722, NULL },
+ { "lslash", 278, NULL },
+ { "quotedblleft", 444, NULL },
+ { "guilsinglright", 333, NULL },
+ { "hyphen", 333, NULL },
+ { "quotesingle", 180, NULL },
+ { "eight", 500, NULL },
+ { "exclamdown", 333, NULL },
+ { "endash", 500, NULL },
+ { "oe", 722, NULL },
+ { "Abreve", 722, NULL },
+ { "Umacron", 722, NULL },
+ { "ecircumflex", 444, NULL },
+ { "Adieresis", 722, NULL },
+ { "copyright", 760, NULL },
+ { "Egrave", 611, NULL },
+ { "slash", 278, NULL },
+ { "Edieresis", 611, NULL },
+ { "otilde", 500, NULL },
+ { "Idieresis", 333, NULL },
+ { "parenleft", 333, NULL },
+ { "one", 500, NULL },
+ { "emacron", 444, NULL },
+ { "Odieresis", 722, NULL },
+ { "ucircumflex", 500, NULL },
+ { "bracketleft", 333, NULL },
+ { "Ugrave", 722, NULL },
+ { "quoteright", 333, NULL },
+ { "Udieresis", 722, NULL },
+ { "perthousand", 1000, NULL },
+ { "Ydieresis", 722, NULL },
+ { "umacron", 500, NULL },
+ { "abreve", 444, NULL },
+ { "Eacute", 611, NULL },
+ { "adieresis", 444, NULL },
+ { "egrave", 444, NULL },
+ { "edieresis", 444, NULL },
+ { "idieresis", 278, NULL },
+ { "Eth", 722, NULL },
+ { "ae", 667, NULL },
+ { "asterisk", 500, NULL },
+ { "odieresis", 500, NULL },
+ { "Uacute", 722, NULL },
+ { "ugrave", 500, NULL },
+ { "nine", 500, NULL },
+ { "five", 500, NULL },
+ { "udieresis", 500, NULL },
+ { "Zcaron", 611, NULL },
+ { "Scommaaccent", 556, NULL },
+ { "threequarters", 750, NULL },
+ { "guillemotright", 500, NULL },
+ { "Ccedilla", 667, NULL },
+ { "ydieresis", 500, NULL },
+ { "tilde", 333, NULL },
+ { "at", 921, NULL },
+ { "eacute", 444, NULL },
+ { "underscore", 500, NULL },
+ { "Euro", 500, NULL },
+ { "Dcroat", 722, NULL },
+ { "multiply", 564, NULL },
+ { "zero", 500, NULL },
+ { "eth", 500, NULL },
+ { "Scedilla", 556, NULL },
+ { "Ograve", 722, NULL },
+ { "Racute", 667, NULL },
+ { "partialdiff", 476, NULL },
+ { "uacute", 500, NULL },
+ { "braceleft", 480, NULL },
+ { "Thorn", 556, NULL },
+ { "zcaron", 444, NULL },
+ { "scommaaccent", 389, NULL },
+ { "ccedilla", 444, NULL },
+ { "Dcaron", 722, NULL },
+ { "dcroat", 500, NULL },
+ { "Ocircumflex", 722, NULL },
+ { "Oacute", 722, NULL },
+ { "scedilla", 389, NULL },
+ { "ogonek", 333, NULL },
+ { "ograve", 500, NULL },
+ { "racute", 333, NULL },
+ { "Tcaron", 611, NULL },
+ { "Eogonek", 611, NULL },
+ { "thorn", 500, NULL },
+ { "degree", 400, NULL },
+ { "registered", 760, NULL },
+ { "radical", 453, NULL },
+ { "Aring", 722, NULL },
+ { "percent", 833, NULL },
+ { "six", 500, NULL },
+ { "paragraph", 453, NULL },
+ { "dcaron", 588, NULL },
+ { "Uogonek", 722, NULL },
+ { "two", 500, NULL },
+ { "summation", 600, NULL },
+ { "Igrave", 333, NULL },
+ { "Lacute", 611, NULL },
+ { "ocircumflex", 500, NULL },
+ { "oacute", 500, NULL },
+ { "Uring", 722, NULL },
+ { "Lcommaaccent", 611, NULL },
+ { "tcaron", 326, NULL },
+ { "eogonek", 444, NULL },
+ { "Delta", 612, NULL },
+ { "Ohungarumlaut", 722, NULL },
+ { "asciicircum", 469, NULL },
+ { "aring", 444, NULL },
+ { "grave", 333, NULL },
+ { "uogonek", 500, NULL },
+ { "bracketright", 333, NULL },
+ { "Iacute", 333, NULL },
+ { "ampersand", 778, NULL },
+ { "igrave", 278, NULL },
+ { "lacute", 278, NULL },
+ { "Ncaron", 722, NULL },
+ { "plus", 564, NULL },
+ { "uring", 500, NULL },
+ { "quotesinglbase", 333, NULL },
+ { "lcommaaccent", 278, NULL },
+ { "Yacute", 722, NULL },
+ { "ohungarumlaut", 500, NULL },
+ { "threesuperior", 300, NULL },
+ { "acute", 333, NULL },
+ { "section", 500, NULL },
+ { "dieresis", 333, NULL },
+ { "iacute", 278, NULL },
+ { "quotedblbase", 444, NULL },
+ { "ncaron", 500, NULL },
+ { "florin", 500, NULL },
+ { "yacute", 500, NULL },
+ { "Rcommaaccent", 667, NULL },
+ { "fi", 556, NULL },
+ { "fl", 556, NULL },
+ { "Acircumflex", 722, NULL },
+ { "Cacute", 667, NULL },
+ { "Icircumflex", 333, NULL },
+ { "guillemotleft", 500, NULL },
+ { "germandbls", 500, NULL },
+ { "Amacron", 722, NULL },
+ { "seven", 500, NULL },
+ { "Sacute", 556, NULL },
+ { "ordmasculine", 310, NULL },
+ { "dotlessi", 278, NULL },
+ { "sterling", 500, NULL },
+ { "notequal", 549, NULL },
+ { "Imacron", 333, NULL },
+ { "rcommaaccent", 333, NULL },
+ { "Zdotaccent", 611, NULL },
+ { "acircumflex", 444, NULL },
+ { "cacute", 444, NULL },
+ { "Ecaron", 611, NULL },
+ { "icircumflex", 278, NULL },
+ { "braceright", 480, NULL },
+ { "quotedblright", 444, NULL },
+ { "amacron", 444, NULL },
+ { "sacute", 389, NULL },
+ { "imacron", 278, NULL },
+ { "cent", 500, NULL },
+ { "currency", 500, NULL },
+ { "logicalnot", 564, NULL },
+ { "zdotaccent", 444, NULL },
+ { "Atilde", 722, NULL },
+ { "breve", 333, NULL },
+ { "bar", 200, NULL },
+ { "fraction", 167, NULL },
+ { "less", 564, NULL },
+ { "ecaron", 444, NULL },
+ { "guilsinglleft", 333, NULL },
+ { "exclam", 333, NULL },
+ { "period", 250, NULL },
+ { "Rcaron", 667, NULL },
+ { "Kcommaaccent", 722, NULL },
+ { "greater", 564, NULL },
+ { "atilde", 444, NULL },
+ { "brokenbar", 200, NULL },
+ { "quoteleft", 333, NULL },
+ { "Edotaccent", 611, NULL },
+ { "onesuperior", 300, NULL }
+};
+
+static BuiltinFontWidth zapfDingbatsWidthsTab[] = {
+ { "a81", 438, NULL },
+ { "a82", 138, NULL },
+ { "a83", 277, NULL },
+ { "a84", 415, NULL },
+ { "a85", 509, NULL },
+ { "a86", 410, NULL },
+ { "a87", 234, NULL },
+ { "a88", 234, NULL },
+ { "a89", 390, NULL },
+ { "a140", 788, NULL },
+ { "a141", 788, NULL },
+ { "a142", 788, NULL },
+ { "a143", 788, NULL },
+ { "a144", 788, NULL },
+ { "a145", 788, NULL },
+ { "a146", 788, NULL },
+ { "a147", 788, NULL },
+ { "a148", 788, NULL },
+ { "a149", 788, NULL },
+ { "a90", 390, NULL },
+ { "a91", 276, NULL },
+ { "a92", 276, NULL },
+ { "space", 278, NULL },
+ { "a93", 317, NULL },
+ { "a94", 317, NULL },
+ { "a95", 334, NULL },
+ { "a96", 334, NULL },
+ { "a97", 392, NULL },
+ { "a98", 392, NULL },
+ { "a99", 668, NULL },
+ { "a150", 788, NULL },
+ { "a151", 788, NULL },
+ { "a152", 788, NULL },
+ { "a153", 788, NULL },
+ { "a154", 788, NULL },
+ { "a155", 788, NULL },
+ { "a156", 788, NULL },
+ { "a157", 788, NULL },
+ { "a158", 788, NULL },
+ { "a159", 788, NULL },
+ { "a160", 894, NULL },
+ { "a161", 838, NULL },
+ { "a162", 924, NULL },
+ { "a163", 1016, NULL },
+ { "a164", 458, NULL },
+ { "a165", 924, NULL },
+ { "a166", 918, NULL },
+ { "a167", 927, NULL },
+ { "a168", 928, NULL },
+ { "a169", 928, NULL },
+ { "a170", 834, NULL },
+ { "a171", 873, NULL },
+ { "a172", 828, NULL },
+ { "a173", 924, NULL },
+ { "a174", 917, NULL },
+ { "a175", 930, NULL },
+ { "a176", 931, NULL },
+ { "a177", 463, NULL },
+ { "a178", 883, NULL },
+ { "a179", 836, NULL },
+ { "a180", 867, NULL },
+ { "a181", 696, NULL },
+ { "a182", 874, NULL },
+ { "a183", 760, NULL },
+ { "a184", 946, NULL },
+ { "a185", 865, NULL },
+ { "a186", 967, NULL },
+ { "a187", 831, NULL },
+ { "a188", 873, NULL },
+ { "a189", 927, NULL },
+ { "a1", 974, NULL },
+ { "a2", 961, NULL },
+ { "a3", 980, NULL },
+ { "a4", 719, NULL },
+ { "a5", 789, NULL },
+ { "a6", 494, NULL },
+ { "a7", 552, NULL },
+ { "a8", 537, NULL },
+ { "a9", 577, NULL },
+ { "a190", 970, NULL },
+ { "a191", 918, NULL },
+ { "a192", 748, NULL },
+ { "a193", 836, NULL },
+ { "a194", 771, NULL },
+ { "a195", 888, NULL },
+ { "a196", 748, NULL },
+ { "a197", 771, NULL },
+ { "a198", 888, NULL },
+ { "a199", 867, NULL },
+ { "a10", 692, NULL },
+ { "a11", 960, NULL },
+ { "a12", 939, NULL },
+ { "a13", 549, NULL },
+ { "a14", 855, NULL },
+ { "a15", 911, NULL },
+ { "a16", 933, NULL },
+ { "a17", 945, NULL },
+ { "a18", 974, NULL },
+ { "a19", 755, NULL },
+ { "a20", 846, NULL },
+ { "a21", 762, NULL },
+ { "a22", 761, NULL },
+ { "a23", 571, NULL },
+ { "a24", 677, NULL },
+ { "a25", 763, NULL },
+ { "a26", 760, NULL },
+ { "a27", 759, NULL },
+ { "a28", 754, NULL },
+ { "a29", 786, NULL },
+ { "a30", 788, NULL },
+ { "a31", 788, NULL },
+ { "a32", 790, NULL },
+ { "a33", 793, NULL },
+ { "a34", 794, NULL },
+ { "a35", 816, NULL },
+ { "a36", 823, NULL },
+ { "a37", 789, NULL },
+ { "a38", 841, NULL },
+ { "a39", 823, NULL },
+ { "a40", 833, NULL },
+ { "a41", 816, NULL },
+ { "a42", 831, NULL },
+ { "a43", 923, NULL },
+ { "a44", 744, NULL },
+ { "a45", 723, NULL },
+ { "a46", 749, NULL },
+ { "a47", 790, NULL },
+ { "a48", 792, NULL },
+ { "a49", 695, NULL },
+ { "a100", 668, NULL },
+ { "a101", 732, NULL },
+ { "a102", 544, NULL },
+ { "a103", 544, NULL },
+ { "a104", 910, NULL },
+ { "a105", 911, NULL },
+ { "a106", 667, NULL },
+ { "a107", 760, NULL },
+ { "a108", 760, NULL },
+ { "a109", 626, NULL },
+ { "a50", 776, NULL },
+ { "a51", 768, NULL },
+ { "a52", 792, NULL },
+ { "a53", 759, NULL },
+ { "a54", 707, NULL },
+ { "a55", 708, NULL },
+ { "a56", 682, NULL },
+ { "a57", 701, NULL },
+ { "a58", 826, NULL },
+ { "a59", 815, NULL },
+ { "a110", 694, NULL },
+ { "a111", 595, NULL },
+ { "a112", 776, NULL },
+ { "a117", 690, NULL },
+ { "a118", 791, NULL },
+ { "a119", 790, NULL },
+ { "a60", 789, NULL },
+ { "a61", 789, NULL },
+ { "a62", 707, NULL },
+ { "a63", 687, NULL },
+ { "a64", 696, NULL },
+ { "a65", 689, NULL },
+ { "a66", 786, NULL },
+ { "a67", 787, NULL },
+ { "a68", 713, NULL },
+ { "a69", 791, NULL },
+ { "a200", 696, NULL },
+ { "a201", 874, NULL },
+ { "a120", 788, NULL },
+ { "a121", 788, NULL },
+ { "a202", 974, NULL },
+ { "a122", 788, NULL },
+ { "a203", 762, NULL },
+ { "a123", 788, NULL },
+ { "a204", 759, NULL },
+ { "a124", 788, NULL },
+ { "a205", 509, NULL },
+ { "a125", 788, NULL },
+ { "a206", 410, NULL },
+ { "a126", 788, NULL },
+ { "a127", 788, NULL },
+ { "a128", 788, NULL },
+ { "a129", 788, NULL },
+ { "a70", 785, NULL },
+ { "a71", 791, NULL },
+ { "a72", 873, NULL },
+ { "a73", 761, NULL },
+ { "a74", 762, NULL },
+ { "a75", 759, NULL },
+ { "a76", 892, NULL },
+ { "a77", 892, NULL },
+ { "a78", 788, NULL },
+ { "a79", 784, NULL },
+ { "a130", 788, NULL },
+ { "a131", 788, NULL },
+ { "a132", 788, NULL },
+ { "a133", 788, NULL },
+ { "a134", 788, NULL },
+ { "a135", 788, NULL },
+ { "a136", 788, NULL },
+ { "a137", 788, NULL },
+ { "a138", 788, NULL },
+ { "a139", 788, NULL }
+};
+
+BuiltinFont builtinFonts[] = {
+ { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL },
+ { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL },
+ { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL },
+ { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL },
+ { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL },
+ { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL },
+ { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL },
+ { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL },
+ { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL },
+ { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL },
+ { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL },
+ { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL },
+ { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL },
+ { "ZapfDingbats", zapfDingbatsEncoding, 820, -143, { -1, -143, 981, 820}, NULL }
+};
+
+BuiltinFont *builtinFontSubst[] = {
+ &builtinFonts[0],
+ &builtinFonts[3],
+ &builtinFonts[1],
+ &builtinFonts[2],
+ &builtinFonts[4],
+ &builtinFonts[7],
+ &builtinFonts[5],
+ &builtinFonts[6],
+ &builtinFonts[12],
+ &builtinFonts[11],
+ &builtinFonts[9],
+ &builtinFonts[10]
+};
+
+void initBuiltinFontTables() {
+ builtinFonts[0].widths = new BuiltinFontWidths(courierWidthsTab, 315);
+ builtinFonts[1].widths = new BuiltinFontWidths(courierBoldWidthsTab, 315);
+ builtinFonts[2].widths = new BuiltinFontWidths(courierBoldObliqueWidthsTab, 315);
+ builtinFonts[3].widths = new BuiltinFontWidths(courierObliqueWidthsTab, 315);
+ builtinFonts[4].widths = new BuiltinFontWidths(helveticaWidthsTab, 315);
+ builtinFonts[5].widths = new BuiltinFontWidths(helveticaBoldWidthsTab, 316);
+ builtinFonts[6].widths = new BuiltinFontWidths(helveticaBoldObliqueWidthsTab, 315);
+ builtinFonts[7].widths = new BuiltinFontWidths(helveticaObliqueWidthsTab, 315);
+ builtinFonts[8].widths = new BuiltinFontWidths(symbolWidthsTab, 190);
+ builtinFonts[9].widths = new BuiltinFontWidths(timesBoldWidthsTab, 315);
+ builtinFonts[10].widths = new BuiltinFontWidths(timesBoldItalicWidthsTab, 315);
+ builtinFonts[11].widths = new BuiltinFontWidths(timesItalicWidthsTab, 315);
+ builtinFonts[12].widths = new BuiltinFontWidths(timesRomanWidthsTab, 315);
+ builtinFonts[13].widths = new BuiltinFontWidths(zapfDingbatsWidthsTab, 202);
+}
+
+void freeBuiltinFontTables() {
+ int i;
+
+ for (i = 0; i < 14; ++i) {
+ delete builtinFonts[i].widths;
+ }
+}
diff --git a/pdftops/BuiltinFontTables.h b/pdftops/BuiltinFontTables.h
new file mode 100644
index 000000000..eb45549ef
--- /dev/null
+++ b/pdftops/BuiltinFontTables.h
@@ -0,0 +1,23 @@
+//========================================================================
+//
+// BuiltinFontTables.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef BUILTINFONTTABLES_H
+#define BUILTINFONTTABLES_H
+
+#include "BuiltinFont.h"
+
+#define nBuiltinFonts 14
+#define nBuiltinFontSubsts 12
+
+extern BuiltinFont builtinFonts[nBuiltinFonts];
+extern BuiltinFont *builtinFontSubst[nBuiltinFontSubsts];
+
+extern void initBuiltinFontTables();
+extern void freeBuiltinFontTables();
+
+#endif
diff --git a/pdftops/CMap.cxx b/pdftops/CMap.cxx
new file mode 100644
index 000000000..1b9489d39
--- /dev/null
+++ b/pdftops/CMap.cxx
@@ -0,0 +1,384 @@
+//========================================================================
+//
+// CMap.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "gmem.h"
+#include "gfile.h"
+#include "GString.h"
+#include "Error.h"
+#include "GlobalParams.h"
+#include "PSTokenizer.h"
+#include "CMap.h"
+
+//------------------------------------------------------------------------
+
+struct CMapVectorEntry {
+ GBool isVector;
+ union {
+ CMapVectorEntry *vector;
+ CID cid;
+ };
+};
+
+//------------------------------------------------------------------------
+
+static int getCharFromFile(void *data) {
+ return fgetc((FILE *)data);
+}
+
+//------------------------------------------------------------------------
+
+CMap *CMap::parse(CMapCache *cache, GString *collectionA,
+ GString *cMapNameA) {
+ FILE *f;
+ CMap *cmap;
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
+ int n1, n2, n3;
+ Guint start, end;
+
+ if (!(f = globalParams->findCMapFile(collectionA, cMapNameA))) {
+
+ // Check for an identity CMap.
+ if (!cMapNameA->cmp("Identity") || !cMapNameA->cmp("Identity-H")) {
+ return new CMap(collectionA->copy(), cMapNameA->copy(), 0);
+ }
+ if (!cMapNameA->cmp("Identity-V")) {
+ return new CMap(collectionA->copy(), cMapNameA->copy(), 1);
+ }
+
+ error(-1, "Couldn't find '%s' CMap file for '%s' collection",
+ cMapNameA->getCString(), collectionA->getCString());
+ return NULL;
+ }
+
+ cmap = new CMap(collectionA->copy(), cMapNameA->copy());
+
+ pst = new PSTokenizer(&getCharFromFile, f);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ while (pst->getToken(tok2, sizeof(tok2), &n2)) {
+ if (!strcmp(tok2, "usecmap")) {
+ if (tok1[0] == '/') {
+ cmap->useCMap(cache, tok1 + 1);
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok1, "/WMode")) {
+ cmap->wMode = atoi(tok2);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincodespacerange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcodespacerange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcodespacerange")) {
+ error(-1, "Illegal entry in codespacerange block in CMap");
+ break;
+ }
+ if (tok1[0] == '<' && tok2[0] == '<' &&
+ n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
+ tok1[n1 - 1] = tok2[n1 - 1] = '\0';
+ sscanf(tok1 + 1, "%x", &start);
+ sscanf(tok2 + 1, "%x", &end);
+ n1 = (n1 - 2) / 2;
+ cmap->addCodeSpace(cmap->vector, start, end, n1);
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "begincidrange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endcidrange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endcidrange") ||
+ !pst->getToken(tok3, sizeof(tok3), &n3) ||
+ !strcmp(tok3, "endcidrange")) {
+ error(-1, "Illegal entry in cidrange block in CMap");
+ break;
+ }
+ if (tok1[0] == '<' && tok2[0] == '<' &&
+ n1 == n2 && n1 >= 4 && (n1 & 1) == 0) {
+ tok1[n1 - 1] = tok2[n1 - 1] = '\0';
+ sscanf(tok1 + 1, "%x", &start);
+ sscanf(tok2 + 1, "%x", &end);
+ n1 = (n1 - 2) / 2;
+ cmap->addCIDs(start, end, n1, (CID)atoi(tok3));
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else {
+ strcpy(tok1, tok2);
+ }
+ }
+ delete pst;
+
+ fclose(f);
+
+ return cmap;
+}
+
+CMap::CMap(GString *collectionA, GString *cMapNameA) {
+ int i;
+
+ collection = collectionA;
+ cMapName = cMapNameA;
+ wMode = 0;
+ vector = (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
+ for (i = 0; i < 256; ++i) {
+ vector[i].isVector = gFalse;
+ vector[i].cid = 0;
+ }
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) {
+ collection = collectionA;
+ cMapName = cMapNameA;
+ wMode = wModeA;
+ vector = NULL;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+void CMap::useCMap(CMapCache *cache, const char *useName) {
+ GString *useNameStr;
+ CMap *subCMap;
+
+ useNameStr = new GString(useName);
+ subCMap = cache->getCMap(collection, useNameStr);
+ delete useNameStr;
+ if (!subCMap) {
+ return;
+ }
+ copyVector(vector, subCMap->vector);
+ subCMap->decRefCnt();
+}
+
+void CMap::copyVector(CMapVectorEntry *dest, CMapVectorEntry *src) {
+ int i, j;
+
+ for (i = 0; i < 256; ++i) {
+ if (src[i].isVector) {
+ if (!dest[i].isVector) {
+ dest[i].isVector = gTrue;
+ dest[i].vector =
+ (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
+ for (j = 0; j < 256; ++j) {
+ dest[i].vector[j].isVector = gFalse;
+ dest[i].vector[j].cid = 0;
+ }
+ }
+ copyVector(dest[i].vector, src[i].vector);
+ } else {
+ if (dest[i].isVector) {
+ error(-1, "Collision in usecmap");
+ } else {
+ dest[i].cid = src[i].cid;
+ }
+ }
+ }
+}
+
+void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
+ Guint nBytes) {
+ Guint start2, end2;
+ int startByte, endByte, i, j;
+
+ if (nBytes > 1) {
+ startByte = (start >> (8 * (nBytes - 1))) & 0xff;
+ endByte = (end >> (8 * (nBytes - 1))) & 0xff;
+ start2 = start & ((1 << (8 * (nBytes - 1))) - 1);
+ end2 = end & ((1 << (8 * (nBytes - 1))) - 1);
+ for (i = startByte; i <= endByte; ++i) {
+ if (!vec[i].isVector) {
+ vec[i].isVector = gTrue;
+ vec[i].vector =
+ (CMapVectorEntry *)gmalloc(256 * sizeof(CMapVectorEntry));
+ for (j = 0; j < 256; ++j) {
+ vec[i].vector[j].isVector = gFalse;
+ vec[i].vector[j].cid = 0;
+ }
+ }
+ addCodeSpace(vec[i].vector, start2, end2, nBytes - 1);
+ }
+ }
+}
+
+void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) {
+ CMapVectorEntry *vec;
+ CID cid;
+ int byte;
+ Guint i;
+
+ vec = vector;
+ for (i = nBytes - 1; i >= 1; --i) {
+ byte = (start >> (8 * i)) & 0xff;
+ if (!vec[byte].isVector) {
+ error(-1, "Invalid CID (%*x - %*x) in CMap",
+ 2*nBytes, start, 2*nBytes, end);
+ return;
+ }
+ vec = vec[byte].vector;
+ }
+ cid = firstCID;
+ for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) {
+ if (vec[byte].isVector) {
+ error(-1, "Invalid CID (%*x - %*x) in CMap",
+ 2*nBytes, start, 2*nBytes, end);
+ } else {
+ vec[byte].cid = cid;
+ }
+ ++cid;
+ }
+}
+
+CMap::~CMap() {
+ delete collection;
+ delete cMapName;
+ if (vector) {
+ freeCMapVector(vector);
+ }
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+void CMap::freeCMapVector(CMapVectorEntry *vec) {
+ int i;
+
+ for (i = 0; i < 256; ++i) {
+ if (vec[i].isVector) {
+ freeCMapVector(vec[i].vector);
+ }
+ }
+ gfree(vec);
+}
+
+void CMap::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ ++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+}
+
+void CMap::decRefCnt() {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
+ delete this;
+ }
+}
+
+GBool CMap::match(GString *collectionA, GString *cMapNameA) {
+ return !collection->cmp(collectionA) && !cMapName->cmp(cMapNameA);
+}
+
+CID CMap::getCID(const char *s, int len, int *nUsed) {
+ CMapVectorEntry *vec;
+ int n, i;
+
+ if (!(vec = vector)) {
+ // identity CMap
+ *nUsed = 2;
+ if (len < 2) {
+ return 0;
+ }
+ return ((s[0] & 0xff) << 8) + (s[1] & 0xff);
+ }
+ n = 0;
+ while (1) {
+ if (n >= len) {
+ *nUsed = n;
+ return 0;
+ }
+ i = s[n++] & 0xff;
+ if (!vec[i].isVector) {
+ *nUsed = n;
+ return vec[i].cid;
+ }
+ vec = vec[i].vector;
+ }
+}
+
+//------------------------------------------------------------------------
+
+CMapCache::CMapCache() {
+ int i;
+
+ for (i = 0; i < cMapCacheSize; ++i) {
+ cache[i] = NULL;
+ }
+}
+
+CMapCache::~CMapCache() {
+ int i;
+
+ for (i = 0; i < cMapCacheSize; ++i) {
+ if (cache[i]) {
+ cache[i]->decRefCnt();
+ }
+ }
+}
+
+CMap *CMapCache::getCMap(GString *collection, GString *cMapName) {
+ CMap *cmap;
+ int i, j;
+
+ if (cache[0] && cache[0]->match(collection, cMapName)) {
+ cache[0]->incRefCnt();
+ return cache[0];
+ }
+ for (i = 1; i < cMapCacheSize; ++i) {
+ if (cache[i] && cache[i]->match(collection, cMapName)) {
+ cmap = cache[i];
+ for (j = i; j >= 1; --j) {
+ cache[j] = cache[j - 1];
+ }
+ cache[0] = cmap;
+ cmap->incRefCnt();
+ return cmap;
+ }
+ }
+ if ((cmap = CMap::parse(this, collection, cMapName))) {
+ if (cache[cMapCacheSize - 1]) {
+ cache[cMapCacheSize - 1]->decRefCnt();
+ }
+ for (j = cMapCacheSize - 1; j >= 1; --j) {
+ cache[j] = cache[j - 1];
+ }
+ cache[0] = cmap;
+ cmap->incRefCnt();
+ return cmap;
+ }
+ return NULL;
+}
diff --git a/pdftops/CMap.h b/pdftops/CMap.h
new file mode 100644
index 000000000..6878bb0ef
--- /dev/null
+++ b/pdftops/CMap.h
@@ -0,0 +1,102 @@
+//========================================================================
+//
+// CMap.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef CMAP_H
+#define CMAP_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "CharTypes.h"
+
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
+class GString;
+struct CMapVectorEntry;
+class CMapCache;
+
+//------------------------------------------------------------------------
+
+class CMap {
+public:
+
+ // Create the CMap specified by <collection> and <cMapName>. Sets
+ // the initial reference count to 1. Returns NULL on failure.
+ static CMap *parse(CMapCache *cache, GString *collectionA,
+ GString *cMapNameA);
+
+ ~CMap();
+
+ void incRefCnt();
+ void decRefCnt();
+
+ // Return collection name (<registry>-<ordering>).
+ GString *getCollection() { return collection; }
+
+ // Return true if this CMap matches the specified <collectionA>, and
+ // <cMapNameA>.
+ GBool match(GString *collectionA, GString *cMapNameA);
+
+ // Return the CID corresponding to the character code starting at
+ // <s>, which contains <len> bytes. Sets *<nUsed> to the number of
+ // bytes used by the char code.
+ CID getCID(const char *s, int len, int *nUsed);
+
+ // Return the writing mode (0=horizontal, 1=vertical).
+ int getWMode() { return wMode; }
+
+private:
+
+ CMap(GString *collectionA, GString *cMapNameA);
+ CMap(GString *collectionA, GString *cMapNameA, int wModeA);
+ void useCMap(CMapCache *cache, const char *useName);
+ void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
+ void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end,
+ Guint nBytes);
+ void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID);
+ void freeCMapVector(CMapVectorEntry *vec);
+
+ GString *collection;
+ GString *cMapName;
+ int wMode; // writing mode (0=horizontal, 1=vertical)
+ CMapVectorEntry *vector; // vector for first byte (NULL for
+ // identity CMap)
+ int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
+};
+
+//------------------------------------------------------------------------
+
+#define cMapCacheSize 4
+
+class CMapCache {
+public:
+
+ CMapCache();
+ ~CMapCache();
+
+ // Get the <cMapName> CMap for the specified character collection.
+ // Increments its reference count; there will be one reference for
+ // the cache plus one for the caller of this function. Returns NULL
+ // on failure.
+ CMap *getCMap(GString *collection, GString *cMapName);
+
+private:
+
+ CMap *cache[cMapCacheSize];
+};
+
+#endif
diff --git a/pdftops/CNS13CMapInfo.h b/pdftops/CNS13CMapInfo.h
new file mode 100644
index 000000000..284e6036d
--- /dev/null
+++ b/pdftops/CNS13CMapInfo.h
@@ -0,0 +1,47771 @@
+//========================================================================
+//
+// CNS13CMapInfo.h
+//
+// This file was automatically generated by makeCMapInfo.
+//
+// Copyright 1998 Derek B. Noonburg
+//
+//========================================================================
+
+#ifndef CNS13CMAPINFO_H
+#define CNS13CMAPINFO_H
+
+static Gushort cns13AdobeCNS10Map2[116] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13AdobeCNS10Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13AdobeCNS10Map2, 58
+};
+
+static Gushort cns13AdobeCNS11Map2[140] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13AdobeCNS11Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13AdobeCNS11Map2, 70
+};
+
+static Gushort cns13AdobeCNS12Map2[142] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0x4400, 0x4400,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13AdobeCNS12Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13AdobeCNS12Map2, 71
+};
+
+static Gushort cns13AdobeCNS13Map2[152] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0x4400, 0x4400,
+ 0x4500, 0x4500,
+ 0x4600, 0x4600,
+ 0x4700, 0x4700,
+ 0x4800, 0x4800,
+ 0x4900, 0x4900,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13AdobeCNS13Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13AdobeCNS13Map2, 76
+};
+
+static Gushort cns13B5HMap2[490] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13B5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557,
+ 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f,
+ 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567,
+ 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f,
+ 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577,
+ 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x357f,
+ 0x3580, 0x3581, 0x3582, 0x3583, 0x3584, 0x3585, 0x3586, 0x3587,
+ 0x3588, 0x3589, 0x358a, 0x358b, 0x358c, 0x358d, 0x358e, 0x358f,
+ 0x3590, 0x3591, 0x3592, 0x3593, 0x3594, 0x3595, 0x3596, 0x3597,
+ 0x3598, 0x3599, 0x359a, 0x359b, 0x359c, 0x359d, 0x359e, 0x359f,
+ 0x35a0, 0x35a1, 0x35a2, 0x35a3, 0x35a4, 0x35a5, 0x35a6, 0x35a7,
+ 0x35a8, 0x35a9, 0x35aa, 0x35ab, 0x35ac, 0x35ad, 0x35ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13B5HMap2, 245
+};
+
+static Gushort cns13B5VMap2[514] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13B5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557,
+ 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f,
+ 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567,
+ 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f,
+ 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577,
+ 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x357f,
+ 0x3580, 0x3581, 0x3582, 0x3583, 0x3584, 0x3585, 0x3586, 0x3587,
+ 0x3588, 0x3589, 0x358a, 0x358b, 0x358c, 0x358d, 0x358e, 0x358f,
+ 0x3590, 0x3591, 0x3592, 0x3593, 0x3594, 0x3595, 0x3596, 0x3597,
+ 0x3598, 0x3599, 0x359a, 0x359b, 0x359c, 0x359d, 0x359e, 0x359f,
+ 0x35a0, 0x35a1, 0x35a2, 0x35a3, 0x35a4, 0x35a5, 0x35a6, 0x35a7,
+ 0x35a8, 0x35a9, 0x35aa, 0x35ab, 0x35ac, 0x35ad, 0x35ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13B5VMap2, 257
+};
+
+static Gushort cns13B5pcHMap2[492] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa3c0, 0x0232,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13B5pcHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x003d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0060, 0x0061, 0x0062 },
+ cns13B5pcHMap2, 246
+};
+
+static Gushort cns13B5pcVMap2[516] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa3c0, 0x0232,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13B5pcVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x003d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0060, 0x0061, 0x0062 },
+ cns13B5pcVMap2, 258
+};
+
+static Gushort cns13CNS1HMap2[316] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0063,
+ 0x2221, 0x00c1,
+ 0x2321, 0x011f,
+ 0x2421, 0x014d,
+ 0x2521, 0x01ab,
+ 0x256e, 0x01f7,
+ 0x2621, 0x01fa,
+ 0x2721, 0x0253,
+ 0x2722, 0x0218,
+ 0x2725, 0x0254,
+ 0x2726, 0x021b,
+ 0x2727, 0x025a,
+ 0x2728, 0x021c,
+ 0x2729, 0x025b,
+ 0x272d, 0x021d,
+ 0x2730, 0x025f,
+ 0x2731, 0x176e,
+ 0x2732, 0x0260,
+ 0x2733, 0x0262,
+ 0x2734, 0x0220,
+ 0x2735, 0x0263,
+ 0x2736, 0x176f,
+ 0x2737, 0x0221,
+ 0x2738, 0x0264,
+ 0x273a, 0x0222,
+ 0x273b, 0x1770,
+ 0x273c, 0x0223,
+ 0x273d, 0x0266,
+ 0x273e, 0x0279,
+ 0x273f, 0x1775,
+ 0x2740, 0x027a,
+ 0x2742, 0x0224,
+ 0x2743, 0x027c,
+ 0x2747, 0x0225,
+ 0x2748, 0x0282,
+ 0x274c, 0x1776,
+ 0x274d, 0x0286,
+ 0x274e, 0x0226,
+ 0x274f, 0x0288,
+ 0x2751, 0x028c,
+ 0x2753, 0x0227,
+ 0x2756, 0x028e,
+ 0x2759, 0x022a,
+ 0x275b, 0x1777,
+ 0x275c, 0x02d0,
+ 0x2760, 0x02d5,
+ 0x2761, 0x022c,
+ 0x2762, 0x02d6,
+ 0x2766, 0x022d,
+ 0x2767, 0x02da,
+ 0x276e, 0x178a,
+ 0x276f, 0x02e1,
+ 0x2773, 0x178c,
+ 0x2774, 0x02e5,
+ 0x2779, 0x178d,
+ 0x277a, 0x02ea,
+ 0x277e, 0x0356,
+ 0x2821, 0x0357,
+ 0x2827, 0x035e,
+ 0x2828, 0x0362,
+ 0x2829, 0x022e,
+ 0x282b, 0x0363,
+ 0x2833, 0x17b2,
+ 0x2834, 0x036b,
+ 0x2837, 0x03f6,
+ 0x283b, 0x1812,
+ 0x283c, 0x03fa,
+ 0x283f, 0x03fe,
+ 0x2844, 0x0405,
+ 0x284d, 0x1813,
+ 0x284e, 0x1818,
+ 0x284f, 0x040f,
+ 0x2853, 0x1819,
+ 0x2854, 0x0508,
+ 0x285a, 0x18e7,
+ 0x285b, 0x050e,
+ 0x2863, 0x0230,
+ 0x2864, 0x051b,
+ 0x2865, 0x0520,
+ 0x2868, 0x0696,
+ 0x286c, 0x0231,
+ 0x286d, 0x069f,
+ 0x2871, 0x0826,
+ 0x287c, 0x09f5,
+ 0x2921, 0x1e33,
+ 0x2922, 0x09f8,
+ 0x2923, 0x1e34,
+ 0x2924, 0x09f9,
+ 0x2926, 0x0be1,
+ 0x292c, 0x0dbb,
+ 0x292f, 0x2360,
+ 0x2930, 0x2612,
+ 0x2931, 0x0f7b,
+ 0x2934, 0x1100,
+ 0x2936, 0x1289,
+ 0x2937, 0x13b2,
+ 0x2939, 0x2f0d,
+ 0x4221, 0x0232,
+ 0x4421, 0x0253,
+ 0x4521, 0x02b1,
+ 0x4621, 0x030f,
+ 0x4721, 0x036d,
+ 0x4821, 0x03cb,
+ 0x4921, 0x0429,
+ 0x4a21, 0x0487,
+ 0x4b21, 0x04e5,
+ 0x4c21, 0x0543,
+ 0x4d21, 0x05a1,
+ 0x4e21, 0x05ff,
+ 0x4f21, 0x065d,
+ 0x5021, 0x06bb,
+ 0x5121, 0x0719,
+ 0x5221, 0x0777,
+ 0x5321, 0x07d5,
+ 0x5421, 0x0833,
+ 0x5521, 0x0891,
+ 0x5621, 0x08ef,
+ 0x5721, 0x094d,
+ 0x5821, 0x09ab,
+ 0x5921, 0x0a09,
+ 0x5a21, 0x0a67,
+ 0x5b21, 0x0ac5,
+ 0x5c21, 0x0b23,
+ 0x5d21, 0x0b81,
+ 0x5e21, 0x0bdf,
+ 0x5f21, 0x0c3d,
+ 0x6021, 0x0c9b,
+ 0x6121, 0x0cf9,
+ 0x6221, 0x0d57,
+ 0x6321, 0x0db5,
+ 0x6421, 0x0e13,
+ 0x6521, 0x0e71,
+ 0x6621, 0x0ecf,
+ 0x6721, 0x0f2d,
+ 0x6821, 0x0f8b,
+ 0x6921, 0x0fe9,
+ 0x6a21, 0x1047,
+ 0x6b21, 0x10a5,
+ 0x6c21, 0x1103,
+ 0x6d21, 0x1161,
+ 0x6e21, 0x11bf,
+ 0x6f21, 0x121d,
+ 0x7021, 0x127b,
+ 0x7121, 0x12d9,
+ 0x7221, 0x1337,
+ 0x7321, 0x1395,
+ 0x7421, 0x13f3,
+ 0x7521, 0x1451,
+ 0x7621, 0x14af,
+ 0x7721, 0x150d,
+ 0x7821, 0x156b,
+ 0x7921, 0x15c9,
+ 0x7a21, 0x1627,
+ 0x7b21, 0x1685,
+ 0x7c21, 0x16e3,
+ 0x7d21, 0x1741,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13CNS1HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13CNS1HMap2, 158
+};
+
+static Gushort cns13CNS1VMap2[340] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0063,
+ 0x2221, 0x00c1,
+ 0x2321, 0x011f,
+ 0x2421, 0x014d,
+ 0x2521, 0x01ab,
+ 0x256e, 0x01f7,
+ 0x2621, 0x01fa,
+ 0x2721, 0x0253,
+ 0x2722, 0x0218,
+ 0x2725, 0x0254,
+ 0x2726, 0x021b,
+ 0x2727, 0x025a,
+ 0x2728, 0x021c,
+ 0x2729, 0x025b,
+ 0x272d, 0x021d,
+ 0x2730, 0x025f,
+ 0x2731, 0x176e,
+ 0x2732, 0x0260,
+ 0x2733, 0x0262,
+ 0x2734, 0x0220,
+ 0x2735, 0x0263,
+ 0x2736, 0x176f,
+ 0x2737, 0x0221,
+ 0x2738, 0x0264,
+ 0x273a, 0x0222,
+ 0x273b, 0x1770,
+ 0x273c, 0x0223,
+ 0x273d, 0x0266,
+ 0x273e, 0x0279,
+ 0x273f, 0x1775,
+ 0x2740, 0x027a,
+ 0x2742, 0x0224,
+ 0x2743, 0x027c,
+ 0x2747, 0x0225,
+ 0x2748, 0x0282,
+ 0x274c, 0x1776,
+ 0x274d, 0x0286,
+ 0x274e, 0x0226,
+ 0x274f, 0x0288,
+ 0x2751, 0x028c,
+ 0x2753, 0x0227,
+ 0x2756, 0x028e,
+ 0x2759, 0x022a,
+ 0x275b, 0x1777,
+ 0x275c, 0x02d0,
+ 0x2760, 0x02d5,
+ 0x2761, 0x022c,
+ 0x2762, 0x02d6,
+ 0x2766, 0x022d,
+ 0x2767, 0x02da,
+ 0x276e, 0x178a,
+ 0x276f, 0x02e1,
+ 0x2773, 0x178c,
+ 0x2774, 0x02e5,
+ 0x2779, 0x178d,
+ 0x277a, 0x02ea,
+ 0x277e, 0x0356,
+ 0x2821, 0x0357,
+ 0x2827, 0x035e,
+ 0x2828, 0x0362,
+ 0x2829, 0x022e,
+ 0x282b, 0x0363,
+ 0x2833, 0x17b2,
+ 0x2834, 0x036b,
+ 0x2837, 0x03f6,
+ 0x283b, 0x1812,
+ 0x283c, 0x03fa,
+ 0x283f, 0x03fe,
+ 0x2844, 0x0405,
+ 0x284d, 0x1813,
+ 0x284e, 0x1818,
+ 0x284f, 0x040f,
+ 0x2853, 0x1819,
+ 0x2854, 0x0508,
+ 0x285a, 0x18e7,
+ 0x285b, 0x050e,
+ 0x2863, 0x0230,
+ 0x2864, 0x051b,
+ 0x2865, 0x0520,
+ 0x2868, 0x0696,
+ 0x286c, 0x0231,
+ 0x286d, 0x069f,
+ 0x2871, 0x0826,
+ 0x287c, 0x09f5,
+ 0x2921, 0x1e33,
+ 0x2922, 0x09f8,
+ 0x2923, 0x1e34,
+ 0x2924, 0x09f9,
+ 0x2926, 0x0be1,
+ 0x292c, 0x0dbb,
+ 0x292f, 0x2360,
+ 0x2930, 0x2612,
+ 0x2931, 0x0f7b,
+ 0x2934, 0x1100,
+ 0x2936, 0x1289,
+ 0x2937, 0x13b2,
+ 0x2939, 0x2f0d,
+ 0x4221, 0x0232,
+ 0x4421, 0x0253,
+ 0x4521, 0x02b1,
+ 0x4621, 0x030f,
+ 0x4721, 0x036d,
+ 0x4821, 0x03cb,
+ 0x4921, 0x0429,
+ 0x4a21, 0x0487,
+ 0x4b21, 0x04e5,
+ 0x4c21, 0x0543,
+ 0x4d21, 0x05a1,
+ 0x4e21, 0x05ff,
+ 0x4f21, 0x065d,
+ 0x5021, 0x06bb,
+ 0x5121, 0x0719,
+ 0x5221, 0x0777,
+ 0x5321, 0x07d5,
+ 0x5421, 0x0833,
+ 0x5521, 0x0891,
+ 0x5621, 0x08ef,
+ 0x5721, 0x094d,
+ 0x5821, 0x09ab,
+ 0x5921, 0x0a09,
+ 0x5a21, 0x0a67,
+ 0x5b21, 0x0ac5,
+ 0x5c21, 0x0b23,
+ 0x5d21, 0x0b81,
+ 0x5e21, 0x0bdf,
+ 0x5f21, 0x0c3d,
+ 0x6021, 0x0c9b,
+ 0x6121, 0x0cf9,
+ 0x6221, 0x0d57,
+ 0x6321, 0x0db5,
+ 0x6421, 0x0e13,
+ 0x6521, 0x0e71,
+ 0x6621, 0x0ecf,
+ 0x6721, 0x0f2d,
+ 0x6821, 0x0f8b,
+ 0x6921, 0x0fe9,
+ 0x6a21, 0x1047,
+ 0x6b21, 0x10a5,
+ 0x6c21, 0x1103,
+ 0x6d21, 0x1161,
+ 0x6e21, 0x11bf,
+ 0x6f21, 0x121d,
+ 0x7021, 0x127b,
+ 0x7121, 0x12d9,
+ 0x7221, 0x1337,
+ 0x7321, 0x1395,
+ 0x7421, 0x13f3,
+ 0x7521, 0x1451,
+ 0x7621, 0x14af,
+ 0x7721, 0x150d,
+ 0x7821, 0x156b,
+ 0x7921, 0x15c9,
+ 0x7a21, 0x1627,
+ 0x7b21, 0x1685,
+ 0x7c21, 0x16e3,
+ 0x7d21, 0x1741,
+ 0x212c, 0x354e,
+ 0x213b, 0x007c,
+ 0x213d, 0x007e,
+ 0x213e, 0x0082,
+ 0x2142, 0x0086,
+ 0x2146, 0x008a,
+ 0x214a, 0x008e,
+ 0x214e, 0x0092,
+ 0x2152, 0x0096,
+ 0x2156, 0x009a,
+ 0x215a, 0x009e,
+ 0x2244, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13CNS1VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13CNS1VMap2, 170
+};
+
+static Gushort cns13CNS2HMap2[168] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x176c,
+ 0x2221, 0x17ca,
+ 0x2321, 0x1828,
+ 0x2421, 0x1886,
+ 0x2521, 0x18e4,
+ 0x2621, 0x1942,
+ 0x2721, 0x19a0,
+ 0x2821, 0x19fe,
+ 0x2921, 0x1a5c,
+ 0x2a21, 0x1aba,
+ 0x2b21, 0x1b18,
+ 0x2c21, 0x1b76,
+ 0x2d21, 0x1bd4,
+ 0x2e21, 0x1c32,
+ 0x2f21, 0x1c90,
+ 0x3021, 0x1cee,
+ 0x3121, 0x1d4c,
+ 0x3221, 0x1daa,
+ 0x3321, 0x1e08,
+ 0x3421, 0x1e66,
+ 0x3521, 0x1ec4,
+ 0x3621, 0x1f22,
+ 0x3721, 0x1f80,
+ 0x3821, 0x1fde,
+ 0x3921, 0x203c,
+ 0x3a21, 0x209a,
+ 0x3b21, 0x20f8,
+ 0x3c21, 0x2156,
+ 0x3d21, 0x21b4,
+ 0x3e21, 0x2212,
+ 0x3f21, 0x2270,
+ 0x4021, 0x22ce,
+ 0x4121, 0x232c,
+ 0x4221, 0x238a,
+ 0x4321, 0x23e8,
+ 0x4421, 0x2446,
+ 0x4521, 0x24a4,
+ 0x4621, 0x2502,
+ 0x4721, 0x2560,
+ 0x4821, 0x25be,
+ 0x4921, 0x261c,
+ 0x4a21, 0x267a,
+ 0x4b21, 0x26d8,
+ 0x4c21, 0x2736,
+ 0x4d21, 0x2794,
+ 0x4e21, 0x27f2,
+ 0x4f21, 0x2850,
+ 0x5021, 0x28ae,
+ 0x5121, 0x290c,
+ 0x5221, 0x296a,
+ 0x5321, 0x29c8,
+ 0x5421, 0x2a26,
+ 0x5521, 0x2a84,
+ 0x5621, 0x2ae2,
+ 0x5721, 0x2b40,
+ 0x5821, 0x2b9e,
+ 0x5921, 0x2bfc,
+ 0x5a21, 0x2c5a,
+ 0x5b21, 0x2cb8,
+ 0x5c21, 0x2d16,
+ 0x5d21, 0x2d74,
+ 0x5e21, 0x2dd2,
+ 0x5f21, 0x2e30,
+ 0x6021, 0x2e8e,
+ 0x6121, 0x2eec,
+ 0x6221, 0x2f4a,
+ 0x6321, 0x2fa8,
+ 0x6421, 0x3006,
+ 0x6521, 0x3064,
+ 0x6621, 0x30c2,
+ 0x6721, 0x3120,
+ 0x6821, 0x317e,
+ 0x6921, 0x31dc,
+ 0x6a21, 0x323a,
+ 0x6b21, 0x3298,
+ 0x6c21, 0x32f6,
+ 0x6d21, 0x3354,
+ 0x6e21, 0x33b2,
+ 0x6f21, 0x3410,
+ 0x7021, 0x346e,
+ 0x7121, 0x34cc,
+ 0x7221, 0x352a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13CNS2HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13CNS2HMap2, 84
+};
+
+static Gushort cns13CNS2VMap2[168] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x176c,
+ 0x2221, 0x17ca,
+ 0x2321, 0x1828,
+ 0x2421, 0x1886,
+ 0x2521, 0x18e4,
+ 0x2621, 0x1942,
+ 0x2721, 0x19a0,
+ 0x2821, 0x19fe,
+ 0x2921, 0x1a5c,
+ 0x2a21, 0x1aba,
+ 0x2b21, 0x1b18,
+ 0x2c21, 0x1b76,
+ 0x2d21, 0x1bd4,
+ 0x2e21, 0x1c32,
+ 0x2f21, 0x1c90,
+ 0x3021, 0x1cee,
+ 0x3121, 0x1d4c,
+ 0x3221, 0x1daa,
+ 0x3321, 0x1e08,
+ 0x3421, 0x1e66,
+ 0x3521, 0x1ec4,
+ 0x3621, 0x1f22,
+ 0x3721, 0x1f80,
+ 0x3821, 0x1fde,
+ 0x3921, 0x203c,
+ 0x3a21, 0x209a,
+ 0x3b21, 0x20f8,
+ 0x3c21, 0x2156,
+ 0x3d21, 0x21b4,
+ 0x3e21, 0x2212,
+ 0x3f21, 0x2270,
+ 0x4021, 0x22ce,
+ 0x4121, 0x232c,
+ 0x4221, 0x238a,
+ 0x4321, 0x23e8,
+ 0x4421, 0x2446,
+ 0x4521, 0x24a4,
+ 0x4621, 0x2502,
+ 0x4721, 0x2560,
+ 0x4821, 0x25be,
+ 0x4921, 0x261c,
+ 0x4a21, 0x267a,
+ 0x4b21, 0x26d8,
+ 0x4c21, 0x2736,
+ 0x4d21, 0x2794,
+ 0x4e21, 0x27f2,
+ 0x4f21, 0x2850,
+ 0x5021, 0x28ae,
+ 0x5121, 0x290c,
+ 0x5221, 0x296a,
+ 0x5321, 0x29c8,
+ 0x5421, 0x2a26,
+ 0x5521, 0x2a84,
+ 0x5621, 0x2ae2,
+ 0x5721, 0x2b40,
+ 0x5821, 0x2b9e,
+ 0x5921, 0x2bfc,
+ 0x5a21, 0x2c5a,
+ 0x5b21, 0x2cb8,
+ 0x5c21, 0x2d16,
+ 0x5d21, 0x2d74,
+ 0x5e21, 0x2dd2,
+ 0x5f21, 0x2e30,
+ 0x6021, 0x2e8e,
+ 0x6121, 0x2eec,
+ 0x6221, 0x2f4a,
+ 0x6321, 0x2fa8,
+ 0x6421, 0x3006,
+ 0x6521, 0x3064,
+ 0x6621, 0x30c2,
+ 0x6721, 0x3120,
+ 0x6821, 0x317e,
+ 0x6921, 0x31dc,
+ 0x6a21, 0x323a,
+ 0x6b21, 0x3298,
+ 0x6c21, 0x32f6,
+ 0x6d21, 0x3354,
+ 0x6e21, 0x33b2,
+ 0x6f21, 0x3410,
+ 0x7021, 0x346e,
+ 0x7121, 0x34cc,
+ 0x7221, 0x352a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13CNS2VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13CNS2VMap2, 84
+};
+
+static Gushort cns13ETHKB5HMap2[2252] = {
+ 0x0000, 0x0000,
+ 0x8840, 0x44c9,
+ 0x8856, 0x4961,
+ 0x88a1, 0x498a,
+ 0x88a9, 0x499c,
+ 0x8940, 0x4534,
+ 0x8943, 0x4536,
+ 0x8946, 0x4537,
+ 0x894c, 0x453b,
+ 0x894d, 0x43c3,
+ 0x894e, 0x453c,
+ 0x8951, 0x439a,
+ 0x8952, 0x453f,
+ 0x89a1, 0x456c,
+ 0x89a6, 0x43a2,
+ 0x89ab, 0x43ec,
+ 0x89ac, 0x4571,
+ 0x89ad, 0x43eb,
+ 0x89ae, 0x4572,
+ 0x89b0, 0x4573,
+ 0x89b5, 0x4576,
+ 0x89c1, 0x4581,
+ 0x89c5, 0x4584,
+ 0x89cf, 0x43bc,
+ 0x89d0, 0x458e,
+ 0x89d9, 0x439c,
+ 0x89da, 0x4597,
+ 0x89db, 0x439e,
+ 0x89dc, 0x4598,
+ 0x89dd, 0x439f,
+ 0x89de, 0x4599,
+ 0x89e1, 0x43a1,
+ 0x89e2, 0x459c,
+ 0x89e3, 0x43a3,
+ 0x89e4, 0x459d,
+ 0x89ea, 0x43a5,
+ 0x89ec, 0x45a3,
+ 0x89fa, 0x43a9,
+ 0x89fb, 0x45b1,
+ 0x8a40, 0x45b5,
+ 0x8a41, 0x4309,
+ 0x8a43, 0x430b,
+ 0x8a4d, 0x45b6,
+ 0x8a4e, 0x4316,
+ 0x8a5a, 0x45b7,
+ 0x8a5b, 0x4323,
+ 0x8a5e, 0x45b8,
+ 0x8a5f, 0x4327,
+ 0x8a64, 0x432c,
+ 0x8a71, 0x45b9,
+ 0x8a72, 0x433a,
+ 0x8a76, 0x433e,
+ 0x8a77, 0x45ba,
+ 0x8a78, 0x4340,
+ 0x8a7a, 0x45bb,
+ 0x8a7b, 0x4343,
+ 0x8a7c, 0x45bc,
+ 0x8a7d, 0x4345,
+ 0x8a7e, 0x45bd,
+ 0x8aa1, 0x4347,
+ 0x8aa8, 0x45be,
+ 0x8aa9, 0x434f,
+ 0x8aac, 0x4352,
+ 0x8ab2, 0x4358,
+ 0x8ab6, 0x45bf,
+ 0x8ab7, 0x435d,
+ 0x8ab8, 0x45c0,
+ 0x8ab9, 0x435f,
+ 0x8abb, 0x4361,
+ 0x8ac9, 0x436f,
+ 0x8acc, 0x45c1,
+ 0x8ace, 0x4374,
+ 0x8ad6, 0x45c2,
+ 0x8ad8, 0x437e,
+ 0x8adf, 0x4385,
+ 0x8ae6, 0x45c4,
+ 0x8ae7, 0x43db,
+ 0x8ae8, 0x45c5,
+ 0x8af6, 0x45d2,
+ 0x8b40, 0x45db,
+ 0x8b41, 0x438c,
+ 0x8b43, 0x45dc,
+ 0x8b45, 0x438e,
+ 0x8b46, 0x45de,
+ 0x8b47, 0x438f,
+ 0x8b48, 0x45df,
+ 0x8b49, 0x4390,
+ 0x8b4a, 0x45e0,
+ 0x8b4b, 0x4391,
+ 0x8b4c, 0x45e1,
+ 0x8b4d, 0x4392,
+ 0x8b51, 0x45e2,
+ 0x8b55, 0x45e5,
+ 0x8b58, 0x4397,
+ 0x8b59, 0x45e8,
+ 0x8b5a, 0x4398,
+ 0x8b5b, 0x43c4,
+ 0x8b5c, 0x45e9,
+ 0x8b61, 0x43a7,
+ 0x8b62, 0x45ee,
+ 0x8b68, 0x43ac,
+ 0x8b69, 0x45f4,
+ 0x8ba1, 0x460a,
+ 0x8bc0, 0x44df,
+ 0x8bde, 0x44fc,
+ 0x8d60, 0x4629,
+ 0x8d62, 0x43ba,
+ 0x8d63, 0x462b,
+ 0x8d68, 0x43bb,
+ 0x8d69, 0x43a0,
+ 0x8d6a, 0x43bd,
+ 0x8d6b, 0x4630,
+ 0x8d6e, 0x43be,
+ 0x8d6f, 0x4633,
+ 0x8d76, 0x43bf,
+ 0x8d77, 0x463a,
+ 0x8d7a, 0x43c0,
+ 0x8d7b, 0x463d,
+ 0x8d7c, 0x43c1,
+ 0x8d7d, 0x463e,
+ 0x8da1, 0x4640,
+ 0x8da5, 0x43c2,
+ 0x8da6, 0x4644,
+ 0x8da8, 0x43b9,
+ 0x8da9, 0x43ad,
+ 0x8daa, 0x4646,
+ 0x8db6, 0x43c7,
+ 0x8db7, 0x4652,
+ 0x8dc3, 0x43c8,
+ 0x8dc4, 0x465e,
+ 0x8dfa, 0x43f9,
+ 0x8dfb, 0x4694,
+ 0x8e40, 0x372b,
+ 0x8e45, 0x4698,
+ 0x8e46, 0x3730,
+ 0x8e6a, 0x3754,
+ 0x8e6b, 0x4699,
+ 0x8e6d, 0x3756,
+ 0x8e70, 0x3759,
+ 0x8e76, 0x469b,
+ 0x8e77, 0x375f,
+ 0x8e7b, 0x469c,
+ 0x8e7c, 0x3764,
+ 0x8ea1, 0x3766,
+ 0x8ea6, 0x469d,
+ 0x8ea7, 0x376b,
+ 0x8eac, 0x3770,
+ 0x8eb5, 0x3779,
+ 0x8eb8, 0x469e,
+ 0x8eb9, 0x377d,
+ 0x8ec9, 0x469f,
+ 0x8eca, 0x378d,
+ 0x8ece, 0x3791,
+ 0x8ed1, 0x3794,
+ 0x8ee5, 0x46a0,
+ 0x8ee6, 0x37a8,
+ 0x8eef, 0x46a1,
+ 0x8ef0, 0x37b1,
+ 0x8ef6, 0x46a2,
+ 0x8ef7, 0x37b8,
+ 0x8f40, 0x37c0,
+ 0x8f58, 0x37d8,
+ 0x8f59, 0x46a3,
+ 0x8f5a, 0x37d9,
+ 0x8f5f, 0x46a4,
+ 0x8f60, 0x37de,
+ 0x8f67, 0x46a5,
+ 0x8f68, 0x37e5,
+ 0x8f6a, 0x37e7,
+ 0x8f6f, 0x37ec,
+ 0x8f79, 0x46a6,
+ 0x8f7a, 0x37f7,
+ 0x8fa1, 0x37fc,
+ 0x8fb0, 0x46a7,
+ 0x8fb1, 0x380c,
+ 0x8fc5, 0x46a8,
+ 0x8fc6, 0x3820,
+ 0x8fc7, 0x46a9,
+ 0x8fc8, 0x3821,
+ 0x8fca, 0x46aa,
+ 0x8fcd, 0x3826,
+ 0x8fda, 0x46ab,
+ 0x8fdb, 0x3833,
+ 0x8fe3, 0x46ac,
+ 0x8fe4, 0x383c,
+ 0x8ffc, 0x46ad,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x9055, 0x46ae,
+ 0x9056, 0x386c,
+ 0x905c, 0x46af,
+ 0x905f, 0x3873,
+ 0x906e, 0x3882,
+ 0x906f, 0x46b2,
+ 0x9070, 0x3883,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a6, 0x46b3,
+ 0x90a7, 0x3896,
+ 0x90b8, 0x46b4,
+ 0x90b9, 0x38a7,
+ 0x90dd, 0x38cb,
+ 0x90f2, 0x38e0,
+ 0x9140, 0x38ed,
+ 0x9165, 0x46b5,
+ 0x9166, 0x3912,
+ 0x916e, 0x46b6,
+ 0x916f, 0x391a,
+ 0x917e, 0x46b7,
+ 0x91a1, 0x3929,
+ 0x91a2, 0x46b8,
+ 0x91a3, 0x392a,
+ 0x91c0, 0x3947,
+ 0x91c8, 0x46b9,
+ 0x91c9, 0x3950,
+ 0x9240, 0x3986,
+ 0x9245, 0x398b,
+ 0x9264, 0x46ba,
+ 0x9265, 0x39ab,
+ 0x926d, 0x46bb,
+ 0x926e, 0x39b4,
+ 0x92a1, 0x39c5,
+ 0x92b3, 0x39d3,
+ 0x92c9, 0x39e9,
+ 0x92d2, 0x39f2,
+ 0x92e5, 0x46bc,
+ 0x92e6, 0x3a05,
+ 0x92f2, 0x46bd,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9368, 0x46be,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93aa, 0x46bf,
+ 0x93ab, 0x3a64,
+ 0x93c2, 0x46c0,
+ 0x93c3, 0x3a7b,
+ 0x93e5, 0x46c1,
+ 0x93e6, 0x3a9d,
+ 0x93e8, 0x46c2,
+ 0x93e9, 0x3aa0,
+ 0x93eb, 0x46c3,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9446, 0x46c4,
+ 0x9448, 0x3abc,
+ 0x9479, 0x46c5,
+ 0x947a, 0x3aee,
+ 0x94a1, 0x3af3,
+ 0x94cb, 0x46c6,
+ 0x94cc, 0x3b1e,
+ 0x9540, 0x3b51,
+ 0x954d, 0x46c7,
+ 0x954e, 0x3b5e,
+ 0x955a, 0x46c8,
+ 0x955b, 0x3b6a,
+ 0x955f, 0x46c9,
+ 0x9560, 0x3b6f,
+ 0x95a1, 0x3b8e,
+ 0x95c6, 0x46ca,
+ 0x95c7, 0x3bb3,
+ 0x95da, 0x3bc6,
+ 0x9640, 0x3beb,
+ 0x9645, 0x3bf0,
+ 0x9651, 0x46cb,
+ 0x9652, 0x3bfd,
+ 0x966a, 0x46cc,
+ 0x966b, 0x3c16,
+ 0x96a1, 0x3c2a,
+ 0x96d4, 0x46cd,
+ 0x96d5, 0x3c5d,
+ 0x96ee, 0x3c76,
+ 0x96fd, 0x3c85,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9844, 0x46ce,
+ 0x9846, 0x3d2a,
+ 0x986f, 0x46d0,
+ 0x9870, 0x3d54,
+ 0x9875, 0x46d1,
+ 0x9877, 0x3d59,
+ 0x9878, 0x46d3,
+ 0x987a, 0x3d5a,
+ 0x987b, 0x46d5,
+ 0x98a1, 0x46d9,
+ 0x98a3, 0x3d5b,
+ 0x98a4, 0x46db,
+ 0x98af, 0x3d5c,
+ 0x98b0, 0x46e6,
+ 0x98b4, 0x43ca,
+ 0x98b5, 0x46ea,
+ 0x98b6, 0x3d5d,
+ 0x98b7, 0x46eb,
+ 0x98b8, 0x43cc,
+ 0x98b9, 0x3d5e,
+ 0x98ba, 0x46ec,
+ 0x98bb, 0x43fa,
+ 0x98bc, 0x46ed,
+ 0x98bd, 0x3d5f,
+ 0x98bf, 0x46ee,
+ 0x98c2, 0x3d61,
+ 0x98c3, 0x46f1,
+ 0x98c4, 0x3d62,
+ 0x98c5, 0x46f2,
+ 0x98c6, 0x3d63,
+ 0x98c8, 0x46f3,
+ 0x98d2, 0x43cd,
+ 0x98d3, 0x46fd,
+ 0x98d8, 0x43ce,
+ 0x98da, 0x4702,
+ 0x98db, 0x43d1,
+ 0x98dc, 0x4703,
+ 0x98df, 0x43d4,
+ 0x98e0, 0x4706,
+ 0x98e3, 0x3d65,
+ 0x98e4, 0x4709,
+ 0x98e7, 0x3d66,
+ 0x98e8, 0x470c,
+ 0x98ed, 0x3d67,
+ 0x98ee, 0x4711,
+ 0x98f0, 0x3d68,
+ 0x98f1, 0x4713,
+ 0x98f2, 0x3d69,
+ 0x98f3, 0x4714,
+ 0x98f4, 0x43d5,
+ 0x98f6, 0x4715,
+ 0x98fc, 0x3d6a,
+ 0x98fd, 0x471b,
+ 0x98fe, 0x43d7,
+ 0x9940, 0x471c,
+ 0x9942, 0x43fc,
+ 0x9943, 0x3d6b,
+ 0x9944, 0x471e,
+ 0x9945, 0x3d6c,
+ 0x9946, 0x471f,
+ 0x9947, 0x43d8,
+ 0x9948, 0x4720,
+ 0x994f, 0x3d6d,
+ 0x9950, 0x4727,
+ 0x9954, 0x43d9,
+ 0x9955, 0x472b,
+ 0x995c, 0x43da,
+ 0x995d, 0x4732,
+ 0x9964, 0x43dc,
+ 0x9965, 0x4739,
+ 0x996a, 0x3d6e,
+ 0x996b, 0x473e,
+ 0x996e, 0x3d6f,
+ 0x996f, 0x4741,
+ 0x9975, 0x3d70,
+ 0x9976, 0x4747,
+ 0x9978, 0x3d71,
+ 0x9979, 0x4749,
+ 0x99a1, 0x474f,
+ 0x99a2, 0x3d72,
+ 0x99a3, 0x4750,
+ 0x99a4, 0x43c5,
+ 0x99a5, 0x4751,
+ 0x99a6, 0x43c6,
+ 0x99a7, 0x4752,
+ 0x99ae, 0x3d73,
+ 0x99af, 0x4759,
+ 0x99b2, 0x43de,
+ 0x99b3, 0x475c,
+ 0x99b6, 0x3d74,
+ 0x99b7, 0x475f,
+ 0x99ba, 0x3d75,
+ 0x99bb, 0x4762,
+ 0x99ca, 0x43e0,
+ 0x99cb, 0x4771,
+ 0x99cd, 0x43e2,
+ 0x99ce, 0x4773,
+ 0x99d3, 0x43e3,
+ 0x99d4, 0x4778,
+ 0x99d6, 0x43e5,
+ 0x99d7, 0x477a,
+ 0x99df, 0x43df,
+ 0x99e0, 0x4782,
+ 0x99e2, 0x3d76,
+ 0x99e3, 0x4784,
+ 0x99e4, 0x43ab,
+ 0x99e5, 0x4785,
+ 0x99e6, 0x43e7,
+ 0x99e7, 0x4786,
+ 0x99e8, 0x43e9,
+ 0x99e9, 0x4787,
+ 0x99ef, 0x43fd,
+ 0x99f0, 0x478d,
+ 0x99f4, 0x3d77,
+ 0x99f5, 0x4791,
+ 0x9a40, 0x479b,
+ 0x9a4a, 0x3d78,
+ 0x9a4b, 0x47a5,
+ 0x9a4c, 0x3d79,
+ 0x9a4d, 0x47a6,
+ 0x9a59, 0x3d7a,
+ 0x9a5a, 0x47b2,
+ 0x9a5f, 0x43af,
+ 0x9a60, 0x47b7,
+ 0x9a61, 0x3d7b,
+ 0x9a62, 0x47b8,
+ 0x9a66, 0x43ed,
+ 0x9a67, 0x47bc,
+ 0x9a68, 0x3d7c,
+ 0x9a69, 0x43ee,
+ 0x9a6a, 0x47bd,
+ 0x9a6b, 0x43ff,
+ 0x9a6c, 0x47be,
+ 0x9a73, 0x3d7d,
+ 0x9a74, 0x47c5,
+ 0x9a75, 0x43f1,
+ 0x9a76, 0x47c6,
+ 0x9a7e, 0x3d7e,
+ 0x9aa1, 0x47ce,
+ 0x9aa3, 0x43f3,
+ 0x9aa4, 0x47d0,
+ 0x9aa5, 0x43f2,
+ 0x9aa6, 0x47d1,
+ 0x9aa9, 0x43f8,
+ 0x9aaa, 0x43f4,
+ 0x9aab, 0x47d4,
+ 0x9ab2, 0x3d7f,
+ 0x9ab3, 0x47db,
+ 0x9ab7, 0x3d80,
+ 0x9ab8, 0x47df,
+ 0x9ab9, 0x3d81,
+ 0x9aba, 0x47e0,
+ 0x9abb, 0x3d82,
+ 0x9abc, 0x47e1,
+ 0x9abd, 0x43b7,
+ 0x9abe, 0x47e2,
+ 0x9ac7, 0x3d83,
+ 0x9ac8, 0x47eb,
+ 0x9ad0, 0x3d84,
+ 0x9ad1, 0x47f3,
+ 0x9ad2, 0x3d85,
+ 0x9ad3, 0x47f4,
+ 0x9ad9, 0x3d86,
+ 0x9adc, 0x47fa,
+ 0x9ae2, 0x3d89,
+ 0x9ae3, 0x4800,
+ 0x9ae4, 0x3d8a,
+ 0x9ae5, 0x4801,
+ 0x9ae8, 0x3d8b,
+ 0x9ae9, 0x43b0,
+ 0x9aea, 0x4804,
+ 0x9aee, 0x43b2,
+ 0x9aef, 0x4808,
+ 0x9af2, 0x3d8c,
+ 0x9af3, 0x480b,
+ 0x9af6, 0x3d8d,
+ 0x9af7, 0x480e,
+ 0x9afb, 0x3d8e,
+ 0x9afc, 0x4812,
+ 0x9b40, 0x4815,
+ 0x9b46, 0x3d8f,
+ 0x9b47, 0x481b,
+ 0x9b4a, 0x3d90,
+ 0x9b4b, 0x481e,
+ 0x9b54, 0x3d92,
+ 0x9b55, 0x4827,
+ 0x9b58, 0x3d93,
+ 0x9b59, 0x482a,
+ 0x9b5a, 0x3d94,
+ 0x9b5b, 0x482b,
+ 0x9b5c, 0x3d95,
+ 0x9b5d, 0x482c,
+ 0x9b5e, 0x3d96,
+ 0x9b60, 0x482d,
+ 0x9b62, 0x482e,
+ 0x9b70, 0x3d98,
+ 0x9b74, 0x483c,
+ 0x9b77, 0x3d9d,
+ 0x9b79, 0x483e,
+ 0x9b7c, 0x3da0,
+ 0x9b7d, 0x4840,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba2, 0x4841,
+ 0x9ba3, 0x3da3,
+ 0x9ba5, 0x4842,
+ 0x9ba7, 0x3da5,
+ 0x9bab, 0x4844,
+ 0x9bac, 0x3da9,
+ 0x9bad, 0x4845,
+ 0x9baf, 0x3daa,
+ 0x9bb0, 0x4847,
+ 0x9bb2, 0x3dab,
+ 0x9bba, 0x4849,
+ 0x9bbe, 0x3db3,
+ 0x9bbf, 0x484d,
+ 0x9bc0, 0x3db4,
+ 0x9bc7, 0x484e,
+ 0x9bca, 0x3dbb,
+ 0x9bcb, 0x4851,
+ 0x9bcc, 0x3dbc,
+ 0x9bcd, 0x4852,
+ 0x9bce, 0x43d0,
+ 0x9bcf, 0x4853,
+ 0x9bd0, 0x3dbd,
+ 0x9bd2, 0x4854,
+ 0x9bd3, 0x3dbf,
+ 0x9bd4, 0x4855,
+ 0x9bd5, 0x3dc0,
+ 0x9bd6, 0x4856,
+ 0x9bd8, 0x3dc1,
+ 0x9bdb, 0x4858,
+ 0x9bdd, 0x3dc4,
+ 0x9bdf, 0x3dc5,
+ 0x9be0, 0x485a,
+ 0x9be1, 0x3dc6,
+ 0x9be2, 0x485b,
+ 0x9be3, 0x3dc7,
+ 0x9be4, 0x485c,
+ 0x9be7, 0x3dc8,
+ 0x9be8, 0x485f,
+ 0x9be9, 0x3dc9,
+ 0x9bed, 0x4860,
+ 0x9bee, 0x3dcd,
+ 0x9bf0, 0x4861,
+ 0x9bf3, 0x3dcf,
+ 0x9bf4, 0x4864,
+ 0x9bf7, 0x4866,
+ 0x9bf8, 0x3dd1,
+ 0x9bfa, 0x4867,
+ 0x9bfb, 0x3dd3,
+ 0x9bfd, 0x4868,
+ 0x9c40, 0x3dd5,
+ 0x9c43, 0x486a,
+ 0x9c44, 0x3dd8,
+ 0x9c47, 0x486b,
+ 0x9c48, 0x3ddb,
+ 0x9c49, 0x486c,
+ 0x9c4a, 0x3ddc,
+ 0x9c4b, 0x486d,
+ 0x9c4d, 0x3ddd,
+ 0x9c54, 0x486f,
+ 0x9c55, 0x3de4,
+ 0x9c56, 0x4870,
+ 0x9c57, 0x3de5,
+ 0x9c5c, 0x4871,
+ 0x9c5d, 0x3dea,
+ 0x9c5e, 0x4872,
+ 0x9c60, 0x3deb,
+ 0x9c61, 0x4874,
+ 0x9c63, 0x4875,
+ 0x9c64, 0x3ded,
+ 0x9c67, 0x4876,
+ 0x9c69, 0x4877,
+ 0x9c6a, 0x3df1,
+ 0x9c6c, 0x4878,
+ 0x9c6d, 0x3df2,
+ 0x9c6e, 0x4879,
+ 0x9c6f, 0x3df3,
+ 0x9c73, 0x487a,
+ 0x9c75, 0x3df7,
+ 0x9c78, 0x487c,
+ 0x9c79, 0x3dfa,
+ 0x9c7a, 0x487d,
+ 0x9c7b, 0x3dfb,
+ 0x9c7d, 0x487e,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca3, 0x487f,
+ 0x9ca5, 0x3e00,
+ 0x9ca6, 0x4881,
+ 0x9ca8, 0x3e01,
+ 0x9caa, 0x4883,
+ 0x9cab, 0x3e03,
+ 0x9cac, 0x4884,
+ 0x9cad, 0x3e04,
+ 0x9caf, 0x4885,
+ 0x9cb1, 0x3e06,
+ 0x9cbb, 0x4887,
+ 0x9cbe, 0x3e12,
+ 0x9cc3, 0x4888,
+ 0x9cc6, 0x3e17,
+ 0x9cce, 0x488b,
+ 0x9ccf, 0x3e1f,
+ 0x9cd1, 0x3e21,
+ 0x9cd4, 0x488c,
+ 0x9cd8, 0x3e24,
+ 0x9cdb, 0x4890,
+ 0x9cdc, 0x3e27,
+ 0x9ce6, 0x4891,
+ 0x9ce7, 0x3e31,
+ 0x9cea, 0x4892,
+ 0x9ceb, 0x3e34,
+ 0x9ced, 0x4893,
+ 0x9cee, 0x3e36,
+ 0x9cfa, 0x4894,
+ 0x9cfd, 0x3e42,
+ 0x9cfe, 0x4897,
+ 0x9d40, 0x43e8,
+ 0x9d41, 0x4898,
+ 0x9d46, 0x3e43,
+ 0x9d47, 0x489d,
+ 0x9d49, 0x3e44,
+ 0x9d4a, 0x489f,
+ 0x9d4c, 0x3e46,
+ 0x9d4e, 0x48a1,
+ 0x9d4f, 0x3e48,
+ 0x9d50, 0x48a2,
+ 0x9d51, 0x3e49,
+ 0x9d52, 0x48a3,
+ 0x9d55, 0x3e4a,
+ 0x9d56, 0x48a6,
+ 0x9d58, 0x48a7,
+ 0x9d5b, 0x48a9,
+ 0x9d61, 0x43c9,
+ 0x9d62, 0x3e4c,
+ 0x9d63, 0x48af,
+ 0x9d64, 0x3e4d,
+ 0x9d65, 0x48b0,
+ 0x9d78, 0x43f5,
+ 0x9d79, 0x3e4e,
+ 0x9d7a, 0x48c3,
+ 0x9d7e, 0x3e4f,
+ 0x9da1, 0x48c7,
+ 0x9da5, 0x3e50,
+ 0x9da9, 0x48cb,
+ 0x9daa, 0x3e54,
+ 0x9dab, 0x48cc,
+ 0x9dac, 0x3e55,
+ 0x9dae, 0x48cd,
+ 0x9db0, 0x3e58,
+ 0x9db1, 0x48cf,
+ 0x9db3, 0x3e59,
+ 0x9db4, 0x48d1,
+ 0x9db5, 0x3e5a,
+ 0x9db6, 0x48d2,
+ 0x9db7, 0x3e5b,
+ 0x9db8, 0x48d3,
+ 0x9dbc, 0x3e5c,
+ 0x9dbe, 0x48d7,
+ 0x9dbf, 0x3e5e,
+ 0x9dc1, 0x48d8,
+ 0x9dc3, 0x3e60,
+ 0x9dc5, 0x48da,
+ 0x9dc7, 0x3e62,
+ 0x9dc9, 0x48dc,
+ 0x9dca, 0x3e64,
+ 0x9dcb, 0x48dd,
+ 0x9dcd, 0x3e65,
+ 0x9dd2, 0x48df,
+ 0x9dd3, 0x3e6a,
+ 0x9dd6, 0x48e0,
+ 0x9dda, 0x3e6d,
+ 0x9dfc, 0x48e4,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e43, 0x48e5,
+ 0x9e44, 0x3e95,
+ 0x9e5f, 0x48e6,
+ 0x9e60, 0x3eb1,
+ 0x9e63, 0x48e7,
+ 0x9e64, 0x3eb4,
+ 0x9e66, 0x48e8,
+ 0x9e68, 0x3eb6,
+ 0x9e69, 0x48ea,
+ 0x9e6a, 0x3eb7,
+ 0x9e6b, 0x48eb,
+ 0x9e71, 0x3eb8,
+ 0x9e72, 0x48f1,
+ 0x9e73, 0x3eb9,
+ 0x9e74, 0x48f2,
+ 0x9e77, 0x3eba,
+ 0x9e79, 0x48f5,
+ 0x9e7a, 0x3ebc,
+ 0x9e7b, 0x48f6,
+ 0x9e7c, 0x3ebd,
+ 0x9e7d, 0x48f7,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea3, 0x48f8,
+ 0x9ea4, 0x3ec1,
+ 0x9ea7, 0x48f9,
+ 0x9eaa, 0x3ec5,
+ 0x9eab, 0x48fb,
+ 0x9ead, 0x3ec7,
+ 0x9eae, 0x48fc,
+ 0x9eaf, 0x3ec8,
+ 0x9eb2, 0x48fd,
+ 0x9eb4, 0x3ecb,
+ 0x9eb5, 0x48ff,
+ 0x9eb6, 0x3ecc,
+ 0x9eb8, 0x4900,
+ 0x9eb9, 0x3ece,
+ 0x9eba, 0x4901,
+ 0x9ebc, 0x3ecf,
+ 0x9ebd, 0x4903,
+ 0x9ebf, 0x3ed0,
+ 0x9ec1, 0x4905,
+ 0x9ec5, 0x3ed3,
+ 0x9ec6, 0x4908,
+ 0x9ec7, 0x3ed4,
+ 0x9ecb, 0x4909,
+ 0x9ecd, 0x3ed9,
+ 0x9ece, 0x490b,
+ 0x9ed0, 0x3eda,
+ 0x9ed2, 0x490d,
+ 0x9ed3, 0x3edc,
+ 0x9ed4, 0x490e,
+ 0x9ed6, 0x3edd,
+ 0x9ed8, 0x4910,
+ 0x9eda, 0x3edf,
+ 0x9ef0, 0x3ef5,
+ 0x9ef2, 0x4912,
+ 0x9ef3, 0x3ef7,
+ 0x9ef5, 0x3ef9,
+ 0x9ef6, 0x4913,
+ 0x9ef9, 0x3efa,
+ 0x9efb, 0x4916,
+ 0x9efc, 0x3efc,
+ 0x9efe, 0x3efe,
+ 0x9f40, 0x3eff,
+ 0x9f43, 0x4917,
+ 0x9f44, 0x3f02,
+ 0x9f48, 0x4918,
+ 0x9f49, 0x3f06,
+ 0x9f4b, 0x4919,
+ 0x9f4d, 0x3f08,
+ 0x9f4f, 0x3f0a,
+ 0x9f61, 0x3f1c,
+ 0x9f67, 0x491b,
+ 0x9f69, 0x3f23,
+ 0x9f70, 0x491d,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fae, 0x3f45,
+ 0x9fb2, 0x3f49,
+ 0x9fb5, 0x491e,
+ 0x9fb6, 0x3f4c,
+ 0x9fbb, 0x491f,
+ 0x9fbc, 0x3f51,
+ 0x9fbf, 0x4920,
+ 0x9fc1, 0x4921,
+ 0x9fc2, 0x3f55,
+ 0x9fc9, 0x3f5c,
+ 0x9fcc, 0x4922,
+ 0x9fcd, 0x3f60,
+ 0x9fd4, 0x4923,
+ 0x9fd5, 0x3f68,
+ 0x9fd9, 0x3f6c,
+ 0x9fdb, 0x3f6e,
+ 0x9fe4, 0x4924,
+ 0x9fe5, 0x3f77,
+ 0x9fe7, 0x3f79,
+ 0x9feb, 0x3f7d,
+ 0x9ff0, 0x3f82,
+ 0x9ff9, 0x4925,
+ 0x9ffa, 0x3f8b,
+ 0xa040, 0x4926,
+ 0xa041, 0x3f90,
+ 0xa047, 0x4927,
+ 0xa048, 0x3f96,
+ 0xa055, 0x4928,
+ 0xa056, 0x3fa3,
+ 0xa058, 0x3fa5,
+ 0xa05b, 0x3fa8,
+ 0xa064, 0x3fb1,
+ 0xa06d, 0x4929,
+ 0xa06e, 0x3fba,
+ 0xa073, 0x3fbf,
+ 0xa078, 0x3fc4,
+ 0xa07b, 0x492a,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a2, 0x492b,
+ 0xa0a3, 0x3fcb,
+ 0xa0a6, 0x3fce,
+ 0xa0a7, 0x492c,
+ 0xa0a8, 0x3fcf,
+ 0xa0ae, 0x3fd5,
+ 0xa0b0, 0x3fd7,
+ 0xa0c5, 0x492d,
+ 0xa0c6, 0x3fec,
+ 0xa0d0, 0x492e,
+ 0xa0d1, 0x3ff6,
+ 0xa0d4, 0x3ff9,
+ 0xa0d6, 0x3ffb,
+ 0xa0e0, 0x4005,
+ 0xa0e2, 0x4007,
+ 0xa0e3, 0x492f,
+ 0xa0e5, 0x4009,
+ 0xa0e7, 0x4930,
+ 0xa0ee, 0x43b4,
+ 0xa0ef, 0x4937,
+ 0xa0f2, 0x43b8,
+ 0xa0f3, 0x493a,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc8d4, 0x44c6,
+ 0xc8d7, 0x451c,
+ 0xc8e0, 0x02dc,
+ 0xc8e1, 0x4525,
+ 0xc8e9, 0x0509,
+ 0xc8ea, 0x452d,
+ 0xc8f1, 0x09f6,
+ 0xc8f5, 0x4992,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xfa40, 0x400b,
+ 0xfa60, 0x402b,
+ 0xfa67, 0x4032,
+ 0xfaa1, 0x404a,
+ 0xfaa9, 0x4946,
+ 0xfaab, 0x4054,
+ 0xfabe, 0x4067,
+ 0xfac6, 0x406f,
+ 0xfad6, 0x407f,
+ 0xfb40, 0x40a8,
+ 0xfb49, 0x40b1,
+ 0xfb53, 0x4948,
+ 0xfb54, 0x40bc,
+ 0xfb6e, 0x4949,
+ 0xfb6f, 0x40d7,
+ 0xfba1, 0x40e7,
+ 0xfba3, 0x494a,
+ 0xfba4, 0x40ea,
+ 0xfbb9, 0x40ff,
+ 0xfbbf, 0x494b,
+ 0xfbc0, 0x4105,
+ 0xfbcd, 0x494c,
+ 0xfbce, 0x4112,
+ 0xfbf4, 0x4138,
+ 0xfbfa, 0x413e,
+ 0xfc40, 0x4143,
+ 0xfc4a, 0x494d,
+ 0xfc4b, 0x414d,
+ 0xfc50, 0x4151,
+ 0xfc52, 0x494e,
+ 0xfc53, 0x4153,
+ 0xfc63, 0x494f,
+ 0xfc64, 0x4163,
+ 0xfc6d, 0x4950,
+ 0xfc6e, 0x416d,
+ 0xfc75, 0x4951,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcba, 0x4195,
+ 0xfcbc, 0x4952,
+ 0xfcbe, 0x4198,
+ 0xfccc, 0x4954,
+ 0xfccd, 0x41a7,
+ 0xfce3, 0x4955,
+ 0xfce4, 0x41bd,
+ 0xfcee, 0x4956,
+ 0xfcef, 0x41c7,
+ 0xfcf2, 0x41ca,
+ 0xfd40, 0x41d7,
+ 0xfd49, 0x4957,
+ 0xfd4a, 0x41e0,
+ 0xfd6a, 0x4958,
+ 0xfd6b, 0x4201,
+ 0xfda1, 0x4215,
+ 0xfdb9, 0x422d,
+ 0xfdbc, 0x4230,
+ 0xfde3, 0x4959,
+ 0xfde4, 0x4258,
+ 0xfdf2, 0x495a,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe53, 0x4285,
+ 0xfe6d, 0x495b,
+ 0xfe6e, 0x429f,
+ 0xfe70, 0x42a1,
+ 0xfe78, 0x495c,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeab, 0x42b8,
+ 0xfede, 0x495d,
+ 0xfee0, 0x42eb,
+ 0xfeed, 0x495f,
+ 0xfeef, 0x42f8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETHKB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETHKB5HMap2, 1126
+};
+
+static Gushort cns13ETHKB5VMap2[2278] = {
+ 0x0000, 0x0000,
+ 0x8840, 0x44c9,
+ 0x8856, 0x4961,
+ 0x88a1, 0x498a,
+ 0x88a9, 0x499c,
+ 0x8940, 0x4534,
+ 0x8943, 0x4536,
+ 0x8946, 0x4537,
+ 0x894c, 0x453b,
+ 0x894d, 0x43c3,
+ 0x894e, 0x453c,
+ 0x8951, 0x439a,
+ 0x8952, 0x453f,
+ 0x89a1, 0x456c,
+ 0x89a6, 0x43a2,
+ 0x89ab, 0x43ec,
+ 0x89ac, 0x4571,
+ 0x89ad, 0x43eb,
+ 0x89ae, 0x4572,
+ 0x89b0, 0x4573,
+ 0x89b5, 0x4576,
+ 0x89c1, 0x4581,
+ 0x89c5, 0x4584,
+ 0x89cf, 0x43bc,
+ 0x89d0, 0x458e,
+ 0x89d9, 0x439c,
+ 0x89da, 0x4597,
+ 0x89db, 0x439e,
+ 0x89dc, 0x4598,
+ 0x89dd, 0x439f,
+ 0x89de, 0x4599,
+ 0x89e1, 0x43a1,
+ 0x89e2, 0x459c,
+ 0x89e3, 0x43a3,
+ 0x89e4, 0x459d,
+ 0x89ea, 0x43a5,
+ 0x89ec, 0x45a3,
+ 0x89fa, 0x43a9,
+ 0x89fb, 0x45b1,
+ 0x8a40, 0x45b5,
+ 0x8a41, 0x4309,
+ 0x8a43, 0x430b,
+ 0x8a4d, 0x45b6,
+ 0x8a4e, 0x4316,
+ 0x8a5a, 0x45b7,
+ 0x8a5b, 0x4323,
+ 0x8a5e, 0x45b8,
+ 0x8a5f, 0x4327,
+ 0x8a64, 0x432c,
+ 0x8a71, 0x45b9,
+ 0x8a72, 0x433a,
+ 0x8a76, 0x433e,
+ 0x8a77, 0x45ba,
+ 0x8a78, 0x4340,
+ 0x8a7a, 0x45bb,
+ 0x8a7b, 0x4343,
+ 0x8a7c, 0x45bc,
+ 0x8a7d, 0x4345,
+ 0x8a7e, 0x45bd,
+ 0x8aa1, 0x4347,
+ 0x8aa8, 0x45be,
+ 0x8aa9, 0x434f,
+ 0x8aac, 0x4352,
+ 0x8ab2, 0x4358,
+ 0x8ab6, 0x45bf,
+ 0x8ab7, 0x435d,
+ 0x8ab8, 0x45c0,
+ 0x8ab9, 0x435f,
+ 0x8abb, 0x4361,
+ 0x8ac9, 0x436f,
+ 0x8acc, 0x45c1,
+ 0x8ace, 0x4374,
+ 0x8ad6, 0x45c2,
+ 0x8ad8, 0x437e,
+ 0x8adf, 0x4385,
+ 0x8ae6, 0x45c4,
+ 0x8ae7, 0x43db,
+ 0x8ae8, 0x45c5,
+ 0x8af6, 0x45d2,
+ 0x8b40, 0x45db,
+ 0x8b41, 0x438c,
+ 0x8b43, 0x45dc,
+ 0x8b45, 0x438e,
+ 0x8b46, 0x45de,
+ 0x8b47, 0x438f,
+ 0x8b48, 0x45df,
+ 0x8b49, 0x4390,
+ 0x8b4a, 0x45e0,
+ 0x8b4b, 0x4391,
+ 0x8b4c, 0x45e1,
+ 0x8b4d, 0x4392,
+ 0x8b51, 0x45e2,
+ 0x8b55, 0x45e5,
+ 0x8b58, 0x4397,
+ 0x8b59, 0x45e8,
+ 0x8b5a, 0x4398,
+ 0x8b5b, 0x43c4,
+ 0x8b5c, 0x45e9,
+ 0x8b61, 0x43a7,
+ 0x8b62, 0x45ee,
+ 0x8b68, 0x43ac,
+ 0x8b69, 0x45f4,
+ 0x8ba1, 0x460a,
+ 0x8bc0, 0x44df,
+ 0x8bde, 0x44fc,
+ 0x8d60, 0x4629,
+ 0x8d62, 0x43ba,
+ 0x8d63, 0x462b,
+ 0x8d68, 0x43bb,
+ 0x8d69, 0x43a0,
+ 0x8d6a, 0x43bd,
+ 0x8d6b, 0x4630,
+ 0x8d6e, 0x43be,
+ 0x8d6f, 0x4633,
+ 0x8d76, 0x43bf,
+ 0x8d77, 0x463a,
+ 0x8d7a, 0x43c0,
+ 0x8d7b, 0x463d,
+ 0x8d7c, 0x43c1,
+ 0x8d7d, 0x463e,
+ 0x8da1, 0x4640,
+ 0x8da5, 0x43c2,
+ 0x8da6, 0x4644,
+ 0x8da8, 0x43b9,
+ 0x8da9, 0x43ad,
+ 0x8daa, 0x4646,
+ 0x8db6, 0x43c7,
+ 0x8db7, 0x4652,
+ 0x8dc3, 0x43c8,
+ 0x8dc4, 0x465e,
+ 0x8dfa, 0x43f9,
+ 0x8dfb, 0x4694,
+ 0x8e40, 0x372b,
+ 0x8e45, 0x4698,
+ 0x8e46, 0x3730,
+ 0x8e6a, 0x3754,
+ 0x8e6b, 0x4699,
+ 0x8e6d, 0x3756,
+ 0x8e70, 0x3759,
+ 0x8e76, 0x469b,
+ 0x8e77, 0x375f,
+ 0x8e7b, 0x469c,
+ 0x8e7c, 0x3764,
+ 0x8ea1, 0x3766,
+ 0x8ea6, 0x469d,
+ 0x8ea7, 0x376b,
+ 0x8eac, 0x3770,
+ 0x8eb5, 0x3779,
+ 0x8eb8, 0x469e,
+ 0x8eb9, 0x377d,
+ 0x8ec9, 0x469f,
+ 0x8eca, 0x378d,
+ 0x8ece, 0x3791,
+ 0x8ed1, 0x3794,
+ 0x8ee5, 0x46a0,
+ 0x8ee6, 0x37a8,
+ 0x8eef, 0x46a1,
+ 0x8ef0, 0x37b1,
+ 0x8ef6, 0x46a2,
+ 0x8ef7, 0x37b8,
+ 0x8f40, 0x37c0,
+ 0x8f58, 0x37d8,
+ 0x8f59, 0x46a3,
+ 0x8f5a, 0x37d9,
+ 0x8f5f, 0x46a4,
+ 0x8f60, 0x37de,
+ 0x8f67, 0x46a5,
+ 0x8f68, 0x37e5,
+ 0x8f6a, 0x37e7,
+ 0x8f6f, 0x37ec,
+ 0x8f79, 0x46a6,
+ 0x8f7a, 0x37f7,
+ 0x8fa1, 0x37fc,
+ 0x8fb0, 0x46a7,
+ 0x8fb1, 0x380c,
+ 0x8fc5, 0x46a8,
+ 0x8fc6, 0x3820,
+ 0x8fc7, 0x46a9,
+ 0x8fc8, 0x3821,
+ 0x8fca, 0x46aa,
+ 0x8fcd, 0x3826,
+ 0x8fda, 0x46ab,
+ 0x8fdb, 0x3833,
+ 0x8fe3, 0x46ac,
+ 0x8fe4, 0x383c,
+ 0x8ffc, 0x46ad,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x9055, 0x46ae,
+ 0x9056, 0x386c,
+ 0x905c, 0x46af,
+ 0x905f, 0x3873,
+ 0x906e, 0x3882,
+ 0x906f, 0x46b2,
+ 0x9070, 0x3883,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a6, 0x46b3,
+ 0x90a7, 0x3896,
+ 0x90b8, 0x46b4,
+ 0x90b9, 0x38a7,
+ 0x90dd, 0x38cb,
+ 0x90f2, 0x38e0,
+ 0x9140, 0x38ed,
+ 0x9165, 0x46b5,
+ 0x9166, 0x3912,
+ 0x916e, 0x46b6,
+ 0x916f, 0x391a,
+ 0x917e, 0x46b7,
+ 0x91a1, 0x3929,
+ 0x91a2, 0x46b8,
+ 0x91a3, 0x392a,
+ 0x91c0, 0x3947,
+ 0x91c8, 0x46b9,
+ 0x91c9, 0x3950,
+ 0x9240, 0x3986,
+ 0x9245, 0x398b,
+ 0x9264, 0x46ba,
+ 0x9265, 0x39ab,
+ 0x926d, 0x46bb,
+ 0x926e, 0x39b4,
+ 0x92a1, 0x39c5,
+ 0x92b3, 0x39d3,
+ 0x92c9, 0x39e9,
+ 0x92d2, 0x39f2,
+ 0x92e5, 0x46bc,
+ 0x92e6, 0x3a05,
+ 0x92f2, 0x46bd,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9368, 0x46be,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93aa, 0x46bf,
+ 0x93ab, 0x3a64,
+ 0x93c2, 0x46c0,
+ 0x93c3, 0x3a7b,
+ 0x93e5, 0x46c1,
+ 0x93e6, 0x3a9d,
+ 0x93e8, 0x46c2,
+ 0x93e9, 0x3aa0,
+ 0x93eb, 0x46c3,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9446, 0x46c4,
+ 0x9448, 0x3abc,
+ 0x9479, 0x46c5,
+ 0x947a, 0x3aee,
+ 0x94a1, 0x3af3,
+ 0x94cb, 0x46c6,
+ 0x94cc, 0x3b1e,
+ 0x9540, 0x3b51,
+ 0x954d, 0x46c7,
+ 0x954e, 0x3b5e,
+ 0x955a, 0x46c8,
+ 0x955b, 0x3b6a,
+ 0x955f, 0x46c9,
+ 0x9560, 0x3b6f,
+ 0x95a1, 0x3b8e,
+ 0x95c6, 0x46ca,
+ 0x95c7, 0x3bb3,
+ 0x95da, 0x3bc6,
+ 0x9640, 0x3beb,
+ 0x9645, 0x3bf0,
+ 0x9651, 0x46cb,
+ 0x9652, 0x3bfd,
+ 0x966a, 0x46cc,
+ 0x966b, 0x3c16,
+ 0x96a1, 0x3c2a,
+ 0x96d4, 0x46cd,
+ 0x96d5, 0x3c5d,
+ 0x96ee, 0x3c76,
+ 0x96fd, 0x3c85,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9844, 0x46ce,
+ 0x9846, 0x3d2a,
+ 0x986f, 0x46d0,
+ 0x9870, 0x3d54,
+ 0x9875, 0x46d1,
+ 0x9877, 0x3d59,
+ 0x9878, 0x46d3,
+ 0x987a, 0x3d5a,
+ 0x987b, 0x46d5,
+ 0x98a1, 0x46d9,
+ 0x98a3, 0x3d5b,
+ 0x98a4, 0x46db,
+ 0x98af, 0x3d5c,
+ 0x98b0, 0x46e6,
+ 0x98b4, 0x43ca,
+ 0x98b5, 0x46ea,
+ 0x98b6, 0x3d5d,
+ 0x98b7, 0x46eb,
+ 0x98b8, 0x43cc,
+ 0x98b9, 0x3d5e,
+ 0x98ba, 0x46ec,
+ 0x98bb, 0x43fa,
+ 0x98bc, 0x46ed,
+ 0x98bd, 0x3d5f,
+ 0x98bf, 0x46ee,
+ 0x98c2, 0x3d61,
+ 0x98c3, 0x46f1,
+ 0x98c4, 0x3d62,
+ 0x98c5, 0x46f2,
+ 0x98c6, 0x3d63,
+ 0x98c8, 0x46f3,
+ 0x98d2, 0x43cd,
+ 0x98d3, 0x46fd,
+ 0x98d8, 0x43ce,
+ 0x98da, 0x4702,
+ 0x98db, 0x43d1,
+ 0x98dc, 0x4703,
+ 0x98df, 0x43d4,
+ 0x98e0, 0x4706,
+ 0x98e3, 0x3d65,
+ 0x98e4, 0x4709,
+ 0x98e7, 0x3d66,
+ 0x98e8, 0x470c,
+ 0x98ed, 0x3d67,
+ 0x98ee, 0x4711,
+ 0x98f0, 0x3d68,
+ 0x98f1, 0x4713,
+ 0x98f2, 0x3d69,
+ 0x98f3, 0x4714,
+ 0x98f4, 0x43d5,
+ 0x98f6, 0x4715,
+ 0x98fc, 0x3d6a,
+ 0x98fd, 0x471b,
+ 0x98fe, 0x43d7,
+ 0x9940, 0x471c,
+ 0x9942, 0x43fc,
+ 0x9943, 0x3d6b,
+ 0x9944, 0x471e,
+ 0x9945, 0x3d6c,
+ 0x9946, 0x471f,
+ 0x9947, 0x43d8,
+ 0x9948, 0x4720,
+ 0x994f, 0x3d6d,
+ 0x9950, 0x4727,
+ 0x9954, 0x43d9,
+ 0x9955, 0x472b,
+ 0x995c, 0x43da,
+ 0x995d, 0x4732,
+ 0x9964, 0x43dc,
+ 0x9965, 0x4739,
+ 0x996a, 0x3d6e,
+ 0x996b, 0x473e,
+ 0x996e, 0x3d6f,
+ 0x996f, 0x4741,
+ 0x9975, 0x3d70,
+ 0x9976, 0x4747,
+ 0x9978, 0x3d71,
+ 0x9979, 0x4749,
+ 0x99a1, 0x474f,
+ 0x99a2, 0x3d72,
+ 0x99a3, 0x4750,
+ 0x99a4, 0x43c5,
+ 0x99a5, 0x4751,
+ 0x99a6, 0x43c6,
+ 0x99a7, 0x4752,
+ 0x99ae, 0x3d73,
+ 0x99af, 0x4759,
+ 0x99b2, 0x43de,
+ 0x99b3, 0x475c,
+ 0x99b6, 0x3d74,
+ 0x99b7, 0x475f,
+ 0x99ba, 0x3d75,
+ 0x99bb, 0x4762,
+ 0x99ca, 0x43e0,
+ 0x99cb, 0x4771,
+ 0x99cd, 0x43e2,
+ 0x99ce, 0x4773,
+ 0x99d3, 0x43e3,
+ 0x99d4, 0x4778,
+ 0x99d6, 0x43e5,
+ 0x99d7, 0x477a,
+ 0x99df, 0x43df,
+ 0x99e0, 0x4782,
+ 0x99e2, 0x3d76,
+ 0x99e3, 0x4784,
+ 0x99e4, 0x43ab,
+ 0x99e5, 0x4785,
+ 0x99e6, 0x43e7,
+ 0x99e7, 0x4786,
+ 0x99e8, 0x43e9,
+ 0x99e9, 0x4787,
+ 0x99ef, 0x43fd,
+ 0x99f0, 0x478d,
+ 0x99f4, 0x3d77,
+ 0x99f5, 0x4791,
+ 0x9a40, 0x479b,
+ 0x9a4a, 0x3d78,
+ 0x9a4b, 0x47a5,
+ 0x9a4c, 0x3d79,
+ 0x9a4d, 0x47a6,
+ 0x9a59, 0x3d7a,
+ 0x9a5a, 0x47b2,
+ 0x9a5f, 0x43af,
+ 0x9a60, 0x47b7,
+ 0x9a61, 0x3d7b,
+ 0x9a62, 0x47b8,
+ 0x9a66, 0x43ed,
+ 0x9a67, 0x47bc,
+ 0x9a68, 0x3d7c,
+ 0x9a69, 0x43ee,
+ 0x9a6a, 0x47bd,
+ 0x9a6b, 0x43ff,
+ 0x9a6c, 0x47be,
+ 0x9a73, 0x3d7d,
+ 0x9a74, 0x47c5,
+ 0x9a75, 0x43f1,
+ 0x9a76, 0x47c6,
+ 0x9a7e, 0x3d7e,
+ 0x9aa1, 0x47ce,
+ 0x9aa3, 0x43f3,
+ 0x9aa4, 0x47d0,
+ 0x9aa5, 0x43f2,
+ 0x9aa6, 0x47d1,
+ 0x9aa9, 0x43f8,
+ 0x9aaa, 0x43f4,
+ 0x9aab, 0x47d4,
+ 0x9ab2, 0x3d7f,
+ 0x9ab3, 0x47db,
+ 0x9ab7, 0x3d80,
+ 0x9ab8, 0x47df,
+ 0x9ab9, 0x3d81,
+ 0x9aba, 0x47e0,
+ 0x9abb, 0x3d82,
+ 0x9abc, 0x47e1,
+ 0x9abd, 0x43b7,
+ 0x9abe, 0x47e2,
+ 0x9ac7, 0x3d83,
+ 0x9ac8, 0x47eb,
+ 0x9ad0, 0x3d84,
+ 0x9ad1, 0x47f3,
+ 0x9ad2, 0x3d85,
+ 0x9ad3, 0x47f4,
+ 0x9ad9, 0x3d86,
+ 0x9adc, 0x47fa,
+ 0x9ae2, 0x3d89,
+ 0x9ae3, 0x4800,
+ 0x9ae4, 0x3d8a,
+ 0x9ae5, 0x4801,
+ 0x9ae8, 0x3d8b,
+ 0x9ae9, 0x43b0,
+ 0x9aea, 0x4804,
+ 0x9aee, 0x43b2,
+ 0x9aef, 0x4808,
+ 0x9af2, 0x3d8c,
+ 0x9af3, 0x480b,
+ 0x9af6, 0x3d8d,
+ 0x9af7, 0x480e,
+ 0x9afb, 0x3d8e,
+ 0x9afc, 0x4812,
+ 0x9b40, 0x4815,
+ 0x9b46, 0x3d8f,
+ 0x9b47, 0x481b,
+ 0x9b4a, 0x3d90,
+ 0x9b4b, 0x481e,
+ 0x9b54, 0x3d92,
+ 0x9b55, 0x4827,
+ 0x9b58, 0x3d93,
+ 0x9b59, 0x482a,
+ 0x9b5a, 0x3d94,
+ 0x9b5b, 0x482b,
+ 0x9b5c, 0x3d95,
+ 0x9b5d, 0x482c,
+ 0x9b5e, 0x3d96,
+ 0x9b60, 0x482d,
+ 0x9b62, 0x482e,
+ 0x9b70, 0x3d98,
+ 0x9b74, 0x483c,
+ 0x9b77, 0x3d9d,
+ 0x9b79, 0x483e,
+ 0x9b7c, 0x3da0,
+ 0x9b7d, 0x4840,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba2, 0x4841,
+ 0x9ba3, 0x3da3,
+ 0x9ba5, 0x4842,
+ 0x9ba7, 0x3da5,
+ 0x9bab, 0x4844,
+ 0x9bac, 0x3da9,
+ 0x9bad, 0x4845,
+ 0x9baf, 0x3daa,
+ 0x9bb0, 0x4847,
+ 0x9bb2, 0x3dab,
+ 0x9bba, 0x4849,
+ 0x9bbe, 0x3db3,
+ 0x9bbf, 0x484d,
+ 0x9bc0, 0x3db4,
+ 0x9bc7, 0x484e,
+ 0x9bca, 0x3dbb,
+ 0x9bcb, 0x4851,
+ 0x9bcc, 0x3dbc,
+ 0x9bcd, 0x4852,
+ 0x9bce, 0x43d0,
+ 0x9bcf, 0x4853,
+ 0x9bd0, 0x3dbd,
+ 0x9bd2, 0x4854,
+ 0x9bd3, 0x3dbf,
+ 0x9bd4, 0x4855,
+ 0x9bd5, 0x3dc0,
+ 0x9bd6, 0x4856,
+ 0x9bd8, 0x3dc1,
+ 0x9bdb, 0x4858,
+ 0x9bdd, 0x3dc4,
+ 0x9bdf, 0x3dc5,
+ 0x9be0, 0x485a,
+ 0x9be1, 0x3dc6,
+ 0x9be2, 0x485b,
+ 0x9be3, 0x3dc7,
+ 0x9be4, 0x485c,
+ 0x9be7, 0x3dc8,
+ 0x9be8, 0x485f,
+ 0x9be9, 0x3dc9,
+ 0x9bed, 0x4860,
+ 0x9bee, 0x3dcd,
+ 0x9bf0, 0x4861,
+ 0x9bf3, 0x3dcf,
+ 0x9bf4, 0x4864,
+ 0x9bf7, 0x4866,
+ 0x9bf8, 0x3dd1,
+ 0x9bfa, 0x4867,
+ 0x9bfb, 0x3dd3,
+ 0x9bfd, 0x4868,
+ 0x9c40, 0x3dd5,
+ 0x9c43, 0x486a,
+ 0x9c44, 0x3dd8,
+ 0x9c47, 0x486b,
+ 0x9c48, 0x3ddb,
+ 0x9c49, 0x486c,
+ 0x9c4a, 0x3ddc,
+ 0x9c4b, 0x486d,
+ 0x9c4d, 0x3ddd,
+ 0x9c54, 0x486f,
+ 0x9c55, 0x3de4,
+ 0x9c56, 0x4870,
+ 0x9c57, 0x3de5,
+ 0x9c5c, 0x4871,
+ 0x9c5d, 0x3dea,
+ 0x9c5e, 0x4872,
+ 0x9c60, 0x3deb,
+ 0x9c61, 0x4874,
+ 0x9c63, 0x4875,
+ 0x9c64, 0x3ded,
+ 0x9c67, 0x4876,
+ 0x9c69, 0x4877,
+ 0x9c6a, 0x3df1,
+ 0x9c6c, 0x4878,
+ 0x9c6d, 0x3df2,
+ 0x9c6e, 0x4879,
+ 0x9c6f, 0x3df3,
+ 0x9c73, 0x487a,
+ 0x9c75, 0x3df7,
+ 0x9c78, 0x487c,
+ 0x9c79, 0x3dfa,
+ 0x9c7a, 0x487d,
+ 0x9c7b, 0x3dfb,
+ 0x9c7d, 0x487e,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca3, 0x487f,
+ 0x9ca5, 0x3e00,
+ 0x9ca6, 0x4881,
+ 0x9ca8, 0x3e01,
+ 0x9caa, 0x4883,
+ 0x9cab, 0x3e03,
+ 0x9cac, 0x4884,
+ 0x9cad, 0x3e04,
+ 0x9caf, 0x4885,
+ 0x9cb1, 0x3e06,
+ 0x9cbb, 0x4887,
+ 0x9cbe, 0x3e12,
+ 0x9cc3, 0x4888,
+ 0x9cc6, 0x3e17,
+ 0x9cce, 0x488b,
+ 0x9ccf, 0x3e1f,
+ 0x9cd1, 0x3e21,
+ 0x9cd4, 0x488c,
+ 0x9cd8, 0x3e24,
+ 0x9cdb, 0x4890,
+ 0x9cdc, 0x3e27,
+ 0x9ce6, 0x4891,
+ 0x9ce7, 0x3e31,
+ 0x9cea, 0x4892,
+ 0x9ceb, 0x3e34,
+ 0x9ced, 0x4893,
+ 0x9cee, 0x3e36,
+ 0x9cfa, 0x4894,
+ 0x9cfd, 0x3e42,
+ 0x9cfe, 0x4897,
+ 0x9d40, 0x43e8,
+ 0x9d41, 0x4898,
+ 0x9d46, 0x3e43,
+ 0x9d47, 0x489d,
+ 0x9d49, 0x3e44,
+ 0x9d4a, 0x489f,
+ 0x9d4c, 0x3e46,
+ 0x9d4e, 0x48a1,
+ 0x9d4f, 0x3e48,
+ 0x9d50, 0x48a2,
+ 0x9d51, 0x3e49,
+ 0x9d52, 0x48a3,
+ 0x9d55, 0x3e4a,
+ 0x9d56, 0x48a6,
+ 0x9d58, 0x48a7,
+ 0x9d5b, 0x48a9,
+ 0x9d61, 0x43c9,
+ 0x9d62, 0x3e4c,
+ 0x9d63, 0x48af,
+ 0x9d64, 0x3e4d,
+ 0x9d65, 0x48b0,
+ 0x9d78, 0x43f5,
+ 0x9d79, 0x3e4e,
+ 0x9d7a, 0x48c3,
+ 0x9d7e, 0x3e4f,
+ 0x9da1, 0x48c7,
+ 0x9da5, 0x3e50,
+ 0x9da9, 0x48cb,
+ 0x9daa, 0x3e54,
+ 0x9dab, 0x48cc,
+ 0x9dac, 0x3e55,
+ 0x9dae, 0x48cd,
+ 0x9db0, 0x3e58,
+ 0x9db1, 0x48cf,
+ 0x9db3, 0x3e59,
+ 0x9db4, 0x48d1,
+ 0x9db5, 0x3e5a,
+ 0x9db6, 0x48d2,
+ 0x9db7, 0x3e5b,
+ 0x9db8, 0x48d3,
+ 0x9dbc, 0x3e5c,
+ 0x9dbe, 0x48d7,
+ 0x9dbf, 0x3e5e,
+ 0x9dc1, 0x48d8,
+ 0x9dc3, 0x3e60,
+ 0x9dc5, 0x48da,
+ 0x9dc7, 0x3e62,
+ 0x9dc9, 0x48dc,
+ 0x9dca, 0x3e64,
+ 0x9dcb, 0x48dd,
+ 0x9dcd, 0x3e65,
+ 0x9dd2, 0x48df,
+ 0x9dd3, 0x3e6a,
+ 0x9dd6, 0x48e0,
+ 0x9dda, 0x3e6d,
+ 0x9dfc, 0x48e4,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e43, 0x48e5,
+ 0x9e44, 0x3e95,
+ 0x9e5f, 0x48e6,
+ 0x9e60, 0x3eb1,
+ 0x9e63, 0x48e7,
+ 0x9e64, 0x3eb4,
+ 0x9e66, 0x48e8,
+ 0x9e68, 0x3eb6,
+ 0x9e69, 0x48ea,
+ 0x9e6a, 0x3eb7,
+ 0x9e6b, 0x48eb,
+ 0x9e71, 0x3eb8,
+ 0x9e72, 0x48f1,
+ 0x9e73, 0x3eb9,
+ 0x9e74, 0x48f2,
+ 0x9e77, 0x3eba,
+ 0x9e79, 0x48f5,
+ 0x9e7a, 0x3ebc,
+ 0x9e7b, 0x48f6,
+ 0x9e7c, 0x3ebd,
+ 0x9e7d, 0x48f7,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea3, 0x48f8,
+ 0x9ea4, 0x3ec1,
+ 0x9ea7, 0x48f9,
+ 0x9eaa, 0x3ec5,
+ 0x9eab, 0x48fb,
+ 0x9ead, 0x3ec7,
+ 0x9eae, 0x48fc,
+ 0x9eaf, 0x3ec8,
+ 0x9eb2, 0x48fd,
+ 0x9eb4, 0x3ecb,
+ 0x9eb5, 0x48ff,
+ 0x9eb6, 0x3ecc,
+ 0x9eb8, 0x4900,
+ 0x9eb9, 0x3ece,
+ 0x9eba, 0x4901,
+ 0x9ebc, 0x3ecf,
+ 0x9ebd, 0x4903,
+ 0x9ebf, 0x3ed0,
+ 0x9ec1, 0x4905,
+ 0x9ec5, 0x3ed3,
+ 0x9ec6, 0x4908,
+ 0x9ec7, 0x3ed4,
+ 0x9ecb, 0x4909,
+ 0x9ecd, 0x3ed9,
+ 0x9ece, 0x490b,
+ 0x9ed0, 0x3eda,
+ 0x9ed2, 0x490d,
+ 0x9ed3, 0x3edc,
+ 0x9ed4, 0x490e,
+ 0x9ed6, 0x3edd,
+ 0x9ed8, 0x4910,
+ 0x9eda, 0x3edf,
+ 0x9ef0, 0x3ef5,
+ 0x9ef2, 0x4912,
+ 0x9ef3, 0x3ef7,
+ 0x9ef5, 0x3ef9,
+ 0x9ef6, 0x4913,
+ 0x9ef9, 0x3efa,
+ 0x9efb, 0x4916,
+ 0x9efc, 0x3efc,
+ 0x9efe, 0x3efe,
+ 0x9f40, 0x3eff,
+ 0x9f43, 0x4917,
+ 0x9f44, 0x3f02,
+ 0x9f48, 0x4918,
+ 0x9f49, 0x3f06,
+ 0x9f4b, 0x4919,
+ 0x9f4d, 0x3f08,
+ 0x9f4f, 0x3f0a,
+ 0x9f61, 0x3f1c,
+ 0x9f67, 0x491b,
+ 0x9f69, 0x3f23,
+ 0x9f70, 0x491d,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fae, 0x3f45,
+ 0x9fb2, 0x3f49,
+ 0x9fb5, 0x491e,
+ 0x9fb6, 0x3f4c,
+ 0x9fbb, 0x491f,
+ 0x9fbc, 0x3f51,
+ 0x9fbf, 0x4920,
+ 0x9fc1, 0x4921,
+ 0x9fc2, 0x3f55,
+ 0x9fc9, 0x3f5c,
+ 0x9fcc, 0x4922,
+ 0x9fcd, 0x3f60,
+ 0x9fd4, 0x4923,
+ 0x9fd5, 0x3f68,
+ 0x9fd9, 0x3f6c,
+ 0x9fdb, 0x3f6e,
+ 0x9fe4, 0x4924,
+ 0x9fe5, 0x3f77,
+ 0x9fe7, 0x3f79,
+ 0x9feb, 0x3f7d,
+ 0x9ff0, 0x3f82,
+ 0x9ff9, 0x4925,
+ 0x9ffa, 0x3f8b,
+ 0xa040, 0x4926,
+ 0xa041, 0x3f90,
+ 0xa047, 0x4927,
+ 0xa048, 0x3f96,
+ 0xa055, 0x4928,
+ 0xa056, 0x3fa3,
+ 0xa058, 0x3fa5,
+ 0xa05b, 0x3fa8,
+ 0xa064, 0x3fb1,
+ 0xa06d, 0x4929,
+ 0xa06e, 0x3fba,
+ 0xa073, 0x3fbf,
+ 0xa078, 0x3fc4,
+ 0xa07b, 0x492a,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a2, 0x492b,
+ 0xa0a3, 0x3fcb,
+ 0xa0a6, 0x3fce,
+ 0xa0a7, 0x492c,
+ 0xa0a8, 0x3fcf,
+ 0xa0ae, 0x3fd5,
+ 0xa0b0, 0x3fd7,
+ 0xa0c5, 0x492d,
+ 0xa0c6, 0x3fec,
+ 0xa0d0, 0x492e,
+ 0xa0d1, 0x3ff6,
+ 0xa0d4, 0x3ff9,
+ 0xa0d6, 0x3ffb,
+ 0xa0e0, 0x4005,
+ 0xa0e2, 0x4007,
+ 0xa0e3, 0x492f,
+ 0xa0e5, 0x4009,
+ 0xa0e7, 0x4930,
+ 0xa0ee, 0x43b4,
+ 0xa0ef, 0x4937,
+ 0xa0f2, 0x43b8,
+ 0xa0f3, 0x493a,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc8d4, 0x44c6,
+ 0xc8d7, 0x451c,
+ 0xc8e0, 0x02dc,
+ 0xc8e1, 0x4525,
+ 0xc8e9, 0x0509,
+ 0xc8ea, 0x452d,
+ 0xc8f1, 0x09f6,
+ 0xc8f5, 0x4992,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xfa40, 0x400b,
+ 0xfa60, 0x402b,
+ 0xfa67, 0x4032,
+ 0xfaa1, 0x404a,
+ 0xfaa9, 0x4946,
+ 0xfaab, 0x4054,
+ 0xfabe, 0x4067,
+ 0xfac6, 0x406f,
+ 0xfad6, 0x407f,
+ 0xfb40, 0x40a8,
+ 0xfb49, 0x40b1,
+ 0xfb53, 0x4948,
+ 0xfb54, 0x40bc,
+ 0xfb6e, 0x4949,
+ 0xfb6f, 0x40d7,
+ 0xfba1, 0x40e7,
+ 0xfba3, 0x494a,
+ 0xfba4, 0x40ea,
+ 0xfbb9, 0x40ff,
+ 0xfbbf, 0x494b,
+ 0xfbc0, 0x4105,
+ 0xfbcd, 0x494c,
+ 0xfbce, 0x4112,
+ 0xfbf4, 0x4138,
+ 0xfbfa, 0x413e,
+ 0xfc40, 0x4143,
+ 0xfc4a, 0x494d,
+ 0xfc4b, 0x414d,
+ 0xfc50, 0x4151,
+ 0xfc52, 0x494e,
+ 0xfc53, 0x4153,
+ 0xfc63, 0x494f,
+ 0xfc64, 0x4163,
+ 0xfc6d, 0x4950,
+ 0xfc6e, 0x416d,
+ 0xfc75, 0x4951,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcba, 0x4195,
+ 0xfcbc, 0x4952,
+ 0xfcbe, 0x4198,
+ 0xfccc, 0x4954,
+ 0xfccd, 0x41a7,
+ 0xfce3, 0x4955,
+ 0xfce4, 0x41bd,
+ 0xfcee, 0x4956,
+ 0xfcef, 0x41c7,
+ 0xfcf2, 0x41ca,
+ 0xfd40, 0x41d7,
+ 0xfd49, 0x4957,
+ 0xfd4a, 0x41e0,
+ 0xfd6a, 0x4958,
+ 0xfd6b, 0x4201,
+ 0xfda1, 0x4215,
+ 0xfdb9, 0x422d,
+ 0xfdbc, 0x4230,
+ 0xfde3, 0x4959,
+ 0xfde4, 0x4258,
+ 0xfdf2, 0x495a,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe53, 0x4285,
+ 0xfe6d, 0x495b,
+ 0xfe6e, 0x429f,
+ 0xfe70, 0x42a1,
+ 0xfe78, 0x495c,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeab, 0x42b8,
+ 0xfede, 0x495d,
+ 0xfee0, 0x42eb,
+ 0xfeed, 0x495f,
+ 0xfeef, 0x42f8,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xc6e4, 0x3711,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETHKB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETHKB5VMap2, 1139
+};
+
+static Gushort cns13ETenB5HMap2[510] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETenB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557,
+ 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f,
+ 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567,
+ 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f,
+ 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577,
+ 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x357f,
+ 0x3580, 0x3581, 0x3582, 0x3583, 0x3584, 0x3585, 0x3586, 0x3587,
+ 0x3588, 0x3589, 0x358a, 0x358b, 0x358c, 0x358d, 0x358e, 0x358f,
+ 0x3590, 0x3591, 0x3592, 0x3593, 0x3594, 0x3595, 0x3596, 0x3597,
+ 0x3598, 0x3599, 0x359a, 0x359b, 0x359c, 0x359d, 0x359e, 0x359f,
+ 0x35a0, 0x35a1, 0x35a2, 0x35a3, 0x35a4, 0x35a5, 0x35a6, 0x35a7,
+ 0x35a8, 0x35a9, 0x35aa, 0x35ab, 0x35ac, 0x35ad, 0x35ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETenB5HMap2, 255
+};
+
+static Gushort cns13ETenB5VMap2[536] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xc6e4, 0x3711,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETenB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3550, 0x3551, 0x3552, 0x3553, 0x3554, 0x3555, 0x3556, 0x3557,
+ 0x3558, 0x3559, 0x355a, 0x355b, 0x355c, 0x355d, 0x355e, 0x355f,
+ 0x3560, 0x3561, 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567,
+ 0x3568, 0x3569, 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f,
+ 0x3570, 0x3571, 0x3572, 0x3573, 0x3574, 0x3575, 0x3576, 0x3577,
+ 0x3578, 0x3579, 0x357a, 0x357b, 0x357c, 0x357d, 0x357e, 0x357f,
+ 0x3580, 0x3581, 0x3582, 0x3583, 0x3584, 0x3585, 0x3586, 0x3587,
+ 0x3588, 0x3589, 0x358a, 0x358b, 0x358c, 0x358d, 0x358e, 0x358f,
+ 0x3590, 0x3591, 0x3592, 0x3593, 0x3594, 0x3595, 0x3596, 0x3597,
+ 0x3598, 0x3599, 0x359a, 0x359b, 0x359c, 0x359d, 0x359e, 0x359f,
+ 0x35a0, 0x35a1, 0x35a2, 0x35a3, 0x35a4, 0x35a5, 0x35a6, 0x35a7,
+ 0x35a8, 0x35a9, 0x35aa, 0x35ab, 0x35ac, 0x35ad, 0x35ae, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETenB5VMap2, 268
+};
+
+static Gushort cns13ETenmsB5HMap2[510] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETenmsB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETenmsB5HMap2, 255
+};
+
+static Gushort cns13ETenmsB5VMap2[568] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa14b, 0x354e,
+ 0xa14c, 0x006d,
+ 0xa14d, 0x0070,
+ 0xa156, 0x0138,
+ 0xa157, 0x007a,
+ 0xa158, 0x007a,
+ 0xa159, 0x35af,
+ 0xa15a, 0x35af,
+ 0xa15b, 0x35b1,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa15f, 0x0082,
+ 0xa161, 0x0086,
+ 0xa163, 0x0086,
+ 0xa165, 0x008a,
+ 0xa167, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16b, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa16f, 0x0092,
+ 0xa171, 0x0096,
+ 0xa173, 0x0096,
+ 0xa175, 0x009a,
+ 0xa177, 0x009a,
+ 0xa179, 0x009e,
+ 0xa17b, 0x009e,
+ 0xa17d, 0x0082,
+ 0xa1a1, 0x0086,
+ 0xa1a3, 0x008a,
+ 0xa1a5, 0x00a6,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d8, 0x35b3,
+ 0xc6df, 0x1794,
+ 0xc6e0, 0x35ba,
+ 0xc6e4, 0x3711,
+ 0xc6e6, 0x35c0,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13ETenmsB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13ETenmsB5VMap2, 284
+};
+
+static Gushort cns13HKdlaB5HMap2[2046] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa41, 0x4149,
+ 0xfa42, 0x3ea3,
+ 0xfa43, 0x3e84,
+ 0xfa44, 0x3e87,
+ 0xfa45, 0x3e05,
+ 0xfa46, 0x4096,
+ 0xfa47, 0x39c4,
+ 0xfa48, 0x3d6d,
+ 0xfa49, 0x3e7f,
+ 0xfa4a, 0x3c77,
+ 0xfa4b, 0x3e86,
+ 0xfa4c, 0x387c,
+ 0xfa4d, 0x3ea7,
+ 0xfa4e, 0x420e,
+ 0xfa4f, 0x3ea4,
+ 0xfa50, 0x418a,
+ 0xfa51, 0x405f,
+ 0xfa52, 0x4116,
+ 0xfa53, 0x408b,
+ 0xfa54, 0x3e66,
+ 0xfa55, 0x3e65,
+ 0xfa56, 0x3d8f,
+ 0xfa57, 0x419e,
+ 0xfa58, 0x3a66,
+ 0xfa59, 0x4161,
+ 0xfa5a, 0x3e8a,
+ 0xfa5b, 0x3d8e,
+ 0xfa5c, 0x3e8d,
+ 0xfa5d, 0x3dbc,
+ 0xfa5e, 0x3e95,
+ 0xfa5f, 0x39a3,
+ 0xfa60, 0x41f4,
+ 0xfa61, 0x3e91,
+ 0xfa62, 0x3bc6,
+ 0xfa63, 0x3dc3,
+ 0xfa64, 0x3eae,
+ 0xfa65, 0x3746,
+ 0xfa66, 0x3871,
+ 0xfa67, 0x3a00,
+ 0xfa68, 0x428c,
+ 0xfa69, 0x425b,
+ 0xfa6a, 0x3ead,
+ 0xfa6b, 0x4123,
+ 0xfa6c, 0x3ea6,
+ 0xfa6d, 0x3ea0,
+ 0xfa6e, 0x3b2e,
+ 0xfa6f, 0x3dbd,
+ 0xfa70, 0x3864,
+ 0xfa71, 0x3c7d,
+ 0xfa72, 0x3ea9,
+ 0xfa73, 0x420d,
+ 0xfa74, 0x3f58,
+ 0xfa75, 0x3e98,
+ 0xfa76, 0x3d70,
+ 0xfa77, 0x3ea8,
+ 0xfa78, 0x3e94,
+ 0xfa79, 0x3e9d,
+ 0xfa7a, 0x3aaa,
+ 0xfa7b, 0x3ea5,
+ 0xfa7c, 0x3ccc,
+ 0xfa7d, 0x4098,
+ 0xfa7e, 0x3e9f,
+ 0xfaa1, 0x41f5,
+ 0xfaa2, 0x3e8b,
+ 0xfaa3, 0x3b72,
+ 0xfaa4, 0x37e0,
+ 0xfaa5, 0x3adf,
+ 0xfaa6, 0x42e0,
+ 0xfaa7, 0x3e97,
+ 0xfaa8, 0x4192,
+ 0xfaa9, 0x3888,
+ 0xfaaa, 0x42c8,
+ 0xfaab, 0x3e90,
+ 0xfaac, 0x386f,
+ 0xfaad, 0x3e9c,
+ 0xfaae, 0x4144,
+ 0xfaaf, 0x4146,
+ 0xfab0, 0x3e9e,
+ 0xfab1, 0x3e89,
+ 0xfab2, 0x4093,
+ 0xfab3, 0x3e81,
+ 0xfab5, 0x3c0e,
+ 0xfab6, 0x3e85,
+ 0xfab7, 0x38dc,
+ 0xfab8, 0x4069,
+ 0xfab9, 0x37d8,
+ 0xfaba, 0x3e99,
+ 0xfabb, 0x3e83,
+ 0xfabc, 0x3e88,
+ 0xfabd, 0x3e80,
+ 0xfabe, 0x3eb1,
+ 0xfabf, 0x416a,
+ 0xfac0, 0x376b,
+ 0xfac1, 0x3e67,
+ 0xfac2, 0x3e78,
+ 0xfac3, 0x4262,
+ 0xfac4, 0x37f5,
+ 0xfac5, 0x37f4,
+ 0xfac6, 0x3b45,
+ 0xfac7, 0x3e59,
+ 0xfac8, 0x2abc,
+ 0xfac9, 0x3dbf,
+ 0xfaca, 0x40bd,
+ 0xfacb, 0x3e7e,
+ 0xfacc, 0x382d,
+ 0xfacd, 0x3eb0,
+ 0xface, 0x3eab,
+ 0xfacf, 0x3eb2,
+ 0xfad0, 0x4221,
+ 0xfad1, 0x3f6a,
+ 0xfad2, 0x381b,
+ 0xfad3, 0x3e9a,
+ 0xfad4, 0x4223,
+ 0xfad5, 0x3e8e,
+ 0xfad6, 0x3bfd,
+ 0xfad7, 0x405a,
+ 0xfad8, 0x3eaf,
+ 0xfad9, 0x3cc8,
+ 0xfada, 0x3948,
+ 0xfadb, 0x42bd,
+ 0xfadc, 0x40cc,
+ 0xfadd, 0x3e5c,
+ 0xfade, 0x3eac,
+ 0xfadf, 0x391a,
+ 0xfae0, 0x3eaa,
+ 0xfae1, 0x4399,
+ 0xfae2, 0x389a,
+ 0xfae3, 0x3e8c,
+ 0xfae4, 0x389f,
+ 0xfae5, 0x3ea1,
+ 0xfae6, 0x4187,
+ 0xfae7, 0x3e8f,
+ 0xfae8, 0x3fc3,
+ 0xfae9, 0x3ea2,
+ 0xfaea, 0x3e9b,
+ 0xfaeb, 0x3e7d,
+ 0xfaec, 0x4051,
+ 0xfaed, 0x3fbc,
+ 0xfaee, 0x3fd5,
+ 0xfaef, 0x3b14,
+ 0xfaf0, 0x4222,
+ 0xfaf1, 0x379b,
+ 0xfaf2, 0x407b,
+ 0xfaf3, 0x3788,
+ 0xfaf4, 0x3bb4,
+ 0xfaf5, 0x41d0,
+ 0xfaf6, 0x4264,
+ 0xfaf7, 0x385e,
+ 0xfaf8, 0x376c,
+ 0xfaf9, 0x3dbe,
+ 0xfafa, 0x3813,
+ 0xfafb, 0x3fff,
+ 0xfafc, 0x3d63,
+ 0xfafd, 0x3786,
+ 0xfafe, 0x3b4a,
+ 0xfb40, 0x373a,
+ 0xfb41, 0x427a,
+ 0xfb42, 0x3c7a,
+ 0xfb43, 0x4205,
+ 0xfb44, 0x3c26,
+ 0xfb45, 0x38af,
+ 0xfb46, 0x3936,
+ 0xfb47, 0x37a8,
+ 0xfb48, 0x3b74,
+ 0xfb49, 0x3f6d,
+ 0xfb4a, 0x3e96,
+ 0xfb4b, 0x37bc,
+ 0xfb4c, 0x3e7b,
+ 0xfb4d, 0x3fea,
+ 0xfb4e, 0x41ca,
+ 0xfb4f, 0x39d7,
+ 0xfb50, 0x40d1,
+ 0xfb51, 0x3b71,
+ 0xfb52, 0x3fcf,
+ 0xfb53, 0x07c2,
+ 0xfb54, 0x42fe,
+ 0xfb55, 0x3ccd,
+ 0xfb56, 0x3e70,
+ 0xfb57, 0x3e72,
+ 0xfb58, 0x374c,
+ 0xfb59, 0x3769,
+ 0xfb5a, 0x3b4f,
+ 0xfb5b, 0x379f,
+ 0xfb5c, 0x2e45,
+ 0xfb5d, 0x380d,
+ 0xfb5e, 0x3fa2,
+ 0xfb5f, 0x381c,
+ 0xfb60, 0x3f7c,
+ 0xfb61, 0x3f59,
+ 0xfb62, 0x3f9e,
+ 0xfb63, 0x3d93,
+ 0xfb64, 0x3815,
+ 0xfb65, 0x388b,
+ 0xfb66, 0x3c60,
+ 0xfb67, 0x38f0,
+ 0xfb68, 0x37aa,
+ 0xfb69, 0x3f34,
+ 0xfb6a, 0x3c12,
+ 0xfb6b, 0x3900,
+ 0xfb6c, 0x3faa,
+ 0xfb6d, 0x390b,
+ 0xfb6e, 0x3929,
+ 0xfb6f, 0x3f27,
+ 0xfb70, 0x3f90,
+ 0xfb71, 0x3f57,
+ 0xfb72, 0x3f5b,
+ 0xfb73, 0x3f62,
+ 0xfb74, 0x3d76,
+ 0xfb75, 0x39c8,
+ 0xfb76, 0x3f64,
+ 0xfb78, 0x393d,
+ 0xfb79, 0x3c66,
+ 0xfb7a, 0x39d0,
+ 0xfb7b, 0x4022,
+ 0xfb7c, 0x3f2c,
+ 0xfb7d, 0x3f28,
+ 0xfb7e, 0x39cc,
+ 0xfba1, 0x3f26,
+ 0xfba2, 0x39cd,
+ 0xfba3, 0x3f3f,
+ 0xfba4, 0x39c5,
+ 0xfba5, 0x3fce,
+ 0xfba6, 0x4034,
+ 0xfba7, 0x3f5e,
+ 0xfba8, 0x4032,
+ 0xfba9, 0x4054,
+ 0xfbaa, 0x4178,
+ 0xfbab, 0x3f60,
+ 0xfbac, 0x3f29,
+ 0xfbad, 0x405d,
+ 0xfbae, 0x3f43,
+ 0xfbaf, 0x3f68,
+ 0xfbb0, 0x4060,
+ 0xfbb1, 0x3f2a,
+ 0xfbb2, 0x4063,
+ 0xfbb3, 0x39e7,
+ 0xfbb4, 0x38b6,
+ 0xfbb5, 0x4090,
+ 0xfbb6, 0x4048,
+ 0xfbb7, 0x4012,
+ 0xfbb8, 0x3d7c,
+ 0xfbb9, 0x404b,
+ 0xfbba, 0x404d,
+ 0xfbbb, 0x404f,
+ 0xfbbc, 0x424f,
+ 0xfbbd, 0x3d79,
+ 0xfbbe, 0x3f40,
+ 0xfbbf, 0x3f0a,
+ 0xfbc0, 0x3fd0,
+ 0xfbc1, 0x3f36,
+ 0xfbc2, 0x406d,
+ 0xfbc3, 0x4085,
+ 0xfbc4, 0x4084,
+ 0xfbc5, 0x413e,
+ 0xfbc6, 0x413b,
+ 0xfbc7, 0x3fc6,
+ 0xfbc8, 0x4086,
+ 0xfbc9, 0x3952,
+ 0xfbca, 0x40a1,
+ 0xfbcb, 0x3f32,
+ 0xfbcc, 0x4203,
+ 0xfbcd, 0x3f66,
+ 0xfbce, 0x3d83,
+ 0xfbcf, 0x3e75,
+ 0xfbd0, 0x40a2,
+ 0xfbd1, 0x0570,
+ 0xfbd2, 0x3f39,
+ 0xfbd3, 0x0871,
+ 0xfbd4, 0x3f24,
+ 0xfbd5, 0x40ae,
+ 0xfbd6, 0x3f44,
+ 0xfbd7, 0x38f5,
+ 0xfbd8, 0x3fc9,
+ 0xfbd9, 0x3fcd,
+ 0xfbda, 0x3fb5,
+ 0xfbdb, 0x3e7c,
+ 0xfbdc, 0x3fd2,
+ 0xfbdd, 0x3f4d,
+ 0xfbde, 0x40bc,
+ 0xfbdf, 0x40b7,
+ 0xfbe0, 0x3858,
+ 0xfbe1, 0x43af,
+ 0xfbe2, 0x3f6c,
+ 0xfbe3, 0x3d85,
+ 0xfbe4, 0x4396,
+ 0xfbe5, 0x39a6,
+ 0xfbe6, 0x3f7d,
+ 0xfbe7, 0x3fbf,
+ 0xfbe8, 0x40c8,
+ 0xfbe9, 0x3f5f,
+ 0xfbea, 0x3f2b,
+ 0xfbeb, 0x3d72,
+ 0xfbec, 0x40cf,
+ 0xfbed, 0x3a05,
+ 0xfbee, 0x3d82,
+ 0xfbef, 0x40dc,
+ 0xfbf0, 0x3d65,
+ 0xfbf1, 0x40d4,
+ 0xfbf2, 0x40da,
+ 0xfbf3, 0x3f2d,
+ 0xfbf4, 0x0595,
+ 0xfbf5, 0x3d81,
+ 0xfbf6, 0x40f1,
+ 0xfbf7, 0x06f5,
+ 0xfbf8, 0x40f8,
+ 0xfbf9, 0x40fb,
+ 0xfbfa, 0x3f41,
+ 0xfbfb, 0x4118,
+ 0xfbfc, 0x3d89,
+ 0xfbfd, 0x3f5c,
+ 0xfbfe, 0x3d67,
+ 0xfc40, 0x3f0e,
+ 0xfc41, 0x3f13,
+ 0xfc42, 0x4122,
+ 0xfc43, 0x3fca,
+ 0xfc44, 0x4129,
+ 0xfc45, 0x3f0c,
+ 0xfc46, 0x3f0b,
+ 0xfc47, 0x3f61,
+ 0xfc48, 0x3d8a,
+ 0xfc49, 0x3f2e,
+ 0xfc4a, 0x1971,
+ 0xfc4b, 0x4135,
+ 0xfc4c, 0x3a2b,
+ 0xfc4d, 0x3f6b,
+ 0xfc4e, 0x3ba5,
+ 0xfc4f, 0x4044,
+ 0xfc50, 0x4255,
+ 0xfc51, 0x3737,
+ 0xfc52, 0x3f25,
+ 0xfc53, 0x3739,
+ 0xfc54, 0x3a30,
+ 0xfc55, 0x4143,
+ 0xfc56, 0x40c4,
+ 0xfc57, 0x3d64,
+ 0xfc58, 0x3fbe,
+ 0xfc59, 0x3fa6,
+ 0xfc5a, 0x402c,
+ 0xfc5b, 0x4157,
+ 0xfc5c, 0x3f9f,
+ 0xfc5d, 0x2b40,
+ 0xfc5e, 0x3fa7,
+ 0xfc5f, 0x4005,
+ 0xfc60, 0x4001,
+ 0xfc61, 0x1c9b,
+ 0xfc62, 0x3d84,
+ 0xfc63, 0x0a95,
+ 0xfc64, 0x416c,
+ 0xfc65, 0x4009,
+ 0xfc66, 0x3d75,
+ 0xfc67, 0x3adc,
+ 0xfc68, 0x3fa8,
+ 0xfc69, 0x3f37,
+ 0xfc6a, 0x4174,
+ 0xfc6b, 0x4006,
+ 0xfc6c, 0x4002,
+ 0xfc6d, 0x3fba,
+ 0xfc6e, 0x3fc0,
+ 0xfc6f, 0x12b0,
+ 0xfc70, 0x3fbd,
+ 0xfc71, 0x4173,
+ 0xfc72, 0x4186,
+ 0xfc73, 0x3a54,
+ 0xfc74, 0x3fc5,
+ 0xfc75, 0x4259,
+ 0xfc76, 0x3fc2,
+ 0xfc77, 0x3f15,
+ 0xfc78, 0x3f50,
+ 0xfc79, 0x3f86,
+ 0xfc7a, 0x3fc1,
+ 0xfc7b, 0x418c,
+ 0xfc7c, 0x3fc7,
+ 0xfc7d, 0x3f16,
+ 0xfc7e, 0x418e,
+ 0xfca1, 0x3f4b,
+ 0xfca2, 0x419d,
+ 0xfca3, 0x115f,
+ 0xfca4, 0x3fc4,
+ 0xfca5, 0x3384,
+ 0xfca6, 0x3d99,
+ 0xfca7, 0x41b9,
+ 0xfca8, 0x3a89,
+ 0xfca9, 0x41b7,
+ 0xfcaa, 0x3d8b,
+ 0xfcab, 0x3d66,
+ 0xfcac, 0x03e2,
+ 0xfcad, 0x3d6a,
+ 0xfcae, 0x3d7a,
+ 0xfcaf, 0x41e3,
+ 0xfcb0, 0x0619,
+ 0xfcb1, 0x3996,
+ 0xfcb2, 0x3fc8,
+ 0xfcb3, 0x3a9e,
+ 0xfcb4, 0x3f38,
+ 0xfcb5, 0x3d80,
+ 0xfcb6, 0x41de,
+ 0xfcb8, 0x42eb,
+ 0xfcb9, 0x3d86,
+ 0xfcba, 0x41db,
+ 0xfcbb, 0x3f3e,
+ 0xfcbc, 0x4056,
+ 0xfcbd, 0x41d9,
+ 0xfcbe, 0x3ff6,
+ 0xfcbf, 0x3f5d,
+ 0xfcc0, 0x3d74,
+ 0xfcc1, 0x41e8,
+ 0xfcc2, 0x41c7,
+ 0xfcc3, 0x3d91,
+ 0xfcc4, 0x3b4b,
+ 0xfcc5, 0x3d42,
+ 0xfcc6, 0x3aad,
+ 0xfcc7, 0x3aa5,
+ 0xfcc8, 0x41f2,
+ 0xfcc9, 0x3f4c,
+ 0xfcca, 0x41f8,
+ 0xfccb, 0x3f6e,
+ 0xfccc, 0x3f79,
+ 0xfccd, 0x3f8d,
+ 0xfcce, 0x4003,
+ 0xfccf, 0x3f91,
+ 0xfcd0, 0x3ac3,
+ 0xfcd1, 0x091a,
+ 0xfcd2, 0x4234,
+ 0xfcd3, 0x3ffb,
+ 0xfcd4, 0x4240,
+ 0xfcd6, 0x3ffd,
+ 0xfcd7, 0x3f78,
+ 0xfcd8, 0x3c75,
+ 0xfcd9, 0x3c73,
+ 0xfcda, 0x38a5,
+ 0xfcdb, 0x43f9,
+ 0xfcdc, 0x3cfe,
+ 0xfcdd, 0x4257,
+ 0xfcde, 0x4233,
+ 0xfcdf, 0x3d69,
+ 0xfce0, 0x3c7e,
+ 0xfce1, 0x3d6f,
+ 0xfce2, 0x4000,
+ 0xfce3, 0x3dc0,
+ 0xfce4, 0x4004,
+ 0xfce5, 0x0e72,
+ 0xfce6, 0x3938,
+ 0xfce7, 0x3fa4,
+ 0xfce8, 0x295a,
+ 0xfce9, 0x4273,
+ 0xfcea, 0x3ac9,
+ 0xfceb, 0x427d,
+ 0xfcec, 0x3aca,
+ 0xfced, 0x3fb2,
+ 0xfcee, 0x3fb6,
+ 0xfcef, 0x3f97,
+ 0xfcf0, 0x3f9a,
+ 0xfcf1, 0x428b,
+ 0xfcf2, 0x43fa,
+ 0xfcf3, 0x428a,
+ 0xfcf4, 0x3f51,
+ 0xfcf5, 0x3f98,
+ 0xfcf6, 0x41a3,
+ 0xfcf7, 0x3d5c,
+ 0xfcf8, 0x3f63,
+ 0xfcf9, 0x4290,
+ 0xfcfa, 0x1f94,
+ 0xfcfb, 0x42c6,
+ 0xfcfc, 0x42a2,
+ 0xfcfd, 0x3ffa,
+ 0xfcfe, 0x3f9d,
+ 0xfd40, 0x3ffe,
+ 0xfd41, 0x3f9b,
+ 0xfd42, 0x3fdf,
+ 0xfd43, 0x3fe6,
+ 0xfd44, 0x3fde,
+ 0xfd45, 0x42b7,
+ 0xfd46, 0x3ff4,
+ 0xfd47, 0x42b8,
+ 0xfd48, 0x3feb,
+ 0xfd49, 0x42bf,
+ 0xfd4a, 0x3d71,
+ 0xfd4b, 0x3f4f,
+ 0xfd4c, 0x42c5,
+ 0xfd4d, 0x42d5,
+ 0xfd4e, 0x42d0,
+ 0xfd4f, 0x42d8,
+ 0xfd50, 0x3f55,
+ 0xfd51, 0x3fe8,
+ 0xfd52, 0x3ff3,
+ 0xfd53, 0x42df,
+ 0xfd54, 0x3fd3,
+ 0xfd55, 0x3e73,
+ 0xfd56, 0x3f95,
+ 0xfd57, 0x42ee,
+ 0xfd58, 0x42f4,
+ 0xfd59, 0x3f8c,
+ 0xfd5a, 0x3fcf,
+ 0xfd5b, 0x42ec,
+ 0xfd5c, 0x3fd4,
+ 0xfd5d, 0x42f0,
+ 0xfd5e, 0x07c2,
+ 0xfd5f, 0x0955,
+ 0xfd60, 0x42fe,
+ 0xfd61, 0x4301,
+ 0xfd62, 0x3ccd,
+ 0xfd63, 0x4307,
+ 0xfd64, 0x43fb,
+ 0xfd65, 0x3fda,
+ 0xfd66, 0x3f8b,
+ 0xfd67, 0x3733,
+ 0xfd68, 0x3f8a,
+ 0xfd69, 0x3741,
+ 0xfd6a, 0x3740,
+ 0xfd6b, 0x3742,
+ 0xfd6c, 0x3f93,
+ 0xfd6d, 0x3f8f,
+ 0xfd6e, 0x3e70,
+ 0xfd6f, 0x42c9,
+ 0xfd70, 0x3e72,
+ 0xfd71, 0x3fa9,
+ 0xfd72, 0x42cd,
+ 0xfd73, 0x43d2,
+ 0xfd74, 0x3f8e,
+ 0xfd75, 0x3f77,
+ 0xfd76, 0x3d6e,
+ 0xfd77, 0x0d0a,
+ 0xfd78, 0x3f11,
+ 0xfd79, 0x3752,
+ 0xfd7a, 0x3f14,
+ 0xfd7b, 0x3f18,
+ 0xfd7c, 0x3f53,
+ 0xfd7d, 0x3f1f,
+ 0xfd7e, 0x3f1c,
+ 0xfda1, 0x3fb8,
+ 0xfda2, 0x339d,
+ 0xfda3, 0x3b3f,
+ 0xfda4, 0x3f52,
+ 0xfda5, 0x3f1a,
+ 0xfda6, 0x3f1d,
+ 0xfda7, 0x375c,
+ 0xfda8, 0x3885,
+ 0xfda9, 0x3761,
+ 0xfdaa, 0x3fd7,
+ 0xfdab, 0x3fd6,
+ 0xfdac, 0x3fd9,
+ 0xfdad, 0x3fd8,
+ 0xfdae, 0x3fdd,
+ 0xfdaf, 0x3e93,
+ 0xfdb0, 0x3769,
+ 0xfdb1, 0x376e,
+ 0xfdb2, 0x3b4c,
+ 0xfdb3, 0x3774,
+ 0xfdb4, 0x377f,
+ 0xfdb5, 0x377b,
+ 0xfdb6, 0x3782,
+ 0xfdb7, 0x3b4f,
+ 0xfdb8, 0x3792,
+ 0xfdb9, 0x3fe3,
+ 0xfdba, 0x3fdc,
+ 0xfdbb, 0x3fdb,
+ 0xfdbc, 0x3fe5,
+ 0xfdbd, 0x3b75,
+ 0xfdbe, 0x37a2,
+ 0xfdbf, 0x3fe2,
+ 0xfdc0, 0x3fe7,
+ 0xfdc1, 0x3e6d,
+ 0xfdc2, 0x0d2a,
+ 0xfdc3, 0x3e79,
+ 0xfdc4, 0x3e76,
+ 0xfdc5, 0x379f,
+ 0xfdc6, 0x3fee,
+ 0xfdc7, 0x42d4,
+ 0xfdc8, 0x3d94,
+ 0xfdc9, 0x3d61,
+ 0xfdca, 0x3fe1,
+ 0xfdcb, 0x375e,
+ 0xfdcc, 0x3b7a,
+ 0xfdcd, 0x380b,
+ 0xfdce, 0x3fec,
+ 0xfdcf, 0x3fef,
+ 0xfdd0, 0x2e45,
+ 0xfdd1, 0x3ffc,
+ 0xfdd2, 0x3fed,
+ 0xfdd3, 0x380d,
+ 0xfdd4, 0x3fe4,
+ 0xfdd5, 0x3f92,
+ 0xfdd6, 0x3fae,
+ 0xfdd7, 0x3811,
+ 0xfdd8, 0x3f7a,
+ 0xfdd9, 0x3b8b,
+ 0xfdda, 0x3f5a,
+ 0xfddb, 0x3816,
+ 0xfddc, 0x3fa2,
+ 0xfddd, 0x3b8e,
+ 0xfdde, 0x381c,
+ 0xfddf, 0x2054,
+ 0xfde0, 0x381f,
+ 0xfde1, 0x3fa0,
+ 0xfde2, 0x43fc,
+ 0xfde3, 0x3e16,
+ 0xfde4, 0x3b94,
+ 0xfde5, 0x3f7c,
+ 0xfde6, 0x4007,
+ 0xfde7, 0x3f7b,
+ 0xfde8, 0x3d73,
+ 0xfde9, 0x3e77,
+ 0xfdea, 0x3d92,
+ 0xfdeb, 0x3fa1,
+ 0xfdec, 0x37c1,
+ 0xfded, 0x37d3,
+ 0xfdee, 0x3e7a,
+ 0xfdef, 0x3f59,
+ 0xfdf0, 0x3c55,
+ 0xfdf1, 0x3ff8,
+ 0xfdf2, 0x3ff5,
+ 0xfdf3, 0x3c4c,
+ 0xfdf4, 0x3d8c,
+ 0xfdf5, 0x3fa3,
+ 0xfdf6, 0x37c0,
+ 0xfdf7, 0x3f54,
+ 0xfdf8, 0x3800,
+ 0xfdf9, 0x3b7f,
+ 0xfdfa, 0x3f9e,
+ 0xfdfb, 0x3822,
+ 0xfdfc, 0x3fe9,
+ 0xfdfd, 0x3823,
+ 0xfdfe, 0x3fe0,
+ 0xfe40, 0x3d93,
+ 0xfe41, 0x3ff9,
+ 0xfe42, 0x3827,
+ 0xfe43, 0x3fa5,
+ 0xfe44, 0x3ff0,
+ 0xfe45, 0x3836,
+ 0xfe46, 0x3f99,
+ 0xfe47, 0x3ff2,
+ 0xfe48, 0x3d8d,
+ 0xfe49, 0x43e6,
+ 0xfe4a, 0x3522,
+ 0xfe4b, 0x3ff1,
+ 0xfe4c, 0x3f9c,
+ 0xfe4d, 0x3fb1,
+ 0xfe4e, 0x3f96,
+ 0xfe4f, 0x3e6f,
+ 0xfe50, 0x3f69,
+ 0xfe51, 0x3ff7,
+ 0xfe52, 0x3f82,
+ 0xfe53, 0x3f88,
+ 0xfe54, 0x3f85,
+ 0xfe55, 0x3f83,
+ 0xfe56, 0x3f7f,
+ 0xfe57, 0x3f89,
+ 0xfe58, 0x3bb5,
+ 0xfe59, 0x3862,
+ 0xfe5a, 0x3f87,
+ 0xfe5b, 0x3f31,
+ 0xfe5c, 0x3815,
+ 0xfe5d, 0x387e,
+ 0xfe5e, 0x3f49,
+ 0xfe5f, 0x3f48,
+ 0xfe60, 0x3f47,
+ 0xfe61, 0x3f45,
+ 0xfe62, 0x43eb,
+ 0xfe63, 0x3882,
+ 0xfe64, 0x3f6f,
+ 0xfe65, 0x3f4e,
+ 0xfe66, 0x3bc8,
+ 0xfe67, 0x43fd,
+ 0xfe68, 0x3d6b,
+ 0xfe6a, 0x43fe,
+ 0xfe6b, 0x3fcb,
+ 0xfe6c, 0x3dd2,
+ 0xfe6d, 0x3879,
+ 0xfe6e, 0x3f10,
+ 0xfe6f, 0x382e,
+ 0xfe70, 0x388b,
+ 0xfe71, 0x3c60,
+ 0xfe72, 0x2a9f,
+ 0xfe73, 0x3c61,
+ 0xfe74, 0x3893,
+ 0xfe75, 0x3e74,
+ 0xfe76, 0x3fac,
+ 0xfe77, 0x3f81,
+ 0xfe78, 0x3bcd,
+ 0xfe79, 0x3bd4,
+ 0xfe7a, 0x3bd3,
+ 0xfe7b, 0x3fcc,
+ 0xfe7c, 0x3fd1,
+ 0xfe7d, 0x3f3d,
+ 0xfe7e, 0x3f4a,
+ 0xfea1, 0x2352,
+ 0xfea2, 0x38ad,
+ 0xfea3, 0x3f46,
+ 0xfea4, 0x38b5,
+ 0xfea5, 0x3f0d,
+ 0xfea6, 0x3fb3,
+ 0xfea7, 0x38c0,
+ 0xfea8, 0x3e2f,
+ 0xfea9, 0x38cf,
+ 0xfeaa, 0x38d5,
+ 0xfeab, 0x3f33,
+ 0xfeac, 0x3d95,
+ 0xfead, 0x3f35,
+ 0xfeae, 0x38d7,
+ 0xfeaf, 0x3f2f,
+ 0xfeb0, 0x38e0,
+ 0xfeb1, 0x3c02,
+ 0xfeb2, 0x3f72,
+ 0xfeb3, 0x3f70,
+ 0xfeb4, 0x3d96,
+ 0xfeb5, 0x38e6,
+ 0xfeb7, 0x4035,
+ 0xfeb8, 0x3f73,
+ 0xfeb9, 0x38f0,
+ 0xfeba, 0x3c0b,
+ 0xfebb, 0x38f7,
+ 0xfebc, 0x37aa,
+ 0xfebd, 0x43ff,
+ 0xfebe, 0x38fa,
+ 0xfebf, 0x3c11,
+ 0xfec0, 0x3f34,
+ 0xfec1, 0x3fb9,
+ 0xfec2, 0x3c12,
+ 0xfec3, 0x400a,
+ 0xfec4, 0x3d77,
+ 0xfec5, 0x3f42,
+ 0xfec6, 0x3900,
+ 0xfec7, 0x3902,
+ 0xfec8, 0x3f74,
+ 0xfec9, 0x3d97,
+ 0xfeca, 0x3faa,
+ 0xfecb, 0x3f19,
+ 0xfecc, 0x3f1b,
+ 0xfecd, 0x390e,
+ 0xfece, 0x3909,
+ 0xfecf, 0x390b,
+ 0xfed0, 0x3f12,
+ 0xfed1, 0x3f17,
+ 0xfed2, 0x3fb7,
+ 0xfed3, 0x3f20,
+ 0xfed4, 0x3fbb,
+ 0xfed5, 0x3f3c,
+ 0xfed6, 0x3fad,
+ 0xfed7, 0x3919,
+ 0xfed8, 0x3f56,
+ 0xfed9, 0x3f71,
+ 0xfeda, 0x3fb4,
+ 0xfedb, 0x391c,
+ 0xfedc, 0x3f1e,
+ 0xfedd, 0x3f3a,
+ 0xfede, 0x391b,
+ 0xfedf, 0x3d87,
+ 0xfee0, 0x3c3a,
+ 0xfee1, 0x3f22,
+ 0xfee2, 0x3e71,
+ 0xfee3, 0x3c39,
+ 0xfee4, 0x3d7e,
+ 0xfee5, 0x4124,
+ 0xfee6, 0x3f3b,
+ 0xfee7, 0x3e6e,
+ 0xfee8, 0x3fab,
+ 0xfee9, 0x3925,
+ 0xfeea, 0x3f30,
+ 0xfeeb, 0x3929,
+ 0xfeec, 0x3f84,
+ 0xfeed, 0x3f0f,
+ 0xfeee, 0x3f76,
+ 0xfeef, 0x3f94,
+ 0xfef0, 0x3932,
+ 0xfef1, 0x3f27,
+ 0xfef2, 0x3933,
+ 0xfef3, 0x3f75,
+ 0xfef4, 0x3937,
+ 0xfef5, 0x3d78,
+ 0xfef6, 0x3f21,
+ 0xfef7, 0x3f90,
+ 0xfef8, 0x3940,
+ 0xfef9, 0x3d7f,
+ 0xfefa, 0x394a,
+ 0xfefb, 0x3f80,
+ 0xfefc, 0x3f23,
+ 0xfefd, 0x3950,
+ 0xfefe, 0x3f7e,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKdlaB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKdlaB5HMap2, 1023
+};
+
+static Gushort cns13HKdlaB5VMap2[2070] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa41, 0x4149,
+ 0xfa42, 0x3ea3,
+ 0xfa43, 0x3e84,
+ 0xfa44, 0x3e87,
+ 0xfa45, 0x3e05,
+ 0xfa46, 0x4096,
+ 0xfa47, 0x39c4,
+ 0xfa48, 0x3d6d,
+ 0xfa49, 0x3e7f,
+ 0xfa4a, 0x3c77,
+ 0xfa4b, 0x3e86,
+ 0xfa4c, 0x387c,
+ 0xfa4d, 0x3ea7,
+ 0xfa4e, 0x420e,
+ 0xfa4f, 0x3ea4,
+ 0xfa50, 0x418a,
+ 0xfa51, 0x405f,
+ 0xfa52, 0x4116,
+ 0xfa53, 0x408b,
+ 0xfa54, 0x3e66,
+ 0xfa55, 0x3e65,
+ 0xfa56, 0x3d8f,
+ 0xfa57, 0x419e,
+ 0xfa58, 0x3a66,
+ 0xfa59, 0x4161,
+ 0xfa5a, 0x3e8a,
+ 0xfa5b, 0x3d8e,
+ 0xfa5c, 0x3e8d,
+ 0xfa5d, 0x3dbc,
+ 0xfa5e, 0x3e95,
+ 0xfa5f, 0x39a3,
+ 0xfa60, 0x41f4,
+ 0xfa61, 0x3e91,
+ 0xfa62, 0x3bc6,
+ 0xfa63, 0x3dc3,
+ 0xfa64, 0x3eae,
+ 0xfa65, 0x3746,
+ 0xfa66, 0x3871,
+ 0xfa67, 0x3a00,
+ 0xfa68, 0x428c,
+ 0xfa69, 0x425b,
+ 0xfa6a, 0x3ead,
+ 0xfa6b, 0x4123,
+ 0xfa6c, 0x3ea6,
+ 0xfa6d, 0x3ea0,
+ 0xfa6e, 0x3b2e,
+ 0xfa6f, 0x3dbd,
+ 0xfa70, 0x3864,
+ 0xfa71, 0x3c7d,
+ 0xfa72, 0x3ea9,
+ 0xfa73, 0x420d,
+ 0xfa74, 0x3f58,
+ 0xfa75, 0x3e98,
+ 0xfa76, 0x3d70,
+ 0xfa77, 0x3ea8,
+ 0xfa78, 0x3e94,
+ 0xfa79, 0x3e9d,
+ 0xfa7a, 0x3aaa,
+ 0xfa7b, 0x3ea5,
+ 0xfa7c, 0x3ccc,
+ 0xfa7d, 0x4098,
+ 0xfa7e, 0x3e9f,
+ 0xfaa1, 0x41f5,
+ 0xfaa2, 0x3e8b,
+ 0xfaa3, 0x3b72,
+ 0xfaa4, 0x37e0,
+ 0xfaa5, 0x3adf,
+ 0xfaa6, 0x42e0,
+ 0xfaa7, 0x3e97,
+ 0xfaa8, 0x4192,
+ 0xfaa9, 0x3888,
+ 0xfaaa, 0x42c8,
+ 0xfaab, 0x3e90,
+ 0xfaac, 0x386f,
+ 0xfaad, 0x3e9c,
+ 0xfaae, 0x4144,
+ 0xfaaf, 0x4146,
+ 0xfab0, 0x3e9e,
+ 0xfab1, 0x3e89,
+ 0xfab2, 0x4093,
+ 0xfab3, 0x3e81,
+ 0xfab5, 0x3c0e,
+ 0xfab6, 0x3e85,
+ 0xfab7, 0x38dc,
+ 0xfab8, 0x4069,
+ 0xfab9, 0x37d8,
+ 0xfaba, 0x3e99,
+ 0xfabb, 0x3e83,
+ 0xfabc, 0x3e88,
+ 0xfabd, 0x3e80,
+ 0xfabe, 0x3eb1,
+ 0xfabf, 0x416a,
+ 0xfac0, 0x376b,
+ 0xfac1, 0x3e67,
+ 0xfac2, 0x3e78,
+ 0xfac3, 0x4262,
+ 0xfac4, 0x37f5,
+ 0xfac5, 0x37f4,
+ 0xfac6, 0x3b45,
+ 0xfac7, 0x3e59,
+ 0xfac8, 0x2abc,
+ 0xfac9, 0x3dbf,
+ 0xfaca, 0x40bd,
+ 0xfacb, 0x3e7e,
+ 0xfacc, 0x382d,
+ 0xfacd, 0x3eb0,
+ 0xface, 0x3eab,
+ 0xfacf, 0x3eb2,
+ 0xfad0, 0x4221,
+ 0xfad1, 0x3f6a,
+ 0xfad2, 0x381b,
+ 0xfad3, 0x3e9a,
+ 0xfad4, 0x4223,
+ 0xfad5, 0x3e8e,
+ 0xfad6, 0x3bfd,
+ 0xfad7, 0x405a,
+ 0xfad8, 0x3eaf,
+ 0xfad9, 0x3cc8,
+ 0xfada, 0x3948,
+ 0xfadb, 0x42bd,
+ 0xfadc, 0x40cc,
+ 0xfadd, 0x3e5c,
+ 0xfade, 0x3eac,
+ 0xfadf, 0x391a,
+ 0xfae0, 0x3eaa,
+ 0xfae1, 0x4399,
+ 0xfae2, 0x389a,
+ 0xfae3, 0x3e8c,
+ 0xfae4, 0x389f,
+ 0xfae5, 0x3ea1,
+ 0xfae6, 0x4187,
+ 0xfae7, 0x3e8f,
+ 0xfae8, 0x3fc3,
+ 0xfae9, 0x3ea2,
+ 0xfaea, 0x3e9b,
+ 0xfaeb, 0x3e7d,
+ 0xfaec, 0x4051,
+ 0xfaed, 0x3fbc,
+ 0xfaee, 0x3fd5,
+ 0xfaef, 0x3b14,
+ 0xfaf0, 0x4222,
+ 0xfaf1, 0x379b,
+ 0xfaf2, 0x407b,
+ 0xfaf3, 0x3788,
+ 0xfaf4, 0x3bb4,
+ 0xfaf5, 0x41d0,
+ 0xfaf6, 0x4264,
+ 0xfaf7, 0x385e,
+ 0xfaf8, 0x376c,
+ 0xfaf9, 0x3dbe,
+ 0xfafa, 0x3813,
+ 0xfafb, 0x3fff,
+ 0xfafc, 0x3d63,
+ 0xfafd, 0x3786,
+ 0xfafe, 0x3b4a,
+ 0xfb40, 0x373a,
+ 0xfb41, 0x427a,
+ 0xfb42, 0x3c7a,
+ 0xfb43, 0x4205,
+ 0xfb44, 0x3c26,
+ 0xfb45, 0x38af,
+ 0xfb46, 0x3936,
+ 0xfb47, 0x37a8,
+ 0xfb48, 0x3b74,
+ 0xfb49, 0x3f6d,
+ 0xfb4a, 0x3e96,
+ 0xfb4b, 0x37bc,
+ 0xfb4c, 0x3e7b,
+ 0xfb4d, 0x3fea,
+ 0xfb4e, 0x41ca,
+ 0xfb4f, 0x39d7,
+ 0xfb50, 0x40d1,
+ 0xfb51, 0x3b71,
+ 0xfb52, 0x3fcf,
+ 0xfb53, 0x07c2,
+ 0xfb54, 0x42fe,
+ 0xfb55, 0x3ccd,
+ 0xfb56, 0x3e70,
+ 0xfb57, 0x3e72,
+ 0xfb58, 0x374c,
+ 0xfb59, 0x3769,
+ 0xfb5a, 0x3b4f,
+ 0xfb5b, 0x379f,
+ 0xfb5c, 0x2e45,
+ 0xfb5d, 0x380d,
+ 0xfb5e, 0x3fa2,
+ 0xfb5f, 0x381c,
+ 0xfb60, 0x3f7c,
+ 0xfb61, 0x3f59,
+ 0xfb62, 0x3f9e,
+ 0xfb63, 0x3d93,
+ 0xfb64, 0x3815,
+ 0xfb65, 0x388b,
+ 0xfb66, 0x3c60,
+ 0xfb67, 0x38f0,
+ 0xfb68, 0x37aa,
+ 0xfb69, 0x3f34,
+ 0xfb6a, 0x3c12,
+ 0xfb6b, 0x3900,
+ 0xfb6c, 0x3faa,
+ 0xfb6d, 0x390b,
+ 0xfb6e, 0x3929,
+ 0xfb6f, 0x3f27,
+ 0xfb70, 0x3f90,
+ 0xfb71, 0x3f57,
+ 0xfb72, 0x3f5b,
+ 0xfb73, 0x3f62,
+ 0xfb74, 0x3d76,
+ 0xfb75, 0x39c8,
+ 0xfb76, 0x3f64,
+ 0xfb78, 0x393d,
+ 0xfb79, 0x3c66,
+ 0xfb7a, 0x39d0,
+ 0xfb7b, 0x4022,
+ 0xfb7c, 0x3f2c,
+ 0xfb7d, 0x3f28,
+ 0xfb7e, 0x39cc,
+ 0xfba1, 0x3f26,
+ 0xfba2, 0x39cd,
+ 0xfba3, 0x3f3f,
+ 0xfba4, 0x39c5,
+ 0xfba5, 0x3fce,
+ 0xfba6, 0x4034,
+ 0xfba7, 0x3f5e,
+ 0xfba8, 0x4032,
+ 0xfba9, 0x4054,
+ 0xfbaa, 0x4178,
+ 0xfbab, 0x3f60,
+ 0xfbac, 0x3f29,
+ 0xfbad, 0x405d,
+ 0xfbae, 0x3f43,
+ 0xfbaf, 0x3f68,
+ 0xfbb0, 0x4060,
+ 0xfbb1, 0x3f2a,
+ 0xfbb2, 0x4063,
+ 0xfbb3, 0x39e7,
+ 0xfbb4, 0x38b6,
+ 0xfbb5, 0x4090,
+ 0xfbb6, 0x4048,
+ 0xfbb7, 0x4012,
+ 0xfbb8, 0x3d7c,
+ 0xfbb9, 0x404b,
+ 0xfbba, 0x404d,
+ 0xfbbb, 0x404f,
+ 0xfbbc, 0x424f,
+ 0xfbbd, 0x3d79,
+ 0xfbbe, 0x3f40,
+ 0xfbbf, 0x3f0a,
+ 0xfbc0, 0x3fd0,
+ 0xfbc1, 0x3f36,
+ 0xfbc2, 0x406d,
+ 0xfbc3, 0x4085,
+ 0xfbc4, 0x4084,
+ 0xfbc5, 0x413e,
+ 0xfbc6, 0x413b,
+ 0xfbc7, 0x3fc6,
+ 0xfbc8, 0x4086,
+ 0xfbc9, 0x3952,
+ 0xfbca, 0x40a1,
+ 0xfbcb, 0x3f32,
+ 0xfbcc, 0x4203,
+ 0xfbcd, 0x3f66,
+ 0xfbce, 0x3d83,
+ 0xfbcf, 0x3e75,
+ 0xfbd0, 0x40a2,
+ 0xfbd1, 0x0570,
+ 0xfbd2, 0x3f39,
+ 0xfbd3, 0x0871,
+ 0xfbd4, 0x3f24,
+ 0xfbd5, 0x40ae,
+ 0xfbd6, 0x3f44,
+ 0xfbd7, 0x38f5,
+ 0xfbd8, 0x3fc9,
+ 0xfbd9, 0x3fcd,
+ 0xfbda, 0x3fb5,
+ 0xfbdb, 0x3e7c,
+ 0xfbdc, 0x3fd2,
+ 0xfbdd, 0x3f4d,
+ 0xfbde, 0x40bc,
+ 0xfbdf, 0x40b7,
+ 0xfbe0, 0x3858,
+ 0xfbe1, 0x43af,
+ 0xfbe2, 0x3f6c,
+ 0xfbe3, 0x3d85,
+ 0xfbe4, 0x4396,
+ 0xfbe5, 0x39a6,
+ 0xfbe6, 0x3f7d,
+ 0xfbe7, 0x3fbf,
+ 0xfbe8, 0x40c8,
+ 0xfbe9, 0x3f5f,
+ 0xfbea, 0x3f2b,
+ 0xfbeb, 0x3d72,
+ 0xfbec, 0x40cf,
+ 0xfbed, 0x3a05,
+ 0xfbee, 0x3d82,
+ 0xfbef, 0x40dc,
+ 0xfbf0, 0x3d65,
+ 0xfbf1, 0x40d4,
+ 0xfbf2, 0x40da,
+ 0xfbf3, 0x3f2d,
+ 0xfbf4, 0x0595,
+ 0xfbf5, 0x3d81,
+ 0xfbf6, 0x40f1,
+ 0xfbf7, 0x06f5,
+ 0xfbf8, 0x40f8,
+ 0xfbf9, 0x40fb,
+ 0xfbfa, 0x3f41,
+ 0xfbfb, 0x4118,
+ 0xfbfc, 0x3d89,
+ 0xfbfd, 0x3f5c,
+ 0xfbfe, 0x3d67,
+ 0xfc40, 0x3f0e,
+ 0xfc41, 0x3f13,
+ 0xfc42, 0x4122,
+ 0xfc43, 0x3fca,
+ 0xfc44, 0x4129,
+ 0xfc45, 0x3f0c,
+ 0xfc46, 0x3f0b,
+ 0xfc47, 0x3f61,
+ 0xfc48, 0x3d8a,
+ 0xfc49, 0x3f2e,
+ 0xfc4a, 0x1971,
+ 0xfc4b, 0x4135,
+ 0xfc4c, 0x3a2b,
+ 0xfc4d, 0x3f6b,
+ 0xfc4e, 0x3ba5,
+ 0xfc4f, 0x4044,
+ 0xfc50, 0x4255,
+ 0xfc51, 0x3737,
+ 0xfc52, 0x3f25,
+ 0xfc53, 0x3739,
+ 0xfc54, 0x3a30,
+ 0xfc55, 0x4143,
+ 0xfc56, 0x40c4,
+ 0xfc57, 0x3d64,
+ 0xfc58, 0x3fbe,
+ 0xfc59, 0x3fa6,
+ 0xfc5a, 0x402c,
+ 0xfc5b, 0x4157,
+ 0xfc5c, 0x3f9f,
+ 0xfc5d, 0x2b40,
+ 0xfc5e, 0x3fa7,
+ 0xfc5f, 0x4005,
+ 0xfc60, 0x4001,
+ 0xfc61, 0x1c9b,
+ 0xfc62, 0x3d84,
+ 0xfc63, 0x0a95,
+ 0xfc64, 0x416c,
+ 0xfc65, 0x4009,
+ 0xfc66, 0x3d75,
+ 0xfc67, 0x3adc,
+ 0xfc68, 0x3fa8,
+ 0xfc69, 0x3f37,
+ 0xfc6a, 0x4174,
+ 0xfc6b, 0x4006,
+ 0xfc6c, 0x4002,
+ 0xfc6d, 0x3fba,
+ 0xfc6e, 0x3fc0,
+ 0xfc6f, 0x12b0,
+ 0xfc70, 0x3fbd,
+ 0xfc71, 0x4173,
+ 0xfc72, 0x4186,
+ 0xfc73, 0x3a54,
+ 0xfc74, 0x3fc5,
+ 0xfc75, 0x4259,
+ 0xfc76, 0x3fc2,
+ 0xfc77, 0x3f15,
+ 0xfc78, 0x3f50,
+ 0xfc79, 0x3f86,
+ 0xfc7a, 0x3fc1,
+ 0xfc7b, 0x418c,
+ 0xfc7c, 0x3fc7,
+ 0xfc7d, 0x3f16,
+ 0xfc7e, 0x418e,
+ 0xfca1, 0x3f4b,
+ 0xfca2, 0x419d,
+ 0xfca3, 0x115f,
+ 0xfca4, 0x3fc4,
+ 0xfca5, 0x3384,
+ 0xfca6, 0x3d99,
+ 0xfca7, 0x41b9,
+ 0xfca8, 0x3a89,
+ 0xfca9, 0x41b7,
+ 0xfcaa, 0x3d8b,
+ 0xfcab, 0x3d66,
+ 0xfcac, 0x03e2,
+ 0xfcad, 0x3d6a,
+ 0xfcae, 0x3d7a,
+ 0xfcaf, 0x41e3,
+ 0xfcb0, 0x0619,
+ 0xfcb1, 0x3996,
+ 0xfcb2, 0x3fc8,
+ 0xfcb3, 0x3a9e,
+ 0xfcb4, 0x3f38,
+ 0xfcb5, 0x3d80,
+ 0xfcb6, 0x41de,
+ 0xfcb8, 0x42eb,
+ 0xfcb9, 0x3d86,
+ 0xfcba, 0x41db,
+ 0xfcbb, 0x3f3e,
+ 0xfcbc, 0x4056,
+ 0xfcbd, 0x41d9,
+ 0xfcbe, 0x3ff6,
+ 0xfcbf, 0x3f5d,
+ 0xfcc0, 0x3d74,
+ 0xfcc1, 0x41e8,
+ 0xfcc2, 0x41c7,
+ 0xfcc3, 0x3d91,
+ 0xfcc4, 0x3b4b,
+ 0xfcc5, 0x3d42,
+ 0xfcc6, 0x3aad,
+ 0xfcc7, 0x3aa5,
+ 0xfcc8, 0x41f2,
+ 0xfcc9, 0x3f4c,
+ 0xfcca, 0x41f8,
+ 0xfccb, 0x3f6e,
+ 0xfccc, 0x3f79,
+ 0xfccd, 0x3f8d,
+ 0xfcce, 0x4003,
+ 0xfccf, 0x3f91,
+ 0xfcd0, 0x3ac3,
+ 0xfcd1, 0x091a,
+ 0xfcd2, 0x4234,
+ 0xfcd3, 0x3ffb,
+ 0xfcd4, 0x4240,
+ 0xfcd6, 0x3ffd,
+ 0xfcd7, 0x3f78,
+ 0xfcd8, 0x3c75,
+ 0xfcd9, 0x3c73,
+ 0xfcda, 0x38a5,
+ 0xfcdb, 0x43f9,
+ 0xfcdc, 0x3cfe,
+ 0xfcdd, 0x4257,
+ 0xfcde, 0x4233,
+ 0xfcdf, 0x3d69,
+ 0xfce0, 0x3c7e,
+ 0xfce1, 0x3d6f,
+ 0xfce2, 0x4000,
+ 0xfce3, 0x3dc0,
+ 0xfce4, 0x4004,
+ 0xfce5, 0x0e72,
+ 0xfce6, 0x3938,
+ 0xfce7, 0x3fa4,
+ 0xfce8, 0x295a,
+ 0xfce9, 0x4273,
+ 0xfcea, 0x3ac9,
+ 0xfceb, 0x427d,
+ 0xfcec, 0x3aca,
+ 0xfced, 0x3fb2,
+ 0xfcee, 0x3fb6,
+ 0xfcef, 0x3f97,
+ 0xfcf0, 0x3f9a,
+ 0xfcf1, 0x428b,
+ 0xfcf2, 0x43fa,
+ 0xfcf3, 0x428a,
+ 0xfcf4, 0x3f51,
+ 0xfcf5, 0x3f98,
+ 0xfcf6, 0x41a3,
+ 0xfcf7, 0x3d5c,
+ 0xfcf8, 0x3f63,
+ 0xfcf9, 0x4290,
+ 0xfcfa, 0x1f94,
+ 0xfcfb, 0x42c6,
+ 0xfcfc, 0x42a2,
+ 0xfcfd, 0x3ffa,
+ 0xfcfe, 0x3f9d,
+ 0xfd40, 0x3ffe,
+ 0xfd41, 0x3f9b,
+ 0xfd42, 0x3fdf,
+ 0xfd43, 0x3fe6,
+ 0xfd44, 0x3fde,
+ 0xfd45, 0x42b7,
+ 0xfd46, 0x3ff4,
+ 0xfd47, 0x42b8,
+ 0xfd48, 0x3feb,
+ 0xfd49, 0x42bf,
+ 0xfd4a, 0x3d71,
+ 0xfd4b, 0x3f4f,
+ 0xfd4c, 0x42c5,
+ 0xfd4d, 0x42d5,
+ 0xfd4e, 0x42d0,
+ 0xfd4f, 0x42d8,
+ 0xfd50, 0x3f55,
+ 0xfd51, 0x3fe8,
+ 0xfd52, 0x3ff3,
+ 0xfd53, 0x42df,
+ 0xfd54, 0x3fd3,
+ 0xfd55, 0x3e73,
+ 0xfd56, 0x3f95,
+ 0xfd57, 0x42ee,
+ 0xfd58, 0x42f4,
+ 0xfd59, 0x3f8c,
+ 0xfd5a, 0x3fcf,
+ 0xfd5b, 0x42ec,
+ 0xfd5c, 0x3fd4,
+ 0xfd5d, 0x42f0,
+ 0xfd5e, 0x07c2,
+ 0xfd5f, 0x0955,
+ 0xfd60, 0x42fe,
+ 0xfd61, 0x4301,
+ 0xfd62, 0x3ccd,
+ 0xfd63, 0x4307,
+ 0xfd64, 0x43fb,
+ 0xfd65, 0x3fda,
+ 0xfd66, 0x3f8b,
+ 0xfd67, 0x3733,
+ 0xfd68, 0x3f8a,
+ 0xfd69, 0x3741,
+ 0xfd6a, 0x3740,
+ 0xfd6b, 0x3742,
+ 0xfd6c, 0x3f93,
+ 0xfd6d, 0x3f8f,
+ 0xfd6e, 0x3e70,
+ 0xfd6f, 0x42c9,
+ 0xfd70, 0x3e72,
+ 0xfd71, 0x3fa9,
+ 0xfd72, 0x42cd,
+ 0xfd73, 0x43d2,
+ 0xfd74, 0x3f8e,
+ 0xfd75, 0x3f77,
+ 0xfd76, 0x3d6e,
+ 0xfd77, 0x0d0a,
+ 0xfd78, 0x3f11,
+ 0xfd79, 0x3752,
+ 0xfd7a, 0x3f14,
+ 0xfd7b, 0x3f18,
+ 0xfd7c, 0x3f53,
+ 0xfd7d, 0x3f1f,
+ 0xfd7e, 0x3f1c,
+ 0xfda1, 0x3fb8,
+ 0xfda2, 0x339d,
+ 0xfda3, 0x3b3f,
+ 0xfda4, 0x3f52,
+ 0xfda5, 0x3f1a,
+ 0xfda6, 0x3f1d,
+ 0xfda7, 0x375c,
+ 0xfda8, 0x3885,
+ 0xfda9, 0x3761,
+ 0xfdaa, 0x3fd7,
+ 0xfdab, 0x3fd6,
+ 0xfdac, 0x3fd9,
+ 0xfdad, 0x3fd8,
+ 0xfdae, 0x3fdd,
+ 0xfdaf, 0x3e93,
+ 0xfdb0, 0x3769,
+ 0xfdb1, 0x376e,
+ 0xfdb2, 0x3b4c,
+ 0xfdb3, 0x3774,
+ 0xfdb4, 0x377f,
+ 0xfdb5, 0x377b,
+ 0xfdb6, 0x3782,
+ 0xfdb7, 0x3b4f,
+ 0xfdb8, 0x3792,
+ 0xfdb9, 0x3fe3,
+ 0xfdba, 0x3fdc,
+ 0xfdbb, 0x3fdb,
+ 0xfdbc, 0x3fe5,
+ 0xfdbd, 0x3b75,
+ 0xfdbe, 0x37a2,
+ 0xfdbf, 0x3fe2,
+ 0xfdc0, 0x3fe7,
+ 0xfdc1, 0x3e6d,
+ 0xfdc2, 0x0d2a,
+ 0xfdc3, 0x3e79,
+ 0xfdc4, 0x3e76,
+ 0xfdc5, 0x379f,
+ 0xfdc6, 0x3fee,
+ 0xfdc7, 0x42d4,
+ 0xfdc8, 0x3d94,
+ 0xfdc9, 0x3d61,
+ 0xfdca, 0x3fe1,
+ 0xfdcb, 0x375e,
+ 0xfdcc, 0x3b7a,
+ 0xfdcd, 0x380b,
+ 0xfdce, 0x3fec,
+ 0xfdcf, 0x3fef,
+ 0xfdd0, 0x2e45,
+ 0xfdd1, 0x3ffc,
+ 0xfdd2, 0x3fed,
+ 0xfdd3, 0x380d,
+ 0xfdd4, 0x3fe4,
+ 0xfdd5, 0x3f92,
+ 0xfdd6, 0x3fae,
+ 0xfdd7, 0x3811,
+ 0xfdd8, 0x3f7a,
+ 0xfdd9, 0x3b8b,
+ 0xfdda, 0x3f5a,
+ 0xfddb, 0x3816,
+ 0xfddc, 0x3fa2,
+ 0xfddd, 0x3b8e,
+ 0xfdde, 0x381c,
+ 0xfddf, 0x2054,
+ 0xfde0, 0x381f,
+ 0xfde1, 0x3fa0,
+ 0xfde2, 0x43fc,
+ 0xfde3, 0x3e16,
+ 0xfde4, 0x3b94,
+ 0xfde5, 0x3f7c,
+ 0xfde6, 0x4007,
+ 0xfde7, 0x3f7b,
+ 0xfde8, 0x3d73,
+ 0xfde9, 0x3e77,
+ 0xfdea, 0x3d92,
+ 0xfdeb, 0x3fa1,
+ 0xfdec, 0x37c1,
+ 0xfded, 0x37d3,
+ 0xfdee, 0x3e7a,
+ 0xfdef, 0x3f59,
+ 0xfdf0, 0x3c55,
+ 0xfdf1, 0x3ff8,
+ 0xfdf2, 0x3ff5,
+ 0xfdf3, 0x3c4c,
+ 0xfdf4, 0x3d8c,
+ 0xfdf5, 0x3fa3,
+ 0xfdf6, 0x37c0,
+ 0xfdf7, 0x3f54,
+ 0xfdf8, 0x3800,
+ 0xfdf9, 0x3b7f,
+ 0xfdfa, 0x3f9e,
+ 0xfdfb, 0x3822,
+ 0xfdfc, 0x3fe9,
+ 0xfdfd, 0x3823,
+ 0xfdfe, 0x3fe0,
+ 0xfe40, 0x3d93,
+ 0xfe41, 0x3ff9,
+ 0xfe42, 0x3827,
+ 0xfe43, 0x3fa5,
+ 0xfe44, 0x3ff0,
+ 0xfe45, 0x3836,
+ 0xfe46, 0x3f99,
+ 0xfe47, 0x3ff2,
+ 0xfe48, 0x3d8d,
+ 0xfe49, 0x43e6,
+ 0xfe4a, 0x3522,
+ 0xfe4b, 0x3ff1,
+ 0xfe4c, 0x3f9c,
+ 0xfe4d, 0x3fb1,
+ 0xfe4e, 0x3f96,
+ 0xfe4f, 0x3e6f,
+ 0xfe50, 0x3f69,
+ 0xfe51, 0x3ff7,
+ 0xfe52, 0x3f82,
+ 0xfe53, 0x3f88,
+ 0xfe54, 0x3f85,
+ 0xfe55, 0x3f83,
+ 0xfe56, 0x3f7f,
+ 0xfe57, 0x3f89,
+ 0xfe58, 0x3bb5,
+ 0xfe59, 0x3862,
+ 0xfe5a, 0x3f87,
+ 0xfe5b, 0x3f31,
+ 0xfe5c, 0x3815,
+ 0xfe5d, 0x387e,
+ 0xfe5e, 0x3f49,
+ 0xfe5f, 0x3f48,
+ 0xfe60, 0x3f47,
+ 0xfe61, 0x3f45,
+ 0xfe62, 0x43eb,
+ 0xfe63, 0x3882,
+ 0xfe64, 0x3f6f,
+ 0xfe65, 0x3f4e,
+ 0xfe66, 0x3bc8,
+ 0xfe67, 0x43fd,
+ 0xfe68, 0x3d6b,
+ 0xfe6a, 0x43fe,
+ 0xfe6b, 0x3fcb,
+ 0xfe6c, 0x3dd2,
+ 0xfe6d, 0x3879,
+ 0xfe6e, 0x3f10,
+ 0xfe6f, 0x382e,
+ 0xfe70, 0x388b,
+ 0xfe71, 0x3c60,
+ 0xfe72, 0x2a9f,
+ 0xfe73, 0x3c61,
+ 0xfe74, 0x3893,
+ 0xfe75, 0x3e74,
+ 0xfe76, 0x3fac,
+ 0xfe77, 0x3f81,
+ 0xfe78, 0x3bcd,
+ 0xfe79, 0x3bd4,
+ 0xfe7a, 0x3bd3,
+ 0xfe7b, 0x3fcc,
+ 0xfe7c, 0x3fd1,
+ 0xfe7d, 0x3f3d,
+ 0xfe7e, 0x3f4a,
+ 0xfea1, 0x2352,
+ 0xfea2, 0x38ad,
+ 0xfea3, 0x3f46,
+ 0xfea4, 0x38b5,
+ 0xfea5, 0x3f0d,
+ 0xfea6, 0x3fb3,
+ 0xfea7, 0x38c0,
+ 0xfea8, 0x3e2f,
+ 0xfea9, 0x38cf,
+ 0xfeaa, 0x38d5,
+ 0xfeab, 0x3f33,
+ 0xfeac, 0x3d95,
+ 0xfead, 0x3f35,
+ 0xfeae, 0x38d7,
+ 0xfeaf, 0x3f2f,
+ 0xfeb0, 0x38e0,
+ 0xfeb1, 0x3c02,
+ 0xfeb2, 0x3f72,
+ 0xfeb3, 0x3f70,
+ 0xfeb4, 0x3d96,
+ 0xfeb5, 0x38e6,
+ 0xfeb7, 0x4035,
+ 0xfeb8, 0x3f73,
+ 0xfeb9, 0x38f0,
+ 0xfeba, 0x3c0b,
+ 0xfebb, 0x38f7,
+ 0xfebc, 0x37aa,
+ 0xfebd, 0x43ff,
+ 0xfebe, 0x38fa,
+ 0xfebf, 0x3c11,
+ 0xfec0, 0x3f34,
+ 0xfec1, 0x3fb9,
+ 0xfec2, 0x3c12,
+ 0xfec3, 0x400a,
+ 0xfec4, 0x3d77,
+ 0xfec5, 0x3f42,
+ 0xfec6, 0x3900,
+ 0xfec7, 0x3902,
+ 0xfec8, 0x3f74,
+ 0xfec9, 0x3d97,
+ 0xfeca, 0x3faa,
+ 0xfecb, 0x3f19,
+ 0xfecc, 0x3f1b,
+ 0xfecd, 0x390e,
+ 0xfece, 0x3909,
+ 0xfecf, 0x390b,
+ 0xfed0, 0x3f12,
+ 0xfed1, 0x3f17,
+ 0xfed2, 0x3fb7,
+ 0xfed3, 0x3f20,
+ 0xfed4, 0x3fbb,
+ 0xfed5, 0x3f3c,
+ 0xfed6, 0x3fad,
+ 0xfed7, 0x3919,
+ 0xfed8, 0x3f56,
+ 0xfed9, 0x3f71,
+ 0xfeda, 0x3fb4,
+ 0xfedb, 0x391c,
+ 0xfedc, 0x3f1e,
+ 0xfedd, 0x3f3a,
+ 0xfede, 0x391b,
+ 0xfedf, 0x3d87,
+ 0xfee0, 0x3c3a,
+ 0xfee1, 0x3f22,
+ 0xfee2, 0x3e71,
+ 0xfee3, 0x3c39,
+ 0xfee4, 0x3d7e,
+ 0xfee5, 0x4124,
+ 0xfee6, 0x3f3b,
+ 0xfee7, 0x3e6e,
+ 0xfee8, 0x3fab,
+ 0xfee9, 0x3925,
+ 0xfeea, 0x3f30,
+ 0xfeeb, 0x3929,
+ 0xfeec, 0x3f84,
+ 0xfeed, 0x3f0f,
+ 0xfeee, 0x3f76,
+ 0xfeef, 0x3f94,
+ 0xfef0, 0x3932,
+ 0xfef1, 0x3f27,
+ 0xfef2, 0x3933,
+ 0xfef3, 0x3f75,
+ 0xfef4, 0x3937,
+ 0xfef5, 0x3d78,
+ 0xfef6, 0x3f21,
+ 0xfef7, 0x3f90,
+ 0xfef8, 0x3940,
+ 0xfef9, 0x3d7f,
+ 0xfefa, 0x394a,
+ 0xfefb, 0x3f80,
+ 0xfefc, 0x3f23,
+ 0xfefd, 0x3950,
+ 0xfefe, 0x3f7e,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKdlaB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKdlaB5VMap2, 1035
+};
+
+static Gushort cns13HKdlbB5HMap2[1816] = {
+ 0x0000, 0x0000,
+ 0x8e40, 0x3d77,
+ 0x8e41, 0x3d6c,
+ 0x8e42, 0x3f59,
+ 0x8e43, 0x3919,
+ 0x8e44, 0x3e70,
+ 0x8e45, 0x3752,
+ 0x8e46, 0x38af,
+ 0x8e47, 0x3786,
+ 0x8e48, 0x3f1b,
+ 0x8e49, 0x3d5c,
+ 0x8e4a, 0x3f99,
+ 0x8e4b, 0x3fe8,
+ 0x8e4c, 0x388b,
+ 0x8e4d, 0x38dc,
+ 0x8e4e, 0x3faa,
+ 0x8e4f, 0x42c8,
+ 0x8e50, 0x3741,
+ 0x8e51, 0x3d7f,
+ 0x8e52, 0x42ec,
+ 0x8e53, 0x3f93,
+ 0x8e54, 0x389a,
+ 0x8e55, 0x3879,
+ 0x8e56, 0x373a,
+ 0x8e57, 0x42d0,
+ 0x8e58, 0x3e6f,
+ 0x8e59, 0x3f18,
+ 0x8e5a, 0x36e8,
+ 0x8e5b, 0x3739,
+ 0x8e5c, 0x3e99,
+ 0x8e5d, 0x3b4c,
+ 0x8e5e, 0x3dd2,
+ 0x8e5f, 0x3fa9,
+ 0x8e60, 0x3fac,
+ 0x8e61, 0x3fcb,
+ 0x8e62, 0x3733,
+ 0x8e63, 0x3f9f,
+ 0x8e64, 0x40da,
+ 0x8e65, 0x3f29,
+ 0x8e66, 0x3c66,
+ 0x8e67, 0x4222,
+ 0x8e68, 0x40ae,
+ 0x8e69, 0x3d7a,
+ 0x8e6a, 0x3f8d,
+ 0x8e6b, 0x39d0,
+ 0x8e6c, 0x4264,
+ 0x8e6d, 0x3d82,
+ 0x8e6e, 0x4203,
+ 0x8e6f, 0x41db,
+ 0x8e70, 0x3fde,
+ 0x8e71, 0x3ff4,
+ 0x8e72, 0x4004,
+ 0x8e73, 0x3f66,
+ 0x8e74, 0x3f9b,
+ 0x8e75, 0x3d66,
+ 0x8e76, 0x404b,
+ 0x8e77, 0x3fdf,
+ 0x8e78, 0x40fb,
+ 0x8e79, 0x4012,
+ 0x8e7a, 0x3fe6,
+ 0x8e7b, 0x42eb,
+ 0x8e7c, 0x4124,
+ 0x8e7d, 0x3d7c,
+ 0x8e7e, 0x3d69,
+ 0x8ea1, 0x3ffe,
+ 0x8ea2, 0x3d72,
+ 0x8ea3, 0x3fc6,
+ 0x8ea4, 0x3cfe,
+ 0x8ea5, 0x43f9,
+ 0x8ea6, 0x3d42,
+ 0x8ea7, 0x3f15,
+ 0x8ea8, 0x3fce,
+ 0x8ea9, 0x428b,
+ 0x8eaa, 0x40cf,
+ 0x8eab, 0x43f6,
+ 0x8eac, 0x4005,
+ 0x8ead, 0x3f2d,
+ 0x8eae, 0x4161,
+ 0x8eaf, 0x3f2c,
+ 0x8eb0, 0x3aca,
+ 0x8eb1, 0x3d6a,
+ 0x8eb2, 0x4063,
+ 0x8eb3, 0x3fc5,
+ 0x8eb4, 0x39e7,
+ 0x8eb5, 0x3f2a,
+ 0x8eb6, 0x4060,
+ 0x8eb7, 0x4273,
+ 0x8eb8, 0x4221,
+ 0x8eb9, 0x40a2,
+ 0x8eba, 0x3f68,
+ 0x8ebb, 0x40a1,
+ 0x8ebc, 0x3f57,
+ 0x8ebd, 0x3f70,
+ 0x8ebe, 0x3fb7,
+ 0x8ebf, 0x3746,
+ 0x8ec0, 0x3fab,
+ 0x8ec1, 0x3ff2,
+ 0x8ec2, 0x3f8c,
+ 0x8ec3, 0x3f88,
+ 0x8ec4, 0x37d3,
+ 0x8ec5, 0x3b74,
+ 0x8ec7, 0x42f4,
+ 0x8ec8, 0x3c4c,
+ 0x8ec9, 0x3b7a,
+ 0x8eca, 0x3885,
+ 0x8ecb, 0x3737,
+ 0x8ecc, 0x3fdb,
+ 0x8ecd, 0x3f1d,
+ 0x8ece, 0x3fec,
+ 0x8ecf, 0x3fe5,
+ 0x8ed0, 0x375e,
+ 0x8ed1, 0x3ff7,
+ 0x8ed2, 0x3813,
+ 0x8ed3, 0x3fe3,
+ 0x8ed4, 0x3f1a,
+ 0x8ed5, 0x38e6,
+ 0x8ed6, 0x3fdc,
+ 0x8ed7, 0x377f,
+ 0x8ed8, 0x3d87,
+ 0x8ed9, 0x3bd3,
+ 0x8eda, 0x3d78,
+ 0x8edb, 0x3bd4,
+ 0x8edc, 0x3f96,
+ 0x8edd, 0x3f95,
+ 0x8ede, 0x3d8c,
+ 0x8edf, 0x3937,
+ 0x8ee0, 0x3f1c,
+ 0x8ee1, 0x3932,
+ 0x8ee2, 0x3d6b,
+ 0x8ee3, 0x3800,
+ 0x8ee4, 0x3ff8,
+ 0x8ee5, 0x3c3a,
+ 0x8ee6, 0x3f42,
+ 0x8ee7, 0x43fd,
+ 0x8ee8, 0x3fb1,
+ 0x8ee9, 0x3792,
+ 0x8eea, 0x3f94,
+ 0x8eeb, 0x3f1e,
+ 0x8eec, 0x400a,
+ 0x8eed, 0x3882,
+ 0x8eee, 0x3f9c,
+ 0x8eef, 0x3d61,
+ 0x8ef0, 0x3f22,
+ 0x8ef1, 0x3fe9,
+ 0x8ef2, 0x3d92,
+ 0x8ef3, 0x377f,
+ 0x8ef4, 0x3b94,
+ 0x8ef5, 0x376e,
+ 0x8ef6, 0x4301,
+ 0x8ef7, 0x3f3a,
+ 0x8ef8, 0x3863,
+ 0x8ef9, 0x3ff1,
+ 0x8efa, 0x42fe,
+ 0x8efb, 0x3bfc,
+ 0x8efc, 0x3f45,
+ 0x8efd, 0x379f,
+ 0x8efe, 0x376b,
+ 0x8f40, 0x3f14,
+ 0x8f41, 0x3f47,
+ 0x8f42, 0x3862,
+ 0x8f43, 0x3769,
+ 0x8f44, 0x3c12,
+ 0x8f45, 0x3f49,
+ 0x8f46, 0x381f,
+ 0x8f47, 0x3929,
+ 0x8f48, 0x3f56,
+ 0x8f49, 0x3f34,
+ 0x8f4a, 0x3fdd,
+ 0x8f4b, 0x38fa,
+ 0x8f4c, 0x3f7b,
+ 0x8f4d, 0x3c11,
+ 0x8f4e, 0x3f7c,
+ 0x8f4f, 0x43ff,
+ 0x8f50, 0x3e73,
+ 0x8f51, 0x3f71,
+ 0x8f52, 0x3925,
+ 0x8f53, 0x3c55,
+ 0x8f54, 0x38b5,
+ 0x8f55, 0x3f5a,
+ 0x8f56, 0x3816,
+ 0x8f57, 0x3e6d,
+ 0x8f58, 0x3782,
+ 0x8f59, 0x3f11,
+ 0x8f5a, 0x3b8b,
+ 0x8f5b, 0x37c0,
+ 0x8f5c, 0x3815,
+ 0x8f5d, 0x383b,
+ 0x8f5e, 0x3d73,
+ 0x8f5f, 0x3d6e,
+ 0x8f60, 0x3f8a,
+ 0x8f61, 0x3f3e,
+ 0x8f62, 0x4234,
+ 0x8f63, 0x41e3,
+ 0x8f64, 0x3fc7,
+ 0x8f65, 0x3ff3,
+ 0x8f66, 0x4003,
+ 0x8f67, 0x4032,
+ 0x8f68, 0x3f6e,
+ 0x8f69, 0x41a3,
+ 0x8f6a, 0x4006,
+ 0x8f6b, 0x3f2b,
+ 0x8f6c, 0x3f7d,
+ 0x8f6d, 0x3c73,
+ 0x8f6e, 0x3f16,
+ 0x8f6f, 0x4002,
+ 0x8f70, 0x4056,
+ 0x8f71, 0x3fba,
+ 0x8f72, 0x3f6b,
+ 0x8f73, 0x3f91,
+ 0x8f74, 0x3fbe,
+ 0x8f75, 0x405a,
+ 0x8f76, 0x3adf,
+ 0x8f77, 0x3e41,
+ 0x8f78, 0x3d67,
+ 0x8f79, 0x3f60,
+ 0x8f7a, 0x41e8,
+ 0x8f7b, 0x3fc0,
+ 0x8f7c, 0x3d83,
+ 0x8f7d, 0x4173,
+ 0x8f7e, 0x3f5c,
+ 0x8fa1, 0x3f32,
+ 0x8fa2, 0x3f3f,
+ 0x8fa3, 0x3d63,
+ 0x8fa4, 0x4146,
+ 0x8fa5, 0x3fcd,
+ 0x8fa6, 0x3d79,
+ 0x8fa7, 0x3f28,
+ 0x8fa8, 0x3fc1,
+ 0x8fa9, 0x40bc,
+ 0x8faa, 0x3d71,
+ 0x8fab, 0x3f37,
+ 0x8fac, 0x42d8,
+ 0x8fad, 0x3feb,
+ 0x8fae, 0x4241,
+ 0x8faf, 0x3a30,
+ 0x8fb0, 0x39cd,
+ 0x8fb1, 0x42bf,
+ 0x8fb2, 0x420e,
+ 0x8fb3, 0x3f0a,
+ 0x8fb4, 0x39cc,
+ 0x8fb5, 0x4044,
+ 0x8fb6, 0x4098,
+ 0x8fb7, 0x418c,
+ 0x8fb8, 0x3d64,
+ 0x8fb9, 0x3f44,
+ 0x8fba, 0x404f,
+ 0x8fbb, 0x42d5,
+ 0x8fbc, 0x4290,
+ 0x8fbd, 0x4000,
+ 0x8fbe, 0x3a89,
+ 0x8fbf, 0x416c,
+ 0x8fc0, 0x40c4,
+ 0x8fc1, 0x404d,
+ 0x8fc2, 0x3dc0,
+ 0x8fc3, 0x3f50,
+ 0x8fc4, 0x4009,
+ 0x8fc5, 0x3faf,
+ 0x8fc6, 0x3f86,
+ 0x8fc7, 0x4093,
+ 0x8fc8, 0x3aad,
+ 0x8fc9, 0x3f38,
+ 0x8fca, 0x3d75,
+ 0x8fcb, 0x3f39,
+ 0x8fcc, 0x42cd,
+ 0x8fcd, 0x3f78,
+ 0x8fce, 0x3f9d,
+ 0x8fcf, 0x4090,
+ 0x8fd0, 0x3d80,
+ 0x8fd1, 0x3f2e,
+ 0x8fd2, 0x38b6,
+ 0x8fd3, 0x41b9,
+ 0x8fd4, 0x3d8a,
+ 0x8fd5, 0x3f24,
+ 0x8fd6, 0x3a9e,
+ 0x8fd7, 0x3adc,
+ 0x8fd8, 0x3d65,
+ 0x8fd9, 0x4085,
+ 0x8fda, 0x3f51,
+ 0x8fdb, 0x43fa,
+ 0x8fdc, 0x3f63,
+ 0x8fdd, 0x4178,
+ 0x8fde, 0x41b7,
+ 0x8fdf, 0x3e72,
+ 0x8fe0, 0x41d9,
+ 0x8fe1, 0x418e,
+ 0x8fe2, 0x3d76,
+ 0x8fe3, 0x42d4,
+ 0x8fe4, 0x42a2,
+ 0x8fe5, 0x4257,
+ 0x8fe6, 0x3f0c,
+ 0x8fe7, 0x3996,
+ 0x8fe8, 0x4255,
+ 0x8fe9, 0x40b7,
+ 0x8fea, 0x3f9a,
+ 0x8feb, 0x3fca,
+ 0x8fec, 0x3f5e,
+ 0x8fed, 0x3d85,
+ 0x8fee, 0x3ffa,
+ 0x8fef, 0x3fb6,
+ 0x8ff0, 0x3ac3,
+ 0x8ff1, 0x3fc8,
+ 0x8ff2, 0x3f4b,
+ 0x8ff3, 0x40f1,
+ 0x8ff4, 0x4034,
+ 0x8ff5, 0x3f5b,
+ 0x8ff6, 0x42c9,
+ 0x8ff7, 0x3c75,
+ 0x8ff8, 0x3f79,
+ 0x8ff9, 0x42c6,
+ 0x8ffa, 0x38cf,
+ 0x8ffb, 0x41f4,
+ 0x8ffc, 0x3f41,
+ 0x8ffd, 0x390b,
+ 0x8ffe, 0x38e0,
+ 0x9040, 0x427d,
+ 0x9041, 0x42f0,
+ 0x9042, 0x3f27,
+ 0x9043, 0x3822,
+ 0x9044, 0x37d8,
+ 0x9045, 0x37a2,
+ 0x9046, 0x3f73,
+ 0x9047, 0x42b8,
+ 0x9048, 0x3f19,
+ 0x9049, 0x42b7,
+ 0x904a, 0x3d8b,
+ 0x904b, 0x4129,
+ 0x904c, 0x40d4,
+ 0x904d, 0x38f5,
+ 0x904e, 0x4143,
+ 0x904f, 0x4022,
+ 0x9050, 0x41d0,
+ 0x9051, 0x41f5,
+ 0x9052, 0x3f43,
+ 0x9053, 0x40c8,
+ 0x9054, 0x4096,
+ 0x9055, 0x405d,
+ 0x9056, 0x4174,
+ 0x9057, 0x413e,
+ 0x9058, 0x413b,
+ 0x9059, 0x39c4,
+ 0x905a, 0x3d89,
+ 0x905b, 0x4205,
+ 0x905c, 0x36eb,
+ 0x905d, 0x39c5,
+ 0x905e, 0x3d84,
+ 0x905f, 0x4054,
+ 0x9060, 0x193f,
+ 0x9061, 0x0619,
+ 0x9062, 0x0871,
+ 0x9063, 0x115f,
+ 0x9064, 0x3f53,
+ 0x9065, 0x3f1f,
+ 0x9066, 0x339d,
+ 0x9067, 0x3fb8,
+ 0x9068, 0x3b3f,
+ 0x9069, 0x3f52,
+ 0x906a, 0x3761,
+ 0x906b, 0x375c,
+ 0x906c, 0x3fd9,
+ 0x906d, 0x3fd7,
+ 0x906e, 0x3fd6,
+ 0x906f, 0x3e93,
+ 0x9070, 0x3774,
+ 0x9071, 0x377b,
+ 0x9072, 0x3b4f,
+ 0x9073, 0x4007,
+ 0x9074, 0x3fe2,
+ 0x9075, 0x3e79,
+ 0x9076, 0x3e76,
+ 0x9077, 0x3fe7,
+ 0x9078, 0x0d2a,
+ 0x9079, 0x3fee,
+ 0x907a, 0x3fe1,
+ 0x907b, 0x3e77,
+ 0x907c, 0x3fa3,
+ 0x907d, 0x3f54,
+ 0x907e, 0x37bc,
+ 0x90a1, 0x3e7a,
+ 0x90a2, 0x3fa1,
+ 0x90a3, 0x37c1,
+ 0x90a4, 0x3ff5,
+ 0x90a5, 0x3f9e,
+ 0x90a6, 0x3b7f,
+ 0x90a7, 0x380b,
+ 0x90a8, 0x3fef,
+ 0x90a9, 0x3ffc,
+ 0x90aa, 0x380d,
+ 0x90ab, 0x3fed,
+ 0x90ac, 0x3fe4,
+ 0x90ad, 0x3811,
+ 0x90ae, 0x3f7a,
+ 0x90af, 0x3fa2,
+ 0x90b0, 0x3b8e,
+ 0x90b1, 0x381c,
+ 0x90b2, 0x3fa0,
+ 0x90b3, 0x3fe0,
+ 0x90b4, 0x3d93,
+ 0x90b5, 0x3827,
+ 0x90b6, 0x3ff0,
+ 0x90b7, 0x3fa5,
+ 0x90b8, 0x3836,
+ 0x90b9, 0x3d8d,
+ 0x90ba, 0x3f69,
+ 0x90bb, 0x3f82,
+ 0x90bc, 0x3f85,
+ 0x90bd, 0x3f83,
+ 0x90be, 0x3f89,
+ 0x90bf, 0x3f7f,
+ 0x90c0, 0x3bb5,
+ 0x90c1, 0x3f87,
+ 0x90c2, 0x3f31,
+ 0x90c3, 0x3d94,
+ 0x90c4, 0x0230,
+ 0x90c5, 0x43fe,
+ 0x90c6, 0x3f10,
+ 0x90c7, 0x387e,
+ 0x90c8, 0x43eb,
+ 0x90c9, 0x3f6f,
+ 0x90ca, 0x3e9b,
+ 0x90cb, 0x3f4e,
+ 0x90cc, 0x3bc8,
+ 0x90cd, 0x1e29,
+ 0x90ce, 0x3f48,
+ 0x90cf, 0x382e,
+ 0x90d0, 0x3c60,
+ 0x90d1, 0x2a9f,
+ 0x90d2, 0x3893,
+ 0x90d3, 0x43f7,
+ 0x90d4, 0x3e74,
+ 0x90d5, 0x3bcd,
+ 0x90d6, 0x3ac9,
+ 0x90d7, 0x3fcc,
+ 0x90d8, 0x3fd1,
+ 0x90d9, 0x3f3d,
+ 0x90da, 0x3f4a,
+ 0x90db, 0x38ad,
+ 0x90dc, 0x2352,
+ 0x90dd, 0x3f46,
+ 0x90de, 0x38b2,
+ 0x90df, 0x3fb3,
+ 0x90e0, 0x3f0d,
+ 0x90e1, 0x38c0,
+ 0x90e2, 0x3e2f,
+ 0x90e3, 0x38d5,
+ 0x90e4, 0x3f35,
+ 0x90e5, 0x38d7,
+ 0x90e6, 0x3f2f,
+ 0x90e7, 0x3f33,
+ 0x90e8, 0x3d95,
+ 0x90e9, 0x3c02,
+ 0x90ea, 0x3f72,
+ 0x90eb, 0x3d96,
+ 0x90ec, 0x38e7,
+ 0x90ed, 0x4035,
+ 0x90ee, 0x3c0b,
+ 0x90ef, 0x38f0,
+ 0x90f0, 0x38f7,
+ 0x90f1, 0x3fb9,
+ 0x90f2, 0x3900,
+ 0x90f3, 0x3f74,
+ 0x90f4, 0x3909,
+ 0x90f5, 0x3f12,
+ 0x90f6, 0x3f17,
+ 0x90f7, 0x3f20,
+ 0x90f8, 0x3fbb,
+ 0x90f9, 0x3f3c,
+ 0x90fa, 0x3fb4,
+ 0x90fb, 0x3fad,
+ 0x90fc, 0x391a,
+ 0x90fd, 0x391c,
+ 0x90fe, 0x391b,
+ 0x9140, 0x3c39,
+ 0x9141, 0x3e71,
+ 0x9142, 0x3d7e,
+ 0x9143, 0x3f3b,
+ 0x9144, 0x3f30,
+ 0x9145, 0x3f84,
+ 0x9146, 0x43f8,
+ 0x9147, 0x3f0f,
+ 0x9148, 0x3f76,
+ 0x9149, 0x3933,
+ 0x914a, 0x3f75,
+ 0x914b, 0x3940,
+ 0x914c, 0x3f21,
+ 0x914d, 0x3f90,
+ 0x914e, 0x394a,
+ 0x914f, 0x3f80,
+ 0x9150, 0x3f23,
+ 0x9151, 0x3950,
+ 0x9152, 0x3d97,
+ 0x9153, 0x2e45,
+ 0x9154, 0x0570,
+ 0x9155, 0x3ead,
+ 0x9156, 0x3522,
+ 0x9157, 0x0be3,
+ 0x9158, 0x0595,
+ 0x9159, 0x0228,
+ 0x915a, 0x0a95,
+ 0x915b, 0x12b0,
+ 0x915c, 0x091a,
+ 0x915d, 0x43fc,
+ 0x915e, 0x3f92,
+ 0x915f, 0x3fae,
+ 0x9160, 0x07c2,
+ 0x9161, 0x0955,
+ 0x9162, 0x3785,
+ 0x9163, 0x3e6e,
+ 0x9164, 0x3d6d,
+ 0x9165, 0x3f62,
+ 0x9166, 0x39c8,
+ 0x9167, 0x3f65,
+ 0x9168, 0x393d,
+ 0x9169, 0x3f26,
+ 0x916a, 0x406d,
+ 0x916b, 0x3fd0,
+ 0x916c, 0x3f36,
+ 0x916d, 0x4086,
+ 0x916e, 0x3952,
+ 0x916f, 0x3fd2,
+ 0x9170, 0x3858,
+ 0x9171, 0x3ffb,
+ 0x9172, 0x3f67,
+ 0x9173, 0x3e81,
+ 0x9174, 0x3fc9,
+ 0x9175, 0x3fb5,
+ 0x9176, 0x3e7c,
+ 0x9177, 0x3e75,
+ 0x9178, 0x3c77,
+ 0x9179, 0x3b2e,
+ 0x917a, 0x3f4d,
+ 0x917b, 0x43af,
+ 0x917c, 0x3e67,
+ 0x917d, 0x40bd,
+ 0x917e, 0x3f6c,
+ 0x91a1, 0x39a6,
+ 0x91a2, 0x3948,
+ 0x91a3, 0x3fbf,
+ 0x91a4, 0x3f5f,
+ 0x91a5, 0x3a05,
+ 0x91a6, 0x06f5,
+ 0x91a7, 0x40f8,
+ 0x91a8, 0x41ad,
+ 0x91a9, 0x3f0e,
+ 0x91aa, 0x4122,
+ 0x91ab, 0x3f13,
+ 0x91ac, 0x3f0b,
+ 0x91ad, 0x4135,
+ 0x91ae, 0x3a2b,
+ 0x91af, 0x4138,
+ 0x91b0, 0x0226,
+ 0x91b1, 0x4149,
+ 0x91b2, 0x3ba5,
+ 0x91b3, 0x4001,
+ 0x91b4, 0x3fbd,
+ 0x91b5, 0x3fa8,
+ 0x91b6, 0x4186,
+ 0x91b7, 0x3a54,
+ 0x91b8, 0x3fc2,
+ 0x91b9, 0x4192,
+ 0x91ba, 0x4187,
+ 0x91bb, 0x3384,
+ 0x91bc, 0x3fc4,
+ 0x91bd, 0x3d99,
+ 0x91be, 0x3aaa,
+ 0x91bf, 0x41de,
+ 0x91c1, 0x3ff6,
+ 0x91c2, 0x3f5d,
+ 0x91c3, 0x41c7,
+ 0x91c4, 0x3d91,
+ 0x91c5, 0x3d74,
+ 0x91c6, 0x3f4c,
+ 0x91c7, 0x41f2,
+ 0x91c8, 0x3aa5,
+ 0x91c9, 0x3b4b,
+ 0x91ca, 0x3d86,
+ 0x91cb, 0x41f8,
+ 0x91cc, 0x4240,
+ 0x91cd, 0x3ffd,
+ 0x91ce, 0x3fa7,
+ 0x91cf, 0x4259,
+ 0x91d0, 0x0e72,
+ 0x91d1, 0x4262,
+ 0x91d2, 0x3c7e,
+ 0x91d3, 0x3938,
+ 0x91d4, 0x4233,
+ 0x91d5, 0x295a,
+ 0x91d7, 0x3f97,
+ 0x91d8, 0x3fb2,
+ 0x91d9, 0x428a,
+ 0x91da, 0x3f98,
+ 0x91db, 0x1f94,
+ 0x91dc, 0x3f40,
+ 0x91dd, 0x3f4f,
+ 0x91de, 0x3f8f,
+ 0x91df, 0x3d6f,
+ 0x91e0, 0x42df,
+ 0x91e1, 0x3f55,
+ 0x91e2, 0x3fd3,
+ 0x91e3, 0x42ee,
+ 0x91e4, 0x3fcf,
+ 0x91e5, 0x3fd4,
+ 0x91e6, 0x3e7d,
+ 0x91e7, 0x4307,
+ 0x91e8, 0x43fb,
+ 0x91e9, 0x3fda,
+ 0x91ea, 0x0d0a,
+ 0x91eb, 0x3f77,
+ 0x91ec, 0x3dbf,
+ 0x91ed, 0x402c,
+ 0x91ee, 0x3fa4,
+ 0x91ef, 0x3d6f,
+ 0x91f0, 0x3ccd,
+ 0x91f1, 0x3f64,
+ 0x91f2, 0x3f8b,
+ 0x91f3, 0x386f,
+ 0x91f4, 0x1971,
+ 0x91f5, 0x1c9b,
+ 0x91f6, 0x0745,
+ 0x91f7, 0x1d75,
+ 0x91f8, 0x3888,
+ 0x91f9, 0x3742,
+ 0x91fa, 0x2b40,
+ 0x91fb, 0x36e9,
+ 0x91fc, 0x37e0,
+ 0x91fd, 0x3e16,
+ 0x91fe, 0x387c,
+ 0x9240, 0x37aa,
+ 0x9241, 0x3f8e,
+ 0x9242, 0x40dc,
+ 0x9243, 0x3c7a,
+ 0x9244, 0x3fa6,
+ 0x9245, 0x405f,
+ 0x9246, 0x3c26,
+ 0x9247, 0x385e,
+ 0x9248, 0x3f25,
+ 0x9249, 0x4048,
+ 0x924a, 0x3d81,
+ 0x924b, 0x390e,
+ 0x924c, 0x4084,
+ 0x924d, 0x4118,
+ 0x924e, 0x4157,
+ 0x924f, 0x3902,
+ 0x9250, 0x389f,
+ 0x9251, 0x3ff9,
+ 0x9252, 0x3823,
+ 0x9253, 0x3871,
+ 0x9254, 0x36ea,
+ 0x9255, 0x376c,
+ 0x9256, 0x3740,
+ 0x9257, 0x37f4,
+ 0x9258, 0x42e0,
+ 0x9259, 0x425b,
+ 0x925a, 0x36ed,
+ 0x925b, 0x3b14,
+ 0x925c, 0x42c5,
+ 0x925d, 0x408b,
+ 0x925e, 0x38a5,
+ 0x925f, 0x416a,
+ 0x9260, 0x419d,
+ 0x9261, 0x4144,
+ 0x9262, 0x424f,
+ 0x9263, 0x3f61,
+ 0x9264, 0x3fd8,
+ 0x9265, 0x061c,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKdlbB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKdlbB5HMap2, 908
+};
+
+static Gushort cns13HKdlbB5VMap2[1840] = {
+ 0x0000, 0x0000,
+ 0x8e40, 0x3d77,
+ 0x8e41, 0x3d6c,
+ 0x8e42, 0x3f59,
+ 0x8e43, 0x3919,
+ 0x8e44, 0x3e70,
+ 0x8e45, 0x3752,
+ 0x8e46, 0x38af,
+ 0x8e47, 0x3786,
+ 0x8e48, 0x3f1b,
+ 0x8e49, 0x3d5c,
+ 0x8e4a, 0x3f99,
+ 0x8e4b, 0x3fe8,
+ 0x8e4c, 0x388b,
+ 0x8e4d, 0x38dc,
+ 0x8e4e, 0x3faa,
+ 0x8e4f, 0x42c8,
+ 0x8e50, 0x3741,
+ 0x8e51, 0x3d7f,
+ 0x8e52, 0x42ec,
+ 0x8e53, 0x3f93,
+ 0x8e54, 0x389a,
+ 0x8e55, 0x3879,
+ 0x8e56, 0x373a,
+ 0x8e57, 0x42d0,
+ 0x8e58, 0x3e6f,
+ 0x8e59, 0x3f18,
+ 0x8e5a, 0x36e8,
+ 0x8e5b, 0x3739,
+ 0x8e5c, 0x3e99,
+ 0x8e5d, 0x3b4c,
+ 0x8e5e, 0x3dd2,
+ 0x8e5f, 0x3fa9,
+ 0x8e60, 0x3fac,
+ 0x8e61, 0x3fcb,
+ 0x8e62, 0x3733,
+ 0x8e63, 0x3f9f,
+ 0x8e64, 0x40da,
+ 0x8e65, 0x3f29,
+ 0x8e66, 0x3c66,
+ 0x8e67, 0x4222,
+ 0x8e68, 0x40ae,
+ 0x8e69, 0x3d7a,
+ 0x8e6a, 0x3f8d,
+ 0x8e6b, 0x39d0,
+ 0x8e6c, 0x4264,
+ 0x8e6d, 0x3d82,
+ 0x8e6e, 0x4203,
+ 0x8e6f, 0x41db,
+ 0x8e70, 0x3fde,
+ 0x8e71, 0x3ff4,
+ 0x8e72, 0x4004,
+ 0x8e73, 0x3f66,
+ 0x8e74, 0x3f9b,
+ 0x8e75, 0x3d66,
+ 0x8e76, 0x404b,
+ 0x8e77, 0x3fdf,
+ 0x8e78, 0x40fb,
+ 0x8e79, 0x4012,
+ 0x8e7a, 0x3fe6,
+ 0x8e7b, 0x42eb,
+ 0x8e7c, 0x4124,
+ 0x8e7d, 0x3d7c,
+ 0x8e7e, 0x3d69,
+ 0x8ea1, 0x3ffe,
+ 0x8ea2, 0x3d72,
+ 0x8ea3, 0x3fc6,
+ 0x8ea4, 0x3cfe,
+ 0x8ea5, 0x43f9,
+ 0x8ea6, 0x3d42,
+ 0x8ea7, 0x3f15,
+ 0x8ea8, 0x3fce,
+ 0x8ea9, 0x428b,
+ 0x8eaa, 0x40cf,
+ 0x8eab, 0x43f6,
+ 0x8eac, 0x4005,
+ 0x8ead, 0x3f2d,
+ 0x8eae, 0x4161,
+ 0x8eaf, 0x3f2c,
+ 0x8eb0, 0x3aca,
+ 0x8eb1, 0x3d6a,
+ 0x8eb2, 0x4063,
+ 0x8eb3, 0x3fc5,
+ 0x8eb4, 0x39e7,
+ 0x8eb5, 0x3f2a,
+ 0x8eb6, 0x4060,
+ 0x8eb7, 0x4273,
+ 0x8eb8, 0x4221,
+ 0x8eb9, 0x40a2,
+ 0x8eba, 0x3f68,
+ 0x8ebb, 0x40a1,
+ 0x8ebc, 0x3f57,
+ 0x8ebd, 0x3f70,
+ 0x8ebe, 0x3fb7,
+ 0x8ebf, 0x3746,
+ 0x8ec0, 0x3fab,
+ 0x8ec1, 0x3ff2,
+ 0x8ec2, 0x3f8c,
+ 0x8ec3, 0x3f88,
+ 0x8ec4, 0x37d3,
+ 0x8ec5, 0x3b74,
+ 0x8ec7, 0x42f4,
+ 0x8ec8, 0x3c4c,
+ 0x8ec9, 0x3b7a,
+ 0x8eca, 0x3885,
+ 0x8ecb, 0x3737,
+ 0x8ecc, 0x3fdb,
+ 0x8ecd, 0x3f1d,
+ 0x8ece, 0x3fec,
+ 0x8ecf, 0x3fe5,
+ 0x8ed0, 0x375e,
+ 0x8ed1, 0x3ff7,
+ 0x8ed2, 0x3813,
+ 0x8ed3, 0x3fe3,
+ 0x8ed4, 0x3f1a,
+ 0x8ed5, 0x38e6,
+ 0x8ed6, 0x3fdc,
+ 0x8ed7, 0x377f,
+ 0x8ed8, 0x3d87,
+ 0x8ed9, 0x3bd3,
+ 0x8eda, 0x3d78,
+ 0x8edb, 0x3bd4,
+ 0x8edc, 0x3f96,
+ 0x8edd, 0x3f95,
+ 0x8ede, 0x3d8c,
+ 0x8edf, 0x3937,
+ 0x8ee0, 0x3f1c,
+ 0x8ee1, 0x3932,
+ 0x8ee2, 0x3d6b,
+ 0x8ee3, 0x3800,
+ 0x8ee4, 0x3ff8,
+ 0x8ee5, 0x3c3a,
+ 0x8ee6, 0x3f42,
+ 0x8ee7, 0x43fd,
+ 0x8ee8, 0x3fb1,
+ 0x8ee9, 0x3792,
+ 0x8eea, 0x3f94,
+ 0x8eeb, 0x3f1e,
+ 0x8eec, 0x400a,
+ 0x8eed, 0x3882,
+ 0x8eee, 0x3f9c,
+ 0x8eef, 0x3d61,
+ 0x8ef0, 0x3f22,
+ 0x8ef1, 0x3fe9,
+ 0x8ef2, 0x3d92,
+ 0x8ef3, 0x377f,
+ 0x8ef4, 0x3b94,
+ 0x8ef5, 0x376e,
+ 0x8ef6, 0x4301,
+ 0x8ef7, 0x3f3a,
+ 0x8ef8, 0x3863,
+ 0x8ef9, 0x3ff1,
+ 0x8efa, 0x42fe,
+ 0x8efb, 0x3bfc,
+ 0x8efc, 0x3f45,
+ 0x8efd, 0x379f,
+ 0x8efe, 0x376b,
+ 0x8f40, 0x3f14,
+ 0x8f41, 0x3f47,
+ 0x8f42, 0x3862,
+ 0x8f43, 0x3769,
+ 0x8f44, 0x3c12,
+ 0x8f45, 0x3f49,
+ 0x8f46, 0x381f,
+ 0x8f47, 0x3929,
+ 0x8f48, 0x3f56,
+ 0x8f49, 0x3f34,
+ 0x8f4a, 0x3fdd,
+ 0x8f4b, 0x38fa,
+ 0x8f4c, 0x3f7b,
+ 0x8f4d, 0x3c11,
+ 0x8f4e, 0x3f7c,
+ 0x8f4f, 0x43ff,
+ 0x8f50, 0x3e73,
+ 0x8f51, 0x3f71,
+ 0x8f52, 0x3925,
+ 0x8f53, 0x3c55,
+ 0x8f54, 0x38b5,
+ 0x8f55, 0x3f5a,
+ 0x8f56, 0x3816,
+ 0x8f57, 0x3e6d,
+ 0x8f58, 0x3782,
+ 0x8f59, 0x3f11,
+ 0x8f5a, 0x3b8b,
+ 0x8f5b, 0x37c0,
+ 0x8f5c, 0x3815,
+ 0x8f5d, 0x383b,
+ 0x8f5e, 0x3d73,
+ 0x8f5f, 0x3d6e,
+ 0x8f60, 0x3f8a,
+ 0x8f61, 0x3f3e,
+ 0x8f62, 0x4234,
+ 0x8f63, 0x41e3,
+ 0x8f64, 0x3fc7,
+ 0x8f65, 0x3ff3,
+ 0x8f66, 0x4003,
+ 0x8f67, 0x4032,
+ 0x8f68, 0x3f6e,
+ 0x8f69, 0x41a3,
+ 0x8f6a, 0x4006,
+ 0x8f6b, 0x3f2b,
+ 0x8f6c, 0x3f7d,
+ 0x8f6d, 0x3c73,
+ 0x8f6e, 0x3f16,
+ 0x8f6f, 0x4002,
+ 0x8f70, 0x4056,
+ 0x8f71, 0x3fba,
+ 0x8f72, 0x3f6b,
+ 0x8f73, 0x3f91,
+ 0x8f74, 0x3fbe,
+ 0x8f75, 0x405a,
+ 0x8f76, 0x3adf,
+ 0x8f77, 0x3e41,
+ 0x8f78, 0x3d67,
+ 0x8f79, 0x3f60,
+ 0x8f7a, 0x41e8,
+ 0x8f7b, 0x3fc0,
+ 0x8f7c, 0x3d83,
+ 0x8f7d, 0x4173,
+ 0x8f7e, 0x3f5c,
+ 0x8fa1, 0x3f32,
+ 0x8fa2, 0x3f3f,
+ 0x8fa3, 0x3d63,
+ 0x8fa4, 0x4146,
+ 0x8fa5, 0x3fcd,
+ 0x8fa6, 0x3d79,
+ 0x8fa7, 0x3f28,
+ 0x8fa8, 0x3fc1,
+ 0x8fa9, 0x40bc,
+ 0x8faa, 0x3d71,
+ 0x8fab, 0x3f37,
+ 0x8fac, 0x42d8,
+ 0x8fad, 0x3feb,
+ 0x8fae, 0x4241,
+ 0x8faf, 0x3a30,
+ 0x8fb0, 0x39cd,
+ 0x8fb1, 0x42bf,
+ 0x8fb2, 0x420e,
+ 0x8fb3, 0x3f0a,
+ 0x8fb4, 0x39cc,
+ 0x8fb5, 0x4044,
+ 0x8fb6, 0x4098,
+ 0x8fb7, 0x418c,
+ 0x8fb8, 0x3d64,
+ 0x8fb9, 0x3f44,
+ 0x8fba, 0x404f,
+ 0x8fbb, 0x42d5,
+ 0x8fbc, 0x4290,
+ 0x8fbd, 0x4000,
+ 0x8fbe, 0x3a89,
+ 0x8fbf, 0x416c,
+ 0x8fc0, 0x40c4,
+ 0x8fc1, 0x404d,
+ 0x8fc2, 0x3dc0,
+ 0x8fc3, 0x3f50,
+ 0x8fc4, 0x4009,
+ 0x8fc5, 0x3faf,
+ 0x8fc6, 0x3f86,
+ 0x8fc7, 0x4093,
+ 0x8fc8, 0x3aad,
+ 0x8fc9, 0x3f38,
+ 0x8fca, 0x3d75,
+ 0x8fcb, 0x3f39,
+ 0x8fcc, 0x42cd,
+ 0x8fcd, 0x3f78,
+ 0x8fce, 0x3f9d,
+ 0x8fcf, 0x4090,
+ 0x8fd0, 0x3d80,
+ 0x8fd1, 0x3f2e,
+ 0x8fd2, 0x38b6,
+ 0x8fd3, 0x41b9,
+ 0x8fd4, 0x3d8a,
+ 0x8fd5, 0x3f24,
+ 0x8fd6, 0x3a9e,
+ 0x8fd7, 0x3adc,
+ 0x8fd8, 0x3d65,
+ 0x8fd9, 0x4085,
+ 0x8fda, 0x3f51,
+ 0x8fdb, 0x43fa,
+ 0x8fdc, 0x3f63,
+ 0x8fdd, 0x4178,
+ 0x8fde, 0x41b7,
+ 0x8fdf, 0x3e72,
+ 0x8fe0, 0x41d9,
+ 0x8fe1, 0x418e,
+ 0x8fe2, 0x3d76,
+ 0x8fe3, 0x42d4,
+ 0x8fe4, 0x42a2,
+ 0x8fe5, 0x4257,
+ 0x8fe6, 0x3f0c,
+ 0x8fe7, 0x3996,
+ 0x8fe8, 0x4255,
+ 0x8fe9, 0x40b7,
+ 0x8fea, 0x3f9a,
+ 0x8feb, 0x3fca,
+ 0x8fec, 0x3f5e,
+ 0x8fed, 0x3d85,
+ 0x8fee, 0x3ffa,
+ 0x8fef, 0x3fb6,
+ 0x8ff0, 0x3ac3,
+ 0x8ff1, 0x3fc8,
+ 0x8ff2, 0x3f4b,
+ 0x8ff3, 0x40f1,
+ 0x8ff4, 0x4034,
+ 0x8ff5, 0x3f5b,
+ 0x8ff6, 0x42c9,
+ 0x8ff7, 0x3c75,
+ 0x8ff8, 0x3f79,
+ 0x8ff9, 0x42c6,
+ 0x8ffa, 0x38cf,
+ 0x8ffb, 0x41f4,
+ 0x8ffc, 0x3f41,
+ 0x8ffd, 0x390b,
+ 0x8ffe, 0x38e0,
+ 0x9040, 0x427d,
+ 0x9041, 0x42f0,
+ 0x9042, 0x3f27,
+ 0x9043, 0x3822,
+ 0x9044, 0x37d8,
+ 0x9045, 0x37a2,
+ 0x9046, 0x3f73,
+ 0x9047, 0x42b8,
+ 0x9048, 0x3f19,
+ 0x9049, 0x42b7,
+ 0x904a, 0x3d8b,
+ 0x904b, 0x4129,
+ 0x904c, 0x40d4,
+ 0x904d, 0x38f5,
+ 0x904e, 0x4143,
+ 0x904f, 0x4022,
+ 0x9050, 0x41d0,
+ 0x9051, 0x41f5,
+ 0x9052, 0x3f43,
+ 0x9053, 0x40c8,
+ 0x9054, 0x4096,
+ 0x9055, 0x405d,
+ 0x9056, 0x4174,
+ 0x9057, 0x413e,
+ 0x9058, 0x413b,
+ 0x9059, 0x39c4,
+ 0x905a, 0x3d89,
+ 0x905b, 0x4205,
+ 0x905c, 0x36eb,
+ 0x905d, 0x39c5,
+ 0x905e, 0x3d84,
+ 0x905f, 0x4054,
+ 0x9060, 0x193f,
+ 0x9061, 0x0619,
+ 0x9062, 0x0871,
+ 0x9063, 0x115f,
+ 0x9064, 0x3f53,
+ 0x9065, 0x3f1f,
+ 0x9066, 0x339d,
+ 0x9067, 0x3fb8,
+ 0x9068, 0x3b3f,
+ 0x9069, 0x3f52,
+ 0x906a, 0x3761,
+ 0x906b, 0x375c,
+ 0x906c, 0x3fd9,
+ 0x906d, 0x3fd7,
+ 0x906e, 0x3fd6,
+ 0x906f, 0x3e93,
+ 0x9070, 0x3774,
+ 0x9071, 0x377b,
+ 0x9072, 0x3b4f,
+ 0x9073, 0x4007,
+ 0x9074, 0x3fe2,
+ 0x9075, 0x3e79,
+ 0x9076, 0x3e76,
+ 0x9077, 0x3fe7,
+ 0x9078, 0x0d2a,
+ 0x9079, 0x3fee,
+ 0x907a, 0x3fe1,
+ 0x907b, 0x3e77,
+ 0x907c, 0x3fa3,
+ 0x907d, 0x3f54,
+ 0x907e, 0x37bc,
+ 0x90a1, 0x3e7a,
+ 0x90a2, 0x3fa1,
+ 0x90a3, 0x37c1,
+ 0x90a4, 0x3ff5,
+ 0x90a5, 0x3f9e,
+ 0x90a6, 0x3b7f,
+ 0x90a7, 0x380b,
+ 0x90a8, 0x3fef,
+ 0x90a9, 0x3ffc,
+ 0x90aa, 0x380d,
+ 0x90ab, 0x3fed,
+ 0x90ac, 0x3fe4,
+ 0x90ad, 0x3811,
+ 0x90ae, 0x3f7a,
+ 0x90af, 0x3fa2,
+ 0x90b0, 0x3b8e,
+ 0x90b1, 0x381c,
+ 0x90b2, 0x3fa0,
+ 0x90b3, 0x3fe0,
+ 0x90b4, 0x3d93,
+ 0x90b5, 0x3827,
+ 0x90b6, 0x3ff0,
+ 0x90b7, 0x3fa5,
+ 0x90b8, 0x3836,
+ 0x90b9, 0x3d8d,
+ 0x90ba, 0x3f69,
+ 0x90bb, 0x3f82,
+ 0x90bc, 0x3f85,
+ 0x90bd, 0x3f83,
+ 0x90be, 0x3f89,
+ 0x90bf, 0x3f7f,
+ 0x90c0, 0x3bb5,
+ 0x90c1, 0x3f87,
+ 0x90c2, 0x3f31,
+ 0x90c3, 0x3d94,
+ 0x90c4, 0x0230,
+ 0x90c5, 0x43fe,
+ 0x90c6, 0x3f10,
+ 0x90c7, 0x387e,
+ 0x90c8, 0x43eb,
+ 0x90c9, 0x3f6f,
+ 0x90ca, 0x3e9b,
+ 0x90cb, 0x3f4e,
+ 0x90cc, 0x3bc8,
+ 0x90cd, 0x1e29,
+ 0x90ce, 0x3f48,
+ 0x90cf, 0x382e,
+ 0x90d0, 0x3c60,
+ 0x90d1, 0x2a9f,
+ 0x90d2, 0x3893,
+ 0x90d3, 0x43f7,
+ 0x90d4, 0x3e74,
+ 0x90d5, 0x3bcd,
+ 0x90d6, 0x3ac9,
+ 0x90d7, 0x3fcc,
+ 0x90d8, 0x3fd1,
+ 0x90d9, 0x3f3d,
+ 0x90da, 0x3f4a,
+ 0x90db, 0x38ad,
+ 0x90dc, 0x2352,
+ 0x90dd, 0x3f46,
+ 0x90de, 0x38b2,
+ 0x90df, 0x3fb3,
+ 0x90e0, 0x3f0d,
+ 0x90e1, 0x38c0,
+ 0x90e2, 0x3e2f,
+ 0x90e3, 0x38d5,
+ 0x90e4, 0x3f35,
+ 0x90e5, 0x38d7,
+ 0x90e6, 0x3f2f,
+ 0x90e7, 0x3f33,
+ 0x90e8, 0x3d95,
+ 0x90e9, 0x3c02,
+ 0x90ea, 0x3f72,
+ 0x90eb, 0x3d96,
+ 0x90ec, 0x38e7,
+ 0x90ed, 0x4035,
+ 0x90ee, 0x3c0b,
+ 0x90ef, 0x38f0,
+ 0x90f0, 0x38f7,
+ 0x90f1, 0x3fb9,
+ 0x90f2, 0x3900,
+ 0x90f3, 0x3f74,
+ 0x90f4, 0x3909,
+ 0x90f5, 0x3f12,
+ 0x90f6, 0x3f17,
+ 0x90f7, 0x3f20,
+ 0x90f8, 0x3fbb,
+ 0x90f9, 0x3f3c,
+ 0x90fa, 0x3fb4,
+ 0x90fb, 0x3fad,
+ 0x90fc, 0x391a,
+ 0x90fd, 0x391c,
+ 0x90fe, 0x391b,
+ 0x9140, 0x3c39,
+ 0x9141, 0x3e71,
+ 0x9142, 0x3d7e,
+ 0x9143, 0x3f3b,
+ 0x9144, 0x3f30,
+ 0x9145, 0x3f84,
+ 0x9146, 0x43f8,
+ 0x9147, 0x3f0f,
+ 0x9148, 0x3f76,
+ 0x9149, 0x3933,
+ 0x914a, 0x3f75,
+ 0x914b, 0x3940,
+ 0x914c, 0x3f21,
+ 0x914d, 0x3f90,
+ 0x914e, 0x394a,
+ 0x914f, 0x3f80,
+ 0x9150, 0x3f23,
+ 0x9151, 0x3950,
+ 0x9152, 0x3d97,
+ 0x9153, 0x2e45,
+ 0x9154, 0x0570,
+ 0x9155, 0x3ead,
+ 0x9156, 0x3522,
+ 0x9157, 0x0be3,
+ 0x9158, 0x0595,
+ 0x9159, 0x0228,
+ 0x915a, 0x0a95,
+ 0x915b, 0x12b0,
+ 0x915c, 0x091a,
+ 0x915d, 0x43fc,
+ 0x915e, 0x3f92,
+ 0x915f, 0x3fae,
+ 0x9160, 0x07c2,
+ 0x9161, 0x0955,
+ 0x9162, 0x3785,
+ 0x9163, 0x3e6e,
+ 0x9164, 0x3d6d,
+ 0x9165, 0x3f62,
+ 0x9166, 0x39c8,
+ 0x9167, 0x3f65,
+ 0x9168, 0x393d,
+ 0x9169, 0x3f26,
+ 0x916a, 0x406d,
+ 0x916b, 0x3fd0,
+ 0x916c, 0x3f36,
+ 0x916d, 0x4086,
+ 0x916e, 0x3952,
+ 0x916f, 0x3fd2,
+ 0x9170, 0x3858,
+ 0x9171, 0x3ffb,
+ 0x9172, 0x3f67,
+ 0x9173, 0x3e81,
+ 0x9174, 0x3fc9,
+ 0x9175, 0x3fb5,
+ 0x9176, 0x3e7c,
+ 0x9177, 0x3e75,
+ 0x9178, 0x3c77,
+ 0x9179, 0x3b2e,
+ 0x917a, 0x3f4d,
+ 0x917b, 0x43af,
+ 0x917c, 0x3e67,
+ 0x917d, 0x40bd,
+ 0x917e, 0x3f6c,
+ 0x91a1, 0x39a6,
+ 0x91a2, 0x3948,
+ 0x91a3, 0x3fbf,
+ 0x91a4, 0x3f5f,
+ 0x91a5, 0x3a05,
+ 0x91a6, 0x06f5,
+ 0x91a7, 0x40f8,
+ 0x91a8, 0x41ad,
+ 0x91a9, 0x3f0e,
+ 0x91aa, 0x4122,
+ 0x91ab, 0x3f13,
+ 0x91ac, 0x3f0b,
+ 0x91ad, 0x4135,
+ 0x91ae, 0x3a2b,
+ 0x91af, 0x4138,
+ 0x91b0, 0x0226,
+ 0x91b1, 0x4149,
+ 0x91b2, 0x3ba5,
+ 0x91b3, 0x4001,
+ 0x91b4, 0x3fbd,
+ 0x91b5, 0x3fa8,
+ 0x91b6, 0x4186,
+ 0x91b7, 0x3a54,
+ 0x91b8, 0x3fc2,
+ 0x91b9, 0x4192,
+ 0x91ba, 0x4187,
+ 0x91bb, 0x3384,
+ 0x91bc, 0x3fc4,
+ 0x91bd, 0x3d99,
+ 0x91be, 0x3aaa,
+ 0x91bf, 0x41de,
+ 0x91c1, 0x3ff6,
+ 0x91c2, 0x3f5d,
+ 0x91c3, 0x41c7,
+ 0x91c4, 0x3d91,
+ 0x91c5, 0x3d74,
+ 0x91c6, 0x3f4c,
+ 0x91c7, 0x41f2,
+ 0x91c8, 0x3aa5,
+ 0x91c9, 0x3b4b,
+ 0x91ca, 0x3d86,
+ 0x91cb, 0x41f8,
+ 0x91cc, 0x4240,
+ 0x91cd, 0x3ffd,
+ 0x91ce, 0x3fa7,
+ 0x91cf, 0x4259,
+ 0x91d0, 0x0e72,
+ 0x91d1, 0x4262,
+ 0x91d2, 0x3c7e,
+ 0x91d3, 0x3938,
+ 0x91d4, 0x4233,
+ 0x91d5, 0x295a,
+ 0x91d7, 0x3f97,
+ 0x91d8, 0x3fb2,
+ 0x91d9, 0x428a,
+ 0x91da, 0x3f98,
+ 0x91db, 0x1f94,
+ 0x91dc, 0x3f40,
+ 0x91dd, 0x3f4f,
+ 0x91de, 0x3f8f,
+ 0x91df, 0x3d6f,
+ 0x91e0, 0x42df,
+ 0x91e1, 0x3f55,
+ 0x91e2, 0x3fd3,
+ 0x91e3, 0x42ee,
+ 0x91e4, 0x3fcf,
+ 0x91e5, 0x3fd4,
+ 0x91e6, 0x3e7d,
+ 0x91e7, 0x4307,
+ 0x91e8, 0x43fb,
+ 0x91e9, 0x3fda,
+ 0x91ea, 0x0d0a,
+ 0x91eb, 0x3f77,
+ 0x91ec, 0x3dbf,
+ 0x91ed, 0x402c,
+ 0x91ee, 0x3fa4,
+ 0x91ef, 0x3d6f,
+ 0x91f0, 0x3ccd,
+ 0x91f1, 0x3f64,
+ 0x91f2, 0x3f8b,
+ 0x91f3, 0x386f,
+ 0x91f4, 0x1971,
+ 0x91f5, 0x1c9b,
+ 0x91f6, 0x0745,
+ 0x91f7, 0x1d75,
+ 0x91f8, 0x3888,
+ 0x91f9, 0x3742,
+ 0x91fa, 0x2b40,
+ 0x91fb, 0x36e9,
+ 0x91fc, 0x37e0,
+ 0x91fd, 0x3e16,
+ 0x91fe, 0x387c,
+ 0x9240, 0x37aa,
+ 0x9241, 0x3f8e,
+ 0x9242, 0x40dc,
+ 0x9243, 0x3c7a,
+ 0x9244, 0x3fa6,
+ 0x9245, 0x405f,
+ 0x9246, 0x3c26,
+ 0x9247, 0x385e,
+ 0x9248, 0x3f25,
+ 0x9249, 0x4048,
+ 0x924a, 0x3d81,
+ 0x924b, 0x390e,
+ 0x924c, 0x4084,
+ 0x924d, 0x4118,
+ 0x924e, 0x4157,
+ 0x924f, 0x3902,
+ 0x9250, 0x389f,
+ 0x9251, 0x3ff9,
+ 0x9252, 0x3823,
+ 0x9253, 0x3871,
+ 0x9254, 0x36ea,
+ 0x9255, 0x376c,
+ 0x9256, 0x3740,
+ 0x9257, 0x37f4,
+ 0x9258, 0x42e0,
+ 0x9259, 0x425b,
+ 0x925a, 0x36ed,
+ 0x925b, 0x3b14,
+ 0x925c, 0x42c5,
+ 0x925d, 0x408b,
+ 0x925e, 0x38a5,
+ 0x925f, 0x416a,
+ 0x9260, 0x419d,
+ 0x9261, 0x4144,
+ 0x9262, 0x424f,
+ 0x9263, 0x3f61,
+ 0x9264, 0x3fd8,
+ 0x9265, 0x061c,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKdlbB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKdlbB5VMap2, 920
+};
+
+static Gushort cns13HKgccsB5HMap2[1106] = {
+ 0x0000, 0x0000,
+ 0x8a40, 0x4308,
+ 0x8aa1, 0x4347,
+ 0x8b41, 0x438c,
+ 0x8b45, 0x438e,
+ 0x8b47, 0x438f,
+ 0x8b49, 0x4390,
+ 0x8b4b, 0x4391,
+ 0x8b4d, 0x4392,
+ 0x8b54, 0x4396,
+ 0x8b58, 0x4397,
+ 0x8b5a, 0x4398,
+ 0x8e40, 0x372b,
+ 0x8e46, 0x3730,
+ 0x8e6c, 0x3755,
+ 0x8e77, 0x375f,
+ 0x8e7e, 0x0121,
+ 0x8ea1, 0x3766,
+ 0x8ea7, 0x376b,
+ 0x8eca, 0x378d,
+ 0x8ee6, 0x37a8,
+ 0x8ef0, 0x37b1,
+ 0x8f40, 0x37c0,
+ 0x8f5a, 0x37d9,
+ 0x8f60, 0x37de,
+ 0x8f68, 0x37e5,
+ 0x8fa1, 0x37fc,
+ 0x8fc6, 0x3820,
+ 0x8fc8, 0x3821,
+ 0x8fdb, 0x3833,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x905e, 0x3872,
+ 0x9070, 0x3883,
+ 0x907a, 0x36e9,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a7, 0x3896,
+ 0x90b9, 0x38a7,
+ 0x9140, 0x38ed,
+ 0x9166, 0x3912,
+ 0x916f, 0x391a,
+ 0x91a1, 0x3929,
+ 0x91a3, 0x392a,
+ 0x9240, 0x3986,
+ 0x92a1, 0x39c5,
+ 0x92af, 0x0119,
+ 0x92b1, 0x011c,
+ 0x92b2, 0x011b,
+ 0x92b3, 0x39d3,
+ 0x92e6, 0x3a05,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93ab, 0x3a64,
+ 0x93c3, 0x3a7b,
+ 0x93e6, 0x3a9d,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9447, 0x3abb,
+ 0x94a1, 0x3af3,
+ 0x9540, 0x3b51,
+ 0x954e, 0x3b5e,
+ 0x955b, 0x3b6a,
+ 0x95a1, 0x3b8e,
+ 0x95c7, 0x3bb3,
+ 0x9640, 0x3beb,
+ 0x96a1, 0x3c2a,
+ 0x96d5, 0x3c5d,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9877, 0x3d59,
+ 0x987a, 0x3d5a,
+ 0x98a3, 0x3d5b,
+ 0x98af, 0x3d5c,
+ 0x98b6, 0x3d5d,
+ 0x98b9, 0x3d5e,
+ 0x98bd, 0x3d5f,
+ 0x98c2, 0x3d61,
+ 0x98c4, 0x3d62,
+ 0x98c6, 0x3d63,
+ 0x98e3, 0x3d65,
+ 0x98e7, 0x3d66,
+ 0x98ed, 0x3d67,
+ 0x98f0, 0x3d68,
+ 0x98f2, 0x3d69,
+ 0x98fc, 0x3d6a,
+ 0x9943, 0x3d6b,
+ 0x9945, 0x3d6c,
+ 0x994f, 0x3d6d,
+ 0x996a, 0x3d6e,
+ 0x996e, 0x3d6f,
+ 0x9975, 0x3d70,
+ 0x9978, 0x3d71,
+ 0x99a2, 0x3d72,
+ 0x99ae, 0x3d73,
+ 0x99b6, 0x3d74,
+ 0x99ba, 0x3d75,
+ 0x99e2, 0x3d76,
+ 0x99f4, 0x3d77,
+ 0x9a4a, 0x3d78,
+ 0x9a4c, 0x3d79,
+ 0x9a59, 0x3d7a,
+ 0x9a61, 0x3d7b,
+ 0x9a68, 0x3d7c,
+ 0x9a73, 0x3d7d,
+ 0x9a7e, 0x3d7e,
+ 0x9ab2, 0x3d7f,
+ 0x9ab7, 0x3d80,
+ 0x9ab9, 0x3d81,
+ 0x9abb, 0x3d82,
+ 0x9ac7, 0x3d83,
+ 0x9ad0, 0x3d84,
+ 0x9ad2, 0x3d85,
+ 0x9ad9, 0x3d86,
+ 0x9ae2, 0x3d89,
+ 0x9ae4, 0x3d8a,
+ 0x9ae8, 0x3d8b,
+ 0x9af2, 0x3d8c,
+ 0x9af6, 0x3d8d,
+ 0x9afb, 0x3d8e,
+ 0x9b46, 0x3d8f,
+ 0x9b4a, 0x3d90,
+ 0x9b4c, 0x3d91,
+ 0x9b54, 0x3d92,
+ 0x9b58, 0x3d93,
+ 0x9b5a, 0x3d94,
+ 0x9b5c, 0x3d95,
+ 0x9b5e, 0x3d96,
+ 0x9b70, 0x3d98,
+ 0x9b76, 0x3d9c,
+ 0x9b7b, 0x3d9f,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba3, 0x3da3,
+ 0x9ba7, 0x3da5,
+ 0x9bac, 0x3da9,
+ 0x9baf, 0x3daa,
+ 0x9bb2, 0x3dab,
+ 0x9bbe, 0x3db3,
+ 0x9bc0, 0x3db4,
+ 0x9bca, 0x3dbb,
+ 0x9bcc, 0x3dbc,
+ 0x9bd0, 0x3dbd,
+ 0x9bd3, 0x3dbf,
+ 0x9bd5, 0x3dc0,
+ 0x9bd8, 0x3dc1,
+ 0x9bdd, 0x3dc4,
+ 0x9bde, 0x1c14,
+ 0x9bdf, 0x3dc5,
+ 0x9be1, 0x3dc6,
+ 0x9be3, 0x3dc7,
+ 0x9be7, 0x3dc8,
+ 0x9be9, 0x3dc9,
+ 0x9bee, 0x3dcd,
+ 0x9bf3, 0x3dcf,
+ 0x9bf6, 0x3dd0,
+ 0x9bf8, 0x3dd1,
+ 0x9bfb, 0x3dd3,
+ 0x9c40, 0x3dd5,
+ 0x9c44, 0x3dd8,
+ 0x9c48, 0x3ddb,
+ 0x9c4a, 0x3ddc,
+ 0x9c4d, 0x3ddd,
+ 0x9c55, 0x3de4,
+ 0x9c57, 0x3de5,
+ 0x9c5d, 0x3dea,
+ 0x9c60, 0x3deb,
+ 0x9c62, 0x3dec,
+ 0x9c64, 0x3ded,
+ 0x9c68, 0x3df0,
+ 0x9c6a, 0x3df1,
+ 0x9c6b, 0x346a,
+ 0x9c6d, 0x3df2,
+ 0x9c6f, 0x3df3,
+ 0x9c75, 0x3df7,
+ 0x9c79, 0x3dfa,
+ 0x9c7b, 0x3dfb,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca5, 0x3e00,
+ 0x9ca8, 0x3e01,
+ 0x9cab, 0x3e03,
+ 0x9cad, 0x3e04,
+ 0x9cb1, 0x3e06,
+ 0x9cbc, 0x3e10,
+ 0x9cc6, 0x3e17,
+ 0x9ccf, 0x3e1f,
+ 0x9cd8, 0x3e24,
+ 0x9cdc, 0x3e27,
+ 0x9ce7, 0x3e31,
+ 0x9ceb, 0x3e34,
+ 0x9cee, 0x3e36,
+ 0x9cfd, 0x3e42,
+ 0x9d46, 0x3e43,
+ 0x9d49, 0x3e44,
+ 0x9d4c, 0x3e46,
+ 0x9d4f, 0x3e48,
+ 0x9d51, 0x3e49,
+ 0x9d55, 0x3e4a,
+ 0x9d57, 0x25c1,
+ 0x9d5a, 0x3e4b,
+ 0x9d62, 0x3e4c,
+ 0x9d64, 0x3e4d,
+ 0x9d79, 0x3e4e,
+ 0x9d7e, 0x3e4f,
+ 0x9da5, 0x3e50,
+ 0x9daa, 0x3e54,
+ 0x9dac, 0x3e55,
+ 0x9db0, 0x3e58,
+ 0x9db3, 0x3e59,
+ 0x9db5, 0x3e5a,
+ 0x9db7, 0x3e5b,
+ 0x9dbc, 0x3e5c,
+ 0x9dbf, 0x3e5e,
+ 0x9dc3, 0x3e60,
+ 0x9dc7, 0x3e62,
+ 0x9dca, 0x3e64,
+ 0x9dcd, 0x3e65,
+ 0x9dd3, 0x3e6a,
+ 0x9dda, 0x3e6d,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e64, 0x3eb4,
+ 0x9e68, 0x3eb6,
+ 0x9e6a, 0x3eb7,
+ 0x9e71, 0x3eb8,
+ 0x9e73, 0x3eb9,
+ 0x9e77, 0x3eba,
+ 0x9e7a, 0x3ebc,
+ 0x9e7c, 0x3ebd,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea4, 0x3ec1,
+ 0x9ea9, 0x3ec4,
+ 0x9eac, 0x3ec6,
+ 0x9eaf, 0x3ec8,
+ 0x9eb4, 0x3ecb,
+ 0x9eb6, 0x3ecc,
+ 0x9eb9, 0x3ece,
+ 0x9ebc, 0x3ecf,
+ 0x9ebf, 0x3ed0,
+ 0x9ec4, 0x3ed2,
+ 0x9ec7, 0x3ed4,
+ 0x9ecc, 0x3ed8,
+ 0x9ed0, 0x3eda,
+ 0x9ed3, 0x3edc,
+ 0x9ed6, 0x3edd,
+ 0x9eda, 0x3edf,
+ 0x9ef3, 0x3ef7,
+ 0x9ef9, 0x3efa,
+ 0x9efc, 0x3efc,
+ 0x9f40, 0x3eff,
+ 0x9f44, 0x3f02,
+ 0x9f49, 0x3f06,
+ 0x9f4d, 0x3f08,
+ 0x9f69, 0x3f23,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fb6, 0x3f4c,
+ 0x9fbc, 0x3f51,
+ 0x9fc0, 0x3f54,
+ 0x9fc2, 0x3f55,
+ 0x9fe5, 0x3f77,
+ 0x9ffa, 0x3f8b,
+ 0xa041, 0x3f90,
+ 0xa048, 0x3f96,
+ 0xa056, 0x3fa3,
+ 0xa06e, 0x3fba,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a3, 0x3fcb,
+ 0xa0a8, 0x3fcf,
+ 0xa0c6, 0x3fec,
+ 0xa0d1, 0x3ff6,
+ 0xa0e4, 0x4008,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa40, 0x400b,
+ 0xfaa1, 0x404a,
+ 0xfb40, 0x40a8,
+ 0xfba1, 0x40e7,
+ 0xfbc0, 0x4105,
+ 0xfbce, 0x4112,
+ 0xfc40, 0x4143,
+ 0xfc4b, 0x414d,
+ 0xfc4f, 0x212f,
+ 0xfc50, 0x4151,
+ 0xfc53, 0x4153,
+ 0xfc64, 0x4163,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcb9, 0x115f,
+ 0xfcba, 0x4195,
+ 0xfcbd, 0x4197,
+ 0xfce4, 0x41bd,
+ 0xfcef, 0x41c7,
+ 0xfd40, 0x41d7,
+ 0xfd4a, 0x41e0,
+ 0xfda1, 0x4215,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe6e, 0x429f,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeaa, 0x0120,
+ 0xfeab, 0x42b8,
+ 0xfee0, 0x42eb,
+ 0xfeef, 0x42f8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKgccsB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKgccsB5HMap2, 553
+};
+
+static Gushort cns13HKgccsB5VMap2[1130] = {
+ 0x0000, 0x0000,
+ 0x8a40, 0x4308,
+ 0x8aa1, 0x4347,
+ 0x8b41, 0x438c,
+ 0x8b45, 0x438e,
+ 0x8b47, 0x438f,
+ 0x8b49, 0x4390,
+ 0x8b4b, 0x4391,
+ 0x8b4d, 0x4392,
+ 0x8b54, 0x4396,
+ 0x8b58, 0x4397,
+ 0x8b5a, 0x4398,
+ 0x8e40, 0x372b,
+ 0x8e46, 0x3730,
+ 0x8e6c, 0x3755,
+ 0x8e77, 0x375f,
+ 0x8e7e, 0x0121,
+ 0x8ea1, 0x3766,
+ 0x8ea7, 0x376b,
+ 0x8eca, 0x378d,
+ 0x8ee6, 0x37a8,
+ 0x8ef0, 0x37b1,
+ 0x8f40, 0x37c0,
+ 0x8f5a, 0x37d9,
+ 0x8f60, 0x37de,
+ 0x8f68, 0x37e5,
+ 0x8fa1, 0x37fc,
+ 0x8fc6, 0x3820,
+ 0x8fc8, 0x3821,
+ 0x8fdb, 0x3833,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x905e, 0x3872,
+ 0x9070, 0x3883,
+ 0x907a, 0x36e9,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a7, 0x3896,
+ 0x90b9, 0x38a7,
+ 0x9140, 0x38ed,
+ 0x9166, 0x3912,
+ 0x916f, 0x391a,
+ 0x91a1, 0x3929,
+ 0x91a3, 0x392a,
+ 0x9240, 0x3986,
+ 0x92a1, 0x39c5,
+ 0x92af, 0x0119,
+ 0x92b1, 0x011c,
+ 0x92b2, 0x011b,
+ 0x92b3, 0x39d3,
+ 0x92e6, 0x3a05,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93ab, 0x3a64,
+ 0x93c3, 0x3a7b,
+ 0x93e6, 0x3a9d,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9447, 0x3abb,
+ 0x94a1, 0x3af3,
+ 0x9540, 0x3b51,
+ 0x954e, 0x3b5e,
+ 0x955b, 0x3b6a,
+ 0x95a1, 0x3b8e,
+ 0x95c7, 0x3bb3,
+ 0x9640, 0x3beb,
+ 0x96a1, 0x3c2a,
+ 0x96d5, 0x3c5d,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9877, 0x3d59,
+ 0x987a, 0x3d5a,
+ 0x98a3, 0x3d5b,
+ 0x98af, 0x3d5c,
+ 0x98b6, 0x3d5d,
+ 0x98b9, 0x3d5e,
+ 0x98bd, 0x3d5f,
+ 0x98c2, 0x3d61,
+ 0x98c4, 0x3d62,
+ 0x98c6, 0x3d63,
+ 0x98e3, 0x3d65,
+ 0x98e7, 0x3d66,
+ 0x98ed, 0x3d67,
+ 0x98f0, 0x3d68,
+ 0x98f2, 0x3d69,
+ 0x98fc, 0x3d6a,
+ 0x9943, 0x3d6b,
+ 0x9945, 0x3d6c,
+ 0x994f, 0x3d6d,
+ 0x996a, 0x3d6e,
+ 0x996e, 0x3d6f,
+ 0x9975, 0x3d70,
+ 0x9978, 0x3d71,
+ 0x99a2, 0x3d72,
+ 0x99ae, 0x3d73,
+ 0x99b6, 0x3d74,
+ 0x99ba, 0x3d75,
+ 0x99e2, 0x3d76,
+ 0x99f4, 0x3d77,
+ 0x9a4a, 0x3d78,
+ 0x9a4c, 0x3d79,
+ 0x9a59, 0x3d7a,
+ 0x9a61, 0x3d7b,
+ 0x9a68, 0x3d7c,
+ 0x9a73, 0x3d7d,
+ 0x9a7e, 0x3d7e,
+ 0x9ab2, 0x3d7f,
+ 0x9ab7, 0x3d80,
+ 0x9ab9, 0x3d81,
+ 0x9abb, 0x3d82,
+ 0x9ac7, 0x3d83,
+ 0x9ad0, 0x3d84,
+ 0x9ad2, 0x3d85,
+ 0x9ad9, 0x3d86,
+ 0x9ae2, 0x3d89,
+ 0x9ae4, 0x3d8a,
+ 0x9ae8, 0x3d8b,
+ 0x9af2, 0x3d8c,
+ 0x9af6, 0x3d8d,
+ 0x9afb, 0x3d8e,
+ 0x9b46, 0x3d8f,
+ 0x9b4a, 0x3d90,
+ 0x9b4c, 0x3d91,
+ 0x9b54, 0x3d92,
+ 0x9b58, 0x3d93,
+ 0x9b5a, 0x3d94,
+ 0x9b5c, 0x3d95,
+ 0x9b5e, 0x3d96,
+ 0x9b70, 0x3d98,
+ 0x9b76, 0x3d9c,
+ 0x9b7b, 0x3d9f,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba3, 0x3da3,
+ 0x9ba7, 0x3da5,
+ 0x9bac, 0x3da9,
+ 0x9baf, 0x3daa,
+ 0x9bb2, 0x3dab,
+ 0x9bbe, 0x3db3,
+ 0x9bc0, 0x3db4,
+ 0x9bca, 0x3dbb,
+ 0x9bcc, 0x3dbc,
+ 0x9bd0, 0x3dbd,
+ 0x9bd3, 0x3dbf,
+ 0x9bd5, 0x3dc0,
+ 0x9bd8, 0x3dc1,
+ 0x9bdd, 0x3dc4,
+ 0x9bde, 0x1c14,
+ 0x9bdf, 0x3dc5,
+ 0x9be1, 0x3dc6,
+ 0x9be3, 0x3dc7,
+ 0x9be7, 0x3dc8,
+ 0x9be9, 0x3dc9,
+ 0x9bee, 0x3dcd,
+ 0x9bf3, 0x3dcf,
+ 0x9bf6, 0x3dd0,
+ 0x9bf8, 0x3dd1,
+ 0x9bfb, 0x3dd3,
+ 0x9c40, 0x3dd5,
+ 0x9c44, 0x3dd8,
+ 0x9c48, 0x3ddb,
+ 0x9c4a, 0x3ddc,
+ 0x9c4d, 0x3ddd,
+ 0x9c55, 0x3de4,
+ 0x9c57, 0x3de5,
+ 0x9c5d, 0x3dea,
+ 0x9c60, 0x3deb,
+ 0x9c62, 0x3dec,
+ 0x9c64, 0x3ded,
+ 0x9c68, 0x3df0,
+ 0x9c6a, 0x3df1,
+ 0x9c6b, 0x346a,
+ 0x9c6d, 0x3df2,
+ 0x9c6f, 0x3df3,
+ 0x9c75, 0x3df7,
+ 0x9c79, 0x3dfa,
+ 0x9c7b, 0x3dfb,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca5, 0x3e00,
+ 0x9ca8, 0x3e01,
+ 0x9cab, 0x3e03,
+ 0x9cad, 0x3e04,
+ 0x9cb1, 0x3e06,
+ 0x9cbc, 0x3e10,
+ 0x9cc6, 0x3e17,
+ 0x9ccf, 0x3e1f,
+ 0x9cd8, 0x3e24,
+ 0x9cdc, 0x3e27,
+ 0x9ce7, 0x3e31,
+ 0x9ceb, 0x3e34,
+ 0x9cee, 0x3e36,
+ 0x9cfd, 0x3e42,
+ 0x9d46, 0x3e43,
+ 0x9d49, 0x3e44,
+ 0x9d4c, 0x3e46,
+ 0x9d4f, 0x3e48,
+ 0x9d51, 0x3e49,
+ 0x9d55, 0x3e4a,
+ 0x9d57, 0x25c1,
+ 0x9d5a, 0x3e4b,
+ 0x9d62, 0x3e4c,
+ 0x9d64, 0x3e4d,
+ 0x9d79, 0x3e4e,
+ 0x9d7e, 0x3e4f,
+ 0x9da5, 0x3e50,
+ 0x9daa, 0x3e54,
+ 0x9dac, 0x3e55,
+ 0x9db0, 0x3e58,
+ 0x9db3, 0x3e59,
+ 0x9db5, 0x3e5a,
+ 0x9db7, 0x3e5b,
+ 0x9dbc, 0x3e5c,
+ 0x9dbf, 0x3e5e,
+ 0x9dc3, 0x3e60,
+ 0x9dc7, 0x3e62,
+ 0x9dca, 0x3e64,
+ 0x9dcd, 0x3e65,
+ 0x9dd3, 0x3e6a,
+ 0x9dda, 0x3e6d,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e64, 0x3eb4,
+ 0x9e68, 0x3eb6,
+ 0x9e6a, 0x3eb7,
+ 0x9e71, 0x3eb8,
+ 0x9e73, 0x3eb9,
+ 0x9e77, 0x3eba,
+ 0x9e7a, 0x3ebc,
+ 0x9e7c, 0x3ebd,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea4, 0x3ec1,
+ 0x9ea9, 0x3ec4,
+ 0x9eac, 0x3ec6,
+ 0x9eaf, 0x3ec8,
+ 0x9eb4, 0x3ecb,
+ 0x9eb6, 0x3ecc,
+ 0x9eb9, 0x3ece,
+ 0x9ebc, 0x3ecf,
+ 0x9ebf, 0x3ed0,
+ 0x9ec4, 0x3ed2,
+ 0x9ec7, 0x3ed4,
+ 0x9ecc, 0x3ed8,
+ 0x9ed0, 0x3eda,
+ 0x9ed3, 0x3edc,
+ 0x9ed6, 0x3edd,
+ 0x9eda, 0x3edf,
+ 0x9ef3, 0x3ef7,
+ 0x9ef9, 0x3efa,
+ 0x9efc, 0x3efc,
+ 0x9f40, 0x3eff,
+ 0x9f44, 0x3f02,
+ 0x9f49, 0x3f06,
+ 0x9f4d, 0x3f08,
+ 0x9f69, 0x3f23,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fb6, 0x3f4c,
+ 0x9fbc, 0x3f51,
+ 0x9fc0, 0x3f54,
+ 0x9fc2, 0x3f55,
+ 0x9fe5, 0x3f77,
+ 0x9ffa, 0x3f8b,
+ 0xa041, 0x3f90,
+ 0xa048, 0x3f96,
+ 0xa056, 0x3fa3,
+ 0xa06e, 0x3fba,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a3, 0x3fcb,
+ 0xa0a8, 0x3fcf,
+ 0xa0c6, 0x3fec,
+ 0xa0d1, 0x3ff6,
+ 0xa0e4, 0x4008,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa40, 0x400b,
+ 0xfaa1, 0x404a,
+ 0xfb40, 0x40a8,
+ 0xfba1, 0x40e7,
+ 0xfbc0, 0x4105,
+ 0xfbce, 0x4112,
+ 0xfc40, 0x4143,
+ 0xfc4b, 0x414d,
+ 0xfc4f, 0x212f,
+ 0xfc50, 0x4151,
+ 0xfc53, 0x4153,
+ 0xfc64, 0x4163,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcb9, 0x115f,
+ 0xfcba, 0x4195,
+ 0xfcbd, 0x4197,
+ 0xfce4, 0x41bd,
+ 0xfcef, 0x41c7,
+ 0xfd40, 0x41d7,
+ 0xfd4a, 0x41e0,
+ 0xfda1, 0x4215,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe6e, 0x429f,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeaa, 0x0120,
+ 0xfeab, 0x42b8,
+ 0xfee0, 0x42eb,
+ 0xfeef, 0x42f8,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKgccsB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKgccsB5VMap2, 565
+};
+
+static Gushort cns13HKm314B5HMap2[1086] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc740, 0x3d6d,
+ 0xc741, 0x39c4,
+ 0xc742, 0x4399,
+ 0xc743, 0x3e05,
+ 0xc744, 0x36ea,
+ 0xc745, 0x39c8,
+ 0xc746, 0x393d,
+ 0xc747, 0x439b,
+ 0xc748, 0x4022,
+ 0xc749, 0x439d,
+ 0xc74a, 0x4034,
+ 0xc74b, 0x439f,
+ 0xc74c, 0x3ea3,
+ 0xc74d, 0x3ea6,
+ 0xc74e, 0x4051,
+ 0xc74f, 0x4048,
+ 0xc751, 0x404b,
+ 0xc752, 0x404f,
+ 0xc753, 0x43a2,
+ 0xc754, 0x405a,
+ 0xc755, 0x3ea4,
+ 0xc756, 0x3dbd,
+ 0xc757, 0x3dbf,
+ 0xc758, 0x405c,
+ 0xc759, 0x405f,
+ 0xc75a, 0x43a4,
+ 0xc75b, 0x407b,
+ 0xc75c, 0x4082,
+ 0xc75d, 0x3f6d,
+ 0xc75e, 0x408b,
+ 0xc75f, 0x43a6,
+ 0xc760, 0x4093,
+ 0xc761, 0x4096,
+ 0xc762, 0x43a7,
+ 0xc763, 0x4098,
+ 0xc764, 0x3e7f,
+ 0xc765, 0x3c77,
+ 0xc766, 0x3ea7,
+ 0xc767, 0x3e8a,
+ 0xc768, 0x3e98,
+ 0xc769, 0x3e8c,
+ 0xc76a, 0x40a1,
+ 0xc76b, 0x3a00,
+ 0xc76c, 0x39a3,
+ 0xc76d, 0x3e8d,
+ 0xc76e, 0x43a8,
+ 0xc76f, 0x3f58,
+ 0xc770, 0x3dbc,
+ 0xc771, 0x3ccc,
+ 0xc772, 0x3ea8,
+ 0xc774, 0x3b2e,
+ 0xc775, 0x3bc6,
+ 0xc776, 0x3e8b,
+ 0xc777, 0x3e9f,
+ 0xc778, 0x432c,
+ 0xc779, 0x43a9,
+ 0xc77a, 0x3f08,
+ 0xc77b, 0x3ea5,
+ 0xc77c, 0x3e89,
+ 0xc77d, 0x3dc3,
+ 0xc77e, 0x3e82,
+ 0xc7a1, 0x3e81,
+ 0xc7a2, 0x3e94,
+ 0xc7a3, 0x3e83,
+ 0xc7a4, 0x3e88,
+ 0xc7a5, 0x43ab,
+ 0xc7a6, 0x3e91,
+ 0xc7a7, 0x43ac,
+ 0xc7a8, 0x3e7c,
+ 0xc7a9, 0x3e80,
+ 0xc7aa, 0x3e8f,
+ 0xc7ab, 0x3e67,
+ 0xc7ac, 0x3e78,
+ 0xc7ad, 0x3e68,
+ 0xc7ae, 0x43ad,
+ 0xc7af, 0x37d2,
+ 0xc7b0, 0x3f4d,
+ 0xc7b1, 0x43ae,
+ 0xc7b2, 0x3e7e,
+ 0xc7b3, 0x40bc,
+ 0xc7b4, 0x3e63,
+ 0xc7b5, 0x40bd,
+ 0xc7b6, 0x43af,
+ 0xc7b7, 0x40b7,
+ 0xc7b8, 0x3eb7,
+ 0xc7b9, 0x3eed,
+ 0xc7ba, 0x3f6a,
+ 0xc7bb, 0x3e95,
+ 0xc7bc, 0x3948,
+ 0xc7bd, 0x3cc8,
+ 0xc7be, 0x43b1,
+ 0xc7c0, 0x40cc,
+ 0xc7c1, 0x3e86,
+ 0xc7c2, 0x3c7a,
+ 0xc7c3, 0x3c7d,
+ 0xc7c4, 0x43b4,
+ 0xc7c5, 0x40d1,
+ 0xc7c6, 0x3d72,
+ 0xc7c7, 0x3c26,
+ 0xc7c8, 0x36eb,
+ 0xc7c9, 0x40bf,
+ 0xc7ca, 0x4100,
+ 0xc7cb, 0x3c85,
+ 0xc7cc, 0x43b5,
+ 0xc7cd, 0x3a1d,
+ 0xc7ce, 0x37f5,
+ 0xc7cf, 0x36ee,
+ 0xc7d0, 0x3e5f,
+ 0xc7d1, 0x4116,
+ 0xc7d2, 0x411f,
+ 0xc7d3, 0x4118,
+ 0xc7d4, 0x4123,
+ 0xc7d5, 0x4127,
+ 0xc7d6, 0x4129,
+ 0xc7d7, 0x43bc,
+ 0xc7d9, 0x3e8e,
+ 0xc7da, 0x386f,
+ 0xc7db, 0x4143,
+ 0xc7dc, 0x4146,
+ 0xc7dd, 0x4144,
+ 0xc7de, 0x4149,
+ 0xc7df, 0x3ba5,
+ 0xc7e0, 0x4157,
+ 0xc7e1, 0x4161,
+ 0xc7e2, 0x36ec,
+ 0xc7e3, 0x416a,
+ 0xc7e4, 0x4002,
+ 0xc7e5, 0x4186,
+ 0xc7e6, 0x3fba,
+ 0xc7e7, 0x3f50,
+ 0xc7e8, 0x3e96,
+ 0xc7e9, 0x418a,
+ 0xc7ea, 0x3fc1,
+ 0xc7eb, 0x3d8f,
+ 0xc7ec, 0x43c1,
+ 0xc7ed, 0x3ea0,
+ 0xc7ee, 0x3f16,
+ 0xc7ef, 0x3e9d,
+ 0xc7f0, 0x4192,
+ 0xc7f1, 0x3a66,
+ 0xc7f2, 0x3e9c,
+ 0xc7f3, 0x3e90,
+ 0xc7f4, 0x419d,
+ 0xc7f5, 0x43c2,
+ 0xc7f7, 0x37a8,
+ 0xc7f8, 0x419e,
+ 0xc7f9, 0x4187,
+ 0xc7fa, 0x3ea2,
+ 0xc7fb, 0x3e87,
+ 0xc7fc, 0x3e84,
+ 0xc7fd, 0x3eae,
+ 0xc7fe, 0x3b74,
+ 0xc840, 0x3b75,
+ 0xc841, 0x3b72,
+ 0xc842, 0x3eb2,
+ 0xc843, 0x3eac,
+ 0xc844, 0x41ca,
+ 0xc845, 0x41f4,
+ 0xc846, 0x41d0,
+ 0xc847, 0x3aaa,
+ 0xc848, 0x41f5,
+ 0xc849, 0x41f8,
+ 0xc84a, 0x41fb,
+ 0xc84b, 0x4205,
+ 0xc84c, 0x3d8e,
+ 0xc84d, 0x420e,
+ 0xc84e, 0x3d63,
+ 0xc84f, 0x4222,
+ 0xc850, 0x4221,
+ 0xc851, 0x4223,
+ 0xc852, 0x4069,
+ 0xc853, 0x402f,
+ 0xc854, 0x38a5,
+ 0xc855, 0x3cf5,
+ 0xc856, 0x3d69,
+ 0xc857, 0x425b,
+ 0xc858, 0x3ac8,
+ 0xc859, 0x3dc0,
+ 0xc85a, 0x39ea,
+ 0xc85b, 0x4000,
+ 0xc85c, 0x4264,
+ 0xc85d, 0x4262,
+ 0xc85e, 0x3fff,
+ 0xc85f, 0x3e9a,
+ 0xc860, 0x4273,
+ 0xc861, 0x3969,
+ 0xc862, 0x427a,
+ 0xc863, 0x43ca,
+ 0xc864, 0x3f9a,
+ 0xc865, 0x3eb5,
+ 0xc866, 0x43cb,
+ 0xc868, 0x3fb2,
+ 0xc869, 0x428a,
+ 0xc86c, 0x3adf,
+ 0xc86d, 0x42c8,
+ 0xc86e, 0x3ead,
+ 0xc86f, 0x43ce,
+ 0xc870, 0x3f8f,
+ 0xc871, 0x43cf,
+ 0xc872, 0x3e72,
+ 0xc873, 0x3eaa,
+ 0xc874, 0x43d3,
+ 0xc875, 0x42e0,
+ 0xc876, 0x382d,
+ 0xc877, 0x3fd5,
+ 0xc878, 0x3b14,
+ 0xc879, 0x36e8,
+ 0xc87a, 0x42f0,
+ 0xc87b, 0x3e7d,
+ 0xc87c, 0x42fe,
+ 0xc87d, 0x4305,
+ 0xc87e, 0x373a,
+ 0xc8a1, 0x3746,
+ 0xc8a2, 0x3752,
+ 0xc8a3, 0x36ed,
+ 0xc8a4, 0x3b4a,
+ 0xc8a5, 0x3b45,
+ 0xc8a6, 0x43da,
+ 0xc8a7, 0x3ede,
+ 0xc8a8, 0x376c,
+ 0xc8a9, 0x376b,
+ 0xc8aa, 0x3782,
+ 0xc8ab, 0x3e69,
+ 0xc8ac, 0x3b4f,
+ 0xc8ad, 0x3786,
+ 0xc8ae, 0x43db,
+ 0xc8af, 0x3788,
+ 0xc8b0, 0x43dc,
+ 0xc8b1, 0x3ecd,
+ 0xc8b2, 0x3797,
+ 0xc8b3, 0x420d,
+ 0xc8b4, 0x37d8,
+ 0xc8b5, 0x3b71,
+ 0xc8b6, 0x38dc,
+ 0xc8b7, 0x37e0,
+ 0xc8b8, 0x37f4,
+ 0xc8b9, 0x3813,
+ 0xc8ba, 0x3eb0,
+ 0xc8bb, 0x380d,
+ 0xc8bc, 0x3eaf,
+ 0xc8bd, 0x381b,
+ 0xc8bf, 0x381e,
+ 0xc8c1, 0x3eb1,
+ 0xc8c2, 0x3fe9,
+ 0xc8c3, 0x43e4,
+ 0xc8c4, 0x3ff9,
+ 0xc8c5, 0x3e59,
+ 0xc8c6, 0x3e99,
+ 0xc8c7, 0x3e5e,
+ 0xc8c8, 0x3bb4,
+ 0xc8c9, 0x3eab,
+ 0xc8ca, 0x43e7,
+ 0xc8cc, 0x385e,
+ 0xc8cd, 0x43e9,
+ 0xc8ce, 0x3dbe,
+ 0xc8cf, 0x3e85,
+ 0xc8d0, 0x3863,
+ 0xc8d2, 0x3d6c,
+ 0xc8d3, 0x3871,
+ 0xc8d4, 0x387c,
+ 0xc8d5, 0x3882,
+ 0xc8d6, 0x3e9b,
+ 0xc8d7, 0x3888,
+ 0xc8d8, 0x3c0e,
+ 0xc8d9, 0x382e,
+ 0xc8da, 0x389a,
+ 0xc8db, 0x388b,
+ 0xc8dc, 0x3c04,
+ 0xc8dd, 0x36e9,
+ 0xc8de, 0x42bd,
+ 0xc8df, 0x3bcd,
+ 0xc8e0, 0x389f,
+ 0xc8e1, 0x379b,
+ 0xc8e2, 0x38af,
+ 0xc8e3, 0x3e97,
+ 0xc8e4, 0x38f0,
+ 0xc8e5, 0x3bfd,
+ 0xc8e6, 0x3c11,
+ 0xc8e8, 0x43ef,
+ 0xc8e9, 0x3785,
+ 0xc8ea, 0x3902,
+ 0xc8eb, 0x3faa,
+ 0xc8ec, 0x3f19,
+ 0xc8ed, 0x3919,
+ 0xc8ee, 0x43f1,
+ 0xc8ef, 0x391a,
+ 0xc8f1, 0x3e66,
+ 0xc8f2, 0x3f22,
+ 0xc8f3, 0x3d7e,
+ 0xc8f4, 0x3c39,
+ 0xc8f5, 0x3ea1,
+ 0xc8f6, 0x43f2,
+ 0xc8f8, 0x3f30,
+ 0xc8f9, 0x3929,
+ 0xc8fa, 0x3fbc,
+ 0xc8fb, 0x3936,
+ 0xc8fd, 0x3f90,
+ 0xc8fe, 0x0aba,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKm314B5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKm314B5HMap2, 543
+};
+
+static Gushort cns13HKm314B5VMap2[1110] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc740, 0x3d6d,
+ 0xc741, 0x39c4,
+ 0xc742, 0x4399,
+ 0xc743, 0x3e05,
+ 0xc744, 0x36ea,
+ 0xc745, 0x39c8,
+ 0xc746, 0x393d,
+ 0xc747, 0x439b,
+ 0xc748, 0x4022,
+ 0xc749, 0x439d,
+ 0xc74a, 0x4034,
+ 0xc74b, 0x439f,
+ 0xc74c, 0x3ea3,
+ 0xc74d, 0x3ea6,
+ 0xc74e, 0x4051,
+ 0xc74f, 0x4048,
+ 0xc751, 0x404b,
+ 0xc752, 0x404f,
+ 0xc753, 0x43a2,
+ 0xc754, 0x405a,
+ 0xc755, 0x3ea4,
+ 0xc756, 0x3dbd,
+ 0xc757, 0x3dbf,
+ 0xc758, 0x405c,
+ 0xc759, 0x405f,
+ 0xc75a, 0x43a4,
+ 0xc75b, 0x407b,
+ 0xc75c, 0x4082,
+ 0xc75d, 0x3f6d,
+ 0xc75e, 0x408b,
+ 0xc75f, 0x43a6,
+ 0xc760, 0x4093,
+ 0xc761, 0x4096,
+ 0xc762, 0x43a7,
+ 0xc763, 0x4098,
+ 0xc764, 0x3e7f,
+ 0xc765, 0x3c77,
+ 0xc766, 0x3ea7,
+ 0xc767, 0x3e8a,
+ 0xc768, 0x3e98,
+ 0xc769, 0x3e8c,
+ 0xc76a, 0x40a1,
+ 0xc76b, 0x3a00,
+ 0xc76c, 0x39a3,
+ 0xc76d, 0x3e8d,
+ 0xc76e, 0x43a8,
+ 0xc76f, 0x3f58,
+ 0xc770, 0x3dbc,
+ 0xc771, 0x3ccc,
+ 0xc772, 0x3ea8,
+ 0xc774, 0x3b2e,
+ 0xc775, 0x3bc6,
+ 0xc776, 0x3e8b,
+ 0xc777, 0x3e9f,
+ 0xc778, 0x432c,
+ 0xc779, 0x43a9,
+ 0xc77a, 0x3f08,
+ 0xc77b, 0x3ea5,
+ 0xc77c, 0x3e89,
+ 0xc77d, 0x3dc3,
+ 0xc77e, 0x3e82,
+ 0xc7a1, 0x3e81,
+ 0xc7a2, 0x3e94,
+ 0xc7a3, 0x3e83,
+ 0xc7a4, 0x3e88,
+ 0xc7a5, 0x43ab,
+ 0xc7a6, 0x3e91,
+ 0xc7a7, 0x43ac,
+ 0xc7a8, 0x3e7c,
+ 0xc7a9, 0x3e80,
+ 0xc7aa, 0x3e8f,
+ 0xc7ab, 0x3e67,
+ 0xc7ac, 0x3e78,
+ 0xc7ad, 0x3e68,
+ 0xc7ae, 0x43ad,
+ 0xc7af, 0x37d2,
+ 0xc7b0, 0x3f4d,
+ 0xc7b1, 0x43ae,
+ 0xc7b2, 0x3e7e,
+ 0xc7b3, 0x40bc,
+ 0xc7b4, 0x3e63,
+ 0xc7b5, 0x40bd,
+ 0xc7b6, 0x43af,
+ 0xc7b7, 0x40b7,
+ 0xc7b8, 0x3eb7,
+ 0xc7b9, 0x3eed,
+ 0xc7ba, 0x3f6a,
+ 0xc7bb, 0x3e95,
+ 0xc7bc, 0x3948,
+ 0xc7bd, 0x3cc8,
+ 0xc7be, 0x43b1,
+ 0xc7c0, 0x40cc,
+ 0xc7c1, 0x3e86,
+ 0xc7c2, 0x3c7a,
+ 0xc7c3, 0x3c7d,
+ 0xc7c4, 0x43b4,
+ 0xc7c5, 0x40d1,
+ 0xc7c6, 0x3d72,
+ 0xc7c7, 0x3c26,
+ 0xc7c8, 0x36eb,
+ 0xc7c9, 0x40bf,
+ 0xc7ca, 0x4100,
+ 0xc7cb, 0x3c85,
+ 0xc7cc, 0x43b5,
+ 0xc7cd, 0x3a1d,
+ 0xc7ce, 0x37f5,
+ 0xc7cf, 0x36ee,
+ 0xc7d0, 0x3e5f,
+ 0xc7d1, 0x4116,
+ 0xc7d2, 0x411f,
+ 0xc7d3, 0x4118,
+ 0xc7d4, 0x4123,
+ 0xc7d5, 0x4127,
+ 0xc7d6, 0x4129,
+ 0xc7d7, 0x43bc,
+ 0xc7d9, 0x3e8e,
+ 0xc7da, 0x386f,
+ 0xc7db, 0x4143,
+ 0xc7dc, 0x4146,
+ 0xc7dd, 0x4144,
+ 0xc7de, 0x4149,
+ 0xc7df, 0x3ba5,
+ 0xc7e0, 0x4157,
+ 0xc7e1, 0x4161,
+ 0xc7e2, 0x36ec,
+ 0xc7e3, 0x416a,
+ 0xc7e4, 0x4002,
+ 0xc7e5, 0x4186,
+ 0xc7e6, 0x3fba,
+ 0xc7e7, 0x3f50,
+ 0xc7e8, 0x3e96,
+ 0xc7e9, 0x418a,
+ 0xc7ea, 0x3fc1,
+ 0xc7eb, 0x3d8f,
+ 0xc7ec, 0x43c1,
+ 0xc7ed, 0x3ea0,
+ 0xc7ee, 0x3f16,
+ 0xc7ef, 0x3e9d,
+ 0xc7f0, 0x4192,
+ 0xc7f1, 0x3a66,
+ 0xc7f2, 0x3e9c,
+ 0xc7f3, 0x3e90,
+ 0xc7f4, 0x419d,
+ 0xc7f5, 0x43c2,
+ 0xc7f7, 0x37a8,
+ 0xc7f8, 0x419e,
+ 0xc7f9, 0x4187,
+ 0xc7fa, 0x3ea2,
+ 0xc7fb, 0x3e87,
+ 0xc7fc, 0x3e84,
+ 0xc7fd, 0x3eae,
+ 0xc7fe, 0x3b74,
+ 0xc840, 0x3b75,
+ 0xc841, 0x3b72,
+ 0xc842, 0x3eb2,
+ 0xc843, 0x3eac,
+ 0xc844, 0x41ca,
+ 0xc845, 0x41f4,
+ 0xc846, 0x41d0,
+ 0xc847, 0x3aaa,
+ 0xc848, 0x41f5,
+ 0xc849, 0x41f8,
+ 0xc84a, 0x41fb,
+ 0xc84b, 0x4205,
+ 0xc84c, 0x3d8e,
+ 0xc84d, 0x420e,
+ 0xc84e, 0x3d63,
+ 0xc84f, 0x4222,
+ 0xc850, 0x4221,
+ 0xc851, 0x4223,
+ 0xc852, 0x4069,
+ 0xc853, 0x402f,
+ 0xc854, 0x38a5,
+ 0xc855, 0x3cf5,
+ 0xc856, 0x3d69,
+ 0xc857, 0x425b,
+ 0xc858, 0x3ac8,
+ 0xc859, 0x3dc0,
+ 0xc85a, 0x39ea,
+ 0xc85b, 0x4000,
+ 0xc85c, 0x4264,
+ 0xc85d, 0x4262,
+ 0xc85e, 0x3fff,
+ 0xc85f, 0x3e9a,
+ 0xc860, 0x4273,
+ 0xc861, 0x3969,
+ 0xc862, 0x427a,
+ 0xc863, 0x43ca,
+ 0xc864, 0x3f9a,
+ 0xc865, 0x3eb5,
+ 0xc866, 0x43cb,
+ 0xc868, 0x3fb2,
+ 0xc869, 0x428a,
+ 0xc86c, 0x3adf,
+ 0xc86d, 0x42c8,
+ 0xc86e, 0x3ead,
+ 0xc86f, 0x43ce,
+ 0xc870, 0x3f8f,
+ 0xc871, 0x43cf,
+ 0xc872, 0x3e72,
+ 0xc873, 0x3eaa,
+ 0xc874, 0x43d3,
+ 0xc875, 0x42e0,
+ 0xc876, 0x382d,
+ 0xc877, 0x3fd5,
+ 0xc878, 0x3b14,
+ 0xc879, 0x36e8,
+ 0xc87a, 0x42f0,
+ 0xc87b, 0x3e7d,
+ 0xc87c, 0x42fe,
+ 0xc87d, 0x4305,
+ 0xc87e, 0x373a,
+ 0xc8a1, 0x3746,
+ 0xc8a2, 0x3752,
+ 0xc8a3, 0x36ed,
+ 0xc8a4, 0x3b4a,
+ 0xc8a5, 0x3b45,
+ 0xc8a6, 0x43da,
+ 0xc8a7, 0x3ede,
+ 0xc8a8, 0x376c,
+ 0xc8a9, 0x376b,
+ 0xc8aa, 0x3782,
+ 0xc8ab, 0x3e69,
+ 0xc8ac, 0x3b4f,
+ 0xc8ad, 0x3786,
+ 0xc8ae, 0x43db,
+ 0xc8af, 0x3788,
+ 0xc8b0, 0x43dc,
+ 0xc8b1, 0x3ecd,
+ 0xc8b2, 0x3797,
+ 0xc8b3, 0x420d,
+ 0xc8b4, 0x37d8,
+ 0xc8b5, 0x3b71,
+ 0xc8b6, 0x38dc,
+ 0xc8b7, 0x37e0,
+ 0xc8b8, 0x37f4,
+ 0xc8b9, 0x3813,
+ 0xc8ba, 0x3eb0,
+ 0xc8bb, 0x380d,
+ 0xc8bc, 0x3eaf,
+ 0xc8bd, 0x381b,
+ 0xc8bf, 0x381e,
+ 0xc8c1, 0x3eb1,
+ 0xc8c2, 0x3fe9,
+ 0xc8c3, 0x43e4,
+ 0xc8c4, 0x3ff9,
+ 0xc8c5, 0x3e59,
+ 0xc8c6, 0x3e99,
+ 0xc8c7, 0x3e5e,
+ 0xc8c8, 0x3bb4,
+ 0xc8c9, 0x3eab,
+ 0xc8ca, 0x43e7,
+ 0xc8cc, 0x385e,
+ 0xc8cd, 0x43e9,
+ 0xc8ce, 0x3dbe,
+ 0xc8cf, 0x3e85,
+ 0xc8d0, 0x3863,
+ 0xc8d2, 0x3d6c,
+ 0xc8d3, 0x3871,
+ 0xc8d4, 0x387c,
+ 0xc8d5, 0x3882,
+ 0xc8d6, 0x3e9b,
+ 0xc8d7, 0x3888,
+ 0xc8d8, 0x3c0e,
+ 0xc8d9, 0x382e,
+ 0xc8da, 0x389a,
+ 0xc8db, 0x388b,
+ 0xc8dc, 0x3c04,
+ 0xc8dd, 0x36e9,
+ 0xc8de, 0x42bd,
+ 0xc8df, 0x3bcd,
+ 0xc8e0, 0x389f,
+ 0xc8e1, 0x379b,
+ 0xc8e2, 0x38af,
+ 0xc8e3, 0x3e97,
+ 0xc8e4, 0x38f0,
+ 0xc8e5, 0x3bfd,
+ 0xc8e6, 0x3c11,
+ 0xc8e8, 0x43ef,
+ 0xc8e9, 0x3785,
+ 0xc8ea, 0x3902,
+ 0xc8eb, 0x3faa,
+ 0xc8ec, 0x3f19,
+ 0xc8ed, 0x3919,
+ 0xc8ee, 0x43f1,
+ 0xc8ef, 0x391a,
+ 0xc8f1, 0x3e66,
+ 0xc8f2, 0x3f22,
+ 0xc8f3, 0x3d7e,
+ 0xc8f4, 0x3c39,
+ 0xc8f5, 0x3ea1,
+ 0xc8f6, 0x43f2,
+ 0xc8f8, 0x3f30,
+ 0xc8f9, 0x3929,
+ 0xc8fa, 0x3fbc,
+ 0xc8fb, 0x3936,
+ 0xc8fd, 0x3f90,
+ 0xc8fe, 0x0aba,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKm314B5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKm314B5VMap2, 555
+};
+
+static Gushort cns13HKm471B5HMap2[1380] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa40, 0x3d6d,
+ 0xfa41, 0x39c4,
+ 0xfa42, 0x4399,
+ 0xfa43, 0x3f4f,
+ 0xfa44, 0x3e05,
+ 0xfa45, 0x439a,
+ 0xfa46, 0x3b8e,
+ 0xfa47, 0x36ea,
+ 0xfa48, 0x39c8,
+ 0xfa49, 0x393d,
+ 0xfa4a, 0x439b,
+ 0xfa4b, 0x4022,
+ 0xfa4c, 0x39cc,
+ 0xfa4e, 0x439c,
+ 0xfa4f, 0x39c5,
+ 0xfa50, 0x439d,
+ 0xfa51, 0x4034,
+ 0xfa52, 0x439e,
+ 0xfa54, 0x3ea3,
+ 0xfa55, 0x3ea6,
+ 0xfa56, 0x43a0,
+ 0xfa57, 0x4051,
+ 0xfa58, 0x4048,
+ 0xfa5a, 0x404b,
+ 0xfa5b, 0x404f,
+ 0xfa5c, 0x4054,
+ 0xfa5d, 0x4178,
+ 0xfa5e, 0x3f0a,
+ 0xfa5f, 0x43a1,
+ 0xfa61, 0x405a,
+ 0xfa62, 0x3ea4,
+ 0xfa63, 0x3dbd,
+ 0xfa64, 0x43a3,
+ 0xfa65, 0x3dbf,
+ 0xfa66, 0x405c,
+ 0xfa67, 0x405f,
+ 0xfa69, 0x4063,
+ 0xfa6a, 0x43a4,
+ 0xfa6b, 0x407a,
+ 0xfa6d, 0x407d,
+ 0xfa6e, 0x4082,
+ 0xfa6f, 0x3f6d,
+ 0xfa70, 0x43a5,
+ 0xfa71, 0x408b,
+ 0xfa72, 0x43a6,
+ 0xfa73, 0x3f39,
+ 0xfa74, 0x4093,
+ 0xfa75, 0x4096,
+ 0xfa76, 0x43a7,
+ 0xfa77, 0x4098,
+ 0xfa78, 0x3e7f,
+ 0xfa79, 0x3c77,
+ 0xfa7a, 0x3ea7,
+ 0xfa7b, 0x4203,
+ 0xfa7c, 0x3ed1,
+ 0xfa7d, 0x3e8a,
+ 0xfa7e, 0x3e98,
+ 0xfaa1, 0x3e8c,
+ 0xfaa2, 0x40a1,
+ 0xfaa3, 0x3d83,
+ 0xfaa4, 0x3a00,
+ 0xfaa5, 0x39a3,
+ 0xfaa6, 0x3e8d,
+ 0xfaa7, 0x43a8,
+ 0xfaa8, 0x3f58,
+ 0xfaa9, 0x3dbc,
+ 0xfaaa, 0x40a2,
+ 0xfaab, 0x3ccc,
+ 0xfaac, 0x3ea8,
+ 0xfaae, 0x3b2e,
+ 0xfaaf, 0x3bc6,
+ 0xfab0, 0x3e8b,
+ 0xfab1, 0x3e9f,
+ 0xfab2, 0x432c,
+ 0xfab3, 0x43a9,
+ 0xfab4, 0x3f08,
+ 0xfab5, 0x3ea5,
+ 0xfab6, 0x3e89,
+ 0xfab7, 0x3dc3,
+ 0xfab8, 0x3e82,
+ 0xfab9, 0x3e81,
+ 0xfaba, 0x3e94,
+ 0xfabb, 0x43aa,
+ 0xfabc, 0x3e83,
+ 0xfabd, 0x3e88,
+ 0xfabe, 0x43ab,
+ 0xfabf, 0x3e91,
+ 0xfac0, 0x43ac,
+ 0xfac1, 0x3e7c,
+ 0xfac2, 0x3e80,
+ 0xfac3, 0x3e8f,
+ 0xfac4, 0x4325,
+ 0xfac5, 0x3e67,
+ 0xfac6, 0x3e78,
+ 0xfac7, 0x3e68,
+ 0xfac8, 0x43ad,
+ 0xfac9, 0x37d2,
+ 0xfaca, 0x3f4d,
+ 0xfacb, 0x43ae,
+ 0xfacc, 0x3e7e,
+ 0xfacd, 0x40bc,
+ 0xface, 0x3e63,
+ 0xfacf, 0x40bd,
+ 0xfad0, 0x43af,
+ 0xfad1, 0x3f6c,
+ 0xfad2, 0x3ef9,
+ 0xfad3, 0x40b7,
+ 0xfad4, 0x3eb7,
+ 0xfad5, 0x3eed,
+ 0xfad6, 0x3f6a,
+ 0xfad7, 0x39a6,
+ 0xfad8, 0x43b0,
+ 0xfad9, 0x3e95,
+ 0xfada, 0x3948,
+ 0xfadb, 0x3cc8,
+ 0xfadc, 0x43b1,
+ 0xfadf, 0x40cc,
+ 0xfae0, 0x3e86,
+ 0xfae1, 0x40c8,
+ 0xfae2, 0x3c7a,
+ 0xfae3, 0x3c7d,
+ 0xfae4, 0x43b4,
+ 0xfae5, 0x40d1,
+ 0xfae6, 0x3d72,
+ 0xfae7, 0x40d4,
+ 0xfae8, 0x3c26,
+ 0xfae9, 0x36eb,
+ 0xfaea, 0x40da,
+ 0xfaeb, 0x40d9,
+ 0xfaec, 0x40bf,
+ 0xfaed, 0x3d81,
+ 0xfaee, 0x40f1,
+ 0xfaef, 0x4100,
+ 0xfaf0, 0x3c85,
+ 0xfaf1, 0x43b5,
+ 0xfaf2, 0x3a1d,
+ 0xfaf3, 0x37f5,
+ 0xfaf4, 0x36ee,
+ 0xfaf5, 0x3e5f,
+ 0xfaf6, 0x4116,
+ 0xfaf7, 0x42bb,
+ 0xfaf8, 0x411f,
+ 0xfaf9, 0x43b6,
+ 0xfafa, 0x4118,
+ 0xfafb, 0x43b7,
+ 0xfafd, 0x4123,
+ 0xfafe, 0x4122,
+ 0xfb40, 0x4127,
+ 0xfb41, 0x43b9,
+ 0xfb42, 0x4129,
+ 0xfb43, 0x43ba,
+ 0xfb44, 0x3dd5,
+ 0xfb45, 0x3eef,
+ 0xfb46, 0x3d8a,
+ 0xfb47, 0x43bb,
+ 0xfb48, 0x3a2b,
+ 0xfb49, 0x43bc,
+ 0xfb4a, 0x4138,
+ 0xfb4b, 0x43bd,
+ 0xfb4c, 0x3e8e,
+ 0xfb4d, 0x3a30,
+ 0xfb4e, 0x386f,
+ 0xfb4f, 0x4143,
+ 0xfb50, 0x4146,
+ 0xfb51, 0x4144,
+ 0xfb52, 0x4149,
+ 0xfb53, 0x3ba5,
+ 0xfb54, 0x4157,
+ 0xfb55, 0x43be,
+ 0xfb56, 0x4161,
+ 0xfb57, 0x36ec,
+ 0xfb58, 0x416a,
+ 0xfb59, 0x3d84,
+ 0xfb5a, 0x4002,
+ 0xfb5b, 0x4186,
+ 0xfb5c, 0x3fba,
+ 0xfb5d, 0x43bf,
+ 0xfb5e, 0x3fc5,
+ 0xfb5f, 0x3f50,
+ 0xfb60, 0x3e96,
+ 0xfb61, 0x43c0,
+ 0xfb62, 0x418a,
+ 0xfb63, 0x3fc1,
+ 0xfb64, 0x3d8f,
+ 0xfb65, 0x43c1,
+ 0xfb66, 0x3ea0,
+ 0xfb67, 0x3f16,
+ 0xfb68, 0x3e9d,
+ 0xfb69, 0x418e,
+ 0xfb6a, 0x4192,
+ 0xfb6b, 0x3a66,
+ 0xfb6c, 0x3e9c,
+ 0xfb6d, 0x438f,
+ 0xfb6e, 0x3e90,
+ 0xfb6f, 0x419d,
+ 0xfb70, 0x43c2,
+ 0xfb72, 0x4356,
+ 0xfb73, 0x37a8,
+ 0xfb74, 0x419e,
+ 0xfb75, 0x4199,
+ 0xfb76, 0x4187,
+ 0xfb77, 0x3ea2,
+ 0xfb78, 0x419f,
+ 0xfb79, 0x3e87,
+ 0xfb7a, 0x3e84,
+ 0xfb7b, 0x3eae,
+ 0xfb7c, 0x3b74,
+ 0xfb7e, 0x37a2,
+ 0xfba1, 0x3b72,
+ 0xfba2, 0x3e79,
+ 0xfba3, 0x3e6d,
+ 0xfba4, 0x43c4,
+ 0xfba6, 0x3eb2,
+ 0xfba7, 0x43c6,
+ 0xfba8, 0x3eac,
+ 0xfba9, 0x41ca,
+ 0xfbaa, 0x41f4,
+ 0xfbab, 0x43c7,
+ 0xfbac, 0x41d0,
+ 0xfbad, 0x3aaa,
+ 0xfbae, 0x41de,
+ 0xfbaf, 0x41db,
+ 0xfbb0, 0x41e8,
+ 0xfbb1, 0x43c8,
+ 0xfbb2, 0x3ff6,
+ 0xfbb3, 0x41d9,
+ 0xfbb4, 0x3d42,
+ 0xfbb5, 0x41f5,
+ 0xfbb6, 0x41f8,
+ 0xfbb7, 0x41fb,
+ 0xfbb8, 0x4205,
+ 0xfbb9, 0x3d8e,
+ 0xfbba, 0x420e,
+ 0xfbbb, 0x3d63,
+ 0xfbbc, 0x4222,
+ 0xfbbd, 0x4221,
+ 0xfbbe, 0x4223,
+ 0xfbbf, 0x4069,
+ 0xfbc0, 0x402f,
+ 0xfbc1, 0x4242,
+ 0xfbc2, 0x38a5,
+ 0xfbc3, 0x4246,
+ 0xfbc4, 0x3cf5,
+ 0xfbc5, 0x3d69,
+ 0xfbc6, 0x3cfe,
+ 0xfbc7, 0x425b,
+ 0xfbc8, 0x3ac8,
+ 0xfbc9, 0x3dc0,
+ 0xfbca, 0x39ea,
+ 0xfbcb, 0x4000,
+ 0xfbcc, 0x4264,
+ 0xfbcd, 0x4262,
+ 0xfbce, 0x3fff,
+ 0xfbcf, 0x3e9a,
+ 0xfbd0, 0x4273,
+ 0xfbd1, 0x3969,
+ 0xfbd2, 0x427a,
+ 0xfbd3, 0x4283,
+ 0xfbd4, 0x43c9,
+ 0xfbd6, 0x3f9a,
+ 0xfbd7, 0x3eb5,
+ 0xfbd8, 0x43cb,
+ 0xfbda, 0x3fb2,
+ 0xfbdb, 0x428a,
+ 0xfbdd, 0x3b17,
+ 0xfbde, 0x428c,
+ 0xfbdf, 0x4290,
+ 0xfbe0, 0x3adf,
+ 0xfbe1, 0x43cd,
+ 0xfbe2, 0x42c5,
+ 0xfbe3, 0x42c8,
+ 0xfbe4, 0x3ead,
+ 0xfbe5, 0x43ce,
+ 0xfbe6, 0x3f8f,
+ 0xfbe7, 0x43cf,
+ 0xfbe8, 0x3e72,
+ 0xfbe9, 0x3e70,
+ 0xfbea, 0x43d0,
+ 0xfbeb, 0x3eaa,
+ 0xfbec, 0x43d1,
+ 0xfbed, 0x3fa9,
+ 0xfbee, 0x43d2,
+ 0xfbf1, 0x42d8,
+ 0xfbf2, 0x3ff3,
+ 0xfbf3, 0x42e0,
+ 0xfbf4, 0x3b00,
+ 0xfbf5, 0x4317,
+ 0xfbf6, 0x382d,
+ 0xfbf7, 0x3e73,
+ 0xfbf8, 0x3fd5,
+ 0xfbf9, 0x43d5,
+ 0xfbfb, 0x3b14,
+ 0xfbfc, 0x36e8,
+ 0xfbfd, 0x42f4,
+ 0xfbfe, 0x3b0e,
+ 0xfc40, 0x42ec,
+ 0xfc41, 0x42f0,
+ 0xfc42, 0x3e7d,
+ 0xfc43, 0x43d7,
+ 0xfc44, 0x42fe,
+ 0xfc45, 0x4305,
+ 0xfc46, 0x3fda,
+ 0xfc47, 0x3df1,
+ 0xfc48, 0x3733,
+ 0xfc49, 0x3d7d,
+ 0xfc4a, 0x43d8,
+ 0xfc4b, 0x373a,
+ 0xfc4c, 0x3740,
+ 0xfc4d, 0x3742,
+ 0xfc4e, 0x3746,
+ 0xfc4f, 0x3752,
+ 0xfc50, 0x3f1f,
+ 0xfc51, 0x43d9,
+ 0xfc52, 0x36ed,
+ 0xfc53, 0x3b4a,
+ 0xfc54, 0x375e,
+ 0xfc55, 0x3b45,
+ 0xfc56, 0x43da,
+ 0xfc57, 0x3ede,
+ 0xfc58, 0x3769,
+ 0xfc59, 0x376c,
+ 0xfc5a, 0x376b,
+ 0xfc5b, 0x376e,
+ 0xfc5c, 0x377f,
+ 0xfc5d, 0x377b,
+ 0xfc5e, 0x3782,
+ 0xfc5f, 0x3e69,
+ 0xfc60, 0x3b4f,
+ 0xfc61, 0x3786,
+ 0xfc62, 0x43db,
+ 0xfc63, 0x3788,
+ 0xfc64, 0x43dc,
+ 0xfc65, 0x3ecd,
+ 0xfc66, 0x3797,
+ 0xfc67, 0x420d,
+ 0xfc68, 0x43dd,
+ 0xfc69, 0x37bc,
+ 0xfc6a, 0x43de,
+ 0xfc6b, 0x37d8,
+ 0xfc6c, 0x3b71,
+ 0xfc6d, 0x3e7a,
+ 0xfc6e, 0x43df,
+ 0xfc6f, 0x38dc,
+ 0xfc70, 0x37e0,
+ 0xfc71, 0x37ee,
+ 0xfc72, 0x37f4,
+ 0xfc73, 0x3813,
+ 0xfc74, 0x43e0,
+ 0xfc76, 0x3eb0,
+ 0xfc77, 0x43e2,
+ 0xfc78, 0x3fed,
+ 0xfc79, 0x380d,
+ 0xfc7a, 0x3eaf,
+ 0xfc7b, 0x3f92,
+ 0xfc7c, 0x3816,
+ 0xfc7d, 0x381b,
+ 0xfc7e, 0x3fa2,
+ 0xfca1, 0x381c,
+ 0xfca2, 0x381e,
+ 0xfca4, 0x3eb1,
+ 0xfca5, 0x134a,
+ 0xfca6, 0x43e3,
+ 0xfca7, 0x3fe9,
+ 0xfca8, 0x43e4,
+ 0xfca9, 0x3ff9,
+ 0xfcaa, 0x3d93,
+ 0xfcab, 0x43e5,
+ 0xfcac, 0x3e59,
+ 0xfcad, 0x43e6,
+ 0xfcae, 0x3837,
+ 0xfcaf, 0x3f99,
+ 0xfcb0, 0x3e99,
+ 0xfcb1, 0x3e5e,
+ 0xfcb2, 0x3bb4,
+ 0xfcb3, 0x3eab,
+ 0xfcb4, 0x43e7,
+ 0xfcb6, 0x385e,
+ 0xfcb7, 0x43e9,
+ 0xfcb8, 0x3dbe,
+ 0xfcb9, 0x3e85,
+ 0xfcba, 0x3863,
+ 0xfcbc, 0x3d6c,
+ 0xfcbd, 0x3871,
+ 0xfcbe, 0x3ee0,
+ 0xfcbf, 0x43ea,
+ 0xfcc0, 0x387c,
+ 0xfcc1, 0x43eb,
+ 0xfcc2, 0x3eb8,
+ 0xfcc3, 0x3882,
+ 0xfcc4, 0x3e9b,
+ 0xfcc5, 0x43ec,
+ 0xfcc6, 0x3888,
+ 0xfcc7, 0x3c0e,
+ 0xfcc8, 0x382e,
+ 0xfcc9, 0x389a,
+ 0xfcca, 0x388b,
+ 0xfccb, 0x3c04,
+ 0xfccc, 0x36e9,
+ 0xfccd, 0x42bd,
+ 0xfcce, 0x3bcd,
+ 0xfccf, 0x389f,
+ 0xfcd0, 0x3dde,
+ 0xfcd1, 0x379b,
+ 0xfcd2, 0x3bd3,
+ 0xfcd3, 0x38af,
+ 0xfcd4, 0x3e97,
+ 0xfcd5, 0x38d6,
+ 0xfcd6, 0x3f35,
+ 0xfcd7, 0x38e0,
+ 0xfcd8, 0x4035,
+ 0xfcd9, 0x38f0,
+ 0xfcda, 0x43ed,
+ 0xfcdc, 0x3bfd,
+ 0xfcdd, 0x3c11,
+ 0xfcdf, 0x43ef,
+ 0xfce0, 0x3785,
+ 0xfce1, 0x3902,
+ 0xfce2, 0x3ddc,
+ 0xfce3, 0x43f0,
+ 0xfce4, 0x3faa,
+ 0xfce5, 0x390b,
+ 0xfce6, 0x3f19,
+ 0xfce7, 0x390e,
+ 0xfce8, 0x3919,
+ 0xfce9, 0x43f1,
+ 0xfcea, 0x3c3c,
+ 0xfceb, 0x391a,
+ 0xfcec, 0x3c3a,
+ 0xfced, 0x391b,
+ 0xfcee, 0x3e66,
+ 0xfcef, 0x3f22,
+ 0xfcf0, 0x3d7e,
+ 0xfcf1, 0x3e71,
+ 0xfcf2, 0x3c39,
+ 0xfcf3, 0x3ea1,
+ 0xfcf4, 0x43f2,
+ 0xfcf6, 0x3f30,
+ 0xfcf7, 0x3929,
+ 0xfcf8, 0x3fbc,
+ 0xfcf9, 0x3936,
+ 0xfcfa, 0x43f4,
+ 0xfcfb, 0x3937,
+ 0xfcfc, 0x3f90,
+ 0xfcfd, 0x43f5,
+ 0xfcfe, 0x0aba,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKm471B5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKm471B5HMap2, 690
+};
+
+static Gushort cns13HKm471B5VMap2[1404] = {
+ 0x0000, 0x0000,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xfa40, 0x3d6d,
+ 0xfa41, 0x39c4,
+ 0xfa42, 0x4399,
+ 0xfa43, 0x3f4f,
+ 0xfa44, 0x3e05,
+ 0xfa45, 0x439a,
+ 0xfa46, 0x3b8e,
+ 0xfa47, 0x36ea,
+ 0xfa48, 0x39c8,
+ 0xfa49, 0x393d,
+ 0xfa4a, 0x439b,
+ 0xfa4b, 0x4022,
+ 0xfa4c, 0x39cc,
+ 0xfa4e, 0x439c,
+ 0xfa4f, 0x39c5,
+ 0xfa50, 0x439d,
+ 0xfa51, 0x4034,
+ 0xfa52, 0x439e,
+ 0xfa54, 0x3ea3,
+ 0xfa55, 0x3ea6,
+ 0xfa56, 0x43a0,
+ 0xfa57, 0x4051,
+ 0xfa58, 0x4048,
+ 0xfa5a, 0x404b,
+ 0xfa5b, 0x404f,
+ 0xfa5c, 0x4054,
+ 0xfa5d, 0x4178,
+ 0xfa5e, 0x3f0a,
+ 0xfa5f, 0x43a1,
+ 0xfa61, 0x405a,
+ 0xfa62, 0x3ea4,
+ 0xfa63, 0x3dbd,
+ 0xfa64, 0x43a3,
+ 0xfa65, 0x3dbf,
+ 0xfa66, 0x405c,
+ 0xfa67, 0x405f,
+ 0xfa69, 0x4063,
+ 0xfa6a, 0x43a4,
+ 0xfa6b, 0x407a,
+ 0xfa6d, 0x407d,
+ 0xfa6e, 0x4082,
+ 0xfa6f, 0x3f6d,
+ 0xfa70, 0x43a5,
+ 0xfa71, 0x408b,
+ 0xfa72, 0x43a6,
+ 0xfa73, 0x3f39,
+ 0xfa74, 0x4093,
+ 0xfa75, 0x4096,
+ 0xfa76, 0x43a7,
+ 0xfa77, 0x4098,
+ 0xfa78, 0x3e7f,
+ 0xfa79, 0x3c77,
+ 0xfa7a, 0x3ea7,
+ 0xfa7b, 0x4203,
+ 0xfa7c, 0x3ed1,
+ 0xfa7d, 0x3e8a,
+ 0xfa7e, 0x3e98,
+ 0xfaa1, 0x3e8c,
+ 0xfaa2, 0x40a1,
+ 0xfaa3, 0x3d83,
+ 0xfaa4, 0x3a00,
+ 0xfaa5, 0x39a3,
+ 0xfaa6, 0x3e8d,
+ 0xfaa7, 0x43a8,
+ 0xfaa8, 0x3f58,
+ 0xfaa9, 0x3dbc,
+ 0xfaaa, 0x40a2,
+ 0xfaab, 0x3ccc,
+ 0xfaac, 0x3ea8,
+ 0xfaae, 0x3b2e,
+ 0xfaaf, 0x3bc6,
+ 0xfab0, 0x3e8b,
+ 0xfab1, 0x3e9f,
+ 0xfab2, 0x432c,
+ 0xfab3, 0x43a9,
+ 0xfab4, 0x3f08,
+ 0xfab5, 0x3ea5,
+ 0xfab6, 0x3e89,
+ 0xfab7, 0x3dc3,
+ 0xfab8, 0x3e82,
+ 0xfab9, 0x3e81,
+ 0xfaba, 0x3e94,
+ 0xfabb, 0x43aa,
+ 0xfabc, 0x3e83,
+ 0xfabd, 0x3e88,
+ 0xfabe, 0x43ab,
+ 0xfabf, 0x3e91,
+ 0xfac0, 0x43ac,
+ 0xfac1, 0x3e7c,
+ 0xfac2, 0x3e80,
+ 0xfac3, 0x3e8f,
+ 0xfac4, 0x4325,
+ 0xfac5, 0x3e67,
+ 0xfac6, 0x3e78,
+ 0xfac7, 0x3e68,
+ 0xfac8, 0x43ad,
+ 0xfac9, 0x37d2,
+ 0xfaca, 0x3f4d,
+ 0xfacb, 0x43ae,
+ 0xfacc, 0x3e7e,
+ 0xfacd, 0x40bc,
+ 0xface, 0x3e63,
+ 0xfacf, 0x40bd,
+ 0xfad0, 0x43af,
+ 0xfad1, 0x3f6c,
+ 0xfad2, 0x3ef9,
+ 0xfad3, 0x40b7,
+ 0xfad4, 0x3eb7,
+ 0xfad5, 0x3eed,
+ 0xfad6, 0x3f6a,
+ 0xfad7, 0x39a6,
+ 0xfad8, 0x43b0,
+ 0xfad9, 0x3e95,
+ 0xfada, 0x3948,
+ 0xfadb, 0x3cc8,
+ 0xfadc, 0x43b1,
+ 0xfadf, 0x40cc,
+ 0xfae0, 0x3e86,
+ 0xfae1, 0x40c8,
+ 0xfae2, 0x3c7a,
+ 0xfae3, 0x3c7d,
+ 0xfae4, 0x43b4,
+ 0xfae5, 0x40d1,
+ 0xfae6, 0x3d72,
+ 0xfae7, 0x40d4,
+ 0xfae8, 0x3c26,
+ 0xfae9, 0x36eb,
+ 0xfaea, 0x40da,
+ 0xfaeb, 0x40d9,
+ 0xfaec, 0x40bf,
+ 0xfaed, 0x3d81,
+ 0xfaee, 0x40f1,
+ 0xfaef, 0x4100,
+ 0xfaf0, 0x3c85,
+ 0xfaf1, 0x43b5,
+ 0xfaf2, 0x3a1d,
+ 0xfaf3, 0x37f5,
+ 0xfaf4, 0x36ee,
+ 0xfaf5, 0x3e5f,
+ 0xfaf6, 0x4116,
+ 0xfaf7, 0x42bb,
+ 0xfaf8, 0x411f,
+ 0xfaf9, 0x43b6,
+ 0xfafa, 0x4118,
+ 0xfafb, 0x43b7,
+ 0xfafd, 0x4123,
+ 0xfafe, 0x4122,
+ 0xfb40, 0x4127,
+ 0xfb41, 0x43b9,
+ 0xfb42, 0x4129,
+ 0xfb43, 0x43ba,
+ 0xfb44, 0x3dd5,
+ 0xfb45, 0x3eef,
+ 0xfb46, 0x3d8a,
+ 0xfb47, 0x43bb,
+ 0xfb48, 0x3a2b,
+ 0xfb49, 0x43bc,
+ 0xfb4a, 0x4138,
+ 0xfb4b, 0x43bd,
+ 0xfb4c, 0x3e8e,
+ 0xfb4d, 0x3a30,
+ 0xfb4e, 0x386f,
+ 0xfb4f, 0x4143,
+ 0xfb50, 0x4146,
+ 0xfb51, 0x4144,
+ 0xfb52, 0x4149,
+ 0xfb53, 0x3ba5,
+ 0xfb54, 0x4157,
+ 0xfb55, 0x43be,
+ 0xfb56, 0x4161,
+ 0xfb57, 0x36ec,
+ 0xfb58, 0x416a,
+ 0xfb59, 0x3d84,
+ 0xfb5a, 0x4002,
+ 0xfb5b, 0x4186,
+ 0xfb5c, 0x3fba,
+ 0xfb5d, 0x43bf,
+ 0xfb5e, 0x3fc5,
+ 0xfb5f, 0x3f50,
+ 0xfb60, 0x3e96,
+ 0xfb61, 0x43c0,
+ 0xfb62, 0x418a,
+ 0xfb63, 0x3fc1,
+ 0xfb64, 0x3d8f,
+ 0xfb65, 0x43c1,
+ 0xfb66, 0x3ea0,
+ 0xfb67, 0x3f16,
+ 0xfb68, 0x3e9d,
+ 0xfb69, 0x418e,
+ 0xfb6a, 0x4192,
+ 0xfb6b, 0x3a66,
+ 0xfb6c, 0x3e9c,
+ 0xfb6d, 0x438f,
+ 0xfb6e, 0x3e90,
+ 0xfb6f, 0x419d,
+ 0xfb70, 0x43c2,
+ 0xfb72, 0x4356,
+ 0xfb73, 0x37a8,
+ 0xfb74, 0x419e,
+ 0xfb75, 0x4199,
+ 0xfb76, 0x4187,
+ 0xfb77, 0x3ea2,
+ 0xfb78, 0x419f,
+ 0xfb79, 0x3e87,
+ 0xfb7a, 0x3e84,
+ 0xfb7b, 0x3eae,
+ 0xfb7c, 0x3b74,
+ 0xfb7e, 0x37a2,
+ 0xfba1, 0x3b72,
+ 0xfba2, 0x3e79,
+ 0xfba3, 0x3e6d,
+ 0xfba4, 0x43c4,
+ 0xfba6, 0x3eb2,
+ 0xfba7, 0x43c6,
+ 0xfba8, 0x3eac,
+ 0xfba9, 0x41ca,
+ 0xfbaa, 0x41f4,
+ 0xfbab, 0x43c7,
+ 0xfbac, 0x41d0,
+ 0xfbad, 0x3aaa,
+ 0xfbae, 0x41de,
+ 0xfbaf, 0x41db,
+ 0xfbb0, 0x41e8,
+ 0xfbb1, 0x43c8,
+ 0xfbb2, 0x3ff6,
+ 0xfbb3, 0x41d9,
+ 0xfbb4, 0x3d42,
+ 0xfbb5, 0x41f5,
+ 0xfbb6, 0x41f8,
+ 0xfbb7, 0x41fb,
+ 0xfbb8, 0x4205,
+ 0xfbb9, 0x3d8e,
+ 0xfbba, 0x420e,
+ 0xfbbb, 0x3d63,
+ 0xfbbc, 0x4222,
+ 0xfbbd, 0x4221,
+ 0xfbbe, 0x4223,
+ 0xfbbf, 0x4069,
+ 0xfbc0, 0x402f,
+ 0xfbc1, 0x4242,
+ 0xfbc2, 0x38a5,
+ 0xfbc3, 0x4246,
+ 0xfbc4, 0x3cf5,
+ 0xfbc5, 0x3d69,
+ 0xfbc6, 0x3cfe,
+ 0xfbc7, 0x425b,
+ 0xfbc8, 0x3ac8,
+ 0xfbc9, 0x3dc0,
+ 0xfbca, 0x39ea,
+ 0xfbcb, 0x4000,
+ 0xfbcc, 0x4264,
+ 0xfbcd, 0x4262,
+ 0xfbce, 0x3fff,
+ 0xfbcf, 0x3e9a,
+ 0xfbd0, 0x4273,
+ 0xfbd1, 0x3969,
+ 0xfbd2, 0x427a,
+ 0xfbd3, 0x4283,
+ 0xfbd4, 0x43c9,
+ 0xfbd6, 0x3f9a,
+ 0xfbd7, 0x3eb5,
+ 0xfbd8, 0x43cb,
+ 0xfbda, 0x3fb2,
+ 0xfbdb, 0x428a,
+ 0xfbdd, 0x3b17,
+ 0xfbde, 0x428c,
+ 0xfbdf, 0x4290,
+ 0xfbe0, 0x3adf,
+ 0xfbe1, 0x43cd,
+ 0xfbe2, 0x42c5,
+ 0xfbe3, 0x42c8,
+ 0xfbe4, 0x3ead,
+ 0xfbe5, 0x43ce,
+ 0xfbe6, 0x3f8f,
+ 0xfbe7, 0x43cf,
+ 0xfbe8, 0x3e72,
+ 0xfbe9, 0x3e70,
+ 0xfbea, 0x43d0,
+ 0xfbeb, 0x3eaa,
+ 0xfbec, 0x43d1,
+ 0xfbed, 0x3fa9,
+ 0xfbee, 0x43d2,
+ 0xfbf1, 0x42d8,
+ 0xfbf2, 0x3ff3,
+ 0xfbf3, 0x42e0,
+ 0xfbf4, 0x3b00,
+ 0xfbf5, 0x4317,
+ 0xfbf6, 0x382d,
+ 0xfbf7, 0x3e73,
+ 0xfbf8, 0x3fd5,
+ 0xfbf9, 0x43d5,
+ 0xfbfb, 0x3b14,
+ 0xfbfc, 0x36e8,
+ 0xfbfd, 0x42f4,
+ 0xfbfe, 0x3b0e,
+ 0xfc40, 0x42ec,
+ 0xfc41, 0x42f0,
+ 0xfc42, 0x3e7d,
+ 0xfc43, 0x43d7,
+ 0xfc44, 0x42fe,
+ 0xfc45, 0x4305,
+ 0xfc46, 0x3fda,
+ 0xfc47, 0x3df1,
+ 0xfc48, 0x3733,
+ 0xfc49, 0x3d7d,
+ 0xfc4a, 0x43d8,
+ 0xfc4b, 0x373a,
+ 0xfc4c, 0x3740,
+ 0xfc4d, 0x3742,
+ 0xfc4e, 0x3746,
+ 0xfc4f, 0x3752,
+ 0xfc50, 0x3f1f,
+ 0xfc51, 0x43d9,
+ 0xfc52, 0x36ed,
+ 0xfc53, 0x3b4a,
+ 0xfc54, 0x375e,
+ 0xfc55, 0x3b45,
+ 0xfc56, 0x43da,
+ 0xfc57, 0x3ede,
+ 0xfc58, 0x3769,
+ 0xfc59, 0x376c,
+ 0xfc5a, 0x376b,
+ 0xfc5b, 0x376e,
+ 0xfc5c, 0x377f,
+ 0xfc5d, 0x377b,
+ 0xfc5e, 0x3782,
+ 0xfc5f, 0x3e69,
+ 0xfc60, 0x3b4f,
+ 0xfc61, 0x3786,
+ 0xfc62, 0x43db,
+ 0xfc63, 0x3788,
+ 0xfc64, 0x43dc,
+ 0xfc65, 0x3ecd,
+ 0xfc66, 0x3797,
+ 0xfc67, 0x420d,
+ 0xfc68, 0x43dd,
+ 0xfc69, 0x37bc,
+ 0xfc6a, 0x43de,
+ 0xfc6b, 0x37d8,
+ 0xfc6c, 0x3b71,
+ 0xfc6d, 0x3e7a,
+ 0xfc6e, 0x43df,
+ 0xfc6f, 0x38dc,
+ 0xfc70, 0x37e0,
+ 0xfc71, 0x37ee,
+ 0xfc72, 0x37f4,
+ 0xfc73, 0x3813,
+ 0xfc74, 0x43e0,
+ 0xfc76, 0x3eb0,
+ 0xfc77, 0x43e2,
+ 0xfc78, 0x3fed,
+ 0xfc79, 0x380d,
+ 0xfc7a, 0x3eaf,
+ 0xfc7b, 0x3f92,
+ 0xfc7c, 0x3816,
+ 0xfc7d, 0x381b,
+ 0xfc7e, 0x3fa2,
+ 0xfca1, 0x381c,
+ 0xfca2, 0x381e,
+ 0xfca4, 0x3eb1,
+ 0xfca5, 0x134a,
+ 0xfca6, 0x43e3,
+ 0xfca7, 0x3fe9,
+ 0xfca8, 0x43e4,
+ 0xfca9, 0x3ff9,
+ 0xfcaa, 0x3d93,
+ 0xfcab, 0x43e5,
+ 0xfcac, 0x3e59,
+ 0xfcad, 0x43e6,
+ 0xfcae, 0x3837,
+ 0xfcaf, 0x3f99,
+ 0xfcb0, 0x3e99,
+ 0xfcb1, 0x3e5e,
+ 0xfcb2, 0x3bb4,
+ 0xfcb3, 0x3eab,
+ 0xfcb4, 0x43e7,
+ 0xfcb6, 0x385e,
+ 0xfcb7, 0x43e9,
+ 0xfcb8, 0x3dbe,
+ 0xfcb9, 0x3e85,
+ 0xfcba, 0x3863,
+ 0xfcbc, 0x3d6c,
+ 0xfcbd, 0x3871,
+ 0xfcbe, 0x3ee0,
+ 0xfcbf, 0x43ea,
+ 0xfcc0, 0x387c,
+ 0xfcc1, 0x43eb,
+ 0xfcc2, 0x3eb8,
+ 0xfcc3, 0x3882,
+ 0xfcc4, 0x3e9b,
+ 0xfcc5, 0x43ec,
+ 0xfcc6, 0x3888,
+ 0xfcc7, 0x3c0e,
+ 0xfcc8, 0x382e,
+ 0xfcc9, 0x389a,
+ 0xfcca, 0x388b,
+ 0xfccb, 0x3c04,
+ 0xfccc, 0x36e9,
+ 0xfccd, 0x42bd,
+ 0xfcce, 0x3bcd,
+ 0xfccf, 0x389f,
+ 0xfcd0, 0x3dde,
+ 0xfcd1, 0x379b,
+ 0xfcd2, 0x3bd3,
+ 0xfcd3, 0x38af,
+ 0xfcd4, 0x3e97,
+ 0xfcd5, 0x38d6,
+ 0xfcd6, 0x3f35,
+ 0xfcd7, 0x38e0,
+ 0xfcd8, 0x4035,
+ 0xfcd9, 0x38f0,
+ 0xfcda, 0x43ed,
+ 0xfcdc, 0x3bfd,
+ 0xfcdd, 0x3c11,
+ 0xfcdf, 0x43ef,
+ 0xfce0, 0x3785,
+ 0xfce1, 0x3902,
+ 0xfce2, 0x3ddc,
+ 0xfce3, 0x43f0,
+ 0xfce4, 0x3faa,
+ 0xfce5, 0x390b,
+ 0xfce6, 0x3f19,
+ 0xfce7, 0x390e,
+ 0xfce8, 0x3919,
+ 0xfce9, 0x43f1,
+ 0xfcea, 0x3c3c,
+ 0xfceb, 0x391a,
+ 0xfcec, 0x3c3a,
+ 0xfced, 0x391b,
+ 0xfcee, 0x3e66,
+ 0xfcef, 0x3f22,
+ 0xfcf0, 0x3d7e,
+ 0xfcf1, 0x3e71,
+ 0xfcf2, 0x3c39,
+ 0xfcf3, 0x3ea1,
+ 0xfcf4, 0x43f2,
+ 0xfcf6, 0x3f30,
+ 0xfcf7, 0x3929,
+ 0xfcf8, 0x3fbc,
+ 0xfcf9, 0x3936,
+ 0xfcfa, 0x43f4,
+ 0xfcfb, 0x3937,
+ 0xfcfc, 0x3f90,
+ 0xfcfd, 0x43f5,
+ 0xfcfe, 0x0aba,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKm471B5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKm471B5VMap2, 702
+};
+
+static Gushort cns13HKscsB5HMap2[2258] = {
+ 0x0000, 0x0000,
+ 0x8840, 0x44c9,
+ 0x8856, 0x4961,
+ 0x88a1, 0x498a,
+ 0x88a9, 0x499c,
+ 0x8940, 0x4534,
+ 0x8943, 0x4536,
+ 0x8946, 0x4537,
+ 0x894c, 0x453b,
+ 0x894d, 0x43c3,
+ 0x894e, 0x453c,
+ 0x8951, 0x439a,
+ 0x8952, 0x453f,
+ 0x89a1, 0x456c,
+ 0x89a6, 0x43a2,
+ 0x89ab, 0x43ec,
+ 0x89ac, 0x4571,
+ 0x89ad, 0x43eb,
+ 0x89ae, 0x4572,
+ 0x89b0, 0x4573,
+ 0x89b5, 0x4576,
+ 0x89c1, 0x4581,
+ 0x89c5, 0x4584,
+ 0x89cf, 0x43bc,
+ 0x89d0, 0x458e,
+ 0x89d9, 0x439c,
+ 0x89da, 0x4597,
+ 0x89db, 0x439e,
+ 0x89dc, 0x4598,
+ 0x89dd, 0x439f,
+ 0x89de, 0x4599,
+ 0x89e1, 0x43a1,
+ 0x89e2, 0x459c,
+ 0x89e3, 0x43a3,
+ 0x89e4, 0x459d,
+ 0x89ea, 0x43a5,
+ 0x89ec, 0x45a3,
+ 0x89fa, 0x43a9,
+ 0x89fb, 0x45b1,
+ 0x8a40, 0x45b5,
+ 0x8a41, 0x4309,
+ 0x8a43, 0x430b,
+ 0x8a4d, 0x45b6,
+ 0x8a4e, 0x4316,
+ 0x8a5a, 0x45b7,
+ 0x8a5b, 0x4323,
+ 0x8a5e, 0x45b8,
+ 0x8a5f, 0x4327,
+ 0x8a64, 0x432c,
+ 0x8a71, 0x45b9,
+ 0x8a72, 0x433a,
+ 0x8a76, 0x433e,
+ 0x8a77, 0x45ba,
+ 0x8a78, 0x4340,
+ 0x8a7a, 0x45bb,
+ 0x8a7b, 0x4343,
+ 0x8a7c, 0x45bc,
+ 0x8a7d, 0x4345,
+ 0x8a7e, 0x45bd,
+ 0x8aa1, 0x4347,
+ 0x8aa8, 0x45be,
+ 0x8aa9, 0x434f,
+ 0x8aac, 0x4352,
+ 0x8ab2, 0x4358,
+ 0x8ab6, 0x45bf,
+ 0x8ab7, 0x435d,
+ 0x8ab8, 0x45c0,
+ 0x8ab9, 0x435f,
+ 0x8abb, 0x4361,
+ 0x8ac9, 0x436f,
+ 0x8acc, 0x45c1,
+ 0x8ace, 0x4374,
+ 0x8ad6, 0x45c2,
+ 0x8ad8, 0x437e,
+ 0x8adf, 0x4385,
+ 0x8ae6, 0x45c4,
+ 0x8ae7, 0x43db,
+ 0x8ae8, 0x45c5,
+ 0x8af6, 0x45d2,
+ 0x8b40, 0x45db,
+ 0x8b41, 0x438c,
+ 0x8b43, 0x45dc,
+ 0x8b45, 0x438e,
+ 0x8b46, 0x45de,
+ 0x8b47, 0x438f,
+ 0x8b48, 0x45df,
+ 0x8b49, 0x4390,
+ 0x8b4a, 0x45e0,
+ 0x8b4b, 0x4391,
+ 0x8b4c, 0x45e1,
+ 0x8b4d, 0x4392,
+ 0x8b51, 0x45e2,
+ 0x8b55, 0x45e5,
+ 0x8b58, 0x4397,
+ 0x8b59, 0x45e8,
+ 0x8b5a, 0x4398,
+ 0x8b5b, 0x43c4,
+ 0x8b5c, 0x45e9,
+ 0x8b61, 0x43a7,
+ 0x8b62, 0x45ee,
+ 0x8b68, 0x43ac,
+ 0x8b69, 0x45f4,
+ 0x8ba1, 0x460a,
+ 0x8bc0, 0x44df,
+ 0x8bde, 0x44fc,
+ 0x8d60, 0x4629,
+ 0x8d62, 0x43ba,
+ 0x8d63, 0x462b,
+ 0x8d68, 0x43bb,
+ 0x8d69, 0x43a0,
+ 0x8d6a, 0x43bd,
+ 0x8d6b, 0x4630,
+ 0x8d6e, 0x43be,
+ 0x8d6f, 0x4633,
+ 0x8d76, 0x43bf,
+ 0x8d77, 0x463a,
+ 0x8d7a, 0x43c0,
+ 0x8d7b, 0x463d,
+ 0x8d7c, 0x43c1,
+ 0x8d7d, 0x463e,
+ 0x8da1, 0x4640,
+ 0x8da5, 0x43c2,
+ 0x8da6, 0x4644,
+ 0x8da8, 0x43b9,
+ 0x8da9, 0x43ad,
+ 0x8daa, 0x4646,
+ 0x8db6, 0x43c7,
+ 0x8db7, 0x4652,
+ 0x8dc3, 0x43c8,
+ 0x8dc4, 0x465e,
+ 0x8dfa, 0x43f9,
+ 0x8dfb, 0x4694,
+ 0x8e40, 0x372b,
+ 0x8e45, 0x4698,
+ 0x8e46, 0x3730,
+ 0x8e6a, 0x3754,
+ 0x8e6b, 0x4699,
+ 0x8e6d, 0x3756,
+ 0x8e70, 0x3759,
+ 0x8e76, 0x469b,
+ 0x8e77, 0x375f,
+ 0x8e7b, 0x469c,
+ 0x8e7c, 0x3764,
+ 0x8ea1, 0x3766,
+ 0x8ea6, 0x469d,
+ 0x8ea7, 0x376b,
+ 0x8eac, 0x3770,
+ 0x8eb5, 0x3779,
+ 0x8eb8, 0x469e,
+ 0x8eb9, 0x377d,
+ 0x8ec9, 0x469f,
+ 0x8eca, 0x378d,
+ 0x8ece, 0x3791,
+ 0x8ed1, 0x3794,
+ 0x8ee5, 0x46a0,
+ 0x8ee6, 0x37a8,
+ 0x8eef, 0x46a1,
+ 0x8ef0, 0x37b1,
+ 0x8ef6, 0x46a2,
+ 0x8ef7, 0x37b8,
+ 0x8f40, 0x37c0,
+ 0x8f58, 0x37d8,
+ 0x8f59, 0x46a3,
+ 0x8f5a, 0x37d9,
+ 0x8f5f, 0x46a4,
+ 0x8f60, 0x37de,
+ 0x8f67, 0x46a5,
+ 0x8f68, 0x37e5,
+ 0x8f6a, 0x37e7,
+ 0x8f6f, 0x37ec,
+ 0x8f79, 0x46a6,
+ 0x8f7a, 0x37f7,
+ 0x8fa1, 0x37fc,
+ 0x8fb0, 0x46a7,
+ 0x8fb1, 0x380c,
+ 0x8fc5, 0x46a8,
+ 0x8fc6, 0x3820,
+ 0x8fc7, 0x46a9,
+ 0x8fc8, 0x3821,
+ 0x8fca, 0x46aa,
+ 0x8fcd, 0x3826,
+ 0x8fda, 0x46ab,
+ 0x8fdb, 0x3833,
+ 0x8fe3, 0x46ac,
+ 0x8fe4, 0x383c,
+ 0x8ffc, 0x46ad,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x9055, 0x46ae,
+ 0x9056, 0x386c,
+ 0x905c, 0x46af,
+ 0x905f, 0x3873,
+ 0x906e, 0x3882,
+ 0x906f, 0x46b2,
+ 0x9070, 0x3883,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a6, 0x46b3,
+ 0x90a7, 0x3896,
+ 0x90b8, 0x46b4,
+ 0x90b9, 0x38a7,
+ 0x90dd, 0x38cb,
+ 0x90f2, 0x38e0,
+ 0x9140, 0x38ed,
+ 0x9165, 0x46b5,
+ 0x9166, 0x3912,
+ 0x916e, 0x46b6,
+ 0x916f, 0x391a,
+ 0x917e, 0x46b7,
+ 0x91a1, 0x3929,
+ 0x91a2, 0x46b8,
+ 0x91a3, 0x392a,
+ 0x91c0, 0x3947,
+ 0x91c8, 0x46b9,
+ 0x91c9, 0x3950,
+ 0x9240, 0x3986,
+ 0x9245, 0x398b,
+ 0x9264, 0x46ba,
+ 0x9265, 0x39ab,
+ 0x926d, 0x46bb,
+ 0x926e, 0x39b4,
+ 0x92a1, 0x39c5,
+ 0x92b3, 0x39d3,
+ 0x92c9, 0x39e9,
+ 0x92d2, 0x39f2,
+ 0x92e5, 0x46bc,
+ 0x92e6, 0x3a05,
+ 0x92f2, 0x46bd,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9368, 0x46be,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93aa, 0x46bf,
+ 0x93ab, 0x3a64,
+ 0x93c2, 0x46c0,
+ 0x93c3, 0x3a7b,
+ 0x93e5, 0x46c1,
+ 0x93e6, 0x3a9d,
+ 0x93e8, 0x46c2,
+ 0x93e9, 0x3aa0,
+ 0x93eb, 0x46c3,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9446, 0x46c4,
+ 0x9448, 0x3abc,
+ 0x9479, 0x46c5,
+ 0x947a, 0x3aee,
+ 0x94a1, 0x3af3,
+ 0x94cb, 0x46c6,
+ 0x94cc, 0x3b1e,
+ 0x9540, 0x3b51,
+ 0x954d, 0x46c7,
+ 0x954e, 0x3b5e,
+ 0x955a, 0x46c8,
+ 0x955b, 0x3b6a,
+ 0x955f, 0x46c9,
+ 0x9560, 0x3b6f,
+ 0x95a1, 0x3b8e,
+ 0x95c6, 0x46ca,
+ 0x95c7, 0x3bb3,
+ 0x95da, 0x3bc6,
+ 0x9640, 0x3beb,
+ 0x9645, 0x3bf0,
+ 0x9651, 0x46cb,
+ 0x9652, 0x3bfd,
+ 0x966a, 0x46cc,
+ 0x966b, 0x3c16,
+ 0x96a1, 0x3c2a,
+ 0x96d4, 0x46cd,
+ 0x96d5, 0x3c5d,
+ 0x96ee, 0x3c76,
+ 0x96fd, 0x3c85,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9844, 0x46ce,
+ 0x9846, 0x3d2a,
+ 0x986f, 0x46d0,
+ 0x9870, 0x3d54,
+ 0x9875, 0x46d1,
+ 0x9877, 0x3d59,
+ 0x9878, 0x46d3,
+ 0x987a, 0x3d5a,
+ 0x987b, 0x46d5,
+ 0x98a1, 0x46d9,
+ 0x98a3, 0x3d5b,
+ 0x98a4, 0x46db,
+ 0x98af, 0x3d5c,
+ 0x98b0, 0x46e6,
+ 0x98b4, 0x43ca,
+ 0x98b5, 0x46ea,
+ 0x98b6, 0x3d5d,
+ 0x98b7, 0x46eb,
+ 0x98b8, 0x43cc,
+ 0x98b9, 0x3d5e,
+ 0x98ba, 0x46ec,
+ 0x98bb, 0x43fa,
+ 0x98bc, 0x46ed,
+ 0x98bd, 0x3d5f,
+ 0x98bf, 0x46ee,
+ 0x98c2, 0x3d61,
+ 0x98c3, 0x46f1,
+ 0x98c4, 0x3d62,
+ 0x98c5, 0x46f2,
+ 0x98c6, 0x3d63,
+ 0x98c8, 0x46f3,
+ 0x98d2, 0x43cd,
+ 0x98d3, 0x46fd,
+ 0x98d8, 0x43ce,
+ 0x98da, 0x4702,
+ 0x98db, 0x43d1,
+ 0x98dc, 0x4703,
+ 0x98df, 0x43d4,
+ 0x98e0, 0x4706,
+ 0x98e3, 0x3d65,
+ 0x98e4, 0x4709,
+ 0x98e7, 0x3d66,
+ 0x98e8, 0x470c,
+ 0x98ed, 0x3d67,
+ 0x98ee, 0x4711,
+ 0x98f0, 0x3d68,
+ 0x98f1, 0x4713,
+ 0x98f2, 0x3d69,
+ 0x98f3, 0x4714,
+ 0x98f4, 0x43d5,
+ 0x98f6, 0x4715,
+ 0x98fc, 0x3d6a,
+ 0x98fd, 0x471b,
+ 0x98fe, 0x43d7,
+ 0x9940, 0x471c,
+ 0x9942, 0x43fc,
+ 0x9943, 0x3d6b,
+ 0x9944, 0x471e,
+ 0x9945, 0x3d6c,
+ 0x9946, 0x471f,
+ 0x9947, 0x43d8,
+ 0x9948, 0x4720,
+ 0x994f, 0x3d6d,
+ 0x9950, 0x4727,
+ 0x9954, 0x43d9,
+ 0x9955, 0x472b,
+ 0x995c, 0x43da,
+ 0x995d, 0x4732,
+ 0x9964, 0x43dc,
+ 0x9965, 0x4739,
+ 0x996a, 0x3d6e,
+ 0x996b, 0x473e,
+ 0x996e, 0x3d6f,
+ 0x996f, 0x4741,
+ 0x9975, 0x3d70,
+ 0x9976, 0x4747,
+ 0x9978, 0x3d71,
+ 0x9979, 0x4749,
+ 0x99a1, 0x474f,
+ 0x99a2, 0x3d72,
+ 0x99a3, 0x4750,
+ 0x99a4, 0x43c5,
+ 0x99a5, 0x4751,
+ 0x99a6, 0x43c6,
+ 0x99a7, 0x4752,
+ 0x99ae, 0x3d73,
+ 0x99af, 0x4759,
+ 0x99b2, 0x43de,
+ 0x99b3, 0x475c,
+ 0x99b6, 0x3d74,
+ 0x99b7, 0x475f,
+ 0x99ba, 0x3d75,
+ 0x99bb, 0x4762,
+ 0x99ca, 0x43e0,
+ 0x99cb, 0x4771,
+ 0x99cd, 0x43e2,
+ 0x99ce, 0x4773,
+ 0x99d3, 0x43e3,
+ 0x99d4, 0x4778,
+ 0x99d6, 0x43e5,
+ 0x99d7, 0x477a,
+ 0x99df, 0x43df,
+ 0x99e0, 0x4782,
+ 0x99e2, 0x3d76,
+ 0x99e3, 0x4784,
+ 0x99e4, 0x43ab,
+ 0x99e5, 0x4785,
+ 0x99e6, 0x43e7,
+ 0x99e7, 0x4786,
+ 0x99e8, 0x43e9,
+ 0x99e9, 0x4787,
+ 0x99ef, 0x43fd,
+ 0x99f0, 0x478d,
+ 0x99f4, 0x3d77,
+ 0x99f5, 0x4791,
+ 0x9a40, 0x479b,
+ 0x9a4a, 0x3d78,
+ 0x9a4b, 0x47a5,
+ 0x9a4c, 0x3d79,
+ 0x9a4d, 0x47a6,
+ 0x9a59, 0x3d7a,
+ 0x9a5a, 0x47b2,
+ 0x9a5f, 0x43af,
+ 0x9a60, 0x47b7,
+ 0x9a61, 0x3d7b,
+ 0x9a62, 0x47b8,
+ 0x9a66, 0x43ed,
+ 0x9a67, 0x47bc,
+ 0x9a68, 0x3d7c,
+ 0x9a69, 0x43ee,
+ 0x9a6a, 0x47bd,
+ 0x9a6b, 0x43ff,
+ 0x9a6c, 0x47be,
+ 0x9a73, 0x3d7d,
+ 0x9a74, 0x47c5,
+ 0x9a75, 0x43f1,
+ 0x9a76, 0x47c6,
+ 0x9a7e, 0x3d7e,
+ 0x9aa1, 0x47ce,
+ 0x9aa3, 0x43f3,
+ 0x9aa4, 0x47d0,
+ 0x9aa5, 0x43f2,
+ 0x9aa6, 0x47d1,
+ 0x9aa9, 0x43f8,
+ 0x9aaa, 0x43f4,
+ 0x9aab, 0x47d4,
+ 0x9ab2, 0x3d7f,
+ 0x9ab3, 0x47db,
+ 0x9ab7, 0x3d80,
+ 0x9ab8, 0x47df,
+ 0x9ab9, 0x3d81,
+ 0x9aba, 0x47e0,
+ 0x9abb, 0x3d82,
+ 0x9abc, 0x47e1,
+ 0x9abd, 0x43b7,
+ 0x9abe, 0x47e2,
+ 0x9ac7, 0x3d83,
+ 0x9ac8, 0x47eb,
+ 0x9ad0, 0x3d84,
+ 0x9ad1, 0x47f3,
+ 0x9ad2, 0x3d85,
+ 0x9ad3, 0x47f4,
+ 0x9ad9, 0x3d86,
+ 0x9adc, 0x47fa,
+ 0x9ae2, 0x3d89,
+ 0x9ae3, 0x4800,
+ 0x9ae4, 0x3d8a,
+ 0x9ae5, 0x4801,
+ 0x9ae8, 0x3d8b,
+ 0x9ae9, 0x43b0,
+ 0x9aea, 0x4804,
+ 0x9aee, 0x43b2,
+ 0x9aef, 0x4808,
+ 0x9af2, 0x3d8c,
+ 0x9af3, 0x480b,
+ 0x9af6, 0x3d8d,
+ 0x9af7, 0x480e,
+ 0x9afb, 0x3d8e,
+ 0x9afc, 0x4812,
+ 0x9b40, 0x4815,
+ 0x9b46, 0x3d8f,
+ 0x9b47, 0x481b,
+ 0x9b4a, 0x3d90,
+ 0x9b4b, 0x481e,
+ 0x9b54, 0x3d92,
+ 0x9b55, 0x4827,
+ 0x9b58, 0x3d93,
+ 0x9b59, 0x482a,
+ 0x9b5a, 0x3d94,
+ 0x9b5b, 0x482b,
+ 0x9b5c, 0x3d95,
+ 0x9b5d, 0x482c,
+ 0x9b5e, 0x3d96,
+ 0x9b60, 0x482d,
+ 0x9b62, 0x482e,
+ 0x9b70, 0x3d98,
+ 0x9b74, 0x483c,
+ 0x9b77, 0x3d9d,
+ 0x9b79, 0x483e,
+ 0x9b7c, 0x3da0,
+ 0x9b7d, 0x4840,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba2, 0x4841,
+ 0x9ba3, 0x3da3,
+ 0x9ba5, 0x4842,
+ 0x9ba7, 0x3da5,
+ 0x9bab, 0x4844,
+ 0x9bac, 0x3da9,
+ 0x9bad, 0x4845,
+ 0x9baf, 0x3daa,
+ 0x9bb0, 0x4847,
+ 0x9bb2, 0x3dab,
+ 0x9bba, 0x4849,
+ 0x9bbe, 0x3db3,
+ 0x9bbf, 0x484d,
+ 0x9bc0, 0x3db4,
+ 0x9bc7, 0x484e,
+ 0x9bca, 0x3dbb,
+ 0x9bcb, 0x4851,
+ 0x9bcc, 0x3dbc,
+ 0x9bcd, 0x4852,
+ 0x9bce, 0x43d0,
+ 0x9bcf, 0x4853,
+ 0x9bd0, 0x3dbd,
+ 0x9bd2, 0x4854,
+ 0x9bd3, 0x3dbf,
+ 0x9bd4, 0x4855,
+ 0x9bd5, 0x3dc0,
+ 0x9bd6, 0x4856,
+ 0x9bd8, 0x3dc1,
+ 0x9bdb, 0x4858,
+ 0x9bdd, 0x3dc4,
+ 0x9bdf, 0x3dc5,
+ 0x9be0, 0x485a,
+ 0x9be1, 0x3dc6,
+ 0x9be2, 0x485b,
+ 0x9be3, 0x3dc7,
+ 0x9be4, 0x485c,
+ 0x9be7, 0x3dc8,
+ 0x9be8, 0x485f,
+ 0x9be9, 0x3dc9,
+ 0x9bed, 0x4860,
+ 0x9bee, 0x3dcd,
+ 0x9bf0, 0x4861,
+ 0x9bf3, 0x3dcf,
+ 0x9bf4, 0x4864,
+ 0x9bf7, 0x4866,
+ 0x9bf8, 0x3dd1,
+ 0x9bfa, 0x4867,
+ 0x9bfb, 0x3dd3,
+ 0x9bfd, 0x4868,
+ 0x9c40, 0x3dd5,
+ 0x9c43, 0x486a,
+ 0x9c44, 0x3dd8,
+ 0x9c47, 0x486b,
+ 0x9c48, 0x3ddb,
+ 0x9c49, 0x486c,
+ 0x9c4a, 0x3ddc,
+ 0x9c4b, 0x486d,
+ 0x9c4d, 0x3ddd,
+ 0x9c54, 0x486f,
+ 0x9c55, 0x3de4,
+ 0x9c56, 0x4870,
+ 0x9c57, 0x3de5,
+ 0x9c5c, 0x4871,
+ 0x9c5d, 0x3dea,
+ 0x9c5e, 0x4872,
+ 0x9c60, 0x3deb,
+ 0x9c61, 0x4874,
+ 0x9c63, 0x4875,
+ 0x9c64, 0x3ded,
+ 0x9c67, 0x4876,
+ 0x9c69, 0x4877,
+ 0x9c6a, 0x3df1,
+ 0x9c6c, 0x4878,
+ 0x9c6d, 0x3df2,
+ 0x9c6e, 0x4879,
+ 0x9c6f, 0x3df3,
+ 0x9c73, 0x487a,
+ 0x9c75, 0x3df7,
+ 0x9c78, 0x487c,
+ 0x9c79, 0x3dfa,
+ 0x9c7a, 0x487d,
+ 0x9c7b, 0x3dfb,
+ 0x9c7d, 0x487e,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca3, 0x487f,
+ 0x9ca5, 0x3e00,
+ 0x9ca6, 0x4881,
+ 0x9ca8, 0x3e01,
+ 0x9caa, 0x4883,
+ 0x9cab, 0x3e03,
+ 0x9cac, 0x4884,
+ 0x9cad, 0x3e04,
+ 0x9caf, 0x4885,
+ 0x9cb1, 0x3e06,
+ 0x9cbb, 0x4887,
+ 0x9cbe, 0x3e12,
+ 0x9cc3, 0x4888,
+ 0x9cc6, 0x3e17,
+ 0x9cce, 0x488b,
+ 0x9ccf, 0x3e1f,
+ 0x9cd1, 0x3e21,
+ 0x9cd4, 0x488c,
+ 0x9cd8, 0x3e24,
+ 0x9cdb, 0x4890,
+ 0x9cdc, 0x3e27,
+ 0x9ce6, 0x4891,
+ 0x9ce7, 0x3e31,
+ 0x9cea, 0x4892,
+ 0x9ceb, 0x3e34,
+ 0x9ced, 0x4893,
+ 0x9cee, 0x3e36,
+ 0x9cfa, 0x4894,
+ 0x9cfd, 0x3e42,
+ 0x9cfe, 0x4897,
+ 0x9d40, 0x43e8,
+ 0x9d41, 0x4898,
+ 0x9d46, 0x3e43,
+ 0x9d47, 0x489d,
+ 0x9d49, 0x3e44,
+ 0x9d4a, 0x489f,
+ 0x9d4c, 0x3e46,
+ 0x9d4e, 0x48a1,
+ 0x9d4f, 0x3e48,
+ 0x9d50, 0x48a2,
+ 0x9d51, 0x3e49,
+ 0x9d52, 0x48a3,
+ 0x9d55, 0x3e4a,
+ 0x9d56, 0x48a6,
+ 0x9d58, 0x48a7,
+ 0x9d5b, 0x48a9,
+ 0x9d61, 0x43c9,
+ 0x9d62, 0x3e4c,
+ 0x9d63, 0x48af,
+ 0x9d64, 0x3e4d,
+ 0x9d65, 0x48b0,
+ 0x9d78, 0x43f5,
+ 0x9d79, 0x3e4e,
+ 0x9d7a, 0x48c3,
+ 0x9d7e, 0x3e4f,
+ 0x9da1, 0x48c7,
+ 0x9da5, 0x3e50,
+ 0x9da9, 0x48cb,
+ 0x9daa, 0x3e54,
+ 0x9dab, 0x48cc,
+ 0x9dac, 0x3e55,
+ 0x9dae, 0x48cd,
+ 0x9db0, 0x3e58,
+ 0x9db1, 0x48cf,
+ 0x9db3, 0x3e59,
+ 0x9db4, 0x48d1,
+ 0x9db5, 0x3e5a,
+ 0x9db6, 0x48d2,
+ 0x9db7, 0x3e5b,
+ 0x9db8, 0x48d3,
+ 0x9dbc, 0x3e5c,
+ 0x9dbe, 0x48d7,
+ 0x9dbf, 0x3e5e,
+ 0x9dc1, 0x48d8,
+ 0x9dc3, 0x3e60,
+ 0x9dc5, 0x48da,
+ 0x9dc7, 0x3e62,
+ 0x9dc9, 0x48dc,
+ 0x9dca, 0x3e64,
+ 0x9dcb, 0x48dd,
+ 0x9dcd, 0x3e65,
+ 0x9dd2, 0x48df,
+ 0x9dd3, 0x3e6a,
+ 0x9dd6, 0x48e0,
+ 0x9dda, 0x3e6d,
+ 0x9dfc, 0x48e4,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e43, 0x48e5,
+ 0x9e44, 0x3e95,
+ 0x9e5f, 0x48e6,
+ 0x9e60, 0x3eb1,
+ 0x9e63, 0x48e7,
+ 0x9e64, 0x3eb4,
+ 0x9e66, 0x48e8,
+ 0x9e68, 0x3eb6,
+ 0x9e69, 0x48ea,
+ 0x9e6a, 0x3eb7,
+ 0x9e6b, 0x48eb,
+ 0x9e71, 0x3eb8,
+ 0x9e72, 0x48f1,
+ 0x9e73, 0x3eb9,
+ 0x9e74, 0x48f2,
+ 0x9e77, 0x3eba,
+ 0x9e79, 0x48f5,
+ 0x9e7a, 0x3ebc,
+ 0x9e7b, 0x48f6,
+ 0x9e7c, 0x3ebd,
+ 0x9e7d, 0x48f7,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea3, 0x48f8,
+ 0x9ea4, 0x3ec1,
+ 0x9ea7, 0x48f9,
+ 0x9eaa, 0x3ec5,
+ 0x9eab, 0x48fb,
+ 0x9ead, 0x3ec7,
+ 0x9eae, 0x48fc,
+ 0x9eaf, 0x3ec8,
+ 0x9eb2, 0x48fd,
+ 0x9eb4, 0x3ecb,
+ 0x9eb5, 0x48ff,
+ 0x9eb6, 0x3ecc,
+ 0x9eb8, 0x4900,
+ 0x9eb9, 0x3ece,
+ 0x9eba, 0x4901,
+ 0x9ebc, 0x3ecf,
+ 0x9ebd, 0x4903,
+ 0x9ebf, 0x3ed0,
+ 0x9ec1, 0x4905,
+ 0x9ec5, 0x3ed3,
+ 0x9ec6, 0x4908,
+ 0x9ec7, 0x3ed4,
+ 0x9ecb, 0x4909,
+ 0x9ecd, 0x3ed9,
+ 0x9ece, 0x490b,
+ 0x9ed0, 0x3eda,
+ 0x9ed2, 0x490d,
+ 0x9ed3, 0x3edc,
+ 0x9ed4, 0x490e,
+ 0x9ed6, 0x3edd,
+ 0x9ed8, 0x4910,
+ 0x9eda, 0x3edf,
+ 0x9ef0, 0x3ef5,
+ 0x9ef2, 0x4912,
+ 0x9ef3, 0x3ef7,
+ 0x9ef5, 0x3ef9,
+ 0x9ef6, 0x4913,
+ 0x9ef9, 0x3efa,
+ 0x9efb, 0x4916,
+ 0x9efc, 0x3efc,
+ 0x9efe, 0x3efe,
+ 0x9f40, 0x3eff,
+ 0x9f43, 0x4917,
+ 0x9f44, 0x3f02,
+ 0x9f48, 0x4918,
+ 0x9f49, 0x3f06,
+ 0x9f4b, 0x4919,
+ 0x9f4d, 0x3f08,
+ 0x9f4f, 0x3f0a,
+ 0x9f61, 0x3f1c,
+ 0x9f67, 0x491b,
+ 0x9f69, 0x3f23,
+ 0x9f70, 0x491d,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fae, 0x3f45,
+ 0x9fb2, 0x3f49,
+ 0x9fb5, 0x491e,
+ 0x9fb6, 0x3f4c,
+ 0x9fbb, 0x491f,
+ 0x9fbc, 0x3f51,
+ 0x9fbf, 0x4920,
+ 0x9fc1, 0x4921,
+ 0x9fc2, 0x3f55,
+ 0x9fc9, 0x3f5c,
+ 0x9fcc, 0x4922,
+ 0x9fcd, 0x3f60,
+ 0x9fd4, 0x4923,
+ 0x9fd5, 0x3f68,
+ 0x9fd9, 0x3f6c,
+ 0x9fdb, 0x3f6e,
+ 0x9fe4, 0x4924,
+ 0x9fe5, 0x3f77,
+ 0x9fe7, 0x3f79,
+ 0x9feb, 0x3f7d,
+ 0x9ff0, 0x3f82,
+ 0x9ff9, 0x4925,
+ 0x9ffa, 0x3f8b,
+ 0xa040, 0x4926,
+ 0xa041, 0x3f90,
+ 0xa047, 0x4927,
+ 0xa048, 0x3f96,
+ 0xa055, 0x4928,
+ 0xa056, 0x3fa3,
+ 0xa058, 0x3fa5,
+ 0xa05b, 0x3fa8,
+ 0xa064, 0x3fb1,
+ 0xa06d, 0x4929,
+ 0xa06e, 0x3fba,
+ 0xa073, 0x3fbf,
+ 0xa078, 0x3fc4,
+ 0xa07b, 0x492a,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a2, 0x492b,
+ 0xa0a3, 0x3fcb,
+ 0xa0a6, 0x3fce,
+ 0xa0a7, 0x492c,
+ 0xa0a8, 0x3fcf,
+ 0xa0ae, 0x3fd5,
+ 0xa0b0, 0x3fd7,
+ 0xa0c5, 0x492d,
+ 0xa0c6, 0x3fec,
+ 0xa0d0, 0x492e,
+ 0xa0d1, 0x3ff6,
+ 0xa0d4, 0x3ff9,
+ 0xa0d6, 0x3ffb,
+ 0xa0e0, 0x4005,
+ 0xa0e2, 0x4007,
+ 0xa0e3, 0x492f,
+ 0xa0e5, 0x4009,
+ 0xa0e7, 0x4930,
+ 0xa0ee, 0x43b4,
+ 0xa0ef, 0x4937,
+ 0xa0f2, 0x43b8,
+ 0xa0f3, 0x493a,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d0, 0x022a,
+ 0xc6d4, 0x022e,
+ 0xc6d6, 0x0230,
+ 0xc6d8, 0x35b3,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc8cd, 0x36e1,
+ 0xc8d4, 0x44c6,
+ 0xc8d7, 0x451c,
+ 0xc8e0, 0x02dc,
+ 0xc8e1, 0x4525,
+ 0xc8e9, 0x0509,
+ 0xc8ea, 0x452d,
+ 0xc8f1, 0x09f6,
+ 0xc8f5, 0x4992,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xfa40, 0x400b,
+ 0xfa60, 0x402b,
+ 0xfa67, 0x4032,
+ 0xfaa1, 0x404a,
+ 0xfaa9, 0x4946,
+ 0xfaab, 0x4054,
+ 0xfabe, 0x4067,
+ 0xfac6, 0x406f,
+ 0xfad6, 0x407f,
+ 0xfb40, 0x40a8,
+ 0xfb49, 0x40b1,
+ 0xfb53, 0x4948,
+ 0xfb54, 0x40bc,
+ 0xfb6e, 0x4949,
+ 0xfb6f, 0x40d7,
+ 0xfba1, 0x40e7,
+ 0xfba3, 0x494a,
+ 0xfba4, 0x40ea,
+ 0xfbb9, 0x40ff,
+ 0xfbbf, 0x494b,
+ 0xfbc0, 0x4105,
+ 0xfbcd, 0x494c,
+ 0xfbce, 0x4112,
+ 0xfbf4, 0x4138,
+ 0xfbfa, 0x413e,
+ 0xfc40, 0x4143,
+ 0xfc4a, 0x494d,
+ 0xfc4b, 0x414d,
+ 0xfc50, 0x4151,
+ 0xfc52, 0x494e,
+ 0xfc53, 0x4153,
+ 0xfc63, 0x494f,
+ 0xfc64, 0x4163,
+ 0xfc6d, 0x4950,
+ 0xfc6e, 0x416d,
+ 0xfc75, 0x4951,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcba, 0x4195,
+ 0xfcbc, 0x4952,
+ 0xfcbe, 0x4198,
+ 0xfccc, 0x4954,
+ 0xfccd, 0x41a7,
+ 0xfce3, 0x4955,
+ 0xfce4, 0x41bd,
+ 0xfcee, 0x4956,
+ 0xfcef, 0x41c7,
+ 0xfcf2, 0x41ca,
+ 0xfd40, 0x41d7,
+ 0xfd49, 0x4957,
+ 0xfd4a, 0x41e0,
+ 0xfd6a, 0x4958,
+ 0xfd6b, 0x4201,
+ 0xfda1, 0x4215,
+ 0xfdb9, 0x422d,
+ 0xfdbc, 0x4230,
+ 0xfde3, 0x4959,
+ 0xfde4, 0x4258,
+ 0xfdf2, 0x495a,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe53, 0x4285,
+ 0xfe6d, 0x495b,
+ 0xfe6e, 0x429f,
+ 0xfe70, 0x42a1,
+ 0xfe78, 0x495c,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeab, 0x42b8,
+ 0xfede, 0x495d,
+ 0xfee0, 0x42eb,
+ 0xfeed, 0x495f,
+ 0xfeef, 0x42f8,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKscsB5HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKscsB5HMap2, 1129
+};
+
+static Gushort cns13HKscsB5VMap2[2284] = {
+ 0x0000, 0x0000,
+ 0x8840, 0x44c9,
+ 0x8856, 0x4961,
+ 0x88a1, 0x498a,
+ 0x88a9, 0x499c,
+ 0x8940, 0x4534,
+ 0x8943, 0x4536,
+ 0x8946, 0x4537,
+ 0x894c, 0x453b,
+ 0x894d, 0x43c3,
+ 0x894e, 0x453c,
+ 0x8951, 0x439a,
+ 0x8952, 0x453f,
+ 0x89a1, 0x456c,
+ 0x89a6, 0x43a2,
+ 0x89ab, 0x43ec,
+ 0x89ac, 0x4571,
+ 0x89ad, 0x43eb,
+ 0x89ae, 0x4572,
+ 0x89b0, 0x4573,
+ 0x89b5, 0x4576,
+ 0x89c1, 0x4581,
+ 0x89c5, 0x4584,
+ 0x89cf, 0x43bc,
+ 0x89d0, 0x458e,
+ 0x89d9, 0x439c,
+ 0x89da, 0x4597,
+ 0x89db, 0x439e,
+ 0x89dc, 0x4598,
+ 0x89dd, 0x439f,
+ 0x89de, 0x4599,
+ 0x89e1, 0x43a1,
+ 0x89e2, 0x459c,
+ 0x89e3, 0x43a3,
+ 0x89e4, 0x459d,
+ 0x89ea, 0x43a5,
+ 0x89ec, 0x45a3,
+ 0x89fa, 0x43a9,
+ 0x89fb, 0x45b1,
+ 0x8a40, 0x45b5,
+ 0x8a41, 0x4309,
+ 0x8a43, 0x430b,
+ 0x8a4d, 0x45b6,
+ 0x8a4e, 0x4316,
+ 0x8a5a, 0x45b7,
+ 0x8a5b, 0x4323,
+ 0x8a5e, 0x45b8,
+ 0x8a5f, 0x4327,
+ 0x8a64, 0x432c,
+ 0x8a71, 0x45b9,
+ 0x8a72, 0x433a,
+ 0x8a76, 0x433e,
+ 0x8a77, 0x45ba,
+ 0x8a78, 0x4340,
+ 0x8a7a, 0x45bb,
+ 0x8a7b, 0x4343,
+ 0x8a7c, 0x45bc,
+ 0x8a7d, 0x4345,
+ 0x8a7e, 0x45bd,
+ 0x8aa1, 0x4347,
+ 0x8aa8, 0x45be,
+ 0x8aa9, 0x434f,
+ 0x8aac, 0x4352,
+ 0x8ab2, 0x4358,
+ 0x8ab6, 0x45bf,
+ 0x8ab7, 0x435d,
+ 0x8ab8, 0x45c0,
+ 0x8ab9, 0x435f,
+ 0x8abb, 0x4361,
+ 0x8ac9, 0x436f,
+ 0x8acc, 0x45c1,
+ 0x8ace, 0x4374,
+ 0x8ad6, 0x45c2,
+ 0x8ad8, 0x437e,
+ 0x8adf, 0x4385,
+ 0x8ae6, 0x45c4,
+ 0x8ae7, 0x43db,
+ 0x8ae8, 0x45c5,
+ 0x8af6, 0x45d2,
+ 0x8b40, 0x45db,
+ 0x8b41, 0x438c,
+ 0x8b43, 0x45dc,
+ 0x8b45, 0x438e,
+ 0x8b46, 0x45de,
+ 0x8b47, 0x438f,
+ 0x8b48, 0x45df,
+ 0x8b49, 0x4390,
+ 0x8b4a, 0x45e0,
+ 0x8b4b, 0x4391,
+ 0x8b4c, 0x45e1,
+ 0x8b4d, 0x4392,
+ 0x8b51, 0x45e2,
+ 0x8b55, 0x45e5,
+ 0x8b58, 0x4397,
+ 0x8b59, 0x45e8,
+ 0x8b5a, 0x4398,
+ 0x8b5b, 0x43c4,
+ 0x8b5c, 0x45e9,
+ 0x8b61, 0x43a7,
+ 0x8b62, 0x45ee,
+ 0x8b68, 0x43ac,
+ 0x8b69, 0x45f4,
+ 0x8ba1, 0x460a,
+ 0x8bc0, 0x44df,
+ 0x8bde, 0x44fc,
+ 0x8d60, 0x4629,
+ 0x8d62, 0x43ba,
+ 0x8d63, 0x462b,
+ 0x8d68, 0x43bb,
+ 0x8d69, 0x43a0,
+ 0x8d6a, 0x43bd,
+ 0x8d6b, 0x4630,
+ 0x8d6e, 0x43be,
+ 0x8d6f, 0x4633,
+ 0x8d76, 0x43bf,
+ 0x8d77, 0x463a,
+ 0x8d7a, 0x43c0,
+ 0x8d7b, 0x463d,
+ 0x8d7c, 0x43c1,
+ 0x8d7d, 0x463e,
+ 0x8da1, 0x4640,
+ 0x8da5, 0x43c2,
+ 0x8da6, 0x4644,
+ 0x8da8, 0x43b9,
+ 0x8da9, 0x43ad,
+ 0x8daa, 0x4646,
+ 0x8db6, 0x43c7,
+ 0x8db7, 0x4652,
+ 0x8dc3, 0x43c8,
+ 0x8dc4, 0x465e,
+ 0x8dfa, 0x43f9,
+ 0x8dfb, 0x4694,
+ 0x8e40, 0x372b,
+ 0x8e45, 0x4698,
+ 0x8e46, 0x3730,
+ 0x8e6a, 0x3754,
+ 0x8e6b, 0x4699,
+ 0x8e6d, 0x3756,
+ 0x8e70, 0x3759,
+ 0x8e76, 0x469b,
+ 0x8e77, 0x375f,
+ 0x8e7b, 0x469c,
+ 0x8e7c, 0x3764,
+ 0x8ea1, 0x3766,
+ 0x8ea6, 0x469d,
+ 0x8ea7, 0x376b,
+ 0x8eac, 0x3770,
+ 0x8eb5, 0x3779,
+ 0x8eb8, 0x469e,
+ 0x8eb9, 0x377d,
+ 0x8ec9, 0x469f,
+ 0x8eca, 0x378d,
+ 0x8ece, 0x3791,
+ 0x8ed1, 0x3794,
+ 0x8ee5, 0x46a0,
+ 0x8ee6, 0x37a8,
+ 0x8eef, 0x46a1,
+ 0x8ef0, 0x37b1,
+ 0x8ef6, 0x46a2,
+ 0x8ef7, 0x37b8,
+ 0x8f40, 0x37c0,
+ 0x8f58, 0x37d8,
+ 0x8f59, 0x46a3,
+ 0x8f5a, 0x37d9,
+ 0x8f5f, 0x46a4,
+ 0x8f60, 0x37de,
+ 0x8f67, 0x46a5,
+ 0x8f68, 0x37e5,
+ 0x8f6a, 0x37e7,
+ 0x8f6f, 0x37ec,
+ 0x8f79, 0x46a6,
+ 0x8f7a, 0x37f7,
+ 0x8fa1, 0x37fc,
+ 0x8fb0, 0x46a7,
+ 0x8fb1, 0x380c,
+ 0x8fc5, 0x46a8,
+ 0x8fc6, 0x3820,
+ 0x8fc7, 0x46a9,
+ 0x8fc8, 0x3821,
+ 0x8fca, 0x46aa,
+ 0x8fcd, 0x3826,
+ 0x8fda, 0x46ab,
+ 0x8fdb, 0x3833,
+ 0x8fe3, 0x46ac,
+ 0x8fe4, 0x383c,
+ 0x8ffc, 0x46ad,
+ 0x8ffd, 0x3854,
+ 0x9040, 0x3856,
+ 0x9055, 0x46ae,
+ 0x9056, 0x386c,
+ 0x905c, 0x46af,
+ 0x905f, 0x3873,
+ 0x906e, 0x3882,
+ 0x906f, 0x46b2,
+ 0x9070, 0x3883,
+ 0x907b, 0x388d,
+ 0x90a1, 0x3891,
+ 0x90a6, 0x46b3,
+ 0x90a7, 0x3896,
+ 0x90b8, 0x46b4,
+ 0x90b9, 0x38a7,
+ 0x90dd, 0x38cb,
+ 0x90f2, 0x38e0,
+ 0x9140, 0x38ed,
+ 0x9165, 0x46b5,
+ 0x9166, 0x3912,
+ 0x916e, 0x46b6,
+ 0x916f, 0x391a,
+ 0x917e, 0x46b7,
+ 0x91a1, 0x3929,
+ 0x91a2, 0x46b8,
+ 0x91a3, 0x392a,
+ 0x91c0, 0x3947,
+ 0x91c8, 0x46b9,
+ 0x91c9, 0x3950,
+ 0x9240, 0x3986,
+ 0x9245, 0x398b,
+ 0x9264, 0x46ba,
+ 0x9265, 0x39ab,
+ 0x926d, 0x46bb,
+ 0x926e, 0x39b4,
+ 0x92a1, 0x39c5,
+ 0x92b3, 0x39d3,
+ 0x92c9, 0x39e9,
+ 0x92d2, 0x39f2,
+ 0x92e5, 0x46bc,
+ 0x92e6, 0x3a05,
+ 0x92f2, 0x46bd,
+ 0x92f3, 0x3a11,
+ 0x9340, 0x3a1d,
+ 0x9368, 0x46be,
+ 0x9369, 0x3a45,
+ 0x93a1, 0x3a5b,
+ 0x93aa, 0x46bf,
+ 0x93ab, 0x3a64,
+ 0x93c2, 0x46c0,
+ 0x93c3, 0x3a7b,
+ 0x93e5, 0x46c1,
+ 0x93e6, 0x3a9d,
+ 0x93e8, 0x46c2,
+ 0x93e9, 0x3aa0,
+ 0x93eb, 0x46c3,
+ 0x93ec, 0x3aa2,
+ 0x9440, 0x3ab5,
+ 0x9446, 0x46c4,
+ 0x9448, 0x3abc,
+ 0x9479, 0x46c5,
+ 0x947a, 0x3aee,
+ 0x94a1, 0x3af3,
+ 0x94cb, 0x46c6,
+ 0x94cc, 0x3b1e,
+ 0x9540, 0x3b51,
+ 0x954d, 0x46c7,
+ 0x954e, 0x3b5e,
+ 0x955a, 0x46c8,
+ 0x955b, 0x3b6a,
+ 0x955f, 0x46c9,
+ 0x9560, 0x3b6f,
+ 0x95a1, 0x3b8e,
+ 0x95c6, 0x46ca,
+ 0x95c7, 0x3bb3,
+ 0x95da, 0x3bc6,
+ 0x9640, 0x3beb,
+ 0x9645, 0x3bf0,
+ 0x9651, 0x46cb,
+ 0x9652, 0x3bfd,
+ 0x966a, 0x46cc,
+ 0x966b, 0x3c16,
+ 0x96a1, 0x3c2a,
+ 0x96d4, 0x46cd,
+ 0x96d5, 0x3c5d,
+ 0x96ee, 0x3c76,
+ 0x96fd, 0x3c85,
+ 0x9740, 0x3c87,
+ 0x97a1, 0x3cc6,
+ 0x9840, 0x3d24,
+ 0x9844, 0x46ce,
+ 0x9846, 0x3d2a,
+ 0x986f, 0x46d0,
+ 0x9870, 0x3d54,
+ 0x9875, 0x46d1,
+ 0x9877, 0x3d59,
+ 0x9878, 0x46d3,
+ 0x987a, 0x3d5a,
+ 0x987b, 0x46d5,
+ 0x98a1, 0x46d9,
+ 0x98a3, 0x3d5b,
+ 0x98a4, 0x46db,
+ 0x98af, 0x3d5c,
+ 0x98b0, 0x46e6,
+ 0x98b4, 0x43ca,
+ 0x98b5, 0x46ea,
+ 0x98b6, 0x3d5d,
+ 0x98b7, 0x46eb,
+ 0x98b8, 0x43cc,
+ 0x98b9, 0x3d5e,
+ 0x98ba, 0x46ec,
+ 0x98bb, 0x43fa,
+ 0x98bc, 0x46ed,
+ 0x98bd, 0x3d5f,
+ 0x98bf, 0x46ee,
+ 0x98c2, 0x3d61,
+ 0x98c3, 0x46f1,
+ 0x98c4, 0x3d62,
+ 0x98c5, 0x46f2,
+ 0x98c6, 0x3d63,
+ 0x98c8, 0x46f3,
+ 0x98d2, 0x43cd,
+ 0x98d3, 0x46fd,
+ 0x98d8, 0x43ce,
+ 0x98da, 0x4702,
+ 0x98db, 0x43d1,
+ 0x98dc, 0x4703,
+ 0x98df, 0x43d4,
+ 0x98e0, 0x4706,
+ 0x98e3, 0x3d65,
+ 0x98e4, 0x4709,
+ 0x98e7, 0x3d66,
+ 0x98e8, 0x470c,
+ 0x98ed, 0x3d67,
+ 0x98ee, 0x4711,
+ 0x98f0, 0x3d68,
+ 0x98f1, 0x4713,
+ 0x98f2, 0x3d69,
+ 0x98f3, 0x4714,
+ 0x98f4, 0x43d5,
+ 0x98f6, 0x4715,
+ 0x98fc, 0x3d6a,
+ 0x98fd, 0x471b,
+ 0x98fe, 0x43d7,
+ 0x9940, 0x471c,
+ 0x9942, 0x43fc,
+ 0x9943, 0x3d6b,
+ 0x9944, 0x471e,
+ 0x9945, 0x3d6c,
+ 0x9946, 0x471f,
+ 0x9947, 0x43d8,
+ 0x9948, 0x4720,
+ 0x994f, 0x3d6d,
+ 0x9950, 0x4727,
+ 0x9954, 0x43d9,
+ 0x9955, 0x472b,
+ 0x995c, 0x43da,
+ 0x995d, 0x4732,
+ 0x9964, 0x43dc,
+ 0x9965, 0x4739,
+ 0x996a, 0x3d6e,
+ 0x996b, 0x473e,
+ 0x996e, 0x3d6f,
+ 0x996f, 0x4741,
+ 0x9975, 0x3d70,
+ 0x9976, 0x4747,
+ 0x9978, 0x3d71,
+ 0x9979, 0x4749,
+ 0x99a1, 0x474f,
+ 0x99a2, 0x3d72,
+ 0x99a3, 0x4750,
+ 0x99a4, 0x43c5,
+ 0x99a5, 0x4751,
+ 0x99a6, 0x43c6,
+ 0x99a7, 0x4752,
+ 0x99ae, 0x3d73,
+ 0x99af, 0x4759,
+ 0x99b2, 0x43de,
+ 0x99b3, 0x475c,
+ 0x99b6, 0x3d74,
+ 0x99b7, 0x475f,
+ 0x99ba, 0x3d75,
+ 0x99bb, 0x4762,
+ 0x99ca, 0x43e0,
+ 0x99cb, 0x4771,
+ 0x99cd, 0x43e2,
+ 0x99ce, 0x4773,
+ 0x99d3, 0x43e3,
+ 0x99d4, 0x4778,
+ 0x99d6, 0x43e5,
+ 0x99d7, 0x477a,
+ 0x99df, 0x43df,
+ 0x99e0, 0x4782,
+ 0x99e2, 0x3d76,
+ 0x99e3, 0x4784,
+ 0x99e4, 0x43ab,
+ 0x99e5, 0x4785,
+ 0x99e6, 0x43e7,
+ 0x99e7, 0x4786,
+ 0x99e8, 0x43e9,
+ 0x99e9, 0x4787,
+ 0x99ef, 0x43fd,
+ 0x99f0, 0x478d,
+ 0x99f4, 0x3d77,
+ 0x99f5, 0x4791,
+ 0x9a40, 0x479b,
+ 0x9a4a, 0x3d78,
+ 0x9a4b, 0x47a5,
+ 0x9a4c, 0x3d79,
+ 0x9a4d, 0x47a6,
+ 0x9a59, 0x3d7a,
+ 0x9a5a, 0x47b2,
+ 0x9a5f, 0x43af,
+ 0x9a60, 0x47b7,
+ 0x9a61, 0x3d7b,
+ 0x9a62, 0x47b8,
+ 0x9a66, 0x43ed,
+ 0x9a67, 0x47bc,
+ 0x9a68, 0x3d7c,
+ 0x9a69, 0x43ee,
+ 0x9a6a, 0x47bd,
+ 0x9a6b, 0x43ff,
+ 0x9a6c, 0x47be,
+ 0x9a73, 0x3d7d,
+ 0x9a74, 0x47c5,
+ 0x9a75, 0x43f1,
+ 0x9a76, 0x47c6,
+ 0x9a7e, 0x3d7e,
+ 0x9aa1, 0x47ce,
+ 0x9aa3, 0x43f3,
+ 0x9aa4, 0x47d0,
+ 0x9aa5, 0x43f2,
+ 0x9aa6, 0x47d1,
+ 0x9aa9, 0x43f8,
+ 0x9aaa, 0x43f4,
+ 0x9aab, 0x47d4,
+ 0x9ab2, 0x3d7f,
+ 0x9ab3, 0x47db,
+ 0x9ab7, 0x3d80,
+ 0x9ab8, 0x47df,
+ 0x9ab9, 0x3d81,
+ 0x9aba, 0x47e0,
+ 0x9abb, 0x3d82,
+ 0x9abc, 0x47e1,
+ 0x9abd, 0x43b7,
+ 0x9abe, 0x47e2,
+ 0x9ac7, 0x3d83,
+ 0x9ac8, 0x47eb,
+ 0x9ad0, 0x3d84,
+ 0x9ad1, 0x47f3,
+ 0x9ad2, 0x3d85,
+ 0x9ad3, 0x47f4,
+ 0x9ad9, 0x3d86,
+ 0x9adc, 0x47fa,
+ 0x9ae2, 0x3d89,
+ 0x9ae3, 0x4800,
+ 0x9ae4, 0x3d8a,
+ 0x9ae5, 0x4801,
+ 0x9ae8, 0x3d8b,
+ 0x9ae9, 0x43b0,
+ 0x9aea, 0x4804,
+ 0x9aee, 0x43b2,
+ 0x9aef, 0x4808,
+ 0x9af2, 0x3d8c,
+ 0x9af3, 0x480b,
+ 0x9af6, 0x3d8d,
+ 0x9af7, 0x480e,
+ 0x9afb, 0x3d8e,
+ 0x9afc, 0x4812,
+ 0x9b40, 0x4815,
+ 0x9b46, 0x3d8f,
+ 0x9b47, 0x481b,
+ 0x9b4a, 0x3d90,
+ 0x9b4b, 0x481e,
+ 0x9b54, 0x3d92,
+ 0x9b55, 0x4827,
+ 0x9b58, 0x3d93,
+ 0x9b59, 0x482a,
+ 0x9b5a, 0x3d94,
+ 0x9b5b, 0x482b,
+ 0x9b5c, 0x3d95,
+ 0x9b5d, 0x482c,
+ 0x9b5e, 0x3d96,
+ 0x9b60, 0x482d,
+ 0x9b62, 0x482e,
+ 0x9b70, 0x3d98,
+ 0x9b74, 0x483c,
+ 0x9b77, 0x3d9d,
+ 0x9b79, 0x483e,
+ 0x9b7c, 0x3da0,
+ 0x9b7d, 0x4840,
+ 0x9b7e, 0x3da1,
+ 0x9ba1, 0x3da2,
+ 0x9ba2, 0x4841,
+ 0x9ba3, 0x3da3,
+ 0x9ba5, 0x4842,
+ 0x9ba7, 0x3da5,
+ 0x9bab, 0x4844,
+ 0x9bac, 0x3da9,
+ 0x9bad, 0x4845,
+ 0x9baf, 0x3daa,
+ 0x9bb0, 0x4847,
+ 0x9bb2, 0x3dab,
+ 0x9bba, 0x4849,
+ 0x9bbe, 0x3db3,
+ 0x9bbf, 0x484d,
+ 0x9bc0, 0x3db4,
+ 0x9bc7, 0x484e,
+ 0x9bca, 0x3dbb,
+ 0x9bcb, 0x4851,
+ 0x9bcc, 0x3dbc,
+ 0x9bcd, 0x4852,
+ 0x9bce, 0x43d0,
+ 0x9bcf, 0x4853,
+ 0x9bd0, 0x3dbd,
+ 0x9bd2, 0x4854,
+ 0x9bd3, 0x3dbf,
+ 0x9bd4, 0x4855,
+ 0x9bd5, 0x3dc0,
+ 0x9bd6, 0x4856,
+ 0x9bd8, 0x3dc1,
+ 0x9bdb, 0x4858,
+ 0x9bdd, 0x3dc4,
+ 0x9bdf, 0x3dc5,
+ 0x9be0, 0x485a,
+ 0x9be1, 0x3dc6,
+ 0x9be2, 0x485b,
+ 0x9be3, 0x3dc7,
+ 0x9be4, 0x485c,
+ 0x9be7, 0x3dc8,
+ 0x9be8, 0x485f,
+ 0x9be9, 0x3dc9,
+ 0x9bed, 0x4860,
+ 0x9bee, 0x3dcd,
+ 0x9bf0, 0x4861,
+ 0x9bf3, 0x3dcf,
+ 0x9bf4, 0x4864,
+ 0x9bf7, 0x4866,
+ 0x9bf8, 0x3dd1,
+ 0x9bfa, 0x4867,
+ 0x9bfb, 0x3dd3,
+ 0x9bfd, 0x4868,
+ 0x9c40, 0x3dd5,
+ 0x9c43, 0x486a,
+ 0x9c44, 0x3dd8,
+ 0x9c47, 0x486b,
+ 0x9c48, 0x3ddb,
+ 0x9c49, 0x486c,
+ 0x9c4a, 0x3ddc,
+ 0x9c4b, 0x486d,
+ 0x9c4d, 0x3ddd,
+ 0x9c54, 0x486f,
+ 0x9c55, 0x3de4,
+ 0x9c56, 0x4870,
+ 0x9c57, 0x3de5,
+ 0x9c5c, 0x4871,
+ 0x9c5d, 0x3dea,
+ 0x9c5e, 0x4872,
+ 0x9c60, 0x3deb,
+ 0x9c61, 0x4874,
+ 0x9c63, 0x4875,
+ 0x9c64, 0x3ded,
+ 0x9c67, 0x4876,
+ 0x9c69, 0x4877,
+ 0x9c6a, 0x3df1,
+ 0x9c6c, 0x4878,
+ 0x9c6d, 0x3df2,
+ 0x9c6e, 0x4879,
+ 0x9c6f, 0x3df3,
+ 0x9c73, 0x487a,
+ 0x9c75, 0x3df7,
+ 0x9c78, 0x487c,
+ 0x9c79, 0x3dfa,
+ 0x9c7a, 0x487d,
+ 0x9c7b, 0x3dfb,
+ 0x9c7d, 0x487e,
+ 0x9c7e, 0x3dfd,
+ 0x9ca1, 0x3dfe,
+ 0x9ca3, 0x487f,
+ 0x9ca5, 0x3e00,
+ 0x9ca6, 0x4881,
+ 0x9ca8, 0x3e01,
+ 0x9caa, 0x4883,
+ 0x9cab, 0x3e03,
+ 0x9cac, 0x4884,
+ 0x9cad, 0x3e04,
+ 0x9caf, 0x4885,
+ 0x9cb1, 0x3e06,
+ 0x9cbb, 0x4887,
+ 0x9cbe, 0x3e12,
+ 0x9cc3, 0x4888,
+ 0x9cc6, 0x3e17,
+ 0x9cce, 0x488b,
+ 0x9ccf, 0x3e1f,
+ 0x9cd1, 0x3e21,
+ 0x9cd4, 0x488c,
+ 0x9cd8, 0x3e24,
+ 0x9cdb, 0x4890,
+ 0x9cdc, 0x3e27,
+ 0x9ce6, 0x4891,
+ 0x9ce7, 0x3e31,
+ 0x9cea, 0x4892,
+ 0x9ceb, 0x3e34,
+ 0x9ced, 0x4893,
+ 0x9cee, 0x3e36,
+ 0x9cfa, 0x4894,
+ 0x9cfd, 0x3e42,
+ 0x9cfe, 0x4897,
+ 0x9d40, 0x43e8,
+ 0x9d41, 0x4898,
+ 0x9d46, 0x3e43,
+ 0x9d47, 0x489d,
+ 0x9d49, 0x3e44,
+ 0x9d4a, 0x489f,
+ 0x9d4c, 0x3e46,
+ 0x9d4e, 0x48a1,
+ 0x9d4f, 0x3e48,
+ 0x9d50, 0x48a2,
+ 0x9d51, 0x3e49,
+ 0x9d52, 0x48a3,
+ 0x9d55, 0x3e4a,
+ 0x9d56, 0x48a6,
+ 0x9d58, 0x48a7,
+ 0x9d5b, 0x48a9,
+ 0x9d61, 0x43c9,
+ 0x9d62, 0x3e4c,
+ 0x9d63, 0x48af,
+ 0x9d64, 0x3e4d,
+ 0x9d65, 0x48b0,
+ 0x9d78, 0x43f5,
+ 0x9d79, 0x3e4e,
+ 0x9d7a, 0x48c3,
+ 0x9d7e, 0x3e4f,
+ 0x9da1, 0x48c7,
+ 0x9da5, 0x3e50,
+ 0x9da9, 0x48cb,
+ 0x9daa, 0x3e54,
+ 0x9dab, 0x48cc,
+ 0x9dac, 0x3e55,
+ 0x9dae, 0x48cd,
+ 0x9db0, 0x3e58,
+ 0x9db1, 0x48cf,
+ 0x9db3, 0x3e59,
+ 0x9db4, 0x48d1,
+ 0x9db5, 0x3e5a,
+ 0x9db6, 0x48d2,
+ 0x9db7, 0x3e5b,
+ 0x9db8, 0x48d3,
+ 0x9dbc, 0x3e5c,
+ 0x9dbe, 0x48d7,
+ 0x9dbf, 0x3e5e,
+ 0x9dc1, 0x48d8,
+ 0x9dc3, 0x3e60,
+ 0x9dc5, 0x48da,
+ 0x9dc7, 0x3e62,
+ 0x9dc9, 0x48dc,
+ 0x9dca, 0x3e64,
+ 0x9dcb, 0x48dd,
+ 0x9dcd, 0x3e65,
+ 0x9dd2, 0x48df,
+ 0x9dd3, 0x3e6a,
+ 0x9dd6, 0x48e0,
+ 0x9dda, 0x3e6d,
+ 0x9dfc, 0x48e4,
+ 0x9dfd, 0x3e8f,
+ 0x9e40, 0x3e91,
+ 0x9e43, 0x48e5,
+ 0x9e44, 0x3e95,
+ 0x9e5f, 0x48e6,
+ 0x9e60, 0x3eb1,
+ 0x9e63, 0x48e7,
+ 0x9e64, 0x3eb4,
+ 0x9e66, 0x48e8,
+ 0x9e68, 0x3eb6,
+ 0x9e69, 0x48ea,
+ 0x9e6a, 0x3eb7,
+ 0x9e6b, 0x48eb,
+ 0x9e71, 0x3eb8,
+ 0x9e72, 0x48f1,
+ 0x9e73, 0x3eb9,
+ 0x9e74, 0x48f2,
+ 0x9e77, 0x3eba,
+ 0x9e79, 0x48f5,
+ 0x9e7a, 0x3ebc,
+ 0x9e7b, 0x48f6,
+ 0x9e7c, 0x3ebd,
+ 0x9e7d, 0x48f7,
+ 0x9e7e, 0x3ebe,
+ 0x9ea1, 0x3ebf,
+ 0x9ea3, 0x48f8,
+ 0x9ea4, 0x3ec1,
+ 0x9ea7, 0x48f9,
+ 0x9eaa, 0x3ec5,
+ 0x9eab, 0x48fb,
+ 0x9ead, 0x3ec7,
+ 0x9eae, 0x48fc,
+ 0x9eaf, 0x3ec8,
+ 0x9eb2, 0x48fd,
+ 0x9eb4, 0x3ecb,
+ 0x9eb5, 0x48ff,
+ 0x9eb6, 0x3ecc,
+ 0x9eb8, 0x4900,
+ 0x9eb9, 0x3ece,
+ 0x9eba, 0x4901,
+ 0x9ebc, 0x3ecf,
+ 0x9ebd, 0x4903,
+ 0x9ebf, 0x3ed0,
+ 0x9ec1, 0x4905,
+ 0x9ec5, 0x3ed3,
+ 0x9ec6, 0x4908,
+ 0x9ec7, 0x3ed4,
+ 0x9ecb, 0x4909,
+ 0x9ecd, 0x3ed9,
+ 0x9ece, 0x490b,
+ 0x9ed0, 0x3eda,
+ 0x9ed2, 0x490d,
+ 0x9ed3, 0x3edc,
+ 0x9ed4, 0x490e,
+ 0x9ed6, 0x3edd,
+ 0x9ed8, 0x4910,
+ 0x9eda, 0x3edf,
+ 0x9ef0, 0x3ef5,
+ 0x9ef2, 0x4912,
+ 0x9ef3, 0x3ef7,
+ 0x9ef5, 0x3ef9,
+ 0x9ef6, 0x4913,
+ 0x9ef9, 0x3efa,
+ 0x9efb, 0x4916,
+ 0x9efc, 0x3efc,
+ 0x9efe, 0x3efe,
+ 0x9f40, 0x3eff,
+ 0x9f43, 0x4917,
+ 0x9f44, 0x3f02,
+ 0x9f48, 0x4918,
+ 0x9f49, 0x3f06,
+ 0x9f4b, 0x4919,
+ 0x9f4d, 0x3f08,
+ 0x9f4f, 0x3f0a,
+ 0x9f61, 0x3f1c,
+ 0x9f67, 0x491b,
+ 0x9f69, 0x3f23,
+ 0x9f70, 0x491d,
+ 0x9f71, 0x3f2a,
+ 0x9fa1, 0x3f38,
+ 0x9fae, 0x3f45,
+ 0x9fb2, 0x3f49,
+ 0x9fb5, 0x491e,
+ 0x9fb6, 0x3f4c,
+ 0x9fbb, 0x491f,
+ 0x9fbc, 0x3f51,
+ 0x9fbf, 0x4920,
+ 0x9fc1, 0x4921,
+ 0x9fc2, 0x3f55,
+ 0x9fc9, 0x3f5c,
+ 0x9fcc, 0x4922,
+ 0x9fcd, 0x3f60,
+ 0x9fd4, 0x4923,
+ 0x9fd5, 0x3f68,
+ 0x9fd9, 0x3f6c,
+ 0x9fdb, 0x3f6e,
+ 0x9fe4, 0x4924,
+ 0x9fe5, 0x3f77,
+ 0x9fe7, 0x3f79,
+ 0x9feb, 0x3f7d,
+ 0x9ff0, 0x3f82,
+ 0x9ff9, 0x4925,
+ 0x9ffa, 0x3f8b,
+ 0xa040, 0x4926,
+ 0xa041, 0x3f90,
+ 0xa047, 0x4927,
+ 0xa048, 0x3f96,
+ 0xa055, 0x4928,
+ 0xa056, 0x3fa3,
+ 0xa058, 0x3fa5,
+ 0xa05b, 0x3fa8,
+ 0xa064, 0x3fb1,
+ 0xa06d, 0x4929,
+ 0xa06e, 0x3fba,
+ 0xa073, 0x3fbf,
+ 0xa078, 0x3fc4,
+ 0xa07b, 0x492a,
+ 0xa07c, 0x3fc7,
+ 0xa0a1, 0x3fca,
+ 0xa0a2, 0x492b,
+ 0xa0a3, 0x3fcb,
+ 0xa0a6, 0x3fce,
+ 0xa0a7, 0x492c,
+ 0xa0a8, 0x3fcf,
+ 0xa0ae, 0x3fd5,
+ 0xa0b0, 0x3fd7,
+ 0xa0c5, 0x492d,
+ 0xa0c6, 0x3fec,
+ 0xa0d0, 0x492e,
+ 0xa0d1, 0x3ff6,
+ 0xa0d4, 0x3ff9,
+ 0xa0d6, 0x3ffb,
+ 0xa0e0, 0x4005,
+ 0xa0e2, 0x4007,
+ 0xa0e3, 0x492f,
+ 0xa0e5, 0x4009,
+ 0xa0e7, 0x4930,
+ 0xa0ee, 0x43b4,
+ 0xa0ef, 0x4937,
+ 0xa0f2, 0x43b8,
+ 0xa0f3, 0x493a,
+ 0xa140, 0x0063,
+ 0xa159, 0x35af,
+ 0xa15d, 0x0080,
+ 0xa1a1, 0x00a2,
+ 0xa1f6, 0x00f8,
+ 0xa1f7, 0x00f7,
+ 0xa1f8, 0x00f9,
+ 0xa240, 0x0100,
+ 0xa2a1, 0x013f,
+ 0xa340, 0x019d,
+ 0xa3a1, 0x01dc,
+ 0xa3bd, 0x01f7,
+ 0xa440, 0x0253,
+ 0xa4a1, 0x0292,
+ 0xa540, 0x02f0,
+ 0xa5a1, 0x032f,
+ 0xa640, 0x038d,
+ 0xa6a1, 0x03cc,
+ 0xa740, 0x042a,
+ 0xa7a1, 0x0469,
+ 0xa840, 0x04c7,
+ 0xa8a1, 0x0506,
+ 0xa940, 0x0564,
+ 0xa9a1, 0x05a3,
+ 0xaa40, 0x0601,
+ 0xaaa1, 0x0640,
+ 0xab40, 0x069e,
+ 0xaba1, 0x06dd,
+ 0xac40, 0x073b,
+ 0xaca1, 0x077a,
+ 0xacfe, 0x097f,
+ 0xad40, 0x07d7,
+ 0xada1, 0x0816,
+ 0xae40, 0x0874,
+ 0xaea1, 0x08b3,
+ 0xaf40, 0x0911,
+ 0xafa1, 0x0950,
+ 0xafd0, 0x0980,
+ 0xb040, 0x09af,
+ 0xb0a1, 0x09ee,
+ 0xb140, 0x0a4c,
+ 0xb1a1, 0x0a8b,
+ 0xb240, 0x0ae9,
+ 0xb2a1, 0x0b28,
+ 0xb340, 0x0b86,
+ 0xb3a1, 0x0bc5,
+ 0xb440, 0x0c23,
+ 0xb4a1, 0x0c62,
+ 0xb540, 0x0cc0,
+ 0xb5a1, 0x0cff,
+ 0xb640, 0x0d5d,
+ 0xb6a1, 0x0d9c,
+ 0xb740, 0x0dfa,
+ 0xb7a1, 0x0e39,
+ 0xb840, 0x0e97,
+ 0xb8a1, 0x0ed6,
+ 0xb940, 0x0f34,
+ 0xb9a1, 0x0f73,
+ 0xba40, 0x0fd1,
+ 0xbaa1, 0x1010,
+ 0xbb40, 0x106e,
+ 0xbba1, 0x10ad,
+ 0xbbc8, 0x10d5,
+ 0xbc40, 0x110c,
+ 0xbca1, 0x114b,
+ 0xbd40, 0x11a9,
+ 0xbda1, 0x11e8,
+ 0xbe40, 0x1246,
+ 0xbe52, 0x10d4,
+ 0xbe53, 0x1258,
+ 0xbea1, 0x1284,
+ 0xbf40, 0x12e2,
+ 0xbfa1, 0x1321,
+ 0xc040, 0x137f,
+ 0xc0a1, 0x13be,
+ 0xc140, 0x141c,
+ 0xc1a1, 0x145b,
+ 0xc1ab, 0x1466,
+ 0xc240, 0x14ba,
+ 0xc2a1, 0x14f9,
+ 0xc2cb, 0x1465,
+ 0xc2cc, 0x1523,
+ 0xc340, 0x1556,
+ 0xc361, 0x1578,
+ 0xc3a1, 0x1596,
+ 0xc3b9, 0x15af,
+ 0xc3ba, 0x15ae,
+ 0xc3bb, 0x15b0,
+ 0xc440, 0x15f4,
+ 0xc456, 0x1577,
+ 0xc457, 0x160a,
+ 0xc4a1, 0x1632,
+ 0xc540, 0x1690,
+ 0xc5a1, 0x16cf,
+ 0xc640, 0x172d,
+ 0xc6a1, 0x01fa,
+ 0xc6bf, 0x0219,
+ 0xc6d0, 0x022a,
+ 0xc6d4, 0x022e,
+ 0xc6d6, 0x0230,
+ 0xc6d8, 0x35b3,
+ 0xc6e0, 0x35ba,
+ 0xc740, 0x35d9,
+ 0xc7a1, 0x3618,
+ 0xc840, 0x3676,
+ 0xc8a1, 0x36b5,
+ 0xc8cd, 0x36e1,
+ 0xc8d4, 0x44c6,
+ 0xc8d7, 0x451c,
+ 0xc8e0, 0x02dc,
+ 0xc8e1, 0x4525,
+ 0xc8e9, 0x0509,
+ 0xc8ea, 0x452d,
+ 0xc8f1, 0x09f6,
+ 0xc8f5, 0x4992,
+ 0xc940, 0x176c,
+ 0xc94a, 0x0274,
+ 0xc94b, 0x1776,
+ 0xc96c, 0x1798,
+ 0xc9a1, 0x17ab,
+ 0xc9be, 0x1797,
+ 0xc9bf, 0x17c8,
+ 0xc9ed, 0x17f7,
+ 0xca40, 0x1809,
+ 0xcaa1, 0x1848,
+ 0xcaf7, 0x17f6,
+ 0xcaf8, 0x189e,
+ 0xcb40, 0x18a5,
+ 0xcba1, 0x18e4,
+ 0xcc40, 0x1942,
+ 0xcca1, 0x1981,
+ 0xcd40, 0x19df,
+ 0xcda1, 0x1a1e,
+ 0xce40, 0x1a7c,
+ 0xcea1, 0x1abb,
+ 0xcf40, 0x1b19,
+ 0xcfa1, 0x1b58,
+ 0xd040, 0x1bb6,
+ 0xd0a1, 0x1bf5,
+ 0xd140, 0x1c53,
+ 0xd1a1, 0x1c92,
+ 0xd240, 0x1cf0,
+ 0xd2a1, 0x1d2f,
+ 0xd340, 0x1d8d,
+ 0xd3a1, 0x1dcc,
+ 0xd440, 0x1e2a,
+ 0xd4a1, 0x1e69,
+ 0xd540, 0x1ec7,
+ 0xd5a1, 0x1f06,
+ 0xd640, 0x1f64,
+ 0xd6a1, 0x1fa3,
+ 0xd6cc, 0x2254,
+ 0xd6cd, 0x1fcf,
+ 0xd740, 0x2001,
+ 0xd77a, 0x22b9,
+ 0xd77b, 0x203b,
+ 0xd7a1, 0x203f,
+ 0xd840, 0x209d,
+ 0xd8a1, 0x20dc,
+ 0xd940, 0x213a,
+ 0xd9a1, 0x2179,
+ 0xda40, 0x21d7,
+ 0xdaa1, 0x2216,
+ 0xdadf, 0x1fce,
+ 0xdae0, 0x2255,
+ 0xdb40, 0x2274,
+ 0xdba1, 0x22b3,
+ 0xdba7, 0x22ba,
+ 0xdc40, 0x2312,
+ 0xdca1, 0x2351,
+ 0xdd40, 0x23af,
+ 0xdda1, 0x23ee,
+ 0xddfc, 0x2381,
+ 0xddfd, 0x2449,
+ 0xde40, 0x244b,
+ 0xdea1, 0x248a,
+ 0xdf40, 0x24e8,
+ 0xdfa1, 0x2527,
+ 0xe040, 0x2585,
+ 0xe0a1, 0x25c4,
+ 0xe140, 0x2622,
+ 0xe1a1, 0x2661,
+ 0xe240, 0x26bf,
+ 0xe2a1, 0x26fe,
+ 0xe340, 0x275c,
+ 0xe3a1, 0x279b,
+ 0xe440, 0x27f9,
+ 0xe4a1, 0x2838,
+ 0xe540, 0x2896,
+ 0xe5a1, 0x28d5,
+ 0xe640, 0x2933,
+ 0xe6a1, 0x2972,
+ 0xe740, 0x29d0,
+ 0xe7a1, 0x2a0f,
+ 0xe840, 0x2a6d,
+ 0xe8a1, 0x2aac,
+ 0xe8a3, 0x2aaf,
+ 0xe940, 0x2b0b,
+ 0xe976, 0x2b42,
+ 0xe9a1, 0x2b4b,
+ 0xea40, 0x2ba9,
+ 0xeaa1, 0x2be8,
+ 0xeb40, 0x2c46,
+ 0xeb5b, 0x2c62,
+ 0xeba1, 0x2c86,
+ 0xebf1, 0x2aae,
+ 0xebf2, 0x2cd6,
+ 0xec40, 0x2ce3,
+ 0xeca1, 0x2d22,
+ 0xecde, 0x2b41,
+ 0xecdf, 0x2d5f,
+ 0xed40, 0x2d7f,
+ 0xeda1, 0x2dbe,
+ 0xedaa, 0x2dc8,
+ 0xee40, 0x2e1d,
+ 0xeea1, 0x2e5c,
+ 0xeeeb, 0x3014,
+ 0xeeec, 0x2ea6,
+ 0xef40, 0x2eb9,
+ 0xefa1, 0x2ef8,
+ 0xf040, 0x2f56,
+ 0xf056, 0x2dc7,
+ 0xf057, 0x2f6c,
+ 0xf0a1, 0x2f94,
+ 0xf0cb, 0x2c61,
+ 0xf0cc, 0x2fbe,
+ 0xf140, 0x2ff1,
+ 0xf163, 0x3015,
+ 0xf16b, 0x3160,
+ 0xf16c, 0x301d,
+ 0xf1a1, 0x3030,
+ 0xf240, 0x308e,
+ 0xf268, 0x31ef,
+ 0xf269, 0x30b6,
+ 0xf2a1, 0x30cc,
+ 0xf2c3, 0x30ef,
+ 0xf340, 0x312b,
+ 0xf375, 0x3161,
+ 0xf3a1, 0x316b,
+ 0xf440, 0x31c9,
+ 0xf466, 0x31f0,
+ 0xf4a1, 0x3209,
+ 0xf4b5, 0x30ee,
+ 0xf4b6, 0x321d,
+ 0xf4fd, 0x3265,
+ 0xf540, 0x3267,
+ 0xf5a1, 0x32a6,
+ 0xf640, 0x3304,
+ 0xf663, 0x3264,
+ 0xf664, 0x3327,
+ 0xf6a1, 0x3342,
+ 0xf740, 0x33a0,
+ 0xf7a1, 0x33df,
+ 0xf840, 0x343d,
+ 0xf8a1, 0x347c,
+ 0xf940, 0x34da,
+ 0xf977, 0x3512,
+ 0xf9a1, 0x351a,
+ 0xf9c4, 0x3511,
+ 0xf9c5, 0x353d,
+ 0xf9c6, 0x3549,
+ 0xf9c7, 0x353e,
+ 0xf9d2, 0x354a,
+ 0xf9d6, 0x36e8,
+ 0xfa40, 0x400b,
+ 0xfa60, 0x402b,
+ 0xfa67, 0x4032,
+ 0xfaa1, 0x404a,
+ 0xfaa9, 0x4946,
+ 0xfaab, 0x4054,
+ 0xfabe, 0x4067,
+ 0xfac6, 0x406f,
+ 0xfad6, 0x407f,
+ 0xfb40, 0x40a8,
+ 0xfb49, 0x40b1,
+ 0xfb53, 0x4948,
+ 0xfb54, 0x40bc,
+ 0xfb6e, 0x4949,
+ 0xfb6f, 0x40d7,
+ 0xfba1, 0x40e7,
+ 0xfba3, 0x494a,
+ 0xfba4, 0x40ea,
+ 0xfbb9, 0x40ff,
+ 0xfbbf, 0x494b,
+ 0xfbc0, 0x4105,
+ 0xfbcd, 0x494c,
+ 0xfbce, 0x4112,
+ 0xfbf4, 0x4138,
+ 0xfbfa, 0x413e,
+ 0xfc40, 0x4143,
+ 0xfc4a, 0x494d,
+ 0xfc4b, 0x414d,
+ 0xfc50, 0x4151,
+ 0xfc52, 0x494e,
+ 0xfc53, 0x4153,
+ 0xfc63, 0x494f,
+ 0xfc64, 0x4163,
+ 0xfc6d, 0x4950,
+ 0xfc6e, 0x416d,
+ 0xfc75, 0x4951,
+ 0xfc76, 0x4174,
+ 0xfca1, 0x417d,
+ 0xfcba, 0x4195,
+ 0xfcbc, 0x4952,
+ 0xfcbe, 0x4198,
+ 0xfccc, 0x4954,
+ 0xfccd, 0x41a7,
+ 0xfce3, 0x4955,
+ 0xfce4, 0x41bd,
+ 0xfcee, 0x4956,
+ 0xfcef, 0x41c7,
+ 0xfcf2, 0x41ca,
+ 0xfd40, 0x41d7,
+ 0xfd49, 0x4957,
+ 0xfd4a, 0x41e0,
+ 0xfd6a, 0x4958,
+ 0xfd6b, 0x4201,
+ 0xfda1, 0x4215,
+ 0xfdb9, 0x422d,
+ 0xfdbc, 0x4230,
+ 0xfde3, 0x4959,
+ 0xfde4, 0x4258,
+ 0xfdf2, 0x495a,
+ 0xfdf3, 0x4266,
+ 0xfe40, 0x4272,
+ 0xfe53, 0x4285,
+ 0xfe6d, 0x495b,
+ 0xfe6e, 0x429f,
+ 0xfe70, 0x42a1,
+ 0xfe78, 0x495c,
+ 0xfe79, 0x42a9,
+ 0xfea1, 0x42af,
+ 0xfeab, 0x42b8,
+ 0xfede, 0x495d,
+ 0xfee0, 0x42eb,
+ 0xfeed, 0x495f,
+ 0xfeef, 0x42f8,
+ 0xa14b, 0x354e,
+ 0xa15a, 0x35af,
+ 0xa15c, 0x35b1,
+ 0xa15d, 0x0082,
+ 0xa161, 0x0086,
+ 0xa165, 0x008a,
+ 0xa169, 0x008e,
+ 0xa16d, 0x0092,
+ 0xa171, 0x0096,
+ 0xa175, 0x009a,
+ 0xa179, 0x009e,
+ 0xa1e3, 0x354f,
+ 0xc6e4, 0x3711,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13HKscsB5VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13HKscsB5VMap2, 1142
+};
+
+static Gushort cns13UniCNSUCS2HMap2[30910] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x00a2, 0x0106,
+ 0x00a5, 0x0104,
+ 0x00a7, 0x00b2,
+ 0x00a8, 0x35b3,
+ 0x00ac, 0x36e1,
+ 0x00b0, 0x0118,
+ 0x00b1, 0x00d4,
+ 0x00b7, 0x0073,
+ 0x00c0, 0x4964,
+ 0x00c1, 0x4962,
+ 0x00c8, 0x4968,
+ 0x00c9, 0x4966,
+ 0x00ca, 0x4971,
+ 0x00d2, 0x496c,
+ 0x00d3, 0x496a,
+ 0x00d7, 0x00d2,
+ 0x00e0, 0x4975,
+ 0x00e1, 0x4973,
+ 0x00e8, 0x497a,
+ 0x00e9, 0x4978,
+ 0x00ea, 0x4990,
+ 0x00ec, 0x497e,
+ 0x00ed, 0x497c,
+ 0x00f2, 0x4982,
+ 0x00f3, 0x4980,
+ 0x00f7, 0x00d3,
+ 0x00f8, 0x4998,
+ 0x00f9, 0x4986,
+ 0x00fa, 0x4984,
+ 0x00fc, 0x498b,
+ 0x0100, 0x4961,
+ 0x0101, 0x4972,
+ 0x0112, 0x4965,
+ 0x0113, 0x4977,
+ 0x011a, 0x4967,
+ 0x011b, 0x4979,
+ 0x012b, 0x497b,
+ 0x014b, 0x4999,
+ 0x014c, 0x4969,
+ 0x014d, 0x497f,
+ 0x0153, 0x4997,
+ 0x016b, 0x4983,
+ 0x01cd, 0x4963,
+ 0x01ce, 0x4974,
+ 0x01d0, 0x497d,
+ 0x01d1, 0x496b,
+ 0x01d2, 0x4981,
+ 0x01d4, 0x4985,
+ 0x01d6, 0x4987,
+ 0x01d8, 0x4988,
+ 0x01da, 0x4989,
+ 0x01dc, 0x498a,
+ 0x0250, 0x4993,
+ 0x0251, 0x4976,
+ 0x0254, 0x4995,
+ 0x025b, 0x4994,
+ 0x0261, 0x4991,
+ 0x026a, 0x499b,
+ 0x0275, 0x4996,
+ 0x0283, 0x4992,
+ 0x028a, 0x499a,
+ 0x02c6, 0x35b4,
+ 0x02c7, 0x01f8,
+ 0x02ca, 0x01f7,
+ 0x02cb, 0x01f9,
+ 0x02d9, 0x01f6,
+ 0x0308, 0x35b3,
+ 0x0391, 0x01a1,
+ 0x03a3, 0x01b2,
+ 0x03b1, 0x01b9,
+ 0x03c3, 0x01ca,
+ 0x0401, 0x3670,
+ 0x0410, 0x366a,
+ 0x0416, 0x3671,
+ 0x0436, 0x3692,
+ 0x0451, 0x3691,
+ 0x1ebe, 0x496e,
+ 0x1ebf, 0x498d,
+ 0x1ec0, 0x4970,
+ 0x1ec1, 0x498f,
+ 0x2013, 0x0079,
+ 0x2014, 0x007b,
+ 0x2018, 0x00a6,
+ 0x201c, 0x00a8,
+ 0x2022, 0x0068,
+ 0x2025, 0x006f,
+ 0x2026, 0x006e,
+ 0x2032, 0x00ad,
+ 0x2035, 0x00ac,
+ 0x203b, 0x00b1,
+ 0x203e, 0x00c3,
+ 0x20ac, 0x44c1,
+ 0x2103, 0x010a,
+ 0x2105, 0x00c2,
+ 0x2109, 0x010b,
+ 0x2116, 0x36e6,
+ 0x2121, 0x36e7,
+ 0x2160, 0x0157,
+ 0x2170, 0x020e,
+ 0x2190, 0x00f8,
+ 0x2191, 0x00f5,
+ 0x2192, 0x00f7,
+ 0x2193, 0x00f6,
+ 0x2196, 0x00f9,
+ 0x2198, 0x00fc,
+ 0x2199, 0x00fb,
+ 0x21b8, 0x36ad,
+ 0x21e7, 0x36ac,
+ 0x221a, 0x00d5,
+ 0x221e, 0x00dc,
+ 0x221f, 0x00e9,
+ 0x2220, 0x00e8,
+ 0x2223, 0x00fe,
+ 0x2225, 0x00fd,
+ 0x2229, 0x00e5,
+ 0x222b, 0x00ed,
+ 0x222e, 0x00ee,
+ 0x2234, 0x00f0,
+ 0x2235, 0x00ef,
+ 0x223c, 0x00e4,
+ 0x2252, 0x00dd,
+ 0x2260, 0x00db,
+ 0x2261, 0x00de,
+ 0x2266, 0x00d9,
+ 0x22a5, 0x00e7,
+ 0x22bf, 0x00ea,
+ 0x2400, 0x0232,
+ 0x2421, 0x0252,
+ 0x2460, 0x01fa,
+ 0x2474, 0x0204,
+ 0x2500, 0x0137,
+ 0x2502, 0x0138,
+ 0x250c, 0x013a,
+ 0x2510, 0x013b,
+ 0x2514, 0x013c,
+ 0x2518, 0x013d,
+ 0x251c, 0x0135,
+ 0x2524, 0x0134,
+ 0x252c, 0x0133,
+ 0x2534, 0x0132,
+ 0x253c, 0x0131,
+ 0x2550, 0x0142,
+ 0x2551, 0x370a,
+ 0x2552, 0x36f8,
+ 0x2553, 0x3701,
+ 0x2554, 0x36ef,
+ 0x2555, 0x36fa,
+ 0x2556, 0x3703,
+ 0x2557, 0x36f1,
+ 0x2558, 0x36fe,
+ 0x2559, 0x3707,
+ 0x255a, 0x36f5,
+ 0x255b, 0x3700,
+ 0x255c, 0x3709,
+ 0x255d, 0x36f7,
+ 0x255e, 0x0143,
+ 0x255f, 0x3704,
+ 0x2560, 0x36f2,
+ 0x2561, 0x0145,
+ 0x2562, 0x3706,
+ 0x2563, 0x36f4,
+ 0x2564, 0x36f9,
+ 0x2565, 0x3702,
+ 0x2566, 0x36f0,
+ 0x2567, 0x36ff,
+ 0x2568, 0x3708,
+ 0x2569, 0x36f6,
+ 0x256a, 0x0144,
+ 0x256b, 0x3705,
+ 0x256c, 0x36f3,
+ 0x256d, 0x013e,
+ 0x256f, 0x0141,
+ 0x2570, 0x0140,
+ 0x2571, 0x014a,
+ 0x2581, 0x0122,
+ 0x2589, 0x0130,
+ 0x258a, 0x012f,
+ 0x258b, 0x012e,
+ 0x258c, 0x012d,
+ 0x258d, 0x012c,
+ 0x258e, 0x012b,
+ 0x258f, 0x012a,
+ 0x2593, 0x3710,
+ 0x2594, 0x0136,
+ 0x2595, 0x0139,
+ 0x25a0, 0x00be,
+ 0x25a1, 0x00bd,
+ 0x25b2, 0x00b7,
+ 0x25b3, 0x00b6,
+ 0x25bc, 0x00c0,
+ 0x25bd, 0x00bf,
+ 0x25c6, 0x00bc,
+ 0x25c7, 0x00bb,
+ 0x25cb, 0x00b4,
+ 0x25ce, 0x00b8,
+ 0x25cf, 0x00b5,
+ 0x25e2, 0x0146,
+ 0x25e4, 0x0149,
+ 0x25e5, 0x0148,
+ 0x2605, 0x00ba,
+ 0x2606, 0x00b9,
+ 0x2609, 0x00f4,
+ 0x2640, 0x00f1,
+ 0x2641, 0x00f3,
+ 0x2642, 0x00f2,
+ 0x273d, 0x35c0,
+ 0x2e80, 0x44c8,
+ 0x2e84, 0x451c,
+ 0x2e86, 0x451d,
+ 0x2e8a, 0x4520,
+ 0x2e8c, 0x4521,
+ 0x2e95, 0x4523,
+ 0x2e9c, 0x4524,
+ 0x2e9d, 0x02dc,
+ 0x2ea5, 0x4525,
+ 0x2ea7, 0x4526,
+ 0x2eaa, 0x4527,
+ 0x2eac, 0x4528,
+ 0x2eae, 0x4529,
+ 0x2eb6, 0x452a,
+ 0x2ebc, 0x452b,
+ 0x2ebe, 0x452c,
+ 0x2ec6, 0x0509,
+ 0x2eca, 0x452d,
+ 0x2ecc, 0x452e,
+ 0x2ecf, 0x4530,
+ 0x2ed6, 0x4531,
+ 0x2ede, 0x4533,
+ 0x2ee3, 0x09f6,
+ 0x2f33, 0x0227,
+ 0x3000, 0x0063,
+ 0x3001, 0x0065,
+ 0x3003, 0x00b3,
+ 0x3005, 0x35ba,
+ 0x3008, 0x0094,
+ 0x300a, 0x0090,
+ 0x300c, 0x0098,
+ 0x300e, 0x009c,
+ 0x3010, 0x008c,
+ 0x3012, 0x0105,
+ 0x3014, 0x0088,
+ 0x301d, 0x00aa,
+ 0x3021, 0x0161,
+ 0x3041, 0x35c1,
+ 0x309b, 0x44c6,
+ 0x309d, 0x35b7,
+ 0x30a1, 0x3614,
+ 0x30fc, 0x35bd,
+ 0x30fd, 0x35b5,
+ 0x3105, 0x01d1,
+ 0x3231, 0x36e5,
+ 0x32a3, 0x00c1,
+ 0x338e, 0x0115,
+ 0x339c, 0x0110,
+ 0x33a1, 0x0114,
+ 0x33c4, 0x0117,
+ 0x33ce, 0x0113,
+ 0x33d1, 0x00ec,
+ 0x33d2, 0x00eb,
+ 0x33d5, 0x010f,
+ 0x3435, 0x39bd,
+ 0x3440, 0x3c67,
+ 0x344c, 0x4593,
+ 0x3464, 0x3a85,
+ 0x3473, 0x3dc5,
+ 0x347a, 0x4033,
+ 0x347d, 0x4597,
+ 0x347e, 0x46a3,
+ 0x3493, 0x439e,
+ 0x3496, 0x37dc,
+ 0x34a5, 0x4598,
+ 0x34af, 0x3c7f,
+ 0x34bc, 0x4380,
+ 0x34c1, 0x44fb,
+ 0x34c8, 0x3d00,
+ 0x34df, 0x3ea4,
+ 0x34e4, 0x3e54,
+ 0x34fb, 0x3dca,
+ 0x3506, 0x4336,
+ 0x353e, 0x44e7,
+ 0x3551, 0x45a1,
+ 0x3553, 0x43a5,
+ 0x3561, 0x40d8,
+ 0x356d, 0x45a4,
+ 0x3570, 0x3b2f,
+ 0x3572, 0x45a5,
+ 0x3577, 0x3ecb,
+ 0x3578, 0x4379,
+ 0x3584, 0x39fb,
+ 0x3597, 0x3b2d,
+ 0x3598, 0x45b0,
+ 0x35a1, 0x40e2,
+ 0x35a5, 0x45b1,
+ 0x35ad, 0x3efc,
+ 0x35bf, 0x45b2,
+ 0x35c1, 0x4580,
+ 0x35c5, 0x45b4,
+ 0x35c7, 0x459f,
+ 0x35ca, 0x3e43,
+ 0x35ce, 0x3e81,
+ 0x35d2, 0x3fc9,
+ 0x35d6, 0x3fb5,
+ 0x35db, 0x470d,
+ 0x35dd, 0x43ac,
+ 0x35f1, 0x4696,
+ 0x35f2, 0x4627,
+ 0x35f3, 0x3f6c,
+ 0x35fb, 0x45c8,
+ 0x35fe, 0x3f6a,
+ 0x3609, 0x45f5,
+ 0x3618, 0x4871,
+ 0x361a, 0x461a,
+ 0x3623, 0x40c6,
+ 0x362d, 0x3e86,
+ 0x3635, 0x492e,
+ 0x3639, 0x4165,
+ 0x363e, 0x3a08,
+ 0x3647, 0x4806,
+ 0x3648, 0x3806,
+ 0x3649, 0x4013,
+ 0x364e, 0x4698,
+ 0x365f, 0x3df3,
+ 0x367a, 0x3ee3,
+ 0x3681, 0x45a6,
+ 0x369a, 0x3c71,
+ 0x36a5, 0x4902,
+ 0x36aa, 0x3b30,
+ 0x36ac, 0x4900,
+ 0x36b0, 0x3cdf,
+ 0x36b1, 0x40cd,
+ 0x36b5, 0x3bc2,
+ 0x36b9, 0x4887,
+ 0x36bc, 0x3cff,
+ 0x36c1, 0x37c5,
+ 0x36c3, 0x40e5,
+ 0x36c4, 0x3905,
+ 0x36c5, 0x4296,
+ 0x36c7, 0x3d3a,
+ 0x36c8, 0x4820,
+ 0x36d3, 0x3a38,
+ 0x36d4, 0x3bb3,
+ 0x36d6, 0x3d0c,
+ 0x36dd, 0x3a36,
+ 0x36e1, 0x397c,
+ 0x36e2, 0x3cdd,
+ 0x36e5, 0x4216,
+ 0x36e6, 0x40fc,
+ 0x36f5, 0x3a18,
+ 0x3701, 0x3a34,
+ 0x3703, 0x460f,
+ 0x3708, 0x40ff,
+ 0x370a, 0x3cd5,
+ 0x370d, 0x4238,
+ 0x371c, 0x3dfe,
+ 0x3722, 0x3979,
+ 0x3723, 0x3980,
+ 0x3725, 0x3849,
+ 0x372c, 0x3c8c,
+ 0x372d, 0x3d37,
+ 0x3730, 0x495c,
+ 0x3732, 0x4106,
+ 0x3733, 0x3997,
+ 0x373a, 0x3e56,
+ 0x3740, 0x4202,
+ 0x3743, 0x4036,
+ 0x3762, 0x3db6,
+ 0x376f, 0x47cb,
+ 0x3797, 0x45ed,
+ 0x37a0, 0x3a28,
+ 0x37b9, 0x43b7,
+ 0x37be, 0x393e,
+ 0x37f2, 0x3ba1,
+ 0x37f8, 0x42d2,
+ 0x37fb, 0x3ef5,
+ 0x380f, 0x462c,
+ 0x3819, 0x39af,
+ 0x3820, 0x462f,
+ 0x382d, 0x412e,
+ 0x3836, 0x4133,
+ 0x3838, 0x43bb,
+ 0x3863, 0x46c3,
+ 0x38a0, 0x4145,
+ 0x38c3, 0x3912,
+ 0x38cc, 0x4076,
+ 0x38d1, 0x3a95,
+ 0x38fa, 0x44eb,
+ 0x3908, 0x4632,
+ 0x3914, 0x43be,
+ 0x3927, 0x3c31,
+ 0x3932, 0x4182,
+ 0x393f, 0x4633,
+ 0x394d, 0x4634,
+ 0x3963, 0x4163,
+ 0x3980, 0x3874,
+ 0x3989, 0x4638,
+ 0x398a, 0x3ce8,
+ 0x3992, 0x4376,
+ 0x3999, 0x39ba,
+ 0x399b, 0x3db3,
+ 0x39a1, 0x3e19,
+ 0x39a4, 0x3e0f,
+ 0x39b8, 0x463b,
+ 0x39dc, 0x3ece,
+ 0x39e2, 0x46c8,
+ 0x39e5, 0x393b,
+ 0x39ec, 0x4310,
+ 0x39f8, 0x463e,
+ 0x39fb, 0x4345,
+ 0x39fe, 0x4368,
+ 0x3a01, 0x41e0,
+ 0x3a03, 0x4640,
+ 0x3a06, 0x4377,
+ 0x3a17, 0x4190,
+ 0x3a18, 0x438f,
+ 0x3a29, 0x3a5e,
+ 0x3a2a, 0x3edf,
+ 0x3a34, 0x4319,
+ 0x3a4b, 0x4644,
+ 0x3a52, 0x3ed3,
+ 0x3a57, 0x419e,
+ 0x3a5c, 0x3fc4,
+ 0x3a5e, 0x3b07,
+ 0x3a66, 0x419c,
+ 0x3a67, 0x4333,
+ 0x3a97, 0x4647,
+ 0x3aab, 0x4091,
+ 0x3abd, 0x4649,
+ 0x3ade, 0x414c,
+ 0x3ae0, 0x3a7a,
+ 0x3af0, 0x46b2,
+ 0x3af2, 0x464c,
+ 0x3afb, 0x3af2,
+ 0x3b0e, 0x38e8,
+ 0x3b19, 0x46c5,
+ 0x3b22, 0x464e,
+ 0x3b2b, 0x4956,
+ 0x3b39, 0x474b,
+ 0x3b42, 0x4650,
+ 0x3b58, 0x4652,
+ 0x3b60, 0x393a,
+ 0x3b71, 0x4656,
+ 0x3b72, 0x4655,
+ 0x3b7b, 0x4657,
+ 0x3b7c, 0x385a,
+ 0x3b80, 0x41e2,
+ 0x3b96, 0x3a9c,
+ 0x3b99, 0x3a98,
+ 0x3ba1, 0x41e9,
+ 0x3bbc, 0x43c8,
+ 0x3bbe, 0x3db1,
+ 0x3bc2, 0x4134,
+ 0x3bc4, 0x3aa0,
+ 0x3bd7, 0x3aac,
+ 0x3bdd, 0x465f,
+ 0x3bec, 0x4664,
+ 0x3bf2, 0x4666,
+ 0x3bf3, 0x41f3,
+ 0x3bf4, 0x3a6e,
+ 0x3c0d, 0x41f7,
+ 0x3c11, 0x3e40,
+ 0x3c15, 0x3998,
+ 0x3c54, 0x3e00,
+ 0x3ccb, 0x4670,
+ 0x3ccd, 0x3ce5,
+ 0x3cd1, 0x4003,
+ 0x3cd6, 0x3cf7,
+ 0x3cdc, 0x404e,
+ 0x3ceb, 0x4217,
+ 0x3cef, 0x4675,
+ 0x3d13, 0x3773,
+ 0x3d1d, 0x393c,
+ 0x3d32, 0x4957,
+ 0x3d3b, 0x4245,
+ 0x3d46, 0x4685,
+ 0x3d4c, 0x3ceb,
+ 0x3d4e, 0x4242,
+ 0x3d51, 0x38ea,
+ 0x3d5f, 0x4159,
+ 0x3d62, 0x3c5e,
+ 0x3d69, 0x3cea,
+ 0x3d6a, 0x4689,
+ 0x3d6f, 0x3cfc,
+ 0x3d75, 0x468a,
+ 0x3d7d, 0x3c2f,
+ 0x3d85, 0x494b,
+ 0x3d8a, 0x468d,
+ 0x3d8f, 0x3abd,
+ 0x3d91, 0x468f,
+ 0x3da5, 0x3d56,
+ 0x3dad, 0x4699,
+ 0x3db4, 0x40a6,
+ 0x3dbf, 0x37d0,
+ 0x3dc6, 0x48de,
+ 0x3dc7, 0x4164,
+ 0x3dcc, 0x3d6f,
+ 0x3dcd, 0x3af3,
+ 0x3dd3, 0x37e1,
+ 0x3ddb, 0x3fff,
+ 0x3de7, 0x3999,
+ 0x3de8, 0x425d,
+ 0x3deb, 0x3e5a,
+ 0x3df3, 0x46d4,
+ 0x3df7, 0x48ab,
+ 0x3dfc, 0x462b,
+ 0x3dfd, 0x3c14,
+ 0x3e06, 0x491d,
+ 0x3e40, 0x4169,
+ 0x3e43, 0x436d,
+ 0x3e48, 0x4595,
+ 0x3e55, 0x427f,
+ 0x3e74, 0x3ee2,
+ 0x3ea8, 0x4304,
+ 0x3ea9, 0x46ed,
+ 0x3eaa, 0x4075,
+ 0x3ead, 0x3b9d,
+ 0x3eb1, 0x3ad8,
+ 0x3eb8, 0x3a4b,
+ 0x3ebf, 0x3b0b,
+ 0x3ec2, 0x3bd8,
+ 0x3ec7, 0x3975,
+ 0x3eca, 0x46f1,
+ 0x3ecc, 0x3be2,
+ 0x3ed0, 0x3854,
+ 0x3ed1, 0x46f2,
+ 0x3ed6, 0x3cad,
+ 0x3ed7, 0x429f,
+ 0x3eda, 0x3d02,
+ 0x3ede, 0x39f2,
+ 0x3ee1, 0x3ca8,
+ 0x3ee2, 0x46f6,
+ 0x3ee7, 0x3bdc,
+ 0x3ee9, 0x3ca4,
+ 0x3eeb, 0x396a,
+ 0x3ef0, 0x46f7,
+ 0x3ef3, 0x3add,
+ 0x3ef4, 0x46f8,
+ 0x3efa, 0x46f9,
+ 0x3efc, 0x3be8,
+ 0x3eff, 0x3af5,
+ 0x3f00, 0x3c0d,
+ 0x3f04, 0x42c3,
+ 0x3f06, 0x3ad7,
+ 0x3f0e, 0x46fb,
+ 0x3f53, 0x46fc,
+ 0x3f58, 0x3ae9,
+ 0x3f59, 0x4089,
+ 0x3f63, 0x3ae6,
+ 0x3f7c, 0x4700,
+ 0x3f93, 0x45cd,
+ 0x3fc0, 0x43cf,
+ 0x3fd7, 0x43d1,
+ 0x3fdc, 0x4704,
+ 0x3fe5, 0x46df,
+ 0x3fed, 0x4335,
+ 0x3ff9, 0x45d7,
+ 0x3ffa, 0x4354,
+ 0x4004, 0x410e,
+ 0x401d, 0x4709,
+ 0x4039, 0x470b,
+ 0x4045, 0x470c,
+ 0x4053, 0x45b6,
+ 0x4057, 0x399d,
+ 0x4062, 0x3bcb,
+ 0x4065, 0x3fd3,
+ 0x406a, 0x470f,
+ 0x406f, 0x4710,
+ 0x40a8, 0x43d5,
+ 0x40bb, 0x45c0,
+ 0x40bf, 0x3eec,
+ 0x40c8, 0x3b0e,
+ 0x40d8, 0x41ab,
+ 0x40df, 0x3e17,
+ 0x40fa, 0x3ebe,
+ 0x4103, 0x43d7,
+ 0x4104, 0x425c,
+ 0x4109, 0x471c,
+ 0x410e, 0x3b1b,
+ 0x4132, 0x3b25,
+ 0x4167, 0x471f,
+ 0x416c, 0x38ae,
+ 0x416e, 0x3b23,
+ 0x417f, 0x3b82,
+ 0x4190, 0x46c0,
+ 0x41b2, 0x4720,
+ 0x41c4, 0x4723,
+ 0x41ca, 0x373f,
+ 0x41cf, 0x4726,
+ 0x41db, 0x37bf,
+ 0x41ef, 0x3743,
+ 0x41f9, 0x3b3e,
+ 0x4211, 0x3b41,
+ 0x4240, 0x37f1,
+ 0x4260, 0x472b,
+ 0x426a, 0x3b55,
+ 0x427a, 0x472c,
+ 0x428c, 0x472f,
+ 0x4294, 0x4731,
+ 0x42b5, 0x4010,
+ 0x42b9, 0x38a6,
+ 0x42bc, 0x3c8a,
+ 0x42f4, 0x3bb9,
+ 0x42fb, 0x3cee,
+ 0x42fc, 0x41e6,
+ 0x432b, 0x377d,
+ 0x436e, 0x46ca,
+ 0x4397, 0x473b,
+ 0x43ba, 0x435f,
+ 0x43c1, 0x4695,
+ 0x43d9, 0x433e,
+ 0x43df, 0x3e49,
+ 0x43ed, 0x4745,
+ 0x43f2, 0x3e48,
+ 0x4401, 0x474a,
+ 0x4402, 0x3b73,
+ 0x4413, 0x474f,
+ 0x4425, 0x4751,
+ 0x442d, 0x4752,
+ 0x447a, 0x37af,
+ 0x448f, 0x4758,
+ 0x449f, 0x3ae2,
+ 0x44a0, 0x37ed,
+ 0x44a2, 0x4079,
+ 0x44b0, 0x475c,
+ 0x44b7, 0x3fa1,
+ 0x44c0, 0x3c07,
+ 0x44c5, 0x4210,
+ 0x44ce, 0x3d23,
+ 0x44dd, 0x39dd,
+ 0x44df, 0x3d22,
+ 0x44e4, 0x37e2,
+ 0x44e9, 0x41cf,
+ 0x44ea, 0x3b71,
+ 0x44eb, 0x3cf2,
+ 0x44ec, 0x3eb4,
+ 0x44f4, 0x3992,
+ 0x4503, 0x469f,
+ 0x4504, 0x4763,
+ 0x4509, 0x3e50,
+ 0x450b, 0x37d4,
+ 0x4516, 0x37f9,
+ 0x451d, 0x3767,
+ 0x4527, 0x37f7,
+ 0x452e, 0x3cd3,
+ 0x4533, 0x3c51,
+ 0x453b, 0x476a,
+ 0x453d, 0x38c4,
+ 0x453f, 0x3e12,
+ 0x4543, 0x37f3,
+ 0x4551, 0x3ae4,
+ 0x4552, 0x40b3,
+ 0x4555, 0x423e,
+ 0x455c, 0x378b,
+ 0x4562, 0x4940,
+ 0x456a, 0x3804,
+ 0x4577, 0x476e,
+ 0x4585, 0x38c5,
+ 0x45e9, 0x3ee4,
+ 0x4606, 0x4773,
+ 0x460f, 0x3815,
+ 0x4615, 0x3843,
+ 0x4617, 0x4774,
+ 0x465b, 0x381d,
+ 0x467a, 0x39e9,
+ 0x4680, 0x3d01,
+ 0x46cf, 0x3ba0,
+ 0x46d0, 0x3dfa,
+ 0x46f5, 0x3b9f,
+ 0x4713, 0x3833,
+ 0x4718, 0x3dc7,
+ 0x474e, 0x3ebc,
+ 0x477c, 0x3dcd,
+ 0x4798, 0x4781,
+ 0x47a6, 0x40a3,
+ 0x47b6, 0x3eea,
+ 0x47d5, 0x431a,
+ 0x47ed, 0x4783,
+ 0x47f4, 0x432f,
+ 0x4800, 0x461e,
+ 0x480b, 0x4352,
+ 0x4837, 0x4787,
+ 0x485d, 0x410f,
+ 0x4871, 0x3d03,
+ 0x489b, 0x3bbd,
+ 0x48ad, 0x4791,
+ 0x48ae, 0x494d,
+ 0x48d0, 0x3da7,
+ 0x48dd, 0x4120,
+ 0x48ed, 0x4288,
+ 0x48f3, 0x3ec1,
+ 0x48fa, 0x3e44,
+ 0x4906, 0x3bc7,
+ 0x4911, 0x4584,
+ 0x491e, 0x4794,
+ 0x4925, 0x3c0f,
+ 0x492a, 0x46ae,
+ 0x492d, 0x46cd,
+ 0x4935, 0x3cc3,
+ 0x493c, 0x3bf8,
+ 0x493e, 0x3d06,
+ 0x4945, 0x47a3,
+ 0x4951, 0x47a4,
+ 0x4953, 0x42ad,
+ 0x4965, 0x3899,
+ 0x496a, 0x47a9,
+ 0x4972, 0x3a24,
+ 0x4989, 0x379b,
+ 0x49a1, 0x38b7,
+ 0x49a7, 0x47ae,
+ 0x49df, 0x38aa,
+ 0x49e5, 0x47b1,
+ 0x49e7, 0x4621,
+ 0x4a0f, 0x38c3,
+ 0x4a1d, 0x3bec,
+ 0x4a24, 0x47b2,
+ 0x4a35, 0x47b4,
+ 0x4a96, 0x3ce7,
+ 0x4ab4, 0x4361,
+ 0x4ab8, 0x3da8,
+ 0x4ad1, 0x38e3,
+ 0x4ae4, 0x47b7,
+ 0x4aff, 0x38f2,
+ 0x4b19, 0x47b9,
+ 0x4b2c, 0x461f,
+ 0x4b37, 0x41a9,
+ 0x4b6f, 0x3c16,
+ 0x4b70, 0x47c0,
+ 0x4b72, 0x38fc,
+ 0x4b7b, 0x3c8d,
+ 0x4b7e, 0x400a,
+ 0x4b8e, 0x39f7,
+ 0x4b90, 0x3c20,
+ 0x4b93, 0x3a8c,
+ 0x4b96, 0x3942,
+ 0x4b97, 0x3c24,
+ 0x4b9d, 0x47c2,
+ 0x4bbd, 0x3c23,
+ 0x4bbe, 0x3954,
+ 0x4bc0, 0x3ddc,
+ 0x4c04, 0x3fbb,
+ 0x4c07, 0x3fb7,
+ 0x4c0e, 0x390c,
+ 0x4c3b, 0x3f3c,
+ 0x4c3e, 0x457b,
+ 0x4c5b, 0x3ed9,
+ 0x4c6d, 0x47c9,
+ 0x4c7d, 0x3e66,
+ 0x4ca4, 0x48be,
+ 0x4cae, 0x3c42,
+ 0x4cb0, 0x3c45,
+ 0x4cb7, 0x3e21,
+ 0x4ccd, 0x4578,
+ 0x4ce1, 0x3ef3,
+ 0x4ced, 0x40ab,
+ 0x4d09, 0x3ed6,
+ 0x4d10, 0x4117,
+ 0x4d34, 0x3935,
+ 0x4d91, 0x43f5,
+ 0x4d9c, 0x48c4,
+ 0x4e00, 0x0253,
+ 0x4e01, 0x0255,
+ 0x4e03, 0x0256,
+ 0x4e04, 0x48fe,
+ 0x4e07, 0x1771,
+ 0x4e08, 0x0269,
+ 0x4e09, 0x0267,
+ 0x4e0a, 0x026a,
+ 0x4e0b, 0x0268,
+ 0x4e0c, 0x1772,
+ 0x4e0d, 0x0294,
+ 0x4e0e, 0x177a,
+ 0x4e0f, 0x1778,
+ 0x4e10, 0x0293,
+ 0x4e11, 0x0292,
+ 0x4e14, 0x02f2,
+ 0x4e15, 0x02f1,
+ 0x4e16, 0x02f0,
+ 0x4e18, 0x02f3,
+ 0x4e19, 0x02ef,
+ 0x4e1a, 0x48fd,
+ 0x4e1c, 0x48e0,
+ 0x4e1e, 0x036e,
+ 0x4e21, 0x3d6d,
+ 0x4e24, 0x458d,
+ 0x4e26, 0x0528,
+ 0x4e28, 0x0218,
+ 0x4e2a, 0x3f57,
+ 0x4e2b, 0x026b,
+ 0x4e2c, 0x44f3,
+ 0x4e2d, 0x0295,
+ 0x4e2e, 0x177b,
+ 0x4e30, 0x0296,
+ 0x4e31, 0x178e,
+ 0x4e32, 0x0415,
+ 0x4e33, 0x18f4,
+ 0x4e36, 0x0219,
+ 0x4e37, 0x4517,
+ 0x4e38, 0x026c,
+ 0x4e39, 0x0297,
+ 0x4e3b, 0x02f4,
+ 0x4e3c, 0x178f,
+ 0x4e3d, 0x4537,
+ 0x4e3f, 0x021a,
+ 0x4e41, 0x36af,
+ 0x4e42, 0x176c,
+ 0x4e43, 0x0257,
+ 0x4e45, 0x026e,
+ 0x4e47, 0x1773,
+ 0x4e48, 0x026f,
+ 0x4e49, 0x408e,
+ 0x4e4b, 0x0298,
+ 0x4e4d, 0x02f5,
+ 0x4e4e, 0x02f7,
+ 0x4e4f, 0x02f6,
+ 0x4e52, 0x0370,
+ 0x4e56, 0x0529,
+ 0x4e58, 0x0831,
+ 0x4e59, 0x0254,
+ 0x4e5a, 0x36b1,
+ 0x4e5b, 0x44e5,
+ 0x4e5c, 0x176d,
+ 0x4e5d, 0x0258,
+ 0x4e5e, 0x0271,
+ 0x4e5f, 0x0270,
+ 0x4e69, 0x0372,
+ 0x4e6a, 0x3de5,
+ 0x4e73, 0x052a,
+ 0x4e78, 0x3d8e,
+ 0x4e7e, 0x09fb,
+ 0x4e7f, 0x1e35,
+ 0x4e80, 0x458e,
+ 0x4e81, 0x43bc,
+ 0x4e82, 0x0dbe,
+ 0x4e83, 0x2361,
+ 0x4e85, 0x021b,
+ 0x4e86, 0x0259,
+ 0x4e87, 0x458f,
+ 0x4e88, 0x029a,
+ 0x4e89, 0x459c,
+ 0x4e8b, 0x052b,
+ 0x4e8c, 0x025a,
+ 0x4e8d, 0x1774,
+ 0x4e8e, 0x0272,
+ 0x4e91, 0x029b,
+ 0x4e92, 0x029d,
+ 0x4e93, 0x177c,
+ 0x4e94, 0x029e,
+ 0x4e95, 0x029c,
+ 0x4e98, 0x39c4,
+ 0x4e99, 0x0373,
+ 0x4e9a, 0x48d5,
+ 0x4e9b, 0x052c,
+ 0x4e9e, 0x052d,
+ 0x4e9f, 0x06a3,
+ 0x4ea0, 0x021c,
+ 0x4ea1, 0x0273,
+ 0x4ea2, 0x029f,
+ 0x4ea4, 0x0374,
+ 0x4ea5, 0x0376,
+ 0x4ea6, 0x0375,
+ 0x4ea8, 0x0416,
+ 0x4eab, 0x052e,
+ 0x4ead, 0x06a4,
+ 0x4eb3, 0x0832,
+ 0x4eb6, 0x2363,
+ 0x4eb7, 0x413c,
+ 0x4eb9, 0x3377,
+ 0x4eba, 0x025b,
+ 0x4ebb, 0x44e6,
+ 0x4ebc, 0x39b1,
+ 0x4ebf, 0x4590,
+ 0x4ec0, 0x02a1,
+ 0x4ec1, 0x02a0,
+ 0x4ec2, 0x177d,
+ 0x4ec3, 0x02a2,
+ 0x4ec4, 0x02a8,
+ 0x4ec6, 0x02a3,
+ 0x4ec8, 0x177f,
+ 0x4ec9, 0x177e,
+ 0x4eca, 0x02a6,
+ 0x4ecd, 0x02a5,
+ 0x4ece, 0x3f62,
+ 0x4ed4, 0x02fa,
+ 0x4ed8, 0x02f9,
+ 0x4ed9, 0x0300,
+ 0x4eda, 0x1795,
+ 0x4edc, 0x1791,
+ 0x4edd, 0x1794,
+ 0x4ede, 0x0301,
+ 0x4edf, 0x0311,
+ 0x4ee1, 0x1793,
+ 0x4ee3, 0x02fe,
+ 0x4ee5, 0x02f8,
+ 0x4ee8, 0x1790,
+ 0x4ee9, 0x1792,
+ 0x4eea, 0x48cb,
+ 0x4eeb, 0x4591,
+ 0x4eee, 0x3d76,
+ 0x4ef0, 0x0383,
+ 0x4ef1, 0x17ba,
+ 0x4ef2, 0x0380,
+ 0x4ef3, 0x0384,
+ 0x4ef4, 0x17c4,
+ 0x4ef5, 0x17b8,
+ 0x4ef6, 0x0381,
+ 0x4ef7, 0x17bc,
+ 0x4ef8, 0x39ad,
+ 0x4efb, 0x0382,
+ 0x4efd, 0x0385,
+ 0x4eff, 0x0377,
+ 0x4f00, 0x17bb,
+ 0x4f01, 0x0386,
+ 0x4f02, 0x17bf,
+ 0x4f03, 0x39c8,
+ 0x4f04, 0x17c3,
+ 0x4f05, 0x17c0,
+ 0x4f08, 0x17bd,
+ 0x4f09, 0x0378,
+ 0x4f0a, 0x037a,
+ 0x4f0b, 0x0387,
+ 0x4f0d, 0x037c,
+ 0x4f0e, 0x17b5,
+ 0x4f0f, 0x037f,
+ 0x4f10, 0x037d,
+ 0x4f12, 0x17c5,
+ 0x4f13, 0x17c2,
+ 0x4f14, 0x17b9,
+ 0x4f15, 0x037b,
+ 0x4f18, 0x17b6,
+ 0x4f19, 0x0379,
+ 0x4f1a, 0x453c,
+ 0x4f1d, 0x17be,
+ 0x4f22, 0x17c1,
+ 0x4f28, 0x453d,
+ 0x4f29, 0x39be,
+ 0x4f2c, 0x17b7,
+ 0x4f2d, 0x182f,
+ 0x4f2f, 0x042c,
+ 0x4f30, 0x041f,
+ 0x4f32, 0x393d,
+ 0x4f33, 0x1830,
+ 0x4f34, 0x041c,
+ 0x4f36, 0x042e,
+ 0x4f37, 0x4592,
+ 0x4f38, 0x0424,
+ 0x4f39, 0x3f65,
+ 0x4f3a, 0x0423,
+ 0x4f3b, 0x1824,
+ 0x4f3c, 0x0427,
+ 0x4f3d, 0x0422,
+ 0x4f3e, 0x1829,
+ 0x4f3f, 0x1831,
+ 0x4f41, 0x182d,
+ 0x4f42, 0x39cb,
+ 0x4f43, 0x0425,
+ 0x4f45, 0x3b8f,
+ 0x4f46, 0x0428,
+ 0x4f47, 0x0419,
+ 0x4f48, 0x0431,
+ 0x4f49, 0x1826,
+ 0x4f4b, 0x39b4,
+ 0x4f4c, 0x1900,
+ 0x4f4d, 0x0417,
+ 0x4f4e, 0x042d,
+ 0x4f4f, 0x0418,
+ 0x4f50, 0x0420,
+ 0x4f52, 0x182b,
+ 0x4f53, 0x1827,
+ 0x4f54, 0x0426,
+ 0x4f55, 0x041e,
+ 0x4f56, 0x1823,
+ 0x4f57, 0x041a,
+ 0x4f58, 0x182e,
+ 0x4f59, 0x042f,
+ 0x4f5a, 0x0432,
+ 0x4f5b, 0x041d,
+ 0x4f5c, 0x042a,
+ 0x4f5d, 0x0430,
+ 0x4f5e, 0x041b,
+ 0x4f5f, 0x182c,
+ 0x4f60, 0x042b,
+ 0x4f61, 0x1832,
+ 0x4f62, 0x1825,
+ 0x4f63, 0x0429,
+ 0x4f64, 0x1828,
+ 0x4f67, 0x182a,
+ 0x4f69, 0x053d,
+ 0x4f6a, 0x1902,
+ 0x4f6b, 0x190e,
+ 0x4f6c, 0x0535,
+ 0x4f6e, 0x190f,
+ 0x4f6f, 0x0530,
+ 0x4f70, 0x053a,
+ 0x4f72, 0x3c72,
+ 0x4f73, 0x0533,
+ 0x4f74, 0x18fc,
+ 0x4f75, 0x053b,
+ 0x4f76, 0x18fb,
+ 0x4f77, 0x18ff,
+ 0x4f78, 0x1906,
+ 0x4f79, 0x1904,
+ 0x4f7a, 0x0543,
+ 0x4f7b, 0x053e,
+ 0x4f7c, 0x18f6,
+ 0x4f7d, 0x18f8,
+ 0x4f7e, 0x0540,
+ 0x4f7f, 0x0534,
+ 0x4f80, 0x18f9,
+ 0x4f81, 0x1905,
+ 0x4f82, 0x190c,
+ 0x4f83, 0x0539,
+ 0x4f84, 0x18fe,
+ 0x4f85, 0x18f7,
+ 0x4f86, 0x0538,
+ 0x4f87, 0x18fa,
+ 0x4f88, 0x053c,
+ 0x4f89, 0x18fd,
+ 0x4f8a, 0x39b5,
+ 0x4f8b, 0x0537,
+ 0x4f8d, 0x0532,
+ 0x4f8f, 0x0541,
+ 0x4f90, 0x1907,
+ 0x4f91, 0x0542,
+ 0x4f92, 0x190b,
+ 0x4f94, 0x1909,
+ 0x4f95, 0x190d,
+ 0x4f96, 0x053f,
+ 0x4f97, 0x1901,
+ 0x4f98, 0x18f5,
+ 0x4f9a, 0x1903,
+ 0x4f9b, 0x0536,
+ 0x4f9c, 0x1908,
+ 0x4f9d, 0x0531,
+ 0x4f9e, 0x190a,
+ 0x4fa2, 0x39c7,
+ 0x4fa8, 0x453e,
+ 0x4fab, 0x4022,
+ 0x4fae, 0x06b4,
+ 0x4faf, 0x06a8,
+ 0x4fb0, 0x3d4a,
+ 0x4fb2, 0x1a5d,
+ 0x4fb3, 0x1a65,
+ 0x4fb5, 0x06a7,
+ 0x4fb6, 0x06af,
+ 0x4fb7, 0x06bb,
+ 0x4fb9, 0x1a6b,
+ 0x4fba, 0x1a69,
+ 0x4fbb, 0x1a64,
+ 0x4fbd, 0x4594,
+ 0x4fbf, 0x06a9,
+ 0x4fc0, 0x1a6a,
+ 0x4fc1, 0x1a60,
+ 0x4fc2, 0x06b7,
+ 0x4fc3, 0x06ae,
+ 0x4fc4, 0x06b6,
+ 0x4fc5, 0x1a5b,
+ 0x4fc7, 0x1a67,
+ 0x4fc8, 0x46e8,
+ 0x4fc9, 0x1a5e,
+ 0x4fca, 0x06b2,
+ 0x4fcb, 0x1a5f,
+ 0x4fcc, 0x39cf,
+ 0x4fcd, 0x1a5a,
+ 0x4fce, 0x06b9,
+ 0x4fcf, 0x06ac,
+ 0x4fd0, 0x06b5,
+ 0x4fd1, 0x06ab,
+ 0x4fd3, 0x1a5c,
+ 0x4fd4, 0x1a61,
+ 0x4fd6, 0x1a68,
+ 0x4fd7, 0x06b3,
+ 0x4fd8, 0x06b0,
+ 0x4fd9, 0x1a63,
+ 0x4fda, 0x06b8,
+ 0x4fdb, 0x1a66,
+ 0x4fdc, 0x1a62,
+ 0x4fdd, 0x06ad,
+ 0x4fde, 0x06ba,
+ 0x4fdf, 0x06b1,
+ 0x4fe0, 0x06aa,
+ 0x4fe1, 0x06a6,
+ 0x4fe4, 0x3c66,
+ 0x4fe5, 0x39d0,
+ 0x4fec, 0x1a6c,
+ 0x4fee, 0x084c,
+ 0x4fef, 0x0836,
+ 0x4ff1, 0x0846,
+ 0x4ff2, 0x3f28,
+ 0x4ff3, 0x084b,
+ 0x4ff4, 0x1c24,
+ 0x4ff5, 0x1c23,
+ 0x4ff6, 0x1c28,
+ 0x4ff8, 0x0839,
+ 0x4ff9, 0x37b3,
+ 0x4ffa, 0x0842,
+ 0x4ffd, 0x3f26,
+ 0x4ffe, 0x084f,
+ 0x5000, 0x0843,
+ 0x5003, 0x4596,
+ 0x5005, 0x1c1d,
+ 0x5006, 0x083c,
+ 0x5007, 0x1c1e,
+ 0x5008, 0x4024,
+ 0x5009, 0x0851,
+ 0x500b, 0x0848,
+ 0x500c, 0x0833,
+ 0x500e, 0x1c31,
+ 0x500f, 0x0a0c,
+ 0x5011, 0x0841,
+ 0x5012, 0x0840,
+ 0x5013, 0x1c1f,
+ 0x5014, 0x0844,
+ 0x5015, 0x1e45,
+ 0x5016, 0x083b,
+ 0x5017, 0x1c2a,
+ 0x5018, 0x084a,
+ 0x5019, 0x0849,
+ 0x501a, 0x083f,
+ 0x501b, 0x1c22,
+ 0x501c, 0x1c2b,
+ 0x501e, 0x1c1c,
+ 0x501f, 0x083e,
+ 0x5020, 0x1c2c,
+ 0x5021, 0x0847,
+ 0x5022, 0x1c20,
+ 0x5023, 0x0835,
+ 0x5025, 0x0838,
+ 0x5026, 0x0837,
+ 0x5027, 0x1c2d,
+ 0x5028, 0x0845,
+ 0x5029, 0x083a,
+ 0x502a, 0x084e,
+ 0x502b, 0x0850,
+ 0x502c, 0x1c27,
+ 0x502d, 0x084d,
+ 0x502e, 0x39cc,
+ 0x502f, 0x1c2f,
+ 0x5030, 0x1c21,
+ 0x5031, 0x1c30,
+ 0x5033, 0x1c25,
+ 0x5034, 0x3910,
+ 0x5035, 0x1c2e,
+ 0x5037, 0x1c26,
+ 0x503c, 0x083d,
+ 0x5040, 0x1e4d,
+ 0x5041, 0x1e41,
+ 0x5043, 0x0a00,
+ 0x5045, 0x1e46,
+ 0x5046, 0x1e4c,
+ 0x5047, 0x09ff,
+ 0x5048, 0x1e3f,
+ 0x5049, 0x0a03,
+ 0x504a, 0x1e43,
+ 0x504b, 0x1e3c,
+ 0x504c, 0x0a01,
+ 0x504d, 0x1e40,
+ 0x504e, 0x0a06,
+ 0x504f, 0x0a0b,
+ 0x5051, 0x1e51,
+ 0x5053, 0x1e3b,
+ 0x5055, 0x0a07,
+ 0x5056, 0x3f2c,
+ 0x5057, 0x1e50,
+ 0x5058, 0x39d1,
+ 0x505a, 0x0a02,
+ 0x505b, 0x1e42,
+ 0x505c, 0x09fe,
+ 0x505d, 0x1e3d,
+ 0x505e, 0x1e39,
+ 0x505f, 0x1e47,
+ 0x5060, 0x1e3a,
+ 0x5061, 0x1e38,
+ 0x5062, 0x1e44,
+ 0x5063, 0x1e4a,
+ 0x5065, 0x0a04,
+ 0x5066, 0x3dc9,
+ 0x5068, 0x20b8,
+ 0x5069, 0x1e48,
+ 0x506a, 0x1e37,
+ 0x506b, 0x1e49,
+ 0x506c, 0x39cd,
+ 0x506d, 0x0a0e,
+ 0x506e, 0x1e4e,
+ 0x506f, 0x0a0d,
+ 0x5070, 0x1e36,
+ 0x5072, 0x1e3e,
+ 0x5073, 0x1e4f,
+ 0x5074, 0x0a09,
+ 0x5075, 0x0a08,
+ 0x5076, 0x0a05,
+ 0x5077, 0x0a0a,
+ 0x507a, 0x09fc,
+ 0x507d, 0x09fd,
+ 0x5080, 0x0bec,
+ 0x5081, 0x39ce,
+ 0x5082, 0x20bb,
+ 0x5083, 0x20b4,
+ 0x5085, 0x0be9,
+ 0x5087, 0x20bc,
+ 0x5088, 0x439c,
+ 0x508b, 0x20b2,
+ 0x508c, 0x20b5,
+ 0x508d, 0x0be8,
+ 0x508e, 0x20b6,
+ 0x5090, 0x41ec,
+ 0x5091, 0x0beb,
+ 0x5092, 0x20ba,
+ 0x5094, 0x20b0,
+ 0x5095, 0x20af,
+ 0x5096, 0x0bed,
+ 0x5098, 0x0bee,
+ 0x5099, 0x0bea,
+ 0x509a, 0x0bef,
+ 0x509b, 0x20ae,
+ 0x509c, 0x20b9,
+ 0x509d, 0x20b7,
+ 0x509e, 0x20b1,
+ 0x50a2, 0x0be7,
+ 0x50a3, 0x20b3,
+ 0x50a6, 0x3f3f,
+ 0x50ac, 0x0dc5,
+ 0x50ad, 0x0dbf,
+ 0x50ae, 0x2367,
+ 0x50af, 0x0dc8,
+ 0x50b0, 0x236d,
+ 0x50b1, 0x2370,
+ 0x50b2, 0x0dc1,
+ 0x50b4, 0x236a,
+ 0x50b5, 0x0dc0,
+ 0x50b6, 0x2373,
+ 0x50b7, 0x0dc6,
+ 0x50b8, 0x2374,
+ 0x50ba, 0x236f,
+ 0x50bb, 0x0dc7,
+ 0x50bd, 0x2364,
+ 0x50be, 0x0dc4,
+ 0x50bf, 0x2365,
+ 0x50c1, 0x236e,
+ 0x50c2, 0x236c,
+ 0x50c4, 0x2368,
+ 0x50c5, 0x0dc3,
+ 0x50c6, 0x2366,
+ 0x50c7, 0x0dc9,
+ 0x50c8, 0x236b,
+ 0x50c9, 0x2372,
+ 0x50ca, 0x2369,
+ 0x50cb, 0x2371,
+ 0x50cd, 0x39c5,
+ 0x50ce, 0x0f88,
+ 0x50cf, 0x0f85,
+ 0x50d0, 0x38d1,
+ 0x50d1, 0x0f86,
+ 0x50d3, 0x261c,
+ 0x50d4, 0x2614,
+ 0x50d5, 0x0f84,
+ 0x50d6, 0x0f81,
+ 0x50d7, 0x2615,
+ 0x50d9, 0x3fce,
+ 0x50da, 0x0f83,
+ 0x50db, 0x2618,
+ 0x50dd, 0x261a,
+ 0x50de, 0x4031,
+ 0x50df, 0x3afd,
+ 0x50e0, 0x2621,
+ 0x50e1, 0x4171,
+ 0x50e3, 0x2620,
+ 0x50e4, 0x261b,
+ 0x50e5, 0x0f80,
+ 0x50e6, 0x2613,
+ 0x50e7, 0x0f7e,
+ 0x50e8, 0x2616,
+ 0x50e9, 0x0f89,
+ 0x50ea, 0x2619,
+ 0x50ec, 0x261d,
+ 0x50ed, 0x0f82,
+ 0x50ee, 0x0f7f,
+ 0x50ef, 0x261f,
+ 0x50f0, 0x261e,
+ 0x50f1, 0x0f87,
+ 0x50f3, 0x2617,
+ 0x50f4, 0x3ce9,
+ 0x50f5, 0x1105,
+ 0x50f6, 0x2883,
+ 0x50f8, 0x2880,
+ 0x50f9, 0x1106,
+ 0x50fb, 0x1104,
+ 0x50fc, 0x39d2,
+ 0x50fd, 0x2887,
+ 0x50fe, 0x2884,
+ 0x50ff, 0x287d,
+ 0x5100, 0x1103,
+ 0x5101, 0x4032,
+ 0x5102, 0x1107,
+ 0x5103, 0x287e,
+ 0x5104, 0x1102,
+ 0x5105, 0x110a,
+ 0x5106, 0x2881,
+ 0x5108, 0x1108,
+ 0x510a, 0x2888,
+ 0x510b, 0x2885,
+ 0x510d, 0x39c6,
+ 0x510e, 0x4034,
+ 0x5110, 0x128d,
+ 0x5111, 0x2b04,
+ 0x5112, 0x128a,
+ 0x5113, 0x2b01,
+ 0x5114, 0x128c,
+ 0x5115, 0x128e,
+ 0x5117, 0x2b02,
+ 0x5118, 0x128b,
+ 0x511a, 0x2b03,
+ 0x511c, 0x2b00,
+ 0x511f, 0x13b5,
+ 0x5120, 0x2d3e,
+ 0x5121, 0x13b6,
+ 0x5122, 0x2d3c,
+ 0x5124, 0x2d3d,
+ 0x5125, 0x2d3b,
+ 0x5126, 0x2d3a,
+ 0x5129, 0x2d3f,
+ 0x512a, 0x13b4,
+ 0x512b, 0x39ae,
+ 0x512d, 0x2f0f,
+ 0x5130, 0x287f,
+ 0x5131, 0x2f0e,
+ 0x5132, 0x13b7,
+ 0x5133, 0x1575,
+ 0x5134, 0x307a,
+ 0x5137, 0x1668,
+ 0x5139, 0x32c6,
+ 0x513a, 0x32c5,
+ 0x513b, 0x16bc,
+ 0x513c, 0x16bb,
+ 0x513d, 0x340e,
+ 0x513f, 0x025c,
+ 0x5140, 0x0274,
+ 0x5141, 0x02aa,
+ 0x5143, 0x02a9,
+ 0x5144, 0x0303,
+ 0x5145, 0x0302,
+ 0x5146, 0x038a,
+ 0x5147, 0x0389,
+ 0x5148, 0x038b,
+ 0x5149, 0x0388,
+ 0x514b, 0x0434,
+ 0x514c, 0x0433,
+ 0x514d, 0x0435,
+ 0x5152, 0x0545,
+ 0x5154, 0x0544,
+ 0x5155, 0x0546,
+ 0x5156, 0x439a,
+ 0x5157, 0x06bc,
+ 0x5159, 0x0119,
+ 0x515a, 0x1c32,
+ 0x515b, 0x011a,
+ 0x515c, 0x0a0f,
+ 0x515d, 0x011c,
+ 0x515e, 0x011b,
+ 0x515f, 0x20bd,
+ 0x5160, 0x403a,
+ 0x5161, 0x011d,
+ 0x5162, 0x0f8a,
+ 0x5163, 0x011e,
+ 0x5165, 0x025d,
+ 0x5167, 0x02ab,
+ 0x5168, 0x038c,
+ 0x5169, 0x0547,
+ 0x516a, 0x403c,
+ 0x516b, 0x025e,
+ 0x516c, 0x02ae,
+ 0x516d, 0x02ac,
+ 0x5171, 0x038d,
+ 0x5174, 0x453f,
+ 0x5175, 0x0436,
+ 0x5176, 0x0549,
+ 0x5177, 0x0548,
+ 0x5178, 0x054a,
+ 0x5179, 0x3ace,
+ 0x517c, 0x0852,
+ 0x5180, 0x128f,
+ 0x5182, 0x021d,
+ 0x5186, 0x439f,
+ 0x5187, 0x1779,
+ 0x5188, 0x36b6,
+ 0x5189, 0x0304,
+ 0x518d, 0x038e,
+ 0x518f, 0x1833,
+ 0x5191, 0x06be,
+ 0x5192, 0x06bd,
+ 0x5193, 0x1c34,
+ 0x5194, 0x1c33,
+ 0x5195, 0x0a10,
+ 0x5196, 0x021e,
+ 0x5197, 0x02af,
+ 0x5198, 0x1780,
+ 0x519a, 0x3ea3,
+ 0x519c, 0x4540,
+ 0x519e, 0x1910,
+ 0x51a0, 0x06bf,
+ 0x51a2, 0x0855,
+ 0x51a4, 0x0853,
+ 0x51a7, 0x3ea6,
+ 0x51a8, 0x39da,
+ 0x51aa, 0x1290,
+ 0x51ab, 0x021f,
+ 0x51ac, 0x0306,
+ 0x51b0, 0x038f,
+ 0x51b1, 0x17c6,
+ 0x51b2, 0x4048,
+ 0x51b3, 0x4051,
+ 0x51b4, 0x3d7c,
+ 0x51b5, 0x4012,
+ 0x51b6, 0x0437,
+ 0x51b8, 0x4049,
+ 0x51b9, 0x1834,
+ 0x51bc, 0x1911,
+ 0x51bd, 0x054b,
+ 0x51be, 0x1912,
+ 0x51c3, 0x39db,
+ 0x51c4, 0x1c36,
+ 0x51c6, 0x0858,
+ 0x51c7, 0x422a,
+ 0x51c8, 0x1c38,
+ 0x51c9, 0x404b,
+ 0x51ca, 0x1c35,
+ 0x51cb, 0x0859,
+ 0x51cc, 0x0857,
+ 0x51cd, 0x0856,
+ 0x51ce, 0x1c39,
+ 0x51cf, 0x404c,
+ 0x51d0, 0x1e52,
+ 0x51d1, 0x404d,
+ 0x51d2, 0x3dad,
+ 0x51d3, 0x404f,
+ 0x51d4, 0x20be,
+ 0x51d7, 0x2375,
+ 0x51d8, 0x2622,
+ 0x51db, 0x459a,
+ 0x51dc, 0x110b,
+ 0x51dd, 0x1291,
+ 0x51de, 0x2b05,
+ 0x51df, 0x424f,
+ 0x51e0, 0x025f,
+ 0x51e1, 0x026d,
+ 0x51e2, 0x4052,
+ 0x51e4, 0x4541,
+ 0x51ed, 0x4054,
+ 0x51f0, 0x0a11,
+ 0x51f1, 0x0bf1,
+ 0x51f3, 0x0f8b,
+ 0x51f4, 0x4178,
+ 0x51f5, 0x176e,
+ 0x51f6, 0x02b0,
+ 0x51f8, 0x0309,
+ 0x51f9, 0x0307,
+ 0x51fc, 0x459b,
+ 0x51fd, 0x054c,
+ 0x51fe, 0x3f0a,
+ 0x5200, 0x0260,
+ 0x5202, 0x36b3,
+ 0x5203, 0x0275,
+ 0x5205, 0x43a1,
+ 0x5206, 0x02b1,
+ 0x5209, 0x1797,
+ 0x520a, 0x030a,
+ 0x520b, 0x4059,
+ 0x520c, 0x1796,
+ 0x520e, 0x0393,
+ 0x5210, 0x17c8,
+ 0x5211, 0x0391,
+ 0x5213, 0x17c7,
+ 0x5216, 0x0394,
+ 0x5217, 0x0390,
+ 0x521c, 0x1835,
+ 0x521d, 0x068b,
+ 0x521e, 0x1836,
+ 0x521f, 0x3f60,
+ 0x5220, 0x4930,
+ 0x5221, 0x1837,
+ 0x5224, 0x043a,
+ 0x5225, 0x0439,
+ 0x5226, 0x405a,
+ 0x5227, 0x43a2,
+ 0x5228, 0x043d,
+ 0x5229, 0x043b,
+ 0x522e, 0x0552,
+ 0x5230, 0x0551,
+ 0x5231, 0x1917,
+ 0x5232, 0x1914,
+ 0x5234, 0x3efb,
+ 0x5235, 0x1913,
+ 0x5236, 0x0553,
+ 0x5237, 0x054f,
+ 0x5238, 0x054e,
+ 0x523a, 0x0550,
+ 0x523b, 0x054d,
+ 0x523c, 0x405b,
+ 0x5241, 0x0554,
+ 0x5243, 0x06c1,
+ 0x5244, 0x1a6d,
+ 0x5246, 0x1916,
+ 0x5247, 0x06c6,
+ 0x5249, 0x1a6e,
+ 0x524a, 0x06c2,
+ 0x524b, 0x06c5,
+ 0x524c, 0x06c4,
+ 0x524d, 0x06c3,
+ 0x524e, 0x06c0,
+ 0x5252, 0x1c3c,
+ 0x5254, 0x085c,
+ 0x5255, 0x1c3f,
+ 0x5256, 0x085a,
+ 0x5257, 0x405d,
+ 0x5259, 0x39e4,
+ 0x525a, 0x1c3b,
+ 0x525b, 0x085d,
+ 0x525c, 0x085b,
+ 0x525d, 0x085e,
+ 0x525e, 0x1c3d,
+ 0x5260, 0x3f29,
+ 0x5261, 0x1c3a,
+ 0x5262, 0x1c40,
+ 0x5268, 0x4619,
+ 0x5269, 0x0bf5,
+ 0x526a, 0x0a12,
+ 0x526b, 0x1e53,
+ 0x526c, 0x1e55,
+ 0x526d, 0x1e54,
+ 0x526e, 0x1e56,
+ 0x526f, 0x0a13,
+ 0x5272, 0x0bf2,
+ 0x5273, 0x3f43,
+ 0x5274, 0x0bf3,
+ 0x5277, 0x0dcb,
+ 0x5278, 0x2377,
+ 0x5279, 0x43a3,
+ 0x527a, 0x2376,
+ 0x527b, 0x2378,
+ 0x527d, 0x0dcc,
+ 0x527f, 0x0dca,
+ 0x5280, 0x2623,
+ 0x5282, 0x0f8d,
+ 0x5283, 0x0f8c,
+ 0x5284, 0x2776,
+ 0x5287, 0x110c,
+ 0x528a, 0x1110,
+ 0x528b, 0x2889,
+ 0x528d, 0x110f,
+ 0x528f, 0x3dbf,
+ 0x5290, 0x459d,
+ 0x5291, 0x1292,
+ 0x5293, 0x1293,
+ 0x5294, 0x405e,
+ 0x5296, 0x307c,
+ 0x5297, 0x32c8,
+ 0x5298, 0x32c7,
+ 0x5299, 0x340f,
+ 0x529a, 0x3f68,
+ 0x529b, 0x0262,
+ 0x529f, 0x030c,
+ 0x52a0, 0x030b,
+ 0x52a1, 0x4542,
+ 0x52a3, 0x0395,
+ 0x52a4, 0x39e5,
+ 0x52a6, 0x17c9,
+ 0x52a8, 0x4543,
+ 0x52a9, 0x043f,
+ 0x52ab, 0x043e,
+ 0x52ac, 0x0441,
+ 0x52ad, 0x1838,
+ 0x52b5, 0x405c,
+ 0x52b9, 0x405f,
+ 0x52bb, 0x0556,
+ 0x52bc, 0x1918,
+ 0x52be, 0x0555,
+ 0x52c0, 0x1a6f,
+ 0x52c1, 0x06ca,
+ 0x52c2, 0x1a70,
+ 0x52c3, 0x06c9,
+ 0x52c5, 0x4060,
+ 0x52c7, 0x06c7,
+ 0x52c9, 0x06c8,
+ 0x52cc, 0x3ee1,
+ 0x52cd, 0x1c41,
+ 0x52d0, 0x4109,
+ 0x52d1, 0x3f2a,
+ 0x52d2, 0x0a14,
+ 0x52d3, 0x1e58,
+ 0x52d5, 0x0a17,
+ 0x52d6, 0x1e57,
+ 0x52d7, 0x0acf,
+ 0x52d8, 0x0a16,
+ 0x52d9, 0x0a15,
+ 0x52db, 0x0bf8,
+ 0x52dd, 0x0bf7,
+ 0x52de, 0x0bf6,
+ 0x52df, 0x0dcd,
+ 0x52e0, 0x4063,
+ 0x52e1, 0x39e7,
+ 0x52e2, 0x0dd0,
+ 0x52e4, 0x0dcf,
+ 0x52e6, 0x0dce,
+ 0x52e9, 0x2625,
+ 0x52eb, 0x2626,
+ 0x52ef, 0x288c,
+ 0x52f0, 0x1111,
+ 0x52f1, 0x288b,
+ 0x52f3, 0x1294,
+ 0x52f4, 0x2d40,
+ 0x52f5, 0x13b8,
+ 0x52f7, 0x307d,
+ 0x52f8, 0x1609,
+ 0x52f9, 0x0220,
+ 0x52fa, 0x0276,
+ 0x52fb, 0x02b4,
+ 0x52fc, 0x1781,
+ 0x52fe, 0x02b5,
+ 0x5301, 0x3d79,
+ 0x5305, 0x030d,
+ 0x5308, 0x0396,
+ 0x5309, 0x183a,
+ 0x530a, 0x1919,
+ 0x530d, 0x06cb,
+ 0x530e, 0x1c42,
+ 0x530f, 0x0a19,
+ 0x5310, 0x0a18,
+ 0x5311, 0x20c0,
+ 0x5312, 0x20bf,
+ 0x5315, 0x0263,
+ 0x5316, 0x02b7,
+ 0x5317, 0x030f,
+ 0x5319, 0x0a1a,
+ 0x531a, 0x176f,
+ 0x531c, 0x1798,
+ 0x531d, 0x0310,
+ 0x531f, 0x17cb,
+ 0x5320, 0x0398,
+ 0x5321, 0x0397,
+ 0x5322, 0x17ca,
+ 0x5323, 0x0442,
+ 0x5327, 0x459e,
+ 0x532a, 0x085f,
+ 0x532c, 0x3f36,
+ 0x532d, 0x1e59,
+ 0x532f, 0x0dd2,
+ 0x5330, 0x2627,
+ 0x5331, 0x0f8e,
+ 0x5332, 0x3fd0,
+ 0x5333, 0x406d,
+ 0x5334, 0x2b06,
+ 0x5337, 0x31c7,
+ 0x5338, 0x0221,
+ 0x5339, 0x02b8,
+ 0x533b, 0x4544,
+ 0x533c, 0x191b,
+ 0x533d, 0x1a71,
+ 0x533e, 0x0a1d,
+ 0x533f, 0x0a1b,
+ 0x5341, 0x0264,
+ 0x5342, 0x4947,
+ 0x5343, 0x0277,
+ 0x5344, 0x016b,
+ 0x5345, 0x02bb,
+ 0x5347, 0x02ba,
+ 0x5348, 0x02b9,
+ 0x5349, 0x0313,
+ 0x534a, 0x0312,
+ 0x534c, 0x1799,
+ 0x534d, 0x17cc,
+ 0x534e, 0x4545,
+ 0x5351, 0x055a,
+ 0x5352, 0x0557,
+ 0x5353, 0x0559,
+ 0x5354, 0x0558,
+ 0x5357, 0x06cc,
+ 0x535a, 0x0bf9,
+ 0x535c, 0x0265,
+ 0x535d, 0x4501,
+ 0x535e, 0x02bc,
+ 0x535f, 0x43a7,
+ 0x5360, 0x0315,
+ 0x5361, 0x0314,
+ 0x5363, 0x183b,
+ 0x5364, 0x480a,
+ 0x5366, 0x055b,
+ 0x5367, 0x3ecd,
+ 0x5369, 0x0222,
+ 0x536c, 0x1782,
+ 0x536d, 0x407a,
+ 0x536e, 0x0317,
+ 0x536f, 0x0316,
+ 0x5370, 0x0399,
+ 0x5372, 0x183c,
+ 0x5373, 0x0443,
+ 0x5374, 0x407b,
+ 0x5375, 0x0444,
+ 0x5377, 0x055c,
+ 0x537b, 0x06cd,
+ 0x537c, 0x1a72,
+ 0x537d, 0x4901,
+ 0x537e, 0x407d,
+ 0x537f, 0x0860,
+ 0x5382, 0x1770,
+ 0x5384, 0x02bd,
+ 0x538a, 0x17cd,
+ 0x538e, 0x183d,
+ 0x5392, 0x191c,
+ 0x5393, 0x4082,
+ 0x5394, 0x191d,
+ 0x5396, 0x1a74,
+ 0x5397, 0x1a73,
+ 0x5398, 0x1a76,
+ 0x5399, 0x1a75,
+ 0x539a, 0x06ce,
+ 0x539c, 0x1e5a,
+ 0x539d, 0x0862,
+ 0x539e, 0x1c43,
+ 0x539f, 0x0861,
+ 0x53a0, 0x4084,
+ 0x53a2, 0x3e2b,
+ 0x53a4, 0x20c1,
+ 0x53a5, 0x0bfa,
+ 0x53a6, 0x413b,
+ 0x53a7, 0x20c2,
+ 0x53a8, 0x413e,
+ 0x53a9, 0x45a0,
+ 0x53aa, 0x3fc6,
+ 0x53ab, 0x4085,
+ 0x53ac, 0x2628,
+ 0x53ad, 0x0f8f,
+ 0x53ae, 0x4086,
+ 0x53b0, 0x45a2,
+ 0x53b2, 0x1112,
+ 0x53b4, 0x307e,
+ 0x53b6, 0x0223,
+ 0x53b9, 0x1783,
+ 0x53bb, 0x0318,
+ 0x53c1, 0x408b,
+ 0x53c2, 0x43a6,
+ 0x53c3, 0x0a1e,
+ 0x53c5, 0x408c,
+ 0x53c8, 0x0266,
+ 0x53c9, 0x0278,
+ 0x53ca, 0x02bf,
+ 0x53cb, 0x02be,
+ 0x53cc, 0x38b6,
+ 0x53cd, 0x02c0,
+ 0x53d0, 0x39fa,
+ 0x53d1, 0x4546,
+ 0x53d2, 0x3e3d,
+ 0x53d4, 0x0560,
+ 0x53d6, 0x055f,
+ 0x53d7, 0x0561,
+ 0x53d8, 0x4547,
+ 0x53d9, 0x4090,
+ 0x53da, 0x3f39,
+ 0x53db, 0x06cf,
+ 0x53df, 0x0863,
+ 0x53e0, 0x4093,
+ 0x53e1, 0x2b07,
+ 0x53e2, 0x14c9,
+ 0x53e3, 0x0279,
+ 0x53e4, 0x031a,
+ 0x53e5, 0x0329,
+ 0x53e6, 0x0324,
+ 0x53e8, 0x031f,
+ 0x53e9, 0x031e,
+ 0x53ea, 0x0325,
+ 0x53eb, 0x0323,
+ 0x53ec, 0x031c,
+ 0x53ed, 0x032a,
+ 0x53ee, 0x031d,
+ 0x53ef, 0x0319,
+ 0x53f0, 0x0328,
+ 0x53f1, 0x0327,
+ 0x53f2, 0x0326,
+ 0x53f3, 0x031b,
+ 0x53f5, 0x0322,
+ 0x53f6, 0x4096,
+ 0x53f7, 0x3808,
+ 0x53f8, 0x0321,
+ 0x53fb, 0x032b,
+ 0x53fc, 0x0320,
+ 0x53fe, 0x40c1,
+ 0x5401, 0x03a0,
+ 0x5403, 0x03a6,
+ 0x5404, 0x03a2,
+ 0x5406, 0x03a8,
+ 0x5407, 0x17ce,
+ 0x5408, 0x03a5,
+ 0x5409, 0x039b,
+ 0x540a, 0x039e,
+ 0x540b, 0x03a1,
+ 0x540c, 0x039d,
+ 0x540d, 0x03a4,
+ 0x540e, 0x03a7,
+ 0x540f, 0x039c,
+ 0x5410, 0x039f,
+ 0x5411, 0x03a3,
+ 0x5412, 0x03a9,
+ 0x5413, 0x4098,
+ 0x5414, 0x3c77,
+ 0x5416, 0x3e7f,
+ 0x5418, 0x1847,
+ 0x5419, 0x1844,
+ 0x541a, 0x3e64,
+ 0x541b, 0x0451,
+ 0x541c, 0x1845,
+ 0x541d, 0x0445,
+ 0x541e, 0x0447,
+ 0x541f, 0x045f,
+ 0x5420, 0x045a,
+ 0x5421, 0x4203,
+ 0x5423, 0x45a3,
+ 0x5424, 0x184c,
+ 0x5425, 0x1846,
+ 0x5426, 0x0449,
+ 0x5427, 0x044b,
+ 0x5428, 0x184b,
+ 0x5429, 0x0452,
+ 0x542a, 0x1841,
+ 0x542b, 0x045e,
+ 0x542c, 0x0460,
+ 0x542d, 0x0446,
+ 0x542e, 0x0457,
+ 0x542f, 0x40ac,
+ 0x5430, 0x183f,
+ 0x5431, 0x045d,
+ 0x5432, 0x3e75,
+ 0x5433, 0x044e,
+ 0x5435, 0x0458,
+ 0x5437, 0x1840,
+ 0x5438, 0x0456,
+ 0x5439, 0x0454,
+ 0x543b, 0x0455,
+ 0x543c, 0x045b,
+ 0x543d, 0x1848,
+ 0x543e, 0x0448,
+ 0x5440, 0x045c,
+ 0x5441, 0x184a,
+ 0x5442, 0x0450,
+ 0x5443, 0x044d,
+ 0x5445, 0x1843,
+ 0x5446, 0x044c,
+ 0x5447, 0x184d,
+ 0x5448, 0x044f,
+ 0x544a, 0x0453,
+ 0x544b, 0x3ed1,
+ 0x544d, 0x3ea7,
+ 0x544e, 0x044a,
+ 0x544f, 0x1849,
+ 0x5454, 0x1842,
+ 0x5460, 0x192e,
+ 0x5461, 0x192d,
+ 0x5462, 0x0573,
+ 0x5463, 0x1930,
+ 0x5464, 0x1932,
+ 0x5465, 0x1927,
+ 0x5466, 0x192a,
+ 0x5467, 0x1931,
+ 0x5468, 0x0574,
+ 0x5469, 0x3f32,
+ 0x546a, 0x3d83,
+ 0x546b, 0x1924,
+ 0x546c, 0x1928,
+ 0x546d, 0x409d,
+ 0x546f, 0x192c,
+ 0x5470, 0x1a85,
+ 0x5471, 0x056f,
+ 0x5472, 0x1a89,
+ 0x5473, 0x0562,
+ 0x5474, 0x1929,
+ 0x5475, 0x0563,
+ 0x5476, 0x0570,
+ 0x5477, 0x0569,
+ 0x5478, 0x0565,
+ 0x547a, 0x1925,
+ 0x547b, 0x0568,
+ 0x547c, 0x056d,
+ 0x547d, 0x0576,
+ 0x547e, 0x1926,
+ 0x547f, 0x191f,
+ 0x5480, 0x0567,
+ 0x5481, 0x1920,
+ 0x5482, 0x1922,
+ 0x5484, 0x056a,
+ 0x5485, 0x46d9,
+ 0x5486, 0x056c,
+ 0x5487, 0x191e,
+ 0x5488, 0x1923,
+ 0x548b, 0x0575,
+ 0x548c, 0x0571,
+ 0x548d, 0x192b,
+ 0x548e, 0x0577,
+ 0x548f, 0x40a1,
+ 0x5490, 0x056e,
+ 0x5491, 0x1921,
+ 0x5492, 0x056b,
+ 0x5493, 0x45a7,
+ 0x5494, 0x3e98,
+ 0x5495, 0x0566,
+ 0x5496, 0x0564,
+ 0x5497, 0x3e8a,
+ 0x5498, 0x192f,
+ 0x549a, 0x0572,
+ 0x549c, 0x3f66,
+ 0x549e, 0x47ed,
+ 0x54a0, 0x1a84,
+ 0x54a1, 0x1a78,
+ 0x54a2, 0x1a87,
+ 0x54a3, 0x45a8,
+ 0x54a4, 0x40a2,
+ 0x54a5, 0x1a7a,
+ 0x54a6, 0x06d6,
+ 0x54a7, 0x06e4,
+ 0x54a8, 0x06d2,
+ 0x54a9, 0x06e3,
+ 0x54aa, 0x06db,
+ 0x54ab, 0x06e0,
+ 0x54ac, 0x06d0,
+ 0x54ad, 0x1a79,
+ 0x54ae, 0x1a7f,
+ 0x54af, 0x06df,
+ 0x54b0, 0x1a8b,
+ 0x54b1, 0x06e1,
+ 0x54b2, 0x3744,
+ 0x54b3, 0x06d7,
+ 0x54b4, 0x45a9,
+ 0x54b6, 0x1a81,
+ 0x54b7, 0x1a7e,
+ 0x54b8, 0x06d5,
+ 0x54b9, 0x45aa,
+ 0x54ba, 0x1a77,
+ 0x54bb, 0x06e2,
+ 0x54bc, 0x1a86,
+ 0x54bd, 0x06da,
+ 0x54be, 0x1a88,
+ 0x54bf, 0x06e5,
+ 0x54c0, 0x06d1,
+ 0x54c1, 0x06dc,
+ 0x54c2, 0x06d9,
+ 0x54c3, 0x1a7c,
+ 0x54c4, 0x06dd,
+ 0x54c5, 0x1a82,
+ 0x54c7, 0x06d8,
+ 0x54c8, 0x06de,
+ 0x54c9, 0x06d4,
+ 0x54cb, 0x39a3,
+ 0x54cc, 0x43a8,
+ 0x54cd, 0x3a00,
+ 0x54ce, 0x06d3,
+ 0x54cf, 0x1a7b,
+ 0x54d0, 0x45ab,
+ 0x54d6, 0x1a80,
+ 0x54da, 0x4923,
+ 0x54de, 0x1a8a,
+ 0x54e0, 0x1c57,
+ 0x54e1, 0x0870,
+ 0x54e2, 0x1c45,
+ 0x54e3, 0x4341,
+ 0x54e4, 0x1c4a,
+ 0x54e5, 0x0869,
+ 0x54e6, 0x0874,
+ 0x54e7, 0x1c48,
+ 0x54e8, 0x0864,
+ 0x54e9, 0x086e,
+ 0x54ea, 0x0873,
+ 0x54eb, 0x1c4f,
+ 0x54ed, 0x086f,
+ 0x54ee, 0x0872,
+ 0x54ef, 0x45ac,
+ 0x54f1, 0x1c52,
+ 0x54f2, 0x086a,
+ 0x54f3, 0x1c49,
+ 0x54f7, 0x1c55,
+ 0x54fa, 0x086c,
+ 0x54fb, 0x1c54,
+ 0x54fc, 0x0868,
+ 0x54fd, 0x0877,
+ 0x54ff, 0x1c4c,
+ 0x5501, 0x0866,
+ 0x5502, 0x3ccc,
+ 0x5503, 0x1c59,
+ 0x5504, 0x1c4d,
+ 0x5505, 0x1c51,
+ 0x5506, 0x086b,
+ 0x5507, 0x0876,
+ 0x5508, 0x1c4e,
+ 0x5509, 0x0871,
+ 0x550a, 0x1c53,
+ 0x550b, 0x1c5a,
+ 0x550c, 0x1e69,
+ 0x550d, 0x3a73,
+ 0x550e, 0x1c58,
+ 0x550f, 0x0878,
+ 0x5510, 0x0865,
+ 0x5511, 0x1c50,
+ 0x5512, 0x1c47,
+ 0x5513, 0x3ea9,
+ 0x5514, 0x086d,
+ 0x5517, 0x1c46,
+ 0x5518, 0x45ad,
+ 0x551a, 0x1c4b,
+ 0x551e, 0x3ea8,
+ 0x5523, 0x45ae,
+ 0x5525, 0x4309,
+ 0x5526, 0x1c44,
+ 0x5527, 0x0875,
+ 0x5528, 0x45af,
+ 0x552a, 0x1e61,
+ 0x552b, 0x409a,
+ 0x552c, 0x0a31,
+ 0x552d, 0x1e6f,
+ 0x552e, 0x0a2f,
+ 0x552f, 0x0a2c,
+ 0x5530, 0x1e66,
+ 0x5531, 0x0a28,
+ 0x5532, 0x1e6a,
+ 0x5533, 0x0a33,
+ 0x5534, 0x1e60,
+ 0x5535, 0x1e65,
+ 0x5536, 0x1e64,
+ 0x5537, 0x0867,
+ 0x5538, 0x0a2e,
+ 0x5539, 0x1e6d,
+ 0x553b, 0x1e70,
+ 0x553c, 0x1e5d,
+ 0x553e, 0x0c0c,
+ 0x553f, 0x43a9,
+ 0x5540, 0x1e71,
+ 0x5541, 0x0a34,
+ 0x5543, 0x0a26,
+ 0x5544, 0x0a23,
+ 0x5545, 0x1e68,
+ 0x5546, 0x0a20,
+ 0x5547, 0x40aa,
+ 0x5548, 0x1e6e,
+ 0x5549, 0x4068,
+ 0x554a, 0x0a27,
+ 0x554b, 0x1e72,
+ 0x554d, 0x1e5e,
+ 0x554e, 0x1e6c,
+ 0x554f, 0x0a2a,
+ 0x5550, 0x1e5f,
+ 0x5551, 0x1e62,
+ 0x5552, 0x1e67,
+ 0x5553, 0x43ae,
+ 0x5555, 0x0a2b,
+ 0x5556, 0x0a29,
+ 0x5557, 0x0a35,
+ 0x555c, 0x0a30,
+ 0x555d, 0x40a0,
+ 0x555e, 0x0a24,
+ 0x555f, 0x0abc,
+ 0x5561, 0x0a25,
+ 0x5562, 0x1e63,
+ 0x5563, 0x0a32,
+ 0x5564, 0x0a2d,
+ 0x5565, 0x1e6b,
+ 0x5566, 0x0a22,
+ 0x5569, 0x3e9f,
+ 0x556a, 0x0a21,
+ 0x556b, 0x3b2e,
+ 0x5571, 0x3bc6,
+ 0x5572, 0x3e8b,
+ 0x5573, 0x3f24,
+ 0x5575, 0x1e5b,
+ 0x5577, 0x20c7,
+ 0x5579, 0x435d,
+ 0x557b, 0x0bfb,
+ 0x557c, 0x0bfe,
+ 0x557d, 0x20d2,
+ 0x557e, 0x0c12,
+ 0x557f, 0x20d5,
+ 0x5580, 0x0bfc,
+ 0x5581, 0x20ce,
+ 0x5582, 0x0c02,
+ 0x5583, 0x0c08,
+ 0x5584, 0x0d1b,
+ 0x5586, 0x40ae,
+ 0x5587, 0x0c06,
+ 0x5588, 0x20cb,
+ 0x5589, 0x0c13,
+ 0x558a, 0x0bff,
+ 0x558b, 0x0c07,
+ 0x558c, 0x20d3,
+ 0x558d, 0x2387,
+ 0x558e, 0x20d8,
+ 0x558f, 0x20cc,
+ 0x5590, 0x430e,
+ 0x5591, 0x20c3,
+ 0x5592, 0x20d0,
+ 0x5593, 0x20ca,
+ 0x5594, 0x0c05,
+ 0x5595, 0x20d6,
+ 0x5598, 0x0c01,
+ 0x5599, 0x0c15,
+ 0x559a, 0x0c0e,
+ 0x559c, 0x0c03,
+ 0x559d, 0x0c00,
+ 0x559f, 0x0c0b,
+ 0x55a1, 0x20d7,
+ 0x55a2, 0x20c9,
+ 0x55a3, 0x20cf,
+ 0x55a4, 0x20d1,
+ 0x55a5, 0x20c5,
+ 0x55a6, 0x20d4,
+ 0x55a7, 0x0bfd,
+ 0x55a8, 0x20c4,
+ 0x55a9, 0x40af,
+ 0x55aa, 0x0c04,
+ 0x55ab, 0x0c14,
+ 0x55ac, 0x0c10,
+ 0x55ad, 0x20c6,
+ 0x55ae, 0x0c0a,
+ 0x55b0, 0x38f5,
+ 0x55b1, 0x0c11,
+ 0x55b2, 0x0c0d,
+ 0x55b3, 0x0c09,
+ 0x55b4, 0x39fe,
+ 0x55b5, 0x20cd,
+ 0x55b9, 0x43aa,
+ 0x55ba, 0x3e89,
+ 0x55bb, 0x0c0f,
+ 0x55bc, 0x3dc3,
+ 0x55bf, 0x2385,
+ 0x55c0, 0x2381,
+ 0x55c1, 0x3e4f,
+ 0x55c2, 0x2390,
+ 0x55c3, 0x237a,
+ 0x55c4, 0x2383,
+ 0x55c5, 0x0de0,
+ 0x55c7, 0x0dd9,
+ 0x55c8, 0x238c,
+ 0x55c9, 0x0de3,
+ 0x55ca, 0x237f,
+ 0x55cb, 0x237e,
+ 0x55cc, 0x237c,
+ 0x55cd, 0x238e,
+ 0x55ce, 0x0dd7,
+ 0x55cf, 0x2388,
+ 0x55d0, 0x237d,
+ 0x55d1, 0x0dda,
+ 0x55d2, 0x2386,
+ 0x55d3, 0x0dd5,
+ 0x55d4, 0x2382,
+ 0x55d5, 0x2389,
+ 0x55d6, 0x238b,
+ 0x55d7, 0x45b3,
+ 0x55d8, 0x43ab,
+ 0x55d9, 0x238f,
+ 0x55da, 0x0dde,
+ 0x55db, 0x237b,
+ 0x55dc, 0x0dd8,
+ 0x55dd, 0x2380,
+ 0x55de, 0x3e94,
+ 0x55df, 0x0dd3,
+ 0x55e1, 0x0ddf,
+ 0x55e2, 0x238a,
+ 0x55e3, 0x0ddb,
+ 0x55e5, 0x0de2,
+ 0x55e6, 0x0dd6,
+ 0x55e7, 0x011f,
+ 0x55e8, 0x0dd4,
+ 0x55e9, 0x2384,
+ 0x55ea, 0x3e7c,
+ 0x55ec, 0x37d2,
+ 0x55ef, 0x0ddd,
+ 0x55f0, 0x3e88,
+ 0x55f1, 0x3e83,
+ 0x55f2, 0x238d,
+ 0x55f5, 0x4786,
+ 0x55f6, 0x0f9f,
+ 0x55f7, 0x0f9a,
+ 0x55f9, 0x2637,
+ 0x55fa, 0x2633,
+ 0x55fb, 0x4626,
+ 0x55fc, 0x262d,
+ 0x55fd, 0x0f94,
+ 0x55fe, 0x0f90,
+ 0x55ff, 0x2636,
+ 0x5600, 0x0f91,
+ 0x5601, 0x2630,
+ 0x5602, 0x2632,
+ 0x5604, 0x2635,
+ 0x5605, 0x3e82,
+ 0x5606, 0x0f96,
+ 0x5608, 0x0f9d,
+ 0x5609, 0x0f97,
+ 0x560c, 0x262b,
+ 0x560d, 0x0f98,
+ 0x560f, 0x262e,
+ 0x5610, 0x0f9e,
+ 0x5611, 0x3f4d,
+ 0x5612, 0x262c,
+ 0x5613, 0x2631,
+ 0x5614, 0x0f95,
+ 0x5615, 0x262a,
+ 0x5616, 0x0f9b,
+ 0x5617, 0x0f93,
+ 0x561b, 0x0f92,
+ 0x561c, 0x262f,
+ 0x561d, 0x2634,
+ 0x561e, 0x3e68,
+ 0x561f, 0x0f9c,
+ 0x5620, 0x3f7d,
+ 0x5621, 0x43ad,
+ 0x5622, 0x3e67,
+ 0x5623, 0x4707,
+ 0x5625, 0x3e78,
+ 0x5627, 0x2629,
+ 0x5629, 0x1119,
+ 0x562a, 0x289d,
+ 0x562c, 0x289a,
+ 0x562d, 0x3e63,
+ 0x562e, 0x1113,
+ 0x562f, 0x111f,
+ 0x5632, 0x1116,
+ 0x5633, 0x2898,
+ 0x5634, 0x1118,
+ 0x5635, 0x2890,
+ 0x5636, 0x111e,
+ 0x5637, 0x40b7,
+ 0x5638, 0x289c,
+ 0x5639, 0x1115,
+ 0x563a, 0x289e,
+ 0x563b, 0x1114,
+ 0x563d, 0x2899,
+ 0x563e, 0x289b,
+ 0x563f, 0x1117,
+ 0x5640, 0x2897,
+ 0x5641, 0x2891,
+ 0x5642, 0x288e,
+ 0x5643, 0x3e7e,
+ 0x5645, 0x20c8,
+ 0x5646, 0x2894,
+ 0x5648, 0x288d,
+ 0x5649, 0x2893,
+ 0x564a, 0x2892,
+ 0x564c, 0x288f,
+ 0x564d, 0x40bc,
+ 0x564e, 0x111b,
+ 0x564f, 0x40bd,
+ 0x5650, 0x47cf,
+ 0x5652, 0x45c2,
+ 0x5653, 0x111a,
+ 0x5654, 0x43af,
+ 0x5657, 0x111c,
+ 0x5658, 0x2895,
+ 0x5659, 0x1295,
+ 0x565a, 0x2896,
+ 0x565d, 0x3ef9,
+ 0x565e, 0x2b10,
+ 0x5660, 0x2b09,
+ 0x5661, 0x3812,
+ 0x5662, 0x12a1,
+ 0x5663, 0x2b0d,
+ 0x5664, 0x1299,
+ 0x5665, 0x129d,
+ 0x5666, 0x2b0c,
+ 0x5668, 0x129c,
+ 0x5669, 0x1298,
+ 0x566a, 0x129b,
+ 0x566b, 0x1296,
+ 0x566c, 0x12a0,
+ 0x566d, 0x2b0e,
+ 0x566e, 0x2b0a,
+ 0x566f, 0x129f,
+ 0x5670, 0x2b08,
+ 0x5671, 0x129e,
+ 0x5672, 0x2b0f,
+ 0x5673, 0x2b0b,
+ 0x5674, 0x111d,
+ 0x5676, 0x12a2,
+ 0x5677, 0x2b11,
+ 0x5678, 0x129a,
+ 0x5679, 0x1297,
+ 0x567a, 0x3d85,
+ 0x567b, 0x3eb7,
+ 0x567c, 0x3eed,
+ 0x567e, 0x2d47,
+ 0x567f, 0x2d49,
+ 0x5680, 0x13ba,
+ 0x5681, 0x2d4a,
+ 0x5682, 0x2d48,
+ 0x5683, 0x2d46,
+ 0x5684, 0x2d45,
+ 0x5685, 0x13bc,
+ 0x5686, 0x2d44,
+ 0x5687, 0x13bd,
+ 0x5689, 0x4628,
+ 0x568a, 0x3949,
+ 0x568b, 0x3e4c,
+ 0x568c, 0x2d42,
+ 0x568e, 0x13b9,
+ 0x568f, 0x13be,
+ 0x5690, 0x13bb,
+ 0x5692, 0x39a6,
+ 0x5693, 0x2d41,
+ 0x5695, 0x14ca,
+ 0x5697, 0x2f13,
+ 0x5698, 0x2f11,
+ 0x5699, 0x2f16,
+ 0x569a, 0x2f14,
+ 0x569c, 0x2f12,
+ 0x569d, 0x2f15,
+ 0x569e, 0x39a4,
+ 0x569f, 0x3948,
+ 0x56a1, 0x436b,
+ 0x56a4, 0x3cc8,
+ 0x56a5, 0x1576,
+ 0x56a6, 0x3081,
+ 0x56a8, 0x1577,
+ 0x56aa, 0x3083,
+ 0x56ab, 0x307f,
+ 0x56ac, 0x3084,
+ 0x56ad, 0x3080,
+ 0x56ae, 0x14cb,
+ 0x56af, 0x45f7,
+ 0x56b1, 0x463f,
+ 0x56b2, 0x31c8,
+ 0x56b3, 0x31ca,
+ 0x56b4, 0x160c,
+ 0x56b5, 0x31c9,
+ 0x56b6, 0x160b,
+ 0x56b7, 0x160a,
+ 0x56b9, 0x486f,
+ 0x56bc, 0x160d,
+ 0x56bd, 0x32ca,
+ 0x56bf, 0x3e5d,
+ 0x56c0, 0x166b,
+ 0x56c1, 0x166a,
+ 0x56c2, 0x166c,
+ 0x56c3, 0x32c9,
+ 0x56c5, 0x3379,
+ 0x56c6, 0x3378,
+ 0x56c8, 0x16bd,
+ 0x56c9, 0x16bf,
+ 0x56ca, 0x16be,
+ 0x56cb, 0x337a,
+ 0x56cc, 0x16f6,
+ 0x56cd, 0x3481,
+ 0x56d1, 0x171f,
+ 0x56d3, 0x3480,
+ 0x56d4, 0x34c9,
+ 0x56d6, 0x488a,
+ 0x56d7, 0x1775,
+ 0x56da, 0x032d,
+ 0x56db, 0x032c,
+ 0x56dd, 0x03ac,
+ 0x56de, 0x03ab,
+ 0x56df, 0x17d0,
+ 0x56e0, 0x03aa,
+ 0x56e1, 0x17cf,
+ 0x56e2, 0x4548,
+ 0x56e4, 0x0463,
+ 0x56e5, 0x1850,
+ 0x56e7, 0x184f,
+ 0x56ea, 0x0461,
+ 0x56eb, 0x0464,
+ 0x56ed, 0x40c4,
+ 0x56ee, 0x184e,
+ 0x56ef, 0x40c3,
+ 0x56f0, 0x0462,
+ 0x56f1, 0x40bf,
+ 0x56f7, 0x1933,
+ 0x56f9, 0x1934,
+ 0x56fa, 0x0578,
+ 0x56fd, 0x3d64,
+ 0x56ff, 0x06e6,
+ 0x5700, 0x40c2,
+ 0x5701, 0x1c5b,
+ 0x5703, 0x0879,
+ 0x5707, 0x1e74,
+ 0x5708, 0x0a36,
+ 0x5709, 0x0a38,
+ 0x570a, 0x1e73,
+ 0x570b, 0x0a37,
+ 0x570c, 0x20d9,
+ 0x570d, 0x0c16,
+ 0x5712, 0x0de4,
+ 0x5714, 0x2391,
+ 0x5715, 0x3e36,
+ 0x5716, 0x0fa1,
+ 0x5718, 0x0fa0,
+ 0x571a, 0x289f,
+ 0x571b, 0x2b13,
+ 0x571c, 0x2b12,
+ 0x571d, 0x3a02,
+ 0x571e, 0x3505,
+ 0x571f, 0x027a,
+ 0x5720, 0x1784,
+ 0x5722, 0x179a,
+ 0x5728, 0x03af,
+ 0x5729, 0x03b3,
+ 0x572a, 0x17d2,
+ 0x572c, 0x03b1,
+ 0x572d, 0x03b0,
+ 0x572e, 0x17d1,
+ 0x572f, 0x03b2,
+ 0x5730, 0x03ae,
+ 0x5732, 0x3af9,
+ 0x5733, 0x03ad,
+ 0x5734, 0x17d3,
+ 0x573b, 0x046e,
+ 0x573e, 0x046b,
+ 0x573f, 0x4855,
+ 0x5740, 0x0467,
+ 0x5741, 0x1851,
+ 0x5742, 0x40cc,
+ 0x5743, 0x40de,
+ 0x5745, 0x1852,
+ 0x5746, 0x40c8,
+ 0x5747, 0x0469,
+ 0x5749, 0x1854,
+ 0x574a, 0x0465,
+ 0x574b, 0x1855,
+ 0x574c, 0x1853,
+ 0x574d, 0x0468,
+ 0x574e, 0x046a,
+ 0x574f, 0x046d,
+ 0x5750, 0x046c,
+ 0x5751, 0x0466,
+ 0x5752, 0x1856,
+ 0x5754, 0x4785,
+ 0x5757, 0x47e6,
+ 0x575b, 0x3982,
+ 0x575f, 0x3fbf,
+ 0x5761, 0x057d,
+ 0x5762, 0x1941,
+ 0x5764, 0x057f,
+ 0x5766, 0x057e,
+ 0x5767, 0x3f2b,
+ 0x5768, 0x1942,
+ 0x5769, 0x057c,
+ 0x576a, 0x057b,
+ 0x576b, 0x1938,
+ 0x576d, 0x1937,
+ 0x576f, 0x1935,
+ 0x5770, 0x193a,
+ 0x5771, 0x1939,
+ 0x5772, 0x1936,
+ 0x5773, 0x193f,
+ 0x5775, 0x193d,
+ 0x5776, 0x193b,
+ 0x5777, 0x057a,
+ 0x577a, 0x3f5f,
+ 0x577b, 0x193e,
+ 0x577c, 0x0580,
+ 0x577d, 0x1943,
+ 0x577e, 0x46dc,
+ 0x577f, 0x3a07,
+ 0x5780, 0x193c,
+ 0x5782, 0x06e7,
+ 0x5783, 0x0579,
+ 0x5788, 0x484b,
+ 0x578a, 0x3c7b,
+ 0x578b, 0x06e8,
+ 0x578c, 0x1a90,
+ 0x578d, 0x3a06,
+ 0x578f, 0x1a96,
+ 0x5790, 0x4166,
+ 0x5793, 0x06ee,
+ 0x5794, 0x1a94,
+ 0x5795, 0x1a9a,
+ 0x5797, 0x1a91,
+ 0x5798, 0x1a95,
+ 0x5799, 0x1a97,
+ 0x579a, 0x1a99,
+ 0x579b, 0x1a93,
+ 0x579c, 0x4608,
+ 0x579d, 0x1a92,
+ 0x579e, 0x1a8d,
+ 0x57a0, 0x06e9,
+ 0x57a1, 0x4864,
+ 0x57a2, 0x06eb,
+ 0x57a3, 0x06ea,
+ 0x57a4, 0x1a8f,
+ 0x57a5, 0x1a98,
+ 0x57a7, 0x4914,
+ 0x57aa, 0x4905,
+ 0x57ae, 0x06ed,
+ 0x57b4, 0x4741,
+ 0x57b5, 0x1a8c,
+ 0x57b6, 0x1c66,
+ 0x57b8, 0x1c65,
+ 0x57b9, 0x1c6a,
+ 0x57ba, 0x1c61,
+ 0x57bb, 0x3c79,
+ 0x57bc, 0x1c64,
+ 0x57bd, 0x1c63,
+ 0x57be, 0x372c,
+ 0x57bf, 0x1c67,
+ 0x57c1, 0x1c6b,
+ 0x57c2, 0x087b,
+ 0x57c3, 0x087e,
+ 0x57c4, 0x3b5b,
+ 0x57c6, 0x1c62,
+ 0x57c7, 0x1c68,
+ 0x57c8, 0x3d0b,
+ 0x57cb, 0x087d,
+ 0x57cc, 0x1c5d,
+ 0x57ce, 0x06ec,
+ 0x57cf, 0x1e82,
+ 0x57d0, 0x1c69,
+ 0x57d2, 0x1c60,
+ 0x57d4, 0x087c,
+ 0x57d5, 0x1c5f,
+ 0x57d7, 0x3c7d,
+ 0x57dc, 0x1e79,
+ 0x57dd, 0x3a05,
+ 0x57de, 0x3f01,
+ 0x57df, 0x0a39,
+ 0x57e0, 0x0a3d,
+ 0x57e1, 0x1e89,
+ 0x57e2, 0x1e77,
+ 0x57e3, 0x1e85,
+ 0x57e4, 0x0a3e,
+ 0x57e5, 0x1e87,
+ 0x57e6, 0x40cf,
+ 0x57e7, 0x1e8d,
+ 0x57e9, 0x1e91,
+ 0x57ec, 0x1e88,
+ 0x57ed, 0x1e7c,
+ 0x57ee, 0x1e84,
+ 0x57ef, 0x4754,
+ 0x57f0, 0x1e92,
+ 0x57f1, 0x1e90,
+ 0x57f2, 0x1e86,
+ 0x57f3, 0x1e81,
+ 0x57f4, 0x1e7a,
+ 0x57f5, 0x20e1,
+ 0x57f6, 0x1e78,
+ 0x57f7, 0x0a42,
+ 0x57f8, 0x1e7f,
+ 0x57f9, 0x0a43,
+ 0x57fa, 0x0a3f,
+ 0x57fb, 0x1e75,
+ 0x57fc, 0x1e8b,
+ 0x57fd, 0x1e7d,
+ 0x57fe, 0x408f,
+ 0x5800, 0x1e7b,
+ 0x5801, 0x1e8e,
+ 0x5802, 0x0a40,
+ 0x5803, 0x40d1,
+ 0x5804, 0x1e94,
+ 0x5805, 0x0a3a,
+ 0x5806, 0x0a3c,
+ 0x5807, 0x1e83,
+ 0x5808, 0x1e7e,
+ 0x5809, 0x087f,
+ 0x580a, 0x0a3b,
+ 0x580b, 0x1e80,
+ 0x580c, 0x1e8f,
+ 0x580d, 0x1e93,
+ 0x580e, 0x1e8a,
+ 0x5810, 0x1e8c,
+ 0x5812, 0x3d0a,
+ 0x5814, 0x1e76,
+ 0x5819, 0x20dc,
+ 0x581b, 0x20e5,
+ 0x581c, 0x20e4,
+ 0x581d, 0x0c1e,
+ 0x581e, 0x20dd,
+ 0x5820, 0x0c1f,
+ 0x5821, 0x0c1d,
+ 0x5822, 0x3c28,
+ 0x5823, 0x20df,
+ 0x5824, 0x0c1a,
+ 0x5825, 0x20e3,
+ 0x5826, 0x40d4,
+ 0x5827, 0x20de,
+ 0x5828, 0x20e0,
+ 0x5829, 0x20da,
+ 0x582a, 0x0c18,
+ 0x582c, 0x20ed,
+ 0x582d, 0x20ec,
+ 0x582e, 0x20e9,
+ 0x582f, 0x0c17,
+ 0x5830, 0x0c1b,
+ 0x5832, 0x1c5e,
+ 0x5833, 0x20e6,
+ 0x5834, 0x0c19,
+ 0x5835, 0x0a41,
+ 0x5836, 0x20e8,
+ 0x5837, 0x20db,
+ 0x5838, 0x20eb,
+ 0x5839, 0x20ea,
+ 0x583a, 0x3d72,
+ 0x583b, 0x20ee,
+ 0x583d, 0x239f,
+ 0x583f, 0x20e7,
+ 0x5840, 0x3d82,
+ 0x5844, 0x47bb,
+ 0x5847, 0x3ac2,
+ 0x5848, 0x20e2,
+ 0x5849, 0x2397,
+ 0x584a, 0x0def,
+ 0x584b, 0x0df2,
+ 0x584c, 0x0ded,
+ 0x584d, 0x2396,
+ 0x584e, 0x239a,
+ 0x584f, 0x2395,
+ 0x5851, 0x0de7,
+ 0x5852, 0x0df1,
+ 0x5853, 0x2392,
+ 0x5854, 0x0deb,
+ 0x5855, 0x2399,
+ 0x5857, 0x0de9,
+ 0x5858, 0x0de8,
+ 0x5859, 0x239c,
+ 0x585a, 0x0dea,
+ 0x585b, 0x239e,
+ 0x585c, 0x4949,
+ 0x585d, 0x239b,
+ 0x585e, 0x0de6,
+ 0x585f, 0x43df,
+ 0x5862, 0x0df0,
+ 0x5863, 0x23a0,
+ 0x5864, 0x2394,
+ 0x5865, 0x239d,
+ 0x5868, 0x2393,
+ 0x5869, 0x3d65,
+ 0x586b, 0x0dec,
+ 0x586c, 0x399a,
+ 0x586d, 0x0dee,
+ 0x586f, 0x2398,
+ 0x5871, 0x23a1,
+ 0x5872, 0x3c26,
+ 0x5873, 0x4355,
+ 0x5874, 0x263f,
+ 0x5875, 0x0fa2,
+ 0x5876, 0x2645,
+ 0x5879, 0x0fa7,
+ 0x587a, 0x2641,
+ 0x587b, 0x2648,
+ 0x587c, 0x2639,
+ 0x587d, 0x0fa9,
+ 0x587e, 0x0fa3,
+ 0x587f, 0x263e,
+ 0x5880, 0x1121,
+ 0x5881, 0x263d,
+ 0x5882, 0x2646,
+ 0x5883, 0x0fa4,
+ 0x5885, 0x0fa8,
+ 0x5886, 0x263c,
+ 0x5887, 0x2642,
+ 0x5888, 0x2647,
+ 0x5889, 0x2638,
+ 0x588a, 0x0fa6,
+ 0x588b, 0x2640,
+ 0x588e, 0x2644,
+ 0x588f, 0x264a,
+ 0x5890, 0x263a,
+ 0x5891, 0x2643,
+ 0x5893, 0x0fa5,
+ 0x5894, 0x2649,
+ 0x5898, 0x263b,
+ 0x5899, 0x4618,
+ 0x589a, 0x4903,
+ 0x589c, 0x1125,
+ 0x589d, 0x28a1,
+ 0x589e, 0x1123,
+ 0x589f, 0x1122,
+ 0x58a0, 0x28a3,
+ 0x58a1, 0x28a8,
+ 0x58a3, 0x28a4,
+ 0x58a5, 0x28a7,
+ 0x58a6, 0x1128,
+ 0x58a7, 0x3eeb,
+ 0x58a8, 0x1288,
+ 0x58a9, 0x1127,
+ 0x58aa, 0x40d7,
+ 0x58ab, 0x28a0,
+ 0x58ac, 0x28a6,
+ 0x58ae, 0x1126,
+ 0x58af, 0x28a5,
+ 0x58b0, 0x37a4,
+ 0x58b1, 0x28a2,
+ 0x58b3, 0x1124,
+ 0x58b5, 0x4840,
+ 0x58b6, 0x3dfd,
+ 0x58ba, 0x2b18,
+ 0x58bb, 0x36eb,
+ 0x58bc, 0x2b1a,
+ 0x58bd, 0x2b15,
+ 0x58be, 0x12a4,
+ 0x58bf, 0x2b17,
+ 0x58c1, 0x12a3,
+ 0x58c2, 0x2b19,
+ 0x58c5, 0x12a6,
+ 0x58c6, 0x2b1b,
+ 0x58c7, 0x12a5,
+ 0x58c8, 0x2b14,
+ 0x58c9, 0x2b16,
+ 0x58cb, 0x3a09,
+ 0x58ce, 0x13c2,
+ 0x58cf, 0x2d4d,
+ 0x58d1, 0x13c1,
+ 0x58d2, 0x2d4e,
+ 0x58d3, 0x13c0,
+ 0x58d4, 0x2d4c,
+ 0x58d5, 0x13bf,
+ 0x58d6, 0x2d4b,
+ 0x58d8, 0x14cd,
+ 0x58d9, 0x14cc,
+ 0x58da, 0x3085,
+ 0x58db, 0x3087,
+ 0x58dc, 0x40da,
+ 0x58dd, 0x3086,
+ 0x58de, 0x1578,
+ 0x58e0, 0x40d9,
+ 0x58e2, 0x157a,
+ 0x58e3, 0x31cb,
+ 0x58e4, 0x160e,
+ 0x58e7, 0x3411,
+ 0x58e8, 0x3410,
+ 0x58e9, 0x1720,
+ 0x58eb, 0x027b,
+ 0x58ec, 0x02c1,
+ 0x58ef, 0x046f,
+ 0x58f0, 0x4549,
+ 0x58f2, 0x3d68,
+ 0x58f3, 0x3c7a,
+ 0x58f4, 0x1a9b,
+ 0x58f9, 0x0c20,
+ 0x58fb, 0x40dc,
+ 0x58fc, 0x23a2,
+ 0x58fd, 0x0faa,
+ 0x58fe, 0x264b,
+ 0x58ff, 0x28a9,
+ 0x5902, 0x0224,
+ 0x5903, 0x1785,
+ 0x5904, 0x454a,
+ 0x5905, 0x4599,
+ 0x5906, 0x1857,
+ 0x5907, 0x454b,
+ 0x590a, 0x0224,
+ 0x590c, 0x1944,
+ 0x590d, 0x1a9c,
+ 0x590e, 0x1c6c,
+ 0x590f, 0x0880,
+ 0x5911, 0x4274,
+ 0x5912, 0x3088,
+ 0x5914, 0x166d,
+ 0x5915, 0x027c,
+ 0x5916, 0x032e,
+ 0x5917, 0x179c,
+ 0x5919, 0x03b4,
+ 0x591c, 0x0581,
+ 0x591f, 0x40e3,
+ 0x5920, 0x0a44,
+ 0x5922, 0x0fac,
+ 0x5924, 0x0fad,
+ 0x5925, 0x0fab,
+ 0x5927, 0x027d,
+ 0x5929, 0x02c2,
+ 0x592a, 0x02c4,
+ 0x592b, 0x02c3,
+ 0x592c, 0x1786,
+ 0x592d, 0x02c5,
+ 0x592e, 0x032f,
+ 0x592f, 0x179d,
+ 0x5931, 0x0330,
+ 0x5932, 0x454c,
+ 0x5934, 0x454d,
+ 0x5937, 0x03b6,
+ 0x593c, 0x17d4,
+ 0x593e, 0x0470,
+ 0x5940, 0x1858,
+ 0x5944, 0x0585,
+ 0x5945, 0x1945,
+ 0x5947, 0x0583,
+ 0x5949, 0x0582,
+ 0x594a, 0x1c6d,
+ 0x594e, 0x06f2,
+ 0x594f, 0x06f1,
+ 0x5950, 0x06f3,
+ 0x5951, 0x06f0,
+ 0x5953, 0x1a9d,
+ 0x5954, 0x0586,
+ 0x5955, 0x06ef,
+ 0x5957, 0x0881,
+ 0x595a, 0x0883,
+ 0x595c, 0x1e95,
+ 0x5960, 0x0c22,
+ 0x5961, 0x20ef,
+ 0x5962, 0x0a45,
+ 0x5965, 0x4852,
+ 0x5967, 0x0df3,
+ 0x5969, 0x0faf,
+ 0x596a, 0x0fae,
+ 0x596b, 0x264c,
+ 0x596d, 0x1129,
+ 0x596e, 0x12a7,
+ 0x5970, 0x2f17,
+ 0x5971, 0x337b,
+ 0x5972, 0x3412,
+ 0x5973, 0x027e,
+ 0x5974, 0x0331,
+ 0x5975, 0x3e6a,
+ 0x5976, 0x0332,
+ 0x5977, 0x17da,
+ 0x5978, 0x03b9,
+ 0x5979, 0x03bc,
+ 0x597b, 0x17d8,
+ 0x597c, 0x17d6,
+ 0x597d, 0x03bb,
+ 0x597e, 0x17d9,
+ 0x597f, 0x17db,
+ 0x5980, 0x17d5,
+ 0x5981, 0x03be,
+ 0x5982, 0x03bd,
+ 0x5983, 0x03ba,
+ 0x5984, 0x03b8,
+ 0x5985, 0x17d7,
+ 0x5989, 0x3d30,
+ 0x598a, 0x047b,
+ 0x598d, 0x0478,
+ 0x598e, 0x185d,
+ 0x598f, 0x1860,
+ 0x5990, 0x185f,
+ 0x5992, 0x0472,
+ 0x5993, 0x047a,
+ 0x5994, 0x3c99,
+ 0x5996, 0x0477,
+ 0x5997, 0x185c,
+ 0x5998, 0x185a,
+ 0x5999, 0x0476,
+ 0x599a, 0x3bb0,
+ 0x599d, 0x0471,
+ 0x599e, 0x0474,
+ 0x599f, 0x3daf,
+ 0x59a0, 0x185b,
+ 0x59a1, 0x1862,
+ 0x59a2, 0x185e,
+ 0x59a3, 0x0475,
+ 0x59a4, 0x0479,
+ 0x59a5, 0x047c,
+ 0x59a6, 0x1859,
+ 0x59a7, 0x1861,
+ 0x59a8, 0x0473,
+ 0x59ac, 0x3d81,
+ 0x59ae, 0x058b,
+ 0x59af, 0x0593,
+ 0x59b0, 0x3cd8,
+ 0x59b1, 0x1951,
+ 0x59b2, 0x194a,
+ 0x59b3, 0x0594,
+ 0x59b4, 0x1955,
+ 0x59b5, 0x1946,
+ 0x59b6, 0x194d,
+ 0x59b7, 0x3f2d,
+ 0x59b8, 0x3a10,
+ 0x59b9, 0x058a,
+ 0x59ba, 0x1947,
+ 0x59bb, 0x0588,
+ 0x59bc, 0x194e,
+ 0x59bd, 0x1952,
+ 0x59be, 0x0587,
+ 0x59c0, 0x1953,
+ 0x59c1, 0x194c,
+ 0x59c3, 0x194f,
+ 0x59c4, 0x3d04,
+ 0x59c5, 0x0596,
+ 0x59c6, 0x058d,
+ 0x59c7, 0x1956,
+ 0x59c8, 0x1954,
+ 0x59c9, 0x40ec,
+ 0x59ca, 0x0592,
+ 0x59cb, 0x0590,
+ 0x59cc, 0x194b,
+ 0x59cd, 0x058f,
+ 0x59ce, 0x1949,
+ 0x59cf, 0x1948,
+ 0x59d0, 0x058e,
+ 0x59d1, 0x058c,
+ 0x59d2, 0x0595,
+ 0x59d3, 0x0591,
+ 0x59d4, 0x0589,
+ 0x59d6, 0x1950,
+ 0x59d8, 0x06f5,
+ 0x59d9, 0x40f1,
+ 0x59da, 0x06fc,
+ 0x59db, 0x1aab,
+ 0x59dc, 0x06f4,
+ 0x59dd, 0x1aa3,
+ 0x59de, 0x1a9f,
+ 0x59e0, 0x1aaf,
+ 0x59e1, 0x1a9e,
+ 0x59e3, 0x06f7,
+ 0x59e4, 0x1aa8,
+ 0x59e5, 0x06fa,
+ 0x59e6, 0x06fd,
+ 0x59e8, 0x06f8,
+ 0x59e9, 0x1aac,
+ 0x59ea, 0x06fb,
+ 0x59eb, 0x3d59,
+ 0x59ec, 0x088a,
+ 0x59ed, 0x1ab2,
+ 0x59ee, 0x1aa0,
+ 0x59ef, 0x3d38,
+ 0x59f0, 0x3bb2,
+ 0x59f1, 0x1aa2,
+ 0x59f2, 0x1aa9,
+ 0x59f3, 0x1aad,
+ 0x59f4, 0x1ab1,
+ 0x59f5, 0x1aae,
+ 0x59f6, 0x1aa7,
+ 0x59f7, 0x1aaa,
+ 0x59f8, 0x3e4a,
+ 0x59f9, 0x40f8,
+ 0x59fa, 0x1aa4,
+ 0x59fb, 0x06ff,
+ 0x59fc, 0x1aa6,
+ 0x59fd, 0x1aa5,
+ 0x59fe, 0x1ab0,
+ 0x59ff, 0x06f6,
+ 0x5a00, 0x1aa1,
+ 0x5a01, 0x06fe,
+ 0x5a02, 0x3b8d,
+ 0x5a03, 0x06f9,
+ 0x5a09, 0x0890,
+ 0x5a0a, 0x1c75,
+ 0x5a0b, 0x3c89,
+ 0x5a0c, 0x088f,
+ 0x5a0d, 0x3b38,
+ 0x5a0f, 0x1c73,
+ 0x5a11, 0x0884,
+ 0x5a12, 0x3a13,
+ 0x5a13, 0x0889,
+ 0x5a15, 0x1c72,
+ 0x5a16, 0x1c6f,
+ 0x5a17, 0x1c74,
+ 0x5a18, 0x0885,
+ 0x5a19, 0x1c6e,
+ 0x5a1b, 0x0888,
+ 0x5a1c, 0x0886,
+ 0x5a1e, 0x1c76,
+ 0x5a1f, 0x0887,
+ 0x5a20, 0x088b,
+ 0x5a21, 0x3a1b,
+ 0x5a23, 0x088c,
+ 0x5a24, 0x40e8,
+ 0x5a25, 0x088e,
+ 0x5a27, 0x3de1,
+ 0x5a29, 0x088d,
+ 0x5a2a, 0x3b3b,
+ 0x5a2b, 0x3d40,
+ 0x5a2c, 0x3a0f,
+ 0x5a2d, 0x1c70,
+ 0x5a33, 0x1c77,
+ 0x5a35, 0x1e9c,
+ 0x5a36, 0x0a46,
+ 0x5a37, 0x20fd,
+ 0x5a38, 0x1e9b,
+ 0x5a39, 0x1eae,
+ 0x5a3c, 0x0a4c,
+ 0x5a3d, 0x3ac0,
+ 0x5a3e, 0x1eac,
+ 0x5a40, 0x0a4b,
+ 0x5a41, 0x0a47,
+ 0x5a42, 0x1eb5,
+ 0x5a43, 0x1ea5,
+ 0x5a44, 0x1ea8,
+ 0x5a45, 0x3917,
+ 0x5a46, 0x0a4f,
+ 0x5a47, 0x1eb2,
+ 0x5a48, 0x1eaa,
+ 0x5a49, 0x0a48,
+ 0x5a4a, 0x0a50,
+ 0x5a4c, 0x1eaf,
+ 0x5a4d, 0x1ead,
+ 0x5a50, 0x1e9e,
+ 0x5a51, 0x1eb3,
+ 0x5a52, 0x1ea7,
+ 0x5a53, 0x1ea2,
+ 0x5a54, 0x4603,
+ 0x5a55, 0x1e98,
+ 0x5a56, 0x1eb4,
+ 0x5a57, 0x1ea4,
+ 0x5a58, 0x1e97,
+ 0x5a59, 0x3b34,
+ 0x5a5a, 0x0a4e,
+ 0x5a5b, 0x1ea9,
+ 0x5a5c, 0x1eb6,
+ 0x5a5d, 0x1ea6,
+ 0x5a5e, 0x1e9a,
+ 0x5a5f, 0x1e9f,
+ 0x5a60, 0x1e96,
+ 0x5a61, 0x3d33,
+ 0x5a62, 0x0a4d,
+ 0x5a63, 0x40fb,
+ 0x5a64, 0x1ea3,
+ 0x5a65, 0x1ea0,
+ 0x5a66, 0x0a49,
+ 0x5a67, 0x1e99,
+ 0x5a68, 0x39b7,
+ 0x5a69, 0x1eb1,
+ 0x5a6a, 0x0a4a,
+ 0x5a6b, 0x3a42,
+ 0x5a6c, 0x1ea1,
+ 0x5a6d, 0x1e9d,
+ 0x5a6e, 0x3d3f,
+ 0x5a70, 0x1eb0,
+ 0x5a71, 0x3d34,
+ 0x5a77, 0x0c23,
+ 0x5a78, 0x20f6,
+ 0x5a79, 0x3ce1,
+ 0x5a7a, 0x20f3,
+ 0x5a7b, 0x2104,
+ 0x5a7c, 0x20f8,
+ 0x5a7d, 0x2105,
+ 0x5a7e, 0x3a11,
+ 0x5a7f, 0x0c25,
+ 0x5a81, 0x3a1d,
+ 0x5a82, 0x3d31,
+ 0x5a83, 0x2101,
+ 0x5a84, 0x20fe,
+ 0x5a86, 0x3b81,
+ 0x5a88, 0x4263,
+ 0x5a8a, 0x20ff,
+ 0x5a8b, 0x2102,
+ 0x5a8c, 0x2106,
+ 0x5a8e, 0x1eab,
+ 0x5a8f, 0x2108,
+ 0x5a90, 0x23b6,
+ 0x5a91, 0x4235,
+ 0x5a92, 0x0c26,
+ 0x5a93, 0x2109,
+ 0x5a94, 0x20f1,
+ 0x5a95, 0x20fb,
+ 0x5a96, 0x4100,
+ 0x5a97, 0x2100,
+ 0x5a99, 0x3a0a,
+ 0x5a9a, 0x0c24,
+ 0x5a9b, 0x0c27,
+ 0x5a9c, 0x2107,
+ 0x5a9d, 0x210a,
+ 0x5a9e, 0x20f5,
+ 0x5a9f, 0x20f2,
+ 0x5aa0, 0x4172,
+ 0x5aa1, 0x3cdc,
+ 0x5aa2, 0x20f4,
+ 0x5aa5, 0x20f9,
+ 0x5aa6, 0x20f7,
+ 0x5aa7, 0x0c28,
+ 0x5aa9, 0x2103,
+ 0x5aab, 0x40fa,
+ 0x5aac, 0x20fa,
+ 0x5aae, 0x20fc,
+ 0x5aaf, 0x20f0,
+ 0x5ab0, 0x23aa,
+ 0x5ab1, 0x23a8,
+ 0x5ab2, 0x0dfc,
+ 0x5ab3, 0x0dfa,
+ 0x5ab4, 0x23b2,
+ 0x5ab5, 0x23a9,
+ 0x5ab6, 0x23b3,
+ 0x5ab7, 0x23af,
+ 0x5ab8, 0x23a7,
+ 0x5ab9, 0x23b5,
+ 0x5aba, 0x23a6,
+ 0x5abb, 0x23ad,
+ 0x5abc, 0x0df9,
+ 0x5abd, 0x0df8,
+ 0x5abe, 0x0df7,
+ 0x5abf, 0x23ab,
+ 0x5ac0, 0x23b0,
+ 0x5ac1, 0x0df4,
+ 0x5ac2, 0x0dfb,
+ 0x5ac3, 0x3896,
+ 0x5ac4, 0x23a4,
+ 0x5ac6, 0x23ae,
+ 0x5ac7, 0x23a3,
+ 0x5ac8, 0x23ac,
+ 0x5ac9, 0x0df5,
+ 0x5aca, 0x23b1,
+ 0x5acb, 0x23a5,
+ 0x5acc, 0x0df6,
+ 0x5acd, 0x23b4,
+ 0x5ace, 0x3c88,
+ 0x5acf, 0x43b5,
+ 0x5ad3, 0x4102,
+ 0x5ad5, 0x2650,
+ 0x5ad6, 0x0fb4,
+ 0x5ad7, 0x0fb3,
+ 0x5ad8, 0x0fb5,
+ 0x5ad9, 0x265c,
+ 0x5ada, 0x2652,
+ 0x5adb, 0x2658,
+ 0x5adc, 0x264d,
+ 0x5add, 0x265b,
+ 0x5ade, 0x265a,
+ 0x5adf, 0x265e,
+ 0x5ae0, 0x2657,
+ 0x5ae1, 0x0fb0,
+ 0x5ae2, 0x2656,
+ 0x5ae3, 0x0fb6,
+ 0x5ae4, 0x3b86,
+ 0x5ae5, 0x264f,
+ 0x5ae6, 0x0fb1,
+ 0x5ae8, 0x265d,
+ 0x5ae9, 0x0fb2,
+ 0x5aea, 0x2651,
+ 0x5aeb, 0x2654,
+ 0x5aec, 0x2659,
+ 0x5aed, 0x2653,
+ 0x5aee, 0x264e,
+ 0x5af0, 0x3ee7,
+ 0x5af2, 0x37f5,
+ 0x5af3, 0x2655,
+ 0x5af4, 0x28ab,
+ 0x5af5, 0x112d,
+ 0x5af6, 0x28ae,
+ 0x5af7, 0x28ad,
+ 0x5af8, 0x28b0,
+ 0x5af9, 0x28b2,
+ 0x5afa, 0x36ee,
+ 0x5afb, 0x112b,
+ 0x5afd, 0x28ac,
+ 0x5afe, 0x3c1d,
+ 0x5aff, 0x28aa,
+ 0x5b01, 0x28b3,
+ 0x5b02, 0x28b1,
+ 0x5b03, 0x28af,
+ 0x5b05, 0x28b5,
+ 0x5b07, 0x28b4,
+ 0x5b08, 0x112f,
+ 0x5b09, 0x112a,
+ 0x5b0b, 0x112c,
+ 0x5b0c, 0x112e,
+ 0x5b0d, 0x48ff,
+ 0x5b0f, 0x28b6,
+ 0x5b10, 0x2b22,
+ 0x5b11, 0x3bf6,
+ 0x5b13, 0x2b21,
+ 0x5b14, 0x2b20,
+ 0x5b16, 0x2b23,
+ 0x5b17, 0x2b1c,
+ 0x5b19, 0x2b1d,
+ 0x5b1a, 0x2b25,
+ 0x5b1b, 0x2b1e,
+ 0x5b1d, 0x12a8,
+ 0x5b1e, 0x2b27,
+ 0x5b1f, 0x4941,
+ 0x5b20, 0x2b26,
+ 0x5b21, 0x2b1f,
+ 0x5b23, 0x2d52,
+ 0x5b24, 0x13c5,
+ 0x5b25, 0x2d50,
+ 0x5b26, 0x2d55,
+ 0x5b27, 0x2d54,
+ 0x5b28, 0x2b24,
+ 0x5b2a, 0x13c4,
+ 0x5b2b, 0x3b84,
+ 0x5b2c, 0x2d53,
+ 0x5b2d, 0x2d4f,
+ 0x5b2e, 0x2d57,
+ 0x5b2f, 0x2d56,
+ 0x5b30, 0x13c3,
+ 0x5b32, 0x2d51,
+ 0x5b34, 0x12a9,
+ 0x5b38, 0x14ce,
+ 0x5b3c, 0x2f18,
+ 0x5b3d, 0x3089,
+ 0x5b40, 0x160f,
+ 0x5b41, 0x38c8,
+ 0x5b43, 0x1610,
+ 0x5b44, 0x3a44,
+ 0x5b45, 0x31cc,
+ 0x5b46, 0x42b2,
+ 0x5b47, 0x32cd,
+ 0x5b48, 0x32cc,
+ 0x5b4a, 0x38cd,
+ 0x5b4b, 0x337c,
+ 0x5b4d, 0x3413,
+ 0x5b4e, 0x3482,
+ 0x5b4f, 0x3a31,
+ 0x5b50, 0x027f,
+ 0x5b53, 0x0281,
+ 0x5b54, 0x02c6,
+ 0x5b55, 0x0333,
+ 0x5b56, 0x17dc,
+ 0x5b57, 0x03bf,
+ 0x5b5a, 0x047f,
+ 0x5b5c, 0x047e,
+ 0x5b5d, 0x047d,
+ 0x5b5f, 0x0597,
+ 0x5b62, 0x1957,
+ 0x5b63, 0x0599,
+ 0x5b64, 0x0598,
+ 0x5b65, 0x1958,
+ 0x5b66, 0x454e,
+ 0x5b68, 0x461d,
+ 0x5b69, 0x0700,
+ 0x5b6b, 0x0891,
+ 0x5b6c, 0x1c78,
+ 0x5b6d, 0x3e5f,
+ 0x5b6e, 0x1eb8,
+ 0x5b70, 0x0a51,
+ 0x5b71, 0x0c2a,
+ 0x5b72, 0x1eb7,
+ 0x5b73, 0x0c29,
+ 0x5b74, 0x3732,
+ 0x5b75, 0x0fb7,
+ 0x5b76, 0x410a,
+ 0x5b77, 0x265f,
+ 0x5b78, 0x12aa,
+ 0x5b7a, 0x13c6,
+ 0x5b7b, 0x2d58,
+ 0x5b7c, 0x410c,
+ 0x5b7d, 0x1611,
+ 0x5b7f, 0x16c0,
+ 0x5b80, 0x0225,
+ 0x5b81, 0x179e,
+ 0x5b82, 0x4044,
+ 0x5b83, 0x0334,
+ 0x5b84, 0x179f,
+ 0x5b85, 0x03c3,
+ 0x5b87, 0x03c1,
+ 0x5b89, 0x03c4,
+ 0x5b8b, 0x0482,
+ 0x5b8c, 0x0481,
+ 0x5b8e, 0x1863,
+ 0x5b8f, 0x0483,
+ 0x5b90, 0x48e9,
+ 0x5b92, 0x1864,
+ 0x5b93, 0x1959,
+ 0x5b95, 0x195a,
+ 0x5b97, 0x059a,
+ 0x5b98, 0x059c,
+ 0x5b99, 0x059e,
+ 0x5b9a, 0x059b,
+ 0x5b9b, 0x059f,
+ 0x5b9c, 0x059d,
+ 0x5b9d, 0x4116,
+ 0x5b9e, 0x454f,
+ 0x5ba2, 0x0704,
+ 0x5ba3, 0x0701,
+ 0x5ba4, 0x0703,
+ 0x5ba5, 0x0705,
+ 0x5ba6, 0x0702,
+ 0x5ba7, 0x1c79,
+ 0x5ba8, 0x1ab3,
+ 0x5baa, 0x417b,
+ 0x5bac, 0x1c7b,
+ 0x5bad, 0x1c7a,
+ 0x5bae, 0x0897,
+ 0x5bb0, 0x0893,
+ 0x5bb3, 0x0894,
+ 0x5bb4, 0x0896,
+ 0x5bb5, 0x0898,
+ 0x5bb6, 0x0895,
+ 0x5bb8, 0x089a,
+ 0x5bb9, 0x0899,
+ 0x5bbf, 0x0a56,
+ 0x5bc0, 0x1eba,
+ 0x5bc1, 0x1eb9,
+ 0x5bc2, 0x0a55,
+ 0x5bc3, 0x3f25,
+ 0x5bc4, 0x0a54,
+ 0x5bc5, 0x0a53,
+ 0x5bc6, 0x0a57,
+ 0x5bc7, 0x0a52,
+ 0x5bca, 0x2110,
+ 0x5bcb, 0x210d,
+ 0x5bcc, 0x0c2c,
+ 0x5bcd, 0x210c,
+ 0x5bce, 0x2111,
+ 0x5bd0, 0x0c2e,
+ 0x5bd1, 0x210f,
+ 0x5bd2, 0x0c2b,
+ 0x5bd3, 0x0c2d,
+ 0x5bd4, 0x210e,
+ 0x5bd5, 0x4111,
+ 0x5bd6, 0x23b7,
+ 0x5bd7, 0x42bb,
+ 0x5bd8, 0x23b8,
+ 0x5bde, 0x0fb8,
+ 0x5bdf, 0x0fc0,
+ 0x5be0, 0x2660,
+ 0x5be1, 0x0fba,
+ 0x5be2, 0x0fbe,
+ 0x5be3, 0x2661,
+ 0x5be4, 0x0fbf,
+ 0x5be5, 0x0fbb,
+ 0x5be7, 0x0fb9,
+ 0x5be8, 0x0fbd,
+ 0x5be9, 0x1132,
+ 0x5bea, 0x210b,
+ 0x5beb, 0x1133,
+ 0x5bec, 0x1131,
+ 0x5bee, 0x1130,
+ 0x5bef, 0x2b28,
+ 0x5bf0, 0x12ab,
+ 0x5bf1, 0x2d59,
+ 0x5bf3, 0x4115,
+ 0x5bf5, 0x157b,
+ 0x5bf6, 0x1612,
+ 0x5bf8, 0x0282,
+ 0x5bfa, 0x03c5,
+ 0x5bff, 0x40dd,
+ 0x5c01, 0x0706,
+ 0x5c03, 0x1c7c,
+ 0x5c04, 0x089b,
+ 0x5c05, 0x4118,
+ 0x5c07, 0x0a5a,
+ 0x5c08, 0x0a59,
+ 0x5c09, 0x0a58,
+ 0x5c0a, 0x0c2f,
+ 0x5c0c, 0x2112,
+ 0x5c0d, 0x0fc1,
+ 0x5c0e, 0x12ac,
+ 0x5c0f, 0x0283,
+ 0x5c10, 0x1787,
+ 0x5c11, 0x02c7,
+ 0x5c12, 0x17a0,
+ 0x5c13, 0x411a,
+ 0x5c14, 0x411c,
+ 0x5c15, 0x17dd,
+ 0x5c16, 0x03c6,
+ 0x5c1a, 0x05a0,
+ 0x5c1c, 0x45ea,
+ 0x5c1e, 0x3a29,
+ 0x5c1f, 0x23ba,
+ 0x5c20, 0x3d89,
+ 0x5c22, 0x0284,
+ 0x5c23, 0x44e8,
+ 0x5c24, 0x02c8,
+ 0x5c25, 0x17de,
+ 0x5c28, 0x1865,
+ 0x5c2a, 0x1866,
+ 0x5c2c, 0x0484,
+ 0x5c30, 0x2113,
+ 0x5c31, 0x0c31,
+ 0x5c33, 0x23bb,
+ 0x5c37, 0x13c7,
+ 0x5c38, 0x0285,
+ 0x5c39, 0x0299,
+ 0x5c3a, 0x02c9,
+ 0x5c3b, 0x17a1,
+ 0x5c3c, 0x0335,
+ 0x5c3e, 0x0488,
+ 0x5c3f, 0x0487,
+ 0x5c40, 0x0485,
+ 0x5c44, 0x195b,
+ 0x5c45, 0x05a2,
+ 0x5c47, 0x195c,
+ 0x5c48, 0x05a1,
+ 0x5c49, 0x411f,
+ 0x5c4a, 0x3f5c,
+ 0x5c4b, 0x070a,
+ 0x5c4c, 0x1ab4,
+ 0x5c4d, 0x0709,
+ 0x5c4e, 0x0707,
+ 0x5c50, 0x089e,
+ 0x5c51, 0x089c,
+ 0x5c53, 0x3f02,
+ 0x5c54, 0x1c7e,
+ 0x5c55, 0x089d,
+ 0x5c56, 0x1c7d,
+ 0x5c58, 0x0892,
+ 0x5c59, 0x1ebb,
+ 0x5c5c, 0x0a5c,
+ 0x5c5e, 0x3d67,
+ 0x5c60, 0x0a5b,
+ 0x5c62, 0x0fc2,
+ 0x5c63, 0x2662,
+ 0x5c64, 0x1134,
+ 0x5c67, 0x28b7,
+ 0x5c68, 0x13c8,
+ 0x5c69, 0x2f19,
+ 0x5c6c, 0x166e,
+ 0x5c6d, 0x3483,
+ 0x5c6e, 0x1776,
+ 0x5c6f, 0x02ca,
+ 0x5c71, 0x0286,
+ 0x5c73, 0x17a3,
+ 0x5c74, 0x17a2,
+ 0x5c79, 0x03c7,
+ 0x5c7a, 0x17e0,
+ 0x5c7c, 0x17df,
+ 0x5c7e, 0x17e2,
+ 0x5c85, 0x4121,
+ 0x5c86, 0x186e,
+ 0x5c88, 0x1869,
+ 0x5c89, 0x186b,
+ 0x5c8a, 0x186d,
+ 0x5c8b, 0x186a,
+ 0x5c8c, 0x048c,
+ 0x5c8d, 0x1867,
+ 0x5c8f, 0x1868,
+ 0x5c90, 0x0489,
+ 0x5c92, 0x186c,
+ 0x5c93, 0x186f,
+ 0x5c94, 0x048b,
+ 0x5c95, 0x1870,
+ 0x5c99, 0x468c,
+ 0x5c9a, 0x4551,
+ 0x5c9c, 0x495a,
+ 0x5c9d, 0x196a,
+ 0x5c9e, 0x3a2a,
+ 0x5c9f, 0x1964,
+ 0x5ca0, 0x195f,
+ 0x5ca1, 0x05a5,
+ 0x5ca2, 0x1967,
+ 0x5ca3, 0x1965,
+ 0x5ca4, 0x195e,
+ 0x5ca5, 0x196b,
+ 0x5ca6, 0x196e,
+ 0x5ca7, 0x1969,
+ 0x5ca8, 0x1962,
+ 0x5ca9, 0x05a7,
+ 0x5caa, 0x1968,
+ 0x5cab, 0x05a8,
+ 0x5cac, 0x1963,
+ 0x5cad, 0x1966,
+ 0x5cae, 0x195d,
+ 0x5caf, 0x1961,
+ 0x5cb0, 0x196d,
+ 0x5cb1, 0x05a9,
+ 0x5cb3, 0x05aa,
+ 0x5cb5, 0x1960,
+ 0x5cb6, 0x196c,
+ 0x5cb7, 0x05a4,
+ 0x5cb8, 0x05a6,
+ 0x5cba, 0x412b,
+ 0x5cc1, 0x43b8,
+ 0x5cc2, 0x3d4c,
+ 0x5cc6, 0x1ac5,
+ 0x5cc7, 0x1abe,
+ 0x5cc8, 0x1ac4,
+ 0x5cc9, 0x1abd,
+ 0x5cca, 0x1abf,
+ 0x5ccb, 0x1ab9,
+ 0x5ccc, 0x1ab7,
+ 0x5cce, 0x1ac6,
+ 0x5ccf, 0x1ac3,
+ 0x5cd0, 0x1ab5,
+ 0x5cd1, 0x3f13,
+ 0x5cd2, 0x070c,
+ 0x5cd3, 0x1ac1,
+ 0x5cd6, 0x1ac0,
+ 0x5cd7, 0x1ab8,
+ 0x5cd8, 0x1ab6,
+ 0x5cd9, 0x070b,
+ 0x5cda, 0x1abc,
+ 0x5cdb, 0x1aba,
+ 0x5cde, 0x1abb,
+ 0x5cdf, 0x1ac7,
+ 0x5ce5, 0x4637,
+ 0x5ce8, 0x08a3,
+ 0x5ce9, 0x4122,
+ 0x5cea, 0x08a2,
+ 0x5cec, 0x1c7f,
+ 0x5ced, 0x089f,
+ 0x5cee, 0x1c81,
+ 0x5cef, 0x4123,
+ 0x5cf0, 0x08a4,
+ 0x5cf1, 0x1c82,
+ 0x5cf4, 0x08a7,
+ 0x5cf6, 0x08a5,
+ 0x5cf7, 0x1c83,
+ 0x5cf8, 0x1ac8,
+ 0x5cf9, 0x1c85,
+ 0x5cfb, 0x08a1,
+ 0x5cfd, 0x08a0,
+ 0x5cff, 0x1c80,
+ 0x5d00, 0x1c84,
+ 0x5d01, 0x08a6,
+ 0x5d06, 0x0a5f,
+ 0x5d07, 0x0a5e,
+ 0x5d0b, 0x1ebd,
+ 0x5d0c, 0x1ec1,
+ 0x5d0d, 0x1ec3,
+ 0x5d0e, 0x0a60,
+ 0x5d0f, 0x1ec6,
+ 0x5d10, 0x4127,
+ 0x5d11, 0x0a64,
+ 0x5d12, 0x1ec8,
+ 0x5d14, 0x0a66,
+ 0x5d15, 0x43b9,
+ 0x5d16, 0x0a62,
+ 0x5d17, 0x0a6a,
+ 0x5d18, 0x4128,
+ 0x5d19, 0x0a67,
+ 0x5d1a, 0x1ebf,
+ 0x5d1b, 0x0a61,
+ 0x5d1d, 0x1ebe,
+ 0x5d1e, 0x1ebc,
+ 0x5d1f, 0x1eca,
+ 0x5d20, 0x1ec0,
+ 0x5d22, 0x0a63,
+ 0x5d23, 0x1ec9,
+ 0x5d24, 0x0a68,
+ 0x5d25, 0x1ec5,
+ 0x5d26, 0x1ec4,
+ 0x5d27, 0x0a69,
+ 0x5d28, 0x1ec2,
+ 0x5d29, 0x0a65,
+ 0x5d2c, 0x3df7,
+ 0x5d2e, 0x1ecb,
+ 0x5d2f, 0x46d3,
+ 0x5d30, 0x1ec7,
+ 0x5d31, 0x2122,
+ 0x5d32, 0x2129,
+ 0x5d33, 0x211e,
+ 0x5d34, 0x0c34,
+ 0x5d35, 0x211a,
+ 0x5d36, 0x212a,
+ 0x5d37, 0x2114,
+ 0x5d38, 0x2127,
+ 0x5d39, 0x2125,
+ 0x5d3a, 0x211f,
+ 0x5d3c, 0x2128,
+ 0x5d3d, 0x2121,
+ 0x5d3e, 0x4629,
+ 0x5d3f, 0x2119,
+ 0x5d40, 0x212b,
+ 0x5d41, 0x2117,
+ 0x5d42, 0x2124,
+ 0x5d43, 0x2115,
+ 0x5d45, 0x212c,
+ 0x5d46, 0x4129,
+ 0x5d47, 0x0c35,
+ 0x5d48, 0x462a,
+ 0x5d49, 0x2126,
+ 0x5d4a, 0x23be,
+ 0x5d4b, 0x2118,
+ 0x5d4c, 0x0c32,
+ 0x5d4e, 0x211c,
+ 0x5d50, 0x0c33,
+ 0x5d51, 0x211b,
+ 0x5d52, 0x2120,
+ 0x5d55, 0x211d,
+ 0x5d56, 0x43ba,
+ 0x5d57, 0x3fca,
+ 0x5d59, 0x2123,
+ 0x5d5b, 0x3dd5,
+ 0x5d5e, 0x23c2,
+ 0x5d62, 0x23c5,
+ 0x5d63, 0x23bd,
+ 0x5d65, 0x23bf,
+ 0x5d67, 0x23c4,
+ 0x5d68, 0x23c3,
+ 0x5d69, 0x0dfd,
+ 0x5d6b, 0x2116,
+ 0x5d6c, 0x23c1,
+ 0x5d6f, 0x0dfe,
+ 0x5d70, 0x46e4,
+ 0x5d71, 0x23bc,
+ 0x5d72, 0x23c0,
+ 0x5d74, 0x3eef,
+ 0x5d77, 0x2669,
+ 0x5d79, 0x2670,
+ 0x5d7a, 0x2667,
+ 0x5d7c, 0x266e,
+ 0x5d7d, 0x2665,
+ 0x5d7e, 0x266d,
+ 0x5d7f, 0x2671,
+ 0x5d80, 0x2664,
+ 0x5d81, 0x2668,
+ 0x5d82, 0x2663,
+ 0x5d84, 0x0fc3,
+ 0x5d85, 0x3e34,
+ 0x5d86, 0x2666,
+ 0x5d87, 0x0fc4,
+ 0x5d88, 0x266c,
+ 0x5d89, 0x266b,
+ 0x5d8a, 0x266a,
+ 0x5d8b, 0x4124,
+ 0x5d8d, 0x266f,
+ 0x5d8e, 0x3f0c,
+ 0x5d92, 0x28bb,
+ 0x5d93, 0x28bd,
+ 0x5d94, 0x1137,
+ 0x5d95, 0x28be,
+ 0x5d97, 0x28b9,
+ 0x5d99, 0x28b8,
+ 0x5d9a, 0x28c2,
+ 0x5d9c, 0x28c0,
+ 0x5d9d, 0x1136,
+ 0x5d9e, 0x28c3,
+ 0x5d9f, 0x28ba,
+ 0x5da0, 0x28bf,
+ 0x5da1, 0x28c1,
+ 0x5da2, 0x28bc,
+ 0x5da4, 0x462d,
+ 0x5da7, 0x2b2c,
+ 0x5da8, 0x2b31,
+ 0x5da9, 0x2b2b,
+ 0x5daa, 0x2b30,
+ 0x5dab, 0x3e39,
+ 0x5dac, 0x2b29,
+ 0x5dad, 0x2b33,
+ 0x5dae, 0x2b2f,
+ 0x5daf, 0x2b34,
+ 0x5db0, 0x2b2e,
+ 0x5db1, 0x2b2a,
+ 0x5db2, 0x2b32,
+ 0x5db4, 0x2b35,
+ 0x5db5, 0x2b2d,
+ 0x5db6, 0x4158,
+ 0x5db7, 0x2d5b,
+ 0x5db8, 0x13cc,
+ 0x5db9, 0x462e,
+ 0x5dba, 0x13ca,
+ 0x5dbc, 0x13c9,
+ 0x5dbd, 0x13cb,
+ 0x5dc0, 0x2f1b,
+ 0x5dc1, 0x3bff,
+ 0x5dc2, 0x3023,
+ 0x5dc3, 0x308c,
+ 0x5dc6, 0x31cd,
+ 0x5dc9, 0x1613,
+ 0x5dcb, 0x32ce,
+ 0x5dcd, 0x166f,
+ 0x5dcf, 0x32cf,
+ 0x5dd1, 0x337f,
+ 0x5dd2, 0x16c2,
+ 0x5dd4, 0x16c1,
+ 0x5dd5, 0x337e,
+ 0x5dd6, 0x16f7,
+ 0x5dd7, 0x412c,
+ 0x5dd8, 0x3414,
+ 0x5ddb, 0x0226,
+ 0x5ddd, 0x0287,
+ 0x5dde, 0x03c8,
+ 0x5ddf, 0x17e3,
+ 0x5de0, 0x1871,
+ 0x5de1, 0x051a,
+ 0x5de2, 0x0a6b,
+ 0x5de5, 0x0288,
+ 0x5de6, 0x0338,
+ 0x5de7, 0x0337,
+ 0x5de8, 0x0336,
+ 0x5deb, 0x048d,
+ 0x5dee, 0x08a8,
+ 0x5df0, 0x23c6,
+ 0x5df1, 0x0289,
+ 0x5df4, 0x02cb,
+ 0x5df5, 0x3f61,
+ 0x5df7, 0x070d,
+ 0x5df9, 0x1ac9,
+ 0x5dfd, 0x0c36,
+ 0x5dfe, 0x028c,
+ 0x5dff, 0x1788,
+ 0x5e02, 0x0339,
+ 0x5e04, 0x17a4,
+ 0x5e06, 0x03c9,
+ 0x5e09, 0x4140,
+ 0x5e0a, 0x1872,
+ 0x5e0b, 0x3d8a,
+ 0x5e0c, 0x048e,
+ 0x5e0e, 0x1873,
+ 0x5e11, 0x05b0,
+ 0x5e12, 0x3f2e,
+ 0x5e14, 0x1970,
+ 0x5e15, 0x05ae,
+ 0x5e16, 0x05ad,
+ 0x5e17, 0x196f,
+ 0x5e18, 0x05ab,
+ 0x5e19, 0x1971,
+ 0x5e1a, 0x05ac,
+ 0x5e1b, 0x05af,
+ 0x5e1d, 0x070e,
+ 0x5e1f, 0x0710,
+ 0x5e20, 0x1acd,
+ 0x5e21, 0x1aca,
+ 0x5e24, 0x1ace,
+ 0x5e25, 0x070f,
+ 0x5e28, 0x1c87,
+ 0x5e29, 0x1c86,
+ 0x5e2b, 0x08aa,
+ 0x5e2d, 0x08a9,
+ 0x5e2e, 0x4135,
+ 0x5e33, 0x0a6e,
+ 0x5e34, 0x1ecd,
+ 0x5e36, 0x0a6d,
+ 0x5e37, 0x0a6f,
+ 0x5e38, 0x0a6c,
+ 0x5e3d, 0x0c38,
+ 0x5e3e, 0x1ecc,
+ 0x5e40, 0x0c39,
+ 0x5e41, 0x212e,
+ 0x5e42, 0x43a0,
+ 0x5e43, 0x0c3a,
+ 0x5e44, 0x212d,
+ 0x5e45, 0x0c37,
+ 0x5e48, 0x3a2c,
+ 0x5e4a, 0x23c9,
+ 0x5e4b, 0x23cb,
+ 0x5e4c, 0x0dff,
+ 0x5e4d, 0x23ca,
+ 0x5e4e, 0x23c8,
+ 0x5e4f, 0x23c7,
+ 0x5e53, 0x2674,
+ 0x5e54, 0x0fc9,
+ 0x5e55, 0x0fc7,
+ 0x5e57, 0x0fc8,
+ 0x5e58, 0x2672,
+ 0x5e5b, 0x0fc5,
+ 0x5e5c, 0x28c7,
+ 0x5e5d, 0x28c5,
+ 0x5e5e, 0x3a2b,
+ 0x5e5f, 0x1139,
+ 0x5e60, 0x28c6,
+ 0x5e61, 0x113a,
+ 0x5e62, 0x1138,
+ 0x5e63, 0x0fc6,
+ 0x5e66, 0x2b38,
+ 0x5e67, 0x2b36,
+ 0x5e69, 0x28c4,
+ 0x5e6a, 0x2d5d,
+ 0x5e6b, 0x13cd,
+ 0x5e6c, 0x2d5c,
+ 0x5e6d, 0x2f1c,
+ 0x5e6f, 0x2b39,
+ 0x5e70, 0x308d,
+ 0x5e72, 0x028d,
+ 0x5e73, 0x033b,
+ 0x5e74, 0x03cb,
+ 0x5e75, 0x17e4,
+ 0x5e76, 0x03ca,
+ 0x5e78, 0x05b1,
+ 0x5e79, 0x0e00,
+ 0x5e7a, 0x0227,
+ 0x5e7b, 0x02cc,
+ 0x5e7c, 0x033c,
+ 0x5e7d, 0x0711,
+ 0x5e7e, 0x0c3b,
+ 0x5e7f, 0x0228,
+ 0x5e80, 0x17a5,
+ 0x5e82, 0x17a6,
+ 0x5e83, 0x4108,
+ 0x5e84, 0x17e5,
+ 0x5e86, 0x4552,
+ 0x5e87, 0x0490,
+ 0x5e88, 0x1877,
+ 0x5e89, 0x1875,
+ 0x5e8a, 0x0491,
+ 0x5e8b, 0x1874,
+ 0x5e8c, 0x1876,
+ 0x5e8d, 0x1878,
+ 0x5e8f, 0x048f,
+ 0x5e95, 0x05b5,
+ 0x5e97, 0x05b3,
+ 0x5e9a, 0x05b2,
+ 0x5e9b, 0x1ad2,
+ 0x5e9c, 0x05b4,
+ 0x5ea0, 0x0712,
+ 0x5ea2, 0x1ad1,
+ 0x5ea3, 0x1ad3,
+ 0x5ea4, 0x1ad0,
+ 0x5ea5, 0x1ad4,
+ 0x5ea6, 0x0713,
+ 0x5ea7, 0x08ad,
+ 0x5ea8, 0x1c88,
+ 0x5eaa, 0x1c8a,
+ 0x5eab, 0x08ab,
+ 0x5eac, 0x1c8b,
+ 0x5ead, 0x08ac,
+ 0x5eae, 0x1c89,
+ 0x5eb0, 0x1acf,
+ 0x5eb1, 0x1ece,
+ 0x5eb2, 0x1ed1,
+ 0x5eb4, 0x1ecf,
+ 0x5eb5, 0x0a73,
+ 0x5eb6, 0x0a72,
+ 0x5eb7, 0x0a70,
+ 0x5eb9, 0x1ed0,
+ 0x5ebd, 0x43bd,
+ 0x5ebe, 0x0a74,
+ 0x5ec1, 0x0c3d,
+ 0x5ec4, 0x0c3f,
+ 0x5ec5, 0x23cc,
+ 0x5ec6, 0x23ce,
+ 0x5ec7, 0x23d0,
+ 0x5ec8, 0x0e02,
+ 0x5ec9, 0x0e01,
+ 0x5eca, 0x0c3c,
+ 0x5ecb, 0x23cf,
+ 0x5ecc, 0x23cd,
+ 0x5ecd, 0x3a30,
+ 0x5ece, 0x2678,
+ 0x5ed0, 0x413d,
+ 0x5ed1, 0x2676,
+ 0x5ed2, 0x267c,
+ 0x5ed3, 0x0fca,
+ 0x5ed4, 0x267d,
+ 0x5ed5, 0x267a,
+ 0x5ed6, 0x0fcb,
+ 0x5ed7, 0x2677,
+ 0x5ed8, 0x2675,
+ 0x5ed9, 0x267b,
+ 0x5eda, 0x113c,
+ 0x5edb, 0x28c9,
+ 0x5edc, 0x2679,
+ 0x5edd, 0x113e,
+ 0x5ede, 0x28ca,
+ 0x5edf, 0x113d,
+ 0x5ee0, 0x1140,
+ 0x5ee1, 0x28cb,
+ 0x5ee2, 0x113b,
+ 0x5ee3, 0x113f,
+ 0x5ee5, 0x2b3e,
+ 0x5ee6, 0x2b3c,
+ 0x5ee7, 0x2b3b,
+ 0x5ee8, 0x2b3d,
+ 0x5ee9, 0x2b3a,
+ 0x5eec, 0x157d,
+ 0x5eee, 0x31cf,
+ 0x5ef1, 0x32d0,
+ 0x5ef2, 0x3380,
+ 0x5ef3, 0x1742,
+ 0x5ef4, 0x0229,
+ 0x5ef6, 0x05b7,
+ 0x5ef7, 0x0492,
+ 0x5ef8, 0x386f,
+ 0x5ef9, 0x4143,
+ 0x5efa, 0x0714,
+ 0x5efb, 0x4144,
+ 0x5efc, 0x4146,
+ 0x5efe, 0x028e,
+ 0x5eff, 0x02cd,
+ 0x5f01, 0x033d,
+ 0x5f02, 0x17e6,
+ 0x5f04, 0x0493,
+ 0x5f05, 0x1879,
+ 0x5f07, 0x1ad5,
+ 0x5f08, 0x0715,
+ 0x5f0a, 0x0fcc,
+ 0x5f0b, 0x028f,
+ 0x5f0c, 0x3a3e,
+ 0x5f0d, 0x4149,
+ 0x5f0e, 0x3a3f,
+ 0x5f0f, 0x03cc,
+ 0x5f12, 0x0e03,
+ 0x5f13, 0x0290,
+ 0x5f14, 0x02ce,
+ 0x5f17, 0x033f,
+ 0x5f18, 0x033e,
+ 0x5f1a, 0x17e7,
+ 0x5f1b, 0x03cd,
+ 0x5f1d, 0x187a,
+ 0x5f1f, 0x0494,
+ 0x5f22, 0x1973,
+ 0x5f25, 0x4630,
+ 0x5f26, 0x05b8,
+ 0x5f28, 0x1972,
+ 0x5f29, 0x05ba,
+ 0x5f2d, 0x0716,
+ 0x5f2e, 0x1ad6,
+ 0x5f30, 0x1c8d,
+ 0x5f31, 0x08ae,
+ 0x5f33, 0x1c8c,
+ 0x5f35, 0x0a75,
+ 0x5f36, 0x1ed3,
+ 0x5f37, 0x0a76,
+ 0x5f38, 0x1ed4,
+ 0x5f3a, 0x414e,
+ 0x5f3c, 0x0c40,
+ 0x5f40, 0x23d1,
+ 0x5f43, 0x267f,
+ 0x5f44, 0x267e,
+ 0x5f46, 0x0fcd,
+ 0x5f48, 0x1141,
+ 0x5f49, 0x28cc,
+ 0x5f4a, 0x12ad,
+ 0x5f4b, 0x2b3f,
+ 0x5f4c, 0x13ce,
+ 0x5f4d, 0x3ba5,
+ 0x5f4e, 0x16c3,
+ 0x5f4f, 0x3416,
+ 0x5f50, 0x022a,
+ 0x5f51, 0x44e9,
+ 0x5f54, 0x1976,
+ 0x5f56, 0x1ad7,
+ 0x5f57, 0x0a77,
+ 0x5f58, 0x212f,
+ 0x5f59, 0x0e04,
+ 0x5f5c, 0x3d5a,
+ 0x5f5d, 0x14cf,
+ 0x5f61, 0x022b,
+ 0x5f62, 0x0496,
+ 0x5f63, 0x4152,
+ 0x5f64, 0x0495,
+ 0x5f65, 0x0717,
+ 0x5f67, 0x1c8e,
+ 0x5f69, 0x0a79,
+ 0x5f6a, 0x0b89,
+ 0x5f6b, 0x0a7a,
+ 0x5f6c, 0x0a78,
+ 0x5f6d, 0x0c41,
+ 0x5f6f, 0x2680,
+ 0x5f70, 0x0fce,
+ 0x5f71, 0x1142,
+ 0x5f72, 0x4154,
+ 0x5f73, 0x1777,
+ 0x5f74, 0x17e8,
+ 0x5f76, 0x187c,
+ 0x5f77, 0x0497,
+ 0x5f78, 0x187b,
+ 0x5f79, 0x0498,
+ 0x5f7b, 0x4058,
+ 0x5f7c, 0x05be,
+ 0x5f7d, 0x1979,
+ 0x5f7e, 0x1978,
+ 0x5f7f, 0x05bd,
+ 0x5f80, 0x05bb,
+ 0x5f82, 0x1977,
+ 0x5f83, 0x4631,
+ 0x5f85, 0x0719,
+ 0x5f86, 0x1ad8,
+ 0x5f87, 0x071c,
+ 0x5f88, 0x0718,
+ 0x5f89, 0x071e,
+ 0x5f8a, 0x071a,
+ 0x5f8c, 0x071d,
+ 0x5f90, 0x08b1,
+ 0x5f91, 0x08b0,
+ 0x5f92, 0x08af,
+ 0x5f96, 0x1ed6,
+ 0x5f97, 0x0a7b,
+ 0x5f98, 0x0a7e,
+ 0x5f99, 0x0a7c,
+ 0x5f9b, 0x1ed5,
+ 0x5f9c, 0x0a81,
+ 0x5f9e, 0x0a7d,
+ 0x5f9f, 0x1ed7,
+ 0x5fa0, 0x0a80,
+ 0x5fa1, 0x0a7f,
+ 0x5fa4, 0x402c,
+ 0x5fa5, 0x2131,
+ 0x5fa6, 0x2130,
+ 0x5fa7, 0x4157,
+ 0x5fa8, 0x0c44,
+ 0x5fa9, 0x0c42,
+ 0x5fab, 0x2132,
+ 0x5fac, 0x0e05,
+ 0x5fad, 0x23d3,
+ 0x5fae, 0x0e06,
+ 0x5faf, 0x23d2,
+ 0x5fb1, 0x3d98,
+ 0x5fb2, 0x28cd,
+ 0x5fb5, 0x1144,
+ 0x5fb6, 0x2681,
+ 0x5fb7, 0x1143,
+ 0x5fb9, 0x0fcf,
+ 0x5fba, 0x3f9f,
+ 0x5fbb, 0x2b41,
+ 0x5fbc, 0x2b40,
+ 0x5fbd, 0x13cf,
+ 0x5fbe, 0x2d5e,
+ 0x5fbf, 0x308e,
+ 0x5fc0, 0x31d1,
+ 0x5fc3, 0x02d0,
+ 0x5fc4, 0x44ea,
+ 0x5fc5, 0x0340,
+ 0x5fc9, 0x17a7,
+ 0x5fcc, 0x049a,
+ 0x5fcd, 0x049c,
+ 0x5fcf, 0x17eb,
+ 0x5fd0, 0x187f,
+ 0x5fd1, 0x187e,
+ 0x5fd2, 0x187d,
+ 0x5fd4, 0x17ea,
+ 0x5fd5, 0x17e9,
+ 0x5fd6, 0x03cf,
+ 0x5fd7, 0x049b,
+ 0x5fd8, 0x0499,
+ 0x5fd9, 0x03ce,
+ 0x5fdb, 0x3a4a,
+ 0x5fdd, 0x05bf,
+ 0x5fde, 0x197a,
+ 0x5fdf, 0x41af,
+ 0x5fe0, 0x05c0,
+ 0x5fe1, 0x1884,
+ 0x5fe3, 0x1886,
+ 0x5fe4, 0x1885,
+ 0x5fe5, 0x197b,
+ 0x5fe8, 0x1881,
+ 0x5fea, 0x04a0,
+ 0x5feb, 0x049e,
+ 0x5fed, 0x1880,
+ 0x5fee, 0x1882,
+ 0x5fef, 0x1888,
+ 0x5ff1, 0x049d,
+ 0x5ff3, 0x1883,
+ 0x5ff4, 0x188c,
+ 0x5ff5, 0x05c2,
+ 0x5ff7, 0x1889,
+ 0x5ff8, 0x049f,
+ 0x5ffa, 0x1887,
+ 0x5ffb, 0x188a,
+ 0x5ffd, 0x05c1,
+ 0x5fff, 0x05c3,
+ 0x6000, 0x188b,
+ 0x6009, 0x198f,
+ 0x600a, 0x1982,
+ 0x600b, 0x1980,
+ 0x600c, 0x198e,
+ 0x600d, 0x1989,
+ 0x600e, 0x0723,
+ 0x600f, 0x05c4,
+ 0x6010, 0x198a,
+ 0x6011, 0x198d,
+ 0x6012, 0x071f,
+ 0x6013, 0x198c,
+ 0x6014, 0x05c5,
+ 0x6015, 0x05ca,
+ 0x6016, 0x05c8,
+ 0x6017, 0x1983,
+ 0x6019, 0x197e,
+ 0x601a, 0x1985,
+ 0x601b, 0x05cf,
+ 0x601c, 0x1990,
+ 0x601d, 0x0720,
+ 0x601e, 0x1986,
+ 0x6020, 0x0721,
+ 0x6021, 0x05cb,
+ 0x6022, 0x1988,
+ 0x6023, 0x4185,
+ 0x6024, 0x1ae7,
+ 0x6025, 0x0722,
+ 0x6026, 0x197d,
+ 0x6027, 0x05cc,
+ 0x6028, 0x0724,
+ 0x6029, 0x05cd,
+ 0x602a, 0x05c9,
+ 0x602b, 0x05ce,
+ 0x602c, 0x1987,
+ 0x602d, 0x197c,
+ 0x602e, 0x198b,
+ 0x602f, 0x05c6,
+ 0x6031, 0x4161,
+ 0x6032, 0x197f,
+ 0x6033, 0x1984,
+ 0x6034, 0x1981,
+ 0x6035, 0x05c7,
+ 0x6037, 0x1ad9,
+ 0x6039, 0x1ada,
+ 0x603b, 0x4553,
+ 0x6040, 0x1ae4,
+ 0x6041, 0x1c92,
+ 0x6042, 0x1ae5,
+ 0x6043, 0x072a,
+ 0x6044, 0x1ae8,
+ 0x6045, 0x1ade,
+ 0x6046, 0x0729,
+ 0x6047, 0x1ae0,
+ 0x6049, 0x1ae1,
+ 0x604a, 0x4074,
+ 0x604c, 0x1ae3,
+ 0x604d, 0x0725,
+ 0x6050, 0x08b5,
+ 0x6052, 0x36ec,
+ 0x6053, 0x1adf,
+ 0x6054, 0x1adb,
+ 0x6055, 0x08b6,
+ 0x6058, 0x1ae9,
+ 0x6059, 0x08b2,
+ 0x605a, 0x1c90,
+ 0x605b, 0x1ae2,
+ 0x605d, 0x1c8f,
+ 0x605e, 0x1add,
+ 0x605f, 0x1ae6,
+ 0x6062, 0x0728,
+ 0x6063, 0x08b3,
+ 0x6064, 0x072e,
+ 0x6065, 0x08b4,
+ 0x6066, 0x1aea,
+ 0x6067, 0x1c91,
+ 0x6068, 0x0727,
+ 0x6069, 0x08b8,
+ 0x606a, 0x072d,
+ 0x606b, 0x072c,
+ 0x606c, 0x072b,
+ 0x606d, 0x08b7,
+ 0x606e, 0x1aeb,
+ 0x606f, 0x08b9,
+ 0x6070, 0x0726,
+ 0x6072, 0x1adc,
+ 0x6075, 0x3a56,
+ 0x6077, 0x4005,
+ 0x607e, 0x3a47,
+ 0x607f, 0x0a82,
+ 0x6080, 0x1c95,
+ 0x6081, 0x1c97,
+ 0x6083, 0x1c99,
+ 0x6084, 0x08ba,
+ 0x6085, 0x08c0,
+ 0x6086, 0x1eda,
+ 0x6087, 0x1c9d,
+ 0x6088, 0x1c94,
+ 0x6089, 0x0a84,
+ 0x608a, 0x1ed8,
+ 0x608c, 0x08bf,
+ 0x608d, 0x08bd,
+ 0x608e, 0x1c9f,
+ 0x6090, 0x1ed9,
+ 0x6092, 0x1c96,
+ 0x6094, 0x08be,
+ 0x6095, 0x1c9a,
+ 0x6096, 0x08c1,
+ 0x6097, 0x1c9c,
+ 0x609a, 0x08bc,
+ 0x609b, 0x1c9b,
+ 0x609c, 0x1c9e,
+ 0x609d, 0x1c98,
+ 0x609e, 0x416a,
+ 0x609f, 0x08bb,
+ 0x60a0, 0x0a85,
+ 0x60a2, 0x1c93,
+ 0x60a3, 0x0a83,
+ 0x60a4, 0x4001,
+ 0x60a7, 0x3adc,
+ 0x60a8, 0x0a86,
+ 0x60b0, 0x1edc,
+ 0x60b1, 0x1ee5,
+ 0x60b2, 0x0c47,
+ 0x60b3, 0x416c,
+ 0x60b4, 0x0a88,
+ 0x60b5, 0x0a8d,
+ 0x60b6, 0x0c48,
+ 0x60b7, 0x1ee7,
+ 0x60b8, 0x0a94,
+ 0x60b9, 0x2134,
+ 0x60ba, 0x1edd,
+ 0x60bb, 0x0a8c,
+ 0x60bc, 0x0a8f,
+ 0x60bd, 0x0a8a,
+ 0x60be, 0x1edb,
+ 0x60bf, 0x1ee9,
+ 0x60c0, 0x1eec,
+ 0x60c1, 0x2143,
+ 0x60c3, 0x1eea,
+ 0x60c4, 0x2138,
+ 0x60c5, 0x0a8b,
+ 0x60c6, 0x0a92,
+ 0x60c7, 0x0a96,
+ 0x60c8, 0x1ee4,
+ 0x60c9, 0x2133,
+ 0x60ca, 0x1ee8,
+ 0x60cb, 0x0a87,
+ 0x60cc, 0x2135,
+ 0x60cd, 0x1eeb,
+ 0x60ce, 0x2137,
+ 0x60cf, 0x1ee0,
+ 0x60d1, 0x0c45,
+ 0x60d3, 0x1ede,
+ 0x60d5, 0x0a91,
+ 0x60d7, 0x4635,
+ 0x60d8, 0x0a90,
+ 0x60d9, 0x1ee2,
+ 0x60da, 0x0a95,
+ 0x60db, 0x1ee6,
+ 0x60dc, 0x0a8e,
+ 0x60dd, 0x1ee3,
+ 0x60de, 0x3dcc,
+ 0x60df, 0x0a93,
+ 0x60e0, 0x0c49,
+ 0x60e1, 0x0c46,
+ 0x60e2, 0x2136,
+ 0x60e3, 0x3d75,
+ 0x60e4, 0x1ee1,
+ 0x60e6, 0x0a89,
+ 0x60e7, 0x3d84,
+ 0x60e8, 0x3d7b,
+ 0x60e9, 0x4009,
+ 0x60f0, 0x0c4e,
+ 0x60f1, 0x0c52,
+ 0x60f2, 0x213a,
+ 0x60f3, 0x0e0b,
+ 0x60f4, 0x0c50,
+ 0x60f5, 0x213e,
+ 0x60f6, 0x0c54,
+ 0x60f7, 0x23d4,
+ 0x60f8, 0x2140,
+ 0x60f9, 0x0e0d,
+ 0x60fa, 0x0c4c,
+ 0x60fb, 0x0c4f,
+ 0x60fc, 0x2141,
+ 0x60fd, 0x3fa8,
+ 0x60fe, 0x2142,
+ 0x60ff, 0x2148,
+ 0x6100, 0x0c56,
+ 0x6101, 0x0e0e,
+ 0x6103, 0x2144,
+ 0x6104, 0x2149,
+ 0x6105, 0x213d,
+ 0x6106, 0x0e18,
+ 0x6107, 0x3c35,
+ 0x6108, 0x0e0f,
+ 0x6109, 0x0c55,
+ 0x610a, 0x213b,
+ 0x610b, 0x214a,
+ 0x610c, 0x3c87,
+ 0x610d, 0x0e17,
+ 0x610e, 0x0c53,
+ 0x610f, 0x0e08,
+ 0x6110, 0x2147,
+ 0x6112, 0x0c57,
+ 0x6113, 0x213f,
+ 0x6114, 0x2139,
+ 0x6115, 0x0c4d,
+ 0x6116, 0x213c,
+ 0x6118, 0x2145,
+ 0x6119, 0x3ef6,
+ 0x611a, 0x0e07,
+ 0x611b, 0x0e0c,
+ 0x611c, 0x0c4a,
+ 0x611d, 0x2146,
+ 0x611f, 0x0e0a,
+ 0x6123, 0x0c4b,
+ 0x6127, 0x0e16,
+ 0x6128, 0x2683,
+ 0x6129, 0x23df,
+ 0x612b, 0x23d7,
+ 0x612c, 0x2682,
+ 0x612e, 0x23db,
+ 0x612f, 0x23dd,
+ 0x6130, 0x3f37,
+ 0x6132, 0x23da,
+ 0x6134, 0x0e15,
+ 0x6136, 0x23d9,
+ 0x6137, 0x0e19,
+ 0x613b, 0x2692,
+ 0x613d, 0x4636,
+ 0x613e, 0x0e14,
+ 0x613f, 0x0fd1,
+ 0x6140, 0x23e0,
+ 0x6141, 0x2684,
+ 0x6142, 0x4174,
+ 0x6144, 0x0e12,
+ 0x6145, 0x23d8,
+ 0x6146, 0x23dc,
+ 0x6147, 0x0fd0,
+ 0x6148, 0x0e09,
+ 0x6149, 0x23d5,
+ 0x614b, 0x0fd2,
+ 0x614c, 0x0e11,
+ 0x614d, 0x0e13,
+ 0x614e, 0x0e10,
+ 0x614f, 0x23de,
+ 0x6150, 0x3c32,
+ 0x6152, 0x2688,
+ 0x6154, 0x268e,
+ 0x6155, 0x1149,
+ 0x6156, 0x2695,
+ 0x6158, 0x0fd8,
+ 0x6159, 0x3fba,
+ 0x615a, 0x0fd7,
+ 0x615b, 0x2690,
+ 0x615c, 0x4186,
+ 0x615d, 0x1148,
+ 0x615e, 0x2685,
+ 0x615f, 0x0fd6,
+ 0x6160, 0x494c,
+ 0x6161, 0x2694,
+ 0x6162, 0x0fd4,
+ 0x6164, 0x4173,
+ 0x6165, 0x2691,
+ 0x6166, 0x28de,
+ 0x6167, 0x1146,
+ 0x6168, 0x0c51,
+ 0x616a, 0x2693,
+ 0x616b, 0x114d,
+ 0x616c, 0x268b,
+ 0x616e, 0x1147,
+ 0x616f, 0x3fc0,
+ 0x6170, 0x114c,
+ 0x6171, 0x2686,
+ 0x6172, 0x268a,
+ 0x6173, 0x2687,
+ 0x6174, 0x268d,
+ 0x6175, 0x0fd9,
+ 0x6176, 0x1145,
+ 0x6177, 0x0fd3,
+ 0x6179, 0x28d0,
+ 0x617a, 0x268f,
+ 0x617c, 0x114b,
+ 0x617d, 0x3fbd,
+ 0x617e, 0x114e,
+ 0x6180, 0x268c,
+ 0x6181, 0x4177,
+ 0x6182, 0x114a,
+ 0x6183, 0x28cf,
+ 0x6187, 0x417a,
+ 0x6189, 0x28d4,
+ 0x618a, 0x12b1,
+ 0x618b, 0x28ce,
+ 0x618c, 0x2b4d,
+ 0x618d, 0x28dd,
+ 0x618e, 0x1152,
+ 0x6190, 0x1150,
+ 0x6191, 0x12af,
+ 0x6192, 0x28da,
+ 0x6193, 0x28d6,
+ 0x6194, 0x1156,
+ 0x6195, 0x3de0,
+ 0x6196, 0x2b44,
+ 0x6198, 0x3a55,
+ 0x6199, 0x3a54,
+ 0x619a, 0x1154,
+ 0x619b, 0x28d5,
+ 0x619c, 0x4002,
+ 0x619d, 0x2b42,
+ 0x619f, 0x28d9,
+ 0x61a1, 0x28dc,
+ 0x61a2, 0x28d3,
+ 0x61a4, 0x1155,
+ 0x61a7, 0x114f,
+ 0x61a8, 0x2b43,
+ 0x61a9, 0x12b0,
+ 0x61aa, 0x28db,
+ 0x61ab, 0x1151,
+ 0x61ac, 0x1153,
+ 0x61ad, 0x28d8,
+ 0x61ae, 0x1157,
+ 0x61af, 0x28d7,
+ 0x61b0, 0x28d2,
+ 0x61b1, 0x28d1,
+ 0x61b2, 0x12ae,
+ 0x61b3, 0x28df,
+ 0x61b4, 0x2b46,
+ 0x61b5, 0x2d60,
+ 0x61b6, 0x12b3,
+ 0x61b7, 0x4639,
+ 0x61b8, 0x2b4c,
+ 0x61b9, 0x43bf,
+ 0x61ba, 0x2b4a,
+ 0x61bc, 0x2d61,
+ 0x61be, 0x12b4,
+ 0x61bf, 0x2b4b,
+ 0x61c0, 0x3a50,
+ 0x61c1, 0x2b48,
+ 0x61c2, 0x13d1,
+ 0x61c3, 0x2d5f,
+ 0x61c5, 0x2b45,
+ 0x61c6, 0x2b47,
+ 0x61c7, 0x13d2,
+ 0x61c8, 0x12b6,
+ 0x61c9, 0x13d0,
+ 0x61ca, 0x12b5,
+ 0x61cb, 0x13d4,
+ 0x61cc, 0x2b49,
+ 0x61cd, 0x12b2,
+ 0x61cf, 0x463a,
+ 0x61d0, 0x4181,
+ 0x61d3, 0x417e,
+ 0x61d6, 0x2f26,
+ 0x61d8, 0x2f1e,
+ 0x61da, 0x38b1,
+ 0x61de, 0x2d67,
+ 0x61df, 0x2f1f,
+ 0x61e0, 0x2d63,
+ 0x61e2, 0x3fc5,
+ 0x61e3, 0x14d0,
+ 0x61e4, 0x2d65,
+ 0x61e5, 0x2d64,
+ 0x61e6, 0x13d3,
+ 0x61e7, 0x2d62,
+ 0x61e8, 0x2d66,
+ 0x61e9, 0x2f27,
+ 0x61ea, 0x2f23,
+ 0x61eb, 0x2f25,
+ 0x61ed, 0x2f20,
+ 0x61f0, 0x2f24,
+ 0x61f1, 0x2f22,
+ 0x61f2, 0x157e,
+ 0x61f5, 0x1581,
+ 0x61f6, 0x1580,
+ 0x61f7, 0x157f,
+ 0x61f8, 0x1614,
+ 0x61f9, 0x31d3,
+ 0x61fa, 0x1615,
+ 0x61fb, 0x308f,
+ 0x61fc, 0x1670,
+ 0x61fd, 0x32d1,
+ 0x61fe, 0x1671,
+ 0x61ff, 0x16c4,
+ 0x6200, 0x16f8,
+ 0x6201, 0x3417,
+ 0x6203, 0x3418,
+ 0x6207, 0x3533,
+ 0x6208, 0x02d1,
+ 0x6209, 0x17a8,
+ 0x620a, 0x0341,
+ 0x620c, 0x03d1,
+ 0x620e, 0x03d0,
+ 0x6210, 0x03d3,
+ 0x6211, 0x04a2,
+ 0x6212, 0x04a1,
+ 0x6214, 0x1991,
+ 0x6215, 0x05d1,
+ 0x6216, 0x05d0,
+ 0x6219, 0x1ca0,
+ 0x621a, 0x0a97,
+ 0x621f, 0x0c58,
+ 0x6220, 0x23e1,
+ 0x6221, 0x0e1a,
+ 0x6223, 0x23e3,
+ 0x6224, 0x23e5,
+ 0x6225, 0x23e4,
+ 0x6227, 0x2697,
+ 0x6229, 0x2696,
+ 0x622a, 0x0fda,
+ 0x622b, 0x2698,
+ 0x622c, 0x463c,
+ 0x622d, 0x28e0,
+ 0x622e, 0x1158,
+ 0x6230, 0x12b7,
+ 0x6232, 0x13d5,
+ 0x6233, 0x14d1,
+ 0x6234, 0x13d6,
+ 0x6236, 0x02d2,
+ 0x6237, 0x451a,
+ 0x6239, 0x3fc2,
+ 0x623a, 0x188d,
+ 0x623d, 0x1992,
+ 0x623e, 0x05d3,
+ 0x623f, 0x05d2,
+ 0x6240, 0x05d4,
+ 0x6241, 0x072f,
+ 0x6242, 0x1aec,
+ 0x6246, 0x1ca1,
+ 0x6247, 0x08c2,
+ 0x6248, 0x0a99,
+ 0x6249, 0x0c59,
+ 0x624a, 0x214b,
+ 0x624b, 0x02d3,
+ 0x624c, 0x44ec,
+ 0x624d, 0x0291,
+ 0x624e, 0x02d4,
+ 0x6250, 0x17a9,
+ 0x6251, 0x0345,
+ 0x6252, 0x0344,
+ 0x6253, 0x0342,
+ 0x6258, 0x03d6,
+ 0x6259, 0x17f2,
+ 0x625a, 0x17f4,
+ 0x625b, 0x03d5,
+ 0x625c, 0x17ec,
+ 0x625e, 0x17ed,
+ 0x6260, 0x17f3,
+ 0x6261, 0x17ef,
+ 0x6262, 0x17f1,
+ 0x6263, 0x03d4,
+ 0x6264, 0x17ee,
+ 0x6265, 0x17f5,
+ 0x6266, 0x17f0,
+ 0x6268, 0x3f15,
+ 0x626d, 0x04a9,
+ 0x626e, 0x04b2,
+ 0x626f, 0x04b0,
+ 0x6270, 0x1897,
+ 0x6271, 0x1894,
+ 0x6272, 0x189c,
+ 0x6273, 0x04ae,
+ 0x6274, 0x189d,
+ 0x6276, 0x04a7,
+ 0x6277, 0x189a,
+ 0x6279, 0x04ad,
+ 0x627a, 0x1896,
+ 0x627b, 0x1895,
+ 0x627c, 0x04ab,
+ 0x627d, 0x189b,
+ 0x627e, 0x04ac,
+ 0x627f, 0x05d5,
+ 0x6280, 0x04a6,
+ 0x6281, 0x1898,
+ 0x6282, 0x3f86,
+ 0x6283, 0x188e,
+ 0x6284, 0x04a3,
+ 0x6285, 0x3f50,
+ 0x6286, 0x04b6,
+ 0x6287, 0x1893,
+ 0x6288, 0x1899,
+ 0x6289, 0x04a8,
+ 0x628a, 0x04aa,
+ 0x628c, 0x188f,
+ 0x628e, 0x1890,
+ 0x6290, 0x43c0,
+ 0x6291, 0x04b5,
+ 0x6292, 0x04af,
+ 0x6293, 0x04b4,
+ 0x6294, 0x1892,
+ 0x6295, 0x04b3,
+ 0x6296, 0x04a5,
+ 0x6297, 0x04a4,
+ 0x6298, 0x04b1,
+ 0x629d, 0x3e96,
+ 0x62a4, 0x3a69,
+ 0x62a6, 0x3fc1,
+ 0x62a8, 0x05e3,
+ 0x62a9, 0x199e,
+ 0x62aa, 0x1997,
+ 0x62ab, 0x05de,
+ 0x62ac, 0x05f1,
+ 0x62ad, 0x1993,
+ 0x62ae, 0x199a,
+ 0x62af, 0x199c,
+ 0x62b0, 0x199f,
+ 0x62b1, 0x05ec,
+ 0x62b3, 0x199b,
+ 0x62b4, 0x1994,
+ 0x62b5, 0x05ea,
+ 0x62b6, 0x1998,
+ 0x62b8, 0x19a0,
+ 0x62b9, 0x05db,
+ 0x62bb, 0x199d,
+ 0x62bc, 0x05e5,
+ 0x62bd, 0x05e4,
+ 0x62be, 0x1996,
+ 0x62bf, 0x05d9,
+ 0x62c2, 0x05da,
+ 0x62c3, 0x3d8f,
+ 0x62c4, 0x05d8,
+ 0x62c5, 0x418a,
+ 0x62c6, 0x05f0,
+ 0x62c7, 0x05e8,
+ 0x62c8, 0x05e2,
+ 0x62c9, 0x05d6,
+ 0x62ca, 0x1999,
+ 0x62cb, 0x05e1,
+ 0x62cc, 0x05d7,
+ 0x62cd, 0x05e9,
+ 0x62ce, 0x05f2,
+ 0x62cf, 0x1aee,
+ 0x62d0, 0x05e6,
+ 0x62d1, 0x1995,
+ 0x62d2, 0x05dc,
+ 0x62d3, 0x05df,
+ 0x62d5, 0x418c,
+ 0x62d6, 0x05ee,
+ 0x62d8, 0x05ed,
+ 0x62d9, 0x05e7,
+ 0x62da, 0x05eb,
+ 0x62db, 0x05dd,
+ 0x62dc, 0x0730,
+ 0x62df, 0x401c,
+ 0x62e5, 0x463d,
+ 0x62eb, 0x1af4,
+ 0x62ec, 0x073c,
+ 0x62ed, 0x0734,
+ 0x62ee, 0x0736,
+ 0x62ef, 0x073b,
+ 0x62f0, 0x1b00,
+ 0x62f1, 0x0739,
+ 0x62f2, 0x1ca2,
+ 0x62f3, 0x08c3,
+ 0x62f4, 0x073e,
+ 0x62f5, 0x1af1,
+ 0x62f6, 0x1af9,
+ 0x62f7, 0x073a,
+ 0x62f8, 0x1af8,
+ 0x62f9, 0x1af5,
+ 0x62fa, 0x1afd,
+ 0x62fb, 0x1aff,
+ 0x62fc, 0x0733,
+ 0x62fd, 0x0737,
+ 0x62fe, 0x073d,
+ 0x62ff, 0x08c5,
+ 0x6300, 0x1afa,
+ 0x6301, 0x0735,
+ 0x6302, 0x0740,
+ 0x6303, 0x1af3,
+ 0x6307, 0x0738,
+ 0x6308, 0x08c4,
+ 0x6309, 0x0732,
+ 0x630b, 0x1af0,
+ 0x630c, 0x1af7,
+ 0x630d, 0x1aef,
+ 0x630e, 0x1af2,
+ 0x630f, 0x1af6,
+ 0x6310, 0x1ca3,
+ 0x6311, 0x073f,
+ 0x6313, 0x1afb,
+ 0x6315, 0x1afe,
+ 0x6316, 0x0731,
+ 0x6318, 0x43c1,
+ 0x6328, 0x08d3,
+ 0x6329, 0x1caf,
+ 0x632a, 0x08d1,
+ 0x632c, 0x1ca5,
+ 0x632d, 0x1cb5,
+ 0x632e, 0x3edd,
+ 0x632f, 0x08c8,
+ 0x6331, 0x3a65,
+ 0x6332, 0x1eed,
+ 0x6333, 0x1cb7,
+ 0x6334, 0x1cb1,
+ 0x6335, 0x3f16,
+ 0x6336, 0x1ca8,
+ 0x6337, 0x3a63,
+ 0x6338, 0x1cba,
+ 0x6339, 0x1cab,
+ 0x633a, 0x08ce,
+ 0x633b, 0x1f04,
+ 0x633c, 0x1cae,
+ 0x633d, 0x08d0,
+ 0x633e, 0x08c7,
+ 0x6340, 0x1cbc,
+ 0x6341, 0x1cb0,
+ 0x6342, 0x08ca,
+ 0x6343, 0x1ca9,
+ 0x6344, 0x1ca6,
+ 0x6346, 0x08cb,
+ 0x6347, 0x1cb6,
+ 0x6348, 0x1cbd,
+ 0x6349, 0x08cd,
+ 0x634a, 0x1cad,
+ 0x634b, 0x1cac,
+ 0x634c, 0x08d5,
+ 0x634d, 0x08d4,
+ 0x634e, 0x08c6,
+ 0x634f, 0x08cc,
+ 0x6350, 0x08cf,
+ 0x6351, 0x1cb9,
+ 0x6354, 0x1cb3,
+ 0x6355, 0x08c9,
+ 0x6356, 0x1ca4,
+ 0x6357, 0x1cbb,
+ 0x6358, 0x1cb2,
+ 0x6359, 0x1cb4,
+ 0x635a, 0x1cb8,
+ 0x6364, 0x3fc7,
+ 0x6365, 0x1eee,
+ 0x6367, 0x0aa1,
+ 0x6368, 0x0ab5,
+ 0x6369, 0x0ab4,
+ 0x636b, 0x0aa9,
+ 0x636c, 0x418e,
+ 0x636d, 0x1f00,
+ 0x636e, 0x1efc,
+ 0x636f, 0x1ef9,
+ 0x6370, 0x1f0b,
+ 0x6371, 0x0aa4,
+ 0x6372, 0x0a9c,
+ 0x6375, 0x1efe,
+ 0x6376, 0x0c69,
+ 0x6377, 0x0aa0,
+ 0x6378, 0x1f06,
+ 0x6379, 0x4367,
+ 0x637a, 0x0ab6,
+ 0x637b, 0x0ab3,
+ 0x637c, 0x1f02,
+ 0x637d, 0x1ef1,
+ 0x637f, 0x3f4b,
+ 0x6380, 0x0ab2,
+ 0x6381, 0x1f08,
+ 0x6382, 0x1ef0,
+ 0x6383, 0x0aa7,
+ 0x6384, 0x0aab,
+ 0x6385, 0x1f07,
+ 0x6387, 0x1efa,
+ 0x6388, 0x0aac,
+ 0x6389, 0x0aa6,
+ 0x638a, 0x1eef,
+ 0x638b, 0x4188,
+ 0x638c, 0x0c5b,
+ 0x638d, 0x1f0a,
+ 0x638e, 0x1ef8,
+ 0x638f, 0x0ab1,
+ 0x6390, 0x1efb,
+ 0x6391, 0x1f09,
+ 0x6392, 0x0ab0,
+ 0x6394, 0x214c,
+ 0x6396, 0x0a9d,
+ 0x6397, 0x1ef6,
+ 0x6398, 0x0aa2,
+ 0x6399, 0x0aad,
+ 0x639b, 0x0aa8,
+ 0x639c, 0x1eff,
+ 0x639d, 0x1ef5,
+ 0x639e, 0x1ef3,
+ 0x639f, 0x1f05,
+ 0x63a0, 0x0a9a,
+ 0x63a1, 0x0aae,
+ 0x63a2, 0x0a9e,
+ 0x63a3, 0x0c5a,
+ 0x63a4, 0x1f03,
+ 0x63a5, 0x0a9f,
+ 0x63a7, 0x0a9b,
+ 0x63a8, 0x0aaa,
+ 0x63a9, 0x0aa5,
+ 0x63aa, 0x0aa3,
+ 0x63ab, 0x1ef7,
+ 0x63ac, 0x0aaf,
+ 0x63ad, 0x1ef4,
+ 0x63ae, 0x1f01,
+ 0x63af, 0x1efd,
+ 0x63b0, 0x214e,
+ 0x63b1, 0x214d,
+ 0x63b9, 0x3e9d,
+ 0x63bd, 0x1ef2,
+ 0x63be, 0x215e,
+ 0x63c0, 0x0c5d,
+ 0x63c1, 0x46a8,
+ 0x63c2, 0x2164,
+ 0x63c3, 0x2153,
+ 0x63c4, 0x2161,
+ 0x63c5, 0x23e6,
+ 0x63c6, 0x0c60,
+ 0x63c7, 0x2165,
+ 0x63c8, 0x2168,
+ 0x63c9, 0x0c5f,
+ 0x63ca, 0x2156,
+ 0x63cb, 0x2167,
+ 0x63cc, 0x2166,
+ 0x63cd, 0x0c61,
+ 0x63ce, 0x214f,
+ 0x63cf, 0x0c5c,
+ 0x63d0, 0x0c64,
+ 0x63d1, 0x3a66,
+ 0x63d2, 0x0c62,
+ 0x63d3, 0x2163,
+ 0x63d5, 0x2159,
+ 0x63d6, 0x0c66,
+ 0x63d7, 0x216a,
+ 0x63d8, 0x2162,
+ 0x63d9, 0x216b,
+ 0x63da, 0x0c6e,
+ 0x63db, 0x0c6c,
+ 0x63dc, 0x2160,
+ 0x63dd, 0x215f,
+ 0x63de, 0x3e60,
+ 0x63df, 0x215d,
+ 0x63e0, 0x2157,
+ 0x63e1, 0x0c65,
+ 0x63e2, 0x4641,
+ 0x63e3, 0x0c63,
+ 0x63e4, 0x1caa,
+ 0x63e5, 0x2150,
+ 0x63e6, 0x489f,
+ 0x63e7, 0x2404,
+ 0x63e8, 0x2151,
+ 0x63e9, 0x0c5e,
+ 0x63ea, 0x0c6b,
+ 0x63eb, 0x23e8,
+ 0x63ed, 0x0c67,
+ 0x63ef, 0x2152,
+ 0x63f0, 0x2169,
+ 0x63f1, 0x23e7,
+ 0x63f2, 0x215a,
+ 0x63f3, 0x2155,
+ 0x63f4, 0x0c6a,
+ 0x63f5, 0x215b,
+ 0x63f6, 0x2158,
+ 0x63f8, 0x4192,
+ 0x63f9, 0x0c6f,
+ 0x63fb, 0x4642,
+ 0x63fc, 0x3e9c,
+ 0x63fe, 0x3e9e,
+ 0x6406, 0x0e2a,
+ 0x6407, 0x4643,
+ 0x6409, 0x23eb,
+ 0x640a, 0x23fe,
+ 0x640b, 0x2403,
+ 0x640c, 0x23f7,
+ 0x640d, 0x0e26,
+ 0x640e, 0x2408,
+ 0x640f, 0x0e23,
+ 0x6410, 0x23e9,
+ 0x6412, 0x23ea,
+ 0x6413, 0x0e1c,
+ 0x6414, 0x0e25,
+ 0x6415, 0x23f1,
+ 0x6416, 0x0e28,
+ 0x6418, 0x23f2,
+ 0x641a, 0x23ff,
+ 0x641b, 0x2405,
+ 0x641c, 0x0e24,
+ 0x641e, 0x0e1e,
+ 0x641f, 0x23f0,
+ 0x6420, 0x23ec,
+ 0x6421, 0x2407,
+ 0x6422, 0x23f5,
+ 0x6424, 0x23ed,
+ 0x6425, 0x2401,
+ 0x6426, 0x23f8,
+ 0x6427, 0x2402,
+ 0x6428, 0x23fa,
+ 0x642a, 0x0e1f,
+ 0x642b, 0x2699,
+ 0x642c, 0x0e22,
+ 0x642d, 0x0e20,
+ 0x642e, 0x2406,
+ 0x642f, 0x23fd,
+ 0x6430, 0x23f9,
+ 0x6432, 0x45d9,
+ 0x6433, 0x23ee,
+ 0x6434, 0x0fe4,
+ 0x6435, 0x23fc,
+ 0x6436, 0x0e27,
+ 0x6437, 0x23f4,
+ 0x6438, 0x4191,
+ 0x6439, 0x23f3,
+ 0x643a, 0x419d,
+ 0x643b, 0x3a6b,
+ 0x643d, 0x0e21,
+ 0x643e, 0x0e1d,
+ 0x643f, 0x26ae,
+ 0x6440, 0x2400,
+ 0x6441, 0x23fb,
+ 0x6443, 0x23ef,
+ 0x644b, 0x26a9,
+ 0x644d, 0x269a,
+ 0x644e, 0x26a5,
+ 0x6450, 0x26ac,
+ 0x6451, 0x0fe2,
+ 0x6452, 0x0c6d,
+ 0x6453, 0x26aa,
+ 0x6454, 0x0fdd,
+ 0x6458, 0x0fdc,
+ 0x6459, 0x26b1,
+ 0x645a, 0x43c2,
+ 0x645b, 0x269b,
+ 0x645c, 0x26a8,
+ 0x645d, 0x269c,
+ 0x645e, 0x26a7,
+ 0x645f, 0x0fe0,
+ 0x6460, 0x26ab,
+ 0x6461, 0x215c,
+ 0x6465, 0x26b2,
+ 0x6466, 0x26a3,
+ 0x6467, 0x0fe3,
+ 0x6468, 0x28ee,
+ 0x6469, 0x1159,
+ 0x646b, 0x26b0,
+ 0x646c, 0x26af,
+ 0x646d, 0x0fe5,
+ 0x646e, 0x28e1,
+ 0x646f, 0x115a,
+ 0x6470, 0x28e2,
+ 0x6471, 0x3a5b,
+ 0x6472, 0x269f,
+ 0x6474, 0x269d,
+ 0x6475, 0x26a2,
+ 0x6476, 0x269e,
+ 0x6477, 0x26b3,
+ 0x6478, 0x0fdf,
+ 0x6479, 0x115b,
+ 0x647a, 0x0fe1,
+ 0x647b, 0x0fe6,
+ 0x647c, 0x436c,
+ 0x647d, 0x26a1,
+ 0x647f, 0x26ad,
+ 0x6482, 0x26a6,
+ 0x6485, 0x28e5,
+ 0x6487, 0x0fdb,
+ 0x6488, 0x115e,
+ 0x6489, 0x2b54,
+ 0x648a, 0x28ea,
+ 0x648b, 0x28e9,
+ 0x648c, 0x28eb,
+ 0x648d, 0x4323,
+ 0x648f, 0x28e8,
+ 0x6490, 0x115f,
+ 0x6491, 0x43c3,
+ 0x6492, 0x1165,
+ 0x6493, 0x1162,
+ 0x6495, 0x1163,
+ 0x6496, 0x28e3,
+ 0x6497, 0x28e6,
+ 0x6498, 0x28f0,
+ 0x6499, 0x116b,
+ 0x649a, 0x1169,
+ 0x649c, 0x28e7,
+ 0x649d, 0x2154,
+ 0x649e, 0x115c,
+ 0x649f, 0x28ed,
+ 0x64a0, 0x28e4,
+ 0x64a2, 0x116c,
+ 0x64a3, 0x28ec,
+ 0x64a4, 0x0fde,
+ 0x64a5, 0x1161,
+ 0x64a6, 0x26a4,
+ 0x64a9, 0x1164,
+ 0x64ab, 0x1168,
+ 0x64ac, 0x116a,
+ 0x64ad, 0x1167,
+ 0x64ae, 0x1166,
+ 0x64af, 0x42e1,
+ 0x64b0, 0x1160,
+ 0x64b1, 0x28ef,
+ 0x64b2, 0x115d,
+ 0x64b3, 0x116d,
+ 0x64b4, 0x4340,
+ 0x64b6, 0x3a64,
+ 0x64bb, 0x12bb,
+ 0x64bd, 0x2b53,
+ 0x64be, 0x12c5,
+ 0x64bf, 0x12c2,
+ 0x64c0, 0x4645,
+ 0x64c1, 0x12b9,
+ 0x64c2, 0x12c0,
+ 0x64c3, 0x2b55,
+ 0x64c4, 0x12be,
+ 0x64c5, 0x12b8,
+ 0x64c7, 0x12bf,
+ 0x64c9, 0x2b52,
+ 0x64ca, 0x13d8,
+ 0x64cb, 0x12ba,
+ 0x64cd, 0x12c1,
+ 0x64ce, 0x13d7,
+ 0x64cf, 0x2b51,
+ 0x64d0, 0x2b50,
+ 0x64d2, 0x12c3,
+ 0x64d3, 0x3f03,
+ 0x64d4, 0x12c4,
+ 0x64d6, 0x2b4f,
+ 0x64d7, 0x2b4e,
+ 0x64d8, 0x13d9,
+ 0x64d9, 0x2b58,
+ 0x64da, 0x12bd,
+ 0x64db, 0x2b56,
+ 0x64dd, 0x431e,
+ 0x64e0, 0x13da,
+ 0x64e1, 0x4199,
+ 0x64e2, 0x13df,
+ 0x64e3, 0x2d6a,
+ 0x64e4, 0x2d6c,
+ 0x64e5, 0x419a,
+ 0x64e6, 0x13dc,
+ 0x64e7, 0x37a8,
+ 0x64e8, 0x2d6d,
+ 0x64e9, 0x2d69,
+ 0x64ea, 0x434a,
+ 0x64eb, 0x2d6b,
+ 0x64ec, 0x13dd,
+ 0x64ed, 0x13e0,
+ 0x64ef, 0x2d68,
+ 0x64f0, 0x13db,
+ 0x64f1, 0x13de,
+ 0x64f2, 0x14d3,
+ 0x64f3, 0x2b57,
+ 0x64f4, 0x14d2,
+ 0x64f7, 0x14d8,
+ 0x64f8, 0x2f2b,
+ 0x64fa, 0x14d6,
+ 0x64fc, 0x2f2e,
+ 0x64fd, 0x2f2a,
+ 0x64fe, 0x14d4,
+ 0x64ff, 0x2f28,
+ 0x6500, 0x1582,
+ 0x6501, 0x2f2c,
+ 0x6503, 0x2f2d,
+ 0x6504, 0x2f29,
+ 0x6506, 0x14d5,
+ 0x6507, 0x3090,
+ 0x6509, 0x3093,
+ 0x650a, 0x4536,
+ 0x650c, 0x3094,
+ 0x650d, 0x3092,
+ 0x650e, 0x3095,
+ 0x650f, 0x1583,
+ 0x6510, 0x3091,
+ 0x6511, 0x3aa9,
+ 0x6513, 0x31d7,
+ 0x6514, 0x1617,
+ 0x6515, 0x31d6,
+ 0x6516, 0x31d5,
+ 0x6517, 0x31d4,
+ 0x6518, 0x1616,
+ 0x6519, 0x1618,
+ 0x651b, 0x32d2,
+ 0x651c, 0x1673,
+ 0x651d, 0x1672,
+ 0x651e, 0x4187,
+ 0x651f, 0x3ec0,
+ 0x6520, 0x3382,
+ 0x6521, 0x3381,
+ 0x6522, 0x3384,
+ 0x6523, 0x16f9,
+ 0x6524, 0x16c5,
+ 0x6525, 0x341b,
+ 0x6526, 0x3383,
+ 0x6529, 0x341a,
+ 0x652a, 0x16fb,
+ 0x652b, 0x16fa,
+ 0x652c, 0x1721,
+ 0x652d, 0x3484,
+ 0x652e, 0x34ca,
+ 0x652f, 0x02d5,
+ 0x6530, 0x3e62,
+ 0x6532, 0x216c,
+ 0x6533, 0x2b59,
+ 0x6534, 0x022c,
+ 0x6535, 0x44ed,
+ 0x6536, 0x03d7,
+ 0x6537, 0x17f6,
+ 0x6538, 0x04b9,
+ 0x6539, 0x04b7,
+ 0x653b, 0x04b8,
+ 0x653d, 0x19a1,
+ 0x653e, 0x05f3,
+ 0x653f, 0x0741,
+ 0x6541, 0x1b01,
+ 0x6543, 0x1b02,
+ 0x6545, 0x0742,
+ 0x6546, 0x1cbf,
+ 0x6548, 0x08d6,
+ 0x654a, 0x1cbe,
+ 0x654d, 0x419f,
+ 0x654f, 0x0abd,
+ 0x6551, 0x0ab9,
+ 0x6553, 0x1f0c,
+ 0x6554, 0x0ac0,
+ 0x6555, 0x0abf,
+ 0x6556, 0x0ab8,
+ 0x6557, 0x0abb,
+ 0x6558, 0x0abe,
+ 0x6559, 0x0aba,
+ 0x655c, 0x2170,
+ 0x655d, 0x0ab7,
+ 0x655e, 0x0c70,
+ 0x655f, 0x41a5,
+ 0x6562, 0x0c72,
+ 0x6564, 0x216f,
+ 0x6565, 0x2172,
+ 0x6566, 0x0c71,
+ 0x6567, 0x216d,
+ 0x6568, 0x2171,
+ 0x656a, 0x216e,
+ 0x656b, 0x3a6c,
+ 0x656c, 0x0e2b,
+ 0x656d, 0x41a4,
+ 0x656f, 0x2409,
+ 0x6572, 0x0fe7,
+ 0x6573, 0x26b4,
+ 0x6574, 0x12c6,
+ 0x6575, 0x116e,
+ 0x6576, 0x28f1,
+ 0x6577, 0x116f,
+ 0x6579, 0x28f3,
+ 0x657a, 0x28f2,
+ 0x657b, 0x28f4,
+ 0x657c, 0x2b5b,
+ 0x657f, 0x2b5a,
+ 0x6580, 0x2d6f,
+ 0x6581, 0x2d6e,
+ 0x6582, 0x13e1,
+ 0x6584, 0x3096,
+ 0x6585, 0x41a3,
+ 0x6586, 0x4648,
+ 0x6587, 0x02d6,
+ 0x6588, 0x410b,
+ 0x6589, 0x4554,
+ 0x658c, 0x2173,
+ 0x6590, 0x0c75,
+ 0x6591, 0x0c74,
+ 0x6592, 0x240a,
+ 0x6594, 0x2f2f,
+ 0x6595, 0x1674,
+ 0x6596, 0x341c,
+ 0x6597, 0x02d7,
+ 0x6599, 0x08d8,
+ 0x659b, 0x0ac2,
+ 0x659c, 0x0ac1,
+ 0x659d, 0x2174,
+ 0x659f, 0x0e2c,
+ 0x65a0, 0x26b5,
+ 0x65a1, 0x0fe8,
+ 0x65a2, 0x2b5c,
+ 0x65a4, 0x02d8,
+ 0x65a5, 0x0346,
+ 0x65a7, 0x05f4,
+ 0x65a8, 0x19a2,
+ 0x65aa, 0x1b03,
+ 0x65ab, 0x0743,
+ 0x65ac, 0x0ac3,
+ 0x65ae, 0x2176,
+ 0x65af, 0x0c76,
+ 0x65b0, 0x0e2d,
+ 0x65b2, 0x28f5,
+ 0x65b5, 0x41a7,
+ 0x65b6, 0x2d70,
+ 0x65b7, 0x14d9,
+ 0x65b8, 0x34cb,
+ 0x65b9, 0x02d9,
+ 0x65bb, 0x19a3,
+ 0x65bc, 0x05f5,
+ 0x65bd, 0x0744,
+ 0x65be, 0x3e3b,
+ 0x65bf, 0x1b04,
+ 0x65c1, 0x08d9,
+ 0x65c2, 0x1cc3,
+ 0x65c3, 0x1cc1,
+ 0x65c5, 0x08da,
+ 0x65c6, 0x1cc0,
+ 0x65cb, 0x0ac5,
+ 0x65cd, 0x1f0d,
+ 0x65ce, 0x0ac7,
+ 0x65cf, 0x0ac4,
+ 0x65d0, 0x2177,
+ 0x65d1, 0x41aa,
+ 0x65d2, 0x2178,
+ 0x65d3, 0x240b,
+ 0x65d4, 0x3ba8,
+ 0x65d6, 0x0fea,
+ 0x65d7, 0x0fe9,
+ 0x65da, 0x2d71,
+ 0x65db, 0x2f30,
+ 0x65dd, 0x3098,
+ 0x65de, 0x3097,
+ 0x65df, 0x31d8,
+ 0x65e0, 0x022d,
+ 0x65e1, 0x1789,
+ 0x65e2, 0x0745,
+ 0x65e3, 0x41ae,
+ 0x65e5, 0x02da,
+ 0x65e6, 0x0347,
+ 0x65e8, 0x03d9,
+ 0x65e9, 0x03d8,
+ 0x65ec, 0x03da,
+ 0x65ee, 0x17f8,
+ 0x65ef, 0x17f7,
+ 0x65f0, 0x189e,
+ 0x65f1, 0x04ba,
+ 0x65f2, 0x18a1,
+ 0x65f3, 0x18a0,
+ 0x65f4, 0x189f,
+ 0x65f5, 0x18a2,
+ 0x65fa, 0x05f6,
+ 0x65fb, 0x19a9,
+ 0x65fc, 0x19a5,
+ 0x65fd, 0x19ae,
+ 0x65ff, 0x464a,
+ 0x6600, 0x05fd,
+ 0x6602, 0x05fb,
+ 0x6603, 0x19aa,
+ 0x6604, 0x19a6,
+ 0x6605, 0x19ad,
+ 0x6606, 0x05fa,
+ 0x6607, 0x0601,
+ 0x6608, 0x19a8,
+ 0x6609, 0x19a4,
+ 0x660a, 0x0600,
+ 0x660b, 0x19ab,
+ 0x660c, 0x05f9,
+ 0x660d, 0x19ac,
+ 0x660e, 0x05fc,
+ 0x660f, 0x05fe,
+ 0x6610, 0x19b0,
+ 0x6611, 0x19af,
+ 0x6612, 0x19a7,
+ 0x6613, 0x05f8,
+ 0x6614, 0x05f7,
+ 0x6615, 0x05ff,
+ 0x6618, 0x41b1,
+ 0x661c, 0x1b09,
+ 0x661d, 0x1b0f,
+ 0x661e, 0x3a93,
+ 0x661f, 0x074b,
+ 0x6620, 0x0748,
+ 0x6621, 0x1b06,
+ 0x6622, 0x1b0b,
+ 0x6623, 0x4295,
+ 0x6624, 0x074e,
+ 0x6625, 0x0746,
+ 0x6626, 0x1b0a,
+ 0x6627, 0x0749,
+ 0x6628, 0x074c,
+ 0x662b, 0x1b0d,
+ 0x662d, 0x0747,
+ 0x662e, 0x1b12,
+ 0x662f, 0x074a,
+ 0x6630, 0x3a8d,
+ 0x6631, 0x074d,
+ 0x6632, 0x1b07,
+ 0x6633, 0x1b0c,
+ 0x6634, 0x1b10,
+ 0x6635, 0x1b08,
+ 0x6636, 0x1b05,
+ 0x6639, 0x1b11,
+ 0x663a, 0x1b0e,
+ 0x6641, 0x08e2,
+ 0x6642, 0x08db,
+ 0x6643, 0x08de,
+ 0x6644, 0x41b4,
+ 0x6645, 0x08e1,
+ 0x6647, 0x1cc6,
+ 0x6648, 0x3d99,
+ 0x6649, 0x08dc,
+ 0x664a, 0x1cc4,
+ 0x664b, 0x41b7,
+ 0x664c, 0x08e0,
+ 0x664f, 0x08dd,
+ 0x6651, 0x1cc7,
+ 0x6652, 0x08df,
+ 0x6653, 0x464b,
+ 0x6657, 0x409b,
+ 0x6659, 0x1f11,
+ 0x665a, 0x0ac9,
+ 0x665b, 0x1f10,
+ 0x665c, 0x1f12,
+ 0x665d, 0x0ac8,
+ 0x665e, 0x0acd,
+ 0x665f, 0x1cc5,
+ 0x6661, 0x1f0f,
+ 0x6662, 0x1f13,
+ 0x6663, 0x3a90,
+ 0x6664, 0x0aca,
+ 0x6665, 0x1f0e,
+ 0x6666, 0x0acc,
+ 0x6667, 0x41b9,
+ 0x6668, 0x0acb,
+ 0x666a, 0x217f,
+ 0x666b, 0x3a8b,
+ 0x666c, 0x217a,
+ 0x666e, 0x0c77,
+ 0x666f, 0x0c7b,
+ 0x6670, 0x0c78,
+ 0x6671, 0x217d,
+ 0x6672, 0x2180,
+ 0x6673, 0x41bb,
+ 0x6674, 0x0c79,
+ 0x6676, 0x0c7a,
+ 0x6677, 0x0c7f,
+ 0x6678, 0x2414,
+ 0x6679, 0x217e,
+ 0x667a, 0x0c7d,
+ 0x667b, 0x217b,
+ 0x667c, 0x2179,
+ 0x667d, 0x469b,
+ 0x667e, 0x0c7e,
+ 0x6680, 0x217c,
+ 0x6684, 0x0e33,
+ 0x6685, 0x4162,
+ 0x6686, 0x240c,
+ 0x6687, 0x0e30,
+ 0x6689, 0x0e2f,
+ 0x668a, 0x2411,
+ 0x668b, 0x2410,
+ 0x668c, 0x240d,
+ 0x668d, 0x0e35,
+ 0x668e, 0x3a89,
+ 0x6690, 0x240f,
+ 0x6691, 0x0c7c,
+ 0x6692, 0x464d,
+ 0x6694, 0x2413,
+ 0x6695, 0x240e,
+ 0x6696, 0x0e32,
+ 0x6697, 0x0e2e,
+ 0x6698, 0x0e34,
+ 0x6699, 0x2412,
+ 0x669a, 0x3d3d,
+ 0x669d, 0x0fed,
+ 0x669f, 0x26b8,
+ 0x66a0, 0x26b7,
+ 0x66a1, 0x26b6,
+ 0x66a2, 0x0feb,
+ 0x66a4, 0x40ba,
+ 0x66a8, 0x0fec,
+ 0x66a9, 0x28f9,
+ 0x66aa, 0x28fc,
+ 0x66ab, 0x1172,
+ 0x66ad, 0x4948,
+ 0x66ae, 0x1171,
+ 0x66af, 0x28fd,
+ 0x66b0, 0x28f8,
+ 0x66b1, 0x1174,
+ 0x66b2, 0x28fa,
+ 0x66b3, 0x40b5,
+ 0x66b4, 0x1173,
+ 0x66b5, 0x28f7,
+ 0x66b6, 0x3e13,
+ 0x66b7, 0x28fb,
+ 0x66b8, 0x12cc,
+ 0x66b9, 0x12c9,
+ 0x66ba, 0x2b65,
+ 0x66bb, 0x2b64,
+ 0x66bd, 0x2b63,
+ 0x66be, 0x2b5e,
+ 0x66bf, 0x3d9a,
+ 0x66c0, 0x2b5f,
+ 0x66c4, 0x12ca,
+ 0x66c6, 0x12c7,
+ 0x66c7, 0x12cb,
+ 0x66c8, 0x2b5d,
+ 0x66c9, 0x12c8,
+ 0x66ca, 0x2b60,
+ 0x66cc, 0x2b66,
+ 0x66cd, 0x40b8,
+ 0x66ce, 0x3a77,
+ 0x66cf, 0x2b62,
+ 0x66d2, 0x2d72,
+ 0x66d6, 0x13e4,
+ 0x66d8, 0x2f33,
+ 0x66d9, 0x13e3,
+ 0x66da, 0x2f31,
+ 0x66dc, 0x14da,
+ 0x66dd, 0x1585,
+ 0x66de, 0x3099,
+ 0x66e0, 0x1584,
+ 0x66e3, 0x31da,
+ 0x66e6, 0x1619,
+ 0x66e8, 0x31d9,
+ 0x66e9, 0x1675,
+ 0x66eb, 0x341d,
+ 0x66ec, 0x16fc,
+ 0x66ed, 0x3485,
+ 0x66f0, 0x02db,
+ 0x66f1, 0x3e84,
+ 0x66f2, 0x03dc,
+ 0x66f4, 0x04bb,
+ 0x66f6, 0x19b1,
+ 0x66f7, 0x074f,
+ 0x66f8, 0x08e3,
+ 0x66f9, 0x0ace,
+ 0x66fc, 0x0a1f,
+ 0x66fe, 0x0c80,
+ 0x6700, 0x0bf0,
+ 0x6701, 0x2181,
+ 0x6702, 0x41c4,
+ 0x6703, 0x0e36,
+ 0x6704, 0x26ba,
+ 0x6705, 0x26b9,
+ 0x6708, 0x02dc,
+ 0x6709, 0x03de,
+ 0x670a, 0x19b2,
+ 0x670b, 0x0603,
+ 0x670c, 0x3fe2,
+ 0x670d, 0x0602,
+ 0x670e, 0x3da1,
+ 0x670f, 0x1b13,
+ 0x6712, 0x1cc8,
+ 0x6714, 0x08e4,
+ 0x6716, 0x464f,
+ 0x6717, 0x08e6,
+ 0x6718, 0x1f14,
+ 0x671b, 0x0ad0,
+ 0x671d, 0x0c83,
+ 0x671e, 0x3d8b,
+ 0x671f, 0x0c82,
+ 0x6720, 0x2415,
+ 0x6721, 0x2522,
+ 0x6722, 0x26bb,
+ 0x6723, 0x2b67,
+ 0x6725, 0x379f,
+ 0x6726, 0x14db,
+ 0x6727, 0x161a,
+ 0x6728, 0x02dd,
+ 0x672a, 0x034a,
+ 0x672c, 0x0349,
+ 0x672d, 0x034c,
+ 0x672e, 0x0348,
+ 0x6731, 0x03e1,
+ 0x6733, 0x1800,
+ 0x6734, 0x03e0,
+ 0x6735, 0x03e2,
+ 0x6736, 0x3e41,
+ 0x6738, 0x17fb,
+ 0x6739, 0x17fa,
+ 0x673a, 0x17fd,
+ 0x673b, 0x17fc,
+ 0x673c, 0x17ff,
+ 0x673d, 0x03df,
+ 0x673e, 0x17f9,
+ 0x673f, 0x17fe,
+ 0x6744, 0x401b,
+ 0x6745, 0x18a3,
+ 0x6746, 0x04c5,
+ 0x6747, 0x18a4,
+ 0x6748, 0x18a8,
+ 0x6749, 0x04c4,
+ 0x674b, 0x18ac,
+ 0x674c, 0x18a7,
+ 0x674d, 0x18aa,
+ 0x674e, 0x04bd,
+ 0x6753, 0x04c7,
+ 0x6755, 0x18a6,
+ 0x6756, 0x04c2,
+ 0x6757, 0x04c8,
+ 0x6759, 0x18a5,
+ 0x675a, 0x18ab,
+ 0x675c, 0x04c1,
+ 0x675d, 0x18a9,
+ 0x675e, 0x04c3,
+ 0x675f, 0x04bc,
+ 0x6760, 0x04c6,
+ 0x6761, 0x3d66,
+ 0x6762, 0x41cb,
+ 0x6767, 0x41ca,
+ 0x676a, 0x0618,
+ 0x676c, 0x19b4,
+ 0x676d, 0x0604,
+ 0x676f, 0x060e,
+ 0x6771, 0x0607,
+ 0x6772, 0x0619,
+ 0x6773, 0x0609,
+ 0x6774, 0x19bc,
+ 0x6775, 0x0614,
+ 0x6776, 0x19b7,
+ 0x6777, 0x060a,
+ 0x6778, 0x19c6,
+ 0x677a, 0x19bf,
+ 0x677b, 0x19b8,
+ 0x677c, 0x0617,
+ 0x677d, 0x19c4,
+ 0x677e, 0x0612,
+ 0x677f, 0x0610,
+ 0x6781, 0x19c5,
+ 0x6783, 0x19c3,
+ 0x6784, 0x19bb,
+ 0x6785, 0x19b3,
+ 0x6786, 0x19ba,
+ 0x6787, 0x060b,
+ 0x6789, 0x0611,
+ 0x678b, 0x0605,
+ 0x678c, 0x19be,
+ 0x678d, 0x19bd,
+ 0x678e, 0x19b5,
+ 0x678f, 0x46c1,
+ 0x6790, 0x0613,
+ 0x6791, 0x19c1,
+ 0x6792, 0x19b6,
+ 0x6793, 0x0616,
+ 0x6794, 0x19c8,
+ 0x6795, 0x0606,
+ 0x6797, 0x060d,
+ 0x6798, 0x19b9,
+ 0x6799, 0x19c2,
+ 0x679a, 0x0615,
+ 0x679c, 0x0608,
+ 0x679d, 0x060c,
+ 0x679f, 0x19c0,
+ 0x67a0, 0x3d7a,
+ 0x67a4, 0x4651,
+ 0x67ac, 0x41e3,
+ 0x67ae, 0x1b34,
+ 0x67af, 0x0757,
+ 0x67b0, 0x0764,
+ 0x67b1, 0x41f4,
+ 0x67b2, 0x1b2f,
+ 0x67b3, 0x1b25,
+ 0x67b4, 0x075d,
+ 0x67b5, 0x1b23,
+ 0x67b6, 0x0756,
+ 0x67b7, 0x1b1e,
+ 0x67b8, 0x0760,
+ 0x67b9, 0x1b2b,
+ 0x67ba, 0x1b18,
+ 0x67bb, 0x1b1a,
+ 0x67bf, 0x37fa,
+ 0x67c0, 0x1b1d,
+ 0x67c1, 0x1b15,
+ 0x67c2, 0x1b2a,
+ 0x67c3, 0x1b3a,
+ 0x67c4, 0x075b,
+ 0x67c5, 0x1b1f,
+ 0x67c6, 0x1b31,
+ 0x67c8, 0x1b17,
+ 0x67c9, 0x1b38,
+ 0x67cb, 0x1b3c,
+ 0x67cc, 0x1b33,
+ 0x67cd, 0x1b24,
+ 0x67ce, 0x1b2c,
+ 0x67cf, 0x0761,
+ 0x67d0, 0x0754,
+ 0x67d1, 0x075c,
+ 0x67d2, 0x0768,
+ 0x67d3, 0x0751,
+ 0x67d4, 0x0753,
+ 0x67d6, 0x3b58,
+ 0x67d7, 0x41ce,
+ 0x67d8, 0x1b1c,
+ 0x67d9, 0x0765,
+ 0x67da, 0x075e,
+ 0x67db, 0x1b36,
+ 0x67dc, 0x1b19,
+ 0x67dd, 0x0767,
+ 0x67de, 0x0762,
+ 0x67df, 0x1b22,
+ 0x67e2, 0x0766,
+ 0x67e3, 0x1b29,
+ 0x67e4, 0x1b21,
+ 0x67e5, 0x075f,
+ 0x67e6, 0x1b35,
+ 0x67e7, 0x1b2d,
+ 0x67e9, 0x0759,
+ 0x67ea, 0x1b3b,
+ 0x67eb, 0x1b20,
+ 0x67ec, 0x0755,
+ 0x67ed, 0x1b32,
+ 0x67ee, 0x1b28,
+ 0x67ef, 0x075a,
+ 0x67f0, 0x1b2e,
+ 0x67f1, 0x0752,
+ 0x67f2, 0x1b16,
+ 0x67f3, 0x0763,
+ 0x67f4, 0x08f5,
+ 0x67f5, 0x0758,
+ 0x67f6, 0x1b27,
+ 0x67f7, 0x1b26,
+ 0x67f8, 0x1b1b,
+ 0x67f9, 0x3996,
+ 0x67fa, 0x1b37,
+ 0x67fc, 0x1b30,
+ 0x67fe, 0x4555,
+ 0x67ff, 0x0750,
+ 0x6800, 0x43c7,
+ 0x6801, 0x41d3,
+ 0x6802, 0x3fc8,
+ 0x6803, 0x3d6a,
+ 0x6804, 0x4556,
+ 0x680d, 0x4281,
+ 0x6810, 0x399c,
+ 0x6812, 0x1cdd,
+ 0x6813, 0x08fc,
+ 0x6814, 0x1cde,
+ 0x6816, 0x1cd2,
+ 0x6817, 0x08f1,
+ 0x6818, 0x08fd,
+ 0x681a, 0x1ccb,
+ 0x681b, 0x4072,
+ 0x681c, 0x1cd4,
+ 0x681d, 0x1cdc,
+ 0x681e, 0x46c2,
+ 0x681f, 0x1cca,
+ 0x6820, 0x1ce5,
+ 0x6821, 0x08e7,
+ 0x6822, 0x41d0,
+ 0x6825, 0x1ce4,
+ 0x6826, 0x1cdf,
+ 0x6828, 0x1ce0,
+ 0x6829, 0x08ef,
+ 0x682a, 0x08fa,
+ 0x682b, 0x1cd6,
+ 0x682d, 0x1cd7,
+ 0x682e, 0x1ce1,
+ 0x682f, 0x1cd8,
+ 0x6831, 0x1cd3,
+ 0x6832, 0x1ccd,
+ 0x6834, 0x1cdb,
+ 0x6835, 0x1cd5,
+ 0x6836, 0x3e2e,
+ 0x6837, 0x421d,
+ 0x6838, 0x08e8,
+ 0x6839, 0x08ec,
+ 0x683a, 0x1ce3,
+ 0x683b, 0x1ccf,
+ 0x683c, 0x08f8,
+ 0x683d, 0x08f4,
+ 0x683e, 0x4147,
+ 0x6840, 0x08f7,
+ 0x6841, 0x08fe,
+ 0x6842, 0x08ed,
+ 0x6843, 0x08f9,
+ 0x6844, 0x1cda,
+ 0x6845, 0x08fb,
+ 0x6846, 0x08ea,
+ 0x6847, 0x3beb,
+ 0x6848, 0x08e9,
+ 0x6849, 0x1ccc,
+ 0x684a, 0x4653,
+ 0x684b, 0x1cd0,
+ 0x684c, 0x08f2,
+ 0x684d, 0x1ce2,
+ 0x684e, 0x1cd9,
+ 0x684f, 0x1cd1,
+ 0x6850, 0x08f6,
+ 0x6851, 0x08f3,
+ 0x6853, 0x08eb,
+ 0x6854, 0x08ee,
+ 0x6855, 0x3d90,
+ 0x6856, 0x3814,
+ 0x685d, 0x41d6,
+ 0x6865, 0x4557,
+ 0x686b, 0x1f29,
+ 0x686d, 0x1f19,
+ 0x686f, 0x1f1e,
+ 0x6871, 0x1f2d,
+ 0x6872, 0x1f2a,
+ 0x6874, 0x1f23,
+ 0x6875, 0x1f22,
+ 0x6876, 0x0ad7,
+ 0x6877, 0x1f26,
+ 0x6878, 0x1f35,
+ 0x6879, 0x1f15,
+ 0x687b, 0x1f36,
+ 0x687c, 0x1f28,
+ 0x687d, 0x1f3a,
+ 0x687e, 0x1f2e,
+ 0x687f, 0x0ad6,
+ 0x6880, 0x1f2c,
+ 0x6881, 0x0ad1,
+ 0x6882, 0x0ae6,
+ 0x6883, 0x0adc,
+ 0x6884, 0x4654,
+ 0x6885, 0x0ae0,
+ 0x6886, 0x0adf,
+ 0x6887, 0x1f16,
+ 0x6888, 0x46b7,
+ 0x6889, 0x1f33,
+ 0x688a, 0x1f39,
+ 0x688b, 0x1f31,
+ 0x688c, 0x1f38,
+ 0x688f, 0x1f25,
+ 0x6890, 0x1f17,
+ 0x6891, 0x1f37,
+ 0x6892, 0x1f27,
+ 0x6893, 0x0ad4,
+ 0x6894, 0x0ae1,
+ 0x6896, 0x1f30,
+ 0x6897, 0x0ada,
+ 0x6898, 0x3aaa,
+ 0x689b, 0x1f2f,
+ 0x689c, 0x1f18,
+ 0x689d, 0x0ae2,
+ 0x689f, 0x0ae4,
+ 0x68a0, 0x1f32,
+ 0x68a1, 0x0ae5,
+ 0x68a2, 0x0ad3,
+ 0x68a3, 0x1f1f,
+ 0x68a4, 0x1f34,
+ 0x68a6, 0x40e4,
+ 0x68a7, 0x0ad9,
+ 0x68a8, 0x0ae3,
+ 0x68a9, 0x1f21,
+ 0x68aa, 0x1f2b,
+ 0x68ab, 0x1f1c,
+ 0x68ac, 0x1f20,
+ 0x68ad, 0x0ade,
+ 0x68ae, 0x1f1b,
+ 0x68af, 0x0ad2,
+ 0x68b0, 0x0adb,
+ 0x68b1, 0x0ad8,
+ 0x68b2, 0x1f24,
+ 0x68b3, 0x08f0,
+ 0x68b4, 0x2198,
+ 0x68b5, 0x0ad5,
+ 0x68b6, 0x3a9e,
+ 0x68b9, 0x3d14,
+ 0x68bd, 0x427c,
+ 0x68c3, 0x41dc,
+ 0x68c4, 0x0add,
+ 0x68c5, 0x3c2e,
+ 0x68c6, 0x219b,
+ 0x68c7, 0x21b1,
+ 0x68c8, 0x21a6,
+ 0x68c9, 0x0c97,
+ 0x68ca, 0x42eb,
+ 0x68cb, 0x0c92,
+ 0x68cc, 0x2195,
+ 0x68cd, 0x0c93,
+ 0x68ce, 0x21a5,
+ 0x68d0, 0x219e,
+ 0x68d1, 0x21ab,
+ 0x68d2, 0x0c8f,
+ 0x68d3, 0x2183,
+ 0x68d4, 0x21ad,
+ 0x68d5, 0x0c85,
+ 0x68d6, 0x218b,
+ 0x68d7, 0x0c88,
+ 0x68d8, 0x0c87,
+ 0x68da, 0x0c98,
+ 0x68dc, 0x2185,
+ 0x68dd, 0x21a7,
+ 0x68df, 0x0c8a,
+ 0x68e0, 0x0c86,
+ 0x68e1, 0x2193,
+ 0x68e3, 0x0c91,
+ 0x68e4, 0x218e,
+ 0x68e6, 0x21a9,
+ 0x68e7, 0x0c8d,
+ 0x68e8, 0x21a1,
+ 0x68e9, 0x21ae,
+ 0x68ea, 0x2188,
+ 0x68eb, 0x218d,
+ 0x68ec, 0x2187,
+ 0x68ee, 0x0c8c,
+ 0x68ef, 0x219a,
+ 0x68f0, 0x242b,
+ 0x68f1, 0x2189,
+ 0x68f2, 0x0c90,
+ 0x68f3, 0x2192,
+ 0x68f4, 0x21aa,
+ 0x68f5, 0x0c8b,
+ 0x68f6, 0x218f,
+ 0x68f7, 0x218c,
+ 0x68f8, 0x219d,
+ 0x68f9, 0x0c8e,
+ 0x68fa, 0x0c84,
+ 0x68fb, 0x0c9a,
+ 0x68fc, 0x21a0,
+ 0x68fd, 0x219f,
+ 0x6900, 0x41df,
+ 0x6901, 0x41de,
+ 0x6902, 0x42fb,
+ 0x6903, 0x429c,
+ 0x6904, 0x2184,
+ 0x6905, 0x0c89,
+ 0x6906, 0x21ac,
+ 0x6907, 0x2194,
+ 0x6908, 0x2196,
+ 0x6909, 0x4658,
+ 0x690a, 0x21a3,
+ 0x690b, 0x21a2,
+ 0x690c, 0x2182,
+ 0x690d, 0x0c94,
+ 0x690e, 0x0c96,
+ 0x690f, 0x218a,
+ 0x6910, 0x2191,
+ 0x6911, 0x2199,
+ 0x6912, 0x0c95,
+ 0x6913, 0x2190,
+ 0x6914, 0x219c,
+ 0x6915, 0x21af,
+ 0x6917, 0x21a4,
+ 0x6918, 0x3da2,
+ 0x691a, 0x3d80,
+ 0x691b, 0x37bd,
+ 0x6925, 0x21b0,
+ 0x692a, 0x2186,
+ 0x692c, 0x3f38,
+ 0x692f, 0x243f,
+ 0x6930, 0x0e3e,
+ 0x6932, 0x243d,
+ 0x6933, 0x2428,
+ 0x6934, 0x242d,
+ 0x6935, 0x2426,
+ 0x6936, 0x41e7,
+ 0x6937, 0x2439,
+ 0x6938, 0x2418,
+ 0x6939, 0x241f,
+ 0x693b, 0x2437,
+ 0x693c, 0x2441,
+ 0x693d, 0x2429,
+ 0x693e, 0x4056,
+ 0x693f, 0x241c,
+ 0x6940, 0x242f,
+ 0x6941, 0x2434,
+ 0x6942, 0x2420,
+ 0x6943, 0x4659,
+ 0x6944, 0x2431,
+ 0x6945, 0x241d,
+ 0x6946, 0x456f,
+ 0x6948, 0x2424,
+ 0x694a, 0x0e40,
+ 0x694b, 0x2438,
+ 0x694c, 0x2436,
+ 0x694e, 0x2419,
+ 0x694f, 0x243b,
+ 0x6951, 0x243c,
+ 0x6952, 0x243e,
+ 0x6953, 0x0e44,
+ 0x6954, 0x0e3c,
+ 0x6955, 0x3d86,
+ 0x6956, 0x1f1d,
+ 0x6957, 0x2421,
+ 0x6958, 0x2433,
+ 0x6959, 0x2422,
+ 0x695a, 0x0e39,
+ 0x695b, 0x0e49,
+ 0x695c, 0x243a,
+ 0x695d, 0x0e47,
+ 0x695e, 0x0e43,
+ 0x695f, 0x2417,
+ 0x6960, 0x0e3b,
+ 0x6961, 0x41e4,
+ 0x6962, 0x241a,
+ 0x6963, 0x0e48,
+ 0x6964, 0x465b,
+ 0x6965, 0x242a,
+ 0x6966, 0x2416,
+ 0x6967, 0x3d15,
+ 0x6968, 0x0e41,
+ 0x6969, 0x242e,
+ 0x696a, 0x241e,
+ 0x696b, 0x0e42,
+ 0x696c, 0x2427,
+ 0x696d, 0x0e38,
+ 0x696e, 0x0c99,
+ 0x696f, 0x2430,
+ 0x6970, 0x2197,
+ 0x6971, 0x241b,
+ 0x6972, 0x3a6d,
+ 0x6973, 0x41db,
+ 0x6974, 0x2435,
+ 0x6975, 0x0e3d,
+ 0x6976, 0x2432,
+ 0x6977, 0x0e3a,
+ 0x6978, 0x242c,
+ 0x6979, 0x0e45,
+ 0x697a, 0x2423,
+ 0x697b, 0x2440,
+ 0x6980, 0x3f3e,
+ 0x6982, 0x0e3f,
+ 0x6983, 0x24af,
+ 0x6985, 0x465d,
+ 0x6986, 0x0e46,
+ 0x698a, 0x3d74,
+ 0x698d, 0x26c9,
+ 0x698e, 0x26c7,
+ 0x6990, 0x26dd,
+ 0x6991, 0x26c5,
+ 0x6993, 0x26d7,
+ 0x6994, 0x0e37,
+ 0x6995, 0x0ff0,
+ 0x6996, 0x26c1,
+ 0x6997, 0x26dc,
+ 0x6998, 0x41e8,
+ 0x6999, 0x26c6,
+ 0x699a, 0x26d4,
+ 0x699b, 0x0ff5,
+ 0x699c, 0x0fee,
+ 0x699e, 0x26da,
+ 0x699f, 0x465c,
+ 0x69a0, 0x26bf,
+ 0x69a1, 0x26d9,
+ 0x69a2, 0x3730,
+ 0x69a3, 0x1000,
+ 0x69a4, 0x26d0,
+ 0x69a5, 0x26e0,
+ 0x69a6, 0x0ffe,
+ 0x69a7, 0x26c8,
+ 0x69a8, 0x0fef,
+ 0x69a9, 0x26ca,
+ 0x69aa, 0x26d8,
+ 0x69ab, 0x0ff8,
+ 0x69ac, 0x26c3,
+ 0x69ad, 0x0ffc,
+ 0x69ae, 0x0ff2,
+ 0x69af, 0x26cc,
+ 0x69b0, 0x26c2,
+ 0x69b1, 0x26bc,
+ 0x69b2, 0x3ff6,
+ 0x69b3, 0x26d6,
+ 0x69b4, 0x0ff9,
+ 0x69b5, 0x26df,
+ 0x69b6, 0x26bd,
+ 0x69b7, 0x0ff6,
+ 0x69b9, 0x26d2,
+ 0x69bb, 0x0ff7,
+ 0x69bc, 0x26c4,
+ 0x69bd, 0x26cf,
+ 0x69be, 0x26cb,
+ 0x69bf, 0x26cd,
+ 0x69c0, 0x3f5d,
+ 0x69c1, 0x0ff1,
+ 0x69c2, 0x26de,
+ 0x69c3, 0x0fff,
+ 0x69c4, 0x26ce,
+ 0x69c6, 0x26e1,
+ 0x69c9, 0x26be,
+ 0x69ca, 0x26d3,
+ 0x69cb, 0x0ff4,
+ 0x69cc, 0x0ffd,
+ 0x69cd, 0x0ffb,
+ 0x69ce, 0x26c0,
+ 0x69cf, 0x26d5,
+ 0x69d0, 0x0ffa,
+ 0x69d1, 0x39ef,
+ 0x69d3, 0x0ff3,
+ 0x69d4, 0x26d1,
+ 0x69d5, 0x3e3c,
+ 0x69d6, 0x465e,
+ 0x69d9, 0x26db,
+ 0x69e1, 0x41d8,
+ 0x69e2, 0x2909,
+ 0x69e4, 0x2905,
+ 0x69e5, 0x2901,
+ 0x69e6, 0x2915,
+ 0x69e7, 0x2912,
+ 0x69e8, 0x1177,
+ 0x69e9, 0x3d91,
+ 0x69eb, 0x2919,
+ 0x69ec, 0x2908,
+ 0x69ed, 0x1182,
+ 0x69ee, 0x290f,
+ 0x69f1, 0x2904,
+ 0x69f2, 0x290e,
+ 0x69f3, 0x117f,
+ 0x69f4, 0x2922,
+ 0x69f6, 0x291f,
+ 0x69f7, 0x2911,
+ 0x69f8, 0x2902,
+ 0x69f9, 0x41ed,
+ 0x69fa, 0x41c7,
+ 0x69fb, 0x2916,
+ 0x69fc, 0x2918,
+ 0x69fd, 0x117b,
+ 0x69fe, 0x290c,
+ 0x69ff, 0x2907,
+ 0x6a00, 0x28fe,
+ 0x6a01, 0x1178,
+ 0x6a02, 0x1180,
+ 0x6a03, 0x3e29,
+ 0x6a04, 0x291b,
+ 0x6a05, 0x1181,
+ 0x6a06, 0x28ff,
+ 0x6a07, 0x2921,
+ 0x6a08, 0x2914,
+ 0x6a09, 0x291a,
+ 0x6a0a, 0x117e,
+ 0x6a0b, 0x41d9,
+ 0x6a0c, 0x3d50,
+ 0x6a0d, 0x2917,
+ 0x6a0f, 0x291e,
+ 0x6a11, 0x1183,
+ 0x6a13, 0x117d,
+ 0x6a14, 0x2910,
+ 0x6a15, 0x2903,
+ 0x6a16, 0x2923,
+ 0x6a17, 0x2900,
+ 0x6a18, 0x291c,
+ 0x6a19, 0x117a,
+ 0x6a1a, 0x3d1e,
+ 0x6a1b, 0x290a,
+ 0x6a1c, 0x3b68,
+ 0x6a1d, 0x290b,
+ 0x6a1e, 0x1179,
+ 0x6a1f, 0x1176,
+ 0x6a20, 0x2906,
+ 0x6a21, 0x117c,
+ 0x6a23, 0x1175,
+ 0x6a25, 0x291d,
+ 0x6a26, 0x2920,
+ 0x6a27, 0x290d,
+ 0x6a28, 0x2b74,
+ 0x6a2b, 0x3d42,
+ 0x6a2c, 0x42ab,
+ 0x6a2d, 0x3b1f,
+ 0x6a32, 0x2b6c,
+ 0x6a33, 0x3aa4,
+ 0x6a34, 0x2b68,
+ 0x6a35, 0x12d9,
+ 0x6a38, 0x12ce,
+ 0x6a39, 0x12d3,
+ 0x6a3a, 0x12cf,
+ 0x6a3b, 0x2b76,
+ 0x6a3c, 0x2b81,
+ 0x6a3d, 0x12cd,
+ 0x6a3e, 0x2b6e,
+ 0x6a3f, 0x2b77,
+ 0x6a40, 0x2913,
+ 0x6a41, 0x2b78,
+ 0x6a44, 0x12d4,
+ 0x6a45, 0x41f0,
+ 0x6a46, 0x2b87,
+ 0x6a47, 0x12d8,
+ 0x6a48, 0x12db,
+ 0x6a49, 0x2b6a,
+ 0x6a4b, 0x12d7,
+ 0x6a4c, 0x3aab,
+ 0x6a4d, 0x2b85,
+ 0x6a4f, 0x2b7c,
+ 0x6a50, 0x2b7b,
+ 0x6a51, 0x2b73,
+ 0x6a52, 0x3aa5,
+ 0x6a53, 0x37ac,
+ 0x6a54, 0x2b7d,
+ 0x6a55, 0x2b84,
+ 0x6a56, 0x2b83,
+ 0x6a57, 0x37da,
+ 0x6a58, 0x12d2,
+ 0x6a59, 0x12d0,
+ 0x6a5a, 0x2b75,
+ 0x6a5b, 0x2b72,
+ 0x6a5d, 0x2b6f,
+ 0x6a5e, 0x2b82,
+ 0x6a5f, 0x12da,
+ 0x6a60, 0x2b80,
+ 0x6a61, 0x12d6,
+ 0x6a62, 0x12d5,
+ 0x6a64, 0x2b7a,
+ 0x6a65, 0x4660,
+ 0x6a66, 0x2b69,
+ 0x6a67, 0x2b6b,
+ 0x6a68, 0x2b6d,
+ 0x6a69, 0x2b7f,
+ 0x6a6a, 0x2b79,
+ 0x6a6b, 0x12d1,
+ 0x6a6d, 0x2b70,
+ 0x6a6f, 0x2b7e,
+ 0x6a71, 0x4662,
+ 0x6a74, 0x4661,
+ 0x6a76, 0x2b71,
+ 0x6a7a, 0x3aad,
+ 0x6a7e, 0x13ec,
+ 0x6a7f, 0x2d84,
+ 0x6a80, 0x13e5,
+ 0x6a81, 0x2d75,
+ 0x6a82, 0x4663,
+ 0x6a83, 0x2d80,
+ 0x6a84, 0x13e7,
+ 0x6a85, 0x2d87,
+ 0x6a87, 0x2d7c,
+ 0x6a89, 0x2d77,
+ 0x6a8a, 0x4136,
+ 0x6a8c, 0x2d88,
+ 0x6a8d, 0x2d73,
+ 0x6a8e, 0x2d7e,
+ 0x6a8f, 0x3c1b,
+ 0x6a90, 0x13ee,
+ 0x6a91, 0x2d83,
+ 0x6a92, 0x2d89,
+ 0x6a93, 0x2d7d,
+ 0x6a94, 0x13e6,
+ 0x6a95, 0x2d7f,
+ 0x6a96, 0x2d74,
+ 0x6a97, 0x13ed,
+ 0x6a99, 0x4665,
+ 0x6a9a, 0x2d86,
+ 0x6a9b, 0x2d79,
+ 0x6a9c, 0x13e9,
+ 0x6a9d, 0x41f2,
+ 0x6a9e, 0x2d7b,
+ 0x6a9f, 0x2d78,
+ 0x6aa0, 0x13ef,
+ 0x6aa1, 0x2d7a,
+ 0x6aa2, 0x13e8,
+ 0x6aa3, 0x13eb,
+ 0x6aa4, 0x2d82,
+ 0x6aa5, 0x2d76,
+ 0x6aa6, 0x2d85,
+ 0x6aa7, 0x37e3,
+ 0x6aa8, 0x2d81,
+ 0x6aab, 0x4667,
+ 0x6aac, 0x14dd,
+ 0x6aad, 0x2f3e,
+ 0x6aae, 0x14e2,
+ 0x6ab1, 0x3e53,
+ 0x6ab2, 0x3b4b,
+ 0x6ab3, 0x14dc,
+ 0x6ab4, 0x2f3d,
+ 0x6ab5, 0x4668,
+ 0x6ab6, 0x2f3a,
+ 0x6ab8, 0x14e0,
+ 0x6ab9, 0x2f35,
+ 0x6aba, 0x2f39,
+ 0x6abb, 0x14df,
+ 0x6abd, 0x2f36,
+ 0x6abe, 0x3aa1,
+ 0x6ac2, 0x14e1,
+ 0x6ac3, 0x14de,
+ 0x6ac5, 0x2f34,
+ 0x6ac6, 0x2f38,
+ 0x6ac7, 0x2f3c,
+ 0x6ac8, 0x41f5,
+ 0x6ac9, 0x3aa6,
+ 0x6aca, 0x3f4c,
+ 0x6acb, 0x309f,
+ 0x6acc, 0x309c,
+ 0x6acd, 0x30a5,
+ 0x6acf, 0x30a4,
+ 0x6ad0, 0x30a2,
+ 0x6ad1, 0x309d,
+ 0x6ad3, 0x1589,
+ 0x6ad4, 0x4669,
+ 0x6ad8, 0x3caa,
+ 0x6ad9, 0x309e,
+ 0x6ada, 0x1588,
+ 0x6adb, 0x13ea,
+ 0x6adc, 0x30a1,
+ 0x6add, 0x1587,
+ 0x6ade, 0x30a6,
+ 0x6adf, 0x30a0,
+ 0x6ae0, 0x309b,
+ 0x6ae1, 0x2f37,
+ 0x6ae5, 0x1586,
+ 0x6ae7, 0x309a,
+ 0x6ae8, 0x31df,
+ 0x6aea, 0x31de,
+ 0x6aeb, 0x30a3,
+ 0x6aec, 0x161b,
+ 0x6aee, 0x31e2,
+ 0x6af0, 0x31dd,
+ 0x6af1, 0x31e1,
+ 0x6af3, 0x31dc,
+ 0x6af6, 0x466a,
+ 0x6af8, 0x32d6,
+ 0x6af9, 0x31e0,
+ 0x6afa, 0x1678,
+ 0x6afb, 0x1676,
+ 0x6afc, 0x32d4,
+ 0x6b00, 0x32d7,
+ 0x6b02, 0x32d3,
+ 0x6b03, 0x32d5,
+ 0x6b04, 0x1677,
+ 0x6b05, 0x3aa7,
+ 0x6b08, 0x3386,
+ 0x6b0a, 0x16c6,
+ 0x6b0b, 0x3385,
+ 0x6b0f, 0x3420,
+ 0x6b10, 0x16fd,
+ 0x6b11, 0x341e,
+ 0x6b13, 0x3487,
+ 0x6b16, 0x1743,
+ 0x6b17, 0x34ce,
+ 0x6b18, 0x34cc,
+ 0x6b1a, 0x34cf,
+ 0x6b1d, 0x41f8,
+ 0x6b1e, 0x3534,
+ 0x6b20, 0x02de,
+ 0x6b21, 0x03e3,
+ 0x6b23, 0x061a,
+ 0x6b25, 0x19c9,
+ 0x6b28, 0x1b3d,
+ 0x6b2c, 0x1ce6,
+ 0x6b2d, 0x1ce8,
+ 0x6b2f, 0x1ce7,
+ 0x6b31, 0x1ce9,
+ 0x6b32, 0x0ae7,
+ 0x6b33, 0x1f3c,
+ 0x6b34, 0x1cea,
+ 0x6b35, 0x41fb,
+ 0x6b36, 0x1f3b,
+ 0x6b37, 0x1f3d,
+ 0x6b39, 0x21b2,
+ 0x6b3a, 0x0c9c,
+ 0x6b3b, 0x21b3,
+ 0x6b3c, 0x21b5,
+ 0x6b3d, 0x0c9d,
+ 0x6b3e, 0x0c9b,
+ 0x6b3f, 0x21b4,
+ 0x6b41, 0x2447,
+ 0x6b42, 0x2445,
+ 0x6b43, 0x2444,
+ 0x6b45, 0x2443,
+ 0x6b46, 0x2442,
+ 0x6b47, 0x0e4a,
+ 0x6b48, 0x2446,
+ 0x6b49, 0x1001,
+ 0x6b4a, 0x26e2,
+ 0x6b4b, 0x26e4,
+ 0x6b4c, 0x1002,
+ 0x6b4d, 0x26e3,
+ 0x6b4e, 0x1185,
+ 0x6b50, 0x1184,
+ 0x6b51, 0x2924,
+ 0x6b52, 0x3f6e,
+ 0x6b54, 0x2b89,
+ 0x6b55, 0x2b88,
+ 0x6b56, 0x2b8a,
+ 0x6b57, 0x3aae,
+ 0x6b59, 0x12dc,
+ 0x6b5b, 0x2d8a,
+ 0x6b5c, 0x13f0,
+ 0x6b5e, 0x2f3f,
+ 0x6b5f, 0x14e4,
+ 0x6b60, 0x30a7,
+ 0x6b61, 0x16c7,
+ 0x6b62, 0x02df,
+ 0x6b63, 0x034d,
+ 0x6b64, 0x03e4,
+ 0x6b65, 0x04c9,
+ 0x6b66, 0x061b,
+ 0x6b6a, 0x0769,
+ 0x6b6d, 0x1ceb,
+ 0x6b6f, 0x4515,
+ 0x6b72, 0x0e4b,
+ 0x6b74, 0x41fc,
+ 0x6b76, 0x29a2,
+ 0x6b77, 0x12dd,
+ 0x6b78, 0x14e5,
+ 0x6b79, 0x02e0,
+ 0x6b7a, 0x44ee,
+ 0x6b7b, 0x03e5,
+ 0x6b7e, 0x19cb,
+ 0x6b7f, 0x061d,
+ 0x6b80, 0x19ca,
+ 0x6b81, 0x466b,
+ 0x6b82, 0x1b3e,
+ 0x6b83, 0x076a,
+ 0x6b84, 0x1b3f,
+ 0x6b86, 0x076b,
+ 0x6b88, 0x1ced,
+ 0x6b89, 0x0900,
+ 0x6b8a, 0x08ff,
+ 0x6b8c, 0x1f43,
+ 0x6b8d, 0x1f41,
+ 0x6b8f, 0x1f40,
+ 0x6b91, 0x1f3f,
+ 0x6b94, 0x21b6,
+ 0x6b95, 0x21b9,
+ 0x6b96, 0x0c9f,
+ 0x6b97, 0x21b7,
+ 0x6b98, 0x0c9e,
+ 0x6b99, 0x21b8,
+ 0x6b9b, 0x2448,
+ 0x6b9e, 0x26e5,
+ 0x6ba2, 0x2927,
+ 0x6ba3, 0x2926,
+ 0x6ba4, 0x1186,
+ 0x6ba5, 0x2925,
+ 0x6ba6, 0x2928,
+ 0x6ba7, 0x2b8b,
+ 0x6baa, 0x2b8c,
+ 0x6bad, 0x2d8b,
+ 0x6bae, 0x13f1,
+ 0x6baf, 0x14e6,
+ 0x6bb0, 0x30a8,
+ 0x6bb2, 0x1679,
+ 0x6bb3, 0x178a,
+ 0x6bb5, 0x076c,
+ 0x6bb6, 0x1b40,
+ 0x6bb7, 0x0901,
+ 0x6bba, 0x0ae8,
+ 0x6bbc, 0x0ca0,
+ 0x6bbd, 0x21ba,
+ 0x6bbf, 0x0e4d,
+ 0x6bc0, 0x0e4c,
+ 0x6bc1, 0x466c,
+ 0x6bc3, 0x26e8,
+ 0x6bc5, 0x1187,
+ 0x6bc7, 0x2b8f,
+ 0x6bc8, 0x2b8e,
+ 0x6bc9, 0x2f40,
+ 0x6bca, 0x3421,
+ 0x6bcb, 0x02e1,
+ 0x6bcc, 0x178b,
+ 0x6bcd, 0x034e,
+ 0x6bcf, 0x04ca,
+ 0x6bd0, 0x18ad,
+ 0x6bd2, 0x076d,
+ 0x6bd3, 0x0e4e,
+ 0x6bd4, 0x02e2,
+ 0x6bd6, 0x1b41,
+ 0x6bd7, 0x076e,
+ 0x6bd8, 0x1b42,
+ 0x6bda, 0x13f2,
+ 0x6bdb, 0x02e3,
+ 0x6bdc, 0x4207,
+ 0x6bde, 0x19cc,
+ 0x6be0, 0x1b43,
+ 0x6be1, 0x4205,
+ 0x6be2, 0x1cf2,
+ 0x6be3, 0x1cf1,
+ 0x6be4, 0x1cef,
+ 0x6be6, 0x1cee,
+ 0x6be7, 0x1cf3,
+ 0x6be8, 0x1cf0,
+ 0x6bea, 0x466d,
+ 0x6beb, 0x0ae9,
+ 0x6bef, 0x0ca1,
+ 0x6bf0, 0x21bb,
+ 0x6bf2, 0x21bc,
+ 0x6bf7, 0x244c,
+ 0x6bf9, 0x244b,
+ 0x6bfa, 0x3f79,
+ 0x6bfb, 0x2449,
+ 0x6bfd, 0x0e4f,
+ 0x6bfe, 0x26ea,
+ 0x6bff, 0x292b,
+ 0x6c00, 0x292a,
+ 0x6c01, 0x2929,
+ 0x6c02, 0x292c,
+ 0x6c03, 0x2b91,
+ 0x6c04, 0x2b90,
+ 0x6c05, 0x12de,
+ 0x6c06, 0x2b92,
+ 0x6c08, 0x13f3,
+ 0x6c09, 0x2d8c,
+ 0x6c0b, 0x2f41,
+ 0x6c0c, 0x30a9,
+ 0x6c0d, 0x3388,
+ 0x6c0f, 0x02e4,
+ 0x6c10, 0x0350,
+ 0x6c11, 0x034f,
+ 0x6c13, 0x061e,
+ 0x6c14, 0x178c,
+ 0x6c15, 0x17aa,
+ 0x6c16, 0x03e6,
+ 0x6c18, 0x1801,
+ 0x6c19, 0x18ae,
+ 0x6c1b, 0x061f,
+ 0x6c1c, 0x38ab,
+ 0x6c1d, 0x19cd,
+ 0x6c1f, 0x076f,
+ 0x6c20, 0x1b44,
+ 0x6c23, 0x0902,
+ 0x6c24, 0x0906,
+ 0x6c25, 0x1cf4,
+ 0x6c26, 0x0905,
+ 0x6c27, 0x0903,
+ 0x6c2a, 0x1f44,
+ 0x6c2b, 0x0aeb,
+ 0x6c2c, 0x0ca4,
+ 0x6c2e, 0x0ca2,
+ 0x6c30, 0x21be,
+ 0x6c31, 0x3f63,
+ 0x6c33, 0x1003,
+ 0x6c34, 0x02e5,
+ 0x6c35, 0x44ef,
+ 0x6c36, 0x17ab,
+ 0x6c37, 0x4208,
+ 0x6c38, 0x0351,
+ 0x6c39, 0x3e05,
+ 0x6c3a, 0x44f0,
+ 0x6c3b, 0x17ae,
+ 0x6c3d, 0x4381,
+ 0x6c3e, 0x0354,
+ 0x6c3f, 0x17ad,
+ 0x6c40, 0x0353,
+ 0x6c41, 0x0352,
+ 0x6c42, 0x04cb,
+ 0x6c43, 0x17ac,
+ 0x6c46, 0x1802,
+ 0x6c49, 0x408d,
+ 0x6c4a, 0x1806,
+ 0x6c4b, 0x1808,
+ 0x6c4d, 0x03f0,
+ 0x6c4f, 0x1805,
+ 0x6c50, 0x03ec,
+ 0x6c52, 0x1803,
+ 0x6c54, 0x1807,
+ 0x6c55, 0x03ed,
+ 0x6c57, 0x03e8,
+ 0x6c58, 0x3bba,
+ 0x6c59, 0x03e9,
+ 0x6c5a, 0x420c,
+ 0x6c5b, 0x03ef,
+ 0x6c5c, 0x1804,
+ 0x6c5d, 0x03e7,
+ 0x6c5e, 0x04cc,
+ 0x6c5f, 0x03ea,
+ 0x6c61, 0x03ee,
+ 0x6c65, 0x18c0,
+ 0x6c66, 0x18be,
+ 0x6c67, 0x18b1,
+ 0x6c68, 0x04d8,
+ 0x6c69, 0x18b8,
+ 0x6c6a, 0x04d3,
+ 0x6c6b, 0x18b2,
+ 0x6c6d, 0x18ba,
+ 0x6c6e, 0x40ca,
+ 0x6c6f, 0x18b7,
+ 0x6c70, 0x04d6,
+ 0x6c71, 0x18b6,
+ 0x6c72, 0x04dd,
+ 0x6c73, 0x18bf,
+ 0x6c74, 0x04df,
+ 0x6c75, 0x466e,
+ 0x6c76, 0x04e1,
+ 0x6c78, 0x18b0,
+ 0x6c79, 0x420e,
+ 0x6c7a, 0x04d4,
+ 0x6c7b, 0x18c1,
+ 0x6c7d, 0x04db,
+ 0x6c7e, 0x04de,
+ 0x6c7f, 0x37a6,
+ 0x6c80, 0x19e4,
+ 0x6c81, 0x04ce,
+ 0x6c82, 0x04e5,
+ 0x6c83, 0x04dc,
+ 0x6c84, 0x18b3,
+ 0x6c85, 0x04d1,
+ 0x6c86, 0x04e0,
+ 0x6c87, 0x18bb,
+ 0x6c88, 0x04cf,
+ 0x6c8a, 0x19e2,
+ 0x6c8b, 0x18b4,
+ 0x6c8c, 0x04d7,
+ 0x6c8d, 0x04e2,
+ 0x6c8e, 0x18c2,
+ 0x6c8f, 0x18b5,
+ 0x6c90, 0x04d5,
+ 0x6c92, 0x04da,
+ 0x6c93, 0x19ce,
+ 0x6c94, 0x04e3,
+ 0x6c95, 0x18bc,
+ 0x6c96, 0x04d9,
+ 0x6c98, 0x04e4,
+ 0x6c99, 0x04cd,
+ 0x6c9a, 0x18b9,
+ 0x6c9b, 0x04d2,
+ 0x6c9c, 0x18bd,
+ 0x6c9d, 0x19e3,
+ 0x6c9f, 0x3889,
+ 0x6ca2, 0x3d63,
+ 0x6caa, 0x466f,
+ 0x6cab, 0x062b,
+ 0x6cac, 0x063b,
+ 0x6cad, 0x19d5,
+ 0x6cae, 0x0632,
+ 0x6caf, 0x3cf6,
+ 0x6cb0, 0x19ea,
+ 0x6cb1, 0x0623,
+ 0x6cb2, 0x3ecc,
+ 0x6cb3, 0x0626,
+ 0x6cb4, 0x19e1,
+ 0x6cb6, 0x19d3,
+ 0x6cb7, 0x19d7,
+ 0x6cb8, 0x062e,
+ 0x6cb9, 0x0630,
+ 0x6cba, 0x19da,
+ 0x6cbb, 0x0637,
+ 0x6cbc, 0x0629,
+ 0x6cbd, 0x0627,
+ 0x6cbf, 0x0636,
+ 0x6cc0, 0x19e6,
+ 0x6cc1, 0x0631,
+ 0x6cc2, 0x19d9,
+ 0x6cc3, 0x19db,
+ 0x6cc4, 0x062f,
+ 0x6cc5, 0x0634,
+ 0x6cc6, 0x19dc,
+ 0x6cc7, 0x19e9,
+ 0x6cc9, 0x0770,
+ 0x6cca, 0x063a,
+ 0x6ccb, 0x4070,
+ 0x6ccc, 0x0624,
+ 0x6ccd, 0x19e8,
+ 0x6cce, 0x3f91,
+ 0x6ccf, 0x19ec,
+ 0x6cd0, 0x19d8,
+ 0x6cd1, 0x19ee,
+ 0x6cd2, 0x19df,
+ 0x6cd3, 0x062d,
+ 0x6cd4, 0x19d4,
+ 0x6cd5, 0x062c,
+ 0x6cd6, 0x063e,
+ 0x6cd7, 0x0633,
+ 0x6cd9, 0x19d2,
+ 0x6cda, 0x1b4e,
+ 0x6cdb, 0x0639,
+ 0x6cdc, 0x063d,
+ 0x6cdd, 0x19e0,
+ 0x6cde, 0x19e5,
+ 0x6cdf, 0x3d57,
+ 0x6ce0, 0x063f,
+ 0x6ce1, 0x0638,
+ 0x6ce2, 0x062a,
+ 0x6ce3, 0x0620,
+ 0x6ce5, 0x0625,
+ 0x6ce7, 0x19d6,
+ 0x6ce8, 0x0621,
+ 0x6ce9, 0x19ed,
+ 0x6cea, 0x3f8d,
+ 0x6ceb, 0x19d0,
+ 0x6cec, 0x19cf,
+ 0x6ced, 0x19dd,
+ 0x6cee, 0x19d1,
+ 0x6cef, 0x063c,
+ 0x6cf0, 0x0907,
+ 0x6cf1, 0x0635,
+ 0x6cf2, 0x19de,
+ 0x6cf3, 0x0622,
+ 0x6cf5, 0x077f,
+ 0x6cf9, 0x19eb,
+ 0x6d00, 0x1b55,
+ 0x6d01, 0x1b58,
+ 0x6d02, 0x4671,
+ 0x6d03, 0x1b5b,
+ 0x6d04, 0x1b50,
+ 0x6d05, 0x3a19,
+ 0x6d06, 0x4672,
+ 0x6d07, 0x1b5e,
+ 0x6d08, 0x1b61,
+ 0x6d09, 0x1b63,
+ 0x6d0a, 0x1b4d,
+ 0x6d0b, 0x0771,
+ 0x6d0c, 0x0776,
+ 0x6d0d, 0x1cf9,
+ 0x6d0e, 0x0786,
+ 0x6d0f, 0x1b5c,
+ 0x6d10, 0x1b64,
+ 0x6d11, 0x1b54,
+ 0x6d12, 0x1b4c,
+ 0x6d16, 0x1d14,
+ 0x6d17, 0x0779,
+ 0x6d18, 0x1b59,
+ 0x6d19, 0x1b51,
+ 0x6d1a, 0x1b53,
+ 0x6d1b, 0x077e,
+ 0x6d1d, 0x1b56,
+ 0x6d1e, 0x0778,
+ 0x6d1f, 0x1b49,
+ 0x6d20, 0x1b5f,
+ 0x6d22, 0x1b62,
+ 0x6d24, 0x3ac3,
+ 0x6d25, 0x0775,
+ 0x6d26, 0x4673,
+ 0x6d27, 0x0781,
+ 0x6d28, 0x1b46,
+ 0x6d29, 0x0783,
+ 0x6d2a, 0x0773,
+ 0x6d2b, 0x0787,
+ 0x6d2c, 0x1b60,
+ 0x6d2d, 0x1b48,
+ 0x6d2e, 0x0784,
+ 0x6d2f, 0x1d0e,
+ 0x6d30, 0x19e7,
+ 0x6d31, 0x0777,
+ 0x6d32, 0x0772,
+ 0x6d33, 0x1b4f,
+ 0x6d34, 0x1b47,
+ 0x6d35, 0x0785,
+ 0x6d36, 0x077d,
+ 0x6d37, 0x1b5a,
+ 0x6d38, 0x0782,
+ 0x6d39, 0x0780,
+ 0x6d3a, 0x1b52,
+ 0x6d3b, 0x077a,
+ 0x6d3c, 0x1b4a,
+ 0x6d3d, 0x077b,
+ 0x6d3f, 0x1b4b,
+ 0x6d40, 0x1b5d,
+ 0x6d41, 0x0774,
+ 0x6d42, 0x1b57,
+ 0x6d4e, 0x4558,
+ 0x6d57, 0x3cf3,
+ 0x6d58, 0x1cfc,
+ 0x6d59, 0x090f,
+ 0x6d5a, 0x0914,
+ 0x6d5b, 0x409c,
+ 0x6d5c, 0x4222,
+ 0x6d5e, 0x1d05,
+ 0x6d5f, 0x1d0b,
+ 0x6d60, 0x1d07,
+ 0x6d61, 0x1cfa,
+ 0x6d62, 0x1cfd,
+ 0x6d63, 0x1cf6,
+ 0x6d65, 0x091b,
+ 0x6d66, 0x090c,
+ 0x6d67, 0x1d06,
+ 0x6d68, 0x1d0f,
+ 0x6d69, 0x0916,
+ 0x6d6a, 0x0908,
+ 0x6d6c, 0x0911,
+ 0x6d6d, 0x1cfe,
+ 0x6d6e, 0x0913,
+ 0x6d6f, 0x1cff,
+ 0x6d70, 0x1d09,
+ 0x6d71, 0x40f5,
+ 0x6d72, 0x39d7,
+ 0x6d74, 0x0915,
+ 0x6d75, 0x1d18,
+ 0x6d76, 0x1cf8,
+ 0x6d77, 0x090e,
+ 0x6d78, 0x090d,
+ 0x6d79, 0x0919,
+ 0x6d7a, 0x1cf5,
+ 0x6d7b, 0x1d16,
+ 0x6d7c, 0x1d0a,
+ 0x6d7d, 0x1d17,
+ 0x6d7e, 0x1d11,
+ 0x6d7f, 0x1d03,
+ 0x6d80, 0x1d12,
+ 0x6d81, 0x4674,
+ 0x6d82, 0x1d0c,
+ 0x6d83, 0x1d15,
+ 0x6d84, 0x1d13,
+ 0x6d85, 0x091a,
+ 0x6d86, 0x1d04,
+ 0x6d87, 0x090b,
+ 0x6d88, 0x090a,
+ 0x6d89, 0x0912,
+ 0x6d8a, 0x0918,
+ 0x6d8b, 0x1d10,
+ 0x6d8c, 0x0917,
+ 0x6d8d, 0x1d01,
+ 0x6d8e, 0x0aec,
+ 0x6d8f, 0x3de8,
+ 0x6d90, 0x1d19,
+ 0x6d91, 0x1d00,
+ 0x6d92, 0x1cfb,
+ 0x6d93, 0x0910,
+ 0x6d94, 0x091c,
+ 0x6d95, 0x0909,
+ 0x6d96, 0x4221,
+ 0x6d97, 0x1d08,
+ 0x6d98, 0x1d0d,
+ 0x6da4, 0x4676,
+ 0x6da5, 0x3ab9,
+ 0x6daa, 0x0b0e,
+ 0x6dab, 0x1f46,
+ 0x6dac, 0x1f4a,
+ 0x6dae, 0x0afb,
+ 0x6daf, 0x0af9,
+ 0x6db1, 0x4677,
+ 0x6db2, 0x0af0,
+ 0x6db3, 0x1f48,
+ 0x6db4, 0x1f47,
+ 0x6db5, 0x0b04,
+ 0x6db7, 0x1f4d,
+ 0x6db8, 0x0afe,
+ 0x6db9, 0x3ffb,
+ 0x6dba, 0x1f5f,
+ 0x6dbb, 0x1f6b,
+ 0x6dbc, 0x0aed,
+ 0x6dbd, 0x1f5c,
+ 0x6dbe, 0x1f55,
+ 0x6dbf, 0x0b10,
+ 0x6dc0, 0x1f45,
+ 0x6dc2, 0x1f61,
+ 0x6dc4, 0x0b0d,
+ 0x6dc5, 0x0b01,
+ 0x6dc6, 0x0b0c,
+ 0x6dc7, 0x0af7,
+ 0x6dc8, 0x1f51,
+ 0x6dc9, 0x1f63,
+ 0x6dca, 0x1f5b,
+ 0x6dcb, 0x0af8,
+ 0x6dcc, 0x0af2,
+ 0x6dcd, 0x1f69,
+ 0x6dcf, 0x1f62,
+ 0x6dd0, 0x1f64,
+ 0x6dd1, 0x0afa,
+ 0x6dd2, 0x0b02,
+ 0x6dd3, 0x1f66,
+ 0x6dd4, 0x1f4f,
+ 0x6dd5, 0x1f60,
+ 0x6dd6, 0x1f54,
+ 0x6dd7, 0x1f68,
+ 0x6dd8, 0x0b07,
+ 0x6dd9, 0x0aef,
+ 0x6dda, 0x0b05,
+ 0x6ddb, 0x1f59,
+ 0x6ddc, 0x1f57,
+ 0x6dde, 0x0afc,
+ 0x6ddf, 0x1f53,
+ 0x6de0, 0x1f52,
+ 0x6de1, 0x0af1,
+ 0x6de2, 0x1f4c,
+ 0x6de3, 0x1f6a,
+ 0x6de4, 0x0af3,
+ 0x6de5, 0x1f56,
+ 0x6de6, 0x0b11,
+ 0x6de8, 0x0b0b,
+ 0x6de9, 0x1f4b,
+ 0x6dea, 0x0b08,
+ 0x6deb, 0x0b06,
+ 0x6dec, 0x0b0f,
+ 0x6ded, 0x1f5d,
+ 0x6dee, 0x0b0a,
+ 0x6def, 0x1d02,
+ 0x6df0, 0x1f5e,
+ 0x6df1, 0x0b09,
+ 0x6df2, 0x1f65,
+ 0x6df3, 0x0aee,
+ 0x6df4, 0x1f5a,
+ 0x6df5, 0x0b00,
+ 0x6df6, 0x1f4e,
+ 0x6df7, 0x0aff,
+ 0x6df9, 0x0afd,
+ 0x6dfa, 0x0af5,
+ 0x6dfb, 0x0af4,
+ 0x6dfc, 0x21bf,
+ 0x6dfd, 0x1f67,
+ 0x6e00, 0x1f50,
+ 0x6e02, 0x3cfa,
+ 0x6e03, 0x21d4,
+ 0x6e04, 0x3abe,
+ 0x6e05, 0x0af6,
+ 0x6e0a, 0x3ac1,
+ 0x6e0f, 0x3cf0,
+ 0x6e15, 0x4678,
+ 0x6e18, 0x4679,
+ 0x6e19, 0x0cc1,
+ 0x6e1a, 0x0b03,
+ 0x6e1b, 0x0caf,
+ 0x6e1c, 0x21ce,
+ 0x6e1d, 0x0cbd,
+ 0x6e1f, 0x21c2,
+ 0x6e20, 0x0cac,
+ 0x6e21, 0x0ca8,
+ 0x6e22, 0x21e0,
+ 0x6e23, 0x0cae,
+ 0x6e24, 0x0cb2,
+ 0x6e25, 0x0cad,
+ 0x6e26, 0x0cb6,
+ 0x6e27, 0x21e4,
+ 0x6e28, 0x21db,
+ 0x6e29, 0x467a,
+ 0x6e2a, 0x4302,
+ 0x6e2b, 0x21c9,
+ 0x6e2c, 0x0cbb,
+ 0x6e2d, 0x0cb5,
+ 0x6e2e, 0x21d5,
+ 0x6e2f, 0x0ca5,
+ 0x6e30, 0x21e1,
+ 0x6e31, 0x21da,
+ 0x6e32, 0x0ca9,
+ 0x6e33, 0x21cf,
+ 0x6e34, 0x0cb8,
+ 0x6e35, 0x21ec,
+ 0x6e38, 0x0ca6,
+ 0x6e39, 0x21df,
+ 0x6e3a, 0x0cba,
+ 0x6e3b, 0x21d3,
+ 0x6e3c, 0x21c5,
+ 0x6e3e, 0x0cbe,
+ 0x6e3f, 0x21ca,
+ 0x6e40, 0x21d1,
+ 0x6e41, 0x21cb,
+ 0x6e43, 0x0cbc,
+ 0x6e44, 0x0cc4,
+ 0x6e45, 0x21c7,
+ 0x6e46, 0x21c0,
+ 0x6e49, 0x21c3,
+ 0x6e4a, 0x0cab,
+ 0x6e4b, 0x21d0,
+ 0x6e4d, 0x0cb9,
+ 0x6e4e, 0x0cc2,
+ 0x6e4f, 0x4234,
+ 0x6e50, 0x41d1,
+ 0x6e51, 0x21d2,
+ 0x6e52, 0x21ea,
+ 0x6e53, 0x21e2,
+ 0x6e54, 0x0ca7,
+ 0x6e55, 0x21e8,
+ 0x6e56, 0x0cb3,
+ 0x6e58, 0x0cb1,
+ 0x6e59, 0x40e6,
+ 0x6e5a, 0x21ee,
+ 0x6e5b, 0x0cb0,
+ 0x6e5c, 0x21d8,
+ 0x6e5d, 0x21cc,
+ 0x6e5e, 0x21d6,
+ 0x6e5f, 0x0cc7,
+ 0x6e60, 0x21dc,
+ 0x6e61, 0x21d9,
+ 0x6e62, 0x21c8,
+ 0x6e63, 0x0cc3,
+ 0x6e64, 0x21e6,
+ 0x6e65, 0x21e3,
+ 0x6e66, 0x21eb,
+ 0x6e67, 0x0caa,
+ 0x6e68, 0x21d7,
+ 0x6e69, 0x0cc6,
+ 0x6e6b, 0x21de,
+ 0x6e6e, 0x0cb4,
+ 0x6e6f, 0x0cb7,
+ 0x6e71, 0x21dd,
+ 0x6e72, 0x0cc5,
+ 0x6e73, 0x21cd,
+ 0x6e74, 0x1f49,
+ 0x6e76, 0x39d3,
+ 0x6e77, 0x21e7,
+ 0x6e78, 0x21e5,
+ 0x6e79, 0x21e9,
+ 0x6e7c, 0x4223,
+ 0x6e86, 0x467b,
+ 0x6e88, 0x21c4,
+ 0x6e89, 0x0cc0,
+ 0x6e8b, 0x3bbf,
+ 0x6e8d, 0x246c,
+ 0x6e8e, 0x246b,
+ 0x6e8f, 0x2451,
+ 0x6e90, 0x0e55,
+ 0x6e92, 0x246a,
+ 0x6e93, 0x2454,
+ 0x6e96, 0x0e5f,
+ 0x6e97, 0x2473,
+ 0x6e98, 0x0e5a,
+ 0x6e99, 0x2469,
+ 0x6e9a, 0x4581,
+ 0x6e9b, 0x244e,
+ 0x6e9c, 0x0e60,
+ 0x6e9d, 0x0e56,
+ 0x6e9e, 0x245d,
+ 0x6e9f, 0x2453,
+ 0x6ea0, 0x2456,
+ 0x6ea1, 0x246e,
+ 0x6ea2, 0x0e50,
+ 0x6ea3, 0x2475,
+ 0x6ea4, 0x246d,
+ 0x6ea5, 0x0e59,
+ 0x6ea6, 0x2462,
+ 0x6ea7, 0x0e64,
+ 0x6eaa, 0x0e63,
+ 0x6eab, 0x0e5d,
+ 0x6eae, 0x2474,
+ 0x6eaf, 0x0e51,
+ 0x6eb0, 0x2460,
+ 0x6eb1, 0x2457,
+ 0x6eb2, 0x2464,
+ 0x6eb3, 0x2470,
+ 0x6eb4, 0x0e65,
+ 0x6eb5, 0x41fe,
+ 0x6eb6, 0x0e53,
+ 0x6eb7, 0x245f,
+ 0x6eb8, 0x3e0c,
+ 0x6eb9, 0x2458,
+ 0x6eba, 0x0e5c,
+ 0x6ebb, 0x467d,
+ 0x6ebc, 0x0e5b,
+ 0x6ebd, 0x245b,
+ 0x6ebe, 0x2465,
+ 0x6ebf, 0x246f,
+ 0x6ec0, 0x2452,
+ 0x6ec1, 0x245c,
+ 0x6ec2, 0x0e54,
+ 0x6ec3, 0x2466,
+ 0x6ec4, 0x0e61,
+ 0x6ec5, 0x0e58,
+ 0x6ec6, 0x2459,
+ 0x6ec7, 0x0e57,
+ 0x6ec8, 0x2450,
+ 0x6ec9, 0x245e,
+ 0x6eca, 0x2472,
+ 0x6ecb, 0x0cbf,
+ 0x6ecc, 0x101f,
+ 0x6ecd, 0x2461,
+ 0x6ece, 0x26eb,
+ 0x6ecf, 0x2463,
+ 0x6ed0, 0x2471,
+ 0x6ed1, 0x0e5e,
+ 0x6ed2, 0x245a,
+ 0x6ed3, 0x0e52,
+ 0x6ed4, 0x0e62,
+ 0x6ed5, 0x119a,
+ 0x6ed6, 0x244f,
+ 0x6ed8, 0x2468,
+ 0x6ed9, 0x4069,
+ 0x6eda, 0x467f,
+ 0x6edb, 0x402f,
+ 0x6edc, 0x2467,
+ 0x6edd, 0x4538,
+ 0x6ee2, 0x467e,
+ 0x6ee8, 0x4681,
+ 0x6eeb, 0x2707,
+ 0x6eec, 0x101c,
+ 0x6eed, 0x26fc,
+ 0x6eee, 0x2701,
+ 0x6eef, 0x1011,
+ 0x6ef1, 0x26ed,
+ 0x6ef2, 0x101e,
+ 0x6ef4, 0x1008,
+ 0x6ef5, 0x26ec,
+ 0x6ef6, 0x270d,
+ 0x6ef7, 0x1020,
+ 0x6ef8, 0x26f0,
+ 0x6ef9, 0x2700,
+ 0x6efa, 0x423b,
+ 0x6efb, 0x26f2,
+ 0x6efc, 0x2710,
+ 0x6efd, 0x270c,
+ 0x6efe, 0x1006,
+ 0x6eff, 0x1010,
+ 0x6f00, 0x2946,
+ 0x6f01, 0x101d,
+ 0x6f02, 0x100e,
+ 0x6f03, 0x26ee,
+ 0x6f04, 0x4224,
+ 0x6f05, 0x270b,
+ 0x6f06, 0x1012,
+ 0x6f07, 0x2708,
+ 0x6f08, 0x2715,
+ 0x6f09, 0x26f4,
+ 0x6f0a, 0x26fd,
+ 0x6f0b, 0x3aba,
+ 0x6f0c, 0x3cfb,
+ 0x6f0d, 0x2713,
+ 0x6f0e, 0x2709,
+ 0x6f0f, 0x100d,
+ 0x6f12, 0x26fb,
+ 0x6f13, 0x1007,
+ 0x6f14, 0x1005,
+ 0x6f15, 0x1017,
+ 0x6f16, 0x41a0,
+ 0x6f17, 0x46ce,
+ 0x6f18, 0x26f9,
+ 0x6f19, 0x26f6,
+ 0x6f1c, 0x270f,
+ 0x6f1e, 0x2714,
+ 0x6f1f, 0x2712,
+ 0x6f20, 0x100b,
+ 0x6f21, 0x2716,
+ 0x6f22, 0x100f,
+ 0x6f23, 0x1016,
+ 0x6f24, 0x4683,
+ 0x6f25, 0x26ef,
+ 0x6f26, 0x292e,
+ 0x6f27, 0x26f8,
+ 0x6f29, 0x1009,
+ 0x6f2a, 0x101b,
+ 0x6f2b, 0x1018,
+ 0x6f2c, 0x100c,
+ 0x6f2d, 0x2702,
+ 0x6f2e, 0x26f3,
+ 0x6f2f, 0x1019,
+ 0x6f30, 0x2704,
+ 0x6f31, 0x1013,
+ 0x6f32, 0x1015,
+ 0x6f33, 0x1004,
+ 0x6f34, 0x4684,
+ 0x6f35, 0x2706,
+ 0x6f36, 0x26fe,
+ 0x6f37, 0x26f1,
+ 0x6f38, 0x1014,
+ 0x6f39, 0x270e,
+ 0x6f3a, 0x2711,
+ 0x6f3b, 0x26fa,
+ 0x6f3c, 0x2705,
+ 0x6f3d, 0x4282,
+ 0x6f3e, 0x100a,
+ 0x6f3f, 0x1189,
+ 0x6f40, 0x2703,
+ 0x6f41, 0x292d,
+ 0x6f43, 0x270a,
+ 0x6f44, 0x4240,
+ 0x6f4e, 0x26f5,
+ 0x6f4f, 0x2937,
+ 0x6f50, 0x2941,
+ 0x6f51, 0x118c,
+ 0x6f52, 0x2940,
+ 0x6f53, 0x294c,
+ 0x6f54, 0x118e,
+ 0x6f55, 0x293e,
+ 0x6f56, 0x3e52,
+ 0x6f57, 0x2942,
+ 0x6f58, 0x1199,
+ 0x6f5a, 0x2939,
+ 0x6f5b, 0x1191,
+ 0x6f5c, 0x4241,
+ 0x6f5d, 0x2945,
+ 0x6f5e, 0x2b9a,
+ 0x6f5f, 0x119d,
+ 0x6f60, 0x119c,
+ 0x6f61, 0x2947,
+ 0x6f62, 0x2936,
+ 0x6f63, 0x2951,
+ 0x6f64, 0x1197,
+ 0x6f66, 0x118d,
+ 0x6f67, 0x294a,
+ 0x6f69, 0x294e,
+ 0x6f6a, 0x2953,
+ 0x6f6b, 0x2948,
+ 0x6f6c, 0x293c,
+ 0x6f6d, 0x1190,
+ 0x6f6e, 0x1193,
+ 0x6f6f, 0x119b,
+ 0x6f70, 0x1196,
+ 0x6f72, 0x293f,
+ 0x6f73, 0x26ff,
+ 0x6f74, 0x4243,
+ 0x6f76, 0x293b,
+ 0x6f77, 0x2952,
+ 0x6f78, 0x1192,
+ 0x6f79, 0x3bbe,
+ 0x6f7a, 0x1195,
+ 0x6f7b, 0x2954,
+ 0x6f7c, 0x118a,
+ 0x6f7d, 0x2949,
+ 0x6f7e, 0x292f,
+ 0x6f7f, 0x294f,
+ 0x6f80, 0x13fc,
+ 0x6f81, 0x4687,
+ 0x6f82, 0x293d,
+ 0x6f84, 0x118b,
+ 0x6f85, 0x2938,
+ 0x6f86, 0x118f,
+ 0x6f87, 0x2930,
+ 0x6f88, 0x101a,
+ 0x6f89, 0x2934,
+ 0x6f8a, 0x4195,
+ 0x6f8b, 0x294d,
+ 0x6f8c, 0x2935,
+ 0x6f8d, 0x2933,
+ 0x6f8e, 0x1194,
+ 0x6f90, 0x294b,
+ 0x6f92, 0x2932,
+ 0x6f93, 0x2944,
+ 0x6f94, 0x2943,
+ 0x6f95, 0x2950,
+ 0x6f96, 0x293a,
+ 0x6f97, 0x1198,
+ 0x6f9d, 0x4239,
+ 0x6f9e, 0x2b9d,
+ 0x6f9f, 0x4246,
+ 0x6fa0, 0x12eb,
+ 0x6fa1, 0x12e1,
+ 0x6fa2, 0x2ba9,
+ 0x6fa3, 0x2b95,
+ 0x6fa4, 0x12e3,
+ 0x6fa5, 0x2ba1,
+ 0x6fa6, 0x12ea,
+ 0x6fa7, 0x12e5,
+ 0x6fa8, 0x2b9f,
+ 0x6fa9, 0x2d8e,
+ 0x6faa, 0x2ba5,
+ 0x6fab, 0x2bab,
+ 0x6fac, 0x2ba4,
+ 0x6fad, 0x2b93,
+ 0x6fae, 0x2ba2,
+ 0x6faf, 0x2bad,
+ 0x6fb0, 0x2baf,
+ 0x6fb1, 0x12e0,
+ 0x6fb2, 0x2bae,
+ 0x6fb3, 0x12e6,
+ 0x6fb4, 0x12ec,
+ 0x6fb5, 0x3e27,
+ 0x6fb6, 0x12e9,
+ 0x6fb8, 0x2ba8,
+ 0x6fb9, 0x12e8,
+ 0x6fba, 0x2ba3,
+ 0x6fbb, 0x3bbb,
+ 0x6fbc, 0x2b97,
+ 0x6fbd, 0x2b9c,
+ 0x6fbe, 0x4688,
+ 0x6fbf, 0x2ba7,
+ 0x6fc0, 0x12e7,
+ 0x6fc1, 0x12e4,
+ 0x6fc2, 0x12df,
+ 0x6fc3, 0x12e2,
+ 0x6fc4, 0x2b9b,
+ 0x6fc6, 0x2931,
+ 0x6fc7, 0x2b96,
+ 0x6fc8, 0x2b99,
+ 0x6fc9, 0x2baa,
+ 0x6fca, 0x2b9e,
+ 0x6fcb, 0x2b94,
+ 0x6fcc, 0x2d8d,
+ 0x6fcd, 0x2bac,
+ 0x6fce, 0x2b98,
+ 0x6fcf, 0x2ba6,
+ 0x6fd3, 0x4248,
+ 0x6fd4, 0x2d90,
+ 0x6fd5, 0x1400,
+ 0x6fd8, 0x13f4,
+ 0x6fd9, 0x3c74,
+ 0x6fda, 0x3c73,
+ 0x6fdb, 0x13f8,
+ 0x6fdc, 0x2d92,
+ 0x6fdd, 0x2d98,
+ 0x6fde, 0x2d96,
+ 0x6fdf, 0x13f6,
+ 0x6fe1, 0x13fe,
+ 0x6fe2, 0x2d99,
+ 0x6fe3, 0x2d91,
+ 0x6fe4, 0x13f9,
+ 0x6fe6, 0x2d95,
+ 0x6fe7, 0x2d94,
+ 0x6fe8, 0x2d9a,
+ 0x6fe9, 0x13ff,
+ 0x6feb, 0x13fa,
+ 0x6fec, 0x13fd,
+ 0x6fed, 0x2d93,
+ 0x6fee, 0x1401,
+ 0x6fef, 0x13fb,
+ 0x6ff0, 0x1402,
+ 0x6ff1, 0x13f5,
+ 0x6ff2, 0x2d97,
+ 0x6ff4, 0x2d8f,
+ 0x6ff6, 0x38a5,
+ 0x6ff7, 0x2f4e,
+ 0x6ff8, 0x4237,
+ 0x6ffa, 0x14eb,
+ 0x6ffb, 0x2f4b,
+ 0x6ffc, 0x2f4d,
+ 0x6ffe, 0x14e9,
+ 0x6fff, 0x2f49,
+ 0x7000, 0x2f4a,
+ 0x7001, 0x2f45,
+ 0x7003, 0x46e2,
+ 0x7004, 0x2ba0,
+ 0x7005, 0x2f46,
+ 0x7006, 0x14ea,
+ 0x7007, 0x2f42,
+ 0x7009, 0x14e7,
+ 0x700a, 0x2f4f,
+ 0x700b, 0x14e8,
+ 0x700c, 0x2f43,
+ 0x700e, 0x2f48,
+ 0x700f, 0x14ed,
+ 0x7011, 0x14ec,
+ 0x7014, 0x2f47,
+ 0x7015, 0x158f,
+ 0x7016, 0x30ad,
+ 0x7017, 0x30b3,
+ 0x7018, 0x1590,
+ 0x7019, 0x30aa,
+ 0x701a, 0x158d,
+ 0x701b, 0x158a,
+ 0x701c, 0x30b5,
+ 0x701d, 0x158e,
+ 0x701e, 0x3c76,
+ 0x701f, 0x158b,
+ 0x7020, 0x30ac,
+ 0x7021, 0x30af,
+ 0x7024, 0x30b4,
+ 0x7026, 0x2f4c,
+ 0x7027, 0x30ab,
+ 0x7028, 0x158c,
+ 0x7029, 0x30b2,
+ 0x702a, 0x31ef,
+ 0x702b, 0x30ae,
+ 0x702c, 0x468e,
+ 0x702f, 0x31e6,
+ 0x7030, 0x161d,
+ 0x7031, 0x31e9,
+ 0x7032, 0x161e,
+ 0x7033, 0x31f2,
+ 0x7034, 0x31e8,
+ 0x7035, 0x31e5,
+ 0x7037, 0x31e7,
+ 0x7038, 0x31eb,
+ 0x7039, 0x31ee,
+ 0x703a, 0x31ed,
+ 0x703b, 0x31f1,
+ 0x703c, 0x31e4,
+ 0x703e, 0x161c,
+ 0x703f, 0x31ec,
+ 0x7040, 0x31f0,
+ 0x7041, 0x31f3,
+ 0x7042, 0x31ea,
+ 0x7043, 0x32d8,
+ 0x7045, 0x32dd,
+ 0x7048, 0x32db,
+ 0x704a, 0x32da,
+ 0x704b, 0x4254,
+ 0x704c, 0x167a,
+ 0x7050, 0x4690,
+ 0x7051, 0x16c8,
+ 0x7052, 0x338c,
+ 0x7054, 0x4691,
+ 0x7055, 0x3389,
+ 0x7058, 0x16c9,
+ 0x705a, 0x3423,
+ 0x705b, 0x3422,
+ 0x705c, 0x3852,
+ 0x705d, 0x348a,
+ 0x705e, 0x1722,
+ 0x705f, 0x3488,
+ 0x7060, 0x348b,
+ 0x7061, 0x3489,
+ 0x7062, 0x34d0,
+ 0x7063, 0x1744,
+ 0x7064, 0x1752,
+ 0x7065, 0x351c,
+ 0x7066, 0x3506,
+ 0x7067, 0x3cf5,
+ 0x7068, 0x351b,
+ 0x7069, 0x3547,
+ 0x706b, 0x02e6,
+ 0x706c, 0x44f1,
+ 0x706f, 0x4692,
+ 0x7070, 0x03f2,
+ 0x7071, 0x180a,
+ 0x7074, 0x18c3,
+ 0x7075, 0x38c7,
+ 0x7076, 0x04e6,
+ 0x7078, 0x04e9,
+ 0x7079, 0x4099,
+ 0x707a, 0x18c4,
+ 0x707c, 0x04e7,
+ 0x707e, 0x4255,
+ 0x707f, 0x4693,
+ 0x7081, 0x4959,
+ 0x7082, 0x19f7,
+ 0x7083, 0x19f9,
+ 0x7084, 0x19f4,
+ 0x7085, 0x19f1,
+ 0x7086, 0x19f3,
+ 0x7089, 0x43f9,
+ 0x708a, 0x0643,
+ 0x708b, 0x40cb,
+ 0x708e, 0x0641,
+ 0x708f, 0x46b3,
+ 0x7091, 0x19f5,
+ 0x7092, 0x0642,
+ 0x7093, 0x19f2,
+ 0x7094, 0x19ef,
+ 0x7095, 0x0640,
+ 0x7096, 0x19f6,
+ 0x7098, 0x19f0,
+ 0x7099, 0x0644,
+ 0x709a, 0x19f8,
+ 0x709f, 0x1b66,
+ 0x70a0, 0x4742,
+ 0x70a1, 0x1b6a,
+ 0x70a3, 0x3972,
+ 0x70a4, 0x0790,
+ 0x70a5, 0x3cb7,
+ 0x70a6, 0x3d53,
+ 0x70a7, 0x4256,
+ 0x70a9, 0x1b6d,
+ 0x70ab, 0x0788,
+ 0x70ac, 0x078b,
+ 0x70ad, 0x078d,
+ 0x70ae, 0x078f,
+ 0x70af, 0x078c,
+ 0x70b0, 0x1b69,
+ 0x70b1, 0x1b68,
+ 0x70b3, 0x078a,
+ 0x70b4, 0x1b6b,
+ 0x70b7, 0x1b65,
+ 0x70b8, 0x078e,
+ 0x70b9, 0x3d69,
+ 0x70ba, 0x0789,
+ 0x70bb, 0x4812,
+ 0x70bc, 0x4559,
+ 0x70bd, 0x4270,
+ 0x70be, 0x1b67,
+ 0x70c0, 0x4733,
+ 0x70c4, 0x3baa,
+ 0x70c5, 0x1d27,
+ 0x70c8, 0x0921,
+ 0x70ca, 0x091d,
+ 0x70cb, 0x1d1e,
+ 0x70cc, 0x4258,
+ 0x70cd, 0x1d26,
+ 0x70ce, 0x1d2b,
+ 0x70cf, 0x0922,
+ 0x70d0, 0x396d,
+ 0x70d1, 0x1d1c,
+ 0x70d2, 0x1d22,
+ 0x70d3, 0x1d1b,
+ 0x70d4, 0x1d25,
+ 0x70d5, 0x4259,
+ 0x70d7, 0x1d21,
+ 0x70d8, 0x091e,
+ 0x70d9, 0x0920,
+ 0x70da, 0x1d2a,
+ 0x70dc, 0x1d1a,
+ 0x70dd, 0x1d1d,
+ 0x70de, 0x1d23,
+ 0x70df, 0x425b,
+ 0x70e0, 0x1d24,
+ 0x70e1, 0x1d2c,
+ 0x70e2, 0x1d20,
+ 0x70e4, 0x091f,
+ 0x70ef, 0x0b16,
+ 0x70f0, 0x1f72,
+ 0x70f1, 0x3ac8,
+ 0x70f3, 0x1f74,
+ 0x70f4, 0x1f70,
+ 0x70f5, 0x4760,
+ 0x70f6, 0x1f7c,
+ 0x70f7, 0x1f6e,
+ 0x70f8, 0x1f7b,
+ 0x70f9, 0x0b12,
+ 0x70fa, 0x1f6c,
+ 0x70fb, 0x21f2,
+ 0x70fc, 0x1f76,
+ 0x70fd, 0x0b15,
+ 0x70fe, 0x3d0e,
+ 0x70ff, 0x1f77,
+ 0x7100, 0x1f7a,
+ 0x7102, 0x1f7e,
+ 0x7104, 0x1f73,
+ 0x7105, 0x3a23,
+ 0x7106, 0x1f78,
+ 0x7109, 0x0b13,
+ 0x710b, 0x1f7d,
+ 0x710c, 0x1f71,
+ 0x710d, 0x1f6d,
+ 0x710e, 0x1f7f,
+ 0x7110, 0x1f75,
+ 0x7113, 0x1f79,
+ 0x7117, 0x1f6f,
+ 0x7119, 0x0cc8,
+ 0x711b, 0x21fc,
+ 0x711c, 0x0ccf,
+ 0x711d, 0x3d47,
+ 0x711e, 0x21f0,
+ 0x711f, 0x21f9,
+ 0x7120, 0x21ef,
+ 0x7121, 0x0ccc,
+ 0x7122, 0x21f7,
+ 0x7123, 0x21f5,
+ 0x7125, 0x21f6,
+ 0x7126, 0x0cca,
+ 0x7128, 0x21fa,
+ 0x7129, 0x3ba9,
+ 0x712b, 0x4261,
+ 0x712c, 0x426a,
+ 0x712e, 0x21f3,
+ 0x712f, 0x21f1,
+ 0x7130, 0x0ccb,
+ 0x7131, 0x21f4,
+ 0x7132, 0x21f8,
+ 0x7133, 0x3d54,
+ 0x7134, 0x3c7e,
+ 0x7135, 0x376d,
+ 0x7136, 0x0ccd,
+ 0x713a, 0x21fb,
+ 0x713b, 0x3ac5,
+ 0x713e, 0x372e,
+ 0x7140, 0x4398,
+ 0x7141, 0x247b,
+ 0x7142, 0x2482,
+ 0x7143, 0x2484,
+ 0x7144, 0x248a,
+ 0x7145, 0x4262,
+ 0x7146, 0x0e72,
+ 0x7147, 0x2476,
+ 0x7149, 0x0e6a,
+ 0x714a, 0x4264,
+ 0x714b, 0x2485,
+ 0x714c, 0x0e6f,
+ 0x714d, 0x248b,
+ 0x714e, 0x0e66,
+ 0x714f, 0x4267,
+ 0x7150, 0x2488,
+ 0x7151, 0x4865,
+ 0x7152, 0x2478,
+ 0x7153, 0x2489,
+ 0x7154, 0x2477,
+ 0x7156, 0x0e74,
+ 0x7158, 0x2483,
+ 0x7159, 0x0e67,
+ 0x715a, 0x248c,
+ 0x715c, 0x0e6c,
+ 0x715d, 0x247c,
+ 0x715e, 0x0e71,
+ 0x715f, 0x2487,
+ 0x7160, 0x247a,
+ 0x7161, 0x2481,
+ 0x7162, 0x247d,
+ 0x7163, 0x2479,
+ 0x7164, 0x0e69,
+ 0x7165, 0x0e70,
+ 0x7166, 0x0e6e,
+ 0x7167, 0x0e6b,
+ 0x7168, 0x0e73,
+ 0x7169, 0x0e68,
+ 0x716a, 0x2480,
+ 0x716b, 0x3cc5,
+ 0x716c, 0x0e6d,
+ 0x716e, 0x0cce,
+ 0x7170, 0x2486,
+ 0x7171, 0x3dc0,
+ 0x7172, 0x247e,
+ 0x7173, 0x47e7,
+ 0x7175, 0x3ced,
+ 0x7176, 0x4000,
+ 0x7177, 0x3957,
+ 0x7178, 0x247f,
+ 0x717a, 0x4924,
+ 0x717b, 0x271e,
+ 0x717c, 0x3835,
+ 0x717d, 0x1023,
+ 0x717e, 0x3970,
+ 0x7180, 0x271a,
+ 0x7181, 0x2720,
+ 0x7182, 0x271c,
+ 0x7184, 0x1025,
+ 0x7185, 0x271b,
+ 0x7186, 0x271f,
+ 0x7187, 0x2717,
+ 0x7188, 0x4706,
+ 0x7189, 0x2719,
+ 0x718a, 0x1024,
+ 0x718c, 0x39ea,
+ 0x718e, 0x3d3b,
+ 0x718f, 0x271d,
+ 0x7190, 0x2718,
+ 0x7192, 0x1026,
+ 0x7194, 0x1021,
+ 0x7196, 0x425f,
+ 0x7197, 0x2721,
+ 0x7198, 0x481d,
+ 0x7199, 0x1022,
+ 0x719a, 0x295a,
+ 0x719b, 0x2957,
+ 0x719c, 0x2963,
+ 0x719d, 0x295d,
+ 0x719e, 0x295f,
+ 0x719f, 0x119e,
+ 0x71a0, 0x2959,
+ 0x71a1, 0x2961,
+ 0x71a2, 0x48c1,
+ 0x71a3, 0x3ec8,
+ 0x71a4, 0x2960,
+ 0x71a5, 0x295e,
+ 0x71a7, 0x2964,
+ 0x71a8, 0x11a1,
+ 0x71a9, 0x295b,
+ 0x71aa, 0x2962,
+ 0x71ac, 0x119f,
+ 0x71ad, 0x3e1d,
+ 0x71af, 0x2956,
+ 0x71b0, 0x2958,
+ 0x71b1, 0x11a0,
+ 0x71b2, 0x2955,
+ 0x71b3, 0x2965,
+ 0x71b4, 0x425e,
+ 0x71b5, 0x295c,
+ 0x71b7, 0x468b,
+ 0x71b8, 0x2bb3,
+ 0x71b9, 0x12f3,
+ 0x71ba, 0x426e,
+ 0x71bc, 0x2bbe,
+ 0x71bd, 0x2bbc,
+ 0x71be, 0x12ed,
+ 0x71bf, 0x2bb2,
+ 0x71c0, 0x2bb5,
+ 0x71c2, 0x2bb1,
+ 0x71c3, 0x12f7,
+ 0x71c5, 0x2bb0,
+ 0x71c6, 0x2bbf,
+ 0x71c7, 0x2bba,
+ 0x71c8, 0x12f1,
+ 0x71c9, 0x12ee,
+ 0x71ca, 0x2bb9,
+ 0x71cb, 0x2bb7,
+ 0x71ce, 0x12f4,
+ 0x71cf, 0x2bbb,
+ 0x71d0, 0x12ef,
+ 0x71d1, 0x373d,
+ 0x71d2, 0x12f0,
+ 0x71d4, 0x2bb8,
+ 0x71d5, 0x12f2,
+ 0x71d6, 0x2bb4,
+ 0x71d8, 0x2bbd,
+ 0x71d9, 0x12f5,
+ 0x71da, 0x2bc0,
+ 0x71dc, 0x12f6,
+ 0x71dd, 0x4078,
+ 0x71df, 0x1404,
+ 0x71e0, 0x140b,
+ 0x71e1, 0x2d9b,
+ 0x71e2, 0x2da1,
+ 0x71e4, 0x2d9f,
+ 0x71e5, 0x1407,
+ 0x71e6, 0x1406,
+ 0x71e7, 0x1403,
+ 0x71e8, 0x2d9d,
+ 0x71eb, 0x3c81,
+ 0x71ec, 0x1409,
+ 0x71ed, 0x1408,
+ 0x71ee, 0x1405,
+ 0x71f0, 0x2da0,
+ 0x71f1, 0x2d9c,
+ 0x71f2, 0x2d9e,
+ 0x71f4, 0x140a,
+ 0x71f5, 0x46ee,
+ 0x71f6, 0x3e9a,
+ 0x71f8, 0x14f1,
+ 0x71f9, 0x2f52,
+ 0x71fb, 0x14ee,
+ 0x71fd, 0x2f54,
+ 0x71fe, 0x14f0,
+ 0x71ff, 0x2f51,
+ 0x7201, 0x2f50,
+ 0x7202, 0x30b9,
+ 0x7203, 0x2f53,
+ 0x7205, 0x30ba,
+ 0x7206, 0x1591,
+ 0x7207, 0x30b8,
+ 0x7209, 0x3dbb,
+ 0x720a, 0x30b7,
+ 0x720c, 0x30b6,
+ 0x720d, 0x1592,
+ 0x720e, 0x4271,
+ 0x720f, 0x39fc,
+ 0x7210, 0x161f,
+ 0x7213, 0x31f4,
+ 0x7215, 0x4273,
+ 0x7216, 0x3953,
+ 0x7217, 0x3969,
+ 0x7219, 0x32e1,
+ 0x721a, 0x32e0,
+ 0x721b, 0x167b,
+ 0x721d, 0x32df,
+ 0x721e, 0x338d,
+ 0x7222, 0x3424,
+ 0x7223, 0x348c,
+ 0x7224, 0x4276,
+ 0x7226, 0x34d1,
+ 0x7227, 0x3535,
+ 0x7228, 0x1766,
+ 0x7229, 0x3549,
+ 0x722a, 0x02e7,
+ 0x722b, 0x44f2,
+ 0x722c, 0x0645,
+ 0x722e, 0x4279,
+ 0x7230, 0x0791,
+ 0x7235, 0x140c,
+ 0x7236, 0x02e8,
+ 0x7238, 0x0647,
+ 0x7239, 0x0923,
+ 0x723a, 0x0e75,
+ 0x723b, 0x02e9,
+ 0x723d, 0x0b17,
+ 0x723e, 0x1027,
+ 0x723f, 0x178d,
+ 0x7240, 0x427a,
+ 0x7241, 0x1b6e,
+ 0x7242, 0x1d2d,
+ 0x7244, 0x2722,
+ 0x7246, 0x140d,
+ 0x7247, 0x02ea,
+ 0x7248, 0x0648,
+ 0x7249, 0x1b6f,
+ 0x724b, 0x21fd,
+ 0x724c, 0x0cd0,
+ 0x724f, 0x248d,
+ 0x7250, 0x3ac9,
+ 0x7252, 0x0e76,
+ 0x7253, 0x2723,
+ 0x7255, 0x427d,
+ 0x7256, 0x11a2,
+ 0x7257, 0x427e,
+ 0x7258, 0x1593,
+ 0x7259, 0x02eb,
+ 0x725a, 0x21fe,
+ 0x725b, 0x02ec,
+ 0x725c, 0x465a,
+ 0x725d, 0x03f4,
+ 0x725e, 0x180b,
+ 0x725f, 0x03f3,
+ 0x7260, 0x04ec,
+ 0x7261, 0x04eb,
+ 0x7262, 0x04ea,
+ 0x7263, 0x18c5,
+ 0x7266, 0x3ebb,
+ 0x7267, 0x0649,
+ 0x7269, 0x064a,
+ 0x726a, 0x19fa,
+ 0x726c, 0x1b71,
+ 0x726e, 0x1b74,
+ 0x726f, 0x0793,
+ 0x7270, 0x1b72,
+ 0x7272, 0x0792,
+ 0x7273, 0x1b73,
+ 0x7274, 0x0794,
+ 0x7276, 0x1d30,
+ 0x7277, 0x1d2f,
+ 0x7278, 0x1d2e,
+ 0x7279, 0x0924,
+ 0x727b, 0x1f81,
+ 0x727d, 0x0b18,
+ 0x727e, 0x1f80,
+ 0x727f, 0x1f83,
+ 0x7280, 0x0cd2,
+ 0x7281, 0x0b19,
+ 0x7282, 0x4283,
+ 0x7284, 0x0cd1,
+ 0x7285, 0x2202,
+ 0x7286, 0x2201,
+ 0x7287, 0x3aca,
+ 0x7288, 0x21ff,
+ 0x728b, 0x2203,
+ 0x728c, 0x248f,
+ 0x728d, 0x248e,
+ 0x728e, 0x2492,
+ 0x728f, 0x43c9,
+ 0x7290, 0x2491,
+ 0x7291, 0x2490,
+ 0x7292, 0x1028,
+ 0x7293, 0x2726,
+ 0x7294, 0x3acb,
+ 0x7295, 0x2725,
+ 0x7296, 0x1029,
+ 0x7297, 0x2724,
+ 0x7298, 0x2966,
+ 0x729a, 0x2967,
+ 0x729b, 0x11a3,
+ 0x729d, 0x2bc2,
+ 0x729f, 0x473a,
+ 0x72a1, 0x30bf,
+ 0x72a2, 0x1594,
+ 0x72a3, 0x30be,
+ 0x72a4, 0x30bd,
+ 0x72a5, 0x30bb,
+ 0x72a7, 0x167c,
+ 0x72a8, 0x31f6,
+ 0x72a9, 0x338f,
+ 0x72aa, 0x34d2,
+ 0x72ac, 0x02ed,
+ 0x72ad, 0x44f4,
+ 0x72ae, 0x17af,
+ 0x72af, 0x0355,
+ 0x72b0, 0x17b0,
+ 0x72b2, 0x3fb6,
+ 0x72b4, 0x180c,
+ 0x72ba, 0x18cb,
+ 0x72bd, 0x18c7,
+ 0x72bf, 0x18c6,
+ 0x72c0, 0x064b,
+ 0x72c1, 0x18ca,
+ 0x72c2, 0x04ee,
+ 0x72c3, 0x18c8,
+ 0x72c4, 0x04ed,
+ 0x72c5, 0x18cc,
+ 0x72c6, 0x18c9,
+ 0x72c9, 0x19fe,
+ 0x72ca, 0x1b75,
+ 0x72cb, 0x19fc,
+ 0x72cc, 0x1a03,
+ 0x72cd, 0x43ca,
+ 0x72ce, 0x064c,
+ 0x72d0, 0x064f,
+ 0x72d1, 0x1a04,
+ 0x72d2, 0x1a00,
+ 0x72d4, 0x1a01,
+ 0x72d6, 0x19fb,
+ 0x72d7, 0x064e,
+ 0x72d8, 0x19fd,
+ 0x72d9, 0x064d,
+ 0x72da, 0x1a02,
+ 0x72dc, 0x19ff,
+ 0x72df, 0x1b79,
+ 0x72e0, 0x0796,
+ 0x72e2, 0x3f97,
+ 0x72e3, 0x1b7c,
+ 0x72e4, 0x1b76,
+ 0x72e6, 0x1b7b,
+ 0x72e8, 0x1b77,
+ 0x72e9, 0x0795,
+ 0x72ea, 0x1b7a,
+ 0x72eb, 0x1b78,
+ 0x72f3, 0x1d36,
+ 0x72f4, 0x1d33,
+ 0x72f6, 0x1d35,
+ 0x72f7, 0x0929,
+ 0x72f8, 0x0928,
+ 0x72f9, 0x0926,
+ 0x72fa, 0x1d32,
+ 0x72fb, 0x1d37,
+ 0x72fc, 0x0925,
+ 0x72fd, 0x0927,
+ 0x72fe, 0x1d34,
+ 0x72ff, 0x1f8b,
+ 0x7300, 0x1d31,
+ 0x7301, 0x1d38,
+ 0x7302, 0x3f9a,
+ 0x7304, 0x3eb5,
+ 0x7307, 0x1f86,
+ 0x7308, 0x1f8a,
+ 0x730a, 0x1f89,
+ 0x730b, 0x2205,
+ 0x730c, 0x2210,
+ 0x730f, 0x1f8c,
+ 0x7310, 0x46ea,
+ 0x7311, 0x1f87,
+ 0x7312, 0x2204,
+ 0x7313, 0x0b1d,
+ 0x7316, 0x0b1c,
+ 0x7317, 0x1f85,
+ 0x7318, 0x1f88,
+ 0x7319, 0x0b1e,
+ 0x731b, 0x0b1b,
+ 0x731c, 0x0b1a,
+ 0x731d, 0x1f84,
+ 0x731e, 0x1f8d,
+ 0x7322, 0x2207,
+ 0x7323, 0x220e,
+ 0x7325, 0x0cd4,
+ 0x7326, 0x220d,
+ 0x7327, 0x220a,
+ 0x7328, 0x428a,
+ 0x7329, 0x0cd6,
+ 0x732a, 0x3d70,
+ 0x732b, 0x4285,
+ 0x732c, 0x3fb2,
+ 0x732d, 0x220c,
+ 0x732e, 0x428b,
+ 0x7330, 0x2206,
+ 0x7331, 0x2208,
+ 0x7332, 0x220b,
+ 0x7333, 0x2209,
+ 0x7334, 0x0cd5,
+ 0x7335, 0x220f,
+ 0x7336, 0x0cd3,
+ 0x7337, 0x0e77,
+ 0x7338, 0x46eb,
+ 0x7339, 0x43cc,
+ 0x733a, 0x2496,
+ 0x733b, 0x2495,
+ 0x733c, 0x2493,
+ 0x733e, 0x0e7a,
+ 0x733f, 0x0e79,
+ 0x7340, 0x2497,
+ 0x7341, 0x46ec,
+ 0x7342, 0x2494,
+ 0x7343, 0x2727,
+ 0x7344, 0x102a,
+ 0x7345, 0x0e78,
+ 0x7348, 0x43fa,
+ 0x7349, 0x2499,
+ 0x734a, 0x2498,
+ 0x734c, 0x272a,
+ 0x734d, 0x2728,
+ 0x734e, 0x11a4,
+ 0x734f, 0x3f51,
+ 0x7350, 0x102b,
+ 0x7351, 0x2729,
+ 0x7352, 0x2969,
+ 0x7357, 0x11a5,
+ 0x7358, 0x2968,
+ 0x7359, 0x2971,
+ 0x735a, 0x2970,
+ 0x735b, 0x296e,
+ 0x735d, 0x296d,
+ 0x735e, 0x296a,
+ 0x7361, 0x296f,
+ 0x7362, 0x2972,
+ 0x7365, 0x2bc8,
+ 0x7366, 0x2bc5,
+ 0x7368, 0x12f9,
+ 0x7369, 0x2bc4,
+ 0x736a, 0x2bca,
+ 0x736b, 0x2bc9,
+ 0x736c, 0x2bc7,
+ 0x736e, 0x2da3,
+ 0x7370, 0x140e,
+ 0x7371, 0x3f98,
+ 0x7372, 0x140f,
+ 0x7373, 0x2da2,
+ 0x7374, 0x3ed4,
+ 0x7375, 0x14f3,
+ 0x7376, 0x2f55,
+ 0x7377, 0x14f2,
+ 0x7378, 0x1595,
+ 0x737a, 0x1596,
+ 0x737b, 0x1620,
+ 0x737c, 0x31f8,
+ 0x737d, 0x31f7,
+ 0x737e, 0x32e2,
+ 0x737f, 0x3390,
+ 0x7380, 0x16ca,
+ 0x7381, 0x3426,
+ 0x7382, 0x3425,
+ 0x7383, 0x3427,
+ 0x7384, 0x0356,
+ 0x7385, 0x1b7d,
+ 0x7386, 0x092a,
+ 0x7387, 0x0b1f,
+ 0x7388, 0x1f8e,
+ 0x7389, 0x0357,
+ 0x738a, 0x17b1,
+ 0x738b, 0x02ee,
+ 0x738e, 0x180e,
+ 0x738f, 0x46e5,
+ 0x7392, 0x18d1,
+ 0x7393, 0x18cf,
+ 0x7395, 0x18cd,
+ 0x7396, 0x04ef,
+ 0x7397, 0x18ce,
+ 0x7398, 0x39f6,
+ 0x739c, 0x408a,
+ 0x739d, 0x1a0c,
+ 0x739e, 0x395b,
+ 0x739f, 0x0652,
+ 0x73a0, 0x1a0a,
+ 0x73a1, 0x1a06,
+ 0x73a2, 0x1a09,
+ 0x73a4, 0x1a05,
+ 0x73a5, 0x0654,
+ 0x73a6, 0x1a08,
+ 0x73a7, 0x4087,
+ 0x73a8, 0x0651,
+ 0x73a9, 0x0650,
+ 0x73aa, 0x428d,
+ 0x73ab, 0x0653,
+ 0x73ac, 0x1a0b,
+ 0x73ad, 0x1a07,
+ 0x73b2, 0x079b,
+ 0x73b3, 0x079e,
+ 0x73b4, 0x1b85,
+ 0x73b5, 0x1b84,
+ 0x73b6, 0x1b83,
+ 0x73b7, 0x0798,
+ 0x73b8, 0x1b8c,
+ 0x73b9, 0x1b82,
+ 0x73bb, 0x079a,
+ 0x73bc, 0x1d3d,
+ 0x73be, 0x1b89,
+ 0x73bf, 0x1b87,
+ 0x73c0, 0x079d,
+ 0x73c2, 0x1b7f,
+ 0x73c3, 0x1b8a,
+ 0x73c5, 0x1b81,
+ 0x73c6, 0x1b8b,
+ 0x73c7, 0x1b88,
+ 0x73c8, 0x1b80,
+ 0x73c9, 0x4290,
+ 0x73ca, 0x0799,
+ 0x73cb, 0x1b8d,
+ 0x73cc, 0x1b7e,
+ 0x73cd, 0x079c,
+ 0x73ce, 0x411b,
+ 0x73cf, 0x428c,
+ 0x73d0, 0x3b17,
+ 0x73d2, 0x1d42,
+ 0x73d3, 0x1d39,
+ 0x73d4, 0x1d44,
+ 0x73d5, 0x4073,
+ 0x73d6, 0x1d3c,
+ 0x73d7, 0x1d47,
+ 0x73d9, 0x1d3a,
+ 0x73da, 0x1d46,
+ 0x73db, 0x1d43,
+ 0x73dc, 0x1d41,
+ 0x73dd, 0x1d45,
+ 0x73de, 0x0930,
+ 0x73e0, 0x092e,
+ 0x73e1, 0x46f0,
+ 0x73e2, 0x3ca3,
+ 0x73e3, 0x1d3f,
+ 0x73e4, 0x42a5,
+ 0x73e5, 0x1d3b,
+ 0x73e6, 0x3cba,
+ 0x73e7, 0x1d3e,
+ 0x73e8, 0x1d49,
+ 0x73e9, 0x1d40,
+ 0x73ea, 0x092f,
+ 0x73eb, 0x1b86,
+ 0x73ed, 0x092b,
+ 0x73ee, 0x092d,
+ 0x73ef, 0x4011,
+ 0x73f3, 0x3cab,
+ 0x73f4, 0x1f9c,
+ 0x73f5, 0x1f91,
+ 0x73f6, 0x1f8f,
+ 0x73f7, 0x429a,
+ 0x73f8, 0x1f90,
+ 0x73f9, 0x3bf9,
+ 0x73fa, 0x1f97,
+ 0x73fb, 0x3cac,
+ 0x73fc, 0x1f98,
+ 0x73fd, 0x1f94,
+ 0x73fe, 0x0b24,
+ 0x73ff, 0x1f99,
+ 0x7400, 0x1f96,
+ 0x7401, 0x1f93,
+ 0x7403, 0x0b22,
+ 0x7404, 0x1f92,
+ 0x7405, 0x0b20,
+ 0x7406, 0x0b23,
+ 0x7407, 0x1f95,
+ 0x7408, 0x1f9d,
+ 0x7409, 0x092c,
+ 0x740a, 0x0b21,
+ 0x740b, 0x1f9b,
+ 0x740c, 0x1f9a,
+ 0x740d, 0x0b25,
+ 0x7411, 0x456c,
+ 0x7412, 0x3be6,
+ 0x7414, 0x39f4,
+ 0x7415, 0x429b,
+ 0x7416, 0x2215,
+ 0x7417, 0x40ad,
+ 0x7419, 0x46f3,
+ 0x741a, 0x2216,
+ 0x741b, 0x0ce0,
+ 0x741c, 0x38dd,
+ 0x741d, 0x221c,
+ 0x741e, 0x46f4,
+ 0x7420, 0x221e,
+ 0x7421, 0x2217,
+ 0x7422, 0x0cda,
+ 0x7423, 0x221b,
+ 0x7424, 0x221a,
+ 0x7425, 0x0cdb,
+ 0x7426, 0x0ce1,
+ 0x7428, 0x0ce2,
+ 0x7429, 0x221d,
+ 0x742a, 0x0cd8,
+ 0x742b, 0x2214,
+ 0x742c, 0x2212,
+ 0x742d, 0x2218,
+ 0x742e, 0x2211,
+ 0x742f, 0x0cdf,
+ 0x7430, 0x2213,
+ 0x7431, 0x2219,
+ 0x7432, 0x221f,
+ 0x7433, 0x0cd9,
+ 0x7434, 0x0cde,
+ 0x7435, 0x0cdc,
+ 0x7437, 0x3ae1,
+ 0x7438, 0x3b09,
+ 0x7439, 0x429e,
+ 0x743a, 0x0cd7,
+ 0x743c, 0x3adf,
+ 0x743f, 0x0e81,
+ 0x7440, 0x24a0,
+ 0x7441, 0x0e80,
+ 0x7442, 0x24a4,
+ 0x7443, 0x3a1a,
+ 0x7444, 0x249a,
+ 0x7445, 0x3bd7,
+ 0x7446, 0x24a5,
+ 0x7447, 0x42a4,
+ 0x7448, 0x3cb5,
+ 0x7449, 0x4291,
+ 0x744a, 0x249b,
+ 0x744d, 0x24a6,
+ 0x744e, 0x24a3,
+ 0x744f, 0x24a1,
+ 0x7451, 0x249e,
+ 0x7452, 0x249d,
+ 0x7453, 0x4231,
+ 0x7454, 0x24a7,
+ 0x7455, 0x0e7d,
+ 0x7456, 0x39f5,
+ 0x7457, 0x249f,
+ 0x7459, 0x0e82,
+ 0x745a, 0x0e7c,
+ 0x745b, 0x0e83,
+ 0x745d, 0x42c6,
+ 0x745e, 0x0e7f,
+ 0x745f, 0x0e7e,
+ 0x7460, 0x42a2,
+ 0x7462, 0x272b,
+ 0x7463, 0x102d,
+ 0x7464, 0x102c,
+ 0x7465, 0x4101,
+ 0x7467, 0x2730,
+ 0x7468, 0x3aee,
+ 0x7469, 0x11a6,
+ 0x746a, 0x102e,
+ 0x746b, 0x3be7,
+ 0x746c, 0x42a8,
+ 0x746d, 0x1030,
+ 0x746e, 0x2731,
+ 0x746f, 0x0e7b,
+ 0x7470, 0x102f,
+ 0x7471, 0x272d,
+ 0x7472, 0x272f,
+ 0x7473, 0x272c,
+ 0x7474, 0x42a9,
+ 0x7475, 0x272e,
+ 0x7476, 0x42a6,
+ 0x7479, 0x297c,
+ 0x747a, 0x3ad1,
+ 0x747c, 0x297b,
+ 0x747d, 0x2978,
+ 0x747e, 0x11a9,
+ 0x747f, 0x2bcb,
+ 0x7480, 0x11aa,
+ 0x7481, 0x2977,
+ 0x7482, 0x42ac,
+ 0x7483, 0x11a8,
+ 0x7485, 0x2979,
+ 0x7486, 0x2976,
+ 0x7487, 0x2973,
+ 0x7488, 0x297a,
+ 0x7489, 0x2974,
+ 0x748b, 0x11a7,
+ 0x748c, 0x3a21,
+ 0x748d, 0x469d,
+ 0x7490, 0x2da8,
+ 0x7492, 0x2bcf,
+ 0x7494, 0x2bce,
+ 0x7495, 0x2bd0,
+ 0x7497, 0x2da5,
+ 0x7498, 0x12fc,
+ 0x7499, 0x39f3,
+ 0x749a, 0x2bcc,
+ 0x749b, 0x3b0a,
+ 0x749c, 0x12fa,
+ 0x749e, 0x12fe,
+ 0x749f, 0x12fd,
+ 0x74a0, 0x2bcd,
+ 0x74a1, 0x2bd1,
+ 0x74a3, 0x12fb,
+ 0x74a4, 0x4170,
+ 0x74a5, 0x2dac,
+ 0x74a6, 0x1412,
+ 0x74a7, 0x14f4,
+ 0x74a8, 0x1413,
+ 0x74a9, 0x1410,
+ 0x74aa, 0x2da9,
+ 0x74ab, 0x2da7,
+ 0x74ad, 0x2daa,
+ 0x74af, 0x2dad,
+ 0x74b0, 0x1411,
+ 0x74b1, 0x2dab,
+ 0x74b2, 0x2da6,
+ 0x74b4, 0x3ca5,
+ 0x74b5, 0x2f58,
+ 0x74b6, 0x2f5b,
+ 0x74b7, 0x30c2,
+ 0x74b8, 0x2f56,
+ 0x74ba, 0x31f9,
+ 0x74bb, 0x2f5c,
+ 0x74bd, 0x1597,
+ 0x74be, 0x2f5a,
+ 0x74bf, 0x14f5,
+ 0x74c0, 0x2f57,
+ 0x74c1, 0x2f59,
+ 0x74c2, 0x2f5d,
+ 0x74c3, 0x30c3,
+ 0x74c5, 0x30c1,
+ 0x74c8, 0x42b5,
+ 0x74ca, 0x1598,
+ 0x74cb, 0x30c0,
+ 0x74cc, 0x3ade,
+ 0x74cf, 0x1621,
+ 0x74d0, 0x3a9b,
+ 0x74d3, 0x46fa,
+ 0x74d4, 0x167e,
+ 0x74d5, 0x3392,
+ 0x74d6, 0x167d,
+ 0x74d7, 0x3394,
+ 0x74d8, 0x3391,
+ 0x74d9, 0x3393,
+ 0x74da, 0x16fe,
+ 0x74db, 0x348d,
+ 0x74dc, 0x0358,
+ 0x74dd, 0x1a0d,
+ 0x74de, 0x1d4a,
+ 0x74e0, 0x0b26,
+ 0x74e1, 0x24a8,
+ 0x74e2, 0x12ff,
+ 0x74e3, 0x1599,
+ 0x74e4, 0x16cb,
+ 0x74e5, 0x348e,
+ 0x74e6, 0x0359,
+ 0x74e7, 0x3ffe,
+ 0x74e8, 0x1a0e,
+ 0x74e9, 0x0120,
+ 0x74ec, 0x1b8e,
+ 0x74ee, 0x1b8f,
+ 0x74f0, 0x3fe6,
+ 0x74f1, 0x3f9b,
+ 0x74f2, 0x3fdf,
+ 0x74f4, 0x1d4c,
+ 0x74f6, 0x0b27,
+ 0x74f8, 0x3ff4,
+ 0x74fb, 0x2220,
+ 0x74fd, 0x24ab,
+ 0x74fe, 0x24aa,
+ 0x74ff, 0x24a9,
+ 0x7500, 0x2732,
+ 0x7502, 0x2733,
+ 0x7504, 0x1031,
+ 0x7505, 0x3fde,
+ 0x7507, 0x297e,
+ 0x7508, 0x297d,
+ 0x750b, 0x2bd2,
+ 0x750c, 0x1300,
+ 0x750e, 0x42b7,
+ 0x750f, 0x2db1,
+ 0x7510, 0x2dae,
+ 0x7513, 0x2f5f,
+ 0x7514, 0x2f5e,
+ 0x7515, 0x14f6,
+ 0x7516, 0x30c4,
+ 0x7517, 0x32e3,
+ 0x7518, 0x035a,
+ 0x7519, 0x4583,
+ 0x751a, 0x079f,
+ 0x751c, 0x0b29,
+ 0x751d, 0x24ac,
+ 0x751e, 0x42b8,
+ 0x751f, 0x035b,
+ 0x7521, 0x1d4e,
+ 0x7522, 0x0b2a,
+ 0x7525, 0x0ce3,
+ 0x7528, 0x035c,
+ 0x752a, 0x180f,
+ 0x752b, 0x04f1,
+ 0x752c, 0x04f0,
+ 0x752d, 0x07a0,
+ 0x752e, 0x1b90,
+ 0x752f, 0x2221,
+ 0x7530, 0x035e,
+ 0x7534, 0x3e87,
+ 0x7535, 0x455a,
+ 0x7537, 0x04f2,
+ 0x7539, 0x18d3,
+ 0x753a, 0x18d2,
+ 0x753b, 0x3dfb,
+ 0x753d, 0x0655,
+ 0x753e, 0x1a11,
+ 0x753f, 0x1a0f,
+ 0x7542, 0x43cd,
+ 0x7546, 0x3f40,
+ 0x7547, 0x1b91,
+ 0x754a, 0x42bf,
+ 0x754b, 0x07a4,
+ 0x754c, 0x07a2,
+ 0x754d, 0x42be,
+ 0x754e, 0x07a3,
+ 0x754f, 0x07a1,
+ 0x7551, 0x3cfe,
+ 0x7553, 0x3feb,
+ 0x7554, 0x0931,
+ 0x7555, 0x3aea,
+ 0x7559, 0x0935,
+ 0x755a, 0x0934,
+ 0x755b, 0x1d4f,
+ 0x755c, 0x0933,
+ 0x755d, 0x0932,
+ 0x755f, 0x1d50,
+ 0x7560, 0x3d71,
+ 0x7562, 0x0b2d,
+ 0x7563, 0x1f9f,
+ 0x7564, 0x1f9e,
+ 0x7565, 0x0b2b,
+ 0x7567, 0x42c0,
+ 0x756a, 0x0ce6,
+ 0x756b, 0x0ce5,
+ 0x756c, 0x2223,
+ 0x756d, 0x46fd,
+ 0x756e, 0x42c1,
+ 0x756f, 0x2222,
+ 0x7570, 0x0b2e,
+ 0x7572, 0x46fe,
+ 0x7576, 0x0e85,
+ 0x7577, 0x24ae,
+ 0x7578, 0x0e86,
+ 0x7579, 0x24ad,
+ 0x757a, 0x3f4f,
+ 0x757d, 0x2735,
+ 0x757e, 0x297f,
+ 0x757f, 0x11ab,
+ 0x7580, 0x2bd3,
+ 0x7583, 0x3ae5,
+ 0x7584, 0x2db2,
+ 0x7586, 0x159b,
+ 0x7587, 0x159a,
+ 0x758a, 0x16cc,
+ 0x758b, 0x0362,
+ 0x758c, 0x1a12,
+ 0x758d, 0x46ff,
+ 0x758e, 0x42c5,
+ 0x758f, 0x0b2f,
+ 0x7590, 0x2736,
+ 0x7591, 0x1032,
+ 0x7592, 0x022e,
+ 0x7594, 0x18d4,
+ 0x7598, 0x1a13,
+ 0x7599, 0x0657,
+ 0x759d, 0x0656,
+ 0x759e, 0x42c7,
+ 0x75a2, 0x07a8,
+ 0x75a4, 0x07a6,
+ 0x75a7, 0x1b93,
+ 0x75aa, 0x1b94,
+ 0x75ab, 0x07a5,
+ 0x75b0, 0x1d51,
+ 0x75b1, 0x3ead,
+ 0x75b2, 0x0939,
+ 0x75b4, 0x42c8,
+ 0x75b5, 0x0b32,
+ 0x75b6, 0x1d57,
+ 0x75b8, 0x093f,
+ 0x75b9, 0x093d,
+ 0x75ba, 0x1d58,
+ 0x75bb, 0x1d53,
+ 0x75bc, 0x093c,
+ 0x75bd, 0x093b,
+ 0x75be, 0x0936,
+ 0x75bf, 0x1d56,
+ 0x75c0, 0x1d55,
+ 0x75c1, 0x1d52,
+ 0x75c2, 0x093e,
+ 0x75c3, 0x3f93,
+ 0x75c4, 0x1d54,
+ 0x75c5, 0x0937,
+ 0x75c7, 0x0938,
+ 0x75c8, 0x4701,
+ 0x75ca, 0x0b33,
+ 0x75cb, 0x1fa3,
+ 0x75cd, 0x0b34,
+ 0x75ce, 0x1fa0,
+ 0x75cf, 0x1fa2,
+ 0x75d0, 0x1fa6,
+ 0x75d1, 0x1fa5,
+ 0x75d2, 0x1fa1,
+ 0x75d4, 0x0b30,
+ 0x75d7, 0x222b,
+ 0x75d8, 0x0ceb,
+ 0x75d9, 0x0cea,
+ 0x75da, 0x2225,
+ 0x75db, 0x0ce8,
+ 0x75dc, 0x43ce,
+ 0x75dd, 0x2228,
+ 0x75de, 0x0cec,
+ 0x75df, 0x2229,
+ 0x75e0, 0x0ced,
+ 0x75e1, 0x2226,
+ 0x75e2, 0x0ce7,
+ 0x75e3, 0x0ce9,
+ 0x75e4, 0x222a,
+ 0x75e6, 0x2227,
+ 0x75e7, 0x2224,
+ 0x75ed, 0x24bb,
+ 0x75ef, 0x24b0,
+ 0x75f0, 0x0e88,
+ 0x75f1, 0x0e8b,
+ 0x75f2, 0x0e8a,
+ 0x75f3, 0x0e8f,
+ 0x75f4, 0x0e8e,
+ 0x75f5, 0x24bc,
+ 0x75f6, 0x24ba,
+ 0x75f7, 0x24b3,
+ 0x75f8, 0x24b7,
+ 0x75f9, 0x24b6,
+ 0x75fa, 0x0e8c,
+ 0x75fb, 0x24b9,
+ 0x75fc, 0x24b5,
+ 0x75fd, 0x24bd,
+ 0x75fe, 0x24b4,
+ 0x75ff, 0x0e8d,
+ 0x7600, 0x0e87,
+ 0x7601, 0x0e89,
+ 0x7602, 0x42c9,
+ 0x7603, 0x24b2,
+ 0x7607, 0x3f8f,
+ 0x7608, 0x2738,
+ 0x7609, 0x1036,
+ 0x760a, 0x273c,
+ 0x760b, 0x1035,
+ 0x760c, 0x2739,
+ 0x760d, 0x1034,
+ 0x760f, 0x24b1,
+ 0x7610, 0x24b8,
+ 0x7611, 0x273b,
+ 0x7613, 0x1037,
+ 0x7614, 0x273d,
+ 0x7615, 0x273a,
+ 0x7616, 0x2737,
+ 0x7619, 0x2982,
+ 0x761a, 0x2986,
+ 0x761b, 0x2988,
+ 0x761c, 0x2984,
+ 0x761d, 0x2983,
+ 0x761e, 0x2981,
+ 0x761f, 0x11ae,
+ 0x7620, 0x11ac,
+ 0x7621, 0x11b1,
+ 0x7623, 0x2985,
+ 0x7624, 0x11af,
+ 0x7625, 0x2980,
+ 0x7626, 0x11b0,
+ 0x7627, 0x1033,
+ 0x7628, 0x2987,
+ 0x7629, 0x11ad,
+ 0x762c, 0x42ca,
+ 0x762d, 0x2bd5,
+ 0x762f, 0x2bd4,
+ 0x7630, 0x2bdc,
+ 0x7631, 0x2bd6,
+ 0x7632, 0x2bdb,
+ 0x7633, 0x2bd8,
+ 0x7634, 0x1302,
+ 0x7635, 0x2bda,
+ 0x7638, 0x1303,
+ 0x763a, 0x1304,
+ 0x763b, 0x3e70,
+ 0x763c, 0x2bd9,
+ 0x763d, 0x2bd7,
+ 0x7640, 0x3ee6,
+ 0x7642, 0x1415,
+ 0x7643, 0x2db3,
+ 0x7646, 0x1414,
+ 0x7647, 0x2db6,
+ 0x7648, 0x2db4,
+ 0x764c, 0x1416,
+ 0x764d, 0x4702,
+ 0x764e, 0x3e72,
+ 0x764f, 0x42cc,
+ 0x7650, 0x2f63,
+ 0x7651, 0x42cb,
+ 0x7652, 0x14f9,
+ 0x7653, 0x2f64,
+ 0x7654, 0x3ef0,
+ 0x7656, 0x14f7,
+ 0x7657, 0x2f65,
+ 0x7658, 0x14f8,
+ 0x7659, 0x2f62,
+ 0x765a, 0x2f66,
+ 0x765c, 0x2f60,
+ 0x765f, 0x159c,
+ 0x7660, 0x30c5,
+ 0x7661, 0x159d,
+ 0x7662, 0x1622,
+ 0x7664, 0x2f61,
+ 0x7665, 0x1623,
+ 0x7666, 0x3eaa,
+ 0x7667, 0x3fa9,
+ 0x7669, 0x167f,
+ 0x766a, 0x32e4,
+ 0x766c, 0x16ce,
+ 0x766d, 0x3395,
+ 0x766e, 0x16cd,
+ 0x766f, 0x42cd,
+ 0x7670, 0x3428,
+ 0x7671, 0x1723,
+ 0x7673, 0x3aeb,
+ 0x7674, 0x4703,
+ 0x7675, 0x3543,
+ 0x7676, 0x022f,
+ 0x7678, 0x07aa,
+ 0x7679, 0x1b95,
+ 0x767a, 0x4705,
+ 0x767b, 0x0cee,
+ 0x767d, 0x0363,
+ 0x767e, 0x03f5,
+ 0x767f, 0x1810,
+ 0x7680, 0x43d3,
+ 0x7681, 0x18d6,
+ 0x7682, 0x04f4,
+ 0x7684, 0x0659,
+ 0x7686, 0x07ab,
+ 0x7689, 0x1fa8,
+ 0x768a, 0x1d59,
+ 0x768b, 0x0940,
+ 0x768c, 0x43d4,
+ 0x768e, 0x0b35,
+ 0x768f, 0x1fa7,
+ 0x7690, 0x42d0,
+ 0x7692, 0x222d,
+ 0x7693, 0x0cf1,
+ 0x7695, 0x222c,
+ 0x7696, 0x0cf0,
+ 0x7699, 0x24be,
+ 0x769a, 0x11b3,
+ 0x769b, 0x298c,
+ 0x769c, 0x2989,
+ 0x76a1, 0x42d5,
+ 0x76a4, 0x2db7,
+ 0x76a5, 0x42d6,
+ 0x76a6, 0x2f67,
+ 0x76aa, 0x31fb,
+ 0x76ab, 0x31fa,
+ 0x76ad, 0x3396,
+ 0x76ae, 0x0364,
+ 0x76af, 0x1a14,
+ 0x76b0, 0x0941,
+ 0x76b4, 0x0cf2,
+ 0x76b5, 0x24bf,
+ 0x76b7, 0x42d7,
+ 0x76b8, 0x273e,
+ 0x76ba, 0x11b4,
+ 0x76bb, 0x2bdd,
+ 0x76bd, 0x2f68,
+ 0x76be, 0x31fc,
+ 0x76bf, 0x0365,
+ 0x76c2, 0x065a,
+ 0x76c3, 0x07b0,
+ 0x76c4, 0x1b96,
+ 0x76c5, 0x07b1,
+ 0x76c6, 0x07af,
+ 0x76c8, 0x07ae,
+ 0x76c9, 0x1d5a,
+ 0x76ca, 0x0942,
+ 0x76cc, 0x42d8,
+ 0x76cd, 0x0943,
+ 0x76d2, 0x0b37,
+ 0x76d3, 0x1fa9,
+ 0x76d4, 0x0b36,
+ 0x76d6, 0x3f55,
+ 0x76da, 0x222e,
+ 0x76db, 0x0b38,
+ 0x76dc, 0x0cf3,
+ 0x76dd, 0x24c0,
+ 0x76de, 0x0e90,
+ 0x76e1, 0x1038,
+ 0x76e3, 0x1039,
+ 0x76e4, 0x11b5,
+ 0x76e5, 0x1306,
+ 0x76e6, 0x2bde,
+ 0x76e7, 0x1305,
+ 0x76e9, 0x2db8,
+ 0x76ea, 0x1417,
+ 0x76ec, 0x2f69,
+ 0x76ed, 0x31fd,
+ 0x76ee, 0x0366,
+ 0x76ef, 0x04f5,
+ 0x76f0, 0x1a17,
+ 0x76f1, 0x1a16,
+ 0x76f2, 0x065b,
+ 0x76f3, 0x1a15,
+ 0x76f4, 0x065c,
+ 0x76f5, 0x1a18,
+ 0x76f7, 0x1b9c,
+ 0x76f8, 0x07b4,
+ 0x76f9, 0x07b3,
+ 0x76fa, 0x1b9e,
+ 0x76fb, 0x1b9d,
+ 0x76fc, 0x07b8,
+ 0x76fe, 0x07b7,
+ 0x7701, 0x07b2,
+ 0x7703, 0x1b98,
+ 0x7707, 0x07b9,
+ 0x7708, 0x1b97,
+ 0x7709, 0x07b5,
+ 0x770a, 0x1b9b,
+ 0x770b, 0x07b6,
+ 0x770c, 0x3d62,
+ 0x770e, 0x3b02,
+ 0x7710, 0x1d5d,
+ 0x7711, 0x1d61,
+ 0x7712, 0x1d5f,
+ 0x7713, 0x1d5e,
+ 0x7715, 0x1d62,
+ 0x7719, 0x1d63,
+ 0x771b, 0x1d5c,
+ 0x771d, 0x1d5b,
+ 0x771e, 0x42de,
+ 0x771f, 0x0946,
+ 0x7722, 0x1d65,
+ 0x7723, 0x1d60,
+ 0x7724, 0x3fe8,
+ 0x7725, 0x1fb2,
+ 0x7726, 0x42df,
+ 0x7727, 0x1d66,
+ 0x7728, 0x0948,
+ 0x7729, 0x0945,
+ 0x772b, 0x3ff3,
+ 0x772d, 0x1fac,
+ 0x772f, 0x1fab,
+ 0x7731, 0x1fad,
+ 0x7733, 0x1fb0,
+ 0x7734, 0x1faf,
+ 0x7735, 0x1fb4,
+ 0x7736, 0x0b3c,
+ 0x7737, 0x0b39,
+ 0x7738, 0x0b3d,
+ 0x7739, 0x1faa,
+ 0x773a, 0x0b3e,
+ 0x773b, 0x1fb3,
+ 0x773c, 0x0b3b,
+ 0x773d, 0x1fb1,
+ 0x773e, 0x0b3a,
+ 0x7740, 0x42e0,
+ 0x7743, 0x470a,
+ 0x7744, 0x2231,
+ 0x7745, 0x2233,
+ 0x7746, 0x222f,
+ 0x774a, 0x2234,
+ 0x774b, 0x2236,
+ 0x774d, 0x2232,
+ 0x774e, 0x2235,
+ 0x774f, 0x0cf4,
+ 0x7752, 0x24c4,
+ 0x7754, 0x24c9,
+ 0x7755, 0x24c1,
+ 0x7756, 0x24c5,
+ 0x7758, 0x42e3,
+ 0x7759, 0x24ca,
+ 0x775a, 0x24c6,
+ 0x775b, 0x0e92,
+ 0x775c, 0x0e9a,
+ 0x775e, 0x0e95,
+ 0x775f, 0x24c2,
+ 0x7761, 0x103d,
+ 0x7762, 0x0e9d,
+ 0x7763, 0x0e96,
+ 0x7765, 0x0e9b,
+ 0x7766, 0x0e94,
+ 0x7767, 0x24c8,
+ 0x7768, 0x0e9c,
+ 0x7769, 0x24c7,
+ 0x776a, 0x0e98,
+ 0x776b, 0x0e93,
+ 0x776c, 0x0e99,
+ 0x776d, 0x24cb,
+ 0x776e, 0x2743,
+ 0x776f, 0x2745,
+ 0x7772, 0x396b,
+ 0x7777, 0x46a9,
+ 0x7778, 0x3b00,
+ 0x7779, 0x0e97,
+ 0x777a, 0x4317,
+ 0x777b, 0x3b04,
+ 0x777c, 0x2740,
+ 0x777d, 0x103b,
+ 0x777e, 0x2746,
+ 0x777f, 0x103c,
+ 0x7780, 0x2744,
+ 0x7781, 0x273f,
+ 0x7782, 0x2742,
+ 0x7783, 0x2747,
+ 0x7784, 0x103a,
+ 0x7785, 0x2741,
+ 0x7787, 0x11b7,
+ 0x7788, 0x2990,
+ 0x7789, 0x298f,
+ 0x778b, 0x11ba,
+ 0x778c, 0x11b8,
+ 0x778d, 0x298d,
+ 0x778e, 0x11b6,
+ 0x778f, 0x298e,
+ 0x7791, 0x11b9,
+ 0x7793, 0x382d,
+ 0x7795, 0x2be6,
+ 0x7797, 0x2be8,
+ 0x7798, 0x470e,
+ 0x7799, 0x2be7,
+ 0x779a, 0x2bdf,
+ 0x779b, 0x2be3,
+ 0x779c, 0x2be2,
+ 0x779d, 0x2be0,
+ 0x779e, 0x1308,
+ 0x77a0, 0x1307,
+ 0x77a1, 0x2be1,
+ 0x77a2, 0x2be4,
+ 0x77a5, 0x130a,
+ 0x77a7, 0x141c,
+ 0x77a8, 0x2dc0,
+ 0x77aa, 0x1419,
+ 0x77ab, 0x2dba,
+ 0x77ac, 0x141b,
+ 0x77ad, 0x141d,
+ 0x77af, 0x42e5,
+ 0x77b0, 0x141a,
+ 0x77b1, 0x2dbf,
+ 0x77b2, 0x2dbb,
+ 0x77b3, 0x1418,
+ 0x77b4, 0x2dbe,
+ 0x77b5, 0x2db9,
+ 0x77b6, 0x2dbd,
+ 0x77b7, 0x2dbc,
+ 0x77b9, 0x3e73,
+ 0x77ba, 0x2f6b,
+ 0x77bb, 0x14fc,
+ 0x77bd, 0x14fa,
+ 0x77be, 0x4711,
+ 0x77bf, 0x14fb,
+ 0x77c2, 0x2f6a,
+ 0x77c3, 0x3bb1,
+ 0x77c4, 0x30c8,
+ 0x77c5, 0x41c1,
+ 0x77c7, 0x159e,
+ 0x77c9, 0x30c6,
+ 0x77cb, 0x4712,
+ 0x77cc, 0x31fe,
+ 0x77cd, 0x3201,
+ 0x77ce, 0x31ff,
+ 0x77d0, 0x32e5,
+ 0x77d3, 0x1680,
+ 0x77d4, 0x3429,
+ 0x77d5, 0x348f,
+ 0x77d7, 0x1725,
+ 0x77d8, 0x34d3,
+ 0x77da, 0x1753,
+ 0x77db, 0x0367,
+ 0x77dc, 0x07ba,
+ 0x77de, 0x2238,
+ 0x77e0, 0x24cc,
+ 0x77e2, 0x0368,
+ 0x77e3, 0x04f6,
+ 0x77e5, 0x065d,
+ 0x77e6, 0x4081,
+ 0x77e7, 0x1b9f,
+ 0x77e9, 0x0949,
+ 0x77ec, 0x2239,
+ 0x77ed, 0x0cf5,
+ 0x77ee, 0x0e9e,
+ 0x77ef, 0x141e,
+ 0x77f0, 0x2dc1,
+ 0x77f1, 0x30c9,
+ 0x77f2, 0x3202,
+ 0x77f3, 0x0369,
+ 0x77f4, 0x42e9,
+ 0x77f7, 0x1a1e,
+ 0x77f8, 0x1a19,
+ 0x77f9, 0x1a1b,
+ 0x77fa, 0x1a1d,
+ 0x77fb, 0x1a1c,
+ 0x77fc, 0x1a1a,
+ 0x77fd, 0x065e,
+ 0x77fe, 0x3fd5,
+ 0x7802, 0x07bb,
+ 0x7803, 0x1ba9,
+ 0x7805, 0x1ba4,
+ 0x7806, 0x1ba1,
+ 0x7808, 0x3e46,
+ 0x7809, 0x1ba8,
+ 0x780c, 0x07bd,
+ 0x780e, 0x1ba7,
+ 0x780f, 0x1ba6,
+ 0x7810, 0x1ba5,
+ 0x7811, 0x1ba2,
+ 0x7813, 0x1baa,
+ 0x7814, 0x07bc,
+ 0x7818, 0x4713,
+ 0x781c, 0x4714,
+ 0x781d, 0x094d,
+ 0x781e, 0x3b13,
+ 0x781f, 0x0953,
+ 0x7820, 0x0952,
+ 0x7821, 0x1d6f,
+ 0x7822, 0x1d69,
+ 0x7823, 0x1d67,
+ 0x7825, 0x0950,
+ 0x7826, 0x1fbb,
+ 0x7827, 0x094b,
+ 0x7828, 0x1d6c,
+ 0x7829, 0x1d70,
+ 0x782a, 0x1d72,
+ 0x782b, 0x1d6e,
+ 0x782c, 0x1d68,
+ 0x782d, 0x0951,
+ 0x782e, 0x1d6d,
+ 0x782f, 0x1d6b,
+ 0x7830, 0x094a,
+ 0x7831, 0x1d73,
+ 0x7832, 0x0954,
+ 0x7833, 0x1d71,
+ 0x7834, 0x094e,
+ 0x7835, 0x1d6a,
+ 0x7837, 0x094f,
+ 0x7838, 0x094c,
+ 0x7839, 0x43d6,
+ 0x783c, 0x401a,
+ 0x783d, 0x3c6a,
+ 0x7842, 0x3ac4,
+ 0x7843, 0x0b40,
+ 0x7844, 0x3c2b,
+ 0x7845, 0x1fbc,
+ 0x7847, 0x4715,
+ 0x7848, 0x1fb5,
+ 0x7849, 0x1fb7,
+ 0x784a, 0x1fb9,
+ 0x784b, 0x3c6d,
+ 0x784c, 0x1fba,
+ 0x784d, 0x1fb8,
+ 0x784e, 0x0b41,
+ 0x7850, 0x1fbd,
+ 0x7851, 0x4716,
+ 0x7852, 0x1fb6,
+ 0x7853, 0x3f95,
+ 0x7854, 0x3c6b,
+ 0x785c, 0x223d,
+ 0x785d, 0x0cf6,
+ 0x785e, 0x2245,
+ 0x7860, 0x223a,
+ 0x7862, 0x2246,
+ 0x7864, 0x223b,
+ 0x7866, 0x4717,
+ 0x7868, 0x2244,
+ 0x7869, 0x2243,
+ 0x786a, 0x2240,
+ 0x786b, 0x0b3f,
+ 0x786c, 0x0cf7,
+ 0x786d, 0x223e,
+ 0x786e, 0x2241,
+ 0x786f, 0x0cf8,
+ 0x7870, 0x2242,
+ 0x7871, 0x223f,
+ 0x7879, 0x24d7,
+ 0x787a, 0x3ee9,
+ 0x787b, 0x24db,
+ 0x787c, 0x0ea5,
+ 0x787e, 0x274d,
+ 0x787f, 0x0ea8,
+ 0x7880, 0x24d9,
+ 0x7881, 0x36e8,
+ 0x7883, 0x24d6,
+ 0x7884, 0x24d1,
+ 0x7885, 0x24d3,
+ 0x7887, 0x24cd,
+ 0x7888, 0x3b15,
+ 0x7889, 0x0ea4,
+ 0x788c, 0x0ea3,
+ 0x788d, 0x3b14,
+ 0x788e, 0x0e9f,
+ 0x788f, 0x24d0,
+ 0x7891, 0x0ea6,
+ 0x7893, 0x0ea7,
+ 0x7894, 0x24cf,
+ 0x7895, 0x24d2,
+ 0x7896, 0x24da,
+ 0x7897, 0x0ea1,
+ 0x7899, 0x24d8,
+ 0x789a, 0x24ce,
+ 0x789e, 0x274f,
+ 0x789f, 0x103f,
+ 0x78a0, 0x2751,
+ 0x78a1, 0x24d5,
+ 0x78a2, 0x2753,
+ 0x78a3, 0x1043,
+ 0x78a4, 0x2754,
+ 0x78a5, 0x2750,
+ 0x78a7, 0x1040,
+ 0x78a8, 0x274c,
+ 0x78a9, 0x1042,
+ 0x78aa, 0x2749,
+ 0x78ab, 0x274e,
+ 0x78ac, 0x2752,
+ 0x78ad, 0x274b,
+ 0x78af, 0x42ec,
+ 0x78b0, 0x0ea0,
+ 0x78b1, 0x42f4,
+ 0x78b2, 0x2748,
+ 0x78b3, 0x1041,
+ 0x78b4, 0x274a,
+ 0x78b6, 0x3c6c,
+ 0x78b8, 0x4571,
+ 0x78b9, 0x3c63,
+ 0x78ba, 0x11bd,
+ 0x78bb, 0x2992,
+ 0x78bc, 0x11c1,
+ 0x78be, 0x11bf,
+ 0x78c1, 0x103e,
+ 0x78c3, 0x2999,
+ 0x78c5, 0x11bc,
+ 0x78c7, 0x42ed,
+ 0x78c8, 0x2998,
+ 0x78c9, 0x299b,
+ 0x78ca, 0x11be,
+ 0x78cb, 0x11bb,
+ 0x78cc, 0x2994,
+ 0x78cd, 0x2991,
+ 0x78ce, 0x2996,
+ 0x78cf, 0x2993,
+ 0x78d0, 0x11c2,
+ 0x78d1, 0x2995,
+ 0x78d2, 0x3b16,
+ 0x78d3, 0x42ee,
+ 0x78d4, 0x2997,
+ 0x78d5, 0x11c0,
+ 0x78d7, 0x42f2,
+ 0x78d8, 0x3f8c,
+ 0x78da, 0x130c,
+ 0x78db, 0x2bef,
+ 0x78dd, 0x2be9,
+ 0x78de, 0x2bed,
+ 0x78df, 0x2bf3,
+ 0x78e1, 0x2bf0,
+ 0x78e3, 0x2bee,
+ 0x78e5, 0x2beb,
+ 0x78e7, 0x130e,
+ 0x78e8, 0x130b,
+ 0x78e9, 0x2bea,
+ 0x78ea, 0x2bec,
+ 0x78ec, 0x130d,
+ 0x78ed, 0x2bf2,
+ 0x78ee, 0x3a81,
+ 0x78ef, 0x1422,
+ 0x78f0, 0x3b3a,
+ 0x78f1, 0x40be,
+ 0x78f2, 0x2dc8,
+ 0x78f3, 0x2dc2,
+ 0x78f4, 0x1421,
+ 0x78f5, 0x38b3,
+ 0x78f7, 0x141f,
+ 0x78f9, 0x2dca,
+ 0x78fa, 0x1420,
+ 0x78fb, 0x2dc5,
+ 0x78fd, 0x2dc3,
+ 0x78fe, 0x2dcb,
+ 0x78ff, 0x2dc7,
+ 0x7901, 0x1423,
+ 0x7902, 0x2dc4,
+ 0x7904, 0x2dcc,
+ 0x7905, 0x2dc9,
+ 0x7906, 0x3fcf,
+ 0x7909, 0x2f6f,
+ 0x790c, 0x2f6c,
+ 0x790e, 0x14fe,
+ 0x7910, 0x2f70,
+ 0x7911, 0x2f72,
+ 0x7912, 0x2f71,
+ 0x7913, 0x2f6d,
+ 0x7917, 0x30ce,
+ 0x7919, 0x159f,
+ 0x791b, 0x30cb,
+ 0x791c, 0x30cd,
+ 0x791d, 0x30ca,
+ 0x791e, 0x30cf,
+ 0x7921, 0x30cc,
+ 0x7923, 0x3204,
+ 0x7924, 0x3207,
+ 0x7925, 0x3203,
+ 0x7926, 0x1624,
+ 0x7927, 0x3205,
+ 0x7929, 0x3208,
+ 0x792a, 0x1625,
+ 0x792b, 0x1627,
+ 0x792c, 0x1626,
+ 0x792d, 0x32e6,
+ 0x792e, 0x42f0,
+ 0x792f, 0x32e8,
+ 0x7931, 0x32e7,
+ 0x7932, 0x471b,
+ 0x7933, 0x471a,
+ 0x7934, 0x42f3,
+ 0x7935, 0x3397,
+ 0x7936, 0x3783,
+ 0x7938, 0x3490,
+ 0x7939, 0x34d5,
+ 0x793a, 0x036a,
+ 0x793b, 0x44f7,
+ 0x793c, 0x4300,
+ 0x793d, 0x18d7,
+ 0x793e, 0x065f,
+ 0x793f, 0x1a20,
+ 0x7940, 0x0660,
+ 0x7942, 0x1a1f,
+ 0x7944, 0x1baf,
+ 0x7945, 0x1bae,
+ 0x7946, 0x07bf,
+ 0x7947, 0x07c2,
+ 0x7948, 0x07c1,
+ 0x7949, 0x07c0,
+ 0x794a, 0x1bab,
+ 0x794b, 0x1bad,
+ 0x794c, 0x1bac,
+ 0x794f, 0x1d76,
+ 0x7950, 0x0956,
+ 0x7951, 0x1d7a,
+ 0x7952, 0x1d79,
+ 0x7953, 0x1d78,
+ 0x7954, 0x1d74,
+ 0x7955, 0x0955,
+ 0x7956, 0x0959,
+ 0x7957, 0x095c,
+ 0x7958, 0x37e5,
+ 0x7959, 0x3b18,
+ 0x795a, 0x095d,
+ 0x795b, 0x1d75,
+ 0x795c, 0x1d77,
+ 0x795d, 0x095b,
+ 0x795e, 0x095a,
+ 0x795f, 0x0958,
+ 0x7960, 0x0957,
+ 0x7961, 0x1fc4,
+ 0x7962, 0x3e7d,
+ 0x7963, 0x1fc2,
+ 0x7964, 0x1fbe,
+ 0x7965, 0x0b42,
+ 0x7967, 0x1fbf,
+ 0x7968, 0x0b43,
+ 0x7969, 0x1fc0,
+ 0x796b, 0x1fc3,
+ 0x796d, 0x0b44,
+ 0x7970, 0x224a,
+ 0x7971, 0x4168,
+ 0x7972, 0x2249,
+ 0x7973, 0x2248,
+ 0x7974, 0x2247,
+ 0x7979, 0x24df,
+ 0x797a, 0x0ea9,
+ 0x797c, 0x24dc,
+ 0x797d, 0x24de,
+ 0x797e, 0x3e26,
+ 0x797f, 0x0eaa,
+ 0x7980, 0x42fc,
+ 0x7981, 0x0eab,
+ 0x7982, 0x24dd,
+ 0x7983, 0x3df6,
+ 0x7986, 0x42f9,
+ 0x7987, 0x4588,
+ 0x7988, 0x275d,
+ 0x798a, 0x2756,
+ 0x798d, 0x1046,
+ 0x798e, 0x1044,
+ 0x7990, 0x275f,
+ 0x7991, 0x471d,
+ 0x7992, 0x275e,
+ 0x7993, 0x275b,
+ 0x7994, 0x275a,
+ 0x7995, 0x2759,
+ 0x7996, 0x2758,
+ 0x7997, 0x275c,
+ 0x7998, 0x2755,
+ 0x7999, 0x43fc,
+ 0x799a, 0x299c,
+ 0x799b, 0x29a1,
+ 0x799c, 0x299f,
+ 0x799d, 0x42fe,
+ 0x799f, 0x395e,
+ 0x79a0, 0x299e,
+ 0x79a1, 0x299d,
+ 0x79a2, 0x29a0,
+ 0x79a4, 0x2bf5,
+ 0x79a5, 0x3b1e,
+ 0x79a6, 0x130f,
+ 0x79a7, 0x1424,
+ 0x79a8, 0x2dce,
+ 0x79a9, 0x4301,
+ 0x79aa, 0x1425,
+ 0x79ab, 0x2dcd,
+ 0x79ac, 0x2f74,
+ 0x79ad, 0x2f73,
+ 0x79ae, 0x14ff,
+ 0x79b0, 0x30d0,
+ 0x79b1, 0x15a0,
+ 0x79b2, 0x3209,
+ 0x79b3, 0x16cf,
+ 0x79b4, 0x3398,
+ 0x79b6, 0x3492,
+ 0x79b7, 0x3491,
+ 0x79b8, 0x17b2,
+ 0x79b9, 0x07c3,
+ 0x79bb, 0x1fc5,
+ 0x79bd, 0x0ead,
+ 0x79be, 0x036b,
+ 0x79bf, 0x04f9,
+ 0x79c0, 0x04f8,
+ 0x79c1, 0x04f7,
+ 0x79c4, 0x3ccd,
+ 0x79c5, 0x1a21,
+ 0x79c6, 0x4305,
+ 0x79c8, 0x0663,
+ 0x79c9, 0x0662,
+ 0x79cb, 0x07c7,
+ 0x79cc, 0x4233,
+ 0x79cd, 0x1bb1,
+ 0x79ce, 0x1bb4,
+ 0x79cf, 0x1bb2,
+ 0x79d1, 0x07c5,
+ 0x79d4, 0x4307,
+ 0x79d5, 0x1bb0,
+ 0x79d6, 0x1bb3,
+ 0x79d8, 0x0964,
+ 0x79dc, 0x1d81,
+ 0x79dd, 0x1d83,
+ 0x79de, 0x1d82,
+ 0x79df, 0x0961,
+ 0x79e0, 0x1d7d,
+ 0x79e2, 0x3c5a,
+ 0x79e3, 0x095f,
+ 0x79e4, 0x095e,
+ 0x79e6, 0x0962,
+ 0x79e7, 0x0960,
+ 0x79e9, 0x0963,
+ 0x79ea, 0x1d80,
+ 0x79eb, 0x1d7b,
+ 0x79ed, 0x1d7f,
+ 0x79ee, 0x1d7e,
+ 0x79f1, 0x3b27,
+ 0x79f4, 0x3b22,
+ 0x79f6, 0x1fc8,
+ 0x79f8, 0x1fc7,
+ 0x79fa, 0x1fc6,
+ 0x79fb, 0x0b45,
+ 0x7a00, 0x0cfd,
+ 0x7a02, 0x224b,
+ 0x7a03, 0x224d,
+ 0x7a04, 0x224f,
+ 0x7a05, 0x0cfc,
+ 0x7a06, 0x471e,
+ 0x7a08, 0x0cfa,
+ 0x7a0a, 0x224c,
+ 0x7a0b, 0x0cfb,
+ 0x7a0c, 0x224e,
+ 0x7a0d, 0x0cf9,
+ 0x7a10, 0x24e9,
+ 0x7a11, 0x24e0,
+ 0x7a12, 0x24e3,
+ 0x7a13, 0x24e7,
+ 0x7a14, 0x0eb1,
+ 0x7a15, 0x24e5,
+ 0x7a17, 0x24e4,
+ 0x7a18, 0x24e1,
+ 0x7a1a, 0x0eaf,
+ 0x7a1b, 0x24e8,
+ 0x7a1c, 0x0eae,
+ 0x7a1e, 0x0eb3,
+ 0x7a1f, 0x0eb2,
+ 0x7a20, 0x0eb0,
+ 0x7a22, 0x24e6,
+ 0x7a26, 0x2765,
+ 0x7a28, 0x2764,
+ 0x7a2b, 0x2760,
+ 0x7a2d, 0x3fda,
+ 0x7a2e, 0x1047,
+ 0x7a2f, 0x2763,
+ 0x7a30, 0x2762,
+ 0x7a31, 0x1048,
+ 0x7a37, 0x11c7,
+ 0x7a39, 0x29a3,
+ 0x7a3a, 0x3b21,
+ 0x7a3b, 0x11c8,
+ 0x7a3c, 0x11c4,
+ 0x7a3d, 0x11c6,
+ 0x7a3e, 0x3f8b,
+ 0x7a3f, 0x11c3,
+ 0x7a40, 0x11c5,
+ 0x7a43, 0x396c,
+ 0x7a44, 0x2bf6,
+ 0x7a45, 0x3df1,
+ 0x7a46, 0x1312,
+ 0x7a47, 0x2bf8,
+ 0x7a48, 0x2bf7,
+ 0x7a49, 0x3733,
+ 0x7a4a, 0x2761,
+ 0x7a4b, 0x1314,
+ 0x7a4c, 0x1313,
+ 0x7a4d, 0x1310,
+ 0x7a54, 0x2dd3,
+ 0x7a56, 0x2dd1,
+ 0x7a57, 0x1426,
+ 0x7a58, 0x2dd2,
+ 0x7a5a, 0x2dd4,
+ 0x7a5b, 0x2dd0,
+ 0x7a5c, 0x2dcf,
+ 0x7a5f, 0x2f75,
+ 0x7a60, 0x1502,
+ 0x7a61, 0x1500,
+ 0x7a65, 0x3736,
+ 0x7a67, 0x30d1,
+ 0x7a69, 0x15a2,
+ 0x7a6b, 0x15a1,
+ 0x7a6c, 0x320b,
+ 0x7a6e, 0x320a,
+ 0x7a70, 0x3399,
+ 0x7a74, 0x036c,
+ 0x7a75, 0x1811,
+ 0x7a76, 0x04fa,
+ 0x7a78, 0x1a22,
+ 0x7a79, 0x0665,
+ 0x7a7a, 0x0664,
+ 0x7a7b, 0x1a23,
+ 0x7a7d, 0x3737,
+ 0x7a7e, 0x1bb6,
+ 0x7a7f, 0x07c8,
+ 0x7a80, 0x1bb5,
+ 0x7a81, 0x07c9,
+ 0x7a83, 0x3d7d,
+ 0x7a84, 0x0965,
+ 0x7a85, 0x1d86,
+ 0x7a86, 0x1d84,
+ 0x7a87, 0x1d8a,
+ 0x7a88, 0x0966,
+ 0x7a89, 0x1d85,
+ 0x7a8a, 0x1d89,
+ 0x7a8b, 0x1d87,
+ 0x7a8f, 0x1fca,
+ 0x7a90, 0x1fcc,
+ 0x7a91, 0x43d8,
+ 0x7a92, 0x0b46,
+ 0x7a94, 0x1fcb,
+ 0x7a95, 0x0b47,
+ 0x7a96, 0x0d00,
+ 0x7a97, 0x0cff,
+ 0x7a98, 0x0cfe,
+ 0x7a99, 0x2250,
+ 0x7a9e, 0x24ec,
+ 0x7a9f, 0x0eb4,
+ 0x7aa2, 0x24eb,
+ 0x7aa3, 0x24ea,
+ 0x7aa8, 0x2766,
+ 0x7aa9, 0x104a,
+ 0x7aaa, 0x1049,
+ 0x7aab, 0x2767,
+ 0x7aae, 0x11ca,
+ 0x7aaf, 0x11c9,
+ 0x7ab0, 0x373a,
+ 0x7ab1, 0x2bfc,
+ 0x7ab2, 0x29a4,
+ 0x7ab3, 0x29a6,
+ 0x7ab4, 0x29a5,
+ 0x7ab5, 0x2bfb,
+ 0x7ab6, 0x2bf9,
+ 0x7ab7, 0x2bfd,
+ 0x7ab8, 0x2bfa,
+ 0x7aba, 0x1315,
+ 0x7abb, 0x3739,
+ 0x7abc, 0x4721,
+ 0x7abe, 0x2dd5,
+ 0x7abf, 0x1427,
+ 0x7ac0, 0x2dd6,
+ 0x7ac2, 0x373b,
+ 0x7ac4, 0x1503,
+ 0x7ac7, 0x1628,
+ 0x7ac8, 0x3d7f,
+ 0x7ac9, 0x4570,
+ 0x7aca, 0x16ff,
+ 0x7acb, 0x036d,
+ 0x7acf, 0x4724,
+ 0x7ad1, 0x1bb7,
+ 0x7ad3, 0x3f8a,
+ 0x7ad8, 0x1d8b,
+ 0x7ad9, 0x0967,
+ 0x7ada, 0x3740,
+ 0x7adb, 0x4725,
+ 0x7adc, 0x3951,
+ 0x7add, 0x3741,
+ 0x7adf, 0x0bde,
+ 0x7ae0, 0x0bdd,
+ 0x7ae2, 0x3b33,
+ 0x7ae3, 0x0d02,
+ 0x7ae4, 0x2252,
+ 0x7ae5, 0x0d01,
+ 0x7ae6, 0x2251,
+ 0x7ae7, 0x385d,
+ 0x7ae9, 0x3831,
+ 0x7aea, 0x3742,
+ 0x7aeb, 0x24ed,
+ 0x7aed, 0x104b,
+ 0x7aee, 0x2769,
+ 0x7aef, 0x104c,
+ 0x7af6, 0x1629,
+ 0x7af7, 0x320d,
+ 0x7af9, 0x03f6,
+ 0x7afa, 0x0666,
+ 0x7afb, 0x1a24,
+ 0x7afd, 0x07cb,
+ 0x7afe, 0x3b3d,
+ 0x7aff, 0x07ca,
+ 0x7b00, 0x1bb8,
+ 0x7b04, 0x1d8d,
+ 0x7b05, 0x1d8f,
+ 0x7b06, 0x0968,
+ 0x7b08, 0x1d91,
+ 0x7b09, 0x1d94,
+ 0x7b0a, 0x1d92,
+ 0x7b0b, 0x3746,
+ 0x7b0c, 0x3b63,
+ 0x7b0e, 0x1d93,
+ 0x7b0f, 0x1d90,
+ 0x7b10, 0x1d8c,
+ 0x7b11, 0x0969,
+ 0x7b12, 0x1d95,
+ 0x7b13, 0x1d8e,
+ 0x7b14, 0x3f77,
+ 0x7b18, 0x1fd5,
+ 0x7b19, 0x0b4d,
+ 0x7b1a, 0x1fde,
+ 0x7b1b, 0x0b4a,
+ 0x7b1d, 0x1fd7,
+ 0x7b1e, 0x0b4e,
+ 0x7b1f, 0x3f11,
+ 0x7b20, 0x0b48,
+ 0x7b22, 0x1fd2,
+ 0x7b23, 0x1fdf,
+ 0x7b24, 0x1fd3,
+ 0x7b25, 0x1fd0,
+ 0x7b26, 0x0b4c,
+ 0x7b27, 0x3b5f,
+ 0x7b28, 0x0b49,
+ 0x7b29, 0x3748,
+ 0x7b2a, 0x1fd6,
+ 0x7b2b, 0x1fd9,
+ 0x7b2c, 0x0b4b,
+ 0x7b2d, 0x1fda,
+ 0x7b2e, 0x0b4f,
+ 0x7b2f, 0x1fdb,
+ 0x7b30, 0x1fd1,
+ 0x7b31, 0x1fd8,
+ 0x7b32, 0x1fdc,
+ 0x7b33, 0x1fd4,
+ 0x7b34, 0x1fcf,
+ 0x7b35, 0x1fcd,
+ 0x7b38, 0x1fdd,
+ 0x7b39, 0x3d6e,
+ 0x7b3b, 0x1fce,
+ 0x7b40, 0x2259,
+ 0x7b42, 0x3ded,
+ 0x7b43, 0x3e25,
+ 0x7b44, 0x2255,
+ 0x7b45, 0x225b,
+ 0x7b46, 0x0d05,
+ 0x7b47, 0x2254,
+ 0x7b48, 0x2256,
+ 0x7b49, 0x0d03,
+ 0x7b4a, 0x2253,
+ 0x7b4b, 0x0d0a,
+ 0x7b4c, 0x2257,
+ 0x7b4d, 0x0d09,
+ 0x7b4e, 0x2258,
+ 0x7b4f, 0x0d0b,
+ 0x7b50, 0x0d06,
+ 0x7b51, 0x0d0c,
+ 0x7b52, 0x0d07,
+ 0x7b54, 0x0d08,
+ 0x7b55, 0x3747,
+ 0x7b56, 0x0d04,
+ 0x7b58, 0x225a,
+ 0x7b60, 0x0eb8,
+ 0x7b61, 0x24f8,
+ 0x7b62, 0x4727,
+ 0x7b63, 0x24fb,
+ 0x7b64, 0x24ef,
+ 0x7b65, 0x24f4,
+ 0x7b66, 0x24ee,
+ 0x7b67, 0x0eba,
+ 0x7b69, 0x24f2,
+ 0x7b6c, 0x4728,
+ 0x7b6d, 0x24f0,
+ 0x7b6e, 0x0eb9,
+ 0x7b6f, 0x374c,
+ 0x7b70, 0x24f7,
+ 0x7b71, 0x24f6,
+ 0x7b72, 0x24f3,
+ 0x7b73, 0x24f5,
+ 0x7b74, 0x24f1,
+ 0x7b75, 0x1050,
+ 0x7b76, 0x24fa,
+ 0x7b77, 0x0eb6,
+ 0x7b78, 0x24f9,
+ 0x7b7b, 0x4729,
+ 0x7b82, 0x2779,
+ 0x7b84, 0x1057,
+ 0x7b85, 0x2774,
+ 0x7b87, 0x1056,
+ 0x7b88, 0x276a,
+ 0x7b8a, 0x276c,
+ 0x7b8b, 0x104f,
+ 0x7b8c, 0x2771,
+ 0x7b8d, 0x2770,
+ 0x7b8e, 0x2773,
+ 0x7b8f, 0x1054,
+ 0x7b90, 0x276e,
+ 0x7b91, 0x276d,
+ 0x7b92, 0x3752,
+ 0x7b94, 0x1053,
+ 0x7b95, 0x104e,
+ 0x7b96, 0x276f,
+ 0x7b97, 0x1051,
+ 0x7b98, 0x2775,
+ 0x7b99, 0x2777,
+ 0x7b9b, 0x2772,
+ 0x7b9c, 0x276b,
+ 0x7b9d, 0x1052,
+ 0x7ba0, 0x11d2,
+ 0x7ba1, 0x104d,
+ 0x7ba2, 0x374b,
+ 0x7ba3, 0x3f14,
+ 0x7ba4, 0x2778,
+ 0x7bac, 0x29aa,
+ 0x7bad, 0x11cb,
+ 0x7baf, 0x29ac,
+ 0x7bb1, 0x11cc,
+ 0x7bb2, 0x461c,
+ 0x7bb4, 0x11ce,
+ 0x7bb5, 0x29af,
+ 0x7bb7, 0x29a7,
+ 0x7bb8, 0x1055,
+ 0x7bb9, 0x29ad,
+ 0x7bbe, 0x29a9,
+ 0x7bc0, 0x0eb7,
+ 0x7bc1, 0x11d1,
+ 0x7bc4, 0x11cd,
+ 0x7bc6, 0x11cf,
+ 0x7bc9, 0x1318,
+ 0x7bca, 0x29ae,
+ 0x7bcb, 0x29a8,
+ 0x7bcc, 0x11d3,
+ 0x7bce, 0x29ab,
+ 0x7bcf, 0x3f18,
+ 0x7bd0, 0x3750,
+ 0x7bd4, 0x2c07,
+ 0x7bd5, 0x2c02,
+ 0x7bd8, 0x2c0c,
+ 0x7bd9, 0x1316,
+ 0x7bda, 0x2c04,
+ 0x7bdb, 0x131a,
+ 0x7bdc, 0x2c0a,
+ 0x7bdd, 0x2c01,
+ 0x7bde, 0x2bfe,
+ 0x7bdf, 0x2c0d,
+ 0x7be0, 0x142d,
+ 0x7be1, 0x131b,
+ 0x7be2, 0x2c09,
+ 0x7be3, 0x2bff,
+ 0x7be4, 0x1319,
+ 0x7be5, 0x2c03,
+ 0x7be6, 0x131d,
+ 0x7be7, 0x2c00,
+ 0x7be8, 0x2c05,
+ 0x7be9, 0x131c,
+ 0x7bea, 0x2c08,
+ 0x7beb, 0x2c0b,
+ 0x7bf0, 0x2de9,
+ 0x7bf2, 0x2dda,
+ 0x7bf3, 0x2de1,
+ 0x7bf4, 0x2ddf,
+ 0x7bf7, 0x142b,
+ 0x7bf8, 0x2de6,
+ 0x7bf9, 0x2c06,
+ 0x7bfa, 0x3757,
+ 0x7bfb, 0x2ddd,
+ 0x7bfc, 0x3f1f,
+ 0x7bfd, 0x2de7,
+ 0x7bfe, 0x142a,
+ 0x7bff, 0x2ddc,
+ 0x7c00, 0x2ddb,
+ 0x7c01, 0x2de5,
+ 0x7c02, 0x2de2,
+ 0x7c03, 0x2de4,
+ 0x7c05, 0x2dd8,
+ 0x7c06, 0x2de8,
+ 0x7c07, 0x1428,
+ 0x7c09, 0x2de3,
+ 0x7c0a, 0x2dec,
+ 0x7c0b, 0x2de0,
+ 0x7c0c, 0x142c,
+ 0x7c0d, 0x1429,
+ 0x7c0e, 0x2dde,
+ 0x7c0f, 0x2dd9,
+ 0x7c10, 0x2deb,
+ 0x7c11, 0x1317,
+ 0x7c12, 0x472a,
+ 0x7c15, 0x4061,
+ 0x7c19, 0x2f78,
+ 0x7c1b, 0x43d9,
+ 0x7c1c, 0x2f76,
+ 0x7c1d, 0x2f7c,
+ 0x7c1e, 0x1508,
+ 0x7c1f, 0x2f7a,
+ 0x7c20, 0x2f79,
+ 0x7c21, 0x150a,
+ 0x7c22, 0x2f7f,
+ 0x7c23, 0x1509,
+ 0x7c25, 0x2f80,
+ 0x7c26, 0x2f7d,
+ 0x7c27, 0x1506,
+ 0x7c28, 0x2f7e,
+ 0x7c29, 0x2f77,
+ 0x7c2a, 0x1507,
+ 0x7c2b, 0x1505,
+ 0x7c2c, 0x30d6,
+ 0x7c2d, 0x2f7b,
+ 0x7c30, 0x2f81,
+ 0x7c33, 0x30d3,
+ 0x7c35, 0x3759,
+ 0x7c37, 0x15a7,
+ 0x7c38, 0x15a5,
+ 0x7c39, 0x30d5,
+ 0x7c3b, 0x30d7,
+ 0x7c3c, 0x30d4,
+ 0x7c3d, 0x15a6,
+ 0x7c3e, 0x15a3,
+ 0x7c40, 0x15a8,
+ 0x7c42, 0x3f1c,
+ 0x7c43, 0x162b,
+ 0x7c44, 0x375b,
+ 0x7c45, 0x3212,
+ 0x7c47, 0x3211,
+ 0x7c48, 0x320f,
+ 0x7c49, 0x320e,
+ 0x7c4a, 0x3210,
+ 0x7c4c, 0x162a,
+ 0x7c4d, 0x162c,
+ 0x7c50, 0x1681,
+ 0x7c51, 0x3fb8,
+ 0x7c53, 0x32ea,
+ 0x7c54, 0x32e9,
+ 0x7c56, 0x3eff,
+ 0x7c57, 0x339b,
+ 0x7c59, 0x339d,
+ 0x7c5a, 0x339f,
+ 0x7c5b, 0x339e,
+ 0x7c5c, 0x339c,
+ 0x7c5d, 0x3b3f,
+ 0x7c5f, 0x16d1,
+ 0x7c60, 0x16d0,
+ 0x7c63, 0x1701,
+ 0x7c64, 0x1700,
+ 0x7c65, 0x1702,
+ 0x7c66, 0x342b,
+ 0x7c67, 0x342a,
+ 0x7c69, 0x34d6,
+ 0x7c6a, 0x3493,
+ 0x7c6b, 0x34d7,
+ 0x7c6c, 0x1745,
+ 0x7c6d, 0x3b40,
+ 0x7c6e, 0x1746,
+ 0x7c6f, 0x3507,
+ 0x7c70, 0x3f52,
+ 0x7c72, 0x176b,
+ 0x7c73, 0x03f7,
+ 0x7c74, 0x469c,
+ 0x7c75, 0x1a25,
+ 0x7c78, 0x1bbb,
+ 0x7c7a, 0x1bba,
+ 0x7c7b, 0x472d,
+ 0x7c7c, 0x3b49,
+ 0x7c7d, 0x07cc,
+ 0x7c7e, 0x3f1a,
+ 0x7c7f, 0x1bbd,
+ 0x7c83, 0x375c,
+ 0x7c84, 0x1d96,
+ 0x7c85, 0x1d9c,
+ 0x7c86, 0x3f1d,
+ 0x7c88, 0x1d9a,
+ 0x7c89, 0x096a,
+ 0x7c8a, 0x1d98,
+ 0x7c8c, 0x1d99,
+ 0x7c8d, 0x1d9b,
+ 0x7c8e, 0x3b48,
+ 0x7c91, 0x1d97,
+ 0x7c92, 0x0b50,
+ 0x7c94, 0x1fe0,
+ 0x7c95, 0x0b52,
+ 0x7c96, 0x1fe2,
+ 0x7c97, 0x0b51,
+ 0x7c98, 0x1fe1,
+ 0x7c9c, 0x472e,
+ 0x7c9e, 0x225d,
+ 0x7c9f, 0x0d0d,
+ 0x7ca1, 0x225f,
+ 0x7ca2, 0x225c,
+ 0x7ca3, 0x1fe3,
+ 0x7ca5, 0x0d0e,
+ 0x7ca6, 0x375e,
+ 0x7ca7, 0x36ed,
+ 0x7ca8, 0x225e,
+ 0x7cac, 0x3885,
+ 0x7cae, 0x3b4a,
+ 0x7caf, 0x24fe,
+ 0x7cb1, 0x0ebb,
+ 0x7cb2, 0x24fc,
+ 0x7cb3, 0x0ebc,
+ 0x7cb4, 0x24fd,
+ 0x7cb5, 0x0ebd,
+ 0x7cb8, 0x4730,
+ 0x7cb9, 0x1058,
+ 0x7cba, 0x277d,
+ 0x7cbb, 0x277a,
+ 0x7cbc, 0x277c,
+ 0x7cbd, 0x1059,
+ 0x7cbf, 0x277b,
+ 0x7cc2, 0x3fd7,
+ 0x7cc5, 0x29b0,
+ 0x7cc7, 0x3761,
+ 0x7cc8, 0x29b1,
+ 0x7cc9, 0x3760,
+ 0x7cca, 0x11d4,
+ 0x7ccb, 0x29b3,
+ 0x7ccc, 0x29b2,
+ 0x7ccd, 0x3b45,
+ 0x7cce, 0x0121,
+ 0x7cd0, 0x2c11,
+ 0x7cd2, 0x2c0e,
+ 0x7cd3, 0x3d5c,
+ 0x7cd4, 0x2c0f,
+ 0x7cd5, 0x131e,
+ 0x7cd7, 0x2c10,
+ 0x7cd9, 0x1433,
+ 0x7cda, 0x3fd9,
+ 0x7cdc, 0x142f,
+ 0x7cdd, 0x1434,
+ 0x7cde, 0x1430,
+ 0x7cdf, 0x1432,
+ 0x7ce0, 0x142e,
+ 0x7ce2, 0x1431,
+ 0x7ce6, 0x3762,
+ 0x7ce7, 0x150b,
+ 0x7ce8, 0x2ded,
+ 0x7cea, 0x30d9,
+ 0x7cec, 0x30d8,
+ 0x7ced, 0x43da,
+ 0x7cee, 0x3213,
+ 0x7cef, 0x162d,
+ 0x7cf1, 0x33a1,
+ 0x7cf2, 0x32eb,
+ 0x7cf3, 0x3764,
+ 0x7cf4, 0x33a0,
+ 0x7cf5, 0x3765,
+ 0x7cf6, 0x34d8,
+ 0x7cf7, 0x351d,
+ 0x7cf8, 0x03f8,
+ 0x7cf9, 0x44f8,
+ 0x7cfb, 0x04fb,
+ 0x7cfc, 0x456d,
+ 0x7cfd, 0x1a26,
+ 0x7cfe, 0x0667,
+ 0x7d00, 0x07cf,
+ 0x7d01, 0x1bc2,
+ 0x7d02, 0x07cd,
+ 0x7d03, 0x1bc0,
+ 0x7d04, 0x07d2,
+ 0x7d05, 0x07ce,
+ 0x7d06, 0x07d3,
+ 0x7d07, 0x07d1,
+ 0x7d08, 0x1bc1,
+ 0x7d09, 0x07d0,
+ 0x7d0a, 0x096e,
+ 0x7d0b, 0x096d,
+ 0x7d0c, 0x1da7,
+ 0x7d0d, 0x0976,
+ 0x7d0e, 0x1da0,
+ 0x7d0f, 0x1da6,
+ 0x7d10, 0x0972,
+ 0x7d11, 0x1d9f,
+ 0x7d12, 0x1da5,
+ 0x7d13, 0x1da3,
+ 0x7d14, 0x0971,
+ 0x7d15, 0x0973,
+ 0x7d16, 0x1da2,
+ 0x7d17, 0x096c,
+ 0x7d18, 0x1da1,
+ 0x7d19, 0x0977,
+ 0x7d1a, 0x0974,
+ 0x7d1b, 0x0978,
+ 0x7d1c, 0x0975,
+ 0x7d1d, 0x1d9e,
+ 0x7d1e, 0x1d9d,
+ 0x7d1f, 0x1da4,
+ 0x7d20, 0x096f,
+ 0x7d21, 0x096b,
+ 0x7d22, 0x0970,
+ 0x7d25, 0x3ede,
+ 0x7d28, 0x1ff2,
+ 0x7d29, 0x1feb,
+ 0x7d2b, 0x0d13,
+ 0x7d2c, 0x1fea,
+ 0x7d2e, 0x0b56,
+ 0x7d2f, 0x0b5d,
+ 0x7d30, 0x0b5a,
+ 0x7d31, 0x0b60,
+ 0x7d32, 0x0b5f,
+ 0x7d33, 0x0b5b,
+ 0x7d35, 0x1fe4,
+ 0x7d36, 0x1fe7,
+ 0x7d38, 0x1fe6,
+ 0x7d39, 0x0b57,
+ 0x7d3a, 0x1fe8,
+ 0x7d3b, 0x1ff1,
+ 0x7d3c, 0x0b58,
+ 0x7d3d, 0x1fe5,
+ 0x7d3e, 0x1fee,
+ 0x7d40, 0x0b59,
+ 0x7d41, 0x1fec,
+ 0x7d42, 0x0b5e,
+ 0x7d43, 0x0b54,
+ 0x7d44, 0x0b5c,
+ 0x7d45, 0x1fe9,
+ 0x7d46, 0x0b53,
+ 0x7d47, 0x1fed,
+ 0x7d4a, 0x1ff0,
+ 0x7d4d, 0x3fdd,
+ 0x7d4e, 0x2270,
+ 0x7d4f, 0x2267,
+ 0x7d50, 0x0d10,
+ 0x7d51, 0x226e,
+ 0x7d52, 0x226b,
+ 0x7d53, 0x2263,
+ 0x7d54, 0x226c,
+ 0x7d55, 0x0d12,
+ 0x7d56, 0x2264,
+ 0x7d58, 0x2260,
+ 0x7d5a, 0x3e93,
+ 0x7d5b, 0x0ec3,
+ 0x7d5c, 0x2269,
+ 0x7d5d, 0x3769,
+ 0x7d5e, 0x0d0f,
+ 0x7d5f, 0x226f,
+ 0x7d61, 0x0d16,
+ 0x7d62, 0x0d18,
+ 0x7d63, 0x2262,
+ 0x7d66, 0x0d17,
+ 0x7d67, 0x2265,
+ 0x7d68, 0x0d11,
+ 0x7d69, 0x226d,
+ 0x7d6a, 0x2266,
+ 0x7d6b, 0x226a,
+ 0x7d6d, 0x2268,
+ 0x7d6e, 0x0d14,
+ 0x7d6f, 0x2261,
+ 0x7d70, 0x0d19,
+ 0x7d71, 0x0b55,
+ 0x7d72, 0x0d15,
+ 0x7d73, 0x0d1a,
+ 0x7d79, 0x0ebf,
+ 0x7d7a, 0x2505,
+ 0x7d7b, 0x2507,
+ 0x7d7c, 0x2509,
+ 0x7d7d, 0x250d,
+ 0x7d7f, 0x2503,
+ 0x7d80, 0x2501,
+ 0x7d81, 0x0ec1,
+ 0x7d83, 0x2508,
+ 0x7d84, 0x250c,
+ 0x7d85, 0x2504,
+ 0x7d86, 0x2500,
+ 0x7d88, 0x24ff,
+ 0x7d89, 0x376b,
+ 0x7d8c, 0x250a,
+ 0x7d8d, 0x2502,
+ 0x7d8e, 0x2506,
+ 0x7d8f, 0x0ec2,
+ 0x7d91, 0x0ec0,
+ 0x7d92, 0x250e,
+ 0x7d93, 0x0ebe,
+ 0x7d94, 0x250b,
+ 0x7d96, 0x278e,
+ 0x7d97, 0x3b53,
+ 0x7d9c, 0x105d,
+ 0x7d9d, 0x2786,
+ 0x7d9e, 0x11e1,
+ 0x7d9f, 0x2790,
+ 0x7da0, 0x1060,
+ 0x7da1, 0x2794,
+ 0x7da2, 0x1066,
+ 0x7da3, 0x2781,
+ 0x7da4, 0x46d7,
+ 0x7da6, 0x2791,
+ 0x7da7, 0x277e,
+ 0x7da8, 0x3c9c,
+ 0x7da9, 0x2793,
+ 0x7daa, 0x2782,
+ 0x7dab, 0x376c,
+ 0x7dac, 0x106d,
+ 0x7dad, 0x106a,
+ 0x7dae, 0x2792,
+ 0x7daf, 0x278c,
+ 0x7db0, 0x105c,
+ 0x7db1, 0x1064,
+ 0x7db2, 0x1063,
+ 0x7db3, 0x376e,
+ 0x7db4, 0x1062,
+ 0x7db5, 0x1068,
+ 0x7db7, 0x277f,
+ 0x7db8, 0x1069,
+ 0x7db9, 0x278d,
+ 0x7dba, 0x1065,
+ 0x7dbb, 0x105b,
+ 0x7dbc, 0x278f,
+ 0x7dbd, 0x105e,
+ 0x7dbf, 0x1067,
+ 0x7dc0, 0x2784,
+ 0x7dc1, 0x2783,
+ 0x7dc2, 0x2780,
+ 0x7dc4, 0x2788,
+ 0x7dc5, 0x2785,
+ 0x7dc6, 0x2789,
+ 0x7dc7, 0x106c,
+ 0x7dc9, 0x2795,
+ 0x7dca, 0x1061,
+ 0x7dcb, 0x278a,
+ 0x7dcd, 0x456e,
+ 0x7dce, 0x2787,
+ 0x7dcf, 0x4735,
+ 0x7dd0, 0x4737,
+ 0x7dd2, 0x106b,
+ 0x7dd3, 0x3b4e,
+ 0x7dd4, 0x4736,
+ 0x7dd6, 0x376f,
+ 0x7dd7, 0x29b8,
+ 0x7dd8, 0x11d9,
+ 0x7dd9, 0x11e2,
+ 0x7dda, 0x11de,
+ 0x7ddb, 0x29b5,
+ 0x7ddc, 0x3b4c,
+ 0x7ddd, 0x11db,
+ 0x7dde, 0x11df,
+ 0x7ddf, 0x29c1,
+ 0x7de0, 0x11d5,
+ 0x7de1, 0x29b9,
+ 0x7de3, 0x11dd,
+ 0x7de4, 0x3772,
+ 0x7de5, 0x3776,
+ 0x7de6, 0x29bc,
+ 0x7de7, 0x29b7,
+ 0x7de8, 0x11dc,
+ 0x7de9, 0x11e0,
+ 0x7dea, 0x29b6,
+ 0x7dec, 0x11da,
+ 0x7dee, 0x29c0,
+ 0x7def, 0x11d7,
+ 0x7df0, 0x29bf,
+ 0x7df1, 0x29be,
+ 0x7df2, 0x11e3,
+ 0x7df3, 0x28c8,
+ 0x7df4, 0x11d6,
+ 0x7df5, 0x3774,
+ 0x7df6, 0x29bd,
+ 0x7df7, 0x29b4,
+ 0x7df9, 0x11e4,
+ 0x7dfa, 0x29bb,
+ 0x7dfb, 0x11d8,
+ 0x7dfd, 0x4738,
+ 0x7dfe, 0x3ccf,
+ 0x7e03, 0x29ba,
+ 0x7e07, 0x3b4d,
+ 0x7e08, 0x1322,
+ 0x7e09, 0x1327,
+ 0x7e0a, 0x1320,
+ 0x7e0b, 0x2c1f,
+ 0x7e0c, 0x2c16,
+ 0x7e0d, 0x2c22,
+ 0x7e0e, 0x2c1a,
+ 0x7e0f, 0x2c20,
+ 0x7e10, 0x1328,
+ 0x7e11, 0x1321,
+ 0x7e12, 0x2c13,
+ 0x7e13, 0x2c19,
+ 0x7e14, 0x2c23,
+ 0x7e15, 0x2c1c,
+ 0x7e16, 0x2c21,
+ 0x7e17, 0x2c15,
+ 0x7e1a, 0x2c1d,
+ 0x7e1b, 0x1323,
+ 0x7e1c, 0x2c1b,
+ 0x7e1d, 0x1326,
+ 0x7e1e, 0x1325,
+ 0x7e1f, 0x2c17,
+ 0x7e21, 0x2c14,
+ 0x7e22, 0x2c1e,
+ 0x7e23, 0x1324,
+ 0x7e24, 0x2c25,
+ 0x7e25, 0x2c24,
+ 0x7e27, 0x377f,
+ 0x7e29, 0x2df8,
+ 0x7e2a, 0x2df4,
+ 0x7e2b, 0x143b,
+ 0x7e2d, 0x2dee,
+ 0x7e2e, 0x1435,
+ 0x7e2f, 0x1445,
+ 0x7e30, 0x2dfa,
+ 0x7e31, 0x143d,
+ 0x7e32, 0x1439,
+ 0x7e33, 0x2df1,
+ 0x7e34, 0x1440,
+ 0x7e35, 0x1443,
+ 0x7e36, 0x2dfc,
+ 0x7e37, 0x1438,
+ 0x7e38, 0x2df3,
+ 0x7e39, 0x1441,
+ 0x7e3a, 0x2dfe,
+ 0x7e3b, 0x2dfb,
+ 0x7e3c, 0x2def,
+ 0x7e3d, 0x143c,
+ 0x7e3e, 0x1436,
+ 0x7e3f, 0x1444,
+ 0x7e40, 0x2df6,
+ 0x7e41, 0x143f,
+ 0x7e42, 0x2df0,
+ 0x7e43, 0x143a,
+ 0x7e44, 0x2dfd,
+ 0x7e45, 0x143e,
+ 0x7e46, 0x1437,
+ 0x7e47, 0x2df7,
+ 0x7e48, 0x1442,
+ 0x7e49, 0x2df5,
+ 0x7e4c, 0x2df9,
+ 0x7e50, 0x2f83,
+ 0x7e51, 0x2f89,
+ 0x7e52, 0x1511,
+ 0x7e53, 0x2f8c,
+ 0x7e54, 0x150c,
+ 0x7e56, 0x2f84,
+ 0x7e57, 0x2f8b,
+ 0x7e58, 0x2f86,
+ 0x7e59, 0x1512,
+ 0x7e5a, 0x150f,
+ 0x7e5c, 0x2f82,
+ 0x7e5e, 0x150e,
+ 0x7e5f, 0x2f88,
+ 0x7e60, 0x2f8a,
+ 0x7e61, 0x1510,
+ 0x7e62, 0x2f87,
+ 0x7e63, 0x2f85,
+ 0x7e65, 0x46d2,
+ 0x7e67, 0x3766,
+ 0x7e68, 0x30e3,
+ 0x7e69, 0x15ac,
+ 0x7e6b, 0x15a9,
+ 0x7e6d, 0x15aa,
+ 0x7e6e, 0x377b,
+ 0x7e6f, 0x30df,
+ 0x7e70, 0x30dd,
+ 0x7e72, 0x30e1,
+ 0x7e73, 0x15ae,
+ 0x7e74, 0x30e2,
+ 0x7e75, 0x30db,
+ 0x7e76, 0x30da,
+ 0x7e77, 0x30de,
+ 0x7e78, 0x30dc,
+ 0x7e79, 0x15ab,
+ 0x7e7a, 0x30e0,
+ 0x7e7b, 0x3214,
+ 0x7e7c, 0x1631,
+ 0x7e7d, 0x1630,
+ 0x7e7e, 0x3215,
+ 0x7e7f, 0x3e51,
+ 0x7e80, 0x3217,
+ 0x7e81, 0x3216,
+ 0x7e82, 0x1632,
+ 0x7e86, 0x32f0,
+ 0x7e87, 0x32ed,
+ 0x7e8a, 0x32ec,
+ 0x7e8b, 0x32ef,
+ 0x7e8c, 0x1683,
+ 0x7e8d, 0x32f1,
+ 0x7e8e, 0x3ec9,
+ 0x7e8f, 0x1682,
+ 0x7e91, 0x33a2,
+ 0x7e92, 0x469e,
+ 0x7e93, 0x1703,
+ 0x7e94, 0x1705,
+ 0x7e95, 0x342c,
+ 0x7e96, 0x1704,
+ 0x7e97, 0x3494,
+ 0x7e98, 0x34da,
+ 0x7e99, 0x34dc,
+ 0x7e9a, 0x34d9,
+ 0x7e9b, 0x34db,
+ 0x7e9c, 0x1759,
+ 0x7e9f, 0x48bb,
+ 0x7ea4, 0x455b,
+ 0x7eac, 0x455c,
+ 0x7eba, 0x455d,
+ 0x7ec7, 0x455e,
+ 0x7ecf, 0x455f,
+ 0x7edf, 0x4560,
+ 0x7f06, 0x4561,
+ 0x7f36, 0x03f9,
+ 0x7f37, 0x4562,
+ 0x7f38, 0x07d4,
+ 0x7f39, 0x1d1f,
+ 0x7f3a, 0x0979,
+ 0x7f3d, 0x0b61,
+ 0x7f3e, 0x2271,
+ 0x7f40, 0x3780,
+ 0x7f43, 0x2c26,
+ 0x7f44, 0x1446,
+ 0x7f45, 0x2dff,
+ 0x7f47, 0x3782,
+ 0x7f48, 0x1513,
+ 0x7f49, 0x3e69,
+ 0x7f4a, 0x30e5,
+ 0x7f4b, 0x30e4,
+ 0x7f4c, 0x1633,
+ 0x7f4d, 0x32f2,
+ 0x7f4e, 0x3b4f,
+ 0x7f4f, 0x33a3,
+ 0x7f50, 0x1726,
+ 0x7f51, 0x1812,
+ 0x7f52, 0x44f6,
+ 0x7f53, 0x44f9,
+ 0x7f54, 0x0668,
+ 0x7f55, 0x04fc,
+ 0x7f58, 0x1bc3,
+ 0x7f5b, 0x1dad,
+ 0x7f5c, 0x1da8,
+ 0x7f5d, 0x1dac,
+ 0x7f5e, 0x1daa,
+ 0x7f5f, 0x097a,
+ 0x7f60, 0x1dab,
+ 0x7f61, 0x1da9,
+ 0x7f63, 0x1ff3,
+ 0x7f65, 0x2273,
+ 0x7f67, 0x2511,
+ 0x7f69, 0x0ec5,
+ 0x7f6b, 0x2510,
+ 0x7f6c, 0x2513,
+ 0x7f6d, 0x250f,
+ 0x7f6e, 0x0ec4,
+ 0x7f70, 0x106e,
+ 0x7f71, 0x4007,
+ 0x7f72, 0x0ec7,
+ 0x7f73, 0x2796,
+ 0x7f75, 0x11e5,
+ 0x7f76, 0x29c2,
+ 0x7f77, 0x11e6,
+ 0x7f78, 0x3f7b,
+ 0x7f79, 0x1329,
+ 0x7f7a, 0x2c29,
+ 0x7f7b, 0x2c27,
+ 0x7f7d, 0x2e02,
+ 0x7f7e, 0x2e01,
+ 0x7f7f, 0x2e00,
+ 0x7f83, 0x30e6,
+ 0x7f85, 0x15af,
+ 0x7f86, 0x30e7,
+ 0x7f87, 0x33a4,
+ 0x7f88, 0x1727,
+ 0x7f89, 0x3495,
+ 0x7f8a, 0x03fa,
+ 0x7f8b, 0x066a,
+ 0x7f8c, 0x0669,
+ 0x7f8d, 0x1bc5,
+ 0x7f8e, 0x07d5,
+ 0x7f8f, 0x421c,
+ 0x7f91, 0x1bc4,
+ 0x7f92, 0x1daf,
+ 0x7f93, 0x43db,
+ 0x7f94, 0x097b,
+ 0x7f95, 0x1ff4,
+ 0x7f96, 0x1dae,
+ 0x7f97, 0x3786,
+ 0x7f9a, 0x0b63,
+ 0x7f9b, 0x1ff7,
+ 0x7f9c, 0x1ff5,
+ 0x7f9e, 0x0b62,
+ 0x7fa0, 0x2276,
+ 0x7fa2, 0x2275,
+ 0x7fa3, 0x3788,
+ 0x7fa4, 0x0eca,
+ 0x7fa5, 0x2515,
+ 0x7fa6, 0x2514,
+ 0x7fa7, 0x2516,
+ 0x7fa8, 0x0ec9,
+ 0x7fa9, 0x0ec8,
+ 0x7fac, 0x29c3,
+ 0x7fad, 0x29c5,
+ 0x7fae, 0x43dc,
+ 0x7faf, 0x11e7,
+ 0x7fb0, 0x29c4,
+ 0x7fb1, 0x2c2a,
+ 0x7fb2, 0x132a,
+ 0x7fb3, 0x2f8e,
+ 0x7fb4, 0x4739,
+ 0x7fb5, 0x2f8d,
+ 0x7fb6, 0x15b0,
+ 0x7fb7, 0x30e8,
+ 0x7fb8, 0x15b2,
+ 0x7fb9, 0x15b1,
+ 0x7fba, 0x3218,
+ 0x7fbb, 0x32f3,
+ 0x7fbc, 0x1684,
+ 0x7fbd, 0x03fb,
+ 0x7fbe, 0x1bc6,
+ 0x7fbf, 0x07d6,
+ 0x7fc0, 0x1db2,
+ 0x7fc1, 0x097d,
+ 0x7fc2, 0x1db1,
+ 0x7fc3, 0x1db0,
+ 0x7fc5, 0x097c,
+ 0x7fc7, 0x1ffd,
+ 0x7fc9, 0x1fff,
+ 0x7fca, 0x1ff8,
+ 0x7fcc, 0x0b64,
+ 0x7fcd, 0x1ffa,
+ 0x7fce, 0x0b65,
+ 0x7fcf, 0x1ffe,
+ 0x7fd0, 0x1ffb,
+ 0x7fd2, 0x0b66,
+ 0x7fd4, 0x0d1c,
+ 0x7fd7, 0x2278,
+ 0x7fdb, 0x2517,
+ 0x7fdd, 0x3b5e,
+ 0x7fde, 0x279a,
+ 0x7fdf, 0x1071,
+ 0x7fe0, 0x106f,
+ 0x7fe2, 0x2797,
+ 0x7fe5, 0x2799,
+ 0x7fe6, 0x29ca,
+ 0x7fe7, 0x46e9,
+ 0x7fe8, 0x29cb,
+ 0x7fe9, 0x11e8,
+ 0x7fea, 0x29c8,
+ 0x7feb, 0x29c7,
+ 0x7fec, 0x29c9,
+ 0x7fed, 0x29c6,
+ 0x7fee, 0x132d,
+ 0x7fef, 0x2c2b,
+ 0x7ff0, 0x132b,
+ 0x7ff2, 0x2e04,
+ 0x7ff3, 0x1447,
+ 0x7ff4, 0x2e03,
+ 0x7ff5, 0x2eff,
+ 0x7ff7, 0x2f8f,
+ 0x7ff9, 0x1514,
+ 0x7ffa, 0x378e,
+ 0x7ffb, 0x1515,
+ 0x7ffc, 0x1448,
+ 0x7ffd, 0x30e9,
+ 0x7fff, 0x3219,
+ 0x8000, 0x1634,
+ 0x8001, 0x03fc,
+ 0x8002, 0x44fd,
+ 0x8003, 0x03fd,
+ 0x8004, 0x097f,
+ 0x8005, 0x066b,
+ 0x8006, 0x097e,
+ 0x8007, 0x1bc7,
+ 0x8008, 0x3791,
+ 0x800b, 0x0d1e,
+ 0x800c, 0x03fe,
+ 0x800d, 0x07d8,
+ 0x800e, 0x1bc8,
+ 0x8010, 0x07d7,
+ 0x8011, 0x07d9,
+ 0x8012, 0x03ff,
+ 0x8014, 0x1bca,
+ 0x8015, 0x0981,
+ 0x8016, 0x1db3,
+ 0x8017, 0x0983,
+ 0x8018, 0x0980,
+ 0x8019, 0x0982,
+ 0x801b, 0x2002,
+ 0x801c, 0x0b67,
+ 0x801d, 0x3792,
+ 0x801e, 0x2001,
+ 0x801f, 0x2000,
+ 0x8020, 0x473c,
+ 0x8021, 0x2519,
+ 0x8024, 0x279b,
+ 0x8025, 0x473d,
+ 0x8026, 0x11e9,
+ 0x8028, 0x132e,
+ 0x8029, 0x2c2d,
+ 0x802a, 0x2c2c,
+ 0x802c, 0x2e05,
+ 0x802e, 0x473e,
+ 0x802f, 0x3794,
+ 0x8030, 0x32f4,
+ 0x8031, 0x473f,
+ 0x8033, 0x0400,
+ 0x8034, 0x18d8,
+ 0x8035, 0x1a27,
+ 0x8036, 0x07da,
+ 0x8037, 0x1bcb,
+ 0x8039, 0x1db5,
+ 0x803b, 0x3797,
+ 0x803d, 0x0984,
+ 0x803e, 0x1db4,
+ 0x803f, 0x0985,
+ 0x8043, 0x2004,
+ 0x8046, 0x0b69,
+ 0x8047, 0x2003,
+ 0x8048, 0x2005,
+ 0x804a, 0x0b68,
+ 0x804f, 0x227a,
+ 0x8051, 0x2279,
+ 0x8052, 0x0d1f,
+ 0x8054, 0x4740,
+ 0x8056, 0x0ecb,
+ 0x8058, 0x0ecc,
+ 0x805a, 0x1073,
+ 0x805b, 0x3fe5,
+ 0x805c, 0x279d,
+ 0x805d, 0x279c,
+ 0x805e, 0x1072,
+ 0x8061, 0x3799,
+ 0x8062, 0x3fe3,
+ 0x8063, 0x3fdc,
+ 0x8064, 0x29cc,
+ 0x8066, 0x3fdb,
+ 0x8067, 0x29cd,
+ 0x806c, 0x2c2e,
+ 0x806f, 0x144c,
+ 0x8070, 0x144b,
+ 0x8071, 0x1449,
+ 0x8073, 0x144d,
+ 0x8075, 0x2f91,
+ 0x8076, 0x1517,
+ 0x8077, 0x1516,
+ 0x8078, 0x30eb,
+ 0x8079, 0x321a,
+ 0x807d, 0x16d3,
+ 0x807e, 0x16d2,
+ 0x807f, 0x0401,
+ 0x8080, 0x44fe,
+ 0x8082, 0x1cec,
+ 0x8084, 0x0ece,
+ 0x8085, 0x0d20,
+ 0x8086, 0x0ecd,
+ 0x8087, 0x1074,
+ 0x8089, 0x0402,
+ 0x808a, 0x17b3,
+ 0x808b, 0x0403,
+ 0x808f, 0x1a28,
+ 0x8090, 0x18db,
+ 0x8092, 0x18dc,
+ 0x8093, 0x04fe,
+ 0x8095, 0x18d9,
+ 0x8096, 0x04fd,
+ 0x8098, 0x0500,
+ 0x8099, 0x18da,
+ 0x809a, 0x0502,
+ 0x809b, 0x0501,
+ 0x809c, 0x18dd,
+ 0x809d, 0x04ff,
+ 0x809f, 0x4576,
+ 0x80a1, 0x0670,
+ 0x80a2, 0x066e,
+ 0x80a3, 0x1a2a,
+ 0x80a5, 0x066d,
+ 0x80a7, 0x37a0,
+ 0x80a9, 0x0672,
+ 0x80aa, 0x0674,
+ 0x80ab, 0x0671,
+ 0x80ad, 0x1a2d,
+ 0x80ae, 0x1a29,
+ 0x80af, 0x0675,
+ 0x80b1, 0x066f,
+ 0x80b2, 0x0503,
+ 0x80b4, 0x0673,
+ 0x80b5, 0x1a2c,
+ 0x80b6, 0x3eae,
+ 0x80b7, 0x4743,
+ 0x80b8, 0x1a2b,
+ 0x80ba, 0x066c,
+ 0x80bc, 0x4572,
+ 0x80bd, 0x3e7b,
+ 0x80c2, 0x1bd1,
+ 0x80c3, 0x07de,
+ 0x80c5, 0x1bd3,
+ 0x80c6, 0x3b74,
+ 0x80c7, 0x1bcd,
+ 0x80c8, 0x1bd0,
+ 0x80c9, 0x1bd9,
+ 0x80ca, 0x1bd7,
+ 0x80cc, 0x07e0,
+ 0x80cd, 0x1bdd,
+ 0x80ce, 0x07e3,
+ 0x80cf, 0x1bda,
+ 0x80d0, 0x1bd2,
+ 0x80d1, 0x1bcf,
+ 0x80d4, 0x227d,
+ 0x80d5, 0x1bd8,
+ 0x80d6, 0x07db,
+ 0x80d7, 0x1bdb,
+ 0x80d8, 0x1bcc,
+ 0x80d9, 0x1bd5,
+ 0x80da, 0x07dd,
+ 0x80db, 0x07e2,
+ 0x80dc, 0x1bd6,
+ 0x80dd, 0x07e6,
+ 0x80de, 0x07e4,
+ 0x80e0, 0x1bce,
+ 0x80e1, 0x07e1,
+ 0x80e3, 0x1bd4,
+ 0x80e4, 0x07e5,
+ 0x80e5, 0x07dc,
+ 0x80e6, 0x1bdc,
+ 0x80e9, 0x4744,
+ 0x80ec, 0x45e9,
+ 0x80ed, 0x098a,
+ 0x80ef, 0x0993,
+ 0x80f0, 0x0988,
+ 0x80f1, 0x0986,
+ 0x80f2, 0x1db7,
+ 0x80f3, 0x098e,
+ 0x80f4, 0x098b,
+ 0x80f5, 0x1db9,
+ 0x80f6, 0x4574,
+ 0x80f8, 0x098d,
+ 0x80f9, 0x1db8,
+ 0x80fa, 0x1db6,
+ 0x80fb, 0x1dbb,
+ 0x80fc, 0x0992,
+ 0x80fd, 0x0990,
+ 0x80fe, 0x227c,
+ 0x8100, 0x1dbc,
+ 0x8101, 0x1dba,
+ 0x8102, 0x0987,
+ 0x8103, 0x3fe7,
+ 0x8105, 0x0989,
+ 0x8106, 0x098c,
+ 0x8107, 0x37a2,
+ 0x8108, 0x098f,
+ 0x8109, 0x3b75,
+ 0x810a, 0x0991,
+ 0x810c, 0x4746,
+ 0x810e, 0x4747,
+ 0x8112, 0x4748,
+ 0x8114, 0x4749,
+ 0x8115, 0x200f,
+ 0x8116, 0x0b6b,
+ 0x8117, 0x3e6d,
+ 0x8118, 0x2006,
+ 0x8119, 0x2008,
+ 0x811a, 0x37a3,
+ 0x811b, 0x2009,
+ 0x811d, 0x2011,
+ 0x811e, 0x200d,
+ 0x811f, 0x200b,
+ 0x8121, 0x200e,
+ 0x8122, 0x2012,
+ 0x8123, 0x0b6c,
+ 0x8124, 0x0b70,
+ 0x8125, 0x2007,
+ 0x8127, 0x2010,
+ 0x8129, 0x0b6e,
+ 0x812a, 0x3a39,
+ 0x812b, 0x0b6d,
+ 0x812c, 0x200c,
+ 0x812d, 0x200a,
+ 0x812f, 0x0b6a,
+ 0x8130, 0x0b6f,
+ 0x8132, 0x3e79,
+ 0x8134, 0x45ec,
+ 0x8137, 0x3b72,
+ 0x8139, 0x0d26,
+ 0x813a, 0x2285,
+ 0x813d, 0x2283,
+ 0x813e, 0x0d28,
+ 0x8142, 0x3b76,
+ 0x8143, 0x227e,
+ 0x8144, 0x2527,
+ 0x8146, 0x0d27,
+ 0x8147, 0x2282,
+ 0x8148, 0x3e76,
+ 0x814a, 0x227f,
+ 0x814b, 0x0d23,
+ 0x814c, 0x0d29,
+ 0x814d, 0x2284,
+ 0x814e, 0x0d25,
+ 0x814f, 0x2281,
+ 0x8150, 0x1075,
+ 0x8151, 0x0d24,
+ 0x8152, 0x2280,
+ 0x8153, 0x0d2a,
+ 0x8154, 0x0d22,
+ 0x8155, 0x0d21,
+ 0x8156, 0x474c,
+ 0x8159, 0x474d,
+ 0x815b, 0x251f,
+ 0x815c, 0x251d,
+ 0x815e, 0x2523,
+ 0x8160, 0x251b,
+ 0x8161, 0x2528,
+ 0x8162, 0x2520,
+ 0x8164, 0x251a,
+ 0x8165, 0x0ed2,
+ 0x8166, 0x0ed8,
+ 0x8167, 0x2525,
+ 0x8169, 0x251e,
+ 0x816b, 0x0ed5,
+ 0x816d, 0x43c4,
+ 0x816e, 0x0ed3,
+ 0x816f, 0x2526,
+ 0x8170, 0x0ed0,
+ 0x8171, 0x0ecf,
+ 0x8172, 0x2521,
+ 0x8173, 0x0ed4,
+ 0x8174, 0x0d2b,
+ 0x8176, 0x2524,
+ 0x8177, 0x251c,
+ 0x8178, 0x0ed1,
+ 0x8179, 0x0ed6,
+ 0x817c, 0x4750,
+ 0x817f, 0x107a,
+ 0x8180, 0x1076,
+ 0x8182, 0x107b,
+ 0x8183, 0x27a0,
+ 0x8184, 0x43c5,
+ 0x8186, 0x279f,
+ 0x8187, 0x27a1,
+ 0x8188, 0x1078,
+ 0x8189, 0x279e,
+ 0x818a, 0x1079,
+ 0x818b, 0x27a4,
+ 0x818c, 0x27a3,
+ 0x818d, 0x27a2,
+ 0x818f, 0x1077,
+ 0x8193, 0x43c6,
+ 0x8195, 0x29d1,
+ 0x8197, 0x29d4,
+ 0x8198, 0x11ef,
+ 0x8199, 0x29d3,
+ 0x819a, 0x11ee,
+ 0x819b, 0x11ea,
+ 0x819e, 0x29d0,
+ 0x819f, 0x29cf,
+ 0x81a0, 0x11ed,
+ 0x81a2, 0x29d2,
+ 0x81a3, 0x29ce,
+ 0x81a5, 0x4753,
+ 0x81a6, 0x2c30,
+ 0x81a7, 0x2c3a,
+ 0x81a8, 0x1331,
+ 0x81a9, 0x1330,
+ 0x81aa, 0x4364,
+ 0x81ab, 0x2c34,
+ 0x81ac, 0x2c36,
+ 0x81ae, 0x2c31,
+ 0x81b0, 0x2c35,
+ 0x81b1, 0x2c2f,
+ 0x81b2, 0x2c38,
+ 0x81b3, 0x132f,
+ 0x81b4, 0x2c37,
+ 0x81b5, 0x2c33,
+ 0x81b6, 0x3eb2,
+ 0x81b7, 0x2c39,
+ 0x81b9, 0x2c32,
+ 0x81ba, 0x1450,
+ 0x81bb, 0x2e06,
+ 0x81bc, 0x2e0c,
+ 0x81bd, 0x1454,
+ 0x81be, 0x1456,
+ 0x81bf, 0x1453,
+ 0x81c0, 0x1452,
+ 0x81c1, 0x4755,
+ 0x81c2, 0x1451,
+ 0x81c3, 0x144f,
+ 0x81c4, 0x2e07,
+ 0x81c5, 0x2e0a,
+ 0x81c6, 0x144e,
+ 0x81c7, 0x2e0b,
+ 0x81c8, 0x3fee,
+ 0x81c9, 0x1455,
+ 0x81ca, 0x2e09,
+ 0x81cc, 0x2e08,
+ 0x81cd, 0x1518,
+ 0x81cf, 0x1519,
+ 0x81d0, 0x2f94,
+ 0x81d1, 0x2f92,
+ 0x81d5, 0x30ed,
+ 0x81d7, 0x30ec,
+ 0x81d8, 0x15b3,
+ 0x81d9, 0x321c,
+ 0x81da, 0x1635,
+ 0x81db, 0x321b,
+ 0x81dd, 0x32f5,
+ 0x81de, 0x33a5,
+ 0x81df, 0x16d4,
+ 0x81e0, 0x34dd,
+ 0x81e2, 0x1706,
+ 0x81e3, 0x0405,
+ 0x81e4, 0x4756,
+ 0x81e5, 0x0676,
+ 0x81e6, 0x2286,
+ 0x81e7, 0x107c,
+ 0x81e8, 0x1457,
+ 0x81e9, 0x2e0d,
+ 0x81ea, 0x0406,
+ 0x81ec, 0x0995,
+ 0x81ed, 0x0994,
+ 0x81ee, 0x2287,
+ 0x81ef, 0x42d1,
+ 0x81f2, 0x2c3b,
+ 0x81f3, 0x0407,
+ 0x81f4, 0x07e7,
+ 0x81f6, 0x3d61,
+ 0x81f7, 0x2288,
+ 0x81fa, 0x107d,
+ 0x81fb, 0x1332,
+ 0x81fc, 0x0408,
+ 0x81fe, 0x0677,
+ 0x81ff, 0x1bde,
+ 0x8200, 0x0996,
+ 0x8201, 0x1dbd,
+ 0x8202, 0x0b71,
+ 0x8204, 0x228b,
+ 0x8205, 0x0ed9,
+ 0x8207, 0x107e,
+ 0x8208, 0x1333,
+ 0x8209, 0x1458,
+ 0x820a, 0x151a,
+ 0x820b, 0x30ee,
+ 0x820c, 0x0409,
+ 0x820d, 0x0678,
+ 0x8210, 0x0997,
+ 0x8211, 0x2013,
+ 0x8212, 0x0d2c,
+ 0x8214, 0x107f,
+ 0x8215, 0x27a5,
+ 0x8216, 0x29d5,
+ 0x8218, 0x37aa,
+ 0x821a, 0x3fe1,
+ 0x821b, 0x040a,
+ 0x821c, 0x0d2d,
+ 0x821d, 0x2529,
+ 0x821e, 0x1080,
+ 0x821f, 0x040b,
+ 0x8220, 0x1a2e,
+ 0x8221, 0x1bdf,
+ 0x8222, 0x07e8,
+ 0x8225, 0x1dbf,
+ 0x8226, 0x420d,
+ 0x8228, 0x099a,
+ 0x8229, 0x37b0,
+ 0x822a, 0x0998,
+ 0x822c, 0x099b,
+ 0x822d, 0x3ed0,
+ 0x822f, 0x1dbe,
+ 0x8232, 0x2018,
+ 0x8233, 0x2015,
+ 0x8234, 0x2017,
+ 0x8235, 0x0b72,
+ 0x8236, 0x0b74,
+ 0x8237, 0x0b73,
+ 0x8238, 0x2014,
+ 0x8239, 0x0b75,
+ 0x823a, 0x2016,
+ 0x823c, 0x228c,
+ 0x823e, 0x4582,
+ 0x823f, 0x228e,
+ 0x8240, 0x252c,
+ 0x8242, 0x252d,
+ 0x8244, 0x252b,
+ 0x8245, 0x252e,
+ 0x8247, 0x0eda,
+ 0x8249, 0x252a,
+ 0x824b, 0x1081,
+ 0x824e, 0x29da,
+ 0x824f, 0x29d6,
+ 0x8250, 0x29d9,
+ 0x8251, 0x29db,
+ 0x8252, 0x29d8,
+ 0x8253, 0x29d7,
+ 0x8254, 0x4757,
+ 0x8255, 0x2c3c,
+ 0x8258, 0x1334,
+ 0x825a, 0x2e0f,
+ 0x825b, 0x2e0e,
+ 0x825c, 0x2e10,
+ 0x825e, 0x2f96,
+ 0x825f, 0x2f95,
+ 0x8261, 0x30f0,
+ 0x8262, 0x3b7a,
+ 0x8263, 0x30f1,
+ 0x8264, 0x30ef,
+ 0x8265, 0x3b7b,
+ 0x8266, 0x1636,
+ 0x8268, 0x321d,
+ 0x826b, 0x33a6,
+ 0x826c, 0x342d,
+ 0x826d, 0x3496,
+ 0x826e, 0x040c,
+ 0x826f, 0x0504,
+ 0x8271, 0x1459,
+ 0x8272, 0x040d,
+ 0x8274, 0x2019,
+ 0x8275, 0x228f,
+ 0x8276, 0x4759,
+ 0x8277, 0x172e,
+ 0x8278, 0x1813,
+ 0x8279, 0x4722,
+ 0x827a, 0x4563,
+ 0x827b, 0x37c8,
+ 0x827c, 0x1814,
+ 0x827d, 0x1816,
+ 0x827e, 0x040e,
+ 0x827f, 0x1817,
+ 0x8280, 0x1815,
+ 0x8283, 0x18e5,
+ 0x8285, 0x18e0,
+ 0x8287, 0x4132,
+ 0x828a, 0x18e4,
+ 0x828b, 0x0506,
+ 0x828d, 0x0507,
+ 0x828e, 0x18e1,
+ 0x828f, 0x18df,
+ 0x8290, 0x18de,
+ 0x8291, 0x18e2,
+ 0x8292, 0x0505,
+ 0x8293, 0x18e3,
+ 0x8294, 0x1be0,
+ 0x8298, 0x1a33,
+ 0x8299, 0x067b,
+ 0x829a, 0x1a32,
+ 0x829b, 0x1a34,
+ 0x829d, 0x067a,
+ 0x829e, 0x1a39,
+ 0x829f, 0x067e,
+ 0x82a0, 0x1a2f,
+ 0x82a1, 0x1a3d,
+ 0x82a2, 0x1a43,
+ 0x82a3, 0x0685,
+ 0x82a4, 0x1a40,
+ 0x82a5, 0x0682,
+ 0x82a6, 0x3d73,
+ 0x82a7, 0x1a36,
+ 0x82a8, 0x1a3c,
+ 0x82a9, 0x1a3e,
+ 0x82aa, 0x37bc,
+ 0x82ab, 0x1a31,
+ 0x82ac, 0x0681,
+ 0x82ad, 0x067c,
+ 0x82ae, 0x1a37,
+ 0x82af, 0x0683,
+ 0x82b0, 0x0686,
+ 0x82b1, 0x0680,
+ 0x82b3, 0x0679,
+ 0x82b4, 0x1a3b,
+ 0x82b5, 0x1a35,
+ 0x82b6, 0x1a42,
+ 0x82b7, 0x0688,
+ 0x82b8, 0x0684,
+ 0x82b9, 0x067f,
+ 0x82ba, 0x1a3a,
+ 0x82bb, 0x099c,
+ 0x82bc, 0x1a38,
+ 0x82bd, 0x067d,
+ 0x82be, 0x0687,
+ 0x82c0, 0x1a30,
+ 0x82c2, 0x1a3f,
+ 0x82c3, 0x1a41,
+ 0x82c4, 0x45e3,
+ 0x82ca, 0x475a,
+ 0x82cf, 0x4564,
+ 0x82d0, 0x37c1,
+ 0x82d1, 0x07f9,
+ 0x82d2, 0x07f3,
+ 0x82d3, 0x07fb,
+ 0x82d4, 0x07f8,
+ 0x82d5, 0x1be7,
+ 0x82d6, 0x1bea,
+ 0x82d7, 0x07f4,
+ 0x82d8, 0x475b,
+ 0x82d9, 0x1be1,
+ 0x82db, 0x07ed,
+ 0x82dc, 0x07f7,
+ 0x82de, 0x07fa,
+ 0x82df, 0x07fc,
+ 0x82e0, 0x1bf6,
+ 0x82e1, 0x1bed,
+ 0x82e2, 0x37c9,
+ 0x82e3, 0x07ec,
+ 0x82e4, 0x1bf5,
+ 0x82e5, 0x07f0,
+ 0x82e6, 0x07ee,
+ 0x82e7, 0x07e9,
+ 0x82e8, 0x1be5,
+ 0x82ea, 0x1bf4,
+ 0x82eb, 0x1be9,
+ 0x82ec, 0x1bec,
+ 0x82ed, 0x1bf9,
+ 0x82ee, 0x4018,
+ 0x82ef, 0x07fd,
+ 0x82f0, 0x1bf3,
+ 0x82f1, 0x07f5,
+ 0x82f2, 0x1bee,
+ 0x82f3, 0x1bf8,
+ 0x82f4, 0x1beb,
+ 0x82f5, 0x1bef,
+ 0x82f6, 0x1bf2,
+ 0x82f7, 0x3e77,
+ 0x82f9, 0x1be3,
+ 0x82fa, 0x1bf7,
+ 0x82fb, 0x1bf1,
+ 0x82fc, 0x412d,
+ 0x82fd, 0x3d92,
+ 0x82fe, 0x1be2,
+ 0x82ff, 0x43de,
+ 0x8300, 0x1be6,
+ 0x8301, 0x07f6,
+ 0x8302, 0x07f1,
+ 0x8303, 0x07ea,
+ 0x8304, 0x07ef,
+ 0x8305, 0x07eb,
+ 0x8306, 0x07fe,
+ 0x8307, 0x1be4,
+ 0x8308, 0x1dd0,
+ 0x8309, 0x07f2,
+ 0x830b, 0x3eb6,
+ 0x830c, 0x1bf0,
+ 0x830d, 0x1a7d,
+ 0x8316, 0x1dd3,
+ 0x8317, 0x09aa,
+ 0x8318, 0x37ca,
+ 0x8319, 0x1dc3,
+ 0x831a, 0x37c2,
+ 0x831b, 0x1dce,
+ 0x831c, 0x1dca,
+ 0x831d, 0x37d1,
+ 0x831e, 0x1ddd,
+ 0x8320, 0x1dd5,
+ 0x8322, 0x1dcb,
+ 0x8324, 0x1dd4,
+ 0x8325, 0x1dc5,
+ 0x8326, 0x1dc9,
+ 0x8327, 0x1de0,
+ 0x8328, 0x09ad,
+ 0x8329, 0x1dd8,
+ 0x832a, 0x1dcf,
+ 0x832b, 0x099d,
+ 0x832c, 0x1dde,
+ 0x832d, 0x1dc1,
+ 0x832f, 0x1dd7,
+ 0x8331, 0x09ac,
+ 0x8332, 0x09a7,
+ 0x8333, 0x1dc0,
+ 0x8334, 0x09a5,
+ 0x8335, 0x09a4,
+ 0x8336, 0x09a9,
+ 0x8337, 0x1dd6,
+ 0x8338, 0x09a1,
+ 0x8339, 0x09a8,
+ 0x833a, 0x1be8,
+ 0x833b, 0x2290,
+ 0x833c, 0x1dd1,
+ 0x833d, 0x3d2a,
+ 0x833f, 0x1dc7,
+ 0x8340, 0x09ab,
+ 0x8341, 0x1dc8,
+ 0x8342, 0x1dcc,
+ 0x8343, 0x09ae,
+ 0x8344, 0x1dc2,
+ 0x8345, 0x1dda,
+ 0x8347, 0x1dd9,
+ 0x8348, 0x1de1,
+ 0x8349, 0x09a3,
+ 0x834a, 0x09a0,
+ 0x834b, 0x1ddf,
+ 0x834c, 0x1ddb,
+ 0x834d, 0x1dd2,
+ 0x834e, 0x1dcd,
+ 0x834f, 0x09a6,
+ 0x8350, 0x09a2,
+ 0x8351, 0x1dc4,
+ 0x8352, 0x099e,
+ 0x8353, 0x1ddc,
+ 0x8354, 0x099f,
+ 0x8356, 0x1dc6,
+ 0x8357, 0x475d,
+ 0x8362, 0x37b6,
+ 0x8363, 0x41eb,
+ 0x8366, 0x3e1e,
+ 0x836f, 0x4565,
+ 0x8373, 0x201f,
+ 0x8374, 0x2021,
+ 0x8375, 0x2026,
+ 0x8376, 0x203a,
+ 0x8377, 0x0b83,
+ 0x8378, 0x0b79,
+ 0x837a, 0x201e,
+ 0x837b, 0x0b84,
+ 0x837d, 0x2029,
+ 0x837e, 0x2030,
+ 0x837f, 0x2036,
+ 0x8381, 0x2023,
+ 0x8383, 0x202a,
+ 0x8385, 0x37d3,
+ 0x8386, 0x0b86,
+ 0x8387, 0x2038,
+ 0x8388, 0x2033,
+ 0x8389, 0x0b81,
+ 0x838a, 0x0b7f,
+ 0x838b, 0x202f,
+ 0x838c, 0x202b,
+ 0x838d, 0x201d,
+ 0x838e, 0x0b76,
+ 0x838f, 0x2022,
+ 0x8390, 0x201a,
+ 0x8391, 0x37ec,
+ 0x8392, 0x0b7e,
+ 0x8393, 0x0b80,
+ 0x8394, 0x2027,
+ 0x8395, 0x2024,
+ 0x8396, 0x0b7b,
+ 0x8397, 0x2034,
+ 0x8398, 0x0b78,
+ 0x8399, 0x2025,
+ 0x839a, 0x22b9,
+ 0x839b, 0x202d,
+ 0x839c, 0x374d,
+ 0x839d, 0x202c,
+ 0x839e, 0x0b77,
+ 0x83a0, 0x0b82,
+ 0x83a2, 0x0b7a,
+ 0x83a3, 0x201b,
+ 0x83a4, 0x2020,
+ 0x83a5, 0x2031,
+ 0x83a6, 0x2037,
+ 0x83a7, 0x0b87,
+ 0x83a8, 0x201c,
+ 0x83a9, 0x2028,
+ 0x83aa, 0x202e,
+ 0x83ab, 0x0b7d,
+ 0x83ac, 0x37d6,
+ 0x83ae, 0x2039,
+ 0x83af, 0x2032,
+ 0x83b0, 0x2035,
+ 0x83b9, 0x42a7,
+ 0x83bd, 0x0b7c,
+ 0x83be, 0x3f59,
+ 0x83bf, 0x22a0,
+ 0x83c0, 0x2294,
+ 0x83c1, 0x0d35,
+ 0x83c2, 0x22b1,
+ 0x83c3, 0x22ba,
+ 0x83c4, 0x22bd,
+ 0x83c5, 0x0d33,
+ 0x83c6, 0x229c,
+ 0x83c7, 0x22b5,
+ 0x83c8, 0x229d,
+ 0x83c9, 0x22ab,
+ 0x83ca, 0x0d40,
+ 0x83cb, 0x22a7,
+ 0x83cc, 0x0d3d,
+ 0x83cd, 0x4055,
+ 0x83ce, 0x22a8,
+ 0x83cf, 0x2291,
+ 0x83d1, 0x22b6,
+ 0x83d3, 0x37d8,
+ 0x83d4, 0x0d46,
+ 0x83d5, 0x22b3,
+ 0x83d6, 0x22a9,
+ 0x83d7, 0x22bf,
+ 0x83d8, 0x22a4,
+ 0x83d9, 0x254e,
+ 0x83db, 0x22c2,
+ 0x83dc, 0x0d44,
+ 0x83dd, 0x22a2,
+ 0x83de, 0x22ae,
+ 0x83df, 0x0d47,
+ 0x83e0, 0x0d32,
+ 0x83e1, 0x22a6,
+ 0x83e2, 0x22c0,
+ 0x83e3, 0x229f,
+ 0x83e4, 0x2298,
+ 0x83e5, 0x22a3,
+ 0x83e7, 0x2297,
+ 0x83e8, 0x2295,
+ 0x83e9, 0x0d2e,
+ 0x83ea, 0x22b7,
+ 0x83eb, 0x229e,
+ 0x83ec, 0x22bb,
+ 0x83ed, 0x3d2c,
+ 0x83ee, 0x22bc,
+ 0x83ef, 0x0d36,
+ 0x83f0, 0x0d3b,
+ 0x83f1, 0x0d37,
+ 0x83f2, 0x0d3f,
+ 0x83f3, 0x22b2,
+ 0x83f4, 0x0d38,
+ 0x83f5, 0x22aa,
+ 0x83f6, 0x229a,
+ 0x83f8, 0x0d30,
+ 0x83f9, 0x2292,
+ 0x83fa, 0x22b4,
+ 0x83fb, 0x22be,
+ 0x83fc, 0x2299,
+ 0x83fd, 0x0d3e,
+ 0x83fe, 0x22c3,
+ 0x83ff, 0x22a5,
+ 0x8401, 0x22a1,
+ 0x8403, 0x0d2f,
+ 0x8404, 0x0d43,
+ 0x8405, 0x475f,
+ 0x8406, 0x22b0,
+ 0x8407, 0x0d45,
+ 0x8409, 0x22ac,
+ 0x840a, 0x0d3a,
+ 0x840b, 0x0d34,
+ 0x840c, 0x0d3c,
+ 0x840d, 0x0d31,
+ 0x840e, 0x0d42,
+ 0x840f, 0x22ad,
+ 0x8410, 0x229b,
+ 0x8411, 0x22af,
+ 0x8412, 0x2296,
+ 0x8413, 0x22b8,
+ 0x8414, 0x3c10,
+ 0x8416, 0x4037,
+ 0x8418, 0x3e7a,
+ 0x841b, 0x22c1,
+ 0x841c, 0x3eb3,
+ 0x8420, 0x3c55,
+ 0x8421, 0x3751,
+ 0x8423, 0x2293,
+ 0x8424, 0x4951,
+ 0x8426, 0x46d8,
+ 0x8429, 0x254d,
+ 0x842b, 0x2563,
+ 0x842c, 0x0eac,
+ 0x842d, 0x2552,
+ 0x842e, 0x422d,
+ 0x842f, 0x2550,
+ 0x8430, 0x253b,
+ 0x8431, 0x0ede,
+ 0x8432, 0x254b,
+ 0x8433, 0x255f,
+ 0x8434, 0x2547,
+ 0x8435, 0x0ee6,
+ 0x8436, 0x255e,
+ 0x8437, 0x2545,
+ 0x8438, 0x0d41,
+ 0x8439, 0x2555,
+ 0x843a, 0x2546,
+ 0x843b, 0x255c,
+ 0x843c, 0x0ee5,
+ 0x843d, 0x0edd,
+ 0x843e, 0x3d21,
+ 0x843f, 0x2530,
+ 0x8440, 0x2538,
+ 0x8442, 0x2551,
+ 0x8443, 0x2549,
+ 0x8444, 0x2562,
+ 0x8445, 0x254c,
+ 0x8446, 0x0eeb,
+ 0x8447, 0x255d,
+ 0x8448, 0x4718,
+ 0x8449, 0x0ee2,
+ 0x844a, 0x37e4,
+ 0x844b, 0x254f,
+ 0x844c, 0x2557,
+ 0x844d, 0x253c,
+ 0x844e, 0x2556,
+ 0x8450, 0x2567,
+ 0x8451, 0x2537,
+ 0x8452, 0x2558,
+ 0x8453, 0x3b7d,
+ 0x8454, 0x2565,
+ 0x8455, 0x398b,
+ 0x8456, 0x2531,
+ 0x8457, 0x0d39,
+ 0x8458, 0x37de,
+ 0x8459, 0x253f,
+ 0x845a, 0x253e,
+ 0x845b, 0x0ee4,
+ 0x845c, 0x3edb,
+ 0x845d, 0x2542,
+ 0x845e, 0x2544,
+ 0x845f, 0x2553,
+ 0x8460, 0x2564,
+ 0x8461, 0x0ee7,
+ 0x8462, 0x42da,
+ 0x8463, 0x0ee8,
+ 0x8464, 0x4761,
+ 0x8465, 0x2536,
+ 0x8466, 0x0ee0,
+ 0x8467, 0x253a,
+ 0x8468, 0x2560,
+ 0x8469, 0x0ee9,
+ 0x846b, 0x0ee1,
+ 0x846c, 0x0ee3,
+ 0x846d, 0x0eea,
+ 0x846e, 0x2566,
+ 0x846f, 0x2559,
+ 0x8470, 0x2554,
+ 0x8471, 0x37e0,
+ 0x8472, 0x3c93,
+ 0x8473, 0x2541,
+ 0x8474, 0x2540,
+ 0x8475, 0x0edf,
+ 0x8476, 0x2532,
+ 0x8477, 0x0edc,
+ 0x8478, 0x254a,
+ 0x8479, 0x2533,
+ 0x847a, 0x2548,
+ 0x847d, 0x253d,
+ 0x847e, 0x2561,
+ 0x847f, 0x394e,
+ 0x8480, 0x3b6e,
+ 0x8482, 0x0edb,
+ 0x8486, 0x2539,
+ 0x8488, 0x4762,
+ 0x848d, 0x2535,
+ 0x848e, 0x255b,
+ 0x848f, 0x2534,
+ 0x8490, 0x108e,
+ 0x8491, 0x27cd,
+ 0x8492, 0x3756,
+ 0x8493, 0x37ee,
+ 0x8494, 0x27bc,
+ 0x8496, 0x3b1d,
+ 0x8497, 0x27a6,
+ 0x8498, 0x27c4,
+ 0x8499, 0x1086,
+ 0x849a, 0x27b5,
+ 0x849b, 0x27bf,
+ 0x849c, 0x1089,
+ 0x849d, 0x27b8,
+ 0x849e, 0x1087,
+ 0x849f, 0x27a9,
+ 0x84a0, 0x27c7,
+ 0x84a1, 0x27a8,
+ 0x84a2, 0x27bb,
+ 0x84a3, 0x3b9e,
+ 0x84a4, 0x27a7,
+ 0x84a7, 0x27b9,
+ 0x84a8, 0x27c2,
+ 0x84a9, 0x27c0,
+ 0x84aa, 0x27b4,
+ 0x84ab, 0x27af,
+ 0x84ac, 0x27ad,
+ 0x84ad, 0x3d8c,
+ 0x84ae, 0x27ae,
+ 0x84af, 0x27c1,
+ 0x84b0, 0x27cc,
+ 0x84b1, 0x27b6,
+ 0x84b2, 0x1088,
+ 0x84b4, 0x27b1,
+ 0x84b6, 0x27c5,
+ 0x84b8, 0x108b,
+ 0x84b9, 0x27b0,
+ 0x84ba, 0x27aa,
+ 0x84bb, 0x27ba,
+ 0x84bc, 0x108f,
+ 0x84bd, 0x3c4c,
+ 0x84be, 0x4764,
+ 0x84bf, 0x1083,
+ 0x84c0, 0x108c,
+ 0x84c1, 0x27b2,
+ 0x84c2, 0x27ac,
+ 0x84c4, 0x1085,
+ 0x84c5, 0x255a,
+ 0x84c6, 0x1084,
+ 0x84c7, 0x27bd,
+ 0x84c9, 0x1082,
+ 0x84ca, 0x1091,
+ 0x84cb, 0x108a,
+ 0x84cc, 0x27be,
+ 0x84cd, 0x27b3,
+ 0x84ce, 0x27ab,
+ 0x84cf, 0x27c6,
+ 0x84d0, 0x27b7,
+ 0x84d1, 0x1090,
+ 0x84d2, 0x27ca,
+ 0x84d3, 0x108d,
+ 0x84d4, 0x27c9,
+ 0x84d6, 0x27c3,
+ 0x84d7, 0x27c8,
+ 0x84da, 0x3ff5,
+ 0x84db, 0x27cb,
+ 0x84de, 0x37ea,
+ 0x84e1, 0x4765,
+ 0x84e2, 0x37b5,
+ 0x84e4, 0x37ef,
+ 0x84e5, 0x3bd0,
+ 0x84e7, 0x2a03,
+ 0x84e9, 0x29f7,
+ 0x84ea, 0x29f6,
+ 0x84eb, 0x29f2,
+ 0x84ec, 0x11fb,
+ 0x84ee, 0x11f3,
+ 0x84ef, 0x2a06,
+ 0x84f0, 0x2a05,
+ 0x84f1, 0x252f,
+ 0x84f2, 0x29ef,
+ 0x84f3, 0x29f3,
+ 0x84f4, 0x29ed,
+ 0x84f6, 0x2a00,
+ 0x84f7, 0x29f1,
+ 0x84f8, 0x4766,
+ 0x84f9, 0x2a07,
+ 0x84fa, 0x29ea,
+ 0x84fb, 0x29e8,
+ 0x84fc, 0x29f4,
+ 0x84fd, 0x29fe,
+ 0x84fe, 0x29f9,
+ 0x84ff, 0x11fd,
+ 0x8500, 0x29df,
+ 0x8502, 0x29fd,
+ 0x8503, 0x398a,
+ 0x8505, 0x40eb,
+ 0x8506, 0x11fe,
+ 0x8507, 0x2543,
+ 0x8508, 0x29eb,
+ 0x8509, 0x29e2,
+ 0x850a, 0x29e5,
+ 0x850b, 0x2a0b,
+ 0x850c, 0x29ec,
+ 0x850d, 0x29e3,
+ 0x850e, 0x29e1,
+ 0x850f, 0x29de,
+ 0x8510, 0x4767,
+ 0x8511, 0x11f7,
+ 0x8512, 0x29f5,
+ 0x8513, 0x11f6,
+ 0x8514, 0x11fa,
+ 0x8515, 0x29f0,
+ 0x8516, 0x29f8,
+ 0x8517, 0x11f0,
+ 0x8518, 0x2a08,
+ 0x8519, 0x2a0c,
+ 0x851a, 0x11f2,
+ 0x851c, 0x29e7,
+ 0x851d, 0x29fb,
+ 0x851e, 0x29ff,
+ 0x851f, 0x29e4,
+ 0x8520, 0x2a09,
+ 0x8521, 0x11f9,
+ 0x8523, 0x11f8,
+ 0x8524, 0x29dc,
+ 0x8525, 0x11fc,
+ 0x8526, 0x2a02,
+ 0x8527, 0x29e6,
+ 0x8528, 0x29fa,
+ 0x8529, 0x29e0,
+ 0x852a, 0x29ee,
+ 0x852b, 0x29e9,
+ 0x852c, 0x11f4,
+ 0x852e, 0x29fc,
+ 0x852f, 0x2a0d,
+ 0x8530, 0x2a0a,
+ 0x8531, 0x2a01,
+ 0x8533, 0x4228,
+ 0x8534, 0x37f4,
+ 0x8538, 0x4768,
+ 0x853b, 0x29dd,
+ 0x853d, 0x11f1,
+ 0x853e, 0x2c4f,
+ 0x8540, 0x2c46,
+ 0x8541, 0x2c49,
+ 0x8542, 0x4062,
+ 0x8543, 0x133b,
+ 0x8544, 0x2c4b,
+ 0x8545, 0x2c40,
+ 0x8546, 0x2c47,
+ 0x8547, 0x2c4d,
+ 0x8548, 0x1338,
+ 0x8549, 0x133c,
+ 0x854a, 0x1336,
+ 0x854b, 0x37c0,
+ 0x854c, 0x400f,
+ 0x854d, 0x2c42,
+ 0x854e, 0x2c52,
+ 0x8551, 0x2c4c,
+ 0x8552, 0x4769,
+ 0x8553, 0x2c43,
+ 0x8554, 0x2c5b,
+ 0x8555, 0x2c55,
+ 0x8556, 0x2c3f,
+ 0x8557, 0x2e23,
+ 0x8558, 0x2c45,
+ 0x8559, 0x1337,
+ 0x855a, 0x37db,
+ 0x855b, 0x2c50,
+ 0x855d, 0x2c5a,
+ 0x855e, 0x133f,
+ 0x8560, 0x2c57,
+ 0x8561, 0x2c44,
+ 0x8562, 0x2c4a,
+ 0x8563, 0x2c4e,
+ 0x8564, 0x2c48,
+ 0x8565, 0x2c5c,
+ 0x8566, 0x2c59,
+ 0x8567, 0x2c56,
+ 0x8568, 0x1339,
+ 0x856a, 0x133e,
+ 0x856b, 0x2c41,
+ 0x856c, 0x2c5d,
+ 0x856d, 0x133d,
+ 0x856e, 0x2c53,
+ 0x856f, 0x476b,
+ 0x8571, 0x2c51,
+ 0x8573, 0x37f8,
+ 0x8575, 0x2c54,
+ 0x8576, 0x2e30,
+ 0x8577, 0x2e1d,
+ 0x8578, 0x2e22,
+ 0x8579, 0x2e2f,
+ 0x857a, 0x2e21,
+ 0x857b, 0x2e19,
+ 0x857c, 0x2e1e,
+ 0x857e, 0x145c,
+ 0x8580, 0x2e12,
+ 0x8581, 0x2e2a,
+ 0x8582, 0x2e2c,
+ 0x8583, 0x2e11,
+ 0x8584, 0x145b,
+ 0x8585, 0x2e2e,
+ 0x8586, 0x2e26,
+ 0x8587, 0x1462,
+ 0x8588, 0x2e2d,
+ 0x8589, 0x2e1f,
+ 0x858a, 0x1464,
+ 0x858b, 0x2e17,
+ 0x858c, 0x2c58,
+ 0x858d, 0x2e27,
+ 0x858e, 0x2e24,
+ 0x858f, 0x2e13,
+ 0x8590, 0x2e32,
+ 0x8591, 0x145e,
+ 0x8594, 0x145f,
+ 0x8595, 0x2e15,
+ 0x8596, 0x2e25,
+ 0x8598, 0x2e31,
+ 0x8599, 0x2e28,
+ 0x859a, 0x2e1b,
+ 0x859b, 0x1461,
+ 0x859c, 0x145d,
+ 0x859d, 0x2e29,
+ 0x859e, 0x2e1c,
+ 0x859f, 0x2e33,
+ 0x85a0, 0x2e16,
+ 0x85a1, 0x2e20,
+ 0x85a2, 0x2e2b,
+ 0x85a3, 0x2e18,
+ 0x85a4, 0x2e1a,
+ 0x85a6, 0x1465,
+ 0x85a7, 0x2e14,
+ 0x85a8, 0x1463,
+ 0x85a9, 0x151c,
+ 0x85aa, 0x145a,
+ 0x85af, 0x1460,
+ 0x85b0, 0x1520,
+ 0x85b1, 0x2fa6,
+ 0x85b3, 0x2f9c,
+ 0x85b4, 0x2f97,
+ 0x85b5, 0x2f9d,
+ 0x85b6, 0x2fa7,
+ 0x85b7, 0x2fab,
+ 0x85b8, 0x2faa,
+ 0x85b9, 0x1522,
+ 0x85ba, 0x1521,
+ 0x85bd, 0x2f9e,
+ 0x85be, 0x2fac,
+ 0x85bf, 0x2fa1,
+ 0x85c0, 0x2f99,
+ 0x85c1, 0x37fe,
+ 0x85c2, 0x2f9b,
+ 0x85c3, 0x2f9a,
+ 0x85c4, 0x2fa0,
+ 0x85c5, 0x2fa5,
+ 0x85c6, 0x2f98,
+ 0x85c7, 0x2f9f,
+ 0x85c8, 0x2fa4,
+ 0x85c9, 0x151f,
+ 0x85cb, 0x2fa2,
+ 0x85cd, 0x151d,
+ 0x85ce, 0x2fa3,
+ 0x85cf, 0x151b,
+ 0x85d0, 0x151e,
+ 0x85d1, 0x3101,
+ 0x85d2, 0x2fa8,
+ 0x85d5, 0x15b7,
+ 0x85d7, 0x30f9,
+ 0x85d8, 0x30fd,
+ 0x85d9, 0x30f5,
+ 0x85da, 0x30f8,
+ 0x85dc, 0x3100,
+ 0x85dd, 0x15b5,
+ 0x85de, 0x3105,
+ 0x85df, 0x30fe,
+ 0x85e0, 0x476d,
+ 0x85e1, 0x30f6,
+ 0x85e2, 0x3106,
+ 0x85e3, 0x30ff,
+ 0x85e4, 0x15b8,
+ 0x85e6, 0x3103,
+ 0x85e8, 0x30f7,
+ 0x85e9, 0x15b4,
+ 0x85ea, 0x15b6,
+ 0x85eb, 0x30f2,
+ 0x85ec, 0x30fa,
+ 0x85ed, 0x30f4,
+ 0x85ee, 0x3c56,
+ 0x85ef, 0x3104,
+ 0x85f0, 0x3102,
+ 0x85f1, 0x30f3,
+ 0x85f2, 0x30fb,
+ 0x85f6, 0x3225,
+ 0x85f7, 0x15ba,
+ 0x85f8, 0x30fc,
+ 0x85f9, 0x1638,
+ 0x85fa, 0x163a,
+ 0x85fb, 0x1637,
+ 0x85fc, 0x3c50,
+ 0x85fd, 0x322a,
+ 0x85fe, 0x3222,
+ 0x85ff, 0x3220,
+ 0x8600, 0x3224,
+ 0x8601, 0x3221,
+ 0x8602, 0x3800,
+ 0x8604, 0x3226,
+ 0x8605, 0x3228,
+ 0x8606, 0x163b,
+ 0x8607, 0x163d,
+ 0x8609, 0x3227,
+ 0x860a, 0x163e,
+ 0x860b, 0x163c,
+ 0x860c, 0x3229,
+ 0x860d, 0x4064,
+ 0x8610, 0x3b7f,
+ 0x8611, 0x1639,
+ 0x8614, 0x46be,
+ 0x8616, 0x37fb,
+ 0x8617, 0x1685,
+ 0x8618, 0x32f6,
+ 0x8619, 0x32fc,
+ 0x861a, 0x1687,
+ 0x861b, 0x3223,
+ 0x861c, 0x32fb,
+ 0x861e, 0x3302,
+ 0x861f, 0x32f9,
+ 0x8620, 0x3300,
+ 0x8621, 0x32ff,
+ 0x8622, 0x321f,
+ 0x8623, 0x32fa,
+ 0x8624, 0x2fa9,
+ 0x8625, 0x3303,
+ 0x8626, 0x32f8,
+ 0x8627, 0x32fd,
+ 0x8628, 0x3805,
+ 0x8629, 0x3301,
+ 0x862a, 0x32f7,
+ 0x862c, 0x33aa,
+ 0x862d, 0x1686,
+ 0x862e, 0x32fe,
+ 0x862f, 0x3f9e,
+ 0x8631, 0x3432,
+ 0x8632, 0x33ab,
+ 0x8633, 0x33a9,
+ 0x8634, 0x33a7,
+ 0x8636, 0x33ac,
+ 0x8638, 0x1707,
+ 0x8639, 0x3430,
+ 0x863a, 0x342e,
+ 0x863b, 0x3433,
+ 0x863c, 0x3431,
+ 0x863e, 0x3434,
+ 0x863f, 0x1708,
+ 0x8640, 0x342f,
+ 0x8642, 0x38c1,
+ 0x8643, 0x3497,
+ 0x8645, 0x3b66,
+ 0x8646, 0x34df,
+ 0x864b, 0x353e,
+ 0x864c, 0x3536,
+ 0x864d, 0x1818,
+ 0x864e, 0x0689,
+ 0x8650, 0x07ff,
+ 0x8652, 0x1de3,
+ 0x8653, 0x1de2,
+ 0x8654, 0x09af,
+ 0x8655, 0x0b88,
+ 0x8656, 0x203c,
+ 0x8659, 0x203b,
+ 0x865b, 0x0d48,
+ 0x865c, 0x0eed,
+ 0x865e, 0x0eec,
+ 0x865f, 0x0eee,
+ 0x8661, 0x27ce,
+ 0x8662, 0x2a0e,
+ 0x8663, 0x2c5e,
+ 0x8664, 0x2c60,
+ 0x8665, 0x2c5f,
+ 0x8667, 0x1466,
+ 0x8668, 0x2e34,
+ 0x8669, 0x2fad,
+ 0x866a, 0x351e,
+ 0x866b, 0x040f,
+ 0x866c, 0x3813,
+ 0x866d, 0x1a46,
+ 0x866f, 0x1a45,
+ 0x8670, 0x1a44,
+ 0x8671, 0x068a,
+ 0x8672, 0x476f,
+ 0x8673, 0x1bfd,
+ 0x8674, 0x1bfb,
+ 0x8677, 0x1bfa,
+ 0x8679, 0x0800,
+ 0x867a, 0x0802,
+ 0x867b, 0x0801,
+ 0x867c, 0x1bfc,
+ 0x867e, 0x380a,
+ 0x8685, 0x1def,
+ 0x8686, 0x1dec,
+ 0x8687, 0x1dea,
+ 0x868a, 0x09b0,
+ 0x868b, 0x1ded,
+ 0x868c, 0x09b5,
+ 0x868d, 0x1de7,
+ 0x868e, 0x1df6,
+ 0x8690, 0x1df8,
+ 0x8691, 0x1de8,
+ 0x8692, 0x4770,
+ 0x8693, 0x09b2,
+ 0x8694, 0x1df9,
+ 0x8695, 0x1df4,
+ 0x8696, 0x1de6,
+ 0x8697, 0x1deb,
+ 0x8698, 0x1df5,
+ 0x8699, 0x1df1,
+ 0x869a, 0x1dee,
+ 0x869c, 0x09b7,
+ 0x869d, 0x1df7,
+ 0x869e, 0x1de9,
+ 0x86a0, 0x3b88,
+ 0x86a1, 0x1df2,
+ 0x86a2, 0x1de4,
+ 0x86a3, 0x09b6,
+ 0x86a4, 0x09b3,
+ 0x86a5, 0x1df0,
+ 0x86a7, 0x1df3,
+ 0x86a8, 0x1de5,
+ 0x86a9, 0x09b4,
+ 0x86aa, 0x09b1,
+ 0x86ad, 0x3f06,
+ 0x86af, 0x0b92,
+ 0x86b0, 0x2043,
+ 0x86b1, 0x0b91,
+ 0x86b2, 0x43e0,
+ 0x86b3, 0x2046,
+ 0x86b4, 0x2049,
+ 0x86b5, 0x0b8e,
+ 0x86b6, 0x0b8c,
+ 0x86b7, 0x203e,
+ 0x86b8, 0x2047,
+ 0x86b9, 0x2045,
+ 0x86ba, 0x2042,
+ 0x86bb, 0x204a,
+ 0x86bd, 0x204d,
+ 0x86bf, 0x203d,
+ 0x86c0, 0x0b8b,
+ 0x86c1, 0x2040,
+ 0x86c2, 0x203f,
+ 0x86c3, 0x204c,
+ 0x86c4, 0x0b8d,
+ 0x86c5, 0x2041,
+ 0x86c6, 0x0b8f,
+ 0x86c7, 0x0b8a,
+ 0x86c8, 0x2044,
+ 0x86c9, 0x0b93,
+ 0x86cb, 0x0b90,
+ 0x86cc, 0x2048,
+ 0x86d0, 0x0d4f,
+ 0x86d1, 0x22d2,
+ 0x86d3, 0x22c7,
+ 0x86d4, 0x0d4c,
+ 0x86d6, 0x256d,
+ 0x86d7, 0x22d0,
+ 0x86d8, 0x22c4,
+ 0x86d9, 0x0d4a,
+ 0x86da, 0x22c9,
+ 0x86db, 0x0d4d,
+ 0x86dc, 0x22cd,
+ 0x86dd, 0x22cb,
+ 0x86de, 0x0d50,
+ 0x86df, 0x0d49,
+ 0x86e2, 0x22c5,
+ 0x86e3, 0x22c8,
+ 0x86e4, 0x0d4e,
+ 0x86e6, 0x22c6,
+ 0x86e8, 0x22d1,
+ 0x86e9, 0x22cf,
+ 0x86ea, 0x22ca,
+ 0x86eb, 0x22cc,
+ 0x86ec, 0x22ce,
+ 0x86ed, 0x0d4b,
+ 0x86ef, 0x4771,
+ 0x86f5, 0x256e,
+ 0x86f6, 0x2574,
+ 0x86f7, 0x256a,
+ 0x86f8, 0x2570,
+ 0x86f9, 0x0eef,
+ 0x86fa, 0x256c,
+ 0x86fb, 0x0ef5,
+ 0x86fe, 0x0ef4,
+ 0x8700, 0x0ef3,
+ 0x8701, 0x2573,
+ 0x8702, 0x0ef6,
+ 0x8704, 0x2569,
+ 0x8705, 0x2576,
+ 0x8706, 0x0ef8,
+ 0x8707, 0x0ef2,
+ 0x8708, 0x0ef1,
+ 0x8709, 0x2572,
+ 0x870a, 0x0ef9,
+ 0x870b, 0x2568,
+ 0x870c, 0x256b,
+ 0x870d, 0x2575,
+ 0x870e, 0x2571,
+ 0x8711, 0x27ee,
+ 0x8712, 0x27e3,
+ 0x8713, 0x0ef0,
+ 0x8718, 0x1098,
+ 0x8719, 0x27d7,
+ 0x871a, 0x27ec,
+ 0x871b, 0x27d8,
+ 0x871c, 0x1093,
+ 0x871e, 0x27d5,
+ 0x8720, 0x27de,
+ 0x8721, 0x27d6,
+ 0x8722, 0x1095,
+ 0x8723, 0x27d0,
+ 0x8724, 0x27eb,
+ 0x8725, 0x1096,
+ 0x8726, 0x27e8,
+ 0x8728, 0x27d1,
+ 0x8729, 0x109b,
+ 0x872a, 0x27e0,
+ 0x872c, 0x27da,
+ 0x872d, 0x27e1,
+ 0x872e, 0x27d4,
+ 0x8730, 0x27ed,
+ 0x8731, 0x27e5,
+ 0x8732, 0x27df,
+ 0x8733, 0x27cf,
+ 0x8734, 0x1097,
+ 0x8735, 0x27e6,
+ 0x8737, 0x109a,
+ 0x8738, 0x27ea,
+ 0x873a, 0x27e4,
+ 0x873b, 0x1094,
+ 0x873c, 0x27e2,
+ 0x873e, 0x27dc,
+ 0x873f, 0x1092,
+ 0x8740, 0x27d3,
+ 0x8741, 0x27db,
+ 0x8742, 0x27e7,
+ 0x8743, 0x27d9,
+ 0x8746, 0x27dd,
+ 0x874c, 0x1208,
+ 0x874d, 0x256f,
+ 0x874e, 0x2a20,
+ 0x874f, 0x2a29,
+ 0x8750, 0x2a1f,
+ 0x8751, 0x2a1b,
+ 0x8752, 0x2a18,
+ 0x8753, 0x1209,
+ 0x8754, 0x2a16,
+ 0x8755, 0x1099,
+ 0x8756, 0x2a0f,
+ 0x8757, 0x1207,
+ 0x8758, 0x2a15,
+ 0x8759, 0x1206,
+ 0x875a, 0x2a1a,
+ 0x875b, 0x2a17,
+ 0x875c, 0x2a27,
+ 0x875d, 0x2a22,
+ 0x875e, 0x2a1c,
+ 0x875f, 0x2a21,
+ 0x8760, 0x1202,
+ 0x8761, 0x2a19,
+ 0x8762, 0x2a2c,
+ 0x8763, 0x2a10,
+ 0x8765, 0x2a28,
+ 0x8766, 0x1203,
+ 0x8767, 0x2a2d,
+ 0x8768, 0x1205,
+ 0x8769, 0x2a2e,
+ 0x876a, 0x2a1e,
+ 0x876b, 0x27d2,
+ 0x876c, 0x2a24,
+ 0x876d, 0x2a1d,
+ 0x876e, 0x2a26,
+ 0x876f, 0x2a23,
+ 0x8770, 0x3e6c,
+ 0x8771, 0x380b,
+ 0x8773, 0x2a14,
+ 0x8774, 0x1200,
+ 0x8775, 0x2a2b,
+ 0x8776, 0x1201,
+ 0x8777, 0x2a12,
+ 0x8778, 0x1204,
+ 0x8779, 0x2c6b,
+ 0x877a, 0x2a25,
+ 0x877b, 0x2a2a,
+ 0x877d, 0x4045,
+ 0x8781, 0x2c68,
+ 0x8782, 0x11ff,
+ 0x8783, 0x1340,
+ 0x8784, 0x2c72,
+ 0x8785, 0x2c6e,
+ 0x8786, 0x3eb0,
+ 0x8787, 0x2c6c,
+ 0x8788, 0x2c67,
+ 0x8789, 0x2c76,
+ 0x878b, 0x43e2,
+ 0x878c, 0x3fef,
+ 0x878d, 0x1344,
+ 0x878f, 0x2c63,
+ 0x8790, 0x2c6f,
+ 0x8792, 0x2c66,
+ 0x8793, 0x2c65,
+ 0x8794, 0x2c73,
+ 0x8796, 0x2c69,
+ 0x8797, 0x2c64,
+ 0x8798, 0x2c6a,
+ 0x879a, 0x2c75,
+ 0x879b, 0x2c62,
+ 0x879c, 0x2c74,
+ 0x879d, 0x2c71,
+ 0x879e, 0x1342,
+ 0x879f, 0x1341,
+ 0x87a2, 0x1343,
+ 0x87a3, 0x2c6d,
+ 0x87a4, 0x2c61,
+ 0x87a5, 0x3d88,
+ 0x87a9, 0x3fec,
+ 0x87aa, 0x2e36,
+ 0x87ab, 0x146c,
+ 0x87ac, 0x2e3a,
+ 0x87ad, 0x2e37,
+ 0x87ae, 0x2e3e,
+ 0x87af, 0x2e44,
+ 0x87b0, 0x2e39,
+ 0x87b1, 0x380f,
+ 0x87b2, 0x2e4d,
+ 0x87b3, 0x1469,
+ 0x87b4, 0x2e47,
+ 0x87b5, 0x2e3c,
+ 0x87b6, 0x2e48,
+ 0x87b7, 0x2e43,
+ 0x87b8, 0x2e4a,
+ 0x87b9, 0x2e3b,
+ 0x87ba, 0x146e,
+ 0x87bb, 0x146d,
+ 0x87bc, 0x2e3d,
+ 0x87bd, 0x2e4b,
+ 0x87be, 0x2e35,
+ 0x87bf, 0x2e49,
+ 0x87c0, 0x1467,
+ 0x87c1, 0x3ffc,
+ 0x87c2, 0x2e41,
+ 0x87c3, 0x2e40,
+ 0x87c4, 0x2e45,
+ 0x87c5, 0x2e38,
+ 0x87c6, 0x146b,
+ 0x87c8, 0x146f,
+ 0x87c9, 0x2e3f,
+ 0x87ca, 0x2e46,
+ 0x87cb, 0x1470,
+ 0x87cc, 0x2e42,
+ 0x87ce, 0x3fed,
+ 0x87d1, 0x1468,
+ 0x87d2, 0x146a,
+ 0x87d3, 0x2fba,
+ 0x87d4, 0x2fb8,
+ 0x87d6, 0x3f92,
+ 0x87d7, 0x2fbe,
+ 0x87d8, 0x2fbc,
+ 0x87d9, 0x2fbf,
+ 0x87da, 0x3810,
+ 0x87db, 0x2fb1,
+ 0x87dc, 0x2fb9,
+ 0x87dd, 0x2fc3,
+ 0x87de, 0x2e4c,
+ 0x87df, 0x2fb5,
+ 0x87e0, 0x1526,
+ 0x87e1, 0x2a13,
+ 0x87e2, 0x2fb0,
+ 0x87e3, 0x2fbd,
+ 0x87e4, 0x2fb7,
+ 0x87e5, 0x2fb4,
+ 0x87e6, 0x2faf,
+ 0x87e7, 0x2fae,
+ 0x87e8, 0x2fc2,
+ 0x87ea, 0x2fb3,
+ 0x87eb, 0x2fb2,
+ 0x87ec, 0x1524,
+ 0x87ed, 0x2fbb,
+ 0x87ee, 0x380d,
+ 0x87ef, 0x1523,
+ 0x87f2, 0x1525,
+ 0x87f3, 0x2fb6,
+ 0x87f4, 0x2fc1,
+ 0x87f5, 0x3fae,
+ 0x87f6, 0x310a,
+ 0x87f9, 0x15be,
+ 0x87fa, 0x3108,
+ 0x87fb, 0x15bb,
+ 0x87fc, 0x3110,
+ 0x87fe, 0x15bf,
+ 0x87ff, 0x3112,
+ 0x8800, 0x3107,
+ 0x8801, 0x2fc0,
+ 0x8802, 0x3114,
+ 0x8803, 0x3109,
+ 0x8804, 0x3eaf,
+ 0x8805, 0x15bc,
+ 0x8806, 0x310f,
+ 0x8808, 0x3111,
+ 0x8809, 0x310c,
+ 0x880a, 0x3113,
+ 0x880b, 0x310e,
+ 0x880c, 0x310d,
+ 0x880d, 0x15bd,
+ 0x880f, 0x3811,
+ 0x8810, 0x322c,
+ 0x8813, 0x322f,
+ 0x8814, 0x163f,
+ 0x8816, 0x3230,
+ 0x8817, 0x322e,
+ 0x8818, 0x3f7a,
+ 0x8819, 0x322b,
+ 0x881b, 0x3306,
+ 0x881c, 0x3309,
+ 0x881d, 0x3305,
+ 0x881f, 0x168b,
+ 0x8820, 0x3307,
+ 0x8821, 0x168a,
+ 0x8822, 0x1689,
+ 0x8823, 0x1688,
+ 0x8824, 0x3308,
+ 0x8825, 0x33b1,
+ 0x8826, 0x33af,
+ 0x8827, 0x3e07,
+ 0x8828, 0x33ae,
+ 0x8829, 0x3304,
+ 0x882a, 0x33b0,
+ 0x882b, 0x330a,
+ 0x882c, 0x33ad,
+ 0x882d, 0x3b8b,
+ 0x882e, 0x3437,
+ 0x882f, 0x3415,
+ 0x8830, 0x3435,
+ 0x8831, 0x1709,
+ 0x8832, 0x3436,
+ 0x8833, 0x3438,
+ 0x8835, 0x349a,
+ 0x8836, 0x1728,
+ 0x8837, 0x3499,
+ 0x8838, 0x3498,
+ 0x8839, 0x1729,
+ 0x883b, 0x1747,
+ 0x883c, 0x3508,
+ 0x883d, 0x3520,
+ 0x883e, 0x351f,
+ 0x883f, 0x3521,
+ 0x8840, 0x0410,
+ 0x8841, 0x1bfe,
+ 0x8842, 0x3f5a,
+ 0x8843, 0x1dfa,
+ 0x8845, 0x3816,
+ 0x8848, 0x22d3,
+ 0x884a, 0x330b,
+ 0x884b, 0x349b,
+ 0x884c, 0x0411,
+ 0x884d, 0x0803,
+ 0x884e, 0x1bff,
+ 0x884f, 0x3844,
+ 0x8852, 0x204f,
+ 0x8853, 0x0b94,
+ 0x8855, 0x22d5,
+ 0x8856, 0x22d4,
+ 0x8857, 0x0d51,
+ 0x8859, 0x0efa,
+ 0x885a, 0x2a2f,
+ 0x885b, 0x120a,
+ 0x885d, 0x120b,
+ 0x885e, 0x381b,
+ 0x8860, 0x3a46,
+ 0x8861, 0x1345,
+ 0x8862, 0x172a,
+ 0x8863, 0x0412,
+ 0x8864, 0x4502,
+ 0x8865, 0x3dfc,
+ 0x8867, 0x1c00,
+ 0x8868, 0x068c,
+ 0x8869, 0x1c02,
+ 0x886a, 0x1c01,
+ 0x886b, 0x0804,
+ 0x886d, 0x1dfc,
+ 0x886e, 0x3b8e,
+ 0x886f, 0x1e03,
+ 0x8870, 0x09b8,
+ 0x8871, 0x1e01,
+ 0x8872, 0x1dff,
+ 0x8874, 0x1e06,
+ 0x8875, 0x1dfd,
+ 0x8877, 0x09b9,
+ 0x8879, 0x09bd,
+ 0x887c, 0x1e07,
+ 0x887d, 0x09bc,
+ 0x887e, 0x1e05,
+ 0x887f, 0x1e02,
+ 0x8880, 0x1e00,
+ 0x8881, 0x09ba,
+ 0x8883, 0x1e04,
+ 0x8884, 0x42f7,
+ 0x8887, 0x3b90,
+ 0x8888, 0x0b96,
+ 0x8889, 0x2050,
+ 0x888b, 0x0b9b,
+ 0x888c, 0x2060,
+ 0x888d, 0x0b9a,
+ 0x888e, 0x2062,
+ 0x8891, 0x2056,
+ 0x8892, 0x0b98,
+ 0x8893, 0x2061,
+ 0x8895, 0x2051,
+ 0x8896, 0x0b99,
+ 0x8897, 0x205d,
+ 0x8898, 0x2059,
+ 0x8899, 0x205b,
+ 0x889a, 0x2055,
+ 0x889b, 0x205c,
+ 0x889c, 0x381c,
+ 0x889e, 0x0b95,
+ 0x889f, 0x2058,
+ 0x88a0, 0x3fa0,
+ 0x88a1, 0x2057,
+ 0x88a2, 0x2053,
+ 0x88a4, 0x205e,
+ 0x88a7, 0x205a,
+ 0x88a8, 0x2052,
+ 0x88aa, 0x2054,
+ 0x88ab, 0x0b97,
+ 0x88ac, 0x205f,
+ 0x88ae, 0x4775,
+ 0x88b1, 0x0d54,
+ 0x88b2, 0x22e0,
+ 0x88b4, 0x381e,
+ 0x88b6, 0x22dc,
+ 0x88b7, 0x22de,
+ 0x88b8, 0x22d9,
+ 0x88b9, 0x22d8,
+ 0x88ba, 0x22d6,
+ 0x88bc, 0x22dd,
+ 0x88bd, 0x22df,
+ 0x88be, 0x22db,
+ 0x88bf, 0x3b91,
+ 0x88c0, 0x22da,
+ 0x88c1, 0x0d52,
+ 0x88c5, 0x3820,
+ 0x88c7, 0x3eb1,
+ 0x88c9, 0x22e2,
+ 0x88ca, 0x0f02,
+ 0x88cb, 0x2578,
+ 0x88cc, 0x257e,
+ 0x88cd, 0x2579,
+ 0x88cf, 0x36ea,
+ 0x88d0, 0x257f,
+ 0x88d2, 0x0f04,
+ 0x88d4, 0x0efc,
+ 0x88d5, 0x0f03,
+ 0x88d6, 0x2577,
+ 0x88d7, 0x22d7,
+ 0x88d8, 0x0eff,
+ 0x88d9, 0x0efd,
+ 0x88da, 0x257d,
+ 0x88db, 0x257c,
+ 0x88dc, 0x0efe,
+ 0x88dd, 0x0f00,
+ 0x88de, 0x257b,
+ 0x88df, 0x0efb,
+ 0x88e1, 0x0f01,
+ 0x88e6, 0x3b92,
+ 0x88e7, 0x27f0,
+ 0x88e8, 0x10a2,
+ 0x88eb, 0x27fb,
+ 0x88ec, 0x27fa,
+ 0x88ee, 0x27f5,
+ 0x88ef, 0x10a4,
+ 0x88f0, 0x27f9,
+ 0x88f1, 0x27f1,
+ 0x88f3, 0x109c,
+ 0x88f4, 0x109e,
+ 0x88f5, 0x3e08,
+ 0x88f6, 0x27f7,
+ 0x88f7, 0x27ef,
+ 0x88f8, 0x10a0,
+ 0x88f9, 0x109f,
+ 0x88fa, 0x27f3,
+ 0x88fb, 0x27f8,
+ 0x88fc, 0x27f6,
+ 0x88fd, 0x10a1,
+ 0x88fe, 0x27f4,
+ 0x88ff, 0x4776,
+ 0x8900, 0x42fa,
+ 0x8901, 0x22e1,
+ 0x8902, 0x109d,
+ 0x8905, 0x2a30,
+ 0x8906, 0x2a37,
+ 0x8907, 0x120d,
+ 0x8909, 0x2a3b,
+ 0x890a, 0x1211,
+ 0x890b, 0x2a33,
+ 0x890c, 0x2a31,
+ 0x890e, 0x2a3a,
+ 0x8910, 0x120c,
+ 0x8911, 0x2a39,
+ 0x8912, 0x120e,
+ 0x8914, 0x2a32,
+ 0x8915, 0x1210,
+ 0x8916, 0x2a38,
+ 0x8917, 0x2a34,
+ 0x891a, 0x10a3,
+ 0x891e, 0x2c77,
+ 0x891f, 0x2c83,
+ 0x8921, 0x134a,
+ 0x8922, 0x2c7e,
+ 0x8923, 0x2c80,
+ 0x8924, 0x4777,
+ 0x8925, 0x1348,
+ 0x8926, 0x2c78,
+ 0x8927, 0x2c7c,
+ 0x8929, 0x2c7f,
+ 0x892a, 0x1346,
+ 0x892b, 0x1349,
+ 0x892c, 0x2c82,
+ 0x892d, 0x2c7a,
+ 0x892f, 0x2c81,
+ 0x8930, 0x2c79,
+ 0x8931, 0x2c7d,
+ 0x8932, 0x1347,
+ 0x8933, 0x2e4f,
+ 0x8935, 0x2e4e,
+ 0x8936, 0x1472,
+ 0x8937, 0x2e54,
+ 0x8938, 0x1474,
+ 0x893b, 0x1471,
+ 0x893c, 0x2e50,
+ 0x893d, 0x1475,
+ 0x893e, 0x2e51,
+ 0x8941, 0x2e52,
+ 0x8942, 0x2e55,
+ 0x8943, 0x3e16,
+ 0x8944, 0x1473,
+ 0x8946, 0x2fc8,
+ 0x8947, 0x43e3,
+ 0x8949, 0x2fcb,
+ 0x894b, 0x2fc5,
+ 0x894c, 0x2fc7,
+ 0x894d, 0x3b94,
+ 0x894f, 0x2fc6,
+ 0x8950, 0x2fc9,
+ 0x8952, 0x2e53,
+ 0x8953, 0x2fc4,
+ 0x8954, 0x3b96,
+ 0x8956, 0x15c2,
+ 0x8957, 0x3118,
+ 0x8958, 0x311b,
+ 0x8959, 0x311d,
+ 0x895a, 0x3116,
+ 0x895c, 0x311a,
+ 0x895d, 0x311c,
+ 0x895e, 0x15c3,
+ 0x895f, 0x15c1,
+ 0x8960, 0x15c0,
+ 0x8961, 0x3119,
+ 0x8962, 0x3115,
+ 0x8963, 0x3231,
+ 0x8964, 0x1641,
+ 0x8965, 0x3b93,
+ 0x8966, 0x3232,
+ 0x8969, 0x330d,
+ 0x896a, 0x168c,
+ 0x896b, 0x330f,
+ 0x896c, 0x168d,
+ 0x896d, 0x330c,
+ 0x896e, 0x330e,
+ 0x896f, 0x16d6,
+ 0x8971, 0x33b2,
+ 0x8972, 0x16d5,
+ 0x8973, 0x343b,
+ 0x8974, 0x343a,
+ 0x8976, 0x3439,
+ 0x8977, 0x3dea,
+ 0x8979, 0x34e2,
+ 0x897b, 0x34e5,
+ 0x897c, 0x34e4,
+ 0x897e, 0x1819,
+ 0x897f, 0x0413,
+ 0x8980, 0x4708,
+ 0x8981, 0x0805,
+ 0x8982, 0x2063,
+ 0x8983, 0x0d55,
+ 0x8985, 0x2580,
+ 0x8986, 0x1527,
+ 0x8987, 0x3822,
+ 0x8988, 0x311e,
+ 0x8989, 0x3fe9,
+ 0x898a, 0x3823,
+ 0x898b, 0x0508,
+ 0x898f, 0x0b9d,
+ 0x8991, 0x4778,
+ 0x8993, 0x0b9c,
+ 0x8994, 0x3fe0,
+ 0x8995, 0x22e3,
+ 0x8996, 0x0d56,
+ 0x8997, 0x22e5,
+ 0x8998, 0x22e4,
+ 0x899b, 0x2581,
+ 0x899c, 0x0f05,
+ 0x899d, 0x27fc,
+ 0x899e, 0x27ff,
+ 0x899f, 0x27fe,
+ 0x89a1, 0x27fd,
+ 0x89a2, 0x2a3c,
+ 0x89a3, 0x2a3e,
+ 0x89a4, 0x2a3d,
+ 0x89a5, 0x3d93,
+ 0x89a6, 0x134c,
+ 0x89a7, 0x3826,
+ 0x89a9, 0x3825,
+ 0x89aa, 0x134b,
+ 0x89ac, 0x1476,
+ 0x89ad, 0x2e56,
+ 0x89ae, 0x2e58,
+ 0x89af, 0x2e57,
+ 0x89b2, 0x1528,
+ 0x89b6, 0x3120,
+ 0x89b7, 0x311f,
+ 0x89b9, 0x3233,
+ 0x89ba, 0x1642,
+ 0x89bc, 0x3827,
+ 0x89bd, 0x168e,
+ 0x89be, 0x33b4,
+ 0x89bf, 0x33b3,
+ 0x89c0, 0x1748,
+ 0x89c1, 0x4503,
+ 0x89c6, 0x4566,
+ 0x89d2, 0x0509,
+ 0x89d3, 0x1c03,
+ 0x89d4, 0x0806,
+ 0x89d5, 0x2066,
+ 0x89d6, 0x2064,
+ 0x89d9, 0x2065,
+ 0x89da, 0x22e7,
+ 0x89dc, 0x2588,
+ 0x89dd, 0x22e6,
+ 0x89df, 0x2582,
+ 0x89e0, 0x2586,
+ 0x89e1, 0x2585,
+ 0x89e2, 0x2587,
+ 0x89e3, 0x0f06,
+ 0x89e4, 0x2584,
+ 0x89e5, 0x2583,
+ 0x89e6, 0x2589,
+ 0x89e7, 0x3829,
+ 0x89e8, 0x2802,
+ 0x89e9, 0x2800,
+ 0x89eb, 0x2801,
+ 0x89ec, 0x2a41,
+ 0x89ed, 0x2a3f,
+ 0x89f0, 0x2a40,
+ 0x89f1, 0x2c84,
+ 0x89f2, 0x2e59,
+ 0x89f4, 0x1529,
+ 0x89f6, 0x3121,
+ 0x89f7, 0x3234,
+ 0x89f8, 0x1643,
+ 0x89fa, 0x3310,
+ 0x89fb, 0x33b5,
+ 0x89fc, 0x16d7,
+ 0x89fe, 0x343c,
+ 0x89ff, 0x34e6,
+ 0x8a00, 0x050a,
+ 0x8a02, 0x0808,
+ 0x8a04, 0x1c04,
+ 0x8a07, 0x1c05,
+ 0x8a08, 0x0807,
+ 0x8a0a, 0x09c3,
+ 0x8a0c, 0x09c1,
+ 0x8a0e, 0x09c0,
+ 0x8a0f, 0x09c7,
+ 0x8a10, 0x09bf,
+ 0x8a11, 0x09c8,
+ 0x8a12, 0x1e08,
+ 0x8a13, 0x09c5,
+ 0x8a15, 0x09c2,
+ 0x8a16, 0x09c6,
+ 0x8a17, 0x09c4,
+ 0x8a18, 0x09be,
+ 0x8a1b, 0x0ba5,
+ 0x8a1c, 0x3ba3,
+ 0x8a1d, 0x0b9f,
+ 0x8a1e, 0x206a,
+ 0x8a1f, 0x0ba4,
+ 0x8a22, 0x0ba6,
+ 0x8a23, 0x0ba0,
+ 0x8a25, 0x0ba1,
+ 0x8a27, 0x2068,
+ 0x8a29, 0x43e5,
+ 0x8a2a, 0x0b9e,
+ 0x8a2b, 0x3bd1,
+ 0x8a2c, 0x2069,
+ 0x8a2d, 0x0ba3,
+ 0x8a30, 0x2067,
+ 0x8a31, 0x0ba2,
+ 0x8a34, 0x0d61,
+ 0x8a36, 0x0d63,
+ 0x8a38, 0x477a,
+ 0x8a39, 0x22eb,
+ 0x8a3a, 0x0d62,
+ 0x8a3b, 0x0d57,
+ 0x8a3c, 0x0d5b,
+ 0x8a3d, 0x3ba2,
+ 0x8a3e, 0x0f19,
+ 0x8a3f, 0x258e,
+ 0x8a40, 0x22ed,
+ 0x8a41, 0x0d5c,
+ 0x8a44, 0x22f0,
+ 0x8a46, 0x0d60,
+ 0x8a48, 0x22f3,
+ 0x8a49, 0x3ff0,
+ 0x8a4a, 0x22f5,
+ 0x8a4c, 0x22f6,
+ 0x8a4d, 0x22ea,
+ 0x8a4e, 0x22e9,
+ 0x8a4f, 0x22f7,
+ 0x8a50, 0x0d5f,
+ 0x8a51, 0x22f4,
+ 0x8a52, 0x22f2,
+ 0x8a54, 0x0d5d,
+ 0x8a55, 0x0d59,
+ 0x8a56, 0x0d64,
+ 0x8a57, 0x22ee,
+ 0x8a59, 0x22ec,
+ 0x8a5b, 0x0d5e,
+ 0x8a5e, 0x0d5a,
+ 0x8a60, 0x0d58,
+ 0x8a61, 0x258d,
+ 0x8a62, 0x0f14,
+ 0x8a63, 0x0f0f,
+ 0x8a66, 0x0f0a,
+ 0x8a67, 0x3f8e,
+ 0x8a68, 0x0f1a,
+ 0x8a69, 0x0f0b,
+ 0x8a6b, 0x0f07,
+ 0x8a6c, 0x0f16,
+ 0x8a6d, 0x0f13,
+ 0x8a6e, 0x0f15,
+ 0x8a70, 0x0f0c,
+ 0x8a71, 0x0f11,
+ 0x8a72, 0x0f08,
+ 0x8a74, 0x2595,
+ 0x8a75, 0x2592,
+ 0x8a76, 0x258a,
+ 0x8a77, 0x258f,
+ 0x8a79, 0x0f17,
+ 0x8a7a, 0x2596,
+ 0x8a7b, 0x0f18,
+ 0x8a7c, 0x0f0e,
+ 0x8a7e, 0x3fa5,
+ 0x8a7f, 0x258c,
+ 0x8a81, 0x2594,
+ 0x8a82, 0x2590,
+ 0x8a83, 0x2593,
+ 0x8a84, 0x2591,
+ 0x8a85, 0x0f12,
+ 0x8a86, 0x258b,
+ 0x8a87, 0x0f0d,
+ 0x8a8b, 0x2805,
+ 0x8a8c, 0x10a6,
+ 0x8a8d, 0x10a9,
+ 0x8a8f, 0x2807,
+ 0x8a90, 0x382f,
+ 0x8a91, 0x10b1,
+ 0x8a92, 0x2806,
+ 0x8a93, 0x10ab,
+ 0x8a94, 0x477b,
+ 0x8a95, 0x1216,
+ 0x8a96, 0x2808,
+ 0x8a98, 0x10b0,
+ 0x8a99, 0x2804,
+ 0x8a9a, 0x10b2,
+ 0x8a9c, 0x382c,
+ 0x8a9e, 0x10a7,
+ 0x8aa0, 0x0f10,
+ 0x8aa1, 0x10aa,
+ 0x8aa3, 0x10a8,
+ 0x8aa4, 0x10ac,
+ 0x8aa5, 0x10ae,
+ 0x8aa6, 0x10a5,
+ 0x8aa7, 0x10b3,
+ 0x8aa8, 0x10af,
+ 0x8aa9, 0x383d,
+ 0x8aaa, 0x10ad,
+ 0x8aab, 0x2803,
+ 0x8aaf, 0x3841,
+ 0x8ab0, 0x121d,
+ 0x8ab2, 0x1219,
+ 0x8ab4, 0x477c,
+ 0x8ab6, 0x1220,
+ 0x8ab8, 0x2a44,
+ 0x8ab9, 0x1221,
+ 0x8aba, 0x2a50,
+ 0x8abb, 0x2a49,
+ 0x8abc, 0x1212,
+ 0x8abd, 0x2a51,
+ 0x8abe, 0x2a4b,
+ 0x8abf, 0x121c,
+ 0x8ac0, 0x2a4c,
+ 0x8ac2, 0x121b,
+ 0x8ac3, 0x2a4f,
+ 0x8ac4, 0x1215,
+ 0x8ac5, 0x2a4d,
+ 0x8ac6, 0x2a43,
+ 0x8ac7, 0x1214,
+ 0x8ac8, 0x2c8f,
+ 0x8ac9, 0x121a,
+ 0x8acb, 0x1217,
+ 0x8acd, 0x121f,
+ 0x8acf, 0x2a42,
+ 0x8ad1, 0x2a46,
+ 0x8ad2, 0x1213,
+ 0x8ad3, 0x2a45,
+ 0x8ad4, 0x2a47,
+ 0x8ad6, 0x121e,
+ 0x8ad7, 0x2a4a,
+ 0x8ad8, 0x2a4e,
+ 0x8ad9, 0x2a52,
+ 0x8ada, 0x39c2,
+ 0x8adb, 0x1222,
+ 0x8adc, 0x1352,
+ 0x8add, 0x2c8a,
+ 0x8ade, 0x2c90,
+ 0x8adf, 0x2c8d,
+ 0x8ae0, 0x2c85,
+ 0x8ae1, 0x2c91,
+ 0x8ae2, 0x2c86,
+ 0x8ae4, 0x2c8c,
+ 0x8ae6, 0x134d,
+ 0x8ae7, 0x1353,
+ 0x8ae8, 0x2c92,
+ 0x8aea, 0x3dd9,
+ 0x8aeb, 0x134f,
+ 0x8aed, 0x1359,
+ 0x8aee, 0x1354,
+ 0x8aef, 0x2c94,
+ 0x8af0, 0x2c8e,
+ 0x8af1, 0x1350,
+ 0x8af2, 0x2c87,
+ 0x8af3, 0x135a,
+ 0x8af4, 0x2c88,
+ 0x8af6, 0x135b,
+ 0x8af7, 0x1358,
+ 0x8af8, 0x1218,
+ 0x8afa, 0x134e,
+ 0x8afb, 0x2c95,
+ 0x8afc, 0x135c,
+ 0x8afe, 0x1355,
+ 0x8aff, 0x2c93,
+ 0x8b00, 0x1351,
+ 0x8b01, 0x1356,
+ 0x8b04, 0x147e,
+ 0x8b05, 0x2e5f,
+ 0x8b06, 0x2e68,
+ 0x8b07, 0x2e65,
+ 0x8b08, 0x2e67,
+ 0x8b0a, 0x147b,
+ 0x8b0b, 0x2e60,
+ 0x8b0c, 0x3836,
+ 0x8b0d, 0x2e66,
+ 0x8b0e, 0x1477,
+ 0x8b0f, 0x2e62,
+ 0x8b10, 0x147f,
+ 0x8b11, 0x2e5e,
+ 0x8b12, 0x2e63,
+ 0x8b13, 0x2e6a,
+ 0x8b14, 0x2c8b,
+ 0x8b15, 0x2e64,
+ 0x8b16, 0x2e5d,
+ 0x8b17, 0x1478,
+ 0x8b18, 0x2e5c,
+ 0x8b19, 0x1479,
+ 0x8b1a, 0x2e6b,
+ 0x8b1b, 0x147a,
+ 0x8b1c, 0x2e69,
+ 0x8b1d, 0x147d,
+ 0x8b1e, 0x2e5b,
+ 0x8b1f, 0x3837,
+ 0x8b20, 0x147c,
+ 0x8b22, 0x2e61,
+ 0x8b23, 0x2fce,
+ 0x8b24, 0x2fdc,
+ 0x8b25, 0x2fd7,
+ 0x8b26, 0x2fd9,
+ 0x8b27, 0x2fcd,
+ 0x8b28, 0x152a,
+ 0x8b2a, 0x2fcc,
+ 0x8b2b, 0x152d,
+ 0x8b2c, 0x152c,
+ 0x8b2d, 0x3f99,
+ 0x8b2e, 0x2fdb,
+ 0x8b2f, 0x2fd3,
+ 0x8b30, 0x2fd0,
+ 0x8b31, 0x2fd6,
+ 0x8b33, 0x2fcf,
+ 0x8b35, 0x2fd1,
+ 0x8b36, 0x2fda,
+ 0x8b37, 0x2fd8,
+ 0x8b39, 0x152b,
+ 0x8b3a, 0x2fdf,
+ 0x8b3b, 0x2fdd,
+ 0x8b3c, 0x2fd4,
+ 0x8b3d, 0x2fde,
+ 0x8b3e, 0x2fd5,
+ 0x8b3f, 0x383a,
+ 0x8b40, 0x3125,
+ 0x8b41, 0x15c4,
+ 0x8b42, 0x312c,
+ 0x8b43, 0x3ff2,
+ 0x8b45, 0x3313,
+ 0x8b46, 0x15cb,
+ 0x8b47, 0x2fd2,
+ 0x8b48, 0x3123,
+ 0x8b49, 0x15c7,
+ 0x8b4a, 0x3124,
+ 0x8b4b, 0x3129,
+ 0x8b4c, 0x383b,
+ 0x8b4e, 0x15c9,
+ 0x8b50, 0x3122,
+ 0x8b51, 0x312b,
+ 0x8b52, 0x312d,
+ 0x8b53, 0x3126,
+ 0x8b54, 0x3128,
+ 0x8b55, 0x312a,
+ 0x8b56, 0x3127,
+ 0x8b57, 0x312e,
+ 0x8b58, 0x15c6,
+ 0x8b59, 0x15cc,
+ 0x8b5a, 0x15c8,
+ 0x8b5c, 0x15c5,
+ 0x8b5d, 0x3237,
+ 0x8b5e, 0x3db8,
+ 0x8b5f, 0x1648,
+ 0x8b60, 0x3235,
+ 0x8b62, 0x3dd4,
+ 0x8b63, 0x3239,
+ 0x8b65, 0x323a,
+ 0x8b66, 0x1646,
+ 0x8b67, 0x323b,
+ 0x8b68, 0x3238,
+ 0x8b69, 0x3bf7,
+ 0x8b6a, 0x3236,
+ 0x8b6b, 0x1649,
+ 0x8b6c, 0x1645,
+ 0x8b6d, 0x323c,
+ 0x8b6f, 0x1647,
+ 0x8b70, 0x1644,
+ 0x8b74, 0x168f,
+ 0x8b77, 0x1690,
+ 0x8b78, 0x3312,
+ 0x8b79, 0x3311,
+ 0x8b7a, 0x3314,
+ 0x8b7d, 0x1691,
+ 0x8b7e, 0x33b6,
+ 0x8b7f, 0x33bb,
+ 0x8b80, 0x16d8,
+ 0x8b81, 0x3d8d,
+ 0x8b82, 0x33b8,
+ 0x8b84, 0x33b7,
+ 0x8b85, 0x33ba,
+ 0x8b86, 0x33b9,
+ 0x8b88, 0x3440,
+ 0x8b8a, 0x170a,
+ 0x8b8b, 0x343f,
+ 0x8b8c, 0x343d,
+ 0x8b8e, 0x343e,
+ 0x8b90, 0x383f,
+ 0x8b92, 0x172c,
+ 0x8b93, 0x172b,
+ 0x8b94, 0x349c,
+ 0x8b96, 0x172d,
+ 0x8b98, 0x34e7,
+ 0x8b9a, 0x1754,
+ 0x8b9b, 0x3840,
+ 0x8b9c, 0x175a,
+ 0x8b9e, 0x3522,
+ 0x8b9f, 0x353f,
+ 0x8ba0, 0x4505,
+ 0x8bbe, 0x4567,
+ 0x8be2, 0x4568,
+ 0x8c37, 0x050b,
+ 0x8c39, 0x206b,
+ 0x8c3b, 0x206c,
+ 0x8c3c, 0x2597,
+ 0x8c3d, 0x2809,
+ 0x8c3e, 0x2a53,
+ 0x8c3f, 0x1481,
+ 0x8c41, 0x1480,
+ 0x8c42, 0x2fe0,
+ 0x8c43, 0x312f,
+ 0x8c45, 0x3441,
+ 0x8c46, 0x050c,
+ 0x8c47, 0x1e09,
+ 0x8c48, 0x09c9,
+ 0x8c49, 0x0ba7,
+ 0x8c4a, 0x2599,
+ 0x8c4b, 0x2598,
+ 0x8c4c, 0x1223,
+ 0x8c4d, 0x2a54,
+ 0x8c4e, 0x1224,
+ 0x8c4f, 0x2e6c,
+ 0x8c50, 0x152e,
+ 0x8c51, 0x477d,
+ 0x8c54, 0x1763,
+ 0x8c55, 0x050d,
+ 0x8c56, 0x1a48,
+ 0x8c57, 0x1e0a,
+ 0x8c5a, 0x0ba8,
+ 0x8c5c, 0x206d,
+ 0x8c5f, 0x22f8,
+ 0x8c61, 0x0d65,
+ 0x8c62, 0x0f1b,
+ 0x8c64, 0x259b,
+ 0x8c65, 0x259a,
+ 0x8c66, 0x259c,
+ 0x8c68, 0x280a,
+ 0x8c6a, 0x10b4,
+ 0x8c6b, 0x135d,
+ 0x8c6c, 0x1225,
+ 0x8c6d, 0x135e,
+ 0x8c6f, 0x2e70,
+ 0x8c70, 0x2e6d,
+ 0x8c71, 0x2e6f,
+ 0x8c72, 0x2e6e,
+ 0x8c73, 0x1482,
+ 0x8c75, 0x2fe1,
+ 0x8c76, 0x3131,
+ 0x8c77, 0x3130,
+ 0x8c78, 0x18e7,
+ 0x8c79, 0x09cb,
+ 0x8c7a, 0x09ca,
+ 0x8c7b, 0x1e0b,
+ 0x8c7d, 0x206f,
+ 0x8c80, 0x22fa,
+ 0x8c81, 0x22f9,
+ 0x8c82, 0x0d66,
+ 0x8c84, 0x259e,
+ 0x8c86, 0x259d,
+ 0x8c89, 0x0f1d,
+ 0x8c8a, 0x0f1c,
+ 0x8c8c, 0x10b6,
+ 0x8c8d, 0x10b5,
+ 0x8c8f, 0x2a55,
+ 0x8c90, 0x2c98,
+ 0x8c91, 0x2c96,
+ 0x8c93, 0x135f,
+ 0x8c94, 0x2e72,
+ 0x8c95, 0x2e71,
+ 0x8c97, 0x2fe4,
+ 0x8c98, 0x2fe3,
+ 0x8c99, 0x2fe2,
+ 0x8c9a, 0x3132,
+ 0x8c9b, 0x3845,
+ 0x8c9c, 0x3523,
+ 0x8c9d, 0x050e,
+ 0x8c9e, 0x080a,
+ 0x8c9f, 0x3bad,
+ 0x8ca0, 0x080b,
+ 0x8ca1, 0x09cc,
+ 0x8ca3, 0x1e0d,
+ 0x8ca4, 0x1e0c,
+ 0x8ca5, 0x2070,
+ 0x8ca7, 0x0bae,
+ 0x8ca8, 0x0bac,
+ 0x8ca9, 0x0ba9,
+ 0x8caa, 0x0bad,
+ 0x8cab, 0x0bab,
+ 0x8cac, 0x0baa,
+ 0x8cad, 0x3ff1,
+ 0x8caf, 0x0d67,
+ 0x8cb0, 0x22fd,
+ 0x8cb2, 0x0f22,
+ 0x8cb3, 0x0d69,
+ 0x8cb4, 0x0d6e,
+ 0x8cb5, 0x22ff,
+ 0x8cb6, 0x0d70,
+ 0x8cb7, 0x0d6f,
+ 0x8cb8, 0x0d72,
+ 0x8cb9, 0x22fe,
+ 0x8cba, 0x22fb,
+ 0x8cbb, 0x0d6c,
+ 0x8cbc, 0x0d68,
+ 0x8cbd, 0x0d6a,
+ 0x8cbe, 0x22fc,
+ 0x8cbf, 0x0d71,
+ 0x8cc0, 0x0d6d,
+ 0x8cc1, 0x0d6b,
+ 0x8cc2, 0x0f24,
+ 0x8cc3, 0x0f23,
+ 0x8cc4, 0x0f21,
+ 0x8cc5, 0x0f25,
+ 0x8cc7, 0x0f1f,
+ 0x8cca, 0x0f1e,
+ 0x8ccc, 0x25a0,
+ 0x8ccd, 0x3e99,
+ 0x8ccf, 0x280d,
+ 0x8cd1, 0x10b8,
+ 0x8cd3, 0x10b7,
+ 0x8cd4, 0x477e,
+ 0x8cd5, 0x280c,
+ 0x8cd6, 0x384b,
+ 0x8cd7, 0x280e,
+ 0x8cd9, 0x2a58,
+ 0x8cda, 0x2a5a,
+ 0x8cdb, 0x3851,
+ 0x8cdc, 0x122e,
+ 0x8cdd, 0x2a5b,
+ 0x8cde, 0x1227,
+ 0x8cdf, 0x2a57,
+ 0x8ce0, 0x1226,
+ 0x8ce1, 0x1230,
+ 0x8ce2, 0x122c,
+ 0x8ce4, 0x1229,
+ 0x8ce5, 0x2a56,
+ 0x8ce6, 0x1228,
+ 0x8ce7, 0x2a5c,
+ 0x8ce8, 0x2a59,
+ 0x8ce9, 0x3bae,
+ 0x8cea, 0x122f,
+ 0x8ceb, 0x3f9c,
+ 0x8cec, 0x122a,
+ 0x8cee, 0x2c9a,
+ 0x8cf0, 0x2c9c,
+ 0x8cf1, 0x2c9b,
+ 0x8cf2, 0x477f,
+ 0x8cf3, 0x2c9d,
+ 0x8cf4, 0x1360,
+ 0x8cf5, 0x2c99,
+ 0x8cf7, 0x3fb1,
+ 0x8cf8, 0x1486,
+ 0x8cf9, 0x2e73,
+ 0x8cfa, 0x1483,
+ 0x8cfb, 0x1487,
+ 0x8cfc, 0x1485,
+ 0x8cfd, 0x1484,
+ 0x8cfe, 0x2fe5,
+ 0x8d00, 0x2fe8,
+ 0x8d02, 0x2fe7,
+ 0x8d03, 0x384f,
+ 0x8d04, 0x2fe6,
+ 0x8d05, 0x152f,
+ 0x8d06, 0x3133,
+ 0x8d08, 0x15cd,
+ 0x8d09, 0x3135,
+ 0x8d0a, 0x15ce,
+ 0x8d0b, 0x4573,
+ 0x8d0c, 0x3f96,
+ 0x8d0d, 0x164b,
+ 0x8d0f, 0x164a,
+ 0x8d10, 0x3316,
+ 0x8d11, 0x3853,
+ 0x8d12, 0x384e,
+ 0x8d13, 0x1692,
+ 0x8d14, 0x3317,
+ 0x8d15, 0x33bc,
+ 0x8d16, 0x16d9,
+ 0x8d18, 0x3e6f,
+ 0x8d19, 0x3442,
+ 0x8d1b, 0x172f,
+ 0x8d1c, 0x4780,
+ 0x8d1d, 0x4506,
+ 0x8d64, 0x050f,
+ 0x8d66, 0x0bb0,
+ 0x8d67, 0x0baf,
+ 0x8d68, 0x25a1,
+ 0x8d6b, 0x10ba,
+ 0x8d6c, 0x2c9e,
+ 0x8d6d, 0x1231,
+ 0x8d6e, 0x2c9f,
+ 0x8d6f, 0x2e74,
+ 0x8d70, 0x0510,
+ 0x8d72, 0x1c06,
+ 0x8d73, 0x080d,
+ 0x8d74, 0x080c,
+ 0x8d76, 0x1e0e,
+ 0x8d77, 0x09ce,
+ 0x8d78, 0x1e0f,
+ 0x8d79, 0x2073,
+ 0x8d7a, 0x39e1,
+ 0x8d7b, 0x2072,
+ 0x8d7d, 0x2071,
+ 0x8d80, 0x2301,
+ 0x8d81, 0x0d75,
+ 0x8d82, 0x3f69,
+ 0x8d84, 0x2300,
+ 0x8d85, 0x0d74,
+ 0x8d89, 0x2302,
+ 0x8d8a, 0x0d73,
+ 0x8d8c, 0x25a4,
+ 0x8d8d, 0x25a7,
+ 0x8d8e, 0x25a5,
+ 0x8d90, 0x25aa,
+ 0x8d91, 0x25a3,
+ 0x8d92, 0x25ab,
+ 0x8d93, 0x25a8,
+ 0x8d95, 0x10bc,
+ 0x8d96, 0x280f,
+ 0x8d99, 0x10bb,
+ 0x8d9b, 0x2a60,
+ 0x8d9c, 0x2a5e,
+ 0x8d9f, 0x1232,
+ 0x8da0, 0x2a5d,
+ 0x8da1, 0x2a5f,
+ 0x8da3, 0x1233,
+ 0x8da5, 0x2ca0,
+ 0x8da6, 0x3ff7,
+ 0x8da7, 0x2ca1,
+ 0x8da8, 0x1488,
+ 0x8da9, 0x3856,
+ 0x8daa, 0x3137,
+ 0x8dab, 0x3139,
+ 0x8dac, 0x3136,
+ 0x8dad, 0x3138,
+ 0x8dae, 0x323d,
+ 0x8daf, 0x3318,
+ 0x8db2, 0x3509,
+ 0x8db3, 0x0511,
+ 0x8db4, 0x080e,
+ 0x8db5, 0x1e10,
+ 0x8db6, 0x1e12,
+ 0x8db7, 0x1e11,
+ 0x8db9, 0x2076,
+ 0x8dba, 0x0bb2,
+ 0x8dbc, 0x2074,
+ 0x8dbe, 0x0bb1,
+ 0x8dbf, 0x2077,
+ 0x8dc0, 0x436a,
+ 0x8dc1, 0x2078,
+ 0x8dc2, 0x2075,
+ 0x8dc3, 0x4782,
+ 0x8dc5, 0x230e,
+ 0x8dc6, 0x0d7d,
+ 0x8dc7, 0x2306,
+ 0x8dc8, 0x230c,
+ 0x8dcb, 0x0d78,
+ 0x8dcc, 0x0d7b,
+ 0x8dcd, 0x2305,
+ 0x8dce, 0x0d76,
+ 0x8dcf, 0x2309,
+ 0x8dd0, 0x25b1,
+ 0x8dd1, 0x0d7a,
+ 0x8dd3, 0x2304,
+ 0x8dd4, 0x3f82,
+ 0x8dd5, 0x230a,
+ 0x8dd6, 0x2307,
+ 0x8dd7, 0x230d,
+ 0x8dd8, 0x2303,
+ 0x8dd9, 0x230b,
+ 0x8dda, 0x0d79,
+ 0x8ddb, 0x0d7c,
+ 0x8ddc, 0x2308,
+ 0x8ddd, 0x0d77,
+ 0x8ddf, 0x0f27,
+ 0x8de0, 0x25ad,
+ 0x8de1, 0x0f26,
+ 0x8de2, 0x25b4,
+ 0x8de3, 0x25b3,
+ 0x8de4, 0x0f2d,
+ 0x8de6, 0x0f2e,
+ 0x8de7, 0x25b5,
+ 0x8de8, 0x0f28,
+ 0x8de9, 0x25b2,
+ 0x8dea, 0x0f2c,
+ 0x8deb, 0x25b7,
+ 0x8dec, 0x25ae,
+ 0x8dee, 0x25b0,
+ 0x8def, 0x0f29,
+ 0x8df0, 0x25ac,
+ 0x8df1, 0x25af,
+ 0x8df2, 0x25b6,
+ 0x8df3, 0x0f2a,
+ 0x8df4, 0x25b8,
+ 0x8dfa, 0x0f2b,
+ 0x8dfc, 0x10bd,
+ 0x8dfd, 0x2814,
+ 0x8dfe, 0x281a,
+ 0x8dff, 0x2812,
+ 0x8e00, 0x281b,
+ 0x8e01, 0x3f85,
+ 0x8e02, 0x2811,
+ 0x8e03, 0x2816,
+ 0x8e04, 0x281c,
+ 0x8e05, 0x2819,
+ 0x8e06, 0x2818,
+ 0x8e07, 0x2817,
+ 0x8e09, 0x2810,
+ 0x8e0a, 0x2815,
+ 0x8e0d, 0x2813,
+ 0x8e0e, 0x3e5e,
+ 0x8e0f, 0x1238,
+ 0x8e10, 0x1235,
+ 0x8e11, 0x2a69,
+ 0x8e12, 0x2a6e,
+ 0x8e13, 0x2a70,
+ 0x8e14, 0x2a6d,
+ 0x8e15, 0x2a66,
+ 0x8e16, 0x2a68,
+ 0x8e17, 0x2a72,
+ 0x8e18, 0x2a6f,
+ 0x8e19, 0x2a6a,
+ 0x8e1a, 0x2a73,
+ 0x8e1b, 0x2a67,
+ 0x8e1c, 0x2a71,
+ 0x8e1d, 0x1236,
+ 0x8e1e, 0x123c,
+ 0x8e1f, 0x123a,
+ 0x8e20, 0x2a61,
+ 0x8e21, 0x123b,
+ 0x8e22, 0x1237,
+ 0x8e23, 0x2a62,
+ 0x8e24, 0x2a64,
+ 0x8e25, 0x2a63,
+ 0x8e26, 0x2a6b,
+ 0x8e28, 0x3f88,
+ 0x8e29, 0x1239,
+ 0x8e2a, 0x3bb4,
+ 0x8e2b, 0x1234,
+ 0x8e2d, 0x3eab,
+ 0x8e2e, 0x2a65,
+ 0x8e30, 0x2cab,
+ 0x8e31, 0x1362,
+ 0x8e33, 0x2ca2,
+ 0x8e34, 0x1363,
+ 0x8e35, 0x1366,
+ 0x8e36, 0x2ca7,
+ 0x8e38, 0x2ca4,
+ 0x8e39, 0x1365,
+ 0x8e3a, 0x4784,
+ 0x8e3c, 0x2ca8,
+ 0x8e3e, 0x2ca3,
+ 0x8e3f, 0x2cac,
+ 0x8e40, 0x2ca5,
+ 0x8e41, 0x2caa,
+ 0x8e42, 0x1364,
+ 0x8e44, 0x1361,
+ 0x8e45, 0x2ca6,
+ 0x8e46, 0x4312,
+ 0x8e47, 0x2e7a,
+ 0x8e48, 0x148b,
+ 0x8e49, 0x1489,
+ 0x8e4a, 0x148c,
+ 0x8e4b, 0x148a,
+ 0x8e4c, 0x2e79,
+ 0x8e4d, 0x2e76,
+ 0x8e4e, 0x2e75,
+ 0x8e4f, 0x3f83,
+ 0x8e50, 0x2e78,
+ 0x8e53, 0x2e77,
+ 0x8e54, 0x2ff6,
+ 0x8e55, 0x1535,
+ 0x8e56, 0x2fed,
+ 0x8e57, 0x2fec,
+ 0x8e59, 0x1530,
+ 0x8e5a, 0x2ff2,
+ 0x8e5b, 0x2ff1,
+ 0x8e5c, 0x2fe9,
+ 0x8e5d, 0x2ff4,
+ 0x8e5e, 0x2fee,
+ 0x8e5f, 0x1534,
+ 0x8e60, 0x2feb,
+ 0x8e61, 0x2ff3,
+ 0x8e62, 0x2fea,
+ 0x8e63, 0x1531,
+ 0x8e64, 0x1533,
+ 0x8e65, 0x2fef,
+ 0x8e66, 0x1532,
+ 0x8e67, 0x2ff0,
+ 0x8e68, 0x434d,
+ 0x8e69, 0x2ff5,
+ 0x8e6a, 0x313d,
+ 0x8e6c, 0x15d3,
+ 0x8e6d, 0x313a,
+ 0x8e6f, 0x313e,
+ 0x8e71, 0x43e7,
+ 0x8e72, 0x15d0,
+ 0x8e73, 0x313c,
+ 0x8e74, 0x15d5,
+ 0x8e75, 0x3f89,
+ 0x8e76, 0x15d2,
+ 0x8e77, 0x3f7f,
+ 0x8e78, 0x313b,
+ 0x8e7a, 0x15d4,
+ 0x8e7b, 0x313f,
+ 0x8e7c, 0x15cf,
+ 0x8e7e, 0x4324,
+ 0x8e80, 0x3e57,
+ 0x8e81, 0x164d,
+ 0x8e82, 0x164f,
+ 0x8e84, 0x3240,
+ 0x8e85, 0x164e,
+ 0x8e86, 0x323e,
+ 0x8e87, 0x15d1,
+ 0x8e88, 0x323f,
+ 0x8e89, 0x164c,
+ 0x8e8a, 0x1693,
+ 0x8e8b, 0x1695,
+ 0x8e8c, 0x331a,
+ 0x8e8d, 0x1694,
+ 0x8e8e, 0x3319,
+ 0x8e90, 0x33c1,
+ 0x8e91, 0x16db,
+ 0x8e92, 0x33c0,
+ 0x8e93, 0x16dc,
+ 0x8e94, 0x33be,
+ 0x8e95, 0x33bd,
+ 0x8e96, 0x33c2,
+ 0x8e98, 0x3443,
+ 0x8e9a, 0x33bf,
+ 0x8e9d, 0x34a1,
+ 0x8e9e, 0x349e,
+ 0x8ea1, 0x1749,
+ 0x8ea3, 0x34eb,
+ 0x8ea4, 0x34ea,
+ 0x8ea5, 0x34e9,
+ 0x8ea6, 0x350a,
+ 0x8ea7, 0x3bb5,
+ 0x8ea8, 0x3537,
+ 0x8ea9, 0x3524,
+ 0x8eaa, 0x175b,
+ 0x8eab, 0x0512,
+ 0x8eac, 0x09cf,
+ 0x8ead, 0x385e,
+ 0x8eb0, 0x43e9,
+ 0x8eb2, 0x0f2f,
+ 0x8eb6, 0x385f,
+ 0x8eba, 0x123d,
+ 0x8ebc, 0x38a0,
+ 0x8ebd, 0x2cad,
+ 0x8ec0, 0x1536,
+ 0x8ec2, 0x3140,
+ 0x8ec3, 0x3860,
+ 0x8ec9, 0x3525,
+ 0x8eca, 0x0513,
+ 0x8ecb, 0x068d,
+ 0x8ecc, 0x0810,
+ 0x8ecd, 0x080f,
+ 0x8ece, 0x4788,
+ 0x8ecf, 0x09d2,
+ 0x8ed1, 0x1e13,
+ 0x8ed2, 0x09d0,
+ 0x8ed3, 0x1e14,
+ 0x8ed4, 0x09d1,
+ 0x8ed7, 0x207d,
+ 0x8ed8, 0x2079,
+ 0x8eda, 0x3dbe,
+ 0x8edb, 0x0bb3,
+ 0x8edc, 0x207c,
+ 0x8edd, 0x207b,
+ 0x8ede, 0x207a,
+ 0x8edf, 0x0bb4,
+ 0x8ee0, 0x207e,
+ 0x8ee2, 0x4789,
+ 0x8ee4, 0x478a,
+ 0x8ee5, 0x2315,
+ 0x8ee6, 0x2313,
+ 0x8ee7, 0x2317,
+ 0x8ee9, 0x231e,
+ 0x8eeb, 0x231a,
+ 0x8eec, 0x231c,
+ 0x8eed, 0x478b,
+ 0x8eee, 0x2314,
+ 0x8eef, 0x230f,
+ 0x8ef1, 0x231b,
+ 0x8ef2, 0x478c,
+ 0x8ef4, 0x231d,
+ 0x8ef5, 0x2316,
+ 0x8ef6, 0x2319,
+ 0x8ef7, 0x2310,
+ 0x8ef8, 0x0d7f,
+ 0x8ef9, 0x2312,
+ 0x8efa, 0x2311,
+ 0x8efb, 0x0d7e,
+ 0x8efc, 0x0d80,
+ 0x8efe, 0x0f32,
+ 0x8eff, 0x25ba,
+ 0x8f00, 0x25bc,
+ 0x8f01, 0x25bb,
+ 0x8f02, 0x25c0,
+ 0x8f03, 0x0f30,
+ 0x8f05, 0x25bd,
+ 0x8f06, 0x25b9,
+ 0x8f07, 0x25be,
+ 0x8f09, 0x0f31,
+ 0x8f0a, 0x0f33,
+ 0x8f0b, 0x25c1,
+ 0x8f0d, 0x2820,
+ 0x8f0e, 0x281f,
+ 0x8f10, 0x281d,
+ 0x8f12, 0x10bf,
+ 0x8f13, 0x10c1,
+ 0x8f14, 0x10be,
+ 0x8f15, 0x10c0,
+ 0x8f16, 0x2a7a,
+ 0x8f18, 0x2a76,
+ 0x8f19, 0x3862,
+ 0x8f1a, 0x2a77,
+ 0x8f1b, 0x123f,
+ 0x8f1c, 0x1244,
+ 0x8f1d, 0x123e,
+ 0x8f1e, 0x1245,
+ 0x8f1f, 0x1240,
+ 0x8f20, 0x2a78,
+ 0x8f23, 0x2a79,
+ 0x8f24, 0x2a75,
+ 0x8f25, 0x1246,
+ 0x8f26, 0x1242,
+ 0x8f29, 0x1241,
+ 0x8f2a, 0x1243,
+ 0x8f2c, 0x2a74,
+ 0x8f2d, 0x3863,
+ 0x8f2e, 0x2caf,
+ 0x8f2f, 0x1368,
+ 0x8f30, 0x3bb7,
+ 0x8f32, 0x2cb1,
+ 0x8f33, 0x136a,
+ 0x8f34, 0x2cb4,
+ 0x8f35, 0x2cb0,
+ 0x8f36, 0x2cae,
+ 0x8f37, 0x2cb3,
+ 0x8f38, 0x1369,
+ 0x8f39, 0x2cb2,
+ 0x8f3b, 0x1367,
+ 0x8f3e, 0x148e,
+ 0x8f3f, 0x1491,
+ 0x8f40, 0x2e7c,
+ 0x8f41, 0x3d07,
+ 0x8f42, 0x148f,
+ 0x8f43, 0x2e7b,
+ 0x8f44, 0x148d,
+ 0x8f45, 0x1490,
+ 0x8f46, 0x2ff7,
+ 0x8f49, 0x1537,
+ 0x8f4a, 0x3bb8,
+ 0x8f4b, 0x2ffa,
+ 0x8f4d, 0x1538,
+ 0x8f4e, 0x15d7,
+ 0x8f4f, 0x3143,
+ 0x8f51, 0x3142,
+ 0x8f52, 0x3141,
+ 0x8f53, 0x3145,
+ 0x8f54, 0x15d6,
+ 0x8f55, 0x3244,
+ 0x8f56, 0x3242,
+ 0x8f58, 0x3245,
+ 0x8f59, 0x3241,
+ 0x8f5a, 0x3246,
+ 0x8f5b, 0x331c,
+ 0x8f5c, 0x3f31,
+ 0x8f5d, 0x331d,
+ 0x8f5e, 0x331b,
+ 0x8f5f, 0x1696,
+ 0x8f60, 0x33c4,
+ 0x8f61, 0x16dd,
+ 0x8f62, 0x33c5,
+ 0x8f63, 0x3445,
+ 0x8f64, 0x3444,
+ 0x8f66, 0x4569,
+ 0x8f6e, 0x456b,
+ 0x8f93, 0x4732,
+ 0x8f9b, 0x0514,
+ 0x8f9c, 0x0d81,
+ 0x8f9f, 0x0f34,
+ 0x8fa0, 0x3d94,
+ 0x8fa3, 0x10c2,
+ 0x8fa5, 0x3866,
+ 0x8fa6, 0x136c,
+ 0x8fa8, 0x136b,
+ 0x8fad, 0x15d8,
+ 0x8fae, 0x162f,
+ 0x8faf, 0x1697,
+ 0x8fb0, 0x0515,
+ 0x8fb1, 0x09d3,
+ 0x8fb2, 0x0f35,
+ 0x8fb3, 0x386a,
+ 0x8fb4, 0x3146,
+ 0x8fb5, 0x0230,
+ 0x8fb6, 0x47d3,
+ 0x8fb7, 0x43fd,
+ 0x8fb8, 0x42f6,
+ 0x8fb9, 0x48c9,
+ 0x8fba, 0x48c7,
+ 0x8fbb, 0x3d6b,
+ 0x8fbe, 0x48c6,
+ 0x8fbf, 0x18e9,
+ 0x8fc1, 0x478d,
+ 0x8fc2, 0x0516,
+ 0x8fc4, 0x0519,
+ 0x8fc5, 0x0518,
+ 0x8fc6, 0x0517,
+ 0x8fc9, 0x18e8,
+ 0x8fca, 0x478e,
+ 0x8fcb, 0x1a4a,
+ 0x8fcc, 0x478f,
+ 0x8fcd, 0x1a4c,
+ 0x8fce, 0x068e,
+ 0x8fd0, 0x48ae,
+ 0x8fd1, 0x0690,
+ 0x8fd2, 0x1a49,
+ 0x8fd3, 0x1a4b,
+ 0x8fd4, 0x068f,
+ 0x8fd5, 0x1a4e,
+ 0x8fd6, 0x1a4d,
+ 0x8fd7, 0x1a4f,
+ 0x8fda, 0x3fcb,
+ 0x8fe0, 0x1c0a,
+ 0x8fe1, 0x1c08,
+ 0x8fe2, 0x0813,
+ 0x8fe3, 0x1c07,
+ 0x8fe4, 0x0818,
+ 0x8fe5, 0x0815,
+ 0x8fe6, 0x0812,
+ 0x8fe8, 0x0819,
+ 0x8fea, 0x0814,
+ 0x8feb, 0x0817,
+ 0x8fed, 0x0816,
+ 0x8fee, 0x1c09,
+ 0x8ff0, 0x0811,
+ 0x8ff4, 0x09d9,
+ 0x8ff5, 0x1e16,
+ 0x8ff6, 0x1e1c,
+ 0x8ff7, 0x09d6,
+ 0x8ff8, 0x09dd,
+ 0x8ff9, 0x3871,
+ 0x8ffa, 0x09d8,
+ 0x8ffb, 0x1e19,
+ 0x8ffc, 0x1e1b,
+ 0x8ffd, 0x09db,
+ 0x8ffe, 0x1e15,
+ 0x8fff, 0x1e18,
+ 0x9000, 0x09d7,
+ 0x9001, 0x09d4,
+ 0x9002, 0x1e17,
+ 0x9003, 0x09da,
+ 0x9004, 0x1e1a,
+ 0x9005, 0x09dc,
+ 0x9006, 0x09d5,
+ 0x9008, 0x3ee0,
+ 0x900b, 0x2081,
+ 0x900c, 0x2084,
+ 0x900d, 0x0bb6,
+ 0x900f, 0x0bc0,
+ 0x9010, 0x0bbc,
+ 0x9011, 0x2082,
+ 0x9012, 0x3e4e,
+ 0x9014, 0x0bc4,
+ 0x9015, 0x0bbd,
+ 0x9016, 0x0bc2,
+ 0x9017, 0x0bb8,
+ 0x9019, 0x0bb5,
+ 0x901a, 0x0bb7,
+ 0x901b, 0x0bc3,
+ 0x901c, 0x2083,
+ 0x901d, 0x0bbb,
+ 0x901e, 0x0bbe,
+ 0x901f, 0x0bba,
+ 0x9020, 0x0bbf,
+ 0x9021, 0x2085,
+ 0x9022, 0x0bc1,
+ 0x9023, 0x0bb9,
+ 0x9024, 0x2080,
+ 0x902d, 0x231f,
+ 0x902e, 0x0d82,
+ 0x902f, 0x2321,
+ 0x9031, 0x0d84,
+ 0x9032, 0x0d86,
+ 0x9033, 0x4790,
+ 0x9034, 0x2320,
+ 0x9035, 0x0d83,
+ 0x9036, 0x0d87,
+ 0x9037, 0x3876,
+ 0x9038, 0x0d85,
+ 0x903c, 0x0f3b,
+ 0x903d, 0x25c6,
+ 0x903e, 0x0f43,
+ 0x903f, 0x25c3,
+ 0x9041, 0x0f44,
+ 0x9042, 0x0f39,
+ 0x9044, 0x25c4,
+ 0x9047, 0x0f3e,
+ 0x9049, 0x25c5,
+ 0x904a, 0x0f37,
+ 0x904b, 0x0f36,
+ 0x904c, 0x3f10,
+ 0x904d, 0x0f41,
+ 0x904e, 0x0f40,
+ 0x904f, 0x0f3f,
+ 0x9050, 0x0f3d,
+ 0x9051, 0x0f42,
+ 0x9052, 0x25c2,
+ 0x9053, 0x0f38,
+ 0x9054, 0x0f3a,
+ 0x9055, 0x0f3c,
+ 0x9056, 0x3dd2,
+ 0x9058, 0x10c4,
+ 0x9059, 0x10c7,
+ 0x905b, 0x10cb,
+ 0x905c, 0x10c5,
+ 0x905d, 0x10ca,
+ 0x905e, 0x10c8,
+ 0x9060, 0x10c3,
+ 0x9061, 0x3879,
+ 0x9062, 0x10c9,
+ 0x9063, 0x10c6,
+ 0x9064, 0x3c68,
+ 0x9067, 0x2a7f,
+ 0x9068, 0x1249,
+ 0x9069, 0x1247,
+ 0x906b, 0x2a80,
+ 0x906c, 0x3d60,
+ 0x906d, 0x124a,
+ 0x906e, 0x1248,
+ 0x906f, 0x2a7e,
+ 0x9070, 0x2a7d,
+ 0x9072, 0x1370,
+ 0x9073, 0x2a7c,
+ 0x9074, 0x136e,
+ 0x9075, 0x136d,
+ 0x9076, 0x2cb5,
+ 0x9077, 0x124b,
+ 0x9078, 0x136f,
+ 0x9079, 0x2cb6,
+ 0x907a, 0x1372,
+ 0x907b, 0x2cb7,
+ 0x907c, 0x1371,
+ 0x907d, 0x1493,
+ 0x907e, 0x2e7e,
+ 0x907f, 0x1492,
+ 0x9080, 0x1497,
+ 0x9081, 0x1495,
+ 0x9083, 0x153a,
+ 0x9084, 0x1494,
+ 0x9085, 0x2e7d,
+ 0x9086, 0x2cb8,
+ 0x9087, 0x1539,
+ 0x9088, 0x153b,
+ 0x908a, 0x15d9,
+ 0x908d, 0x3247,
+ 0x908f, 0x170c,
+ 0x9090, 0x170b,
+ 0x9091, 0x051b,
+ 0x9094, 0x181e,
+ 0x9095, 0x09de,
+ 0x9097, 0x181b,
+ 0x9099, 0x181a,
+ 0x909b, 0x181d,
+ 0x909e, 0x18ed,
+ 0x909f, 0x18ea,
+ 0x90a0, 0x18ef,
+ 0x90a1, 0x18eb,
+ 0x90a2, 0x051c,
+ 0x90a3, 0x051f,
+ 0x90a5, 0x18ec,
+ 0x90a6, 0x051e,
+ 0x90a7, 0x18ee,
+ 0x90a8, 0x387c,
+ 0x90aa, 0x051d,
+ 0x90ae, 0x3880,
+ 0x90af, 0x1a52,
+ 0x90b0, 0x1a54,
+ 0x90b1, 0x0693,
+ 0x90b2, 0x1a50,
+ 0x90b3, 0x1a53,
+ 0x90b4, 0x1a51,
+ 0x90b5, 0x0691,
+ 0x90b6, 0x0694,
+ 0x90b8, 0x0692,
+ 0x90bb, 0x3bc4,
+ 0x90bd, 0x1c0c,
+ 0x90be, 0x1c10,
+ 0x90bf, 0x1c0d,
+ 0x90c1, 0x081c,
+ 0x90c3, 0x081d,
+ 0x90c4, 0x387e,
+ 0x90c5, 0x1c0f,
+ 0x90c7, 0x1c11,
+ 0x90c8, 0x1c13,
+ 0x90ca, 0x081a,
+ 0x90cb, 0x1c12,
+ 0x90ce, 0x081b,
+ 0x90d4, 0x208c,
+ 0x90d5, 0x1c0e,
+ 0x90d6, 0x1e1d,
+ 0x90d7, 0x1e26,
+ 0x90d8, 0x1e24,
+ 0x90d9, 0x1e1f,
+ 0x90db, 0x1e25,
+ 0x90dc, 0x1e27,
+ 0x90dd, 0x09e0,
+ 0x90df, 0x1e22,
+ 0x90e0, 0x1e1e,
+ 0x90e1, 0x09df,
+ 0x90e2, 0x09e1,
+ 0x90e3, 0x1e21,
+ 0x90e4, 0x1e28,
+ 0x90e5, 0x1e23,
+ 0x90e8, 0x0bc5,
+ 0x90e9, 0x208f,
+ 0x90ea, 0x2087,
+ 0x90eb, 0x208d,
+ 0x90ed, 0x0bc6,
+ 0x90ef, 0x2086,
+ 0x90f0, 0x2088,
+ 0x90f1, 0x1c0b,
+ 0x90f2, 0x208a,
+ 0x90f4, 0x2089,
+ 0x90f5, 0x0d89,
+ 0x90f9, 0x2328,
+ 0x90fa, 0x2cb9,
+ 0x90fb, 0x2329,
+ 0x90fc, 0x2326,
+ 0x90fd, 0x0bc7,
+ 0x90fe, 0x0d8b,
+ 0x90ff, 0x2325,
+ 0x9100, 0x232b,
+ 0x9101, 0x232a,
+ 0x9102, 0x0d88,
+ 0x9103, 0x232e,
+ 0x9104, 0x2324,
+ 0x9105, 0x232d,
+ 0x9106, 0x2322,
+ 0x9107, 0x232c,
+ 0x9108, 0x2327,
+ 0x9109, 0x0d8a,
+ 0x910b, 0x25cd,
+ 0x910d, 0x25c8,
+ 0x910e, 0x25ce,
+ 0x910f, 0x25c9,
+ 0x9110, 0x25c7,
+ 0x9111, 0x25ca,
+ 0x9112, 0x0f45,
+ 0x9114, 0x25cc,
+ 0x9116, 0x25cb,
+ 0x9117, 0x0f46,
+ 0x9118, 0x10cd,
+ 0x9119, 0x10cc,
+ 0x911a, 0x2827,
+ 0x911b, 0x282a,
+ 0x911c, 0x2822,
+ 0x911d, 0x2826,
+ 0x911e, 0x10ce,
+ 0x911f, 0x2825,
+ 0x9120, 0x2823,
+ 0x9121, 0x2829,
+ 0x9122, 0x2824,
+ 0x9123, 0x2821,
+ 0x9124, 0x2828,
+ 0x9126, 0x2a86,
+ 0x9127, 0x124e,
+ 0x9128, 0x2ffb,
+ 0x9129, 0x2a83,
+ 0x912b, 0x2a82,
+ 0x912c, 0x2323,
+ 0x912d, 0x124d,
+ 0x912e, 0x2a87,
+ 0x912f, 0x2a81,
+ 0x9130, 0x124c,
+ 0x9131, 0x124f,
+ 0x9132, 0x2a85,
+ 0x9133, 0x2cba,
+ 0x9134, 0x1373,
+ 0x9135, 0x2cbb,
+ 0x9138, 0x2e7f,
+ 0x9139, 0x1498,
+ 0x913a, 0x2ffc,
+ 0x913e, 0x2ffe,
+ 0x913f, 0x3148,
+ 0x9140, 0x3147,
+ 0x9141, 0x3249,
+ 0x9143, 0x3248,
+ 0x9144, 0x331f,
+ 0x9146, 0x331e,
+ 0x9147, 0x33c6,
+ 0x9148, 0x16de,
+ 0x9149, 0x0520,
+ 0x914a, 0x081f,
+ 0x914b, 0x081e,
+ 0x914c, 0x09e4,
+ 0x914d, 0x09e3,
+ 0x914e, 0x1e2a,
+ 0x9150, 0x1e29,
+ 0x9151, 0x3f49,
+ 0x9152, 0x09e2,
+ 0x9153, 0x2093,
+ 0x9155, 0x2094,
+ 0x9156, 0x2090,
+ 0x9157, 0x0bc8,
+ 0x9158, 0x2091,
+ 0x9159, 0x3f45,
+ 0x915a, 0x2092,
+ 0x915c, 0x3f47,
+ 0x915e, 0x43eb,
+ 0x915f, 0x2331,
+ 0x9160, 0x2333,
+ 0x9161, 0x232f,
+ 0x9162, 0x2332,
+ 0x9163, 0x0d8c,
+ 0x9164, 0x2330,
+ 0x9165, 0x0d8d,
+ 0x9167, 0x3882,
+ 0x9168, 0x23e2,
+ 0x9169, 0x0f49,
+ 0x916a, 0x0f48,
+ 0x916c, 0x0f47,
+ 0x916e, 0x25cf,
+ 0x9170, 0x3eb8,
+ 0x9172, 0x282c,
+ 0x9173, 0x282e,
+ 0x9174, 0x10d2,
+ 0x9175, 0x10cf,
+ 0x9176, 0x3e9b,
+ 0x9177, 0x10d1,
+ 0x9178, 0x10d0,
+ 0x9179, 0x282d,
+ 0x917a, 0x282b,
+ 0x917c, 0x3f6f,
+ 0x9180, 0x2a8e,
+ 0x9181, 0x2a8b,
+ 0x9183, 0x1253,
+ 0x9184, 0x2a8d,
+ 0x9185, 0x2a88,
+ 0x9187, 0x1250,
+ 0x9189, 0x1251,
+ 0x918a, 0x2a8a,
+ 0x918b, 0x1252,
+ 0x918c, 0x43ec,
+ 0x918d, 0x2cc0,
+ 0x918e, 0x3f4e,
+ 0x918f, 0x2cc1,
+ 0x9190, 0x2cbe,
+ 0x9192, 0x1374,
+ 0x9193, 0x2cbd,
+ 0x9199, 0x2e83,
+ 0x919a, 0x2e80,
+ 0x919b, 0x2e82,
+ 0x919c, 0x149b,
+ 0x919d, 0x2e86,
+ 0x919e, 0x149a,
+ 0x919f, 0x2e84,
+ 0x91a0, 0x2e87,
+ 0x91a1, 0x2e85,
+ 0x91a2, 0x2e81,
+ 0x91a3, 0x1499,
+ 0x91a5, 0x3000,
+ 0x91a7, 0x3001,
+ 0x91a8, 0x2fff,
+ 0x91a9, 0x3883,
+ 0x91aa, 0x3003,
+ 0x91ab, 0x153c,
+ 0x91ad, 0x314a,
+ 0x91ae, 0x15dc,
+ 0x91af, 0x3002,
+ 0x91b0, 0x3149,
+ 0x91b1, 0x15db,
+ 0x91b2, 0x324c,
+ 0x91b4, 0x1650,
+ 0x91b5, 0x324b,
+ 0x91b6, 0x45ef,
+ 0x91b7, 0x324a,
+ 0x91b9, 0x3321,
+ 0x91ba, 0x1698,
+ 0x91bb, 0x3bc8,
+ 0x91bc, 0x3446,
+ 0x91bd, 0x34a3,
+ 0x91be, 0x34a2,
+ 0x91c0, 0x1730,
+ 0x91c1, 0x174a,
+ 0x91c2, 0x34a4,
+ 0x91c3, 0x350b,
+ 0x91c4, 0x3884,
+ 0x91c5, 0x175c,
+ 0x91c6, 0x0521,
+ 0x91c7, 0x0695,
+ 0x91c9, 0x0f4a,
+ 0x91cb, 0x1651,
+ 0x91cc, 0x0522,
+ 0x91cd, 0x0820,
+ 0x91ce, 0x0bc9,
+ 0x91cf, 0x0d8e,
+ 0x91d0, 0x153e,
+ 0x91d1, 0x0696,
+ 0x91d3, 0x1c15,
+ 0x91d4, 0x1c14,
+ 0x91d5, 0x1e2c,
+ 0x91d6, 0x415e,
+ 0x91d7, 0x09e7,
+ 0x91d8, 0x09e5,
+ 0x91d9, 0x09e9,
+ 0x91da, 0x1e2e,
+ 0x91dc, 0x09e8,
+ 0x91dd, 0x09e6,
+ 0x91df, 0x453a,
+ 0x91e2, 0x1e2d,
+ 0x91e3, 0x0bcc,
+ 0x91e4, 0x209a,
+ 0x91e5, 0x3c06,
+ 0x91e6, 0x0bcb,
+ 0x91e7, 0x0bcd,
+ 0x91e8, 0x209f,
+ 0x91e9, 0x0bcf,
+ 0x91ea, 0x209c,
+ 0x91ec, 0x2095,
+ 0x91ed, 0x0bce,
+ 0x91ee, 0x20a0,
+ 0x91f1, 0x2097,
+ 0x91f3, 0x2098,
+ 0x91f4, 0x2096,
+ 0x91f5, 0x0bca,
+ 0x91f7, 0x209e,
+ 0x91f8, 0x2099,
+ 0x91f9, 0x209b,
+ 0x91fa, 0x3af8,
+ 0x91fd, 0x233f,
+ 0x91fe, 0x382e,
+ 0x91ff, 0x233e,
+ 0x9200, 0x233c,
+ 0x9201, 0x2334,
+ 0x9202, 0x2343,
+ 0x9203, 0x2337,
+ 0x9204, 0x2341,
+ 0x9205, 0x2348,
+ 0x9206, 0x2340,
+ 0x9207, 0x0d96,
+ 0x9208, 0x3eb9,
+ 0x9209, 0x0d92,
+ 0x920a, 0x2335,
+ 0x920c, 0x233b,
+ 0x920d, 0x0d94,
+ 0x920e, 0x3888,
+ 0x920f, 0x233a,
+ 0x9210, 0x0d95,
+ 0x9211, 0x0d97,
+ 0x9212, 0x233d,
+ 0x9213, 0x4793,
+ 0x9214, 0x0d8f,
+ 0x9216, 0x2349,
+ 0x9217, 0x2347,
+ 0x9219, 0x2346,
+ 0x921a, 0x2338,
+ 0x921c, 0x2344,
+ 0x921e, 0x0d93,
+ 0x9223, 0x0d91,
+ 0x9224, 0x2345,
+ 0x9225, 0x2336,
+ 0x9226, 0x2339,
+ 0x9227, 0x2342,
+ 0x9228, 0x4795,
+ 0x922a, 0x3c0e,
+ 0x922b, 0x3ba6,
+ 0x922d, 0x2851,
+ 0x922e, 0x25da,
+ 0x9230, 0x25d3,
+ 0x9231, 0x25e6,
+ 0x9232, 0x25ef,
+ 0x9233, 0x25d6,
+ 0x9234, 0x0f55,
+ 0x9235, 0x3b26,
+ 0x9236, 0x25e3,
+ 0x9237, 0x0f4b,
+ 0x9238, 0x0f4d,
+ 0x9239, 0x0f59,
+ 0x923a, 0x25d4,
+ 0x923c, 0x41d2,
+ 0x923d, 0x0f4e,
+ 0x923e, 0x0f50,
+ 0x923f, 0x0f5a,
+ 0x9240, 0x0f4f,
+ 0x9241, 0x388a,
+ 0x9244, 0x389a,
+ 0x9245, 0x0f58,
+ 0x9246, 0x25dc,
+ 0x9248, 0x25d1,
+ 0x9249, 0x0f56,
+ 0x924a, 0x25db,
+ 0x924b, 0x0f52,
+ 0x924c, 0x25ed,
+ 0x924d, 0x0f57,
+ 0x924e, 0x25eb,
+ 0x924f, 0x25df,
+ 0x9250, 0x25e9,
+ 0x9251, 0x0f54,
+ 0x9252, 0x25d2,
+ 0x9253, 0x25ec,
+ 0x9254, 0x25e7,
+ 0x9255, 0x3e47,
+ 0x9256, 0x25ee,
+ 0x9257, 0x0f4c,
+ 0x9258, 0x4796,
+ 0x925a, 0x0f5b,
+ 0x925b, 0x0f51,
+ 0x925d, 0x3a03,
+ 0x925e, 0x25d8,
+ 0x925f, 0x3ce0,
+ 0x9260, 0x25e0,
+ 0x9261, 0x25e4,
+ 0x9262, 0x388b,
+ 0x9263, 0x25e8,
+ 0x9264, 0x0f53,
+ 0x9265, 0x25d7,
+ 0x9266, 0x25d5,
+ 0x9267, 0x25e1,
+ 0x926b, 0x4797,
+ 0x926c, 0x25de,
+ 0x926d, 0x25dd,
+ 0x926e, 0x3d05,
+ 0x926f, 0x25e2,
+ 0x9270, 0x25e5,
+ 0x9272, 0x25ea,
+ 0x9276, 0x2831,
+ 0x9277, 0x3c64,
+ 0x9278, 0x10d3,
+ 0x9279, 0x283b,
+ 0x927a, 0x2833,
+ 0x927b, 0x10d9,
+ 0x927c, 0x10dd,
+ 0x927d, 0x2844,
+ 0x927e, 0x284c,
+ 0x927f, 0x283d,
+ 0x9280, 0x10d5,
+ 0x9281, 0x3e01,
+ 0x9282, 0x2841,
+ 0x9283, 0x25d9,
+ 0x9284, 0x3cb9,
+ 0x9285, 0x10d6,
+ 0x9286, 0x2848,
+ 0x9287, 0x284d,
+ 0x9288, 0x2845,
+ 0x9289, 0x3ab5,
+ 0x928a, 0x2847,
+ 0x928b, 0x2850,
+ 0x928c, 0x2849,
+ 0x928d, 0x2837,
+ 0x928e, 0x2840,
+ 0x928f, 0x46bd,
+ 0x9291, 0x10de,
+ 0x9293, 0x10da,
+ 0x9294, 0x2835,
+ 0x9295, 0x2842,
+ 0x9296, 0x10d8,
+ 0x9297, 0x283c,
+ 0x9298, 0x10d7,
+ 0x9299, 0x284a,
+ 0x929a, 0x2839,
+ 0x929b, 0x2832,
+ 0x929c, 0x10db,
+ 0x929d, 0x284f,
+ 0x92a0, 0x2834,
+ 0x92a1, 0x2846,
+ 0x92a2, 0x2843,
+ 0x92a3, 0x283e,
+ 0x92a4, 0x2830,
+ 0x92a5, 0x282f,
+ 0x92a6, 0x2838,
+ 0x92a7, 0x284b,
+ 0x92a8, 0x10dc,
+ 0x92a9, 0x284e,
+ 0x92aa, 0x2836,
+ 0x92ab, 0x283a,
+ 0x92ac, 0x10d4,
+ 0x92ae, 0x4799,
+ 0x92b1, 0x4798,
+ 0x92b2, 0x125f,
+ 0x92b3, 0x125a,
+ 0x92b4, 0x2ab0,
+ 0x92b5, 0x2aac,
+ 0x92b6, 0x2a94,
+ 0x92b7, 0x1256,
+ 0x92b9, 0x36e9,
+ 0x92ba, 0x3bf5,
+ 0x92bb, 0x1255,
+ 0x92bc, 0x125b,
+ 0x92be, 0x3c60,
+ 0x92bf, 0x479a,
+ 0x92c0, 0x2a92,
+ 0x92c1, 0x1259,
+ 0x92c2, 0x2a9e,
+ 0x92c3, 0x2a90,
+ 0x92c5, 0x1254,
+ 0x92c6, 0x2aaf,
+ 0x92c7, 0x125d,
+ 0x92c8, 0x2aa1,
+ 0x92c9, 0x2aa6,
+ 0x92ca, 0x2aa0,
+ 0x92cb, 0x2cd3,
+ 0x92cc, 0x2a9c,
+ 0x92cd, 0x2aa4,
+ 0x92ce, 0x2aa2,
+ 0x92cf, 0x2a95,
+ 0x92d0, 0x2a8f,
+ 0x92d1, 0x2aaa,
+ 0x92d2, 0x125c,
+ 0x92d3, 0x2aab,
+ 0x92d4, 0x3861,
+ 0x92d5, 0x2aa5,
+ 0x92d7, 0x2a9a,
+ 0x92d8, 0x2a98,
+ 0x92d9, 0x2a93,
+ 0x92db, 0x400c,
+ 0x92dd, 0x2a9b,
+ 0x92de, 0x2aa8,
+ 0x92df, 0x2a97,
+ 0x92e0, 0x2aa7,
+ 0x92e1, 0x2aad,
+ 0x92e3, 0x479b,
+ 0x92e4, 0x1258,
+ 0x92e5, 0x3ca2,
+ 0x92e6, 0x2aa3,
+ 0x92e7, 0x2aa9,
+ 0x92e8, 0x2a9f,
+ 0x92e9, 0x2a99,
+ 0x92ea, 0x1257,
+ 0x92eb, 0x479c,
+ 0x92ec, 0x3964,
+ 0x92ee, 0x283f,
+ 0x92ef, 0x2a9d,
+ 0x92f0, 0x125e,
+ 0x92f1, 0x2a96,
+ 0x92f2, 0x3ab2,
+ 0x92f3, 0x479d,
+ 0x92f6, 0x3c04,
+ 0x92f7, 0x2cd8,
+ 0x92f8, 0x1377,
+ 0x92f9, 0x2cd7,
+ 0x92fa, 0x2cd5,
+ 0x92fb, 0x2ce7,
+ 0x92fc, 0x137b,
+ 0x92fd, 0x479f,
+ 0x92fe, 0x2ce4,
+ 0x92ff, 0x2cdc,
+ 0x9300, 0x2ce6,
+ 0x9301, 0x2cce,
+ 0x9302, 0x2cda,
+ 0x9303, 0x3867,
+ 0x9304, 0x137d,
+ 0x9306, 0x2cc6,
+ 0x9307, 0x3b11,
+ 0x9308, 0x2cc4,
+ 0x9309, 0x2ce5,
+ 0x930b, 0x2ce3,
+ 0x930c, 0x2ce2,
+ 0x930d, 0x2cd2,
+ 0x930e, 0x2cd1,
+ 0x930f, 0x2cc7,
+ 0x9310, 0x137f,
+ 0x9312, 0x2ccd,
+ 0x9313, 0x2cd6,
+ 0x9314, 0x2ce1,
+ 0x9315, 0x1382,
+ 0x9316, 0x2ce8,
+ 0x9318, 0x14a3,
+ 0x9319, 0x1384,
+ 0x931a, 0x137e,
+ 0x931b, 0x2ccb,
+ 0x931d, 0x2cd4,
+ 0x931e, 0x2cc3,
+ 0x931f, 0x2cc5,
+ 0x9320, 0x1375,
+ 0x9321, 0x1381,
+ 0x9322, 0x137a,
+ 0x9323, 0x2ccc,
+ 0x9324, 0x2cdb,
+ 0x9325, 0x2aae,
+ 0x9326, 0x1380,
+ 0x9327, 0x2cc2,
+ 0x9328, 0x149e,
+ 0x9329, 0x2cdd,
+ 0x932a, 0x2ce0,
+ 0x932b, 0x137c,
+ 0x932c, 0x3892,
+ 0x932d, 0x2cd0,
+ 0x932e, 0x1383,
+ 0x932f, 0x1379,
+ 0x9330, 0x3e03,
+ 0x9331, 0x3cbd,
+ 0x9333, 0x1378,
+ 0x9334, 0x2cd9,
+ 0x9335, 0x2cdf,
+ 0x9336, 0x1376,
+ 0x9338, 0x2cc9,
+ 0x9339, 0x2cde,
+ 0x933c, 0x2cca,
+ 0x9340, 0x4155,
+ 0x9341, 0x4277,
+ 0x9342, 0x3afa,
+ 0x9343, 0x47a0,
+ 0x9344, 0x4016,
+ 0x9345, 0x3e74,
+ 0x9346, 0x2ccf,
+ 0x9347, 0x2e8d,
+ 0x9348, 0x3c61,
+ 0x9349, 0x2e92,
+ 0x934a, 0x14a0,
+ 0x934b, 0x14a2,
+ 0x934c, 0x2e98,
+ 0x934d, 0x149c,
+ 0x934e, 0x2ea6,
+ 0x934f, 0x2e9e,
+ 0x9350, 0x2e93,
+ 0x9352, 0x2e9d,
+ 0x9354, 0x14a9,
+ 0x9355, 0x2e9c,
+ 0x9356, 0x2e8c,
+ 0x9357, 0x2e9b,
+ 0x9358, 0x2e8f,
+ 0x9359, 0x2ea7,
+ 0x935a, 0x14a8,
+ 0x935b, 0x14a6,
+ 0x935c, 0x2e90,
+ 0x935e, 0x2ea3,
+ 0x935f, 0x3cbb,
+ 0x9360, 0x2e95,
+ 0x9361, 0x2ea2,
+ 0x9362, 0x4268,
+ 0x9363, 0x2ea4,
+ 0x9364, 0x2e8b,
+ 0x9365, 0x14a1,
+ 0x9366, 0x46bc,
+ 0x9367, 0x2ea5,
+ 0x9368, 0x3bf0,
+ 0x9369, 0x3961,
+ 0x936a, 0x2e99,
+ 0x936b, 0x3893,
+ 0x936c, 0x14a5,
+ 0x936d, 0x2e96,
+ 0x936e, 0x39e8,
+ 0x9370, 0x14a7,
+ 0x9371, 0x2e9f,
+ 0x9373, 0x389e,
+ 0x9374, 0x3ce4,
+ 0x9375, 0x149f,
+ 0x9376, 0x2e91,
+ 0x9377, 0x2ea0,
+ 0x9378, 0x38f9,
+ 0x9379, 0x2e9a,
+ 0x937a, 0x2cc8,
+ 0x937b, 0x2ea1,
+ 0x937c, 0x2e8e,
+ 0x937d, 0x3c25,
+ 0x937e, 0x14a4,
+ 0x9380, 0x3014,
+ 0x9381, 0x3965,
+ 0x9382, 0x149d,
+ 0x9383, 0x2e89,
+ 0x9384, 0x47a1,
+ 0x9385, 0x42bd,
+ 0x9386, 0x3cc0,
+ 0x9387, 0x3ae0,
+ 0x9388, 0x3011,
+ 0x9389, 0x300a,
+ 0x938a, 0x1540,
+ 0x938c, 0x3005,
+ 0x938d, 0x3015,
+ 0x938e, 0x300c,
+ 0x938f, 0x2e97,
+ 0x9390, 0x3d3c,
+ 0x9391, 0x3017,
+ 0x9392, 0x3006,
+ 0x9394, 0x153f,
+ 0x9395, 0x3010,
+ 0x9396, 0x1541,
+ 0x9397, 0x1549,
+ 0x9398, 0x1547,
+ 0x9399, 0x3012,
+ 0x939a, 0x1548,
+ 0x939b, 0x3008,
+ 0x939c, 0x39ac,
+ 0x939d, 0x3009,
+ 0x939e, 0x300e,
+ 0x939f, 0x3013,
+ 0x93a0, 0x3ab1,
+ 0x93a1, 0x2e88,
+ 0x93a2, 0x1542,
+ 0x93a3, 0x301c,
+ 0x93a4, 0x3019,
+ 0x93a5, 0x3160,
+ 0x93a6, 0x300f,
+ 0x93a7, 0x300b,
+ 0x93a8, 0x301a,
+ 0x93a9, 0x3155,
+ 0x93aa, 0x300d,
+ 0x93ac, 0x1545,
+ 0x93ad, 0x47a2,
+ 0x93ae, 0x1544,
+ 0x93af, 0x2e8a,
+ 0x93b0, 0x1546,
+ 0x93b1, 0x3016,
+ 0x93b2, 0x3018,
+ 0x93b3, 0x1543,
+ 0x93b4, 0x301b,
+ 0x93b5, 0x3004,
+ 0x93b7, 0x3007,
+ 0x93b8, 0x3c90,
+ 0x93ba, 0x43f7,
+ 0x93bb, 0x3c8f,
+ 0x93bd, 0x3a27,
+ 0x93bf, 0x3e2d,
+ 0x93c0, 0x315e,
+ 0x93c2, 0x314e,
+ 0x93c3, 0x15e0,
+ 0x93c4, 0x315c,
+ 0x93c6, 0x39aa,
+ 0x93c7, 0x314c,
+ 0x93c8, 0x15e1,
+ 0x93ca, 0x3157,
+ 0x93cb, 0x3966,
+ 0x93cc, 0x3153,
+ 0x93cd, 0x15e6,
+ 0x93ce, 0x315d,
+ 0x93cf, 0x314d,
+ 0x93d0, 0x3150,
+ 0x93d1, 0x15de,
+ 0x93d2, 0x315f,
+ 0x93d3, 0x40e1,
+ 0x93d4, 0x3158,
+ 0x93d5, 0x315b,
+ 0x93d6, 0x15e4,
+ 0x93d7, 0x15e9,
+ 0x93d8, 0x15e7,
+ 0x93d9, 0x3154,
+ 0x93da, 0x314f,
+ 0x93db, 0x3c5f,
+ 0x93dc, 0x15e2,
+ 0x93de, 0x314b,
+ 0x93df, 0x15df,
+ 0x93e0, 0x3a20,
+ 0x93e1, 0x15dd,
+ 0x93e2, 0x15e5,
+ 0x93e3, 0x315a,
+ 0x93e4, 0x15e8,
+ 0x93e6, 0x3156,
+ 0x93e7, 0x3161,
+ 0x93e8, 0x15ea,
+ 0x93ec, 0x3152,
+ 0x93ee, 0x3159,
+ 0x93f0, 0x423f,
+ 0x93f1, 0x42aa,
+ 0x93f3, 0x3962,
+ 0x93f5, 0x325a,
+ 0x93f6, 0x3269,
+ 0x93f7, 0x325c,
+ 0x93f8, 0x3263,
+ 0x93f9, 0x3151,
+ 0x93fa, 0x3261,
+ 0x93fb, 0x3250,
+ 0x93fc, 0x3267,
+ 0x93fd, 0x1654,
+ 0x93fe, 0x3254,
+ 0x93ff, 0x3266,
+ 0x9400, 0x325b,
+ 0x9401, 0x3cd4,
+ 0x9403, 0x1653,
+ 0x9404, 0x3bc9,
+ 0x9406, 0x326b,
+ 0x9407, 0x325d,
+ 0x9408, 0x3a25,
+ 0x9409, 0x3262,
+ 0x940a, 0x3265,
+ 0x940b, 0x324e,
+ 0x940c, 0x3268,
+ 0x940d, 0x3259,
+ 0x940e, 0x325e,
+ 0x940f, 0x3252,
+ 0x9410, 0x3256,
+ 0x9411, 0x326a,
+ 0x9412, 0x3260,
+ 0x9413, 0x324f,
+ 0x9414, 0x3253,
+ 0x9415, 0x3255,
+ 0x9416, 0x325f,
+ 0x9417, 0x47a5,
+ 0x9418, 0x1652,
+ 0x9419, 0x3258,
+ 0x941b, 0x4148,
+ 0x941d, 0x47a6,
+ 0x9420, 0x3251,
+ 0x9424, 0x3943,
+ 0x9425, 0x38d0,
+ 0x9426, 0x38a3,
+ 0x9427, 0x3bcd,
+ 0x9428, 0x3257,
+ 0x9429, 0x3325,
+ 0x942a, 0x3329,
+ 0x942b, 0x169f,
+ 0x942c, 0x332b,
+ 0x942d, 0x47a7,
+ 0x942e, 0x1699,
+ 0x9430, 0x3327,
+ 0x9431, 0x332d,
+ 0x9432, 0x169e,
+ 0x9433, 0x169a,
+ 0x9435, 0x169b,
+ 0x9436, 0x3324,
+ 0x9437, 0x332a,
+ 0x9438, 0x169d,
+ 0x9439, 0x3328,
+ 0x943a, 0x169c,
+ 0x943b, 0x3323,
+ 0x943c, 0x3264,
+ 0x943d, 0x3326,
+ 0x943e, 0x47a8,
+ 0x943f, 0x3322,
+ 0x9440, 0x332c,
+ 0x9442, 0x4272,
+ 0x9443, 0x4275,
+ 0x9444, 0x16df,
+ 0x9445, 0x33cd,
+ 0x9446, 0x33d0,
+ 0x9447, 0x33cc,
+ 0x9448, 0x33ce,
+ 0x944a, 0x33c9,
+ 0x944c, 0x33c7,
+ 0x944d, 0x3c65,
+ 0x944f, 0x33cb,
+ 0x9450, 0x33c8,
+ 0x9451, 0x16e0,
+ 0x9454, 0x47aa,
+ 0x9455, 0x3448,
+ 0x9457, 0x344a,
+ 0x9458, 0x3c30,
+ 0x945b, 0x389f,
+ 0x945d, 0x3449,
+ 0x945e, 0x344b,
+ 0x9460, 0x170e,
+ 0x9462, 0x3447,
+ 0x9463, 0x170d,
+ 0x9464, 0x170f,
+ 0x9465, 0x3dde,
+ 0x9467, 0x3ab8,
+ 0x9468, 0x34a6,
+ 0x946a, 0x1731,
+ 0x946b, 0x34a5,
+ 0x946c, 0x377e,
+ 0x946d, 0x34ed,
+ 0x946e, 0x34ec,
+ 0x946f, 0x34ee,
+ 0x9470, 0x174c,
+ 0x9471, 0x34ef,
+ 0x9472, 0x174b,
+ 0x9473, 0x34f0,
+ 0x9474, 0x350c,
+ 0x9475, 0x350f,
+ 0x9476, 0x350e,
+ 0x9477, 0x1755,
+ 0x9478, 0x350d,
+ 0x9479, 0x47ab,
+ 0x947b, 0x419b,
+ 0x947c, 0x175f,
+ 0x947d, 0x175d,
+ 0x947f, 0x1764,
+ 0x9480, 0x3539,
+ 0x9482, 0x3538,
+ 0x9483, 0x3540,
+ 0x9485, 0x4507,
+ 0x949f, 0x4885,
+ 0x94a2, 0x451b,
+ 0x94c1, 0x47e1,
+ 0x94c3, 0x47df,
+ 0x94dc, 0x47d7,
+ 0x94f6, 0x47d2,
+ 0x952d, 0x47ac,
+ 0x9547, 0x48bf,
+ 0x9577, 0x0697,
+ 0x9578, 0x4508,
+ 0x957a, 0x20a1,
+ 0x957b, 0x234a,
+ 0x957c, 0x2ab1,
+ 0x957d, 0x3162,
+ 0x957f, 0x4509,
+ 0x9580, 0x0698,
+ 0x9582, 0x0821,
+ 0x9583, 0x09ea,
+ 0x9585, 0x38a1,
+ 0x9586, 0x20a2,
+ 0x9588, 0x20a3,
+ 0x9589, 0x0bd0,
+ 0x958b, 0x0d9a,
+ 0x958c, 0x234c,
+ 0x958d, 0x234b,
+ 0x958e, 0x0d9e,
+ 0x958f, 0x0d99,
+ 0x9590, 0x234d,
+ 0x9591, 0x0d9b,
+ 0x9592, 0x0d9d,
+ 0x9593, 0x0d9c,
+ 0x9594, 0x0d98,
+ 0x9596, 0x3bd5,
+ 0x9597, 0x3bd4,
+ 0x9598, 0x0f5c,
+ 0x9599, 0x3bd2,
+ 0x959b, 0x25f3,
+ 0x959c, 0x25f1,
+ 0x959e, 0x25f2,
+ 0x959f, 0x25f0,
+ 0x95a0, 0x38a4,
+ 0x95a1, 0x10df,
+ 0x95a2, 0x47ad,
+ 0x95a3, 0x10e2,
+ 0x95a4, 0x10e4,
+ 0x95a5, 0x10e3,
+ 0x95a6, 0x38a2,
+ 0x95a7, 0x3bd3,
+ 0x95a8, 0x10e0,
+ 0x95aa, 0x4395,
+ 0x95ab, 0x2ab3,
+ 0x95ac, 0x2ab2,
+ 0x95ad, 0x1260,
+ 0x95ae, 0x2ab4,
+ 0x95b0, 0x2ab5,
+ 0x95b1, 0x1261,
+ 0x95b5, 0x2cf0,
+ 0x95b6, 0x2cee,
+ 0x95b7, 0x2ead,
+ 0x95b9, 0x2cec,
+ 0x95bb, 0x1385,
+ 0x95bc, 0x2ce9,
+ 0x95bd, 0x2cf1,
+ 0x95be, 0x2ceb,
+ 0x95bf, 0x2cef,
+ 0x95c0, 0x2ea9,
+ 0x95c3, 0x2eab,
+ 0x95c5, 0x2eac,
+ 0x95c6, 0x14ae,
+ 0x95c7, 0x2ea8,
+ 0x95c8, 0x14ad,
+ 0x95c9, 0x2eaa,
+ 0x95ca, 0x14aa,
+ 0x95cd, 0x2cea,
+ 0x95d0, 0x154c,
+ 0x95d1, 0x301f,
+ 0x95d2, 0x301d,
+ 0x95d4, 0x154a,
+ 0x95d5, 0x154d,
+ 0x95d6, 0x154b,
+ 0x95da, 0x3163,
+ 0x95dc, 0x15eb,
+ 0x95de, 0x326c,
+ 0x95df, 0x326e,
+ 0x95e0, 0x326d,
+ 0x95e1, 0x1655,
+ 0x95e2, 0x16a0,
+ 0x95e3, 0x3330,
+ 0x95e4, 0x332f,
+ 0x95e5, 0x332e,
+ 0x95e8, 0x450a,
+ 0x95f4, 0x47af,
+ 0x961c, 0x0699,
+ 0x961d, 0x4519,
+ 0x961e, 0x17b4,
+ 0x9620, 0x1821,
+ 0x9621, 0x0414,
+ 0x9622, 0x181f,
+ 0x9623, 0x1822,
+ 0x9624, 0x1820,
+ 0x9628, 0x18f1,
+ 0x962a, 0x0526,
+ 0x962c, 0x0527,
+ 0x962d, 0x18f3,
+ 0x962e, 0x0524,
+ 0x962f, 0x18f2,
+ 0x9630, 0x18f0,
+ 0x9631, 0x0525,
+ 0x9632, 0x0523,
+ 0x9633, 0x47b0,
+ 0x9638, 0x3fd1,
+ 0x9639, 0x1a55,
+ 0x963a, 0x1a58,
+ 0x963b, 0x069c,
+ 0x963c, 0x1a57,
+ 0x963d, 0x1a56,
+ 0x963f, 0x069b,
+ 0x9640, 0x069a,
+ 0x9641, 0x3f3d,
+ 0x9642, 0x069e,
+ 0x9643, 0x1a59,
+ 0x9644, 0x069d,
+ 0x9645, 0x4772,
+ 0x964a, 0x1c1a,
+ 0x964b, 0x0823,
+ 0x964e, 0x1c1b,
+ 0x964f, 0x1c17,
+ 0x9650, 0x0822,
+ 0x9651, 0x1c18,
+ 0x9653, 0x1c19,
+ 0x9654, 0x1c16,
+ 0x9656, 0x3de7,
+ 0x9658, 0x09f1,
+ 0x965b, 0x09ee,
+ 0x965c, 0x1e2f,
+ 0x965d, 0x09ef,
+ 0x965e, 0x09f2,
+ 0x965f, 0x1e30,
+ 0x9661, 0x09ed,
+ 0x9662, 0x09eb,
+ 0x9664, 0x09f0,
+ 0x9669, 0x475e,
+ 0x966a, 0x0bd1,
+ 0x966b, 0x20a6,
+ 0x966c, 0x0bd9,
+ 0x966d, 0x20a5,
+ 0x966f, 0x20a8,
+ 0x9670, 0x0bd5,
+ 0x9671, 0x20a7,
+ 0x9672, 0x0da6,
+ 0x9673, 0x0bd3,
+ 0x9674, 0x0bd6,
+ 0x9675, 0x0bd2,
+ 0x9676, 0x0bd7,
+ 0x9678, 0x0bd4,
+ 0x967b, 0x38ac,
+ 0x967c, 0x20a4,
+ 0x967d, 0x0da2,
+ 0x967e, 0x234f,
+ 0x9680, 0x2353,
+ 0x9681, 0x3f46,
+ 0x9683, 0x2352,
+ 0x9684, 0x0da7,
+ 0x9685, 0x0da3,
+ 0x9687, 0x234e,
+ 0x9688, 0x2350,
+ 0x968a, 0x0d9f,
+ 0x968b, 0x0da1,
+ 0x968d, 0x0da5,
+ 0x968e, 0x0da0,
+ 0x968f, 0x3bde,
+ 0x9691, 0x25f6,
+ 0x9692, 0x25f4,
+ 0x9694, 0x0f5e,
+ 0x9696, 0x38ad,
+ 0x9697, 0x25f7,
+ 0x9698, 0x0f5d,
+ 0x9699, 0x10e5,
+ 0x969b, 0x10e7,
+ 0x969c, 0x10e6,
+ 0x969e, 0x2852,
+ 0x96a1, 0x2853,
+ 0x96a2, 0x2ab7,
+ 0x96a3, 0x38af,
+ 0x96a4, 0x2ab6,
+ 0x96a5, 0x42ef,
+ 0x96a7, 0x1386,
+ 0x96a9, 0x2cf2,
+ 0x96aa, 0x1388,
+ 0x96ac, 0x2eb0,
+ 0x96ae, 0x2eae,
+ 0x96b0, 0x2eaf,
+ 0x96b1, 0x14af,
+ 0x96b3, 0x3020,
+ 0x96b4, 0x15ec,
+ 0x96b6, 0x0231,
+ 0x96b8, 0x14b0,
+ 0x96b9, 0x069f,
+ 0x96bb, 0x09f3,
+ 0x96bc, 0x1e31,
+ 0x96bd, 0x38b5,
+ 0x96bf, 0x20a9,
+ 0x96c0, 0x0bda,
+ 0x96c1, 0x0da8,
+ 0x96c2, 0x2354,
+ 0x96c3, 0x2356,
+ 0x96c4, 0x0daa,
+ 0x96c5, 0x0da9,
+ 0x96c6, 0x0dab,
+ 0x96c8, 0x2355,
+ 0x96c9, 0x0f62,
+ 0x96cb, 0x0f61,
+ 0x96cc, 0x10e8,
+ 0x96cd, 0x0f60,
+ 0x96ce, 0x25f8,
+ 0x96d2, 0x10e9,
+ 0x96d3, 0x2ab8,
+ 0x96d4, 0x2cf3,
+ 0x96d5, 0x1389,
+ 0x96d6, 0x14b1,
+ 0x96d7, 0x3021,
+ 0x96d8, 0x3025,
+ 0x96d9, 0x1550,
+ 0x96da, 0x3022,
+ 0x96db, 0x1551,
+ 0x96dc, 0x154f,
+ 0x96dd, 0x3026,
+ 0x96de, 0x1552,
+ 0x96df, 0x3024,
+ 0x96e1, 0x3165,
+ 0x96e2, 0x154e,
+ 0x96e3, 0x15ed,
+ 0x96e5, 0x34a8,
+ 0x96e8, 0x06a0,
+ 0x96e9, 0x0bdc,
+ 0x96ea, 0x0bdb,
+ 0x96ef, 0x0dad,
+ 0x96f0, 0x2358,
+ 0x96f1, 0x2357,
+ 0x96f2, 0x0dae,
+ 0x96f4, 0x3a04,
+ 0x96f5, 0x25fc,
+ 0x96f6, 0x0f67,
+ 0x96f7, 0x0f64,
+ 0x96f8, 0x25fb,
+ 0x96f9, 0x0f66,
+ 0x96fa, 0x25f9,
+ 0x96fb, 0x0f65,
+ 0x96fd, 0x25fa,
+ 0x96ff, 0x2854,
+ 0x9700, 0x10ea,
+ 0x9702, 0x2abb,
+ 0x9703, 0x3f0d,
+ 0x9704, 0x1262,
+ 0x9705, 0x2ab9,
+ 0x9706, 0x1263,
+ 0x9708, 0x2aba,
+ 0x9709, 0x1265,
+ 0x970b, 0x2cf4,
+ 0x970d, 0x138d,
+ 0x970e, 0x138a,
+ 0x970f, 0x138f,
+ 0x9710, 0x2cf6,
+ 0x9711, 0x138b,
+ 0x9712, 0x2cf5,
+ 0x9713, 0x138e,
+ 0x9716, 0x138c,
+ 0x9718, 0x2eb3,
+ 0x9719, 0x2eb5,
+ 0x971b, 0x38c9,
+ 0x971c, 0x14b2,
+ 0x971d, 0x2eb4,
+ 0x971e, 0x14b3,
+ 0x971f, 0x2eb2,
+ 0x9720, 0x2eb1,
+ 0x9721, 0x3fb3,
+ 0x9722, 0x3028,
+ 0x9723, 0x3027,
+ 0x9724, 0x1553,
+ 0x9725, 0x3029,
+ 0x9726, 0x316a,
+ 0x9727, 0x15ef,
+ 0x9728, 0x3169,
+ 0x9729, 0x3166,
+ 0x972a, 0x15ee,
+ 0x972b, 0x3167,
+ 0x972e, 0x326f,
+ 0x9730, 0x1656,
+ 0x9731, 0x38c0,
+ 0x9732, 0x16a3,
+ 0x9735, 0x3331,
+ 0x9736, 0x38c2,
+ 0x9738, 0x16a1,
+ 0x973a, 0x3332,
+ 0x973d, 0x16e2,
+ 0x973f, 0x33d1,
+ 0x9740, 0x47b3,
+ 0x9741, 0x3be9,
+ 0x9742, 0x1732,
+ 0x9743, 0x34aa,
+ 0x9744, 0x1734,
+ 0x9746, 0x34a9,
+ 0x9747, 0x34ab,
+ 0x9748, 0x1733,
+ 0x9749, 0x34f1,
+ 0x974b, 0x3526,
+ 0x9751, 0x44e3,
+ 0x9752, 0x06a1,
+ 0x9756, 0x0f68,
+ 0x9757, 0x38cc,
+ 0x9758, 0x2855,
+ 0x975a, 0x2abc,
+ 0x975b, 0x1390,
+ 0x975d, 0x3bef,
+ 0x975e, 0x06a2,
+ 0x975f, 0x38cf,
+ 0x9760, 0x1266,
+ 0x9761, 0x15f0,
+ 0x9762, 0x0826,
+ 0x9766, 0x1392,
+ 0x9768, 0x1710,
+ 0x9769, 0x0827,
+ 0x976a, 0x20aa,
+ 0x976c, 0x2359,
+ 0x976d, 0x3e97,
+ 0x976e, 0x235b,
+ 0x9770, 0x235a,
+ 0x9771, 0x3bfc,
+ 0x9772, 0x2600,
+ 0x9773, 0x25fd,
+ 0x9774, 0x0f69,
+ 0x9776, 0x0f6a,
+ 0x9777, 0x25fe,
+ 0x977a, 0x2857,
+ 0x977b, 0x285c,
+ 0x977c, 0x10eb,
+ 0x977d, 0x2856,
+ 0x977e, 0x2858,
+ 0x977f, 0x285f,
+ 0x9780, 0x285a,
+ 0x9781, 0x285e,
+ 0x9782, 0x285b,
+ 0x9783, 0x2859,
+ 0x9784, 0x285d,
+ 0x9785, 0x10ec,
+ 0x9787, 0x40c0,
+ 0x9788, 0x2abf,
+ 0x9789, 0x38d4,
+ 0x978a, 0x2abd,
+ 0x978b, 0x1268,
+ 0x978d, 0x1267,
+ 0x978e, 0x2abe,
+ 0x978f, 0x1269,
+ 0x9794, 0x2cf9,
+ 0x9797, 0x2cf8,
+ 0x9798, 0x1393,
+ 0x9799, 0x2cf7,
+ 0x979a, 0x2eb6,
+ 0x979b, 0x3bfb,
+ 0x979c, 0x2eb8,
+ 0x979d, 0x2eba,
+ 0x979e, 0x2eb9,
+ 0x979f, 0x38d5,
+ 0x97a0, 0x14b4,
+ 0x97a1, 0x2eb7,
+ 0x97a2, 0x3030,
+ 0x97a3, 0x1554,
+ 0x97a4, 0x302e,
+ 0x97a5, 0x3031,
+ 0x97a6, 0x1555,
+ 0x97a8, 0x302c,
+ 0x97aa, 0x302f,
+ 0x97ab, 0x302d,
+ 0x97ac, 0x302a,
+ 0x97ad, 0x1556,
+ 0x97ae, 0x302b,
+ 0x97b1, 0x38d6,
+ 0x97b2, 0x47b5,
+ 0x97b3, 0x316b,
+ 0x97b4, 0x3f33,
+ 0x97b6, 0x316d,
+ 0x97b7, 0x316c,
+ 0x97b8, 0x3d95,
+ 0x97b9, 0x3271,
+ 0x97ba, 0x3f35,
+ 0x97bb, 0x3272,
+ 0x97bd, 0x494e,
+ 0x97be, 0x38d7,
+ 0x97bf, 0x3333,
+ 0x97c0, 0x38d8,
+ 0x97c1, 0x16e5,
+ 0x97c2, 0x47b6,
+ 0x97c3, 0x16e4,
+ 0x97c4, 0x344c,
+ 0x97c6, 0x1735,
+ 0x97c7, 0x34ac,
+ 0x97c8, 0x3f2f,
+ 0x97c9, 0x1756,
+ 0x97cb, 0x0828,
+ 0x97cc, 0x0daf,
+ 0x97cd, 0x2861,
+ 0x97ce, 0x2860,
+ 0x97cf, 0x2ac1,
+ 0x97d0, 0x2ac0,
+ 0x97d2, 0x38d9,
+ 0x97d3, 0x14b5,
+ 0x97d4, 0x2ebc,
+ 0x97d5, 0x2ebb,
+ 0x97d6, 0x3034,
+ 0x97d7, 0x3032,
+ 0x97d8, 0x3035,
+ 0x97d9, 0x3033,
+ 0x97dc, 0x15f1,
+ 0x97dd, 0x316e,
+ 0x97e0, 0x38da,
+ 0x97e1, 0x3334,
+ 0x97e3, 0x33d2,
+ 0x97e5, 0x34ad,
+ 0x97e6, 0x450c,
+ 0x97ed, 0x0829,
+ 0x97ee, 0x38dc,
+ 0x97f0, 0x2cfa,
+ 0x97f1, 0x2ebd,
+ 0x97f2, 0x394d,
+ 0x97f3, 0x082a,
+ 0x97f5, 0x38e0,
+ 0x97f6, 0x10ed,
+ 0x97f8, 0x2cfb,
+ 0x97f9, 0x1557,
+ 0x97fa, 0x3036,
+ 0x97fb, 0x15f2,
+ 0x97fd, 0x3273,
+ 0x97ff, 0x16a4,
+ 0x9800, 0x344e,
+ 0x9801, 0x082b,
+ 0x9802, 0x0bdf,
+ 0x9804, 0x20ab,
+ 0x9805, 0x0db0,
+ 0x9807, 0x235c,
+ 0x9808, 0x0db2,
+ 0x980a, 0x0f6e,
+ 0x980c, 0x0f70,
+ 0x980d, 0x2602,
+ 0x980f, 0x2601,
+ 0x9810, 0x0f6b,
+ 0x9812, 0x0f6f,
+ 0x9813, 0x0f6d,
+ 0x9814, 0x4952,
+ 0x9815, 0x433c,
+ 0x9816, 0x2862,
+ 0x9817, 0x10ee,
+ 0x981b, 0x2ac8,
+ 0x981c, 0x126c,
+ 0x981d, 0x2ac3,
+ 0x981e, 0x2ac2,
+ 0x981f, 0x3c02,
+ 0x9820, 0x2ac7,
+ 0x9821, 0x126a,
+ 0x9823, 0x3e37,
+ 0x9824, 0x139a,
+ 0x9826, 0x2ac4,
+ 0x9827, 0x2ac9,
+ 0x9828, 0x2ac6,
+ 0x9829, 0x2ac5,
+ 0x982b, 0x126b,
+ 0x982d, 0x1398,
+ 0x982e, 0x3f72,
+ 0x982f, 0x2cfd,
+ 0x9830, 0x1394,
+ 0x9832, 0x2cfe,
+ 0x9833, 0x38e5,
+ 0x9834, 0x38e4,
+ 0x9835, 0x2cfc,
+ 0x9837, 0x1397,
+ 0x9838, 0x1395,
+ 0x9839, 0x1399,
+ 0x983b, 0x1396,
+ 0x9841, 0x2ebe,
+ 0x9843, 0x2ec3,
+ 0x9844, 0x2ebf,
+ 0x9845, 0x2ec2,
+ 0x9846, 0x14b6,
+ 0x9847, 0x3d96,
+ 0x9848, 0x2df2,
+ 0x9849, 0x2ec1,
+ 0x984a, 0x2ec0,
+ 0x984b, 0x38e6,
+ 0x984c, 0x155a,
+ 0x984d, 0x1558,
+ 0x984e, 0x155b,
+ 0x984f, 0x1559,
+ 0x9850, 0x3037,
+ 0x9853, 0x155c,
+ 0x9857, 0x3174,
+ 0x9858, 0x15f4,
+ 0x9859, 0x3172,
+ 0x985b, 0x15f5,
+ 0x985c, 0x3171,
+ 0x985d, 0x3173,
+ 0x985e, 0x15f3,
+ 0x985f, 0x3278,
+ 0x9860, 0x3275,
+ 0x9862, 0x3276,
+ 0x9864, 0x3335,
+ 0x9865, 0x16a6,
+ 0x9866, 0x38e7,
+ 0x9867, 0x16a5,
+ 0x9869, 0x33d4,
+ 0x986a, 0x33d3,
+ 0x986b, 0x16e6,
+ 0x986c, 0x4035,
+ 0x986f, 0x1711,
+ 0x9870, 0x1736,
+ 0x9871, 0x174d,
+ 0x9872, 0x34f2,
+ 0x9873, 0x3527,
+ 0x9875, 0x450d,
+ 0x98a8, 0x082c,
+ 0x98a9, 0x235d,
+ 0x98ac, 0x2604,
+ 0x98ad, 0x2863,
+ 0x98af, 0x10f0,
+ 0x98b1, 0x10f1,
+ 0x98b2, 0x2aca,
+ 0x98b3, 0x126d,
+ 0x98b4, 0x3f73,
+ 0x98b6, 0x14b7,
+ 0x98b7, 0x38ef,
+ 0x98b8, 0x303a,
+ 0x98b9, 0x47b8,
+ 0x98ba, 0x155d,
+ 0x98bb, 0x3177,
+ 0x98bc, 0x15f6,
+ 0x98bd, 0x3176,
+ 0x98be, 0x3178,
+ 0x98bf, 0x3175,
+ 0x98c0, 0x3338,
+ 0x98c1, 0x3279,
+ 0x98c3, 0x3b78,
+ 0x98c4, 0x1657,
+ 0x98c6, 0x3337,
+ 0x98c7, 0x38f1,
+ 0x98c8, 0x38f0,
+ 0x98c9, 0x3336,
+ 0x98ca, 0x38ee,
+ 0x98cb, 0x33d5,
+ 0x98cc, 0x3529,
+ 0x98ce, 0x450e,
+ 0x98db, 0x082d,
+ 0x98dc, 0x3c0b,
+ 0x98de, 0x450f,
+ 0x98df, 0x082e,
+ 0x98e0, 0x4792,
+ 0x98e1, 0x38f6,
+ 0x98e2, 0x09f4,
+ 0x98e3, 0x1e32,
+ 0x98e5, 0x20ac,
+ 0x98e6, 0x38f7,
+ 0x98e7, 0x0db3,
+ 0x98e9, 0x0db6,
+ 0x98ea, 0x0db4,
+ 0x98eb, 0x235e,
+ 0x98ec, 0x38f8,
+ 0x98ed, 0x0db8,
+ 0x98ef, 0x0db5,
+ 0x98f1, 0x47ba,
+ 0x98f2, 0x0db7,
+ 0x98f4, 0x0f72,
+ 0x98f5, 0x4365,
+ 0x98f6, 0x2605,
+ 0x98f9, 0x2606,
+ 0x98fa, 0x2acc,
+ 0x98fc, 0x0f71,
+ 0x98fd, 0x0f73,
+ 0x9900, 0x2866,
+ 0x9902, 0x2865,
+ 0x9903, 0x10f2,
+ 0x9905, 0x10f3,
+ 0x9907, 0x2867,
+ 0x9908, 0x2acb,
+ 0x9909, 0x10f5,
+ 0x990a, 0x126e,
+ 0x990c, 0x10f4,
+ 0x990e, 0x43ed,
+ 0x9910, 0x139b,
+ 0x9911, 0x2acd,
+ 0x9912, 0x1270,
+ 0x9913, 0x126f,
+ 0x9914, 0x2ace,
+ 0x9915, 0x2ad1,
+ 0x9916, 0x2acf,
+ 0x9918, 0x1271,
+ 0x9919, 0x47bc,
+ 0x991a, 0x13a0,
+ 0x991b, 0x139e,
+ 0x991c, 0x43ee,
+ 0x991e, 0x139d,
+ 0x991f, 0x2d00,
+ 0x9921, 0x139f,
+ 0x9924, 0x2cff,
+ 0x9925, 0x2ec4,
+ 0x9927, 0x2d01,
+ 0x9928, 0x139c,
+ 0x9929, 0x2d02,
+ 0x992a, 0x2ec7,
+ 0x992b, 0x2ec5,
+ 0x992d, 0x2ecb,
+ 0x992e, 0x1561,
+ 0x992f, 0x2eca,
+ 0x9930, 0x2ecd,
+ 0x9931, 0x2ecc,
+ 0x9932, 0x2ec9,
+ 0x9933, 0x2ec8,
+ 0x9935, 0x14b8,
+ 0x9937, 0x47bd,
+ 0x9938, 0x3bfd,
+ 0x9939, 0x38fa,
+ 0x993a, 0x303d,
+ 0x993b, 0x3c11,
+ 0x993c, 0x303c,
+ 0x993d, 0x1560,
+ 0x993e, 0x155e,
+ 0x9940, 0x3f34,
+ 0x9941, 0x303b,
+ 0x9942, 0x43ff,
+ 0x9943, 0x317b,
+ 0x9945, 0x15f7,
+ 0x9947, 0x317a,
+ 0x9948, 0x3179,
+ 0x9949, 0x15f8,
+ 0x994a, 0x3fb9,
+ 0x994b, 0x327f,
+ 0x994c, 0x327e,
+ 0x994d, 0x3c12,
+ 0x994e, 0x327c,
+ 0x9950, 0x327b,
+ 0x9951, 0x1659,
+ 0x9952, 0x1658,
+ 0x9953, 0x3280,
+ 0x9954, 0x33d6,
+ 0x9955, 0x16e7,
+ 0x9956, 0x333a,
+ 0x9957, 0x16a7,
+ 0x9958, 0x3339,
+ 0x9959, 0x327d,
+ 0x995b, 0x33d7,
+ 0x995c, 0x1712,
+ 0x995d, 0x47be,
+ 0x995e, 0x174e,
+ 0x995f, 0x34f3,
+ 0x9961, 0x352a,
+ 0x9962, 0x43ef,
+ 0x9963, 0x4510,
+ 0x9996, 0x082f,
+ 0x9997, 0x20ad,
+ 0x9998, 0x2ece,
+ 0x9999, 0x0830,
+ 0x999b, 0x3c15,
+ 0x999c, 0x2869,
+ 0x999d, 0x2868,
+ 0x999e, 0x2d03,
+ 0x99a1, 0x2ed0,
+ 0x99a3, 0x2ecf,
+ 0x99a4, 0x41c3,
+ 0x99a5, 0x1562,
+ 0x99a6, 0x317c,
+ 0x99a8, 0x165a,
+ 0x99aa, 0x3c17,
+ 0x99ab, 0x352b,
+ 0x99ac, 0x09f5,
+ 0x99ad, 0x0dba,
+ 0x99ae, 0x0db9,
+ 0x99af, 0x2607,
+ 0x99b0, 0x2609,
+ 0x99b1, 0x0f76,
+ 0x99b2, 0x2608,
+ 0x99b3, 0x0f75,
+ 0x99b4, 0x0f77,
+ 0x99b5, 0x260a,
+ 0x99b8, 0x394b,
+ 0x99b9, 0x286b,
+ 0x99ba, 0x286d,
+ 0x99bb, 0x286c,
+ 0x99bc, 0x3c22,
+ 0x99bd, 0x286f,
+ 0x99c1, 0x10f6,
+ 0x99c2, 0x286e,
+ 0x99c3, 0x286a,
+ 0x99c4, 0x3d77,
+ 0x99c5, 0x47c1,
+ 0x99c7, 0x2870,
+ 0x99c9, 0x2ad8,
+ 0x99cb, 0x2adb,
+ 0x99cc, 0x2add,
+ 0x99cd, 0x2ad3,
+ 0x99ce, 0x2ad7,
+ 0x99cf, 0x2ad4,
+ 0x99d0, 0x1273,
+ 0x99d1, 0x1276,
+ 0x99d2, 0x1278,
+ 0x99d3, 0x2ad5,
+ 0x99d5, 0x1277,
+ 0x99d6, 0x2ad9,
+ 0x99d7, 0x2adc,
+ 0x99d8, 0x2ada,
+ 0x99d9, 0x1279,
+ 0x99da, 0x3f42,
+ 0x99db, 0x1275,
+ 0x99dc, 0x2ad2,
+ 0x99dd, 0x1272,
+ 0x99df, 0x1274,
+ 0x99e1, 0x3785,
+ 0x99e2, 0x13a2,
+ 0x99e3, 0x2d09,
+ 0x99e4, 0x2d07,
+ 0x99e5, 0x2d06,
+ 0x99e6, 0x3b65,
+ 0x99e7, 0x2d0c,
+ 0x99e9, 0x2d0b,
+ 0x99ea, 0x2d0a,
+ 0x99ec, 0x2d05,
+ 0x99ed, 0x13a1,
+ 0x99ee, 0x2d04,
+ 0x99f0, 0x2d08,
+ 0x99f1, 0x13a3,
+ 0x99f4, 0x2ed3,
+ 0x99f5, 0x38ff,
+ 0x99f6, 0x2ed7,
+ 0x99f7, 0x2ed4,
+ 0x99f8, 0x2ed6,
+ 0x99f9, 0x2ed5,
+ 0x99fa, 0x2ed2,
+ 0x99fb, 0x2ed8,
+ 0x99fc, 0x2edb,
+ 0x99fd, 0x2ed9,
+ 0x99ff, 0x14ba,
+ 0x9a01, 0x14b9,
+ 0x9a02, 0x2ed1,
+ 0x9a03, 0x2edc,
+ 0x9a04, 0x3042,
+ 0x9a05, 0x3045,
+ 0x9a06, 0x3047,
+ 0x9a07, 0x3046,
+ 0x9a09, 0x3040,
+ 0x9a0a, 0x3044,
+ 0x9a0b, 0x303f,
+ 0x9a0c, 0x3900,
+ 0x9a0d, 0x3041,
+ 0x9a0e, 0x1563,
+ 0x9a0f, 0x303e,
+ 0x9a10, 0x3902,
+ 0x9a11, 0x3043,
+ 0x9a14, 0x318a,
+ 0x9a15, 0x317f,
+ 0x9a16, 0x15f9,
+ 0x9a19, 0x15fa,
+ 0x9a1a, 0x317e,
+ 0x9a1b, 0x3183,
+ 0x9a1c, 0x3189,
+ 0x9a1d, 0x3181,
+ 0x9a1e, 0x3188,
+ 0x9a1f, 0x3b6c,
+ 0x9a20, 0x3185,
+ 0x9a21, 0x3c1c,
+ 0x9a22, 0x3184,
+ 0x9a23, 0x3187,
+ 0x9a24, 0x3182,
+ 0x9a25, 0x3180,
+ 0x9a26, 0x3df2,
+ 0x9a27, 0x3186,
+ 0x9a29, 0x3287,
+ 0x9a2a, 0x3285,
+ 0x9a2b, 0x165b,
+ 0x9a2c, 0x3284,
+ 0x9a2d, 0x328a,
+ 0x9a2e, 0x3288,
+ 0x9a2f, 0x3c1e,
+ 0x9a30, 0x165c,
+ 0x9a31, 0x3283,
+ 0x9a32, 0x3281,
+ 0x9a34, 0x3282,
+ 0x9a35, 0x165e,
+ 0x9a36, 0x3286,
+ 0x9a37, 0x165d,
+ 0x9a38, 0x3289,
+ 0x9a39, 0x333b,
+ 0x9a3a, 0x3341,
+ 0x9a3b, 0x3901,
+ 0x9a3c, 0x47c3,
+ 0x9a3d, 0x333c,
+ 0x9a3e, 0x16ab,
+ 0x9a3f, 0x3342,
+ 0x9a40, 0x16aa,
+ 0x9a41, 0x3340,
+ 0x9a42, 0x333f,
+ 0x9a43, 0x16a9,
+ 0x9a44, 0x333e,
+ 0x9a45, 0x16a8,
+ 0x9a46, 0x333d,
+ 0x9a48, 0x33dd,
+ 0x9a49, 0x33df,
+ 0x9a4a, 0x33de,
+ 0x9a4c, 0x33db,
+ 0x9a4d, 0x16e9,
+ 0x9a4e, 0x33d8,
+ 0x9a4f, 0x33dc,
+ 0x9a50, 0x33e1,
+ 0x9a52, 0x33e0,
+ 0x9a53, 0x33d9,
+ 0x9a55, 0x16e8,
+ 0x9a56, 0x344f,
+ 0x9a57, 0x1715,
+ 0x9a58, 0x3903,
+ 0x9a59, 0x3450,
+ 0x9a5a, 0x1713,
+ 0x9a5c, 0x3c18,
+ 0x9a5e, 0x34ae,
+ 0x9a5f, 0x1737,
+ 0x9a60, 0x3510,
+ 0x9a62, 0x1757,
+ 0x9a63, 0x3b67,
+ 0x9a64, 0x352c,
+ 0x9a65, 0x1758,
+ 0x9a66, 0x352d,
+ 0x9a68, 0x353c,
+ 0x9a69, 0x353b,
+ 0x9a6a, 0x1767,
+ 0x9a6b, 0x3544,
+ 0x9a6c, 0x4585,
+ 0x9a8f, 0x4586,
+ 0x9aa8, 0x09f6,
+ 0x9aab, 0x260c,
+ 0x9aad, 0x260b,
+ 0x9aaf, 0x10f7,
+ 0x9ab1, 0x2871,
+ 0x9ab2, 0x4332,
+ 0x9ab3, 0x2ade,
+ 0x9ab4, 0x2d0f,
+ 0x9ab6, 0x43f0,
+ 0x9ab7, 0x127a,
+ 0x9ab8, 0x13a4,
+ 0x9ab9, 0x2d0d,
+ 0x9aba, 0x3f74,
+ 0x9abb, 0x2d10,
+ 0x9abc, 0x13a5,
+ 0x9abd, 0x3d97,
+ 0x9abe, 0x2edd,
+ 0x9abf, 0x2d0e,
+ 0x9ac0, 0x3048,
+ 0x9ac1, 0x1564,
+ 0x9ac2, 0x318b,
+ 0x9ac6, 0x328d,
+ 0x9ac7, 0x328b,
+ 0x9aca, 0x328c,
+ 0x9acd, 0x3343,
+ 0x9acf, 0x16ac,
+ 0x9ad0, 0x33e2,
+ 0x9ad1, 0x1718,
+ 0x9ad2, 0x16ea,
+ 0x9ad3, 0x1716,
+ 0x9ad5, 0x34af,
+ 0x9ad6, 0x174f,
+ 0x9ad7, 0x3faa,
+ 0x9ad8, 0x09f7,
+ 0x9adc, 0x3049,
+ 0x9adf, 0x1e33,
+ 0x9ae0, 0x3908,
+ 0x9ae1, 0x0f78,
+ 0x9ae2, 0x3909,
+ 0x9ae3, 0x2872,
+ 0x9ae6, 0x10f9,
+ 0x9ae7, 0x2873,
+ 0x9aeb, 0x2ae0,
+ 0x9aec, 0x2adf,
+ 0x9aed, 0x13a7,
+ 0x9aee, 0x127b,
+ 0x9af1, 0x2ae3,
+ 0x9af2, 0x2ae2,
+ 0x9af3, 0x2ae1,
+ 0x9af4, 0x390b,
+ 0x9af6, 0x2d11,
+ 0x9af7, 0x2d14,
+ 0x9af9, 0x2d13,
+ 0x9afa, 0x2d12,
+ 0x9afb, 0x13a6,
+ 0x9afc, 0x2ee1,
+ 0x9afd, 0x2edf,
+ 0x9afe, 0x2ede,
+ 0x9aff, 0x3f17,
+ 0x9b01, 0x2ee0,
+ 0x9b02, 0x3f12,
+ 0x9b03, 0x1565,
+ 0x9b04, 0x304b,
+ 0x9b06, 0x1566,
+ 0x9b08, 0x304a,
+ 0x9b09, 0x3f20,
+ 0x9b0a, 0x318d,
+ 0x9b0b, 0x318c,
+ 0x9b0c, 0x318f,
+ 0x9b0d, 0x15fb,
+ 0x9b0e, 0x318e,
+ 0x9b0f, 0x47c4,
+ 0x9b10, 0x328e,
+ 0x9b11, 0x3290,
+ 0x9b12, 0x328f,
+ 0x9b14, 0x390d,
+ 0x9b15, 0x3344,
+ 0x9b16, 0x3347,
+ 0x9b17, 0x3345,
+ 0x9b19, 0x33e3,
+ 0x9b1a, 0x16eb,
+ 0x9b1e, 0x3451,
+ 0x9b22, 0x1738,
+ 0x9b23, 0x1750,
+ 0x9b24, 0x352f,
+ 0x9b25, 0x09f8,
+ 0x9b27, 0x127d,
+ 0x9b28, 0x13a8,
+ 0x9b29, 0x304d,
+ 0x9b2a, 0x3f19,
+ 0x9b2b, 0x33e4,
+ 0x9b2d, 0x390e,
+ 0x9b2e, 0x3511,
+ 0x9b2f, 0x1e34,
+ 0x9b31, 0x1768,
+ 0x9b32, 0x09f9,
+ 0x9b33, 0x2d15,
+ 0x9b34, 0x3911,
+ 0x9b35, 0x304e,
+ 0x9b37, 0x3190,
+ 0x9b39, 0x3f00,
+ 0x9b3a, 0x3348,
+ 0x9b3b, 0x33e5,
+ 0x9b3c, 0x09fa,
+ 0x9b3e, 0x2874,
+ 0x9b40, 0x3915,
+ 0x9b41, 0x10fa,
+ 0x9b43, 0x2ae5,
+ 0x9b44, 0x127f,
+ 0x9b45, 0x127e,
+ 0x9b46, 0x2ae4,
+ 0x9b48, 0x2ee2,
+ 0x9b4a, 0x304f,
+ 0x9b4b, 0x3051,
+ 0x9b4c, 0x3050,
+ 0x9b4d, 0x1569,
+ 0x9b4e, 0x1568,
+ 0x9b4f, 0x1567,
+ 0x9b50, 0x3914,
+ 0x9b51, 0x16ae,
+ 0x9b52, 0x3349,
+ 0x9b54, 0x16ad,
+ 0x9b55, 0x33e7,
+ 0x9b56, 0x33e6,
+ 0x9b58, 0x1739,
+ 0x9b59, 0x34b0,
+ 0x9b5a, 0x0be1,
+ 0x9b5b, 0x260d,
+ 0x9b5f, 0x2878,
+ 0x9b60, 0x2876,
+ 0x9b64, 0x2aee,
+ 0x9b66, 0x2ae9,
+ 0x9b67, 0x2ae6,
+ 0x9b68, 0x2aed,
+ 0x9b69, 0x47c5,
+ 0x9b6c, 0x2aef,
+ 0x9b6f, 0x1281,
+ 0x9b70, 0x2aec,
+ 0x9b71, 0x2ae8,
+ 0x9b74, 0x2ae7,
+ 0x9b75, 0x2aeb,
+ 0x9b76, 0x2aea,
+ 0x9b77, 0x1280,
+ 0x9b7a, 0x2d20,
+ 0x9b7b, 0x2d1b,
+ 0x9b7c, 0x2d19,
+ 0x9b7d, 0x2d22,
+ 0x9b7e, 0x2d1a,
+ 0x9b7f, 0x3c3b,
+ 0x9b80, 0x2d16,
+ 0x9b81, 0x43f1,
+ 0x9b82, 0x2d1c,
+ 0x9b83, 0x4219,
+ 0x9b85, 0x2d17,
+ 0x9b86, 0x2eeb,
+ 0x9b87, 0x2d18,
+ 0x9b88, 0x2d23,
+ 0x9b8b, 0x3eee,
+ 0x9b8d, 0x4623,
+ 0x9b8e, 0x3919,
+ 0x9b8f, 0x3fad,
+ 0x9b90, 0x2d1f,
+ 0x9b91, 0x13a9,
+ 0x9b92, 0x2d1e,
+ 0x9b93, 0x2d1d,
+ 0x9b95, 0x2d21,
+ 0x9b97, 0x3f71,
+ 0x9b9a, 0x2ee3,
+ 0x9b9b, 0x2ee6,
+ 0x9b9d, 0x3f56,
+ 0x9b9e, 0x2ee5,
+ 0x9b9f, 0x3c3e,
+ 0x9ba0, 0x2eed,
+ 0x9ba1, 0x2ee8,
+ 0x9ba2, 0x2eec,
+ 0x9ba4, 0x2eea,
+ 0x9ba5, 0x2ee9,
+ 0x9ba6, 0x2ee7,
+ 0x9ba8, 0x2ee4,
+ 0x9baa, 0x14bd,
+ 0x9bab, 0x14bc,
+ 0x9bad, 0x14be,
+ 0x9bae, 0x14bb,
+ 0x9baf, 0x2eee,
+ 0x9bb0, 0x3fb4,
+ 0x9bb5, 0x3057,
+ 0x9bb6, 0x305a,
+ 0x9bb8, 0x3058,
+ 0x9bb9, 0x305c,
+ 0x9bbd, 0x305d,
+ 0x9bbf, 0x3055,
+ 0x9bc0, 0x156e,
+ 0x9bc1, 0x3056,
+ 0x9bc3, 0x3054,
+ 0x9bc4, 0x305b,
+ 0x9bc6, 0x3053,
+ 0x9bc7, 0x3052,
+ 0x9bc8, 0x156d,
+ 0x9bc9, 0x156b,
+ 0x9bca, 0x156a,
+ 0x9bcf, 0x3c3c,
+ 0x9bd3, 0x3059,
+ 0x9bd4, 0x3199,
+ 0x9bd5, 0x319f,
+ 0x9bd6, 0x15fe,
+ 0x9bd7, 0x319a,
+ 0x9bd9, 0x319d,
+ 0x9bda, 0x31a1,
+ 0x9bdb, 0x15ff,
+ 0x9bdc, 0x319c,
+ 0x9bdd, 0x47c6,
+ 0x9bde, 0x3194,
+ 0x9be0, 0x3193,
+ 0x9be1, 0x31a0,
+ 0x9be2, 0x3197,
+ 0x9be4, 0x3195,
+ 0x9be5, 0x319e,
+ 0x9be6, 0x3196,
+ 0x9be7, 0x15fd,
+ 0x9be8, 0x15fc,
+ 0x9be9, 0x3bc1,
+ 0x9bea, 0x3191,
+ 0x9bec, 0x319b,
+ 0x9bed, 0x3ed7,
+ 0x9bf0, 0x3198,
+ 0x9bf1, 0x47c7,
+ 0x9bf4, 0x47c8,
+ 0x9bf7, 0x3293,
+ 0x9bf8, 0x3296,
+ 0x9bfd, 0x156c,
+ 0x9bff, 0x391b,
+ 0x9c02, 0x391a,
+ 0x9c05, 0x3294,
+ 0x9c06, 0x329a,
+ 0x9c07, 0x3298,
+ 0x9c08, 0x3292,
+ 0x9c09, 0x329d,
+ 0x9c0a, 0x3f3a,
+ 0x9c0b, 0x3291,
+ 0x9c0c, 0x391c,
+ 0x9c0d, 0x1660,
+ 0x9c0e, 0x3299,
+ 0x9c10, 0x3c3a,
+ 0x9c12, 0x3295,
+ 0x9c13, 0x165f,
+ 0x9c14, 0x329c,
+ 0x9c15, 0x3f1e,
+ 0x9c17, 0x329b,
+ 0x9c1b, 0x491b,
+ 0x9c1c, 0x334c,
+ 0x9c1d, 0x334b,
+ 0x9c1f, 0x4622,
+ 0x9c20, 0x47ca,
+ 0x9c21, 0x3352,
+ 0x9c23, 0x334e,
+ 0x9c24, 0x3351,
+ 0x9c25, 0x16b0,
+ 0x9c26, 0x45e6,
+ 0x9c28, 0x334f,
+ 0x9c2b, 0x334a,
+ 0x9c2c, 0x334d,
+ 0x9c2d, 0x16af,
+ 0x9c2e, 0x3f22,
+ 0x9c2f, 0x3d87,
+ 0x9c31, 0x16ed,
+ 0x9c32, 0x33f2,
+ 0x9c33, 0x33ed,
+ 0x9c34, 0x33f1,
+ 0x9c35, 0x3c39,
+ 0x9c36, 0x33f4,
+ 0x9c37, 0x33f0,
+ 0x9c39, 0x33ec,
+ 0x9c3a, 0x3d7e,
+ 0x9c3b, 0x16ef,
+ 0x9c3c, 0x33ef,
+ 0x9c3d, 0x33f3,
+ 0x9c3e, 0x16ee,
+ 0x9c3f, 0x33ea,
+ 0x9c40, 0x3297,
+ 0x9c41, 0x33ee,
+ 0x9c44, 0x33eb,
+ 0x9c45, 0x3e71,
+ 0x9c46, 0x33e8,
+ 0x9c48, 0x33e9,
+ 0x9c49, 0x16ec,
+ 0x9c4a, 0x3457,
+ 0x9c4b, 0x3459,
+ 0x9c4c, 0x345c,
+ 0x9c4d, 0x3458,
+ 0x9c4e, 0x345d,
+ 0x9c4f, 0x3c36,
+ 0x9c50, 0x3456,
+ 0x9c52, 0x3454,
+ 0x9c53, 0x3c37,
+ 0x9c54, 0x1719,
+ 0x9c55, 0x345a,
+ 0x9c56, 0x171b,
+ 0x9c57, 0x171a,
+ 0x9c58, 0x3455,
+ 0x9c59, 0x345b,
+ 0x9c5d, 0x3ebf,
+ 0x9c5e, 0x34b5,
+ 0x9c5f, 0x173a,
+ 0x9c60, 0x34b6,
+ 0x9c62, 0x34b4,
+ 0x9c63, 0x34b1,
+ 0x9c66, 0x34b3,
+ 0x9c67, 0x34b2,
+ 0x9c68, 0x34f4,
+ 0x9c6d, 0x34f6,
+ 0x9c6e, 0x34f5,
+ 0x9c71, 0x3514,
+ 0x9c72, 0x3ea1,
+ 0x9c73, 0x3513,
+ 0x9c74, 0x3512,
+ 0x9c75, 0x3515,
+ 0x9c77, 0x1760,
+ 0x9c79, 0x3541,
+ 0x9c7a, 0x3545,
+ 0x9c7b, 0x3c38,
+ 0x9c7c, 0x4512,
+ 0x9ce5, 0x0be2,
+ 0x9ce6, 0x235f,
+ 0x9ce7, 0x2610,
+ 0x9ce9, 0x0f79,
+ 0x9cea, 0x260e,
+ 0x9ced, 0x260f,
+ 0x9cf1, 0x2879,
+ 0x9cf3, 0x10fe,
+ 0x9cf4, 0x10fc,
+ 0x9cf5, 0x287b,
+ 0x9cf6, 0x10fd,
+ 0x9cf7, 0x2af4,
+ 0x9cf9, 0x2af7,
+ 0x9cfa, 0x2af1,
+ 0x9cfb, 0x2af8,
+ 0x9cfc, 0x2af0,
+ 0x9cfd, 0x2af2,
+ 0x9cff, 0x2af3,
+ 0x9d00, 0x2af6,
+ 0x9d02, 0x3f3b,
+ 0x9d03, 0x1284,
+ 0x9d04, 0x2afb,
+ 0x9d05, 0x2afa,
+ 0x9d06, 0x1282,
+ 0x9d07, 0x2af5,
+ 0x9d08, 0x2af9,
+ 0x9d09, 0x1283,
+ 0x9d0c, 0x3c46,
+ 0x9d10, 0x2d2d,
+ 0x9d12, 0x13ae,
+ 0x9d14, 0x2d28,
+ 0x9d15, 0x13aa,
+ 0x9d16, 0x3c7c,
+ 0x9d17, 0x2d25,
+ 0x9d18, 0x2d2b,
+ 0x9d19, 0x2d2e,
+ 0x9d1b, 0x13af,
+ 0x9d1d, 0x2d2a,
+ 0x9d1e, 0x2d27,
+ 0x9d1f, 0x2d2f,
+ 0x9d20, 0x2d26,
+ 0x9d21, 0x3c41,
+ 0x9d22, 0x2d2c,
+ 0x9d23, 0x13ab,
+ 0x9d25, 0x2d24,
+ 0x9d26, 0x13ac,
+ 0x9d28, 0x13ad,
+ 0x9d29, 0x2d29,
+ 0x9d2d, 0x2f00,
+ 0x9d2e, 0x2ef3,
+ 0x9d30, 0x2ef7,
+ 0x9d31, 0x2ef5,
+ 0x9d33, 0x2eef,
+ 0x9d34, 0x404a,
+ 0x9d36, 0x2ef2,
+ 0x9d37, 0x2efc,
+ 0x9d38, 0x2ef6,
+ 0x9d39, 0x392e,
+ 0x9d3b, 0x14bf,
+ 0x9d3d, 0x2efe,
+ 0x9d3e, 0x2efb,
+ 0x9d3f, 0x14c0,
+ 0x9d40, 0x2efd,
+ 0x9d41, 0x2ef0,
+ 0x9d42, 0x2ef9,
+ 0x9d44, 0x3fab,
+ 0x9d45, 0x2ef8,
+ 0x9d49, 0x47cd,
+ 0x9d4a, 0x3061,
+ 0x9d4b, 0x3063,
+ 0x9d4c, 0x3066,
+ 0x9d4e, 0x4539,
+ 0x9d4f, 0x3060,
+ 0x9d50, 0x3eca,
+ 0x9d51, 0x156f,
+ 0x9d52, 0x3068,
+ 0x9d53, 0x305f,
+ 0x9d54, 0x3069,
+ 0x9d56, 0x3065,
+ 0x9d57, 0x3067,
+ 0x9d58, 0x306b,
+ 0x9d59, 0x3064,
+ 0x9d5a, 0x306c,
+ 0x9d5b, 0x3062,
+ 0x9d5c, 0x305e,
+ 0x9d5d, 0x1570,
+ 0x9d5e, 0x3e6e,
+ 0x9d5f, 0x306a,
+ 0x9d60, 0x1571,
+ 0x9d61, 0x1601,
+ 0x9d67, 0x2ef1,
+ 0x9d68, 0x31bb,
+ 0x9d69, 0x31b2,
+ 0x9d6a, 0x1603,
+ 0x9d6b, 0x31ae,
+ 0x9d6c, 0x1604,
+ 0x9d6d, 0x3bac,
+ 0x9d6e, 0x433b,
+ 0x9d6f, 0x31b7,
+ 0x9d70, 0x31b1,
+ 0x9d71, 0x31a7,
+ 0x9d72, 0x1602,
+ 0x9d73, 0x31b4,
+ 0x9d74, 0x31af,
+ 0x9d77, 0x31a2,
+ 0x9d78, 0x31a9,
+ 0x9d79, 0x31b8,
+ 0x9d7b, 0x31b5,
+ 0x9d7c, 0x3efe,
+ 0x9d7d, 0x31ad,
+ 0x9d7e, 0x3925,
+ 0x9d7f, 0x31b9,
+ 0x9d80, 0x31a8,
+ 0x9d81, 0x31a3,
+ 0x9d82, 0x31b6,
+ 0x9d83, 0x3926,
+ 0x9d84, 0x31a5,
+ 0x9d85, 0x31b3,
+ 0x9d86, 0x31aa,
+ 0x9d87, 0x31ba,
+ 0x9d88, 0x31a6,
+ 0x9d89, 0x1600,
+ 0x9d8a, 0x31a4,
+ 0x9d8b, 0x31ab,
+ 0x9d90, 0x32a4,
+ 0x9d92, 0x32a2,
+ 0x9d93, 0x43f3,
+ 0x9d94, 0x32a7,
+ 0x9d96, 0x32b3,
+ 0x9d97, 0x32aa,
+ 0x9d98, 0x32a3,
+ 0x9d99, 0x329f,
+ 0x9d9a, 0x32ac,
+ 0x9d9b, 0x32a5,
+ 0x9d9c, 0x32a8,
+ 0x9d9d, 0x32a1,
+ 0x9d9e, 0x32af,
+ 0x9d9f, 0x329e,
+ 0x9da0, 0x32a6,
+ 0x9da1, 0x32ab,
+ 0x9da2, 0x32ad,
+ 0x9da3, 0x32b0,
+ 0x9da4, 0x32a0,
+ 0x9da5, 0x3c4b,
+ 0x9da6, 0x32b4,
+ 0x9da8, 0x32ae,
+ 0x9da9, 0x32b2,
+ 0x9daa, 0x32a9,
+ 0x9dab, 0x3f30,
+ 0x9dac, 0x3362,
+ 0x9dad, 0x3365,
+ 0x9daf, 0x16b1,
+ 0x9db1, 0x3364,
+ 0x9db2, 0x3369,
+ 0x9db3, 0x3367,
+ 0x9db4, 0x16b2,
+ 0x9db5, 0x335e,
+ 0x9db6, 0x3354,
+ 0x9db7, 0x3353,
+ 0x9db8, 0x16b4,
+ 0x9db9, 0x3360,
+ 0x9dbb, 0x335d,
+ 0x9dbc, 0x3355,
+ 0x9dbd, 0x47d0,
+ 0x9dbe, 0x335a,
+ 0x9dbf, 0x32b1,
+ 0x9dc0, 0x43f2,
+ 0x9dc1, 0x3356,
+ 0x9dc2, 0x16b3,
+ 0x9dc3, 0x335c,
+ 0x9dc4, 0x3929,
+ 0x9dc5, 0x335b,
+ 0x9dc7, 0x3357,
+ 0x9dc8, 0x3363,
+ 0x9dc9, 0x4579,
+ 0x9dca, 0x3358,
+ 0x9dcb, 0x33f9,
+ 0x9dcc, 0x3366,
+ 0x9dcd, 0x3368,
+ 0x9dce, 0x335f,
+ 0x9dcf, 0x3359,
+ 0x9dd0, 0x33fa,
+ 0x9dd1, 0x33fc,
+ 0x9dd2, 0x33f6,
+ 0x9dd3, 0x16f0,
+ 0x9dd4, 0x391e,
+ 0x9dd5, 0x3403,
+ 0x9dd6, 0x3401,
+ 0x9dd7, 0x16f1,
+ 0x9dd8, 0x3400,
+ 0x9dd9, 0x33ff,
+ 0x9dda, 0x33f8,
+ 0x9ddb, 0x33f5,
+ 0x9ddc, 0x33fb,
+ 0x9ddd, 0x3404,
+ 0x9dde, 0x33f7,
+ 0x9ddf, 0x33fd,
+ 0x9de1, 0x3466,
+ 0x9de2, 0x346b,
+ 0x9de3, 0x3461,
+ 0x9de4, 0x3464,
+ 0x9de5, 0x171c,
+ 0x9de6, 0x3468,
+ 0x9de8, 0x346f,
+ 0x9de9, 0x33fe,
+ 0x9deb, 0x3462,
+ 0x9dec, 0x346c,
+ 0x9ded, 0x3470,
+ 0x9dee, 0x3467,
+ 0x9def, 0x3460,
+ 0x9df0, 0x346a,
+ 0x9df2, 0x3469,
+ 0x9df3, 0x346e,
+ 0x9df4, 0x346d,
+ 0x9df5, 0x3402,
+ 0x9df6, 0x3465,
+ 0x9df7, 0x345f,
+ 0x9df8, 0x3463,
+ 0x9df9, 0x173b,
+ 0x9dfb, 0x345e,
+ 0x9dfc, 0x47d1,
+ 0x9dfd, 0x34c1,
+ 0x9dfe, 0x34b8,
+ 0x9dff, 0x34c0,
+ 0x9e00, 0x34bd,
+ 0x9e02, 0x34b7,
+ 0x9e03, 0x34ba,
+ 0x9e04, 0x34c2,
+ 0x9e05, 0x34bc,
+ 0x9e06, 0x34bb,
+ 0x9e07, 0x34b9,
+ 0x9e09, 0x34bf,
+ 0x9e0a, 0x457e,
+ 0x9e0b, 0x34f7,
+ 0x9e0c, 0x457a,
+ 0x9e0d, 0x34f8,
+ 0x9e0e, 0x3928,
+ 0x9e0f, 0x34fa,
+ 0x9e10, 0x34f9,
+ 0x9e11, 0x34fc,
+ 0x9e12, 0x34fb,
+ 0x9e13, 0x3517,
+ 0x9e14, 0x3516,
+ 0x9e15, 0x3530,
+ 0x9e17, 0x3531,
+ 0x9e18, 0x3c44,
+ 0x9e19, 0x353d,
+ 0x9e1a, 0x1765,
+ 0x9e1b, 0x1769,
+ 0x9e1c, 0x3f84,
+ 0x9e1d, 0x3546,
+ 0x9e1e, 0x176a,
+ 0x9e1f, 0x4513,
+ 0x9e75, 0x0be3,
+ 0x9e79, 0x1661,
+ 0x9e7a, 0x336a,
+ 0x9e7b, 0x43f8,
+ 0x9e7c, 0x173d,
+ 0x9e7f, 0x0be4,
+ 0x9e80, 0x2611,
+ 0x9e81, 0x3f0f,
+ 0x9e82, 0x0f7a,
+ 0x9e83, 0x2afc,
+ 0x9e84, 0x3f76,
+ 0x9e85, 0x3ef2,
+ 0x9e86, 0x2d31,
+ 0x9e88, 0x2d30,
+ 0x9e89, 0x2f02,
+ 0x9e8a, 0x2f01,
+ 0x9e8b, 0x14c1,
+ 0x9e8c, 0x306e,
+ 0x9e8d, 0x2f03,
+ 0x9e8e, 0x306d,
+ 0x9e90, 0x3931,
+ 0x9e91, 0x31bd,
+ 0x9e92, 0x1605,
+ 0x9e93, 0x1607,
+ 0x9e94, 0x31bc,
+ 0x9e95, 0x3932,
+ 0x9e96, 0x3fbc,
+ 0x9e97, 0x1606,
+ 0x9e98, 0x3f27,
+ 0x9e99, 0x32b6,
+ 0x9e9a, 0x32b8,
+ 0x9e9b, 0x32b7,
+ 0x9e9c, 0x336b,
+ 0x9e9d, 0x16b5,
+ 0x9e9e, 0x3933,
+ 0x9e9f, 0x171d,
+ 0x9ea0, 0x34c3,
+ 0x9ea1, 0x34fd,
+ 0x9ea2, 0x3934,
+ 0x9ea4, 0x354a,
+ 0x9ea5, 0x0be5,
+ 0x9ea6, 0x4944,
+ 0x9ea7, 0x287c,
+ 0x9ea8, 0x3f75,
+ 0x9ea9, 0x1285,
+ 0x9eaa, 0x3936,
+ 0x9eab, 0x3e92,
+ 0x9eac, 0x43f4,
+ 0x9ead, 0x2d34,
+ 0x9eae, 0x2d33,
+ 0x9eaf, 0x3937,
+ 0x9eb0, 0x2f04,
+ 0x9eb1, 0x47d4,
+ 0x9eb4, 0x1608,
+ 0x9eb5, 0x1662,
+ 0x9eb6, 0x3405,
+ 0x9eb7, 0x3542,
+ 0x9ebb, 0x0be6,
+ 0x9ebc, 0x10ff,
+ 0x9ebd, 0x47d5,
+ 0x9ebe, 0x1286,
+ 0x9ebf, 0x3d78,
+ 0x9ec0, 0x31be,
+ 0x9ec1, 0x3939,
+ 0x9ec2, 0x3471,
+ 0x9ec3, 0x0dbb,
+ 0x9ec4, 0x4514,
+ 0x9ec6, 0x47d6,
+ 0x9ec7, 0x4577,
+ 0x9ec8, 0x2f05,
+ 0x9ecc, 0x1751,
+ 0x9ecd, 0x0dbc,
+ 0x9ece, 0x1287,
+ 0x9ecf, 0x14c2,
+ 0x9ed0, 0x3472,
+ 0x9ed1, 0x0dbd,
+ 0x9ed3, 0x2afd,
+ 0x9ed4, 0x13b1,
+ 0x9ed5, 0x2d35,
+ 0x9ed8, 0x13b0,
+ 0x9eda, 0x2f06,
+ 0x9edb, 0x14c6,
+ 0x9edc, 0x14c4,
+ 0x9ede, 0x14c3,
+ 0x9edf, 0x306f,
+ 0x9ee0, 0x1572,
+ 0x9ee2, 0x47d8,
+ 0x9ee4, 0x32ba,
+ 0x9ee5, 0x32b9,
+ 0x9ee6, 0x32bc,
+ 0x9ee7, 0x32bb,
+ 0x9ee8, 0x1663,
+ 0x9eeb, 0x336c,
+ 0x9eed, 0x336e,
+ 0x9eee, 0x336d,
+ 0x9eef, 0x16b6,
+ 0x9ef0, 0x3406,
+ 0x9ef1, 0x47d9,
+ 0x9ef2, 0x3473,
+ 0x9ef4, 0x171e,
+ 0x9ef5, 0x34fe,
+ 0x9ef6, 0x3518,
+ 0x9ef7, 0x1762,
+ 0x9ef8, 0x47da,
+ 0x9ef9, 0x2360,
+ 0x9efa, 0x2d37,
+ 0x9efb, 0x2f07,
+ 0x9efc, 0x31bf,
+ 0x9efd, 0x2612,
+ 0x9efe, 0x47ce,
+ 0x9eff, 0x2f08,
+ 0x9f00, 0x3071,
+ 0x9f01, 0x3070,
+ 0x9f02, 0x3940,
+ 0x9f06, 0x3475,
+ 0x9f07, 0x173f,
+ 0x9f08, 0x3941,
+ 0x9f09, 0x34ff,
+ 0x9f0a, 0x3519,
+ 0x9f0e, 0x0f7b,
+ 0x9f0f, 0x2afe,
+ 0x9f12, 0x2d38,
+ 0x9f13, 0x0f7c,
+ 0x9f15, 0x1573,
+ 0x9f16, 0x3072,
+ 0x9f17, 0x3945,
+ 0x9f18, 0x3370,
+ 0x9f19, 0x16b7,
+ 0x9f1a, 0x3371,
+ 0x9f1b, 0x336f,
+ 0x9f1c, 0x3476,
+ 0x9f1e, 0x34c4,
+ 0x9f20, 0x0f7d,
+ 0x9f22, 0x2f0b,
+ 0x9f23, 0x2f0a,
+ 0x9f24, 0x2f09,
+ 0x9f25, 0x3073,
+ 0x9f26, 0x3f90,
+ 0x9f27, 0x4620,
+ 0x9f28, 0x3077,
+ 0x9f29, 0x3076,
+ 0x9f2a, 0x3075,
+ 0x9f2b, 0x3074,
+ 0x9f2c, 0x1574,
+ 0x9f2d, 0x31c0,
+ 0x9f2e, 0x32be,
+ 0x9f2f, 0x1664,
+ 0x9f30, 0x32bd,
+ 0x9f31, 0x3372,
+ 0x9f32, 0x3409,
+ 0x9f33, 0x3408,
+ 0x9f34, 0x16f2,
+ 0x9f35, 0x3407,
+ 0x9f36, 0x3479,
+ 0x9f37, 0x3478,
+ 0x9f38, 0x3477,
+ 0x9f39, 0x3947,
+ 0x9f3b, 0x1100,
+ 0x9f3d, 0x2d39,
+ 0x9f3e, 0x14c7,
+ 0x9f40, 0x31c1,
+ 0x9f42, 0x340a,
+ 0x9f43, 0x347a,
+ 0x9f44, 0x47db,
+ 0x9f45, 0x394a,
+ 0x9f46, 0x34c5,
+ 0x9f47, 0x3500,
+ 0x9f48, 0x3532,
+ 0x9f49, 0x354c,
+ 0x9f4a, 0x1101,
+ 0x9f4b, 0x14c8,
+ 0x9f4c, 0x3078,
+ 0x9f4d, 0x31c3,
+ 0x9f4e, 0x3373,
+ 0x9f4f, 0x347b,
+ 0x9f50, 0x4943,
+ 0x9f52, 0x1289,
+ 0x9f53, 0x3f80,
+ 0x9f54, 0x2f0c,
+ 0x9f55, 0x3079,
+ 0x9f56, 0x31c4,
+ 0x9f59, 0x32c3,
+ 0x9f5a, 0x3f23,
+ 0x9f5b, 0x32bf,
+ 0x9f5c, 0x16b8,
+ 0x9f5d, 0x32c2,
+ 0x9f5e, 0x32c1,
+ 0x9f5f, 0x1665,
+ 0x9f60, 0x32c0,
+ 0x9f61, 0x1667,
+ 0x9f62, 0x394f,
+ 0x9f63, 0x1666,
+ 0x9f64, 0x3375,
+ 0x9f65, 0x3374,
+ 0x9f66, 0x16b9,
+ 0x9f69, 0x3950,
+ 0x9f6a, 0x16f4,
+ 0x9f6b, 0x340b,
+ 0x9f6c, 0x16f3,
+ 0x9f6e, 0x347e,
+ 0x9f70, 0x347d,
+ 0x9f71, 0x347c,
+ 0x9f72, 0x1741,
+ 0x9f74, 0x34c6,
+ 0x9f77, 0x1740,
+ 0x9f78, 0x3501,
+ 0x9f79, 0x3504,
+ 0x9f7a, 0x3503,
+ 0x9f7b, 0x3502,
+ 0x9f7e, 0x354b,
+ 0x9f7f, 0x4680,
+ 0x9f8d, 0x13b2,
+ 0x9f8e, 0x3952,
+ 0x9f90, 0x157c,
+ 0x9f91, 0x32c4,
+ 0x9f92, 0x3376,
+ 0x9f94, 0x16f5,
+ 0x9f95, 0x340c,
+ 0x9f98, 0x354d,
+ 0x9f99, 0x4587,
+ 0x9f9c, 0x13b3,
+ 0x9f9f, 0x4646,
+ 0x9fa0, 0x2f0d,
+ 0x9fa2, 0x340d,
+ 0x9fa4, 0x351a,
+ 0x9fa5, 0x3f70,
+ 0xfa0c, 0x0274,
+ 0xfa0d, 0x2381,
+ 0xfe30, 0x006d,
+ 0xfe31, 0x007a,
+ 0xfe33, 0x35af,
+ 0xfe34, 0x35b1,
+ 0xfe35, 0x0082,
+ 0xfe37, 0x0086,
+ 0xfe39, 0x008a,
+ 0xfe3b, 0x008e,
+ 0xfe3d, 0x0092,
+ 0xfe3f, 0x0096,
+ 0xfe41, 0x009a,
+ 0xfe43, 0x009e,
+ 0xfe49, 0x00c7,
+ 0xfe4b, 0x00cb,
+ 0xfe4d, 0x00c9,
+ 0xfe4f, 0x35b2,
+ 0xfe50, 0x0070,
+ 0xfe52, 0x0072,
+ 0xfe54, 0x0074,
+ 0xfe59, 0x00a0,
+ 0xfe5f, 0x00cd,
+ 0xfe62, 0x00df,
+ 0xfe69, 0x010c,
+ 0xff01, 0x006c,
+ 0xff02, 0x36e4,
+ 0xff03, 0x00ae,
+ 0xff04, 0x0103,
+ 0xff05, 0x0108,
+ 0xff06, 0x00af,
+ 0xff07, 0x36e3,
+ 0xff08, 0x0080,
+ 0xff0a, 0x00b0,
+ 0xff0b, 0x00d0,
+ 0xff0c, 0x0064,
+ 0xff0d, 0x00d1,
+ 0xff0e, 0x0067,
+ 0xff0f, 0x0101,
+ 0xff10, 0x014d,
+ 0xff1a, 0x006a,
+ 0xff1b, 0x0069,
+ 0xff1c, 0x00d6,
+ 0xff1d, 0x00d8,
+ 0xff1e, 0x00d7,
+ 0xff1f, 0x006b,
+ 0xff20, 0x0109,
+ 0xff21, 0x016d,
+ 0xff3b, 0x35be,
+ 0xff3c, 0x0102,
+ 0xff3d, 0x35bf,
+ 0xff3e, 0x35b4,
+ 0xff3f, 0x00c5,
+ 0xff41, 0x0187,
+ 0xff5b, 0x0084,
+ 0xff5c, 0x0078,
+ 0xff5d, 0x0085,
+ 0xff64, 0x0071,
+ 0xffe2, 0x36e1,
+ 0xffe4, 0x36e2,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13UniCNSUCS2HEnc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13UniCNSUCS2HMap2, 15455
+};
+
+static Gushort cns13UniCNSUCS2VMap2[30936] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x00a2, 0x0106,
+ 0x00a5, 0x0104,
+ 0x00a7, 0x00b2,
+ 0x00a8, 0x35b3,
+ 0x00ac, 0x36e1,
+ 0x00b0, 0x0118,
+ 0x00b1, 0x00d4,
+ 0x00b7, 0x0073,
+ 0x00c0, 0x4964,
+ 0x00c1, 0x4962,
+ 0x00c8, 0x4968,
+ 0x00c9, 0x4966,
+ 0x00ca, 0x4971,
+ 0x00d2, 0x496c,
+ 0x00d3, 0x496a,
+ 0x00d7, 0x00d2,
+ 0x00e0, 0x4975,
+ 0x00e1, 0x4973,
+ 0x00e8, 0x497a,
+ 0x00e9, 0x4978,
+ 0x00ea, 0x4990,
+ 0x00ec, 0x497e,
+ 0x00ed, 0x497c,
+ 0x00f2, 0x4982,
+ 0x00f3, 0x4980,
+ 0x00f7, 0x00d3,
+ 0x00f8, 0x4998,
+ 0x00f9, 0x4986,
+ 0x00fa, 0x4984,
+ 0x00fc, 0x498b,
+ 0x0100, 0x4961,
+ 0x0101, 0x4972,
+ 0x0112, 0x4965,
+ 0x0113, 0x4977,
+ 0x011a, 0x4967,
+ 0x011b, 0x4979,
+ 0x012b, 0x497b,
+ 0x014b, 0x4999,
+ 0x014c, 0x4969,
+ 0x014d, 0x497f,
+ 0x0153, 0x4997,
+ 0x016b, 0x4983,
+ 0x01cd, 0x4963,
+ 0x01ce, 0x4974,
+ 0x01d0, 0x497d,
+ 0x01d1, 0x496b,
+ 0x01d2, 0x4981,
+ 0x01d4, 0x4985,
+ 0x01d6, 0x4987,
+ 0x01d8, 0x4988,
+ 0x01da, 0x4989,
+ 0x01dc, 0x498a,
+ 0x0250, 0x4993,
+ 0x0251, 0x4976,
+ 0x0254, 0x4995,
+ 0x025b, 0x4994,
+ 0x0261, 0x4991,
+ 0x026a, 0x499b,
+ 0x0275, 0x4996,
+ 0x0283, 0x4992,
+ 0x028a, 0x499a,
+ 0x02c6, 0x35b4,
+ 0x02c7, 0x01f8,
+ 0x02ca, 0x01f7,
+ 0x02cb, 0x01f9,
+ 0x02d9, 0x01f6,
+ 0x0308, 0x35b3,
+ 0x0391, 0x01a1,
+ 0x03a3, 0x01b2,
+ 0x03b1, 0x01b9,
+ 0x03c3, 0x01ca,
+ 0x0401, 0x3670,
+ 0x0410, 0x366a,
+ 0x0416, 0x3671,
+ 0x0436, 0x3692,
+ 0x0451, 0x3691,
+ 0x1ebe, 0x496e,
+ 0x1ebf, 0x498d,
+ 0x1ec0, 0x4970,
+ 0x1ec1, 0x498f,
+ 0x2013, 0x0079,
+ 0x2014, 0x007b,
+ 0x2018, 0x00a6,
+ 0x201c, 0x00a8,
+ 0x2022, 0x0068,
+ 0x2025, 0x006f,
+ 0x2026, 0x006e,
+ 0x2032, 0x00ad,
+ 0x2035, 0x00ac,
+ 0x203b, 0x00b1,
+ 0x203e, 0x00c3,
+ 0x20ac, 0x44c1,
+ 0x2103, 0x010a,
+ 0x2105, 0x00c2,
+ 0x2109, 0x010b,
+ 0x2116, 0x36e6,
+ 0x2121, 0x36e7,
+ 0x2160, 0x0157,
+ 0x2170, 0x020e,
+ 0x2190, 0x00f8,
+ 0x2191, 0x00f5,
+ 0x2192, 0x00f7,
+ 0x2193, 0x00f6,
+ 0x2196, 0x00f9,
+ 0x2198, 0x00fc,
+ 0x2199, 0x00fb,
+ 0x21b8, 0x36ad,
+ 0x21e7, 0x36ac,
+ 0x221a, 0x00d5,
+ 0x221e, 0x00dc,
+ 0x221f, 0x00e9,
+ 0x2220, 0x00e8,
+ 0x2223, 0x00fe,
+ 0x2225, 0x00fd,
+ 0x2229, 0x00e5,
+ 0x222b, 0x00ed,
+ 0x222e, 0x00ee,
+ 0x2234, 0x00f0,
+ 0x2235, 0x00ef,
+ 0x223c, 0x00e4,
+ 0x2252, 0x00dd,
+ 0x2260, 0x00db,
+ 0x2261, 0x00de,
+ 0x2266, 0x00d9,
+ 0x22a5, 0x00e7,
+ 0x22bf, 0x00ea,
+ 0x2400, 0x0232,
+ 0x2421, 0x0252,
+ 0x2460, 0x01fa,
+ 0x2474, 0x0204,
+ 0x2500, 0x0137,
+ 0x2502, 0x0138,
+ 0x250c, 0x013a,
+ 0x2510, 0x013b,
+ 0x2514, 0x013c,
+ 0x2518, 0x013d,
+ 0x251c, 0x0135,
+ 0x2524, 0x0134,
+ 0x252c, 0x0133,
+ 0x2534, 0x0132,
+ 0x253c, 0x0131,
+ 0x2550, 0x0142,
+ 0x2551, 0x370a,
+ 0x2552, 0x36f8,
+ 0x2553, 0x3701,
+ 0x2554, 0x36ef,
+ 0x2555, 0x36fa,
+ 0x2556, 0x3703,
+ 0x2557, 0x36f1,
+ 0x2558, 0x36fe,
+ 0x2559, 0x3707,
+ 0x255a, 0x36f5,
+ 0x255b, 0x3700,
+ 0x255c, 0x3709,
+ 0x255d, 0x36f7,
+ 0x255e, 0x0143,
+ 0x255f, 0x3704,
+ 0x2560, 0x36f2,
+ 0x2561, 0x0145,
+ 0x2562, 0x3706,
+ 0x2563, 0x36f4,
+ 0x2564, 0x36f9,
+ 0x2565, 0x3702,
+ 0x2566, 0x36f0,
+ 0x2567, 0x36ff,
+ 0x2568, 0x3708,
+ 0x2569, 0x36f6,
+ 0x256a, 0x0144,
+ 0x256b, 0x3705,
+ 0x256c, 0x36f3,
+ 0x256d, 0x013e,
+ 0x256f, 0x0141,
+ 0x2570, 0x0140,
+ 0x2571, 0x014a,
+ 0x2581, 0x0122,
+ 0x2589, 0x0130,
+ 0x258a, 0x012f,
+ 0x258b, 0x012e,
+ 0x258c, 0x012d,
+ 0x258d, 0x012c,
+ 0x258e, 0x012b,
+ 0x258f, 0x012a,
+ 0x2593, 0x3710,
+ 0x2594, 0x0136,
+ 0x2595, 0x0139,
+ 0x25a0, 0x00be,
+ 0x25a1, 0x00bd,
+ 0x25b2, 0x00b7,
+ 0x25b3, 0x00b6,
+ 0x25bc, 0x00c0,
+ 0x25bd, 0x00bf,
+ 0x25c6, 0x00bc,
+ 0x25c7, 0x00bb,
+ 0x25cb, 0x00b4,
+ 0x25ce, 0x00b8,
+ 0x25cf, 0x00b5,
+ 0x25e2, 0x0146,
+ 0x25e4, 0x0149,
+ 0x25e5, 0x0148,
+ 0x2605, 0x00ba,
+ 0x2606, 0x00b9,
+ 0x2609, 0x00f4,
+ 0x2640, 0x00f1,
+ 0x2641, 0x00f3,
+ 0x2642, 0x00f2,
+ 0x273d, 0x35c0,
+ 0x2e80, 0x44c8,
+ 0x2e84, 0x451c,
+ 0x2e86, 0x451d,
+ 0x2e8a, 0x4520,
+ 0x2e8c, 0x4521,
+ 0x2e95, 0x4523,
+ 0x2e9c, 0x4524,
+ 0x2e9d, 0x02dc,
+ 0x2ea5, 0x4525,
+ 0x2ea7, 0x4526,
+ 0x2eaa, 0x4527,
+ 0x2eac, 0x4528,
+ 0x2eae, 0x4529,
+ 0x2eb6, 0x452a,
+ 0x2ebc, 0x452b,
+ 0x2ebe, 0x452c,
+ 0x2ec6, 0x0509,
+ 0x2eca, 0x452d,
+ 0x2ecc, 0x452e,
+ 0x2ecf, 0x4530,
+ 0x2ed6, 0x4531,
+ 0x2ede, 0x4533,
+ 0x2ee3, 0x09f6,
+ 0x2f33, 0x0227,
+ 0x3000, 0x0063,
+ 0x3001, 0x0065,
+ 0x3003, 0x00b3,
+ 0x3005, 0x35ba,
+ 0x3008, 0x0094,
+ 0x300a, 0x0090,
+ 0x300c, 0x0098,
+ 0x300e, 0x009c,
+ 0x3010, 0x008c,
+ 0x3012, 0x0105,
+ 0x3014, 0x0088,
+ 0x301d, 0x00aa,
+ 0x3021, 0x0161,
+ 0x3041, 0x35c1,
+ 0x309b, 0x44c6,
+ 0x309d, 0x35b7,
+ 0x30a1, 0x3614,
+ 0x30fc, 0x35bd,
+ 0x30fd, 0x35b5,
+ 0x3105, 0x01d1,
+ 0x3231, 0x36e5,
+ 0x32a3, 0x00c1,
+ 0x338e, 0x0115,
+ 0x339c, 0x0110,
+ 0x33a1, 0x0114,
+ 0x33c4, 0x0117,
+ 0x33ce, 0x0113,
+ 0x33d1, 0x00ec,
+ 0x33d2, 0x00eb,
+ 0x33d5, 0x010f,
+ 0x3435, 0x39bd,
+ 0x3440, 0x3c67,
+ 0x344c, 0x4593,
+ 0x3464, 0x3a85,
+ 0x3473, 0x3dc5,
+ 0x347a, 0x4033,
+ 0x347d, 0x4597,
+ 0x347e, 0x46a3,
+ 0x3493, 0x439e,
+ 0x3496, 0x37dc,
+ 0x34a5, 0x4598,
+ 0x34af, 0x3c7f,
+ 0x34bc, 0x4380,
+ 0x34c1, 0x44fb,
+ 0x34c8, 0x3d00,
+ 0x34df, 0x3ea4,
+ 0x34e4, 0x3e54,
+ 0x34fb, 0x3dca,
+ 0x3506, 0x4336,
+ 0x353e, 0x44e7,
+ 0x3551, 0x45a1,
+ 0x3553, 0x43a5,
+ 0x3561, 0x40d8,
+ 0x356d, 0x45a4,
+ 0x3570, 0x3b2f,
+ 0x3572, 0x45a5,
+ 0x3577, 0x3ecb,
+ 0x3578, 0x4379,
+ 0x3584, 0x39fb,
+ 0x3597, 0x3b2d,
+ 0x3598, 0x45b0,
+ 0x35a1, 0x40e2,
+ 0x35a5, 0x45b1,
+ 0x35ad, 0x3efc,
+ 0x35bf, 0x45b2,
+ 0x35c1, 0x4580,
+ 0x35c5, 0x45b4,
+ 0x35c7, 0x459f,
+ 0x35ca, 0x3e43,
+ 0x35ce, 0x3e81,
+ 0x35d2, 0x3fc9,
+ 0x35d6, 0x3fb5,
+ 0x35db, 0x470d,
+ 0x35dd, 0x43ac,
+ 0x35f1, 0x4696,
+ 0x35f2, 0x4627,
+ 0x35f3, 0x3f6c,
+ 0x35fb, 0x45c8,
+ 0x35fe, 0x3f6a,
+ 0x3609, 0x45f5,
+ 0x3618, 0x4871,
+ 0x361a, 0x461a,
+ 0x3623, 0x40c6,
+ 0x362d, 0x3e86,
+ 0x3635, 0x492e,
+ 0x3639, 0x4165,
+ 0x363e, 0x3a08,
+ 0x3647, 0x4806,
+ 0x3648, 0x3806,
+ 0x3649, 0x4013,
+ 0x364e, 0x4698,
+ 0x365f, 0x3df3,
+ 0x367a, 0x3ee3,
+ 0x3681, 0x45a6,
+ 0x369a, 0x3c71,
+ 0x36a5, 0x4902,
+ 0x36aa, 0x3b30,
+ 0x36ac, 0x4900,
+ 0x36b0, 0x3cdf,
+ 0x36b1, 0x40cd,
+ 0x36b5, 0x3bc2,
+ 0x36b9, 0x4887,
+ 0x36bc, 0x3cff,
+ 0x36c1, 0x37c5,
+ 0x36c3, 0x40e5,
+ 0x36c4, 0x3905,
+ 0x36c5, 0x4296,
+ 0x36c7, 0x3d3a,
+ 0x36c8, 0x4820,
+ 0x36d3, 0x3a38,
+ 0x36d4, 0x3bb3,
+ 0x36d6, 0x3d0c,
+ 0x36dd, 0x3a36,
+ 0x36e1, 0x397c,
+ 0x36e2, 0x3cdd,
+ 0x36e5, 0x4216,
+ 0x36e6, 0x40fc,
+ 0x36f5, 0x3a18,
+ 0x3701, 0x3a34,
+ 0x3703, 0x460f,
+ 0x3708, 0x40ff,
+ 0x370a, 0x3cd5,
+ 0x370d, 0x4238,
+ 0x371c, 0x3dfe,
+ 0x3722, 0x3979,
+ 0x3723, 0x3980,
+ 0x3725, 0x3849,
+ 0x372c, 0x3c8c,
+ 0x372d, 0x3d37,
+ 0x3730, 0x495c,
+ 0x3732, 0x4106,
+ 0x3733, 0x3997,
+ 0x373a, 0x3e56,
+ 0x3740, 0x4202,
+ 0x3743, 0x4036,
+ 0x3762, 0x3db6,
+ 0x376f, 0x47cb,
+ 0x3797, 0x45ed,
+ 0x37a0, 0x3a28,
+ 0x37b9, 0x43b7,
+ 0x37be, 0x393e,
+ 0x37f2, 0x3ba1,
+ 0x37f8, 0x42d2,
+ 0x37fb, 0x3ef5,
+ 0x380f, 0x462c,
+ 0x3819, 0x39af,
+ 0x3820, 0x462f,
+ 0x382d, 0x412e,
+ 0x3836, 0x4133,
+ 0x3838, 0x43bb,
+ 0x3863, 0x46c3,
+ 0x38a0, 0x4145,
+ 0x38c3, 0x3912,
+ 0x38cc, 0x4076,
+ 0x38d1, 0x3a95,
+ 0x38fa, 0x44eb,
+ 0x3908, 0x4632,
+ 0x3914, 0x43be,
+ 0x3927, 0x3c31,
+ 0x3932, 0x4182,
+ 0x393f, 0x4633,
+ 0x394d, 0x4634,
+ 0x3963, 0x4163,
+ 0x3980, 0x3874,
+ 0x3989, 0x4638,
+ 0x398a, 0x3ce8,
+ 0x3992, 0x4376,
+ 0x3999, 0x39ba,
+ 0x399b, 0x3db3,
+ 0x39a1, 0x3e19,
+ 0x39a4, 0x3e0f,
+ 0x39b8, 0x463b,
+ 0x39dc, 0x3ece,
+ 0x39e2, 0x46c8,
+ 0x39e5, 0x393b,
+ 0x39ec, 0x4310,
+ 0x39f8, 0x463e,
+ 0x39fb, 0x4345,
+ 0x39fe, 0x4368,
+ 0x3a01, 0x41e0,
+ 0x3a03, 0x4640,
+ 0x3a06, 0x4377,
+ 0x3a17, 0x4190,
+ 0x3a18, 0x438f,
+ 0x3a29, 0x3a5e,
+ 0x3a2a, 0x3edf,
+ 0x3a34, 0x4319,
+ 0x3a4b, 0x4644,
+ 0x3a52, 0x3ed3,
+ 0x3a57, 0x419e,
+ 0x3a5c, 0x3fc4,
+ 0x3a5e, 0x3b07,
+ 0x3a66, 0x419c,
+ 0x3a67, 0x4333,
+ 0x3a97, 0x4647,
+ 0x3aab, 0x4091,
+ 0x3abd, 0x4649,
+ 0x3ade, 0x414c,
+ 0x3ae0, 0x3a7a,
+ 0x3af0, 0x46b2,
+ 0x3af2, 0x464c,
+ 0x3afb, 0x3af2,
+ 0x3b0e, 0x38e8,
+ 0x3b19, 0x46c5,
+ 0x3b22, 0x464e,
+ 0x3b2b, 0x4956,
+ 0x3b39, 0x474b,
+ 0x3b42, 0x4650,
+ 0x3b58, 0x4652,
+ 0x3b60, 0x393a,
+ 0x3b71, 0x4656,
+ 0x3b72, 0x4655,
+ 0x3b7b, 0x4657,
+ 0x3b7c, 0x385a,
+ 0x3b80, 0x41e2,
+ 0x3b96, 0x3a9c,
+ 0x3b99, 0x3a98,
+ 0x3ba1, 0x41e9,
+ 0x3bbc, 0x43c8,
+ 0x3bbe, 0x3db1,
+ 0x3bc2, 0x4134,
+ 0x3bc4, 0x3aa0,
+ 0x3bd7, 0x3aac,
+ 0x3bdd, 0x465f,
+ 0x3bec, 0x4664,
+ 0x3bf2, 0x4666,
+ 0x3bf3, 0x41f3,
+ 0x3bf4, 0x3a6e,
+ 0x3c0d, 0x41f7,
+ 0x3c11, 0x3e40,
+ 0x3c15, 0x3998,
+ 0x3c54, 0x3e00,
+ 0x3ccb, 0x4670,
+ 0x3ccd, 0x3ce5,
+ 0x3cd1, 0x4003,
+ 0x3cd6, 0x3cf7,
+ 0x3cdc, 0x404e,
+ 0x3ceb, 0x4217,
+ 0x3cef, 0x4675,
+ 0x3d13, 0x3773,
+ 0x3d1d, 0x393c,
+ 0x3d32, 0x4957,
+ 0x3d3b, 0x4245,
+ 0x3d46, 0x4685,
+ 0x3d4c, 0x3ceb,
+ 0x3d4e, 0x4242,
+ 0x3d51, 0x38ea,
+ 0x3d5f, 0x4159,
+ 0x3d62, 0x3c5e,
+ 0x3d69, 0x3cea,
+ 0x3d6a, 0x4689,
+ 0x3d6f, 0x3cfc,
+ 0x3d75, 0x468a,
+ 0x3d7d, 0x3c2f,
+ 0x3d85, 0x494b,
+ 0x3d8a, 0x468d,
+ 0x3d8f, 0x3abd,
+ 0x3d91, 0x468f,
+ 0x3da5, 0x3d56,
+ 0x3dad, 0x4699,
+ 0x3db4, 0x40a6,
+ 0x3dbf, 0x37d0,
+ 0x3dc6, 0x48de,
+ 0x3dc7, 0x4164,
+ 0x3dcc, 0x3d6f,
+ 0x3dcd, 0x3af3,
+ 0x3dd3, 0x37e1,
+ 0x3ddb, 0x3fff,
+ 0x3de7, 0x3999,
+ 0x3de8, 0x425d,
+ 0x3deb, 0x3e5a,
+ 0x3df3, 0x46d4,
+ 0x3df7, 0x48ab,
+ 0x3dfc, 0x462b,
+ 0x3dfd, 0x3c14,
+ 0x3e06, 0x491d,
+ 0x3e40, 0x4169,
+ 0x3e43, 0x436d,
+ 0x3e48, 0x4595,
+ 0x3e55, 0x427f,
+ 0x3e74, 0x3ee2,
+ 0x3ea8, 0x4304,
+ 0x3ea9, 0x46ed,
+ 0x3eaa, 0x4075,
+ 0x3ead, 0x3b9d,
+ 0x3eb1, 0x3ad8,
+ 0x3eb8, 0x3a4b,
+ 0x3ebf, 0x3b0b,
+ 0x3ec2, 0x3bd8,
+ 0x3ec7, 0x3975,
+ 0x3eca, 0x46f1,
+ 0x3ecc, 0x3be2,
+ 0x3ed0, 0x3854,
+ 0x3ed1, 0x46f2,
+ 0x3ed6, 0x3cad,
+ 0x3ed7, 0x429f,
+ 0x3eda, 0x3d02,
+ 0x3ede, 0x39f2,
+ 0x3ee1, 0x3ca8,
+ 0x3ee2, 0x46f6,
+ 0x3ee7, 0x3bdc,
+ 0x3ee9, 0x3ca4,
+ 0x3eeb, 0x396a,
+ 0x3ef0, 0x46f7,
+ 0x3ef3, 0x3add,
+ 0x3ef4, 0x46f8,
+ 0x3efa, 0x46f9,
+ 0x3efc, 0x3be8,
+ 0x3eff, 0x3af5,
+ 0x3f00, 0x3c0d,
+ 0x3f04, 0x42c3,
+ 0x3f06, 0x3ad7,
+ 0x3f0e, 0x46fb,
+ 0x3f53, 0x46fc,
+ 0x3f58, 0x3ae9,
+ 0x3f59, 0x4089,
+ 0x3f63, 0x3ae6,
+ 0x3f7c, 0x4700,
+ 0x3f93, 0x45cd,
+ 0x3fc0, 0x43cf,
+ 0x3fd7, 0x43d1,
+ 0x3fdc, 0x4704,
+ 0x3fe5, 0x46df,
+ 0x3fed, 0x4335,
+ 0x3ff9, 0x45d7,
+ 0x3ffa, 0x4354,
+ 0x4004, 0x410e,
+ 0x401d, 0x4709,
+ 0x4039, 0x470b,
+ 0x4045, 0x470c,
+ 0x4053, 0x45b6,
+ 0x4057, 0x399d,
+ 0x4062, 0x3bcb,
+ 0x4065, 0x3fd3,
+ 0x406a, 0x470f,
+ 0x406f, 0x4710,
+ 0x40a8, 0x43d5,
+ 0x40bb, 0x45c0,
+ 0x40bf, 0x3eec,
+ 0x40c8, 0x3b0e,
+ 0x40d8, 0x41ab,
+ 0x40df, 0x3e17,
+ 0x40fa, 0x3ebe,
+ 0x4103, 0x43d7,
+ 0x4104, 0x425c,
+ 0x4109, 0x471c,
+ 0x410e, 0x3b1b,
+ 0x4132, 0x3b25,
+ 0x4167, 0x471f,
+ 0x416c, 0x38ae,
+ 0x416e, 0x3b23,
+ 0x417f, 0x3b82,
+ 0x4190, 0x46c0,
+ 0x41b2, 0x4720,
+ 0x41c4, 0x4723,
+ 0x41ca, 0x373f,
+ 0x41cf, 0x4726,
+ 0x41db, 0x37bf,
+ 0x41ef, 0x3743,
+ 0x41f9, 0x3b3e,
+ 0x4211, 0x3b41,
+ 0x4240, 0x37f1,
+ 0x4260, 0x472b,
+ 0x426a, 0x3b55,
+ 0x427a, 0x472c,
+ 0x428c, 0x472f,
+ 0x4294, 0x4731,
+ 0x42b5, 0x4010,
+ 0x42b9, 0x38a6,
+ 0x42bc, 0x3c8a,
+ 0x42f4, 0x3bb9,
+ 0x42fb, 0x3cee,
+ 0x42fc, 0x41e6,
+ 0x432b, 0x377d,
+ 0x436e, 0x46ca,
+ 0x4397, 0x473b,
+ 0x43ba, 0x435f,
+ 0x43c1, 0x4695,
+ 0x43d9, 0x433e,
+ 0x43df, 0x3e49,
+ 0x43ed, 0x4745,
+ 0x43f2, 0x3e48,
+ 0x4401, 0x474a,
+ 0x4402, 0x3b73,
+ 0x4413, 0x474f,
+ 0x4425, 0x4751,
+ 0x442d, 0x4752,
+ 0x447a, 0x37af,
+ 0x448f, 0x4758,
+ 0x449f, 0x3ae2,
+ 0x44a0, 0x37ed,
+ 0x44a2, 0x4079,
+ 0x44b0, 0x475c,
+ 0x44b7, 0x3fa1,
+ 0x44c0, 0x3c07,
+ 0x44c5, 0x4210,
+ 0x44ce, 0x3d23,
+ 0x44dd, 0x39dd,
+ 0x44df, 0x3d22,
+ 0x44e4, 0x37e2,
+ 0x44e9, 0x41cf,
+ 0x44ea, 0x3b71,
+ 0x44eb, 0x3cf2,
+ 0x44ec, 0x3eb4,
+ 0x44f4, 0x3992,
+ 0x4503, 0x469f,
+ 0x4504, 0x4763,
+ 0x4509, 0x3e50,
+ 0x450b, 0x37d4,
+ 0x4516, 0x37f9,
+ 0x451d, 0x3767,
+ 0x4527, 0x37f7,
+ 0x452e, 0x3cd3,
+ 0x4533, 0x3c51,
+ 0x453b, 0x476a,
+ 0x453d, 0x38c4,
+ 0x453f, 0x3e12,
+ 0x4543, 0x37f3,
+ 0x4551, 0x3ae4,
+ 0x4552, 0x40b3,
+ 0x4555, 0x423e,
+ 0x455c, 0x378b,
+ 0x4562, 0x4940,
+ 0x456a, 0x3804,
+ 0x4577, 0x476e,
+ 0x4585, 0x38c5,
+ 0x45e9, 0x3ee4,
+ 0x4606, 0x4773,
+ 0x460f, 0x3815,
+ 0x4615, 0x3843,
+ 0x4617, 0x4774,
+ 0x465b, 0x381d,
+ 0x467a, 0x39e9,
+ 0x4680, 0x3d01,
+ 0x46cf, 0x3ba0,
+ 0x46d0, 0x3dfa,
+ 0x46f5, 0x3b9f,
+ 0x4713, 0x3833,
+ 0x4718, 0x3dc7,
+ 0x474e, 0x3ebc,
+ 0x477c, 0x3dcd,
+ 0x4798, 0x4781,
+ 0x47a6, 0x40a3,
+ 0x47b6, 0x3eea,
+ 0x47d5, 0x431a,
+ 0x47ed, 0x4783,
+ 0x47f4, 0x432f,
+ 0x4800, 0x461e,
+ 0x480b, 0x4352,
+ 0x4837, 0x4787,
+ 0x485d, 0x410f,
+ 0x4871, 0x3d03,
+ 0x489b, 0x3bbd,
+ 0x48ad, 0x4791,
+ 0x48ae, 0x494d,
+ 0x48d0, 0x3da7,
+ 0x48dd, 0x4120,
+ 0x48ed, 0x4288,
+ 0x48f3, 0x3ec1,
+ 0x48fa, 0x3e44,
+ 0x4906, 0x3bc7,
+ 0x4911, 0x4584,
+ 0x491e, 0x4794,
+ 0x4925, 0x3c0f,
+ 0x492a, 0x46ae,
+ 0x492d, 0x46cd,
+ 0x4935, 0x3cc3,
+ 0x493c, 0x3bf8,
+ 0x493e, 0x3d06,
+ 0x4945, 0x47a3,
+ 0x4951, 0x47a4,
+ 0x4953, 0x42ad,
+ 0x4965, 0x3899,
+ 0x496a, 0x47a9,
+ 0x4972, 0x3a24,
+ 0x4989, 0x379b,
+ 0x49a1, 0x38b7,
+ 0x49a7, 0x47ae,
+ 0x49df, 0x38aa,
+ 0x49e5, 0x47b1,
+ 0x49e7, 0x4621,
+ 0x4a0f, 0x38c3,
+ 0x4a1d, 0x3bec,
+ 0x4a24, 0x47b2,
+ 0x4a35, 0x47b4,
+ 0x4a96, 0x3ce7,
+ 0x4ab4, 0x4361,
+ 0x4ab8, 0x3da8,
+ 0x4ad1, 0x38e3,
+ 0x4ae4, 0x47b7,
+ 0x4aff, 0x38f2,
+ 0x4b19, 0x47b9,
+ 0x4b2c, 0x461f,
+ 0x4b37, 0x41a9,
+ 0x4b6f, 0x3c16,
+ 0x4b70, 0x47c0,
+ 0x4b72, 0x38fc,
+ 0x4b7b, 0x3c8d,
+ 0x4b7e, 0x400a,
+ 0x4b8e, 0x39f7,
+ 0x4b90, 0x3c20,
+ 0x4b93, 0x3a8c,
+ 0x4b96, 0x3942,
+ 0x4b97, 0x3c24,
+ 0x4b9d, 0x47c2,
+ 0x4bbd, 0x3c23,
+ 0x4bbe, 0x3954,
+ 0x4bc0, 0x3ddc,
+ 0x4c04, 0x3fbb,
+ 0x4c07, 0x3fb7,
+ 0x4c0e, 0x390c,
+ 0x4c3b, 0x3f3c,
+ 0x4c3e, 0x457b,
+ 0x4c5b, 0x3ed9,
+ 0x4c6d, 0x47c9,
+ 0x4c7d, 0x3e66,
+ 0x4ca4, 0x48be,
+ 0x4cae, 0x3c42,
+ 0x4cb0, 0x3c45,
+ 0x4cb7, 0x3e21,
+ 0x4ccd, 0x4578,
+ 0x4ce1, 0x3ef3,
+ 0x4ced, 0x40ab,
+ 0x4d09, 0x3ed6,
+ 0x4d10, 0x4117,
+ 0x4d34, 0x3935,
+ 0x4d91, 0x43f5,
+ 0x4d9c, 0x48c4,
+ 0x4e00, 0x0253,
+ 0x4e01, 0x0255,
+ 0x4e03, 0x0256,
+ 0x4e04, 0x48fe,
+ 0x4e07, 0x1771,
+ 0x4e08, 0x0269,
+ 0x4e09, 0x0267,
+ 0x4e0a, 0x026a,
+ 0x4e0b, 0x0268,
+ 0x4e0c, 0x1772,
+ 0x4e0d, 0x0294,
+ 0x4e0e, 0x177a,
+ 0x4e0f, 0x1778,
+ 0x4e10, 0x0293,
+ 0x4e11, 0x0292,
+ 0x4e14, 0x02f2,
+ 0x4e15, 0x02f1,
+ 0x4e16, 0x02f0,
+ 0x4e18, 0x02f3,
+ 0x4e19, 0x02ef,
+ 0x4e1a, 0x48fd,
+ 0x4e1c, 0x48e0,
+ 0x4e1e, 0x036e,
+ 0x4e21, 0x3d6d,
+ 0x4e24, 0x458d,
+ 0x4e26, 0x0528,
+ 0x4e28, 0x0218,
+ 0x4e2a, 0x3f57,
+ 0x4e2b, 0x026b,
+ 0x4e2c, 0x44f3,
+ 0x4e2d, 0x0295,
+ 0x4e2e, 0x177b,
+ 0x4e30, 0x0296,
+ 0x4e31, 0x178e,
+ 0x4e32, 0x0415,
+ 0x4e33, 0x18f4,
+ 0x4e36, 0x0219,
+ 0x4e37, 0x4517,
+ 0x4e38, 0x026c,
+ 0x4e39, 0x0297,
+ 0x4e3b, 0x02f4,
+ 0x4e3c, 0x178f,
+ 0x4e3d, 0x4537,
+ 0x4e3f, 0x021a,
+ 0x4e41, 0x36af,
+ 0x4e42, 0x176c,
+ 0x4e43, 0x0257,
+ 0x4e45, 0x026e,
+ 0x4e47, 0x1773,
+ 0x4e48, 0x026f,
+ 0x4e49, 0x408e,
+ 0x4e4b, 0x0298,
+ 0x4e4d, 0x02f5,
+ 0x4e4e, 0x02f7,
+ 0x4e4f, 0x02f6,
+ 0x4e52, 0x0370,
+ 0x4e56, 0x0529,
+ 0x4e58, 0x0831,
+ 0x4e59, 0x0254,
+ 0x4e5a, 0x36b1,
+ 0x4e5b, 0x44e5,
+ 0x4e5c, 0x176d,
+ 0x4e5d, 0x0258,
+ 0x4e5e, 0x0271,
+ 0x4e5f, 0x0270,
+ 0x4e69, 0x0372,
+ 0x4e6a, 0x3de5,
+ 0x4e73, 0x052a,
+ 0x4e78, 0x3d8e,
+ 0x4e7e, 0x09fb,
+ 0x4e7f, 0x1e35,
+ 0x4e80, 0x458e,
+ 0x4e81, 0x43bc,
+ 0x4e82, 0x0dbe,
+ 0x4e83, 0x2361,
+ 0x4e85, 0x021b,
+ 0x4e86, 0x0259,
+ 0x4e87, 0x458f,
+ 0x4e88, 0x029a,
+ 0x4e89, 0x459c,
+ 0x4e8b, 0x052b,
+ 0x4e8c, 0x025a,
+ 0x4e8d, 0x1774,
+ 0x4e8e, 0x0272,
+ 0x4e91, 0x029b,
+ 0x4e92, 0x029d,
+ 0x4e93, 0x177c,
+ 0x4e94, 0x029e,
+ 0x4e95, 0x029c,
+ 0x4e98, 0x39c4,
+ 0x4e99, 0x0373,
+ 0x4e9a, 0x48d5,
+ 0x4e9b, 0x052c,
+ 0x4e9e, 0x052d,
+ 0x4e9f, 0x06a3,
+ 0x4ea0, 0x021c,
+ 0x4ea1, 0x0273,
+ 0x4ea2, 0x029f,
+ 0x4ea4, 0x0374,
+ 0x4ea5, 0x0376,
+ 0x4ea6, 0x0375,
+ 0x4ea8, 0x0416,
+ 0x4eab, 0x052e,
+ 0x4ead, 0x06a4,
+ 0x4eb3, 0x0832,
+ 0x4eb6, 0x2363,
+ 0x4eb7, 0x413c,
+ 0x4eb9, 0x3377,
+ 0x4eba, 0x025b,
+ 0x4ebb, 0x44e6,
+ 0x4ebc, 0x39b1,
+ 0x4ebf, 0x4590,
+ 0x4ec0, 0x02a1,
+ 0x4ec1, 0x02a0,
+ 0x4ec2, 0x177d,
+ 0x4ec3, 0x02a2,
+ 0x4ec4, 0x02a8,
+ 0x4ec6, 0x02a3,
+ 0x4ec8, 0x177f,
+ 0x4ec9, 0x177e,
+ 0x4eca, 0x02a6,
+ 0x4ecd, 0x02a5,
+ 0x4ece, 0x3f62,
+ 0x4ed4, 0x02fa,
+ 0x4ed8, 0x02f9,
+ 0x4ed9, 0x0300,
+ 0x4eda, 0x1795,
+ 0x4edc, 0x1791,
+ 0x4edd, 0x1794,
+ 0x4ede, 0x0301,
+ 0x4edf, 0x0311,
+ 0x4ee1, 0x1793,
+ 0x4ee3, 0x02fe,
+ 0x4ee5, 0x02f8,
+ 0x4ee8, 0x1790,
+ 0x4ee9, 0x1792,
+ 0x4eea, 0x48cb,
+ 0x4eeb, 0x4591,
+ 0x4eee, 0x3d76,
+ 0x4ef0, 0x0383,
+ 0x4ef1, 0x17ba,
+ 0x4ef2, 0x0380,
+ 0x4ef3, 0x0384,
+ 0x4ef4, 0x17c4,
+ 0x4ef5, 0x17b8,
+ 0x4ef6, 0x0381,
+ 0x4ef7, 0x17bc,
+ 0x4ef8, 0x39ad,
+ 0x4efb, 0x0382,
+ 0x4efd, 0x0385,
+ 0x4eff, 0x0377,
+ 0x4f00, 0x17bb,
+ 0x4f01, 0x0386,
+ 0x4f02, 0x17bf,
+ 0x4f03, 0x39c8,
+ 0x4f04, 0x17c3,
+ 0x4f05, 0x17c0,
+ 0x4f08, 0x17bd,
+ 0x4f09, 0x0378,
+ 0x4f0a, 0x037a,
+ 0x4f0b, 0x0387,
+ 0x4f0d, 0x037c,
+ 0x4f0e, 0x17b5,
+ 0x4f0f, 0x037f,
+ 0x4f10, 0x037d,
+ 0x4f12, 0x17c5,
+ 0x4f13, 0x17c2,
+ 0x4f14, 0x17b9,
+ 0x4f15, 0x037b,
+ 0x4f18, 0x17b6,
+ 0x4f19, 0x0379,
+ 0x4f1a, 0x453c,
+ 0x4f1d, 0x17be,
+ 0x4f22, 0x17c1,
+ 0x4f28, 0x453d,
+ 0x4f29, 0x39be,
+ 0x4f2c, 0x17b7,
+ 0x4f2d, 0x182f,
+ 0x4f2f, 0x042c,
+ 0x4f30, 0x041f,
+ 0x4f32, 0x393d,
+ 0x4f33, 0x1830,
+ 0x4f34, 0x041c,
+ 0x4f36, 0x042e,
+ 0x4f37, 0x4592,
+ 0x4f38, 0x0424,
+ 0x4f39, 0x3f65,
+ 0x4f3a, 0x0423,
+ 0x4f3b, 0x1824,
+ 0x4f3c, 0x0427,
+ 0x4f3d, 0x0422,
+ 0x4f3e, 0x1829,
+ 0x4f3f, 0x1831,
+ 0x4f41, 0x182d,
+ 0x4f42, 0x39cb,
+ 0x4f43, 0x0425,
+ 0x4f45, 0x3b8f,
+ 0x4f46, 0x0428,
+ 0x4f47, 0x0419,
+ 0x4f48, 0x0431,
+ 0x4f49, 0x1826,
+ 0x4f4b, 0x39b4,
+ 0x4f4c, 0x1900,
+ 0x4f4d, 0x0417,
+ 0x4f4e, 0x042d,
+ 0x4f4f, 0x0418,
+ 0x4f50, 0x0420,
+ 0x4f52, 0x182b,
+ 0x4f53, 0x1827,
+ 0x4f54, 0x0426,
+ 0x4f55, 0x041e,
+ 0x4f56, 0x1823,
+ 0x4f57, 0x041a,
+ 0x4f58, 0x182e,
+ 0x4f59, 0x042f,
+ 0x4f5a, 0x0432,
+ 0x4f5b, 0x041d,
+ 0x4f5c, 0x042a,
+ 0x4f5d, 0x0430,
+ 0x4f5e, 0x041b,
+ 0x4f5f, 0x182c,
+ 0x4f60, 0x042b,
+ 0x4f61, 0x1832,
+ 0x4f62, 0x1825,
+ 0x4f63, 0x0429,
+ 0x4f64, 0x1828,
+ 0x4f67, 0x182a,
+ 0x4f69, 0x053d,
+ 0x4f6a, 0x1902,
+ 0x4f6b, 0x190e,
+ 0x4f6c, 0x0535,
+ 0x4f6e, 0x190f,
+ 0x4f6f, 0x0530,
+ 0x4f70, 0x053a,
+ 0x4f72, 0x3c72,
+ 0x4f73, 0x0533,
+ 0x4f74, 0x18fc,
+ 0x4f75, 0x053b,
+ 0x4f76, 0x18fb,
+ 0x4f77, 0x18ff,
+ 0x4f78, 0x1906,
+ 0x4f79, 0x1904,
+ 0x4f7a, 0x0543,
+ 0x4f7b, 0x053e,
+ 0x4f7c, 0x18f6,
+ 0x4f7d, 0x18f8,
+ 0x4f7e, 0x0540,
+ 0x4f7f, 0x0534,
+ 0x4f80, 0x18f9,
+ 0x4f81, 0x1905,
+ 0x4f82, 0x190c,
+ 0x4f83, 0x0539,
+ 0x4f84, 0x18fe,
+ 0x4f85, 0x18f7,
+ 0x4f86, 0x0538,
+ 0x4f87, 0x18fa,
+ 0x4f88, 0x053c,
+ 0x4f89, 0x18fd,
+ 0x4f8a, 0x39b5,
+ 0x4f8b, 0x0537,
+ 0x4f8d, 0x0532,
+ 0x4f8f, 0x0541,
+ 0x4f90, 0x1907,
+ 0x4f91, 0x0542,
+ 0x4f92, 0x190b,
+ 0x4f94, 0x1909,
+ 0x4f95, 0x190d,
+ 0x4f96, 0x053f,
+ 0x4f97, 0x1901,
+ 0x4f98, 0x18f5,
+ 0x4f9a, 0x1903,
+ 0x4f9b, 0x0536,
+ 0x4f9c, 0x1908,
+ 0x4f9d, 0x0531,
+ 0x4f9e, 0x190a,
+ 0x4fa2, 0x39c7,
+ 0x4fa8, 0x453e,
+ 0x4fab, 0x4022,
+ 0x4fae, 0x06b4,
+ 0x4faf, 0x06a8,
+ 0x4fb0, 0x3d4a,
+ 0x4fb2, 0x1a5d,
+ 0x4fb3, 0x1a65,
+ 0x4fb5, 0x06a7,
+ 0x4fb6, 0x06af,
+ 0x4fb7, 0x06bb,
+ 0x4fb9, 0x1a6b,
+ 0x4fba, 0x1a69,
+ 0x4fbb, 0x1a64,
+ 0x4fbd, 0x4594,
+ 0x4fbf, 0x06a9,
+ 0x4fc0, 0x1a6a,
+ 0x4fc1, 0x1a60,
+ 0x4fc2, 0x06b7,
+ 0x4fc3, 0x06ae,
+ 0x4fc4, 0x06b6,
+ 0x4fc5, 0x1a5b,
+ 0x4fc7, 0x1a67,
+ 0x4fc8, 0x46e8,
+ 0x4fc9, 0x1a5e,
+ 0x4fca, 0x06b2,
+ 0x4fcb, 0x1a5f,
+ 0x4fcc, 0x39cf,
+ 0x4fcd, 0x1a5a,
+ 0x4fce, 0x06b9,
+ 0x4fcf, 0x06ac,
+ 0x4fd0, 0x06b5,
+ 0x4fd1, 0x06ab,
+ 0x4fd3, 0x1a5c,
+ 0x4fd4, 0x1a61,
+ 0x4fd6, 0x1a68,
+ 0x4fd7, 0x06b3,
+ 0x4fd8, 0x06b0,
+ 0x4fd9, 0x1a63,
+ 0x4fda, 0x06b8,
+ 0x4fdb, 0x1a66,
+ 0x4fdc, 0x1a62,
+ 0x4fdd, 0x06ad,
+ 0x4fde, 0x06ba,
+ 0x4fdf, 0x06b1,
+ 0x4fe0, 0x06aa,
+ 0x4fe1, 0x06a6,
+ 0x4fe4, 0x3c66,
+ 0x4fe5, 0x39d0,
+ 0x4fec, 0x1a6c,
+ 0x4fee, 0x084c,
+ 0x4fef, 0x0836,
+ 0x4ff1, 0x0846,
+ 0x4ff2, 0x3f28,
+ 0x4ff3, 0x084b,
+ 0x4ff4, 0x1c24,
+ 0x4ff5, 0x1c23,
+ 0x4ff6, 0x1c28,
+ 0x4ff8, 0x0839,
+ 0x4ff9, 0x37b3,
+ 0x4ffa, 0x0842,
+ 0x4ffd, 0x3f26,
+ 0x4ffe, 0x084f,
+ 0x5000, 0x0843,
+ 0x5003, 0x4596,
+ 0x5005, 0x1c1d,
+ 0x5006, 0x083c,
+ 0x5007, 0x1c1e,
+ 0x5008, 0x4024,
+ 0x5009, 0x0851,
+ 0x500b, 0x0848,
+ 0x500c, 0x0833,
+ 0x500e, 0x1c31,
+ 0x500f, 0x0a0c,
+ 0x5011, 0x0841,
+ 0x5012, 0x0840,
+ 0x5013, 0x1c1f,
+ 0x5014, 0x0844,
+ 0x5015, 0x1e45,
+ 0x5016, 0x083b,
+ 0x5017, 0x1c2a,
+ 0x5018, 0x084a,
+ 0x5019, 0x0849,
+ 0x501a, 0x083f,
+ 0x501b, 0x1c22,
+ 0x501c, 0x1c2b,
+ 0x501e, 0x1c1c,
+ 0x501f, 0x083e,
+ 0x5020, 0x1c2c,
+ 0x5021, 0x0847,
+ 0x5022, 0x1c20,
+ 0x5023, 0x0835,
+ 0x5025, 0x0838,
+ 0x5026, 0x0837,
+ 0x5027, 0x1c2d,
+ 0x5028, 0x0845,
+ 0x5029, 0x083a,
+ 0x502a, 0x084e,
+ 0x502b, 0x0850,
+ 0x502c, 0x1c27,
+ 0x502d, 0x084d,
+ 0x502e, 0x39cc,
+ 0x502f, 0x1c2f,
+ 0x5030, 0x1c21,
+ 0x5031, 0x1c30,
+ 0x5033, 0x1c25,
+ 0x5034, 0x3910,
+ 0x5035, 0x1c2e,
+ 0x5037, 0x1c26,
+ 0x503c, 0x083d,
+ 0x5040, 0x1e4d,
+ 0x5041, 0x1e41,
+ 0x5043, 0x0a00,
+ 0x5045, 0x1e46,
+ 0x5046, 0x1e4c,
+ 0x5047, 0x09ff,
+ 0x5048, 0x1e3f,
+ 0x5049, 0x0a03,
+ 0x504a, 0x1e43,
+ 0x504b, 0x1e3c,
+ 0x504c, 0x0a01,
+ 0x504d, 0x1e40,
+ 0x504e, 0x0a06,
+ 0x504f, 0x0a0b,
+ 0x5051, 0x1e51,
+ 0x5053, 0x1e3b,
+ 0x5055, 0x0a07,
+ 0x5056, 0x3f2c,
+ 0x5057, 0x1e50,
+ 0x5058, 0x39d1,
+ 0x505a, 0x0a02,
+ 0x505b, 0x1e42,
+ 0x505c, 0x09fe,
+ 0x505d, 0x1e3d,
+ 0x505e, 0x1e39,
+ 0x505f, 0x1e47,
+ 0x5060, 0x1e3a,
+ 0x5061, 0x1e38,
+ 0x5062, 0x1e44,
+ 0x5063, 0x1e4a,
+ 0x5065, 0x0a04,
+ 0x5066, 0x3dc9,
+ 0x5068, 0x20b8,
+ 0x5069, 0x1e48,
+ 0x506a, 0x1e37,
+ 0x506b, 0x1e49,
+ 0x506c, 0x39cd,
+ 0x506d, 0x0a0e,
+ 0x506e, 0x1e4e,
+ 0x506f, 0x0a0d,
+ 0x5070, 0x1e36,
+ 0x5072, 0x1e3e,
+ 0x5073, 0x1e4f,
+ 0x5074, 0x0a09,
+ 0x5075, 0x0a08,
+ 0x5076, 0x0a05,
+ 0x5077, 0x0a0a,
+ 0x507a, 0x09fc,
+ 0x507d, 0x09fd,
+ 0x5080, 0x0bec,
+ 0x5081, 0x39ce,
+ 0x5082, 0x20bb,
+ 0x5083, 0x20b4,
+ 0x5085, 0x0be9,
+ 0x5087, 0x20bc,
+ 0x5088, 0x439c,
+ 0x508b, 0x20b2,
+ 0x508c, 0x20b5,
+ 0x508d, 0x0be8,
+ 0x508e, 0x20b6,
+ 0x5090, 0x41ec,
+ 0x5091, 0x0beb,
+ 0x5092, 0x20ba,
+ 0x5094, 0x20b0,
+ 0x5095, 0x20af,
+ 0x5096, 0x0bed,
+ 0x5098, 0x0bee,
+ 0x5099, 0x0bea,
+ 0x509a, 0x0bef,
+ 0x509b, 0x20ae,
+ 0x509c, 0x20b9,
+ 0x509d, 0x20b7,
+ 0x509e, 0x20b1,
+ 0x50a2, 0x0be7,
+ 0x50a3, 0x20b3,
+ 0x50a6, 0x3f3f,
+ 0x50ac, 0x0dc5,
+ 0x50ad, 0x0dbf,
+ 0x50ae, 0x2367,
+ 0x50af, 0x0dc8,
+ 0x50b0, 0x236d,
+ 0x50b1, 0x2370,
+ 0x50b2, 0x0dc1,
+ 0x50b4, 0x236a,
+ 0x50b5, 0x0dc0,
+ 0x50b6, 0x2373,
+ 0x50b7, 0x0dc6,
+ 0x50b8, 0x2374,
+ 0x50ba, 0x236f,
+ 0x50bb, 0x0dc7,
+ 0x50bd, 0x2364,
+ 0x50be, 0x0dc4,
+ 0x50bf, 0x2365,
+ 0x50c1, 0x236e,
+ 0x50c2, 0x236c,
+ 0x50c4, 0x2368,
+ 0x50c5, 0x0dc3,
+ 0x50c6, 0x2366,
+ 0x50c7, 0x0dc9,
+ 0x50c8, 0x236b,
+ 0x50c9, 0x2372,
+ 0x50ca, 0x2369,
+ 0x50cb, 0x2371,
+ 0x50cd, 0x39c5,
+ 0x50ce, 0x0f88,
+ 0x50cf, 0x0f85,
+ 0x50d0, 0x38d1,
+ 0x50d1, 0x0f86,
+ 0x50d3, 0x261c,
+ 0x50d4, 0x2614,
+ 0x50d5, 0x0f84,
+ 0x50d6, 0x0f81,
+ 0x50d7, 0x2615,
+ 0x50d9, 0x3fce,
+ 0x50da, 0x0f83,
+ 0x50db, 0x2618,
+ 0x50dd, 0x261a,
+ 0x50de, 0x4031,
+ 0x50df, 0x3afd,
+ 0x50e0, 0x2621,
+ 0x50e1, 0x4171,
+ 0x50e3, 0x2620,
+ 0x50e4, 0x261b,
+ 0x50e5, 0x0f80,
+ 0x50e6, 0x2613,
+ 0x50e7, 0x0f7e,
+ 0x50e8, 0x2616,
+ 0x50e9, 0x0f89,
+ 0x50ea, 0x2619,
+ 0x50ec, 0x261d,
+ 0x50ed, 0x0f82,
+ 0x50ee, 0x0f7f,
+ 0x50ef, 0x261f,
+ 0x50f0, 0x261e,
+ 0x50f1, 0x0f87,
+ 0x50f3, 0x2617,
+ 0x50f4, 0x3ce9,
+ 0x50f5, 0x1105,
+ 0x50f6, 0x2883,
+ 0x50f8, 0x2880,
+ 0x50f9, 0x1106,
+ 0x50fb, 0x1104,
+ 0x50fc, 0x39d2,
+ 0x50fd, 0x2887,
+ 0x50fe, 0x2884,
+ 0x50ff, 0x287d,
+ 0x5100, 0x1103,
+ 0x5101, 0x4032,
+ 0x5102, 0x1107,
+ 0x5103, 0x287e,
+ 0x5104, 0x1102,
+ 0x5105, 0x110a,
+ 0x5106, 0x2881,
+ 0x5108, 0x1108,
+ 0x510a, 0x2888,
+ 0x510b, 0x2885,
+ 0x510d, 0x39c6,
+ 0x510e, 0x4034,
+ 0x5110, 0x128d,
+ 0x5111, 0x2b04,
+ 0x5112, 0x128a,
+ 0x5113, 0x2b01,
+ 0x5114, 0x128c,
+ 0x5115, 0x128e,
+ 0x5117, 0x2b02,
+ 0x5118, 0x128b,
+ 0x511a, 0x2b03,
+ 0x511c, 0x2b00,
+ 0x511f, 0x13b5,
+ 0x5120, 0x2d3e,
+ 0x5121, 0x13b6,
+ 0x5122, 0x2d3c,
+ 0x5124, 0x2d3d,
+ 0x5125, 0x2d3b,
+ 0x5126, 0x2d3a,
+ 0x5129, 0x2d3f,
+ 0x512a, 0x13b4,
+ 0x512b, 0x39ae,
+ 0x512d, 0x2f0f,
+ 0x5130, 0x287f,
+ 0x5131, 0x2f0e,
+ 0x5132, 0x13b7,
+ 0x5133, 0x1575,
+ 0x5134, 0x307a,
+ 0x5137, 0x1668,
+ 0x5139, 0x32c6,
+ 0x513a, 0x32c5,
+ 0x513b, 0x16bc,
+ 0x513c, 0x16bb,
+ 0x513d, 0x340e,
+ 0x513f, 0x025c,
+ 0x5140, 0x0274,
+ 0x5141, 0x02aa,
+ 0x5143, 0x02a9,
+ 0x5144, 0x0303,
+ 0x5145, 0x0302,
+ 0x5146, 0x038a,
+ 0x5147, 0x0389,
+ 0x5148, 0x038b,
+ 0x5149, 0x0388,
+ 0x514b, 0x0434,
+ 0x514c, 0x0433,
+ 0x514d, 0x0435,
+ 0x5152, 0x0545,
+ 0x5154, 0x0544,
+ 0x5155, 0x0546,
+ 0x5156, 0x439a,
+ 0x5157, 0x06bc,
+ 0x5159, 0x0119,
+ 0x515a, 0x1c32,
+ 0x515b, 0x011a,
+ 0x515c, 0x0a0f,
+ 0x515d, 0x011c,
+ 0x515e, 0x011b,
+ 0x515f, 0x20bd,
+ 0x5160, 0x403a,
+ 0x5161, 0x011d,
+ 0x5162, 0x0f8a,
+ 0x5163, 0x011e,
+ 0x5165, 0x025d,
+ 0x5167, 0x02ab,
+ 0x5168, 0x038c,
+ 0x5169, 0x0547,
+ 0x516a, 0x403c,
+ 0x516b, 0x025e,
+ 0x516c, 0x02ae,
+ 0x516d, 0x02ac,
+ 0x5171, 0x038d,
+ 0x5174, 0x453f,
+ 0x5175, 0x0436,
+ 0x5176, 0x0549,
+ 0x5177, 0x0548,
+ 0x5178, 0x054a,
+ 0x5179, 0x3ace,
+ 0x517c, 0x0852,
+ 0x5180, 0x128f,
+ 0x5182, 0x021d,
+ 0x5186, 0x439f,
+ 0x5187, 0x1779,
+ 0x5188, 0x36b6,
+ 0x5189, 0x0304,
+ 0x518d, 0x038e,
+ 0x518f, 0x1833,
+ 0x5191, 0x06be,
+ 0x5192, 0x06bd,
+ 0x5193, 0x1c34,
+ 0x5194, 0x1c33,
+ 0x5195, 0x0a10,
+ 0x5196, 0x021e,
+ 0x5197, 0x02af,
+ 0x5198, 0x1780,
+ 0x519a, 0x3ea3,
+ 0x519c, 0x4540,
+ 0x519e, 0x1910,
+ 0x51a0, 0x06bf,
+ 0x51a2, 0x0855,
+ 0x51a4, 0x0853,
+ 0x51a7, 0x3ea6,
+ 0x51a8, 0x39da,
+ 0x51aa, 0x1290,
+ 0x51ab, 0x021f,
+ 0x51ac, 0x0306,
+ 0x51b0, 0x038f,
+ 0x51b1, 0x17c6,
+ 0x51b2, 0x4048,
+ 0x51b3, 0x4051,
+ 0x51b4, 0x3d7c,
+ 0x51b5, 0x4012,
+ 0x51b6, 0x0437,
+ 0x51b8, 0x4049,
+ 0x51b9, 0x1834,
+ 0x51bc, 0x1911,
+ 0x51bd, 0x054b,
+ 0x51be, 0x1912,
+ 0x51c3, 0x39db,
+ 0x51c4, 0x1c36,
+ 0x51c6, 0x0858,
+ 0x51c7, 0x422a,
+ 0x51c8, 0x1c38,
+ 0x51c9, 0x404b,
+ 0x51ca, 0x1c35,
+ 0x51cb, 0x0859,
+ 0x51cc, 0x0857,
+ 0x51cd, 0x0856,
+ 0x51ce, 0x1c39,
+ 0x51cf, 0x404c,
+ 0x51d0, 0x1e52,
+ 0x51d1, 0x404d,
+ 0x51d2, 0x3dad,
+ 0x51d3, 0x404f,
+ 0x51d4, 0x20be,
+ 0x51d7, 0x2375,
+ 0x51d8, 0x2622,
+ 0x51db, 0x459a,
+ 0x51dc, 0x110b,
+ 0x51dd, 0x1291,
+ 0x51de, 0x2b05,
+ 0x51df, 0x424f,
+ 0x51e0, 0x025f,
+ 0x51e1, 0x026d,
+ 0x51e2, 0x4052,
+ 0x51e4, 0x4541,
+ 0x51ed, 0x4054,
+ 0x51f0, 0x0a11,
+ 0x51f1, 0x0bf1,
+ 0x51f3, 0x0f8b,
+ 0x51f4, 0x4178,
+ 0x51f5, 0x176e,
+ 0x51f6, 0x02b0,
+ 0x51f8, 0x0309,
+ 0x51f9, 0x0307,
+ 0x51fc, 0x459b,
+ 0x51fd, 0x054c,
+ 0x51fe, 0x3f0a,
+ 0x5200, 0x0260,
+ 0x5202, 0x36b3,
+ 0x5203, 0x0275,
+ 0x5205, 0x43a1,
+ 0x5206, 0x02b1,
+ 0x5209, 0x1797,
+ 0x520a, 0x030a,
+ 0x520b, 0x4059,
+ 0x520c, 0x1796,
+ 0x520e, 0x0393,
+ 0x5210, 0x17c8,
+ 0x5211, 0x0391,
+ 0x5213, 0x17c7,
+ 0x5216, 0x0394,
+ 0x5217, 0x0390,
+ 0x521c, 0x1835,
+ 0x521d, 0x068b,
+ 0x521e, 0x1836,
+ 0x521f, 0x3f60,
+ 0x5220, 0x4930,
+ 0x5221, 0x1837,
+ 0x5224, 0x043a,
+ 0x5225, 0x0439,
+ 0x5226, 0x405a,
+ 0x5227, 0x43a2,
+ 0x5228, 0x043d,
+ 0x5229, 0x043b,
+ 0x522e, 0x0552,
+ 0x5230, 0x0551,
+ 0x5231, 0x1917,
+ 0x5232, 0x1914,
+ 0x5234, 0x3efb,
+ 0x5235, 0x1913,
+ 0x5236, 0x0553,
+ 0x5237, 0x054f,
+ 0x5238, 0x054e,
+ 0x523a, 0x0550,
+ 0x523b, 0x054d,
+ 0x523c, 0x405b,
+ 0x5241, 0x0554,
+ 0x5243, 0x06c1,
+ 0x5244, 0x1a6d,
+ 0x5246, 0x1916,
+ 0x5247, 0x06c6,
+ 0x5249, 0x1a6e,
+ 0x524a, 0x06c2,
+ 0x524b, 0x06c5,
+ 0x524c, 0x06c4,
+ 0x524d, 0x06c3,
+ 0x524e, 0x06c0,
+ 0x5252, 0x1c3c,
+ 0x5254, 0x085c,
+ 0x5255, 0x1c3f,
+ 0x5256, 0x085a,
+ 0x5257, 0x405d,
+ 0x5259, 0x39e4,
+ 0x525a, 0x1c3b,
+ 0x525b, 0x085d,
+ 0x525c, 0x085b,
+ 0x525d, 0x085e,
+ 0x525e, 0x1c3d,
+ 0x5260, 0x3f29,
+ 0x5261, 0x1c3a,
+ 0x5262, 0x1c40,
+ 0x5268, 0x4619,
+ 0x5269, 0x0bf5,
+ 0x526a, 0x0a12,
+ 0x526b, 0x1e53,
+ 0x526c, 0x1e55,
+ 0x526d, 0x1e54,
+ 0x526e, 0x1e56,
+ 0x526f, 0x0a13,
+ 0x5272, 0x0bf2,
+ 0x5273, 0x3f43,
+ 0x5274, 0x0bf3,
+ 0x5277, 0x0dcb,
+ 0x5278, 0x2377,
+ 0x5279, 0x43a3,
+ 0x527a, 0x2376,
+ 0x527b, 0x2378,
+ 0x527d, 0x0dcc,
+ 0x527f, 0x0dca,
+ 0x5280, 0x2623,
+ 0x5282, 0x0f8d,
+ 0x5283, 0x0f8c,
+ 0x5284, 0x2776,
+ 0x5287, 0x110c,
+ 0x528a, 0x1110,
+ 0x528b, 0x2889,
+ 0x528d, 0x110f,
+ 0x528f, 0x3dbf,
+ 0x5290, 0x459d,
+ 0x5291, 0x1292,
+ 0x5293, 0x1293,
+ 0x5294, 0x405e,
+ 0x5296, 0x307c,
+ 0x5297, 0x32c8,
+ 0x5298, 0x32c7,
+ 0x5299, 0x340f,
+ 0x529a, 0x3f68,
+ 0x529b, 0x0262,
+ 0x529f, 0x030c,
+ 0x52a0, 0x030b,
+ 0x52a1, 0x4542,
+ 0x52a3, 0x0395,
+ 0x52a4, 0x39e5,
+ 0x52a6, 0x17c9,
+ 0x52a8, 0x4543,
+ 0x52a9, 0x043f,
+ 0x52ab, 0x043e,
+ 0x52ac, 0x0441,
+ 0x52ad, 0x1838,
+ 0x52b5, 0x405c,
+ 0x52b9, 0x405f,
+ 0x52bb, 0x0556,
+ 0x52bc, 0x1918,
+ 0x52be, 0x0555,
+ 0x52c0, 0x1a6f,
+ 0x52c1, 0x06ca,
+ 0x52c2, 0x1a70,
+ 0x52c3, 0x06c9,
+ 0x52c5, 0x4060,
+ 0x52c7, 0x06c7,
+ 0x52c9, 0x06c8,
+ 0x52cc, 0x3ee1,
+ 0x52cd, 0x1c41,
+ 0x52d0, 0x4109,
+ 0x52d1, 0x3f2a,
+ 0x52d2, 0x0a14,
+ 0x52d3, 0x1e58,
+ 0x52d5, 0x0a17,
+ 0x52d6, 0x1e57,
+ 0x52d7, 0x0acf,
+ 0x52d8, 0x0a16,
+ 0x52d9, 0x0a15,
+ 0x52db, 0x0bf8,
+ 0x52dd, 0x0bf7,
+ 0x52de, 0x0bf6,
+ 0x52df, 0x0dcd,
+ 0x52e0, 0x4063,
+ 0x52e1, 0x39e7,
+ 0x52e2, 0x0dd0,
+ 0x52e4, 0x0dcf,
+ 0x52e6, 0x0dce,
+ 0x52e9, 0x2625,
+ 0x52eb, 0x2626,
+ 0x52ef, 0x288c,
+ 0x52f0, 0x1111,
+ 0x52f1, 0x288b,
+ 0x52f3, 0x1294,
+ 0x52f4, 0x2d40,
+ 0x52f5, 0x13b8,
+ 0x52f7, 0x307d,
+ 0x52f8, 0x1609,
+ 0x52f9, 0x0220,
+ 0x52fa, 0x0276,
+ 0x52fb, 0x02b4,
+ 0x52fc, 0x1781,
+ 0x52fe, 0x02b5,
+ 0x5301, 0x3d79,
+ 0x5305, 0x030d,
+ 0x5308, 0x0396,
+ 0x5309, 0x183a,
+ 0x530a, 0x1919,
+ 0x530d, 0x06cb,
+ 0x530e, 0x1c42,
+ 0x530f, 0x0a19,
+ 0x5310, 0x0a18,
+ 0x5311, 0x20c0,
+ 0x5312, 0x20bf,
+ 0x5315, 0x0263,
+ 0x5316, 0x02b7,
+ 0x5317, 0x030f,
+ 0x5319, 0x0a1a,
+ 0x531a, 0x176f,
+ 0x531c, 0x1798,
+ 0x531d, 0x0310,
+ 0x531f, 0x17cb,
+ 0x5320, 0x0398,
+ 0x5321, 0x0397,
+ 0x5322, 0x17ca,
+ 0x5323, 0x0442,
+ 0x5327, 0x459e,
+ 0x532a, 0x085f,
+ 0x532c, 0x3f36,
+ 0x532d, 0x1e59,
+ 0x532f, 0x0dd2,
+ 0x5330, 0x2627,
+ 0x5331, 0x0f8e,
+ 0x5332, 0x3fd0,
+ 0x5333, 0x406d,
+ 0x5334, 0x2b06,
+ 0x5337, 0x31c7,
+ 0x5338, 0x0221,
+ 0x5339, 0x02b8,
+ 0x533b, 0x4544,
+ 0x533c, 0x191b,
+ 0x533d, 0x1a71,
+ 0x533e, 0x0a1d,
+ 0x533f, 0x0a1b,
+ 0x5341, 0x0264,
+ 0x5342, 0x4947,
+ 0x5343, 0x0277,
+ 0x5344, 0x016b,
+ 0x5345, 0x02bb,
+ 0x5347, 0x02ba,
+ 0x5348, 0x02b9,
+ 0x5349, 0x0313,
+ 0x534a, 0x0312,
+ 0x534c, 0x1799,
+ 0x534d, 0x17cc,
+ 0x534e, 0x4545,
+ 0x5351, 0x055a,
+ 0x5352, 0x0557,
+ 0x5353, 0x0559,
+ 0x5354, 0x0558,
+ 0x5357, 0x06cc,
+ 0x535a, 0x0bf9,
+ 0x535c, 0x0265,
+ 0x535d, 0x4501,
+ 0x535e, 0x02bc,
+ 0x535f, 0x43a7,
+ 0x5360, 0x0315,
+ 0x5361, 0x0314,
+ 0x5363, 0x183b,
+ 0x5364, 0x480a,
+ 0x5366, 0x055b,
+ 0x5367, 0x3ecd,
+ 0x5369, 0x0222,
+ 0x536c, 0x1782,
+ 0x536d, 0x407a,
+ 0x536e, 0x0317,
+ 0x536f, 0x0316,
+ 0x5370, 0x0399,
+ 0x5372, 0x183c,
+ 0x5373, 0x0443,
+ 0x5374, 0x407b,
+ 0x5375, 0x0444,
+ 0x5377, 0x055c,
+ 0x537b, 0x06cd,
+ 0x537c, 0x1a72,
+ 0x537d, 0x4901,
+ 0x537e, 0x407d,
+ 0x537f, 0x0860,
+ 0x5382, 0x1770,
+ 0x5384, 0x02bd,
+ 0x538a, 0x17cd,
+ 0x538e, 0x183d,
+ 0x5392, 0x191c,
+ 0x5393, 0x4082,
+ 0x5394, 0x191d,
+ 0x5396, 0x1a74,
+ 0x5397, 0x1a73,
+ 0x5398, 0x1a76,
+ 0x5399, 0x1a75,
+ 0x539a, 0x06ce,
+ 0x539c, 0x1e5a,
+ 0x539d, 0x0862,
+ 0x539e, 0x1c43,
+ 0x539f, 0x0861,
+ 0x53a0, 0x4084,
+ 0x53a2, 0x3e2b,
+ 0x53a4, 0x20c1,
+ 0x53a5, 0x0bfa,
+ 0x53a6, 0x413b,
+ 0x53a7, 0x20c2,
+ 0x53a8, 0x413e,
+ 0x53a9, 0x45a0,
+ 0x53aa, 0x3fc6,
+ 0x53ab, 0x4085,
+ 0x53ac, 0x2628,
+ 0x53ad, 0x0f8f,
+ 0x53ae, 0x4086,
+ 0x53b0, 0x45a2,
+ 0x53b2, 0x1112,
+ 0x53b4, 0x307e,
+ 0x53b6, 0x0223,
+ 0x53b9, 0x1783,
+ 0x53bb, 0x0318,
+ 0x53c1, 0x408b,
+ 0x53c2, 0x43a6,
+ 0x53c3, 0x0a1e,
+ 0x53c5, 0x408c,
+ 0x53c8, 0x0266,
+ 0x53c9, 0x0278,
+ 0x53ca, 0x02bf,
+ 0x53cb, 0x02be,
+ 0x53cc, 0x38b6,
+ 0x53cd, 0x02c0,
+ 0x53d0, 0x39fa,
+ 0x53d1, 0x4546,
+ 0x53d2, 0x3e3d,
+ 0x53d4, 0x0560,
+ 0x53d6, 0x055f,
+ 0x53d7, 0x0561,
+ 0x53d8, 0x4547,
+ 0x53d9, 0x4090,
+ 0x53da, 0x3f39,
+ 0x53db, 0x06cf,
+ 0x53df, 0x0863,
+ 0x53e0, 0x4093,
+ 0x53e1, 0x2b07,
+ 0x53e2, 0x14c9,
+ 0x53e3, 0x0279,
+ 0x53e4, 0x031a,
+ 0x53e5, 0x0329,
+ 0x53e6, 0x0324,
+ 0x53e8, 0x031f,
+ 0x53e9, 0x031e,
+ 0x53ea, 0x0325,
+ 0x53eb, 0x0323,
+ 0x53ec, 0x031c,
+ 0x53ed, 0x032a,
+ 0x53ee, 0x031d,
+ 0x53ef, 0x0319,
+ 0x53f0, 0x0328,
+ 0x53f1, 0x0327,
+ 0x53f2, 0x0326,
+ 0x53f3, 0x031b,
+ 0x53f5, 0x0322,
+ 0x53f6, 0x4096,
+ 0x53f7, 0x3808,
+ 0x53f8, 0x0321,
+ 0x53fb, 0x032b,
+ 0x53fc, 0x0320,
+ 0x53fe, 0x40c1,
+ 0x5401, 0x03a0,
+ 0x5403, 0x03a6,
+ 0x5404, 0x03a2,
+ 0x5406, 0x03a8,
+ 0x5407, 0x17ce,
+ 0x5408, 0x03a5,
+ 0x5409, 0x039b,
+ 0x540a, 0x039e,
+ 0x540b, 0x03a1,
+ 0x540c, 0x039d,
+ 0x540d, 0x03a4,
+ 0x540e, 0x03a7,
+ 0x540f, 0x039c,
+ 0x5410, 0x039f,
+ 0x5411, 0x03a3,
+ 0x5412, 0x03a9,
+ 0x5413, 0x4098,
+ 0x5414, 0x3c77,
+ 0x5416, 0x3e7f,
+ 0x5418, 0x1847,
+ 0x5419, 0x1844,
+ 0x541a, 0x3e64,
+ 0x541b, 0x0451,
+ 0x541c, 0x1845,
+ 0x541d, 0x0445,
+ 0x541e, 0x0447,
+ 0x541f, 0x045f,
+ 0x5420, 0x045a,
+ 0x5421, 0x4203,
+ 0x5423, 0x45a3,
+ 0x5424, 0x184c,
+ 0x5425, 0x1846,
+ 0x5426, 0x0449,
+ 0x5427, 0x044b,
+ 0x5428, 0x184b,
+ 0x5429, 0x0452,
+ 0x542a, 0x1841,
+ 0x542b, 0x045e,
+ 0x542c, 0x0460,
+ 0x542d, 0x0446,
+ 0x542e, 0x0457,
+ 0x542f, 0x40ac,
+ 0x5430, 0x183f,
+ 0x5431, 0x045d,
+ 0x5432, 0x3e75,
+ 0x5433, 0x044e,
+ 0x5435, 0x0458,
+ 0x5437, 0x1840,
+ 0x5438, 0x0456,
+ 0x5439, 0x0454,
+ 0x543b, 0x0455,
+ 0x543c, 0x045b,
+ 0x543d, 0x1848,
+ 0x543e, 0x0448,
+ 0x5440, 0x045c,
+ 0x5441, 0x184a,
+ 0x5442, 0x0450,
+ 0x5443, 0x044d,
+ 0x5445, 0x1843,
+ 0x5446, 0x044c,
+ 0x5447, 0x184d,
+ 0x5448, 0x044f,
+ 0x544a, 0x0453,
+ 0x544b, 0x3ed1,
+ 0x544d, 0x3ea7,
+ 0x544e, 0x044a,
+ 0x544f, 0x1849,
+ 0x5454, 0x1842,
+ 0x5460, 0x192e,
+ 0x5461, 0x192d,
+ 0x5462, 0x0573,
+ 0x5463, 0x1930,
+ 0x5464, 0x1932,
+ 0x5465, 0x1927,
+ 0x5466, 0x192a,
+ 0x5467, 0x1931,
+ 0x5468, 0x0574,
+ 0x5469, 0x3f32,
+ 0x546a, 0x3d83,
+ 0x546b, 0x1924,
+ 0x546c, 0x1928,
+ 0x546d, 0x409d,
+ 0x546f, 0x192c,
+ 0x5470, 0x1a85,
+ 0x5471, 0x056f,
+ 0x5472, 0x1a89,
+ 0x5473, 0x0562,
+ 0x5474, 0x1929,
+ 0x5475, 0x0563,
+ 0x5476, 0x0570,
+ 0x5477, 0x0569,
+ 0x5478, 0x0565,
+ 0x547a, 0x1925,
+ 0x547b, 0x0568,
+ 0x547c, 0x056d,
+ 0x547d, 0x0576,
+ 0x547e, 0x1926,
+ 0x547f, 0x191f,
+ 0x5480, 0x0567,
+ 0x5481, 0x1920,
+ 0x5482, 0x1922,
+ 0x5484, 0x056a,
+ 0x5485, 0x46d9,
+ 0x5486, 0x056c,
+ 0x5487, 0x191e,
+ 0x5488, 0x1923,
+ 0x548b, 0x0575,
+ 0x548c, 0x0571,
+ 0x548d, 0x192b,
+ 0x548e, 0x0577,
+ 0x548f, 0x40a1,
+ 0x5490, 0x056e,
+ 0x5491, 0x1921,
+ 0x5492, 0x056b,
+ 0x5493, 0x45a7,
+ 0x5494, 0x3e98,
+ 0x5495, 0x0566,
+ 0x5496, 0x0564,
+ 0x5497, 0x3e8a,
+ 0x5498, 0x192f,
+ 0x549a, 0x0572,
+ 0x549c, 0x3f66,
+ 0x549e, 0x47ed,
+ 0x54a0, 0x1a84,
+ 0x54a1, 0x1a78,
+ 0x54a2, 0x1a87,
+ 0x54a3, 0x45a8,
+ 0x54a4, 0x40a2,
+ 0x54a5, 0x1a7a,
+ 0x54a6, 0x06d6,
+ 0x54a7, 0x06e4,
+ 0x54a8, 0x06d2,
+ 0x54a9, 0x06e3,
+ 0x54aa, 0x06db,
+ 0x54ab, 0x06e0,
+ 0x54ac, 0x06d0,
+ 0x54ad, 0x1a79,
+ 0x54ae, 0x1a7f,
+ 0x54af, 0x06df,
+ 0x54b0, 0x1a8b,
+ 0x54b1, 0x06e1,
+ 0x54b2, 0x3744,
+ 0x54b3, 0x06d7,
+ 0x54b4, 0x45a9,
+ 0x54b6, 0x1a81,
+ 0x54b7, 0x1a7e,
+ 0x54b8, 0x06d5,
+ 0x54b9, 0x45aa,
+ 0x54ba, 0x1a77,
+ 0x54bb, 0x06e2,
+ 0x54bc, 0x1a86,
+ 0x54bd, 0x06da,
+ 0x54be, 0x1a88,
+ 0x54bf, 0x06e5,
+ 0x54c0, 0x06d1,
+ 0x54c1, 0x06dc,
+ 0x54c2, 0x06d9,
+ 0x54c3, 0x1a7c,
+ 0x54c4, 0x06dd,
+ 0x54c5, 0x1a82,
+ 0x54c7, 0x06d8,
+ 0x54c8, 0x06de,
+ 0x54c9, 0x06d4,
+ 0x54cb, 0x39a3,
+ 0x54cc, 0x43a8,
+ 0x54cd, 0x3a00,
+ 0x54ce, 0x06d3,
+ 0x54cf, 0x1a7b,
+ 0x54d0, 0x45ab,
+ 0x54d6, 0x1a80,
+ 0x54da, 0x4923,
+ 0x54de, 0x1a8a,
+ 0x54e0, 0x1c57,
+ 0x54e1, 0x0870,
+ 0x54e2, 0x1c45,
+ 0x54e3, 0x4341,
+ 0x54e4, 0x1c4a,
+ 0x54e5, 0x0869,
+ 0x54e6, 0x0874,
+ 0x54e7, 0x1c48,
+ 0x54e8, 0x0864,
+ 0x54e9, 0x086e,
+ 0x54ea, 0x0873,
+ 0x54eb, 0x1c4f,
+ 0x54ed, 0x086f,
+ 0x54ee, 0x0872,
+ 0x54ef, 0x45ac,
+ 0x54f1, 0x1c52,
+ 0x54f2, 0x086a,
+ 0x54f3, 0x1c49,
+ 0x54f7, 0x1c55,
+ 0x54fa, 0x086c,
+ 0x54fb, 0x1c54,
+ 0x54fc, 0x0868,
+ 0x54fd, 0x0877,
+ 0x54ff, 0x1c4c,
+ 0x5501, 0x0866,
+ 0x5502, 0x3ccc,
+ 0x5503, 0x1c59,
+ 0x5504, 0x1c4d,
+ 0x5505, 0x1c51,
+ 0x5506, 0x086b,
+ 0x5507, 0x0876,
+ 0x5508, 0x1c4e,
+ 0x5509, 0x0871,
+ 0x550a, 0x1c53,
+ 0x550b, 0x1c5a,
+ 0x550c, 0x1e69,
+ 0x550d, 0x3a73,
+ 0x550e, 0x1c58,
+ 0x550f, 0x0878,
+ 0x5510, 0x0865,
+ 0x5511, 0x1c50,
+ 0x5512, 0x1c47,
+ 0x5513, 0x3ea9,
+ 0x5514, 0x086d,
+ 0x5517, 0x1c46,
+ 0x5518, 0x45ad,
+ 0x551a, 0x1c4b,
+ 0x551e, 0x3ea8,
+ 0x5523, 0x45ae,
+ 0x5525, 0x4309,
+ 0x5526, 0x1c44,
+ 0x5527, 0x0875,
+ 0x5528, 0x45af,
+ 0x552a, 0x1e61,
+ 0x552b, 0x409a,
+ 0x552c, 0x0a31,
+ 0x552d, 0x1e6f,
+ 0x552e, 0x0a2f,
+ 0x552f, 0x0a2c,
+ 0x5530, 0x1e66,
+ 0x5531, 0x0a28,
+ 0x5532, 0x1e6a,
+ 0x5533, 0x0a33,
+ 0x5534, 0x1e60,
+ 0x5535, 0x1e65,
+ 0x5536, 0x1e64,
+ 0x5537, 0x0867,
+ 0x5538, 0x0a2e,
+ 0x5539, 0x1e6d,
+ 0x553b, 0x1e70,
+ 0x553c, 0x1e5d,
+ 0x553e, 0x0c0c,
+ 0x553f, 0x43a9,
+ 0x5540, 0x1e71,
+ 0x5541, 0x0a34,
+ 0x5543, 0x0a26,
+ 0x5544, 0x0a23,
+ 0x5545, 0x1e68,
+ 0x5546, 0x0a20,
+ 0x5547, 0x40aa,
+ 0x5548, 0x1e6e,
+ 0x5549, 0x4068,
+ 0x554a, 0x0a27,
+ 0x554b, 0x1e72,
+ 0x554d, 0x1e5e,
+ 0x554e, 0x1e6c,
+ 0x554f, 0x0a2a,
+ 0x5550, 0x1e5f,
+ 0x5551, 0x1e62,
+ 0x5552, 0x1e67,
+ 0x5553, 0x43ae,
+ 0x5555, 0x0a2b,
+ 0x5556, 0x0a29,
+ 0x5557, 0x0a35,
+ 0x555c, 0x0a30,
+ 0x555d, 0x40a0,
+ 0x555e, 0x0a24,
+ 0x555f, 0x0abc,
+ 0x5561, 0x0a25,
+ 0x5562, 0x1e63,
+ 0x5563, 0x0a32,
+ 0x5564, 0x0a2d,
+ 0x5565, 0x1e6b,
+ 0x5566, 0x0a22,
+ 0x5569, 0x3e9f,
+ 0x556a, 0x0a21,
+ 0x556b, 0x3b2e,
+ 0x5571, 0x3bc6,
+ 0x5572, 0x3e8b,
+ 0x5573, 0x3f24,
+ 0x5575, 0x1e5b,
+ 0x5577, 0x20c7,
+ 0x5579, 0x435d,
+ 0x557b, 0x0bfb,
+ 0x557c, 0x0bfe,
+ 0x557d, 0x20d2,
+ 0x557e, 0x0c12,
+ 0x557f, 0x20d5,
+ 0x5580, 0x0bfc,
+ 0x5581, 0x20ce,
+ 0x5582, 0x0c02,
+ 0x5583, 0x0c08,
+ 0x5584, 0x0d1b,
+ 0x5586, 0x40ae,
+ 0x5587, 0x0c06,
+ 0x5588, 0x20cb,
+ 0x5589, 0x0c13,
+ 0x558a, 0x0bff,
+ 0x558b, 0x0c07,
+ 0x558c, 0x20d3,
+ 0x558d, 0x2387,
+ 0x558e, 0x20d8,
+ 0x558f, 0x20cc,
+ 0x5590, 0x430e,
+ 0x5591, 0x20c3,
+ 0x5592, 0x20d0,
+ 0x5593, 0x20ca,
+ 0x5594, 0x0c05,
+ 0x5595, 0x20d6,
+ 0x5598, 0x0c01,
+ 0x5599, 0x0c15,
+ 0x559a, 0x0c0e,
+ 0x559c, 0x0c03,
+ 0x559d, 0x0c00,
+ 0x559f, 0x0c0b,
+ 0x55a1, 0x20d7,
+ 0x55a2, 0x20c9,
+ 0x55a3, 0x20cf,
+ 0x55a4, 0x20d1,
+ 0x55a5, 0x20c5,
+ 0x55a6, 0x20d4,
+ 0x55a7, 0x0bfd,
+ 0x55a8, 0x20c4,
+ 0x55a9, 0x40af,
+ 0x55aa, 0x0c04,
+ 0x55ab, 0x0c14,
+ 0x55ac, 0x0c10,
+ 0x55ad, 0x20c6,
+ 0x55ae, 0x0c0a,
+ 0x55b0, 0x38f5,
+ 0x55b1, 0x0c11,
+ 0x55b2, 0x0c0d,
+ 0x55b3, 0x0c09,
+ 0x55b4, 0x39fe,
+ 0x55b5, 0x20cd,
+ 0x55b9, 0x43aa,
+ 0x55ba, 0x3e89,
+ 0x55bb, 0x0c0f,
+ 0x55bc, 0x3dc3,
+ 0x55bf, 0x2385,
+ 0x55c0, 0x2381,
+ 0x55c1, 0x3e4f,
+ 0x55c2, 0x2390,
+ 0x55c3, 0x237a,
+ 0x55c4, 0x2383,
+ 0x55c5, 0x0de0,
+ 0x55c7, 0x0dd9,
+ 0x55c8, 0x238c,
+ 0x55c9, 0x0de3,
+ 0x55ca, 0x237f,
+ 0x55cb, 0x237e,
+ 0x55cc, 0x237c,
+ 0x55cd, 0x238e,
+ 0x55ce, 0x0dd7,
+ 0x55cf, 0x2388,
+ 0x55d0, 0x237d,
+ 0x55d1, 0x0dda,
+ 0x55d2, 0x2386,
+ 0x55d3, 0x0dd5,
+ 0x55d4, 0x2382,
+ 0x55d5, 0x2389,
+ 0x55d6, 0x238b,
+ 0x55d7, 0x45b3,
+ 0x55d8, 0x43ab,
+ 0x55d9, 0x238f,
+ 0x55da, 0x0dde,
+ 0x55db, 0x237b,
+ 0x55dc, 0x0dd8,
+ 0x55dd, 0x2380,
+ 0x55de, 0x3e94,
+ 0x55df, 0x0dd3,
+ 0x55e1, 0x0ddf,
+ 0x55e2, 0x238a,
+ 0x55e3, 0x0ddb,
+ 0x55e5, 0x0de2,
+ 0x55e6, 0x0dd6,
+ 0x55e7, 0x011f,
+ 0x55e8, 0x0dd4,
+ 0x55e9, 0x2384,
+ 0x55ea, 0x3e7c,
+ 0x55ec, 0x37d2,
+ 0x55ef, 0x0ddd,
+ 0x55f0, 0x3e88,
+ 0x55f1, 0x3e83,
+ 0x55f2, 0x238d,
+ 0x55f5, 0x4786,
+ 0x55f6, 0x0f9f,
+ 0x55f7, 0x0f9a,
+ 0x55f9, 0x2637,
+ 0x55fa, 0x2633,
+ 0x55fb, 0x4626,
+ 0x55fc, 0x262d,
+ 0x55fd, 0x0f94,
+ 0x55fe, 0x0f90,
+ 0x55ff, 0x2636,
+ 0x5600, 0x0f91,
+ 0x5601, 0x2630,
+ 0x5602, 0x2632,
+ 0x5604, 0x2635,
+ 0x5605, 0x3e82,
+ 0x5606, 0x0f96,
+ 0x5608, 0x0f9d,
+ 0x5609, 0x0f97,
+ 0x560c, 0x262b,
+ 0x560d, 0x0f98,
+ 0x560f, 0x262e,
+ 0x5610, 0x0f9e,
+ 0x5611, 0x3f4d,
+ 0x5612, 0x262c,
+ 0x5613, 0x2631,
+ 0x5614, 0x0f95,
+ 0x5615, 0x262a,
+ 0x5616, 0x0f9b,
+ 0x5617, 0x0f93,
+ 0x561b, 0x0f92,
+ 0x561c, 0x262f,
+ 0x561d, 0x2634,
+ 0x561e, 0x3e68,
+ 0x561f, 0x0f9c,
+ 0x5620, 0x3f7d,
+ 0x5621, 0x43ad,
+ 0x5622, 0x3e67,
+ 0x5623, 0x4707,
+ 0x5625, 0x3e78,
+ 0x5627, 0x2629,
+ 0x5629, 0x1119,
+ 0x562a, 0x289d,
+ 0x562c, 0x289a,
+ 0x562d, 0x3e63,
+ 0x562e, 0x1113,
+ 0x562f, 0x111f,
+ 0x5632, 0x1116,
+ 0x5633, 0x2898,
+ 0x5634, 0x1118,
+ 0x5635, 0x2890,
+ 0x5636, 0x111e,
+ 0x5637, 0x40b7,
+ 0x5638, 0x289c,
+ 0x5639, 0x1115,
+ 0x563a, 0x289e,
+ 0x563b, 0x1114,
+ 0x563d, 0x2899,
+ 0x563e, 0x289b,
+ 0x563f, 0x1117,
+ 0x5640, 0x2897,
+ 0x5641, 0x2891,
+ 0x5642, 0x288e,
+ 0x5643, 0x3e7e,
+ 0x5645, 0x20c8,
+ 0x5646, 0x2894,
+ 0x5648, 0x288d,
+ 0x5649, 0x2893,
+ 0x564a, 0x2892,
+ 0x564c, 0x288f,
+ 0x564d, 0x40bc,
+ 0x564e, 0x111b,
+ 0x564f, 0x40bd,
+ 0x5650, 0x47cf,
+ 0x5652, 0x45c2,
+ 0x5653, 0x111a,
+ 0x5654, 0x43af,
+ 0x5657, 0x111c,
+ 0x5658, 0x2895,
+ 0x5659, 0x1295,
+ 0x565a, 0x2896,
+ 0x565d, 0x3ef9,
+ 0x565e, 0x2b10,
+ 0x5660, 0x2b09,
+ 0x5661, 0x3812,
+ 0x5662, 0x12a1,
+ 0x5663, 0x2b0d,
+ 0x5664, 0x1299,
+ 0x5665, 0x129d,
+ 0x5666, 0x2b0c,
+ 0x5668, 0x129c,
+ 0x5669, 0x1298,
+ 0x566a, 0x129b,
+ 0x566b, 0x1296,
+ 0x566c, 0x12a0,
+ 0x566d, 0x2b0e,
+ 0x566e, 0x2b0a,
+ 0x566f, 0x129f,
+ 0x5670, 0x2b08,
+ 0x5671, 0x129e,
+ 0x5672, 0x2b0f,
+ 0x5673, 0x2b0b,
+ 0x5674, 0x111d,
+ 0x5676, 0x12a2,
+ 0x5677, 0x2b11,
+ 0x5678, 0x129a,
+ 0x5679, 0x1297,
+ 0x567a, 0x3d85,
+ 0x567b, 0x3eb7,
+ 0x567c, 0x3eed,
+ 0x567e, 0x2d47,
+ 0x567f, 0x2d49,
+ 0x5680, 0x13ba,
+ 0x5681, 0x2d4a,
+ 0x5682, 0x2d48,
+ 0x5683, 0x2d46,
+ 0x5684, 0x2d45,
+ 0x5685, 0x13bc,
+ 0x5686, 0x2d44,
+ 0x5687, 0x13bd,
+ 0x5689, 0x4628,
+ 0x568a, 0x3949,
+ 0x568b, 0x3e4c,
+ 0x568c, 0x2d42,
+ 0x568e, 0x13b9,
+ 0x568f, 0x13be,
+ 0x5690, 0x13bb,
+ 0x5692, 0x39a6,
+ 0x5693, 0x2d41,
+ 0x5695, 0x14ca,
+ 0x5697, 0x2f13,
+ 0x5698, 0x2f11,
+ 0x5699, 0x2f16,
+ 0x569a, 0x2f14,
+ 0x569c, 0x2f12,
+ 0x569d, 0x2f15,
+ 0x569e, 0x39a4,
+ 0x569f, 0x3948,
+ 0x56a1, 0x436b,
+ 0x56a4, 0x3cc8,
+ 0x56a5, 0x1576,
+ 0x56a6, 0x3081,
+ 0x56a8, 0x1577,
+ 0x56aa, 0x3083,
+ 0x56ab, 0x307f,
+ 0x56ac, 0x3084,
+ 0x56ad, 0x3080,
+ 0x56ae, 0x14cb,
+ 0x56af, 0x45f7,
+ 0x56b1, 0x463f,
+ 0x56b2, 0x31c8,
+ 0x56b3, 0x31ca,
+ 0x56b4, 0x160c,
+ 0x56b5, 0x31c9,
+ 0x56b6, 0x160b,
+ 0x56b7, 0x160a,
+ 0x56b9, 0x486f,
+ 0x56bc, 0x160d,
+ 0x56bd, 0x32ca,
+ 0x56bf, 0x3e5d,
+ 0x56c0, 0x166b,
+ 0x56c1, 0x166a,
+ 0x56c2, 0x166c,
+ 0x56c3, 0x32c9,
+ 0x56c5, 0x3379,
+ 0x56c6, 0x3378,
+ 0x56c8, 0x16bd,
+ 0x56c9, 0x16bf,
+ 0x56ca, 0x16be,
+ 0x56cb, 0x337a,
+ 0x56cc, 0x16f6,
+ 0x56cd, 0x3481,
+ 0x56d1, 0x171f,
+ 0x56d3, 0x3480,
+ 0x56d4, 0x34c9,
+ 0x56d6, 0x488a,
+ 0x56d7, 0x1775,
+ 0x56da, 0x032d,
+ 0x56db, 0x032c,
+ 0x56dd, 0x03ac,
+ 0x56de, 0x03ab,
+ 0x56df, 0x17d0,
+ 0x56e0, 0x03aa,
+ 0x56e1, 0x17cf,
+ 0x56e2, 0x4548,
+ 0x56e4, 0x0463,
+ 0x56e5, 0x1850,
+ 0x56e7, 0x184f,
+ 0x56ea, 0x0461,
+ 0x56eb, 0x0464,
+ 0x56ed, 0x40c4,
+ 0x56ee, 0x184e,
+ 0x56ef, 0x40c3,
+ 0x56f0, 0x0462,
+ 0x56f1, 0x40bf,
+ 0x56f7, 0x1933,
+ 0x56f9, 0x1934,
+ 0x56fa, 0x0578,
+ 0x56fd, 0x3d64,
+ 0x56ff, 0x06e6,
+ 0x5700, 0x40c2,
+ 0x5701, 0x1c5b,
+ 0x5703, 0x0879,
+ 0x5707, 0x1e74,
+ 0x5708, 0x0a36,
+ 0x5709, 0x0a38,
+ 0x570a, 0x1e73,
+ 0x570b, 0x0a37,
+ 0x570c, 0x20d9,
+ 0x570d, 0x0c16,
+ 0x5712, 0x0de4,
+ 0x5714, 0x2391,
+ 0x5715, 0x3e36,
+ 0x5716, 0x0fa1,
+ 0x5718, 0x0fa0,
+ 0x571a, 0x289f,
+ 0x571b, 0x2b13,
+ 0x571c, 0x2b12,
+ 0x571d, 0x3a02,
+ 0x571e, 0x3505,
+ 0x571f, 0x027a,
+ 0x5720, 0x1784,
+ 0x5722, 0x179a,
+ 0x5728, 0x03af,
+ 0x5729, 0x03b3,
+ 0x572a, 0x17d2,
+ 0x572c, 0x03b1,
+ 0x572d, 0x03b0,
+ 0x572e, 0x17d1,
+ 0x572f, 0x03b2,
+ 0x5730, 0x03ae,
+ 0x5732, 0x3af9,
+ 0x5733, 0x03ad,
+ 0x5734, 0x17d3,
+ 0x573b, 0x046e,
+ 0x573e, 0x046b,
+ 0x573f, 0x4855,
+ 0x5740, 0x0467,
+ 0x5741, 0x1851,
+ 0x5742, 0x40cc,
+ 0x5743, 0x40de,
+ 0x5745, 0x1852,
+ 0x5746, 0x40c8,
+ 0x5747, 0x0469,
+ 0x5749, 0x1854,
+ 0x574a, 0x0465,
+ 0x574b, 0x1855,
+ 0x574c, 0x1853,
+ 0x574d, 0x0468,
+ 0x574e, 0x046a,
+ 0x574f, 0x046d,
+ 0x5750, 0x046c,
+ 0x5751, 0x0466,
+ 0x5752, 0x1856,
+ 0x5754, 0x4785,
+ 0x5757, 0x47e6,
+ 0x575b, 0x3982,
+ 0x575f, 0x3fbf,
+ 0x5761, 0x057d,
+ 0x5762, 0x1941,
+ 0x5764, 0x057f,
+ 0x5766, 0x057e,
+ 0x5767, 0x3f2b,
+ 0x5768, 0x1942,
+ 0x5769, 0x057c,
+ 0x576a, 0x057b,
+ 0x576b, 0x1938,
+ 0x576d, 0x1937,
+ 0x576f, 0x1935,
+ 0x5770, 0x193a,
+ 0x5771, 0x1939,
+ 0x5772, 0x1936,
+ 0x5773, 0x193f,
+ 0x5775, 0x193d,
+ 0x5776, 0x193b,
+ 0x5777, 0x057a,
+ 0x577a, 0x3f5f,
+ 0x577b, 0x193e,
+ 0x577c, 0x0580,
+ 0x577d, 0x1943,
+ 0x577e, 0x46dc,
+ 0x577f, 0x3a07,
+ 0x5780, 0x193c,
+ 0x5782, 0x06e7,
+ 0x5783, 0x0579,
+ 0x5788, 0x484b,
+ 0x578a, 0x3c7b,
+ 0x578b, 0x06e8,
+ 0x578c, 0x1a90,
+ 0x578d, 0x3a06,
+ 0x578f, 0x1a96,
+ 0x5790, 0x4166,
+ 0x5793, 0x06ee,
+ 0x5794, 0x1a94,
+ 0x5795, 0x1a9a,
+ 0x5797, 0x1a91,
+ 0x5798, 0x1a95,
+ 0x5799, 0x1a97,
+ 0x579a, 0x1a99,
+ 0x579b, 0x1a93,
+ 0x579c, 0x4608,
+ 0x579d, 0x1a92,
+ 0x579e, 0x1a8d,
+ 0x57a0, 0x06e9,
+ 0x57a1, 0x4864,
+ 0x57a2, 0x06eb,
+ 0x57a3, 0x06ea,
+ 0x57a4, 0x1a8f,
+ 0x57a5, 0x1a98,
+ 0x57a7, 0x4914,
+ 0x57aa, 0x4905,
+ 0x57ae, 0x06ed,
+ 0x57b4, 0x4741,
+ 0x57b5, 0x1a8c,
+ 0x57b6, 0x1c66,
+ 0x57b8, 0x1c65,
+ 0x57b9, 0x1c6a,
+ 0x57ba, 0x1c61,
+ 0x57bb, 0x3c79,
+ 0x57bc, 0x1c64,
+ 0x57bd, 0x1c63,
+ 0x57be, 0x372c,
+ 0x57bf, 0x1c67,
+ 0x57c1, 0x1c6b,
+ 0x57c2, 0x087b,
+ 0x57c3, 0x087e,
+ 0x57c4, 0x3b5b,
+ 0x57c6, 0x1c62,
+ 0x57c7, 0x1c68,
+ 0x57c8, 0x3d0b,
+ 0x57cb, 0x087d,
+ 0x57cc, 0x1c5d,
+ 0x57ce, 0x06ec,
+ 0x57cf, 0x1e82,
+ 0x57d0, 0x1c69,
+ 0x57d2, 0x1c60,
+ 0x57d4, 0x087c,
+ 0x57d5, 0x1c5f,
+ 0x57d7, 0x3c7d,
+ 0x57dc, 0x1e79,
+ 0x57dd, 0x3a05,
+ 0x57de, 0x3f01,
+ 0x57df, 0x0a39,
+ 0x57e0, 0x0a3d,
+ 0x57e1, 0x1e89,
+ 0x57e2, 0x1e77,
+ 0x57e3, 0x1e85,
+ 0x57e4, 0x0a3e,
+ 0x57e5, 0x1e87,
+ 0x57e6, 0x40cf,
+ 0x57e7, 0x1e8d,
+ 0x57e9, 0x1e91,
+ 0x57ec, 0x1e88,
+ 0x57ed, 0x1e7c,
+ 0x57ee, 0x1e84,
+ 0x57ef, 0x4754,
+ 0x57f0, 0x1e92,
+ 0x57f1, 0x1e90,
+ 0x57f2, 0x1e86,
+ 0x57f3, 0x1e81,
+ 0x57f4, 0x1e7a,
+ 0x57f5, 0x20e1,
+ 0x57f6, 0x1e78,
+ 0x57f7, 0x0a42,
+ 0x57f8, 0x1e7f,
+ 0x57f9, 0x0a43,
+ 0x57fa, 0x0a3f,
+ 0x57fb, 0x1e75,
+ 0x57fc, 0x1e8b,
+ 0x57fd, 0x1e7d,
+ 0x57fe, 0x408f,
+ 0x5800, 0x1e7b,
+ 0x5801, 0x1e8e,
+ 0x5802, 0x0a40,
+ 0x5803, 0x40d1,
+ 0x5804, 0x1e94,
+ 0x5805, 0x0a3a,
+ 0x5806, 0x0a3c,
+ 0x5807, 0x1e83,
+ 0x5808, 0x1e7e,
+ 0x5809, 0x087f,
+ 0x580a, 0x0a3b,
+ 0x580b, 0x1e80,
+ 0x580c, 0x1e8f,
+ 0x580d, 0x1e93,
+ 0x580e, 0x1e8a,
+ 0x5810, 0x1e8c,
+ 0x5812, 0x3d0a,
+ 0x5814, 0x1e76,
+ 0x5819, 0x20dc,
+ 0x581b, 0x20e5,
+ 0x581c, 0x20e4,
+ 0x581d, 0x0c1e,
+ 0x581e, 0x20dd,
+ 0x5820, 0x0c1f,
+ 0x5821, 0x0c1d,
+ 0x5822, 0x3c28,
+ 0x5823, 0x20df,
+ 0x5824, 0x0c1a,
+ 0x5825, 0x20e3,
+ 0x5826, 0x40d4,
+ 0x5827, 0x20de,
+ 0x5828, 0x20e0,
+ 0x5829, 0x20da,
+ 0x582a, 0x0c18,
+ 0x582c, 0x20ed,
+ 0x582d, 0x20ec,
+ 0x582e, 0x20e9,
+ 0x582f, 0x0c17,
+ 0x5830, 0x0c1b,
+ 0x5832, 0x1c5e,
+ 0x5833, 0x20e6,
+ 0x5834, 0x0c19,
+ 0x5835, 0x0a41,
+ 0x5836, 0x20e8,
+ 0x5837, 0x20db,
+ 0x5838, 0x20eb,
+ 0x5839, 0x20ea,
+ 0x583a, 0x3d72,
+ 0x583b, 0x20ee,
+ 0x583d, 0x239f,
+ 0x583f, 0x20e7,
+ 0x5840, 0x3d82,
+ 0x5844, 0x47bb,
+ 0x5847, 0x3ac2,
+ 0x5848, 0x20e2,
+ 0x5849, 0x2397,
+ 0x584a, 0x0def,
+ 0x584b, 0x0df2,
+ 0x584c, 0x0ded,
+ 0x584d, 0x2396,
+ 0x584e, 0x239a,
+ 0x584f, 0x2395,
+ 0x5851, 0x0de7,
+ 0x5852, 0x0df1,
+ 0x5853, 0x2392,
+ 0x5854, 0x0deb,
+ 0x5855, 0x2399,
+ 0x5857, 0x0de9,
+ 0x5858, 0x0de8,
+ 0x5859, 0x239c,
+ 0x585a, 0x0dea,
+ 0x585b, 0x239e,
+ 0x585c, 0x4949,
+ 0x585d, 0x239b,
+ 0x585e, 0x0de6,
+ 0x585f, 0x43df,
+ 0x5862, 0x0df0,
+ 0x5863, 0x23a0,
+ 0x5864, 0x2394,
+ 0x5865, 0x239d,
+ 0x5868, 0x2393,
+ 0x5869, 0x3d65,
+ 0x586b, 0x0dec,
+ 0x586c, 0x399a,
+ 0x586d, 0x0dee,
+ 0x586f, 0x2398,
+ 0x5871, 0x23a1,
+ 0x5872, 0x3c26,
+ 0x5873, 0x4355,
+ 0x5874, 0x263f,
+ 0x5875, 0x0fa2,
+ 0x5876, 0x2645,
+ 0x5879, 0x0fa7,
+ 0x587a, 0x2641,
+ 0x587b, 0x2648,
+ 0x587c, 0x2639,
+ 0x587d, 0x0fa9,
+ 0x587e, 0x0fa3,
+ 0x587f, 0x263e,
+ 0x5880, 0x1121,
+ 0x5881, 0x263d,
+ 0x5882, 0x2646,
+ 0x5883, 0x0fa4,
+ 0x5885, 0x0fa8,
+ 0x5886, 0x263c,
+ 0x5887, 0x2642,
+ 0x5888, 0x2647,
+ 0x5889, 0x2638,
+ 0x588a, 0x0fa6,
+ 0x588b, 0x2640,
+ 0x588e, 0x2644,
+ 0x588f, 0x264a,
+ 0x5890, 0x263a,
+ 0x5891, 0x2643,
+ 0x5893, 0x0fa5,
+ 0x5894, 0x2649,
+ 0x5898, 0x263b,
+ 0x5899, 0x4618,
+ 0x589a, 0x4903,
+ 0x589c, 0x1125,
+ 0x589d, 0x28a1,
+ 0x589e, 0x1123,
+ 0x589f, 0x1122,
+ 0x58a0, 0x28a3,
+ 0x58a1, 0x28a8,
+ 0x58a3, 0x28a4,
+ 0x58a5, 0x28a7,
+ 0x58a6, 0x1128,
+ 0x58a7, 0x3eeb,
+ 0x58a8, 0x1288,
+ 0x58a9, 0x1127,
+ 0x58aa, 0x40d7,
+ 0x58ab, 0x28a0,
+ 0x58ac, 0x28a6,
+ 0x58ae, 0x1126,
+ 0x58af, 0x28a5,
+ 0x58b0, 0x37a4,
+ 0x58b1, 0x28a2,
+ 0x58b3, 0x1124,
+ 0x58b5, 0x4840,
+ 0x58b6, 0x3dfd,
+ 0x58ba, 0x2b18,
+ 0x58bb, 0x36eb,
+ 0x58bc, 0x2b1a,
+ 0x58bd, 0x2b15,
+ 0x58be, 0x12a4,
+ 0x58bf, 0x2b17,
+ 0x58c1, 0x12a3,
+ 0x58c2, 0x2b19,
+ 0x58c5, 0x12a6,
+ 0x58c6, 0x2b1b,
+ 0x58c7, 0x12a5,
+ 0x58c8, 0x2b14,
+ 0x58c9, 0x2b16,
+ 0x58cb, 0x3a09,
+ 0x58ce, 0x13c2,
+ 0x58cf, 0x2d4d,
+ 0x58d1, 0x13c1,
+ 0x58d2, 0x2d4e,
+ 0x58d3, 0x13c0,
+ 0x58d4, 0x2d4c,
+ 0x58d5, 0x13bf,
+ 0x58d6, 0x2d4b,
+ 0x58d8, 0x14cd,
+ 0x58d9, 0x14cc,
+ 0x58da, 0x3085,
+ 0x58db, 0x3087,
+ 0x58dc, 0x40da,
+ 0x58dd, 0x3086,
+ 0x58de, 0x1578,
+ 0x58e0, 0x40d9,
+ 0x58e2, 0x157a,
+ 0x58e3, 0x31cb,
+ 0x58e4, 0x160e,
+ 0x58e7, 0x3411,
+ 0x58e8, 0x3410,
+ 0x58e9, 0x1720,
+ 0x58eb, 0x027b,
+ 0x58ec, 0x02c1,
+ 0x58ef, 0x046f,
+ 0x58f0, 0x4549,
+ 0x58f2, 0x3d68,
+ 0x58f3, 0x3c7a,
+ 0x58f4, 0x1a9b,
+ 0x58f9, 0x0c20,
+ 0x58fb, 0x40dc,
+ 0x58fc, 0x23a2,
+ 0x58fd, 0x0faa,
+ 0x58fe, 0x264b,
+ 0x58ff, 0x28a9,
+ 0x5902, 0x0224,
+ 0x5903, 0x1785,
+ 0x5904, 0x454a,
+ 0x5905, 0x4599,
+ 0x5906, 0x1857,
+ 0x5907, 0x454b,
+ 0x590a, 0x0224,
+ 0x590c, 0x1944,
+ 0x590d, 0x1a9c,
+ 0x590e, 0x1c6c,
+ 0x590f, 0x0880,
+ 0x5911, 0x4274,
+ 0x5912, 0x3088,
+ 0x5914, 0x166d,
+ 0x5915, 0x027c,
+ 0x5916, 0x032e,
+ 0x5917, 0x179c,
+ 0x5919, 0x03b4,
+ 0x591c, 0x0581,
+ 0x591f, 0x40e3,
+ 0x5920, 0x0a44,
+ 0x5922, 0x0fac,
+ 0x5924, 0x0fad,
+ 0x5925, 0x0fab,
+ 0x5927, 0x027d,
+ 0x5929, 0x02c2,
+ 0x592a, 0x02c4,
+ 0x592b, 0x02c3,
+ 0x592c, 0x1786,
+ 0x592d, 0x02c5,
+ 0x592e, 0x032f,
+ 0x592f, 0x179d,
+ 0x5931, 0x0330,
+ 0x5932, 0x454c,
+ 0x5934, 0x454d,
+ 0x5937, 0x03b6,
+ 0x593c, 0x17d4,
+ 0x593e, 0x0470,
+ 0x5940, 0x1858,
+ 0x5944, 0x0585,
+ 0x5945, 0x1945,
+ 0x5947, 0x0583,
+ 0x5949, 0x0582,
+ 0x594a, 0x1c6d,
+ 0x594e, 0x06f2,
+ 0x594f, 0x06f1,
+ 0x5950, 0x06f3,
+ 0x5951, 0x06f0,
+ 0x5953, 0x1a9d,
+ 0x5954, 0x0586,
+ 0x5955, 0x06ef,
+ 0x5957, 0x0881,
+ 0x595a, 0x0883,
+ 0x595c, 0x1e95,
+ 0x5960, 0x0c22,
+ 0x5961, 0x20ef,
+ 0x5962, 0x0a45,
+ 0x5965, 0x4852,
+ 0x5967, 0x0df3,
+ 0x5969, 0x0faf,
+ 0x596a, 0x0fae,
+ 0x596b, 0x264c,
+ 0x596d, 0x1129,
+ 0x596e, 0x12a7,
+ 0x5970, 0x2f17,
+ 0x5971, 0x337b,
+ 0x5972, 0x3412,
+ 0x5973, 0x027e,
+ 0x5974, 0x0331,
+ 0x5975, 0x3e6a,
+ 0x5976, 0x0332,
+ 0x5977, 0x17da,
+ 0x5978, 0x03b9,
+ 0x5979, 0x03bc,
+ 0x597b, 0x17d8,
+ 0x597c, 0x17d6,
+ 0x597d, 0x03bb,
+ 0x597e, 0x17d9,
+ 0x597f, 0x17db,
+ 0x5980, 0x17d5,
+ 0x5981, 0x03be,
+ 0x5982, 0x03bd,
+ 0x5983, 0x03ba,
+ 0x5984, 0x03b8,
+ 0x5985, 0x17d7,
+ 0x5989, 0x3d30,
+ 0x598a, 0x047b,
+ 0x598d, 0x0478,
+ 0x598e, 0x185d,
+ 0x598f, 0x1860,
+ 0x5990, 0x185f,
+ 0x5992, 0x0472,
+ 0x5993, 0x047a,
+ 0x5994, 0x3c99,
+ 0x5996, 0x0477,
+ 0x5997, 0x185c,
+ 0x5998, 0x185a,
+ 0x5999, 0x0476,
+ 0x599a, 0x3bb0,
+ 0x599d, 0x0471,
+ 0x599e, 0x0474,
+ 0x599f, 0x3daf,
+ 0x59a0, 0x185b,
+ 0x59a1, 0x1862,
+ 0x59a2, 0x185e,
+ 0x59a3, 0x0475,
+ 0x59a4, 0x0479,
+ 0x59a5, 0x047c,
+ 0x59a6, 0x1859,
+ 0x59a7, 0x1861,
+ 0x59a8, 0x0473,
+ 0x59ac, 0x3d81,
+ 0x59ae, 0x058b,
+ 0x59af, 0x0593,
+ 0x59b0, 0x3cd8,
+ 0x59b1, 0x1951,
+ 0x59b2, 0x194a,
+ 0x59b3, 0x0594,
+ 0x59b4, 0x1955,
+ 0x59b5, 0x1946,
+ 0x59b6, 0x194d,
+ 0x59b7, 0x3f2d,
+ 0x59b8, 0x3a10,
+ 0x59b9, 0x058a,
+ 0x59ba, 0x1947,
+ 0x59bb, 0x0588,
+ 0x59bc, 0x194e,
+ 0x59bd, 0x1952,
+ 0x59be, 0x0587,
+ 0x59c0, 0x1953,
+ 0x59c1, 0x194c,
+ 0x59c3, 0x194f,
+ 0x59c4, 0x3d04,
+ 0x59c5, 0x0596,
+ 0x59c6, 0x058d,
+ 0x59c7, 0x1956,
+ 0x59c8, 0x1954,
+ 0x59c9, 0x40ec,
+ 0x59ca, 0x0592,
+ 0x59cb, 0x0590,
+ 0x59cc, 0x194b,
+ 0x59cd, 0x058f,
+ 0x59ce, 0x1949,
+ 0x59cf, 0x1948,
+ 0x59d0, 0x058e,
+ 0x59d1, 0x058c,
+ 0x59d2, 0x0595,
+ 0x59d3, 0x0591,
+ 0x59d4, 0x0589,
+ 0x59d6, 0x1950,
+ 0x59d8, 0x06f5,
+ 0x59d9, 0x40f1,
+ 0x59da, 0x06fc,
+ 0x59db, 0x1aab,
+ 0x59dc, 0x06f4,
+ 0x59dd, 0x1aa3,
+ 0x59de, 0x1a9f,
+ 0x59e0, 0x1aaf,
+ 0x59e1, 0x1a9e,
+ 0x59e3, 0x06f7,
+ 0x59e4, 0x1aa8,
+ 0x59e5, 0x06fa,
+ 0x59e6, 0x06fd,
+ 0x59e8, 0x06f8,
+ 0x59e9, 0x1aac,
+ 0x59ea, 0x06fb,
+ 0x59eb, 0x3d59,
+ 0x59ec, 0x088a,
+ 0x59ed, 0x1ab2,
+ 0x59ee, 0x1aa0,
+ 0x59ef, 0x3d38,
+ 0x59f0, 0x3bb2,
+ 0x59f1, 0x1aa2,
+ 0x59f2, 0x1aa9,
+ 0x59f3, 0x1aad,
+ 0x59f4, 0x1ab1,
+ 0x59f5, 0x1aae,
+ 0x59f6, 0x1aa7,
+ 0x59f7, 0x1aaa,
+ 0x59f8, 0x3e4a,
+ 0x59f9, 0x40f8,
+ 0x59fa, 0x1aa4,
+ 0x59fb, 0x06ff,
+ 0x59fc, 0x1aa6,
+ 0x59fd, 0x1aa5,
+ 0x59fe, 0x1ab0,
+ 0x59ff, 0x06f6,
+ 0x5a00, 0x1aa1,
+ 0x5a01, 0x06fe,
+ 0x5a02, 0x3b8d,
+ 0x5a03, 0x06f9,
+ 0x5a09, 0x0890,
+ 0x5a0a, 0x1c75,
+ 0x5a0b, 0x3c89,
+ 0x5a0c, 0x088f,
+ 0x5a0d, 0x3b38,
+ 0x5a0f, 0x1c73,
+ 0x5a11, 0x0884,
+ 0x5a12, 0x3a13,
+ 0x5a13, 0x0889,
+ 0x5a15, 0x1c72,
+ 0x5a16, 0x1c6f,
+ 0x5a17, 0x1c74,
+ 0x5a18, 0x0885,
+ 0x5a19, 0x1c6e,
+ 0x5a1b, 0x0888,
+ 0x5a1c, 0x0886,
+ 0x5a1e, 0x1c76,
+ 0x5a1f, 0x0887,
+ 0x5a20, 0x088b,
+ 0x5a21, 0x3a1b,
+ 0x5a23, 0x088c,
+ 0x5a24, 0x40e8,
+ 0x5a25, 0x088e,
+ 0x5a27, 0x3de1,
+ 0x5a29, 0x088d,
+ 0x5a2a, 0x3b3b,
+ 0x5a2b, 0x3d40,
+ 0x5a2c, 0x3a0f,
+ 0x5a2d, 0x1c70,
+ 0x5a33, 0x1c77,
+ 0x5a35, 0x1e9c,
+ 0x5a36, 0x0a46,
+ 0x5a37, 0x20fd,
+ 0x5a38, 0x1e9b,
+ 0x5a39, 0x1eae,
+ 0x5a3c, 0x0a4c,
+ 0x5a3d, 0x3ac0,
+ 0x5a3e, 0x1eac,
+ 0x5a40, 0x0a4b,
+ 0x5a41, 0x0a47,
+ 0x5a42, 0x1eb5,
+ 0x5a43, 0x1ea5,
+ 0x5a44, 0x1ea8,
+ 0x5a45, 0x3917,
+ 0x5a46, 0x0a4f,
+ 0x5a47, 0x1eb2,
+ 0x5a48, 0x1eaa,
+ 0x5a49, 0x0a48,
+ 0x5a4a, 0x0a50,
+ 0x5a4c, 0x1eaf,
+ 0x5a4d, 0x1ead,
+ 0x5a50, 0x1e9e,
+ 0x5a51, 0x1eb3,
+ 0x5a52, 0x1ea7,
+ 0x5a53, 0x1ea2,
+ 0x5a54, 0x4603,
+ 0x5a55, 0x1e98,
+ 0x5a56, 0x1eb4,
+ 0x5a57, 0x1ea4,
+ 0x5a58, 0x1e97,
+ 0x5a59, 0x3b34,
+ 0x5a5a, 0x0a4e,
+ 0x5a5b, 0x1ea9,
+ 0x5a5c, 0x1eb6,
+ 0x5a5d, 0x1ea6,
+ 0x5a5e, 0x1e9a,
+ 0x5a5f, 0x1e9f,
+ 0x5a60, 0x1e96,
+ 0x5a61, 0x3d33,
+ 0x5a62, 0x0a4d,
+ 0x5a63, 0x40fb,
+ 0x5a64, 0x1ea3,
+ 0x5a65, 0x1ea0,
+ 0x5a66, 0x0a49,
+ 0x5a67, 0x1e99,
+ 0x5a68, 0x39b7,
+ 0x5a69, 0x1eb1,
+ 0x5a6a, 0x0a4a,
+ 0x5a6b, 0x3a42,
+ 0x5a6c, 0x1ea1,
+ 0x5a6d, 0x1e9d,
+ 0x5a6e, 0x3d3f,
+ 0x5a70, 0x1eb0,
+ 0x5a71, 0x3d34,
+ 0x5a77, 0x0c23,
+ 0x5a78, 0x20f6,
+ 0x5a79, 0x3ce1,
+ 0x5a7a, 0x20f3,
+ 0x5a7b, 0x2104,
+ 0x5a7c, 0x20f8,
+ 0x5a7d, 0x2105,
+ 0x5a7e, 0x3a11,
+ 0x5a7f, 0x0c25,
+ 0x5a81, 0x3a1d,
+ 0x5a82, 0x3d31,
+ 0x5a83, 0x2101,
+ 0x5a84, 0x20fe,
+ 0x5a86, 0x3b81,
+ 0x5a88, 0x4263,
+ 0x5a8a, 0x20ff,
+ 0x5a8b, 0x2102,
+ 0x5a8c, 0x2106,
+ 0x5a8e, 0x1eab,
+ 0x5a8f, 0x2108,
+ 0x5a90, 0x23b6,
+ 0x5a91, 0x4235,
+ 0x5a92, 0x0c26,
+ 0x5a93, 0x2109,
+ 0x5a94, 0x20f1,
+ 0x5a95, 0x20fb,
+ 0x5a96, 0x4100,
+ 0x5a97, 0x2100,
+ 0x5a99, 0x3a0a,
+ 0x5a9a, 0x0c24,
+ 0x5a9b, 0x0c27,
+ 0x5a9c, 0x2107,
+ 0x5a9d, 0x210a,
+ 0x5a9e, 0x20f5,
+ 0x5a9f, 0x20f2,
+ 0x5aa0, 0x4172,
+ 0x5aa1, 0x3cdc,
+ 0x5aa2, 0x20f4,
+ 0x5aa5, 0x20f9,
+ 0x5aa6, 0x20f7,
+ 0x5aa7, 0x0c28,
+ 0x5aa9, 0x2103,
+ 0x5aab, 0x40fa,
+ 0x5aac, 0x20fa,
+ 0x5aae, 0x20fc,
+ 0x5aaf, 0x20f0,
+ 0x5ab0, 0x23aa,
+ 0x5ab1, 0x23a8,
+ 0x5ab2, 0x0dfc,
+ 0x5ab3, 0x0dfa,
+ 0x5ab4, 0x23b2,
+ 0x5ab5, 0x23a9,
+ 0x5ab6, 0x23b3,
+ 0x5ab7, 0x23af,
+ 0x5ab8, 0x23a7,
+ 0x5ab9, 0x23b5,
+ 0x5aba, 0x23a6,
+ 0x5abb, 0x23ad,
+ 0x5abc, 0x0df9,
+ 0x5abd, 0x0df8,
+ 0x5abe, 0x0df7,
+ 0x5abf, 0x23ab,
+ 0x5ac0, 0x23b0,
+ 0x5ac1, 0x0df4,
+ 0x5ac2, 0x0dfb,
+ 0x5ac3, 0x3896,
+ 0x5ac4, 0x23a4,
+ 0x5ac6, 0x23ae,
+ 0x5ac7, 0x23a3,
+ 0x5ac8, 0x23ac,
+ 0x5ac9, 0x0df5,
+ 0x5aca, 0x23b1,
+ 0x5acb, 0x23a5,
+ 0x5acc, 0x0df6,
+ 0x5acd, 0x23b4,
+ 0x5ace, 0x3c88,
+ 0x5acf, 0x43b5,
+ 0x5ad3, 0x4102,
+ 0x5ad5, 0x2650,
+ 0x5ad6, 0x0fb4,
+ 0x5ad7, 0x0fb3,
+ 0x5ad8, 0x0fb5,
+ 0x5ad9, 0x265c,
+ 0x5ada, 0x2652,
+ 0x5adb, 0x2658,
+ 0x5adc, 0x264d,
+ 0x5add, 0x265b,
+ 0x5ade, 0x265a,
+ 0x5adf, 0x265e,
+ 0x5ae0, 0x2657,
+ 0x5ae1, 0x0fb0,
+ 0x5ae2, 0x2656,
+ 0x5ae3, 0x0fb6,
+ 0x5ae4, 0x3b86,
+ 0x5ae5, 0x264f,
+ 0x5ae6, 0x0fb1,
+ 0x5ae8, 0x265d,
+ 0x5ae9, 0x0fb2,
+ 0x5aea, 0x2651,
+ 0x5aeb, 0x2654,
+ 0x5aec, 0x2659,
+ 0x5aed, 0x2653,
+ 0x5aee, 0x264e,
+ 0x5af0, 0x3ee7,
+ 0x5af2, 0x37f5,
+ 0x5af3, 0x2655,
+ 0x5af4, 0x28ab,
+ 0x5af5, 0x112d,
+ 0x5af6, 0x28ae,
+ 0x5af7, 0x28ad,
+ 0x5af8, 0x28b0,
+ 0x5af9, 0x28b2,
+ 0x5afa, 0x36ee,
+ 0x5afb, 0x112b,
+ 0x5afd, 0x28ac,
+ 0x5afe, 0x3c1d,
+ 0x5aff, 0x28aa,
+ 0x5b01, 0x28b3,
+ 0x5b02, 0x28b1,
+ 0x5b03, 0x28af,
+ 0x5b05, 0x28b5,
+ 0x5b07, 0x28b4,
+ 0x5b08, 0x112f,
+ 0x5b09, 0x112a,
+ 0x5b0b, 0x112c,
+ 0x5b0c, 0x112e,
+ 0x5b0d, 0x48ff,
+ 0x5b0f, 0x28b6,
+ 0x5b10, 0x2b22,
+ 0x5b11, 0x3bf6,
+ 0x5b13, 0x2b21,
+ 0x5b14, 0x2b20,
+ 0x5b16, 0x2b23,
+ 0x5b17, 0x2b1c,
+ 0x5b19, 0x2b1d,
+ 0x5b1a, 0x2b25,
+ 0x5b1b, 0x2b1e,
+ 0x5b1d, 0x12a8,
+ 0x5b1e, 0x2b27,
+ 0x5b1f, 0x4941,
+ 0x5b20, 0x2b26,
+ 0x5b21, 0x2b1f,
+ 0x5b23, 0x2d52,
+ 0x5b24, 0x13c5,
+ 0x5b25, 0x2d50,
+ 0x5b26, 0x2d55,
+ 0x5b27, 0x2d54,
+ 0x5b28, 0x2b24,
+ 0x5b2a, 0x13c4,
+ 0x5b2b, 0x3b84,
+ 0x5b2c, 0x2d53,
+ 0x5b2d, 0x2d4f,
+ 0x5b2e, 0x2d57,
+ 0x5b2f, 0x2d56,
+ 0x5b30, 0x13c3,
+ 0x5b32, 0x2d51,
+ 0x5b34, 0x12a9,
+ 0x5b38, 0x14ce,
+ 0x5b3c, 0x2f18,
+ 0x5b3d, 0x3089,
+ 0x5b40, 0x160f,
+ 0x5b41, 0x38c8,
+ 0x5b43, 0x1610,
+ 0x5b44, 0x3a44,
+ 0x5b45, 0x31cc,
+ 0x5b46, 0x42b2,
+ 0x5b47, 0x32cd,
+ 0x5b48, 0x32cc,
+ 0x5b4a, 0x38cd,
+ 0x5b4b, 0x337c,
+ 0x5b4d, 0x3413,
+ 0x5b4e, 0x3482,
+ 0x5b4f, 0x3a31,
+ 0x5b50, 0x027f,
+ 0x5b53, 0x0281,
+ 0x5b54, 0x02c6,
+ 0x5b55, 0x0333,
+ 0x5b56, 0x17dc,
+ 0x5b57, 0x03bf,
+ 0x5b5a, 0x047f,
+ 0x5b5c, 0x047e,
+ 0x5b5d, 0x047d,
+ 0x5b5f, 0x0597,
+ 0x5b62, 0x1957,
+ 0x5b63, 0x0599,
+ 0x5b64, 0x0598,
+ 0x5b65, 0x1958,
+ 0x5b66, 0x454e,
+ 0x5b68, 0x461d,
+ 0x5b69, 0x0700,
+ 0x5b6b, 0x0891,
+ 0x5b6c, 0x1c78,
+ 0x5b6d, 0x3e5f,
+ 0x5b6e, 0x1eb8,
+ 0x5b70, 0x0a51,
+ 0x5b71, 0x0c2a,
+ 0x5b72, 0x1eb7,
+ 0x5b73, 0x0c29,
+ 0x5b74, 0x3732,
+ 0x5b75, 0x0fb7,
+ 0x5b76, 0x410a,
+ 0x5b77, 0x265f,
+ 0x5b78, 0x12aa,
+ 0x5b7a, 0x13c6,
+ 0x5b7b, 0x2d58,
+ 0x5b7c, 0x410c,
+ 0x5b7d, 0x1611,
+ 0x5b7f, 0x16c0,
+ 0x5b80, 0x0225,
+ 0x5b81, 0x179e,
+ 0x5b82, 0x4044,
+ 0x5b83, 0x0334,
+ 0x5b84, 0x179f,
+ 0x5b85, 0x03c3,
+ 0x5b87, 0x03c1,
+ 0x5b89, 0x03c4,
+ 0x5b8b, 0x0482,
+ 0x5b8c, 0x0481,
+ 0x5b8e, 0x1863,
+ 0x5b8f, 0x0483,
+ 0x5b90, 0x48e9,
+ 0x5b92, 0x1864,
+ 0x5b93, 0x1959,
+ 0x5b95, 0x195a,
+ 0x5b97, 0x059a,
+ 0x5b98, 0x059c,
+ 0x5b99, 0x059e,
+ 0x5b9a, 0x059b,
+ 0x5b9b, 0x059f,
+ 0x5b9c, 0x059d,
+ 0x5b9d, 0x4116,
+ 0x5b9e, 0x454f,
+ 0x5ba2, 0x0704,
+ 0x5ba3, 0x0701,
+ 0x5ba4, 0x0703,
+ 0x5ba5, 0x0705,
+ 0x5ba6, 0x0702,
+ 0x5ba7, 0x1c79,
+ 0x5ba8, 0x1ab3,
+ 0x5baa, 0x417b,
+ 0x5bac, 0x1c7b,
+ 0x5bad, 0x1c7a,
+ 0x5bae, 0x0897,
+ 0x5bb0, 0x0893,
+ 0x5bb3, 0x0894,
+ 0x5bb4, 0x0896,
+ 0x5bb5, 0x0898,
+ 0x5bb6, 0x0895,
+ 0x5bb8, 0x089a,
+ 0x5bb9, 0x0899,
+ 0x5bbf, 0x0a56,
+ 0x5bc0, 0x1eba,
+ 0x5bc1, 0x1eb9,
+ 0x5bc2, 0x0a55,
+ 0x5bc3, 0x3f25,
+ 0x5bc4, 0x0a54,
+ 0x5bc5, 0x0a53,
+ 0x5bc6, 0x0a57,
+ 0x5bc7, 0x0a52,
+ 0x5bca, 0x2110,
+ 0x5bcb, 0x210d,
+ 0x5bcc, 0x0c2c,
+ 0x5bcd, 0x210c,
+ 0x5bce, 0x2111,
+ 0x5bd0, 0x0c2e,
+ 0x5bd1, 0x210f,
+ 0x5bd2, 0x0c2b,
+ 0x5bd3, 0x0c2d,
+ 0x5bd4, 0x210e,
+ 0x5bd5, 0x4111,
+ 0x5bd6, 0x23b7,
+ 0x5bd7, 0x42bb,
+ 0x5bd8, 0x23b8,
+ 0x5bde, 0x0fb8,
+ 0x5bdf, 0x0fc0,
+ 0x5be0, 0x2660,
+ 0x5be1, 0x0fba,
+ 0x5be2, 0x0fbe,
+ 0x5be3, 0x2661,
+ 0x5be4, 0x0fbf,
+ 0x5be5, 0x0fbb,
+ 0x5be7, 0x0fb9,
+ 0x5be8, 0x0fbd,
+ 0x5be9, 0x1132,
+ 0x5bea, 0x210b,
+ 0x5beb, 0x1133,
+ 0x5bec, 0x1131,
+ 0x5bee, 0x1130,
+ 0x5bef, 0x2b28,
+ 0x5bf0, 0x12ab,
+ 0x5bf1, 0x2d59,
+ 0x5bf3, 0x4115,
+ 0x5bf5, 0x157b,
+ 0x5bf6, 0x1612,
+ 0x5bf8, 0x0282,
+ 0x5bfa, 0x03c5,
+ 0x5bff, 0x40dd,
+ 0x5c01, 0x0706,
+ 0x5c03, 0x1c7c,
+ 0x5c04, 0x089b,
+ 0x5c05, 0x4118,
+ 0x5c07, 0x0a5a,
+ 0x5c08, 0x0a59,
+ 0x5c09, 0x0a58,
+ 0x5c0a, 0x0c2f,
+ 0x5c0c, 0x2112,
+ 0x5c0d, 0x0fc1,
+ 0x5c0e, 0x12ac,
+ 0x5c0f, 0x0283,
+ 0x5c10, 0x1787,
+ 0x5c11, 0x02c7,
+ 0x5c12, 0x17a0,
+ 0x5c13, 0x411a,
+ 0x5c14, 0x411c,
+ 0x5c15, 0x17dd,
+ 0x5c16, 0x03c6,
+ 0x5c1a, 0x05a0,
+ 0x5c1c, 0x45ea,
+ 0x5c1e, 0x3a29,
+ 0x5c1f, 0x23ba,
+ 0x5c20, 0x3d89,
+ 0x5c22, 0x0284,
+ 0x5c23, 0x44e8,
+ 0x5c24, 0x02c8,
+ 0x5c25, 0x17de,
+ 0x5c28, 0x1865,
+ 0x5c2a, 0x1866,
+ 0x5c2c, 0x0484,
+ 0x5c30, 0x2113,
+ 0x5c31, 0x0c31,
+ 0x5c33, 0x23bb,
+ 0x5c37, 0x13c7,
+ 0x5c38, 0x0285,
+ 0x5c39, 0x0299,
+ 0x5c3a, 0x02c9,
+ 0x5c3b, 0x17a1,
+ 0x5c3c, 0x0335,
+ 0x5c3e, 0x0488,
+ 0x5c3f, 0x0487,
+ 0x5c40, 0x0485,
+ 0x5c44, 0x195b,
+ 0x5c45, 0x05a2,
+ 0x5c47, 0x195c,
+ 0x5c48, 0x05a1,
+ 0x5c49, 0x411f,
+ 0x5c4a, 0x3f5c,
+ 0x5c4b, 0x070a,
+ 0x5c4c, 0x1ab4,
+ 0x5c4d, 0x0709,
+ 0x5c4e, 0x0707,
+ 0x5c50, 0x089e,
+ 0x5c51, 0x089c,
+ 0x5c53, 0x3f02,
+ 0x5c54, 0x1c7e,
+ 0x5c55, 0x089d,
+ 0x5c56, 0x1c7d,
+ 0x5c58, 0x0892,
+ 0x5c59, 0x1ebb,
+ 0x5c5c, 0x0a5c,
+ 0x5c5e, 0x3d67,
+ 0x5c60, 0x0a5b,
+ 0x5c62, 0x0fc2,
+ 0x5c63, 0x2662,
+ 0x5c64, 0x1134,
+ 0x5c67, 0x28b7,
+ 0x5c68, 0x13c8,
+ 0x5c69, 0x2f19,
+ 0x5c6c, 0x166e,
+ 0x5c6d, 0x3483,
+ 0x5c6e, 0x1776,
+ 0x5c6f, 0x02ca,
+ 0x5c71, 0x0286,
+ 0x5c73, 0x17a3,
+ 0x5c74, 0x17a2,
+ 0x5c79, 0x03c7,
+ 0x5c7a, 0x17e0,
+ 0x5c7c, 0x17df,
+ 0x5c7e, 0x17e2,
+ 0x5c85, 0x4121,
+ 0x5c86, 0x186e,
+ 0x5c88, 0x1869,
+ 0x5c89, 0x186b,
+ 0x5c8a, 0x186d,
+ 0x5c8b, 0x186a,
+ 0x5c8c, 0x048c,
+ 0x5c8d, 0x1867,
+ 0x5c8f, 0x1868,
+ 0x5c90, 0x0489,
+ 0x5c92, 0x186c,
+ 0x5c93, 0x186f,
+ 0x5c94, 0x048b,
+ 0x5c95, 0x1870,
+ 0x5c99, 0x468c,
+ 0x5c9a, 0x4551,
+ 0x5c9c, 0x495a,
+ 0x5c9d, 0x196a,
+ 0x5c9e, 0x3a2a,
+ 0x5c9f, 0x1964,
+ 0x5ca0, 0x195f,
+ 0x5ca1, 0x05a5,
+ 0x5ca2, 0x1967,
+ 0x5ca3, 0x1965,
+ 0x5ca4, 0x195e,
+ 0x5ca5, 0x196b,
+ 0x5ca6, 0x196e,
+ 0x5ca7, 0x1969,
+ 0x5ca8, 0x1962,
+ 0x5ca9, 0x05a7,
+ 0x5caa, 0x1968,
+ 0x5cab, 0x05a8,
+ 0x5cac, 0x1963,
+ 0x5cad, 0x1966,
+ 0x5cae, 0x195d,
+ 0x5caf, 0x1961,
+ 0x5cb0, 0x196d,
+ 0x5cb1, 0x05a9,
+ 0x5cb3, 0x05aa,
+ 0x5cb5, 0x1960,
+ 0x5cb6, 0x196c,
+ 0x5cb7, 0x05a4,
+ 0x5cb8, 0x05a6,
+ 0x5cba, 0x412b,
+ 0x5cc1, 0x43b8,
+ 0x5cc2, 0x3d4c,
+ 0x5cc6, 0x1ac5,
+ 0x5cc7, 0x1abe,
+ 0x5cc8, 0x1ac4,
+ 0x5cc9, 0x1abd,
+ 0x5cca, 0x1abf,
+ 0x5ccb, 0x1ab9,
+ 0x5ccc, 0x1ab7,
+ 0x5cce, 0x1ac6,
+ 0x5ccf, 0x1ac3,
+ 0x5cd0, 0x1ab5,
+ 0x5cd1, 0x3f13,
+ 0x5cd2, 0x070c,
+ 0x5cd3, 0x1ac1,
+ 0x5cd6, 0x1ac0,
+ 0x5cd7, 0x1ab8,
+ 0x5cd8, 0x1ab6,
+ 0x5cd9, 0x070b,
+ 0x5cda, 0x1abc,
+ 0x5cdb, 0x1aba,
+ 0x5cde, 0x1abb,
+ 0x5cdf, 0x1ac7,
+ 0x5ce5, 0x4637,
+ 0x5ce8, 0x08a3,
+ 0x5ce9, 0x4122,
+ 0x5cea, 0x08a2,
+ 0x5cec, 0x1c7f,
+ 0x5ced, 0x089f,
+ 0x5cee, 0x1c81,
+ 0x5cef, 0x4123,
+ 0x5cf0, 0x08a4,
+ 0x5cf1, 0x1c82,
+ 0x5cf4, 0x08a7,
+ 0x5cf6, 0x08a5,
+ 0x5cf7, 0x1c83,
+ 0x5cf8, 0x1ac8,
+ 0x5cf9, 0x1c85,
+ 0x5cfb, 0x08a1,
+ 0x5cfd, 0x08a0,
+ 0x5cff, 0x1c80,
+ 0x5d00, 0x1c84,
+ 0x5d01, 0x08a6,
+ 0x5d06, 0x0a5f,
+ 0x5d07, 0x0a5e,
+ 0x5d0b, 0x1ebd,
+ 0x5d0c, 0x1ec1,
+ 0x5d0d, 0x1ec3,
+ 0x5d0e, 0x0a60,
+ 0x5d0f, 0x1ec6,
+ 0x5d10, 0x4127,
+ 0x5d11, 0x0a64,
+ 0x5d12, 0x1ec8,
+ 0x5d14, 0x0a66,
+ 0x5d15, 0x43b9,
+ 0x5d16, 0x0a62,
+ 0x5d17, 0x0a6a,
+ 0x5d18, 0x4128,
+ 0x5d19, 0x0a67,
+ 0x5d1a, 0x1ebf,
+ 0x5d1b, 0x0a61,
+ 0x5d1d, 0x1ebe,
+ 0x5d1e, 0x1ebc,
+ 0x5d1f, 0x1eca,
+ 0x5d20, 0x1ec0,
+ 0x5d22, 0x0a63,
+ 0x5d23, 0x1ec9,
+ 0x5d24, 0x0a68,
+ 0x5d25, 0x1ec5,
+ 0x5d26, 0x1ec4,
+ 0x5d27, 0x0a69,
+ 0x5d28, 0x1ec2,
+ 0x5d29, 0x0a65,
+ 0x5d2c, 0x3df7,
+ 0x5d2e, 0x1ecb,
+ 0x5d2f, 0x46d3,
+ 0x5d30, 0x1ec7,
+ 0x5d31, 0x2122,
+ 0x5d32, 0x2129,
+ 0x5d33, 0x211e,
+ 0x5d34, 0x0c34,
+ 0x5d35, 0x211a,
+ 0x5d36, 0x212a,
+ 0x5d37, 0x2114,
+ 0x5d38, 0x2127,
+ 0x5d39, 0x2125,
+ 0x5d3a, 0x211f,
+ 0x5d3c, 0x2128,
+ 0x5d3d, 0x2121,
+ 0x5d3e, 0x4629,
+ 0x5d3f, 0x2119,
+ 0x5d40, 0x212b,
+ 0x5d41, 0x2117,
+ 0x5d42, 0x2124,
+ 0x5d43, 0x2115,
+ 0x5d45, 0x212c,
+ 0x5d46, 0x4129,
+ 0x5d47, 0x0c35,
+ 0x5d48, 0x462a,
+ 0x5d49, 0x2126,
+ 0x5d4a, 0x23be,
+ 0x5d4b, 0x2118,
+ 0x5d4c, 0x0c32,
+ 0x5d4e, 0x211c,
+ 0x5d50, 0x0c33,
+ 0x5d51, 0x211b,
+ 0x5d52, 0x2120,
+ 0x5d55, 0x211d,
+ 0x5d56, 0x43ba,
+ 0x5d57, 0x3fca,
+ 0x5d59, 0x2123,
+ 0x5d5b, 0x3dd5,
+ 0x5d5e, 0x23c2,
+ 0x5d62, 0x23c5,
+ 0x5d63, 0x23bd,
+ 0x5d65, 0x23bf,
+ 0x5d67, 0x23c4,
+ 0x5d68, 0x23c3,
+ 0x5d69, 0x0dfd,
+ 0x5d6b, 0x2116,
+ 0x5d6c, 0x23c1,
+ 0x5d6f, 0x0dfe,
+ 0x5d70, 0x46e4,
+ 0x5d71, 0x23bc,
+ 0x5d72, 0x23c0,
+ 0x5d74, 0x3eef,
+ 0x5d77, 0x2669,
+ 0x5d79, 0x2670,
+ 0x5d7a, 0x2667,
+ 0x5d7c, 0x266e,
+ 0x5d7d, 0x2665,
+ 0x5d7e, 0x266d,
+ 0x5d7f, 0x2671,
+ 0x5d80, 0x2664,
+ 0x5d81, 0x2668,
+ 0x5d82, 0x2663,
+ 0x5d84, 0x0fc3,
+ 0x5d85, 0x3e34,
+ 0x5d86, 0x2666,
+ 0x5d87, 0x0fc4,
+ 0x5d88, 0x266c,
+ 0x5d89, 0x266b,
+ 0x5d8a, 0x266a,
+ 0x5d8b, 0x4124,
+ 0x5d8d, 0x266f,
+ 0x5d8e, 0x3f0c,
+ 0x5d92, 0x28bb,
+ 0x5d93, 0x28bd,
+ 0x5d94, 0x1137,
+ 0x5d95, 0x28be,
+ 0x5d97, 0x28b9,
+ 0x5d99, 0x28b8,
+ 0x5d9a, 0x28c2,
+ 0x5d9c, 0x28c0,
+ 0x5d9d, 0x1136,
+ 0x5d9e, 0x28c3,
+ 0x5d9f, 0x28ba,
+ 0x5da0, 0x28bf,
+ 0x5da1, 0x28c1,
+ 0x5da2, 0x28bc,
+ 0x5da4, 0x462d,
+ 0x5da7, 0x2b2c,
+ 0x5da8, 0x2b31,
+ 0x5da9, 0x2b2b,
+ 0x5daa, 0x2b30,
+ 0x5dab, 0x3e39,
+ 0x5dac, 0x2b29,
+ 0x5dad, 0x2b33,
+ 0x5dae, 0x2b2f,
+ 0x5daf, 0x2b34,
+ 0x5db0, 0x2b2e,
+ 0x5db1, 0x2b2a,
+ 0x5db2, 0x2b32,
+ 0x5db4, 0x2b35,
+ 0x5db5, 0x2b2d,
+ 0x5db6, 0x4158,
+ 0x5db7, 0x2d5b,
+ 0x5db8, 0x13cc,
+ 0x5db9, 0x462e,
+ 0x5dba, 0x13ca,
+ 0x5dbc, 0x13c9,
+ 0x5dbd, 0x13cb,
+ 0x5dc0, 0x2f1b,
+ 0x5dc1, 0x3bff,
+ 0x5dc2, 0x3023,
+ 0x5dc3, 0x308c,
+ 0x5dc6, 0x31cd,
+ 0x5dc9, 0x1613,
+ 0x5dcb, 0x32ce,
+ 0x5dcd, 0x166f,
+ 0x5dcf, 0x32cf,
+ 0x5dd1, 0x337f,
+ 0x5dd2, 0x16c2,
+ 0x5dd4, 0x16c1,
+ 0x5dd5, 0x337e,
+ 0x5dd6, 0x16f7,
+ 0x5dd7, 0x412c,
+ 0x5dd8, 0x3414,
+ 0x5ddb, 0x0226,
+ 0x5ddd, 0x0287,
+ 0x5dde, 0x03c8,
+ 0x5ddf, 0x17e3,
+ 0x5de0, 0x1871,
+ 0x5de1, 0x051a,
+ 0x5de2, 0x0a6b,
+ 0x5de5, 0x0288,
+ 0x5de6, 0x0338,
+ 0x5de7, 0x0337,
+ 0x5de8, 0x0336,
+ 0x5deb, 0x048d,
+ 0x5dee, 0x08a8,
+ 0x5df0, 0x23c6,
+ 0x5df1, 0x0289,
+ 0x5df4, 0x02cb,
+ 0x5df5, 0x3f61,
+ 0x5df7, 0x070d,
+ 0x5df9, 0x1ac9,
+ 0x5dfd, 0x0c36,
+ 0x5dfe, 0x028c,
+ 0x5dff, 0x1788,
+ 0x5e02, 0x0339,
+ 0x5e04, 0x17a4,
+ 0x5e06, 0x03c9,
+ 0x5e09, 0x4140,
+ 0x5e0a, 0x1872,
+ 0x5e0b, 0x3d8a,
+ 0x5e0c, 0x048e,
+ 0x5e0e, 0x1873,
+ 0x5e11, 0x05b0,
+ 0x5e12, 0x3f2e,
+ 0x5e14, 0x1970,
+ 0x5e15, 0x05ae,
+ 0x5e16, 0x05ad,
+ 0x5e17, 0x196f,
+ 0x5e18, 0x05ab,
+ 0x5e19, 0x1971,
+ 0x5e1a, 0x05ac,
+ 0x5e1b, 0x05af,
+ 0x5e1d, 0x070e,
+ 0x5e1f, 0x0710,
+ 0x5e20, 0x1acd,
+ 0x5e21, 0x1aca,
+ 0x5e24, 0x1ace,
+ 0x5e25, 0x070f,
+ 0x5e28, 0x1c87,
+ 0x5e29, 0x1c86,
+ 0x5e2b, 0x08aa,
+ 0x5e2d, 0x08a9,
+ 0x5e2e, 0x4135,
+ 0x5e33, 0x0a6e,
+ 0x5e34, 0x1ecd,
+ 0x5e36, 0x0a6d,
+ 0x5e37, 0x0a6f,
+ 0x5e38, 0x0a6c,
+ 0x5e3d, 0x0c38,
+ 0x5e3e, 0x1ecc,
+ 0x5e40, 0x0c39,
+ 0x5e41, 0x212e,
+ 0x5e42, 0x43a0,
+ 0x5e43, 0x0c3a,
+ 0x5e44, 0x212d,
+ 0x5e45, 0x0c37,
+ 0x5e48, 0x3a2c,
+ 0x5e4a, 0x23c9,
+ 0x5e4b, 0x23cb,
+ 0x5e4c, 0x0dff,
+ 0x5e4d, 0x23ca,
+ 0x5e4e, 0x23c8,
+ 0x5e4f, 0x23c7,
+ 0x5e53, 0x2674,
+ 0x5e54, 0x0fc9,
+ 0x5e55, 0x0fc7,
+ 0x5e57, 0x0fc8,
+ 0x5e58, 0x2672,
+ 0x5e5b, 0x0fc5,
+ 0x5e5c, 0x28c7,
+ 0x5e5d, 0x28c5,
+ 0x5e5e, 0x3a2b,
+ 0x5e5f, 0x1139,
+ 0x5e60, 0x28c6,
+ 0x5e61, 0x113a,
+ 0x5e62, 0x1138,
+ 0x5e63, 0x0fc6,
+ 0x5e66, 0x2b38,
+ 0x5e67, 0x2b36,
+ 0x5e69, 0x28c4,
+ 0x5e6a, 0x2d5d,
+ 0x5e6b, 0x13cd,
+ 0x5e6c, 0x2d5c,
+ 0x5e6d, 0x2f1c,
+ 0x5e6f, 0x2b39,
+ 0x5e70, 0x308d,
+ 0x5e72, 0x028d,
+ 0x5e73, 0x033b,
+ 0x5e74, 0x03cb,
+ 0x5e75, 0x17e4,
+ 0x5e76, 0x03ca,
+ 0x5e78, 0x05b1,
+ 0x5e79, 0x0e00,
+ 0x5e7a, 0x0227,
+ 0x5e7b, 0x02cc,
+ 0x5e7c, 0x033c,
+ 0x5e7d, 0x0711,
+ 0x5e7e, 0x0c3b,
+ 0x5e7f, 0x0228,
+ 0x5e80, 0x17a5,
+ 0x5e82, 0x17a6,
+ 0x5e83, 0x4108,
+ 0x5e84, 0x17e5,
+ 0x5e86, 0x4552,
+ 0x5e87, 0x0490,
+ 0x5e88, 0x1877,
+ 0x5e89, 0x1875,
+ 0x5e8a, 0x0491,
+ 0x5e8b, 0x1874,
+ 0x5e8c, 0x1876,
+ 0x5e8d, 0x1878,
+ 0x5e8f, 0x048f,
+ 0x5e95, 0x05b5,
+ 0x5e97, 0x05b3,
+ 0x5e9a, 0x05b2,
+ 0x5e9b, 0x1ad2,
+ 0x5e9c, 0x05b4,
+ 0x5ea0, 0x0712,
+ 0x5ea2, 0x1ad1,
+ 0x5ea3, 0x1ad3,
+ 0x5ea4, 0x1ad0,
+ 0x5ea5, 0x1ad4,
+ 0x5ea6, 0x0713,
+ 0x5ea7, 0x08ad,
+ 0x5ea8, 0x1c88,
+ 0x5eaa, 0x1c8a,
+ 0x5eab, 0x08ab,
+ 0x5eac, 0x1c8b,
+ 0x5ead, 0x08ac,
+ 0x5eae, 0x1c89,
+ 0x5eb0, 0x1acf,
+ 0x5eb1, 0x1ece,
+ 0x5eb2, 0x1ed1,
+ 0x5eb4, 0x1ecf,
+ 0x5eb5, 0x0a73,
+ 0x5eb6, 0x0a72,
+ 0x5eb7, 0x0a70,
+ 0x5eb9, 0x1ed0,
+ 0x5ebd, 0x43bd,
+ 0x5ebe, 0x0a74,
+ 0x5ec1, 0x0c3d,
+ 0x5ec4, 0x0c3f,
+ 0x5ec5, 0x23cc,
+ 0x5ec6, 0x23ce,
+ 0x5ec7, 0x23d0,
+ 0x5ec8, 0x0e02,
+ 0x5ec9, 0x0e01,
+ 0x5eca, 0x0c3c,
+ 0x5ecb, 0x23cf,
+ 0x5ecc, 0x23cd,
+ 0x5ecd, 0x3a30,
+ 0x5ece, 0x2678,
+ 0x5ed0, 0x413d,
+ 0x5ed1, 0x2676,
+ 0x5ed2, 0x267c,
+ 0x5ed3, 0x0fca,
+ 0x5ed4, 0x267d,
+ 0x5ed5, 0x267a,
+ 0x5ed6, 0x0fcb,
+ 0x5ed7, 0x2677,
+ 0x5ed8, 0x2675,
+ 0x5ed9, 0x267b,
+ 0x5eda, 0x113c,
+ 0x5edb, 0x28c9,
+ 0x5edc, 0x2679,
+ 0x5edd, 0x113e,
+ 0x5ede, 0x28ca,
+ 0x5edf, 0x113d,
+ 0x5ee0, 0x1140,
+ 0x5ee1, 0x28cb,
+ 0x5ee2, 0x113b,
+ 0x5ee3, 0x113f,
+ 0x5ee5, 0x2b3e,
+ 0x5ee6, 0x2b3c,
+ 0x5ee7, 0x2b3b,
+ 0x5ee8, 0x2b3d,
+ 0x5ee9, 0x2b3a,
+ 0x5eec, 0x157d,
+ 0x5eee, 0x31cf,
+ 0x5ef1, 0x32d0,
+ 0x5ef2, 0x3380,
+ 0x5ef3, 0x1742,
+ 0x5ef4, 0x0229,
+ 0x5ef6, 0x05b7,
+ 0x5ef7, 0x0492,
+ 0x5ef8, 0x386f,
+ 0x5ef9, 0x4143,
+ 0x5efa, 0x0714,
+ 0x5efb, 0x4144,
+ 0x5efc, 0x4146,
+ 0x5efe, 0x028e,
+ 0x5eff, 0x02cd,
+ 0x5f01, 0x033d,
+ 0x5f02, 0x17e6,
+ 0x5f04, 0x0493,
+ 0x5f05, 0x1879,
+ 0x5f07, 0x1ad5,
+ 0x5f08, 0x0715,
+ 0x5f0a, 0x0fcc,
+ 0x5f0b, 0x028f,
+ 0x5f0c, 0x3a3e,
+ 0x5f0d, 0x4149,
+ 0x5f0e, 0x3a3f,
+ 0x5f0f, 0x03cc,
+ 0x5f12, 0x0e03,
+ 0x5f13, 0x0290,
+ 0x5f14, 0x02ce,
+ 0x5f17, 0x033f,
+ 0x5f18, 0x033e,
+ 0x5f1a, 0x17e7,
+ 0x5f1b, 0x03cd,
+ 0x5f1d, 0x187a,
+ 0x5f1f, 0x0494,
+ 0x5f22, 0x1973,
+ 0x5f25, 0x4630,
+ 0x5f26, 0x05b8,
+ 0x5f28, 0x1972,
+ 0x5f29, 0x05ba,
+ 0x5f2d, 0x0716,
+ 0x5f2e, 0x1ad6,
+ 0x5f30, 0x1c8d,
+ 0x5f31, 0x08ae,
+ 0x5f33, 0x1c8c,
+ 0x5f35, 0x0a75,
+ 0x5f36, 0x1ed3,
+ 0x5f37, 0x0a76,
+ 0x5f38, 0x1ed4,
+ 0x5f3a, 0x414e,
+ 0x5f3c, 0x0c40,
+ 0x5f40, 0x23d1,
+ 0x5f43, 0x267f,
+ 0x5f44, 0x267e,
+ 0x5f46, 0x0fcd,
+ 0x5f48, 0x1141,
+ 0x5f49, 0x28cc,
+ 0x5f4a, 0x12ad,
+ 0x5f4b, 0x2b3f,
+ 0x5f4c, 0x13ce,
+ 0x5f4d, 0x3ba5,
+ 0x5f4e, 0x16c3,
+ 0x5f4f, 0x3416,
+ 0x5f50, 0x022a,
+ 0x5f51, 0x44e9,
+ 0x5f54, 0x1976,
+ 0x5f56, 0x1ad7,
+ 0x5f57, 0x0a77,
+ 0x5f58, 0x212f,
+ 0x5f59, 0x0e04,
+ 0x5f5c, 0x3d5a,
+ 0x5f5d, 0x14cf,
+ 0x5f61, 0x022b,
+ 0x5f62, 0x0496,
+ 0x5f63, 0x4152,
+ 0x5f64, 0x0495,
+ 0x5f65, 0x0717,
+ 0x5f67, 0x1c8e,
+ 0x5f69, 0x0a79,
+ 0x5f6a, 0x0b89,
+ 0x5f6b, 0x0a7a,
+ 0x5f6c, 0x0a78,
+ 0x5f6d, 0x0c41,
+ 0x5f6f, 0x2680,
+ 0x5f70, 0x0fce,
+ 0x5f71, 0x1142,
+ 0x5f72, 0x4154,
+ 0x5f73, 0x1777,
+ 0x5f74, 0x17e8,
+ 0x5f76, 0x187c,
+ 0x5f77, 0x0497,
+ 0x5f78, 0x187b,
+ 0x5f79, 0x0498,
+ 0x5f7b, 0x4058,
+ 0x5f7c, 0x05be,
+ 0x5f7d, 0x1979,
+ 0x5f7e, 0x1978,
+ 0x5f7f, 0x05bd,
+ 0x5f80, 0x05bb,
+ 0x5f82, 0x1977,
+ 0x5f83, 0x4631,
+ 0x5f85, 0x0719,
+ 0x5f86, 0x1ad8,
+ 0x5f87, 0x071c,
+ 0x5f88, 0x0718,
+ 0x5f89, 0x071e,
+ 0x5f8a, 0x071a,
+ 0x5f8c, 0x071d,
+ 0x5f90, 0x08b1,
+ 0x5f91, 0x08b0,
+ 0x5f92, 0x08af,
+ 0x5f96, 0x1ed6,
+ 0x5f97, 0x0a7b,
+ 0x5f98, 0x0a7e,
+ 0x5f99, 0x0a7c,
+ 0x5f9b, 0x1ed5,
+ 0x5f9c, 0x0a81,
+ 0x5f9e, 0x0a7d,
+ 0x5f9f, 0x1ed7,
+ 0x5fa0, 0x0a80,
+ 0x5fa1, 0x0a7f,
+ 0x5fa4, 0x402c,
+ 0x5fa5, 0x2131,
+ 0x5fa6, 0x2130,
+ 0x5fa7, 0x4157,
+ 0x5fa8, 0x0c44,
+ 0x5fa9, 0x0c42,
+ 0x5fab, 0x2132,
+ 0x5fac, 0x0e05,
+ 0x5fad, 0x23d3,
+ 0x5fae, 0x0e06,
+ 0x5faf, 0x23d2,
+ 0x5fb1, 0x3d98,
+ 0x5fb2, 0x28cd,
+ 0x5fb5, 0x1144,
+ 0x5fb6, 0x2681,
+ 0x5fb7, 0x1143,
+ 0x5fb9, 0x0fcf,
+ 0x5fba, 0x3f9f,
+ 0x5fbb, 0x2b41,
+ 0x5fbc, 0x2b40,
+ 0x5fbd, 0x13cf,
+ 0x5fbe, 0x2d5e,
+ 0x5fbf, 0x308e,
+ 0x5fc0, 0x31d1,
+ 0x5fc3, 0x02d0,
+ 0x5fc4, 0x44ea,
+ 0x5fc5, 0x0340,
+ 0x5fc9, 0x17a7,
+ 0x5fcc, 0x049a,
+ 0x5fcd, 0x049c,
+ 0x5fcf, 0x17eb,
+ 0x5fd0, 0x187f,
+ 0x5fd1, 0x187e,
+ 0x5fd2, 0x187d,
+ 0x5fd4, 0x17ea,
+ 0x5fd5, 0x17e9,
+ 0x5fd6, 0x03cf,
+ 0x5fd7, 0x049b,
+ 0x5fd8, 0x0499,
+ 0x5fd9, 0x03ce,
+ 0x5fdb, 0x3a4a,
+ 0x5fdd, 0x05bf,
+ 0x5fde, 0x197a,
+ 0x5fdf, 0x41af,
+ 0x5fe0, 0x05c0,
+ 0x5fe1, 0x1884,
+ 0x5fe3, 0x1886,
+ 0x5fe4, 0x1885,
+ 0x5fe5, 0x197b,
+ 0x5fe8, 0x1881,
+ 0x5fea, 0x04a0,
+ 0x5feb, 0x049e,
+ 0x5fed, 0x1880,
+ 0x5fee, 0x1882,
+ 0x5fef, 0x1888,
+ 0x5ff1, 0x049d,
+ 0x5ff3, 0x1883,
+ 0x5ff4, 0x188c,
+ 0x5ff5, 0x05c2,
+ 0x5ff7, 0x1889,
+ 0x5ff8, 0x049f,
+ 0x5ffa, 0x1887,
+ 0x5ffb, 0x188a,
+ 0x5ffd, 0x05c1,
+ 0x5fff, 0x05c3,
+ 0x6000, 0x188b,
+ 0x6009, 0x198f,
+ 0x600a, 0x1982,
+ 0x600b, 0x1980,
+ 0x600c, 0x198e,
+ 0x600d, 0x1989,
+ 0x600e, 0x0723,
+ 0x600f, 0x05c4,
+ 0x6010, 0x198a,
+ 0x6011, 0x198d,
+ 0x6012, 0x071f,
+ 0x6013, 0x198c,
+ 0x6014, 0x05c5,
+ 0x6015, 0x05ca,
+ 0x6016, 0x05c8,
+ 0x6017, 0x1983,
+ 0x6019, 0x197e,
+ 0x601a, 0x1985,
+ 0x601b, 0x05cf,
+ 0x601c, 0x1990,
+ 0x601d, 0x0720,
+ 0x601e, 0x1986,
+ 0x6020, 0x0721,
+ 0x6021, 0x05cb,
+ 0x6022, 0x1988,
+ 0x6023, 0x4185,
+ 0x6024, 0x1ae7,
+ 0x6025, 0x0722,
+ 0x6026, 0x197d,
+ 0x6027, 0x05cc,
+ 0x6028, 0x0724,
+ 0x6029, 0x05cd,
+ 0x602a, 0x05c9,
+ 0x602b, 0x05ce,
+ 0x602c, 0x1987,
+ 0x602d, 0x197c,
+ 0x602e, 0x198b,
+ 0x602f, 0x05c6,
+ 0x6031, 0x4161,
+ 0x6032, 0x197f,
+ 0x6033, 0x1984,
+ 0x6034, 0x1981,
+ 0x6035, 0x05c7,
+ 0x6037, 0x1ad9,
+ 0x6039, 0x1ada,
+ 0x603b, 0x4553,
+ 0x6040, 0x1ae4,
+ 0x6041, 0x1c92,
+ 0x6042, 0x1ae5,
+ 0x6043, 0x072a,
+ 0x6044, 0x1ae8,
+ 0x6045, 0x1ade,
+ 0x6046, 0x0729,
+ 0x6047, 0x1ae0,
+ 0x6049, 0x1ae1,
+ 0x604a, 0x4074,
+ 0x604c, 0x1ae3,
+ 0x604d, 0x0725,
+ 0x6050, 0x08b5,
+ 0x6052, 0x36ec,
+ 0x6053, 0x1adf,
+ 0x6054, 0x1adb,
+ 0x6055, 0x08b6,
+ 0x6058, 0x1ae9,
+ 0x6059, 0x08b2,
+ 0x605a, 0x1c90,
+ 0x605b, 0x1ae2,
+ 0x605d, 0x1c8f,
+ 0x605e, 0x1add,
+ 0x605f, 0x1ae6,
+ 0x6062, 0x0728,
+ 0x6063, 0x08b3,
+ 0x6064, 0x072e,
+ 0x6065, 0x08b4,
+ 0x6066, 0x1aea,
+ 0x6067, 0x1c91,
+ 0x6068, 0x0727,
+ 0x6069, 0x08b8,
+ 0x606a, 0x072d,
+ 0x606b, 0x072c,
+ 0x606c, 0x072b,
+ 0x606d, 0x08b7,
+ 0x606e, 0x1aeb,
+ 0x606f, 0x08b9,
+ 0x6070, 0x0726,
+ 0x6072, 0x1adc,
+ 0x6075, 0x3a56,
+ 0x6077, 0x4005,
+ 0x607e, 0x3a47,
+ 0x607f, 0x0a82,
+ 0x6080, 0x1c95,
+ 0x6081, 0x1c97,
+ 0x6083, 0x1c99,
+ 0x6084, 0x08ba,
+ 0x6085, 0x08c0,
+ 0x6086, 0x1eda,
+ 0x6087, 0x1c9d,
+ 0x6088, 0x1c94,
+ 0x6089, 0x0a84,
+ 0x608a, 0x1ed8,
+ 0x608c, 0x08bf,
+ 0x608d, 0x08bd,
+ 0x608e, 0x1c9f,
+ 0x6090, 0x1ed9,
+ 0x6092, 0x1c96,
+ 0x6094, 0x08be,
+ 0x6095, 0x1c9a,
+ 0x6096, 0x08c1,
+ 0x6097, 0x1c9c,
+ 0x609a, 0x08bc,
+ 0x609b, 0x1c9b,
+ 0x609c, 0x1c9e,
+ 0x609d, 0x1c98,
+ 0x609e, 0x416a,
+ 0x609f, 0x08bb,
+ 0x60a0, 0x0a85,
+ 0x60a2, 0x1c93,
+ 0x60a3, 0x0a83,
+ 0x60a4, 0x4001,
+ 0x60a7, 0x3adc,
+ 0x60a8, 0x0a86,
+ 0x60b0, 0x1edc,
+ 0x60b1, 0x1ee5,
+ 0x60b2, 0x0c47,
+ 0x60b3, 0x416c,
+ 0x60b4, 0x0a88,
+ 0x60b5, 0x0a8d,
+ 0x60b6, 0x0c48,
+ 0x60b7, 0x1ee7,
+ 0x60b8, 0x0a94,
+ 0x60b9, 0x2134,
+ 0x60ba, 0x1edd,
+ 0x60bb, 0x0a8c,
+ 0x60bc, 0x0a8f,
+ 0x60bd, 0x0a8a,
+ 0x60be, 0x1edb,
+ 0x60bf, 0x1ee9,
+ 0x60c0, 0x1eec,
+ 0x60c1, 0x2143,
+ 0x60c3, 0x1eea,
+ 0x60c4, 0x2138,
+ 0x60c5, 0x0a8b,
+ 0x60c6, 0x0a92,
+ 0x60c7, 0x0a96,
+ 0x60c8, 0x1ee4,
+ 0x60c9, 0x2133,
+ 0x60ca, 0x1ee8,
+ 0x60cb, 0x0a87,
+ 0x60cc, 0x2135,
+ 0x60cd, 0x1eeb,
+ 0x60ce, 0x2137,
+ 0x60cf, 0x1ee0,
+ 0x60d1, 0x0c45,
+ 0x60d3, 0x1ede,
+ 0x60d5, 0x0a91,
+ 0x60d7, 0x4635,
+ 0x60d8, 0x0a90,
+ 0x60d9, 0x1ee2,
+ 0x60da, 0x0a95,
+ 0x60db, 0x1ee6,
+ 0x60dc, 0x0a8e,
+ 0x60dd, 0x1ee3,
+ 0x60de, 0x3dcc,
+ 0x60df, 0x0a93,
+ 0x60e0, 0x0c49,
+ 0x60e1, 0x0c46,
+ 0x60e2, 0x2136,
+ 0x60e3, 0x3d75,
+ 0x60e4, 0x1ee1,
+ 0x60e6, 0x0a89,
+ 0x60e7, 0x3d84,
+ 0x60e8, 0x3d7b,
+ 0x60e9, 0x4009,
+ 0x60f0, 0x0c4e,
+ 0x60f1, 0x0c52,
+ 0x60f2, 0x213a,
+ 0x60f3, 0x0e0b,
+ 0x60f4, 0x0c50,
+ 0x60f5, 0x213e,
+ 0x60f6, 0x0c54,
+ 0x60f7, 0x23d4,
+ 0x60f8, 0x2140,
+ 0x60f9, 0x0e0d,
+ 0x60fa, 0x0c4c,
+ 0x60fb, 0x0c4f,
+ 0x60fc, 0x2141,
+ 0x60fd, 0x3fa8,
+ 0x60fe, 0x2142,
+ 0x60ff, 0x2148,
+ 0x6100, 0x0c56,
+ 0x6101, 0x0e0e,
+ 0x6103, 0x2144,
+ 0x6104, 0x2149,
+ 0x6105, 0x213d,
+ 0x6106, 0x0e18,
+ 0x6107, 0x3c35,
+ 0x6108, 0x0e0f,
+ 0x6109, 0x0c55,
+ 0x610a, 0x213b,
+ 0x610b, 0x214a,
+ 0x610c, 0x3c87,
+ 0x610d, 0x0e17,
+ 0x610e, 0x0c53,
+ 0x610f, 0x0e08,
+ 0x6110, 0x2147,
+ 0x6112, 0x0c57,
+ 0x6113, 0x213f,
+ 0x6114, 0x2139,
+ 0x6115, 0x0c4d,
+ 0x6116, 0x213c,
+ 0x6118, 0x2145,
+ 0x6119, 0x3ef6,
+ 0x611a, 0x0e07,
+ 0x611b, 0x0e0c,
+ 0x611c, 0x0c4a,
+ 0x611d, 0x2146,
+ 0x611f, 0x0e0a,
+ 0x6123, 0x0c4b,
+ 0x6127, 0x0e16,
+ 0x6128, 0x2683,
+ 0x6129, 0x23df,
+ 0x612b, 0x23d7,
+ 0x612c, 0x2682,
+ 0x612e, 0x23db,
+ 0x612f, 0x23dd,
+ 0x6130, 0x3f37,
+ 0x6132, 0x23da,
+ 0x6134, 0x0e15,
+ 0x6136, 0x23d9,
+ 0x6137, 0x0e19,
+ 0x613b, 0x2692,
+ 0x613d, 0x4636,
+ 0x613e, 0x0e14,
+ 0x613f, 0x0fd1,
+ 0x6140, 0x23e0,
+ 0x6141, 0x2684,
+ 0x6142, 0x4174,
+ 0x6144, 0x0e12,
+ 0x6145, 0x23d8,
+ 0x6146, 0x23dc,
+ 0x6147, 0x0fd0,
+ 0x6148, 0x0e09,
+ 0x6149, 0x23d5,
+ 0x614b, 0x0fd2,
+ 0x614c, 0x0e11,
+ 0x614d, 0x0e13,
+ 0x614e, 0x0e10,
+ 0x614f, 0x23de,
+ 0x6150, 0x3c32,
+ 0x6152, 0x2688,
+ 0x6154, 0x268e,
+ 0x6155, 0x1149,
+ 0x6156, 0x2695,
+ 0x6158, 0x0fd8,
+ 0x6159, 0x3fba,
+ 0x615a, 0x0fd7,
+ 0x615b, 0x2690,
+ 0x615c, 0x4186,
+ 0x615d, 0x1148,
+ 0x615e, 0x2685,
+ 0x615f, 0x0fd6,
+ 0x6160, 0x494c,
+ 0x6161, 0x2694,
+ 0x6162, 0x0fd4,
+ 0x6164, 0x4173,
+ 0x6165, 0x2691,
+ 0x6166, 0x28de,
+ 0x6167, 0x1146,
+ 0x6168, 0x0c51,
+ 0x616a, 0x2693,
+ 0x616b, 0x114d,
+ 0x616c, 0x268b,
+ 0x616e, 0x1147,
+ 0x616f, 0x3fc0,
+ 0x6170, 0x114c,
+ 0x6171, 0x2686,
+ 0x6172, 0x268a,
+ 0x6173, 0x2687,
+ 0x6174, 0x268d,
+ 0x6175, 0x0fd9,
+ 0x6176, 0x1145,
+ 0x6177, 0x0fd3,
+ 0x6179, 0x28d0,
+ 0x617a, 0x268f,
+ 0x617c, 0x114b,
+ 0x617d, 0x3fbd,
+ 0x617e, 0x114e,
+ 0x6180, 0x268c,
+ 0x6181, 0x4177,
+ 0x6182, 0x114a,
+ 0x6183, 0x28cf,
+ 0x6187, 0x417a,
+ 0x6189, 0x28d4,
+ 0x618a, 0x12b1,
+ 0x618b, 0x28ce,
+ 0x618c, 0x2b4d,
+ 0x618d, 0x28dd,
+ 0x618e, 0x1152,
+ 0x6190, 0x1150,
+ 0x6191, 0x12af,
+ 0x6192, 0x28da,
+ 0x6193, 0x28d6,
+ 0x6194, 0x1156,
+ 0x6195, 0x3de0,
+ 0x6196, 0x2b44,
+ 0x6198, 0x3a55,
+ 0x6199, 0x3a54,
+ 0x619a, 0x1154,
+ 0x619b, 0x28d5,
+ 0x619c, 0x4002,
+ 0x619d, 0x2b42,
+ 0x619f, 0x28d9,
+ 0x61a1, 0x28dc,
+ 0x61a2, 0x28d3,
+ 0x61a4, 0x1155,
+ 0x61a7, 0x114f,
+ 0x61a8, 0x2b43,
+ 0x61a9, 0x12b0,
+ 0x61aa, 0x28db,
+ 0x61ab, 0x1151,
+ 0x61ac, 0x1153,
+ 0x61ad, 0x28d8,
+ 0x61ae, 0x1157,
+ 0x61af, 0x28d7,
+ 0x61b0, 0x28d2,
+ 0x61b1, 0x28d1,
+ 0x61b2, 0x12ae,
+ 0x61b3, 0x28df,
+ 0x61b4, 0x2b46,
+ 0x61b5, 0x2d60,
+ 0x61b6, 0x12b3,
+ 0x61b7, 0x4639,
+ 0x61b8, 0x2b4c,
+ 0x61b9, 0x43bf,
+ 0x61ba, 0x2b4a,
+ 0x61bc, 0x2d61,
+ 0x61be, 0x12b4,
+ 0x61bf, 0x2b4b,
+ 0x61c0, 0x3a50,
+ 0x61c1, 0x2b48,
+ 0x61c2, 0x13d1,
+ 0x61c3, 0x2d5f,
+ 0x61c5, 0x2b45,
+ 0x61c6, 0x2b47,
+ 0x61c7, 0x13d2,
+ 0x61c8, 0x12b6,
+ 0x61c9, 0x13d0,
+ 0x61ca, 0x12b5,
+ 0x61cb, 0x13d4,
+ 0x61cc, 0x2b49,
+ 0x61cd, 0x12b2,
+ 0x61cf, 0x463a,
+ 0x61d0, 0x4181,
+ 0x61d3, 0x417e,
+ 0x61d6, 0x2f26,
+ 0x61d8, 0x2f1e,
+ 0x61da, 0x38b1,
+ 0x61de, 0x2d67,
+ 0x61df, 0x2f1f,
+ 0x61e0, 0x2d63,
+ 0x61e2, 0x3fc5,
+ 0x61e3, 0x14d0,
+ 0x61e4, 0x2d65,
+ 0x61e5, 0x2d64,
+ 0x61e6, 0x13d3,
+ 0x61e7, 0x2d62,
+ 0x61e8, 0x2d66,
+ 0x61e9, 0x2f27,
+ 0x61ea, 0x2f23,
+ 0x61eb, 0x2f25,
+ 0x61ed, 0x2f20,
+ 0x61f0, 0x2f24,
+ 0x61f1, 0x2f22,
+ 0x61f2, 0x157e,
+ 0x61f5, 0x1581,
+ 0x61f6, 0x1580,
+ 0x61f7, 0x157f,
+ 0x61f8, 0x1614,
+ 0x61f9, 0x31d3,
+ 0x61fa, 0x1615,
+ 0x61fb, 0x308f,
+ 0x61fc, 0x1670,
+ 0x61fd, 0x32d1,
+ 0x61fe, 0x1671,
+ 0x61ff, 0x16c4,
+ 0x6200, 0x16f8,
+ 0x6201, 0x3417,
+ 0x6203, 0x3418,
+ 0x6207, 0x3533,
+ 0x6208, 0x02d1,
+ 0x6209, 0x17a8,
+ 0x620a, 0x0341,
+ 0x620c, 0x03d1,
+ 0x620e, 0x03d0,
+ 0x6210, 0x03d3,
+ 0x6211, 0x04a2,
+ 0x6212, 0x04a1,
+ 0x6214, 0x1991,
+ 0x6215, 0x05d1,
+ 0x6216, 0x05d0,
+ 0x6219, 0x1ca0,
+ 0x621a, 0x0a97,
+ 0x621f, 0x0c58,
+ 0x6220, 0x23e1,
+ 0x6221, 0x0e1a,
+ 0x6223, 0x23e3,
+ 0x6224, 0x23e5,
+ 0x6225, 0x23e4,
+ 0x6227, 0x2697,
+ 0x6229, 0x2696,
+ 0x622a, 0x0fda,
+ 0x622b, 0x2698,
+ 0x622c, 0x463c,
+ 0x622d, 0x28e0,
+ 0x622e, 0x1158,
+ 0x6230, 0x12b7,
+ 0x6232, 0x13d5,
+ 0x6233, 0x14d1,
+ 0x6234, 0x13d6,
+ 0x6236, 0x02d2,
+ 0x6237, 0x451a,
+ 0x6239, 0x3fc2,
+ 0x623a, 0x188d,
+ 0x623d, 0x1992,
+ 0x623e, 0x05d3,
+ 0x623f, 0x05d2,
+ 0x6240, 0x05d4,
+ 0x6241, 0x072f,
+ 0x6242, 0x1aec,
+ 0x6246, 0x1ca1,
+ 0x6247, 0x08c2,
+ 0x6248, 0x0a99,
+ 0x6249, 0x0c59,
+ 0x624a, 0x214b,
+ 0x624b, 0x02d3,
+ 0x624c, 0x44ec,
+ 0x624d, 0x0291,
+ 0x624e, 0x02d4,
+ 0x6250, 0x17a9,
+ 0x6251, 0x0345,
+ 0x6252, 0x0344,
+ 0x6253, 0x0342,
+ 0x6258, 0x03d6,
+ 0x6259, 0x17f2,
+ 0x625a, 0x17f4,
+ 0x625b, 0x03d5,
+ 0x625c, 0x17ec,
+ 0x625e, 0x17ed,
+ 0x6260, 0x17f3,
+ 0x6261, 0x17ef,
+ 0x6262, 0x17f1,
+ 0x6263, 0x03d4,
+ 0x6264, 0x17ee,
+ 0x6265, 0x17f5,
+ 0x6266, 0x17f0,
+ 0x6268, 0x3f15,
+ 0x626d, 0x04a9,
+ 0x626e, 0x04b2,
+ 0x626f, 0x04b0,
+ 0x6270, 0x1897,
+ 0x6271, 0x1894,
+ 0x6272, 0x189c,
+ 0x6273, 0x04ae,
+ 0x6274, 0x189d,
+ 0x6276, 0x04a7,
+ 0x6277, 0x189a,
+ 0x6279, 0x04ad,
+ 0x627a, 0x1896,
+ 0x627b, 0x1895,
+ 0x627c, 0x04ab,
+ 0x627d, 0x189b,
+ 0x627e, 0x04ac,
+ 0x627f, 0x05d5,
+ 0x6280, 0x04a6,
+ 0x6281, 0x1898,
+ 0x6282, 0x3f86,
+ 0x6283, 0x188e,
+ 0x6284, 0x04a3,
+ 0x6285, 0x3f50,
+ 0x6286, 0x04b6,
+ 0x6287, 0x1893,
+ 0x6288, 0x1899,
+ 0x6289, 0x04a8,
+ 0x628a, 0x04aa,
+ 0x628c, 0x188f,
+ 0x628e, 0x1890,
+ 0x6290, 0x43c0,
+ 0x6291, 0x04b5,
+ 0x6292, 0x04af,
+ 0x6293, 0x04b4,
+ 0x6294, 0x1892,
+ 0x6295, 0x04b3,
+ 0x6296, 0x04a5,
+ 0x6297, 0x04a4,
+ 0x6298, 0x04b1,
+ 0x629d, 0x3e96,
+ 0x62a4, 0x3a69,
+ 0x62a6, 0x3fc1,
+ 0x62a8, 0x05e3,
+ 0x62a9, 0x199e,
+ 0x62aa, 0x1997,
+ 0x62ab, 0x05de,
+ 0x62ac, 0x05f1,
+ 0x62ad, 0x1993,
+ 0x62ae, 0x199a,
+ 0x62af, 0x199c,
+ 0x62b0, 0x199f,
+ 0x62b1, 0x05ec,
+ 0x62b3, 0x199b,
+ 0x62b4, 0x1994,
+ 0x62b5, 0x05ea,
+ 0x62b6, 0x1998,
+ 0x62b8, 0x19a0,
+ 0x62b9, 0x05db,
+ 0x62bb, 0x199d,
+ 0x62bc, 0x05e5,
+ 0x62bd, 0x05e4,
+ 0x62be, 0x1996,
+ 0x62bf, 0x05d9,
+ 0x62c2, 0x05da,
+ 0x62c3, 0x3d8f,
+ 0x62c4, 0x05d8,
+ 0x62c5, 0x418a,
+ 0x62c6, 0x05f0,
+ 0x62c7, 0x05e8,
+ 0x62c8, 0x05e2,
+ 0x62c9, 0x05d6,
+ 0x62ca, 0x1999,
+ 0x62cb, 0x05e1,
+ 0x62cc, 0x05d7,
+ 0x62cd, 0x05e9,
+ 0x62ce, 0x05f2,
+ 0x62cf, 0x1aee,
+ 0x62d0, 0x05e6,
+ 0x62d1, 0x1995,
+ 0x62d2, 0x05dc,
+ 0x62d3, 0x05df,
+ 0x62d5, 0x418c,
+ 0x62d6, 0x05ee,
+ 0x62d8, 0x05ed,
+ 0x62d9, 0x05e7,
+ 0x62da, 0x05eb,
+ 0x62db, 0x05dd,
+ 0x62dc, 0x0730,
+ 0x62df, 0x401c,
+ 0x62e5, 0x463d,
+ 0x62eb, 0x1af4,
+ 0x62ec, 0x073c,
+ 0x62ed, 0x0734,
+ 0x62ee, 0x0736,
+ 0x62ef, 0x073b,
+ 0x62f0, 0x1b00,
+ 0x62f1, 0x0739,
+ 0x62f2, 0x1ca2,
+ 0x62f3, 0x08c3,
+ 0x62f4, 0x073e,
+ 0x62f5, 0x1af1,
+ 0x62f6, 0x1af9,
+ 0x62f7, 0x073a,
+ 0x62f8, 0x1af8,
+ 0x62f9, 0x1af5,
+ 0x62fa, 0x1afd,
+ 0x62fb, 0x1aff,
+ 0x62fc, 0x0733,
+ 0x62fd, 0x0737,
+ 0x62fe, 0x073d,
+ 0x62ff, 0x08c5,
+ 0x6300, 0x1afa,
+ 0x6301, 0x0735,
+ 0x6302, 0x0740,
+ 0x6303, 0x1af3,
+ 0x6307, 0x0738,
+ 0x6308, 0x08c4,
+ 0x6309, 0x0732,
+ 0x630b, 0x1af0,
+ 0x630c, 0x1af7,
+ 0x630d, 0x1aef,
+ 0x630e, 0x1af2,
+ 0x630f, 0x1af6,
+ 0x6310, 0x1ca3,
+ 0x6311, 0x073f,
+ 0x6313, 0x1afb,
+ 0x6315, 0x1afe,
+ 0x6316, 0x0731,
+ 0x6318, 0x43c1,
+ 0x6328, 0x08d3,
+ 0x6329, 0x1caf,
+ 0x632a, 0x08d1,
+ 0x632c, 0x1ca5,
+ 0x632d, 0x1cb5,
+ 0x632e, 0x3edd,
+ 0x632f, 0x08c8,
+ 0x6331, 0x3a65,
+ 0x6332, 0x1eed,
+ 0x6333, 0x1cb7,
+ 0x6334, 0x1cb1,
+ 0x6335, 0x3f16,
+ 0x6336, 0x1ca8,
+ 0x6337, 0x3a63,
+ 0x6338, 0x1cba,
+ 0x6339, 0x1cab,
+ 0x633a, 0x08ce,
+ 0x633b, 0x1f04,
+ 0x633c, 0x1cae,
+ 0x633d, 0x08d0,
+ 0x633e, 0x08c7,
+ 0x6340, 0x1cbc,
+ 0x6341, 0x1cb0,
+ 0x6342, 0x08ca,
+ 0x6343, 0x1ca9,
+ 0x6344, 0x1ca6,
+ 0x6346, 0x08cb,
+ 0x6347, 0x1cb6,
+ 0x6348, 0x1cbd,
+ 0x6349, 0x08cd,
+ 0x634a, 0x1cad,
+ 0x634b, 0x1cac,
+ 0x634c, 0x08d5,
+ 0x634d, 0x08d4,
+ 0x634e, 0x08c6,
+ 0x634f, 0x08cc,
+ 0x6350, 0x08cf,
+ 0x6351, 0x1cb9,
+ 0x6354, 0x1cb3,
+ 0x6355, 0x08c9,
+ 0x6356, 0x1ca4,
+ 0x6357, 0x1cbb,
+ 0x6358, 0x1cb2,
+ 0x6359, 0x1cb4,
+ 0x635a, 0x1cb8,
+ 0x6364, 0x3fc7,
+ 0x6365, 0x1eee,
+ 0x6367, 0x0aa1,
+ 0x6368, 0x0ab5,
+ 0x6369, 0x0ab4,
+ 0x636b, 0x0aa9,
+ 0x636c, 0x418e,
+ 0x636d, 0x1f00,
+ 0x636e, 0x1efc,
+ 0x636f, 0x1ef9,
+ 0x6370, 0x1f0b,
+ 0x6371, 0x0aa4,
+ 0x6372, 0x0a9c,
+ 0x6375, 0x1efe,
+ 0x6376, 0x0c69,
+ 0x6377, 0x0aa0,
+ 0x6378, 0x1f06,
+ 0x6379, 0x4367,
+ 0x637a, 0x0ab6,
+ 0x637b, 0x0ab3,
+ 0x637c, 0x1f02,
+ 0x637d, 0x1ef1,
+ 0x637f, 0x3f4b,
+ 0x6380, 0x0ab2,
+ 0x6381, 0x1f08,
+ 0x6382, 0x1ef0,
+ 0x6383, 0x0aa7,
+ 0x6384, 0x0aab,
+ 0x6385, 0x1f07,
+ 0x6387, 0x1efa,
+ 0x6388, 0x0aac,
+ 0x6389, 0x0aa6,
+ 0x638a, 0x1eef,
+ 0x638b, 0x4188,
+ 0x638c, 0x0c5b,
+ 0x638d, 0x1f0a,
+ 0x638e, 0x1ef8,
+ 0x638f, 0x0ab1,
+ 0x6390, 0x1efb,
+ 0x6391, 0x1f09,
+ 0x6392, 0x0ab0,
+ 0x6394, 0x214c,
+ 0x6396, 0x0a9d,
+ 0x6397, 0x1ef6,
+ 0x6398, 0x0aa2,
+ 0x6399, 0x0aad,
+ 0x639b, 0x0aa8,
+ 0x639c, 0x1eff,
+ 0x639d, 0x1ef5,
+ 0x639e, 0x1ef3,
+ 0x639f, 0x1f05,
+ 0x63a0, 0x0a9a,
+ 0x63a1, 0x0aae,
+ 0x63a2, 0x0a9e,
+ 0x63a3, 0x0c5a,
+ 0x63a4, 0x1f03,
+ 0x63a5, 0x0a9f,
+ 0x63a7, 0x0a9b,
+ 0x63a8, 0x0aaa,
+ 0x63a9, 0x0aa5,
+ 0x63aa, 0x0aa3,
+ 0x63ab, 0x1ef7,
+ 0x63ac, 0x0aaf,
+ 0x63ad, 0x1ef4,
+ 0x63ae, 0x1f01,
+ 0x63af, 0x1efd,
+ 0x63b0, 0x214e,
+ 0x63b1, 0x214d,
+ 0x63b9, 0x3e9d,
+ 0x63bd, 0x1ef2,
+ 0x63be, 0x215e,
+ 0x63c0, 0x0c5d,
+ 0x63c1, 0x46a8,
+ 0x63c2, 0x2164,
+ 0x63c3, 0x2153,
+ 0x63c4, 0x2161,
+ 0x63c5, 0x23e6,
+ 0x63c6, 0x0c60,
+ 0x63c7, 0x2165,
+ 0x63c8, 0x2168,
+ 0x63c9, 0x0c5f,
+ 0x63ca, 0x2156,
+ 0x63cb, 0x2167,
+ 0x63cc, 0x2166,
+ 0x63cd, 0x0c61,
+ 0x63ce, 0x214f,
+ 0x63cf, 0x0c5c,
+ 0x63d0, 0x0c64,
+ 0x63d1, 0x3a66,
+ 0x63d2, 0x0c62,
+ 0x63d3, 0x2163,
+ 0x63d5, 0x2159,
+ 0x63d6, 0x0c66,
+ 0x63d7, 0x216a,
+ 0x63d8, 0x2162,
+ 0x63d9, 0x216b,
+ 0x63da, 0x0c6e,
+ 0x63db, 0x0c6c,
+ 0x63dc, 0x2160,
+ 0x63dd, 0x215f,
+ 0x63de, 0x3e60,
+ 0x63df, 0x215d,
+ 0x63e0, 0x2157,
+ 0x63e1, 0x0c65,
+ 0x63e2, 0x4641,
+ 0x63e3, 0x0c63,
+ 0x63e4, 0x1caa,
+ 0x63e5, 0x2150,
+ 0x63e6, 0x489f,
+ 0x63e7, 0x2404,
+ 0x63e8, 0x2151,
+ 0x63e9, 0x0c5e,
+ 0x63ea, 0x0c6b,
+ 0x63eb, 0x23e8,
+ 0x63ed, 0x0c67,
+ 0x63ef, 0x2152,
+ 0x63f0, 0x2169,
+ 0x63f1, 0x23e7,
+ 0x63f2, 0x215a,
+ 0x63f3, 0x2155,
+ 0x63f4, 0x0c6a,
+ 0x63f5, 0x215b,
+ 0x63f6, 0x2158,
+ 0x63f8, 0x4192,
+ 0x63f9, 0x0c6f,
+ 0x63fb, 0x4642,
+ 0x63fc, 0x3e9c,
+ 0x63fe, 0x3e9e,
+ 0x6406, 0x0e2a,
+ 0x6407, 0x4643,
+ 0x6409, 0x23eb,
+ 0x640a, 0x23fe,
+ 0x640b, 0x2403,
+ 0x640c, 0x23f7,
+ 0x640d, 0x0e26,
+ 0x640e, 0x2408,
+ 0x640f, 0x0e23,
+ 0x6410, 0x23e9,
+ 0x6412, 0x23ea,
+ 0x6413, 0x0e1c,
+ 0x6414, 0x0e25,
+ 0x6415, 0x23f1,
+ 0x6416, 0x0e28,
+ 0x6418, 0x23f2,
+ 0x641a, 0x23ff,
+ 0x641b, 0x2405,
+ 0x641c, 0x0e24,
+ 0x641e, 0x0e1e,
+ 0x641f, 0x23f0,
+ 0x6420, 0x23ec,
+ 0x6421, 0x2407,
+ 0x6422, 0x23f5,
+ 0x6424, 0x23ed,
+ 0x6425, 0x2401,
+ 0x6426, 0x23f8,
+ 0x6427, 0x2402,
+ 0x6428, 0x23fa,
+ 0x642a, 0x0e1f,
+ 0x642b, 0x2699,
+ 0x642c, 0x0e22,
+ 0x642d, 0x0e20,
+ 0x642e, 0x2406,
+ 0x642f, 0x23fd,
+ 0x6430, 0x23f9,
+ 0x6432, 0x45d9,
+ 0x6433, 0x23ee,
+ 0x6434, 0x0fe4,
+ 0x6435, 0x23fc,
+ 0x6436, 0x0e27,
+ 0x6437, 0x23f4,
+ 0x6438, 0x4191,
+ 0x6439, 0x23f3,
+ 0x643a, 0x419d,
+ 0x643b, 0x3a6b,
+ 0x643d, 0x0e21,
+ 0x643e, 0x0e1d,
+ 0x643f, 0x26ae,
+ 0x6440, 0x2400,
+ 0x6441, 0x23fb,
+ 0x6443, 0x23ef,
+ 0x644b, 0x26a9,
+ 0x644d, 0x269a,
+ 0x644e, 0x26a5,
+ 0x6450, 0x26ac,
+ 0x6451, 0x0fe2,
+ 0x6452, 0x0c6d,
+ 0x6453, 0x26aa,
+ 0x6454, 0x0fdd,
+ 0x6458, 0x0fdc,
+ 0x6459, 0x26b1,
+ 0x645a, 0x43c2,
+ 0x645b, 0x269b,
+ 0x645c, 0x26a8,
+ 0x645d, 0x269c,
+ 0x645e, 0x26a7,
+ 0x645f, 0x0fe0,
+ 0x6460, 0x26ab,
+ 0x6461, 0x215c,
+ 0x6465, 0x26b2,
+ 0x6466, 0x26a3,
+ 0x6467, 0x0fe3,
+ 0x6468, 0x28ee,
+ 0x6469, 0x1159,
+ 0x646b, 0x26b0,
+ 0x646c, 0x26af,
+ 0x646d, 0x0fe5,
+ 0x646e, 0x28e1,
+ 0x646f, 0x115a,
+ 0x6470, 0x28e2,
+ 0x6471, 0x3a5b,
+ 0x6472, 0x269f,
+ 0x6474, 0x269d,
+ 0x6475, 0x26a2,
+ 0x6476, 0x269e,
+ 0x6477, 0x26b3,
+ 0x6478, 0x0fdf,
+ 0x6479, 0x115b,
+ 0x647a, 0x0fe1,
+ 0x647b, 0x0fe6,
+ 0x647c, 0x436c,
+ 0x647d, 0x26a1,
+ 0x647f, 0x26ad,
+ 0x6482, 0x26a6,
+ 0x6485, 0x28e5,
+ 0x6487, 0x0fdb,
+ 0x6488, 0x115e,
+ 0x6489, 0x2b54,
+ 0x648a, 0x28ea,
+ 0x648b, 0x28e9,
+ 0x648c, 0x28eb,
+ 0x648d, 0x4323,
+ 0x648f, 0x28e8,
+ 0x6490, 0x115f,
+ 0x6491, 0x43c3,
+ 0x6492, 0x1165,
+ 0x6493, 0x1162,
+ 0x6495, 0x1163,
+ 0x6496, 0x28e3,
+ 0x6497, 0x28e6,
+ 0x6498, 0x28f0,
+ 0x6499, 0x116b,
+ 0x649a, 0x1169,
+ 0x649c, 0x28e7,
+ 0x649d, 0x2154,
+ 0x649e, 0x115c,
+ 0x649f, 0x28ed,
+ 0x64a0, 0x28e4,
+ 0x64a2, 0x116c,
+ 0x64a3, 0x28ec,
+ 0x64a4, 0x0fde,
+ 0x64a5, 0x1161,
+ 0x64a6, 0x26a4,
+ 0x64a9, 0x1164,
+ 0x64ab, 0x1168,
+ 0x64ac, 0x116a,
+ 0x64ad, 0x1167,
+ 0x64ae, 0x1166,
+ 0x64af, 0x42e1,
+ 0x64b0, 0x1160,
+ 0x64b1, 0x28ef,
+ 0x64b2, 0x115d,
+ 0x64b3, 0x116d,
+ 0x64b4, 0x4340,
+ 0x64b6, 0x3a64,
+ 0x64bb, 0x12bb,
+ 0x64bd, 0x2b53,
+ 0x64be, 0x12c5,
+ 0x64bf, 0x12c2,
+ 0x64c0, 0x4645,
+ 0x64c1, 0x12b9,
+ 0x64c2, 0x12c0,
+ 0x64c3, 0x2b55,
+ 0x64c4, 0x12be,
+ 0x64c5, 0x12b8,
+ 0x64c7, 0x12bf,
+ 0x64c9, 0x2b52,
+ 0x64ca, 0x13d8,
+ 0x64cb, 0x12ba,
+ 0x64cd, 0x12c1,
+ 0x64ce, 0x13d7,
+ 0x64cf, 0x2b51,
+ 0x64d0, 0x2b50,
+ 0x64d2, 0x12c3,
+ 0x64d3, 0x3f03,
+ 0x64d4, 0x12c4,
+ 0x64d6, 0x2b4f,
+ 0x64d7, 0x2b4e,
+ 0x64d8, 0x13d9,
+ 0x64d9, 0x2b58,
+ 0x64da, 0x12bd,
+ 0x64db, 0x2b56,
+ 0x64dd, 0x431e,
+ 0x64e0, 0x13da,
+ 0x64e1, 0x4199,
+ 0x64e2, 0x13df,
+ 0x64e3, 0x2d6a,
+ 0x64e4, 0x2d6c,
+ 0x64e5, 0x419a,
+ 0x64e6, 0x13dc,
+ 0x64e7, 0x37a8,
+ 0x64e8, 0x2d6d,
+ 0x64e9, 0x2d69,
+ 0x64ea, 0x434a,
+ 0x64eb, 0x2d6b,
+ 0x64ec, 0x13dd,
+ 0x64ed, 0x13e0,
+ 0x64ef, 0x2d68,
+ 0x64f0, 0x13db,
+ 0x64f1, 0x13de,
+ 0x64f2, 0x14d3,
+ 0x64f3, 0x2b57,
+ 0x64f4, 0x14d2,
+ 0x64f7, 0x14d8,
+ 0x64f8, 0x2f2b,
+ 0x64fa, 0x14d6,
+ 0x64fc, 0x2f2e,
+ 0x64fd, 0x2f2a,
+ 0x64fe, 0x14d4,
+ 0x64ff, 0x2f28,
+ 0x6500, 0x1582,
+ 0x6501, 0x2f2c,
+ 0x6503, 0x2f2d,
+ 0x6504, 0x2f29,
+ 0x6506, 0x14d5,
+ 0x6507, 0x3090,
+ 0x6509, 0x3093,
+ 0x650a, 0x4536,
+ 0x650c, 0x3094,
+ 0x650d, 0x3092,
+ 0x650e, 0x3095,
+ 0x650f, 0x1583,
+ 0x6510, 0x3091,
+ 0x6511, 0x3aa9,
+ 0x6513, 0x31d7,
+ 0x6514, 0x1617,
+ 0x6515, 0x31d6,
+ 0x6516, 0x31d5,
+ 0x6517, 0x31d4,
+ 0x6518, 0x1616,
+ 0x6519, 0x1618,
+ 0x651b, 0x32d2,
+ 0x651c, 0x1673,
+ 0x651d, 0x1672,
+ 0x651e, 0x4187,
+ 0x651f, 0x3ec0,
+ 0x6520, 0x3382,
+ 0x6521, 0x3381,
+ 0x6522, 0x3384,
+ 0x6523, 0x16f9,
+ 0x6524, 0x16c5,
+ 0x6525, 0x341b,
+ 0x6526, 0x3383,
+ 0x6529, 0x341a,
+ 0x652a, 0x16fb,
+ 0x652b, 0x16fa,
+ 0x652c, 0x1721,
+ 0x652d, 0x3484,
+ 0x652e, 0x34ca,
+ 0x652f, 0x02d5,
+ 0x6530, 0x3e62,
+ 0x6532, 0x216c,
+ 0x6533, 0x2b59,
+ 0x6534, 0x022c,
+ 0x6535, 0x44ed,
+ 0x6536, 0x03d7,
+ 0x6537, 0x17f6,
+ 0x6538, 0x04b9,
+ 0x6539, 0x04b7,
+ 0x653b, 0x04b8,
+ 0x653d, 0x19a1,
+ 0x653e, 0x05f3,
+ 0x653f, 0x0741,
+ 0x6541, 0x1b01,
+ 0x6543, 0x1b02,
+ 0x6545, 0x0742,
+ 0x6546, 0x1cbf,
+ 0x6548, 0x08d6,
+ 0x654a, 0x1cbe,
+ 0x654d, 0x419f,
+ 0x654f, 0x0abd,
+ 0x6551, 0x0ab9,
+ 0x6553, 0x1f0c,
+ 0x6554, 0x0ac0,
+ 0x6555, 0x0abf,
+ 0x6556, 0x0ab8,
+ 0x6557, 0x0abb,
+ 0x6558, 0x0abe,
+ 0x6559, 0x0aba,
+ 0x655c, 0x2170,
+ 0x655d, 0x0ab7,
+ 0x655e, 0x0c70,
+ 0x655f, 0x41a5,
+ 0x6562, 0x0c72,
+ 0x6564, 0x216f,
+ 0x6565, 0x2172,
+ 0x6566, 0x0c71,
+ 0x6567, 0x216d,
+ 0x6568, 0x2171,
+ 0x656a, 0x216e,
+ 0x656b, 0x3a6c,
+ 0x656c, 0x0e2b,
+ 0x656d, 0x41a4,
+ 0x656f, 0x2409,
+ 0x6572, 0x0fe7,
+ 0x6573, 0x26b4,
+ 0x6574, 0x12c6,
+ 0x6575, 0x116e,
+ 0x6576, 0x28f1,
+ 0x6577, 0x116f,
+ 0x6579, 0x28f3,
+ 0x657a, 0x28f2,
+ 0x657b, 0x28f4,
+ 0x657c, 0x2b5b,
+ 0x657f, 0x2b5a,
+ 0x6580, 0x2d6f,
+ 0x6581, 0x2d6e,
+ 0x6582, 0x13e1,
+ 0x6584, 0x3096,
+ 0x6585, 0x41a3,
+ 0x6586, 0x4648,
+ 0x6587, 0x02d6,
+ 0x6588, 0x410b,
+ 0x6589, 0x4554,
+ 0x658c, 0x2173,
+ 0x6590, 0x0c75,
+ 0x6591, 0x0c74,
+ 0x6592, 0x240a,
+ 0x6594, 0x2f2f,
+ 0x6595, 0x1674,
+ 0x6596, 0x341c,
+ 0x6597, 0x02d7,
+ 0x6599, 0x08d8,
+ 0x659b, 0x0ac2,
+ 0x659c, 0x0ac1,
+ 0x659d, 0x2174,
+ 0x659f, 0x0e2c,
+ 0x65a0, 0x26b5,
+ 0x65a1, 0x0fe8,
+ 0x65a2, 0x2b5c,
+ 0x65a4, 0x02d8,
+ 0x65a5, 0x0346,
+ 0x65a7, 0x05f4,
+ 0x65a8, 0x19a2,
+ 0x65aa, 0x1b03,
+ 0x65ab, 0x0743,
+ 0x65ac, 0x0ac3,
+ 0x65ae, 0x2176,
+ 0x65af, 0x0c76,
+ 0x65b0, 0x0e2d,
+ 0x65b2, 0x28f5,
+ 0x65b5, 0x41a7,
+ 0x65b6, 0x2d70,
+ 0x65b7, 0x14d9,
+ 0x65b8, 0x34cb,
+ 0x65b9, 0x02d9,
+ 0x65bb, 0x19a3,
+ 0x65bc, 0x05f5,
+ 0x65bd, 0x0744,
+ 0x65be, 0x3e3b,
+ 0x65bf, 0x1b04,
+ 0x65c1, 0x08d9,
+ 0x65c2, 0x1cc3,
+ 0x65c3, 0x1cc1,
+ 0x65c5, 0x08da,
+ 0x65c6, 0x1cc0,
+ 0x65cb, 0x0ac5,
+ 0x65cd, 0x1f0d,
+ 0x65ce, 0x0ac7,
+ 0x65cf, 0x0ac4,
+ 0x65d0, 0x2177,
+ 0x65d1, 0x41aa,
+ 0x65d2, 0x2178,
+ 0x65d3, 0x240b,
+ 0x65d4, 0x3ba8,
+ 0x65d6, 0x0fea,
+ 0x65d7, 0x0fe9,
+ 0x65da, 0x2d71,
+ 0x65db, 0x2f30,
+ 0x65dd, 0x3098,
+ 0x65de, 0x3097,
+ 0x65df, 0x31d8,
+ 0x65e0, 0x022d,
+ 0x65e1, 0x1789,
+ 0x65e2, 0x0745,
+ 0x65e3, 0x41ae,
+ 0x65e5, 0x02da,
+ 0x65e6, 0x0347,
+ 0x65e8, 0x03d9,
+ 0x65e9, 0x03d8,
+ 0x65ec, 0x03da,
+ 0x65ee, 0x17f8,
+ 0x65ef, 0x17f7,
+ 0x65f0, 0x189e,
+ 0x65f1, 0x04ba,
+ 0x65f2, 0x18a1,
+ 0x65f3, 0x18a0,
+ 0x65f4, 0x189f,
+ 0x65f5, 0x18a2,
+ 0x65fa, 0x05f6,
+ 0x65fb, 0x19a9,
+ 0x65fc, 0x19a5,
+ 0x65fd, 0x19ae,
+ 0x65ff, 0x464a,
+ 0x6600, 0x05fd,
+ 0x6602, 0x05fb,
+ 0x6603, 0x19aa,
+ 0x6604, 0x19a6,
+ 0x6605, 0x19ad,
+ 0x6606, 0x05fa,
+ 0x6607, 0x0601,
+ 0x6608, 0x19a8,
+ 0x6609, 0x19a4,
+ 0x660a, 0x0600,
+ 0x660b, 0x19ab,
+ 0x660c, 0x05f9,
+ 0x660d, 0x19ac,
+ 0x660e, 0x05fc,
+ 0x660f, 0x05fe,
+ 0x6610, 0x19b0,
+ 0x6611, 0x19af,
+ 0x6612, 0x19a7,
+ 0x6613, 0x05f8,
+ 0x6614, 0x05f7,
+ 0x6615, 0x05ff,
+ 0x6618, 0x41b1,
+ 0x661c, 0x1b09,
+ 0x661d, 0x1b0f,
+ 0x661e, 0x3a93,
+ 0x661f, 0x074b,
+ 0x6620, 0x0748,
+ 0x6621, 0x1b06,
+ 0x6622, 0x1b0b,
+ 0x6623, 0x4295,
+ 0x6624, 0x074e,
+ 0x6625, 0x0746,
+ 0x6626, 0x1b0a,
+ 0x6627, 0x0749,
+ 0x6628, 0x074c,
+ 0x662b, 0x1b0d,
+ 0x662d, 0x0747,
+ 0x662e, 0x1b12,
+ 0x662f, 0x074a,
+ 0x6630, 0x3a8d,
+ 0x6631, 0x074d,
+ 0x6632, 0x1b07,
+ 0x6633, 0x1b0c,
+ 0x6634, 0x1b10,
+ 0x6635, 0x1b08,
+ 0x6636, 0x1b05,
+ 0x6639, 0x1b11,
+ 0x663a, 0x1b0e,
+ 0x6641, 0x08e2,
+ 0x6642, 0x08db,
+ 0x6643, 0x08de,
+ 0x6644, 0x41b4,
+ 0x6645, 0x08e1,
+ 0x6647, 0x1cc6,
+ 0x6648, 0x3d99,
+ 0x6649, 0x08dc,
+ 0x664a, 0x1cc4,
+ 0x664b, 0x41b7,
+ 0x664c, 0x08e0,
+ 0x664f, 0x08dd,
+ 0x6651, 0x1cc7,
+ 0x6652, 0x08df,
+ 0x6653, 0x464b,
+ 0x6657, 0x409b,
+ 0x6659, 0x1f11,
+ 0x665a, 0x0ac9,
+ 0x665b, 0x1f10,
+ 0x665c, 0x1f12,
+ 0x665d, 0x0ac8,
+ 0x665e, 0x0acd,
+ 0x665f, 0x1cc5,
+ 0x6661, 0x1f0f,
+ 0x6662, 0x1f13,
+ 0x6663, 0x3a90,
+ 0x6664, 0x0aca,
+ 0x6665, 0x1f0e,
+ 0x6666, 0x0acc,
+ 0x6667, 0x41b9,
+ 0x6668, 0x0acb,
+ 0x666a, 0x217f,
+ 0x666b, 0x3a8b,
+ 0x666c, 0x217a,
+ 0x666e, 0x0c77,
+ 0x666f, 0x0c7b,
+ 0x6670, 0x0c78,
+ 0x6671, 0x217d,
+ 0x6672, 0x2180,
+ 0x6673, 0x41bb,
+ 0x6674, 0x0c79,
+ 0x6676, 0x0c7a,
+ 0x6677, 0x0c7f,
+ 0x6678, 0x2414,
+ 0x6679, 0x217e,
+ 0x667a, 0x0c7d,
+ 0x667b, 0x217b,
+ 0x667c, 0x2179,
+ 0x667d, 0x469b,
+ 0x667e, 0x0c7e,
+ 0x6680, 0x217c,
+ 0x6684, 0x0e33,
+ 0x6685, 0x4162,
+ 0x6686, 0x240c,
+ 0x6687, 0x0e30,
+ 0x6689, 0x0e2f,
+ 0x668a, 0x2411,
+ 0x668b, 0x2410,
+ 0x668c, 0x240d,
+ 0x668d, 0x0e35,
+ 0x668e, 0x3a89,
+ 0x6690, 0x240f,
+ 0x6691, 0x0c7c,
+ 0x6692, 0x464d,
+ 0x6694, 0x2413,
+ 0x6695, 0x240e,
+ 0x6696, 0x0e32,
+ 0x6697, 0x0e2e,
+ 0x6698, 0x0e34,
+ 0x6699, 0x2412,
+ 0x669a, 0x3d3d,
+ 0x669d, 0x0fed,
+ 0x669f, 0x26b8,
+ 0x66a0, 0x26b7,
+ 0x66a1, 0x26b6,
+ 0x66a2, 0x0feb,
+ 0x66a4, 0x40ba,
+ 0x66a8, 0x0fec,
+ 0x66a9, 0x28f9,
+ 0x66aa, 0x28fc,
+ 0x66ab, 0x1172,
+ 0x66ad, 0x4948,
+ 0x66ae, 0x1171,
+ 0x66af, 0x28fd,
+ 0x66b0, 0x28f8,
+ 0x66b1, 0x1174,
+ 0x66b2, 0x28fa,
+ 0x66b3, 0x40b5,
+ 0x66b4, 0x1173,
+ 0x66b5, 0x28f7,
+ 0x66b6, 0x3e13,
+ 0x66b7, 0x28fb,
+ 0x66b8, 0x12cc,
+ 0x66b9, 0x12c9,
+ 0x66ba, 0x2b65,
+ 0x66bb, 0x2b64,
+ 0x66bd, 0x2b63,
+ 0x66be, 0x2b5e,
+ 0x66bf, 0x3d9a,
+ 0x66c0, 0x2b5f,
+ 0x66c4, 0x12ca,
+ 0x66c6, 0x12c7,
+ 0x66c7, 0x12cb,
+ 0x66c8, 0x2b5d,
+ 0x66c9, 0x12c8,
+ 0x66ca, 0x2b60,
+ 0x66cc, 0x2b66,
+ 0x66cd, 0x40b8,
+ 0x66ce, 0x3a77,
+ 0x66cf, 0x2b62,
+ 0x66d2, 0x2d72,
+ 0x66d6, 0x13e4,
+ 0x66d8, 0x2f33,
+ 0x66d9, 0x13e3,
+ 0x66da, 0x2f31,
+ 0x66dc, 0x14da,
+ 0x66dd, 0x1585,
+ 0x66de, 0x3099,
+ 0x66e0, 0x1584,
+ 0x66e3, 0x31da,
+ 0x66e6, 0x1619,
+ 0x66e8, 0x31d9,
+ 0x66e9, 0x1675,
+ 0x66eb, 0x341d,
+ 0x66ec, 0x16fc,
+ 0x66ed, 0x3485,
+ 0x66f0, 0x02db,
+ 0x66f1, 0x3e84,
+ 0x66f2, 0x03dc,
+ 0x66f4, 0x04bb,
+ 0x66f6, 0x19b1,
+ 0x66f7, 0x074f,
+ 0x66f8, 0x08e3,
+ 0x66f9, 0x0ace,
+ 0x66fc, 0x0a1f,
+ 0x66fe, 0x0c80,
+ 0x6700, 0x0bf0,
+ 0x6701, 0x2181,
+ 0x6702, 0x41c4,
+ 0x6703, 0x0e36,
+ 0x6704, 0x26ba,
+ 0x6705, 0x26b9,
+ 0x6708, 0x02dc,
+ 0x6709, 0x03de,
+ 0x670a, 0x19b2,
+ 0x670b, 0x0603,
+ 0x670c, 0x3fe2,
+ 0x670d, 0x0602,
+ 0x670e, 0x3da1,
+ 0x670f, 0x1b13,
+ 0x6712, 0x1cc8,
+ 0x6714, 0x08e4,
+ 0x6716, 0x464f,
+ 0x6717, 0x08e6,
+ 0x6718, 0x1f14,
+ 0x671b, 0x0ad0,
+ 0x671d, 0x0c83,
+ 0x671e, 0x3d8b,
+ 0x671f, 0x0c82,
+ 0x6720, 0x2415,
+ 0x6721, 0x2522,
+ 0x6722, 0x26bb,
+ 0x6723, 0x2b67,
+ 0x6725, 0x379f,
+ 0x6726, 0x14db,
+ 0x6727, 0x161a,
+ 0x6728, 0x02dd,
+ 0x672a, 0x034a,
+ 0x672c, 0x0349,
+ 0x672d, 0x034c,
+ 0x672e, 0x0348,
+ 0x6731, 0x03e1,
+ 0x6733, 0x1800,
+ 0x6734, 0x03e0,
+ 0x6735, 0x03e2,
+ 0x6736, 0x3e41,
+ 0x6738, 0x17fb,
+ 0x6739, 0x17fa,
+ 0x673a, 0x17fd,
+ 0x673b, 0x17fc,
+ 0x673c, 0x17ff,
+ 0x673d, 0x03df,
+ 0x673e, 0x17f9,
+ 0x673f, 0x17fe,
+ 0x6744, 0x401b,
+ 0x6745, 0x18a3,
+ 0x6746, 0x04c5,
+ 0x6747, 0x18a4,
+ 0x6748, 0x18a8,
+ 0x6749, 0x04c4,
+ 0x674b, 0x18ac,
+ 0x674c, 0x18a7,
+ 0x674d, 0x18aa,
+ 0x674e, 0x04bd,
+ 0x6753, 0x04c7,
+ 0x6755, 0x18a6,
+ 0x6756, 0x04c2,
+ 0x6757, 0x04c8,
+ 0x6759, 0x18a5,
+ 0x675a, 0x18ab,
+ 0x675c, 0x04c1,
+ 0x675d, 0x18a9,
+ 0x675e, 0x04c3,
+ 0x675f, 0x04bc,
+ 0x6760, 0x04c6,
+ 0x6761, 0x3d66,
+ 0x6762, 0x41cb,
+ 0x6767, 0x41ca,
+ 0x676a, 0x0618,
+ 0x676c, 0x19b4,
+ 0x676d, 0x0604,
+ 0x676f, 0x060e,
+ 0x6771, 0x0607,
+ 0x6772, 0x0619,
+ 0x6773, 0x0609,
+ 0x6774, 0x19bc,
+ 0x6775, 0x0614,
+ 0x6776, 0x19b7,
+ 0x6777, 0x060a,
+ 0x6778, 0x19c6,
+ 0x677a, 0x19bf,
+ 0x677b, 0x19b8,
+ 0x677c, 0x0617,
+ 0x677d, 0x19c4,
+ 0x677e, 0x0612,
+ 0x677f, 0x0610,
+ 0x6781, 0x19c5,
+ 0x6783, 0x19c3,
+ 0x6784, 0x19bb,
+ 0x6785, 0x19b3,
+ 0x6786, 0x19ba,
+ 0x6787, 0x060b,
+ 0x6789, 0x0611,
+ 0x678b, 0x0605,
+ 0x678c, 0x19be,
+ 0x678d, 0x19bd,
+ 0x678e, 0x19b5,
+ 0x678f, 0x46c1,
+ 0x6790, 0x0613,
+ 0x6791, 0x19c1,
+ 0x6792, 0x19b6,
+ 0x6793, 0x0616,
+ 0x6794, 0x19c8,
+ 0x6795, 0x0606,
+ 0x6797, 0x060d,
+ 0x6798, 0x19b9,
+ 0x6799, 0x19c2,
+ 0x679a, 0x0615,
+ 0x679c, 0x0608,
+ 0x679d, 0x060c,
+ 0x679f, 0x19c0,
+ 0x67a0, 0x3d7a,
+ 0x67a4, 0x4651,
+ 0x67ac, 0x41e3,
+ 0x67ae, 0x1b34,
+ 0x67af, 0x0757,
+ 0x67b0, 0x0764,
+ 0x67b1, 0x41f4,
+ 0x67b2, 0x1b2f,
+ 0x67b3, 0x1b25,
+ 0x67b4, 0x075d,
+ 0x67b5, 0x1b23,
+ 0x67b6, 0x0756,
+ 0x67b7, 0x1b1e,
+ 0x67b8, 0x0760,
+ 0x67b9, 0x1b2b,
+ 0x67ba, 0x1b18,
+ 0x67bb, 0x1b1a,
+ 0x67bf, 0x37fa,
+ 0x67c0, 0x1b1d,
+ 0x67c1, 0x1b15,
+ 0x67c2, 0x1b2a,
+ 0x67c3, 0x1b3a,
+ 0x67c4, 0x075b,
+ 0x67c5, 0x1b1f,
+ 0x67c6, 0x1b31,
+ 0x67c8, 0x1b17,
+ 0x67c9, 0x1b38,
+ 0x67cb, 0x1b3c,
+ 0x67cc, 0x1b33,
+ 0x67cd, 0x1b24,
+ 0x67ce, 0x1b2c,
+ 0x67cf, 0x0761,
+ 0x67d0, 0x0754,
+ 0x67d1, 0x075c,
+ 0x67d2, 0x0768,
+ 0x67d3, 0x0751,
+ 0x67d4, 0x0753,
+ 0x67d6, 0x3b58,
+ 0x67d7, 0x41ce,
+ 0x67d8, 0x1b1c,
+ 0x67d9, 0x0765,
+ 0x67da, 0x075e,
+ 0x67db, 0x1b36,
+ 0x67dc, 0x1b19,
+ 0x67dd, 0x0767,
+ 0x67de, 0x0762,
+ 0x67df, 0x1b22,
+ 0x67e2, 0x0766,
+ 0x67e3, 0x1b29,
+ 0x67e4, 0x1b21,
+ 0x67e5, 0x075f,
+ 0x67e6, 0x1b35,
+ 0x67e7, 0x1b2d,
+ 0x67e9, 0x0759,
+ 0x67ea, 0x1b3b,
+ 0x67eb, 0x1b20,
+ 0x67ec, 0x0755,
+ 0x67ed, 0x1b32,
+ 0x67ee, 0x1b28,
+ 0x67ef, 0x075a,
+ 0x67f0, 0x1b2e,
+ 0x67f1, 0x0752,
+ 0x67f2, 0x1b16,
+ 0x67f3, 0x0763,
+ 0x67f4, 0x08f5,
+ 0x67f5, 0x0758,
+ 0x67f6, 0x1b27,
+ 0x67f7, 0x1b26,
+ 0x67f8, 0x1b1b,
+ 0x67f9, 0x3996,
+ 0x67fa, 0x1b37,
+ 0x67fc, 0x1b30,
+ 0x67fe, 0x4555,
+ 0x67ff, 0x0750,
+ 0x6800, 0x43c7,
+ 0x6801, 0x41d3,
+ 0x6802, 0x3fc8,
+ 0x6803, 0x3d6a,
+ 0x6804, 0x4556,
+ 0x680d, 0x4281,
+ 0x6810, 0x399c,
+ 0x6812, 0x1cdd,
+ 0x6813, 0x08fc,
+ 0x6814, 0x1cde,
+ 0x6816, 0x1cd2,
+ 0x6817, 0x08f1,
+ 0x6818, 0x08fd,
+ 0x681a, 0x1ccb,
+ 0x681b, 0x4072,
+ 0x681c, 0x1cd4,
+ 0x681d, 0x1cdc,
+ 0x681e, 0x46c2,
+ 0x681f, 0x1cca,
+ 0x6820, 0x1ce5,
+ 0x6821, 0x08e7,
+ 0x6822, 0x41d0,
+ 0x6825, 0x1ce4,
+ 0x6826, 0x1cdf,
+ 0x6828, 0x1ce0,
+ 0x6829, 0x08ef,
+ 0x682a, 0x08fa,
+ 0x682b, 0x1cd6,
+ 0x682d, 0x1cd7,
+ 0x682e, 0x1ce1,
+ 0x682f, 0x1cd8,
+ 0x6831, 0x1cd3,
+ 0x6832, 0x1ccd,
+ 0x6834, 0x1cdb,
+ 0x6835, 0x1cd5,
+ 0x6836, 0x3e2e,
+ 0x6837, 0x421d,
+ 0x6838, 0x08e8,
+ 0x6839, 0x08ec,
+ 0x683a, 0x1ce3,
+ 0x683b, 0x1ccf,
+ 0x683c, 0x08f8,
+ 0x683d, 0x08f4,
+ 0x683e, 0x4147,
+ 0x6840, 0x08f7,
+ 0x6841, 0x08fe,
+ 0x6842, 0x08ed,
+ 0x6843, 0x08f9,
+ 0x6844, 0x1cda,
+ 0x6845, 0x08fb,
+ 0x6846, 0x08ea,
+ 0x6847, 0x3beb,
+ 0x6848, 0x08e9,
+ 0x6849, 0x1ccc,
+ 0x684a, 0x4653,
+ 0x684b, 0x1cd0,
+ 0x684c, 0x08f2,
+ 0x684d, 0x1ce2,
+ 0x684e, 0x1cd9,
+ 0x684f, 0x1cd1,
+ 0x6850, 0x08f6,
+ 0x6851, 0x08f3,
+ 0x6853, 0x08eb,
+ 0x6854, 0x08ee,
+ 0x6855, 0x3d90,
+ 0x6856, 0x3814,
+ 0x685d, 0x41d6,
+ 0x6865, 0x4557,
+ 0x686b, 0x1f29,
+ 0x686d, 0x1f19,
+ 0x686f, 0x1f1e,
+ 0x6871, 0x1f2d,
+ 0x6872, 0x1f2a,
+ 0x6874, 0x1f23,
+ 0x6875, 0x1f22,
+ 0x6876, 0x0ad7,
+ 0x6877, 0x1f26,
+ 0x6878, 0x1f35,
+ 0x6879, 0x1f15,
+ 0x687b, 0x1f36,
+ 0x687c, 0x1f28,
+ 0x687d, 0x1f3a,
+ 0x687e, 0x1f2e,
+ 0x687f, 0x0ad6,
+ 0x6880, 0x1f2c,
+ 0x6881, 0x0ad1,
+ 0x6882, 0x0ae6,
+ 0x6883, 0x0adc,
+ 0x6884, 0x4654,
+ 0x6885, 0x0ae0,
+ 0x6886, 0x0adf,
+ 0x6887, 0x1f16,
+ 0x6888, 0x46b7,
+ 0x6889, 0x1f33,
+ 0x688a, 0x1f39,
+ 0x688b, 0x1f31,
+ 0x688c, 0x1f38,
+ 0x688f, 0x1f25,
+ 0x6890, 0x1f17,
+ 0x6891, 0x1f37,
+ 0x6892, 0x1f27,
+ 0x6893, 0x0ad4,
+ 0x6894, 0x0ae1,
+ 0x6896, 0x1f30,
+ 0x6897, 0x0ada,
+ 0x6898, 0x3aaa,
+ 0x689b, 0x1f2f,
+ 0x689c, 0x1f18,
+ 0x689d, 0x0ae2,
+ 0x689f, 0x0ae4,
+ 0x68a0, 0x1f32,
+ 0x68a1, 0x0ae5,
+ 0x68a2, 0x0ad3,
+ 0x68a3, 0x1f1f,
+ 0x68a4, 0x1f34,
+ 0x68a6, 0x40e4,
+ 0x68a7, 0x0ad9,
+ 0x68a8, 0x0ae3,
+ 0x68a9, 0x1f21,
+ 0x68aa, 0x1f2b,
+ 0x68ab, 0x1f1c,
+ 0x68ac, 0x1f20,
+ 0x68ad, 0x0ade,
+ 0x68ae, 0x1f1b,
+ 0x68af, 0x0ad2,
+ 0x68b0, 0x0adb,
+ 0x68b1, 0x0ad8,
+ 0x68b2, 0x1f24,
+ 0x68b3, 0x08f0,
+ 0x68b4, 0x2198,
+ 0x68b5, 0x0ad5,
+ 0x68b6, 0x3a9e,
+ 0x68b9, 0x3d14,
+ 0x68bd, 0x427c,
+ 0x68c3, 0x41dc,
+ 0x68c4, 0x0add,
+ 0x68c5, 0x3c2e,
+ 0x68c6, 0x219b,
+ 0x68c7, 0x21b1,
+ 0x68c8, 0x21a6,
+ 0x68c9, 0x0c97,
+ 0x68ca, 0x42eb,
+ 0x68cb, 0x0c92,
+ 0x68cc, 0x2195,
+ 0x68cd, 0x0c93,
+ 0x68ce, 0x21a5,
+ 0x68d0, 0x219e,
+ 0x68d1, 0x21ab,
+ 0x68d2, 0x0c8f,
+ 0x68d3, 0x2183,
+ 0x68d4, 0x21ad,
+ 0x68d5, 0x0c85,
+ 0x68d6, 0x218b,
+ 0x68d7, 0x0c88,
+ 0x68d8, 0x0c87,
+ 0x68da, 0x0c98,
+ 0x68dc, 0x2185,
+ 0x68dd, 0x21a7,
+ 0x68df, 0x0c8a,
+ 0x68e0, 0x0c86,
+ 0x68e1, 0x2193,
+ 0x68e3, 0x0c91,
+ 0x68e4, 0x218e,
+ 0x68e6, 0x21a9,
+ 0x68e7, 0x0c8d,
+ 0x68e8, 0x21a1,
+ 0x68e9, 0x21ae,
+ 0x68ea, 0x2188,
+ 0x68eb, 0x218d,
+ 0x68ec, 0x2187,
+ 0x68ee, 0x0c8c,
+ 0x68ef, 0x219a,
+ 0x68f0, 0x242b,
+ 0x68f1, 0x2189,
+ 0x68f2, 0x0c90,
+ 0x68f3, 0x2192,
+ 0x68f4, 0x21aa,
+ 0x68f5, 0x0c8b,
+ 0x68f6, 0x218f,
+ 0x68f7, 0x218c,
+ 0x68f8, 0x219d,
+ 0x68f9, 0x0c8e,
+ 0x68fa, 0x0c84,
+ 0x68fb, 0x0c9a,
+ 0x68fc, 0x21a0,
+ 0x68fd, 0x219f,
+ 0x6900, 0x41df,
+ 0x6901, 0x41de,
+ 0x6902, 0x42fb,
+ 0x6903, 0x429c,
+ 0x6904, 0x2184,
+ 0x6905, 0x0c89,
+ 0x6906, 0x21ac,
+ 0x6907, 0x2194,
+ 0x6908, 0x2196,
+ 0x6909, 0x4658,
+ 0x690a, 0x21a3,
+ 0x690b, 0x21a2,
+ 0x690c, 0x2182,
+ 0x690d, 0x0c94,
+ 0x690e, 0x0c96,
+ 0x690f, 0x218a,
+ 0x6910, 0x2191,
+ 0x6911, 0x2199,
+ 0x6912, 0x0c95,
+ 0x6913, 0x2190,
+ 0x6914, 0x219c,
+ 0x6915, 0x21af,
+ 0x6917, 0x21a4,
+ 0x6918, 0x3da2,
+ 0x691a, 0x3d80,
+ 0x691b, 0x37bd,
+ 0x6925, 0x21b0,
+ 0x692a, 0x2186,
+ 0x692c, 0x3f38,
+ 0x692f, 0x243f,
+ 0x6930, 0x0e3e,
+ 0x6932, 0x243d,
+ 0x6933, 0x2428,
+ 0x6934, 0x242d,
+ 0x6935, 0x2426,
+ 0x6936, 0x41e7,
+ 0x6937, 0x2439,
+ 0x6938, 0x2418,
+ 0x6939, 0x241f,
+ 0x693b, 0x2437,
+ 0x693c, 0x2441,
+ 0x693d, 0x2429,
+ 0x693e, 0x4056,
+ 0x693f, 0x241c,
+ 0x6940, 0x242f,
+ 0x6941, 0x2434,
+ 0x6942, 0x2420,
+ 0x6943, 0x4659,
+ 0x6944, 0x2431,
+ 0x6945, 0x241d,
+ 0x6946, 0x456f,
+ 0x6948, 0x2424,
+ 0x694a, 0x0e40,
+ 0x694b, 0x2438,
+ 0x694c, 0x2436,
+ 0x694e, 0x2419,
+ 0x694f, 0x243b,
+ 0x6951, 0x243c,
+ 0x6952, 0x243e,
+ 0x6953, 0x0e44,
+ 0x6954, 0x0e3c,
+ 0x6955, 0x3d86,
+ 0x6956, 0x1f1d,
+ 0x6957, 0x2421,
+ 0x6958, 0x2433,
+ 0x6959, 0x2422,
+ 0x695a, 0x0e39,
+ 0x695b, 0x0e49,
+ 0x695c, 0x243a,
+ 0x695d, 0x0e47,
+ 0x695e, 0x0e43,
+ 0x695f, 0x2417,
+ 0x6960, 0x0e3b,
+ 0x6961, 0x41e4,
+ 0x6962, 0x241a,
+ 0x6963, 0x0e48,
+ 0x6964, 0x465b,
+ 0x6965, 0x242a,
+ 0x6966, 0x2416,
+ 0x6967, 0x3d15,
+ 0x6968, 0x0e41,
+ 0x6969, 0x242e,
+ 0x696a, 0x241e,
+ 0x696b, 0x0e42,
+ 0x696c, 0x2427,
+ 0x696d, 0x0e38,
+ 0x696e, 0x0c99,
+ 0x696f, 0x2430,
+ 0x6970, 0x2197,
+ 0x6971, 0x241b,
+ 0x6972, 0x3a6d,
+ 0x6973, 0x41db,
+ 0x6974, 0x2435,
+ 0x6975, 0x0e3d,
+ 0x6976, 0x2432,
+ 0x6977, 0x0e3a,
+ 0x6978, 0x242c,
+ 0x6979, 0x0e45,
+ 0x697a, 0x2423,
+ 0x697b, 0x2440,
+ 0x6980, 0x3f3e,
+ 0x6982, 0x0e3f,
+ 0x6983, 0x24af,
+ 0x6985, 0x465d,
+ 0x6986, 0x0e46,
+ 0x698a, 0x3d74,
+ 0x698d, 0x26c9,
+ 0x698e, 0x26c7,
+ 0x6990, 0x26dd,
+ 0x6991, 0x26c5,
+ 0x6993, 0x26d7,
+ 0x6994, 0x0e37,
+ 0x6995, 0x0ff0,
+ 0x6996, 0x26c1,
+ 0x6997, 0x26dc,
+ 0x6998, 0x41e8,
+ 0x6999, 0x26c6,
+ 0x699a, 0x26d4,
+ 0x699b, 0x0ff5,
+ 0x699c, 0x0fee,
+ 0x699e, 0x26da,
+ 0x699f, 0x465c,
+ 0x69a0, 0x26bf,
+ 0x69a1, 0x26d9,
+ 0x69a2, 0x3730,
+ 0x69a3, 0x1000,
+ 0x69a4, 0x26d0,
+ 0x69a5, 0x26e0,
+ 0x69a6, 0x0ffe,
+ 0x69a7, 0x26c8,
+ 0x69a8, 0x0fef,
+ 0x69a9, 0x26ca,
+ 0x69aa, 0x26d8,
+ 0x69ab, 0x0ff8,
+ 0x69ac, 0x26c3,
+ 0x69ad, 0x0ffc,
+ 0x69ae, 0x0ff2,
+ 0x69af, 0x26cc,
+ 0x69b0, 0x26c2,
+ 0x69b1, 0x26bc,
+ 0x69b2, 0x3ff6,
+ 0x69b3, 0x26d6,
+ 0x69b4, 0x0ff9,
+ 0x69b5, 0x26df,
+ 0x69b6, 0x26bd,
+ 0x69b7, 0x0ff6,
+ 0x69b9, 0x26d2,
+ 0x69bb, 0x0ff7,
+ 0x69bc, 0x26c4,
+ 0x69bd, 0x26cf,
+ 0x69be, 0x26cb,
+ 0x69bf, 0x26cd,
+ 0x69c0, 0x3f5d,
+ 0x69c1, 0x0ff1,
+ 0x69c2, 0x26de,
+ 0x69c3, 0x0fff,
+ 0x69c4, 0x26ce,
+ 0x69c6, 0x26e1,
+ 0x69c9, 0x26be,
+ 0x69ca, 0x26d3,
+ 0x69cb, 0x0ff4,
+ 0x69cc, 0x0ffd,
+ 0x69cd, 0x0ffb,
+ 0x69ce, 0x26c0,
+ 0x69cf, 0x26d5,
+ 0x69d0, 0x0ffa,
+ 0x69d1, 0x39ef,
+ 0x69d3, 0x0ff3,
+ 0x69d4, 0x26d1,
+ 0x69d5, 0x3e3c,
+ 0x69d6, 0x465e,
+ 0x69d9, 0x26db,
+ 0x69e1, 0x41d8,
+ 0x69e2, 0x2909,
+ 0x69e4, 0x2905,
+ 0x69e5, 0x2901,
+ 0x69e6, 0x2915,
+ 0x69e7, 0x2912,
+ 0x69e8, 0x1177,
+ 0x69e9, 0x3d91,
+ 0x69eb, 0x2919,
+ 0x69ec, 0x2908,
+ 0x69ed, 0x1182,
+ 0x69ee, 0x290f,
+ 0x69f1, 0x2904,
+ 0x69f2, 0x290e,
+ 0x69f3, 0x117f,
+ 0x69f4, 0x2922,
+ 0x69f6, 0x291f,
+ 0x69f7, 0x2911,
+ 0x69f8, 0x2902,
+ 0x69f9, 0x41ed,
+ 0x69fa, 0x41c7,
+ 0x69fb, 0x2916,
+ 0x69fc, 0x2918,
+ 0x69fd, 0x117b,
+ 0x69fe, 0x290c,
+ 0x69ff, 0x2907,
+ 0x6a00, 0x28fe,
+ 0x6a01, 0x1178,
+ 0x6a02, 0x1180,
+ 0x6a03, 0x3e29,
+ 0x6a04, 0x291b,
+ 0x6a05, 0x1181,
+ 0x6a06, 0x28ff,
+ 0x6a07, 0x2921,
+ 0x6a08, 0x2914,
+ 0x6a09, 0x291a,
+ 0x6a0a, 0x117e,
+ 0x6a0b, 0x41d9,
+ 0x6a0c, 0x3d50,
+ 0x6a0d, 0x2917,
+ 0x6a0f, 0x291e,
+ 0x6a11, 0x1183,
+ 0x6a13, 0x117d,
+ 0x6a14, 0x2910,
+ 0x6a15, 0x2903,
+ 0x6a16, 0x2923,
+ 0x6a17, 0x2900,
+ 0x6a18, 0x291c,
+ 0x6a19, 0x117a,
+ 0x6a1a, 0x3d1e,
+ 0x6a1b, 0x290a,
+ 0x6a1c, 0x3b68,
+ 0x6a1d, 0x290b,
+ 0x6a1e, 0x1179,
+ 0x6a1f, 0x1176,
+ 0x6a20, 0x2906,
+ 0x6a21, 0x117c,
+ 0x6a23, 0x1175,
+ 0x6a25, 0x291d,
+ 0x6a26, 0x2920,
+ 0x6a27, 0x290d,
+ 0x6a28, 0x2b74,
+ 0x6a2b, 0x3d42,
+ 0x6a2c, 0x42ab,
+ 0x6a2d, 0x3b1f,
+ 0x6a32, 0x2b6c,
+ 0x6a33, 0x3aa4,
+ 0x6a34, 0x2b68,
+ 0x6a35, 0x12d9,
+ 0x6a38, 0x12ce,
+ 0x6a39, 0x12d3,
+ 0x6a3a, 0x12cf,
+ 0x6a3b, 0x2b76,
+ 0x6a3c, 0x2b81,
+ 0x6a3d, 0x12cd,
+ 0x6a3e, 0x2b6e,
+ 0x6a3f, 0x2b77,
+ 0x6a40, 0x2913,
+ 0x6a41, 0x2b78,
+ 0x6a44, 0x12d4,
+ 0x6a45, 0x41f0,
+ 0x6a46, 0x2b87,
+ 0x6a47, 0x12d8,
+ 0x6a48, 0x12db,
+ 0x6a49, 0x2b6a,
+ 0x6a4b, 0x12d7,
+ 0x6a4c, 0x3aab,
+ 0x6a4d, 0x2b85,
+ 0x6a4f, 0x2b7c,
+ 0x6a50, 0x2b7b,
+ 0x6a51, 0x2b73,
+ 0x6a52, 0x3aa5,
+ 0x6a53, 0x37ac,
+ 0x6a54, 0x2b7d,
+ 0x6a55, 0x2b84,
+ 0x6a56, 0x2b83,
+ 0x6a57, 0x37da,
+ 0x6a58, 0x12d2,
+ 0x6a59, 0x12d0,
+ 0x6a5a, 0x2b75,
+ 0x6a5b, 0x2b72,
+ 0x6a5d, 0x2b6f,
+ 0x6a5e, 0x2b82,
+ 0x6a5f, 0x12da,
+ 0x6a60, 0x2b80,
+ 0x6a61, 0x12d6,
+ 0x6a62, 0x12d5,
+ 0x6a64, 0x2b7a,
+ 0x6a65, 0x4660,
+ 0x6a66, 0x2b69,
+ 0x6a67, 0x2b6b,
+ 0x6a68, 0x2b6d,
+ 0x6a69, 0x2b7f,
+ 0x6a6a, 0x2b79,
+ 0x6a6b, 0x12d1,
+ 0x6a6d, 0x2b70,
+ 0x6a6f, 0x2b7e,
+ 0x6a71, 0x4662,
+ 0x6a74, 0x4661,
+ 0x6a76, 0x2b71,
+ 0x6a7a, 0x3aad,
+ 0x6a7e, 0x13ec,
+ 0x6a7f, 0x2d84,
+ 0x6a80, 0x13e5,
+ 0x6a81, 0x2d75,
+ 0x6a82, 0x4663,
+ 0x6a83, 0x2d80,
+ 0x6a84, 0x13e7,
+ 0x6a85, 0x2d87,
+ 0x6a87, 0x2d7c,
+ 0x6a89, 0x2d77,
+ 0x6a8a, 0x4136,
+ 0x6a8c, 0x2d88,
+ 0x6a8d, 0x2d73,
+ 0x6a8e, 0x2d7e,
+ 0x6a8f, 0x3c1b,
+ 0x6a90, 0x13ee,
+ 0x6a91, 0x2d83,
+ 0x6a92, 0x2d89,
+ 0x6a93, 0x2d7d,
+ 0x6a94, 0x13e6,
+ 0x6a95, 0x2d7f,
+ 0x6a96, 0x2d74,
+ 0x6a97, 0x13ed,
+ 0x6a99, 0x4665,
+ 0x6a9a, 0x2d86,
+ 0x6a9b, 0x2d79,
+ 0x6a9c, 0x13e9,
+ 0x6a9d, 0x41f2,
+ 0x6a9e, 0x2d7b,
+ 0x6a9f, 0x2d78,
+ 0x6aa0, 0x13ef,
+ 0x6aa1, 0x2d7a,
+ 0x6aa2, 0x13e8,
+ 0x6aa3, 0x13eb,
+ 0x6aa4, 0x2d82,
+ 0x6aa5, 0x2d76,
+ 0x6aa6, 0x2d85,
+ 0x6aa7, 0x37e3,
+ 0x6aa8, 0x2d81,
+ 0x6aab, 0x4667,
+ 0x6aac, 0x14dd,
+ 0x6aad, 0x2f3e,
+ 0x6aae, 0x14e2,
+ 0x6ab1, 0x3e53,
+ 0x6ab2, 0x3b4b,
+ 0x6ab3, 0x14dc,
+ 0x6ab4, 0x2f3d,
+ 0x6ab5, 0x4668,
+ 0x6ab6, 0x2f3a,
+ 0x6ab8, 0x14e0,
+ 0x6ab9, 0x2f35,
+ 0x6aba, 0x2f39,
+ 0x6abb, 0x14df,
+ 0x6abd, 0x2f36,
+ 0x6abe, 0x3aa1,
+ 0x6ac2, 0x14e1,
+ 0x6ac3, 0x14de,
+ 0x6ac5, 0x2f34,
+ 0x6ac6, 0x2f38,
+ 0x6ac7, 0x2f3c,
+ 0x6ac8, 0x41f5,
+ 0x6ac9, 0x3aa6,
+ 0x6aca, 0x3f4c,
+ 0x6acb, 0x309f,
+ 0x6acc, 0x309c,
+ 0x6acd, 0x30a5,
+ 0x6acf, 0x30a4,
+ 0x6ad0, 0x30a2,
+ 0x6ad1, 0x309d,
+ 0x6ad3, 0x1589,
+ 0x6ad4, 0x4669,
+ 0x6ad8, 0x3caa,
+ 0x6ad9, 0x309e,
+ 0x6ada, 0x1588,
+ 0x6adb, 0x13ea,
+ 0x6adc, 0x30a1,
+ 0x6add, 0x1587,
+ 0x6ade, 0x30a6,
+ 0x6adf, 0x30a0,
+ 0x6ae0, 0x309b,
+ 0x6ae1, 0x2f37,
+ 0x6ae5, 0x1586,
+ 0x6ae7, 0x309a,
+ 0x6ae8, 0x31df,
+ 0x6aea, 0x31de,
+ 0x6aeb, 0x30a3,
+ 0x6aec, 0x161b,
+ 0x6aee, 0x31e2,
+ 0x6af0, 0x31dd,
+ 0x6af1, 0x31e1,
+ 0x6af3, 0x31dc,
+ 0x6af6, 0x466a,
+ 0x6af8, 0x32d6,
+ 0x6af9, 0x31e0,
+ 0x6afa, 0x1678,
+ 0x6afb, 0x1676,
+ 0x6afc, 0x32d4,
+ 0x6b00, 0x32d7,
+ 0x6b02, 0x32d3,
+ 0x6b03, 0x32d5,
+ 0x6b04, 0x1677,
+ 0x6b05, 0x3aa7,
+ 0x6b08, 0x3386,
+ 0x6b0a, 0x16c6,
+ 0x6b0b, 0x3385,
+ 0x6b0f, 0x3420,
+ 0x6b10, 0x16fd,
+ 0x6b11, 0x341e,
+ 0x6b13, 0x3487,
+ 0x6b16, 0x1743,
+ 0x6b17, 0x34ce,
+ 0x6b18, 0x34cc,
+ 0x6b1a, 0x34cf,
+ 0x6b1d, 0x41f8,
+ 0x6b1e, 0x3534,
+ 0x6b20, 0x02de,
+ 0x6b21, 0x03e3,
+ 0x6b23, 0x061a,
+ 0x6b25, 0x19c9,
+ 0x6b28, 0x1b3d,
+ 0x6b2c, 0x1ce6,
+ 0x6b2d, 0x1ce8,
+ 0x6b2f, 0x1ce7,
+ 0x6b31, 0x1ce9,
+ 0x6b32, 0x0ae7,
+ 0x6b33, 0x1f3c,
+ 0x6b34, 0x1cea,
+ 0x6b35, 0x41fb,
+ 0x6b36, 0x1f3b,
+ 0x6b37, 0x1f3d,
+ 0x6b39, 0x21b2,
+ 0x6b3a, 0x0c9c,
+ 0x6b3b, 0x21b3,
+ 0x6b3c, 0x21b5,
+ 0x6b3d, 0x0c9d,
+ 0x6b3e, 0x0c9b,
+ 0x6b3f, 0x21b4,
+ 0x6b41, 0x2447,
+ 0x6b42, 0x2445,
+ 0x6b43, 0x2444,
+ 0x6b45, 0x2443,
+ 0x6b46, 0x2442,
+ 0x6b47, 0x0e4a,
+ 0x6b48, 0x2446,
+ 0x6b49, 0x1001,
+ 0x6b4a, 0x26e2,
+ 0x6b4b, 0x26e4,
+ 0x6b4c, 0x1002,
+ 0x6b4d, 0x26e3,
+ 0x6b4e, 0x1185,
+ 0x6b50, 0x1184,
+ 0x6b51, 0x2924,
+ 0x6b52, 0x3f6e,
+ 0x6b54, 0x2b89,
+ 0x6b55, 0x2b88,
+ 0x6b56, 0x2b8a,
+ 0x6b57, 0x3aae,
+ 0x6b59, 0x12dc,
+ 0x6b5b, 0x2d8a,
+ 0x6b5c, 0x13f0,
+ 0x6b5e, 0x2f3f,
+ 0x6b5f, 0x14e4,
+ 0x6b60, 0x30a7,
+ 0x6b61, 0x16c7,
+ 0x6b62, 0x02df,
+ 0x6b63, 0x034d,
+ 0x6b64, 0x03e4,
+ 0x6b65, 0x04c9,
+ 0x6b66, 0x061b,
+ 0x6b6a, 0x0769,
+ 0x6b6d, 0x1ceb,
+ 0x6b6f, 0x4515,
+ 0x6b72, 0x0e4b,
+ 0x6b74, 0x41fc,
+ 0x6b76, 0x29a2,
+ 0x6b77, 0x12dd,
+ 0x6b78, 0x14e5,
+ 0x6b79, 0x02e0,
+ 0x6b7a, 0x44ee,
+ 0x6b7b, 0x03e5,
+ 0x6b7e, 0x19cb,
+ 0x6b7f, 0x061d,
+ 0x6b80, 0x19ca,
+ 0x6b81, 0x466b,
+ 0x6b82, 0x1b3e,
+ 0x6b83, 0x076a,
+ 0x6b84, 0x1b3f,
+ 0x6b86, 0x076b,
+ 0x6b88, 0x1ced,
+ 0x6b89, 0x0900,
+ 0x6b8a, 0x08ff,
+ 0x6b8c, 0x1f43,
+ 0x6b8d, 0x1f41,
+ 0x6b8f, 0x1f40,
+ 0x6b91, 0x1f3f,
+ 0x6b94, 0x21b6,
+ 0x6b95, 0x21b9,
+ 0x6b96, 0x0c9f,
+ 0x6b97, 0x21b7,
+ 0x6b98, 0x0c9e,
+ 0x6b99, 0x21b8,
+ 0x6b9b, 0x2448,
+ 0x6b9e, 0x26e5,
+ 0x6ba2, 0x2927,
+ 0x6ba3, 0x2926,
+ 0x6ba4, 0x1186,
+ 0x6ba5, 0x2925,
+ 0x6ba6, 0x2928,
+ 0x6ba7, 0x2b8b,
+ 0x6baa, 0x2b8c,
+ 0x6bad, 0x2d8b,
+ 0x6bae, 0x13f1,
+ 0x6baf, 0x14e6,
+ 0x6bb0, 0x30a8,
+ 0x6bb2, 0x1679,
+ 0x6bb3, 0x178a,
+ 0x6bb5, 0x076c,
+ 0x6bb6, 0x1b40,
+ 0x6bb7, 0x0901,
+ 0x6bba, 0x0ae8,
+ 0x6bbc, 0x0ca0,
+ 0x6bbd, 0x21ba,
+ 0x6bbf, 0x0e4d,
+ 0x6bc0, 0x0e4c,
+ 0x6bc1, 0x466c,
+ 0x6bc3, 0x26e8,
+ 0x6bc5, 0x1187,
+ 0x6bc7, 0x2b8f,
+ 0x6bc8, 0x2b8e,
+ 0x6bc9, 0x2f40,
+ 0x6bca, 0x3421,
+ 0x6bcb, 0x02e1,
+ 0x6bcc, 0x178b,
+ 0x6bcd, 0x034e,
+ 0x6bcf, 0x04ca,
+ 0x6bd0, 0x18ad,
+ 0x6bd2, 0x076d,
+ 0x6bd3, 0x0e4e,
+ 0x6bd4, 0x02e2,
+ 0x6bd6, 0x1b41,
+ 0x6bd7, 0x076e,
+ 0x6bd8, 0x1b42,
+ 0x6bda, 0x13f2,
+ 0x6bdb, 0x02e3,
+ 0x6bdc, 0x4207,
+ 0x6bde, 0x19cc,
+ 0x6be0, 0x1b43,
+ 0x6be1, 0x4205,
+ 0x6be2, 0x1cf2,
+ 0x6be3, 0x1cf1,
+ 0x6be4, 0x1cef,
+ 0x6be6, 0x1cee,
+ 0x6be7, 0x1cf3,
+ 0x6be8, 0x1cf0,
+ 0x6bea, 0x466d,
+ 0x6beb, 0x0ae9,
+ 0x6bef, 0x0ca1,
+ 0x6bf0, 0x21bb,
+ 0x6bf2, 0x21bc,
+ 0x6bf7, 0x244c,
+ 0x6bf9, 0x244b,
+ 0x6bfa, 0x3f79,
+ 0x6bfb, 0x2449,
+ 0x6bfd, 0x0e4f,
+ 0x6bfe, 0x26ea,
+ 0x6bff, 0x292b,
+ 0x6c00, 0x292a,
+ 0x6c01, 0x2929,
+ 0x6c02, 0x292c,
+ 0x6c03, 0x2b91,
+ 0x6c04, 0x2b90,
+ 0x6c05, 0x12de,
+ 0x6c06, 0x2b92,
+ 0x6c08, 0x13f3,
+ 0x6c09, 0x2d8c,
+ 0x6c0b, 0x2f41,
+ 0x6c0c, 0x30a9,
+ 0x6c0d, 0x3388,
+ 0x6c0f, 0x02e4,
+ 0x6c10, 0x0350,
+ 0x6c11, 0x034f,
+ 0x6c13, 0x061e,
+ 0x6c14, 0x178c,
+ 0x6c15, 0x17aa,
+ 0x6c16, 0x03e6,
+ 0x6c18, 0x1801,
+ 0x6c19, 0x18ae,
+ 0x6c1b, 0x061f,
+ 0x6c1c, 0x38ab,
+ 0x6c1d, 0x19cd,
+ 0x6c1f, 0x076f,
+ 0x6c20, 0x1b44,
+ 0x6c23, 0x0902,
+ 0x6c24, 0x0906,
+ 0x6c25, 0x1cf4,
+ 0x6c26, 0x0905,
+ 0x6c27, 0x0903,
+ 0x6c2a, 0x1f44,
+ 0x6c2b, 0x0aeb,
+ 0x6c2c, 0x0ca4,
+ 0x6c2e, 0x0ca2,
+ 0x6c30, 0x21be,
+ 0x6c31, 0x3f63,
+ 0x6c33, 0x1003,
+ 0x6c34, 0x02e5,
+ 0x6c35, 0x44ef,
+ 0x6c36, 0x17ab,
+ 0x6c37, 0x4208,
+ 0x6c38, 0x0351,
+ 0x6c39, 0x3e05,
+ 0x6c3a, 0x44f0,
+ 0x6c3b, 0x17ae,
+ 0x6c3d, 0x4381,
+ 0x6c3e, 0x0354,
+ 0x6c3f, 0x17ad,
+ 0x6c40, 0x0353,
+ 0x6c41, 0x0352,
+ 0x6c42, 0x04cb,
+ 0x6c43, 0x17ac,
+ 0x6c46, 0x1802,
+ 0x6c49, 0x408d,
+ 0x6c4a, 0x1806,
+ 0x6c4b, 0x1808,
+ 0x6c4d, 0x03f0,
+ 0x6c4f, 0x1805,
+ 0x6c50, 0x03ec,
+ 0x6c52, 0x1803,
+ 0x6c54, 0x1807,
+ 0x6c55, 0x03ed,
+ 0x6c57, 0x03e8,
+ 0x6c58, 0x3bba,
+ 0x6c59, 0x03e9,
+ 0x6c5a, 0x420c,
+ 0x6c5b, 0x03ef,
+ 0x6c5c, 0x1804,
+ 0x6c5d, 0x03e7,
+ 0x6c5e, 0x04cc,
+ 0x6c5f, 0x03ea,
+ 0x6c61, 0x03ee,
+ 0x6c65, 0x18c0,
+ 0x6c66, 0x18be,
+ 0x6c67, 0x18b1,
+ 0x6c68, 0x04d8,
+ 0x6c69, 0x18b8,
+ 0x6c6a, 0x04d3,
+ 0x6c6b, 0x18b2,
+ 0x6c6d, 0x18ba,
+ 0x6c6e, 0x40ca,
+ 0x6c6f, 0x18b7,
+ 0x6c70, 0x04d6,
+ 0x6c71, 0x18b6,
+ 0x6c72, 0x04dd,
+ 0x6c73, 0x18bf,
+ 0x6c74, 0x04df,
+ 0x6c75, 0x466e,
+ 0x6c76, 0x04e1,
+ 0x6c78, 0x18b0,
+ 0x6c79, 0x420e,
+ 0x6c7a, 0x04d4,
+ 0x6c7b, 0x18c1,
+ 0x6c7d, 0x04db,
+ 0x6c7e, 0x04de,
+ 0x6c7f, 0x37a6,
+ 0x6c80, 0x19e4,
+ 0x6c81, 0x04ce,
+ 0x6c82, 0x04e5,
+ 0x6c83, 0x04dc,
+ 0x6c84, 0x18b3,
+ 0x6c85, 0x04d1,
+ 0x6c86, 0x04e0,
+ 0x6c87, 0x18bb,
+ 0x6c88, 0x04cf,
+ 0x6c8a, 0x19e2,
+ 0x6c8b, 0x18b4,
+ 0x6c8c, 0x04d7,
+ 0x6c8d, 0x04e2,
+ 0x6c8e, 0x18c2,
+ 0x6c8f, 0x18b5,
+ 0x6c90, 0x04d5,
+ 0x6c92, 0x04da,
+ 0x6c93, 0x19ce,
+ 0x6c94, 0x04e3,
+ 0x6c95, 0x18bc,
+ 0x6c96, 0x04d9,
+ 0x6c98, 0x04e4,
+ 0x6c99, 0x04cd,
+ 0x6c9a, 0x18b9,
+ 0x6c9b, 0x04d2,
+ 0x6c9c, 0x18bd,
+ 0x6c9d, 0x19e3,
+ 0x6c9f, 0x3889,
+ 0x6ca2, 0x3d63,
+ 0x6caa, 0x466f,
+ 0x6cab, 0x062b,
+ 0x6cac, 0x063b,
+ 0x6cad, 0x19d5,
+ 0x6cae, 0x0632,
+ 0x6caf, 0x3cf6,
+ 0x6cb0, 0x19ea,
+ 0x6cb1, 0x0623,
+ 0x6cb2, 0x3ecc,
+ 0x6cb3, 0x0626,
+ 0x6cb4, 0x19e1,
+ 0x6cb6, 0x19d3,
+ 0x6cb7, 0x19d7,
+ 0x6cb8, 0x062e,
+ 0x6cb9, 0x0630,
+ 0x6cba, 0x19da,
+ 0x6cbb, 0x0637,
+ 0x6cbc, 0x0629,
+ 0x6cbd, 0x0627,
+ 0x6cbf, 0x0636,
+ 0x6cc0, 0x19e6,
+ 0x6cc1, 0x0631,
+ 0x6cc2, 0x19d9,
+ 0x6cc3, 0x19db,
+ 0x6cc4, 0x062f,
+ 0x6cc5, 0x0634,
+ 0x6cc6, 0x19dc,
+ 0x6cc7, 0x19e9,
+ 0x6cc9, 0x0770,
+ 0x6cca, 0x063a,
+ 0x6ccb, 0x4070,
+ 0x6ccc, 0x0624,
+ 0x6ccd, 0x19e8,
+ 0x6cce, 0x3f91,
+ 0x6ccf, 0x19ec,
+ 0x6cd0, 0x19d8,
+ 0x6cd1, 0x19ee,
+ 0x6cd2, 0x19df,
+ 0x6cd3, 0x062d,
+ 0x6cd4, 0x19d4,
+ 0x6cd5, 0x062c,
+ 0x6cd6, 0x063e,
+ 0x6cd7, 0x0633,
+ 0x6cd9, 0x19d2,
+ 0x6cda, 0x1b4e,
+ 0x6cdb, 0x0639,
+ 0x6cdc, 0x063d,
+ 0x6cdd, 0x19e0,
+ 0x6cde, 0x19e5,
+ 0x6cdf, 0x3d57,
+ 0x6ce0, 0x063f,
+ 0x6ce1, 0x0638,
+ 0x6ce2, 0x062a,
+ 0x6ce3, 0x0620,
+ 0x6ce5, 0x0625,
+ 0x6ce7, 0x19d6,
+ 0x6ce8, 0x0621,
+ 0x6ce9, 0x19ed,
+ 0x6cea, 0x3f8d,
+ 0x6ceb, 0x19d0,
+ 0x6cec, 0x19cf,
+ 0x6ced, 0x19dd,
+ 0x6cee, 0x19d1,
+ 0x6cef, 0x063c,
+ 0x6cf0, 0x0907,
+ 0x6cf1, 0x0635,
+ 0x6cf2, 0x19de,
+ 0x6cf3, 0x0622,
+ 0x6cf5, 0x077f,
+ 0x6cf9, 0x19eb,
+ 0x6d00, 0x1b55,
+ 0x6d01, 0x1b58,
+ 0x6d02, 0x4671,
+ 0x6d03, 0x1b5b,
+ 0x6d04, 0x1b50,
+ 0x6d05, 0x3a19,
+ 0x6d06, 0x4672,
+ 0x6d07, 0x1b5e,
+ 0x6d08, 0x1b61,
+ 0x6d09, 0x1b63,
+ 0x6d0a, 0x1b4d,
+ 0x6d0b, 0x0771,
+ 0x6d0c, 0x0776,
+ 0x6d0d, 0x1cf9,
+ 0x6d0e, 0x0786,
+ 0x6d0f, 0x1b5c,
+ 0x6d10, 0x1b64,
+ 0x6d11, 0x1b54,
+ 0x6d12, 0x1b4c,
+ 0x6d16, 0x1d14,
+ 0x6d17, 0x0779,
+ 0x6d18, 0x1b59,
+ 0x6d19, 0x1b51,
+ 0x6d1a, 0x1b53,
+ 0x6d1b, 0x077e,
+ 0x6d1d, 0x1b56,
+ 0x6d1e, 0x0778,
+ 0x6d1f, 0x1b49,
+ 0x6d20, 0x1b5f,
+ 0x6d22, 0x1b62,
+ 0x6d24, 0x3ac3,
+ 0x6d25, 0x0775,
+ 0x6d26, 0x4673,
+ 0x6d27, 0x0781,
+ 0x6d28, 0x1b46,
+ 0x6d29, 0x0783,
+ 0x6d2a, 0x0773,
+ 0x6d2b, 0x0787,
+ 0x6d2c, 0x1b60,
+ 0x6d2d, 0x1b48,
+ 0x6d2e, 0x0784,
+ 0x6d2f, 0x1d0e,
+ 0x6d30, 0x19e7,
+ 0x6d31, 0x0777,
+ 0x6d32, 0x0772,
+ 0x6d33, 0x1b4f,
+ 0x6d34, 0x1b47,
+ 0x6d35, 0x0785,
+ 0x6d36, 0x077d,
+ 0x6d37, 0x1b5a,
+ 0x6d38, 0x0782,
+ 0x6d39, 0x0780,
+ 0x6d3a, 0x1b52,
+ 0x6d3b, 0x077a,
+ 0x6d3c, 0x1b4a,
+ 0x6d3d, 0x077b,
+ 0x6d3f, 0x1b4b,
+ 0x6d40, 0x1b5d,
+ 0x6d41, 0x0774,
+ 0x6d42, 0x1b57,
+ 0x6d4e, 0x4558,
+ 0x6d57, 0x3cf3,
+ 0x6d58, 0x1cfc,
+ 0x6d59, 0x090f,
+ 0x6d5a, 0x0914,
+ 0x6d5b, 0x409c,
+ 0x6d5c, 0x4222,
+ 0x6d5e, 0x1d05,
+ 0x6d5f, 0x1d0b,
+ 0x6d60, 0x1d07,
+ 0x6d61, 0x1cfa,
+ 0x6d62, 0x1cfd,
+ 0x6d63, 0x1cf6,
+ 0x6d65, 0x091b,
+ 0x6d66, 0x090c,
+ 0x6d67, 0x1d06,
+ 0x6d68, 0x1d0f,
+ 0x6d69, 0x0916,
+ 0x6d6a, 0x0908,
+ 0x6d6c, 0x0911,
+ 0x6d6d, 0x1cfe,
+ 0x6d6e, 0x0913,
+ 0x6d6f, 0x1cff,
+ 0x6d70, 0x1d09,
+ 0x6d71, 0x40f5,
+ 0x6d72, 0x39d7,
+ 0x6d74, 0x0915,
+ 0x6d75, 0x1d18,
+ 0x6d76, 0x1cf8,
+ 0x6d77, 0x090e,
+ 0x6d78, 0x090d,
+ 0x6d79, 0x0919,
+ 0x6d7a, 0x1cf5,
+ 0x6d7b, 0x1d16,
+ 0x6d7c, 0x1d0a,
+ 0x6d7d, 0x1d17,
+ 0x6d7e, 0x1d11,
+ 0x6d7f, 0x1d03,
+ 0x6d80, 0x1d12,
+ 0x6d81, 0x4674,
+ 0x6d82, 0x1d0c,
+ 0x6d83, 0x1d15,
+ 0x6d84, 0x1d13,
+ 0x6d85, 0x091a,
+ 0x6d86, 0x1d04,
+ 0x6d87, 0x090b,
+ 0x6d88, 0x090a,
+ 0x6d89, 0x0912,
+ 0x6d8a, 0x0918,
+ 0x6d8b, 0x1d10,
+ 0x6d8c, 0x0917,
+ 0x6d8d, 0x1d01,
+ 0x6d8e, 0x0aec,
+ 0x6d8f, 0x3de8,
+ 0x6d90, 0x1d19,
+ 0x6d91, 0x1d00,
+ 0x6d92, 0x1cfb,
+ 0x6d93, 0x0910,
+ 0x6d94, 0x091c,
+ 0x6d95, 0x0909,
+ 0x6d96, 0x4221,
+ 0x6d97, 0x1d08,
+ 0x6d98, 0x1d0d,
+ 0x6da4, 0x4676,
+ 0x6da5, 0x3ab9,
+ 0x6daa, 0x0b0e,
+ 0x6dab, 0x1f46,
+ 0x6dac, 0x1f4a,
+ 0x6dae, 0x0afb,
+ 0x6daf, 0x0af9,
+ 0x6db1, 0x4677,
+ 0x6db2, 0x0af0,
+ 0x6db3, 0x1f48,
+ 0x6db4, 0x1f47,
+ 0x6db5, 0x0b04,
+ 0x6db7, 0x1f4d,
+ 0x6db8, 0x0afe,
+ 0x6db9, 0x3ffb,
+ 0x6dba, 0x1f5f,
+ 0x6dbb, 0x1f6b,
+ 0x6dbc, 0x0aed,
+ 0x6dbd, 0x1f5c,
+ 0x6dbe, 0x1f55,
+ 0x6dbf, 0x0b10,
+ 0x6dc0, 0x1f45,
+ 0x6dc2, 0x1f61,
+ 0x6dc4, 0x0b0d,
+ 0x6dc5, 0x0b01,
+ 0x6dc6, 0x0b0c,
+ 0x6dc7, 0x0af7,
+ 0x6dc8, 0x1f51,
+ 0x6dc9, 0x1f63,
+ 0x6dca, 0x1f5b,
+ 0x6dcb, 0x0af8,
+ 0x6dcc, 0x0af2,
+ 0x6dcd, 0x1f69,
+ 0x6dcf, 0x1f62,
+ 0x6dd0, 0x1f64,
+ 0x6dd1, 0x0afa,
+ 0x6dd2, 0x0b02,
+ 0x6dd3, 0x1f66,
+ 0x6dd4, 0x1f4f,
+ 0x6dd5, 0x1f60,
+ 0x6dd6, 0x1f54,
+ 0x6dd7, 0x1f68,
+ 0x6dd8, 0x0b07,
+ 0x6dd9, 0x0aef,
+ 0x6dda, 0x0b05,
+ 0x6ddb, 0x1f59,
+ 0x6ddc, 0x1f57,
+ 0x6dde, 0x0afc,
+ 0x6ddf, 0x1f53,
+ 0x6de0, 0x1f52,
+ 0x6de1, 0x0af1,
+ 0x6de2, 0x1f4c,
+ 0x6de3, 0x1f6a,
+ 0x6de4, 0x0af3,
+ 0x6de5, 0x1f56,
+ 0x6de6, 0x0b11,
+ 0x6de8, 0x0b0b,
+ 0x6de9, 0x1f4b,
+ 0x6dea, 0x0b08,
+ 0x6deb, 0x0b06,
+ 0x6dec, 0x0b0f,
+ 0x6ded, 0x1f5d,
+ 0x6dee, 0x0b0a,
+ 0x6def, 0x1d02,
+ 0x6df0, 0x1f5e,
+ 0x6df1, 0x0b09,
+ 0x6df2, 0x1f65,
+ 0x6df3, 0x0aee,
+ 0x6df4, 0x1f5a,
+ 0x6df5, 0x0b00,
+ 0x6df6, 0x1f4e,
+ 0x6df7, 0x0aff,
+ 0x6df9, 0x0afd,
+ 0x6dfa, 0x0af5,
+ 0x6dfb, 0x0af4,
+ 0x6dfc, 0x21bf,
+ 0x6dfd, 0x1f67,
+ 0x6e00, 0x1f50,
+ 0x6e02, 0x3cfa,
+ 0x6e03, 0x21d4,
+ 0x6e04, 0x3abe,
+ 0x6e05, 0x0af6,
+ 0x6e0a, 0x3ac1,
+ 0x6e0f, 0x3cf0,
+ 0x6e15, 0x4678,
+ 0x6e18, 0x4679,
+ 0x6e19, 0x0cc1,
+ 0x6e1a, 0x0b03,
+ 0x6e1b, 0x0caf,
+ 0x6e1c, 0x21ce,
+ 0x6e1d, 0x0cbd,
+ 0x6e1f, 0x21c2,
+ 0x6e20, 0x0cac,
+ 0x6e21, 0x0ca8,
+ 0x6e22, 0x21e0,
+ 0x6e23, 0x0cae,
+ 0x6e24, 0x0cb2,
+ 0x6e25, 0x0cad,
+ 0x6e26, 0x0cb6,
+ 0x6e27, 0x21e4,
+ 0x6e28, 0x21db,
+ 0x6e29, 0x467a,
+ 0x6e2a, 0x4302,
+ 0x6e2b, 0x21c9,
+ 0x6e2c, 0x0cbb,
+ 0x6e2d, 0x0cb5,
+ 0x6e2e, 0x21d5,
+ 0x6e2f, 0x0ca5,
+ 0x6e30, 0x21e1,
+ 0x6e31, 0x21da,
+ 0x6e32, 0x0ca9,
+ 0x6e33, 0x21cf,
+ 0x6e34, 0x0cb8,
+ 0x6e35, 0x21ec,
+ 0x6e38, 0x0ca6,
+ 0x6e39, 0x21df,
+ 0x6e3a, 0x0cba,
+ 0x6e3b, 0x21d3,
+ 0x6e3c, 0x21c5,
+ 0x6e3e, 0x0cbe,
+ 0x6e3f, 0x21ca,
+ 0x6e40, 0x21d1,
+ 0x6e41, 0x21cb,
+ 0x6e43, 0x0cbc,
+ 0x6e44, 0x0cc4,
+ 0x6e45, 0x21c7,
+ 0x6e46, 0x21c0,
+ 0x6e49, 0x21c3,
+ 0x6e4a, 0x0cab,
+ 0x6e4b, 0x21d0,
+ 0x6e4d, 0x0cb9,
+ 0x6e4e, 0x0cc2,
+ 0x6e4f, 0x4234,
+ 0x6e50, 0x41d1,
+ 0x6e51, 0x21d2,
+ 0x6e52, 0x21ea,
+ 0x6e53, 0x21e2,
+ 0x6e54, 0x0ca7,
+ 0x6e55, 0x21e8,
+ 0x6e56, 0x0cb3,
+ 0x6e58, 0x0cb1,
+ 0x6e59, 0x40e6,
+ 0x6e5a, 0x21ee,
+ 0x6e5b, 0x0cb0,
+ 0x6e5c, 0x21d8,
+ 0x6e5d, 0x21cc,
+ 0x6e5e, 0x21d6,
+ 0x6e5f, 0x0cc7,
+ 0x6e60, 0x21dc,
+ 0x6e61, 0x21d9,
+ 0x6e62, 0x21c8,
+ 0x6e63, 0x0cc3,
+ 0x6e64, 0x21e6,
+ 0x6e65, 0x21e3,
+ 0x6e66, 0x21eb,
+ 0x6e67, 0x0caa,
+ 0x6e68, 0x21d7,
+ 0x6e69, 0x0cc6,
+ 0x6e6b, 0x21de,
+ 0x6e6e, 0x0cb4,
+ 0x6e6f, 0x0cb7,
+ 0x6e71, 0x21dd,
+ 0x6e72, 0x0cc5,
+ 0x6e73, 0x21cd,
+ 0x6e74, 0x1f49,
+ 0x6e76, 0x39d3,
+ 0x6e77, 0x21e7,
+ 0x6e78, 0x21e5,
+ 0x6e79, 0x21e9,
+ 0x6e7c, 0x4223,
+ 0x6e86, 0x467b,
+ 0x6e88, 0x21c4,
+ 0x6e89, 0x0cc0,
+ 0x6e8b, 0x3bbf,
+ 0x6e8d, 0x246c,
+ 0x6e8e, 0x246b,
+ 0x6e8f, 0x2451,
+ 0x6e90, 0x0e55,
+ 0x6e92, 0x246a,
+ 0x6e93, 0x2454,
+ 0x6e96, 0x0e5f,
+ 0x6e97, 0x2473,
+ 0x6e98, 0x0e5a,
+ 0x6e99, 0x2469,
+ 0x6e9a, 0x4581,
+ 0x6e9b, 0x244e,
+ 0x6e9c, 0x0e60,
+ 0x6e9d, 0x0e56,
+ 0x6e9e, 0x245d,
+ 0x6e9f, 0x2453,
+ 0x6ea0, 0x2456,
+ 0x6ea1, 0x246e,
+ 0x6ea2, 0x0e50,
+ 0x6ea3, 0x2475,
+ 0x6ea4, 0x246d,
+ 0x6ea5, 0x0e59,
+ 0x6ea6, 0x2462,
+ 0x6ea7, 0x0e64,
+ 0x6eaa, 0x0e63,
+ 0x6eab, 0x0e5d,
+ 0x6eae, 0x2474,
+ 0x6eaf, 0x0e51,
+ 0x6eb0, 0x2460,
+ 0x6eb1, 0x2457,
+ 0x6eb2, 0x2464,
+ 0x6eb3, 0x2470,
+ 0x6eb4, 0x0e65,
+ 0x6eb5, 0x41fe,
+ 0x6eb6, 0x0e53,
+ 0x6eb7, 0x245f,
+ 0x6eb8, 0x3e0c,
+ 0x6eb9, 0x2458,
+ 0x6eba, 0x0e5c,
+ 0x6ebb, 0x467d,
+ 0x6ebc, 0x0e5b,
+ 0x6ebd, 0x245b,
+ 0x6ebe, 0x2465,
+ 0x6ebf, 0x246f,
+ 0x6ec0, 0x2452,
+ 0x6ec1, 0x245c,
+ 0x6ec2, 0x0e54,
+ 0x6ec3, 0x2466,
+ 0x6ec4, 0x0e61,
+ 0x6ec5, 0x0e58,
+ 0x6ec6, 0x2459,
+ 0x6ec7, 0x0e57,
+ 0x6ec8, 0x2450,
+ 0x6ec9, 0x245e,
+ 0x6eca, 0x2472,
+ 0x6ecb, 0x0cbf,
+ 0x6ecc, 0x101f,
+ 0x6ecd, 0x2461,
+ 0x6ece, 0x26eb,
+ 0x6ecf, 0x2463,
+ 0x6ed0, 0x2471,
+ 0x6ed1, 0x0e5e,
+ 0x6ed2, 0x245a,
+ 0x6ed3, 0x0e52,
+ 0x6ed4, 0x0e62,
+ 0x6ed5, 0x119a,
+ 0x6ed6, 0x244f,
+ 0x6ed8, 0x2468,
+ 0x6ed9, 0x4069,
+ 0x6eda, 0x467f,
+ 0x6edb, 0x402f,
+ 0x6edc, 0x2467,
+ 0x6edd, 0x4538,
+ 0x6ee2, 0x467e,
+ 0x6ee8, 0x4681,
+ 0x6eeb, 0x2707,
+ 0x6eec, 0x101c,
+ 0x6eed, 0x26fc,
+ 0x6eee, 0x2701,
+ 0x6eef, 0x1011,
+ 0x6ef1, 0x26ed,
+ 0x6ef2, 0x101e,
+ 0x6ef4, 0x1008,
+ 0x6ef5, 0x26ec,
+ 0x6ef6, 0x270d,
+ 0x6ef7, 0x1020,
+ 0x6ef8, 0x26f0,
+ 0x6ef9, 0x2700,
+ 0x6efa, 0x423b,
+ 0x6efb, 0x26f2,
+ 0x6efc, 0x2710,
+ 0x6efd, 0x270c,
+ 0x6efe, 0x1006,
+ 0x6eff, 0x1010,
+ 0x6f00, 0x2946,
+ 0x6f01, 0x101d,
+ 0x6f02, 0x100e,
+ 0x6f03, 0x26ee,
+ 0x6f04, 0x4224,
+ 0x6f05, 0x270b,
+ 0x6f06, 0x1012,
+ 0x6f07, 0x2708,
+ 0x6f08, 0x2715,
+ 0x6f09, 0x26f4,
+ 0x6f0a, 0x26fd,
+ 0x6f0b, 0x3aba,
+ 0x6f0c, 0x3cfb,
+ 0x6f0d, 0x2713,
+ 0x6f0e, 0x2709,
+ 0x6f0f, 0x100d,
+ 0x6f12, 0x26fb,
+ 0x6f13, 0x1007,
+ 0x6f14, 0x1005,
+ 0x6f15, 0x1017,
+ 0x6f16, 0x41a0,
+ 0x6f17, 0x46ce,
+ 0x6f18, 0x26f9,
+ 0x6f19, 0x26f6,
+ 0x6f1c, 0x270f,
+ 0x6f1e, 0x2714,
+ 0x6f1f, 0x2712,
+ 0x6f20, 0x100b,
+ 0x6f21, 0x2716,
+ 0x6f22, 0x100f,
+ 0x6f23, 0x1016,
+ 0x6f24, 0x4683,
+ 0x6f25, 0x26ef,
+ 0x6f26, 0x292e,
+ 0x6f27, 0x26f8,
+ 0x6f29, 0x1009,
+ 0x6f2a, 0x101b,
+ 0x6f2b, 0x1018,
+ 0x6f2c, 0x100c,
+ 0x6f2d, 0x2702,
+ 0x6f2e, 0x26f3,
+ 0x6f2f, 0x1019,
+ 0x6f30, 0x2704,
+ 0x6f31, 0x1013,
+ 0x6f32, 0x1015,
+ 0x6f33, 0x1004,
+ 0x6f34, 0x4684,
+ 0x6f35, 0x2706,
+ 0x6f36, 0x26fe,
+ 0x6f37, 0x26f1,
+ 0x6f38, 0x1014,
+ 0x6f39, 0x270e,
+ 0x6f3a, 0x2711,
+ 0x6f3b, 0x26fa,
+ 0x6f3c, 0x2705,
+ 0x6f3d, 0x4282,
+ 0x6f3e, 0x100a,
+ 0x6f3f, 0x1189,
+ 0x6f40, 0x2703,
+ 0x6f41, 0x292d,
+ 0x6f43, 0x270a,
+ 0x6f44, 0x4240,
+ 0x6f4e, 0x26f5,
+ 0x6f4f, 0x2937,
+ 0x6f50, 0x2941,
+ 0x6f51, 0x118c,
+ 0x6f52, 0x2940,
+ 0x6f53, 0x294c,
+ 0x6f54, 0x118e,
+ 0x6f55, 0x293e,
+ 0x6f56, 0x3e52,
+ 0x6f57, 0x2942,
+ 0x6f58, 0x1199,
+ 0x6f5a, 0x2939,
+ 0x6f5b, 0x1191,
+ 0x6f5c, 0x4241,
+ 0x6f5d, 0x2945,
+ 0x6f5e, 0x2b9a,
+ 0x6f5f, 0x119d,
+ 0x6f60, 0x119c,
+ 0x6f61, 0x2947,
+ 0x6f62, 0x2936,
+ 0x6f63, 0x2951,
+ 0x6f64, 0x1197,
+ 0x6f66, 0x118d,
+ 0x6f67, 0x294a,
+ 0x6f69, 0x294e,
+ 0x6f6a, 0x2953,
+ 0x6f6b, 0x2948,
+ 0x6f6c, 0x293c,
+ 0x6f6d, 0x1190,
+ 0x6f6e, 0x1193,
+ 0x6f6f, 0x119b,
+ 0x6f70, 0x1196,
+ 0x6f72, 0x293f,
+ 0x6f73, 0x26ff,
+ 0x6f74, 0x4243,
+ 0x6f76, 0x293b,
+ 0x6f77, 0x2952,
+ 0x6f78, 0x1192,
+ 0x6f79, 0x3bbe,
+ 0x6f7a, 0x1195,
+ 0x6f7b, 0x2954,
+ 0x6f7c, 0x118a,
+ 0x6f7d, 0x2949,
+ 0x6f7e, 0x292f,
+ 0x6f7f, 0x294f,
+ 0x6f80, 0x13fc,
+ 0x6f81, 0x4687,
+ 0x6f82, 0x293d,
+ 0x6f84, 0x118b,
+ 0x6f85, 0x2938,
+ 0x6f86, 0x118f,
+ 0x6f87, 0x2930,
+ 0x6f88, 0x101a,
+ 0x6f89, 0x2934,
+ 0x6f8a, 0x4195,
+ 0x6f8b, 0x294d,
+ 0x6f8c, 0x2935,
+ 0x6f8d, 0x2933,
+ 0x6f8e, 0x1194,
+ 0x6f90, 0x294b,
+ 0x6f92, 0x2932,
+ 0x6f93, 0x2944,
+ 0x6f94, 0x2943,
+ 0x6f95, 0x2950,
+ 0x6f96, 0x293a,
+ 0x6f97, 0x1198,
+ 0x6f9d, 0x4239,
+ 0x6f9e, 0x2b9d,
+ 0x6f9f, 0x4246,
+ 0x6fa0, 0x12eb,
+ 0x6fa1, 0x12e1,
+ 0x6fa2, 0x2ba9,
+ 0x6fa3, 0x2b95,
+ 0x6fa4, 0x12e3,
+ 0x6fa5, 0x2ba1,
+ 0x6fa6, 0x12ea,
+ 0x6fa7, 0x12e5,
+ 0x6fa8, 0x2b9f,
+ 0x6fa9, 0x2d8e,
+ 0x6faa, 0x2ba5,
+ 0x6fab, 0x2bab,
+ 0x6fac, 0x2ba4,
+ 0x6fad, 0x2b93,
+ 0x6fae, 0x2ba2,
+ 0x6faf, 0x2bad,
+ 0x6fb0, 0x2baf,
+ 0x6fb1, 0x12e0,
+ 0x6fb2, 0x2bae,
+ 0x6fb3, 0x12e6,
+ 0x6fb4, 0x12ec,
+ 0x6fb5, 0x3e27,
+ 0x6fb6, 0x12e9,
+ 0x6fb8, 0x2ba8,
+ 0x6fb9, 0x12e8,
+ 0x6fba, 0x2ba3,
+ 0x6fbb, 0x3bbb,
+ 0x6fbc, 0x2b97,
+ 0x6fbd, 0x2b9c,
+ 0x6fbe, 0x4688,
+ 0x6fbf, 0x2ba7,
+ 0x6fc0, 0x12e7,
+ 0x6fc1, 0x12e4,
+ 0x6fc2, 0x12df,
+ 0x6fc3, 0x12e2,
+ 0x6fc4, 0x2b9b,
+ 0x6fc6, 0x2931,
+ 0x6fc7, 0x2b96,
+ 0x6fc8, 0x2b99,
+ 0x6fc9, 0x2baa,
+ 0x6fca, 0x2b9e,
+ 0x6fcb, 0x2b94,
+ 0x6fcc, 0x2d8d,
+ 0x6fcd, 0x2bac,
+ 0x6fce, 0x2b98,
+ 0x6fcf, 0x2ba6,
+ 0x6fd3, 0x4248,
+ 0x6fd4, 0x2d90,
+ 0x6fd5, 0x1400,
+ 0x6fd8, 0x13f4,
+ 0x6fd9, 0x3c74,
+ 0x6fda, 0x3c73,
+ 0x6fdb, 0x13f8,
+ 0x6fdc, 0x2d92,
+ 0x6fdd, 0x2d98,
+ 0x6fde, 0x2d96,
+ 0x6fdf, 0x13f6,
+ 0x6fe1, 0x13fe,
+ 0x6fe2, 0x2d99,
+ 0x6fe3, 0x2d91,
+ 0x6fe4, 0x13f9,
+ 0x6fe6, 0x2d95,
+ 0x6fe7, 0x2d94,
+ 0x6fe8, 0x2d9a,
+ 0x6fe9, 0x13ff,
+ 0x6feb, 0x13fa,
+ 0x6fec, 0x13fd,
+ 0x6fed, 0x2d93,
+ 0x6fee, 0x1401,
+ 0x6fef, 0x13fb,
+ 0x6ff0, 0x1402,
+ 0x6ff1, 0x13f5,
+ 0x6ff2, 0x2d97,
+ 0x6ff4, 0x2d8f,
+ 0x6ff6, 0x38a5,
+ 0x6ff7, 0x2f4e,
+ 0x6ff8, 0x4237,
+ 0x6ffa, 0x14eb,
+ 0x6ffb, 0x2f4b,
+ 0x6ffc, 0x2f4d,
+ 0x6ffe, 0x14e9,
+ 0x6fff, 0x2f49,
+ 0x7000, 0x2f4a,
+ 0x7001, 0x2f45,
+ 0x7003, 0x46e2,
+ 0x7004, 0x2ba0,
+ 0x7005, 0x2f46,
+ 0x7006, 0x14ea,
+ 0x7007, 0x2f42,
+ 0x7009, 0x14e7,
+ 0x700a, 0x2f4f,
+ 0x700b, 0x14e8,
+ 0x700c, 0x2f43,
+ 0x700e, 0x2f48,
+ 0x700f, 0x14ed,
+ 0x7011, 0x14ec,
+ 0x7014, 0x2f47,
+ 0x7015, 0x158f,
+ 0x7016, 0x30ad,
+ 0x7017, 0x30b3,
+ 0x7018, 0x1590,
+ 0x7019, 0x30aa,
+ 0x701a, 0x158d,
+ 0x701b, 0x158a,
+ 0x701c, 0x30b5,
+ 0x701d, 0x158e,
+ 0x701e, 0x3c76,
+ 0x701f, 0x158b,
+ 0x7020, 0x30ac,
+ 0x7021, 0x30af,
+ 0x7024, 0x30b4,
+ 0x7026, 0x2f4c,
+ 0x7027, 0x30ab,
+ 0x7028, 0x158c,
+ 0x7029, 0x30b2,
+ 0x702a, 0x31ef,
+ 0x702b, 0x30ae,
+ 0x702c, 0x468e,
+ 0x702f, 0x31e6,
+ 0x7030, 0x161d,
+ 0x7031, 0x31e9,
+ 0x7032, 0x161e,
+ 0x7033, 0x31f2,
+ 0x7034, 0x31e8,
+ 0x7035, 0x31e5,
+ 0x7037, 0x31e7,
+ 0x7038, 0x31eb,
+ 0x7039, 0x31ee,
+ 0x703a, 0x31ed,
+ 0x703b, 0x31f1,
+ 0x703c, 0x31e4,
+ 0x703e, 0x161c,
+ 0x703f, 0x31ec,
+ 0x7040, 0x31f0,
+ 0x7041, 0x31f3,
+ 0x7042, 0x31ea,
+ 0x7043, 0x32d8,
+ 0x7045, 0x32dd,
+ 0x7048, 0x32db,
+ 0x704a, 0x32da,
+ 0x704b, 0x4254,
+ 0x704c, 0x167a,
+ 0x7050, 0x4690,
+ 0x7051, 0x16c8,
+ 0x7052, 0x338c,
+ 0x7054, 0x4691,
+ 0x7055, 0x3389,
+ 0x7058, 0x16c9,
+ 0x705a, 0x3423,
+ 0x705b, 0x3422,
+ 0x705c, 0x3852,
+ 0x705d, 0x348a,
+ 0x705e, 0x1722,
+ 0x705f, 0x3488,
+ 0x7060, 0x348b,
+ 0x7061, 0x3489,
+ 0x7062, 0x34d0,
+ 0x7063, 0x1744,
+ 0x7064, 0x1752,
+ 0x7065, 0x351c,
+ 0x7066, 0x3506,
+ 0x7067, 0x3cf5,
+ 0x7068, 0x351b,
+ 0x7069, 0x3547,
+ 0x706b, 0x02e6,
+ 0x706c, 0x44f1,
+ 0x706f, 0x4692,
+ 0x7070, 0x03f2,
+ 0x7071, 0x180a,
+ 0x7074, 0x18c3,
+ 0x7075, 0x38c7,
+ 0x7076, 0x04e6,
+ 0x7078, 0x04e9,
+ 0x7079, 0x4099,
+ 0x707a, 0x18c4,
+ 0x707c, 0x04e7,
+ 0x707e, 0x4255,
+ 0x707f, 0x4693,
+ 0x7081, 0x4959,
+ 0x7082, 0x19f7,
+ 0x7083, 0x19f9,
+ 0x7084, 0x19f4,
+ 0x7085, 0x19f1,
+ 0x7086, 0x19f3,
+ 0x7089, 0x43f9,
+ 0x708a, 0x0643,
+ 0x708b, 0x40cb,
+ 0x708e, 0x0641,
+ 0x708f, 0x46b3,
+ 0x7091, 0x19f5,
+ 0x7092, 0x0642,
+ 0x7093, 0x19f2,
+ 0x7094, 0x19ef,
+ 0x7095, 0x0640,
+ 0x7096, 0x19f6,
+ 0x7098, 0x19f0,
+ 0x7099, 0x0644,
+ 0x709a, 0x19f8,
+ 0x709f, 0x1b66,
+ 0x70a0, 0x4742,
+ 0x70a1, 0x1b6a,
+ 0x70a3, 0x3972,
+ 0x70a4, 0x0790,
+ 0x70a5, 0x3cb7,
+ 0x70a6, 0x3d53,
+ 0x70a7, 0x4256,
+ 0x70a9, 0x1b6d,
+ 0x70ab, 0x0788,
+ 0x70ac, 0x078b,
+ 0x70ad, 0x078d,
+ 0x70ae, 0x078f,
+ 0x70af, 0x078c,
+ 0x70b0, 0x1b69,
+ 0x70b1, 0x1b68,
+ 0x70b3, 0x078a,
+ 0x70b4, 0x1b6b,
+ 0x70b7, 0x1b65,
+ 0x70b8, 0x078e,
+ 0x70b9, 0x3d69,
+ 0x70ba, 0x0789,
+ 0x70bb, 0x4812,
+ 0x70bc, 0x4559,
+ 0x70bd, 0x4270,
+ 0x70be, 0x1b67,
+ 0x70c0, 0x4733,
+ 0x70c4, 0x3baa,
+ 0x70c5, 0x1d27,
+ 0x70c8, 0x0921,
+ 0x70ca, 0x091d,
+ 0x70cb, 0x1d1e,
+ 0x70cc, 0x4258,
+ 0x70cd, 0x1d26,
+ 0x70ce, 0x1d2b,
+ 0x70cf, 0x0922,
+ 0x70d0, 0x396d,
+ 0x70d1, 0x1d1c,
+ 0x70d2, 0x1d22,
+ 0x70d3, 0x1d1b,
+ 0x70d4, 0x1d25,
+ 0x70d5, 0x4259,
+ 0x70d7, 0x1d21,
+ 0x70d8, 0x091e,
+ 0x70d9, 0x0920,
+ 0x70da, 0x1d2a,
+ 0x70dc, 0x1d1a,
+ 0x70dd, 0x1d1d,
+ 0x70de, 0x1d23,
+ 0x70df, 0x425b,
+ 0x70e0, 0x1d24,
+ 0x70e1, 0x1d2c,
+ 0x70e2, 0x1d20,
+ 0x70e4, 0x091f,
+ 0x70ef, 0x0b16,
+ 0x70f0, 0x1f72,
+ 0x70f1, 0x3ac8,
+ 0x70f3, 0x1f74,
+ 0x70f4, 0x1f70,
+ 0x70f5, 0x4760,
+ 0x70f6, 0x1f7c,
+ 0x70f7, 0x1f6e,
+ 0x70f8, 0x1f7b,
+ 0x70f9, 0x0b12,
+ 0x70fa, 0x1f6c,
+ 0x70fb, 0x21f2,
+ 0x70fc, 0x1f76,
+ 0x70fd, 0x0b15,
+ 0x70fe, 0x3d0e,
+ 0x70ff, 0x1f77,
+ 0x7100, 0x1f7a,
+ 0x7102, 0x1f7e,
+ 0x7104, 0x1f73,
+ 0x7105, 0x3a23,
+ 0x7106, 0x1f78,
+ 0x7109, 0x0b13,
+ 0x710b, 0x1f7d,
+ 0x710c, 0x1f71,
+ 0x710d, 0x1f6d,
+ 0x710e, 0x1f7f,
+ 0x7110, 0x1f75,
+ 0x7113, 0x1f79,
+ 0x7117, 0x1f6f,
+ 0x7119, 0x0cc8,
+ 0x711b, 0x21fc,
+ 0x711c, 0x0ccf,
+ 0x711d, 0x3d47,
+ 0x711e, 0x21f0,
+ 0x711f, 0x21f9,
+ 0x7120, 0x21ef,
+ 0x7121, 0x0ccc,
+ 0x7122, 0x21f7,
+ 0x7123, 0x21f5,
+ 0x7125, 0x21f6,
+ 0x7126, 0x0cca,
+ 0x7128, 0x21fa,
+ 0x7129, 0x3ba9,
+ 0x712b, 0x4261,
+ 0x712c, 0x426a,
+ 0x712e, 0x21f3,
+ 0x712f, 0x21f1,
+ 0x7130, 0x0ccb,
+ 0x7131, 0x21f4,
+ 0x7132, 0x21f8,
+ 0x7133, 0x3d54,
+ 0x7134, 0x3c7e,
+ 0x7135, 0x376d,
+ 0x7136, 0x0ccd,
+ 0x713a, 0x21fb,
+ 0x713b, 0x3ac5,
+ 0x713e, 0x372e,
+ 0x7140, 0x4398,
+ 0x7141, 0x247b,
+ 0x7142, 0x2482,
+ 0x7143, 0x2484,
+ 0x7144, 0x248a,
+ 0x7145, 0x4262,
+ 0x7146, 0x0e72,
+ 0x7147, 0x2476,
+ 0x7149, 0x0e6a,
+ 0x714a, 0x4264,
+ 0x714b, 0x2485,
+ 0x714c, 0x0e6f,
+ 0x714d, 0x248b,
+ 0x714e, 0x0e66,
+ 0x714f, 0x4267,
+ 0x7150, 0x2488,
+ 0x7151, 0x4865,
+ 0x7152, 0x2478,
+ 0x7153, 0x2489,
+ 0x7154, 0x2477,
+ 0x7156, 0x0e74,
+ 0x7158, 0x2483,
+ 0x7159, 0x0e67,
+ 0x715a, 0x248c,
+ 0x715c, 0x0e6c,
+ 0x715d, 0x247c,
+ 0x715e, 0x0e71,
+ 0x715f, 0x2487,
+ 0x7160, 0x247a,
+ 0x7161, 0x2481,
+ 0x7162, 0x247d,
+ 0x7163, 0x2479,
+ 0x7164, 0x0e69,
+ 0x7165, 0x0e70,
+ 0x7166, 0x0e6e,
+ 0x7167, 0x0e6b,
+ 0x7168, 0x0e73,
+ 0x7169, 0x0e68,
+ 0x716a, 0x2480,
+ 0x716b, 0x3cc5,
+ 0x716c, 0x0e6d,
+ 0x716e, 0x0cce,
+ 0x7170, 0x2486,
+ 0x7171, 0x3dc0,
+ 0x7172, 0x247e,
+ 0x7173, 0x47e7,
+ 0x7175, 0x3ced,
+ 0x7176, 0x4000,
+ 0x7177, 0x3957,
+ 0x7178, 0x247f,
+ 0x717a, 0x4924,
+ 0x717b, 0x271e,
+ 0x717c, 0x3835,
+ 0x717d, 0x1023,
+ 0x717e, 0x3970,
+ 0x7180, 0x271a,
+ 0x7181, 0x2720,
+ 0x7182, 0x271c,
+ 0x7184, 0x1025,
+ 0x7185, 0x271b,
+ 0x7186, 0x271f,
+ 0x7187, 0x2717,
+ 0x7188, 0x4706,
+ 0x7189, 0x2719,
+ 0x718a, 0x1024,
+ 0x718c, 0x39ea,
+ 0x718e, 0x3d3b,
+ 0x718f, 0x271d,
+ 0x7190, 0x2718,
+ 0x7192, 0x1026,
+ 0x7194, 0x1021,
+ 0x7196, 0x425f,
+ 0x7197, 0x2721,
+ 0x7198, 0x481d,
+ 0x7199, 0x1022,
+ 0x719a, 0x295a,
+ 0x719b, 0x2957,
+ 0x719c, 0x2963,
+ 0x719d, 0x295d,
+ 0x719e, 0x295f,
+ 0x719f, 0x119e,
+ 0x71a0, 0x2959,
+ 0x71a1, 0x2961,
+ 0x71a2, 0x48c1,
+ 0x71a3, 0x3ec8,
+ 0x71a4, 0x2960,
+ 0x71a5, 0x295e,
+ 0x71a7, 0x2964,
+ 0x71a8, 0x11a1,
+ 0x71a9, 0x295b,
+ 0x71aa, 0x2962,
+ 0x71ac, 0x119f,
+ 0x71ad, 0x3e1d,
+ 0x71af, 0x2956,
+ 0x71b0, 0x2958,
+ 0x71b1, 0x11a0,
+ 0x71b2, 0x2955,
+ 0x71b3, 0x2965,
+ 0x71b4, 0x425e,
+ 0x71b5, 0x295c,
+ 0x71b7, 0x468b,
+ 0x71b8, 0x2bb3,
+ 0x71b9, 0x12f3,
+ 0x71ba, 0x426e,
+ 0x71bc, 0x2bbe,
+ 0x71bd, 0x2bbc,
+ 0x71be, 0x12ed,
+ 0x71bf, 0x2bb2,
+ 0x71c0, 0x2bb5,
+ 0x71c2, 0x2bb1,
+ 0x71c3, 0x12f7,
+ 0x71c5, 0x2bb0,
+ 0x71c6, 0x2bbf,
+ 0x71c7, 0x2bba,
+ 0x71c8, 0x12f1,
+ 0x71c9, 0x12ee,
+ 0x71ca, 0x2bb9,
+ 0x71cb, 0x2bb7,
+ 0x71ce, 0x12f4,
+ 0x71cf, 0x2bbb,
+ 0x71d0, 0x12ef,
+ 0x71d1, 0x373d,
+ 0x71d2, 0x12f0,
+ 0x71d4, 0x2bb8,
+ 0x71d5, 0x12f2,
+ 0x71d6, 0x2bb4,
+ 0x71d8, 0x2bbd,
+ 0x71d9, 0x12f5,
+ 0x71da, 0x2bc0,
+ 0x71dc, 0x12f6,
+ 0x71dd, 0x4078,
+ 0x71df, 0x1404,
+ 0x71e0, 0x140b,
+ 0x71e1, 0x2d9b,
+ 0x71e2, 0x2da1,
+ 0x71e4, 0x2d9f,
+ 0x71e5, 0x1407,
+ 0x71e6, 0x1406,
+ 0x71e7, 0x1403,
+ 0x71e8, 0x2d9d,
+ 0x71eb, 0x3c81,
+ 0x71ec, 0x1409,
+ 0x71ed, 0x1408,
+ 0x71ee, 0x1405,
+ 0x71f0, 0x2da0,
+ 0x71f1, 0x2d9c,
+ 0x71f2, 0x2d9e,
+ 0x71f4, 0x140a,
+ 0x71f5, 0x46ee,
+ 0x71f6, 0x3e9a,
+ 0x71f8, 0x14f1,
+ 0x71f9, 0x2f52,
+ 0x71fb, 0x14ee,
+ 0x71fd, 0x2f54,
+ 0x71fe, 0x14f0,
+ 0x71ff, 0x2f51,
+ 0x7201, 0x2f50,
+ 0x7202, 0x30b9,
+ 0x7203, 0x2f53,
+ 0x7205, 0x30ba,
+ 0x7206, 0x1591,
+ 0x7207, 0x30b8,
+ 0x7209, 0x3dbb,
+ 0x720a, 0x30b7,
+ 0x720c, 0x30b6,
+ 0x720d, 0x1592,
+ 0x720e, 0x4271,
+ 0x720f, 0x39fc,
+ 0x7210, 0x161f,
+ 0x7213, 0x31f4,
+ 0x7215, 0x4273,
+ 0x7216, 0x3953,
+ 0x7217, 0x3969,
+ 0x7219, 0x32e1,
+ 0x721a, 0x32e0,
+ 0x721b, 0x167b,
+ 0x721d, 0x32df,
+ 0x721e, 0x338d,
+ 0x7222, 0x3424,
+ 0x7223, 0x348c,
+ 0x7224, 0x4276,
+ 0x7226, 0x34d1,
+ 0x7227, 0x3535,
+ 0x7228, 0x1766,
+ 0x7229, 0x3549,
+ 0x722a, 0x02e7,
+ 0x722b, 0x44f2,
+ 0x722c, 0x0645,
+ 0x722e, 0x4279,
+ 0x7230, 0x0791,
+ 0x7235, 0x140c,
+ 0x7236, 0x02e8,
+ 0x7238, 0x0647,
+ 0x7239, 0x0923,
+ 0x723a, 0x0e75,
+ 0x723b, 0x02e9,
+ 0x723d, 0x0b17,
+ 0x723e, 0x1027,
+ 0x723f, 0x178d,
+ 0x7240, 0x427a,
+ 0x7241, 0x1b6e,
+ 0x7242, 0x1d2d,
+ 0x7244, 0x2722,
+ 0x7246, 0x140d,
+ 0x7247, 0x02ea,
+ 0x7248, 0x0648,
+ 0x7249, 0x1b6f,
+ 0x724b, 0x21fd,
+ 0x724c, 0x0cd0,
+ 0x724f, 0x248d,
+ 0x7250, 0x3ac9,
+ 0x7252, 0x0e76,
+ 0x7253, 0x2723,
+ 0x7255, 0x427d,
+ 0x7256, 0x11a2,
+ 0x7257, 0x427e,
+ 0x7258, 0x1593,
+ 0x7259, 0x02eb,
+ 0x725a, 0x21fe,
+ 0x725b, 0x02ec,
+ 0x725c, 0x465a,
+ 0x725d, 0x03f4,
+ 0x725e, 0x180b,
+ 0x725f, 0x03f3,
+ 0x7260, 0x04ec,
+ 0x7261, 0x04eb,
+ 0x7262, 0x04ea,
+ 0x7263, 0x18c5,
+ 0x7266, 0x3ebb,
+ 0x7267, 0x0649,
+ 0x7269, 0x064a,
+ 0x726a, 0x19fa,
+ 0x726c, 0x1b71,
+ 0x726e, 0x1b74,
+ 0x726f, 0x0793,
+ 0x7270, 0x1b72,
+ 0x7272, 0x0792,
+ 0x7273, 0x1b73,
+ 0x7274, 0x0794,
+ 0x7276, 0x1d30,
+ 0x7277, 0x1d2f,
+ 0x7278, 0x1d2e,
+ 0x7279, 0x0924,
+ 0x727b, 0x1f81,
+ 0x727d, 0x0b18,
+ 0x727e, 0x1f80,
+ 0x727f, 0x1f83,
+ 0x7280, 0x0cd2,
+ 0x7281, 0x0b19,
+ 0x7282, 0x4283,
+ 0x7284, 0x0cd1,
+ 0x7285, 0x2202,
+ 0x7286, 0x2201,
+ 0x7287, 0x3aca,
+ 0x7288, 0x21ff,
+ 0x728b, 0x2203,
+ 0x728c, 0x248f,
+ 0x728d, 0x248e,
+ 0x728e, 0x2492,
+ 0x728f, 0x43c9,
+ 0x7290, 0x2491,
+ 0x7291, 0x2490,
+ 0x7292, 0x1028,
+ 0x7293, 0x2726,
+ 0x7294, 0x3acb,
+ 0x7295, 0x2725,
+ 0x7296, 0x1029,
+ 0x7297, 0x2724,
+ 0x7298, 0x2966,
+ 0x729a, 0x2967,
+ 0x729b, 0x11a3,
+ 0x729d, 0x2bc2,
+ 0x729f, 0x473a,
+ 0x72a1, 0x30bf,
+ 0x72a2, 0x1594,
+ 0x72a3, 0x30be,
+ 0x72a4, 0x30bd,
+ 0x72a5, 0x30bb,
+ 0x72a7, 0x167c,
+ 0x72a8, 0x31f6,
+ 0x72a9, 0x338f,
+ 0x72aa, 0x34d2,
+ 0x72ac, 0x02ed,
+ 0x72ad, 0x44f4,
+ 0x72ae, 0x17af,
+ 0x72af, 0x0355,
+ 0x72b0, 0x17b0,
+ 0x72b2, 0x3fb6,
+ 0x72b4, 0x180c,
+ 0x72ba, 0x18cb,
+ 0x72bd, 0x18c7,
+ 0x72bf, 0x18c6,
+ 0x72c0, 0x064b,
+ 0x72c1, 0x18ca,
+ 0x72c2, 0x04ee,
+ 0x72c3, 0x18c8,
+ 0x72c4, 0x04ed,
+ 0x72c5, 0x18cc,
+ 0x72c6, 0x18c9,
+ 0x72c9, 0x19fe,
+ 0x72ca, 0x1b75,
+ 0x72cb, 0x19fc,
+ 0x72cc, 0x1a03,
+ 0x72cd, 0x43ca,
+ 0x72ce, 0x064c,
+ 0x72d0, 0x064f,
+ 0x72d1, 0x1a04,
+ 0x72d2, 0x1a00,
+ 0x72d4, 0x1a01,
+ 0x72d6, 0x19fb,
+ 0x72d7, 0x064e,
+ 0x72d8, 0x19fd,
+ 0x72d9, 0x064d,
+ 0x72da, 0x1a02,
+ 0x72dc, 0x19ff,
+ 0x72df, 0x1b79,
+ 0x72e0, 0x0796,
+ 0x72e2, 0x3f97,
+ 0x72e3, 0x1b7c,
+ 0x72e4, 0x1b76,
+ 0x72e6, 0x1b7b,
+ 0x72e8, 0x1b77,
+ 0x72e9, 0x0795,
+ 0x72ea, 0x1b7a,
+ 0x72eb, 0x1b78,
+ 0x72f3, 0x1d36,
+ 0x72f4, 0x1d33,
+ 0x72f6, 0x1d35,
+ 0x72f7, 0x0929,
+ 0x72f8, 0x0928,
+ 0x72f9, 0x0926,
+ 0x72fa, 0x1d32,
+ 0x72fb, 0x1d37,
+ 0x72fc, 0x0925,
+ 0x72fd, 0x0927,
+ 0x72fe, 0x1d34,
+ 0x72ff, 0x1f8b,
+ 0x7300, 0x1d31,
+ 0x7301, 0x1d38,
+ 0x7302, 0x3f9a,
+ 0x7304, 0x3eb5,
+ 0x7307, 0x1f86,
+ 0x7308, 0x1f8a,
+ 0x730a, 0x1f89,
+ 0x730b, 0x2205,
+ 0x730c, 0x2210,
+ 0x730f, 0x1f8c,
+ 0x7310, 0x46ea,
+ 0x7311, 0x1f87,
+ 0x7312, 0x2204,
+ 0x7313, 0x0b1d,
+ 0x7316, 0x0b1c,
+ 0x7317, 0x1f85,
+ 0x7318, 0x1f88,
+ 0x7319, 0x0b1e,
+ 0x731b, 0x0b1b,
+ 0x731c, 0x0b1a,
+ 0x731d, 0x1f84,
+ 0x731e, 0x1f8d,
+ 0x7322, 0x2207,
+ 0x7323, 0x220e,
+ 0x7325, 0x0cd4,
+ 0x7326, 0x220d,
+ 0x7327, 0x220a,
+ 0x7328, 0x428a,
+ 0x7329, 0x0cd6,
+ 0x732a, 0x3d70,
+ 0x732b, 0x4285,
+ 0x732c, 0x3fb2,
+ 0x732d, 0x220c,
+ 0x732e, 0x428b,
+ 0x7330, 0x2206,
+ 0x7331, 0x2208,
+ 0x7332, 0x220b,
+ 0x7333, 0x2209,
+ 0x7334, 0x0cd5,
+ 0x7335, 0x220f,
+ 0x7336, 0x0cd3,
+ 0x7337, 0x0e77,
+ 0x7338, 0x46eb,
+ 0x7339, 0x43cc,
+ 0x733a, 0x2496,
+ 0x733b, 0x2495,
+ 0x733c, 0x2493,
+ 0x733e, 0x0e7a,
+ 0x733f, 0x0e79,
+ 0x7340, 0x2497,
+ 0x7341, 0x46ec,
+ 0x7342, 0x2494,
+ 0x7343, 0x2727,
+ 0x7344, 0x102a,
+ 0x7345, 0x0e78,
+ 0x7348, 0x43fa,
+ 0x7349, 0x2499,
+ 0x734a, 0x2498,
+ 0x734c, 0x272a,
+ 0x734d, 0x2728,
+ 0x734e, 0x11a4,
+ 0x734f, 0x3f51,
+ 0x7350, 0x102b,
+ 0x7351, 0x2729,
+ 0x7352, 0x2969,
+ 0x7357, 0x11a5,
+ 0x7358, 0x2968,
+ 0x7359, 0x2971,
+ 0x735a, 0x2970,
+ 0x735b, 0x296e,
+ 0x735d, 0x296d,
+ 0x735e, 0x296a,
+ 0x7361, 0x296f,
+ 0x7362, 0x2972,
+ 0x7365, 0x2bc8,
+ 0x7366, 0x2bc5,
+ 0x7368, 0x12f9,
+ 0x7369, 0x2bc4,
+ 0x736a, 0x2bca,
+ 0x736b, 0x2bc9,
+ 0x736c, 0x2bc7,
+ 0x736e, 0x2da3,
+ 0x7370, 0x140e,
+ 0x7371, 0x3f98,
+ 0x7372, 0x140f,
+ 0x7373, 0x2da2,
+ 0x7374, 0x3ed4,
+ 0x7375, 0x14f3,
+ 0x7376, 0x2f55,
+ 0x7377, 0x14f2,
+ 0x7378, 0x1595,
+ 0x737a, 0x1596,
+ 0x737b, 0x1620,
+ 0x737c, 0x31f8,
+ 0x737d, 0x31f7,
+ 0x737e, 0x32e2,
+ 0x737f, 0x3390,
+ 0x7380, 0x16ca,
+ 0x7381, 0x3426,
+ 0x7382, 0x3425,
+ 0x7383, 0x3427,
+ 0x7384, 0x0356,
+ 0x7385, 0x1b7d,
+ 0x7386, 0x092a,
+ 0x7387, 0x0b1f,
+ 0x7388, 0x1f8e,
+ 0x7389, 0x0357,
+ 0x738a, 0x17b1,
+ 0x738b, 0x02ee,
+ 0x738e, 0x180e,
+ 0x738f, 0x46e5,
+ 0x7392, 0x18d1,
+ 0x7393, 0x18cf,
+ 0x7395, 0x18cd,
+ 0x7396, 0x04ef,
+ 0x7397, 0x18ce,
+ 0x7398, 0x39f6,
+ 0x739c, 0x408a,
+ 0x739d, 0x1a0c,
+ 0x739e, 0x395b,
+ 0x739f, 0x0652,
+ 0x73a0, 0x1a0a,
+ 0x73a1, 0x1a06,
+ 0x73a2, 0x1a09,
+ 0x73a4, 0x1a05,
+ 0x73a5, 0x0654,
+ 0x73a6, 0x1a08,
+ 0x73a7, 0x4087,
+ 0x73a8, 0x0651,
+ 0x73a9, 0x0650,
+ 0x73aa, 0x428d,
+ 0x73ab, 0x0653,
+ 0x73ac, 0x1a0b,
+ 0x73ad, 0x1a07,
+ 0x73b2, 0x079b,
+ 0x73b3, 0x079e,
+ 0x73b4, 0x1b85,
+ 0x73b5, 0x1b84,
+ 0x73b6, 0x1b83,
+ 0x73b7, 0x0798,
+ 0x73b8, 0x1b8c,
+ 0x73b9, 0x1b82,
+ 0x73bb, 0x079a,
+ 0x73bc, 0x1d3d,
+ 0x73be, 0x1b89,
+ 0x73bf, 0x1b87,
+ 0x73c0, 0x079d,
+ 0x73c2, 0x1b7f,
+ 0x73c3, 0x1b8a,
+ 0x73c5, 0x1b81,
+ 0x73c6, 0x1b8b,
+ 0x73c7, 0x1b88,
+ 0x73c8, 0x1b80,
+ 0x73c9, 0x4290,
+ 0x73ca, 0x0799,
+ 0x73cb, 0x1b8d,
+ 0x73cc, 0x1b7e,
+ 0x73cd, 0x079c,
+ 0x73ce, 0x411b,
+ 0x73cf, 0x428c,
+ 0x73d0, 0x3b17,
+ 0x73d2, 0x1d42,
+ 0x73d3, 0x1d39,
+ 0x73d4, 0x1d44,
+ 0x73d5, 0x4073,
+ 0x73d6, 0x1d3c,
+ 0x73d7, 0x1d47,
+ 0x73d9, 0x1d3a,
+ 0x73da, 0x1d46,
+ 0x73db, 0x1d43,
+ 0x73dc, 0x1d41,
+ 0x73dd, 0x1d45,
+ 0x73de, 0x0930,
+ 0x73e0, 0x092e,
+ 0x73e1, 0x46f0,
+ 0x73e2, 0x3ca3,
+ 0x73e3, 0x1d3f,
+ 0x73e4, 0x42a5,
+ 0x73e5, 0x1d3b,
+ 0x73e6, 0x3cba,
+ 0x73e7, 0x1d3e,
+ 0x73e8, 0x1d49,
+ 0x73e9, 0x1d40,
+ 0x73ea, 0x092f,
+ 0x73eb, 0x1b86,
+ 0x73ed, 0x092b,
+ 0x73ee, 0x092d,
+ 0x73ef, 0x4011,
+ 0x73f3, 0x3cab,
+ 0x73f4, 0x1f9c,
+ 0x73f5, 0x1f91,
+ 0x73f6, 0x1f8f,
+ 0x73f7, 0x429a,
+ 0x73f8, 0x1f90,
+ 0x73f9, 0x3bf9,
+ 0x73fa, 0x1f97,
+ 0x73fb, 0x3cac,
+ 0x73fc, 0x1f98,
+ 0x73fd, 0x1f94,
+ 0x73fe, 0x0b24,
+ 0x73ff, 0x1f99,
+ 0x7400, 0x1f96,
+ 0x7401, 0x1f93,
+ 0x7403, 0x0b22,
+ 0x7404, 0x1f92,
+ 0x7405, 0x0b20,
+ 0x7406, 0x0b23,
+ 0x7407, 0x1f95,
+ 0x7408, 0x1f9d,
+ 0x7409, 0x092c,
+ 0x740a, 0x0b21,
+ 0x740b, 0x1f9b,
+ 0x740c, 0x1f9a,
+ 0x740d, 0x0b25,
+ 0x7411, 0x456c,
+ 0x7412, 0x3be6,
+ 0x7414, 0x39f4,
+ 0x7415, 0x429b,
+ 0x7416, 0x2215,
+ 0x7417, 0x40ad,
+ 0x7419, 0x46f3,
+ 0x741a, 0x2216,
+ 0x741b, 0x0ce0,
+ 0x741c, 0x38dd,
+ 0x741d, 0x221c,
+ 0x741e, 0x46f4,
+ 0x7420, 0x221e,
+ 0x7421, 0x2217,
+ 0x7422, 0x0cda,
+ 0x7423, 0x221b,
+ 0x7424, 0x221a,
+ 0x7425, 0x0cdb,
+ 0x7426, 0x0ce1,
+ 0x7428, 0x0ce2,
+ 0x7429, 0x221d,
+ 0x742a, 0x0cd8,
+ 0x742b, 0x2214,
+ 0x742c, 0x2212,
+ 0x742d, 0x2218,
+ 0x742e, 0x2211,
+ 0x742f, 0x0cdf,
+ 0x7430, 0x2213,
+ 0x7431, 0x2219,
+ 0x7432, 0x221f,
+ 0x7433, 0x0cd9,
+ 0x7434, 0x0cde,
+ 0x7435, 0x0cdc,
+ 0x7437, 0x3ae1,
+ 0x7438, 0x3b09,
+ 0x7439, 0x429e,
+ 0x743a, 0x0cd7,
+ 0x743c, 0x3adf,
+ 0x743f, 0x0e81,
+ 0x7440, 0x24a0,
+ 0x7441, 0x0e80,
+ 0x7442, 0x24a4,
+ 0x7443, 0x3a1a,
+ 0x7444, 0x249a,
+ 0x7445, 0x3bd7,
+ 0x7446, 0x24a5,
+ 0x7447, 0x42a4,
+ 0x7448, 0x3cb5,
+ 0x7449, 0x4291,
+ 0x744a, 0x249b,
+ 0x744d, 0x24a6,
+ 0x744e, 0x24a3,
+ 0x744f, 0x24a1,
+ 0x7451, 0x249e,
+ 0x7452, 0x249d,
+ 0x7453, 0x4231,
+ 0x7454, 0x24a7,
+ 0x7455, 0x0e7d,
+ 0x7456, 0x39f5,
+ 0x7457, 0x249f,
+ 0x7459, 0x0e82,
+ 0x745a, 0x0e7c,
+ 0x745b, 0x0e83,
+ 0x745d, 0x42c6,
+ 0x745e, 0x0e7f,
+ 0x745f, 0x0e7e,
+ 0x7460, 0x42a2,
+ 0x7462, 0x272b,
+ 0x7463, 0x102d,
+ 0x7464, 0x102c,
+ 0x7465, 0x4101,
+ 0x7467, 0x2730,
+ 0x7468, 0x3aee,
+ 0x7469, 0x11a6,
+ 0x746a, 0x102e,
+ 0x746b, 0x3be7,
+ 0x746c, 0x42a8,
+ 0x746d, 0x1030,
+ 0x746e, 0x2731,
+ 0x746f, 0x0e7b,
+ 0x7470, 0x102f,
+ 0x7471, 0x272d,
+ 0x7472, 0x272f,
+ 0x7473, 0x272c,
+ 0x7474, 0x42a9,
+ 0x7475, 0x272e,
+ 0x7476, 0x42a6,
+ 0x7479, 0x297c,
+ 0x747a, 0x3ad1,
+ 0x747c, 0x297b,
+ 0x747d, 0x2978,
+ 0x747e, 0x11a9,
+ 0x747f, 0x2bcb,
+ 0x7480, 0x11aa,
+ 0x7481, 0x2977,
+ 0x7482, 0x42ac,
+ 0x7483, 0x11a8,
+ 0x7485, 0x2979,
+ 0x7486, 0x2976,
+ 0x7487, 0x2973,
+ 0x7488, 0x297a,
+ 0x7489, 0x2974,
+ 0x748b, 0x11a7,
+ 0x748c, 0x3a21,
+ 0x748d, 0x469d,
+ 0x7490, 0x2da8,
+ 0x7492, 0x2bcf,
+ 0x7494, 0x2bce,
+ 0x7495, 0x2bd0,
+ 0x7497, 0x2da5,
+ 0x7498, 0x12fc,
+ 0x7499, 0x39f3,
+ 0x749a, 0x2bcc,
+ 0x749b, 0x3b0a,
+ 0x749c, 0x12fa,
+ 0x749e, 0x12fe,
+ 0x749f, 0x12fd,
+ 0x74a0, 0x2bcd,
+ 0x74a1, 0x2bd1,
+ 0x74a3, 0x12fb,
+ 0x74a4, 0x4170,
+ 0x74a5, 0x2dac,
+ 0x74a6, 0x1412,
+ 0x74a7, 0x14f4,
+ 0x74a8, 0x1413,
+ 0x74a9, 0x1410,
+ 0x74aa, 0x2da9,
+ 0x74ab, 0x2da7,
+ 0x74ad, 0x2daa,
+ 0x74af, 0x2dad,
+ 0x74b0, 0x1411,
+ 0x74b1, 0x2dab,
+ 0x74b2, 0x2da6,
+ 0x74b4, 0x3ca5,
+ 0x74b5, 0x2f58,
+ 0x74b6, 0x2f5b,
+ 0x74b7, 0x30c2,
+ 0x74b8, 0x2f56,
+ 0x74ba, 0x31f9,
+ 0x74bb, 0x2f5c,
+ 0x74bd, 0x1597,
+ 0x74be, 0x2f5a,
+ 0x74bf, 0x14f5,
+ 0x74c0, 0x2f57,
+ 0x74c1, 0x2f59,
+ 0x74c2, 0x2f5d,
+ 0x74c3, 0x30c3,
+ 0x74c5, 0x30c1,
+ 0x74c8, 0x42b5,
+ 0x74ca, 0x1598,
+ 0x74cb, 0x30c0,
+ 0x74cc, 0x3ade,
+ 0x74cf, 0x1621,
+ 0x74d0, 0x3a9b,
+ 0x74d3, 0x46fa,
+ 0x74d4, 0x167e,
+ 0x74d5, 0x3392,
+ 0x74d6, 0x167d,
+ 0x74d7, 0x3394,
+ 0x74d8, 0x3391,
+ 0x74d9, 0x3393,
+ 0x74da, 0x16fe,
+ 0x74db, 0x348d,
+ 0x74dc, 0x0358,
+ 0x74dd, 0x1a0d,
+ 0x74de, 0x1d4a,
+ 0x74e0, 0x0b26,
+ 0x74e1, 0x24a8,
+ 0x74e2, 0x12ff,
+ 0x74e3, 0x1599,
+ 0x74e4, 0x16cb,
+ 0x74e5, 0x348e,
+ 0x74e6, 0x0359,
+ 0x74e7, 0x3ffe,
+ 0x74e8, 0x1a0e,
+ 0x74e9, 0x0120,
+ 0x74ec, 0x1b8e,
+ 0x74ee, 0x1b8f,
+ 0x74f0, 0x3fe6,
+ 0x74f1, 0x3f9b,
+ 0x74f2, 0x3fdf,
+ 0x74f4, 0x1d4c,
+ 0x74f6, 0x0b27,
+ 0x74f8, 0x3ff4,
+ 0x74fb, 0x2220,
+ 0x74fd, 0x24ab,
+ 0x74fe, 0x24aa,
+ 0x74ff, 0x24a9,
+ 0x7500, 0x2732,
+ 0x7502, 0x2733,
+ 0x7504, 0x1031,
+ 0x7505, 0x3fde,
+ 0x7507, 0x297e,
+ 0x7508, 0x297d,
+ 0x750b, 0x2bd2,
+ 0x750c, 0x1300,
+ 0x750e, 0x42b7,
+ 0x750f, 0x2db1,
+ 0x7510, 0x2dae,
+ 0x7513, 0x2f5f,
+ 0x7514, 0x2f5e,
+ 0x7515, 0x14f6,
+ 0x7516, 0x30c4,
+ 0x7517, 0x32e3,
+ 0x7518, 0x035a,
+ 0x7519, 0x4583,
+ 0x751a, 0x079f,
+ 0x751c, 0x0b29,
+ 0x751d, 0x24ac,
+ 0x751e, 0x42b8,
+ 0x751f, 0x035b,
+ 0x7521, 0x1d4e,
+ 0x7522, 0x0b2a,
+ 0x7525, 0x0ce3,
+ 0x7528, 0x035c,
+ 0x752a, 0x180f,
+ 0x752b, 0x04f1,
+ 0x752c, 0x04f0,
+ 0x752d, 0x07a0,
+ 0x752e, 0x1b90,
+ 0x752f, 0x2221,
+ 0x7530, 0x035e,
+ 0x7534, 0x3e87,
+ 0x7535, 0x455a,
+ 0x7537, 0x04f2,
+ 0x7539, 0x18d3,
+ 0x753a, 0x18d2,
+ 0x753b, 0x3dfb,
+ 0x753d, 0x0655,
+ 0x753e, 0x1a11,
+ 0x753f, 0x1a0f,
+ 0x7542, 0x43cd,
+ 0x7546, 0x3f40,
+ 0x7547, 0x1b91,
+ 0x754a, 0x42bf,
+ 0x754b, 0x07a4,
+ 0x754c, 0x07a2,
+ 0x754d, 0x42be,
+ 0x754e, 0x07a3,
+ 0x754f, 0x07a1,
+ 0x7551, 0x3cfe,
+ 0x7553, 0x3feb,
+ 0x7554, 0x0931,
+ 0x7555, 0x3aea,
+ 0x7559, 0x0935,
+ 0x755a, 0x0934,
+ 0x755b, 0x1d4f,
+ 0x755c, 0x0933,
+ 0x755d, 0x0932,
+ 0x755f, 0x1d50,
+ 0x7560, 0x3d71,
+ 0x7562, 0x0b2d,
+ 0x7563, 0x1f9f,
+ 0x7564, 0x1f9e,
+ 0x7565, 0x0b2b,
+ 0x7567, 0x42c0,
+ 0x756a, 0x0ce6,
+ 0x756b, 0x0ce5,
+ 0x756c, 0x2223,
+ 0x756d, 0x46fd,
+ 0x756e, 0x42c1,
+ 0x756f, 0x2222,
+ 0x7570, 0x0b2e,
+ 0x7572, 0x46fe,
+ 0x7576, 0x0e85,
+ 0x7577, 0x24ae,
+ 0x7578, 0x0e86,
+ 0x7579, 0x24ad,
+ 0x757a, 0x3f4f,
+ 0x757d, 0x2735,
+ 0x757e, 0x297f,
+ 0x757f, 0x11ab,
+ 0x7580, 0x2bd3,
+ 0x7583, 0x3ae5,
+ 0x7584, 0x2db2,
+ 0x7586, 0x159b,
+ 0x7587, 0x159a,
+ 0x758a, 0x16cc,
+ 0x758b, 0x0362,
+ 0x758c, 0x1a12,
+ 0x758d, 0x46ff,
+ 0x758e, 0x42c5,
+ 0x758f, 0x0b2f,
+ 0x7590, 0x2736,
+ 0x7591, 0x1032,
+ 0x7592, 0x022e,
+ 0x7594, 0x18d4,
+ 0x7598, 0x1a13,
+ 0x7599, 0x0657,
+ 0x759d, 0x0656,
+ 0x759e, 0x42c7,
+ 0x75a2, 0x07a8,
+ 0x75a4, 0x07a6,
+ 0x75a7, 0x1b93,
+ 0x75aa, 0x1b94,
+ 0x75ab, 0x07a5,
+ 0x75b0, 0x1d51,
+ 0x75b1, 0x3ead,
+ 0x75b2, 0x0939,
+ 0x75b4, 0x42c8,
+ 0x75b5, 0x0b32,
+ 0x75b6, 0x1d57,
+ 0x75b8, 0x093f,
+ 0x75b9, 0x093d,
+ 0x75ba, 0x1d58,
+ 0x75bb, 0x1d53,
+ 0x75bc, 0x093c,
+ 0x75bd, 0x093b,
+ 0x75be, 0x0936,
+ 0x75bf, 0x1d56,
+ 0x75c0, 0x1d55,
+ 0x75c1, 0x1d52,
+ 0x75c2, 0x093e,
+ 0x75c3, 0x3f93,
+ 0x75c4, 0x1d54,
+ 0x75c5, 0x0937,
+ 0x75c7, 0x0938,
+ 0x75c8, 0x4701,
+ 0x75ca, 0x0b33,
+ 0x75cb, 0x1fa3,
+ 0x75cd, 0x0b34,
+ 0x75ce, 0x1fa0,
+ 0x75cf, 0x1fa2,
+ 0x75d0, 0x1fa6,
+ 0x75d1, 0x1fa5,
+ 0x75d2, 0x1fa1,
+ 0x75d4, 0x0b30,
+ 0x75d7, 0x222b,
+ 0x75d8, 0x0ceb,
+ 0x75d9, 0x0cea,
+ 0x75da, 0x2225,
+ 0x75db, 0x0ce8,
+ 0x75dc, 0x43ce,
+ 0x75dd, 0x2228,
+ 0x75de, 0x0cec,
+ 0x75df, 0x2229,
+ 0x75e0, 0x0ced,
+ 0x75e1, 0x2226,
+ 0x75e2, 0x0ce7,
+ 0x75e3, 0x0ce9,
+ 0x75e4, 0x222a,
+ 0x75e6, 0x2227,
+ 0x75e7, 0x2224,
+ 0x75ed, 0x24bb,
+ 0x75ef, 0x24b0,
+ 0x75f0, 0x0e88,
+ 0x75f1, 0x0e8b,
+ 0x75f2, 0x0e8a,
+ 0x75f3, 0x0e8f,
+ 0x75f4, 0x0e8e,
+ 0x75f5, 0x24bc,
+ 0x75f6, 0x24ba,
+ 0x75f7, 0x24b3,
+ 0x75f8, 0x24b7,
+ 0x75f9, 0x24b6,
+ 0x75fa, 0x0e8c,
+ 0x75fb, 0x24b9,
+ 0x75fc, 0x24b5,
+ 0x75fd, 0x24bd,
+ 0x75fe, 0x24b4,
+ 0x75ff, 0x0e8d,
+ 0x7600, 0x0e87,
+ 0x7601, 0x0e89,
+ 0x7602, 0x42c9,
+ 0x7603, 0x24b2,
+ 0x7607, 0x3f8f,
+ 0x7608, 0x2738,
+ 0x7609, 0x1036,
+ 0x760a, 0x273c,
+ 0x760b, 0x1035,
+ 0x760c, 0x2739,
+ 0x760d, 0x1034,
+ 0x760f, 0x24b1,
+ 0x7610, 0x24b8,
+ 0x7611, 0x273b,
+ 0x7613, 0x1037,
+ 0x7614, 0x273d,
+ 0x7615, 0x273a,
+ 0x7616, 0x2737,
+ 0x7619, 0x2982,
+ 0x761a, 0x2986,
+ 0x761b, 0x2988,
+ 0x761c, 0x2984,
+ 0x761d, 0x2983,
+ 0x761e, 0x2981,
+ 0x761f, 0x11ae,
+ 0x7620, 0x11ac,
+ 0x7621, 0x11b1,
+ 0x7623, 0x2985,
+ 0x7624, 0x11af,
+ 0x7625, 0x2980,
+ 0x7626, 0x11b0,
+ 0x7627, 0x1033,
+ 0x7628, 0x2987,
+ 0x7629, 0x11ad,
+ 0x762c, 0x42ca,
+ 0x762d, 0x2bd5,
+ 0x762f, 0x2bd4,
+ 0x7630, 0x2bdc,
+ 0x7631, 0x2bd6,
+ 0x7632, 0x2bdb,
+ 0x7633, 0x2bd8,
+ 0x7634, 0x1302,
+ 0x7635, 0x2bda,
+ 0x7638, 0x1303,
+ 0x763a, 0x1304,
+ 0x763b, 0x3e70,
+ 0x763c, 0x2bd9,
+ 0x763d, 0x2bd7,
+ 0x7640, 0x3ee6,
+ 0x7642, 0x1415,
+ 0x7643, 0x2db3,
+ 0x7646, 0x1414,
+ 0x7647, 0x2db6,
+ 0x7648, 0x2db4,
+ 0x764c, 0x1416,
+ 0x764d, 0x4702,
+ 0x764e, 0x3e72,
+ 0x764f, 0x42cc,
+ 0x7650, 0x2f63,
+ 0x7651, 0x42cb,
+ 0x7652, 0x14f9,
+ 0x7653, 0x2f64,
+ 0x7654, 0x3ef0,
+ 0x7656, 0x14f7,
+ 0x7657, 0x2f65,
+ 0x7658, 0x14f8,
+ 0x7659, 0x2f62,
+ 0x765a, 0x2f66,
+ 0x765c, 0x2f60,
+ 0x765f, 0x159c,
+ 0x7660, 0x30c5,
+ 0x7661, 0x159d,
+ 0x7662, 0x1622,
+ 0x7664, 0x2f61,
+ 0x7665, 0x1623,
+ 0x7666, 0x3eaa,
+ 0x7667, 0x3fa9,
+ 0x7669, 0x167f,
+ 0x766a, 0x32e4,
+ 0x766c, 0x16ce,
+ 0x766d, 0x3395,
+ 0x766e, 0x16cd,
+ 0x766f, 0x42cd,
+ 0x7670, 0x3428,
+ 0x7671, 0x1723,
+ 0x7673, 0x3aeb,
+ 0x7674, 0x4703,
+ 0x7675, 0x3543,
+ 0x7676, 0x022f,
+ 0x7678, 0x07aa,
+ 0x7679, 0x1b95,
+ 0x767a, 0x4705,
+ 0x767b, 0x0cee,
+ 0x767d, 0x0363,
+ 0x767e, 0x03f5,
+ 0x767f, 0x1810,
+ 0x7680, 0x43d3,
+ 0x7681, 0x18d6,
+ 0x7682, 0x04f4,
+ 0x7684, 0x0659,
+ 0x7686, 0x07ab,
+ 0x7689, 0x1fa8,
+ 0x768a, 0x1d59,
+ 0x768b, 0x0940,
+ 0x768c, 0x43d4,
+ 0x768e, 0x0b35,
+ 0x768f, 0x1fa7,
+ 0x7690, 0x42d0,
+ 0x7692, 0x222d,
+ 0x7693, 0x0cf1,
+ 0x7695, 0x222c,
+ 0x7696, 0x0cf0,
+ 0x7699, 0x24be,
+ 0x769a, 0x11b3,
+ 0x769b, 0x298c,
+ 0x769c, 0x2989,
+ 0x76a1, 0x42d5,
+ 0x76a4, 0x2db7,
+ 0x76a5, 0x42d6,
+ 0x76a6, 0x2f67,
+ 0x76aa, 0x31fb,
+ 0x76ab, 0x31fa,
+ 0x76ad, 0x3396,
+ 0x76ae, 0x0364,
+ 0x76af, 0x1a14,
+ 0x76b0, 0x0941,
+ 0x76b4, 0x0cf2,
+ 0x76b5, 0x24bf,
+ 0x76b7, 0x42d7,
+ 0x76b8, 0x273e,
+ 0x76ba, 0x11b4,
+ 0x76bb, 0x2bdd,
+ 0x76bd, 0x2f68,
+ 0x76be, 0x31fc,
+ 0x76bf, 0x0365,
+ 0x76c2, 0x065a,
+ 0x76c3, 0x07b0,
+ 0x76c4, 0x1b96,
+ 0x76c5, 0x07b1,
+ 0x76c6, 0x07af,
+ 0x76c8, 0x07ae,
+ 0x76c9, 0x1d5a,
+ 0x76ca, 0x0942,
+ 0x76cc, 0x42d8,
+ 0x76cd, 0x0943,
+ 0x76d2, 0x0b37,
+ 0x76d3, 0x1fa9,
+ 0x76d4, 0x0b36,
+ 0x76d6, 0x3f55,
+ 0x76da, 0x222e,
+ 0x76db, 0x0b38,
+ 0x76dc, 0x0cf3,
+ 0x76dd, 0x24c0,
+ 0x76de, 0x0e90,
+ 0x76e1, 0x1038,
+ 0x76e3, 0x1039,
+ 0x76e4, 0x11b5,
+ 0x76e5, 0x1306,
+ 0x76e6, 0x2bde,
+ 0x76e7, 0x1305,
+ 0x76e9, 0x2db8,
+ 0x76ea, 0x1417,
+ 0x76ec, 0x2f69,
+ 0x76ed, 0x31fd,
+ 0x76ee, 0x0366,
+ 0x76ef, 0x04f5,
+ 0x76f0, 0x1a17,
+ 0x76f1, 0x1a16,
+ 0x76f2, 0x065b,
+ 0x76f3, 0x1a15,
+ 0x76f4, 0x065c,
+ 0x76f5, 0x1a18,
+ 0x76f7, 0x1b9c,
+ 0x76f8, 0x07b4,
+ 0x76f9, 0x07b3,
+ 0x76fa, 0x1b9e,
+ 0x76fb, 0x1b9d,
+ 0x76fc, 0x07b8,
+ 0x76fe, 0x07b7,
+ 0x7701, 0x07b2,
+ 0x7703, 0x1b98,
+ 0x7707, 0x07b9,
+ 0x7708, 0x1b97,
+ 0x7709, 0x07b5,
+ 0x770a, 0x1b9b,
+ 0x770b, 0x07b6,
+ 0x770c, 0x3d62,
+ 0x770e, 0x3b02,
+ 0x7710, 0x1d5d,
+ 0x7711, 0x1d61,
+ 0x7712, 0x1d5f,
+ 0x7713, 0x1d5e,
+ 0x7715, 0x1d62,
+ 0x7719, 0x1d63,
+ 0x771b, 0x1d5c,
+ 0x771d, 0x1d5b,
+ 0x771e, 0x42de,
+ 0x771f, 0x0946,
+ 0x7722, 0x1d65,
+ 0x7723, 0x1d60,
+ 0x7724, 0x3fe8,
+ 0x7725, 0x1fb2,
+ 0x7726, 0x42df,
+ 0x7727, 0x1d66,
+ 0x7728, 0x0948,
+ 0x7729, 0x0945,
+ 0x772b, 0x3ff3,
+ 0x772d, 0x1fac,
+ 0x772f, 0x1fab,
+ 0x7731, 0x1fad,
+ 0x7733, 0x1fb0,
+ 0x7734, 0x1faf,
+ 0x7735, 0x1fb4,
+ 0x7736, 0x0b3c,
+ 0x7737, 0x0b39,
+ 0x7738, 0x0b3d,
+ 0x7739, 0x1faa,
+ 0x773a, 0x0b3e,
+ 0x773b, 0x1fb3,
+ 0x773c, 0x0b3b,
+ 0x773d, 0x1fb1,
+ 0x773e, 0x0b3a,
+ 0x7740, 0x42e0,
+ 0x7743, 0x470a,
+ 0x7744, 0x2231,
+ 0x7745, 0x2233,
+ 0x7746, 0x222f,
+ 0x774a, 0x2234,
+ 0x774b, 0x2236,
+ 0x774d, 0x2232,
+ 0x774e, 0x2235,
+ 0x774f, 0x0cf4,
+ 0x7752, 0x24c4,
+ 0x7754, 0x24c9,
+ 0x7755, 0x24c1,
+ 0x7756, 0x24c5,
+ 0x7758, 0x42e3,
+ 0x7759, 0x24ca,
+ 0x775a, 0x24c6,
+ 0x775b, 0x0e92,
+ 0x775c, 0x0e9a,
+ 0x775e, 0x0e95,
+ 0x775f, 0x24c2,
+ 0x7761, 0x103d,
+ 0x7762, 0x0e9d,
+ 0x7763, 0x0e96,
+ 0x7765, 0x0e9b,
+ 0x7766, 0x0e94,
+ 0x7767, 0x24c8,
+ 0x7768, 0x0e9c,
+ 0x7769, 0x24c7,
+ 0x776a, 0x0e98,
+ 0x776b, 0x0e93,
+ 0x776c, 0x0e99,
+ 0x776d, 0x24cb,
+ 0x776e, 0x2743,
+ 0x776f, 0x2745,
+ 0x7772, 0x396b,
+ 0x7777, 0x46a9,
+ 0x7778, 0x3b00,
+ 0x7779, 0x0e97,
+ 0x777a, 0x4317,
+ 0x777b, 0x3b04,
+ 0x777c, 0x2740,
+ 0x777d, 0x103b,
+ 0x777e, 0x2746,
+ 0x777f, 0x103c,
+ 0x7780, 0x2744,
+ 0x7781, 0x273f,
+ 0x7782, 0x2742,
+ 0x7783, 0x2747,
+ 0x7784, 0x103a,
+ 0x7785, 0x2741,
+ 0x7787, 0x11b7,
+ 0x7788, 0x2990,
+ 0x7789, 0x298f,
+ 0x778b, 0x11ba,
+ 0x778c, 0x11b8,
+ 0x778d, 0x298d,
+ 0x778e, 0x11b6,
+ 0x778f, 0x298e,
+ 0x7791, 0x11b9,
+ 0x7793, 0x382d,
+ 0x7795, 0x2be6,
+ 0x7797, 0x2be8,
+ 0x7798, 0x470e,
+ 0x7799, 0x2be7,
+ 0x779a, 0x2bdf,
+ 0x779b, 0x2be3,
+ 0x779c, 0x2be2,
+ 0x779d, 0x2be0,
+ 0x779e, 0x1308,
+ 0x77a0, 0x1307,
+ 0x77a1, 0x2be1,
+ 0x77a2, 0x2be4,
+ 0x77a5, 0x130a,
+ 0x77a7, 0x141c,
+ 0x77a8, 0x2dc0,
+ 0x77aa, 0x1419,
+ 0x77ab, 0x2dba,
+ 0x77ac, 0x141b,
+ 0x77ad, 0x141d,
+ 0x77af, 0x42e5,
+ 0x77b0, 0x141a,
+ 0x77b1, 0x2dbf,
+ 0x77b2, 0x2dbb,
+ 0x77b3, 0x1418,
+ 0x77b4, 0x2dbe,
+ 0x77b5, 0x2db9,
+ 0x77b6, 0x2dbd,
+ 0x77b7, 0x2dbc,
+ 0x77b9, 0x3e73,
+ 0x77ba, 0x2f6b,
+ 0x77bb, 0x14fc,
+ 0x77bd, 0x14fa,
+ 0x77be, 0x4711,
+ 0x77bf, 0x14fb,
+ 0x77c2, 0x2f6a,
+ 0x77c3, 0x3bb1,
+ 0x77c4, 0x30c8,
+ 0x77c5, 0x41c1,
+ 0x77c7, 0x159e,
+ 0x77c9, 0x30c6,
+ 0x77cb, 0x4712,
+ 0x77cc, 0x31fe,
+ 0x77cd, 0x3201,
+ 0x77ce, 0x31ff,
+ 0x77d0, 0x32e5,
+ 0x77d3, 0x1680,
+ 0x77d4, 0x3429,
+ 0x77d5, 0x348f,
+ 0x77d7, 0x1725,
+ 0x77d8, 0x34d3,
+ 0x77da, 0x1753,
+ 0x77db, 0x0367,
+ 0x77dc, 0x07ba,
+ 0x77de, 0x2238,
+ 0x77e0, 0x24cc,
+ 0x77e2, 0x0368,
+ 0x77e3, 0x04f6,
+ 0x77e5, 0x065d,
+ 0x77e6, 0x4081,
+ 0x77e7, 0x1b9f,
+ 0x77e9, 0x0949,
+ 0x77ec, 0x2239,
+ 0x77ed, 0x0cf5,
+ 0x77ee, 0x0e9e,
+ 0x77ef, 0x141e,
+ 0x77f0, 0x2dc1,
+ 0x77f1, 0x30c9,
+ 0x77f2, 0x3202,
+ 0x77f3, 0x0369,
+ 0x77f4, 0x42e9,
+ 0x77f7, 0x1a1e,
+ 0x77f8, 0x1a19,
+ 0x77f9, 0x1a1b,
+ 0x77fa, 0x1a1d,
+ 0x77fb, 0x1a1c,
+ 0x77fc, 0x1a1a,
+ 0x77fd, 0x065e,
+ 0x77fe, 0x3fd5,
+ 0x7802, 0x07bb,
+ 0x7803, 0x1ba9,
+ 0x7805, 0x1ba4,
+ 0x7806, 0x1ba1,
+ 0x7808, 0x3e46,
+ 0x7809, 0x1ba8,
+ 0x780c, 0x07bd,
+ 0x780e, 0x1ba7,
+ 0x780f, 0x1ba6,
+ 0x7810, 0x1ba5,
+ 0x7811, 0x1ba2,
+ 0x7813, 0x1baa,
+ 0x7814, 0x07bc,
+ 0x7818, 0x4713,
+ 0x781c, 0x4714,
+ 0x781d, 0x094d,
+ 0x781e, 0x3b13,
+ 0x781f, 0x0953,
+ 0x7820, 0x0952,
+ 0x7821, 0x1d6f,
+ 0x7822, 0x1d69,
+ 0x7823, 0x1d67,
+ 0x7825, 0x0950,
+ 0x7826, 0x1fbb,
+ 0x7827, 0x094b,
+ 0x7828, 0x1d6c,
+ 0x7829, 0x1d70,
+ 0x782a, 0x1d72,
+ 0x782b, 0x1d6e,
+ 0x782c, 0x1d68,
+ 0x782d, 0x0951,
+ 0x782e, 0x1d6d,
+ 0x782f, 0x1d6b,
+ 0x7830, 0x094a,
+ 0x7831, 0x1d73,
+ 0x7832, 0x0954,
+ 0x7833, 0x1d71,
+ 0x7834, 0x094e,
+ 0x7835, 0x1d6a,
+ 0x7837, 0x094f,
+ 0x7838, 0x094c,
+ 0x7839, 0x43d6,
+ 0x783c, 0x401a,
+ 0x783d, 0x3c6a,
+ 0x7842, 0x3ac4,
+ 0x7843, 0x0b40,
+ 0x7844, 0x3c2b,
+ 0x7845, 0x1fbc,
+ 0x7847, 0x4715,
+ 0x7848, 0x1fb5,
+ 0x7849, 0x1fb7,
+ 0x784a, 0x1fb9,
+ 0x784b, 0x3c6d,
+ 0x784c, 0x1fba,
+ 0x784d, 0x1fb8,
+ 0x784e, 0x0b41,
+ 0x7850, 0x1fbd,
+ 0x7851, 0x4716,
+ 0x7852, 0x1fb6,
+ 0x7853, 0x3f95,
+ 0x7854, 0x3c6b,
+ 0x785c, 0x223d,
+ 0x785d, 0x0cf6,
+ 0x785e, 0x2245,
+ 0x7860, 0x223a,
+ 0x7862, 0x2246,
+ 0x7864, 0x223b,
+ 0x7866, 0x4717,
+ 0x7868, 0x2244,
+ 0x7869, 0x2243,
+ 0x786a, 0x2240,
+ 0x786b, 0x0b3f,
+ 0x786c, 0x0cf7,
+ 0x786d, 0x223e,
+ 0x786e, 0x2241,
+ 0x786f, 0x0cf8,
+ 0x7870, 0x2242,
+ 0x7871, 0x223f,
+ 0x7879, 0x24d7,
+ 0x787a, 0x3ee9,
+ 0x787b, 0x24db,
+ 0x787c, 0x0ea5,
+ 0x787e, 0x274d,
+ 0x787f, 0x0ea8,
+ 0x7880, 0x24d9,
+ 0x7881, 0x36e8,
+ 0x7883, 0x24d6,
+ 0x7884, 0x24d1,
+ 0x7885, 0x24d3,
+ 0x7887, 0x24cd,
+ 0x7888, 0x3b15,
+ 0x7889, 0x0ea4,
+ 0x788c, 0x0ea3,
+ 0x788d, 0x3b14,
+ 0x788e, 0x0e9f,
+ 0x788f, 0x24d0,
+ 0x7891, 0x0ea6,
+ 0x7893, 0x0ea7,
+ 0x7894, 0x24cf,
+ 0x7895, 0x24d2,
+ 0x7896, 0x24da,
+ 0x7897, 0x0ea1,
+ 0x7899, 0x24d8,
+ 0x789a, 0x24ce,
+ 0x789e, 0x274f,
+ 0x789f, 0x103f,
+ 0x78a0, 0x2751,
+ 0x78a1, 0x24d5,
+ 0x78a2, 0x2753,
+ 0x78a3, 0x1043,
+ 0x78a4, 0x2754,
+ 0x78a5, 0x2750,
+ 0x78a7, 0x1040,
+ 0x78a8, 0x274c,
+ 0x78a9, 0x1042,
+ 0x78aa, 0x2749,
+ 0x78ab, 0x274e,
+ 0x78ac, 0x2752,
+ 0x78ad, 0x274b,
+ 0x78af, 0x42ec,
+ 0x78b0, 0x0ea0,
+ 0x78b1, 0x42f4,
+ 0x78b2, 0x2748,
+ 0x78b3, 0x1041,
+ 0x78b4, 0x274a,
+ 0x78b6, 0x3c6c,
+ 0x78b8, 0x4571,
+ 0x78b9, 0x3c63,
+ 0x78ba, 0x11bd,
+ 0x78bb, 0x2992,
+ 0x78bc, 0x11c1,
+ 0x78be, 0x11bf,
+ 0x78c1, 0x103e,
+ 0x78c3, 0x2999,
+ 0x78c5, 0x11bc,
+ 0x78c7, 0x42ed,
+ 0x78c8, 0x2998,
+ 0x78c9, 0x299b,
+ 0x78ca, 0x11be,
+ 0x78cb, 0x11bb,
+ 0x78cc, 0x2994,
+ 0x78cd, 0x2991,
+ 0x78ce, 0x2996,
+ 0x78cf, 0x2993,
+ 0x78d0, 0x11c2,
+ 0x78d1, 0x2995,
+ 0x78d2, 0x3b16,
+ 0x78d3, 0x42ee,
+ 0x78d4, 0x2997,
+ 0x78d5, 0x11c0,
+ 0x78d7, 0x42f2,
+ 0x78d8, 0x3f8c,
+ 0x78da, 0x130c,
+ 0x78db, 0x2bef,
+ 0x78dd, 0x2be9,
+ 0x78de, 0x2bed,
+ 0x78df, 0x2bf3,
+ 0x78e1, 0x2bf0,
+ 0x78e3, 0x2bee,
+ 0x78e5, 0x2beb,
+ 0x78e7, 0x130e,
+ 0x78e8, 0x130b,
+ 0x78e9, 0x2bea,
+ 0x78ea, 0x2bec,
+ 0x78ec, 0x130d,
+ 0x78ed, 0x2bf2,
+ 0x78ee, 0x3a81,
+ 0x78ef, 0x1422,
+ 0x78f0, 0x3b3a,
+ 0x78f1, 0x40be,
+ 0x78f2, 0x2dc8,
+ 0x78f3, 0x2dc2,
+ 0x78f4, 0x1421,
+ 0x78f5, 0x38b3,
+ 0x78f7, 0x141f,
+ 0x78f9, 0x2dca,
+ 0x78fa, 0x1420,
+ 0x78fb, 0x2dc5,
+ 0x78fd, 0x2dc3,
+ 0x78fe, 0x2dcb,
+ 0x78ff, 0x2dc7,
+ 0x7901, 0x1423,
+ 0x7902, 0x2dc4,
+ 0x7904, 0x2dcc,
+ 0x7905, 0x2dc9,
+ 0x7906, 0x3fcf,
+ 0x7909, 0x2f6f,
+ 0x790c, 0x2f6c,
+ 0x790e, 0x14fe,
+ 0x7910, 0x2f70,
+ 0x7911, 0x2f72,
+ 0x7912, 0x2f71,
+ 0x7913, 0x2f6d,
+ 0x7917, 0x30ce,
+ 0x7919, 0x159f,
+ 0x791b, 0x30cb,
+ 0x791c, 0x30cd,
+ 0x791d, 0x30ca,
+ 0x791e, 0x30cf,
+ 0x7921, 0x30cc,
+ 0x7923, 0x3204,
+ 0x7924, 0x3207,
+ 0x7925, 0x3203,
+ 0x7926, 0x1624,
+ 0x7927, 0x3205,
+ 0x7929, 0x3208,
+ 0x792a, 0x1625,
+ 0x792b, 0x1627,
+ 0x792c, 0x1626,
+ 0x792d, 0x32e6,
+ 0x792e, 0x42f0,
+ 0x792f, 0x32e8,
+ 0x7931, 0x32e7,
+ 0x7932, 0x471b,
+ 0x7933, 0x471a,
+ 0x7934, 0x42f3,
+ 0x7935, 0x3397,
+ 0x7936, 0x3783,
+ 0x7938, 0x3490,
+ 0x7939, 0x34d5,
+ 0x793a, 0x036a,
+ 0x793b, 0x44f7,
+ 0x793c, 0x4300,
+ 0x793d, 0x18d7,
+ 0x793e, 0x065f,
+ 0x793f, 0x1a20,
+ 0x7940, 0x0660,
+ 0x7942, 0x1a1f,
+ 0x7944, 0x1baf,
+ 0x7945, 0x1bae,
+ 0x7946, 0x07bf,
+ 0x7947, 0x07c2,
+ 0x7948, 0x07c1,
+ 0x7949, 0x07c0,
+ 0x794a, 0x1bab,
+ 0x794b, 0x1bad,
+ 0x794c, 0x1bac,
+ 0x794f, 0x1d76,
+ 0x7950, 0x0956,
+ 0x7951, 0x1d7a,
+ 0x7952, 0x1d79,
+ 0x7953, 0x1d78,
+ 0x7954, 0x1d74,
+ 0x7955, 0x0955,
+ 0x7956, 0x0959,
+ 0x7957, 0x095c,
+ 0x7958, 0x37e5,
+ 0x7959, 0x3b18,
+ 0x795a, 0x095d,
+ 0x795b, 0x1d75,
+ 0x795c, 0x1d77,
+ 0x795d, 0x095b,
+ 0x795e, 0x095a,
+ 0x795f, 0x0958,
+ 0x7960, 0x0957,
+ 0x7961, 0x1fc4,
+ 0x7962, 0x3e7d,
+ 0x7963, 0x1fc2,
+ 0x7964, 0x1fbe,
+ 0x7965, 0x0b42,
+ 0x7967, 0x1fbf,
+ 0x7968, 0x0b43,
+ 0x7969, 0x1fc0,
+ 0x796b, 0x1fc3,
+ 0x796d, 0x0b44,
+ 0x7970, 0x224a,
+ 0x7971, 0x4168,
+ 0x7972, 0x2249,
+ 0x7973, 0x2248,
+ 0x7974, 0x2247,
+ 0x7979, 0x24df,
+ 0x797a, 0x0ea9,
+ 0x797c, 0x24dc,
+ 0x797d, 0x24de,
+ 0x797e, 0x3e26,
+ 0x797f, 0x0eaa,
+ 0x7980, 0x42fc,
+ 0x7981, 0x0eab,
+ 0x7982, 0x24dd,
+ 0x7983, 0x3df6,
+ 0x7986, 0x42f9,
+ 0x7987, 0x4588,
+ 0x7988, 0x275d,
+ 0x798a, 0x2756,
+ 0x798d, 0x1046,
+ 0x798e, 0x1044,
+ 0x7990, 0x275f,
+ 0x7991, 0x471d,
+ 0x7992, 0x275e,
+ 0x7993, 0x275b,
+ 0x7994, 0x275a,
+ 0x7995, 0x2759,
+ 0x7996, 0x2758,
+ 0x7997, 0x275c,
+ 0x7998, 0x2755,
+ 0x7999, 0x43fc,
+ 0x799a, 0x299c,
+ 0x799b, 0x29a1,
+ 0x799c, 0x299f,
+ 0x799d, 0x42fe,
+ 0x799f, 0x395e,
+ 0x79a0, 0x299e,
+ 0x79a1, 0x299d,
+ 0x79a2, 0x29a0,
+ 0x79a4, 0x2bf5,
+ 0x79a5, 0x3b1e,
+ 0x79a6, 0x130f,
+ 0x79a7, 0x1424,
+ 0x79a8, 0x2dce,
+ 0x79a9, 0x4301,
+ 0x79aa, 0x1425,
+ 0x79ab, 0x2dcd,
+ 0x79ac, 0x2f74,
+ 0x79ad, 0x2f73,
+ 0x79ae, 0x14ff,
+ 0x79b0, 0x30d0,
+ 0x79b1, 0x15a0,
+ 0x79b2, 0x3209,
+ 0x79b3, 0x16cf,
+ 0x79b4, 0x3398,
+ 0x79b6, 0x3492,
+ 0x79b7, 0x3491,
+ 0x79b8, 0x17b2,
+ 0x79b9, 0x07c3,
+ 0x79bb, 0x1fc5,
+ 0x79bd, 0x0ead,
+ 0x79be, 0x036b,
+ 0x79bf, 0x04f9,
+ 0x79c0, 0x04f8,
+ 0x79c1, 0x04f7,
+ 0x79c4, 0x3ccd,
+ 0x79c5, 0x1a21,
+ 0x79c6, 0x4305,
+ 0x79c8, 0x0663,
+ 0x79c9, 0x0662,
+ 0x79cb, 0x07c7,
+ 0x79cc, 0x4233,
+ 0x79cd, 0x1bb1,
+ 0x79ce, 0x1bb4,
+ 0x79cf, 0x1bb2,
+ 0x79d1, 0x07c5,
+ 0x79d4, 0x4307,
+ 0x79d5, 0x1bb0,
+ 0x79d6, 0x1bb3,
+ 0x79d8, 0x0964,
+ 0x79dc, 0x1d81,
+ 0x79dd, 0x1d83,
+ 0x79de, 0x1d82,
+ 0x79df, 0x0961,
+ 0x79e0, 0x1d7d,
+ 0x79e2, 0x3c5a,
+ 0x79e3, 0x095f,
+ 0x79e4, 0x095e,
+ 0x79e6, 0x0962,
+ 0x79e7, 0x0960,
+ 0x79e9, 0x0963,
+ 0x79ea, 0x1d80,
+ 0x79eb, 0x1d7b,
+ 0x79ed, 0x1d7f,
+ 0x79ee, 0x1d7e,
+ 0x79f1, 0x3b27,
+ 0x79f4, 0x3b22,
+ 0x79f6, 0x1fc8,
+ 0x79f8, 0x1fc7,
+ 0x79fa, 0x1fc6,
+ 0x79fb, 0x0b45,
+ 0x7a00, 0x0cfd,
+ 0x7a02, 0x224b,
+ 0x7a03, 0x224d,
+ 0x7a04, 0x224f,
+ 0x7a05, 0x0cfc,
+ 0x7a06, 0x471e,
+ 0x7a08, 0x0cfa,
+ 0x7a0a, 0x224c,
+ 0x7a0b, 0x0cfb,
+ 0x7a0c, 0x224e,
+ 0x7a0d, 0x0cf9,
+ 0x7a10, 0x24e9,
+ 0x7a11, 0x24e0,
+ 0x7a12, 0x24e3,
+ 0x7a13, 0x24e7,
+ 0x7a14, 0x0eb1,
+ 0x7a15, 0x24e5,
+ 0x7a17, 0x24e4,
+ 0x7a18, 0x24e1,
+ 0x7a1a, 0x0eaf,
+ 0x7a1b, 0x24e8,
+ 0x7a1c, 0x0eae,
+ 0x7a1e, 0x0eb3,
+ 0x7a1f, 0x0eb2,
+ 0x7a20, 0x0eb0,
+ 0x7a22, 0x24e6,
+ 0x7a26, 0x2765,
+ 0x7a28, 0x2764,
+ 0x7a2b, 0x2760,
+ 0x7a2d, 0x3fda,
+ 0x7a2e, 0x1047,
+ 0x7a2f, 0x2763,
+ 0x7a30, 0x2762,
+ 0x7a31, 0x1048,
+ 0x7a37, 0x11c7,
+ 0x7a39, 0x29a3,
+ 0x7a3a, 0x3b21,
+ 0x7a3b, 0x11c8,
+ 0x7a3c, 0x11c4,
+ 0x7a3d, 0x11c6,
+ 0x7a3e, 0x3f8b,
+ 0x7a3f, 0x11c3,
+ 0x7a40, 0x11c5,
+ 0x7a43, 0x396c,
+ 0x7a44, 0x2bf6,
+ 0x7a45, 0x3df1,
+ 0x7a46, 0x1312,
+ 0x7a47, 0x2bf8,
+ 0x7a48, 0x2bf7,
+ 0x7a49, 0x3733,
+ 0x7a4a, 0x2761,
+ 0x7a4b, 0x1314,
+ 0x7a4c, 0x1313,
+ 0x7a4d, 0x1310,
+ 0x7a54, 0x2dd3,
+ 0x7a56, 0x2dd1,
+ 0x7a57, 0x1426,
+ 0x7a58, 0x2dd2,
+ 0x7a5a, 0x2dd4,
+ 0x7a5b, 0x2dd0,
+ 0x7a5c, 0x2dcf,
+ 0x7a5f, 0x2f75,
+ 0x7a60, 0x1502,
+ 0x7a61, 0x1500,
+ 0x7a65, 0x3736,
+ 0x7a67, 0x30d1,
+ 0x7a69, 0x15a2,
+ 0x7a6b, 0x15a1,
+ 0x7a6c, 0x320b,
+ 0x7a6e, 0x320a,
+ 0x7a70, 0x3399,
+ 0x7a74, 0x036c,
+ 0x7a75, 0x1811,
+ 0x7a76, 0x04fa,
+ 0x7a78, 0x1a22,
+ 0x7a79, 0x0665,
+ 0x7a7a, 0x0664,
+ 0x7a7b, 0x1a23,
+ 0x7a7d, 0x3737,
+ 0x7a7e, 0x1bb6,
+ 0x7a7f, 0x07c8,
+ 0x7a80, 0x1bb5,
+ 0x7a81, 0x07c9,
+ 0x7a83, 0x3d7d,
+ 0x7a84, 0x0965,
+ 0x7a85, 0x1d86,
+ 0x7a86, 0x1d84,
+ 0x7a87, 0x1d8a,
+ 0x7a88, 0x0966,
+ 0x7a89, 0x1d85,
+ 0x7a8a, 0x1d89,
+ 0x7a8b, 0x1d87,
+ 0x7a8f, 0x1fca,
+ 0x7a90, 0x1fcc,
+ 0x7a91, 0x43d8,
+ 0x7a92, 0x0b46,
+ 0x7a94, 0x1fcb,
+ 0x7a95, 0x0b47,
+ 0x7a96, 0x0d00,
+ 0x7a97, 0x0cff,
+ 0x7a98, 0x0cfe,
+ 0x7a99, 0x2250,
+ 0x7a9e, 0x24ec,
+ 0x7a9f, 0x0eb4,
+ 0x7aa2, 0x24eb,
+ 0x7aa3, 0x24ea,
+ 0x7aa8, 0x2766,
+ 0x7aa9, 0x104a,
+ 0x7aaa, 0x1049,
+ 0x7aab, 0x2767,
+ 0x7aae, 0x11ca,
+ 0x7aaf, 0x11c9,
+ 0x7ab0, 0x373a,
+ 0x7ab1, 0x2bfc,
+ 0x7ab2, 0x29a4,
+ 0x7ab3, 0x29a6,
+ 0x7ab4, 0x29a5,
+ 0x7ab5, 0x2bfb,
+ 0x7ab6, 0x2bf9,
+ 0x7ab7, 0x2bfd,
+ 0x7ab8, 0x2bfa,
+ 0x7aba, 0x1315,
+ 0x7abb, 0x3739,
+ 0x7abc, 0x4721,
+ 0x7abe, 0x2dd5,
+ 0x7abf, 0x1427,
+ 0x7ac0, 0x2dd6,
+ 0x7ac2, 0x373b,
+ 0x7ac4, 0x1503,
+ 0x7ac7, 0x1628,
+ 0x7ac8, 0x3d7f,
+ 0x7ac9, 0x4570,
+ 0x7aca, 0x16ff,
+ 0x7acb, 0x036d,
+ 0x7acf, 0x4724,
+ 0x7ad1, 0x1bb7,
+ 0x7ad3, 0x3f8a,
+ 0x7ad8, 0x1d8b,
+ 0x7ad9, 0x0967,
+ 0x7ada, 0x3740,
+ 0x7adb, 0x4725,
+ 0x7adc, 0x3951,
+ 0x7add, 0x3741,
+ 0x7adf, 0x0bde,
+ 0x7ae0, 0x0bdd,
+ 0x7ae2, 0x3b33,
+ 0x7ae3, 0x0d02,
+ 0x7ae4, 0x2252,
+ 0x7ae5, 0x0d01,
+ 0x7ae6, 0x2251,
+ 0x7ae7, 0x385d,
+ 0x7ae9, 0x3831,
+ 0x7aea, 0x3742,
+ 0x7aeb, 0x24ed,
+ 0x7aed, 0x104b,
+ 0x7aee, 0x2769,
+ 0x7aef, 0x104c,
+ 0x7af6, 0x1629,
+ 0x7af7, 0x320d,
+ 0x7af9, 0x03f6,
+ 0x7afa, 0x0666,
+ 0x7afb, 0x1a24,
+ 0x7afd, 0x07cb,
+ 0x7afe, 0x3b3d,
+ 0x7aff, 0x07ca,
+ 0x7b00, 0x1bb8,
+ 0x7b04, 0x1d8d,
+ 0x7b05, 0x1d8f,
+ 0x7b06, 0x0968,
+ 0x7b08, 0x1d91,
+ 0x7b09, 0x1d94,
+ 0x7b0a, 0x1d92,
+ 0x7b0b, 0x3746,
+ 0x7b0c, 0x3b63,
+ 0x7b0e, 0x1d93,
+ 0x7b0f, 0x1d90,
+ 0x7b10, 0x1d8c,
+ 0x7b11, 0x0969,
+ 0x7b12, 0x1d95,
+ 0x7b13, 0x1d8e,
+ 0x7b14, 0x3f77,
+ 0x7b18, 0x1fd5,
+ 0x7b19, 0x0b4d,
+ 0x7b1a, 0x1fde,
+ 0x7b1b, 0x0b4a,
+ 0x7b1d, 0x1fd7,
+ 0x7b1e, 0x0b4e,
+ 0x7b1f, 0x3f11,
+ 0x7b20, 0x0b48,
+ 0x7b22, 0x1fd2,
+ 0x7b23, 0x1fdf,
+ 0x7b24, 0x1fd3,
+ 0x7b25, 0x1fd0,
+ 0x7b26, 0x0b4c,
+ 0x7b27, 0x3b5f,
+ 0x7b28, 0x0b49,
+ 0x7b29, 0x3748,
+ 0x7b2a, 0x1fd6,
+ 0x7b2b, 0x1fd9,
+ 0x7b2c, 0x0b4b,
+ 0x7b2d, 0x1fda,
+ 0x7b2e, 0x0b4f,
+ 0x7b2f, 0x1fdb,
+ 0x7b30, 0x1fd1,
+ 0x7b31, 0x1fd8,
+ 0x7b32, 0x1fdc,
+ 0x7b33, 0x1fd4,
+ 0x7b34, 0x1fcf,
+ 0x7b35, 0x1fcd,
+ 0x7b38, 0x1fdd,
+ 0x7b39, 0x3d6e,
+ 0x7b3b, 0x1fce,
+ 0x7b40, 0x2259,
+ 0x7b42, 0x3ded,
+ 0x7b43, 0x3e25,
+ 0x7b44, 0x2255,
+ 0x7b45, 0x225b,
+ 0x7b46, 0x0d05,
+ 0x7b47, 0x2254,
+ 0x7b48, 0x2256,
+ 0x7b49, 0x0d03,
+ 0x7b4a, 0x2253,
+ 0x7b4b, 0x0d0a,
+ 0x7b4c, 0x2257,
+ 0x7b4d, 0x0d09,
+ 0x7b4e, 0x2258,
+ 0x7b4f, 0x0d0b,
+ 0x7b50, 0x0d06,
+ 0x7b51, 0x0d0c,
+ 0x7b52, 0x0d07,
+ 0x7b54, 0x0d08,
+ 0x7b55, 0x3747,
+ 0x7b56, 0x0d04,
+ 0x7b58, 0x225a,
+ 0x7b60, 0x0eb8,
+ 0x7b61, 0x24f8,
+ 0x7b62, 0x4727,
+ 0x7b63, 0x24fb,
+ 0x7b64, 0x24ef,
+ 0x7b65, 0x24f4,
+ 0x7b66, 0x24ee,
+ 0x7b67, 0x0eba,
+ 0x7b69, 0x24f2,
+ 0x7b6c, 0x4728,
+ 0x7b6d, 0x24f0,
+ 0x7b6e, 0x0eb9,
+ 0x7b6f, 0x374c,
+ 0x7b70, 0x24f7,
+ 0x7b71, 0x24f6,
+ 0x7b72, 0x24f3,
+ 0x7b73, 0x24f5,
+ 0x7b74, 0x24f1,
+ 0x7b75, 0x1050,
+ 0x7b76, 0x24fa,
+ 0x7b77, 0x0eb6,
+ 0x7b78, 0x24f9,
+ 0x7b7b, 0x4729,
+ 0x7b82, 0x2779,
+ 0x7b84, 0x1057,
+ 0x7b85, 0x2774,
+ 0x7b87, 0x1056,
+ 0x7b88, 0x276a,
+ 0x7b8a, 0x276c,
+ 0x7b8b, 0x104f,
+ 0x7b8c, 0x2771,
+ 0x7b8d, 0x2770,
+ 0x7b8e, 0x2773,
+ 0x7b8f, 0x1054,
+ 0x7b90, 0x276e,
+ 0x7b91, 0x276d,
+ 0x7b92, 0x3752,
+ 0x7b94, 0x1053,
+ 0x7b95, 0x104e,
+ 0x7b96, 0x276f,
+ 0x7b97, 0x1051,
+ 0x7b98, 0x2775,
+ 0x7b99, 0x2777,
+ 0x7b9b, 0x2772,
+ 0x7b9c, 0x276b,
+ 0x7b9d, 0x1052,
+ 0x7ba0, 0x11d2,
+ 0x7ba1, 0x104d,
+ 0x7ba2, 0x374b,
+ 0x7ba3, 0x3f14,
+ 0x7ba4, 0x2778,
+ 0x7bac, 0x29aa,
+ 0x7bad, 0x11cb,
+ 0x7baf, 0x29ac,
+ 0x7bb1, 0x11cc,
+ 0x7bb2, 0x461c,
+ 0x7bb4, 0x11ce,
+ 0x7bb5, 0x29af,
+ 0x7bb7, 0x29a7,
+ 0x7bb8, 0x1055,
+ 0x7bb9, 0x29ad,
+ 0x7bbe, 0x29a9,
+ 0x7bc0, 0x0eb7,
+ 0x7bc1, 0x11d1,
+ 0x7bc4, 0x11cd,
+ 0x7bc6, 0x11cf,
+ 0x7bc9, 0x1318,
+ 0x7bca, 0x29ae,
+ 0x7bcb, 0x29a8,
+ 0x7bcc, 0x11d3,
+ 0x7bce, 0x29ab,
+ 0x7bcf, 0x3f18,
+ 0x7bd0, 0x3750,
+ 0x7bd4, 0x2c07,
+ 0x7bd5, 0x2c02,
+ 0x7bd8, 0x2c0c,
+ 0x7bd9, 0x1316,
+ 0x7bda, 0x2c04,
+ 0x7bdb, 0x131a,
+ 0x7bdc, 0x2c0a,
+ 0x7bdd, 0x2c01,
+ 0x7bde, 0x2bfe,
+ 0x7bdf, 0x2c0d,
+ 0x7be0, 0x142d,
+ 0x7be1, 0x131b,
+ 0x7be2, 0x2c09,
+ 0x7be3, 0x2bff,
+ 0x7be4, 0x1319,
+ 0x7be5, 0x2c03,
+ 0x7be6, 0x131d,
+ 0x7be7, 0x2c00,
+ 0x7be8, 0x2c05,
+ 0x7be9, 0x131c,
+ 0x7bea, 0x2c08,
+ 0x7beb, 0x2c0b,
+ 0x7bf0, 0x2de9,
+ 0x7bf2, 0x2dda,
+ 0x7bf3, 0x2de1,
+ 0x7bf4, 0x2ddf,
+ 0x7bf7, 0x142b,
+ 0x7bf8, 0x2de6,
+ 0x7bf9, 0x2c06,
+ 0x7bfa, 0x3757,
+ 0x7bfb, 0x2ddd,
+ 0x7bfc, 0x3f1f,
+ 0x7bfd, 0x2de7,
+ 0x7bfe, 0x142a,
+ 0x7bff, 0x2ddc,
+ 0x7c00, 0x2ddb,
+ 0x7c01, 0x2de5,
+ 0x7c02, 0x2de2,
+ 0x7c03, 0x2de4,
+ 0x7c05, 0x2dd8,
+ 0x7c06, 0x2de8,
+ 0x7c07, 0x1428,
+ 0x7c09, 0x2de3,
+ 0x7c0a, 0x2dec,
+ 0x7c0b, 0x2de0,
+ 0x7c0c, 0x142c,
+ 0x7c0d, 0x1429,
+ 0x7c0e, 0x2dde,
+ 0x7c0f, 0x2dd9,
+ 0x7c10, 0x2deb,
+ 0x7c11, 0x1317,
+ 0x7c12, 0x472a,
+ 0x7c15, 0x4061,
+ 0x7c19, 0x2f78,
+ 0x7c1b, 0x43d9,
+ 0x7c1c, 0x2f76,
+ 0x7c1d, 0x2f7c,
+ 0x7c1e, 0x1508,
+ 0x7c1f, 0x2f7a,
+ 0x7c20, 0x2f79,
+ 0x7c21, 0x150a,
+ 0x7c22, 0x2f7f,
+ 0x7c23, 0x1509,
+ 0x7c25, 0x2f80,
+ 0x7c26, 0x2f7d,
+ 0x7c27, 0x1506,
+ 0x7c28, 0x2f7e,
+ 0x7c29, 0x2f77,
+ 0x7c2a, 0x1507,
+ 0x7c2b, 0x1505,
+ 0x7c2c, 0x30d6,
+ 0x7c2d, 0x2f7b,
+ 0x7c30, 0x2f81,
+ 0x7c33, 0x30d3,
+ 0x7c35, 0x3759,
+ 0x7c37, 0x15a7,
+ 0x7c38, 0x15a5,
+ 0x7c39, 0x30d5,
+ 0x7c3b, 0x30d7,
+ 0x7c3c, 0x30d4,
+ 0x7c3d, 0x15a6,
+ 0x7c3e, 0x15a3,
+ 0x7c40, 0x15a8,
+ 0x7c42, 0x3f1c,
+ 0x7c43, 0x162b,
+ 0x7c44, 0x375b,
+ 0x7c45, 0x3212,
+ 0x7c47, 0x3211,
+ 0x7c48, 0x320f,
+ 0x7c49, 0x320e,
+ 0x7c4a, 0x3210,
+ 0x7c4c, 0x162a,
+ 0x7c4d, 0x162c,
+ 0x7c50, 0x1681,
+ 0x7c51, 0x3fb8,
+ 0x7c53, 0x32ea,
+ 0x7c54, 0x32e9,
+ 0x7c56, 0x3eff,
+ 0x7c57, 0x339b,
+ 0x7c59, 0x339d,
+ 0x7c5a, 0x339f,
+ 0x7c5b, 0x339e,
+ 0x7c5c, 0x339c,
+ 0x7c5d, 0x3b3f,
+ 0x7c5f, 0x16d1,
+ 0x7c60, 0x16d0,
+ 0x7c63, 0x1701,
+ 0x7c64, 0x1700,
+ 0x7c65, 0x1702,
+ 0x7c66, 0x342b,
+ 0x7c67, 0x342a,
+ 0x7c69, 0x34d6,
+ 0x7c6a, 0x3493,
+ 0x7c6b, 0x34d7,
+ 0x7c6c, 0x1745,
+ 0x7c6d, 0x3b40,
+ 0x7c6e, 0x1746,
+ 0x7c6f, 0x3507,
+ 0x7c70, 0x3f52,
+ 0x7c72, 0x176b,
+ 0x7c73, 0x03f7,
+ 0x7c74, 0x469c,
+ 0x7c75, 0x1a25,
+ 0x7c78, 0x1bbb,
+ 0x7c7a, 0x1bba,
+ 0x7c7b, 0x472d,
+ 0x7c7c, 0x3b49,
+ 0x7c7d, 0x07cc,
+ 0x7c7e, 0x3f1a,
+ 0x7c7f, 0x1bbd,
+ 0x7c83, 0x375c,
+ 0x7c84, 0x1d96,
+ 0x7c85, 0x1d9c,
+ 0x7c86, 0x3f1d,
+ 0x7c88, 0x1d9a,
+ 0x7c89, 0x096a,
+ 0x7c8a, 0x1d98,
+ 0x7c8c, 0x1d99,
+ 0x7c8d, 0x1d9b,
+ 0x7c8e, 0x3b48,
+ 0x7c91, 0x1d97,
+ 0x7c92, 0x0b50,
+ 0x7c94, 0x1fe0,
+ 0x7c95, 0x0b52,
+ 0x7c96, 0x1fe2,
+ 0x7c97, 0x0b51,
+ 0x7c98, 0x1fe1,
+ 0x7c9c, 0x472e,
+ 0x7c9e, 0x225d,
+ 0x7c9f, 0x0d0d,
+ 0x7ca1, 0x225f,
+ 0x7ca2, 0x225c,
+ 0x7ca3, 0x1fe3,
+ 0x7ca5, 0x0d0e,
+ 0x7ca6, 0x375e,
+ 0x7ca7, 0x36ed,
+ 0x7ca8, 0x225e,
+ 0x7cac, 0x3885,
+ 0x7cae, 0x3b4a,
+ 0x7caf, 0x24fe,
+ 0x7cb1, 0x0ebb,
+ 0x7cb2, 0x24fc,
+ 0x7cb3, 0x0ebc,
+ 0x7cb4, 0x24fd,
+ 0x7cb5, 0x0ebd,
+ 0x7cb8, 0x4730,
+ 0x7cb9, 0x1058,
+ 0x7cba, 0x277d,
+ 0x7cbb, 0x277a,
+ 0x7cbc, 0x277c,
+ 0x7cbd, 0x1059,
+ 0x7cbf, 0x277b,
+ 0x7cc2, 0x3fd7,
+ 0x7cc5, 0x29b0,
+ 0x7cc7, 0x3761,
+ 0x7cc8, 0x29b1,
+ 0x7cc9, 0x3760,
+ 0x7cca, 0x11d4,
+ 0x7ccb, 0x29b3,
+ 0x7ccc, 0x29b2,
+ 0x7ccd, 0x3b45,
+ 0x7cce, 0x0121,
+ 0x7cd0, 0x2c11,
+ 0x7cd2, 0x2c0e,
+ 0x7cd3, 0x3d5c,
+ 0x7cd4, 0x2c0f,
+ 0x7cd5, 0x131e,
+ 0x7cd7, 0x2c10,
+ 0x7cd9, 0x1433,
+ 0x7cda, 0x3fd9,
+ 0x7cdc, 0x142f,
+ 0x7cdd, 0x1434,
+ 0x7cde, 0x1430,
+ 0x7cdf, 0x1432,
+ 0x7ce0, 0x142e,
+ 0x7ce2, 0x1431,
+ 0x7ce6, 0x3762,
+ 0x7ce7, 0x150b,
+ 0x7ce8, 0x2ded,
+ 0x7cea, 0x30d9,
+ 0x7cec, 0x30d8,
+ 0x7ced, 0x43da,
+ 0x7cee, 0x3213,
+ 0x7cef, 0x162d,
+ 0x7cf1, 0x33a1,
+ 0x7cf2, 0x32eb,
+ 0x7cf3, 0x3764,
+ 0x7cf4, 0x33a0,
+ 0x7cf5, 0x3765,
+ 0x7cf6, 0x34d8,
+ 0x7cf7, 0x351d,
+ 0x7cf8, 0x03f8,
+ 0x7cf9, 0x44f8,
+ 0x7cfb, 0x04fb,
+ 0x7cfc, 0x456d,
+ 0x7cfd, 0x1a26,
+ 0x7cfe, 0x0667,
+ 0x7d00, 0x07cf,
+ 0x7d01, 0x1bc2,
+ 0x7d02, 0x07cd,
+ 0x7d03, 0x1bc0,
+ 0x7d04, 0x07d2,
+ 0x7d05, 0x07ce,
+ 0x7d06, 0x07d3,
+ 0x7d07, 0x07d1,
+ 0x7d08, 0x1bc1,
+ 0x7d09, 0x07d0,
+ 0x7d0a, 0x096e,
+ 0x7d0b, 0x096d,
+ 0x7d0c, 0x1da7,
+ 0x7d0d, 0x0976,
+ 0x7d0e, 0x1da0,
+ 0x7d0f, 0x1da6,
+ 0x7d10, 0x0972,
+ 0x7d11, 0x1d9f,
+ 0x7d12, 0x1da5,
+ 0x7d13, 0x1da3,
+ 0x7d14, 0x0971,
+ 0x7d15, 0x0973,
+ 0x7d16, 0x1da2,
+ 0x7d17, 0x096c,
+ 0x7d18, 0x1da1,
+ 0x7d19, 0x0977,
+ 0x7d1a, 0x0974,
+ 0x7d1b, 0x0978,
+ 0x7d1c, 0x0975,
+ 0x7d1d, 0x1d9e,
+ 0x7d1e, 0x1d9d,
+ 0x7d1f, 0x1da4,
+ 0x7d20, 0x096f,
+ 0x7d21, 0x096b,
+ 0x7d22, 0x0970,
+ 0x7d25, 0x3ede,
+ 0x7d28, 0x1ff2,
+ 0x7d29, 0x1feb,
+ 0x7d2b, 0x0d13,
+ 0x7d2c, 0x1fea,
+ 0x7d2e, 0x0b56,
+ 0x7d2f, 0x0b5d,
+ 0x7d30, 0x0b5a,
+ 0x7d31, 0x0b60,
+ 0x7d32, 0x0b5f,
+ 0x7d33, 0x0b5b,
+ 0x7d35, 0x1fe4,
+ 0x7d36, 0x1fe7,
+ 0x7d38, 0x1fe6,
+ 0x7d39, 0x0b57,
+ 0x7d3a, 0x1fe8,
+ 0x7d3b, 0x1ff1,
+ 0x7d3c, 0x0b58,
+ 0x7d3d, 0x1fe5,
+ 0x7d3e, 0x1fee,
+ 0x7d40, 0x0b59,
+ 0x7d41, 0x1fec,
+ 0x7d42, 0x0b5e,
+ 0x7d43, 0x0b54,
+ 0x7d44, 0x0b5c,
+ 0x7d45, 0x1fe9,
+ 0x7d46, 0x0b53,
+ 0x7d47, 0x1fed,
+ 0x7d4a, 0x1ff0,
+ 0x7d4d, 0x3fdd,
+ 0x7d4e, 0x2270,
+ 0x7d4f, 0x2267,
+ 0x7d50, 0x0d10,
+ 0x7d51, 0x226e,
+ 0x7d52, 0x226b,
+ 0x7d53, 0x2263,
+ 0x7d54, 0x226c,
+ 0x7d55, 0x0d12,
+ 0x7d56, 0x2264,
+ 0x7d58, 0x2260,
+ 0x7d5a, 0x3e93,
+ 0x7d5b, 0x0ec3,
+ 0x7d5c, 0x2269,
+ 0x7d5d, 0x3769,
+ 0x7d5e, 0x0d0f,
+ 0x7d5f, 0x226f,
+ 0x7d61, 0x0d16,
+ 0x7d62, 0x0d18,
+ 0x7d63, 0x2262,
+ 0x7d66, 0x0d17,
+ 0x7d67, 0x2265,
+ 0x7d68, 0x0d11,
+ 0x7d69, 0x226d,
+ 0x7d6a, 0x2266,
+ 0x7d6b, 0x226a,
+ 0x7d6d, 0x2268,
+ 0x7d6e, 0x0d14,
+ 0x7d6f, 0x2261,
+ 0x7d70, 0x0d19,
+ 0x7d71, 0x0b55,
+ 0x7d72, 0x0d15,
+ 0x7d73, 0x0d1a,
+ 0x7d79, 0x0ebf,
+ 0x7d7a, 0x2505,
+ 0x7d7b, 0x2507,
+ 0x7d7c, 0x2509,
+ 0x7d7d, 0x250d,
+ 0x7d7f, 0x2503,
+ 0x7d80, 0x2501,
+ 0x7d81, 0x0ec1,
+ 0x7d83, 0x2508,
+ 0x7d84, 0x250c,
+ 0x7d85, 0x2504,
+ 0x7d86, 0x2500,
+ 0x7d88, 0x24ff,
+ 0x7d89, 0x376b,
+ 0x7d8c, 0x250a,
+ 0x7d8d, 0x2502,
+ 0x7d8e, 0x2506,
+ 0x7d8f, 0x0ec2,
+ 0x7d91, 0x0ec0,
+ 0x7d92, 0x250e,
+ 0x7d93, 0x0ebe,
+ 0x7d94, 0x250b,
+ 0x7d96, 0x278e,
+ 0x7d97, 0x3b53,
+ 0x7d9c, 0x105d,
+ 0x7d9d, 0x2786,
+ 0x7d9e, 0x11e1,
+ 0x7d9f, 0x2790,
+ 0x7da0, 0x1060,
+ 0x7da1, 0x2794,
+ 0x7da2, 0x1066,
+ 0x7da3, 0x2781,
+ 0x7da4, 0x46d7,
+ 0x7da6, 0x2791,
+ 0x7da7, 0x277e,
+ 0x7da8, 0x3c9c,
+ 0x7da9, 0x2793,
+ 0x7daa, 0x2782,
+ 0x7dab, 0x376c,
+ 0x7dac, 0x106d,
+ 0x7dad, 0x106a,
+ 0x7dae, 0x2792,
+ 0x7daf, 0x278c,
+ 0x7db0, 0x105c,
+ 0x7db1, 0x1064,
+ 0x7db2, 0x1063,
+ 0x7db3, 0x376e,
+ 0x7db4, 0x1062,
+ 0x7db5, 0x1068,
+ 0x7db7, 0x277f,
+ 0x7db8, 0x1069,
+ 0x7db9, 0x278d,
+ 0x7dba, 0x1065,
+ 0x7dbb, 0x105b,
+ 0x7dbc, 0x278f,
+ 0x7dbd, 0x105e,
+ 0x7dbf, 0x1067,
+ 0x7dc0, 0x2784,
+ 0x7dc1, 0x2783,
+ 0x7dc2, 0x2780,
+ 0x7dc4, 0x2788,
+ 0x7dc5, 0x2785,
+ 0x7dc6, 0x2789,
+ 0x7dc7, 0x106c,
+ 0x7dc9, 0x2795,
+ 0x7dca, 0x1061,
+ 0x7dcb, 0x278a,
+ 0x7dcd, 0x456e,
+ 0x7dce, 0x2787,
+ 0x7dcf, 0x4735,
+ 0x7dd0, 0x4737,
+ 0x7dd2, 0x106b,
+ 0x7dd3, 0x3b4e,
+ 0x7dd4, 0x4736,
+ 0x7dd6, 0x376f,
+ 0x7dd7, 0x29b8,
+ 0x7dd8, 0x11d9,
+ 0x7dd9, 0x11e2,
+ 0x7dda, 0x11de,
+ 0x7ddb, 0x29b5,
+ 0x7ddc, 0x3b4c,
+ 0x7ddd, 0x11db,
+ 0x7dde, 0x11df,
+ 0x7ddf, 0x29c1,
+ 0x7de0, 0x11d5,
+ 0x7de1, 0x29b9,
+ 0x7de3, 0x11dd,
+ 0x7de4, 0x3772,
+ 0x7de5, 0x3776,
+ 0x7de6, 0x29bc,
+ 0x7de7, 0x29b7,
+ 0x7de8, 0x11dc,
+ 0x7de9, 0x11e0,
+ 0x7dea, 0x29b6,
+ 0x7dec, 0x11da,
+ 0x7dee, 0x29c0,
+ 0x7def, 0x11d7,
+ 0x7df0, 0x29bf,
+ 0x7df1, 0x29be,
+ 0x7df2, 0x11e3,
+ 0x7df3, 0x28c8,
+ 0x7df4, 0x11d6,
+ 0x7df5, 0x3774,
+ 0x7df6, 0x29bd,
+ 0x7df7, 0x29b4,
+ 0x7df9, 0x11e4,
+ 0x7dfa, 0x29bb,
+ 0x7dfb, 0x11d8,
+ 0x7dfd, 0x4738,
+ 0x7dfe, 0x3ccf,
+ 0x7e03, 0x29ba,
+ 0x7e07, 0x3b4d,
+ 0x7e08, 0x1322,
+ 0x7e09, 0x1327,
+ 0x7e0a, 0x1320,
+ 0x7e0b, 0x2c1f,
+ 0x7e0c, 0x2c16,
+ 0x7e0d, 0x2c22,
+ 0x7e0e, 0x2c1a,
+ 0x7e0f, 0x2c20,
+ 0x7e10, 0x1328,
+ 0x7e11, 0x1321,
+ 0x7e12, 0x2c13,
+ 0x7e13, 0x2c19,
+ 0x7e14, 0x2c23,
+ 0x7e15, 0x2c1c,
+ 0x7e16, 0x2c21,
+ 0x7e17, 0x2c15,
+ 0x7e1a, 0x2c1d,
+ 0x7e1b, 0x1323,
+ 0x7e1c, 0x2c1b,
+ 0x7e1d, 0x1326,
+ 0x7e1e, 0x1325,
+ 0x7e1f, 0x2c17,
+ 0x7e21, 0x2c14,
+ 0x7e22, 0x2c1e,
+ 0x7e23, 0x1324,
+ 0x7e24, 0x2c25,
+ 0x7e25, 0x2c24,
+ 0x7e27, 0x377f,
+ 0x7e29, 0x2df8,
+ 0x7e2a, 0x2df4,
+ 0x7e2b, 0x143b,
+ 0x7e2d, 0x2dee,
+ 0x7e2e, 0x1435,
+ 0x7e2f, 0x1445,
+ 0x7e30, 0x2dfa,
+ 0x7e31, 0x143d,
+ 0x7e32, 0x1439,
+ 0x7e33, 0x2df1,
+ 0x7e34, 0x1440,
+ 0x7e35, 0x1443,
+ 0x7e36, 0x2dfc,
+ 0x7e37, 0x1438,
+ 0x7e38, 0x2df3,
+ 0x7e39, 0x1441,
+ 0x7e3a, 0x2dfe,
+ 0x7e3b, 0x2dfb,
+ 0x7e3c, 0x2def,
+ 0x7e3d, 0x143c,
+ 0x7e3e, 0x1436,
+ 0x7e3f, 0x1444,
+ 0x7e40, 0x2df6,
+ 0x7e41, 0x143f,
+ 0x7e42, 0x2df0,
+ 0x7e43, 0x143a,
+ 0x7e44, 0x2dfd,
+ 0x7e45, 0x143e,
+ 0x7e46, 0x1437,
+ 0x7e47, 0x2df7,
+ 0x7e48, 0x1442,
+ 0x7e49, 0x2df5,
+ 0x7e4c, 0x2df9,
+ 0x7e50, 0x2f83,
+ 0x7e51, 0x2f89,
+ 0x7e52, 0x1511,
+ 0x7e53, 0x2f8c,
+ 0x7e54, 0x150c,
+ 0x7e56, 0x2f84,
+ 0x7e57, 0x2f8b,
+ 0x7e58, 0x2f86,
+ 0x7e59, 0x1512,
+ 0x7e5a, 0x150f,
+ 0x7e5c, 0x2f82,
+ 0x7e5e, 0x150e,
+ 0x7e5f, 0x2f88,
+ 0x7e60, 0x2f8a,
+ 0x7e61, 0x1510,
+ 0x7e62, 0x2f87,
+ 0x7e63, 0x2f85,
+ 0x7e65, 0x46d2,
+ 0x7e67, 0x3766,
+ 0x7e68, 0x30e3,
+ 0x7e69, 0x15ac,
+ 0x7e6b, 0x15a9,
+ 0x7e6d, 0x15aa,
+ 0x7e6e, 0x377b,
+ 0x7e6f, 0x30df,
+ 0x7e70, 0x30dd,
+ 0x7e72, 0x30e1,
+ 0x7e73, 0x15ae,
+ 0x7e74, 0x30e2,
+ 0x7e75, 0x30db,
+ 0x7e76, 0x30da,
+ 0x7e77, 0x30de,
+ 0x7e78, 0x30dc,
+ 0x7e79, 0x15ab,
+ 0x7e7a, 0x30e0,
+ 0x7e7b, 0x3214,
+ 0x7e7c, 0x1631,
+ 0x7e7d, 0x1630,
+ 0x7e7e, 0x3215,
+ 0x7e7f, 0x3e51,
+ 0x7e80, 0x3217,
+ 0x7e81, 0x3216,
+ 0x7e82, 0x1632,
+ 0x7e86, 0x32f0,
+ 0x7e87, 0x32ed,
+ 0x7e8a, 0x32ec,
+ 0x7e8b, 0x32ef,
+ 0x7e8c, 0x1683,
+ 0x7e8d, 0x32f1,
+ 0x7e8e, 0x3ec9,
+ 0x7e8f, 0x1682,
+ 0x7e91, 0x33a2,
+ 0x7e92, 0x469e,
+ 0x7e93, 0x1703,
+ 0x7e94, 0x1705,
+ 0x7e95, 0x342c,
+ 0x7e96, 0x1704,
+ 0x7e97, 0x3494,
+ 0x7e98, 0x34da,
+ 0x7e99, 0x34dc,
+ 0x7e9a, 0x34d9,
+ 0x7e9b, 0x34db,
+ 0x7e9c, 0x1759,
+ 0x7e9f, 0x48bb,
+ 0x7ea4, 0x455b,
+ 0x7eac, 0x455c,
+ 0x7eba, 0x455d,
+ 0x7ec7, 0x455e,
+ 0x7ecf, 0x455f,
+ 0x7edf, 0x4560,
+ 0x7f06, 0x4561,
+ 0x7f36, 0x03f9,
+ 0x7f37, 0x4562,
+ 0x7f38, 0x07d4,
+ 0x7f39, 0x1d1f,
+ 0x7f3a, 0x0979,
+ 0x7f3d, 0x0b61,
+ 0x7f3e, 0x2271,
+ 0x7f40, 0x3780,
+ 0x7f43, 0x2c26,
+ 0x7f44, 0x1446,
+ 0x7f45, 0x2dff,
+ 0x7f47, 0x3782,
+ 0x7f48, 0x1513,
+ 0x7f49, 0x3e69,
+ 0x7f4a, 0x30e5,
+ 0x7f4b, 0x30e4,
+ 0x7f4c, 0x1633,
+ 0x7f4d, 0x32f2,
+ 0x7f4e, 0x3b4f,
+ 0x7f4f, 0x33a3,
+ 0x7f50, 0x1726,
+ 0x7f51, 0x1812,
+ 0x7f52, 0x44f6,
+ 0x7f53, 0x44f9,
+ 0x7f54, 0x0668,
+ 0x7f55, 0x04fc,
+ 0x7f58, 0x1bc3,
+ 0x7f5b, 0x1dad,
+ 0x7f5c, 0x1da8,
+ 0x7f5d, 0x1dac,
+ 0x7f5e, 0x1daa,
+ 0x7f5f, 0x097a,
+ 0x7f60, 0x1dab,
+ 0x7f61, 0x1da9,
+ 0x7f63, 0x1ff3,
+ 0x7f65, 0x2273,
+ 0x7f67, 0x2511,
+ 0x7f69, 0x0ec5,
+ 0x7f6b, 0x2510,
+ 0x7f6c, 0x2513,
+ 0x7f6d, 0x250f,
+ 0x7f6e, 0x0ec4,
+ 0x7f70, 0x106e,
+ 0x7f71, 0x4007,
+ 0x7f72, 0x0ec7,
+ 0x7f73, 0x2796,
+ 0x7f75, 0x11e5,
+ 0x7f76, 0x29c2,
+ 0x7f77, 0x11e6,
+ 0x7f78, 0x3f7b,
+ 0x7f79, 0x1329,
+ 0x7f7a, 0x2c29,
+ 0x7f7b, 0x2c27,
+ 0x7f7d, 0x2e02,
+ 0x7f7e, 0x2e01,
+ 0x7f7f, 0x2e00,
+ 0x7f83, 0x30e6,
+ 0x7f85, 0x15af,
+ 0x7f86, 0x30e7,
+ 0x7f87, 0x33a4,
+ 0x7f88, 0x1727,
+ 0x7f89, 0x3495,
+ 0x7f8a, 0x03fa,
+ 0x7f8b, 0x066a,
+ 0x7f8c, 0x0669,
+ 0x7f8d, 0x1bc5,
+ 0x7f8e, 0x07d5,
+ 0x7f8f, 0x421c,
+ 0x7f91, 0x1bc4,
+ 0x7f92, 0x1daf,
+ 0x7f93, 0x43db,
+ 0x7f94, 0x097b,
+ 0x7f95, 0x1ff4,
+ 0x7f96, 0x1dae,
+ 0x7f97, 0x3786,
+ 0x7f9a, 0x0b63,
+ 0x7f9b, 0x1ff7,
+ 0x7f9c, 0x1ff5,
+ 0x7f9e, 0x0b62,
+ 0x7fa0, 0x2276,
+ 0x7fa2, 0x2275,
+ 0x7fa3, 0x3788,
+ 0x7fa4, 0x0eca,
+ 0x7fa5, 0x2515,
+ 0x7fa6, 0x2514,
+ 0x7fa7, 0x2516,
+ 0x7fa8, 0x0ec9,
+ 0x7fa9, 0x0ec8,
+ 0x7fac, 0x29c3,
+ 0x7fad, 0x29c5,
+ 0x7fae, 0x43dc,
+ 0x7faf, 0x11e7,
+ 0x7fb0, 0x29c4,
+ 0x7fb1, 0x2c2a,
+ 0x7fb2, 0x132a,
+ 0x7fb3, 0x2f8e,
+ 0x7fb4, 0x4739,
+ 0x7fb5, 0x2f8d,
+ 0x7fb6, 0x15b0,
+ 0x7fb7, 0x30e8,
+ 0x7fb8, 0x15b2,
+ 0x7fb9, 0x15b1,
+ 0x7fba, 0x3218,
+ 0x7fbb, 0x32f3,
+ 0x7fbc, 0x1684,
+ 0x7fbd, 0x03fb,
+ 0x7fbe, 0x1bc6,
+ 0x7fbf, 0x07d6,
+ 0x7fc0, 0x1db2,
+ 0x7fc1, 0x097d,
+ 0x7fc2, 0x1db1,
+ 0x7fc3, 0x1db0,
+ 0x7fc5, 0x097c,
+ 0x7fc7, 0x1ffd,
+ 0x7fc9, 0x1fff,
+ 0x7fca, 0x1ff8,
+ 0x7fcc, 0x0b64,
+ 0x7fcd, 0x1ffa,
+ 0x7fce, 0x0b65,
+ 0x7fcf, 0x1ffe,
+ 0x7fd0, 0x1ffb,
+ 0x7fd2, 0x0b66,
+ 0x7fd4, 0x0d1c,
+ 0x7fd7, 0x2278,
+ 0x7fdb, 0x2517,
+ 0x7fdd, 0x3b5e,
+ 0x7fde, 0x279a,
+ 0x7fdf, 0x1071,
+ 0x7fe0, 0x106f,
+ 0x7fe2, 0x2797,
+ 0x7fe5, 0x2799,
+ 0x7fe6, 0x29ca,
+ 0x7fe7, 0x46e9,
+ 0x7fe8, 0x29cb,
+ 0x7fe9, 0x11e8,
+ 0x7fea, 0x29c8,
+ 0x7feb, 0x29c7,
+ 0x7fec, 0x29c9,
+ 0x7fed, 0x29c6,
+ 0x7fee, 0x132d,
+ 0x7fef, 0x2c2b,
+ 0x7ff0, 0x132b,
+ 0x7ff2, 0x2e04,
+ 0x7ff3, 0x1447,
+ 0x7ff4, 0x2e03,
+ 0x7ff5, 0x2eff,
+ 0x7ff7, 0x2f8f,
+ 0x7ff9, 0x1514,
+ 0x7ffa, 0x378e,
+ 0x7ffb, 0x1515,
+ 0x7ffc, 0x1448,
+ 0x7ffd, 0x30e9,
+ 0x7fff, 0x3219,
+ 0x8000, 0x1634,
+ 0x8001, 0x03fc,
+ 0x8002, 0x44fd,
+ 0x8003, 0x03fd,
+ 0x8004, 0x097f,
+ 0x8005, 0x066b,
+ 0x8006, 0x097e,
+ 0x8007, 0x1bc7,
+ 0x8008, 0x3791,
+ 0x800b, 0x0d1e,
+ 0x800c, 0x03fe,
+ 0x800d, 0x07d8,
+ 0x800e, 0x1bc8,
+ 0x8010, 0x07d7,
+ 0x8011, 0x07d9,
+ 0x8012, 0x03ff,
+ 0x8014, 0x1bca,
+ 0x8015, 0x0981,
+ 0x8016, 0x1db3,
+ 0x8017, 0x0983,
+ 0x8018, 0x0980,
+ 0x8019, 0x0982,
+ 0x801b, 0x2002,
+ 0x801c, 0x0b67,
+ 0x801d, 0x3792,
+ 0x801e, 0x2001,
+ 0x801f, 0x2000,
+ 0x8020, 0x473c,
+ 0x8021, 0x2519,
+ 0x8024, 0x279b,
+ 0x8025, 0x473d,
+ 0x8026, 0x11e9,
+ 0x8028, 0x132e,
+ 0x8029, 0x2c2d,
+ 0x802a, 0x2c2c,
+ 0x802c, 0x2e05,
+ 0x802e, 0x473e,
+ 0x802f, 0x3794,
+ 0x8030, 0x32f4,
+ 0x8031, 0x473f,
+ 0x8033, 0x0400,
+ 0x8034, 0x18d8,
+ 0x8035, 0x1a27,
+ 0x8036, 0x07da,
+ 0x8037, 0x1bcb,
+ 0x8039, 0x1db5,
+ 0x803b, 0x3797,
+ 0x803d, 0x0984,
+ 0x803e, 0x1db4,
+ 0x803f, 0x0985,
+ 0x8043, 0x2004,
+ 0x8046, 0x0b69,
+ 0x8047, 0x2003,
+ 0x8048, 0x2005,
+ 0x804a, 0x0b68,
+ 0x804f, 0x227a,
+ 0x8051, 0x2279,
+ 0x8052, 0x0d1f,
+ 0x8054, 0x4740,
+ 0x8056, 0x0ecb,
+ 0x8058, 0x0ecc,
+ 0x805a, 0x1073,
+ 0x805b, 0x3fe5,
+ 0x805c, 0x279d,
+ 0x805d, 0x279c,
+ 0x805e, 0x1072,
+ 0x8061, 0x3799,
+ 0x8062, 0x3fe3,
+ 0x8063, 0x3fdc,
+ 0x8064, 0x29cc,
+ 0x8066, 0x3fdb,
+ 0x8067, 0x29cd,
+ 0x806c, 0x2c2e,
+ 0x806f, 0x144c,
+ 0x8070, 0x144b,
+ 0x8071, 0x1449,
+ 0x8073, 0x144d,
+ 0x8075, 0x2f91,
+ 0x8076, 0x1517,
+ 0x8077, 0x1516,
+ 0x8078, 0x30eb,
+ 0x8079, 0x321a,
+ 0x807d, 0x16d3,
+ 0x807e, 0x16d2,
+ 0x807f, 0x0401,
+ 0x8080, 0x44fe,
+ 0x8082, 0x1cec,
+ 0x8084, 0x0ece,
+ 0x8085, 0x0d20,
+ 0x8086, 0x0ecd,
+ 0x8087, 0x1074,
+ 0x8089, 0x0402,
+ 0x808a, 0x17b3,
+ 0x808b, 0x0403,
+ 0x808f, 0x1a28,
+ 0x8090, 0x18db,
+ 0x8092, 0x18dc,
+ 0x8093, 0x04fe,
+ 0x8095, 0x18d9,
+ 0x8096, 0x04fd,
+ 0x8098, 0x0500,
+ 0x8099, 0x18da,
+ 0x809a, 0x0502,
+ 0x809b, 0x0501,
+ 0x809c, 0x18dd,
+ 0x809d, 0x04ff,
+ 0x809f, 0x4576,
+ 0x80a1, 0x0670,
+ 0x80a2, 0x066e,
+ 0x80a3, 0x1a2a,
+ 0x80a5, 0x066d,
+ 0x80a7, 0x37a0,
+ 0x80a9, 0x0672,
+ 0x80aa, 0x0674,
+ 0x80ab, 0x0671,
+ 0x80ad, 0x1a2d,
+ 0x80ae, 0x1a29,
+ 0x80af, 0x0675,
+ 0x80b1, 0x066f,
+ 0x80b2, 0x0503,
+ 0x80b4, 0x0673,
+ 0x80b5, 0x1a2c,
+ 0x80b6, 0x3eae,
+ 0x80b7, 0x4743,
+ 0x80b8, 0x1a2b,
+ 0x80ba, 0x066c,
+ 0x80bc, 0x4572,
+ 0x80bd, 0x3e7b,
+ 0x80c2, 0x1bd1,
+ 0x80c3, 0x07de,
+ 0x80c5, 0x1bd3,
+ 0x80c6, 0x3b74,
+ 0x80c7, 0x1bcd,
+ 0x80c8, 0x1bd0,
+ 0x80c9, 0x1bd9,
+ 0x80ca, 0x1bd7,
+ 0x80cc, 0x07e0,
+ 0x80cd, 0x1bdd,
+ 0x80ce, 0x07e3,
+ 0x80cf, 0x1bda,
+ 0x80d0, 0x1bd2,
+ 0x80d1, 0x1bcf,
+ 0x80d4, 0x227d,
+ 0x80d5, 0x1bd8,
+ 0x80d6, 0x07db,
+ 0x80d7, 0x1bdb,
+ 0x80d8, 0x1bcc,
+ 0x80d9, 0x1bd5,
+ 0x80da, 0x07dd,
+ 0x80db, 0x07e2,
+ 0x80dc, 0x1bd6,
+ 0x80dd, 0x07e6,
+ 0x80de, 0x07e4,
+ 0x80e0, 0x1bce,
+ 0x80e1, 0x07e1,
+ 0x80e3, 0x1bd4,
+ 0x80e4, 0x07e5,
+ 0x80e5, 0x07dc,
+ 0x80e6, 0x1bdc,
+ 0x80e9, 0x4744,
+ 0x80ec, 0x45e9,
+ 0x80ed, 0x098a,
+ 0x80ef, 0x0993,
+ 0x80f0, 0x0988,
+ 0x80f1, 0x0986,
+ 0x80f2, 0x1db7,
+ 0x80f3, 0x098e,
+ 0x80f4, 0x098b,
+ 0x80f5, 0x1db9,
+ 0x80f6, 0x4574,
+ 0x80f8, 0x098d,
+ 0x80f9, 0x1db8,
+ 0x80fa, 0x1db6,
+ 0x80fb, 0x1dbb,
+ 0x80fc, 0x0992,
+ 0x80fd, 0x0990,
+ 0x80fe, 0x227c,
+ 0x8100, 0x1dbc,
+ 0x8101, 0x1dba,
+ 0x8102, 0x0987,
+ 0x8103, 0x3fe7,
+ 0x8105, 0x0989,
+ 0x8106, 0x098c,
+ 0x8107, 0x37a2,
+ 0x8108, 0x098f,
+ 0x8109, 0x3b75,
+ 0x810a, 0x0991,
+ 0x810c, 0x4746,
+ 0x810e, 0x4747,
+ 0x8112, 0x4748,
+ 0x8114, 0x4749,
+ 0x8115, 0x200f,
+ 0x8116, 0x0b6b,
+ 0x8117, 0x3e6d,
+ 0x8118, 0x2006,
+ 0x8119, 0x2008,
+ 0x811a, 0x37a3,
+ 0x811b, 0x2009,
+ 0x811d, 0x2011,
+ 0x811e, 0x200d,
+ 0x811f, 0x200b,
+ 0x8121, 0x200e,
+ 0x8122, 0x2012,
+ 0x8123, 0x0b6c,
+ 0x8124, 0x0b70,
+ 0x8125, 0x2007,
+ 0x8127, 0x2010,
+ 0x8129, 0x0b6e,
+ 0x812a, 0x3a39,
+ 0x812b, 0x0b6d,
+ 0x812c, 0x200c,
+ 0x812d, 0x200a,
+ 0x812f, 0x0b6a,
+ 0x8130, 0x0b6f,
+ 0x8132, 0x3e79,
+ 0x8134, 0x45ec,
+ 0x8137, 0x3b72,
+ 0x8139, 0x0d26,
+ 0x813a, 0x2285,
+ 0x813d, 0x2283,
+ 0x813e, 0x0d28,
+ 0x8142, 0x3b76,
+ 0x8143, 0x227e,
+ 0x8144, 0x2527,
+ 0x8146, 0x0d27,
+ 0x8147, 0x2282,
+ 0x8148, 0x3e76,
+ 0x814a, 0x227f,
+ 0x814b, 0x0d23,
+ 0x814c, 0x0d29,
+ 0x814d, 0x2284,
+ 0x814e, 0x0d25,
+ 0x814f, 0x2281,
+ 0x8150, 0x1075,
+ 0x8151, 0x0d24,
+ 0x8152, 0x2280,
+ 0x8153, 0x0d2a,
+ 0x8154, 0x0d22,
+ 0x8155, 0x0d21,
+ 0x8156, 0x474c,
+ 0x8159, 0x474d,
+ 0x815b, 0x251f,
+ 0x815c, 0x251d,
+ 0x815e, 0x2523,
+ 0x8160, 0x251b,
+ 0x8161, 0x2528,
+ 0x8162, 0x2520,
+ 0x8164, 0x251a,
+ 0x8165, 0x0ed2,
+ 0x8166, 0x0ed8,
+ 0x8167, 0x2525,
+ 0x8169, 0x251e,
+ 0x816b, 0x0ed5,
+ 0x816d, 0x43c4,
+ 0x816e, 0x0ed3,
+ 0x816f, 0x2526,
+ 0x8170, 0x0ed0,
+ 0x8171, 0x0ecf,
+ 0x8172, 0x2521,
+ 0x8173, 0x0ed4,
+ 0x8174, 0x0d2b,
+ 0x8176, 0x2524,
+ 0x8177, 0x251c,
+ 0x8178, 0x0ed1,
+ 0x8179, 0x0ed6,
+ 0x817c, 0x4750,
+ 0x817f, 0x107a,
+ 0x8180, 0x1076,
+ 0x8182, 0x107b,
+ 0x8183, 0x27a0,
+ 0x8184, 0x43c5,
+ 0x8186, 0x279f,
+ 0x8187, 0x27a1,
+ 0x8188, 0x1078,
+ 0x8189, 0x279e,
+ 0x818a, 0x1079,
+ 0x818b, 0x27a4,
+ 0x818c, 0x27a3,
+ 0x818d, 0x27a2,
+ 0x818f, 0x1077,
+ 0x8193, 0x43c6,
+ 0x8195, 0x29d1,
+ 0x8197, 0x29d4,
+ 0x8198, 0x11ef,
+ 0x8199, 0x29d3,
+ 0x819a, 0x11ee,
+ 0x819b, 0x11ea,
+ 0x819e, 0x29d0,
+ 0x819f, 0x29cf,
+ 0x81a0, 0x11ed,
+ 0x81a2, 0x29d2,
+ 0x81a3, 0x29ce,
+ 0x81a5, 0x4753,
+ 0x81a6, 0x2c30,
+ 0x81a7, 0x2c3a,
+ 0x81a8, 0x1331,
+ 0x81a9, 0x1330,
+ 0x81aa, 0x4364,
+ 0x81ab, 0x2c34,
+ 0x81ac, 0x2c36,
+ 0x81ae, 0x2c31,
+ 0x81b0, 0x2c35,
+ 0x81b1, 0x2c2f,
+ 0x81b2, 0x2c38,
+ 0x81b3, 0x132f,
+ 0x81b4, 0x2c37,
+ 0x81b5, 0x2c33,
+ 0x81b6, 0x3eb2,
+ 0x81b7, 0x2c39,
+ 0x81b9, 0x2c32,
+ 0x81ba, 0x1450,
+ 0x81bb, 0x2e06,
+ 0x81bc, 0x2e0c,
+ 0x81bd, 0x1454,
+ 0x81be, 0x1456,
+ 0x81bf, 0x1453,
+ 0x81c0, 0x1452,
+ 0x81c1, 0x4755,
+ 0x81c2, 0x1451,
+ 0x81c3, 0x144f,
+ 0x81c4, 0x2e07,
+ 0x81c5, 0x2e0a,
+ 0x81c6, 0x144e,
+ 0x81c7, 0x2e0b,
+ 0x81c8, 0x3fee,
+ 0x81c9, 0x1455,
+ 0x81ca, 0x2e09,
+ 0x81cc, 0x2e08,
+ 0x81cd, 0x1518,
+ 0x81cf, 0x1519,
+ 0x81d0, 0x2f94,
+ 0x81d1, 0x2f92,
+ 0x81d5, 0x30ed,
+ 0x81d7, 0x30ec,
+ 0x81d8, 0x15b3,
+ 0x81d9, 0x321c,
+ 0x81da, 0x1635,
+ 0x81db, 0x321b,
+ 0x81dd, 0x32f5,
+ 0x81de, 0x33a5,
+ 0x81df, 0x16d4,
+ 0x81e0, 0x34dd,
+ 0x81e2, 0x1706,
+ 0x81e3, 0x0405,
+ 0x81e4, 0x4756,
+ 0x81e5, 0x0676,
+ 0x81e6, 0x2286,
+ 0x81e7, 0x107c,
+ 0x81e8, 0x1457,
+ 0x81e9, 0x2e0d,
+ 0x81ea, 0x0406,
+ 0x81ec, 0x0995,
+ 0x81ed, 0x0994,
+ 0x81ee, 0x2287,
+ 0x81ef, 0x42d1,
+ 0x81f2, 0x2c3b,
+ 0x81f3, 0x0407,
+ 0x81f4, 0x07e7,
+ 0x81f6, 0x3d61,
+ 0x81f7, 0x2288,
+ 0x81fa, 0x107d,
+ 0x81fb, 0x1332,
+ 0x81fc, 0x0408,
+ 0x81fe, 0x0677,
+ 0x81ff, 0x1bde,
+ 0x8200, 0x0996,
+ 0x8201, 0x1dbd,
+ 0x8202, 0x0b71,
+ 0x8204, 0x228b,
+ 0x8205, 0x0ed9,
+ 0x8207, 0x107e,
+ 0x8208, 0x1333,
+ 0x8209, 0x1458,
+ 0x820a, 0x151a,
+ 0x820b, 0x30ee,
+ 0x820c, 0x0409,
+ 0x820d, 0x0678,
+ 0x8210, 0x0997,
+ 0x8211, 0x2013,
+ 0x8212, 0x0d2c,
+ 0x8214, 0x107f,
+ 0x8215, 0x27a5,
+ 0x8216, 0x29d5,
+ 0x8218, 0x37aa,
+ 0x821a, 0x3fe1,
+ 0x821b, 0x040a,
+ 0x821c, 0x0d2d,
+ 0x821d, 0x2529,
+ 0x821e, 0x1080,
+ 0x821f, 0x040b,
+ 0x8220, 0x1a2e,
+ 0x8221, 0x1bdf,
+ 0x8222, 0x07e8,
+ 0x8225, 0x1dbf,
+ 0x8226, 0x420d,
+ 0x8228, 0x099a,
+ 0x8229, 0x37b0,
+ 0x822a, 0x0998,
+ 0x822c, 0x099b,
+ 0x822d, 0x3ed0,
+ 0x822f, 0x1dbe,
+ 0x8232, 0x2018,
+ 0x8233, 0x2015,
+ 0x8234, 0x2017,
+ 0x8235, 0x0b72,
+ 0x8236, 0x0b74,
+ 0x8237, 0x0b73,
+ 0x8238, 0x2014,
+ 0x8239, 0x0b75,
+ 0x823a, 0x2016,
+ 0x823c, 0x228c,
+ 0x823e, 0x4582,
+ 0x823f, 0x228e,
+ 0x8240, 0x252c,
+ 0x8242, 0x252d,
+ 0x8244, 0x252b,
+ 0x8245, 0x252e,
+ 0x8247, 0x0eda,
+ 0x8249, 0x252a,
+ 0x824b, 0x1081,
+ 0x824e, 0x29da,
+ 0x824f, 0x29d6,
+ 0x8250, 0x29d9,
+ 0x8251, 0x29db,
+ 0x8252, 0x29d8,
+ 0x8253, 0x29d7,
+ 0x8254, 0x4757,
+ 0x8255, 0x2c3c,
+ 0x8258, 0x1334,
+ 0x825a, 0x2e0f,
+ 0x825b, 0x2e0e,
+ 0x825c, 0x2e10,
+ 0x825e, 0x2f96,
+ 0x825f, 0x2f95,
+ 0x8261, 0x30f0,
+ 0x8262, 0x3b7a,
+ 0x8263, 0x30f1,
+ 0x8264, 0x30ef,
+ 0x8265, 0x3b7b,
+ 0x8266, 0x1636,
+ 0x8268, 0x321d,
+ 0x826b, 0x33a6,
+ 0x826c, 0x342d,
+ 0x826d, 0x3496,
+ 0x826e, 0x040c,
+ 0x826f, 0x0504,
+ 0x8271, 0x1459,
+ 0x8272, 0x040d,
+ 0x8274, 0x2019,
+ 0x8275, 0x228f,
+ 0x8276, 0x4759,
+ 0x8277, 0x172e,
+ 0x8278, 0x1813,
+ 0x8279, 0x4722,
+ 0x827a, 0x4563,
+ 0x827b, 0x37c8,
+ 0x827c, 0x1814,
+ 0x827d, 0x1816,
+ 0x827e, 0x040e,
+ 0x827f, 0x1817,
+ 0x8280, 0x1815,
+ 0x8283, 0x18e5,
+ 0x8285, 0x18e0,
+ 0x8287, 0x4132,
+ 0x828a, 0x18e4,
+ 0x828b, 0x0506,
+ 0x828d, 0x0507,
+ 0x828e, 0x18e1,
+ 0x828f, 0x18df,
+ 0x8290, 0x18de,
+ 0x8291, 0x18e2,
+ 0x8292, 0x0505,
+ 0x8293, 0x18e3,
+ 0x8294, 0x1be0,
+ 0x8298, 0x1a33,
+ 0x8299, 0x067b,
+ 0x829a, 0x1a32,
+ 0x829b, 0x1a34,
+ 0x829d, 0x067a,
+ 0x829e, 0x1a39,
+ 0x829f, 0x067e,
+ 0x82a0, 0x1a2f,
+ 0x82a1, 0x1a3d,
+ 0x82a2, 0x1a43,
+ 0x82a3, 0x0685,
+ 0x82a4, 0x1a40,
+ 0x82a5, 0x0682,
+ 0x82a6, 0x3d73,
+ 0x82a7, 0x1a36,
+ 0x82a8, 0x1a3c,
+ 0x82a9, 0x1a3e,
+ 0x82aa, 0x37bc,
+ 0x82ab, 0x1a31,
+ 0x82ac, 0x0681,
+ 0x82ad, 0x067c,
+ 0x82ae, 0x1a37,
+ 0x82af, 0x0683,
+ 0x82b0, 0x0686,
+ 0x82b1, 0x0680,
+ 0x82b3, 0x0679,
+ 0x82b4, 0x1a3b,
+ 0x82b5, 0x1a35,
+ 0x82b6, 0x1a42,
+ 0x82b7, 0x0688,
+ 0x82b8, 0x0684,
+ 0x82b9, 0x067f,
+ 0x82ba, 0x1a3a,
+ 0x82bb, 0x099c,
+ 0x82bc, 0x1a38,
+ 0x82bd, 0x067d,
+ 0x82be, 0x0687,
+ 0x82c0, 0x1a30,
+ 0x82c2, 0x1a3f,
+ 0x82c3, 0x1a41,
+ 0x82c4, 0x45e3,
+ 0x82ca, 0x475a,
+ 0x82cf, 0x4564,
+ 0x82d0, 0x37c1,
+ 0x82d1, 0x07f9,
+ 0x82d2, 0x07f3,
+ 0x82d3, 0x07fb,
+ 0x82d4, 0x07f8,
+ 0x82d5, 0x1be7,
+ 0x82d6, 0x1bea,
+ 0x82d7, 0x07f4,
+ 0x82d8, 0x475b,
+ 0x82d9, 0x1be1,
+ 0x82db, 0x07ed,
+ 0x82dc, 0x07f7,
+ 0x82de, 0x07fa,
+ 0x82df, 0x07fc,
+ 0x82e0, 0x1bf6,
+ 0x82e1, 0x1bed,
+ 0x82e2, 0x37c9,
+ 0x82e3, 0x07ec,
+ 0x82e4, 0x1bf5,
+ 0x82e5, 0x07f0,
+ 0x82e6, 0x07ee,
+ 0x82e7, 0x07e9,
+ 0x82e8, 0x1be5,
+ 0x82ea, 0x1bf4,
+ 0x82eb, 0x1be9,
+ 0x82ec, 0x1bec,
+ 0x82ed, 0x1bf9,
+ 0x82ee, 0x4018,
+ 0x82ef, 0x07fd,
+ 0x82f0, 0x1bf3,
+ 0x82f1, 0x07f5,
+ 0x82f2, 0x1bee,
+ 0x82f3, 0x1bf8,
+ 0x82f4, 0x1beb,
+ 0x82f5, 0x1bef,
+ 0x82f6, 0x1bf2,
+ 0x82f7, 0x3e77,
+ 0x82f9, 0x1be3,
+ 0x82fa, 0x1bf7,
+ 0x82fb, 0x1bf1,
+ 0x82fc, 0x412d,
+ 0x82fd, 0x3d92,
+ 0x82fe, 0x1be2,
+ 0x82ff, 0x43de,
+ 0x8300, 0x1be6,
+ 0x8301, 0x07f6,
+ 0x8302, 0x07f1,
+ 0x8303, 0x07ea,
+ 0x8304, 0x07ef,
+ 0x8305, 0x07eb,
+ 0x8306, 0x07fe,
+ 0x8307, 0x1be4,
+ 0x8308, 0x1dd0,
+ 0x8309, 0x07f2,
+ 0x830b, 0x3eb6,
+ 0x830c, 0x1bf0,
+ 0x830d, 0x1a7d,
+ 0x8316, 0x1dd3,
+ 0x8317, 0x09aa,
+ 0x8318, 0x37ca,
+ 0x8319, 0x1dc3,
+ 0x831a, 0x37c2,
+ 0x831b, 0x1dce,
+ 0x831c, 0x1dca,
+ 0x831d, 0x37d1,
+ 0x831e, 0x1ddd,
+ 0x8320, 0x1dd5,
+ 0x8322, 0x1dcb,
+ 0x8324, 0x1dd4,
+ 0x8325, 0x1dc5,
+ 0x8326, 0x1dc9,
+ 0x8327, 0x1de0,
+ 0x8328, 0x09ad,
+ 0x8329, 0x1dd8,
+ 0x832a, 0x1dcf,
+ 0x832b, 0x099d,
+ 0x832c, 0x1dde,
+ 0x832d, 0x1dc1,
+ 0x832f, 0x1dd7,
+ 0x8331, 0x09ac,
+ 0x8332, 0x09a7,
+ 0x8333, 0x1dc0,
+ 0x8334, 0x09a5,
+ 0x8335, 0x09a4,
+ 0x8336, 0x09a9,
+ 0x8337, 0x1dd6,
+ 0x8338, 0x09a1,
+ 0x8339, 0x09a8,
+ 0x833a, 0x1be8,
+ 0x833b, 0x2290,
+ 0x833c, 0x1dd1,
+ 0x833d, 0x3d2a,
+ 0x833f, 0x1dc7,
+ 0x8340, 0x09ab,
+ 0x8341, 0x1dc8,
+ 0x8342, 0x1dcc,
+ 0x8343, 0x09ae,
+ 0x8344, 0x1dc2,
+ 0x8345, 0x1dda,
+ 0x8347, 0x1dd9,
+ 0x8348, 0x1de1,
+ 0x8349, 0x09a3,
+ 0x834a, 0x09a0,
+ 0x834b, 0x1ddf,
+ 0x834c, 0x1ddb,
+ 0x834d, 0x1dd2,
+ 0x834e, 0x1dcd,
+ 0x834f, 0x09a6,
+ 0x8350, 0x09a2,
+ 0x8351, 0x1dc4,
+ 0x8352, 0x099e,
+ 0x8353, 0x1ddc,
+ 0x8354, 0x099f,
+ 0x8356, 0x1dc6,
+ 0x8357, 0x475d,
+ 0x8362, 0x37b6,
+ 0x8363, 0x41eb,
+ 0x8366, 0x3e1e,
+ 0x836f, 0x4565,
+ 0x8373, 0x201f,
+ 0x8374, 0x2021,
+ 0x8375, 0x2026,
+ 0x8376, 0x203a,
+ 0x8377, 0x0b83,
+ 0x8378, 0x0b79,
+ 0x837a, 0x201e,
+ 0x837b, 0x0b84,
+ 0x837d, 0x2029,
+ 0x837e, 0x2030,
+ 0x837f, 0x2036,
+ 0x8381, 0x2023,
+ 0x8383, 0x202a,
+ 0x8385, 0x37d3,
+ 0x8386, 0x0b86,
+ 0x8387, 0x2038,
+ 0x8388, 0x2033,
+ 0x8389, 0x0b81,
+ 0x838a, 0x0b7f,
+ 0x838b, 0x202f,
+ 0x838c, 0x202b,
+ 0x838d, 0x201d,
+ 0x838e, 0x0b76,
+ 0x838f, 0x2022,
+ 0x8390, 0x201a,
+ 0x8391, 0x37ec,
+ 0x8392, 0x0b7e,
+ 0x8393, 0x0b80,
+ 0x8394, 0x2027,
+ 0x8395, 0x2024,
+ 0x8396, 0x0b7b,
+ 0x8397, 0x2034,
+ 0x8398, 0x0b78,
+ 0x8399, 0x2025,
+ 0x839a, 0x22b9,
+ 0x839b, 0x202d,
+ 0x839c, 0x374d,
+ 0x839d, 0x202c,
+ 0x839e, 0x0b77,
+ 0x83a0, 0x0b82,
+ 0x83a2, 0x0b7a,
+ 0x83a3, 0x201b,
+ 0x83a4, 0x2020,
+ 0x83a5, 0x2031,
+ 0x83a6, 0x2037,
+ 0x83a7, 0x0b87,
+ 0x83a8, 0x201c,
+ 0x83a9, 0x2028,
+ 0x83aa, 0x202e,
+ 0x83ab, 0x0b7d,
+ 0x83ac, 0x37d6,
+ 0x83ae, 0x2039,
+ 0x83af, 0x2032,
+ 0x83b0, 0x2035,
+ 0x83b9, 0x42a7,
+ 0x83bd, 0x0b7c,
+ 0x83be, 0x3f59,
+ 0x83bf, 0x22a0,
+ 0x83c0, 0x2294,
+ 0x83c1, 0x0d35,
+ 0x83c2, 0x22b1,
+ 0x83c3, 0x22ba,
+ 0x83c4, 0x22bd,
+ 0x83c5, 0x0d33,
+ 0x83c6, 0x229c,
+ 0x83c7, 0x22b5,
+ 0x83c8, 0x229d,
+ 0x83c9, 0x22ab,
+ 0x83ca, 0x0d40,
+ 0x83cb, 0x22a7,
+ 0x83cc, 0x0d3d,
+ 0x83cd, 0x4055,
+ 0x83ce, 0x22a8,
+ 0x83cf, 0x2291,
+ 0x83d1, 0x22b6,
+ 0x83d3, 0x37d8,
+ 0x83d4, 0x0d46,
+ 0x83d5, 0x22b3,
+ 0x83d6, 0x22a9,
+ 0x83d7, 0x22bf,
+ 0x83d8, 0x22a4,
+ 0x83d9, 0x254e,
+ 0x83db, 0x22c2,
+ 0x83dc, 0x0d44,
+ 0x83dd, 0x22a2,
+ 0x83de, 0x22ae,
+ 0x83df, 0x0d47,
+ 0x83e0, 0x0d32,
+ 0x83e1, 0x22a6,
+ 0x83e2, 0x22c0,
+ 0x83e3, 0x229f,
+ 0x83e4, 0x2298,
+ 0x83e5, 0x22a3,
+ 0x83e7, 0x2297,
+ 0x83e8, 0x2295,
+ 0x83e9, 0x0d2e,
+ 0x83ea, 0x22b7,
+ 0x83eb, 0x229e,
+ 0x83ec, 0x22bb,
+ 0x83ed, 0x3d2c,
+ 0x83ee, 0x22bc,
+ 0x83ef, 0x0d36,
+ 0x83f0, 0x0d3b,
+ 0x83f1, 0x0d37,
+ 0x83f2, 0x0d3f,
+ 0x83f3, 0x22b2,
+ 0x83f4, 0x0d38,
+ 0x83f5, 0x22aa,
+ 0x83f6, 0x229a,
+ 0x83f8, 0x0d30,
+ 0x83f9, 0x2292,
+ 0x83fa, 0x22b4,
+ 0x83fb, 0x22be,
+ 0x83fc, 0x2299,
+ 0x83fd, 0x0d3e,
+ 0x83fe, 0x22c3,
+ 0x83ff, 0x22a5,
+ 0x8401, 0x22a1,
+ 0x8403, 0x0d2f,
+ 0x8404, 0x0d43,
+ 0x8405, 0x475f,
+ 0x8406, 0x22b0,
+ 0x8407, 0x0d45,
+ 0x8409, 0x22ac,
+ 0x840a, 0x0d3a,
+ 0x840b, 0x0d34,
+ 0x840c, 0x0d3c,
+ 0x840d, 0x0d31,
+ 0x840e, 0x0d42,
+ 0x840f, 0x22ad,
+ 0x8410, 0x229b,
+ 0x8411, 0x22af,
+ 0x8412, 0x2296,
+ 0x8413, 0x22b8,
+ 0x8414, 0x3c10,
+ 0x8416, 0x4037,
+ 0x8418, 0x3e7a,
+ 0x841b, 0x22c1,
+ 0x841c, 0x3eb3,
+ 0x8420, 0x3c55,
+ 0x8421, 0x3751,
+ 0x8423, 0x2293,
+ 0x8424, 0x4951,
+ 0x8426, 0x46d8,
+ 0x8429, 0x254d,
+ 0x842b, 0x2563,
+ 0x842c, 0x0eac,
+ 0x842d, 0x2552,
+ 0x842e, 0x422d,
+ 0x842f, 0x2550,
+ 0x8430, 0x253b,
+ 0x8431, 0x0ede,
+ 0x8432, 0x254b,
+ 0x8433, 0x255f,
+ 0x8434, 0x2547,
+ 0x8435, 0x0ee6,
+ 0x8436, 0x255e,
+ 0x8437, 0x2545,
+ 0x8438, 0x0d41,
+ 0x8439, 0x2555,
+ 0x843a, 0x2546,
+ 0x843b, 0x255c,
+ 0x843c, 0x0ee5,
+ 0x843d, 0x0edd,
+ 0x843e, 0x3d21,
+ 0x843f, 0x2530,
+ 0x8440, 0x2538,
+ 0x8442, 0x2551,
+ 0x8443, 0x2549,
+ 0x8444, 0x2562,
+ 0x8445, 0x254c,
+ 0x8446, 0x0eeb,
+ 0x8447, 0x255d,
+ 0x8448, 0x4718,
+ 0x8449, 0x0ee2,
+ 0x844a, 0x37e4,
+ 0x844b, 0x254f,
+ 0x844c, 0x2557,
+ 0x844d, 0x253c,
+ 0x844e, 0x2556,
+ 0x8450, 0x2567,
+ 0x8451, 0x2537,
+ 0x8452, 0x2558,
+ 0x8453, 0x3b7d,
+ 0x8454, 0x2565,
+ 0x8455, 0x398b,
+ 0x8456, 0x2531,
+ 0x8457, 0x0d39,
+ 0x8458, 0x37de,
+ 0x8459, 0x253f,
+ 0x845a, 0x253e,
+ 0x845b, 0x0ee4,
+ 0x845c, 0x3edb,
+ 0x845d, 0x2542,
+ 0x845e, 0x2544,
+ 0x845f, 0x2553,
+ 0x8460, 0x2564,
+ 0x8461, 0x0ee7,
+ 0x8462, 0x42da,
+ 0x8463, 0x0ee8,
+ 0x8464, 0x4761,
+ 0x8465, 0x2536,
+ 0x8466, 0x0ee0,
+ 0x8467, 0x253a,
+ 0x8468, 0x2560,
+ 0x8469, 0x0ee9,
+ 0x846b, 0x0ee1,
+ 0x846c, 0x0ee3,
+ 0x846d, 0x0eea,
+ 0x846e, 0x2566,
+ 0x846f, 0x2559,
+ 0x8470, 0x2554,
+ 0x8471, 0x37e0,
+ 0x8472, 0x3c93,
+ 0x8473, 0x2541,
+ 0x8474, 0x2540,
+ 0x8475, 0x0edf,
+ 0x8476, 0x2532,
+ 0x8477, 0x0edc,
+ 0x8478, 0x254a,
+ 0x8479, 0x2533,
+ 0x847a, 0x2548,
+ 0x847d, 0x253d,
+ 0x847e, 0x2561,
+ 0x847f, 0x394e,
+ 0x8480, 0x3b6e,
+ 0x8482, 0x0edb,
+ 0x8486, 0x2539,
+ 0x8488, 0x4762,
+ 0x848d, 0x2535,
+ 0x848e, 0x255b,
+ 0x848f, 0x2534,
+ 0x8490, 0x108e,
+ 0x8491, 0x27cd,
+ 0x8492, 0x3756,
+ 0x8493, 0x37ee,
+ 0x8494, 0x27bc,
+ 0x8496, 0x3b1d,
+ 0x8497, 0x27a6,
+ 0x8498, 0x27c4,
+ 0x8499, 0x1086,
+ 0x849a, 0x27b5,
+ 0x849b, 0x27bf,
+ 0x849c, 0x1089,
+ 0x849d, 0x27b8,
+ 0x849e, 0x1087,
+ 0x849f, 0x27a9,
+ 0x84a0, 0x27c7,
+ 0x84a1, 0x27a8,
+ 0x84a2, 0x27bb,
+ 0x84a3, 0x3b9e,
+ 0x84a4, 0x27a7,
+ 0x84a7, 0x27b9,
+ 0x84a8, 0x27c2,
+ 0x84a9, 0x27c0,
+ 0x84aa, 0x27b4,
+ 0x84ab, 0x27af,
+ 0x84ac, 0x27ad,
+ 0x84ad, 0x3d8c,
+ 0x84ae, 0x27ae,
+ 0x84af, 0x27c1,
+ 0x84b0, 0x27cc,
+ 0x84b1, 0x27b6,
+ 0x84b2, 0x1088,
+ 0x84b4, 0x27b1,
+ 0x84b6, 0x27c5,
+ 0x84b8, 0x108b,
+ 0x84b9, 0x27b0,
+ 0x84ba, 0x27aa,
+ 0x84bb, 0x27ba,
+ 0x84bc, 0x108f,
+ 0x84bd, 0x3c4c,
+ 0x84be, 0x4764,
+ 0x84bf, 0x1083,
+ 0x84c0, 0x108c,
+ 0x84c1, 0x27b2,
+ 0x84c2, 0x27ac,
+ 0x84c4, 0x1085,
+ 0x84c5, 0x255a,
+ 0x84c6, 0x1084,
+ 0x84c7, 0x27bd,
+ 0x84c9, 0x1082,
+ 0x84ca, 0x1091,
+ 0x84cb, 0x108a,
+ 0x84cc, 0x27be,
+ 0x84cd, 0x27b3,
+ 0x84ce, 0x27ab,
+ 0x84cf, 0x27c6,
+ 0x84d0, 0x27b7,
+ 0x84d1, 0x1090,
+ 0x84d2, 0x27ca,
+ 0x84d3, 0x108d,
+ 0x84d4, 0x27c9,
+ 0x84d6, 0x27c3,
+ 0x84d7, 0x27c8,
+ 0x84da, 0x3ff5,
+ 0x84db, 0x27cb,
+ 0x84de, 0x37ea,
+ 0x84e1, 0x4765,
+ 0x84e2, 0x37b5,
+ 0x84e4, 0x37ef,
+ 0x84e5, 0x3bd0,
+ 0x84e7, 0x2a03,
+ 0x84e9, 0x29f7,
+ 0x84ea, 0x29f6,
+ 0x84eb, 0x29f2,
+ 0x84ec, 0x11fb,
+ 0x84ee, 0x11f3,
+ 0x84ef, 0x2a06,
+ 0x84f0, 0x2a05,
+ 0x84f1, 0x252f,
+ 0x84f2, 0x29ef,
+ 0x84f3, 0x29f3,
+ 0x84f4, 0x29ed,
+ 0x84f6, 0x2a00,
+ 0x84f7, 0x29f1,
+ 0x84f8, 0x4766,
+ 0x84f9, 0x2a07,
+ 0x84fa, 0x29ea,
+ 0x84fb, 0x29e8,
+ 0x84fc, 0x29f4,
+ 0x84fd, 0x29fe,
+ 0x84fe, 0x29f9,
+ 0x84ff, 0x11fd,
+ 0x8500, 0x29df,
+ 0x8502, 0x29fd,
+ 0x8503, 0x398a,
+ 0x8505, 0x40eb,
+ 0x8506, 0x11fe,
+ 0x8507, 0x2543,
+ 0x8508, 0x29eb,
+ 0x8509, 0x29e2,
+ 0x850a, 0x29e5,
+ 0x850b, 0x2a0b,
+ 0x850c, 0x29ec,
+ 0x850d, 0x29e3,
+ 0x850e, 0x29e1,
+ 0x850f, 0x29de,
+ 0x8510, 0x4767,
+ 0x8511, 0x11f7,
+ 0x8512, 0x29f5,
+ 0x8513, 0x11f6,
+ 0x8514, 0x11fa,
+ 0x8515, 0x29f0,
+ 0x8516, 0x29f8,
+ 0x8517, 0x11f0,
+ 0x8518, 0x2a08,
+ 0x8519, 0x2a0c,
+ 0x851a, 0x11f2,
+ 0x851c, 0x29e7,
+ 0x851d, 0x29fb,
+ 0x851e, 0x29ff,
+ 0x851f, 0x29e4,
+ 0x8520, 0x2a09,
+ 0x8521, 0x11f9,
+ 0x8523, 0x11f8,
+ 0x8524, 0x29dc,
+ 0x8525, 0x11fc,
+ 0x8526, 0x2a02,
+ 0x8527, 0x29e6,
+ 0x8528, 0x29fa,
+ 0x8529, 0x29e0,
+ 0x852a, 0x29ee,
+ 0x852b, 0x29e9,
+ 0x852c, 0x11f4,
+ 0x852e, 0x29fc,
+ 0x852f, 0x2a0d,
+ 0x8530, 0x2a0a,
+ 0x8531, 0x2a01,
+ 0x8533, 0x4228,
+ 0x8534, 0x37f4,
+ 0x8538, 0x4768,
+ 0x853b, 0x29dd,
+ 0x853d, 0x11f1,
+ 0x853e, 0x2c4f,
+ 0x8540, 0x2c46,
+ 0x8541, 0x2c49,
+ 0x8542, 0x4062,
+ 0x8543, 0x133b,
+ 0x8544, 0x2c4b,
+ 0x8545, 0x2c40,
+ 0x8546, 0x2c47,
+ 0x8547, 0x2c4d,
+ 0x8548, 0x1338,
+ 0x8549, 0x133c,
+ 0x854a, 0x1336,
+ 0x854b, 0x37c0,
+ 0x854c, 0x400f,
+ 0x854d, 0x2c42,
+ 0x854e, 0x2c52,
+ 0x8551, 0x2c4c,
+ 0x8552, 0x4769,
+ 0x8553, 0x2c43,
+ 0x8554, 0x2c5b,
+ 0x8555, 0x2c55,
+ 0x8556, 0x2c3f,
+ 0x8557, 0x2e23,
+ 0x8558, 0x2c45,
+ 0x8559, 0x1337,
+ 0x855a, 0x37db,
+ 0x855b, 0x2c50,
+ 0x855d, 0x2c5a,
+ 0x855e, 0x133f,
+ 0x8560, 0x2c57,
+ 0x8561, 0x2c44,
+ 0x8562, 0x2c4a,
+ 0x8563, 0x2c4e,
+ 0x8564, 0x2c48,
+ 0x8565, 0x2c5c,
+ 0x8566, 0x2c59,
+ 0x8567, 0x2c56,
+ 0x8568, 0x1339,
+ 0x856a, 0x133e,
+ 0x856b, 0x2c41,
+ 0x856c, 0x2c5d,
+ 0x856d, 0x133d,
+ 0x856e, 0x2c53,
+ 0x856f, 0x476b,
+ 0x8571, 0x2c51,
+ 0x8573, 0x37f8,
+ 0x8575, 0x2c54,
+ 0x8576, 0x2e30,
+ 0x8577, 0x2e1d,
+ 0x8578, 0x2e22,
+ 0x8579, 0x2e2f,
+ 0x857a, 0x2e21,
+ 0x857b, 0x2e19,
+ 0x857c, 0x2e1e,
+ 0x857e, 0x145c,
+ 0x8580, 0x2e12,
+ 0x8581, 0x2e2a,
+ 0x8582, 0x2e2c,
+ 0x8583, 0x2e11,
+ 0x8584, 0x145b,
+ 0x8585, 0x2e2e,
+ 0x8586, 0x2e26,
+ 0x8587, 0x1462,
+ 0x8588, 0x2e2d,
+ 0x8589, 0x2e1f,
+ 0x858a, 0x1464,
+ 0x858b, 0x2e17,
+ 0x858c, 0x2c58,
+ 0x858d, 0x2e27,
+ 0x858e, 0x2e24,
+ 0x858f, 0x2e13,
+ 0x8590, 0x2e32,
+ 0x8591, 0x145e,
+ 0x8594, 0x145f,
+ 0x8595, 0x2e15,
+ 0x8596, 0x2e25,
+ 0x8598, 0x2e31,
+ 0x8599, 0x2e28,
+ 0x859a, 0x2e1b,
+ 0x859b, 0x1461,
+ 0x859c, 0x145d,
+ 0x859d, 0x2e29,
+ 0x859e, 0x2e1c,
+ 0x859f, 0x2e33,
+ 0x85a0, 0x2e16,
+ 0x85a1, 0x2e20,
+ 0x85a2, 0x2e2b,
+ 0x85a3, 0x2e18,
+ 0x85a4, 0x2e1a,
+ 0x85a6, 0x1465,
+ 0x85a7, 0x2e14,
+ 0x85a8, 0x1463,
+ 0x85a9, 0x151c,
+ 0x85aa, 0x145a,
+ 0x85af, 0x1460,
+ 0x85b0, 0x1520,
+ 0x85b1, 0x2fa6,
+ 0x85b3, 0x2f9c,
+ 0x85b4, 0x2f97,
+ 0x85b5, 0x2f9d,
+ 0x85b6, 0x2fa7,
+ 0x85b7, 0x2fab,
+ 0x85b8, 0x2faa,
+ 0x85b9, 0x1522,
+ 0x85ba, 0x1521,
+ 0x85bd, 0x2f9e,
+ 0x85be, 0x2fac,
+ 0x85bf, 0x2fa1,
+ 0x85c0, 0x2f99,
+ 0x85c1, 0x37fe,
+ 0x85c2, 0x2f9b,
+ 0x85c3, 0x2f9a,
+ 0x85c4, 0x2fa0,
+ 0x85c5, 0x2fa5,
+ 0x85c6, 0x2f98,
+ 0x85c7, 0x2f9f,
+ 0x85c8, 0x2fa4,
+ 0x85c9, 0x151f,
+ 0x85cb, 0x2fa2,
+ 0x85cd, 0x151d,
+ 0x85ce, 0x2fa3,
+ 0x85cf, 0x151b,
+ 0x85d0, 0x151e,
+ 0x85d1, 0x3101,
+ 0x85d2, 0x2fa8,
+ 0x85d5, 0x15b7,
+ 0x85d7, 0x30f9,
+ 0x85d8, 0x30fd,
+ 0x85d9, 0x30f5,
+ 0x85da, 0x30f8,
+ 0x85dc, 0x3100,
+ 0x85dd, 0x15b5,
+ 0x85de, 0x3105,
+ 0x85df, 0x30fe,
+ 0x85e0, 0x476d,
+ 0x85e1, 0x30f6,
+ 0x85e2, 0x3106,
+ 0x85e3, 0x30ff,
+ 0x85e4, 0x15b8,
+ 0x85e6, 0x3103,
+ 0x85e8, 0x30f7,
+ 0x85e9, 0x15b4,
+ 0x85ea, 0x15b6,
+ 0x85eb, 0x30f2,
+ 0x85ec, 0x30fa,
+ 0x85ed, 0x30f4,
+ 0x85ee, 0x3c56,
+ 0x85ef, 0x3104,
+ 0x85f0, 0x3102,
+ 0x85f1, 0x30f3,
+ 0x85f2, 0x30fb,
+ 0x85f6, 0x3225,
+ 0x85f7, 0x15ba,
+ 0x85f8, 0x30fc,
+ 0x85f9, 0x1638,
+ 0x85fa, 0x163a,
+ 0x85fb, 0x1637,
+ 0x85fc, 0x3c50,
+ 0x85fd, 0x322a,
+ 0x85fe, 0x3222,
+ 0x85ff, 0x3220,
+ 0x8600, 0x3224,
+ 0x8601, 0x3221,
+ 0x8602, 0x3800,
+ 0x8604, 0x3226,
+ 0x8605, 0x3228,
+ 0x8606, 0x163b,
+ 0x8607, 0x163d,
+ 0x8609, 0x3227,
+ 0x860a, 0x163e,
+ 0x860b, 0x163c,
+ 0x860c, 0x3229,
+ 0x860d, 0x4064,
+ 0x8610, 0x3b7f,
+ 0x8611, 0x1639,
+ 0x8614, 0x46be,
+ 0x8616, 0x37fb,
+ 0x8617, 0x1685,
+ 0x8618, 0x32f6,
+ 0x8619, 0x32fc,
+ 0x861a, 0x1687,
+ 0x861b, 0x3223,
+ 0x861c, 0x32fb,
+ 0x861e, 0x3302,
+ 0x861f, 0x32f9,
+ 0x8620, 0x3300,
+ 0x8621, 0x32ff,
+ 0x8622, 0x321f,
+ 0x8623, 0x32fa,
+ 0x8624, 0x2fa9,
+ 0x8625, 0x3303,
+ 0x8626, 0x32f8,
+ 0x8627, 0x32fd,
+ 0x8628, 0x3805,
+ 0x8629, 0x3301,
+ 0x862a, 0x32f7,
+ 0x862c, 0x33aa,
+ 0x862d, 0x1686,
+ 0x862e, 0x32fe,
+ 0x862f, 0x3f9e,
+ 0x8631, 0x3432,
+ 0x8632, 0x33ab,
+ 0x8633, 0x33a9,
+ 0x8634, 0x33a7,
+ 0x8636, 0x33ac,
+ 0x8638, 0x1707,
+ 0x8639, 0x3430,
+ 0x863a, 0x342e,
+ 0x863b, 0x3433,
+ 0x863c, 0x3431,
+ 0x863e, 0x3434,
+ 0x863f, 0x1708,
+ 0x8640, 0x342f,
+ 0x8642, 0x38c1,
+ 0x8643, 0x3497,
+ 0x8645, 0x3b66,
+ 0x8646, 0x34df,
+ 0x864b, 0x353e,
+ 0x864c, 0x3536,
+ 0x864d, 0x1818,
+ 0x864e, 0x0689,
+ 0x8650, 0x07ff,
+ 0x8652, 0x1de3,
+ 0x8653, 0x1de2,
+ 0x8654, 0x09af,
+ 0x8655, 0x0b88,
+ 0x8656, 0x203c,
+ 0x8659, 0x203b,
+ 0x865b, 0x0d48,
+ 0x865c, 0x0eed,
+ 0x865e, 0x0eec,
+ 0x865f, 0x0eee,
+ 0x8661, 0x27ce,
+ 0x8662, 0x2a0e,
+ 0x8663, 0x2c5e,
+ 0x8664, 0x2c60,
+ 0x8665, 0x2c5f,
+ 0x8667, 0x1466,
+ 0x8668, 0x2e34,
+ 0x8669, 0x2fad,
+ 0x866a, 0x351e,
+ 0x866b, 0x040f,
+ 0x866c, 0x3813,
+ 0x866d, 0x1a46,
+ 0x866f, 0x1a45,
+ 0x8670, 0x1a44,
+ 0x8671, 0x068a,
+ 0x8672, 0x476f,
+ 0x8673, 0x1bfd,
+ 0x8674, 0x1bfb,
+ 0x8677, 0x1bfa,
+ 0x8679, 0x0800,
+ 0x867a, 0x0802,
+ 0x867b, 0x0801,
+ 0x867c, 0x1bfc,
+ 0x867e, 0x380a,
+ 0x8685, 0x1def,
+ 0x8686, 0x1dec,
+ 0x8687, 0x1dea,
+ 0x868a, 0x09b0,
+ 0x868b, 0x1ded,
+ 0x868c, 0x09b5,
+ 0x868d, 0x1de7,
+ 0x868e, 0x1df6,
+ 0x8690, 0x1df8,
+ 0x8691, 0x1de8,
+ 0x8692, 0x4770,
+ 0x8693, 0x09b2,
+ 0x8694, 0x1df9,
+ 0x8695, 0x1df4,
+ 0x8696, 0x1de6,
+ 0x8697, 0x1deb,
+ 0x8698, 0x1df5,
+ 0x8699, 0x1df1,
+ 0x869a, 0x1dee,
+ 0x869c, 0x09b7,
+ 0x869d, 0x1df7,
+ 0x869e, 0x1de9,
+ 0x86a0, 0x3b88,
+ 0x86a1, 0x1df2,
+ 0x86a2, 0x1de4,
+ 0x86a3, 0x09b6,
+ 0x86a4, 0x09b3,
+ 0x86a5, 0x1df0,
+ 0x86a7, 0x1df3,
+ 0x86a8, 0x1de5,
+ 0x86a9, 0x09b4,
+ 0x86aa, 0x09b1,
+ 0x86ad, 0x3f06,
+ 0x86af, 0x0b92,
+ 0x86b0, 0x2043,
+ 0x86b1, 0x0b91,
+ 0x86b2, 0x43e0,
+ 0x86b3, 0x2046,
+ 0x86b4, 0x2049,
+ 0x86b5, 0x0b8e,
+ 0x86b6, 0x0b8c,
+ 0x86b7, 0x203e,
+ 0x86b8, 0x2047,
+ 0x86b9, 0x2045,
+ 0x86ba, 0x2042,
+ 0x86bb, 0x204a,
+ 0x86bd, 0x204d,
+ 0x86bf, 0x203d,
+ 0x86c0, 0x0b8b,
+ 0x86c1, 0x2040,
+ 0x86c2, 0x203f,
+ 0x86c3, 0x204c,
+ 0x86c4, 0x0b8d,
+ 0x86c5, 0x2041,
+ 0x86c6, 0x0b8f,
+ 0x86c7, 0x0b8a,
+ 0x86c8, 0x2044,
+ 0x86c9, 0x0b93,
+ 0x86cb, 0x0b90,
+ 0x86cc, 0x2048,
+ 0x86d0, 0x0d4f,
+ 0x86d1, 0x22d2,
+ 0x86d3, 0x22c7,
+ 0x86d4, 0x0d4c,
+ 0x86d6, 0x256d,
+ 0x86d7, 0x22d0,
+ 0x86d8, 0x22c4,
+ 0x86d9, 0x0d4a,
+ 0x86da, 0x22c9,
+ 0x86db, 0x0d4d,
+ 0x86dc, 0x22cd,
+ 0x86dd, 0x22cb,
+ 0x86de, 0x0d50,
+ 0x86df, 0x0d49,
+ 0x86e2, 0x22c5,
+ 0x86e3, 0x22c8,
+ 0x86e4, 0x0d4e,
+ 0x86e6, 0x22c6,
+ 0x86e8, 0x22d1,
+ 0x86e9, 0x22cf,
+ 0x86ea, 0x22ca,
+ 0x86eb, 0x22cc,
+ 0x86ec, 0x22ce,
+ 0x86ed, 0x0d4b,
+ 0x86ef, 0x4771,
+ 0x86f5, 0x256e,
+ 0x86f6, 0x2574,
+ 0x86f7, 0x256a,
+ 0x86f8, 0x2570,
+ 0x86f9, 0x0eef,
+ 0x86fa, 0x256c,
+ 0x86fb, 0x0ef5,
+ 0x86fe, 0x0ef4,
+ 0x8700, 0x0ef3,
+ 0x8701, 0x2573,
+ 0x8702, 0x0ef6,
+ 0x8704, 0x2569,
+ 0x8705, 0x2576,
+ 0x8706, 0x0ef8,
+ 0x8707, 0x0ef2,
+ 0x8708, 0x0ef1,
+ 0x8709, 0x2572,
+ 0x870a, 0x0ef9,
+ 0x870b, 0x2568,
+ 0x870c, 0x256b,
+ 0x870d, 0x2575,
+ 0x870e, 0x2571,
+ 0x8711, 0x27ee,
+ 0x8712, 0x27e3,
+ 0x8713, 0x0ef0,
+ 0x8718, 0x1098,
+ 0x8719, 0x27d7,
+ 0x871a, 0x27ec,
+ 0x871b, 0x27d8,
+ 0x871c, 0x1093,
+ 0x871e, 0x27d5,
+ 0x8720, 0x27de,
+ 0x8721, 0x27d6,
+ 0x8722, 0x1095,
+ 0x8723, 0x27d0,
+ 0x8724, 0x27eb,
+ 0x8725, 0x1096,
+ 0x8726, 0x27e8,
+ 0x8728, 0x27d1,
+ 0x8729, 0x109b,
+ 0x872a, 0x27e0,
+ 0x872c, 0x27da,
+ 0x872d, 0x27e1,
+ 0x872e, 0x27d4,
+ 0x8730, 0x27ed,
+ 0x8731, 0x27e5,
+ 0x8732, 0x27df,
+ 0x8733, 0x27cf,
+ 0x8734, 0x1097,
+ 0x8735, 0x27e6,
+ 0x8737, 0x109a,
+ 0x8738, 0x27ea,
+ 0x873a, 0x27e4,
+ 0x873b, 0x1094,
+ 0x873c, 0x27e2,
+ 0x873e, 0x27dc,
+ 0x873f, 0x1092,
+ 0x8740, 0x27d3,
+ 0x8741, 0x27db,
+ 0x8742, 0x27e7,
+ 0x8743, 0x27d9,
+ 0x8746, 0x27dd,
+ 0x874c, 0x1208,
+ 0x874d, 0x256f,
+ 0x874e, 0x2a20,
+ 0x874f, 0x2a29,
+ 0x8750, 0x2a1f,
+ 0x8751, 0x2a1b,
+ 0x8752, 0x2a18,
+ 0x8753, 0x1209,
+ 0x8754, 0x2a16,
+ 0x8755, 0x1099,
+ 0x8756, 0x2a0f,
+ 0x8757, 0x1207,
+ 0x8758, 0x2a15,
+ 0x8759, 0x1206,
+ 0x875a, 0x2a1a,
+ 0x875b, 0x2a17,
+ 0x875c, 0x2a27,
+ 0x875d, 0x2a22,
+ 0x875e, 0x2a1c,
+ 0x875f, 0x2a21,
+ 0x8760, 0x1202,
+ 0x8761, 0x2a19,
+ 0x8762, 0x2a2c,
+ 0x8763, 0x2a10,
+ 0x8765, 0x2a28,
+ 0x8766, 0x1203,
+ 0x8767, 0x2a2d,
+ 0x8768, 0x1205,
+ 0x8769, 0x2a2e,
+ 0x876a, 0x2a1e,
+ 0x876b, 0x27d2,
+ 0x876c, 0x2a24,
+ 0x876d, 0x2a1d,
+ 0x876e, 0x2a26,
+ 0x876f, 0x2a23,
+ 0x8770, 0x3e6c,
+ 0x8771, 0x380b,
+ 0x8773, 0x2a14,
+ 0x8774, 0x1200,
+ 0x8775, 0x2a2b,
+ 0x8776, 0x1201,
+ 0x8777, 0x2a12,
+ 0x8778, 0x1204,
+ 0x8779, 0x2c6b,
+ 0x877a, 0x2a25,
+ 0x877b, 0x2a2a,
+ 0x877d, 0x4045,
+ 0x8781, 0x2c68,
+ 0x8782, 0x11ff,
+ 0x8783, 0x1340,
+ 0x8784, 0x2c72,
+ 0x8785, 0x2c6e,
+ 0x8786, 0x3eb0,
+ 0x8787, 0x2c6c,
+ 0x8788, 0x2c67,
+ 0x8789, 0x2c76,
+ 0x878b, 0x43e2,
+ 0x878c, 0x3fef,
+ 0x878d, 0x1344,
+ 0x878f, 0x2c63,
+ 0x8790, 0x2c6f,
+ 0x8792, 0x2c66,
+ 0x8793, 0x2c65,
+ 0x8794, 0x2c73,
+ 0x8796, 0x2c69,
+ 0x8797, 0x2c64,
+ 0x8798, 0x2c6a,
+ 0x879a, 0x2c75,
+ 0x879b, 0x2c62,
+ 0x879c, 0x2c74,
+ 0x879d, 0x2c71,
+ 0x879e, 0x1342,
+ 0x879f, 0x1341,
+ 0x87a2, 0x1343,
+ 0x87a3, 0x2c6d,
+ 0x87a4, 0x2c61,
+ 0x87a5, 0x3d88,
+ 0x87a9, 0x3fec,
+ 0x87aa, 0x2e36,
+ 0x87ab, 0x146c,
+ 0x87ac, 0x2e3a,
+ 0x87ad, 0x2e37,
+ 0x87ae, 0x2e3e,
+ 0x87af, 0x2e44,
+ 0x87b0, 0x2e39,
+ 0x87b1, 0x380f,
+ 0x87b2, 0x2e4d,
+ 0x87b3, 0x1469,
+ 0x87b4, 0x2e47,
+ 0x87b5, 0x2e3c,
+ 0x87b6, 0x2e48,
+ 0x87b7, 0x2e43,
+ 0x87b8, 0x2e4a,
+ 0x87b9, 0x2e3b,
+ 0x87ba, 0x146e,
+ 0x87bb, 0x146d,
+ 0x87bc, 0x2e3d,
+ 0x87bd, 0x2e4b,
+ 0x87be, 0x2e35,
+ 0x87bf, 0x2e49,
+ 0x87c0, 0x1467,
+ 0x87c1, 0x3ffc,
+ 0x87c2, 0x2e41,
+ 0x87c3, 0x2e40,
+ 0x87c4, 0x2e45,
+ 0x87c5, 0x2e38,
+ 0x87c6, 0x146b,
+ 0x87c8, 0x146f,
+ 0x87c9, 0x2e3f,
+ 0x87ca, 0x2e46,
+ 0x87cb, 0x1470,
+ 0x87cc, 0x2e42,
+ 0x87ce, 0x3fed,
+ 0x87d1, 0x1468,
+ 0x87d2, 0x146a,
+ 0x87d3, 0x2fba,
+ 0x87d4, 0x2fb8,
+ 0x87d6, 0x3f92,
+ 0x87d7, 0x2fbe,
+ 0x87d8, 0x2fbc,
+ 0x87d9, 0x2fbf,
+ 0x87da, 0x3810,
+ 0x87db, 0x2fb1,
+ 0x87dc, 0x2fb9,
+ 0x87dd, 0x2fc3,
+ 0x87de, 0x2e4c,
+ 0x87df, 0x2fb5,
+ 0x87e0, 0x1526,
+ 0x87e1, 0x2a13,
+ 0x87e2, 0x2fb0,
+ 0x87e3, 0x2fbd,
+ 0x87e4, 0x2fb7,
+ 0x87e5, 0x2fb4,
+ 0x87e6, 0x2faf,
+ 0x87e7, 0x2fae,
+ 0x87e8, 0x2fc2,
+ 0x87ea, 0x2fb3,
+ 0x87eb, 0x2fb2,
+ 0x87ec, 0x1524,
+ 0x87ed, 0x2fbb,
+ 0x87ee, 0x380d,
+ 0x87ef, 0x1523,
+ 0x87f2, 0x1525,
+ 0x87f3, 0x2fb6,
+ 0x87f4, 0x2fc1,
+ 0x87f5, 0x3fae,
+ 0x87f6, 0x310a,
+ 0x87f9, 0x15be,
+ 0x87fa, 0x3108,
+ 0x87fb, 0x15bb,
+ 0x87fc, 0x3110,
+ 0x87fe, 0x15bf,
+ 0x87ff, 0x3112,
+ 0x8800, 0x3107,
+ 0x8801, 0x2fc0,
+ 0x8802, 0x3114,
+ 0x8803, 0x3109,
+ 0x8804, 0x3eaf,
+ 0x8805, 0x15bc,
+ 0x8806, 0x310f,
+ 0x8808, 0x3111,
+ 0x8809, 0x310c,
+ 0x880a, 0x3113,
+ 0x880b, 0x310e,
+ 0x880c, 0x310d,
+ 0x880d, 0x15bd,
+ 0x880f, 0x3811,
+ 0x8810, 0x322c,
+ 0x8813, 0x322f,
+ 0x8814, 0x163f,
+ 0x8816, 0x3230,
+ 0x8817, 0x322e,
+ 0x8818, 0x3f7a,
+ 0x8819, 0x322b,
+ 0x881b, 0x3306,
+ 0x881c, 0x3309,
+ 0x881d, 0x3305,
+ 0x881f, 0x168b,
+ 0x8820, 0x3307,
+ 0x8821, 0x168a,
+ 0x8822, 0x1689,
+ 0x8823, 0x1688,
+ 0x8824, 0x3308,
+ 0x8825, 0x33b1,
+ 0x8826, 0x33af,
+ 0x8827, 0x3e07,
+ 0x8828, 0x33ae,
+ 0x8829, 0x3304,
+ 0x882a, 0x33b0,
+ 0x882b, 0x330a,
+ 0x882c, 0x33ad,
+ 0x882d, 0x3b8b,
+ 0x882e, 0x3437,
+ 0x882f, 0x3415,
+ 0x8830, 0x3435,
+ 0x8831, 0x1709,
+ 0x8832, 0x3436,
+ 0x8833, 0x3438,
+ 0x8835, 0x349a,
+ 0x8836, 0x1728,
+ 0x8837, 0x3499,
+ 0x8838, 0x3498,
+ 0x8839, 0x1729,
+ 0x883b, 0x1747,
+ 0x883c, 0x3508,
+ 0x883d, 0x3520,
+ 0x883e, 0x351f,
+ 0x883f, 0x3521,
+ 0x8840, 0x0410,
+ 0x8841, 0x1bfe,
+ 0x8842, 0x3f5a,
+ 0x8843, 0x1dfa,
+ 0x8845, 0x3816,
+ 0x8848, 0x22d3,
+ 0x884a, 0x330b,
+ 0x884b, 0x349b,
+ 0x884c, 0x0411,
+ 0x884d, 0x0803,
+ 0x884e, 0x1bff,
+ 0x884f, 0x3844,
+ 0x8852, 0x204f,
+ 0x8853, 0x0b94,
+ 0x8855, 0x22d5,
+ 0x8856, 0x22d4,
+ 0x8857, 0x0d51,
+ 0x8859, 0x0efa,
+ 0x885a, 0x2a2f,
+ 0x885b, 0x120a,
+ 0x885d, 0x120b,
+ 0x885e, 0x381b,
+ 0x8860, 0x3a46,
+ 0x8861, 0x1345,
+ 0x8862, 0x172a,
+ 0x8863, 0x0412,
+ 0x8864, 0x4502,
+ 0x8865, 0x3dfc,
+ 0x8867, 0x1c00,
+ 0x8868, 0x068c,
+ 0x8869, 0x1c02,
+ 0x886a, 0x1c01,
+ 0x886b, 0x0804,
+ 0x886d, 0x1dfc,
+ 0x886e, 0x3b8e,
+ 0x886f, 0x1e03,
+ 0x8870, 0x09b8,
+ 0x8871, 0x1e01,
+ 0x8872, 0x1dff,
+ 0x8874, 0x1e06,
+ 0x8875, 0x1dfd,
+ 0x8877, 0x09b9,
+ 0x8879, 0x09bd,
+ 0x887c, 0x1e07,
+ 0x887d, 0x09bc,
+ 0x887e, 0x1e05,
+ 0x887f, 0x1e02,
+ 0x8880, 0x1e00,
+ 0x8881, 0x09ba,
+ 0x8883, 0x1e04,
+ 0x8884, 0x42f7,
+ 0x8887, 0x3b90,
+ 0x8888, 0x0b96,
+ 0x8889, 0x2050,
+ 0x888b, 0x0b9b,
+ 0x888c, 0x2060,
+ 0x888d, 0x0b9a,
+ 0x888e, 0x2062,
+ 0x8891, 0x2056,
+ 0x8892, 0x0b98,
+ 0x8893, 0x2061,
+ 0x8895, 0x2051,
+ 0x8896, 0x0b99,
+ 0x8897, 0x205d,
+ 0x8898, 0x2059,
+ 0x8899, 0x205b,
+ 0x889a, 0x2055,
+ 0x889b, 0x205c,
+ 0x889c, 0x381c,
+ 0x889e, 0x0b95,
+ 0x889f, 0x2058,
+ 0x88a0, 0x3fa0,
+ 0x88a1, 0x2057,
+ 0x88a2, 0x2053,
+ 0x88a4, 0x205e,
+ 0x88a7, 0x205a,
+ 0x88a8, 0x2052,
+ 0x88aa, 0x2054,
+ 0x88ab, 0x0b97,
+ 0x88ac, 0x205f,
+ 0x88ae, 0x4775,
+ 0x88b1, 0x0d54,
+ 0x88b2, 0x22e0,
+ 0x88b4, 0x381e,
+ 0x88b6, 0x22dc,
+ 0x88b7, 0x22de,
+ 0x88b8, 0x22d9,
+ 0x88b9, 0x22d8,
+ 0x88ba, 0x22d6,
+ 0x88bc, 0x22dd,
+ 0x88bd, 0x22df,
+ 0x88be, 0x22db,
+ 0x88bf, 0x3b91,
+ 0x88c0, 0x22da,
+ 0x88c1, 0x0d52,
+ 0x88c5, 0x3820,
+ 0x88c7, 0x3eb1,
+ 0x88c9, 0x22e2,
+ 0x88ca, 0x0f02,
+ 0x88cb, 0x2578,
+ 0x88cc, 0x257e,
+ 0x88cd, 0x2579,
+ 0x88cf, 0x36ea,
+ 0x88d0, 0x257f,
+ 0x88d2, 0x0f04,
+ 0x88d4, 0x0efc,
+ 0x88d5, 0x0f03,
+ 0x88d6, 0x2577,
+ 0x88d7, 0x22d7,
+ 0x88d8, 0x0eff,
+ 0x88d9, 0x0efd,
+ 0x88da, 0x257d,
+ 0x88db, 0x257c,
+ 0x88dc, 0x0efe,
+ 0x88dd, 0x0f00,
+ 0x88de, 0x257b,
+ 0x88df, 0x0efb,
+ 0x88e1, 0x0f01,
+ 0x88e6, 0x3b92,
+ 0x88e7, 0x27f0,
+ 0x88e8, 0x10a2,
+ 0x88eb, 0x27fb,
+ 0x88ec, 0x27fa,
+ 0x88ee, 0x27f5,
+ 0x88ef, 0x10a4,
+ 0x88f0, 0x27f9,
+ 0x88f1, 0x27f1,
+ 0x88f3, 0x109c,
+ 0x88f4, 0x109e,
+ 0x88f5, 0x3e08,
+ 0x88f6, 0x27f7,
+ 0x88f7, 0x27ef,
+ 0x88f8, 0x10a0,
+ 0x88f9, 0x109f,
+ 0x88fa, 0x27f3,
+ 0x88fb, 0x27f8,
+ 0x88fc, 0x27f6,
+ 0x88fd, 0x10a1,
+ 0x88fe, 0x27f4,
+ 0x88ff, 0x4776,
+ 0x8900, 0x42fa,
+ 0x8901, 0x22e1,
+ 0x8902, 0x109d,
+ 0x8905, 0x2a30,
+ 0x8906, 0x2a37,
+ 0x8907, 0x120d,
+ 0x8909, 0x2a3b,
+ 0x890a, 0x1211,
+ 0x890b, 0x2a33,
+ 0x890c, 0x2a31,
+ 0x890e, 0x2a3a,
+ 0x8910, 0x120c,
+ 0x8911, 0x2a39,
+ 0x8912, 0x120e,
+ 0x8914, 0x2a32,
+ 0x8915, 0x1210,
+ 0x8916, 0x2a38,
+ 0x8917, 0x2a34,
+ 0x891a, 0x10a3,
+ 0x891e, 0x2c77,
+ 0x891f, 0x2c83,
+ 0x8921, 0x134a,
+ 0x8922, 0x2c7e,
+ 0x8923, 0x2c80,
+ 0x8924, 0x4777,
+ 0x8925, 0x1348,
+ 0x8926, 0x2c78,
+ 0x8927, 0x2c7c,
+ 0x8929, 0x2c7f,
+ 0x892a, 0x1346,
+ 0x892b, 0x1349,
+ 0x892c, 0x2c82,
+ 0x892d, 0x2c7a,
+ 0x892f, 0x2c81,
+ 0x8930, 0x2c79,
+ 0x8931, 0x2c7d,
+ 0x8932, 0x1347,
+ 0x8933, 0x2e4f,
+ 0x8935, 0x2e4e,
+ 0x8936, 0x1472,
+ 0x8937, 0x2e54,
+ 0x8938, 0x1474,
+ 0x893b, 0x1471,
+ 0x893c, 0x2e50,
+ 0x893d, 0x1475,
+ 0x893e, 0x2e51,
+ 0x8941, 0x2e52,
+ 0x8942, 0x2e55,
+ 0x8943, 0x3e16,
+ 0x8944, 0x1473,
+ 0x8946, 0x2fc8,
+ 0x8947, 0x43e3,
+ 0x8949, 0x2fcb,
+ 0x894b, 0x2fc5,
+ 0x894c, 0x2fc7,
+ 0x894d, 0x3b94,
+ 0x894f, 0x2fc6,
+ 0x8950, 0x2fc9,
+ 0x8952, 0x2e53,
+ 0x8953, 0x2fc4,
+ 0x8954, 0x3b96,
+ 0x8956, 0x15c2,
+ 0x8957, 0x3118,
+ 0x8958, 0x311b,
+ 0x8959, 0x311d,
+ 0x895a, 0x3116,
+ 0x895c, 0x311a,
+ 0x895d, 0x311c,
+ 0x895e, 0x15c3,
+ 0x895f, 0x15c1,
+ 0x8960, 0x15c0,
+ 0x8961, 0x3119,
+ 0x8962, 0x3115,
+ 0x8963, 0x3231,
+ 0x8964, 0x1641,
+ 0x8965, 0x3b93,
+ 0x8966, 0x3232,
+ 0x8969, 0x330d,
+ 0x896a, 0x168c,
+ 0x896b, 0x330f,
+ 0x896c, 0x168d,
+ 0x896d, 0x330c,
+ 0x896e, 0x330e,
+ 0x896f, 0x16d6,
+ 0x8971, 0x33b2,
+ 0x8972, 0x16d5,
+ 0x8973, 0x343b,
+ 0x8974, 0x343a,
+ 0x8976, 0x3439,
+ 0x8977, 0x3dea,
+ 0x8979, 0x34e2,
+ 0x897b, 0x34e5,
+ 0x897c, 0x34e4,
+ 0x897e, 0x1819,
+ 0x897f, 0x0413,
+ 0x8980, 0x4708,
+ 0x8981, 0x0805,
+ 0x8982, 0x2063,
+ 0x8983, 0x0d55,
+ 0x8985, 0x2580,
+ 0x8986, 0x1527,
+ 0x8987, 0x3822,
+ 0x8988, 0x311e,
+ 0x8989, 0x3fe9,
+ 0x898a, 0x3823,
+ 0x898b, 0x0508,
+ 0x898f, 0x0b9d,
+ 0x8991, 0x4778,
+ 0x8993, 0x0b9c,
+ 0x8994, 0x3fe0,
+ 0x8995, 0x22e3,
+ 0x8996, 0x0d56,
+ 0x8997, 0x22e5,
+ 0x8998, 0x22e4,
+ 0x899b, 0x2581,
+ 0x899c, 0x0f05,
+ 0x899d, 0x27fc,
+ 0x899e, 0x27ff,
+ 0x899f, 0x27fe,
+ 0x89a1, 0x27fd,
+ 0x89a2, 0x2a3c,
+ 0x89a3, 0x2a3e,
+ 0x89a4, 0x2a3d,
+ 0x89a5, 0x3d93,
+ 0x89a6, 0x134c,
+ 0x89a7, 0x3826,
+ 0x89a9, 0x3825,
+ 0x89aa, 0x134b,
+ 0x89ac, 0x1476,
+ 0x89ad, 0x2e56,
+ 0x89ae, 0x2e58,
+ 0x89af, 0x2e57,
+ 0x89b2, 0x1528,
+ 0x89b6, 0x3120,
+ 0x89b7, 0x311f,
+ 0x89b9, 0x3233,
+ 0x89ba, 0x1642,
+ 0x89bc, 0x3827,
+ 0x89bd, 0x168e,
+ 0x89be, 0x33b4,
+ 0x89bf, 0x33b3,
+ 0x89c0, 0x1748,
+ 0x89c1, 0x4503,
+ 0x89c6, 0x4566,
+ 0x89d2, 0x0509,
+ 0x89d3, 0x1c03,
+ 0x89d4, 0x0806,
+ 0x89d5, 0x2066,
+ 0x89d6, 0x2064,
+ 0x89d9, 0x2065,
+ 0x89da, 0x22e7,
+ 0x89dc, 0x2588,
+ 0x89dd, 0x22e6,
+ 0x89df, 0x2582,
+ 0x89e0, 0x2586,
+ 0x89e1, 0x2585,
+ 0x89e2, 0x2587,
+ 0x89e3, 0x0f06,
+ 0x89e4, 0x2584,
+ 0x89e5, 0x2583,
+ 0x89e6, 0x2589,
+ 0x89e7, 0x3829,
+ 0x89e8, 0x2802,
+ 0x89e9, 0x2800,
+ 0x89eb, 0x2801,
+ 0x89ec, 0x2a41,
+ 0x89ed, 0x2a3f,
+ 0x89f0, 0x2a40,
+ 0x89f1, 0x2c84,
+ 0x89f2, 0x2e59,
+ 0x89f4, 0x1529,
+ 0x89f6, 0x3121,
+ 0x89f7, 0x3234,
+ 0x89f8, 0x1643,
+ 0x89fa, 0x3310,
+ 0x89fb, 0x33b5,
+ 0x89fc, 0x16d7,
+ 0x89fe, 0x343c,
+ 0x89ff, 0x34e6,
+ 0x8a00, 0x050a,
+ 0x8a02, 0x0808,
+ 0x8a04, 0x1c04,
+ 0x8a07, 0x1c05,
+ 0x8a08, 0x0807,
+ 0x8a0a, 0x09c3,
+ 0x8a0c, 0x09c1,
+ 0x8a0e, 0x09c0,
+ 0x8a0f, 0x09c7,
+ 0x8a10, 0x09bf,
+ 0x8a11, 0x09c8,
+ 0x8a12, 0x1e08,
+ 0x8a13, 0x09c5,
+ 0x8a15, 0x09c2,
+ 0x8a16, 0x09c6,
+ 0x8a17, 0x09c4,
+ 0x8a18, 0x09be,
+ 0x8a1b, 0x0ba5,
+ 0x8a1c, 0x3ba3,
+ 0x8a1d, 0x0b9f,
+ 0x8a1e, 0x206a,
+ 0x8a1f, 0x0ba4,
+ 0x8a22, 0x0ba6,
+ 0x8a23, 0x0ba0,
+ 0x8a25, 0x0ba1,
+ 0x8a27, 0x2068,
+ 0x8a29, 0x43e5,
+ 0x8a2a, 0x0b9e,
+ 0x8a2b, 0x3bd1,
+ 0x8a2c, 0x2069,
+ 0x8a2d, 0x0ba3,
+ 0x8a30, 0x2067,
+ 0x8a31, 0x0ba2,
+ 0x8a34, 0x0d61,
+ 0x8a36, 0x0d63,
+ 0x8a38, 0x477a,
+ 0x8a39, 0x22eb,
+ 0x8a3a, 0x0d62,
+ 0x8a3b, 0x0d57,
+ 0x8a3c, 0x0d5b,
+ 0x8a3d, 0x3ba2,
+ 0x8a3e, 0x0f19,
+ 0x8a3f, 0x258e,
+ 0x8a40, 0x22ed,
+ 0x8a41, 0x0d5c,
+ 0x8a44, 0x22f0,
+ 0x8a46, 0x0d60,
+ 0x8a48, 0x22f3,
+ 0x8a49, 0x3ff0,
+ 0x8a4a, 0x22f5,
+ 0x8a4c, 0x22f6,
+ 0x8a4d, 0x22ea,
+ 0x8a4e, 0x22e9,
+ 0x8a4f, 0x22f7,
+ 0x8a50, 0x0d5f,
+ 0x8a51, 0x22f4,
+ 0x8a52, 0x22f2,
+ 0x8a54, 0x0d5d,
+ 0x8a55, 0x0d59,
+ 0x8a56, 0x0d64,
+ 0x8a57, 0x22ee,
+ 0x8a59, 0x22ec,
+ 0x8a5b, 0x0d5e,
+ 0x8a5e, 0x0d5a,
+ 0x8a60, 0x0d58,
+ 0x8a61, 0x258d,
+ 0x8a62, 0x0f14,
+ 0x8a63, 0x0f0f,
+ 0x8a66, 0x0f0a,
+ 0x8a67, 0x3f8e,
+ 0x8a68, 0x0f1a,
+ 0x8a69, 0x0f0b,
+ 0x8a6b, 0x0f07,
+ 0x8a6c, 0x0f16,
+ 0x8a6d, 0x0f13,
+ 0x8a6e, 0x0f15,
+ 0x8a70, 0x0f0c,
+ 0x8a71, 0x0f11,
+ 0x8a72, 0x0f08,
+ 0x8a74, 0x2595,
+ 0x8a75, 0x2592,
+ 0x8a76, 0x258a,
+ 0x8a77, 0x258f,
+ 0x8a79, 0x0f17,
+ 0x8a7a, 0x2596,
+ 0x8a7b, 0x0f18,
+ 0x8a7c, 0x0f0e,
+ 0x8a7e, 0x3fa5,
+ 0x8a7f, 0x258c,
+ 0x8a81, 0x2594,
+ 0x8a82, 0x2590,
+ 0x8a83, 0x2593,
+ 0x8a84, 0x2591,
+ 0x8a85, 0x0f12,
+ 0x8a86, 0x258b,
+ 0x8a87, 0x0f0d,
+ 0x8a8b, 0x2805,
+ 0x8a8c, 0x10a6,
+ 0x8a8d, 0x10a9,
+ 0x8a8f, 0x2807,
+ 0x8a90, 0x382f,
+ 0x8a91, 0x10b1,
+ 0x8a92, 0x2806,
+ 0x8a93, 0x10ab,
+ 0x8a94, 0x477b,
+ 0x8a95, 0x1216,
+ 0x8a96, 0x2808,
+ 0x8a98, 0x10b0,
+ 0x8a99, 0x2804,
+ 0x8a9a, 0x10b2,
+ 0x8a9c, 0x382c,
+ 0x8a9e, 0x10a7,
+ 0x8aa0, 0x0f10,
+ 0x8aa1, 0x10aa,
+ 0x8aa3, 0x10a8,
+ 0x8aa4, 0x10ac,
+ 0x8aa5, 0x10ae,
+ 0x8aa6, 0x10a5,
+ 0x8aa7, 0x10b3,
+ 0x8aa8, 0x10af,
+ 0x8aa9, 0x383d,
+ 0x8aaa, 0x10ad,
+ 0x8aab, 0x2803,
+ 0x8aaf, 0x3841,
+ 0x8ab0, 0x121d,
+ 0x8ab2, 0x1219,
+ 0x8ab4, 0x477c,
+ 0x8ab6, 0x1220,
+ 0x8ab8, 0x2a44,
+ 0x8ab9, 0x1221,
+ 0x8aba, 0x2a50,
+ 0x8abb, 0x2a49,
+ 0x8abc, 0x1212,
+ 0x8abd, 0x2a51,
+ 0x8abe, 0x2a4b,
+ 0x8abf, 0x121c,
+ 0x8ac0, 0x2a4c,
+ 0x8ac2, 0x121b,
+ 0x8ac3, 0x2a4f,
+ 0x8ac4, 0x1215,
+ 0x8ac5, 0x2a4d,
+ 0x8ac6, 0x2a43,
+ 0x8ac7, 0x1214,
+ 0x8ac8, 0x2c8f,
+ 0x8ac9, 0x121a,
+ 0x8acb, 0x1217,
+ 0x8acd, 0x121f,
+ 0x8acf, 0x2a42,
+ 0x8ad1, 0x2a46,
+ 0x8ad2, 0x1213,
+ 0x8ad3, 0x2a45,
+ 0x8ad4, 0x2a47,
+ 0x8ad6, 0x121e,
+ 0x8ad7, 0x2a4a,
+ 0x8ad8, 0x2a4e,
+ 0x8ad9, 0x2a52,
+ 0x8ada, 0x39c2,
+ 0x8adb, 0x1222,
+ 0x8adc, 0x1352,
+ 0x8add, 0x2c8a,
+ 0x8ade, 0x2c90,
+ 0x8adf, 0x2c8d,
+ 0x8ae0, 0x2c85,
+ 0x8ae1, 0x2c91,
+ 0x8ae2, 0x2c86,
+ 0x8ae4, 0x2c8c,
+ 0x8ae6, 0x134d,
+ 0x8ae7, 0x1353,
+ 0x8ae8, 0x2c92,
+ 0x8aea, 0x3dd9,
+ 0x8aeb, 0x134f,
+ 0x8aed, 0x1359,
+ 0x8aee, 0x1354,
+ 0x8aef, 0x2c94,
+ 0x8af0, 0x2c8e,
+ 0x8af1, 0x1350,
+ 0x8af2, 0x2c87,
+ 0x8af3, 0x135a,
+ 0x8af4, 0x2c88,
+ 0x8af6, 0x135b,
+ 0x8af7, 0x1358,
+ 0x8af8, 0x1218,
+ 0x8afa, 0x134e,
+ 0x8afb, 0x2c95,
+ 0x8afc, 0x135c,
+ 0x8afe, 0x1355,
+ 0x8aff, 0x2c93,
+ 0x8b00, 0x1351,
+ 0x8b01, 0x1356,
+ 0x8b04, 0x147e,
+ 0x8b05, 0x2e5f,
+ 0x8b06, 0x2e68,
+ 0x8b07, 0x2e65,
+ 0x8b08, 0x2e67,
+ 0x8b0a, 0x147b,
+ 0x8b0b, 0x2e60,
+ 0x8b0c, 0x3836,
+ 0x8b0d, 0x2e66,
+ 0x8b0e, 0x1477,
+ 0x8b0f, 0x2e62,
+ 0x8b10, 0x147f,
+ 0x8b11, 0x2e5e,
+ 0x8b12, 0x2e63,
+ 0x8b13, 0x2e6a,
+ 0x8b14, 0x2c8b,
+ 0x8b15, 0x2e64,
+ 0x8b16, 0x2e5d,
+ 0x8b17, 0x1478,
+ 0x8b18, 0x2e5c,
+ 0x8b19, 0x1479,
+ 0x8b1a, 0x2e6b,
+ 0x8b1b, 0x147a,
+ 0x8b1c, 0x2e69,
+ 0x8b1d, 0x147d,
+ 0x8b1e, 0x2e5b,
+ 0x8b1f, 0x3837,
+ 0x8b20, 0x147c,
+ 0x8b22, 0x2e61,
+ 0x8b23, 0x2fce,
+ 0x8b24, 0x2fdc,
+ 0x8b25, 0x2fd7,
+ 0x8b26, 0x2fd9,
+ 0x8b27, 0x2fcd,
+ 0x8b28, 0x152a,
+ 0x8b2a, 0x2fcc,
+ 0x8b2b, 0x152d,
+ 0x8b2c, 0x152c,
+ 0x8b2d, 0x3f99,
+ 0x8b2e, 0x2fdb,
+ 0x8b2f, 0x2fd3,
+ 0x8b30, 0x2fd0,
+ 0x8b31, 0x2fd6,
+ 0x8b33, 0x2fcf,
+ 0x8b35, 0x2fd1,
+ 0x8b36, 0x2fda,
+ 0x8b37, 0x2fd8,
+ 0x8b39, 0x152b,
+ 0x8b3a, 0x2fdf,
+ 0x8b3b, 0x2fdd,
+ 0x8b3c, 0x2fd4,
+ 0x8b3d, 0x2fde,
+ 0x8b3e, 0x2fd5,
+ 0x8b3f, 0x383a,
+ 0x8b40, 0x3125,
+ 0x8b41, 0x15c4,
+ 0x8b42, 0x312c,
+ 0x8b43, 0x3ff2,
+ 0x8b45, 0x3313,
+ 0x8b46, 0x15cb,
+ 0x8b47, 0x2fd2,
+ 0x8b48, 0x3123,
+ 0x8b49, 0x15c7,
+ 0x8b4a, 0x3124,
+ 0x8b4b, 0x3129,
+ 0x8b4c, 0x383b,
+ 0x8b4e, 0x15c9,
+ 0x8b50, 0x3122,
+ 0x8b51, 0x312b,
+ 0x8b52, 0x312d,
+ 0x8b53, 0x3126,
+ 0x8b54, 0x3128,
+ 0x8b55, 0x312a,
+ 0x8b56, 0x3127,
+ 0x8b57, 0x312e,
+ 0x8b58, 0x15c6,
+ 0x8b59, 0x15cc,
+ 0x8b5a, 0x15c8,
+ 0x8b5c, 0x15c5,
+ 0x8b5d, 0x3237,
+ 0x8b5e, 0x3db8,
+ 0x8b5f, 0x1648,
+ 0x8b60, 0x3235,
+ 0x8b62, 0x3dd4,
+ 0x8b63, 0x3239,
+ 0x8b65, 0x323a,
+ 0x8b66, 0x1646,
+ 0x8b67, 0x323b,
+ 0x8b68, 0x3238,
+ 0x8b69, 0x3bf7,
+ 0x8b6a, 0x3236,
+ 0x8b6b, 0x1649,
+ 0x8b6c, 0x1645,
+ 0x8b6d, 0x323c,
+ 0x8b6f, 0x1647,
+ 0x8b70, 0x1644,
+ 0x8b74, 0x168f,
+ 0x8b77, 0x1690,
+ 0x8b78, 0x3312,
+ 0x8b79, 0x3311,
+ 0x8b7a, 0x3314,
+ 0x8b7d, 0x1691,
+ 0x8b7e, 0x33b6,
+ 0x8b7f, 0x33bb,
+ 0x8b80, 0x16d8,
+ 0x8b81, 0x3d8d,
+ 0x8b82, 0x33b8,
+ 0x8b84, 0x33b7,
+ 0x8b85, 0x33ba,
+ 0x8b86, 0x33b9,
+ 0x8b88, 0x3440,
+ 0x8b8a, 0x170a,
+ 0x8b8b, 0x343f,
+ 0x8b8c, 0x343d,
+ 0x8b8e, 0x343e,
+ 0x8b90, 0x383f,
+ 0x8b92, 0x172c,
+ 0x8b93, 0x172b,
+ 0x8b94, 0x349c,
+ 0x8b96, 0x172d,
+ 0x8b98, 0x34e7,
+ 0x8b9a, 0x1754,
+ 0x8b9b, 0x3840,
+ 0x8b9c, 0x175a,
+ 0x8b9e, 0x3522,
+ 0x8b9f, 0x353f,
+ 0x8ba0, 0x4505,
+ 0x8bbe, 0x4567,
+ 0x8be2, 0x4568,
+ 0x8c37, 0x050b,
+ 0x8c39, 0x206b,
+ 0x8c3b, 0x206c,
+ 0x8c3c, 0x2597,
+ 0x8c3d, 0x2809,
+ 0x8c3e, 0x2a53,
+ 0x8c3f, 0x1481,
+ 0x8c41, 0x1480,
+ 0x8c42, 0x2fe0,
+ 0x8c43, 0x312f,
+ 0x8c45, 0x3441,
+ 0x8c46, 0x050c,
+ 0x8c47, 0x1e09,
+ 0x8c48, 0x09c9,
+ 0x8c49, 0x0ba7,
+ 0x8c4a, 0x2599,
+ 0x8c4b, 0x2598,
+ 0x8c4c, 0x1223,
+ 0x8c4d, 0x2a54,
+ 0x8c4e, 0x1224,
+ 0x8c4f, 0x2e6c,
+ 0x8c50, 0x152e,
+ 0x8c51, 0x477d,
+ 0x8c54, 0x1763,
+ 0x8c55, 0x050d,
+ 0x8c56, 0x1a48,
+ 0x8c57, 0x1e0a,
+ 0x8c5a, 0x0ba8,
+ 0x8c5c, 0x206d,
+ 0x8c5f, 0x22f8,
+ 0x8c61, 0x0d65,
+ 0x8c62, 0x0f1b,
+ 0x8c64, 0x259b,
+ 0x8c65, 0x259a,
+ 0x8c66, 0x259c,
+ 0x8c68, 0x280a,
+ 0x8c6a, 0x10b4,
+ 0x8c6b, 0x135d,
+ 0x8c6c, 0x1225,
+ 0x8c6d, 0x135e,
+ 0x8c6f, 0x2e70,
+ 0x8c70, 0x2e6d,
+ 0x8c71, 0x2e6f,
+ 0x8c72, 0x2e6e,
+ 0x8c73, 0x1482,
+ 0x8c75, 0x2fe1,
+ 0x8c76, 0x3131,
+ 0x8c77, 0x3130,
+ 0x8c78, 0x18e7,
+ 0x8c79, 0x09cb,
+ 0x8c7a, 0x09ca,
+ 0x8c7b, 0x1e0b,
+ 0x8c7d, 0x206f,
+ 0x8c80, 0x22fa,
+ 0x8c81, 0x22f9,
+ 0x8c82, 0x0d66,
+ 0x8c84, 0x259e,
+ 0x8c86, 0x259d,
+ 0x8c89, 0x0f1d,
+ 0x8c8a, 0x0f1c,
+ 0x8c8c, 0x10b6,
+ 0x8c8d, 0x10b5,
+ 0x8c8f, 0x2a55,
+ 0x8c90, 0x2c98,
+ 0x8c91, 0x2c96,
+ 0x8c93, 0x135f,
+ 0x8c94, 0x2e72,
+ 0x8c95, 0x2e71,
+ 0x8c97, 0x2fe4,
+ 0x8c98, 0x2fe3,
+ 0x8c99, 0x2fe2,
+ 0x8c9a, 0x3132,
+ 0x8c9b, 0x3845,
+ 0x8c9c, 0x3523,
+ 0x8c9d, 0x050e,
+ 0x8c9e, 0x080a,
+ 0x8c9f, 0x3bad,
+ 0x8ca0, 0x080b,
+ 0x8ca1, 0x09cc,
+ 0x8ca3, 0x1e0d,
+ 0x8ca4, 0x1e0c,
+ 0x8ca5, 0x2070,
+ 0x8ca7, 0x0bae,
+ 0x8ca8, 0x0bac,
+ 0x8ca9, 0x0ba9,
+ 0x8caa, 0x0bad,
+ 0x8cab, 0x0bab,
+ 0x8cac, 0x0baa,
+ 0x8cad, 0x3ff1,
+ 0x8caf, 0x0d67,
+ 0x8cb0, 0x22fd,
+ 0x8cb2, 0x0f22,
+ 0x8cb3, 0x0d69,
+ 0x8cb4, 0x0d6e,
+ 0x8cb5, 0x22ff,
+ 0x8cb6, 0x0d70,
+ 0x8cb7, 0x0d6f,
+ 0x8cb8, 0x0d72,
+ 0x8cb9, 0x22fe,
+ 0x8cba, 0x22fb,
+ 0x8cbb, 0x0d6c,
+ 0x8cbc, 0x0d68,
+ 0x8cbd, 0x0d6a,
+ 0x8cbe, 0x22fc,
+ 0x8cbf, 0x0d71,
+ 0x8cc0, 0x0d6d,
+ 0x8cc1, 0x0d6b,
+ 0x8cc2, 0x0f24,
+ 0x8cc3, 0x0f23,
+ 0x8cc4, 0x0f21,
+ 0x8cc5, 0x0f25,
+ 0x8cc7, 0x0f1f,
+ 0x8cca, 0x0f1e,
+ 0x8ccc, 0x25a0,
+ 0x8ccd, 0x3e99,
+ 0x8ccf, 0x280d,
+ 0x8cd1, 0x10b8,
+ 0x8cd3, 0x10b7,
+ 0x8cd4, 0x477e,
+ 0x8cd5, 0x280c,
+ 0x8cd6, 0x384b,
+ 0x8cd7, 0x280e,
+ 0x8cd9, 0x2a58,
+ 0x8cda, 0x2a5a,
+ 0x8cdb, 0x3851,
+ 0x8cdc, 0x122e,
+ 0x8cdd, 0x2a5b,
+ 0x8cde, 0x1227,
+ 0x8cdf, 0x2a57,
+ 0x8ce0, 0x1226,
+ 0x8ce1, 0x1230,
+ 0x8ce2, 0x122c,
+ 0x8ce4, 0x1229,
+ 0x8ce5, 0x2a56,
+ 0x8ce6, 0x1228,
+ 0x8ce7, 0x2a5c,
+ 0x8ce8, 0x2a59,
+ 0x8ce9, 0x3bae,
+ 0x8cea, 0x122f,
+ 0x8ceb, 0x3f9c,
+ 0x8cec, 0x122a,
+ 0x8cee, 0x2c9a,
+ 0x8cf0, 0x2c9c,
+ 0x8cf1, 0x2c9b,
+ 0x8cf2, 0x477f,
+ 0x8cf3, 0x2c9d,
+ 0x8cf4, 0x1360,
+ 0x8cf5, 0x2c99,
+ 0x8cf7, 0x3fb1,
+ 0x8cf8, 0x1486,
+ 0x8cf9, 0x2e73,
+ 0x8cfa, 0x1483,
+ 0x8cfb, 0x1487,
+ 0x8cfc, 0x1485,
+ 0x8cfd, 0x1484,
+ 0x8cfe, 0x2fe5,
+ 0x8d00, 0x2fe8,
+ 0x8d02, 0x2fe7,
+ 0x8d03, 0x384f,
+ 0x8d04, 0x2fe6,
+ 0x8d05, 0x152f,
+ 0x8d06, 0x3133,
+ 0x8d08, 0x15cd,
+ 0x8d09, 0x3135,
+ 0x8d0a, 0x15ce,
+ 0x8d0b, 0x4573,
+ 0x8d0c, 0x3f96,
+ 0x8d0d, 0x164b,
+ 0x8d0f, 0x164a,
+ 0x8d10, 0x3316,
+ 0x8d11, 0x3853,
+ 0x8d12, 0x384e,
+ 0x8d13, 0x1692,
+ 0x8d14, 0x3317,
+ 0x8d15, 0x33bc,
+ 0x8d16, 0x16d9,
+ 0x8d18, 0x3e6f,
+ 0x8d19, 0x3442,
+ 0x8d1b, 0x172f,
+ 0x8d1c, 0x4780,
+ 0x8d1d, 0x4506,
+ 0x8d64, 0x050f,
+ 0x8d66, 0x0bb0,
+ 0x8d67, 0x0baf,
+ 0x8d68, 0x25a1,
+ 0x8d6b, 0x10ba,
+ 0x8d6c, 0x2c9e,
+ 0x8d6d, 0x1231,
+ 0x8d6e, 0x2c9f,
+ 0x8d6f, 0x2e74,
+ 0x8d70, 0x0510,
+ 0x8d72, 0x1c06,
+ 0x8d73, 0x080d,
+ 0x8d74, 0x080c,
+ 0x8d76, 0x1e0e,
+ 0x8d77, 0x09ce,
+ 0x8d78, 0x1e0f,
+ 0x8d79, 0x2073,
+ 0x8d7a, 0x39e1,
+ 0x8d7b, 0x2072,
+ 0x8d7d, 0x2071,
+ 0x8d80, 0x2301,
+ 0x8d81, 0x0d75,
+ 0x8d82, 0x3f69,
+ 0x8d84, 0x2300,
+ 0x8d85, 0x0d74,
+ 0x8d89, 0x2302,
+ 0x8d8a, 0x0d73,
+ 0x8d8c, 0x25a4,
+ 0x8d8d, 0x25a7,
+ 0x8d8e, 0x25a5,
+ 0x8d90, 0x25aa,
+ 0x8d91, 0x25a3,
+ 0x8d92, 0x25ab,
+ 0x8d93, 0x25a8,
+ 0x8d95, 0x10bc,
+ 0x8d96, 0x280f,
+ 0x8d99, 0x10bb,
+ 0x8d9b, 0x2a60,
+ 0x8d9c, 0x2a5e,
+ 0x8d9f, 0x1232,
+ 0x8da0, 0x2a5d,
+ 0x8da1, 0x2a5f,
+ 0x8da3, 0x1233,
+ 0x8da5, 0x2ca0,
+ 0x8da6, 0x3ff7,
+ 0x8da7, 0x2ca1,
+ 0x8da8, 0x1488,
+ 0x8da9, 0x3856,
+ 0x8daa, 0x3137,
+ 0x8dab, 0x3139,
+ 0x8dac, 0x3136,
+ 0x8dad, 0x3138,
+ 0x8dae, 0x323d,
+ 0x8daf, 0x3318,
+ 0x8db2, 0x3509,
+ 0x8db3, 0x0511,
+ 0x8db4, 0x080e,
+ 0x8db5, 0x1e10,
+ 0x8db6, 0x1e12,
+ 0x8db7, 0x1e11,
+ 0x8db9, 0x2076,
+ 0x8dba, 0x0bb2,
+ 0x8dbc, 0x2074,
+ 0x8dbe, 0x0bb1,
+ 0x8dbf, 0x2077,
+ 0x8dc0, 0x436a,
+ 0x8dc1, 0x2078,
+ 0x8dc2, 0x2075,
+ 0x8dc3, 0x4782,
+ 0x8dc5, 0x230e,
+ 0x8dc6, 0x0d7d,
+ 0x8dc7, 0x2306,
+ 0x8dc8, 0x230c,
+ 0x8dcb, 0x0d78,
+ 0x8dcc, 0x0d7b,
+ 0x8dcd, 0x2305,
+ 0x8dce, 0x0d76,
+ 0x8dcf, 0x2309,
+ 0x8dd0, 0x25b1,
+ 0x8dd1, 0x0d7a,
+ 0x8dd3, 0x2304,
+ 0x8dd4, 0x3f82,
+ 0x8dd5, 0x230a,
+ 0x8dd6, 0x2307,
+ 0x8dd7, 0x230d,
+ 0x8dd8, 0x2303,
+ 0x8dd9, 0x230b,
+ 0x8dda, 0x0d79,
+ 0x8ddb, 0x0d7c,
+ 0x8ddc, 0x2308,
+ 0x8ddd, 0x0d77,
+ 0x8ddf, 0x0f27,
+ 0x8de0, 0x25ad,
+ 0x8de1, 0x0f26,
+ 0x8de2, 0x25b4,
+ 0x8de3, 0x25b3,
+ 0x8de4, 0x0f2d,
+ 0x8de6, 0x0f2e,
+ 0x8de7, 0x25b5,
+ 0x8de8, 0x0f28,
+ 0x8de9, 0x25b2,
+ 0x8dea, 0x0f2c,
+ 0x8deb, 0x25b7,
+ 0x8dec, 0x25ae,
+ 0x8dee, 0x25b0,
+ 0x8def, 0x0f29,
+ 0x8df0, 0x25ac,
+ 0x8df1, 0x25af,
+ 0x8df2, 0x25b6,
+ 0x8df3, 0x0f2a,
+ 0x8df4, 0x25b8,
+ 0x8dfa, 0x0f2b,
+ 0x8dfc, 0x10bd,
+ 0x8dfd, 0x2814,
+ 0x8dfe, 0x281a,
+ 0x8dff, 0x2812,
+ 0x8e00, 0x281b,
+ 0x8e01, 0x3f85,
+ 0x8e02, 0x2811,
+ 0x8e03, 0x2816,
+ 0x8e04, 0x281c,
+ 0x8e05, 0x2819,
+ 0x8e06, 0x2818,
+ 0x8e07, 0x2817,
+ 0x8e09, 0x2810,
+ 0x8e0a, 0x2815,
+ 0x8e0d, 0x2813,
+ 0x8e0e, 0x3e5e,
+ 0x8e0f, 0x1238,
+ 0x8e10, 0x1235,
+ 0x8e11, 0x2a69,
+ 0x8e12, 0x2a6e,
+ 0x8e13, 0x2a70,
+ 0x8e14, 0x2a6d,
+ 0x8e15, 0x2a66,
+ 0x8e16, 0x2a68,
+ 0x8e17, 0x2a72,
+ 0x8e18, 0x2a6f,
+ 0x8e19, 0x2a6a,
+ 0x8e1a, 0x2a73,
+ 0x8e1b, 0x2a67,
+ 0x8e1c, 0x2a71,
+ 0x8e1d, 0x1236,
+ 0x8e1e, 0x123c,
+ 0x8e1f, 0x123a,
+ 0x8e20, 0x2a61,
+ 0x8e21, 0x123b,
+ 0x8e22, 0x1237,
+ 0x8e23, 0x2a62,
+ 0x8e24, 0x2a64,
+ 0x8e25, 0x2a63,
+ 0x8e26, 0x2a6b,
+ 0x8e28, 0x3f88,
+ 0x8e29, 0x1239,
+ 0x8e2a, 0x3bb4,
+ 0x8e2b, 0x1234,
+ 0x8e2d, 0x3eab,
+ 0x8e2e, 0x2a65,
+ 0x8e30, 0x2cab,
+ 0x8e31, 0x1362,
+ 0x8e33, 0x2ca2,
+ 0x8e34, 0x1363,
+ 0x8e35, 0x1366,
+ 0x8e36, 0x2ca7,
+ 0x8e38, 0x2ca4,
+ 0x8e39, 0x1365,
+ 0x8e3a, 0x4784,
+ 0x8e3c, 0x2ca8,
+ 0x8e3e, 0x2ca3,
+ 0x8e3f, 0x2cac,
+ 0x8e40, 0x2ca5,
+ 0x8e41, 0x2caa,
+ 0x8e42, 0x1364,
+ 0x8e44, 0x1361,
+ 0x8e45, 0x2ca6,
+ 0x8e46, 0x4312,
+ 0x8e47, 0x2e7a,
+ 0x8e48, 0x148b,
+ 0x8e49, 0x1489,
+ 0x8e4a, 0x148c,
+ 0x8e4b, 0x148a,
+ 0x8e4c, 0x2e79,
+ 0x8e4d, 0x2e76,
+ 0x8e4e, 0x2e75,
+ 0x8e4f, 0x3f83,
+ 0x8e50, 0x2e78,
+ 0x8e53, 0x2e77,
+ 0x8e54, 0x2ff6,
+ 0x8e55, 0x1535,
+ 0x8e56, 0x2fed,
+ 0x8e57, 0x2fec,
+ 0x8e59, 0x1530,
+ 0x8e5a, 0x2ff2,
+ 0x8e5b, 0x2ff1,
+ 0x8e5c, 0x2fe9,
+ 0x8e5d, 0x2ff4,
+ 0x8e5e, 0x2fee,
+ 0x8e5f, 0x1534,
+ 0x8e60, 0x2feb,
+ 0x8e61, 0x2ff3,
+ 0x8e62, 0x2fea,
+ 0x8e63, 0x1531,
+ 0x8e64, 0x1533,
+ 0x8e65, 0x2fef,
+ 0x8e66, 0x1532,
+ 0x8e67, 0x2ff0,
+ 0x8e68, 0x434d,
+ 0x8e69, 0x2ff5,
+ 0x8e6a, 0x313d,
+ 0x8e6c, 0x15d3,
+ 0x8e6d, 0x313a,
+ 0x8e6f, 0x313e,
+ 0x8e71, 0x43e7,
+ 0x8e72, 0x15d0,
+ 0x8e73, 0x313c,
+ 0x8e74, 0x15d5,
+ 0x8e75, 0x3f89,
+ 0x8e76, 0x15d2,
+ 0x8e77, 0x3f7f,
+ 0x8e78, 0x313b,
+ 0x8e7a, 0x15d4,
+ 0x8e7b, 0x313f,
+ 0x8e7c, 0x15cf,
+ 0x8e7e, 0x4324,
+ 0x8e80, 0x3e57,
+ 0x8e81, 0x164d,
+ 0x8e82, 0x164f,
+ 0x8e84, 0x3240,
+ 0x8e85, 0x164e,
+ 0x8e86, 0x323e,
+ 0x8e87, 0x15d1,
+ 0x8e88, 0x323f,
+ 0x8e89, 0x164c,
+ 0x8e8a, 0x1693,
+ 0x8e8b, 0x1695,
+ 0x8e8c, 0x331a,
+ 0x8e8d, 0x1694,
+ 0x8e8e, 0x3319,
+ 0x8e90, 0x33c1,
+ 0x8e91, 0x16db,
+ 0x8e92, 0x33c0,
+ 0x8e93, 0x16dc,
+ 0x8e94, 0x33be,
+ 0x8e95, 0x33bd,
+ 0x8e96, 0x33c2,
+ 0x8e98, 0x3443,
+ 0x8e9a, 0x33bf,
+ 0x8e9d, 0x34a1,
+ 0x8e9e, 0x349e,
+ 0x8ea1, 0x1749,
+ 0x8ea3, 0x34eb,
+ 0x8ea4, 0x34ea,
+ 0x8ea5, 0x34e9,
+ 0x8ea6, 0x350a,
+ 0x8ea7, 0x3bb5,
+ 0x8ea8, 0x3537,
+ 0x8ea9, 0x3524,
+ 0x8eaa, 0x175b,
+ 0x8eab, 0x0512,
+ 0x8eac, 0x09cf,
+ 0x8ead, 0x385e,
+ 0x8eb0, 0x43e9,
+ 0x8eb2, 0x0f2f,
+ 0x8eb6, 0x385f,
+ 0x8eba, 0x123d,
+ 0x8ebc, 0x38a0,
+ 0x8ebd, 0x2cad,
+ 0x8ec0, 0x1536,
+ 0x8ec2, 0x3140,
+ 0x8ec3, 0x3860,
+ 0x8ec9, 0x3525,
+ 0x8eca, 0x0513,
+ 0x8ecb, 0x068d,
+ 0x8ecc, 0x0810,
+ 0x8ecd, 0x080f,
+ 0x8ece, 0x4788,
+ 0x8ecf, 0x09d2,
+ 0x8ed1, 0x1e13,
+ 0x8ed2, 0x09d0,
+ 0x8ed3, 0x1e14,
+ 0x8ed4, 0x09d1,
+ 0x8ed7, 0x207d,
+ 0x8ed8, 0x2079,
+ 0x8eda, 0x3dbe,
+ 0x8edb, 0x0bb3,
+ 0x8edc, 0x207c,
+ 0x8edd, 0x207b,
+ 0x8ede, 0x207a,
+ 0x8edf, 0x0bb4,
+ 0x8ee0, 0x207e,
+ 0x8ee2, 0x4789,
+ 0x8ee4, 0x478a,
+ 0x8ee5, 0x2315,
+ 0x8ee6, 0x2313,
+ 0x8ee7, 0x2317,
+ 0x8ee9, 0x231e,
+ 0x8eeb, 0x231a,
+ 0x8eec, 0x231c,
+ 0x8eed, 0x478b,
+ 0x8eee, 0x2314,
+ 0x8eef, 0x230f,
+ 0x8ef1, 0x231b,
+ 0x8ef2, 0x478c,
+ 0x8ef4, 0x231d,
+ 0x8ef5, 0x2316,
+ 0x8ef6, 0x2319,
+ 0x8ef7, 0x2310,
+ 0x8ef8, 0x0d7f,
+ 0x8ef9, 0x2312,
+ 0x8efa, 0x2311,
+ 0x8efb, 0x0d7e,
+ 0x8efc, 0x0d80,
+ 0x8efe, 0x0f32,
+ 0x8eff, 0x25ba,
+ 0x8f00, 0x25bc,
+ 0x8f01, 0x25bb,
+ 0x8f02, 0x25c0,
+ 0x8f03, 0x0f30,
+ 0x8f05, 0x25bd,
+ 0x8f06, 0x25b9,
+ 0x8f07, 0x25be,
+ 0x8f09, 0x0f31,
+ 0x8f0a, 0x0f33,
+ 0x8f0b, 0x25c1,
+ 0x8f0d, 0x2820,
+ 0x8f0e, 0x281f,
+ 0x8f10, 0x281d,
+ 0x8f12, 0x10bf,
+ 0x8f13, 0x10c1,
+ 0x8f14, 0x10be,
+ 0x8f15, 0x10c0,
+ 0x8f16, 0x2a7a,
+ 0x8f18, 0x2a76,
+ 0x8f19, 0x3862,
+ 0x8f1a, 0x2a77,
+ 0x8f1b, 0x123f,
+ 0x8f1c, 0x1244,
+ 0x8f1d, 0x123e,
+ 0x8f1e, 0x1245,
+ 0x8f1f, 0x1240,
+ 0x8f20, 0x2a78,
+ 0x8f23, 0x2a79,
+ 0x8f24, 0x2a75,
+ 0x8f25, 0x1246,
+ 0x8f26, 0x1242,
+ 0x8f29, 0x1241,
+ 0x8f2a, 0x1243,
+ 0x8f2c, 0x2a74,
+ 0x8f2d, 0x3863,
+ 0x8f2e, 0x2caf,
+ 0x8f2f, 0x1368,
+ 0x8f30, 0x3bb7,
+ 0x8f32, 0x2cb1,
+ 0x8f33, 0x136a,
+ 0x8f34, 0x2cb4,
+ 0x8f35, 0x2cb0,
+ 0x8f36, 0x2cae,
+ 0x8f37, 0x2cb3,
+ 0x8f38, 0x1369,
+ 0x8f39, 0x2cb2,
+ 0x8f3b, 0x1367,
+ 0x8f3e, 0x148e,
+ 0x8f3f, 0x1491,
+ 0x8f40, 0x2e7c,
+ 0x8f41, 0x3d07,
+ 0x8f42, 0x148f,
+ 0x8f43, 0x2e7b,
+ 0x8f44, 0x148d,
+ 0x8f45, 0x1490,
+ 0x8f46, 0x2ff7,
+ 0x8f49, 0x1537,
+ 0x8f4a, 0x3bb8,
+ 0x8f4b, 0x2ffa,
+ 0x8f4d, 0x1538,
+ 0x8f4e, 0x15d7,
+ 0x8f4f, 0x3143,
+ 0x8f51, 0x3142,
+ 0x8f52, 0x3141,
+ 0x8f53, 0x3145,
+ 0x8f54, 0x15d6,
+ 0x8f55, 0x3244,
+ 0x8f56, 0x3242,
+ 0x8f58, 0x3245,
+ 0x8f59, 0x3241,
+ 0x8f5a, 0x3246,
+ 0x8f5b, 0x331c,
+ 0x8f5c, 0x3f31,
+ 0x8f5d, 0x331d,
+ 0x8f5e, 0x331b,
+ 0x8f5f, 0x1696,
+ 0x8f60, 0x33c4,
+ 0x8f61, 0x16dd,
+ 0x8f62, 0x33c5,
+ 0x8f63, 0x3445,
+ 0x8f64, 0x3444,
+ 0x8f66, 0x4569,
+ 0x8f6e, 0x456b,
+ 0x8f93, 0x4732,
+ 0x8f9b, 0x0514,
+ 0x8f9c, 0x0d81,
+ 0x8f9f, 0x0f34,
+ 0x8fa0, 0x3d94,
+ 0x8fa3, 0x10c2,
+ 0x8fa5, 0x3866,
+ 0x8fa6, 0x136c,
+ 0x8fa8, 0x136b,
+ 0x8fad, 0x15d8,
+ 0x8fae, 0x162f,
+ 0x8faf, 0x1697,
+ 0x8fb0, 0x0515,
+ 0x8fb1, 0x09d3,
+ 0x8fb2, 0x0f35,
+ 0x8fb3, 0x386a,
+ 0x8fb4, 0x3146,
+ 0x8fb5, 0x0230,
+ 0x8fb6, 0x47d3,
+ 0x8fb7, 0x43fd,
+ 0x8fb8, 0x42f6,
+ 0x8fb9, 0x48c9,
+ 0x8fba, 0x48c7,
+ 0x8fbb, 0x3d6b,
+ 0x8fbe, 0x48c6,
+ 0x8fbf, 0x18e9,
+ 0x8fc1, 0x478d,
+ 0x8fc2, 0x0516,
+ 0x8fc4, 0x0519,
+ 0x8fc5, 0x0518,
+ 0x8fc6, 0x0517,
+ 0x8fc9, 0x18e8,
+ 0x8fca, 0x478e,
+ 0x8fcb, 0x1a4a,
+ 0x8fcc, 0x478f,
+ 0x8fcd, 0x1a4c,
+ 0x8fce, 0x068e,
+ 0x8fd0, 0x48ae,
+ 0x8fd1, 0x0690,
+ 0x8fd2, 0x1a49,
+ 0x8fd3, 0x1a4b,
+ 0x8fd4, 0x068f,
+ 0x8fd5, 0x1a4e,
+ 0x8fd6, 0x1a4d,
+ 0x8fd7, 0x1a4f,
+ 0x8fda, 0x3fcb,
+ 0x8fe0, 0x1c0a,
+ 0x8fe1, 0x1c08,
+ 0x8fe2, 0x0813,
+ 0x8fe3, 0x1c07,
+ 0x8fe4, 0x0818,
+ 0x8fe5, 0x0815,
+ 0x8fe6, 0x0812,
+ 0x8fe8, 0x0819,
+ 0x8fea, 0x0814,
+ 0x8feb, 0x0817,
+ 0x8fed, 0x0816,
+ 0x8fee, 0x1c09,
+ 0x8ff0, 0x0811,
+ 0x8ff4, 0x09d9,
+ 0x8ff5, 0x1e16,
+ 0x8ff6, 0x1e1c,
+ 0x8ff7, 0x09d6,
+ 0x8ff8, 0x09dd,
+ 0x8ff9, 0x3871,
+ 0x8ffa, 0x09d8,
+ 0x8ffb, 0x1e19,
+ 0x8ffc, 0x1e1b,
+ 0x8ffd, 0x09db,
+ 0x8ffe, 0x1e15,
+ 0x8fff, 0x1e18,
+ 0x9000, 0x09d7,
+ 0x9001, 0x09d4,
+ 0x9002, 0x1e17,
+ 0x9003, 0x09da,
+ 0x9004, 0x1e1a,
+ 0x9005, 0x09dc,
+ 0x9006, 0x09d5,
+ 0x9008, 0x3ee0,
+ 0x900b, 0x2081,
+ 0x900c, 0x2084,
+ 0x900d, 0x0bb6,
+ 0x900f, 0x0bc0,
+ 0x9010, 0x0bbc,
+ 0x9011, 0x2082,
+ 0x9012, 0x3e4e,
+ 0x9014, 0x0bc4,
+ 0x9015, 0x0bbd,
+ 0x9016, 0x0bc2,
+ 0x9017, 0x0bb8,
+ 0x9019, 0x0bb5,
+ 0x901a, 0x0bb7,
+ 0x901b, 0x0bc3,
+ 0x901c, 0x2083,
+ 0x901d, 0x0bbb,
+ 0x901e, 0x0bbe,
+ 0x901f, 0x0bba,
+ 0x9020, 0x0bbf,
+ 0x9021, 0x2085,
+ 0x9022, 0x0bc1,
+ 0x9023, 0x0bb9,
+ 0x9024, 0x2080,
+ 0x902d, 0x231f,
+ 0x902e, 0x0d82,
+ 0x902f, 0x2321,
+ 0x9031, 0x0d84,
+ 0x9032, 0x0d86,
+ 0x9033, 0x4790,
+ 0x9034, 0x2320,
+ 0x9035, 0x0d83,
+ 0x9036, 0x0d87,
+ 0x9037, 0x3876,
+ 0x9038, 0x0d85,
+ 0x903c, 0x0f3b,
+ 0x903d, 0x25c6,
+ 0x903e, 0x0f43,
+ 0x903f, 0x25c3,
+ 0x9041, 0x0f44,
+ 0x9042, 0x0f39,
+ 0x9044, 0x25c4,
+ 0x9047, 0x0f3e,
+ 0x9049, 0x25c5,
+ 0x904a, 0x0f37,
+ 0x904b, 0x0f36,
+ 0x904c, 0x3f10,
+ 0x904d, 0x0f41,
+ 0x904e, 0x0f40,
+ 0x904f, 0x0f3f,
+ 0x9050, 0x0f3d,
+ 0x9051, 0x0f42,
+ 0x9052, 0x25c2,
+ 0x9053, 0x0f38,
+ 0x9054, 0x0f3a,
+ 0x9055, 0x0f3c,
+ 0x9056, 0x3dd2,
+ 0x9058, 0x10c4,
+ 0x9059, 0x10c7,
+ 0x905b, 0x10cb,
+ 0x905c, 0x10c5,
+ 0x905d, 0x10ca,
+ 0x905e, 0x10c8,
+ 0x9060, 0x10c3,
+ 0x9061, 0x3879,
+ 0x9062, 0x10c9,
+ 0x9063, 0x10c6,
+ 0x9064, 0x3c68,
+ 0x9067, 0x2a7f,
+ 0x9068, 0x1249,
+ 0x9069, 0x1247,
+ 0x906b, 0x2a80,
+ 0x906c, 0x3d60,
+ 0x906d, 0x124a,
+ 0x906e, 0x1248,
+ 0x906f, 0x2a7e,
+ 0x9070, 0x2a7d,
+ 0x9072, 0x1370,
+ 0x9073, 0x2a7c,
+ 0x9074, 0x136e,
+ 0x9075, 0x136d,
+ 0x9076, 0x2cb5,
+ 0x9077, 0x124b,
+ 0x9078, 0x136f,
+ 0x9079, 0x2cb6,
+ 0x907a, 0x1372,
+ 0x907b, 0x2cb7,
+ 0x907c, 0x1371,
+ 0x907d, 0x1493,
+ 0x907e, 0x2e7e,
+ 0x907f, 0x1492,
+ 0x9080, 0x1497,
+ 0x9081, 0x1495,
+ 0x9083, 0x153a,
+ 0x9084, 0x1494,
+ 0x9085, 0x2e7d,
+ 0x9086, 0x2cb8,
+ 0x9087, 0x1539,
+ 0x9088, 0x153b,
+ 0x908a, 0x15d9,
+ 0x908d, 0x3247,
+ 0x908f, 0x170c,
+ 0x9090, 0x170b,
+ 0x9091, 0x051b,
+ 0x9094, 0x181e,
+ 0x9095, 0x09de,
+ 0x9097, 0x181b,
+ 0x9099, 0x181a,
+ 0x909b, 0x181d,
+ 0x909e, 0x18ed,
+ 0x909f, 0x18ea,
+ 0x90a0, 0x18ef,
+ 0x90a1, 0x18eb,
+ 0x90a2, 0x051c,
+ 0x90a3, 0x051f,
+ 0x90a5, 0x18ec,
+ 0x90a6, 0x051e,
+ 0x90a7, 0x18ee,
+ 0x90a8, 0x387c,
+ 0x90aa, 0x051d,
+ 0x90ae, 0x3880,
+ 0x90af, 0x1a52,
+ 0x90b0, 0x1a54,
+ 0x90b1, 0x0693,
+ 0x90b2, 0x1a50,
+ 0x90b3, 0x1a53,
+ 0x90b4, 0x1a51,
+ 0x90b5, 0x0691,
+ 0x90b6, 0x0694,
+ 0x90b8, 0x0692,
+ 0x90bb, 0x3bc4,
+ 0x90bd, 0x1c0c,
+ 0x90be, 0x1c10,
+ 0x90bf, 0x1c0d,
+ 0x90c1, 0x081c,
+ 0x90c3, 0x081d,
+ 0x90c4, 0x387e,
+ 0x90c5, 0x1c0f,
+ 0x90c7, 0x1c11,
+ 0x90c8, 0x1c13,
+ 0x90ca, 0x081a,
+ 0x90cb, 0x1c12,
+ 0x90ce, 0x081b,
+ 0x90d4, 0x208c,
+ 0x90d5, 0x1c0e,
+ 0x90d6, 0x1e1d,
+ 0x90d7, 0x1e26,
+ 0x90d8, 0x1e24,
+ 0x90d9, 0x1e1f,
+ 0x90db, 0x1e25,
+ 0x90dc, 0x1e27,
+ 0x90dd, 0x09e0,
+ 0x90df, 0x1e22,
+ 0x90e0, 0x1e1e,
+ 0x90e1, 0x09df,
+ 0x90e2, 0x09e1,
+ 0x90e3, 0x1e21,
+ 0x90e4, 0x1e28,
+ 0x90e5, 0x1e23,
+ 0x90e8, 0x0bc5,
+ 0x90e9, 0x208f,
+ 0x90ea, 0x2087,
+ 0x90eb, 0x208d,
+ 0x90ed, 0x0bc6,
+ 0x90ef, 0x2086,
+ 0x90f0, 0x2088,
+ 0x90f1, 0x1c0b,
+ 0x90f2, 0x208a,
+ 0x90f4, 0x2089,
+ 0x90f5, 0x0d89,
+ 0x90f9, 0x2328,
+ 0x90fa, 0x2cb9,
+ 0x90fb, 0x2329,
+ 0x90fc, 0x2326,
+ 0x90fd, 0x0bc7,
+ 0x90fe, 0x0d8b,
+ 0x90ff, 0x2325,
+ 0x9100, 0x232b,
+ 0x9101, 0x232a,
+ 0x9102, 0x0d88,
+ 0x9103, 0x232e,
+ 0x9104, 0x2324,
+ 0x9105, 0x232d,
+ 0x9106, 0x2322,
+ 0x9107, 0x232c,
+ 0x9108, 0x2327,
+ 0x9109, 0x0d8a,
+ 0x910b, 0x25cd,
+ 0x910d, 0x25c8,
+ 0x910e, 0x25ce,
+ 0x910f, 0x25c9,
+ 0x9110, 0x25c7,
+ 0x9111, 0x25ca,
+ 0x9112, 0x0f45,
+ 0x9114, 0x25cc,
+ 0x9116, 0x25cb,
+ 0x9117, 0x0f46,
+ 0x9118, 0x10cd,
+ 0x9119, 0x10cc,
+ 0x911a, 0x2827,
+ 0x911b, 0x282a,
+ 0x911c, 0x2822,
+ 0x911d, 0x2826,
+ 0x911e, 0x10ce,
+ 0x911f, 0x2825,
+ 0x9120, 0x2823,
+ 0x9121, 0x2829,
+ 0x9122, 0x2824,
+ 0x9123, 0x2821,
+ 0x9124, 0x2828,
+ 0x9126, 0x2a86,
+ 0x9127, 0x124e,
+ 0x9128, 0x2ffb,
+ 0x9129, 0x2a83,
+ 0x912b, 0x2a82,
+ 0x912c, 0x2323,
+ 0x912d, 0x124d,
+ 0x912e, 0x2a87,
+ 0x912f, 0x2a81,
+ 0x9130, 0x124c,
+ 0x9131, 0x124f,
+ 0x9132, 0x2a85,
+ 0x9133, 0x2cba,
+ 0x9134, 0x1373,
+ 0x9135, 0x2cbb,
+ 0x9138, 0x2e7f,
+ 0x9139, 0x1498,
+ 0x913a, 0x2ffc,
+ 0x913e, 0x2ffe,
+ 0x913f, 0x3148,
+ 0x9140, 0x3147,
+ 0x9141, 0x3249,
+ 0x9143, 0x3248,
+ 0x9144, 0x331f,
+ 0x9146, 0x331e,
+ 0x9147, 0x33c6,
+ 0x9148, 0x16de,
+ 0x9149, 0x0520,
+ 0x914a, 0x081f,
+ 0x914b, 0x081e,
+ 0x914c, 0x09e4,
+ 0x914d, 0x09e3,
+ 0x914e, 0x1e2a,
+ 0x9150, 0x1e29,
+ 0x9151, 0x3f49,
+ 0x9152, 0x09e2,
+ 0x9153, 0x2093,
+ 0x9155, 0x2094,
+ 0x9156, 0x2090,
+ 0x9157, 0x0bc8,
+ 0x9158, 0x2091,
+ 0x9159, 0x3f45,
+ 0x915a, 0x2092,
+ 0x915c, 0x3f47,
+ 0x915e, 0x43eb,
+ 0x915f, 0x2331,
+ 0x9160, 0x2333,
+ 0x9161, 0x232f,
+ 0x9162, 0x2332,
+ 0x9163, 0x0d8c,
+ 0x9164, 0x2330,
+ 0x9165, 0x0d8d,
+ 0x9167, 0x3882,
+ 0x9168, 0x23e2,
+ 0x9169, 0x0f49,
+ 0x916a, 0x0f48,
+ 0x916c, 0x0f47,
+ 0x916e, 0x25cf,
+ 0x9170, 0x3eb8,
+ 0x9172, 0x282c,
+ 0x9173, 0x282e,
+ 0x9174, 0x10d2,
+ 0x9175, 0x10cf,
+ 0x9176, 0x3e9b,
+ 0x9177, 0x10d1,
+ 0x9178, 0x10d0,
+ 0x9179, 0x282d,
+ 0x917a, 0x282b,
+ 0x917c, 0x3f6f,
+ 0x9180, 0x2a8e,
+ 0x9181, 0x2a8b,
+ 0x9183, 0x1253,
+ 0x9184, 0x2a8d,
+ 0x9185, 0x2a88,
+ 0x9187, 0x1250,
+ 0x9189, 0x1251,
+ 0x918a, 0x2a8a,
+ 0x918b, 0x1252,
+ 0x918c, 0x43ec,
+ 0x918d, 0x2cc0,
+ 0x918e, 0x3f4e,
+ 0x918f, 0x2cc1,
+ 0x9190, 0x2cbe,
+ 0x9192, 0x1374,
+ 0x9193, 0x2cbd,
+ 0x9199, 0x2e83,
+ 0x919a, 0x2e80,
+ 0x919b, 0x2e82,
+ 0x919c, 0x149b,
+ 0x919d, 0x2e86,
+ 0x919e, 0x149a,
+ 0x919f, 0x2e84,
+ 0x91a0, 0x2e87,
+ 0x91a1, 0x2e85,
+ 0x91a2, 0x2e81,
+ 0x91a3, 0x1499,
+ 0x91a5, 0x3000,
+ 0x91a7, 0x3001,
+ 0x91a8, 0x2fff,
+ 0x91a9, 0x3883,
+ 0x91aa, 0x3003,
+ 0x91ab, 0x153c,
+ 0x91ad, 0x314a,
+ 0x91ae, 0x15dc,
+ 0x91af, 0x3002,
+ 0x91b0, 0x3149,
+ 0x91b1, 0x15db,
+ 0x91b2, 0x324c,
+ 0x91b4, 0x1650,
+ 0x91b5, 0x324b,
+ 0x91b6, 0x45ef,
+ 0x91b7, 0x324a,
+ 0x91b9, 0x3321,
+ 0x91ba, 0x1698,
+ 0x91bb, 0x3bc8,
+ 0x91bc, 0x3446,
+ 0x91bd, 0x34a3,
+ 0x91be, 0x34a2,
+ 0x91c0, 0x1730,
+ 0x91c1, 0x174a,
+ 0x91c2, 0x34a4,
+ 0x91c3, 0x350b,
+ 0x91c4, 0x3884,
+ 0x91c5, 0x175c,
+ 0x91c6, 0x0521,
+ 0x91c7, 0x0695,
+ 0x91c9, 0x0f4a,
+ 0x91cb, 0x1651,
+ 0x91cc, 0x0522,
+ 0x91cd, 0x0820,
+ 0x91ce, 0x0bc9,
+ 0x91cf, 0x0d8e,
+ 0x91d0, 0x153e,
+ 0x91d1, 0x0696,
+ 0x91d3, 0x1c15,
+ 0x91d4, 0x1c14,
+ 0x91d5, 0x1e2c,
+ 0x91d6, 0x415e,
+ 0x91d7, 0x09e7,
+ 0x91d8, 0x09e5,
+ 0x91d9, 0x09e9,
+ 0x91da, 0x1e2e,
+ 0x91dc, 0x09e8,
+ 0x91dd, 0x09e6,
+ 0x91df, 0x453a,
+ 0x91e2, 0x1e2d,
+ 0x91e3, 0x0bcc,
+ 0x91e4, 0x209a,
+ 0x91e5, 0x3c06,
+ 0x91e6, 0x0bcb,
+ 0x91e7, 0x0bcd,
+ 0x91e8, 0x209f,
+ 0x91e9, 0x0bcf,
+ 0x91ea, 0x209c,
+ 0x91ec, 0x2095,
+ 0x91ed, 0x0bce,
+ 0x91ee, 0x20a0,
+ 0x91f1, 0x2097,
+ 0x91f3, 0x2098,
+ 0x91f4, 0x2096,
+ 0x91f5, 0x0bca,
+ 0x91f7, 0x209e,
+ 0x91f8, 0x2099,
+ 0x91f9, 0x209b,
+ 0x91fa, 0x3af8,
+ 0x91fd, 0x233f,
+ 0x91fe, 0x382e,
+ 0x91ff, 0x233e,
+ 0x9200, 0x233c,
+ 0x9201, 0x2334,
+ 0x9202, 0x2343,
+ 0x9203, 0x2337,
+ 0x9204, 0x2341,
+ 0x9205, 0x2348,
+ 0x9206, 0x2340,
+ 0x9207, 0x0d96,
+ 0x9208, 0x3eb9,
+ 0x9209, 0x0d92,
+ 0x920a, 0x2335,
+ 0x920c, 0x233b,
+ 0x920d, 0x0d94,
+ 0x920e, 0x3888,
+ 0x920f, 0x233a,
+ 0x9210, 0x0d95,
+ 0x9211, 0x0d97,
+ 0x9212, 0x233d,
+ 0x9213, 0x4793,
+ 0x9214, 0x0d8f,
+ 0x9216, 0x2349,
+ 0x9217, 0x2347,
+ 0x9219, 0x2346,
+ 0x921a, 0x2338,
+ 0x921c, 0x2344,
+ 0x921e, 0x0d93,
+ 0x9223, 0x0d91,
+ 0x9224, 0x2345,
+ 0x9225, 0x2336,
+ 0x9226, 0x2339,
+ 0x9227, 0x2342,
+ 0x9228, 0x4795,
+ 0x922a, 0x3c0e,
+ 0x922b, 0x3ba6,
+ 0x922d, 0x2851,
+ 0x922e, 0x25da,
+ 0x9230, 0x25d3,
+ 0x9231, 0x25e6,
+ 0x9232, 0x25ef,
+ 0x9233, 0x25d6,
+ 0x9234, 0x0f55,
+ 0x9235, 0x3b26,
+ 0x9236, 0x25e3,
+ 0x9237, 0x0f4b,
+ 0x9238, 0x0f4d,
+ 0x9239, 0x0f59,
+ 0x923a, 0x25d4,
+ 0x923c, 0x41d2,
+ 0x923d, 0x0f4e,
+ 0x923e, 0x0f50,
+ 0x923f, 0x0f5a,
+ 0x9240, 0x0f4f,
+ 0x9241, 0x388a,
+ 0x9244, 0x389a,
+ 0x9245, 0x0f58,
+ 0x9246, 0x25dc,
+ 0x9248, 0x25d1,
+ 0x9249, 0x0f56,
+ 0x924a, 0x25db,
+ 0x924b, 0x0f52,
+ 0x924c, 0x25ed,
+ 0x924d, 0x0f57,
+ 0x924e, 0x25eb,
+ 0x924f, 0x25df,
+ 0x9250, 0x25e9,
+ 0x9251, 0x0f54,
+ 0x9252, 0x25d2,
+ 0x9253, 0x25ec,
+ 0x9254, 0x25e7,
+ 0x9255, 0x3e47,
+ 0x9256, 0x25ee,
+ 0x9257, 0x0f4c,
+ 0x9258, 0x4796,
+ 0x925a, 0x0f5b,
+ 0x925b, 0x0f51,
+ 0x925d, 0x3a03,
+ 0x925e, 0x25d8,
+ 0x925f, 0x3ce0,
+ 0x9260, 0x25e0,
+ 0x9261, 0x25e4,
+ 0x9262, 0x388b,
+ 0x9263, 0x25e8,
+ 0x9264, 0x0f53,
+ 0x9265, 0x25d7,
+ 0x9266, 0x25d5,
+ 0x9267, 0x25e1,
+ 0x926b, 0x4797,
+ 0x926c, 0x25de,
+ 0x926d, 0x25dd,
+ 0x926e, 0x3d05,
+ 0x926f, 0x25e2,
+ 0x9270, 0x25e5,
+ 0x9272, 0x25ea,
+ 0x9276, 0x2831,
+ 0x9277, 0x3c64,
+ 0x9278, 0x10d3,
+ 0x9279, 0x283b,
+ 0x927a, 0x2833,
+ 0x927b, 0x10d9,
+ 0x927c, 0x10dd,
+ 0x927d, 0x2844,
+ 0x927e, 0x284c,
+ 0x927f, 0x283d,
+ 0x9280, 0x10d5,
+ 0x9281, 0x3e01,
+ 0x9282, 0x2841,
+ 0x9283, 0x25d9,
+ 0x9284, 0x3cb9,
+ 0x9285, 0x10d6,
+ 0x9286, 0x2848,
+ 0x9287, 0x284d,
+ 0x9288, 0x2845,
+ 0x9289, 0x3ab5,
+ 0x928a, 0x2847,
+ 0x928b, 0x2850,
+ 0x928c, 0x2849,
+ 0x928d, 0x2837,
+ 0x928e, 0x2840,
+ 0x928f, 0x46bd,
+ 0x9291, 0x10de,
+ 0x9293, 0x10da,
+ 0x9294, 0x2835,
+ 0x9295, 0x2842,
+ 0x9296, 0x10d8,
+ 0x9297, 0x283c,
+ 0x9298, 0x10d7,
+ 0x9299, 0x284a,
+ 0x929a, 0x2839,
+ 0x929b, 0x2832,
+ 0x929c, 0x10db,
+ 0x929d, 0x284f,
+ 0x92a0, 0x2834,
+ 0x92a1, 0x2846,
+ 0x92a2, 0x2843,
+ 0x92a3, 0x283e,
+ 0x92a4, 0x2830,
+ 0x92a5, 0x282f,
+ 0x92a6, 0x2838,
+ 0x92a7, 0x284b,
+ 0x92a8, 0x10dc,
+ 0x92a9, 0x284e,
+ 0x92aa, 0x2836,
+ 0x92ab, 0x283a,
+ 0x92ac, 0x10d4,
+ 0x92ae, 0x4799,
+ 0x92b1, 0x4798,
+ 0x92b2, 0x125f,
+ 0x92b3, 0x125a,
+ 0x92b4, 0x2ab0,
+ 0x92b5, 0x2aac,
+ 0x92b6, 0x2a94,
+ 0x92b7, 0x1256,
+ 0x92b9, 0x36e9,
+ 0x92ba, 0x3bf5,
+ 0x92bb, 0x1255,
+ 0x92bc, 0x125b,
+ 0x92be, 0x3c60,
+ 0x92bf, 0x479a,
+ 0x92c0, 0x2a92,
+ 0x92c1, 0x1259,
+ 0x92c2, 0x2a9e,
+ 0x92c3, 0x2a90,
+ 0x92c5, 0x1254,
+ 0x92c6, 0x2aaf,
+ 0x92c7, 0x125d,
+ 0x92c8, 0x2aa1,
+ 0x92c9, 0x2aa6,
+ 0x92ca, 0x2aa0,
+ 0x92cb, 0x2cd3,
+ 0x92cc, 0x2a9c,
+ 0x92cd, 0x2aa4,
+ 0x92ce, 0x2aa2,
+ 0x92cf, 0x2a95,
+ 0x92d0, 0x2a8f,
+ 0x92d1, 0x2aaa,
+ 0x92d2, 0x125c,
+ 0x92d3, 0x2aab,
+ 0x92d4, 0x3861,
+ 0x92d5, 0x2aa5,
+ 0x92d7, 0x2a9a,
+ 0x92d8, 0x2a98,
+ 0x92d9, 0x2a93,
+ 0x92db, 0x400c,
+ 0x92dd, 0x2a9b,
+ 0x92de, 0x2aa8,
+ 0x92df, 0x2a97,
+ 0x92e0, 0x2aa7,
+ 0x92e1, 0x2aad,
+ 0x92e3, 0x479b,
+ 0x92e4, 0x1258,
+ 0x92e5, 0x3ca2,
+ 0x92e6, 0x2aa3,
+ 0x92e7, 0x2aa9,
+ 0x92e8, 0x2a9f,
+ 0x92e9, 0x2a99,
+ 0x92ea, 0x1257,
+ 0x92eb, 0x479c,
+ 0x92ec, 0x3964,
+ 0x92ee, 0x283f,
+ 0x92ef, 0x2a9d,
+ 0x92f0, 0x125e,
+ 0x92f1, 0x2a96,
+ 0x92f2, 0x3ab2,
+ 0x92f3, 0x479d,
+ 0x92f6, 0x3c04,
+ 0x92f7, 0x2cd8,
+ 0x92f8, 0x1377,
+ 0x92f9, 0x2cd7,
+ 0x92fa, 0x2cd5,
+ 0x92fb, 0x2ce7,
+ 0x92fc, 0x137b,
+ 0x92fd, 0x479f,
+ 0x92fe, 0x2ce4,
+ 0x92ff, 0x2cdc,
+ 0x9300, 0x2ce6,
+ 0x9301, 0x2cce,
+ 0x9302, 0x2cda,
+ 0x9303, 0x3867,
+ 0x9304, 0x137d,
+ 0x9306, 0x2cc6,
+ 0x9307, 0x3b11,
+ 0x9308, 0x2cc4,
+ 0x9309, 0x2ce5,
+ 0x930b, 0x2ce3,
+ 0x930c, 0x2ce2,
+ 0x930d, 0x2cd2,
+ 0x930e, 0x2cd1,
+ 0x930f, 0x2cc7,
+ 0x9310, 0x137f,
+ 0x9312, 0x2ccd,
+ 0x9313, 0x2cd6,
+ 0x9314, 0x2ce1,
+ 0x9315, 0x1382,
+ 0x9316, 0x2ce8,
+ 0x9318, 0x14a3,
+ 0x9319, 0x1384,
+ 0x931a, 0x137e,
+ 0x931b, 0x2ccb,
+ 0x931d, 0x2cd4,
+ 0x931e, 0x2cc3,
+ 0x931f, 0x2cc5,
+ 0x9320, 0x1375,
+ 0x9321, 0x1381,
+ 0x9322, 0x137a,
+ 0x9323, 0x2ccc,
+ 0x9324, 0x2cdb,
+ 0x9325, 0x2aae,
+ 0x9326, 0x1380,
+ 0x9327, 0x2cc2,
+ 0x9328, 0x149e,
+ 0x9329, 0x2cdd,
+ 0x932a, 0x2ce0,
+ 0x932b, 0x137c,
+ 0x932c, 0x3892,
+ 0x932d, 0x2cd0,
+ 0x932e, 0x1383,
+ 0x932f, 0x1379,
+ 0x9330, 0x3e03,
+ 0x9331, 0x3cbd,
+ 0x9333, 0x1378,
+ 0x9334, 0x2cd9,
+ 0x9335, 0x2cdf,
+ 0x9336, 0x1376,
+ 0x9338, 0x2cc9,
+ 0x9339, 0x2cde,
+ 0x933c, 0x2cca,
+ 0x9340, 0x4155,
+ 0x9341, 0x4277,
+ 0x9342, 0x3afa,
+ 0x9343, 0x47a0,
+ 0x9344, 0x4016,
+ 0x9345, 0x3e74,
+ 0x9346, 0x2ccf,
+ 0x9347, 0x2e8d,
+ 0x9348, 0x3c61,
+ 0x9349, 0x2e92,
+ 0x934a, 0x14a0,
+ 0x934b, 0x14a2,
+ 0x934c, 0x2e98,
+ 0x934d, 0x149c,
+ 0x934e, 0x2ea6,
+ 0x934f, 0x2e9e,
+ 0x9350, 0x2e93,
+ 0x9352, 0x2e9d,
+ 0x9354, 0x14a9,
+ 0x9355, 0x2e9c,
+ 0x9356, 0x2e8c,
+ 0x9357, 0x2e9b,
+ 0x9358, 0x2e8f,
+ 0x9359, 0x2ea7,
+ 0x935a, 0x14a8,
+ 0x935b, 0x14a6,
+ 0x935c, 0x2e90,
+ 0x935e, 0x2ea3,
+ 0x935f, 0x3cbb,
+ 0x9360, 0x2e95,
+ 0x9361, 0x2ea2,
+ 0x9362, 0x4268,
+ 0x9363, 0x2ea4,
+ 0x9364, 0x2e8b,
+ 0x9365, 0x14a1,
+ 0x9366, 0x46bc,
+ 0x9367, 0x2ea5,
+ 0x9368, 0x3bf0,
+ 0x9369, 0x3961,
+ 0x936a, 0x2e99,
+ 0x936b, 0x3893,
+ 0x936c, 0x14a5,
+ 0x936d, 0x2e96,
+ 0x936e, 0x39e8,
+ 0x9370, 0x14a7,
+ 0x9371, 0x2e9f,
+ 0x9373, 0x389e,
+ 0x9374, 0x3ce4,
+ 0x9375, 0x149f,
+ 0x9376, 0x2e91,
+ 0x9377, 0x2ea0,
+ 0x9378, 0x38f9,
+ 0x9379, 0x2e9a,
+ 0x937a, 0x2cc8,
+ 0x937b, 0x2ea1,
+ 0x937c, 0x2e8e,
+ 0x937d, 0x3c25,
+ 0x937e, 0x14a4,
+ 0x9380, 0x3014,
+ 0x9381, 0x3965,
+ 0x9382, 0x149d,
+ 0x9383, 0x2e89,
+ 0x9384, 0x47a1,
+ 0x9385, 0x42bd,
+ 0x9386, 0x3cc0,
+ 0x9387, 0x3ae0,
+ 0x9388, 0x3011,
+ 0x9389, 0x300a,
+ 0x938a, 0x1540,
+ 0x938c, 0x3005,
+ 0x938d, 0x3015,
+ 0x938e, 0x300c,
+ 0x938f, 0x2e97,
+ 0x9390, 0x3d3c,
+ 0x9391, 0x3017,
+ 0x9392, 0x3006,
+ 0x9394, 0x153f,
+ 0x9395, 0x3010,
+ 0x9396, 0x1541,
+ 0x9397, 0x1549,
+ 0x9398, 0x1547,
+ 0x9399, 0x3012,
+ 0x939a, 0x1548,
+ 0x939b, 0x3008,
+ 0x939c, 0x39ac,
+ 0x939d, 0x3009,
+ 0x939e, 0x300e,
+ 0x939f, 0x3013,
+ 0x93a0, 0x3ab1,
+ 0x93a1, 0x2e88,
+ 0x93a2, 0x1542,
+ 0x93a3, 0x301c,
+ 0x93a4, 0x3019,
+ 0x93a5, 0x3160,
+ 0x93a6, 0x300f,
+ 0x93a7, 0x300b,
+ 0x93a8, 0x301a,
+ 0x93a9, 0x3155,
+ 0x93aa, 0x300d,
+ 0x93ac, 0x1545,
+ 0x93ad, 0x47a2,
+ 0x93ae, 0x1544,
+ 0x93af, 0x2e8a,
+ 0x93b0, 0x1546,
+ 0x93b1, 0x3016,
+ 0x93b2, 0x3018,
+ 0x93b3, 0x1543,
+ 0x93b4, 0x301b,
+ 0x93b5, 0x3004,
+ 0x93b7, 0x3007,
+ 0x93b8, 0x3c90,
+ 0x93ba, 0x43f7,
+ 0x93bb, 0x3c8f,
+ 0x93bd, 0x3a27,
+ 0x93bf, 0x3e2d,
+ 0x93c0, 0x315e,
+ 0x93c2, 0x314e,
+ 0x93c3, 0x15e0,
+ 0x93c4, 0x315c,
+ 0x93c6, 0x39aa,
+ 0x93c7, 0x314c,
+ 0x93c8, 0x15e1,
+ 0x93ca, 0x3157,
+ 0x93cb, 0x3966,
+ 0x93cc, 0x3153,
+ 0x93cd, 0x15e6,
+ 0x93ce, 0x315d,
+ 0x93cf, 0x314d,
+ 0x93d0, 0x3150,
+ 0x93d1, 0x15de,
+ 0x93d2, 0x315f,
+ 0x93d3, 0x40e1,
+ 0x93d4, 0x3158,
+ 0x93d5, 0x315b,
+ 0x93d6, 0x15e4,
+ 0x93d7, 0x15e9,
+ 0x93d8, 0x15e7,
+ 0x93d9, 0x3154,
+ 0x93da, 0x314f,
+ 0x93db, 0x3c5f,
+ 0x93dc, 0x15e2,
+ 0x93de, 0x314b,
+ 0x93df, 0x15df,
+ 0x93e0, 0x3a20,
+ 0x93e1, 0x15dd,
+ 0x93e2, 0x15e5,
+ 0x93e3, 0x315a,
+ 0x93e4, 0x15e8,
+ 0x93e6, 0x3156,
+ 0x93e7, 0x3161,
+ 0x93e8, 0x15ea,
+ 0x93ec, 0x3152,
+ 0x93ee, 0x3159,
+ 0x93f0, 0x423f,
+ 0x93f1, 0x42aa,
+ 0x93f3, 0x3962,
+ 0x93f5, 0x325a,
+ 0x93f6, 0x3269,
+ 0x93f7, 0x325c,
+ 0x93f8, 0x3263,
+ 0x93f9, 0x3151,
+ 0x93fa, 0x3261,
+ 0x93fb, 0x3250,
+ 0x93fc, 0x3267,
+ 0x93fd, 0x1654,
+ 0x93fe, 0x3254,
+ 0x93ff, 0x3266,
+ 0x9400, 0x325b,
+ 0x9401, 0x3cd4,
+ 0x9403, 0x1653,
+ 0x9404, 0x3bc9,
+ 0x9406, 0x326b,
+ 0x9407, 0x325d,
+ 0x9408, 0x3a25,
+ 0x9409, 0x3262,
+ 0x940a, 0x3265,
+ 0x940b, 0x324e,
+ 0x940c, 0x3268,
+ 0x940d, 0x3259,
+ 0x940e, 0x325e,
+ 0x940f, 0x3252,
+ 0x9410, 0x3256,
+ 0x9411, 0x326a,
+ 0x9412, 0x3260,
+ 0x9413, 0x324f,
+ 0x9414, 0x3253,
+ 0x9415, 0x3255,
+ 0x9416, 0x325f,
+ 0x9417, 0x47a5,
+ 0x9418, 0x1652,
+ 0x9419, 0x3258,
+ 0x941b, 0x4148,
+ 0x941d, 0x47a6,
+ 0x9420, 0x3251,
+ 0x9424, 0x3943,
+ 0x9425, 0x38d0,
+ 0x9426, 0x38a3,
+ 0x9427, 0x3bcd,
+ 0x9428, 0x3257,
+ 0x9429, 0x3325,
+ 0x942a, 0x3329,
+ 0x942b, 0x169f,
+ 0x942c, 0x332b,
+ 0x942d, 0x47a7,
+ 0x942e, 0x1699,
+ 0x9430, 0x3327,
+ 0x9431, 0x332d,
+ 0x9432, 0x169e,
+ 0x9433, 0x169a,
+ 0x9435, 0x169b,
+ 0x9436, 0x3324,
+ 0x9437, 0x332a,
+ 0x9438, 0x169d,
+ 0x9439, 0x3328,
+ 0x943a, 0x169c,
+ 0x943b, 0x3323,
+ 0x943c, 0x3264,
+ 0x943d, 0x3326,
+ 0x943e, 0x47a8,
+ 0x943f, 0x3322,
+ 0x9440, 0x332c,
+ 0x9442, 0x4272,
+ 0x9443, 0x4275,
+ 0x9444, 0x16df,
+ 0x9445, 0x33cd,
+ 0x9446, 0x33d0,
+ 0x9447, 0x33cc,
+ 0x9448, 0x33ce,
+ 0x944a, 0x33c9,
+ 0x944c, 0x33c7,
+ 0x944d, 0x3c65,
+ 0x944f, 0x33cb,
+ 0x9450, 0x33c8,
+ 0x9451, 0x16e0,
+ 0x9454, 0x47aa,
+ 0x9455, 0x3448,
+ 0x9457, 0x344a,
+ 0x9458, 0x3c30,
+ 0x945b, 0x389f,
+ 0x945d, 0x3449,
+ 0x945e, 0x344b,
+ 0x9460, 0x170e,
+ 0x9462, 0x3447,
+ 0x9463, 0x170d,
+ 0x9464, 0x170f,
+ 0x9465, 0x3dde,
+ 0x9467, 0x3ab8,
+ 0x9468, 0x34a6,
+ 0x946a, 0x1731,
+ 0x946b, 0x34a5,
+ 0x946c, 0x377e,
+ 0x946d, 0x34ed,
+ 0x946e, 0x34ec,
+ 0x946f, 0x34ee,
+ 0x9470, 0x174c,
+ 0x9471, 0x34ef,
+ 0x9472, 0x174b,
+ 0x9473, 0x34f0,
+ 0x9474, 0x350c,
+ 0x9475, 0x350f,
+ 0x9476, 0x350e,
+ 0x9477, 0x1755,
+ 0x9478, 0x350d,
+ 0x9479, 0x47ab,
+ 0x947b, 0x419b,
+ 0x947c, 0x175f,
+ 0x947d, 0x175d,
+ 0x947f, 0x1764,
+ 0x9480, 0x3539,
+ 0x9482, 0x3538,
+ 0x9483, 0x3540,
+ 0x9485, 0x4507,
+ 0x949f, 0x4885,
+ 0x94a2, 0x451b,
+ 0x94c1, 0x47e1,
+ 0x94c3, 0x47df,
+ 0x94dc, 0x47d7,
+ 0x94f6, 0x47d2,
+ 0x952d, 0x47ac,
+ 0x9547, 0x48bf,
+ 0x9577, 0x0697,
+ 0x9578, 0x4508,
+ 0x957a, 0x20a1,
+ 0x957b, 0x234a,
+ 0x957c, 0x2ab1,
+ 0x957d, 0x3162,
+ 0x957f, 0x4509,
+ 0x9580, 0x0698,
+ 0x9582, 0x0821,
+ 0x9583, 0x09ea,
+ 0x9585, 0x38a1,
+ 0x9586, 0x20a2,
+ 0x9588, 0x20a3,
+ 0x9589, 0x0bd0,
+ 0x958b, 0x0d9a,
+ 0x958c, 0x234c,
+ 0x958d, 0x234b,
+ 0x958e, 0x0d9e,
+ 0x958f, 0x0d99,
+ 0x9590, 0x234d,
+ 0x9591, 0x0d9b,
+ 0x9592, 0x0d9d,
+ 0x9593, 0x0d9c,
+ 0x9594, 0x0d98,
+ 0x9596, 0x3bd5,
+ 0x9597, 0x3bd4,
+ 0x9598, 0x0f5c,
+ 0x9599, 0x3bd2,
+ 0x959b, 0x25f3,
+ 0x959c, 0x25f1,
+ 0x959e, 0x25f2,
+ 0x959f, 0x25f0,
+ 0x95a0, 0x38a4,
+ 0x95a1, 0x10df,
+ 0x95a2, 0x47ad,
+ 0x95a3, 0x10e2,
+ 0x95a4, 0x10e4,
+ 0x95a5, 0x10e3,
+ 0x95a6, 0x38a2,
+ 0x95a7, 0x3bd3,
+ 0x95a8, 0x10e0,
+ 0x95aa, 0x4395,
+ 0x95ab, 0x2ab3,
+ 0x95ac, 0x2ab2,
+ 0x95ad, 0x1260,
+ 0x95ae, 0x2ab4,
+ 0x95b0, 0x2ab5,
+ 0x95b1, 0x1261,
+ 0x95b5, 0x2cf0,
+ 0x95b6, 0x2cee,
+ 0x95b7, 0x2ead,
+ 0x95b9, 0x2cec,
+ 0x95bb, 0x1385,
+ 0x95bc, 0x2ce9,
+ 0x95bd, 0x2cf1,
+ 0x95be, 0x2ceb,
+ 0x95bf, 0x2cef,
+ 0x95c0, 0x2ea9,
+ 0x95c3, 0x2eab,
+ 0x95c5, 0x2eac,
+ 0x95c6, 0x14ae,
+ 0x95c7, 0x2ea8,
+ 0x95c8, 0x14ad,
+ 0x95c9, 0x2eaa,
+ 0x95ca, 0x14aa,
+ 0x95cd, 0x2cea,
+ 0x95d0, 0x154c,
+ 0x95d1, 0x301f,
+ 0x95d2, 0x301d,
+ 0x95d4, 0x154a,
+ 0x95d5, 0x154d,
+ 0x95d6, 0x154b,
+ 0x95da, 0x3163,
+ 0x95dc, 0x15eb,
+ 0x95de, 0x326c,
+ 0x95df, 0x326e,
+ 0x95e0, 0x326d,
+ 0x95e1, 0x1655,
+ 0x95e2, 0x16a0,
+ 0x95e3, 0x3330,
+ 0x95e4, 0x332f,
+ 0x95e5, 0x332e,
+ 0x95e8, 0x450a,
+ 0x95f4, 0x47af,
+ 0x961c, 0x0699,
+ 0x961d, 0x4519,
+ 0x961e, 0x17b4,
+ 0x9620, 0x1821,
+ 0x9621, 0x0414,
+ 0x9622, 0x181f,
+ 0x9623, 0x1822,
+ 0x9624, 0x1820,
+ 0x9628, 0x18f1,
+ 0x962a, 0x0526,
+ 0x962c, 0x0527,
+ 0x962d, 0x18f3,
+ 0x962e, 0x0524,
+ 0x962f, 0x18f2,
+ 0x9630, 0x18f0,
+ 0x9631, 0x0525,
+ 0x9632, 0x0523,
+ 0x9633, 0x47b0,
+ 0x9638, 0x3fd1,
+ 0x9639, 0x1a55,
+ 0x963a, 0x1a58,
+ 0x963b, 0x069c,
+ 0x963c, 0x1a57,
+ 0x963d, 0x1a56,
+ 0x963f, 0x069b,
+ 0x9640, 0x069a,
+ 0x9641, 0x3f3d,
+ 0x9642, 0x069e,
+ 0x9643, 0x1a59,
+ 0x9644, 0x069d,
+ 0x9645, 0x4772,
+ 0x964a, 0x1c1a,
+ 0x964b, 0x0823,
+ 0x964e, 0x1c1b,
+ 0x964f, 0x1c17,
+ 0x9650, 0x0822,
+ 0x9651, 0x1c18,
+ 0x9653, 0x1c19,
+ 0x9654, 0x1c16,
+ 0x9656, 0x3de7,
+ 0x9658, 0x09f1,
+ 0x965b, 0x09ee,
+ 0x965c, 0x1e2f,
+ 0x965d, 0x09ef,
+ 0x965e, 0x09f2,
+ 0x965f, 0x1e30,
+ 0x9661, 0x09ed,
+ 0x9662, 0x09eb,
+ 0x9664, 0x09f0,
+ 0x9669, 0x475e,
+ 0x966a, 0x0bd1,
+ 0x966b, 0x20a6,
+ 0x966c, 0x0bd9,
+ 0x966d, 0x20a5,
+ 0x966f, 0x20a8,
+ 0x9670, 0x0bd5,
+ 0x9671, 0x20a7,
+ 0x9672, 0x0da6,
+ 0x9673, 0x0bd3,
+ 0x9674, 0x0bd6,
+ 0x9675, 0x0bd2,
+ 0x9676, 0x0bd7,
+ 0x9678, 0x0bd4,
+ 0x967b, 0x38ac,
+ 0x967c, 0x20a4,
+ 0x967d, 0x0da2,
+ 0x967e, 0x234f,
+ 0x9680, 0x2353,
+ 0x9681, 0x3f46,
+ 0x9683, 0x2352,
+ 0x9684, 0x0da7,
+ 0x9685, 0x0da3,
+ 0x9687, 0x234e,
+ 0x9688, 0x2350,
+ 0x968a, 0x0d9f,
+ 0x968b, 0x0da1,
+ 0x968d, 0x0da5,
+ 0x968e, 0x0da0,
+ 0x968f, 0x3bde,
+ 0x9691, 0x25f6,
+ 0x9692, 0x25f4,
+ 0x9694, 0x0f5e,
+ 0x9696, 0x38ad,
+ 0x9697, 0x25f7,
+ 0x9698, 0x0f5d,
+ 0x9699, 0x10e5,
+ 0x969b, 0x10e7,
+ 0x969c, 0x10e6,
+ 0x969e, 0x2852,
+ 0x96a1, 0x2853,
+ 0x96a2, 0x2ab7,
+ 0x96a3, 0x38af,
+ 0x96a4, 0x2ab6,
+ 0x96a5, 0x42ef,
+ 0x96a7, 0x1386,
+ 0x96a9, 0x2cf2,
+ 0x96aa, 0x1388,
+ 0x96ac, 0x2eb0,
+ 0x96ae, 0x2eae,
+ 0x96b0, 0x2eaf,
+ 0x96b1, 0x14af,
+ 0x96b3, 0x3020,
+ 0x96b4, 0x15ec,
+ 0x96b6, 0x0231,
+ 0x96b8, 0x14b0,
+ 0x96b9, 0x069f,
+ 0x96bb, 0x09f3,
+ 0x96bc, 0x1e31,
+ 0x96bd, 0x38b5,
+ 0x96bf, 0x20a9,
+ 0x96c0, 0x0bda,
+ 0x96c1, 0x0da8,
+ 0x96c2, 0x2354,
+ 0x96c3, 0x2356,
+ 0x96c4, 0x0daa,
+ 0x96c5, 0x0da9,
+ 0x96c6, 0x0dab,
+ 0x96c8, 0x2355,
+ 0x96c9, 0x0f62,
+ 0x96cb, 0x0f61,
+ 0x96cc, 0x10e8,
+ 0x96cd, 0x0f60,
+ 0x96ce, 0x25f8,
+ 0x96d2, 0x10e9,
+ 0x96d3, 0x2ab8,
+ 0x96d4, 0x2cf3,
+ 0x96d5, 0x1389,
+ 0x96d6, 0x14b1,
+ 0x96d7, 0x3021,
+ 0x96d8, 0x3025,
+ 0x96d9, 0x1550,
+ 0x96da, 0x3022,
+ 0x96db, 0x1551,
+ 0x96dc, 0x154f,
+ 0x96dd, 0x3026,
+ 0x96de, 0x1552,
+ 0x96df, 0x3024,
+ 0x96e1, 0x3165,
+ 0x96e2, 0x154e,
+ 0x96e3, 0x15ed,
+ 0x96e5, 0x34a8,
+ 0x96e8, 0x06a0,
+ 0x96e9, 0x0bdc,
+ 0x96ea, 0x0bdb,
+ 0x96ef, 0x0dad,
+ 0x96f0, 0x2358,
+ 0x96f1, 0x2357,
+ 0x96f2, 0x0dae,
+ 0x96f4, 0x3a04,
+ 0x96f5, 0x25fc,
+ 0x96f6, 0x0f67,
+ 0x96f7, 0x0f64,
+ 0x96f8, 0x25fb,
+ 0x96f9, 0x0f66,
+ 0x96fa, 0x25f9,
+ 0x96fb, 0x0f65,
+ 0x96fd, 0x25fa,
+ 0x96ff, 0x2854,
+ 0x9700, 0x10ea,
+ 0x9702, 0x2abb,
+ 0x9703, 0x3f0d,
+ 0x9704, 0x1262,
+ 0x9705, 0x2ab9,
+ 0x9706, 0x1263,
+ 0x9708, 0x2aba,
+ 0x9709, 0x1265,
+ 0x970b, 0x2cf4,
+ 0x970d, 0x138d,
+ 0x970e, 0x138a,
+ 0x970f, 0x138f,
+ 0x9710, 0x2cf6,
+ 0x9711, 0x138b,
+ 0x9712, 0x2cf5,
+ 0x9713, 0x138e,
+ 0x9716, 0x138c,
+ 0x9718, 0x2eb3,
+ 0x9719, 0x2eb5,
+ 0x971b, 0x38c9,
+ 0x971c, 0x14b2,
+ 0x971d, 0x2eb4,
+ 0x971e, 0x14b3,
+ 0x971f, 0x2eb2,
+ 0x9720, 0x2eb1,
+ 0x9721, 0x3fb3,
+ 0x9722, 0x3028,
+ 0x9723, 0x3027,
+ 0x9724, 0x1553,
+ 0x9725, 0x3029,
+ 0x9726, 0x316a,
+ 0x9727, 0x15ef,
+ 0x9728, 0x3169,
+ 0x9729, 0x3166,
+ 0x972a, 0x15ee,
+ 0x972b, 0x3167,
+ 0x972e, 0x326f,
+ 0x9730, 0x1656,
+ 0x9731, 0x38c0,
+ 0x9732, 0x16a3,
+ 0x9735, 0x3331,
+ 0x9736, 0x38c2,
+ 0x9738, 0x16a1,
+ 0x973a, 0x3332,
+ 0x973d, 0x16e2,
+ 0x973f, 0x33d1,
+ 0x9740, 0x47b3,
+ 0x9741, 0x3be9,
+ 0x9742, 0x1732,
+ 0x9743, 0x34aa,
+ 0x9744, 0x1734,
+ 0x9746, 0x34a9,
+ 0x9747, 0x34ab,
+ 0x9748, 0x1733,
+ 0x9749, 0x34f1,
+ 0x974b, 0x3526,
+ 0x9751, 0x44e3,
+ 0x9752, 0x06a1,
+ 0x9756, 0x0f68,
+ 0x9757, 0x38cc,
+ 0x9758, 0x2855,
+ 0x975a, 0x2abc,
+ 0x975b, 0x1390,
+ 0x975d, 0x3bef,
+ 0x975e, 0x06a2,
+ 0x975f, 0x38cf,
+ 0x9760, 0x1266,
+ 0x9761, 0x15f0,
+ 0x9762, 0x0826,
+ 0x9766, 0x1392,
+ 0x9768, 0x1710,
+ 0x9769, 0x0827,
+ 0x976a, 0x20aa,
+ 0x976c, 0x2359,
+ 0x976d, 0x3e97,
+ 0x976e, 0x235b,
+ 0x9770, 0x235a,
+ 0x9771, 0x3bfc,
+ 0x9772, 0x2600,
+ 0x9773, 0x25fd,
+ 0x9774, 0x0f69,
+ 0x9776, 0x0f6a,
+ 0x9777, 0x25fe,
+ 0x977a, 0x2857,
+ 0x977b, 0x285c,
+ 0x977c, 0x10eb,
+ 0x977d, 0x2856,
+ 0x977e, 0x2858,
+ 0x977f, 0x285f,
+ 0x9780, 0x285a,
+ 0x9781, 0x285e,
+ 0x9782, 0x285b,
+ 0x9783, 0x2859,
+ 0x9784, 0x285d,
+ 0x9785, 0x10ec,
+ 0x9787, 0x40c0,
+ 0x9788, 0x2abf,
+ 0x9789, 0x38d4,
+ 0x978a, 0x2abd,
+ 0x978b, 0x1268,
+ 0x978d, 0x1267,
+ 0x978e, 0x2abe,
+ 0x978f, 0x1269,
+ 0x9794, 0x2cf9,
+ 0x9797, 0x2cf8,
+ 0x9798, 0x1393,
+ 0x9799, 0x2cf7,
+ 0x979a, 0x2eb6,
+ 0x979b, 0x3bfb,
+ 0x979c, 0x2eb8,
+ 0x979d, 0x2eba,
+ 0x979e, 0x2eb9,
+ 0x979f, 0x38d5,
+ 0x97a0, 0x14b4,
+ 0x97a1, 0x2eb7,
+ 0x97a2, 0x3030,
+ 0x97a3, 0x1554,
+ 0x97a4, 0x302e,
+ 0x97a5, 0x3031,
+ 0x97a6, 0x1555,
+ 0x97a8, 0x302c,
+ 0x97aa, 0x302f,
+ 0x97ab, 0x302d,
+ 0x97ac, 0x302a,
+ 0x97ad, 0x1556,
+ 0x97ae, 0x302b,
+ 0x97b1, 0x38d6,
+ 0x97b2, 0x47b5,
+ 0x97b3, 0x316b,
+ 0x97b4, 0x3f33,
+ 0x97b6, 0x316d,
+ 0x97b7, 0x316c,
+ 0x97b8, 0x3d95,
+ 0x97b9, 0x3271,
+ 0x97ba, 0x3f35,
+ 0x97bb, 0x3272,
+ 0x97bd, 0x494e,
+ 0x97be, 0x38d7,
+ 0x97bf, 0x3333,
+ 0x97c0, 0x38d8,
+ 0x97c1, 0x16e5,
+ 0x97c2, 0x47b6,
+ 0x97c3, 0x16e4,
+ 0x97c4, 0x344c,
+ 0x97c6, 0x1735,
+ 0x97c7, 0x34ac,
+ 0x97c8, 0x3f2f,
+ 0x97c9, 0x1756,
+ 0x97cb, 0x0828,
+ 0x97cc, 0x0daf,
+ 0x97cd, 0x2861,
+ 0x97ce, 0x2860,
+ 0x97cf, 0x2ac1,
+ 0x97d0, 0x2ac0,
+ 0x97d2, 0x38d9,
+ 0x97d3, 0x14b5,
+ 0x97d4, 0x2ebc,
+ 0x97d5, 0x2ebb,
+ 0x97d6, 0x3034,
+ 0x97d7, 0x3032,
+ 0x97d8, 0x3035,
+ 0x97d9, 0x3033,
+ 0x97dc, 0x15f1,
+ 0x97dd, 0x316e,
+ 0x97e0, 0x38da,
+ 0x97e1, 0x3334,
+ 0x97e3, 0x33d2,
+ 0x97e5, 0x34ad,
+ 0x97e6, 0x450c,
+ 0x97ed, 0x0829,
+ 0x97ee, 0x38dc,
+ 0x97f0, 0x2cfa,
+ 0x97f1, 0x2ebd,
+ 0x97f2, 0x394d,
+ 0x97f3, 0x082a,
+ 0x97f5, 0x38e0,
+ 0x97f6, 0x10ed,
+ 0x97f8, 0x2cfb,
+ 0x97f9, 0x1557,
+ 0x97fa, 0x3036,
+ 0x97fb, 0x15f2,
+ 0x97fd, 0x3273,
+ 0x97ff, 0x16a4,
+ 0x9800, 0x344e,
+ 0x9801, 0x082b,
+ 0x9802, 0x0bdf,
+ 0x9804, 0x20ab,
+ 0x9805, 0x0db0,
+ 0x9807, 0x235c,
+ 0x9808, 0x0db2,
+ 0x980a, 0x0f6e,
+ 0x980c, 0x0f70,
+ 0x980d, 0x2602,
+ 0x980f, 0x2601,
+ 0x9810, 0x0f6b,
+ 0x9812, 0x0f6f,
+ 0x9813, 0x0f6d,
+ 0x9814, 0x4952,
+ 0x9815, 0x433c,
+ 0x9816, 0x2862,
+ 0x9817, 0x10ee,
+ 0x981b, 0x2ac8,
+ 0x981c, 0x126c,
+ 0x981d, 0x2ac3,
+ 0x981e, 0x2ac2,
+ 0x981f, 0x3c02,
+ 0x9820, 0x2ac7,
+ 0x9821, 0x126a,
+ 0x9823, 0x3e37,
+ 0x9824, 0x139a,
+ 0x9826, 0x2ac4,
+ 0x9827, 0x2ac9,
+ 0x9828, 0x2ac6,
+ 0x9829, 0x2ac5,
+ 0x982b, 0x126b,
+ 0x982d, 0x1398,
+ 0x982e, 0x3f72,
+ 0x982f, 0x2cfd,
+ 0x9830, 0x1394,
+ 0x9832, 0x2cfe,
+ 0x9833, 0x38e5,
+ 0x9834, 0x38e4,
+ 0x9835, 0x2cfc,
+ 0x9837, 0x1397,
+ 0x9838, 0x1395,
+ 0x9839, 0x1399,
+ 0x983b, 0x1396,
+ 0x9841, 0x2ebe,
+ 0x9843, 0x2ec3,
+ 0x9844, 0x2ebf,
+ 0x9845, 0x2ec2,
+ 0x9846, 0x14b6,
+ 0x9847, 0x3d96,
+ 0x9848, 0x2df2,
+ 0x9849, 0x2ec1,
+ 0x984a, 0x2ec0,
+ 0x984b, 0x38e6,
+ 0x984c, 0x155a,
+ 0x984d, 0x1558,
+ 0x984e, 0x155b,
+ 0x984f, 0x1559,
+ 0x9850, 0x3037,
+ 0x9853, 0x155c,
+ 0x9857, 0x3174,
+ 0x9858, 0x15f4,
+ 0x9859, 0x3172,
+ 0x985b, 0x15f5,
+ 0x985c, 0x3171,
+ 0x985d, 0x3173,
+ 0x985e, 0x15f3,
+ 0x985f, 0x3278,
+ 0x9860, 0x3275,
+ 0x9862, 0x3276,
+ 0x9864, 0x3335,
+ 0x9865, 0x16a6,
+ 0x9866, 0x38e7,
+ 0x9867, 0x16a5,
+ 0x9869, 0x33d4,
+ 0x986a, 0x33d3,
+ 0x986b, 0x16e6,
+ 0x986c, 0x4035,
+ 0x986f, 0x1711,
+ 0x9870, 0x1736,
+ 0x9871, 0x174d,
+ 0x9872, 0x34f2,
+ 0x9873, 0x3527,
+ 0x9875, 0x450d,
+ 0x98a8, 0x082c,
+ 0x98a9, 0x235d,
+ 0x98ac, 0x2604,
+ 0x98ad, 0x2863,
+ 0x98af, 0x10f0,
+ 0x98b1, 0x10f1,
+ 0x98b2, 0x2aca,
+ 0x98b3, 0x126d,
+ 0x98b4, 0x3f73,
+ 0x98b6, 0x14b7,
+ 0x98b7, 0x38ef,
+ 0x98b8, 0x303a,
+ 0x98b9, 0x47b8,
+ 0x98ba, 0x155d,
+ 0x98bb, 0x3177,
+ 0x98bc, 0x15f6,
+ 0x98bd, 0x3176,
+ 0x98be, 0x3178,
+ 0x98bf, 0x3175,
+ 0x98c0, 0x3338,
+ 0x98c1, 0x3279,
+ 0x98c3, 0x3b78,
+ 0x98c4, 0x1657,
+ 0x98c6, 0x3337,
+ 0x98c7, 0x38f1,
+ 0x98c8, 0x38f0,
+ 0x98c9, 0x3336,
+ 0x98ca, 0x38ee,
+ 0x98cb, 0x33d5,
+ 0x98cc, 0x3529,
+ 0x98ce, 0x450e,
+ 0x98db, 0x082d,
+ 0x98dc, 0x3c0b,
+ 0x98de, 0x450f,
+ 0x98df, 0x082e,
+ 0x98e0, 0x4792,
+ 0x98e1, 0x38f6,
+ 0x98e2, 0x09f4,
+ 0x98e3, 0x1e32,
+ 0x98e5, 0x20ac,
+ 0x98e6, 0x38f7,
+ 0x98e7, 0x0db3,
+ 0x98e9, 0x0db6,
+ 0x98ea, 0x0db4,
+ 0x98eb, 0x235e,
+ 0x98ec, 0x38f8,
+ 0x98ed, 0x0db8,
+ 0x98ef, 0x0db5,
+ 0x98f1, 0x47ba,
+ 0x98f2, 0x0db7,
+ 0x98f4, 0x0f72,
+ 0x98f5, 0x4365,
+ 0x98f6, 0x2605,
+ 0x98f9, 0x2606,
+ 0x98fa, 0x2acc,
+ 0x98fc, 0x0f71,
+ 0x98fd, 0x0f73,
+ 0x9900, 0x2866,
+ 0x9902, 0x2865,
+ 0x9903, 0x10f2,
+ 0x9905, 0x10f3,
+ 0x9907, 0x2867,
+ 0x9908, 0x2acb,
+ 0x9909, 0x10f5,
+ 0x990a, 0x126e,
+ 0x990c, 0x10f4,
+ 0x990e, 0x43ed,
+ 0x9910, 0x139b,
+ 0x9911, 0x2acd,
+ 0x9912, 0x1270,
+ 0x9913, 0x126f,
+ 0x9914, 0x2ace,
+ 0x9915, 0x2ad1,
+ 0x9916, 0x2acf,
+ 0x9918, 0x1271,
+ 0x9919, 0x47bc,
+ 0x991a, 0x13a0,
+ 0x991b, 0x139e,
+ 0x991c, 0x43ee,
+ 0x991e, 0x139d,
+ 0x991f, 0x2d00,
+ 0x9921, 0x139f,
+ 0x9924, 0x2cff,
+ 0x9925, 0x2ec4,
+ 0x9927, 0x2d01,
+ 0x9928, 0x139c,
+ 0x9929, 0x2d02,
+ 0x992a, 0x2ec7,
+ 0x992b, 0x2ec5,
+ 0x992d, 0x2ecb,
+ 0x992e, 0x1561,
+ 0x992f, 0x2eca,
+ 0x9930, 0x2ecd,
+ 0x9931, 0x2ecc,
+ 0x9932, 0x2ec9,
+ 0x9933, 0x2ec8,
+ 0x9935, 0x14b8,
+ 0x9937, 0x47bd,
+ 0x9938, 0x3bfd,
+ 0x9939, 0x38fa,
+ 0x993a, 0x303d,
+ 0x993b, 0x3c11,
+ 0x993c, 0x303c,
+ 0x993d, 0x1560,
+ 0x993e, 0x155e,
+ 0x9940, 0x3f34,
+ 0x9941, 0x303b,
+ 0x9942, 0x43ff,
+ 0x9943, 0x317b,
+ 0x9945, 0x15f7,
+ 0x9947, 0x317a,
+ 0x9948, 0x3179,
+ 0x9949, 0x15f8,
+ 0x994a, 0x3fb9,
+ 0x994b, 0x327f,
+ 0x994c, 0x327e,
+ 0x994d, 0x3c12,
+ 0x994e, 0x327c,
+ 0x9950, 0x327b,
+ 0x9951, 0x1659,
+ 0x9952, 0x1658,
+ 0x9953, 0x3280,
+ 0x9954, 0x33d6,
+ 0x9955, 0x16e7,
+ 0x9956, 0x333a,
+ 0x9957, 0x16a7,
+ 0x9958, 0x3339,
+ 0x9959, 0x327d,
+ 0x995b, 0x33d7,
+ 0x995c, 0x1712,
+ 0x995d, 0x47be,
+ 0x995e, 0x174e,
+ 0x995f, 0x34f3,
+ 0x9961, 0x352a,
+ 0x9962, 0x43ef,
+ 0x9963, 0x4510,
+ 0x9996, 0x082f,
+ 0x9997, 0x20ad,
+ 0x9998, 0x2ece,
+ 0x9999, 0x0830,
+ 0x999b, 0x3c15,
+ 0x999c, 0x2869,
+ 0x999d, 0x2868,
+ 0x999e, 0x2d03,
+ 0x99a1, 0x2ed0,
+ 0x99a3, 0x2ecf,
+ 0x99a4, 0x41c3,
+ 0x99a5, 0x1562,
+ 0x99a6, 0x317c,
+ 0x99a8, 0x165a,
+ 0x99aa, 0x3c17,
+ 0x99ab, 0x352b,
+ 0x99ac, 0x09f5,
+ 0x99ad, 0x0dba,
+ 0x99ae, 0x0db9,
+ 0x99af, 0x2607,
+ 0x99b0, 0x2609,
+ 0x99b1, 0x0f76,
+ 0x99b2, 0x2608,
+ 0x99b3, 0x0f75,
+ 0x99b4, 0x0f77,
+ 0x99b5, 0x260a,
+ 0x99b8, 0x394b,
+ 0x99b9, 0x286b,
+ 0x99ba, 0x286d,
+ 0x99bb, 0x286c,
+ 0x99bc, 0x3c22,
+ 0x99bd, 0x286f,
+ 0x99c1, 0x10f6,
+ 0x99c2, 0x286e,
+ 0x99c3, 0x286a,
+ 0x99c4, 0x3d77,
+ 0x99c5, 0x47c1,
+ 0x99c7, 0x2870,
+ 0x99c9, 0x2ad8,
+ 0x99cb, 0x2adb,
+ 0x99cc, 0x2add,
+ 0x99cd, 0x2ad3,
+ 0x99ce, 0x2ad7,
+ 0x99cf, 0x2ad4,
+ 0x99d0, 0x1273,
+ 0x99d1, 0x1276,
+ 0x99d2, 0x1278,
+ 0x99d3, 0x2ad5,
+ 0x99d5, 0x1277,
+ 0x99d6, 0x2ad9,
+ 0x99d7, 0x2adc,
+ 0x99d8, 0x2ada,
+ 0x99d9, 0x1279,
+ 0x99da, 0x3f42,
+ 0x99db, 0x1275,
+ 0x99dc, 0x2ad2,
+ 0x99dd, 0x1272,
+ 0x99df, 0x1274,
+ 0x99e1, 0x3785,
+ 0x99e2, 0x13a2,
+ 0x99e3, 0x2d09,
+ 0x99e4, 0x2d07,
+ 0x99e5, 0x2d06,
+ 0x99e6, 0x3b65,
+ 0x99e7, 0x2d0c,
+ 0x99e9, 0x2d0b,
+ 0x99ea, 0x2d0a,
+ 0x99ec, 0x2d05,
+ 0x99ed, 0x13a1,
+ 0x99ee, 0x2d04,
+ 0x99f0, 0x2d08,
+ 0x99f1, 0x13a3,
+ 0x99f4, 0x2ed3,
+ 0x99f5, 0x38ff,
+ 0x99f6, 0x2ed7,
+ 0x99f7, 0x2ed4,
+ 0x99f8, 0x2ed6,
+ 0x99f9, 0x2ed5,
+ 0x99fa, 0x2ed2,
+ 0x99fb, 0x2ed8,
+ 0x99fc, 0x2edb,
+ 0x99fd, 0x2ed9,
+ 0x99ff, 0x14ba,
+ 0x9a01, 0x14b9,
+ 0x9a02, 0x2ed1,
+ 0x9a03, 0x2edc,
+ 0x9a04, 0x3042,
+ 0x9a05, 0x3045,
+ 0x9a06, 0x3047,
+ 0x9a07, 0x3046,
+ 0x9a09, 0x3040,
+ 0x9a0a, 0x3044,
+ 0x9a0b, 0x303f,
+ 0x9a0c, 0x3900,
+ 0x9a0d, 0x3041,
+ 0x9a0e, 0x1563,
+ 0x9a0f, 0x303e,
+ 0x9a10, 0x3902,
+ 0x9a11, 0x3043,
+ 0x9a14, 0x318a,
+ 0x9a15, 0x317f,
+ 0x9a16, 0x15f9,
+ 0x9a19, 0x15fa,
+ 0x9a1a, 0x317e,
+ 0x9a1b, 0x3183,
+ 0x9a1c, 0x3189,
+ 0x9a1d, 0x3181,
+ 0x9a1e, 0x3188,
+ 0x9a1f, 0x3b6c,
+ 0x9a20, 0x3185,
+ 0x9a21, 0x3c1c,
+ 0x9a22, 0x3184,
+ 0x9a23, 0x3187,
+ 0x9a24, 0x3182,
+ 0x9a25, 0x3180,
+ 0x9a26, 0x3df2,
+ 0x9a27, 0x3186,
+ 0x9a29, 0x3287,
+ 0x9a2a, 0x3285,
+ 0x9a2b, 0x165b,
+ 0x9a2c, 0x3284,
+ 0x9a2d, 0x328a,
+ 0x9a2e, 0x3288,
+ 0x9a2f, 0x3c1e,
+ 0x9a30, 0x165c,
+ 0x9a31, 0x3283,
+ 0x9a32, 0x3281,
+ 0x9a34, 0x3282,
+ 0x9a35, 0x165e,
+ 0x9a36, 0x3286,
+ 0x9a37, 0x165d,
+ 0x9a38, 0x3289,
+ 0x9a39, 0x333b,
+ 0x9a3a, 0x3341,
+ 0x9a3b, 0x3901,
+ 0x9a3c, 0x47c3,
+ 0x9a3d, 0x333c,
+ 0x9a3e, 0x16ab,
+ 0x9a3f, 0x3342,
+ 0x9a40, 0x16aa,
+ 0x9a41, 0x3340,
+ 0x9a42, 0x333f,
+ 0x9a43, 0x16a9,
+ 0x9a44, 0x333e,
+ 0x9a45, 0x16a8,
+ 0x9a46, 0x333d,
+ 0x9a48, 0x33dd,
+ 0x9a49, 0x33df,
+ 0x9a4a, 0x33de,
+ 0x9a4c, 0x33db,
+ 0x9a4d, 0x16e9,
+ 0x9a4e, 0x33d8,
+ 0x9a4f, 0x33dc,
+ 0x9a50, 0x33e1,
+ 0x9a52, 0x33e0,
+ 0x9a53, 0x33d9,
+ 0x9a55, 0x16e8,
+ 0x9a56, 0x344f,
+ 0x9a57, 0x1715,
+ 0x9a58, 0x3903,
+ 0x9a59, 0x3450,
+ 0x9a5a, 0x1713,
+ 0x9a5c, 0x3c18,
+ 0x9a5e, 0x34ae,
+ 0x9a5f, 0x1737,
+ 0x9a60, 0x3510,
+ 0x9a62, 0x1757,
+ 0x9a63, 0x3b67,
+ 0x9a64, 0x352c,
+ 0x9a65, 0x1758,
+ 0x9a66, 0x352d,
+ 0x9a68, 0x353c,
+ 0x9a69, 0x353b,
+ 0x9a6a, 0x1767,
+ 0x9a6b, 0x3544,
+ 0x9a6c, 0x4585,
+ 0x9a8f, 0x4586,
+ 0x9aa8, 0x09f6,
+ 0x9aab, 0x260c,
+ 0x9aad, 0x260b,
+ 0x9aaf, 0x10f7,
+ 0x9ab1, 0x2871,
+ 0x9ab2, 0x4332,
+ 0x9ab3, 0x2ade,
+ 0x9ab4, 0x2d0f,
+ 0x9ab6, 0x43f0,
+ 0x9ab7, 0x127a,
+ 0x9ab8, 0x13a4,
+ 0x9ab9, 0x2d0d,
+ 0x9aba, 0x3f74,
+ 0x9abb, 0x2d10,
+ 0x9abc, 0x13a5,
+ 0x9abd, 0x3d97,
+ 0x9abe, 0x2edd,
+ 0x9abf, 0x2d0e,
+ 0x9ac0, 0x3048,
+ 0x9ac1, 0x1564,
+ 0x9ac2, 0x318b,
+ 0x9ac6, 0x328d,
+ 0x9ac7, 0x328b,
+ 0x9aca, 0x328c,
+ 0x9acd, 0x3343,
+ 0x9acf, 0x16ac,
+ 0x9ad0, 0x33e2,
+ 0x9ad1, 0x1718,
+ 0x9ad2, 0x16ea,
+ 0x9ad3, 0x1716,
+ 0x9ad5, 0x34af,
+ 0x9ad6, 0x174f,
+ 0x9ad7, 0x3faa,
+ 0x9ad8, 0x09f7,
+ 0x9adc, 0x3049,
+ 0x9adf, 0x1e33,
+ 0x9ae0, 0x3908,
+ 0x9ae1, 0x0f78,
+ 0x9ae2, 0x3909,
+ 0x9ae3, 0x2872,
+ 0x9ae6, 0x10f9,
+ 0x9ae7, 0x2873,
+ 0x9aeb, 0x2ae0,
+ 0x9aec, 0x2adf,
+ 0x9aed, 0x13a7,
+ 0x9aee, 0x127b,
+ 0x9af1, 0x2ae3,
+ 0x9af2, 0x2ae2,
+ 0x9af3, 0x2ae1,
+ 0x9af4, 0x390b,
+ 0x9af6, 0x2d11,
+ 0x9af7, 0x2d14,
+ 0x9af9, 0x2d13,
+ 0x9afa, 0x2d12,
+ 0x9afb, 0x13a6,
+ 0x9afc, 0x2ee1,
+ 0x9afd, 0x2edf,
+ 0x9afe, 0x2ede,
+ 0x9aff, 0x3f17,
+ 0x9b01, 0x2ee0,
+ 0x9b02, 0x3f12,
+ 0x9b03, 0x1565,
+ 0x9b04, 0x304b,
+ 0x9b06, 0x1566,
+ 0x9b08, 0x304a,
+ 0x9b09, 0x3f20,
+ 0x9b0a, 0x318d,
+ 0x9b0b, 0x318c,
+ 0x9b0c, 0x318f,
+ 0x9b0d, 0x15fb,
+ 0x9b0e, 0x318e,
+ 0x9b0f, 0x47c4,
+ 0x9b10, 0x328e,
+ 0x9b11, 0x3290,
+ 0x9b12, 0x328f,
+ 0x9b14, 0x390d,
+ 0x9b15, 0x3344,
+ 0x9b16, 0x3347,
+ 0x9b17, 0x3345,
+ 0x9b19, 0x33e3,
+ 0x9b1a, 0x16eb,
+ 0x9b1e, 0x3451,
+ 0x9b22, 0x1738,
+ 0x9b23, 0x1750,
+ 0x9b24, 0x352f,
+ 0x9b25, 0x09f8,
+ 0x9b27, 0x127d,
+ 0x9b28, 0x13a8,
+ 0x9b29, 0x304d,
+ 0x9b2a, 0x3f19,
+ 0x9b2b, 0x33e4,
+ 0x9b2d, 0x390e,
+ 0x9b2e, 0x3511,
+ 0x9b2f, 0x1e34,
+ 0x9b31, 0x1768,
+ 0x9b32, 0x09f9,
+ 0x9b33, 0x2d15,
+ 0x9b34, 0x3911,
+ 0x9b35, 0x304e,
+ 0x9b37, 0x3190,
+ 0x9b39, 0x3f00,
+ 0x9b3a, 0x3348,
+ 0x9b3b, 0x33e5,
+ 0x9b3c, 0x09fa,
+ 0x9b3e, 0x2874,
+ 0x9b40, 0x3915,
+ 0x9b41, 0x10fa,
+ 0x9b43, 0x2ae5,
+ 0x9b44, 0x127f,
+ 0x9b45, 0x127e,
+ 0x9b46, 0x2ae4,
+ 0x9b48, 0x2ee2,
+ 0x9b4a, 0x304f,
+ 0x9b4b, 0x3051,
+ 0x9b4c, 0x3050,
+ 0x9b4d, 0x1569,
+ 0x9b4e, 0x1568,
+ 0x9b4f, 0x1567,
+ 0x9b50, 0x3914,
+ 0x9b51, 0x16ae,
+ 0x9b52, 0x3349,
+ 0x9b54, 0x16ad,
+ 0x9b55, 0x33e7,
+ 0x9b56, 0x33e6,
+ 0x9b58, 0x1739,
+ 0x9b59, 0x34b0,
+ 0x9b5a, 0x0be1,
+ 0x9b5b, 0x260d,
+ 0x9b5f, 0x2878,
+ 0x9b60, 0x2876,
+ 0x9b64, 0x2aee,
+ 0x9b66, 0x2ae9,
+ 0x9b67, 0x2ae6,
+ 0x9b68, 0x2aed,
+ 0x9b69, 0x47c5,
+ 0x9b6c, 0x2aef,
+ 0x9b6f, 0x1281,
+ 0x9b70, 0x2aec,
+ 0x9b71, 0x2ae8,
+ 0x9b74, 0x2ae7,
+ 0x9b75, 0x2aeb,
+ 0x9b76, 0x2aea,
+ 0x9b77, 0x1280,
+ 0x9b7a, 0x2d20,
+ 0x9b7b, 0x2d1b,
+ 0x9b7c, 0x2d19,
+ 0x9b7d, 0x2d22,
+ 0x9b7e, 0x2d1a,
+ 0x9b7f, 0x3c3b,
+ 0x9b80, 0x2d16,
+ 0x9b81, 0x43f1,
+ 0x9b82, 0x2d1c,
+ 0x9b83, 0x4219,
+ 0x9b85, 0x2d17,
+ 0x9b86, 0x2eeb,
+ 0x9b87, 0x2d18,
+ 0x9b88, 0x2d23,
+ 0x9b8b, 0x3eee,
+ 0x9b8d, 0x4623,
+ 0x9b8e, 0x3919,
+ 0x9b8f, 0x3fad,
+ 0x9b90, 0x2d1f,
+ 0x9b91, 0x13a9,
+ 0x9b92, 0x2d1e,
+ 0x9b93, 0x2d1d,
+ 0x9b95, 0x2d21,
+ 0x9b97, 0x3f71,
+ 0x9b9a, 0x2ee3,
+ 0x9b9b, 0x2ee6,
+ 0x9b9d, 0x3f56,
+ 0x9b9e, 0x2ee5,
+ 0x9b9f, 0x3c3e,
+ 0x9ba0, 0x2eed,
+ 0x9ba1, 0x2ee8,
+ 0x9ba2, 0x2eec,
+ 0x9ba4, 0x2eea,
+ 0x9ba5, 0x2ee9,
+ 0x9ba6, 0x2ee7,
+ 0x9ba8, 0x2ee4,
+ 0x9baa, 0x14bd,
+ 0x9bab, 0x14bc,
+ 0x9bad, 0x14be,
+ 0x9bae, 0x14bb,
+ 0x9baf, 0x2eee,
+ 0x9bb0, 0x3fb4,
+ 0x9bb5, 0x3057,
+ 0x9bb6, 0x305a,
+ 0x9bb8, 0x3058,
+ 0x9bb9, 0x305c,
+ 0x9bbd, 0x305d,
+ 0x9bbf, 0x3055,
+ 0x9bc0, 0x156e,
+ 0x9bc1, 0x3056,
+ 0x9bc3, 0x3054,
+ 0x9bc4, 0x305b,
+ 0x9bc6, 0x3053,
+ 0x9bc7, 0x3052,
+ 0x9bc8, 0x156d,
+ 0x9bc9, 0x156b,
+ 0x9bca, 0x156a,
+ 0x9bcf, 0x3c3c,
+ 0x9bd3, 0x3059,
+ 0x9bd4, 0x3199,
+ 0x9bd5, 0x319f,
+ 0x9bd6, 0x15fe,
+ 0x9bd7, 0x319a,
+ 0x9bd9, 0x319d,
+ 0x9bda, 0x31a1,
+ 0x9bdb, 0x15ff,
+ 0x9bdc, 0x319c,
+ 0x9bdd, 0x47c6,
+ 0x9bde, 0x3194,
+ 0x9be0, 0x3193,
+ 0x9be1, 0x31a0,
+ 0x9be2, 0x3197,
+ 0x9be4, 0x3195,
+ 0x9be5, 0x319e,
+ 0x9be6, 0x3196,
+ 0x9be7, 0x15fd,
+ 0x9be8, 0x15fc,
+ 0x9be9, 0x3bc1,
+ 0x9bea, 0x3191,
+ 0x9bec, 0x319b,
+ 0x9bed, 0x3ed7,
+ 0x9bf0, 0x3198,
+ 0x9bf1, 0x47c7,
+ 0x9bf4, 0x47c8,
+ 0x9bf7, 0x3293,
+ 0x9bf8, 0x3296,
+ 0x9bfd, 0x156c,
+ 0x9bff, 0x391b,
+ 0x9c02, 0x391a,
+ 0x9c05, 0x3294,
+ 0x9c06, 0x329a,
+ 0x9c07, 0x3298,
+ 0x9c08, 0x3292,
+ 0x9c09, 0x329d,
+ 0x9c0a, 0x3f3a,
+ 0x9c0b, 0x3291,
+ 0x9c0c, 0x391c,
+ 0x9c0d, 0x1660,
+ 0x9c0e, 0x3299,
+ 0x9c10, 0x3c3a,
+ 0x9c12, 0x3295,
+ 0x9c13, 0x165f,
+ 0x9c14, 0x329c,
+ 0x9c15, 0x3f1e,
+ 0x9c17, 0x329b,
+ 0x9c1b, 0x491b,
+ 0x9c1c, 0x334c,
+ 0x9c1d, 0x334b,
+ 0x9c1f, 0x4622,
+ 0x9c20, 0x47ca,
+ 0x9c21, 0x3352,
+ 0x9c23, 0x334e,
+ 0x9c24, 0x3351,
+ 0x9c25, 0x16b0,
+ 0x9c26, 0x45e6,
+ 0x9c28, 0x334f,
+ 0x9c2b, 0x334a,
+ 0x9c2c, 0x334d,
+ 0x9c2d, 0x16af,
+ 0x9c2e, 0x3f22,
+ 0x9c2f, 0x3d87,
+ 0x9c31, 0x16ed,
+ 0x9c32, 0x33f2,
+ 0x9c33, 0x33ed,
+ 0x9c34, 0x33f1,
+ 0x9c35, 0x3c39,
+ 0x9c36, 0x33f4,
+ 0x9c37, 0x33f0,
+ 0x9c39, 0x33ec,
+ 0x9c3a, 0x3d7e,
+ 0x9c3b, 0x16ef,
+ 0x9c3c, 0x33ef,
+ 0x9c3d, 0x33f3,
+ 0x9c3e, 0x16ee,
+ 0x9c3f, 0x33ea,
+ 0x9c40, 0x3297,
+ 0x9c41, 0x33ee,
+ 0x9c44, 0x33eb,
+ 0x9c45, 0x3e71,
+ 0x9c46, 0x33e8,
+ 0x9c48, 0x33e9,
+ 0x9c49, 0x16ec,
+ 0x9c4a, 0x3457,
+ 0x9c4b, 0x3459,
+ 0x9c4c, 0x345c,
+ 0x9c4d, 0x3458,
+ 0x9c4e, 0x345d,
+ 0x9c4f, 0x3c36,
+ 0x9c50, 0x3456,
+ 0x9c52, 0x3454,
+ 0x9c53, 0x3c37,
+ 0x9c54, 0x1719,
+ 0x9c55, 0x345a,
+ 0x9c56, 0x171b,
+ 0x9c57, 0x171a,
+ 0x9c58, 0x3455,
+ 0x9c59, 0x345b,
+ 0x9c5d, 0x3ebf,
+ 0x9c5e, 0x34b5,
+ 0x9c5f, 0x173a,
+ 0x9c60, 0x34b6,
+ 0x9c62, 0x34b4,
+ 0x9c63, 0x34b1,
+ 0x9c66, 0x34b3,
+ 0x9c67, 0x34b2,
+ 0x9c68, 0x34f4,
+ 0x9c6d, 0x34f6,
+ 0x9c6e, 0x34f5,
+ 0x9c71, 0x3514,
+ 0x9c72, 0x3ea1,
+ 0x9c73, 0x3513,
+ 0x9c74, 0x3512,
+ 0x9c75, 0x3515,
+ 0x9c77, 0x1760,
+ 0x9c79, 0x3541,
+ 0x9c7a, 0x3545,
+ 0x9c7b, 0x3c38,
+ 0x9c7c, 0x4512,
+ 0x9ce5, 0x0be2,
+ 0x9ce6, 0x235f,
+ 0x9ce7, 0x2610,
+ 0x9ce9, 0x0f79,
+ 0x9cea, 0x260e,
+ 0x9ced, 0x260f,
+ 0x9cf1, 0x2879,
+ 0x9cf3, 0x10fe,
+ 0x9cf4, 0x10fc,
+ 0x9cf5, 0x287b,
+ 0x9cf6, 0x10fd,
+ 0x9cf7, 0x2af4,
+ 0x9cf9, 0x2af7,
+ 0x9cfa, 0x2af1,
+ 0x9cfb, 0x2af8,
+ 0x9cfc, 0x2af0,
+ 0x9cfd, 0x2af2,
+ 0x9cff, 0x2af3,
+ 0x9d00, 0x2af6,
+ 0x9d02, 0x3f3b,
+ 0x9d03, 0x1284,
+ 0x9d04, 0x2afb,
+ 0x9d05, 0x2afa,
+ 0x9d06, 0x1282,
+ 0x9d07, 0x2af5,
+ 0x9d08, 0x2af9,
+ 0x9d09, 0x1283,
+ 0x9d0c, 0x3c46,
+ 0x9d10, 0x2d2d,
+ 0x9d12, 0x13ae,
+ 0x9d14, 0x2d28,
+ 0x9d15, 0x13aa,
+ 0x9d16, 0x3c7c,
+ 0x9d17, 0x2d25,
+ 0x9d18, 0x2d2b,
+ 0x9d19, 0x2d2e,
+ 0x9d1b, 0x13af,
+ 0x9d1d, 0x2d2a,
+ 0x9d1e, 0x2d27,
+ 0x9d1f, 0x2d2f,
+ 0x9d20, 0x2d26,
+ 0x9d21, 0x3c41,
+ 0x9d22, 0x2d2c,
+ 0x9d23, 0x13ab,
+ 0x9d25, 0x2d24,
+ 0x9d26, 0x13ac,
+ 0x9d28, 0x13ad,
+ 0x9d29, 0x2d29,
+ 0x9d2d, 0x2f00,
+ 0x9d2e, 0x2ef3,
+ 0x9d30, 0x2ef7,
+ 0x9d31, 0x2ef5,
+ 0x9d33, 0x2eef,
+ 0x9d34, 0x404a,
+ 0x9d36, 0x2ef2,
+ 0x9d37, 0x2efc,
+ 0x9d38, 0x2ef6,
+ 0x9d39, 0x392e,
+ 0x9d3b, 0x14bf,
+ 0x9d3d, 0x2efe,
+ 0x9d3e, 0x2efb,
+ 0x9d3f, 0x14c0,
+ 0x9d40, 0x2efd,
+ 0x9d41, 0x2ef0,
+ 0x9d42, 0x2ef9,
+ 0x9d44, 0x3fab,
+ 0x9d45, 0x2ef8,
+ 0x9d49, 0x47cd,
+ 0x9d4a, 0x3061,
+ 0x9d4b, 0x3063,
+ 0x9d4c, 0x3066,
+ 0x9d4e, 0x4539,
+ 0x9d4f, 0x3060,
+ 0x9d50, 0x3eca,
+ 0x9d51, 0x156f,
+ 0x9d52, 0x3068,
+ 0x9d53, 0x305f,
+ 0x9d54, 0x3069,
+ 0x9d56, 0x3065,
+ 0x9d57, 0x3067,
+ 0x9d58, 0x306b,
+ 0x9d59, 0x3064,
+ 0x9d5a, 0x306c,
+ 0x9d5b, 0x3062,
+ 0x9d5c, 0x305e,
+ 0x9d5d, 0x1570,
+ 0x9d5e, 0x3e6e,
+ 0x9d5f, 0x306a,
+ 0x9d60, 0x1571,
+ 0x9d61, 0x1601,
+ 0x9d67, 0x2ef1,
+ 0x9d68, 0x31bb,
+ 0x9d69, 0x31b2,
+ 0x9d6a, 0x1603,
+ 0x9d6b, 0x31ae,
+ 0x9d6c, 0x1604,
+ 0x9d6d, 0x3bac,
+ 0x9d6e, 0x433b,
+ 0x9d6f, 0x31b7,
+ 0x9d70, 0x31b1,
+ 0x9d71, 0x31a7,
+ 0x9d72, 0x1602,
+ 0x9d73, 0x31b4,
+ 0x9d74, 0x31af,
+ 0x9d77, 0x31a2,
+ 0x9d78, 0x31a9,
+ 0x9d79, 0x31b8,
+ 0x9d7b, 0x31b5,
+ 0x9d7c, 0x3efe,
+ 0x9d7d, 0x31ad,
+ 0x9d7e, 0x3925,
+ 0x9d7f, 0x31b9,
+ 0x9d80, 0x31a8,
+ 0x9d81, 0x31a3,
+ 0x9d82, 0x31b6,
+ 0x9d83, 0x3926,
+ 0x9d84, 0x31a5,
+ 0x9d85, 0x31b3,
+ 0x9d86, 0x31aa,
+ 0x9d87, 0x31ba,
+ 0x9d88, 0x31a6,
+ 0x9d89, 0x1600,
+ 0x9d8a, 0x31a4,
+ 0x9d8b, 0x31ab,
+ 0x9d90, 0x32a4,
+ 0x9d92, 0x32a2,
+ 0x9d93, 0x43f3,
+ 0x9d94, 0x32a7,
+ 0x9d96, 0x32b3,
+ 0x9d97, 0x32aa,
+ 0x9d98, 0x32a3,
+ 0x9d99, 0x329f,
+ 0x9d9a, 0x32ac,
+ 0x9d9b, 0x32a5,
+ 0x9d9c, 0x32a8,
+ 0x9d9d, 0x32a1,
+ 0x9d9e, 0x32af,
+ 0x9d9f, 0x329e,
+ 0x9da0, 0x32a6,
+ 0x9da1, 0x32ab,
+ 0x9da2, 0x32ad,
+ 0x9da3, 0x32b0,
+ 0x9da4, 0x32a0,
+ 0x9da5, 0x3c4b,
+ 0x9da6, 0x32b4,
+ 0x9da8, 0x32ae,
+ 0x9da9, 0x32b2,
+ 0x9daa, 0x32a9,
+ 0x9dab, 0x3f30,
+ 0x9dac, 0x3362,
+ 0x9dad, 0x3365,
+ 0x9daf, 0x16b1,
+ 0x9db1, 0x3364,
+ 0x9db2, 0x3369,
+ 0x9db3, 0x3367,
+ 0x9db4, 0x16b2,
+ 0x9db5, 0x335e,
+ 0x9db6, 0x3354,
+ 0x9db7, 0x3353,
+ 0x9db8, 0x16b4,
+ 0x9db9, 0x3360,
+ 0x9dbb, 0x335d,
+ 0x9dbc, 0x3355,
+ 0x9dbd, 0x47d0,
+ 0x9dbe, 0x335a,
+ 0x9dbf, 0x32b1,
+ 0x9dc0, 0x43f2,
+ 0x9dc1, 0x3356,
+ 0x9dc2, 0x16b3,
+ 0x9dc3, 0x335c,
+ 0x9dc4, 0x3929,
+ 0x9dc5, 0x335b,
+ 0x9dc7, 0x3357,
+ 0x9dc8, 0x3363,
+ 0x9dc9, 0x4579,
+ 0x9dca, 0x3358,
+ 0x9dcb, 0x33f9,
+ 0x9dcc, 0x3366,
+ 0x9dcd, 0x3368,
+ 0x9dce, 0x335f,
+ 0x9dcf, 0x3359,
+ 0x9dd0, 0x33fa,
+ 0x9dd1, 0x33fc,
+ 0x9dd2, 0x33f6,
+ 0x9dd3, 0x16f0,
+ 0x9dd4, 0x391e,
+ 0x9dd5, 0x3403,
+ 0x9dd6, 0x3401,
+ 0x9dd7, 0x16f1,
+ 0x9dd8, 0x3400,
+ 0x9dd9, 0x33ff,
+ 0x9dda, 0x33f8,
+ 0x9ddb, 0x33f5,
+ 0x9ddc, 0x33fb,
+ 0x9ddd, 0x3404,
+ 0x9dde, 0x33f7,
+ 0x9ddf, 0x33fd,
+ 0x9de1, 0x3466,
+ 0x9de2, 0x346b,
+ 0x9de3, 0x3461,
+ 0x9de4, 0x3464,
+ 0x9de5, 0x171c,
+ 0x9de6, 0x3468,
+ 0x9de8, 0x346f,
+ 0x9de9, 0x33fe,
+ 0x9deb, 0x3462,
+ 0x9dec, 0x346c,
+ 0x9ded, 0x3470,
+ 0x9dee, 0x3467,
+ 0x9def, 0x3460,
+ 0x9df0, 0x346a,
+ 0x9df2, 0x3469,
+ 0x9df3, 0x346e,
+ 0x9df4, 0x346d,
+ 0x9df5, 0x3402,
+ 0x9df6, 0x3465,
+ 0x9df7, 0x345f,
+ 0x9df8, 0x3463,
+ 0x9df9, 0x173b,
+ 0x9dfb, 0x345e,
+ 0x9dfc, 0x47d1,
+ 0x9dfd, 0x34c1,
+ 0x9dfe, 0x34b8,
+ 0x9dff, 0x34c0,
+ 0x9e00, 0x34bd,
+ 0x9e02, 0x34b7,
+ 0x9e03, 0x34ba,
+ 0x9e04, 0x34c2,
+ 0x9e05, 0x34bc,
+ 0x9e06, 0x34bb,
+ 0x9e07, 0x34b9,
+ 0x9e09, 0x34bf,
+ 0x9e0a, 0x457e,
+ 0x9e0b, 0x34f7,
+ 0x9e0c, 0x457a,
+ 0x9e0d, 0x34f8,
+ 0x9e0e, 0x3928,
+ 0x9e0f, 0x34fa,
+ 0x9e10, 0x34f9,
+ 0x9e11, 0x34fc,
+ 0x9e12, 0x34fb,
+ 0x9e13, 0x3517,
+ 0x9e14, 0x3516,
+ 0x9e15, 0x3530,
+ 0x9e17, 0x3531,
+ 0x9e18, 0x3c44,
+ 0x9e19, 0x353d,
+ 0x9e1a, 0x1765,
+ 0x9e1b, 0x1769,
+ 0x9e1c, 0x3f84,
+ 0x9e1d, 0x3546,
+ 0x9e1e, 0x176a,
+ 0x9e1f, 0x4513,
+ 0x9e75, 0x0be3,
+ 0x9e79, 0x1661,
+ 0x9e7a, 0x336a,
+ 0x9e7b, 0x43f8,
+ 0x9e7c, 0x173d,
+ 0x9e7f, 0x0be4,
+ 0x9e80, 0x2611,
+ 0x9e81, 0x3f0f,
+ 0x9e82, 0x0f7a,
+ 0x9e83, 0x2afc,
+ 0x9e84, 0x3f76,
+ 0x9e85, 0x3ef2,
+ 0x9e86, 0x2d31,
+ 0x9e88, 0x2d30,
+ 0x9e89, 0x2f02,
+ 0x9e8a, 0x2f01,
+ 0x9e8b, 0x14c1,
+ 0x9e8c, 0x306e,
+ 0x9e8d, 0x2f03,
+ 0x9e8e, 0x306d,
+ 0x9e90, 0x3931,
+ 0x9e91, 0x31bd,
+ 0x9e92, 0x1605,
+ 0x9e93, 0x1607,
+ 0x9e94, 0x31bc,
+ 0x9e95, 0x3932,
+ 0x9e96, 0x3fbc,
+ 0x9e97, 0x1606,
+ 0x9e98, 0x3f27,
+ 0x9e99, 0x32b6,
+ 0x9e9a, 0x32b8,
+ 0x9e9b, 0x32b7,
+ 0x9e9c, 0x336b,
+ 0x9e9d, 0x16b5,
+ 0x9e9e, 0x3933,
+ 0x9e9f, 0x171d,
+ 0x9ea0, 0x34c3,
+ 0x9ea1, 0x34fd,
+ 0x9ea2, 0x3934,
+ 0x9ea4, 0x354a,
+ 0x9ea5, 0x0be5,
+ 0x9ea6, 0x4944,
+ 0x9ea7, 0x287c,
+ 0x9ea8, 0x3f75,
+ 0x9ea9, 0x1285,
+ 0x9eaa, 0x3936,
+ 0x9eab, 0x3e92,
+ 0x9eac, 0x43f4,
+ 0x9ead, 0x2d34,
+ 0x9eae, 0x2d33,
+ 0x9eaf, 0x3937,
+ 0x9eb0, 0x2f04,
+ 0x9eb1, 0x47d4,
+ 0x9eb4, 0x1608,
+ 0x9eb5, 0x1662,
+ 0x9eb6, 0x3405,
+ 0x9eb7, 0x3542,
+ 0x9ebb, 0x0be6,
+ 0x9ebc, 0x10ff,
+ 0x9ebd, 0x47d5,
+ 0x9ebe, 0x1286,
+ 0x9ebf, 0x3d78,
+ 0x9ec0, 0x31be,
+ 0x9ec1, 0x3939,
+ 0x9ec2, 0x3471,
+ 0x9ec3, 0x0dbb,
+ 0x9ec4, 0x4514,
+ 0x9ec6, 0x47d6,
+ 0x9ec7, 0x4577,
+ 0x9ec8, 0x2f05,
+ 0x9ecc, 0x1751,
+ 0x9ecd, 0x0dbc,
+ 0x9ece, 0x1287,
+ 0x9ecf, 0x14c2,
+ 0x9ed0, 0x3472,
+ 0x9ed1, 0x0dbd,
+ 0x9ed3, 0x2afd,
+ 0x9ed4, 0x13b1,
+ 0x9ed5, 0x2d35,
+ 0x9ed8, 0x13b0,
+ 0x9eda, 0x2f06,
+ 0x9edb, 0x14c6,
+ 0x9edc, 0x14c4,
+ 0x9ede, 0x14c3,
+ 0x9edf, 0x306f,
+ 0x9ee0, 0x1572,
+ 0x9ee2, 0x47d8,
+ 0x9ee4, 0x32ba,
+ 0x9ee5, 0x32b9,
+ 0x9ee6, 0x32bc,
+ 0x9ee7, 0x32bb,
+ 0x9ee8, 0x1663,
+ 0x9eeb, 0x336c,
+ 0x9eed, 0x336e,
+ 0x9eee, 0x336d,
+ 0x9eef, 0x16b6,
+ 0x9ef0, 0x3406,
+ 0x9ef1, 0x47d9,
+ 0x9ef2, 0x3473,
+ 0x9ef4, 0x171e,
+ 0x9ef5, 0x34fe,
+ 0x9ef6, 0x3518,
+ 0x9ef7, 0x1762,
+ 0x9ef8, 0x47da,
+ 0x9ef9, 0x2360,
+ 0x9efa, 0x2d37,
+ 0x9efb, 0x2f07,
+ 0x9efc, 0x31bf,
+ 0x9efd, 0x2612,
+ 0x9efe, 0x47ce,
+ 0x9eff, 0x2f08,
+ 0x9f00, 0x3071,
+ 0x9f01, 0x3070,
+ 0x9f02, 0x3940,
+ 0x9f06, 0x3475,
+ 0x9f07, 0x173f,
+ 0x9f08, 0x3941,
+ 0x9f09, 0x34ff,
+ 0x9f0a, 0x3519,
+ 0x9f0e, 0x0f7b,
+ 0x9f0f, 0x2afe,
+ 0x9f12, 0x2d38,
+ 0x9f13, 0x0f7c,
+ 0x9f15, 0x1573,
+ 0x9f16, 0x3072,
+ 0x9f17, 0x3945,
+ 0x9f18, 0x3370,
+ 0x9f19, 0x16b7,
+ 0x9f1a, 0x3371,
+ 0x9f1b, 0x336f,
+ 0x9f1c, 0x3476,
+ 0x9f1e, 0x34c4,
+ 0x9f20, 0x0f7d,
+ 0x9f22, 0x2f0b,
+ 0x9f23, 0x2f0a,
+ 0x9f24, 0x2f09,
+ 0x9f25, 0x3073,
+ 0x9f26, 0x3f90,
+ 0x9f27, 0x4620,
+ 0x9f28, 0x3077,
+ 0x9f29, 0x3076,
+ 0x9f2a, 0x3075,
+ 0x9f2b, 0x3074,
+ 0x9f2c, 0x1574,
+ 0x9f2d, 0x31c0,
+ 0x9f2e, 0x32be,
+ 0x9f2f, 0x1664,
+ 0x9f30, 0x32bd,
+ 0x9f31, 0x3372,
+ 0x9f32, 0x3409,
+ 0x9f33, 0x3408,
+ 0x9f34, 0x16f2,
+ 0x9f35, 0x3407,
+ 0x9f36, 0x3479,
+ 0x9f37, 0x3478,
+ 0x9f38, 0x3477,
+ 0x9f39, 0x3947,
+ 0x9f3b, 0x1100,
+ 0x9f3d, 0x2d39,
+ 0x9f3e, 0x14c7,
+ 0x9f40, 0x31c1,
+ 0x9f42, 0x340a,
+ 0x9f43, 0x347a,
+ 0x9f44, 0x47db,
+ 0x9f45, 0x394a,
+ 0x9f46, 0x34c5,
+ 0x9f47, 0x3500,
+ 0x9f48, 0x3532,
+ 0x9f49, 0x354c,
+ 0x9f4a, 0x1101,
+ 0x9f4b, 0x14c8,
+ 0x9f4c, 0x3078,
+ 0x9f4d, 0x31c3,
+ 0x9f4e, 0x3373,
+ 0x9f4f, 0x347b,
+ 0x9f50, 0x4943,
+ 0x9f52, 0x1289,
+ 0x9f53, 0x3f80,
+ 0x9f54, 0x2f0c,
+ 0x9f55, 0x3079,
+ 0x9f56, 0x31c4,
+ 0x9f59, 0x32c3,
+ 0x9f5a, 0x3f23,
+ 0x9f5b, 0x32bf,
+ 0x9f5c, 0x16b8,
+ 0x9f5d, 0x32c2,
+ 0x9f5e, 0x32c1,
+ 0x9f5f, 0x1665,
+ 0x9f60, 0x32c0,
+ 0x9f61, 0x1667,
+ 0x9f62, 0x394f,
+ 0x9f63, 0x1666,
+ 0x9f64, 0x3375,
+ 0x9f65, 0x3374,
+ 0x9f66, 0x16b9,
+ 0x9f69, 0x3950,
+ 0x9f6a, 0x16f4,
+ 0x9f6b, 0x340b,
+ 0x9f6c, 0x16f3,
+ 0x9f6e, 0x347e,
+ 0x9f70, 0x347d,
+ 0x9f71, 0x347c,
+ 0x9f72, 0x1741,
+ 0x9f74, 0x34c6,
+ 0x9f77, 0x1740,
+ 0x9f78, 0x3501,
+ 0x9f79, 0x3504,
+ 0x9f7a, 0x3503,
+ 0x9f7b, 0x3502,
+ 0x9f7e, 0x354b,
+ 0x9f7f, 0x4680,
+ 0x9f8d, 0x13b2,
+ 0x9f8e, 0x3952,
+ 0x9f90, 0x157c,
+ 0x9f91, 0x32c4,
+ 0x9f92, 0x3376,
+ 0x9f94, 0x16f5,
+ 0x9f95, 0x340c,
+ 0x9f98, 0x354d,
+ 0x9f99, 0x4587,
+ 0x9f9c, 0x13b3,
+ 0x9f9f, 0x4646,
+ 0x9fa0, 0x2f0d,
+ 0x9fa2, 0x340d,
+ 0x9fa4, 0x351a,
+ 0x9fa5, 0x3f70,
+ 0xfa0c, 0x0274,
+ 0xfa0d, 0x2381,
+ 0xfe30, 0x006d,
+ 0xfe31, 0x007a,
+ 0xfe33, 0x35af,
+ 0xfe34, 0x35b1,
+ 0xfe35, 0x0082,
+ 0xfe37, 0x0086,
+ 0xfe39, 0x008a,
+ 0xfe3b, 0x008e,
+ 0xfe3d, 0x0092,
+ 0xfe3f, 0x0096,
+ 0xfe41, 0x009a,
+ 0xfe43, 0x009e,
+ 0xfe49, 0x00c7,
+ 0xfe4b, 0x00cb,
+ 0xfe4d, 0x00c9,
+ 0xfe4f, 0x35b2,
+ 0xfe50, 0x0070,
+ 0xfe52, 0x0072,
+ 0xfe54, 0x0074,
+ 0xfe59, 0x00a0,
+ 0xfe5f, 0x00cd,
+ 0xfe62, 0x00df,
+ 0xfe69, 0x010c,
+ 0xff01, 0x006c,
+ 0xff02, 0x36e4,
+ 0xff03, 0x00ae,
+ 0xff04, 0x0103,
+ 0xff05, 0x0108,
+ 0xff06, 0x00af,
+ 0xff07, 0x36e3,
+ 0xff08, 0x0080,
+ 0xff0a, 0x00b0,
+ 0xff0b, 0x00d0,
+ 0xff0c, 0x0064,
+ 0xff0d, 0x00d1,
+ 0xff0e, 0x0067,
+ 0xff0f, 0x0101,
+ 0xff10, 0x014d,
+ 0xff1a, 0x006a,
+ 0xff1b, 0x0069,
+ 0xff1c, 0x00d6,
+ 0xff1d, 0x00d8,
+ 0xff1e, 0x00d7,
+ 0xff1f, 0x006b,
+ 0xff20, 0x0109,
+ 0xff21, 0x016d,
+ 0xff3b, 0x35be,
+ 0xff3c, 0x0102,
+ 0xff3d, 0x35bf,
+ 0xff3e, 0x35b4,
+ 0xff3f, 0x00c5,
+ 0xff41, 0x0187,
+ 0xff5b, 0x0084,
+ 0xff5c, 0x0078,
+ 0xff5d, 0x0085,
+ 0xff64, 0x0071,
+ 0xffe2, 0x36e1,
+ 0xffe4, 0x36e2,
+ 0x2013, 0x0078,
+ 0x2014, 0x007a,
+ 0x2025, 0x006d,
+ 0x300a, 0x0092,
+ 0x3008, 0x0096,
+ 0x300c, 0x009a,
+ 0x300e, 0x009e,
+ 0x3010, 0x008e,
+ 0x3014, 0x008a,
+ 0xfe4f, 0x35b1,
+ 0xff08, 0x0082,
+ 0xff5b, 0x0086,
+ 0xff5d, 0x0087,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13UniCNSUCS2VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13UniCNSUCS2VMap2, 15468
+};
+
+static Gushort cns13AdobeCNS13VMap2[152] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0x4400, 0x4400,
+ 0x4500, 0x4500,
+ 0x4600, 0x4600,
+ 0x4700, 0x4700,
+ 0x4800, 0x4800,
+ 0x4900, 0x4900,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 cns13AdobeCNS13VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ cns13AdobeCNS13VMap2, 76
+};
+
+static struct {
+ char *name;
+ GfxFontEncoding16 *enc;
+} gfxCNS13Tab[] = {
+ { "Adobe-CNS1-0", &cns13AdobeCNS10Enc16 },
+ { "Adobe-CNS1-1", &cns13AdobeCNS11Enc16 },
+ { "Adobe-CNS1-2", &cns13AdobeCNS12Enc16 },
+ { "Adobe-CNS1-3", &cns13AdobeCNS13Enc16 },
+ { "B5-H", &cns13B5HEnc16 },
+ { "B5-V", &cns13B5VEnc16 },
+ { "B5pc-H", &cns13B5pcHEnc16 },
+ { "B5pc-V", &cns13B5pcVEnc16 },
+ { "CNS1-H", &cns13CNS1HEnc16 },
+ { "CNS1-V", &cns13CNS1VEnc16 },
+ { "CNS2-H", &cns13CNS2HEnc16 },
+ { "CNS2-V", &cns13CNS2VEnc16 },
+ { "ETHK-B5-H", &cns13ETHKB5HEnc16 },
+ { "ETHK-B5-V", &cns13ETHKB5VEnc16 },
+ { "ETen-B5-H", &cns13ETenB5HEnc16 },
+ { "ETen-B5-V", &cns13ETenB5VEnc16 },
+ { "ETenms-B5-H", &cns13ETenmsB5HEnc16 },
+ { "ETenms-B5-V", &cns13ETenmsB5VEnc16 },
+ { "HKdla-B5-H", &cns13HKdlaB5HEnc16 },
+ { "HKdla-B5-V", &cns13HKdlaB5VEnc16 },
+ { "HKdlb-B5-H", &cns13HKdlbB5HEnc16 },
+ { "HKdlb-B5-V", &cns13HKdlbB5VEnc16 },
+ { "HKgccs-B5-H", &cns13HKgccsB5HEnc16 },
+ { "HKgccs-B5-V", &cns13HKgccsB5VEnc16 },
+ { "HKm314-B5-H", &cns13HKm314B5HEnc16 },
+ { "HKm314-B5-V", &cns13HKm314B5VEnc16 },
+ { "HKm471-B5-H", &cns13HKm471B5HEnc16 },
+ { "HKm471-B5-V", &cns13HKm471B5VEnc16 },
+ { "HKscs-B5-H", &cns13HKscsB5HEnc16 },
+ { "HKscs-B5-V", &cns13HKscsB5VEnc16 },
+ { "UniCNS-UCS2-H", &cns13UniCNSUCS2HEnc16 },
+ { "UniCNS-UCS2-V", &cns13UniCNSUCS2VEnc16 },
+ { "Identity-H", &cns13AdobeCNS13Enc16 },
+ { "Identity-V", &cns13AdobeCNS13VEnc16 },
+ { NULL, NULL }
+};
+
+#endif
diff --git a/pdftops/COPYING b/pdftops/COPYING
new file mode 100644
index 000000000..a43ea2126
--- /dev/null
+++ b/pdftops/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/pdftops/Catalog.cxx b/pdftops/Catalog.cxx
new file mode 100644
index 000000000..507d3faa8
--- /dev/null
+++ b/pdftops/Catalog.cxx
@@ -0,0 +1,360 @@
+//========================================================================
+//
+// Catalog.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include "gmem.h"
+#include "Object.h"
+#include "XRef.h"
+#include "Array.h"
+#include "Dict.h"
+#include "Page.h"
+#include "Error.h"
+#include "Link.h"
+#include "Catalog.h"
+
+//------------------------------------------------------------------------
+// Catalog
+//------------------------------------------------------------------------
+
+Catalog::Catalog(XRef *xrefA) {
+ Object catDict, pagesDict;
+ Object obj, obj2;
+ int numPages0;
+ int i;
+
+ ok = gTrue;
+ xref = xrefA;
+ pages = NULL;
+ pageRefs = NULL;
+ numPages = pagesSize = 0;
+ baseURI = NULL;
+
+ xref->getCatalog(&catDict);
+ if (!catDict.isDict()) {
+ error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
+ goto err1;
+ }
+
+ // read page tree
+ catDict.dictLookup("Pages", &pagesDict);
+ // This should really be isDict("Pages"), but I've seen at least one
+ // PDF file where the /Type entry is missing.
+ if (!pagesDict.isDict()) {
+ error(-1, "Top-level pages object is wrong type (%s)",
+ pagesDict.getTypeName());
+ goto err2;
+ }
+ pagesDict.dictLookup("Count", &obj);
+ // some PDF files actually use real numbers here ("/Count 9.0")
+ if (!obj.isNum()) {
+ error(-1, "Page count in top-level pages object is wrong type (%s)",
+ obj.getTypeName());
+ goto err3;
+ }
+ pagesSize = numPages0 = (int)obj.getNum();
+ obj.free();
+ if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize ||
+ pagesSize*sizeof(Ref)/sizeof(Ref) != pagesSize) {
+ error(-1, "Invalid 'pagesSize'");
+ ok = gFalse;
+ return;
+ }
+ pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
+ pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
+ for (i = 0; i < pagesSize; ++i) {
+ pages[i] = NULL;
+ pageRefs[i].num = -1;
+ pageRefs[i].gen = -1;
+ }
+ numPages = readPageTree(pagesDict.getDict(), NULL, 0);
+ if (numPages != numPages0) {
+ error(-1, "Page count in top-level pages object is incorrect");
+ }
+ pagesDict.free();
+
+ // read named destination dictionary
+ catDict.dictLookup("Dests", &dests);
+
+ // read root of named destination tree
+ if (catDict.dictLookup("Names", &obj)->isDict())
+ obj.dictLookup("Dests", &nameTree);
+ else
+ nameTree.initNull();
+ obj.free();
+
+ // read base URI
+ if (catDict.dictLookup("URI", &obj)->isDict()) {
+ if (obj.dictLookup("Base", &obj2)->isString()) {
+ baseURI = obj2.getString()->copy();
+ }
+ obj2.free();
+ }
+ obj.free();
+
+ // get the metadata stream
+ catDict.dictLookup("Metadata", &metadata);
+
+ // get the structure tree root
+ catDict.dictLookup("StructTreeRoot", &structTreeRoot);
+
+ // get the outline dictionary
+ catDict.dictLookup("Outlines", &outline);
+
+ catDict.free();
+ return;
+
+ err3:
+ obj.free();
+ err2:
+ pagesDict.free();
+ err1:
+ catDict.free();
+ dests.initNull();
+ nameTree.initNull();
+ ok = gFalse;
+}
+
+Catalog::~Catalog() {
+ int i;
+
+ if (pages) {
+ for (i = 0; i < pagesSize; ++i) {
+ if (pages[i]) {
+ delete pages[i];
+ }
+ }
+ gfree(pages);
+ gfree(pageRefs);
+ }
+ dests.free();
+ nameTree.free();
+ if (baseURI) {
+ delete baseURI;
+ }
+ metadata.free();
+ structTreeRoot.free();
+ outline.free();
+}
+
+GString *Catalog::readMetadata() {
+ GString *s;
+ Dict *dict;
+ Object obj;
+ int c;
+
+ if (!metadata.isStream()) {
+ return NULL;
+ }
+ dict = metadata.streamGetDict();
+ if (!dict->lookup("Subtype", &obj)->isName("XML")) {
+ error(-1, "Unknown Metadata type: '%s'",
+ obj.isName() ? obj.getName() : "???");
+ }
+ obj.free();
+ s = new GString();
+ metadata.streamReset();
+ while ((c = metadata.streamGetChar()) != EOF) {
+ s->append(c);
+ }
+ metadata.streamClose();
+ return s;
+}
+
+int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
+ Object kids;
+ Object kid;
+ Object kidRef;
+ PageAttrs *attrs1, *attrs2;
+ Page *page;
+ int i, j;
+
+ attrs1 = new PageAttrs(attrs, pagesDict);
+ pagesDict->lookup("Kids", &kids);
+ if (!kids.isArray()) {
+ error(-1, "Kids object (page %d) is wrong type (%s)",
+ start+1, kids.getTypeName());
+ goto err1;
+ }
+ for (i = 0; i < kids.arrayGetLength(); ++i) {
+ kids.arrayGet(i, &kid);
+ if (kid.isDict("Page")) {
+ attrs2 = new PageAttrs(attrs1, kid.getDict());
+ page = new Page(xref, start+1, kid.getDict(), attrs2);
+ if (!page->isOk()) {
+ ++start;
+ goto err3;
+ }
+ if (start >= pagesSize) {
+ pagesSize += 32;
+ if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize) {
+ error(-1, "Invalid 'pagesSize' parameter.");
+ goto err3;
+ }
+ pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *));
+ pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref));
+ for (j = pagesSize - 32; j < pagesSize; ++j) {
+ pages[j] = NULL;
+ pageRefs[j].num = -1;
+ pageRefs[j].gen = -1;
+ }
+ }
+ pages[start] = page;
+ kids.arrayGetNF(i, &kidRef);
+ if (kidRef.isRef()) {
+ pageRefs[start].num = kidRef.getRefNum();
+ pageRefs[start].gen = kidRef.getRefGen();
+ }
+ kidRef.free();
+ ++start;
+ // This should really be isDict("Pages"), but I've seen at least one
+ // PDF file where the /Type entry is missing.
+ } else if (kid.isDict()) {
+ if ((start = readPageTree(kid.getDict(), attrs1, start))
+ < 0)
+ goto err2;
+ } else {
+ error(-1, "Kid object (page %d) is wrong type (%s)",
+ start+1, kid.getTypeName());
+ goto err2;
+ }
+ kid.free();
+ }
+ delete attrs1;
+ kids.free();
+ return start;
+
+ err3:
+ delete page;
+ err2:
+ kid.free();
+ err1:
+ kids.free();
+ delete attrs1;
+ ok = gFalse;
+ return -1;
+}
+
+int Catalog::findPage(int num, int gen) {
+ int i;
+
+ for (i = 0; i < numPages; ++i) {
+ if (pageRefs[i].num == num && pageRefs[i].gen == gen)
+ return i + 1;
+ }
+ return 0;
+}
+
+LinkDest *Catalog::findDest(GString *name) {
+ LinkDest *dest;
+ Object obj1, obj2;
+ GBool found;
+
+ // try named destination dictionary then name tree
+ found = gFalse;
+ if (dests.isDict()) {
+ if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
+ found = gTrue;
+ else
+ obj1.free();
+ }
+ if (!found && nameTree.isDict()) {
+ if (!findDestInTree(&nameTree, name, &obj1)->isNull())
+ found = gTrue;
+ else
+ obj1.free();
+ }
+ if (!found)
+ return NULL;
+
+ // construct LinkDest
+ dest = NULL;
+ if (obj1.isArray()) {
+ dest = new LinkDest(obj1.getArray());
+ } else if (obj1.isDict()) {
+ if (obj1.dictLookup("D", &obj2)->isArray())
+ dest = new LinkDest(obj2.getArray());
+ else
+ error(-1, "Bad named destination value");
+ obj2.free();
+ } else {
+ error(-1, "Bad named destination value");
+ }
+ obj1.free();
+ if (dest && !dest->isOk()) {
+ delete dest;
+ dest = NULL;
+ }
+
+ return dest;
+}
+
+Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
+ Object names, name1;
+ Object kids, kid, limits, low, high;
+ GBool done, found;
+ int cmp, i;
+
+ // leaf node
+ if (tree->dictLookup("Names", &names)->isArray()) {
+ done = found = gFalse;
+ for (i = 0; !done && i < names.arrayGetLength(); i += 2) {
+ if (names.arrayGet(i, &name1)->isString()) {
+ cmp = name->cmp(name1.getString());
+ if (cmp == 0) {
+ names.arrayGet(i+1, obj);
+ found = gTrue;
+ done = gTrue;
+ } else if (cmp < 0) {
+ done = gTrue;
+ }
+ }
+ name1.free();
+ }
+ names.free();
+ if (!found)
+ obj->initNull();
+ return obj;
+ }
+ names.free();
+
+ // root or intermediate node
+ done = gFalse;
+ if (tree->dictLookup("Kids", &kids)->isArray()) {
+ for (i = 0; !done && i < kids.arrayGetLength(); ++i) {
+ if (kids.arrayGet(i, &kid)->isDict()) {
+ if (kid.dictLookup("Limits", &limits)->isArray()) {
+ if (limits.arrayGet(0, &low)->isString() &&
+ name->cmp(low.getString()) >= 0) {
+ if (limits.arrayGet(1, &high)->isString() &&
+ name->cmp(high.getString()) <= 0) {
+ findDestInTree(&kid, name, obj);
+ done = gTrue;
+ }
+ high.free();
+ }
+ low.free();
+ }
+ limits.free();
+ }
+ kid.free();
+ }
+ }
+ kids.free();
+
+ // name was outside of ranges of all kids
+ if (!done)
+ obj->initNull();
+
+ return obj;
+}
diff --git a/pdftops/Catalog.h b/pdftops/Catalog.h
new file mode 100644
index 000000000..0c86ded48
--- /dev/null
+++ b/pdftops/Catalog.h
@@ -0,0 +1,89 @@
+//========================================================================
+//
+// Catalog.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef CATALOG_H
+#define CATALOG_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+class XRef;
+class Object;
+class Page;
+class PageAttrs;
+struct Ref;
+class LinkDest;
+
+//------------------------------------------------------------------------
+// Catalog
+//------------------------------------------------------------------------
+
+class Catalog {
+public:
+
+ // Constructor.
+ Catalog(XRef *xrefA);
+
+ // Destructor.
+ ~Catalog();
+
+ // Is catalog valid?
+ GBool isOk() { return ok; }
+
+ // Get number of pages.
+ int getNumPages() { return numPages; }
+
+ // Get a page.
+ Page *getPage(int i) { return pages[i-1]; }
+
+ // Get the reference for a page object.
+ Ref *getPageRef(int i) { return &pageRefs[i-1]; }
+
+ // Return base URI, or NULL if none.
+ GString *getBaseURI() { return baseURI; }
+
+ // Return the contents of the metadata stream, or NULL if there is
+ // no metadata.
+ GString *readMetadata();
+
+ // Return the structure tree root object.
+ Object *getStructTreeRoot() { return &structTreeRoot; }
+
+ // Find a page, given its object ID. Returns page number, or 0 if
+ // not found.
+ int findPage(int num, int gen);
+
+ // Find a named destination. Returns the link destination, or
+ // NULL if <name> is not a destination.
+ LinkDest *findDest(GString *name);
+
+ Object *getOutline() { return &outline; }
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ Page **pages; // array of pages
+ Ref *pageRefs; // object ID for each page
+ int numPages; // number of pages
+ int pagesSize; // size of pages array
+ Object dests; // named destination dictionary
+ Object nameTree; // name tree
+ GString *baseURI; // base URI for URI-type links
+ Object metadata; // metadata stream
+ Object structTreeRoot; // structure tree root dictionary
+ Object outline; // outline dictionary
+ GBool ok; // true if catalog is valid
+
+ int readPageTree(Dict *pages, PageAttrs *attrs, int start);
+ Object *findDestInTree(Object *tree, GString *name, Object *obj);
+};
+
+#endif
diff --git a/pdftops/CharCodeToUnicode.cxx b/pdftops/CharCodeToUnicode.cxx
new file mode 100644
index 000000000..67727b2db
--- /dev/null
+++ b/pdftops/CharCodeToUnicode.cxx
@@ -0,0 +1,533 @@
+//========================================================================
+//
+// CharCodeToUnicode.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "gmem.h"
+#include "gfile.h"
+#include "GString.h"
+#include "Error.h"
+#include "GlobalParams.h"
+#include "PSTokenizer.h"
+#include "CharCodeToUnicode.h"
+
+//------------------------------------------------------------------------
+
+#define maxUnicodeString 8
+
+struct CharCodeToUnicodeString {
+ CharCode c;
+ Unicode u[maxUnicodeString];
+ int len;
+};
+
+//------------------------------------------------------------------------
+
+static int getCharFromString(void *data) {
+ char *p;
+ int c;
+
+ p = *(char **)data;
+ if (*p) {
+ c = *p++;
+ *(char **)data = p;
+ } else {
+ c = EOF;
+ }
+ return c;
+}
+
+static int getCharFromFile(void *data) {
+ return fgetc((FILE *)data);
+}
+
+//------------------------------------------------------------------------
+
+CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName,
+ GString *collection) {
+ FILE *f;
+ Unicode *mapA;
+ CharCode size, mapLenA;
+ char buf[64];
+ Unicode u;
+ CharCodeToUnicode *ctu;
+
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ error(-1, "Couldn't open cidToUnicode file '%s'",
+ fileName->getCString());
+ return NULL;
+ }
+
+ size = 32768;
+ mapA = (Unicode *)gmalloc(size * sizeof(Unicode));
+ mapLenA = 0;
+
+ while (getLine(buf, sizeof(buf), f)) {
+ if (mapLenA == size) {
+ size *= 2;
+ mapA = (Unicode *)grealloc(mapA, size * sizeof(Unicode));
+ }
+ if (sscanf(buf, "%x", &u) == 1) {
+ mapA[mapLenA] = u;
+ } else {
+ error(-1, "Bad line (%d) in cidToUnicode file '%s'",
+ (int)(mapLenA + 1), fileName->getCString());
+ mapA[mapLenA] = 0;
+ }
+ ++mapLenA;
+ }
+ fclose(f);
+
+ ctu = new CharCodeToUnicode(collection->copy(), mapA, mapLenA, gTrue,
+ NULL, 0, 0);
+ gfree(mapA);
+ return ctu;
+}
+
+CharCodeToUnicode *CharCodeToUnicode::parseUnicodeToUnicode(
+ GString *fileName) {
+ FILE *f;
+ Unicode *mapA;
+ CharCodeToUnicodeString *sMapA;
+ CharCode size, oldSize, len, sMapSizeA, sMapLenA;
+ char buf[256];
+ char *tok;
+ Unicode u0;
+ Unicode uBuf[maxUnicodeString];
+ CharCodeToUnicode *ctu;
+ int line, n, i;
+
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ error(-1, "Couldn't open unicodeToUnicode file '%s'",
+ fileName->getCString());
+ return NULL;
+ }
+
+ size = 4096;
+ mapA = (Unicode *)gmalloc(size * sizeof(Unicode));
+ memset(mapA, 0, size * sizeof(Unicode));
+ len = 0;
+ sMapA = NULL;
+ sMapSizeA = sMapLenA = 0;
+
+ line = 0;
+ while (getLine(buf, sizeof(buf), f)) {
+ ++line;
+ if (!(tok = strtok(buf, " \t\r\n")) ||
+ sscanf(tok, "%x", &u0) != 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ continue;
+ }
+ n = 0;
+ while (n < maxUnicodeString) {
+ if (!(tok = strtok(NULL, " \t\r\n"))) {
+ break;
+ }
+ if (sscanf(tok, "%x", &uBuf[n]) != 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ break;
+ }
+ ++n;
+ }
+ if (n < 1) {
+ error(-1, "Bad line (%d) in unicodeToUnicode file '%s'",
+ line, fileName->getCString());
+ continue;
+ }
+ if (u0 >= size) {
+ oldSize = size;
+ while (u0 >= size) {
+ size *= 2;
+ }
+ mapA = (Unicode *)grealloc(mapA, size * sizeof(Unicode));
+ memset(mapA + oldSize, 0, (size - oldSize) * sizeof(Unicode));
+ }
+ if (n == 1) {
+ mapA[u0] = uBuf[0];
+ } else {
+ mapA[u0] = 0;
+ if (sMapLenA == sMapSizeA) {
+ sMapSizeA += 16;
+ sMapA = (CharCodeToUnicodeString *)
+ grealloc(sMapA, sMapSizeA * sizeof(CharCodeToUnicodeString));
+ }
+ sMapA[sMapLenA].c = u0;
+ for (i = 0; i < n; ++i) {
+ sMapA[sMapLenA].u[i] = uBuf[i];
+ }
+ sMapA[sMapLenA].len = n;
+ ++sMapLenA;
+ }
+ if (u0 >= len) {
+ len = u0 + 1;
+ }
+ }
+ fclose(f);
+
+ ctu = new CharCodeToUnicode(fileName->copy(), mapA, len, gTrue,
+ sMapA, sMapLenA, sMapSizeA);
+ gfree(mapA);
+ return ctu;
+}
+
+CharCodeToUnicode *CharCodeToUnicode::make8BitToUnicode(Unicode *toUnicode) {
+ return new CharCodeToUnicode(NULL, toUnicode, 256, gTrue, NULL, 0, 0);
+}
+
+CharCodeToUnicode *CharCodeToUnicode::parseCMap(GString *buf, int nBits) {
+ CharCodeToUnicode *ctu;
+ char *p;
+
+ ctu = new CharCodeToUnicode(NULL);
+ p = buf->getCString();
+ ctu->parseCMap1(&getCharFromString, &p, nBits);
+ return ctu;
+}
+
+void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) {
+ char *p;
+
+ p = buf->getCString();
+ parseCMap1(&getCharFromString, &p, nBits);
+}
+
+void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data,
+ int nBits) {
+ PSTokenizer *pst;
+ char tok1[256], tok2[256], tok3[256];
+ int nDigits, n1, n2, n3;
+ CharCode i;
+ CharCode code1, code2;
+ GString *name;
+ FILE *f;
+
+ nDigits = nBits / 4;
+ pst = new PSTokenizer(getCharFunc, data);
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ while (pst->getToken(tok2, sizeof(tok2), &n2)) {
+ if (!strcmp(tok2, "usecmap")) {
+ if (tok1[0] == '/') {
+ name = new GString(tok1 + 1);
+ if ((f = globalParams->findToUnicodeFile(name))) {
+ parseCMap1(&getCharFromFile, f, nBits);
+ fclose(f);
+ } else {
+ error(-1, "Couldn't find ToUnicode CMap file for '%s'",
+ name->getCString());
+ }
+ delete name;
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "beginbfchar")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endbfchar")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endbfchar")) {
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ break;
+ }
+ if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
+ tok2[0] == '<' && tok2[n2 - 1] == '>')) {
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ continue;
+ }
+ tok1[n1 - 1] = tok2[n2 - 1] = '\0';
+ if (sscanf(tok1 + 1, "%x", &code1) != 1) {
+ error(-1, "Illegal entry in bfchar block in ToUnicode CMap");
+ continue;
+ }
+ addMapping(code1, tok2 + 1, n2 - 1, 0);
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else if (!strcmp(tok2, "beginbfrange")) {
+ while (pst->getToken(tok1, sizeof(tok1), &n1)) {
+ if (!strcmp(tok1, "endbfrange")) {
+ break;
+ }
+ if (!pst->getToken(tok2, sizeof(tok2), &n2) ||
+ !strcmp(tok2, "endbfrange") ||
+ !pst->getToken(tok3, sizeof(tok3), &n3) ||
+ !strcmp(tok3, "endbfrange")) {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ break;
+ }
+ if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' &&
+ n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ continue;
+ }
+ tok1[n1 - 1] = tok2[n2 - 1] = '\0';
+ if (sscanf(tok1 + 1, "%x", &code1) != 1 ||
+ sscanf(tok2 + 1, "%x", &code2) != 1) {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ continue;
+ }
+ if (!strcmp(tok3, "[")) {
+ i = 0;
+ while (pst->getToken(tok1, sizeof(tok1), &n1) &&
+ code1 + i <= code2) {
+ if (!strcmp(tok1, "]")) {
+ break;
+ }
+ if (tok1[0] == '<' && tok1[n1 - 1] == '>') {
+ tok1[n1 - 1] = '\0';
+ addMapping(code1 + i, tok1 + 1, n1 - 2, 0);
+ } else {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ }
+ ++i;
+ }
+ } else if (tok3[0] == '<' && tok3[n3 - 1] == '>') {
+ tok3[n3 - 1] = '\0';
+ for (i = 0; code1 <= code2; ++code1, ++i) {
+ addMapping(code1, tok3 + 1, n3 - 2, i);
+ }
+
+ } else {
+ error(-1, "Illegal entry in bfrange block in ToUnicode CMap");
+ }
+ }
+ pst->getToken(tok1, sizeof(tok1), &n1);
+ } else {
+ strcpy(tok1, tok2);
+ }
+ }
+ delete pst;
+}
+
+void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n,
+ int offset) {
+ CharCode oldLen, i;
+ Unicode u;
+ char uHex[5];
+ int j;
+
+ if (code >= mapLen) {
+ oldLen = mapLen;
+ mapLen = (code + 256) & ~255;
+ map = (Unicode *)grealloc(map, mapLen * sizeof(Unicode));
+ for (i = oldLen; i < mapLen; ++i) {
+ map[i] = 0;
+ }
+ }
+ if (n <= 4) {
+ if (sscanf(uStr, "%x", &u) != 1) {
+ error(-1, "Illegal entry in ToUnicode CMap");
+ return;
+ }
+ map[code] = u + offset;
+ } else {
+ if (sMapLen >= sMapSize) {
+ sMapSize = sMapSize + 16;
+ sMap = (CharCodeToUnicodeString *)
+ grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
+ }
+ map[code] = 0;
+ sMap[sMapLen].c = code;
+ sMap[sMapLen].len = n / 4;
+ for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) {
+ strncpy(uHex, uStr + j*4, 4);
+ uHex[4] = '\0';
+ if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) {
+ error(-1, "Illegal entry in ToUnicode CMap");
+ }
+ }
+ sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset;
+ ++sMapLen;
+ }
+ }
+
+CharCodeToUnicode::CharCodeToUnicode(GString *tagA) {
+ CharCode i;
+
+ tag = tagA;
+ mapLen = 256;
+ map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
+ for (i = 0; i < mapLen; ++i) {
+ map[i] = 0;
+ }
+ sMap = NULL;
+ sMapLen = sMapSize = 0;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+CharCodeToUnicode::CharCodeToUnicode(GString *tagA, Unicode *mapA,
+ CharCode mapLenA, GBool copyMap,
+ CharCodeToUnicodeString *sMapA,
+ int sMapLenA, int sMapSizeA) {
+ tag = tagA;
+ mapLen = mapLenA;
+ if (copyMap) {
+ map = (Unicode *)gmalloc(mapLen * sizeof(Unicode));
+ memcpy(map, mapA, mapLen * sizeof(Unicode));
+ } else {
+ map = mapA;
+ }
+ sMap = sMapA;
+ sMapLen = sMapLenA;
+ sMapSize = sMapSizeA;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+CharCodeToUnicode::~CharCodeToUnicode() {
+ if (tag) {
+ delete tag;
+ }
+ gfree(map);
+ if (sMap) {
+ gfree(sMap);
+ }
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+void CharCodeToUnicode::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ ++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+}
+
+void CharCodeToUnicode::decRefCnt() {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
+ delete this;
+ }
+}
+
+GBool CharCodeToUnicode::match(GString *tagA) {
+ return tag && !tag->cmp(tagA);
+}
+
+void CharCodeToUnicode::setMapping(CharCode c, Unicode *u, int len) {
+ int i;
+
+ if (len == 1) {
+ map[c] = u[0];
+ } else {
+ map[c] = 0;
+ if (sMapLen == sMapSize) {
+ sMapSize += 8;
+ sMap = (CharCodeToUnicodeString *)
+ grealloc(sMap, sMapSize * sizeof(CharCodeToUnicodeString));
+ }
+ sMap[sMapLen].c = c;
+ sMap[sMapLen].len = len;
+ for (i = 0; i < len && i < maxUnicodeString; ++i) {
+ sMap[sMapLen].u[i] = u[i];
+ }
+ ++sMapLen;
+ }
+}
+
+int CharCodeToUnicode::mapToUnicode(CharCode c, Unicode *u, int size) {
+ int i, j;
+
+ if (c >= mapLen) {
+ return 0;
+ }
+ if (map[c]) {
+ u[0] = map[c];
+ return 1;
+ }
+ for (i = 0; i < sMapLen; ++i) {
+ if (sMap[i].c == c) {
+ for (j = 0; j < sMap[i].len && j < size; ++j) {
+ u[j] = sMap[i].u[j];
+ }
+ return j;
+ }
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------
+
+CharCodeToUnicodeCache::CharCodeToUnicodeCache(int sizeA) {
+ int i;
+
+ size = sizeA;
+ cache = (CharCodeToUnicode **)gmalloc(size * sizeof(CharCodeToUnicode *));
+ for (i = 0; i < size; ++i) {
+ cache[i] = NULL;
+ }
+}
+
+CharCodeToUnicodeCache::~CharCodeToUnicodeCache() {
+ int i;
+
+ for (i = 0; i < size; ++i) {
+ if (cache[i]) {
+ cache[i]->decRefCnt();
+ }
+ }
+ gfree(cache);
+}
+
+CharCodeToUnicode *CharCodeToUnicodeCache::getCharCodeToUnicode(GString *tag) {
+ CharCodeToUnicode *ctu;
+ int i, j;
+
+ if (cache[0] && cache[0]->match(tag)) {
+ cache[0]->incRefCnt();
+ return cache[0];
+ }
+ for (i = 1; i < size; ++i) {
+ if (cache[i] && cache[i]->match(tag)) {
+ ctu = cache[i];
+ for (j = i; j >= 1; --j) {
+ cache[j] = cache[j - 1];
+ }
+ cache[0] = ctu;
+ ctu->incRefCnt();
+ return ctu;
+ }
+ }
+ return NULL;
+}
+
+void CharCodeToUnicodeCache::add(CharCodeToUnicode *ctu) {
+ int i;
+
+ if (cache[size - 1]) {
+ cache[size - 1]->decRefCnt();
+ }
+ for (i = size - 1; i >= 1; --i) {
+ cache[i] = cache[i - 1];
+ }
+ cache[0] = ctu;
+ ctu->incRefCnt();
+}
diff --git a/pdftops/CharCodeToUnicode.h b/pdftops/CharCodeToUnicode.h
new file mode 100644
index 000000000..8ce3252f8
--- /dev/null
+++ b/pdftops/CharCodeToUnicode.h
@@ -0,0 +1,113 @@
+//========================================================================
+//
+// CharCodeToUnicode.h
+//
+// Mapping from character codes to Unicode.
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef CHARCODETOUNICODE_H
+#define CHARCODETOUNICODE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "CharTypes.h"
+
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
+struct CharCodeToUnicodeString;
+
+//------------------------------------------------------------------------
+
+class CharCodeToUnicode {
+public:
+
+ // Read the CID-to-Unicode mapping for <collection> from the file
+ // specified by <fileName>. Sets the initial reference count to 1.
+ // Returns NULL on failure.
+ static CharCodeToUnicode *parseCIDToUnicode(GString *fileName,
+ GString *collection);
+
+ // Create a Unicode-to-Unicode mapping from the file specified by
+ // <fileName>. Sets the initial reference count to 1. Returns NULL
+ // on failure.
+ static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName);
+
+ // Create the CharCode-to-Unicode mapping for an 8-bit font.
+ // <toUnicode> is an array of 256 Unicode indexes. Sets the initial
+ // reference count to 1.
+ static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode);
+
+ // Parse a ToUnicode CMap for an 8- or 16-bit font.
+ static CharCodeToUnicode *parseCMap(GString *buf, int nBits);
+
+ // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into
+ // <this>.
+ void mergeCMap(GString *buf, int nBits);
+
+ ~CharCodeToUnicode();
+
+ void incRefCnt();
+ void decRefCnt();
+
+ // Return true if this mapping matches the specified <tagA>.
+ GBool match(GString *tagA);
+
+ // Set the mapping for <c>.
+ void setMapping(CharCode c, Unicode *u, int len);
+
+ // Map a CharCode to Unicode.
+ int mapToUnicode(CharCode c, Unicode *u, int size);
+
+private:
+
+ void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits);
+ void addMapping(CharCode code, char *uStr, int n, int offset);
+ CharCodeToUnicode(GString *tagA);
+ CharCodeToUnicode(GString *tagA, Unicode *mapA,
+ CharCode mapLenA, GBool copyMap,
+ CharCodeToUnicodeString *sMapA,
+ int sMapLenA, int sMapSizeA);
+
+ GString *tag;
+ Unicode *map;
+ CharCode mapLen;
+ CharCodeToUnicodeString *sMap;
+ int sMapLen, sMapSize;
+ int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
+};
+
+//------------------------------------------------------------------------
+
+class CharCodeToUnicodeCache {
+public:
+
+ CharCodeToUnicodeCache(int sizeA);
+ ~CharCodeToUnicodeCache();
+
+ // Get the CharCodeToUnicode object for <tag>. Increments its
+ // reference count; there will be one reference for the cache plus
+ // one for the caller of this function. Returns NULL on failure.
+ CharCodeToUnicode *getCharCodeToUnicode(GString *tag);
+
+ // Insert <ctu> into the cache, in the most-recently-used position.
+ void add(CharCodeToUnicode *ctu);
+
+private:
+
+ CharCodeToUnicode **cache;
+ int size;
+};
+
+#endif
diff --git a/pdftops/CharTypes.h b/pdftops/CharTypes.h
new file mode 100644
index 000000000..d0df630d0
--- /dev/null
+++ b/pdftops/CharTypes.h
@@ -0,0 +1,24 @@
+//========================================================================
+//
+// CharTypes.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef CHARTYPES_H
+#define CHARTYPES_H
+
+// Unicode character.
+typedef unsigned int Unicode;
+
+// Character ID for CID character collections.
+typedef unsigned int CID;
+
+// This is large enough to hold any of the following:
+// - 8-bit char code
+// - 16-bit CID
+// - Unicode
+typedef unsigned int CharCode;
+
+#endif
diff --git a/pdftops/CompactFontTables.h b/pdftops/CompactFontTables.h
new file mode 100644
index 000000000..4e2679349
--- /dev/null
+++ b/pdftops/CompactFontTables.h
@@ -0,0 +1,464 @@
+//========================================================================
+//
+// CompactFontTables.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef COMPACTFONTINFO_H
+#define COMPACTFONTINFO_H
+
+static const char *type1CStdStrings[391] = {
+ ".notdef",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcentered",
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ "questiondown",
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ "AE",
+ "ordfeminine",
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ "ae",
+ "dotlessi",
+ "lslash",
+ "oslash",
+ "oe",
+ "germandbls",
+ "onesuperior",
+ "logicalnot",
+ "mu",
+ "trademark",
+ "Eth",
+ "onehalf",
+ "plusminus",
+ "Thorn",
+ "onequarter",
+ "divide",
+ "brokenbar",
+ "degree",
+ "thorn",
+ "threequarters",
+ "twosuperior",
+ "registered",
+ "minus",
+ "eth",
+ "multiply",
+ "threesuperior",
+ "copyright",
+ "Aacute",
+ "Acircumflex",
+ "Adieresis",
+ "Agrave",
+ "Aring",
+ "Atilde",
+ "Ccedilla",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Ntilde",
+ "Oacute",
+ "Ocircumflex",
+ "Odieresis",
+ "Ograve",
+ "Otilde",
+ "Scaron",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Ugrave",
+ "Yacute",
+ "Ydieresis",
+ "Zcaron",
+ "aacute",
+ "acircumflex",
+ "adieresis",
+ "agrave",
+ "aring",
+ "atilde",
+ "ccedilla",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "egrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "igrave",
+ "ntilde",
+ "oacute",
+ "ocircumflex",
+ "odieresis",
+ "ograve",
+ "otilde",
+ "scaron",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "ugrave",
+ "yacute",
+ "ydieresis",
+ "zcaron",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ "isuperior",
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ "ff",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ "Dotaccentsmall",
+ "Macronsmall",
+ "figuredash",
+ "hypheninferior",
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ "zerosuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacutesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall",
+ "001.000",
+ "001.001",
+ "001.002",
+ "001.003",
+ "Black",
+ "Bold",
+ "Book",
+ "Light",
+ "Medium",
+ "Regular",
+ "Roman",
+ "Semibold"
+};
+
+static Gushort type1CISOAdobeCharset[229] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228
+};
+
+static Gushort type1CExpertCharset[166] = {
+ 0, 1, 229, 230, 231, 232, 233, 234, 235, 236,
+ 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
+ 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+ 261, 262, 263, 264, 265, 266, 109, 110, 267, 268,
+ 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+ 158, 155, 163, 319, 320, 321, 322, 323, 324, 325,
+ 326, 150, 164, 169, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+ 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+ 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
+ 373, 374, 375, 376, 377, 378
+};
+
+static Gushort type1CExpertSubsetCharset[87] = {
+ 0, 1, 231, 232, 235, 236, 237, 238, 13, 14,
+ 15, 99, 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 27, 28, 249, 250, 251, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+ 266, 109, 110, 267, 268, 269, 270, 272, 300, 301,
+ 302, 305, 314, 315, 158, 155, 163, 320, 321, 322,
+ 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
+ 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
+ 340, 341, 342, 343, 344, 345, 346
+};
+
+#endif
diff --git a/pdftops/Decrypt.cxx b/pdftops/Decrypt.cxx
new file mode 100644
index 000000000..919911781
--- /dev/null
+++ b/pdftops/Decrypt.cxx
@@ -0,0 +1,399 @@
+//========================================================================
+//
+// Decrypt.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "Decrypt.h"
+
+static void rc4InitKey(Guchar *key, int keyLen, Guchar *state);
+static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c);
+static void md5(Guchar *msg, int msgLen, Guchar *digest);
+
+static Guchar passwordPad[32] = {
+ 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41,
+ 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08,
+ 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80,
+ 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a
+};
+
+//------------------------------------------------------------------------
+// Decrypt
+//------------------------------------------------------------------------
+
+Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) {
+ int i;
+
+ // construct object key
+ for (i = 0; i < keyLength; ++i) {
+ objKey[i] = fileKey[i];
+ }
+ objKey[keyLength] = objNum & 0xff;
+ objKey[keyLength + 1] = (objNum >> 8) & 0xff;
+ objKey[keyLength + 2] = (objNum >> 16) & 0xff;
+ objKey[keyLength + 3] = objGen & 0xff;
+ objKey[keyLength + 4] = (objGen >> 8) & 0xff;
+ md5(objKey, keyLength + 5, objKey);
+
+ // set up for decryption
+ x = y = 0;
+ if ((objKeyLength = keyLength + 5) > 16) {
+ objKeyLength = 16;
+ }
+ rc4InitKey(objKey, objKeyLength, state);
+}
+
+void Decrypt::reset() {
+ x = y = 0;
+ rc4InitKey(objKey, objKeyLength, state);
+}
+
+Guchar Decrypt::decryptByte(Guchar c) {
+ return rc4DecryptByte(state, &x, &y, c);
+}
+
+GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength,
+ GString *ownerKey, GString *userKey,
+ int permissions, GString *fileID,
+ GString *ownerPassword, GString *userPassword,
+ Guchar *fileKey, GBool *ownerPasswordOk) {
+ Guchar test[32], test2[32];
+ GString *userPassword2;
+ Guchar fState[256];
+ Guchar tmpKey[16];
+ Guchar fx, fy;
+ int len, i, j;
+
+ // try using the supplied owner password to generate the user password
+ *ownerPasswordOk = gFalse;
+ if (ownerPassword) {
+ len = ownerPassword->getLength();
+ if (len < 32) {
+ memcpy(test, ownerPassword->getCString(), len);
+ memcpy(test + len, passwordPad, 32 - len);
+ } else {
+ memcpy(test, ownerPassword->getCString(), 32);
+ }
+ md5(test, 32, test);
+ if (encRevision == 3) {
+ for (i = 0; i < 50; ++i) {
+ md5(test, 16, test);
+ }
+ }
+ if (encRevision == 2) {
+ rc4InitKey(test, keyLength, fState);
+ fx = fy = 0;
+ for (i = 0; i < 32; ++i) {
+ test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i));
+ }
+ } else {
+ memcpy(test2, ownerKey->getCString(), 32);
+ for (i = 19; i >= 0; --i) {
+ for (j = 0; j < keyLength; ++j) {
+ tmpKey[j] = test[j] ^ i;
+ }
+ rc4InitKey(tmpKey, keyLength, fState);
+ fx = fy = 0;
+ for (j = 0; j < 32; ++j) {
+ test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]);
+ }
+ }
+ }
+ userPassword2 = new GString((char *)test2, 32);
+ if (makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+ permissions, fileID, userPassword2, fileKey)) {
+ *ownerPasswordOk = gTrue;
+ delete userPassword2;
+ return gTrue;
+ }
+ delete userPassword2;
+ }
+
+ // try using the supplied user password
+ return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey,
+ permissions, fileID, userPassword, fileKey);
+}
+
+GBool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength,
+ GString *ownerKey, GString *userKey,
+ int permissions, GString *fileID,
+ GString *userPassword, Guchar *fileKey) {
+ Guchar *buf;
+ Guchar test[32];
+ Guchar fState[256];
+ Guchar tmpKey[16];
+ Guchar fx, fy;
+ int len, i, j;
+ GBool ok;
+
+ // generate file key
+ buf = (Guchar *)gmalloc(68 + fileID->getLength());
+ if (userPassword) {
+ len = userPassword->getLength();
+ if (len < 32) {
+ memcpy(buf, userPassword->getCString(), len);
+ memcpy(buf + len, passwordPad, 32 - len);
+ } else {
+ memcpy(buf, userPassword->getCString(), 32);
+ }
+ } else {
+ memcpy(buf, passwordPad, 32);
+ }
+ memcpy(buf + 32, ownerKey->getCString(), 32);
+ buf[64] = permissions & 0xff;
+ buf[65] = (permissions >> 8) & 0xff;
+ buf[66] = (permissions >> 16) & 0xff;
+ buf[67] = (permissions >> 24) & 0xff;
+ memcpy(buf + 68, fileID->getCString(), fileID->getLength());
+ md5(buf, 68 + fileID->getLength(), fileKey);
+ if (encRevision == 3) {
+ for (i = 0; i < 50; ++i) {
+ md5(fileKey, keyLength, fileKey);
+ }
+ }
+
+ // test user password
+ if (encRevision == 2) {
+ rc4InitKey(fileKey, keyLength, fState);
+ fx = fy = 0;
+ for (i = 0; i < 32; ++i) {
+ test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i));
+ }
+ ok = memcmp(test, passwordPad, 32) == 0;
+ } else if (encRevision == 3) {
+ memcpy(test, userKey->getCString(), 32);
+ for (i = 19; i >= 0; --i) {
+ for (j = 0; j < keyLength; ++j) {
+ tmpKey[j] = fileKey[j] ^ i;
+ }
+ rc4InitKey(tmpKey, keyLength, fState);
+ fx = fy = 0;
+ for (j = 0; j < 32; ++j) {
+ test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]);
+ }
+ }
+ memcpy(buf, passwordPad, 32);
+ memcpy(buf + 32, fileID->getCString(), fileID->getLength());
+ md5(buf, 32 + fileID->getLength(), buf);
+ ok = memcmp(test, buf, 16) == 0;
+ } else {
+ ok = gFalse;
+ }
+
+ gfree(buf);
+ return ok;
+}
+
+//------------------------------------------------------------------------
+// RC4-compatible decryption
+//------------------------------------------------------------------------
+
+static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) {
+ Guchar index1, index2;
+ Guchar t;
+ int i;
+
+ for (i = 0; i < 256; ++i)
+ state[i] = i;
+ index1 = index2 = 0;
+ for (i = 0; i < 256; ++i) {
+ index2 = (key[index1] + state[i] + index2) % 256;
+ t = state[i];
+ state[i] = state[index2];
+ state[index2] = t;
+ index1 = (index1 + 1) % keyLen;
+ }
+}
+
+static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) {
+ Guchar x1, y1, tx, ty;
+
+ x1 = *x = (*x + 1) % 256;
+ y1 = *y = (state[*x] + *y) % 256;
+ tx = state[x1];
+ ty = state[y1];
+ state[x1] = ty;
+ state[y1] = tx;
+ return c ^ state[(tx + ty) % 256];
+}
+
+//------------------------------------------------------------------------
+// MD5 message digest
+//------------------------------------------------------------------------
+
+// this works around a bug in older Sun compilers
+static inline Gulong rotateLeft(Gulong x, int r) {
+ x &= 0xffffffff;
+ return ((x << r) | (x >> (32 - r))) & 0xffffffff;
+}
+
+static inline Gulong md5Round1(Gulong a, Gulong b, Gulong c, Gulong d,
+ Gulong Xk, Gulong s, Gulong Ti) {
+ return b + rotateLeft((a + ((b & c) | (~b & d)) + Xk + Ti), s);
+}
+
+static inline Gulong md5Round2(Gulong a, Gulong b, Gulong c, Gulong d,
+ Gulong Xk, Gulong s, Gulong Ti) {
+ return b + rotateLeft((a + ((b & d) | (c & ~d)) + Xk + Ti), s);
+}
+
+static inline Gulong md5Round3(Gulong a, Gulong b, Gulong c, Gulong d,
+ Gulong Xk, Gulong s, Gulong Ti) {
+ return b + rotateLeft((a + (b ^ c ^ d) + Xk + Ti), s);
+}
+
+static inline Gulong md5Round4(Gulong a, Gulong b, Gulong c, Gulong d,
+ Gulong Xk, Gulong s, Gulong Ti) {
+ return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s);
+}
+
+static void md5(Guchar *msg, int msgLen, Guchar *digest) {
+ Gulong x[16];
+ Gulong a, b, c, d, aa, bb, cc, dd;
+ int n64;
+ int i, j, k;
+
+ // compute number of 64-byte blocks
+ // (length + pad byte (0x80) + 8 bytes for length)
+ n64 = (msgLen + 1 + 8 + 63) / 64;
+
+ // initialize a, b, c, d
+ a = 0x67452301;
+ b = 0xefcdab89;
+ c = 0x98badcfe;
+ d = 0x10325476;
+
+ // loop through blocks
+ k = 0;
+ for (i = 0; i < n64; ++i) {
+
+ // grab a 64-byte block
+ for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4)
+ x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k];
+ if (i == n64 - 1) {
+ if (k == msgLen - 3)
+ x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k];
+ else if (k == msgLen - 2)
+ x[j] = 0x800000 + (msg[k+1] << 8) + msg[k];
+ else if (k == msgLen - 1)
+ x[j] = 0x8000 + msg[k];
+ else
+ x[j] = 0x80;
+ ++j;
+ while (j < 16)
+ x[j++] = 0;
+ x[14] = msgLen << 3;
+ }
+
+ // save a, b, c, d
+ aa = a;
+ bb = b;
+ cc = c;
+ dd = d;
+
+ // round 1
+ a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478);
+ d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756);
+ c = md5Round1(c, d, a, b, x[2], 17, 0x242070db);
+ b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee);
+ a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf);
+ d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a);
+ c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613);
+ b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501);
+ a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8);
+ d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af);
+ c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1);
+ b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be);
+ a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122);
+ d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193);
+ c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e);
+ b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821);
+
+ // round 2
+ a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562);
+ d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340);
+ c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51);
+ b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa);
+ a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d);
+ d = md5Round2(d, a, b, c, x[10], 9, 0x02441453);
+ c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681);
+ b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8);
+ a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6);
+ d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6);
+ c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87);
+ b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed);
+ a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905);
+ d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8);
+ c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9);
+ b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a);
+
+ // round 3
+ a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942);
+ d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681);
+ c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122);
+ b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c);
+ a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44);
+ d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9);
+ c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60);
+ b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70);
+ a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6);
+ d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa);
+ c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085);
+ b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05);
+ a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039);
+ d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5);
+ c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8);
+ b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665);
+
+ // round 4
+ a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244);
+ d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97);
+ c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7);
+ b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039);
+ a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3);
+ d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92);
+ c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d);
+ b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1);
+ a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f);
+ d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0);
+ c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314);
+ b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1);
+ a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82);
+ d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235);
+ c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb);
+ b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391);
+
+ // increment a, b, c, d
+ a += aa;
+ b += bb;
+ c += cc;
+ d += dd;
+ }
+
+ // break digest into bytes
+ digest[0] = (Guchar)(a & 0xff);
+ digest[1] = (Guchar)((a >>= 8) & 0xff);
+ digest[2] = (Guchar)((a >>= 8) & 0xff);
+ digest[3] = (Guchar)((a >>= 8) & 0xff);
+ digest[4] = (Guchar)(b & 0xff);
+ digest[5] = (Guchar)((b >>= 8) & 0xff);
+ digest[6] = (Guchar)((b >>= 8) & 0xff);
+ digest[7] = (Guchar)((b >>= 8) & 0xff);
+ digest[8] = (Guchar)(c & 0xff);
+ digest[9] = (Guchar)((c >>= 8) & 0xff);
+ digest[10] = (Guchar)((c >>= 8) & 0xff);
+ digest[11] = (Guchar)((c >>= 8) & 0xff);
+ digest[12] = (Guchar)(d & 0xff);
+ digest[13] = (Guchar)((d >>= 8) & 0xff);
+ digest[14] = (Guchar)((d >>= 8) & 0xff);
+ digest[15] = (Guchar)((d >>= 8) & 0xff);
+}
diff --git a/pdftops/Decrypt.h b/pdftops/Decrypt.h
new file mode 100644
index 000000000..9b776ccb5
--- /dev/null
+++ b/pdftops/Decrypt.h
@@ -0,0 +1,61 @@
+//========================================================================
+//
+// Decrypt.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef DECRYPT_H
+#define DECRYPT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "GString.h"
+
+//------------------------------------------------------------------------
+// Decrypt
+//------------------------------------------------------------------------
+
+class Decrypt {
+public:
+
+ // Initialize the decryptor object.
+ Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen);
+
+ // Reset decryption.
+ void reset();
+
+ // Decrypt one byte.
+ Guchar decryptByte(Guchar c);
+
+ // Generate a file key. The <fileKey> buffer must have space for at
+ // least 16 bytes. Checks <ownerPassword> and then <userPassword>
+ // and returns true if either is correct. Sets <ownerPasswordOk> if
+ // the owner password was correct. Either or both of the passwords
+ // may be NULL, which is treated as an empty string.
+ static GBool makeFileKey(int encVersion, int encRevision, int keyLength,
+ GString *ownerKey, GString *userKey,
+ int permissions, GString *fileID,
+ GString *ownerPassword, GString *userPassword,
+ Guchar *fileKey, GBool *ownerPasswordOk);
+
+private:
+
+ static GBool makeFileKey2(int encVersion, int encRevision, int keyLength,
+ GString *ownerKey, GString *userKey,
+ int permissions, GString *fileID,
+ GString *userPassword, Guchar *fileKey);
+
+ int objKeyLength;
+ Guchar objKey[21];
+ Guchar state[256];
+ Guchar x, y;
+};
+
+#endif
diff --git a/pdftops/Dependencies b/pdftops/Dependencies
new file mode 100644
index 000000000..3f7285fcc
--- /dev/null
+++ b/pdftops/Dependencies
@@ -0,0 +1,88 @@
+# DO NOT DELETE
+
+pdftops.o: ../cups/string.h ../config.h parseargs.h gtypes.h GString.h gmem.h
+pdftops.o: Object.h Array.h Dict.h Stream.h XRef.h Catalog.h Page.h PDFDoc.h
+pdftops.o: Link.h PSOutputDev.h GlobalParams.h CharTypes.h OutputDev.h
+pdftops.o: Params.h Error.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+pdftops.o: ../cups/md5.h ../cups/ppd.h
+Annot.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Annot.o: Stream.h Gfx.h Annot.h
+Array.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Array.o: Stream.h
+BuiltinFont.o: ../config.h gmem.h FontEncodingTables.h BuiltinFont.h gtypes.h
+BuiltinFontTables.o: ../config.h FontEncodingTables.h BuiltinFontTables.h
+BuiltinFontTables.o: BuiltinFont.h gtypes.h
+Catalog.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Catalog.o: Stream.h XRef.h Page.h Error.h Link.h Catalog.h
+CharCodeToUnicode.o: ../config.h gmem.h gfile.h gtypes.h GString.h Error.h
+CharCodeToUnicode.o: GlobalParams.h CharTypes.h PSTokenizer.h
+CharCodeToUnicode.o: CharCodeToUnicode.h
+CMap.o: ../config.h gmem.h gfile.h gtypes.h GString.h Error.h GlobalParams.h
+CMap.o: CharTypes.h PSTokenizer.h CMap.h
+Decrypt.o: ../config.h gmem.h Decrypt.h gtypes.h GString.h
+Dict.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Dict.o: Stream.h XRef.h
+Error.o: ../config.h GlobalParams.h gtypes.h CharTypes.h Error.h
+FontEncoding.o: gmem.h FontEncoding.h gtypes.h
+FontEncodingTables.o: ../config.h FontEncodingTables.h
+FontFile.o: ../config.h gmem.h GHash.h gtypes.h Error.h GlobalParams.h
+FontFile.o: CharTypes.h CharCodeToUnicode.h FontEncodingTables.h FontFile.h
+FontFile.o: GString.h CompactFontTables.h
+Function.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+Function.o: Stream.h Error.h Function.h
+gfile.o: ../config.h GString.h gfile.h gtypes.h
+Gfx.o: ../config.h gmem.h GlobalParams.h gtypes.h CharTypes.h Object.h
+Gfx.o: GString.h Array.h Dict.h Stream.h Lexer.h Parser.h GfxFont.h
+Gfx.o: GfxState.h Function.h OutputDev.h Page.h Error.h Gfx.h
+GfxFont.o: ../config.h gmem.h GHash.h gtypes.h Error.h Object.h GString.h
+GfxFont.o: Array.h Dict.h Stream.h GlobalParams.h CharTypes.h CMap.h
+GfxFont.o: CharCodeToUnicode.h FontEncodingTables.h BuiltinFontTables.h
+GfxFont.o: BuiltinFont.h FontFile.h GfxFont.h
+GfxState.o: ../config.h gmem.h Error.h Object.h gtypes.h GString.h Array.h
+GfxState.o: Dict.h Stream.h Page.h GfxState.h Function.h
+GHash.o: ../config.h gmem.h GString.h GHash.h gtypes.h
+GList.o: ../config.h gmem.h GList.h gtypes.h
+GlobalParams.o: ../config.h gmem.h GString.h GList.h gtypes.h GHash.h gfile.h
+GlobalParams.o: Error.h NameToCharCode.h CharTypes.h CharCodeToUnicode.h
+GlobalParams.o: UnicodeMap.h CMap.h BuiltinFontTables.h BuiltinFont.h
+GlobalParams.o: FontEncodingTables.h GlobalParams.h NameToUnicodeTable.h
+GlobalParams.o: UnicodeMapTables.h DisplayFontTable.h UTF8.h
+gmempp.o: ../config.h gmem.h
+GString.o: ../config.h gtypes.h GString.h
+JBIG2Stream.o: ../config.h GList.h gtypes.h Error.h JBIG2Stream.h Object.h
+JBIG2Stream.o: gmem.h GString.h Array.h Dict.h Stream.h Stream-CCITT.h
+Lexer.o: ../config.h Lexer.h Object.h gtypes.h gmem.h GString.h Array.h
+Lexer.o: Dict.h Stream.h Error.h
+Link.o: ../config.h gmem.h GString.h Error.h Object.h gtypes.h Array.h Dict.h
+Link.o: Stream.h Link.h
+NameToCharCode.o: ../config.h gmem.h NameToCharCode.h CharTypes.h
+Object.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+Object.o: Stream.h Error.h XRef.h
+Outline.o: ../config.h gmem.h GString.h GList.h gtypes.h Link.h Object.h
+Outline.o: Array.h Dict.h Stream.h PDFDocEncoding.h CharTypes.h Outline.h
+OutputDev.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+OutputDev.o: Stream.h GfxState.h Function.h OutputDev.h CharTypes.h
+Page.o: ../config.h GlobalParams.h gtypes.h CharTypes.h Object.h gmem.h
+Page.o: GString.h Array.h Dict.h Stream.h XRef.h Link.h OutputDev.h Gfx.h
+Page.o: Annot.h Error.h Page.h
+Params.o: gtypes.h gmem.h GString.h ../config.h gfile.h Params.h
+Parser.o: ../config.h Object.h gtypes.h gmem.h GString.h Array.h Dict.h
+Parser.o: Stream.h Parser.h Lexer.h XRef.h Error.h Decrypt.h
+PDFDoc.o: ../config.h GString.h GlobalParams.h gtypes.h CharTypes.h Page.h
+PDFDoc.o: Object.h gmem.h Array.h Dict.h Stream.h Catalog.h XRef.h Link.h
+PDFDoc.o: OutputDev.h Error.h ErrorCodes.h Lexer.h Parser.h Outline.h
+PDFDoc.o: PDFDoc.h
+PDFDocEncoding.o: PDFDocEncoding.h CharTypes.h
+PSOutputDev.o: ../config.h GString.h GList.h gtypes.h GlobalParams.h
+PSOutputDev.o: CharTypes.h Object.h gmem.h Array.h Dict.h Stream.h Error.h
+PSOutputDev.o: Function.h Gfx.h GfxState.h GfxFont.h UnicodeMap.h FontFile.h
+PSOutputDev.o: Catalog.h Page.h Annot.h PSOutputDev.h OutputDev.h
+PSTokenizer.o: ../config.h PSTokenizer.h gtypes.h
+Stream.o: ../config.h gmem.h gfile.h gtypes.h Error.h Object.h GString.h
+Stream.o: Array.h Dict.h Stream.h Decrypt.h JBIG2Stream.h Stream-CCITT.h
+UnicodeMap.o: ../config.h gmem.h gfile.h gtypes.h GString.h GList.h Error.h
+UnicodeMap.o: GlobalParams.h CharTypes.h UnicodeMap.h
+XRef.o: ../config.h gmem.h Object.h gtypes.h GString.h Array.h Dict.h
+XRef.o: Stream.h Lexer.h Parser.h Decrypt.h Error.h ErrorCodes.h XRef.h
+gmem.o: ../config.h gmem.h
+parseargs.o: parseargs.h gtypes.h
diff --git a/pdftops/Dict.cxx b/pdftops/Dict.cxx
new file mode 100644
index 000000000..ae0ef7c26
--- /dev/null
+++ b/pdftops/Dict.cxx
@@ -0,0 +1,95 @@
+//========================================================================
+//
+// Dict.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include "gmem.h"
+#include "Object.h"
+#include "XRef.h"
+#include "Dict.h"
+
+//------------------------------------------------------------------------
+// Dict
+//------------------------------------------------------------------------
+
+Dict::Dict(XRef *xrefA) {
+ xref = xrefA;
+ entries = NULL;
+ size = length = 0;
+ ref = 1;
+}
+
+Dict::~Dict() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ gfree((void *)entries[i].key);
+ entries[i].val.free();
+ }
+ gfree(entries);
+}
+
+void Dict::add(const char *key, Object *val) {
+ if (length == size) {
+ if (length == 0) {
+ size = 8;
+ } else {
+ size *= 2;
+ }
+ entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
+ }
+ entries[length].key = key;
+ entries[length].val = *val;
+ ++length;
+}
+
+inline DictEntry *Dict::find(const char *key) {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ if (!strcmp(key, entries[i].key))
+ return &entries[i];
+ }
+ return NULL;
+}
+
+GBool Dict::is(const char *type) {
+ DictEntry *e;
+
+ return (e = find("Type")) && e->val.isName(type);
+}
+
+Object *Dict::lookup(const char *key, Object *obj) {
+ DictEntry *e;
+
+ return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull();
+}
+
+Object *Dict::lookupNF(const char *key, Object *obj) {
+ DictEntry *e;
+
+ return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
+}
+
+const char *Dict::getKey(int i) {
+ return entries[i].key;
+}
+
+Object *Dict::getVal(int i, Object *obj) {
+ return entries[i].val.fetch(xref, obj);
+}
+
+Object *Dict::getValNF(int i, Object *obj) {
+ return entries[i].val.copy(obj);
+}
diff --git a/pdftops/Dict.h b/pdftops/Dict.h
new file mode 100644
index 000000000..5de03897b
--- /dev/null
+++ b/pdftops/Dict.h
@@ -0,0 +1,77 @@
+//========================================================================
+//
+// Dict.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef DICT_H
+#define DICT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+
+//------------------------------------------------------------------------
+// Dict
+//------------------------------------------------------------------------
+
+struct DictEntry {
+ const char *key;
+ Object val;
+};
+
+class Dict {
+public:
+
+ // Constructor.
+ Dict(XRef *xrefA);
+
+ // Destructor.
+ ~Dict();
+
+ // Reference counting.
+ int incRef() { return ++ref; }
+ int decRef() { return --ref; }
+
+ // Get number of entries.
+ int getLength() { return length; }
+
+ // Add an entry. NB: does not copy key.
+ void add(const char *key, Object *val);
+
+ // Check if dictionary is of specified type.
+ GBool is(const char *type);
+
+ // Look up an entry and return the value. Returns a null object
+ // if <key> is not in the dictionary.
+ Object *lookup(const char *key, Object *obj);
+ Object *lookupNF(const char *key, Object *obj);
+
+ // Iterative accessors.
+ const char *getKey(int i);
+ Object *getVal(int i, Object *obj);
+ Object *getValNF(int i, Object *obj);
+
+ // Set the xref pointer. This is only used in one special case: the
+ // trailer dictionary, which is read before the xref table is
+ // parsed.
+ void setXRef(XRef *xrefA) { xref = xrefA; }
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ DictEntry *entries; // array of entries
+ int size; // size of <entries> array
+ int length; // number of entries in dictionary
+ int ref; // reference count
+
+ DictEntry *find(const char *key);
+};
+
+#endif
diff --git a/pdftops/DisplayFontTable.h b/pdftops/DisplayFontTable.h
new file mode 100644
index 000000000..f3803dd85
--- /dev/null
+++ b/pdftops/DisplayFontTable.h
@@ -0,0 +1,29 @@
+//========================================================================
+//
+// DisplayFontTable.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+static struct {
+ const char *name;
+ const char *xlfd;
+ const char *encoding;
+} displayFontTab[] = {
+ {"Courier", "-*-courier-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Courier-Bold", "-*-courier-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Courier-BoldOblique", "-*-courier-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Courier-Oblique", "-*-courier-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Helvetica", "-*-helvetica-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Helvetica-Bold", "-*-helvetica-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Helvetica-BoldOblique", "-*-helvetica-bold-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Helvetica-Oblique", "-*-helvetica-medium-o-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Symbol", "-*-symbol-medium-r-normal-*-%s-*-*-*-*-*-adobe-fontspecific", "Symbol"},
+ {"Times-Bold", "-*-times-bold-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Times-BoldItalic", "-*-times-bold-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Times-Italic", "-*-times-medium-i-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"Times-Roman", "-*-times-medium-r-normal-*-%s-*-*-*-*-*-iso8859-1", "Latin1"},
+ {"ZapfDingbats", "-*-zapfdingbats-medium-r-normal-*-%s-*-*-*-*-*-*-*", "ZapfDingbats"},
+ {NULL}
+};
diff --git a/pdftops/Error.cxx b/pdftops/Error.cxx
new file mode 100644
index 000000000..d2804c671
--- /dev/null
+++ b/pdftops/Error.cxx
@@ -0,0 +1,38 @@
+//========================================================================
+//
+// Error.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include "GlobalParams.h"
+#include "Error.h"
+
+void CDECL error(int pos, const char *msg, ...) {
+ va_list args;
+
+ // NB: this can be called before the globalParams object is created
+ if (globalParams && globalParams->getErrQuiet()) {
+ return;
+ }
+ if (pos >= 0) {
+ fprintf(stderr, "ERROR: (%d) ", pos);
+ } else {
+ fprintf(stderr, "ERROR: ");
+ }
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
diff --git a/pdftops/Error.h b/pdftops/Error.h
new file mode 100644
index 000000000..ce2aeade9
--- /dev/null
+++ b/pdftops/Error.h
@@ -0,0 +1,23 @@
+//========================================================================
+//
+// Error.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef ERROR_H
+#define ERROR_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "config.h"
+
+extern void CDECL error(int pos, const char *msg, ...);
+
+#endif
diff --git a/pdftops/ErrorCodes.h b/pdftops/ErrorCodes.h
new file mode 100644
index 000000000..6eb14350c
--- /dev/null
+++ b/pdftops/ErrorCodes.h
@@ -0,0 +1,34 @@
+//========================================================================
+//
+// ErrorCodes.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef ERRORCODES_H
+#define ERRORCODES_H
+
+#define errNone 0 // no error
+
+#define errOpenFile 1 // couldn't open the PDF file
+
+#define errBadCatalog 2 // couldn't read the page catalog
+
+#define errDamaged 3 // PDF file was damaged and couldn't be
+ // repaired
+
+#define errEncrypted 4 // file was encrypted and password was
+ // incorrect or not supplied
+
+#define errHighlightFile 5 // nonexistent or invalid highlight file
+
+#define errBadPrinter 6 // invalid printer
+
+#define errPrinting 7 // error during printing
+
+#define errPermission 8 // PDF file doesn't allow that operation
+
+#define errBadPageNum 9 // invalid page number
+
+#endif
diff --git a/pdftops/FontEncoding.cxx b/pdftops/FontEncoding.cxx
new file mode 100644
index 000000000..3d084cc9d
--- /dev/null
+++ b/pdftops/FontEncoding.cxx
@@ -0,0 +1,143 @@
+//========================================================================
+//
+// FontEncoding.cc
+//
+// Copyright 1999 Derek B. Noonburg
+//
+//========================================================================
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "gmem.h"
+#include "FontEncoding.h"
+
+//------------------------------------------------------------------------
+// FontEncoding
+//------------------------------------------------------------------------
+
+inline int FontEncoding::hash(char *name) {
+ Guint h;
+
+ h = (Guint)name[0] & 0xff;
+ if (h && name[1])
+ h = h * 61 + ((Guint)name[1] & 0xff);
+ return (int)(h % (Guint)fontEncHashSize);
+}
+
+FontEncoding::FontEncoding() {
+ int i;
+
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ size = 256;
+ freeEnc = gTrue;
+ for (i = 0; i < 256; ++i)
+ encoding[i] = NULL;
+ for (i = 0; i < fontEncHashSize; ++i)
+ hashTab[i] = -1;
+}
+
+FontEncoding::FontEncoding(char **encodingA, int sizeA) {
+ int i;
+
+ encoding = encodingA;
+ size = sizeA;
+ freeEnc = gFalse;
+ for (i = 0; i < fontEncHashSize; ++i)
+ hashTab[i] = -1;
+ for (i = 0; i < size; ++i) {
+ if (encoding[i])
+ addChar1(i, encoding[i]);
+ }
+}
+
+FontEncoding::FontEncoding(FontEncoding *fontEnc) {
+ int i;
+
+ encoding = (char **)gmalloc(fontEnc->size * sizeof(char *));
+ size = fontEnc->size;
+ freeEnc = gTrue;
+ for (i = 0; i < size; ++i) {
+ encoding[i] =
+ fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : (char *)NULL;
+ }
+ memcpy(hashTab, fontEnc->hashTab, fontEncHashSize * sizeof(short));
+}
+
+void FontEncoding::addChar(int code, char *name) {
+ int h, i;
+
+ // replace character associated with code
+ if (encoding[code]) {
+ h = hash(encoding[code]);
+ for (i = 0; i < fontEncHashSize; ++i) {
+ if (hashTab[h] == code) {
+ hashTab[h] = -2;
+ break;
+ }
+ if (++h == fontEncHashSize)
+ h = 0;
+ }
+ gfree(encoding[code]);
+ }
+
+ // associate name with code
+ encoding[code] = name;
+
+ // insert name in hash table
+ addChar1(code, name);
+}
+
+void FontEncoding::addChar1(int code, char *name) {
+ int h, i, code2;
+
+ // insert name in hash table
+ h = hash(name);
+ for (i = 0; i < fontEncHashSize; ++i) {
+ code2 = hashTab[h];
+ if (code2 < 0) {
+ hashTab[h] = code;
+ break;
+ } else if (encoding[code2] && !strcmp(encoding[code2], name)) {
+ // keep the highest code for each char -- this is needed because
+ // X won't display chars with codes < 32
+ if (code > code2)
+ hashTab[h] = code;
+ break;
+ }
+ if (++h == fontEncHashSize)
+ h = 0;
+ }
+}
+
+FontEncoding::~FontEncoding() {
+ int i;
+
+ if (freeEnc) {
+ for (i = 0; i < size; ++i) {
+ if (encoding[i])
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+}
+
+int FontEncoding::getCharCode(char *name) {
+ int h, i, code;
+
+ h = hash(name);
+ for (i = 0; i < fontEncHashSize; ++i) {
+ code = hashTab[h];
+ if (code == -1 ||
+ (code >= 0 && encoding[code] && !strcmp(encoding[code], name)))
+ return code;
+ if (++h >= fontEncHashSize)
+ h = 0;
+ }
+ return -1;
+}
diff --git a/pdftops/FontEncoding.h b/pdftops/FontEncoding.h
new file mode 100644
index 000000000..9a5695dbe
--- /dev/null
+++ b/pdftops/FontEncoding.h
@@ -0,0 +1,64 @@
+//========================================================================
+//
+// FontEncoding.h
+//
+// Copyright 1999 Derek B. Noonburg
+//
+//========================================================================
+
+#ifndef FONTENCODING_H
+#define FONTENCODING_H
+
+#ifdef __GNUC__
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// FontEncoding
+//------------------------------------------------------------------------
+
+#define fontEncHashSize 419
+
+class FontEncoding {
+public:
+
+ // Construct an empty encoding.
+ FontEncoding();
+
+ // Construct an encoding from an array of char names.
+ FontEncoding(char **encodingA, int sizeA);
+
+ // Destructor.
+ ~FontEncoding();
+
+ // Create a copy of the encoding.
+ FontEncoding *copy() { return new FontEncoding(this); }
+
+ // Return number of codes in encoding, i.e., max code + 1.
+ int getSize() { return size; }
+
+ // Add a char to the encoding.
+ void addChar(int code, char *name);
+
+ // Return the character name associated with <code>.
+ char *getCharName(int code) { return encoding[code]; }
+
+ // Return the code associated with <name>.
+ int getCharCode(char *name);
+
+private:
+
+ FontEncoding(FontEncoding *fontEnc);
+ int hash(char *name);
+ void addChar1(int code, char *name);
+
+ char **encoding; // code --> name mapping
+ int size; // number of codes
+ GBool freeEnc; // should we free the encoding array?
+ short // name --> code hash table
+ hashTab[fontEncHashSize];
+};
+
+#endif
diff --git a/pdftops/FontEncodingTables.cxx b/pdftops/FontEncodingTables.cxx
new file mode 100644
index 000000000..6ebef7874
--- /dev/null
+++ b/pdftops/FontEncodingTables.cxx
@@ -0,0 +1,1824 @@
+//========================================================================
+//
+// FontEncodingTables.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+#include <stdlib.h>
+#include "FontEncodingTables.h"
+
+const char *macRomanEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ NULL,
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "space",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Oacute",
+ "Ocircumflex",
+ "apple",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron"
+};
+
+const char *macExpertEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ "centoldstyle",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "comma",
+ "hyphen",
+ "period",
+ "fraction",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "colon",
+ "semicolon",
+ NULL,
+ "threequartersemdash",
+ NULL,
+ "questionsmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Ethsmall",
+ NULL,
+ NULL,
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ff",
+ "fi",
+ "fl",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ NULL,
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hypheninferior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ NULL,
+ NULL,
+ "asuperior",
+ "centsuperior",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Aacutesmall",
+ "Agravesmall",
+ "Acircumflexsmall",
+ "Adieresissmall",
+ "Atildesmall",
+ "Aringsmall",
+ "Ccedillasmall",
+ "Eacutesmall",
+ "Egravesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Iacutesmall",
+ "Igravesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ntildesmall",
+ "Oacutesmall",
+ "Ogravesmall",
+ "Ocircumflexsmall",
+ "Odieresissmall",
+ "Otildesmall",
+ "Uacutesmall",
+ "Ugravesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ NULL,
+ "eightsuperior",
+ "fourinferior",
+ "threeinferior",
+ "sixinferior",
+ "eightinferior",
+ "seveninferior",
+ "Scaronsmall",
+ NULL,
+ "centinferior",
+ "twoinferior",
+ NULL,
+ "Dieresissmall",
+ NULL,
+ "Caronsmall",
+ "osuperior",
+ "fiveinferior",
+ NULL,
+ "commainferior",
+ "periodinferior",
+ "Yacutesmall",
+ NULL,
+ "dollarinferior",
+ NULL,
+ NULL,
+ "Thornsmall",
+ NULL,
+ "nineinferior",
+ "zeroinferior",
+ "Zcaronsmall",
+ "AEsmall",
+ "Oslashsmall",
+ "questiondownsmall",
+ "oneinferior",
+ "Lslashsmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Cedillasmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "OEsmall",
+ "figuredash",
+ "hyphensuperior",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdownsmall",
+ NULL,
+ "Ydieresissmall",
+ NULL,
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "ninesuperior",
+ "zerosuperior",
+ NULL,
+ "esuperior",
+ "rsuperior",
+ "tsuperior",
+ NULL,
+ NULL,
+ "isuperior",
+ "ssuperior",
+ "dsuperior",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "lsuperior",
+ "Ogoneksmall",
+ "Brevesmall",
+ "Macronsmall",
+ "bsuperior",
+ "nsuperior",
+ "msuperior",
+ "commasuperior",
+ "periodsuperior",
+ "Dotaccentsmall",
+ "Ringsmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+const char *winAnsiEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "bullet",
+ "Euro",
+ "bullet",
+ "quotesinglbase",
+ "florin",
+ "quotedblbase",
+ "ellipsis",
+ "dagger",
+ "daggerdbl",
+ "circumflex",
+ "perthousand",
+ "Scaron",
+ "guilsinglleft",
+ "OE",
+ "bullet",
+ "Zcaron",
+ "bullet",
+ "bullet",
+ "quoteleft",
+ "quoteright",
+ "quotedblleft",
+ "quotedblright",
+ "bullet",
+ "endash",
+ "emdash",
+ "tilde",
+ "trademark",
+ "scaron",
+ "guilsinglright",
+ "oe",
+ "bullet",
+ "zcaron",
+ "Ydieresis",
+ "space",
+ "exclamdown",
+ "cent",
+ "sterling",
+ "currency",
+ "yen",
+ "brokenbar",
+ "section",
+ "dieresis",
+ "copyright",
+ "ordfeminine",
+ "guillemotleft",
+ "logicalnot",
+ "hyphen",
+ "registered",
+ "macron",
+ "degree",
+ "plusminus",
+ "twosuperior",
+ "threesuperior",
+ "acute",
+ "mu",
+ "paragraph",
+ "periodcentered",
+ "cedilla",
+ "onesuperior",
+ "ordmasculine",
+ "guillemotright",
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "questiondown",
+ "Agrave",
+ "Aacute",
+ "Acircumflex",
+ "Atilde",
+ "Adieresis",
+ "Aring",
+ "AE",
+ "Ccedilla",
+ "Egrave",
+ "Eacute",
+ "Ecircumflex",
+ "Edieresis",
+ "Igrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Eth",
+ "Ntilde",
+ "Ograve",
+ "Oacute",
+ "Ocircumflex",
+ "Otilde",
+ "Odieresis",
+ "multiply",
+ "Oslash",
+ "Ugrave",
+ "Uacute",
+ "Ucircumflex",
+ "Udieresis",
+ "Yacute",
+ "Thorn",
+ "germandbls",
+ "agrave",
+ "aacute",
+ "acircumflex",
+ "atilde",
+ "adieresis",
+ "aring",
+ "ae",
+ "ccedilla",
+ "egrave",
+ "eacute",
+ "ecircumflex",
+ "edieresis",
+ "igrave",
+ "iacute",
+ "icircumflex",
+ "idieresis",
+ "eth",
+ "ntilde",
+ "ograve",
+ "oacute",
+ "ocircumflex",
+ "otilde",
+ "odieresis",
+ "divide",
+ "oslash",
+ "ugrave",
+ "uacute",
+ "ucircumflex",
+ "udieresis",
+ "yacute",
+ "thorn",
+ "ydieresis"
+};
+
+const char *standardEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quoteright",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "quoteleft",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdown",
+ "cent",
+ "sterling",
+ "fraction",
+ "yen",
+ "florin",
+ "section",
+ "currency",
+ "quotesingle",
+ "quotedblleft",
+ "guillemotleft",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ NULL,
+ "endash",
+ "dagger",
+ "daggerdbl",
+ "periodcentered",
+ NULL,
+ "paragraph",
+ "bullet",
+ "quotesinglbase",
+ "quotedblbase",
+ "quotedblright",
+ "guillemotright",
+ "ellipsis",
+ "perthousand",
+ NULL,
+ "questiondown",
+ NULL,
+ "grave",
+ "acute",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "dieresis",
+ NULL,
+ "ring",
+ "cedilla",
+ NULL,
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "emdash",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "AE",
+ NULL,
+ "ordfeminine",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Lslash",
+ "Oslash",
+ "OE",
+ "ordmasculine",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "ae",
+ NULL,
+ NULL,
+ NULL,
+ "dotlessi",
+ NULL,
+ NULL,
+ "lslash",
+ "oslash",
+ "oe",
+ "germandbls",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+const char *expertEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclamsmall",
+ "Hungarumlautsmall",
+ NULL,
+ "dollaroldstyle",
+ "dollarsuperior",
+ "ampersandsmall",
+ "Acutesmall",
+ "parenleftsuperior",
+ "parenrightsuperior",
+ "twodotenleader",
+ "onedotenleader",
+ "comma",
+ "hyphen",
+ "period",
+ "fraction",
+ "zerooldstyle",
+ "oneoldstyle",
+ "twooldstyle",
+ "threeoldstyle",
+ "fouroldstyle",
+ "fiveoldstyle",
+ "sixoldstyle",
+ "sevenoldstyle",
+ "eightoldstyle",
+ "nineoldstyle",
+ "colon",
+ "semicolon",
+ "commasuperior",
+ "threequartersemdash",
+ "periodsuperior",
+ "questionsmall",
+ NULL,
+ "asuperior",
+ "bsuperior",
+ "centsuperior",
+ "dsuperior",
+ "esuperior",
+ NULL,
+ NULL,
+ NULL,
+ "isuperior",
+ NULL,
+ NULL,
+ "lsuperior",
+ "msuperior",
+ "nsuperior",
+ "osuperior",
+ NULL,
+ NULL,
+ "rsuperior",
+ "ssuperior",
+ "tsuperior",
+ NULL,
+ "ff",
+ "fi",
+ "fl",
+ "ffi",
+ "ffl",
+ "parenleftinferior",
+ NULL,
+ "parenrightinferior",
+ "Circumflexsmall",
+ "hyphensuperior",
+ "Gravesmall",
+ "Asmall",
+ "Bsmall",
+ "Csmall",
+ "Dsmall",
+ "Esmall",
+ "Fsmall",
+ "Gsmall",
+ "Hsmall",
+ "Ismall",
+ "Jsmall",
+ "Ksmall",
+ "Lsmall",
+ "Msmall",
+ "Nsmall",
+ "Osmall",
+ "Psmall",
+ "Qsmall",
+ "Rsmall",
+ "Ssmall",
+ "Tsmall",
+ "Usmall",
+ "Vsmall",
+ "Wsmall",
+ "Xsmall",
+ "Ysmall",
+ "Zsmall",
+ "colonmonetary",
+ "onefitted",
+ "rupiah",
+ "Tildesmall",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "exclamdownsmall",
+ "centoldstyle",
+ "Lslashsmall",
+ NULL,
+ NULL,
+ "Scaronsmall",
+ "Zcaronsmall",
+ "Dieresissmall",
+ "Brevesmall",
+ "Caronsmall",
+ NULL,
+ "Dotaccentsmall",
+ NULL,
+ NULL,
+ "Macronsmall",
+ NULL,
+ NULL,
+ "figuredash",
+ "hypheninferior",
+ NULL,
+ NULL,
+ "Ogoneksmall",
+ "Ringsmall",
+ "Cedillasmall",
+ NULL,
+ NULL,
+ NULL,
+ "onequarter",
+ "onehalf",
+ "threequarters",
+ "questiondownsmall",
+ "oneeighth",
+ "threeeighths",
+ "fiveeighths",
+ "seveneighths",
+ "onethird",
+ "twothirds",
+ NULL,
+ NULL,
+ "zerosuperior",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "foursuperior",
+ "fivesuperior",
+ "sixsuperior",
+ "sevensuperior",
+ "eightsuperior",
+ "ninesuperior",
+ "zeroinferior",
+ "oneinferior",
+ "twoinferior",
+ "threeinferior",
+ "fourinferior",
+ "fiveinferior",
+ "sixinferior",
+ "seveninferior",
+ "eightinferior",
+ "nineinferior",
+ "centinferior",
+ "dollarinferior",
+ "periodinferior",
+ "commainferior",
+ "Agravesmall",
+ "Aacutesmall",
+ "Acircumflexsmall",
+ "Atildesmall",
+ "Adieresissmall",
+ "Aringsmall",
+ "AEsmall",
+ "Ccedillasmall",
+ "Egravesmall",
+ "Eacutesmall",
+ "Ecircumflexsmall",
+ "Edieresissmall",
+ "Igravesmall",
+ "Iacutesmall",
+ "Icircumflexsmall",
+ "Idieresissmall",
+ "Ethsmall",
+ "Ntildesmall",
+ "Ogravesmall",
+ "Oacutesmall",
+ "Ocircumflexsmall",
+ "Otildesmall",
+ "Odieresissmall",
+ "OEsmall",
+ "Oslashsmall",
+ "Ugravesmall",
+ "Uacutesmall",
+ "Ucircumflexsmall",
+ "Udieresissmall",
+ "Yacutesmall",
+ "Thornsmall",
+ "Ydieresissmall"
+};
+
+const char *symbolEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "exclam",
+ "universal",
+ "numbersign",
+ "existential",
+ "percent",
+ "ampersand",
+ "suchthat",
+ "parenleft",
+ "parenright",
+ "asteriskmath",
+ "plus",
+ "comma",
+ "minus",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "congruent",
+ "Alpha",
+ "Beta",
+ "Chi",
+ "Delta",
+ "Epsilon",
+ "Phi",
+ "Gamma",
+ "Eta",
+ "Iota",
+ "theta1",
+ "Kappa",
+ "Lambda",
+ "Mu",
+ "Nu",
+ "Omicron",
+ "Pi",
+ "Theta",
+ "Rho",
+ "Sigma",
+ "Tau",
+ "Upsilon",
+ "sigma1",
+ "Omega",
+ "Xi",
+ "Psi",
+ "Zeta",
+ "bracketleft",
+ "therefore",
+ "bracketright",
+ "perpendicular",
+ "underscore",
+ "radicalex",
+ "alpha",
+ "beta",
+ "chi",
+ "delta",
+ "epsilon",
+ "phi",
+ "gamma",
+ "eta",
+ "iota",
+ "phi1",
+ "kappa",
+ "lambda",
+ "mu",
+ "nu",
+ "omicron",
+ "pi",
+ "theta",
+ "rho",
+ "sigma",
+ "tau",
+ "upsilon",
+ "omega1",
+ "omega",
+ "xi",
+ "psi",
+ "zeta",
+ "braceleft",
+ "bar",
+ "braceright",
+ "similar",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Upsilon1",
+ "minute",
+ "lessequal",
+ "fraction",
+ "infinity",
+ "florin",
+ "club",
+ "diamond",
+ "heart",
+ "spade",
+ "arrowboth",
+ "arrowleft",
+ "arrowup",
+ "arrowright",
+ "arrowdown",
+ "degree",
+ "plusminus",
+ "second",
+ "greaterequal",
+ "multiply",
+ "proportional",
+ "partialdiff",
+ "bullet",
+ "divide",
+ "notequal",
+ "equivalence",
+ "approxequal",
+ "ellipsis",
+ "arrowvertex",
+ "arrowhorizex",
+ "carriagereturn",
+ "aleph",
+ "Ifraktur",
+ "Rfraktur",
+ "weierstrass",
+ "circlemultiply",
+ "circleplus",
+ "emptyset",
+ "intersection",
+ "union",
+ "propersuperset",
+ "reflexsuperset",
+ "notsubset",
+ "propersubset",
+ "reflexsubset",
+ "element",
+ "notelement",
+ "angle",
+ "gradient",
+ "registerserif",
+ "copyrightserif",
+ "trademarkserif",
+ "product",
+ "radical",
+ "dotmath",
+ "logicalnot",
+ "logicaland",
+ "logicalor",
+ "arrowdblboth",
+ "arrowdblleft",
+ "arrowdblup",
+ "arrowdblright",
+ "arrowdbldown",
+ "lozenge",
+ "angleleft",
+ "registersans",
+ "copyrightsans",
+ "trademarksans",
+ "summation",
+ "parenlefttp",
+ "parenleftex",
+ "parenleftbt",
+ "bracketlefttp",
+ "bracketleftex",
+ "bracketleftbt",
+ "bracelefttp",
+ "braceleftmid",
+ "braceleftbt",
+ "braceex",
+ NULL,
+ "angleright",
+ "integral",
+ "integraltp",
+ "integralex",
+ "integralbt",
+ "parenrighttp",
+ "parenrightex",
+ "parenrightbt",
+ "bracketrighttp",
+ "bracketrightex",
+ "bracketrightbt",
+ "bracerighttp",
+ "bracerightmid",
+ "bracerightbt",
+ NULL
+};
+
+const char *zapfDingbatsEncoding[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "space",
+ "a1",
+ "a2",
+ "a202",
+ "a3",
+ "a4",
+ "a5",
+ "a119",
+ "a118",
+ "a117",
+ "a11",
+ "a12",
+ "a13",
+ "a14",
+ "a15",
+ "a16",
+ "a105",
+ "a17",
+ "a18",
+ "a19",
+ "a20",
+ "a21",
+ "a22",
+ "a23",
+ "a24",
+ "a25",
+ "a26",
+ "a27",
+ "a28",
+ "a6",
+ "a7",
+ "a8",
+ "a9",
+ "a10",
+ "a29",
+ "a30",
+ "a31",
+ "a32",
+ "a33",
+ "a34",
+ "a35",
+ "a36",
+ "a37",
+ "a38",
+ "a39",
+ "a40",
+ "a41",
+ "a42",
+ "a43",
+ "a44",
+ "a45",
+ "a46",
+ "a47",
+ "a48",
+ "a49",
+ "a50",
+ "a51",
+ "a52",
+ "a53",
+ "a54",
+ "a55",
+ "a56",
+ "a57",
+ "a58",
+ "a59",
+ "a60",
+ "a61",
+ "a62",
+ "a63",
+ "a64",
+ "a65",
+ "a66",
+ "a67",
+ "a68",
+ "a69",
+ "a70",
+ "a71",
+ "a72",
+ "a73",
+ "a74",
+ "a203",
+ "a75",
+ "a204",
+ "a76",
+ "a77",
+ "a78",
+ "a79",
+ "a81",
+ "a82",
+ "a83",
+ "a84",
+ "a97",
+ "a98",
+ "a99",
+ "a100",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "a101",
+ "a102",
+ "a103",
+ "a104",
+ "a106",
+ "a107",
+ "a108",
+ "a112",
+ "a111",
+ "a110",
+ "a109",
+ "a120",
+ "a121",
+ "a122",
+ "a123",
+ "a124",
+ "a125",
+ "a126",
+ "a127",
+ "a128",
+ "a129",
+ "a130",
+ "a131",
+ "a132",
+ "a133",
+ "a134",
+ "a135",
+ "a136",
+ "a137",
+ "a138",
+ "a139",
+ "a140",
+ "a141",
+ "a142",
+ "a143",
+ "a144",
+ "a145",
+ "a146",
+ "a147",
+ "a148",
+ "a149",
+ "a150",
+ "a151",
+ "a152",
+ "a153",
+ "a154",
+ "a155",
+ "a156",
+ "a157",
+ "a158",
+ "a159",
+ "a160",
+ "a161",
+ "a163",
+ "a164",
+ "a196",
+ "a165",
+ "a192",
+ "a166",
+ "a167",
+ "a168",
+ "a169",
+ "a170",
+ "a171",
+ "a172",
+ "a173",
+ "a162",
+ "a174",
+ "a175",
+ "a176",
+ "a177",
+ "a178",
+ "a179",
+ "a193",
+ "a180",
+ "a199",
+ "a181",
+ "a200",
+ "a182",
+ NULL,
+ "a201",
+ "a183",
+ "a184",
+ "a197",
+ "a185",
+ "a194",
+ "a198",
+ "a186",
+ "a195",
+ "a187",
+ "a188",
+ "a189",
+ "a190",
+ "a191",
+ NULL
+};
diff --git a/pdftops/FontEncodingTables.h b/pdftops/FontEncodingTables.h
new file mode 100644
index 000000000..a417b324e
--- /dev/null
+++ b/pdftops/FontEncodingTables.h
@@ -0,0 +1,20 @@
+//========================================================================
+//
+// FontEncodingTables.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FONTENCODINGTABLES_H
+#define FONTENCODINGTABLES_H
+
+extern const char *macRomanEncoding[];
+extern const char *macExpertEncoding[];
+extern const char *winAnsiEncoding[];
+extern const char *standardEncoding[];
+extern const char *expertEncoding[];
+extern const char *symbolEncoding[];
+extern const char *zapfDingbatsEncoding[];
+
+#endif
diff --git a/pdftops/FontFile.cxx b/pdftops/FontFile.cxx
new file mode 100644
index 000000000..edeeb21b0
--- /dev/null
+++ b/pdftops/FontFile.cxx
@@ -0,0 +1,4109 @@
+//========================================================================
+//
+// FontFile.cc
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include "gmem.h"
+#include "GHash.h"
+#include "Error.h"
+#include "GlobalParams.h"
+#include "CharCodeToUnicode.h"
+#include "FontEncodingTables.h"
+#include "FontFile.h"
+
+#include "CompactFontTables.h"
+
+//------------------------------------------------------------------------
+
+static inline const char *nextLine(const char *line, const char *end) {
+ while (line < end && *line != '\n' && *line != '\r')
+ ++line;
+ while (line < end && (*line == '\n' || *line == '\r'))
+ ++line;
+ return line;
+}
+
+static const char hexChars[17] = "0123456789ABCDEF";
+
+//------------------------------------------------------------------------
+// FontFile
+//------------------------------------------------------------------------
+
+FontFile::FontFile() {
+}
+
+FontFile::~FontFile() {
+}
+
+//------------------------------------------------------------------------
+// Type1FontFile
+//------------------------------------------------------------------------
+
+Type1FontFile::Type1FontFile(const char *file, int len) {
+ const char *line, *line1;
+ char *p, *p2;
+ GBool haveEncoding;
+ char buf[256];
+ char c;
+ int n, code, i, j;
+
+ name = NULL;
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ for (i = 0; i < 256; ++i) {
+ encoding[i] = NULL;
+ }
+ haveEncoding = gFalse;
+
+ for (i = 1, line = file;
+ i <= 100 && line < file + len && !haveEncoding;
+ ++i) {
+
+ // get font name
+ if (!strncmp(line, "/FontName", 9)) {
+ strncpy(buf, line, 255);
+ buf[255] = '\0';
+ if ((p = strchr(buf+9, '/')) &&
+ (p = strtok(p+1, " \t\n\r"))) {
+ name = copyString(p);
+ }
+ line = nextLine(line, file + len);
+
+ // get encoding
+ } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
+ for (j = 0; j < 256; ++j) {
+ if (standardEncoding[j]) {
+ encoding[j] = copyString(standardEncoding[j]);
+ }
+ }
+ haveEncoding = gTrue;
+ } else if (!strncmp(line, "/Encoding 256 array", 19)) {
+ for (j = 0; j < 300; ++j) {
+ line1 = nextLine(line, file + len);
+ if ((n = line1 - line) > 255) {
+ n = 255;
+ }
+ strncpy(buf, line, n);
+ buf[n] = '\0';
+ for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
+ if (!strncmp(p, "dup", 3)) {
+ for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+ for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
+ if (*p2) {
+ c = *p2;
+ *p2 = '\0';
+ if ((code = atoi(p)) < 256) {
+ *p2 = c;
+ for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+ if (*p == '/') {
+ ++p;
+ for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+ *p2 = '\0';
+ encoding[code] = copyString(p);
+ }
+ }
+ }
+ } else {
+ if (strtok(buf, " \t") &&
+ (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+ break;
+ }
+ }
+ line = line1;
+ }
+ //~ check for getinterval/putinterval junk
+ haveEncoding = gTrue;
+
+ } else {
+ line = nextLine(line, file + len);
+ }
+ }
+}
+
+Type1FontFile::~Type1FontFile() {
+ int i;
+
+ if (name) {
+ gfree(name);
+ }
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+}
+
+//------------------------------------------------------------------------
+// Type1CFontFile
+//------------------------------------------------------------------------
+
+struct Type1CTopDict {
+ int version;
+ int notice;
+ int copyright;
+ int fullName;
+ int familyName;
+ int weight;
+ int isFixedPitch;
+ double italicAngle;
+ double underlinePosition;
+ double underlineThickness;
+ int paintType;
+ int charstringType;
+ double fontMatrix[6];
+ int uniqueID;
+ double fontBBox[4];
+ double strokeWidth;
+ int charset;
+ int encoding;
+ int charStrings;
+ int privateSize;
+ int privateOffset;
+
+ //----- CIDFont entries
+ int registry;
+ int ordering;
+ int supplement;
+ int fdArrayOffset;
+ int fdSelectOffset;
+};
+
+struct Type1CPrivateDict {
+ GString *dictData;
+ int subrsOffset;
+ double defaultWidthX;
+ GBool defaultWidthXFP;
+ double nominalWidthX;
+ GBool nominalWidthXFP;
+};
+
+Type1CFontFile::Type1CFontFile(const char *fileA, int lenA) {
+ int nameIdxPos, namePos, nameLen;
+
+ file = (const Guchar *)fileA;
+ len = lenA;
+ name = NULL;
+ encoding = NULL;
+ ok = gFalse;
+
+ // some tools embed Type 1C fonts with an extra whitespace char at
+ // the beginning
+ if (len > 0 && file[0] != '\x01') {
+ ++file;
+ --len;
+ }
+
+ // make sure the header exists
+ if (len < 4) {
+ return;
+ }
+
+ // read name index (first font only)
+ nameIdxPos = file[2] & 0xff;
+ if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
+ return;
+ }
+ name = new GString((char *)&file[namePos], nameLen);
+
+ topDictIdxPos = getIndexEnd(nameIdxPos);
+ stringIdxPos = getIndexEnd(topDictIdxPos);
+ gsubrIdxPos = getIndexEnd(stringIdxPos);
+
+ ok = gTrue;
+}
+
+Type1CFontFile::~Type1CFontFile() {
+ int i;
+
+ delete name;
+ if (encoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+}
+
+const char *Type1CFontFile::getName() {
+ return name->getCString();
+}
+
+const char **Type1CFontFile::getEncoding() {
+ if (!encoding) {
+ readEncoding();
+ }
+ return (const char **)encoding;
+}
+
+void Type1CFontFile::readEncoding() {
+ char buf[256];
+ int idxPos, idxLen, pos;
+ int nGlyphs;
+ int nCodes, nRanges, nLeft, nSups;
+ Gushort *glyphNames;
+ int charset, enc, charstrings;
+ int encFormat;
+ int c, sid;
+ double x;
+ GBool isFP;
+ int key;
+ int i, j;
+
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ for (i = 0; i < 256; ++i) {
+ encoding[i] = NULL;
+ }
+
+ // read top dict (first font only)
+ if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
+ return;
+ }
+ charset = enc = charstrings = 0;
+ i = 0;
+ pos = idxPos;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
+ if (key == 0x0c) {
+ if (pos >= idxPos + idxLen) {
+ return;
+ }
+ key = (key << 8) | file[pos++];
+ }
+ if (key == 0x0f) { // charset
+ charset = (int)op[0];
+ } else if (key == 0x10) { // encoding
+ enc = (int)op[0];
+ } else if (key == 0x11) { // charstrings
+ charstrings = (int)op[0];
+ }
+ i = 0;
+ } else {
+ x = getNum(&pos, &isFP);
+ if (i < 48) {
+ op[i++] = x;
+ }
+ }
+ }
+
+ // get number of glyphs from charstrings index
+ nGlyphs = getIndexLen(charstrings);
+
+ // read charset (GID -> name mapping)
+ glyphNames = readCharset(charset, nGlyphs);
+
+ // read encoding (GID -> code mapping)
+ if (enc == 0) {
+ for (i = 0; i < 256; ++i) {
+ if (standardEncoding[i]) {
+ encoding[i] = copyString(standardEncoding[i]);
+ }
+ }
+ } else if (enc == 1) {
+ for (i = 0; i < 256; ++i) {
+ if (expertEncoding[i]) {
+ encoding[i] = copyString(expertEncoding[i]);
+ }
+ }
+ } else {
+ pos = enc;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ encFormat = file[pos++];
+ if ((encFormat & 0x7f) == 0) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nCodes = 1 + file[pos++];
+ if (nCodes > nGlyphs) {
+ nCodes = nGlyphs;
+ }
+ if (pos + nCodes - 1 > len) {
+ goto err0;
+ }
+ for (i = 1; i < nCodes; ++i) {
+ c = file[pos++];
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(glyphNames[i], buf));
+ }
+ } else if ((encFormat & 0x7f) == 1) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nRanges = file[pos++];
+ if (pos + 2 * nRanges > len) {
+ goto err0;
+ }
+ nCodes = 1;
+ for (i = 0; i < nRanges; ++i) {
+ c = file[pos++];
+ nLeft = file[pos++];
+ for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
+ if (c < 256) {
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(glyphNames[nCodes], buf));
+ }
+ ++nCodes;
+ ++c;
+ }
+ }
+ }
+ if (encFormat & 0x80) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nSups = file[pos++];
+ if (pos + nSups * 3 > len) {
+ goto err0;
+ }
+ for (i = 0; i < nSups; ++i) {
+ c = file[pos++];
+ sid = getWord(pos, 2);
+ pos += 2;
+ if (encoding[c]) {
+ gfree(encoding[c]);
+ }
+ encoding[c] = copyString(getString(sid, buf));
+ }
+ }
+ }
+
+ err0:
+ if (charset < 0 || charset > 2) {
+ gfree(glyphNames);
+ }
+}
+
+void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
+ void *outputStreamA) {
+ Type1CTopDict dict;
+ Type1CPrivateDict privateDict;
+ char buf[512], eBuf[256];
+ int idxPos, idxLen, pos;
+ int nGlyphs, nCodes, nRanges, nLeft, nSups;
+ Gushort *glyphNames;
+ int encFormat, nCharStrings;
+ int c, sid;
+ int i, j;
+
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+
+ // read top dict (first font only)
+ readTopDict(&dict);
+
+ // write header and font dictionary, up to encoding
+ (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ if (dict.version != 0) {
+ getString(dict.version, buf);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ // the dictionary needs room for 12 entries: the following 9, plus
+ // Private and CharStrings (in the eexec section) and FID (which is
+ // added by definefont)
+ (*outputFunc)(outputStream, "12 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
+ if (dict.version != 0) {
+ (*outputFunc)(outputStream, "/version (", 10);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.notice != 0) {
+ getString(dict.notice, buf);
+ (*outputFunc)(outputStream, "/Notice (", 9);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.copyright != 0) {
+ getString(dict.copyright, buf);
+ (*outputFunc)(outputStream, "/Copyright (", 12);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.fullName != 0) {
+ getString(dict.fullName, buf);
+ (*outputFunc)(outputStream, "/FullName (", 11);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.familyName != 0) {
+ getString(dict.familyName, buf);
+ (*outputFunc)(outputStream, "/FamilyName (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.weight != 0) {
+ getString(dict.weight, buf);
+ (*outputFunc)(outputStream, "/Weight (", 9);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") readonly def\n", 15);
+ }
+ if (dict.isFixedPitch) {
+ (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
+ } else {
+ (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
+ }
+ sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, " def\n", 5);
+ sprintf(buf, "/PaintType %d def\n", dict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
+ dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
+ dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
+ dict.fontBBox[0], dict.fontBBox[1],
+ dict.fontBBox[2], dict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (dict.uniqueID != 0) {
+ sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+
+ // get number of glyphs from charstrings index
+ nGlyphs = getIndexLen(dict.charStrings);
+
+ // read charset
+ glyphNames = readCharset(dict.charset, nGlyphs);
+
+ // read encoding (glyph -> code mapping), write Type 1 encoding
+ (*outputFunc)(outputStream, "/Encoding ", 10);
+ if (dict.encoding == 0) {
+ (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
+ } else {
+ (*outputFunc)(outputStream, "256 array\n", 10);
+ (*outputFunc)(outputStream,
+ "0 1 255 {1 index exch /.notdef put} for\n", 40);
+ if (dict.encoding == 1) {
+ for (i = 0; i < 256; ++i) {
+ if (expertEncoding[i]) {
+ sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ } else {
+ pos = dict.encoding;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ encFormat = file[pos++];
+ if ((encFormat & 0x7f) == 0) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nCodes = 1 + file[pos++];
+ if (nCodes > nGlyphs) {
+ nCodes = nGlyphs;
+ }
+ if (pos + nCodes - 1 > len) {
+ goto err0;
+ }
+ for (i = 1; i < nCodes; ++i) {
+ c = file[pos++];
+ sprintf(buf, "dup %d /", c);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ getString(glyphNames[i], buf);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, " put\n", 5);
+ }
+ } else if ((encFormat & 0x7f) == 1) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nRanges = file[pos++];
+ if (pos + 2 * nRanges > len) {
+ goto err0;
+ }
+ nCodes = 1;
+ for (i = 0; i < nRanges; ++i) {
+ c = file[pos++];
+ nLeft = file[pos++];
+ for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
+ sprintf(buf, "dup %d /", c);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ getString(glyphNames[nCodes], buf);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, " put\n", 5);
+ ++nCodes;
+ ++c;
+ }
+ }
+ }
+ if (encFormat & 0x80) {
+ if (pos >= len) {
+ goto err0;
+ }
+ nSups = file[pos++];
+ if (pos + nSups * 3 > len) {
+ goto err0;
+ }
+ for (i = 0; i < nSups; ++i) {
+ c = file[pos++];
+ sid = getWord(pos, 2);
+ pos += 2;
+ sprintf(buf, "dup %d /", c);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ getString(sid, buf);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, " put\n", 5);
+ }
+ }
+ err0:;
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ }
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ r1 = 55665;
+ line = 0;
+
+ // get private dictionary
+ eexecWrite("\x83\xca\x73\xd5");
+ eexecWrite("dup /Private 32 dict dup begin\n");
+ eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
+ eexecWrite("/ND {noaccess def} executeonly def\n");
+ eexecWrite("/NP {noaccess put} executeonly def\n");
+ eexecWrite("/MinFeature {16 16} def\n");
+ eexecWrite("/password 5839 def\n");
+ readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
+ eexecWrite(privateDict.dictData->getCString());
+ defaultWidthX = privateDict.defaultWidthX;
+ defaultWidthXFP = privateDict.defaultWidthXFP;
+ nominalWidthX = privateDict.nominalWidthX;
+ nominalWidthXFP = privateDict.nominalWidthXFP;
+
+ // set up subroutines
+ subrIdxPos = privateDict.subrsOffset;
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+ i = getIndexLen(subrIdxPos);
+ subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+
+ // get CharStrings
+ nCharStrings = getIndexLen(dict.charStrings);
+ sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
+ eexecWrite(eBuf);
+ for (i = 0; i < nCharStrings; ++i) {
+ if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
+ eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
+ }
+ }
+ eexecWrite("end\n");
+ eexecWrite("end\n");
+ eexecWrite("readonly put\n");
+ eexecWrite("noaccess put\n");
+ eexecWrite("dup /FontName get exch definefont pop\n");
+ eexecWrite("mark currentfile closefile\n");
+
+ // trailer
+ if (line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+
+ // clean up
+ delete privateDict.dictData;
+ if (dict.charset > 2) {
+ gfree(glyphNames);
+ }
+}
+
+void Type1CFontFile::convertToCIDType0(const char *psName,
+ FontFileOutputFunc outputFuncA,
+ void *outputStreamA) {
+ Type1CTopDict dict;
+ Type1CPrivateDict *privateDicts;
+ GString *charStrings;
+ int *charStringOffsets;
+ Gushort *charset;
+ int *cidMap;
+ Guchar *fdSelect;
+ int idxPos, idxLen, pos;
+ char buf[512], buf2[16];
+ int nGlyphs, nCIDs, gdBytes, nFDs;
+ int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
+ int key;
+ double x;
+ GBool isFP;
+ int i, j, k, n;
+
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+
+ (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
+
+ // read top dict (first font only)
+ readTopDict(&dict);
+
+ // read the FDArray dictionaries and Private dictionaries
+ if (dict.fdArrayOffset == 0) {
+ nFDs = 1;
+ privateDicts = (Type1CPrivateDict *)
+ gmalloc(nFDs * sizeof(Type1CPrivateDict));
+ privateDicts[0].dictData = new GString();
+ privateDicts[0].subrsOffset = 0;
+ privateDicts[0].defaultWidthX = 0;
+ privateDicts[0].defaultWidthXFP = gFalse;
+ privateDicts[0].nominalWidthX = 0;
+ privateDicts[0].nominalWidthXFP = gFalse;
+ } else {
+ if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
+ goto err0;
+ }
+ privateDicts = (Type1CPrivateDict *)
+ gmalloc(nFDs * sizeof(Type1CPrivateDict));
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ }
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
+ goto err1;
+ }
+ pos = idxPos;
+ j = 0;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
+ if (key == 0x0c) {
+ if (pos >= idxPos + idxLen) {
+ goto err1;
+ }
+ key = (key << 8) | file[pos++];
+ }
+ if (key == 0x0012) {
+ readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
+ }
+ j = 0;
+ } else {
+ x = getNum(&pos, &isFP);
+ if (j < 48) {
+ op[j] = x;
+ fp[j++] = isFP;
+ }
+ }
+ }
+ if (!privateDicts[i].dictData) {
+ privateDicts[i].dictData = new GString();
+ privateDicts[i].subrsOffset = 0;
+ privateDicts[i].defaultWidthX = 0;
+ privateDicts[i].defaultWidthXFP = gFalse;
+ privateDicts[i].nominalWidthX = 0;
+ privateDicts[i].nominalWidthXFP = gFalse;
+ }
+ }
+ }
+
+ // get the glyph count
+ if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
+ goto err1;
+ }
+
+ // read the FDSelect table
+ fdSelect = (Guchar *)gmalloc(nGlyphs);
+ if (dict.fdSelectOffset == 0) {
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ } else {
+ pos = dict.fdSelectOffset;
+ if (pos < 0 || pos >= len) {
+ goto err2;
+ }
+ fdSelectFmt = file[pos++];
+ if (fdSelectFmt == 0) {
+ if (pos + nGlyphs > len) {
+ goto err2;
+ }
+ memcpy(fdSelect, file + pos, nGlyphs);
+ } else if (fdSelectFmt == 3) {
+ if (pos + 4 > len) {
+ goto err2;
+ }
+ nRanges = getWord(pos, 2);
+ pos += 2;
+ gid0 = getWord(pos, 2);
+ pos += 2;
+ if (pos + nRanges * 3 > len) {
+ goto err2;
+ }
+ for (i = 1; i <= nRanges; ++i) {
+ fd = file[pos++];
+ gid1 = getWord(pos, 2);
+ pos += 2;
+ for (j = gid0; j < gid1; ++j) {
+ fdSelect[j] = fd;
+ }
+ gid0 = gid1;
+ }
+ } else {
+ error(-1, "Unknown FDSelect table format in CID font");
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ }
+ }
+
+ // read the charset, compute the CID-to-GID mapping
+ charset = readCharset(dict.charset, nGlyphs);
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+
+ // set up global subroutines
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+
+ // build the charstrings
+ charStrings = new GString();
+ charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ charStringOffsets[i] = charStrings->getLength();
+ if (cidMap[i] >= 0) {
+ if ((idxPos = getIndexValPos(dict.charStrings,
+ cidMap[i], &idxLen)) >= 0) {
+ j = fdSelect[cidMap[i]];
+ defaultWidthX = privateDicts[j].defaultWidthX;
+ defaultWidthXFP = privateDicts[j].defaultWidthXFP;
+ nominalWidthX = privateDicts[j].nominalWidthX;
+ nominalWidthXFP = privateDicts[j].nominalWidthXFP;
+ subrIdxPos = privateDicts[j].subrsOffset;
+ k = getIndexLen(subrIdxPos);
+ subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
+ cvtGlyph(idxPos, idxLen, gTrue);
+ charStrings->append(charBuf);
+ delete charBuf;
+ }
+ }
+ }
+ charStringOffsets[nCIDs] = charStrings->getLength();
+
+ // compute gdBytes = number of bytes needed for charstring offsets
+ // (offset size needs to account for the charstring offset table,
+ // with a worst case of five bytes per entry, plus the charstrings
+ // themselves)
+ i = (nCIDs + 1) * 5 + charStrings->getLength();
+ if (i < 0x100) {
+ gdBytes = 1;
+ } else if (i < 0x10000) {
+ gdBytes = 2;
+ } else if (i < 0x1000000) {
+ gdBytes = 3;
+ } else {
+ gdBytes = 4;
+ }
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ if (dict.registry > 0 && dict.ordering > 0) {
+ getString(dict.registry, buf);
+ (*outputFunc)(outputStream, " /Registry (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ getString(dict.ordering, buf);
+ (*outputFunc)(outputStream, " /Ordering (", 13);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, ") def\n", 6);
+ } else {
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ }
+ sprintf(buf, " /Supplement %d def\n", dict.supplement);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "end def\n", 8);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+ dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
+ dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
+ dict.fontBBox[0], dict.fontBBox[1],
+ dict.fontBBox[2], dict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
+ (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
+ (*outputFunc)(outputStream, "end def\n", 8);
+
+ // CIDFont-specific entries
+ sprintf(buf, "/CIDCount %d def\n", nCIDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
+ sprintf(buf, "/GDBytes %d def\n", gdBytes);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
+ if (dict.paintType != 0) {
+ sprintf(buf, "/PaintType %d def\n", dict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+
+ // FDArray entry
+ sprintf(buf, "/FDArray %d array\n", nFDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ for (i = 0; i < nFDs; ++i) {
+ sprintf(buf, "dup %d 10 dict begin\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/PaintType %d def\n", dict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
+ (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
+ privateDicts[i].dictData->getLength());
+ (*outputFunc)(outputStream, "currentdict end def\n", 20);
+ (*outputFunc)(outputStream, "currentdict end put\n", 20);
+ }
+ (*outputFunc)(outputStream, "def\n", 4);
+
+ // start the binary section
+ offset = (nCIDs + 1) * (1 + gdBytes);
+ sprintf(buf, "(Hex) %d StartData\n",
+ offset + charStrings->getLength());
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // write the charstring offset (CIDMap) table
+ for (i = 0; i <= nCIDs; i += 6) {
+ for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
+ if (i+j < nCIDs && cidMap[i+j] >= 0) {
+ buf[0] = (char)fdSelect[cidMap[i+j]];
+ } else {
+ buf[0] = (char)0;
+ }
+ n = offset + charStringOffsets[i+j];
+ for (k = gdBytes; k >= 1; --k) {
+ buf[k] = (char)(n & 0xff);
+ n >>= 8;
+ }
+ for (k = 0; k <= gdBytes; ++k) {
+ sprintf(buf2, "%02x", buf[k] & 0xff);
+ (*outputFunc)(outputStream, buf2, 2);
+ }
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ // write the charstring data
+ n = charStrings->getLength();
+ for (i = 0; i < n; i += 32) {
+ for (j = 0; j < 32 && i+j < n; ++j) {
+ sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (i + 32 >= n) {
+ (*outputFunc)(outputStream, ">", 1);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+
+ gfree(charStringOffsets);
+ delete charStrings;
+ gfree(cidMap);
+ gfree(charset);
+ err2:
+ gfree(fdSelect);
+ err1:
+ for (i = 0; i < nFDs; ++i) {
+ if (privateDicts[i].dictData) {
+ delete privateDicts[i].dictData;
+ }
+ }
+ gfree(privateDicts);
+ err0:;
+}
+
+void Type1CFontFile::convertToType0(const char *psName,
+ FontFileOutputFunc outputFuncA,
+ void *outputStreamA) {
+ Type1CTopDict dict;
+ Type1CPrivateDict *privateDicts;
+ Gushort *charset;
+ int *cidMap;
+ Guchar *fdSelect;
+ int idxPos, idxLen, pos;
+ char buf[512];
+ char eBuf[256];
+ int nGlyphs, nCIDs, nFDs;
+ int fdSelectFmt, nRanges, gid0, gid1, fd;
+ int key;
+ double x;
+ GBool isFP;
+ int i, j;
+
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+
+ // read top dict (first font only)
+ readTopDict(&dict);
+
+ // read the FDArray dictionaries and Private dictionaries
+ if (dict.fdArrayOffset == 0) {
+ nFDs = 1;
+ privateDicts = (Type1CPrivateDict *)
+ gmalloc(nFDs * sizeof(Type1CPrivateDict));
+ privateDicts[0].dictData = new GString();
+ privateDicts[0].subrsOffset = 0;
+ privateDicts[0].defaultWidthX = 0;
+ privateDicts[0].defaultWidthXFP = gFalse;
+ privateDicts[0].nominalWidthX = 0;
+ privateDicts[0].nominalWidthXFP = gFalse;
+ } else {
+ if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
+ goto err0;
+ }
+ privateDicts = (Type1CPrivateDict *)
+ gmalloc(nFDs * sizeof(Type1CPrivateDict));
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ }
+ for (i = 0; i < nFDs; ++i) {
+ privateDicts[i].dictData = NULL;
+ if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
+ goto err1;
+ }
+ pos = idxPos;
+ j = 0;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
+ if (key == 0x0c) {
+ if (pos >= idxPos + idxLen) {
+ goto err1;
+ }
+ key = (key << 8) | file[pos++];
+ }
+ if (key == 0x0012) {
+ readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
+ }
+ j = 0;
+ } else {
+ x = getNum(&pos, &isFP);
+ if (j < 48) {
+ op[j] = x;
+ fp[j++] = isFP;
+ }
+ }
+ }
+ if (!privateDicts[i].dictData) {
+ privateDicts[i].dictData = new GString();
+ privateDicts[i].subrsOffset = 0;
+ privateDicts[i].defaultWidthX = 0;
+ privateDicts[i].defaultWidthXFP = gFalse;
+ privateDicts[i].nominalWidthX = 0;
+ privateDicts[i].nominalWidthXFP = gFalse;
+ }
+ }
+ }
+
+ // get the glyph count
+ if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
+ goto err1;
+ }
+
+ // read the FDSelect table
+ fdSelect = (Guchar *)gmalloc(nGlyphs);
+ if (dict.fdSelectOffset == 0) {
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ } else {
+ pos = dict.fdSelectOffset;
+ if (pos < 0 || pos >= len) {
+ goto err2;
+ }
+ fdSelectFmt = file[pos++];
+ if (fdSelectFmt == 0) {
+ if (pos + nGlyphs > len) {
+ goto err2;
+ }
+ memcpy(fdSelect, file + pos, nGlyphs);
+ } else if (fdSelectFmt == 3) {
+ if (pos + 4 > len) {
+ goto err2;
+ }
+ nRanges = getWord(pos, 2);
+ pos += 2;
+ gid0 = getWord(pos, 2);
+ pos += 2;
+ if (pos + nRanges * 3 > len) {
+ goto err2;
+ }
+ for (i = 1; i <= nRanges; ++i) {
+ fd = file[pos++];
+ gid1 = getWord(pos, 2);
+ pos += 2;
+ for (j = gid0; j < gid1; ++j) {
+ fdSelect[j] = fd;
+ }
+ gid0 = gid1;
+ }
+ } else {
+ error(-1, "Unknown FDSelect table format in CID font");
+ for (i = 0; i < nGlyphs; ++i) {
+ fdSelect[i] = 0;
+ }
+ }
+ }
+
+ // read the charset, compute the CID-to-GID mapping
+ charset = readCharset(dict.charset, nGlyphs);
+ nCIDs = 0;
+ for (i = 0; i < nGlyphs; ++i) {
+ if (charset[i] >= nCIDs) {
+ nCIDs = charset[i] + 1;
+ }
+ }
+ cidMap = (int *)gmalloc(nCIDs * sizeof(int));
+ for (i = 0; i < nCIDs; ++i) {
+ cidMap[i] = -1;
+ }
+ for (i = 0; i < nGlyphs; ++i) {
+ cidMap[charset[i]] = i;
+ }
+
+ // set up global subroutines
+ i = getIndexLen(gsubrIdxPos);
+ gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
+
+ // write the descendant Type 1 fonts
+ for (i = 0; i < nCIDs; i += 256) {
+
+ //~ this assumes that all CIDs in this block have the same FD --
+ //~ to handle multiple FDs correctly, need to somehow divide the
+ //~ font up by FD
+ fd = 0;
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ fd = fdSelect[cidMap[i+j]];
+ break;
+ }
+ }
+
+ // font dictionary (unencrypted section)
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x def\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
+ sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
+ dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
+ dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
+ dict.fontBBox[0], dict.fontBBox[1],
+ dict.fontBBox[2], dict.fontBBox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, "/PaintType %d def\n", dict.paintType);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (dict.paintType != 0) {
+ sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ sprintf(buf, "dup %d /c%02x put\n", j, j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (j < 256) {
+ sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "currentdict end\n", 16);
+
+ // start the binary section
+ (*outputFunc)(outputStream, "currentfile eexec\n", 18);
+ r1 = 55665;
+ line = 0;
+
+ // start the private dictionary
+ eexecWrite("\x83\xca\x73\xd5");
+ eexecWrite("dup /Private 32 dict dup begin\n");
+ eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
+ eexecWrite("/ND {noaccess def} executeonly def\n");
+ eexecWrite("/NP {noaccess put} executeonly def\n");
+ eexecWrite("/MinFeature {16 16} def\n");
+ eexecWrite("/password 5839 def\n");
+ eexecWrite(privateDicts[fd].dictData->getCString());
+ defaultWidthX = privateDicts[fd].defaultWidthX;
+ defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
+ nominalWidthX = privateDicts[fd].nominalWidthX;
+ nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
+
+ // set up the subroutines
+ subrIdxPos = privateDicts[fd].subrsOffset;
+ j = getIndexLen(subrIdxPos);
+ subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
+
+ // start the CharStrings
+ sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
+ eexecWrite(eBuf);
+
+ // write the .notdef CharString
+ if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
+ eexecCvtGlyph(".notdef", idxPos, idxLen);
+ }
+
+ // write the CharStrings
+ for (j = 0; j < 256 && i+j < nCIDs; ++j) {
+ if (cidMap[i+j] >= 0) {
+ if ((idxPos = getIndexValPos(dict.charStrings,
+ cidMap[i+j], &idxLen)) >= 0) {
+ sprintf(buf, "c%02x", j);
+ eexecCvtGlyph(buf, idxPos, idxLen);
+ }
+ }
+ }
+ eexecWrite("end\n");
+ eexecWrite("end\n");
+ eexecWrite("readonly put\n");
+ eexecWrite("noaccess put\n");
+ eexecWrite("dup /FontName get exch definefont pop\n");
+ eexecWrite("mark currentfile closefile\n");
+
+ // trailer
+ if (line > 0) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ for (j = 0; j < 8; ++j) {
+ (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
+ }
+ (*outputFunc)(outputStream, "cleartomark\n", 12);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < nCIDs; i += 256) {
+ sprintf(buf, "%d\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < nCIDs; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, psName, strlen(psName));
+ sprintf(buf, "_%02x findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+
+ // clean up
+ gfree(cidMap);
+ gfree(charset);
+ err2:
+ gfree(fdSelect);
+ err1:
+ for (i = 0; i < nFDs; ++i) {
+ if (privateDicts[i].dictData) {
+ delete privateDicts[i].dictData;
+ }
+ }
+ gfree(privateDicts);
+ err0:;
+}
+
+void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
+ int idxPos, idxLen, pos;
+ double x;
+ GBool isFP;
+ int key;
+ int i;
+
+ dict->version = 0;
+ dict->notice = 0;
+ dict->copyright = 0;
+ dict->fullName = 0;
+ dict->familyName = 0;
+ dict->weight = 0;
+ dict->isFixedPitch = 0;
+ dict->italicAngle = 0;
+ dict->underlinePosition = -100;
+ dict->underlineThickness = 50;
+ dict->paintType = 0;
+ dict->charstringType = 2;
+ dict->fontMatrix[0] = 0.001;
+ dict->fontMatrix[1] = 0;
+ dict->fontMatrix[2] = 0;
+ dict->fontMatrix[3] = 0.001;
+ dict->fontMatrix[4] = 0;
+ dict->fontMatrix[5] = 0;
+ dict->uniqueID = 0;
+ dict->fontBBox[0] = 0;
+ dict->fontBBox[1] = 0;
+ dict->fontBBox[2] = 0;
+ dict->fontBBox[3] = 0;
+ dict->strokeWidth = 0;
+ dict->charset = 0;
+ dict->encoding = 0;
+ dict->charStrings = 0;
+ dict->privateSize = 0;
+ dict->privateOffset = 0;
+ dict->registry = 0;
+ dict->ordering = 0;
+ dict->supplement = 0;
+ dict->fdArrayOffset = 0;
+ dict->fdSelectOffset = 0;
+ if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
+ return;
+ }
+ i = 0;
+ pos = idxPos;
+ while (pos < idxPos + idxLen) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
+ if (key == 0x0c) {
+ if (pos >= idxPos + idxLen) {
+ break;
+ }
+ key = (key << 8) | file[pos++];
+ }
+ switch (key) {
+ case 0x0000: dict->version = (int)op[0]; break;
+ case 0x0001: dict->notice = (int)op[0]; break;
+ case 0x0c00: dict->copyright = (int)op[0]; break;
+ case 0x0002: dict->fullName = (int)op[0]; break;
+ case 0x0003: dict->familyName = (int)op[0]; break;
+ case 0x0004: dict->weight = (int)op[0]; break;
+ case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
+ case 0x0c02: dict->italicAngle = op[0]; break;
+ case 0x0c03: dict->underlinePosition = op[0]; break;
+ case 0x0c04: dict->underlineThickness = op[0]; break;
+ case 0x0c05: dict->paintType = (int)op[0]; break;
+ case 0x0c06: dict->charstringType = (int)op[0]; break;
+ case 0x0c07: dict->fontMatrix[0] = op[0];
+ dict->fontMatrix[1] = op[1];
+ dict->fontMatrix[2] = op[2];
+ dict->fontMatrix[3] = op[3];
+ dict->fontMatrix[4] = op[4];
+ dict->fontMatrix[5] = op[5]; break;
+ case 0x000d: dict->uniqueID = (int)op[0]; break;
+ case 0x0005: dict->fontBBox[0] = op[0];
+ dict->fontBBox[1] = op[1];
+ dict->fontBBox[2] = op[2];
+ dict->fontBBox[3] = op[3]; break;
+ case 0x0c08: dict->strokeWidth = op[0]; break;
+ case 0x000f: dict->charset = (int)op[0]; break;
+ case 0x0010: dict->encoding = (int)op[0]; break;
+ case 0x0011: dict->charStrings = (int)op[0]; break;
+ case 0x0012: dict->privateSize = (int)op[0];
+ dict->privateOffset = (int)op[1]; break;
+ case 0x0c1e: dict->registry = (int)op[0];
+ dict->ordering = (int)op[1];
+ dict->supplement = (int)op[2]; break;
+ case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
+ case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
+ }
+ i = 0;
+ } else {
+ x = getNum(&pos, &isFP);
+ if (i < 48) {
+ op[i] = x;
+ fp[i++] = isFP;
+ }
+ }
+ }
+}
+
+void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
+ int offset, int size) {
+ int pos;
+ char eBuf[256];
+ int key;
+ double x;
+ GBool isFP;
+ int i;
+
+ privateDict->dictData = new GString();
+ privateDict->subrsOffset = 0;
+ privateDict->defaultWidthX = 0;
+ privateDict->defaultWidthXFP = gFalse;
+ privateDict->nominalWidthX = 0;
+ privateDict->nominalWidthXFP = gFalse;
+ if (offset < 0 || offset + size > len) {
+ return;
+ }
+ pos = offset;
+ i = 0;
+ while (pos < offset + size) {
+ if (file[pos] <= 27 || file[pos] == 31) {
+ key = file[pos++];
+ if (key == 0x0c) {
+ if (pos >= offset + size) {
+ break;
+ }
+ key = (key << 8) | file[pos++];
+ }
+ switch (key) {
+ case 0x0006:
+ getDeltaInt(eBuf, "BlueValues", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0007:
+ getDeltaInt(eBuf, "OtherBlues", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0008:
+ getDeltaInt(eBuf, "FamilyBlues", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0009:
+ getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c09:
+ sprintf(eBuf, "/BlueScale %g def\n", op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0a:
+ sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0b:
+ sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x000a:
+ sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x000b:
+ sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0c:
+ getDeltaReal(eBuf, "StemSnapH", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0d:
+ getDeltaReal(eBuf, "StemSnapV", op, i);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0e:
+ sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c0f:
+ sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c11:
+ sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c12:
+ sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
+ privateDict->dictData->append(eBuf);
+ break;
+ case 0x0c13:
+ error(-1, "Got Type 1C InitialRandomSeed");
+ break;
+ case 0x0013:
+ privateDict->subrsOffset = offset + (int)op[0];
+ break;
+ case 0x0014:
+ privateDict->defaultWidthX = op[0];
+ privateDict->defaultWidthXFP = fp[0];
+ break;
+ case 0x0015:
+ privateDict->nominalWidthX = op[0];
+ privateDict->nominalWidthXFP = fp[0];
+ break;
+ default:
+ error(-1, "Unknown Type 1C private dict entry %04x", key);
+ break;
+ }
+ i = 0;
+ } else {
+ x = getNum(&pos, &isFP);
+ if (i < 48) {
+ op[i] = x;
+ fp[i++] = isFP;
+ }
+ }
+ }
+}
+
+Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
+ Gushort *glyphNames;
+ int pos;
+ int charsetFormat, c;
+ int nLeft, i, j;
+
+ if (charset == 0) {
+ glyphNames = type1CISOAdobeCharset;
+ } else if (charset == 1) {
+ glyphNames = type1CExpertCharset;
+ } else if (charset == 2) {
+ glyphNames = type1CExpertSubsetCharset;
+ } else {
+ glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
+ for (i = 0; i < nGlyphs; ++i) {
+ glyphNames[i] = 0;
+ }
+ pos = charset;
+ if (pos < 0 || pos >= len) {
+ goto err0;
+ }
+ charsetFormat = file[pos++];
+ if (charsetFormat == 0) {
+ if (pos + (nGlyphs - 1) * 2 >= len) {
+ goto err0;
+ }
+ for (i = 1; i < nGlyphs; ++i) {
+ glyphNames[i] = getWord(pos, 2);
+ pos += 2;
+ }
+ } else if (charsetFormat == 1) {
+ i = 1;
+ while (i < nGlyphs) {
+ if (pos + 3 > len) {
+ goto err0;
+ }
+ c = getWord(pos, 2);
+ pos += 2;
+ nLeft = file[pos++];
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ glyphNames[i++] = c++;
+ }
+ }
+ } else if (charsetFormat == 2) {
+ i = 1;
+ while (i < nGlyphs) {
+ if (pos + 4 > len) {
+ goto err0;
+ }
+ c = getWord(pos, 2);
+ pos += 2;
+ nLeft = getWord(pos, 2);
+ pos += 2;
+ for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
+ glyphNames[i++] = c++;
+ }
+ }
+ }
+ }
+ err0:
+ return glyphNames;
+}
+
+void Type1CFontFile::eexecWrite(const char *s) {
+ Guchar *p;
+ Guchar x;
+
+ for (p = (Guchar *)s; *p; ++p) {
+ x = *p ^ (r1 >> 8);
+ r1 = (x + r1) * 52845 + 22719;
+ (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
+ (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
+ line += 2;
+ if (line == 64) {
+ (*outputFunc)(outputStream, "\n", 1);
+ line = 0;
+ }
+ }
+}
+
+void Type1CFontFile::eexecCvtGlyph(const char *glyphName, int pos, int n) {
+ char eBuf[256];
+
+ cvtGlyph(pos, n, gTrue);
+ sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
+ eexecWrite(eBuf);
+ eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
+ eexecWrite(" ND\n");
+ delete charBuf;
+}
+
+void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
+ int x;
+ int subrPos, subrLen;
+ double d, dx, dy;
+ GBool dFP;
+ Gushort r2;
+ Guchar byte;
+ int i, k;
+
+ if (pos < 0 || pos + n > len) {
+ return;
+ }
+
+ if (top) {
+ charBuf = new GString();
+ charBuf->append((char)73);
+ charBuf->append((char)58);
+ charBuf->append((char)147);
+ charBuf->append((char)134);
+ nOps = 0;
+ nHints = 0;
+ firstOp = gTrue;
+ }
+
+ i = pos;
+ while (i < pos + n) {
+ if (file[i] == 12) {
+ if (i + 2 > pos + n) {
+ break;
+ }
+ switch (file[i+1]) {
+ case 0: // dotsection (should be Type 1 only?)
+ // ignored
+ break;
+ case 34: // hflex
+ if (nOps != 7) {
+ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpOp1(8);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[5], fp[5]);
+ eexecDumpNum(-op[2], fp[2]);
+ eexecDumpNum(op[6], fp[6]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpOp1(8);
+ break;
+ case 35: // flex
+ if (nOps != 13) {
+ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpNum(op[5], fp[5]);
+ eexecDumpOp1(8);
+ eexecDumpNum(op[6], fp[6]);
+ eexecDumpNum(op[7], fp[7]);
+ eexecDumpNum(op[8], fp[8]);
+ eexecDumpNum(op[9], fp[9]);
+ eexecDumpNum(op[10], fp[10]);
+ eexecDumpNum(op[11], fp[11]);
+ eexecDumpOp1(8);
+ break;
+ case 36: // hflex1
+ if (nOps != 9) {
+ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpOp1(8);
+ eexecDumpNum(op[5], fp[5]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[6], fp[6]);
+ eexecDumpNum(op[7], fp[7]);
+ eexecDumpNum(op[8], fp[8]);
+ eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
+ eexecDumpOp1(8);
+ break;
+ case 37: // flex1
+ if (nOps != 11) {
+ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpNum(op[5], fp[5]);
+ eexecDumpOp1(8);
+ eexecDumpNum(op[6], fp[6]);
+ eexecDumpNum(op[7], fp[7]);
+ eexecDumpNum(op[8], fp[8]);
+ eexecDumpNum(op[9], fp[9]);
+ dx = op[0] + op[2] + op[4] + op[6] + op[8];
+ dy = op[1] + op[3] + op[5] + op[7] + op[9];
+ if (fabs(dx) > fabs(dy)) {
+ eexecDumpNum(op[10], fp[10]);
+ eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
+ } else {
+ eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
+ eexecDumpNum(op[10], fp[10]);
+ }
+ eexecDumpOp1(8);
+ break;
+ case 3: // and
+ case 4: // or
+ case 5: // not
+ case 8: // store
+ case 9: // abs
+ case 10: // add
+ case 11: // sub
+ case 12: // div
+ case 13: // load
+ case 14: // neg
+ case 15: // eq
+ case 18: // drop
+ case 20: // put
+ case 21: // get
+ case 22: // ifelse
+ case 23: // random
+ case 24: // mul
+ case 26: // sqrt
+ case 27: // dup
+ case 28: // exch
+ case 29: // index
+ case 30: // roll
+ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
+ break;
+ default:
+ error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
+ break;
+ }
+ i += 2;
+ nOps = 0;
+ } else if (file[i] == 19) { // hintmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
+ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ i += 1 + ((nHints + 7) >> 3);
+ nOps = 0;
+ } else if (file[i] == 20) { // cntrmask
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps > 0) {
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
+ nOps);
+ }
+ nHints += nOps / 2;
+ }
+ i += 1 + ((nHints + 7) >> 3);
+ nOps = 0;
+ } else if (file[i] == 28) {
+ if (i + 3 > len) {
+ break;
+ }
+ x = (file[i+1] << 8) + file[i+2];
+ if (x & 0x8000) {
+ x |= -1 << 15;
+ }
+ if (nOps < 48) {
+ fp[nOps] = gFalse;
+ op[nOps++] = x;
+ }
+ i += 3;
+ } else if (file[i] == 10) { // callsubr
+ if (nOps >= 1) {
+ k = subrBias + (int)op[nOps - 1];
+ --nOps;
+ if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
+ cvtGlyph(subrPos, subrLen, gFalse);
+ }
+ } else {
+ error(-1, "Too few args to Type 2 callsubr");
+ }
+ // don't clear the stack
+ ++i;
+ } else if (file[i] == 29) { // callgsubr
+ if (nOps >= 1) {
+ k = gsubrBias + (int)op[nOps - 1];
+ --nOps;
+ if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
+ cvtGlyph(subrPos, subrLen, gFalse);
+ }
+ } else {
+ error(-1, "Too few args to Type 2 callgsubr");
+ }
+ // don't clear the stack
+ ++i;
+ } else if (file[i] == 11) { // return
+ // don't clear the stack
+ ++i;
+ } else if (file[i] <= 31) {
+ switch (file[i]) {
+ case 4: // vmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2);
+ firstOp = gFalse;
+ }
+ if (nOps != 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpOp1(4);
+ break;
+ case 5: // rlineto
+ if (nOps < 2 || nOps % 2 != 0) {
+ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
+ }
+ for (k = 0; k < nOps; k += 2) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpOp1(5);
+ }
+ break;
+ case 6: // hlineto
+ if (nOps < 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpOp1((k & 1) ? 7 : 6);
+ }
+ break;
+ case 7: // vlineto
+ if (nOps < 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
+ }
+ for (k = 0; k < nOps; ++k) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpOp1((k & 1) ? 6 : 7);
+ }
+ break;
+ case 8: // rrcurveto
+ if (nOps < 6 || nOps % 6 != 0) {
+ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
+ }
+ for (k = 0; k < nOps; k += 6) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ eexecDumpNum(op[k+5], fp[k+5]);
+ eexecDumpOp1(8);
+ }
+ break;
+ case 14: // endchar / seac
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 1 || nOps == 5);
+ firstOp = gFalse;
+ }
+ if (nOps == 4) {
+ eexecDumpNum(0, 0);
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpOp2(6);
+ } else if (nOps == 0) {
+ eexecDumpOp1(14);
+ } else {
+ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
+ }
+ break;
+ case 21: // rmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 3);
+ firstOp = gFalse;
+ }
+ if (nOps != 2) {
+ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpOp1(21);
+ break;
+ case 22: // hmoveto
+ if (firstOp) {
+ cvtGlyphWidth(nOps == 2);
+ firstOp = gFalse;
+ }
+ if (nOps != 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
+ }
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpOp1(22);
+ break;
+ case 24: // rcurveline
+ if (nOps < 8 || (nOps - 2) % 6 != 0) {
+ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
+ }
+ for (k = 0; k < nOps - 2; k += 6) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ eexecDumpNum(op[k+5], fp[k+5]);
+ eexecDumpOp1(8);
+ }
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k]);
+ eexecDumpOp1(5);
+ break;
+ case 25: // rlinecurve
+ if (nOps < 8 || (nOps - 6) % 2 != 0) {
+ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
+ }
+ for (k = 0; k < nOps - 6; k += 2) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k]);
+ eexecDumpOp1(5);
+ }
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ eexecDumpNum(op[k+5], fp[k+5]);
+ eexecDumpOp1(8);
+ break;
+ case 26: // vvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
+ }
+ if (nOps % 2 == 1) {
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpOp1(8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k < nOps; k += 4) {
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpOp1(8);
+ }
+ break;
+ case 27: // hhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
+ }
+ if (nOps % 2 == 1) {
+ eexecDumpNum(op[1], fp[1]);
+ eexecDumpNum(op[0], fp[0]);
+ eexecDumpNum(op[2], fp[2]);
+ eexecDumpNum(op[3], fp[3]);
+ eexecDumpNum(op[4], fp[4]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpOp1(8);
+ k = 5;
+ } else {
+ k = 0;
+ }
+ for (; k < nOps; k += 4) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpOp1(8);
+ }
+ break;
+ case 30: // vhcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
+ }
+ for (k = 0; k < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpOp1(30);
+ } else {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpOp1(31);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ } else {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ }
+ eexecDumpOp1(8);
+ }
+ break;
+ case 31: // hvcurveto
+ if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
+ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
+ }
+ for (k = 0; k < nOps && k != nOps-5; k += 4) {
+ if (k % 8 == 0) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpOp1(31);
+ } else {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpOp1(30);
+ }
+ }
+ if (k == nOps-5) {
+ if (k % 8 == 0) {
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ } else {
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(op[k], fp[k]);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ eexecDumpNum(op[k+2], fp[k+2]);
+ eexecDumpNum(op[k+3], fp[k+3]);
+ eexecDumpNum(op[k+4], fp[k+4]);
+ }
+ eexecDumpOp1(8);
+ }
+ break;
+ case 1: // hstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
+ }
+ d = 0;
+ dFP = gFalse;
+ for (k = 0; k < nOps; k += 2) {
+ if (op[k+1] < 0) {
+ d += op[k] + op[k+1];
+ dFP |= fp[k] | fp[k+1];
+ eexecDumpNum(d, dFP);
+ eexecDumpNum(-op[k+1], fp[k+1]);
+ } else {
+ d += op[k];
+ dFP |= fp[k];
+ eexecDumpNum(d, dFP);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ d += op[k+1];
+ dFP |= fp[k+1];
+ }
+ eexecDumpOp1(1);
+ }
+ nHints += nOps / 2;
+ break;
+ case 3: // vstem
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
+ }
+ d = 0;
+ dFP = gFalse;
+ for (k = 0; k < nOps; k += 2) {
+ if (op[k+1] < 0) {
+ d += op[k] + op[k+1];
+ dFP |= fp[k] | fp[k+1];
+ eexecDumpNum(d, dFP);
+ eexecDumpNum(-op[k+1], fp[k+1]);
+ } else {
+ d += op[k];
+ dFP |= fp[k];
+ eexecDumpNum(d, dFP);
+ eexecDumpNum(op[k+1], fp[k+1]);
+ d += op[k+1];
+ dFP |= fp[k+1];
+ }
+ eexecDumpOp1(3);
+ }
+ nHints += nOps / 2;
+ break;
+ case 15: // (obsolete)
+ // this op is ignored, but we need the glyph width
+ if (firstOp) {
+ cvtGlyphWidth(nOps > 0);
+ firstOp = gFalse;
+ }
+ break;
+ case 18: // hstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ break;
+ case 23: // vstemhm
+ // ignored
+ if (firstOp) {
+ cvtGlyphWidth(nOps & 1);
+ firstOp = gFalse;
+ }
+ if (nOps & 1) {
+ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
+ }
+ nHints += nOps / 2;
+ break;
+ case 16: // blend
+ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
+ break;
+ default:
+ error(-1, "Illegal Type 2 charstring op: %d", file[i]);
+ break;
+ }
+ ++i;
+ nOps = 0;
+ } else if (file[i] <= 246) {
+ if (nOps < 48) {
+ fp[nOps] = gFalse;
+ op[nOps++] = (int)file[i] - 139;
+ }
+ ++i;
+ } else if (file[i] <= 250) {
+ if (i + 2 > len) {
+ break;
+ }
+ if (nOps < 48) {
+ fp[nOps] = gFalse;
+ op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
+ }
+ i += 2;
+ } else if (file[i] <= 254) {
+ if (i + 2 > len) {
+ break;
+ }
+ if (nOps < 48) {
+ fp[nOps] = gFalse;
+ op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
+ }
+ i += 2;
+ } else {
+ if (i + 5 > len) {
+ break;
+ }
+ x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
+ if (x & 0x80000000) {
+ x |= -1 << 31;
+ }
+ if (nOps < 48) {
+ fp[nOps] = gTrue;
+ op[nOps++] = (double)x / 65536.0;
+ }
+ i += 5;
+ }
+ }
+
+ // charstring encryption
+ if (top) {
+ r2 = 4330;
+ for (i = 0; i < charBuf->getLength(); ++i) {
+ byte = charBuf->getChar(i) ^ (r2 >> 8);
+ charBuf->setChar(i, byte);
+ r2 = (byte + r2) * 52845 + 22719;
+ }
+ }
+}
+
+void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
+ double w;
+ GBool wFP;
+ int i;
+
+ if (useOp) {
+ w = nominalWidthX + op[0];
+ wFP = nominalWidthXFP | fp[0];
+ for (i = 1; i < nOps; ++i) {
+ op[i-1] = op[i];
+ fp[i-1] = fp[i];
+ }
+ --nOps;
+ } else {
+ w = defaultWidthX;
+ wFP = defaultWidthXFP;
+ }
+ eexecDumpNum(0, gFalse);
+ eexecDumpNum(w, wFP);
+ eexecDumpOp1(13);
+}
+
+void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
+ Guchar buf[12];
+ int y, n;
+
+ n = 0;
+ if (fpA) {
+ if (x >= -32768 && x < 32768) {
+ y = (int)(x * 256.0);
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ buf[5] = 255;
+ buf[6] = 0;
+ buf[7] = 0;
+ buf[8] = 1;
+ buf[9] = 0;
+ buf[10] = 12;
+ buf[11] = 12;
+ n = 12;
+ } else {
+ error(-1, "Type 2 fixed point constant out of range");
+ }
+ } else {
+ y = (int)x;
+ if (y >= -107 && y <= 107) {
+ buf[0] = (Guchar)(y + 139);
+ n = 1;
+ } else if (y > 107 && y <= 1131) {
+ y -= 108;
+ buf[0] = (Guchar)((y >> 8) + 247);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else if (y < -107 && y >= -1131) {
+ y = -y - 108;
+ buf[0] = (Guchar)((y >> 8) + 251);
+ buf[1] = (Guchar)(y & 0xff);
+ n = 2;
+ } else {
+ buf[0] = 255;
+ buf[1] = (Guchar)(y >> 24);
+ buf[2] = (Guchar)(y >> 16);
+ buf[3] = (Guchar)(y >> 8);
+ buf[4] = (Guchar)y;
+ n = 5;
+ }
+ }
+ charBuf->append((char *)buf, n);
+}
+
+void Type1CFontFile::eexecDumpOp1(int opA) {
+ charBuf->append((char)opA);
+}
+
+void Type1CFontFile::eexecDumpOp2(int opA) {
+ charBuf->append((char)12);
+ charBuf->append((char)opA);
+}
+
+void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
+ Guchar x;
+ int i;
+
+ // eexec encryption
+ for (i = 0; i < n; ++i) {
+ x = s[i] ^ (r1 >> 8);
+ r1 = (x + r1) * 52845 + 22719;
+ (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
+ (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
+ line += 2;
+ if (line == 64) {
+ (*outputFunc)(outputStream, "\n", 1);
+ line = 0;
+ }
+ }
+}
+
+void Type1CFontFile::getDeltaInt(char *buf, const char *key, double *opA,
+ int n) {
+ int x, i;
+
+ sprintf(buf, "/%s [", key);
+ buf += strlen(buf);
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += (int)opA[i];
+ sprintf(buf, "%s%d", i > 0 ? " " : "", x);
+ buf += strlen(buf);
+ }
+ sprintf(buf, "] def\n");
+}
+
+void Type1CFontFile::getDeltaReal(char *buf, const char *key, double *opA,
+ int n) {
+ double x;
+ int i;
+
+ sprintf(buf, "/%s [", key);
+ buf += strlen(buf);
+ x = 0;
+ for (i = 0; i < n; ++i) {
+ x += opA[i];
+ sprintf(buf, "%s%g", i > 0 ? " " : "", x);
+ buf += strlen(buf);
+ }
+ sprintf(buf, "] def\n");
+}
+
+int Type1CFontFile::getIndexLen(int indexPos) {
+ if (indexPos + 2 > len) {
+ return -1;
+ }
+ return (int)getWord(indexPos, 2);
+}
+
+int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
+ int n, offSize, idxStartPos;
+ int pos0, pos1;
+
+ if (indexPos < 0 || indexPos + 3 > len) {
+ return -1;
+ }
+ n = (int)getWord(indexPos, 2);
+ if (i >= n) {
+ return -1;
+ }
+ offSize = file[indexPos + 2];
+ if (offSize < 1 || offSize > 4) {
+ return -1;
+ }
+ idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
+ if (idxStartPos >= len) {
+ return -1;
+ }
+ pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
+ pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
+ if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
+ return -1;
+ }
+ *valLen = pos1 - pos0;
+ return pos0;
+}
+
+int Type1CFontFile::getIndexEnd(int indexPos) {
+ int n, offSize, idxStartPos;
+
+ if (indexPos < 0 || indexPos + 3 > len) {
+ return -1;
+ }
+ n = (int)getWord(indexPos, 2);
+ offSize = file[indexPos + 2];
+ idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
+ if (idxStartPos >= len) {
+ return -1;
+ }
+ return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
+}
+
+Guint Type1CFontFile::getWord(int pos, int size) {
+ Guint x;
+ int i;
+
+ if (pos < 0 || pos + size > len) {
+ return 0;
+ }
+ x = 0;
+ for (i = 0; i < size; ++i) {
+ x = (x << 8) + file[pos + i];
+ }
+ return x;
+}
+
+double Type1CFontFile::getNum(int *pos, GBool *isFP) {
+ static char nybChars[16] = "0123456789.ee -";
+ int b0, b, nyb0, nyb1;
+ double x;
+ char buf[65];
+ int i;
+
+ x = 0;
+ *isFP = gFalse;
+ if (*pos >= len) {
+ return 0;
+ }
+ b0 = file[*pos];
+ if (b0 < 28) {
+ x = 0;
+ } else if (b0 == 28) {
+ if (*pos + 3 <= len) {
+ x = (file[*pos + 1] << 8) + file[*pos + 2];
+ *pos += 3;
+ }
+ } else if (b0 == 29) {
+ if (*pos + 5 <= len) {
+ x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
+ (file[*pos + 3] << 8) + file[*pos + 4];
+ *pos += 5;
+ }
+ } else if (b0 == 30) {
+ *pos += 1;
+ i = 0;
+ do {
+ if (*pos >= len) {
+ break;
+ }
+ b = file[(*pos)++];
+ nyb0 = b >> 4;
+ nyb1 = b & 0x0f;
+ if (nyb0 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb0];
+ if (i == 64) {
+ break;
+ }
+ if (nyb0 == 0xc) {
+ buf[i++] = '-';
+ }
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xf) {
+ break;
+ }
+ buf[i++] = nybChars[nyb1];
+ if (i == 64) {
+ break;
+ }
+ if (nyb1 == 0xc) {
+ buf[i++] = '-';
+ }
+ } while (i < 64);
+ buf[i] = '\0';
+ x = atof(buf);
+ *isFP = gTrue;
+ } else if (b0 == 31) {
+ x = 0;
+ } else if (b0 < 247) {
+ x = b0 - 139;
+ *pos += 1;
+ } else if (b0 < 251) {
+ if (*pos + 2 <= len) {
+ x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
+ *pos += 2;
+ }
+ } else {
+ if (*pos + 2 <= len) {
+ x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
+ *pos += 2;
+ }
+ }
+ return x;
+}
+
+char *Type1CFontFile::getString(int sid, char *buf) {
+ int idxPos, n;
+
+ if (sid < 391) {
+ strcpy(buf, type1CStdStrings[sid]);
+ } else {
+ sid -= 391;
+ idxPos = getIndexValPos(stringIdxPos, sid, &n);
+ if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
+ buf[0] = '\0';
+ } else {
+ strncpy(buf, (char *)&file[idxPos], n);
+ buf[n] = '\0';
+ }
+ }
+ return buf;
+}
+
+//------------------------------------------------------------------------
+// TrueTypeFontFile
+//------------------------------------------------------------------------
+
+//
+// Terminology
+// -----------
+//
+// character code = number used as an element of a text string
+//
+// character name = glyph name = name for a particular glyph within a
+// font
+//
+// glyph index = position (within some internal table in the font)
+// where the instructions to draw a particular glyph are
+// stored
+//
+// Type 1 fonts
+// ------------
+//
+// Type 1 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of instructions, keyed by character names,
+// maps character name to glyph data
+//
+// CharStrings[charName] = glyphData
+//
+// TrueType fonts
+// --------------
+//
+// TrueType fonts contain:
+//
+// 'cmap' table: mapping from character code to glyph index; there may
+// be multiple cmaps in a TrueType font
+//
+// cmap[charCode] = glyphIdx
+//
+// 'post' table: mapping from glyph index to glyph name
+//
+// post[glyphIdx] = glyphName
+//
+// Type 42 fonts
+// -------------
+//
+// Type 42 fonts contain:
+//
+// Encoding: array of glyph names, maps char codes to glyph names
+//
+// Encoding[charCode] = charName
+//
+// CharStrings: dictionary of glyph indexes, keyed by character names,
+// maps character name to glyph index
+//
+// CharStrings[charName] = glyphIdx
+//
+
+struct TTFontTableHdr {
+ char tag[4];
+ Guint checksum;
+ Guint offset;
+ Guint length;
+};
+
+struct T42Table {
+ const char *tag; // 4-byte tag
+ GBool required; // required by the TrueType spec?
+};
+
+struct TTFontCmap {
+ int platform;
+ int encoding;
+ int offset;
+ int len;
+ int fmt;
+};
+
+// TrueType tables to be embedded in Type 42 fonts.
+// NB: the table names must be in alphabetical order here.
+#define nT42Tables 11
+static T42Table t42Tables[nT42Tables] = {
+ { "cvt ", gTrue },
+ { "fpgm", gTrue },
+ { "glyf", gTrue },
+ { "head", gTrue },
+ { "hhea", gTrue },
+ { "hmtx", gTrue },
+ { "loca", gTrue },
+ { "maxp", gTrue },
+ { "prep", gTrue },
+ { "vhea", gFalse },
+ { "vmtx", gFalse }
+};
+#define t42HeadTable 3
+#define t42LocaTable 6
+#define t42GlyfTable 2
+
+// Glyph names in some arbitrary standard that Apple uses for their
+// TrueType fonts.
+static const char *macGlyphNames[258] = {
+ ".notdef",
+ "null",
+ "CR",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu1",
+ "partialdiff",
+ "summation",
+ "product",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Ohm",
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "increment",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nbspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+ "Oacute",
+ "Ocircumflex",
+ "applelogo",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "overscore",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+ "ccaron",
+ "dmacron"
+};
+
+struct TrueTypeLoca {
+ int idx;
+ int pos;
+ int length;
+};
+
+TrueTypeFontFile::TrueTypeFontFile(const char *fileA, int lenA) {
+ int pos, pos2, i, idx, n, length;
+ Guint size, startPos, endPos;
+
+ file = fileA;
+ len = lenA;
+
+ encoding = NULL;
+ cmaps = NULL;
+ nCmaps = 0;
+
+ // read table directory
+ nTables = getUShort(4);
+ tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
+ pos = 12;
+ for (i = 0; i < nTables; ++i) {
+ tableHdrs[i].tag[0] = getByte(pos+0);
+ tableHdrs[i].tag[1] = getByte(pos+1);
+ tableHdrs[i].tag[2] = getByte(pos+2);
+ tableHdrs[i].tag[3] = getByte(pos+3);
+ tableHdrs[i].checksum = getULong(pos+4);
+ tableHdrs[i].offset = getULong(pos+8);
+ tableHdrs[i].length = getULong(pos+12);
+ if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
+ tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
+ tableHdrs[i].offset = (Guint)-1;
+ }
+ pos += 16;
+ }
+
+ // check for tables that are required by both the TrueType spec
+ // and the Type 42 spec
+ if (seekTable("head") < 0 ||
+ seekTable("hhea") < 0 ||
+ seekTable("loca") < 0 ||
+ seekTable("maxp") < 0 ||
+ seekTable("glyf") < 0 ||
+ seekTable("hmtx") < 0) {
+ error(-1, "TrueType font file is missing a required table");
+ return;
+ }
+
+ // some embedded TrueType fonts have an incorrect (too small) cmap
+ // table size
+ idx = seekTableIdx("cmap");
+ if (idx >= 0) {
+ pos = tableHdrs[idx].offset;
+ n = getUShort(pos + 2);
+ size = (Guint)(4 + 8 * n);
+ for (i = 0; i < n; ++i) {
+ startPos = getULong(pos + 4 + 8*i + 4);
+ length = getUShort(pos + startPos + 2);
+ endPos = startPos + length;
+ if (endPos > size) {
+ size = endPos;
+ }
+ }
+ if ((mungedCmapSize = size > tableHdrs[idx].length)) {
+#if 0 // don't bother printing this error message - it's too common
+ error(-1, "Bad cmap table size in TrueType font");
+#endif
+ tableHdrs[idx].length = size;
+ }
+ } else {
+ mungedCmapSize = gFalse;
+ }
+
+ // read the 'head' table
+ pos = seekTable("head");
+ bbox[0] = getShort(pos + 36);
+ bbox[1] = getShort(pos + 38);
+ bbox[2] = getShort(pos + 40);
+ bbox[3] = getShort(pos + 42);
+ locaFmt = getShort(pos + 50);
+
+ // read the 'maxp' table
+ pos = seekTable("maxp");
+ nGlyphs = getUShort(pos + 4);
+
+ // read the 'cmap' table
+ if ((pos = seekTable("cmap")) >= 0) {
+ pos2 = pos + 2;
+ if ((nCmaps = getUShort(pos2)) > 0) {
+ pos2 += 2;
+ cmaps = (TTFontCmap *)gmalloc(nCmaps * sizeof(TTFontCmap));
+ for (i = 0; i < nCmaps; ++i) {
+ cmaps[i].platform = getUShort(pos2);
+ cmaps[i].encoding = getUShort(pos2 + 2);
+ cmaps[i].offset = pos + getULong(pos2 + 4);
+ pos2 += 8;
+ cmaps[i].fmt = getUShort(cmaps[i].offset);
+ cmaps[i].len = getUShort(cmaps[i].offset + 2);
+ }
+ }
+ }
+}
+
+TrueTypeFontFile::~TrueTypeFontFile() {
+ int i;
+
+ if (encoding) {
+ for (i = 0; i < 256; ++i) {
+ gfree(encoding[i]);
+ }
+ gfree(encoding);
+ }
+ if (cmaps) {
+ gfree(cmaps);
+ }
+ gfree(tableHdrs);
+}
+
+const char *TrueTypeFontFile::getName() {
+ return NULL;
+}
+
+const char **TrueTypeFontFile::getEncoding() {
+ int i;
+
+ if (!encoding) {
+ encoding = (char **)gmalloc(256 * sizeof(char *));
+ for (i = 0; i < 256; ++i) {
+ encoding[i] = NULL;
+ }
+ }
+ return (const char **)encoding;
+}
+
+int TrueTypeFontFile::getNumCmaps() {
+ return nCmaps;
+}
+
+int TrueTypeFontFile::getCmapPlatform(int i) {
+ return cmaps[i].platform;
+}
+
+int TrueTypeFontFile::getCmapEncoding(int i) {
+ return cmaps[i].encoding;
+}
+
+int TrueTypeFontFile::findCmap(int platform, int enc) {
+ int i;
+
+ for (i = 0; i < nCmaps; ++i) {
+ if (cmaps[i].platform == platform && cmaps[i].encoding == enc) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+Gushort TrueTypeFontFile::mapCodeToGID(int i, int c) {
+ if (i < 0 || i >= nCmaps) {
+ return 0;
+ }
+ return (Gushort)getCmapEntry(cmaps[i].fmt, cmaps[i].offset, c);
+}
+
+GHash *TrueTypeFontFile::getNameToGID() {
+ GHash *nameToGID;
+ Guint fmt;
+ GString *s;
+ int stringIdx, stringPos, pos, i, j, n;
+
+ if ((pos = seekTable("post")) < 0) {
+ return NULL;
+ }
+
+ fmt = getULong(pos);
+ nameToGID = NULL;
+
+ // Apple font
+ if (fmt == 0x00010000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < 258; ++i) {
+ nameToGID->add(new GString(macGlyphNames[i]), (void *)i);
+ }
+
+ // Microsoft font
+ } else if (fmt == 0x00020000) {
+ nameToGID = new GHash(gTrue);
+ n = getUShort(pos + 32);
+ if (n > nGlyphs) {
+ n = nGlyphs;
+ }
+ stringIdx = 0;
+ stringPos = pos + 34 + 2*nGlyphs;
+ for (i = 0; i < nGlyphs; ++i) {
+ j = getUShort(pos + 34 + 2*i);
+ if (j < 258) {
+ nameToGID->remove(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
+ } else {
+ j -= 258;
+ if (j != stringIdx) {
+ for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
+ stringIdx < j;
+ ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
+ }
+ n = getByte(stringPos);
+ if (stringPos >= 0 && stringPos + 1 + n <= len) {
+ s = new GString(file + stringPos + 1, n);
+ nameToGID->remove(s);
+ nameToGID->add(s, (void *)i);
+ }
+ ++stringIdx;
+ stringPos += 1 + n;
+ }
+ }
+
+ // Apple subset
+ } else if (fmt == 0x000280000) {
+ nameToGID = new GHash(gTrue);
+ for (i = 0; i < nGlyphs; ++i) {
+ j = getByte(pos + 32 + i);
+ if (j < 258) {
+ nameToGID->remove(macGlyphNames[j]);
+ nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
+ }
+ }
+ }
+
+ return nameToGID;
+}
+
+void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
+ GBool pdfFontHasEncoding,
+ Gushort *codeToGID,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+
+ // write the header
+ sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+
+ // write the guts of the dictionary
+ cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
+ cvtCharStrings(encodingA, pdfFontHasEncoding, codeToGID,
+ outputFunc, outputStream);
+ cvtSfnts(outputFunc, outputStream, NULL);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+void TrueTypeFontFile::convertToCIDType2(const char *name, Gushort *cidMap,
+ int nCIDs,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+ Gushort cid;
+ int i, j, k;
+
+ // write the header
+ sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
+ (*outputFunc)(outputStream, buf, strlen(buf));
+
+ // begin the font dictionary
+ (*outputFunc)(outputStream, "20 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/CIDFontName /", 14);
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
+ (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
+ (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
+ (*outputFunc)(outputStream, " end def\n", 10);
+ (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
+ if (cidMap) {
+ sprintf(buf, "/CIDCount %d def\n", nCIDs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (nCIDs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [", 9);
+ for (i = 0; i < nCIDs; i += 32768 - 16) {
+ (*outputFunc)(outputStream, "<\n", 2);
+ for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
+ cid = cidMap[i+j+k];
+ sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, " >", 3);
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ (*outputFunc)(outputStream, "/CIDMap <\n", 10);
+ for (i = 0; i < nCIDs; i += 16) {
+ (*outputFunc)(outputStream, " ", 2);
+ for (j = 0; j < 16 && i+j < nCIDs; ++j) {
+ cid = cidMap[i+j];
+ sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ (*outputFunc)(outputStream, "> def\n", 6);
+ }
+ } else {
+ // direct mapping - just fill the string(s) with s[i]=i
+ sprintf(buf, "/CIDCount %d def\n", nGlyphs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ if (nGlyphs > 32767) {
+ (*outputFunc)(outputStream, "/CIDMap [\n", 10);
+ for (i = 0; i < nGlyphs; i += 32767) {
+ j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
+ sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
+ " 255 and put\n", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, " } for\n", 8);
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ } else {
+ sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream,
+ " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
+ (*outputFunc)(outputStream,
+ " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
+ (*outputFunc)(outputStream, " } for\n", 8);
+ (*outputFunc)(outputStream, "def\n", 4);
+ }
+ }
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
+ (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
+ (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
+ (*outputFunc)(outputStream, " end readonly def\n", 19);
+
+ // write the guts of the dictionary
+ cvtSfnts(outputFunc, outputStream, NULL);
+
+ // end the dictionary and define the font
+ (*outputFunc)(outputStream,
+ "CIDFontName currentdict end /CIDFont defineresource pop\n",
+ 56);
+}
+
+void TrueTypeFontFile::convertToType0(const char *name, Gushort *cidMap,
+ int nCIDs,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[512];
+ GString *sfntsName;
+ int n, i, j;
+
+ // write the Type 42 sfnts array
+ sfntsName = (new GString(name))->append("_sfnts");
+ cvtSfnts(outputFunc, outputStream, sfntsName);
+ delete sfntsName;
+
+ // write the descendant Type 42 fonts
+ n = cidMap ? nCIDs : nGlyphs;
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "10 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, name, strlen(name));
+ sprintf(buf, "_%02x def\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
+ bbox[0], bbox[1], bbox[2], bbox[3]);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
+ (*outputFunc)(outputStream, "/sfnts ", 7);
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, "_sfnts def\n", 11);
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ sprintf(buf, "dup %d /c%02x put\n", j, j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+ (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+ for (j = 0; j < 256 && i+j < n; ++j) {
+ sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+ (*outputFunc)(outputStream,
+ "FontName currentdict end definefont pop\n", 40);
+ }
+
+ // write the Type 0 parent font
+ (*outputFunc)(outputStream, "16 dict begin\n", 14);
+ (*outputFunc)(outputStream, "/FontName /", 11);
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, " def\n", 5);
+ (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
+ (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
+ (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
+ (*outputFunc)(outputStream, "/Encoding [\n", 12);
+ for (i = 0; i < n; i += 256) {
+ sprintf(buf, "%d\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "/FDepVector [\n", 14);
+ for (i = 0; i < n; i += 256) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name, strlen(name));
+ sprintf(buf, "_%02x findfont\n", i >> 8);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ (*outputFunc)(outputStream, "] def\n", 6);
+ (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
+}
+
+int TrueTypeFontFile::getByte(int pos) {
+ if (pos < 0 || pos >= len) {
+ return 0;
+ }
+ return file[pos] & 0xff;
+}
+
+int TrueTypeFontFile::getChar(int pos) {
+ int x;
+
+ if (pos < 0 || pos >= len) {
+ return 0;
+ }
+ x = file[pos] & 0xff;
+ if (x & 0x80)
+ x |= 0xffffff00;
+ return x;
+}
+
+int TrueTypeFontFile::getUShort(int pos) {
+ int x;
+
+ if (pos < 0 || pos+1 >= len) {
+ return 0;
+ }
+ x = file[pos] & 0xff;
+ x = (x << 8) + (file[pos+1] & 0xff);
+ return x;
+}
+
+int TrueTypeFontFile::getShort(int pos) {
+ int x;
+
+ if (pos < 0 || pos+1 >= len) {
+ return 0;
+ }
+ x = file[pos] & 0xff;
+ x = (x << 8) + (file[pos+1] & 0xff);
+ if (x & 0x8000)
+ x |= 0xffff0000;
+ return x;
+}
+
+Guint TrueTypeFontFile::getULong(int pos) {
+ int x;
+
+ if (pos < 0 || pos+3 >= len) {
+ return 0;
+ }
+ x = file[pos] & 0xff;
+ x = (x << 8) + (file[pos+1] & 0xff);
+ x = (x << 8) + (file[pos+2] & 0xff);
+ x = (x << 8) + (file[pos+3] & 0xff);
+ return x;
+}
+
+double TrueTypeFontFile::getFixed(int pos) {
+ int x, y;
+
+ x = getShort(pos);
+ y = getUShort(pos+2);
+ return (double)x + (double)y / 65536;
+}
+
+int TrueTypeFontFile::seekTable(const char *tag) {
+ int i;
+
+ for (i = 0; i < nTables; ++i) {
+ if (!strncmp(tableHdrs[i].tag, tag, 4)) {
+ return (int)tableHdrs[i].offset;
+ }
+ }
+ return -1;
+}
+
+int TrueTypeFontFile::seekTableIdx(const char *tag) {
+ int i;
+
+ for (i = 0; i < nTables; ++i) {
+ if (!strncmp(tableHdrs[i].tag, tag, 4)) {
+ if (tableHdrs[i].offset == (Guint)-1) {
+ return -1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+void TrueTypeFontFile::cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ const char *name;
+ char buf[64];
+ int i;
+
+ (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
+ if (pdfFontHasEncoding) {
+ for (i = 0; i < 256; ++i) {
+ if (!(name = encodingA[i])) {
+ name = ".notdef";
+ }
+ sprintf(buf, "dup %d /", i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, name, strlen(name));
+ (*outputFunc)(outputStream, " put\n", 5);
+ }
+ } else {
+ for (i = 0; i < 256; ++i) {
+ sprintf(buf, "dup %d /c%02x put\n", i, i);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ (*outputFunc)(outputStream, "readonly def\n", 13);
+}
+
+void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
+ GBool pdfFontHasEncoding,
+ Gushort *codeToGID,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ const char *name;
+ char buf[64], buf2[16];
+ int i, k;
+
+ // always define '.notdef'
+ (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
+ (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
+
+ // if there's no 'cmap' table, punt
+ if (nCmaps == 0) {
+ goto err;
+ }
+
+ // map char name to glyph index:
+ // 1. use encoding to map name to char code
+ // 2. use codeToGID to map char code to glyph index
+ // N.B. We do this in reverse order because font subsets can have
+ // weird encodings that use the same character name twice, and
+ // the first definition is probably the one we want.
+ k = 0; // make gcc happy
+ for (i = 255; i >= 0; --i) {
+ if (pdfFontHasEncoding) {
+ name = encodingA[i];
+ } else {
+ sprintf(buf2, "c%02x", i);
+ name = buf2;
+ }
+ if (name && strcmp(name, ".notdef")) {
+ k = codeToGID[i];
+ // note: Distiller (maybe Adobe's PS interpreter in general)
+ // doesn't like TrueType fonts that have CharStrings entries
+ // which point to nonexistent glyphs, hence the (k < nGlyphs)
+ // test
+ if (k > 0 && k < nGlyphs) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name, strlen(name));
+ sprintf(buf, " %d def\n", k);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ }
+ }
+
+ err:
+ (*outputFunc)(outputStream, "end readonly def\n", 17);
+}
+
+int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
+ int cmapLen, cmapFirst;
+ int segCnt, segEnd, segStart, segDelta, segOffset;
+ int a, b, m, i;
+
+ switch (cmapFmt) {
+ case 0: // byte encoding table (Apple standard)
+ cmapLen = getUShort(pos + 2);
+ if (code >= cmapLen) {
+ return 0;
+ }
+ return getByte(pos + 6 + code);
+
+ case 4: // segment mapping to delta values (Microsoft standard)
+ segCnt = getUShort(pos + 6) / 2;
+ a = -1;
+ b = segCnt - 1;
+ segEnd = getUShort(pos + 14 + 2*b);
+ if (code > segEnd) {
+ // malformed font -- the TrueType spec requires the last segEnd
+ // to be 0xffff
+ return 0;
+ }
+ // invariant: seg[a].end < code <= seg[b].end
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ segEnd = getUShort(pos + 14 + 2*m);
+ if (segEnd < code) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
+ segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
+ segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
+ if (code < segStart) {
+ return 0;
+ }
+ if (segOffset == 0) {
+ i = (code + segDelta) & 0xffff;
+ } else {
+ i = getUShort(pos + 16 + 6*segCnt + 2*b +
+ segOffset + 2 * (code - segStart));
+ if (i != 0) {
+ i = (i + segDelta) & 0xffff;
+ }
+ }
+ return i;
+
+ case 6: // trimmed table mapping
+ cmapFirst = getUShort(pos + 6);
+ cmapLen = getUShort(pos + 8);
+ if (code < cmapFirst || code >= cmapFirst + cmapLen) {
+ return 0;
+ }
+ return getUShort(pos + 10 + 2*(code - cmapFirst));
+
+ default:
+ // shouldn't happen - this is checked earlier
+ break;
+ }
+ return 0;
+}
+
+static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
+ return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
+}
+
+static int cmpTrueTypeLocaPos(const void *p1, const void *p2) {
+ if (((TrueTypeLoca *)p1)->pos == ((TrueTypeLoca *)p2)->pos) {
+ return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
+ } else {
+ return ((TrueTypeLoca *)p1)->pos - ((TrueTypeLoca *)p2)->pos;
+ }
+}
+
+void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
+ void *outputStream, GString *name) {
+ TTFontTableHdr newTableHdrs[nT42Tables];
+ char tableDir[12 + nT42Tables*16];
+ char headTable[54];
+ TrueTypeLoca *origLocaTable;
+ char *locaTable;
+ int nNewTables;
+ Guint checksum;
+ int pos, glyfPos, length, glyphLength, pad;
+ int i, j, k;
+
+ // construct the 'head' table, zero out the font checksum
+ memcpy(headTable, file + seekTable("head"), 54);
+ headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
+
+ // read the original 'loca' table and sort it into proper order --
+ // some (non-compliant) fonts have out-of-order loca tables; in
+ // order to correctly handle the case where (compliant) fonts have
+ // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
+ // pos as its primary sort key, and idx as its secondary key
+ // (ensuring that adjacent entries with the same pos value remain in
+ // the same order)
+ origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
+ sizeof(TrueTypeLoca));
+ pos = seekTable("loca");
+ for (i = 0; i <= nGlyphs; ++i) {
+ origLocaTable[i].idx = i;
+ if (locaFmt) {
+ origLocaTable[i].pos = getULong(pos + 4*i);
+ } else {
+ origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
+ }
+ }
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaPos);
+ for (i = 0; i < nGlyphs; ++i) {
+ origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
+ }
+ origLocaTable[nGlyphs].length = 0;
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
+
+ // construct the new 'loca' table, padding each glyph out to a
+ // multiple of 4 bytes
+ locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ locaTable[4*i ] = (char)(pos >> 24);
+ locaTable[4*i+1] = (char)(pos >> 16);
+ locaTable[4*i+2] = (char)(pos >> 8);
+ locaTable[4*i+3] = (char) pos;
+ } else {
+ locaTable[2*i ] = (char)(pos >> 9);
+ locaTable[2*i+1] = (char)(pos >> 1);
+ }
+ length = origLocaTable[i].length;
+ if (length & 3) {
+ length += 4 - (length & 3);
+ }
+ pos += length;
+ }
+
+ // count the number of tables
+ nNewTables = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ if (t42Tables[i].required ||
+ seekTable(t42Tables[i].tag) >= 0) {
+ ++nNewTables;
+ }
+ }
+
+ // construct the new table headers, including table checksums
+ // (pad each table out to a multiple of 4 bytes)
+ pos = 12 + nNewTables*16;
+ k = 0;
+ for (i = 0; i < nT42Tables; ++i) {
+ length = -1;
+ checksum = 0; // make gcc happy
+ if (i == t42HeadTable) {
+ length = 54;
+ checksum = computeTableChecksum(headTable, 54);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ checksum = computeTableChecksum(locaTable, length);
+ } else if (i == t42GlyfTable) {
+ length = 0;
+ checksum = 0;
+ glyfPos = seekTable("glyf");
+ for (j = 0; j < nGlyphs; ++j) {
+ glyphLength = origLocaTable[j].length;
+ pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
+ length += glyphLength + pad;
+ if (glyphLength >= 0 &&
+ glyfPos + origLocaTable[j].pos + glyphLength <= len) {
+ checksum +=
+ computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
+ glyphLength);
+ }
+ }
+ } else {
+ if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
+ length = tableHdrs[j].length;
+ checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
+ } else if (t42Tables[i].required) {
+ error(-1, "Embedded TrueType font is missing a required table ('%s')",
+ t42Tables[i].tag);
+ length = 0;
+ checksum = 0;
+ }
+ }
+ if (length >= 0) {
+ strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
+ newTableHdrs[k].checksum = checksum;
+ newTableHdrs[k].offset = pos;
+ newTableHdrs[k].length = length;
+ pad = (length & 3) ? 4 - (length & 3) : 0;
+ pos += length + pad;
+ ++k;
+ }
+ }
+
+ // construct the table directory
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = 0; // numTables
+ tableDir[5] = nNewTables;
+ tableDir[6] = 0; // searchRange
+ tableDir[7] = (char)128;
+ tableDir[8] = 0; // entrySelector
+ tableDir[9] = 3;
+ tableDir[10] = 0; // rangeShift
+ tableDir[11] = (char)(16 * nNewTables - 128);
+ pos = 12;
+ for (i = 0; i < nNewTables; ++i) {
+ tableDir[pos ] = newTableHdrs[i].tag[0];
+ tableDir[pos+ 1] = newTableHdrs[i].tag[1];
+ tableDir[pos+ 2] = newTableHdrs[i].tag[2];
+ tableDir[pos+ 3] = newTableHdrs[i].tag[3];
+ tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
+ tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
+ tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
+ tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
+ tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
+ tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
+ tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
+ tableDir[pos+11] = (char) newTableHdrs[i].offset;
+ tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
+ tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
+ tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
+ tableDir[pos+15] = (char) newTableHdrs[i].length;
+ pos += 16;
+ }
+
+ // compute the font checksum and store it in the head table
+ checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
+ for (i = 0; i < nNewTables; ++i) {
+ checksum += newTableHdrs[i].checksum;
+ }
+ checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
+ headTable[ 8] = (char)(checksum >> 24);
+ headTable[ 9] = (char)(checksum >> 16);
+ headTable[10] = (char)(checksum >> 8);
+ headTable[11] = (char) checksum;
+
+ // start the sfnts array
+ if (name) {
+ (*outputFunc)(outputStream, "/", 1);
+ (*outputFunc)(outputStream, name->getCString(), name->getLength());
+ (*outputFunc)(outputStream, " [\n", 3);
+ } else {
+ (*outputFunc)(outputStream, "/sfnts [\n", 9);
+ }
+
+ // write the table directory
+ dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
+
+ // write the tables
+ for (i = 0; i < nNewTables; ++i) {
+ if (i == t42HeadTable) {
+ dumpString(headTable, 54, outputFunc, outputStream);
+ } else if (i == t42LocaTable) {
+ length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ dumpString(locaTable, length, outputFunc, outputStream);
+ } else if (i == t42GlyfTable) {
+ glyfPos = seekTable("glyf");
+ for (j = 0; j < nGlyphs; ++j) {
+ length = origLocaTable[j].length;
+ if (length > 0 &&
+ glyfPos + origLocaTable[j].pos + length <= len) {
+ dumpString(file + glyfPos + origLocaTable[j].pos, length,
+ outputFunc, outputStream);
+ }
+ }
+ } else {
+ // length == 0 means the table is missing and the error was
+ // already reported during the construction of the table
+ // headers
+ if ((length = newTableHdrs[i].length) > 0) {
+ j = seekTable(t42Tables[i].tag);
+ if (j >= 0) {
+ dumpString(file + seekTable(t42Tables[i].tag), length,
+ outputFunc, outputStream);
+ }
+ }
+ }
+ }
+
+ // end the sfnts array
+ (*outputFunc)(outputStream, "] def\n", 6);
+
+ gfree(origLocaTable);
+ gfree(locaTable);
+}
+
+void TrueTypeFontFile::dumpString(const char *s, int length,
+ FontFileOutputFunc outputFunc,
+ void *outputStream) {
+ char buf[64];
+ int pad, i, j;
+
+ (*outputFunc)(outputStream, "<", 1);
+ for (i = 0; i < length; i += 32) {
+ for (j = 0; j < 32 && i+j < length; ++j) {
+ sprintf(buf, "%02X", s[i+j] & 0xff);
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ if (i % (65536 - 32) == 65536 - 64) {
+ (*outputFunc)(outputStream, ">\n<", 3);
+ } else if (i+32 < length) {
+ (*outputFunc)(outputStream, "\n", 1);
+ }
+ }
+ if (length & 3) {
+ pad = 4 - (length & 3);
+ for (i = 0; i < pad; ++i) {
+ (*outputFunc)(outputStream, "00", 2);
+ }
+ }
+ // add an extra zero byte because the Adobe Type 42 spec says so
+ (*outputFunc)(outputStream, "00>\n", 4);
+}
+
+Guint TrueTypeFontFile::computeTableChecksum(const char *data, int length) {
+ Guint checksum, word;
+ int i;
+
+ checksum = 0;
+ for (i = 0; i+3 < length; i += 4) {
+ word = ((data[i ] & 0xff) << 24) +
+ ((data[i+1] & 0xff) << 16) +
+ ((data[i+2] & 0xff) << 8) +
+ (data[i+3] & 0xff);
+ checksum += word;
+ }
+ if (length & 3) {
+ word = 0;
+ i = length & ~3;
+ switch (length & 3) {
+ case 3:
+ word |= (data[i+2] & 0xff) << 8;
+ case 2:
+ word |= (data[i+1] & 0xff) << 16;
+ case 1:
+ word |= (data[i ] & 0xff) << 24;
+ break;
+ }
+ checksum += word;
+ }
+ return checksum;
+}
+
+void TrueTypeFontFile::writeTTF(FILE *out) {
+ static char cmapTab[20] = {
+ 0, 0, // table version number
+ 0, 1, // number of encoding tables
+ 0, 1, // platform ID
+ 0, 0, // encoding ID
+ 0, 0, 0, 12, // offset of subtable
+ 0, 0, // subtable format
+ 0, 1, // subtable length
+ 0, 1, // subtable version
+ 0, // map char 0 -> glyph 0
+ 0 // pad to multiple of four bytes
+ };
+ static char nameTab[8] = {
+ 0, 0, // format
+ 0, 0, // number of name records
+ 0, 6, // offset to start of string storage
+ 0, 0 // pad to multiple of four bytes
+ };
+ static char postTab[32] = {
+ 0, 1, 0, 0, // format
+ 0, 0, 0, 0, // italic angle
+ 0, 0, // underline position
+ 0, 0, // underline thickness
+ 0, 0, 0, 0, // fixed pitch
+ 0, 0, 0, 0, // min Type 42 memory
+ 0, 0, 0, 0, // max Type 42 memory
+ 0, 0, 0, 0, // min Type 1 memory
+ 0, 0, 0, 0 // max Type 1 memory
+ };
+ GBool haveCmap, haveName, havePost;
+ GBool dirCmap, dirName, dirPost;
+ GBool unsortedLoca;
+ int nNewTables, nZeroLengthTables, nAllTables;
+ TTFontTableHdr *newTableHdrs;
+ char *tableDir;
+ TrueTypeLoca *origLocaTable;
+ char *locaTable;
+ int length, glyfLength;
+ Guint t, pos, pos2, pos3;
+ int i, j, k;
+
+ // check for missing/broken tables
+ haveCmap = seekTable("cmap") >= 0;
+ haveName = seekTable("name") >= 0;
+ havePost = seekTable("post") >= 0;
+ unsortedLoca = gFalse;
+ pos = seekTable("loca");
+ pos2 = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ pos3 = getULong(pos + 4*i);
+ } else {
+ pos3 = 2 * getUShort(pos + 2*i);
+ }
+ if (pos3 < pos2) {
+ unsortedLoca = gTrue;
+ break;
+ }
+ pos2 = pos3;
+ }
+ nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
+ nZeroLengthTables = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (tableHdrs[i].length == 0) {
+ ++nZeroLengthTables;
+ }
+ }
+ if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
+ // nothing is broken - write the TTF file as is
+ fwrite(file, 1, len, out);
+ return;
+ }
+
+ // if the glyph data isn't sorted (as listed in the 'loca' table),
+ // construct a new 'loca' table
+ if (unsortedLoca) {
+ origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
+ sizeof(TrueTypeLoca));
+ pos = seekTable("loca");
+ for (i = 0; i <= nGlyphs; ++i) {
+ origLocaTable[i].idx = i;
+ if (locaFmt) {
+ origLocaTable[i].pos = getULong(pos + 4*i);
+ } else {
+ origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
+ }
+ }
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaPos);
+ for (i = 0; i < nGlyphs; ++i) {
+ origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
+ }
+ origLocaTable[nGlyphs].length = 0;
+ qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
+ &cmpTrueTypeLocaIdx);
+ locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
+ pos = 0;
+ for (i = 0; i <= nGlyphs; ++i) {
+ if (locaFmt) {
+ locaTable[4*i ] = (char)(pos >> 24);
+ locaTable[4*i+1] = (char)(pos >> 16);
+ locaTable[4*i+2] = (char)(pos >> 8);
+ locaTable[4*i+3] = (char) pos;
+ } else {
+ locaTable[2*i ] = (char)(pos >> 9);
+ locaTable[2*i+1] = (char)(pos >> 1);
+ }
+ length = origLocaTable[i].length;
+ if (length & 3) {
+ length += 4 - (length & 3);
+ }
+ pos += length;
+ }
+ glyfLength = pos;
+ } else {
+ origLocaTable = NULL; // make gcc happy
+ locaTable = NULL; // make gcc happy
+ glyfLength = 0; // make gcc happy
+ }
+
+ // construct the new table directory
+ nAllTables = nTables - nZeroLengthTables + nNewTables;
+ newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
+ sizeof(TTFontTableHdr));
+ dirCmap = haveCmap;
+ dirName = haveName;
+ dirPost = havePost;
+ pos = 12 + nAllTables * 16;
+ j = 0;
+ for (i = 0; i < nTables; ++i) {
+ if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
+ memcpy(newTableHdrs[j].tag, "cmap", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(cmapTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ dirCmap = gTrue;
+ }
+ if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
+ memcpy(newTableHdrs[j].tag, "name", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(nameTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ dirName = gTrue;
+ }
+ if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
+ memcpy(newTableHdrs[j].tag, "post", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(postTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ dirPost = gTrue;
+ }
+ // throw away zero-length tables - they confuse FreeType
+ if (tableHdrs[i].length > 0) {
+ memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
+ newTableHdrs[j].checksum = tableHdrs[i].checksum;
+ newTableHdrs[j].offset = pos;
+ if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
+ newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
+ } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
+ newTableHdrs[j].length = glyfLength;
+ } else {
+ newTableHdrs[j].length = tableHdrs[i].length;
+ }
+ pos += newTableHdrs[j].length;
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ }
+ }
+ if (!dirCmap) {
+ memcpy(newTableHdrs[j].tag, "cmap", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(cmapTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ }
+ if (!dirName) {
+ memcpy(newTableHdrs[j].tag, "name", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(nameTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ }
+ if (!dirPost) {
+ memcpy(newTableHdrs[j].tag, "post", 4);
+ newTableHdrs[j].checksum = 0; //~ should compute the checksum
+ newTableHdrs[j].offset = pos;
+ pos += newTableHdrs[j].length = sizeof(postTab);
+ if (pos & 3) {
+ pos += 4 - (pos & 3);
+ }
+ ++j;
+ }
+ tableDir = (char *)gmalloc(12 + nAllTables * 16);
+ tableDir[0] = 0x00; // sfnt version
+ tableDir[1] = 0x01;
+ tableDir[2] = 0x00;
+ tableDir[3] = 0x00;
+ tableDir[4] = (char)((nAllTables >> 8) & 0xff); // numTables
+ tableDir[5] = (char)(nAllTables & 0xff);
+ for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
+ t = 1 << (4 + i);
+ tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
+ tableDir[7] = (char)(t & 0xff);
+ tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
+ tableDir[9] = (char)(i & 0xff);
+ t = nAllTables * 16 - t;
+ tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
+ tableDir[11] = (char)(t & 0xff);
+ pos = 12;
+ for (i = 0; i < nAllTables; ++i) {
+ tableDir[pos ] = newTableHdrs[i].tag[0];
+ tableDir[pos+ 1] = newTableHdrs[i].tag[1];
+ tableDir[pos+ 2] = newTableHdrs[i].tag[2];
+ tableDir[pos+ 3] = newTableHdrs[i].tag[3];
+ tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
+ tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
+ tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
+ tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
+ tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
+ tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
+ tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
+ tableDir[pos+11] = (char) newTableHdrs[i].offset;
+ tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
+ tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
+ tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
+ tableDir[pos+15] = (char) newTableHdrs[i].length;
+ pos += 16;
+ }
+
+ // write the table directory
+ fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
+
+ // write the tables
+ for (i = 0; i < nAllTables; ++i) {
+ if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
+ fwrite(cmapTab, 1, newTableHdrs[i].length, out);
+ } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
+ fwrite(nameTab, 1, newTableHdrs[i].length, out);
+ } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
+ fwrite(postTab, 1, newTableHdrs[i].length, out);
+ } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
+ fwrite(locaTable, 1, newTableHdrs[i].length, out);
+ } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
+ pos = seekTable("glyf");
+ for (j = 0; j < nGlyphs; ++j) {
+ length = origLocaTable[j].length;
+ if (length > 0 &&
+ pos + origLocaTable[j].pos + length <= (Guint)len) {
+ fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
+ if ((k = length & 3)) {
+ for (; k < 4; ++k) {
+ fputc((char)0, out);
+ }
+ }
+ }
+ }
+ } else {
+ fwrite(file + seekTable(newTableHdrs[i].tag),
+ 1, newTableHdrs[i].length, out);
+ }
+ if ((j = (newTableHdrs[i].length & 3))) {
+ for (; j < 4; ++j) {
+ fputc((char)0, out);
+ }
+ }
+ }
+
+ gfree(tableDir);
+ gfree(newTableHdrs);
+ if (unsortedLoca) {
+ gfree(origLocaTable);
+ gfree(locaTable);
+ }
+}
diff --git a/pdftops/FontFile.h b/pdftops/FontFile.h
new file mode 100644
index 000000000..0f452a140
--- /dev/null
+++ b/pdftops/FontFile.h
@@ -0,0 +1,261 @@
+//========================================================================
+//
+// FontFile.h
+//
+// Copyright 1999-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FONTFILE_H
+#define FONTFILE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "gtypes.h"
+#include "GString.h"
+#include "CharTypes.h"
+
+class GHash;
+class CharCodeToUnicode;
+
+//------------------------------------------------------------------------
+
+typedef void (*FontFileOutputFunc)(void *stream, const char *data, int len);
+
+//------------------------------------------------------------------------
+// FontFile
+//------------------------------------------------------------------------
+
+class FontFile {
+public:
+
+ FontFile();
+ virtual ~FontFile();
+
+ // Returns the font name, as specified internally by the font file.
+ // Returns NULL if no name is available.
+ virtual const char *getName() = 0;
+
+ // Returns the custom font encoding, or NULL if the encoding is not
+ // available.
+ virtual const char **getEncoding() = 0;
+};
+
+//------------------------------------------------------------------------
+// Type1FontFile
+//------------------------------------------------------------------------
+
+class Type1FontFile: public FontFile {
+public:
+
+ Type1FontFile(const char *file, int len);
+ virtual ~Type1FontFile();
+ virtual const char *getName() { return name; }
+ virtual const char **getEncoding() { return (const char **)encoding; }
+
+private:
+
+ char *name;
+ char **encoding;
+};
+
+//------------------------------------------------------------------------
+// Type1CFontFile
+//------------------------------------------------------------------------
+
+struct Type1CTopDict;
+struct Type1CPrivateDict;
+
+class Type1CFontFile: public FontFile {
+public:
+
+ Type1CFontFile(const char *fileA, int lenA);
+ virtual ~Type1CFontFile();
+ GBool isOk() { return ok; }
+
+ virtual const char *getName();
+ virtual const char **getEncoding();
+
+ // Convert to a Type 1 font, suitable for embedding in a PostScript
+ // file. The name will be used as the PostScript font name.
+ void convertToType1(FontFileOutputFunc outputFuncA, void *outputStreamA);
+
+ // Convert to a Type 0 CIDFont, suitable for embedding in a
+ // PostScript file. The name will be used as the PostScript font
+ // name.
+ void convertToCIDType0(const char *psName,
+ FontFileOutputFunc outputFuncA, void *outputStreamA);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. The name will be used as the
+ // PostScript font name.
+ void convertToType0(const char *psName,
+ FontFileOutputFunc outputFuncA, void *outputStreamA);
+
+private:
+
+ void readEncoding();
+ void readTopDict(Type1CTopDict *dict);
+ void readPrivateDict(Type1CPrivateDict *privateDict,
+ int offset, int size);
+ Gushort *readCharset(int charset, int nGlyphs);
+ void eexecWrite(const char *s);
+ void eexecCvtGlyph(const char *glyphName, int pos, int n);
+ void cvtGlyph(int pos, int n, GBool top);
+ void cvtGlyphWidth(GBool useOp);
+ void eexecDumpNum(double x, GBool fpA);
+ void eexecDumpOp1(int opA);
+ void eexecDumpOp2(int opA);
+ void eexecWriteCharstring(Guchar *s, int n);
+ void getDeltaInt(char *buf, const char *key, double *opA, int n);
+ void getDeltaReal(char *buf, const char *key, double *opA, int n);
+ int getIndexLen(int indexPos);
+ int getIndexValPos(int indexPos, int i, int *valLen);
+ int getIndexEnd(int indexPos);
+ Guint getWord(int pos, int size);
+ double getNum(int *pos, GBool *fp);
+ char *getString(int sid, char *buf);
+
+ const Guchar *file;
+ int len;
+
+ GString *name;
+ char **encoding;
+
+ int topDictIdxPos;
+ int stringIdxPos;
+ int gsubrIdxPos;
+ int subrIdxPos;
+ int gsubrBias;
+ int subrBias;
+
+ FontFileOutputFunc outputFunc;
+ void *outputStream;
+ double op[48]; // operands
+ GBool fp[48]; // true if operand is fixed point
+ int nOps; // number of operands
+ int nHints; // number of hints for the current glyph
+ GBool firstOp; // true if we haven't hit the first op yet
+ double defaultWidthX; // default glyph width
+ double nominalWidthX; // nominal glyph width
+ GBool defaultWidthXFP; // true if defaultWidthX is fixed point
+ GBool nominalWidthXFP; // true if nominalWidthX is fixed point
+ Gushort r1; // eexec encryption key
+ GString *charBuf; // charstring output buffer
+ int line; // number of eexec chars on current line
+
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// TrueTypeFontFile
+//------------------------------------------------------------------------
+
+struct TTFontTableHdr;
+struct TTFontCmap;
+
+class TrueTypeFontFile: public FontFile {
+public:
+
+ TrueTypeFontFile(const char *fileA, int lenA);
+ ~TrueTypeFontFile();
+
+ // This always returns NULL, since it's probably better to trust the
+ // font name in the PDF file rather than the one in the TrueType
+ // font file.
+ virtual const char *getName();
+
+ virtual const char **getEncoding();
+
+ // Return the number of cmaps defined by this font.
+ int getNumCmaps();
+
+ // Return the platform ID of the <i>th cmap.
+ int getCmapPlatform(int i);
+
+ // Return the encoding ID of the <i>th cmap.
+ int getCmapEncoding(int i);
+
+ // Return the index of the cmap for <platform>, <encoding>. Returns
+ // -1 if there is no corresponding cmap.
+ int findCmap(int platform, int enc);
+
+ // Return the GID corresponding to <c> according to the <i>th cmap.
+ Gushort mapCodeToGID(int i, int c);
+
+ // Return a name-to-GID mapping, constructed from the font's post
+ // table. Returns NULL if there is no post table.
+ GHash *getNameToGID();
+
+ // Convert to a Type 42 font, suitable for embedding in a PostScript
+ // file. The name will be used as the PostScript font name (so we
+ // don't need to depend on the 'name' table in the font). The
+ // encoding is needed because the PDF Font object can modify the
+ // encoding.
+ void convertToType42(const char *name, const char **encodingA,
+ GBool pdfFontHasEncoding,
+ Gushort *codeToGID,
+ FontFileOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 2 CIDFont, suitable for embedding in a
+ // PostScript file. The name will be used as the PostScript font
+ // name (so we don't need to depend on the 'name' table in the
+ // font).
+ void convertToCIDType2(const char *name, Gushort *cidMap, int nCIDs,
+ FontFileOutputFunc outputFunc, void *outputStream);
+
+ // Convert to a Type 0 (but non-CID) composite font, suitable for
+ // embedding in a PostScript file. The name will be used as the
+ // PostScript font name (so we don't need to depend on the 'name'
+ // table in the font).
+ void convertToType0(const char *name, Gushort *cidMap, int nCIDs,
+ FontFileOutputFunc outputFunc, void *outputStream);
+
+ // Write a TTF file, filling in any missing tables that are required
+ // by the TrueType spec. If the font already has all the required
+ // tables, it will be written unmodified.
+ void writeTTF(FILE *out);
+
+private:
+
+ const char *file;
+ int len;
+
+ char **encoding;
+
+ TTFontTableHdr *tableHdrs;
+ int nTables;
+ int bbox[4];
+ int locaFmt;
+ int nGlyphs;
+ GBool mungedCmapSize;
+ TTFontCmap *cmaps;
+ int nCmaps;
+
+ int getByte(int pos);
+ int getChar(int pos);
+ int getUShort(int pos);
+ int getShort(int pos);
+ Guint getULong(int pos);
+ double getFixed(int pos);
+ int seekTable(const char *tag);
+ int seekTableIdx(const char *tag);
+ void cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
+ FontFileOutputFunc outputFunc, void *outputStream);
+ void cvtCharStrings(const char **encodingA, GBool pdfFontHasEncoding,
+ Gushort *codeToGID,
+ FontFileOutputFunc outputFunc, void *outputStream);
+ int getCmapEntry(int cmapFmt, int pos, int code);
+ void cvtSfnts(FontFileOutputFunc outputFunc, void *outputStream,
+ GString *name);
+ void dumpString(const char *s, int length,
+ FontFileOutputFunc outputFunc, void *outputStream);
+ Guint computeTableChecksum(const char *data, int length);
+};
+
+#endif
diff --git a/pdftops/Function.cxx b/pdftops/Function.cxx
new file mode 100644
index 000000000..0a5e9ae7a
--- /dev/null
+++ b/pdftops/Function.cxx
@@ -0,0 +1,1520 @@
+//========================================================================
+//
+// Function.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include "gmem.h"
+#include "Object.h"
+#include "Dict.h"
+#include "Stream.h"
+#include "Error.h"
+#include "Function.h"
+
+//------------------------------------------------------------------------
+// Function
+//------------------------------------------------------------------------
+
+Function::Function() {
+}
+
+Function::~Function() {
+}
+
+Function *Function::parse(Object *funcObj) {
+ Function *func;
+ Dict *dict;
+ int funcType;
+ Object obj1;
+
+ if (funcObj->isStream()) {
+ dict = funcObj->streamGetDict();
+ } else if (funcObj->isDict()) {
+ dict = funcObj->getDict();
+ } else if (funcObj->isName("Identity")) {
+ return new IdentityFunction();
+ } else {
+ error(-1, "Expected function dictionary or stream");
+ return NULL;
+ }
+
+ if (!dict->lookup("FunctionType", &obj1)->isInt()) {
+ error(-1, "Function type is missing or wrong type");
+ obj1.free();
+ return NULL;
+ }
+ funcType = obj1.getInt();
+ obj1.free();
+
+ if (funcType == 0) {
+ func = new SampledFunction(funcObj, dict);
+ } else if (funcType == 2) {
+ func = new ExponentialFunction(funcObj, dict);
+ } else if (funcType == 3) {
+ func = new StitchingFunction(funcObj, dict);
+ } else if (funcType == 4) {
+ func = new PostScriptFunction(funcObj, dict);
+ } else {
+ error(-1, "Unimplemented function type (%d)", funcType);
+ return NULL;
+ }
+ if (!func->isOk()) {
+ delete func;
+ return NULL;
+ }
+
+ return func;
+}
+
+GBool Function::init(Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
+ //----- Domain
+ if (!dict->lookup("Domain", &obj1)->isArray()) {
+ error(-1, "Function is missing domain");
+ goto err2;
+ }
+ m = obj1.arrayGetLength() / 2;
+ if (m > funcMaxInputs) {
+ error(-1, "Functions with more than %d inputs are unsupported",
+ funcMaxInputs);
+ goto err2;
+ }
+ for (i = 0; i < m; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function domain array");
+ goto err1;
+ }
+ domain[i][0] = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2*i+1, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function domain array");
+ goto err1;
+ }
+ domain[i][1] = obj2.getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ //----- Range
+ hasRange = gFalse;
+ n = 0;
+ if (dict->lookup("Range", &obj1)->isArray()) {
+ hasRange = gTrue;
+ n = obj1.arrayGetLength() / 2;
+ if (n > funcMaxOutputs) {
+ error(-1, "Functions with more than %d outputs are unsupported",
+ funcMaxOutputs);
+ goto err2;
+ }
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function range array");
+ goto err1;
+ }
+ range[i][0] = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2*i+1, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function range array");
+ goto err1;
+ }
+ range[i][1] = obj2.getNum();
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ return gTrue;
+
+ err1:
+ obj2.free();
+ err2:
+ obj1.free();
+ return gFalse;
+}
+
+//------------------------------------------------------------------------
+// IdentityFunction
+//------------------------------------------------------------------------
+
+IdentityFunction::IdentityFunction() {
+ int i;
+
+ // fill these in with arbitrary values just in case they get used
+ // somewhere
+ m = funcMaxInputs;
+ n = funcMaxOutputs;
+ for (i = 0; i < funcMaxInputs; ++i) {
+ domain[i][0] = 0;
+ domain[i][1] = 1;
+ }
+ hasRange = gFalse;
+}
+
+IdentityFunction::~IdentityFunction() {
+}
+
+void IdentityFunction::transform(double *in, double *out) {
+ int i;
+
+ for (i = 0; i < funcMaxOutputs; ++i) {
+ out[i] = in[i];
+ }
+}
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
+ Stream *str;
+ int nSamples, sampleBits;
+ double sampleMul;
+ Object obj1, obj2;
+ Guint buf, bitMask;
+ int bits;
+ int s;
+ int i;
+
+ samples = NULL;
+ ok = gFalse;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (!hasRange) {
+ error(-1, "Type 0 function is missing range");
+ goto err1;
+ }
+
+ //----- get the stream
+ if (!funcObj->isStream()) {
+ error(-1, "Type 0 function isn't a stream");
+ goto err1;
+ }
+ str = funcObj->getStream();
+
+ //----- Size
+ if (!dict->lookup("Size", &obj1)->isArray() ||
+ obj1.arrayGetLength() != m) {
+ error(-1, "Function has missing or invalid size array");
+ goto err2;
+ }
+ for (i = 0; i < m; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isInt()) {
+ error(-1, "Illegal value in function size array");
+ goto err3;
+ }
+ sampleSize[i] = obj2.getInt();
+ obj2.free();
+ }
+ obj1.free();
+
+ //----- BitsPerSample
+ if (!dict->lookup("BitsPerSample", &obj1)->isInt()) {
+ error(-1, "Function has missing or invalid BitsPerSample");
+ goto err2;
+ }
+ sampleBits = obj1.getInt();
+ sampleMul = 1.0 / (double)((1 << sampleBits) - 1);
+ obj1.free();
+
+ //----- Encode
+ if (dict->lookup("Encode", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2*m) {
+ for (i = 0; i < m; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function encode array");
+ goto err3;
+ }
+ encode[i][0] = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2*i+1, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function encode array");
+ goto err3;
+ }
+ encode[i][1] = obj2.getNum();
+ obj2.free();
+ }
+ } else {
+ for (i = 0; i < m; ++i) {
+ encode[i][0] = 0;
+ encode[i][1] = sampleSize[i] - 1;
+ }
+ }
+ obj1.free();
+
+ //----- Decode
+ if (dict->lookup("Decode", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2*n) {
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function decode array");
+ goto err3;
+ }
+ decode[i][0] = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2*i+1, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function decode array");
+ goto err3;
+ }
+ decode[i][1] = obj2.getNum();
+ obj2.free();
+ }
+ } else {
+ for (i = 0; i < n; ++i) {
+ decode[i][0] = range[i][0];
+ decode[i][1] = range[i][1];
+ }
+ }
+ obj1.free();
+
+ //----- samples
+ nSamples = n;
+ for (i = 0; i < m; ++i)
+ nSamples *= sampleSize[i];
+ samples = (double *)gmalloc(nSamples * sizeof(double));
+ buf = 0;
+ bits = 0;
+ bitMask = (1 << sampleBits) - 1;
+ str->reset();
+ for (i = 0; i < nSamples; ++i) {
+ if (sampleBits == 8) {
+ s = str->getChar();
+ } else if (sampleBits == 16) {
+ s = str->getChar();
+ s = (s << 8) + str->getChar();
+ } else if (sampleBits == 32) {
+ s = str->getChar();
+ s = (s << 8) + str->getChar();
+ s = (s << 8) + str->getChar();
+ s = (s << 8) + str->getChar();
+ } else {
+ while (bits < sampleBits) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bits += 8;
+ }
+ s = (buf >> (bits - sampleBits)) & bitMask;
+ bits -= sampleBits;
+ }
+ samples[i] = (double)s * sampleMul;
+ }
+ str->close();
+
+ ok = gTrue;
+ return;
+
+ err3:
+ obj2.free();
+ err2:
+ obj1.free();
+ err1:
+ return;
+}
+
+SampledFunction::~SampledFunction() {
+ if (samples) {
+ gfree(samples);
+ }
+}
+
+SampledFunction::SampledFunction(SampledFunction *func) {
+ int nSamples, i;
+
+ memcpy(this, func, sizeof(SampledFunction));
+
+ nSamples = n;
+ for (i = 0; i < m; ++i) {
+ nSamples *= sampleSize[i];
+ }
+ samples = (double *)gmalloc(nSamples * sizeof(double));
+ memcpy(samples, func->samples, nSamples * sizeof(double));
+}
+
+void SampledFunction::transform(double *in, double *out) {
+ double x;
+ int e[2][funcMaxInputs];
+ double efrac[funcMaxInputs];
+ double s0[1 << funcMaxInputs], s1[1 << funcMaxInputs];
+ int i, j, k, idx;
+
+ // map input values into sample array
+ for (i = 0; i < m; ++i) {
+ x = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
+ (encode[i][1] - encode[i][0]) + encode[i][0];
+ if (x < 0) {
+ x = 0;
+ } else if (x > sampleSize[i] - 1) {
+ x = sampleSize[i] - 1;
+ }
+ e[0][i] = (int)floor(x);
+ e[1][i] = (int)ceil(x);
+ efrac[i] = x - e[0][i];
+ }
+
+ // for each output, do m-linear interpolation
+ for (i = 0; i < n; ++i) {
+
+ // pull 2^m values out of the sample array
+ for (j = 0; j < (1<<m); ++j) {
+ idx = 0;
+ for (k = m - 1; k >= 0; --k) {
+ idx = idx * sampleSize[k] + e[(j >> k) & 1][k];
+ }
+ idx = idx * n + i;
+ s0[j] = samples[idx];
+ }
+
+ // do m sets of interpolations
+ for (j = 0; j < m; ++j) {
+ for (k = 0; k < (1 << (m - j)); k += 2) {
+ s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1];
+ }
+ memcpy(s0, s1, (1 << (m - j - 1)) * sizeof(double));
+ }
+
+ // map output value to range
+ out[i] = s0[0] * (decode[i][1] - decode[i][0]) + decode[i][0];
+ if (out[i] < range[i][0]) {
+ out[i] = range[i][0];
+ } else if (out[i] > range[i][1]) {
+ out[i] = range[i][1];
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
+ ok = gFalse;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (m != 1) {
+ error(-1, "Exponential function with more than one input");
+ goto err1;
+ }
+
+ //----- C0
+ if (dict->lookup("C0", &obj1)->isArray()) {
+ if (hasRange && obj1.arrayGetLength() != n) {
+ error(-1, "Function's C0 array is wrong length");
+ goto err2;
+ }
+ n = obj1.arrayGetLength();
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function C0 array");
+ goto err3;
+ }
+ c0[i] = obj2.getNum();
+ obj2.free();
+ }
+ } else {
+ if (hasRange && n != 1) {
+ error(-1, "Function's C0 array is wrong length");
+ goto err2;
+ }
+ n = 1;
+ c0[0] = 0;
+ }
+ obj1.free();
+
+ //----- C1
+ if (dict->lookup("C1", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() != n) {
+ error(-1, "Function's C1 array is wrong length");
+ goto err2;
+ }
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function C1 array");
+ goto err3;
+ }
+ c1[i] = obj2.getNum();
+ obj2.free();
+ }
+ } else {
+ if (n != 1) {
+ error(-1, "Function's C1 array is wrong length");
+ goto err2;
+ }
+ c1[0] = 1;
+ }
+ obj1.free();
+
+ //----- N (exponent)
+ if (!dict->lookup("N", &obj1)->isNum()) {
+ error(-1, "Function has missing or invalid N");
+ goto err2;
+ }
+ e = obj1.getNum();
+ obj1.free();
+
+ ok = gTrue;
+ return;
+
+ err3:
+ obj2.free();
+ err2:
+ obj1.free();
+ err1:
+ return;
+}
+
+ExponentialFunction::~ExponentialFunction() {
+}
+
+ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
+ memcpy(this, func, sizeof(ExponentialFunction));
+}
+
+void ExponentialFunction::transform(double *in, double *out) {
+ double x;
+ int i;
+
+ if (in[0] < domain[0][0]) {
+ x = domain[0][0];
+ } else if (in[0] > domain[0][1]) {
+ x = domain[0][1];
+ } else {
+ x = in[0];
+ }
+ for (i = 0; i < n; ++i) {
+ out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
+ if (hasRange) {
+ if (out[i] < range[i][0]) {
+ out[i] = range[i][0];
+ } else if (out[i] > range[i][1]) {
+ out[i] = range[i][1];
+ }
+ }
+ }
+ return;
+}
+
+//------------------------------------------------------------------------
+// StitchingFunction
+//------------------------------------------------------------------------
+
+StitchingFunction::StitchingFunction(Object *funcObj, Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
+ ok = gFalse;
+ funcs = NULL;
+ bounds = NULL;
+ encode = NULL;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (m != 1) {
+ error(-1, "Stitching function with more than one input");
+ goto err1;
+ }
+
+ //----- Functions
+ if (!dict->lookup("Functions", &obj1)->isArray()) {
+ error(-1, "Missing 'Functions' entry in stitching function");
+ goto err1;
+ }
+ k = obj1.arrayGetLength();
+ funcs = (Function **)gmalloc(k * sizeof(Function *));
+ bounds = (double *)gmalloc((k + 1) * sizeof(double));
+ encode = (double *)gmalloc(2 * k * sizeof(double));
+ for (i = 0; i < k; ++i) {
+ funcs[i] = NULL;
+ }
+ for (i = 0; i < k; ++i) {
+ if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) {
+ goto err2;
+ }
+ if (i > 0 && (funcs[i]->getInputSize() != 1 ||
+ funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) {
+ error(-1, "Incompatible subfunctions in stitching function");
+ goto err2;
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ //----- Bounds
+ if (!dict->lookup("Bounds", &obj1)->isArray() ||
+ obj1.arrayGetLength() != k - 1) {
+ error(-1, "Missing or invalid 'Bounds' entry in stitching function");
+ goto err1;
+ }
+ bounds[0] = domain[0][0];
+ for (i = 1; i < k; ++i) {
+ if (!obj1.arrayGet(i - 1, &obj2)->isNum()) {
+ error(-1, "Invalid type in 'Bounds' array in stitching function");
+ goto err2;
+ }
+ bounds[i] = obj2.getNum();
+ obj2.free();
+ }
+ bounds[k] = domain[0][1];
+ obj1.free();
+
+ //----- Encode
+ if (!dict->lookup("Encode", &obj1)->isArray() ||
+ obj1.arrayGetLength() != 2 * k) {
+ error(-1, "Missing or invalid 'Encode' entry in stitching function");
+ goto err1;
+ }
+ for (i = 0; i < 2 * k; ++i) {
+ if (!obj1.arrayGet(i, &obj2)->isNum()) {
+ error(-1, "Invalid type in 'Encode' array in stitching function");
+ goto err2;
+ }
+ encode[i] = obj2.getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ ok = gTrue;
+ return;
+
+ err2:
+ obj2.free();
+ err1:
+ obj1.free();
+}
+
+StitchingFunction::StitchingFunction(StitchingFunction *func) {
+ int i;
+
+ k = func->k;
+ funcs = (Function **)gmalloc(k * sizeof(Function *));
+ for (i = 0; i < k; ++i) {
+ funcs[i] = func->funcs[i]->copy();
+ }
+ bounds = (double *)gmalloc((k + 1) * sizeof(double));
+ memcpy(bounds, func->bounds, (k + 1) * sizeof(double));
+ encode = (double *)gmalloc(2 * k * sizeof(double));
+ memcpy(encode, func->encode, 2 * k * sizeof(double));
+ ok = gTrue;
+}
+
+StitchingFunction::~StitchingFunction() {
+ int i;
+
+ if (funcs) {
+ for (i = 0; i < k; ++i) {
+ if (funcs[i]) {
+ delete funcs[i];
+ }
+ }
+ }
+ gfree(funcs);
+ gfree(bounds);
+ gfree(encode);
+}
+
+void StitchingFunction::transform(double *in, double *out) {
+ double x;
+ int i;
+
+ if (in[0] < domain[0][0]) {
+ x = domain[0][0];
+ } else if (in[0] > domain[0][1]) {
+ x = domain[0][1];
+ } else {
+ x = in[0];
+ }
+ for (i = 0; i < k - 1; ++i) {
+ if (x < bounds[i+1]) {
+ break;
+ }
+ }
+ x = encode[2*i] + ((x - bounds[i]) / (bounds[i+1] - bounds[i])) *
+ (encode[2*i+1] - encode[2*i]);
+ funcs[i]->transform(&x, out);
+}
+
+//------------------------------------------------------------------------
+// PostScriptFunction
+//------------------------------------------------------------------------
+
+enum PSOp {
+ psOpAbs,
+ psOpAdd,
+ psOpAnd,
+ psOpAtan,
+ psOpBitshift,
+ psOpCeiling,
+ psOpCopy,
+ psOpCos,
+ psOpCvi,
+ psOpCvr,
+ psOpDiv,
+ psOpDup,
+ psOpEq,
+ psOpExch,
+ psOpExp,
+ psOpFalse,
+ psOpFloor,
+ psOpGe,
+ psOpGt,
+ psOpIdiv,
+ psOpIndex,
+ psOpLe,
+ psOpLn,
+ psOpLog,
+ psOpLt,
+ psOpMod,
+ psOpMul,
+ psOpNe,
+ psOpNeg,
+ psOpNot,
+ psOpOr,
+ psOpPop,
+ psOpRoll,
+ psOpRound,
+ psOpSin,
+ psOpSqrt,
+ psOpSub,
+ psOpTrue,
+ psOpTruncate,
+ psOpXor,
+ psOpIf,
+ psOpIfelse,
+ psOpReturn
+};
+
+// Note: 'if' and 'ifelse' are parsed separately.
+// The rest are listed here in alphabetical order.
+// The index in this table is equivalent to the entry in PSOp.
+const char *psOpNames[] = {
+ "abs",
+ "add",
+ "and",
+ "atan",
+ "bitshift",
+ "ceiling",
+ "copy",
+ "cos",
+ "cvi",
+ "cvr",
+ "div",
+ "dup",
+ "eq",
+ "exch",
+ "exp",
+ "false",
+ "floor",
+ "ge",
+ "gt",
+ "idiv",
+ "index",
+ "le",
+ "ln",
+ "log",
+ "lt",
+ "mod",
+ "mul",
+ "ne",
+ "neg",
+ "not",
+ "or",
+ "pop",
+ "roll",
+ "round",
+ "sin",
+ "sqrt",
+ "sub",
+ "true",
+ "truncate",
+ "xor"
+};
+
+#define nPSOps (sizeof(psOpNames) / sizeof(char *))
+
+enum PSObjectType {
+ psBool,
+ psInt,
+ psReal,
+ psOperator,
+ psBlock
+};
+
+// In the code array, 'if'/'ifelse' operators take up three slots
+// plus space for the code in the subclause(s).
+//
+// +---------------------------------+
+// | psOperator: psOpIf / psOpIfelse |
+// +---------------------------------+
+// | psBlock: ptr=<A> |
+// +---------------------------------+
+// | psBlock: ptr=<B> |
+// +---------------------------------+
+// | if clause |
+// | ... |
+// | psOperator: psOpReturn |
+// +---------------------------------+
+// <A> | else clause |
+// | ... |
+// | psOperator: psOpReturn |
+// +---------------------------------+
+// <B> | ... |
+//
+// For 'if', pointer <A> is present in the code stream but unused.
+
+struct PSObject {
+ PSObjectType type;
+ union {
+ GBool booln; // boolean (stack only)
+ int intg; // integer (stack and code)
+ double real; // real (stack and code)
+ PSOp op; // operator (code only)
+ int blk; // if/ifelse block pointer (code only)
+ };
+};
+
+#define psStackSize 100
+
+class PSStack {
+public:
+
+ PSStack() { sp = psStackSize; }
+ void pushBool(GBool booln);
+ void pushInt(int intg);
+ void pushReal(double real);
+ GBool popBool();
+ int popInt();
+ double popNum();
+ GBool empty() { return sp == psStackSize; }
+ GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; }
+ GBool topTwoAreInts()
+ { return sp < psStackSize - 1 &&
+ stack[sp].type == psInt &&
+ stack[sp+1].type == psInt; }
+ GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; }
+ GBool topTwoAreNums()
+ { return sp < psStackSize - 1 &&
+ (stack[sp].type == psInt || stack[sp].type == psReal) &&
+ (stack[sp+1].type == psInt || stack[sp+1].type == psReal); }
+ void copy(int n);
+ void roll(int n, int j);
+ void index(int i);
+ void pop();
+
+private:
+
+ GBool checkOverflow(int n = 1);
+ GBool checkUnderflow();
+ GBool checkType(PSObjectType t1, PSObjectType t2);
+
+ PSObject stack[psStackSize];
+ int sp;
+};
+
+GBool PSStack::checkOverflow(int n) {
+ if (sp - n < 0) {
+ error(-1, "Stack overflow in PostScript function");
+ return gFalse;
+ }
+ return gTrue;
+}
+
+GBool PSStack::checkUnderflow() {
+ if (sp == psStackSize) {
+ error(-1, "Stack underflow in PostScript function");
+ return gFalse;
+ }
+ return gTrue;
+}
+
+GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) {
+ if (stack[sp].type != t1 && stack[sp].type != t2) {
+ error(-1, "Type mismatch in PostScript function");
+ return gFalse;
+ }
+ return gTrue;
+}
+
+void PSStack::pushBool(GBool booln) {
+ if (checkOverflow()) {
+ stack[--sp].type = psBool;
+ stack[sp].booln = booln;
+ }
+}
+
+void PSStack::pushInt(int intg) {
+ if (checkOverflow()) {
+ stack[--sp].type = psInt;
+ stack[sp].intg = intg;
+ }
+}
+
+void PSStack::pushReal(double real) {
+ if (checkOverflow()) {
+ stack[--sp].type = psReal;
+ stack[sp].real = real;
+ }
+}
+
+GBool PSStack::popBool() {
+ if (checkUnderflow() && checkType(psBool, psBool)) {
+ return stack[sp++].booln;
+ }
+ return gFalse;
+}
+
+int PSStack::popInt() {
+ if (checkUnderflow() && checkType(psInt, psInt)) {
+ return stack[sp++].intg;
+ }
+ return 0;
+}
+
+double PSStack::popNum() {
+ double ret;
+
+ if (checkUnderflow() && checkType(psInt, psReal)) {
+ ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real;
+ ++sp;
+ return ret;
+ }
+ return 0;
+}
+
+void PSStack::copy(int n) {
+ int i;
+
+ if (!checkOverflow(n)) {
+ return;
+ }
+ for (i = sp + n - 1; i <= sp; ++i) {
+ stack[i - n] = stack[i];
+ }
+ sp -= n;
+}
+
+void PSStack::roll(int n, int j) {
+ PSObject obj;
+ int i, k;
+
+ if (j >= 0) {
+ j %= n;
+ } else {
+ j = -j % n;
+ if (j != 0) {
+ j = n - j;
+ }
+ }
+ if (n <= 0 || j == 0) {
+ return;
+ }
+ for (i = 0; i < j; ++i) {
+ obj = stack[sp];
+ for (k = sp; k < sp + n - 1; ++k) {
+ stack[k] = stack[k+1];
+ }
+ stack[sp + n - 1] = obj;
+ }
+}
+
+void PSStack::index(int i) {
+ if (!checkOverflow()) {
+ return;
+ }
+ --sp;
+ stack[sp] = stack[sp + 1 + i];
+}
+
+void PSStack::pop() {
+ if (!checkUnderflow()) {
+ return;
+ }
+ ++sp;
+}
+
+PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) {
+ Stream *str;
+ int codePtr;
+ GString *tok;
+
+ code = NULL;
+ codeSize = 0;
+ ok = gFalse;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (!hasRange) {
+ error(-1, "Type 4 function is missing range");
+ goto err1;
+ }
+
+ //----- get the stream
+ if (!funcObj->isStream()) {
+ error(-1, "Type 4 function isn't a stream");
+ goto err1;
+ }
+ str = funcObj->getStream();
+
+ //----- parse the function
+ str->reset();
+ if (!(tok = getToken(str)) || tok->cmp("{")) {
+ error(-1, "Expected '{' at start of PostScript function");
+ if (tok) {
+ delete tok;
+ }
+ goto err1;
+ }
+ delete tok;
+ codePtr = 0;
+ if (!parseCode(str, &codePtr)) {
+ goto err2;
+ }
+ str->close();
+
+ ok = gTrue;
+
+ err2:
+ str->close();
+ err1:
+ return;
+}
+
+PostScriptFunction::PostScriptFunction(PostScriptFunction *func) {
+ memcpy(this, func, sizeof(PostScriptFunction));
+ code = (PSObject *)gmalloc(codeSize * sizeof(PSObject));
+ memcpy(code, func->code, codeSize * sizeof(PSObject));
+}
+
+PostScriptFunction::~PostScriptFunction() {
+ gfree(code);
+}
+
+void PostScriptFunction::transform(double *in, double *out) {
+ PSStack *stack;
+ int i;
+
+ stack = new PSStack();
+ for (i = 0; i < m; ++i) {
+ //~ may need to check for integers here
+ stack->pushReal(in[i]);
+ }
+ exec(stack, 0);
+ for (i = n - 1; i >= 0; --i) {
+ out[i] = stack->popNum();
+ if (out[i] < range[i][0]) {
+ out[i] = range[i][0];
+ } else if (out[i] > range[i][1]) {
+ out[i] = range[i][1];
+ }
+ }
+ // if (!stack->empty()) {
+ // error(-1, "Extra values on stack at end of PostScript function");
+ // }
+ delete stack;
+}
+
+GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) {
+ GString *tok;
+ char *p;
+ GBool isReal;
+ int opPtr, elsePtr;
+ int a, b, mid, cmp;
+
+ while (1) {
+ if (!(tok = getToken(str))) {
+ error(-1, "Unexpected end of PostScript function stream");
+ return gFalse;
+ }
+ p = tok->getCString();
+ if (isdigit(*p) || *p == '.' || *p == '-') {
+ isReal = gFalse;
+ for (++p; *p; ++p) {
+ if (*p == '.') {
+ isReal = gTrue;
+ break;
+ }
+ }
+ resizeCode(*codePtr);
+ if (isReal) {
+ code[*codePtr].type = psReal;
+ code[*codePtr].real = atof(tok->getCString());
+ } else {
+ code[*codePtr].type = psInt;
+ code[*codePtr].intg = atoi(tok->getCString());
+ }
+ ++*codePtr;
+ delete tok;
+ } else if (!tok->cmp("{")) {
+ delete tok;
+ opPtr = *codePtr;
+ *codePtr += 3;
+ resizeCode(opPtr + 2);
+ if (!parseCode(str, codePtr)) {
+ return gFalse;
+ }
+ if (!(tok = getToken(str))) {
+ error(-1, "Unexpected end of PostScript function stream");
+ return gFalse;
+ }
+ if (!tok->cmp("{")) {
+ elsePtr = *codePtr;
+ if (!parseCode(str, codePtr)) {
+ return gFalse;
+ }
+ delete tok;
+ if (!(tok = getToken(str))) {
+ error(-1, "Unexpected end of PostScript function stream");
+ return gFalse;
+ }
+ } else {
+ elsePtr = -1;
+ }
+ if (!tok->cmp("if")) {
+ if (elsePtr >= 0) {
+ error(-1, "Got 'if' operator with two blocks in PostScript function");
+ return gFalse;
+ }
+ code[opPtr].type = psOperator;
+ code[opPtr].op = psOpIf;
+ code[opPtr+2].type = psBlock;
+ code[opPtr+2].blk = *codePtr;
+ } else if (!tok->cmp("ifelse")) {
+ if (elsePtr < 0) {
+ error(-1, "Got 'ifelse' operator with one blocks in PostScript function");
+ return gFalse;
+ }
+ code[opPtr].type = psOperator;
+ code[opPtr].op = psOpIfelse;
+ code[opPtr+1].type = psBlock;
+ code[opPtr+1].blk = elsePtr;
+ code[opPtr+2].type = psBlock;
+ code[opPtr+2].blk = *codePtr;
+ } else {
+ error(-1, "Expected if/ifelse operator in PostScript function");
+ delete tok;
+ return gFalse;
+ }
+ delete tok;
+ } else if (!tok->cmp("}")) {
+ delete tok;
+ resizeCode(*codePtr);
+ code[*codePtr].type = psOperator;
+ code[*codePtr].op = psOpReturn;
+ ++*codePtr;
+ break;
+ } else {
+ a = -1;
+ b = nPSOps;
+ // invariant: psOpNames[a] < tok < psOpNames[b]
+ while (b - a > 1) {
+ mid = (a + b) / 2;
+ cmp = tok->cmp(psOpNames[mid]);
+ if (cmp > 0) {
+ a = mid;
+ } else if (cmp < 0) {
+ b = mid;
+ } else {
+ a = b = mid;
+ }
+ }
+ if (cmp != 0) {
+ error(-1, "Unknown operator '%s' in PostScript function",
+ tok->getCString());
+ delete tok;
+ return gFalse;
+ }
+ delete tok;
+ resizeCode(*codePtr);
+ code[*codePtr].type = psOperator;
+ code[*codePtr].op = (PSOp)a;
+ ++*codePtr;
+ }
+ }
+ return gTrue;
+}
+
+GString *PostScriptFunction::getToken(Stream *str) {
+ GString *s;
+ int c;
+
+ s = new GString();
+ do {
+ c = str->getChar();
+ } while (c != EOF && isspace(c));
+ if (c == '{' || c == '}') {
+ s->append((char)c);
+ } else if (isdigit(c) || c == '.' || c == '-') {
+ while (1) {
+ s->append((char)c);
+ c = str->lookChar();
+ if (c == EOF || !(isdigit(c) || c == '.' || c == '-')) {
+ break;
+ }
+ str->getChar();
+ }
+ } else {
+ while (1) {
+ s->append((char)c);
+ c = str->lookChar();
+ if (c == EOF || !isalnum(c)) {
+ break;
+ }
+ str->getChar();
+ }
+ }
+ return s;
+}
+
+void PostScriptFunction::resizeCode(int newSize) {
+ if (newSize >= codeSize) {
+ codeSize += 64;
+ code = (PSObject *)grealloc(code, codeSize * sizeof(PSObject));
+ }
+}
+
+void PostScriptFunction::exec(PSStack *stack, int codePtr) {
+ int i1, i2;
+ double r1, r2;
+ GBool b1, b2;
+
+ while (1) {
+ switch (code[codePtr].type) {
+ case psInt:
+ stack->pushInt(code[codePtr++].intg);
+ break;
+ case psReal:
+ stack->pushReal(code[codePtr++].real);
+ break;
+ case psOperator:
+ switch (code[codePtr++].op) {
+ case psOpAbs:
+ if (stack->topIsInt()) {
+ stack->pushInt(abs(stack->popInt()));
+ } else {
+ stack->pushReal(fabs(stack->popNum()));
+ }
+ break;
+ case psOpAdd:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 + i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(r1 + r2);
+ }
+ break;
+ case psOpAnd:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 & i2);
+ } else {
+ b2 = stack->popBool();
+ b1 = stack->popBool();
+ stack->pushBool(b1 && b2);
+ }
+ break;
+ case psOpAtan:
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(atan2(r1, r2));
+ break;
+ case psOpBitshift:
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ if (i2 > 0) {
+ stack->pushInt(i1 << i2);
+ } else if (i2 < 0) {
+ stack->pushInt((int)((Guint)i1 >> i2));
+ } else {
+ stack->pushInt(i1);
+ }
+ break;
+ case psOpCeiling:
+ if (!stack->topIsInt()) {
+ stack->pushReal(ceil(stack->popNum()));
+ }
+ break;
+ case psOpCopy:
+ stack->copy(stack->popInt());
+ break;
+ case psOpCos:
+ stack->pushReal(cos(stack->popNum()));
+ break;
+ case psOpCvi:
+ if (!stack->topIsInt()) {
+ stack->pushInt((int)stack->popNum());
+ }
+ break;
+ case psOpCvr:
+ if (!stack->topIsReal()) {
+ stack->pushReal(stack->popNum());
+ }
+ break;
+ case psOpDiv:
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(r1 / r2);
+ break;
+ case psOpDup:
+ stack->copy(1);
+ break;
+ case psOpEq:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 == i2);
+ } else if (stack->topTwoAreNums()) {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 == r2);
+ } else {
+ b2 = stack->popBool();
+ b1 = stack->popBool();
+ stack->pushBool(b1 == b2);
+ }
+ break;
+ case psOpExch:
+ stack->roll(2, 1);
+ break;
+ case psOpExp:
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(pow(r1, r2));
+ break;
+ case psOpFalse:
+ stack->pushBool(gFalse);
+ break;
+ case psOpFloor:
+ if (!stack->topIsInt()) {
+ stack->pushReal(floor(stack->popNum()));
+ }
+ break;
+ case psOpGe:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 >= i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 >= r2);
+ }
+ break;
+ case psOpGt:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 > i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 > r2);
+ }
+ break;
+ case psOpIdiv:
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 / i2);
+ break;
+ case psOpIndex:
+ stack->index(stack->popInt());
+ break;
+ case psOpLe:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 <= i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 <= r2);
+ }
+ break;
+ case psOpLn:
+ stack->pushReal(log(stack->popNum()));
+ break;
+ case psOpLog:
+ stack->pushReal(log10(stack->popNum()));
+ break;
+ case psOpLt:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 < i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 < r2);
+ }
+ break;
+ case psOpMod:
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 % i2);
+ break;
+ case psOpMul:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ //~ should check for out-of-range, and push a real instead
+ stack->pushInt(i1 * i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(r1 * r2);
+ }
+ break;
+ case psOpNe:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushBool(i1 != i2);
+ } else if (stack->topTwoAreNums()) {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushBool(r1 != r2);
+ } else {
+ b2 = stack->popBool();
+ b1 = stack->popBool();
+ stack->pushBool(b1 != b2);
+ }
+ break;
+ case psOpNeg:
+ if (stack->topIsInt()) {
+ stack->pushInt(-stack->popInt());
+ } else {
+ stack->pushReal(-stack->popNum());
+ }
+ break;
+ case psOpNot:
+ if (stack->topIsInt()) {
+ stack->pushInt(~stack->popInt());
+ } else {
+ stack->pushBool(!stack->popBool());
+ }
+ break;
+ case psOpOr:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 | i2);
+ } else {
+ b2 = stack->popBool();
+ b1 = stack->popBool();
+ stack->pushBool(b1 || b2);
+ }
+ break;
+ case psOpPop:
+ stack->pop();
+ break;
+ case psOpRoll:
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->roll(i1, i2);
+ break;
+ case psOpRound:
+ if (!stack->topIsInt()) {
+ r1 = stack->popNum();
+ stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
+ }
+ break;
+ case psOpSin:
+ stack->pushReal(sin(stack->popNum()));
+ break;
+ case psOpSqrt:
+ stack->pushReal(sqrt(stack->popNum()));
+ break;
+ case psOpSub:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 - i2);
+ } else {
+ r2 = stack->popNum();
+ r1 = stack->popNum();
+ stack->pushReal(r1 - r2);
+ }
+ break;
+ case psOpTrue:
+ stack->pushBool(gTrue);
+ break;
+ case psOpTruncate:
+ if (!stack->topIsInt()) {
+ r1 = stack->popNum();
+ stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1));
+ }
+ break;
+ case psOpXor:
+ if (stack->topTwoAreInts()) {
+ i2 = stack->popInt();
+ i1 = stack->popInt();
+ stack->pushInt(i1 ^ i2);
+ } else {
+ b2 = stack->popBool();
+ b1 = stack->popBool();
+ stack->pushBool(b1 ^ b2);
+ }
+ break;
+ case psOpIf:
+ b1 = stack->popBool();
+ if (b1) {
+ exec(stack, codePtr + 2);
+ }
+ codePtr = code[codePtr + 1].blk;
+ break;
+ case psOpIfelse:
+ b1 = stack->popBool();
+ if (b1) {
+ exec(stack, codePtr + 2);
+ } else {
+ exec(stack, code[codePtr].blk);
+ }
+ codePtr = code[codePtr + 1].blk;
+ break;
+ case psOpReturn:
+ return;
+ }
+ break;
+ default:
+ error(-1, "Internal: bad object in PostScript function code");
+ break;
+ }
+ }
+}
diff --git a/pdftops/Function.h b/pdftops/Function.h
new file mode 100644
index 000000000..bcde6a0aa
--- /dev/null
+++ b/pdftops/Function.h
@@ -0,0 +1,183 @@
+//========================================================================
+//
+// Function.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef FUNCTION_H
+#define FUNCTION_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+
+class Dict;
+class Stream;
+struct PSObject;
+class PSStack;
+
+//------------------------------------------------------------------------
+// Function
+//------------------------------------------------------------------------
+
+#define funcMaxInputs 8
+#define funcMaxOutputs 8
+
+class Function {
+public:
+
+ Function();
+
+ virtual ~Function();
+
+ // Construct a function. Returns NULL if unsuccessful.
+ static Function *parse(Object *funcObj);
+
+ // Initialize the entries common to all function types.
+ GBool init(Dict *dict);
+
+ virtual Function *copy() = 0;
+
+ // Return size of input and output tuples.
+ int getInputSize() { return m; }
+ int getOutputSize() { return n; }
+
+ // Transform an input tuple into an output tuple.
+ virtual void transform(double *in, double *out) = 0;
+
+ virtual GBool isOk() = 0;
+
+protected:
+
+ int m, n; // size of input and output tuples
+ double // min and max values for function domain
+ domain[funcMaxInputs][2];
+ double // min and max values for function range
+ range[funcMaxOutputs][2];
+ GBool hasRange; // set if range is defined
+};
+
+//------------------------------------------------------------------------
+// IdentityFunction
+//------------------------------------------------------------------------
+
+class IdentityFunction: public Function {
+public:
+
+ IdentityFunction();
+ virtual ~IdentityFunction();
+ virtual Function *copy() { return new IdentityFunction(); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return gTrue; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+class SampledFunction: public Function {
+public:
+
+ SampledFunction(Object *funcObj, Dict *dict);
+ virtual ~SampledFunction();
+ virtual Function *copy() { return new SampledFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ SampledFunction(SampledFunction *func);
+
+ int // number of samples for each domain element
+ sampleSize[funcMaxInputs];
+ double // min and max values for domain encoder
+ encode[funcMaxInputs][2];
+ double // min and max values for range decoder
+ decode[funcMaxOutputs][2];
+ double *samples; // the samples
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+class ExponentialFunction: public Function {
+public:
+
+ ExponentialFunction(Object *funcObj, Dict *dict);
+ virtual ~ExponentialFunction();
+ virtual Function *copy() { return new ExponentialFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ ExponentialFunction(ExponentialFunction *func);
+
+ double c0[funcMaxOutputs];
+ double c1[funcMaxOutputs];
+ double e;
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// StitchingFunction
+//------------------------------------------------------------------------
+
+class StitchingFunction: public Function {
+public:
+
+ StitchingFunction(Object *funcObj, Dict *dict);
+ virtual ~StitchingFunction();
+ virtual Function *copy() { return new StitchingFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ StitchingFunction(StitchingFunction *func);
+
+ int k;
+ Function **funcs;
+ double *bounds;
+ double *encode;
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// PostScriptFunction
+//------------------------------------------------------------------------
+
+class PostScriptFunction: public Function {
+public:
+
+ PostScriptFunction(Object *funcObj, Dict *dict);
+ virtual ~PostScriptFunction();
+ virtual Function *copy() { return new PostScriptFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ PostScriptFunction(PostScriptFunction *func);
+ GBool parseCode(Stream *str, int *codePtr);
+ GString *getToken(Stream *str);
+ void resizeCode(int newSize);
+ void exec(PSStack *stack, int codePtr);
+
+ PSObject *code;
+ int codeSize;
+ GBool ok;
+};
+
+#endif
diff --git a/pdftops/GB12CMapInfo.h b/pdftops/GB12CMapInfo.h
new file mode 100644
index 000000000..880375737
--- /dev/null
+++ b/pdftops/GB12CMapInfo.h
@@ -0,0 +1,50880 @@
+//========================================================================
+//
+// GB12CMapInfo.h
+//
+// This file was automatically generated by makeCMapInfo.
+//
+// Copyright 1998 Derek B. Noonburg
+//
+//========================================================================
+
+#ifndef GB12CMAPINFO_H
+#define GB12CMAPINFO_H
+
+static Gushort gb12AdobeGB10Map2[66] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12AdobeGB10Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12AdobeGB10Map2, 33
+};
+
+static Gushort gb12AdobeGB11Map2[82] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12AdobeGB11Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12AdobeGB11Map2, 41
+};
+
+static Gushort gb12AdobeGB12Map2[178] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0x4400, 0x4400,
+ 0x4500, 0x4500,
+ 0x4600, 0x4600,
+ 0x4700, 0x4700,
+ 0x4800, 0x4800,
+ 0x4900, 0x4900,
+ 0x4a00, 0x4a00,
+ 0x4b00, 0x4b00,
+ 0x4c00, 0x4c00,
+ 0x4d00, 0x4d00,
+ 0x4e00, 0x4e00,
+ 0x4f00, 0x4f00,
+ 0x5000, 0x5000,
+ 0x5100, 0x5100,
+ 0x5200, 0x5200,
+ 0x5300, 0x5300,
+ 0x5400, 0x5400,
+ 0x5500, 0x5500,
+ 0x5600, 0x5600,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12AdobeGB12Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12AdobeGB12Map2, 89
+};
+
+static Gushort gb12GBEUCHMap2[180] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb1a1, 0x040a,
+ 0xb2a1, 0x0468,
+ 0xb3a1, 0x04c6,
+ 0xb4a1, 0x0524,
+ 0xb5a1, 0x0582,
+ 0xb6a1, 0x05e0,
+ 0xb7a1, 0x063e,
+ 0xb8a1, 0x069c,
+ 0xb9a1, 0x06fa,
+ 0xbaa1, 0x0758,
+ 0xbba1, 0x07b6,
+ 0xbca1, 0x0814,
+ 0xbda1, 0x0872,
+ 0xbea1, 0x08d0,
+ 0xbfa1, 0x092e,
+ 0xc0a1, 0x098c,
+ 0xc1a1, 0x09ea,
+ 0xc2a1, 0x0a48,
+ 0xc3a1, 0x0aa6,
+ 0xc4a1, 0x0b04,
+ 0xc5a1, 0x0b62,
+ 0xc6a1, 0x0bc0,
+ 0xc7a1, 0x0c1e,
+ 0xc8a1, 0x0c7c,
+ 0xc9a1, 0x0cda,
+ 0xcaa1, 0x0d38,
+ 0xcba1, 0x0d96,
+ 0xcca1, 0x0df4,
+ 0xcda1, 0x0e52,
+ 0xcea1, 0x0eb0,
+ 0xcfa1, 0x0f0e,
+ 0xd0a1, 0x0f6c,
+ 0xd1a1, 0x0fca,
+ 0xd2a1, 0x1028,
+ 0xd3a1, 0x1086,
+ 0xd4a1, 0x10e4,
+ 0xd5a1, 0x1142,
+ 0xd6a1, 0x11a0,
+ 0xd7a1, 0x11fe,
+ 0xd8a1, 0x1257,
+ 0xd9a1, 0x12b5,
+ 0xdaa1, 0x1313,
+ 0xdba1, 0x1371,
+ 0xdca1, 0x13cf,
+ 0xdda1, 0x142d,
+ 0xdea1, 0x148b,
+ 0xdfa1, 0x14e9,
+ 0xe0a1, 0x1547,
+ 0xe1a1, 0x15a5,
+ 0xe2a1, 0x1603,
+ 0xe3a1, 0x1661,
+ 0xe4a1, 0x16bf,
+ 0xe5a1, 0x171d,
+ 0xe6a1, 0x177b,
+ 0xe7a1, 0x17d9,
+ 0xe8a1, 0x1837,
+ 0xe9a1, 0x1895,
+ 0xeaa1, 0x18f3,
+ 0xeba1, 0x1951,
+ 0xeca1, 0x19af,
+ 0xeda1, 0x1a0d,
+ 0xeea1, 0x1a6b,
+ 0xefa1, 0x1ac9,
+ 0xf0a1, 0x1b27,
+ 0xf1a1, 0x1b85,
+ 0xf2a1, 0x1be3,
+ 0xf3a1, 0x1c41,
+ 0xf4a1, 0x1c9f,
+ 0xf5a1, 0x1cfd,
+ 0xf6a1, 0x1d5b,
+ 0xf7a1, 0x1db9,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBEUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBEUCHMap2, 90
+};
+
+static Gushort gb12GBEUCVMap2[220] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb1a1, 0x040a,
+ 0xb2a1, 0x0468,
+ 0xb3a1, 0x04c6,
+ 0xb4a1, 0x0524,
+ 0xb5a1, 0x0582,
+ 0xb6a1, 0x05e0,
+ 0xb7a1, 0x063e,
+ 0xb8a1, 0x069c,
+ 0xb9a1, 0x06fa,
+ 0xbaa1, 0x0758,
+ 0xbba1, 0x07b6,
+ 0xbca1, 0x0814,
+ 0xbda1, 0x0872,
+ 0xbea1, 0x08d0,
+ 0xbfa1, 0x092e,
+ 0xc0a1, 0x098c,
+ 0xc1a1, 0x09ea,
+ 0xc2a1, 0x0a48,
+ 0xc3a1, 0x0aa6,
+ 0xc4a1, 0x0b04,
+ 0xc5a1, 0x0b62,
+ 0xc6a1, 0x0bc0,
+ 0xc7a1, 0x0c1e,
+ 0xc8a1, 0x0c7c,
+ 0xc9a1, 0x0cda,
+ 0xcaa1, 0x0d38,
+ 0xcba1, 0x0d96,
+ 0xcca1, 0x0df4,
+ 0xcda1, 0x0e52,
+ 0xcea1, 0x0eb0,
+ 0xcfa1, 0x0f0e,
+ 0xd0a1, 0x0f6c,
+ 0xd1a1, 0x0fca,
+ 0xd2a1, 0x1028,
+ 0xd3a1, 0x1086,
+ 0xd4a1, 0x10e4,
+ 0xd5a1, 0x1142,
+ 0xd6a1, 0x11a0,
+ 0xd7a1, 0x11fe,
+ 0xd8a1, 0x1257,
+ 0xd9a1, 0x12b5,
+ 0xdaa1, 0x1313,
+ 0xdba1, 0x1371,
+ 0xdca1, 0x13cf,
+ 0xdda1, 0x142d,
+ 0xdea1, 0x148b,
+ 0xdfa1, 0x14e9,
+ 0xe0a1, 0x1547,
+ 0xe1a1, 0x15a5,
+ 0xe2a1, 0x1603,
+ 0xe3a1, 0x1661,
+ 0xe4a1, 0x16bf,
+ 0xe5a1, 0x171d,
+ 0xe6a1, 0x177b,
+ 0xe7a1, 0x17d9,
+ 0xe8a1, 0x1837,
+ 0xe9a1, 0x1895,
+ 0xeaa1, 0x18f3,
+ 0xeba1, 0x1951,
+ 0xeca1, 0x19af,
+ 0xeda1, 0x1a0d,
+ 0xeea1, 0x1a6b,
+ 0xefa1, 0x1ac9,
+ 0xf0a1, 0x1b27,
+ 0xf1a1, 0x1b85,
+ 0xf2a1, 0x1be3,
+ 0xf3a1, 0x1c41,
+ 0xf4a1, 0x1c9f,
+ 0xf5a1, 0x1cfd,
+ 0xf6a1, 0x1d5b,
+ 0xf7a1, 0x1db9,
+ 0xa1a2, 0x023f,
+ 0xa1a3, 0x023e,
+ 0xa1aa, 0x0256,
+ 0xa1ab, 0x1e18,
+ 0xa1ad, 0x0257,
+ 0xa1b2, 0x0246,
+ 0xa1fe, 0x1e1a,
+ 0xa3a1, 0x0242,
+ 0xa3a8, 0x0244,
+ 0xa3ac, 0x023d,
+ 0xa3ae, 0x1e1b,
+ 0xa3ba, 0x0240,
+ 0xa3bd, 0x1e1c,
+ 0xa3bf, 0x0243,
+ 0xa3db, 0x1e1d,
+ 0xa3dd, 0x1e1e,
+ 0xa3df, 0x0258,
+ 0xa3fb, 0x0254,
+ 0xa3fd, 0x0255,
+ 0xa3fe, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBEUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBEUCVMap2, 110
+};
+
+static Gushort gb12GBHMap2[180] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0060,
+ 0x2231, 0x00be,
+ 0x2265, 0x00f0,
+ 0x2271, 0x00fa,
+ 0x2321, 0x0106,
+ 0x2421, 0x0164,
+ 0x2521, 0x01b7,
+ 0x2621, 0x020d,
+ 0x2641, 0x0225,
+ 0x2721, 0x025a,
+ 0x2751, 0x027b,
+ 0x2821, 0x029c,
+ 0x2845, 0x02bc,
+ 0x2924, 0x02e2,
+ 0x2a21, 0x032e,
+ 0x2b21, 0x038c,
+ 0x3021, 0x03ac,
+ 0x3121, 0x040a,
+ 0x3221, 0x0468,
+ 0x3321, 0x04c6,
+ 0x3421, 0x0524,
+ 0x3521, 0x0582,
+ 0x3621, 0x05e0,
+ 0x3721, 0x063e,
+ 0x3821, 0x069c,
+ 0x3921, 0x06fa,
+ 0x3a21, 0x0758,
+ 0x3b21, 0x07b6,
+ 0x3c21, 0x0814,
+ 0x3d21, 0x0872,
+ 0x3e21, 0x08d0,
+ 0x3f21, 0x092e,
+ 0x4021, 0x098c,
+ 0x4121, 0x09ea,
+ 0x4221, 0x0a48,
+ 0x4321, 0x0aa6,
+ 0x4421, 0x0b04,
+ 0x4521, 0x0b62,
+ 0x4621, 0x0bc0,
+ 0x4721, 0x0c1e,
+ 0x4821, 0x0c7c,
+ 0x4921, 0x0cda,
+ 0x4a21, 0x0d38,
+ 0x4b21, 0x0d96,
+ 0x4c21, 0x0df4,
+ 0x4d21, 0x0e52,
+ 0x4e21, 0x0eb0,
+ 0x4f21, 0x0f0e,
+ 0x5021, 0x0f6c,
+ 0x5121, 0x0fca,
+ 0x5221, 0x1028,
+ 0x5321, 0x1086,
+ 0x5421, 0x10e4,
+ 0x5521, 0x1142,
+ 0x5621, 0x11a0,
+ 0x5721, 0x11fe,
+ 0x5821, 0x1257,
+ 0x5921, 0x12b5,
+ 0x5a21, 0x1313,
+ 0x5b21, 0x1371,
+ 0x5c21, 0x13cf,
+ 0x5d21, 0x142d,
+ 0x5e21, 0x148b,
+ 0x5f21, 0x14e9,
+ 0x6021, 0x1547,
+ 0x6121, 0x15a5,
+ 0x6221, 0x1603,
+ 0x6321, 0x1661,
+ 0x6421, 0x16bf,
+ 0x6521, 0x171d,
+ 0x6621, 0x177b,
+ 0x6721, 0x17d9,
+ 0x6821, 0x1837,
+ 0x6921, 0x1895,
+ 0x6a21, 0x18f3,
+ 0x6b21, 0x1951,
+ 0x6c21, 0x19af,
+ 0x6d21, 0x1a0d,
+ 0x6e21, 0x1a6b,
+ 0x6f21, 0x1ac9,
+ 0x7021, 0x1b27,
+ 0x7121, 0x1b85,
+ 0x7221, 0x1be3,
+ 0x7321, 0x1c41,
+ 0x7421, 0x1c9f,
+ 0x7521, 0x1cfd,
+ 0x7621, 0x1d5b,
+ 0x7721, 0x1db9,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBHMap2, 90
+};
+
+static Gushort gb12GBVMap2[220] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0060,
+ 0x2231, 0x00be,
+ 0x2265, 0x00f0,
+ 0x2271, 0x00fa,
+ 0x2321, 0x0106,
+ 0x2421, 0x0164,
+ 0x2521, 0x01b7,
+ 0x2621, 0x020d,
+ 0x2641, 0x0225,
+ 0x2721, 0x025a,
+ 0x2751, 0x027b,
+ 0x2821, 0x029c,
+ 0x2845, 0x02bc,
+ 0x2924, 0x02e2,
+ 0x2a21, 0x032e,
+ 0x2b21, 0x038c,
+ 0x3021, 0x03ac,
+ 0x3121, 0x040a,
+ 0x3221, 0x0468,
+ 0x3321, 0x04c6,
+ 0x3421, 0x0524,
+ 0x3521, 0x0582,
+ 0x3621, 0x05e0,
+ 0x3721, 0x063e,
+ 0x3821, 0x069c,
+ 0x3921, 0x06fa,
+ 0x3a21, 0x0758,
+ 0x3b21, 0x07b6,
+ 0x3c21, 0x0814,
+ 0x3d21, 0x0872,
+ 0x3e21, 0x08d0,
+ 0x3f21, 0x092e,
+ 0x4021, 0x098c,
+ 0x4121, 0x09ea,
+ 0x4221, 0x0a48,
+ 0x4321, 0x0aa6,
+ 0x4421, 0x0b04,
+ 0x4521, 0x0b62,
+ 0x4621, 0x0bc0,
+ 0x4721, 0x0c1e,
+ 0x4821, 0x0c7c,
+ 0x4921, 0x0cda,
+ 0x4a21, 0x0d38,
+ 0x4b21, 0x0d96,
+ 0x4c21, 0x0df4,
+ 0x4d21, 0x0e52,
+ 0x4e21, 0x0eb0,
+ 0x4f21, 0x0f0e,
+ 0x5021, 0x0f6c,
+ 0x5121, 0x0fca,
+ 0x5221, 0x1028,
+ 0x5321, 0x1086,
+ 0x5421, 0x10e4,
+ 0x5521, 0x1142,
+ 0x5621, 0x11a0,
+ 0x5721, 0x11fe,
+ 0x5821, 0x1257,
+ 0x5921, 0x12b5,
+ 0x5a21, 0x1313,
+ 0x5b21, 0x1371,
+ 0x5c21, 0x13cf,
+ 0x5d21, 0x142d,
+ 0x5e21, 0x148b,
+ 0x5f21, 0x14e9,
+ 0x6021, 0x1547,
+ 0x6121, 0x15a5,
+ 0x6221, 0x1603,
+ 0x6321, 0x1661,
+ 0x6421, 0x16bf,
+ 0x6521, 0x171d,
+ 0x6621, 0x177b,
+ 0x6721, 0x17d9,
+ 0x6821, 0x1837,
+ 0x6921, 0x1895,
+ 0x6a21, 0x18f3,
+ 0x6b21, 0x1951,
+ 0x6c21, 0x19af,
+ 0x6d21, 0x1a0d,
+ 0x6e21, 0x1a6b,
+ 0x6f21, 0x1ac9,
+ 0x7021, 0x1b27,
+ 0x7121, 0x1b85,
+ 0x7221, 0x1be3,
+ 0x7321, 0x1c41,
+ 0x7421, 0x1c9f,
+ 0x7521, 0x1cfd,
+ 0x7621, 0x1d5b,
+ 0x7721, 0x1db9,
+ 0x2122, 0x023f,
+ 0x2123, 0x023e,
+ 0x212a, 0x0256,
+ 0x212b, 0x1e18,
+ 0x212d, 0x0257,
+ 0x2132, 0x0246,
+ 0x217e, 0x1e1a,
+ 0x2321, 0x0242,
+ 0x2328, 0x0244,
+ 0x232c, 0x023d,
+ 0x232e, 0x1e1b,
+ 0x233a, 0x0240,
+ 0x233d, 0x1e1c,
+ 0x233f, 0x0243,
+ 0x235b, 0x1e1d,
+ 0x235d, 0x1e1e,
+ 0x235f, 0x0258,
+ 0x237b, 0x0254,
+ 0x237d, 0x0255,
+ 0x237e, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBVMap2, 110
+};
+
+static Gushort gb12GBKEUCHMap2[8142] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x2758,
+ 0x8179, 0x2059,
+ 0x817a, 0x2791,
+ 0x8180, 0x2796,
+ 0x8186, 0x21f1,
+ 0x8187, 0x279c,
+ 0x81ed, 0x1ff2,
+ 0x81ee, 0x2802,
+ 0x81f6, 0x205d,
+ 0x81f7, 0x280a,
+ 0x8240, 0x2812,
+ 0x8253, 0x269c,
+ 0x8254, 0x2825,
+ 0x8262, 0x21b5,
+ 0x8263, 0x2833,
+ 0x8274, 0x22cc,
+ 0x8275, 0x2844,
+ 0x827a, 0x2016,
+ 0x827b, 0x2849,
+ 0x827d, 0x1e62,
+ 0x827e, 0x284b,
+ 0x8280, 0x1f20,
+ 0x8281, 0x284c,
+ 0x8283, 0x207f,
+ 0x8284, 0x284e,
+ 0x8290, 0x205c,
+ 0x8291, 0x285a,
+ 0x82a5, 0x2194,
+ 0x82a6, 0x286e,
+ 0x82c8, 0x1e65,
+ 0x82c9, 0x2281,
+ 0x82ca, 0x2890,
+ 0x82e1, 0x22cd,
+ 0x82e2, 0x28a7,
+ 0x82e3, 0x210a,
+ 0x82e4, 0x1e3e,
+ 0x82e5, 0x28a8,
+ 0x82ed, 0x267f,
+ 0x82ee, 0x28b0,
+ 0x82f2, 0x222e,
+ 0x82f3, 0x28b4,
+ 0x82f7, 0x1e96,
+ 0x82f8, 0x22cb,
+ 0x82f9, 0x226c,
+ 0x82fa, 0x28b8,
+ 0x82fb, 0x2117,
+ 0x82fc, 0x28b9,
+ 0x8340, 0x28bc,
+ 0x8341, 0x20e8,
+ 0x8342, 0x28bd,
+ 0x8345, 0x22d4,
+ 0x8346, 0x28c0,
+ 0x8348, 0x1fb9,
+ 0x8349, 0x28c2,
+ 0x834c, 0x22d8,
+ 0x834d, 0x28c5,
+ 0x8353, 0x20df,
+ 0x8354, 0x28cb,
+ 0x8357, 0x20c2,
+ 0x8358, 0x28ce,
+ 0x835e, 0x2195,
+ 0x835f, 0x28d4,
+ 0x8365, 0x1fac,
+ 0x8366, 0x22d3,
+ 0x8367, 0x28da,
+ 0x8372, 0x1f81,
+ 0x8373, 0x28e5,
+ 0x8378, 0x2210,
+ 0x8379, 0x28ea,
+ 0x837a, 0x22cf,
+ 0x837b, 0x28eb,
+ 0x837c, 0x2213,
+ 0x837d, 0x28ec,
+ 0x837e, 0x1fe4,
+ 0x8380, 0x1f90,
+ 0x8381, 0x28ed,
+ 0x8386, 0x22d6,
+ 0x8387, 0x28f2,
+ 0x8389, 0x22d0,
+ 0x838a, 0x22ce,
+ 0x838b, 0x28f4,
+ 0x838d, 0x2681,
+ 0x838e, 0x28f6,
+ 0x8394, 0x1e76,
+ 0x8395, 0x28fc,
+ 0x839e, 0x2231,
+ 0x839f, 0x2905,
+ 0x83a6, 0x1e93,
+ 0x83a7, 0x290c,
+ 0x83ab, 0x22d2,
+ 0x83ac, 0x2910,
+ 0x83ae, 0x22d7,
+ 0x83af, 0x22d5,
+ 0x83b0, 0x22d1,
+ 0x83b1, 0x2912,
+ 0x83ba, 0x1ee5,
+ 0x83bb, 0x291b,
+ 0x83c9, 0x2025,
+ 0x83ca, 0x2929,
+ 0x83f6, 0x1ecf,
+ 0x83f7, 0x2955,
+ 0x8440, 0x295d,
+ 0x8450, 0x1fd9,
+ 0x8451, 0x296d,
+ 0x8471, 0x22c8,
+ 0x8472, 0x298d,
+ 0x8474, 0x2263,
+ 0x8475, 0x298f,
+ 0x8477, 0x2683,
+ 0x8478, 0x2991,
+ 0x8480, 0x2998,
+ 0x8482, 0x1f17,
+ 0x8483, 0x299a,
+ 0x848e, 0x1f2b,
+ 0x848f, 0x29a5,
+ 0x8492, 0x22ca,
+ 0x8493, 0x1e99,
+ 0x8494, 0x29a8,
+ 0x849d, 0x1f4f,
+ 0x849e, 0x29b1,
+ 0x84a1, 0x1fcf,
+ 0x84a2, 0x2036,
+ 0x84a3, 0x1f3a,
+ 0x84a4, 0x29b4,
+ 0x84a5, 0x22c9,
+ 0x84a6, 0x1f99,
+ 0x84a7, 0x29b5,
+ 0x84a9, 0x1f75,
+ 0x84aa, 0x29b7,
+ 0x84c5, 0x1fbe,
+ 0x84c6, 0x29d2,
+ 0x84d3, 0x1ecd,
+ 0x84d4, 0x29df,
+ 0x84d5, 0x21a9,
+ 0x84d6, 0x29e0,
+ 0x84d7, 0x21e6,
+ 0x84d8, 0x29e1,
+ 0x84d9, 0x2127,
+ 0x84da, 0x2003,
+ 0x84db, 0x29e2,
+ 0x84dd, 0x2132,
+ 0x84de, 0x29e4,
+ 0x84ea, 0x2323,
+ 0x84eb, 0x29f0,
+ 0x84ee, 0x2011,
+ 0x84ef, 0x29f3,
+ 0x84f1, 0x20f5,
+ 0x84f2, 0x29f5,
+ 0x8540, 0x2a02,
+ 0x8551, 0x22c5,
+ 0x8552, 0x1f5e,
+ 0x8553, 0x2a13,
+ 0x8554, 0x22c6,
+ 0x8555, 0x2a14,
+ 0x855e, 0x20ef,
+ 0x855f, 0x2a1d,
+ 0x8566, 0x21d0,
+ 0x8567, 0x2a24,
+ 0x8580, 0x2a3c,
+ 0x8587, 0x22c1,
+ 0x8588, 0x2a43,
+ 0x858b, 0x1e64,
+ 0x858c, 0x2a46,
+ 0x8592, 0x21f9,
+ 0x8593, 0x2a4c,
+ 0x8596, 0x2010,
+ 0x8597, 0x2a4f,
+ 0x8598, 0x22c2,
+ 0x8599, 0x2a50,
+ 0x85a2, 0x1e5a,
+ 0x85a3, 0x2a59,
+ 0x85b2, 0x1ea2,
+ 0x85b3, 0x2a68,
+ 0x8640, 0x2ab4,
+ 0x864a, 0x236d,
+ 0x864b, 0x2abe,
+ 0x8654, 0x2247,
+ 0x8655, 0x2ac7,
+ 0x8668, 0x236c,
+ 0x8669, 0x2ada,
+ 0x8680, 0x2af0,
+ 0x8696, 0x219c,
+ 0x8697, 0x2b06,
+ 0x8699, 0x20c9,
+ 0x869a, 0x2b08,
+ 0x86a1, 0x21f0,
+ 0x86a2, 0x2b0f,
+ 0x86ca, 0x210b,
+ 0x86cb, 0x2b37,
+ 0x86cc, 0x20de,
+ 0x86cd, 0x2b38,
+ 0x86ce, 0x1eaa,
+ 0x86cf, 0x2b39,
+ 0x86d1, 0x222c,
+ 0x86d2, 0x2b3b,
+ 0x86dc, 0x20d8,
+ 0x86dd, 0x22c0,
+ 0x86de, 0x2b45,
+ 0x86e1, 0x206f,
+ 0x86e2, 0x2b48,
+ 0x86e8, 0x21a1,
+ 0x86e9, 0x2b4e,
+ 0x86ee, 0x2379,
+ 0x86ef, 0x2b53,
+ 0x86f4, 0x2372,
+ 0x86f5, 0x2b58,
+ 0x8740, 0x216a,
+ 0x8741, 0x2b62,
+ 0x8744, 0x237c,
+ 0x8745, 0x2b65,
+ 0x8749, 0x20b0,
+ 0x874a, 0x2b69,
+ 0x874b, 0x237a,
+ 0x874c, 0x1e74,
+ 0x874d, 0x2b6a,
+ 0x874f, 0x2377,
+ 0x8750, 0x2b6c,
+ 0x8757, 0x1f4c,
+ 0x8758, 0x2b73,
+ 0x875a, 0x2378,
+ 0x875b, 0x21cf,
+ 0x875c, 0x2368,
+ 0x875d, 0x2b75,
+ 0x875e, 0x2371,
+ 0x875f, 0x2b76,
+ 0x8760, 0x2369,
+ 0x8761, 0x2b77,
+ 0x8766, 0x2674,
+ 0x8767, 0x2b7c,
+ 0x877a, 0x236f,
+ 0x877b, 0x2b8f,
+ 0x877d, 0x2370,
+ 0x877e, 0x2b91,
+ 0x8780, 0x2b92,
+ 0x8781, 0x2376,
+ 0x8782, 0x2373,
+ 0x8783, 0x2b93,
+ 0x8786, 0x237f,
+ 0x8787, 0x2b96,
+ 0x8788, 0x2374,
+ 0x8789, 0x2b97,
+ 0x878a, 0x20b5,
+ 0x878b, 0x2b98,
+ 0x878d, 0x1edb,
+ 0x878e, 0x2672,
+ 0x878f, 0x2b9a,
+ 0x8793, 0x236e,
+ 0x8794, 0x2b9e,
+ 0x8798, 0x21b7,
+ 0x8799, 0x2ba2,
+ 0x879d, 0x2375,
+ 0x879e, 0x2ba6,
+ 0x87a3, 0x2382,
+ 0x87a4, 0x2bab,
+ 0x87a7, 0x209e,
+ 0x87a8, 0x2bae,
+ 0x87b3, 0x236b,
+ 0x87b4, 0x2bb9,
+ 0x87b5, 0x2039,
+ 0x87b6, 0x2bba,
+ 0x87bb, 0x269f,
+ 0x87bc, 0x2bbf,
+ 0x87bf, 0x237d,
+ 0x87c0, 0x21f5,
+ 0x87c1, 0x2bc2,
+ 0x87c2, 0x2381,
+ 0x87c3, 0x2bc3,
+ 0x87ca, 0x237b,
+ 0x87cb, 0x237e,
+ 0x87cc, 0x21cc,
+ 0x87cd, 0x2bca,
+ 0x87cf, 0x22db,
+ 0x87d0, 0x2bcc,
+ 0x87d2, 0x236a,
+ 0x87d3, 0x2689,
+ 0x87d4, 0x2bce,
+ 0x87d5, 0x2697,
+ 0x87d6, 0x2bcf,
+ 0x87da, 0x22a1,
+ 0x87db, 0x2bd3,
+ 0x87f7, 0x2383,
+ 0x87f8, 0x1f3d,
+ 0x87f9, 0x2bef,
+ 0x87fa, 0x218f,
+ 0x87fb, 0x2bf0,
+ 0x8840, 0x2246,
+ 0x8841, 0x2248,
+ 0x8842, 0x2bf4,
+ 0x8844, 0x217e,
+ 0x8845, 0x2bf6,
+ 0x8846, 0x2180,
+ 0x8847, 0x2bf7,
+ 0x8880, 0x2c2f,
+ 0x88ba, 0x232a,
+ 0x88bb, 0x2c69,
+ 0x88cc, 0x228b,
+ 0x88cd, 0x2c7a,
+ 0x88d4, 0x1f85,
+ 0x88d5, 0x2c81,
+ 0x88d7, 0x2325,
+ 0x88d8, 0x2c83,
+ 0x88df, 0x232c,
+ 0x88e0, 0x2c8a,
+ 0x88e5, 0x232e,
+ 0x88e6, 0x2c8f,
+ 0x88f2, 0x2205,
+ 0x88f3, 0x1e38,
+ 0x88f4, 0x2c9b,
+ 0x88f6, 0x1e73,
+ 0x88f7, 0x2c9d,
+ 0x8940, 0x2ca5,
+ 0x894b, 0x1fe3,
+ 0x894c, 0x2339,
+ 0x894d, 0x2cb0,
+ 0x894e, 0x232b,
+ 0x894f, 0x2cb1,
+ 0x8950, 0x232d,
+ 0x8951, 0x2cb2,
+ 0x8954, 0x217f,
+ 0x8955, 0x2cb5,
+ 0x895d, 0x21a7,
+ 0x895e, 0x2cbd,
+ 0x895f, 0x232f,
+ 0x8960, 0x2cbe,
+ 0x896d, 0x1e7d,
+ 0x896e, 0x2ccb,
+ 0x8971, 0x20d6,
+ 0x8972, 0x2cce,
+ 0x897c, 0x1ec2,
+ 0x897d, 0x2cd8,
+ 0x8980, 0x2cda,
+ 0x898b, 0x22b2,
+ 0x898c, 0x2ce5,
+ 0x8999, 0x1edf,
+ 0x899a, 0x2cf2,
+ 0x899e, 0x1ef9,
+ 0x899f, 0x2cf6,
+ 0x89a6, 0x20d9,
+ 0x89a7, 0x2cfd,
+ 0x89a8, 0x1fdd,
+ 0x89a9, 0x2cfe,
+ 0x89af, 0x2167,
+ 0x89b0, 0x2d04,
+ 0x89ba, 0x21ed,
+ 0x89bb, 0x2d0e,
+ 0x89be, 0x2007,
+ 0x89bf, 0x2326,
+ 0x89c0, 0x2329,
+ 0x89c1, 0x2d11,
+ 0x89c4, 0x1f52,
+ 0x89c5, 0x203b,
+ 0x89c6, 0x2328,
+ 0x89c7, 0x2d14,
+ 0x89c8, 0x2327,
+ 0x89c9, 0x2d15,
+ 0x89ce, 0x1e2b,
+ 0x89cf, 0x2d1a,
+ 0x89d1, 0x22ae,
+ 0x89d2, 0x2d1c,
+ 0x89d8, 0x1f49,
+ 0x89d9, 0x2d22,
+ 0x89db, 0x2138,
+ 0x89dc, 0x2d24,
+ 0x89f4, 0x2081,
+ 0x89f5, 0x2d3c,
+ 0x8a40, 0x2d46,
+ 0x8a41, 0x1f7c,
+ 0x8a42, 0x2d47,
+ 0x8a59, 0x235b,
+ 0x8a5a, 0x1ede,
+ 0x8a5b, 0x2d5e,
+ 0x8a5c, 0x1fa2,
+ 0x8a5d, 0x2d5f,
+ 0x8a5e, 0x1efa,
+ 0x8a5f, 0x2d60,
+ 0x8a79, 0x22ad,
+ 0x8a7a, 0x2d7a,
+ 0x8a80, 0x2d7f,
+ 0x8ae4, 0x203f,
+ 0x8ae5, 0x2de3,
+ 0x8b40, 0x2dfd,
+ 0x8b44, 0x1f0e,
+ 0x8b45, 0x2e01,
+ 0x8b49, 0x23f9,
+ 0x8b4a, 0x2e05,
+ 0x8b7a, 0x23fc,
+ 0x8b7b, 0x2e35,
+ 0x8b80, 0x2e39,
+ 0x8b8c, 0x2069,
+ 0x8b8d, 0x2e45,
+ 0x8b9e, 0x23f7,
+ 0x8b9f, 0x2e56,
+ 0x8bb3, 0x23f6,
+ 0x8bb4, 0x2e6a,
+ 0x8bb9, 0x23fd,
+ 0x8bba, 0x2e6f,
+ 0x8bbe, 0x23f8,
+ 0x8bbf, 0x2e73,
+ 0x8bc6, 0x23fa,
+ 0x8bc7, 0x2e7a,
+ 0x8bc8, 0x23fe,
+ 0x8bc9, 0x1fa8,
+ 0x8bca, 0x2e7b,
+ 0x8bd4, 0x2401,
+ 0x8bd5, 0x2e85,
+ 0x8bdc, 0x23ff,
+ 0x8bdd, 0x2e8c,
+ 0x8be5, 0x2400,
+ 0x8be6, 0x2e94,
+ 0x8beb, 0x2221,
+ 0x8bec, 0x2e99,
+ 0x8bf0, 0x2122,
+ 0x8bf1, 0x2e9d,
+ 0x8c40, 0x2eab,
+ 0x8c44, 0x23fb,
+ 0x8c45, 0x2eaf,
+ 0x8c4f, 0x215a,
+ 0x8c50, 0x2eb9,
+ 0x8c57, 0x21e5,
+ 0x8c58, 0x2ec0,
+ 0x8c5c, 0x2057,
+ 0x8c5d, 0x2ec4,
+ 0x8c80, 0x2ee6,
+ 0x8c8b, 0x20e5,
+ 0x8c8c, 0x2ef1,
+ 0x8c8d, 0x212f,
+ 0x8c8e, 0x20a3,
+ 0x8c8f, 0x2121,
+ 0x8c90, 0x2ef2,
+ 0x8c91, 0x21d4,
+ 0x8c92, 0x1fe5,
+ 0x8c93, 0x2ef3,
+ 0x8c99, 0x1e8a,
+ 0x8c9a, 0x1e37,
+ 0x8c9b, 0x2ef9,
+ 0x8ca2, 0x1f9e,
+ 0x8ca3, 0x22a6,
+ 0x8ca4, 0x21e8,
+ 0x8ca5, 0x2f00,
+ 0x8ca6, 0x1eda,
+ 0x8ca7, 0x1eb9,
+ 0x8ca8, 0x2f01,
+ 0x8cc0, 0x235c,
+ 0x8cc1, 0x2f19,
+ 0x8cd2, 0x2050,
+ 0x8cd3, 0x1e67,
+ 0x8cd4, 0x2f2a,
+ 0x8cd5, 0x23f4,
+ 0x8cd6, 0x2f2b,
+ 0x8cd9, 0x213e,
+ 0x8cda, 0x2f2e,
+ 0x8cf9, 0x1f16,
+ 0x8cfa, 0x2f4d,
+ 0x8d40, 0x2f52,
+ 0x8d73, 0x2389,
+ 0x8d74, 0x2f85,
+ 0x8d75, 0x1eb7,
+ 0x8d76, 0x2f86,
+ 0x8d7b, 0x21b4,
+ 0x8d7c, 0x2f8b,
+ 0x8d80, 0x2f8e,
+ 0x8d88, 0x238f,
+ 0x8d89, 0x2f96,
+ 0x8d8f, 0x1f1a,
+ 0x8d90, 0x2f9c,
+ 0x8d9e, 0x238b,
+ 0x8d9f, 0x2faa,
+ 0x8db9, 0x238a,
+ 0x8dba, 0x2fc4,
+ 0x8de2, 0x2391,
+ 0x8de3, 0x2fec,
+ 0x8de4, 0x2271,
+ 0x8de5, 0x2fed,
+ 0x8de7, 0x2388,
+ 0x8de8, 0x2fef,
+ 0x8df7, 0x238e,
+ 0x8df8, 0x2ffe,
+ 0x8dfe, 0x238d,
+ 0x8e40, 0x3004,
+ 0x8e46, 0x238c,
+ 0x8e47, 0x300a,
+ 0x8e56, 0x2390,
+ 0x8e57, 0x3019,
+ 0x8e58, 0x2033,
+ 0x8e59, 0x301a,
+ 0x8e5a, 0x223c,
+ 0x8e5b, 0x301b,
+ 0x8e68, 0x1fe9,
+ 0x8e69, 0x3028,
+ 0x8e6e, 0x2055,
+ 0x8e6f, 0x302d,
+ 0x8e70, 0x2392,
+ 0x8e71, 0x302e,
+ 0x8e80, 0x2324,
+ 0x8e81, 0x303c,
+ 0x8e9b, 0x2143,
+ 0x8e9c, 0x3056,
+ 0x8e9f, 0x2129,
+ 0x8ea0, 0x3059,
+ 0x8ea4, 0x2277,
+ 0x8ea5, 0x305d,
+ 0x8ea7, 0x1ea7,
+ 0x8ea8, 0x305f,
+ 0x8eac, 0x2285,
+ 0x8ead, 0x3063,
+ 0x8eae, 0x2384,
+ 0x8eaf, 0x3064,
+ 0x8ebd, 0x2387,
+ 0x8ebe, 0x2386,
+ 0x8ebf, 0x3072,
+ 0x8ec3, 0x2290,
+ 0x8ec4, 0x3076,
+ 0x8ec5, 0x1e44,
+ 0x8ec6, 0x3077,
+ 0x8ecd, 0x1e32,
+ 0x8ece, 0x2385,
+ 0x8ecf, 0x307e,
+ 0x8ed6, 0x1f13,
+ 0x8ed7, 0x1f73,
+ 0x8ed8, 0x3085,
+ 0x8eec, 0x1fe0,
+ 0x8eed, 0x3099,
+ 0x8f40, 0x30ab,
+ 0x8f52, 0x2087,
+ 0x8f53, 0x1e78,
+ 0x8f54, 0x23ae,
+ 0x8f55, 0x1ef6,
+ 0x8f56, 0x1f31,
+ 0x8f57, 0x30bd,
+ 0x8f5d, 0x2045,
+ 0x8f5e, 0x30c3,
+ 0x8f64, 0x2178,
+ 0x8f65, 0x30c9,
+ 0x8f80, 0x30e3,
+ 0x8f86, 0x23f5,
+ 0x8f87, 0x30e9,
+ 0x8f88, 0x2275,
+ 0x8f89, 0x30ea,
+ 0x8f95, 0x266e,
+ 0x8f96, 0x30f6,
+ 0x8f97, 0x1eb0,
+ 0x8f98, 0x30f7,
+ 0x8f9b, 0x2083,
+ 0x8f9c, 0x30fa,
+ 0x8f9d, 0x2188,
+ 0x8f9e, 0x30fb,
+ 0x8fa1, 0x267c,
+ 0x8fa2, 0x30fe,
+ 0x8fbd, 0x1fc5,
+ 0x8fbe, 0x3119,
+ 0x8fc4, 0x1ea1,
+ 0x8fc5, 0x311f,
+ 0x8fc6, 0x2393,
+ 0x8fc7, 0x3120,
+ 0x8fcd, 0x1f0b,
+ 0x8fce, 0x3126,
+ 0x8fd8, 0x1e7c,
+ 0x8fd9, 0x3130,
+ 0x9040, 0x3156,
+ 0x9080, 0x3195,
+ 0x909d, 0x23b4,
+ 0x909e, 0x207e,
+ 0x909f, 0x31b2,
+ 0x90ba, 0x1ee3,
+ 0x90bb, 0x31cd,
+ 0x90c0, 0x2095,
+ 0x90c1, 0x23bb,
+ 0x90c2, 0x31d2,
+ 0x90c5, 0x23b9,
+ 0x90c6, 0x31d5,
+ 0x90db, 0x1e28,
+ 0x90dc, 0x23bd,
+ 0x90dd, 0x31ea,
+ 0x90ed, 0x23b5,
+ 0x90ee, 0x31fa,
+ 0x90f0, 0x23ba,
+ 0x90f1, 0x31fc,
+ 0x90f7, 0x23b3,
+ 0x90f8, 0x3202,
+ 0x9140, 0x3209,
+ 0x9142, 0x2162,
+ 0x9143, 0x320b,
+ 0x914b, 0x1e5e,
+ 0x914c, 0x3213,
+ 0x914d, 0x1e5d,
+ 0x914e, 0x3214,
+ 0x9151, 0x23b7,
+ 0x9152, 0x3217,
+ 0x9154, 0x1f2f,
+ 0x9155, 0x24df,
+ 0x9156, 0x3219,
+ 0x9159, 0x23b2,
+ 0x915a, 0x214e,
+ 0x915b, 0x321c,
+ 0x915d, 0x2052,
+ 0x915e, 0x321e,
+ 0x9161, 0x23bc,
+ 0x9162, 0x3221,
+ 0x9163, 0x20eb,
+ 0x9164, 0x3222,
+ 0x916e, 0x2232,
+ 0x916f, 0x322c,
+ 0x9176, 0x1e3f,
+ 0x9177, 0x3233,
+ 0x917a, 0x201b,
+ 0x917b, 0x20bc,
+ 0x917c, 0x23be,
+ 0x917d, 0x3236,
+ 0x9180, 0x3238,
+ 0x9184, 0x1eae,
+ 0x9185, 0x323c,
+ 0x918d, 0x1efb,
+ 0x918e, 0x3244,
+ 0x9191, 0x2089,
+ 0x9192, 0x3247,
+ 0x9193, 0x23b1,
+ 0x9194, 0x3248,
+ 0x9197, 0x21c4,
+ 0x9198, 0x324b,
+ 0x919b, 0x2214,
+ 0x919c, 0x324e,
+ 0x91a9, 0x1fde,
+ 0x91aa, 0x2223,
+ 0x91ab, 0x23b6,
+ 0x91ac, 0x325b,
+ 0x91ba, 0x268c,
+ 0x91bb, 0x24de,
+ 0x91bc, 0x3269,
+ 0x91bf, 0x24e0,
+ 0x91c0, 0x326c,
+ 0x91c3, 0x23b8,
+ 0x91c4, 0x326f,
+ 0x91cd, 0x1e81,
+ 0x91ce, 0x3278,
+ 0x91d0, 0x1ffe,
+ 0x91d1, 0x1f51,
+ 0x91d2, 0x21e1,
+ 0x91d3, 0x327a,
+ 0x91d4, 0x23b0,
+ 0x91d5, 0x327b,
+ 0x91d6, 0x1fce,
+ 0x91d7, 0x327c,
+ 0x91d8, 0x211e,
+ 0x91d9, 0x2021,
+ 0x91da, 0x327d,
+ 0x91df, 0x24e1,
+ 0x91e0, 0x3282,
+ 0x91e2, 0x24a3,
+ 0x91e3, 0x3284,
+ 0x91ea, 0x24a4,
+ 0x91eb, 0x328b,
+ 0x91f0, 0x2273,
+ 0x91f1, 0x3290,
+ 0x91f2, 0x21b0,
+ 0x91f3, 0x3291,
+ 0x9240, 0x329d,
+ 0x9280, 0x32dc,
+ 0x92b6, 0x21d1,
+ 0x92b7, 0x3312,
+ 0x92ce, 0x211c,
+ 0x92cf, 0x3329,
+ 0x92d0, 0x235d,
+ 0x92d1, 0x332a,
+ 0x92d4, 0x2682,
+ 0x92d5, 0x332d,
+ 0x92df, 0x210d,
+ 0x92e0, 0x205a,
+ 0x92e1, 0x3337,
+ 0x92fe, 0x1f8d,
+ 0x9340, 0x3354,
+ 0x9350, 0x21ff,
+ 0x9351, 0x3364,
+ 0x935d, 0x1f58,
+ 0x935e, 0x3370,
+ 0x9370, 0x215b,
+ 0x9371, 0x3382,
+ 0x9376, 0x1eb6,
+ 0x9377, 0x3387,
+ 0x9380, 0x338f,
+ 0x938c, 0x20db,
+ 0x938d, 0x339b,
+ 0x939d, 0x2360,
+ 0x939e, 0x33ab,
+ 0x93a5, 0x2361,
+ 0x93a6, 0x33b2,
+ 0x93a7, 0x2040,
+ 0x93a8, 0x33b3,
+ 0x93b4, 0x228e,
+ 0x93b5, 0x33bf,
+ 0x93b8, 0x1fdf,
+ 0x93b9, 0x33c2,
+ 0x93bb, 0x235e,
+ 0x93bc, 0x33c4,
+ 0x93bd, 0x1e6a,
+ 0x93be, 0x33c5,
+ 0x93c6, 0x2002,
+ 0x93c7, 0x33cd,
+ 0x93cf, 0x2093,
+ 0x93d0, 0x33d5,
+ 0x93d7, 0x235f,
+ 0x93d8, 0x33dc,
+ 0x93db, 0x1eac,
+ 0x93dc, 0x1e54,
+ 0x93dd, 0x33df,
+ 0x93e1, 0x1f08,
+ 0x93e2, 0x33e3,
+ 0x93e4, 0x20c0,
+ 0x93e5, 0x2362,
+ 0x93e6, 0x33e5,
+ 0x93e9, 0x2160,
+ 0x93ea, 0x33e8,
+ 0x93eb, 0x219d,
+ 0x93ec, 0x1f8e,
+ 0x93ed, 0x222d,
+ 0x93ee, 0x33e9,
+ 0x93ef, 0x2047,
+ 0x93f0, 0x33ea,
+ 0x93f1, 0x2262,
+ 0x93f2, 0x33eb,
+ 0x93f4, 0x1f67,
+ 0x93f5, 0x1eb2,
+ 0x93f6, 0x33ed,
+ 0x93fa, 0x1ea9,
+ 0x93fb, 0x33f1,
+ 0x93fe, 0x1fcc,
+ 0x9440, 0x33f4,
+ 0x9444, 0x1f72,
+ 0x9445, 0x33f8,
+ 0x944d, 0x2098,
+ 0x944e, 0x3400,
+ 0x9450, 0x1e52,
+ 0x9451, 0x20a4,
+ 0x9452, 0x1f1c,
+ 0x9453, 0x228f,
+ 0x9454, 0x3402,
+ 0x9455, 0x1fed,
+ 0x9456, 0x3403,
+ 0x9458, 0x2365,
+ 0x9459, 0x3405,
+ 0x945b, 0x1e2d,
+ 0x945c, 0x2152,
+ 0x945d, 0x2366,
+ 0x945e, 0x3407,
+ 0x945f, 0x20fa,
+ 0x9460, 0x3408,
+ 0x9464, 0x2363,
+ 0x9465, 0x340c,
+ 0x9466, 0x209a,
+ 0x9467, 0x340d,
+ 0x946e, 0x203c,
+ 0x946f, 0x3414,
+ 0x9472, 0x1ff6,
+ 0x9473, 0x3417,
+ 0x9474, 0x2364,
+ 0x9475, 0x3418,
+ 0x9476, 0x1e69,
+ 0x9477, 0x3419,
+ 0x9478, 0x2367,
+ 0x9479, 0x341a,
+ 0x947a, 0x211d,
+ 0x947b, 0x341b,
+ 0x9480, 0x2259,
+ 0x9481, 0x2056,
+ 0x9482, 0x2163,
+ 0x9483, 0x341f,
+ 0x9487, 0x1fa9,
+ 0x9488, 0x1ffc,
+ 0x9489, 0x3423,
+ 0x94a1, 0x1e2e,
+ 0x94a2, 0x343b,
+ 0x94b3, 0x1ebc,
+ 0x94b4, 0x344c,
+ 0x94b5, 0x2142,
+ 0x94b6, 0x344d,
+ 0x94bf, 0x201e,
+ 0x94c0, 0x1e43,
+ 0x94c1, 0x3456,
+ 0x94cc, 0x24d4,
+ 0x94cd, 0x3461,
+ 0x94d8, 0x226f,
+ 0x94d9, 0x346c,
+ 0x94e0, 0x1ed7,
+ 0x94e1, 0x3473,
+ 0x9540, 0x3491,
+ 0x9572, 0x212d,
+ 0x9573, 0x34c3,
+ 0x9580, 0x34cf,
+ 0x9583, 0x229b,
+ 0x9584, 0x34d2,
+ 0x959e, 0x2256,
+ 0x959f, 0x24a8,
+ 0x95a0, 0x34ec,
+ 0x95b3, 0x1e79,
+ 0x95b4, 0x34ff,
+ 0x95ba, 0x225a,
+ 0x95bb, 0x3505,
+ 0x95cf, 0x24a7,
+ 0x95d0, 0x3519,
+ 0x95d1, 0x2686,
+ 0x95d2, 0x24a6,
+ 0x95d3, 0x351a,
+ 0x95d4, 0x21ce,
+ 0x95d5, 0x351b,
+ 0x95e1, 0x24a9,
+ 0x95e2, 0x3527,
+ 0x95e7, 0x1fe7,
+ 0x95e8, 0x352c,
+ 0x95f1, 0x2112,
+ 0x95f2, 0x3535,
+ 0x95f8, 0x213c,
+ 0x95f9, 0x353b,
+ 0x95fe, 0x1f5c,
+ 0x9640, 0x3540,
+ 0x9656, 0x24c4,
+ 0x9657, 0x3556,
+ 0x967c, 0x1ecc,
+ 0x967d, 0x357b,
+ 0x9680, 0x357d,
+ 0x9740, 0x35fc,
+ 0x9767, 0x246a,
+ 0x9768, 0x3623,
+ 0x976c, 0x2175,
+ 0x976d, 0x3627,
+ 0x976e, 0x246d,
+ 0x976f, 0x3628,
+ 0x9780, 0x3638,
+ 0x9796, 0x246b,
+ 0x9797, 0x225f,
+ 0x9798, 0x364e,
+ 0x979d, 0x1ece,
+ 0x979e, 0x3653,
+ 0x97a3, 0x2272,
+ 0x97a4, 0x3658,
+ 0x97bf, 0x2473,
+ 0x97c0, 0x3673,
+ 0x97ee, 0x21fe,
+ 0x97ef, 0x36a1,
+ 0x97f7, 0x1efe,
+ 0x97f8, 0x36a9,
+ 0x9840, 0x36b0,
+ 0x9845, 0x2475,
+ 0x9846, 0x36b5,
+ 0x9849, 0x220a,
+ 0x984a, 0x36b8,
+ 0x984f, 0x1f6f,
+ 0x9850, 0x36bd,
+ 0x9871, 0x2468,
+ 0x9872, 0x36de,
+ 0x9873, 0x2100,
+ 0x9874, 0x36df,
+ 0x9880, 0x36ea,
+ 0x9881, 0x2476,
+ 0x9882, 0x36eb,
+ 0x988b, 0x1f27,
+ 0x988c, 0x20d7,
+ 0x988d, 0x36f4,
+ 0x98a0, 0x247c,
+ 0x98a1, 0x3707,
+ 0x98aa, 0x1fa1,
+ 0x98ab, 0x3710,
+ 0x98b6, 0x22aa,
+ 0x98b7, 0x2005,
+ 0x98b8, 0x371b,
+ 0x98ba, 0x246c,
+ 0x98bb, 0x371d,
+ 0x98c7, 0x203e,
+ 0x98c8, 0x3729,
+ 0x98cb, 0x1e4c,
+ 0x98cc, 0x372c,
+ 0x98d0, 0x213a,
+ 0x98d1, 0x3730,
+ 0x98d3, 0x2204,
+ 0x98d4, 0x3732,
+ 0x98e3, 0x20c3,
+ 0x98e4, 0x2140,
+ 0x98e5, 0x2477,
+ 0x98e6, 0x3741,
+ 0x98ef, 0x2474,
+ 0x98f0, 0x374a,
+ 0x98f2, 0x20dd,
+ 0x98f3, 0x374c,
+ 0x9940, 0x3758,
+ 0x9943, 0x1f68,
+ 0x9944, 0x375b,
+ 0x9945, 0x2185,
+ 0x9946, 0x375c,
+ 0x9966, 0x2472,
+ 0x9967, 0x377c,
+ 0x996e, 0x1eb5,
+ 0x996f, 0x3783,
+ 0x9975, 0x2478,
+ 0x9976, 0x3789,
+ 0x997a, 0x1f8b,
+ 0x997b, 0x2484,
+ 0x997c, 0x378d,
+ 0x9980, 0x3790,
+ 0x9985, 0x2699,
+ 0x9986, 0x3795,
+ 0x9989, 0x2482,
+ 0x998a, 0x3798,
+ 0x998e, 0x20a1,
+ 0x998f, 0x379c,
+ 0x9991, 0x1f92,
+ 0x9992, 0x379e,
+ 0x9999, 0x1f38,
+ 0x999a, 0x37a5,
+ 0x99a9, 0x2485,
+ 0x99aa, 0x37b4,
+ 0x99b0, 0x2480,
+ 0x99b1, 0x246e,
+ 0x99b2, 0x37ba,
+ 0x99b3, 0x247b,
+ 0x99b4, 0x2486,
+ 0x99b5, 0x2471,
+ 0x99b6, 0x37bb,
+ 0x99bd, 0x2483,
+ 0x99be, 0x2470,
+ 0x99bf, 0x37c2,
+ 0x99c0, 0x2469,
+ 0x99c1, 0x37c3,
+ 0x99c2, 0x247f,
+ 0x99c3, 0x37c4,
+ 0x99c9, 0x246f,
+ 0x99ca, 0x37ca,
+ 0x99ce, 0x2481,
+ 0x99cf, 0x37ce,
+ 0x99d1, 0x2220,
+ 0x99d2, 0x37d0,
+ 0x99da, 0x1ff5,
+ 0x99db, 0x37d8,
+ 0x99e0, 0x20f4,
+ 0x99e1, 0x37dd,
+ 0x99e5, 0x247d,
+ 0x99e6, 0x37e1,
+ 0x99e8, 0x2479,
+ 0x99e9, 0x37e3,
+ 0x99ec, 0x247e,
+ 0x99ed, 0x37e6,
+ 0x99f4, 0x247a,
+ 0x99f5, 0x37ed,
+ 0x9a40, 0x37f7,
+ 0x9a4a, 0x20e3,
+ 0x9a4b, 0x3801,
+ 0x9a57, 0x20ad,
+ 0x9a58, 0x380d,
+ 0x9a65, 0x24cb,
+ 0x9a66, 0x381a,
+ 0x9a67, 0x1f53,
+ 0x9a68, 0x381b,
+ 0x9a71, 0x2159,
+ 0x9a72, 0x3824,
+ 0x9a76, 0x2013,
+ 0x9a77, 0x1f33,
+ 0x9a78, 0x3828,
+ 0x9a80, 0x382f,
+ 0x9a88, 0x1e5c,
+ 0x9a89, 0x3837,
+ 0x9a8c, 0x2488,
+ 0x9a8d, 0x383a,
+ 0x9a91, 0x2487,
+ 0x9a92, 0x383e,
+ 0x9a97, 0x248a,
+ 0x9a98, 0x3843,
+ 0x9a9a, 0x2489,
+ 0x9a9b, 0x248b,
+ 0x9a9c, 0x3845,
+ 0x9a9e, 0x1f83,
+ 0x9a9f, 0x3847,
+ 0x9aa2, 0x210f,
+ 0x9aa3, 0x1fdb,
+ 0x9aa4, 0x384a,
+ 0x9aaa, 0x20af,
+ 0x9aab, 0x3850,
+ 0x9ad0, 0x24c0,
+ 0x9ad1, 0x3875,
+ 0x9ad6, 0x226d,
+ 0x9ad7, 0x387a,
+ 0x9ada, 0x24c1,
+ 0x9adb, 0x387d,
+ 0x9ae2, 0x20ca,
+ 0x9ae3, 0x3884,
+ 0x9ae4, 0x20e7,
+ 0x9ae5, 0x24c2,
+ 0x9ae6, 0x3885,
+ 0x9b40, 0x389e,
+ 0x9b80, 0x38dd,
+ 0x9bd1, 0x23dc,
+ 0x9bd2, 0x392e,
+ 0x9bdc, 0x23db,
+ 0x9bdd, 0x3938,
+ 0x9c40, 0x395a,
+ 0x9c53, 0x205e,
+ 0x9c54, 0x396d,
+ 0x9c59, 0x2244,
+ 0x9c5a, 0x23e2,
+ 0x9c5b, 0x3972,
+ 0x9c5c, 0x20d4,
+ 0x9c5d, 0x3973,
+ 0x9c75, 0x219f,
+ 0x9c76, 0x398b,
+ 0x9c79, 0x1e66,
+ 0x9c7a, 0x398e,
+ 0x9c80, 0x3993,
+ 0x9c86, 0x1f63,
+ 0x9c87, 0x3999,
+ 0x9c9d, 0x23dd,
+ 0x9c9e, 0x39af,
+ 0x9cab, 0x216b,
+ 0x9cac, 0x39bc,
+ 0x9cca, 0x22b5,
+ 0x9ccb, 0x39da,
+ 0x9ccf, 0x1f26,
+ 0x9cd0, 0x39de,
+ 0x9ce6, 0x1e63,
+ 0x9ce7, 0x2088,
+ 0x9ce8, 0x39f4,
+ 0x9cec, 0x1ebd,
+ 0x9ced, 0x39f8,
+ 0x9cee, 0x2341,
+ 0x9cef, 0x39f9,
+ 0x9cfb, 0x1f4b,
+ 0x9cfc, 0x3a05,
+ 0x9cfe, 0x2292,
+ 0x9d40, 0x3a07,
+ 0x9d42, 0x2124,
+ 0x9d43, 0x3a09,
+ 0x9d46, 0x2048,
+ 0x9d47, 0x23e0,
+ 0x9d48, 0x3a0c,
+ 0x9d4d, 0x2077,
+ 0x9d4e, 0x3a11,
+ 0x9d4f, 0x223a,
+ 0x9d50, 0x3a12,
+ 0x9d61, 0x20b1,
+ 0x9d62, 0x3a23,
+ 0x9d68, 0x1f41,
+ 0x9d69, 0x201c,
+ 0x9d6a, 0x3a29,
+ 0x9d6e, 0x22b8,
+ 0x9d6f, 0x3a2d,
+ 0x9d71, 0x2276,
+ 0x9d72, 0x3a2f,
+ 0x9d75, 0x1f9b,
+ 0x9d76, 0x3a32,
+ 0x9d7b, 0x1f9f,
+ 0x9d7c, 0x3a37,
+ 0x9d7d, 0x25ca,
+ 0x9d7e, 0x3a38,
+ 0x9d80, 0x3a39,
+ 0x9d8a, 0x20be,
+ 0x9d8b, 0x3a43,
+ 0x9d8d, 0x1fb4,
+ 0x9d8e, 0x3a45,
+ 0x9d91, 0x23d7,
+ 0x9d92, 0x3a48,
+ 0x9d99, 0x2105,
+ 0x9d9a, 0x3a4f,
+ 0x9da1, 0x23e1,
+ 0x9da2, 0x1fec,
+ 0x9da3, 0x3a56,
+ 0x9da7, 0x23ea,
+ 0x9da8, 0x3a5a,
+ 0x9dac, 0x23e3,
+ 0x9dad, 0x210e,
+ 0x9dae, 0x3a5e,
+ 0x9db2, 0x1fa6,
+ 0x9db3, 0x2004,
+ 0x9db4, 0x3a62,
+ 0x9dbe, 0x1f9d,
+ 0x9dbf, 0x3a6c,
+ 0x9dc6, 0x23e5,
+ 0x9dc7, 0x3a73,
+ 0x9dc9, 0x2264,
+ 0x9dca, 0x3a75,
+ 0x9dcd, 0x24e2,
+ 0x9dce, 0x3a78,
+ 0x9dd2, 0x23de,
+ 0x9dd3, 0x3a7c,
+ 0x9dd5, 0x1ec4,
+ 0x9dd6, 0x3a7e,
+ 0x9de1, 0x22b6,
+ 0x9de2, 0x20a9,
+ 0x9de3, 0x3a89,
+ 0x9df1, 0x212b,
+ 0x9df2, 0x3a97,
+ 0x9df4, 0x20a5,
+ 0x9df5, 0x3a99,
+ 0x9df7, 0x268b,
+ 0x9df8, 0x3a9b,
+ 0x9dfa, 0x1f76,
+ 0x9dfb, 0x3a9d,
+ 0x9dfd, 0x216d,
+ 0x9dfe, 0x3a9f,
+ 0x9e40, 0x3aa0,
+ 0x9e45, 0x2001,
+ 0x9e46, 0x3aa5,
+ 0x9e48, 0x2191,
+ 0x9e49, 0x1e50,
+ 0x9e4a, 0x3aa7,
+ 0x9e52, 0x1f9c,
+ 0x9e53, 0x3aaf,
+ 0x9e54, 0x23da,
+ 0x9e55, 0x3ab0,
+ 0x9e56, 0x2053,
+ 0x9e57, 0x3ab1,
+ 0x9e5d, 0x23e9,
+ 0x9e5e, 0x23e4,
+ 0x9e5f, 0x3ab7,
+ 0x9e61, 0x21d5,
+ 0x9e62, 0x3ab9,
+ 0x9e63, 0x23e6,
+ 0x9e64, 0x3aba,
+ 0x9e67, 0x23df,
+ 0x9e68, 0x3abd,
+ 0x9e6c, 0x1e4f,
+ 0x9e6d, 0x3ac1,
+ 0x9e6f, 0x23d9,
+ 0x9e70, 0x3ac3,
+ 0x9e72, 0x2014,
+ 0x9e73, 0x3ac5,
+ 0x9e74, 0x23ec,
+ 0x9e75, 0x23eb,
+ 0x9e76, 0x3ac6,
+ 0x9e7b, 0x23d8,
+ 0x9e7c, 0x23ee,
+ 0x9e7d, 0x3acb,
+ 0x9e80, 0x3acd,
+ 0x9e85, 0x268e,
+ 0x9e86, 0x3ad2,
+ 0x9e87, 0x23ed,
+ 0x9e88, 0x3ad3,
+ 0x9e91, 0x1ffa,
+ 0x9e92, 0x3adc,
+ 0x9e96, 0x23d6,
+ 0x9e97, 0x23e8,
+ 0x9e98, 0x3ae0,
+ 0x9ea2, 0x2106,
+ 0x9ea3, 0x3aea,
+ 0x9ea6, 0x200b,
+ 0x9ea7, 0x3aed,
+ 0x9ea9, 0x2166,
+ 0x9eaa, 0x3aef,
+ 0x9eae, 0x23ef,
+ 0x9eaf, 0x3af3,
+ 0x9eb3, 0x2189,
+ 0x9eb4, 0x2058,
+ 0x9eb5, 0x3af7,
+ 0x9eb7, 0x23e7,
+ 0x9eb8, 0x3af9,
+ 0x9ef5, 0x21a3,
+ 0x9ef6, 0x3b36,
+ 0x9f40, 0x3b3f,
+ 0x9f4e, 0x217a,
+ 0x9f4f, 0x3b4d,
+ 0x9f6f, 0x21a5,
+ 0x9f70, 0x3b6d,
+ 0x9f80, 0x3b7c,
+ 0x9f92, 0x2022,
+ 0x9f93, 0x3b8e,
+ 0x9f98, 0x24d6,
+ 0x9f99, 0x3b93,
+ 0x9fa6, 0x233a,
+ 0x9fa7, 0x3ba0,
+ 0x9fa9, 0x1eee,
+ 0x9faa, 0x3ba2,
+ 0x9fac, 0x24d5,
+ 0x9fad, 0x3ba4,
+ 0x9fc9, 0x2228,
+ 0x9fca, 0x3bc0,
+ 0x9fcd, 0x24d7,
+ 0x9fce, 0x3bc3,
+ 0x9fe1, 0x20fc,
+ 0x9fe2, 0x3bd6,
+ 0x9feb, 0x1e87,
+ 0x9fec, 0x3bdf,
+ 0x9fee, 0x24d8,
+ 0x9fef, 0x3be1,
+ 0x9ff4, 0x1eba,
+ 0x9ff5, 0x3be6,
+ 0x9ffd, 0x2119,
+ 0x9ffe, 0x3bee,
+ 0xa040, 0x3bef,
+ 0xa043, 0x216c,
+ 0xa044, 0x3bf2,
+ 0xa046, 0x24d9,
+ 0xa047, 0x3bf4,
+ 0xa049, 0x2227,
+ 0xa04a, 0x3bf6,
+ 0xa04e, 0x1e5f,
+ 0xa04f, 0x3bfa,
+ 0xa054, 0x229f,
+ 0xa055, 0x3bff,
+ 0xa05a, 0x1f5d,
+ 0xa05b, 0x3c04,
+ 0xa061, 0x1fbc,
+ 0xa062, 0x3c0a,
+ 0xa063, 0x24da,
+ 0xa064, 0x3c0b,
+ 0xa071, 0x2149,
+ 0xa072, 0x3c18,
+ 0xa074, 0x2046,
+ 0xa075, 0x3c1a,
+ 0xa080, 0x2000,
+ 0xa081, 0x3c24,
+ 0xa091, 0x2190,
+ 0xa092, 0x3c34,
+ 0xa094, 0x2208,
+ 0xa095, 0x3c36,
+ 0xa096, 0x1ee6,
+ 0xa097, 0x3c37,
+ 0xa0a9, 0x24c3,
+ 0xa0aa, 0x3c49,
+ 0xa0bf, 0x20cc,
+ 0xa0c0, 0x3c5e,
+ 0xa0ce, 0x2340,
+ 0xa0cf, 0x3c6c,
+ 0xa0d9, 0x1ed1,
+ 0xa0da, 0x3c76,
+ 0xa0de, 0x21ac,
+ 0xa0df, 0x3c7a,
+ 0xa0ee, 0x22af,
+ 0xa0ef, 0x3c89,
+ 0xa1a1, 0x0060,
+ 0xa2a1, 0x26a9,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa840, 0x26b3,
+ 0xa880, 0x26f2,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa940, 0x2708,
+ 0xa959, 0x2720,
+ 0xa95c, 0x2722,
+ 0xa960, 0x2723,
+ 0xa980, 0x2742,
+ 0xa996, 0x1e17,
+ 0xa9a4, 0x02e2,
+ 0xaa40, 0x3c99,
+ 0xaa4d, 0x21b6,
+ 0xaa4e, 0x1e3d,
+ 0xaa4f, 0x3ca6,
+ 0xaa71, 0x2235,
+ 0xaa72, 0x3cc8,
+ 0xaa73, 0x2397,
+ 0xaa74, 0x3cc9,
+ 0xaa77, 0x2395,
+ 0xaa78, 0x3ccc,
+ 0xaa7a, 0x223f,
+ 0xaa7b, 0x212a,
+ 0xaa7c, 0x3cce,
+ 0xaa80, 0x3cd1,
+ 0xaa9a, 0x1ed2,
+ 0xaa9b, 0x3ceb,
+ 0xaa9c, 0x2396,
+ 0xaa9d, 0x2398,
+ 0xaa9e, 0x3cec,
+ 0xaa9f, 0x20a2,
+ 0xaaa0, 0x3ced,
+ 0xaaa1, 0x032e,
+ 0xab40, 0x1f64,
+ 0xab41, 0x3cee,
+ 0xab43, 0x202b,
+ 0xab44, 0x3cf0,
+ 0xab45, 0x2394,
+ 0xab46, 0x2139,
+ 0xab47, 0x3cf1,
+ 0xab48, 0x215f,
+ 0xab49, 0x21c1,
+ 0xab4a, 0x239a,
+ 0xab4b, 0x3cf2,
+ 0xab4d, 0x2399,
+ 0xab4e, 0x3cf4,
+ 0xab80, 0x3d25,
+ 0xaba1, 0x038c,
+ 0xac40, 0x3d46,
+ 0xac46, 0x21c0,
+ 0xac47, 0x3d4c,
+ 0xac71, 0x2460,
+ 0xac72, 0x3d76,
+ 0xac7c, 0x245c,
+ 0xac7d, 0x3d80,
+ 0xac80, 0x3d82,
+ 0xac8d, 0x215d,
+ 0xac8e, 0x3d8f,
+ 0xac93, 0x2225,
+ 0xac94, 0x206a,
+ 0xac95, 0x3d94,
+ 0xad40, 0x3da0,
+ 0xad49, 0x2461,
+ 0xad4a, 0x3da9,
+ 0xad5e, 0x245b,
+ 0xad5f, 0x3dbd,
+ 0xad61, 0x2462,
+ 0xad62, 0x3dbf,
+ 0xad68, 0x1f54,
+ 0xad69, 0x3dc5,
+ 0xad74, 0x245f,
+ 0xad75, 0x3dd0,
+ 0xad80, 0x3dda,
+ 0xad82, 0x20ec,
+ 0xad83, 0x3ddc,
+ 0xad87, 0x245d,
+ 0xad88, 0x3de0,
+ 0xad8b, 0x2463,
+ 0xad8c, 0x3de3,
+ 0xad91, 0x2464,
+ 0xad92, 0x3de8,
+ 0xae40, 0x3df7,
+ 0xae54, 0x24a5,
+ 0xae55, 0x3e0b,
+ 0xae62, 0x1e70,
+ 0xae63, 0x3e18,
+ 0xae80, 0x208f,
+ 0xae81, 0x3e34,
+ 0xae85, 0x1e42,
+ 0xae86, 0x3e38,
+ 0xae8b, 0x1f4e,
+ 0xae8c, 0x3e3d,
+ 0xae94, 0x1eb1,
+ 0xae95, 0x3e45,
+ 0xaea0, 0x1e8b,
+ 0xaf40, 0x3e50,
+ 0xaf64, 0x1fc6,
+ 0xaf65, 0x3e74,
+ 0xaf7b, 0x25ae,
+ 0xaf7c, 0x3e8a,
+ 0xaf80, 0x3e8d,
+ 0xaf82, 0x1f01,
+ 0xaf83, 0x2200,
+ 0xaf84, 0x3e8f,
+ 0xaf8e, 0x25b2,
+ 0xaf8f, 0x1e97,
+ 0xaf90, 0x3e99,
+ 0xaf91, 0x20ab,
+ 0xaf92, 0x3e9a,
+ 0xaf9c, 0x25b3,
+ 0xaf9d, 0x3ea4,
+ 0xaf9f, 0x2028,
+ 0xafa0, 0x3ea6,
+ 0xb040, 0x3ea7,
+ 0xb041, 0x25af,
+ 0xb043, 0x3ea8,
+ 0xb044, 0x25b1,
+ 0xb045, 0x3ea9,
+ 0xb04f, 0x25ac,
+ 0xb050, 0x3eb3,
+ 0xb054, 0x1e4e,
+ 0xb055, 0x3eb7,
+ 0xb057, 0x2202,
+ 0xb058, 0x25ab,
+ 0xb059, 0x2286,
+ 0xb05a, 0x3eb9,
+ 0xb05b, 0x25ad,
+ 0xb05c, 0x3eba,
+ 0xb05d, 0x25b6,
+ 0xb05e, 0x3ebb,
+ 0xb05f, 0x21e3,
+ 0xb060, 0x25b4,
+ 0xb062, 0x222f,
+ 0xb063, 0x2165,
+ 0xb064, 0x25b7,
+ 0xb065, 0x3ebc,
+ 0xb06c, 0x1ee9,
+ 0xb06d, 0x3ec3,
+ 0xb07d, 0x1e25,
+ 0xb07e, 0x3ed3,
+ 0xb080, 0x3ed4,
+ 0xb097, 0x25c0,
+ 0xb098, 0x3eeb,
+ 0xb099, 0x229a,
+ 0xb09a, 0x3eec,
+ 0xb0a1, 0x03ac,
+ 0xb140, 0x3ef3,
+ 0xb14b, 0x226e,
+ 0xb14c, 0x3efe,
+ 0xb14d, 0x1fbd,
+ 0xb14e, 0x3eff,
+ 0xb14f, 0x1f84,
+ 0xb150, 0x20b2,
+ 0xb151, 0x3f00,
+ 0xb152, 0x2043,
+ 0xb153, 0x3f01,
+ 0xb180, 0x3f2d,
+ 0xb197, 0x2684,
+ 0xb198, 0x3f44,
+ 0xb1a1, 0x040a,
+ 0xb240, 0x3f4d,
+ 0xb241, 0x24ef,
+ 0xb242, 0x3f4e,
+ 0xb267, 0x24ee,
+ 0xb268, 0x3f73,
+ 0xb26d, 0x2074,
+ 0xb26e, 0x3f78,
+ 0xb274, 0x2687,
+ 0xb275, 0x3f7e,
+ 0xb280, 0x24f0,
+ 0xb281, 0x3f88,
+ 0xb289, 0x268d,
+ 0xb28a, 0x3f90,
+ 0xb29a, 0x22a0,
+ 0xb29b, 0x3fa0,
+ 0xb2a1, 0x0468,
+ 0xb340, 0x3fa6,
+ 0xb343, 0x1fab,
+ 0xb344, 0x3fa9,
+ 0xb370, 0x26a8,
+ 0xb371, 0x3fd5,
+ 0xb380, 0x3fe3,
+ 0xb388, 0x24e9,
+ 0xb389, 0x3feb,
+ 0xb38c, 0x24e5,
+ 0xb38d, 0x3fee,
+ 0xb38e, 0x21fa,
+ 0xb38f, 0x3fef,
+ 0xb3a1, 0x04c6,
+ 0xb440, 0x4001,
+ 0xb454, 0x2148,
+ 0xb455, 0x4015,
+ 0xb458, 0x24e4,
+ 0xb459, 0x4018,
+ 0xb45e, 0x24e6,
+ 0xb45f, 0x20f7,
+ 0xb460, 0x401d,
+ 0xb461, 0x206b,
+ 0xb462, 0x401e,
+ 0xb475, 0x22a7,
+ 0xb476, 0x4031,
+ 0xb47e, 0x24ec,
+ 0xb480, 0x4039,
+ 0xb483, 0x24eb,
+ 0xb484, 0x403c,
+ 0xb489, 0x24e3,
+ 0xb48a, 0x4041,
+ 0xb493, 0x24ea,
+ 0xb494, 0x404a,
+ 0xb4a1, 0x0524,
+ 0xb540, 0x4057,
+ 0xb541, 0x1e92,
+ 0xb542, 0x4058,
+ 0xb54b, 0x1e27,
+ 0xb54c, 0x4061,
+ 0xb556, 0x1fe6,
+ 0xb557, 0x406b,
+ 0xb55a, 0x24e7,
+ 0xb55b, 0x2012,
+ 0xb55c, 0x1eec,
+ 0xb55d, 0x406e,
+ 0xb561, 0x24e8,
+ 0xb562, 0x4072,
+ 0xb580, 0x408f,
+ 0xb59c, 0x1f66,
+ 0xb59d, 0x24dc,
+ 0xb59e, 0x40ab,
+ 0xb5a1, 0x0582,
+ 0xb640, 0x40ae,
+ 0xb652, 0x26a2,
+ 0xb653, 0x40c0,
+ 0xb655, 0x24dd,
+ 0xb656, 0x40c2,
+ 0xb659, 0x200e,
+ 0xb65a, 0x40c5,
+ 0xb65b, 0x24db,
+ 0xb65c, 0x1eb8,
+ 0xb65d, 0x40c6,
+ 0xb680, 0x40e8,
+ 0xb6a1, 0x05e0,
+ 0xb740, 0x4109,
+ 0xb74e, 0x2295,
+ 0xb74f, 0x4117,
+ 0xb751, 0x1e80,
+ 0xb752, 0x4119,
+ 0xb759, 0x2677,
+ 0xb75a, 0x4120,
+ 0xb764, 0x2624,
+ 0xb765, 0x1f69,
+ 0xb766, 0x222b,
+ 0xb767, 0x412a,
+ 0xb777, 0x257f,
+ 0xb778, 0x1f5b,
+ 0xb779, 0x413a,
+ 0xb780, 0x219b,
+ 0xb781, 0x4140,
+ 0xb782, 0x267d,
+ 0xb783, 0x4141,
+ 0xb7a1, 0x063e,
+ 0xb840, 0x415f,
+ 0xb843, 0x21a0,
+ 0xb844, 0x2186,
+ 0xb845, 0x4162,
+ 0xb846, 0x20ed,
+ 0xb847, 0x4163,
+ 0xb84d, 0x25b9,
+ 0xb84e, 0x4169,
+ 0xb851, 0x1fea,
+ 0xb852, 0x416c,
+ 0xb85a, 0x1ea4,
+ 0xb85b, 0x20e1,
+ 0xb85c, 0x4174,
+ 0xb85d, 0x25b8,
+ 0xb85e, 0x2260,
+ 0xb85f, 0x4175,
+ 0xb860, 0x20e2,
+ 0xb861, 0x4176,
+ 0xb877, 0x2141,
+ 0xb878, 0x418c,
+ 0xb880, 0x4193,
+ 0xb882, 0x1fc7,
+ 0xb883, 0x4195,
+ 0xb8a1, 0x069c,
+ 0xb940, 0x41b3,
+ 0xb950, 0x1e41,
+ 0xb951, 0x41c3,
+ 0xb961, 0x25e4,
+ 0xb962, 0x41d3,
+ 0xb97b, 0x1f86,
+ 0xb97c, 0x41ec,
+ 0xb980, 0x41ef,
+ 0xb99d, 0x1fb3,
+ 0xb99e, 0x420c,
+ 0xb9a0, 0x1eef,
+ 0xb9a1, 0x06fa,
+ 0xba40, 0x420e,
+ 0xba42, 0x22a4,
+ 0xba43, 0x4210,
+ 0xba44, 0x25e8,
+ 0xba45, 0x4211,
+ 0xba56, 0x25e3,
+ 0xba57, 0x4222,
+ 0xba59, 0x2111,
+ 0xba5a, 0x4224,
+ 0xba60, 0x25e6,
+ 0xba61, 0x422a,
+ 0xba6a, 0x25e7,
+ 0xba6b, 0x4233,
+ 0xba74, 0x2041,
+ 0xba75, 0x423c,
+ 0xba80, 0x4246,
+ 0xba84, 0x25ea,
+ 0xba85, 0x424a,
+ 0xba86, 0x1f8f,
+ 0xba87, 0x424b,
+ 0xba88, 0x25ec,
+ 0xba89, 0x424c,
+ 0xba8d, 0x25eb,
+ 0xba8e, 0x4250,
+ 0xba9e, 0x20d0,
+ 0xba9f, 0x201d,
+ 0xbaa0, 0x4260,
+ 0xbaa1, 0x0758,
+ 0xbb40, 0x1ff7,
+ 0xbb41, 0x4261,
+ 0xbb49, 0x1e8d,
+ 0xbb4a, 0x4269,
+ 0xbb58, 0x25e9,
+ 0xbb59, 0x4277,
+ 0xbb5b, 0x25ee,
+ 0xbb5c, 0x203a,
+ 0xbb5d, 0x4279,
+ 0xbb60, 0x2693,
+ 0xbb61, 0x427c,
+ 0xbb65, 0x25e5,
+ 0xbb66, 0x25ed,
+ 0xbb67, 0x4280,
+ 0xbb68, 0x2009,
+ 0xbb69, 0x4281,
+ 0xbb6a, 0x2065,
+ 0xbb6b, 0x4282,
+ 0xbb6e, 0x26a3,
+ 0xbb6f, 0x4285,
+ 0xbb80, 0x4295,
+ 0xbba1, 0x07b6,
+ 0xbc40, 0x42b6,
+ 0xbc52, 0x25f5,
+ 0xbc53, 0x1efc,
+ 0xbc54, 0x42c8,
+ 0xbc5a, 0x2024,
+ 0xbc5b, 0x42ce,
+ 0xbc61, 0x269b,
+ 0xbc62, 0x42d4,
+ 0xbc63, 0x25f3,
+ 0xbc64, 0x42d5,
+ 0xbc65, 0x22d9,
+ 0xbc66, 0x42d6,
+ 0xbc67, 0x25f4,
+ 0xbc68, 0x42d7,
+ 0xbc69, 0x241b,
+ 0xbc6a, 0x42d8,
+ 0xbc6d, 0x1fc8,
+ 0xbc6e, 0x42db,
+ 0xbc6f, 0x1f7b,
+ 0xbc70, 0x42dc,
+ 0xbc71, 0x241d,
+ 0xbc72, 0x42dd,
+ 0xbc73, 0x224c,
+ 0xbc74, 0x1f48,
+ 0xbc75, 0x241c,
+ 0xbc76, 0x241e,
+ 0xbc78, 0x20ff,
+ 0xbc79, 0x219a,
+ 0xbc7a, 0x42de,
+ 0xbc7b, 0x2091,
+ 0xbc7c, 0x42df,
+ 0xbc7e, 0x20a7,
+ 0xbc80, 0x42e1,
+ 0xbc82, 0x2423,
+ 0xbc83, 0x1e9b,
+ 0xbc84, 0x2422,
+ 0xbc85, 0x42e3,
+ 0xbc86, 0x2110,
+ 0xbc87, 0x42e4,
+ 0xbc88, 0x228d,
+ 0xbc89, 0x1f71,
+ 0xbc8a, 0x1ef8,
+ 0xbc8b, 0x2421,
+ 0xbc8c, 0x42e5,
+ 0xbc8f, 0x1ef3,
+ 0xbc90, 0x42e8,
+ 0xbc9a, 0x21b1,
+ 0xbc9b, 0x2426,
+ 0xbc9c, 0x2425,
+ 0xbc9d, 0x2120,
+ 0xbc9e, 0x42f2,
+ 0xbca1, 0x0814,
+ 0xbd40, 0x42f5,
+ 0xbd42, 0x211a,
+ 0xbd43, 0x2424,
+ 0xbd44, 0x42f7,
+ 0xbd45, 0x2428,
+ 0xbd46, 0x42f8,
+ 0xbd48, 0x242a,
+ 0xbd49, 0x2429,
+ 0xbd4a, 0x42fa,
+ 0xbd4b, 0x2294,
+ 0xbd4c, 0x42fb,
+ 0xbd4d, 0x22be,
+ 0xbd4e, 0x42fc,
+ 0xbd4f, 0x1e31,
+ 0xbd50, 0x42fd,
+ 0xbd57, 0x242c,
+ 0xbd58, 0x4304,
+ 0xbd59, 0x1fb5,
+ 0xbd5a, 0x4305,
+ 0xbd66, 0x242b,
+ 0xbd67, 0x1faf,
+ 0xbd68, 0x4311,
+ 0xbd6a, 0x2068,
+ 0xbd6b, 0x21e4,
+ 0xbd6c, 0x4313,
+ 0xbd6f, 0x1f21,
+ 0xbd70, 0x4316,
+ 0xbd71, 0x2101,
+ 0xbd72, 0x4317,
+ 0xbd79, 0x217c,
+ 0xbd7a, 0x214a,
+ 0xbd7b, 0x242d,
+ 0xbd7c, 0x431e,
+ 0xbd7e, 0x1fd4,
+ 0xbd80, 0x4320,
+ 0xbd81, 0x1fd1,
+ 0xbd82, 0x4321,
+ 0xbd89, 0x1e33,
+ 0xbd8a, 0x4328,
+ 0xbd8b, 0x242f,
+ 0xbd8c, 0x4329,
+ 0xbd8e, 0x242e,
+ 0xbd8f, 0x432b,
+ 0xbd90, 0x2430,
+ 0xbd91, 0x21db,
+ 0xbd92, 0x432c,
+ 0xbd97, 0x2158,
+ 0xbd98, 0x4331,
+ 0xbd9b, 0x1fc2,
+ 0xbd9c, 0x4334,
+ 0xbda1, 0x0872,
+ 0xbe40, 0x4339,
+ 0xbe43, 0x22b9,
+ 0xbe44, 0x433c,
+ 0xbe45, 0x2436,
+ 0xbe46, 0x433d,
+ 0xbe49, 0x1e8e,
+ 0xbe4a, 0x2439,
+ 0xbe4b, 0x4340,
+ 0xbe51, 0x21c5,
+ 0xbe52, 0x2437,
+ 0xbe53, 0x2192,
+ 0xbe54, 0x4346,
+ 0xbe55, 0x243a,
+ 0xbe56, 0x1f19,
+ 0xbe57, 0x218c,
+ 0xbe58, 0x1e40,
+ 0xbe59, 0x22b3,
+ 0xbe5a, 0x4347,
+ 0xbe5d, 0x205f,
+ 0xbe5e, 0x2438,
+ 0xbe5f, 0x2432,
+ 0xbe60, 0x2274,
+ 0xbe61, 0x434a,
+ 0xbe62, 0x1e9c,
+ 0xbe63, 0x2431,
+ 0xbe64, 0x2085,
+ 0xbe65, 0x434b,
+ 0xbe69, 0x2435,
+ 0xbe6a, 0x434f,
+ 0xbe6c, 0x243b,
+ 0xbe6d, 0x4351,
+ 0xbe6f, 0x1fb7,
+ 0xbe70, 0x2433,
+ 0xbe71, 0x4353,
+ 0xbe76, 0x2054,
+ 0xbe77, 0x21de,
+ 0xbe78, 0x4358,
+ 0xbe79, 0x2434,
+ 0xbe7a, 0x4359,
+ 0xbe7c, 0x243d,
+ 0xbe7d, 0x1f89,
+ 0xbe7e, 0x243c,
+ 0xbe80, 0x435b,
+ 0xbe83, 0x1f6e,
+ 0xbe84, 0x1ed8,
+ 0xbe85, 0x435e,
+ 0xbe86, 0x1ebf,
+ 0xbe87, 0x2445,
+ 0xbe88, 0x435f,
+ 0xbe89, 0x2249,
+ 0xbe8a, 0x4360,
+ 0xbe8c, 0x2441,
+ 0xbe8d, 0x4362,
+ 0xbe8e, 0x1e47,
+ 0xbe8f, 0x1f56,
+ 0xbe90, 0x4363,
+ 0xbe92, 0x2086,
+ 0xbe93, 0x4365,
+ 0xbe95, 0x2196,
+ 0xbe96, 0x4367,
+ 0xbe97, 0x2443,
+ 0xbe98, 0x243f,
+ 0xbe99, 0x4368,
+ 0xbe9a, 0x2023,
+ 0xbe9b, 0x4369,
+ 0xbe9c, 0x2442,
+ 0xbe9d, 0x436a,
+ 0xbe9f, 0x243e,
+ 0xbea0, 0x436c,
+ 0xbea1, 0x08d0,
+ 0xbf40, 0x26a6,
+ 0xbf41, 0x436d,
+ 0xbf4d, 0x234e,
+ 0xbf4e, 0x2446,
+ 0xbf4f, 0x244b,
+ 0xbf50, 0x2444,
+ 0xbf51, 0x4379,
+ 0xbf55, 0x2427,
+ 0xbf56, 0x244c,
+ 0xbf57, 0x437d,
+ 0xbf60, 0x1f0f,
+ 0xbf61, 0x4386,
+ 0xbf62, 0x2447,
+ 0xbf63, 0x2449,
+ 0xbf64, 0x2448,
+ 0xbf65, 0x4387,
+ 0xbf68, 0x21c2,
+ 0xbf69, 0x438a,
+ 0xbf6c, 0x216e,
+ 0xbf6d, 0x438d,
+ 0xbf70, 0x1f03,
+ 0xbf71, 0x4390,
+ 0xbf72, 0x244a,
+ 0xbf73, 0x215c,
+ 0xbf74, 0x4391,
+ 0xbf76, 0x22bb,
+ 0xbf77, 0x2450,
+ 0xbf78, 0x4393,
+ 0xbf79, 0x2694,
+ 0xbf7a, 0x244f,
+ 0xbf7b, 0x25f6,
+ 0xbf7c, 0x2051,
+ 0xbf7d, 0x4394,
+ 0xbf7e, 0x244e,
+ 0xbf80, 0x4395,
+ 0xbf82, 0x22ba,
+ 0xbf83, 0x1f6d,
+ 0xbf84, 0x4397,
+ 0xbf89, 0x2452,
+ 0xbf8a, 0x2451,
+ 0xbf8b, 0x439c,
+ 0xbf95, 0x2455,
+ 0xbf96, 0x43a6,
+ 0xbf97, 0x2289,
+ 0xbf98, 0x2116,
+ 0xbf99, 0x43a7,
+ 0xbf9d, 0x2454,
+ 0xbf9e, 0x43ab,
+ 0xbfa1, 0x092e,
+ 0xc040, 0x20fb,
+ 0xc041, 0x43ae,
+ 0xc044, 0x2440,
+ 0xc045, 0x43b1,
+ 0xc04b, 0x2126,
+ 0xc04c, 0x1f61,
+ 0xc04d, 0x269d,
+ 0xc04e, 0x43b7,
+ 0xc04f, 0x1f8a,
+ 0xc050, 0x2456,
+ 0xc051, 0x2459,
+ 0xc052, 0x2458,
+ 0xc053, 0x43b8,
+ 0xc055, 0x1fae,
+ 0xc056, 0x43ba,
+ 0xc05b, 0x221a,
+ 0xc05c, 0x43bf,
+ 0xc05e, 0x1f7a,
+ 0xc05f, 0x244d,
+ 0xc060, 0x2457,
+ 0xc061, 0x43c1,
+ 0xc069, 0x2453,
+ 0xc06a, 0x43c9,
+ 0xc06b, 0x2420,
+ 0xc06c, 0x43ca,
+ 0xc06d, 0x21df,
+ 0xc06e, 0x2685,
+ 0xc06f, 0x43cb,
+ 0xc070, 0x1e6e,
+ 0xc071, 0x43cc,
+ 0xc074, 0x2224,
+ 0xc075, 0x2670,
+ 0xc076, 0x43cf,
+ 0xc077, 0x21ba,
+ 0xc078, 0x43d0,
+ 0xc079, 0x245a,
+ 0xc07a, 0x43d1,
+ 0xc07c, 0x1fff,
+ 0xc07d, 0x43d3,
+ 0xc080, 0x43d5,
+ 0xc09b, 0x25e2,
+ 0xc09c, 0x43f0,
+ 0xc09d, 0x269a,
+ 0xc09e, 0x43f1,
+ 0xc0a1, 0x098c,
+ 0xc140, 0x43f4,
+ 0xc150, 0x1eea,
+ 0xc151, 0x4404,
+ 0xc154, 0x1e2c,
+ 0xc155, 0x4407,
+ 0xc15f, 0x2062,
+ 0xc160, 0x24f1,
+ 0xc161, 0x4411,
+ 0xc162, 0x24f2,
+ 0xc163, 0x4412,
+ 0xc175, 0x25f2,
+ 0xc176, 0x4424,
+ 0xc178, 0x2215,
+ 0xc179, 0x4426,
+ 0xc180, 0x442c,
+ 0xc195, 0x21ae,
+ 0xc196, 0x4441,
+ 0xc1a1, 0x09ea,
+ 0xc240, 0x444c,
+ 0xc24e, 0x20e0,
+ 0xc24f, 0x445a,
+ 0xc265, 0x25c2,
+ 0xc266, 0x4470,
+ 0xc267, 0x25c1,
+ 0xc268, 0x4471,
+ 0xc27d, 0x2128,
+ 0xc27e, 0x4486,
+ 0xc280, 0x4487,
+ 0xc284, 0x2199,
+ 0xc285, 0x448b,
+ 0xc293, 0x2017,
+ 0xc294, 0x1ea0,
+ 0xc295, 0x2125,
+ 0xc296, 0x214d,
+ 0xc297, 0x4499,
+ 0xc298, 0x25c4,
+ 0xc299, 0x209d,
+ 0xc29a, 0x228a,
+ 0xc29b, 0x449a,
+ 0xc29c, 0x25c3,
+ 0xc29d, 0x449b,
+ 0xc2a0, 0x2179,
+ 0xc2a1, 0x0a48,
+ 0xc340, 0x2038,
+ 0xc341, 0x449e,
+ 0xc343, 0x2155,
+ 0xc344, 0x44a0,
+ 0xc37b, 0x21d2,
+ 0xc37c, 0x44d7,
+ 0xc380, 0x44da,
+ 0xc384, 0x24c7,
+ 0xc385, 0x44de,
+ 0xc39b, 0x2279,
+ 0xc39c, 0x44f4,
+ 0xc3a1, 0x0aa6,
+ 0xc440, 0x44f9,
+ 0xc449, 0x2123,
+ 0xc44a, 0x4502,
+ 0xc44c, 0x24c5,
+ 0xc44d, 0x4504,
+ 0xc454, 0x24c9,
+ 0xc455, 0x450b,
+ 0xc458, 0x2094,
+ 0xc459, 0x450e,
+ 0xc45b, 0x2296,
+ 0xc45c, 0x4510,
+ 0xc463, 0x1e77,
+ 0xc464, 0x4517,
+ 0xc477, 0x1f06,
+ 0xc478, 0x452a,
+ 0xc47a, 0x1fa5,
+ 0xc47b, 0x452c,
+ 0xc480, 0x4530,
+ 0xc481, 0x2099,
+ 0xc482, 0x4531,
+ 0xc491, 0x1ead,
+ 0xc492, 0x24c8,
+ 0xc493, 0x20a8,
+ 0xc494, 0x4540,
+ 0xc498, 0x201f,
+ 0xc499, 0x4544,
+ 0xc49a, 0x20c5,
+ 0xc49b, 0x4545,
+ 0xc49c, 0x24ca,
+ 0xc49d, 0x4546,
+ 0xc4a1, 0x0b04,
+ 0xc540, 0x454a,
+ 0xc544, 0x1ff0,
+ 0xc545, 0x454e,
+ 0xc546, 0x24c6,
+ 0xc547, 0x454f,
+ 0xc54b, 0x225d,
+ 0xc54c, 0x22de,
+ 0xc54d, 0x4553,
+ 0xc552, 0x202c,
+ 0xc553, 0x4558,
+ 0xc55f, 0x2161,
+ 0xc560, 0x4564,
+ 0xc563, 0x223b,
+ 0xc564, 0x21d9,
+ 0xc565, 0x1fcb,
+ 0xc566, 0x1fc9,
+ 0xc567, 0x4567,
+ 0xc580, 0x457f,
+ 0xc593, 0x1e61,
+ 0xc594, 0x4592,
+ 0xc59c, 0x25ef,
+ 0xc59d, 0x459a,
+ 0xc59e, 0x1f98,
+ 0xc59f, 0x459b,
+ 0xc5a1, 0x0b62,
+ 0xc640, 0x459d,
+ 0xc641, 0x25f0,
+ 0xc642, 0x459e,
+ 0xc644, 0x1f88,
+ 0xc645, 0x45a0,
+ 0xc647, 0x21f8,
+ 0xc648, 0x45a2,
+ 0xc663, 0x2322,
+ 0xc664, 0x45bd,
+ 0xc672, 0x2336,
+ 0xc673, 0x45cb,
+ 0xc680, 0x45d7,
+ 0xc6a1, 0x0bc0,
+ 0xc740, 0x45f8,
+ 0xc766, 0x22ab,
+ 0xc767, 0x461e,
+ 0xc76f, 0x1fbf,
+ 0xc770, 0x4626,
+ 0xc776, 0x1f7d,
+ 0xc777, 0x462c,
+ 0xc77b, 0x2333,
+ 0xc77c, 0x4630,
+ 0xc780, 0x4633,
+ 0xc7a1, 0x0c1e,
+ 0xc840, 0x4654,
+ 0xc841, 0x1f4d,
+ 0xc842, 0x4655,
+ 0xc84f, 0x2334,
+ 0xc850, 0x4662,
+ 0xc852, 0x1ff1,
+ 0xc853, 0x4664,
+ 0xc866, 0x218b,
+ 0xc867, 0x4677,
+ 0xc86e, 0x2349,
+ 0xc86f, 0x467e,
+ 0xc87e, 0x220b,
+ 0xc880, 0x468d,
+ 0xc887, 0x2346,
+ 0xc888, 0x4694,
+ 0xc892, 0x2347,
+ 0xc893, 0x469e,
+ 0xc894, 0x2193,
+ 0xc895, 0x469f,
+ 0xc899, 0x26a1,
+ 0xc89a, 0x46a3,
+ 0xc89d, 0x1f62,
+ 0xc89e, 0x46a6,
+ 0xc8a1, 0x0c7c,
+ 0xc940, 0x46a9,
+ 0xc94f, 0x234d,
+ 0xc950, 0x2348,
+ 0xc951, 0x46b8,
+ 0xc96e, 0x1e60,
+ 0xc96f, 0x46d5,
+ 0xc970, 0x2345,
+ 0xc971, 0x46d6,
+ 0xc977, 0x1f12,
+ 0xc978, 0x46dc,
+ 0xc980, 0x46e3,
+ 0xc98f, 0x2018,
+ 0xc990, 0x2335,
+ 0xc991, 0x46f2,
+ 0xc99c, 0x233c,
+ 0xc99d, 0x46fd,
+ 0xc9a1, 0x0cda,
+ 0xca40, 0x4701,
+ 0xca4e, 0x266f,
+ 0xca4f, 0x470f,
+ 0xca56, 0x2351,
+ 0xca57, 0x4716,
+ 0xca59, 0x1fa0,
+ 0xca5a, 0x4718,
+ 0xca5c, 0x2338,
+ 0xca5d, 0x471a,
+ 0xca61, 0x221b,
+ 0xca62, 0x471e,
+ 0xca6e, 0x2342,
+ 0xca6f, 0x472a,
+ 0xca72, 0x234f,
+ 0xca73, 0x472d,
+ 0xca77, 0x233d,
+ 0xca78, 0x4731,
+ 0xca7b, 0x2344,
+ 0xca7c, 0x2331,
+ 0xca7d, 0x4734,
+ 0xca7e, 0x234b,
+ 0xca80, 0x4735,
+ 0xca81, 0x233b,
+ 0xca82, 0x4736,
+ 0xca89, 0x2350,
+ 0xca8a, 0x473d,
+ 0xca8e, 0x1eb4,
+ 0xca8f, 0x21a6,
+ 0xca90, 0x4741,
+ 0xca92, 0x21cb,
+ 0xca93, 0x4743,
+ 0xca9a, 0x2355,
+ 0xca9b, 0x474a,
+ 0xcaa1, 0x0d38,
+ 0xcb40, 0x4750,
+ 0xcb43, 0x233e,
+ 0xcb44, 0x4753,
+ 0xcb45, 0x1f74,
+ 0xcb46, 0x4754,
+ 0xcb47, 0x2330,
+ 0xcb48, 0x4755,
+ 0xcb4b, 0x2680,
+ 0xcb4c, 0x4758,
+ 0xcb4e, 0x20da,
+ 0xcb4f, 0x475a,
+ 0xcb57, 0x234a,
+ 0xcb58, 0x4762,
+ 0xcb5d, 0x1f91,
+ 0xcb5e, 0x4767,
+ 0xcb5f, 0x2107,
+ 0xcb60, 0x4768,
+ 0xcb6a, 0x233f,
+ 0xcb6b, 0x4772,
+ 0xcb7b, 0x1ff4,
+ 0xcb7c, 0x2343,
+ 0xcb7d, 0x4782,
+ 0xcb80, 0x4784,
+ 0xcb87, 0x2212,
+ 0xcb88, 0x478b,
+ 0xcb8e, 0x2207,
+ 0xcb8f, 0x4791,
+ 0xcb92, 0x2359,
+ 0xcb93, 0x4794,
+ 0xcb9c, 0x2254,
+ 0xcb9d, 0x479d,
+ 0xcb9e, 0x2332,
+ 0xcb9f, 0x479e,
+ 0xcba1, 0x0d96,
+ 0xcc40, 0x1e26,
+ 0xcc41, 0x2357,
+ 0xcc42, 0x47a0,
+ 0xcc49, 0x2358,
+ 0xcc4a, 0x2042,
+ 0xcc4b, 0x2153,
+ 0xcc4c, 0x47a7,
+ 0xcc4f, 0x20bb,
+ 0xcc50, 0x47aa,
+ 0xcc5c, 0x235a,
+ 0xcc5d, 0x47b6,
+ 0xcc60, 0x2356,
+ 0xcc61, 0x47b9,
+ 0xcc64, 0x2337,
+ 0xcc65, 0x47bc,
+ 0xcc6d, 0x1ff9,
+ 0xcc6e, 0x47c4,
+ 0xcc79, 0x2353,
+ 0xcc7a, 0x47cf,
+ 0xcc7d, 0x2061,
+ 0xcc7e, 0x47d2,
+ 0xcc80, 0x47d3,
+ 0xcc8e, 0x1e95,
+ 0xcc8f, 0x47e1,
+ 0xcc94, 0x2049,
+ 0xcc95, 0x47e6,
+ 0xcc96, 0x1f42,
+ 0xcc97, 0x47e7,
+ 0xcc9d, 0x1fe8,
+ 0xcc9e, 0x47ed,
+ 0xcca1, 0x0df4,
+ 0xcd40, 0x47f0,
+ 0xcd80, 0x482f,
+ 0xcd90, 0x25da,
+ 0xcd91, 0x483f,
+ 0xcd98, 0x25d7,
+ 0xcd99, 0x4846,
+ 0xcda1, 0x0e52,
+ 0xce40, 0x484e,
+ 0xce67, 0x212e,
+ 0xce68, 0x4875,
+ 0xce72, 0x21b2,
+ 0xce73, 0x487f,
+ 0xce80, 0x488b,
+ 0xce81, 0x219e,
+ 0xce82, 0x488c,
+ 0xce87, 0x25dc,
+ 0xce88, 0x4891,
+ 0xce9b, 0x206c,
+ 0xce9c, 0x48a4,
+ 0xce9e, 0x2226,
+ 0xce9f, 0x48a6,
+ 0xcea1, 0x0eb0,
+ 0xcf40, 0x48a8,
+ 0xcf4e, 0x25e0,
+ 0xcf4f, 0x48b6,
+ 0xcf55, 0x227b,
+ 0xcf56, 0x48bc,
+ 0xcf58, 0x25de,
+ 0xcf59, 0x48be,
+ 0xcf5c, 0x25e1,
+ 0xcf5d, 0x48c1,
+ 0xcf6c, 0x25d5,
+ 0xcf6d, 0x48d0,
+ 0xcf73, 0x1e6b,
+ 0xcf74, 0x48d6,
+ 0xcf75, 0x25db,
+ 0xcf76, 0x48d7,
+ 0xcf78, 0x1e89,
+ 0xcf79, 0x48d9,
+ 0xcf7c, 0x25d9,
+ 0xcf7d, 0x48dc,
+ 0xcf80, 0x48de,
+ 0xcf81, 0x2211,
+ 0xcf82, 0x48df,
+ 0xcf89, 0x2229,
+ 0xcf8a, 0x25d6,
+ 0xcf8b, 0x48e6,
+ 0xcf93, 0x25dd,
+ 0xcf94, 0x25df,
+ 0xcf95, 0x48ee,
+ 0xcf9e, 0x1fef,
+ 0xcf9f, 0x48f7,
+ 0xcfa0, 0x25d8,
+ 0xcfa1, 0x0f0e,
+ 0xd040, 0x48f8,
+ 0xd04d, 0x1f29,
+ 0xd04e, 0x4905,
+ 0xd051, 0x1e5b,
+ 0xd052, 0x4908,
+ 0xd055, 0x2076,
+ 0xd056, 0x490b,
+ 0xd05c, 0x2297,
+ 0xd05d, 0x4911,
+ 0xd060, 0x2690,
+ 0xd061, 0x4914,
+ 0xd067, 0x213f,
+ 0xd068, 0x491a,
+ 0xd06c, 0x2198,
+ 0xd06d, 0x491e,
+ 0xd06e, 0x1e88,
+ 0xd06f, 0x491f,
+ 0xd07d, 0x228c,
+ 0xd07e, 0x492d,
+ 0xd080, 0x492e,
+ 0xd0a1, 0x0f6c,
+ 0xd140, 0x494f,
+ 0xd155, 0x25f1,
+ 0xd156, 0x4964,
+ 0xd159, 0x200c,
+ 0xd15a, 0x4967,
+ 0xd161, 0x1e58,
+ 0xd162, 0x22ac,
+ 0xd163, 0x496e,
+ 0xd175, 0x26a7,
+ 0xd176, 0x4980,
+ 0xd17d, 0x2676,
+ 0xd17e, 0x4987,
+ 0xd180, 0x4988,
+ 0xd19d, 0x1fe1,
+ 0xd19e, 0x25bb,
+ 0xd19f, 0x49a5,
+ 0xd1a1, 0x0fca,
+ 0xd240, 0x25be,
+ 0xd241, 0x49a7,
+ 0xd243, 0x22dd,
+ 0xd244, 0x49a9,
+ 0xd24d, 0x25bd,
+ 0xd24e, 0x49b2,
+ 0xd25c, 0x1e2a,
+ 0xd25d, 0x49c0,
+ 0xd263, 0x25bc,
+ 0xd264, 0x25ba,
+ 0xd265, 0x49c6,
+ 0xd268, 0x25bf,
+ 0xd269, 0x49c9,
+ 0xd26d, 0x2187,
+ 0xd26e, 0x49cd,
+ 0xd26f, 0x266b,
+ 0xd270, 0x49ce,
+ 0xd272, 0x1e7f,
+ 0xd273, 0x49d0,
+ 0xd275, 0x21ad,
+ 0xd276, 0x49d2,
+ 0xd280, 0x49db,
+ 0xd28a, 0x1f96,
+ 0xd28b, 0x49e5,
+ 0xd28e, 0x1f32,
+ 0xd28f, 0x49e8,
+ 0xd292, 0x2084,
+ 0xd293, 0x49eb,
+ 0xd295, 0x2136,
+ 0xd296, 0x49ed,
+ 0xd297, 0x24b8,
+ 0xd298, 0x49ee,
+ 0xd2a0, 0x24ba,
+ 0xd2a1, 0x1028,
+ 0xd340, 0x49f6,
+ 0xd344, 0x24bc,
+ 0xd345, 0x49fa,
+ 0xd348, 0x20e4,
+ 0xd349, 0x49fd,
+ 0xd34a, 0x24b9,
+ 0xd34b, 0x49fe,
+ 0xd34d, 0x24bd,
+ 0xd34e, 0x4a00,
+ 0xd350, 0x24be,
+ 0xd351, 0x4a02,
+ 0xd355, 0x24bf,
+ 0xd356, 0x4a06,
+ 0xd358, 0x1fd2,
+ 0xd359, 0x4a08,
+ 0xd35b, 0x1ffd,
+ 0xd35c, 0x4a0a,
+ 0xd35d, 0x24bb,
+ 0xd35e, 0x1f2d,
+ 0xd35f, 0x4a0b,
+ 0xd378, 0x2609,
+ 0xd379, 0x4a24,
+ 0xd37a, 0x260a,
+ 0xd37b, 0x4a25,
+ 0xd37c, 0x1e94,
+ 0xd37d, 0x4a26,
+ 0xd380, 0x4a28,
+ 0xd385, 0x22df,
+ 0xd386, 0x1ecb,
+ 0xd387, 0x1f0d,
+ 0xd388, 0x4a2d,
+ 0xd38b, 0x1f77,
+ 0xd38c, 0x4a30,
+ 0xd38d, 0x21eb,
+ 0xd38e, 0x4a31,
+ 0xd38f, 0x22e1,
+ 0xd390, 0x4a32,
+ 0xd391, 0x216f,
+ 0xd392, 0x4a33,
+ 0xd393, 0x22e0,
+ 0xd394, 0x4a34,
+ 0xd396, 0x21ea,
+ 0xd397, 0x4a36,
+ 0xd398, 0x22e2,
+ 0xd399, 0x20cb,
+ 0xd39a, 0x4a37,
+ 0xd39b, 0x1f78,
+ 0xd39c, 0x4a38,
+ 0xd39e, 0x1ee2,
+ 0xd39f, 0x4a3a,
+ 0xd3a0, 0x21f2,
+ 0xd3a1, 0x1086,
+ 0xd440, 0x4a3b,
+ 0xd441, 0x2150,
+ 0xd442, 0x4a3c,
+ 0xd445, 0x1fd3,
+ 0xd446, 0x4a3f,
+ 0xd447, 0x22e5,
+ 0xd448, 0x4a40,
+ 0xd44c, 0x1ef2,
+ 0xd44d, 0x4a44,
+ 0xd44f, 0x211f,
+ 0xd450, 0x4a46,
+ 0xd453, 0x21dd,
+ 0xd454, 0x4a49,
+ 0xd456, 0x2154,
+ 0xd457, 0x4a4b,
+ 0xd458, 0x22e7,
+ 0xd459, 0x4a4c,
+ 0xd45c, 0x2282,
+ 0xd45d, 0x4a4f,
+ 0xd462, 0x22e6,
+ 0xd463, 0x4a54,
+ 0xd467, 0x22e8,
+ 0xd468, 0x4a58,
+ 0xd46e, 0x22e4,
+ 0xd46f, 0x4a5e,
+ 0xd470, 0x226a,
+ 0xd471, 0x4a5f,
+ 0xd472, 0x22eb,
+ 0xd473, 0x4a60,
+ 0xd474, 0x22e9,
+ 0xd475, 0x20bd,
+ 0xd476, 0x4a61,
+ 0xd478, 0x22ea,
+ 0xd479, 0x4a63,
+ 0xd47b, 0x22bd,
+ 0xd47c, 0x4a65,
+ 0xd47e, 0x1e9e,
+ 0xd480, 0x4a67,
+ 0xd482, 0x22f6,
+ 0xd483, 0x21e7,
+ 0xd484, 0x2216,
+ 0xd485, 0x4a69,
+ 0xd487, 0x2137,
+ 0xd488, 0x4a6b,
+ 0xd48a, 0x212c,
+ 0xd48b, 0x4a6d,
+ 0xd48c, 0x1e68,
+ 0xd48d, 0x22f2,
+ 0xd48e, 0x1f37,
+ 0xd48f, 0x22f3,
+ 0xd490, 0x4a6e,
+ 0xd491, 0x22ef,
+ 0xd492, 0x1f50,
+ 0xd493, 0x1f10,
+ 0xd494, 0x21c8,
+ 0xd495, 0x4a6f,
+ 0xd496, 0x22f1,
+ 0xd497, 0x4a70,
+ 0xd49c, 0x22f0,
+ 0xd49d, 0x4a75,
+ 0xd49f, 0x22ee,
+ 0xd4a0, 0x4a77,
+ 0xd4a1, 0x10e4,
+ 0xd540, 0x4a78,
+ 0xd543, 0x22ed,
+ 0xd544, 0x229e,
+ 0xd545, 0x22ec,
+ 0xd546, 0x1fe2,
+ 0xd547, 0x4a7b,
+ 0xd54a, 0x20fe,
+ 0xd54b, 0x4a7e,
+ 0xd54e, 0x22f9,
+ 0xd550, 0x4a81,
+ 0xd551, 0x1eaf,
+ 0xd552, 0x4a82,
+ 0xd554, 0x2236,
+ 0xd555, 0x4a84,
+ 0xd556, 0x22f7,
+ 0xd557, 0x4a85,
+ 0xd55a, 0x223d,
+ 0xd55b, 0x4a88,
+ 0xd55c, 0x1e82,
+ 0xd55d, 0x1fb6,
+ 0xd55e, 0x4a89,
+ 0xd55f, 0x21a4,
+ 0xd560, 0x21aa,
+ 0xd561, 0x22f8,
+ 0xd562, 0x2151,
+ 0xd563, 0x4a8a,
+ 0xd564, 0x1f60,
+ 0xd565, 0x4a8b,
+ 0xd568, 0x2147,
+ 0xd569, 0x4a8e,
+ 0xd56c, 0x2145,
+ 0xd56d, 0x4a91,
+ 0xd56e, 0x1fdc,
+ 0xd56f, 0x4a92,
+ 0xd572, 0x2301,
+ 0xd573, 0x4a95,
+ 0xd575, 0x1ef5,
+ 0xd576, 0x4a97,
+ 0xd578, 0x2218,
+ 0xd579, 0x4a99,
+ 0xd57b, 0x1ec6,
+ 0xd57c, 0x4a9b,
+ 0xd57e, 0x2300,
+ 0xd580, 0x4a9d,
+ 0xd581, 0x22b4,
+ 0xd582, 0x4a9e,
+ 0xd584, 0x2169,
+ 0xd585, 0x4aa0,
+ 0xd586, 0x22fd,
+ 0xd587, 0x4aa1,
+ 0xd588, 0x20ea,
+ 0xd589, 0x4aa2,
+ 0xd58a, 0x22f4,
+ 0xd58b, 0x4aa3,
+ 0xd58c, 0x22fb,
+ 0xd58d, 0x4aa4,
+ 0xd58e, 0x22fc,
+ 0xd58f, 0x2027,
+ 0xd590, 0x4aa5,
+ 0xd593, 0x2060,
+ 0xd594, 0x22ff,
+ 0xd595, 0x4aa8,
+ 0xd598, 0x22fe,
+ 0xd599, 0x1ec7,
+ 0xd59a, 0x4aab,
+ 0xd59b, 0x230c,
+ 0xd59c, 0x4aac,
+ 0xd59f, 0x22f5,
+ 0xd5a0, 0x4aaf,
+ 0xd5a1, 0x1142,
+ 0xd640, 0x2306,
+ 0xd641, 0x4ab0,
+ 0xd642, 0x230a,
+ 0xd643, 0x21d3,
+ 0xd644, 0x4ab1,
+ 0xd647, 0x2303,
+ 0xd648, 0x4ab4,
+ 0xd649, 0x2307,
+ 0xd64a, 0x230b,
+ 0xd64b, 0x4ab5,
+ 0xd64d, 0x1f5f,
+ 0xd64e, 0x4ab7,
+ 0xd64f, 0x2309,
+ 0xd650, 0x4ab8,
+ 0xd652, 0x2302,
+ 0xd653, 0x1f04,
+ 0xd654, 0x229d,
+ 0xd655, 0x4aba,
+ 0xd656, 0x21fb,
+ 0xd657, 0x4abb,
+ 0xd658, 0x2308,
+ 0xd659, 0x4abc,
+ 0xd65a, 0x20ac,
+ 0xd65b, 0x4abd,
+ 0xd65c, 0x208e,
+ 0xd65d, 0x2305,
+ 0xd65e, 0x2197,
+ 0xd65f, 0x4abe,
+ 0xd660, 0x2171,
+ 0xd661, 0x2298,
+ 0xd662, 0x4abf,
+ 0xd665, 0x1f57,
+ 0xd666, 0x4ac2,
+ 0xd669, 0x2082,
+ 0xd66a, 0x4ac5,
+ 0xd66b, 0x2311,
+ 0xd66c, 0x4ac6,
+ 0xd66f, 0x2304,
+ 0xd670, 0x4ac9,
+ 0xd671, 0x230f,
+ 0xd672, 0x1e35,
+ 0xd673, 0x4aca,
+ 0xd674, 0x20d1,
+ 0xd675, 0x2310,
+ 0xd676, 0x1fa3,
+ 0xd677, 0x4acb,
+ 0xd678, 0x21d6,
+ 0xd679, 0x4acc,
+ 0xd67c, 0x2206,
+ 0xd67d, 0x4acf,
+ 0xd680, 0x4ad1,
+ 0xd683, 0x230d,
+ 0xd684, 0x4ad4,
+ 0xd686, 0x2312,
+ 0xd687, 0x208d,
+ 0xd688, 0x2313,
+ 0xd689, 0x4ad6,
+ 0xd68e, 0x22e3,
+ 0xd68f, 0x4adb,
+ 0xd694, 0x1fba,
+ 0xd695, 0x4ae0,
+ 0xd699, 0x2078,
+ 0xd69a, 0x4ae4,
+ 0xd6a1, 0x11a0,
+ 0xd740, 0x4aeb,
+ 0xd743, 0x2288,
+ 0xd744, 0x4aee,
+ 0xd748, 0x2316,
+ 0xd749, 0x1f6b,
+ 0xd74a, 0x4af2,
+ 0xd750, 0x2314,
+ 0xd751, 0x4af8,
+ 0xd752, 0x2130,
+ 0xd753, 0x2315,
+ 0xd754, 0x2168,
+ 0xd755, 0x4af9,
+ 0xd756, 0x20c4,
+ 0xd757, 0x4afa,
+ 0xd764, 0x2318,
+ 0xd765, 0x4b07,
+ 0xd767, 0x2219,
+ 0xd768, 0x2217,
+ 0xd769, 0x4b09,
+ 0xd76c, 0x20d5,
+ 0xd76d, 0x4b0c,
+ 0xd76f, 0x1f4a,
+ 0xd770, 0x4b0e,
+ 0xd775, 0x2240,
+ 0xd776, 0x4b13,
+ 0xd778, 0x1ed3,
+ 0xd779, 0x4b15,
+ 0xd780, 0x4b1b,
+ 0xd783, 0x1e49,
+ 0xd784, 0x4b1e,
+ 0xd787, 0x261b,
+ 0xd788, 0x4b21,
+ 0xd78b, 0x1e6d,
+ 0xd78c, 0x20f8,
+ 0xd78d, 0x4b24,
+ 0xd78e, 0x1ffb,
+ 0xd78f, 0x2319,
+ 0xd790, 0x4b25,
+ 0xd795, 0x230e,
+ 0xd796, 0x4b2a,
+ 0xd797, 0x2317,
+ 0xd798, 0x4b2b,
+ 0xd7a1, 0x11fe,
+ 0xd840, 0x4b34,
+ 0xd84d, 0x20c8,
+ 0xd84e, 0x4b41,
+ 0xd853, 0x1efd,
+ 0xd854, 0x4b46,
+ 0xd880, 0x4b71,
+ 0xd890, 0x1e3b,
+ 0xd891, 0x227f,
+ 0xd892, 0x4b81,
+ 0xd893, 0x1f0c,
+ 0xd894, 0x1e59,
+ 0xd895, 0x1f24,
+ 0xd896, 0x4b82,
+ 0xd89a, 0x20ba,
+ 0xd89b, 0x1f65,
+ 0xd89c, 0x1ef0,
+ 0xd89d, 0x2164,
+ 0xd89e, 0x1f30,
+ 0xd89f, 0x2261,
+ 0xd8a0, 0x4b86,
+ 0xd8a1, 0x1257,
+ 0xd940, 0x4b87,
+ 0xd941, 0x22a2,
+ 0xd942, 0x24ab,
+ 0xd943, 0x4b88,
+ 0xd944, 0x24af,
+ 0xd945, 0x1ee8,
+ 0xd946, 0x1f39,
+ 0xd947, 0x4b89,
+ 0xd948, 0x1e48,
+ 0xd949, 0x2070,
+ 0xd94a, 0x1ea8,
+ 0xd94b, 0x4b8a,
+ 0xd94c, 0x24ac,
+ 0xd94d, 0x1ef7,
+ 0xd94e, 0x2176,
+ 0xd94f, 0x24ad,
+ 0xd950, 0x4b8b,
+ 0xd951, 0x207b,
+ 0xd952, 0x1f45,
+ 0xd953, 0x24aa,
+ 0xd954, 0x204b,
+ 0xd955, 0x202f,
+ 0xd956, 0x1f5a,
+ 0xd957, 0x24b0,
+ 0xd958, 0x4b8c,
+ 0xd959, 0x22b7,
+ 0xd95a, 0x1f7f,
+ 0xd95b, 0x4b8d,
+ 0xd95c, 0x2265,
+ 0xd95d, 0x4b8e,
+ 0xd963, 0x24b2,
+ 0xd964, 0x211b,
+ 0xd965, 0x1e51,
+ 0xd966, 0x4b94,
+ 0xd967, 0x24b4,
+ 0xd968, 0x4b95,
+ 0xd96c, 0x24b3,
+ 0xd96d, 0x4b99,
+ 0xd96e, 0x1e9f,
+ 0xd96f, 0x4b9a,
+ 0xd970, 0x2118,
+ 0xd971, 0x4b9b,
+ 0xd972, 0x20b4,
+ 0xd973, 0x23af,
+ 0xd974, 0x21bb,
+ 0xd975, 0x2072,
+ 0xd976, 0x1f95,
+ 0xd977, 0x4b9c,
+ 0xd978, 0x1f0a,
+ 0xd979, 0x24b6,
+ 0xd97a, 0x4b9d,
+ 0xd97c, 0x2291,
+ 0xd97d, 0x24b5,
+ 0xd97e, 0x2278,
+ 0xd980, 0x1ed4,
+ 0xd981, 0x4b9f,
+ 0xd987, 0x1ff3,
+ 0xd988, 0x4ba5,
+ 0xd98d, 0x22a9,
+ 0xd98e, 0x24b7,
+ 0xd98f, 0x1f28,
+ 0xd990, 0x2109,
+ 0xd991, 0x22c7,
+ 0xd992, 0x4baa,
+ 0xd997, 0x24ae,
+ 0xd998, 0x22b1,
+ 0xd999, 0x4baf,
+ 0xd99b, 0x2266,
+ 0xd99c, 0x4bb1,
+ 0xd99d, 0x225b,
+ 0xd99e, 0x22c4,
+ 0xd99f, 0x4bb2,
+ 0xd9a0, 0x2115,
+ 0xd9a1, 0x12b5,
+ 0xda40, 0x4bb3,
+ 0xda41, 0x222a,
+ 0xda42, 0x24b1,
+ 0xda43, 0x4bb4,
+ 0xda48, 0x213d,
+ 0xda49, 0x4bb9,
+ 0xda4d, 0x1f15,
+ 0xda4e, 0x225c,
+ 0xda4f, 0x4bbd,
+ 0xda73, 0x1f14,
+ 0xda74, 0x4be1,
+ 0xda77, 0x227a,
+ 0xda78, 0x4be4,
+ 0xda80, 0x4beb,
+ 0xda85, 0x20ee,
+ 0xda86, 0x4bf0,
+ 0xda8e, 0x25f8,
+ 0xda8f, 0x4bf8,
+ 0xdaa1, 0x1313,
+ 0xdb40, 0x4c0a,
+ 0xdb60, 0x1f94,
+ 0xdb61, 0x4c2a,
+ 0xdb78, 0x2230,
+ 0xdb79, 0x4c41,
+ 0xdb80, 0x4c47,
+ 0xdb84, 0x25fd,
+ 0xdb85, 0x4c4b,
+ 0xdb8b, 0x2600,
+ 0xdb8c, 0x4c51,
+ 0xdb98, 0x2606,
+ 0xdb99, 0x4c5d,
+ 0xdba1, 0x1371,
+ 0xdc40, 0x4c65,
+ 0xdc45, 0x25ff,
+ 0xdc46, 0x4c6a,
+ 0xdc4f, 0x25fc,
+ 0xdc50, 0x1e8c,
+ 0xdc51, 0x2602,
+ 0xdc52, 0x4c73,
+ 0xdc53, 0x224d,
+ 0xdc54, 0x4c74,
+ 0xdc55, 0x2604,
+ 0xdc56, 0x25fe,
+ 0xdc57, 0x2603,
+ 0xdc58, 0x4c75,
+ 0xdc5d, 0x2601,
+ 0xdc5e, 0x4c7a,
+ 0xdc62, 0x2605,
+ 0xdc63, 0x4c7e,
+ 0xdc66, 0x1ea3,
+ 0xdc67, 0x2608,
+ 0xdc68, 0x4c81,
+ 0xdc6b, 0x2607,
+ 0xdc6c, 0x4c84,
+ 0xdc7c, 0x20f0,
+ 0xdc7d, 0x4c94,
+ 0xdc80, 0x4c96,
+ 0xdc87, 0x1e7b,
+ 0xdc88, 0x2267,
+ 0xdc89, 0x1f36,
+ 0xdc8a, 0x1fd6,
+ 0xdc8b, 0x4c9d,
+ 0xdc8e, 0x21e0,
+ 0xdc8f, 0x4ca0,
+ 0xdc90, 0x248c,
+ 0xdc91, 0x4ca1,
+ 0xdc97, 0x248d,
+ 0xdc98, 0x4ca7,
+ 0xdc9b, 0x2102,
+ 0xdc9c, 0x4caa,
+ 0xdca0, 0x2494,
+ 0xdca1, 0x13cf,
+ 0xdd40, 0x4cae,
+ 0xdd46, 0x2493,
+ 0xdd47, 0x4cb4,
+ 0xdd4d, 0x248e,
+ 0xdd4e, 0x4cba,
+ 0xdd53, 0x2299,
+ 0xdd54, 0x2491,
+ 0xdd55, 0x2496,
+ 0xdd56, 0x248f,
+ 0xdd57, 0x2492,
+ 0xdd58, 0x4cbf,
+ 0xdd59, 0x2497,
+ 0xdd5a, 0x4cc0,
+ 0xdd5e, 0x1fb1,
+ 0xdd5f, 0x4cc4,
+ 0xdd60, 0x249a,
+ 0xdd61, 0x4cc5,
+ 0xdd62, 0x2499,
+ 0xdd63, 0x4cc6,
+ 0xdd64, 0x2258,
+ 0xdd65, 0x2498,
+ 0xdd66, 0x4cc7,
+ 0xdd6d, 0x249b,
+ 0xdd6e, 0x4cce,
+ 0xdd6f, 0x1f09,
+ 0xdd70, 0x20e6,
+ 0xdd71, 0x4ccf,
+ 0xdd76, 0x2026,
+ 0xdd77, 0x249f,
+ 0xdd78, 0x1f59,
+ 0xdd79, 0x249d,
+ 0xdd7b, 0x4cd4,
+ 0xdd80, 0x4cd8,
+ 0xdd81, 0x1f3b,
+ 0xdd82, 0x249c,
+ 0xdd83, 0x4cd9,
+ 0xdd85, 0x1e3a,
+ 0xdd86, 0x205b,
+ 0xdd87, 0x4cdb,
+ 0xdd8b, 0x1f70,
+ 0xdd8c, 0x4cdf,
+ 0xdd8f, 0x24a0,
+ 0xdd90, 0x4ce2,
+ 0xdd94, 0x213b,
+ 0xdd95, 0x4ce6,
+ 0xdd97, 0x1f07,
+ 0xdd98, 0x4ce8,
+ 0xdd9a, 0x2270,
+ 0xdd9b, 0x2237,
+ 0xdd9c, 0x4cea,
+ 0xdd9e, 0x24d2,
+ 0xdd9f, 0x4cec,
+ 0xdda0, 0x21b3,
+ 0xdda1, 0x142d,
+ 0xde40, 0x2245,
+ 0xde41, 0x24a1,
+ 0xde42, 0x4ced,
+ 0xde44, 0x22a8,
+ 0xde45, 0x4cef,
+ 0xde48, 0x227c,
+ 0xde49, 0x1fb0,
+ 0xde4a, 0x4cf2,
+ 0xde4f, 0x24a2,
+ 0xde50, 0x4cf7,
+ 0xde5a, 0x1f46,
+ 0xde5b, 0x4d01,
+ 0xde5c, 0x2380,
+ 0xde5d, 0x2495,
+ 0xde5e, 0x4d02,
+ 0xde5f, 0x2490,
+ 0xde60, 0x4d03,
+ 0xde6b, 0x1e30,
+ 0xde6c, 0x4d0e,
+ 0xde6f, 0x1e9d,
+ 0xde70, 0x1e4b,
+ 0xde71, 0x1e4a,
+ 0xde72, 0x20aa,
+ 0xde73, 0x4d11,
+ 0xde80, 0x4d1d,
+ 0xde92, 0x267b,
+ 0xde93, 0x4d2f,
+ 0xde9f, 0x23f2,
+ 0xdea0, 0x4d3b,
+ 0xdea1, 0x148b,
+ 0xdf40, 0x227e,
+ 0xdf41, 0x4d3c,
+ 0xdf42, 0x2019,
+ 0xdf43, 0x4d3d,
+ 0xdf4d, 0x1fbb,
+ 0xdf4e, 0x4d47,
+ 0xdf5c, 0x2253,
+ 0xdf5d, 0x4d55,
+ 0xdf5e, 0x1f3e,
+ 0xdf5f, 0x1ea6,
+ 0xdf60, 0x218e,
+ 0xdf61, 0x4d56,
+ 0xdf64, 0x21ec,
+ 0xdf65, 0x4d59,
+ 0xdf66, 0x1ebe,
+ 0xdf67, 0x4d5a,
+ 0xdf68, 0x224a,
+ 0xdf69, 0x4d5b,
+ 0xdf6d, 0x2133,
+ 0xdf6e, 0x4d5f,
+ 0xdf74, 0x1e84,
+ 0xdf75, 0x4d65,
+ 0xdf77, 0x20cf,
+ 0xdf78, 0x21e2,
+ 0xdf79, 0x4d67,
+ 0xdf7a, 0x220f,
+ 0xdf7b, 0x4d68,
+ 0xdf7c, 0x2029,
+ 0xdf7d, 0x4d69,
+ 0xdf7e, 0x2073,
+ 0xdf80, 0x1f55,
+ 0xdf81, 0x4d6a,
+ 0xdf83, 0x23f1,
+ 0xdf84, 0x4d6c,
+ 0xdf85, 0x1e46,
+ 0xdf86, 0x4d6d,
+ 0xdf89, 0x2063,
+ 0xdf8a, 0x23f3,
+ 0xdf8b, 0x4d70,
+ 0xdfa1, 0x14e9,
+ 0xe040, 0x4d86,
+ 0xe050, 0x231e,
+ 0xe051, 0x4d96,
+ 0xe05d, 0x2233,
+ 0xe05e, 0x4da2,
+ 0xe069, 0x2320,
+ 0xe06a, 0x4dad,
+ 0xe06c, 0x21c7,
+ 0xe06d, 0x4daf,
+ 0xe075, 0x22bc,
+ 0xe076, 0x4db7,
+ 0xe077, 0x231c,
+ 0xe078, 0x4db8,
+ 0xe079, 0x2251,
+ 0xe07a, 0x4db9,
+ 0xe080, 0x4dbe,
+ 0xe087, 0x1ebb,
+ 0xe088, 0x4dc5,
+ 0xe08d, 0x2287,
+ 0xe08e, 0x4dca,
+ 0xe08f, 0x202d,
+ 0xe090, 0x1eab,
+ 0xe091, 0x4dcb,
+ 0xe092, 0x231d,
+ 0xe093, 0x4dcc,
+ 0xe094, 0x231f,
+ 0xe095, 0x4dcd,
+ 0xe097, 0x231b,
+ 0xe098, 0x4dcf,
+ 0xe0a1, 0x1547,
+ 0xe140, 0x4dd8,
+ 0xe142, 0x2321,
+ 0xe143, 0x4dda,
+ 0xe164, 0x2255,
+ 0xe165, 0x4dfb,
+ 0xe168, 0x1e8f,
+ 0xe169, 0x4dfe,
+ 0xe174, 0x220c,
+ 0xe175, 0x1fa4,
+ 0xe176, 0x4e09,
+ 0xe180, 0x4e12,
+ 0xe184, 0x209b,
+ 0xe185, 0x21d8,
+ 0xe186, 0x4e16,
+ 0xe187, 0x25fa,
+ 0xe188, 0x4e17,
+ 0xe189, 0x25f9,
+ 0xe18a, 0x4e18,
+ 0xe18c, 0x2134,
+ 0xe18d, 0x4e1a,
+ 0xe18e, 0x24f3,
+ 0xe191, 0x24f8,
+ 0xe192, 0x4e1b,
+ 0xe193, 0x24f7,
+ 0xe194, 0x1ec8,
+ 0xe195, 0x24f6,
+ 0xe196, 0x4e1c,
+ 0xe198, 0x2280,
+ 0xe199, 0x4e1e,
+ 0xe19e, 0x1ec5,
+ 0xe19f, 0x24fb,
+ 0xe1a0, 0x4e23,
+ 0xe1a1, 0x15a5,
+ 0xe240, 0x4e24,
+ 0xe241, 0x24fa,
+ 0xe242, 0x4e25,
+ 0xe243, 0x1eed,
+ 0xe244, 0x4e26,
+ 0xe24f, 0x24fd,
+ 0xe250, 0x4e31,
+ 0xe251, 0x24f9,
+ 0xe252, 0x4e32,
+ 0xe253, 0x24fe,
+ 0xe254, 0x20cd,
+ 0xe255, 0x4e33,
+ 0xe25a, 0x2508,
+ 0xe25b, 0x2504,
+ 0xe25c, 0x4e38,
+ 0xe25e, 0x2506,
+ 0xe25f, 0x4e3a,
+ 0xe262, 0x24ff,
+ 0xe263, 0x2090,
+ 0xe264, 0x4e3d,
+ 0xe267, 0x1edd,
+ 0xe268, 0x1f25,
+ 0xe269, 0x4e40,
+ 0xe26a, 0x2503,
+ 0xe26b, 0x2502,
+ 0xe26c, 0x4e41,
+ 0xe26e, 0x1e7a,
+ 0xe26f, 0x20a6,
+ 0xe270, 0x4e43,
+ 0xe278, 0x1fd5,
+ 0xe279, 0x4e4b,
+ 0xe27d, 0x1f11,
+ 0xe27e, 0x4e4f,
+ 0xe280, 0x2507,
+ 0xe281, 0x2500,
+ 0xe282, 0x2505,
+ 0xe283, 0x4e50,
+ 0xe289, 0x2519,
+ 0xe28a, 0x4e56,
+ 0xe28b, 0x2515,
+ 0xe28c, 0x4e57,
+ 0xe28e, 0x250c,
+ 0xe28f, 0x2031,
+ 0xe290, 0x4e59,
+ 0xe292, 0x250b,
+ 0xe293, 0x250f,
+ 0xe294, 0x251a,
+ 0xe295, 0x2509,
+ 0xe296, 0x4e5b,
+ 0xe298, 0x250e,
+ 0xe299, 0x2234,
+ 0xe29a, 0x2513,
+ 0xe29b, 0x1f80,
+ 0xe29c, 0x4e5d,
+ 0xe2a0, 0x2501,
+ 0xe2a1, 0x1603,
+ 0xe340, 0x4e61,
+ 0xe342, 0x2517,
+ 0xe343, 0x2516,
+ 0xe344, 0x4e63,
+ 0xe347, 0x2518,
+ 0xe348, 0x4e66,
+ 0xe34b, 0x1e56,
+ 0xe34c, 0x4e69,
+ 0xe34f, 0x250d,
+ 0xe350, 0x4e6c,
+ 0xe351, 0x20d3,
+ 0xe352, 0x4e6d,
+ 0xe354, 0x207a,
+ 0xe355, 0x20ce,
+ 0xe356, 0x4e6f,
+ 0xe358, 0x2510,
+ 0xe359, 0x4e71,
+ 0xe35c, 0x1e55,
+ 0xe35d, 0x4e74,
+ 0xe360, 0x250a,
+ 0xe361, 0x4e77,
+ 0xe366, 0x2511,
+ 0xe368, 0x4e7c,
+ 0xe371, 0x1faa,
+ 0xe372, 0x4e85,
+ 0xe373, 0x251e,
+ 0xe374, 0x1f1f,
+ 0xe375, 0x4e86,
+ 0xe378, 0x252d,
+ 0xe379, 0x221d,
+ 0xe37a, 0x4e89,
+ 0xe37c, 0x2532,
+ 0xe37d, 0x4e8b,
+ 0xe37e, 0x217b,
+ 0xe380, 0x4e8c,
+ 0xe38a, 0x21af,
+ 0xe38b, 0x4e96,
+ 0xe38c, 0x252c,
+ 0xe38d, 0x4e97,
+ 0xe38f, 0x2528,
+ 0xe390, 0x4e99,
+ 0xe391, 0x208c,
+ 0xe392, 0x4e9a,
+ 0xe393, 0x252f,
+ 0xe394, 0x4e9b,
+ 0xe395, 0x21bc,
+ 0xe396, 0x4e9c,
+ 0xe399, 0x251d,
+ 0xe39a, 0x4e9f,
+ 0xe39c, 0x2535,
+ 0xe39d, 0x4ea1,
+ 0xe39e, 0x220d,
+ 0xe39f, 0x2526,
+ 0xe3a0, 0x4ea2,
+ 0xe3a1, 0x1661,
+ 0xe440, 0x2534,
+ 0xe441, 0x252a,
+ 0xe442, 0x251f,
+ 0xe443, 0x2531,
+ 0xe444, 0x251c,
+ 0xe445, 0x4ea3,
+ 0xe448, 0x2525,
+ 0xe449, 0x4ea6,
+ 0xe44e, 0x21cd,
+ 0xe44f, 0x4eab,
+ 0xe450, 0x21da,
+ 0xe451, 0x4eac,
+ 0xe452, 0x2172,
+ 0xe453, 0x253e,
+ 0xe454, 0x4ead,
+ 0xe458, 0x204f,
+ 0xe459, 0x4eb1,
+ 0xe45a, 0x2543,
+ 0xe45b, 0x4eb2,
+ 0xe45c, 0x21d7,
+ 0xe45d, 0x4eb3,
+ 0xe45e, 0x1e3c,
+ 0xe45f, 0x4eb4,
+ 0xe462, 0x2529,
+ 0xe463, 0x4eb7,
+ 0xe465, 0x2521,
+ 0xe466, 0x4eb9,
+ 0xe468, 0x1eff,
+ 0xe469, 0x4ebb,
+ 0xe473, 0x253f,
+ 0xe474, 0x4ec5,
+ 0xe475, 0x2544,
+ 0xe476, 0x4ec6,
+ 0xe479, 0x2523,
+ 0xe47a, 0x1e90,
+ 0xe47b, 0x253a,
+ 0xe47c, 0x2545,
+ 0xe47d, 0x4ec9,
+ 0xe47e, 0x253d,
+ 0xe480, 0x4eca,
+ 0xe481, 0x20c1,
+ 0xe482, 0x4ecb,
+ 0xe484, 0x2103,
+ 0xe485, 0x2520,
+ 0xe486, 0x253c,
+ 0xe487, 0x253b,
+ 0xe488, 0x2538,
+ 0xe489, 0x4ecd,
+ 0xe48d, 0x2540,
+ 0xe48e, 0x4ed1,
+ 0xe48f, 0x1fcd,
+ 0xe490, 0x4ed2,
+ 0xe493, 0x1f18,
+ 0xe494, 0x4ed5,
+ 0xe498, 0x254b,
+ 0xe499, 0x4ed9,
+ 0xe49d, 0x2547,
+ 0xe49e, 0x254f,
+ 0xe4a0, 0x4edd,
+ 0xe4a1, 0x16bf,
+ 0xe540, 0x4ede,
+ 0xe546, 0x22b0,
+ 0xe547, 0x4ee4,
+ 0xe548, 0x2546,
+ 0xe549, 0x4ee5,
+ 0xe54b, 0x254c,
+ 0xe54c, 0x4ee7,
+ 0xe54e, 0x1e9a,
+ 0xe54f, 0x2552,
+ 0xe550, 0x2530,
+ 0xe551, 0x2549,
+ 0xe552, 0x4ee9,
+ 0xe555, 0x2551,
+ 0xe556, 0x1eca,
+ 0xe557, 0x4eec,
+ 0xe558, 0x20d2,
+ 0xe559, 0x4eed,
+ 0xe55c, 0x1fb8,
+ 0xe55d, 0x4ef0,
+ 0xe55e, 0x2079,
+ 0xe55f, 0x4ef1,
+ 0xe561, 0x21ab,
+ 0xe562, 0x4ef3,
+ 0xe564, 0x254d,
+ 0xe565, 0x1ea5,
+ 0xe566, 0x4ef5,
+ 0xe568, 0x204c,
+ 0xe569, 0x2080,
+ 0xe56a, 0x4ef7,
+ 0xe56c, 0x266d,
+ 0xe56d, 0x4ef9,
+ 0xe56e, 0x2537,
+ 0xe56f, 0x4efa,
+ 0xe575, 0x254a,
+ 0xe576, 0x21b8,
+ 0xe577, 0x4f00,
+ 0xe578, 0x254e,
+ 0xe579, 0x4f01,
+ 0xe57b, 0x24fc,
+ 0xe57c, 0x2554,
+ 0xe57d, 0x4f03,
+ 0xe580, 0x4f05,
+ 0xe581, 0x1f3c,
+ 0xe582, 0x4f06,
+ 0xe583, 0x1ed5,
+ 0xe584, 0x4f07,
+ 0xe58a, 0x2556,
+ 0xe58b, 0x4f0d,
+ 0xe58e, 0x2268,
+ 0xe58f, 0x4f10,
+ 0xe591, 0x1ed6,
+ 0xe592, 0x4f12,
+ 0xe59a, 0x2557,
+ 0xe59b, 0x2553,
+ 0xe59c, 0x4f1a,
+ 0xe59f, 0x2548,
+ 0xe5a0, 0x4f1d,
+ 0xe5a1, 0x171d,
+ 0xe640, 0x20dc,
+ 0xe641, 0x4f1e,
+ 0xe644, 0x2559,
+ 0xe645, 0x4f21,
+ 0xe649, 0x1f97,
+ 0xe64a, 0x2555,
+ 0xe64b, 0x4f25,
+ 0xe64e, 0x227d,
+ 0xe64f, 0x4f28,
+ 0xe652, 0x257e,
+ 0xe653, 0x4f2b,
+ 0xe656, 0x207c,
+ 0xe657, 0x4f2e,
+ 0xe658, 0x255a,
+ 0xe659, 0x4f2f,
+ 0xe65b, 0x255e,
+ 0xe65c, 0x4f31,
+ 0xe65e, 0x1e34,
+ 0xe65f, 0x4f33,
+ 0xe669, 0x215e,
+ 0xe66a, 0x4f3d,
+ 0xe66b, 0x2560,
+ 0xe66c, 0x4f3e,
+ 0xe675, 0x21a2,
+ 0xe676, 0x2354,
+ 0xe677, 0x4f47,
+ 0xe679, 0x2563,
+ 0xe67a, 0x2527,
+ 0xe67b, 0x4f49,
+ 0xe67c, 0x252e,
+ 0xe67d, 0x2558,
+ 0xe67e, 0x4f4a,
+ 0xe680, 0x1f1b,
+ 0xe681, 0x4f4b,
+ 0xe682, 0x2283,
+ 0xe683, 0x4f4c,
+ 0xe684, 0x2564,
+ 0xe685, 0x4f4d,
+ 0xe687, 0x20a0,
+ 0xe688, 0x4f4f,
+ 0xe689, 0x2565,
+ 0xe68a, 0x4f50,
+ 0xe68c, 0x2561,
+ 0xe68d, 0x4f52,
+ 0xe693, 0x2562,
+ 0xe694, 0x4f58,
+ 0xe697, 0x256c,
+ 0xe698, 0x4f5b,
+ 0xe69b, 0x256d,
+ 0xe69c, 0x2020,
+ 0xe69d, 0x4f5e,
+ 0xe69f, 0x255f,
+ 0xe6a0, 0x256a,
+ 0xe6a1, 0x177b,
+ 0xe740, 0x4f60,
+ 0xe743, 0x256e,
+ 0xe744, 0x4f63,
+ 0xe748, 0x2539,
+ 0xe749, 0x255c,
+ 0xe74a, 0x4f67,
+ 0xe74d, 0x2568,
+ 0xe74f, 0x256b,
+ 0xe750, 0x1e6f,
+ 0xe751, 0x4f6a,
+ 0xe752, 0x1fc4,
+ 0xe753, 0x2567,
+ 0xe754, 0x4f6b,
+ 0xe755, 0x255b,
+ 0xe756, 0x4f6c,
+ 0xe759, 0x261d,
+ 0xe75a, 0x4f6f,
+ 0xe766, 0x252b,
+ 0xe767, 0x4f7b,
+ 0xe768, 0x2571,
+ 0xe769, 0x4f7c,
+ 0xe76a, 0x2577,
+ 0xe76b, 0x4f7d,
+ 0xe774, 0x2522,
+ 0xe775, 0x4f86,
+ 0xe77c, 0x2533,
+ 0xe77d, 0x4f8d,
+ 0xe780, 0x4f8f,
+ 0xe782, 0x202a,
+ 0xe783, 0x4f91,
+ 0xe784, 0x2536,
+ 0xe785, 0x2573,
+ 0xe786, 0x256f,
+ 0xe787, 0x4f92,
+ 0xe78a, 0x2293,
+ 0xe78b, 0x2578,
+ 0xe78c, 0x4f95,
+ 0xe78f, 0x2570,
+ 0xe790, 0x4f98,
+ 0xe792, 0x2575,
+ 0xe793, 0x4f9a,
+ 0xe798, 0x2541,
+ 0xe79a, 0x255d,
+ 0xe79b, 0x4f9f,
+ 0xe7a0, 0x201a,
+ 0xe7a1, 0x17d9,
+ 0xe840, 0x4fa4,
+ 0xe843, 0x257a,
+ 0xe844, 0x2006,
+ 0xe845, 0x4fa7,
+ 0xe846, 0x2177,
+ 0xe847, 0x4fa8,
+ 0xe849, 0x251b,
+ 0xe84a, 0x4faa,
+ 0xe84b, 0x2524,
+ 0xe84c, 0x4fab,
+ 0xe84f, 0x257b,
+ 0xe850, 0x4fae,
+ 0xe854, 0x22a3,
+ 0xe855, 0x4fb2,
+ 0xe85a, 0x2579,
+ 0xe85b, 0x4fb7,
+ 0xe85c, 0x2566,
+ 0xe85d, 0x4fb8,
+ 0xe862, 0x1f93,
+ 0xe863, 0x4fbd,
+ 0xe864, 0x257c,
+ 0xe865, 0x4fbe,
+ 0xe870, 0x2514,
+ 0xe871, 0x4fc9,
+ 0xe873, 0x257d,
+ 0xe874, 0x4fcb,
+ 0xe875, 0x2572,
+ 0xe876, 0x4fcc,
+ 0xe87c, 0x2574,
+ 0xe87d, 0x4fd2,
+ 0xe880, 0x224e,
+ 0xe881, 0x4fd4,
+ 0xe882, 0x21c6,
+ 0xe883, 0x4fd5,
+ 0xe887, 0x209f,
+ 0xe888, 0x4fd9,
+ 0xe889, 0x2576,
+ 0xe88a, 0x4fda,
+ 0xe88c, 0x2064,
+ 0xe88d, 0x22bf,
+ 0xe88e, 0x261c,
+ 0xe88f, 0x225e,
+ 0xe890, 0x4fdc,
+ 0xe8a1, 0x1837,
+ 0xe940, 0x4fed,
+ 0xe94c, 0x1e75,
+ 0xe94d, 0x4ff9,
+ 0xe954, 0x207d,
+ 0xe955, 0x5000,
+ 0xe956, 0x23bf,
+ 0xe957, 0x2113,
+ 0xe958, 0x5001,
+ 0xe95a, 0x23c0,
+ 0xe95b, 0x5003,
+ 0xe95d, 0x1e45,
+ 0xe95e, 0x5005,
+ 0xe95f, 0x1fd8,
+ 0xe960, 0x23c4,
+ 0xe961, 0x5006,
+ 0xe962, 0x23c2,
+ 0xe963, 0x2104,
+ 0xe964, 0x5007,
+ 0xe965, 0x21bd,
+ 0xe966, 0x5008,
+ 0xe967, 0x1f87,
+ 0xe968, 0x23c3,
+ 0xe969, 0x5009,
+ 0xe96c, 0x2269,
+ 0xe96d, 0x500c,
+ 0xe975, 0x1f43,
+ 0xe976, 0x5014,
+ 0xe977, 0x1f1e,
+ 0xe978, 0x2679,
+ 0xe979, 0x1eeb,
+ 0xe97a, 0x5015,
+ 0xe97c, 0x1f35,
+ 0xe97d, 0x208a,
+ 0xe97e, 0x5017,
+ 0xe980, 0x23c7,
+ 0xe981, 0x23c9,
+ 0xe982, 0x23c6,
+ 0xe983, 0x5018,
+ 0xe987, 0x224f,
+ 0xe988, 0x501c,
+ 0xe98b, 0x23cb,
+ 0xe98c, 0x501f,
+ 0xe98e, 0x21f3,
+ 0xe98f, 0x5021,
+ 0xe990, 0x21f7,
+ 0xe991, 0x23cf,
+ 0xe992, 0x23ce,
+ 0xe993, 0x23ca,
+ 0xe994, 0x23cd,
+ 0xe995, 0x5022,
+ 0xe998, 0x23d0,
+ 0xe999, 0x5025,
+ 0xe99b, 0x266c,
+ 0xe99c, 0x5027,
+ 0xe99d, 0x23c1,
+ 0xe99e, 0x5028,
+ 0xe99f, 0x1fee,
+ 0xe9a0, 0x23d1,
+ 0xe9a1, 0x1895,
+ 0xea40, 0x1ff8,
+ 0xea41, 0x5029,
+ 0xea44, 0x23d3,
+ 0xea45, 0x502c,
+ 0xea48, 0x23d2,
+ 0xea49, 0x23d4,
+ 0xea4a, 0x1e98,
+ 0xea4b, 0x502f,
+ 0xea50, 0x1f2c,
+ 0xea51, 0x5034,
+ 0xea52, 0x23d5,
+ 0xea53, 0x5035,
+ 0xea55, 0x1e71,
+ 0xea56, 0x2691,
+ 0xea57, 0x5037,
+ 0xea59, 0x23c5,
+ 0xea5a, 0x5039,
+ 0xea80, 0x231a,
+ 0xea81, 0x505e,
+ 0xea84, 0x2114,
+ 0xea85, 0x5061,
+ 0xea87, 0x2284,
+ 0xea88, 0x5063,
+ 0xea8e, 0x221c,
+ 0xea8f, 0x5069,
+ 0xea90, 0x1e7e,
+ 0xea91, 0x204d,
+ 0xea92, 0x506a,
+ 0xea96, 0x2201,
+ 0xea97, 0x506e,
+ 0xeaa0, 0x1ed9,
+ 0xeaa1, 0x18f3,
+ 0xeb40, 0x5077,
+ 0xeb41, 0x1fb2,
+ 0xeb42, 0x5078,
+ 0xeb45, 0x2252,
+ 0xeb46, 0x507b,
+ 0xeb48, 0x1f79,
+ 0xeb49, 0x507d,
+ 0xeb53, 0x2157,
+ 0xeb54, 0x5087,
+ 0xeb55, 0x21bf,
+ 0xeb56, 0x5088,
+ 0xeb5b, 0x221f,
+ 0xeb5c, 0x508d,
+ 0xeb5d, 0x203d,
+ 0xeb5e, 0x508e,
+ 0xeb60, 0x2015,
+ 0xeb61, 0x5090,
+ 0xeb62, 0x26a5,
+ 0xeb63, 0x5091,
+ 0xeb6d, 0x2156,
+ 0xeb6e, 0x509b,
+ 0xeb70, 0x2144,
+ 0xeb71, 0x509d,
+ 0xeb72, 0x1e91,
+ 0xeb73, 0x2257,
+ 0xeb74, 0x509e,
+ 0xeb78, 0x200a,
+ 0xeb79, 0x2092,
+ 0xeb7a, 0x50a2,
+ 0xeb80, 0x50a7,
+ 0xeb85, 0x2250,
+ 0xeb86, 0x50ac,
+ 0xeb8a, 0x1ec3,
+ 0xeb8b, 0x50b0,
+ 0xeba1, 0x1951,
+ 0xec40, 0x50c6,
+ 0xec46, 0x21a8,
+ 0xec47, 0x50cc,
+ 0xec56, 0x260d,
+ 0xec57, 0x50db,
+ 0xec5a, 0x260c,
+ 0xec5b, 0x50de,
+ 0xec5c, 0x260e,
+ 0xec5d, 0x50df,
+ 0xec60, 0x2032,
+ 0xec61, 0x50e2,
+ 0xec6e, 0x260b,
+ 0xec6f, 0x50ef,
+ 0xec76, 0x22c3,
+ 0xec77, 0x50f6,
+ 0xec80, 0x50fe,
+ 0xec96, 0x1f23,
+ 0xec97, 0x5114,
+ 0xeca1, 0x19af,
+ 0xed40, 0x511e,
+ 0xed46, 0x2695,
+ 0xed47, 0x5124,
+ 0xed58, 0x265e,
+ 0xed59, 0x5135,
+ 0xed5e, 0x265d,
+ 0xed5f, 0x513a,
+ 0xed61, 0x2692,
+ 0xed62, 0x513c,
+ 0xed64, 0x265f,
+ 0xed65, 0x513e,
+ 0xed66, 0x218d,
+ 0xed67, 0x20fd,
+ 0xed68, 0x513f,
+ 0xed6e, 0x1f40,
+ 0xed6f, 0x5145,
+ 0xed74, 0x2465,
+ 0xed75, 0x514a,
+ 0xed77, 0x2467,
+ 0xed78, 0x514c,
+ 0xed79, 0x2466,
+ 0xed7a, 0x514d,
+ 0xed80, 0x5152,
+ 0xed91, 0x21c9,
+ 0xed92, 0x5163,
+ 0xed93, 0x2209,
+ 0xed94, 0x1ec9,
+ 0xed95, 0x20e9,
+ 0xed96, 0x5164,
+ 0xed97, 0x21ca,
+ 0xed98, 0x2146,
+ 0xed99, 0x25c5,
+ 0xed9a, 0x21dc,
+ 0xed9b, 0x5165,
+ 0xed9c, 0x245e,
+ 0xed9d, 0x5166,
+ 0xed9e, 0x214f,
+ 0xed9f, 0x5167,
+ 0xeda0, 0x25c6,
+ 0xeda1, 0x1a0d,
+ 0xee40, 0x25c7,
+ 0xee41, 0x2241,
+ 0xee42, 0x218a,
+ 0xee43, 0x1e2f,
+ 0xee44, 0x1edc,
+ 0xee45, 0x5168,
+ 0xee48, 0x20bf,
+ 0xee49, 0x2034,
+ 0xee4a, 0x516b,
+ 0xee4d, 0x25c9,
+ 0xee4e, 0x516e,
+ 0xee52, 0x25c8,
+ 0xee53, 0x5172,
+ 0xee55, 0x220e,
+ 0xee56, 0x5174,
+ 0xee57, 0x25cb,
+ 0xee58, 0x5175,
+ 0xee5e, 0x217d,
+ 0xee5f, 0x517b,
+ 0xee61, 0x1f7e,
+ 0xee62, 0x517d,
+ 0xee68, 0x25cc,
+ 0xee69, 0x1fc3,
+ 0xee6a, 0x5183,
+ 0xee6c, 0x20b9,
+ 0xee6d, 0x5185,
+ 0xee6e, 0x2181,
+ 0xee6f, 0x5186,
+ 0xee77, 0x1fda,
+ 0xee78, 0x518e,
+ 0xee7d, 0x2173,
+ 0xee7e, 0x1ee1,
+ 0xee80, 0x25cd,
+ 0xee81, 0x5193,
+ 0xee85, 0x25ce,
+ 0xee86, 0x21f6,
+ 0xee87, 0x5197,
+ 0xee8a, 0x224b,
+ 0xee8b, 0x25d1,
+ 0xee8c, 0x519a,
+ 0xee8d, 0x1ec0,
+ 0xee8e, 0x519b,
+ 0xee90, 0x2008,
+ 0xee91, 0x519d,
+ 0xee94, 0x25d0,
+ 0xee95, 0x51a0,
+ 0xee97, 0x25d2,
+ 0xee98, 0x51a2,
+ 0xee99, 0x1f2a,
+ 0xee9a, 0x51a3,
+ 0xee9d, 0x1e72,
+ 0xee9e, 0x25d3,
+ 0xee9f, 0x51a6,
+ 0xeea1, 0x1a6b,
+ 0xef40, 0x21be,
+ 0xef41, 0x25d4,
+ 0xef42, 0x2044,
+ 0xef43, 0x51a8,
+ 0xef44, 0x25cf,
+ 0xef45, 0x20f3,
+ 0xef46, 0x51a9,
+ 0xef4c, 0x1f00,
+ 0xef4d, 0x51af,
+ 0xef52, 0x24cc,
+ 0xef54, 0x51b4,
+ 0xef55, 0x2698,
+ 0xef56, 0x51b5,
+ 0xef57, 0x2678,
+ 0xef58, 0x51b6,
+ 0xef5a, 0x24ce,
+ 0xef5b, 0x51b8,
+ 0xef60, 0x24cf,
+ 0xef61, 0x51bd,
+ 0xef68, 0x20b8,
+ 0xef69, 0x51c4,
+ 0xef6a, 0x24d0,
+ 0xef6b, 0x51c5,
+ 0xef6c, 0x24d1,
+ 0xef6d, 0x51c6,
+ 0xef77, 0x1ef4,
+ 0xef78, 0x51d0,
+ 0xef7a, 0x239b,
+ 0xef7b, 0x51d2,
+ 0xef7c, 0x267e,
+ 0xef7d, 0x51d3,
+ 0xef80, 0x51d5,
+ 0xef82, 0x239d,
+ 0xef83, 0x239f,
+ 0xef85, 0x51d7,
+ 0xef86, 0x23a1,
+ 0xef87, 0x51d8,
+ 0xef88, 0x1ef1,
+ 0xef89, 0x51d9,
+ 0xef8b, 0x221e,
+ 0xef8c, 0x51db,
+ 0xef8d, 0x23a2,
+ 0xef8e, 0x51dc,
+ 0xef95, 0x214b,
+ 0xef96, 0x1e36,
+ 0xef97, 0x2135,
+ 0xef98, 0x51e3,
+ 0xef9c, 0x1fad,
+ 0xef9d, 0x51e7,
+ 0xef9e, 0x1e53,
+ 0xef9f, 0x51e8,
+ 0xefa1, 0x1ac9,
+ 0xf040, 0x51ea,
+ 0xf041, 0x23a3,
+ 0xf042, 0x2203,
+ 0xf043, 0x51eb,
+ 0xf044, 0x1ee7,
+ 0xf045, 0x51ec,
+ 0xf047, 0x23a4,
+ 0xf048, 0x2097,
+ 0xf049, 0x1ee4,
+ 0xf04a, 0x51ee,
+ 0xf04e, 0x2238,
+ 0xf04f, 0x51f2,
+ 0xf051, 0x23a5,
+ 0xf052, 0x51f4,
+ 0xf054, 0x1f9a,
+ 0xf055, 0x51f6,
+ 0xf057, 0x21c3,
+ 0xf058, 0x51f8,
+ 0xf05e, 0x1f2e,
+ 0xf05f, 0x51fe,
+ 0xf068, 0x239c,
+ 0xf069, 0x5207,
+ 0xf06c, 0x23a6,
+ 0xf06d, 0x520a,
+ 0xf071, 0x239e,
+ 0xf072, 0x520e,
+ 0xf073, 0x2035,
+ 0xf074, 0x23a7,
+ 0xf075, 0x520f,
+ 0xf078, 0x23a8,
+ 0xf079, 0x5212,
+ 0xf07a, 0x2075,
+ 0xf07b, 0x5213,
+ 0xf07d, 0x23a9,
+ 0xf080, 0x23ab,
+ 0xf081, 0x1feb,
+ 0xf082, 0x23ac,
+ 0xf083, 0x5215,
+ 0xf087, 0x1f6a,
+ 0xf088, 0x20f9,
+ 0xf089, 0x5219,
+ 0xf08b, 0x2666,
+ 0xf08c, 0x521b,
+ 0xf090, 0x2667,
+ 0xf091, 0x521f,
+ 0xf092, 0x1e6c,
+ 0xf093, 0x5220,
+ 0xf096, 0x23ad,
+ 0xf097, 0x5223,
+ 0xf0a1, 0x1b27,
+ 0xf140, 0x522d,
+ 0xf152, 0x206d,
+ 0xf153, 0x2242,
+ 0xf154, 0x1f02,
+ 0xf155, 0x523f,
+ 0xf157, 0x2183,
+ 0xf158, 0x5241,
+ 0xf159, 0x1e85,
+ 0xf15a, 0x21e9,
+ 0xf15b, 0x5242,
+ 0xf167, 0x1e57,
+ 0xf168, 0x524e,
+ 0xf176, 0x22a5,
+ 0xf177, 0x2407,
+ 0xf178, 0x1fca,
+ 0xf179, 0x525c,
+ 0xf17a, 0x2402,
+ 0xf17b, 0x1f82,
+ 0xf17c, 0x525d,
+ 0xf17e, 0x2408,
+ 0xf180, 0x2404,
+ 0xf181, 0x525f,
+ 0xf182, 0x2131,
+ 0xf183, 0x5260,
+ 0xf184, 0x2184,
+ 0xf185, 0x5261,
+ 0xf186, 0x2403,
+ 0xf187, 0x5262,
+ 0xf188, 0x206e,
+ 0xf189, 0x240b,
+ 0xf18a, 0x5263,
+ 0xf194, 0x1f3f,
+ 0xf195, 0x526d,
+ 0xf198, 0x2067,
+ 0xf199, 0x5270,
+ 0xf1a1, 0x1b85,
+ 0xf240, 0x5278,
+ 0xf245, 0x1fd7,
+ 0xf246, 0x527d,
+ 0xf247, 0x1e83,
+ 0xf248, 0x527e,
+ 0xf24b, 0x240f,
+ 0xf24c, 0x5281,
+ 0xf253, 0x240e,
+ 0xf254, 0x20c7,
+ 0xf255, 0x240d,
+ 0xf256, 0x5288,
+ 0xf25c, 0x2412,
+ 0xf25d, 0x528e,
+ 0xf25f, 0x20b7,
+ 0xf260, 0x5290,
+ 0xf271, 0x23f0,
+ 0xf272, 0x52a1,
+ 0xf273, 0x2411,
+ 0xf274, 0x2414,
+ 0xf275, 0x52a2,
+ 0xf276, 0x2170,
+ 0xf277, 0x52a3,
+ 0xf27c, 0x2405,
+ 0xf27d, 0x210c,
+ 0xf27e, 0x2415,
+ 0xf280, 0x52a8,
+ 0xf285, 0x2066,
+ 0xf286, 0x52ad,
+ 0xf287, 0x2352,
+ 0xf288, 0x2413,
+ 0xf289, 0x2410,
+ 0xf28a, 0x2416,
+ 0xf28c, 0x20f1,
+ 0xf28d, 0x52ae,
+ 0xf291, 0x240a,
+ 0xf292, 0x52b2,
+ 0xf294, 0x2409,
+ 0xf295, 0x52b4,
+ 0xf296, 0x2418,
+ 0xf297, 0x52b5,
+ 0xf29c, 0x1fa7,
+ 0xf29d, 0x52ba,
+ 0xf29e, 0x21fc,
+ 0xf29f, 0x52bb,
+ 0xf2a1, 0x1be3,
+ 0xf340, 0x1fc1,
+ 0xf341, 0x2406,
+ 0xf342, 0x52bd,
+ 0xf345, 0x229c,
+ 0xf346, 0x52c0,
+ 0xf348, 0x204e,
+ 0xf349, 0x52c2,
+ 0xf34a, 0x241a,
+ 0xf34b, 0x2419,
+ 0xf34c, 0x52c3,
+ 0xf350, 0x240c,
+ 0xf351, 0x52c7,
+ 0xf361, 0x1e29,
+ 0xf362, 0x52d7,
+ 0xf374, 0x2661,
+ 0xf375, 0x52e9,
+ 0xf376, 0x26a4,
+ 0xf377, 0x2174,
+ 0xf378, 0x2663,
+ 0xf379, 0x2662,
+ 0xf37a, 0x52ea,
+ 0xf380, 0x52ef,
+ 0xf38c, 0x2675,
+ 0xf38d, 0x52fb,
+ 0xf3a0, 0x214c,
+ 0xf3a1, 0x1c41,
+ 0xf440, 0x530e,
+ 0xf445, 0x267a,
+ 0xf446, 0x5313,
+ 0xf450, 0x26a0,
+ 0xf451, 0x531d,
+ 0xf457, 0x2668,
+ 0xf458, 0x5323,
+ 0xf459, 0x1ed0,
+ 0xf45a, 0x5324,
+ 0xf45b, 0x2096,
+ 0xf45c, 0x5325,
+ 0xf45d, 0x23cc,
+ 0xf45e, 0x5326,
+ 0xf462, 0x23c8,
+ 0xf463, 0x532a,
+ 0xf464, 0x223e,
+ 0xf465, 0x532b,
+ 0xf475, 0x2665,
+ 0xf476, 0x533b,
+ 0xf47c, 0x2664,
+ 0xf47d, 0x5341,
+ 0xf47e, 0x2239,
+ 0xf480, 0x5342,
+ 0xf494, 0x204a,
+ 0xf495, 0x5356,
+ 0xf499, 0x261f,
+ 0xf49a, 0x535a,
+ 0xf49c, 0x261e,
+ 0xf49d, 0x535c,
+ 0xf4a1, 0x1c9f,
+ 0xf540, 0x5360,
+ 0xf545, 0x2620,
+ 0xf546, 0x5365,
+ 0xf547, 0x2621,
+ 0xf548, 0x5366,
+ 0xf552, 0x2622,
+ 0xf553, 0x5370,
+ 0xf554, 0x2627,
+ 0xf555, 0x1e39,
+ 0xf556, 0x2625,
+ 0xf557, 0x5371,
+ 0xf55e, 0x2629,
+ 0xf55f, 0x5378,
+ 0xf561, 0x262e,
+ 0xf562, 0x262b,
+ 0xf563, 0x537a,
+ 0xf56e, 0x262a,
+ 0xf56f, 0x262d,
+ 0xf570, 0x5385,
+ 0xf571, 0x2628,
+ 0xf572, 0x21b9,
+ 0xf573, 0x5386,
+ 0xf580, 0x5392,
+ 0xf585, 0x2636,
+ 0xf586, 0x2630,
+ 0xf587, 0x5397,
+ 0xf58c, 0x2638,
+ 0xf58d, 0x539c,
+ 0xf58e, 0x200d,
+ 0xf58f, 0x2637,
+ 0xf590, 0x539d,
+ 0xf599, 0x2645,
+ 0xf59a, 0x53a6,
+ 0xf59b, 0x263a,
+ 0xf59c, 0x53a7,
+ 0xf5a0, 0x2643,
+ 0xf5a1, 0x1cfd,
+ 0xf640, 0x53ab,
+ 0xf641, 0x2640,
+ 0xf642, 0x53ac,
+ 0xf645, 0x263d,
+ 0xf646, 0x2641,
+ 0xf647, 0x53af,
+ 0xf648, 0x263e,
+ 0xf649, 0x53b0,
+ 0xf64b, 0x263f,
+ 0xf64c, 0x1fc0,
+ 0xf64d, 0x53b2,
+ 0xf64e, 0x263b,
+ 0xf650, 0x53b3,
+ 0xf654, 0x2642,
+ 0xf655, 0x53b7,
+ 0xf658, 0x2644,
+ 0xf659, 0x53ba,
+ 0xf661, 0x2639,
+ 0xf662, 0x53c2,
+ 0xf663, 0x264c,
+ 0xf664, 0x53c3,
+ 0xf66c, 0x2647,
+ 0xf66d, 0x264b,
+ 0xf66e, 0x53cb,
+ 0xf671, 0x2649,
+ 0xf672, 0x53ce,
+ 0xf674, 0x2648,
+ 0xf675, 0x53d0,
+ 0xf676, 0x264a,
+ 0xf677, 0x2108,
+ 0xf678, 0x53d1,
+ 0xf680, 0x53d8,
+ 0xf685, 0x264d,
+ 0xf686, 0x53dd,
+ 0xf688, 0x2634,
+ 0xf689, 0x53df,
+ 0xf68a, 0x2651,
+ 0xf68b, 0x53e0,
+ 0xf68d, 0x2650,
+ 0xf68e, 0x2652,
+ 0xf68f, 0x53e2,
+ 0xf692, 0x264f,
+ 0xf693, 0x53e5,
+ 0xf696, 0x2632,
+ 0xf697, 0x264e,
+ 0xf698, 0x2653,
+ 0xf699, 0x53e8,
+ 0xf69a, 0x2657,
+ 0xf69b, 0x53e9,
+ 0xf69c, 0x2635,
+ 0xf69d, 0x53ea,
+ 0xf69e, 0x2633,
+ 0xf69f, 0x53eb,
+ 0xf6a0, 0x2656,
+ 0xf6a1, 0x1d5b,
+ 0xf740, 0x53ec,
+ 0xf742, 0x2654,
+ 0xf743, 0x53ee,
+ 0xf749, 0x2658,
+ 0xf74a, 0x53f4,
+ 0xf74c, 0x2655,
+ 0xf74d, 0x1e4d,
+ 0xf74e, 0x53f6,
+ 0xf756, 0x265b,
+ 0xf757, 0x53fe,
+ 0xf758, 0x265a,
+ 0xf759, 0x53ff,
+ 0xf75a, 0x2659,
+ 0xf75b, 0x202e,
+ 0xf75c, 0x262f,
+ 0xf75d, 0x5400,
+ 0xf761, 0x2646,
+ 0xf762, 0x5404,
+ 0xf763, 0x2626,
+ 0xf764, 0x5405,
+ 0xf76b, 0x265c,
+ 0xf76c, 0x540c,
+ 0xf771, 0x262c,
+ 0xf772, 0x5411,
+ 0xf77c, 0x2623,
+ 0xf77d, 0x541b,
+ 0xf77e, 0x2631,
+ 0xf780, 0x541c,
+ 0xf7a1, 0x1db9,
+ 0xf840, 0x543d,
+ 0xf842, 0x209c,
+ 0xf843, 0x543f,
+ 0xf846, 0x2580,
+ 0xf847, 0x5442,
+ 0xf849, 0x22dc,
+ 0xf84a, 0x5444,
+ 0xf850, 0x1f05,
+ 0xf851, 0x208b,
+ 0xf852, 0x544a,
+ 0xf853, 0x2581,
+ 0xf854, 0x544b,
+ 0xf863, 0x2583,
+ 0xf864, 0x2582,
+ 0xf865, 0x545a,
+ 0xf866, 0x21ee,
+ 0xf867, 0x545b,
+ 0xf872, 0x2182,
+ 0xf873, 0x5466,
+ 0xf878, 0x2243,
+ 0xf879, 0x546b,
+ 0xf87a, 0x2587,
+ 0xf87b, 0x546c,
+ 0xf87c, 0x2588,
+ 0xf87d, 0x546d,
+ 0xf880, 0x546f,
+ 0xf881, 0x2584,
+ 0xf882, 0x5470,
+ 0xf884, 0x21fd,
+ 0xf885, 0x5472,
+ 0xf886, 0x21ef,
+ 0xf887, 0x5473,
+ 0xf88d, 0x258a,
+ 0xf88e, 0x258c,
+ 0xf88f, 0x5479,
+ 0xf899, 0x1f47,
+ 0xf89a, 0x5483,
+ 0xf89d, 0x1f1d,
+ 0xf89e, 0x5486,
+ 0xf8a0, 0x258d,
+ 0xf940, 0x5488,
+ 0xf94e, 0x1fd0,
+ 0xf94f, 0x2592,
+ 0xf950, 0x258f,
+ 0xf951, 0x5496,
+ 0xf959, 0x2594,
+ 0xf95a, 0x1ee0,
+ 0xf95b, 0x549e,
+ 0xf95d, 0x2591,
+ 0xf95e, 0x2595,
+ 0xf95f, 0x54a0,
+ 0xf967, 0x2597,
+ 0xf968, 0x54a8,
+ 0xf969, 0x20b6,
+ 0xf96a, 0x54a9,
+ 0xf96c, 0x2598,
+ 0xf96d, 0x54ab,
+ 0xf96f, 0x20f6,
+ 0xf970, 0x54ad,
+ 0xf980, 0x54bc,
+ 0xf985, 0x2585,
+ 0xf986, 0x54c1,
+ 0xf987, 0x2599,
+ 0xf988, 0x54c2,
+ 0xf991, 0x2596,
+ 0xf992, 0x54cb,
+ 0xf996, 0x259a,
+ 0xf997, 0x54cf,
+ 0xf998, 0x259b,
+ 0xf999, 0x54d0,
+ 0xfa40, 0x54d8,
+ 0xfa42, 0x259d,
+ 0xfa43, 0x54da,
+ 0xfa46, 0x259e,
+ 0xfa47, 0x54dd,
+ 0xfa4c, 0x234c,
+ 0xfa4d, 0x54e2,
+ 0xfa51, 0x1f44,
+ 0xfa52, 0x54e6,
+ 0xfa58, 0x2660,
+ 0xfa59, 0x25a0,
+ 0xfa5a, 0x54ec,
+ 0xfa5d, 0x259c,
+ 0xfa5e, 0x54ef,
+ 0xfa5f, 0x259f,
+ 0xfa60, 0x54f0,
+ 0xfa61, 0x1f6c,
+ 0xfa62, 0x54f1,
+ 0xfa70, 0x25a2,
+ 0xfa71, 0x54ff,
+ 0xfa74, 0x20ae,
+ 0xfa75, 0x5502,
+ 0xfa76, 0x258b,
+ 0xfa77, 0x25a3,
+ 0xfa78, 0x5503,
+ 0xfa80, 0x550a,
+ 0xfa83, 0x2589,
+ 0xfa84, 0x25a5,
+ 0xfa85, 0x550d,
+ 0xfa8d, 0x25a4,
+ 0xfa8e, 0x5515,
+ 0xfa90, 0x25a6,
+ 0xfa91, 0x2593,
+ 0xfa92, 0x5517,
+ 0xfa96, 0x25a7,
+ 0xfa97, 0x2222,
+ 0xfa98, 0x25a9,
+ 0xfa99, 0x551b,
+ 0xfb40, 0x5523,
+ 0xfb49, 0x25a8,
+ 0xfb4a, 0x552c,
+ 0xfb52, 0x2586,
+ 0xfb53, 0x5534,
+ 0xfb57, 0x25a1,
+ 0xfb58, 0x25aa,
+ 0xfb59, 0x5538,
+ 0xfb5a, 0x2590,
+ 0xfb5b, 0x258e,
+ 0xfb5c, 0x5539,
+ 0xfb75, 0x2688,
+ 0xfb76, 0x5552,
+ 0xfb79, 0x269e,
+ 0xfb7a, 0x25fb,
+ 0xfb7b, 0x5555,
+ 0xfb7c, 0x1f8c,
+ 0xfb7d, 0x21f4,
+ 0xfb7e, 0x5556,
+ 0xfb80, 0x5557,
+ 0xfb90, 0x200f,
+ 0xfb91, 0x5567,
+ 0xfb9c, 0x2071,
+ 0xfb9d, 0x5572,
+ 0xfb9f, 0x25f7,
+ 0xfba0, 0x5574,
+ 0xfc40, 0x5575,
+ 0xfc44, 0x2696,
+ 0xfc45, 0x5579,
+ 0xfc49, 0x268f,
+ 0xfc4a, 0x557d,
+ 0xfc5a, 0x22da,
+ 0xfc5b, 0x558d,
+ 0xfc63, 0x1ec1,
+ 0xfc64, 0x5595,
+ 0xfc68, 0x1eb3,
+ 0xfc69, 0x5599,
+ 0xfc6f, 0x266a,
+ 0xfc70, 0x559f,
+ 0xfc71, 0x268a,
+ 0xfc72, 0x55a0,
+ 0xfc74, 0x2669,
+ 0xfc75, 0x55a2,
+ 0xfc77, 0x2618,
+ 0xfc79, 0x55a4,
+ 0xfc80, 0x55aa,
+ 0xfc83, 0x261a,
+ 0xfc84, 0x55ad,
+ 0xfc8a, 0x2673,
+ 0xfc8b, 0x55b3,
+ 0xfd40, 0x55c9,
+ 0xfd52, 0x20c6,
+ 0xfd53, 0x226b,
+ 0xfd54, 0x55db,
+ 0xfd57, 0x24d3,
+ 0xfd58, 0x1e86,
+ 0xfd59, 0x55de,
+ 0xfd5a, 0x260f,
+ 0xfd5b, 0x55df,
+ 0xfd5f, 0x2611,
+ 0xfd60, 0x55e3,
+ 0xfd62, 0x2613,
+ 0xfd63, 0x55e5,
+ 0xfd65, 0x2610,
+ 0xfd66, 0x2612,
+ 0xfd67, 0x2030,
+ 0xfd68, 0x55e7,
+ 0xfd69, 0x2671,
+ 0xfd6a, 0x55e8,
+ 0xfd6c, 0x2614,
+ 0xfd6d, 0x55ea,
+ 0xfd70, 0x2616,
+ 0xfd71, 0x55ed,
+ 0xfd72, 0x2615,
+ 0xfd73, 0x55ee,
+ 0xfd78, 0x20f2,
+ 0xfd79, 0x55f3,
+ 0xfd7d, 0x2617,
+ 0xfd7e, 0x55f7,
+ 0xfd80, 0x55f8,
+ 0xfd88, 0x2037,
+ 0xfd89, 0x5600,
+ 0xfd8b, 0x20b3,
+ 0xfd8c, 0x5602,
+ 0xfd8f, 0x1f22,
+ 0xfd90, 0x24ed,
+ 0xfd91, 0x5605,
+ 0xfd94, 0x1f34,
+ 0xfd95, 0x5608,
+ 0xfd9d, 0x0a02,
+ 0xfd9e, 0x40d3,
+ 0xfd9f, 0x200c,
+ 0xfda0, 0x5083,
+ 0xfe40, 0x1259,
+ 0xfe41, 0x5610,
+ 0xfe80, 0x564e,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBKEUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBKEUCHMap2, 4071
+};
+
+static Gushort gb12GBKEUCVMap2[8182] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x2758,
+ 0x8179, 0x2059,
+ 0x817a, 0x2791,
+ 0x8180, 0x2796,
+ 0x8186, 0x21f1,
+ 0x8187, 0x279c,
+ 0x81ed, 0x1ff2,
+ 0x81ee, 0x2802,
+ 0x81f6, 0x205d,
+ 0x81f7, 0x280a,
+ 0x8240, 0x2812,
+ 0x8253, 0x269c,
+ 0x8254, 0x2825,
+ 0x8262, 0x21b5,
+ 0x8263, 0x2833,
+ 0x8274, 0x22cc,
+ 0x8275, 0x2844,
+ 0x827a, 0x2016,
+ 0x827b, 0x2849,
+ 0x827d, 0x1e62,
+ 0x827e, 0x284b,
+ 0x8280, 0x1f20,
+ 0x8281, 0x284c,
+ 0x8283, 0x207f,
+ 0x8284, 0x284e,
+ 0x8290, 0x205c,
+ 0x8291, 0x285a,
+ 0x82a5, 0x2194,
+ 0x82a6, 0x286e,
+ 0x82c8, 0x1e65,
+ 0x82c9, 0x2281,
+ 0x82ca, 0x2890,
+ 0x82e1, 0x22cd,
+ 0x82e2, 0x28a7,
+ 0x82e3, 0x210a,
+ 0x82e4, 0x1e3e,
+ 0x82e5, 0x28a8,
+ 0x82ed, 0x267f,
+ 0x82ee, 0x28b0,
+ 0x82f2, 0x222e,
+ 0x82f3, 0x28b4,
+ 0x82f7, 0x1e96,
+ 0x82f8, 0x22cb,
+ 0x82f9, 0x226c,
+ 0x82fa, 0x28b8,
+ 0x82fb, 0x2117,
+ 0x82fc, 0x28b9,
+ 0x8340, 0x28bc,
+ 0x8341, 0x20e8,
+ 0x8342, 0x28bd,
+ 0x8345, 0x22d4,
+ 0x8346, 0x28c0,
+ 0x8348, 0x1fb9,
+ 0x8349, 0x28c2,
+ 0x834c, 0x22d8,
+ 0x834d, 0x28c5,
+ 0x8353, 0x20df,
+ 0x8354, 0x28cb,
+ 0x8357, 0x20c2,
+ 0x8358, 0x28ce,
+ 0x835e, 0x2195,
+ 0x835f, 0x28d4,
+ 0x8365, 0x1fac,
+ 0x8366, 0x22d3,
+ 0x8367, 0x28da,
+ 0x8372, 0x1f81,
+ 0x8373, 0x28e5,
+ 0x8378, 0x2210,
+ 0x8379, 0x28ea,
+ 0x837a, 0x22cf,
+ 0x837b, 0x28eb,
+ 0x837c, 0x2213,
+ 0x837d, 0x28ec,
+ 0x837e, 0x1fe4,
+ 0x8380, 0x1f90,
+ 0x8381, 0x28ed,
+ 0x8386, 0x22d6,
+ 0x8387, 0x28f2,
+ 0x8389, 0x22d0,
+ 0x838a, 0x22ce,
+ 0x838b, 0x28f4,
+ 0x838d, 0x2681,
+ 0x838e, 0x28f6,
+ 0x8394, 0x1e76,
+ 0x8395, 0x28fc,
+ 0x839e, 0x2231,
+ 0x839f, 0x2905,
+ 0x83a6, 0x1e93,
+ 0x83a7, 0x290c,
+ 0x83ab, 0x22d2,
+ 0x83ac, 0x2910,
+ 0x83ae, 0x22d7,
+ 0x83af, 0x22d5,
+ 0x83b0, 0x22d1,
+ 0x83b1, 0x2912,
+ 0x83ba, 0x1ee5,
+ 0x83bb, 0x291b,
+ 0x83c9, 0x2025,
+ 0x83ca, 0x2929,
+ 0x83f6, 0x1ecf,
+ 0x83f7, 0x2955,
+ 0x8440, 0x295d,
+ 0x8450, 0x1fd9,
+ 0x8451, 0x296d,
+ 0x8471, 0x22c8,
+ 0x8472, 0x298d,
+ 0x8474, 0x2263,
+ 0x8475, 0x298f,
+ 0x8477, 0x2683,
+ 0x8478, 0x2991,
+ 0x8480, 0x2998,
+ 0x8482, 0x1f17,
+ 0x8483, 0x299a,
+ 0x848e, 0x1f2b,
+ 0x848f, 0x29a5,
+ 0x8492, 0x22ca,
+ 0x8493, 0x1e99,
+ 0x8494, 0x29a8,
+ 0x849d, 0x1f4f,
+ 0x849e, 0x29b1,
+ 0x84a1, 0x1fcf,
+ 0x84a2, 0x2036,
+ 0x84a3, 0x1f3a,
+ 0x84a4, 0x29b4,
+ 0x84a5, 0x22c9,
+ 0x84a6, 0x1f99,
+ 0x84a7, 0x29b5,
+ 0x84a9, 0x1f75,
+ 0x84aa, 0x29b7,
+ 0x84c5, 0x1fbe,
+ 0x84c6, 0x29d2,
+ 0x84d3, 0x1ecd,
+ 0x84d4, 0x29df,
+ 0x84d5, 0x21a9,
+ 0x84d6, 0x29e0,
+ 0x84d7, 0x21e6,
+ 0x84d8, 0x29e1,
+ 0x84d9, 0x2127,
+ 0x84da, 0x2003,
+ 0x84db, 0x29e2,
+ 0x84dd, 0x2132,
+ 0x84de, 0x29e4,
+ 0x84ea, 0x2323,
+ 0x84eb, 0x29f0,
+ 0x84ee, 0x2011,
+ 0x84ef, 0x29f3,
+ 0x84f1, 0x20f5,
+ 0x84f2, 0x29f5,
+ 0x8540, 0x2a02,
+ 0x8551, 0x22c5,
+ 0x8552, 0x1f5e,
+ 0x8553, 0x2a13,
+ 0x8554, 0x22c6,
+ 0x8555, 0x2a14,
+ 0x855e, 0x20ef,
+ 0x855f, 0x2a1d,
+ 0x8566, 0x21d0,
+ 0x8567, 0x2a24,
+ 0x8580, 0x2a3c,
+ 0x8587, 0x22c1,
+ 0x8588, 0x2a43,
+ 0x858b, 0x1e64,
+ 0x858c, 0x2a46,
+ 0x8592, 0x21f9,
+ 0x8593, 0x2a4c,
+ 0x8596, 0x2010,
+ 0x8597, 0x2a4f,
+ 0x8598, 0x22c2,
+ 0x8599, 0x2a50,
+ 0x85a2, 0x1e5a,
+ 0x85a3, 0x2a59,
+ 0x85b2, 0x1ea2,
+ 0x85b3, 0x2a68,
+ 0x8640, 0x2ab4,
+ 0x864a, 0x236d,
+ 0x864b, 0x2abe,
+ 0x8654, 0x2247,
+ 0x8655, 0x2ac7,
+ 0x8668, 0x236c,
+ 0x8669, 0x2ada,
+ 0x8680, 0x2af0,
+ 0x8696, 0x219c,
+ 0x8697, 0x2b06,
+ 0x8699, 0x20c9,
+ 0x869a, 0x2b08,
+ 0x86a1, 0x21f0,
+ 0x86a2, 0x2b0f,
+ 0x86ca, 0x210b,
+ 0x86cb, 0x2b37,
+ 0x86cc, 0x20de,
+ 0x86cd, 0x2b38,
+ 0x86ce, 0x1eaa,
+ 0x86cf, 0x2b39,
+ 0x86d1, 0x222c,
+ 0x86d2, 0x2b3b,
+ 0x86dc, 0x20d8,
+ 0x86dd, 0x22c0,
+ 0x86de, 0x2b45,
+ 0x86e1, 0x206f,
+ 0x86e2, 0x2b48,
+ 0x86e8, 0x21a1,
+ 0x86e9, 0x2b4e,
+ 0x86ee, 0x2379,
+ 0x86ef, 0x2b53,
+ 0x86f4, 0x2372,
+ 0x86f5, 0x2b58,
+ 0x8740, 0x216a,
+ 0x8741, 0x2b62,
+ 0x8744, 0x237c,
+ 0x8745, 0x2b65,
+ 0x8749, 0x20b0,
+ 0x874a, 0x2b69,
+ 0x874b, 0x237a,
+ 0x874c, 0x1e74,
+ 0x874d, 0x2b6a,
+ 0x874f, 0x2377,
+ 0x8750, 0x2b6c,
+ 0x8757, 0x1f4c,
+ 0x8758, 0x2b73,
+ 0x875a, 0x2378,
+ 0x875b, 0x21cf,
+ 0x875c, 0x2368,
+ 0x875d, 0x2b75,
+ 0x875e, 0x2371,
+ 0x875f, 0x2b76,
+ 0x8760, 0x2369,
+ 0x8761, 0x2b77,
+ 0x8766, 0x2674,
+ 0x8767, 0x2b7c,
+ 0x877a, 0x236f,
+ 0x877b, 0x2b8f,
+ 0x877d, 0x2370,
+ 0x877e, 0x2b91,
+ 0x8780, 0x2b92,
+ 0x8781, 0x2376,
+ 0x8782, 0x2373,
+ 0x8783, 0x2b93,
+ 0x8786, 0x237f,
+ 0x8787, 0x2b96,
+ 0x8788, 0x2374,
+ 0x8789, 0x2b97,
+ 0x878a, 0x20b5,
+ 0x878b, 0x2b98,
+ 0x878d, 0x1edb,
+ 0x878e, 0x2672,
+ 0x878f, 0x2b9a,
+ 0x8793, 0x236e,
+ 0x8794, 0x2b9e,
+ 0x8798, 0x21b7,
+ 0x8799, 0x2ba2,
+ 0x879d, 0x2375,
+ 0x879e, 0x2ba6,
+ 0x87a3, 0x2382,
+ 0x87a4, 0x2bab,
+ 0x87a7, 0x209e,
+ 0x87a8, 0x2bae,
+ 0x87b3, 0x236b,
+ 0x87b4, 0x2bb9,
+ 0x87b5, 0x2039,
+ 0x87b6, 0x2bba,
+ 0x87bb, 0x269f,
+ 0x87bc, 0x2bbf,
+ 0x87bf, 0x237d,
+ 0x87c0, 0x21f5,
+ 0x87c1, 0x2bc2,
+ 0x87c2, 0x2381,
+ 0x87c3, 0x2bc3,
+ 0x87ca, 0x237b,
+ 0x87cb, 0x237e,
+ 0x87cc, 0x21cc,
+ 0x87cd, 0x2bca,
+ 0x87cf, 0x22db,
+ 0x87d0, 0x2bcc,
+ 0x87d2, 0x236a,
+ 0x87d3, 0x2689,
+ 0x87d4, 0x2bce,
+ 0x87d5, 0x2697,
+ 0x87d6, 0x2bcf,
+ 0x87da, 0x22a1,
+ 0x87db, 0x2bd3,
+ 0x87f7, 0x2383,
+ 0x87f8, 0x1f3d,
+ 0x87f9, 0x2bef,
+ 0x87fa, 0x218f,
+ 0x87fb, 0x2bf0,
+ 0x8840, 0x2246,
+ 0x8841, 0x2248,
+ 0x8842, 0x2bf4,
+ 0x8844, 0x217e,
+ 0x8845, 0x2bf6,
+ 0x8846, 0x2180,
+ 0x8847, 0x2bf7,
+ 0x8880, 0x2c2f,
+ 0x88ba, 0x232a,
+ 0x88bb, 0x2c69,
+ 0x88cc, 0x228b,
+ 0x88cd, 0x2c7a,
+ 0x88d4, 0x1f85,
+ 0x88d5, 0x2c81,
+ 0x88d7, 0x2325,
+ 0x88d8, 0x2c83,
+ 0x88df, 0x232c,
+ 0x88e0, 0x2c8a,
+ 0x88e5, 0x232e,
+ 0x88e6, 0x2c8f,
+ 0x88f2, 0x2205,
+ 0x88f3, 0x1e38,
+ 0x88f4, 0x2c9b,
+ 0x88f6, 0x1e73,
+ 0x88f7, 0x2c9d,
+ 0x8940, 0x2ca5,
+ 0x894b, 0x1fe3,
+ 0x894c, 0x2339,
+ 0x894d, 0x2cb0,
+ 0x894e, 0x232b,
+ 0x894f, 0x2cb1,
+ 0x8950, 0x232d,
+ 0x8951, 0x2cb2,
+ 0x8954, 0x217f,
+ 0x8955, 0x2cb5,
+ 0x895d, 0x21a7,
+ 0x895e, 0x2cbd,
+ 0x895f, 0x232f,
+ 0x8960, 0x2cbe,
+ 0x896d, 0x1e7d,
+ 0x896e, 0x2ccb,
+ 0x8971, 0x20d6,
+ 0x8972, 0x2cce,
+ 0x897c, 0x1ec2,
+ 0x897d, 0x2cd8,
+ 0x8980, 0x2cda,
+ 0x898b, 0x22b2,
+ 0x898c, 0x2ce5,
+ 0x8999, 0x1edf,
+ 0x899a, 0x2cf2,
+ 0x899e, 0x1ef9,
+ 0x899f, 0x2cf6,
+ 0x89a6, 0x20d9,
+ 0x89a7, 0x2cfd,
+ 0x89a8, 0x1fdd,
+ 0x89a9, 0x2cfe,
+ 0x89af, 0x2167,
+ 0x89b0, 0x2d04,
+ 0x89ba, 0x21ed,
+ 0x89bb, 0x2d0e,
+ 0x89be, 0x2007,
+ 0x89bf, 0x2326,
+ 0x89c0, 0x2329,
+ 0x89c1, 0x2d11,
+ 0x89c4, 0x1f52,
+ 0x89c5, 0x203b,
+ 0x89c6, 0x2328,
+ 0x89c7, 0x2d14,
+ 0x89c8, 0x2327,
+ 0x89c9, 0x2d15,
+ 0x89ce, 0x1e2b,
+ 0x89cf, 0x2d1a,
+ 0x89d1, 0x22ae,
+ 0x89d2, 0x2d1c,
+ 0x89d8, 0x1f49,
+ 0x89d9, 0x2d22,
+ 0x89db, 0x2138,
+ 0x89dc, 0x2d24,
+ 0x89f4, 0x2081,
+ 0x89f5, 0x2d3c,
+ 0x8a40, 0x2d46,
+ 0x8a41, 0x1f7c,
+ 0x8a42, 0x2d47,
+ 0x8a59, 0x235b,
+ 0x8a5a, 0x1ede,
+ 0x8a5b, 0x2d5e,
+ 0x8a5c, 0x1fa2,
+ 0x8a5d, 0x2d5f,
+ 0x8a5e, 0x1efa,
+ 0x8a5f, 0x2d60,
+ 0x8a79, 0x22ad,
+ 0x8a7a, 0x2d7a,
+ 0x8a80, 0x2d7f,
+ 0x8ae4, 0x203f,
+ 0x8ae5, 0x2de3,
+ 0x8b40, 0x2dfd,
+ 0x8b44, 0x1f0e,
+ 0x8b45, 0x2e01,
+ 0x8b49, 0x23f9,
+ 0x8b4a, 0x2e05,
+ 0x8b7a, 0x23fc,
+ 0x8b7b, 0x2e35,
+ 0x8b80, 0x2e39,
+ 0x8b8c, 0x2069,
+ 0x8b8d, 0x2e45,
+ 0x8b9e, 0x23f7,
+ 0x8b9f, 0x2e56,
+ 0x8bb3, 0x23f6,
+ 0x8bb4, 0x2e6a,
+ 0x8bb9, 0x23fd,
+ 0x8bba, 0x2e6f,
+ 0x8bbe, 0x23f8,
+ 0x8bbf, 0x2e73,
+ 0x8bc6, 0x23fa,
+ 0x8bc7, 0x2e7a,
+ 0x8bc8, 0x23fe,
+ 0x8bc9, 0x1fa8,
+ 0x8bca, 0x2e7b,
+ 0x8bd4, 0x2401,
+ 0x8bd5, 0x2e85,
+ 0x8bdc, 0x23ff,
+ 0x8bdd, 0x2e8c,
+ 0x8be5, 0x2400,
+ 0x8be6, 0x2e94,
+ 0x8beb, 0x2221,
+ 0x8bec, 0x2e99,
+ 0x8bf0, 0x2122,
+ 0x8bf1, 0x2e9d,
+ 0x8c40, 0x2eab,
+ 0x8c44, 0x23fb,
+ 0x8c45, 0x2eaf,
+ 0x8c4f, 0x215a,
+ 0x8c50, 0x2eb9,
+ 0x8c57, 0x21e5,
+ 0x8c58, 0x2ec0,
+ 0x8c5c, 0x2057,
+ 0x8c5d, 0x2ec4,
+ 0x8c80, 0x2ee6,
+ 0x8c8b, 0x20e5,
+ 0x8c8c, 0x2ef1,
+ 0x8c8d, 0x212f,
+ 0x8c8e, 0x20a3,
+ 0x8c8f, 0x2121,
+ 0x8c90, 0x2ef2,
+ 0x8c91, 0x21d4,
+ 0x8c92, 0x1fe5,
+ 0x8c93, 0x2ef3,
+ 0x8c99, 0x1e8a,
+ 0x8c9a, 0x1e37,
+ 0x8c9b, 0x2ef9,
+ 0x8ca2, 0x1f9e,
+ 0x8ca3, 0x22a6,
+ 0x8ca4, 0x21e8,
+ 0x8ca5, 0x2f00,
+ 0x8ca6, 0x1eda,
+ 0x8ca7, 0x1eb9,
+ 0x8ca8, 0x2f01,
+ 0x8cc0, 0x235c,
+ 0x8cc1, 0x2f19,
+ 0x8cd2, 0x2050,
+ 0x8cd3, 0x1e67,
+ 0x8cd4, 0x2f2a,
+ 0x8cd5, 0x23f4,
+ 0x8cd6, 0x2f2b,
+ 0x8cd9, 0x213e,
+ 0x8cda, 0x2f2e,
+ 0x8cf9, 0x1f16,
+ 0x8cfa, 0x2f4d,
+ 0x8d40, 0x2f52,
+ 0x8d73, 0x2389,
+ 0x8d74, 0x2f85,
+ 0x8d75, 0x1eb7,
+ 0x8d76, 0x2f86,
+ 0x8d7b, 0x21b4,
+ 0x8d7c, 0x2f8b,
+ 0x8d80, 0x2f8e,
+ 0x8d88, 0x238f,
+ 0x8d89, 0x2f96,
+ 0x8d8f, 0x1f1a,
+ 0x8d90, 0x2f9c,
+ 0x8d9e, 0x238b,
+ 0x8d9f, 0x2faa,
+ 0x8db9, 0x238a,
+ 0x8dba, 0x2fc4,
+ 0x8de2, 0x2391,
+ 0x8de3, 0x2fec,
+ 0x8de4, 0x2271,
+ 0x8de5, 0x2fed,
+ 0x8de7, 0x2388,
+ 0x8de8, 0x2fef,
+ 0x8df7, 0x238e,
+ 0x8df8, 0x2ffe,
+ 0x8dfe, 0x238d,
+ 0x8e40, 0x3004,
+ 0x8e46, 0x238c,
+ 0x8e47, 0x300a,
+ 0x8e56, 0x2390,
+ 0x8e57, 0x3019,
+ 0x8e58, 0x2033,
+ 0x8e59, 0x301a,
+ 0x8e5a, 0x223c,
+ 0x8e5b, 0x301b,
+ 0x8e68, 0x1fe9,
+ 0x8e69, 0x3028,
+ 0x8e6e, 0x2055,
+ 0x8e6f, 0x302d,
+ 0x8e70, 0x2392,
+ 0x8e71, 0x302e,
+ 0x8e80, 0x2324,
+ 0x8e81, 0x303c,
+ 0x8e9b, 0x2143,
+ 0x8e9c, 0x3056,
+ 0x8e9f, 0x2129,
+ 0x8ea0, 0x3059,
+ 0x8ea4, 0x2277,
+ 0x8ea5, 0x305d,
+ 0x8ea7, 0x1ea7,
+ 0x8ea8, 0x305f,
+ 0x8eac, 0x2285,
+ 0x8ead, 0x3063,
+ 0x8eae, 0x2384,
+ 0x8eaf, 0x3064,
+ 0x8ebd, 0x2387,
+ 0x8ebe, 0x2386,
+ 0x8ebf, 0x3072,
+ 0x8ec3, 0x2290,
+ 0x8ec4, 0x3076,
+ 0x8ec5, 0x1e44,
+ 0x8ec6, 0x3077,
+ 0x8ecd, 0x1e32,
+ 0x8ece, 0x2385,
+ 0x8ecf, 0x307e,
+ 0x8ed6, 0x1f13,
+ 0x8ed7, 0x1f73,
+ 0x8ed8, 0x3085,
+ 0x8eec, 0x1fe0,
+ 0x8eed, 0x3099,
+ 0x8f40, 0x30ab,
+ 0x8f52, 0x2087,
+ 0x8f53, 0x1e78,
+ 0x8f54, 0x23ae,
+ 0x8f55, 0x1ef6,
+ 0x8f56, 0x1f31,
+ 0x8f57, 0x30bd,
+ 0x8f5d, 0x2045,
+ 0x8f5e, 0x30c3,
+ 0x8f64, 0x2178,
+ 0x8f65, 0x30c9,
+ 0x8f80, 0x30e3,
+ 0x8f86, 0x23f5,
+ 0x8f87, 0x30e9,
+ 0x8f88, 0x2275,
+ 0x8f89, 0x30ea,
+ 0x8f95, 0x266e,
+ 0x8f96, 0x30f6,
+ 0x8f97, 0x1eb0,
+ 0x8f98, 0x30f7,
+ 0x8f9b, 0x2083,
+ 0x8f9c, 0x30fa,
+ 0x8f9d, 0x2188,
+ 0x8f9e, 0x30fb,
+ 0x8fa1, 0x267c,
+ 0x8fa2, 0x30fe,
+ 0x8fbd, 0x1fc5,
+ 0x8fbe, 0x3119,
+ 0x8fc4, 0x1ea1,
+ 0x8fc5, 0x311f,
+ 0x8fc6, 0x2393,
+ 0x8fc7, 0x3120,
+ 0x8fcd, 0x1f0b,
+ 0x8fce, 0x3126,
+ 0x8fd8, 0x1e7c,
+ 0x8fd9, 0x3130,
+ 0x9040, 0x3156,
+ 0x9080, 0x3195,
+ 0x909d, 0x23b4,
+ 0x909e, 0x207e,
+ 0x909f, 0x31b2,
+ 0x90ba, 0x1ee3,
+ 0x90bb, 0x31cd,
+ 0x90c0, 0x2095,
+ 0x90c1, 0x23bb,
+ 0x90c2, 0x31d2,
+ 0x90c5, 0x23b9,
+ 0x90c6, 0x31d5,
+ 0x90db, 0x1e28,
+ 0x90dc, 0x23bd,
+ 0x90dd, 0x31ea,
+ 0x90ed, 0x23b5,
+ 0x90ee, 0x31fa,
+ 0x90f0, 0x23ba,
+ 0x90f1, 0x31fc,
+ 0x90f7, 0x23b3,
+ 0x90f8, 0x3202,
+ 0x9140, 0x3209,
+ 0x9142, 0x2162,
+ 0x9143, 0x320b,
+ 0x914b, 0x1e5e,
+ 0x914c, 0x3213,
+ 0x914d, 0x1e5d,
+ 0x914e, 0x3214,
+ 0x9151, 0x23b7,
+ 0x9152, 0x3217,
+ 0x9154, 0x1f2f,
+ 0x9155, 0x24df,
+ 0x9156, 0x3219,
+ 0x9159, 0x23b2,
+ 0x915a, 0x214e,
+ 0x915b, 0x321c,
+ 0x915d, 0x2052,
+ 0x915e, 0x321e,
+ 0x9161, 0x23bc,
+ 0x9162, 0x3221,
+ 0x9163, 0x20eb,
+ 0x9164, 0x3222,
+ 0x916e, 0x2232,
+ 0x916f, 0x322c,
+ 0x9176, 0x1e3f,
+ 0x9177, 0x3233,
+ 0x917a, 0x201b,
+ 0x917b, 0x20bc,
+ 0x917c, 0x23be,
+ 0x917d, 0x3236,
+ 0x9180, 0x3238,
+ 0x9184, 0x1eae,
+ 0x9185, 0x323c,
+ 0x918d, 0x1efb,
+ 0x918e, 0x3244,
+ 0x9191, 0x2089,
+ 0x9192, 0x3247,
+ 0x9193, 0x23b1,
+ 0x9194, 0x3248,
+ 0x9197, 0x21c4,
+ 0x9198, 0x324b,
+ 0x919b, 0x2214,
+ 0x919c, 0x324e,
+ 0x91a9, 0x1fde,
+ 0x91aa, 0x2223,
+ 0x91ab, 0x23b6,
+ 0x91ac, 0x325b,
+ 0x91ba, 0x268c,
+ 0x91bb, 0x24de,
+ 0x91bc, 0x3269,
+ 0x91bf, 0x24e0,
+ 0x91c0, 0x326c,
+ 0x91c3, 0x23b8,
+ 0x91c4, 0x326f,
+ 0x91cd, 0x1e81,
+ 0x91ce, 0x3278,
+ 0x91d0, 0x1ffe,
+ 0x91d1, 0x1f51,
+ 0x91d2, 0x21e1,
+ 0x91d3, 0x327a,
+ 0x91d4, 0x23b0,
+ 0x91d5, 0x327b,
+ 0x91d6, 0x1fce,
+ 0x91d7, 0x327c,
+ 0x91d8, 0x211e,
+ 0x91d9, 0x2021,
+ 0x91da, 0x327d,
+ 0x91df, 0x24e1,
+ 0x91e0, 0x3282,
+ 0x91e2, 0x24a3,
+ 0x91e3, 0x3284,
+ 0x91ea, 0x24a4,
+ 0x91eb, 0x328b,
+ 0x91f0, 0x2273,
+ 0x91f1, 0x3290,
+ 0x91f2, 0x21b0,
+ 0x91f3, 0x3291,
+ 0x9240, 0x329d,
+ 0x9280, 0x32dc,
+ 0x92b6, 0x21d1,
+ 0x92b7, 0x3312,
+ 0x92ce, 0x211c,
+ 0x92cf, 0x3329,
+ 0x92d0, 0x235d,
+ 0x92d1, 0x332a,
+ 0x92d4, 0x2682,
+ 0x92d5, 0x332d,
+ 0x92df, 0x210d,
+ 0x92e0, 0x205a,
+ 0x92e1, 0x3337,
+ 0x92fe, 0x1f8d,
+ 0x9340, 0x3354,
+ 0x9350, 0x21ff,
+ 0x9351, 0x3364,
+ 0x935d, 0x1f58,
+ 0x935e, 0x3370,
+ 0x9370, 0x215b,
+ 0x9371, 0x3382,
+ 0x9376, 0x1eb6,
+ 0x9377, 0x3387,
+ 0x9380, 0x338f,
+ 0x938c, 0x20db,
+ 0x938d, 0x339b,
+ 0x939d, 0x2360,
+ 0x939e, 0x33ab,
+ 0x93a5, 0x2361,
+ 0x93a6, 0x33b2,
+ 0x93a7, 0x2040,
+ 0x93a8, 0x33b3,
+ 0x93b4, 0x228e,
+ 0x93b5, 0x33bf,
+ 0x93b8, 0x1fdf,
+ 0x93b9, 0x33c2,
+ 0x93bb, 0x235e,
+ 0x93bc, 0x33c4,
+ 0x93bd, 0x1e6a,
+ 0x93be, 0x33c5,
+ 0x93c6, 0x2002,
+ 0x93c7, 0x33cd,
+ 0x93cf, 0x2093,
+ 0x93d0, 0x33d5,
+ 0x93d7, 0x235f,
+ 0x93d8, 0x33dc,
+ 0x93db, 0x1eac,
+ 0x93dc, 0x1e54,
+ 0x93dd, 0x33df,
+ 0x93e1, 0x1f08,
+ 0x93e2, 0x33e3,
+ 0x93e4, 0x20c0,
+ 0x93e5, 0x2362,
+ 0x93e6, 0x33e5,
+ 0x93e9, 0x2160,
+ 0x93ea, 0x33e8,
+ 0x93eb, 0x219d,
+ 0x93ec, 0x1f8e,
+ 0x93ed, 0x222d,
+ 0x93ee, 0x33e9,
+ 0x93ef, 0x2047,
+ 0x93f0, 0x33ea,
+ 0x93f1, 0x2262,
+ 0x93f2, 0x33eb,
+ 0x93f4, 0x1f67,
+ 0x93f5, 0x1eb2,
+ 0x93f6, 0x33ed,
+ 0x93fa, 0x1ea9,
+ 0x93fb, 0x33f1,
+ 0x93fe, 0x1fcc,
+ 0x9440, 0x33f4,
+ 0x9444, 0x1f72,
+ 0x9445, 0x33f8,
+ 0x944d, 0x2098,
+ 0x944e, 0x3400,
+ 0x9450, 0x1e52,
+ 0x9451, 0x20a4,
+ 0x9452, 0x1f1c,
+ 0x9453, 0x228f,
+ 0x9454, 0x3402,
+ 0x9455, 0x1fed,
+ 0x9456, 0x3403,
+ 0x9458, 0x2365,
+ 0x9459, 0x3405,
+ 0x945b, 0x1e2d,
+ 0x945c, 0x2152,
+ 0x945d, 0x2366,
+ 0x945e, 0x3407,
+ 0x945f, 0x20fa,
+ 0x9460, 0x3408,
+ 0x9464, 0x2363,
+ 0x9465, 0x340c,
+ 0x9466, 0x209a,
+ 0x9467, 0x340d,
+ 0x946e, 0x203c,
+ 0x946f, 0x3414,
+ 0x9472, 0x1ff6,
+ 0x9473, 0x3417,
+ 0x9474, 0x2364,
+ 0x9475, 0x3418,
+ 0x9476, 0x1e69,
+ 0x9477, 0x3419,
+ 0x9478, 0x2367,
+ 0x9479, 0x341a,
+ 0x947a, 0x211d,
+ 0x947b, 0x341b,
+ 0x9480, 0x2259,
+ 0x9481, 0x2056,
+ 0x9482, 0x2163,
+ 0x9483, 0x341f,
+ 0x9487, 0x1fa9,
+ 0x9488, 0x1ffc,
+ 0x9489, 0x3423,
+ 0x94a1, 0x1e2e,
+ 0x94a2, 0x343b,
+ 0x94b3, 0x1ebc,
+ 0x94b4, 0x344c,
+ 0x94b5, 0x2142,
+ 0x94b6, 0x344d,
+ 0x94bf, 0x201e,
+ 0x94c0, 0x1e43,
+ 0x94c1, 0x3456,
+ 0x94cc, 0x24d4,
+ 0x94cd, 0x3461,
+ 0x94d8, 0x226f,
+ 0x94d9, 0x346c,
+ 0x94e0, 0x1ed7,
+ 0x94e1, 0x3473,
+ 0x9540, 0x3491,
+ 0x9572, 0x212d,
+ 0x9573, 0x34c3,
+ 0x9580, 0x34cf,
+ 0x9583, 0x229b,
+ 0x9584, 0x34d2,
+ 0x959e, 0x2256,
+ 0x959f, 0x24a8,
+ 0x95a0, 0x34ec,
+ 0x95b3, 0x1e79,
+ 0x95b4, 0x34ff,
+ 0x95ba, 0x225a,
+ 0x95bb, 0x3505,
+ 0x95cf, 0x24a7,
+ 0x95d0, 0x3519,
+ 0x95d1, 0x2686,
+ 0x95d2, 0x24a6,
+ 0x95d3, 0x351a,
+ 0x95d4, 0x21ce,
+ 0x95d5, 0x351b,
+ 0x95e1, 0x24a9,
+ 0x95e2, 0x3527,
+ 0x95e7, 0x1fe7,
+ 0x95e8, 0x352c,
+ 0x95f1, 0x2112,
+ 0x95f2, 0x3535,
+ 0x95f8, 0x213c,
+ 0x95f9, 0x353b,
+ 0x95fe, 0x1f5c,
+ 0x9640, 0x3540,
+ 0x9656, 0x24c4,
+ 0x9657, 0x3556,
+ 0x967c, 0x1ecc,
+ 0x967d, 0x357b,
+ 0x9680, 0x357d,
+ 0x9740, 0x35fc,
+ 0x9767, 0x246a,
+ 0x9768, 0x3623,
+ 0x976c, 0x2175,
+ 0x976d, 0x3627,
+ 0x976e, 0x246d,
+ 0x976f, 0x3628,
+ 0x9780, 0x3638,
+ 0x9796, 0x246b,
+ 0x9797, 0x225f,
+ 0x9798, 0x364e,
+ 0x979d, 0x1ece,
+ 0x979e, 0x3653,
+ 0x97a3, 0x2272,
+ 0x97a4, 0x3658,
+ 0x97bf, 0x2473,
+ 0x97c0, 0x3673,
+ 0x97ee, 0x21fe,
+ 0x97ef, 0x36a1,
+ 0x97f7, 0x1efe,
+ 0x97f8, 0x36a9,
+ 0x9840, 0x36b0,
+ 0x9845, 0x2475,
+ 0x9846, 0x36b5,
+ 0x9849, 0x220a,
+ 0x984a, 0x36b8,
+ 0x984f, 0x1f6f,
+ 0x9850, 0x36bd,
+ 0x9871, 0x2468,
+ 0x9872, 0x36de,
+ 0x9873, 0x2100,
+ 0x9874, 0x36df,
+ 0x9880, 0x36ea,
+ 0x9881, 0x2476,
+ 0x9882, 0x36eb,
+ 0x988b, 0x1f27,
+ 0x988c, 0x20d7,
+ 0x988d, 0x36f4,
+ 0x98a0, 0x247c,
+ 0x98a1, 0x3707,
+ 0x98aa, 0x1fa1,
+ 0x98ab, 0x3710,
+ 0x98b6, 0x22aa,
+ 0x98b7, 0x2005,
+ 0x98b8, 0x371b,
+ 0x98ba, 0x246c,
+ 0x98bb, 0x371d,
+ 0x98c7, 0x203e,
+ 0x98c8, 0x3729,
+ 0x98cb, 0x1e4c,
+ 0x98cc, 0x372c,
+ 0x98d0, 0x213a,
+ 0x98d1, 0x3730,
+ 0x98d3, 0x2204,
+ 0x98d4, 0x3732,
+ 0x98e3, 0x20c3,
+ 0x98e4, 0x2140,
+ 0x98e5, 0x2477,
+ 0x98e6, 0x3741,
+ 0x98ef, 0x2474,
+ 0x98f0, 0x374a,
+ 0x98f2, 0x20dd,
+ 0x98f3, 0x374c,
+ 0x9940, 0x3758,
+ 0x9943, 0x1f68,
+ 0x9944, 0x375b,
+ 0x9945, 0x2185,
+ 0x9946, 0x375c,
+ 0x9966, 0x2472,
+ 0x9967, 0x377c,
+ 0x996e, 0x1eb5,
+ 0x996f, 0x3783,
+ 0x9975, 0x2478,
+ 0x9976, 0x3789,
+ 0x997a, 0x1f8b,
+ 0x997b, 0x2484,
+ 0x997c, 0x378d,
+ 0x9980, 0x3790,
+ 0x9985, 0x2699,
+ 0x9986, 0x3795,
+ 0x9989, 0x2482,
+ 0x998a, 0x3798,
+ 0x998e, 0x20a1,
+ 0x998f, 0x379c,
+ 0x9991, 0x1f92,
+ 0x9992, 0x379e,
+ 0x9999, 0x1f38,
+ 0x999a, 0x37a5,
+ 0x99a9, 0x2485,
+ 0x99aa, 0x37b4,
+ 0x99b0, 0x2480,
+ 0x99b1, 0x246e,
+ 0x99b2, 0x37ba,
+ 0x99b3, 0x247b,
+ 0x99b4, 0x2486,
+ 0x99b5, 0x2471,
+ 0x99b6, 0x37bb,
+ 0x99bd, 0x2483,
+ 0x99be, 0x2470,
+ 0x99bf, 0x37c2,
+ 0x99c0, 0x2469,
+ 0x99c1, 0x37c3,
+ 0x99c2, 0x247f,
+ 0x99c3, 0x37c4,
+ 0x99c9, 0x246f,
+ 0x99ca, 0x37ca,
+ 0x99ce, 0x2481,
+ 0x99cf, 0x37ce,
+ 0x99d1, 0x2220,
+ 0x99d2, 0x37d0,
+ 0x99da, 0x1ff5,
+ 0x99db, 0x37d8,
+ 0x99e0, 0x20f4,
+ 0x99e1, 0x37dd,
+ 0x99e5, 0x247d,
+ 0x99e6, 0x37e1,
+ 0x99e8, 0x2479,
+ 0x99e9, 0x37e3,
+ 0x99ec, 0x247e,
+ 0x99ed, 0x37e6,
+ 0x99f4, 0x247a,
+ 0x99f5, 0x37ed,
+ 0x9a40, 0x37f7,
+ 0x9a4a, 0x20e3,
+ 0x9a4b, 0x3801,
+ 0x9a57, 0x20ad,
+ 0x9a58, 0x380d,
+ 0x9a65, 0x24cb,
+ 0x9a66, 0x381a,
+ 0x9a67, 0x1f53,
+ 0x9a68, 0x381b,
+ 0x9a71, 0x2159,
+ 0x9a72, 0x3824,
+ 0x9a76, 0x2013,
+ 0x9a77, 0x1f33,
+ 0x9a78, 0x3828,
+ 0x9a80, 0x382f,
+ 0x9a88, 0x1e5c,
+ 0x9a89, 0x3837,
+ 0x9a8c, 0x2488,
+ 0x9a8d, 0x383a,
+ 0x9a91, 0x2487,
+ 0x9a92, 0x383e,
+ 0x9a97, 0x248a,
+ 0x9a98, 0x3843,
+ 0x9a9a, 0x2489,
+ 0x9a9b, 0x248b,
+ 0x9a9c, 0x3845,
+ 0x9a9e, 0x1f83,
+ 0x9a9f, 0x3847,
+ 0x9aa2, 0x210f,
+ 0x9aa3, 0x1fdb,
+ 0x9aa4, 0x384a,
+ 0x9aaa, 0x20af,
+ 0x9aab, 0x3850,
+ 0x9ad0, 0x24c0,
+ 0x9ad1, 0x3875,
+ 0x9ad6, 0x226d,
+ 0x9ad7, 0x387a,
+ 0x9ada, 0x24c1,
+ 0x9adb, 0x387d,
+ 0x9ae2, 0x20ca,
+ 0x9ae3, 0x3884,
+ 0x9ae4, 0x20e7,
+ 0x9ae5, 0x24c2,
+ 0x9ae6, 0x3885,
+ 0x9b40, 0x389e,
+ 0x9b80, 0x38dd,
+ 0x9bd1, 0x23dc,
+ 0x9bd2, 0x392e,
+ 0x9bdc, 0x23db,
+ 0x9bdd, 0x3938,
+ 0x9c40, 0x395a,
+ 0x9c53, 0x205e,
+ 0x9c54, 0x396d,
+ 0x9c59, 0x2244,
+ 0x9c5a, 0x23e2,
+ 0x9c5b, 0x3972,
+ 0x9c5c, 0x20d4,
+ 0x9c5d, 0x3973,
+ 0x9c75, 0x219f,
+ 0x9c76, 0x398b,
+ 0x9c79, 0x1e66,
+ 0x9c7a, 0x398e,
+ 0x9c80, 0x3993,
+ 0x9c86, 0x1f63,
+ 0x9c87, 0x3999,
+ 0x9c9d, 0x23dd,
+ 0x9c9e, 0x39af,
+ 0x9cab, 0x216b,
+ 0x9cac, 0x39bc,
+ 0x9cca, 0x22b5,
+ 0x9ccb, 0x39da,
+ 0x9ccf, 0x1f26,
+ 0x9cd0, 0x39de,
+ 0x9ce6, 0x1e63,
+ 0x9ce7, 0x2088,
+ 0x9ce8, 0x39f4,
+ 0x9cec, 0x1ebd,
+ 0x9ced, 0x39f8,
+ 0x9cee, 0x2341,
+ 0x9cef, 0x39f9,
+ 0x9cfb, 0x1f4b,
+ 0x9cfc, 0x3a05,
+ 0x9cfe, 0x2292,
+ 0x9d40, 0x3a07,
+ 0x9d42, 0x2124,
+ 0x9d43, 0x3a09,
+ 0x9d46, 0x2048,
+ 0x9d47, 0x23e0,
+ 0x9d48, 0x3a0c,
+ 0x9d4d, 0x2077,
+ 0x9d4e, 0x3a11,
+ 0x9d4f, 0x223a,
+ 0x9d50, 0x3a12,
+ 0x9d61, 0x20b1,
+ 0x9d62, 0x3a23,
+ 0x9d68, 0x1f41,
+ 0x9d69, 0x201c,
+ 0x9d6a, 0x3a29,
+ 0x9d6e, 0x22b8,
+ 0x9d6f, 0x3a2d,
+ 0x9d71, 0x2276,
+ 0x9d72, 0x3a2f,
+ 0x9d75, 0x1f9b,
+ 0x9d76, 0x3a32,
+ 0x9d7b, 0x1f9f,
+ 0x9d7c, 0x3a37,
+ 0x9d7d, 0x25ca,
+ 0x9d7e, 0x3a38,
+ 0x9d80, 0x3a39,
+ 0x9d8a, 0x20be,
+ 0x9d8b, 0x3a43,
+ 0x9d8d, 0x1fb4,
+ 0x9d8e, 0x3a45,
+ 0x9d91, 0x23d7,
+ 0x9d92, 0x3a48,
+ 0x9d99, 0x2105,
+ 0x9d9a, 0x3a4f,
+ 0x9da1, 0x23e1,
+ 0x9da2, 0x1fec,
+ 0x9da3, 0x3a56,
+ 0x9da7, 0x23ea,
+ 0x9da8, 0x3a5a,
+ 0x9dac, 0x23e3,
+ 0x9dad, 0x210e,
+ 0x9dae, 0x3a5e,
+ 0x9db2, 0x1fa6,
+ 0x9db3, 0x2004,
+ 0x9db4, 0x3a62,
+ 0x9dbe, 0x1f9d,
+ 0x9dbf, 0x3a6c,
+ 0x9dc6, 0x23e5,
+ 0x9dc7, 0x3a73,
+ 0x9dc9, 0x2264,
+ 0x9dca, 0x3a75,
+ 0x9dcd, 0x24e2,
+ 0x9dce, 0x3a78,
+ 0x9dd2, 0x23de,
+ 0x9dd3, 0x3a7c,
+ 0x9dd5, 0x1ec4,
+ 0x9dd6, 0x3a7e,
+ 0x9de1, 0x22b6,
+ 0x9de2, 0x20a9,
+ 0x9de3, 0x3a89,
+ 0x9df1, 0x212b,
+ 0x9df2, 0x3a97,
+ 0x9df4, 0x20a5,
+ 0x9df5, 0x3a99,
+ 0x9df7, 0x268b,
+ 0x9df8, 0x3a9b,
+ 0x9dfa, 0x1f76,
+ 0x9dfb, 0x3a9d,
+ 0x9dfd, 0x216d,
+ 0x9dfe, 0x3a9f,
+ 0x9e40, 0x3aa0,
+ 0x9e45, 0x2001,
+ 0x9e46, 0x3aa5,
+ 0x9e48, 0x2191,
+ 0x9e49, 0x1e50,
+ 0x9e4a, 0x3aa7,
+ 0x9e52, 0x1f9c,
+ 0x9e53, 0x3aaf,
+ 0x9e54, 0x23da,
+ 0x9e55, 0x3ab0,
+ 0x9e56, 0x2053,
+ 0x9e57, 0x3ab1,
+ 0x9e5d, 0x23e9,
+ 0x9e5e, 0x23e4,
+ 0x9e5f, 0x3ab7,
+ 0x9e61, 0x21d5,
+ 0x9e62, 0x3ab9,
+ 0x9e63, 0x23e6,
+ 0x9e64, 0x3aba,
+ 0x9e67, 0x23df,
+ 0x9e68, 0x3abd,
+ 0x9e6c, 0x1e4f,
+ 0x9e6d, 0x3ac1,
+ 0x9e6f, 0x23d9,
+ 0x9e70, 0x3ac3,
+ 0x9e72, 0x2014,
+ 0x9e73, 0x3ac5,
+ 0x9e74, 0x23ec,
+ 0x9e75, 0x23eb,
+ 0x9e76, 0x3ac6,
+ 0x9e7b, 0x23d8,
+ 0x9e7c, 0x23ee,
+ 0x9e7d, 0x3acb,
+ 0x9e80, 0x3acd,
+ 0x9e85, 0x268e,
+ 0x9e86, 0x3ad2,
+ 0x9e87, 0x23ed,
+ 0x9e88, 0x3ad3,
+ 0x9e91, 0x1ffa,
+ 0x9e92, 0x3adc,
+ 0x9e96, 0x23d6,
+ 0x9e97, 0x23e8,
+ 0x9e98, 0x3ae0,
+ 0x9ea2, 0x2106,
+ 0x9ea3, 0x3aea,
+ 0x9ea6, 0x200b,
+ 0x9ea7, 0x3aed,
+ 0x9ea9, 0x2166,
+ 0x9eaa, 0x3aef,
+ 0x9eae, 0x23ef,
+ 0x9eaf, 0x3af3,
+ 0x9eb3, 0x2189,
+ 0x9eb4, 0x2058,
+ 0x9eb5, 0x3af7,
+ 0x9eb7, 0x23e7,
+ 0x9eb8, 0x3af9,
+ 0x9ef5, 0x21a3,
+ 0x9ef6, 0x3b36,
+ 0x9f40, 0x3b3f,
+ 0x9f4e, 0x217a,
+ 0x9f4f, 0x3b4d,
+ 0x9f6f, 0x21a5,
+ 0x9f70, 0x3b6d,
+ 0x9f80, 0x3b7c,
+ 0x9f92, 0x2022,
+ 0x9f93, 0x3b8e,
+ 0x9f98, 0x24d6,
+ 0x9f99, 0x3b93,
+ 0x9fa6, 0x233a,
+ 0x9fa7, 0x3ba0,
+ 0x9fa9, 0x1eee,
+ 0x9faa, 0x3ba2,
+ 0x9fac, 0x24d5,
+ 0x9fad, 0x3ba4,
+ 0x9fc9, 0x2228,
+ 0x9fca, 0x3bc0,
+ 0x9fcd, 0x24d7,
+ 0x9fce, 0x3bc3,
+ 0x9fe1, 0x20fc,
+ 0x9fe2, 0x3bd6,
+ 0x9feb, 0x1e87,
+ 0x9fec, 0x3bdf,
+ 0x9fee, 0x24d8,
+ 0x9fef, 0x3be1,
+ 0x9ff4, 0x1eba,
+ 0x9ff5, 0x3be6,
+ 0x9ffd, 0x2119,
+ 0x9ffe, 0x3bee,
+ 0xa040, 0x3bef,
+ 0xa043, 0x216c,
+ 0xa044, 0x3bf2,
+ 0xa046, 0x24d9,
+ 0xa047, 0x3bf4,
+ 0xa049, 0x2227,
+ 0xa04a, 0x3bf6,
+ 0xa04e, 0x1e5f,
+ 0xa04f, 0x3bfa,
+ 0xa054, 0x229f,
+ 0xa055, 0x3bff,
+ 0xa05a, 0x1f5d,
+ 0xa05b, 0x3c04,
+ 0xa061, 0x1fbc,
+ 0xa062, 0x3c0a,
+ 0xa063, 0x24da,
+ 0xa064, 0x3c0b,
+ 0xa071, 0x2149,
+ 0xa072, 0x3c18,
+ 0xa074, 0x2046,
+ 0xa075, 0x3c1a,
+ 0xa080, 0x2000,
+ 0xa081, 0x3c24,
+ 0xa091, 0x2190,
+ 0xa092, 0x3c34,
+ 0xa094, 0x2208,
+ 0xa095, 0x3c36,
+ 0xa096, 0x1ee6,
+ 0xa097, 0x3c37,
+ 0xa0a9, 0x24c3,
+ 0xa0aa, 0x3c49,
+ 0xa0bf, 0x20cc,
+ 0xa0c0, 0x3c5e,
+ 0xa0ce, 0x2340,
+ 0xa0cf, 0x3c6c,
+ 0xa0d9, 0x1ed1,
+ 0xa0da, 0x3c76,
+ 0xa0de, 0x21ac,
+ 0xa0df, 0x3c7a,
+ 0xa0ee, 0x22af,
+ 0xa0ef, 0x3c89,
+ 0xa1a1, 0x0060,
+ 0xa2a1, 0x26a9,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa840, 0x26b3,
+ 0xa880, 0x26f2,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa940, 0x2708,
+ 0xa959, 0x2720,
+ 0xa95c, 0x2722,
+ 0xa960, 0x2723,
+ 0xa980, 0x2742,
+ 0xa996, 0x1e17,
+ 0xa9a4, 0x02e2,
+ 0xaa40, 0x3c99,
+ 0xaa4d, 0x21b6,
+ 0xaa4e, 0x1e3d,
+ 0xaa4f, 0x3ca6,
+ 0xaa71, 0x2235,
+ 0xaa72, 0x3cc8,
+ 0xaa73, 0x2397,
+ 0xaa74, 0x3cc9,
+ 0xaa77, 0x2395,
+ 0xaa78, 0x3ccc,
+ 0xaa7a, 0x223f,
+ 0xaa7b, 0x212a,
+ 0xaa7c, 0x3cce,
+ 0xaa80, 0x3cd1,
+ 0xaa9a, 0x1ed2,
+ 0xaa9b, 0x3ceb,
+ 0xaa9c, 0x2396,
+ 0xaa9d, 0x2398,
+ 0xaa9e, 0x3cec,
+ 0xaa9f, 0x20a2,
+ 0xaaa0, 0x3ced,
+ 0xaaa1, 0x032e,
+ 0xab40, 0x1f64,
+ 0xab41, 0x3cee,
+ 0xab43, 0x202b,
+ 0xab44, 0x3cf0,
+ 0xab45, 0x2394,
+ 0xab46, 0x2139,
+ 0xab47, 0x3cf1,
+ 0xab48, 0x215f,
+ 0xab49, 0x21c1,
+ 0xab4a, 0x239a,
+ 0xab4b, 0x3cf2,
+ 0xab4d, 0x2399,
+ 0xab4e, 0x3cf4,
+ 0xab80, 0x3d25,
+ 0xaba1, 0x038c,
+ 0xac40, 0x3d46,
+ 0xac46, 0x21c0,
+ 0xac47, 0x3d4c,
+ 0xac71, 0x2460,
+ 0xac72, 0x3d76,
+ 0xac7c, 0x245c,
+ 0xac7d, 0x3d80,
+ 0xac80, 0x3d82,
+ 0xac8d, 0x215d,
+ 0xac8e, 0x3d8f,
+ 0xac93, 0x2225,
+ 0xac94, 0x206a,
+ 0xac95, 0x3d94,
+ 0xad40, 0x3da0,
+ 0xad49, 0x2461,
+ 0xad4a, 0x3da9,
+ 0xad5e, 0x245b,
+ 0xad5f, 0x3dbd,
+ 0xad61, 0x2462,
+ 0xad62, 0x3dbf,
+ 0xad68, 0x1f54,
+ 0xad69, 0x3dc5,
+ 0xad74, 0x245f,
+ 0xad75, 0x3dd0,
+ 0xad80, 0x3dda,
+ 0xad82, 0x20ec,
+ 0xad83, 0x3ddc,
+ 0xad87, 0x245d,
+ 0xad88, 0x3de0,
+ 0xad8b, 0x2463,
+ 0xad8c, 0x3de3,
+ 0xad91, 0x2464,
+ 0xad92, 0x3de8,
+ 0xae40, 0x3df7,
+ 0xae54, 0x24a5,
+ 0xae55, 0x3e0b,
+ 0xae62, 0x1e70,
+ 0xae63, 0x3e18,
+ 0xae80, 0x208f,
+ 0xae81, 0x3e34,
+ 0xae85, 0x1e42,
+ 0xae86, 0x3e38,
+ 0xae8b, 0x1f4e,
+ 0xae8c, 0x3e3d,
+ 0xae94, 0x1eb1,
+ 0xae95, 0x3e45,
+ 0xaea0, 0x1e8b,
+ 0xaf40, 0x3e50,
+ 0xaf64, 0x1fc6,
+ 0xaf65, 0x3e74,
+ 0xaf7b, 0x25ae,
+ 0xaf7c, 0x3e8a,
+ 0xaf80, 0x3e8d,
+ 0xaf82, 0x1f01,
+ 0xaf83, 0x2200,
+ 0xaf84, 0x3e8f,
+ 0xaf8e, 0x25b2,
+ 0xaf8f, 0x1e97,
+ 0xaf90, 0x3e99,
+ 0xaf91, 0x20ab,
+ 0xaf92, 0x3e9a,
+ 0xaf9c, 0x25b3,
+ 0xaf9d, 0x3ea4,
+ 0xaf9f, 0x2028,
+ 0xafa0, 0x3ea6,
+ 0xb040, 0x3ea7,
+ 0xb041, 0x25af,
+ 0xb043, 0x3ea8,
+ 0xb044, 0x25b1,
+ 0xb045, 0x3ea9,
+ 0xb04f, 0x25ac,
+ 0xb050, 0x3eb3,
+ 0xb054, 0x1e4e,
+ 0xb055, 0x3eb7,
+ 0xb057, 0x2202,
+ 0xb058, 0x25ab,
+ 0xb059, 0x2286,
+ 0xb05a, 0x3eb9,
+ 0xb05b, 0x25ad,
+ 0xb05c, 0x3eba,
+ 0xb05d, 0x25b6,
+ 0xb05e, 0x3ebb,
+ 0xb05f, 0x21e3,
+ 0xb060, 0x25b4,
+ 0xb062, 0x222f,
+ 0xb063, 0x2165,
+ 0xb064, 0x25b7,
+ 0xb065, 0x3ebc,
+ 0xb06c, 0x1ee9,
+ 0xb06d, 0x3ec3,
+ 0xb07d, 0x1e25,
+ 0xb07e, 0x3ed3,
+ 0xb080, 0x3ed4,
+ 0xb097, 0x25c0,
+ 0xb098, 0x3eeb,
+ 0xb099, 0x229a,
+ 0xb09a, 0x3eec,
+ 0xb0a1, 0x03ac,
+ 0xb140, 0x3ef3,
+ 0xb14b, 0x226e,
+ 0xb14c, 0x3efe,
+ 0xb14d, 0x1fbd,
+ 0xb14e, 0x3eff,
+ 0xb14f, 0x1f84,
+ 0xb150, 0x20b2,
+ 0xb151, 0x3f00,
+ 0xb152, 0x2043,
+ 0xb153, 0x3f01,
+ 0xb180, 0x3f2d,
+ 0xb197, 0x2684,
+ 0xb198, 0x3f44,
+ 0xb1a1, 0x040a,
+ 0xb240, 0x3f4d,
+ 0xb241, 0x24ef,
+ 0xb242, 0x3f4e,
+ 0xb267, 0x24ee,
+ 0xb268, 0x3f73,
+ 0xb26d, 0x2074,
+ 0xb26e, 0x3f78,
+ 0xb274, 0x2687,
+ 0xb275, 0x3f7e,
+ 0xb280, 0x24f0,
+ 0xb281, 0x3f88,
+ 0xb289, 0x268d,
+ 0xb28a, 0x3f90,
+ 0xb29a, 0x22a0,
+ 0xb29b, 0x3fa0,
+ 0xb2a1, 0x0468,
+ 0xb340, 0x3fa6,
+ 0xb343, 0x1fab,
+ 0xb344, 0x3fa9,
+ 0xb370, 0x26a8,
+ 0xb371, 0x3fd5,
+ 0xb380, 0x3fe3,
+ 0xb388, 0x24e9,
+ 0xb389, 0x3feb,
+ 0xb38c, 0x24e5,
+ 0xb38d, 0x3fee,
+ 0xb38e, 0x21fa,
+ 0xb38f, 0x3fef,
+ 0xb3a1, 0x04c6,
+ 0xb440, 0x4001,
+ 0xb454, 0x2148,
+ 0xb455, 0x4015,
+ 0xb458, 0x24e4,
+ 0xb459, 0x4018,
+ 0xb45e, 0x24e6,
+ 0xb45f, 0x20f7,
+ 0xb460, 0x401d,
+ 0xb461, 0x206b,
+ 0xb462, 0x401e,
+ 0xb475, 0x22a7,
+ 0xb476, 0x4031,
+ 0xb47e, 0x24ec,
+ 0xb480, 0x4039,
+ 0xb483, 0x24eb,
+ 0xb484, 0x403c,
+ 0xb489, 0x24e3,
+ 0xb48a, 0x4041,
+ 0xb493, 0x24ea,
+ 0xb494, 0x404a,
+ 0xb4a1, 0x0524,
+ 0xb540, 0x4057,
+ 0xb541, 0x1e92,
+ 0xb542, 0x4058,
+ 0xb54b, 0x1e27,
+ 0xb54c, 0x4061,
+ 0xb556, 0x1fe6,
+ 0xb557, 0x406b,
+ 0xb55a, 0x24e7,
+ 0xb55b, 0x2012,
+ 0xb55c, 0x1eec,
+ 0xb55d, 0x406e,
+ 0xb561, 0x24e8,
+ 0xb562, 0x4072,
+ 0xb580, 0x408f,
+ 0xb59c, 0x1f66,
+ 0xb59d, 0x24dc,
+ 0xb59e, 0x40ab,
+ 0xb5a1, 0x0582,
+ 0xb640, 0x40ae,
+ 0xb652, 0x26a2,
+ 0xb653, 0x40c0,
+ 0xb655, 0x24dd,
+ 0xb656, 0x40c2,
+ 0xb659, 0x200e,
+ 0xb65a, 0x40c5,
+ 0xb65b, 0x24db,
+ 0xb65c, 0x1eb8,
+ 0xb65d, 0x40c6,
+ 0xb680, 0x40e8,
+ 0xb6a1, 0x05e0,
+ 0xb740, 0x4109,
+ 0xb74e, 0x2295,
+ 0xb74f, 0x4117,
+ 0xb751, 0x1e80,
+ 0xb752, 0x4119,
+ 0xb759, 0x2677,
+ 0xb75a, 0x4120,
+ 0xb764, 0x2624,
+ 0xb765, 0x1f69,
+ 0xb766, 0x222b,
+ 0xb767, 0x412a,
+ 0xb777, 0x257f,
+ 0xb778, 0x1f5b,
+ 0xb779, 0x413a,
+ 0xb780, 0x219b,
+ 0xb781, 0x4140,
+ 0xb782, 0x267d,
+ 0xb783, 0x4141,
+ 0xb7a1, 0x063e,
+ 0xb840, 0x415f,
+ 0xb843, 0x21a0,
+ 0xb844, 0x2186,
+ 0xb845, 0x4162,
+ 0xb846, 0x20ed,
+ 0xb847, 0x4163,
+ 0xb84d, 0x25b9,
+ 0xb84e, 0x4169,
+ 0xb851, 0x1fea,
+ 0xb852, 0x416c,
+ 0xb85a, 0x1ea4,
+ 0xb85b, 0x20e1,
+ 0xb85c, 0x4174,
+ 0xb85d, 0x25b8,
+ 0xb85e, 0x2260,
+ 0xb85f, 0x4175,
+ 0xb860, 0x20e2,
+ 0xb861, 0x4176,
+ 0xb877, 0x2141,
+ 0xb878, 0x418c,
+ 0xb880, 0x4193,
+ 0xb882, 0x1fc7,
+ 0xb883, 0x4195,
+ 0xb8a1, 0x069c,
+ 0xb940, 0x41b3,
+ 0xb950, 0x1e41,
+ 0xb951, 0x41c3,
+ 0xb961, 0x25e4,
+ 0xb962, 0x41d3,
+ 0xb97b, 0x1f86,
+ 0xb97c, 0x41ec,
+ 0xb980, 0x41ef,
+ 0xb99d, 0x1fb3,
+ 0xb99e, 0x420c,
+ 0xb9a0, 0x1eef,
+ 0xb9a1, 0x06fa,
+ 0xba40, 0x420e,
+ 0xba42, 0x22a4,
+ 0xba43, 0x4210,
+ 0xba44, 0x25e8,
+ 0xba45, 0x4211,
+ 0xba56, 0x25e3,
+ 0xba57, 0x4222,
+ 0xba59, 0x2111,
+ 0xba5a, 0x4224,
+ 0xba60, 0x25e6,
+ 0xba61, 0x422a,
+ 0xba6a, 0x25e7,
+ 0xba6b, 0x4233,
+ 0xba74, 0x2041,
+ 0xba75, 0x423c,
+ 0xba80, 0x4246,
+ 0xba84, 0x25ea,
+ 0xba85, 0x424a,
+ 0xba86, 0x1f8f,
+ 0xba87, 0x424b,
+ 0xba88, 0x25ec,
+ 0xba89, 0x424c,
+ 0xba8d, 0x25eb,
+ 0xba8e, 0x4250,
+ 0xba9e, 0x20d0,
+ 0xba9f, 0x201d,
+ 0xbaa0, 0x4260,
+ 0xbaa1, 0x0758,
+ 0xbb40, 0x1ff7,
+ 0xbb41, 0x4261,
+ 0xbb49, 0x1e8d,
+ 0xbb4a, 0x4269,
+ 0xbb58, 0x25e9,
+ 0xbb59, 0x4277,
+ 0xbb5b, 0x25ee,
+ 0xbb5c, 0x203a,
+ 0xbb5d, 0x4279,
+ 0xbb60, 0x2693,
+ 0xbb61, 0x427c,
+ 0xbb65, 0x25e5,
+ 0xbb66, 0x25ed,
+ 0xbb67, 0x4280,
+ 0xbb68, 0x2009,
+ 0xbb69, 0x4281,
+ 0xbb6a, 0x2065,
+ 0xbb6b, 0x4282,
+ 0xbb6e, 0x26a3,
+ 0xbb6f, 0x4285,
+ 0xbb80, 0x4295,
+ 0xbba1, 0x07b6,
+ 0xbc40, 0x42b6,
+ 0xbc52, 0x25f5,
+ 0xbc53, 0x1efc,
+ 0xbc54, 0x42c8,
+ 0xbc5a, 0x2024,
+ 0xbc5b, 0x42ce,
+ 0xbc61, 0x269b,
+ 0xbc62, 0x42d4,
+ 0xbc63, 0x25f3,
+ 0xbc64, 0x42d5,
+ 0xbc65, 0x22d9,
+ 0xbc66, 0x42d6,
+ 0xbc67, 0x25f4,
+ 0xbc68, 0x42d7,
+ 0xbc69, 0x241b,
+ 0xbc6a, 0x42d8,
+ 0xbc6d, 0x1fc8,
+ 0xbc6e, 0x42db,
+ 0xbc6f, 0x1f7b,
+ 0xbc70, 0x42dc,
+ 0xbc71, 0x241d,
+ 0xbc72, 0x42dd,
+ 0xbc73, 0x224c,
+ 0xbc74, 0x1f48,
+ 0xbc75, 0x241c,
+ 0xbc76, 0x241e,
+ 0xbc78, 0x20ff,
+ 0xbc79, 0x219a,
+ 0xbc7a, 0x42de,
+ 0xbc7b, 0x2091,
+ 0xbc7c, 0x42df,
+ 0xbc7e, 0x20a7,
+ 0xbc80, 0x42e1,
+ 0xbc82, 0x2423,
+ 0xbc83, 0x1e9b,
+ 0xbc84, 0x2422,
+ 0xbc85, 0x42e3,
+ 0xbc86, 0x2110,
+ 0xbc87, 0x42e4,
+ 0xbc88, 0x228d,
+ 0xbc89, 0x1f71,
+ 0xbc8a, 0x1ef8,
+ 0xbc8b, 0x2421,
+ 0xbc8c, 0x42e5,
+ 0xbc8f, 0x1ef3,
+ 0xbc90, 0x42e8,
+ 0xbc9a, 0x21b1,
+ 0xbc9b, 0x2426,
+ 0xbc9c, 0x2425,
+ 0xbc9d, 0x2120,
+ 0xbc9e, 0x42f2,
+ 0xbca1, 0x0814,
+ 0xbd40, 0x42f5,
+ 0xbd42, 0x211a,
+ 0xbd43, 0x2424,
+ 0xbd44, 0x42f7,
+ 0xbd45, 0x2428,
+ 0xbd46, 0x42f8,
+ 0xbd48, 0x242a,
+ 0xbd49, 0x2429,
+ 0xbd4a, 0x42fa,
+ 0xbd4b, 0x2294,
+ 0xbd4c, 0x42fb,
+ 0xbd4d, 0x22be,
+ 0xbd4e, 0x42fc,
+ 0xbd4f, 0x1e31,
+ 0xbd50, 0x42fd,
+ 0xbd57, 0x242c,
+ 0xbd58, 0x4304,
+ 0xbd59, 0x1fb5,
+ 0xbd5a, 0x4305,
+ 0xbd66, 0x242b,
+ 0xbd67, 0x1faf,
+ 0xbd68, 0x4311,
+ 0xbd6a, 0x2068,
+ 0xbd6b, 0x21e4,
+ 0xbd6c, 0x4313,
+ 0xbd6f, 0x1f21,
+ 0xbd70, 0x4316,
+ 0xbd71, 0x2101,
+ 0xbd72, 0x4317,
+ 0xbd79, 0x217c,
+ 0xbd7a, 0x214a,
+ 0xbd7b, 0x242d,
+ 0xbd7c, 0x431e,
+ 0xbd7e, 0x1fd4,
+ 0xbd80, 0x4320,
+ 0xbd81, 0x1fd1,
+ 0xbd82, 0x4321,
+ 0xbd89, 0x1e33,
+ 0xbd8a, 0x4328,
+ 0xbd8b, 0x242f,
+ 0xbd8c, 0x4329,
+ 0xbd8e, 0x242e,
+ 0xbd8f, 0x432b,
+ 0xbd90, 0x2430,
+ 0xbd91, 0x21db,
+ 0xbd92, 0x432c,
+ 0xbd97, 0x2158,
+ 0xbd98, 0x4331,
+ 0xbd9b, 0x1fc2,
+ 0xbd9c, 0x4334,
+ 0xbda1, 0x0872,
+ 0xbe40, 0x4339,
+ 0xbe43, 0x22b9,
+ 0xbe44, 0x433c,
+ 0xbe45, 0x2436,
+ 0xbe46, 0x433d,
+ 0xbe49, 0x1e8e,
+ 0xbe4a, 0x2439,
+ 0xbe4b, 0x4340,
+ 0xbe51, 0x21c5,
+ 0xbe52, 0x2437,
+ 0xbe53, 0x2192,
+ 0xbe54, 0x4346,
+ 0xbe55, 0x243a,
+ 0xbe56, 0x1f19,
+ 0xbe57, 0x218c,
+ 0xbe58, 0x1e40,
+ 0xbe59, 0x22b3,
+ 0xbe5a, 0x4347,
+ 0xbe5d, 0x205f,
+ 0xbe5e, 0x2438,
+ 0xbe5f, 0x2432,
+ 0xbe60, 0x2274,
+ 0xbe61, 0x434a,
+ 0xbe62, 0x1e9c,
+ 0xbe63, 0x2431,
+ 0xbe64, 0x2085,
+ 0xbe65, 0x434b,
+ 0xbe69, 0x2435,
+ 0xbe6a, 0x434f,
+ 0xbe6c, 0x243b,
+ 0xbe6d, 0x4351,
+ 0xbe6f, 0x1fb7,
+ 0xbe70, 0x2433,
+ 0xbe71, 0x4353,
+ 0xbe76, 0x2054,
+ 0xbe77, 0x21de,
+ 0xbe78, 0x4358,
+ 0xbe79, 0x2434,
+ 0xbe7a, 0x4359,
+ 0xbe7c, 0x243d,
+ 0xbe7d, 0x1f89,
+ 0xbe7e, 0x243c,
+ 0xbe80, 0x435b,
+ 0xbe83, 0x1f6e,
+ 0xbe84, 0x1ed8,
+ 0xbe85, 0x435e,
+ 0xbe86, 0x1ebf,
+ 0xbe87, 0x2445,
+ 0xbe88, 0x435f,
+ 0xbe89, 0x2249,
+ 0xbe8a, 0x4360,
+ 0xbe8c, 0x2441,
+ 0xbe8d, 0x4362,
+ 0xbe8e, 0x1e47,
+ 0xbe8f, 0x1f56,
+ 0xbe90, 0x4363,
+ 0xbe92, 0x2086,
+ 0xbe93, 0x4365,
+ 0xbe95, 0x2196,
+ 0xbe96, 0x4367,
+ 0xbe97, 0x2443,
+ 0xbe98, 0x243f,
+ 0xbe99, 0x4368,
+ 0xbe9a, 0x2023,
+ 0xbe9b, 0x4369,
+ 0xbe9c, 0x2442,
+ 0xbe9d, 0x436a,
+ 0xbe9f, 0x243e,
+ 0xbea0, 0x436c,
+ 0xbea1, 0x08d0,
+ 0xbf40, 0x26a6,
+ 0xbf41, 0x436d,
+ 0xbf4d, 0x234e,
+ 0xbf4e, 0x2446,
+ 0xbf4f, 0x244b,
+ 0xbf50, 0x2444,
+ 0xbf51, 0x4379,
+ 0xbf55, 0x2427,
+ 0xbf56, 0x244c,
+ 0xbf57, 0x437d,
+ 0xbf60, 0x1f0f,
+ 0xbf61, 0x4386,
+ 0xbf62, 0x2447,
+ 0xbf63, 0x2449,
+ 0xbf64, 0x2448,
+ 0xbf65, 0x4387,
+ 0xbf68, 0x21c2,
+ 0xbf69, 0x438a,
+ 0xbf6c, 0x216e,
+ 0xbf6d, 0x438d,
+ 0xbf70, 0x1f03,
+ 0xbf71, 0x4390,
+ 0xbf72, 0x244a,
+ 0xbf73, 0x215c,
+ 0xbf74, 0x4391,
+ 0xbf76, 0x22bb,
+ 0xbf77, 0x2450,
+ 0xbf78, 0x4393,
+ 0xbf79, 0x2694,
+ 0xbf7a, 0x244f,
+ 0xbf7b, 0x25f6,
+ 0xbf7c, 0x2051,
+ 0xbf7d, 0x4394,
+ 0xbf7e, 0x244e,
+ 0xbf80, 0x4395,
+ 0xbf82, 0x22ba,
+ 0xbf83, 0x1f6d,
+ 0xbf84, 0x4397,
+ 0xbf89, 0x2452,
+ 0xbf8a, 0x2451,
+ 0xbf8b, 0x439c,
+ 0xbf95, 0x2455,
+ 0xbf96, 0x43a6,
+ 0xbf97, 0x2289,
+ 0xbf98, 0x2116,
+ 0xbf99, 0x43a7,
+ 0xbf9d, 0x2454,
+ 0xbf9e, 0x43ab,
+ 0xbfa1, 0x092e,
+ 0xc040, 0x20fb,
+ 0xc041, 0x43ae,
+ 0xc044, 0x2440,
+ 0xc045, 0x43b1,
+ 0xc04b, 0x2126,
+ 0xc04c, 0x1f61,
+ 0xc04d, 0x269d,
+ 0xc04e, 0x43b7,
+ 0xc04f, 0x1f8a,
+ 0xc050, 0x2456,
+ 0xc051, 0x2459,
+ 0xc052, 0x2458,
+ 0xc053, 0x43b8,
+ 0xc055, 0x1fae,
+ 0xc056, 0x43ba,
+ 0xc05b, 0x221a,
+ 0xc05c, 0x43bf,
+ 0xc05e, 0x1f7a,
+ 0xc05f, 0x244d,
+ 0xc060, 0x2457,
+ 0xc061, 0x43c1,
+ 0xc069, 0x2453,
+ 0xc06a, 0x43c9,
+ 0xc06b, 0x2420,
+ 0xc06c, 0x43ca,
+ 0xc06d, 0x21df,
+ 0xc06e, 0x2685,
+ 0xc06f, 0x43cb,
+ 0xc070, 0x1e6e,
+ 0xc071, 0x43cc,
+ 0xc074, 0x2224,
+ 0xc075, 0x2670,
+ 0xc076, 0x43cf,
+ 0xc077, 0x21ba,
+ 0xc078, 0x43d0,
+ 0xc079, 0x245a,
+ 0xc07a, 0x43d1,
+ 0xc07c, 0x1fff,
+ 0xc07d, 0x43d3,
+ 0xc080, 0x43d5,
+ 0xc09b, 0x25e2,
+ 0xc09c, 0x43f0,
+ 0xc09d, 0x269a,
+ 0xc09e, 0x43f1,
+ 0xc0a1, 0x098c,
+ 0xc140, 0x43f4,
+ 0xc150, 0x1eea,
+ 0xc151, 0x4404,
+ 0xc154, 0x1e2c,
+ 0xc155, 0x4407,
+ 0xc15f, 0x2062,
+ 0xc160, 0x24f1,
+ 0xc161, 0x4411,
+ 0xc162, 0x24f2,
+ 0xc163, 0x4412,
+ 0xc175, 0x25f2,
+ 0xc176, 0x4424,
+ 0xc178, 0x2215,
+ 0xc179, 0x4426,
+ 0xc180, 0x442c,
+ 0xc195, 0x21ae,
+ 0xc196, 0x4441,
+ 0xc1a1, 0x09ea,
+ 0xc240, 0x444c,
+ 0xc24e, 0x20e0,
+ 0xc24f, 0x445a,
+ 0xc265, 0x25c2,
+ 0xc266, 0x4470,
+ 0xc267, 0x25c1,
+ 0xc268, 0x4471,
+ 0xc27d, 0x2128,
+ 0xc27e, 0x4486,
+ 0xc280, 0x4487,
+ 0xc284, 0x2199,
+ 0xc285, 0x448b,
+ 0xc293, 0x2017,
+ 0xc294, 0x1ea0,
+ 0xc295, 0x2125,
+ 0xc296, 0x214d,
+ 0xc297, 0x4499,
+ 0xc298, 0x25c4,
+ 0xc299, 0x209d,
+ 0xc29a, 0x228a,
+ 0xc29b, 0x449a,
+ 0xc29c, 0x25c3,
+ 0xc29d, 0x449b,
+ 0xc2a0, 0x2179,
+ 0xc2a1, 0x0a48,
+ 0xc340, 0x2038,
+ 0xc341, 0x449e,
+ 0xc343, 0x2155,
+ 0xc344, 0x44a0,
+ 0xc37b, 0x21d2,
+ 0xc37c, 0x44d7,
+ 0xc380, 0x44da,
+ 0xc384, 0x24c7,
+ 0xc385, 0x44de,
+ 0xc39b, 0x2279,
+ 0xc39c, 0x44f4,
+ 0xc3a1, 0x0aa6,
+ 0xc440, 0x44f9,
+ 0xc449, 0x2123,
+ 0xc44a, 0x4502,
+ 0xc44c, 0x24c5,
+ 0xc44d, 0x4504,
+ 0xc454, 0x24c9,
+ 0xc455, 0x450b,
+ 0xc458, 0x2094,
+ 0xc459, 0x450e,
+ 0xc45b, 0x2296,
+ 0xc45c, 0x4510,
+ 0xc463, 0x1e77,
+ 0xc464, 0x4517,
+ 0xc477, 0x1f06,
+ 0xc478, 0x452a,
+ 0xc47a, 0x1fa5,
+ 0xc47b, 0x452c,
+ 0xc480, 0x4530,
+ 0xc481, 0x2099,
+ 0xc482, 0x4531,
+ 0xc491, 0x1ead,
+ 0xc492, 0x24c8,
+ 0xc493, 0x20a8,
+ 0xc494, 0x4540,
+ 0xc498, 0x201f,
+ 0xc499, 0x4544,
+ 0xc49a, 0x20c5,
+ 0xc49b, 0x4545,
+ 0xc49c, 0x24ca,
+ 0xc49d, 0x4546,
+ 0xc4a1, 0x0b04,
+ 0xc540, 0x454a,
+ 0xc544, 0x1ff0,
+ 0xc545, 0x454e,
+ 0xc546, 0x24c6,
+ 0xc547, 0x454f,
+ 0xc54b, 0x225d,
+ 0xc54c, 0x22de,
+ 0xc54d, 0x4553,
+ 0xc552, 0x202c,
+ 0xc553, 0x4558,
+ 0xc55f, 0x2161,
+ 0xc560, 0x4564,
+ 0xc563, 0x223b,
+ 0xc564, 0x21d9,
+ 0xc565, 0x1fcb,
+ 0xc566, 0x1fc9,
+ 0xc567, 0x4567,
+ 0xc580, 0x457f,
+ 0xc593, 0x1e61,
+ 0xc594, 0x4592,
+ 0xc59c, 0x25ef,
+ 0xc59d, 0x459a,
+ 0xc59e, 0x1f98,
+ 0xc59f, 0x459b,
+ 0xc5a1, 0x0b62,
+ 0xc640, 0x459d,
+ 0xc641, 0x25f0,
+ 0xc642, 0x459e,
+ 0xc644, 0x1f88,
+ 0xc645, 0x45a0,
+ 0xc647, 0x21f8,
+ 0xc648, 0x45a2,
+ 0xc663, 0x2322,
+ 0xc664, 0x45bd,
+ 0xc672, 0x2336,
+ 0xc673, 0x45cb,
+ 0xc680, 0x45d7,
+ 0xc6a1, 0x0bc0,
+ 0xc740, 0x45f8,
+ 0xc766, 0x22ab,
+ 0xc767, 0x461e,
+ 0xc76f, 0x1fbf,
+ 0xc770, 0x4626,
+ 0xc776, 0x1f7d,
+ 0xc777, 0x462c,
+ 0xc77b, 0x2333,
+ 0xc77c, 0x4630,
+ 0xc780, 0x4633,
+ 0xc7a1, 0x0c1e,
+ 0xc840, 0x4654,
+ 0xc841, 0x1f4d,
+ 0xc842, 0x4655,
+ 0xc84f, 0x2334,
+ 0xc850, 0x4662,
+ 0xc852, 0x1ff1,
+ 0xc853, 0x4664,
+ 0xc866, 0x218b,
+ 0xc867, 0x4677,
+ 0xc86e, 0x2349,
+ 0xc86f, 0x467e,
+ 0xc87e, 0x220b,
+ 0xc880, 0x468d,
+ 0xc887, 0x2346,
+ 0xc888, 0x4694,
+ 0xc892, 0x2347,
+ 0xc893, 0x469e,
+ 0xc894, 0x2193,
+ 0xc895, 0x469f,
+ 0xc899, 0x26a1,
+ 0xc89a, 0x46a3,
+ 0xc89d, 0x1f62,
+ 0xc89e, 0x46a6,
+ 0xc8a1, 0x0c7c,
+ 0xc940, 0x46a9,
+ 0xc94f, 0x234d,
+ 0xc950, 0x2348,
+ 0xc951, 0x46b8,
+ 0xc96e, 0x1e60,
+ 0xc96f, 0x46d5,
+ 0xc970, 0x2345,
+ 0xc971, 0x46d6,
+ 0xc977, 0x1f12,
+ 0xc978, 0x46dc,
+ 0xc980, 0x46e3,
+ 0xc98f, 0x2018,
+ 0xc990, 0x2335,
+ 0xc991, 0x46f2,
+ 0xc99c, 0x233c,
+ 0xc99d, 0x46fd,
+ 0xc9a1, 0x0cda,
+ 0xca40, 0x4701,
+ 0xca4e, 0x266f,
+ 0xca4f, 0x470f,
+ 0xca56, 0x2351,
+ 0xca57, 0x4716,
+ 0xca59, 0x1fa0,
+ 0xca5a, 0x4718,
+ 0xca5c, 0x2338,
+ 0xca5d, 0x471a,
+ 0xca61, 0x221b,
+ 0xca62, 0x471e,
+ 0xca6e, 0x2342,
+ 0xca6f, 0x472a,
+ 0xca72, 0x234f,
+ 0xca73, 0x472d,
+ 0xca77, 0x233d,
+ 0xca78, 0x4731,
+ 0xca7b, 0x2344,
+ 0xca7c, 0x2331,
+ 0xca7d, 0x4734,
+ 0xca7e, 0x234b,
+ 0xca80, 0x4735,
+ 0xca81, 0x233b,
+ 0xca82, 0x4736,
+ 0xca89, 0x2350,
+ 0xca8a, 0x473d,
+ 0xca8e, 0x1eb4,
+ 0xca8f, 0x21a6,
+ 0xca90, 0x4741,
+ 0xca92, 0x21cb,
+ 0xca93, 0x4743,
+ 0xca9a, 0x2355,
+ 0xca9b, 0x474a,
+ 0xcaa1, 0x0d38,
+ 0xcb40, 0x4750,
+ 0xcb43, 0x233e,
+ 0xcb44, 0x4753,
+ 0xcb45, 0x1f74,
+ 0xcb46, 0x4754,
+ 0xcb47, 0x2330,
+ 0xcb48, 0x4755,
+ 0xcb4b, 0x2680,
+ 0xcb4c, 0x4758,
+ 0xcb4e, 0x20da,
+ 0xcb4f, 0x475a,
+ 0xcb57, 0x234a,
+ 0xcb58, 0x4762,
+ 0xcb5d, 0x1f91,
+ 0xcb5e, 0x4767,
+ 0xcb5f, 0x2107,
+ 0xcb60, 0x4768,
+ 0xcb6a, 0x233f,
+ 0xcb6b, 0x4772,
+ 0xcb7b, 0x1ff4,
+ 0xcb7c, 0x2343,
+ 0xcb7d, 0x4782,
+ 0xcb80, 0x4784,
+ 0xcb87, 0x2212,
+ 0xcb88, 0x478b,
+ 0xcb8e, 0x2207,
+ 0xcb8f, 0x4791,
+ 0xcb92, 0x2359,
+ 0xcb93, 0x4794,
+ 0xcb9c, 0x2254,
+ 0xcb9d, 0x479d,
+ 0xcb9e, 0x2332,
+ 0xcb9f, 0x479e,
+ 0xcba1, 0x0d96,
+ 0xcc40, 0x1e26,
+ 0xcc41, 0x2357,
+ 0xcc42, 0x47a0,
+ 0xcc49, 0x2358,
+ 0xcc4a, 0x2042,
+ 0xcc4b, 0x2153,
+ 0xcc4c, 0x47a7,
+ 0xcc4f, 0x20bb,
+ 0xcc50, 0x47aa,
+ 0xcc5c, 0x235a,
+ 0xcc5d, 0x47b6,
+ 0xcc60, 0x2356,
+ 0xcc61, 0x47b9,
+ 0xcc64, 0x2337,
+ 0xcc65, 0x47bc,
+ 0xcc6d, 0x1ff9,
+ 0xcc6e, 0x47c4,
+ 0xcc79, 0x2353,
+ 0xcc7a, 0x47cf,
+ 0xcc7d, 0x2061,
+ 0xcc7e, 0x47d2,
+ 0xcc80, 0x47d3,
+ 0xcc8e, 0x1e95,
+ 0xcc8f, 0x47e1,
+ 0xcc94, 0x2049,
+ 0xcc95, 0x47e6,
+ 0xcc96, 0x1f42,
+ 0xcc97, 0x47e7,
+ 0xcc9d, 0x1fe8,
+ 0xcc9e, 0x47ed,
+ 0xcca1, 0x0df4,
+ 0xcd40, 0x47f0,
+ 0xcd80, 0x482f,
+ 0xcd90, 0x25da,
+ 0xcd91, 0x483f,
+ 0xcd98, 0x25d7,
+ 0xcd99, 0x4846,
+ 0xcda1, 0x0e52,
+ 0xce40, 0x484e,
+ 0xce67, 0x212e,
+ 0xce68, 0x4875,
+ 0xce72, 0x21b2,
+ 0xce73, 0x487f,
+ 0xce80, 0x488b,
+ 0xce81, 0x219e,
+ 0xce82, 0x488c,
+ 0xce87, 0x25dc,
+ 0xce88, 0x4891,
+ 0xce9b, 0x206c,
+ 0xce9c, 0x48a4,
+ 0xce9e, 0x2226,
+ 0xce9f, 0x48a6,
+ 0xcea1, 0x0eb0,
+ 0xcf40, 0x48a8,
+ 0xcf4e, 0x25e0,
+ 0xcf4f, 0x48b6,
+ 0xcf55, 0x227b,
+ 0xcf56, 0x48bc,
+ 0xcf58, 0x25de,
+ 0xcf59, 0x48be,
+ 0xcf5c, 0x25e1,
+ 0xcf5d, 0x48c1,
+ 0xcf6c, 0x25d5,
+ 0xcf6d, 0x48d0,
+ 0xcf73, 0x1e6b,
+ 0xcf74, 0x48d6,
+ 0xcf75, 0x25db,
+ 0xcf76, 0x48d7,
+ 0xcf78, 0x1e89,
+ 0xcf79, 0x48d9,
+ 0xcf7c, 0x25d9,
+ 0xcf7d, 0x48dc,
+ 0xcf80, 0x48de,
+ 0xcf81, 0x2211,
+ 0xcf82, 0x48df,
+ 0xcf89, 0x2229,
+ 0xcf8a, 0x25d6,
+ 0xcf8b, 0x48e6,
+ 0xcf93, 0x25dd,
+ 0xcf94, 0x25df,
+ 0xcf95, 0x48ee,
+ 0xcf9e, 0x1fef,
+ 0xcf9f, 0x48f7,
+ 0xcfa0, 0x25d8,
+ 0xcfa1, 0x0f0e,
+ 0xd040, 0x48f8,
+ 0xd04d, 0x1f29,
+ 0xd04e, 0x4905,
+ 0xd051, 0x1e5b,
+ 0xd052, 0x4908,
+ 0xd055, 0x2076,
+ 0xd056, 0x490b,
+ 0xd05c, 0x2297,
+ 0xd05d, 0x4911,
+ 0xd060, 0x2690,
+ 0xd061, 0x4914,
+ 0xd067, 0x213f,
+ 0xd068, 0x491a,
+ 0xd06c, 0x2198,
+ 0xd06d, 0x491e,
+ 0xd06e, 0x1e88,
+ 0xd06f, 0x491f,
+ 0xd07d, 0x228c,
+ 0xd07e, 0x492d,
+ 0xd080, 0x492e,
+ 0xd0a1, 0x0f6c,
+ 0xd140, 0x494f,
+ 0xd155, 0x25f1,
+ 0xd156, 0x4964,
+ 0xd159, 0x200c,
+ 0xd15a, 0x4967,
+ 0xd161, 0x1e58,
+ 0xd162, 0x22ac,
+ 0xd163, 0x496e,
+ 0xd175, 0x26a7,
+ 0xd176, 0x4980,
+ 0xd17d, 0x2676,
+ 0xd17e, 0x4987,
+ 0xd180, 0x4988,
+ 0xd19d, 0x1fe1,
+ 0xd19e, 0x25bb,
+ 0xd19f, 0x49a5,
+ 0xd1a1, 0x0fca,
+ 0xd240, 0x25be,
+ 0xd241, 0x49a7,
+ 0xd243, 0x22dd,
+ 0xd244, 0x49a9,
+ 0xd24d, 0x25bd,
+ 0xd24e, 0x49b2,
+ 0xd25c, 0x1e2a,
+ 0xd25d, 0x49c0,
+ 0xd263, 0x25bc,
+ 0xd264, 0x25ba,
+ 0xd265, 0x49c6,
+ 0xd268, 0x25bf,
+ 0xd269, 0x49c9,
+ 0xd26d, 0x2187,
+ 0xd26e, 0x49cd,
+ 0xd26f, 0x266b,
+ 0xd270, 0x49ce,
+ 0xd272, 0x1e7f,
+ 0xd273, 0x49d0,
+ 0xd275, 0x21ad,
+ 0xd276, 0x49d2,
+ 0xd280, 0x49db,
+ 0xd28a, 0x1f96,
+ 0xd28b, 0x49e5,
+ 0xd28e, 0x1f32,
+ 0xd28f, 0x49e8,
+ 0xd292, 0x2084,
+ 0xd293, 0x49eb,
+ 0xd295, 0x2136,
+ 0xd296, 0x49ed,
+ 0xd297, 0x24b8,
+ 0xd298, 0x49ee,
+ 0xd2a0, 0x24ba,
+ 0xd2a1, 0x1028,
+ 0xd340, 0x49f6,
+ 0xd344, 0x24bc,
+ 0xd345, 0x49fa,
+ 0xd348, 0x20e4,
+ 0xd349, 0x49fd,
+ 0xd34a, 0x24b9,
+ 0xd34b, 0x49fe,
+ 0xd34d, 0x24bd,
+ 0xd34e, 0x4a00,
+ 0xd350, 0x24be,
+ 0xd351, 0x4a02,
+ 0xd355, 0x24bf,
+ 0xd356, 0x4a06,
+ 0xd358, 0x1fd2,
+ 0xd359, 0x4a08,
+ 0xd35b, 0x1ffd,
+ 0xd35c, 0x4a0a,
+ 0xd35d, 0x24bb,
+ 0xd35e, 0x1f2d,
+ 0xd35f, 0x4a0b,
+ 0xd378, 0x2609,
+ 0xd379, 0x4a24,
+ 0xd37a, 0x260a,
+ 0xd37b, 0x4a25,
+ 0xd37c, 0x1e94,
+ 0xd37d, 0x4a26,
+ 0xd380, 0x4a28,
+ 0xd385, 0x22df,
+ 0xd386, 0x1ecb,
+ 0xd387, 0x1f0d,
+ 0xd388, 0x4a2d,
+ 0xd38b, 0x1f77,
+ 0xd38c, 0x4a30,
+ 0xd38d, 0x21eb,
+ 0xd38e, 0x4a31,
+ 0xd38f, 0x22e1,
+ 0xd390, 0x4a32,
+ 0xd391, 0x216f,
+ 0xd392, 0x4a33,
+ 0xd393, 0x22e0,
+ 0xd394, 0x4a34,
+ 0xd396, 0x21ea,
+ 0xd397, 0x4a36,
+ 0xd398, 0x22e2,
+ 0xd399, 0x20cb,
+ 0xd39a, 0x4a37,
+ 0xd39b, 0x1f78,
+ 0xd39c, 0x4a38,
+ 0xd39e, 0x1ee2,
+ 0xd39f, 0x4a3a,
+ 0xd3a0, 0x21f2,
+ 0xd3a1, 0x1086,
+ 0xd440, 0x4a3b,
+ 0xd441, 0x2150,
+ 0xd442, 0x4a3c,
+ 0xd445, 0x1fd3,
+ 0xd446, 0x4a3f,
+ 0xd447, 0x22e5,
+ 0xd448, 0x4a40,
+ 0xd44c, 0x1ef2,
+ 0xd44d, 0x4a44,
+ 0xd44f, 0x211f,
+ 0xd450, 0x4a46,
+ 0xd453, 0x21dd,
+ 0xd454, 0x4a49,
+ 0xd456, 0x2154,
+ 0xd457, 0x4a4b,
+ 0xd458, 0x22e7,
+ 0xd459, 0x4a4c,
+ 0xd45c, 0x2282,
+ 0xd45d, 0x4a4f,
+ 0xd462, 0x22e6,
+ 0xd463, 0x4a54,
+ 0xd467, 0x22e8,
+ 0xd468, 0x4a58,
+ 0xd46e, 0x22e4,
+ 0xd46f, 0x4a5e,
+ 0xd470, 0x226a,
+ 0xd471, 0x4a5f,
+ 0xd472, 0x22eb,
+ 0xd473, 0x4a60,
+ 0xd474, 0x22e9,
+ 0xd475, 0x20bd,
+ 0xd476, 0x4a61,
+ 0xd478, 0x22ea,
+ 0xd479, 0x4a63,
+ 0xd47b, 0x22bd,
+ 0xd47c, 0x4a65,
+ 0xd47e, 0x1e9e,
+ 0xd480, 0x4a67,
+ 0xd482, 0x22f6,
+ 0xd483, 0x21e7,
+ 0xd484, 0x2216,
+ 0xd485, 0x4a69,
+ 0xd487, 0x2137,
+ 0xd488, 0x4a6b,
+ 0xd48a, 0x212c,
+ 0xd48b, 0x4a6d,
+ 0xd48c, 0x1e68,
+ 0xd48d, 0x22f2,
+ 0xd48e, 0x1f37,
+ 0xd48f, 0x22f3,
+ 0xd490, 0x4a6e,
+ 0xd491, 0x22ef,
+ 0xd492, 0x1f50,
+ 0xd493, 0x1f10,
+ 0xd494, 0x21c8,
+ 0xd495, 0x4a6f,
+ 0xd496, 0x22f1,
+ 0xd497, 0x4a70,
+ 0xd49c, 0x22f0,
+ 0xd49d, 0x4a75,
+ 0xd49f, 0x22ee,
+ 0xd4a0, 0x4a77,
+ 0xd4a1, 0x10e4,
+ 0xd540, 0x4a78,
+ 0xd543, 0x22ed,
+ 0xd544, 0x229e,
+ 0xd545, 0x22ec,
+ 0xd546, 0x1fe2,
+ 0xd547, 0x4a7b,
+ 0xd54a, 0x20fe,
+ 0xd54b, 0x4a7e,
+ 0xd54e, 0x22f9,
+ 0xd550, 0x4a81,
+ 0xd551, 0x1eaf,
+ 0xd552, 0x4a82,
+ 0xd554, 0x2236,
+ 0xd555, 0x4a84,
+ 0xd556, 0x22f7,
+ 0xd557, 0x4a85,
+ 0xd55a, 0x223d,
+ 0xd55b, 0x4a88,
+ 0xd55c, 0x1e82,
+ 0xd55d, 0x1fb6,
+ 0xd55e, 0x4a89,
+ 0xd55f, 0x21a4,
+ 0xd560, 0x21aa,
+ 0xd561, 0x22f8,
+ 0xd562, 0x2151,
+ 0xd563, 0x4a8a,
+ 0xd564, 0x1f60,
+ 0xd565, 0x4a8b,
+ 0xd568, 0x2147,
+ 0xd569, 0x4a8e,
+ 0xd56c, 0x2145,
+ 0xd56d, 0x4a91,
+ 0xd56e, 0x1fdc,
+ 0xd56f, 0x4a92,
+ 0xd572, 0x2301,
+ 0xd573, 0x4a95,
+ 0xd575, 0x1ef5,
+ 0xd576, 0x4a97,
+ 0xd578, 0x2218,
+ 0xd579, 0x4a99,
+ 0xd57b, 0x1ec6,
+ 0xd57c, 0x4a9b,
+ 0xd57e, 0x2300,
+ 0xd580, 0x4a9d,
+ 0xd581, 0x22b4,
+ 0xd582, 0x4a9e,
+ 0xd584, 0x2169,
+ 0xd585, 0x4aa0,
+ 0xd586, 0x22fd,
+ 0xd587, 0x4aa1,
+ 0xd588, 0x20ea,
+ 0xd589, 0x4aa2,
+ 0xd58a, 0x22f4,
+ 0xd58b, 0x4aa3,
+ 0xd58c, 0x22fb,
+ 0xd58d, 0x4aa4,
+ 0xd58e, 0x22fc,
+ 0xd58f, 0x2027,
+ 0xd590, 0x4aa5,
+ 0xd593, 0x2060,
+ 0xd594, 0x22ff,
+ 0xd595, 0x4aa8,
+ 0xd598, 0x22fe,
+ 0xd599, 0x1ec7,
+ 0xd59a, 0x4aab,
+ 0xd59b, 0x230c,
+ 0xd59c, 0x4aac,
+ 0xd59f, 0x22f5,
+ 0xd5a0, 0x4aaf,
+ 0xd5a1, 0x1142,
+ 0xd640, 0x2306,
+ 0xd641, 0x4ab0,
+ 0xd642, 0x230a,
+ 0xd643, 0x21d3,
+ 0xd644, 0x4ab1,
+ 0xd647, 0x2303,
+ 0xd648, 0x4ab4,
+ 0xd649, 0x2307,
+ 0xd64a, 0x230b,
+ 0xd64b, 0x4ab5,
+ 0xd64d, 0x1f5f,
+ 0xd64e, 0x4ab7,
+ 0xd64f, 0x2309,
+ 0xd650, 0x4ab8,
+ 0xd652, 0x2302,
+ 0xd653, 0x1f04,
+ 0xd654, 0x229d,
+ 0xd655, 0x4aba,
+ 0xd656, 0x21fb,
+ 0xd657, 0x4abb,
+ 0xd658, 0x2308,
+ 0xd659, 0x4abc,
+ 0xd65a, 0x20ac,
+ 0xd65b, 0x4abd,
+ 0xd65c, 0x208e,
+ 0xd65d, 0x2305,
+ 0xd65e, 0x2197,
+ 0xd65f, 0x4abe,
+ 0xd660, 0x2171,
+ 0xd661, 0x2298,
+ 0xd662, 0x4abf,
+ 0xd665, 0x1f57,
+ 0xd666, 0x4ac2,
+ 0xd669, 0x2082,
+ 0xd66a, 0x4ac5,
+ 0xd66b, 0x2311,
+ 0xd66c, 0x4ac6,
+ 0xd66f, 0x2304,
+ 0xd670, 0x4ac9,
+ 0xd671, 0x230f,
+ 0xd672, 0x1e35,
+ 0xd673, 0x4aca,
+ 0xd674, 0x20d1,
+ 0xd675, 0x2310,
+ 0xd676, 0x1fa3,
+ 0xd677, 0x4acb,
+ 0xd678, 0x21d6,
+ 0xd679, 0x4acc,
+ 0xd67c, 0x2206,
+ 0xd67d, 0x4acf,
+ 0xd680, 0x4ad1,
+ 0xd683, 0x230d,
+ 0xd684, 0x4ad4,
+ 0xd686, 0x2312,
+ 0xd687, 0x208d,
+ 0xd688, 0x2313,
+ 0xd689, 0x4ad6,
+ 0xd68e, 0x22e3,
+ 0xd68f, 0x4adb,
+ 0xd694, 0x1fba,
+ 0xd695, 0x4ae0,
+ 0xd699, 0x2078,
+ 0xd69a, 0x4ae4,
+ 0xd6a1, 0x11a0,
+ 0xd740, 0x4aeb,
+ 0xd743, 0x2288,
+ 0xd744, 0x4aee,
+ 0xd748, 0x2316,
+ 0xd749, 0x1f6b,
+ 0xd74a, 0x4af2,
+ 0xd750, 0x2314,
+ 0xd751, 0x4af8,
+ 0xd752, 0x2130,
+ 0xd753, 0x2315,
+ 0xd754, 0x2168,
+ 0xd755, 0x4af9,
+ 0xd756, 0x20c4,
+ 0xd757, 0x4afa,
+ 0xd764, 0x2318,
+ 0xd765, 0x4b07,
+ 0xd767, 0x2219,
+ 0xd768, 0x2217,
+ 0xd769, 0x4b09,
+ 0xd76c, 0x20d5,
+ 0xd76d, 0x4b0c,
+ 0xd76f, 0x1f4a,
+ 0xd770, 0x4b0e,
+ 0xd775, 0x2240,
+ 0xd776, 0x4b13,
+ 0xd778, 0x1ed3,
+ 0xd779, 0x4b15,
+ 0xd780, 0x4b1b,
+ 0xd783, 0x1e49,
+ 0xd784, 0x4b1e,
+ 0xd787, 0x261b,
+ 0xd788, 0x4b21,
+ 0xd78b, 0x1e6d,
+ 0xd78c, 0x20f8,
+ 0xd78d, 0x4b24,
+ 0xd78e, 0x1ffb,
+ 0xd78f, 0x2319,
+ 0xd790, 0x4b25,
+ 0xd795, 0x230e,
+ 0xd796, 0x4b2a,
+ 0xd797, 0x2317,
+ 0xd798, 0x4b2b,
+ 0xd7a1, 0x11fe,
+ 0xd840, 0x4b34,
+ 0xd84d, 0x20c8,
+ 0xd84e, 0x4b41,
+ 0xd853, 0x1efd,
+ 0xd854, 0x4b46,
+ 0xd880, 0x4b71,
+ 0xd890, 0x1e3b,
+ 0xd891, 0x227f,
+ 0xd892, 0x4b81,
+ 0xd893, 0x1f0c,
+ 0xd894, 0x1e59,
+ 0xd895, 0x1f24,
+ 0xd896, 0x4b82,
+ 0xd89a, 0x20ba,
+ 0xd89b, 0x1f65,
+ 0xd89c, 0x1ef0,
+ 0xd89d, 0x2164,
+ 0xd89e, 0x1f30,
+ 0xd89f, 0x2261,
+ 0xd8a0, 0x4b86,
+ 0xd8a1, 0x1257,
+ 0xd940, 0x4b87,
+ 0xd941, 0x22a2,
+ 0xd942, 0x24ab,
+ 0xd943, 0x4b88,
+ 0xd944, 0x24af,
+ 0xd945, 0x1ee8,
+ 0xd946, 0x1f39,
+ 0xd947, 0x4b89,
+ 0xd948, 0x1e48,
+ 0xd949, 0x2070,
+ 0xd94a, 0x1ea8,
+ 0xd94b, 0x4b8a,
+ 0xd94c, 0x24ac,
+ 0xd94d, 0x1ef7,
+ 0xd94e, 0x2176,
+ 0xd94f, 0x24ad,
+ 0xd950, 0x4b8b,
+ 0xd951, 0x207b,
+ 0xd952, 0x1f45,
+ 0xd953, 0x24aa,
+ 0xd954, 0x204b,
+ 0xd955, 0x202f,
+ 0xd956, 0x1f5a,
+ 0xd957, 0x24b0,
+ 0xd958, 0x4b8c,
+ 0xd959, 0x22b7,
+ 0xd95a, 0x1f7f,
+ 0xd95b, 0x4b8d,
+ 0xd95c, 0x2265,
+ 0xd95d, 0x4b8e,
+ 0xd963, 0x24b2,
+ 0xd964, 0x211b,
+ 0xd965, 0x1e51,
+ 0xd966, 0x4b94,
+ 0xd967, 0x24b4,
+ 0xd968, 0x4b95,
+ 0xd96c, 0x24b3,
+ 0xd96d, 0x4b99,
+ 0xd96e, 0x1e9f,
+ 0xd96f, 0x4b9a,
+ 0xd970, 0x2118,
+ 0xd971, 0x4b9b,
+ 0xd972, 0x20b4,
+ 0xd973, 0x23af,
+ 0xd974, 0x21bb,
+ 0xd975, 0x2072,
+ 0xd976, 0x1f95,
+ 0xd977, 0x4b9c,
+ 0xd978, 0x1f0a,
+ 0xd979, 0x24b6,
+ 0xd97a, 0x4b9d,
+ 0xd97c, 0x2291,
+ 0xd97d, 0x24b5,
+ 0xd97e, 0x2278,
+ 0xd980, 0x1ed4,
+ 0xd981, 0x4b9f,
+ 0xd987, 0x1ff3,
+ 0xd988, 0x4ba5,
+ 0xd98d, 0x22a9,
+ 0xd98e, 0x24b7,
+ 0xd98f, 0x1f28,
+ 0xd990, 0x2109,
+ 0xd991, 0x22c7,
+ 0xd992, 0x4baa,
+ 0xd997, 0x24ae,
+ 0xd998, 0x22b1,
+ 0xd999, 0x4baf,
+ 0xd99b, 0x2266,
+ 0xd99c, 0x4bb1,
+ 0xd99d, 0x225b,
+ 0xd99e, 0x22c4,
+ 0xd99f, 0x4bb2,
+ 0xd9a0, 0x2115,
+ 0xd9a1, 0x12b5,
+ 0xda40, 0x4bb3,
+ 0xda41, 0x222a,
+ 0xda42, 0x24b1,
+ 0xda43, 0x4bb4,
+ 0xda48, 0x213d,
+ 0xda49, 0x4bb9,
+ 0xda4d, 0x1f15,
+ 0xda4e, 0x225c,
+ 0xda4f, 0x4bbd,
+ 0xda73, 0x1f14,
+ 0xda74, 0x4be1,
+ 0xda77, 0x227a,
+ 0xda78, 0x4be4,
+ 0xda80, 0x4beb,
+ 0xda85, 0x20ee,
+ 0xda86, 0x4bf0,
+ 0xda8e, 0x25f8,
+ 0xda8f, 0x4bf8,
+ 0xdaa1, 0x1313,
+ 0xdb40, 0x4c0a,
+ 0xdb60, 0x1f94,
+ 0xdb61, 0x4c2a,
+ 0xdb78, 0x2230,
+ 0xdb79, 0x4c41,
+ 0xdb80, 0x4c47,
+ 0xdb84, 0x25fd,
+ 0xdb85, 0x4c4b,
+ 0xdb8b, 0x2600,
+ 0xdb8c, 0x4c51,
+ 0xdb98, 0x2606,
+ 0xdb99, 0x4c5d,
+ 0xdba1, 0x1371,
+ 0xdc40, 0x4c65,
+ 0xdc45, 0x25ff,
+ 0xdc46, 0x4c6a,
+ 0xdc4f, 0x25fc,
+ 0xdc50, 0x1e8c,
+ 0xdc51, 0x2602,
+ 0xdc52, 0x4c73,
+ 0xdc53, 0x224d,
+ 0xdc54, 0x4c74,
+ 0xdc55, 0x2604,
+ 0xdc56, 0x25fe,
+ 0xdc57, 0x2603,
+ 0xdc58, 0x4c75,
+ 0xdc5d, 0x2601,
+ 0xdc5e, 0x4c7a,
+ 0xdc62, 0x2605,
+ 0xdc63, 0x4c7e,
+ 0xdc66, 0x1ea3,
+ 0xdc67, 0x2608,
+ 0xdc68, 0x4c81,
+ 0xdc6b, 0x2607,
+ 0xdc6c, 0x4c84,
+ 0xdc7c, 0x20f0,
+ 0xdc7d, 0x4c94,
+ 0xdc80, 0x4c96,
+ 0xdc87, 0x1e7b,
+ 0xdc88, 0x2267,
+ 0xdc89, 0x1f36,
+ 0xdc8a, 0x1fd6,
+ 0xdc8b, 0x4c9d,
+ 0xdc8e, 0x21e0,
+ 0xdc8f, 0x4ca0,
+ 0xdc90, 0x248c,
+ 0xdc91, 0x4ca1,
+ 0xdc97, 0x248d,
+ 0xdc98, 0x4ca7,
+ 0xdc9b, 0x2102,
+ 0xdc9c, 0x4caa,
+ 0xdca0, 0x2494,
+ 0xdca1, 0x13cf,
+ 0xdd40, 0x4cae,
+ 0xdd46, 0x2493,
+ 0xdd47, 0x4cb4,
+ 0xdd4d, 0x248e,
+ 0xdd4e, 0x4cba,
+ 0xdd53, 0x2299,
+ 0xdd54, 0x2491,
+ 0xdd55, 0x2496,
+ 0xdd56, 0x248f,
+ 0xdd57, 0x2492,
+ 0xdd58, 0x4cbf,
+ 0xdd59, 0x2497,
+ 0xdd5a, 0x4cc0,
+ 0xdd5e, 0x1fb1,
+ 0xdd5f, 0x4cc4,
+ 0xdd60, 0x249a,
+ 0xdd61, 0x4cc5,
+ 0xdd62, 0x2499,
+ 0xdd63, 0x4cc6,
+ 0xdd64, 0x2258,
+ 0xdd65, 0x2498,
+ 0xdd66, 0x4cc7,
+ 0xdd6d, 0x249b,
+ 0xdd6e, 0x4cce,
+ 0xdd6f, 0x1f09,
+ 0xdd70, 0x20e6,
+ 0xdd71, 0x4ccf,
+ 0xdd76, 0x2026,
+ 0xdd77, 0x249f,
+ 0xdd78, 0x1f59,
+ 0xdd79, 0x249d,
+ 0xdd7b, 0x4cd4,
+ 0xdd80, 0x4cd8,
+ 0xdd81, 0x1f3b,
+ 0xdd82, 0x249c,
+ 0xdd83, 0x4cd9,
+ 0xdd85, 0x1e3a,
+ 0xdd86, 0x205b,
+ 0xdd87, 0x4cdb,
+ 0xdd8b, 0x1f70,
+ 0xdd8c, 0x4cdf,
+ 0xdd8f, 0x24a0,
+ 0xdd90, 0x4ce2,
+ 0xdd94, 0x213b,
+ 0xdd95, 0x4ce6,
+ 0xdd97, 0x1f07,
+ 0xdd98, 0x4ce8,
+ 0xdd9a, 0x2270,
+ 0xdd9b, 0x2237,
+ 0xdd9c, 0x4cea,
+ 0xdd9e, 0x24d2,
+ 0xdd9f, 0x4cec,
+ 0xdda0, 0x21b3,
+ 0xdda1, 0x142d,
+ 0xde40, 0x2245,
+ 0xde41, 0x24a1,
+ 0xde42, 0x4ced,
+ 0xde44, 0x22a8,
+ 0xde45, 0x4cef,
+ 0xde48, 0x227c,
+ 0xde49, 0x1fb0,
+ 0xde4a, 0x4cf2,
+ 0xde4f, 0x24a2,
+ 0xde50, 0x4cf7,
+ 0xde5a, 0x1f46,
+ 0xde5b, 0x4d01,
+ 0xde5c, 0x2380,
+ 0xde5d, 0x2495,
+ 0xde5e, 0x4d02,
+ 0xde5f, 0x2490,
+ 0xde60, 0x4d03,
+ 0xde6b, 0x1e30,
+ 0xde6c, 0x4d0e,
+ 0xde6f, 0x1e9d,
+ 0xde70, 0x1e4b,
+ 0xde71, 0x1e4a,
+ 0xde72, 0x20aa,
+ 0xde73, 0x4d11,
+ 0xde80, 0x4d1d,
+ 0xde92, 0x267b,
+ 0xde93, 0x4d2f,
+ 0xde9f, 0x23f2,
+ 0xdea0, 0x4d3b,
+ 0xdea1, 0x148b,
+ 0xdf40, 0x227e,
+ 0xdf41, 0x4d3c,
+ 0xdf42, 0x2019,
+ 0xdf43, 0x4d3d,
+ 0xdf4d, 0x1fbb,
+ 0xdf4e, 0x4d47,
+ 0xdf5c, 0x2253,
+ 0xdf5d, 0x4d55,
+ 0xdf5e, 0x1f3e,
+ 0xdf5f, 0x1ea6,
+ 0xdf60, 0x218e,
+ 0xdf61, 0x4d56,
+ 0xdf64, 0x21ec,
+ 0xdf65, 0x4d59,
+ 0xdf66, 0x1ebe,
+ 0xdf67, 0x4d5a,
+ 0xdf68, 0x224a,
+ 0xdf69, 0x4d5b,
+ 0xdf6d, 0x2133,
+ 0xdf6e, 0x4d5f,
+ 0xdf74, 0x1e84,
+ 0xdf75, 0x4d65,
+ 0xdf77, 0x20cf,
+ 0xdf78, 0x21e2,
+ 0xdf79, 0x4d67,
+ 0xdf7a, 0x220f,
+ 0xdf7b, 0x4d68,
+ 0xdf7c, 0x2029,
+ 0xdf7d, 0x4d69,
+ 0xdf7e, 0x2073,
+ 0xdf80, 0x1f55,
+ 0xdf81, 0x4d6a,
+ 0xdf83, 0x23f1,
+ 0xdf84, 0x4d6c,
+ 0xdf85, 0x1e46,
+ 0xdf86, 0x4d6d,
+ 0xdf89, 0x2063,
+ 0xdf8a, 0x23f3,
+ 0xdf8b, 0x4d70,
+ 0xdfa1, 0x14e9,
+ 0xe040, 0x4d86,
+ 0xe050, 0x231e,
+ 0xe051, 0x4d96,
+ 0xe05d, 0x2233,
+ 0xe05e, 0x4da2,
+ 0xe069, 0x2320,
+ 0xe06a, 0x4dad,
+ 0xe06c, 0x21c7,
+ 0xe06d, 0x4daf,
+ 0xe075, 0x22bc,
+ 0xe076, 0x4db7,
+ 0xe077, 0x231c,
+ 0xe078, 0x4db8,
+ 0xe079, 0x2251,
+ 0xe07a, 0x4db9,
+ 0xe080, 0x4dbe,
+ 0xe087, 0x1ebb,
+ 0xe088, 0x4dc5,
+ 0xe08d, 0x2287,
+ 0xe08e, 0x4dca,
+ 0xe08f, 0x202d,
+ 0xe090, 0x1eab,
+ 0xe091, 0x4dcb,
+ 0xe092, 0x231d,
+ 0xe093, 0x4dcc,
+ 0xe094, 0x231f,
+ 0xe095, 0x4dcd,
+ 0xe097, 0x231b,
+ 0xe098, 0x4dcf,
+ 0xe0a1, 0x1547,
+ 0xe140, 0x4dd8,
+ 0xe142, 0x2321,
+ 0xe143, 0x4dda,
+ 0xe164, 0x2255,
+ 0xe165, 0x4dfb,
+ 0xe168, 0x1e8f,
+ 0xe169, 0x4dfe,
+ 0xe174, 0x220c,
+ 0xe175, 0x1fa4,
+ 0xe176, 0x4e09,
+ 0xe180, 0x4e12,
+ 0xe184, 0x209b,
+ 0xe185, 0x21d8,
+ 0xe186, 0x4e16,
+ 0xe187, 0x25fa,
+ 0xe188, 0x4e17,
+ 0xe189, 0x25f9,
+ 0xe18a, 0x4e18,
+ 0xe18c, 0x2134,
+ 0xe18d, 0x4e1a,
+ 0xe18e, 0x24f3,
+ 0xe191, 0x24f8,
+ 0xe192, 0x4e1b,
+ 0xe193, 0x24f7,
+ 0xe194, 0x1ec8,
+ 0xe195, 0x24f6,
+ 0xe196, 0x4e1c,
+ 0xe198, 0x2280,
+ 0xe199, 0x4e1e,
+ 0xe19e, 0x1ec5,
+ 0xe19f, 0x24fb,
+ 0xe1a0, 0x4e23,
+ 0xe1a1, 0x15a5,
+ 0xe240, 0x4e24,
+ 0xe241, 0x24fa,
+ 0xe242, 0x4e25,
+ 0xe243, 0x1eed,
+ 0xe244, 0x4e26,
+ 0xe24f, 0x24fd,
+ 0xe250, 0x4e31,
+ 0xe251, 0x24f9,
+ 0xe252, 0x4e32,
+ 0xe253, 0x24fe,
+ 0xe254, 0x20cd,
+ 0xe255, 0x4e33,
+ 0xe25a, 0x2508,
+ 0xe25b, 0x2504,
+ 0xe25c, 0x4e38,
+ 0xe25e, 0x2506,
+ 0xe25f, 0x4e3a,
+ 0xe262, 0x24ff,
+ 0xe263, 0x2090,
+ 0xe264, 0x4e3d,
+ 0xe267, 0x1edd,
+ 0xe268, 0x1f25,
+ 0xe269, 0x4e40,
+ 0xe26a, 0x2503,
+ 0xe26b, 0x2502,
+ 0xe26c, 0x4e41,
+ 0xe26e, 0x1e7a,
+ 0xe26f, 0x20a6,
+ 0xe270, 0x4e43,
+ 0xe278, 0x1fd5,
+ 0xe279, 0x4e4b,
+ 0xe27d, 0x1f11,
+ 0xe27e, 0x4e4f,
+ 0xe280, 0x2507,
+ 0xe281, 0x2500,
+ 0xe282, 0x2505,
+ 0xe283, 0x4e50,
+ 0xe289, 0x2519,
+ 0xe28a, 0x4e56,
+ 0xe28b, 0x2515,
+ 0xe28c, 0x4e57,
+ 0xe28e, 0x250c,
+ 0xe28f, 0x2031,
+ 0xe290, 0x4e59,
+ 0xe292, 0x250b,
+ 0xe293, 0x250f,
+ 0xe294, 0x251a,
+ 0xe295, 0x2509,
+ 0xe296, 0x4e5b,
+ 0xe298, 0x250e,
+ 0xe299, 0x2234,
+ 0xe29a, 0x2513,
+ 0xe29b, 0x1f80,
+ 0xe29c, 0x4e5d,
+ 0xe2a0, 0x2501,
+ 0xe2a1, 0x1603,
+ 0xe340, 0x4e61,
+ 0xe342, 0x2517,
+ 0xe343, 0x2516,
+ 0xe344, 0x4e63,
+ 0xe347, 0x2518,
+ 0xe348, 0x4e66,
+ 0xe34b, 0x1e56,
+ 0xe34c, 0x4e69,
+ 0xe34f, 0x250d,
+ 0xe350, 0x4e6c,
+ 0xe351, 0x20d3,
+ 0xe352, 0x4e6d,
+ 0xe354, 0x207a,
+ 0xe355, 0x20ce,
+ 0xe356, 0x4e6f,
+ 0xe358, 0x2510,
+ 0xe359, 0x4e71,
+ 0xe35c, 0x1e55,
+ 0xe35d, 0x4e74,
+ 0xe360, 0x250a,
+ 0xe361, 0x4e77,
+ 0xe366, 0x2511,
+ 0xe368, 0x4e7c,
+ 0xe371, 0x1faa,
+ 0xe372, 0x4e85,
+ 0xe373, 0x251e,
+ 0xe374, 0x1f1f,
+ 0xe375, 0x4e86,
+ 0xe378, 0x252d,
+ 0xe379, 0x221d,
+ 0xe37a, 0x4e89,
+ 0xe37c, 0x2532,
+ 0xe37d, 0x4e8b,
+ 0xe37e, 0x217b,
+ 0xe380, 0x4e8c,
+ 0xe38a, 0x21af,
+ 0xe38b, 0x4e96,
+ 0xe38c, 0x252c,
+ 0xe38d, 0x4e97,
+ 0xe38f, 0x2528,
+ 0xe390, 0x4e99,
+ 0xe391, 0x208c,
+ 0xe392, 0x4e9a,
+ 0xe393, 0x252f,
+ 0xe394, 0x4e9b,
+ 0xe395, 0x21bc,
+ 0xe396, 0x4e9c,
+ 0xe399, 0x251d,
+ 0xe39a, 0x4e9f,
+ 0xe39c, 0x2535,
+ 0xe39d, 0x4ea1,
+ 0xe39e, 0x220d,
+ 0xe39f, 0x2526,
+ 0xe3a0, 0x4ea2,
+ 0xe3a1, 0x1661,
+ 0xe440, 0x2534,
+ 0xe441, 0x252a,
+ 0xe442, 0x251f,
+ 0xe443, 0x2531,
+ 0xe444, 0x251c,
+ 0xe445, 0x4ea3,
+ 0xe448, 0x2525,
+ 0xe449, 0x4ea6,
+ 0xe44e, 0x21cd,
+ 0xe44f, 0x4eab,
+ 0xe450, 0x21da,
+ 0xe451, 0x4eac,
+ 0xe452, 0x2172,
+ 0xe453, 0x253e,
+ 0xe454, 0x4ead,
+ 0xe458, 0x204f,
+ 0xe459, 0x4eb1,
+ 0xe45a, 0x2543,
+ 0xe45b, 0x4eb2,
+ 0xe45c, 0x21d7,
+ 0xe45d, 0x4eb3,
+ 0xe45e, 0x1e3c,
+ 0xe45f, 0x4eb4,
+ 0xe462, 0x2529,
+ 0xe463, 0x4eb7,
+ 0xe465, 0x2521,
+ 0xe466, 0x4eb9,
+ 0xe468, 0x1eff,
+ 0xe469, 0x4ebb,
+ 0xe473, 0x253f,
+ 0xe474, 0x4ec5,
+ 0xe475, 0x2544,
+ 0xe476, 0x4ec6,
+ 0xe479, 0x2523,
+ 0xe47a, 0x1e90,
+ 0xe47b, 0x253a,
+ 0xe47c, 0x2545,
+ 0xe47d, 0x4ec9,
+ 0xe47e, 0x253d,
+ 0xe480, 0x4eca,
+ 0xe481, 0x20c1,
+ 0xe482, 0x4ecb,
+ 0xe484, 0x2103,
+ 0xe485, 0x2520,
+ 0xe486, 0x253c,
+ 0xe487, 0x253b,
+ 0xe488, 0x2538,
+ 0xe489, 0x4ecd,
+ 0xe48d, 0x2540,
+ 0xe48e, 0x4ed1,
+ 0xe48f, 0x1fcd,
+ 0xe490, 0x4ed2,
+ 0xe493, 0x1f18,
+ 0xe494, 0x4ed5,
+ 0xe498, 0x254b,
+ 0xe499, 0x4ed9,
+ 0xe49d, 0x2547,
+ 0xe49e, 0x254f,
+ 0xe4a0, 0x4edd,
+ 0xe4a1, 0x16bf,
+ 0xe540, 0x4ede,
+ 0xe546, 0x22b0,
+ 0xe547, 0x4ee4,
+ 0xe548, 0x2546,
+ 0xe549, 0x4ee5,
+ 0xe54b, 0x254c,
+ 0xe54c, 0x4ee7,
+ 0xe54e, 0x1e9a,
+ 0xe54f, 0x2552,
+ 0xe550, 0x2530,
+ 0xe551, 0x2549,
+ 0xe552, 0x4ee9,
+ 0xe555, 0x2551,
+ 0xe556, 0x1eca,
+ 0xe557, 0x4eec,
+ 0xe558, 0x20d2,
+ 0xe559, 0x4eed,
+ 0xe55c, 0x1fb8,
+ 0xe55d, 0x4ef0,
+ 0xe55e, 0x2079,
+ 0xe55f, 0x4ef1,
+ 0xe561, 0x21ab,
+ 0xe562, 0x4ef3,
+ 0xe564, 0x254d,
+ 0xe565, 0x1ea5,
+ 0xe566, 0x4ef5,
+ 0xe568, 0x204c,
+ 0xe569, 0x2080,
+ 0xe56a, 0x4ef7,
+ 0xe56c, 0x266d,
+ 0xe56d, 0x4ef9,
+ 0xe56e, 0x2537,
+ 0xe56f, 0x4efa,
+ 0xe575, 0x254a,
+ 0xe576, 0x21b8,
+ 0xe577, 0x4f00,
+ 0xe578, 0x254e,
+ 0xe579, 0x4f01,
+ 0xe57b, 0x24fc,
+ 0xe57c, 0x2554,
+ 0xe57d, 0x4f03,
+ 0xe580, 0x4f05,
+ 0xe581, 0x1f3c,
+ 0xe582, 0x4f06,
+ 0xe583, 0x1ed5,
+ 0xe584, 0x4f07,
+ 0xe58a, 0x2556,
+ 0xe58b, 0x4f0d,
+ 0xe58e, 0x2268,
+ 0xe58f, 0x4f10,
+ 0xe591, 0x1ed6,
+ 0xe592, 0x4f12,
+ 0xe59a, 0x2557,
+ 0xe59b, 0x2553,
+ 0xe59c, 0x4f1a,
+ 0xe59f, 0x2548,
+ 0xe5a0, 0x4f1d,
+ 0xe5a1, 0x171d,
+ 0xe640, 0x20dc,
+ 0xe641, 0x4f1e,
+ 0xe644, 0x2559,
+ 0xe645, 0x4f21,
+ 0xe649, 0x1f97,
+ 0xe64a, 0x2555,
+ 0xe64b, 0x4f25,
+ 0xe64e, 0x227d,
+ 0xe64f, 0x4f28,
+ 0xe652, 0x257e,
+ 0xe653, 0x4f2b,
+ 0xe656, 0x207c,
+ 0xe657, 0x4f2e,
+ 0xe658, 0x255a,
+ 0xe659, 0x4f2f,
+ 0xe65b, 0x255e,
+ 0xe65c, 0x4f31,
+ 0xe65e, 0x1e34,
+ 0xe65f, 0x4f33,
+ 0xe669, 0x215e,
+ 0xe66a, 0x4f3d,
+ 0xe66b, 0x2560,
+ 0xe66c, 0x4f3e,
+ 0xe675, 0x21a2,
+ 0xe676, 0x2354,
+ 0xe677, 0x4f47,
+ 0xe679, 0x2563,
+ 0xe67a, 0x2527,
+ 0xe67b, 0x4f49,
+ 0xe67c, 0x252e,
+ 0xe67d, 0x2558,
+ 0xe67e, 0x4f4a,
+ 0xe680, 0x1f1b,
+ 0xe681, 0x4f4b,
+ 0xe682, 0x2283,
+ 0xe683, 0x4f4c,
+ 0xe684, 0x2564,
+ 0xe685, 0x4f4d,
+ 0xe687, 0x20a0,
+ 0xe688, 0x4f4f,
+ 0xe689, 0x2565,
+ 0xe68a, 0x4f50,
+ 0xe68c, 0x2561,
+ 0xe68d, 0x4f52,
+ 0xe693, 0x2562,
+ 0xe694, 0x4f58,
+ 0xe697, 0x256c,
+ 0xe698, 0x4f5b,
+ 0xe69b, 0x256d,
+ 0xe69c, 0x2020,
+ 0xe69d, 0x4f5e,
+ 0xe69f, 0x255f,
+ 0xe6a0, 0x256a,
+ 0xe6a1, 0x177b,
+ 0xe740, 0x4f60,
+ 0xe743, 0x256e,
+ 0xe744, 0x4f63,
+ 0xe748, 0x2539,
+ 0xe749, 0x255c,
+ 0xe74a, 0x4f67,
+ 0xe74d, 0x2568,
+ 0xe74f, 0x256b,
+ 0xe750, 0x1e6f,
+ 0xe751, 0x4f6a,
+ 0xe752, 0x1fc4,
+ 0xe753, 0x2567,
+ 0xe754, 0x4f6b,
+ 0xe755, 0x255b,
+ 0xe756, 0x4f6c,
+ 0xe759, 0x261d,
+ 0xe75a, 0x4f6f,
+ 0xe766, 0x252b,
+ 0xe767, 0x4f7b,
+ 0xe768, 0x2571,
+ 0xe769, 0x4f7c,
+ 0xe76a, 0x2577,
+ 0xe76b, 0x4f7d,
+ 0xe774, 0x2522,
+ 0xe775, 0x4f86,
+ 0xe77c, 0x2533,
+ 0xe77d, 0x4f8d,
+ 0xe780, 0x4f8f,
+ 0xe782, 0x202a,
+ 0xe783, 0x4f91,
+ 0xe784, 0x2536,
+ 0xe785, 0x2573,
+ 0xe786, 0x256f,
+ 0xe787, 0x4f92,
+ 0xe78a, 0x2293,
+ 0xe78b, 0x2578,
+ 0xe78c, 0x4f95,
+ 0xe78f, 0x2570,
+ 0xe790, 0x4f98,
+ 0xe792, 0x2575,
+ 0xe793, 0x4f9a,
+ 0xe798, 0x2541,
+ 0xe79a, 0x255d,
+ 0xe79b, 0x4f9f,
+ 0xe7a0, 0x201a,
+ 0xe7a1, 0x17d9,
+ 0xe840, 0x4fa4,
+ 0xe843, 0x257a,
+ 0xe844, 0x2006,
+ 0xe845, 0x4fa7,
+ 0xe846, 0x2177,
+ 0xe847, 0x4fa8,
+ 0xe849, 0x251b,
+ 0xe84a, 0x4faa,
+ 0xe84b, 0x2524,
+ 0xe84c, 0x4fab,
+ 0xe84f, 0x257b,
+ 0xe850, 0x4fae,
+ 0xe854, 0x22a3,
+ 0xe855, 0x4fb2,
+ 0xe85a, 0x2579,
+ 0xe85b, 0x4fb7,
+ 0xe85c, 0x2566,
+ 0xe85d, 0x4fb8,
+ 0xe862, 0x1f93,
+ 0xe863, 0x4fbd,
+ 0xe864, 0x257c,
+ 0xe865, 0x4fbe,
+ 0xe870, 0x2514,
+ 0xe871, 0x4fc9,
+ 0xe873, 0x257d,
+ 0xe874, 0x4fcb,
+ 0xe875, 0x2572,
+ 0xe876, 0x4fcc,
+ 0xe87c, 0x2574,
+ 0xe87d, 0x4fd2,
+ 0xe880, 0x224e,
+ 0xe881, 0x4fd4,
+ 0xe882, 0x21c6,
+ 0xe883, 0x4fd5,
+ 0xe887, 0x209f,
+ 0xe888, 0x4fd9,
+ 0xe889, 0x2576,
+ 0xe88a, 0x4fda,
+ 0xe88c, 0x2064,
+ 0xe88d, 0x22bf,
+ 0xe88e, 0x261c,
+ 0xe88f, 0x225e,
+ 0xe890, 0x4fdc,
+ 0xe8a1, 0x1837,
+ 0xe940, 0x4fed,
+ 0xe94c, 0x1e75,
+ 0xe94d, 0x4ff9,
+ 0xe954, 0x207d,
+ 0xe955, 0x5000,
+ 0xe956, 0x23bf,
+ 0xe957, 0x2113,
+ 0xe958, 0x5001,
+ 0xe95a, 0x23c0,
+ 0xe95b, 0x5003,
+ 0xe95d, 0x1e45,
+ 0xe95e, 0x5005,
+ 0xe95f, 0x1fd8,
+ 0xe960, 0x23c4,
+ 0xe961, 0x5006,
+ 0xe962, 0x23c2,
+ 0xe963, 0x2104,
+ 0xe964, 0x5007,
+ 0xe965, 0x21bd,
+ 0xe966, 0x5008,
+ 0xe967, 0x1f87,
+ 0xe968, 0x23c3,
+ 0xe969, 0x5009,
+ 0xe96c, 0x2269,
+ 0xe96d, 0x500c,
+ 0xe975, 0x1f43,
+ 0xe976, 0x5014,
+ 0xe977, 0x1f1e,
+ 0xe978, 0x2679,
+ 0xe979, 0x1eeb,
+ 0xe97a, 0x5015,
+ 0xe97c, 0x1f35,
+ 0xe97d, 0x208a,
+ 0xe97e, 0x5017,
+ 0xe980, 0x23c7,
+ 0xe981, 0x23c9,
+ 0xe982, 0x23c6,
+ 0xe983, 0x5018,
+ 0xe987, 0x224f,
+ 0xe988, 0x501c,
+ 0xe98b, 0x23cb,
+ 0xe98c, 0x501f,
+ 0xe98e, 0x21f3,
+ 0xe98f, 0x5021,
+ 0xe990, 0x21f7,
+ 0xe991, 0x23cf,
+ 0xe992, 0x23ce,
+ 0xe993, 0x23ca,
+ 0xe994, 0x23cd,
+ 0xe995, 0x5022,
+ 0xe998, 0x23d0,
+ 0xe999, 0x5025,
+ 0xe99b, 0x266c,
+ 0xe99c, 0x5027,
+ 0xe99d, 0x23c1,
+ 0xe99e, 0x5028,
+ 0xe99f, 0x1fee,
+ 0xe9a0, 0x23d1,
+ 0xe9a1, 0x1895,
+ 0xea40, 0x1ff8,
+ 0xea41, 0x5029,
+ 0xea44, 0x23d3,
+ 0xea45, 0x502c,
+ 0xea48, 0x23d2,
+ 0xea49, 0x23d4,
+ 0xea4a, 0x1e98,
+ 0xea4b, 0x502f,
+ 0xea50, 0x1f2c,
+ 0xea51, 0x5034,
+ 0xea52, 0x23d5,
+ 0xea53, 0x5035,
+ 0xea55, 0x1e71,
+ 0xea56, 0x2691,
+ 0xea57, 0x5037,
+ 0xea59, 0x23c5,
+ 0xea5a, 0x5039,
+ 0xea80, 0x231a,
+ 0xea81, 0x505e,
+ 0xea84, 0x2114,
+ 0xea85, 0x5061,
+ 0xea87, 0x2284,
+ 0xea88, 0x5063,
+ 0xea8e, 0x221c,
+ 0xea8f, 0x5069,
+ 0xea90, 0x1e7e,
+ 0xea91, 0x204d,
+ 0xea92, 0x506a,
+ 0xea96, 0x2201,
+ 0xea97, 0x506e,
+ 0xeaa0, 0x1ed9,
+ 0xeaa1, 0x18f3,
+ 0xeb40, 0x5077,
+ 0xeb41, 0x1fb2,
+ 0xeb42, 0x5078,
+ 0xeb45, 0x2252,
+ 0xeb46, 0x507b,
+ 0xeb48, 0x1f79,
+ 0xeb49, 0x507d,
+ 0xeb53, 0x2157,
+ 0xeb54, 0x5087,
+ 0xeb55, 0x21bf,
+ 0xeb56, 0x5088,
+ 0xeb5b, 0x221f,
+ 0xeb5c, 0x508d,
+ 0xeb5d, 0x203d,
+ 0xeb5e, 0x508e,
+ 0xeb60, 0x2015,
+ 0xeb61, 0x5090,
+ 0xeb62, 0x26a5,
+ 0xeb63, 0x5091,
+ 0xeb6d, 0x2156,
+ 0xeb6e, 0x509b,
+ 0xeb70, 0x2144,
+ 0xeb71, 0x509d,
+ 0xeb72, 0x1e91,
+ 0xeb73, 0x2257,
+ 0xeb74, 0x509e,
+ 0xeb78, 0x200a,
+ 0xeb79, 0x2092,
+ 0xeb7a, 0x50a2,
+ 0xeb80, 0x50a7,
+ 0xeb85, 0x2250,
+ 0xeb86, 0x50ac,
+ 0xeb8a, 0x1ec3,
+ 0xeb8b, 0x50b0,
+ 0xeba1, 0x1951,
+ 0xec40, 0x50c6,
+ 0xec46, 0x21a8,
+ 0xec47, 0x50cc,
+ 0xec56, 0x260d,
+ 0xec57, 0x50db,
+ 0xec5a, 0x260c,
+ 0xec5b, 0x50de,
+ 0xec5c, 0x260e,
+ 0xec5d, 0x50df,
+ 0xec60, 0x2032,
+ 0xec61, 0x50e2,
+ 0xec6e, 0x260b,
+ 0xec6f, 0x50ef,
+ 0xec76, 0x22c3,
+ 0xec77, 0x50f6,
+ 0xec80, 0x50fe,
+ 0xec96, 0x1f23,
+ 0xec97, 0x5114,
+ 0xeca1, 0x19af,
+ 0xed40, 0x511e,
+ 0xed46, 0x2695,
+ 0xed47, 0x5124,
+ 0xed58, 0x265e,
+ 0xed59, 0x5135,
+ 0xed5e, 0x265d,
+ 0xed5f, 0x513a,
+ 0xed61, 0x2692,
+ 0xed62, 0x513c,
+ 0xed64, 0x265f,
+ 0xed65, 0x513e,
+ 0xed66, 0x218d,
+ 0xed67, 0x20fd,
+ 0xed68, 0x513f,
+ 0xed6e, 0x1f40,
+ 0xed6f, 0x5145,
+ 0xed74, 0x2465,
+ 0xed75, 0x514a,
+ 0xed77, 0x2467,
+ 0xed78, 0x514c,
+ 0xed79, 0x2466,
+ 0xed7a, 0x514d,
+ 0xed80, 0x5152,
+ 0xed91, 0x21c9,
+ 0xed92, 0x5163,
+ 0xed93, 0x2209,
+ 0xed94, 0x1ec9,
+ 0xed95, 0x20e9,
+ 0xed96, 0x5164,
+ 0xed97, 0x21ca,
+ 0xed98, 0x2146,
+ 0xed99, 0x25c5,
+ 0xed9a, 0x21dc,
+ 0xed9b, 0x5165,
+ 0xed9c, 0x245e,
+ 0xed9d, 0x5166,
+ 0xed9e, 0x214f,
+ 0xed9f, 0x5167,
+ 0xeda0, 0x25c6,
+ 0xeda1, 0x1a0d,
+ 0xee40, 0x25c7,
+ 0xee41, 0x2241,
+ 0xee42, 0x218a,
+ 0xee43, 0x1e2f,
+ 0xee44, 0x1edc,
+ 0xee45, 0x5168,
+ 0xee48, 0x20bf,
+ 0xee49, 0x2034,
+ 0xee4a, 0x516b,
+ 0xee4d, 0x25c9,
+ 0xee4e, 0x516e,
+ 0xee52, 0x25c8,
+ 0xee53, 0x5172,
+ 0xee55, 0x220e,
+ 0xee56, 0x5174,
+ 0xee57, 0x25cb,
+ 0xee58, 0x5175,
+ 0xee5e, 0x217d,
+ 0xee5f, 0x517b,
+ 0xee61, 0x1f7e,
+ 0xee62, 0x517d,
+ 0xee68, 0x25cc,
+ 0xee69, 0x1fc3,
+ 0xee6a, 0x5183,
+ 0xee6c, 0x20b9,
+ 0xee6d, 0x5185,
+ 0xee6e, 0x2181,
+ 0xee6f, 0x5186,
+ 0xee77, 0x1fda,
+ 0xee78, 0x518e,
+ 0xee7d, 0x2173,
+ 0xee7e, 0x1ee1,
+ 0xee80, 0x25cd,
+ 0xee81, 0x5193,
+ 0xee85, 0x25ce,
+ 0xee86, 0x21f6,
+ 0xee87, 0x5197,
+ 0xee8a, 0x224b,
+ 0xee8b, 0x25d1,
+ 0xee8c, 0x519a,
+ 0xee8d, 0x1ec0,
+ 0xee8e, 0x519b,
+ 0xee90, 0x2008,
+ 0xee91, 0x519d,
+ 0xee94, 0x25d0,
+ 0xee95, 0x51a0,
+ 0xee97, 0x25d2,
+ 0xee98, 0x51a2,
+ 0xee99, 0x1f2a,
+ 0xee9a, 0x51a3,
+ 0xee9d, 0x1e72,
+ 0xee9e, 0x25d3,
+ 0xee9f, 0x51a6,
+ 0xeea1, 0x1a6b,
+ 0xef40, 0x21be,
+ 0xef41, 0x25d4,
+ 0xef42, 0x2044,
+ 0xef43, 0x51a8,
+ 0xef44, 0x25cf,
+ 0xef45, 0x20f3,
+ 0xef46, 0x51a9,
+ 0xef4c, 0x1f00,
+ 0xef4d, 0x51af,
+ 0xef52, 0x24cc,
+ 0xef54, 0x51b4,
+ 0xef55, 0x2698,
+ 0xef56, 0x51b5,
+ 0xef57, 0x2678,
+ 0xef58, 0x51b6,
+ 0xef5a, 0x24ce,
+ 0xef5b, 0x51b8,
+ 0xef60, 0x24cf,
+ 0xef61, 0x51bd,
+ 0xef68, 0x20b8,
+ 0xef69, 0x51c4,
+ 0xef6a, 0x24d0,
+ 0xef6b, 0x51c5,
+ 0xef6c, 0x24d1,
+ 0xef6d, 0x51c6,
+ 0xef77, 0x1ef4,
+ 0xef78, 0x51d0,
+ 0xef7a, 0x239b,
+ 0xef7b, 0x51d2,
+ 0xef7c, 0x267e,
+ 0xef7d, 0x51d3,
+ 0xef80, 0x51d5,
+ 0xef82, 0x239d,
+ 0xef83, 0x239f,
+ 0xef85, 0x51d7,
+ 0xef86, 0x23a1,
+ 0xef87, 0x51d8,
+ 0xef88, 0x1ef1,
+ 0xef89, 0x51d9,
+ 0xef8b, 0x221e,
+ 0xef8c, 0x51db,
+ 0xef8d, 0x23a2,
+ 0xef8e, 0x51dc,
+ 0xef95, 0x214b,
+ 0xef96, 0x1e36,
+ 0xef97, 0x2135,
+ 0xef98, 0x51e3,
+ 0xef9c, 0x1fad,
+ 0xef9d, 0x51e7,
+ 0xef9e, 0x1e53,
+ 0xef9f, 0x51e8,
+ 0xefa1, 0x1ac9,
+ 0xf040, 0x51ea,
+ 0xf041, 0x23a3,
+ 0xf042, 0x2203,
+ 0xf043, 0x51eb,
+ 0xf044, 0x1ee7,
+ 0xf045, 0x51ec,
+ 0xf047, 0x23a4,
+ 0xf048, 0x2097,
+ 0xf049, 0x1ee4,
+ 0xf04a, 0x51ee,
+ 0xf04e, 0x2238,
+ 0xf04f, 0x51f2,
+ 0xf051, 0x23a5,
+ 0xf052, 0x51f4,
+ 0xf054, 0x1f9a,
+ 0xf055, 0x51f6,
+ 0xf057, 0x21c3,
+ 0xf058, 0x51f8,
+ 0xf05e, 0x1f2e,
+ 0xf05f, 0x51fe,
+ 0xf068, 0x239c,
+ 0xf069, 0x5207,
+ 0xf06c, 0x23a6,
+ 0xf06d, 0x520a,
+ 0xf071, 0x239e,
+ 0xf072, 0x520e,
+ 0xf073, 0x2035,
+ 0xf074, 0x23a7,
+ 0xf075, 0x520f,
+ 0xf078, 0x23a8,
+ 0xf079, 0x5212,
+ 0xf07a, 0x2075,
+ 0xf07b, 0x5213,
+ 0xf07d, 0x23a9,
+ 0xf080, 0x23ab,
+ 0xf081, 0x1feb,
+ 0xf082, 0x23ac,
+ 0xf083, 0x5215,
+ 0xf087, 0x1f6a,
+ 0xf088, 0x20f9,
+ 0xf089, 0x5219,
+ 0xf08b, 0x2666,
+ 0xf08c, 0x521b,
+ 0xf090, 0x2667,
+ 0xf091, 0x521f,
+ 0xf092, 0x1e6c,
+ 0xf093, 0x5220,
+ 0xf096, 0x23ad,
+ 0xf097, 0x5223,
+ 0xf0a1, 0x1b27,
+ 0xf140, 0x522d,
+ 0xf152, 0x206d,
+ 0xf153, 0x2242,
+ 0xf154, 0x1f02,
+ 0xf155, 0x523f,
+ 0xf157, 0x2183,
+ 0xf158, 0x5241,
+ 0xf159, 0x1e85,
+ 0xf15a, 0x21e9,
+ 0xf15b, 0x5242,
+ 0xf167, 0x1e57,
+ 0xf168, 0x524e,
+ 0xf176, 0x22a5,
+ 0xf177, 0x2407,
+ 0xf178, 0x1fca,
+ 0xf179, 0x525c,
+ 0xf17a, 0x2402,
+ 0xf17b, 0x1f82,
+ 0xf17c, 0x525d,
+ 0xf17e, 0x2408,
+ 0xf180, 0x2404,
+ 0xf181, 0x525f,
+ 0xf182, 0x2131,
+ 0xf183, 0x5260,
+ 0xf184, 0x2184,
+ 0xf185, 0x5261,
+ 0xf186, 0x2403,
+ 0xf187, 0x5262,
+ 0xf188, 0x206e,
+ 0xf189, 0x240b,
+ 0xf18a, 0x5263,
+ 0xf194, 0x1f3f,
+ 0xf195, 0x526d,
+ 0xf198, 0x2067,
+ 0xf199, 0x5270,
+ 0xf1a1, 0x1b85,
+ 0xf240, 0x5278,
+ 0xf245, 0x1fd7,
+ 0xf246, 0x527d,
+ 0xf247, 0x1e83,
+ 0xf248, 0x527e,
+ 0xf24b, 0x240f,
+ 0xf24c, 0x5281,
+ 0xf253, 0x240e,
+ 0xf254, 0x20c7,
+ 0xf255, 0x240d,
+ 0xf256, 0x5288,
+ 0xf25c, 0x2412,
+ 0xf25d, 0x528e,
+ 0xf25f, 0x20b7,
+ 0xf260, 0x5290,
+ 0xf271, 0x23f0,
+ 0xf272, 0x52a1,
+ 0xf273, 0x2411,
+ 0xf274, 0x2414,
+ 0xf275, 0x52a2,
+ 0xf276, 0x2170,
+ 0xf277, 0x52a3,
+ 0xf27c, 0x2405,
+ 0xf27d, 0x210c,
+ 0xf27e, 0x2415,
+ 0xf280, 0x52a8,
+ 0xf285, 0x2066,
+ 0xf286, 0x52ad,
+ 0xf287, 0x2352,
+ 0xf288, 0x2413,
+ 0xf289, 0x2410,
+ 0xf28a, 0x2416,
+ 0xf28c, 0x20f1,
+ 0xf28d, 0x52ae,
+ 0xf291, 0x240a,
+ 0xf292, 0x52b2,
+ 0xf294, 0x2409,
+ 0xf295, 0x52b4,
+ 0xf296, 0x2418,
+ 0xf297, 0x52b5,
+ 0xf29c, 0x1fa7,
+ 0xf29d, 0x52ba,
+ 0xf29e, 0x21fc,
+ 0xf29f, 0x52bb,
+ 0xf2a1, 0x1be3,
+ 0xf340, 0x1fc1,
+ 0xf341, 0x2406,
+ 0xf342, 0x52bd,
+ 0xf345, 0x229c,
+ 0xf346, 0x52c0,
+ 0xf348, 0x204e,
+ 0xf349, 0x52c2,
+ 0xf34a, 0x241a,
+ 0xf34b, 0x2419,
+ 0xf34c, 0x52c3,
+ 0xf350, 0x240c,
+ 0xf351, 0x52c7,
+ 0xf361, 0x1e29,
+ 0xf362, 0x52d7,
+ 0xf374, 0x2661,
+ 0xf375, 0x52e9,
+ 0xf376, 0x26a4,
+ 0xf377, 0x2174,
+ 0xf378, 0x2663,
+ 0xf379, 0x2662,
+ 0xf37a, 0x52ea,
+ 0xf380, 0x52ef,
+ 0xf38c, 0x2675,
+ 0xf38d, 0x52fb,
+ 0xf3a0, 0x214c,
+ 0xf3a1, 0x1c41,
+ 0xf440, 0x530e,
+ 0xf445, 0x267a,
+ 0xf446, 0x5313,
+ 0xf450, 0x26a0,
+ 0xf451, 0x531d,
+ 0xf457, 0x2668,
+ 0xf458, 0x5323,
+ 0xf459, 0x1ed0,
+ 0xf45a, 0x5324,
+ 0xf45b, 0x2096,
+ 0xf45c, 0x5325,
+ 0xf45d, 0x23cc,
+ 0xf45e, 0x5326,
+ 0xf462, 0x23c8,
+ 0xf463, 0x532a,
+ 0xf464, 0x223e,
+ 0xf465, 0x532b,
+ 0xf475, 0x2665,
+ 0xf476, 0x533b,
+ 0xf47c, 0x2664,
+ 0xf47d, 0x5341,
+ 0xf47e, 0x2239,
+ 0xf480, 0x5342,
+ 0xf494, 0x204a,
+ 0xf495, 0x5356,
+ 0xf499, 0x261f,
+ 0xf49a, 0x535a,
+ 0xf49c, 0x261e,
+ 0xf49d, 0x535c,
+ 0xf4a1, 0x1c9f,
+ 0xf540, 0x5360,
+ 0xf545, 0x2620,
+ 0xf546, 0x5365,
+ 0xf547, 0x2621,
+ 0xf548, 0x5366,
+ 0xf552, 0x2622,
+ 0xf553, 0x5370,
+ 0xf554, 0x2627,
+ 0xf555, 0x1e39,
+ 0xf556, 0x2625,
+ 0xf557, 0x5371,
+ 0xf55e, 0x2629,
+ 0xf55f, 0x5378,
+ 0xf561, 0x262e,
+ 0xf562, 0x262b,
+ 0xf563, 0x537a,
+ 0xf56e, 0x262a,
+ 0xf56f, 0x262d,
+ 0xf570, 0x5385,
+ 0xf571, 0x2628,
+ 0xf572, 0x21b9,
+ 0xf573, 0x5386,
+ 0xf580, 0x5392,
+ 0xf585, 0x2636,
+ 0xf586, 0x2630,
+ 0xf587, 0x5397,
+ 0xf58c, 0x2638,
+ 0xf58d, 0x539c,
+ 0xf58e, 0x200d,
+ 0xf58f, 0x2637,
+ 0xf590, 0x539d,
+ 0xf599, 0x2645,
+ 0xf59a, 0x53a6,
+ 0xf59b, 0x263a,
+ 0xf59c, 0x53a7,
+ 0xf5a0, 0x2643,
+ 0xf5a1, 0x1cfd,
+ 0xf640, 0x53ab,
+ 0xf641, 0x2640,
+ 0xf642, 0x53ac,
+ 0xf645, 0x263d,
+ 0xf646, 0x2641,
+ 0xf647, 0x53af,
+ 0xf648, 0x263e,
+ 0xf649, 0x53b0,
+ 0xf64b, 0x263f,
+ 0xf64c, 0x1fc0,
+ 0xf64d, 0x53b2,
+ 0xf64e, 0x263b,
+ 0xf650, 0x53b3,
+ 0xf654, 0x2642,
+ 0xf655, 0x53b7,
+ 0xf658, 0x2644,
+ 0xf659, 0x53ba,
+ 0xf661, 0x2639,
+ 0xf662, 0x53c2,
+ 0xf663, 0x264c,
+ 0xf664, 0x53c3,
+ 0xf66c, 0x2647,
+ 0xf66d, 0x264b,
+ 0xf66e, 0x53cb,
+ 0xf671, 0x2649,
+ 0xf672, 0x53ce,
+ 0xf674, 0x2648,
+ 0xf675, 0x53d0,
+ 0xf676, 0x264a,
+ 0xf677, 0x2108,
+ 0xf678, 0x53d1,
+ 0xf680, 0x53d8,
+ 0xf685, 0x264d,
+ 0xf686, 0x53dd,
+ 0xf688, 0x2634,
+ 0xf689, 0x53df,
+ 0xf68a, 0x2651,
+ 0xf68b, 0x53e0,
+ 0xf68d, 0x2650,
+ 0xf68e, 0x2652,
+ 0xf68f, 0x53e2,
+ 0xf692, 0x264f,
+ 0xf693, 0x53e5,
+ 0xf696, 0x2632,
+ 0xf697, 0x264e,
+ 0xf698, 0x2653,
+ 0xf699, 0x53e8,
+ 0xf69a, 0x2657,
+ 0xf69b, 0x53e9,
+ 0xf69c, 0x2635,
+ 0xf69d, 0x53ea,
+ 0xf69e, 0x2633,
+ 0xf69f, 0x53eb,
+ 0xf6a0, 0x2656,
+ 0xf6a1, 0x1d5b,
+ 0xf740, 0x53ec,
+ 0xf742, 0x2654,
+ 0xf743, 0x53ee,
+ 0xf749, 0x2658,
+ 0xf74a, 0x53f4,
+ 0xf74c, 0x2655,
+ 0xf74d, 0x1e4d,
+ 0xf74e, 0x53f6,
+ 0xf756, 0x265b,
+ 0xf757, 0x53fe,
+ 0xf758, 0x265a,
+ 0xf759, 0x53ff,
+ 0xf75a, 0x2659,
+ 0xf75b, 0x202e,
+ 0xf75c, 0x262f,
+ 0xf75d, 0x5400,
+ 0xf761, 0x2646,
+ 0xf762, 0x5404,
+ 0xf763, 0x2626,
+ 0xf764, 0x5405,
+ 0xf76b, 0x265c,
+ 0xf76c, 0x540c,
+ 0xf771, 0x262c,
+ 0xf772, 0x5411,
+ 0xf77c, 0x2623,
+ 0xf77d, 0x541b,
+ 0xf77e, 0x2631,
+ 0xf780, 0x541c,
+ 0xf7a1, 0x1db9,
+ 0xf840, 0x543d,
+ 0xf842, 0x209c,
+ 0xf843, 0x543f,
+ 0xf846, 0x2580,
+ 0xf847, 0x5442,
+ 0xf849, 0x22dc,
+ 0xf84a, 0x5444,
+ 0xf850, 0x1f05,
+ 0xf851, 0x208b,
+ 0xf852, 0x544a,
+ 0xf853, 0x2581,
+ 0xf854, 0x544b,
+ 0xf863, 0x2583,
+ 0xf864, 0x2582,
+ 0xf865, 0x545a,
+ 0xf866, 0x21ee,
+ 0xf867, 0x545b,
+ 0xf872, 0x2182,
+ 0xf873, 0x5466,
+ 0xf878, 0x2243,
+ 0xf879, 0x546b,
+ 0xf87a, 0x2587,
+ 0xf87b, 0x546c,
+ 0xf87c, 0x2588,
+ 0xf87d, 0x546d,
+ 0xf880, 0x546f,
+ 0xf881, 0x2584,
+ 0xf882, 0x5470,
+ 0xf884, 0x21fd,
+ 0xf885, 0x5472,
+ 0xf886, 0x21ef,
+ 0xf887, 0x5473,
+ 0xf88d, 0x258a,
+ 0xf88e, 0x258c,
+ 0xf88f, 0x5479,
+ 0xf899, 0x1f47,
+ 0xf89a, 0x5483,
+ 0xf89d, 0x1f1d,
+ 0xf89e, 0x5486,
+ 0xf8a0, 0x258d,
+ 0xf940, 0x5488,
+ 0xf94e, 0x1fd0,
+ 0xf94f, 0x2592,
+ 0xf950, 0x258f,
+ 0xf951, 0x5496,
+ 0xf959, 0x2594,
+ 0xf95a, 0x1ee0,
+ 0xf95b, 0x549e,
+ 0xf95d, 0x2591,
+ 0xf95e, 0x2595,
+ 0xf95f, 0x54a0,
+ 0xf967, 0x2597,
+ 0xf968, 0x54a8,
+ 0xf969, 0x20b6,
+ 0xf96a, 0x54a9,
+ 0xf96c, 0x2598,
+ 0xf96d, 0x54ab,
+ 0xf96f, 0x20f6,
+ 0xf970, 0x54ad,
+ 0xf980, 0x54bc,
+ 0xf985, 0x2585,
+ 0xf986, 0x54c1,
+ 0xf987, 0x2599,
+ 0xf988, 0x54c2,
+ 0xf991, 0x2596,
+ 0xf992, 0x54cb,
+ 0xf996, 0x259a,
+ 0xf997, 0x54cf,
+ 0xf998, 0x259b,
+ 0xf999, 0x54d0,
+ 0xfa40, 0x54d8,
+ 0xfa42, 0x259d,
+ 0xfa43, 0x54da,
+ 0xfa46, 0x259e,
+ 0xfa47, 0x54dd,
+ 0xfa4c, 0x234c,
+ 0xfa4d, 0x54e2,
+ 0xfa51, 0x1f44,
+ 0xfa52, 0x54e6,
+ 0xfa58, 0x2660,
+ 0xfa59, 0x25a0,
+ 0xfa5a, 0x54ec,
+ 0xfa5d, 0x259c,
+ 0xfa5e, 0x54ef,
+ 0xfa5f, 0x259f,
+ 0xfa60, 0x54f0,
+ 0xfa61, 0x1f6c,
+ 0xfa62, 0x54f1,
+ 0xfa70, 0x25a2,
+ 0xfa71, 0x54ff,
+ 0xfa74, 0x20ae,
+ 0xfa75, 0x5502,
+ 0xfa76, 0x258b,
+ 0xfa77, 0x25a3,
+ 0xfa78, 0x5503,
+ 0xfa80, 0x550a,
+ 0xfa83, 0x2589,
+ 0xfa84, 0x25a5,
+ 0xfa85, 0x550d,
+ 0xfa8d, 0x25a4,
+ 0xfa8e, 0x5515,
+ 0xfa90, 0x25a6,
+ 0xfa91, 0x2593,
+ 0xfa92, 0x5517,
+ 0xfa96, 0x25a7,
+ 0xfa97, 0x2222,
+ 0xfa98, 0x25a9,
+ 0xfa99, 0x551b,
+ 0xfb40, 0x5523,
+ 0xfb49, 0x25a8,
+ 0xfb4a, 0x552c,
+ 0xfb52, 0x2586,
+ 0xfb53, 0x5534,
+ 0xfb57, 0x25a1,
+ 0xfb58, 0x25aa,
+ 0xfb59, 0x5538,
+ 0xfb5a, 0x2590,
+ 0xfb5b, 0x258e,
+ 0xfb5c, 0x5539,
+ 0xfb75, 0x2688,
+ 0xfb76, 0x5552,
+ 0xfb79, 0x269e,
+ 0xfb7a, 0x25fb,
+ 0xfb7b, 0x5555,
+ 0xfb7c, 0x1f8c,
+ 0xfb7d, 0x21f4,
+ 0xfb7e, 0x5556,
+ 0xfb80, 0x5557,
+ 0xfb90, 0x200f,
+ 0xfb91, 0x5567,
+ 0xfb9c, 0x2071,
+ 0xfb9d, 0x5572,
+ 0xfb9f, 0x25f7,
+ 0xfba0, 0x5574,
+ 0xfc40, 0x5575,
+ 0xfc44, 0x2696,
+ 0xfc45, 0x5579,
+ 0xfc49, 0x268f,
+ 0xfc4a, 0x557d,
+ 0xfc5a, 0x22da,
+ 0xfc5b, 0x558d,
+ 0xfc63, 0x1ec1,
+ 0xfc64, 0x5595,
+ 0xfc68, 0x1eb3,
+ 0xfc69, 0x5599,
+ 0xfc6f, 0x266a,
+ 0xfc70, 0x559f,
+ 0xfc71, 0x268a,
+ 0xfc72, 0x55a0,
+ 0xfc74, 0x2669,
+ 0xfc75, 0x55a2,
+ 0xfc77, 0x2618,
+ 0xfc79, 0x55a4,
+ 0xfc80, 0x55aa,
+ 0xfc83, 0x261a,
+ 0xfc84, 0x55ad,
+ 0xfc8a, 0x2673,
+ 0xfc8b, 0x55b3,
+ 0xfd40, 0x55c9,
+ 0xfd52, 0x20c6,
+ 0xfd53, 0x226b,
+ 0xfd54, 0x55db,
+ 0xfd57, 0x24d3,
+ 0xfd58, 0x1e86,
+ 0xfd59, 0x55de,
+ 0xfd5a, 0x260f,
+ 0xfd5b, 0x55df,
+ 0xfd5f, 0x2611,
+ 0xfd60, 0x55e3,
+ 0xfd62, 0x2613,
+ 0xfd63, 0x55e5,
+ 0xfd65, 0x2610,
+ 0xfd66, 0x2612,
+ 0xfd67, 0x2030,
+ 0xfd68, 0x55e7,
+ 0xfd69, 0x2671,
+ 0xfd6a, 0x55e8,
+ 0xfd6c, 0x2614,
+ 0xfd6d, 0x55ea,
+ 0xfd70, 0x2616,
+ 0xfd71, 0x55ed,
+ 0xfd72, 0x2615,
+ 0xfd73, 0x55ee,
+ 0xfd78, 0x20f2,
+ 0xfd79, 0x55f3,
+ 0xfd7d, 0x2617,
+ 0xfd7e, 0x55f7,
+ 0xfd80, 0x55f8,
+ 0xfd88, 0x2037,
+ 0xfd89, 0x5600,
+ 0xfd8b, 0x20b3,
+ 0xfd8c, 0x5602,
+ 0xfd8f, 0x1f22,
+ 0xfd90, 0x24ed,
+ 0xfd91, 0x5605,
+ 0xfd94, 0x1f34,
+ 0xfd95, 0x5608,
+ 0xfd9d, 0x0a02,
+ 0xfd9e, 0x40d3,
+ 0xfd9f, 0x200c,
+ 0xfda0, 0x5083,
+ 0xfe40, 0x1259,
+ 0xfe41, 0x5610,
+ 0xfe80, 0x564e,
+ 0xa1a2, 0x023f,
+ 0xa1a3, 0x023e,
+ 0xa1aa, 0x0256,
+ 0xa1ab, 0x1e18,
+ 0xa1ad, 0x0257,
+ 0xa1b2, 0x0246,
+ 0xa1fe, 0x1e1a,
+ 0xa3a1, 0x0242,
+ 0xa3a8, 0x0244,
+ 0xa3ac, 0x023d,
+ 0xa3ae, 0x1e1b,
+ 0xa3ba, 0x0240,
+ 0xa3bd, 0x1e1c,
+ 0xa3bf, 0x0243,
+ 0xa3db, 0x1e1d,
+ 0xa3dd, 0x1e1e,
+ 0xa3df, 0x0258,
+ 0xa3fb, 0x0254,
+ 0xa3fd, 0x0255,
+ 0xa3fe, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBKEUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBKEUCVMap2, 4091
+};
+
+static Gushort gb12GBTEUCHMap2[4566] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb0a8, 0x1e25,
+ 0xb0a9, 0x03b4,
+ 0xb0aa, 0x1e26,
+ 0xb0ab, 0x03b6,
+ 0xb0ad, 0x1e27,
+ 0xb0af, 0x03ba,
+ 0xb0b9, 0x1e29,
+ 0xb0ba, 0x03c5,
+ 0xb0c0, 0x1e2a,
+ 0xb0c1, 0x03cc,
+ 0xb0d3, 0x1e2b,
+ 0xb0d4, 0x03df,
+ 0xb0d5, 0x1e2c,
+ 0xb0d6, 0x03e1,
+ 0xb0da, 0x1e2d,
+ 0xb0db, 0x03e6,
+ 0xb0dc, 0x1e2e,
+ 0xb0dd, 0x03e8,
+ 0xb0e4, 0x1e2f,
+ 0xb0e5, 0x03f0,
+ 0xb0ec, 0x1e30,
+ 0xb0ee, 0x03f9,
+ 0xb0ef, 0x1e32,
+ 0xb0f0, 0x03fb,
+ 0xb0f3, 0x1e33,
+ 0xb0f4, 0x03ff,
+ 0xb0f7, 0x1e34,
+ 0xb0f8, 0x0403,
+ 0xb0f9, 0x1e35,
+ 0xb0fa, 0x0405,
+ 0xb1a1, 0x040a,
+ 0xb1a5, 0x1e36,
+ 0xb1a7, 0x0410,
+ 0xb1a8, 0x1e38,
+ 0xb1a9, 0x0412,
+ 0xb1ab, 0x1e39,
+ 0xb1ac, 0x0415,
+ 0xb1b2, 0x1e3a,
+ 0xb1b3, 0x041c,
+ 0xb1b4, 0x1e3b,
+ 0xb1b6, 0x041f,
+ 0xb1b7, 0x1e3d,
+ 0xb1ba, 0x0423,
+ 0xb1c1, 0x1e40,
+ 0xb1c2, 0x042b,
+ 0xb1ca, 0x1e41,
+ 0xb1cb, 0x0434,
+ 0xb1cf, 0x1e42,
+ 0xb1d1, 0x043a,
+ 0xb1d2, 0x1e44,
+ 0xb1d3, 0x043c,
+ 0xb1d5, 0x1e45,
+ 0xb1d6, 0x043f,
+ 0xb1df, 0x1e46,
+ 0xb1e2, 0x044b,
+ 0xb1e4, 0x1e49,
+ 0xb1e5, 0x044e,
+ 0xb1e7, 0x1e4a,
+ 0xb1e9, 0x0452,
+ 0xb1ea, 0x1e4c,
+ 0xb1eb, 0x0454,
+ 0xb1ee, 0x1e4d,
+ 0xb1ef, 0x0458,
+ 0xb1f1, 0x1e4e,
+ 0xb1f2, 0x045b,
+ 0xb1f4, 0x1e4f,
+ 0xb1f8, 0x0461,
+ 0xb1fd, 0x1e53,
+ 0xb1fe, 0x0467,
+ 0xb2a1, 0x0468,
+ 0xb2a6, 0x1e54,
+ 0xb2a8, 0x046f,
+ 0xb2ac, 0x1e56,
+ 0xb2ad, 0x0474,
+ 0xb2b5, 0x1e57,
+ 0xb2b6, 0x047d,
+ 0xb2b9, 0x1e58,
+ 0xb2ba, 0x0481,
+ 0xb2c6, 0x1e59,
+ 0xb2c7, 0x048e,
+ 0xb2ce, 0x1e5a,
+ 0xb2d8, 0x049f,
+ 0xb2de, 0x1e64,
+ 0xb2df, 0x04a6,
+ 0xb2e0, 0x1e65,
+ 0xb2e1, 0x04a8,
+ 0xb2e2, 0x1e66,
+ 0xb2e4, 0x04ab,
+ 0xb2ef, 0x1e68,
+ 0xb2f0, 0x04b7,
+ 0xb2f3, 0x1e69,
+ 0xb2fd, 0x04c4,
+ 0xb3a1, 0x1e73,
+ 0xb3a3, 0x04c8,
+ 0xb3a4, 0x1e75,
+ 0xb3a8, 0x04cd,
+ 0xb3a9, 0x1e79,
+ 0xb3aa, 0x04cf,
+ 0xb3ae, 0x1e7a,
+ 0xb3af, 0x04d4,
+ 0xb3b5, 0x1e7b,
+ 0xb3b6, 0x04db,
+ 0xb3b9, 0x1e7c,
+ 0xb3ba, 0x04df,
+ 0xb3be, 0x1e7d,
+ 0xb3bf, 0x04e4,
+ 0xb3c2, 0x1e7e,
+ 0xb3c3, 0x04e8,
+ 0xb3c4, 0x1e7f,
+ 0xb3c5, 0x04ea,
+ 0xb3c6, 0x1e80,
+ 0xb3c7, 0x04ec,
+ 0xb3cd, 0x1e81,
+ 0xb3ce, 0x04f3,
+ 0xb3cf, 0x1e82,
+ 0xb3d0, 0x04f5,
+ 0xb3d2, 0x1e83,
+ 0xb3d3, 0x04f8,
+ 0xb3d9, 0x1e84,
+ 0xb3da, 0x04ff,
+ 0xb3db, 0x1e85,
+ 0xb3dc, 0x0501,
+ 0xb3dd, 0x1e86,
+ 0xb3de, 0x0503,
+ 0xb3e3, 0x1e87,
+ 0xb3e4, 0x0509,
+ 0xb3e5, 0x1e88,
+ 0xb3e7, 0x050c,
+ 0xb3e8, 0x1e8a,
+ 0xb3e9, 0x050e,
+ 0xb3eb, 0x1e8b,
+ 0xb3ed, 0x0512,
+ 0xb3ef, 0x1e8d,
+ 0xb3f0, 0x0515,
+ 0xb3f1, 0x1e8e,
+ 0xb3f2, 0x0517,
+ 0xb3f3, 0x1e8f,
+ 0xb3f4, 0x0519,
+ 0xb3fa, 0x1e90,
+ 0xb3fc, 0x0521,
+ 0xb4a1, 0x1e92,
+ 0xb4a3, 0x0526,
+ 0xb4a5, 0x1e94,
+ 0xb4a7, 0x052a,
+ 0xb4ab, 0x1e96,
+ 0xb4ac, 0x052f,
+ 0xb4af, 0x1e97,
+ 0xb4b0, 0x0533,
+ 0xb4b3, 0x1e98,
+ 0xb4b5, 0x0538,
+ 0xb4b8, 0x1e9a,
+ 0xb4b9, 0x053c,
+ 0xb4bf, 0x1e9b,
+ 0xb4c0, 0x0543,
+ 0xb4c2, 0x1e9c,
+ 0xb4c3, 0x0546,
+ 0xb4c7, 0x1e9d,
+ 0xb4c8, 0x054b,
+ 0xb4ca, 0x1e9e,
+ 0xb4cb, 0x054e,
+ 0xb4cd, 0x1e9f,
+ 0xb4ce, 0x0551,
+ 0xb4cf, 0x1ea0,
+ 0xb4d0, 0x0553,
+ 0xb4d3, 0x1ea1,
+ 0xb4d5, 0x0558,
+ 0xb4da, 0x1ea3,
+ 0xb4db, 0x055e,
+ 0xb4dc, 0x1ea4,
+ 0xb4dd, 0x0560,
+ 0xb4ed, 0x1ea5,
+ 0xb4ee, 0x0571,
+ 0xb4ef, 0x1ea6,
+ 0xb4f0, 0x0573,
+ 0xb4f8, 0x1ea7,
+ 0xb4f9, 0x057c,
+ 0xb4fb, 0x1ea8,
+ 0xb4fc, 0x057f,
+ 0xb5a1, 0x0582,
+ 0xb5a3, 0x1ea9,
+ 0xb5a4, 0x0585,
+ 0xb5a5, 0x1eaa,
+ 0xb5a9, 0x058a,
+ 0xb5ac, 0x1eae,
+ 0xb5ad, 0x058e,
+ 0xb5ae, 0x1eaf,
+ 0xb5b0, 0x0591,
+ 0xb5b1, 0x1eb1,
+ 0xb5b6, 0x0597,
+ 0xb5b7, 0x1eb6,
+ 0xb5b8, 0x0599,
+ 0xb5ba, 0x1eb7,
+ 0xb5bd, 0x059e,
+ 0xb5c6, 0x1eba,
+ 0xb5c7, 0x05a8,
+ 0xb5cb, 0x1ebb,
+ 0xb5cc, 0x05ad,
+ 0xb5d0, 0x1ebc,
+ 0xb5d1, 0x05b2,
+ 0xb5d3, 0x1ebd,
+ 0xb5d4, 0x05b5,
+ 0xb5dd, 0x1ebe,
+ 0xb5e0, 0x05c1,
+ 0xb5e3, 0x1ec1,
+ 0xb5e4, 0x05c5,
+ 0xb5e6, 0x1ec2,
+ 0xb5e8, 0x05c9,
+ 0xb5ed, 0x1ec4,
+ 0xb5ee, 0x05cf,
+ 0xb5f6, 0x1ec5,
+ 0xb5f8, 0x05d9,
+ 0xb5fd, 0x1ec7,
+ 0xb5fe, 0x05df,
+ 0xb6a1, 0x05e0,
+ 0xb6a4, 0x1ec8,
+ 0xb6a6, 0x05e5,
+ 0xb6a7, 0x1eca,
+ 0xb6a8, 0x05e7,
+ 0xb6a9, 0x1ecb,
+ 0xb6aa, 0x05e9,
+ 0xb6ab, 0x1ecc,
+ 0xb6ac, 0x05eb,
+ 0xb6af, 0x1ecd,
+ 0xb6b1, 0x05f0,
+ 0xb6b3, 0x1ecf,
+ 0xb6b4, 0x05f3,
+ 0xb6b7, 0x1ed0,
+ 0xb6b8, 0x05f7,
+ 0xb6bf, 0x1ed1,
+ 0xb6c2, 0x0601,
+ 0xb6c4, 0x1ed4,
+ 0xb6c5, 0x0604,
+ 0xb6c6, 0x1ed5,
+ 0xb6c7, 0x0606,
+ 0xb6cd, 0x1ed6,
+ 0xb6ce, 0x060d,
+ 0xb6cf, 0x1ed7,
+ 0xb6d1, 0x0610,
+ 0xb6d3, 0x1ed9,
+ 0xb6d5, 0x0614,
+ 0xb6d6, 0x1edb,
+ 0xb6d7, 0x0616,
+ 0xb6d9, 0x1edc,
+ 0xb6da, 0x0619,
+ 0xb6db, 0x1edd,
+ 0xb6dc, 0x061b,
+ 0xb6e1, 0x1ede,
+ 0xb6e2, 0x0621,
+ 0xb6e9, 0x1edf,
+ 0xb6ea, 0x0629,
+ 0xb6ec, 0x1ee0,
+ 0xb6ed, 0x062c,
+ 0xb6ee, 0x1ee1,
+ 0xb6f0, 0x062f,
+ 0xb6f1, 0x1ee3,
+ 0xb6f2, 0x0631,
+ 0xb6f6, 0x1ee4,
+ 0xb6f7, 0x0636,
+ 0xb6f9, 0x1ee5,
+ 0xb6fa, 0x0639,
+ 0xb6fb, 0x1ee6,
+ 0xb6fd, 0x063c,
+ 0xb7a1, 0x1ee8,
+ 0xb7a4, 0x0641,
+ 0xb7a7, 0x1eeb,
+ 0xb7a8, 0x0645,
+ 0xb7af, 0x1eec,
+ 0xb7b1, 0x064e,
+ 0xb7b3, 0x1eee,
+ 0xb7b4, 0x0651,
+ 0xb7b6, 0x1eef,
+ 0xb7b8, 0x0655,
+ 0xb7b9, 0x1ef1,
+ 0xb7ba, 0x0657,
+ 0xb7c3, 0x1ef2,
+ 0xb7c5, 0x0662,
+ 0xb7c9, 0x1ef4,
+ 0xb7ca, 0x0667,
+ 0xb7cc, 0x1ef5,
+ 0xb7cd, 0x066a,
+ 0xb7cf, 0x1ef6,
+ 0xb7d0, 0x066d,
+ 0xb7d1, 0x1ef7,
+ 0xb7d2, 0x066f,
+ 0xb7d7, 0x1ef8,
+ 0xb7d9, 0x0676,
+ 0xb7dc, 0x1efa,
+ 0xb7dd, 0x067a,
+ 0xb7df, 0x1efb,
+ 0xb7e2, 0x067f,
+ 0xb7e3, 0x1efe,
+ 0xb7e4, 0x0681,
+ 0xb7e6, 0x1eff,
+ 0xb7e9, 0x0686,
+ 0xb7eb, 0x1f02,
+ 0xb7ee, 0x068b,
+ 0xb7ef, 0x1f05,
+ 0xb7f0, 0x068d,
+ 0xb7f4, 0x1f06,
+ 0xb7f5, 0x0692,
+ 0xb7f8, 0x1f07,
+ 0xb7f9, 0x0696,
+ 0xb8a1, 0x069c,
+ 0xb8a7, 0x1f08,
+ 0xb8a9, 0x06a4,
+ 0xb8b3, 0x1f0a,
+ 0xb8b5, 0x06b0,
+ 0xb8ba, 0x1f0c,
+ 0xb8bb, 0x06b6,
+ 0xb8bc, 0x1f0d,
+ 0xb8bd, 0x06b8,
+ 0xb8be, 0x1f0e,
+ 0xb8c0, 0x06bb,
+ 0xb8c3, 0x1f10,
+ 0xb8c4, 0x06bf,
+ 0xb8c6, 0x1f11,
+ 0xb8c8, 0x06c3,
+ 0xb8c9, 0x1f13,
+ 0xb8ca, 0x06c5,
+ 0xb8cf, 0x1f14,
+ 0xb8d0, 0x06cb,
+ 0xb8d3, 0x1f15,
+ 0xb8d7, 0x06d2,
+ 0xb8d9, 0x1f19,
+ 0xb8db, 0x06d6,
+ 0xb8e4, 0x1f1b,
+ 0xb8e5, 0x06e0,
+ 0xb8e9, 0x1f1c,
+ 0xb8ea, 0x06e5,
+ 0xb8eb, 0x1f1d,
+ 0xb8ec, 0x06e7,
+ 0xb8f3, 0x1f1e,
+ 0xb8f4, 0x06ef,
+ 0xb8f5, 0x1f1f,
+ 0xb8f7, 0x06f2,
+ 0xb8f8, 0x1f21,
+ 0xb8f9, 0x06f4,
+ 0xb9a1, 0x06fa,
+ 0xb9a8, 0x1f22,
+ 0xb9a9, 0x0702,
+ 0xb9ae, 0x1f23,
+ 0xb9af, 0x0708,
+ 0xb9b1, 0x1f24,
+ 0xb9b2, 0x070b,
+ 0xb9b3, 0x1f25,
+ 0xb9b4, 0x070d,
+ 0xb9b5, 0x1f26,
+ 0xb9b6, 0x070f,
+ 0xb9b9, 0x1f27,
+ 0xb9bb, 0x0714,
+ 0xb9c6, 0x1f29,
+ 0xb9c7, 0x0720,
+ 0xb9cb, 0x1f2a,
+ 0xb9cc, 0x0725,
+ 0xb9d0, 0x1f2b,
+ 0xb9d1, 0x072a,
+ 0xb9d8, 0x1f2c,
+ 0xb9d9, 0x0732,
+ 0xb9db, 0x1f2d,
+ 0xb9dc, 0x0735,
+ 0xb9dd, 0x1f2e,
+ 0xb9de, 0x0737,
+ 0xb9df, 0x1f2f,
+ 0xb9e0, 0x0739,
+ 0xb9e1, 0x1f30,
+ 0xb9e2, 0x073b,
+ 0xb9e3, 0x1f31,
+ 0xb9e4, 0x073d,
+ 0xb9e6, 0x1f32,
+ 0xb9e7, 0x0740,
+ 0xb9e9, 0x1f33,
+ 0xb9ed, 0x0746,
+ 0xb9ee, 0x1f37,
+ 0xb9ef, 0x0748,
+ 0xb9f1, 0x1f38,
+ 0xb9f2, 0x074b,
+ 0xb9f3, 0x1f39,
+ 0xb9f6, 0x074f,
+ 0xb9f8, 0x1f3c,
+ 0xb9f9, 0x0752,
+ 0xb9fa, 0x1f3d,
+ 0xb9fb, 0x0754,
+ 0xb9fd, 0x1f3e,
+ 0xb9fe, 0x0757,
+ 0xbaa1, 0x0758,
+ 0xbaa7, 0x1f3f,
+ 0xbaa8, 0x075f,
+ 0xbaab, 0x1f40,
+ 0xbaac, 0x0763,
+ 0xbaba, 0x1f41,
+ 0xbabb, 0x0772,
+ 0xbac5, 0x1f42,
+ 0xbac6, 0x077d,
+ 0xbad2, 0x1f43,
+ 0xbad3, 0x078a,
+ 0xbad7, 0x1f44,
+ 0xbad9, 0x0790,
+ 0xbae4, 0x1f46,
+ 0xbae5, 0x079c,
+ 0xbae8, 0x1f47,
+ 0xbae9, 0x07a0,
+ 0xbaec, 0x1f48,
+ 0xbaed, 0x07a4,
+ 0xbaf3, 0x15e5,
+ 0xbaf4, 0x07ab,
+ 0xbaf8, 0x1f49,
+ 0xbaf9, 0x07b0,
+ 0xbba1, 0x07b6,
+ 0xbba4, 0x1f4a,
+ 0xbba5, 0x07ba,
+ 0xbba6, 0x1f4b,
+ 0xbba7, 0x07bc,
+ 0xbba9, 0x1f4c,
+ 0xbbab, 0x07c0,
+ 0xbbad, 0x1f4e,
+ 0xbbaf, 0x07c4,
+ 0xbbb0, 0x1f50,
+ 0xbbb1, 0x07c6,
+ 0xbbb3, 0x1f51,
+ 0xbbb4, 0x07c9,
+ 0xbbb5, 0x1f52,
+ 0xbbb8, 0x07cd,
+ 0xbbb9, 0x1f55,
+ 0xbbbb, 0x07d0,
+ 0xbbd1, 0x1f57,
+ 0xbbd2, 0x07e7,
+ 0xbbd3, 0x1f58,
+ 0xbbd5, 0x07ea,
+ 0xbbdf, 0x1f5a,
+ 0xbbe8, 0x07fd,
+ 0xbbeb, 0x1f63,
+ 0xbbec, 0x0801,
+ 0xbbf1, 0x1f64,
+ 0xbbf2, 0x0807,
+ 0xbbf5, 0x1f65,
+ 0xbbf8, 0x080d,
+ 0xbbfa, 0x1f68,
+ 0xbbfb, 0x0810,
+ 0xbbfd, 0x1f69,
+ 0xbbfe, 0x0813,
+ 0xbca1, 0x0814,
+ 0xbca2, 0x1f6a,
+ 0xbca3, 0x0816,
+ 0xbca5, 0x1f6b,
+ 0xbca7, 0x081a,
+ 0xbca8, 0x1f6d,
+ 0xbcaa, 0x081d,
+ 0xbcab, 0x1f6f,
+ 0xbcac, 0x081f,
+ 0xbcad, 0x1f70,
+ 0xbcae, 0x0821,
+ 0xbcb6, 0x1f71,
+ 0xbcb9, 0x082c,
+ 0xbcbb, 0x1f74,
+ 0xbcbc, 0x082f,
+ 0xbcc1, 0x1f75,
+ 0xbcc2, 0x0835,
+ 0xbcc3, 0x1f76,
+ 0xbcc4, 0x0837,
+ 0xbcc6, 0x1f77,
+ 0xbcc8, 0x083b,
+ 0xbcca, 0x1f79,
+ 0xbccb, 0x083e,
+ 0xbccc, 0x1f7a,
+ 0xbcce, 0x0841,
+ 0xbcd0, 0x1f7c,
+ 0xbcd1, 0x0844,
+ 0xbcd4, 0x1f7d,
+ 0xbcd7, 0x084a,
+ 0xbcd8, 0x1f80,
+ 0xbcd9, 0x084c,
+ 0xbcdb, 0x1f81,
+ 0xbcdc, 0x084f,
+ 0xbcdd, 0x1f82,
+ 0xbcde, 0x0851,
+ 0xbcdf, 0x1f83,
+ 0xbce2, 0x0855,
+ 0xbce3, 0x1f86,
+ 0xbce5, 0x0858,
+ 0xbce8, 0x1f88,
+ 0xbce9, 0x085c,
+ 0xbcea, 0x1f89,
+ 0xbced, 0x0860,
+ 0xbcef, 0x1f8c,
+ 0xbcf4, 0x0867,
+ 0xbcf6, 0x1f91,
+ 0xbcfd, 0x0870,
+ 0xbda1, 0x0872,
+ 0xbda2, 0x1f98,
+ 0xbda8, 0x0879,
+ 0xbdab, 0x1f9e,
+ 0xbdad, 0x087e,
+ 0xbdaf, 0x1fa0,
+ 0xbdb3, 0x0884,
+ 0xbdb4, 0x1fa4,
+ 0xbdb5, 0x0886,
+ 0xbdba, 0x1fa5,
+ 0xbdbb, 0x088c,
+ 0xbdbd, 0x1fa6,
+ 0xbdc0, 0x0891,
+ 0xbdc1, 0x1fa9,
+ 0xbdc5, 0x0896,
+ 0xbdc8, 0x1fad,
+ 0xbdcb, 0x089c,
+ 0xbdce, 0x1fb0,
+ 0xbdd0, 0x08a1,
+ 0xbdd7, 0x1fb2,
+ 0xbdd8, 0x08a9,
+ 0xbdda, 0x1fb3,
+ 0xbddb, 0x08ac,
+ 0xbde0, 0x1fb4,
+ 0xbde2, 0x08b3,
+ 0xbdeb, 0x1fb6,
+ 0xbdec, 0x08bd,
+ 0xbdf4, 0x1fb7,
+ 0xbdf9, 0x08ca,
+ 0xbdfd, 0x1fbc,
+ 0xbdfe, 0x08cf,
+ 0xbea1, 0x1fbd,
+ 0xbea3, 0x08d2,
+ 0xbea5, 0x1fbf,
+ 0xbea6, 0x08d5,
+ 0xbea8, 0x1fc0,
+ 0xbea9, 0x08d8,
+ 0xbeaa, 0x1fc1,
+ 0xbeab, 0x08da,
+ 0xbead, 0x1fc2,
+ 0xbeae, 0x08dd,
+ 0xbeb1, 0x1fc3,
+ 0xbeb2, 0x08e1,
+ 0xbeb5, 0x1fc4,
+ 0xbeb8, 0x08e7,
+ 0xbeba, 0x1fc7,
+ 0xbebb, 0x08ea,
+ 0xbec0, 0x1fc8,
+ 0xbec1, 0x08f0,
+ 0xbec9, 0x1fc9,
+ 0xbeca, 0x08f9,
+ 0xbed4, 0x1fca,
+ 0xbed5, 0x0904,
+ 0xbed9, 0x1fcb,
+ 0xbeda, 0x0909,
+ 0xbedd, 0x1fcc,
+ 0xbede, 0x090d,
+ 0xbee2, 0x1fcd,
+ 0xbee3, 0x0912,
+ 0xbee5, 0x1fce,
+ 0xbee6, 0x0915,
+ 0xbee7, 0x1fcf,
+ 0xbee8, 0x0917,
+ 0xbee9, 0x1fd0,
+ 0xbeea, 0x0919,
+ 0xbeee, 0x1fd1,
+ 0xbeef, 0x091e,
+ 0xbef5, 0x1fd2,
+ 0xbef6, 0x0925,
+ 0xbef7, 0x1fd3,
+ 0xbef9, 0x0928,
+ 0xbefb, 0x1fd5,
+ 0xbefd, 0x092c,
+ 0xbfa1, 0x092e,
+ 0xbfa5, 0x1fd7,
+ 0xbfa6, 0x0933,
+ 0xbfaa, 0x1fd8,
+ 0xbfab, 0x0938,
+ 0xbfad, 0x1fd9,
+ 0xbfae, 0x093b,
+ 0xbfc5, 0x1fda,
+ 0xbfc6, 0x0953,
+ 0xbfc7, 0x1fdb,
+ 0xbfc8, 0x0955,
+ 0xbfce, 0x1fdc,
+ 0xbfcf, 0x095c,
+ 0xbfd1, 0x1fdd,
+ 0xbfd3, 0x0960,
+ 0xbfd9, 0x1fdf,
+ 0xbfda, 0x0967,
+ 0xbfe2, 0x1fe0,
+ 0xbfe5, 0x0972,
+ 0xbfe9, 0x1fe3,
+ 0xbfea, 0x0977,
+ 0xbfeb, 0x1fe4,
+ 0xbfec, 0x0979,
+ 0xbfed, 0x1fe5,
+ 0xbfee, 0x097b,
+ 0xbff3, 0x1fe6,
+ 0xbff4, 0x0981,
+ 0xbff5, 0x1fe7,
+ 0xbff6, 0x0983,
+ 0xbff7, 0x1fe8,
+ 0xbff8, 0x0985,
+ 0xbff9, 0x1fe9,
+ 0xbffb, 0x0988,
+ 0xc0a1, 0x1feb,
+ 0xc0a2, 0x098d,
+ 0xc0a3, 0x1fec,
+ 0xc0a4, 0x098f,
+ 0xc0a9, 0x1fed,
+ 0xc0aa, 0x0995,
+ 0xc0ab, 0x1fee,
+ 0xc0ac, 0x0997,
+ 0xc0af, 0x1fef,
+ 0xc0b1, 0x099c,
+ 0xc0b3, 0x1ff1,
+ 0xc0b7, 0x09a2,
+ 0xc0b8, 0x1ff5,
+ 0xc0c5, 0x09b0,
+ 0xc0cc, 0x2002,
+ 0xc0ce, 0x09b9,
+ 0xc0d4, 0x2004,
+ 0xc0d5, 0x09c0,
+ 0xc0d6, 0x2005,
+ 0xc0d7, 0x09c2,
+ 0xc0d8, 0x2006,
+ 0xc0d9, 0x09c4,
+ 0xc0dd, 0x2007,
+ 0xc0de, 0x09c9,
+ 0xc0e0, 0x2008,
+ 0xc0e1, 0x09cc,
+ 0xc0e9, 0x2009,
+ 0xc0ea, 0x09d5,
+ 0xc0eb, 0x200a,
+ 0xc0ed, 0x09d8,
+ 0xc0ef, 0x200c,
+ 0xc0f2, 0x09dd,
+ 0xc0f6, 0x200f,
+ 0xc0fb, 0x09e6,
+ 0xc1a1, 0x09ea,
+ 0xc1a4, 0x2014,
+ 0xc1a6, 0x09ef,
+ 0xc1a9, 0x2016,
+ 0xc1ae, 0x09f7,
+ 0xc1af, 0x201b,
+ 0xc1b9, 0x0a02,
+ 0xc1bd, 0x2025,
+ 0xc1bf, 0x0a08,
+ 0xc1c2, 0x2027,
+ 0xc1c3, 0x0a0c,
+ 0xc1c6, 0x2028,
+ 0xc1c7, 0x0a10,
+ 0xc1c9, 0x2029,
+ 0xc1ca, 0x0a13,
+ 0xc1cd, 0x202a,
+ 0xc1ce, 0x0a17,
+ 0xc1d4, 0x202b,
+ 0xc1d5, 0x0a1e,
+ 0xc1d9, 0x202c,
+ 0xc1dc, 0x0a25,
+ 0xc1de, 0x202f,
+ 0xc1df, 0x0a28,
+ 0xc1e4, 0x2030,
+ 0xc1e6, 0x0a2f,
+ 0xc1e9, 0x2032,
+ 0xc1ea, 0x0a33,
+ 0xc1eb, 0x2033,
+ 0xc1ed, 0x0a36,
+ 0xc1f3, 0x2035,
+ 0xc1f4, 0x0a3d,
+ 0xc1f5, 0x2036,
+ 0xc1f6, 0x0a3f,
+ 0xc1fa, 0x2037,
+ 0xc1fe, 0x0a47,
+ 0xc2a1, 0x0a48,
+ 0xc2a2, 0x203b,
+ 0xc2a9, 0x0a50,
+ 0xc2ab, 0x2042,
+ 0xc2b4, 0x0a5b,
+ 0xc2b8, 0x204b,
+ 0xc2b9, 0x0a60,
+ 0xc2bc, 0x204c,
+ 0xc2be, 0x0a65,
+ 0xc2bf, 0x204e,
+ 0xc2c0, 0x0a67,
+ 0xc2c1, 0x204f,
+ 0xc2c2, 0x0a69,
+ 0xc2c5, 0x2050,
+ 0xc2c8, 0x0a6f,
+ 0xc2cb, 0x2053,
+ 0xc2d1, 0x0a78,
+ 0xc2d2, 0x2059,
+ 0xc2d3, 0x0a7a,
+ 0xc2d5, 0x205a,
+ 0xc2dd, 0x0a84,
+ 0xc2de, 0x2062,
+ 0xc2e3, 0x0a8a,
+ 0xc2e6, 0x2067,
+ 0xc2e9, 0x0a90,
+ 0xc2ea, 0x206a,
+ 0xc2ef, 0x0a96,
+ 0xc2f0, 0x206f,
+ 0xc2f1, 0x0a98,
+ 0xc2f2, 0x2070,
+ 0xc2f6, 0x0a9d,
+ 0xc2f7, 0x2074,
+ 0xc2fb, 0x0aa2,
+ 0xc3a1, 0x2078,
+ 0xc3a2, 0x0aa7,
+ 0xc3aa, 0x2079,
+ 0xc3ab, 0x0ab0,
+ 0xc3ad, 0x207a,
+ 0xc3ae, 0x0ab3,
+ 0xc3b3, 0x207b,
+ 0xc3b4, 0x1df9,
+ 0xc3b5, 0x0aba,
+ 0xc3be, 0x207c,
+ 0xc3bf, 0x0ac4,
+ 0xc3c5, 0x207d,
+ 0xc3c8, 0x0acd,
+ 0xc3cc, 0x2080,
+ 0xc3cd, 0x0ad2,
+ 0xc3ce, 0x2081,
+ 0xc3cf, 0x0ad4,
+ 0xc3d5, 0x2082,
+ 0xc3d7, 0x0adc,
+ 0xc3d9, 0x2084,
+ 0xc3da, 0x0adf,
+ 0xc3e0, 0x2085,
+ 0xc3e1, 0x0ae6,
+ 0xc3e5, 0x2086,
+ 0xc3e6, 0x0aeb,
+ 0xc3ed, 0x2087,
+ 0xc3ee, 0x0af3,
+ 0xc3f0, 0x2088,
+ 0xc3f1, 0x0af6,
+ 0xc3f5, 0x2089,
+ 0xc3f7, 0x0afc,
+ 0xc3f9, 0x208b,
+ 0xc3fb, 0x0b00,
+ 0xc3fd, 0x208d,
+ 0xc3fe, 0x0b03,
+ 0xc4a1, 0x0b04,
+ 0xc4b1, 0x208e,
+ 0xc4b2, 0x0b15,
+ 0xc4b6, 0x208f,
+ 0xc4b7, 0x0b1a,
+ 0xc4c6, 0x2090,
+ 0xc4c7, 0x0b2a,
+ 0xc4c9, 0x2091,
+ 0xc4ca, 0x0b2d,
+ 0xc4d1, 0x2092,
+ 0xc4d2, 0x0b35,
+ 0xc4d3, 0x2093,
+ 0xc4d7, 0x0b3a,
+ 0xc4d9, 0x2097,
+ 0xc4da, 0x0b3d,
+ 0xc4e2, 0x2098,
+ 0xc4e3, 0x0b46,
+ 0xc4e5, 0x2099,
+ 0xc4e6, 0x0b49,
+ 0xc4ec, 0x209a,
+ 0xc4ed, 0x0b50,
+ 0xc4f0, 0x209b,
+ 0xc4f2, 0x0b55,
+ 0xc4f4, 0x209d,
+ 0xc4f5, 0x0b58,
+ 0xc4f6, 0x209e,
+ 0xc4f9, 0x0b5c,
+ 0xc4fb, 0x20a1,
+ 0xc4fd, 0x0b60,
+ 0xc4fe, 0x20a3,
+ 0xc5a1, 0x20a4,
+ 0xc5a3, 0x0b64,
+ 0xc5a5, 0x20a6,
+ 0xc5aa, 0x0b6b,
+ 0xc5b1, 0x20ab,
+ 0xc5b2, 0x0b73,
+ 0xc5b5, 0x20ac,
+ 0xc5b6, 0x0b77,
+ 0xc5b7, 0x20ad,
+ 0xc5ba, 0x0b7b,
+ 0xc5bb, 0x20b0,
+ 0xc5bc, 0x0b7d,
+ 0xc5bd, 0x20b1,
+ 0xc5be, 0x0b7f,
+ 0xc5cc, 0x20b2,
+ 0xc5cd, 0x0b8e,
+ 0xc5d3, 0x20b3,
+ 0xc5d4, 0x0b95,
+ 0xc5e2, 0x20b4,
+ 0xc5e3, 0x0ba4,
+ 0xc5e7, 0x20b5,
+ 0xc5e8, 0x0ba9,
+ 0xc5f4, 0x20b6,
+ 0xc5f5, 0x0bb6,
+ 0xc6a1, 0x0bc0,
+ 0xc6ad, 0x20b7,
+ 0xc6af, 0x0bce,
+ 0xc6b5, 0x20b9,
+ 0xc6b7, 0x0bd6,
+ 0xc6bb, 0x20bb,
+ 0xc6bc, 0x0bdb,
+ 0xc6be, 0x20bc,
+ 0xc6bf, 0x0bde,
+ 0xc6c0, 0x20bd,
+ 0xc6c1, 0x0be0,
+ 0xc6c3, 0x20be,
+ 0xc6c5, 0x0be4,
+ 0xc6cb, 0x20c0,
+ 0xc6ce, 0x0bed,
+ 0xc6d3, 0x20c3,
+ 0xc6d4, 0x0bf3,
+ 0xc6d7, 0x20c4,
+ 0xc6d8, 0x0bf7,
+ 0xc6ea, 0x20c5,
+ 0xc6ec, 0x0c0b,
+ 0xc6ef, 0x20c7,
+ 0xc6f0, 0x0c0f,
+ 0xc6f1, 0x20c8,
+ 0xc6f2, 0x0c11,
+ 0xc6f4, 0x20c9,
+ 0xc6f5, 0x0c14,
+ 0xc6f8, 0x20ca,
+ 0xc6f9, 0x0c18,
+ 0xc6fd, 0x20cb,
+ 0xc6fe, 0x0c1d,
+ 0xc7a1, 0x0c1e,
+ 0xc7a3, 0x20cc,
+ 0xc7a4, 0x0c21,
+ 0xc7a5, 0x20cd,
+ 0xc7a7, 0x0c24,
+ 0xc7a8, 0x20cf,
+ 0xc7aa, 0x0c27,
+ 0xc7ab, 0x20d1,
+ 0xc7ac, 0x0c29,
+ 0xc7ae, 0x20d2,
+ 0xc7b0, 0x0c2d,
+ 0xc7b3, 0x20d4,
+ 0xc7b6, 0x0c33,
+ 0xc7b9, 0x20d7,
+ 0xc7bb, 0x0c38,
+ 0xc7bd, 0x20d9,
+ 0xc7bf, 0x0c3c,
+ 0xc7c0, 0x20db,
+ 0xc7c1, 0x0c3e,
+ 0xc7c2, 0x20dc,
+ 0xc7c3, 0x0c40,
+ 0xc7c5, 0x20dd,
+ 0xc7c6, 0x0c43,
+ 0xc7c7, 0x20de,
+ 0xc7c9, 0x0c46,
+ 0xc7cc, 0x20e0,
+ 0xc7cd, 0x0c4a,
+ 0xc7cf, 0x20e1,
+ 0xc7d0, 0x0c4d,
+ 0xc7d4, 0x20e2,
+ 0xc7d6, 0x0c53,
+ 0xc7d7, 0x20e4,
+ 0xc7d8, 0x0c55,
+ 0xc7de, 0x20e5,
+ 0xc7df, 0x0c5c,
+ 0xc7e1, 0x20e6,
+ 0xc7e4, 0x0c61,
+ 0xc7ea, 0x20e9,
+ 0xc7ef, 0x0c6c,
+ 0xc7f7, 0x20ee,
+ 0xc7f9, 0x0c76,
+ 0xc7fb, 0x20f0,
+ 0xc7fc, 0x0c79,
+ 0xc7fd, 0x20f1,
+ 0xc7fe, 0x0c7b,
+ 0xc8a1, 0x0c7c,
+ 0xc8a3, 0x20f2,
+ 0xc8a4, 0x0c7f,
+ 0xc8a7, 0x20f3,
+ 0xc8a9, 0x0c84,
+ 0xc8b0, 0x20f5,
+ 0xc8b1, 0x0c8c,
+ 0xc8b5, 0x20f6,
+ 0xc8b6, 0x0c91,
+ 0xc8b7, 0x20f7,
+ 0xc8b8, 0x0c93,
+ 0xc8c3, 0x20f8,
+ 0xc8c7, 0x0ca2,
+ 0xc8c8, 0x20fc,
+ 0xc8c9, 0x0ca4,
+ 0xc8cd, 0x20fd,
+ 0xc8ce, 0x0ca9,
+ 0xc8cf, 0x20fe,
+ 0xc8d0, 0x0cab,
+ 0xc8d2, 0x20ff,
+ 0xc8d3, 0x0cae,
+ 0xc8d9, 0x2100,
+ 0xc8da, 0x0cb5,
+ 0xc8de, 0x2101,
+ 0xc8df, 0x0cba,
+ 0xc8ed, 0x2102,
+ 0xc8ee, 0x0cc9,
+ 0xc8f1, 0x2103,
+ 0xc8f4, 0x0ccf,
+ 0xc8f7, 0x2106,
+ 0xc8f9, 0x0cd4,
+ 0xc8fa, 0x2108,
+ 0xc8fb, 0x0cd6,
+ 0xc8fc, 0x2109,
+ 0xc8fd, 0x0cd8,
+ 0xc9a1, 0x210a,
+ 0xc9a2, 0x0cdb,
+ 0xc9a5, 0x210b,
+ 0xc9a6, 0x0cdf,
+ 0xc9a7, 0x210c,
+ 0xc9a9, 0x0ce2,
+ 0xc9ac, 0x210e,
+ 0xc9ad, 0x0ce6,
+ 0xc9b1, 0x210f,
+ 0xc9b2, 0x0ceb,
+ 0xc9b4, 0x2110,
+ 0xc9b5, 0x0cee,
+ 0xc9b8, 0x2111,
+ 0xc9ba, 0x0cf3,
+ 0xc9c1, 0x2113,
+ 0xc9c3, 0x0cfc,
+ 0xc9c4, 0x2115,
+ 0xc9c5, 0x0cfe,
+ 0xc9c9, 0x2116,
+ 0xc9ca, 0x0d03,
+ 0xc9cb, 0x2117,
+ 0xc9cc, 0x0d05,
+ 0xc9cd, 0x2118,
+ 0xc9ce, 0x0d07,
+ 0xc9d5, 0x2119,
+ 0xc9d6, 0x0d0f,
+ 0xc9dc, 0x211a,
+ 0xc9dd, 0x0d16,
+ 0xc9de, 0x211b,
+ 0xc9df, 0x0d18,
+ 0xc9e1, 0x211c,
+ 0xc9e2, 0x0d1b,
+ 0xc9e3, 0x211d,
+ 0xc9e4, 0x0d1d,
+ 0xc9e5, 0x211e,
+ 0xc9e6, 0x0d1f,
+ 0xc9e8, 0x211f,
+ 0xc9e9, 0x0d22,
+ 0xc9f0, 0x2120,
+ 0xc9f1, 0x0d2a,
+ 0xc9f3, 0x2121,
+ 0xc9f5, 0x0d2e,
+ 0xc9f6, 0x2123,
+ 0xc9f7, 0x0d30,
+ 0xc9f8, 0x2124,
+ 0xc9fa, 0x0d33,
+ 0xc9fe, 0x2126,
+ 0xcaa1, 0x0d38,
+ 0xcaa4, 0x2127,
+ 0xcaa7, 0x0d3e,
+ 0xcaa8, 0x212a,
+ 0xcaa9, 0x0d40,
+ 0xcaaa, 0x212b,
+ 0xcaac, 0x0d43,
+ 0xcab1, 0x212d,
+ 0xcab2, 0x0d49,
+ 0xcab4, 0x212e,
+ 0xcab7, 0x0d4e,
+ 0xcabb, 0x2131,
+ 0xcabc, 0x0d53,
+ 0xcac6, 0x2132,
+ 0xcac7, 0x0d5e,
+ 0xcaca, 0x2133,
+ 0xcacb, 0x0d62,
+ 0xcacd, 0x2134,
+ 0xcacf, 0x0d66,
+ 0xcad3, 0x2136,
+ 0xcad5, 0x0d6c,
+ 0xcad9, 0x2138,
+ 0xcada, 0x0d71,
+ 0xcade, 0x2139,
+ 0xcadf, 0x0d76,
+ 0xcae0, 0x213a,
+ 0xcae1, 0x0d78,
+ 0xcae4, 0x213b,
+ 0xcae5, 0x0d7c,
+ 0xcae9, 0x213c,
+ 0xcaeb, 0x0d82,
+ 0xcaf4, 0x213e,
+ 0xcaf6, 0x0d8d,
+ 0xcaf7, 0x2140,
+ 0xcaf8, 0x0d8f,
+ 0xcafa, 0x2141,
+ 0xcafb, 0x0d92,
+ 0xcafd, 0x2142,
+ 0xcafe, 0x0d95,
+ 0xcba1, 0x0d96,
+ 0xcba7, 0x2143,
+ 0xcba8, 0x0d9d,
+ 0xcbab, 0x2144,
+ 0xcbac, 0x0da1,
+ 0xcbad, 0x2145,
+ 0xcbae, 0x0da3,
+ 0xcbb3, 0x2146,
+ 0xcbb4, 0x0da9,
+ 0xcbb5, 0x2147,
+ 0xcbb7, 0x0dac,
+ 0xcbb8, 0x2149,
+ 0xcbb9, 0x0dae,
+ 0xcbbf, 0x214a,
+ 0xcbc0, 0x0db5,
+ 0xcbc7, 0x214b,
+ 0xcbc8, 0x0dbd,
+ 0xcbc9, 0x214c,
+ 0xcbcd, 0x0dc2,
+ 0xcbcf, 0x2150,
+ 0xcbd1, 0x0dc6,
+ 0xcbd3, 0x2152,
+ 0xcbd4, 0x0dc9,
+ 0xcbd5, 0x2153,
+ 0xcbd6, 0x0dcb,
+ 0xcbdf, 0x2154,
+ 0xcbe1, 0x0dd6,
+ 0xcbe4, 0x2156,
+ 0xcbe5, 0x0dda,
+ 0xcbe6, 0x2157,
+ 0xcbe8, 0x0ddd,
+ 0xcbea, 0x2159,
+ 0xcbeb, 0x0de0,
+ 0xcbef, 0x215a,
+ 0xcbf1, 0x0de6,
+ 0xcbf5, 0x215c,
+ 0xcbf7, 0x0dec,
+ 0xcbf8, 0x215e,
+ 0xcbf9, 0x0dee,
+ 0xcca1, 0x215f,
+ 0xcca3, 0x0df6,
+ 0xcca8, 0x2161,
+ 0xcca9, 0x0dfc,
+ 0xccac, 0x2162,
+ 0xccad, 0x0e00,
+ 0xccaf, 0x2163,
+ 0xccb4, 0x0e07,
+ 0xccb7, 0x2168,
+ 0xccb9, 0x0e0c,
+ 0xccbe, 0x216a,
+ 0xccbf, 0x0e12,
+ 0xccc0, 0x216b,
+ 0xccc1, 0x0e14,
+ 0xcccc, 0x216c,
+ 0xcccd, 0x0e20,
+ 0xccce, 0x216d,
+ 0xcccf, 0x0e22,
+ 0xccd0, 0x216e,
+ 0xccd1, 0x0e24,
+ 0xccd6, 0x216f,
+ 0xccd7, 0x0e2a,
+ 0xccda, 0x2170,
+ 0xccdb, 0x0e2e,
+ 0xccdc, 0x2171,
+ 0xccdd, 0x0e30,
+ 0xcce0, 0x2172,
+ 0xcce1, 0x0e34,
+ 0xcce2, 0x2173,
+ 0xcce3, 0x0e36,
+ 0xcce5, 0x2174,
+ 0xcce6, 0x0e39,
+ 0xccf5, 0x2175,
+ 0xccf6, 0x0e49,
+ 0xccf9, 0x2176,
+ 0xccfb, 0x0e4e,
+ 0xccfc, 0x2178,
+ 0xcda1, 0x0e52,
+ 0xcdad, 0x217b,
+ 0xcdae, 0x0e5f,
+ 0xcdb3, 0x217c,
+ 0xcdb4, 0x0e65,
+ 0xcdb7, 0x217d,
+ 0xcdb8, 0x0e69,
+ 0xcdbc, 0x217e,
+ 0xcdbd, 0x0e6e,
+ 0xcdbf, 0x217f,
+ 0xcdc0, 0x0e71,
+ 0xcdc5, 0x2180,
+ 0xcdc6, 0x0e77,
+ 0xcdc7, 0x2181,
+ 0xcdc8, 0x0e79,
+ 0xcdd2, 0x2182,
+ 0xcdd3, 0x0e84,
+ 0xcdd4, 0x2183,
+ 0xcdd7, 0x0e88,
+ 0xcddd, 0x2186,
+ 0xcdde, 0x0e8f,
+ 0xcde0, 0x2187,
+ 0xcde1, 0x0e92,
+ 0xcde4, 0x2188,
+ 0xcde6, 0x0e97,
+ 0xcde7, 0x218a,
+ 0xcde8, 0x0e99,
+ 0xcdf2, 0x218b,
+ 0xcdf3, 0x0ea4,
+ 0xcdf8, 0x218c,
+ 0xcdf9, 0x0eaa,
+ 0xcea1, 0x0eb0,
+ 0xcea4, 0x218d,
+ 0xcea6, 0x0eb5,
+ 0xcea7, 0x218f,
+ 0xcea8, 0x0eb7,
+ 0xceaa, 0x2190,
+ 0xceae, 0x0ebd,
+ 0xceb0, 0x2194,
+ 0xceb2, 0x0ec1,
+ 0xceb3, 0x2196,
+ 0xceb4, 0x0ec3,
+ 0xcebd, 0x2197,
+ 0xcebe, 0x0ecd,
+ 0xcec0, 0x2198,
+ 0xcec1, 0x0ed0,
+ 0xcec5, 0x2199,
+ 0xcec7, 0x0ed6,
+ 0xcec8, 0x219b,
+ 0xcec9, 0x0ed8,
+ 0xceca, 0x219c,
+ 0xcecb, 0x0eda,
+ 0xcece, 0x219d,
+ 0xced2, 0x0ee1,
+ 0xced8, 0x21a1,
+ 0xcedb, 0x0eea,
+ 0xcedc, 0x21a4,
+ 0xcedd, 0x0eec,
+ 0xcede, 0x21a5,
+ 0xcee0, 0x0eef,
+ 0xceeb, 0x21a7,
+ 0xceec, 0x0efb,
+ 0xceed, 0x21a8,
+ 0xceee, 0x0efd,
+ 0xcef1, 0x21a9,
+ 0xcef2, 0x0f01,
+ 0xcef3, 0x21aa,
+ 0xcef4, 0x0f03,
+ 0xcefd, 0x21ab,
+ 0xcfa1, 0x0f0e,
+ 0xcfae, 0x21ad,
+ 0xcfaf, 0x0f1c,
+ 0xcfb0, 0x21ae,
+ 0xcfb1, 0x0f1e,
+ 0xcfb3, 0x21af,
+ 0xcfb4, 0x0f21,
+ 0xcfb7, 0x21b0,
+ 0xcfb9, 0x0f26,
+ 0xcfba, 0x21b2,
+ 0xcfbb, 0x0f28,
+ 0xcfbd, 0x21b3,
+ 0xcfbe, 0x0f2b,
+ 0xcfbf, 0x21b4,
+ 0xcfc2, 0x0f2f,
+ 0xcfc5, 0x21b7,
+ 0xcfc6, 0x0f33,
+ 0xcfc7, 0x21b8,
+ 0xcfc8, 0x0f35,
+ 0xcfca, 0x21b9,
+ 0xcfcc, 0x0f39,
+ 0xcfcd, 0x21bb,
+ 0xcfcf, 0x0f3c,
+ 0xcfd0, 0x21bd,
+ 0xcfd1, 0x0f3e,
+ 0xcfd4, 0x21be,
+ 0xcfd9, 0x0f46,
+ 0xcfda, 0x21c3,
+ 0xcfdb, 0x0f48,
+ 0xcfdc, 0x21c4,
+ 0xcfdd, 0x0f4a,
+ 0xcfdf, 0x21c5,
+ 0xcfe0, 0x0f4d,
+ 0xcfe2, 0x21c6,
+ 0xcfe3, 0x0f50,
+ 0xcfe7, 0x21c7,
+ 0xcfe8, 0x0f55,
+ 0xcfea, 0x21c8,
+ 0xcfeb, 0x0f58,
+ 0xcfec, 0x21c9,
+ 0xcfed, 0x0f5a,
+ 0xcfee, 0x21ca,
+ 0xcfef, 0x0f5c,
+ 0xcff4, 0x21cb,
+ 0xcff5, 0x0f62,
+ 0xcff9, 0x21cc,
+ 0xcffb, 0x0f68,
+ 0xcffe, 0x21ce,
+ 0xd0a1, 0x0f6c,
+ 0xd0a5, 0x21cf,
+ 0xd0a6, 0x0f71,
+ 0xd0ad, 0x21d0,
+ 0xd0af, 0x0f7a,
+ 0xd0b2, 0x21d2,
+ 0xd0b5, 0x0f80,
+ 0xd0ba, 0x21d5,
+ 0xd0bc, 0x0f87,
+ 0xd0bf, 0x21d7,
+ 0xd0c0, 0x0f8b,
+ 0xd0c6, 0x21d8,
+ 0xd0c7, 0x0f92,
+ 0xd0cb, 0x21d9,
+ 0xd0cc, 0x0f97,
+ 0xd0e2, 0x21da,
+ 0xd0e3, 0x0fae,
+ 0xd0e5, 0x21db,
+ 0xd0e6, 0x0fb1,
+ 0xd0eb, 0x21dc,
+ 0xd0ec, 0x0fb7,
+ 0xd0ed, 0x21dd,
+ 0xd0ee, 0x0fb9,
+ 0xd0f7, 0x21de,
+ 0xd0fa, 0x0fc5,
+ 0xd0fc, 0x21e1,
+ 0xd0fd, 0x0fc8,
+ 0xd1a1, 0x21e2,
+ 0xd1a3, 0x0fcc,
+ 0xd1a4, 0x21e4,
+ 0xd1a5, 0x0fce,
+ 0xd1a7, 0x21e5,
+ 0xd1a8, 0x0fd1,
+ 0xd1ab, 0x21e6,
+ 0xd1ac, 0x0fd5,
+ 0xd1af, 0x21e7,
+ 0xd1b2, 0x0fdb,
+ 0xd1b5, 0x21ea,
+ 0xd1b8, 0x0fe1,
+ 0xd1b9, 0x21ed,
+ 0xd1ba, 0x0fe3,
+ 0xd1bb, 0x21ee,
+ 0xd1bd, 0x0fe6,
+ 0xd1c6, 0x21f0,
+ 0xd1c9, 0x0ff2,
+ 0xd1cb, 0x21f3,
+ 0xd1cc, 0x0ff5,
+ 0xd1ce, 0x21f4,
+ 0xd1d0, 0x0ff9,
+ 0xd1d5, 0x21f6,
+ 0xd1d7, 0x1000,
+ 0xd1de, 0x21f8,
+ 0xd1df, 0x1008,
+ 0xd1e1, 0x21f9,
+ 0xd1e3, 0x100c,
+ 0xd1e8, 0x21fb,
+ 0xd1ea, 0x1013,
+ 0xd1ec, 0x21fd,
+ 0xd1ed, 0x1016,
+ 0xd1ee, 0x21fe,
+ 0xd1f0, 0x1019,
+ 0xd1f1, 0x2200,
+ 0xd1f2, 0x101b,
+ 0xd1f4, 0x2201,
+ 0xd1f5, 0x101e,
+ 0xd1f7, 0x2202,
+ 0xd1fa, 0x1023,
+ 0xd2a1, 0x1028,
+ 0xd2a2, 0x2205,
+ 0xd2a3, 0x102a,
+ 0xd2a5, 0x2206,
+ 0xd2a6, 0x102d,
+ 0xd2a9, 0x2207,
+ 0xd2aa, 0x1031,
+ 0xd2af, 0x2208,
+ 0xd2b0, 0x1037,
+ 0xd2b3, 0x2209,
+ 0xd2b4, 0x103b,
+ 0xd2b5, 0x220a,
+ 0xd2b7, 0x103e,
+ 0xd2bd, 0x220c,
+ 0xd2be, 0x1045,
+ 0xd2bf, 0x220d,
+ 0xd2c0, 0x1047,
+ 0xd2c3, 0x220e,
+ 0xd2c4, 0x104b,
+ 0xd2c5, 0x220f,
+ 0xd2c6, 0x104d,
+ 0xd2c7, 0x2210,
+ 0xd2c8, 0x104f,
+ 0xd2cf, 0x2211,
+ 0xd2d0, 0x1057,
+ 0xd2d5, 0x2212,
+ 0xd2d6, 0x105d,
+ 0xd2da, 0x2213,
+ 0xd2db, 0x1062,
+ 0xd2e4, 0x2214,
+ 0xd2e6, 0x106d,
+ 0xd2e8, 0x2216,
+ 0xd2ec, 0x1073,
+ 0xd2ef, 0x221a,
+ 0xd2f0, 0x1077,
+ 0xd2f1, 0x221b,
+ 0xd2f2, 0x1079,
+ 0xd2f5, 0x221c,
+ 0xd2f6, 0x107d,
+ 0xd2f8, 0x221d,
+ 0xd2f9, 0x1080,
+ 0xd2fb, 0x221e,
+ 0xd2fc, 0x1083,
+ 0xd2fe, 0x221f,
+ 0xd3a1, 0x1086,
+ 0xd3a3, 0x2220,
+ 0xd3ad, 0x1092,
+ 0xd3ae, 0x222a,
+ 0xd3af, 0x1094,
+ 0xd3b1, 0x222b,
+ 0xd3b2, 0x1097,
+ 0xd3b4, 0x222c,
+ 0xd3b7, 0x109c,
+ 0xd3b8, 0x222f,
+ 0xd3b9, 0x109e,
+ 0xd3bb, 0x2230,
+ 0xd3bc, 0x10a1,
+ 0xd3c5, 0x2231,
+ 0xd3c6, 0x10ab,
+ 0xd3c7, 0x2232,
+ 0xd3c8, 0x10ad,
+ 0xd3ca, 0x2233,
+ 0xd3cd, 0x10b2,
+ 0xd3d5, 0x2236,
+ 0xd3d6, 0x10bb,
+ 0xd3df, 0x2237,
+ 0xd3e1, 0x10c6,
+ 0xd3e3, 0x2239,
+ 0xd3e4, 0x10c9,
+ 0xd3e6, 0x223a,
+ 0xd3e7, 0x10cc,
+ 0xd3eb, 0x223b,
+ 0xd3ed, 0x10d2,
+ 0xd3ef, 0x223d,
+ 0xd3f0, 0x10d5,
+ 0xd3f4, 0x223e,
+ 0xd3f5, 0x10da,
+ 0xd3fc, 0x223f,
+ 0xd3fd, 0x10e2,
+ 0xd3fe, 0x2240,
+ 0xd4a1, 0x10e4,
+ 0xd4a4, 0x2241,
+ 0xd4a5, 0x10e8,
+ 0xd4a6, 0x2242,
+ 0xd4a9, 0x10ec,
+ 0xd4af, 0x2245,
+ 0xd4b3, 0x10f6,
+ 0xd4b5, 0x2249,
+ 0xd4b7, 0x10fa,
+ 0xd4b8, 0x224b,
+ 0xd4b9, 0x10fc,
+ 0xd4bc, 0x224c,
+ 0xd4bd, 0x1100,
+ 0xd4be, 0x224d,
+ 0xd4c0, 0x1103,
+ 0xd4c4, 0x224f,
+ 0xd4c5, 0x1108,
+ 0xd4c6, 0x2250,
+ 0xd4c8, 0x110b,
+ 0xd4c9, 0x2252,
+ 0xd4ca, 0x110d,
+ 0xd4cb, 0x2253,
+ 0xd4cf, 0x1112,
+ 0xd4d3, 0x2257,
+ 0xd4d4, 0x1117,
+ 0xd4d8, 0x2258,
+ 0xd4d9, 0x111c,
+ 0xd4dc, 0x2259,
+ 0xd4e1, 0x1124,
+ 0xd4e4, 0x225e,
+ 0xd4e5, 0x1128,
+ 0xd4e6, 0x225f,
+ 0xd4e7, 0x112a,
+ 0xd4ee, 0x2260,
+ 0xd4ef, 0x1132,
+ 0xd4f0, 0x2261,
+ 0xd4f5, 0x1138,
+ 0xd4f9, 0x2266,
+ 0xd4fa, 0x113d,
+ 0xd4fe, 0x2267,
+ 0xd5a1, 0x2268,
+ 0xd5a3, 0x1144,
+ 0xd5a9, 0x226a,
+ 0xd5aa, 0x114b,
+ 0xd5ab, 0x226b,
+ 0xd5ac, 0x114d,
+ 0xd5ae, 0x226c,
+ 0xd5af, 0x1150,
+ 0xd5b1, 0x226d,
+ 0xd5b2, 0x1153,
+ 0xd5b5, 0x226e,
+ 0xd5b9, 0x115a,
+ 0xd5bb, 0x2272,
+ 0xd5bc, 0x115d,
+ 0xd5bd, 0x2273,
+ 0xd5be, 0x115f,
+ 0xd5c0, 0x2274,
+ 0xd5c1, 0x1162,
+ 0xd5c5, 0x2275,
+ 0xd5c6, 0x1167,
+ 0xd5c7, 0x2276,
+ 0xd5c8, 0x1169,
+ 0xd5ca, 0x2277,
+ 0xd5cc, 0x116d,
+ 0xd5cd, 0x2279,
+ 0xd5ce, 0x116f,
+ 0xd5d4, 0x227a,
+ 0xd5d5, 0x1176,
+ 0xd5dd, 0x227b,
+ 0xd5df, 0x1180,
+ 0xd5e0, 0x227d,
+ 0xd5e1, 0x1182,
+ 0xd5e2, 0x227e,
+ 0xd5e3, 0x1184,
+ 0xd5ea, 0x227f,
+ 0xd5ed, 0x118e,
+ 0xd5ef, 0x2282,
+ 0xd5f0, 0x1191,
+ 0xd5f2, 0x2283,
+ 0xd5f4, 0x1195,
+ 0xd5f7, 0x15eb,
+ 0xd5f8, 0x1199,
+ 0xd6a1, 0x2285,
+ 0xd6a5, 0x11a4,
+ 0xd6af, 0x2289,
+ 0xd6b1, 0x11b0,
+ 0xd6b4, 0x228b,
+ 0xd6b5, 0x11b4,
+ 0xd6bb, 0x228c,
+ 0xd6bc, 0x11bb,
+ 0xd6bd, 0x228d,
+ 0xd6be, 0x11bd,
+ 0xd6bf, 0x228e,
+ 0xd6c1, 0x11c0,
+ 0xd6c4, 0x2290,
+ 0xd6c5, 0x11c4,
+ 0xd6ca, 0x2291,
+ 0xd6cb, 0x11ca,
+ 0xd6cd, 0x2292,
+ 0xd6ce, 0x11cd,
+ 0xd6d3, 0x2293,
+ 0xd6d4, 0x11d3,
+ 0xd6d5, 0x2294,
+ 0xd6d8, 0x11d7,
+ 0xd6da, 0x2297,
+ 0xd6db, 0x11da,
+ 0xd6df, 0x2298,
+ 0xd6e0, 0x11df,
+ 0xd6e1, 0x2299,
+ 0xd6e2, 0x11e1,
+ 0xd6e5, 0x229a,
+ 0xd6e6, 0x11e5,
+ 0xd6e7, 0x229b,
+ 0xd6e9, 0x11e8,
+ 0xd6ee, 0x229d,
+ 0xd6f0, 0x11ef,
+ 0xd6f2, 0x229f,
+ 0xd6f3, 0x11f2,
+ 0xd6f5, 0x22a0,
+ 0xd6f7, 0x11f6,
+ 0xd6fc, 0x22a2,
+ 0xd7a1, 0x11fe,
+ 0xd7a4, 0x22a5,
+ 0xd7a5, 0x1202,
+ 0xd7a8, 0x22a6,
+ 0xd7ab, 0x1208,
+ 0xd7ac, 0x22a9,
+ 0xd7ad, 0x120a,
+ 0xd7ae, 0x22aa,
+ 0xd7b2, 0x120f,
+ 0xd7b3, 0x22ae,
+ 0xd7b5, 0x1212,
+ 0xd7b6, 0x22b0,
+ 0xd7b7, 0x1214,
+ 0xd7b8, 0x22b1,
+ 0xd7bd, 0x121a,
+ 0xd7c7, 0x22b6,
+ 0xd7c8, 0x1225,
+ 0xd7ca, 0x22b7,
+ 0xd7cb, 0x1228,
+ 0xd7d5, 0x22b8,
+ 0xd7d6, 0x1233,
+ 0xd7db, 0x22b9,
+ 0xd7df, 0x123c,
+ 0xd7e7, 0x22bd,
+ 0xd7e8, 0x1245,
+ 0xd7e9, 0x22be,
+ 0xd7eb, 0x1248,
+ 0xd8a1, 0x1257,
+ 0xd8c4, 0x22c0,
+ 0xd8c5, 0x127b,
+ 0xd8c7, 0x22c1,
+ 0xd8c8, 0x127e,
+ 0xd8c9, 0x22c2,
+ 0xd8ca, 0x1280,
+ 0xd8cc, 0x22c3,
+ 0xd8ce, 0x1284,
+ 0xd8d0, 0x22c5,
+ 0xd8d2, 0x1288,
+ 0xd8d3, 0x22c7,
+ 0xd8d4, 0x128a,
+ 0xd8d9, 0x22c8,
+ 0xd8da, 0x1290,
+ 0xd8db, 0x22c9,
+ 0xd8dd, 0x1293,
+ 0xd8f1, 0x22cb,
+ 0xd8f2, 0x12a8,
+ 0xd8f6, 0x22cc,
+ 0xd8f8, 0x12ae,
+ 0xd9a1, 0x12b5,
+ 0xd9ad, 0x22ce,
+ 0xd9ae, 0x12c2,
+ 0xd9af, 0x22cf,
+ 0xd9b0, 0x12c4,
+ 0xd9b1, 0x22d0,
+ 0xd9b4, 0x12c8,
+ 0xd9c7, 0x22d3,
+ 0xd9c8, 0x12dc,
+ 0xd9cd, 0x22d4,
+ 0xd9d1, 0x12e5,
+ 0xd9dd, 0x22d8,
+ 0xd9de, 0x12f2,
+ 0xd9e1, 0x22d9,
+ 0xd9e2, 0x12f6,
+ 0xd9e4, 0x22da,
+ 0xd9e5, 0x12f9,
+ 0xd9e6, 0x22db,
+ 0xd9e7, 0x12fb,
+ 0xd9ec, 0x22dc,
+ 0xd9ed, 0x1301,
+ 0xd9f4, 0x22dd,
+ 0xd9f6, 0x130a,
+ 0xdaa1, 0x1313,
+ 0xdaa5, 0x22df,
+ 0xdae0, 0x1352,
+ 0xdaea, 0x231a,
+ 0xdaeb, 0x135d,
+ 0xdaf7, 0x231b,
+ 0xdaf8, 0x136a,
+ 0xdaf9, 0x231c,
+ 0xdafa, 0x136c,
+ 0xdafe, 0x231d,
+ 0xdba1, 0x1371,
+ 0xdba3, 0x231e,
+ 0xdba4, 0x1374,
+ 0xdba6, 0x231f,
+ 0xdba7, 0x1377,
+ 0xdba9, 0x2320,
+ 0xdbab, 0x137b,
+ 0xdbbb, 0x2322,
+ 0xdbbc, 0x138c,
+ 0xdbbd, 0x2323,
+ 0xdbbe, 0x138e,
+ 0xdbcf, 0x2324,
+ 0xdbd0, 0x13a0,
+ 0xdbd1, 0x2325,
+ 0xdbd2, 0x13a2,
+ 0xdbdb, 0x2326,
+ 0xdbdc, 0x13ac,
+ 0xdbde, 0x2327,
+ 0xdbdf, 0x13af,
+ 0xdbe2, 0x2328,
+ 0xdbe3, 0x13b3,
+ 0xdbe4, 0x2329,
+ 0xdbe5, 0x13b5,
+ 0xdbeb, 0x232a,
+ 0xdbec, 0x13bc,
+ 0xdbee, 0x232b,
+ 0xdbef, 0x13bf,
+ 0xdbf1, 0x232c,
+ 0xdbf2, 0x13c2,
+ 0xdbf5, 0x232d,
+ 0xdbf8, 0x13c8,
+ 0xdca1, 0x13cf,
+ 0xdcbc, 0x2330,
+ 0xdcbd, 0x13eb,
+ 0xdcbf, 0x2331,
+ 0xdcc0, 0x13ee,
+ 0xdcc2, 0x2332,
+ 0xdcc3, 0x13f1,
+ 0xdcc8, 0x2333,
+ 0xdccb, 0x13f9,
+ 0xdcd1, 0x2336,
+ 0xdcd2, 0x1400,
+ 0xdcd7, 0x2337,
+ 0xdcd8, 0x1406,
+ 0xdce0, 0x2338,
+ 0xdce1, 0x140f,
+ 0xdce3, 0x2339,
+ 0xdce5, 0x1413,
+ 0xdce9, 0x233b,
+ 0xdceb, 0x1419,
+ 0xdcf1, 0x233d,
+ 0xdcf2, 0x1420,
+ 0xdcf6, 0x233e,
+ 0xdcf7, 0x1425,
+ 0xdcf9, 0x233f,
+ 0xdcfa, 0x1428,
+ 0xdcfd, 0x2340,
+ 0xdda1, 0x2342,
+ 0xdda2, 0x142e,
+ 0xdda3, 0x2343,
+ 0xdda8, 0x1434,
+ 0xddaa, 0x2348,
+ 0xddac, 0x1438,
+ 0xddb2, 0x234a,
+ 0xddb3, 0x143f,
+ 0xddb5, 0x234b,
+ 0xddb6, 0x1442,
+ 0xddba, 0x234c,
+ 0xddbc, 0x1448,
+ 0xddd3, 0x234e,
+ 0xddd4, 0x1460,
+ 0xdddb, 0x234f,
+ 0xdddc, 0x1468,
+ 0xddde, 0x2350,
+ 0xdddf, 0x146b,
+ 0xdde4, 0x2351,
+ 0xdde5, 0x1471,
+ 0xddeb, 0x2352,
+ 0xddec, 0x1478,
+ 0xddf1, 0x2353,
+ 0xddf2, 0x147e,
+ 0xddf6, 0x2354,
+ 0xddf8, 0x1484,
+ 0xddfc, 0x2356,
+ 0xddfd, 0x1489,
+ 0xddfe, 0x2357,
+ 0xdea1, 0x148b,
+ 0xdead, 0x2358,
+ 0xdeae, 0x1498,
+ 0xdeb4, 0x2359,
+ 0xdeb5, 0x149f,
+ 0xdeba, 0x235a,
+ 0xdebb, 0x14a5,
+ 0xdec6, 0x235b,
+ 0xdec7, 0x14b1,
+ 0xdecf, 0x235c,
+ 0xded0, 0x14ba,
+ 0xded1, 0x235d,
+ 0xded3, 0x14bd,
+ 0xded8, 0x235f,
+ 0xded9, 0x14c3,
+ 0xdee2, 0x2360,
+ 0xdee3, 0x14cd,
+ 0xdee8, 0x2361,
+ 0xdee9, 0x14d3,
+ 0xdeec, 0x2362,
+ 0xdeed, 0x14d7,
+ 0xdef3, 0x2363,
+ 0xdef4, 0x14de,
+ 0xdefc, 0x2364,
+ 0xdefd, 0x14e7,
+ 0xdfa1, 0x14e9,
+ 0xdfa2, 0x2365,
+ 0xdfa4, 0x14ec,
+ 0xdfa5, 0x2367,
+ 0xdfa6, 0x14ee,
+ 0xdfb4, 0x2368,
+ 0xdfb5, 0x14fd,
+ 0xdfbc, 0x2369,
+ 0xdfbe, 0x1506,
+ 0xdfbf, 0x236b,
+ 0xdfc0, 0x1508,
+ 0xdfc2, 0x236c,
+ 0xdfc4, 0x150c,
+ 0xdfcc, 0x236e,
+ 0xdfcd, 0x1515,
+ 0xdfd0, 0x236f,
+ 0xdfd1, 0x1519,
+ 0xdfd5, 0x2370,
+ 0xdfd6, 0x151e,
+ 0xdfd8, 0x2371,
+ 0xdfda, 0x1522,
+ 0xdfdc, 0x2373,
+ 0xdfdd, 0x1525,
+ 0xdfe0, 0x2374,
+ 0xdfe1, 0x1529,
+ 0xdfe2, 0x2375,
+ 0xdfe3, 0x152b,
+ 0xdfe6, 0x2376,
+ 0xdfe7, 0x152f,
+ 0xdfe9, 0x2377,
+ 0xdfea, 0x1532,
+ 0xdfeb, 0x2378,
+ 0xdfec, 0x1534,
+ 0xdfef, 0x2379,
+ 0xdff0, 0x1538,
+ 0xdff5, 0x237a,
+ 0xdff6, 0x153e,
+ 0xdff9, 0x237b,
+ 0xdffa, 0x1542,
+ 0xe0a1, 0x1547,
+ 0xe0b6, 0x237c,
+ 0xe0b8, 0x155e,
+ 0xe0bf, 0x237e,
+ 0xe0c0, 0x1566,
+ 0xe0c8, 0x237f,
+ 0xe0c9, 0x156f,
+ 0xe0ce, 0x2380,
+ 0xe0cf, 0x1575,
+ 0xe0d3, 0x2381,
+ 0xe0d4, 0x157a,
+ 0xe0e0, 0x2382,
+ 0xe0e1, 0x1587,
+ 0xe0f0, 0x2383,
+ 0xe0f1, 0x1597,
+ 0xe0f8, 0x2384,
+ 0xe0f9, 0x159f,
+ 0xe0fc, 0x2385,
+ 0xe1a1, 0x15a5,
+ 0xe1ab, 0x2388,
+ 0xe1ac, 0x15b0,
+ 0xe1ad, 0x2389,
+ 0xe1ae, 0x15b2,
+ 0xe1b0, 0x238a,
+ 0xe1b1, 0x15b5,
+ 0xe1b4, 0x238b,
+ 0xe1b5, 0x15b9,
+ 0xe1bb, 0x238c,
+ 0xe1bc, 0x15c0,
+ 0xe1bd, 0x238d,
+ 0xe1be, 0x15c2,
+ 0xe1c0, 0x238e,
+ 0xe1c2, 0x15c6,
+ 0xe1c9, 0x2390,
+ 0xe1ca, 0x15ce,
+ 0xe1d0, 0x2391,
+ 0xe1d1, 0x15d5,
+ 0xe1db, 0x2392,
+ 0xe1dc, 0x15e0,
+ 0xe1e1, 0x07aa,
+ 0xe1e2, 0x2393,
+ 0xe1e3, 0x15e7,
+ 0xe1e7, 0x1198,
+ 0xe1e8, 0x15ec,
+ 0xe1ee, 0x2394,
+ 0xe1f0, 0x15f4,
+ 0xe1f6, 0x2396,
+ 0xe1f7, 0x15fb,
+ 0xe1f8, 0x2397,
+ 0xe1f9, 0x15fd,
+ 0xe1fd, 0x2398,
+ 0xe1fe, 0x1602,
+ 0xe2a1, 0x1603,
+ 0xe2a4, 0x2399,
+ 0xe2a5, 0x1607,
+ 0xe2a8, 0x239a,
+ 0xe2a9, 0x160b,
+ 0xe2bb, 0x239b,
+ 0xe2c5, 0x10c5,
+ 0xe2c6, 0x23a5,
+ 0xe2cf, 0x1631,
+ 0xe2d0, 0x23ae,
+ 0xe2d1, 0x1633,
+ 0xe2d9, 0x23af,
+ 0xe2da, 0x163c,
+ 0xe2e3, 0x23b0,
+ 0xe2e5, 0x1647,
+ 0xe2e6, 0x23b2,
+ 0xe2e7, 0x1649,
+ 0xe2e9, 0x23b3,
+ 0xe2ec, 0x164e,
+ 0xe2f8, 0x23b6,
+ 0xe2f9, 0x165b,
+ 0xe2fa, 0x23b7,
+ 0xe2fe, 0x1660,
+ 0xe3a1, 0x1661,
+ 0xe3a2, 0x23bb,
+ 0xe3a3, 0x1663,
+ 0xe3a5, 0x23bc,
+ 0xe3a6, 0x1666,
+ 0xe3ab, 0x23bd,
+ 0xe3ac, 0x166c,
+ 0xe3b4, 0x23be,
+ 0xe3b5, 0x1675,
+ 0xe3c5, 0x23bf,
+ 0xe3dc, 0x169c,
+ 0xe3e3, 0x23d6,
+ 0xe3e4, 0x16a4,
+ 0xe3ed, 0x23d7,
+ 0xe3ee, 0x16ae,
+ 0xe3f1, 0x23d8,
+ 0xe3f3, 0x16b3,
+ 0xe3f8, 0x23da,
+ 0xe3f9, 0x16b9,
+ 0xe3fe, 0x23db,
+ 0xe4a1, 0x16bf,
+ 0xe4a4, 0x23dc,
+ 0xe4a6, 0x16c4,
+ 0xe4ab, 0x23de,
+ 0xe4ac, 0x16ca,
+ 0xe4af, 0x23df,
+ 0xe4b2, 0x16d0,
+ 0xe4b5, 0x23e2,
+ 0xe4b7, 0x16d5,
+ 0xe4c2, 0x23e4,
+ 0xe4c3, 0x16e1,
+ 0xe4c5, 0x23e5,
+ 0xe4c6, 0x16e4,
+ 0xe4c9, 0x23e6,
+ 0xe4ca, 0x16e8,
+ 0xe4d9, 0x23e7,
+ 0xe4da, 0x16f8,
+ 0xe4dc, 0x23e8,
+ 0xe4dd, 0x16fb,
+ 0xe4de, 0x23e9,
+ 0xe4df, 0x16fd,
+ 0xe4e4, 0x23ea,
+ 0xe4e5, 0x1703,
+ 0xe4eb, 0x23eb,
+ 0xe4ed, 0x170b,
+ 0xe4f2, 0x23ed,
+ 0xe4f3, 0x1711,
+ 0xe4fe, 0x23ee,
+ 0xe5a1, 0x171d,
+ 0xe5b0, 0x23ef,
+ 0xe5b1, 0x172d,
+ 0xe5b9, 0x23f0,
+ 0xe5ba, 0x1736,
+ 0xe5c7, 0x23f1,
+ 0xe5c8, 0x1744,
+ 0xe5c9, 0x23f2,
+ 0xe5ca, 0x1746,
+ 0xe5ce, 0x23f3,
+ 0xe5cf, 0x174b,
+ 0xe5f0, 0x23f4,
+ 0xe5f1, 0x176d,
+ 0xe5f2, 0x23f5,
+ 0xe5f3, 0x176f,
+ 0xe5fc, 0x23f6,
+ 0xe5fe, 0x177a,
+ 0xe6a1, 0x177b,
+ 0xe6a3, 0x23f8,
+ 0xe6a4, 0x177e,
+ 0xe6ab, 0x23f9,
+ 0xe6ad, 0x1787,
+ 0xe6ae, 0x23fb,
+ 0xe6af, 0x1789,
+ 0xe6b4, 0x23fc,
+ 0xe6b6, 0x1790,
+ 0xe6bf, 0x23fe,
+ 0xe6c0, 0x179a,
+ 0xe6c8, 0x23ff,
+ 0xe6ca, 0x17a4,
+ 0xe6cd, 0x2401,
+ 0xe6ce, 0x17a8,
+ 0xe6e0, 0x2402,
+ 0xe7a1, 0x2421,
+ 0xe7db, 0x1813,
+ 0xe7e1, 0x245b,
+ 0xe7e3, 0x181b,
+ 0xe7e7, 0x245d,
+ 0xe7e8, 0x1820,
+ 0xe7ef, 0x245e,
+ 0xe7f0, 0x1828,
+ 0xe7f4, 0x245f,
+ 0xe7f7, 0x182f,
+ 0xe8a1, 0x1837,
+ 0xe8a8, 0x2462,
+ 0xe8a9, 0x183f,
+ 0xe8ac, 0x2463,
+ 0xe8ad, 0x1843,
+ 0xe8b6, 0x2464,
+ 0xe8b7, 0x184d,
+ 0xe8b8, 0x2465,
+ 0xe8bb, 0x1851,
+ 0xe8bf, 0x2468,
+ 0xe8c1, 0x1857,
+ 0xe8c5, 0x246a,
+ 0xe8c6, 0x185c,
+ 0xe8c7, 0x246b,
+ 0xe8ca, 0x1860,
+ 0xe8ce, 0x246e,
+ 0xe8cf, 0x1865,
+ 0xe8d0, 0x246f,
+ 0xe8d1, 0x1867,
+ 0xe8d3, 0x2470,
+ 0xe8d4, 0x186a,
+ 0xe8dd, 0x2471,
+ 0xe8de, 0x1874,
+ 0xe8df, 0x2472,
+ 0xe8e0, 0x1876,
+ 0xe8e2, 0x2473,
+ 0xe8e4, 0x187a,
+ 0xe8e5, 0x2475,
+ 0xe8e6, 0x187c,
+ 0xe8e7, 0x2476,
+ 0xe8e8, 0x187e,
+ 0xe8eb, 0x2477,
+ 0xe8ec, 0x1882,
+ 0xe8ed, 0x2478,
+ 0xe8ee, 0x1884,
+ 0xe8ef, 0x2479,
+ 0xe8f0, 0x1886,
+ 0xe8f9, 0x247a,
+ 0xe8fa, 0x1890,
+ 0xe8fc, 0x247b,
+ 0xe8fe, 0x1894,
+ 0xe9a1, 0x247d,
+ 0xe9a2, 0x1896,
+ 0xe9ad, 0x247e,
+ 0xe9ae, 0x18a2,
+ 0xe9b4, 0x247f,
+ 0xe9b6, 0x18aa,
+ 0xe9b7, 0x2481,
+ 0xe9b8, 0x18ac,
+ 0xe9c4, 0x2482,
+ 0xe9c5, 0x18b9,
+ 0xe9c6, 0x2483,
+ 0xe9c7, 0x18bb,
+ 0xe9c9, 0x2484,
+ 0xe9ca, 0x18be,
+ 0xe9d6, 0x2485,
+ 0xe9d7, 0x18cb,
+ 0xe9da, 0x2486,
+ 0xe9db, 0x18cf,
+ 0xe9e4, 0x2487,
+ 0xe9e5, 0x18d9,
+ 0xe9e6, 0x2488,
+ 0xe9e8, 0x18dc,
+ 0xe9e9, 0x248a,
+ 0xe9ea, 0x18de,
+ 0xe9eb, 0x248b,
+ 0xe9ec, 0x18e0,
+ 0xe9ed, 0x248c,
+ 0xeaa1, 0x249e,
+ 0xeaa6, 0x18f8,
+ 0xeaa7, 0x24a3,
+ 0xeaa9, 0x18fb,
+ 0xeab1, 0x24a5,
+ 0xeab2, 0x1904,
+ 0xeabc, 0x24a6,
+ 0xeabd, 0x190f,
+ 0xeaca, 0x24a7,
+ 0xeacb, 0x191d,
+ 0xeacd, 0x24a8,
+ 0xeace, 0x1920,
+ 0xead3, 0x24a9,
+ 0xead4, 0x1926,
+ 0xeada, 0x24aa,
+ 0xeaf0, 0x1942,
+ 0xeba1, 0x1951,
+ 0xeba7, 0x24c0,
+ 0xeba8, 0x1958,
+ 0xebaa, 0x24c1,
+ 0xebab, 0x195b,
+ 0xebb2, 0x24c2,
+ 0xebb3, 0x1963,
+ 0xebb9, 0x24c3,
+ 0xebba, 0x196a,
+ 0xebca, 0x24c4,
+ 0xebcc, 0x197c,
+ 0xebcd, 0x24c6,
+ 0xebce, 0x197e,
+ 0xebd6, 0x24c7,
+ 0xebd7, 0x1987,
+ 0xebda, 0x24c8,
+ 0xebdb, 0x198b,
+ 0xebe1, 0x24c9,
+ 0xebe2, 0x1992,
+ 0xebf7, 0x24ca,
+ 0xebf8, 0x19a8,
+ 0xeca1, 0x19af,
+ 0xeca3, 0x24cb,
+ 0xeca4, 0x19b2,
+ 0xeca9, 0x24cc,
+ 0xecaf, 0x19bd,
+ 0xecb1, 0x24d2,
+ 0xecb2, 0x19c0,
+ 0xecb4, 0x24d3,
+ 0xecb6, 0x19c4,
+ 0xecbe, 0x24d5,
+ 0xecc0, 0x19ce,
+ 0xecc1, 0x24d7,
+ 0xecc2, 0x19d0,
+ 0xecc7, 0x24d8,
+ 0xecc8, 0x19d6,
+ 0xeccb, 0x24d9,
+ 0xeccc, 0x19da,
+ 0xece2, 0x24da,
+ 0xece3, 0x19f1,
+ 0xecf2, 0x24db,
+ 0xecf3, 0x1a01,
+ 0xecf5, 0x24dc,
+ 0xecf6, 0x1a04,
+ 0xecf8, 0x24dd,
+ 0xecf9, 0x1a07,
+ 0xeda1, 0x24de,
+ 0xeda2, 0x1a0e,
+ 0xeda8, 0x24df,
+ 0xeda9, 0x1a15,
+ 0xedaf, 0x24e0,
+ 0xedb1, 0x1a1d,
+ 0xedb4, 0x24e2,
+ 0xedb5, 0x1a21,
+ 0xedb6, 0x24e3,
+ 0xedb7, 0x1a23,
+ 0xedb8, 0x24e4,
+ 0xedb9, 0x1a25,
+ 0xedba, 0x24e5,
+ 0xedbb, 0x1a27,
+ 0xedbf, 0x24e6,
+ 0xedc0, 0x1a2c,
+ 0xedc2, 0x24e7,
+ 0xedc4, 0x1a30,
+ 0xedcc, 0x24e9,
+ 0xedce, 0x1a3a,
+ 0xedd3, 0x24eb,
+ 0xedd4, 0x1a40,
+ 0xedd7, 0x24ec,
+ 0xedd8, 0x1a44,
+ 0xede8, 0x24ed,
+ 0xede9, 0x1a55,
+ 0xedee, 0x24ee,
+ 0xedef, 0x1a5b,
+ 0xedf9, 0x24ef,
+ 0xedfb, 0x1a67,
+ 0xeea1, 0x1a6b,
+ 0xeebc, 0x24f1,
+ 0xeebd, 0x1a87,
+ 0xeebf, 0x24f2,
+ 0xeec0, 0x1a8a,
+ 0xeec4, 0x24f3,
+ 0xefa1, 0x252e,
+ 0xeff2, 0x1b1a,
+ 0xf0a1, 0x1b27,
+ 0xf0a3, 0x257f,
+ 0xf0a4, 0x1b2a,
+ 0xf0af, 0x2580,
+ 0xf0da, 0x1b60,
+ 0xf0dc, 0x25ab,
+ 0xf0de, 0x1b64,
+ 0xf0df, 0x25ad,
+ 0xf0e0, 0x1b66,
+ 0xf0e9, 0x25ae,
+ 0xf0ea, 0x1b70,
+ 0xf0ec, 0x25af,
+ 0xf0ed, 0x1b73,
+ 0xf0ef, 0x25b0,
+ 0xf0f0, 0x1b76,
+ 0xf0f7, 0x25b1,
+ 0xf0f8, 0x1b7e,
+ 0xf0f9, 0x25b2,
+ 0xf0fa, 0x1b80,
+ 0xf0fc, 0x25b3,
+ 0xf0fd, 0x1b83,
+ 0xf1a1, 0x1b85,
+ 0xf1a8, 0x25b4,
+ 0xf1a9, 0x1b8d,
+ 0xf1ab, 0x25b5,
+ 0xf1ac, 0x1b90,
+ 0xf1ae, 0x25b6,
+ 0xf1af, 0x1b93,
+ 0xf1b2, 0x25b7,
+ 0xf1b3, 0x1b97,
+ 0xf1bc, 0x25b8,
+ 0xf1bd, 0x1ba1,
+ 0xf1c0, 0x25b9,
+ 0xf1c1, 0x1ba5,
+ 0xf1c9, 0x25ba,
+ 0xf1ca, 0x1bae,
+ 0xf1cd, 0x25bb,
+ 0xf1ce, 0x1bb2,
+ 0xf1cf, 0x25bc,
+ 0xf1d1, 0x1bb5,
+ 0xf1da, 0x25be,
+ 0xf1db, 0x1bbf,
+ 0xf1dc, 0x25bf,
+ 0xf1dd, 0x1bc1,
+ 0xf1e4, 0x25c0,
+ 0xf1e5, 0x1bc9,
+ 0xf1ec, 0x25c1,
+ 0xf1ed, 0x1bd1,
+ 0xf1ef, 0x25c2,
+ 0xf1f0, 0x1bd4,
+ 0xf1f7, 0x25c3,
+ 0xf1f8, 0x1bdc,
+ 0xf1f9, 0x25c4,
+ 0xf1fa, 0x1bde,
+ 0xf1fc, 0x25c5,
+ 0xf2a1, 0x25c8,
+ 0xf2ae, 0x1bf0,
+ 0xf2b1, 0x25d5,
+ 0xf2b3, 0x1bf5,
+ 0xf2b9, 0x25d7,
+ 0xf2ba, 0x1bfc,
+ 0xf2c3, 0x25d8,
+ 0xf2c4, 0x1c06,
+ 0xf2c9, 0x25d9,
+ 0xf2ca, 0x1c0c,
+ 0xf2cc, 0x25da,
+ 0xf2ce, 0x1c10,
+ 0xf2cf, 0x25dc,
+ 0xf2d0, 0x1c12,
+ 0xf2d3, 0x25dd,
+ 0xf2d4, 0x1c16,
+ 0xf2e5, 0x25de,
+ 0xf2e6, 0x1c28,
+ 0xf2ee, 0x25df,
+ 0xf2ef, 0x1c31,
+ 0xf2f7, 0x25e0,
+ 0xf2f8, 0x1c3a,
+ 0xf2fd, 0x25e1,
+ 0xf2fe, 0x1c40,
+ 0xf3a1, 0x1c41,
+ 0xf3bf, 0x25e2,
+ 0xf3c0, 0x1c60,
+ 0xf3c6, 0x25e3,
+ 0xf3c7, 0x1c67,
+ 0xf3c8, 0x25e4,
+ 0xf3c9, 0x1c69,
+ 0xf3d6, 0x25e5,
+ 0xf3d7, 0x1c77,
+ 0xf3d9, 0x25e6,
+ 0xf3da, 0x1c7a,
+ 0xf3e5, 0x25e7,
+ 0xf3e7, 0x1c87,
+ 0xf3ea, 0x25e9,
+ 0xf3eb, 0x1c8b,
+ 0xf3ec, 0x25ea,
+ 0xf3ed, 0x1c8d,
+ 0xf3ef, 0x25eb,
+ 0xf3f0, 0x1c90,
+ 0xf3f1, 0x25ec,
+ 0xf3f2, 0x1c92,
+ 0xf3fd, 0x25ed,
+ 0xf3fe, 0x1c9e,
+ 0xf4a1, 0x1c9f,
+ 0xf4a5, 0x25ee,
+ 0xf4a6, 0x1ca4,
+ 0xf4af, 0x25ef,
+ 0xf4b0, 0x1cae,
+ 0xf4b5, 0x25f0,
+ 0xf4b6, 0x1cb4,
+ 0xf4c1, 0x25f1,
+ 0xf4c2, 0x1cc0,
+ 0xf4c7, 0x25f2,
+ 0xf4c8, 0x1cc6,
+ 0xf4cf, 0x25f3,
+ 0xf4d1, 0x1ccf,
+ 0xf4d6, 0x25f5,
+ 0xf4d7, 0x1cd5,
+ 0xf4ea, 0x25f6,
+ 0xf4eb, 0x1ce9,
+ 0xf4ef, 0x25f7,
+ 0xf4f0, 0x1cee,
+ 0xf4f5, 0x25f8,
+ 0xf4f6, 0x1cf4,
+ 0xf5a1, 0x1cfd,
+ 0xf5a6, 0x25f9,
+ 0xf5a8, 0x1d04,
+ 0xf5ba, 0x25fb,
+ 0xf5bc, 0x1d18,
+ 0xf5c4, 0x25fd,
+ 0xf5c5, 0x1d21,
+ 0xf5c8, 0x25fe,
+ 0xf5c9, 0x1d25,
+ 0xf5ce, 0x25ff,
+ 0xf5d0, 0x1d2c,
+ 0xf5d1, 0x2601,
+ 0xf5d3, 0x1d2f,
+ 0xf5d9, 0x2603,
+ 0xf5da, 0x1d36,
+ 0xf5dc, 0x2604,
+ 0xf5dd, 0x1d39,
+ 0xf5e6, 0x2605,
+ 0xf5e8, 0x1d44,
+ 0xf5ef, 0x2607,
+ 0xf5f0, 0x1d4c,
+ 0xf5f2, 0x2608,
+ 0xf5f3, 0x1d4f,
+ 0xf5fc, 0x2609,
+ 0xf5fd, 0x1d59,
+ 0xf6a1, 0x1d5b,
+ 0xf6a3, 0x260a,
+ 0xf6a4, 0x1d5e,
+ 0xf6a6, 0x260b,
+ 0xf6a7, 0x1d61,
+ 0xf6a8, 0x260c,
+ 0xf6a9, 0x1d63,
+ 0xf6ab, 0x260d,
+ 0xf6ac, 0x1d66,
+ 0xf6b0, 0x260e,
+ 0xf6b1, 0x1d6b,
+ 0xf6b3, 0x260f,
+ 0xf6bf, 0x1d79,
+ 0xf6c5, 0x261b,
+ 0xf6c6, 0x1d80,
+ 0xf6c7, 0x261c,
+ 0xf6c8, 0x1d82,
+ 0xf6c9, 0x261d,
+ 0xf6ca, 0x1d84,
+ 0xf6cf, 0x261e,
+ 0xf7a1, 0x264e,
+ 0xf7b0, 0x1dc8,
+ 0xf7b2, 0x265d,
+ 0xf7b4, 0x1dcc,
+ 0xf7b5, 0x265f,
+ 0xf7b6, 0x1dce,
+ 0xf7bd, 0x2660,
+ 0xf7be, 0x1dd6,
+ 0xf7c3, 0x2661,
+ 0xf7c4, 0x1ddc,
+ 0xf7c5, 0x2662,
+ 0xf7c7, 0x1ddf,
+ 0xf7ca, 0x2664,
+ 0xf7cc, 0x1de4,
+ 0xf7cf, 0x2666,
+ 0xf7d1, 0x1de9,
+ 0xf7de, 0x2668,
+ 0xf7df, 0x1df7,
+ 0xf7e1, 0x0ab9,
+ 0xf7e2, 0x1dfa,
+ 0xf7f2, 0x2669,
+ 0xf7f3, 0x1e0b,
+ 0xf7f5, 0x266a,
+ 0xf7f6, 0x1e0e,
+ 0xf8a1, 0x266b,
+ 0xf8a7, 0x04cc,
+ 0xf8a8, 0x050a,
+ 0xf8a9, 0x0518,
+ 0xf8aa, 0x2671,
+ 0xf8ac, 0x0594,
+ 0xf8ad, 0x05ce,
+ 0xf8ae, 0x2673,
+ 0xf8af, 0x05f6,
+ 0xf8b0, 0x2674,
+ 0xf8b2, 0x0653,
+ 0xf8b3, 0x067e,
+ 0xf8b4, 0x2676,
+ 0xf8b5, 0x06c4,
+ 0xf8b6, 0x2677,
+ 0xf8b8, 0x073c,
+ 0xf8b9, 0x2679,
+ 0xf8bb, 0x07c3,
+ 0xf8bc, 0x267b,
+ 0xf8c0, 0x082b,
+ 0xf8c1, 0x267f,
+ 0xf8c2, 0x084e,
+ 0xf8c3, 0x0869,
+ 0xf8c4, 0x2680,
+ 0xf8c6, 0x090c,
+ 0xf8c7, 0x2682,
+ 0xf8c9, 0x0971,
+ 0xf8ca, 0x2684,
+ 0xf8cb, 0x099a,
+ 0xf8cd, 0x2685,
+ 0xf8ce, 0x09da,
+ 0xf8cf, 0x2686,
+ 0xf8d0, 0x09fa,
+ 0xf8d1, 0x2687,
+ 0xf8dc, 0x0bda,
+ 0xf8dd, 0x0bdd,
+ 0xf8de, 0x0bea,
+ 0xf8df, 0x0bec,
+ 0xf8e0, 0x0bf2,
+ 0xf8e1, 0x2692,
+ 0xf8e6, 0x0c92,
+ 0xf8e7, 0x0d1a,
+ 0xf8e8, 0x0d8c,
+ 0xf8e9, 0x0dbe,
+ 0xf8ea, 0x2697,
+ 0xf8eb, 0x0dfb,
+ 0xf8ec, 0x2698,
+ 0xf8ef, 0x0e70,
+ 0xf8f0, 0x269b,
+ 0xf8f1, 0x0ea3,
+ 0xf8f2, 0x269c,
+ 0xf8f8, 0x103d,
+ 0xf8f9, 0x10d9,
+ 0xf8fa, 0x26a2,
+ 0xf8fc, 0x10fb,
+ 0xf8fd, 0x1109,
+ 0xf8fe, 0x26a4,
+ 0xf9a1, 0x11a1,
+ 0xf9a2, 0x26a5,
+ 0xf9a3, 0x11ba,
+ 0xf9a4, 0x26a6,
+ 0xf9a6, 0x11d5,
+ 0xf9a7, 0x26a8,
+ 0xf9a8, 0x11fd,
+ 0xf9a9, 0x1219,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTEUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBTEUCHMap2, 2283
+};
+
+static Gushort gb12GBTEUCVMap2[4606] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb0a8, 0x1e25,
+ 0xb0a9, 0x03b4,
+ 0xb0aa, 0x1e26,
+ 0xb0ab, 0x03b6,
+ 0xb0ad, 0x1e27,
+ 0xb0af, 0x03ba,
+ 0xb0b9, 0x1e29,
+ 0xb0ba, 0x03c5,
+ 0xb0c0, 0x1e2a,
+ 0xb0c1, 0x03cc,
+ 0xb0d3, 0x1e2b,
+ 0xb0d4, 0x03df,
+ 0xb0d5, 0x1e2c,
+ 0xb0d6, 0x03e1,
+ 0xb0da, 0x1e2d,
+ 0xb0db, 0x03e6,
+ 0xb0dc, 0x1e2e,
+ 0xb0dd, 0x03e8,
+ 0xb0e4, 0x1e2f,
+ 0xb0e5, 0x03f0,
+ 0xb0ec, 0x1e30,
+ 0xb0ee, 0x03f9,
+ 0xb0ef, 0x1e32,
+ 0xb0f0, 0x03fb,
+ 0xb0f3, 0x1e33,
+ 0xb0f4, 0x03ff,
+ 0xb0f7, 0x1e34,
+ 0xb0f8, 0x0403,
+ 0xb0f9, 0x1e35,
+ 0xb0fa, 0x0405,
+ 0xb1a1, 0x040a,
+ 0xb1a5, 0x1e36,
+ 0xb1a7, 0x0410,
+ 0xb1a8, 0x1e38,
+ 0xb1a9, 0x0412,
+ 0xb1ab, 0x1e39,
+ 0xb1ac, 0x0415,
+ 0xb1b2, 0x1e3a,
+ 0xb1b3, 0x041c,
+ 0xb1b4, 0x1e3b,
+ 0xb1b6, 0x041f,
+ 0xb1b7, 0x1e3d,
+ 0xb1ba, 0x0423,
+ 0xb1c1, 0x1e40,
+ 0xb1c2, 0x042b,
+ 0xb1ca, 0x1e41,
+ 0xb1cb, 0x0434,
+ 0xb1cf, 0x1e42,
+ 0xb1d1, 0x043a,
+ 0xb1d2, 0x1e44,
+ 0xb1d3, 0x043c,
+ 0xb1d5, 0x1e45,
+ 0xb1d6, 0x043f,
+ 0xb1df, 0x1e46,
+ 0xb1e2, 0x044b,
+ 0xb1e4, 0x1e49,
+ 0xb1e5, 0x044e,
+ 0xb1e7, 0x1e4a,
+ 0xb1e9, 0x0452,
+ 0xb1ea, 0x1e4c,
+ 0xb1eb, 0x0454,
+ 0xb1ee, 0x1e4d,
+ 0xb1ef, 0x0458,
+ 0xb1f1, 0x1e4e,
+ 0xb1f2, 0x045b,
+ 0xb1f4, 0x1e4f,
+ 0xb1f8, 0x0461,
+ 0xb1fd, 0x1e53,
+ 0xb1fe, 0x0467,
+ 0xb2a1, 0x0468,
+ 0xb2a6, 0x1e54,
+ 0xb2a8, 0x046f,
+ 0xb2ac, 0x1e56,
+ 0xb2ad, 0x0474,
+ 0xb2b5, 0x1e57,
+ 0xb2b6, 0x047d,
+ 0xb2b9, 0x1e58,
+ 0xb2ba, 0x0481,
+ 0xb2c6, 0x1e59,
+ 0xb2c7, 0x048e,
+ 0xb2ce, 0x1e5a,
+ 0xb2d8, 0x049f,
+ 0xb2de, 0x1e64,
+ 0xb2df, 0x04a6,
+ 0xb2e0, 0x1e65,
+ 0xb2e1, 0x04a8,
+ 0xb2e2, 0x1e66,
+ 0xb2e4, 0x04ab,
+ 0xb2ef, 0x1e68,
+ 0xb2f0, 0x04b7,
+ 0xb2f3, 0x1e69,
+ 0xb2fd, 0x04c4,
+ 0xb3a1, 0x1e73,
+ 0xb3a3, 0x04c8,
+ 0xb3a4, 0x1e75,
+ 0xb3a8, 0x04cd,
+ 0xb3a9, 0x1e79,
+ 0xb3aa, 0x04cf,
+ 0xb3ae, 0x1e7a,
+ 0xb3af, 0x04d4,
+ 0xb3b5, 0x1e7b,
+ 0xb3b6, 0x04db,
+ 0xb3b9, 0x1e7c,
+ 0xb3ba, 0x04df,
+ 0xb3be, 0x1e7d,
+ 0xb3bf, 0x04e4,
+ 0xb3c2, 0x1e7e,
+ 0xb3c3, 0x04e8,
+ 0xb3c4, 0x1e7f,
+ 0xb3c5, 0x04ea,
+ 0xb3c6, 0x1e80,
+ 0xb3c7, 0x04ec,
+ 0xb3cd, 0x1e81,
+ 0xb3ce, 0x04f3,
+ 0xb3cf, 0x1e82,
+ 0xb3d0, 0x04f5,
+ 0xb3d2, 0x1e83,
+ 0xb3d3, 0x04f8,
+ 0xb3d9, 0x1e84,
+ 0xb3da, 0x04ff,
+ 0xb3db, 0x1e85,
+ 0xb3dc, 0x0501,
+ 0xb3dd, 0x1e86,
+ 0xb3de, 0x0503,
+ 0xb3e3, 0x1e87,
+ 0xb3e4, 0x0509,
+ 0xb3e5, 0x1e88,
+ 0xb3e7, 0x050c,
+ 0xb3e8, 0x1e8a,
+ 0xb3e9, 0x050e,
+ 0xb3eb, 0x1e8b,
+ 0xb3ed, 0x0512,
+ 0xb3ef, 0x1e8d,
+ 0xb3f0, 0x0515,
+ 0xb3f1, 0x1e8e,
+ 0xb3f2, 0x0517,
+ 0xb3f3, 0x1e8f,
+ 0xb3f4, 0x0519,
+ 0xb3fa, 0x1e90,
+ 0xb3fc, 0x0521,
+ 0xb4a1, 0x1e92,
+ 0xb4a3, 0x0526,
+ 0xb4a5, 0x1e94,
+ 0xb4a7, 0x052a,
+ 0xb4ab, 0x1e96,
+ 0xb4ac, 0x052f,
+ 0xb4af, 0x1e97,
+ 0xb4b0, 0x0533,
+ 0xb4b3, 0x1e98,
+ 0xb4b5, 0x0538,
+ 0xb4b8, 0x1e9a,
+ 0xb4b9, 0x053c,
+ 0xb4bf, 0x1e9b,
+ 0xb4c0, 0x0543,
+ 0xb4c2, 0x1e9c,
+ 0xb4c3, 0x0546,
+ 0xb4c7, 0x1e9d,
+ 0xb4c8, 0x054b,
+ 0xb4ca, 0x1e9e,
+ 0xb4cb, 0x054e,
+ 0xb4cd, 0x1e9f,
+ 0xb4ce, 0x0551,
+ 0xb4cf, 0x1ea0,
+ 0xb4d0, 0x0553,
+ 0xb4d3, 0x1ea1,
+ 0xb4d5, 0x0558,
+ 0xb4da, 0x1ea3,
+ 0xb4db, 0x055e,
+ 0xb4dc, 0x1ea4,
+ 0xb4dd, 0x0560,
+ 0xb4ed, 0x1ea5,
+ 0xb4ee, 0x0571,
+ 0xb4ef, 0x1ea6,
+ 0xb4f0, 0x0573,
+ 0xb4f8, 0x1ea7,
+ 0xb4f9, 0x057c,
+ 0xb4fb, 0x1ea8,
+ 0xb4fc, 0x057f,
+ 0xb5a1, 0x0582,
+ 0xb5a3, 0x1ea9,
+ 0xb5a4, 0x0585,
+ 0xb5a5, 0x1eaa,
+ 0xb5a9, 0x058a,
+ 0xb5ac, 0x1eae,
+ 0xb5ad, 0x058e,
+ 0xb5ae, 0x1eaf,
+ 0xb5b0, 0x0591,
+ 0xb5b1, 0x1eb1,
+ 0xb5b6, 0x0597,
+ 0xb5b7, 0x1eb6,
+ 0xb5b8, 0x0599,
+ 0xb5ba, 0x1eb7,
+ 0xb5bd, 0x059e,
+ 0xb5c6, 0x1eba,
+ 0xb5c7, 0x05a8,
+ 0xb5cb, 0x1ebb,
+ 0xb5cc, 0x05ad,
+ 0xb5d0, 0x1ebc,
+ 0xb5d1, 0x05b2,
+ 0xb5d3, 0x1ebd,
+ 0xb5d4, 0x05b5,
+ 0xb5dd, 0x1ebe,
+ 0xb5e0, 0x05c1,
+ 0xb5e3, 0x1ec1,
+ 0xb5e4, 0x05c5,
+ 0xb5e6, 0x1ec2,
+ 0xb5e8, 0x05c9,
+ 0xb5ed, 0x1ec4,
+ 0xb5ee, 0x05cf,
+ 0xb5f6, 0x1ec5,
+ 0xb5f8, 0x05d9,
+ 0xb5fd, 0x1ec7,
+ 0xb5fe, 0x05df,
+ 0xb6a1, 0x05e0,
+ 0xb6a4, 0x1ec8,
+ 0xb6a6, 0x05e5,
+ 0xb6a7, 0x1eca,
+ 0xb6a8, 0x05e7,
+ 0xb6a9, 0x1ecb,
+ 0xb6aa, 0x05e9,
+ 0xb6ab, 0x1ecc,
+ 0xb6ac, 0x05eb,
+ 0xb6af, 0x1ecd,
+ 0xb6b1, 0x05f0,
+ 0xb6b3, 0x1ecf,
+ 0xb6b4, 0x05f3,
+ 0xb6b7, 0x1ed0,
+ 0xb6b8, 0x05f7,
+ 0xb6bf, 0x1ed1,
+ 0xb6c2, 0x0601,
+ 0xb6c4, 0x1ed4,
+ 0xb6c5, 0x0604,
+ 0xb6c6, 0x1ed5,
+ 0xb6c7, 0x0606,
+ 0xb6cd, 0x1ed6,
+ 0xb6ce, 0x060d,
+ 0xb6cf, 0x1ed7,
+ 0xb6d1, 0x0610,
+ 0xb6d3, 0x1ed9,
+ 0xb6d5, 0x0614,
+ 0xb6d6, 0x1edb,
+ 0xb6d7, 0x0616,
+ 0xb6d9, 0x1edc,
+ 0xb6da, 0x0619,
+ 0xb6db, 0x1edd,
+ 0xb6dc, 0x061b,
+ 0xb6e1, 0x1ede,
+ 0xb6e2, 0x0621,
+ 0xb6e9, 0x1edf,
+ 0xb6ea, 0x0629,
+ 0xb6ec, 0x1ee0,
+ 0xb6ed, 0x062c,
+ 0xb6ee, 0x1ee1,
+ 0xb6f0, 0x062f,
+ 0xb6f1, 0x1ee3,
+ 0xb6f2, 0x0631,
+ 0xb6f6, 0x1ee4,
+ 0xb6f7, 0x0636,
+ 0xb6f9, 0x1ee5,
+ 0xb6fa, 0x0639,
+ 0xb6fb, 0x1ee6,
+ 0xb6fd, 0x063c,
+ 0xb7a1, 0x1ee8,
+ 0xb7a4, 0x0641,
+ 0xb7a7, 0x1eeb,
+ 0xb7a8, 0x0645,
+ 0xb7af, 0x1eec,
+ 0xb7b1, 0x064e,
+ 0xb7b3, 0x1eee,
+ 0xb7b4, 0x0651,
+ 0xb7b6, 0x1eef,
+ 0xb7b8, 0x0655,
+ 0xb7b9, 0x1ef1,
+ 0xb7ba, 0x0657,
+ 0xb7c3, 0x1ef2,
+ 0xb7c5, 0x0662,
+ 0xb7c9, 0x1ef4,
+ 0xb7ca, 0x0667,
+ 0xb7cc, 0x1ef5,
+ 0xb7cd, 0x066a,
+ 0xb7cf, 0x1ef6,
+ 0xb7d0, 0x066d,
+ 0xb7d1, 0x1ef7,
+ 0xb7d2, 0x066f,
+ 0xb7d7, 0x1ef8,
+ 0xb7d9, 0x0676,
+ 0xb7dc, 0x1efa,
+ 0xb7dd, 0x067a,
+ 0xb7df, 0x1efb,
+ 0xb7e2, 0x067f,
+ 0xb7e3, 0x1efe,
+ 0xb7e4, 0x0681,
+ 0xb7e6, 0x1eff,
+ 0xb7e9, 0x0686,
+ 0xb7eb, 0x1f02,
+ 0xb7ee, 0x068b,
+ 0xb7ef, 0x1f05,
+ 0xb7f0, 0x068d,
+ 0xb7f4, 0x1f06,
+ 0xb7f5, 0x0692,
+ 0xb7f8, 0x1f07,
+ 0xb7f9, 0x0696,
+ 0xb8a1, 0x069c,
+ 0xb8a7, 0x1f08,
+ 0xb8a9, 0x06a4,
+ 0xb8b3, 0x1f0a,
+ 0xb8b5, 0x06b0,
+ 0xb8ba, 0x1f0c,
+ 0xb8bb, 0x06b6,
+ 0xb8bc, 0x1f0d,
+ 0xb8bd, 0x06b8,
+ 0xb8be, 0x1f0e,
+ 0xb8c0, 0x06bb,
+ 0xb8c3, 0x1f10,
+ 0xb8c4, 0x06bf,
+ 0xb8c6, 0x1f11,
+ 0xb8c8, 0x06c3,
+ 0xb8c9, 0x1f13,
+ 0xb8ca, 0x06c5,
+ 0xb8cf, 0x1f14,
+ 0xb8d0, 0x06cb,
+ 0xb8d3, 0x1f15,
+ 0xb8d7, 0x06d2,
+ 0xb8d9, 0x1f19,
+ 0xb8db, 0x06d6,
+ 0xb8e4, 0x1f1b,
+ 0xb8e5, 0x06e0,
+ 0xb8e9, 0x1f1c,
+ 0xb8ea, 0x06e5,
+ 0xb8eb, 0x1f1d,
+ 0xb8ec, 0x06e7,
+ 0xb8f3, 0x1f1e,
+ 0xb8f4, 0x06ef,
+ 0xb8f5, 0x1f1f,
+ 0xb8f7, 0x06f2,
+ 0xb8f8, 0x1f21,
+ 0xb8f9, 0x06f4,
+ 0xb9a1, 0x06fa,
+ 0xb9a8, 0x1f22,
+ 0xb9a9, 0x0702,
+ 0xb9ae, 0x1f23,
+ 0xb9af, 0x0708,
+ 0xb9b1, 0x1f24,
+ 0xb9b2, 0x070b,
+ 0xb9b3, 0x1f25,
+ 0xb9b4, 0x070d,
+ 0xb9b5, 0x1f26,
+ 0xb9b6, 0x070f,
+ 0xb9b9, 0x1f27,
+ 0xb9bb, 0x0714,
+ 0xb9c6, 0x1f29,
+ 0xb9c7, 0x0720,
+ 0xb9cb, 0x1f2a,
+ 0xb9cc, 0x0725,
+ 0xb9d0, 0x1f2b,
+ 0xb9d1, 0x072a,
+ 0xb9d8, 0x1f2c,
+ 0xb9d9, 0x0732,
+ 0xb9db, 0x1f2d,
+ 0xb9dc, 0x0735,
+ 0xb9dd, 0x1f2e,
+ 0xb9de, 0x0737,
+ 0xb9df, 0x1f2f,
+ 0xb9e0, 0x0739,
+ 0xb9e1, 0x1f30,
+ 0xb9e2, 0x073b,
+ 0xb9e3, 0x1f31,
+ 0xb9e4, 0x073d,
+ 0xb9e6, 0x1f32,
+ 0xb9e7, 0x0740,
+ 0xb9e9, 0x1f33,
+ 0xb9ed, 0x0746,
+ 0xb9ee, 0x1f37,
+ 0xb9ef, 0x0748,
+ 0xb9f1, 0x1f38,
+ 0xb9f2, 0x074b,
+ 0xb9f3, 0x1f39,
+ 0xb9f6, 0x074f,
+ 0xb9f8, 0x1f3c,
+ 0xb9f9, 0x0752,
+ 0xb9fa, 0x1f3d,
+ 0xb9fb, 0x0754,
+ 0xb9fd, 0x1f3e,
+ 0xb9fe, 0x0757,
+ 0xbaa1, 0x0758,
+ 0xbaa7, 0x1f3f,
+ 0xbaa8, 0x075f,
+ 0xbaab, 0x1f40,
+ 0xbaac, 0x0763,
+ 0xbaba, 0x1f41,
+ 0xbabb, 0x0772,
+ 0xbac5, 0x1f42,
+ 0xbac6, 0x077d,
+ 0xbad2, 0x1f43,
+ 0xbad3, 0x078a,
+ 0xbad7, 0x1f44,
+ 0xbad9, 0x0790,
+ 0xbae4, 0x1f46,
+ 0xbae5, 0x079c,
+ 0xbae8, 0x1f47,
+ 0xbae9, 0x07a0,
+ 0xbaec, 0x1f48,
+ 0xbaed, 0x07a4,
+ 0xbaf3, 0x15e5,
+ 0xbaf4, 0x07ab,
+ 0xbaf8, 0x1f49,
+ 0xbaf9, 0x07b0,
+ 0xbba1, 0x07b6,
+ 0xbba4, 0x1f4a,
+ 0xbba5, 0x07ba,
+ 0xbba6, 0x1f4b,
+ 0xbba7, 0x07bc,
+ 0xbba9, 0x1f4c,
+ 0xbbab, 0x07c0,
+ 0xbbad, 0x1f4e,
+ 0xbbaf, 0x07c4,
+ 0xbbb0, 0x1f50,
+ 0xbbb1, 0x07c6,
+ 0xbbb3, 0x1f51,
+ 0xbbb4, 0x07c9,
+ 0xbbb5, 0x1f52,
+ 0xbbb8, 0x07cd,
+ 0xbbb9, 0x1f55,
+ 0xbbbb, 0x07d0,
+ 0xbbd1, 0x1f57,
+ 0xbbd2, 0x07e7,
+ 0xbbd3, 0x1f58,
+ 0xbbd5, 0x07ea,
+ 0xbbdf, 0x1f5a,
+ 0xbbe8, 0x07fd,
+ 0xbbeb, 0x1f63,
+ 0xbbec, 0x0801,
+ 0xbbf1, 0x1f64,
+ 0xbbf2, 0x0807,
+ 0xbbf5, 0x1f65,
+ 0xbbf8, 0x080d,
+ 0xbbfa, 0x1f68,
+ 0xbbfb, 0x0810,
+ 0xbbfd, 0x1f69,
+ 0xbbfe, 0x0813,
+ 0xbca1, 0x0814,
+ 0xbca2, 0x1f6a,
+ 0xbca3, 0x0816,
+ 0xbca5, 0x1f6b,
+ 0xbca7, 0x081a,
+ 0xbca8, 0x1f6d,
+ 0xbcaa, 0x081d,
+ 0xbcab, 0x1f6f,
+ 0xbcac, 0x081f,
+ 0xbcad, 0x1f70,
+ 0xbcae, 0x0821,
+ 0xbcb6, 0x1f71,
+ 0xbcb9, 0x082c,
+ 0xbcbb, 0x1f74,
+ 0xbcbc, 0x082f,
+ 0xbcc1, 0x1f75,
+ 0xbcc2, 0x0835,
+ 0xbcc3, 0x1f76,
+ 0xbcc4, 0x0837,
+ 0xbcc6, 0x1f77,
+ 0xbcc8, 0x083b,
+ 0xbcca, 0x1f79,
+ 0xbccb, 0x083e,
+ 0xbccc, 0x1f7a,
+ 0xbcce, 0x0841,
+ 0xbcd0, 0x1f7c,
+ 0xbcd1, 0x0844,
+ 0xbcd4, 0x1f7d,
+ 0xbcd7, 0x084a,
+ 0xbcd8, 0x1f80,
+ 0xbcd9, 0x084c,
+ 0xbcdb, 0x1f81,
+ 0xbcdc, 0x084f,
+ 0xbcdd, 0x1f82,
+ 0xbcde, 0x0851,
+ 0xbcdf, 0x1f83,
+ 0xbce2, 0x0855,
+ 0xbce3, 0x1f86,
+ 0xbce5, 0x0858,
+ 0xbce8, 0x1f88,
+ 0xbce9, 0x085c,
+ 0xbcea, 0x1f89,
+ 0xbced, 0x0860,
+ 0xbcef, 0x1f8c,
+ 0xbcf4, 0x0867,
+ 0xbcf6, 0x1f91,
+ 0xbcfd, 0x0870,
+ 0xbda1, 0x0872,
+ 0xbda2, 0x1f98,
+ 0xbda8, 0x0879,
+ 0xbdab, 0x1f9e,
+ 0xbdad, 0x087e,
+ 0xbdaf, 0x1fa0,
+ 0xbdb3, 0x0884,
+ 0xbdb4, 0x1fa4,
+ 0xbdb5, 0x0886,
+ 0xbdba, 0x1fa5,
+ 0xbdbb, 0x088c,
+ 0xbdbd, 0x1fa6,
+ 0xbdc0, 0x0891,
+ 0xbdc1, 0x1fa9,
+ 0xbdc5, 0x0896,
+ 0xbdc8, 0x1fad,
+ 0xbdcb, 0x089c,
+ 0xbdce, 0x1fb0,
+ 0xbdd0, 0x08a1,
+ 0xbdd7, 0x1fb2,
+ 0xbdd8, 0x08a9,
+ 0xbdda, 0x1fb3,
+ 0xbddb, 0x08ac,
+ 0xbde0, 0x1fb4,
+ 0xbde2, 0x08b3,
+ 0xbdeb, 0x1fb6,
+ 0xbdec, 0x08bd,
+ 0xbdf4, 0x1fb7,
+ 0xbdf9, 0x08ca,
+ 0xbdfd, 0x1fbc,
+ 0xbdfe, 0x08cf,
+ 0xbea1, 0x1fbd,
+ 0xbea3, 0x08d2,
+ 0xbea5, 0x1fbf,
+ 0xbea6, 0x08d5,
+ 0xbea8, 0x1fc0,
+ 0xbea9, 0x08d8,
+ 0xbeaa, 0x1fc1,
+ 0xbeab, 0x08da,
+ 0xbead, 0x1fc2,
+ 0xbeae, 0x08dd,
+ 0xbeb1, 0x1fc3,
+ 0xbeb2, 0x08e1,
+ 0xbeb5, 0x1fc4,
+ 0xbeb8, 0x08e7,
+ 0xbeba, 0x1fc7,
+ 0xbebb, 0x08ea,
+ 0xbec0, 0x1fc8,
+ 0xbec1, 0x08f0,
+ 0xbec9, 0x1fc9,
+ 0xbeca, 0x08f9,
+ 0xbed4, 0x1fca,
+ 0xbed5, 0x0904,
+ 0xbed9, 0x1fcb,
+ 0xbeda, 0x0909,
+ 0xbedd, 0x1fcc,
+ 0xbede, 0x090d,
+ 0xbee2, 0x1fcd,
+ 0xbee3, 0x0912,
+ 0xbee5, 0x1fce,
+ 0xbee6, 0x0915,
+ 0xbee7, 0x1fcf,
+ 0xbee8, 0x0917,
+ 0xbee9, 0x1fd0,
+ 0xbeea, 0x0919,
+ 0xbeee, 0x1fd1,
+ 0xbeef, 0x091e,
+ 0xbef5, 0x1fd2,
+ 0xbef6, 0x0925,
+ 0xbef7, 0x1fd3,
+ 0xbef9, 0x0928,
+ 0xbefb, 0x1fd5,
+ 0xbefd, 0x092c,
+ 0xbfa1, 0x092e,
+ 0xbfa5, 0x1fd7,
+ 0xbfa6, 0x0933,
+ 0xbfaa, 0x1fd8,
+ 0xbfab, 0x0938,
+ 0xbfad, 0x1fd9,
+ 0xbfae, 0x093b,
+ 0xbfc5, 0x1fda,
+ 0xbfc6, 0x0953,
+ 0xbfc7, 0x1fdb,
+ 0xbfc8, 0x0955,
+ 0xbfce, 0x1fdc,
+ 0xbfcf, 0x095c,
+ 0xbfd1, 0x1fdd,
+ 0xbfd3, 0x0960,
+ 0xbfd9, 0x1fdf,
+ 0xbfda, 0x0967,
+ 0xbfe2, 0x1fe0,
+ 0xbfe5, 0x0972,
+ 0xbfe9, 0x1fe3,
+ 0xbfea, 0x0977,
+ 0xbfeb, 0x1fe4,
+ 0xbfec, 0x0979,
+ 0xbfed, 0x1fe5,
+ 0xbfee, 0x097b,
+ 0xbff3, 0x1fe6,
+ 0xbff4, 0x0981,
+ 0xbff5, 0x1fe7,
+ 0xbff6, 0x0983,
+ 0xbff7, 0x1fe8,
+ 0xbff8, 0x0985,
+ 0xbff9, 0x1fe9,
+ 0xbffb, 0x0988,
+ 0xc0a1, 0x1feb,
+ 0xc0a2, 0x098d,
+ 0xc0a3, 0x1fec,
+ 0xc0a4, 0x098f,
+ 0xc0a9, 0x1fed,
+ 0xc0aa, 0x0995,
+ 0xc0ab, 0x1fee,
+ 0xc0ac, 0x0997,
+ 0xc0af, 0x1fef,
+ 0xc0b1, 0x099c,
+ 0xc0b3, 0x1ff1,
+ 0xc0b7, 0x09a2,
+ 0xc0b8, 0x1ff5,
+ 0xc0c5, 0x09b0,
+ 0xc0cc, 0x2002,
+ 0xc0ce, 0x09b9,
+ 0xc0d4, 0x2004,
+ 0xc0d5, 0x09c0,
+ 0xc0d6, 0x2005,
+ 0xc0d7, 0x09c2,
+ 0xc0d8, 0x2006,
+ 0xc0d9, 0x09c4,
+ 0xc0dd, 0x2007,
+ 0xc0de, 0x09c9,
+ 0xc0e0, 0x2008,
+ 0xc0e1, 0x09cc,
+ 0xc0e9, 0x2009,
+ 0xc0ea, 0x09d5,
+ 0xc0eb, 0x200a,
+ 0xc0ed, 0x09d8,
+ 0xc0ef, 0x200c,
+ 0xc0f2, 0x09dd,
+ 0xc0f6, 0x200f,
+ 0xc0fb, 0x09e6,
+ 0xc1a1, 0x09ea,
+ 0xc1a4, 0x2014,
+ 0xc1a6, 0x09ef,
+ 0xc1a9, 0x2016,
+ 0xc1ae, 0x09f7,
+ 0xc1af, 0x201b,
+ 0xc1b9, 0x0a02,
+ 0xc1bd, 0x2025,
+ 0xc1bf, 0x0a08,
+ 0xc1c2, 0x2027,
+ 0xc1c3, 0x0a0c,
+ 0xc1c6, 0x2028,
+ 0xc1c7, 0x0a10,
+ 0xc1c9, 0x2029,
+ 0xc1ca, 0x0a13,
+ 0xc1cd, 0x202a,
+ 0xc1ce, 0x0a17,
+ 0xc1d4, 0x202b,
+ 0xc1d5, 0x0a1e,
+ 0xc1d9, 0x202c,
+ 0xc1dc, 0x0a25,
+ 0xc1de, 0x202f,
+ 0xc1df, 0x0a28,
+ 0xc1e4, 0x2030,
+ 0xc1e6, 0x0a2f,
+ 0xc1e9, 0x2032,
+ 0xc1ea, 0x0a33,
+ 0xc1eb, 0x2033,
+ 0xc1ed, 0x0a36,
+ 0xc1f3, 0x2035,
+ 0xc1f4, 0x0a3d,
+ 0xc1f5, 0x2036,
+ 0xc1f6, 0x0a3f,
+ 0xc1fa, 0x2037,
+ 0xc1fe, 0x0a47,
+ 0xc2a1, 0x0a48,
+ 0xc2a2, 0x203b,
+ 0xc2a9, 0x0a50,
+ 0xc2ab, 0x2042,
+ 0xc2b4, 0x0a5b,
+ 0xc2b8, 0x204b,
+ 0xc2b9, 0x0a60,
+ 0xc2bc, 0x204c,
+ 0xc2be, 0x0a65,
+ 0xc2bf, 0x204e,
+ 0xc2c0, 0x0a67,
+ 0xc2c1, 0x204f,
+ 0xc2c2, 0x0a69,
+ 0xc2c5, 0x2050,
+ 0xc2c8, 0x0a6f,
+ 0xc2cb, 0x2053,
+ 0xc2d1, 0x0a78,
+ 0xc2d2, 0x2059,
+ 0xc2d3, 0x0a7a,
+ 0xc2d5, 0x205a,
+ 0xc2dd, 0x0a84,
+ 0xc2de, 0x2062,
+ 0xc2e3, 0x0a8a,
+ 0xc2e6, 0x2067,
+ 0xc2e9, 0x0a90,
+ 0xc2ea, 0x206a,
+ 0xc2ef, 0x0a96,
+ 0xc2f0, 0x206f,
+ 0xc2f1, 0x0a98,
+ 0xc2f2, 0x2070,
+ 0xc2f6, 0x0a9d,
+ 0xc2f7, 0x2074,
+ 0xc2fb, 0x0aa2,
+ 0xc3a1, 0x2078,
+ 0xc3a2, 0x0aa7,
+ 0xc3aa, 0x2079,
+ 0xc3ab, 0x0ab0,
+ 0xc3ad, 0x207a,
+ 0xc3ae, 0x0ab3,
+ 0xc3b3, 0x207b,
+ 0xc3b4, 0x1df9,
+ 0xc3b5, 0x0aba,
+ 0xc3be, 0x207c,
+ 0xc3bf, 0x0ac4,
+ 0xc3c5, 0x207d,
+ 0xc3c8, 0x0acd,
+ 0xc3cc, 0x2080,
+ 0xc3cd, 0x0ad2,
+ 0xc3ce, 0x2081,
+ 0xc3cf, 0x0ad4,
+ 0xc3d5, 0x2082,
+ 0xc3d7, 0x0adc,
+ 0xc3d9, 0x2084,
+ 0xc3da, 0x0adf,
+ 0xc3e0, 0x2085,
+ 0xc3e1, 0x0ae6,
+ 0xc3e5, 0x2086,
+ 0xc3e6, 0x0aeb,
+ 0xc3ed, 0x2087,
+ 0xc3ee, 0x0af3,
+ 0xc3f0, 0x2088,
+ 0xc3f1, 0x0af6,
+ 0xc3f5, 0x2089,
+ 0xc3f7, 0x0afc,
+ 0xc3f9, 0x208b,
+ 0xc3fb, 0x0b00,
+ 0xc3fd, 0x208d,
+ 0xc3fe, 0x0b03,
+ 0xc4a1, 0x0b04,
+ 0xc4b1, 0x208e,
+ 0xc4b2, 0x0b15,
+ 0xc4b6, 0x208f,
+ 0xc4b7, 0x0b1a,
+ 0xc4c6, 0x2090,
+ 0xc4c7, 0x0b2a,
+ 0xc4c9, 0x2091,
+ 0xc4ca, 0x0b2d,
+ 0xc4d1, 0x2092,
+ 0xc4d2, 0x0b35,
+ 0xc4d3, 0x2093,
+ 0xc4d7, 0x0b3a,
+ 0xc4d9, 0x2097,
+ 0xc4da, 0x0b3d,
+ 0xc4e2, 0x2098,
+ 0xc4e3, 0x0b46,
+ 0xc4e5, 0x2099,
+ 0xc4e6, 0x0b49,
+ 0xc4ec, 0x209a,
+ 0xc4ed, 0x0b50,
+ 0xc4f0, 0x209b,
+ 0xc4f2, 0x0b55,
+ 0xc4f4, 0x209d,
+ 0xc4f5, 0x0b58,
+ 0xc4f6, 0x209e,
+ 0xc4f9, 0x0b5c,
+ 0xc4fb, 0x20a1,
+ 0xc4fd, 0x0b60,
+ 0xc4fe, 0x20a3,
+ 0xc5a1, 0x20a4,
+ 0xc5a3, 0x0b64,
+ 0xc5a5, 0x20a6,
+ 0xc5aa, 0x0b6b,
+ 0xc5b1, 0x20ab,
+ 0xc5b2, 0x0b73,
+ 0xc5b5, 0x20ac,
+ 0xc5b6, 0x0b77,
+ 0xc5b7, 0x20ad,
+ 0xc5ba, 0x0b7b,
+ 0xc5bb, 0x20b0,
+ 0xc5bc, 0x0b7d,
+ 0xc5bd, 0x20b1,
+ 0xc5be, 0x0b7f,
+ 0xc5cc, 0x20b2,
+ 0xc5cd, 0x0b8e,
+ 0xc5d3, 0x20b3,
+ 0xc5d4, 0x0b95,
+ 0xc5e2, 0x20b4,
+ 0xc5e3, 0x0ba4,
+ 0xc5e7, 0x20b5,
+ 0xc5e8, 0x0ba9,
+ 0xc5f4, 0x20b6,
+ 0xc5f5, 0x0bb6,
+ 0xc6a1, 0x0bc0,
+ 0xc6ad, 0x20b7,
+ 0xc6af, 0x0bce,
+ 0xc6b5, 0x20b9,
+ 0xc6b7, 0x0bd6,
+ 0xc6bb, 0x20bb,
+ 0xc6bc, 0x0bdb,
+ 0xc6be, 0x20bc,
+ 0xc6bf, 0x0bde,
+ 0xc6c0, 0x20bd,
+ 0xc6c1, 0x0be0,
+ 0xc6c3, 0x20be,
+ 0xc6c5, 0x0be4,
+ 0xc6cb, 0x20c0,
+ 0xc6ce, 0x0bed,
+ 0xc6d3, 0x20c3,
+ 0xc6d4, 0x0bf3,
+ 0xc6d7, 0x20c4,
+ 0xc6d8, 0x0bf7,
+ 0xc6ea, 0x20c5,
+ 0xc6ec, 0x0c0b,
+ 0xc6ef, 0x20c7,
+ 0xc6f0, 0x0c0f,
+ 0xc6f1, 0x20c8,
+ 0xc6f2, 0x0c11,
+ 0xc6f4, 0x20c9,
+ 0xc6f5, 0x0c14,
+ 0xc6f8, 0x20ca,
+ 0xc6f9, 0x0c18,
+ 0xc6fd, 0x20cb,
+ 0xc6fe, 0x0c1d,
+ 0xc7a1, 0x0c1e,
+ 0xc7a3, 0x20cc,
+ 0xc7a4, 0x0c21,
+ 0xc7a5, 0x20cd,
+ 0xc7a7, 0x0c24,
+ 0xc7a8, 0x20cf,
+ 0xc7aa, 0x0c27,
+ 0xc7ab, 0x20d1,
+ 0xc7ac, 0x0c29,
+ 0xc7ae, 0x20d2,
+ 0xc7b0, 0x0c2d,
+ 0xc7b3, 0x20d4,
+ 0xc7b6, 0x0c33,
+ 0xc7b9, 0x20d7,
+ 0xc7bb, 0x0c38,
+ 0xc7bd, 0x20d9,
+ 0xc7bf, 0x0c3c,
+ 0xc7c0, 0x20db,
+ 0xc7c1, 0x0c3e,
+ 0xc7c2, 0x20dc,
+ 0xc7c3, 0x0c40,
+ 0xc7c5, 0x20dd,
+ 0xc7c6, 0x0c43,
+ 0xc7c7, 0x20de,
+ 0xc7c9, 0x0c46,
+ 0xc7cc, 0x20e0,
+ 0xc7cd, 0x0c4a,
+ 0xc7cf, 0x20e1,
+ 0xc7d0, 0x0c4d,
+ 0xc7d4, 0x20e2,
+ 0xc7d6, 0x0c53,
+ 0xc7d7, 0x20e4,
+ 0xc7d8, 0x0c55,
+ 0xc7de, 0x20e5,
+ 0xc7df, 0x0c5c,
+ 0xc7e1, 0x20e6,
+ 0xc7e4, 0x0c61,
+ 0xc7ea, 0x20e9,
+ 0xc7ef, 0x0c6c,
+ 0xc7f7, 0x20ee,
+ 0xc7f9, 0x0c76,
+ 0xc7fb, 0x20f0,
+ 0xc7fc, 0x0c79,
+ 0xc7fd, 0x20f1,
+ 0xc7fe, 0x0c7b,
+ 0xc8a1, 0x0c7c,
+ 0xc8a3, 0x20f2,
+ 0xc8a4, 0x0c7f,
+ 0xc8a7, 0x20f3,
+ 0xc8a9, 0x0c84,
+ 0xc8b0, 0x20f5,
+ 0xc8b1, 0x0c8c,
+ 0xc8b5, 0x20f6,
+ 0xc8b6, 0x0c91,
+ 0xc8b7, 0x20f7,
+ 0xc8b8, 0x0c93,
+ 0xc8c3, 0x20f8,
+ 0xc8c7, 0x0ca2,
+ 0xc8c8, 0x20fc,
+ 0xc8c9, 0x0ca4,
+ 0xc8cd, 0x20fd,
+ 0xc8ce, 0x0ca9,
+ 0xc8cf, 0x20fe,
+ 0xc8d0, 0x0cab,
+ 0xc8d2, 0x20ff,
+ 0xc8d3, 0x0cae,
+ 0xc8d9, 0x2100,
+ 0xc8da, 0x0cb5,
+ 0xc8de, 0x2101,
+ 0xc8df, 0x0cba,
+ 0xc8ed, 0x2102,
+ 0xc8ee, 0x0cc9,
+ 0xc8f1, 0x2103,
+ 0xc8f4, 0x0ccf,
+ 0xc8f7, 0x2106,
+ 0xc8f9, 0x0cd4,
+ 0xc8fa, 0x2108,
+ 0xc8fb, 0x0cd6,
+ 0xc8fc, 0x2109,
+ 0xc8fd, 0x0cd8,
+ 0xc9a1, 0x210a,
+ 0xc9a2, 0x0cdb,
+ 0xc9a5, 0x210b,
+ 0xc9a6, 0x0cdf,
+ 0xc9a7, 0x210c,
+ 0xc9a9, 0x0ce2,
+ 0xc9ac, 0x210e,
+ 0xc9ad, 0x0ce6,
+ 0xc9b1, 0x210f,
+ 0xc9b2, 0x0ceb,
+ 0xc9b4, 0x2110,
+ 0xc9b5, 0x0cee,
+ 0xc9b8, 0x2111,
+ 0xc9ba, 0x0cf3,
+ 0xc9c1, 0x2113,
+ 0xc9c3, 0x0cfc,
+ 0xc9c4, 0x2115,
+ 0xc9c5, 0x0cfe,
+ 0xc9c9, 0x2116,
+ 0xc9ca, 0x0d03,
+ 0xc9cb, 0x2117,
+ 0xc9cc, 0x0d05,
+ 0xc9cd, 0x2118,
+ 0xc9ce, 0x0d07,
+ 0xc9d5, 0x2119,
+ 0xc9d6, 0x0d0f,
+ 0xc9dc, 0x211a,
+ 0xc9dd, 0x0d16,
+ 0xc9de, 0x211b,
+ 0xc9df, 0x0d18,
+ 0xc9e1, 0x211c,
+ 0xc9e2, 0x0d1b,
+ 0xc9e3, 0x211d,
+ 0xc9e4, 0x0d1d,
+ 0xc9e5, 0x211e,
+ 0xc9e6, 0x0d1f,
+ 0xc9e8, 0x211f,
+ 0xc9e9, 0x0d22,
+ 0xc9f0, 0x2120,
+ 0xc9f1, 0x0d2a,
+ 0xc9f3, 0x2121,
+ 0xc9f5, 0x0d2e,
+ 0xc9f6, 0x2123,
+ 0xc9f7, 0x0d30,
+ 0xc9f8, 0x2124,
+ 0xc9fa, 0x0d33,
+ 0xc9fe, 0x2126,
+ 0xcaa1, 0x0d38,
+ 0xcaa4, 0x2127,
+ 0xcaa7, 0x0d3e,
+ 0xcaa8, 0x212a,
+ 0xcaa9, 0x0d40,
+ 0xcaaa, 0x212b,
+ 0xcaac, 0x0d43,
+ 0xcab1, 0x212d,
+ 0xcab2, 0x0d49,
+ 0xcab4, 0x212e,
+ 0xcab7, 0x0d4e,
+ 0xcabb, 0x2131,
+ 0xcabc, 0x0d53,
+ 0xcac6, 0x2132,
+ 0xcac7, 0x0d5e,
+ 0xcaca, 0x2133,
+ 0xcacb, 0x0d62,
+ 0xcacd, 0x2134,
+ 0xcacf, 0x0d66,
+ 0xcad3, 0x2136,
+ 0xcad5, 0x0d6c,
+ 0xcad9, 0x2138,
+ 0xcada, 0x0d71,
+ 0xcade, 0x2139,
+ 0xcadf, 0x0d76,
+ 0xcae0, 0x213a,
+ 0xcae1, 0x0d78,
+ 0xcae4, 0x213b,
+ 0xcae5, 0x0d7c,
+ 0xcae9, 0x213c,
+ 0xcaeb, 0x0d82,
+ 0xcaf4, 0x213e,
+ 0xcaf6, 0x0d8d,
+ 0xcaf7, 0x2140,
+ 0xcaf8, 0x0d8f,
+ 0xcafa, 0x2141,
+ 0xcafb, 0x0d92,
+ 0xcafd, 0x2142,
+ 0xcafe, 0x0d95,
+ 0xcba1, 0x0d96,
+ 0xcba7, 0x2143,
+ 0xcba8, 0x0d9d,
+ 0xcbab, 0x2144,
+ 0xcbac, 0x0da1,
+ 0xcbad, 0x2145,
+ 0xcbae, 0x0da3,
+ 0xcbb3, 0x2146,
+ 0xcbb4, 0x0da9,
+ 0xcbb5, 0x2147,
+ 0xcbb7, 0x0dac,
+ 0xcbb8, 0x2149,
+ 0xcbb9, 0x0dae,
+ 0xcbbf, 0x214a,
+ 0xcbc0, 0x0db5,
+ 0xcbc7, 0x214b,
+ 0xcbc8, 0x0dbd,
+ 0xcbc9, 0x214c,
+ 0xcbcd, 0x0dc2,
+ 0xcbcf, 0x2150,
+ 0xcbd1, 0x0dc6,
+ 0xcbd3, 0x2152,
+ 0xcbd4, 0x0dc9,
+ 0xcbd5, 0x2153,
+ 0xcbd6, 0x0dcb,
+ 0xcbdf, 0x2154,
+ 0xcbe1, 0x0dd6,
+ 0xcbe4, 0x2156,
+ 0xcbe5, 0x0dda,
+ 0xcbe6, 0x2157,
+ 0xcbe8, 0x0ddd,
+ 0xcbea, 0x2159,
+ 0xcbeb, 0x0de0,
+ 0xcbef, 0x215a,
+ 0xcbf1, 0x0de6,
+ 0xcbf5, 0x215c,
+ 0xcbf7, 0x0dec,
+ 0xcbf8, 0x215e,
+ 0xcbf9, 0x0dee,
+ 0xcca1, 0x215f,
+ 0xcca3, 0x0df6,
+ 0xcca8, 0x2161,
+ 0xcca9, 0x0dfc,
+ 0xccac, 0x2162,
+ 0xccad, 0x0e00,
+ 0xccaf, 0x2163,
+ 0xccb4, 0x0e07,
+ 0xccb7, 0x2168,
+ 0xccb9, 0x0e0c,
+ 0xccbe, 0x216a,
+ 0xccbf, 0x0e12,
+ 0xccc0, 0x216b,
+ 0xccc1, 0x0e14,
+ 0xcccc, 0x216c,
+ 0xcccd, 0x0e20,
+ 0xccce, 0x216d,
+ 0xcccf, 0x0e22,
+ 0xccd0, 0x216e,
+ 0xccd1, 0x0e24,
+ 0xccd6, 0x216f,
+ 0xccd7, 0x0e2a,
+ 0xccda, 0x2170,
+ 0xccdb, 0x0e2e,
+ 0xccdc, 0x2171,
+ 0xccdd, 0x0e30,
+ 0xcce0, 0x2172,
+ 0xcce1, 0x0e34,
+ 0xcce2, 0x2173,
+ 0xcce3, 0x0e36,
+ 0xcce5, 0x2174,
+ 0xcce6, 0x0e39,
+ 0xccf5, 0x2175,
+ 0xccf6, 0x0e49,
+ 0xccf9, 0x2176,
+ 0xccfb, 0x0e4e,
+ 0xccfc, 0x2178,
+ 0xcda1, 0x0e52,
+ 0xcdad, 0x217b,
+ 0xcdae, 0x0e5f,
+ 0xcdb3, 0x217c,
+ 0xcdb4, 0x0e65,
+ 0xcdb7, 0x217d,
+ 0xcdb8, 0x0e69,
+ 0xcdbc, 0x217e,
+ 0xcdbd, 0x0e6e,
+ 0xcdbf, 0x217f,
+ 0xcdc0, 0x0e71,
+ 0xcdc5, 0x2180,
+ 0xcdc6, 0x0e77,
+ 0xcdc7, 0x2181,
+ 0xcdc8, 0x0e79,
+ 0xcdd2, 0x2182,
+ 0xcdd3, 0x0e84,
+ 0xcdd4, 0x2183,
+ 0xcdd7, 0x0e88,
+ 0xcddd, 0x2186,
+ 0xcdde, 0x0e8f,
+ 0xcde0, 0x2187,
+ 0xcde1, 0x0e92,
+ 0xcde4, 0x2188,
+ 0xcde6, 0x0e97,
+ 0xcde7, 0x218a,
+ 0xcde8, 0x0e99,
+ 0xcdf2, 0x218b,
+ 0xcdf3, 0x0ea4,
+ 0xcdf8, 0x218c,
+ 0xcdf9, 0x0eaa,
+ 0xcea1, 0x0eb0,
+ 0xcea4, 0x218d,
+ 0xcea6, 0x0eb5,
+ 0xcea7, 0x218f,
+ 0xcea8, 0x0eb7,
+ 0xceaa, 0x2190,
+ 0xceae, 0x0ebd,
+ 0xceb0, 0x2194,
+ 0xceb2, 0x0ec1,
+ 0xceb3, 0x2196,
+ 0xceb4, 0x0ec3,
+ 0xcebd, 0x2197,
+ 0xcebe, 0x0ecd,
+ 0xcec0, 0x2198,
+ 0xcec1, 0x0ed0,
+ 0xcec5, 0x2199,
+ 0xcec7, 0x0ed6,
+ 0xcec8, 0x219b,
+ 0xcec9, 0x0ed8,
+ 0xceca, 0x219c,
+ 0xcecb, 0x0eda,
+ 0xcece, 0x219d,
+ 0xced2, 0x0ee1,
+ 0xced8, 0x21a1,
+ 0xcedb, 0x0eea,
+ 0xcedc, 0x21a4,
+ 0xcedd, 0x0eec,
+ 0xcede, 0x21a5,
+ 0xcee0, 0x0eef,
+ 0xceeb, 0x21a7,
+ 0xceec, 0x0efb,
+ 0xceed, 0x21a8,
+ 0xceee, 0x0efd,
+ 0xcef1, 0x21a9,
+ 0xcef2, 0x0f01,
+ 0xcef3, 0x21aa,
+ 0xcef4, 0x0f03,
+ 0xcefd, 0x21ab,
+ 0xcfa1, 0x0f0e,
+ 0xcfae, 0x21ad,
+ 0xcfaf, 0x0f1c,
+ 0xcfb0, 0x21ae,
+ 0xcfb1, 0x0f1e,
+ 0xcfb3, 0x21af,
+ 0xcfb4, 0x0f21,
+ 0xcfb7, 0x21b0,
+ 0xcfb9, 0x0f26,
+ 0xcfba, 0x21b2,
+ 0xcfbb, 0x0f28,
+ 0xcfbd, 0x21b3,
+ 0xcfbe, 0x0f2b,
+ 0xcfbf, 0x21b4,
+ 0xcfc2, 0x0f2f,
+ 0xcfc5, 0x21b7,
+ 0xcfc6, 0x0f33,
+ 0xcfc7, 0x21b8,
+ 0xcfc8, 0x0f35,
+ 0xcfca, 0x21b9,
+ 0xcfcc, 0x0f39,
+ 0xcfcd, 0x21bb,
+ 0xcfcf, 0x0f3c,
+ 0xcfd0, 0x21bd,
+ 0xcfd1, 0x0f3e,
+ 0xcfd4, 0x21be,
+ 0xcfd9, 0x0f46,
+ 0xcfda, 0x21c3,
+ 0xcfdb, 0x0f48,
+ 0xcfdc, 0x21c4,
+ 0xcfdd, 0x0f4a,
+ 0xcfdf, 0x21c5,
+ 0xcfe0, 0x0f4d,
+ 0xcfe2, 0x21c6,
+ 0xcfe3, 0x0f50,
+ 0xcfe7, 0x21c7,
+ 0xcfe8, 0x0f55,
+ 0xcfea, 0x21c8,
+ 0xcfeb, 0x0f58,
+ 0xcfec, 0x21c9,
+ 0xcfed, 0x0f5a,
+ 0xcfee, 0x21ca,
+ 0xcfef, 0x0f5c,
+ 0xcff4, 0x21cb,
+ 0xcff5, 0x0f62,
+ 0xcff9, 0x21cc,
+ 0xcffb, 0x0f68,
+ 0xcffe, 0x21ce,
+ 0xd0a1, 0x0f6c,
+ 0xd0a5, 0x21cf,
+ 0xd0a6, 0x0f71,
+ 0xd0ad, 0x21d0,
+ 0xd0af, 0x0f7a,
+ 0xd0b2, 0x21d2,
+ 0xd0b5, 0x0f80,
+ 0xd0ba, 0x21d5,
+ 0xd0bc, 0x0f87,
+ 0xd0bf, 0x21d7,
+ 0xd0c0, 0x0f8b,
+ 0xd0c6, 0x21d8,
+ 0xd0c7, 0x0f92,
+ 0xd0cb, 0x21d9,
+ 0xd0cc, 0x0f97,
+ 0xd0e2, 0x21da,
+ 0xd0e3, 0x0fae,
+ 0xd0e5, 0x21db,
+ 0xd0e6, 0x0fb1,
+ 0xd0eb, 0x21dc,
+ 0xd0ec, 0x0fb7,
+ 0xd0ed, 0x21dd,
+ 0xd0ee, 0x0fb9,
+ 0xd0f7, 0x21de,
+ 0xd0fa, 0x0fc5,
+ 0xd0fc, 0x21e1,
+ 0xd0fd, 0x0fc8,
+ 0xd1a1, 0x21e2,
+ 0xd1a3, 0x0fcc,
+ 0xd1a4, 0x21e4,
+ 0xd1a5, 0x0fce,
+ 0xd1a7, 0x21e5,
+ 0xd1a8, 0x0fd1,
+ 0xd1ab, 0x21e6,
+ 0xd1ac, 0x0fd5,
+ 0xd1af, 0x21e7,
+ 0xd1b2, 0x0fdb,
+ 0xd1b5, 0x21ea,
+ 0xd1b8, 0x0fe1,
+ 0xd1b9, 0x21ed,
+ 0xd1ba, 0x0fe3,
+ 0xd1bb, 0x21ee,
+ 0xd1bd, 0x0fe6,
+ 0xd1c6, 0x21f0,
+ 0xd1c9, 0x0ff2,
+ 0xd1cb, 0x21f3,
+ 0xd1cc, 0x0ff5,
+ 0xd1ce, 0x21f4,
+ 0xd1d0, 0x0ff9,
+ 0xd1d5, 0x21f6,
+ 0xd1d7, 0x1000,
+ 0xd1de, 0x21f8,
+ 0xd1df, 0x1008,
+ 0xd1e1, 0x21f9,
+ 0xd1e3, 0x100c,
+ 0xd1e8, 0x21fb,
+ 0xd1ea, 0x1013,
+ 0xd1ec, 0x21fd,
+ 0xd1ed, 0x1016,
+ 0xd1ee, 0x21fe,
+ 0xd1f0, 0x1019,
+ 0xd1f1, 0x2200,
+ 0xd1f2, 0x101b,
+ 0xd1f4, 0x2201,
+ 0xd1f5, 0x101e,
+ 0xd1f7, 0x2202,
+ 0xd1fa, 0x1023,
+ 0xd2a1, 0x1028,
+ 0xd2a2, 0x2205,
+ 0xd2a3, 0x102a,
+ 0xd2a5, 0x2206,
+ 0xd2a6, 0x102d,
+ 0xd2a9, 0x2207,
+ 0xd2aa, 0x1031,
+ 0xd2af, 0x2208,
+ 0xd2b0, 0x1037,
+ 0xd2b3, 0x2209,
+ 0xd2b4, 0x103b,
+ 0xd2b5, 0x220a,
+ 0xd2b7, 0x103e,
+ 0xd2bd, 0x220c,
+ 0xd2be, 0x1045,
+ 0xd2bf, 0x220d,
+ 0xd2c0, 0x1047,
+ 0xd2c3, 0x220e,
+ 0xd2c4, 0x104b,
+ 0xd2c5, 0x220f,
+ 0xd2c6, 0x104d,
+ 0xd2c7, 0x2210,
+ 0xd2c8, 0x104f,
+ 0xd2cf, 0x2211,
+ 0xd2d0, 0x1057,
+ 0xd2d5, 0x2212,
+ 0xd2d6, 0x105d,
+ 0xd2da, 0x2213,
+ 0xd2db, 0x1062,
+ 0xd2e4, 0x2214,
+ 0xd2e6, 0x106d,
+ 0xd2e8, 0x2216,
+ 0xd2ec, 0x1073,
+ 0xd2ef, 0x221a,
+ 0xd2f0, 0x1077,
+ 0xd2f1, 0x221b,
+ 0xd2f2, 0x1079,
+ 0xd2f5, 0x221c,
+ 0xd2f6, 0x107d,
+ 0xd2f8, 0x221d,
+ 0xd2f9, 0x1080,
+ 0xd2fb, 0x221e,
+ 0xd2fc, 0x1083,
+ 0xd2fe, 0x221f,
+ 0xd3a1, 0x1086,
+ 0xd3a3, 0x2220,
+ 0xd3ad, 0x1092,
+ 0xd3ae, 0x222a,
+ 0xd3af, 0x1094,
+ 0xd3b1, 0x222b,
+ 0xd3b2, 0x1097,
+ 0xd3b4, 0x222c,
+ 0xd3b7, 0x109c,
+ 0xd3b8, 0x222f,
+ 0xd3b9, 0x109e,
+ 0xd3bb, 0x2230,
+ 0xd3bc, 0x10a1,
+ 0xd3c5, 0x2231,
+ 0xd3c6, 0x10ab,
+ 0xd3c7, 0x2232,
+ 0xd3c8, 0x10ad,
+ 0xd3ca, 0x2233,
+ 0xd3cd, 0x10b2,
+ 0xd3d5, 0x2236,
+ 0xd3d6, 0x10bb,
+ 0xd3df, 0x2237,
+ 0xd3e1, 0x10c6,
+ 0xd3e3, 0x2239,
+ 0xd3e4, 0x10c9,
+ 0xd3e6, 0x223a,
+ 0xd3e7, 0x10cc,
+ 0xd3eb, 0x223b,
+ 0xd3ed, 0x10d2,
+ 0xd3ef, 0x223d,
+ 0xd3f0, 0x10d5,
+ 0xd3f4, 0x223e,
+ 0xd3f5, 0x10da,
+ 0xd3fc, 0x223f,
+ 0xd3fd, 0x10e2,
+ 0xd3fe, 0x2240,
+ 0xd4a1, 0x10e4,
+ 0xd4a4, 0x2241,
+ 0xd4a5, 0x10e8,
+ 0xd4a6, 0x2242,
+ 0xd4a9, 0x10ec,
+ 0xd4af, 0x2245,
+ 0xd4b3, 0x10f6,
+ 0xd4b5, 0x2249,
+ 0xd4b7, 0x10fa,
+ 0xd4b8, 0x224b,
+ 0xd4b9, 0x10fc,
+ 0xd4bc, 0x224c,
+ 0xd4bd, 0x1100,
+ 0xd4be, 0x224d,
+ 0xd4c0, 0x1103,
+ 0xd4c4, 0x224f,
+ 0xd4c5, 0x1108,
+ 0xd4c6, 0x2250,
+ 0xd4c8, 0x110b,
+ 0xd4c9, 0x2252,
+ 0xd4ca, 0x110d,
+ 0xd4cb, 0x2253,
+ 0xd4cf, 0x1112,
+ 0xd4d3, 0x2257,
+ 0xd4d4, 0x1117,
+ 0xd4d8, 0x2258,
+ 0xd4d9, 0x111c,
+ 0xd4dc, 0x2259,
+ 0xd4e1, 0x1124,
+ 0xd4e4, 0x225e,
+ 0xd4e5, 0x1128,
+ 0xd4e6, 0x225f,
+ 0xd4e7, 0x112a,
+ 0xd4ee, 0x2260,
+ 0xd4ef, 0x1132,
+ 0xd4f0, 0x2261,
+ 0xd4f5, 0x1138,
+ 0xd4f9, 0x2266,
+ 0xd4fa, 0x113d,
+ 0xd4fe, 0x2267,
+ 0xd5a1, 0x2268,
+ 0xd5a3, 0x1144,
+ 0xd5a9, 0x226a,
+ 0xd5aa, 0x114b,
+ 0xd5ab, 0x226b,
+ 0xd5ac, 0x114d,
+ 0xd5ae, 0x226c,
+ 0xd5af, 0x1150,
+ 0xd5b1, 0x226d,
+ 0xd5b2, 0x1153,
+ 0xd5b5, 0x226e,
+ 0xd5b9, 0x115a,
+ 0xd5bb, 0x2272,
+ 0xd5bc, 0x115d,
+ 0xd5bd, 0x2273,
+ 0xd5be, 0x115f,
+ 0xd5c0, 0x2274,
+ 0xd5c1, 0x1162,
+ 0xd5c5, 0x2275,
+ 0xd5c6, 0x1167,
+ 0xd5c7, 0x2276,
+ 0xd5c8, 0x1169,
+ 0xd5ca, 0x2277,
+ 0xd5cc, 0x116d,
+ 0xd5cd, 0x2279,
+ 0xd5ce, 0x116f,
+ 0xd5d4, 0x227a,
+ 0xd5d5, 0x1176,
+ 0xd5dd, 0x227b,
+ 0xd5df, 0x1180,
+ 0xd5e0, 0x227d,
+ 0xd5e1, 0x1182,
+ 0xd5e2, 0x227e,
+ 0xd5e3, 0x1184,
+ 0xd5ea, 0x227f,
+ 0xd5ed, 0x118e,
+ 0xd5ef, 0x2282,
+ 0xd5f0, 0x1191,
+ 0xd5f2, 0x2283,
+ 0xd5f4, 0x1195,
+ 0xd5f7, 0x15eb,
+ 0xd5f8, 0x1199,
+ 0xd6a1, 0x2285,
+ 0xd6a5, 0x11a4,
+ 0xd6af, 0x2289,
+ 0xd6b1, 0x11b0,
+ 0xd6b4, 0x228b,
+ 0xd6b5, 0x11b4,
+ 0xd6bb, 0x228c,
+ 0xd6bc, 0x11bb,
+ 0xd6bd, 0x228d,
+ 0xd6be, 0x11bd,
+ 0xd6bf, 0x228e,
+ 0xd6c1, 0x11c0,
+ 0xd6c4, 0x2290,
+ 0xd6c5, 0x11c4,
+ 0xd6ca, 0x2291,
+ 0xd6cb, 0x11ca,
+ 0xd6cd, 0x2292,
+ 0xd6ce, 0x11cd,
+ 0xd6d3, 0x2293,
+ 0xd6d4, 0x11d3,
+ 0xd6d5, 0x2294,
+ 0xd6d8, 0x11d7,
+ 0xd6da, 0x2297,
+ 0xd6db, 0x11da,
+ 0xd6df, 0x2298,
+ 0xd6e0, 0x11df,
+ 0xd6e1, 0x2299,
+ 0xd6e2, 0x11e1,
+ 0xd6e5, 0x229a,
+ 0xd6e6, 0x11e5,
+ 0xd6e7, 0x229b,
+ 0xd6e9, 0x11e8,
+ 0xd6ee, 0x229d,
+ 0xd6f0, 0x11ef,
+ 0xd6f2, 0x229f,
+ 0xd6f3, 0x11f2,
+ 0xd6f5, 0x22a0,
+ 0xd6f7, 0x11f6,
+ 0xd6fc, 0x22a2,
+ 0xd7a1, 0x11fe,
+ 0xd7a4, 0x22a5,
+ 0xd7a5, 0x1202,
+ 0xd7a8, 0x22a6,
+ 0xd7ab, 0x1208,
+ 0xd7ac, 0x22a9,
+ 0xd7ad, 0x120a,
+ 0xd7ae, 0x22aa,
+ 0xd7b2, 0x120f,
+ 0xd7b3, 0x22ae,
+ 0xd7b5, 0x1212,
+ 0xd7b6, 0x22b0,
+ 0xd7b7, 0x1214,
+ 0xd7b8, 0x22b1,
+ 0xd7bd, 0x121a,
+ 0xd7c7, 0x22b6,
+ 0xd7c8, 0x1225,
+ 0xd7ca, 0x22b7,
+ 0xd7cb, 0x1228,
+ 0xd7d5, 0x22b8,
+ 0xd7d6, 0x1233,
+ 0xd7db, 0x22b9,
+ 0xd7df, 0x123c,
+ 0xd7e7, 0x22bd,
+ 0xd7e8, 0x1245,
+ 0xd7e9, 0x22be,
+ 0xd7eb, 0x1248,
+ 0xd8a1, 0x1257,
+ 0xd8c4, 0x22c0,
+ 0xd8c5, 0x127b,
+ 0xd8c7, 0x22c1,
+ 0xd8c8, 0x127e,
+ 0xd8c9, 0x22c2,
+ 0xd8ca, 0x1280,
+ 0xd8cc, 0x22c3,
+ 0xd8ce, 0x1284,
+ 0xd8d0, 0x22c5,
+ 0xd8d2, 0x1288,
+ 0xd8d3, 0x22c7,
+ 0xd8d4, 0x128a,
+ 0xd8d9, 0x22c8,
+ 0xd8da, 0x1290,
+ 0xd8db, 0x22c9,
+ 0xd8dd, 0x1293,
+ 0xd8f1, 0x22cb,
+ 0xd8f2, 0x12a8,
+ 0xd8f6, 0x22cc,
+ 0xd8f8, 0x12ae,
+ 0xd9a1, 0x12b5,
+ 0xd9ad, 0x22ce,
+ 0xd9ae, 0x12c2,
+ 0xd9af, 0x22cf,
+ 0xd9b0, 0x12c4,
+ 0xd9b1, 0x22d0,
+ 0xd9b4, 0x12c8,
+ 0xd9c7, 0x22d3,
+ 0xd9c8, 0x12dc,
+ 0xd9cd, 0x22d4,
+ 0xd9d1, 0x12e5,
+ 0xd9dd, 0x22d8,
+ 0xd9de, 0x12f2,
+ 0xd9e1, 0x22d9,
+ 0xd9e2, 0x12f6,
+ 0xd9e4, 0x22da,
+ 0xd9e5, 0x12f9,
+ 0xd9e6, 0x22db,
+ 0xd9e7, 0x12fb,
+ 0xd9ec, 0x22dc,
+ 0xd9ed, 0x1301,
+ 0xd9f4, 0x22dd,
+ 0xd9f6, 0x130a,
+ 0xdaa1, 0x1313,
+ 0xdaa5, 0x22df,
+ 0xdae0, 0x1352,
+ 0xdaea, 0x231a,
+ 0xdaeb, 0x135d,
+ 0xdaf7, 0x231b,
+ 0xdaf8, 0x136a,
+ 0xdaf9, 0x231c,
+ 0xdafa, 0x136c,
+ 0xdafe, 0x231d,
+ 0xdba1, 0x1371,
+ 0xdba3, 0x231e,
+ 0xdba4, 0x1374,
+ 0xdba6, 0x231f,
+ 0xdba7, 0x1377,
+ 0xdba9, 0x2320,
+ 0xdbab, 0x137b,
+ 0xdbbb, 0x2322,
+ 0xdbbc, 0x138c,
+ 0xdbbd, 0x2323,
+ 0xdbbe, 0x138e,
+ 0xdbcf, 0x2324,
+ 0xdbd0, 0x13a0,
+ 0xdbd1, 0x2325,
+ 0xdbd2, 0x13a2,
+ 0xdbdb, 0x2326,
+ 0xdbdc, 0x13ac,
+ 0xdbde, 0x2327,
+ 0xdbdf, 0x13af,
+ 0xdbe2, 0x2328,
+ 0xdbe3, 0x13b3,
+ 0xdbe4, 0x2329,
+ 0xdbe5, 0x13b5,
+ 0xdbeb, 0x232a,
+ 0xdbec, 0x13bc,
+ 0xdbee, 0x232b,
+ 0xdbef, 0x13bf,
+ 0xdbf1, 0x232c,
+ 0xdbf2, 0x13c2,
+ 0xdbf5, 0x232d,
+ 0xdbf8, 0x13c8,
+ 0xdca1, 0x13cf,
+ 0xdcbc, 0x2330,
+ 0xdcbd, 0x13eb,
+ 0xdcbf, 0x2331,
+ 0xdcc0, 0x13ee,
+ 0xdcc2, 0x2332,
+ 0xdcc3, 0x13f1,
+ 0xdcc8, 0x2333,
+ 0xdccb, 0x13f9,
+ 0xdcd1, 0x2336,
+ 0xdcd2, 0x1400,
+ 0xdcd7, 0x2337,
+ 0xdcd8, 0x1406,
+ 0xdce0, 0x2338,
+ 0xdce1, 0x140f,
+ 0xdce3, 0x2339,
+ 0xdce5, 0x1413,
+ 0xdce9, 0x233b,
+ 0xdceb, 0x1419,
+ 0xdcf1, 0x233d,
+ 0xdcf2, 0x1420,
+ 0xdcf6, 0x233e,
+ 0xdcf7, 0x1425,
+ 0xdcf9, 0x233f,
+ 0xdcfa, 0x1428,
+ 0xdcfd, 0x2340,
+ 0xdda1, 0x2342,
+ 0xdda2, 0x142e,
+ 0xdda3, 0x2343,
+ 0xdda8, 0x1434,
+ 0xddaa, 0x2348,
+ 0xddac, 0x1438,
+ 0xddb2, 0x234a,
+ 0xddb3, 0x143f,
+ 0xddb5, 0x234b,
+ 0xddb6, 0x1442,
+ 0xddba, 0x234c,
+ 0xddbc, 0x1448,
+ 0xddd3, 0x234e,
+ 0xddd4, 0x1460,
+ 0xdddb, 0x234f,
+ 0xdddc, 0x1468,
+ 0xddde, 0x2350,
+ 0xdddf, 0x146b,
+ 0xdde4, 0x2351,
+ 0xdde5, 0x1471,
+ 0xddeb, 0x2352,
+ 0xddec, 0x1478,
+ 0xddf1, 0x2353,
+ 0xddf2, 0x147e,
+ 0xddf6, 0x2354,
+ 0xddf8, 0x1484,
+ 0xddfc, 0x2356,
+ 0xddfd, 0x1489,
+ 0xddfe, 0x2357,
+ 0xdea1, 0x148b,
+ 0xdead, 0x2358,
+ 0xdeae, 0x1498,
+ 0xdeb4, 0x2359,
+ 0xdeb5, 0x149f,
+ 0xdeba, 0x235a,
+ 0xdebb, 0x14a5,
+ 0xdec6, 0x235b,
+ 0xdec7, 0x14b1,
+ 0xdecf, 0x235c,
+ 0xded0, 0x14ba,
+ 0xded1, 0x235d,
+ 0xded3, 0x14bd,
+ 0xded8, 0x235f,
+ 0xded9, 0x14c3,
+ 0xdee2, 0x2360,
+ 0xdee3, 0x14cd,
+ 0xdee8, 0x2361,
+ 0xdee9, 0x14d3,
+ 0xdeec, 0x2362,
+ 0xdeed, 0x14d7,
+ 0xdef3, 0x2363,
+ 0xdef4, 0x14de,
+ 0xdefc, 0x2364,
+ 0xdefd, 0x14e7,
+ 0xdfa1, 0x14e9,
+ 0xdfa2, 0x2365,
+ 0xdfa4, 0x14ec,
+ 0xdfa5, 0x2367,
+ 0xdfa6, 0x14ee,
+ 0xdfb4, 0x2368,
+ 0xdfb5, 0x14fd,
+ 0xdfbc, 0x2369,
+ 0xdfbe, 0x1506,
+ 0xdfbf, 0x236b,
+ 0xdfc0, 0x1508,
+ 0xdfc2, 0x236c,
+ 0xdfc4, 0x150c,
+ 0xdfcc, 0x236e,
+ 0xdfcd, 0x1515,
+ 0xdfd0, 0x236f,
+ 0xdfd1, 0x1519,
+ 0xdfd5, 0x2370,
+ 0xdfd6, 0x151e,
+ 0xdfd8, 0x2371,
+ 0xdfda, 0x1522,
+ 0xdfdc, 0x2373,
+ 0xdfdd, 0x1525,
+ 0xdfe0, 0x2374,
+ 0xdfe1, 0x1529,
+ 0xdfe2, 0x2375,
+ 0xdfe3, 0x152b,
+ 0xdfe6, 0x2376,
+ 0xdfe7, 0x152f,
+ 0xdfe9, 0x2377,
+ 0xdfea, 0x1532,
+ 0xdfeb, 0x2378,
+ 0xdfec, 0x1534,
+ 0xdfef, 0x2379,
+ 0xdff0, 0x1538,
+ 0xdff5, 0x237a,
+ 0xdff6, 0x153e,
+ 0xdff9, 0x237b,
+ 0xdffa, 0x1542,
+ 0xe0a1, 0x1547,
+ 0xe0b6, 0x237c,
+ 0xe0b8, 0x155e,
+ 0xe0bf, 0x237e,
+ 0xe0c0, 0x1566,
+ 0xe0c8, 0x237f,
+ 0xe0c9, 0x156f,
+ 0xe0ce, 0x2380,
+ 0xe0cf, 0x1575,
+ 0xe0d3, 0x2381,
+ 0xe0d4, 0x157a,
+ 0xe0e0, 0x2382,
+ 0xe0e1, 0x1587,
+ 0xe0f0, 0x2383,
+ 0xe0f1, 0x1597,
+ 0xe0f8, 0x2384,
+ 0xe0f9, 0x159f,
+ 0xe0fc, 0x2385,
+ 0xe1a1, 0x15a5,
+ 0xe1ab, 0x2388,
+ 0xe1ac, 0x15b0,
+ 0xe1ad, 0x2389,
+ 0xe1ae, 0x15b2,
+ 0xe1b0, 0x238a,
+ 0xe1b1, 0x15b5,
+ 0xe1b4, 0x238b,
+ 0xe1b5, 0x15b9,
+ 0xe1bb, 0x238c,
+ 0xe1bc, 0x15c0,
+ 0xe1bd, 0x238d,
+ 0xe1be, 0x15c2,
+ 0xe1c0, 0x238e,
+ 0xe1c2, 0x15c6,
+ 0xe1c9, 0x2390,
+ 0xe1ca, 0x15ce,
+ 0xe1d0, 0x2391,
+ 0xe1d1, 0x15d5,
+ 0xe1db, 0x2392,
+ 0xe1dc, 0x15e0,
+ 0xe1e1, 0x07aa,
+ 0xe1e2, 0x2393,
+ 0xe1e3, 0x15e7,
+ 0xe1e7, 0x1198,
+ 0xe1e8, 0x15ec,
+ 0xe1ee, 0x2394,
+ 0xe1f0, 0x15f4,
+ 0xe1f6, 0x2396,
+ 0xe1f7, 0x15fb,
+ 0xe1f8, 0x2397,
+ 0xe1f9, 0x15fd,
+ 0xe1fd, 0x2398,
+ 0xe1fe, 0x1602,
+ 0xe2a1, 0x1603,
+ 0xe2a4, 0x2399,
+ 0xe2a5, 0x1607,
+ 0xe2a8, 0x239a,
+ 0xe2a9, 0x160b,
+ 0xe2bb, 0x239b,
+ 0xe2c5, 0x10c5,
+ 0xe2c6, 0x23a5,
+ 0xe2cf, 0x1631,
+ 0xe2d0, 0x23ae,
+ 0xe2d1, 0x1633,
+ 0xe2d9, 0x23af,
+ 0xe2da, 0x163c,
+ 0xe2e3, 0x23b0,
+ 0xe2e5, 0x1647,
+ 0xe2e6, 0x23b2,
+ 0xe2e7, 0x1649,
+ 0xe2e9, 0x23b3,
+ 0xe2ec, 0x164e,
+ 0xe2f8, 0x23b6,
+ 0xe2f9, 0x165b,
+ 0xe2fa, 0x23b7,
+ 0xe2fe, 0x1660,
+ 0xe3a1, 0x1661,
+ 0xe3a2, 0x23bb,
+ 0xe3a3, 0x1663,
+ 0xe3a5, 0x23bc,
+ 0xe3a6, 0x1666,
+ 0xe3ab, 0x23bd,
+ 0xe3ac, 0x166c,
+ 0xe3b4, 0x23be,
+ 0xe3b5, 0x1675,
+ 0xe3c5, 0x23bf,
+ 0xe3dc, 0x169c,
+ 0xe3e3, 0x23d6,
+ 0xe3e4, 0x16a4,
+ 0xe3ed, 0x23d7,
+ 0xe3ee, 0x16ae,
+ 0xe3f1, 0x23d8,
+ 0xe3f3, 0x16b3,
+ 0xe3f8, 0x23da,
+ 0xe3f9, 0x16b9,
+ 0xe3fe, 0x23db,
+ 0xe4a1, 0x16bf,
+ 0xe4a4, 0x23dc,
+ 0xe4a6, 0x16c4,
+ 0xe4ab, 0x23de,
+ 0xe4ac, 0x16ca,
+ 0xe4af, 0x23df,
+ 0xe4b2, 0x16d0,
+ 0xe4b5, 0x23e2,
+ 0xe4b7, 0x16d5,
+ 0xe4c2, 0x23e4,
+ 0xe4c3, 0x16e1,
+ 0xe4c5, 0x23e5,
+ 0xe4c6, 0x16e4,
+ 0xe4c9, 0x23e6,
+ 0xe4ca, 0x16e8,
+ 0xe4d9, 0x23e7,
+ 0xe4da, 0x16f8,
+ 0xe4dc, 0x23e8,
+ 0xe4dd, 0x16fb,
+ 0xe4de, 0x23e9,
+ 0xe4df, 0x16fd,
+ 0xe4e4, 0x23ea,
+ 0xe4e5, 0x1703,
+ 0xe4eb, 0x23eb,
+ 0xe4ed, 0x170b,
+ 0xe4f2, 0x23ed,
+ 0xe4f3, 0x1711,
+ 0xe4fe, 0x23ee,
+ 0xe5a1, 0x171d,
+ 0xe5b0, 0x23ef,
+ 0xe5b1, 0x172d,
+ 0xe5b9, 0x23f0,
+ 0xe5ba, 0x1736,
+ 0xe5c7, 0x23f1,
+ 0xe5c8, 0x1744,
+ 0xe5c9, 0x23f2,
+ 0xe5ca, 0x1746,
+ 0xe5ce, 0x23f3,
+ 0xe5cf, 0x174b,
+ 0xe5f0, 0x23f4,
+ 0xe5f1, 0x176d,
+ 0xe5f2, 0x23f5,
+ 0xe5f3, 0x176f,
+ 0xe5fc, 0x23f6,
+ 0xe5fe, 0x177a,
+ 0xe6a1, 0x177b,
+ 0xe6a3, 0x23f8,
+ 0xe6a4, 0x177e,
+ 0xe6ab, 0x23f9,
+ 0xe6ad, 0x1787,
+ 0xe6ae, 0x23fb,
+ 0xe6af, 0x1789,
+ 0xe6b4, 0x23fc,
+ 0xe6b6, 0x1790,
+ 0xe6bf, 0x23fe,
+ 0xe6c0, 0x179a,
+ 0xe6c8, 0x23ff,
+ 0xe6ca, 0x17a4,
+ 0xe6cd, 0x2401,
+ 0xe6ce, 0x17a8,
+ 0xe6e0, 0x2402,
+ 0xe7a1, 0x2421,
+ 0xe7db, 0x1813,
+ 0xe7e1, 0x245b,
+ 0xe7e3, 0x181b,
+ 0xe7e7, 0x245d,
+ 0xe7e8, 0x1820,
+ 0xe7ef, 0x245e,
+ 0xe7f0, 0x1828,
+ 0xe7f4, 0x245f,
+ 0xe7f7, 0x182f,
+ 0xe8a1, 0x1837,
+ 0xe8a8, 0x2462,
+ 0xe8a9, 0x183f,
+ 0xe8ac, 0x2463,
+ 0xe8ad, 0x1843,
+ 0xe8b6, 0x2464,
+ 0xe8b7, 0x184d,
+ 0xe8b8, 0x2465,
+ 0xe8bb, 0x1851,
+ 0xe8bf, 0x2468,
+ 0xe8c1, 0x1857,
+ 0xe8c5, 0x246a,
+ 0xe8c6, 0x185c,
+ 0xe8c7, 0x246b,
+ 0xe8ca, 0x1860,
+ 0xe8ce, 0x246e,
+ 0xe8cf, 0x1865,
+ 0xe8d0, 0x246f,
+ 0xe8d1, 0x1867,
+ 0xe8d3, 0x2470,
+ 0xe8d4, 0x186a,
+ 0xe8dd, 0x2471,
+ 0xe8de, 0x1874,
+ 0xe8df, 0x2472,
+ 0xe8e0, 0x1876,
+ 0xe8e2, 0x2473,
+ 0xe8e4, 0x187a,
+ 0xe8e5, 0x2475,
+ 0xe8e6, 0x187c,
+ 0xe8e7, 0x2476,
+ 0xe8e8, 0x187e,
+ 0xe8eb, 0x2477,
+ 0xe8ec, 0x1882,
+ 0xe8ed, 0x2478,
+ 0xe8ee, 0x1884,
+ 0xe8ef, 0x2479,
+ 0xe8f0, 0x1886,
+ 0xe8f9, 0x247a,
+ 0xe8fa, 0x1890,
+ 0xe8fc, 0x247b,
+ 0xe8fe, 0x1894,
+ 0xe9a1, 0x247d,
+ 0xe9a2, 0x1896,
+ 0xe9ad, 0x247e,
+ 0xe9ae, 0x18a2,
+ 0xe9b4, 0x247f,
+ 0xe9b6, 0x18aa,
+ 0xe9b7, 0x2481,
+ 0xe9b8, 0x18ac,
+ 0xe9c4, 0x2482,
+ 0xe9c5, 0x18b9,
+ 0xe9c6, 0x2483,
+ 0xe9c7, 0x18bb,
+ 0xe9c9, 0x2484,
+ 0xe9ca, 0x18be,
+ 0xe9d6, 0x2485,
+ 0xe9d7, 0x18cb,
+ 0xe9da, 0x2486,
+ 0xe9db, 0x18cf,
+ 0xe9e4, 0x2487,
+ 0xe9e5, 0x18d9,
+ 0xe9e6, 0x2488,
+ 0xe9e8, 0x18dc,
+ 0xe9e9, 0x248a,
+ 0xe9ea, 0x18de,
+ 0xe9eb, 0x248b,
+ 0xe9ec, 0x18e0,
+ 0xe9ed, 0x248c,
+ 0xeaa1, 0x249e,
+ 0xeaa6, 0x18f8,
+ 0xeaa7, 0x24a3,
+ 0xeaa9, 0x18fb,
+ 0xeab1, 0x24a5,
+ 0xeab2, 0x1904,
+ 0xeabc, 0x24a6,
+ 0xeabd, 0x190f,
+ 0xeaca, 0x24a7,
+ 0xeacb, 0x191d,
+ 0xeacd, 0x24a8,
+ 0xeace, 0x1920,
+ 0xead3, 0x24a9,
+ 0xead4, 0x1926,
+ 0xeada, 0x24aa,
+ 0xeaf0, 0x1942,
+ 0xeba1, 0x1951,
+ 0xeba7, 0x24c0,
+ 0xeba8, 0x1958,
+ 0xebaa, 0x24c1,
+ 0xebab, 0x195b,
+ 0xebb2, 0x24c2,
+ 0xebb3, 0x1963,
+ 0xebb9, 0x24c3,
+ 0xebba, 0x196a,
+ 0xebca, 0x24c4,
+ 0xebcc, 0x197c,
+ 0xebcd, 0x24c6,
+ 0xebce, 0x197e,
+ 0xebd6, 0x24c7,
+ 0xebd7, 0x1987,
+ 0xebda, 0x24c8,
+ 0xebdb, 0x198b,
+ 0xebe1, 0x24c9,
+ 0xebe2, 0x1992,
+ 0xebf7, 0x24ca,
+ 0xebf8, 0x19a8,
+ 0xeca1, 0x19af,
+ 0xeca3, 0x24cb,
+ 0xeca4, 0x19b2,
+ 0xeca9, 0x24cc,
+ 0xecaf, 0x19bd,
+ 0xecb1, 0x24d2,
+ 0xecb2, 0x19c0,
+ 0xecb4, 0x24d3,
+ 0xecb6, 0x19c4,
+ 0xecbe, 0x24d5,
+ 0xecc0, 0x19ce,
+ 0xecc1, 0x24d7,
+ 0xecc2, 0x19d0,
+ 0xecc7, 0x24d8,
+ 0xecc8, 0x19d6,
+ 0xeccb, 0x24d9,
+ 0xeccc, 0x19da,
+ 0xece2, 0x24da,
+ 0xece3, 0x19f1,
+ 0xecf2, 0x24db,
+ 0xecf3, 0x1a01,
+ 0xecf5, 0x24dc,
+ 0xecf6, 0x1a04,
+ 0xecf8, 0x24dd,
+ 0xecf9, 0x1a07,
+ 0xeda1, 0x24de,
+ 0xeda2, 0x1a0e,
+ 0xeda8, 0x24df,
+ 0xeda9, 0x1a15,
+ 0xedaf, 0x24e0,
+ 0xedb1, 0x1a1d,
+ 0xedb4, 0x24e2,
+ 0xedb5, 0x1a21,
+ 0xedb6, 0x24e3,
+ 0xedb7, 0x1a23,
+ 0xedb8, 0x24e4,
+ 0xedb9, 0x1a25,
+ 0xedba, 0x24e5,
+ 0xedbb, 0x1a27,
+ 0xedbf, 0x24e6,
+ 0xedc0, 0x1a2c,
+ 0xedc2, 0x24e7,
+ 0xedc4, 0x1a30,
+ 0xedcc, 0x24e9,
+ 0xedce, 0x1a3a,
+ 0xedd3, 0x24eb,
+ 0xedd4, 0x1a40,
+ 0xedd7, 0x24ec,
+ 0xedd8, 0x1a44,
+ 0xede8, 0x24ed,
+ 0xede9, 0x1a55,
+ 0xedee, 0x24ee,
+ 0xedef, 0x1a5b,
+ 0xedf9, 0x24ef,
+ 0xedfb, 0x1a67,
+ 0xeea1, 0x1a6b,
+ 0xeebc, 0x24f1,
+ 0xeebd, 0x1a87,
+ 0xeebf, 0x24f2,
+ 0xeec0, 0x1a8a,
+ 0xeec4, 0x24f3,
+ 0xefa1, 0x252e,
+ 0xeff2, 0x1b1a,
+ 0xf0a1, 0x1b27,
+ 0xf0a3, 0x257f,
+ 0xf0a4, 0x1b2a,
+ 0xf0af, 0x2580,
+ 0xf0da, 0x1b60,
+ 0xf0dc, 0x25ab,
+ 0xf0de, 0x1b64,
+ 0xf0df, 0x25ad,
+ 0xf0e0, 0x1b66,
+ 0xf0e9, 0x25ae,
+ 0xf0ea, 0x1b70,
+ 0xf0ec, 0x25af,
+ 0xf0ed, 0x1b73,
+ 0xf0ef, 0x25b0,
+ 0xf0f0, 0x1b76,
+ 0xf0f7, 0x25b1,
+ 0xf0f8, 0x1b7e,
+ 0xf0f9, 0x25b2,
+ 0xf0fa, 0x1b80,
+ 0xf0fc, 0x25b3,
+ 0xf0fd, 0x1b83,
+ 0xf1a1, 0x1b85,
+ 0xf1a8, 0x25b4,
+ 0xf1a9, 0x1b8d,
+ 0xf1ab, 0x25b5,
+ 0xf1ac, 0x1b90,
+ 0xf1ae, 0x25b6,
+ 0xf1af, 0x1b93,
+ 0xf1b2, 0x25b7,
+ 0xf1b3, 0x1b97,
+ 0xf1bc, 0x25b8,
+ 0xf1bd, 0x1ba1,
+ 0xf1c0, 0x25b9,
+ 0xf1c1, 0x1ba5,
+ 0xf1c9, 0x25ba,
+ 0xf1ca, 0x1bae,
+ 0xf1cd, 0x25bb,
+ 0xf1ce, 0x1bb2,
+ 0xf1cf, 0x25bc,
+ 0xf1d1, 0x1bb5,
+ 0xf1da, 0x25be,
+ 0xf1db, 0x1bbf,
+ 0xf1dc, 0x25bf,
+ 0xf1dd, 0x1bc1,
+ 0xf1e4, 0x25c0,
+ 0xf1e5, 0x1bc9,
+ 0xf1ec, 0x25c1,
+ 0xf1ed, 0x1bd1,
+ 0xf1ef, 0x25c2,
+ 0xf1f0, 0x1bd4,
+ 0xf1f7, 0x25c3,
+ 0xf1f8, 0x1bdc,
+ 0xf1f9, 0x25c4,
+ 0xf1fa, 0x1bde,
+ 0xf1fc, 0x25c5,
+ 0xf2a1, 0x25c8,
+ 0xf2ae, 0x1bf0,
+ 0xf2b1, 0x25d5,
+ 0xf2b3, 0x1bf5,
+ 0xf2b9, 0x25d7,
+ 0xf2ba, 0x1bfc,
+ 0xf2c3, 0x25d8,
+ 0xf2c4, 0x1c06,
+ 0xf2c9, 0x25d9,
+ 0xf2ca, 0x1c0c,
+ 0xf2cc, 0x25da,
+ 0xf2ce, 0x1c10,
+ 0xf2cf, 0x25dc,
+ 0xf2d0, 0x1c12,
+ 0xf2d3, 0x25dd,
+ 0xf2d4, 0x1c16,
+ 0xf2e5, 0x25de,
+ 0xf2e6, 0x1c28,
+ 0xf2ee, 0x25df,
+ 0xf2ef, 0x1c31,
+ 0xf2f7, 0x25e0,
+ 0xf2f8, 0x1c3a,
+ 0xf2fd, 0x25e1,
+ 0xf2fe, 0x1c40,
+ 0xf3a1, 0x1c41,
+ 0xf3bf, 0x25e2,
+ 0xf3c0, 0x1c60,
+ 0xf3c6, 0x25e3,
+ 0xf3c7, 0x1c67,
+ 0xf3c8, 0x25e4,
+ 0xf3c9, 0x1c69,
+ 0xf3d6, 0x25e5,
+ 0xf3d7, 0x1c77,
+ 0xf3d9, 0x25e6,
+ 0xf3da, 0x1c7a,
+ 0xf3e5, 0x25e7,
+ 0xf3e7, 0x1c87,
+ 0xf3ea, 0x25e9,
+ 0xf3eb, 0x1c8b,
+ 0xf3ec, 0x25ea,
+ 0xf3ed, 0x1c8d,
+ 0xf3ef, 0x25eb,
+ 0xf3f0, 0x1c90,
+ 0xf3f1, 0x25ec,
+ 0xf3f2, 0x1c92,
+ 0xf3fd, 0x25ed,
+ 0xf3fe, 0x1c9e,
+ 0xf4a1, 0x1c9f,
+ 0xf4a5, 0x25ee,
+ 0xf4a6, 0x1ca4,
+ 0xf4af, 0x25ef,
+ 0xf4b0, 0x1cae,
+ 0xf4b5, 0x25f0,
+ 0xf4b6, 0x1cb4,
+ 0xf4c1, 0x25f1,
+ 0xf4c2, 0x1cc0,
+ 0xf4c7, 0x25f2,
+ 0xf4c8, 0x1cc6,
+ 0xf4cf, 0x25f3,
+ 0xf4d1, 0x1ccf,
+ 0xf4d6, 0x25f5,
+ 0xf4d7, 0x1cd5,
+ 0xf4ea, 0x25f6,
+ 0xf4eb, 0x1ce9,
+ 0xf4ef, 0x25f7,
+ 0xf4f0, 0x1cee,
+ 0xf4f5, 0x25f8,
+ 0xf4f6, 0x1cf4,
+ 0xf5a1, 0x1cfd,
+ 0xf5a6, 0x25f9,
+ 0xf5a8, 0x1d04,
+ 0xf5ba, 0x25fb,
+ 0xf5bc, 0x1d18,
+ 0xf5c4, 0x25fd,
+ 0xf5c5, 0x1d21,
+ 0xf5c8, 0x25fe,
+ 0xf5c9, 0x1d25,
+ 0xf5ce, 0x25ff,
+ 0xf5d0, 0x1d2c,
+ 0xf5d1, 0x2601,
+ 0xf5d3, 0x1d2f,
+ 0xf5d9, 0x2603,
+ 0xf5da, 0x1d36,
+ 0xf5dc, 0x2604,
+ 0xf5dd, 0x1d39,
+ 0xf5e6, 0x2605,
+ 0xf5e8, 0x1d44,
+ 0xf5ef, 0x2607,
+ 0xf5f0, 0x1d4c,
+ 0xf5f2, 0x2608,
+ 0xf5f3, 0x1d4f,
+ 0xf5fc, 0x2609,
+ 0xf5fd, 0x1d59,
+ 0xf6a1, 0x1d5b,
+ 0xf6a3, 0x260a,
+ 0xf6a4, 0x1d5e,
+ 0xf6a6, 0x260b,
+ 0xf6a7, 0x1d61,
+ 0xf6a8, 0x260c,
+ 0xf6a9, 0x1d63,
+ 0xf6ab, 0x260d,
+ 0xf6ac, 0x1d66,
+ 0xf6b0, 0x260e,
+ 0xf6b1, 0x1d6b,
+ 0xf6b3, 0x260f,
+ 0xf6bf, 0x1d79,
+ 0xf6c5, 0x261b,
+ 0xf6c6, 0x1d80,
+ 0xf6c7, 0x261c,
+ 0xf6c8, 0x1d82,
+ 0xf6c9, 0x261d,
+ 0xf6ca, 0x1d84,
+ 0xf6cf, 0x261e,
+ 0xf7a1, 0x264e,
+ 0xf7b0, 0x1dc8,
+ 0xf7b2, 0x265d,
+ 0xf7b4, 0x1dcc,
+ 0xf7b5, 0x265f,
+ 0xf7b6, 0x1dce,
+ 0xf7bd, 0x2660,
+ 0xf7be, 0x1dd6,
+ 0xf7c3, 0x2661,
+ 0xf7c4, 0x1ddc,
+ 0xf7c5, 0x2662,
+ 0xf7c7, 0x1ddf,
+ 0xf7ca, 0x2664,
+ 0xf7cc, 0x1de4,
+ 0xf7cf, 0x2666,
+ 0xf7d1, 0x1de9,
+ 0xf7de, 0x2668,
+ 0xf7df, 0x1df7,
+ 0xf7e1, 0x0ab9,
+ 0xf7e2, 0x1dfa,
+ 0xf7f2, 0x2669,
+ 0xf7f3, 0x1e0b,
+ 0xf7f5, 0x266a,
+ 0xf7f6, 0x1e0e,
+ 0xf8a1, 0x266b,
+ 0xf8a7, 0x04cc,
+ 0xf8a8, 0x050a,
+ 0xf8a9, 0x0518,
+ 0xf8aa, 0x2671,
+ 0xf8ac, 0x0594,
+ 0xf8ad, 0x05ce,
+ 0xf8ae, 0x2673,
+ 0xf8af, 0x05f6,
+ 0xf8b0, 0x2674,
+ 0xf8b2, 0x0653,
+ 0xf8b3, 0x067e,
+ 0xf8b4, 0x2676,
+ 0xf8b5, 0x06c4,
+ 0xf8b6, 0x2677,
+ 0xf8b8, 0x073c,
+ 0xf8b9, 0x2679,
+ 0xf8bb, 0x07c3,
+ 0xf8bc, 0x267b,
+ 0xf8c0, 0x082b,
+ 0xf8c1, 0x267f,
+ 0xf8c2, 0x084e,
+ 0xf8c3, 0x0869,
+ 0xf8c4, 0x2680,
+ 0xf8c6, 0x090c,
+ 0xf8c7, 0x2682,
+ 0xf8c9, 0x0971,
+ 0xf8ca, 0x2684,
+ 0xf8cb, 0x099a,
+ 0xf8cd, 0x2685,
+ 0xf8ce, 0x09da,
+ 0xf8cf, 0x2686,
+ 0xf8d0, 0x09fa,
+ 0xf8d1, 0x2687,
+ 0xf8dc, 0x0bda,
+ 0xf8dd, 0x0bdd,
+ 0xf8de, 0x0bea,
+ 0xf8df, 0x0bec,
+ 0xf8e0, 0x0bf2,
+ 0xf8e1, 0x2692,
+ 0xf8e6, 0x0c92,
+ 0xf8e7, 0x0d1a,
+ 0xf8e8, 0x0d8c,
+ 0xf8e9, 0x0dbe,
+ 0xf8ea, 0x2697,
+ 0xf8eb, 0x0dfb,
+ 0xf8ec, 0x2698,
+ 0xf8ef, 0x0e70,
+ 0xf8f0, 0x269b,
+ 0xf8f1, 0x0ea3,
+ 0xf8f2, 0x269c,
+ 0xf8f8, 0x103d,
+ 0xf8f9, 0x10d9,
+ 0xf8fa, 0x26a2,
+ 0xf8fc, 0x10fb,
+ 0xf8fd, 0x1109,
+ 0xf8fe, 0x26a4,
+ 0xf9a1, 0x11a1,
+ 0xf9a2, 0x26a5,
+ 0xf9a3, 0x11ba,
+ 0xf9a4, 0x26a6,
+ 0xf9a6, 0x11d5,
+ 0xf9a7, 0x26a8,
+ 0xf9a8, 0x11fd,
+ 0xf9a9, 0x1219,
+ 0xa1a2, 0x023f,
+ 0xa1a3, 0x023e,
+ 0xa1aa, 0x0256,
+ 0xa1ab, 0x1e18,
+ 0xa1ad, 0x0257,
+ 0xa1b2, 0x0246,
+ 0xa1fe, 0x1e1a,
+ 0xa3a1, 0x0242,
+ 0xa3a8, 0x0244,
+ 0xa3ac, 0x023d,
+ 0xa3ae, 0x1e1b,
+ 0xa3ba, 0x0240,
+ 0xa3bd, 0x1e1c,
+ 0xa3bf, 0x0243,
+ 0xa3db, 0x1e1d,
+ 0xa3dd, 0x1e1e,
+ 0xa3df, 0x0258,
+ 0xa3fb, 0x0254,
+ 0xa3fd, 0x0255,
+ 0xa3fe, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTEUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e24, 0x032e, 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0334,
+ 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033a, 0x033b, 0x033c,
+ 0x033d, 0x033e, 0x033f, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344,
+ 0x0345, 0x0346, 0x0347, 0x0348, 0x0349, 0x034a, 0x034b, 0x034c,
+ 0x034d, 0x034e, 0x034f, 0x0350, 0x0351, 0x0352, 0x0353, 0x0354,
+ 0x0355, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035c,
+ 0x035d, 0x035e, 0x035f, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364,
+ 0x0365, 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c,
+ 0x036d, 0x036e, 0x036f, 0x0370, 0x0371, 0x0372, 0x0373, 0x0374,
+ 0x0375, 0x0376, 0x0377, 0x0378, 0x0379, 0x037a, 0x037b, 0x037c,
+ 0x037d, 0x037e, 0x037f, 0x0380, 0x0381, 0x0382, 0x0383, 0x0384,
+ 0x0385, 0x0386, 0x0387, 0x0388, 0x0389, 0x038a, 0x038b, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBTEUCVMap2, 2303
+};
+
+static Gushort gb12GBTHMap2[4566] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0060,
+ 0x2231, 0x00be,
+ 0x2265, 0x00f0,
+ 0x2271, 0x00fa,
+ 0x2321, 0x0106,
+ 0x2421, 0x0164,
+ 0x2521, 0x01b7,
+ 0x2621, 0x020d,
+ 0x2641, 0x0225,
+ 0x2721, 0x025a,
+ 0x2751, 0x027b,
+ 0x2821, 0x029c,
+ 0x2845, 0x02bc,
+ 0x2924, 0x02e2,
+ 0x2a21, 0x032e,
+ 0x2b21, 0x038c,
+ 0x3021, 0x03ac,
+ 0x3028, 0x1e25,
+ 0x3029, 0x03b4,
+ 0x302a, 0x1e26,
+ 0x302b, 0x03b6,
+ 0x302d, 0x1e27,
+ 0x302f, 0x03ba,
+ 0x3039, 0x1e29,
+ 0x303a, 0x03c5,
+ 0x3040, 0x1e2a,
+ 0x3041, 0x03cc,
+ 0x3053, 0x1e2b,
+ 0x3054, 0x03df,
+ 0x3055, 0x1e2c,
+ 0x3056, 0x03e1,
+ 0x305a, 0x1e2d,
+ 0x305b, 0x03e6,
+ 0x305c, 0x1e2e,
+ 0x305d, 0x03e8,
+ 0x3064, 0x1e2f,
+ 0x3065, 0x03f0,
+ 0x306c, 0x1e30,
+ 0x306e, 0x03f9,
+ 0x306f, 0x1e32,
+ 0x3070, 0x03fb,
+ 0x3073, 0x1e33,
+ 0x3074, 0x03ff,
+ 0x3077, 0x1e34,
+ 0x3078, 0x0403,
+ 0x3079, 0x1e35,
+ 0x307a, 0x0405,
+ 0x3121, 0x040a,
+ 0x3125, 0x1e36,
+ 0x3127, 0x0410,
+ 0x3128, 0x1e38,
+ 0x3129, 0x0412,
+ 0x312b, 0x1e39,
+ 0x312c, 0x0415,
+ 0x3132, 0x1e3a,
+ 0x3133, 0x041c,
+ 0x3134, 0x1e3b,
+ 0x3136, 0x041f,
+ 0x3137, 0x1e3d,
+ 0x313a, 0x0423,
+ 0x3141, 0x1e40,
+ 0x3142, 0x042b,
+ 0x314a, 0x1e41,
+ 0x314b, 0x0434,
+ 0x314f, 0x1e42,
+ 0x3151, 0x043a,
+ 0x3152, 0x1e44,
+ 0x3153, 0x043c,
+ 0x3155, 0x1e45,
+ 0x3156, 0x043f,
+ 0x315f, 0x1e46,
+ 0x3162, 0x044b,
+ 0x3164, 0x1e49,
+ 0x3165, 0x044e,
+ 0x3167, 0x1e4a,
+ 0x3169, 0x0452,
+ 0x316a, 0x1e4c,
+ 0x316b, 0x0454,
+ 0x316e, 0x1e4d,
+ 0x316f, 0x0458,
+ 0x3171, 0x1e4e,
+ 0x3172, 0x045b,
+ 0x3174, 0x1e4f,
+ 0x3178, 0x0461,
+ 0x317d, 0x1e53,
+ 0x317e, 0x0467,
+ 0x3221, 0x0468,
+ 0x3226, 0x1e54,
+ 0x3228, 0x046f,
+ 0x322c, 0x1e56,
+ 0x322d, 0x0474,
+ 0x3235, 0x1e57,
+ 0x3236, 0x047d,
+ 0x3239, 0x1e58,
+ 0x323a, 0x0481,
+ 0x3246, 0x1e59,
+ 0x3247, 0x048e,
+ 0x324e, 0x1e5a,
+ 0x3258, 0x049f,
+ 0x325e, 0x1e64,
+ 0x325f, 0x04a6,
+ 0x3260, 0x1e65,
+ 0x3261, 0x04a8,
+ 0x3262, 0x1e66,
+ 0x3264, 0x04ab,
+ 0x326f, 0x1e68,
+ 0x3270, 0x04b7,
+ 0x3273, 0x1e69,
+ 0x327d, 0x04c4,
+ 0x3321, 0x1e73,
+ 0x3323, 0x04c8,
+ 0x3324, 0x1e75,
+ 0x3328, 0x04cd,
+ 0x3329, 0x1e79,
+ 0x332a, 0x04cf,
+ 0x332e, 0x1e7a,
+ 0x332f, 0x04d4,
+ 0x3335, 0x1e7b,
+ 0x3336, 0x04db,
+ 0x3339, 0x1e7c,
+ 0x333a, 0x04df,
+ 0x333e, 0x1e7d,
+ 0x333f, 0x04e4,
+ 0x3342, 0x1e7e,
+ 0x3343, 0x04e8,
+ 0x3344, 0x1e7f,
+ 0x3345, 0x04ea,
+ 0x3346, 0x1e80,
+ 0x3347, 0x04ec,
+ 0x334d, 0x1e81,
+ 0x334e, 0x04f3,
+ 0x334f, 0x1e82,
+ 0x3350, 0x04f5,
+ 0x3352, 0x1e83,
+ 0x3353, 0x04f8,
+ 0x3359, 0x1e84,
+ 0x335a, 0x04ff,
+ 0x335b, 0x1e85,
+ 0x335c, 0x0501,
+ 0x335d, 0x1e86,
+ 0x335e, 0x0503,
+ 0x3363, 0x1e87,
+ 0x3364, 0x0509,
+ 0x3365, 0x1e88,
+ 0x3367, 0x050c,
+ 0x3368, 0x1e8a,
+ 0x3369, 0x050e,
+ 0x336b, 0x1e8b,
+ 0x336d, 0x0512,
+ 0x336f, 0x1e8d,
+ 0x3370, 0x0515,
+ 0x3371, 0x1e8e,
+ 0x3372, 0x0517,
+ 0x3373, 0x1e8f,
+ 0x3374, 0x0519,
+ 0x337a, 0x1e90,
+ 0x337c, 0x0521,
+ 0x3421, 0x1e92,
+ 0x3423, 0x0526,
+ 0x3425, 0x1e94,
+ 0x3427, 0x052a,
+ 0x342b, 0x1e96,
+ 0x342c, 0x052f,
+ 0x342f, 0x1e97,
+ 0x3430, 0x0533,
+ 0x3433, 0x1e98,
+ 0x3435, 0x0538,
+ 0x3438, 0x1e9a,
+ 0x3439, 0x053c,
+ 0x343f, 0x1e9b,
+ 0x3440, 0x0543,
+ 0x3442, 0x1e9c,
+ 0x3443, 0x0546,
+ 0x3447, 0x1e9d,
+ 0x3448, 0x054b,
+ 0x344a, 0x1e9e,
+ 0x344b, 0x054e,
+ 0x344d, 0x1e9f,
+ 0x344e, 0x0551,
+ 0x344f, 0x1ea0,
+ 0x3450, 0x0553,
+ 0x3453, 0x1ea1,
+ 0x3455, 0x0558,
+ 0x345a, 0x1ea3,
+ 0x345b, 0x055e,
+ 0x345c, 0x1ea4,
+ 0x345d, 0x0560,
+ 0x346d, 0x1ea5,
+ 0x346e, 0x0571,
+ 0x346f, 0x1ea6,
+ 0x3470, 0x0573,
+ 0x3478, 0x1ea7,
+ 0x3479, 0x057c,
+ 0x347b, 0x1ea8,
+ 0x347c, 0x057f,
+ 0x3521, 0x0582,
+ 0x3523, 0x1ea9,
+ 0x3524, 0x0585,
+ 0x3525, 0x1eaa,
+ 0x3529, 0x058a,
+ 0x352c, 0x1eae,
+ 0x352d, 0x058e,
+ 0x352e, 0x1eaf,
+ 0x3530, 0x0591,
+ 0x3531, 0x1eb1,
+ 0x3536, 0x0597,
+ 0x3537, 0x1eb6,
+ 0x3538, 0x0599,
+ 0x353a, 0x1eb7,
+ 0x353d, 0x059e,
+ 0x3546, 0x1eba,
+ 0x3547, 0x05a8,
+ 0x354b, 0x1ebb,
+ 0x354c, 0x05ad,
+ 0x3550, 0x1ebc,
+ 0x3551, 0x05b2,
+ 0x3553, 0x1ebd,
+ 0x3554, 0x05b5,
+ 0x355d, 0x1ebe,
+ 0x3560, 0x05c1,
+ 0x3563, 0x1ec1,
+ 0x3564, 0x05c5,
+ 0x3566, 0x1ec2,
+ 0x3568, 0x05c9,
+ 0x356d, 0x1ec4,
+ 0x356e, 0x05cf,
+ 0x3576, 0x1ec5,
+ 0x3578, 0x05d9,
+ 0x357d, 0x1ec7,
+ 0x357e, 0x05df,
+ 0x3621, 0x05e0,
+ 0x3624, 0x1ec8,
+ 0x3626, 0x05e5,
+ 0x3627, 0x1eca,
+ 0x3628, 0x05e7,
+ 0x3629, 0x1ecb,
+ 0x362a, 0x05e9,
+ 0x362b, 0x1ecc,
+ 0x362c, 0x05eb,
+ 0x362f, 0x1ecd,
+ 0x3631, 0x05f0,
+ 0x3633, 0x1ecf,
+ 0x3634, 0x05f3,
+ 0x3637, 0x1ed0,
+ 0x3638, 0x05f7,
+ 0x363f, 0x1ed1,
+ 0x3642, 0x0601,
+ 0x3644, 0x1ed4,
+ 0x3645, 0x0604,
+ 0x3646, 0x1ed5,
+ 0x3647, 0x0606,
+ 0x364d, 0x1ed6,
+ 0x364e, 0x060d,
+ 0x364f, 0x1ed7,
+ 0x3651, 0x0610,
+ 0x3653, 0x1ed9,
+ 0x3655, 0x0614,
+ 0x3656, 0x1edb,
+ 0x3657, 0x0616,
+ 0x3659, 0x1edc,
+ 0x365a, 0x0619,
+ 0x365b, 0x1edd,
+ 0x365c, 0x061b,
+ 0x3661, 0x1ede,
+ 0x3662, 0x0621,
+ 0x3669, 0x1edf,
+ 0x366a, 0x0629,
+ 0x366c, 0x1ee0,
+ 0x366d, 0x062c,
+ 0x366e, 0x1ee1,
+ 0x3670, 0x062f,
+ 0x3671, 0x1ee3,
+ 0x3672, 0x0631,
+ 0x3676, 0x1ee4,
+ 0x3677, 0x0636,
+ 0x3679, 0x1ee5,
+ 0x367a, 0x0639,
+ 0x367b, 0x1ee6,
+ 0x367d, 0x063c,
+ 0x3721, 0x1ee8,
+ 0x3724, 0x0641,
+ 0x3727, 0x1eeb,
+ 0x3728, 0x0645,
+ 0x372f, 0x1eec,
+ 0x3731, 0x064e,
+ 0x3733, 0x1eee,
+ 0x3734, 0x0651,
+ 0x3736, 0x1eef,
+ 0x3738, 0x0655,
+ 0x3739, 0x1ef1,
+ 0x373a, 0x0657,
+ 0x3743, 0x1ef2,
+ 0x3745, 0x0662,
+ 0x3749, 0x1ef4,
+ 0x374a, 0x0667,
+ 0x374c, 0x1ef5,
+ 0x374d, 0x066a,
+ 0x374f, 0x1ef6,
+ 0x3750, 0x066d,
+ 0x3751, 0x1ef7,
+ 0x3752, 0x066f,
+ 0x3757, 0x1ef8,
+ 0x3759, 0x0676,
+ 0x375c, 0x1efa,
+ 0x375d, 0x067a,
+ 0x375f, 0x1efb,
+ 0x3762, 0x067f,
+ 0x3763, 0x1efe,
+ 0x3764, 0x0681,
+ 0x3766, 0x1eff,
+ 0x3769, 0x0686,
+ 0x376b, 0x1f02,
+ 0x376e, 0x068b,
+ 0x376f, 0x1f05,
+ 0x3770, 0x068d,
+ 0x3774, 0x1f06,
+ 0x3775, 0x0692,
+ 0x3778, 0x1f07,
+ 0x3779, 0x0696,
+ 0x3821, 0x069c,
+ 0x3827, 0x1f08,
+ 0x3829, 0x06a4,
+ 0x3833, 0x1f0a,
+ 0x3835, 0x06b0,
+ 0x383a, 0x1f0c,
+ 0x383b, 0x06b6,
+ 0x383c, 0x1f0d,
+ 0x383d, 0x06b8,
+ 0x383e, 0x1f0e,
+ 0x3840, 0x06bb,
+ 0x3843, 0x1f10,
+ 0x3844, 0x06bf,
+ 0x3846, 0x1f11,
+ 0x3848, 0x06c3,
+ 0x3849, 0x1f13,
+ 0x384a, 0x06c5,
+ 0x384f, 0x1f14,
+ 0x3850, 0x06cb,
+ 0x3853, 0x1f15,
+ 0x3857, 0x06d2,
+ 0x3859, 0x1f19,
+ 0x385b, 0x06d6,
+ 0x3864, 0x1f1b,
+ 0x3865, 0x06e0,
+ 0x3869, 0x1f1c,
+ 0x386a, 0x06e5,
+ 0x386b, 0x1f1d,
+ 0x386c, 0x06e7,
+ 0x3873, 0x1f1e,
+ 0x3874, 0x06ef,
+ 0x3875, 0x1f1f,
+ 0x3877, 0x06f2,
+ 0x3878, 0x1f21,
+ 0x3879, 0x06f4,
+ 0x3921, 0x06fa,
+ 0x3928, 0x1f22,
+ 0x3929, 0x0702,
+ 0x392e, 0x1f23,
+ 0x392f, 0x0708,
+ 0x3931, 0x1f24,
+ 0x3932, 0x070b,
+ 0x3933, 0x1f25,
+ 0x3934, 0x070d,
+ 0x3935, 0x1f26,
+ 0x3936, 0x070f,
+ 0x3939, 0x1f27,
+ 0x393b, 0x0714,
+ 0x3946, 0x1f29,
+ 0x3947, 0x0720,
+ 0x394b, 0x1f2a,
+ 0x394c, 0x0725,
+ 0x3950, 0x1f2b,
+ 0x3951, 0x072a,
+ 0x3958, 0x1f2c,
+ 0x3959, 0x0732,
+ 0x395b, 0x1f2d,
+ 0x395c, 0x0735,
+ 0x395d, 0x1f2e,
+ 0x395e, 0x0737,
+ 0x395f, 0x1f2f,
+ 0x3960, 0x0739,
+ 0x3961, 0x1f30,
+ 0x3962, 0x073b,
+ 0x3963, 0x1f31,
+ 0x3964, 0x073d,
+ 0x3966, 0x1f32,
+ 0x3967, 0x0740,
+ 0x3969, 0x1f33,
+ 0x396d, 0x0746,
+ 0x396e, 0x1f37,
+ 0x396f, 0x0748,
+ 0x3971, 0x1f38,
+ 0x3972, 0x074b,
+ 0x3973, 0x1f39,
+ 0x3976, 0x074f,
+ 0x3978, 0x1f3c,
+ 0x3979, 0x0752,
+ 0x397a, 0x1f3d,
+ 0x397b, 0x0754,
+ 0x397d, 0x1f3e,
+ 0x397e, 0x0757,
+ 0x3a21, 0x0758,
+ 0x3a27, 0x1f3f,
+ 0x3a28, 0x075f,
+ 0x3a2b, 0x1f40,
+ 0x3a2c, 0x0763,
+ 0x3a3a, 0x1f41,
+ 0x3a3b, 0x0772,
+ 0x3a45, 0x1f42,
+ 0x3a46, 0x077d,
+ 0x3a52, 0x1f43,
+ 0x3a53, 0x078a,
+ 0x3a57, 0x1f44,
+ 0x3a59, 0x0790,
+ 0x3a64, 0x1f46,
+ 0x3a65, 0x079c,
+ 0x3a68, 0x1f47,
+ 0x3a69, 0x07a0,
+ 0x3a6c, 0x1f48,
+ 0x3a6d, 0x07a4,
+ 0x3a73, 0x15e5,
+ 0x3a74, 0x07ab,
+ 0x3a78, 0x1f49,
+ 0x3a79, 0x07b0,
+ 0x3b21, 0x07b6,
+ 0x3b24, 0x1f4a,
+ 0x3b25, 0x07ba,
+ 0x3b26, 0x1f4b,
+ 0x3b27, 0x07bc,
+ 0x3b29, 0x1f4c,
+ 0x3b2b, 0x07c0,
+ 0x3b2d, 0x1f4e,
+ 0x3b2f, 0x07c4,
+ 0x3b30, 0x1f50,
+ 0x3b31, 0x07c6,
+ 0x3b33, 0x1f51,
+ 0x3b34, 0x07c9,
+ 0x3b35, 0x1f52,
+ 0x3b38, 0x07cd,
+ 0x3b39, 0x1f55,
+ 0x3b3b, 0x07d0,
+ 0x3b51, 0x1f57,
+ 0x3b52, 0x07e7,
+ 0x3b53, 0x1f58,
+ 0x3b55, 0x07ea,
+ 0x3b5f, 0x1f5a,
+ 0x3b68, 0x07fd,
+ 0x3b6b, 0x1f63,
+ 0x3b6c, 0x0801,
+ 0x3b71, 0x1f64,
+ 0x3b72, 0x0807,
+ 0x3b75, 0x1f65,
+ 0x3b78, 0x080d,
+ 0x3b7a, 0x1f68,
+ 0x3b7b, 0x0810,
+ 0x3b7d, 0x1f69,
+ 0x3b7e, 0x0813,
+ 0x3c21, 0x0814,
+ 0x3c22, 0x1f6a,
+ 0x3c23, 0x0816,
+ 0x3c25, 0x1f6b,
+ 0x3c27, 0x081a,
+ 0x3c28, 0x1f6d,
+ 0x3c2a, 0x081d,
+ 0x3c2b, 0x1f6f,
+ 0x3c2c, 0x081f,
+ 0x3c2d, 0x1f70,
+ 0x3c2e, 0x0821,
+ 0x3c36, 0x1f71,
+ 0x3c39, 0x082c,
+ 0x3c3b, 0x1f74,
+ 0x3c3c, 0x082f,
+ 0x3c41, 0x1f75,
+ 0x3c42, 0x0835,
+ 0x3c43, 0x1f76,
+ 0x3c44, 0x0837,
+ 0x3c46, 0x1f77,
+ 0x3c48, 0x083b,
+ 0x3c4a, 0x1f79,
+ 0x3c4b, 0x083e,
+ 0x3c4c, 0x1f7a,
+ 0x3c4e, 0x0841,
+ 0x3c50, 0x1f7c,
+ 0x3c51, 0x0844,
+ 0x3c54, 0x1f7d,
+ 0x3c57, 0x084a,
+ 0x3c58, 0x1f80,
+ 0x3c59, 0x084c,
+ 0x3c5b, 0x1f81,
+ 0x3c5c, 0x084f,
+ 0x3c5d, 0x1f82,
+ 0x3c5e, 0x0851,
+ 0x3c5f, 0x1f83,
+ 0x3c62, 0x0855,
+ 0x3c63, 0x1f86,
+ 0x3c65, 0x0858,
+ 0x3c68, 0x1f88,
+ 0x3c69, 0x085c,
+ 0x3c6a, 0x1f89,
+ 0x3c6d, 0x0860,
+ 0x3c6f, 0x1f8c,
+ 0x3c74, 0x0867,
+ 0x3c76, 0x1f91,
+ 0x3c7d, 0x0870,
+ 0x3d21, 0x0872,
+ 0x3d22, 0x1f98,
+ 0x3d28, 0x0879,
+ 0x3d2b, 0x1f9e,
+ 0x3d2d, 0x087e,
+ 0x3d2f, 0x1fa0,
+ 0x3d33, 0x0884,
+ 0x3d34, 0x1fa4,
+ 0x3d35, 0x0886,
+ 0x3d3a, 0x1fa5,
+ 0x3d3b, 0x088c,
+ 0x3d3d, 0x1fa6,
+ 0x3d40, 0x0891,
+ 0x3d41, 0x1fa9,
+ 0x3d45, 0x0896,
+ 0x3d48, 0x1fad,
+ 0x3d4b, 0x089c,
+ 0x3d4e, 0x1fb0,
+ 0x3d50, 0x08a1,
+ 0x3d57, 0x1fb2,
+ 0x3d58, 0x08a9,
+ 0x3d5a, 0x1fb3,
+ 0x3d5b, 0x08ac,
+ 0x3d60, 0x1fb4,
+ 0x3d62, 0x08b3,
+ 0x3d6b, 0x1fb6,
+ 0x3d6c, 0x08bd,
+ 0x3d74, 0x1fb7,
+ 0x3d79, 0x08ca,
+ 0x3d7d, 0x1fbc,
+ 0x3d7e, 0x08cf,
+ 0x3e21, 0x1fbd,
+ 0x3e23, 0x08d2,
+ 0x3e25, 0x1fbf,
+ 0x3e26, 0x08d5,
+ 0x3e28, 0x1fc0,
+ 0x3e29, 0x08d8,
+ 0x3e2a, 0x1fc1,
+ 0x3e2b, 0x08da,
+ 0x3e2d, 0x1fc2,
+ 0x3e2e, 0x08dd,
+ 0x3e31, 0x1fc3,
+ 0x3e32, 0x08e1,
+ 0x3e35, 0x1fc4,
+ 0x3e38, 0x08e7,
+ 0x3e3a, 0x1fc7,
+ 0x3e3b, 0x08ea,
+ 0x3e40, 0x1fc8,
+ 0x3e41, 0x08f0,
+ 0x3e49, 0x1fc9,
+ 0x3e4a, 0x08f9,
+ 0x3e54, 0x1fca,
+ 0x3e55, 0x0904,
+ 0x3e59, 0x1fcb,
+ 0x3e5a, 0x0909,
+ 0x3e5d, 0x1fcc,
+ 0x3e5e, 0x090d,
+ 0x3e62, 0x1fcd,
+ 0x3e63, 0x0912,
+ 0x3e65, 0x1fce,
+ 0x3e66, 0x0915,
+ 0x3e67, 0x1fcf,
+ 0x3e68, 0x0917,
+ 0x3e69, 0x1fd0,
+ 0x3e6a, 0x0919,
+ 0x3e6e, 0x1fd1,
+ 0x3e6f, 0x091e,
+ 0x3e75, 0x1fd2,
+ 0x3e76, 0x0925,
+ 0x3e77, 0x1fd3,
+ 0x3e79, 0x0928,
+ 0x3e7b, 0x1fd5,
+ 0x3e7d, 0x092c,
+ 0x3f21, 0x092e,
+ 0x3f25, 0x1fd7,
+ 0x3f26, 0x0933,
+ 0x3f2a, 0x1fd8,
+ 0x3f2b, 0x0938,
+ 0x3f2d, 0x1fd9,
+ 0x3f2e, 0x093b,
+ 0x3f45, 0x1fda,
+ 0x3f46, 0x0953,
+ 0x3f47, 0x1fdb,
+ 0x3f48, 0x0955,
+ 0x3f4e, 0x1fdc,
+ 0x3f4f, 0x095c,
+ 0x3f51, 0x1fdd,
+ 0x3f53, 0x0960,
+ 0x3f59, 0x1fdf,
+ 0x3f5a, 0x0967,
+ 0x3f62, 0x1fe0,
+ 0x3f65, 0x0972,
+ 0x3f69, 0x1fe3,
+ 0x3f6a, 0x0977,
+ 0x3f6b, 0x1fe4,
+ 0x3f6c, 0x0979,
+ 0x3f6d, 0x1fe5,
+ 0x3f6e, 0x097b,
+ 0x3f73, 0x1fe6,
+ 0x3f74, 0x0981,
+ 0x3f75, 0x1fe7,
+ 0x3f76, 0x0983,
+ 0x3f77, 0x1fe8,
+ 0x3f78, 0x0985,
+ 0x3f79, 0x1fe9,
+ 0x3f7b, 0x0988,
+ 0x4021, 0x1feb,
+ 0x4022, 0x098d,
+ 0x4023, 0x1fec,
+ 0x4024, 0x098f,
+ 0x4029, 0x1fed,
+ 0x402a, 0x0995,
+ 0x402b, 0x1fee,
+ 0x402c, 0x0997,
+ 0x402f, 0x1fef,
+ 0x4031, 0x099c,
+ 0x4033, 0x1ff1,
+ 0x4037, 0x09a2,
+ 0x4038, 0x1ff5,
+ 0x4045, 0x09b0,
+ 0x404c, 0x2002,
+ 0x404e, 0x09b9,
+ 0x4054, 0x2004,
+ 0x4055, 0x09c0,
+ 0x4056, 0x2005,
+ 0x4057, 0x09c2,
+ 0x4058, 0x2006,
+ 0x4059, 0x09c4,
+ 0x405d, 0x2007,
+ 0x405e, 0x09c9,
+ 0x4060, 0x2008,
+ 0x4061, 0x09cc,
+ 0x4069, 0x2009,
+ 0x406a, 0x09d5,
+ 0x406b, 0x200a,
+ 0x406d, 0x09d8,
+ 0x406f, 0x200c,
+ 0x4072, 0x09dd,
+ 0x4076, 0x200f,
+ 0x407b, 0x09e6,
+ 0x4121, 0x09ea,
+ 0x4124, 0x2014,
+ 0x4126, 0x09ef,
+ 0x4129, 0x2016,
+ 0x412e, 0x09f7,
+ 0x412f, 0x201b,
+ 0x4139, 0x0a02,
+ 0x413d, 0x2025,
+ 0x413f, 0x0a08,
+ 0x4142, 0x2027,
+ 0x4143, 0x0a0c,
+ 0x4146, 0x2028,
+ 0x4147, 0x0a10,
+ 0x4149, 0x2029,
+ 0x414a, 0x0a13,
+ 0x414d, 0x202a,
+ 0x414e, 0x0a17,
+ 0x4154, 0x202b,
+ 0x4155, 0x0a1e,
+ 0x4159, 0x202c,
+ 0x415c, 0x0a25,
+ 0x415e, 0x202f,
+ 0x415f, 0x0a28,
+ 0x4164, 0x2030,
+ 0x4166, 0x0a2f,
+ 0x4169, 0x2032,
+ 0x416a, 0x0a33,
+ 0x416b, 0x2033,
+ 0x416d, 0x0a36,
+ 0x4173, 0x2035,
+ 0x4174, 0x0a3d,
+ 0x4175, 0x2036,
+ 0x4176, 0x0a3f,
+ 0x417a, 0x2037,
+ 0x417e, 0x0a47,
+ 0x4221, 0x0a48,
+ 0x4222, 0x203b,
+ 0x4229, 0x0a50,
+ 0x422b, 0x2042,
+ 0x4234, 0x0a5b,
+ 0x4238, 0x204b,
+ 0x4239, 0x0a60,
+ 0x423c, 0x204c,
+ 0x423e, 0x0a65,
+ 0x423f, 0x204e,
+ 0x4240, 0x0a67,
+ 0x4241, 0x204f,
+ 0x4242, 0x0a69,
+ 0x4245, 0x2050,
+ 0x4248, 0x0a6f,
+ 0x424b, 0x2053,
+ 0x4251, 0x0a78,
+ 0x4252, 0x2059,
+ 0x4253, 0x0a7a,
+ 0x4255, 0x205a,
+ 0x425d, 0x0a84,
+ 0x425e, 0x2062,
+ 0x4263, 0x0a8a,
+ 0x4266, 0x2067,
+ 0x4269, 0x0a90,
+ 0x426a, 0x206a,
+ 0x426f, 0x0a96,
+ 0x4270, 0x206f,
+ 0x4271, 0x0a98,
+ 0x4272, 0x2070,
+ 0x4276, 0x0a9d,
+ 0x4277, 0x2074,
+ 0x427b, 0x0aa2,
+ 0x4321, 0x2078,
+ 0x4322, 0x0aa7,
+ 0x432a, 0x2079,
+ 0x432b, 0x0ab0,
+ 0x432d, 0x207a,
+ 0x432e, 0x0ab3,
+ 0x4333, 0x207b,
+ 0x4334, 0x1df9,
+ 0x4335, 0x0aba,
+ 0x433e, 0x207c,
+ 0x433f, 0x0ac4,
+ 0x4345, 0x207d,
+ 0x4348, 0x0acd,
+ 0x434c, 0x2080,
+ 0x434d, 0x0ad2,
+ 0x434e, 0x2081,
+ 0x434f, 0x0ad4,
+ 0x4355, 0x2082,
+ 0x4357, 0x0adc,
+ 0x4359, 0x2084,
+ 0x435a, 0x0adf,
+ 0x4360, 0x2085,
+ 0x4361, 0x0ae6,
+ 0x4365, 0x2086,
+ 0x4366, 0x0aeb,
+ 0x436d, 0x2087,
+ 0x436e, 0x0af3,
+ 0x4370, 0x2088,
+ 0x4371, 0x0af6,
+ 0x4375, 0x2089,
+ 0x4377, 0x0afc,
+ 0x4379, 0x208b,
+ 0x437b, 0x0b00,
+ 0x437d, 0x208d,
+ 0x437e, 0x0b03,
+ 0x4421, 0x0b04,
+ 0x4431, 0x208e,
+ 0x4432, 0x0b15,
+ 0x4436, 0x208f,
+ 0x4437, 0x0b1a,
+ 0x4446, 0x2090,
+ 0x4447, 0x0b2a,
+ 0x4449, 0x2091,
+ 0x444a, 0x0b2d,
+ 0x4451, 0x2092,
+ 0x4452, 0x0b35,
+ 0x4453, 0x2093,
+ 0x4457, 0x0b3a,
+ 0x4459, 0x2097,
+ 0x445a, 0x0b3d,
+ 0x4462, 0x2098,
+ 0x4463, 0x0b46,
+ 0x4465, 0x2099,
+ 0x4466, 0x0b49,
+ 0x446c, 0x209a,
+ 0x446d, 0x0b50,
+ 0x4470, 0x209b,
+ 0x4472, 0x0b55,
+ 0x4474, 0x209d,
+ 0x4475, 0x0b58,
+ 0x4476, 0x209e,
+ 0x4479, 0x0b5c,
+ 0x447b, 0x20a1,
+ 0x447d, 0x0b60,
+ 0x447e, 0x20a3,
+ 0x4521, 0x20a4,
+ 0x4523, 0x0b64,
+ 0x4525, 0x20a6,
+ 0x452a, 0x0b6b,
+ 0x4531, 0x20ab,
+ 0x4532, 0x0b73,
+ 0x4535, 0x20ac,
+ 0x4536, 0x0b77,
+ 0x4537, 0x20ad,
+ 0x453a, 0x0b7b,
+ 0x453b, 0x20b0,
+ 0x453c, 0x0b7d,
+ 0x453d, 0x20b1,
+ 0x453e, 0x0b7f,
+ 0x454c, 0x20b2,
+ 0x454d, 0x0b8e,
+ 0x4553, 0x20b3,
+ 0x4554, 0x0b95,
+ 0x4562, 0x20b4,
+ 0x4563, 0x0ba4,
+ 0x4567, 0x20b5,
+ 0x4568, 0x0ba9,
+ 0x4574, 0x20b6,
+ 0x4575, 0x0bb6,
+ 0x4621, 0x0bc0,
+ 0x462d, 0x20b7,
+ 0x462f, 0x0bce,
+ 0x4635, 0x20b9,
+ 0x4637, 0x0bd6,
+ 0x463b, 0x20bb,
+ 0x463c, 0x0bdb,
+ 0x463e, 0x20bc,
+ 0x463f, 0x0bde,
+ 0x4640, 0x20bd,
+ 0x4641, 0x0be0,
+ 0x4643, 0x20be,
+ 0x4645, 0x0be4,
+ 0x464b, 0x20c0,
+ 0x464e, 0x0bed,
+ 0x4653, 0x20c3,
+ 0x4654, 0x0bf3,
+ 0x4657, 0x20c4,
+ 0x4658, 0x0bf7,
+ 0x466a, 0x20c5,
+ 0x466c, 0x0c0b,
+ 0x466f, 0x20c7,
+ 0x4670, 0x0c0f,
+ 0x4671, 0x20c8,
+ 0x4672, 0x0c11,
+ 0x4674, 0x20c9,
+ 0x4675, 0x0c14,
+ 0x4678, 0x20ca,
+ 0x4679, 0x0c18,
+ 0x467d, 0x20cb,
+ 0x467e, 0x0c1d,
+ 0x4721, 0x0c1e,
+ 0x4723, 0x20cc,
+ 0x4724, 0x0c21,
+ 0x4725, 0x20cd,
+ 0x4727, 0x0c24,
+ 0x4728, 0x20cf,
+ 0x472a, 0x0c27,
+ 0x472b, 0x20d1,
+ 0x472c, 0x0c29,
+ 0x472e, 0x20d2,
+ 0x4730, 0x0c2d,
+ 0x4733, 0x20d4,
+ 0x4736, 0x0c33,
+ 0x4739, 0x20d7,
+ 0x473b, 0x0c38,
+ 0x473d, 0x20d9,
+ 0x473f, 0x0c3c,
+ 0x4740, 0x20db,
+ 0x4741, 0x0c3e,
+ 0x4742, 0x20dc,
+ 0x4743, 0x0c40,
+ 0x4745, 0x20dd,
+ 0x4746, 0x0c43,
+ 0x4747, 0x20de,
+ 0x4749, 0x0c46,
+ 0x474c, 0x20e0,
+ 0x474d, 0x0c4a,
+ 0x474f, 0x20e1,
+ 0x4750, 0x0c4d,
+ 0x4754, 0x20e2,
+ 0x4756, 0x0c53,
+ 0x4757, 0x20e4,
+ 0x4758, 0x0c55,
+ 0x475e, 0x20e5,
+ 0x475f, 0x0c5c,
+ 0x4761, 0x20e6,
+ 0x4764, 0x0c61,
+ 0x476a, 0x20e9,
+ 0x476f, 0x0c6c,
+ 0x4777, 0x20ee,
+ 0x4779, 0x0c76,
+ 0x477b, 0x20f0,
+ 0x477c, 0x0c79,
+ 0x477d, 0x20f1,
+ 0x477e, 0x0c7b,
+ 0x4821, 0x0c7c,
+ 0x4823, 0x20f2,
+ 0x4824, 0x0c7f,
+ 0x4827, 0x20f3,
+ 0x4829, 0x0c84,
+ 0x4830, 0x20f5,
+ 0x4831, 0x0c8c,
+ 0x4835, 0x20f6,
+ 0x4836, 0x0c91,
+ 0x4837, 0x20f7,
+ 0x4838, 0x0c93,
+ 0x4843, 0x20f8,
+ 0x4847, 0x0ca2,
+ 0x4848, 0x20fc,
+ 0x4849, 0x0ca4,
+ 0x484d, 0x20fd,
+ 0x484e, 0x0ca9,
+ 0x484f, 0x20fe,
+ 0x4850, 0x0cab,
+ 0x4852, 0x20ff,
+ 0x4853, 0x0cae,
+ 0x4859, 0x2100,
+ 0x485a, 0x0cb5,
+ 0x485e, 0x2101,
+ 0x485f, 0x0cba,
+ 0x486d, 0x2102,
+ 0x486e, 0x0cc9,
+ 0x4871, 0x2103,
+ 0x4874, 0x0ccf,
+ 0x4877, 0x2106,
+ 0x4879, 0x0cd4,
+ 0x487a, 0x2108,
+ 0x487b, 0x0cd6,
+ 0x487c, 0x2109,
+ 0x487d, 0x0cd8,
+ 0x4921, 0x210a,
+ 0x4922, 0x0cdb,
+ 0x4925, 0x210b,
+ 0x4926, 0x0cdf,
+ 0x4927, 0x210c,
+ 0x4929, 0x0ce2,
+ 0x492c, 0x210e,
+ 0x492d, 0x0ce6,
+ 0x4931, 0x210f,
+ 0x4932, 0x0ceb,
+ 0x4934, 0x2110,
+ 0x4935, 0x0cee,
+ 0x4938, 0x2111,
+ 0x493a, 0x0cf3,
+ 0x4941, 0x2113,
+ 0x4943, 0x0cfc,
+ 0x4944, 0x2115,
+ 0x4945, 0x0cfe,
+ 0x4949, 0x2116,
+ 0x494a, 0x0d03,
+ 0x494b, 0x2117,
+ 0x494c, 0x0d05,
+ 0x494d, 0x2118,
+ 0x494e, 0x0d07,
+ 0x4955, 0x2119,
+ 0x4956, 0x0d0f,
+ 0x495c, 0x211a,
+ 0x495d, 0x0d16,
+ 0x495e, 0x211b,
+ 0x495f, 0x0d18,
+ 0x4961, 0x211c,
+ 0x4962, 0x0d1b,
+ 0x4963, 0x211d,
+ 0x4964, 0x0d1d,
+ 0x4965, 0x211e,
+ 0x4966, 0x0d1f,
+ 0x4968, 0x211f,
+ 0x4969, 0x0d22,
+ 0x4970, 0x2120,
+ 0x4971, 0x0d2a,
+ 0x4973, 0x2121,
+ 0x4975, 0x0d2e,
+ 0x4976, 0x2123,
+ 0x4977, 0x0d30,
+ 0x4978, 0x2124,
+ 0x497a, 0x0d33,
+ 0x497e, 0x2126,
+ 0x4a21, 0x0d38,
+ 0x4a24, 0x2127,
+ 0x4a27, 0x0d3e,
+ 0x4a28, 0x212a,
+ 0x4a29, 0x0d40,
+ 0x4a2a, 0x212b,
+ 0x4a2c, 0x0d43,
+ 0x4a31, 0x212d,
+ 0x4a32, 0x0d49,
+ 0x4a34, 0x212e,
+ 0x4a37, 0x0d4e,
+ 0x4a3b, 0x2131,
+ 0x4a3c, 0x0d53,
+ 0x4a46, 0x2132,
+ 0x4a47, 0x0d5e,
+ 0x4a4a, 0x2133,
+ 0x4a4b, 0x0d62,
+ 0x4a4d, 0x2134,
+ 0x4a4f, 0x0d66,
+ 0x4a53, 0x2136,
+ 0x4a55, 0x0d6c,
+ 0x4a59, 0x2138,
+ 0x4a5a, 0x0d71,
+ 0x4a5e, 0x2139,
+ 0x4a5f, 0x0d76,
+ 0x4a60, 0x213a,
+ 0x4a61, 0x0d78,
+ 0x4a64, 0x213b,
+ 0x4a65, 0x0d7c,
+ 0x4a69, 0x213c,
+ 0x4a6b, 0x0d82,
+ 0x4a74, 0x213e,
+ 0x4a76, 0x0d8d,
+ 0x4a77, 0x2140,
+ 0x4a78, 0x0d8f,
+ 0x4a7a, 0x2141,
+ 0x4a7b, 0x0d92,
+ 0x4a7d, 0x2142,
+ 0x4a7e, 0x0d95,
+ 0x4b21, 0x0d96,
+ 0x4b27, 0x2143,
+ 0x4b28, 0x0d9d,
+ 0x4b2b, 0x2144,
+ 0x4b2c, 0x0da1,
+ 0x4b2d, 0x2145,
+ 0x4b2e, 0x0da3,
+ 0x4b33, 0x2146,
+ 0x4b34, 0x0da9,
+ 0x4b35, 0x2147,
+ 0x4b37, 0x0dac,
+ 0x4b38, 0x2149,
+ 0x4b39, 0x0dae,
+ 0x4b3f, 0x214a,
+ 0x4b40, 0x0db5,
+ 0x4b47, 0x214b,
+ 0x4b48, 0x0dbd,
+ 0x4b49, 0x214c,
+ 0x4b4d, 0x0dc2,
+ 0x4b4f, 0x2150,
+ 0x4b51, 0x0dc6,
+ 0x4b53, 0x2152,
+ 0x4b54, 0x0dc9,
+ 0x4b55, 0x2153,
+ 0x4b56, 0x0dcb,
+ 0x4b5f, 0x2154,
+ 0x4b61, 0x0dd6,
+ 0x4b64, 0x2156,
+ 0x4b65, 0x0dda,
+ 0x4b66, 0x2157,
+ 0x4b68, 0x0ddd,
+ 0x4b6a, 0x2159,
+ 0x4b6b, 0x0de0,
+ 0x4b6f, 0x215a,
+ 0x4b71, 0x0de6,
+ 0x4b75, 0x215c,
+ 0x4b77, 0x0dec,
+ 0x4b78, 0x215e,
+ 0x4b79, 0x0dee,
+ 0x4c21, 0x215f,
+ 0x4c23, 0x0df6,
+ 0x4c28, 0x2161,
+ 0x4c29, 0x0dfc,
+ 0x4c2c, 0x2162,
+ 0x4c2d, 0x0e00,
+ 0x4c2f, 0x2163,
+ 0x4c34, 0x0e07,
+ 0x4c37, 0x2168,
+ 0x4c39, 0x0e0c,
+ 0x4c3e, 0x216a,
+ 0x4c3f, 0x0e12,
+ 0x4c40, 0x216b,
+ 0x4c41, 0x0e14,
+ 0x4c4c, 0x216c,
+ 0x4c4d, 0x0e20,
+ 0x4c4e, 0x216d,
+ 0x4c4f, 0x0e22,
+ 0x4c50, 0x216e,
+ 0x4c51, 0x0e24,
+ 0x4c56, 0x216f,
+ 0x4c57, 0x0e2a,
+ 0x4c5a, 0x2170,
+ 0x4c5b, 0x0e2e,
+ 0x4c5c, 0x2171,
+ 0x4c5d, 0x0e30,
+ 0x4c60, 0x2172,
+ 0x4c61, 0x0e34,
+ 0x4c62, 0x2173,
+ 0x4c63, 0x0e36,
+ 0x4c65, 0x2174,
+ 0x4c66, 0x0e39,
+ 0x4c75, 0x2175,
+ 0x4c76, 0x0e49,
+ 0x4c79, 0x2176,
+ 0x4c7b, 0x0e4e,
+ 0x4c7c, 0x2178,
+ 0x4d21, 0x0e52,
+ 0x4d2d, 0x217b,
+ 0x4d2e, 0x0e5f,
+ 0x4d33, 0x217c,
+ 0x4d34, 0x0e65,
+ 0x4d37, 0x217d,
+ 0x4d38, 0x0e69,
+ 0x4d3c, 0x217e,
+ 0x4d3d, 0x0e6e,
+ 0x4d3f, 0x217f,
+ 0x4d40, 0x0e71,
+ 0x4d45, 0x2180,
+ 0x4d46, 0x0e77,
+ 0x4d47, 0x2181,
+ 0x4d48, 0x0e79,
+ 0x4d52, 0x2182,
+ 0x4d53, 0x0e84,
+ 0x4d54, 0x2183,
+ 0x4d57, 0x0e88,
+ 0x4d5d, 0x2186,
+ 0x4d5e, 0x0e8f,
+ 0x4d60, 0x2187,
+ 0x4d61, 0x0e92,
+ 0x4d64, 0x2188,
+ 0x4d66, 0x0e97,
+ 0x4d67, 0x218a,
+ 0x4d68, 0x0e99,
+ 0x4d72, 0x218b,
+ 0x4d73, 0x0ea4,
+ 0x4d78, 0x218c,
+ 0x4d79, 0x0eaa,
+ 0x4e21, 0x0eb0,
+ 0x4e24, 0x218d,
+ 0x4e26, 0x0eb5,
+ 0x4e27, 0x218f,
+ 0x4e28, 0x0eb7,
+ 0x4e2a, 0x2190,
+ 0x4e2e, 0x0ebd,
+ 0x4e30, 0x2194,
+ 0x4e32, 0x0ec1,
+ 0x4e33, 0x2196,
+ 0x4e34, 0x0ec3,
+ 0x4e3d, 0x2197,
+ 0x4e3e, 0x0ecd,
+ 0x4e40, 0x2198,
+ 0x4e41, 0x0ed0,
+ 0x4e45, 0x2199,
+ 0x4e47, 0x0ed6,
+ 0x4e48, 0x219b,
+ 0x4e49, 0x0ed8,
+ 0x4e4a, 0x219c,
+ 0x4e4b, 0x0eda,
+ 0x4e4e, 0x219d,
+ 0x4e52, 0x0ee1,
+ 0x4e58, 0x21a1,
+ 0x4e5b, 0x0eea,
+ 0x4e5c, 0x21a4,
+ 0x4e5d, 0x0eec,
+ 0x4e5e, 0x21a5,
+ 0x4e60, 0x0eef,
+ 0x4e6b, 0x21a7,
+ 0x4e6c, 0x0efb,
+ 0x4e6d, 0x21a8,
+ 0x4e6e, 0x0efd,
+ 0x4e71, 0x21a9,
+ 0x4e72, 0x0f01,
+ 0x4e73, 0x21aa,
+ 0x4e74, 0x0f03,
+ 0x4e7d, 0x21ab,
+ 0x4f21, 0x0f0e,
+ 0x4f2e, 0x21ad,
+ 0x4f2f, 0x0f1c,
+ 0x4f30, 0x21ae,
+ 0x4f31, 0x0f1e,
+ 0x4f33, 0x21af,
+ 0x4f34, 0x0f21,
+ 0x4f37, 0x21b0,
+ 0x4f39, 0x0f26,
+ 0x4f3a, 0x21b2,
+ 0x4f3b, 0x0f28,
+ 0x4f3d, 0x21b3,
+ 0x4f3e, 0x0f2b,
+ 0x4f3f, 0x21b4,
+ 0x4f42, 0x0f2f,
+ 0x4f45, 0x21b7,
+ 0x4f46, 0x0f33,
+ 0x4f47, 0x21b8,
+ 0x4f48, 0x0f35,
+ 0x4f4a, 0x21b9,
+ 0x4f4c, 0x0f39,
+ 0x4f4d, 0x21bb,
+ 0x4f4f, 0x0f3c,
+ 0x4f50, 0x21bd,
+ 0x4f51, 0x0f3e,
+ 0x4f54, 0x21be,
+ 0x4f59, 0x0f46,
+ 0x4f5a, 0x21c3,
+ 0x4f5b, 0x0f48,
+ 0x4f5c, 0x21c4,
+ 0x4f5d, 0x0f4a,
+ 0x4f5f, 0x21c5,
+ 0x4f60, 0x0f4d,
+ 0x4f62, 0x21c6,
+ 0x4f63, 0x0f50,
+ 0x4f67, 0x21c7,
+ 0x4f68, 0x0f55,
+ 0x4f6a, 0x21c8,
+ 0x4f6b, 0x0f58,
+ 0x4f6c, 0x21c9,
+ 0x4f6d, 0x0f5a,
+ 0x4f6e, 0x21ca,
+ 0x4f6f, 0x0f5c,
+ 0x4f74, 0x21cb,
+ 0x4f75, 0x0f62,
+ 0x4f79, 0x21cc,
+ 0x4f7b, 0x0f68,
+ 0x4f7e, 0x21ce,
+ 0x5021, 0x0f6c,
+ 0x5025, 0x21cf,
+ 0x5026, 0x0f71,
+ 0x502d, 0x21d0,
+ 0x502f, 0x0f7a,
+ 0x5032, 0x21d2,
+ 0x5035, 0x0f80,
+ 0x503a, 0x21d5,
+ 0x503c, 0x0f87,
+ 0x503f, 0x21d7,
+ 0x5040, 0x0f8b,
+ 0x5046, 0x21d8,
+ 0x5047, 0x0f92,
+ 0x504b, 0x21d9,
+ 0x504c, 0x0f97,
+ 0x5062, 0x21da,
+ 0x5063, 0x0fae,
+ 0x5065, 0x21db,
+ 0x5066, 0x0fb1,
+ 0x506b, 0x21dc,
+ 0x506c, 0x0fb7,
+ 0x506d, 0x21dd,
+ 0x506e, 0x0fb9,
+ 0x5077, 0x21de,
+ 0x507a, 0x0fc5,
+ 0x507c, 0x21e1,
+ 0x507d, 0x0fc8,
+ 0x5121, 0x21e2,
+ 0x5123, 0x0fcc,
+ 0x5124, 0x21e4,
+ 0x5125, 0x0fce,
+ 0x5127, 0x21e5,
+ 0x5128, 0x0fd1,
+ 0x512b, 0x21e6,
+ 0x512c, 0x0fd5,
+ 0x512f, 0x21e7,
+ 0x5132, 0x0fdb,
+ 0x5135, 0x21ea,
+ 0x5138, 0x0fe1,
+ 0x5139, 0x21ed,
+ 0x513a, 0x0fe3,
+ 0x513b, 0x21ee,
+ 0x513d, 0x0fe6,
+ 0x5146, 0x21f0,
+ 0x5149, 0x0ff2,
+ 0x514b, 0x21f3,
+ 0x514c, 0x0ff5,
+ 0x514e, 0x21f4,
+ 0x5150, 0x0ff9,
+ 0x5155, 0x21f6,
+ 0x5157, 0x1000,
+ 0x515e, 0x21f8,
+ 0x515f, 0x1008,
+ 0x5161, 0x21f9,
+ 0x5163, 0x100c,
+ 0x5168, 0x21fb,
+ 0x516a, 0x1013,
+ 0x516c, 0x21fd,
+ 0x516d, 0x1016,
+ 0x516e, 0x21fe,
+ 0x5170, 0x1019,
+ 0x5171, 0x2200,
+ 0x5172, 0x101b,
+ 0x5174, 0x2201,
+ 0x5175, 0x101e,
+ 0x5177, 0x2202,
+ 0x517a, 0x1023,
+ 0x5221, 0x1028,
+ 0x5222, 0x2205,
+ 0x5223, 0x102a,
+ 0x5225, 0x2206,
+ 0x5226, 0x102d,
+ 0x5229, 0x2207,
+ 0x522a, 0x1031,
+ 0x522f, 0x2208,
+ 0x5230, 0x1037,
+ 0x5233, 0x2209,
+ 0x5234, 0x103b,
+ 0x5235, 0x220a,
+ 0x5237, 0x103e,
+ 0x523d, 0x220c,
+ 0x523e, 0x1045,
+ 0x523f, 0x220d,
+ 0x5240, 0x1047,
+ 0x5243, 0x220e,
+ 0x5244, 0x104b,
+ 0x5245, 0x220f,
+ 0x5246, 0x104d,
+ 0x5247, 0x2210,
+ 0x5248, 0x104f,
+ 0x524f, 0x2211,
+ 0x5250, 0x1057,
+ 0x5255, 0x2212,
+ 0x5256, 0x105d,
+ 0x525a, 0x2213,
+ 0x525b, 0x1062,
+ 0x5264, 0x2214,
+ 0x5266, 0x106d,
+ 0x5268, 0x2216,
+ 0x526c, 0x1073,
+ 0x526f, 0x221a,
+ 0x5270, 0x1077,
+ 0x5271, 0x221b,
+ 0x5272, 0x1079,
+ 0x5275, 0x221c,
+ 0x5276, 0x107d,
+ 0x5278, 0x221d,
+ 0x5279, 0x1080,
+ 0x527b, 0x221e,
+ 0x527c, 0x1083,
+ 0x527e, 0x221f,
+ 0x5321, 0x1086,
+ 0x5323, 0x2220,
+ 0x532d, 0x1092,
+ 0x532e, 0x222a,
+ 0x532f, 0x1094,
+ 0x5331, 0x222b,
+ 0x5332, 0x1097,
+ 0x5334, 0x222c,
+ 0x5337, 0x109c,
+ 0x5338, 0x222f,
+ 0x5339, 0x109e,
+ 0x533b, 0x2230,
+ 0x533c, 0x10a1,
+ 0x5345, 0x2231,
+ 0x5346, 0x10ab,
+ 0x5347, 0x2232,
+ 0x5348, 0x10ad,
+ 0x534a, 0x2233,
+ 0x534d, 0x10b2,
+ 0x5355, 0x2236,
+ 0x5356, 0x10bb,
+ 0x535f, 0x2237,
+ 0x5361, 0x10c6,
+ 0x5363, 0x2239,
+ 0x5364, 0x10c9,
+ 0x5366, 0x223a,
+ 0x5367, 0x10cc,
+ 0x536b, 0x223b,
+ 0x536d, 0x10d2,
+ 0x536f, 0x223d,
+ 0x5370, 0x10d5,
+ 0x5374, 0x223e,
+ 0x5375, 0x10da,
+ 0x537c, 0x223f,
+ 0x537d, 0x10e2,
+ 0x537e, 0x2240,
+ 0x5421, 0x10e4,
+ 0x5424, 0x2241,
+ 0x5425, 0x10e8,
+ 0x5426, 0x2242,
+ 0x5429, 0x10ec,
+ 0x542f, 0x2245,
+ 0x5433, 0x10f6,
+ 0x5435, 0x2249,
+ 0x5437, 0x10fa,
+ 0x5438, 0x224b,
+ 0x5439, 0x10fc,
+ 0x543c, 0x224c,
+ 0x543d, 0x1100,
+ 0x543e, 0x224d,
+ 0x5440, 0x1103,
+ 0x5444, 0x224f,
+ 0x5445, 0x1108,
+ 0x5446, 0x2250,
+ 0x5448, 0x110b,
+ 0x5449, 0x2252,
+ 0x544a, 0x110d,
+ 0x544b, 0x2253,
+ 0x544f, 0x1112,
+ 0x5453, 0x2257,
+ 0x5454, 0x1117,
+ 0x5458, 0x2258,
+ 0x5459, 0x111c,
+ 0x545c, 0x2259,
+ 0x5461, 0x1124,
+ 0x5464, 0x225e,
+ 0x5465, 0x1128,
+ 0x5466, 0x225f,
+ 0x5467, 0x112a,
+ 0x546e, 0x2260,
+ 0x546f, 0x1132,
+ 0x5470, 0x2261,
+ 0x5475, 0x1138,
+ 0x5479, 0x2266,
+ 0x547a, 0x113d,
+ 0x547e, 0x2267,
+ 0x5521, 0x2268,
+ 0x5523, 0x1144,
+ 0x5529, 0x226a,
+ 0x552a, 0x114b,
+ 0x552b, 0x226b,
+ 0x552c, 0x114d,
+ 0x552e, 0x226c,
+ 0x552f, 0x1150,
+ 0x5531, 0x226d,
+ 0x5532, 0x1153,
+ 0x5535, 0x226e,
+ 0x5539, 0x115a,
+ 0x553b, 0x2272,
+ 0x553c, 0x115d,
+ 0x553d, 0x2273,
+ 0x553e, 0x115f,
+ 0x5540, 0x2274,
+ 0x5541, 0x1162,
+ 0x5545, 0x2275,
+ 0x5546, 0x1167,
+ 0x5547, 0x2276,
+ 0x5548, 0x1169,
+ 0x554a, 0x2277,
+ 0x554c, 0x116d,
+ 0x554d, 0x2279,
+ 0x554e, 0x116f,
+ 0x5554, 0x227a,
+ 0x5555, 0x1176,
+ 0x555d, 0x227b,
+ 0x555f, 0x1180,
+ 0x5560, 0x227d,
+ 0x5561, 0x1182,
+ 0x5562, 0x227e,
+ 0x5563, 0x1184,
+ 0x556a, 0x227f,
+ 0x556d, 0x118e,
+ 0x556f, 0x2282,
+ 0x5570, 0x1191,
+ 0x5572, 0x2283,
+ 0x5574, 0x1195,
+ 0x5577, 0x15eb,
+ 0x5578, 0x1199,
+ 0x5621, 0x2285,
+ 0x5625, 0x11a4,
+ 0x562f, 0x2289,
+ 0x5631, 0x11b0,
+ 0x5634, 0x228b,
+ 0x5635, 0x11b4,
+ 0x563b, 0x228c,
+ 0x563c, 0x11bb,
+ 0x563d, 0x228d,
+ 0x563e, 0x11bd,
+ 0x563f, 0x228e,
+ 0x5641, 0x11c0,
+ 0x5644, 0x2290,
+ 0x5645, 0x11c4,
+ 0x564a, 0x2291,
+ 0x564b, 0x11ca,
+ 0x564d, 0x2292,
+ 0x564e, 0x11cd,
+ 0x5653, 0x2293,
+ 0x5654, 0x11d3,
+ 0x5655, 0x2294,
+ 0x5658, 0x11d7,
+ 0x565a, 0x2297,
+ 0x565b, 0x11da,
+ 0x565f, 0x2298,
+ 0x5660, 0x11df,
+ 0x5661, 0x2299,
+ 0x5662, 0x11e1,
+ 0x5665, 0x229a,
+ 0x5666, 0x11e5,
+ 0x5667, 0x229b,
+ 0x5669, 0x11e8,
+ 0x566e, 0x229d,
+ 0x5670, 0x11ef,
+ 0x5672, 0x229f,
+ 0x5673, 0x11f2,
+ 0x5675, 0x22a0,
+ 0x5677, 0x11f6,
+ 0x567c, 0x22a2,
+ 0x5721, 0x11fe,
+ 0x5724, 0x22a5,
+ 0x5725, 0x1202,
+ 0x5728, 0x22a6,
+ 0x572b, 0x1208,
+ 0x572c, 0x22a9,
+ 0x572d, 0x120a,
+ 0x572e, 0x22aa,
+ 0x5732, 0x120f,
+ 0x5733, 0x22ae,
+ 0x5735, 0x1212,
+ 0x5736, 0x22b0,
+ 0x5737, 0x1214,
+ 0x5738, 0x22b1,
+ 0x573d, 0x121a,
+ 0x5747, 0x22b6,
+ 0x5748, 0x1225,
+ 0x574a, 0x22b7,
+ 0x574b, 0x1228,
+ 0x5755, 0x22b8,
+ 0x5756, 0x1233,
+ 0x575b, 0x22b9,
+ 0x575f, 0x123c,
+ 0x5767, 0x22bd,
+ 0x5768, 0x1245,
+ 0x5769, 0x22be,
+ 0x576b, 0x1248,
+ 0x5821, 0x1257,
+ 0x5844, 0x22c0,
+ 0x5845, 0x127b,
+ 0x5847, 0x22c1,
+ 0x5848, 0x127e,
+ 0x5849, 0x22c2,
+ 0x584a, 0x1280,
+ 0x584c, 0x22c3,
+ 0x584e, 0x1284,
+ 0x5850, 0x22c5,
+ 0x5852, 0x1288,
+ 0x5853, 0x22c7,
+ 0x5854, 0x128a,
+ 0x5859, 0x22c8,
+ 0x585a, 0x1290,
+ 0x585b, 0x22c9,
+ 0x585d, 0x1293,
+ 0x5871, 0x22cb,
+ 0x5872, 0x12a8,
+ 0x5876, 0x22cc,
+ 0x5878, 0x12ae,
+ 0x5921, 0x12b5,
+ 0x592d, 0x22ce,
+ 0x592e, 0x12c2,
+ 0x592f, 0x22cf,
+ 0x5930, 0x12c4,
+ 0x5931, 0x22d0,
+ 0x5934, 0x12c8,
+ 0x5947, 0x22d3,
+ 0x5948, 0x12dc,
+ 0x594d, 0x22d4,
+ 0x5951, 0x12e5,
+ 0x595d, 0x22d8,
+ 0x595e, 0x12f2,
+ 0x5961, 0x22d9,
+ 0x5962, 0x12f6,
+ 0x5964, 0x22da,
+ 0x5965, 0x12f9,
+ 0x5966, 0x22db,
+ 0x5967, 0x12fb,
+ 0x596c, 0x22dc,
+ 0x596d, 0x1301,
+ 0x5974, 0x22dd,
+ 0x5976, 0x130a,
+ 0x5a21, 0x1313,
+ 0x5a25, 0x22df,
+ 0x5a60, 0x1352,
+ 0x5a6a, 0x231a,
+ 0x5a6b, 0x135d,
+ 0x5a77, 0x231b,
+ 0x5a78, 0x136a,
+ 0x5a79, 0x231c,
+ 0x5a7a, 0x136c,
+ 0x5a7e, 0x231d,
+ 0x5b21, 0x1371,
+ 0x5b23, 0x231e,
+ 0x5b24, 0x1374,
+ 0x5b26, 0x231f,
+ 0x5b27, 0x1377,
+ 0x5b29, 0x2320,
+ 0x5b2b, 0x137b,
+ 0x5b3b, 0x2322,
+ 0x5b3c, 0x138c,
+ 0x5b3d, 0x2323,
+ 0x5b3e, 0x138e,
+ 0x5b4f, 0x2324,
+ 0x5b50, 0x13a0,
+ 0x5b51, 0x2325,
+ 0x5b52, 0x13a2,
+ 0x5b5b, 0x2326,
+ 0x5b5c, 0x13ac,
+ 0x5b5e, 0x2327,
+ 0x5b5f, 0x13af,
+ 0x5b62, 0x2328,
+ 0x5b63, 0x13b3,
+ 0x5b64, 0x2329,
+ 0x5b65, 0x13b5,
+ 0x5b6b, 0x232a,
+ 0x5b6c, 0x13bc,
+ 0x5b6e, 0x232b,
+ 0x5b6f, 0x13bf,
+ 0x5b71, 0x232c,
+ 0x5b72, 0x13c2,
+ 0x5b75, 0x232d,
+ 0x5b78, 0x13c8,
+ 0x5c21, 0x13cf,
+ 0x5c3c, 0x2330,
+ 0x5c3d, 0x13eb,
+ 0x5c3f, 0x2331,
+ 0x5c40, 0x13ee,
+ 0x5c42, 0x2332,
+ 0x5c43, 0x13f1,
+ 0x5c48, 0x2333,
+ 0x5c4b, 0x13f9,
+ 0x5c51, 0x2336,
+ 0x5c52, 0x1400,
+ 0x5c57, 0x2337,
+ 0x5c58, 0x1406,
+ 0x5c60, 0x2338,
+ 0x5c61, 0x140f,
+ 0x5c63, 0x2339,
+ 0x5c65, 0x1413,
+ 0x5c69, 0x233b,
+ 0x5c6b, 0x1419,
+ 0x5c71, 0x233d,
+ 0x5c72, 0x1420,
+ 0x5c76, 0x233e,
+ 0x5c77, 0x1425,
+ 0x5c79, 0x233f,
+ 0x5c7a, 0x1428,
+ 0x5c7d, 0x2340,
+ 0x5d21, 0x2342,
+ 0x5d22, 0x142e,
+ 0x5d23, 0x2343,
+ 0x5d28, 0x1434,
+ 0x5d2a, 0x2348,
+ 0x5d2c, 0x1438,
+ 0x5d32, 0x234a,
+ 0x5d33, 0x143f,
+ 0x5d35, 0x234b,
+ 0x5d36, 0x1442,
+ 0x5d3a, 0x234c,
+ 0x5d3c, 0x1448,
+ 0x5d53, 0x234e,
+ 0x5d54, 0x1460,
+ 0x5d5b, 0x234f,
+ 0x5d5c, 0x1468,
+ 0x5d5e, 0x2350,
+ 0x5d5f, 0x146b,
+ 0x5d64, 0x2351,
+ 0x5d65, 0x1471,
+ 0x5d6b, 0x2352,
+ 0x5d6c, 0x1478,
+ 0x5d71, 0x2353,
+ 0x5d72, 0x147e,
+ 0x5d76, 0x2354,
+ 0x5d78, 0x1484,
+ 0x5d7c, 0x2356,
+ 0x5d7d, 0x1489,
+ 0x5d7e, 0x2357,
+ 0x5e21, 0x148b,
+ 0x5e2d, 0x2358,
+ 0x5e2e, 0x1498,
+ 0x5e34, 0x2359,
+ 0x5e35, 0x149f,
+ 0x5e3a, 0x235a,
+ 0x5e3b, 0x14a5,
+ 0x5e46, 0x235b,
+ 0x5e47, 0x14b1,
+ 0x5e4f, 0x235c,
+ 0x5e50, 0x14ba,
+ 0x5e51, 0x235d,
+ 0x5e53, 0x14bd,
+ 0x5e58, 0x235f,
+ 0x5e59, 0x14c3,
+ 0x5e62, 0x2360,
+ 0x5e63, 0x14cd,
+ 0x5e68, 0x2361,
+ 0x5e69, 0x14d3,
+ 0x5e6c, 0x2362,
+ 0x5e6d, 0x14d7,
+ 0x5e73, 0x2363,
+ 0x5e74, 0x14de,
+ 0x5e7c, 0x2364,
+ 0x5e7d, 0x14e7,
+ 0x5f21, 0x14e9,
+ 0x5f22, 0x2365,
+ 0x5f24, 0x14ec,
+ 0x5f25, 0x2367,
+ 0x5f26, 0x14ee,
+ 0x5f34, 0x2368,
+ 0x5f35, 0x14fd,
+ 0x5f3c, 0x2369,
+ 0x5f3e, 0x1506,
+ 0x5f3f, 0x236b,
+ 0x5f40, 0x1508,
+ 0x5f42, 0x236c,
+ 0x5f44, 0x150c,
+ 0x5f4c, 0x236e,
+ 0x5f4d, 0x1515,
+ 0x5f50, 0x236f,
+ 0x5f51, 0x1519,
+ 0x5f55, 0x2370,
+ 0x5f56, 0x151e,
+ 0x5f58, 0x2371,
+ 0x5f5a, 0x1522,
+ 0x5f5c, 0x2373,
+ 0x5f5d, 0x1525,
+ 0x5f60, 0x2374,
+ 0x5f61, 0x1529,
+ 0x5f62, 0x2375,
+ 0x5f63, 0x152b,
+ 0x5f66, 0x2376,
+ 0x5f67, 0x152f,
+ 0x5f69, 0x2377,
+ 0x5f6a, 0x1532,
+ 0x5f6b, 0x2378,
+ 0x5f6c, 0x1534,
+ 0x5f6f, 0x2379,
+ 0x5f70, 0x1538,
+ 0x5f75, 0x237a,
+ 0x5f76, 0x153e,
+ 0x5f79, 0x237b,
+ 0x5f7a, 0x1542,
+ 0x6021, 0x1547,
+ 0x6036, 0x237c,
+ 0x6038, 0x155e,
+ 0x603f, 0x237e,
+ 0x6040, 0x1566,
+ 0x6048, 0x237f,
+ 0x6049, 0x156f,
+ 0x604e, 0x2380,
+ 0x604f, 0x1575,
+ 0x6053, 0x2381,
+ 0x6054, 0x157a,
+ 0x6060, 0x2382,
+ 0x6061, 0x1587,
+ 0x6070, 0x2383,
+ 0x6071, 0x1597,
+ 0x6078, 0x2384,
+ 0x6079, 0x159f,
+ 0x607c, 0x2385,
+ 0x6121, 0x15a5,
+ 0x612b, 0x2388,
+ 0x612c, 0x15b0,
+ 0x612d, 0x2389,
+ 0x612e, 0x15b2,
+ 0x6130, 0x238a,
+ 0x6131, 0x15b5,
+ 0x6134, 0x238b,
+ 0x6135, 0x15b9,
+ 0x613b, 0x238c,
+ 0x613c, 0x15c0,
+ 0x613d, 0x238d,
+ 0x613e, 0x15c2,
+ 0x6140, 0x238e,
+ 0x6142, 0x15c6,
+ 0x6149, 0x2390,
+ 0x614a, 0x15ce,
+ 0x6150, 0x2391,
+ 0x6151, 0x15d5,
+ 0x615b, 0x2392,
+ 0x615c, 0x15e0,
+ 0x6161, 0x07aa,
+ 0x6162, 0x2393,
+ 0x6163, 0x15e7,
+ 0x6167, 0x1198,
+ 0x6168, 0x15ec,
+ 0x616e, 0x2394,
+ 0x6170, 0x15f4,
+ 0x6176, 0x2396,
+ 0x6177, 0x15fb,
+ 0x6178, 0x2397,
+ 0x6179, 0x15fd,
+ 0x617d, 0x2398,
+ 0x617e, 0x1602,
+ 0x6221, 0x1603,
+ 0x6224, 0x2399,
+ 0x6225, 0x1607,
+ 0x6228, 0x239a,
+ 0x6229, 0x160b,
+ 0x623b, 0x239b,
+ 0x6245, 0x10c5,
+ 0x6246, 0x23a5,
+ 0x624f, 0x1631,
+ 0x6250, 0x23ae,
+ 0x6251, 0x1633,
+ 0x6259, 0x23af,
+ 0x625a, 0x163c,
+ 0x6263, 0x23b0,
+ 0x6265, 0x1647,
+ 0x6266, 0x23b2,
+ 0x6267, 0x1649,
+ 0x6269, 0x23b3,
+ 0x626c, 0x164e,
+ 0x6278, 0x23b6,
+ 0x6279, 0x165b,
+ 0x627a, 0x23b7,
+ 0x627e, 0x1660,
+ 0x6321, 0x1661,
+ 0x6322, 0x23bb,
+ 0x6323, 0x1663,
+ 0x6325, 0x23bc,
+ 0x6326, 0x1666,
+ 0x632b, 0x23bd,
+ 0x632c, 0x166c,
+ 0x6334, 0x23be,
+ 0x6335, 0x1675,
+ 0x6345, 0x23bf,
+ 0x635c, 0x169c,
+ 0x6363, 0x23d6,
+ 0x6364, 0x16a4,
+ 0x636d, 0x23d7,
+ 0x636e, 0x16ae,
+ 0x6371, 0x23d8,
+ 0x6373, 0x16b3,
+ 0x6378, 0x23da,
+ 0x6379, 0x16b9,
+ 0x637e, 0x23db,
+ 0x6421, 0x16bf,
+ 0x6424, 0x23dc,
+ 0x6426, 0x16c4,
+ 0x642b, 0x23de,
+ 0x642c, 0x16ca,
+ 0x642f, 0x23df,
+ 0x6432, 0x16d0,
+ 0x6435, 0x23e2,
+ 0x6437, 0x16d5,
+ 0x6442, 0x23e4,
+ 0x6443, 0x16e1,
+ 0x6445, 0x23e5,
+ 0x6446, 0x16e4,
+ 0x6449, 0x23e6,
+ 0x644a, 0x16e8,
+ 0x6459, 0x23e7,
+ 0x645a, 0x16f8,
+ 0x645c, 0x23e8,
+ 0x645d, 0x16fb,
+ 0x645e, 0x23e9,
+ 0x645f, 0x16fd,
+ 0x6464, 0x23ea,
+ 0x6465, 0x1703,
+ 0x646b, 0x23eb,
+ 0x646d, 0x170b,
+ 0x6472, 0x23ed,
+ 0x6473, 0x1711,
+ 0x647e, 0x23ee,
+ 0x6521, 0x171d,
+ 0x6530, 0x23ef,
+ 0x6531, 0x172d,
+ 0x6539, 0x23f0,
+ 0x653a, 0x1736,
+ 0x6547, 0x23f1,
+ 0x6548, 0x1744,
+ 0x6549, 0x23f2,
+ 0x654a, 0x1746,
+ 0x654e, 0x23f3,
+ 0x654f, 0x174b,
+ 0x6570, 0x23f4,
+ 0x6571, 0x176d,
+ 0x6572, 0x23f5,
+ 0x6573, 0x176f,
+ 0x657c, 0x23f6,
+ 0x657e, 0x177a,
+ 0x6621, 0x177b,
+ 0x6623, 0x23f8,
+ 0x6624, 0x177e,
+ 0x662b, 0x23f9,
+ 0x662d, 0x1787,
+ 0x662e, 0x23fb,
+ 0x662f, 0x1789,
+ 0x6634, 0x23fc,
+ 0x6636, 0x1790,
+ 0x663f, 0x23fe,
+ 0x6640, 0x179a,
+ 0x6648, 0x23ff,
+ 0x664a, 0x17a4,
+ 0x664d, 0x2401,
+ 0x664e, 0x17a8,
+ 0x6660, 0x2402,
+ 0x6721, 0x2421,
+ 0x675b, 0x1813,
+ 0x6761, 0x245b,
+ 0x6763, 0x181b,
+ 0x6767, 0x245d,
+ 0x6768, 0x1820,
+ 0x676f, 0x245e,
+ 0x6770, 0x1828,
+ 0x6774, 0x245f,
+ 0x6777, 0x182f,
+ 0x6821, 0x1837,
+ 0x6828, 0x2462,
+ 0x6829, 0x183f,
+ 0x682c, 0x2463,
+ 0x682d, 0x1843,
+ 0x6836, 0x2464,
+ 0x6837, 0x184d,
+ 0x6838, 0x2465,
+ 0x683b, 0x1851,
+ 0x683f, 0x2468,
+ 0x6841, 0x1857,
+ 0x6845, 0x246a,
+ 0x6846, 0x185c,
+ 0x6847, 0x246b,
+ 0x684a, 0x1860,
+ 0x684e, 0x246e,
+ 0x684f, 0x1865,
+ 0x6850, 0x246f,
+ 0x6851, 0x1867,
+ 0x6853, 0x2470,
+ 0x6854, 0x186a,
+ 0x685d, 0x2471,
+ 0x685e, 0x1874,
+ 0x685f, 0x2472,
+ 0x6860, 0x1876,
+ 0x6862, 0x2473,
+ 0x6864, 0x187a,
+ 0x6865, 0x2475,
+ 0x6866, 0x187c,
+ 0x6867, 0x2476,
+ 0x6868, 0x187e,
+ 0x686b, 0x2477,
+ 0x686c, 0x1882,
+ 0x686d, 0x2478,
+ 0x686e, 0x1884,
+ 0x686f, 0x2479,
+ 0x6870, 0x1886,
+ 0x6879, 0x247a,
+ 0x687a, 0x1890,
+ 0x687c, 0x247b,
+ 0x687e, 0x1894,
+ 0x6921, 0x247d,
+ 0x6922, 0x1896,
+ 0x692d, 0x247e,
+ 0x692e, 0x18a2,
+ 0x6934, 0x247f,
+ 0x6936, 0x18aa,
+ 0x6937, 0x2481,
+ 0x6938, 0x18ac,
+ 0x6944, 0x2482,
+ 0x6945, 0x18b9,
+ 0x6946, 0x2483,
+ 0x6947, 0x18bb,
+ 0x6949, 0x2484,
+ 0x694a, 0x18be,
+ 0x6956, 0x2485,
+ 0x6957, 0x18cb,
+ 0x695a, 0x2486,
+ 0x695b, 0x18cf,
+ 0x6964, 0x2487,
+ 0x6965, 0x18d9,
+ 0x6966, 0x2488,
+ 0x6968, 0x18dc,
+ 0x6969, 0x248a,
+ 0x696a, 0x18de,
+ 0x696b, 0x248b,
+ 0x696c, 0x18e0,
+ 0x696d, 0x248c,
+ 0x6a21, 0x249e,
+ 0x6a26, 0x18f8,
+ 0x6a27, 0x24a3,
+ 0x6a29, 0x18fb,
+ 0x6a31, 0x24a5,
+ 0x6a32, 0x1904,
+ 0x6a3c, 0x24a6,
+ 0x6a3d, 0x190f,
+ 0x6a4a, 0x24a7,
+ 0x6a4b, 0x191d,
+ 0x6a4d, 0x24a8,
+ 0x6a4e, 0x1920,
+ 0x6a53, 0x24a9,
+ 0x6a54, 0x1926,
+ 0x6a5a, 0x24aa,
+ 0x6a70, 0x1942,
+ 0x6b21, 0x1951,
+ 0x6b27, 0x24c0,
+ 0x6b28, 0x1958,
+ 0x6b2a, 0x24c1,
+ 0x6b2b, 0x195b,
+ 0x6b32, 0x24c2,
+ 0x6b33, 0x1963,
+ 0x6b39, 0x24c3,
+ 0x6b3a, 0x196a,
+ 0x6b4a, 0x24c4,
+ 0x6b4c, 0x197c,
+ 0x6b4d, 0x24c6,
+ 0x6b4e, 0x197e,
+ 0x6b56, 0x24c7,
+ 0x6b57, 0x1987,
+ 0x6b5a, 0x24c8,
+ 0x6b5b, 0x198b,
+ 0x6b61, 0x24c9,
+ 0x6b62, 0x1992,
+ 0x6b77, 0x24ca,
+ 0x6b78, 0x19a8,
+ 0x6c21, 0x19af,
+ 0x6c23, 0x24cb,
+ 0x6c24, 0x19b2,
+ 0x6c29, 0x24cc,
+ 0x6c2f, 0x19bd,
+ 0x6c31, 0x24d2,
+ 0x6c32, 0x19c0,
+ 0x6c34, 0x24d3,
+ 0x6c36, 0x19c4,
+ 0x6c3e, 0x24d5,
+ 0x6c40, 0x19ce,
+ 0x6c41, 0x24d7,
+ 0x6c42, 0x19d0,
+ 0x6c47, 0x24d8,
+ 0x6c48, 0x19d6,
+ 0x6c4b, 0x24d9,
+ 0x6c4c, 0x19da,
+ 0x6c62, 0x24da,
+ 0x6c63, 0x19f1,
+ 0x6c72, 0x24db,
+ 0x6c73, 0x1a01,
+ 0x6c75, 0x24dc,
+ 0x6c76, 0x1a04,
+ 0x6c78, 0x24dd,
+ 0x6c79, 0x1a07,
+ 0x6d21, 0x24de,
+ 0x6d22, 0x1a0e,
+ 0x6d28, 0x24df,
+ 0x6d29, 0x1a15,
+ 0x6d2f, 0x24e0,
+ 0x6d31, 0x1a1d,
+ 0x6d34, 0x24e2,
+ 0x6d35, 0x1a21,
+ 0x6d36, 0x24e3,
+ 0x6d37, 0x1a23,
+ 0x6d38, 0x24e4,
+ 0x6d39, 0x1a25,
+ 0x6d3a, 0x24e5,
+ 0x6d3b, 0x1a27,
+ 0x6d3f, 0x24e6,
+ 0x6d40, 0x1a2c,
+ 0x6d42, 0x24e7,
+ 0x6d44, 0x1a30,
+ 0x6d4c, 0x24e9,
+ 0x6d4e, 0x1a3a,
+ 0x6d53, 0x24eb,
+ 0x6d54, 0x1a40,
+ 0x6d57, 0x24ec,
+ 0x6d58, 0x1a44,
+ 0x6d68, 0x24ed,
+ 0x6d69, 0x1a55,
+ 0x6d6e, 0x24ee,
+ 0x6d6f, 0x1a5b,
+ 0x6d79, 0x24ef,
+ 0x6d7b, 0x1a67,
+ 0x6e21, 0x1a6b,
+ 0x6e3c, 0x24f1,
+ 0x6e3d, 0x1a87,
+ 0x6e3f, 0x24f2,
+ 0x6e40, 0x1a8a,
+ 0x6e44, 0x24f3,
+ 0x6f21, 0x252e,
+ 0x6f72, 0x1b1a,
+ 0x7021, 0x1b27,
+ 0x7023, 0x257f,
+ 0x7024, 0x1b2a,
+ 0x702f, 0x2580,
+ 0x705a, 0x1b60,
+ 0x705c, 0x25ab,
+ 0x705e, 0x1b64,
+ 0x705f, 0x25ad,
+ 0x7060, 0x1b66,
+ 0x7069, 0x25ae,
+ 0x706a, 0x1b70,
+ 0x706c, 0x25af,
+ 0x706d, 0x1b73,
+ 0x706f, 0x25b0,
+ 0x7070, 0x1b76,
+ 0x7077, 0x25b1,
+ 0x7078, 0x1b7e,
+ 0x7079, 0x25b2,
+ 0x707a, 0x1b80,
+ 0x707c, 0x25b3,
+ 0x707d, 0x1b83,
+ 0x7121, 0x1b85,
+ 0x7128, 0x25b4,
+ 0x7129, 0x1b8d,
+ 0x712b, 0x25b5,
+ 0x712c, 0x1b90,
+ 0x712e, 0x25b6,
+ 0x712f, 0x1b93,
+ 0x7132, 0x25b7,
+ 0x7133, 0x1b97,
+ 0x713c, 0x25b8,
+ 0x713d, 0x1ba1,
+ 0x7140, 0x25b9,
+ 0x7141, 0x1ba5,
+ 0x7149, 0x25ba,
+ 0x714a, 0x1bae,
+ 0x714d, 0x25bb,
+ 0x714e, 0x1bb2,
+ 0x714f, 0x25bc,
+ 0x7151, 0x1bb5,
+ 0x715a, 0x25be,
+ 0x715b, 0x1bbf,
+ 0x715c, 0x25bf,
+ 0x715d, 0x1bc1,
+ 0x7164, 0x25c0,
+ 0x7165, 0x1bc9,
+ 0x716c, 0x25c1,
+ 0x716d, 0x1bd1,
+ 0x716f, 0x25c2,
+ 0x7170, 0x1bd4,
+ 0x7177, 0x25c3,
+ 0x7178, 0x1bdc,
+ 0x7179, 0x25c4,
+ 0x717a, 0x1bde,
+ 0x717c, 0x25c5,
+ 0x7221, 0x25c8,
+ 0x722e, 0x1bf0,
+ 0x7231, 0x25d5,
+ 0x7233, 0x1bf5,
+ 0x7239, 0x25d7,
+ 0x723a, 0x1bfc,
+ 0x7243, 0x25d8,
+ 0x7244, 0x1c06,
+ 0x7249, 0x25d9,
+ 0x724a, 0x1c0c,
+ 0x724c, 0x25da,
+ 0x724e, 0x1c10,
+ 0x724f, 0x25dc,
+ 0x7250, 0x1c12,
+ 0x7253, 0x25dd,
+ 0x7254, 0x1c16,
+ 0x7265, 0x25de,
+ 0x7266, 0x1c28,
+ 0x726e, 0x25df,
+ 0x726f, 0x1c31,
+ 0x7277, 0x25e0,
+ 0x7278, 0x1c3a,
+ 0x727d, 0x25e1,
+ 0x727e, 0x1c40,
+ 0x7321, 0x1c41,
+ 0x733f, 0x25e2,
+ 0x7340, 0x1c60,
+ 0x7346, 0x25e3,
+ 0x7347, 0x1c67,
+ 0x7348, 0x25e4,
+ 0x7349, 0x1c69,
+ 0x7356, 0x25e5,
+ 0x7357, 0x1c77,
+ 0x7359, 0x25e6,
+ 0x735a, 0x1c7a,
+ 0x7365, 0x25e7,
+ 0x7367, 0x1c87,
+ 0x736a, 0x25e9,
+ 0x736b, 0x1c8b,
+ 0x736c, 0x25ea,
+ 0x736d, 0x1c8d,
+ 0x736f, 0x25eb,
+ 0x7370, 0x1c90,
+ 0x7371, 0x25ec,
+ 0x7372, 0x1c92,
+ 0x737d, 0x25ed,
+ 0x737e, 0x1c9e,
+ 0x7421, 0x1c9f,
+ 0x7425, 0x25ee,
+ 0x7426, 0x1ca4,
+ 0x742f, 0x25ef,
+ 0x7430, 0x1cae,
+ 0x7435, 0x25f0,
+ 0x7436, 0x1cb4,
+ 0x7441, 0x25f1,
+ 0x7442, 0x1cc0,
+ 0x7447, 0x25f2,
+ 0x7448, 0x1cc6,
+ 0x744f, 0x25f3,
+ 0x7451, 0x1ccf,
+ 0x7456, 0x25f5,
+ 0x7457, 0x1cd5,
+ 0x746a, 0x25f6,
+ 0x746b, 0x1ce9,
+ 0x746f, 0x25f7,
+ 0x7470, 0x1cee,
+ 0x7475, 0x25f8,
+ 0x7476, 0x1cf4,
+ 0x7521, 0x1cfd,
+ 0x7526, 0x25f9,
+ 0x7528, 0x1d04,
+ 0x753a, 0x25fb,
+ 0x753c, 0x1d18,
+ 0x7544, 0x25fd,
+ 0x7545, 0x1d21,
+ 0x7548, 0x25fe,
+ 0x7549, 0x1d25,
+ 0x754e, 0x25ff,
+ 0x7550, 0x1d2c,
+ 0x7551, 0x2601,
+ 0x7553, 0x1d2f,
+ 0x7559, 0x2603,
+ 0x755a, 0x1d36,
+ 0x755c, 0x2604,
+ 0x755d, 0x1d39,
+ 0x7566, 0x2605,
+ 0x7568, 0x1d44,
+ 0x756f, 0x2607,
+ 0x7570, 0x1d4c,
+ 0x7572, 0x2608,
+ 0x7573, 0x1d4f,
+ 0x757c, 0x2609,
+ 0x757d, 0x1d59,
+ 0x7621, 0x1d5b,
+ 0x7623, 0x260a,
+ 0x7624, 0x1d5e,
+ 0x7626, 0x260b,
+ 0x7627, 0x1d61,
+ 0x7628, 0x260c,
+ 0x7629, 0x1d63,
+ 0x762b, 0x260d,
+ 0x762c, 0x1d66,
+ 0x7630, 0x260e,
+ 0x7631, 0x1d6b,
+ 0x7633, 0x260f,
+ 0x763f, 0x1d79,
+ 0x7645, 0x261b,
+ 0x7646, 0x1d80,
+ 0x7647, 0x261c,
+ 0x7648, 0x1d82,
+ 0x7649, 0x261d,
+ 0x764a, 0x1d84,
+ 0x764f, 0x261e,
+ 0x7721, 0x264e,
+ 0x7730, 0x1dc8,
+ 0x7732, 0x265d,
+ 0x7734, 0x1dcc,
+ 0x7735, 0x265f,
+ 0x7736, 0x1dce,
+ 0x773d, 0x2660,
+ 0x773e, 0x1dd6,
+ 0x7743, 0x2661,
+ 0x7744, 0x1ddc,
+ 0x7745, 0x2662,
+ 0x7747, 0x1ddf,
+ 0x774a, 0x2664,
+ 0x774c, 0x1de4,
+ 0x774f, 0x2666,
+ 0x7751, 0x1de9,
+ 0x775e, 0x2668,
+ 0x775f, 0x1df7,
+ 0x7761, 0x0ab9,
+ 0x7762, 0x1dfa,
+ 0x7772, 0x2669,
+ 0x7773, 0x1e0b,
+ 0x7775, 0x266a,
+ 0x7776, 0x1e0e,
+ 0x7821, 0x266b,
+ 0x7827, 0x04cc,
+ 0x7828, 0x050a,
+ 0x7829, 0x0518,
+ 0x782a, 0x2671,
+ 0x782c, 0x0594,
+ 0x782d, 0x05ce,
+ 0x782e, 0x2673,
+ 0x782f, 0x05f6,
+ 0x7830, 0x2674,
+ 0x7832, 0x0653,
+ 0x7833, 0x067e,
+ 0x7834, 0x2676,
+ 0x7835, 0x06c4,
+ 0x7836, 0x2677,
+ 0x7838, 0x073c,
+ 0x7839, 0x2679,
+ 0x783b, 0x07c3,
+ 0x783c, 0x267b,
+ 0x7840, 0x082b,
+ 0x7841, 0x267f,
+ 0x7842, 0x084e,
+ 0x7843, 0x0869,
+ 0x7844, 0x2680,
+ 0x7846, 0x090c,
+ 0x7847, 0x2682,
+ 0x7849, 0x0971,
+ 0x784a, 0x2684,
+ 0x784b, 0x099a,
+ 0x784d, 0x2685,
+ 0x784e, 0x09da,
+ 0x784f, 0x2686,
+ 0x7850, 0x09fa,
+ 0x7851, 0x2687,
+ 0x785c, 0x0bda,
+ 0x785d, 0x0bdd,
+ 0x785e, 0x0bea,
+ 0x785f, 0x0bec,
+ 0x7860, 0x0bf2,
+ 0x7861, 0x2692,
+ 0x7866, 0x0c92,
+ 0x7867, 0x0d1a,
+ 0x7868, 0x0d8c,
+ 0x7869, 0x0dbe,
+ 0x786a, 0x2697,
+ 0x786b, 0x0dfb,
+ 0x786c, 0x2698,
+ 0x786f, 0x0e70,
+ 0x7870, 0x269b,
+ 0x7871, 0x0ea3,
+ 0x7872, 0x269c,
+ 0x7878, 0x103d,
+ 0x7879, 0x10d9,
+ 0x787a, 0x26a2,
+ 0x787c, 0x10fb,
+ 0x787d, 0x1109,
+ 0x787e, 0x26a4,
+ 0x7921, 0x11a1,
+ 0x7922, 0x26a5,
+ 0x7923, 0x11ba,
+ 0x7924, 0x26a6,
+ 0x7926, 0x11d5,
+ 0x7927, 0x26a8,
+ 0x7928, 0x11fd,
+ 0x7929, 0x1219,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBTHMap2, 2283
+};
+
+static Gushort gb12GBTVMap2[4606] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0060,
+ 0x2231, 0x00be,
+ 0x2265, 0x00f0,
+ 0x2271, 0x00fa,
+ 0x2321, 0x0106,
+ 0x2421, 0x0164,
+ 0x2521, 0x01b7,
+ 0x2621, 0x020d,
+ 0x2641, 0x0225,
+ 0x2721, 0x025a,
+ 0x2751, 0x027b,
+ 0x2821, 0x029c,
+ 0x2845, 0x02bc,
+ 0x2924, 0x02e2,
+ 0x2a21, 0x032e,
+ 0x2b21, 0x038c,
+ 0x3021, 0x03ac,
+ 0x3028, 0x1e25,
+ 0x3029, 0x03b4,
+ 0x302a, 0x1e26,
+ 0x302b, 0x03b6,
+ 0x302d, 0x1e27,
+ 0x302f, 0x03ba,
+ 0x3039, 0x1e29,
+ 0x303a, 0x03c5,
+ 0x3040, 0x1e2a,
+ 0x3041, 0x03cc,
+ 0x3053, 0x1e2b,
+ 0x3054, 0x03df,
+ 0x3055, 0x1e2c,
+ 0x3056, 0x03e1,
+ 0x305a, 0x1e2d,
+ 0x305b, 0x03e6,
+ 0x305c, 0x1e2e,
+ 0x305d, 0x03e8,
+ 0x3064, 0x1e2f,
+ 0x3065, 0x03f0,
+ 0x306c, 0x1e30,
+ 0x306e, 0x03f9,
+ 0x306f, 0x1e32,
+ 0x3070, 0x03fb,
+ 0x3073, 0x1e33,
+ 0x3074, 0x03ff,
+ 0x3077, 0x1e34,
+ 0x3078, 0x0403,
+ 0x3079, 0x1e35,
+ 0x307a, 0x0405,
+ 0x3121, 0x040a,
+ 0x3125, 0x1e36,
+ 0x3127, 0x0410,
+ 0x3128, 0x1e38,
+ 0x3129, 0x0412,
+ 0x312b, 0x1e39,
+ 0x312c, 0x0415,
+ 0x3132, 0x1e3a,
+ 0x3133, 0x041c,
+ 0x3134, 0x1e3b,
+ 0x3136, 0x041f,
+ 0x3137, 0x1e3d,
+ 0x313a, 0x0423,
+ 0x3141, 0x1e40,
+ 0x3142, 0x042b,
+ 0x314a, 0x1e41,
+ 0x314b, 0x0434,
+ 0x314f, 0x1e42,
+ 0x3151, 0x043a,
+ 0x3152, 0x1e44,
+ 0x3153, 0x043c,
+ 0x3155, 0x1e45,
+ 0x3156, 0x043f,
+ 0x315f, 0x1e46,
+ 0x3162, 0x044b,
+ 0x3164, 0x1e49,
+ 0x3165, 0x044e,
+ 0x3167, 0x1e4a,
+ 0x3169, 0x0452,
+ 0x316a, 0x1e4c,
+ 0x316b, 0x0454,
+ 0x316e, 0x1e4d,
+ 0x316f, 0x0458,
+ 0x3171, 0x1e4e,
+ 0x3172, 0x045b,
+ 0x3174, 0x1e4f,
+ 0x3178, 0x0461,
+ 0x317d, 0x1e53,
+ 0x317e, 0x0467,
+ 0x3221, 0x0468,
+ 0x3226, 0x1e54,
+ 0x3228, 0x046f,
+ 0x322c, 0x1e56,
+ 0x322d, 0x0474,
+ 0x3235, 0x1e57,
+ 0x3236, 0x047d,
+ 0x3239, 0x1e58,
+ 0x323a, 0x0481,
+ 0x3246, 0x1e59,
+ 0x3247, 0x048e,
+ 0x324e, 0x1e5a,
+ 0x3258, 0x049f,
+ 0x325e, 0x1e64,
+ 0x325f, 0x04a6,
+ 0x3260, 0x1e65,
+ 0x3261, 0x04a8,
+ 0x3262, 0x1e66,
+ 0x3264, 0x04ab,
+ 0x326f, 0x1e68,
+ 0x3270, 0x04b7,
+ 0x3273, 0x1e69,
+ 0x327d, 0x04c4,
+ 0x3321, 0x1e73,
+ 0x3323, 0x04c8,
+ 0x3324, 0x1e75,
+ 0x3328, 0x04cd,
+ 0x3329, 0x1e79,
+ 0x332a, 0x04cf,
+ 0x332e, 0x1e7a,
+ 0x332f, 0x04d4,
+ 0x3335, 0x1e7b,
+ 0x3336, 0x04db,
+ 0x3339, 0x1e7c,
+ 0x333a, 0x04df,
+ 0x333e, 0x1e7d,
+ 0x333f, 0x04e4,
+ 0x3342, 0x1e7e,
+ 0x3343, 0x04e8,
+ 0x3344, 0x1e7f,
+ 0x3345, 0x04ea,
+ 0x3346, 0x1e80,
+ 0x3347, 0x04ec,
+ 0x334d, 0x1e81,
+ 0x334e, 0x04f3,
+ 0x334f, 0x1e82,
+ 0x3350, 0x04f5,
+ 0x3352, 0x1e83,
+ 0x3353, 0x04f8,
+ 0x3359, 0x1e84,
+ 0x335a, 0x04ff,
+ 0x335b, 0x1e85,
+ 0x335c, 0x0501,
+ 0x335d, 0x1e86,
+ 0x335e, 0x0503,
+ 0x3363, 0x1e87,
+ 0x3364, 0x0509,
+ 0x3365, 0x1e88,
+ 0x3367, 0x050c,
+ 0x3368, 0x1e8a,
+ 0x3369, 0x050e,
+ 0x336b, 0x1e8b,
+ 0x336d, 0x0512,
+ 0x336f, 0x1e8d,
+ 0x3370, 0x0515,
+ 0x3371, 0x1e8e,
+ 0x3372, 0x0517,
+ 0x3373, 0x1e8f,
+ 0x3374, 0x0519,
+ 0x337a, 0x1e90,
+ 0x337c, 0x0521,
+ 0x3421, 0x1e92,
+ 0x3423, 0x0526,
+ 0x3425, 0x1e94,
+ 0x3427, 0x052a,
+ 0x342b, 0x1e96,
+ 0x342c, 0x052f,
+ 0x342f, 0x1e97,
+ 0x3430, 0x0533,
+ 0x3433, 0x1e98,
+ 0x3435, 0x0538,
+ 0x3438, 0x1e9a,
+ 0x3439, 0x053c,
+ 0x343f, 0x1e9b,
+ 0x3440, 0x0543,
+ 0x3442, 0x1e9c,
+ 0x3443, 0x0546,
+ 0x3447, 0x1e9d,
+ 0x3448, 0x054b,
+ 0x344a, 0x1e9e,
+ 0x344b, 0x054e,
+ 0x344d, 0x1e9f,
+ 0x344e, 0x0551,
+ 0x344f, 0x1ea0,
+ 0x3450, 0x0553,
+ 0x3453, 0x1ea1,
+ 0x3455, 0x0558,
+ 0x345a, 0x1ea3,
+ 0x345b, 0x055e,
+ 0x345c, 0x1ea4,
+ 0x345d, 0x0560,
+ 0x346d, 0x1ea5,
+ 0x346e, 0x0571,
+ 0x346f, 0x1ea6,
+ 0x3470, 0x0573,
+ 0x3478, 0x1ea7,
+ 0x3479, 0x057c,
+ 0x347b, 0x1ea8,
+ 0x347c, 0x057f,
+ 0x3521, 0x0582,
+ 0x3523, 0x1ea9,
+ 0x3524, 0x0585,
+ 0x3525, 0x1eaa,
+ 0x3529, 0x058a,
+ 0x352c, 0x1eae,
+ 0x352d, 0x058e,
+ 0x352e, 0x1eaf,
+ 0x3530, 0x0591,
+ 0x3531, 0x1eb1,
+ 0x3536, 0x0597,
+ 0x3537, 0x1eb6,
+ 0x3538, 0x0599,
+ 0x353a, 0x1eb7,
+ 0x353d, 0x059e,
+ 0x3546, 0x1eba,
+ 0x3547, 0x05a8,
+ 0x354b, 0x1ebb,
+ 0x354c, 0x05ad,
+ 0x3550, 0x1ebc,
+ 0x3551, 0x05b2,
+ 0x3553, 0x1ebd,
+ 0x3554, 0x05b5,
+ 0x355d, 0x1ebe,
+ 0x3560, 0x05c1,
+ 0x3563, 0x1ec1,
+ 0x3564, 0x05c5,
+ 0x3566, 0x1ec2,
+ 0x3568, 0x05c9,
+ 0x356d, 0x1ec4,
+ 0x356e, 0x05cf,
+ 0x3576, 0x1ec5,
+ 0x3578, 0x05d9,
+ 0x357d, 0x1ec7,
+ 0x357e, 0x05df,
+ 0x3621, 0x05e0,
+ 0x3624, 0x1ec8,
+ 0x3626, 0x05e5,
+ 0x3627, 0x1eca,
+ 0x3628, 0x05e7,
+ 0x3629, 0x1ecb,
+ 0x362a, 0x05e9,
+ 0x362b, 0x1ecc,
+ 0x362c, 0x05eb,
+ 0x362f, 0x1ecd,
+ 0x3631, 0x05f0,
+ 0x3633, 0x1ecf,
+ 0x3634, 0x05f3,
+ 0x3637, 0x1ed0,
+ 0x3638, 0x05f7,
+ 0x363f, 0x1ed1,
+ 0x3642, 0x0601,
+ 0x3644, 0x1ed4,
+ 0x3645, 0x0604,
+ 0x3646, 0x1ed5,
+ 0x3647, 0x0606,
+ 0x364d, 0x1ed6,
+ 0x364e, 0x060d,
+ 0x364f, 0x1ed7,
+ 0x3651, 0x0610,
+ 0x3653, 0x1ed9,
+ 0x3655, 0x0614,
+ 0x3656, 0x1edb,
+ 0x3657, 0x0616,
+ 0x3659, 0x1edc,
+ 0x365a, 0x0619,
+ 0x365b, 0x1edd,
+ 0x365c, 0x061b,
+ 0x3661, 0x1ede,
+ 0x3662, 0x0621,
+ 0x3669, 0x1edf,
+ 0x366a, 0x0629,
+ 0x366c, 0x1ee0,
+ 0x366d, 0x062c,
+ 0x366e, 0x1ee1,
+ 0x3670, 0x062f,
+ 0x3671, 0x1ee3,
+ 0x3672, 0x0631,
+ 0x3676, 0x1ee4,
+ 0x3677, 0x0636,
+ 0x3679, 0x1ee5,
+ 0x367a, 0x0639,
+ 0x367b, 0x1ee6,
+ 0x367d, 0x063c,
+ 0x3721, 0x1ee8,
+ 0x3724, 0x0641,
+ 0x3727, 0x1eeb,
+ 0x3728, 0x0645,
+ 0x372f, 0x1eec,
+ 0x3731, 0x064e,
+ 0x3733, 0x1eee,
+ 0x3734, 0x0651,
+ 0x3736, 0x1eef,
+ 0x3738, 0x0655,
+ 0x3739, 0x1ef1,
+ 0x373a, 0x0657,
+ 0x3743, 0x1ef2,
+ 0x3745, 0x0662,
+ 0x3749, 0x1ef4,
+ 0x374a, 0x0667,
+ 0x374c, 0x1ef5,
+ 0x374d, 0x066a,
+ 0x374f, 0x1ef6,
+ 0x3750, 0x066d,
+ 0x3751, 0x1ef7,
+ 0x3752, 0x066f,
+ 0x3757, 0x1ef8,
+ 0x3759, 0x0676,
+ 0x375c, 0x1efa,
+ 0x375d, 0x067a,
+ 0x375f, 0x1efb,
+ 0x3762, 0x067f,
+ 0x3763, 0x1efe,
+ 0x3764, 0x0681,
+ 0x3766, 0x1eff,
+ 0x3769, 0x0686,
+ 0x376b, 0x1f02,
+ 0x376e, 0x068b,
+ 0x376f, 0x1f05,
+ 0x3770, 0x068d,
+ 0x3774, 0x1f06,
+ 0x3775, 0x0692,
+ 0x3778, 0x1f07,
+ 0x3779, 0x0696,
+ 0x3821, 0x069c,
+ 0x3827, 0x1f08,
+ 0x3829, 0x06a4,
+ 0x3833, 0x1f0a,
+ 0x3835, 0x06b0,
+ 0x383a, 0x1f0c,
+ 0x383b, 0x06b6,
+ 0x383c, 0x1f0d,
+ 0x383d, 0x06b8,
+ 0x383e, 0x1f0e,
+ 0x3840, 0x06bb,
+ 0x3843, 0x1f10,
+ 0x3844, 0x06bf,
+ 0x3846, 0x1f11,
+ 0x3848, 0x06c3,
+ 0x3849, 0x1f13,
+ 0x384a, 0x06c5,
+ 0x384f, 0x1f14,
+ 0x3850, 0x06cb,
+ 0x3853, 0x1f15,
+ 0x3857, 0x06d2,
+ 0x3859, 0x1f19,
+ 0x385b, 0x06d6,
+ 0x3864, 0x1f1b,
+ 0x3865, 0x06e0,
+ 0x3869, 0x1f1c,
+ 0x386a, 0x06e5,
+ 0x386b, 0x1f1d,
+ 0x386c, 0x06e7,
+ 0x3873, 0x1f1e,
+ 0x3874, 0x06ef,
+ 0x3875, 0x1f1f,
+ 0x3877, 0x06f2,
+ 0x3878, 0x1f21,
+ 0x3879, 0x06f4,
+ 0x3921, 0x06fa,
+ 0x3928, 0x1f22,
+ 0x3929, 0x0702,
+ 0x392e, 0x1f23,
+ 0x392f, 0x0708,
+ 0x3931, 0x1f24,
+ 0x3932, 0x070b,
+ 0x3933, 0x1f25,
+ 0x3934, 0x070d,
+ 0x3935, 0x1f26,
+ 0x3936, 0x070f,
+ 0x3939, 0x1f27,
+ 0x393b, 0x0714,
+ 0x3946, 0x1f29,
+ 0x3947, 0x0720,
+ 0x394b, 0x1f2a,
+ 0x394c, 0x0725,
+ 0x3950, 0x1f2b,
+ 0x3951, 0x072a,
+ 0x3958, 0x1f2c,
+ 0x3959, 0x0732,
+ 0x395b, 0x1f2d,
+ 0x395c, 0x0735,
+ 0x395d, 0x1f2e,
+ 0x395e, 0x0737,
+ 0x395f, 0x1f2f,
+ 0x3960, 0x0739,
+ 0x3961, 0x1f30,
+ 0x3962, 0x073b,
+ 0x3963, 0x1f31,
+ 0x3964, 0x073d,
+ 0x3966, 0x1f32,
+ 0x3967, 0x0740,
+ 0x3969, 0x1f33,
+ 0x396d, 0x0746,
+ 0x396e, 0x1f37,
+ 0x396f, 0x0748,
+ 0x3971, 0x1f38,
+ 0x3972, 0x074b,
+ 0x3973, 0x1f39,
+ 0x3976, 0x074f,
+ 0x3978, 0x1f3c,
+ 0x3979, 0x0752,
+ 0x397a, 0x1f3d,
+ 0x397b, 0x0754,
+ 0x397d, 0x1f3e,
+ 0x397e, 0x0757,
+ 0x3a21, 0x0758,
+ 0x3a27, 0x1f3f,
+ 0x3a28, 0x075f,
+ 0x3a2b, 0x1f40,
+ 0x3a2c, 0x0763,
+ 0x3a3a, 0x1f41,
+ 0x3a3b, 0x0772,
+ 0x3a45, 0x1f42,
+ 0x3a46, 0x077d,
+ 0x3a52, 0x1f43,
+ 0x3a53, 0x078a,
+ 0x3a57, 0x1f44,
+ 0x3a59, 0x0790,
+ 0x3a64, 0x1f46,
+ 0x3a65, 0x079c,
+ 0x3a68, 0x1f47,
+ 0x3a69, 0x07a0,
+ 0x3a6c, 0x1f48,
+ 0x3a6d, 0x07a4,
+ 0x3a73, 0x15e5,
+ 0x3a74, 0x07ab,
+ 0x3a78, 0x1f49,
+ 0x3a79, 0x07b0,
+ 0x3b21, 0x07b6,
+ 0x3b24, 0x1f4a,
+ 0x3b25, 0x07ba,
+ 0x3b26, 0x1f4b,
+ 0x3b27, 0x07bc,
+ 0x3b29, 0x1f4c,
+ 0x3b2b, 0x07c0,
+ 0x3b2d, 0x1f4e,
+ 0x3b2f, 0x07c4,
+ 0x3b30, 0x1f50,
+ 0x3b31, 0x07c6,
+ 0x3b33, 0x1f51,
+ 0x3b34, 0x07c9,
+ 0x3b35, 0x1f52,
+ 0x3b38, 0x07cd,
+ 0x3b39, 0x1f55,
+ 0x3b3b, 0x07d0,
+ 0x3b51, 0x1f57,
+ 0x3b52, 0x07e7,
+ 0x3b53, 0x1f58,
+ 0x3b55, 0x07ea,
+ 0x3b5f, 0x1f5a,
+ 0x3b68, 0x07fd,
+ 0x3b6b, 0x1f63,
+ 0x3b6c, 0x0801,
+ 0x3b71, 0x1f64,
+ 0x3b72, 0x0807,
+ 0x3b75, 0x1f65,
+ 0x3b78, 0x080d,
+ 0x3b7a, 0x1f68,
+ 0x3b7b, 0x0810,
+ 0x3b7d, 0x1f69,
+ 0x3b7e, 0x0813,
+ 0x3c21, 0x0814,
+ 0x3c22, 0x1f6a,
+ 0x3c23, 0x0816,
+ 0x3c25, 0x1f6b,
+ 0x3c27, 0x081a,
+ 0x3c28, 0x1f6d,
+ 0x3c2a, 0x081d,
+ 0x3c2b, 0x1f6f,
+ 0x3c2c, 0x081f,
+ 0x3c2d, 0x1f70,
+ 0x3c2e, 0x0821,
+ 0x3c36, 0x1f71,
+ 0x3c39, 0x082c,
+ 0x3c3b, 0x1f74,
+ 0x3c3c, 0x082f,
+ 0x3c41, 0x1f75,
+ 0x3c42, 0x0835,
+ 0x3c43, 0x1f76,
+ 0x3c44, 0x0837,
+ 0x3c46, 0x1f77,
+ 0x3c48, 0x083b,
+ 0x3c4a, 0x1f79,
+ 0x3c4b, 0x083e,
+ 0x3c4c, 0x1f7a,
+ 0x3c4e, 0x0841,
+ 0x3c50, 0x1f7c,
+ 0x3c51, 0x0844,
+ 0x3c54, 0x1f7d,
+ 0x3c57, 0x084a,
+ 0x3c58, 0x1f80,
+ 0x3c59, 0x084c,
+ 0x3c5b, 0x1f81,
+ 0x3c5c, 0x084f,
+ 0x3c5d, 0x1f82,
+ 0x3c5e, 0x0851,
+ 0x3c5f, 0x1f83,
+ 0x3c62, 0x0855,
+ 0x3c63, 0x1f86,
+ 0x3c65, 0x0858,
+ 0x3c68, 0x1f88,
+ 0x3c69, 0x085c,
+ 0x3c6a, 0x1f89,
+ 0x3c6d, 0x0860,
+ 0x3c6f, 0x1f8c,
+ 0x3c74, 0x0867,
+ 0x3c76, 0x1f91,
+ 0x3c7d, 0x0870,
+ 0x3d21, 0x0872,
+ 0x3d22, 0x1f98,
+ 0x3d28, 0x0879,
+ 0x3d2b, 0x1f9e,
+ 0x3d2d, 0x087e,
+ 0x3d2f, 0x1fa0,
+ 0x3d33, 0x0884,
+ 0x3d34, 0x1fa4,
+ 0x3d35, 0x0886,
+ 0x3d3a, 0x1fa5,
+ 0x3d3b, 0x088c,
+ 0x3d3d, 0x1fa6,
+ 0x3d40, 0x0891,
+ 0x3d41, 0x1fa9,
+ 0x3d45, 0x0896,
+ 0x3d48, 0x1fad,
+ 0x3d4b, 0x089c,
+ 0x3d4e, 0x1fb0,
+ 0x3d50, 0x08a1,
+ 0x3d57, 0x1fb2,
+ 0x3d58, 0x08a9,
+ 0x3d5a, 0x1fb3,
+ 0x3d5b, 0x08ac,
+ 0x3d60, 0x1fb4,
+ 0x3d62, 0x08b3,
+ 0x3d6b, 0x1fb6,
+ 0x3d6c, 0x08bd,
+ 0x3d74, 0x1fb7,
+ 0x3d79, 0x08ca,
+ 0x3d7d, 0x1fbc,
+ 0x3d7e, 0x08cf,
+ 0x3e21, 0x1fbd,
+ 0x3e23, 0x08d2,
+ 0x3e25, 0x1fbf,
+ 0x3e26, 0x08d5,
+ 0x3e28, 0x1fc0,
+ 0x3e29, 0x08d8,
+ 0x3e2a, 0x1fc1,
+ 0x3e2b, 0x08da,
+ 0x3e2d, 0x1fc2,
+ 0x3e2e, 0x08dd,
+ 0x3e31, 0x1fc3,
+ 0x3e32, 0x08e1,
+ 0x3e35, 0x1fc4,
+ 0x3e38, 0x08e7,
+ 0x3e3a, 0x1fc7,
+ 0x3e3b, 0x08ea,
+ 0x3e40, 0x1fc8,
+ 0x3e41, 0x08f0,
+ 0x3e49, 0x1fc9,
+ 0x3e4a, 0x08f9,
+ 0x3e54, 0x1fca,
+ 0x3e55, 0x0904,
+ 0x3e59, 0x1fcb,
+ 0x3e5a, 0x0909,
+ 0x3e5d, 0x1fcc,
+ 0x3e5e, 0x090d,
+ 0x3e62, 0x1fcd,
+ 0x3e63, 0x0912,
+ 0x3e65, 0x1fce,
+ 0x3e66, 0x0915,
+ 0x3e67, 0x1fcf,
+ 0x3e68, 0x0917,
+ 0x3e69, 0x1fd0,
+ 0x3e6a, 0x0919,
+ 0x3e6e, 0x1fd1,
+ 0x3e6f, 0x091e,
+ 0x3e75, 0x1fd2,
+ 0x3e76, 0x0925,
+ 0x3e77, 0x1fd3,
+ 0x3e79, 0x0928,
+ 0x3e7b, 0x1fd5,
+ 0x3e7d, 0x092c,
+ 0x3f21, 0x092e,
+ 0x3f25, 0x1fd7,
+ 0x3f26, 0x0933,
+ 0x3f2a, 0x1fd8,
+ 0x3f2b, 0x0938,
+ 0x3f2d, 0x1fd9,
+ 0x3f2e, 0x093b,
+ 0x3f45, 0x1fda,
+ 0x3f46, 0x0953,
+ 0x3f47, 0x1fdb,
+ 0x3f48, 0x0955,
+ 0x3f4e, 0x1fdc,
+ 0x3f4f, 0x095c,
+ 0x3f51, 0x1fdd,
+ 0x3f53, 0x0960,
+ 0x3f59, 0x1fdf,
+ 0x3f5a, 0x0967,
+ 0x3f62, 0x1fe0,
+ 0x3f65, 0x0972,
+ 0x3f69, 0x1fe3,
+ 0x3f6a, 0x0977,
+ 0x3f6b, 0x1fe4,
+ 0x3f6c, 0x0979,
+ 0x3f6d, 0x1fe5,
+ 0x3f6e, 0x097b,
+ 0x3f73, 0x1fe6,
+ 0x3f74, 0x0981,
+ 0x3f75, 0x1fe7,
+ 0x3f76, 0x0983,
+ 0x3f77, 0x1fe8,
+ 0x3f78, 0x0985,
+ 0x3f79, 0x1fe9,
+ 0x3f7b, 0x0988,
+ 0x4021, 0x1feb,
+ 0x4022, 0x098d,
+ 0x4023, 0x1fec,
+ 0x4024, 0x098f,
+ 0x4029, 0x1fed,
+ 0x402a, 0x0995,
+ 0x402b, 0x1fee,
+ 0x402c, 0x0997,
+ 0x402f, 0x1fef,
+ 0x4031, 0x099c,
+ 0x4033, 0x1ff1,
+ 0x4037, 0x09a2,
+ 0x4038, 0x1ff5,
+ 0x4045, 0x09b0,
+ 0x404c, 0x2002,
+ 0x404e, 0x09b9,
+ 0x4054, 0x2004,
+ 0x4055, 0x09c0,
+ 0x4056, 0x2005,
+ 0x4057, 0x09c2,
+ 0x4058, 0x2006,
+ 0x4059, 0x09c4,
+ 0x405d, 0x2007,
+ 0x405e, 0x09c9,
+ 0x4060, 0x2008,
+ 0x4061, 0x09cc,
+ 0x4069, 0x2009,
+ 0x406a, 0x09d5,
+ 0x406b, 0x200a,
+ 0x406d, 0x09d8,
+ 0x406f, 0x200c,
+ 0x4072, 0x09dd,
+ 0x4076, 0x200f,
+ 0x407b, 0x09e6,
+ 0x4121, 0x09ea,
+ 0x4124, 0x2014,
+ 0x4126, 0x09ef,
+ 0x4129, 0x2016,
+ 0x412e, 0x09f7,
+ 0x412f, 0x201b,
+ 0x4139, 0x0a02,
+ 0x413d, 0x2025,
+ 0x413f, 0x0a08,
+ 0x4142, 0x2027,
+ 0x4143, 0x0a0c,
+ 0x4146, 0x2028,
+ 0x4147, 0x0a10,
+ 0x4149, 0x2029,
+ 0x414a, 0x0a13,
+ 0x414d, 0x202a,
+ 0x414e, 0x0a17,
+ 0x4154, 0x202b,
+ 0x4155, 0x0a1e,
+ 0x4159, 0x202c,
+ 0x415c, 0x0a25,
+ 0x415e, 0x202f,
+ 0x415f, 0x0a28,
+ 0x4164, 0x2030,
+ 0x4166, 0x0a2f,
+ 0x4169, 0x2032,
+ 0x416a, 0x0a33,
+ 0x416b, 0x2033,
+ 0x416d, 0x0a36,
+ 0x4173, 0x2035,
+ 0x4174, 0x0a3d,
+ 0x4175, 0x2036,
+ 0x4176, 0x0a3f,
+ 0x417a, 0x2037,
+ 0x417e, 0x0a47,
+ 0x4221, 0x0a48,
+ 0x4222, 0x203b,
+ 0x4229, 0x0a50,
+ 0x422b, 0x2042,
+ 0x4234, 0x0a5b,
+ 0x4238, 0x204b,
+ 0x4239, 0x0a60,
+ 0x423c, 0x204c,
+ 0x423e, 0x0a65,
+ 0x423f, 0x204e,
+ 0x4240, 0x0a67,
+ 0x4241, 0x204f,
+ 0x4242, 0x0a69,
+ 0x4245, 0x2050,
+ 0x4248, 0x0a6f,
+ 0x424b, 0x2053,
+ 0x4251, 0x0a78,
+ 0x4252, 0x2059,
+ 0x4253, 0x0a7a,
+ 0x4255, 0x205a,
+ 0x425d, 0x0a84,
+ 0x425e, 0x2062,
+ 0x4263, 0x0a8a,
+ 0x4266, 0x2067,
+ 0x4269, 0x0a90,
+ 0x426a, 0x206a,
+ 0x426f, 0x0a96,
+ 0x4270, 0x206f,
+ 0x4271, 0x0a98,
+ 0x4272, 0x2070,
+ 0x4276, 0x0a9d,
+ 0x4277, 0x2074,
+ 0x427b, 0x0aa2,
+ 0x4321, 0x2078,
+ 0x4322, 0x0aa7,
+ 0x432a, 0x2079,
+ 0x432b, 0x0ab0,
+ 0x432d, 0x207a,
+ 0x432e, 0x0ab3,
+ 0x4333, 0x207b,
+ 0x4334, 0x1df9,
+ 0x4335, 0x0aba,
+ 0x433e, 0x207c,
+ 0x433f, 0x0ac4,
+ 0x4345, 0x207d,
+ 0x4348, 0x0acd,
+ 0x434c, 0x2080,
+ 0x434d, 0x0ad2,
+ 0x434e, 0x2081,
+ 0x434f, 0x0ad4,
+ 0x4355, 0x2082,
+ 0x4357, 0x0adc,
+ 0x4359, 0x2084,
+ 0x435a, 0x0adf,
+ 0x4360, 0x2085,
+ 0x4361, 0x0ae6,
+ 0x4365, 0x2086,
+ 0x4366, 0x0aeb,
+ 0x436d, 0x2087,
+ 0x436e, 0x0af3,
+ 0x4370, 0x2088,
+ 0x4371, 0x0af6,
+ 0x4375, 0x2089,
+ 0x4377, 0x0afc,
+ 0x4379, 0x208b,
+ 0x437b, 0x0b00,
+ 0x437d, 0x208d,
+ 0x437e, 0x0b03,
+ 0x4421, 0x0b04,
+ 0x4431, 0x208e,
+ 0x4432, 0x0b15,
+ 0x4436, 0x208f,
+ 0x4437, 0x0b1a,
+ 0x4446, 0x2090,
+ 0x4447, 0x0b2a,
+ 0x4449, 0x2091,
+ 0x444a, 0x0b2d,
+ 0x4451, 0x2092,
+ 0x4452, 0x0b35,
+ 0x4453, 0x2093,
+ 0x4457, 0x0b3a,
+ 0x4459, 0x2097,
+ 0x445a, 0x0b3d,
+ 0x4462, 0x2098,
+ 0x4463, 0x0b46,
+ 0x4465, 0x2099,
+ 0x4466, 0x0b49,
+ 0x446c, 0x209a,
+ 0x446d, 0x0b50,
+ 0x4470, 0x209b,
+ 0x4472, 0x0b55,
+ 0x4474, 0x209d,
+ 0x4475, 0x0b58,
+ 0x4476, 0x209e,
+ 0x4479, 0x0b5c,
+ 0x447b, 0x20a1,
+ 0x447d, 0x0b60,
+ 0x447e, 0x20a3,
+ 0x4521, 0x20a4,
+ 0x4523, 0x0b64,
+ 0x4525, 0x20a6,
+ 0x452a, 0x0b6b,
+ 0x4531, 0x20ab,
+ 0x4532, 0x0b73,
+ 0x4535, 0x20ac,
+ 0x4536, 0x0b77,
+ 0x4537, 0x20ad,
+ 0x453a, 0x0b7b,
+ 0x453b, 0x20b0,
+ 0x453c, 0x0b7d,
+ 0x453d, 0x20b1,
+ 0x453e, 0x0b7f,
+ 0x454c, 0x20b2,
+ 0x454d, 0x0b8e,
+ 0x4553, 0x20b3,
+ 0x4554, 0x0b95,
+ 0x4562, 0x20b4,
+ 0x4563, 0x0ba4,
+ 0x4567, 0x20b5,
+ 0x4568, 0x0ba9,
+ 0x4574, 0x20b6,
+ 0x4575, 0x0bb6,
+ 0x4621, 0x0bc0,
+ 0x462d, 0x20b7,
+ 0x462f, 0x0bce,
+ 0x4635, 0x20b9,
+ 0x4637, 0x0bd6,
+ 0x463b, 0x20bb,
+ 0x463c, 0x0bdb,
+ 0x463e, 0x20bc,
+ 0x463f, 0x0bde,
+ 0x4640, 0x20bd,
+ 0x4641, 0x0be0,
+ 0x4643, 0x20be,
+ 0x4645, 0x0be4,
+ 0x464b, 0x20c0,
+ 0x464e, 0x0bed,
+ 0x4653, 0x20c3,
+ 0x4654, 0x0bf3,
+ 0x4657, 0x20c4,
+ 0x4658, 0x0bf7,
+ 0x466a, 0x20c5,
+ 0x466c, 0x0c0b,
+ 0x466f, 0x20c7,
+ 0x4670, 0x0c0f,
+ 0x4671, 0x20c8,
+ 0x4672, 0x0c11,
+ 0x4674, 0x20c9,
+ 0x4675, 0x0c14,
+ 0x4678, 0x20ca,
+ 0x4679, 0x0c18,
+ 0x467d, 0x20cb,
+ 0x467e, 0x0c1d,
+ 0x4721, 0x0c1e,
+ 0x4723, 0x20cc,
+ 0x4724, 0x0c21,
+ 0x4725, 0x20cd,
+ 0x4727, 0x0c24,
+ 0x4728, 0x20cf,
+ 0x472a, 0x0c27,
+ 0x472b, 0x20d1,
+ 0x472c, 0x0c29,
+ 0x472e, 0x20d2,
+ 0x4730, 0x0c2d,
+ 0x4733, 0x20d4,
+ 0x4736, 0x0c33,
+ 0x4739, 0x20d7,
+ 0x473b, 0x0c38,
+ 0x473d, 0x20d9,
+ 0x473f, 0x0c3c,
+ 0x4740, 0x20db,
+ 0x4741, 0x0c3e,
+ 0x4742, 0x20dc,
+ 0x4743, 0x0c40,
+ 0x4745, 0x20dd,
+ 0x4746, 0x0c43,
+ 0x4747, 0x20de,
+ 0x4749, 0x0c46,
+ 0x474c, 0x20e0,
+ 0x474d, 0x0c4a,
+ 0x474f, 0x20e1,
+ 0x4750, 0x0c4d,
+ 0x4754, 0x20e2,
+ 0x4756, 0x0c53,
+ 0x4757, 0x20e4,
+ 0x4758, 0x0c55,
+ 0x475e, 0x20e5,
+ 0x475f, 0x0c5c,
+ 0x4761, 0x20e6,
+ 0x4764, 0x0c61,
+ 0x476a, 0x20e9,
+ 0x476f, 0x0c6c,
+ 0x4777, 0x20ee,
+ 0x4779, 0x0c76,
+ 0x477b, 0x20f0,
+ 0x477c, 0x0c79,
+ 0x477d, 0x20f1,
+ 0x477e, 0x0c7b,
+ 0x4821, 0x0c7c,
+ 0x4823, 0x20f2,
+ 0x4824, 0x0c7f,
+ 0x4827, 0x20f3,
+ 0x4829, 0x0c84,
+ 0x4830, 0x20f5,
+ 0x4831, 0x0c8c,
+ 0x4835, 0x20f6,
+ 0x4836, 0x0c91,
+ 0x4837, 0x20f7,
+ 0x4838, 0x0c93,
+ 0x4843, 0x20f8,
+ 0x4847, 0x0ca2,
+ 0x4848, 0x20fc,
+ 0x4849, 0x0ca4,
+ 0x484d, 0x20fd,
+ 0x484e, 0x0ca9,
+ 0x484f, 0x20fe,
+ 0x4850, 0x0cab,
+ 0x4852, 0x20ff,
+ 0x4853, 0x0cae,
+ 0x4859, 0x2100,
+ 0x485a, 0x0cb5,
+ 0x485e, 0x2101,
+ 0x485f, 0x0cba,
+ 0x486d, 0x2102,
+ 0x486e, 0x0cc9,
+ 0x4871, 0x2103,
+ 0x4874, 0x0ccf,
+ 0x4877, 0x2106,
+ 0x4879, 0x0cd4,
+ 0x487a, 0x2108,
+ 0x487b, 0x0cd6,
+ 0x487c, 0x2109,
+ 0x487d, 0x0cd8,
+ 0x4921, 0x210a,
+ 0x4922, 0x0cdb,
+ 0x4925, 0x210b,
+ 0x4926, 0x0cdf,
+ 0x4927, 0x210c,
+ 0x4929, 0x0ce2,
+ 0x492c, 0x210e,
+ 0x492d, 0x0ce6,
+ 0x4931, 0x210f,
+ 0x4932, 0x0ceb,
+ 0x4934, 0x2110,
+ 0x4935, 0x0cee,
+ 0x4938, 0x2111,
+ 0x493a, 0x0cf3,
+ 0x4941, 0x2113,
+ 0x4943, 0x0cfc,
+ 0x4944, 0x2115,
+ 0x4945, 0x0cfe,
+ 0x4949, 0x2116,
+ 0x494a, 0x0d03,
+ 0x494b, 0x2117,
+ 0x494c, 0x0d05,
+ 0x494d, 0x2118,
+ 0x494e, 0x0d07,
+ 0x4955, 0x2119,
+ 0x4956, 0x0d0f,
+ 0x495c, 0x211a,
+ 0x495d, 0x0d16,
+ 0x495e, 0x211b,
+ 0x495f, 0x0d18,
+ 0x4961, 0x211c,
+ 0x4962, 0x0d1b,
+ 0x4963, 0x211d,
+ 0x4964, 0x0d1d,
+ 0x4965, 0x211e,
+ 0x4966, 0x0d1f,
+ 0x4968, 0x211f,
+ 0x4969, 0x0d22,
+ 0x4970, 0x2120,
+ 0x4971, 0x0d2a,
+ 0x4973, 0x2121,
+ 0x4975, 0x0d2e,
+ 0x4976, 0x2123,
+ 0x4977, 0x0d30,
+ 0x4978, 0x2124,
+ 0x497a, 0x0d33,
+ 0x497e, 0x2126,
+ 0x4a21, 0x0d38,
+ 0x4a24, 0x2127,
+ 0x4a27, 0x0d3e,
+ 0x4a28, 0x212a,
+ 0x4a29, 0x0d40,
+ 0x4a2a, 0x212b,
+ 0x4a2c, 0x0d43,
+ 0x4a31, 0x212d,
+ 0x4a32, 0x0d49,
+ 0x4a34, 0x212e,
+ 0x4a37, 0x0d4e,
+ 0x4a3b, 0x2131,
+ 0x4a3c, 0x0d53,
+ 0x4a46, 0x2132,
+ 0x4a47, 0x0d5e,
+ 0x4a4a, 0x2133,
+ 0x4a4b, 0x0d62,
+ 0x4a4d, 0x2134,
+ 0x4a4f, 0x0d66,
+ 0x4a53, 0x2136,
+ 0x4a55, 0x0d6c,
+ 0x4a59, 0x2138,
+ 0x4a5a, 0x0d71,
+ 0x4a5e, 0x2139,
+ 0x4a5f, 0x0d76,
+ 0x4a60, 0x213a,
+ 0x4a61, 0x0d78,
+ 0x4a64, 0x213b,
+ 0x4a65, 0x0d7c,
+ 0x4a69, 0x213c,
+ 0x4a6b, 0x0d82,
+ 0x4a74, 0x213e,
+ 0x4a76, 0x0d8d,
+ 0x4a77, 0x2140,
+ 0x4a78, 0x0d8f,
+ 0x4a7a, 0x2141,
+ 0x4a7b, 0x0d92,
+ 0x4a7d, 0x2142,
+ 0x4a7e, 0x0d95,
+ 0x4b21, 0x0d96,
+ 0x4b27, 0x2143,
+ 0x4b28, 0x0d9d,
+ 0x4b2b, 0x2144,
+ 0x4b2c, 0x0da1,
+ 0x4b2d, 0x2145,
+ 0x4b2e, 0x0da3,
+ 0x4b33, 0x2146,
+ 0x4b34, 0x0da9,
+ 0x4b35, 0x2147,
+ 0x4b37, 0x0dac,
+ 0x4b38, 0x2149,
+ 0x4b39, 0x0dae,
+ 0x4b3f, 0x214a,
+ 0x4b40, 0x0db5,
+ 0x4b47, 0x214b,
+ 0x4b48, 0x0dbd,
+ 0x4b49, 0x214c,
+ 0x4b4d, 0x0dc2,
+ 0x4b4f, 0x2150,
+ 0x4b51, 0x0dc6,
+ 0x4b53, 0x2152,
+ 0x4b54, 0x0dc9,
+ 0x4b55, 0x2153,
+ 0x4b56, 0x0dcb,
+ 0x4b5f, 0x2154,
+ 0x4b61, 0x0dd6,
+ 0x4b64, 0x2156,
+ 0x4b65, 0x0dda,
+ 0x4b66, 0x2157,
+ 0x4b68, 0x0ddd,
+ 0x4b6a, 0x2159,
+ 0x4b6b, 0x0de0,
+ 0x4b6f, 0x215a,
+ 0x4b71, 0x0de6,
+ 0x4b75, 0x215c,
+ 0x4b77, 0x0dec,
+ 0x4b78, 0x215e,
+ 0x4b79, 0x0dee,
+ 0x4c21, 0x215f,
+ 0x4c23, 0x0df6,
+ 0x4c28, 0x2161,
+ 0x4c29, 0x0dfc,
+ 0x4c2c, 0x2162,
+ 0x4c2d, 0x0e00,
+ 0x4c2f, 0x2163,
+ 0x4c34, 0x0e07,
+ 0x4c37, 0x2168,
+ 0x4c39, 0x0e0c,
+ 0x4c3e, 0x216a,
+ 0x4c3f, 0x0e12,
+ 0x4c40, 0x216b,
+ 0x4c41, 0x0e14,
+ 0x4c4c, 0x216c,
+ 0x4c4d, 0x0e20,
+ 0x4c4e, 0x216d,
+ 0x4c4f, 0x0e22,
+ 0x4c50, 0x216e,
+ 0x4c51, 0x0e24,
+ 0x4c56, 0x216f,
+ 0x4c57, 0x0e2a,
+ 0x4c5a, 0x2170,
+ 0x4c5b, 0x0e2e,
+ 0x4c5c, 0x2171,
+ 0x4c5d, 0x0e30,
+ 0x4c60, 0x2172,
+ 0x4c61, 0x0e34,
+ 0x4c62, 0x2173,
+ 0x4c63, 0x0e36,
+ 0x4c65, 0x2174,
+ 0x4c66, 0x0e39,
+ 0x4c75, 0x2175,
+ 0x4c76, 0x0e49,
+ 0x4c79, 0x2176,
+ 0x4c7b, 0x0e4e,
+ 0x4c7c, 0x2178,
+ 0x4d21, 0x0e52,
+ 0x4d2d, 0x217b,
+ 0x4d2e, 0x0e5f,
+ 0x4d33, 0x217c,
+ 0x4d34, 0x0e65,
+ 0x4d37, 0x217d,
+ 0x4d38, 0x0e69,
+ 0x4d3c, 0x217e,
+ 0x4d3d, 0x0e6e,
+ 0x4d3f, 0x217f,
+ 0x4d40, 0x0e71,
+ 0x4d45, 0x2180,
+ 0x4d46, 0x0e77,
+ 0x4d47, 0x2181,
+ 0x4d48, 0x0e79,
+ 0x4d52, 0x2182,
+ 0x4d53, 0x0e84,
+ 0x4d54, 0x2183,
+ 0x4d57, 0x0e88,
+ 0x4d5d, 0x2186,
+ 0x4d5e, 0x0e8f,
+ 0x4d60, 0x2187,
+ 0x4d61, 0x0e92,
+ 0x4d64, 0x2188,
+ 0x4d66, 0x0e97,
+ 0x4d67, 0x218a,
+ 0x4d68, 0x0e99,
+ 0x4d72, 0x218b,
+ 0x4d73, 0x0ea4,
+ 0x4d78, 0x218c,
+ 0x4d79, 0x0eaa,
+ 0x4e21, 0x0eb0,
+ 0x4e24, 0x218d,
+ 0x4e26, 0x0eb5,
+ 0x4e27, 0x218f,
+ 0x4e28, 0x0eb7,
+ 0x4e2a, 0x2190,
+ 0x4e2e, 0x0ebd,
+ 0x4e30, 0x2194,
+ 0x4e32, 0x0ec1,
+ 0x4e33, 0x2196,
+ 0x4e34, 0x0ec3,
+ 0x4e3d, 0x2197,
+ 0x4e3e, 0x0ecd,
+ 0x4e40, 0x2198,
+ 0x4e41, 0x0ed0,
+ 0x4e45, 0x2199,
+ 0x4e47, 0x0ed6,
+ 0x4e48, 0x219b,
+ 0x4e49, 0x0ed8,
+ 0x4e4a, 0x219c,
+ 0x4e4b, 0x0eda,
+ 0x4e4e, 0x219d,
+ 0x4e52, 0x0ee1,
+ 0x4e58, 0x21a1,
+ 0x4e5b, 0x0eea,
+ 0x4e5c, 0x21a4,
+ 0x4e5d, 0x0eec,
+ 0x4e5e, 0x21a5,
+ 0x4e60, 0x0eef,
+ 0x4e6b, 0x21a7,
+ 0x4e6c, 0x0efb,
+ 0x4e6d, 0x21a8,
+ 0x4e6e, 0x0efd,
+ 0x4e71, 0x21a9,
+ 0x4e72, 0x0f01,
+ 0x4e73, 0x21aa,
+ 0x4e74, 0x0f03,
+ 0x4e7d, 0x21ab,
+ 0x4f21, 0x0f0e,
+ 0x4f2e, 0x21ad,
+ 0x4f2f, 0x0f1c,
+ 0x4f30, 0x21ae,
+ 0x4f31, 0x0f1e,
+ 0x4f33, 0x21af,
+ 0x4f34, 0x0f21,
+ 0x4f37, 0x21b0,
+ 0x4f39, 0x0f26,
+ 0x4f3a, 0x21b2,
+ 0x4f3b, 0x0f28,
+ 0x4f3d, 0x21b3,
+ 0x4f3e, 0x0f2b,
+ 0x4f3f, 0x21b4,
+ 0x4f42, 0x0f2f,
+ 0x4f45, 0x21b7,
+ 0x4f46, 0x0f33,
+ 0x4f47, 0x21b8,
+ 0x4f48, 0x0f35,
+ 0x4f4a, 0x21b9,
+ 0x4f4c, 0x0f39,
+ 0x4f4d, 0x21bb,
+ 0x4f4f, 0x0f3c,
+ 0x4f50, 0x21bd,
+ 0x4f51, 0x0f3e,
+ 0x4f54, 0x21be,
+ 0x4f59, 0x0f46,
+ 0x4f5a, 0x21c3,
+ 0x4f5b, 0x0f48,
+ 0x4f5c, 0x21c4,
+ 0x4f5d, 0x0f4a,
+ 0x4f5f, 0x21c5,
+ 0x4f60, 0x0f4d,
+ 0x4f62, 0x21c6,
+ 0x4f63, 0x0f50,
+ 0x4f67, 0x21c7,
+ 0x4f68, 0x0f55,
+ 0x4f6a, 0x21c8,
+ 0x4f6b, 0x0f58,
+ 0x4f6c, 0x21c9,
+ 0x4f6d, 0x0f5a,
+ 0x4f6e, 0x21ca,
+ 0x4f6f, 0x0f5c,
+ 0x4f74, 0x21cb,
+ 0x4f75, 0x0f62,
+ 0x4f79, 0x21cc,
+ 0x4f7b, 0x0f68,
+ 0x4f7e, 0x21ce,
+ 0x5021, 0x0f6c,
+ 0x5025, 0x21cf,
+ 0x5026, 0x0f71,
+ 0x502d, 0x21d0,
+ 0x502f, 0x0f7a,
+ 0x5032, 0x21d2,
+ 0x5035, 0x0f80,
+ 0x503a, 0x21d5,
+ 0x503c, 0x0f87,
+ 0x503f, 0x21d7,
+ 0x5040, 0x0f8b,
+ 0x5046, 0x21d8,
+ 0x5047, 0x0f92,
+ 0x504b, 0x21d9,
+ 0x504c, 0x0f97,
+ 0x5062, 0x21da,
+ 0x5063, 0x0fae,
+ 0x5065, 0x21db,
+ 0x5066, 0x0fb1,
+ 0x506b, 0x21dc,
+ 0x506c, 0x0fb7,
+ 0x506d, 0x21dd,
+ 0x506e, 0x0fb9,
+ 0x5077, 0x21de,
+ 0x507a, 0x0fc5,
+ 0x507c, 0x21e1,
+ 0x507d, 0x0fc8,
+ 0x5121, 0x21e2,
+ 0x5123, 0x0fcc,
+ 0x5124, 0x21e4,
+ 0x5125, 0x0fce,
+ 0x5127, 0x21e5,
+ 0x5128, 0x0fd1,
+ 0x512b, 0x21e6,
+ 0x512c, 0x0fd5,
+ 0x512f, 0x21e7,
+ 0x5132, 0x0fdb,
+ 0x5135, 0x21ea,
+ 0x5138, 0x0fe1,
+ 0x5139, 0x21ed,
+ 0x513a, 0x0fe3,
+ 0x513b, 0x21ee,
+ 0x513d, 0x0fe6,
+ 0x5146, 0x21f0,
+ 0x5149, 0x0ff2,
+ 0x514b, 0x21f3,
+ 0x514c, 0x0ff5,
+ 0x514e, 0x21f4,
+ 0x5150, 0x0ff9,
+ 0x5155, 0x21f6,
+ 0x5157, 0x1000,
+ 0x515e, 0x21f8,
+ 0x515f, 0x1008,
+ 0x5161, 0x21f9,
+ 0x5163, 0x100c,
+ 0x5168, 0x21fb,
+ 0x516a, 0x1013,
+ 0x516c, 0x21fd,
+ 0x516d, 0x1016,
+ 0x516e, 0x21fe,
+ 0x5170, 0x1019,
+ 0x5171, 0x2200,
+ 0x5172, 0x101b,
+ 0x5174, 0x2201,
+ 0x5175, 0x101e,
+ 0x5177, 0x2202,
+ 0x517a, 0x1023,
+ 0x5221, 0x1028,
+ 0x5222, 0x2205,
+ 0x5223, 0x102a,
+ 0x5225, 0x2206,
+ 0x5226, 0x102d,
+ 0x5229, 0x2207,
+ 0x522a, 0x1031,
+ 0x522f, 0x2208,
+ 0x5230, 0x1037,
+ 0x5233, 0x2209,
+ 0x5234, 0x103b,
+ 0x5235, 0x220a,
+ 0x5237, 0x103e,
+ 0x523d, 0x220c,
+ 0x523e, 0x1045,
+ 0x523f, 0x220d,
+ 0x5240, 0x1047,
+ 0x5243, 0x220e,
+ 0x5244, 0x104b,
+ 0x5245, 0x220f,
+ 0x5246, 0x104d,
+ 0x5247, 0x2210,
+ 0x5248, 0x104f,
+ 0x524f, 0x2211,
+ 0x5250, 0x1057,
+ 0x5255, 0x2212,
+ 0x5256, 0x105d,
+ 0x525a, 0x2213,
+ 0x525b, 0x1062,
+ 0x5264, 0x2214,
+ 0x5266, 0x106d,
+ 0x5268, 0x2216,
+ 0x526c, 0x1073,
+ 0x526f, 0x221a,
+ 0x5270, 0x1077,
+ 0x5271, 0x221b,
+ 0x5272, 0x1079,
+ 0x5275, 0x221c,
+ 0x5276, 0x107d,
+ 0x5278, 0x221d,
+ 0x5279, 0x1080,
+ 0x527b, 0x221e,
+ 0x527c, 0x1083,
+ 0x527e, 0x221f,
+ 0x5321, 0x1086,
+ 0x5323, 0x2220,
+ 0x532d, 0x1092,
+ 0x532e, 0x222a,
+ 0x532f, 0x1094,
+ 0x5331, 0x222b,
+ 0x5332, 0x1097,
+ 0x5334, 0x222c,
+ 0x5337, 0x109c,
+ 0x5338, 0x222f,
+ 0x5339, 0x109e,
+ 0x533b, 0x2230,
+ 0x533c, 0x10a1,
+ 0x5345, 0x2231,
+ 0x5346, 0x10ab,
+ 0x5347, 0x2232,
+ 0x5348, 0x10ad,
+ 0x534a, 0x2233,
+ 0x534d, 0x10b2,
+ 0x5355, 0x2236,
+ 0x5356, 0x10bb,
+ 0x535f, 0x2237,
+ 0x5361, 0x10c6,
+ 0x5363, 0x2239,
+ 0x5364, 0x10c9,
+ 0x5366, 0x223a,
+ 0x5367, 0x10cc,
+ 0x536b, 0x223b,
+ 0x536d, 0x10d2,
+ 0x536f, 0x223d,
+ 0x5370, 0x10d5,
+ 0x5374, 0x223e,
+ 0x5375, 0x10da,
+ 0x537c, 0x223f,
+ 0x537d, 0x10e2,
+ 0x537e, 0x2240,
+ 0x5421, 0x10e4,
+ 0x5424, 0x2241,
+ 0x5425, 0x10e8,
+ 0x5426, 0x2242,
+ 0x5429, 0x10ec,
+ 0x542f, 0x2245,
+ 0x5433, 0x10f6,
+ 0x5435, 0x2249,
+ 0x5437, 0x10fa,
+ 0x5438, 0x224b,
+ 0x5439, 0x10fc,
+ 0x543c, 0x224c,
+ 0x543d, 0x1100,
+ 0x543e, 0x224d,
+ 0x5440, 0x1103,
+ 0x5444, 0x224f,
+ 0x5445, 0x1108,
+ 0x5446, 0x2250,
+ 0x5448, 0x110b,
+ 0x5449, 0x2252,
+ 0x544a, 0x110d,
+ 0x544b, 0x2253,
+ 0x544f, 0x1112,
+ 0x5453, 0x2257,
+ 0x5454, 0x1117,
+ 0x5458, 0x2258,
+ 0x5459, 0x111c,
+ 0x545c, 0x2259,
+ 0x5461, 0x1124,
+ 0x5464, 0x225e,
+ 0x5465, 0x1128,
+ 0x5466, 0x225f,
+ 0x5467, 0x112a,
+ 0x546e, 0x2260,
+ 0x546f, 0x1132,
+ 0x5470, 0x2261,
+ 0x5475, 0x1138,
+ 0x5479, 0x2266,
+ 0x547a, 0x113d,
+ 0x547e, 0x2267,
+ 0x5521, 0x2268,
+ 0x5523, 0x1144,
+ 0x5529, 0x226a,
+ 0x552a, 0x114b,
+ 0x552b, 0x226b,
+ 0x552c, 0x114d,
+ 0x552e, 0x226c,
+ 0x552f, 0x1150,
+ 0x5531, 0x226d,
+ 0x5532, 0x1153,
+ 0x5535, 0x226e,
+ 0x5539, 0x115a,
+ 0x553b, 0x2272,
+ 0x553c, 0x115d,
+ 0x553d, 0x2273,
+ 0x553e, 0x115f,
+ 0x5540, 0x2274,
+ 0x5541, 0x1162,
+ 0x5545, 0x2275,
+ 0x5546, 0x1167,
+ 0x5547, 0x2276,
+ 0x5548, 0x1169,
+ 0x554a, 0x2277,
+ 0x554c, 0x116d,
+ 0x554d, 0x2279,
+ 0x554e, 0x116f,
+ 0x5554, 0x227a,
+ 0x5555, 0x1176,
+ 0x555d, 0x227b,
+ 0x555f, 0x1180,
+ 0x5560, 0x227d,
+ 0x5561, 0x1182,
+ 0x5562, 0x227e,
+ 0x5563, 0x1184,
+ 0x556a, 0x227f,
+ 0x556d, 0x118e,
+ 0x556f, 0x2282,
+ 0x5570, 0x1191,
+ 0x5572, 0x2283,
+ 0x5574, 0x1195,
+ 0x5577, 0x15eb,
+ 0x5578, 0x1199,
+ 0x5621, 0x2285,
+ 0x5625, 0x11a4,
+ 0x562f, 0x2289,
+ 0x5631, 0x11b0,
+ 0x5634, 0x228b,
+ 0x5635, 0x11b4,
+ 0x563b, 0x228c,
+ 0x563c, 0x11bb,
+ 0x563d, 0x228d,
+ 0x563e, 0x11bd,
+ 0x563f, 0x228e,
+ 0x5641, 0x11c0,
+ 0x5644, 0x2290,
+ 0x5645, 0x11c4,
+ 0x564a, 0x2291,
+ 0x564b, 0x11ca,
+ 0x564d, 0x2292,
+ 0x564e, 0x11cd,
+ 0x5653, 0x2293,
+ 0x5654, 0x11d3,
+ 0x5655, 0x2294,
+ 0x5658, 0x11d7,
+ 0x565a, 0x2297,
+ 0x565b, 0x11da,
+ 0x565f, 0x2298,
+ 0x5660, 0x11df,
+ 0x5661, 0x2299,
+ 0x5662, 0x11e1,
+ 0x5665, 0x229a,
+ 0x5666, 0x11e5,
+ 0x5667, 0x229b,
+ 0x5669, 0x11e8,
+ 0x566e, 0x229d,
+ 0x5670, 0x11ef,
+ 0x5672, 0x229f,
+ 0x5673, 0x11f2,
+ 0x5675, 0x22a0,
+ 0x5677, 0x11f6,
+ 0x567c, 0x22a2,
+ 0x5721, 0x11fe,
+ 0x5724, 0x22a5,
+ 0x5725, 0x1202,
+ 0x5728, 0x22a6,
+ 0x572b, 0x1208,
+ 0x572c, 0x22a9,
+ 0x572d, 0x120a,
+ 0x572e, 0x22aa,
+ 0x5732, 0x120f,
+ 0x5733, 0x22ae,
+ 0x5735, 0x1212,
+ 0x5736, 0x22b0,
+ 0x5737, 0x1214,
+ 0x5738, 0x22b1,
+ 0x573d, 0x121a,
+ 0x5747, 0x22b6,
+ 0x5748, 0x1225,
+ 0x574a, 0x22b7,
+ 0x574b, 0x1228,
+ 0x5755, 0x22b8,
+ 0x5756, 0x1233,
+ 0x575b, 0x22b9,
+ 0x575f, 0x123c,
+ 0x5767, 0x22bd,
+ 0x5768, 0x1245,
+ 0x5769, 0x22be,
+ 0x576b, 0x1248,
+ 0x5821, 0x1257,
+ 0x5844, 0x22c0,
+ 0x5845, 0x127b,
+ 0x5847, 0x22c1,
+ 0x5848, 0x127e,
+ 0x5849, 0x22c2,
+ 0x584a, 0x1280,
+ 0x584c, 0x22c3,
+ 0x584e, 0x1284,
+ 0x5850, 0x22c5,
+ 0x5852, 0x1288,
+ 0x5853, 0x22c7,
+ 0x5854, 0x128a,
+ 0x5859, 0x22c8,
+ 0x585a, 0x1290,
+ 0x585b, 0x22c9,
+ 0x585d, 0x1293,
+ 0x5871, 0x22cb,
+ 0x5872, 0x12a8,
+ 0x5876, 0x22cc,
+ 0x5878, 0x12ae,
+ 0x5921, 0x12b5,
+ 0x592d, 0x22ce,
+ 0x592e, 0x12c2,
+ 0x592f, 0x22cf,
+ 0x5930, 0x12c4,
+ 0x5931, 0x22d0,
+ 0x5934, 0x12c8,
+ 0x5947, 0x22d3,
+ 0x5948, 0x12dc,
+ 0x594d, 0x22d4,
+ 0x5951, 0x12e5,
+ 0x595d, 0x22d8,
+ 0x595e, 0x12f2,
+ 0x5961, 0x22d9,
+ 0x5962, 0x12f6,
+ 0x5964, 0x22da,
+ 0x5965, 0x12f9,
+ 0x5966, 0x22db,
+ 0x5967, 0x12fb,
+ 0x596c, 0x22dc,
+ 0x596d, 0x1301,
+ 0x5974, 0x22dd,
+ 0x5976, 0x130a,
+ 0x5a21, 0x1313,
+ 0x5a25, 0x22df,
+ 0x5a60, 0x1352,
+ 0x5a6a, 0x231a,
+ 0x5a6b, 0x135d,
+ 0x5a77, 0x231b,
+ 0x5a78, 0x136a,
+ 0x5a79, 0x231c,
+ 0x5a7a, 0x136c,
+ 0x5a7e, 0x231d,
+ 0x5b21, 0x1371,
+ 0x5b23, 0x231e,
+ 0x5b24, 0x1374,
+ 0x5b26, 0x231f,
+ 0x5b27, 0x1377,
+ 0x5b29, 0x2320,
+ 0x5b2b, 0x137b,
+ 0x5b3b, 0x2322,
+ 0x5b3c, 0x138c,
+ 0x5b3d, 0x2323,
+ 0x5b3e, 0x138e,
+ 0x5b4f, 0x2324,
+ 0x5b50, 0x13a0,
+ 0x5b51, 0x2325,
+ 0x5b52, 0x13a2,
+ 0x5b5b, 0x2326,
+ 0x5b5c, 0x13ac,
+ 0x5b5e, 0x2327,
+ 0x5b5f, 0x13af,
+ 0x5b62, 0x2328,
+ 0x5b63, 0x13b3,
+ 0x5b64, 0x2329,
+ 0x5b65, 0x13b5,
+ 0x5b6b, 0x232a,
+ 0x5b6c, 0x13bc,
+ 0x5b6e, 0x232b,
+ 0x5b6f, 0x13bf,
+ 0x5b71, 0x232c,
+ 0x5b72, 0x13c2,
+ 0x5b75, 0x232d,
+ 0x5b78, 0x13c8,
+ 0x5c21, 0x13cf,
+ 0x5c3c, 0x2330,
+ 0x5c3d, 0x13eb,
+ 0x5c3f, 0x2331,
+ 0x5c40, 0x13ee,
+ 0x5c42, 0x2332,
+ 0x5c43, 0x13f1,
+ 0x5c48, 0x2333,
+ 0x5c4b, 0x13f9,
+ 0x5c51, 0x2336,
+ 0x5c52, 0x1400,
+ 0x5c57, 0x2337,
+ 0x5c58, 0x1406,
+ 0x5c60, 0x2338,
+ 0x5c61, 0x140f,
+ 0x5c63, 0x2339,
+ 0x5c65, 0x1413,
+ 0x5c69, 0x233b,
+ 0x5c6b, 0x1419,
+ 0x5c71, 0x233d,
+ 0x5c72, 0x1420,
+ 0x5c76, 0x233e,
+ 0x5c77, 0x1425,
+ 0x5c79, 0x233f,
+ 0x5c7a, 0x1428,
+ 0x5c7d, 0x2340,
+ 0x5d21, 0x2342,
+ 0x5d22, 0x142e,
+ 0x5d23, 0x2343,
+ 0x5d28, 0x1434,
+ 0x5d2a, 0x2348,
+ 0x5d2c, 0x1438,
+ 0x5d32, 0x234a,
+ 0x5d33, 0x143f,
+ 0x5d35, 0x234b,
+ 0x5d36, 0x1442,
+ 0x5d3a, 0x234c,
+ 0x5d3c, 0x1448,
+ 0x5d53, 0x234e,
+ 0x5d54, 0x1460,
+ 0x5d5b, 0x234f,
+ 0x5d5c, 0x1468,
+ 0x5d5e, 0x2350,
+ 0x5d5f, 0x146b,
+ 0x5d64, 0x2351,
+ 0x5d65, 0x1471,
+ 0x5d6b, 0x2352,
+ 0x5d6c, 0x1478,
+ 0x5d71, 0x2353,
+ 0x5d72, 0x147e,
+ 0x5d76, 0x2354,
+ 0x5d78, 0x1484,
+ 0x5d7c, 0x2356,
+ 0x5d7d, 0x1489,
+ 0x5d7e, 0x2357,
+ 0x5e21, 0x148b,
+ 0x5e2d, 0x2358,
+ 0x5e2e, 0x1498,
+ 0x5e34, 0x2359,
+ 0x5e35, 0x149f,
+ 0x5e3a, 0x235a,
+ 0x5e3b, 0x14a5,
+ 0x5e46, 0x235b,
+ 0x5e47, 0x14b1,
+ 0x5e4f, 0x235c,
+ 0x5e50, 0x14ba,
+ 0x5e51, 0x235d,
+ 0x5e53, 0x14bd,
+ 0x5e58, 0x235f,
+ 0x5e59, 0x14c3,
+ 0x5e62, 0x2360,
+ 0x5e63, 0x14cd,
+ 0x5e68, 0x2361,
+ 0x5e69, 0x14d3,
+ 0x5e6c, 0x2362,
+ 0x5e6d, 0x14d7,
+ 0x5e73, 0x2363,
+ 0x5e74, 0x14de,
+ 0x5e7c, 0x2364,
+ 0x5e7d, 0x14e7,
+ 0x5f21, 0x14e9,
+ 0x5f22, 0x2365,
+ 0x5f24, 0x14ec,
+ 0x5f25, 0x2367,
+ 0x5f26, 0x14ee,
+ 0x5f34, 0x2368,
+ 0x5f35, 0x14fd,
+ 0x5f3c, 0x2369,
+ 0x5f3e, 0x1506,
+ 0x5f3f, 0x236b,
+ 0x5f40, 0x1508,
+ 0x5f42, 0x236c,
+ 0x5f44, 0x150c,
+ 0x5f4c, 0x236e,
+ 0x5f4d, 0x1515,
+ 0x5f50, 0x236f,
+ 0x5f51, 0x1519,
+ 0x5f55, 0x2370,
+ 0x5f56, 0x151e,
+ 0x5f58, 0x2371,
+ 0x5f5a, 0x1522,
+ 0x5f5c, 0x2373,
+ 0x5f5d, 0x1525,
+ 0x5f60, 0x2374,
+ 0x5f61, 0x1529,
+ 0x5f62, 0x2375,
+ 0x5f63, 0x152b,
+ 0x5f66, 0x2376,
+ 0x5f67, 0x152f,
+ 0x5f69, 0x2377,
+ 0x5f6a, 0x1532,
+ 0x5f6b, 0x2378,
+ 0x5f6c, 0x1534,
+ 0x5f6f, 0x2379,
+ 0x5f70, 0x1538,
+ 0x5f75, 0x237a,
+ 0x5f76, 0x153e,
+ 0x5f79, 0x237b,
+ 0x5f7a, 0x1542,
+ 0x6021, 0x1547,
+ 0x6036, 0x237c,
+ 0x6038, 0x155e,
+ 0x603f, 0x237e,
+ 0x6040, 0x1566,
+ 0x6048, 0x237f,
+ 0x6049, 0x156f,
+ 0x604e, 0x2380,
+ 0x604f, 0x1575,
+ 0x6053, 0x2381,
+ 0x6054, 0x157a,
+ 0x6060, 0x2382,
+ 0x6061, 0x1587,
+ 0x6070, 0x2383,
+ 0x6071, 0x1597,
+ 0x6078, 0x2384,
+ 0x6079, 0x159f,
+ 0x607c, 0x2385,
+ 0x6121, 0x15a5,
+ 0x612b, 0x2388,
+ 0x612c, 0x15b0,
+ 0x612d, 0x2389,
+ 0x612e, 0x15b2,
+ 0x6130, 0x238a,
+ 0x6131, 0x15b5,
+ 0x6134, 0x238b,
+ 0x6135, 0x15b9,
+ 0x613b, 0x238c,
+ 0x613c, 0x15c0,
+ 0x613d, 0x238d,
+ 0x613e, 0x15c2,
+ 0x6140, 0x238e,
+ 0x6142, 0x15c6,
+ 0x6149, 0x2390,
+ 0x614a, 0x15ce,
+ 0x6150, 0x2391,
+ 0x6151, 0x15d5,
+ 0x615b, 0x2392,
+ 0x615c, 0x15e0,
+ 0x6161, 0x07aa,
+ 0x6162, 0x2393,
+ 0x6163, 0x15e7,
+ 0x6167, 0x1198,
+ 0x6168, 0x15ec,
+ 0x616e, 0x2394,
+ 0x6170, 0x15f4,
+ 0x6176, 0x2396,
+ 0x6177, 0x15fb,
+ 0x6178, 0x2397,
+ 0x6179, 0x15fd,
+ 0x617d, 0x2398,
+ 0x617e, 0x1602,
+ 0x6221, 0x1603,
+ 0x6224, 0x2399,
+ 0x6225, 0x1607,
+ 0x6228, 0x239a,
+ 0x6229, 0x160b,
+ 0x623b, 0x239b,
+ 0x6245, 0x10c5,
+ 0x6246, 0x23a5,
+ 0x624f, 0x1631,
+ 0x6250, 0x23ae,
+ 0x6251, 0x1633,
+ 0x6259, 0x23af,
+ 0x625a, 0x163c,
+ 0x6263, 0x23b0,
+ 0x6265, 0x1647,
+ 0x6266, 0x23b2,
+ 0x6267, 0x1649,
+ 0x6269, 0x23b3,
+ 0x626c, 0x164e,
+ 0x6278, 0x23b6,
+ 0x6279, 0x165b,
+ 0x627a, 0x23b7,
+ 0x627e, 0x1660,
+ 0x6321, 0x1661,
+ 0x6322, 0x23bb,
+ 0x6323, 0x1663,
+ 0x6325, 0x23bc,
+ 0x6326, 0x1666,
+ 0x632b, 0x23bd,
+ 0x632c, 0x166c,
+ 0x6334, 0x23be,
+ 0x6335, 0x1675,
+ 0x6345, 0x23bf,
+ 0x635c, 0x169c,
+ 0x6363, 0x23d6,
+ 0x6364, 0x16a4,
+ 0x636d, 0x23d7,
+ 0x636e, 0x16ae,
+ 0x6371, 0x23d8,
+ 0x6373, 0x16b3,
+ 0x6378, 0x23da,
+ 0x6379, 0x16b9,
+ 0x637e, 0x23db,
+ 0x6421, 0x16bf,
+ 0x6424, 0x23dc,
+ 0x6426, 0x16c4,
+ 0x642b, 0x23de,
+ 0x642c, 0x16ca,
+ 0x642f, 0x23df,
+ 0x6432, 0x16d0,
+ 0x6435, 0x23e2,
+ 0x6437, 0x16d5,
+ 0x6442, 0x23e4,
+ 0x6443, 0x16e1,
+ 0x6445, 0x23e5,
+ 0x6446, 0x16e4,
+ 0x6449, 0x23e6,
+ 0x644a, 0x16e8,
+ 0x6459, 0x23e7,
+ 0x645a, 0x16f8,
+ 0x645c, 0x23e8,
+ 0x645d, 0x16fb,
+ 0x645e, 0x23e9,
+ 0x645f, 0x16fd,
+ 0x6464, 0x23ea,
+ 0x6465, 0x1703,
+ 0x646b, 0x23eb,
+ 0x646d, 0x170b,
+ 0x6472, 0x23ed,
+ 0x6473, 0x1711,
+ 0x647e, 0x23ee,
+ 0x6521, 0x171d,
+ 0x6530, 0x23ef,
+ 0x6531, 0x172d,
+ 0x6539, 0x23f0,
+ 0x653a, 0x1736,
+ 0x6547, 0x23f1,
+ 0x6548, 0x1744,
+ 0x6549, 0x23f2,
+ 0x654a, 0x1746,
+ 0x654e, 0x23f3,
+ 0x654f, 0x174b,
+ 0x6570, 0x23f4,
+ 0x6571, 0x176d,
+ 0x6572, 0x23f5,
+ 0x6573, 0x176f,
+ 0x657c, 0x23f6,
+ 0x657e, 0x177a,
+ 0x6621, 0x177b,
+ 0x6623, 0x23f8,
+ 0x6624, 0x177e,
+ 0x662b, 0x23f9,
+ 0x662d, 0x1787,
+ 0x662e, 0x23fb,
+ 0x662f, 0x1789,
+ 0x6634, 0x23fc,
+ 0x6636, 0x1790,
+ 0x663f, 0x23fe,
+ 0x6640, 0x179a,
+ 0x6648, 0x23ff,
+ 0x664a, 0x17a4,
+ 0x664d, 0x2401,
+ 0x664e, 0x17a8,
+ 0x6660, 0x2402,
+ 0x6721, 0x2421,
+ 0x675b, 0x1813,
+ 0x6761, 0x245b,
+ 0x6763, 0x181b,
+ 0x6767, 0x245d,
+ 0x6768, 0x1820,
+ 0x676f, 0x245e,
+ 0x6770, 0x1828,
+ 0x6774, 0x245f,
+ 0x6777, 0x182f,
+ 0x6821, 0x1837,
+ 0x6828, 0x2462,
+ 0x6829, 0x183f,
+ 0x682c, 0x2463,
+ 0x682d, 0x1843,
+ 0x6836, 0x2464,
+ 0x6837, 0x184d,
+ 0x6838, 0x2465,
+ 0x683b, 0x1851,
+ 0x683f, 0x2468,
+ 0x6841, 0x1857,
+ 0x6845, 0x246a,
+ 0x6846, 0x185c,
+ 0x6847, 0x246b,
+ 0x684a, 0x1860,
+ 0x684e, 0x246e,
+ 0x684f, 0x1865,
+ 0x6850, 0x246f,
+ 0x6851, 0x1867,
+ 0x6853, 0x2470,
+ 0x6854, 0x186a,
+ 0x685d, 0x2471,
+ 0x685e, 0x1874,
+ 0x685f, 0x2472,
+ 0x6860, 0x1876,
+ 0x6862, 0x2473,
+ 0x6864, 0x187a,
+ 0x6865, 0x2475,
+ 0x6866, 0x187c,
+ 0x6867, 0x2476,
+ 0x6868, 0x187e,
+ 0x686b, 0x2477,
+ 0x686c, 0x1882,
+ 0x686d, 0x2478,
+ 0x686e, 0x1884,
+ 0x686f, 0x2479,
+ 0x6870, 0x1886,
+ 0x6879, 0x247a,
+ 0x687a, 0x1890,
+ 0x687c, 0x247b,
+ 0x687e, 0x1894,
+ 0x6921, 0x247d,
+ 0x6922, 0x1896,
+ 0x692d, 0x247e,
+ 0x692e, 0x18a2,
+ 0x6934, 0x247f,
+ 0x6936, 0x18aa,
+ 0x6937, 0x2481,
+ 0x6938, 0x18ac,
+ 0x6944, 0x2482,
+ 0x6945, 0x18b9,
+ 0x6946, 0x2483,
+ 0x6947, 0x18bb,
+ 0x6949, 0x2484,
+ 0x694a, 0x18be,
+ 0x6956, 0x2485,
+ 0x6957, 0x18cb,
+ 0x695a, 0x2486,
+ 0x695b, 0x18cf,
+ 0x6964, 0x2487,
+ 0x6965, 0x18d9,
+ 0x6966, 0x2488,
+ 0x6968, 0x18dc,
+ 0x6969, 0x248a,
+ 0x696a, 0x18de,
+ 0x696b, 0x248b,
+ 0x696c, 0x18e0,
+ 0x696d, 0x248c,
+ 0x6a21, 0x249e,
+ 0x6a26, 0x18f8,
+ 0x6a27, 0x24a3,
+ 0x6a29, 0x18fb,
+ 0x6a31, 0x24a5,
+ 0x6a32, 0x1904,
+ 0x6a3c, 0x24a6,
+ 0x6a3d, 0x190f,
+ 0x6a4a, 0x24a7,
+ 0x6a4b, 0x191d,
+ 0x6a4d, 0x24a8,
+ 0x6a4e, 0x1920,
+ 0x6a53, 0x24a9,
+ 0x6a54, 0x1926,
+ 0x6a5a, 0x24aa,
+ 0x6a70, 0x1942,
+ 0x6b21, 0x1951,
+ 0x6b27, 0x24c0,
+ 0x6b28, 0x1958,
+ 0x6b2a, 0x24c1,
+ 0x6b2b, 0x195b,
+ 0x6b32, 0x24c2,
+ 0x6b33, 0x1963,
+ 0x6b39, 0x24c3,
+ 0x6b3a, 0x196a,
+ 0x6b4a, 0x24c4,
+ 0x6b4c, 0x197c,
+ 0x6b4d, 0x24c6,
+ 0x6b4e, 0x197e,
+ 0x6b56, 0x24c7,
+ 0x6b57, 0x1987,
+ 0x6b5a, 0x24c8,
+ 0x6b5b, 0x198b,
+ 0x6b61, 0x24c9,
+ 0x6b62, 0x1992,
+ 0x6b77, 0x24ca,
+ 0x6b78, 0x19a8,
+ 0x6c21, 0x19af,
+ 0x6c23, 0x24cb,
+ 0x6c24, 0x19b2,
+ 0x6c29, 0x24cc,
+ 0x6c2f, 0x19bd,
+ 0x6c31, 0x24d2,
+ 0x6c32, 0x19c0,
+ 0x6c34, 0x24d3,
+ 0x6c36, 0x19c4,
+ 0x6c3e, 0x24d5,
+ 0x6c40, 0x19ce,
+ 0x6c41, 0x24d7,
+ 0x6c42, 0x19d0,
+ 0x6c47, 0x24d8,
+ 0x6c48, 0x19d6,
+ 0x6c4b, 0x24d9,
+ 0x6c4c, 0x19da,
+ 0x6c62, 0x24da,
+ 0x6c63, 0x19f1,
+ 0x6c72, 0x24db,
+ 0x6c73, 0x1a01,
+ 0x6c75, 0x24dc,
+ 0x6c76, 0x1a04,
+ 0x6c78, 0x24dd,
+ 0x6c79, 0x1a07,
+ 0x6d21, 0x24de,
+ 0x6d22, 0x1a0e,
+ 0x6d28, 0x24df,
+ 0x6d29, 0x1a15,
+ 0x6d2f, 0x24e0,
+ 0x6d31, 0x1a1d,
+ 0x6d34, 0x24e2,
+ 0x6d35, 0x1a21,
+ 0x6d36, 0x24e3,
+ 0x6d37, 0x1a23,
+ 0x6d38, 0x24e4,
+ 0x6d39, 0x1a25,
+ 0x6d3a, 0x24e5,
+ 0x6d3b, 0x1a27,
+ 0x6d3f, 0x24e6,
+ 0x6d40, 0x1a2c,
+ 0x6d42, 0x24e7,
+ 0x6d44, 0x1a30,
+ 0x6d4c, 0x24e9,
+ 0x6d4e, 0x1a3a,
+ 0x6d53, 0x24eb,
+ 0x6d54, 0x1a40,
+ 0x6d57, 0x24ec,
+ 0x6d58, 0x1a44,
+ 0x6d68, 0x24ed,
+ 0x6d69, 0x1a55,
+ 0x6d6e, 0x24ee,
+ 0x6d6f, 0x1a5b,
+ 0x6d79, 0x24ef,
+ 0x6d7b, 0x1a67,
+ 0x6e21, 0x1a6b,
+ 0x6e3c, 0x24f1,
+ 0x6e3d, 0x1a87,
+ 0x6e3f, 0x24f2,
+ 0x6e40, 0x1a8a,
+ 0x6e44, 0x24f3,
+ 0x6f21, 0x252e,
+ 0x6f72, 0x1b1a,
+ 0x7021, 0x1b27,
+ 0x7023, 0x257f,
+ 0x7024, 0x1b2a,
+ 0x702f, 0x2580,
+ 0x705a, 0x1b60,
+ 0x705c, 0x25ab,
+ 0x705e, 0x1b64,
+ 0x705f, 0x25ad,
+ 0x7060, 0x1b66,
+ 0x7069, 0x25ae,
+ 0x706a, 0x1b70,
+ 0x706c, 0x25af,
+ 0x706d, 0x1b73,
+ 0x706f, 0x25b0,
+ 0x7070, 0x1b76,
+ 0x7077, 0x25b1,
+ 0x7078, 0x1b7e,
+ 0x7079, 0x25b2,
+ 0x707a, 0x1b80,
+ 0x707c, 0x25b3,
+ 0x707d, 0x1b83,
+ 0x7121, 0x1b85,
+ 0x7128, 0x25b4,
+ 0x7129, 0x1b8d,
+ 0x712b, 0x25b5,
+ 0x712c, 0x1b90,
+ 0x712e, 0x25b6,
+ 0x712f, 0x1b93,
+ 0x7132, 0x25b7,
+ 0x7133, 0x1b97,
+ 0x713c, 0x25b8,
+ 0x713d, 0x1ba1,
+ 0x7140, 0x25b9,
+ 0x7141, 0x1ba5,
+ 0x7149, 0x25ba,
+ 0x714a, 0x1bae,
+ 0x714d, 0x25bb,
+ 0x714e, 0x1bb2,
+ 0x714f, 0x25bc,
+ 0x7151, 0x1bb5,
+ 0x715a, 0x25be,
+ 0x715b, 0x1bbf,
+ 0x715c, 0x25bf,
+ 0x715d, 0x1bc1,
+ 0x7164, 0x25c0,
+ 0x7165, 0x1bc9,
+ 0x716c, 0x25c1,
+ 0x716d, 0x1bd1,
+ 0x716f, 0x25c2,
+ 0x7170, 0x1bd4,
+ 0x7177, 0x25c3,
+ 0x7178, 0x1bdc,
+ 0x7179, 0x25c4,
+ 0x717a, 0x1bde,
+ 0x717c, 0x25c5,
+ 0x7221, 0x25c8,
+ 0x722e, 0x1bf0,
+ 0x7231, 0x25d5,
+ 0x7233, 0x1bf5,
+ 0x7239, 0x25d7,
+ 0x723a, 0x1bfc,
+ 0x7243, 0x25d8,
+ 0x7244, 0x1c06,
+ 0x7249, 0x25d9,
+ 0x724a, 0x1c0c,
+ 0x724c, 0x25da,
+ 0x724e, 0x1c10,
+ 0x724f, 0x25dc,
+ 0x7250, 0x1c12,
+ 0x7253, 0x25dd,
+ 0x7254, 0x1c16,
+ 0x7265, 0x25de,
+ 0x7266, 0x1c28,
+ 0x726e, 0x25df,
+ 0x726f, 0x1c31,
+ 0x7277, 0x25e0,
+ 0x7278, 0x1c3a,
+ 0x727d, 0x25e1,
+ 0x727e, 0x1c40,
+ 0x7321, 0x1c41,
+ 0x733f, 0x25e2,
+ 0x7340, 0x1c60,
+ 0x7346, 0x25e3,
+ 0x7347, 0x1c67,
+ 0x7348, 0x25e4,
+ 0x7349, 0x1c69,
+ 0x7356, 0x25e5,
+ 0x7357, 0x1c77,
+ 0x7359, 0x25e6,
+ 0x735a, 0x1c7a,
+ 0x7365, 0x25e7,
+ 0x7367, 0x1c87,
+ 0x736a, 0x25e9,
+ 0x736b, 0x1c8b,
+ 0x736c, 0x25ea,
+ 0x736d, 0x1c8d,
+ 0x736f, 0x25eb,
+ 0x7370, 0x1c90,
+ 0x7371, 0x25ec,
+ 0x7372, 0x1c92,
+ 0x737d, 0x25ed,
+ 0x737e, 0x1c9e,
+ 0x7421, 0x1c9f,
+ 0x7425, 0x25ee,
+ 0x7426, 0x1ca4,
+ 0x742f, 0x25ef,
+ 0x7430, 0x1cae,
+ 0x7435, 0x25f0,
+ 0x7436, 0x1cb4,
+ 0x7441, 0x25f1,
+ 0x7442, 0x1cc0,
+ 0x7447, 0x25f2,
+ 0x7448, 0x1cc6,
+ 0x744f, 0x25f3,
+ 0x7451, 0x1ccf,
+ 0x7456, 0x25f5,
+ 0x7457, 0x1cd5,
+ 0x746a, 0x25f6,
+ 0x746b, 0x1ce9,
+ 0x746f, 0x25f7,
+ 0x7470, 0x1cee,
+ 0x7475, 0x25f8,
+ 0x7476, 0x1cf4,
+ 0x7521, 0x1cfd,
+ 0x7526, 0x25f9,
+ 0x7528, 0x1d04,
+ 0x753a, 0x25fb,
+ 0x753c, 0x1d18,
+ 0x7544, 0x25fd,
+ 0x7545, 0x1d21,
+ 0x7548, 0x25fe,
+ 0x7549, 0x1d25,
+ 0x754e, 0x25ff,
+ 0x7550, 0x1d2c,
+ 0x7551, 0x2601,
+ 0x7553, 0x1d2f,
+ 0x7559, 0x2603,
+ 0x755a, 0x1d36,
+ 0x755c, 0x2604,
+ 0x755d, 0x1d39,
+ 0x7566, 0x2605,
+ 0x7568, 0x1d44,
+ 0x756f, 0x2607,
+ 0x7570, 0x1d4c,
+ 0x7572, 0x2608,
+ 0x7573, 0x1d4f,
+ 0x757c, 0x2609,
+ 0x757d, 0x1d59,
+ 0x7621, 0x1d5b,
+ 0x7623, 0x260a,
+ 0x7624, 0x1d5e,
+ 0x7626, 0x260b,
+ 0x7627, 0x1d61,
+ 0x7628, 0x260c,
+ 0x7629, 0x1d63,
+ 0x762b, 0x260d,
+ 0x762c, 0x1d66,
+ 0x7630, 0x260e,
+ 0x7631, 0x1d6b,
+ 0x7633, 0x260f,
+ 0x763f, 0x1d79,
+ 0x7645, 0x261b,
+ 0x7646, 0x1d80,
+ 0x7647, 0x261c,
+ 0x7648, 0x1d82,
+ 0x7649, 0x261d,
+ 0x764a, 0x1d84,
+ 0x764f, 0x261e,
+ 0x7721, 0x264e,
+ 0x7730, 0x1dc8,
+ 0x7732, 0x265d,
+ 0x7734, 0x1dcc,
+ 0x7735, 0x265f,
+ 0x7736, 0x1dce,
+ 0x773d, 0x2660,
+ 0x773e, 0x1dd6,
+ 0x7743, 0x2661,
+ 0x7744, 0x1ddc,
+ 0x7745, 0x2662,
+ 0x7747, 0x1ddf,
+ 0x774a, 0x2664,
+ 0x774c, 0x1de4,
+ 0x774f, 0x2666,
+ 0x7751, 0x1de9,
+ 0x775e, 0x2668,
+ 0x775f, 0x1df7,
+ 0x7761, 0x0ab9,
+ 0x7762, 0x1dfa,
+ 0x7772, 0x2669,
+ 0x7773, 0x1e0b,
+ 0x7775, 0x266a,
+ 0x7776, 0x1e0e,
+ 0x7821, 0x266b,
+ 0x7827, 0x04cc,
+ 0x7828, 0x050a,
+ 0x7829, 0x0518,
+ 0x782a, 0x2671,
+ 0x782c, 0x0594,
+ 0x782d, 0x05ce,
+ 0x782e, 0x2673,
+ 0x782f, 0x05f6,
+ 0x7830, 0x2674,
+ 0x7832, 0x0653,
+ 0x7833, 0x067e,
+ 0x7834, 0x2676,
+ 0x7835, 0x06c4,
+ 0x7836, 0x2677,
+ 0x7838, 0x073c,
+ 0x7839, 0x2679,
+ 0x783b, 0x07c3,
+ 0x783c, 0x267b,
+ 0x7840, 0x082b,
+ 0x7841, 0x267f,
+ 0x7842, 0x084e,
+ 0x7843, 0x0869,
+ 0x7844, 0x2680,
+ 0x7846, 0x090c,
+ 0x7847, 0x2682,
+ 0x7849, 0x0971,
+ 0x784a, 0x2684,
+ 0x784b, 0x099a,
+ 0x784d, 0x2685,
+ 0x784e, 0x09da,
+ 0x784f, 0x2686,
+ 0x7850, 0x09fa,
+ 0x7851, 0x2687,
+ 0x785c, 0x0bda,
+ 0x785d, 0x0bdd,
+ 0x785e, 0x0bea,
+ 0x785f, 0x0bec,
+ 0x7860, 0x0bf2,
+ 0x7861, 0x2692,
+ 0x7866, 0x0c92,
+ 0x7867, 0x0d1a,
+ 0x7868, 0x0d8c,
+ 0x7869, 0x0dbe,
+ 0x786a, 0x2697,
+ 0x786b, 0x0dfb,
+ 0x786c, 0x2698,
+ 0x786f, 0x0e70,
+ 0x7870, 0x269b,
+ 0x7871, 0x0ea3,
+ 0x7872, 0x269c,
+ 0x7878, 0x103d,
+ 0x7879, 0x10d9,
+ 0x787a, 0x26a2,
+ 0x787c, 0x10fb,
+ 0x787d, 0x1109,
+ 0x787e, 0x26a4,
+ 0x7921, 0x11a1,
+ 0x7922, 0x26a5,
+ 0x7923, 0x11ba,
+ 0x7924, 0x26a6,
+ 0x7926, 0x11d5,
+ 0x7927, 0x26a8,
+ 0x7928, 0x11fd,
+ 0x7929, 0x1219,
+ 0x2122, 0x023f,
+ 0x2123, 0x023e,
+ 0x212a, 0x0256,
+ 0x212b, 0x1e18,
+ 0x212d, 0x0257,
+ 0x2132, 0x0246,
+ 0x217e, 0x1e1a,
+ 0x2321, 0x0242,
+ 0x2328, 0x0244,
+ 0x232c, 0x023d,
+ 0x232e, 0x1e1b,
+ 0x233a, 0x0240,
+ 0x233d, 0x1e1c,
+ 0x233f, 0x0243,
+ 0x235b, 0x1e1d,
+ 0x235d, 0x1e1e,
+ 0x235f, 0x0258,
+ 0x237b, 0x0254,
+ 0x237d, 0x0255,
+ 0x237e, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12GBTVMap2, 2303
+};
+
+static Gushort gb12GBTpcEUCHMap2[4566] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb0a8, 0x1e25,
+ 0xb0a9, 0x03b4,
+ 0xb0aa, 0x1e26,
+ 0xb0ab, 0x03b6,
+ 0xb0ad, 0x1e27,
+ 0xb0af, 0x03ba,
+ 0xb0b9, 0x1e29,
+ 0xb0ba, 0x03c5,
+ 0xb0c0, 0x1e2a,
+ 0xb0c1, 0x03cc,
+ 0xb0d3, 0x1e2b,
+ 0xb0d4, 0x03df,
+ 0xb0d5, 0x1e2c,
+ 0xb0d6, 0x03e1,
+ 0xb0da, 0x1e2d,
+ 0xb0db, 0x03e6,
+ 0xb0dc, 0x1e2e,
+ 0xb0dd, 0x03e8,
+ 0xb0e4, 0x1e2f,
+ 0xb0e5, 0x03f0,
+ 0xb0ec, 0x1e30,
+ 0xb0ee, 0x03f9,
+ 0xb0ef, 0x1e32,
+ 0xb0f0, 0x03fb,
+ 0xb0f3, 0x1e33,
+ 0xb0f4, 0x03ff,
+ 0xb0f7, 0x1e34,
+ 0xb0f8, 0x0403,
+ 0xb0f9, 0x1e35,
+ 0xb0fa, 0x0405,
+ 0xb1a1, 0x040a,
+ 0xb1a5, 0x1e36,
+ 0xb1a7, 0x0410,
+ 0xb1a8, 0x1e38,
+ 0xb1a9, 0x0412,
+ 0xb1ab, 0x1e39,
+ 0xb1ac, 0x0415,
+ 0xb1b2, 0x1e3a,
+ 0xb1b3, 0x041c,
+ 0xb1b4, 0x1e3b,
+ 0xb1b6, 0x041f,
+ 0xb1b7, 0x1e3d,
+ 0xb1ba, 0x0423,
+ 0xb1c1, 0x1e40,
+ 0xb1c2, 0x042b,
+ 0xb1ca, 0x1e41,
+ 0xb1cb, 0x0434,
+ 0xb1cf, 0x1e42,
+ 0xb1d1, 0x043a,
+ 0xb1d2, 0x1e44,
+ 0xb1d3, 0x043c,
+ 0xb1d5, 0x1e45,
+ 0xb1d6, 0x043f,
+ 0xb1df, 0x1e46,
+ 0xb1e2, 0x044b,
+ 0xb1e4, 0x1e49,
+ 0xb1e5, 0x044e,
+ 0xb1e7, 0x1e4a,
+ 0xb1e9, 0x0452,
+ 0xb1ea, 0x1e4c,
+ 0xb1eb, 0x0454,
+ 0xb1ee, 0x1e4d,
+ 0xb1ef, 0x0458,
+ 0xb1f1, 0x1e4e,
+ 0xb1f2, 0x045b,
+ 0xb1f4, 0x1e4f,
+ 0xb1f8, 0x0461,
+ 0xb1fd, 0x1e53,
+ 0xb1fe, 0x0467,
+ 0xb2a1, 0x0468,
+ 0xb2a6, 0x1e54,
+ 0xb2a8, 0x046f,
+ 0xb2ac, 0x1e56,
+ 0xb2ad, 0x0474,
+ 0xb2b5, 0x1e57,
+ 0xb2b6, 0x047d,
+ 0xb2b9, 0x1e58,
+ 0xb2ba, 0x0481,
+ 0xb2c6, 0x1e59,
+ 0xb2c7, 0x048e,
+ 0xb2ce, 0x1e5a,
+ 0xb2d8, 0x049f,
+ 0xb2de, 0x1e64,
+ 0xb2df, 0x04a6,
+ 0xb2e0, 0x1e65,
+ 0xb2e1, 0x04a8,
+ 0xb2e2, 0x1e66,
+ 0xb2e4, 0x04ab,
+ 0xb2ef, 0x1e68,
+ 0xb2f0, 0x04b7,
+ 0xb2f3, 0x1e69,
+ 0xb2fd, 0x04c4,
+ 0xb3a1, 0x1e73,
+ 0xb3a3, 0x04c8,
+ 0xb3a4, 0x1e75,
+ 0xb3a8, 0x04cd,
+ 0xb3a9, 0x1e79,
+ 0xb3aa, 0x04cf,
+ 0xb3ae, 0x1e7a,
+ 0xb3af, 0x04d4,
+ 0xb3b5, 0x1e7b,
+ 0xb3b6, 0x04db,
+ 0xb3b9, 0x1e7c,
+ 0xb3ba, 0x04df,
+ 0xb3be, 0x1e7d,
+ 0xb3bf, 0x04e4,
+ 0xb3c2, 0x1e7e,
+ 0xb3c3, 0x04e8,
+ 0xb3c4, 0x1e7f,
+ 0xb3c5, 0x04ea,
+ 0xb3c6, 0x1e80,
+ 0xb3c7, 0x04ec,
+ 0xb3cd, 0x1e81,
+ 0xb3ce, 0x04f3,
+ 0xb3cf, 0x1e82,
+ 0xb3d0, 0x04f5,
+ 0xb3d2, 0x1e83,
+ 0xb3d3, 0x04f8,
+ 0xb3d9, 0x1e84,
+ 0xb3da, 0x04ff,
+ 0xb3db, 0x1e85,
+ 0xb3dc, 0x0501,
+ 0xb3dd, 0x1e86,
+ 0xb3de, 0x0503,
+ 0xb3e3, 0x1e87,
+ 0xb3e4, 0x0509,
+ 0xb3e5, 0x1e88,
+ 0xb3e7, 0x050c,
+ 0xb3e8, 0x1e8a,
+ 0xb3e9, 0x050e,
+ 0xb3eb, 0x1e8b,
+ 0xb3ed, 0x0512,
+ 0xb3ef, 0x1e8d,
+ 0xb3f0, 0x0515,
+ 0xb3f1, 0x1e8e,
+ 0xb3f2, 0x0517,
+ 0xb3f3, 0x1e8f,
+ 0xb3f4, 0x0519,
+ 0xb3fa, 0x1e90,
+ 0xb3fc, 0x0521,
+ 0xb4a1, 0x1e92,
+ 0xb4a3, 0x0526,
+ 0xb4a5, 0x1e94,
+ 0xb4a7, 0x052a,
+ 0xb4ab, 0x1e96,
+ 0xb4ac, 0x052f,
+ 0xb4af, 0x1e97,
+ 0xb4b0, 0x0533,
+ 0xb4b3, 0x1e98,
+ 0xb4b5, 0x0538,
+ 0xb4b8, 0x1e9a,
+ 0xb4b9, 0x053c,
+ 0xb4bf, 0x1e9b,
+ 0xb4c0, 0x0543,
+ 0xb4c2, 0x1e9c,
+ 0xb4c3, 0x0546,
+ 0xb4c7, 0x1e9d,
+ 0xb4c8, 0x054b,
+ 0xb4ca, 0x1e9e,
+ 0xb4cb, 0x054e,
+ 0xb4cd, 0x1e9f,
+ 0xb4ce, 0x0551,
+ 0xb4cf, 0x1ea0,
+ 0xb4d0, 0x0553,
+ 0xb4d3, 0x1ea1,
+ 0xb4d5, 0x0558,
+ 0xb4da, 0x1ea3,
+ 0xb4db, 0x055e,
+ 0xb4dc, 0x1ea4,
+ 0xb4dd, 0x0560,
+ 0xb4ed, 0x1ea5,
+ 0xb4ee, 0x0571,
+ 0xb4ef, 0x1ea6,
+ 0xb4f0, 0x0573,
+ 0xb4f8, 0x1ea7,
+ 0xb4f9, 0x057c,
+ 0xb4fb, 0x1ea8,
+ 0xb4fc, 0x057f,
+ 0xb5a1, 0x0582,
+ 0xb5a3, 0x1ea9,
+ 0xb5a4, 0x0585,
+ 0xb5a5, 0x1eaa,
+ 0xb5a9, 0x058a,
+ 0xb5ac, 0x1eae,
+ 0xb5ad, 0x058e,
+ 0xb5ae, 0x1eaf,
+ 0xb5b0, 0x0591,
+ 0xb5b1, 0x1eb1,
+ 0xb5b6, 0x0597,
+ 0xb5b7, 0x1eb6,
+ 0xb5b8, 0x0599,
+ 0xb5ba, 0x1eb7,
+ 0xb5bd, 0x059e,
+ 0xb5c6, 0x1eba,
+ 0xb5c7, 0x05a8,
+ 0xb5cb, 0x1ebb,
+ 0xb5cc, 0x05ad,
+ 0xb5d0, 0x1ebc,
+ 0xb5d1, 0x05b2,
+ 0xb5d3, 0x1ebd,
+ 0xb5d4, 0x05b5,
+ 0xb5dd, 0x1ebe,
+ 0xb5e0, 0x05c1,
+ 0xb5e3, 0x1ec1,
+ 0xb5e4, 0x05c5,
+ 0xb5e6, 0x1ec2,
+ 0xb5e8, 0x05c9,
+ 0xb5ed, 0x1ec4,
+ 0xb5ee, 0x05cf,
+ 0xb5f6, 0x1ec5,
+ 0xb5f8, 0x05d9,
+ 0xb5fd, 0x1ec7,
+ 0xb5fe, 0x05df,
+ 0xb6a1, 0x05e0,
+ 0xb6a4, 0x1ec8,
+ 0xb6a6, 0x05e5,
+ 0xb6a7, 0x1eca,
+ 0xb6a8, 0x05e7,
+ 0xb6a9, 0x1ecb,
+ 0xb6aa, 0x05e9,
+ 0xb6ab, 0x1ecc,
+ 0xb6ac, 0x05eb,
+ 0xb6af, 0x1ecd,
+ 0xb6b1, 0x05f0,
+ 0xb6b3, 0x1ecf,
+ 0xb6b4, 0x05f3,
+ 0xb6b7, 0x1ed0,
+ 0xb6b8, 0x05f7,
+ 0xb6bf, 0x1ed1,
+ 0xb6c2, 0x0601,
+ 0xb6c4, 0x1ed4,
+ 0xb6c5, 0x0604,
+ 0xb6c6, 0x1ed5,
+ 0xb6c7, 0x0606,
+ 0xb6cd, 0x1ed6,
+ 0xb6ce, 0x060d,
+ 0xb6cf, 0x1ed7,
+ 0xb6d1, 0x0610,
+ 0xb6d3, 0x1ed9,
+ 0xb6d5, 0x0614,
+ 0xb6d6, 0x1edb,
+ 0xb6d7, 0x0616,
+ 0xb6d9, 0x1edc,
+ 0xb6da, 0x0619,
+ 0xb6db, 0x1edd,
+ 0xb6dc, 0x061b,
+ 0xb6e1, 0x1ede,
+ 0xb6e2, 0x0621,
+ 0xb6e9, 0x1edf,
+ 0xb6ea, 0x0629,
+ 0xb6ec, 0x1ee0,
+ 0xb6ed, 0x062c,
+ 0xb6ee, 0x1ee1,
+ 0xb6f0, 0x062f,
+ 0xb6f1, 0x1ee3,
+ 0xb6f2, 0x0631,
+ 0xb6f6, 0x1ee4,
+ 0xb6f7, 0x0636,
+ 0xb6f9, 0x1ee5,
+ 0xb6fa, 0x0639,
+ 0xb6fb, 0x1ee6,
+ 0xb6fd, 0x063c,
+ 0xb7a1, 0x1ee8,
+ 0xb7a4, 0x0641,
+ 0xb7a7, 0x1eeb,
+ 0xb7a8, 0x0645,
+ 0xb7af, 0x1eec,
+ 0xb7b1, 0x064e,
+ 0xb7b3, 0x1eee,
+ 0xb7b4, 0x0651,
+ 0xb7b6, 0x1eef,
+ 0xb7b8, 0x0655,
+ 0xb7b9, 0x1ef1,
+ 0xb7ba, 0x0657,
+ 0xb7c3, 0x1ef2,
+ 0xb7c5, 0x0662,
+ 0xb7c9, 0x1ef4,
+ 0xb7ca, 0x0667,
+ 0xb7cc, 0x1ef5,
+ 0xb7cd, 0x066a,
+ 0xb7cf, 0x1ef6,
+ 0xb7d0, 0x066d,
+ 0xb7d1, 0x1ef7,
+ 0xb7d2, 0x066f,
+ 0xb7d7, 0x1ef8,
+ 0xb7d9, 0x0676,
+ 0xb7dc, 0x1efa,
+ 0xb7dd, 0x067a,
+ 0xb7df, 0x1efb,
+ 0xb7e2, 0x067f,
+ 0xb7e3, 0x1efe,
+ 0xb7e4, 0x0681,
+ 0xb7e6, 0x1eff,
+ 0xb7e9, 0x0686,
+ 0xb7eb, 0x1f02,
+ 0xb7ee, 0x068b,
+ 0xb7ef, 0x1f05,
+ 0xb7f0, 0x068d,
+ 0xb7f4, 0x1f06,
+ 0xb7f5, 0x0692,
+ 0xb7f8, 0x1f07,
+ 0xb7f9, 0x0696,
+ 0xb8a1, 0x069c,
+ 0xb8a7, 0x1f08,
+ 0xb8a9, 0x06a4,
+ 0xb8b3, 0x1f0a,
+ 0xb8b5, 0x06b0,
+ 0xb8ba, 0x1f0c,
+ 0xb8bb, 0x06b6,
+ 0xb8bc, 0x1f0d,
+ 0xb8bd, 0x06b8,
+ 0xb8be, 0x1f0e,
+ 0xb8c0, 0x06bb,
+ 0xb8c3, 0x1f10,
+ 0xb8c4, 0x06bf,
+ 0xb8c6, 0x1f11,
+ 0xb8c8, 0x06c3,
+ 0xb8c9, 0x1f13,
+ 0xb8ca, 0x06c5,
+ 0xb8cf, 0x1f14,
+ 0xb8d0, 0x06cb,
+ 0xb8d3, 0x1f15,
+ 0xb8d7, 0x06d2,
+ 0xb8d9, 0x1f19,
+ 0xb8db, 0x06d6,
+ 0xb8e4, 0x1f1b,
+ 0xb8e5, 0x06e0,
+ 0xb8e9, 0x1f1c,
+ 0xb8ea, 0x06e5,
+ 0xb8eb, 0x1f1d,
+ 0xb8ec, 0x06e7,
+ 0xb8f3, 0x1f1e,
+ 0xb8f4, 0x06ef,
+ 0xb8f5, 0x1f1f,
+ 0xb8f7, 0x06f2,
+ 0xb8f8, 0x1f21,
+ 0xb8f9, 0x06f4,
+ 0xb9a1, 0x06fa,
+ 0xb9a8, 0x1f22,
+ 0xb9a9, 0x0702,
+ 0xb9ae, 0x1f23,
+ 0xb9af, 0x0708,
+ 0xb9b1, 0x1f24,
+ 0xb9b2, 0x070b,
+ 0xb9b3, 0x1f25,
+ 0xb9b4, 0x070d,
+ 0xb9b5, 0x1f26,
+ 0xb9b6, 0x070f,
+ 0xb9b9, 0x1f27,
+ 0xb9bb, 0x0714,
+ 0xb9c6, 0x1f29,
+ 0xb9c7, 0x0720,
+ 0xb9cb, 0x1f2a,
+ 0xb9cc, 0x0725,
+ 0xb9d0, 0x1f2b,
+ 0xb9d1, 0x072a,
+ 0xb9d8, 0x1f2c,
+ 0xb9d9, 0x0732,
+ 0xb9db, 0x1f2d,
+ 0xb9dc, 0x0735,
+ 0xb9dd, 0x1f2e,
+ 0xb9de, 0x0737,
+ 0xb9df, 0x1f2f,
+ 0xb9e0, 0x0739,
+ 0xb9e1, 0x1f30,
+ 0xb9e2, 0x073b,
+ 0xb9e3, 0x1f31,
+ 0xb9e4, 0x073d,
+ 0xb9e6, 0x1f32,
+ 0xb9e7, 0x0740,
+ 0xb9e9, 0x1f33,
+ 0xb9ed, 0x0746,
+ 0xb9ee, 0x1f37,
+ 0xb9ef, 0x0748,
+ 0xb9f1, 0x1f38,
+ 0xb9f2, 0x074b,
+ 0xb9f3, 0x1f39,
+ 0xb9f6, 0x074f,
+ 0xb9f8, 0x1f3c,
+ 0xb9f9, 0x0752,
+ 0xb9fa, 0x1f3d,
+ 0xb9fb, 0x0754,
+ 0xb9fd, 0x1f3e,
+ 0xb9fe, 0x0757,
+ 0xbaa1, 0x0758,
+ 0xbaa7, 0x1f3f,
+ 0xbaa8, 0x075f,
+ 0xbaab, 0x1f40,
+ 0xbaac, 0x0763,
+ 0xbaba, 0x1f41,
+ 0xbabb, 0x0772,
+ 0xbac5, 0x1f42,
+ 0xbac6, 0x077d,
+ 0xbad2, 0x1f43,
+ 0xbad3, 0x078a,
+ 0xbad7, 0x1f44,
+ 0xbad9, 0x0790,
+ 0xbae4, 0x1f46,
+ 0xbae5, 0x079c,
+ 0xbae8, 0x1f47,
+ 0xbae9, 0x07a0,
+ 0xbaec, 0x1f48,
+ 0xbaed, 0x07a4,
+ 0xbaf3, 0x15e5,
+ 0xbaf4, 0x07ab,
+ 0xbaf8, 0x1f49,
+ 0xbaf9, 0x07b0,
+ 0xbba1, 0x07b6,
+ 0xbba4, 0x1f4a,
+ 0xbba5, 0x07ba,
+ 0xbba6, 0x1f4b,
+ 0xbba7, 0x07bc,
+ 0xbba9, 0x1f4c,
+ 0xbbab, 0x07c0,
+ 0xbbad, 0x1f4e,
+ 0xbbaf, 0x07c4,
+ 0xbbb0, 0x1f50,
+ 0xbbb1, 0x07c6,
+ 0xbbb3, 0x1f51,
+ 0xbbb4, 0x07c9,
+ 0xbbb5, 0x1f52,
+ 0xbbb8, 0x07cd,
+ 0xbbb9, 0x1f55,
+ 0xbbbb, 0x07d0,
+ 0xbbd1, 0x1f57,
+ 0xbbd2, 0x07e7,
+ 0xbbd3, 0x1f58,
+ 0xbbd5, 0x07ea,
+ 0xbbdf, 0x1f5a,
+ 0xbbe8, 0x07fd,
+ 0xbbeb, 0x1f63,
+ 0xbbec, 0x0801,
+ 0xbbf1, 0x1f64,
+ 0xbbf2, 0x0807,
+ 0xbbf5, 0x1f65,
+ 0xbbf8, 0x080d,
+ 0xbbfa, 0x1f68,
+ 0xbbfb, 0x0810,
+ 0xbbfd, 0x1f69,
+ 0xbbfe, 0x0813,
+ 0xbca1, 0x0814,
+ 0xbca2, 0x1f6a,
+ 0xbca3, 0x0816,
+ 0xbca5, 0x1f6b,
+ 0xbca7, 0x081a,
+ 0xbca8, 0x1f6d,
+ 0xbcaa, 0x081d,
+ 0xbcab, 0x1f6f,
+ 0xbcac, 0x081f,
+ 0xbcad, 0x1f70,
+ 0xbcae, 0x0821,
+ 0xbcb6, 0x1f71,
+ 0xbcb9, 0x082c,
+ 0xbcbb, 0x1f74,
+ 0xbcbc, 0x082f,
+ 0xbcc1, 0x1f75,
+ 0xbcc2, 0x0835,
+ 0xbcc3, 0x1f76,
+ 0xbcc4, 0x0837,
+ 0xbcc6, 0x1f77,
+ 0xbcc8, 0x083b,
+ 0xbcca, 0x1f79,
+ 0xbccb, 0x083e,
+ 0xbccc, 0x1f7a,
+ 0xbcce, 0x0841,
+ 0xbcd0, 0x1f7c,
+ 0xbcd1, 0x0844,
+ 0xbcd4, 0x1f7d,
+ 0xbcd7, 0x084a,
+ 0xbcd8, 0x1f80,
+ 0xbcd9, 0x084c,
+ 0xbcdb, 0x1f81,
+ 0xbcdc, 0x084f,
+ 0xbcdd, 0x1f82,
+ 0xbcde, 0x0851,
+ 0xbcdf, 0x1f83,
+ 0xbce2, 0x0855,
+ 0xbce3, 0x1f86,
+ 0xbce5, 0x0858,
+ 0xbce8, 0x1f88,
+ 0xbce9, 0x085c,
+ 0xbcea, 0x1f89,
+ 0xbced, 0x0860,
+ 0xbcef, 0x1f8c,
+ 0xbcf4, 0x0867,
+ 0xbcf6, 0x1f91,
+ 0xbcfd, 0x0870,
+ 0xbda1, 0x0872,
+ 0xbda2, 0x1f98,
+ 0xbda8, 0x0879,
+ 0xbdab, 0x1f9e,
+ 0xbdad, 0x087e,
+ 0xbdaf, 0x1fa0,
+ 0xbdb3, 0x0884,
+ 0xbdb4, 0x1fa4,
+ 0xbdb5, 0x0886,
+ 0xbdba, 0x1fa5,
+ 0xbdbb, 0x088c,
+ 0xbdbd, 0x1fa6,
+ 0xbdc0, 0x0891,
+ 0xbdc1, 0x1fa9,
+ 0xbdc5, 0x0896,
+ 0xbdc8, 0x1fad,
+ 0xbdcb, 0x089c,
+ 0xbdce, 0x1fb0,
+ 0xbdd0, 0x08a1,
+ 0xbdd7, 0x1fb2,
+ 0xbdd8, 0x08a9,
+ 0xbdda, 0x1fb3,
+ 0xbddb, 0x08ac,
+ 0xbde0, 0x1fb4,
+ 0xbde2, 0x08b3,
+ 0xbdeb, 0x1fb6,
+ 0xbdec, 0x08bd,
+ 0xbdf4, 0x1fb7,
+ 0xbdf9, 0x08ca,
+ 0xbdfd, 0x1fbc,
+ 0xbdfe, 0x08cf,
+ 0xbea1, 0x1fbd,
+ 0xbea3, 0x08d2,
+ 0xbea5, 0x1fbf,
+ 0xbea6, 0x08d5,
+ 0xbea8, 0x1fc0,
+ 0xbea9, 0x08d8,
+ 0xbeaa, 0x1fc1,
+ 0xbeab, 0x08da,
+ 0xbead, 0x1fc2,
+ 0xbeae, 0x08dd,
+ 0xbeb1, 0x1fc3,
+ 0xbeb2, 0x08e1,
+ 0xbeb5, 0x1fc4,
+ 0xbeb8, 0x08e7,
+ 0xbeba, 0x1fc7,
+ 0xbebb, 0x08ea,
+ 0xbec0, 0x1fc8,
+ 0xbec1, 0x08f0,
+ 0xbec9, 0x1fc9,
+ 0xbeca, 0x08f9,
+ 0xbed4, 0x1fca,
+ 0xbed5, 0x0904,
+ 0xbed9, 0x1fcb,
+ 0xbeda, 0x0909,
+ 0xbedd, 0x1fcc,
+ 0xbede, 0x090d,
+ 0xbee2, 0x1fcd,
+ 0xbee3, 0x0912,
+ 0xbee5, 0x1fce,
+ 0xbee6, 0x0915,
+ 0xbee7, 0x1fcf,
+ 0xbee8, 0x0917,
+ 0xbee9, 0x1fd0,
+ 0xbeea, 0x0919,
+ 0xbeee, 0x1fd1,
+ 0xbeef, 0x091e,
+ 0xbef5, 0x1fd2,
+ 0xbef6, 0x0925,
+ 0xbef7, 0x1fd3,
+ 0xbef9, 0x0928,
+ 0xbefb, 0x1fd5,
+ 0xbefd, 0x092c,
+ 0xbfa1, 0x092e,
+ 0xbfa5, 0x1fd7,
+ 0xbfa6, 0x0933,
+ 0xbfaa, 0x1fd8,
+ 0xbfab, 0x0938,
+ 0xbfad, 0x1fd9,
+ 0xbfae, 0x093b,
+ 0xbfc5, 0x1fda,
+ 0xbfc6, 0x0953,
+ 0xbfc7, 0x1fdb,
+ 0xbfc8, 0x0955,
+ 0xbfce, 0x1fdc,
+ 0xbfcf, 0x095c,
+ 0xbfd1, 0x1fdd,
+ 0xbfd3, 0x0960,
+ 0xbfd9, 0x1fdf,
+ 0xbfda, 0x0967,
+ 0xbfe2, 0x1fe0,
+ 0xbfe5, 0x0972,
+ 0xbfe9, 0x1fe3,
+ 0xbfea, 0x0977,
+ 0xbfeb, 0x1fe4,
+ 0xbfec, 0x0979,
+ 0xbfed, 0x1fe5,
+ 0xbfee, 0x097b,
+ 0xbff3, 0x1fe6,
+ 0xbff4, 0x0981,
+ 0xbff5, 0x1fe7,
+ 0xbff6, 0x0983,
+ 0xbff7, 0x1fe8,
+ 0xbff8, 0x0985,
+ 0xbff9, 0x1fe9,
+ 0xbffb, 0x0988,
+ 0xc0a1, 0x1feb,
+ 0xc0a2, 0x098d,
+ 0xc0a3, 0x1fec,
+ 0xc0a4, 0x098f,
+ 0xc0a9, 0x1fed,
+ 0xc0aa, 0x0995,
+ 0xc0ab, 0x1fee,
+ 0xc0ac, 0x0997,
+ 0xc0af, 0x1fef,
+ 0xc0b1, 0x099c,
+ 0xc0b3, 0x1ff1,
+ 0xc0b7, 0x09a2,
+ 0xc0b8, 0x1ff5,
+ 0xc0c5, 0x09b0,
+ 0xc0cc, 0x2002,
+ 0xc0ce, 0x09b9,
+ 0xc0d4, 0x2004,
+ 0xc0d5, 0x09c0,
+ 0xc0d6, 0x2005,
+ 0xc0d7, 0x09c2,
+ 0xc0d8, 0x2006,
+ 0xc0d9, 0x09c4,
+ 0xc0dd, 0x2007,
+ 0xc0de, 0x09c9,
+ 0xc0e0, 0x2008,
+ 0xc0e1, 0x09cc,
+ 0xc0e9, 0x2009,
+ 0xc0ea, 0x09d5,
+ 0xc0eb, 0x200a,
+ 0xc0ed, 0x09d8,
+ 0xc0ef, 0x200c,
+ 0xc0f2, 0x09dd,
+ 0xc0f6, 0x200f,
+ 0xc0fb, 0x09e6,
+ 0xc1a1, 0x09ea,
+ 0xc1a4, 0x2014,
+ 0xc1a6, 0x09ef,
+ 0xc1a9, 0x2016,
+ 0xc1ae, 0x09f7,
+ 0xc1af, 0x201b,
+ 0xc1b9, 0x0a02,
+ 0xc1bd, 0x2025,
+ 0xc1bf, 0x0a08,
+ 0xc1c2, 0x2027,
+ 0xc1c3, 0x0a0c,
+ 0xc1c6, 0x2028,
+ 0xc1c7, 0x0a10,
+ 0xc1c9, 0x2029,
+ 0xc1ca, 0x0a13,
+ 0xc1cd, 0x202a,
+ 0xc1ce, 0x0a17,
+ 0xc1d4, 0x202b,
+ 0xc1d5, 0x0a1e,
+ 0xc1d9, 0x202c,
+ 0xc1dc, 0x0a25,
+ 0xc1de, 0x202f,
+ 0xc1df, 0x0a28,
+ 0xc1e4, 0x2030,
+ 0xc1e6, 0x0a2f,
+ 0xc1e9, 0x2032,
+ 0xc1ea, 0x0a33,
+ 0xc1eb, 0x2033,
+ 0xc1ed, 0x0a36,
+ 0xc1f3, 0x2035,
+ 0xc1f4, 0x0a3d,
+ 0xc1f5, 0x2036,
+ 0xc1f6, 0x0a3f,
+ 0xc1fa, 0x2037,
+ 0xc1fe, 0x0a47,
+ 0xc2a1, 0x0a48,
+ 0xc2a2, 0x203b,
+ 0xc2a9, 0x0a50,
+ 0xc2ab, 0x2042,
+ 0xc2b4, 0x0a5b,
+ 0xc2b8, 0x204b,
+ 0xc2b9, 0x0a60,
+ 0xc2bc, 0x204c,
+ 0xc2be, 0x0a65,
+ 0xc2bf, 0x204e,
+ 0xc2c0, 0x0a67,
+ 0xc2c1, 0x204f,
+ 0xc2c2, 0x0a69,
+ 0xc2c5, 0x2050,
+ 0xc2c8, 0x0a6f,
+ 0xc2cb, 0x2053,
+ 0xc2d1, 0x0a78,
+ 0xc2d2, 0x2059,
+ 0xc2d3, 0x0a7a,
+ 0xc2d5, 0x205a,
+ 0xc2dd, 0x0a84,
+ 0xc2de, 0x2062,
+ 0xc2e3, 0x0a8a,
+ 0xc2e6, 0x2067,
+ 0xc2e9, 0x0a90,
+ 0xc2ea, 0x206a,
+ 0xc2ef, 0x0a96,
+ 0xc2f0, 0x206f,
+ 0xc2f1, 0x0a98,
+ 0xc2f2, 0x2070,
+ 0xc2f6, 0x0a9d,
+ 0xc2f7, 0x2074,
+ 0xc2fb, 0x0aa2,
+ 0xc3a1, 0x2078,
+ 0xc3a2, 0x0aa7,
+ 0xc3aa, 0x2079,
+ 0xc3ab, 0x0ab0,
+ 0xc3ad, 0x207a,
+ 0xc3ae, 0x0ab3,
+ 0xc3b3, 0x207b,
+ 0xc3b4, 0x1df9,
+ 0xc3b5, 0x0aba,
+ 0xc3be, 0x207c,
+ 0xc3bf, 0x0ac4,
+ 0xc3c5, 0x207d,
+ 0xc3c8, 0x0acd,
+ 0xc3cc, 0x2080,
+ 0xc3cd, 0x0ad2,
+ 0xc3ce, 0x2081,
+ 0xc3cf, 0x0ad4,
+ 0xc3d5, 0x2082,
+ 0xc3d7, 0x0adc,
+ 0xc3d9, 0x2084,
+ 0xc3da, 0x0adf,
+ 0xc3e0, 0x2085,
+ 0xc3e1, 0x0ae6,
+ 0xc3e5, 0x2086,
+ 0xc3e6, 0x0aeb,
+ 0xc3ed, 0x2087,
+ 0xc3ee, 0x0af3,
+ 0xc3f0, 0x2088,
+ 0xc3f1, 0x0af6,
+ 0xc3f5, 0x2089,
+ 0xc3f7, 0x0afc,
+ 0xc3f9, 0x208b,
+ 0xc3fb, 0x0b00,
+ 0xc3fd, 0x208d,
+ 0xc3fe, 0x0b03,
+ 0xc4a1, 0x0b04,
+ 0xc4b1, 0x208e,
+ 0xc4b2, 0x0b15,
+ 0xc4b6, 0x208f,
+ 0xc4b7, 0x0b1a,
+ 0xc4c6, 0x2090,
+ 0xc4c7, 0x0b2a,
+ 0xc4c9, 0x2091,
+ 0xc4ca, 0x0b2d,
+ 0xc4d1, 0x2092,
+ 0xc4d2, 0x0b35,
+ 0xc4d3, 0x2093,
+ 0xc4d7, 0x0b3a,
+ 0xc4d9, 0x2097,
+ 0xc4da, 0x0b3d,
+ 0xc4e2, 0x2098,
+ 0xc4e3, 0x0b46,
+ 0xc4e5, 0x2099,
+ 0xc4e6, 0x0b49,
+ 0xc4ec, 0x209a,
+ 0xc4ed, 0x0b50,
+ 0xc4f0, 0x209b,
+ 0xc4f2, 0x0b55,
+ 0xc4f4, 0x209d,
+ 0xc4f5, 0x0b58,
+ 0xc4f6, 0x209e,
+ 0xc4f9, 0x0b5c,
+ 0xc4fb, 0x20a1,
+ 0xc4fd, 0x0b60,
+ 0xc4fe, 0x20a3,
+ 0xc5a1, 0x20a4,
+ 0xc5a3, 0x0b64,
+ 0xc5a5, 0x20a6,
+ 0xc5aa, 0x0b6b,
+ 0xc5b1, 0x20ab,
+ 0xc5b2, 0x0b73,
+ 0xc5b5, 0x20ac,
+ 0xc5b6, 0x0b77,
+ 0xc5b7, 0x20ad,
+ 0xc5ba, 0x0b7b,
+ 0xc5bb, 0x20b0,
+ 0xc5bc, 0x0b7d,
+ 0xc5bd, 0x20b1,
+ 0xc5be, 0x0b7f,
+ 0xc5cc, 0x20b2,
+ 0xc5cd, 0x0b8e,
+ 0xc5d3, 0x20b3,
+ 0xc5d4, 0x0b95,
+ 0xc5e2, 0x20b4,
+ 0xc5e3, 0x0ba4,
+ 0xc5e7, 0x20b5,
+ 0xc5e8, 0x0ba9,
+ 0xc5f4, 0x20b6,
+ 0xc5f5, 0x0bb6,
+ 0xc6a1, 0x0bc0,
+ 0xc6ad, 0x20b7,
+ 0xc6af, 0x0bce,
+ 0xc6b5, 0x20b9,
+ 0xc6b7, 0x0bd6,
+ 0xc6bb, 0x20bb,
+ 0xc6bc, 0x0bdb,
+ 0xc6be, 0x20bc,
+ 0xc6bf, 0x0bde,
+ 0xc6c0, 0x20bd,
+ 0xc6c1, 0x0be0,
+ 0xc6c3, 0x20be,
+ 0xc6c5, 0x0be4,
+ 0xc6cb, 0x20c0,
+ 0xc6ce, 0x0bed,
+ 0xc6d3, 0x20c3,
+ 0xc6d4, 0x0bf3,
+ 0xc6d7, 0x20c4,
+ 0xc6d8, 0x0bf7,
+ 0xc6ea, 0x20c5,
+ 0xc6ec, 0x0c0b,
+ 0xc6ef, 0x20c7,
+ 0xc6f0, 0x0c0f,
+ 0xc6f1, 0x20c8,
+ 0xc6f2, 0x0c11,
+ 0xc6f4, 0x20c9,
+ 0xc6f5, 0x0c14,
+ 0xc6f8, 0x20ca,
+ 0xc6f9, 0x0c18,
+ 0xc6fd, 0x20cb,
+ 0xc6fe, 0x0c1d,
+ 0xc7a1, 0x0c1e,
+ 0xc7a3, 0x20cc,
+ 0xc7a4, 0x0c21,
+ 0xc7a5, 0x20cd,
+ 0xc7a7, 0x0c24,
+ 0xc7a8, 0x20cf,
+ 0xc7aa, 0x0c27,
+ 0xc7ab, 0x20d1,
+ 0xc7ac, 0x0c29,
+ 0xc7ae, 0x20d2,
+ 0xc7b0, 0x0c2d,
+ 0xc7b3, 0x20d4,
+ 0xc7b6, 0x0c33,
+ 0xc7b9, 0x20d7,
+ 0xc7bb, 0x0c38,
+ 0xc7bd, 0x20d9,
+ 0xc7bf, 0x0c3c,
+ 0xc7c0, 0x20db,
+ 0xc7c1, 0x0c3e,
+ 0xc7c2, 0x20dc,
+ 0xc7c3, 0x0c40,
+ 0xc7c5, 0x20dd,
+ 0xc7c6, 0x0c43,
+ 0xc7c7, 0x20de,
+ 0xc7c9, 0x0c46,
+ 0xc7cc, 0x20e0,
+ 0xc7cd, 0x0c4a,
+ 0xc7cf, 0x20e1,
+ 0xc7d0, 0x0c4d,
+ 0xc7d4, 0x20e2,
+ 0xc7d6, 0x0c53,
+ 0xc7d7, 0x20e4,
+ 0xc7d8, 0x0c55,
+ 0xc7de, 0x20e5,
+ 0xc7df, 0x0c5c,
+ 0xc7e1, 0x20e6,
+ 0xc7e4, 0x0c61,
+ 0xc7ea, 0x20e9,
+ 0xc7ef, 0x0c6c,
+ 0xc7f7, 0x20ee,
+ 0xc7f9, 0x0c76,
+ 0xc7fb, 0x20f0,
+ 0xc7fc, 0x0c79,
+ 0xc7fd, 0x20f1,
+ 0xc7fe, 0x0c7b,
+ 0xc8a1, 0x0c7c,
+ 0xc8a3, 0x20f2,
+ 0xc8a4, 0x0c7f,
+ 0xc8a7, 0x20f3,
+ 0xc8a9, 0x0c84,
+ 0xc8b0, 0x20f5,
+ 0xc8b1, 0x0c8c,
+ 0xc8b5, 0x20f6,
+ 0xc8b6, 0x0c91,
+ 0xc8b7, 0x20f7,
+ 0xc8b8, 0x0c93,
+ 0xc8c3, 0x20f8,
+ 0xc8c7, 0x0ca2,
+ 0xc8c8, 0x20fc,
+ 0xc8c9, 0x0ca4,
+ 0xc8cd, 0x20fd,
+ 0xc8ce, 0x0ca9,
+ 0xc8cf, 0x20fe,
+ 0xc8d0, 0x0cab,
+ 0xc8d2, 0x20ff,
+ 0xc8d3, 0x0cae,
+ 0xc8d9, 0x2100,
+ 0xc8da, 0x0cb5,
+ 0xc8de, 0x2101,
+ 0xc8df, 0x0cba,
+ 0xc8ed, 0x2102,
+ 0xc8ee, 0x0cc9,
+ 0xc8f1, 0x2103,
+ 0xc8f4, 0x0ccf,
+ 0xc8f7, 0x2106,
+ 0xc8f9, 0x0cd4,
+ 0xc8fa, 0x2108,
+ 0xc8fb, 0x0cd6,
+ 0xc8fc, 0x2109,
+ 0xc8fd, 0x0cd8,
+ 0xc9a1, 0x210a,
+ 0xc9a2, 0x0cdb,
+ 0xc9a5, 0x210b,
+ 0xc9a6, 0x0cdf,
+ 0xc9a7, 0x210c,
+ 0xc9a9, 0x0ce2,
+ 0xc9ac, 0x210e,
+ 0xc9ad, 0x0ce6,
+ 0xc9b1, 0x210f,
+ 0xc9b2, 0x0ceb,
+ 0xc9b4, 0x2110,
+ 0xc9b5, 0x0cee,
+ 0xc9b8, 0x2111,
+ 0xc9ba, 0x0cf3,
+ 0xc9c1, 0x2113,
+ 0xc9c3, 0x0cfc,
+ 0xc9c4, 0x2115,
+ 0xc9c5, 0x0cfe,
+ 0xc9c9, 0x2116,
+ 0xc9ca, 0x0d03,
+ 0xc9cb, 0x2117,
+ 0xc9cc, 0x0d05,
+ 0xc9cd, 0x2118,
+ 0xc9ce, 0x0d07,
+ 0xc9d5, 0x2119,
+ 0xc9d6, 0x0d0f,
+ 0xc9dc, 0x211a,
+ 0xc9dd, 0x0d16,
+ 0xc9de, 0x211b,
+ 0xc9df, 0x0d18,
+ 0xc9e1, 0x211c,
+ 0xc9e2, 0x0d1b,
+ 0xc9e3, 0x211d,
+ 0xc9e4, 0x0d1d,
+ 0xc9e5, 0x211e,
+ 0xc9e6, 0x0d1f,
+ 0xc9e8, 0x211f,
+ 0xc9e9, 0x0d22,
+ 0xc9f0, 0x2120,
+ 0xc9f1, 0x0d2a,
+ 0xc9f3, 0x2121,
+ 0xc9f5, 0x0d2e,
+ 0xc9f6, 0x2123,
+ 0xc9f7, 0x0d30,
+ 0xc9f8, 0x2124,
+ 0xc9fa, 0x0d33,
+ 0xc9fe, 0x2126,
+ 0xcaa1, 0x0d38,
+ 0xcaa4, 0x2127,
+ 0xcaa7, 0x0d3e,
+ 0xcaa8, 0x212a,
+ 0xcaa9, 0x0d40,
+ 0xcaaa, 0x212b,
+ 0xcaac, 0x0d43,
+ 0xcab1, 0x212d,
+ 0xcab2, 0x0d49,
+ 0xcab4, 0x212e,
+ 0xcab7, 0x0d4e,
+ 0xcabb, 0x2131,
+ 0xcabc, 0x0d53,
+ 0xcac6, 0x2132,
+ 0xcac7, 0x0d5e,
+ 0xcaca, 0x2133,
+ 0xcacb, 0x0d62,
+ 0xcacd, 0x2134,
+ 0xcacf, 0x0d66,
+ 0xcad3, 0x2136,
+ 0xcad5, 0x0d6c,
+ 0xcad9, 0x2138,
+ 0xcada, 0x0d71,
+ 0xcade, 0x2139,
+ 0xcadf, 0x0d76,
+ 0xcae0, 0x213a,
+ 0xcae1, 0x0d78,
+ 0xcae4, 0x213b,
+ 0xcae5, 0x0d7c,
+ 0xcae9, 0x213c,
+ 0xcaeb, 0x0d82,
+ 0xcaf4, 0x213e,
+ 0xcaf6, 0x0d8d,
+ 0xcaf7, 0x2140,
+ 0xcaf8, 0x0d8f,
+ 0xcafa, 0x2141,
+ 0xcafb, 0x0d92,
+ 0xcafd, 0x2142,
+ 0xcafe, 0x0d95,
+ 0xcba1, 0x0d96,
+ 0xcba7, 0x2143,
+ 0xcba8, 0x0d9d,
+ 0xcbab, 0x2144,
+ 0xcbac, 0x0da1,
+ 0xcbad, 0x2145,
+ 0xcbae, 0x0da3,
+ 0xcbb3, 0x2146,
+ 0xcbb4, 0x0da9,
+ 0xcbb5, 0x2147,
+ 0xcbb7, 0x0dac,
+ 0xcbb8, 0x2149,
+ 0xcbb9, 0x0dae,
+ 0xcbbf, 0x214a,
+ 0xcbc0, 0x0db5,
+ 0xcbc7, 0x214b,
+ 0xcbc8, 0x0dbd,
+ 0xcbc9, 0x214c,
+ 0xcbcd, 0x0dc2,
+ 0xcbcf, 0x2150,
+ 0xcbd1, 0x0dc6,
+ 0xcbd3, 0x2152,
+ 0xcbd4, 0x0dc9,
+ 0xcbd5, 0x2153,
+ 0xcbd6, 0x0dcb,
+ 0xcbdf, 0x2154,
+ 0xcbe1, 0x0dd6,
+ 0xcbe4, 0x2156,
+ 0xcbe5, 0x0dda,
+ 0xcbe6, 0x2157,
+ 0xcbe8, 0x0ddd,
+ 0xcbea, 0x2159,
+ 0xcbeb, 0x0de0,
+ 0xcbef, 0x215a,
+ 0xcbf1, 0x0de6,
+ 0xcbf5, 0x215c,
+ 0xcbf7, 0x0dec,
+ 0xcbf8, 0x215e,
+ 0xcbf9, 0x0dee,
+ 0xcca1, 0x215f,
+ 0xcca3, 0x0df6,
+ 0xcca8, 0x2161,
+ 0xcca9, 0x0dfc,
+ 0xccac, 0x2162,
+ 0xccad, 0x0e00,
+ 0xccaf, 0x2163,
+ 0xccb4, 0x0e07,
+ 0xccb7, 0x2168,
+ 0xccb9, 0x0e0c,
+ 0xccbe, 0x216a,
+ 0xccbf, 0x0e12,
+ 0xccc0, 0x216b,
+ 0xccc1, 0x0e14,
+ 0xcccc, 0x216c,
+ 0xcccd, 0x0e20,
+ 0xccce, 0x216d,
+ 0xcccf, 0x0e22,
+ 0xccd0, 0x216e,
+ 0xccd1, 0x0e24,
+ 0xccd6, 0x216f,
+ 0xccd7, 0x0e2a,
+ 0xccda, 0x2170,
+ 0xccdb, 0x0e2e,
+ 0xccdc, 0x2171,
+ 0xccdd, 0x0e30,
+ 0xcce0, 0x2172,
+ 0xcce1, 0x0e34,
+ 0xcce2, 0x2173,
+ 0xcce3, 0x0e36,
+ 0xcce5, 0x2174,
+ 0xcce6, 0x0e39,
+ 0xccf5, 0x2175,
+ 0xccf6, 0x0e49,
+ 0xccf9, 0x2176,
+ 0xccfb, 0x0e4e,
+ 0xccfc, 0x2178,
+ 0xcda1, 0x0e52,
+ 0xcdad, 0x217b,
+ 0xcdae, 0x0e5f,
+ 0xcdb3, 0x217c,
+ 0xcdb4, 0x0e65,
+ 0xcdb7, 0x217d,
+ 0xcdb8, 0x0e69,
+ 0xcdbc, 0x217e,
+ 0xcdbd, 0x0e6e,
+ 0xcdbf, 0x217f,
+ 0xcdc0, 0x0e71,
+ 0xcdc5, 0x2180,
+ 0xcdc6, 0x0e77,
+ 0xcdc7, 0x2181,
+ 0xcdc8, 0x0e79,
+ 0xcdd2, 0x2182,
+ 0xcdd3, 0x0e84,
+ 0xcdd4, 0x2183,
+ 0xcdd7, 0x0e88,
+ 0xcddd, 0x2186,
+ 0xcdde, 0x0e8f,
+ 0xcde0, 0x2187,
+ 0xcde1, 0x0e92,
+ 0xcde4, 0x2188,
+ 0xcde6, 0x0e97,
+ 0xcde7, 0x218a,
+ 0xcde8, 0x0e99,
+ 0xcdf2, 0x218b,
+ 0xcdf3, 0x0ea4,
+ 0xcdf8, 0x218c,
+ 0xcdf9, 0x0eaa,
+ 0xcea1, 0x0eb0,
+ 0xcea4, 0x218d,
+ 0xcea6, 0x0eb5,
+ 0xcea7, 0x218f,
+ 0xcea8, 0x0eb7,
+ 0xceaa, 0x2190,
+ 0xceae, 0x0ebd,
+ 0xceb0, 0x2194,
+ 0xceb2, 0x0ec1,
+ 0xceb3, 0x2196,
+ 0xceb4, 0x0ec3,
+ 0xcebd, 0x2197,
+ 0xcebe, 0x0ecd,
+ 0xcec0, 0x2198,
+ 0xcec1, 0x0ed0,
+ 0xcec5, 0x2199,
+ 0xcec7, 0x0ed6,
+ 0xcec8, 0x219b,
+ 0xcec9, 0x0ed8,
+ 0xceca, 0x219c,
+ 0xcecb, 0x0eda,
+ 0xcece, 0x219d,
+ 0xced2, 0x0ee1,
+ 0xced8, 0x21a1,
+ 0xcedb, 0x0eea,
+ 0xcedc, 0x21a4,
+ 0xcedd, 0x0eec,
+ 0xcede, 0x21a5,
+ 0xcee0, 0x0eef,
+ 0xceeb, 0x21a7,
+ 0xceec, 0x0efb,
+ 0xceed, 0x21a8,
+ 0xceee, 0x0efd,
+ 0xcef1, 0x21a9,
+ 0xcef2, 0x0f01,
+ 0xcef3, 0x21aa,
+ 0xcef4, 0x0f03,
+ 0xcefd, 0x21ab,
+ 0xcfa1, 0x0f0e,
+ 0xcfae, 0x21ad,
+ 0xcfaf, 0x0f1c,
+ 0xcfb0, 0x21ae,
+ 0xcfb1, 0x0f1e,
+ 0xcfb3, 0x21af,
+ 0xcfb4, 0x0f21,
+ 0xcfb7, 0x21b0,
+ 0xcfb9, 0x0f26,
+ 0xcfba, 0x21b2,
+ 0xcfbb, 0x0f28,
+ 0xcfbd, 0x21b3,
+ 0xcfbe, 0x0f2b,
+ 0xcfbf, 0x21b4,
+ 0xcfc2, 0x0f2f,
+ 0xcfc5, 0x21b7,
+ 0xcfc6, 0x0f33,
+ 0xcfc7, 0x21b8,
+ 0xcfc8, 0x0f35,
+ 0xcfca, 0x21b9,
+ 0xcfcc, 0x0f39,
+ 0xcfcd, 0x21bb,
+ 0xcfcf, 0x0f3c,
+ 0xcfd0, 0x21bd,
+ 0xcfd1, 0x0f3e,
+ 0xcfd4, 0x21be,
+ 0xcfd9, 0x0f46,
+ 0xcfda, 0x21c3,
+ 0xcfdb, 0x0f48,
+ 0xcfdc, 0x21c4,
+ 0xcfdd, 0x0f4a,
+ 0xcfdf, 0x21c5,
+ 0xcfe0, 0x0f4d,
+ 0xcfe2, 0x21c6,
+ 0xcfe3, 0x0f50,
+ 0xcfe7, 0x21c7,
+ 0xcfe8, 0x0f55,
+ 0xcfea, 0x21c8,
+ 0xcfeb, 0x0f58,
+ 0xcfec, 0x21c9,
+ 0xcfed, 0x0f5a,
+ 0xcfee, 0x21ca,
+ 0xcfef, 0x0f5c,
+ 0xcff4, 0x21cb,
+ 0xcff5, 0x0f62,
+ 0xcff9, 0x21cc,
+ 0xcffb, 0x0f68,
+ 0xcffe, 0x21ce,
+ 0xd0a1, 0x0f6c,
+ 0xd0a5, 0x21cf,
+ 0xd0a6, 0x0f71,
+ 0xd0ad, 0x21d0,
+ 0xd0af, 0x0f7a,
+ 0xd0b2, 0x21d2,
+ 0xd0b5, 0x0f80,
+ 0xd0ba, 0x21d5,
+ 0xd0bc, 0x0f87,
+ 0xd0bf, 0x21d7,
+ 0xd0c0, 0x0f8b,
+ 0xd0c6, 0x21d8,
+ 0xd0c7, 0x0f92,
+ 0xd0cb, 0x21d9,
+ 0xd0cc, 0x0f97,
+ 0xd0e2, 0x21da,
+ 0xd0e3, 0x0fae,
+ 0xd0e5, 0x21db,
+ 0xd0e6, 0x0fb1,
+ 0xd0eb, 0x21dc,
+ 0xd0ec, 0x0fb7,
+ 0xd0ed, 0x21dd,
+ 0xd0ee, 0x0fb9,
+ 0xd0f7, 0x21de,
+ 0xd0fa, 0x0fc5,
+ 0xd0fc, 0x21e1,
+ 0xd0fd, 0x0fc8,
+ 0xd1a1, 0x21e2,
+ 0xd1a3, 0x0fcc,
+ 0xd1a4, 0x21e4,
+ 0xd1a5, 0x0fce,
+ 0xd1a7, 0x21e5,
+ 0xd1a8, 0x0fd1,
+ 0xd1ab, 0x21e6,
+ 0xd1ac, 0x0fd5,
+ 0xd1af, 0x21e7,
+ 0xd1b2, 0x0fdb,
+ 0xd1b5, 0x21ea,
+ 0xd1b8, 0x0fe1,
+ 0xd1b9, 0x21ed,
+ 0xd1ba, 0x0fe3,
+ 0xd1bb, 0x21ee,
+ 0xd1bd, 0x0fe6,
+ 0xd1c6, 0x21f0,
+ 0xd1c9, 0x0ff2,
+ 0xd1cb, 0x21f3,
+ 0xd1cc, 0x0ff5,
+ 0xd1ce, 0x21f4,
+ 0xd1d0, 0x0ff9,
+ 0xd1d5, 0x21f6,
+ 0xd1d7, 0x1000,
+ 0xd1de, 0x21f8,
+ 0xd1df, 0x1008,
+ 0xd1e1, 0x21f9,
+ 0xd1e3, 0x100c,
+ 0xd1e8, 0x21fb,
+ 0xd1ea, 0x1013,
+ 0xd1ec, 0x21fd,
+ 0xd1ed, 0x1016,
+ 0xd1ee, 0x21fe,
+ 0xd1f0, 0x1019,
+ 0xd1f1, 0x2200,
+ 0xd1f2, 0x101b,
+ 0xd1f4, 0x2201,
+ 0xd1f5, 0x101e,
+ 0xd1f7, 0x2202,
+ 0xd1fa, 0x1023,
+ 0xd2a1, 0x1028,
+ 0xd2a2, 0x2205,
+ 0xd2a3, 0x102a,
+ 0xd2a5, 0x2206,
+ 0xd2a6, 0x102d,
+ 0xd2a9, 0x2207,
+ 0xd2aa, 0x1031,
+ 0xd2af, 0x2208,
+ 0xd2b0, 0x1037,
+ 0xd2b3, 0x2209,
+ 0xd2b4, 0x103b,
+ 0xd2b5, 0x220a,
+ 0xd2b7, 0x103e,
+ 0xd2bd, 0x220c,
+ 0xd2be, 0x1045,
+ 0xd2bf, 0x220d,
+ 0xd2c0, 0x1047,
+ 0xd2c3, 0x220e,
+ 0xd2c4, 0x104b,
+ 0xd2c5, 0x220f,
+ 0xd2c6, 0x104d,
+ 0xd2c7, 0x2210,
+ 0xd2c8, 0x104f,
+ 0xd2cf, 0x2211,
+ 0xd2d0, 0x1057,
+ 0xd2d5, 0x2212,
+ 0xd2d6, 0x105d,
+ 0xd2da, 0x2213,
+ 0xd2db, 0x1062,
+ 0xd2e4, 0x2214,
+ 0xd2e6, 0x106d,
+ 0xd2e8, 0x2216,
+ 0xd2ec, 0x1073,
+ 0xd2ef, 0x221a,
+ 0xd2f0, 0x1077,
+ 0xd2f1, 0x221b,
+ 0xd2f2, 0x1079,
+ 0xd2f5, 0x221c,
+ 0xd2f6, 0x107d,
+ 0xd2f8, 0x221d,
+ 0xd2f9, 0x1080,
+ 0xd2fb, 0x221e,
+ 0xd2fc, 0x1083,
+ 0xd2fe, 0x221f,
+ 0xd3a1, 0x1086,
+ 0xd3a3, 0x2220,
+ 0xd3ad, 0x1092,
+ 0xd3ae, 0x222a,
+ 0xd3af, 0x1094,
+ 0xd3b1, 0x222b,
+ 0xd3b2, 0x1097,
+ 0xd3b4, 0x222c,
+ 0xd3b7, 0x109c,
+ 0xd3b8, 0x222f,
+ 0xd3b9, 0x109e,
+ 0xd3bb, 0x2230,
+ 0xd3bc, 0x10a1,
+ 0xd3c5, 0x2231,
+ 0xd3c6, 0x10ab,
+ 0xd3c7, 0x2232,
+ 0xd3c8, 0x10ad,
+ 0xd3ca, 0x2233,
+ 0xd3cd, 0x10b2,
+ 0xd3d5, 0x2236,
+ 0xd3d6, 0x10bb,
+ 0xd3df, 0x2237,
+ 0xd3e1, 0x10c6,
+ 0xd3e3, 0x2239,
+ 0xd3e4, 0x10c9,
+ 0xd3e6, 0x223a,
+ 0xd3e7, 0x10cc,
+ 0xd3eb, 0x223b,
+ 0xd3ed, 0x10d2,
+ 0xd3ef, 0x223d,
+ 0xd3f0, 0x10d5,
+ 0xd3f4, 0x223e,
+ 0xd3f5, 0x10da,
+ 0xd3fc, 0x223f,
+ 0xd3fd, 0x10e2,
+ 0xd3fe, 0x2240,
+ 0xd4a1, 0x10e4,
+ 0xd4a4, 0x2241,
+ 0xd4a5, 0x10e8,
+ 0xd4a6, 0x2242,
+ 0xd4a9, 0x10ec,
+ 0xd4af, 0x2245,
+ 0xd4b3, 0x10f6,
+ 0xd4b5, 0x2249,
+ 0xd4b7, 0x10fa,
+ 0xd4b8, 0x224b,
+ 0xd4b9, 0x10fc,
+ 0xd4bc, 0x224c,
+ 0xd4bd, 0x1100,
+ 0xd4be, 0x224d,
+ 0xd4c0, 0x1103,
+ 0xd4c4, 0x224f,
+ 0xd4c5, 0x1108,
+ 0xd4c6, 0x2250,
+ 0xd4c8, 0x110b,
+ 0xd4c9, 0x2252,
+ 0xd4ca, 0x110d,
+ 0xd4cb, 0x2253,
+ 0xd4cf, 0x1112,
+ 0xd4d3, 0x2257,
+ 0xd4d4, 0x1117,
+ 0xd4d8, 0x2258,
+ 0xd4d9, 0x111c,
+ 0xd4dc, 0x2259,
+ 0xd4e1, 0x1124,
+ 0xd4e4, 0x225e,
+ 0xd4e5, 0x1128,
+ 0xd4e6, 0x225f,
+ 0xd4e7, 0x112a,
+ 0xd4ee, 0x2260,
+ 0xd4ef, 0x1132,
+ 0xd4f0, 0x2261,
+ 0xd4f5, 0x1138,
+ 0xd4f9, 0x2266,
+ 0xd4fa, 0x113d,
+ 0xd4fe, 0x2267,
+ 0xd5a1, 0x2268,
+ 0xd5a3, 0x1144,
+ 0xd5a9, 0x226a,
+ 0xd5aa, 0x114b,
+ 0xd5ab, 0x226b,
+ 0xd5ac, 0x114d,
+ 0xd5ae, 0x226c,
+ 0xd5af, 0x1150,
+ 0xd5b1, 0x226d,
+ 0xd5b2, 0x1153,
+ 0xd5b5, 0x226e,
+ 0xd5b9, 0x115a,
+ 0xd5bb, 0x2272,
+ 0xd5bc, 0x115d,
+ 0xd5bd, 0x2273,
+ 0xd5be, 0x115f,
+ 0xd5c0, 0x2274,
+ 0xd5c1, 0x1162,
+ 0xd5c5, 0x2275,
+ 0xd5c6, 0x1167,
+ 0xd5c7, 0x2276,
+ 0xd5c8, 0x1169,
+ 0xd5ca, 0x2277,
+ 0xd5cc, 0x116d,
+ 0xd5cd, 0x2279,
+ 0xd5ce, 0x116f,
+ 0xd5d4, 0x227a,
+ 0xd5d5, 0x1176,
+ 0xd5dd, 0x227b,
+ 0xd5df, 0x1180,
+ 0xd5e0, 0x227d,
+ 0xd5e1, 0x1182,
+ 0xd5e2, 0x227e,
+ 0xd5e3, 0x1184,
+ 0xd5ea, 0x227f,
+ 0xd5ed, 0x118e,
+ 0xd5ef, 0x2282,
+ 0xd5f0, 0x1191,
+ 0xd5f2, 0x2283,
+ 0xd5f4, 0x1195,
+ 0xd5f7, 0x15eb,
+ 0xd5f8, 0x1199,
+ 0xd6a1, 0x2285,
+ 0xd6a5, 0x11a4,
+ 0xd6af, 0x2289,
+ 0xd6b1, 0x11b0,
+ 0xd6b4, 0x228b,
+ 0xd6b5, 0x11b4,
+ 0xd6bb, 0x228c,
+ 0xd6bc, 0x11bb,
+ 0xd6bd, 0x228d,
+ 0xd6be, 0x11bd,
+ 0xd6bf, 0x228e,
+ 0xd6c1, 0x11c0,
+ 0xd6c4, 0x2290,
+ 0xd6c5, 0x11c4,
+ 0xd6ca, 0x2291,
+ 0xd6cb, 0x11ca,
+ 0xd6cd, 0x2292,
+ 0xd6ce, 0x11cd,
+ 0xd6d3, 0x2293,
+ 0xd6d4, 0x11d3,
+ 0xd6d5, 0x2294,
+ 0xd6d8, 0x11d7,
+ 0xd6da, 0x2297,
+ 0xd6db, 0x11da,
+ 0xd6df, 0x2298,
+ 0xd6e0, 0x11df,
+ 0xd6e1, 0x2299,
+ 0xd6e2, 0x11e1,
+ 0xd6e5, 0x229a,
+ 0xd6e6, 0x11e5,
+ 0xd6e7, 0x229b,
+ 0xd6e9, 0x11e8,
+ 0xd6ee, 0x229d,
+ 0xd6f0, 0x11ef,
+ 0xd6f2, 0x229f,
+ 0xd6f3, 0x11f2,
+ 0xd6f5, 0x22a0,
+ 0xd6f7, 0x11f6,
+ 0xd6fc, 0x22a2,
+ 0xd7a1, 0x11fe,
+ 0xd7a4, 0x22a5,
+ 0xd7a5, 0x1202,
+ 0xd7a8, 0x22a6,
+ 0xd7ab, 0x1208,
+ 0xd7ac, 0x22a9,
+ 0xd7ad, 0x120a,
+ 0xd7ae, 0x22aa,
+ 0xd7b2, 0x120f,
+ 0xd7b3, 0x22ae,
+ 0xd7b5, 0x1212,
+ 0xd7b6, 0x22b0,
+ 0xd7b7, 0x1214,
+ 0xd7b8, 0x22b1,
+ 0xd7bd, 0x121a,
+ 0xd7c7, 0x22b6,
+ 0xd7c8, 0x1225,
+ 0xd7ca, 0x22b7,
+ 0xd7cb, 0x1228,
+ 0xd7d5, 0x22b8,
+ 0xd7d6, 0x1233,
+ 0xd7db, 0x22b9,
+ 0xd7df, 0x123c,
+ 0xd7e7, 0x22bd,
+ 0xd7e8, 0x1245,
+ 0xd7e9, 0x22be,
+ 0xd7eb, 0x1248,
+ 0xd8a1, 0x1257,
+ 0xd8c4, 0x22c0,
+ 0xd8c5, 0x127b,
+ 0xd8c7, 0x22c1,
+ 0xd8c8, 0x127e,
+ 0xd8c9, 0x22c2,
+ 0xd8ca, 0x1280,
+ 0xd8cc, 0x22c3,
+ 0xd8ce, 0x1284,
+ 0xd8d0, 0x22c5,
+ 0xd8d2, 0x1288,
+ 0xd8d3, 0x22c7,
+ 0xd8d4, 0x128a,
+ 0xd8d9, 0x22c8,
+ 0xd8da, 0x1290,
+ 0xd8db, 0x22c9,
+ 0xd8dd, 0x1293,
+ 0xd8f1, 0x22cb,
+ 0xd8f2, 0x12a8,
+ 0xd8f6, 0x22cc,
+ 0xd8f8, 0x12ae,
+ 0xd9a1, 0x12b5,
+ 0xd9ad, 0x22ce,
+ 0xd9ae, 0x12c2,
+ 0xd9af, 0x22cf,
+ 0xd9b0, 0x12c4,
+ 0xd9b1, 0x22d0,
+ 0xd9b4, 0x12c8,
+ 0xd9c7, 0x22d3,
+ 0xd9c8, 0x12dc,
+ 0xd9cd, 0x22d4,
+ 0xd9d1, 0x12e5,
+ 0xd9dd, 0x22d8,
+ 0xd9de, 0x12f2,
+ 0xd9e1, 0x22d9,
+ 0xd9e2, 0x12f6,
+ 0xd9e4, 0x22da,
+ 0xd9e5, 0x12f9,
+ 0xd9e6, 0x22db,
+ 0xd9e7, 0x12fb,
+ 0xd9ec, 0x22dc,
+ 0xd9ed, 0x1301,
+ 0xd9f4, 0x22dd,
+ 0xd9f6, 0x130a,
+ 0xdaa1, 0x1313,
+ 0xdaa5, 0x22df,
+ 0xdae0, 0x1352,
+ 0xdaea, 0x231a,
+ 0xdaeb, 0x135d,
+ 0xdaf7, 0x231b,
+ 0xdaf8, 0x136a,
+ 0xdaf9, 0x231c,
+ 0xdafa, 0x136c,
+ 0xdafe, 0x231d,
+ 0xdba1, 0x1371,
+ 0xdba3, 0x231e,
+ 0xdba4, 0x1374,
+ 0xdba6, 0x231f,
+ 0xdba7, 0x1377,
+ 0xdba9, 0x2320,
+ 0xdbab, 0x137b,
+ 0xdbbb, 0x2322,
+ 0xdbbc, 0x138c,
+ 0xdbbd, 0x2323,
+ 0xdbbe, 0x138e,
+ 0xdbcf, 0x2324,
+ 0xdbd0, 0x13a0,
+ 0xdbd1, 0x2325,
+ 0xdbd2, 0x13a2,
+ 0xdbdb, 0x2326,
+ 0xdbdc, 0x13ac,
+ 0xdbde, 0x2327,
+ 0xdbdf, 0x13af,
+ 0xdbe2, 0x2328,
+ 0xdbe3, 0x13b3,
+ 0xdbe4, 0x2329,
+ 0xdbe5, 0x13b5,
+ 0xdbeb, 0x232a,
+ 0xdbec, 0x13bc,
+ 0xdbee, 0x232b,
+ 0xdbef, 0x13bf,
+ 0xdbf1, 0x232c,
+ 0xdbf2, 0x13c2,
+ 0xdbf5, 0x232d,
+ 0xdbf8, 0x13c8,
+ 0xdca1, 0x13cf,
+ 0xdcbc, 0x2330,
+ 0xdcbd, 0x13eb,
+ 0xdcbf, 0x2331,
+ 0xdcc0, 0x13ee,
+ 0xdcc2, 0x2332,
+ 0xdcc3, 0x13f1,
+ 0xdcc8, 0x2333,
+ 0xdccb, 0x13f9,
+ 0xdcd1, 0x2336,
+ 0xdcd2, 0x1400,
+ 0xdcd7, 0x2337,
+ 0xdcd8, 0x1406,
+ 0xdce0, 0x2338,
+ 0xdce1, 0x140f,
+ 0xdce3, 0x2339,
+ 0xdce5, 0x1413,
+ 0xdce9, 0x233b,
+ 0xdceb, 0x1419,
+ 0xdcf1, 0x233d,
+ 0xdcf2, 0x1420,
+ 0xdcf6, 0x233e,
+ 0xdcf7, 0x1425,
+ 0xdcf9, 0x233f,
+ 0xdcfa, 0x1428,
+ 0xdcfd, 0x2340,
+ 0xdda1, 0x2342,
+ 0xdda2, 0x142e,
+ 0xdda3, 0x2343,
+ 0xdda8, 0x1434,
+ 0xddaa, 0x2348,
+ 0xddac, 0x1438,
+ 0xddb2, 0x234a,
+ 0xddb3, 0x143f,
+ 0xddb5, 0x234b,
+ 0xddb6, 0x1442,
+ 0xddba, 0x234c,
+ 0xddbc, 0x1448,
+ 0xddd3, 0x234e,
+ 0xddd4, 0x1460,
+ 0xdddb, 0x234f,
+ 0xdddc, 0x1468,
+ 0xddde, 0x2350,
+ 0xdddf, 0x146b,
+ 0xdde4, 0x2351,
+ 0xdde5, 0x1471,
+ 0xddeb, 0x2352,
+ 0xddec, 0x1478,
+ 0xddf1, 0x2353,
+ 0xddf2, 0x147e,
+ 0xddf6, 0x2354,
+ 0xddf8, 0x1484,
+ 0xddfc, 0x2356,
+ 0xddfd, 0x1489,
+ 0xddfe, 0x2357,
+ 0xdea1, 0x148b,
+ 0xdead, 0x2358,
+ 0xdeae, 0x1498,
+ 0xdeb4, 0x2359,
+ 0xdeb5, 0x149f,
+ 0xdeba, 0x235a,
+ 0xdebb, 0x14a5,
+ 0xdec6, 0x235b,
+ 0xdec7, 0x14b1,
+ 0xdecf, 0x235c,
+ 0xded0, 0x14ba,
+ 0xded1, 0x235d,
+ 0xded3, 0x14bd,
+ 0xded8, 0x235f,
+ 0xded9, 0x14c3,
+ 0xdee2, 0x2360,
+ 0xdee3, 0x14cd,
+ 0xdee8, 0x2361,
+ 0xdee9, 0x14d3,
+ 0xdeec, 0x2362,
+ 0xdeed, 0x14d7,
+ 0xdef3, 0x2363,
+ 0xdef4, 0x14de,
+ 0xdefc, 0x2364,
+ 0xdefd, 0x14e7,
+ 0xdfa1, 0x14e9,
+ 0xdfa2, 0x2365,
+ 0xdfa4, 0x14ec,
+ 0xdfa5, 0x2367,
+ 0xdfa6, 0x14ee,
+ 0xdfb4, 0x2368,
+ 0xdfb5, 0x14fd,
+ 0xdfbc, 0x2369,
+ 0xdfbe, 0x1506,
+ 0xdfbf, 0x236b,
+ 0xdfc0, 0x1508,
+ 0xdfc2, 0x236c,
+ 0xdfc4, 0x150c,
+ 0xdfcc, 0x236e,
+ 0xdfcd, 0x1515,
+ 0xdfd0, 0x236f,
+ 0xdfd1, 0x1519,
+ 0xdfd5, 0x2370,
+ 0xdfd6, 0x151e,
+ 0xdfd8, 0x2371,
+ 0xdfda, 0x1522,
+ 0xdfdc, 0x2373,
+ 0xdfdd, 0x1525,
+ 0xdfe0, 0x2374,
+ 0xdfe1, 0x1529,
+ 0xdfe2, 0x2375,
+ 0xdfe3, 0x152b,
+ 0xdfe6, 0x2376,
+ 0xdfe7, 0x152f,
+ 0xdfe9, 0x2377,
+ 0xdfea, 0x1532,
+ 0xdfeb, 0x2378,
+ 0xdfec, 0x1534,
+ 0xdfef, 0x2379,
+ 0xdff0, 0x1538,
+ 0xdff5, 0x237a,
+ 0xdff6, 0x153e,
+ 0xdff9, 0x237b,
+ 0xdffa, 0x1542,
+ 0xe0a1, 0x1547,
+ 0xe0b6, 0x237c,
+ 0xe0b8, 0x155e,
+ 0xe0bf, 0x237e,
+ 0xe0c0, 0x1566,
+ 0xe0c8, 0x237f,
+ 0xe0c9, 0x156f,
+ 0xe0ce, 0x2380,
+ 0xe0cf, 0x1575,
+ 0xe0d3, 0x2381,
+ 0xe0d4, 0x157a,
+ 0xe0e0, 0x2382,
+ 0xe0e1, 0x1587,
+ 0xe0f0, 0x2383,
+ 0xe0f1, 0x1597,
+ 0xe0f8, 0x2384,
+ 0xe0f9, 0x159f,
+ 0xe0fc, 0x2385,
+ 0xe1a1, 0x15a5,
+ 0xe1ab, 0x2388,
+ 0xe1ac, 0x15b0,
+ 0xe1ad, 0x2389,
+ 0xe1ae, 0x15b2,
+ 0xe1b0, 0x238a,
+ 0xe1b1, 0x15b5,
+ 0xe1b4, 0x238b,
+ 0xe1b5, 0x15b9,
+ 0xe1bb, 0x238c,
+ 0xe1bc, 0x15c0,
+ 0xe1bd, 0x238d,
+ 0xe1be, 0x15c2,
+ 0xe1c0, 0x238e,
+ 0xe1c2, 0x15c6,
+ 0xe1c9, 0x2390,
+ 0xe1ca, 0x15ce,
+ 0xe1d0, 0x2391,
+ 0xe1d1, 0x15d5,
+ 0xe1db, 0x2392,
+ 0xe1dc, 0x15e0,
+ 0xe1e1, 0x07aa,
+ 0xe1e2, 0x2393,
+ 0xe1e3, 0x15e7,
+ 0xe1e7, 0x1198,
+ 0xe1e8, 0x15ec,
+ 0xe1ee, 0x2394,
+ 0xe1f0, 0x15f4,
+ 0xe1f6, 0x2396,
+ 0xe1f7, 0x15fb,
+ 0xe1f8, 0x2397,
+ 0xe1f9, 0x15fd,
+ 0xe1fd, 0x2398,
+ 0xe1fe, 0x1602,
+ 0xe2a1, 0x1603,
+ 0xe2a4, 0x2399,
+ 0xe2a5, 0x1607,
+ 0xe2a8, 0x239a,
+ 0xe2a9, 0x160b,
+ 0xe2bb, 0x239b,
+ 0xe2c5, 0x10c5,
+ 0xe2c6, 0x23a5,
+ 0xe2cf, 0x1631,
+ 0xe2d0, 0x23ae,
+ 0xe2d1, 0x1633,
+ 0xe2d9, 0x23af,
+ 0xe2da, 0x163c,
+ 0xe2e3, 0x23b0,
+ 0xe2e5, 0x1647,
+ 0xe2e6, 0x23b2,
+ 0xe2e7, 0x1649,
+ 0xe2e9, 0x23b3,
+ 0xe2ec, 0x164e,
+ 0xe2f8, 0x23b6,
+ 0xe2f9, 0x165b,
+ 0xe2fa, 0x23b7,
+ 0xe2fe, 0x1660,
+ 0xe3a1, 0x1661,
+ 0xe3a2, 0x23bb,
+ 0xe3a3, 0x1663,
+ 0xe3a5, 0x23bc,
+ 0xe3a6, 0x1666,
+ 0xe3ab, 0x23bd,
+ 0xe3ac, 0x166c,
+ 0xe3b4, 0x23be,
+ 0xe3b5, 0x1675,
+ 0xe3c5, 0x23bf,
+ 0xe3dc, 0x169c,
+ 0xe3e3, 0x23d6,
+ 0xe3e4, 0x16a4,
+ 0xe3ed, 0x23d7,
+ 0xe3ee, 0x16ae,
+ 0xe3f1, 0x23d8,
+ 0xe3f3, 0x16b3,
+ 0xe3f8, 0x23da,
+ 0xe3f9, 0x16b9,
+ 0xe3fe, 0x23db,
+ 0xe4a1, 0x16bf,
+ 0xe4a4, 0x23dc,
+ 0xe4a6, 0x16c4,
+ 0xe4ab, 0x23de,
+ 0xe4ac, 0x16ca,
+ 0xe4af, 0x23df,
+ 0xe4b2, 0x16d0,
+ 0xe4b5, 0x23e2,
+ 0xe4b7, 0x16d5,
+ 0xe4c2, 0x23e4,
+ 0xe4c3, 0x16e1,
+ 0xe4c5, 0x23e5,
+ 0xe4c6, 0x16e4,
+ 0xe4c9, 0x23e6,
+ 0xe4ca, 0x16e8,
+ 0xe4d9, 0x23e7,
+ 0xe4da, 0x16f8,
+ 0xe4dc, 0x23e8,
+ 0xe4dd, 0x16fb,
+ 0xe4de, 0x23e9,
+ 0xe4df, 0x16fd,
+ 0xe4e4, 0x23ea,
+ 0xe4e5, 0x1703,
+ 0xe4eb, 0x23eb,
+ 0xe4ed, 0x170b,
+ 0xe4f2, 0x23ed,
+ 0xe4f3, 0x1711,
+ 0xe4fe, 0x23ee,
+ 0xe5a1, 0x171d,
+ 0xe5b0, 0x23ef,
+ 0xe5b1, 0x172d,
+ 0xe5b9, 0x23f0,
+ 0xe5ba, 0x1736,
+ 0xe5c7, 0x23f1,
+ 0xe5c8, 0x1744,
+ 0xe5c9, 0x23f2,
+ 0xe5ca, 0x1746,
+ 0xe5ce, 0x23f3,
+ 0xe5cf, 0x174b,
+ 0xe5f0, 0x23f4,
+ 0xe5f1, 0x176d,
+ 0xe5f2, 0x23f5,
+ 0xe5f3, 0x176f,
+ 0xe5fc, 0x23f6,
+ 0xe5fe, 0x177a,
+ 0xe6a1, 0x177b,
+ 0xe6a3, 0x23f8,
+ 0xe6a4, 0x177e,
+ 0xe6ab, 0x23f9,
+ 0xe6ad, 0x1787,
+ 0xe6ae, 0x23fb,
+ 0xe6af, 0x1789,
+ 0xe6b4, 0x23fc,
+ 0xe6b6, 0x1790,
+ 0xe6bf, 0x23fe,
+ 0xe6c0, 0x179a,
+ 0xe6c8, 0x23ff,
+ 0xe6ca, 0x17a4,
+ 0xe6cd, 0x2401,
+ 0xe6ce, 0x17a8,
+ 0xe6e0, 0x2402,
+ 0xe7a1, 0x2421,
+ 0xe7db, 0x1813,
+ 0xe7e1, 0x245b,
+ 0xe7e3, 0x181b,
+ 0xe7e7, 0x245d,
+ 0xe7e8, 0x1820,
+ 0xe7ef, 0x245e,
+ 0xe7f0, 0x1828,
+ 0xe7f4, 0x245f,
+ 0xe7f7, 0x182f,
+ 0xe8a1, 0x1837,
+ 0xe8a8, 0x2462,
+ 0xe8a9, 0x183f,
+ 0xe8ac, 0x2463,
+ 0xe8ad, 0x1843,
+ 0xe8b6, 0x2464,
+ 0xe8b7, 0x184d,
+ 0xe8b8, 0x2465,
+ 0xe8bb, 0x1851,
+ 0xe8bf, 0x2468,
+ 0xe8c1, 0x1857,
+ 0xe8c5, 0x246a,
+ 0xe8c6, 0x185c,
+ 0xe8c7, 0x246b,
+ 0xe8ca, 0x1860,
+ 0xe8ce, 0x246e,
+ 0xe8cf, 0x1865,
+ 0xe8d0, 0x246f,
+ 0xe8d1, 0x1867,
+ 0xe8d3, 0x2470,
+ 0xe8d4, 0x186a,
+ 0xe8dd, 0x2471,
+ 0xe8de, 0x1874,
+ 0xe8df, 0x2472,
+ 0xe8e0, 0x1876,
+ 0xe8e2, 0x2473,
+ 0xe8e4, 0x187a,
+ 0xe8e5, 0x2475,
+ 0xe8e6, 0x187c,
+ 0xe8e7, 0x2476,
+ 0xe8e8, 0x187e,
+ 0xe8eb, 0x2477,
+ 0xe8ec, 0x1882,
+ 0xe8ed, 0x2478,
+ 0xe8ee, 0x1884,
+ 0xe8ef, 0x2479,
+ 0xe8f0, 0x1886,
+ 0xe8f9, 0x247a,
+ 0xe8fa, 0x1890,
+ 0xe8fc, 0x247b,
+ 0xe8fe, 0x1894,
+ 0xe9a1, 0x247d,
+ 0xe9a2, 0x1896,
+ 0xe9ad, 0x247e,
+ 0xe9ae, 0x18a2,
+ 0xe9b4, 0x247f,
+ 0xe9b6, 0x18aa,
+ 0xe9b7, 0x2481,
+ 0xe9b8, 0x18ac,
+ 0xe9c4, 0x2482,
+ 0xe9c5, 0x18b9,
+ 0xe9c6, 0x2483,
+ 0xe9c7, 0x18bb,
+ 0xe9c9, 0x2484,
+ 0xe9ca, 0x18be,
+ 0xe9d6, 0x2485,
+ 0xe9d7, 0x18cb,
+ 0xe9da, 0x2486,
+ 0xe9db, 0x18cf,
+ 0xe9e4, 0x2487,
+ 0xe9e5, 0x18d9,
+ 0xe9e6, 0x2488,
+ 0xe9e8, 0x18dc,
+ 0xe9e9, 0x248a,
+ 0xe9ea, 0x18de,
+ 0xe9eb, 0x248b,
+ 0xe9ec, 0x18e0,
+ 0xe9ed, 0x248c,
+ 0xeaa1, 0x249e,
+ 0xeaa6, 0x18f8,
+ 0xeaa7, 0x24a3,
+ 0xeaa9, 0x18fb,
+ 0xeab1, 0x24a5,
+ 0xeab2, 0x1904,
+ 0xeabc, 0x24a6,
+ 0xeabd, 0x190f,
+ 0xeaca, 0x24a7,
+ 0xeacb, 0x191d,
+ 0xeacd, 0x24a8,
+ 0xeace, 0x1920,
+ 0xead3, 0x24a9,
+ 0xead4, 0x1926,
+ 0xeada, 0x24aa,
+ 0xeaf0, 0x1942,
+ 0xeba1, 0x1951,
+ 0xeba7, 0x24c0,
+ 0xeba8, 0x1958,
+ 0xebaa, 0x24c1,
+ 0xebab, 0x195b,
+ 0xebb2, 0x24c2,
+ 0xebb3, 0x1963,
+ 0xebb9, 0x24c3,
+ 0xebba, 0x196a,
+ 0xebca, 0x24c4,
+ 0xebcc, 0x197c,
+ 0xebcd, 0x24c6,
+ 0xebce, 0x197e,
+ 0xebd6, 0x24c7,
+ 0xebd7, 0x1987,
+ 0xebda, 0x24c8,
+ 0xebdb, 0x198b,
+ 0xebe1, 0x24c9,
+ 0xebe2, 0x1992,
+ 0xebf7, 0x24ca,
+ 0xebf8, 0x19a8,
+ 0xeca1, 0x19af,
+ 0xeca3, 0x24cb,
+ 0xeca4, 0x19b2,
+ 0xeca9, 0x24cc,
+ 0xecaf, 0x19bd,
+ 0xecb1, 0x24d2,
+ 0xecb2, 0x19c0,
+ 0xecb4, 0x24d3,
+ 0xecb6, 0x19c4,
+ 0xecbe, 0x24d5,
+ 0xecc0, 0x19ce,
+ 0xecc1, 0x24d7,
+ 0xecc2, 0x19d0,
+ 0xecc7, 0x24d8,
+ 0xecc8, 0x19d6,
+ 0xeccb, 0x24d9,
+ 0xeccc, 0x19da,
+ 0xece2, 0x24da,
+ 0xece3, 0x19f1,
+ 0xecf2, 0x24db,
+ 0xecf3, 0x1a01,
+ 0xecf5, 0x24dc,
+ 0xecf6, 0x1a04,
+ 0xecf8, 0x24dd,
+ 0xecf9, 0x1a07,
+ 0xeda1, 0x24de,
+ 0xeda2, 0x1a0e,
+ 0xeda8, 0x24df,
+ 0xeda9, 0x1a15,
+ 0xedaf, 0x24e0,
+ 0xedb1, 0x1a1d,
+ 0xedb4, 0x24e2,
+ 0xedb5, 0x1a21,
+ 0xedb6, 0x24e3,
+ 0xedb7, 0x1a23,
+ 0xedb8, 0x24e4,
+ 0xedb9, 0x1a25,
+ 0xedba, 0x24e5,
+ 0xedbb, 0x1a27,
+ 0xedbf, 0x24e6,
+ 0xedc0, 0x1a2c,
+ 0xedc2, 0x24e7,
+ 0xedc4, 0x1a30,
+ 0xedcc, 0x24e9,
+ 0xedce, 0x1a3a,
+ 0xedd3, 0x24eb,
+ 0xedd4, 0x1a40,
+ 0xedd7, 0x24ec,
+ 0xedd8, 0x1a44,
+ 0xede8, 0x24ed,
+ 0xede9, 0x1a55,
+ 0xedee, 0x24ee,
+ 0xedef, 0x1a5b,
+ 0xedf9, 0x24ef,
+ 0xedfb, 0x1a67,
+ 0xeea1, 0x1a6b,
+ 0xeebc, 0x24f1,
+ 0xeebd, 0x1a87,
+ 0xeebf, 0x24f2,
+ 0xeec0, 0x1a8a,
+ 0xeec4, 0x24f3,
+ 0xefa1, 0x252e,
+ 0xeff2, 0x1b1a,
+ 0xf0a1, 0x1b27,
+ 0xf0a3, 0x257f,
+ 0xf0a4, 0x1b2a,
+ 0xf0af, 0x2580,
+ 0xf0da, 0x1b60,
+ 0xf0dc, 0x25ab,
+ 0xf0de, 0x1b64,
+ 0xf0df, 0x25ad,
+ 0xf0e0, 0x1b66,
+ 0xf0e9, 0x25ae,
+ 0xf0ea, 0x1b70,
+ 0xf0ec, 0x25af,
+ 0xf0ed, 0x1b73,
+ 0xf0ef, 0x25b0,
+ 0xf0f0, 0x1b76,
+ 0xf0f7, 0x25b1,
+ 0xf0f8, 0x1b7e,
+ 0xf0f9, 0x25b2,
+ 0xf0fa, 0x1b80,
+ 0xf0fc, 0x25b3,
+ 0xf0fd, 0x1b83,
+ 0xf1a1, 0x1b85,
+ 0xf1a8, 0x25b4,
+ 0xf1a9, 0x1b8d,
+ 0xf1ab, 0x25b5,
+ 0xf1ac, 0x1b90,
+ 0xf1ae, 0x25b6,
+ 0xf1af, 0x1b93,
+ 0xf1b2, 0x25b7,
+ 0xf1b3, 0x1b97,
+ 0xf1bc, 0x25b8,
+ 0xf1bd, 0x1ba1,
+ 0xf1c0, 0x25b9,
+ 0xf1c1, 0x1ba5,
+ 0xf1c9, 0x25ba,
+ 0xf1ca, 0x1bae,
+ 0xf1cd, 0x25bb,
+ 0xf1ce, 0x1bb2,
+ 0xf1cf, 0x25bc,
+ 0xf1d1, 0x1bb5,
+ 0xf1da, 0x25be,
+ 0xf1db, 0x1bbf,
+ 0xf1dc, 0x25bf,
+ 0xf1dd, 0x1bc1,
+ 0xf1e4, 0x25c0,
+ 0xf1e5, 0x1bc9,
+ 0xf1ec, 0x25c1,
+ 0xf1ed, 0x1bd1,
+ 0xf1ef, 0x25c2,
+ 0xf1f0, 0x1bd4,
+ 0xf1f7, 0x25c3,
+ 0xf1f8, 0x1bdc,
+ 0xf1f9, 0x25c4,
+ 0xf1fa, 0x1bde,
+ 0xf1fc, 0x25c5,
+ 0xf2a1, 0x25c8,
+ 0xf2ae, 0x1bf0,
+ 0xf2b1, 0x25d5,
+ 0xf2b3, 0x1bf5,
+ 0xf2b9, 0x25d7,
+ 0xf2ba, 0x1bfc,
+ 0xf2c3, 0x25d8,
+ 0xf2c4, 0x1c06,
+ 0xf2c9, 0x25d9,
+ 0xf2ca, 0x1c0c,
+ 0xf2cc, 0x25da,
+ 0xf2ce, 0x1c10,
+ 0xf2cf, 0x25dc,
+ 0xf2d0, 0x1c12,
+ 0xf2d3, 0x25dd,
+ 0xf2d4, 0x1c16,
+ 0xf2e5, 0x25de,
+ 0xf2e6, 0x1c28,
+ 0xf2ee, 0x25df,
+ 0xf2ef, 0x1c31,
+ 0xf2f7, 0x25e0,
+ 0xf2f8, 0x1c3a,
+ 0xf2fd, 0x25e1,
+ 0xf2fe, 0x1c40,
+ 0xf3a1, 0x1c41,
+ 0xf3bf, 0x25e2,
+ 0xf3c0, 0x1c60,
+ 0xf3c6, 0x25e3,
+ 0xf3c7, 0x1c67,
+ 0xf3c8, 0x25e4,
+ 0xf3c9, 0x1c69,
+ 0xf3d6, 0x25e5,
+ 0xf3d7, 0x1c77,
+ 0xf3d9, 0x25e6,
+ 0xf3da, 0x1c7a,
+ 0xf3e5, 0x25e7,
+ 0xf3e7, 0x1c87,
+ 0xf3ea, 0x25e9,
+ 0xf3eb, 0x1c8b,
+ 0xf3ec, 0x25ea,
+ 0xf3ed, 0x1c8d,
+ 0xf3ef, 0x25eb,
+ 0xf3f0, 0x1c90,
+ 0xf3f1, 0x25ec,
+ 0xf3f2, 0x1c92,
+ 0xf3fd, 0x25ed,
+ 0xf3fe, 0x1c9e,
+ 0xf4a1, 0x1c9f,
+ 0xf4a5, 0x25ee,
+ 0xf4a6, 0x1ca4,
+ 0xf4af, 0x25ef,
+ 0xf4b0, 0x1cae,
+ 0xf4b5, 0x25f0,
+ 0xf4b6, 0x1cb4,
+ 0xf4c1, 0x25f1,
+ 0xf4c2, 0x1cc0,
+ 0xf4c7, 0x25f2,
+ 0xf4c8, 0x1cc6,
+ 0xf4cf, 0x25f3,
+ 0xf4d1, 0x1ccf,
+ 0xf4d6, 0x25f5,
+ 0xf4d7, 0x1cd5,
+ 0xf4ea, 0x25f6,
+ 0xf4eb, 0x1ce9,
+ 0xf4ef, 0x25f7,
+ 0xf4f0, 0x1cee,
+ 0xf4f5, 0x25f8,
+ 0xf4f6, 0x1cf4,
+ 0xf5a1, 0x1cfd,
+ 0xf5a6, 0x25f9,
+ 0xf5a8, 0x1d04,
+ 0xf5ba, 0x25fb,
+ 0xf5bc, 0x1d18,
+ 0xf5c4, 0x25fd,
+ 0xf5c5, 0x1d21,
+ 0xf5c8, 0x25fe,
+ 0xf5c9, 0x1d25,
+ 0xf5ce, 0x25ff,
+ 0xf5d0, 0x1d2c,
+ 0xf5d1, 0x2601,
+ 0xf5d3, 0x1d2f,
+ 0xf5d9, 0x2603,
+ 0xf5da, 0x1d36,
+ 0xf5dc, 0x2604,
+ 0xf5dd, 0x1d39,
+ 0xf5e6, 0x2605,
+ 0xf5e8, 0x1d44,
+ 0xf5ef, 0x2607,
+ 0xf5f0, 0x1d4c,
+ 0xf5f2, 0x2608,
+ 0xf5f3, 0x1d4f,
+ 0xf5fc, 0x2609,
+ 0xf5fd, 0x1d59,
+ 0xf6a1, 0x1d5b,
+ 0xf6a3, 0x260a,
+ 0xf6a4, 0x1d5e,
+ 0xf6a6, 0x260b,
+ 0xf6a7, 0x1d61,
+ 0xf6a8, 0x260c,
+ 0xf6a9, 0x1d63,
+ 0xf6ab, 0x260d,
+ 0xf6ac, 0x1d66,
+ 0xf6b0, 0x260e,
+ 0xf6b1, 0x1d6b,
+ 0xf6b3, 0x260f,
+ 0xf6bf, 0x1d79,
+ 0xf6c5, 0x261b,
+ 0xf6c6, 0x1d80,
+ 0xf6c7, 0x261c,
+ 0xf6c8, 0x1d82,
+ 0xf6c9, 0x261d,
+ 0xf6ca, 0x1d84,
+ 0xf6cf, 0x261e,
+ 0xf7a1, 0x264e,
+ 0xf7b0, 0x1dc8,
+ 0xf7b2, 0x265d,
+ 0xf7b4, 0x1dcc,
+ 0xf7b5, 0x265f,
+ 0xf7b6, 0x1dce,
+ 0xf7bd, 0x2660,
+ 0xf7be, 0x1dd6,
+ 0xf7c3, 0x2661,
+ 0xf7c4, 0x1ddc,
+ 0xf7c5, 0x2662,
+ 0xf7c7, 0x1ddf,
+ 0xf7ca, 0x2664,
+ 0xf7cc, 0x1de4,
+ 0xf7cf, 0x2666,
+ 0xf7d1, 0x1de9,
+ 0xf7de, 0x2668,
+ 0xf7df, 0x1df7,
+ 0xf7e1, 0x0ab9,
+ 0xf7e2, 0x1dfa,
+ 0xf7f2, 0x2669,
+ 0xf7f3, 0x1e0b,
+ 0xf7f5, 0x266a,
+ 0xf7f6, 0x1e0e,
+ 0xf8a1, 0x266b,
+ 0xf8a7, 0x04cc,
+ 0xf8a8, 0x050a,
+ 0xf8a9, 0x0518,
+ 0xf8aa, 0x2671,
+ 0xf8ac, 0x0594,
+ 0xf8ad, 0x05ce,
+ 0xf8ae, 0x2673,
+ 0xf8af, 0x05f6,
+ 0xf8b0, 0x2674,
+ 0xf8b2, 0x0653,
+ 0xf8b3, 0x067e,
+ 0xf8b4, 0x2676,
+ 0xf8b5, 0x06c4,
+ 0xf8b6, 0x2677,
+ 0xf8b8, 0x073c,
+ 0xf8b9, 0x2679,
+ 0xf8bb, 0x07c3,
+ 0xf8bc, 0x267b,
+ 0xf8c0, 0x082b,
+ 0xf8c1, 0x267f,
+ 0xf8c2, 0x084e,
+ 0xf8c3, 0x0869,
+ 0xf8c4, 0x2680,
+ 0xf8c6, 0x090c,
+ 0xf8c7, 0x2682,
+ 0xf8c9, 0x0971,
+ 0xf8ca, 0x2684,
+ 0xf8cb, 0x099a,
+ 0xf8cd, 0x2685,
+ 0xf8ce, 0x09da,
+ 0xf8cf, 0x2686,
+ 0xf8d0, 0x09fa,
+ 0xf8d1, 0x2687,
+ 0xf8dc, 0x0bda,
+ 0xf8dd, 0x0bdd,
+ 0xf8de, 0x0bea,
+ 0xf8df, 0x0bec,
+ 0xf8e0, 0x0bf2,
+ 0xf8e1, 0x2692,
+ 0xf8e6, 0x0c92,
+ 0xf8e7, 0x0d1a,
+ 0xf8e8, 0x0d8c,
+ 0xf8e9, 0x0dbe,
+ 0xf8ea, 0x2697,
+ 0xf8eb, 0x0dfb,
+ 0xf8ec, 0x2698,
+ 0xf8ef, 0x0e70,
+ 0xf8f0, 0x269b,
+ 0xf8f1, 0x0ea3,
+ 0xf8f2, 0x269c,
+ 0xf8f8, 0x103d,
+ 0xf8f9, 0x10d9,
+ 0xf8fa, 0x26a2,
+ 0xf8fc, 0x10fb,
+ 0xf8fd, 0x1109,
+ 0xf8fe, 0x26a4,
+ 0xf9a1, 0x11a1,
+ 0xf9a2, 0x26a5,
+ 0xf9a3, 0x11ba,
+ 0xf9a4, 0x26a6,
+ 0xf9a6, 0x11d5,
+ 0xf9a7, 0x26a8,
+ 0xf9a8, 0x11fd,
+ 0xf9a9, 0x1219,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTpcEUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 },
+ gb12GBTpcEUCHMap2, 2283
+};
+
+static Gushort gb12GBTpcEUCVMap2[4606] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb0a8, 0x1e25,
+ 0xb0a9, 0x03b4,
+ 0xb0aa, 0x1e26,
+ 0xb0ab, 0x03b6,
+ 0xb0ad, 0x1e27,
+ 0xb0af, 0x03ba,
+ 0xb0b9, 0x1e29,
+ 0xb0ba, 0x03c5,
+ 0xb0c0, 0x1e2a,
+ 0xb0c1, 0x03cc,
+ 0xb0d3, 0x1e2b,
+ 0xb0d4, 0x03df,
+ 0xb0d5, 0x1e2c,
+ 0xb0d6, 0x03e1,
+ 0xb0da, 0x1e2d,
+ 0xb0db, 0x03e6,
+ 0xb0dc, 0x1e2e,
+ 0xb0dd, 0x03e8,
+ 0xb0e4, 0x1e2f,
+ 0xb0e5, 0x03f0,
+ 0xb0ec, 0x1e30,
+ 0xb0ee, 0x03f9,
+ 0xb0ef, 0x1e32,
+ 0xb0f0, 0x03fb,
+ 0xb0f3, 0x1e33,
+ 0xb0f4, 0x03ff,
+ 0xb0f7, 0x1e34,
+ 0xb0f8, 0x0403,
+ 0xb0f9, 0x1e35,
+ 0xb0fa, 0x0405,
+ 0xb1a1, 0x040a,
+ 0xb1a5, 0x1e36,
+ 0xb1a7, 0x0410,
+ 0xb1a8, 0x1e38,
+ 0xb1a9, 0x0412,
+ 0xb1ab, 0x1e39,
+ 0xb1ac, 0x0415,
+ 0xb1b2, 0x1e3a,
+ 0xb1b3, 0x041c,
+ 0xb1b4, 0x1e3b,
+ 0xb1b6, 0x041f,
+ 0xb1b7, 0x1e3d,
+ 0xb1ba, 0x0423,
+ 0xb1c1, 0x1e40,
+ 0xb1c2, 0x042b,
+ 0xb1ca, 0x1e41,
+ 0xb1cb, 0x0434,
+ 0xb1cf, 0x1e42,
+ 0xb1d1, 0x043a,
+ 0xb1d2, 0x1e44,
+ 0xb1d3, 0x043c,
+ 0xb1d5, 0x1e45,
+ 0xb1d6, 0x043f,
+ 0xb1df, 0x1e46,
+ 0xb1e2, 0x044b,
+ 0xb1e4, 0x1e49,
+ 0xb1e5, 0x044e,
+ 0xb1e7, 0x1e4a,
+ 0xb1e9, 0x0452,
+ 0xb1ea, 0x1e4c,
+ 0xb1eb, 0x0454,
+ 0xb1ee, 0x1e4d,
+ 0xb1ef, 0x0458,
+ 0xb1f1, 0x1e4e,
+ 0xb1f2, 0x045b,
+ 0xb1f4, 0x1e4f,
+ 0xb1f8, 0x0461,
+ 0xb1fd, 0x1e53,
+ 0xb1fe, 0x0467,
+ 0xb2a1, 0x0468,
+ 0xb2a6, 0x1e54,
+ 0xb2a8, 0x046f,
+ 0xb2ac, 0x1e56,
+ 0xb2ad, 0x0474,
+ 0xb2b5, 0x1e57,
+ 0xb2b6, 0x047d,
+ 0xb2b9, 0x1e58,
+ 0xb2ba, 0x0481,
+ 0xb2c6, 0x1e59,
+ 0xb2c7, 0x048e,
+ 0xb2ce, 0x1e5a,
+ 0xb2d8, 0x049f,
+ 0xb2de, 0x1e64,
+ 0xb2df, 0x04a6,
+ 0xb2e0, 0x1e65,
+ 0xb2e1, 0x04a8,
+ 0xb2e2, 0x1e66,
+ 0xb2e4, 0x04ab,
+ 0xb2ef, 0x1e68,
+ 0xb2f0, 0x04b7,
+ 0xb2f3, 0x1e69,
+ 0xb2fd, 0x04c4,
+ 0xb3a1, 0x1e73,
+ 0xb3a3, 0x04c8,
+ 0xb3a4, 0x1e75,
+ 0xb3a8, 0x04cd,
+ 0xb3a9, 0x1e79,
+ 0xb3aa, 0x04cf,
+ 0xb3ae, 0x1e7a,
+ 0xb3af, 0x04d4,
+ 0xb3b5, 0x1e7b,
+ 0xb3b6, 0x04db,
+ 0xb3b9, 0x1e7c,
+ 0xb3ba, 0x04df,
+ 0xb3be, 0x1e7d,
+ 0xb3bf, 0x04e4,
+ 0xb3c2, 0x1e7e,
+ 0xb3c3, 0x04e8,
+ 0xb3c4, 0x1e7f,
+ 0xb3c5, 0x04ea,
+ 0xb3c6, 0x1e80,
+ 0xb3c7, 0x04ec,
+ 0xb3cd, 0x1e81,
+ 0xb3ce, 0x04f3,
+ 0xb3cf, 0x1e82,
+ 0xb3d0, 0x04f5,
+ 0xb3d2, 0x1e83,
+ 0xb3d3, 0x04f8,
+ 0xb3d9, 0x1e84,
+ 0xb3da, 0x04ff,
+ 0xb3db, 0x1e85,
+ 0xb3dc, 0x0501,
+ 0xb3dd, 0x1e86,
+ 0xb3de, 0x0503,
+ 0xb3e3, 0x1e87,
+ 0xb3e4, 0x0509,
+ 0xb3e5, 0x1e88,
+ 0xb3e7, 0x050c,
+ 0xb3e8, 0x1e8a,
+ 0xb3e9, 0x050e,
+ 0xb3eb, 0x1e8b,
+ 0xb3ed, 0x0512,
+ 0xb3ef, 0x1e8d,
+ 0xb3f0, 0x0515,
+ 0xb3f1, 0x1e8e,
+ 0xb3f2, 0x0517,
+ 0xb3f3, 0x1e8f,
+ 0xb3f4, 0x0519,
+ 0xb3fa, 0x1e90,
+ 0xb3fc, 0x0521,
+ 0xb4a1, 0x1e92,
+ 0xb4a3, 0x0526,
+ 0xb4a5, 0x1e94,
+ 0xb4a7, 0x052a,
+ 0xb4ab, 0x1e96,
+ 0xb4ac, 0x052f,
+ 0xb4af, 0x1e97,
+ 0xb4b0, 0x0533,
+ 0xb4b3, 0x1e98,
+ 0xb4b5, 0x0538,
+ 0xb4b8, 0x1e9a,
+ 0xb4b9, 0x053c,
+ 0xb4bf, 0x1e9b,
+ 0xb4c0, 0x0543,
+ 0xb4c2, 0x1e9c,
+ 0xb4c3, 0x0546,
+ 0xb4c7, 0x1e9d,
+ 0xb4c8, 0x054b,
+ 0xb4ca, 0x1e9e,
+ 0xb4cb, 0x054e,
+ 0xb4cd, 0x1e9f,
+ 0xb4ce, 0x0551,
+ 0xb4cf, 0x1ea0,
+ 0xb4d0, 0x0553,
+ 0xb4d3, 0x1ea1,
+ 0xb4d5, 0x0558,
+ 0xb4da, 0x1ea3,
+ 0xb4db, 0x055e,
+ 0xb4dc, 0x1ea4,
+ 0xb4dd, 0x0560,
+ 0xb4ed, 0x1ea5,
+ 0xb4ee, 0x0571,
+ 0xb4ef, 0x1ea6,
+ 0xb4f0, 0x0573,
+ 0xb4f8, 0x1ea7,
+ 0xb4f9, 0x057c,
+ 0xb4fb, 0x1ea8,
+ 0xb4fc, 0x057f,
+ 0xb5a1, 0x0582,
+ 0xb5a3, 0x1ea9,
+ 0xb5a4, 0x0585,
+ 0xb5a5, 0x1eaa,
+ 0xb5a9, 0x058a,
+ 0xb5ac, 0x1eae,
+ 0xb5ad, 0x058e,
+ 0xb5ae, 0x1eaf,
+ 0xb5b0, 0x0591,
+ 0xb5b1, 0x1eb1,
+ 0xb5b6, 0x0597,
+ 0xb5b7, 0x1eb6,
+ 0xb5b8, 0x0599,
+ 0xb5ba, 0x1eb7,
+ 0xb5bd, 0x059e,
+ 0xb5c6, 0x1eba,
+ 0xb5c7, 0x05a8,
+ 0xb5cb, 0x1ebb,
+ 0xb5cc, 0x05ad,
+ 0xb5d0, 0x1ebc,
+ 0xb5d1, 0x05b2,
+ 0xb5d3, 0x1ebd,
+ 0xb5d4, 0x05b5,
+ 0xb5dd, 0x1ebe,
+ 0xb5e0, 0x05c1,
+ 0xb5e3, 0x1ec1,
+ 0xb5e4, 0x05c5,
+ 0xb5e6, 0x1ec2,
+ 0xb5e8, 0x05c9,
+ 0xb5ed, 0x1ec4,
+ 0xb5ee, 0x05cf,
+ 0xb5f6, 0x1ec5,
+ 0xb5f8, 0x05d9,
+ 0xb5fd, 0x1ec7,
+ 0xb5fe, 0x05df,
+ 0xb6a1, 0x05e0,
+ 0xb6a4, 0x1ec8,
+ 0xb6a6, 0x05e5,
+ 0xb6a7, 0x1eca,
+ 0xb6a8, 0x05e7,
+ 0xb6a9, 0x1ecb,
+ 0xb6aa, 0x05e9,
+ 0xb6ab, 0x1ecc,
+ 0xb6ac, 0x05eb,
+ 0xb6af, 0x1ecd,
+ 0xb6b1, 0x05f0,
+ 0xb6b3, 0x1ecf,
+ 0xb6b4, 0x05f3,
+ 0xb6b7, 0x1ed0,
+ 0xb6b8, 0x05f7,
+ 0xb6bf, 0x1ed1,
+ 0xb6c2, 0x0601,
+ 0xb6c4, 0x1ed4,
+ 0xb6c5, 0x0604,
+ 0xb6c6, 0x1ed5,
+ 0xb6c7, 0x0606,
+ 0xb6cd, 0x1ed6,
+ 0xb6ce, 0x060d,
+ 0xb6cf, 0x1ed7,
+ 0xb6d1, 0x0610,
+ 0xb6d3, 0x1ed9,
+ 0xb6d5, 0x0614,
+ 0xb6d6, 0x1edb,
+ 0xb6d7, 0x0616,
+ 0xb6d9, 0x1edc,
+ 0xb6da, 0x0619,
+ 0xb6db, 0x1edd,
+ 0xb6dc, 0x061b,
+ 0xb6e1, 0x1ede,
+ 0xb6e2, 0x0621,
+ 0xb6e9, 0x1edf,
+ 0xb6ea, 0x0629,
+ 0xb6ec, 0x1ee0,
+ 0xb6ed, 0x062c,
+ 0xb6ee, 0x1ee1,
+ 0xb6f0, 0x062f,
+ 0xb6f1, 0x1ee3,
+ 0xb6f2, 0x0631,
+ 0xb6f6, 0x1ee4,
+ 0xb6f7, 0x0636,
+ 0xb6f9, 0x1ee5,
+ 0xb6fa, 0x0639,
+ 0xb6fb, 0x1ee6,
+ 0xb6fd, 0x063c,
+ 0xb7a1, 0x1ee8,
+ 0xb7a4, 0x0641,
+ 0xb7a7, 0x1eeb,
+ 0xb7a8, 0x0645,
+ 0xb7af, 0x1eec,
+ 0xb7b1, 0x064e,
+ 0xb7b3, 0x1eee,
+ 0xb7b4, 0x0651,
+ 0xb7b6, 0x1eef,
+ 0xb7b8, 0x0655,
+ 0xb7b9, 0x1ef1,
+ 0xb7ba, 0x0657,
+ 0xb7c3, 0x1ef2,
+ 0xb7c5, 0x0662,
+ 0xb7c9, 0x1ef4,
+ 0xb7ca, 0x0667,
+ 0xb7cc, 0x1ef5,
+ 0xb7cd, 0x066a,
+ 0xb7cf, 0x1ef6,
+ 0xb7d0, 0x066d,
+ 0xb7d1, 0x1ef7,
+ 0xb7d2, 0x066f,
+ 0xb7d7, 0x1ef8,
+ 0xb7d9, 0x0676,
+ 0xb7dc, 0x1efa,
+ 0xb7dd, 0x067a,
+ 0xb7df, 0x1efb,
+ 0xb7e2, 0x067f,
+ 0xb7e3, 0x1efe,
+ 0xb7e4, 0x0681,
+ 0xb7e6, 0x1eff,
+ 0xb7e9, 0x0686,
+ 0xb7eb, 0x1f02,
+ 0xb7ee, 0x068b,
+ 0xb7ef, 0x1f05,
+ 0xb7f0, 0x068d,
+ 0xb7f4, 0x1f06,
+ 0xb7f5, 0x0692,
+ 0xb7f8, 0x1f07,
+ 0xb7f9, 0x0696,
+ 0xb8a1, 0x069c,
+ 0xb8a7, 0x1f08,
+ 0xb8a9, 0x06a4,
+ 0xb8b3, 0x1f0a,
+ 0xb8b5, 0x06b0,
+ 0xb8ba, 0x1f0c,
+ 0xb8bb, 0x06b6,
+ 0xb8bc, 0x1f0d,
+ 0xb8bd, 0x06b8,
+ 0xb8be, 0x1f0e,
+ 0xb8c0, 0x06bb,
+ 0xb8c3, 0x1f10,
+ 0xb8c4, 0x06bf,
+ 0xb8c6, 0x1f11,
+ 0xb8c8, 0x06c3,
+ 0xb8c9, 0x1f13,
+ 0xb8ca, 0x06c5,
+ 0xb8cf, 0x1f14,
+ 0xb8d0, 0x06cb,
+ 0xb8d3, 0x1f15,
+ 0xb8d7, 0x06d2,
+ 0xb8d9, 0x1f19,
+ 0xb8db, 0x06d6,
+ 0xb8e4, 0x1f1b,
+ 0xb8e5, 0x06e0,
+ 0xb8e9, 0x1f1c,
+ 0xb8ea, 0x06e5,
+ 0xb8eb, 0x1f1d,
+ 0xb8ec, 0x06e7,
+ 0xb8f3, 0x1f1e,
+ 0xb8f4, 0x06ef,
+ 0xb8f5, 0x1f1f,
+ 0xb8f7, 0x06f2,
+ 0xb8f8, 0x1f21,
+ 0xb8f9, 0x06f4,
+ 0xb9a1, 0x06fa,
+ 0xb9a8, 0x1f22,
+ 0xb9a9, 0x0702,
+ 0xb9ae, 0x1f23,
+ 0xb9af, 0x0708,
+ 0xb9b1, 0x1f24,
+ 0xb9b2, 0x070b,
+ 0xb9b3, 0x1f25,
+ 0xb9b4, 0x070d,
+ 0xb9b5, 0x1f26,
+ 0xb9b6, 0x070f,
+ 0xb9b9, 0x1f27,
+ 0xb9bb, 0x0714,
+ 0xb9c6, 0x1f29,
+ 0xb9c7, 0x0720,
+ 0xb9cb, 0x1f2a,
+ 0xb9cc, 0x0725,
+ 0xb9d0, 0x1f2b,
+ 0xb9d1, 0x072a,
+ 0xb9d8, 0x1f2c,
+ 0xb9d9, 0x0732,
+ 0xb9db, 0x1f2d,
+ 0xb9dc, 0x0735,
+ 0xb9dd, 0x1f2e,
+ 0xb9de, 0x0737,
+ 0xb9df, 0x1f2f,
+ 0xb9e0, 0x0739,
+ 0xb9e1, 0x1f30,
+ 0xb9e2, 0x073b,
+ 0xb9e3, 0x1f31,
+ 0xb9e4, 0x073d,
+ 0xb9e6, 0x1f32,
+ 0xb9e7, 0x0740,
+ 0xb9e9, 0x1f33,
+ 0xb9ed, 0x0746,
+ 0xb9ee, 0x1f37,
+ 0xb9ef, 0x0748,
+ 0xb9f1, 0x1f38,
+ 0xb9f2, 0x074b,
+ 0xb9f3, 0x1f39,
+ 0xb9f6, 0x074f,
+ 0xb9f8, 0x1f3c,
+ 0xb9f9, 0x0752,
+ 0xb9fa, 0x1f3d,
+ 0xb9fb, 0x0754,
+ 0xb9fd, 0x1f3e,
+ 0xb9fe, 0x0757,
+ 0xbaa1, 0x0758,
+ 0xbaa7, 0x1f3f,
+ 0xbaa8, 0x075f,
+ 0xbaab, 0x1f40,
+ 0xbaac, 0x0763,
+ 0xbaba, 0x1f41,
+ 0xbabb, 0x0772,
+ 0xbac5, 0x1f42,
+ 0xbac6, 0x077d,
+ 0xbad2, 0x1f43,
+ 0xbad3, 0x078a,
+ 0xbad7, 0x1f44,
+ 0xbad9, 0x0790,
+ 0xbae4, 0x1f46,
+ 0xbae5, 0x079c,
+ 0xbae8, 0x1f47,
+ 0xbae9, 0x07a0,
+ 0xbaec, 0x1f48,
+ 0xbaed, 0x07a4,
+ 0xbaf3, 0x15e5,
+ 0xbaf4, 0x07ab,
+ 0xbaf8, 0x1f49,
+ 0xbaf9, 0x07b0,
+ 0xbba1, 0x07b6,
+ 0xbba4, 0x1f4a,
+ 0xbba5, 0x07ba,
+ 0xbba6, 0x1f4b,
+ 0xbba7, 0x07bc,
+ 0xbba9, 0x1f4c,
+ 0xbbab, 0x07c0,
+ 0xbbad, 0x1f4e,
+ 0xbbaf, 0x07c4,
+ 0xbbb0, 0x1f50,
+ 0xbbb1, 0x07c6,
+ 0xbbb3, 0x1f51,
+ 0xbbb4, 0x07c9,
+ 0xbbb5, 0x1f52,
+ 0xbbb8, 0x07cd,
+ 0xbbb9, 0x1f55,
+ 0xbbbb, 0x07d0,
+ 0xbbd1, 0x1f57,
+ 0xbbd2, 0x07e7,
+ 0xbbd3, 0x1f58,
+ 0xbbd5, 0x07ea,
+ 0xbbdf, 0x1f5a,
+ 0xbbe8, 0x07fd,
+ 0xbbeb, 0x1f63,
+ 0xbbec, 0x0801,
+ 0xbbf1, 0x1f64,
+ 0xbbf2, 0x0807,
+ 0xbbf5, 0x1f65,
+ 0xbbf8, 0x080d,
+ 0xbbfa, 0x1f68,
+ 0xbbfb, 0x0810,
+ 0xbbfd, 0x1f69,
+ 0xbbfe, 0x0813,
+ 0xbca1, 0x0814,
+ 0xbca2, 0x1f6a,
+ 0xbca3, 0x0816,
+ 0xbca5, 0x1f6b,
+ 0xbca7, 0x081a,
+ 0xbca8, 0x1f6d,
+ 0xbcaa, 0x081d,
+ 0xbcab, 0x1f6f,
+ 0xbcac, 0x081f,
+ 0xbcad, 0x1f70,
+ 0xbcae, 0x0821,
+ 0xbcb6, 0x1f71,
+ 0xbcb9, 0x082c,
+ 0xbcbb, 0x1f74,
+ 0xbcbc, 0x082f,
+ 0xbcc1, 0x1f75,
+ 0xbcc2, 0x0835,
+ 0xbcc3, 0x1f76,
+ 0xbcc4, 0x0837,
+ 0xbcc6, 0x1f77,
+ 0xbcc8, 0x083b,
+ 0xbcca, 0x1f79,
+ 0xbccb, 0x083e,
+ 0xbccc, 0x1f7a,
+ 0xbcce, 0x0841,
+ 0xbcd0, 0x1f7c,
+ 0xbcd1, 0x0844,
+ 0xbcd4, 0x1f7d,
+ 0xbcd7, 0x084a,
+ 0xbcd8, 0x1f80,
+ 0xbcd9, 0x084c,
+ 0xbcdb, 0x1f81,
+ 0xbcdc, 0x084f,
+ 0xbcdd, 0x1f82,
+ 0xbcde, 0x0851,
+ 0xbcdf, 0x1f83,
+ 0xbce2, 0x0855,
+ 0xbce3, 0x1f86,
+ 0xbce5, 0x0858,
+ 0xbce8, 0x1f88,
+ 0xbce9, 0x085c,
+ 0xbcea, 0x1f89,
+ 0xbced, 0x0860,
+ 0xbcef, 0x1f8c,
+ 0xbcf4, 0x0867,
+ 0xbcf6, 0x1f91,
+ 0xbcfd, 0x0870,
+ 0xbda1, 0x0872,
+ 0xbda2, 0x1f98,
+ 0xbda8, 0x0879,
+ 0xbdab, 0x1f9e,
+ 0xbdad, 0x087e,
+ 0xbdaf, 0x1fa0,
+ 0xbdb3, 0x0884,
+ 0xbdb4, 0x1fa4,
+ 0xbdb5, 0x0886,
+ 0xbdba, 0x1fa5,
+ 0xbdbb, 0x088c,
+ 0xbdbd, 0x1fa6,
+ 0xbdc0, 0x0891,
+ 0xbdc1, 0x1fa9,
+ 0xbdc5, 0x0896,
+ 0xbdc8, 0x1fad,
+ 0xbdcb, 0x089c,
+ 0xbdce, 0x1fb0,
+ 0xbdd0, 0x08a1,
+ 0xbdd7, 0x1fb2,
+ 0xbdd8, 0x08a9,
+ 0xbdda, 0x1fb3,
+ 0xbddb, 0x08ac,
+ 0xbde0, 0x1fb4,
+ 0xbde2, 0x08b3,
+ 0xbdeb, 0x1fb6,
+ 0xbdec, 0x08bd,
+ 0xbdf4, 0x1fb7,
+ 0xbdf9, 0x08ca,
+ 0xbdfd, 0x1fbc,
+ 0xbdfe, 0x08cf,
+ 0xbea1, 0x1fbd,
+ 0xbea3, 0x08d2,
+ 0xbea5, 0x1fbf,
+ 0xbea6, 0x08d5,
+ 0xbea8, 0x1fc0,
+ 0xbea9, 0x08d8,
+ 0xbeaa, 0x1fc1,
+ 0xbeab, 0x08da,
+ 0xbead, 0x1fc2,
+ 0xbeae, 0x08dd,
+ 0xbeb1, 0x1fc3,
+ 0xbeb2, 0x08e1,
+ 0xbeb5, 0x1fc4,
+ 0xbeb8, 0x08e7,
+ 0xbeba, 0x1fc7,
+ 0xbebb, 0x08ea,
+ 0xbec0, 0x1fc8,
+ 0xbec1, 0x08f0,
+ 0xbec9, 0x1fc9,
+ 0xbeca, 0x08f9,
+ 0xbed4, 0x1fca,
+ 0xbed5, 0x0904,
+ 0xbed9, 0x1fcb,
+ 0xbeda, 0x0909,
+ 0xbedd, 0x1fcc,
+ 0xbede, 0x090d,
+ 0xbee2, 0x1fcd,
+ 0xbee3, 0x0912,
+ 0xbee5, 0x1fce,
+ 0xbee6, 0x0915,
+ 0xbee7, 0x1fcf,
+ 0xbee8, 0x0917,
+ 0xbee9, 0x1fd0,
+ 0xbeea, 0x0919,
+ 0xbeee, 0x1fd1,
+ 0xbeef, 0x091e,
+ 0xbef5, 0x1fd2,
+ 0xbef6, 0x0925,
+ 0xbef7, 0x1fd3,
+ 0xbef9, 0x0928,
+ 0xbefb, 0x1fd5,
+ 0xbefd, 0x092c,
+ 0xbfa1, 0x092e,
+ 0xbfa5, 0x1fd7,
+ 0xbfa6, 0x0933,
+ 0xbfaa, 0x1fd8,
+ 0xbfab, 0x0938,
+ 0xbfad, 0x1fd9,
+ 0xbfae, 0x093b,
+ 0xbfc5, 0x1fda,
+ 0xbfc6, 0x0953,
+ 0xbfc7, 0x1fdb,
+ 0xbfc8, 0x0955,
+ 0xbfce, 0x1fdc,
+ 0xbfcf, 0x095c,
+ 0xbfd1, 0x1fdd,
+ 0xbfd3, 0x0960,
+ 0xbfd9, 0x1fdf,
+ 0xbfda, 0x0967,
+ 0xbfe2, 0x1fe0,
+ 0xbfe5, 0x0972,
+ 0xbfe9, 0x1fe3,
+ 0xbfea, 0x0977,
+ 0xbfeb, 0x1fe4,
+ 0xbfec, 0x0979,
+ 0xbfed, 0x1fe5,
+ 0xbfee, 0x097b,
+ 0xbff3, 0x1fe6,
+ 0xbff4, 0x0981,
+ 0xbff5, 0x1fe7,
+ 0xbff6, 0x0983,
+ 0xbff7, 0x1fe8,
+ 0xbff8, 0x0985,
+ 0xbff9, 0x1fe9,
+ 0xbffb, 0x0988,
+ 0xc0a1, 0x1feb,
+ 0xc0a2, 0x098d,
+ 0xc0a3, 0x1fec,
+ 0xc0a4, 0x098f,
+ 0xc0a9, 0x1fed,
+ 0xc0aa, 0x0995,
+ 0xc0ab, 0x1fee,
+ 0xc0ac, 0x0997,
+ 0xc0af, 0x1fef,
+ 0xc0b1, 0x099c,
+ 0xc0b3, 0x1ff1,
+ 0xc0b7, 0x09a2,
+ 0xc0b8, 0x1ff5,
+ 0xc0c5, 0x09b0,
+ 0xc0cc, 0x2002,
+ 0xc0ce, 0x09b9,
+ 0xc0d4, 0x2004,
+ 0xc0d5, 0x09c0,
+ 0xc0d6, 0x2005,
+ 0xc0d7, 0x09c2,
+ 0xc0d8, 0x2006,
+ 0xc0d9, 0x09c4,
+ 0xc0dd, 0x2007,
+ 0xc0de, 0x09c9,
+ 0xc0e0, 0x2008,
+ 0xc0e1, 0x09cc,
+ 0xc0e9, 0x2009,
+ 0xc0ea, 0x09d5,
+ 0xc0eb, 0x200a,
+ 0xc0ed, 0x09d8,
+ 0xc0ef, 0x200c,
+ 0xc0f2, 0x09dd,
+ 0xc0f6, 0x200f,
+ 0xc0fb, 0x09e6,
+ 0xc1a1, 0x09ea,
+ 0xc1a4, 0x2014,
+ 0xc1a6, 0x09ef,
+ 0xc1a9, 0x2016,
+ 0xc1ae, 0x09f7,
+ 0xc1af, 0x201b,
+ 0xc1b9, 0x0a02,
+ 0xc1bd, 0x2025,
+ 0xc1bf, 0x0a08,
+ 0xc1c2, 0x2027,
+ 0xc1c3, 0x0a0c,
+ 0xc1c6, 0x2028,
+ 0xc1c7, 0x0a10,
+ 0xc1c9, 0x2029,
+ 0xc1ca, 0x0a13,
+ 0xc1cd, 0x202a,
+ 0xc1ce, 0x0a17,
+ 0xc1d4, 0x202b,
+ 0xc1d5, 0x0a1e,
+ 0xc1d9, 0x202c,
+ 0xc1dc, 0x0a25,
+ 0xc1de, 0x202f,
+ 0xc1df, 0x0a28,
+ 0xc1e4, 0x2030,
+ 0xc1e6, 0x0a2f,
+ 0xc1e9, 0x2032,
+ 0xc1ea, 0x0a33,
+ 0xc1eb, 0x2033,
+ 0xc1ed, 0x0a36,
+ 0xc1f3, 0x2035,
+ 0xc1f4, 0x0a3d,
+ 0xc1f5, 0x2036,
+ 0xc1f6, 0x0a3f,
+ 0xc1fa, 0x2037,
+ 0xc1fe, 0x0a47,
+ 0xc2a1, 0x0a48,
+ 0xc2a2, 0x203b,
+ 0xc2a9, 0x0a50,
+ 0xc2ab, 0x2042,
+ 0xc2b4, 0x0a5b,
+ 0xc2b8, 0x204b,
+ 0xc2b9, 0x0a60,
+ 0xc2bc, 0x204c,
+ 0xc2be, 0x0a65,
+ 0xc2bf, 0x204e,
+ 0xc2c0, 0x0a67,
+ 0xc2c1, 0x204f,
+ 0xc2c2, 0x0a69,
+ 0xc2c5, 0x2050,
+ 0xc2c8, 0x0a6f,
+ 0xc2cb, 0x2053,
+ 0xc2d1, 0x0a78,
+ 0xc2d2, 0x2059,
+ 0xc2d3, 0x0a7a,
+ 0xc2d5, 0x205a,
+ 0xc2dd, 0x0a84,
+ 0xc2de, 0x2062,
+ 0xc2e3, 0x0a8a,
+ 0xc2e6, 0x2067,
+ 0xc2e9, 0x0a90,
+ 0xc2ea, 0x206a,
+ 0xc2ef, 0x0a96,
+ 0xc2f0, 0x206f,
+ 0xc2f1, 0x0a98,
+ 0xc2f2, 0x2070,
+ 0xc2f6, 0x0a9d,
+ 0xc2f7, 0x2074,
+ 0xc2fb, 0x0aa2,
+ 0xc3a1, 0x2078,
+ 0xc3a2, 0x0aa7,
+ 0xc3aa, 0x2079,
+ 0xc3ab, 0x0ab0,
+ 0xc3ad, 0x207a,
+ 0xc3ae, 0x0ab3,
+ 0xc3b3, 0x207b,
+ 0xc3b4, 0x1df9,
+ 0xc3b5, 0x0aba,
+ 0xc3be, 0x207c,
+ 0xc3bf, 0x0ac4,
+ 0xc3c5, 0x207d,
+ 0xc3c8, 0x0acd,
+ 0xc3cc, 0x2080,
+ 0xc3cd, 0x0ad2,
+ 0xc3ce, 0x2081,
+ 0xc3cf, 0x0ad4,
+ 0xc3d5, 0x2082,
+ 0xc3d7, 0x0adc,
+ 0xc3d9, 0x2084,
+ 0xc3da, 0x0adf,
+ 0xc3e0, 0x2085,
+ 0xc3e1, 0x0ae6,
+ 0xc3e5, 0x2086,
+ 0xc3e6, 0x0aeb,
+ 0xc3ed, 0x2087,
+ 0xc3ee, 0x0af3,
+ 0xc3f0, 0x2088,
+ 0xc3f1, 0x0af6,
+ 0xc3f5, 0x2089,
+ 0xc3f7, 0x0afc,
+ 0xc3f9, 0x208b,
+ 0xc3fb, 0x0b00,
+ 0xc3fd, 0x208d,
+ 0xc3fe, 0x0b03,
+ 0xc4a1, 0x0b04,
+ 0xc4b1, 0x208e,
+ 0xc4b2, 0x0b15,
+ 0xc4b6, 0x208f,
+ 0xc4b7, 0x0b1a,
+ 0xc4c6, 0x2090,
+ 0xc4c7, 0x0b2a,
+ 0xc4c9, 0x2091,
+ 0xc4ca, 0x0b2d,
+ 0xc4d1, 0x2092,
+ 0xc4d2, 0x0b35,
+ 0xc4d3, 0x2093,
+ 0xc4d7, 0x0b3a,
+ 0xc4d9, 0x2097,
+ 0xc4da, 0x0b3d,
+ 0xc4e2, 0x2098,
+ 0xc4e3, 0x0b46,
+ 0xc4e5, 0x2099,
+ 0xc4e6, 0x0b49,
+ 0xc4ec, 0x209a,
+ 0xc4ed, 0x0b50,
+ 0xc4f0, 0x209b,
+ 0xc4f2, 0x0b55,
+ 0xc4f4, 0x209d,
+ 0xc4f5, 0x0b58,
+ 0xc4f6, 0x209e,
+ 0xc4f9, 0x0b5c,
+ 0xc4fb, 0x20a1,
+ 0xc4fd, 0x0b60,
+ 0xc4fe, 0x20a3,
+ 0xc5a1, 0x20a4,
+ 0xc5a3, 0x0b64,
+ 0xc5a5, 0x20a6,
+ 0xc5aa, 0x0b6b,
+ 0xc5b1, 0x20ab,
+ 0xc5b2, 0x0b73,
+ 0xc5b5, 0x20ac,
+ 0xc5b6, 0x0b77,
+ 0xc5b7, 0x20ad,
+ 0xc5ba, 0x0b7b,
+ 0xc5bb, 0x20b0,
+ 0xc5bc, 0x0b7d,
+ 0xc5bd, 0x20b1,
+ 0xc5be, 0x0b7f,
+ 0xc5cc, 0x20b2,
+ 0xc5cd, 0x0b8e,
+ 0xc5d3, 0x20b3,
+ 0xc5d4, 0x0b95,
+ 0xc5e2, 0x20b4,
+ 0xc5e3, 0x0ba4,
+ 0xc5e7, 0x20b5,
+ 0xc5e8, 0x0ba9,
+ 0xc5f4, 0x20b6,
+ 0xc5f5, 0x0bb6,
+ 0xc6a1, 0x0bc0,
+ 0xc6ad, 0x20b7,
+ 0xc6af, 0x0bce,
+ 0xc6b5, 0x20b9,
+ 0xc6b7, 0x0bd6,
+ 0xc6bb, 0x20bb,
+ 0xc6bc, 0x0bdb,
+ 0xc6be, 0x20bc,
+ 0xc6bf, 0x0bde,
+ 0xc6c0, 0x20bd,
+ 0xc6c1, 0x0be0,
+ 0xc6c3, 0x20be,
+ 0xc6c5, 0x0be4,
+ 0xc6cb, 0x20c0,
+ 0xc6ce, 0x0bed,
+ 0xc6d3, 0x20c3,
+ 0xc6d4, 0x0bf3,
+ 0xc6d7, 0x20c4,
+ 0xc6d8, 0x0bf7,
+ 0xc6ea, 0x20c5,
+ 0xc6ec, 0x0c0b,
+ 0xc6ef, 0x20c7,
+ 0xc6f0, 0x0c0f,
+ 0xc6f1, 0x20c8,
+ 0xc6f2, 0x0c11,
+ 0xc6f4, 0x20c9,
+ 0xc6f5, 0x0c14,
+ 0xc6f8, 0x20ca,
+ 0xc6f9, 0x0c18,
+ 0xc6fd, 0x20cb,
+ 0xc6fe, 0x0c1d,
+ 0xc7a1, 0x0c1e,
+ 0xc7a3, 0x20cc,
+ 0xc7a4, 0x0c21,
+ 0xc7a5, 0x20cd,
+ 0xc7a7, 0x0c24,
+ 0xc7a8, 0x20cf,
+ 0xc7aa, 0x0c27,
+ 0xc7ab, 0x20d1,
+ 0xc7ac, 0x0c29,
+ 0xc7ae, 0x20d2,
+ 0xc7b0, 0x0c2d,
+ 0xc7b3, 0x20d4,
+ 0xc7b6, 0x0c33,
+ 0xc7b9, 0x20d7,
+ 0xc7bb, 0x0c38,
+ 0xc7bd, 0x20d9,
+ 0xc7bf, 0x0c3c,
+ 0xc7c0, 0x20db,
+ 0xc7c1, 0x0c3e,
+ 0xc7c2, 0x20dc,
+ 0xc7c3, 0x0c40,
+ 0xc7c5, 0x20dd,
+ 0xc7c6, 0x0c43,
+ 0xc7c7, 0x20de,
+ 0xc7c9, 0x0c46,
+ 0xc7cc, 0x20e0,
+ 0xc7cd, 0x0c4a,
+ 0xc7cf, 0x20e1,
+ 0xc7d0, 0x0c4d,
+ 0xc7d4, 0x20e2,
+ 0xc7d6, 0x0c53,
+ 0xc7d7, 0x20e4,
+ 0xc7d8, 0x0c55,
+ 0xc7de, 0x20e5,
+ 0xc7df, 0x0c5c,
+ 0xc7e1, 0x20e6,
+ 0xc7e4, 0x0c61,
+ 0xc7ea, 0x20e9,
+ 0xc7ef, 0x0c6c,
+ 0xc7f7, 0x20ee,
+ 0xc7f9, 0x0c76,
+ 0xc7fb, 0x20f0,
+ 0xc7fc, 0x0c79,
+ 0xc7fd, 0x20f1,
+ 0xc7fe, 0x0c7b,
+ 0xc8a1, 0x0c7c,
+ 0xc8a3, 0x20f2,
+ 0xc8a4, 0x0c7f,
+ 0xc8a7, 0x20f3,
+ 0xc8a9, 0x0c84,
+ 0xc8b0, 0x20f5,
+ 0xc8b1, 0x0c8c,
+ 0xc8b5, 0x20f6,
+ 0xc8b6, 0x0c91,
+ 0xc8b7, 0x20f7,
+ 0xc8b8, 0x0c93,
+ 0xc8c3, 0x20f8,
+ 0xc8c7, 0x0ca2,
+ 0xc8c8, 0x20fc,
+ 0xc8c9, 0x0ca4,
+ 0xc8cd, 0x20fd,
+ 0xc8ce, 0x0ca9,
+ 0xc8cf, 0x20fe,
+ 0xc8d0, 0x0cab,
+ 0xc8d2, 0x20ff,
+ 0xc8d3, 0x0cae,
+ 0xc8d9, 0x2100,
+ 0xc8da, 0x0cb5,
+ 0xc8de, 0x2101,
+ 0xc8df, 0x0cba,
+ 0xc8ed, 0x2102,
+ 0xc8ee, 0x0cc9,
+ 0xc8f1, 0x2103,
+ 0xc8f4, 0x0ccf,
+ 0xc8f7, 0x2106,
+ 0xc8f9, 0x0cd4,
+ 0xc8fa, 0x2108,
+ 0xc8fb, 0x0cd6,
+ 0xc8fc, 0x2109,
+ 0xc8fd, 0x0cd8,
+ 0xc9a1, 0x210a,
+ 0xc9a2, 0x0cdb,
+ 0xc9a5, 0x210b,
+ 0xc9a6, 0x0cdf,
+ 0xc9a7, 0x210c,
+ 0xc9a9, 0x0ce2,
+ 0xc9ac, 0x210e,
+ 0xc9ad, 0x0ce6,
+ 0xc9b1, 0x210f,
+ 0xc9b2, 0x0ceb,
+ 0xc9b4, 0x2110,
+ 0xc9b5, 0x0cee,
+ 0xc9b8, 0x2111,
+ 0xc9ba, 0x0cf3,
+ 0xc9c1, 0x2113,
+ 0xc9c3, 0x0cfc,
+ 0xc9c4, 0x2115,
+ 0xc9c5, 0x0cfe,
+ 0xc9c9, 0x2116,
+ 0xc9ca, 0x0d03,
+ 0xc9cb, 0x2117,
+ 0xc9cc, 0x0d05,
+ 0xc9cd, 0x2118,
+ 0xc9ce, 0x0d07,
+ 0xc9d5, 0x2119,
+ 0xc9d6, 0x0d0f,
+ 0xc9dc, 0x211a,
+ 0xc9dd, 0x0d16,
+ 0xc9de, 0x211b,
+ 0xc9df, 0x0d18,
+ 0xc9e1, 0x211c,
+ 0xc9e2, 0x0d1b,
+ 0xc9e3, 0x211d,
+ 0xc9e4, 0x0d1d,
+ 0xc9e5, 0x211e,
+ 0xc9e6, 0x0d1f,
+ 0xc9e8, 0x211f,
+ 0xc9e9, 0x0d22,
+ 0xc9f0, 0x2120,
+ 0xc9f1, 0x0d2a,
+ 0xc9f3, 0x2121,
+ 0xc9f5, 0x0d2e,
+ 0xc9f6, 0x2123,
+ 0xc9f7, 0x0d30,
+ 0xc9f8, 0x2124,
+ 0xc9fa, 0x0d33,
+ 0xc9fe, 0x2126,
+ 0xcaa1, 0x0d38,
+ 0xcaa4, 0x2127,
+ 0xcaa7, 0x0d3e,
+ 0xcaa8, 0x212a,
+ 0xcaa9, 0x0d40,
+ 0xcaaa, 0x212b,
+ 0xcaac, 0x0d43,
+ 0xcab1, 0x212d,
+ 0xcab2, 0x0d49,
+ 0xcab4, 0x212e,
+ 0xcab7, 0x0d4e,
+ 0xcabb, 0x2131,
+ 0xcabc, 0x0d53,
+ 0xcac6, 0x2132,
+ 0xcac7, 0x0d5e,
+ 0xcaca, 0x2133,
+ 0xcacb, 0x0d62,
+ 0xcacd, 0x2134,
+ 0xcacf, 0x0d66,
+ 0xcad3, 0x2136,
+ 0xcad5, 0x0d6c,
+ 0xcad9, 0x2138,
+ 0xcada, 0x0d71,
+ 0xcade, 0x2139,
+ 0xcadf, 0x0d76,
+ 0xcae0, 0x213a,
+ 0xcae1, 0x0d78,
+ 0xcae4, 0x213b,
+ 0xcae5, 0x0d7c,
+ 0xcae9, 0x213c,
+ 0xcaeb, 0x0d82,
+ 0xcaf4, 0x213e,
+ 0xcaf6, 0x0d8d,
+ 0xcaf7, 0x2140,
+ 0xcaf8, 0x0d8f,
+ 0xcafa, 0x2141,
+ 0xcafb, 0x0d92,
+ 0xcafd, 0x2142,
+ 0xcafe, 0x0d95,
+ 0xcba1, 0x0d96,
+ 0xcba7, 0x2143,
+ 0xcba8, 0x0d9d,
+ 0xcbab, 0x2144,
+ 0xcbac, 0x0da1,
+ 0xcbad, 0x2145,
+ 0xcbae, 0x0da3,
+ 0xcbb3, 0x2146,
+ 0xcbb4, 0x0da9,
+ 0xcbb5, 0x2147,
+ 0xcbb7, 0x0dac,
+ 0xcbb8, 0x2149,
+ 0xcbb9, 0x0dae,
+ 0xcbbf, 0x214a,
+ 0xcbc0, 0x0db5,
+ 0xcbc7, 0x214b,
+ 0xcbc8, 0x0dbd,
+ 0xcbc9, 0x214c,
+ 0xcbcd, 0x0dc2,
+ 0xcbcf, 0x2150,
+ 0xcbd1, 0x0dc6,
+ 0xcbd3, 0x2152,
+ 0xcbd4, 0x0dc9,
+ 0xcbd5, 0x2153,
+ 0xcbd6, 0x0dcb,
+ 0xcbdf, 0x2154,
+ 0xcbe1, 0x0dd6,
+ 0xcbe4, 0x2156,
+ 0xcbe5, 0x0dda,
+ 0xcbe6, 0x2157,
+ 0xcbe8, 0x0ddd,
+ 0xcbea, 0x2159,
+ 0xcbeb, 0x0de0,
+ 0xcbef, 0x215a,
+ 0xcbf1, 0x0de6,
+ 0xcbf5, 0x215c,
+ 0xcbf7, 0x0dec,
+ 0xcbf8, 0x215e,
+ 0xcbf9, 0x0dee,
+ 0xcca1, 0x215f,
+ 0xcca3, 0x0df6,
+ 0xcca8, 0x2161,
+ 0xcca9, 0x0dfc,
+ 0xccac, 0x2162,
+ 0xccad, 0x0e00,
+ 0xccaf, 0x2163,
+ 0xccb4, 0x0e07,
+ 0xccb7, 0x2168,
+ 0xccb9, 0x0e0c,
+ 0xccbe, 0x216a,
+ 0xccbf, 0x0e12,
+ 0xccc0, 0x216b,
+ 0xccc1, 0x0e14,
+ 0xcccc, 0x216c,
+ 0xcccd, 0x0e20,
+ 0xccce, 0x216d,
+ 0xcccf, 0x0e22,
+ 0xccd0, 0x216e,
+ 0xccd1, 0x0e24,
+ 0xccd6, 0x216f,
+ 0xccd7, 0x0e2a,
+ 0xccda, 0x2170,
+ 0xccdb, 0x0e2e,
+ 0xccdc, 0x2171,
+ 0xccdd, 0x0e30,
+ 0xcce0, 0x2172,
+ 0xcce1, 0x0e34,
+ 0xcce2, 0x2173,
+ 0xcce3, 0x0e36,
+ 0xcce5, 0x2174,
+ 0xcce6, 0x0e39,
+ 0xccf5, 0x2175,
+ 0xccf6, 0x0e49,
+ 0xccf9, 0x2176,
+ 0xccfb, 0x0e4e,
+ 0xccfc, 0x2178,
+ 0xcda1, 0x0e52,
+ 0xcdad, 0x217b,
+ 0xcdae, 0x0e5f,
+ 0xcdb3, 0x217c,
+ 0xcdb4, 0x0e65,
+ 0xcdb7, 0x217d,
+ 0xcdb8, 0x0e69,
+ 0xcdbc, 0x217e,
+ 0xcdbd, 0x0e6e,
+ 0xcdbf, 0x217f,
+ 0xcdc0, 0x0e71,
+ 0xcdc5, 0x2180,
+ 0xcdc6, 0x0e77,
+ 0xcdc7, 0x2181,
+ 0xcdc8, 0x0e79,
+ 0xcdd2, 0x2182,
+ 0xcdd3, 0x0e84,
+ 0xcdd4, 0x2183,
+ 0xcdd7, 0x0e88,
+ 0xcddd, 0x2186,
+ 0xcdde, 0x0e8f,
+ 0xcde0, 0x2187,
+ 0xcde1, 0x0e92,
+ 0xcde4, 0x2188,
+ 0xcde6, 0x0e97,
+ 0xcde7, 0x218a,
+ 0xcde8, 0x0e99,
+ 0xcdf2, 0x218b,
+ 0xcdf3, 0x0ea4,
+ 0xcdf8, 0x218c,
+ 0xcdf9, 0x0eaa,
+ 0xcea1, 0x0eb0,
+ 0xcea4, 0x218d,
+ 0xcea6, 0x0eb5,
+ 0xcea7, 0x218f,
+ 0xcea8, 0x0eb7,
+ 0xceaa, 0x2190,
+ 0xceae, 0x0ebd,
+ 0xceb0, 0x2194,
+ 0xceb2, 0x0ec1,
+ 0xceb3, 0x2196,
+ 0xceb4, 0x0ec3,
+ 0xcebd, 0x2197,
+ 0xcebe, 0x0ecd,
+ 0xcec0, 0x2198,
+ 0xcec1, 0x0ed0,
+ 0xcec5, 0x2199,
+ 0xcec7, 0x0ed6,
+ 0xcec8, 0x219b,
+ 0xcec9, 0x0ed8,
+ 0xceca, 0x219c,
+ 0xcecb, 0x0eda,
+ 0xcece, 0x219d,
+ 0xced2, 0x0ee1,
+ 0xced8, 0x21a1,
+ 0xcedb, 0x0eea,
+ 0xcedc, 0x21a4,
+ 0xcedd, 0x0eec,
+ 0xcede, 0x21a5,
+ 0xcee0, 0x0eef,
+ 0xceeb, 0x21a7,
+ 0xceec, 0x0efb,
+ 0xceed, 0x21a8,
+ 0xceee, 0x0efd,
+ 0xcef1, 0x21a9,
+ 0xcef2, 0x0f01,
+ 0xcef3, 0x21aa,
+ 0xcef4, 0x0f03,
+ 0xcefd, 0x21ab,
+ 0xcfa1, 0x0f0e,
+ 0xcfae, 0x21ad,
+ 0xcfaf, 0x0f1c,
+ 0xcfb0, 0x21ae,
+ 0xcfb1, 0x0f1e,
+ 0xcfb3, 0x21af,
+ 0xcfb4, 0x0f21,
+ 0xcfb7, 0x21b0,
+ 0xcfb9, 0x0f26,
+ 0xcfba, 0x21b2,
+ 0xcfbb, 0x0f28,
+ 0xcfbd, 0x21b3,
+ 0xcfbe, 0x0f2b,
+ 0xcfbf, 0x21b4,
+ 0xcfc2, 0x0f2f,
+ 0xcfc5, 0x21b7,
+ 0xcfc6, 0x0f33,
+ 0xcfc7, 0x21b8,
+ 0xcfc8, 0x0f35,
+ 0xcfca, 0x21b9,
+ 0xcfcc, 0x0f39,
+ 0xcfcd, 0x21bb,
+ 0xcfcf, 0x0f3c,
+ 0xcfd0, 0x21bd,
+ 0xcfd1, 0x0f3e,
+ 0xcfd4, 0x21be,
+ 0xcfd9, 0x0f46,
+ 0xcfda, 0x21c3,
+ 0xcfdb, 0x0f48,
+ 0xcfdc, 0x21c4,
+ 0xcfdd, 0x0f4a,
+ 0xcfdf, 0x21c5,
+ 0xcfe0, 0x0f4d,
+ 0xcfe2, 0x21c6,
+ 0xcfe3, 0x0f50,
+ 0xcfe7, 0x21c7,
+ 0xcfe8, 0x0f55,
+ 0xcfea, 0x21c8,
+ 0xcfeb, 0x0f58,
+ 0xcfec, 0x21c9,
+ 0xcfed, 0x0f5a,
+ 0xcfee, 0x21ca,
+ 0xcfef, 0x0f5c,
+ 0xcff4, 0x21cb,
+ 0xcff5, 0x0f62,
+ 0xcff9, 0x21cc,
+ 0xcffb, 0x0f68,
+ 0xcffe, 0x21ce,
+ 0xd0a1, 0x0f6c,
+ 0xd0a5, 0x21cf,
+ 0xd0a6, 0x0f71,
+ 0xd0ad, 0x21d0,
+ 0xd0af, 0x0f7a,
+ 0xd0b2, 0x21d2,
+ 0xd0b5, 0x0f80,
+ 0xd0ba, 0x21d5,
+ 0xd0bc, 0x0f87,
+ 0xd0bf, 0x21d7,
+ 0xd0c0, 0x0f8b,
+ 0xd0c6, 0x21d8,
+ 0xd0c7, 0x0f92,
+ 0xd0cb, 0x21d9,
+ 0xd0cc, 0x0f97,
+ 0xd0e2, 0x21da,
+ 0xd0e3, 0x0fae,
+ 0xd0e5, 0x21db,
+ 0xd0e6, 0x0fb1,
+ 0xd0eb, 0x21dc,
+ 0xd0ec, 0x0fb7,
+ 0xd0ed, 0x21dd,
+ 0xd0ee, 0x0fb9,
+ 0xd0f7, 0x21de,
+ 0xd0fa, 0x0fc5,
+ 0xd0fc, 0x21e1,
+ 0xd0fd, 0x0fc8,
+ 0xd1a1, 0x21e2,
+ 0xd1a3, 0x0fcc,
+ 0xd1a4, 0x21e4,
+ 0xd1a5, 0x0fce,
+ 0xd1a7, 0x21e5,
+ 0xd1a8, 0x0fd1,
+ 0xd1ab, 0x21e6,
+ 0xd1ac, 0x0fd5,
+ 0xd1af, 0x21e7,
+ 0xd1b2, 0x0fdb,
+ 0xd1b5, 0x21ea,
+ 0xd1b8, 0x0fe1,
+ 0xd1b9, 0x21ed,
+ 0xd1ba, 0x0fe3,
+ 0xd1bb, 0x21ee,
+ 0xd1bd, 0x0fe6,
+ 0xd1c6, 0x21f0,
+ 0xd1c9, 0x0ff2,
+ 0xd1cb, 0x21f3,
+ 0xd1cc, 0x0ff5,
+ 0xd1ce, 0x21f4,
+ 0xd1d0, 0x0ff9,
+ 0xd1d5, 0x21f6,
+ 0xd1d7, 0x1000,
+ 0xd1de, 0x21f8,
+ 0xd1df, 0x1008,
+ 0xd1e1, 0x21f9,
+ 0xd1e3, 0x100c,
+ 0xd1e8, 0x21fb,
+ 0xd1ea, 0x1013,
+ 0xd1ec, 0x21fd,
+ 0xd1ed, 0x1016,
+ 0xd1ee, 0x21fe,
+ 0xd1f0, 0x1019,
+ 0xd1f1, 0x2200,
+ 0xd1f2, 0x101b,
+ 0xd1f4, 0x2201,
+ 0xd1f5, 0x101e,
+ 0xd1f7, 0x2202,
+ 0xd1fa, 0x1023,
+ 0xd2a1, 0x1028,
+ 0xd2a2, 0x2205,
+ 0xd2a3, 0x102a,
+ 0xd2a5, 0x2206,
+ 0xd2a6, 0x102d,
+ 0xd2a9, 0x2207,
+ 0xd2aa, 0x1031,
+ 0xd2af, 0x2208,
+ 0xd2b0, 0x1037,
+ 0xd2b3, 0x2209,
+ 0xd2b4, 0x103b,
+ 0xd2b5, 0x220a,
+ 0xd2b7, 0x103e,
+ 0xd2bd, 0x220c,
+ 0xd2be, 0x1045,
+ 0xd2bf, 0x220d,
+ 0xd2c0, 0x1047,
+ 0xd2c3, 0x220e,
+ 0xd2c4, 0x104b,
+ 0xd2c5, 0x220f,
+ 0xd2c6, 0x104d,
+ 0xd2c7, 0x2210,
+ 0xd2c8, 0x104f,
+ 0xd2cf, 0x2211,
+ 0xd2d0, 0x1057,
+ 0xd2d5, 0x2212,
+ 0xd2d6, 0x105d,
+ 0xd2da, 0x2213,
+ 0xd2db, 0x1062,
+ 0xd2e4, 0x2214,
+ 0xd2e6, 0x106d,
+ 0xd2e8, 0x2216,
+ 0xd2ec, 0x1073,
+ 0xd2ef, 0x221a,
+ 0xd2f0, 0x1077,
+ 0xd2f1, 0x221b,
+ 0xd2f2, 0x1079,
+ 0xd2f5, 0x221c,
+ 0xd2f6, 0x107d,
+ 0xd2f8, 0x221d,
+ 0xd2f9, 0x1080,
+ 0xd2fb, 0x221e,
+ 0xd2fc, 0x1083,
+ 0xd2fe, 0x221f,
+ 0xd3a1, 0x1086,
+ 0xd3a3, 0x2220,
+ 0xd3ad, 0x1092,
+ 0xd3ae, 0x222a,
+ 0xd3af, 0x1094,
+ 0xd3b1, 0x222b,
+ 0xd3b2, 0x1097,
+ 0xd3b4, 0x222c,
+ 0xd3b7, 0x109c,
+ 0xd3b8, 0x222f,
+ 0xd3b9, 0x109e,
+ 0xd3bb, 0x2230,
+ 0xd3bc, 0x10a1,
+ 0xd3c5, 0x2231,
+ 0xd3c6, 0x10ab,
+ 0xd3c7, 0x2232,
+ 0xd3c8, 0x10ad,
+ 0xd3ca, 0x2233,
+ 0xd3cd, 0x10b2,
+ 0xd3d5, 0x2236,
+ 0xd3d6, 0x10bb,
+ 0xd3df, 0x2237,
+ 0xd3e1, 0x10c6,
+ 0xd3e3, 0x2239,
+ 0xd3e4, 0x10c9,
+ 0xd3e6, 0x223a,
+ 0xd3e7, 0x10cc,
+ 0xd3eb, 0x223b,
+ 0xd3ed, 0x10d2,
+ 0xd3ef, 0x223d,
+ 0xd3f0, 0x10d5,
+ 0xd3f4, 0x223e,
+ 0xd3f5, 0x10da,
+ 0xd3fc, 0x223f,
+ 0xd3fd, 0x10e2,
+ 0xd3fe, 0x2240,
+ 0xd4a1, 0x10e4,
+ 0xd4a4, 0x2241,
+ 0xd4a5, 0x10e8,
+ 0xd4a6, 0x2242,
+ 0xd4a9, 0x10ec,
+ 0xd4af, 0x2245,
+ 0xd4b3, 0x10f6,
+ 0xd4b5, 0x2249,
+ 0xd4b7, 0x10fa,
+ 0xd4b8, 0x224b,
+ 0xd4b9, 0x10fc,
+ 0xd4bc, 0x224c,
+ 0xd4bd, 0x1100,
+ 0xd4be, 0x224d,
+ 0xd4c0, 0x1103,
+ 0xd4c4, 0x224f,
+ 0xd4c5, 0x1108,
+ 0xd4c6, 0x2250,
+ 0xd4c8, 0x110b,
+ 0xd4c9, 0x2252,
+ 0xd4ca, 0x110d,
+ 0xd4cb, 0x2253,
+ 0xd4cf, 0x1112,
+ 0xd4d3, 0x2257,
+ 0xd4d4, 0x1117,
+ 0xd4d8, 0x2258,
+ 0xd4d9, 0x111c,
+ 0xd4dc, 0x2259,
+ 0xd4e1, 0x1124,
+ 0xd4e4, 0x225e,
+ 0xd4e5, 0x1128,
+ 0xd4e6, 0x225f,
+ 0xd4e7, 0x112a,
+ 0xd4ee, 0x2260,
+ 0xd4ef, 0x1132,
+ 0xd4f0, 0x2261,
+ 0xd4f5, 0x1138,
+ 0xd4f9, 0x2266,
+ 0xd4fa, 0x113d,
+ 0xd4fe, 0x2267,
+ 0xd5a1, 0x2268,
+ 0xd5a3, 0x1144,
+ 0xd5a9, 0x226a,
+ 0xd5aa, 0x114b,
+ 0xd5ab, 0x226b,
+ 0xd5ac, 0x114d,
+ 0xd5ae, 0x226c,
+ 0xd5af, 0x1150,
+ 0xd5b1, 0x226d,
+ 0xd5b2, 0x1153,
+ 0xd5b5, 0x226e,
+ 0xd5b9, 0x115a,
+ 0xd5bb, 0x2272,
+ 0xd5bc, 0x115d,
+ 0xd5bd, 0x2273,
+ 0xd5be, 0x115f,
+ 0xd5c0, 0x2274,
+ 0xd5c1, 0x1162,
+ 0xd5c5, 0x2275,
+ 0xd5c6, 0x1167,
+ 0xd5c7, 0x2276,
+ 0xd5c8, 0x1169,
+ 0xd5ca, 0x2277,
+ 0xd5cc, 0x116d,
+ 0xd5cd, 0x2279,
+ 0xd5ce, 0x116f,
+ 0xd5d4, 0x227a,
+ 0xd5d5, 0x1176,
+ 0xd5dd, 0x227b,
+ 0xd5df, 0x1180,
+ 0xd5e0, 0x227d,
+ 0xd5e1, 0x1182,
+ 0xd5e2, 0x227e,
+ 0xd5e3, 0x1184,
+ 0xd5ea, 0x227f,
+ 0xd5ed, 0x118e,
+ 0xd5ef, 0x2282,
+ 0xd5f0, 0x1191,
+ 0xd5f2, 0x2283,
+ 0xd5f4, 0x1195,
+ 0xd5f7, 0x15eb,
+ 0xd5f8, 0x1199,
+ 0xd6a1, 0x2285,
+ 0xd6a5, 0x11a4,
+ 0xd6af, 0x2289,
+ 0xd6b1, 0x11b0,
+ 0xd6b4, 0x228b,
+ 0xd6b5, 0x11b4,
+ 0xd6bb, 0x228c,
+ 0xd6bc, 0x11bb,
+ 0xd6bd, 0x228d,
+ 0xd6be, 0x11bd,
+ 0xd6bf, 0x228e,
+ 0xd6c1, 0x11c0,
+ 0xd6c4, 0x2290,
+ 0xd6c5, 0x11c4,
+ 0xd6ca, 0x2291,
+ 0xd6cb, 0x11ca,
+ 0xd6cd, 0x2292,
+ 0xd6ce, 0x11cd,
+ 0xd6d3, 0x2293,
+ 0xd6d4, 0x11d3,
+ 0xd6d5, 0x2294,
+ 0xd6d8, 0x11d7,
+ 0xd6da, 0x2297,
+ 0xd6db, 0x11da,
+ 0xd6df, 0x2298,
+ 0xd6e0, 0x11df,
+ 0xd6e1, 0x2299,
+ 0xd6e2, 0x11e1,
+ 0xd6e5, 0x229a,
+ 0xd6e6, 0x11e5,
+ 0xd6e7, 0x229b,
+ 0xd6e9, 0x11e8,
+ 0xd6ee, 0x229d,
+ 0xd6f0, 0x11ef,
+ 0xd6f2, 0x229f,
+ 0xd6f3, 0x11f2,
+ 0xd6f5, 0x22a0,
+ 0xd6f7, 0x11f6,
+ 0xd6fc, 0x22a2,
+ 0xd7a1, 0x11fe,
+ 0xd7a4, 0x22a5,
+ 0xd7a5, 0x1202,
+ 0xd7a8, 0x22a6,
+ 0xd7ab, 0x1208,
+ 0xd7ac, 0x22a9,
+ 0xd7ad, 0x120a,
+ 0xd7ae, 0x22aa,
+ 0xd7b2, 0x120f,
+ 0xd7b3, 0x22ae,
+ 0xd7b5, 0x1212,
+ 0xd7b6, 0x22b0,
+ 0xd7b7, 0x1214,
+ 0xd7b8, 0x22b1,
+ 0xd7bd, 0x121a,
+ 0xd7c7, 0x22b6,
+ 0xd7c8, 0x1225,
+ 0xd7ca, 0x22b7,
+ 0xd7cb, 0x1228,
+ 0xd7d5, 0x22b8,
+ 0xd7d6, 0x1233,
+ 0xd7db, 0x22b9,
+ 0xd7df, 0x123c,
+ 0xd7e7, 0x22bd,
+ 0xd7e8, 0x1245,
+ 0xd7e9, 0x22be,
+ 0xd7eb, 0x1248,
+ 0xd8a1, 0x1257,
+ 0xd8c4, 0x22c0,
+ 0xd8c5, 0x127b,
+ 0xd8c7, 0x22c1,
+ 0xd8c8, 0x127e,
+ 0xd8c9, 0x22c2,
+ 0xd8ca, 0x1280,
+ 0xd8cc, 0x22c3,
+ 0xd8ce, 0x1284,
+ 0xd8d0, 0x22c5,
+ 0xd8d2, 0x1288,
+ 0xd8d3, 0x22c7,
+ 0xd8d4, 0x128a,
+ 0xd8d9, 0x22c8,
+ 0xd8da, 0x1290,
+ 0xd8db, 0x22c9,
+ 0xd8dd, 0x1293,
+ 0xd8f1, 0x22cb,
+ 0xd8f2, 0x12a8,
+ 0xd8f6, 0x22cc,
+ 0xd8f8, 0x12ae,
+ 0xd9a1, 0x12b5,
+ 0xd9ad, 0x22ce,
+ 0xd9ae, 0x12c2,
+ 0xd9af, 0x22cf,
+ 0xd9b0, 0x12c4,
+ 0xd9b1, 0x22d0,
+ 0xd9b4, 0x12c8,
+ 0xd9c7, 0x22d3,
+ 0xd9c8, 0x12dc,
+ 0xd9cd, 0x22d4,
+ 0xd9d1, 0x12e5,
+ 0xd9dd, 0x22d8,
+ 0xd9de, 0x12f2,
+ 0xd9e1, 0x22d9,
+ 0xd9e2, 0x12f6,
+ 0xd9e4, 0x22da,
+ 0xd9e5, 0x12f9,
+ 0xd9e6, 0x22db,
+ 0xd9e7, 0x12fb,
+ 0xd9ec, 0x22dc,
+ 0xd9ed, 0x1301,
+ 0xd9f4, 0x22dd,
+ 0xd9f6, 0x130a,
+ 0xdaa1, 0x1313,
+ 0xdaa5, 0x22df,
+ 0xdae0, 0x1352,
+ 0xdaea, 0x231a,
+ 0xdaeb, 0x135d,
+ 0xdaf7, 0x231b,
+ 0xdaf8, 0x136a,
+ 0xdaf9, 0x231c,
+ 0xdafa, 0x136c,
+ 0xdafe, 0x231d,
+ 0xdba1, 0x1371,
+ 0xdba3, 0x231e,
+ 0xdba4, 0x1374,
+ 0xdba6, 0x231f,
+ 0xdba7, 0x1377,
+ 0xdba9, 0x2320,
+ 0xdbab, 0x137b,
+ 0xdbbb, 0x2322,
+ 0xdbbc, 0x138c,
+ 0xdbbd, 0x2323,
+ 0xdbbe, 0x138e,
+ 0xdbcf, 0x2324,
+ 0xdbd0, 0x13a0,
+ 0xdbd1, 0x2325,
+ 0xdbd2, 0x13a2,
+ 0xdbdb, 0x2326,
+ 0xdbdc, 0x13ac,
+ 0xdbde, 0x2327,
+ 0xdbdf, 0x13af,
+ 0xdbe2, 0x2328,
+ 0xdbe3, 0x13b3,
+ 0xdbe4, 0x2329,
+ 0xdbe5, 0x13b5,
+ 0xdbeb, 0x232a,
+ 0xdbec, 0x13bc,
+ 0xdbee, 0x232b,
+ 0xdbef, 0x13bf,
+ 0xdbf1, 0x232c,
+ 0xdbf2, 0x13c2,
+ 0xdbf5, 0x232d,
+ 0xdbf8, 0x13c8,
+ 0xdca1, 0x13cf,
+ 0xdcbc, 0x2330,
+ 0xdcbd, 0x13eb,
+ 0xdcbf, 0x2331,
+ 0xdcc0, 0x13ee,
+ 0xdcc2, 0x2332,
+ 0xdcc3, 0x13f1,
+ 0xdcc8, 0x2333,
+ 0xdccb, 0x13f9,
+ 0xdcd1, 0x2336,
+ 0xdcd2, 0x1400,
+ 0xdcd7, 0x2337,
+ 0xdcd8, 0x1406,
+ 0xdce0, 0x2338,
+ 0xdce1, 0x140f,
+ 0xdce3, 0x2339,
+ 0xdce5, 0x1413,
+ 0xdce9, 0x233b,
+ 0xdceb, 0x1419,
+ 0xdcf1, 0x233d,
+ 0xdcf2, 0x1420,
+ 0xdcf6, 0x233e,
+ 0xdcf7, 0x1425,
+ 0xdcf9, 0x233f,
+ 0xdcfa, 0x1428,
+ 0xdcfd, 0x2340,
+ 0xdda1, 0x2342,
+ 0xdda2, 0x142e,
+ 0xdda3, 0x2343,
+ 0xdda8, 0x1434,
+ 0xddaa, 0x2348,
+ 0xddac, 0x1438,
+ 0xddb2, 0x234a,
+ 0xddb3, 0x143f,
+ 0xddb5, 0x234b,
+ 0xddb6, 0x1442,
+ 0xddba, 0x234c,
+ 0xddbc, 0x1448,
+ 0xddd3, 0x234e,
+ 0xddd4, 0x1460,
+ 0xdddb, 0x234f,
+ 0xdddc, 0x1468,
+ 0xddde, 0x2350,
+ 0xdddf, 0x146b,
+ 0xdde4, 0x2351,
+ 0xdde5, 0x1471,
+ 0xddeb, 0x2352,
+ 0xddec, 0x1478,
+ 0xddf1, 0x2353,
+ 0xddf2, 0x147e,
+ 0xddf6, 0x2354,
+ 0xddf8, 0x1484,
+ 0xddfc, 0x2356,
+ 0xddfd, 0x1489,
+ 0xddfe, 0x2357,
+ 0xdea1, 0x148b,
+ 0xdead, 0x2358,
+ 0xdeae, 0x1498,
+ 0xdeb4, 0x2359,
+ 0xdeb5, 0x149f,
+ 0xdeba, 0x235a,
+ 0xdebb, 0x14a5,
+ 0xdec6, 0x235b,
+ 0xdec7, 0x14b1,
+ 0xdecf, 0x235c,
+ 0xded0, 0x14ba,
+ 0xded1, 0x235d,
+ 0xded3, 0x14bd,
+ 0xded8, 0x235f,
+ 0xded9, 0x14c3,
+ 0xdee2, 0x2360,
+ 0xdee3, 0x14cd,
+ 0xdee8, 0x2361,
+ 0xdee9, 0x14d3,
+ 0xdeec, 0x2362,
+ 0xdeed, 0x14d7,
+ 0xdef3, 0x2363,
+ 0xdef4, 0x14de,
+ 0xdefc, 0x2364,
+ 0xdefd, 0x14e7,
+ 0xdfa1, 0x14e9,
+ 0xdfa2, 0x2365,
+ 0xdfa4, 0x14ec,
+ 0xdfa5, 0x2367,
+ 0xdfa6, 0x14ee,
+ 0xdfb4, 0x2368,
+ 0xdfb5, 0x14fd,
+ 0xdfbc, 0x2369,
+ 0xdfbe, 0x1506,
+ 0xdfbf, 0x236b,
+ 0xdfc0, 0x1508,
+ 0xdfc2, 0x236c,
+ 0xdfc4, 0x150c,
+ 0xdfcc, 0x236e,
+ 0xdfcd, 0x1515,
+ 0xdfd0, 0x236f,
+ 0xdfd1, 0x1519,
+ 0xdfd5, 0x2370,
+ 0xdfd6, 0x151e,
+ 0xdfd8, 0x2371,
+ 0xdfda, 0x1522,
+ 0xdfdc, 0x2373,
+ 0xdfdd, 0x1525,
+ 0xdfe0, 0x2374,
+ 0xdfe1, 0x1529,
+ 0xdfe2, 0x2375,
+ 0xdfe3, 0x152b,
+ 0xdfe6, 0x2376,
+ 0xdfe7, 0x152f,
+ 0xdfe9, 0x2377,
+ 0xdfea, 0x1532,
+ 0xdfeb, 0x2378,
+ 0xdfec, 0x1534,
+ 0xdfef, 0x2379,
+ 0xdff0, 0x1538,
+ 0xdff5, 0x237a,
+ 0xdff6, 0x153e,
+ 0xdff9, 0x237b,
+ 0xdffa, 0x1542,
+ 0xe0a1, 0x1547,
+ 0xe0b6, 0x237c,
+ 0xe0b8, 0x155e,
+ 0xe0bf, 0x237e,
+ 0xe0c0, 0x1566,
+ 0xe0c8, 0x237f,
+ 0xe0c9, 0x156f,
+ 0xe0ce, 0x2380,
+ 0xe0cf, 0x1575,
+ 0xe0d3, 0x2381,
+ 0xe0d4, 0x157a,
+ 0xe0e0, 0x2382,
+ 0xe0e1, 0x1587,
+ 0xe0f0, 0x2383,
+ 0xe0f1, 0x1597,
+ 0xe0f8, 0x2384,
+ 0xe0f9, 0x159f,
+ 0xe0fc, 0x2385,
+ 0xe1a1, 0x15a5,
+ 0xe1ab, 0x2388,
+ 0xe1ac, 0x15b0,
+ 0xe1ad, 0x2389,
+ 0xe1ae, 0x15b2,
+ 0xe1b0, 0x238a,
+ 0xe1b1, 0x15b5,
+ 0xe1b4, 0x238b,
+ 0xe1b5, 0x15b9,
+ 0xe1bb, 0x238c,
+ 0xe1bc, 0x15c0,
+ 0xe1bd, 0x238d,
+ 0xe1be, 0x15c2,
+ 0xe1c0, 0x238e,
+ 0xe1c2, 0x15c6,
+ 0xe1c9, 0x2390,
+ 0xe1ca, 0x15ce,
+ 0xe1d0, 0x2391,
+ 0xe1d1, 0x15d5,
+ 0xe1db, 0x2392,
+ 0xe1dc, 0x15e0,
+ 0xe1e1, 0x07aa,
+ 0xe1e2, 0x2393,
+ 0xe1e3, 0x15e7,
+ 0xe1e7, 0x1198,
+ 0xe1e8, 0x15ec,
+ 0xe1ee, 0x2394,
+ 0xe1f0, 0x15f4,
+ 0xe1f6, 0x2396,
+ 0xe1f7, 0x15fb,
+ 0xe1f8, 0x2397,
+ 0xe1f9, 0x15fd,
+ 0xe1fd, 0x2398,
+ 0xe1fe, 0x1602,
+ 0xe2a1, 0x1603,
+ 0xe2a4, 0x2399,
+ 0xe2a5, 0x1607,
+ 0xe2a8, 0x239a,
+ 0xe2a9, 0x160b,
+ 0xe2bb, 0x239b,
+ 0xe2c5, 0x10c5,
+ 0xe2c6, 0x23a5,
+ 0xe2cf, 0x1631,
+ 0xe2d0, 0x23ae,
+ 0xe2d1, 0x1633,
+ 0xe2d9, 0x23af,
+ 0xe2da, 0x163c,
+ 0xe2e3, 0x23b0,
+ 0xe2e5, 0x1647,
+ 0xe2e6, 0x23b2,
+ 0xe2e7, 0x1649,
+ 0xe2e9, 0x23b3,
+ 0xe2ec, 0x164e,
+ 0xe2f8, 0x23b6,
+ 0xe2f9, 0x165b,
+ 0xe2fa, 0x23b7,
+ 0xe2fe, 0x1660,
+ 0xe3a1, 0x1661,
+ 0xe3a2, 0x23bb,
+ 0xe3a3, 0x1663,
+ 0xe3a5, 0x23bc,
+ 0xe3a6, 0x1666,
+ 0xe3ab, 0x23bd,
+ 0xe3ac, 0x166c,
+ 0xe3b4, 0x23be,
+ 0xe3b5, 0x1675,
+ 0xe3c5, 0x23bf,
+ 0xe3dc, 0x169c,
+ 0xe3e3, 0x23d6,
+ 0xe3e4, 0x16a4,
+ 0xe3ed, 0x23d7,
+ 0xe3ee, 0x16ae,
+ 0xe3f1, 0x23d8,
+ 0xe3f3, 0x16b3,
+ 0xe3f8, 0x23da,
+ 0xe3f9, 0x16b9,
+ 0xe3fe, 0x23db,
+ 0xe4a1, 0x16bf,
+ 0xe4a4, 0x23dc,
+ 0xe4a6, 0x16c4,
+ 0xe4ab, 0x23de,
+ 0xe4ac, 0x16ca,
+ 0xe4af, 0x23df,
+ 0xe4b2, 0x16d0,
+ 0xe4b5, 0x23e2,
+ 0xe4b7, 0x16d5,
+ 0xe4c2, 0x23e4,
+ 0xe4c3, 0x16e1,
+ 0xe4c5, 0x23e5,
+ 0xe4c6, 0x16e4,
+ 0xe4c9, 0x23e6,
+ 0xe4ca, 0x16e8,
+ 0xe4d9, 0x23e7,
+ 0xe4da, 0x16f8,
+ 0xe4dc, 0x23e8,
+ 0xe4dd, 0x16fb,
+ 0xe4de, 0x23e9,
+ 0xe4df, 0x16fd,
+ 0xe4e4, 0x23ea,
+ 0xe4e5, 0x1703,
+ 0xe4eb, 0x23eb,
+ 0xe4ed, 0x170b,
+ 0xe4f2, 0x23ed,
+ 0xe4f3, 0x1711,
+ 0xe4fe, 0x23ee,
+ 0xe5a1, 0x171d,
+ 0xe5b0, 0x23ef,
+ 0xe5b1, 0x172d,
+ 0xe5b9, 0x23f0,
+ 0xe5ba, 0x1736,
+ 0xe5c7, 0x23f1,
+ 0xe5c8, 0x1744,
+ 0xe5c9, 0x23f2,
+ 0xe5ca, 0x1746,
+ 0xe5ce, 0x23f3,
+ 0xe5cf, 0x174b,
+ 0xe5f0, 0x23f4,
+ 0xe5f1, 0x176d,
+ 0xe5f2, 0x23f5,
+ 0xe5f3, 0x176f,
+ 0xe5fc, 0x23f6,
+ 0xe5fe, 0x177a,
+ 0xe6a1, 0x177b,
+ 0xe6a3, 0x23f8,
+ 0xe6a4, 0x177e,
+ 0xe6ab, 0x23f9,
+ 0xe6ad, 0x1787,
+ 0xe6ae, 0x23fb,
+ 0xe6af, 0x1789,
+ 0xe6b4, 0x23fc,
+ 0xe6b6, 0x1790,
+ 0xe6bf, 0x23fe,
+ 0xe6c0, 0x179a,
+ 0xe6c8, 0x23ff,
+ 0xe6ca, 0x17a4,
+ 0xe6cd, 0x2401,
+ 0xe6ce, 0x17a8,
+ 0xe6e0, 0x2402,
+ 0xe7a1, 0x2421,
+ 0xe7db, 0x1813,
+ 0xe7e1, 0x245b,
+ 0xe7e3, 0x181b,
+ 0xe7e7, 0x245d,
+ 0xe7e8, 0x1820,
+ 0xe7ef, 0x245e,
+ 0xe7f0, 0x1828,
+ 0xe7f4, 0x245f,
+ 0xe7f7, 0x182f,
+ 0xe8a1, 0x1837,
+ 0xe8a8, 0x2462,
+ 0xe8a9, 0x183f,
+ 0xe8ac, 0x2463,
+ 0xe8ad, 0x1843,
+ 0xe8b6, 0x2464,
+ 0xe8b7, 0x184d,
+ 0xe8b8, 0x2465,
+ 0xe8bb, 0x1851,
+ 0xe8bf, 0x2468,
+ 0xe8c1, 0x1857,
+ 0xe8c5, 0x246a,
+ 0xe8c6, 0x185c,
+ 0xe8c7, 0x246b,
+ 0xe8ca, 0x1860,
+ 0xe8ce, 0x246e,
+ 0xe8cf, 0x1865,
+ 0xe8d0, 0x246f,
+ 0xe8d1, 0x1867,
+ 0xe8d3, 0x2470,
+ 0xe8d4, 0x186a,
+ 0xe8dd, 0x2471,
+ 0xe8de, 0x1874,
+ 0xe8df, 0x2472,
+ 0xe8e0, 0x1876,
+ 0xe8e2, 0x2473,
+ 0xe8e4, 0x187a,
+ 0xe8e5, 0x2475,
+ 0xe8e6, 0x187c,
+ 0xe8e7, 0x2476,
+ 0xe8e8, 0x187e,
+ 0xe8eb, 0x2477,
+ 0xe8ec, 0x1882,
+ 0xe8ed, 0x2478,
+ 0xe8ee, 0x1884,
+ 0xe8ef, 0x2479,
+ 0xe8f0, 0x1886,
+ 0xe8f9, 0x247a,
+ 0xe8fa, 0x1890,
+ 0xe8fc, 0x247b,
+ 0xe8fe, 0x1894,
+ 0xe9a1, 0x247d,
+ 0xe9a2, 0x1896,
+ 0xe9ad, 0x247e,
+ 0xe9ae, 0x18a2,
+ 0xe9b4, 0x247f,
+ 0xe9b6, 0x18aa,
+ 0xe9b7, 0x2481,
+ 0xe9b8, 0x18ac,
+ 0xe9c4, 0x2482,
+ 0xe9c5, 0x18b9,
+ 0xe9c6, 0x2483,
+ 0xe9c7, 0x18bb,
+ 0xe9c9, 0x2484,
+ 0xe9ca, 0x18be,
+ 0xe9d6, 0x2485,
+ 0xe9d7, 0x18cb,
+ 0xe9da, 0x2486,
+ 0xe9db, 0x18cf,
+ 0xe9e4, 0x2487,
+ 0xe9e5, 0x18d9,
+ 0xe9e6, 0x2488,
+ 0xe9e8, 0x18dc,
+ 0xe9e9, 0x248a,
+ 0xe9ea, 0x18de,
+ 0xe9eb, 0x248b,
+ 0xe9ec, 0x18e0,
+ 0xe9ed, 0x248c,
+ 0xeaa1, 0x249e,
+ 0xeaa6, 0x18f8,
+ 0xeaa7, 0x24a3,
+ 0xeaa9, 0x18fb,
+ 0xeab1, 0x24a5,
+ 0xeab2, 0x1904,
+ 0xeabc, 0x24a6,
+ 0xeabd, 0x190f,
+ 0xeaca, 0x24a7,
+ 0xeacb, 0x191d,
+ 0xeacd, 0x24a8,
+ 0xeace, 0x1920,
+ 0xead3, 0x24a9,
+ 0xead4, 0x1926,
+ 0xeada, 0x24aa,
+ 0xeaf0, 0x1942,
+ 0xeba1, 0x1951,
+ 0xeba7, 0x24c0,
+ 0xeba8, 0x1958,
+ 0xebaa, 0x24c1,
+ 0xebab, 0x195b,
+ 0xebb2, 0x24c2,
+ 0xebb3, 0x1963,
+ 0xebb9, 0x24c3,
+ 0xebba, 0x196a,
+ 0xebca, 0x24c4,
+ 0xebcc, 0x197c,
+ 0xebcd, 0x24c6,
+ 0xebce, 0x197e,
+ 0xebd6, 0x24c7,
+ 0xebd7, 0x1987,
+ 0xebda, 0x24c8,
+ 0xebdb, 0x198b,
+ 0xebe1, 0x24c9,
+ 0xebe2, 0x1992,
+ 0xebf7, 0x24ca,
+ 0xebf8, 0x19a8,
+ 0xeca1, 0x19af,
+ 0xeca3, 0x24cb,
+ 0xeca4, 0x19b2,
+ 0xeca9, 0x24cc,
+ 0xecaf, 0x19bd,
+ 0xecb1, 0x24d2,
+ 0xecb2, 0x19c0,
+ 0xecb4, 0x24d3,
+ 0xecb6, 0x19c4,
+ 0xecbe, 0x24d5,
+ 0xecc0, 0x19ce,
+ 0xecc1, 0x24d7,
+ 0xecc2, 0x19d0,
+ 0xecc7, 0x24d8,
+ 0xecc8, 0x19d6,
+ 0xeccb, 0x24d9,
+ 0xeccc, 0x19da,
+ 0xece2, 0x24da,
+ 0xece3, 0x19f1,
+ 0xecf2, 0x24db,
+ 0xecf3, 0x1a01,
+ 0xecf5, 0x24dc,
+ 0xecf6, 0x1a04,
+ 0xecf8, 0x24dd,
+ 0xecf9, 0x1a07,
+ 0xeda1, 0x24de,
+ 0xeda2, 0x1a0e,
+ 0xeda8, 0x24df,
+ 0xeda9, 0x1a15,
+ 0xedaf, 0x24e0,
+ 0xedb1, 0x1a1d,
+ 0xedb4, 0x24e2,
+ 0xedb5, 0x1a21,
+ 0xedb6, 0x24e3,
+ 0xedb7, 0x1a23,
+ 0xedb8, 0x24e4,
+ 0xedb9, 0x1a25,
+ 0xedba, 0x24e5,
+ 0xedbb, 0x1a27,
+ 0xedbf, 0x24e6,
+ 0xedc0, 0x1a2c,
+ 0xedc2, 0x24e7,
+ 0xedc4, 0x1a30,
+ 0xedcc, 0x24e9,
+ 0xedce, 0x1a3a,
+ 0xedd3, 0x24eb,
+ 0xedd4, 0x1a40,
+ 0xedd7, 0x24ec,
+ 0xedd8, 0x1a44,
+ 0xede8, 0x24ed,
+ 0xede9, 0x1a55,
+ 0xedee, 0x24ee,
+ 0xedef, 0x1a5b,
+ 0xedf9, 0x24ef,
+ 0xedfb, 0x1a67,
+ 0xeea1, 0x1a6b,
+ 0xeebc, 0x24f1,
+ 0xeebd, 0x1a87,
+ 0xeebf, 0x24f2,
+ 0xeec0, 0x1a8a,
+ 0xeec4, 0x24f3,
+ 0xefa1, 0x252e,
+ 0xeff2, 0x1b1a,
+ 0xf0a1, 0x1b27,
+ 0xf0a3, 0x257f,
+ 0xf0a4, 0x1b2a,
+ 0xf0af, 0x2580,
+ 0xf0da, 0x1b60,
+ 0xf0dc, 0x25ab,
+ 0xf0de, 0x1b64,
+ 0xf0df, 0x25ad,
+ 0xf0e0, 0x1b66,
+ 0xf0e9, 0x25ae,
+ 0xf0ea, 0x1b70,
+ 0xf0ec, 0x25af,
+ 0xf0ed, 0x1b73,
+ 0xf0ef, 0x25b0,
+ 0xf0f0, 0x1b76,
+ 0xf0f7, 0x25b1,
+ 0xf0f8, 0x1b7e,
+ 0xf0f9, 0x25b2,
+ 0xf0fa, 0x1b80,
+ 0xf0fc, 0x25b3,
+ 0xf0fd, 0x1b83,
+ 0xf1a1, 0x1b85,
+ 0xf1a8, 0x25b4,
+ 0xf1a9, 0x1b8d,
+ 0xf1ab, 0x25b5,
+ 0xf1ac, 0x1b90,
+ 0xf1ae, 0x25b6,
+ 0xf1af, 0x1b93,
+ 0xf1b2, 0x25b7,
+ 0xf1b3, 0x1b97,
+ 0xf1bc, 0x25b8,
+ 0xf1bd, 0x1ba1,
+ 0xf1c0, 0x25b9,
+ 0xf1c1, 0x1ba5,
+ 0xf1c9, 0x25ba,
+ 0xf1ca, 0x1bae,
+ 0xf1cd, 0x25bb,
+ 0xf1ce, 0x1bb2,
+ 0xf1cf, 0x25bc,
+ 0xf1d1, 0x1bb5,
+ 0xf1da, 0x25be,
+ 0xf1db, 0x1bbf,
+ 0xf1dc, 0x25bf,
+ 0xf1dd, 0x1bc1,
+ 0xf1e4, 0x25c0,
+ 0xf1e5, 0x1bc9,
+ 0xf1ec, 0x25c1,
+ 0xf1ed, 0x1bd1,
+ 0xf1ef, 0x25c2,
+ 0xf1f0, 0x1bd4,
+ 0xf1f7, 0x25c3,
+ 0xf1f8, 0x1bdc,
+ 0xf1f9, 0x25c4,
+ 0xf1fa, 0x1bde,
+ 0xf1fc, 0x25c5,
+ 0xf2a1, 0x25c8,
+ 0xf2ae, 0x1bf0,
+ 0xf2b1, 0x25d5,
+ 0xf2b3, 0x1bf5,
+ 0xf2b9, 0x25d7,
+ 0xf2ba, 0x1bfc,
+ 0xf2c3, 0x25d8,
+ 0xf2c4, 0x1c06,
+ 0xf2c9, 0x25d9,
+ 0xf2ca, 0x1c0c,
+ 0xf2cc, 0x25da,
+ 0xf2ce, 0x1c10,
+ 0xf2cf, 0x25dc,
+ 0xf2d0, 0x1c12,
+ 0xf2d3, 0x25dd,
+ 0xf2d4, 0x1c16,
+ 0xf2e5, 0x25de,
+ 0xf2e6, 0x1c28,
+ 0xf2ee, 0x25df,
+ 0xf2ef, 0x1c31,
+ 0xf2f7, 0x25e0,
+ 0xf2f8, 0x1c3a,
+ 0xf2fd, 0x25e1,
+ 0xf2fe, 0x1c40,
+ 0xf3a1, 0x1c41,
+ 0xf3bf, 0x25e2,
+ 0xf3c0, 0x1c60,
+ 0xf3c6, 0x25e3,
+ 0xf3c7, 0x1c67,
+ 0xf3c8, 0x25e4,
+ 0xf3c9, 0x1c69,
+ 0xf3d6, 0x25e5,
+ 0xf3d7, 0x1c77,
+ 0xf3d9, 0x25e6,
+ 0xf3da, 0x1c7a,
+ 0xf3e5, 0x25e7,
+ 0xf3e7, 0x1c87,
+ 0xf3ea, 0x25e9,
+ 0xf3eb, 0x1c8b,
+ 0xf3ec, 0x25ea,
+ 0xf3ed, 0x1c8d,
+ 0xf3ef, 0x25eb,
+ 0xf3f0, 0x1c90,
+ 0xf3f1, 0x25ec,
+ 0xf3f2, 0x1c92,
+ 0xf3fd, 0x25ed,
+ 0xf3fe, 0x1c9e,
+ 0xf4a1, 0x1c9f,
+ 0xf4a5, 0x25ee,
+ 0xf4a6, 0x1ca4,
+ 0xf4af, 0x25ef,
+ 0xf4b0, 0x1cae,
+ 0xf4b5, 0x25f0,
+ 0xf4b6, 0x1cb4,
+ 0xf4c1, 0x25f1,
+ 0xf4c2, 0x1cc0,
+ 0xf4c7, 0x25f2,
+ 0xf4c8, 0x1cc6,
+ 0xf4cf, 0x25f3,
+ 0xf4d1, 0x1ccf,
+ 0xf4d6, 0x25f5,
+ 0xf4d7, 0x1cd5,
+ 0xf4ea, 0x25f6,
+ 0xf4eb, 0x1ce9,
+ 0xf4ef, 0x25f7,
+ 0xf4f0, 0x1cee,
+ 0xf4f5, 0x25f8,
+ 0xf4f6, 0x1cf4,
+ 0xf5a1, 0x1cfd,
+ 0xf5a6, 0x25f9,
+ 0xf5a8, 0x1d04,
+ 0xf5ba, 0x25fb,
+ 0xf5bc, 0x1d18,
+ 0xf5c4, 0x25fd,
+ 0xf5c5, 0x1d21,
+ 0xf5c8, 0x25fe,
+ 0xf5c9, 0x1d25,
+ 0xf5ce, 0x25ff,
+ 0xf5d0, 0x1d2c,
+ 0xf5d1, 0x2601,
+ 0xf5d3, 0x1d2f,
+ 0xf5d9, 0x2603,
+ 0xf5da, 0x1d36,
+ 0xf5dc, 0x2604,
+ 0xf5dd, 0x1d39,
+ 0xf5e6, 0x2605,
+ 0xf5e8, 0x1d44,
+ 0xf5ef, 0x2607,
+ 0xf5f0, 0x1d4c,
+ 0xf5f2, 0x2608,
+ 0xf5f3, 0x1d4f,
+ 0xf5fc, 0x2609,
+ 0xf5fd, 0x1d59,
+ 0xf6a1, 0x1d5b,
+ 0xf6a3, 0x260a,
+ 0xf6a4, 0x1d5e,
+ 0xf6a6, 0x260b,
+ 0xf6a7, 0x1d61,
+ 0xf6a8, 0x260c,
+ 0xf6a9, 0x1d63,
+ 0xf6ab, 0x260d,
+ 0xf6ac, 0x1d66,
+ 0xf6b0, 0x260e,
+ 0xf6b1, 0x1d6b,
+ 0xf6b3, 0x260f,
+ 0xf6bf, 0x1d79,
+ 0xf6c5, 0x261b,
+ 0xf6c6, 0x1d80,
+ 0xf6c7, 0x261c,
+ 0xf6c8, 0x1d82,
+ 0xf6c9, 0x261d,
+ 0xf6ca, 0x1d84,
+ 0xf6cf, 0x261e,
+ 0xf7a1, 0x264e,
+ 0xf7b0, 0x1dc8,
+ 0xf7b2, 0x265d,
+ 0xf7b4, 0x1dcc,
+ 0xf7b5, 0x265f,
+ 0xf7b6, 0x1dce,
+ 0xf7bd, 0x2660,
+ 0xf7be, 0x1dd6,
+ 0xf7c3, 0x2661,
+ 0xf7c4, 0x1ddc,
+ 0xf7c5, 0x2662,
+ 0xf7c7, 0x1ddf,
+ 0xf7ca, 0x2664,
+ 0xf7cc, 0x1de4,
+ 0xf7cf, 0x2666,
+ 0xf7d1, 0x1de9,
+ 0xf7de, 0x2668,
+ 0xf7df, 0x1df7,
+ 0xf7e1, 0x0ab9,
+ 0xf7e2, 0x1dfa,
+ 0xf7f2, 0x2669,
+ 0xf7f3, 0x1e0b,
+ 0xf7f5, 0x266a,
+ 0xf7f6, 0x1e0e,
+ 0xf8a1, 0x266b,
+ 0xf8a7, 0x04cc,
+ 0xf8a8, 0x050a,
+ 0xf8a9, 0x0518,
+ 0xf8aa, 0x2671,
+ 0xf8ac, 0x0594,
+ 0xf8ad, 0x05ce,
+ 0xf8ae, 0x2673,
+ 0xf8af, 0x05f6,
+ 0xf8b0, 0x2674,
+ 0xf8b2, 0x0653,
+ 0xf8b3, 0x067e,
+ 0xf8b4, 0x2676,
+ 0xf8b5, 0x06c4,
+ 0xf8b6, 0x2677,
+ 0xf8b8, 0x073c,
+ 0xf8b9, 0x2679,
+ 0xf8bb, 0x07c3,
+ 0xf8bc, 0x267b,
+ 0xf8c0, 0x082b,
+ 0xf8c1, 0x267f,
+ 0xf8c2, 0x084e,
+ 0xf8c3, 0x0869,
+ 0xf8c4, 0x2680,
+ 0xf8c6, 0x090c,
+ 0xf8c7, 0x2682,
+ 0xf8c9, 0x0971,
+ 0xf8ca, 0x2684,
+ 0xf8cb, 0x099a,
+ 0xf8cd, 0x2685,
+ 0xf8ce, 0x09da,
+ 0xf8cf, 0x2686,
+ 0xf8d0, 0x09fa,
+ 0xf8d1, 0x2687,
+ 0xf8dc, 0x0bda,
+ 0xf8dd, 0x0bdd,
+ 0xf8de, 0x0bea,
+ 0xf8df, 0x0bec,
+ 0xf8e0, 0x0bf2,
+ 0xf8e1, 0x2692,
+ 0xf8e6, 0x0c92,
+ 0xf8e7, 0x0d1a,
+ 0xf8e8, 0x0d8c,
+ 0xf8e9, 0x0dbe,
+ 0xf8ea, 0x2697,
+ 0xf8eb, 0x0dfb,
+ 0xf8ec, 0x2698,
+ 0xf8ef, 0x0e70,
+ 0xf8f0, 0x269b,
+ 0xf8f1, 0x0ea3,
+ 0xf8f2, 0x269c,
+ 0xf8f8, 0x103d,
+ 0xf8f9, 0x10d9,
+ 0xf8fa, 0x26a2,
+ 0xf8fc, 0x10fb,
+ 0xf8fd, 0x1109,
+ 0xf8fe, 0x26a4,
+ 0xf9a1, 0x11a1,
+ 0xf9a2, 0x26a5,
+ 0xf9a3, 0x11ba,
+ 0xf9a4, 0x26a6,
+ 0xf9a6, 0x11d5,
+ 0xf9a7, 0x26a8,
+ 0xf9a8, 0x11fd,
+ 0xf9a9, 0x1219,
+ 0xa1a2, 0x023f,
+ 0xa1a3, 0x023e,
+ 0xa1aa, 0x0256,
+ 0xa1ab, 0x1e18,
+ 0xa1ad, 0x0257,
+ 0xa1b2, 0x0246,
+ 0xa1fe, 0x1e1a,
+ 0xa3a1, 0x0242,
+ 0xa3a8, 0x0244,
+ 0xa3ac, 0x023d,
+ 0xa3ae, 0x1e1b,
+ 0xa3ba, 0x0240,
+ 0xa3bd, 0x1e1c,
+ 0xa3bf, 0x0243,
+ 0xa3db, 0x1e1d,
+ 0xa3dd, 0x1e1e,
+ 0xa3df, 0x0258,
+ 0xa3fb, 0x0254,
+ 0xa3fd, 0x0255,
+ 0xa3fe, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBTpcEUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 },
+ gb12GBTpcEUCVMap2, 2303
+};
+
+static Gushort gb12GBpcEUCHMap2[180] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb1a1, 0x040a,
+ 0xb2a1, 0x0468,
+ 0xb3a1, 0x04c6,
+ 0xb4a1, 0x0524,
+ 0xb5a1, 0x0582,
+ 0xb6a1, 0x05e0,
+ 0xb7a1, 0x063e,
+ 0xb8a1, 0x069c,
+ 0xb9a1, 0x06fa,
+ 0xbaa1, 0x0758,
+ 0xbba1, 0x07b6,
+ 0xbca1, 0x0814,
+ 0xbda1, 0x0872,
+ 0xbea1, 0x08d0,
+ 0xbfa1, 0x092e,
+ 0xc0a1, 0x098c,
+ 0xc1a1, 0x09ea,
+ 0xc2a1, 0x0a48,
+ 0xc3a1, 0x0aa6,
+ 0xc4a1, 0x0b04,
+ 0xc5a1, 0x0b62,
+ 0xc6a1, 0x0bc0,
+ 0xc7a1, 0x0c1e,
+ 0xc8a1, 0x0c7c,
+ 0xc9a1, 0x0cda,
+ 0xcaa1, 0x0d38,
+ 0xcba1, 0x0d96,
+ 0xcca1, 0x0df4,
+ 0xcda1, 0x0e52,
+ 0xcea1, 0x0eb0,
+ 0xcfa1, 0x0f0e,
+ 0xd0a1, 0x0f6c,
+ 0xd1a1, 0x0fca,
+ 0xd2a1, 0x1028,
+ 0xd3a1, 0x1086,
+ 0xd4a1, 0x10e4,
+ 0xd5a1, 0x1142,
+ 0xd6a1, 0x11a0,
+ 0xd7a1, 0x11fe,
+ 0xd8a1, 0x1257,
+ 0xd9a1, 0x12b5,
+ 0xdaa1, 0x1313,
+ 0xdba1, 0x1371,
+ 0xdca1, 0x13cf,
+ 0xdda1, 0x142d,
+ 0xdea1, 0x148b,
+ 0xdfa1, 0x14e9,
+ 0xe0a1, 0x1547,
+ 0xe1a1, 0x15a5,
+ 0xe2a1, 0x1603,
+ 0xe3a1, 0x1661,
+ 0xe4a1, 0x16bf,
+ 0xe5a1, 0x171d,
+ 0xe6a1, 0x177b,
+ 0xe7a1, 0x17d9,
+ 0xe8a1, 0x1837,
+ 0xe9a1, 0x1895,
+ 0xeaa1, 0x18f3,
+ 0xeba1, 0x1951,
+ 0xeca1, 0x19af,
+ 0xeda1, 0x1a0d,
+ 0xeea1, 0x1a6b,
+ 0xefa1, 0x1ac9,
+ 0xf0a1, 0x1b27,
+ 0xf1a1, 0x1b85,
+ 0xf2a1, 0x1be3,
+ 0xf3a1, 0x1c41,
+ 0xf4a1, 0x1c9f,
+ 0xf5a1, 0x1cfd,
+ 0xf6a1, 0x1d5b,
+ 0xf7a1, 0x1db9,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBpcEUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 },
+ gb12GBpcEUCHMap2, 90
+};
+
+static Gushort gb12GBpcEUCVMap2[220] = {
+ 0x0000, 0x0000,
+ 0xa1a1, 0x0060,
+ 0xa2b1, 0x00be,
+ 0xa2e5, 0x00f0,
+ 0xa2f1, 0x00fa,
+ 0xa3a1, 0x0106,
+ 0xa4a1, 0x0164,
+ 0xa5a1, 0x01b7,
+ 0xa6a1, 0x020d,
+ 0xa6c1, 0x0225,
+ 0xa7a1, 0x025a,
+ 0xa7d1, 0x027b,
+ 0xa8a1, 0x029c,
+ 0xa8c5, 0x02bc,
+ 0xa9a4, 0x02e2,
+ 0xaaa1, 0x032e,
+ 0xaba1, 0x038c,
+ 0xb0a1, 0x03ac,
+ 0xb1a1, 0x040a,
+ 0xb2a1, 0x0468,
+ 0xb3a1, 0x04c6,
+ 0xb4a1, 0x0524,
+ 0xb5a1, 0x0582,
+ 0xb6a1, 0x05e0,
+ 0xb7a1, 0x063e,
+ 0xb8a1, 0x069c,
+ 0xb9a1, 0x06fa,
+ 0xbaa1, 0x0758,
+ 0xbba1, 0x07b6,
+ 0xbca1, 0x0814,
+ 0xbda1, 0x0872,
+ 0xbea1, 0x08d0,
+ 0xbfa1, 0x092e,
+ 0xc0a1, 0x098c,
+ 0xc1a1, 0x09ea,
+ 0xc2a1, 0x0a48,
+ 0xc3a1, 0x0aa6,
+ 0xc4a1, 0x0b04,
+ 0xc5a1, 0x0b62,
+ 0xc6a1, 0x0bc0,
+ 0xc7a1, 0x0c1e,
+ 0xc8a1, 0x0c7c,
+ 0xc9a1, 0x0cda,
+ 0xcaa1, 0x0d38,
+ 0xcba1, 0x0d96,
+ 0xcca1, 0x0df4,
+ 0xcda1, 0x0e52,
+ 0xcea1, 0x0eb0,
+ 0xcfa1, 0x0f0e,
+ 0xd0a1, 0x0f6c,
+ 0xd1a1, 0x0fca,
+ 0xd2a1, 0x1028,
+ 0xd3a1, 0x1086,
+ 0xd4a1, 0x10e4,
+ 0xd5a1, 0x1142,
+ 0xd6a1, 0x11a0,
+ 0xd7a1, 0x11fe,
+ 0xd8a1, 0x1257,
+ 0xd9a1, 0x12b5,
+ 0xdaa1, 0x1313,
+ 0xdba1, 0x1371,
+ 0xdca1, 0x13cf,
+ 0xdda1, 0x142d,
+ 0xdea1, 0x148b,
+ 0xdfa1, 0x14e9,
+ 0xe0a1, 0x1547,
+ 0xe1a1, 0x15a5,
+ 0xe2a1, 0x1603,
+ 0xe3a1, 0x1661,
+ 0xe4a1, 0x16bf,
+ 0xe5a1, 0x171d,
+ 0xe6a1, 0x177b,
+ 0xe7a1, 0x17d9,
+ 0xe8a1, 0x1837,
+ 0xe9a1, 0x1895,
+ 0xeaa1, 0x18f3,
+ 0xeba1, 0x1951,
+ 0xeca1, 0x19af,
+ 0xeda1, 0x1a0d,
+ 0xeea1, 0x1a6b,
+ 0xefa1, 0x1ac9,
+ 0xf0a1, 0x1b27,
+ 0xf1a1, 0x1b85,
+ 0xf2a1, 0x1be3,
+ 0xf3a1, 0x1c41,
+ 0xf4a1, 0x1c9f,
+ 0xf5a1, 0x1cfd,
+ 0xf6a1, 0x1d5b,
+ 0xf7a1, 0x1db9,
+ 0xa1a2, 0x023f,
+ 0xa1a3, 0x023e,
+ 0xa1aa, 0x0256,
+ 0xa1ab, 0x1e18,
+ 0xa1ad, 0x0257,
+ 0xa1b2, 0x0246,
+ 0xa1fe, 0x1e1a,
+ 0xa3a1, 0x0242,
+ 0xa3a8, 0x0244,
+ 0xa3ac, 0x023d,
+ 0xa3ae, 0x1e1b,
+ 0xa3ba, 0x0240,
+ 0xa3bd, 0x1e1c,
+ 0xa3bf, 0x0243,
+ 0xa3db, 0x1e1d,
+ 0xa3dd, 0x1e1e,
+ 0xa3df, 0x0258,
+ 0xa3fb, 0x0254,
+ 0xa3fd, 0x0255,
+ 0xa3fe, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12GBpcEUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x1e20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e21, 0x1e22, 0x1e23 },
+ gb12GBpcEUCVMap2, 110
+};
+
+static Gushort gb12UniGBUCS2HMap2[26922] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x00a4, 0x00a7,
+ 0x00a7, 0x00ab,
+ 0x00a8, 0x0066,
+ 0x00b0, 0x00a2,
+ 0x00b1, 0x007f,
+ 0x00d7, 0x0080,
+ 0x00e0, 0x029f,
+ 0x00e1, 0x029d,
+ 0x00e8, 0x02a3,
+ 0x00e9, 0x02a1,
+ 0x00ea, 0x02b5,
+ 0x00ec, 0x02a7,
+ 0x00ed, 0x02a5,
+ 0x00f2, 0x02ab,
+ 0x00f3, 0x02a9,
+ 0x00f7, 0x0081,
+ 0x00f9, 0x02af,
+ 0x00fa, 0x02ad,
+ 0x00fc, 0x02b4,
+ 0x0101, 0x029c,
+ 0x0113, 0x02a0,
+ 0x011b, 0x02a2,
+ 0x012b, 0x02a4,
+ 0x014d, 0x02a8,
+ 0x016b, 0x02ac,
+ 0x01ce, 0x029e,
+ 0x01d0, 0x02a6,
+ 0x01d2, 0x02aa,
+ 0x01d4, 0x02ae,
+ 0x01d6, 0x02b0,
+ 0x01d8, 0x02b1,
+ 0x01da, 0x02b2,
+ 0x01dc, 0x02b3,
+ 0x02c7, 0x0065,
+ 0x02c9, 0x0064,
+ 0x02ca, 0x26b3,
+ 0x02d9, 0x26b5,
+ 0x0391, 0x020d,
+ 0x03a3, 0x021e,
+ 0x03b1, 0x0225,
+ 0x03c3, 0x0236,
+ 0x0401, 0x0260,
+ 0x0410, 0x025a,
+ 0x0416, 0x0261,
+ 0x0436, 0x0282,
+ 0x0451, 0x0281,
+ 0x1e3f, 0x02b7,
+ 0x2010, 0x2722,
+ 0x2013, 0x26b6,
+ 0x2014, 0x0069,
+ 0x2015, 0x26b7,
+ 0x2016, 0x006b,
+ 0x2018, 0x006d,
+ 0x201c, 0x006f,
+ 0x2025, 0x26b8,
+ 0x2026, 0x006c,
+ 0x2030, 0x00aa,
+ 0x2032, 0x00a3,
+ 0x2035, 0x26b9,
+ 0x203b, 0x00b8,
+ 0x2103, 0x00a5,
+ 0x2105, 0x26ba,
+ 0x2109, 0x26bb,
+ 0x2116, 0x00ac,
+ 0x2121, 0x2720,
+ 0x2160, 0x00fa,
+ 0x2170, 0x26a9,
+ 0x2190, 0x00ba,
+ 0x2192, 0x00b9,
+ 0x2193, 0x00bc,
+ 0x2196, 0x26bc,
+ 0x2208, 0x0089,
+ 0x220f, 0x0086,
+ 0x2211, 0x0085,
+ 0x2215, 0x26c0,
+ 0x221a, 0x008b,
+ 0x221d, 0x0097,
+ 0x221e, 0x009d,
+ 0x221f, 0x26c1,
+ 0x2220, 0x008e,
+ 0x2223, 0x26c2,
+ 0x2225, 0x008d,
+ 0x2227, 0x0083,
+ 0x2229, 0x0088,
+ 0x222a, 0x0087,
+ 0x222b, 0x0091,
+ 0x222e, 0x0092,
+ 0x2234, 0x009f,
+ 0x2235, 0x009e,
+ 0x2236, 0x0082,
+ 0x2237, 0x008a,
+ 0x223d, 0x0096,
+ 0x2248, 0x0095,
+ 0x224c, 0x0094,
+ 0x2252, 0x26c3,
+ 0x2260, 0x0098,
+ 0x2261, 0x0093,
+ 0x2264, 0x009b,
+ 0x2266, 0x26c4,
+ 0x226e, 0x0099,
+ 0x2295, 0x2704,
+ 0x2299, 0x0090,
+ 0x22a5, 0x008c,
+ 0x22bf, 0x26c6,
+ 0x22ef, 0x006c,
+ 0x2312, 0x008f,
+ 0x2460, 0x00e6,
+ 0x2474, 0x00d2,
+ 0x2488, 0x00be,
+ 0x2500, 0x02e2,
+ 0x2550, 0x26c7,
+ 0x2581, 0x26eb,
+ 0x2593, 0x26fa,
+ 0x25a0, 0x00b5,
+ 0x25a1, 0x00b4,
+ 0x25b2, 0x00b7,
+ 0x25b3, 0x00b6,
+ 0x25bc, 0x26fd,
+ 0x25c6, 0x00b3,
+ 0x25c7, 0x00b2,
+ 0x25cb, 0x00af,
+ 0x25ce, 0x00b1,
+ 0x25cf, 0x00b0,
+ 0x25e2, 0x26ff,
+ 0x2605, 0x00ae,
+ 0x2606, 0x00ad,
+ 0x2609, 0x2703,
+ 0x2640, 0x00a1,
+ 0x2642, 0x00a0,
+ 0x3000, 0x0060,
+ 0x3003, 0x0067,
+ 0x3005, 0x0068,
+ 0x3006, 0x2728,
+ 0x3007, 0x1e17,
+ 0x3008, 0x0073,
+ 0x3010, 0x007d,
+ 0x3012, 0x2705,
+ 0x3013, 0x00bd,
+ 0x3014, 0x0071,
+ 0x3016, 0x007b,
+ 0x301d, 0x2706,
+ 0x3021, 0x2708,
+ 0x3041, 0x0164,
+ 0x309b, 0x2724,
+ 0x309d, 0x2729,
+ 0x30a1, 0x01b7,
+ 0x30fb, 0x0063,
+ 0x30fc, 0x2723,
+ 0x30fd, 0x2726,
+ 0x3105, 0x02bc,
+ 0x3220, 0x00f0,
+ 0x3231, 0x2721,
+ 0x32a3, 0x2711,
+ 0x338e, 0x2712,
+ 0x339c, 0x2714,
+ 0x33a1, 0x2717,
+ 0x33c4, 0x2718,
+ 0x33ce, 0x2719,
+ 0x33d1, 0x271a,
+ 0x33d5, 0x271c,
+ 0x4e00, 0x1042,
+ 0x4e01, 0x05e0,
+ 0x4e02, 0x2758,
+ 0x4e03, 0x0bfe,
+ 0x4e04, 0x2759,
+ 0x4e07, 0x0ea3,
+ 0x4e08, 0x116a,
+ 0x4e09, 0x0cd8,
+ 0x4e0a, 0x0d08,
+ 0x4e0b, 0x0f2f,
+ 0x4e0c, 0x1258,
+ 0x4e0d, 0x0482,
+ 0x4e0e, 0x10d0,
+ 0x4e0f, 0x275c,
+ 0x4e10, 0x125a,
+ 0x4e11, 0x0518,
+ 0x4e12, 0x275d,
+ 0x4e13, 0x1205,
+ 0x4e14, 0x0c4f,
+ 0x4e15, 0x125d,
+ 0x4e16, 0x0d57,
+ 0x4e17, 0x275e,
+ 0x4e18, 0x0c6d,
+ 0x4e19, 0x0464,
+ 0x4e1a, 0x103c,
+ 0x4e1b, 0x0557,
+ 0x4e1c, 0x05ea,
+ 0x4e1d, 0x0db4,
+ 0x4e1e, 0x125f,
+ 0x4e1f, 0x275f,
+ 0x4e22, 0x05e9,
+ 0x4e23, 0x2762,
+ 0x4e24, 0x0a06,
+ 0x4e25, 0x0ff8,
+ 0x4e26, 0x2763,
+ 0x4e27, 0x0cde,
+ 0x4e28, 0x1263,
+ 0x4e29, 0x2764,
+ 0x4e2a, 0x06f1,
+ 0x4e2b, 0x0fe7,
+ 0x4e2c, 0x169c,
+ 0x4e2d, 0x11cf,
+ 0x4e2e, 0x2765,
+ 0x4e30, 0x067e,
+ 0x4e31, 0x2767,
+ 0x4e32, 0x0531,
+ 0x4e33, 0x2768,
+ 0x4e34, 0x0a22,
+ 0x4e35, 0x2769,
+ 0x4e36, 0x1272,
+ 0x4e37, 0x276a,
+ 0x4e38, 0x0e99,
+ 0x4e39, 0x0585,
+ 0x4e3a, 0x0eb9,
+ 0x4e3b, 0x11f6,
+ 0x4e3c, 0x276b,
+ 0x4e3d, 0x09e1,
+ 0x4e3e, 0x0908,
+ 0x4e3f, 0x1265,
+ 0x4e40, 0x276c,
+ 0x4e43, 0x0b2e,
+ 0x4e44, 0x276f,
+ 0x4e45, 0x08f2,
+ 0x4e46, 0x2770,
+ 0x4e47, 0x1267,
+ 0x4e48, 0x0ab9,
+ 0x4e49, 0x106c,
+ 0x4e4a, 0x2771,
+ 0x4e4b, 0x11ad,
+ 0x4e4c, 0x0ee9,
+ 0x4e4d, 0x1148,
+ 0x4e4e, 0x07ac,
+ 0x4e4f, 0x0643,
+ 0x4e50, 0x09c1,
+ 0x4e51, 0x2772,
+ 0x4e52, 0x0bd8,
+ 0x4e53, 0x0b93,
+ 0x4e54, 0x0c44,
+ 0x4e55, 0x2773,
+ 0x4e56, 0x072d,
+ 0x4e57, 0x2774,
+ 0x4e58, 0x04f0,
+ 0x4e59, 0x1059,
+ 0x4e5a, 0x2775,
+ 0x4e5c, 0x1275,
+ 0x4e5d, 0x08f4,
+ 0x4e5e, 0x0c11,
+ 0x4e5f, 0x1039,
+ 0x4e60, 0x0f1d,
+ 0x4e61, 0x0f54,
+ 0x4e62, 0x2777,
+ 0x4e66, 0x0d80,
+ 0x4e67, 0x277b,
+ 0x4e69, 0x1276,
+ 0x4e6a, 0x277d,
+ 0x4e70, 0x0a99,
+ 0x4e71, 0x0a79,
+ 0x4e72, 0x2783,
+ 0x4e73, 0x0cc4,
+ 0x4e74, 0x2784,
+ 0x4e7e, 0x0c29,
+ 0x4e7f, 0x278e,
+ 0x4e82, 0x2059,
+ 0x4e83, 0x2791,
+ 0x4e86, 0x0a14,
+ 0x4e87, 0x2794,
+ 0x4e88, 0x10cd,
+ 0x4e89, 0x119a,
+ 0x4e8a, 0x2795,
+ 0x4e8b, 0x0d59,
+ 0x4e8c, 0x063d,
+ 0x4e8d, 0x1257,
+ 0x4e8e, 0x10bf,
+ 0x4e8f, 0x0984,
+ 0x4e90, 0x2796,
+ 0x4e91, 0x1109,
+ 0x4e92, 0x07ba,
+ 0x4e93, 0x1277,
+ 0x4e94, 0x0ef4,
+ 0x4e95, 0x08dd,
+ 0x4e96, 0x2797,
+ 0x4e98, 0x125e,
+ 0x4e99, 0x2799,
+ 0x4e9a, 0x0ff0,
+ 0x4e9b, 0x0f74,
+ 0x4e9c, 0x279a,
+ 0x4e9e, 0x21f1,
+ 0x4e9f, 0x1273,
+ 0x4ea0, 0x1303,
+ 0x4ea1, 0x0ea7,
+ 0x4ea2, 0x0947,
+ 0x4ea3, 0x279c,
+ 0x4ea4, 0x088c,
+ 0x4ea5, 0x075c,
+ 0x4ea6, 0x1067,
+ 0x4ea7, 0x04c1,
+ 0x4ea8, 0x0797,
+ 0x4ea9, 0x0b19,
+ 0x4eaa, 0x279d,
+ 0x4eab, 0x0f5a,
+ 0x4eac, 0x08d8,
+ 0x4ead, 0x0e55,
+ 0x4eae, 0x0a0a,
+ 0x4eaf, 0x279e,
+ 0x4eb2, 0x0c54,
+ 0x4eb3, 0x1305,
+ 0x4eb4, 0x27a1,
+ 0x4eb5, 0x1308,
+ 0x4eb6, 0x27a2,
+ 0x4eba, 0x0ca6,
+ 0x4ebb, 0x129f,
+ 0x4ebc, 0x27a6,
+ 0x4ebf, 0x1061,
+ 0x4ec0, 0x0d49,
+ 0x4ec1, 0x0ca5,
+ 0x4ec2, 0x12a2,
+ 0x4ec3, 0x12a0,
+ 0x4ec4, 0x127c,
+ 0x4ec5, 0x08c7,
+ 0x4ec6, 0x0bec,
+ 0x4ec7, 0x0515,
+ 0x4ec8, 0x27a9,
+ 0x4ec9, 0x12a1,
+ 0x4eca, 0x08c2,
+ 0x4ecb, 0x08ba,
+ 0x4ecc, 0x27aa,
+ 0x4ecd, 0x0caf,
+ 0x4ece, 0x0556,
+ 0x4ecf, 0x27ab,
+ 0x4ed1, 0x0a7f,
+ 0x4ed2, 0x27ad,
+ 0x4ed3, 0x049d,
+ 0x4ed4, 0x122d,
+ 0x4ed5, 0x0d62,
+ 0x4ed6, 0x0df0,
+ 0x4ed7, 0x116d,
+ 0x4ed8, 0x06b1,
+ 0x4ed9, 0x0f36,
+ 0x4eda, 0x27ae,
+ 0x4edd, 0x12ee,
+ 0x4ede, 0x12a6,
+ 0x4edf, 0x0c27,
+ 0x4ee0, 0x27b1,
+ 0x4ee1, 0x12a4,
+ 0x4ee2, 0x27b2,
+ 0x4ee3, 0x057d,
+ 0x4ee4, 0x0a37,
+ 0x4ee5, 0x105b,
+ 0x4ee6, 0x27b3,
+ 0x4ee8, 0x12a3,
+ 0x4ee9, 0x27b5,
+ 0x4eea, 0x104e,
+ 0x4eeb, 0x12a5,
+ 0x4eec, 0x0acc,
+ 0x4eed, 0x27b6,
+ 0x4ef0, 0x101f,
+ 0x4ef1, 0x27b9,
+ 0x4ef2, 0x11d8,
+ 0x4ef3, 0x12a8,
+ 0x4ef4, 0x27ba,
+ 0x4ef5, 0x12ab,
+ 0x4ef6, 0x0871,
+ 0x4ef7, 0x084e,
+ 0x4ef8, 0x27bb,
+ 0x4efb, 0x0ca9,
+ 0x4efc, 0x27be,
+ 0x4efd, 0x067a,
+ 0x4efe, 0x27bf,
+ 0x4eff, 0x065f,
+ 0x4f00, 0x27c0,
+ 0x4f01, 0x0c12,
+ 0x4f02, 0x27c1,
+ 0x4f09, 0x12ae,
+ 0x4f0a, 0x1048,
+ 0x4f0b, 0x27c8,
+ 0x4f0d, 0x0ef8,
+ 0x4f0e, 0x0832,
+ 0x4f0f, 0x0699,
+ 0x4f10, 0x0642,
+ 0x4f11, 0x0fa8,
+ 0x4f12, 0x27ca,
+ 0x4f17, 0x11d9,
+ 0x4f18, 0x10aa,
+ 0x4f19, 0x0804,
+ 0x4f1a, 0x07f6,
+ 0x4f1b, 0x12a7,
+ 0x4f1c, 0x27cf,
+ 0x4f1e, 0x0cda,
+ 0x4f1f, 0x0ebf,
+ 0x4f20, 0x052e,
+ 0x4f21, 0x27d1,
+ 0x4f22, 0x12a9,
+ 0x4f23, 0x27d2,
+ 0x4f24, 0x0d04,
+ 0x4f25, 0x12ac,
+ 0x4f26, 0x0a7e,
+ 0x4f27, 0x12ad,
+ 0x4f28, 0x27d3,
+ 0x4f2a, 0x0ec0,
+ 0x4f2b, 0x12af,
+ 0x4f2c, 0x27d5,
+ 0x4f2f, 0x0475,
+ 0x4f30, 0x0719,
+ 0x4f31, 0x27d8,
+ 0x4f32, 0x12b7,
+ 0x4f33, 0x27d9,
+ 0x4f34, 0x03f4,
+ 0x4f35, 0x27da,
+ 0x4f36, 0x0a2f,
+ 0x4f37, 0x27db,
+ 0x4f38, 0x0d25,
+ 0x4f39, 0x27dc,
+ 0x4f3a, 0x0dba,
+ 0x4f3b, 0x27dd,
+ 0x4f3c, 0x0dbb,
+ 0x4f3d, 0x12b8,
+ 0x4f3e, 0x27de,
+ 0x4f43, 0x05c9,
+ 0x4f44, 0x27e3,
+ 0x4f46, 0x058c,
+ 0x4f47, 0x27e5,
+ 0x4f4d, 0x0eca,
+ 0x4f4e, 0x05ae,
+ 0x4f4f, 0x11fe,
+ 0x4f50, 0x1251,
+ 0x4f51, 0x10b8,
+ 0x4f52, 0x27eb,
+ 0x4f53, 0x0e38,
+ 0x4f54, 0x27ec,
+ 0x4f55, 0x0785,
+ 0x4f56, 0x27ed,
+ 0x4f57, 0x12b6,
+ 0x4f58, 0x12f0,
+ 0x4f59, 0x10c5,
+ 0x4f5a, 0x12b3,
+ 0x4f5b, 0x068d,
+ 0x4f5c, 0x1254,
+ 0x4f5d, 0x12b4,
+ 0x4f5e, 0x12b0,
+ 0x4f5f, 0x12b5,
+ 0x4f60, 0x0b46,
+ 0x4f61, 0x27ee,
+ 0x4f63, 0x109b,
+ 0x4f64, 0x12aa,
+ 0x4f65, 0x12f1,
+ 0x4f66, 0x27f0,
+ 0x4f67, 0x12b1,
+ 0x4f68, 0x27f1,
+ 0x4f69, 0x0ba6,
+ 0x4f6a, 0x27f2,
+ 0x4f6c, 0x09bb,
+ 0x4f6d, 0x27f4,
+ 0x4f6f, 0x1019,
+ 0x4f70, 0x03e6,
+ 0x4f71, 0x27f6,
+ 0x4f73, 0x0844,
+ 0x4f74, 0x12ba,
+ 0x4f75, 0x27f8,
+ 0x4f76, 0x12b9,
+ 0x4f77, 0x27f9,
+ 0x4f7b, 0x12c0,
+ 0x4f7c, 0x12c2,
+ 0x4f7d, 0x27fd,
+ 0x4f7e, 0x12bf,
+ 0x4f7f, 0x0d50,
+ 0x4f80, 0x27fe,
+ 0x4f83, 0x12bd,
+ 0x4f84, 0x11b5,
+ 0x4f85, 0x2801,
+ 0x4f86, 0x1ff2,
+ 0x4f87, 0x2802,
+ 0x4f88, 0x0503,
+ 0x4f89, 0x12bc,
+ 0x4f8a, 0x2803,
+ 0x4f8b, 0x09e8,
+ 0x4f8c, 0x2804,
+ 0x4f8d, 0x0d63,
+ 0x4f8e, 0x2805,
+ 0x4f8f, 0x12be,
+ 0x4f90, 0x2806,
+ 0x4f91, 0x12bb,
+ 0x4f92, 0x2807,
+ 0x4f94, 0x12c4,
+ 0x4f95, 0x2809,
+ 0x4f96, 0x205d,
+ 0x4f97, 0x05f0,
+ 0x4f98, 0x280a,
+ 0x4f9b, 0x0702,
+ 0x4f9c, 0x280d,
+ 0x4f9d, 0x1047,
+ 0x4f9e, 0x280e,
+ 0x4fa0, 0x0f2d,
+ 0x4fa1, 0x2810,
+ 0x4fa3, 0x0a69,
+ 0x4fa4, 0x2812,
+ 0x4fa5, 0x0895,
+ 0x4fa6, 0x118d,
+ 0x4fa7, 0x04a7,
+ 0x4fa8, 0x0c45,
+ 0x4fa9, 0x0978,
+ 0x4faa, 0x12c1,
+ 0x4fab, 0x2813,
+ 0x4fac, 0x12c3,
+ 0x4fad, 0x2814,
+ 0x4fae, 0x0ef9,
+ 0x4faf, 0x07a5,
+ 0x4fb0, 0x2815,
+ 0x4fb5, 0x0c53,
+ 0x4fb6, 0x281a,
+ 0x4fbf, 0x044c,
+ 0x4fc0, 0x2823,
+ 0x4fc2, 0x269c,
+ 0x4fc3, 0x055c,
+ 0x4fc4, 0x062c,
+ 0x4fc5, 0x12c8,
+ 0x4fc6, 0x2825,
+ 0x4fca, 0x092e,
+ 0x4fcb, 0x2829,
+ 0x4fce, 0x12f2,
+ 0x4fcf, 0x0c4b,
+ 0x4fd0, 0x09e9,
+ 0x4fd1, 0x12cc,
+ 0x4fd2, 0x282c,
+ 0x4fd7, 0x0dcc,
+ 0x4fd8, 0x069a,
+ 0x4fd9, 0x2831,
+ 0x4fda, 0x12c9,
+ 0x4fdb, 0x2832,
+ 0x4fdc, 0x12cb,
+ 0x4fdd, 0x040c,
+ 0x4fde, 0x10c6,
+ 0x4fdf, 0x12cd,
+ 0x4fe0, 0x21b5,
+ 0x4fe1, 0x0f90,
+ 0x4fe2, 0x2833,
+ 0x4fe3, 0x12ca,
+ 0x4fe4, 0x2834,
+ 0x4fe6, 0x12c5,
+ 0x4fe7, 0x2836,
+ 0x4fe8, 0x12c6,
+ 0x4fe9, 0x09f2,
+ 0x4fea, 0x12c7,
+ 0x4feb, 0x2837,
+ 0x4fed, 0x0866,
+ 0x4fee, 0x0fa9,
+ 0x4fef, 0x06a4,
+ 0x4ff0, 0x2839,
+ 0x4ff1, 0x0912,
+ 0x4ff2, 0x283a,
+ 0x4ff3, 0x12d1,
+ 0x4ff4, 0x283b,
+ 0x4ff8, 0x12ce,
+ 0x4ff9, 0x283f,
+ 0x4ffa, 0x03be,
+ 0x4ffb, 0x2840,
+ 0x4ffe, 0x12d6,
+ 0x4fff, 0x2843,
+ 0x5000, 0x22cc,
+ 0x5001, 0x2844,
+ 0x5006, 0x2016,
+ 0x5007, 0x2849,
+ 0x5009, 0x1e62,
+ 0x500a, 0x284b,
+ 0x500b, 0x1f20,
+ 0x500c, 0x12d8,
+ 0x500d, 0x041f,
+ 0x500e, 0x284c,
+ 0x500f, 0x12d3,
+ 0x5010, 0x284d,
+ 0x5011, 0x207f,
+ 0x5012, 0x059a,
+ 0x5013, 0x284e,
+ 0x5014, 0x0922,
+ 0x5015, 0x284f,
+ 0x5018, 0x0e1b,
+ 0x5019, 0x07a9,
+ 0x501a, 0x1057,
+ 0x501b, 0x2852,
+ 0x501c, 0x12d7,
+ 0x501d, 0x2853,
+ 0x501f, 0x08b9,
+ 0x5020, 0x2855,
+ 0x5021, 0x04d0,
+ 0x5022, 0x2856,
+ 0x5025, 0x12d9,
+ 0x5026, 0x091a,
+ 0x5027, 0x2859,
+ 0x5028, 0x12da,
+ 0x5029, 0x12cf,
+ 0x502a, 0x0b42,
+ 0x502b, 0x205c,
+ 0x502c, 0x12d2,
+ 0x502d, 0x12d5,
+ 0x502e, 0x12d4,
+ 0x502f, 0x285a,
+ 0x503a, 0x114f,
+ 0x503b, 0x2865,
+ 0x503c, 0x11b4,
+ 0x503d, 0x2866,
+ 0x503e, 0x0c60,
+ 0x503f, 0x2867,
+ 0x5043, 0x12dc,
+ 0x5044, 0x286b,
+ 0x5047, 0x084c,
+ 0x5048, 0x12de,
+ 0x5049, 0x2194,
+ 0x504a, 0x286e,
+ 0x504c, 0x12d0,
+ 0x504d, 0x2870,
+ 0x504e, 0x12df,
+ 0x504f, 0x0bca,
+ 0x5050, 0x2871,
+ 0x5055, 0x12dd,
+ 0x5056, 0x2876,
+ 0x505a, 0x1253,
+ 0x505b, 0x287a,
+ 0x505c, 0x0e54,
+ 0x505d, 0x287b,
+ 0x5065, 0x0872,
+ 0x5066, 0x2883,
+ 0x506c, 0x12e0,
+ 0x506d, 0x2889,
+ 0x5074, 0x1e65,
+ 0x5075, 0x2281,
+ 0x5076, 0x0b7d,
+ 0x5077, 0x0e66,
+ 0x5078, 0x2890,
+ 0x507b, 0x12e1,
+ 0x507c, 0x2893,
+ 0x507e, 0x12db,
+ 0x507f, 0x04ca,
+ 0x5080, 0x098b,
+ 0x5081, 0x2895,
+ 0x5085, 0x06b0,
+ 0x5086, 0x2899,
+ 0x5088, 0x09e7,
+ 0x5089, 0x289b,
+ 0x508d, 0x0403,
+ 0x508e, 0x289f,
+ 0x5096, 0x22cd,
+ 0x5097, 0x28a7,
+ 0x5098, 0x210a,
+ 0x5099, 0x1e3e,
+ 0x509a, 0x28a8,
+ 0x50a2, 0x267f,
+ 0x50a3, 0x0579,
+ 0x50a4, 0x28b0,
+ 0x50a5, 0x12e2,
+ 0x50a6, 0x28b1,
+ 0x50a7, 0x12e3,
+ 0x50a8, 0x0525,
+ 0x50a9, 0x12e4,
+ 0x50aa, 0x28b2,
+ 0x50ac, 0x0562,
+ 0x50ad, 0x222e,
+ 0x50ae, 0x28b4,
+ 0x50b2, 0x03cc,
+ 0x50b3, 0x1e96,
+ 0x50b4, 0x22cb,
+ 0x50b5, 0x226c,
+ 0x50b6, 0x28b8,
+ 0x50b7, 0x2117,
+ 0x50b8, 0x28b9,
+ 0x50ba, 0x12e5,
+ 0x50bb, 0x0cee,
+ 0x50bc, 0x28bb,
+ 0x50be, 0x20e8,
+ 0x50bf, 0x28bd,
+ 0x50c2, 0x22d4,
+ 0x50c3, 0x28c0,
+ 0x50c5, 0x1fb9,
+ 0x50c6, 0x28c2,
+ 0x50c9, 0x22d8,
+ 0x50ca, 0x28c5,
+ 0x50cf, 0x0f5e,
+ 0x50d0, 0x28ca,
+ 0x50d1, 0x20df,
+ 0x50d2, 0x28cb,
+ 0x50d5, 0x20c2,
+ 0x50d6, 0x12e6,
+ 0x50d7, 0x28ce,
+ 0x50da, 0x0a0e,
+ 0x50db, 0x28d1,
+ 0x50de, 0x2195,
+ 0x50df, 0x28d4,
+ 0x50e5, 0x1fac,
+ 0x50e6, 0x12ea,
+ 0x50e7, 0x0ce7,
+ 0x50e8, 0x22d3,
+ 0x50e9, 0x28da,
+ 0x50ec, 0x12e9,
+ 0x50ed, 0x12e8,
+ 0x50ee, 0x12eb,
+ 0x50ef, 0x28dd,
+ 0x50f3, 0x0dd0,
+ 0x50f4, 0x28e1,
+ 0x50f5, 0x087a,
+ 0x50f6, 0x28e2,
+ 0x50f9, 0x1f81,
+ 0x50fa, 0x28e5,
+ 0x50fb, 0x0bc6,
+ 0x50fc, 0x28e6,
+ 0x5100, 0x2210,
+ 0x5101, 0x28ea,
+ 0x5102, 0x22cf,
+ 0x5103, 0x28eb,
+ 0x5104, 0x2213,
+ 0x5105, 0x28ec,
+ 0x5106, 0x12e7,
+ 0x5107, 0x12ec,
+ 0x5108, 0x1fe4,
+ 0x5109, 0x1f90,
+ 0x510a, 0x28ed,
+ 0x510b, 0x12ed,
+ 0x510c, 0x28ee,
+ 0x5110, 0x22d6,
+ 0x5111, 0x28f2,
+ 0x5112, 0x0cc0,
+ 0x5113, 0x28f3,
+ 0x5114, 0x22d0,
+ 0x5115, 0x22ce,
+ 0x5116, 0x28f4,
+ 0x5118, 0x2681,
+ 0x5119, 0x28f6,
+ 0x511f, 0x1e76,
+ 0x5120, 0x28fc,
+ 0x5121, 0x09c7,
+ 0x5122, 0x28fd,
+ 0x512a, 0x2231,
+ 0x512b, 0x2905,
+ 0x5132, 0x1e93,
+ 0x5133, 0x290c,
+ 0x5137, 0x22d2,
+ 0x5138, 0x2910,
+ 0x513a, 0x22d7,
+ 0x513b, 0x22d5,
+ 0x513c, 0x22d1,
+ 0x513d, 0x2912,
+ 0x513f, 0x0638,
+ 0x5140, 0x1259,
+ 0x5141, 0x110d,
+ 0x5142, 0x2914,
+ 0x5143, 0x10ed,
+ 0x5144, 0x0fa1,
+ 0x5145, 0x0509,
+ 0x5146, 0x1178,
+ 0x5147, 0x2915,
+ 0x5148, 0x0f35,
+ 0x5149, 0x073b,
+ 0x514a, 0x2916,
+ 0x514b, 0x0958,
+ 0x514c, 0x2917,
+ 0x514d, 0x0ae7,
+ 0x514e, 0x2918,
+ 0x5151, 0x0611,
+ 0x5152, 0x1ee5,
+ 0x5153, 0x291b,
+ 0x5154, 0x0e74,
+ 0x5155, 0x1302,
+ 0x5156, 0x1304,
+ 0x5157, 0x291c,
+ 0x515a, 0x0594,
+ 0x515b, 0x291f,
+ 0x515c, 0x05f4,
+ 0x515d, 0x2920,
+ 0x5162, 0x08d3,
+ 0x5163, 0x2925,
+ 0x5165, 0x0cc6,
+ 0x5166, 0x2927,
+ 0x5168, 0x0c86,
+ 0x5169, 0x2025,
+ 0x516a, 0x2929,
+ 0x516b, 0x03d6,
+ 0x516c, 0x0704,
+ 0x516d, 0x0a42,
+ 0x516e, 0x12f6,
+ 0x516f, 0x292a,
+ 0x5170, 0x09a7,
+ 0x5171, 0x070b,
+ 0x5172, 0x292b,
+ 0x5173, 0x0731,
+ 0x5174, 0x0f96,
+ 0x5175, 0x0461,
+ 0x5176, 0x0c03,
+ 0x5177, 0x090e,
+ 0x5178, 0x05c5,
+ 0x5179, 0x1225,
+ 0x517a, 0x292c,
+ 0x517b, 0x1021,
+ 0x517c, 0x0859,
+ 0x517d, 0x0d75,
+ 0x517e, 0x292d,
+ 0x5180, 0x0830,
+ 0x5181, 0x12fa,
+ 0x5182, 0x129d,
+ 0x5183, 0x292f,
+ 0x5185, 0x0b3d,
+ 0x5186, 0x2931,
+ 0x5188, 0x06cf,
+ 0x5189, 0x0c98,
+ 0x518a, 0x2933,
+ 0x518c, 0x04a8,
+ 0x518d, 0x111c,
+ 0x518e, 0x2935,
+ 0x5192, 0x0ab5,
+ 0x5193, 0x2939,
+ 0x5195, 0x0ae6,
+ 0x5196, 0x1314,
+ 0x5197, 0x0cba,
+ 0x5198, 0x293b,
+ 0x5199, 0x0f7f,
+ 0x519a, 0x293c,
+ 0x519b, 0x092b,
+ 0x519c, 0x0b6a,
+ 0x519d, 0x293d,
+ 0x51a0, 0x0733,
+ 0x51a1, 0x2940,
+ 0x51a2, 0x1315,
+ 0x51a3, 0x2941,
+ 0x51a4, 0x10ec,
+ 0x51a5, 0x1316,
+ 0x51a6, 0x2942,
+ 0x51ab, 0x130f,
+ 0x51ac, 0x05eb,
+ 0x51ad, 0x2947,
+ 0x51af, 0x0688,
+ 0x51b0, 0x0462,
+ 0x51b1, 0x1310,
+ 0x51b2, 0x050a,
+ 0x51b3, 0x0925,
+ 0x51b4, 0x2949,
+ 0x51b5, 0x0983,
+ 0x51b6, 0x1038,
+ 0x51b7, 0x09cf,
+ 0x51b8, 0x294a,
+ 0x51bb, 0x05f2,
+ 0x51bc, 0x1312,
+ 0x51bd, 0x1311,
+ 0x51be, 0x294d,
+ 0x51c0, 0x08ea,
+ 0x51c1, 0x294f,
+ 0x51c4, 0x0bff,
+ 0x51c5, 0x2952,
+ 0x51c6, 0x1219,
+ 0x51c7, 0x1313,
+ 0x51c8, 0x2953,
+ 0x51c9, 0x0a02,
+ 0x51ca, 0x2954,
+ 0x51cb, 0x05d3,
+ 0x51cc, 0x0a31,
+ 0x51cd, 0x1ecf,
+ 0x51ce, 0x2955,
+ 0x51cf, 0x0868,
+ 0x51d0, 0x2956,
+ 0x51d1, 0x0558,
+ 0x51d2, 0x2957,
+ 0x51db, 0x0a26,
+ 0x51dc, 0x2960,
+ 0x51dd, 0x0b60,
+ 0x51de, 0x2961,
+ 0x51e0, 0x082b,
+ 0x51e1, 0x064f,
+ 0x51e2, 0x2963,
+ 0x51e4, 0x068c,
+ 0x51e5, 0x2965,
+ 0x51eb, 0x1300,
+ 0x51ec, 0x296b,
+ 0x51ed, 0x0bdd,
+ 0x51ee, 0x296c,
+ 0x51ef, 0x093a,
+ 0x51f0, 0x07e0,
+ 0x51f1, 0x1fd9,
+ 0x51f2, 0x296d,
+ 0x51f3, 0x05ab,
+ 0x51f4, 0x296e,
+ 0x51f5, 0x1399,
+ 0x51f6, 0x0fa2,
+ 0x51f7, 0x296f,
+ 0x51f8, 0x0e6a,
+ 0x51f9, 0x03c7,
+ 0x51fa, 0x051b,
+ 0x51fb, 0x080c,
+ 0x51fc, 0x139a,
+ 0x51fd, 0x0766,
+ 0x51fe, 0x2970,
+ 0x51ff, 0x1127,
+ 0x5200, 0x0597,
+ 0x5201, 0x05d4,
+ 0x5202, 0x128c,
+ 0x5203, 0x0cab,
+ 0x5204, 0x2971,
+ 0x5206, 0x0673,
+ 0x5207, 0x0c4d,
+ 0x5208, 0x128d,
+ 0x5209, 0x2973,
+ 0x520a, 0x093c,
+ 0x520b, 0x2974,
+ 0x520d, 0x138b,
+ 0x520e, 0x128e,
+ 0x520f, 0x2976,
+ 0x5211, 0x0f97,
+ 0x5212, 0x07c3,
+ 0x5213, 0x2978,
+ 0x5216, 0x196e,
+ 0x5217, 0x0a19,
+ 0x5218, 0x0a3e,
+ 0x5219, 0x1135,
+ 0x521a, 0x06d0,
+ 0x521b, 0x0537,
+ 0x521c, 0x297b,
+ 0x521d, 0x051a,
+ 0x521e, 0x297c,
+ 0x5220, 0x0cf7,
+ 0x5221, 0x297e,
+ 0x5224, 0x0b91,
+ 0x5225, 0x2981,
+ 0x5228, 0x0b9a,
+ 0x5229, 0x09e6,
+ 0x522a, 0x2984,
+ 0x522b, 0x0459,
+ 0x522c, 0x2985,
+ 0x522d, 0x128f,
+ 0x522e, 0x0727,
+ 0x522f, 0x2986,
+ 0x5230, 0x059e,
+ 0x5231, 0x2987,
+ 0x5233, 0x1290,
+ 0x5234, 0x2989,
+ 0x5236, 0x11c5,
+ 0x5237, 0x0d97,
+ 0x5238, 0x0c8a,
+ 0x5239, 0x0ceb,
+ 0x523a, 0x054f,
+ 0x523b, 0x0959,
+ 0x523c, 0x298b,
+ 0x523d, 0x074d,
+ 0x523e, 0x298c,
+ 0x523f, 0x1291,
+ 0x5241, 0x0626,
+ 0x5242, 0x0834,
+ 0x5243, 0x0e3d,
+ 0x5244, 0x22c8,
+ 0x5245, 0x298d,
+ 0x5247, 0x2263,
+ 0x5248, 0x298f,
+ 0x524a, 0x0f64,
+ 0x524b, 0x2683,
+ 0x524c, 0x1293,
+ 0x524d, 0x0c2d,
+ 0x524e, 0x2991,
+ 0x5250, 0x0729,
+ 0x5251, 0x0874,
+ 0x5252, 0x2993,
+ 0x5254, 0x0e31,
+ 0x5255, 0x2995,
+ 0x5256, 0x0be9,
+ 0x5257, 0x2996,
+ 0x525b, 0x1f17,
+ 0x525c, 0x1296,
+ 0x525d, 0x299a,
+ 0x525e, 0x1294,
+ 0x525f, 0x299b,
+ 0x5261, 0x1295,
+ 0x5262, 0x299d,
+ 0x5265, 0x0409,
+ 0x5266, 0x29a0,
+ 0x5267, 0x0916,
+ 0x5268, 0x29a1,
+ 0x5269, 0x0d3a,
+ 0x526a, 0x0867,
+ 0x526b, 0x29a2,
+ 0x526e, 0x1f2b,
+ 0x526f, 0x06ac,
+ 0x5270, 0x29a5,
+ 0x5272, 0x06e9,
+ 0x5273, 0x29a7,
+ 0x5274, 0x22ca,
+ 0x5275, 0x1e99,
+ 0x5276, 0x29a8,
+ 0x527d, 0x1298,
+ 0x527e, 0x29af,
+ 0x527f, 0x089c,
+ 0x5280, 0x29b0,
+ 0x5281, 0x129a,
+ 0x5282, 0x1299,
+ 0x5283, 0x1f4f,
+ 0x5284, 0x29b1,
+ 0x5287, 0x1fcf,
+ 0x5288, 0x0bbd,
+ 0x5289, 0x2036,
+ 0x528a, 0x1f3a,
+ 0x528b, 0x29b4,
+ 0x528c, 0x22c9,
+ 0x528d, 0x1f99,
+ 0x528e, 0x29b5,
+ 0x5290, 0x129b,
+ 0x5291, 0x1f75,
+ 0x5292, 0x29b7,
+ 0x5293, 0x129c,
+ 0x5294, 0x29b8,
+ 0x529b, 0x09ef,
+ 0x529c, 0x29bf,
+ 0x529d, 0x0c8b,
+ 0x529e, 0x03f7,
+ 0x529f, 0x06ff,
+ 0x52a0, 0x0846,
+ 0x52a1, 0x0f00,
+ 0x52a2, 0x138d,
+ 0x52a3, 0x0a1c,
+ 0x52a4, 0x29c0,
+ 0x52a8, 0x05ee,
+ 0x52a9, 0x11f9,
+ 0x52aa, 0x0b6d,
+ 0x52ab, 0x08aa,
+ 0x52ac, 0x138e,
+ 0x52ae, 0x29c4,
+ 0x52b1, 0x09e3,
+ 0x52b2, 0x08d1,
+ 0x52b3, 0x09b8,
+ 0x52b4, 0x29c7,
+ 0x52be, 0x1390,
+ 0x52bf, 0x0d5d,
+ 0x52c0, 0x29d1,
+ 0x52c1, 0x1fbe,
+ 0x52c2, 0x29d2,
+ 0x52c3, 0x0471,
+ 0x52c4, 0x29d3,
+ 0x52c7, 0x10a7,
+ 0x52c8, 0x29d6,
+ 0x52c9, 0x0ae8,
+ 0x52ca, 0x29d7,
+ 0x52cb, 0x0fd4,
+ 0x52cc, 0x29d8,
+ 0x52d0, 0x1392,
+ 0x52d1, 0x29dc,
+ 0x52d2, 0x09c0,
+ 0x52d3, 0x29dd,
+ 0x52d5, 0x1ecd,
+ 0x52d6, 0x1393,
+ 0x52d7, 0x29df,
+ 0x52d8, 0x093e,
+ 0x52d9, 0x21a9,
+ 0x52da, 0x29e0,
+ 0x52db, 0x21e6,
+ 0x52dc, 0x29e1,
+ 0x52dd, 0x2127,
+ 0x52de, 0x2003,
+ 0x52df, 0x0b1f,
+ 0x52e0, 0x29e2,
+ 0x52e2, 0x2132,
+ 0x52e3, 0x29e4,
+ 0x52e4, 0x0c57,
+ 0x52e5, 0x29e5,
+ 0x52f0, 0x1394,
+ 0x52f1, 0x2323,
+ 0x52f2, 0x29f0,
+ 0x52f5, 0x2011,
+ 0x52f6, 0x29f3,
+ 0x52f8, 0x20f5,
+ 0x52f9, 0x12fc,
+ 0x52fa, 0x0d10,
+ 0x52fb, 0x29f5,
+ 0x52fe, 0x070d,
+ 0x52ff, 0x0eff,
+ 0x5300, 0x110b,
+ 0x5301, 0x29f8,
+ 0x5305, 0x0407,
+ 0x5306, 0x0555,
+ 0x5307, 0x29fc,
+ 0x5308, 0x0fa4,
+ 0x5309, 0x29fd,
+ 0x530d, 0x12fd,
+ 0x530e, 0x2a01,
+ 0x530f, 0x14b5,
+ 0x5310, 0x12ff,
+ 0x5311, 0x2a02,
+ 0x5315, 0x1266,
+ 0x5316, 0x07c4,
+ 0x5317, 0x041a,
+ 0x5318, 0x2a06,
+ 0x5319, 0x04fc,
+ 0x531a, 0x1284,
+ 0x531b, 0x2a07,
+ 0x531d, 0x1114,
+ 0x531e, 0x2a09,
+ 0x5320, 0x0884,
+ 0x5321, 0x097c,
+ 0x5322, 0x2a0b,
+ 0x5323, 0x0f28,
+ 0x5324, 0x2a0c,
+ 0x5326, 0x1286,
+ 0x5327, 0x2a0e,
+ 0x532a, 0x0668,
+ 0x532b, 0x2a11,
+ 0x532d, 0x22c5,
+ 0x532e, 0x1287,
+ 0x532f, 0x1f5e,
+ 0x5330, 0x2a13,
+ 0x5331, 0x22c6,
+ 0x5332, 0x2a14,
+ 0x5339, 0x0bc4,
+ 0x533a, 0x0c75,
+ 0x533b, 0x1044,
+ 0x533c, 0x2a1b,
+ 0x533e, 0x1288,
+ 0x533f, 0x0b47,
+ 0x5340, 0x20ef,
+ 0x5341, 0x0d45,
+ 0x5342, 0x2a1d,
+ 0x5343, 0x0c24,
+ 0x5344, 0x2a1e,
+ 0x5345, 0x125c,
+ 0x5346, 0x2a1f,
+ 0x5347, 0x0d36,
+ 0x5348, 0x0ef6,
+ 0x5349, 0x07f1,
+ 0x534a, 0x03f6,
+ 0x534b, 0x2a20,
+ 0x534e, 0x07bf,
+ 0x534f, 0x0f78,
+ 0x5350, 0x2a23,
+ 0x5351, 0x0419,
+ 0x5352, 0x1241,
+ 0x5353, 0x121c,
+ 0x5354, 0x21d0,
+ 0x5355, 0x0586,
+ 0x5356, 0x0a9b,
+ 0x5357, 0x0b32,
+ 0x5358, 0x2a24,
+ 0x535a, 0x0470,
+ 0x535b, 0x2a26,
+ 0x535c, 0x047e,
+ 0x535d, 0x2a27,
+ 0x535e, 0x044e,
+ 0x535f, 0x14fa,
+ 0x5360, 0x115d,
+ 0x5361, 0x0935,
+ 0x5362, 0x0a53,
+ 0x5363, 0x128b,
+ 0x5364, 0x0a58,
+ 0x5365, 0x2a28,
+ 0x5366, 0x128a,
+ 0x5367, 0x0ee3,
+ 0x5368, 0x2a29,
+ 0x5369, 0x1352,
+ 0x536a, 0x2a2a,
+ 0x536b, 0x0ecf,
+ 0x536c, 0x2a2b,
+ 0x536e, 0x126a,
+ 0x536f, 0x0ab3,
+ 0x5370, 0x1086,
+ 0x5371, 0x0eb2,
+ 0x5372, 0x2a2d,
+ 0x5373, 0x0827,
+ 0x5374, 0x0c8f,
+ 0x5375, 0x0a78,
+ 0x5376, 0x2a2e,
+ 0x5377, 0x091c,
+ 0x5378, 0x0f81,
+ 0x5379, 0x2a2f,
+ 0x537a, 0x1353,
+ 0x537b, 0x2a30,
+ 0x537f, 0x0c61,
+ 0x5380, 0x2a34,
+ 0x5382, 0x04cc,
+ 0x5383, 0x2a36,
+ 0x5384, 0x0631,
+ 0x5385, 0x0e4f,
+ 0x5386, 0x09e5,
+ 0x5387, 0x2a37,
+ 0x5389, 0x09e2,
+ 0x538a, 0x2a39,
+ 0x538b, 0x0fe2,
+ 0x538c, 0x100a,
+ 0x538d, 0x127d,
+ 0x538e, 0x2a3a,
+ 0x5395, 0x04a5,
+ 0x5396, 0x2a41,
+ 0x5398, 0x09d0,
+ 0x5399, 0x22c1,
+ 0x539a, 0x07a8,
+ 0x539b, 0x2a43,
+ 0x539d, 0x127e,
+ 0x539e, 0x2a45,
+ 0x539f, 0x10f0,
+ 0x53a0, 0x1e64,
+ 0x53a1, 0x2a46,
+ 0x53a2, 0x0f4e,
+ 0x53a3, 0x127f,
+ 0x53a4, 0x2a47,
+ 0x53a5, 0x1280,
+ 0x53a6, 0x0f30,
+ 0x53a7, 0x2a48,
+ 0x53a8, 0x051d,
+ 0x53a9, 0x08f6,
+ 0x53aa, 0x2a49,
+ 0x53ad, 0x21f9,
+ 0x53ae, 0x1281,
+ 0x53af, 0x2a4c,
+ 0x53b2, 0x2010,
+ 0x53b3, 0x2a4f,
+ 0x53b4, 0x22c2,
+ 0x53b5, 0x2a50,
+ 0x53b6, 0x139c,
+ 0x53b7, 0x2a51,
+ 0x53bb, 0x0c80,
+ 0x53bc, 0x2a55,
+ 0x53bf, 0x0f45,
+ 0x53c0, 0x2a58,
+ 0x53c1, 0x0cd9,
+ 0x53c2, 0x0495,
+ 0x53c3, 0x1e5a,
+ 0x53c4, 0x2a59,
+ 0x53c8, 0x10bb,
+ 0x53c9, 0x04ad,
+ 0x53ca, 0x0823,
+ 0x53cb, 0x10b6,
+ 0x53cc, 0x0da0,
+ 0x53cd, 0x0651,
+ 0x53ce, 0x2a5d,
+ 0x53d1, 0x063f,
+ 0x53d2, 0x2a60,
+ 0x53d4, 0x0d7c,
+ 0x53d5, 0x2a62,
+ 0x53d6, 0x0c7c,
+ 0x53d7, 0x0d73,
+ 0x53d8, 0x044d,
+ 0x53d9, 0x0fbb,
+ 0x53da, 0x2a63,
+ 0x53db, 0x0b92,
+ 0x53dc, 0x2a64,
+ 0x53df, 0x1395,
+ 0x53e0, 0x05df,
+ 0x53e1, 0x2a67,
+ 0x53e2, 0x1ea2,
+ 0x53e3, 0x0967,
+ 0x53e4, 0x071e,
+ 0x53e5, 0x0913,
+ 0x53e6, 0x0a36,
+ 0x53e7, 0x2a68,
+ 0x53e8, 0x14fe,
+ 0x53e9, 0x14fd,
+ 0x53ea, 0x11ba,
+ 0x53eb, 0x08a1,
+ 0x53ec, 0x117a,
+ 0x53ed, 0x03d3,
+ 0x53ee, 0x05e2,
+ 0x53ef, 0x0956,
+ 0x53f0, 0x0dfb,
+ 0x53f1, 0x14fb,
+ 0x53f2, 0x0d4e,
+ 0x53f3, 0x10b7,
+ 0x53f4, 0x2a69,
+ 0x53f5, 0x1285,
+ 0x53f6, 0x103d,
+ 0x53f7, 0x077c,
+ 0x53f8, 0x0db3,
+ 0x53f9, 0x0e11,
+ 0x53fa, 0x2a6a,
+ 0x53fb, 0x14ff,
+ 0x53fc, 0x05d1,
+ 0x53fd, 0x14fc,
+ 0x53fe, 0x2a6b,
+ 0x5400, 0x2a6d,
+ 0x5401, 0x10da,
+ 0x5402, 0x2a6e,
+ 0x5403, 0x04f9,
+ 0x5404, 0x06f2,
+ 0x5405, 0x2a6f,
+ 0x5406, 0x1502,
+ 0x5407, 0x2a70,
+ 0x5408, 0x0786,
+ 0x5409, 0x081d,
+ 0x540a, 0x05d6,
+ 0x540b, 0x2a71,
+ 0x540c, 0x0e5d,
+ 0x540d, 0x0b00,
+ 0x540e, 0x07aa,
+ 0x540f, 0x09df,
+ 0x5410, 0x0e73,
+ 0x5411, 0x0f5f,
+ 0x5412, 0x1500,
+ 0x5413, 0x0f32,
+ 0x5414, 0x2a72,
+ 0x5415, 0x0a67,
+ 0x5416, 0x1501,
+ 0x5417, 0x0a97,
+ 0x5418, 0x2a73,
+ 0x541b, 0x092c,
+ 0x541c, 0x2a76,
+ 0x541d, 0x0a28,
+ 0x541e, 0x0e7d,
+ 0x541f, 0x107e,
+ 0x5420, 0x066a,
+ 0x5421, 0x1509,
+ 0x5422, 0x2a77,
+ 0x5423, 0x150c,
+ 0x5424, 0x2a78,
+ 0x5426, 0x068e,
+ 0x5427, 0x03d4,
+ 0x5428, 0x0615,
+ 0x5429, 0x0671,
+ 0x542a, 0x2a7a,
+ 0x542b, 0x0763,
+ 0x542c, 0x0e50,
+ 0x542d, 0x0961,
+ 0x542e, 0x0da6,
+ 0x542f, 0x0c13,
+ 0x5430, 0x2a7b,
+ 0x5431, 0x11a7,
+ 0x5432, 0x150d,
+ 0x5433, 0x2a7c,
+ 0x5434, 0x0ef1,
+ 0x5435, 0x04d8,
+ 0x5436, 0x2a7d,
+ 0x5438, 0x0f0b,
+ 0x5439, 0x0538,
+ 0x543a, 0x2a7f,
+ 0x543b, 0x0ed6,
+ 0x543c, 0x07a7,
+ 0x543d, 0x2a80,
+ 0x543e, 0x0ef0,
+ 0x543f, 0x2a81,
+ 0x5440, 0x0fe6,
+ 0x5441, 0x2a82,
+ 0x5443, 0x1508,
+ 0x5444, 0x2a84,
+ 0x5446, 0x0577,
+ 0x5447, 0x2a86,
+ 0x5448, 0x04ef,
+ 0x5449, 0x2a87,
+ 0x544a, 0x06e1,
+ 0x544b, 0x1503,
+ 0x544c, 0x2a88,
+ 0x5450, 0x0b28,
+ 0x5451, 0x2a8c,
+ 0x5452, 0x1504,
+ 0x5455, 0x0b7c,
+ 0x5456, 0x1507,
+ 0x5457, 0x150a,
+ 0x5458, 0x10f4,
+ 0x5459, 0x150b,
+ 0x545a, 0x2a8d,
+ 0x545b, 0x0c37,
+ 0x545c, 0x0ee7,
+ 0x545d, 0x2a8e,
+ 0x5462, 0x0b3b,
+ 0x5463, 0x2a93,
+ 0x5464, 0x1512,
+ 0x5465, 0x2a94,
+ 0x5466, 0x1517,
+ 0x5467, 0x2a95,
+ 0x5468, 0x11db,
+ 0x5469, 0x2a96,
+ 0x5471, 0x1511,
+ 0x5472, 0x1522,
+ 0x5473, 0x0ec5,
+ 0x5474, 0x2a9e,
+ 0x5475, 0x077e,
+ 0x5476, 0x1516,
+ 0x5477, 0x1510,
+ 0x5478, 0x0b9f,
+ 0x5479, 0x2a9f,
+ 0x547b, 0x0d24,
+ 0x547c, 0x07ab,
+ 0x547d, 0x0b01,
+ 0x547e, 0x2aa1,
+ 0x5480, 0x0906,
+ 0x5481, 0x2aa3,
+ 0x5482, 0x150e,
+ 0x5483, 0x2aa4,
+ 0x5484, 0x1515,
+ 0x5485, 0x2aa5,
+ 0x5486, 0x0b99,
+ 0x5487, 0x2aa6,
+ 0x548b, 0x1147,
+ 0x548c, 0x0784,
+ 0x548d, 0x2aaa,
+ 0x548e, 0x08fb,
+ 0x548f, 0x10a2,
+ 0x5490, 0x06bb,
+ 0x5491, 0x2aab,
+ 0x5492, 0x11e3,
+ 0x5493, 0x2aac,
+ 0x5494, 0x150f,
+ 0x5495, 0x0717,
+ 0x5496, 0x0934,
+ 0x5497, 0x2aad,
+ 0x5499, 0x0a45,
+ 0x549a, 0x1513,
+ 0x549c, 0x2aaf,
+ 0x549d, 0x1518,
+ 0x549e, 0x2ab0,
+ 0x54a3, 0x1523,
+ 0x54a4, 0x152d,
+ 0x54a5, 0x2ab5,
+ 0x54a6, 0x151f,
+ 0x54a7, 0x151e,
+ 0x54a8, 0x1226,
+ 0x54a9, 0x152b,
+ 0x54ab, 0x1767,
+ 0x54ac, 0x102e,
+ 0x54ad, 0x151a,
+ 0x54ae, 0x2ab6,
+ 0x54af, 0x0936,
+ 0x54b0, 0x2ab7,
+ 0x54b1, 0x111e,
+ 0x54b2, 0x2ab8,
+ 0x54b3, 0x0955,
+ 0x54b4, 0x151c,
+ 0x54b5, 0x2ab9,
+ 0x54b8, 0x0f39,
+ 0x54b9, 0x2abc,
+ 0x54bb, 0x1525,
+ 0x54bc, 0x236d,
+ 0x54bd, 0x0ff3,
+ 0x54be, 0x2abe,
+ 0x54bf, 0x1526,
+ 0x54c0, 0x03b2,
+ 0x54c1, 0x0bd6,
+ 0x54c2, 0x151b,
+ 0x54c3, 0x2abf,
+ 0x54c4, 0x079c,
+ 0x54c5, 0x2ac0,
+ 0x54c6, 0x061e,
+ 0x54c7, 0x0e8c,
+ 0x54c8, 0x0757,
+ 0x54c9, 0x1118,
+ 0x54ca, 0x2ac1,
+ 0x54cc, 0x1527,
+ 0x54cd, 0x0f59,
+ 0x54ce, 0x03b0,
+ 0x54cf, 0x152f,
+ 0x54d0, 0x1519,
+ 0x54d1, 0x0fef,
+ 0x54d2, 0x151d,
+ 0x54d3, 0x1520,
+ 0x54d5, 0x1524,
+ 0x54d6, 0x2ac3,
+ 0x54d7, 0x07be,
+ 0x54d8, 0x2ac4,
+ 0x54d9, 0x1528,
+ 0x54db, 0x2ac5,
+ 0x54dc, 0x152a,
+ 0x54dd, 0x152e,
+ 0x54de, 0x1530,
+ 0x54df, 0x1099,
+ 0x54e0, 0x2ac6,
+ 0x54e1, 0x2247,
+ 0x54e2, 0x2ac7,
+ 0x54e5, 0x06e2,
+ 0x54e6, 0x0b77,
+ 0x54e7, 0x1532,
+ 0x54e8, 0x0d13,
+ 0x54e9, 0x09f1,
+ 0x54ea, 0x0b27,
+ 0x54eb, 0x2aca,
+ 0x54ed, 0x096b,
+ 0x54ee, 0x0f65,
+ 0x54ef, 0x2acc,
+ 0x54f2, 0x117d,
+ 0x54f3, 0x1536,
+ 0x54f4, 0x2acf,
+ 0x54fa, 0x047f,
+ 0x54fb, 0x2ad5,
+ 0x54fc, 0x0796,
+ 0x54fd, 0x1534,
+ 0x54fe, 0x2ad6,
+ 0x54ff, 0x1391,
+ 0x5500, 0x2ad7,
+ 0x5501, 0x100d,
+ 0x5502, 0x2ad8,
+ 0x5504, 0x236c,
+ 0x5505, 0x2ada,
+ 0x5506, 0x0de9,
+ 0x5507, 0x0540,
+ 0x5508, 0x2adb,
+ 0x5509, 0x03b1,
+ 0x550a, 0x2adc,
+ 0x550f, 0x1539,
+ 0x5510, 0x0e19,
+ 0x5511, 0x153a,
+ 0x5512, 0x2ae1,
+ 0x5514, 0x1535,
+ 0x5515, 0x2ae3,
+ 0x551b, 0x1531,
+ 0x551c, 0x2ae9,
+ 0x5520, 0x1533,
+ 0x5521, 0x2aed,
+ 0x5522, 0x1537,
+ 0x5524, 0x07d2,
+ 0x5525, 0x2aee,
+ 0x5527, 0x153b,
+ 0x5528, 0x2af0,
+ 0x552a, 0x153c,
+ 0x552b, 0x2af2,
+ 0x552c, 0x07b8,
+ 0x552d, 0x2af3,
+ 0x552e, 0x0d72,
+ 0x552f, 0x0eb7,
+ 0x5530, 0x154d,
+ 0x5531, 0x04cf,
+ 0x5532, 0x2af4,
+ 0x5533, 0x154c,
+ 0x5534, 0x2af5,
+ 0x5537, 0x1547,
+ 0x5538, 0x2af8,
+ 0x553c, 0x1546,
+ 0x553d, 0x2afc,
+ 0x553e, 0x0e8a,
+ 0x553f, 0x1544,
+ 0x5540, 0x2afd,
+ 0x5541, 0x1542,
+ 0x5542, 0x2afe,
+ 0x5543, 0x095d,
+ 0x5544, 0x1221,
+ 0x5545, 0x2aff,
+ 0x5546, 0x0d05,
+ 0x5547, 0x2b00,
+ 0x5549, 0x1540,
+ 0x554a, 0x03ac,
+ 0x554b, 0x2b02,
+ 0x554f, 0x219c,
+ 0x5550, 0x1545,
+ 0x5551, 0x2b06,
+ 0x5553, 0x20c9,
+ 0x5554, 0x2b08,
+ 0x5555, 0x1543,
+ 0x5556, 0x1548,
+ 0x5557, 0x2b09,
+ 0x555c, 0x154e,
+ 0x555d, 0x2b0e,
+ 0x555e, 0x21f0,
+ 0x555f, 0x2b0f,
+ 0x5561, 0x0665,
+ 0x5562, 0x2b11,
+ 0x5564, 0x0bc0,
+ 0x5565, 0x0cef,
+ 0x5566, 0x099d,
+ 0x5567, 0x153d,
+ 0x5568, 0x2b13,
+ 0x556a, 0x0b7f,
+ 0x556b, 0x2b15,
+ 0x556c, 0x127a,
+ 0x556d, 0x1541,
+ 0x556e, 0x0b59,
+ 0x556f, 0x2b16,
+ 0x5575, 0x1549,
+ 0x5578, 0x0f70,
+ 0x5579, 0x2b1c,
+ 0x557b, 0x155a,
+ 0x557c, 0x0e37,
+ 0x557d, 0x2b1e,
+ 0x557e, 0x1557,
+ 0x557f, 0x2b1f,
+ 0x5580, 0x0933,
+ 0x5581, 0x1555,
+ 0x5582, 0x0ec8,
+ 0x5583, 0x1551,
+ 0x5584, 0x0cff,
+ 0x5585, 0x2b20,
+ 0x5587, 0x0999,
+ 0x5588, 0x1554,
+ 0x5589, 0x07a4,
+ 0x558a, 0x0767,
+ 0x558b, 0x154f,
+ 0x558c, 0x2b22,
+ 0x558f, 0x153e,
+ 0x5590, 0x2b25,
+ 0x5591, 0x1559,
+ 0x5592, 0x2b26,
+ 0x5594, 0x155e,
+ 0x5595, 0x2b28,
+ 0x5598, 0x0530,
+ 0x5599, 0x155f,
+ 0x559a, 0x2b2b,
+ 0x559c, 0x0f1f,
+ 0x559d, 0x077f,
+ 0x559e, 0x2b2d,
+ 0x559f, 0x1556,
+ 0x55a0, 0x2b2e,
+ 0x55a7, 0x0fc5,
+ 0x55a8, 0x2b35,
+ 0x55aa, 0x210b,
+ 0x55ab, 0x2b37,
+ 0x55ac, 0x20de,
+ 0x55ad, 0x2b38,
+ 0x55ae, 0x1eaa,
+ 0x55af, 0x2b39,
+ 0x55b1, 0x1552,
+ 0x55b2, 0x222c,
+ 0x55b3, 0x113e,
+ 0x55b4, 0x2b3b,
+ 0x55b5, 0x153f,
+ 0x55b6, 0x2b3c,
+ 0x55b7, 0x0ba8,
+ 0x55b8, 0x2b3d,
+ 0x55b9, 0x1553,
+ 0x55ba, 0x2b3e,
+ 0x55bb, 0x10dc,
+ 0x55bc, 0x2b3f,
+ 0x55bd, 0x155c,
+ 0x55bf, 0x2b40,
+ 0x55c4, 0x156a,
+ 0x55c5, 0x0fac,
+ 0x55c6, 0x20d8,
+ 0x55c7, 0x22c0,
+ 0x55c8, 0x2b45,
+ 0x55c9, 0x1562,
+ 0x55ca, 0x2b46,
+ 0x55cc, 0x156f,
+ 0x55ce, 0x206f,
+ 0x55cf, 0x2b48,
+ 0x55d1, 0x1564,
+ 0x55d2, 0x1550,
+ 0x55d3, 0x0cdd,
+ 0x55d4, 0x1567,
+ 0x55d5, 0x2b4a,
+ 0x55d6, 0x1558,
+ 0x55d7, 0x2b4b,
+ 0x55da, 0x21a1,
+ 0x55db, 0x2b4e,
+ 0x55dc, 0x0d5f,
+ 0x55dd, 0x1569,
+ 0x55de, 0x2b4f,
+ 0x55df, 0x155b,
+ 0x55e0, 0x2b50,
+ 0x55e1, 0x0eda,
+ 0x55e2, 0x2b51,
+ 0x55e3, 0x0db8,
+ 0x55e4, 0x1573,
+ 0x55e5, 0x156c,
+ 0x55e6, 0x1568,
+ 0x55e7, 0x2b52,
+ 0x55e8, 0x1571,
+ 0x55e9, 0x2379,
+ 0x55ea, 0x1560,
+ 0x55eb, 0x1565,
+ 0x55ed, 0x2b53,
+ 0x55ef, 0x156b,
+ 0x55f0, 0x2b55,
+ 0x55f2, 0x156d,
+ 0x55f4, 0x2b57,
+ 0x55f5, 0x1572,
+ 0x55f6, 0x2372,
+ 0x55f7, 0x1561,
+ 0x55f8, 0x2b58,
+ 0x55fd, 0x0dc9,
+ 0x55fe, 0x157b,
+ 0x55ff, 0x2b5d,
+ 0x5600, 0x157c,
+ 0x5601, 0x1578,
+ 0x5602, 0x2b5e,
+ 0x5606, 0x216a,
+ 0x5607, 0x2b62,
+ 0x5608, 0x1576,
+ 0x5609, 0x0841,
+ 0x560a, 0x2b63,
+ 0x560c, 0x1577,
+ 0x560d, 0x237c,
+ 0x560e, 0x06bd,
+ 0x560f, 0x127b,
+ 0x5610, 0x2b65,
+ 0x5614, 0x20b0,
+ 0x5615, 0x2b69,
+ 0x5616, 0x237a,
+ 0x5617, 0x1e74,
+ 0x5618, 0x0fb5,
+ 0x5619, 0x2b6a,
+ 0x561b, 0x0a96,
+ 0x561c, 0x2377,
+ 0x561d, 0x2b6c,
+ 0x561e, 0x1575,
+ 0x561f, 0x1563,
+ 0x5620, 0x2b6d,
+ 0x5623, 0x157a,
+ 0x5624, 0x1579,
+ 0x5625, 0x2b70,
+ 0x5627, 0x157d,
+ 0x5628, 0x2b72,
+ 0x5629, 0x1f4c,
+ 0x562a, 0x2b73,
+ 0x562c, 0x1582,
+ 0x562d, 0x157e,
+ 0x562e, 0x2378,
+ 0x562f, 0x21cf,
+ 0x5630, 0x2368,
+ 0x5631, 0x11f5,
+ 0x5632, 0x04d5,
+ 0x5633, 0x2b75,
+ 0x5634, 0x1249,
+ 0x5635, 0x2371,
+ 0x5636, 0x0db0,
+ 0x5637, 0x2b76,
+ 0x5638, 0x2369,
+ 0x5639, 0x1580,
+ 0x563a, 0x2b77,
+ 0x563b, 0x0f0a,
+ 0x563c, 0x2b78,
+ 0x563f, 0x0790,
+ 0x5640, 0x2b7b,
+ 0x5641, 0x2674,
+ 0x5642, 0x2b7c,
+ 0x564c, 0x1587,
+ 0x564d, 0x1583,
+ 0x564e, 0x1034,
+ 0x564f, 0x2b86,
+ 0x5654, 0x1588,
+ 0x5655, 0x2b8b,
+ 0x5657, 0x1581,
+ 0x5658, 0x157f,
+ 0x5659, 0x1585,
+ 0x565a, 0x2b8d,
+ 0x565c, 0x1586,
+ 0x565d, 0x236f,
+ 0x565e, 0x2b8f,
+ 0x5660, 0x2370,
+ 0x5661, 0x2b91,
+ 0x5662, 0x1584,
+ 0x5663, 0x2b92,
+ 0x5664, 0x158a,
+ 0x5665, 0x2376,
+ 0x5666, 0x2373,
+ 0x5667, 0x2b93,
+ 0x5668, 0x0c16,
+ 0x5669, 0x1262,
+ 0x566a, 0x112e,
+ 0x566b, 0x158c,
+ 0x566c, 0x0d60,
+ 0x566d, 0x2b94,
+ 0x566f, 0x237f,
+ 0x5670, 0x2b96,
+ 0x5671, 0x158b,
+ 0x5672, 0x2374,
+ 0x5673, 0x2b97,
+ 0x5674, 0x20b5,
+ 0x5675, 0x2b98,
+ 0x5676, 0x06bc,
+ 0x5677, 0x2b99,
+ 0x5678, 0x1edb,
+ 0x5679, 0x2672,
+ 0x567a, 0x2b9a,
+ 0x567b, 0x158d,
+ 0x567d, 0x2b9b,
+ 0x5680, 0x236e,
+ 0x5681, 0x2b9e,
+ 0x5685, 0x158f,
+ 0x5686, 0x1589,
+ 0x5687, 0x21b7,
+ 0x5688, 0x2ba2,
+ 0x568c, 0x2375,
+ 0x568d, 0x2ba6,
+ 0x568e, 0x0776,
+ 0x568f, 0x0e3a,
+ 0x5690, 0x2ba7,
+ 0x5693, 0x1590,
+ 0x5694, 0x2baa,
+ 0x5695, 0x2382,
+ 0x5696, 0x2bab,
+ 0x5699, 0x209e,
+ 0x569a, 0x2bae,
+ 0x56a3, 0x0f66,
+ 0x56a4, 0x2bb7,
+ 0x56a6, 0x236b,
+ 0x56a7, 0x2bb9,
+ 0x56a8, 0x2039,
+ 0x56a9, 0x2bba,
+ 0x56ae, 0x269f,
+ 0x56af, 0x1591,
+ 0x56b0, 0x2bbf,
+ 0x56b3, 0x237d,
+ 0x56b4, 0x21f5,
+ 0x56b5, 0x2bc2,
+ 0x56b6, 0x2381,
+ 0x56b7, 0x0c9d,
+ 0x56b8, 0x2bc3,
+ 0x56bc, 0x0891,
+ 0x56bd, 0x2bc7,
+ 0x56c0, 0x237b,
+ 0x56c1, 0x237e,
+ 0x56c2, 0x21cc,
+ 0x56c3, 0x2bca,
+ 0x56c5, 0x22db,
+ 0x56c6, 0x2bcc,
+ 0x56c8, 0x236a,
+ 0x56c9, 0x2689,
+ 0x56ca, 0x0b35,
+ 0x56cb, 0x2bce,
+ 0x56cc, 0x2697,
+ 0x56cd, 0x2bcf,
+ 0x56d1, 0x22a1,
+ 0x56d2, 0x2bd3,
+ 0x56d4, 0x1592,
+ 0x56d5, 0x2bd5,
+ 0x56d7, 0x1593,
+ 0x56d8, 0x2bd7,
+ 0x56da, 0x0c71,
+ 0x56db, 0x0db9,
+ 0x56dc, 0x2bd9,
+ 0x56dd, 0x1594,
+ 0x56de, 0x07ed,
+ 0x56df, 0x126c,
+ 0x56e0, 0x1079,
+ 0x56e1, 0x1595,
+ 0x56e2, 0x0e76,
+ 0x56e3, 0x2bda,
+ 0x56e4, 0x0619,
+ 0x56e5, 0x2bdb,
+ 0x56eb, 0x1597,
+ 0x56ec, 0x2be1,
+ 0x56ed, 0x10f3,
+ 0x56ee, 0x2be2,
+ 0x56f0, 0x0992,
+ 0x56f1, 0x0554,
+ 0x56f2, 0x2be4,
+ 0x56f4, 0x0eb6,
+ 0x56f5, 0x1596,
+ 0x56f6, 0x2be6,
+ 0x56f9, 0x1598,
+ 0x56fa, 0x0725,
+ 0x56fb, 0x2be9,
+ 0x56fd, 0x0753,
+ 0x56fe, 0x0e6d,
+ 0x56ff, 0x1599,
+ 0x5700, 0x2beb,
+ 0x5703, 0x0bf3,
+ 0x5704, 0x159a,
+ 0x5705, 0x2bee,
+ 0x5706, 0x10f5,
+ 0x5707, 0x2383,
+ 0x5708, 0x0c81,
+ 0x5709, 0x159c,
+ 0x570a, 0x159b,
+ 0x570b, 0x1f3d,
+ 0x570c, 0x2bef,
+ 0x570d, 0x218f,
+ 0x570e, 0x2bf0,
+ 0x5712, 0x2246,
+ 0x5713, 0x2248,
+ 0x5714, 0x2bf4,
+ 0x5716, 0x217e,
+ 0x5717, 0x2bf6,
+ 0x5718, 0x2180,
+ 0x5719, 0x2bf7,
+ 0x571c, 0x159d,
+ 0x571d, 0x2bfa,
+ 0x571f, 0x0e72,
+ 0x5720, 0x2bfc,
+ 0x5723, 0x0d3c,
+ 0x5724, 0x2bff,
+ 0x5728, 0x111d,
+ 0x5729, 0x13a7,
+ 0x572a, 0x13a9,
+ 0x572b, 0x2c03,
+ 0x572c, 0x13a8,
+ 0x572d, 0x0740,
+ 0x572e, 0x13ac,
+ 0x5730, 0x05b9,
+ 0x5731, 0x2c04,
+ 0x5733, 0x13aa,
+ 0x5734, 0x2c06,
+ 0x5739, 0x13ab,
+ 0x573a, 0x04c6,
+ 0x573b, 0x13af,
+ 0x573c, 0x2c0b,
+ 0x573e, 0x080d,
+ 0x573f, 0x2c0d,
+ 0x5740, 0x11b6,
+ 0x5741, 0x2c0e,
+ 0x5742, 0x13b0,
+ 0x5743, 0x2c0f,
+ 0x5747, 0x0928,
+ 0x5748, 0x2c13,
+ 0x574a, 0x0658,
+ 0x574b, 0x2c15,
+ 0x574c, 0x13a0,
+ 0x574d, 0x0e01,
+ 0x574e, 0x093f,
+ 0x574f, 0x07ca,
+ 0x5750, 0x1255,
+ 0x5751, 0x0960,
+ 0x5752, 0x2c16,
+ 0x5757, 0x0976,
+ 0x5758, 0x2c1b,
+ 0x575a, 0x0854,
+ 0x575b, 0x0e06,
+ 0x575c, 0x13ae,
+ 0x575d, 0x03de,
+ 0x575e, 0x0efa,
+ 0x575f, 0x0675,
+ 0x5760, 0x1216,
+ 0x5761, 0x0be1,
+ 0x5762, 0x2c1d,
+ 0x5764, 0x098f,
+ 0x5765, 0x2c1f,
+ 0x5766, 0x0e0c,
+ 0x5767, 0x2c20,
+ 0x5768, 0x13b7,
+ 0x5769, 0x13b1,
+ 0x576a, 0x0bd9,
+ 0x576b, 0x13b3,
+ 0x576c, 0x2c21,
+ 0x576d, 0x13b8,
+ 0x576e, 0x2c22,
+ 0x576f, 0x0bb8,
+ 0x5770, 0x2c23,
+ 0x5773, 0x13ba,
+ 0x5774, 0x2c26,
+ 0x5776, 0x13b9,
+ 0x5777, 0x094d,
+ 0x5778, 0x2c28,
+ 0x577b, 0x13b6,
+ 0x577c, 0x13b5,
+ 0x577d, 0x2c2b,
+ 0x5782, 0x053c,
+ 0x5783, 0x0997,
+ 0x5784, 0x0a49,
+ 0x5785, 0x13b2,
+ 0x5786, 0x13b4,
+ 0x5787, 0x2c30,
+ 0x578b, 0x0f98,
+ 0x578c, 0x13bd,
+ 0x578d, 0x2c34,
+ 0x5792, 0x09c8,
+ 0x5793, 0x13c2,
+ 0x5794, 0x2c39,
+ 0x579b, 0x0621,
+ 0x579c, 0x2c40,
+ 0x57a0, 0x13c3,
+ 0x57a1, 0x13a2,
+ 0x57a2, 0x0711,
+ 0x57a3, 0x10ee,
+ 0x57a4, 0x13bc,
+ 0x57a5, 0x2c44,
+ 0x57a6, 0x095e,
+ 0x57a7, 0x13c0,
+ 0x57a8, 0x2c45,
+ 0x57a9, 0x13a1,
+ 0x57aa, 0x2c46,
+ 0x57ab, 0x05c7,
+ 0x57ac, 0x2c47,
+ 0x57ad, 0x13bb,
+ 0x57ae, 0x0972,
+ 0x57af, 0x2c48,
+ 0x57b2, 0x13be,
+ 0x57b3, 0x2c4b,
+ 0x57b4, 0x13c1,
+ 0x57b5, 0x2c4c,
+ 0x57b8, 0x13c9,
+ 0x57b9, 0x2c4f,
+ 0x57c2, 0x06fa,
+ 0x57c3, 0x03ae,
+ 0x57c4, 0x2c58,
+ 0x57cb, 0x0a98,
+ 0x57cc, 0x2c5f,
+ 0x57ce, 0x04ec,
+ 0x57cf, 0x13bf,
+ 0x57d0, 0x2c61,
+ 0x57d2, 0x13c8,
+ 0x57d3, 0x2c63,
+ 0x57d4, 0x0bf1,
+ 0x57d5, 0x13c4,
+ 0x57d6, 0x2c64,
+ 0x57d8, 0x13c5,
+ 0x57d9, 0x13c7,
+ 0x57da, 0x13c6,
+ 0x57db, 0x2c66,
+ 0x57dd, 0x13ce,
+ 0x57de, 0x2c68,
+ 0x57df, 0x10d7,
+ 0x57e0, 0x0481,
+ 0x57e1, 0x232a,
+ 0x57e2, 0x2c69,
+ 0x57e4, 0x13cd,
+ 0x57e5, 0x2c6b,
+ 0x57ed, 0x13d2,
+ 0x57ee, 0x2c73,
+ 0x57ef, 0x13cb,
+ 0x57f0, 0x2c74,
+ 0x57f4, 0x13ca,
+ 0x57f5, 0x2c78,
+ 0x57f7, 0x228b,
+ 0x57f8, 0x13cc,
+ 0x57f9, 0x0ba1,
+ 0x57fa, 0x080e,
+ 0x57fb, 0x2c7a,
+ 0x57fd, 0x13d1,
+ 0x57fe, 0x2c7c,
+ 0x5800, 0x13d3,
+ 0x5801, 0x2c7e,
+ 0x5802, 0x0e16,
+ 0x5803, 0x2c7f,
+ 0x5805, 0x1f85,
+ 0x5806, 0x0610,
+ 0x5807, 0x144c,
+ 0x5808, 0x2c81,
+ 0x580a, 0x2325,
+ 0x580b, 0x13cf,
+ 0x580c, 0x2c83,
+ 0x580d, 0x13d0,
+ 0x580e, 0x2c84,
+ 0x5811, 0x0c32,
+ 0x5812, 0x2c87,
+ 0x5815, 0x0628,
+ 0x5816, 0x232c,
+ 0x5817, 0x2c8a,
+ 0x5819, 0x13d5,
+ 0x581a, 0x2c8c,
+ 0x581d, 0x232e,
+ 0x581e, 0x13d4,
+ 0x581f, 0x2c8f,
+ 0x5820, 0x13d7,
+ 0x5821, 0x040d,
+ 0x5822, 0x2c90,
+ 0x5824, 0x05ad,
+ 0x5825, 0x2c92,
+ 0x582a, 0x093d,
+ 0x582b, 0x2c97,
+ 0x582f, 0x2205,
+ 0x5830, 0x1008,
+ 0x5831, 0x1e38,
+ 0x5832, 0x2c9b,
+ 0x5834, 0x1e73,
+ 0x5835, 0x0601,
+ 0x5836, 0x2c9d,
+ 0x5844, 0x13d6,
+ 0x5845, 0x2cab,
+ 0x584a, 0x1fe3,
+ 0x584b, 0x2339,
+ 0x584c, 0x0def,
+ 0x584d, 0x19a3,
+ 0x584e, 0x2cb0,
+ 0x584f, 0x232b,
+ 0x5850, 0x2cb1,
+ 0x5851, 0x0dd1,
+ 0x5852, 0x232d,
+ 0x5853, 0x2cb2,
+ 0x5854, 0x0df3,
+ 0x5855, 0x2cb3,
+ 0x5857, 0x217f,
+ 0x5858, 0x0e14,
+ 0x5859, 0x2cb5,
+ 0x585e, 0x0cd6,
+ 0x585f, 0x2cba,
+ 0x5862, 0x21a7,
+ 0x5863, 0x2cbd,
+ 0x5864, 0x232f,
+ 0x5865, 0x13d8,
+ 0x5866, 0x2cbe,
+ 0x586b, 0x0e41,
+ 0x586c, 0x13d9,
+ 0x586d, 0x2cc3,
+ 0x5875, 0x1e7d,
+ 0x5876, 0x2ccb,
+ 0x5879, 0x20d6,
+ 0x587a, 0x2cce,
+ 0x587e, 0x13a3,
+ 0x587f, 0x2cd2,
+ 0x5880, 0x13dd,
+ 0x5881, 0x13da,
+ 0x5882, 0x2cd3,
+ 0x5883, 0x08e2,
+ 0x5884, 0x2cd4,
+ 0x5885, 0x0d92,
+ 0x5886, 0x2cd5,
+ 0x5889, 0x13db,
+ 0x588a, 0x1ec2,
+ 0x588b, 0x2cd8,
+ 0x5892, 0x0d03,
+ 0x5893, 0x0b1c,
+ 0x5894, 0x2cdf,
+ 0x5899, 0x0c3a,
+ 0x589a, 0x13dc,
+ 0x589b, 0x2ce4,
+ 0x589c, 0x22b2,
+ 0x589d, 0x2ce5,
+ 0x589e, 0x1139,
+ 0x589f, 0x0fb1,
+ 0x58a0, 0x2ce6,
+ 0x58a8, 0x0b0e,
+ 0x58a9, 0x0614,
+ 0x58aa, 0x2cee,
+ 0x58ae, 0x1edf,
+ 0x58af, 0x2cf2,
+ 0x58b3, 0x1ef9,
+ 0x58b4, 0x2cf6,
+ 0x58bb, 0x20d9,
+ 0x58bc, 0x13a4,
+ 0x58bd, 0x2cfd,
+ 0x58be, 0x1fdd,
+ 0x58bf, 0x2cfe,
+ 0x58c1, 0x0443,
+ 0x58c2, 0x2d00,
+ 0x58c5, 0x13a5,
+ 0x58c6, 0x2d03,
+ 0x58c7, 0x2167,
+ 0x58c8, 0x2d04,
+ 0x58d1, 0x13a6,
+ 0x58d2, 0x2d0d,
+ 0x58d3, 0x21ed,
+ 0x58d4, 0x2d0e,
+ 0x58d5, 0x0775,
+ 0x58d6, 0x2d0f,
+ 0x58d8, 0x2007,
+ 0x58d9, 0x2326,
+ 0x58da, 0x2329,
+ 0x58db, 0x2d11,
+ 0x58de, 0x1f52,
+ 0x58df, 0x203b,
+ 0x58e0, 0x2328,
+ 0x58e1, 0x2d14,
+ 0x58e2, 0x2327,
+ 0x58e3, 0x2d15,
+ 0x58e4, 0x0c9b,
+ 0x58e5, 0x2d16,
+ 0x58e9, 0x1e2b,
+ 0x58ea, 0x2d1a,
+ 0x58eb, 0x0d56,
+ 0x58ec, 0x0ca4,
+ 0x58ed, 0x2d1b,
+ 0x58ee, 0x1210,
+ 0x58ef, 0x22ae,
+ 0x58f0, 0x0d32,
+ 0x58f1, 0x2d1c,
+ 0x58f3, 0x0954,
+ 0x58f4, 0x2d1e,
+ 0x58f6, 0x07af,
+ 0x58f7, 0x2d20,
+ 0x58f9, 0x1043,
+ 0x58fa, 0x1f49,
+ 0x58fb, 0x2d22,
+ 0x58fd, 0x2138,
+ 0x58fe, 0x2d24,
+ 0x5900, 0x2d26,
+ 0x5902, 0x161c,
+ 0x5903, 0x2d28,
+ 0x5904, 0x0529,
+ 0x5905, 0x2d29,
+ 0x5907, 0x0421,
+ 0x5908, 0x2d2b,
+ 0x590d, 0x06af,
+ 0x590e, 0x2d30,
+ 0x590f, 0x0f31,
+ 0x5910, 0x2d31,
+ 0x5914, 0x12fb,
+ 0x5915, 0x0f13,
+ 0x5916, 0x0e93,
+ 0x5917, 0x2d35,
+ 0x5919, 0x1301,
+ 0x591a, 0x061f,
+ 0x591b, 0x2d37,
+ 0x591c, 0x1040,
+ 0x591d, 0x2d38,
+ 0x591f, 0x0714,
+ 0x5920, 0x2d3a,
+ 0x5922, 0x2081,
+ 0x5923, 0x2d3c,
+ 0x5924, 0x161b,
+ 0x5925, 0x1619,
+ 0x5926, 0x2d3d,
+ 0x5927, 0x0576,
+ 0x5928, 0x2d3e,
+ 0x5929, 0x0e3f,
+ 0x592a, 0x0dfe,
+ 0x592b, 0x068f,
+ 0x592c, 0x2d3f,
+ 0x592d, 0x1268,
+ 0x592e, 0x1014,
+ 0x592f, 0x0772,
+ 0x5930, 0x2d40,
+ 0x5931, 0x0d3e,
+ 0x5932, 0x2d41,
+ 0x5934, 0x0e68,
+ 0x5935, 0x2d43,
+ 0x5937, 0x104b,
+ 0x5938, 0x0971,
+ 0x5939, 0x0843,
+ 0x593a, 0x0620,
+ 0x593b, 0x2d45,
+ 0x593c, 0x14af,
+ 0x593d, 0x2d46,
+ 0x593e, 0x1f7c,
+ 0x593f, 0x2d47,
+ 0x5941, 0x14b0,
+ 0x5942, 0x138c,
+ 0x5943, 0x2d49,
+ 0x5944, 0x1002,
+ 0x5945, 0x2d4a,
+ 0x5947, 0x0c05,
+ 0x5948, 0x0b31,
+ 0x5949, 0x068b,
+ 0x594a, 0x2d4c,
+ 0x594b, 0x0679,
+ 0x594c, 0x2d4d,
+ 0x594e, 0x0989,
+ 0x594f, 0x123d,
+ 0x5950, 0x2d4f,
+ 0x5951, 0x0c14,
+ 0x5952, 0x2d50,
+ 0x5954, 0x0425,
+ 0x5955, 0x14b2,
+ 0x5956, 0x0882,
+ 0x5957, 0x0e2a,
+ 0x5958, 0x14b4,
+ 0x5959, 0x2d52,
+ 0x595a, 0x14b3,
+ 0x595b, 0x2d53,
+ 0x5960, 0x05cd,
+ 0x5961, 0x2d58,
+ 0x5962, 0x0d16,
+ 0x5963, 0x2d59,
+ 0x5965, 0x03cd,
+ 0x5966, 0x2d5b,
+ 0x5969, 0x235b,
+ 0x596a, 0x1ede,
+ 0x596b, 0x2d5e,
+ 0x596c, 0x1fa2,
+ 0x596d, 0x2d5f,
+ 0x596e, 0x1efa,
+ 0x596f, 0x2d60,
+ 0x5973, 0x0b6f,
+ 0x5974, 0x0b6c,
+ 0x5975, 0x2d64,
+ 0x5976, 0x0b2f,
+ 0x5977, 0x2d65,
+ 0x5978, 0x085c,
+ 0x5979, 0x0df2,
+ 0x597a, 0x2d66,
+ 0x597d, 0x077a,
+ 0x597e, 0x2d69,
+ 0x5981, 0x1775,
+ 0x5982, 0x0cc2,
+ 0x5983, 0x1776,
+ 0x5984, 0x0eae,
+ 0x5985, 0x2d6c,
+ 0x5986, 0x120e,
+ 0x5987, 0x06b9,
+ 0x5988, 0x0a8f,
+ 0x5989, 0x2d6d,
+ 0x598a, 0x0cac,
+ 0x598b, 0x2d6e,
+ 0x598d, 0x1777,
+ 0x598e, 0x2d70,
+ 0x5992, 0x0609,
+ 0x5993, 0x083e,
+ 0x5994, 0x2d74,
+ 0x5996, 0x1026,
+ 0x5997, 0x177b,
+ 0x5998, 0x2d76,
+ 0x5999, 0x0af3,
+ 0x599a, 0x2d77,
+ 0x599d, 0x22ad,
+ 0x599e, 0x177e,
+ 0x599f, 0x2d7a,
+ 0x59a3, 0x177a,
+ 0x59a4, 0x177f,
+ 0x59a5, 0x0e88,
+ 0x59a6, 0x2d7e,
+ 0x59a8, 0x065e,
+ 0x59a9, 0x1778,
+ 0x59ab, 0x177d,
+ 0x59ac, 0x2d80,
+ 0x59ae, 0x0b40,
+ 0x59af, 0x1782,
+ 0x59b0, 0x2d82,
+ 0x59b2, 0x1781,
+ 0x59b3, 0x2d84,
+ 0x59b9, 0x0ac8,
+ 0x59ba, 0x2d8a,
+ 0x59bb, 0x0bfd,
+ 0x59bc, 0x2d8b,
+ 0x59be, 0x1784,
+ 0x59bf, 0x2d8d,
+ 0x59c6, 0x0b1a,
+ 0x59c7, 0x2d94,
+ 0x59ca, 0x177c,
+ 0x59cb, 0x0d53,
+ 0x59cc, 0x2d97,
+ 0x59d0, 0x08b4,
+ 0x59d1, 0x071c,
+ 0x59d2, 0x1780,
+ 0x59d3, 0x0fa0,
+ 0x59d4, 0x0ebe,
+ 0x59d5, 0x2d9b,
+ 0x59d7, 0x1783,
+ 0x59d8, 0x178a,
+ 0x59d9, 0x2d9d,
+ 0x59da, 0x102d,
+ 0x59db, 0x2d9e,
+ 0x59dc, 0x087b,
+ 0x59dd, 0x1787,
+ 0x59de, 0x2d9f,
+ 0x59e3, 0x1789,
+ 0x59e4, 0x2da4,
+ 0x59e5, 0x09bc,
+ 0x59e6, 0x2da5,
+ 0x59e8, 0x1053,
+ 0x59e9, 0x2da7,
+ 0x59ec, 0x081a,
+ 0x59ed, 0x2daa,
+ 0x59f9, 0x178b,
+ 0x59fa, 0x2db6,
+ 0x59fb, 0x107d,
+ 0x59fc, 0x2db7,
+ 0x59ff, 0x1228,
+ 0x5a00, 0x2dba,
+ 0x5a01, 0x0eaf,
+ 0x5a02, 0x2dbb,
+ 0x5a03, 0x0e8f,
+ 0x5a04, 0x0a4d,
+ 0x5a05, 0x1785,
+ 0x5a07, 0x0890,
+ 0x5a08, 0x1788,
+ 0x5a09, 0x178d,
+ 0x5a0a, 0x2dbc,
+ 0x5a0c, 0x178c,
+ 0x5a0d, 0x2dbe,
+ 0x5a11, 0x1790,
+ 0x5a12, 0x2dc2,
+ 0x5a13, 0x1792,
+ 0x5a14, 0x2dc3,
+ 0x5a18, 0x0b52,
+ 0x5a19, 0x2dc7,
+ 0x5a1c, 0x0b2b,
+ 0x5a1d, 0x2dca,
+ 0x5a1f, 0x0919,
+ 0x5a20, 0x0d28,
+ 0x5a21, 0x2dcc,
+ 0x5a23, 0x1791,
+ 0x5a24, 0x2dce,
+ 0x5a25, 0x062f,
+ 0x5a26, 0x2dcf,
+ 0x5a29, 0x0ae9,
+ 0x5a2a, 0x2dd2,
+ 0x5a31, 0x10ce,
+ 0x5a32, 0x178e,
+ 0x5a33, 0x2dd9,
+ 0x5a34, 0x178f,
+ 0x5a35, 0x2dda,
+ 0x5a36, 0x0c7d,
+ 0x5a37, 0x2ddb,
+ 0x5a3c, 0x1797,
+ 0x5a3d, 0x2de0,
+ 0x5a40, 0x1793,
+ 0x5a41, 0x203f,
+ 0x5a42, 0x2de3,
+ 0x5a46, 0x0be4,
+ 0x5a47, 0x2de7,
+ 0x5a49, 0x0ea2,
+ 0x5a4a, 0x1795,
+ 0x5a4b, 0x2de9,
+ 0x5a55, 0x1796,
+ 0x5a56, 0x2df3,
+ 0x5a5a, 0x07fe,
+ 0x5a5b, 0x2df7,
+ 0x5a62, 0x1798,
+ 0x5a63, 0x2dfe,
+ 0x5a66, 0x1f0e,
+ 0x5a67, 0x1794,
+ 0x5a68, 0x2e01,
+ 0x5a6a, 0x09a2,
+ 0x5a6b, 0x2e03,
+ 0x5a6d, 0x23f9,
+ 0x5a6e, 0x2e05,
+ 0x5a74, 0x1089,
+ 0x5a75, 0x1799,
+ 0x5a76, 0x0d2d,
+ 0x5a77, 0x179d,
+ 0x5a78, 0x2e0b,
+ 0x5a7a, 0x179e,
+ 0x5a7b, 0x2e0d,
+ 0x5a7f, 0x0fc1,
+ 0x5a80, 0x2e11,
+ 0x5a92, 0x0ac2,
+ 0x5a93, 0x2e23,
+ 0x5a9a, 0x0ac9,
+ 0x5a9b, 0x179c,
+ 0x5a9c, 0x2e2a,
+ 0x5aa7, 0x23fc,
+ 0x5aa8, 0x2e35,
+ 0x5aaa, 0x179b,
+ 0x5aab, 0x2e37,
+ 0x5ab2, 0x17a1,
+ 0x5ab3, 0x0f1e,
+ 0x5ab4, 0x2e3e,
+ 0x5ab5, 0x19a4,
+ 0x5ab6, 0x2e3f,
+ 0x5ab8, 0x17a4,
+ 0x5ab9, 0x2e41,
+ 0x5abd, 0x2069,
+ 0x5abe, 0x179f,
+ 0x5abf, 0x2e45,
+ 0x5ac1, 0x0851,
+ 0x5ac2, 0x0ce2,
+ 0x5ac3, 0x2e47,
+ 0x5ac9, 0x0828,
+ 0x5aca, 0x2e4d,
+ 0x5acc, 0x0f40,
+ 0x5acd, 0x2e4f,
+ 0x5ad2, 0x17a2,
+ 0x5ad3, 0x2e54,
+ 0x5ad4, 0x17a3,
+ 0x5ad5, 0x2e55,
+ 0x5ad6, 0x17a8,
+ 0x5ad7, 0x23f7,
+ 0x5ad8, 0x17aa,
+ 0x5ad9, 0x2e56,
+ 0x5adc, 0x17ab,
+ 0x5add, 0x2e59,
+ 0x5ae0, 0x17a5,
+ 0x5ae1, 0x05b6,
+ 0x5ae2, 0x2e5c,
+ 0x5ae3, 0x17a6,
+ 0x5ae4, 0x2e5d,
+ 0x5ae6, 0x17a9,
+ 0x5ae7, 0x2e5f,
+ 0x5ae9, 0x0b3e,
+ 0x5aea, 0x2e61,
+ 0x5aeb, 0x17a0,
+ 0x5aec, 0x2e62,
+ 0x5af1, 0x17a7,
+ 0x5af2, 0x2e67,
+ 0x5af5, 0x23f6,
+ 0x5af6, 0x2e6a,
+ 0x5afb, 0x23fd,
+ 0x5afc, 0x2e6f,
+ 0x5b00, 0x23f8,
+ 0x5b01, 0x2e73,
+ 0x5b08, 0x23fa,
+ 0x5b09, 0x17ac,
+ 0x5b0a, 0x2e7a,
+ 0x5b0b, 0x23fe,
+ 0x5b0c, 0x1fa8,
+ 0x5b0d, 0x2e7b,
+ 0x5b16, 0x17ae,
+ 0x5b17, 0x17ad,
+ 0x5b18, 0x2e84,
+ 0x5b19, 0x2401,
+ 0x5b1a, 0x2e85,
+ 0x5b21, 0x23ff,
+ 0x5b22, 0x2e8c,
+ 0x5b2a, 0x2400,
+ 0x5b2b, 0x2e94,
+ 0x5b30, 0x2221,
+ 0x5b31, 0x2e99,
+ 0x5b32, 0x17af,
+ 0x5b33, 0x2e9a,
+ 0x5b34, 0x130c,
+ 0x5b35, 0x2e9b,
+ 0x5b37, 0x17b0,
+ 0x5b38, 0x2122,
+ 0x5b39, 0x2e9d,
+ 0x5b40, 0x17b1,
+ 0x5b41, 0x2ea4,
+ 0x5b4c, 0x23fb,
+ 0x5b4d, 0x2eaf,
+ 0x5b50, 0x1230,
+ 0x5b51, 0x17b7,
+ 0x5b52, 0x2eb2,
+ 0x5b53, 0x17b8,
+ 0x5b54, 0x0964,
+ 0x5b55, 0x1113,
+ 0x5b56, 0x2eb3,
+ 0x5b57, 0x1233,
+ 0x5b58, 0x0569,
+ 0x5b59, 0x0de4,
+ 0x5b5a, 0x17b4,
+ 0x5b5b, 0x1279,
+ 0x5b5c, 0x122b,
+ 0x5b5d, 0x0f6d,
+ 0x5b5e, 0x2eb4,
+ 0x5b5f, 0x0ad4,
+ 0x5b60, 0x2eb5,
+ 0x5b62, 0x17b9,
+ 0x5b63, 0x0831,
+ 0x5b64, 0x071b,
+ 0x5b65, 0x17b5,
+ 0x5b66, 0x0fd0,
+ 0x5b67, 0x2eb7,
+ 0x5b69, 0x0759,
+ 0x5b6a, 0x0a76,
+ 0x5b6b, 0x215a,
+ 0x5b6c, 0x1261,
+ 0x5b6d, 0x2eb9,
+ 0x5b70, 0x0d82,
+ 0x5b71, 0x176a,
+ 0x5b72, 0x2ebc,
+ 0x5b73, 0x17b6,
+ 0x5b74, 0x2ebd,
+ 0x5b75, 0x0692,
+ 0x5b76, 0x2ebe,
+ 0x5b78, 0x21e5,
+ 0x5b79, 0x2ec0,
+ 0x5b7a, 0x0cc1,
+ 0x5b7b, 0x2ec1,
+ 0x5b7d, 0x0b58,
+ 0x5b7e, 0x2ec3,
+ 0x5b7f, 0x2057,
+ 0x5b80, 0x172e,
+ 0x5b81, 0x0b61,
+ 0x5b82, 0x2ec4,
+ 0x5b83, 0x0df1,
+ 0x5b84, 0x172f,
+ 0x5b85, 0x114d,
+ 0x5b86, 0x2ec5,
+ 0x5b87, 0x10d3,
+ 0x5b88, 0x0d6f,
+ 0x5b89, 0x03bd,
+ 0x5b8a, 0x2ec6,
+ 0x5b8b, 0x0dc3,
+ 0x5b8c, 0x0e9b,
+ 0x5b8d, 0x2ec7,
+ 0x5b8f, 0x07a1,
+ 0x5b90, 0x2ec9,
+ 0x5b93, 0x1731,
+ 0x5b94, 0x2ecc,
+ 0x5b95, 0x1730,
+ 0x5b96, 0x2ecd,
+ 0x5b97, 0x1237,
+ 0x5b98, 0x0732,
+ 0x5b99, 0x11e5,
+ 0x5b9a, 0x05e7,
+ 0x5b9b, 0x0ea1,
+ 0x5b9c, 0x1052,
+ 0x5b9d, 0x040f,
+ 0x5b9e, 0x0d4c,
+ 0x5b9f, 0x2ece,
+ 0x5ba0, 0x050d,
+ 0x5ba1, 0x0d2c,
+ 0x5ba2, 0x095a,
+ 0x5ba3, 0x0fc6,
+ 0x5ba4, 0x0d69,
+ 0x5ba5, 0x1732,
+ 0x5ba6, 0x07d7,
+ 0x5ba7, 0x2ecf,
+ 0x5baa, 0x0f49,
+ 0x5bab, 0x0705,
+ 0x5bac, 0x2ed2,
+ 0x5bb0, 0x111a,
+ 0x5bb1, 0x2ed6,
+ 0x5bb3, 0x075d,
+ 0x5bb4, 0x1010,
+ 0x5bb5, 0x0f69,
+ 0x5bb6, 0x0845,
+ 0x5bb7, 0x2ed8,
+ 0x5bb8, 0x1733,
+ 0x5bb9, 0x0cb8,
+ 0x5bba, 0x2ed9,
+ 0x5bbd, 0x097a,
+ 0x5bbe, 0x045f,
+ 0x5bbf, 0x0dd3,
+ 0x5bc0, 0x2edc,
+ 0x5bc2, 0x0838,
+ 0x5bc3, 0x2ede,
+ 0x5bc4, 0x0837,
+ 0x5bc5, 0x1081,
+ 0x5bc6, 0x0ae1,
+ 0x5bc7, 0x0969,
+ 0x5bc8, 0x2edf,
+ 0x5bcc, 0x06b6,
+ 0x5bcd, 0x2ee3,
+ 0x5bd0, 0x0ac7,
+ 0x5bd1, 0x2ee6,
+ 0x5bd2, 0x0765,
+ 0x5bd3, 0x10e5,
+ 0x5bd4, 0x2ee7,
+ 0x5bdd, 0x0c5b,
+ 0x5bde, 0x0b12,
+ 0x5bdf, 0x04b3,
+ 0x5be0, 0x2ef0,
+ 0x5be1, 0x072a,
+ 0x5be2, 0x20e5,
+ 0x5be3, 0x2ef1,
+ 0x5be4, 0x1737,
+ 0x5be5, 0x0a11,
+ 0x5be6, 0x212f,
+ 0x5be7, 0x20a3,
+ 0x5be8, 0x1150,
+ 0x5be9, 0x2121,
+ 0x5bea, 0x2ef2,
+ 0x5beb, 0x21d4,
+ 0x5bec, 0x1fe5,
+ 0x5bed, 0x2ef3,
+ 0x5bee, 0x1738,
+ 0x5bef, 0x2ef4,
+ 0x5bf0, 0x173a,
+ 0x5bf1, 0x2ef5,
+ 0x5bf5, 0x1e8a,
+ 0x5bf6, 0x1e37,
+ 0x5bf7, 0x2ef9,
+ 0x5bf8, 0x056a,
+ 0x5bf9, 0x0613,
+ 0x5bfa, 0x0db7,
+ 0x5bfb, 0x0fd9,
+ 0x5bfc, 0x059d,
+ 0x5bfd, 0x2efa,
+ 0x5bff, 0x0d70,
+ 0x5c00, 0x2efc,
+ 0x5c01, 0x067f,
+ 0x5c02, 0x2efd,
+ 0x5c04, 0x0d1d,
+ 0x5c05, 0x2eff,
+ 0x5c06, 0x087c,
+ 0x5c07, 0x1f9e,
+ 0x5c08, 0x22a6,
+ 0x5c09, 0x0ecd,
+ 0x5c0a, 0x124d,
+ 0x5c0b, 0x21e8,
+ 0x5c0c, 0x2f00,
+ 0x5c0d, 0x1eda,
+ 0x5c0e, 0x1eb9,
+ 0x5c0f, 0x0f6c,
+ 0x5c10, 0x2f01,
+ 0x5c11, 0x0d12,
+ 0x5c12, 0x2f02,
+ 0x5c14, 0x063a,
+ 0x5c15, 0x17b2,
+ 0x5c16, 0x0855,
+ 0x5c17, 0x2f04,
+ 0x5c18, 0x04e3,
+ 0x5c19, 0x2f05,
+ 0x5c1a, 0x0d09,
+ 0x5c1b, 0x2f06,
+ 0x5c1c, 0x17b3,
+ 0x5c1d, 0x04c7,
+ 0x5c1e, 0x2f07,
+ 0x5c22, 0x14b6,
+ 0x5c23, 0x2f0b,
+ 0x5c24, 0x10ad,
+ 0x5c25, 0x14b7,
+ 0x5c26, 0x2f0c,
+ 0x5c27, 0x1029,
+ 0x5c28, 0x2f0d,
+ 0x5c2c, 0x14b8,
+ 0x5c2d, 0x2f11,
+ 0x5c31, 0x08fc,
+ 0x5c32, 0x2f15,
+ 0x5c34, 0x14b9,
+ 0x5c35, 0x2f17,
+ 0x5c37, 0x235c,
+ 0x5c38, 0x0d43,
+ 0x5c39, 0x1083,
+ 0x5c3a, 0x0504,
+ 0x5c3b, 0x1766,
+ 0x5c3c, 0x0b44,
+ 0x5c3d, 0x08d0,
+ 0x5c3e, 0x0ec1,
+ 0x5c3f, 0x0b55,
+ 0x5c40, 0x0905,
+ 0x5c41, 0x0bc7,
+ 0x5c42, 0x04aa,
+ 0x5c43, 0x2f19,
+ 0x5c45, 0x0902,
+ 0x5c46, 0x2f1b,
+ 0x5c48, 0x0c79,
+ 0x5c49, 0x0e3e,
+ 0x5c4a, 0x08bd,
+ 0x5c4b, 0x0eec,
+ 0x5c4c, 0x2f1d,
+ 0x5c4e, 0x0d51,
+ 0x5c4f, 0x0be0,
+ 0x5c50, 0x1768,
+ 0x5c51, 0x0f87,
+ 0x5c52, 0x2f1f,
+ 0x5c55, 0x115a,
+ 0x5c56, 0x2f22,
+ 0x5c59, 0x1769,
+ 0x5c5a, 0x2f25,
+ 0x5c5e, 0x0d8b,
+ 0x5c5f, 0x2f29,
+ 0x5c60, 0x0e71,
+ 0x5c61, 0x0a6c,
+ 0x5c62, 0x2050,
+ 0x5c63, 0x176b,
+ 0x5c64, 0x1e67,
+ 0x5c65, 0x0a6b,
+ 0x5c66, 0x176c,
+ 0x5c67, 0x2f2a,
+ 0x5c68, 0x23f4,
+ 0x5c69, 0x2f2b,
+ 0x5c6c, 0x213e,
+ 0x5c6d, 0x2f2e,
+ 0x5c6e, 0x1774,
+ 0x5c6f, 0x0e7e,
+ 0x5c70, 0x2f2f,
+ 0x5c71, 0x0cf6,
+ 0x5c72, 0x2f30,
+ 0x5c79, 0x1060,
+ 0x5c7a, 0x15ac,
+ 0x5c7b, 0x2f37,
+ 0x5c7f, 0x10d1,
+ 0x5c80, 0x2f3b,
+ 0x5c81, 0x0ddf,
+ 0x5c82, 0x0c10,
+ 0x5c83, 0x2f3c,
+ 0x5c88, 0x15b0,
+ 0x5c89, 0x2f41,
+ 0x5c8c, 0x15ab,
+ 0x5c8d, 0x15ad,
+ 0x5c8e, 0x2f44,
+ 0x5c90, 0x15ae,
+ 0x5c91, 0x15b3,
+ 0x5c92, 0x2f46,
+ 0x5c94, 0x04b4,
+ 0x5c95, 0x2f48,
+ 0x5c96, 0x15af,
+ 0x5c97, 0x06d5,
+ 0x5c98, 0x15b1,
+ 0x5c9a, 0x15b4,
+ 0x5c9b, 0x059b,
+ 0x5c9c, 0x15b5,
+ 0x5c9d, 0x2f49,
+ 0x5ca1, 0x1f16,
+ 0x5ca2, 0x15b7,
+ 0x5ca3, 0x15bc,
+ 0x5ca4, 0x2f4d,
+ 0x5ca9, 0x0ffb,
+ 0x5caa, 0x2f52,
+ 0x5cab, 0x15ba,
+ 0x5cac, 0x15b9,
+ 0x5cad, 0x0a34,
+ 0x5cae, 0x2f53,
+ 0x5cb1, 0x15bb,
+ 0x5cb2, 0x2f56,
+ 0x5cb3, 0x1103,
+ 0x5cb4, 0x2f57,
+ 0x5cb5, 0x15b6,
+ 0x5cb6, 0x2f58,
+ 0x5cb7, 0x15be,
+ 0x5cb8, 0x03c1,
+ 0x5cb9, 0x2f59,
+ 0x5cbd, 0x15b8,
+ 0x5cbe, 0x2f5d,
+ 0x5cbf, 0x0986,
+ 0x5cc0, 0x2f5e,
+ 0x5cc1, 0x15bd,
+ 0x5cc2, 0x2f5f,
+ 0x5cc4, 0x15bf,
+ 0x5cc5, 0x2f61,
+ 0x5ccb, 0x15c2,
+ 0x5ccc, 0x2f67,
+ 0x5cd2, 0x15c0,
+ 0x5cd3, 0x2f6d,
+ 0x5cd9, 0x11c4,
+ 0x5cda, 0x2f73,
+ 0x5ce1, 0x0f2c,
+ 0x5ce2, 0x2f7a,
+ 0x5ce4, 0x15c1,
+ 0x5ce5, 0x15c3,
+ 0x5ce6, 0x0a74,
+ 0x5ce7, 0x2f7c,
+ 0x5ce8, 0x062a,
+ 0x5ce9, 0x2f7d,
+ 0x5cea, 0x10dd,
+ 0x5ceb, 0x2f7e,
+ 0x5ced, 0x0c4a,
+ 0x5cee, 0x2f80,
+ 0x5cf0, 0x0682,
+ 0x5cf1, 0x2f82,
+ 0x5cf4, 0x2389,
+ 0x5cf5, 0x2f85,
+ 0x5cf6, 0x1eb7,
+ 0x5cf7, 0x2f86,
+ 0x5cfb, 0x092d,
+ 0x5cfc, 0x2f8a,
+ 0x5cfd, 0x21b4,
+ 0x5cfe, 0x2f8b,
+ 0x5d00, 0x2f8d,
+ 0x5d02, 0x15c4,
+ 0x5d04, 0x2f8f,
+ 0x5d06, 0x15cb,
+ 0x5d07, 0x050c,
+ 0x5d08, 0x2f91,
+ 0x5d0d, 0x238f,
+ 0x5d0e, 0x0c08,
+ 0x5d0f, 0x2f96,
+ 0x5d14, 0x0561,
+ 0x5d15, 0x2f9b,
+ 0x5d16, 0x0feb,
+ 0x5d17, 0x1f1a,
+ 0x5d18, 0x2f9c,
+ 0x5d1b, 0x15cc,
+ 0x5d1c, 0x2f9f,
+ 0x5d1e, 0x15ca,
+ 0x5d1f, 0x2fa1,
+ 0x5d24, 0x15c9,
+ 0x5d25, 0x2fa6,
+ 0x5d26, 0x15c7,
+ 0x5d27, 0x15c6,
+ 0x5d28, 0x2fa7,
+ 0x5d29, 0x0429,
+ 0x5d2a, 0x2fa8,
+ 0x5d2c, 0x238b,
+ 0x5d2d, 0x1159,
+ 0x5d2e, 0x15c8,
+ 0x5d2f, 0x2faa,
+ 0x5d34, 0x15cf,
+ 0x5d35, 0x2faf,
+ 0x5d3d, 0x15d0,
+ 0x5d3e, 0x15ce,
+ 0x5d3f, 0x2fb7,
+ 0x5d47, 0x1b22,
+ 0x5d48, 0x2fbf,
+ 0x5d4a, 0x15d7,
+ 0x5d4b, 0x15d6,
+ 0x5d4c, 0x0c33,
+ 0x5d4d, 0x2fc1,
+ 0x5d50, 0x238a,
+ 0x5d51, 0x2fc4,
+ 0x5d58, 0x15cd,
+ 0x5d59, 0x2fcb,
+ 0x5d5b, 0x15d2,
+ 0x5d5c, 0x2fcd,
+ 0x5d5d, 0x15d4,
+ 0x5d5e, 0x2fce,
+ 0x5d69, 0x15d8,
+ 0x5d6a, 0x2fd9,
+ 0x5d6b, 0x15d5,
+ 0x5d6c, 0x15d1,
+ 0x5d6d, 0x2fda,
+ 0x5d6f, 0x15d3,
+ 0x5d70, 0x2fdc,
+ 0x5d74, 0x15d9,
+ 0x5d75, 0x2fe0,
+ 0x5d81, 0x2391,
+ 0x5d82, 0x15da,
+ 0x5d83, 0x2fec,
+ 0x5d84, 0x2271,
+ 0x5d85, 0x2fed,
+ 0x5d87, 0x2388,
+ 0x5d88, 0x2fef,
+ 0x5d97, 0x238e,
+ 0x5d98, 0x2ffe,
+ 0x5d99, 0x15db,
+ 0x5d9a, 0x2fff,
+ 0x5d9d, 0x15dc,
+ 0x5d9e, 0x3002,
+ 0x5da0, 0x238d,
+ 0x5da1, 0x3004,
+ 0x5da7, 0x238c,
+ 0x5da8, 0x300a,
+ 0x5db7, 0x15de,
+ 0x5db8, 0x2390,
+ 0x5db9, 0x3019,
+ 0x5dba, 0x2033,
+ 0x5dbb, 0x301a,
+ 0x5dbc, 0x223c,
+ 0x5dbd, 0x301b,
+ 0x5dc5, 0x15df,
+ 0x5dc6, 0x3023,
+ 0x5dcb, 0x1fe9,
+ 0x5dcc, 0x3028,
+ 0x5dcd, 0x0eb0,
+ 0x5dce, 0x3029,
+ 0x5dd2, 0x2055,
+ 0x5dd3, 0x302d,
+ 0x5dd4, 0x2392,
+ 0x5dd5, 0x302e,
+ 0x5ddb, 0x1815,
+ 0x5ddc, 0x3034,
+ 0x5ddd, 0x052b,
+ 0x5dde, 0x11dc,
+ 0x5ddf, 0x3035,
+ 0x5de1, 0x0fdb,
+ 0x5de2, 0x04d7,
+ 0x5de3, 0x3037,
+ 0x5de5, 0x06fd,
+ 0x5de6, 0x1250,
+ 0x5de7, 0x0c46,
+ 0x5de8, 0x090d,
+ 0x5de9, 0x0707,
+ 0x5dea, 0x3039,
+ 0x5deb, 0x0ee6,
+ 0x5dec, 0x303a,
+ 0x5dee, 0x04b5,
+ 0x5def, 0x139f,
+ 0x5df0, 0x2324,
+ 0x5df1, 0x082d,
+ 0x5df2, 0x1058,
+ 0x5df3, 0x0dbd,
+ 0x5df4, 0x03d8,
+ 0x5df5, 0x303c,
+ 0x5df7, 0x0f5c,
+ 0x5df8, 0x303e,
+ 0x5dfd, 0x12f7,
+ 0x5dfe, 0x08be,
+ 0x5dff, 0x3043,
+ 0x5e00, 0x3044,
+ 0x5e01, 0x043b,
+ 0x5e02, 0x0d67,
+ 0x5e03, 0x0483,
+ 0x5e04, 0x3045,
+ 0x5e05, 0x0d9c,
+ 0x5e06, 0x0648,
+ 0x5e07, 0x3046,
+ 0x5e08, 0x0d3d,
+ 0x5e09, 0x3047,
+ 0x5e0c, 0x0f10,
+ 0x5e0d, 0x304a,
+ 0x5e0f, 0x159e,
+ 0x5e10, 0x116b,
+ 0x5e11, 0x15a1,
+ 0x5e12, 0x304c,
+ 0x5e14, 0x15a0,
+ 0x5e15, 0x0b82,
+ 0x5e16, 0x0e4e,
+ 0x5e17, 0x304e,
+ 0x5e18, 0x09fa,
+ 0x5e19, 0x159f,
+ 0x5e1a, 0x11e2,
+ 0x5e1b, 0x0476,
+ 0x5e1c, 0x11c3,
+ 0x5e1d, 0x05bc,
+ 0x5e1e, 0x304f,
+ 0x5e25, 0x2143,
+ 0x5e26, 0x057b,
+ 0x5e27, 0x11a0,
+ 0x5e28, 0x3056,
+ 0x5e2b, 0x2129,
+ 0x5e2c, 0x3059,
+ 0x5e2d, 0x0f1c,
+ 0x5e2e, 0x03fa,
+ 0x5e2f, 0x305a,
+ 0x5e31, 0x15a2,
+ 0x5e32, 0x305c,
+ 0x5e33, 0x2277,
+ 0x5e34, 0x305d,
+ 0x5e36, 0x1ea7,
+ 0x5e37, 0x15a5,
+ 0x5e38, 0x04c8,
+ 0x5e39, 0x305f,
+ 0x5e3b, 0x15a3,
+ 0x5e3d, 0x0ab6,
+ 0x5e3e, 0x3061,
+ 0x5e40, 0x2285,
+ 0x5e41, 0x3063,
+ 0x5e42, 0x0ae2,
+ 0x5e43, 0x2384,
+ 0x5e44, 0x15a6,
+ 0x5e45, 0x0696,
+ 0x5e46, 0x3064,
+ 0x5e4c, 0x07e4,
+ 0x5e4d, 0x306a,
+ 0x5e54, 0x15a7,
+ 0x5e55, 0x0b1e,
+ 0x5e56, 0x3071,
+ 0x5e57, 0x2387,
+ 0x5e58, 0x2386,
+ 0x5e59, 0x3072,
+ 0x5e5b, 0x15a8,
+ 0x5e5c, 0x3074,
+ 0x5e5e, 0x15a9,
+ 0x5e5f, 0x2290,
+ 0x5e60, 0x3076,
+ 0x5e61, 0x15aa,
+ 0x5e62, 0x0534,
+ 0x5e63, 0x1e44,
+ 0x5e64, 0x3077,
+ 0x5e6b, 0x1e32,
+ 0x5e6c, 0x2385,
+ 0x5e6d, 0x307e,
+ 0x5e72, 0x06c4,
+ 0x5e73, 0x0bdc,
+ 0x5e74, 0x0b4d,
+ 0x5e75, 0x3083,
+ 0x5e76, 0x0469,
+ 0x5e77, 0x3084,
+ 0x5e78, 0x0f9d,
+ 0x5e79, 0x1f13,
+ 0x5e7a, 0x1813,
+ 0x5e7b, 0x07d8,
+ 0x5e7c, 0x10bc,
+ 0x5e7d, 0x10a9,
+ 0x5e7e, 0x1f73,
+ 0x5e7f, 0x073c,
+ 0x5e80, 0x1631,
+ 0x5e81, 0x3085,
+ 0x5e84, 0x120c,
+ 0x5e85, 0x3088,
+ 0x5e86, 0x0c69,
+ 0x5e87, 0x043c,
+ 0x5e88, 0x3089,
+ 0x5e8a, 0x0535,
+ 0x5e8b, 0x1633,
+ 0x5e8c, 0x308b,
+ 0x5e8f, 0x0fbd,
+ 0x5e90, 0x0a55,
+ 0x5e91, 0x1632,
+ 0x5e92, 0x308e,
+ 0x5e93, 0x096f,
+ 0x5e94, 0x108b,
+ 0x5e95, 0x05b8,
+ 0x5e96, 0x1634,
+ 0x5e97, 0x05cb,
+ 0x5e98, 0x308f,
+ 0x5e99, 0x0af2,
+ 0x5e9a, 0x06f8,
+ 0x5e9b, 0x3090,
+ 0x5e9c, 0x06a9,
+ 0x5e9d, 0x3091,
+ 0x5e9e, 0x0b94,
+ 0x5e9f, 0x066c,
+ 0x5ea0, 0x1636,
+ 0x5ea1, 0x3092,
+ 0x5ea5, 0x1635,
+ 0x5ea6, 0x0607,
+ 0x5ea7, 0x1256,
+ 0x5ea8, 0x3096,
+ 0x5eab, 0x1fe0,
+ 0x5eac, 0x3099,
+ 0x5ead, 0x0e56,
+ 0x5eae, 0x309a,
+ 0x5eb3, 0x163a,
+ 0x5eb4, 0x309f,
+ 0x5eb5, 0x1638,
+ 0x5eb6, 0x0d93,
+ 0x5eb7, 0x0942,
+ 0x5eb8, 0x109e,
+ 0x5eb9, 0x1637,
+ 0x5eba, 0x30a0,
+ 0x5ebe, 0x1639,
+ 0x5ebf, 0x30a4,
+ 0x5ec9, 0x09f7,
+ 0x5eca, 0x09b3,
+ 0x5ecb, 0x30ae,
+ 0x5ed1, 0x163d,
+ 0x5ed2, 0x163c,
+ 0x5ed3, 0x0995,
+ 0x5ed4, 0x30b4,
+ 0x5ed6, 0x0a17,
+ 0x5ed7, 0x30b6,
+ 0x5edb, 0x163e,
+ 0x5edc, 0x30ba,
+ 0x5edf, 0x2087,
+ 0x5ee0, 0x1e78,
+ 0x5ee1, 0x23ae,
+ 0x5ee2, 0x1ef6,
+ 0x5ee3, 0x1f31,
+ 0x5ee4, 0x30bd,
+ 0x5ee8, 0x163f,
+ 0x5ee9, 0x30c1,
+ 0x5eea, 0x1640,
+ 0x5eeb, 0x30c2,
+ 0x5eec, 0x2045,
+ 0x5eed, 0x30c3,
+ 0x5ef3, 0x2178,
+ 0x5ef4, 0x1398,
+ 0x5ef5, 0x30c9,
+ 0x5ef6, 0x0ffc,
+ 0x5ef7, 0x0e53,
+ 0x5ef8, 0x30ca,
+ 0x5efa, 0x0879,
+ 0x5efb, 0x30cc,
+ 0x5efe, 0x14ad,
+ 0x5eff, 0x125b,
+ 0x5f00, 0x0937,
+ 0x5f01, 0x139d,
+ 0x5f02, 0x1073,
+ 0x5f03, 0x0c19,
+ 0x5f04, 0x0b6b,
+ 0x5f05, 0x30cf,
+ 0x5f08, 0x14ae,
+ 0x5f09, 0x30d2,
+ 0x5f0a, 0x0440,
+ 0x5f0b, 0x14f6,
+ 0x5f0c, 0x30d3,
+ 0x5f0f, 0x0d54,
+ 0x5f10, 0x30d6,
+ 0x5f11, 0x14f9,
+ 0x5f12, 0x30d7,
+ 0x5f13, 0x0706,
+ 0x5f14, 0x30d8,
+ 0x5f15, 0x1084,
+ 0x5f16, 0x30d9,
+ 0x5f17, 0x06a0,
+ 0x5f18, 0x07a2,
+ 0x5f19, 0x30da,
+ 0x5f1b, 0x04ff,
+ 0x5f1c, 0x30dc,
+ 0x5f1f, 0x05bd,
+ 0x5f20, 0x1166,
+ 0x5f21, 0x30df,
+ 0x5f25, 0x0adb,
+ 0x5f26, 0x0f3f,
+ 0x5f27, 0x07b6,
+ 0x5f28, 0x30e3,
+ 0x5f29, 0x176f,
+ 0x5f2a, 0x176e,
+ 0x5f2b, 0x30e4,
+ 0x5f2d, 0x1770,
+ 0x5f2e, 0x30e6,
+ 0x5f2f, 0x0e95,
+ 0x5f30, 0x30e7,
+ 0x5f31, 0x0cd0,
+ 0x5f32, 0x30e8,
+ 0x5f33, 0x23f5,
+ 0x5f34, 0x30e9,
+ 0x5f35, 0x2275,
+ 0x5f36, 0x30ea,
+ 0x5f39, 0x0590,
+ 0x5f3a, 0x0c3c,
+ 0x5f3b, 0x30ed,
+ 0x5f3c, 0x1772,
+ 0x5f3d, 0x30ee,
+ 0x5f40, 0x19be,
+ 0x5f41, 0x30f1,
+ 0x5f46, 0x266e,
+ 0x5f47, 0x30f6,
+ 0x5f48, 0x1eb0,
+ 0x5f49, 0x30f7,
+ 0x5f4c, 0x2083,
+ 0x5f4d, 0x30fa,
+ 0x5f4e, 0x2188,
+ 0x5f4f, 0x30fb,
+ 0x5f50, 0x1762,
+ 0x5f51, 0x30fc,
+ 0x5f52, 0x0742,
+ 0x5f53, 0x0592,
+ 0x5f54, 0x30fd,
+ 0x5f55, 0x0a63,
+ 0x5f56, 0x1764,
+ 0x5f57, 0x1763,
+ 0x5f58, 0x1765,
+ 0x5f59, 0x267c,
+ 0x5f5a, 0x30fe,
+ 0x5f5d, 0x1054,
+ 0x5f5e, 0x3101,
+ 0x5f61, 0x15ee,
+ 0x5f62, 0x0f99,
+ 0x5f63, 0x3104,
+ 0x5f64, 0x0e5f,
+ 0x5f65, 0x3105,
+ 0x5f66, 0x100e,
+ 0x5f67, 0x3106,
+ 0x5f69, 0x0491,
+ 0x5f6a, 0x0454,
+ 0x5f6b, 0x3108,
+ 0x5f6c, 0x045b,
+ 0x5f6d, 0x0bae,
+ 0x5f6e, 0x3109,
+ 0x5f70, 0x1164,
+ 0x5f71, 0x1095,
+ 0x5f72, 0x310b,
+ 0x5f73, 0x15e0,
+ 0x5f74, 0x310c,
+ 0x5f77, 0x15e1,
+ 0x5f78, 0x310f,
+ 0x5f79, 0x1062,
+ 0x5f7a, 0x3110,
+ 0x5f7b, 0x04de,
+ 0x5f7c, 0x0434,
+ 0x5f7d, 0x3111,
+ 0x5f80, 0x0eaa,
+ 0x5f81, 0x1198,
+ 0x5f82, 0x15e2,
+ 0x5f83, 0x3114,
+ 0x5f84, 0x08e5,
+ 0x5f85, 0x0580,
+ 0x5f86, 0x3115,
+ 0x5f87, 0x15e3,
+ 0x5f88, 0x0793,
+ 0x5f89, 0x15e4,
+ 0x5f8a, 0x07c7,
+ 0x5f8b, 0x0a70,
+ 0x5f8c, 0x15e5,
+ 0x5f8d, 0x3116,
+ 0x5f90, 0x0fb7,
+ 0x5f91, 0x1fc5,
+ 0x5f92, 0x0e6e,
+ 0x5f93, 0x3119,
+ 0x5f95, 0x15e6,
+ 0x5f96, 0x311b,
+ 0x5f97, 0x05a4,
+ 0x5f98, 0x0b88,
+ 0x5f99, 0x15e7,
+ 0x5f9a, 0x311c,
+ 0x5f9c, 0x15e8,
+ 0x5f9d, 0x311e,
+ 0x5f9e, 0x1ea1,
+ 0x5f9f, 0x311f,
+ 0x5fa0, 0x2393,
+ 0x5fa1, 0x10de,
+ 0x5fa2, 0x3120,
+ 0x5fa8, 0x15e9,
+ 0x5fa9, 0x1f0b,
+ 0x5faa, 0x0fd6,
+ 0x5fab, 0x3126,
+ 0x5fad, 0x15ea,
+ 0x5fae, 0x0eb1,
+ 0x5faf, 0x3128,
+ 0x5fb5, 0x15eb,
+ 0x5fb6, 0x312e,
+ 0x5fb7, 0x05a3,
+ 0x5fb8, 0x312f,
+ 0x5fb9, 0x1e7c,
+ 0x5fba, 0x3130,
+ 0x5fbc, 0x15ec,
+ 0x5fbd, 0x07ea,
+ 0x5fbe, 0x3132,
+ 0x5fc3, 0x0f8f,
+ 0x5fc4, 0x1642,
+ 0x5fc5, 0x0441,
+ 0x5fc6, 0x106b,
+ 0x5fc7, 0x3137,
+ 0x5fc9, 0x1643,
+ 0x5fca, 0x3139,
+ 0x5fcc, 0x083c,
+ 0x5fcd, 0x0ca7,
+ 0x5fce, 0x313b,
+ 0x5fcf, 0x1645,
+ 0x5fd0, 0x1a0c,
+ 0x5fd1, 0x1a0b,
+ 0x5fd2, 0x14f7,
+ 0x5fd3, 0x313c,
+ 0x5fd6, 0x1644,
+ 0x5fd7, 0x11bd,
+ 0x5fd8, 0x0ead,
+ 0x5fd9, 0x0aab,
+ 0x5fda, 0x313f,
+ 0x5fdd, 0x1683,
+ 0x5fde, 0x3142,
+ 0x5fe0, 0x11d1,
+ 0x5fe1, 0x1649,
+ 0x5fe2, 0x3144,
+ 0x5fe4, 0x164a,
+ 0x5fe5, 0x3146,
+ 0x5fe7, 0x10ac,
+ 0x5fe8, 0x3148,
+ 0x5fea, 0x164e,
+ 0x5feb, 0x0979,
+ 0x5fec, 0x314a,
+ 0x5fed, 0x164f,
+ 0x5fee, 0x1647,
+ 0x5fef, 0x314b,
+ 0x5ff1, 0x04e5,
+ 0x5ff2, 0x314d,
+ 0x5ff5, 0x0b51,
+ 0x5ff6, 0x3150,
+ 0x5ff8, 0x1650,
+ 0x5ff9, 0x3152,
+ 0x5ffb, 0x0f8e,
+ 0x5ffc, 0x3154,
+ 0x5ffd, 0x07ad,
+ 0x5ffe, 0x164b,
+ 0x5fff, 0x067b,
+ 0x6000, 0x07c8,
+ 0x6001, 0x0dff,
+ 0x6002, 0x0dc0,
+ 0x6003, 0x1646,
+ 0x6004, 0x1648,
+ 0x6005, 0x164c,
+ 0x6007, 0x3155,
+ 0x600a, 0x1659,
+ 0x600b, 0x3158,
+ 0x600d, 0x1656,
+ 0x600e, 0x1138,
+ 0x600f, 0x1655,
+ 0x6010, 0x315a,
+ 0x6012, 0x0b6e,
+ 0x6013, 0x315c,
+ 0x6014, 0x119b,
+ 0x6015, 0x0b83,
+ 0x6016, 0x0487,
+ 0x6017, 0x315d,
+ 0x6019, 0x1651,
+ 0x601a, 0x315f,
+ 0x601b, 0x1654,
+ 0x601c, 0x09f8,
+ 0x601d, 0x0db1,
+ 0x601e, 0x3160,
+ 0x6020, 0x0582,
+ 0x6021, 0x165b,
+ 0x6022, 0x3162,
+ 0x6025, 0x0824,
+ 0x6026, 0x1653,
+ 0x6027, 0x0f9f,
+ 0x6028, 0x10fc,
+ 0x6029, 0x1657,
+ 0x602a, 0x072f,
+ 0x602b, 0x1658,
+ 0x602c, 0x3165,
+ 0x602f, 0x0c50,
+ 0x6030, 0x3168,
+ 0x6035, 0x1652,
+ 0x6036, 0x316d,
+ 0x603b, 0x1239,
+ 0x603c, 0x1a0d,
+ 0x603d, 0x3172,
+ 0x603f, 0x165a,
+ 0x6040, 0x3174,
+ 0x6041, 0x1a11,
+ 0x6042, 0x1660,
+ 0x6043, 0x0d68,
+ 0x6044, 0x3175,
+ 0x604b, 0x09fe,
+ 0x604c, 0x317c,
+ 0x604d, 0x07e5,
+ 0x604e, 0x317d,
+ 0x6050, 0x0963,
+ 0x6051, 0x317f,
+ 0x6052, 0x079a,
+ 0x6053, 0x3180,
+ 0x6055, 0x0d96,
+ 0x6056, 0x3182,
+ 0x6059, 0x1a12,
+ 0x605a, 0x1a0f,
+ 0x605b, 0x3185,
+ 0x605d, 0x1a0e,
+ 0x605e, 0x3187,
+ 0x6062, 0x07eb,
+ 0x6063, 0x1a13,
+ 0x6064, 0x0fbf,
+ 0x6065, 0x318b,
+ 0x6067, 0x1a10,
+ 0x6068, 0x0795,
+ 0x6069, 0x0636,
+ 0x606a, 0x1661,
+ 0x606b, 0x05f1,
+ 0x606c, 0x0e44,
+ 0x606d, 0x0700,
+ 0x606e, 0x318d,
+ 0x606f, 0x0f0f,
+ 0x6070, 0x0c1e,
+ 0x6071, 0x318e,
+ 0x6073, 0x095f,
+ 0x6074, 0x3190,
+ 0x6076, 0x0630,
+ 0x6077, 0x3192,
+ 0x6078, 0x165c,
+ 0x607a, 0x165f,
+ 0x607b, 0x165e,
+ 0x607c, 0x0b38,
+ 0x607d, 0x1662,
+ 0x607e, 0x3193,
+ 0x607f, 0x10a6,
+ 0x6080, 0x3194,
+ 0x6083, 0x1667,
+ 0x6084, 0x0c41,
+ 0x6085, 0x3197,
+ 0x6089, 0x0f11,
+ 0x608a, 0x319b,
+ 0x608c, 0x1669,
+ 0x608d, 0x076e,
+ 0x608e, 0x319d,
+ 0x6092, 0x1668,
+ 0x6093, 0x31a1,
+ 0x6094, 0x07ef,
+ 0x6095, 0x31a2,
+ 0x6096, 0x1663,
+ 0x6097, 0x31a3,
+ 0x609a, 0x1664,
+ 0x609b, 0x166a,
+ 0x609c, 0x31a6,
+ 0x609d, 0x1666,
+ 0x609e, 0x31a7,
+ 0x609f, 0x0f01,
+ 0x60a0, 0x10ab,
+ 0x60a1, 0x31a8,
+ 0x60a3, 0x07d1,
+ 0x60a4, 0x31aa,
+ 0x60a6, 0x1106,
+ 0x60a7, 0x31ac,
+ 0x60a8, 0x0b5d,
+ 0x60a9, 0x31ad,
+ 0x60ab, 0x1a14,
+ 0x60ac, 0x0fc7,
+ 0x60ad, 0x1665,
+ 0x60ae, 0x31af,
+ 0x60af, 0x0afa,
+ 0x60b0, 0x31b0,
+ 0x60b1, 0x166d,
+ 0x60b2, 0x0418,
+ 0x60b3, 0x31b1,
+ 0x60b4, 0x1672,
+ 0x60b5, 0x23b4,
+ 0x60b6, 0x207e,
+ 0x60b7, 0x31b2,
+ 0x60b8, 0x0835,
+ 0x60b9, 0x31b3,
+ 0x60bb, 0x166c,
+ 0x60bc, 0x05a0,
+ 0x60bd, 0x31b5,
+ 0x60c5, 0x0c66,
+ 0x60c6, 0x1670,
+ 0x60c7, 0x31bd,
+ 0x60ca, 0x08d9,
+ 0x60cb, 0x0ea0,
+ 0x60cc, 0x31c0,
+ 0x60d1, 0x0808,
+ 0x60d2, 0x31c5,
+ 0x60d5, 0x0e3b,
+ 0x60d6, 0x31c8,
+ 0x60d8, 0x166f,
+ 0x60d9, 0x31ca,
+ 0x60da, 0x1671,
+ 0x60db, 0x31cb,
+ 0x60dc, 0x0f14,
+ 0x60dd, 0x166e,
+ 0x60de, 0x31cc,
+ 0x60df, 0x0eb8,
+ 0x60e0, 0x07f2,
+ 0x60e1, 0x1ee3,
+ 0x60e2, 0x31cd,
+ 0x60e6, 0x05cc,
+ 0x60e7, 0x0914,
+ 0x60e8, 0x0499,
+ 0x60e9, 0x04f2,
+ 0x60ea, 0x31d1,
+ 0x60eb, 0x0422,
+ 0x60ec, 0x166b,
+ 0x60ed, 0x0498,
+ 0x60ee, 0x058d,
+ 0x60ef, 0x0738,
+ 0x60f0, 0x0627,
+ 0x60f1, 0x2095,
+ 0x60f2, 0x23bb,
+ 0x60f3, 0x0f58,
+ 0x60f4, 0x1677,
+ 0x60f5, 0x31d2,
+ 0x60f6, 0x07e1,
+ 0x60f7, 0x31d3,
+ 0x60f9, 0x0ca2,
+ 0x60fa, 0x0f95,
+ 0x60fb, 0x23b9,
+ 0x60fc, 0x31d5,
+ 0x6100, 0x1678,
+ 0x6101, 0x0513,
+ 0x6102, 0x31d9,
+ 0x6106, 0x1a15,
+ 0x6107, 0x31dd,
+ 0x6108, 0x10df,
+ 0x6109, 0x10c9,
+ 0x610a, 0x31de,
+ 0x610d, 0x1a16,
+ 0x610e, 0x1679,
+ 0x610f, 0x1069,
+ 0x6110, 0x31e1,
+ 0x6115, 0x1675,
+ 0x6116, 0x31e6,
+ 0x611a, 0x10c3,
+ 0x611b, 0x1e28,
+ 0x611c, 0x23bd,
+ 0x611d, 0x31ea,
+ 0x611f, 0x06cb,
+ 0x6120, 0x1673,
+ 0x6121, 0x31ec,
+ 0x6123, 0x1676,
+ 0x6124, 0x067c,
+ 0x6125, 0x31ee,
+ 0x6126, 0x1674,
+ 0x6127, 0x098d,
+ 0x6128, 0x31ef,
+ 0x612b, 0x167a,
+ 0x612c, 0x31f2,
+ 0x6134, 0x23b5,
+ 0x6135, 0x31fa,
+ 0x6137, 0x23ba,
+ 0x6138, 0x31fc,
+ 0x613e, 0x23b3,
+ 0x613f, 0x10fb,
+ 0x6140, 0x3202,
+ 0x6148, 0x054b,
+ 0x6149, 0x320a,
+ 0x614a, 0x167b,
+ 0x614b, 0x2162,
+ 0x614c, 0x07da,
+ 0x614d, 0x320b,
+ 0x614e, 0x0d30,
+ 0x614f, 0x320c,
+ 0x6151, 0x0d1e,
+ 0x6152, 0x320e,
+ 0x6155, 0x0b20,
+ 0x6156, 0x3211,
+ 0x6158, 0x1e5e,
+ 0x6159, 0x3213,
+ 0x615a, 0x1e5d,
+ 0x615b, 0x3214,
+ 0x615d, 0x1a17,
+ 0x615e, 0x3216,
+ 0x615f, 0x23b7,
+ 0x6160, 0x3217,
+ 0x6162, 0x0aa4,
+ 0x6163, 0x1f2f,
+ 0x6164, 0x24df,
+ 0x6165, 0x3219,
+ 0x6167, 0x07f0,
+ 0x6168, 0x093b,
+ 0x6169, 0x321b,
+ 0x616a, 0x23b2,
+ 0x616b, 0x214e,
+ 0x616c, 0x321c,
+ 0x616e, 0x2052,
+ 0x616f, 0x321e,
+ 0x6170, 0x0ece,
+ 0x6171, 0x321f,
+ 0x6173, 0x23bc,
+ 0x6174, 0x3221,
+ 0x6175, 0x167c,
+ 0x6176, 0x20eb,
+ 0x6177, 0x0943,
+ 0x6178, 0x3222,
+ 0x6182, 0x2232,
+ 0x6183, 0x322c,
+ 0x618a, 0x1e3f,
+ 0x618b, 0x0458,
+ 0x618c, 0x3233,
+ 0x618e, 0x113a,
+ 0x618f, 0x3235,
+ 0x6190, 0x201b,
+ 0x6191, 0x20bc,
+ 0x6192, 0x23be,
+ 0x6193, 0x3236,
+ 0x6194, 0x167e,
+ 0x6195, 0x3237,
+ 0x619a, 0x1eae,
+ 0x619b, 0x323c,
+ 0x619d, 0x1a19,
+ 0x619e, 0x323e,
+ 0x61a4, 0x1efb,
+ 0x61a5, 0x3244,
+ 0x61a7, 0x167f,
+ 0x61a8, 0x0760,
+ 0x61a9, 0x1a18,
+ 0x61aa, 0x3246,
+ 0x61ab, 0x2089,
+ 0x61ac, 0x167d,
+ 0x61ad, 0x3247,
+ 0x61ae, 0x23b1,
+ 0x61af, 0x3248,
+ 0x61b2, 0x21c4,
+ 0x61b3, 0x324b,
+ 0x61b6, 0x2214,
+ 0x61b7, 0x1680,
+ 0x61b8, 0x324e,
+ 0x61be, 0x076d,
+ 0x61bf, 0x3254,
+ 0x61c2, 0x05ed,
+ 0x61c3, 0x3257,
+ 0x61c7, 0x1fde,
+ 0x61c8, 0x0f83,
+ 0x61c9, 0x2223,
+ 0x61ca, 0x03ce,
+ 0x61cb, 0x1a1a,
+ 0x61cc, 0x23b6,
+ 0x61cd, 0x325b,
+ 0x61d1, 0x1a1b,
+ 0x61d2, 0x09ac,
+ 0x61d3, 0x325f,
+ 0x61d4, 0x1681,
+ 0x61d5, 0x3260,
+ 0x61de, 0x268c,
+ 0x61df, 0x24de,
+ 0x61e0, 0x3269,
+ 0x61e3, 0x24e0,
+ 0x61e4, 0x326c,
+ 0x61e6, 0x0b74,
+ 0x61e7, 0x326e,
+ 0x61e8, 0x23b8,
+ 0x61e9, 0x326f,
+ 0x61f2, 0x1e81,
+ 0x61f3, 0x3278,
+ 0x61f5, 0x1682,
+ 0x61f6, 0x1ffe,
+ 0x61f7, 0x1f51,
+ 0x61f8, 0x21e1,
+ 0x61f9, 0x327a,
+ 0x61fa, 0x23b0,
+ 0x61fb, 0x327b,
+ 0x61fc, 0x1fce,
+ 0x61fd, 0x327c,
+ 0x61fe, 0x211e,
+ 0x61ff, 0x13e0,
+ 0x6200, 0x2021,
+ 0x6201, 0x327d,
+ 0x6206, 0x1a1c,
+ 0x6207, 0x24e1,
+ 0x6208, 0x06e5,
+ 0x6209, 0x3282,
+ 0x620a, 0x0efb,
+ 0x620b, 0x18f9,
+ 0x620c, 0x0fb2,
+ 0x620d, 0x0d90,
+ 0x620e, 0x0cb1,
+ 0x620f, 0x0f24,
+ 0x6210, 0x04ee,
+ 0x6211, 0x0ee1,
+ 0x6212, 0x08b5,
+ 0x6213, 0x3283,
+ 0x6214, 0x24a3,
+ 0x6215, 0x169e,
+ 0x6216, 0x0807,
+ 0x6217, 0x18fa,
+ 0x6218, 0x115e,
+ 0x6219, 0x3284,
+ 0x621a, 0x0bfc,
+ 0x621b, 0x18fb,
+ 0x621c, 0x3285,
+ 0x621f, 0x18fc,
+ 0x6220, 0x3288,
+ 0x6221, 0x18fe,
+ 0x6222, 0x18fd,
+ 0x6223, 0x3289,
+ 0x6224, 0x1900,
+ 0x6225, 0x18ff,
+ 0x6226, 0x328a,
+ 0x6227, 0x24a4,
+ 0x6228, 0x328b,
+ 0x622a, 0x08a9,
+ 0x622b, 0x328d,
+ 0x622c, 0x1901,
+ 0x622d, 0x328e,
+ 0x622e, 0x0a65,
+ 0x622f, 0x328f,
+ 0x6230, 0x2273,
+ 0x6231, 0x3290,
+ 0x6232, 0x21b0,
+ 0x6233, 0x0544,
+ 0x6234, 0x057a,
+ 0x6235, 0x3291,
+ 0x6237, 0x07bc,
+ 0x6238, 0x3293,
+ 0x623d, 0x19f4,
+ 0x623e, 0x19f3,
+ 0x623f, 0x065c,
+ 0x6240, 0x0dee,
+ 0x6241, 0x044b,
+ 0x6242, 0x3298,
+ 0x6243, 0x19f5,
+ 0x6244, 0x3299,
+ 0x6247, 0x0d01,
+ 0x6248, 0x19f6,
+ 0x624a, 0x329c,
+ 0x624b, 0x0d6d,
+ 0x624c, 0x14ba,
+ 0x624d, 0x048c,
+ 0x624e, 0x113d,
+ 0x624f, 0x329d,
+ 0x6251, 0x0bea,
+ 0x6252, 0x03d2,
+ 0x6253, 0x0575,
+ 0x6254, 0x0cae,
+ 0x6255, 0x329f,
+ 0x6258, 0x0e81,
+ 0x6259, 0x32a2,
+ 0x625b, 0x0945,
+ 0x625c, 0x32a4,
+ 0x6263, 0x0968,
+ 0x6264, 0x32ab,
+ 0x6266, 0x0c21,
+ 0x6267, 0x11b3,
+ 0x6268, 0x32ad,
+ 0x6269, 0x0994,
+ 0x626a, 0x14bb,
+ 0x626b, 0x0ce1,
+ 0x626c, 0x1018,
+ 0x626d, 0x0b65,
+ 0x626e, 0x03f2,
+ 0x626f, 0x04db,
+ 0x6270, 0x0ca0,
+ 0x6271, 0x32ae,
+ 0x6273, 0x03ed,
+ 0x6274, 0x32b0,
+ 0x6276, 0x0693,
+ 0x6277, 0x32b2,
+ 0x6279, 0x0bbb,
+ 0x627a, 0x32b4,
+ 0x627c, 0x0632,
+ 0x627d, 0x32b6,
+ 0x627e, 0x1173,
+ 0x627f, 0x04f5,
+ 0x6280, 0x082f,
+ 0x6281, 0x32b7,
+ 0x6284, 0x04d2,
+ 0x6285, 0x32ba,
+ 0x6289, 0x0920,
+ 0x628a, 0x03dc,
+ 0x628b, 0x32be,
+ 0x6291, 0x105d,
+ 0x6292, 0x0d7a,
+ 0x6293, 0x1202,
+ 0x6294, 0x32c4,
+ 0x6295, 0x0e67,
+ 0x6296, 0x05f5,
+ 0x6297, 0x0946,
+ 0x6298, 0x117c,
+ 0x6299, 0x32c5,
+ 0x629a, 0x06a2,
+ 0x629b, 0x0b98,
+ 0x629c, 0x32c6,
+ 0x629f, 0x14bc,
+ 0x62a0, 0x0966,
+ 0x62a1, 0x0a7c,
+ 0x62a2, 0x0c3d,
+ 0x62a3, 0x32c9,
+ 0x62a4, 0x07b9,
+ 0x62a5, 0x0411,
+ 0x62a6, 0x32ca,
+ 0x62a8, 0x0bab,
+ 0x62a9, 0x32cc,
+ 0x62ab, 0x0bbc,
+ 0x62ac, 0x0dfa,
+ 0x62ad, 0x32ce,
+ 0x62b1, 0x0410,
+ 0x62b2, 0x32d2,
+ 0x62b5, 0x05b7,
+ 0x62b6, 0x32d5,
+ 0x62b9, 0x0b0b,
+ 0x62ba, 0x32d8,
+ 0x62bb, 0x14bd,
+ 0x62bc, 0x0fe3,
+ 0x62bd, 0x050e,
+ 0x62be, 0x32d9,
+ 0x62bf, 0x0af7,
+ 0x62c0, 0x32da,
+ 0x62c2, 0x0694,
+ 0x62c3, 0x32dc,
+ 0x62c4, 0x11f3,
+ 0x62c5, 0x0584,
+ 0x62c6, 0x04b7,
+ 0x62c7, 0x0b17,
+ 0x62c8, 0x0b4c,
+ 0x62c9, 0x0998,
+ 0x62ca, 0x14be,
+ 0x62cb, 0x32dd,
+ 0x62cc, 0x03f3,
+ 0x62cd, 0x0b85,
+ 0x62ce, 0x0a29,
+ 0x62cf, 0x32de,
+ 0x62d0, 0x072e,
+ 0x62d1, 0x32df,
+ 0x62d2, 0x090b,
+ 0x62d3, 0x0e89,
+ 0x62d4, 0x03d9,
+ 0x62d5, 0x32e0,
+ 0x62d6, 0x0e80,
+ 0x62d7, 0x14c0,
+ 0x62d8, 0x08ff,
+ 0x62d9, 0x121b,
+ 0x62da, 0x14bf,
+ 0x62db, 0x1171,
+ 0x62dc, 0x03e8,
+ 0x62dd, 0x32e1,
+ 0x62df, 0x0b45,
+ 0x62e0, 0x32e3,
+ 0x62e2, 0x0a4a,
+ 0x62e3, 0x0863,
+ 0x62e4, 0x32e5,
+ 0x62e5, 0x109a,
+ 0x62e6, 0x09a4,
+ 0x62e7, 0x0b62,
+ 0x62e8, 0x046d,
+ 0x62e9, 0x1134,
+ 0x62ea, 0x32e6,
+ 0x62ec, 0x0993,
+ 0x62ed, 0x0d5a,
+ 0x62ee, 0x14c1,
+ 0x62ef, 0x119d,
+ 0x62f0, 0x32e8,
+ 0x62f1, 0x0709,
+ 0x62f2, 0x32e9,
+ 0x62f3, 0x0c88,
+ 0x62f4, 0x0d9e,
+ 0x62f5, 0x32ea,
+ 0x62f6, 0x14c3,
+ 0x62f7, 0x094a,
+ 0x62f8, 0x32eb,
+ 0x62fc, 0x0bd3,
+ 0x62fd, 0x1204,
+ 0x62fe, 0x0d47,
+ 0x62ff, 0x0b26,
+ 0x6300, 0x32ef,
+ 0x6301, 0x04fb,
+ 0x6302, 0x072b,
+ 0x6303, 0x32f0,
+ 0x6307, 0x11b7,
+ 0x6308, 0x194e,
+ 0x6309, 0x03bf,
+ 0x630a, 0x32f4,
+ 0x630e, 0x0973,
+ 0x630f, 0x32f8,
+ 0x6311, 0x0e47,
+ 0x6312, 0x32fa,
+ 0x6316, 0x0e8b,
+ 0x6317, 0x32fe,
+ 0x631a, 0x11be,
+ 0x631b, 0x0a75,
+ 0x631c, 0x3301,
+ 0x631d, 0x0edd,
+ 0x631e, 0x0df5,
+ 0x631f, 0x0f79,
+ 0x6320, 0x0b36,
+ 0x6321, 0x0593,
+ 0x6322, 0x14c2,
+ 0x6323, 0x1196,
+ 0x6324, 0x082a,
+ 0x6325, 0x07e8,
+ 0x6326, 0x3302,
+ 0x6328, 0x03af,
+ 0x6329, 0x3304,
+ 0x632a, 0x0b73,
+ 0x632b, 0x056f,
+ 0x632c, 0x3305,
+ 0x632f, 0x1192,
+ 0x6330, 0x3308,
+ 0x6332, 0x194f,
+ 0x6333, 0x330a,
+ 0x6339, 0x14c4,
+ 0x633a, 0x0e57,
+ 0x633b, 0x3310,
+ 0x633d, 0x0e9d,
+ 0x633e, 0x21d1,
+ 0x633f, 0x3312,
+ 0x6342, 0x0ef5,
+ 0x6343, 0x14c6,
+ 0x6344, 0x3315,
+ 0x6345, 0x0e62,
+ 0x6346, 0x0991,
+ 0x6347, 0x3316,
+ 0x6349, 0x121a,
+ 0x634a, 0x3318,
+ 0x634b, 0x14c5,
+ 0x634c, 0x03d1,
+ 0x634d, 0x076b,
+ 0x634e, 0x0d0c,
+ 0x634f, 0x0b56,
+ 0x6350, 0x0917,
+ 0x6351, 0x3319,
+ 0x6355, 0x047d,
+ 0x6356, 0x331d,
+ 0x635e, 0x09b7,
+ 0x635f, 0x0de5,
+ 0x6360, 0x3325,
+ 0x6361, 0x0864,
+ 0x6362, 0x07d0,
+ 0x6363, 0x0598,
+ 0x6364, 0x3326,
+ 0x6367, 0x0bb6,
+ 0x6368, 0x211c,
+ 0x6369, 0x14d0,
+ 0x636a, 0x3329,
+ 0x636b, 0x235d,
+ 0x636c, 0x332a,
+ 0x636d, 0x14cd,
+ 0x636e, 0x090c,
+ 0x636f, 0x332b,
+ 0x6371, 0x14c9,
+ 0x6372, 0x2682,
+ 0x6373, 0x332d,
+ 0x6376, 0x053a,
+ 0x6377, 0x08ae,
+ 0x6378, 0x3330,
+ 0x637a, 0x14ca,
+ 0x637b, 0x0b50,
+ 0x637c, 0x3332,
+ 0x6380, 0x0f33,
+ 0x6381, 0x3336,
+ 0x6382, 0x05c1,
+ 0x6383, 0x210d,
+ 0x6384, 0x205a,
+ 0x6385, 0x3337,
+ 0x6387, 0x061d,
+ 0x6388, 0x0d71,
+ 0x6389, 0x05d5,
+ 0x638a, 0x14cf,
+ 0x638b, 0x3339,
+ 0x638c, 0x1167,
+ 0x638d, 0x333a,
+ 0x638e, 0x14cb,
+ 0x638f, 0x0e20,
+ 0x6390, 0x0c1d,
+ 0x6391, 0x333b,
+ 0x6392, 0x0b86,
+ 0x6393, 0x333c,
+ 0x6396, 0x103b,
+ 0x6397, 0x333f,
+ 0x6398, 0x0921,
+ 0x6399, 0x3340,
+ 0x63a0, 0x0a7a,
+ 0x63a1, 0x3347,
+ 0x63a2, 0x0e10,
+ 0x63a3, 0x04dd,
+ 0x63a4, 0x3348,
+ 0x63a5, 0x08a4,
+ 0x63a6, 0x3349,
+ 0x63a7, 0x0965,
+ 0x63a8, 0x0e77,
+ 0x63a9, 0x1003,
+ 0x63aa, 0x056e,
+ 0x63ab, 0x334a,
+ 0x63ac, 0x14ce,
+ 0x63ad, 0x14c7,
+ 0x63ae, 0x14d1,
+ 0x63af, 0x334b,
+ 0x63b0, 0x1950,
+ 0x63b1, 0x334c,
+ 0x63b3, 0x0a57,
+ 0x63b4, 0x14cc,
+ 0x63b5, 0x334e,
+ 0x63b7, 0x11bf,
+ 0x63b8, 0x0588,
+ 0x63b9, 0x3350,
+ 0x63ba, 0x04bb,
+ 0x63bb, 0x3351,
+ 0x63bc, 0x14d2,
+ 0x63bd, 0x3352,
+ 0x63be, 0x14dc,
+ 0x63bf, 0x3353,
+ 0x63c0, 0x1f8d,
+ 0x63c1, 0x3354,
+ 0x63c4, 0x14d7,
+ 0x63c5, 0x3357,
+ 0x63c6, 0x14db,
+ 0x63c7, 0x3358,
+ 0x63c9, 0x0cbb,
+ 0x63ca, 0x335a,
+ 0x63cd, 0x123e,
+ 0x63ce, 0x14d9,
+ 0x63cf, 0x0aed,
+ 0x63d0, 0x0e34,
+ 0x63d1, 0x335d,
+ 0x63d2, 0x04ac,
+ 0x63d3, 0x335e,
+ 0x63d6, 0x1045,
+ 0x63d7, 0x3361,
+ 0x63da, 0x21ff,
+ 0x63db, 0x3364,
+ 0x63de, 0x14d8,
+ 0x63df, 0x3367,
+ 0x63e0, 0x14d5,
+ 0x63e1, 0x0ee4,
+ 0x63e2, 0x3368,
+ 0x63e3, 0x052a,
+ 0x63e4, 0x3369,
+ 0x63e9, 0x0938,
+ 0x63ea, 0x08ed,
+ 0x63eb, 0x336e,
+ 0x63ed, 0x08a3,
+ 0x63ee, 0x1f58,
+ 0x63ef, 0x3370,
+ 0x63f2, 0x14d3,
+ 0x63f3, 0x3373,
+ 0x63f4, 0x10f1,
+ 0x63f5, 0x3374,
+ 0x63f6, 0x14c8,
+ 0x63f7, 0x3375,
+ 0x63f8, 0x14d4,
+ 0x63f9, 0x3376,
+ 0x63fd, 0x09aa,
+ 0x63fe, 0x337a,
+ 0x63ff, 0x14d6,
+ 0x6400, 0x04ba,
+ 0x6401, 0x06e4,
+ 0x6402, 0x0a4e,
+ 0x6403, 0x337b,
+ 0x6405, 0x0892,
+ 0x6406, 0x337d,
+ 0x640b, 0x14df,
+ 0x640c, 0x14e2,
+ 0x640d, 0x215b,
+ 0x640e, 0x3382,
+ 0x640f, 0x0472,
+ 0x6410, 0x0527,
+ 0x6411, 0x3383,
+ 0x6413, 0x056d,
+ 0x6414, 0x0cdf,
+ 0x6415, 0x3385,
+ 0x6417, 0x1eb6,
+ 0x6418, 0x3387,
+ 0x641b, 0x14e0,
+ 0x641c, 0x0dc6,
+ 0x641d, 0x338a,
+ 0x641e, 0x06de,
+ 0x641f, 0x338b,
+ 0x6420, 0x14e1,
+ 0x6421, 0x14e4,
+ 0x6422, 0x338c,
+ 0x6426, 0x14e3,
+ 0x6427, 0x3390,
+ 0x642a, 0x0e15,
+ 0x642b, 0x3393,
+ 0x642c, 0x03ec,
+ 0x642d, 0x0571,
+ 0x642e, 0x3394,
+ 0x6434, 0x1736,
+ 0x6435, 0x339a,
+ 0x6436, 0x20db,
+ 0x6437, 0x339b,
+ 0x643a, 0x0f7a,
+ 0x643b, 0x339e,
+ 0x643d, 0x04b2,
+ 0x643e, 0x33a0,
+ 0x643f, 0x1951,
+ 0x6440, 0x33a1,
+ 0x6441, 0x14de,
+ 0x6442, 0x33a2,
+ 0x6444, 0x0d1c,
+ 0x6445, 0x14dd,
+ 0x6446, 0x03e5,
+ 0x6447, 0x1028,
+ 0x6448, 0x0460,
+ 0x6449, 0x33a4,
+ 0x644a, 0x0e02,
+ 0x644b, 0x33a5,
+ 0x6451, 0x2360,
+ 0x6452, 0x14da,
+ 0x6453, 0x33ab,
+ 0x6454, 0x0d99,
+ 0x6455, 0x33ac,
+ 0x6458, 0x114b,
+ 0x6459, 0x33af,
+ 0x645c, 0x2361,
+ 0x645d, 0x33b2,
+ 0x645e, 0x14e5,
+ 0x645f, 0x2040,
+ 0x6460, 0x33b3,
+ 0x6467, 0x0560,
+ 0x6468, 0x33ba,
+ 0x6469, 0x0b09,
+ 0x646a, 0x33bb,
+ 0x646d, 0x14e7,
+ 0x646e, 0x33be,
+ 0x646f, 0x228e,
+ 0x6470, 0x33bf,
+ 0x6473, 0x1fdf,
+ 0x6474, 0x33c2,
+ 0x6476, 0x235e,
+ 0x6477, 0x33c4,
+ 0x6478, 0x0b03,
+ 0x647a, 0x14e9,
+ 0x647b, 0x1e6a,
+ 0x647c, 0x33c5,
+ 0x6482, 0x0a15,
+ 0x6483, 0x33cb,
+ 0x6484, 0x14e6,
+ 0x6485, 0x091e,
+ 0x6486, 0x33cc,
+ 0x6487, 0x0bd1,
+ 0x6488, 0x2002,
+ 0x6489, 0x33cd,
+ 0x6491, 0x04ea,
+ 0x6492, 0x0cd1,
+ 0x6493, 0x2093,
+ 0x6494, 0x33d5,
+ 0x6495, 0x0daf,
+ 0x6496, 0x14e8,
+ 0x6497, 0x33d6,
+ 0x6499, 0x14ec,
+ 0x649a, 0x33d8,
+ 0x649e, 0x120f,
+ 0x649f, 0x235f,
+ 0x64a0, 0x33dc,
+ 0x64a3, 0x1eac,
+ 0x64a4, 0x04dc,
+ 0x64a5, 0x1e54,
+ 0x64a6, 0x33df,
+ 0x64a9, 0x0a0c,
+ 0x64aa, 0x33e2,
+ 0x64ab, 0x1f08,
+ 0x64ac, 0x0c48,
+ 0x64ad, 0x046c,
+ 0x64ae, 0x056c,
+ 0x64af, 0x33e3,
+ 0x64b0, 0x1208,
+ 0x64b1, 0x33e4,
+ 0x64b2, 0x20c0,
+ 0x64b3, 0x2362,
+ 0x64b4, 0x33e5,
+ 0x64b5, 0x0b4f,
+ 0x64b6, 0x33e6,
+ 0x64b7, 0x14ea,
+ 0x64b9, 0x33e7,
+ 0x64ba, 0x14ed,
+ 0x64bb, 0x2160,
+ 0x64bc, 0x076a,
+ 0x64bd, 0x33e8,
+ 0x64be, 0x219d,
+ 0x64bf, 0x1f8e,
+ 0x64c0, 0x14ee,
+ 0x64c1, 0x222d,
+ 0x64c2, 0x09c9,
+ 0x64c3, 0x33e9,
+ 0x64c4, 0x2047,
+ 0x64c5, 0x0cfc,
+ 0x64c6, 0x33ea,
+ 0x64c7, 0x2262,
+ 0x64c8, 0x33eb,
+ 0x64ca, 0x1f67,
+ 0x64cb, 0x1eb2,
+ 0x64cc, 0x33ed,
+ 0x64cd, 0x04a0,
+ 0x64ce, 0x0c63,
+ 0x64cf, 0x33ee,
+ 0x64d0, 0x14ef,
+ 0x64d1, 0x33ef,
+ 0x64d2, 0x0c59,
+ 0x64d3, 0x33f0,
+ 0x64d4, 0x1ea9,
+ 0x64d5, 0x33f1,
+ 0x64d7, 0x14f0,
+ 0x64d8, 0x1952,
+ 0x64d9, 0x33f3,
+ 0x64da, 0x1fcc,
+ 0x64db, 0x33f4,
+ 0x64de, 0x0dc8,
+ 0x64df, 0x33f7,
+ 0x64e0, 0x1f72,
+ 0x64e1, 0x33f8,
+ 0x64e2, 0x14f2,
+ 0x64e3, 0x33f9,
+ 0x64e4, 0x14f1,
+ 0x64e5, 0x33fa,
+ 0x64e6, 0x0488,
+ 0x64e7, 0x33fb,
+ 0x64ec, 0x2098,
+ 0x64ed, 0x3400,
+ 0x64ef, 0x1e52,
+ 0x64f0, 0x20a4,
+ 0x64f1, 0x1f1c,
+ 0x64f2, 0x228f,
+ 0x64f3, 0x3402,
+ 0x64f4, 0x1fed,
+ 0x64f5, 0x3403,
+ 0x64f7, 0x2365,
+ 0x64f8, 0x3405,
+ 0x64fa, 0x1e2d,
+ 0x64fb, 0x2152,
+ 0x64fc, 0x2366,
+ 0x64fd, 0x3407,
+ 0x64fe, 0x20fa,
+ 0x64ff, 0x3408,
+ 0x6500, 0x0b8b,
+ 0x6501, 0x3409,
+ 0x6504, 0x2363,
+ 0x6505, 0x340c,
+ 0x6506, 0x209a,
+ 0x6507, 0x340d,
+ 0x6509, 0x14f3,
+ 0x650a, 0x340f,
+ 0x650f, 0x203c,
+ 0x6510, 0x3414,
+ 0x6512, 0x111f,
+ 0x6513, 0x3416,
+ 0x6514, 0x1ff6,
+ 0x6515, 0x3417,
+ 0x6516, 0x2364,
+ 0x6517, 0x3418,
+ 0x6518, 0x0c9c,
+ 0x6519, 0x1e69,
+ 0x651a, 0x3419,
+ 0x651b, 0x2367,
+ 0x651c, 0x341a,
+ 0x651d, 0x211d,
+ 0x651e, 0x341b,
+ 0x6522, 0x2259,
+ 0x6523, 0x2056,
+ 0x6524, 0x2163,
+ 0x6525, 0x14f4,
+ 0x6526, 0x341f,
+ 0x652a, 0x1fa9,
+ 0x652b, 0x091f,
+ 0x652c, 0x1ffc,
+ 0x652d, 0x3423,
+ 0x652e, 0x14f5,
+ 0x652f, 0x11a6,
+ 0x6530, 0x3424,
+ 0x6534, 0x1909,
+ 0x6535, 0x1966,
+ 0x6536, 0x0d6c,
+ 0x6537, 0x3428,
+ 0x6538, 0x12b2,
+ 0x6539, 0x06bf,
+ 0x653a, 0x3429,
+ 0x653b, 0x06fe,
+ 0x653c, 0x342a,
+ 0x653e, 0x0662,
+ 0x653f, 0x119f,
+ 0x6540, 0x342c,
+ 0x6545, 0x0723,
+ 0x6546, 0x3431,
+ 0x6548, 0x0f72,
+ 0x6549, 0x1ccb,
+ 0x654a, 0x3433,
+ 0x654c, 0x05b1,
+ 0x654d, 0x3435,
+ 0x654f, 0x0af9,
+ 0x6550, 0x3437,
+ 0x6551, 0x08f7,
+ 0x6552, 0x3438,
+ 0x6555, 0x1967,
+ 0x6556, 0x03c8,
+ 0x6557, 0x1e2e,
+ 0x6558, 0x343b,
+ 0x6559, 0x089d,
+ 0x655a, 0x343c,
+ 0x655b, 0x09fb,
+ 0x655c, 0x343d,
+ 0x655d, 0x043f,
+ 0x655e, 0x04cd,
+ 0x655f, 0x343e,
+ 0x6562, 0x06cd,
+ 0x6563, 0x0cdb,
+ 0x6564, 0x3441,
+ 0x6566, 0x0617,
+ 0x6567, 0x3443,
+ 0x656b, 0x1968,
+ 0x656c, 0x08e3,
+ 0x656d, 0x3447,
+ 0x6570, 0x0d94,
+ 0x6571, 0x344a,
+ 0x6572, 0x0c40,
+ 0x6573, 0x344b,
+ 0x6574, 0x119c,
+ 0x6575, 0x1ebc,
+ 0x6576, 0x344c,
+ 0x6577, 0x0690,
+ 0x6578, 0x2142,
+ 0x6579, 0x344d,
+ 0x6582, 0x201e,
+ 0x6583, 0x1e43,
+ 0x6584, 0x3456,
+ 0x6587, 0x0ed3,
+ 0x6588, 0x3459,
+ 0x658b, 0x114c,
+ 0x658c, 0x045c,
+ 0x658d, 0x345c,
+ 0x6590, 0x19c1,
+ 0x6591, 0x03ea,
+ 0x6592, 0x345f,
+ 0x6593, 0x19c3,
+ 0x6594, 0x3460,
+ 0x6595, 0x24d4,
+ 0x6596, 0x3461,
+ 0x6597, 0x05f6,
+ 0x6598, 0x3462,
+ 0x6599, 0x0a18,
+ 0x659a, 0x3463,
+ 0x659b, 0x1d56,
+ 0x659c, 0x0f7c,
+ 0x659d, 0x3464,
+ 0x659f, 0x1186,
+ 0x65a0, 0x3466,
+ 0x65a1, 0x0ee2,
+ 0x65a2, 0x3467,
+ 0x65a4, 0x08c0,
+ 0x65a5, 0x0507,
+ 0x65a6, 0x3469,
+ 0x65a7, 0x06a6,
+ 0x65a8, 0x346a,
+ 0x65a9, 0x1157,
+ 0x65aa, 0x346b,
+ 0x65ab, 0x1a29,
+ 0x65ac, 0x226f,
+ 0x65ad, 0x060e,
+ 0x65ae, 0x346c,
+ 0x65af, 0x0dae,
+ 0x65b0, 0x0f8d,
+ 0x65b1, 0x346d,
+ 0x65b7, 0x1ed7,
+ 0x65b8, 0x3473,
+ 0x65b9, 0x065a,
+ 0x65ba, 0x3474,
+ 0x65bc, 0x19c4,
+ 0x65bd, 0x0d40,
+ 0x65be, 0x3476,
+ 0x65c1, 0x0b95,
+ 0x65c2, 0x3479,
+ 0x65c3, 0x19c7,
+ 0x65c4, 0x19c6,
+ 0x65c5, 0x0a6a,
+ 0x65c6, 0x19c5,
+ 0x65c7, 0x347a,
+ 0x65cb, 0x0fc8,
+ 0x65cc, 0x19c8,
+ 0x65cd, 0x347e,
+ 0x65ce, 0x19c9,
+ 0x65cf, 0x1242,
+ 0x65d0, 0x347f,
+ 0x65d2, 0x19ca,
+ 0x65d3, 0x3481,
+ 0x65d6, 0x19cb,
+ 0x65d7, 0x0c0b,
+ 0x65d8, 0x3484,
+ 0x65e0, 0x0eed,
+ 0x65e1, 0x348c,
+ 0x65e2, 0x083b,
+ 0x65e3, 0x348d,
+ 0x65e5, 0x0cb0,
+ 0x65e6, 0x058a,
+ 0x65e7, 0x08f8,
+ 0x65e8, 0x11bb,
+ 0x65e9, 0x112a,
+ 0x65ea, 0x348f,
+ 0x65ec, 0x0fd7,
+ 0x65ed, 0x0fbc,
+ 0x65ee, 0x190a,
+ 0x65f1, 0x076c,
+ 0x65f2, 0x3491,
+ 0x65f6, 0x0d48,
+ 0x65f7, 0x0982,
+ 0x65f8, 0x3495,
+ 0x65fa, 0x0eab,
+ 0x65fb, 0x3497,
+ 0x6600, 0x1912,
+ 0x6601, 0x349c,
+ 0x6602, 0x03c5,
+ 0x6603, 0x1910,
+ 0x6604, 0x349d,
+ 0x6606, 0x0990,
+ 0x6607, 0x349f,
+ 0x660a, 0x190d,
+ 0x660b, 0x34a2,
+ 0x660c, 0x04c4,
+ 0x660d, 0x34a3,
+ 0x660e, 0x0afc,
+ 0x660f, 0x07fd,
+ 0x6610, 0x34a4,
+ 0x6613, 0x105e,
+ 0x6614, 0x0f03,
+ 0x6615, 0x1911,
+ 0x6616, 0x34a7,
+ 0x6619, 0x190e,
+ 0x661a, 0x34aa,
+ 0x661d, 0x1915,
+ 0x661e, 0x34ad,
+ 0x661f, 0x0f92,
+ 0x6620, 0x1098,
+ 0x6621, 0x34ae,
+ 0x6625, 0x053d,
+ 0x6626, 0x34b2,
+ 0x6627, 0x0ac6,
+ 0x6628, 0x124f,
+ 0x6629, 0x34b3,
+ 0x662d, 0x1172,
+ 0x662e, 0x34b7,
+ 0x662f, 0x0d5e,
+ 0x6630, 0x34b8,
+ 0x6631, 0x1917,
+ 0x6632, 0x34b9,
+ 0x6634, 0x1916,
+ 0x6635, 0x1919,
+ 0x6636, 0x1918,
+ 0x6637, 0x34bb,
+ 0x663c, 0x11e6,
+ 0x663d, 0x34c0,
+ 0x663e, 0x0f41,
+ 0x663f, 0x34c1,
+ 0x6641, 0x191d,
+ 0x6642, 0x212d,
+ 0x6643, 0x07e3,
+ 0x6644, 0x34c3,
+ 0x664b, 0x08cb,
+ 0x664c, 0x0d07,
+ 0x664d, 0x34ca,
+ 0x664f, 0x191e,
+ 0x6650, 0x34cc,
+ 0x6652, 0x0cf2,
+ 0x6653, 0x0f6b,
+ 0x6654, 0x191c,
+ 0x6655, 0x1111,
+ 0x6656, 0x191f,
+ 0x6657, 0x1921,
+ 0x6658, 0x34ce,
+ 0x665a, 0x0e9e,
+ 0x665b, 0x34d0,
+ 0x665d, 0x229b,
+ 0x665e, 0x34d2,
+ 0x665f, 0x191b,
+ 0x6660, 0x34d3,
+ 0x6661, 0x1920,
+ 0x6662, 0x34d4,
+ 0x6664, 0x0efd,
+ 0x6665, 0x34d6,
+ 0x6666, 0x07f3,
+ 0x6667, 0x34d7,
+ 0x6668, 0x04e4,
+ 0x6669, 0x34d8,
+ 0x666e, 0x0bf4,
+ 0x666f, 0x08df,
+ 0x6670, 0x0f09,
+ 0x6671, 0x34dd,
+ 0x6674, 0x0c64,
+ 0x6675, 0x34e0,
+ 0x6676, 0x08d6,
+ 0x6677, 0x1922,
+ 0x6678, 0x34e1,
+ 0x667a, 0x11c6,
+ 0x667b, 0x34e3,
+ 0x667e, 0x0a09,
+ 0x667f, 0x34e6,
+ 0x6682, 0x1120,
+ 0x6683, 0x34e9,
+ 0x6684, 0x1923,
+ 0x6685, 0x34ea,
+ 0x6687, 0x0f2b,
+ 0x6688, 0x2256,
+ 0x6689, 0x24a8,
+ 0x668a, 0x34ec,
+ 0x668c, 0x1924,
+ 0x668d, 0x34ee,
+ 0x6691, 0x0d85,
+ 0x6692, 0x34f2,
+ 0x6696, 0x0b70,
+ 0x6697, 0x03c0,
+ 0x6698, 0x34f6,
+ 0x669d, 0x1926,
+ 0x669e, 0x34fb,
+ 0x66a2, 0x1e79,
+ 0x66a3, 0x34ff,
+ 0x66a7, 0x1925,
+ 0x66a8, 0x1cdd,
+ 0x66a9, 0x3503,
+ 0x66ab, 0x225a,
+ 0x66ac, 0x3505,
+ 0x66ae, 0x0b1d,
+ 0x66af, 0x3507,
+ 0x66b4, 0x0412,
+ 0x66b5, 0x350c,
+ 0x66b9, 0x175b,
+ 0x66ba, 0x3510,
+ 0x66be, 0x1927,
+ 0x66bf, 0x3514,
+ 0x66c4, 0x24a7,
+ 0x66c5, 0x3519,
+ 0x66c6, 0x2686,
+ 0x66c7, 0x24a6,
+ 0x66c8, 0x351a,
+ 0x66c9, 0x21ce,
+ 0x66ca, 0x351b,
+ 0x66d6, 0x24a9,
+ 0x66d7, 0x3527,
+ 0x66d9, 0x0d86,
+ 0x66da, 0x3529,
+ 0x66db, 0x1928,
+ 0x66dd, 0x0bf7,
+ 0x66de, 0x352a,
+ 0x66e0, 0x1fe7,
+ 0x66e1, 0x352c,
+ 0x66e6, 0x192a,
+ 0x66e7, 0x3531,
+ 0x66e9, 0x192b,
+ 0x66ea, 0x3533,
+ 0x66ec, 0x2112,
+ 0x66ed, 0x3535,
+ 0x66f0, 0x10fe,
+ 0x66f1, 0x3538,
+ 0x66f2, 0x0c77,
+ 0x66f3, 0x103e,
+ 0x66f4, 0x06f7,
+ 0x66f5, 0x3539,
+ 0x66f7, 0x1914,
+ 0x66f8, 0x213c,
+ 0x66f9, 0x04a3,
+ 0x66fa, 0x353b,
+ 0x66fc, 0x0aa3,
+ 0x66fd, 0x353d,
+ 0x66fe, 0x113b,
+ 0x66ff, 0x0e39,
+ 0x6700, 0x124b,
+ 0x6701, 0x353e,
+ 0x6703, 0x1f5c,
+ 0x6704, 0x3540,
+ 0x6708, 0x1105,
+ 0x6709, 0x10b5,
+ 0x670a, 0x1973,
+ 0x670b, 0x0bb4,
+ 0x670c, 0x3544,
+ 0x670d, 0x069b,
+ 0x670e, 0x3545,
+ 0x6710, 0x1984,
+ 0x6711, 0x3547,
+ 0x6714, 0x0dac,
+ 0x6715, 0x198e,
+ 0x6716, 0x354a,
+ 0x6717, 0x09b5,
+ 0x6718, 0x354b,
+ 0x671b, 0x0eac,
+ 0x671c, 0x354e,
+ 0x671d, 0x04d4,
+ 0x671e, 0x354f,
+ 0x671f, 0x0bf9,
+ 0x6720, 0x3550,
+ 0x6726, 0x19ac,
+ 0x6727, 0x24c4,
+ 0x6728, 0x0b21,
+ 0x6729, 0x3556,
+ 0x672a, 0x0ec3,
+ 0x672b, 0x0b0c,
+ 0x672c, 0x0427,
+ 0x672d, 0x1140,
+ 0x672e, 0x3557,
+ 0x672f, 0x0d8c,
+ 0x6730, 0x3558,
+ 0x6731, 0x11eb,
+ 0x6732, 0x3559,
+ 0x6734, 0x0bf2,
+ 0x6735, 0x0623,
+ 0x6736, 0x355b,
+ 0x673a, 0x080f,
+ 0x673b, 0x355f,
+ 0x673d, 0x0fab,
+ 0x673e, 0x3561,
+ 0x6740, 0x0cea,
+ 0x6741, 0x3563,
+ 0x6742, 0x1116,
+ 0x6743, 0x0c83,
+ 0x6744, 0x3564,
+ 0x6746, 0x06c6,
+ 0x6747, 0x3566,
+ 0x6748, 0x1854,
+ 0x6749, 0x0cf5,
+ 0x674a, 0x3567,
+ 0x674c, 0x1851,
+ 0x674d, 0x3569,
+ 0x674e, 0x09d9,
+ 0x674f, 0x0f9e,
+ 0x6750, 0x048b,
+ 0x6751, 0x0568,
+ 0x6752, 0x356a,
+ 0x6753, 0x1852,
+ 0x6754, 0x356b,
+ 0x6756, 0x1169,
+ 0x6757, 0x356d,
+ 0x675c, 0x0604,
+ 0x675d, 0x3572,
+ 0x675e, 0x1853,
+ 0x675f, 0x0d8f,
+ 0x6760, 0x06d7,
+ 0x6761, 0x0e48,
+ 0x6762, 0x3573,
+ 0x6765, 0x099f,
+ 0x6766, 0x3576,
+ 0x6768, 0x1017,
+ 0x6769, 0x1855,
+ 0x676a, 0x1858,
+ 0x676b, 0x3578,
+ 0x676d, 0x0773,
+ 0x676e, 0x357a,
+ 0x676f, 0x0416,
+ 0x6770, 0x08ad,
+ 0x6771, 0x1ecc,
+ 0x6772, 0x190f,
+ 0x6773, 0x1859,
+ 0x6774, 0x357b,
+ 0x6775, 0x185c,
+ 0x6776, 0x357c,
+ 0x6777, 0x1861,
+ 0x6778, 0x357d,
+ 0x677c, 0x1862,
+ 0x677d, 0x3581,
+ 0x677e, 0x0dbe,
+ 0x677f, 0x03f0,
+ 0x6780, 0x3582,
+ 0x6781, 0x081e,
+ 0x6782, 0x3583,
+ 0x6784, 0x0712,
+ 0x6785, 0x3585,
+ 0x6787, 0x1857,
+ 0x6788, 0x3587,
+ 0x6789, 0x0ea8,
+ 0x678a, 0x3588,
+ 0x678b, 0x1860,
+ 0x678c, 0x3589,
+ 0x6790, 0x0f05,
+ 0x6791, 0x358d,
+ 0x6795, 0x118e,
+ 0x6796, 0x3591,
+ 0x6797, 0x0a1f,
+ 0x6798, 0x185a,
+ 0x6799, 0x3592,
+ 0x679a, 0x0abb,
+ 0x679b, 0x3593,
+ 0x679c, 0x0754,
+ 0x679d, 0x11a5,
+ 0x679e, 0x185e,
+ 0x679f, 0x3594,
+ 0x67a2, 0x0d77,
+ 0x67a3, 0x1129,
+ 0x67a4, 0x3597,
+ 0x67a5, 0x1856,
+ 0x67a6, 0x3598,
+ 0x67a7, 0x185b,
+ 0x67a8, 0x185d,
+ 0x67a9, 0x3599,
+ 0x67aa, 0x0c36,
+ 0x67ab, 0x0680,
+ 0x67ac, 0x359a,
+ 0x67ad, 0x185f,
+ 0x67ae, 0x359b,
+ 0x67af, 0x096a,
+ 0x67b0, 0x1868,
+ 0x67b1, 0x359c,
+ 0x67b3, 0x186d,
+ 0x67b4, 0x359e,
+ 0x67b5, 0x186b,
+ 0x67b6, 0x084f,
+ 0x67b7, 0x0842,
+ 0x67b8, 0x1871,
+ 0x67b9, 0x359f,
+ 0x67c1, 0x1874,
+ 0x67c2, 0x35a7,
+ 0x67c3, 0x1870,
+ 0x67c4, 0x0463,
+ 0x67c5, 0x35a8,
+ 0x67cf, 0x03e3,
+ 0x67d0, 0x0b16,
+ 0x67d1, 0x06c7,
+ 0x67d2, 0x0c01,
+ 0x67d3, 0x0c99,
+ 0x67d4, 0x0cbc,
+ 0x67d5, 0x35b2,
+ 0x67d8, 0x1865,
+ 0x67d9, 0x186a,
+ 0x67da, 0x186c,
+ 0x67db, 0x35b5,
+ 0x67dc, 0x074a,
+ 0x67dd, 0x186e,
+ 0x67de, 0x1252,
+ 0x67df, 0x35b6,
+ 0x67e0, 0x0b5e,
+ 0x67e1, 0x35b7,
+ 0x67e2, 0x1872,
+ 0x67e3, 0x35b8,
+ 0x67e5, 0x04b0,
+ 0x67e6, 0x35ba,
+ 0x67e9, 0x1867,
+ 0x67ea, 0x35bd,
+ 0x67ec, 0x0860,
+ 0x67ed, 0x35bf,
+ 0x67ef, 0x094f,
+ 0x67f0, 0x1863,
+ 0x67f1, 0x11f8,
+ 0x67f2, 0x35c1,
+ 0x67f3, 0x0a41,
+ 0x67f4, 0x04b8,
+ 0x67f5, 0x35c2,
+ 0x67fd, 0x1875,
+ 0x67fe, 0x35ca,
+ 0x67ff, 0x0d58,
+ 0x6800, 0x186f,
+ 0x6801, 0x35cb,
+ 0x6805, 0x1145,
+ 0x6806, 0x35cf,
+ 0x6807, 0x0453,
+ 0x6808, 0x115c,
+ 0x6809, 0x1864,
+ 0x680a, 0x1866,
+ 0x680b, 0x05ef,
+ 0x680c, 0x1869,
+ 0x680d, 0x35d0,
+ 0x680e, 0x1873,
+ 0x680f, 0x09a3,
+ 0x6810, 0x35d1,
+ 0x6811, 0x0d8e,
+ 0x6812, 0x35d2,
+ 0x6813, 0x0d9d,
+ 0x6814, 0x35d3,
+ 0x6816, 0x0bfb,
+ 0x6817, 0x09e0,
+ 0x6818, 0x35d5,
+ 0x681d, 0x187f,
+ 0x681e, 0x35da,
+ 0x6821, 0x0f6e,
+ 0x6822, 0x35dd,
+ 0x6829, 0x1888,
+ 0x682a, 0x11e9,
+ 0x682b, 0x35e4,
+ 0x6832, 0x1876,
+ 0x6834, 0x35eb,
+ 0x6837, 0x1022,
+ 0x6838, 0x0782,
+ 0x6839, 0x06f4,
+ 0x683a, 0x35ee,
+ 0x683c, 0x06ec,
+ 0x683d, 0x1117,
+ 0x683e, 0x1885,
+ 0x683f, 0x35f0,
+ 0x6840, 0x1884,
+ 0x6841, 0x1882,
+ 0x6842, 0x0749,
+ 0x6843, 0x0e25,
+ 0x6844, 0x187c,
+ 0x6845, 0x0eb5,
+ 0x6846, 0x097f,
+ 0x6847, 0x35f1,
+ 0x6848, 0x03c3,
+ 0x6849, 0x1887,
+ 0x684a, 0x1886,
+ 0x684b, 0x35f2,
+ 0x684c, 0x121d,
+ 0x684d, 0x35f3,
+ 0x684e, 0x187a,
+ 0x684f, 0x35f4,
+ 0x6850, 0x0e5a,
+ 0x6851, 0x0cdc,
+ 0x6852, 0x35f5,
+ 0x6853, 0x07cd,
+ 0x6854, 0x08ac,
+ 0x6855, 0x1880,
+ 0x6856, 0x35f6,
+ 0x6860, 0x1878,
+ 0x6862, 0x187b,
+ 0x6863, 0x0596,
+ 0x6864, 0x187d,
+ 0x6865, 0x0c42,
+ 0x6866, 0x1881,
+ 0x6867, 0x1883,
+ 0x6868, 0x0881,
+ 0x6869, 0x120b,
+ 0x686a, 0x3600,
+ 0x686b, 0x188e,
+ 0x686c, 0x3601,
+ 0x6874, 0x188b,
+ 0x6875, 0x3609,
+ 0x6876, 0x0e61,
+ 0x6877, 0x188c,
+ 0x6878, 0x360a,
+ 0x6881, 0x0a03,
+ 0x6882, 0x3613,
+ 0x6883, 0x187e,
+ 0x6884, 0x3614,
+ 0x6885, 0x0abc,
+ 0x6886, 0x03fb,
+ 0x6887, 0x3615,
+ 0x688f, 0x188a,
+ 0x6890, 0x361d,
+ 0x6893, 0x188d,
+ 0x6894, 0x3620,
+ 0x6897, 0x06fc,
+ 0x6898, 0x246a,
+ 0x6899, 0x3623,
+ 0x689d, 0x2175,
+ 0x689e, 0x3627,
+ 0x689f, 0x246d,
+ 0x68a0, 0x3628,
+ 0x68a2, 0x0d0b,
+ 0x68a3, 0x362a,
+ 0x68a6, 0x0ad3,
+ 0x68a7, 0x0eef,
+ 0x68a8, 0x09d1,
+ 0x68a9, 0x362d,
+ 0x68ad, 0x0de8,
+ 0x68ae, 0x3631,
+ 0x68af, 0x0e30,
+ 0x68b0, 0x0f80,
+ 0x68b1, 0x3632,
+ 0x68b3, 0x0d78,
+ 0x68b4, 0x3634,
+ 0x68b5, 0x1889,
+ 0x68b6, 0x3635,
+ 0x68c0, 0x085f,
+ 0x68c1, 0x363f,
+ 0x68c2, 0x188f,
+ 0x68c3, 0x3640,
+ 0x68c9, 0x0ae3,
+ 0x68ca, 0x3646,
+ 0x68cb, 0x0c04,
+ 0x68cc, 0x3647,
+ 0x68cd, 0x0750,
+ 0x68ce, 0x3648,
+ 0x68d2, 0x03ff,
+ 0x68d3, 0x364c,
+ 0x68d5, 0x1235,
+ 0x68d6, 0x246b,
+ 0x68d7, 0x225f,
+ 0x68d8, 0x081f,
+ 0x68d9, 0x364e,
+ 0x68da, 0x0bb0,
+ 0x68db, 0x364f,
+ 0x68df, 0x1ece,
+ 0x68e0, 0x0e17,
+ 0x68e1, 0x3653,
+ 0x68e3, 0x189a,
+ 0x68e4, 0x3655,
+ 0x68e7, 0x2272,
+ 0x68e8, 0x3658,
+ 0x68ee, 0x0ce6,
+ 0x68ef, 0x365e,
+ 0x68f0, 0x1896,
+ 0x68f1, 0x09cd,
+ 0x68f2, 0x365f,
+ 0x68f5, 0x0950,
+ 0x68f6, 0x3662,
+ 0x68f9, 0x1894,
+ 0x68fa, 0x0730,
+ 0x68fb, 0x3665,
+ 0x68fc, 0x1891,
+ 0x68fd, 0x3666,
+ 0x6900, 0x3669,
+ 0x6901, 0x1898,
+ 0x6902, 0x366a,
+ 0x6905, 0x1055,
+ 0x6906, 0x366d,
+ 0x690b, 0x1897,
+ 0x690c, 0x3672,
+ 0x690d, 0x11b1,
+ 0x690e, 0x1212,
+ 0x690f, 0x2473,
+ 0x6910, 0x189b,
+ 0x6911, 0x3673,
+ 0x6912, 0x0888,
+ 0x6913, 0x3674,
+ 0x691f, 0x1892,
+ 0x6921, 0x3680,
+ 0x6924, 0x1895,
+ 0x6925, 0x3683,
+ 0x692d, 0x0e87,
+ 0x692e, 0x368b,
+ 0x6930, 0x1033,
+ 0x6931, 0x368d,
+ 0x6934, 0x18a6,
+ 0x6935, 0x3690,
+ 0x6939, 0x189d,
+ 0x693a, 0x3694,
+ 0x693d, 0x052d,
+ 0x693e, 0x3697,
+ 0x693f, 0x053e,
+ 0x6940, 0x3698,
+ 0x6942, 0x189f,
+ 0x6943, 0x369a,
+ 0x694a, 0x21fe,
+ 0x694b, 0x36a1,
+ 0x6953, 0x1efe,
+ 0x6954, 0x0f73,
+ 0x6955, 0x36a9,
+ 0x6957, 0x1899,
+ 0x6958, 0x36ab,
+ 0x695a, 0x0523,
+ 0x695b, 0x36ad,
+ 0x695d, 0x18a0,
+ 0x695e, 0x09ce,
+ 0x695f, 0x36af,
+ 0x6960, 0x189e,
+ 0x6961, 0x36b0,
+ 0x6963, 0x18ad,
+ 0x6964, 0x36b2,
+ 0x6966, 0x18ac,
+ 0x6967, 0x36b4,
+ 0x6968, 0x2475,
+ 0x6969, 0x36b5,
+ 0x696b, 0x18a2,
+ 0x696c, 0x36b7,
+ 0x696d, 0x220a,
+ 0x696e, 0x1890,
+ 0x696f, 0x36b8,
+ 0x6971, 0x189c,
+ 0x6972, 0x36ba,
+ 0x6975, 0x1f6f,
+ 0x6976, 0x36bd,
+ 0x6977, 0x0939,
+ 0x6978, 0x18a5,
+ 0x6979, 0x18ae,
+ 0x697a, 0x36be,
+ 0x697c, 0x0a4c,
+ 0x697d, 0x36c0,
+ 0x6980, 0x18a3,
+ 0x6981, 0x36c3,
+ 0x6982, 0x06c0,
+ 0x6983, 0x36c4,
+ 0x6984, 0x18a1,
+ 0x6985, 0x36c5,
+ 0x6986, 0x10c1,
+ 0x6987, 0x18a8,
+ 0x6989, 0x18ab,
+ 0x698a, 0x36c6,
+ 0x698d, 0x18bb,
+ 0x698e, 0x36c9,
+ 0x6994, 0x09b1,
+ 0x6995, 0x18b9,
+ 0x6996, 0x36cf,
+ 0x6998, 0x18a4,
+ 0x6999, 0x36d1,
+ 0x699b, 0x18af,
+ 0x699c, 0x03fc,
+ 0x699d, 0x36d3,
+ 0x69a7, 0x18b0,
+ 0x69a8, 0x1146,
+ 0x69a9, 0x36dd,
+ 0x69aa, 0x2468,
+ 0x69ab, 0x18b2,
+ 0x69ac, 0x36de,
+ 0x69ad, 0x18b3,
+ 0x69ae, 0x2100,
+ 0x69af, 0x36df,
+ 0x69b1, 0x18b5,
+ 0x69b2, 0x36e1,
+ 0x69b4, 0x0a3a,
+ 0x69b5, 0x36e3,
+ 0x69b7, 0x0c91,
+ 0x69b8, 0x36e5,
+ 0x69bb, 0x18b1,
+ 0x69bc, 0x36e8,
+ 0x69bf, 0x2476,
+ 0x69c0, 0x36eb,
+ 0x69c1, 0x18b6,
+ 0x69c2, 0x36ec,
+ 0x69ca, 0x18b7,
+ 0x69cb, 0x1f27,
+ 0x69cc, 0x18a7,
+ 0x69cd, 0x20d7,
+ 0x69ce, 0x18aa,
+ 0x69cf, 0x36f4,
+ 0x69d0, 0x07c6,
+ 0x69d1, 0x36f5,
+ 0x69d4, 0x18b4,
+ 0x69d5, 0x36f8,
+ 0x69db, 0x086a,
+ 0x69dc, 0x36fe,
+ 0x69df, 0x18b8,
+ 0x69e0, 0x18ba,
+ 0x69e1, 0x3701,
+ 0x69e7, 0x247c,
+ 0x69e8, 0x3707,
+ 0x69ed, 0x18be,
+ 0x69ee, 0x370c,
+ 0x69f2, 0x18c2,
+ 0x69f3, 0x1fa1,
+ 0x69f4, 0x3710,
+ 0x69fd, 0x04a2,
+ 0x69fe, 0x3719,
+ 0x69ff, 0x18bc,
+ 0x6a00, 0x371a,
+ 0x6a01, 0x22aa,
+ 0x6a02, 0x2005,
+ 0x6a03, 0x371b,
+ 0x6a05, 0x246c,
+ 0x6a06, 0x371d,
+ 0x6a0a, 0x064b,
+ 0x6a0b, 0x3721,
+ 0x6a13, 0x203e,
+ 0x6a14, 0x3729,
+ 0x6a17, 0x18bf,
+ 0x6a19, 0x1e4c,
+ 0x6a1a, 0x372c,
+ 0x6a1e, 0x213a,
+ 0x6a1f, 0x1162,
+ 0x6a20, 0x3730,
+ 0x6a21, 0x0b06,
+ 0x6a22, 0x3731,
+ 0x6a23, 0x2204,
+ 0x6a24, 0x3732,
+ 0x6a28, 0x18cc,
+ 0x6a29, 0x3736,
+ 0x6a2a, 0x0798,
+ 0x6a2b, 0x3737,
+ 0x6a2f, 0x18bd,
+ 0x6a30, 0x373b,
+ 0x6a31, 0x1088,
+ 0x6a32, 0x373c,
+ 0x6a35, 0x18c8,
+ 0x6a36, 0x373f,
+ 0x6a38, 0x20c3,
+ 0x6a39, 0x2140,
+ 0x6a3a, 0x2477,
+ 0x6a3b, 0x3741,
+ 0x6a3d, 0x18cb,
+ 0x6a3e, 0x18c4,
+ 0x6a3f, 0x3743,
+ 0x6a44, 0x18c3,
+ 0x6a45, 0x3748,
+ 0x6a47, 0x0c3e,
+ 0x6a48, 0x2474,
+ 0x6a49, 0x374a,
+ 0x6a4b, 0x20dd,
+ 0x6a4c, 0x374c,
+ 0x6a50, 0x18c6,
+ 0x6a51, 0x3750,
+ 0x6a58, 0x18cd,
+ 0x6a59, 0x04ed,
+ 0x6a5a, 0x3757,
+ 0x6a5b, 0x18c7,
+ 0x6a5c, 0x3758,
+ 0x6a5f, 0x1f68,
+ 0x6a60, 0x375b,
+ 0x6a61, 0x0f5d,
+ 0x6a62, 0x2185,
+ 0x6a63, 0x375c,
+ 0x6a65, 0x18c1,
+ 0x6a66, 0x375e,
+ 0x6a71, 0x051c,
+ 0x6a72, 0x3769,
+ 0x6a79, 0x18ca,
+ 0x6a7a, 0x3770,
+ 0x6a7c, 0x18ce,
+ 0x6a7d, 0x3772,
+ 0x6a80, 0x0e07,
+ 0x6a81, 0x3775,
+ 0x6a84, 0x0f1a,
+ 0x6a85, 0x3778,
+ 0x6a89, 0x2472,
+ 0x6a8a, 0x377c,
+ 0x6a8e, 0x18c9,
+ 0x6a8f, 0x3780,
+ 0x6a90, 0x18d0,
+ 0x6a91, 0x18cf,
+ 0x6a92, 0x3781,
+ 0x6a94, 0x1eb5,
+ 0x6a95, 0x3783,
+ 0x6a97, 0x18d2,
+ 0x6a98, 0x3785,
+ 0x6a9c, 0x2478,
+ 0x6a9d, 0x3789,
+ 0x6aa0, 0x18c5,
+ 0x6aa1, 0x378c,
+ 0x6aa2, 0x1f8b,
+ 0x6aa3, 0x2484,
+ 0x6aa4, 0x378d,
+ 0x6aa9, 0x18d1,
+ 0x6aaa, 0x3792,
+ 0x6aab, 0x18d3,
+ 0x6aac, 0x0acf,
+ 0x6aad, 0x3793,
+ 0x6aaf, 0x2699,
+ 0x6ab0, 0x3795,
+ 0x6ab3, 0x2482,
+ 0x6ab4, 0x3798,
+ 0x6ab8, 0x20a1,
+ 0x6ab9, 0x379c,
+ 0x6abb, 0x1f92,
+ 0x6abc, 0x379e,
+ 0x6ac3, 0x1f38,
+ 0x6ac4, 0x37a5,
+ 0x6ad3, 0x2485,
+ 0x6ad4, 0x37b4,
+ 0x6ada, 0x2480,
+ 0x6adb, 0x246e,
+ 0x6adc, 0x37ba,
+ 0x6add, 0x247b,
+ 0x6ade, 0x2486,
+ 0x6adf, 0x2471,
+ 0x6ae0, 0x37bb,
+ 0x6ae7, 0x2483,
+ 0x6ae8, 0x2470,
+ 0x6ae9, 0x37c2,
+ 0x6aea, 0x2469,
+ 0x6aeb, 0x37c3,
+ 0x6aec, 0x247f,
+ 0x6aed, 0x37c4,
+ 0x6af3, 0x246f,
+ 0x6af4, 0x37ca,
+ 0x6af8, 0x2481,
+ 0x6af9, 0x37ce,
+ 0x6afb, 0x2220,
+ 0x6afc, 0x37d0,
+ 0x6b00, 0x37d4,
+ 0x6b04, 0x1ff5,
+ 0x6b05, 0x37d8,
+ 0x6b0a, 0x20f4,
+ 0x6b0b, 0x37dd,
+ 0x6b0f, 0x247d,
+ 0x6b10, 0x37e1,
+ 0x6b12, 0x2479,
+ 0x6b13, 0x37e3,
+ 0x6b16, 0x247e,
+ 0x6b17, 0x37e6,
+ 0x6b1e, 0x247a,
+ 0x6b1f, 0x37ed,
+ 0x6b20, 0x0c34,
+ 0x6b21, 0x0551,
+ 0x6b22, 0x07cb,
+ 0x6b23, 0x0f8b,
+ 0x6b24, 0x19b1,
+ 0x6b25, 0x37ee,
+ 0x6b27, 0x0b78,
+ 0x6b28, 0x37f0,
+ 0x6b32, 0x10e0,
+ 0x6b33, 0x37fa,
+ 0x6b37, 0x19b2,
+ 0x6b38, 0x37fe,
+ 0x6b39, 0x19b3,
+ 0x6b3a, 0x0bfa,
+ 0x6b3b, 0x37ff,
+ 0x6b3d, 0x20e3,
+ 0x6b3e, 0x097b,
+ 0x6b3f, 0x3801,
+ 0x6b43, 0x19b4,
+ 0x6b44, 0x3805,
+ 0x6b46, 0x19b5,
+ 0x6b47, 0x0f75,
+ 0x6b48, 0x3807,
+ 0x6b49, 0x0c35,
+ 0x6b4a, 0x3808,
+ 0x6b4c, 0x06e3,
+ 0x6b4d, 0x380a,
+ 0x6b50, 0x20ad,
+ 0x6b51, 0x380d,
+ 0x6b59, 0x19b6,
+ 0x6b5a, 0x3815,
+ 0x6b5f, 0x24cb,
+ 0x6b60, 0x381a,
+ 0x6b61, 0x1f53,
+ 0x6b62, 0x11b8,
+ 0x6b63, 0x119e,
+ 0x6b64, 0x054e,
+ 0x6b65, 0x0484,
+ 0x6b66, 0x0ef3,
+ 0x6b67, 0x0c06,
+ 0x6b68, 0x381b,
+ 0x6b6a, 0x0e92,
+ 0x6b6b, 0x381d,
+ 0x6b72, 0x2159,
+ 0x6b73, 0x3824,
+ 0x6b77, 0x2013,
+ 0x6b78, 0x1f33,
+ 0x6b79, 0x0578,
+ 0x6b7a, 0x3828,
+ 0x6b7b, 0x0db5,
+ 0x6b7c, 0x0852,
+ 0x6b7d, 0x3829,
+ 0x6b81, 0x18d6,
+ 0x6b83, 0x1013,
+ 0x6b84, 0x18d9,
+ 0x6b85, 0x382d,
+ 0x6b86, 0x057c,
+ 0x6b87, 0x18d8,
+ 0x6b88, 0x382e,
+ 0x6b89, 0x0fdc,
+ 0x6b8a, 0x0d79,
+ 0x6b8b, 0x0497,
+ 0x6b8c, 0x382f,
+ 0x6b8d, 0x18dc,
+ 0x6b8e, 0x3830,
+ 0x6b92, 0x18da,
+ 0x6b94, 0x3834,
+ 0x6b96, 0x11b2,
+ 0x6b97, 0x3836,
+ 0x6b98, 0x1e5c,
+ 0x6b99, 0x3837,
+ 0x6b9a, 0x18dd,
+ 0x6b9c, 0x3838,
+ 0x6b9e, 0x2488,
+ 0x6b9f, 0x383a,
+ 0x6ba1, 0x18df,
+ 0x6ba2, 0x383c,
+ 0x6ba4, 0x2487,
+ 0x6ba5, 0x383e,
+ 0x6baa, 0x18e0,
+ 0x6bab, 0x248a,
+ 0x6bac, 0x3843,
+ 0x6bae, 0x2489,
+ 0x6baf, 0x248b,
+ 0x6bb0, 0x3845,
+ 0x6bb2, 0x1f83,
+ 0x6bb3, 0x19bd,
+ 0x6bb4, 0x0b7a,
+ 0x6bb5, 0x060d,
+ 0x6bb6, 0x3847,
+ 0x6bb7, 0x107a,
+ 0x6bb8, 0x3848,
+ 0x6bba, 0x210f,
+ 0x6bbb, 0x1fdb,
+ 0x6bbc, 0x384a,
+ 0x6bbf, 0x05cf,
+ 0x6bc0, 0x384d,
+ 0x6bc1, 0x07ee,
+ 0x6bc2, 0x19bf,
+ 0x6bc3, 0x384e,
+ 0x6bc5, 0x106a,
+ 0x6bc6, 0x20af,
+ 0x6bc7, 0x3850,
+ 0x6bcb, 0x0ef2,
+ 0x6bcc, 0x3854,
+ 0x6bcd, 0x0b1b,
+ 0x6bce, 0x3855,
+ 0x6bcf, 0x0ac4,
+ 0x6bd0, 0x3856,
+ 0x6bd2, 0x05fd,
+ 0x6bd3, 0x126f,
+ 0x6bd4, 0x0431,
+ 0x6bd5, 0x0438,
+ 0x6bd6, 0x043a,
+ 0x6bd7, 0x0bbf,
+ 0x6bd8, 0x3858,
+ 0x6bd9, 0x0439,
+ 0x6bda, 0x3859,
+ 0x6bdb, 0x0ab0,
+ 0x6bdc, 0x385a,
+ 0x6be1, 0x1152,
+ 0x6be2, 0x385f,
+ 0x6bea, 0x1954,
+ 0x6beb, 0x0778,
+ 0x6bec, 0x3867,
+ 0x6bef, 0x0e0d,
+ 0x6bf0, 0x386a,
+ 0x6bf3, 0x1955,
+ 0x6bf4, 0x386d,
+ 0x6bf5, 0x1957,
+ 0x6bf6, 0x386e,
+ 0x6bf9, 0x1958,
+ 0x6bfa, 0x3871,
+ 0x6bfd, 0x1956,
+ 0x6bfe, 0x3874,
+ 0x6bff, 0x24c0,
+ 0x6c00, 0x3875,
+ 0x6c05, 0x1959,
+ 0x6c06, 0x195b,
+ 0x6c07, 0x195a,
+ 0x6c08, 0x226d,
+ 0x6c09, 0x387a,
+ 0x6c0c, 0x24c1,
+ 0x6c0d, 0x195c,
+ 0x6c0e, 0x387d,
+ 0x6c0f, 0x0d66,
+ 0x6c10, 0x126b,
+ 0x6c11, 0x0af6,
+ 0x6c12, 0x387e,
+ 0x6c13, 0x0aaa,
+ 0x6c14, 0x0c17,
+ 0x6c15, 0x195d,
+ 0x6c16, 0x0b2d,
+ 0x6c17, 0x387f,
+ 0x6c18, 0x195e,
+ 0x6c1b, 0x0672,
+ 0x6c1c, 0x3880,
+ 0x6c1f, 0x0697,
+ 0x6c20, 0x3883,
+ 0x6c21, 0x1961,
+ 0x6c22, 0x0c5f,
+ 0x6c23, 0x20ca,
+ 0x6c24, 0x1963,
+ 0x6c25, 0x3884,
+ 0x6c26, 0x075b,
+ 0x6c27, 0x101e,
+ 0x6c28, 0x03bc,
+ 0x6c29, 0x1962,
+ 0x6c2a, 0x1964,
+ 0x6c2b, 0x20e7,
+ 0x6c2c, 0x24c2,
+ 0x6c2d, 0x3885,
+ 0x6c2e, 0x058b,
+ 0x6c2f, 0x0a6f,
+ 0x6c30, 0x0c65,
+ 0x6c31, 0x3886,
+ 0x6c32, 0x1965,
+ 0x6c33, 0x3887,
+ 0x6c34, 0x0da3,
+ 0x6c35, 0x169f,
+ 0x6c36, 0x3888,
+ 0x6c38, 0x10a5,
+ 0x6c39, 0x388a,
+ 0x6c3d, 0x12ef,
+ 0x6c3e, 0x388e,
+ 0x6c40, 0x0e52,
+ 0x6c41, 0x11ac,
+ 0x6c42, 0x0c70,
+ 0x6c43, 0x3890,
+ 0x6c46, 0x12f4,
+ 0x6c47, 0x07f8,
+ 0x6c48, 0x3893,
+ 0x6c49, 0x0771,
+ 0x6c4a, 0x16a2,
+ 0x6c4b, 0x3894,
+ 0x6c50, 0x0f18,
+ 0x6c51, 0x3899,
+ 0x6c54, 0x16a0,
+ 0x6c55, 0x0d00,
+ 0x6c56, 0x389c,
+ 0x6c57, 0x0770,
+ 0x6c58, 0x389d,
+ 0x6c5b, 0x0fdd,
+ 0x6c5c, 0x16a1,
+ 0x6c5d, 0x0cc5,
+ 0x6c5e, 0x0708,
+ 0x6c5f, 0x087e,
+ 0x6c60, 0x04fd,
+ 0x6c61, 0x0eea,
+ 0x6c62, 0x38a0,
+ 0x6c64, 0x0e13,
+ 0x6c65, 0x38a2,
+ 0x6c68, 0x16a8,
+ 0x6c6a, 0x0ea5,
+ 0x6c6b, 0x38a5,
+ 0x6c70, 0x0e00,
+ 0x6c71, 0x38aa,
+ 0x6c72, 0x0826,
+ 0x6c73, 0x38ab,
+ 0x6c74, 0x16aa,
+ 0x6c75, 0x38ac,
+ 0x6c76, 0x16ab,
+ 0x6c77, 0x38ad,
+ 0x6c79, 0x0fa5,
+ 0x6c7a, 0x38af,
+ 0x6c7d, 0x0c1a,
+ 0x6c7e, 0x0677,
+ 0x6c7f, 0x38b2,
+ 0x6c81, 0x0c5c,
+ 0x6c82, 0x1051,
+ 0x6c83, 0x0ee5,
+ 0x6c84, 0x38b4,
+ 0x6c85, 0x16a4,
+ 0x6c86, 0x16ac,
+ 0x6c87, 0x38b5,
+ 0x6c88, 0x0d2b,
+ 0x6c89, 0x04e6,
+ 0x6c8a, 0x38b6,
+ 0x6c8c, 0x16a7,
+ 0x6c8d, 0x38b8,
+ 0x6c8f, 0x0c02,
+ 0x6c90, 0x16a5,
+ 0x6c91, 0x38ba,
+ 0x6c93, 0x1a1f,
+ 0x6c94, 0x16a6,
+ 0x6c95, 0x38bc,
+ 0x6c99, 0x0cec,
+ 0x6c9a, 0x38c0,
+ 0x6c9b, 0x0ba7,
+ 0x6c9c, 0x38c1,
+ 0x6c9f, 0x070e,
+ 0x6ca0, 0x38c4,
+ 0x6ca1, 0x0ac0,
+ 0x6ca2, 0x38c5,
+ 0x6ca3, 0x16a3,
+ 0x6ca4, 0x0b7e,
+ 0x6ca5, 0x09ed,
+ 0x6ca6, 0x0a80,
+ 0x6ca7, 0x049e,
+ 0x6ca8, 0x38c6,
+ 0x6ca9, 0x16ad,
+ 0x6caa, 0x07bb,
+ 0x6cab, 0x0b10,
+ 0x6cac, 0x38c7,
+ 0x6cad, 0x16b0,
+ 0x6cae, 0x0909,
+ 0x6caf, 0x38c8,
+ 0x6cb1, 0x16bb,
+ 0x6cb2, 0x16b5,
+ 0x6cb3, 0x078a,
+ 0x6cb4, 0x38ca,
+ 0x6cb8, 0x066d,
+ 0x6cb9, 0x10b2,
+ 0x6cba, 0x38ce,
+ 0x6cbb, 0x11cd,
+ 0x6cbc, 0x1174,
+ 0x6cbd, 0x071a,
+ 0x6cbe, 0x1155,
+ 0x6cbf, 0x1001,
+ 0x6cc0, 0x38cf,
+ 0x6cc4, 0x0f84,
+ 0x6cc5, 0x0c73,
+ 0x6cc6, 0x38d3,
+ 0x6cc9, 0x0c85,
+ 0x6cca, 0x047b,
+ 0x6ccb, 0x38d6,
+ 0x6ccc, 0x0adf,
+ 0x6ccd, 0x38d7,
+ 0x6cd0, 0x16ae,
+ 0x6cd1, 0x38da,
+ 0x6cd3, 0x16bc,
+ 0x6cd4, 0x16af,
+ 0x6cd5, 0x0645,
+ 0x6cd6, 0x16b7,
+ 0x6cd7, 0x16b4,
+ 0x6cd8, 0x38dc,
+ 0x6cdb, 0x0657,
+ 0x6cdc, 0x38df,
+ 0x6cde, 0x0b63,
+ 0x6cdf, 0x38e1,
+ 0x6ce0, 0x16b6,
+ 0x6ce1, 0x0b9e,
+ 0x6ce2, 0x046f,
+ 0x6ce3, 0x0c1b,
+ 0x6ce4, 0x38e2,
+ 0x6ce5, 0x0b43,
+ 0x6ce6, 0x38e3,
+ 0x6ce8, 0x11ff,
+ 0x6ce9, 0x38e5,
+ 0x6cea, 0x09cc,
+ 0x6ceb, 0x16b9,
+ 0x6cec, 0x38e6,
+ 0x6cee, 0x16ba,
+ 0x6cef, 0x16bd,
+ 0x6cf0, 0x0dfc,
+ 0x6cf1, 0x16b3,
+ 0x6cf2, 0x38e8,
+ 0x6cf3, 0x10a3,
+ 0x6cf4, 0x38e9,
+ 0x6cf5, 0x042c,
+ 0x6cf6, 0x1a20,
+ 0x6cf7, 0x16b1,
+ 0x6cf9, 0x38ea,
+ 0x6cfa, 0x16b8,
+ 0x6cfb, 0x0f85,
+ 0x6cfc, 0x0be2,
+ 0x6cfd, 0x1136,
+ 0x6cfe, 0x16be,
+ 0x6cff, 0x38eb,
+ 0x6d00, 0x38ec,
+ 0x6d01, 0x08b1,
+ 0x6d02, 0x38ed,
+ 0x6d04, 0x16c5,
+ 0x6d05, 0x38ef,
+ 0x6d07, 0x16c4,
+ 0x6d08, 0x38f1,
+ 0x6d0b, 0x101c,
+ 0x6d0c, 0x16c1,
+ 0x6d0d, 0x38f4,
+ 0x6d0e, 0x16c7,
+ 0x6d0f, 0x38f5,
+ 0x6d12, 0x0cd2,
+ 0x6d13, 0x38f8,
+ 0x6d17, 0x0f21,
+ 0x6d18, 0x38fc,
+ 0x6d19, 0x16c6,
+ 0x6d1a, 0x16cc,
+ 0x6d1b, 0x0a8c,
+ 0x6d1c, 0x38fd,
+ 0x6d1e, 0x05f3,
+ 0x6d1f, 0x38ff,
+ 0x6d25, 0x08c3,
+ 0x6d26, 0x3905,
+ 0x6d27, 0x16c0,
+ 0x6d28, 0x3906,
+ 0x6d2a, 0x07a0,
+ 0x6d2b, 0x16c8,
+ 0x6d2c, 0x3908,
+ 0x6d2e, 0x16ca,
+ 0x6d2f, 0x390a,
+ 0x6d31, 0x063c,
+ 0x6d32, 0x11dd,
+ 0x6d33, 0x16d0,
+ 0x6d34, 0x390c,
+ 0x6d35, 0x16cb,
+ 0x6d36, 0x390d,
+ 0x6d39, 0x16bf,
+ 0x6d3a, 0x3910,
+ 0x6d3b, 0x0803,
+ 0x6d3c, 0x0e8e,
+ 0x6d3d, 0x0c1f,
+ 0x6d3e, 0x0b8a,
+ 0x6d3f, 0x3911,
+ 0x6d41, 0x0a40,
+ 0x6d42, 0x3913,
+ 0x6d43, 0x16c2,
+ 0x6d44, 0x3914,
+ 0x6d45, 0x0c30,
+ 0x6d46, 0x087d,
+ 0x6d47, 0x088e,
+ 0x6d48, 0x16c3,
+ 0x6d49, 0x3915,
+ 0x6d4a, 0x1224,
+ 0x6d4b, 0x04a9,
+ 0x6d4c, 0x3916,
+ 0x6d4d, 0x16c9,
+ 0x6d4e, 0x0836,
+ 0x6d4f, 0x16cd,
+ 0x6d50, 0x3917,
+ 0x6d51, 0x0800,
+ 0x6d52, 0x16ce,
+ 0x6d53, 0x0b69,
+ 0x6d54, 0x16cf,
+ 0x6d55, 0x3918,
+ 0x6d59, 0x1184,
+ 0x6d5a, 0x0930,
+ 0x6d5b, 0x391c,
+ 0x6d5c, 0x16d8,
+ 0x6d5d, 0x391d,
+ 0x6d5e, 0x16d5,
+ 0x6d5f, 0x391e,
+ 0x6d60, 0x16d9,
+ 0x6d61, 0x391f,
+ 0x6d63, 0x16db,
+ 0x6d64, 0x3921,
+ 0x6d66, 0x0bf5,
+ 0x6d67, 0x3923,
+ 0x6d69, 0x077d,
+ 0x6d6a, 0x09b6,
+ 0x6d6b, 0x3925,
+ 0x6d6e, 0x069c,
+ 0x6d6f, 0x16d2,
+ 0x6d70, 0x3928,
+ 0x6d74, 0x10e4,
+ 0x6d75, 0x392c,
+ 0x6d77, 0x075a,
+ 0x6d78, 0x08cf,
+ 0x6d79, 0x23dc,
+ 0x6d7a, 0x392e,
+ 0x6d7c, 0x16da,
+ 0x6d7d, 0x3930,
+ 0x6d82, 0x0e70,
+ 0x6d83, 0x3935,
+ 0x6d85, 0x0b5c,
+ 0x6d86, 0x3937,
+ 0x6d87, 0x23db,
+ 0x6d88, 0x0f68,
+ 0x6d89, 0x0d1f,
+ 0x6d8a, 0x3938,
+ 0x6d8c, 0x10a4,
+ 0x6d8d, 0x393a,
+ 0x6d8e, 0x0f3e,
+ 0x6d8f, 0x393b,
+ 0x6d91, 0x16d1,
+ 0x6d92, 0x393d,
+ 0x6d93, 0x16d6,
+ 0x6d95, 0x0e3c,
+ 0x6d96, 0x393e,
+ 0x6d9b, 0x0e21,
+ 0x6d9c, 0x3943,
+ 0x6d9d, 0x09bf,
+ 0x6d9e, 0x16d3,
+ 0x6d9f, 0x09f9,
+ 0x6da0, 0x16d4,
+ 0x6da1, 0x0edf,
+ 0x6da2, 0x3944,
+ 0x6da3, 0x07d6,
+ 0x6da4, 0x05b4,
+ 0x6da5, 0x3945,
+ 0x6da6, 0x0cce,
+ 0x6da7, 0x0878,
+ 0x6da8, 0x1168,
+ 0x6da9, 0x0ce5,
+ 0x6daa, 0x069d,
+ 0x6dab, 0x16e8,
+ 0x6dac, 0x3946,
+ 0x6dae, 0x16ea,
+ 0x6daf, 0x0fed,
+ 0x6db0, 0x3948,
+ 0x6db2, 0x1041,
+ 0x6db3, 0x394a,
+ 0x6db5, 0x0764,
+ 0x6db6, 0x394c,
+ 0x6db8, 0x078b,
+ 0x6db9, 0x394e,
+ 0x6dbf, 0x16e1,
+ 0x6dc0, 0x05ce,
+ 0x6dc1, 0x3954,
+ 0x6dc4, 0x122a,
+ 0x6dc5, 0x16de,
+ 0x6dc6, 0x0f6a,
+ 0x6dc7, 0x16dd,
+ 0x6dc8, 0x3957,
+ 0x6dcb, 0x0a25,
+ 0x6dcc, 0x0e1d,
+ 0x6dcd, 0x395a,
+ 0x6dd1, 0x0d7e,
+ 0x6dd2, 0x395e,
+ 0x6dd6, 0x0b3a,
+ 0x6dd7, 0x3962,
+ 0x6dd8, 0x0e27,
+ 0x6dd9, 0x16e6,
+ 0x6dda, 0x3963,
+ 0x6ddd, 0x16e5,
+ 0x6dde, 0x16df,
+ 0x6ddf, 0x3966,
+ 0x6de0, 0x16e2,
+ 0x6de1, 0x058e,
+ 0x6de2, 0x3967,
+ 0x6de4, 0x10be,
+ 0x6de5, 0x3969,
+ 0x6de6, 0x16e4,
+ 0x6de7, 0x396a,
+ 0x6dea, 0x205e,
+ 0x6deb, 0x1080,
+ 0x6dec, 0x0566,
+ 0x6ded, 0x396d,
+ 0x6dee, 0x07c9,
+ 0x6def, 0x396e,
+ 0x6df1, 0x0d27,
+ 0x6df2, 0x3970,
+ 0x6df3, 0x0541,
+ 0x6df4, 0x3971,
+ 0x6df5, 0x2244,
+ 0x6df6, 0x23e2,
+ 0x6df7, 0x0801,
+ 0x6df8, 0x3972,
+ 0x6df9, 0x0ff6,
+ 0x6dfa, 0x20d4,
+ 0x6dfb, 0x0e40,
+ 0x6dfc, 0x1a21,
+ 0x6dfd, 0x3973,
+ 0x6e00, 0x3976,
+ 0x6e05, 0x0c62,
+ 0x6e06, 0x397b,
+ 0x6e0a, 0x10eb,
+ 0x6e0b, 0x397f,
+ 0x6e0c, 0x16e9,
+ 0x6e0d, 0x1232,
+ 0x6e0e, 0x16e0,
+ 0x6e0f, 0x3980,
+ 0x6e10, 0x0876,
+ 0x6e11, 0x16e3,
+ 0x6e12, 0x3981,
+ 0x6e14, 0x10cb,
+ 0x6e15, 0x3983,
+ 0x6e16, 0x16e7,
+ 0x6e17, 0x0d31,
+ 0x6e18, 0x3984,
+ 0x6e1a, 0x16dc,
+ 0x6e1b, 0x3986,
+ 0x6e1d, 0x10ca,
+ 0x6e1e, 0x3988,
+ 0x6e20, 0x0c7b,
+ 0x6e21, 0x0608,
+ 0x6e22, 0x398a,
+ 0x6e23, 0x113f,
+ 0x6e24, 0x047a,
+ 0x6e25, 0x16f5,
+ 0x6e26, 0x219f,
+ 0x6e27, 0x398b,
+ 0x6e29, 0x0ed1,
+ 0x6e2a, 0x398d,
+ 0x6e2b, 0x16eb,
+ 0x6e2c, 0x1e66,
+ 0x6e2d, 0x0ecb,
+ 0x6e2e, 0x398e,
+ 0x6e2f, 0x06d6,
+ 0x6e30, 0x398f,
+ 0x6e32, 0x16f4,
+ 0x6e33, 0x3991,
+ 0x6e34, 0x0957,
+ 0x6e35, 0x3992,
+ 0x6e38, 0x10b3,
+ 0x6e39, 0x3995,
+ 0x6e3a, 0x0af1,
+ 0x6e3b, 0x3996,
+ 0x6e3e, 0x1f63,
+ 0x6e3f, 0x3999,
+ 0x6e43, 0x0b89,
+ 0x6e44, 0x16f6,
+ 0x6e45, 0x399d,
+ 0x6e4d, 0x0e75,
+ 0x6e4e, 0x16ed,
+ 0x6e4f, 0x39a5,
+ 0x6e53, 0x16f2,
+ 0x6e55, 0x39a9,
+ 0x6e56, 0x07b5,
+ 0x6e57, 0x39aa,
+ 0x6e58, 0x0f53,
+ 0x6e59, 0x39ab,
+ 0x6e5b, 0x1160,
+ 0x6e5c, 0x39ad,
+ 0x6e5e, 0x23dd,
+ 0x6e5f, 0x16f0,
+ 0x6e60, 0x39af,
+ 0x6e6b, 0x16ee,
+ 0x6e6c, 0x39ba,
+ 0x6e6e, 0x16ec,
+ 0x6e6f, 0x216b,
+ 0x6e70, 0x39bc,
+ 0x6e7e, 0x0e96,
+ 0x6e7f, 0x0d41,
+ 0x6e80, 0x39ca,
+ 0x6e83, 0x098e,
+ 0x6e84, 0x39cd,
+ 0x6e85, 0x0877,
+ 0x6e86, 0x16f1,
+ 0x6e87, 0x39ce,
+ 0x6e89, 0x06c3,
+ 0x6e8a, 0x39d0,
+ 0x6e8f, 0x1705,
+ 0x6e90, 0x10f7,
+ 0x6e91, 0x39d5,
+ 0x6e96, 0x22b5,
+ 0x6e97, 0x39da,
+ 0x6e98, 0x16f9,
+ 0x6e99, 0x39db,
+ 0x6e9c, 0x0a38,
+ 0x6e9d, 0x1f26,
+ 0x6e9e, 0x39de,
+ 0x6e9f, 0x1707,
+ 0x6ea0, 0x39df,
+ 0x6ea2, 0x106e,
+ 0x6ea3, 0x39e1,
+ 0x6ea5, 0x16fd,
+ 0x6ea6, 0x39e3,
+ 0x6ea7, 0x16fe,
+ 0x6ea8, 0x39e4,
+ 0x6eaa, 0x0f17,
+ 0x6eab, 0x39e6,
+ 0x6eaf, 0x0dd2,
+ 0x6eb0, 0x39ea,
+ 0x6eb1, 0x16f8,
+ 0x6eb2, 0x16ef,
+ 0x6eb3, 0x39eb,
+ 0x6eb4, 0x1703,
+ 0x6eb5, 0x39ec,
+ 0x6eb6, 0x0cb7,
+ 0x6eb7, 0x1701,
+ 0x6eb8, 0x39ed,
+ 0x6eba, 0x0b4a,
+ 0x6ebb, 0x1700,
+ 0x6ebc, 0x39ef,
+ 0x6ebd, 0x16ff,
+ 0x6ebe, 0x39f0,
+ 0x6ec1, 0x0521,
+ 0x6ec2, 0x1706,
+ 0x6ec3, 0x39f3,
+ 0x6ec4, 0x1e63,
+ 0x6ec5, 0x2088,
+ 0x6ec6, 0x39f4,
+ 0x6ec7, 0x05c2,
+ 0x6ec8, 0x39f5,
+ 0x6ecb, 0x1229,
+ 0x6ecc, 0x1ebd,
+ 0x6ecd, 0x39f8,
+ 0x6ece, 0x2341,
+ 0x6ecf, 0x1704,
+ 0x6ed0, 0x39f9,
+ 0x6ed1, 0x07c1,
+ 0x6ed2, 0x39fa,
+ 0x6ed3, 0x122f,
+ 0x6ed4, 0x0e22,
+ 0x6ed5, 0x19a8,
+ 0x6ed6, 0x39fb,
+ 0x6ed7, 0x1702,
+ 0x6ed8, 0x39fc,
+ 0x6eda, 0x074f,
+ 0x6edb, 0x39fe,
+ 0x6ede, 0x11cc,
+ 0x6edf, 0x16f7,
+ 0x6ee0, 0x16fa,
+ 0x6ee1, 0x0aa1,
+ 0x6ee2, 0x16fc,
+ 0x6ee3, 0x3a01,
+ 0x6ee4, 0x0a72,
+ 0x6ee5, 0x09af,
+ 0x6ee6, 0x0a77,
+ 0x6ee7, 0x3a02,
+ 0x6ee8, 0x045e,
+ 0x6ee9, 0x0e05,
+ 0x6eea, 0x3a03,
+ 0x6eec, 0x1f4b,
+ 0x6eed, 0x3a05,
+ 0x6eef, 0x2292,
+ 0x6ef0, 0x3a07,
+ 0x6ef2, 0x2124,
+ 0x6ef3, 0x3a09,
+ 0x6ef4, 0x05af,
+ 0x6ef5, 0x3a0a,
+ 0x6ef7, 0x2048,
+ 0x6ef8, 0x23e0,
+ 0x6ef9, 0x170d,
+ 0x6efa, 0x3a0c,
+ 0x6eff, 0x2077,
+ 0x6f00, 0x3a11,
+ 0x6f01, 0x223a,
+ 0x6f02, 0x0bce,
+ 0x6f03, 0x3a12,
+ 0x6f06, 0x0c00,
+ 0x6f07, 0x3a15,
+ 0x6f09, 0x1713,
+ 0x6f0a, 0x3a17,
+ 0x6f0f, 0x0a50,
+ 0x6f10, 0x3a1c,
+ 0x6f13, 0x09d7,
+ 0x6f14, 0x1006,
+ 0x6f15, 0x170c,
+ 0x6f16, 0x3a1f,
+ 0x6f1a, 0x20b1,
+ 0x6f1b, 0x3a23,
+ 0x6f20, 0x0b11,
+ 0x6f21, 0x3a28,
+ 0x6f22, 0x1f41,
+ 0x6f23, 0x201c,
+ 0x6f24, 0x170b,
+ 0x6f25, 0x3a29,
+ 0x6f29, 0x1714,
+ 0x6f2a, 0x1712,
+ 0x6f2b, 0x0aa5,
+ 0x6f2c, 0x22b8,
+ 0x6f2d, 0x16fb,
+ 0x6f2e, 0x3a2d,
+ 0x6f2f, 0x170e,
+ 0x6f30, 0x3a2e,
+ 0x6f31, 0x0d95,
+ 0x6f32, 0x2276,
+ 0x6f33, 0x1165,
+ 0x6f34, 0x3a2f,
+ 0x6f36, 0x170f,
+ 0x6f37, 0x3a31,
+ 0x6f38, 0x1f9b,
+ 0x6f39, 0x3a32,
+ 0x6f3e, 0x1023,
+ 0x6f3f, 0x1f9f,
+ 0x6f40, 0x3a37,
+ 0x6f41, 0x25ca,
+ 0x6f42, 0x3a38,
+ 0x6f46, 0x1709,
+ 0x6f48, 0x3a3c,
+ 0x6f4b, 0x1710,
+ 0x6f4c, 0x3a3f,
+ 0x6f4d, 0x0eba,
+ 0x6f4e, 0x3a40,
+ 0x6f51, 0x20be,
+ 0x6f52, 0x3a43,
+ 0x6f54, 0x1fb4,
+ 0x6f55, 0x3a45,
+ 0x6f58, 0x0b8c,
+ 0x6f59, 0x23d7,
+ 0x6f5a, 0x3a48,
+ 0x6f5c, 0x0c2e,
+ 0x6f5d, 0x3a4a,
+ 0x6f5e, 0x0a61,
+ 0x6f5f, 0x3a4b,
+ 0x6f62, 0x1708,
+ 0x6f63, 0x3a4e,
+ 0x6f64, 0x2105,
+ 0x6f65, 0x3a4f,
+ 0x6f66, 0x0a13,
+ 0x6f67, 0x3a50,
+ 0x6f6d, 0x0e09,
+ 0x6f6e, 0x04d6,
+ 0x6f6f, 0x23e1,
+ 0x6f70, 0x1fec,
+ 0x6f71, 0x3a56,
+ 0x6f72, 0x1719,
+ 0x6f73, 0x3a57,
+ 0x6f74, 0x1711,
+ 0x6f75, 0x3a58,
+ 0x6f77, 0x23ea,
+ 0x6f78, 0x1718,
+ 0x6f79, 0x3a5a,
+ 0x6f7a, 0x171b,
+ 0x6f7b, 0x3a5b,
+ 0x6f7c, 0x171a,
+ 0x6f7d, 0x3a5c,
+ 0x6f7f, 0x23e3,
+ 0x6f80, 0x210e,
+ 0x6f81, 0x3a5e,
+ 0x6f84, 0x04f3,
+ 0x6f85, 0x3a61,
+ 0x6f86, 0x1fa6,
+ 0x6f87, 0x2004,
+ 0x6f88, 0x04df,
+ 0x6f89, 0x1715,
+ 0x6f8a, 0x3a62,
+ 0x6f8c, 0x1717,
+ 0x6f8d, 0x1716,
+ 0x6f8e, 0x0bad,
+ 0x6f8f, 0x3a64,
+ 0x6f97, 0x1f9d,
+ 0x6f98, 0x3a6c,
+ 0x6f9c, 0x09a8,
+ 0x6f9d, 0x3a70,
+ 0x6fa0, 0x23e5,
+ 0x6fa1, 0x112b,
+ 0x6fa2, 0x3a73,
+ 0x6fa4, 0x2264,
+ 0x6fa5, 0x3a75,
+ 0x6fa7, 0x171e,
+ 0x6fa8, 0x3a77,
+ 0x6fa9, 0x24e2,
+ 0x6faa, 0x3a78,
+ 0x6fae, 0x23de,
+ 0x6faf, 0x3a7c,
+ 0x6fb1, 0x1ec4,
+ 0x6fb2, 0x3a7e,
+ 0x6fb3, 0x03cf,
+ 0x6fb4, 0x3a7f,
+ 0x6fb6, 0x1720,
+ 0x6fb7, 0x3a81,
+ 0x6fb9, 0x171f,
+ 0x6fba, 0x3a83,
+ 0x6fc0, 0x0817,
+ 0x6fc1, 0x22b6,
+ 0x6fc2, 0x1721,
+ 0x6fc3, 0x20a9,
+ 0x6fc4, 0x3a89,
+ 0x6fc9, 0x171d,
+ 0x6fca, 0x3a8e,
+ 0x6fd1, 0x171c,
+ 0x6fd2, 0x045d,
+ 0x6fd3, 0x3a95,
+ 0x6fd5, 0x212b,
+ 0x6fd6, 0x3a97,
+ 0x6fd8, 0x20a5,
+ 0x6fd9, 0x3a99,
+ 0x6fdb, 0x268b,
+ 0x6fdc, 0x3a9b,
+ 0x6fde, 0x1724,
+ 0x6fdf, 0x1f76,
+ 0x6fe0, 0x1725,
+ 0x6fe1, 0x1722,
+ 0x6fe2, 0x3a9d,
+ 0x6fe4, 0x216d,
+ 0x6fe5, 0x3a9f,
+ 0x6feb, 0x2001,
+ 0x6fec, 0x3aa5,
+ 0x6fee, 0x1723,
+ 0x6fef, 0x1726,
+ 0x6ff0, 0x2191,
+ 0x6ff1, 0x1e50,
+ 0x6ff2, 0x3aa7,
+ 0x6ffa, 0x1f9c,
+ 0x6ffb, 0x3aaf,
+ 0x6ffc, 0x23da,
+ 0x6ffd, 0x3ab0,
+ 0x6ffe, 0x2053,
+ 0x6fff, 0x3ab1,
+ 0x7000, 0x3ab2,
+ 0x7005, 0x23e9,
+ 0x7006, 0x23e4,
+ 0x7007, 0x3ab7,
+ 0x7009, 0x21d5,
+ 0x700a, 0x3ab9,
+ 0x700b, 0x23e6,
+ 0x700c, 0x3aba,
+ 0x700f, 0x23df,
+ 0x7010, 0x3abd,
+ 0x7011, 0x0bf8,
+ 0x7012, 0x3abe,
+ 0x7015, 0x1e4f,
+ 0x7016, 0x3ac1,
+ 0x7018, 0x23d9,
+ 0x7019, 0x3ac3,
+ 0x701a, 0x1727,
+ 0x701b, 0x1729,
+ 0x701c, 0x3ac4,
+ 0x701d, 0x2014,
+ 0x701e, 0x3ac5,
+ 0x701f, 0x23ec,
+ 0x7020, 0x23eb,
+ 0x7021, 0x3ac6,
+ 0x7023, 0x1728,
+ 0x7024, 0x3ac8,
+ 0x7027, 0x23d8,
+ 0x7028, 0x23ee,
+ 0x7029, 0x3acb,
+ 0x7030, 0x268e,
+ 0x7031, 0x3ad2,
+ 0x7032, 0x23ed,
+ 0x7033, 0x3ad3,
+ 0x7035, 0x172b,
+ 0x7036, 0x3ad5,
+ 0x7039, 0x172a,
+ 0x703a, 0x3ad8,
+ 0x703e, 0x1ffa,
+ 0x703f, 0x3adc,
+ 0x7043, 0x23d6,
+ 0x7044, 0x23e8,
+ 0x7045, 0x3ae0,
+ 0x704c, 0x0739,
+ 0x704d, 0x3ae7,
+ 0x704f, 0x172c,
+ 0x7050, 0x3ae9,
+ 0x7051, 0x2106,
+ 0x7052, 0x3aea,
+ 0x7055, 0x200b,
+ 0x7056, 0x3aed,
+ 0x7058, 0x2166,
+ 0x7059, 0x3aef,
+ 0x705d, 0x23ef,
+ 0x705e, 0x172d,
+ 0x705f, 0x3af3,
+ 0x7063, 0x2189,
+ 0x7064, 0x2058,
+ 0x7065, 0x3af7,
+ 0x7067, 0x23e7,
+ 0x7068, 0x3af9,
+ 0x706b, 0x0805,
+ 0x706c, 0x19ef,
+ 0x706d, 0x0af5,
+ 0x706e, 0x3afc,
+ 0x706f, 0x05a7,
+ 0x7070, 0x07e7,
+ 0x7071, 0x3afd,
+ 0x7075, 0x0a32,
+ 0x7076, 0x1131,
+ 0x7077, 0x3b01,
+ 0x7078, 0x08f3,
+ 0x7079, 0x3b02,
+ 0x707c, 0x1223,
+ 0x707d, 0x3b05,
+ 0x707e, 0x1119,
+ 0x707f, 0x049a,
+ 0x7080, 0x19cc,
+ 0x7081, 0x3b06,
+ 0x7085, 0x1913,
+ 0x7086, 0x3b0a,
+ 0x7089, 0x0a56,
+ 0x708a, 0x0539,
+ 0x708b, 0x3b0d,
+ 0x708e, 0x1000,
+ 0x708f, 0x3b10,
+ 0x7092, 0x04d9,
+ 0x7093, 0x3b13,
+ 0x7094, 0x0c8d,
+ 0x7095, 0x0948,
+ 0x7096, 0x19ce,
+ 0x7097, 0x3b14,
+ 0x7099, 0x11ca,
+ 0x709a, 0x3b16,
+ 0x709c, 0x19cd,
+ 0x709d, 0x19cf,
+ 0x709e, 0x3b18,
+ 0x70ab, 0x19d3,
+ 0x70ac, 0x0915,
+ 0x70ad, 0x0e12,
+ 0x70ae, 0x0b9b,
+ 0x70af, 0x08eb,
+ 0x70b0, 0x3b25,
+ 0x70b1, 0x19d4,
+ 0x70b2, 0x3b26,
+ 0x70b3, 0x0467,
+ 0x70b4, 0x3b27,
+ 0x70b7, 0x19d2,
+ 0x70b8, 0x1149,
+ 0x70b9, 0x05c4,
+ 0x70ba, 0x3b2a,
+ 0x70bb, 0x19d0,
+ 0x70bc, 0x09ff,
+ 0x70bd, 0x0508,
+ 0x70be, 0x3b2b,
+ 0x70c0, 0x19d1,
+ 0x70c1, 0x0dad,
+ 0x70c2, 0x09ae,
+ 0x70c3, 0x0e51,
+ 0x70c4, 0x3b2d,
+ 0x70c8, 0x0a1b,
+ 0x70c9, 0x3b31,
+ 0x70ca, 0x19d6,
+ 0x70cb, 0x3b32,
+ 0x70cf, 0x21a3,
+ 0x70d0, 0x3b36,
+ 0x70d8, 0x079d,
+ 0x70d9, 0x09be,
+ 0x70da, 0x3b3e,
+ 0x70db, 0x11f1,
+ 0x70dc, 0x3b3f,
+ 0x70df, 0x0ff5,
+ 0x70e0, 0x3b42,
+ 0x70e4, 0x094b,
+ 0x70e5, 0x3b46,
+ 0x70e6, 0x0650,
+ 0x70e7, 0x0d0e,
+ 0x70e8, 0x19d5,
+ 0x70e9, 0x07f7,
+ 0x70ea, 0x3b47,
+ 0x70eb, 0x0e1f,
+ 0x70ec, 0x08ce,
+ 0x70ed, 0x0ca3,
+ 0x70ee, 0x3b48,
+ 0x70ef, 0x0f16,
+ 0x70f0, 0x3b49,
+ 0x70f4, 0x217a,
+ 0x70f5, 0x3b4d,
+ 0x70f7, 0x0e9a,
+ 0x70f8, 0x3b4f,
+ 0x70f9, 0x0bac,
+ 0x70fa, 0x3b50,
+ 0x70fd, 0x0686,
+ 0x70fe, 0x3b53,
+ 0x7100, 0x3b55,
+ 0x7109, 0x0ff2,
+ 0x710a, 0x076f,
+ 0x710b, 0x3b5e,
+ 0x7110, 0x19d7,
+ 0x7111, 0x3b63,
+ 0x7113, 0x19d8,
+ 0x7114, 0x3b65,
+ 0x7115, 0x07d5,
+ 0x7116, 0x19d9,
+ 0x7117, 0x3b66,
+ 0x7118, 0x19f0,
+ 0x7119, 0x0423,
+ 0x711a, 0x0676,
+ 0x711b, 0x3b67,
+ 0x7121, 0x21a5,
+ 0x7122, 0x3b6d,
+ 0x7126, 0x088a,
+ 0x7127, 0x3b71,
+ 0x712f, 0x19da,
+ 0x7130, 0x100f,
+ 0x7131, 0x19db,
+ 0x7132, 0x3b79,
+ 0x7136, 0x0c96,
+ 0x7137, 0x3b7d,
+ 0x7145, 0x19df,
+ 0x7146, 0x3b8b,
+ 0x7149, 0x2022,
+ 0x714a, 0x19e1,
+ 0x714b, 0x3b8e,
+ 0x714c, 0x07e2,
+ 0x714d, 0x3b8f,
+ 0x714e, 0x0858,
+ 0x714f, 0x3b90,
+ 0x7152, 0x24d6,
+ 0x7153, 0x3b93,
+ 0x715c, 0x19dd,
+ 0x715d, 0x3b9c,
+ 0x715e, 0x0cf0,
+ 0x715f, 0x3b9d,
+ 0x7162, 0x233a,
+ 0x7163, 0x3ba0,
+ 0x7164, 0x0abf,
+ 0x7165, 0x3ba1,
+ 0x7166, 0x19f1,
+ 0x7167, 0x1176,
+ 0x7168, 0x19de,
+ 0x7169, 0x1eee,
+ 0x716a, 0x3ba2,
+ 0x716c, 0x24d5,
+ 0x716d, 0x3ba4,
+ 0x716e, 0x11f2,
+ 0x716f, 0x3ba5,
+ 0x7172, 0x19e0,
+ 0x7173, 0x19dc,
+ 0x7174, 0x3ba8,
+ 0x7178, 0x19e2,
+ 0x7179, 0x3bac,
+ 0x717a, 0x19e3,
+ 0x717b, 0x3bad,
+ 0x717d, 0x0cf8,
+ 0x717e, 0x3baf,
+ 0x7184, 0x0f15,
+ 0x7185, 0x3bb5,
+ 0x718a, 0x0fa7,
+ 0x718b, 0x3bba,
+ 0x718f, 0x0fd5,
+ 0x7190, 0x3bbe,
+ 0x7192, 0x2228,
+ 0x7193, 0x3bc0,
+ 0x7194, 0x0cb6,
+ 0x7195, 0x3bc1,
+ 0x7197, 0x24d7,
+ 0x7198, 0x19e4,
+ 0x7199, 0x0f04,
+ 0x719a, 0x3bc3,
+ 0x719f, 0x0d83,
+ 0x71a0, 0x19e8,
+ 0x71a1, 0x3bc8,
+ 0x71a8, 0x19e7,
+ 0x71a9, 0x3bcf,
+ 0x71ac, 0x03c9,
+ 0x71ad, 0x3bd2,
+ 0x71b1, 0x20fc,
+ 0x71b2, 0x3bd6,
+ 0x71b3, 0x19e5,
+ 0x71b4, 0x3bd7,
+ 0x71b5, 0x19e6,
+ 0x71b6, 0x3bd8,
+ 0x71b9, 0x19f2,
+ 0x71ba, 0x3bdb,
+ 0x71be, 0x1e87,
+ 0x71bf, 0x3bdf,
+ 0x71c1, 0x24d8,
+ 0x71c2, 0x3be1,
+ 0x71c3, 0x0c97,
+ 0x71c4, 0x3be2,
+ 0x71c8, 0x1eba,
+ 0x71c9, 0x3be6,
+ 0x71ce, 0x0a10,
+ 0x71cf, 0x3beb,
+ 0x71d2, 0x2119,
+ 0x71d3, 0x3bee,
+ 0x71d4, 0x19ea,
+ 0x71d5, 0x1009,
+ 0x71d6, 0x3bef,
+ 0x71d9, 0x216c,
+ 0x71da, 0x3bf2,
+ 0x71dc, 0x24d9,
+ 0x71dd, 0x3bf4,
+ 0x71df, 0x2227,
+ 0x71e0, 0x19e9,
+ 0x71e1, 0x3bf6,
+ 0x71e5, 0x1132,
+ 0x71e6, 0x1e5f,
+ 0x71e7, 0x19eb,
+ 0x71e8, 0x3bfa,
+ 0x71ed, 0x229f,
+ 0x71ee, 0x1396,
+ 0x71ef, 0x3bff,
+ 0x71f4, 0x1f5d,
+ 0x71f5, 0x3c04,
+ 0x71f9, 0x19ec,
+ 0x71fa, 0x3c08,
+ 0x71fc, 0x1fbc,
+ 0x71fd, 0x3c0a,
+ 0x71fe, 0x24da,
+ 0x71ff, 0x3c0b,
+ 0x7200, 0x3c0c,
+ 0x7206, 0x0415,
+ 0x7207, 0x3c12,
+ 0x720d, 0x2149,
+ 0x720e, 0x3c18,
+ 0x7210, 0x2046,
+ 0x7211, 0x3c1a,
+ 0x721b, 0x2000,
+ 0x721c, 0x3c24,
+ 0x721d, 0x19ed,
+ 0x721e, 0x3c25,
+ 0x7228, 0x19ee,
+ 0x7229, 0x3c2f,
+ 0x722a, 0x1203,
+ 0x722b, 0x3c30,
+ 0x722c, 0x0b81,
+ 0x722d, 0x3c31,
+ 0x7230, 0x196c,
+ 0x7231, 0x03b9,
+ 0x7232, 0x2190,
+ 0x7233, 0x3c34,
+ 0x7235, 0x0923,
+ 0x7236, 0x06b3,
+ 0x7237, 0x1036,
+ 0x7238, 0x03e1,
+ 0x7239, 0x05da,
+ 0x723a, 0x2208,
+ 0x723b, 0x1269,
+ 0x723c, 0x3c36,
+ 0x723d, 0x0da1,
+ 0x723e, 0x1ee6,
+ 0x723f, 0x169d,
+ 0x7240, 0x3c37,
+ 0x7247, 0x0bcb,
+ 0x7248, 0x03f1,
+ 0x7249, 0x3c3e,
+ 0x724c, 0x0b87,
+ 0x724d, 0x1969,
+ 0x724e, 0x3c41,
+ 0x7252, 0x196a,
+ 0x7253, 0x3c45,
+ 0x7256, 0x196b,
+ 0x7257, 0x3c48,
+ 0x7258, 0x24c3,
+ 0x7259, 0x0fe9,
+ 0x725a, 0x3c49,
+ 0x725b, 0x0b64,
+ 0x725c, 0x3c4a,
+ 0x725d, 0x1944,
+ 0x725e, 0x3c4b,
+ 0x725f, 0x0b15,
+ 0x7260, 0x3c4c,
+ 0x7261, 0x0b18,
+ 0x7262, 0x09b9,
+ 0x7263, 0x3c4d,
+ 0x7266, 0x1945,
+ 0x7267, 0x0b24,
+ 0x7268, 0x3c50,
+ 0x7269, 0x0efe,
+ 0x726a, 0x3c51,
+ 0x726e, 0x1942,
+ 0x726f, 0x1946,
+ 0x7270, 0x3c55,
+ 0x7272, 0x0d35,
+ 0x7273, 0x3c57,
+ 0x7275, 0x0c20,
+ 0x7276, 0x3c59,
+ 0x7279, 0x0e2b,
+ 0x727a, 0x0f0d,
+ 0x727b, 0x3c5c,
+ 0x727d, 0x20cc,
+ 0x727e, 0x1947,
+ 0x7280, 0x0f19,
+ 0x7281, 0x09d2,
+ 0x7282, 0x3c5e,
+ 0x7284, 0x1949,
+ 0x7285, 0x3c60,
+ 0x728a, 0x05fe,
+ 0x728b, 0x194a,
+ 0x728c, 0x3c65,
+ 0x728d, 0x194b,
+ 0x728e, 0x3c66,
+ 0x728f, 0x194c,
+ 0x7290, 0x3c67,
+ 0x7292, 0x194d,
+ 0x7293, 0x3c69,
+ 0x7296, 0x2340,
+ 0x7297, 0x3c6c,
+ 0x729f, 0x1943,
+ 0x72a0, 0x3c74,
+ 0x72a2, 0x1ed1,
+ 0x72a3, 0x3c76,
+ 0x72a7, 0x21ac,
+ 0x72a8, 0x3c7a,
+ 0x72ac, 0x0c89,
+ 0x72ad, 0x15ef,
+ 0x72ae, 0x3c7e,
+ 0x72af, 0x0655,
+ 0x72b0, 0x15f0,
+ 0x72b1, 0x3c7f,
+ 0x72b4, 0x15f1,
+ 0x72b5, 0x3c82,
+ 0x72b6, 0x1211,
+ 0x72b7, 0x15f2,
+ 0x72b9, 0x10b1,
+ 0x72ba, 0x3c83,
+ 0x72c0, 0x22af,
+ 0x72c1, 0x15f5,
+ 0x72c2, 0x097e,
+ 0x72c3, 0x15f4,
+ 0x72c4, 0x05b3,
+ 0x72c5, 0x3c89,
+ 0x72c8, 0x0420,
+ 0x72c9, 0x3c8c,
+ 0x72cd, 0x15f7,
+ 0x72ce, 0x15f6,
+ 0x72cf, 0x3c90,
+ 0x72d0, 0x07b3,
+ 0x72d1, 0x3c91,
+ 0x72d2, 0x15f8,
+ 0x72d3, 0x3c92,
+ 0x72d7, 0x0710,
+ 0x72d8, 0x3c96,
+ 0x72d9, 0x0900,
+ 0x72da, 0x3c97,
+ 0x72de, 0x0b5f,
+ 0x72df, 0x3c9b,
+ 0x72e0, 0x0794,
+ 0x72e1, 0x0897,
+ 0x72e2, 0x3c9c,
+ 0x72e8, 0x15f9,
+ 0x72e9, 0x15fb,
+ 0x72ea, 0x3ca2,
+ 0x72ec, 0x05ff,
+ 0x72ed, 0x0f2e,
+ 0x72ee, 0x0d3f,
+ 0x72ef, 0x15fa,
+ 0x72f0, 0x1199,
+ 0x72f1, 0x10e1,
+ 0x72f2, 0x15fc,
+ 0x72f3, 0x1600,
+ 0x72f4, 0x15fd,
+ 0x72f5, 0x3ca4,
+ 0x72f7, 0x15fe,
+ 0x72f8, 0x09d5,
+ 0x72f9, 0x21b6,
+ 0x72fa, 0x1602,
+ 0x72fc, 0x09b2,
+ 0x72fd, 0x1e3d,
+ 0x72fe, 0x3ca6,
+ 0x7300, 0x3ca8,
+ 0x7301, 0x15ff,
+ 0x7302, 0x3ca9,
+ 0x7303, 0x1601,
+ 0x7304, 0x3caa,
+ 0x730a, 0x1607,
+ 0x730b, 0x3cb0,
+ 0x730e, 0x0a1d,
+ 0x730f, 0x3cb3,
+ 0x7313, 0x1605,
+ 0x7314, 0x3cb7,
+ 0x7315, 0x160a,
+ 0x7316, 0x04c5,
+ 0x7317, 0x1604,
+ 0x7318, 0x3cb8,
+ 0x731b, 0x0ad2,
+ 0x731c, 0x0489,
+ 0x731d, 0x1609,
+ 0x731e, 0x1608,
+ 0x731f, 0x3cbb,
+ 0x7321, 0x1606,
+ 0x7322, 0x160b,
+ 0x7323, 0x3cbd,
+ 0x7325, 0x160d,
+ 0x7326, 0x3cbf,
+ 0x7329, 0x0f94,
+ 0x732a, 0x11ec,
+ 0x732b, 0x0aad,
+ 0x732c, 0x160e,
+ 0x732d, 0x3cc2,
+ 0x732e, 0x0f44,
+ 0x732f, 0x3cc3,
+ 0x7331, 0x1610,
+ 0x7332, 0x3cc5,
+ 0x7334, 0x07a6,
+ 0x7335, 0x3cc7,
+ 0x7336, 0x2235,
+ 0x7337, 0x18d4,
+ 0x7338, 0x160f,
+ 0x7339, 0x160c,
+ 0x733a, 0x3cc8,
+ 0x733b, 0x2397,
+ 0x733c, 0x3cc9,
+ 0x733e, 0x07c0,
+ 0x733f, 0x10f6,
+ 0x7340, 0x3ccb,
+ 0x7341, 0x2395,
+ 0x7342, 0x3ccc,
+ 0x7344, 0x223f,
+ 0x7345, 0x212a,
+ 0x7346, 0x3cce,
+ 0x734d, 0x1612,
+ 0x734e, 0x3cd5,
+ 0x7350, 0x1611,
+ 0x7351, 0x3cd7,
+ 0x7352, 0x18d5,
+ 0x7353, 0x3cd8,
+ 0x7357, 0x1613,
+ 0x7358, 0x3cdc,
+ 0x7360, 0x1614,
+ 0x7361, 0x3ce4,
+ 0x7368, 0x1ed2,
+ 0x7369, 0x3ceb,
+ 0x736a, 0x2396,
+ 0x736b, 0x2398,
+ 0x736c, 0x1615,
+ 0x736d, 0x0df4,
+ 0x736e, 0x3cec,
+ 0x736f, 0x1616,
+ 0x7370, 0x20a2,
+ 0x7371, 0x3ced,
+ 0x7372, 0x1f64,
+ 0x7373, 0x3cee,
+ 0x7375, 0x202b,
+ 0x7376, 0x3cf0,
+ 0x7377, 0x2394,
+ 0x7378, 0x2139,
+ 0x7379, 0x3cf1,
+ 0x737a, 0x215f,
+ 0x737b, 0x21c1,
+ 0x737c, 0x239a,
+ 0x737d, 0x3cf2,
+ 0x737e, 0x1617,
+ 0x737f, 0x3cf3,
+ 0x7380, 0x2399,
+ 0x7381, 0x3cf4,
+ 0x7384, 0x0fc9,
+ 0x7385, 0x3cf7,
+ 0x7387, 0x0a71,
+ 0x7388, 0x3cf9,
+ 0x7389, 0x10d6,
+ 0x738a, 0x3cfa,
+ 0x738b, 0x0ea6,
+ 0x738c, 0x3cfb,
+ 0x738e, 0x1818,
+ 0x738f, 0x3cfd,
+ 0x7391, 0x1819,
+ 0x7392, 0x3cff,
+ 0x7396, 0x08f0,
+ 0x7397, 0x3d03,
+ 0x739b, 0x0a91,
+ 0x739c, 0x3d07,
+ 0x739f, 0x181c,
+ 0x73a0, 0x3d0a,
+ 0x73a2, 0x181b,
+ 0x73a3, 0x3d0c,
+ 0x73a9, 0x0e97,
+ 0x73aa, 0x3d12,
+ 0x73ab, 0x0aba,
+ 0x73ac, 0x3d13,
+ 0x73ae, 0x181a,
+ 0x73af, 0x07cc,
+ 0x73b0, 0x0f43,
+ 0x73b1, 0x3d15,
+ 0x73b2, 0x0a2a,
+ 0x73b3, 0x1821,
+ 0x73b4, 0x3d16,
+ 0x73b7, 0x1820,
+ 0x73b8, 0x3d19,
+ 0x73ba, 0x182c,
+ 0x73bb, 0x046a,
+ 0x73bc, 0x3d1b,
+ 0x73c0, 0x1822,
+ 0x73c1, 0x3d1f,
+ 0x73c2, 0x181e,
+ 0x73c3, 0x3d20,
+ 0x73c8, 0x1824,
+ 0x73c9, 0x1823,
+ 0x73ca, 0x0cf3,
+ 0x73cb, 0x3d25,
+ 0x73cd, 0x1185,
+ 0x73ce, 0x3d27,
+ 0x73cf, 0x181d,
+ 0x73d0, 0x0646,
+ 0x73d1, 0x181f,
+ 0x73d2, 0x3d28,
+ 0x73d9, 0x1826,
+ 0x73da, 0x3d2f,
+ 0x73de, 0x182b,
+ 0x73df, 0x3d33,
+ 0x73e0, 0x11e8,
+ 0x73e1, 0x3d34,
+ 0x73e5, 0x1825,
+ 0x73e6, 0x3d38,
+ 0x73e7, 0x182a,
+ 0x73e8, 0x3d39,
+ 0x73e9, 0x1829,
+ 0x73ea, 0x3d3a,
+ 0x73ed, 0x03eb,
+ 0x73ee, 0x3d3d,
+ 0x73f2, 0x182d,
+ 0x73f3, 0x3d41,
+ 0x73fe, 0x21c0,
+ 0x73ff, 0x3d4c,
+ 0x7400, 0x3d4d,
+ 0x7403, 0x0c6f,
+ 0x7404, 0x3d50,
+ 0x7405, 0x09b0,
+ 0x7406, 0x09d8,
+ 0x7407, 0x3d51,
+ 0x7409, 0x0a39,
+ 0x740a, 0x1828,
+ 0x740b, 0x3d53,
+ 0x740f, 0x182e,
+ 0x7410, 0x0deb,
+ 0x7411, 0x3d57,
+ 0x741a, 0x1838,
+ 0x741b, 0x1837,
+ 0x741c, 0x3d60,
+ 0x7422, 0x121e,
+ 0x7423, 0x3d66,
+ 0x7425, 0x1832,
+ 0x7426, 0x1831,
+ 0x7427, 0x3d68,
+ 0x7428, 0x1833,
+ 0x7429, 0x3d69,
+ 0x742a, 0x182f,
+ 0x742b, 0x3d6a,
+ 0x742c, 0x1836,
+ 0x742d, 0x3d6b,
+ 0x742e, 0x1835,
+ 0x742f, 0x3d6c,
+ 0x7430, 0x1834,
+ 0x7431, 0x3d6d,
+ 0x7433, 0x0a1e,
+ 0x7434, 0x0c56,
+ 0x7435, 0x0bbe,
+ 0x7436, 0x0b84,
+ 0x7437, 0x3d6f,
+ 0x743c, 0x0c6a,
+ 0x743d, 0x3d74,
+ 0x743f, 0x2460,
+ 0x7440, 0x3d76,
+ 0x7441, 0x1839,
+ 0x7442, 0x3d77,
+ 0x744b, 0x245c,
+ 0x744c, 0x3d80,
+ 0x7455, 0x183c,
+ 0x7456, 0x3d89,
+ 0x7457, 0x183b,
+ 0x7458, 0x3d8a,
+ 0x7459, 0x183d,
+ 0x745a, 0x07ae,
+ 0x745b, 0x1830,
+ 0x745c, 0x183a,
+ 0x745d, 0x3d8b,
+ 0x745e, 0x0ccb,
+ 0x745f, 0x0ce3,
+ 0x7460, 0x3d8c,
+ 0x7463, 0x215d,
+ 0x7464, 0x3d8f,
+ 0x7469, 0x2225,
+ 0x746a, 0x206a,
+ 0x746b, 0x3d94,
+ 0x746d, 0x183f,
+ 0x746e, 0x3d96,
+ 0x7470, 0x073e,
+ 0x7471, 0x3d98,
+ 0x7476, 0x1027,
+ 0x7477, 0x183e,
+ 0x7478, 0x3d9d,
+ 0x747e, 0x1840,
+ 0x747f, 0x3da3,
+ 0x7480, 0x1843,
+ 0x7482, 0x3da4,
+ 0x7483, 0x09f0,
+ 0x7484, 0x3da5,
+ 0x7487, 0x1845,
+ 0x7488, 0x3da8,
+ 0x7489, 0x2461,
+ 0x748a, 0x3da9,
+ 0x748b, 0x1846,
+ 0x748c, 0x3daa,
+ 0x748e, 0x1842,
+ 0x748f, 0x3dac,
+ 0x7490, 0x184a,
+ 0x7491, 0x3dad,
+ 0x749c, 0x1841,
+ 0x749d, 0x3db8,
+ 0x749e, 0x1847,
+ 0x749f, 0x3db9,
+ 0x74a3, 0x245b,
+ 0x74a4, 0x3dbd,
+ 0x74a6, 0x2462,
+ 0x74a7, 0x184b,
+ 0x74a8, 0x1848,
+ 0x74aa, 0x3dbf,
+ 0x74b0, 0x1f54,
+ 0x74b1, 0x3dc5,
+ 0x74ba, 0x184d,
+ 0x74bb, 0x3dce,
+ 0x74bd, 0x245f,
+ 0x74be, 0x3dd0,
+ 0x74ca, 0x20ec,
+ 0x74cb, 0x3ddc,
+ 0x74cf, 0x245d,
+ 0x74d0, 0x3de0,
+ 0x74d2, 0x184c,
+ 0x74d3, 0x3de2,
+ 0x74d4, 0x2463,
+ 0x74d5, 0x3de3,
+ 0x74da, 0x2464,
+ 0x74db, 0x3de8,
+ 0x74dc, 0x0728,
+ 0x74dd, 0x3de9,
+ 0x74de, 0x1b32,
+ 0x74df, 0x3dea,
+ 0x74e0, 0x1b33,
+ 0x74e1, 0x3deb,
+ 0x74e2, 0x0bcf,
+ 0x74e3, 0x03f5,
+ 0x74e4, 0x0c9a,
+ 0x74e5, 0x3dec,
+ 0x74e6, 0x0e90,
+ 0x74e7, 0x3ded,
+ 0x74ee, 0x0edc,
+ 0x74ef, 0x1903,
+ 0x74f0, 0x3df4,
+ 0x74f4, 0x1904,
+ 0x74f5, 0x3df8,
+ 0x74f6, 0x0bde,
+ 0x74f7, 0x054c,
+ 0x74f8, 0x3df9,
+ 0x74ff, 0x1905,
+ 0x7500, 0x3e00,
+ 0x7504, 0x1188,
+ 0x7505, 0x3e04,
+ 0x750c, 0x24a5,
+ 0x750d, 0x1485,
+ 0x750e, 0x3e0b,
+ 0x750f, 0x1906,
+ 0x7510, 0x3e0c,
+ 0x7511, 0x1907,
+ 0x7512, 0x3e0d,
+ 0x7513, 0x1908,
+ 0x7514, 0x3e0e,
+ 0x7518, 0x06c5,
+ 0x7519, 0x14f8,
+ 0x751a, 0x0d2e,
+ 0x751b, 0x3e12,
+ 0x751c, 0x0e43,
+ 0x751d, 0x3e13,
+ 0x751f, 0x0d33,
+ 0x7520, 0x3e15,
+ 0x7523, 0x1e70,
+ 0x7524, 0x3e18,
+ 0x7525, 0x0d34,
+ 0x7526, 0x3e19,
+ 0x7528, 0x10a8,
+ 0x7529, 0x0d9b,
+ 0x752a, 0x3e1b,
+ 0x752b, 0x06a1,
+ 0x752c, 0x1b34,
+ 0x752d, 0x042b,
+ 0x752e, 0x3e1c,
+ 0x752f, 0x1734,
+ 0x7530, 0x0e42,
+ 0x7531, 0x10ae,
+ 0x7532, 0x084a,
+ 0x7533, 0x0d23,
+ 0x7534, 0x3e1d,
+ 0x7535, 0x05c8,
+ 0x7536, 0x3e1e,
+ 0x7537, 0x0b33,
+ 0x7538, 0x05ca,
+ 0x7539, 0x3e1f,
+ 0x753a, 0x1a78,
+ 0x753b, 0x07c2,
+ 0x753c, 0x3e20,
+ 0x753e, 0x1816,
+ 0x753f, 0x3e22,
+ 0x7540, 0x1a79,
+ 0x7541, 0x3e23,
+ 0x7545, 0x04ce,
+ 0x7546, 0x3e27,
+ 0x7548, 0x1a7c,
+ 0x7549, 0x3e29,
+ 0x754b, 0x1a7b,
+ 0x754c, 0x08b8,
+ 0x754d, 0x3e2b,
+ 0x754e, 0x1a7a,
+ 0x754f, 0x0ec6,
+ 0x7550, 0x3e2c,
+ 0x7554, 0x0b90,
+ 0x7555, 0x3e30,
+ 0x7559, 0x0a3d,
+ 0x755a, 0x139e,
+ 0x755b, 0x1a7d,
+ 0x755c, 0x0fbe,
+ 0x755d, 0x208f,
+ 0x755e, 0x3e34,
+ 0x7562, 0x1e42,
+ 0x7563, 0x3e38,
+ 0x7565, 0x0a7b,
+ 0x7566, 0x0c07,
+ 0x7567, 0x3e3a,
+ 0x756a, 0x0649,
+ 0x756b, 0x1f4e,
+ 0x756c, 0x3e3d,
+ 0x7572, 0x1a7e,
+ 0x7573, 0x3e43,
+ 0x7574, 0x0510,
+ 0x7575, 0x3e44,
+ 0x7576, 0x1eb1,
+ 0x7577, 0x3e45,
+ 0x7578, 0x0810,
+ 0x7579, 0x1a7f,
+ 0x757a, 0x3e46,
+ 0x757f, 0x1814,
+ 0x7580, 0x3e4b,
+ 0x7583, 0x1a80,
+ 0x7584, 0x3e4e,
+ 0x7586, 0x087f,
+ 0x7587, 0x1e8b,
+ 0x7588, 0x3e50,
+ 0x758b, 0x1bc6,
+ 0x758c, 0x3e53,
+ 0x758f, 0x0d7f,
+ 0x7590, 0x3e56,
+ 0x7591, 0x1050,
+ 0x7592, 0x1b60,
+ 0x7593, 0x3e57,
+ 0x7594, 0x1b61,
+ 0x7595, 0x3e58,
+ 0x7596, 0x1b62,
+ 0x7597, 0x0a0f,
+ 0x7598, 0x3e59,
+ 0x7599, 0x06e8,
+ 0x759a, 0x08fd,
+ 0x759b, 0x3e5a,
+ 0x759d, 0x1b64,
+ 0x759e, 0x3e5c,
+ 0x759f, 0x0b72,
+ 0x75a0, 0x1b63,
+ 0x75a1, 0x101a,
+ 0x75a2, 0x3e5d,
+ 0x75a3, 0x1b66,
+ 0x75a4, 0x03d7,
+ 0x75a5, 0x08bb,
+ 0x75a6, 0x3e5e,
+ 0x75ab, 0x1066,
+ 0x75ac, 0x1b65,
+ 0x75ad, 0x3e63,
+ 0x75ae, 0x0532,
+ 0x75af, 0x0685,
+ 0x75b0, 0x1b6c,
+ 0x75b1, 0x1b6b,
+ 0x75b2, 0x0bc2,
+ 0x75b3, 0x1b67,
+ 0x75b5, 0x0546,
+ 0x75b6, 0x3e64,
+ 0x75b8, 0x1b69,
+ 0x75b9, 0x118f,
+ 0x75ba, 0x3e66,
+ 0x75bc, 0x0e2e,
+ 0x75bd, 0x0901,
+ 0x75be, 0x0825,
+ 0x75bf, 0x3e68,
+ 0x75c2, 0x1b6e,
+ 0x75c3, 0x1b6d,
+ 0x75c4, 0x1b6a,
+ 0x75c5, 0x0468,
+ 0x75c6, 0x3e6b,
+ 0x75c7, 0x11a1,
+ 0x75c8, 0x109d,
+ 0x75c9, 0x08e6,
+ 0x75ca, 0x0c87,
+ 0x75cb, 0x3e6c,
+ 0x75cd, 0x1b70,
+ 0x75ce, 0x3e6e,
+ 0x75d2, 0x1020,
+ 0x75d3, 0x3e72,
+ 0x75d4, 0x11cb,
+ 0x75d5, 0x0792,
+ 0x75d6, 0x1b6f,
+ 0x75d7, 0x3e73,
+ 0x75d8, 0x05fa,
+ 0x75d9, 0x1fc6,
+ 0x75da, 0x3e74,
+ 0x75db, 0x0e65,
+ 0x75dc, 0x3e75,
+ 0x75de, 0x0bc5,
+ 0x75df, 0x3e77,
+ 0x75e2, 0x09ea,
+ 0x75e3, 0x1b71,
+ 0x75e4, 0x1b74,
+ 0x75e5, 0x3e7a,
+ 0x75e6, 0x1b73,
+ 0x75e7, 0x1b76,
+ 0x75e8, 0x1b72,
+ 0x75e9, 0x3e7b,
+ 0x75ea, 0x07d3,
+ 0x75eb, 0x1b75,
+ 0x75ec, 0x3e7c,
+ 0x75f0, 0x0e08,
+ 0x75f1, 0x1b78,
+ 0x75f2, 0x3e80,
+ 0x75f4, 0x04fa,
+ 0x75f5, 0x3e82,
+ 0x75f9, 0x043d,
+ 0x75fa, 0x3e86,
+ 0x75fc, 0x1b79,
+ 0x75fd, 0x3e88,
+ 0x75ff, 0x1b7a,
+ 0x7600, 0x1b7c,
+ 0x7601, 0x0564,
+ 0x7602, 0x25ae,
+ 0x7603, 0x1b77,
+ 0x7604, 0x3e8a,
+ 0x7605, 0x1b7d,
+ 0x7606, 0x3e8b,
+ 0x760a, 0x1b80,
+ 0x760b, 0x1f01,
+ 0x760c, 0x1b7e,
+ 0x760d, 0x2200,
+ 0x760e, 0x3e8f,
+ 0x7610, 0x1b7b,
+ 0x7611, 0x3e91,
+ 0x7615, 0x1b83,
+ 0x7616, 0x3e95,
+ 0x7617, 0x1b7f,
+ 0x7618, 0x1b82,
+ 0x7619, 0x1b84,
+ 0x761a, 0x3e96,
+ 0x761b, 0x1b85,
+ 0x761c, 0x3e97,
+ 0x761e, 0x25b2,
+ 0x761f, 0x0ed0,
+ 0x7620, 0x1b88,
+ 0x7621, 0x1e97,
+ 0x7622, 0x1b87,
+ 0x7623, 0x3e99,
+ 0x7624, 0x0a3f,
+ 0x7625, 0x1b81,
+ 0x7626, 0x0d74,
+ 0x7627, 0x20ab,
+ 0x7628, 0x3e9a,
+ 0x7629, 0x0574,
+ 0x762a, 0x045a,
+ 0x762b, 0x0e04,
+ 0x762c, 0x3e9b,
+ 0x762d, 0x1b8a,
+ 0x762e, 0x3e9c,
+ 0x7630, 0x1b8b,
+ 0x7631, 0x3e9e,
+ 0x7633, 0x1b90,
+ 0x7634, 0x116f,
+ 0x7635, 0x1b8d,
+ 0x7636, 0x3ea0,
+ 0x7638, 0x0c8e,
+ 0x7639, 0x3ea2,
+ 0x763b, 0x25b3,
+ 0x763c, 0x1b86,
+ 0x763d, 0x3ea4,
+ 0x763e, 0x1b8f,
+ 0x763f, 0x1b8c,
+ 0x7640, 0x1b89,
+ 0x7641, 0x3ea5,
+ 0x7642, 0x2028,
+ 0x7643, 0x1b8e,
+ 0x7644, 0x3ea6,
+ 0x7646, 0x25af,
+ 0x7648, 0x3ea8,
+ 0x7649, 0x25b1,
+ 0x764a, 0x3ea9,
+ 0x764c, 0x03b4,
+ 0x764d, 0x1b91,
+ 0x764e, 0x3eab,
+ 0x7654, 0x1b93,
+ 0x7655, 0x3eb1,
+ 0x7656, 0x1b95,
+ 0x7657, 0x3eb2,
+ 0x7658, 0x25ac,
+ 0x7659, 0x3eb3,
+ 0x765c, 0x1b94,
+ 0x765d, 0x3eb6,
+ 0x765e, 0x1b92,
+ 0x765f, 0x1e4e,
+ 0x7660, 0x3eb7,
+ 0x7662, 0x2202,
+ 0x7663, 0x0fcb,
+ 0x7664, 0x25ab,
+ 0x7665, 0x2286,
+ 0x7666, 0x3eb9,
+ 0x7667, 0x25ad,
+ 0x7668, 0x3eba,
+ 0x7669, 0x25b6,
+ 0x766a, 0x3ebb,
+ 0x766b, 0x1b96,
+ 0x766c, 0x21e3,
+ 0x766d, 0x25b4,
+ 0x766f, 0x1b97,
+ 0x7670, 0x222f,
+ 0x7671, 0x2165,
+ 0x7672, 0x25b7,
+ 0x7673, 0x3ebc,
+ 0x7678, 0x0748,
+ 0x7679, 0x3ec1,
+ 0x767b, 0x05a8,
+ 0x767c, 0x1ee9,
+ 0x767d, 0x03e2,
+ 0x767e, 0x03e4,
+ 0x767f, 0x3ec3,
+ 0x7682, 0x1130,
+ 0x7683, 0x3ec6,
+ 0x7684, 0x05a5,
+ 0x7685, 0x3ec7,
+ 0x7686, 0x08a5,
+ 0x7687, 0x07df,
+ 0x7688, 0x1b2d,
+ 0x7689, 0x3ec8,
+ 0x768b, 0x06d9,
+ 0x768c, 0x3eca,
+ 0x768e, 0x1b2e,
+ 0x768f, 0x3ecc,
+ 0x7691, 0x03b3,
+ 0x7692, 0x3ece,
+ 0x7693, 0x1b2f,
+ 0x7694, 0x3ecf,
+ 0x7696, 0x0e9f,
+ 0x7697, 0x3ed1,
+ 0x7699, 0x1b30,
+ 0x769a, 0x1e25,
+ 0x769b, 0x3ed3,
+ 0x76a4, 0x1b31,
+ 0x76a5, 0x3edc,
+ 0x76ae, 0x0bc3,
+ 0x76af, 0x3ee5,
+ 0x76b1, 0x11e4,
+ 0x76b2, 0x1bc8,
+ 0x76b3, 0x3ee7,
+ 0x76b4, 0x1bc9,
+ 0x76b5, 0x3ee8,
+ 0x76b8, 0x25c0,
+ 0x76b9, 0x3eeb,
+ 0x76ba, 0x229a,
+ 0x76bb, 0x3eec,
+ 0x76bf, 0x0af8,
+ 0x76c0, 0x3ef0,
+ 0x76c2, 0x10c0,
+ 0x76c3, 0x3ef2,
+ 0x76c5, 0x11d0,
+ 0x76c6, 0x0ba9,
+ 0x76c7, 0x3ef4,
+ 0x76c8, 0x1094,
+ 0x76c9, 0x3ef5,
+ 0x76ca, 0x106d,
+ 0x76cb, 0x3ef6,
+ 0x76cd, 0x1a8b,
+ 0x76ce, 0x03c6,
+ 0x76cf, 0x1156,
+ 0x76d0, 0x0ff7,
+ 0x76d1, 0x0853,
+ 0x76d2, 0x0787,
+ 0x76d3, 0x3ef8,
+ 0x76d4, 0x0985,
+ 0x76d5, 0x3ef9,
+ 0x76d6, 0x06c2,
+ 0x76d7, 0x05a2,
+ 0x76d8, 0x0b8d,
+ 0x76d9, 0x3efa,
+ 0x76db, 0x0d39,
+ 0x76dc, 0x3efc,
+ 0x76de, 0x226e,
+ 0x76df, 0x0ad0,
+ 0x76e0, 0x3efe,
+ 0x76e1, 0x1fbd,
+ 0x76e2, 0x3eff,
+ 0x76e3, 0x1f84,
+ 0x76e4, 0x20b2,
+ 0x76e5, 0x1a8c,
+ 0x76e6, 0x3f00,
+ 0x76e7, 0x2043,
+ 0x76e8, 0x3f01,
+ 0x76ee, 0x0b22,
+ 0x76ef, 0x05e1,
+ 0x76f0, 0x3f07,
+ 0x76f1, 0x1a58,
+ 0x76f2, 0x0aa9,
+ 0x76f3, 0x3f08,
+ 0x76f4, 0x11b0,
+ 0x76f5, 0x3f09,
+ 0x76f8, 0x0f4d,
+ 0x76f9, 0x1a5b,
+ 0x76fa, 0x3f0c,
+ 0x76fc, 0x0b8f,
+ 0x76fd, 0x3f0e,
+ 0x76fe, 0x061b,
+ 0x76ff, 0x3f0f,
+ 0x7700, 0x3f10,
+ 0x7701, 0x0d38,
+ 0x7702, 0x3f11,
+ 0x7704, 0x1a59,
+ 0x7705, 0x3f13,
+ 0x7707, 0x1a5c,
+ 0x7709, 0x0ac1,
+ 0x770a, 0x3f15,
+ 0x770b, 0x0941,
+ 0x770c, 0x3f16,
+ 0x770d, 0x1a5a,
+ 0x770e, 0x3f17,
+ 0x7719, 0x1a60,
+ 0x771a, 0x1a5e,
+ 0x771b, 0x3f22,
+ 0x771f, 0x1187,
+ 0x7720, 0x0ae4,
+ 0x7721, 0x3f26,
+ 0x7722, 0x1a5f,
+ 0x7723, 0x3f27,
+ 0x7726, 0x1a62,
+ 0x7727, 0x3f2a,
+ 0x7728, 0x1144,
+ 0x7729, 0x0fcc,
+ 0x772a, 0x3f2b,
+ 0x772d, 0x1a61,
+ 0x772e, 0x3f2e,
+ 0x772f, 0x0ad5,
+ 0x7730, 0x3f2f,
+ 0x7735, 0x1a63,
+ 0x7736, 0x0981,
+ 0x7737, 0x091b,
+ 0x7738, 0x1a64,
+ 0x7739, 0x3f34,
+ 0x773a, 0x0e4a,
+ 0x773b, 0x3f35,
+ 0x773c, 0x1004,
+ 0x773d, 0x3f36,
+ 0x7740, 0x1222,
+ 0x7741, 0x1197,
+ 0x7742, 0x3f39,
+ 0x7743, 0x1a68,
+ 0x7744, 0x3f3a,
+ 0x7747, 0x1a67,
+ 0x7748, 0x3f3d,
+ 0x774f, 0x2684,
+ 0x7750, 0x1a65,
+ 0x7752, 0x3f44,
+ 0x775a, 0x1a69,
+ 0x775b, 0x08d5,
+ 0x775c, 0x3f4c,
+ 0x775e, 0x24ef,
+ 0x775f, 0x3f4e,
+ 0x7761, 0x0da4,
+ 0x7762, 0x1a6b,
+ 0x7763, 0x05fc,
+ 0x7764, 0x3f50,
+ 0x7765, 0x1a6c,
+ 0x7766, 0x0b23,
+ 0x7767, 0x3f51,
+ 0x7768, 0x1a6a,
+ 0x7769, 0x3f52,
+ 0x776b, 0x08af,
+ 0x776c, 0x048e,
+ 0x776d, 0x3f54,
+ 0x7779, 0x0602,
+ 0x777a, 0x3f60,
+ 0x777d, 0x1a6f,
+ 0x777e, 0x1270,
+ 0x777f, 0x1a6d,
+ 0x7780, 0x1a70,
+ 0x7781, 0x3f63,
+ 0x7784, 0x0aee,
+ 0x7785, 0x0517,
+ 0x7786, 0x3f66,
+ 0x778c, 0x1a71,
+ 0x778d, 0x1a6e,
+ 0x778e, 0x0f26,
+ 0x778f, 0x3f6c,
+ 0x7791, 0x1a72,
+ 0x7792, 0x0a9e,
+ 0x7793, 0x3f6e,
+ 0x7798, 0x24ee,
+ 0x7799, 0x3f73,
+ 0x779e, 0x2074,
+ 0x779f, 0x1a73,
+ 0x77a1, 0x3f78,
+ 0x77a2, 0x1495,
+ 0x77a3, 0x3f79,
+ 0x77a5, 0x0bd2,
+ 0x77a6, 0x3f7b,
+ 0x77a7, 0x0c43,
+ 0x77a8, 0x3f7c,
+ 0x77a9, 0x11f4,
+ 0x77aa, 0x05aa,
+ 0x77ab, 0x3f7d,
+ 0x77ac, 0x0da7,
+ 0x77ad, 0x2687,
+ 0x77ae, 0x3f7e,
+ 0x77b0, 0x1a75,
+ 0x77b1, 0x3f80,
+ 0x77b3, 0x0e5c,
+ 0x77b4, 0x3f82,
+ 0x77b5, 0x1a76,
+ 0x77b6, 0x3f83,
+ 0x77bb, 0x1151,
+ 0x77bc, 0x24f0,
+ 0x77bd, 0x1a77,
+ 0x77be, 0x3f88,
+ 0x77bf, 0x1d7e,
+ 0x77c0, 0x3f89,
+ 0x77c7, 0x268d,
+ 0x77c8, 0x3f90,
+ 0x77cd, 0x1397,
+ 0x77ce, 0x3f95,
+ 0x77d7, 0x0526,
+ 0x77d8, 0x3f9e,
+ 0x77da, 0x22a0,
+ 0x77db, 0x0ab1,
+ 0x77dc, 0x1bca,
+ 0x77dd, 0x3fa0,
+ 0x77e2, 0x0d4f,
+ 0x77e3, 0x105a,
+ 0x77e4, 0x3fa5,
+ 0x77e5, 0x11a9,
+ 0x77e6, 0x3fa6,
+ 0x77e7, 0x1b1a,
+ 0x77e8, 0x3fa7,
+ 0x77e9, 0x0907,
+ 0x77ea, 0x3fa8,
+ 0x77eb, 0x0894,
+ 0x77ec, 0x1b1b,
+ 0x77ed, 0x060b,
+ 0x77ee, 0x03b6,
+ 0x77ef, 0x1fab,
+ 0x77f0, 0x3fa9,
+ 0x77f3, 0x0d46,
+ 0x77f4, 0x3fac,
+ 0x77f6, 0x1a22,
+ 0x77f7, 0x3fae,
+ 0x77f8, 0x1a23,
+ 0x77f9, 0x3faf,
+ 0x77fd, 0x0f08,
+ 0x77fe, 0x064c,
+ 0x77ff, 0x0980,
+ 0x7800, 0x1a24,
+ 0x7801, 0x0a92,
+ 0x7802, 0x0ce9,
+ 0x7803, 0x3fb3,
+ 0x7809, 0x1a25,
+ 0x780a, 0x3fb9,
+ 0x780c, 0x0c15,
+ 0x780d, 0x0940,
+ 0x780e, 0x3fbb,
+ 0x7811, 0x1a28,
+ 0x7812, 0x0bb9,
+ 0x7813, 0x3fbe,
+ 0x7814, 0x0ff9,
+ 0x7815, 0x3fbf,
+ 0x7816, 0x1206,
+ 0x7817, 0x1a26,
+ 0x7819, 0x3fc0,
+ 0x781a, 0x100b,
+ 0x781b, 0x3fc1,
+ 0x781c, 0x1a2b,
+ 0x781e, 0x3fc2,
+ 0x781f, 0x1a30,
+ 0x7820, 0x3fc3,
+ 0x7823, 0x1a34,
+ 0x7824, 0x3fc6,
+ 0x7825, 0x1a32,
+ 0x7826, 0x1a3a,
+ 0x7827, 0x1189,
+ 0x7828, 0x3fc7,
+ 0x7829, 0x1a35,
+ 0x782a, 0x3fc8,
+ 0x782c, 0x1a33,
+ 0x782d, 0x1a2a,
+ 0x782e, 0x3fca,
+ 0x7830, 0x0baa,
+ 0x7831, 0x3fcc,
+ 0x7834, 0x0be5,
+ 0x7835, 0x3fcf,
+ 0x7837, 0x0d22,
+ 0x7838, 0x1115,
+ 0x7839, 0x1a2d,
+ 0x783c, 0x1a31,
+ 0x783d, 0x3fd1,
+ 0x783e, 0x09e4,
+ 0x783f, 0x3fd2,
+ 0x7840, 0x0524,
+ 0x7841, 0x3fd3,
+ 0x7843, 0x26a8,
+ 0x7844, 0x3fd5,
+ 0x7845, 0x0741,
+ 0x7846, 0x3fd6,
+ 0x7847, 0x1a3c,
+ 0x7848, 0x3fd7,
+ 0x784c, 0x1a3d,
+ 0x784d, 0x3fdb,
+ 0x784e, 0x1a36,
+ 0x784f, 0x3fdc,
+ 0x7850, 0x1a3b,
+ 0x7851, 0x3fdd,
+ 0x7852, 0x0f07,
+ 0x7853, 0x3fde,
+ 0x7855, 0x0dab,
+ 0x7856, 0x1a38,
+ 0x7858, 0x3fe0,
+ 0x785d, 0x0f62,
+ 0x785e, 0x3fe5,
+ 0x7864, 0x24e9,
+ 0x7865, 0x3feb,
+ 0x7868, 0x24e5,
+ 0x7869, 0x3fee,
+ 0x786a, 0x1a3e,
+ 0x786b, 0x0a3b,
+ 0x786c, 0x1097,
+ 0x786d, 0x1a37,
+ 0x786e, 0x0c92,
+ 0x786f, 0x21fa,
+ 0x7870, 0x3fef,
+ 0x7877, 0x0862,
+ 0x7878, 0x3ff6,
+ 0x787c, 0x0bb1,
+ 0x787d, 0x3ffa,
+ 0x7887, 0x1a42,
+ 0x7888, 0x4004,
+ 0x7889, 0x05d0,
+ 0x788a, 0x4005,
+ 0x788c, 0x0a5c,
+ 0x788d, 0x03b8,
+ 0x788e, 0x0dde,
+ 0x788f, 0x4007,
+ 0x7891, 0x0417,
+ 0x7892, 0x4009,
+ 0x7893, 0x1a40,
+ 0x7894, 0x400a,
+ 0x7897, 0x0e9c,
+ 0x7898, 0x05c3,
+ 0x7899, 0x400d,
+ 0x789a, 0x1a41,
+ 0x789b, 0x1a3f,
+ 0x789c, 0x1a43,
+ 0x789d, 0x400e,
+ 0x789f, 0x05db,
+ 0x78a0, 0x4010,
+ 0x78a1, 0x1a44,
+ 0x78a2, 0x4011,
+ 0x78a3, 0x1a45,
+ 0x78a4, 0x4012,
+ 0x78a5, 0x1a48,
+ 0x78a6, 0x4013,
+ 0x78a7, 0x0435,
+ 0x78a8, 0x4014,
+ 0x78a9, 0x2148,
+ 0x78aa, 0x4015,
+ 0x78ad, 0x24e4,
+ 0x78ae, 0x4018,
+ 0x78b0, 0x0bb7,
+ 0x78b1, 0x0861,
+ 0x78b2, 0x1a46,
+ 0x78b3, 0x0e0f,
+ 0x78b4, 0x04b1,
+ 0x78b5, 0x401a,
+ 0x78b8, 0x24e6,
+ 0x78b9, 0x1a47,
+ 0x78ba, 0x20f7,
+ 0x78bb, 0x401d,
+ 0x78bc, 0x206b,
+ 0x78bd, 0x401e,
+ 0x78be, 0x0b4e,
+ 0x78bf, 0x401f,
+ 0x78c1, 0x0548,
+ 0x78c2, 0x4021,
+ 0x78c5, 0x0400,
+ 0x78c6, 0x4024,
+ 0x78c9, 0x1a4b,
+ 0x78ca, 0x09c5,
+ 0x78cb, 0x056b,
+ 0x78cc, 0x4027,
+ 0x78d0, 0x0b8e,
+ 0x78d1, 0x402b,
+ 0x78d4, 0x1a49,
+ 0x78d5, 0x0951,
+ 0x78d6, 0x402e,
+ 0x78d9, 0x1a4a,
+ 0x78da, 0x22a7,
+ 0x78db, 0x4031,
+ 0x78e3, 0x24ec,
+ 0x78e4, 0x4039,
+ 0x78e7, 0x24eb,
+ 0x78e8, 0x0b08,
+ 0x78e9, 0x403c,
+ 0x78ec, 0x1a4c,
+ 0x78ed, 0x403f,
+ 0x78ef, 0x24e3,
+ 0x78f0, 0x4041,
+ 0x78f2, 0x1a4d,
+ 0x78f3, 0x4043,
+ 0x78f4, 0x1a4f,
+ 0x78f5, 0x4044,
+ 0x78f7, 0x0a20,
+ 0x78f8, 0x4046,
+ 0x78fa, 0x07dc,
+ 0x78fb, 0x4048,
+ 0x78fd, 0x24ea,
+ 0x78fe, 0x404a,
+ 0x7900, 0x404c,
+ 0x7901, 0x0889,
+ 0x7902, 0x404d,
+ 0x7905, 0x1a4e,
+ 0x7906, 0x4050,
+ 0x790e, 0x1e92,
+ 0x790f, 0x4058,
+ 0x7913, 0x1a50,
+ 0x7914, 0x405c,
+ 0x7919, 0x1e27,
+ 0x791a, 0x4061,
+ 0x791e, 0x1a52,
+ 0x791f, 0x4065,
+ 0x7924, 0x1a51,
+ 0x7925, 0x406a,
+ 0x7926, 0x1fe6,
+ 0x7927, 0x406b,
+ 0x792a, 0x24e7,
+ 0x792b, 0x2012,
+ 0x792c, 0x1eec,
+ 0x792d, 0x406e,
+ 0x7931, 0x24e8,
+ 0x7932, 0x4072,
+ 0x7934, 0x1a53,
+ 0x7935, 0x4074,
+ 0x793a, 0x0d55,
+ 0x793b, 0x19f8,
+ 0x793c, 0x09dc,
+ 0x793d, 0x4079,
+ 0x793e, 0x0d20,
+ 0x793f, 0x407a,
+ 0x7940, 0x19f9,
+ 0x7941, 0x0c0d,
+ 0x7942, 0x407b,
+ 0x7946, 0x19fa,
+ 0x7947, 0x407f,
+ 0x7948, 0x0c0c,
+ 0x7949, 0x19fb,
+ 0x794a, 0x4080,
+ 0x7953, 0x19fe,
+ 0x7954, 0x4089,
+ 0x7956, 0x1243,
+ 0x7957, 0x1a01,
+ 0x7958, 0x408b,
+ 0x795a, 0x19ff,
+ 0x795b, 0x19fc,
+ 0x795d, 0x1200,
+ 0x795e, 0x0d2a,
+ 0x795f, 0x0de3,
+ 0x7960, 0x1a02,
+ 0x7961, 0x408d,
+ 0x7962, 0x1a00,
+ 0x7963, 0x408e,
+ 0x7965, 0x0f56,
+ 0x7966, 0x4090,
+ 0x7967, 0x1a04,
+ 0x7968, 0x0bd0,
+ 0x7969, 0x4091,
+ 0x796d, 0x0833,
+ 0x796e, 0x4095,
+ 0x796f, 0x1a03,
+ 0x7970, 0x4096,
+ 0x7977, 0x059c,
+ 0x7978, 0x080b,
+ 0x7979, 0x409d,
+ 0x797a, 0x1a05,
+ 0x797b, 0x409e,
+ 0x7980, 0x130b,
+ 0x7981, 0x08cc,
+ 0x7982, 0x40a3,
+ 0x7984, 0x0a62,
+ 0x7985, 0x1a06,
+ 0x7986, 0x40a5,
+ 0x798a, 0x1a07,
+ 0x798b, 0x40a9,
+ 0x798d, 0x1f66,
+ 0x798e, 0x24dc,
+ 0x798f, 0x069e,
+ 0x7990, 0x40ab,
+ 0x799a, 0x1a08,
+ 0x799b, 0x40b5,
+ 0x79a6, 0x26a2,
+ 0x79a7, 0x1a09,
+ 0x79a8, 0x40c0,
+ 0x79aa, 0x24dd,
+ 0x79ab, 0x40c2,
+ 0x79ae, 0x200e,
+ 0x79af, 0x40c5,
+ 0x79b0, 0x24db,
+ 0x79b1, 0x1eb8,
+ 0x79b2, 0x40c6,
+ 0x79b3, 0x1a0a,
+ 0x79b4, 0x40c7,
+ 0x79b9, 0x10d2,
+ 0x79ba, 0x1264,
+ 0x79bb, 0x09d6,
+ 0x79bc, 0x40cc,
+ 0x79bd, 0x0c5a,
+ 0x79be, 0x0783,
+ 0x79bf, 0x40cd,
+ 0x79c0, 0x0fae,
+ 0x79c1, 0x0db2,
+ 0x79c2, 0x40ce,
+ 0x79c3, 0x0e6b,
+ 0x79c4, 0x40cf,
+ 0x79c6, 0x06cc,
+ 0x79c7, 0x40d1,
+ 0x79c9, 0x0465,
+ 0x79ca, 0x40d3,
+ 0x79cb, 0x0c6c,
+ 0x79cc, 0x40d4,
+ 0x79cd, 0x11d5,
+ 0x79ce, 0x40d5,
+ 0x79d1, 0x0953,
+ 0x79d2, 0x0af0,
+ 0x79d3, 0x40d8,
+ 0x79d5, 0x1b1d,
+ 0x79d6, 0x40da,
+ 0x79d8, 0x0add,
+ 0x79d9, 0x40dc,
+ 0x79df, 0x123f,
+ 0x79e0, 0x40e2,
+ 0x79e3, 0x1b1f,
+ 0x79e4, 0x04f8,
+ 0x79e5, 0x40e5,
+ 0x79e6, 0x0c55,
+ 0x79e7, 0x1016,
+ 0x79e8, 0x40e6,
+ 0x79e9, 0x11c7,
+ 0x79ea, 0x40e7,
+ 0x79eb, 0x1b20,
+ 0x79ec, 0x40e8,
+ 0x79ed, 0x1b1e,
+ 0x79ee, 0x40e9,
+ 0x79ef, 0x0812,
+ 0x79f0, 0x04eb,
+ 0x79f1, 0x40ea,
+ 0x79f8, 0x08a6,
+ 0x79f9, 0x40f1,
+ 0x79fb, 0x104d,
+ 0x79fc, 0x40f3,
+ 0x79fd, 0x07f5,
+ 0x79fe, 0x40f4,
+ 0x7a00, 0x0f0e,
+ 0x7a01, 0x40f6,
+ 0x7a02, 0x1b24,
+ 0x7a03, 0x1b23,
+ 0x7a04, 0x40f7,
+ 0x7a06, 0x1b21,
+ 0x7a07, 0x40f9,
+ 0x7a0b, 0x04f1,
+ 0x7a0c, 0x40fd,
+ 0x7a0d, 0x0d0d,
+ 0x7a0e, 0x0da5,
+ 0x7a0f, 0x40fe,
+ 0x7a14, 0x1b26,
+ 0x7a15, 0x4103,
+ 0x7a17, 0x03e9,
+ 0x7a18, 0x4105,
+ 0x7a1a, 0x11c8,
+ 0x7a1b, 0x4107,
+ 0x7a1e, 0x1b25,
+ 0x7a1f, 0x410a,
+ 0x7a20, 0x0512,
+ 0x7a21, 0x410b,
+ 0x7a23, 0x1d8f,
+ 0x7a24, 0x410d,
+ 0x7a2e, 0x2295,
+ 0x7a2f, 0x4117,
+ 0x7a31, 0x1e80,
+ 0x7a32, 0x4119,
+ 0x7a33, 0x0ed7,
+ 0x7a34, 0x411a,
+ 0x7a37, 0x1b28,
+ 0x7a38, 0x411d,
+ 0x7a39, 0x1b27,
+ 0x7a3a, 0x411e,
+ 0x7a3b, 0x059f,
+ 0x7a3c, 0x084d,
+ 0x7a3d, 0x0811,
+ 0x7a3e, 0x411f,
+ 0x7a3f, 0x06e0,
+ 0x7a40, 0x2677,
+ 0x7a41, 0x4120,
+ 0x7a46, 0x0b25,
+ 0x7a47, 0x4125,
+ 0x7a4c, 0x2624,
+ 0x7a4d, 0x1f69,
+ 0x7a4e, 0x222b,
+ 0x7a4f, 0x412a,
+ 0x7a51, 0x1b29,
+ 0x7a52, 0x412c,
+ 0x7a57, 0x0de0,
+ 0x7a58, 0x4131,
+ 0x7a61, 0x257f,
+ 0x7a62, 0x1f5b,
+ 0x7a63, 0x413a,
+ 0x7a69, 0x219b,
+ 0x7a6a, 0x4140,
+ 0x7a6b, 0x267d,
+ 0x7a6c, 0x4141,
+ 0x7a70, 0x1b2c,
+ 0x7a71, 0x4145,
+ 0x7a74, 0x0fd1,
+ 0x7a75, 0x4148,
+ 0x7a76, 0x08ee,
+ 0x7a77, 0x0c6b,
+ 0x7a78, 0x1b9a,
+ 0x7a7a, 0x0962,
+ 0x7a7b, 0x4149,
+ 0x7a7f, 0x052c,
+ 0x7a80, 0x1b9c,
+ 0x7a81, 0x0e6c,
+ 0x7a82, 0x414d,
+ 0x7a83, 0x0c51,
+ 0x7a84, 0x114e,
+ 0x7a85, 0x414e,
+ 0x7a86, 0x1b9d,
+ 0x7a87, 0x414f,
+ 0x7a88, 0x1b9e,
+ 0x7a89, 0x4150,
+ 0x7a8d, 0x0c4c,
+ 0x7a8e, 0x4154,
+ 0x7a91, 0x102b,
+ 0x7a92, 0x11ce,
+ 0x7a93, 0x4157,
+ 0x7a95, 0x1b9f,
+ 0x7a96, 0x08a2,
+ 0x7a97, 0x0533,
+ 0x7a98, 0x08ec,
+ 0x7a99, 0x4159,
+ 0x7a9c, 0x055f,
+ 0x7a9d, 0x0ee0,
+ 0x7a9e, 0x415c,
+ 0x7a9f, 0x096c,
+ 0x7aa0, 0x1ba1,
+ 0x7aa1, 0x415d,
+ 0x7aa5, 0x0987,
+ 0x7aa6, 0x1ba0,
+ 0x7aa7, 0x4161,
+ 0x7aa8, 0x1ba3,
+ 0x7aa9, 0x21a0,
+ 0x7aaa, 0x2186,
+ 0x7aab, 0x4162,
+ 0x7aac, 0x1ba2,
+ 0x7aad, 0x1ba4,
+ 0x7aae, 0x20ed,
+ 0x7aaf, 0x4163,
+ 0x7ab3, 0x1ba5,
+ 0x7ab4, 0x4167,
+ 0x7ab6, 0x25b9,
+ 0x7ab7, 0x4169,
+ 0x7aba, 0x1fea,
+ 0x7abb, 0x416c,
+ 0x7abf, 0x0a47,
+ 0x7ac0, 0x4170,
+ 0x7ac4, 0x1ea4,
+ 0x7ac5, 0x20e1,
+ 0x7ac6, 0x4174,
+ 0x7ac7, 0x25b8,
+ 0x7ac8, 0x2260,
+ 0x7ac9, 0x4175,
+ 0x7aca, 0x20e2,
+ 0x7acb, 0x09eb,
+ 0x7acc, 0x4176,
+ 0x7ad6, 0x0d91,
+ 0x7ad7, 0x4180,
+ 0x7ad9, 0x115f,
+ 0x7ada, 0x4182,
+ 0x7ade, 0x08e9,
+ 0x7adf, 0x08e8,
+ 0x7ae0, 0x1163,
+ 0x7ae1, 0x4186,
+ 0x7ae3, 0x092f,
+ 0x7ae4, 0x4188,
+ 0x7ae5, 0x0e60,
+ 0x7ae6, 0x1b99,
+ 0x7ae7, 0x4189,
+ 0x7aea, 0x2141,
+ 0x7aeb, 0x418c,
+ 0x7aed, 0x08b0,
+ 0x7aee, 0x418e,
+ 0x7aef, 0x060a,
+ 0x7af0, 0x418f,
+ 0x7af6, 0x1fc7,
+ 0x7af7, 0x4195,
+ 0x7af9, 0x11f0,
+ 0x7afa, 0x1c63,
+ 0x7afb, 0x4197,
+ 0x7afd, 0x1c64,
+ 0x7afe, 0x4199,
+ 0x7aff, 0x06c8,
+ 0x7b00, 0x419a,
+ 0x7b03, 0x1c66,
+ 0x7b05, 0x419d,
+ 0x7b06, 0x03d5,
+ 0x7b07, 0x419e,
+ 0x7b08, 0x1c65,
+ 0x7b09, 0x419f,
+ 0x7b0a, 0x1c69,
+ 0x7b0b, 0x0de6,
+ 0x7b0c, 0x41a0,
+ 0x7b0f, 0x1c6b,
+ 0x7b10, 0x41a3,
+ 0x7b11, 0x0f71,
+ 0x7b12, 0x41a4,
+ 0x7b14, 0x0433,
+ 0x7b15, 0x1c68,
+ 0x7b16, 0x41a6,
+ 0x7b19, 0x1c6f,
+ 0x7b1a, 0x41a9,
+ 0x7b1b, 0x05b2,
+ 0x7b1c, 0x41aa,
+ 0x7b1e, 0x1c77,
+ 0x7b1f, 0x41ac,
+ 0x7b20, 0x1c72,
+ 0x7b21, 0x41ad,
+ 0x7b24, 0x1c74,
+ 0x7b25, 0x1c73,
+ 0x7b26, 0x0698,
+ 0x7b27, 0x41b0,
+ 0x7b28, 0x0428,
+ 0x7b29, 0x41b1,
+ 0x7b2a, 0x1c6e,
+ 0x7b2b, 0x1c6a,
+ 0x7b2c, 0x05bb,
+ 0x7b2d, 0x41b2,
+ 0x7b2e, 0x1c70,
+ 0x7b2f, 0x41b3,
+ 0x7b31, 0x1c71,
+ 0x7b32, 0x41b5,
+ 0x7b33, 0x1c75,
+ 0x7b34, 0x41b6,
+ 0x7b38, 0x1c6d,
+ 0x7b39, 0x41ba,
+ 0x7b3a, 0x0856,
+ 0x7b3b, 0x41bb,
+ 0x7b3c, 0x0a46,
+ 0x7b3d, 0x41bc,
+ 0x7b3e, 0x1c76,
+ 0x7b3f, 0x41bd,
+ 0x7b45, 0x1c7a,
+ 0x7b46, 0x1e41,
+ 0x7b47, 0x1c6c,
+ 0x7b48, 0x41c3,
+ 0x7b49, 0x05a9,
+ 0x7b4a, 0x41c4,
+ 0x7b4b, 0x08bf,
+ 0x7b4c, 0x1c7c,
+ 0x7b4d, 0x41c5,
+ 0x7b4f, 0x0641,
+ 0x7b50, 0x097d,
+ 0x7b51, 0x11fd,
+ 0x7b52, 0x0e63,
+ 0x7b53, 0x41c7,
+ 0x7b54, 0x0573,
+ 0x7b55, 0x41c8,
+ 0x7b56, 0x04a6,
+ 0x7b57, 0x41c9,
+ 0x7b58, 0x1c78,
+ 0x7b59, 0x41ca,
+ 0x7b5a, 0x1c79,
+ 0x7b5b, 0x0cf1,
+ 0x7b5c, 0x41cb,
+ 0x7b5d, 0x1c7d,
+ 0x7b5e, 0x41cc,
+ 0x7b60, 0x1c7e,
+ 0x7b61, 0x41ce,
+ 0x7b62, 0x1c81,
+ 0x7b63, 0x41cf,
+ 0x7b67, 0x25e4,
+ 0x7b68, 0x41d3,
+ 0x7b6e, 0x1c7f,
+ 0x7b6f, 0x41d9,
+ 0x7b71, 0x1c83,
+ 0x7b72, 0x1c82,
+ 0x7b73, 0x41db,
+ 0x7b75, 0x1c7b,
+ 0x7b76, 0x41dd,
+ 0x7b77, 0x0977,
+ 0x7b78, 0x41de,
+ 0x7b79, 0x0514,
+ 0x7b7a, 0x41df,
+ 0x7b7b, 0x1c80,
+ 0x7b7c, 0x41e0,
+ 0x7b7e, 0x0c26,
+ 0x7b7f, 0x41e2,
+ 0x7b80, 0x0865,
+ 0x7b81, 0x41e3,
+ 0x7b85, 0x1c8b,
+ 0x7b86, 0x41e7,
+ 0x7b8b, 0x1f86,
+ 0x7b8c, 0x41ec,
+ 0x7b8d, 0x0718,
+ 0x7b8e, 0x41ed,
+ 0x7b90, 0x1c84,
+ 0x7b91, 0x41ef,
+ 0x7b94, 0x0474,
+ 0x7b95, 0x0813,
+ 0x7b96, 0x41f2,
+ 0x7b97, 0x0dd8,
+ 0x7b98, 0x41f3,
+ 0x7b9c, 0x1c8d,
+ 0x7b9d, 0x1c89,
+ 0x7b9e, 0x41f7,
+ 0x7ba1, 0x0735,
+ 0x7ba2, 0x1c8e,
+ 0x7ba3, 0x41fa,
+ 0x7ba6, 0x1c85,
+ 0x7ba8, 0x1c8a,
+ 0x7ba9, 0x0a88,
+ 0x7baa, 0x1c8c,
+ 0x7bab, 0x1c8f,
+ 0x7bac, 0x1c88,
+ 0x7bad, 0x0870,
+ 0x7bae, 0x41fd,
+ 0x7bb1, 0x0f51,
+ 0x7bb2, 0x4200,
+ 0x7bb4, 0x1c90,
+ 0x7bb5, 0x4202,
+ 0x7bb8, 0x1c87,
+ 0x7bb9, 0x4205,
+ 0x7bc0, 0x1fb3,
+ 0x7bc1, 0x1c92,
+ 0x7bc2, 0x420c,
+ 0x7bc4, 0x1eef,
+ 0x7bc5, 0x420e,
+ 0x7bc6, 0x120a,
+ 0x7bc7, 0x0bc9,
+ 0x7bc8, 0x420f,
+ 0x7bc9, 0x22a4,
+ 0x7bca, 0x4210,
+ 0x7bcb, 0x25e8,
+ 0x7bcc, 0x1c93,
+ 0x7bcd, 0x4211,
+ 0x7bd1, 0x1c91,
+ 0x7bd2, 0x4215,
+ 0x7bd3, 0x0a4f,
+ 0x7bd4, 0x4216,
+ 0x7bd9, 0x06d8,
+ 0x7bda, 0x1c95,
+ 0x7bdb, 0x421b,
+ 0x7bdd, 0x1c94,
+ 0x7bde, 0x421d,
+ 0x7be1, 0x055e,
+ 0x7be2, 0x4220,
+ 0x7be4, 0x25e3,
+ 0x7be5, 0x1c96,
+ 0x7be7, 0x4222,
+ 0x7be9, 0x2111,
+ 0x7bea, 0x1c98,
+ 0x7beb, 0x4224,
+ 0x7bee, 0x09a5,
+ 0x7bef, 0x4227,
+ 0x7bf1, 0x09d4,
+ 0x7bf2, 0x4229,
+ 0x7bf3, 0x25e6,
+ 0x7bf4, 0x422a,
+ 0x7bf7, 0x0bb2,
+ 0x7bf8, 0x422d,
+ 0x7bfc, 0x1c9b,
+ 0x7bfd, 0x4231,
+ 0x7bfe, 0x1c9a,
+ 0x7bff, 0x4232,
+ 0x7c00, 0x25e7,
+ 0x7c01, 0x4233,
+ 0x7c07, 0x055b,
+ 0x7c08, 0x4239,
+ 0x7c0b, 0x1c9e,
+ 0x7c0c, 0x1c99,
+ 0x7c0d, 0x2041,
+ 0x7c0e, 0x423c,
+ 0x7c0f, 0x1c9c,
+ 0x7c10, 0x423d,
+ 0x7c16, 0x1c9d,
+ 0x7c17, 0x4243,
+ 0x7c1e, 0x25ea,
+ 0x7c1f, 0x1c9f,
+ 0x7c20, 0x424a,
+ 0x7c21, 0x1f8f,
+ 0x7c22, 0x424b,
+ 0x7c23, 0x25ec,
+ 0x7c24, 0x424c,
+ 0x7c26, 0x1ca1,
+ 0x7c27, 0x07de,
+ 0x7c28, 0x424e,
+ 0x7c2a, 0x1ca0,
+ 0x7c2b, 0x25eb,
+ 0x7c2c, 0x4250,
+ 0x7c38, 0x1ca2,
+ 0x7c39, 0x425c,
+ 0x7c3d, 0x20d0,
+ 0x7c3e, 0x201d,
+ 0x7c3f, 0x0485,
+ 0x7c40, 0x1ca4,
+ 0x7c41, 0x1ca3,
+ 0x7c42, 0x4260,
+ 0x7c43, 0x1ff7,
+ 0x7c44, 0x4261,
+ 0x7c4c, 0x1e8d,
+ 0x7c4d, 0x0821,
+ 0x7c4e, 0x4269,
+ 0x7c5c, 0x25e9,
+ 0x7c5d, 0x4277,
+ 0x7c5f, 0x25ee,
+ 0x7c60, 0x203a,
+ 0x7c61, 0x4279,
+ 0x7c64, 0x2693,
+ 0x7c65, 0x427c,
+ 0x7c69, 0x25e5,
+ 0x7c6a, 0x25ed,
+ 0x7c6b, 0x4280,
+ 0x7c6c, 0x2009,
+ 0x7c6d, 0x4281,
+ 0x7c6e, 0x2065,
+ 0x7c6f, 0x4282,
+ 0x7c72, 0x26a3,
+ 0x7c73, 0x0adc,
+ 0x7c74, 0x12f5,
+ 0x7c75, 0x4285,
+ 0x7c7b, 0x09cb,
+ 0x7c7c, 0x1cca,
+ 0x7c7d, 0x122e,
+ 0x7c7e, 0x428b,
+ 0x7c89, 0x0678,
+ 0x7c8a, 0x4296,
+ 0x7c91, 0x1ccc,
+ 0x7c92, 0x09ec,
+ 0x7c93, 0x429d,
+ 0x7c95, 0x0be8,
+ 0x7c96, 0x429f,
+ 0x7c97, 0x0559,
+ 0x7c98, 0x1154,
+ 0x7c99, 0x42a0,
+ 0x7c9c, 0x1cce,
+ 0x7c9d, 0x1ccd,
+ 0x7c9e, 0x1ccf,
+ 0x7c9f, 0x0dcf,
+ 0x7ca0, 0x42a3,
+ 0x7ca2, 0x1cd0,
+ 0x7ca3, 0x42a5,
+ 0x7ca4, 0x1104,
+ 0x7ca5, 0x11df,
+ 0x7ca6, 0x42a6,
+ 0x7caa, 0x067d,
+ 0x7cab, 0x42aa,
+ 0x7cae, 0x0a01,
+ 0x7caf, 0x42ad,
+ 0x7cb1, 0x0a04,
+ 0x7cb2, 0x1cd1,
+ 0x7cb3, 0x08db,
+ 0x7cb4, 0x42af,
+ 0x7cb9, 0x0565,
+ 0x7cba, 0x42b4,
+ 0x7cbc, 0x1cd2,
+ 0x7cbe, 0x08da,
+ 0x7cbf, 0x42b6,
+ 0x7cc1, 0x1cd4,
+ 0x7cc2, 0x42b8,
+ 0x7cc5, 0x1cd9,
+ 0x7cc6, 0x42bb,
+ 0x7cc7, 0x1cd5,
+ 0x7cc8, 0x1cd8,
+ 0x7cc9, 0x42bc,
+ 0x7cca, 0x07b4,
+ 0x7ccb, 0x42bd,
+ 0x7ccc, 0x1cd6,
+ 0x7cce, 0x42be,
+ 0x7cd5, 0x06dd,
+ 0x7cd6, 0x0e1a,
+ 0x7cd7, 0x1cda,
+ 0x7cd8, 0x42c5,
+ 0x7cd9, 0x04a1,
+ 0x7cda, 0x42c6,
+ 0x7cdc, 0x0ad8,
+ 0x7cdd, 0x25f5,
+ 0x7cde, 0x1efc,
+ 0x7cdf, 0x1126,
+ 0x7ce0, 0x0944,
+ 0x7ce1, 0x42c8,
+ 0x7ce7, 0x2024,
+ 0x7ce8, 0x1cdb,
+ 0x7ce9, 0x42ce,
+ 0x7cef, 0x0b75,
+ 0x7cf0, 0x269b,
+ 0x7cf1, 0x42d4,
+ 0x7cf2, 0x25f3,
+ 0x7cf3, 0x42d5,
+ 0x7cf4, 0x22d9,
+ 0x7cf5, 0x42d6,
+ 0x7cf6, 0x25f4,
+ 0x7cf7, 0x42d7,
+ 0x7cf8, 0x1ce7,
+ 0x7cf9, 0x241b,
+ 0x7cfa, 0x42d8,
+ 0x7cfb, 0x0f22,
+ 0x7cfc, 0x42d9,
+ 0x7cfe, 0x1fc8,
+ 0x7cff, 0x42db,
+ 0x7d00, 0x1f7b,
+ 0x7d01, 0x42dc,
+ 0x7d02, 0x241d,
+ 0x7d03, 0x42dd,
+ 0x7d04, 0x224c,
+ 0x7d05, 0x1f48,
+ 0x7d06, 0x241c,
+ 0x7d07, 0x241e,
+ 0x7d09, 0x20ff,
+ 0x7d0a, 0x0ed8,
+ 0x7d0b, 0x219a,
+ 0x7d0c, 0x42de,
+ 0x7d0d, 0x2091,
+ 0x7d0e, 0x42df,
+ 0x7d10, 0x20a7,
+ 0x7d11, 0x42e1,
+ 0x7d13, 0x2423,
+ 0x7d14, 0x1e9b,
+ 0x7d15, 0x2422,
+ 0x7d16, 0x42e3,
+ 0x7d17, 0x2110,
+ 0x7d18, 0x42e4,
+ 0x7d19, 0x228d,
+ 0x7d1a, 0x1f71,
+ 0x7d1b, 0x1ef8,
+ 0x7d1c, 0x2421,
+ 0x7d1d, 0x42e5,
+ 0x7d20, 0x0dcd,
+ 0x7d21, 0x1ef3,
+ 0x7d22, 0x0dec,
+ 0x7d23, 0x42e8,
+ 0x7d27, 0x08c5,
+ 0x7d28, 0x42ec,
+ 0x7d2b, 0x122c,
+ 0x7d2c, 0x42ef,
+ 0x7d2f, 0x09c6,
+ 0x7d30, 0x21b1,
+ 0x7d31, 0x2426,
+ 0x7d32, 0x2425,
+ 0x7d33, 0x2120,
+ 0x7d34, 0x42f2,
+ 0x7d39, 0x211a,
+ 0x7d3a, 0x2424,
+ 0x7d3b, 0x42f7,
+ 0x7d3c, 0x2428,
+ 0x7d3d, 0x42f8,
+ 0x7d3f, 0x242a,
+ 0x7d40, 0x2429,
+ 0x7d41, 0x42fa,
+ 0x7d42, 0x2294,
+ 0x7d43, 0x42fb,
+ 0x7d44, 0x22be,
+ 0x7d45, 0x42fc,
+ 0x7d46, 0x1e31,
+ 0x7d47, 0x42fd,
+ 0x7d4e, 0x242c,
+ 0x7d4f, 0x4304,
+ 0x7d50, 0x1fb5,
+ 0x7d51, 0x4305,
+ 0x7d5d, 0x242b,
+ 0x7d5e, 0x1faf,
+ 0x7d5f, 0x4311,
+ 0x7d61, 0x2068,
+ 0x7d62, 0x21e4,
+ 0x7d63, 0x4313,
+ 0x7d66, 0x1f21,
+ 0x7d67, 0x4316,
+ 0x7d68, 0x2101,
+ 0x7d69, 0x4317,
+ 0x7d6e, 0x0fc0,
+ 0x7d6f, 0x431c,
+ 0x7d71, 0x217c,
+ 0x7d72, 0x214a,
+ 0x7d73, 0x242d,
+ 0x7d74, 0x431e,
+ 0x7d76, 0x1fd4,
+ 0x7d77, 0x1ce8,
+ 0x7d78, 0x4320,
+ 0x7d79, 0x1fd1,
+ 0x7d7a, 0x4321,
+ 0x7d81, 0x1e33,
+ 0x7d82, 0x4328,
+ 0x7d83, 0x242f,
+ 0x7d84, 0x4329,
+ 0x7d86, 0x242e,
+ 0x7d87, 0x432b,
+ 0x7d88, 0x2430,
+ 0x7d89, 0x21db,
+ 0x7d8a, 0x432c,
+ 0x7d8f, 0x2158,
+ 0x7d90, 0x4331,
+ 0x7d93, 0x1fc2,
+ 0x7d94, 0x4334,
+ 0x7d9c, 0x22b9,
+ 0x7d9d, 0x433c,
+ 0x7d9e, 0x2436,
+ 0x7d9f, 0x433d,
+ 0x7da2, 0x1e8e,
+ 0x7da3, 0x2439,
+ 0x7da4, 0x4340,
+ 0x7da6, 0x1ce9,
+ 0x7da7, 0x4342,
+ 0x7dab, 0x21c5,
+ 0x7dac, 0x2437,
+ 0x7dad, 0x2192,
+ 0x7dae, 0x1cea,
+ 0x7daf, 0x4346,
+ 0x7db0, 0x243a,
+ 0x7db1, 0x1f19,
+ 0x7db2, 0x218c,
+ 0x7db3, 0x1e40,
+ 0x7db4, 0x22b3,
+ 0x7db5, 0x4347,
+ 0x7db8, 0x205f,
+ 0x7db9, 0x2438,
+ 0x7dba, 0x2432,
+ 0x7dbb, 0x2274,
+ 0x7dbc, 0x434a,
+ 0x7dbd, 0x1e9c,
+ 0x7dbe, 0x2431,
+ 0x7dbf, 0x2085,
+ 0x7dc0, 0x434b,
+ 0x7dc4, 0x2435,
+ 0x7dc5, 0x434f,
+ 0x7dc7, 0x243b,
+ 0x7dc8, 0x4351,
+ 0x7dca, 0x1fb7,
+ 0x7dcb, 0x2433,
+ 0x7dcc, 0x4353,
+ 0x7dd1, 0x2054,
+ 0x7dd2, 0x21de,
+ 0x7dd3, 0x4358,
+ 0x7dd4, 0x2434,
+ 0x7dd5, 0x4359,
+ 0x7dd7, 0x243d,
+ 0x7dd8, 0x1f89,
+ 0x7dd9, 0x243c,
+ 0x7dda, 0x435b,
+ 0x7ddd, 0x1f6e,
+ 0x7dde, 0x1ed8,
+ 0x7ddf, 0x435e,
+ 0x7de0, 0x1ebf,
+ 0x7de1, 0x2445,
+ 0x7de2, 0x435f,
+ 0x7de3, 0x2249,
+ 0x7de4, 0x4360,
+ 0x7de6, 0x2441,
+ 0x7de7, 0x4362,
+ 0x7de8, 0x1e47,
+ 0x7de9, 0x1f56,
+ 0x7dea, 0x4363,
+ 0x7dec, 0x2086,
+ 0x7ded, 0x4365,
+ 0x7def, 0x2196,
+ 0x7df0, 0x4367,
+ 0x7df1, 0x2443,
+ 0x7df2, 0x243f,
+ 0x7df3, 0x4368,
+ 0x7df4, 0x2023,
+ 0x7df5, 0x4369,
+ 0x7df6, 0x2442,
+ 0x7df7, 0x436a,
+ 0x7df9, 0x243e,
+ 0x7dfa, 0x436c,
+ 0x7dfb, 0x26a6,
+ 0x7dfc, 0x436d,
+ 0x7e00, 0x4371,
+ 0x7e08, 0x234e,
+ 0x7e09, 0x2446,
+ 0x7e0a, 0x244b,
+ 0x7e0b, 0x2444,
+ 0x7e0c, 0x4379,
+ 0x7e10, 0x2427,
+ 0x7e11, 0x244c,
+ 0x7e12, 0x437d,
+ 0x7e1b, 0x1f0f,
+ 0x7e1c, 0x4386,
+ 0x7e1d, 0x2447,
+ 0x7e1e, 0x2449,
+ 0x7e1f, 0x2448,
+ 0x7e20, 0x4387,
+ 0x7e23, 0x21c2,
+ 0x7e24, 0x438a,
+ 0x7e27, 0x216e,
+ 0x7e28, 0x438d,
+ 0x7e2b, 0x1f03,
+ 0x7e2c, 0x4390,
+ 0x7e2d, 0x244a,
+ 0x7e2e, 0x215c,
+ 0x7e2f, 0x4391,
+ 0x7e31, 0x22bb,
+ 0x7e32, 0x2450,
+ 0x7e33, 0x4393,
+ 0x7e34, 0x2694,
+ 0x7e35, 0x244f,
+ 0x7e36, 0x25f6,
+ 0x7e37, 0x2051,
+ 0x7e38, 0x4394,
+ 0x7e39, 0x244e,
+ 0x7e3a, 0x4395,
+ 0x7e3b, 0x1dfb,
+ 0x7e3c, 0x4396,
+ 0x7e3d, 0x22ba,
+ 0x7e3e, 0x1f6d,
+ 0x7e3f, 0x4397,
+ 0x7e41, 0x064e,
+ 0x7e42, 0x4399,
+ 0x7e45, 0x2452,
+ 0x7e46, 0x2451,
+ 0x7e47, 0x1ceb,
+ 0x7e48, 0x439c,
+ 0x7e52, 0x2455,
+ 0x7e53, 0x43a6,
+ 0x7e54, 0x2289,
+ 0x7e55, 0x2116,
+ 0x7e56, 0x43a7,
+ 0x7e5a, 0x2454,
+ 0x7e5b, 0x43ab,
+ 0x7e5e, 0x20fb,
+ 0x7e5f, 0x43ae,
+ 0x7e62, 0x2440,
+ 0x7e63, 0x43b1,
+ 0x7e69, 0x2126,
+ 0x7e6a, 0x1f61,
+ 0x7e6b, 0x269d,
+ 0x7e6c, 0x43b7,
+ 0x7e6d, 0x1f8a,
+ 0x7e6e, 0x2456,
+ 0x7e6f, 0x2459,
+ 0x7e70, 0x2458,
+ 0x7e71, 0x43b8,
+ 0x7e73, 0x1fae,
+ 0x7e74, 0x43ba,
+ 0x7e79, 0x221a,
+ 0x7e7a, 0x43bf,
+ 0x7e7c, 0x1f7a,
+ 0x7e7d, 0x244d,
+ 0x7e7e, 0x2457,
+ 0x7e7f, 0x43c1,
+ 0x7e82, 0x1248,
+ 0x7e83, 0x43c4,
+ 0x7e88, 0x2453,
+ 0x7e89, 0x43c9,
+ 0x7e8a, 0x2420,
+ 0x7e8b, 0x43ca,
+ 0x7e8c, 0x21df,
+ 0x7e8d, 0x2685,
+ 0x7e8e, 0x43cb,
+ 0x7e8f, 0x1e6e,
+ 0x7e90, 0x43cc,
+ 0x7e93, 0x2224,
+ 0x7e94, 0x2670,
+ 0x7e95, 0x43cf,
+ 0x7e96, 0x21ba,
+ 0x7e97, 0x43d0,
+ 0x7e98, 0x245a,
+ 0x7e99, 0x43d1,
+ 0x7e9b, 0x1cec,
+ 0x7e9c, 0x1fff,
+ 0x7e9d, 0x43d3,
+ 0x7e9f, 0x17d3,
+ 0x7ea0, 0x08ef,
+ 0x7ea1, 0x17d4,
+ 0x7ea2, 0x07a3,
+ 0x7ea3, 0x17d5,
+ 0x7ea4, 0x0f38,
+ 0x7ea5, 0x17d6,
+ 0x7ea6, 0x10ff,
+ 0x7ea7, 0x0829,
+ 0x7ea8, 0x17d7,
+ 0x7eaa, 0x0840,
+ 0x7eab, 0x0cad,
+ 0x7eac, 0x0ec2,
+ 0x7ead, 0x17d9,
+ 0x7eae, 0x43d5,
+ 0x7eaf, 0x0542,
+ 0x7eb0, 0x17da,
+ 0x7eb1, 0x0ced,
+ 0x7eb2, 0x06d4,
+ 0x7eb3, 0x0b2c,
+ 0x7eb4, 0x43d6,
+ 0x7eb5, 0x123a,
+ 0x7eb6, 0x0a81,
+ 0x7eb7, 0x0674,
+ 0x7eb8, 0x11bc,
+ 0x7eb9, 0x0ed5,
+ 0x7eba, 0x0661,
+ 0x7ebb, 0x43d7,
+ 0x7ebd, 0x0b67,
+ 0x7ebe, 0x17db,
+ 0x7ebf, 0x0f4c,
+ 0x7ec0, 0x17dc,
+ 0x7ec3, 0x0a00,
+ 0x7ec4, 0x1246,
+ 0x7ec5, 0x0d29,
+ 0x7ec6, 0x0f25,
+ 0x7ec7, 0x11ae,
+ 0x7ec8, 0x11d4,
+ 0x7ec9, 0x17df,
+ 0x7eca, 0x03f8,
+ 0x7ecb, 0x17e0,
+ 0x7ecd, 0x0d15,
+ 0x7ece, 0x1076,
+ 0x7ecf, 0x08dc,
+ 0x7ed0, 0x17e2,
+ 0x7ed1, 0x03fe,
+ 0x7ed2, 0x0cb9,
+ 0x7ed3, 0x08b2,
+ 0x7ed4, 0x17e3,
+ 0x7ed5, 0x0ca1,
+ 0x7ed6, 0x43d9,
+ 0x7ed7, 0x17e4,
+ 0x7ed8, 0x07fb,
+ 0x7ed9, 0x06f3,
+ 0x7eda, 0x0fcd,
+ 0x7edb, 0x17e5,
+ 0x7edc, 0x0a8e,
+ 0x7edd, 0x0927,
+ 0x7ede, 0x089b,
+ 0x7edf, 0x0e64,
+ 0x7ee0, 0x17e6,
+ 0x7ee2, 0x091d,
+ 0x7ee3, 0x0fb0,
+ 0x7ee4, 0x43da,
+ 0x7ee5, 0x0ddc,
+ 0x7ee6, 0x0e23,
+ 0x7ee7, 0x083f,
+ 0x7ee8, 0x17e8,
+ 0x7ee9, 0x081b,
+ 0x7eea, 0x0fc2,
+ 0x7eeb, 0x17e9,
+ 0x7eec, 0x43db,
+ 0x7eed, 0x0fc3,
+ 0x7eee, 0x17ea,
+ 0x7ef0, 0x0545,
+ 0x7ef1, 0x17ec,
+ 0x7ef3, 0x0d37,
+ 0x7ef4, 0x0ebb,
+ 0x7ef5, 0x0ae5,
+ 0x7ef6, 0x17ef,
+ 0x7ef7, 0x042a,
+ 0x7ef8, 0x0516,
+ 0x7ef9, 0x43dc,
+ 0x7efa, 0x17f0,
+ 0x7efc, 0x1238,
+ 0x7efd, 0x1161,
+ 0x7efe, 0x17f2,
+ 0x7eff, 0x0a73,
+ 0x7f00, 0x1217,
+ 0x7f01, 0x17f3,
+ 0x7f04, 0x085d,
+ 0x7f05, 0x0aea,
+ 0x7f06, 0x09ad,
+ 0x7f07, 0x17f6,
+ 0x7f09, 0x081c,
+ 0x7f0a, 0x43dd,
+ 0x7f0b, 0x17f8,
+ 0x7f0d, 0x17ee,
+ 0x7f0e, 0x060f,
+ 0x7f0f, 0x17fa,
+ 0x7f10, 0x43de,
+ 0x7f11, 0x17fb,
+ 0x7f13, 0x07cf,
+ 0x7f14, 0x05bf,
+ 0x7f15, 0x0a6d,
+ 0x7f16, 0x0449,
+ 0x7f17, 0x17fd,
+ 0x7f18, 0x10f8,
+ 0x7f19, 0x17fe,
+ 0x7f1a, 0x06ba,
+ 0x7f1b, 0x1800,
+ 0x7f1c, 0x17ff,
+ 0x7f1d, 0x0689,
+ 0x7f1e, 0x43df,
+ 0x7f1f, 0x1801,
+ 0x7f20, 0x04bf,
+ 0x7f21, 0x1802,
+ 0x7f28, 0x108c,
+ 0x7f29, 0x0dea,
+ 0x7f2a, 0x1809,
+ 0x7f2e, 0x0d02,
+ 0x7f2f, 0x180d,
+ 0x7f34, 0x089a,
+ 0x7f35, 0x1812,
+ 0x7f36, 0x1c5e,
+ 0x7f37, 0x43e0,
+ 0x7f38, 0x06d2,
+ 0x7f39, 0x43e1,
+ 0x7f3a, 0x0c8c,
+ 0x7f3b, 0x43e2,
+ 0x7f42, 0x1c5f,
+ 0x7f43, 0x43e9,
+ 0x7f44, 0x1c60,
+ 0x7f46, 0x43ea,
+ 0x7f4c, 0x25e2,
+ 0x7f4d, 0x43f0,
+ 0x7f4e, 0x269a,
+ 0x7f4f, 0x43f1,
+ 0x7f50, 0x0737,
+ 0x7f51, 0x0ea9,
+ 0x7f52, 0x43f2,
+ 0x7f54, 0x129e,
+ 0x7f55, 0x0768,
+ 0x7f56, 0x43f4,
+ 0x7f57, 0x0a85,
+ 0x7f58, 0x1a81,
+ 0x7f59, 0x43f5,
+ 0x7f5a, 0x0640,
+ 0x7f5b, 0x43f6,
+ 0x7f5f, 0x1a83,
+ 0x7f60, 0x43fa,
+ 0x7f61, 0x1a82,
+ 0x7f62, 0x03e0,
+ 0x7f63, 0x43fb,
+ 0x7f68, 0x1a85,
+ 0x7f69, 0x1177,
+ 0x7f6a, 0x124c,
+ 0x7f6b, 0x4400,
+ 0x7f6e, 0x11c2,
+ 0x7f6f, 0x4403,
+ 0x7f70, 0x1eea,
+ 0x7f71, 0x1a87,
+ 0x7f72, 0x0d87,
+ 0x7f73, 0x4404,
+ 0x7f74, 0x1a86,
+ 0x7f75, 0x4405,
+ 0x7f77, 0x1e2c,
+ 0x7f78, 0x4407,
+ 0x7f79, 0x1a88,
+ 0x7f7a, 0x4408,
+ 0x7f7e, 0x1a8a,
+ 0x7f7f, 0x440c,
+ 0x7f81, 0x1a89,
+ 0x7f82, 0x440e,
+ 0x7f85, 0x2062,
+ 0x7f86, 0x24f1,
+ 0x7f87, 0x4411,
+ 0x7f88, 0x24f2,
+ 0x7f89, 0x4412,
+ 0x7f8a, 0x101b,
+ 0x7f8b, 0x4413,
+ 0x7f8c, 0x0c39,
+ 0x7f8d, 0x4414,
+ 0x7f8e, 0x0ac5,
+ 0x7f8f, 0x4415,
+ 0x7f94, 0x06dc,
+ 0x7f95, 0x441a,
+ 0x7f9a, 0x0a30,
+ 0x7f9b, 0x441f,
+ 0x7f9d, 0x1cc4,
+ 0x7f9e, 0x0faa,
+ 0x7f9f, 0x1cc5,
+ 0x7fa0, 0x4421,
+ 0x7fa1, 0x0f48,
+ 0x7fa2, 0x4422,
+ 0x7fa4, 0x0c95,
+ 0x7fa5, 0x25f2,
+ 0x7fa6, 0x4424,
+ 0x7fa7, 0x1cc6,
+ 0x7fa8, 0x4425,
+ 0x7fa9, 0x2215,
+ 0x7faa, 0x4426,
+ 0x7faf, 0x1cc7,
+ 0x7fb1, 0x442b,
+ 0x7fb2, 0x1cc9,
+ 0x7fb3, 0x442c,
+ 0x7fb8, 0x130e,
+ 0x7fb9, 0x06f9,
+ 0x7fba, 0x4431,
+ 0x7fbc, 0x176d,
+ 0x7fbd, 0x10d5,
+ 0x7fbe, 0x4433,
+ 0x7fbf, 0x1cde,
+ 0x7fc0, 0x4434,
+ 0x7fc1, 0x0edb,
+ 0x7fc2, 0x4435,
+ 0x7fc5, 0x0506,
+ 0x7fc6, 0x4438,
+ 0x7fca, 0x1b98,
+ 0x7fcb, 0x443c,
+ 0x7fcc, 0x1075,
+ 0x7fcd, 0x443d,
+ 0x7fce, 0x1cdf,
+ 0x7fcf, 0x443e,
+ 0x7fd2, 0x21ae,
+ 0x7fd3, 0x4441,
+ 0x7fd4, 0x0f55,
+ 0x7fd5, 0x1ce0,
+ 0x7fd6, 0x4442,
+ 0x7fd8, 0x0c49,
+ 0x7fd9, 0x4444,
+ 0x7fdf, 0x05b5,
+ 0x7fe0, 0x0567,
+ 0x7fe1, 0x1ce2,
+ 0x7fe2, 0x444a,
+ 0x7fe5, 0x1ce1,
+ 0x7fe6, 0x1ce3,
+ 0x7fe7, 0x444d,
+ 0x7fe9, 0x1ce4,
+ 0x7fea, 0x444f,
+ 0x7fee, 0x1ce5,
+ 0x7fef, 0x4453,
+ 0x7ff0, 0x0769,
+ 0x7ff1, 0x03ca,
+ 0x7ff2, 0x4454,
+ 0x7ff3, 0x1ce6,
+ 0x7ff4, 0x4455,
+ 0x7ff9, 0x20e0,
+ 0x7ffa, 0x445a,
+ 0x7ffb, 0x064a,
+ 0x7ffc, 0x1074,
+ 0x7ffd, 0x445b,
+ 0x8000, 0x1032,
+ 0x8001, 0x09ba,
+ 0x8002, 0x445e,
+ 0x8003, 0x0949,
+ 0x8004, 0x1953,
+ 0x8005, 0x1180,
+ 0x8006, 0x191a,
+ 0x8007, 0x445f,
+ 0x800b, 0x1bd7,
+ 0x800c, 0x0637,
+ 0x800d, 0x0d98,
+ 0x800e, 0x4463,
+ 0x8010, 0x0b30,
+ 0x8011, 0x4465,
+ 0x8012, 0x1bcb,
+ 0x8013, 0x4466,
+ 0x8014, 0x1bcc,
+ 0x8015, 0x06f6,
+ 0x8016, 0x1bcd,
+ 0x8017, 0x077b,
+ 0x8018, 0x1108,
+ 0x8019, 0x03dd,
+ 0x801a, 0x4467,
+ 0x801c, 0x1bce,
+ 0x801d, 0x4469,
+ 0x8020, 0x1bcf,
+ 0x8021, 0x446c,
+ 0x8022, 0x1bd0,
+ 0x8023, 0x446d,
+ 0x8025, 0x1bd1,
+ 0x8028, 0x1bd5,
+ 0x8029, 0x1bd4,
+ 0x802a, 0x0b96,
+ 0x802b, 0x446f,
+ 0x802c, 0x25c2,
+ 0x802d, 0x4470,
+ 0x802e, 0x25c1,
+ 0x802f, 0x4471,
+ 0x8031, 0x1bd6,
+ 0x8032, 0x4473,
+ 0x8033, 0x0639,
+ 0x8034, 0x4474,
+ 0x8035, 0x1bd8,
+ 0x8036, 0x1035,
+ 0x8037, 0x14b1,
+ 0x8038, 0x0dbf,
+ 0x8039, 0x4475,
+ 0x803b, 0x0501,
+ 0x803c, 0x4477,
+ 0x803d, 0x0583,
+ 0x803e, 0x4478,
+ 0x803f, 0x06fb,
+ 0x8040, 0x4479,
+ 0x8042, 0x0b57,
+ 0x8043, 0x1bd9,
+ 0x8044, 0x447b,
+ 0x8046, 0x1bda,
+ 0x8047, 0x447d,
+ 0x804a, 0x0a0d,
+ 0x804b, 0x0a44,
+ 0x804c, 0x11af,
+ 0x804d, 0x1bdb,
+ 0x804e, 0x4480,
+ 0x8052, 0x1bdc,
+ 0x8053, 0x4484,
+ 0x8054, 0x09f3,
+ 0x8055, 0x4485,
+ 0x8056, 0x2128,
+ 0x8057, 0x4486,
+ 0x8058, 0x0bd7,
+ 0x8059, 0x4487,
+ 0x805a, 0x090a,
+ 0x805b, 0x4488,
+ 0x805e, 0x2199,
+ 0x805f, 0x448b,
+ 0x8069, 0x1bdd,
+ 0x806a, 0x0552,
+ 0x806b, 0x4495,
+ 0x806f, 0x2017,
+ 0x8070, 0x1ea0,
+ 0x8071, 0x1bde,
+ 0x8072, 0x2125,
+ 0x8073, 0x214d,
+ 0x8074, 0x4499,
+ 0x8075, 0x25c4,
+ 0x8076, 0x209d,
+ 0x8077, 0x228a,
+ 0x8078, 0x449a,
+ 0x8079, 0x25c3,
+ 0x807a, 0x449b,
+ 0x807d, 0x2179,
+ 0x807e, 0x2038,
+ 0x807f, 0x1a1e,
+ 0x8080, 0x1a1d,
+ 0x8081, 0x449e,
+ 0x8083, 0x0dd5,
+ 0x8084, 0x1065,
+ 0x8085, 0x2155,
+ 0x8086, 0x0db6,
+ 0x8087, 0x1179,
+ 0x8088, 0x44a0,
+ 0x8089, 0x0cbd,
+ 0x808a, 0x44a1,
+ 0x808b, 0x09ca,
+ 0x808c, 0x0814,
+ 0x808d, 0x44a2,
+ 0x8093, 0x1971,
+ 0x8094, 0x44a8,
+ 0x8096, 0x0f6f,
+ 0x8097, 0x44aa,
+ 0x8098, 0x11e1,
+ 0x8099, 0x44ab,
+ 0x809a, 0x0606,
+ 0x809b, 0x06d3,
+ 0x809c, 0x1970,
+ 0x809d, 0x06c9,
+ 0x809e, 0x44ac,
+ 0x809f, 0x196f,
+ 0x80a0, 0x04cb,
+ 0x80a1, 0x0722,
+ 0x80a2, 0x11aa,
+ 0x80a3, 0x44ad,
+ 0x80a4, 0x0691,
+ 0x80a5, 0x0667,
+ 0x80a6, 0x44ae,
+ 0x80a9, 0x085a,
+ 0x80aa, 0x065b,
+ 0x80ab, 0x1976,
+ 0x80ac, 0x44b1,
+ 0x80ad, 0x1977,
+ 0x80ae, 0x03c4,
+ 0x80af, 0x095c,
+ 0x80b0, 0x44b2,
+ 0x80b1, 0x1975,
+ 0x80b2, 0x10e2,
+ 0x80b3, 0x44b3,
+ 0x80b4, 0x1978,
+ 0x80b5, 0x44b4,
+ 0x80b7, 0x1979,
+ 0x80b8, 0x44b6,
+ 0x80ba, 0x066b,
+ 0x80bb, 0x44b8,
+ 0x80bc, 0x1972,
+ 0x80bd, 0x1974,
+ 0x80be, 0x0d2f,
+ 0x80bf, 0x11d6,
+ 0x80c0, 0x116e,
+ 0x80c1, 0x0f7d,
+ 0x80c2, 0x197f,
+ 0x80c3, 0x0ec7,
+ 0x80c4, 0x1980,
+ 0x80c5, 0x44b9,
+ 0x80c6, 0x0589,
+ 0x80c7, 0x44ba,
+ 0x80cc, 0x041c,
+ 0x80cd, 0x1982,
+ 0x80ce, 0x0df8,
+ 0x80cf, 0x44bf,
+ 0x80d6, 0x0b97,
+ 0x80d7, 0x1983,
+ 0x80d8, 0x44c6,
+ 0x80d9, 0x1981,
+ 0x80da, 0x0ba0,
+ 0x80db, 0x197e,
+ 0x80dc, 0x0d3b,
+ 0x80dd, 0x1985,
+ 0x80de, 0x0406,
+ 0x80df, 0x44c7,
+ 0x80e1, 0x07b1,
+ 0x80e2, 0x44c9,
+ 0x80e4, 0x126d,
+ 0x80e5, 0x1bc7,
+ 0x80e6, 0x44cb,
+ 0x80e7, 0x197a,
+ 0x80eb, 0x1986,
+ 0x80ec, 0x179a,
+ 0x80ed, 0x1989,
+ 0x80ee, 0x44cc,
+ 0x80ef, 0x0975,
+ 0x80f0, 0x104f,
+ 0x80f1, 0x1987,
+ 0x80f2, 0x198c,
+ 0x80f3, 0x06e7,
+ 0x80f4, 0x1988,
+ 0x80f5, 0x44cd,
+ 0x80f6, 0x088b,
+ 0x80f7, 0x44ce,
+ 0x80f8, 0x0fa3,
+ 0x80f9, 0x44cf,
+ 0x80fa, 0x03c2,
+ 0x80fb, 0x44d0,
+ 0x80fc, 0x198d,
+ 0x80fd, 0x0b3f,
+ 0x80fe, 0x44d1,
+ 0x8100, 0x44d3,
+ 0x8102, 0x11ab,
+ 0x8103, 0x44d5,
+ 0x8105, 0x21d2,
+ 0x8106, 0x0563,
+ 0x8107, 0x44d7,
+ 0x8109, 0x0a9d,
+ 0x810a, 0x082c,
+ 0x810b, 0x44d9,
+ 0x810d, 0x198a,
+ 0x810f, 0x1123,
+ 0x8110, 0x0c09,
+ 0x8111, 0x0b37,
+ 0x8112, 0x198f,
+ 0x8113, 0x0b68,
+ 0x8114, 0x1309,
+ 0x8115, 0x44db,
+ 0x8116, 0x0478,
+ 0x8117, 0x44dc,
+ 0x8118, 0x1994,
+ 0x8119, 0x44dd,
+ 0x811a, 0x0896,
+ 0x811b, 0x24c7,
+ 0x811c, 0x44de,
+ 0x811e, 0x1992,
+ 0x811f, 0x44e0,
+ 0x812c, 0x1993,
+ 0x812d, 0x44ed,
+ 0x812f, 0x06a7,
+ 0x8130, 0x44ef,
+ 0x8131, 0x0e82,
+ 0x8132, 0x1995,
+ 0x8133, 0x44f0,
+ 0x8136, 0x1991,
+ 0x8137, 0x44f3,
+ 0x8138, 0x09fc,
+ 0x8139, 0x2279,
+ 0x813a, 0x44f4,
+ 0x813e, 0x0bc1,
+ 0x813f, 0x44f8,
+ 0x8146, 0x0e46,
+ 0x8147, 0x44ff,
+ 0x8148, 0x1996,
+ 0x8149, 0x4500,
+ 0x814a, 0x099b,
+ 0x814b, 0x103f,
+ 0x814c, 0x1997,
+ 0x814d, 0x4501,
+ 0x814e, 0x2123,
+ 0x814f, 0x4502,
+ 0x8150, 0x06aa,
+ 0x8151, 0x06a8,
+ 0x8152, 0x4503,
+ 0x8153, 0x1998,
+ 0x8154, 0x0c38,
+ 0x8155, 0x0ea4,
+ 0x8156, 0x24c5,
+ 0x8157, 0x4504,
+ 0x8159, 0x199a,
+ 0x815b, 0x4506,
+ 0x8160, 0x199d,
+ 0x8161, 0x24c9,
+ 0x8162, 0x450b,
+ 0x8165, 0x0f93,
+ 0x8166, 0x2094,
+ 0x8167, 0x19a2,
+ 0x8168, 0x450e,
+ 0x8169, 0x199e,
+ 0x816a, 0x450f,
+ 0x816b, 0x2296,
+ 0x816c, 0x4510,
+ 0x816d, 0x19a1,
+ 0x816e, 0x0cd4,
+ 0x816f, 0x4511,
+ 0x8170, 0x1025,
+ 0x8171, 0x199c,
+ 0x8172, 0x4512,
+ 0x8174, 0x1999,
+ 0x8175, 0x4514,
+ 0x8178, 0x1e77,
+ 0x8179, 0x06b4,
+ 0x817a, 0x0f46,
+ 0x817b, 0x0b48,
+ 0x817c, 0x199f,
+ 0x817e, 0x0e2d,
+ 0x817f, 0x0e79,
+ 0x8180, 0x03fd,
+ 0x8181, 0x4517,
+ 0x8182, 0x19a6,
+ 0x8183, 0x4518,
+ 0x8188, 0x19a5,
+ 0x8189, 0x451d,
+ 0x818a, 0x0479,
+ 0x818b, 0x451e,
+ 0x818f, 0x06db,
+ 0x8190, 0x4522,
+ 0x8191, 0x19a7,
+ 0x8192, 0x4523,
+ 0x8198, 0x0455,
+ 0x8199, 0x4529,
+ 0x819a, 0x1f06,
+ 0x819b, 0x0e18,
+ 0x819c, 0x0b07,
+ 0x819d, 0x0f12,
+ 0x819e, 0x452a,
+ 0x81a0, 0x1fa5,
+ 0x81a1, 0x452c,
+ 0x81a3, 0x19a9,
+ 0x81a4, 0x452e,
+ 0x81a6, 0x19b0,
+ 0x81a7, 0x4530,
+ 0x81a8, 0x0bb3,
+ 0x81a9, 0x2099,
+ 0x81aa, 0x19aa,
+ 0x81ab, 0x4531,
+ 0x81b3, 0x0cfe,
+ 0x81b4, 0x4539,
+ 0x81ba, 0x1641,
+ 0x81bb, 0x19ae,
+ 0x81bc, 0x453f,
+ 0x81bd, 0x1ead,
+ 0x81be, 0x24c8,
+ 0x81bf, 0x20a8,
+ 0x81c0, 0x0e7f,
+ 0x81c1, 0x19af,
+ 0x81c2, 0x0444,
+ 0x81c3, 0x109c,
+ 0x81c4, 0x4540,
+ 0x81c6, 0x1063,
+ 0x81c7, 0x4542,
+ 0x81c9, 0x201f,
+ 0x81ca, 0x19ad,
+ 0x81cb, 0x4544,
+ 0x81cc, 0x19ab,
+ 0x81cd, 0x20c5,
+ 0x81ce, 0x4545,
+ 0x81cf, 0x24ca,
+ 0x81d0, 0x4546,
+ 0x81d8, 0x1ff0,
+ 0x81d9, 0x454e,
+ 0x81da, 0x24c6,
+ 0x81db, 0x454f,
+ 0x81df, 0x225d,
+ 0x81e0, 0x22de,
+ 0x81e1, 0x4553,
+ 0x81e3, 0x04e1,
+ 0x81e4, 0x4555,
+ 0x81e7, 0x1902,
+ 0x81e8, 0x202c,
+ 0x81e9, 0x4558,
+ 0x81ea, 0x1231,
+ 0x81eb, 0x4559,
+ 0x81ec, 0x1ca9,
+ 0x81ed, 0x0519,
+ 0x81ee, 0x455a,
+ 0x81f3, 0x11c0,
+ 0x81f5, 0x455f,
+ 0x81fa, 0x2161,
+ 0x81fb, 0x118a,
+ 0x81fc, 0x08f9,
+ 0x81fd, 0x4564,
+ 0x81fe, 0x1ca5,
+ 0x81ff, 0x4565,
+ 0x8200, 0x102f,
+ 0x8201, 0x1ca6,
+ 0x8203, 0x4566,
+ 0x8204, 0x1ca8,
+ 0x8205, 0x08fa,
+ 0x8206, 0x10c4,
+ 0x8207, 0x223b,
+ 0x8208, 0x21d9,
+ 0x8209, 0x1fcb,
+ 0x820a, 0x1fc9,
+ 0x820b, 0x4567,
+ 0x820c, 0x0d19,
+ 0x820e, 0x4568,
+ 0x8210, 0x1c62,
+ 0x8211, 0x456a,
+ 0x8212, 0x0d7d,
+ 0x8213, 0x456b,
+ 0x8214, 0x0e45,
+ 0x8215, 0x456c,
+ 0x821b, 0x1618,
+ 0x821c, 0x0da9,
+ 0x821d, 0x4572,
+ 0x821e, 0x0ef7,
+ 0x821f, 0x11da,
+ 0x8220, 0x4573,
+ 0x8221, 0x1cab,
+ 0x8224, 0x4574,
+ 0x8228, 0x1cb0,
+ 0x8229, 0x4578,
+ 0x822a, 0x0774,
+ 0x822b, 0x1cb1,
+ 0x822c, 0x03ee,
+ 0x822d, 0x1cae,
+ 0x822e, 0x4579,
+ 0x822f, 0x1caf,
+ 0x8230, 0x0873,
+ 0x8231, 0x049c,
+ 0x8232, 0x457a,
+ 0x8233, 0x1cb4,
+ 0x8235, 0x0625,
+ 0x8236, 0x0477,
+ 0x8237, 0x0f3c,
+ 0x8238, 0x1cb2,
+ 0x8239, 0x052f,
+ 0x823a, 0x457b,
+ 0x823b, 0x1cb3,
+ 0x823c, 0x457c,
+ 0x823e, 0x1cb6,
+ 0x823f, 0x457e,
+ 0x8244, 0x1cb7,
+ 0x8245, 0x4583,
+ 0x8247, 0x0e58,
+ 0x8248, 0x4585,
+ 0x8249, 0x1cb8,
+ 0x824a, 0x4586,
+ 0x824b, 0x1cb9,
+ 0x824c, 0x4587,
+ 0x824f, 0x1cba,
+ 0x8250, 0x458a,
+ 0x8258, 0x0dc7,
+ 0x8259, 0x1e61,
+ 0x825a, 0x1cbb,
+ 0x825b, 0x4592,
+ 0x825f, 0x1cbc,
+ 0x8260, 0x4596,
+ 0x8264, 0x25ef,
+ 0x8265, 0x459a,
+ 0x8266, 0x1f98,
+ 0x8267, 0x459b,
+ 0x8268, 0x1cbd,
+ 0x8269, 0x459c,
+ 0x826b, 0x25f0,
+ 0x826c, 0x459e,
+ 0x826e, 0x1cdc,
+ 0x826f, 0x0a05,
+ 0x8270, 0x085b,
+ 0x8271, 0x1f88,
+ 0x8272, 0x0ce4,
+ 0x8273, 0x1007,
+ 0x8274, 0x1771,
+ 0x8275, 0x45a0,
+ 0x8277, 0x21f8,
+ 0x8278, 0x45a2,
+ 0x8279, 0x13e1,
+ 0x827a, 0x105c,
+ 0x827b, 0x45a3,
+ 0x827d, 0x13e2,
+ 0x827e, 0x03b7,
+ 0x827f, 0x13e3,
+ 0x8280, 0x45a5,
+ 0x8282, 0x08ab,
+ 0x8283, 0x45a7,
+ 0x8284, 0x13e7,
+ 0x8285, 0x45a8,
+ 0x8288, 0x1278,
+ 0x8289, 0x45ab,
+ 0x828a, 0x13e5,
+ 0x828b, 0x10d8,
+ 0x828c, 0x45ac,
+ 0x828d, 0x0d0f,
+ 0x828e, 0x13e8,
+ 0x828f, 0x13e4,
+ 0x8290, 0x45ad,
+ 0x8291, 0x13e9,
+ 0x8292, 0x0aa7,
+ 0x8293, 0x45ae,
+ 0x8297, 0x13ea,
+ 0x8298, 0x13f3,
+ 0x8299, 0x13eb,
+ 0x829a, 0x45b2,
+ 0x829c, 0x0eee,
+ 0x829d, 0x11a4,
+ 0x829e, 0x45b4,
+ 0x829f, 0x13fd,
+ 0x82a0, 0x45b5,
+ 0x82a1, 0x13fb,
+ 0x82a2, 0x45b6,
+ 0x82a4, 0x1400,
+ 0x82a5, 0x08b7,
+ 0x82a6, 0x0a52,
+ 0x82a7, 0x45b8,
+ 0x82a8, 0x13e6,
+ 0x82a9, 0x13f9,
+ 0x82aa, 0x13fc,
+ 0x82ab, 0x13ec,
+ 0x82ac, 0x066f,
+ 0x82ad, 0x03d0,
+ 0x82ae, 0x13f5,
+ 0x82af, 0x0f89,
+ 0x82b0, 0x13ef,
+ 0x82b1, 0x07bd,
+ 0x82b2, 0x45b9,
+ 0x82b3, 0x0659,
+ 0x82b4, 0x13fa,
+ 0x82b5, 0x45ba,
+ 0x82b7, 0x13f4,
+ 0x82b8, 0x13ed,
+ 0x82b9, 0x0c58,
+ 0x82ba, 0x45bc,
+ 0x82bb, 0x2322,
+ 0x82bc, 0x45bd,
+ 0x82bd, 0x0fe8,
+ 0x82be, 0x13ee,
+ 0x82bf, 0x45be,
+ 0x82c1, 0x13f8,
+ 0x82c2, 0x45c0,
+ 0x82c4, 0x13fe,
+ 0x82c5, 0x45c2,
+ 0x82c7, 0x0ebc,
+ 0x82c8, 0x13f0,
+ 0x82c9, 0x45c4,
+ 0x82ca, 0x13f1,
+ 0x82cb, 0x13f6,
+ 0x82cd, 0x049b,
+ 0x82ce, 0x13ff,
+ 0x82cf, 0x0dca,
+ 0x82d0, 0x45c5,
+ 0x82d1, 0x10fa,
+ 0x82d2, 0x1409,
+ 0x82d3, 0x140d,
+ 0x82d4, 0x0df9,
+ 0x82d5, 0x1414,
+ 0x82d6, 0x45c6,
+ 0x82d7, 0x0aec,
+ 0x82d8, 0x140a,
+ 0x82d9, 0x45c7,
+ 0x82db, 0x094e,
+ 0x82dc, 0x1407,
+ 0x82dd, 0x45c9,
+ 0x82de, 0x0405,
+ 0x82df, 0x070f,
+ 0x82e0, 0x1413,
+ 0x82e1, 0x1401,
+ 0x82e2, 0x45ca,
+ 0x82e3, 0x13f2,
+ 0x82e4, 0x1404,
+ 0x82e5, 0x0ccf,
+ 0x82e6, 0x096d,
+ 0x82e7, 0x2336,
+ 0x82e8, 0x45cb,
+ 0x82eb, 0x0cf4,
+ 0x82ec, 0x45ce,
+ 0x82ef, 0x0426,
+ 0x82f0, 0x45d1,
+ 0x82f1, 0x1087,
+ 0x82f2, 0x45d2,
+ 0x82f4, 0x1408,
+ 0x82f5, 0x45d4,
+ 0x82f7, 0x1403,
+ 0x82f8, 0x45d6,
+ 0x82f9, 0x0bda,
+ 0x82fa, 0x45d7,
+ 0x82fb, 0x140c,
+ 0x82fc, 0x45d8,
+ 0x8300, 0x45dc,
+ 0x8301, 0x121f,
+ 0x8302, 0x0ab4,
+ 0x8303, 0x0653,
+ 0x8304, 0x0c4e,
+ 0x8305, 0x0aae,
+ 0x8306, 0x1410,
+ 0x8307, 0x1406,
+ 0x8308, 0x1419,
+ 0x8309, 0x1402,
+ 0x830a, 0x45dd,
+ 0x830c, 0x140b,
+ 0x830d, 0x45df,
+ 0x830e, 0x08d4,
+ 0x830f, 0x1405,
+ 0x8310, 0x45e0,
+ 0x8311, 0x140e,
+ 0x8312, 0x45e1,
+ 0x8314, 0x1411,
+ 0x8316, 0x45e3,
+ 0x8317, 0x1426,
+ 0x8318, 0x45e4,
+ 0x831a, 0x140f,
+ 0x831b, 0x142e,
+ 0x831c, 0x1415,
+ 0x831d, 0x45e6,
+ 0x8327, 0x085e,
+ 0x8328, 0x0547,
+ 0x8329, 0x45f0,
+ 0x832b, 0x0aa8,
+ 0x832c, 0x04ae,
+ 0x832d, 0x1428,
+ 0x832e, 0x45f2,
+ 0x832f, 0x1420,
+ 0x8330, 0x45f3,
+ 0x8331, 0x141d,
+ 0x8332, 0x45f4,
+ 0x8333, 0x142a,
+ 0x8334, 0x141c,
+ 0x8335, 0x1077,
+ 0x8336, 0x04af,
+ 0x8337, 0x45f5,
+ 0x8338, 0x0cb2,
+ 0x8339, 0x0cbe,
+ 0x833a, 0x1429,
+ 0x833b, 0x45f6,
+ 0x833c, 0x141b,
+ 0x833d, 0x45f7,
+ 0x8340, 0x1425,
+ 0x8341, 0x45fa,
+ 0x8343, 0x1423,
+ 0x8344, 0x45fc,
+ 0x8346, 0x08d2,
+ 0x8347, 0x1422,
+ 0x8348, 0x45fe,
+ 0x8349, 0x04a4,
+ 0x834a, 0x45ff,
+ 0x834f, 0x1421,
+ 0x8350, 0x0869,
+ 0x8351, 0x1416,
+ 0x8352, 0x07d9,
+ 0x8353, 0x4604,
+ 0x8354, 0x09de,
+ 0x8355, 0x4605,
+ 0x835a, 0x0847,
+ 0x835b, 0x1417,
+ 0x835d, 0x460a,
+ 0x835e, 0x141f,
+ 0x835f, 0x1424,
+ 0x8360, 0x1427,
+ 0x8361, 0x0595,
+ 0x8362, 0x460b,
+ 0x8363, 0x0cb4,
+ 0x8364, 0x07fc,
+ 0x8365, 0x142c,
+ 0x8366, 0x142b,
+ 0x8367, 0x1090,
+ 0x8368, 0x142d,
+ 0x8369, 0x142f,
+ 0x836a, 0x1431,
+ 0x836b, 0x1078,
+ 0x836c, 0x1430,
+ 0x836d, 0x1432,
+ 0x836f, 0x1030,
+ 0x8370, 0x460c,
+ 0x8377, 0x0780,
+ 0x8378, 0x1435,
+ 0x8379, 0x4613,
+ 0x837b, 0x1442,
+ 0x837c, 0x143d,
+ 0x837d, 0x1440,
+ 0x837e, 0x4615,
+ 0x8385, 0x143c,
+ 0x8386, 0x0bed,
+ 0x8387, 0x461c,
+ 0x8389, 0x09dd,
+ 0x838a, 0x22ab,
+ 0x838b, 0x461e,
+ 0x838e, 0x0ce8,
+ 0x838f, 0x4621,
+ 0x8392, 0x141a,
+ 0x8393, 0x143a,
+ 0x8394, 0x4624,
+ 0x8396, 0x1fbf,
+ 0x8397, 0x4626,
+ 0x8398, 0x1443,
+ 0x8399, 0x4627,
+ 0x839b, 0x141e,
+ 0x839c, 0x143b,
+ 0x839d, 0x4629,
+ 0x839e, 0x1444,
+ 0x839f, 0x462a,
+ 0x83a0, 0x1438,
+ 0x83a1, 0x462b,
+ 0x83a2, 0x1f7d,
+ 0x83a3, 0x462c,
+ 0x83a7, 0x2333,
+ 0x83a8, 0x1445,
+ 0x83a9, 0x143f,
+ 0x83aa, 0x1439,
+ 0x83ab, 0x0b0d,
+ 0x83ac, 0x4630,
+ 0x83b0, 0x1434,
+ 0x83b1, 0x099e,
+ 0x83b2, 0x09f4,
+ 0x83b3, 0x1436,
+ 0x83b5, 0x4634,
+ 0x83b6, 0x143e,
+ 0x83b7, 0x0806,
+ 0x83b8, 0x1441,
+ 0x83b9, 0x108d,
+ 0x83ba, 0x1446,
+ 0x83bb, 0x4635,
+ 0x83bc, 0x1447,
+ 0x83bd, 0x0aac,
+ 0x83be, 0x4636,
+ 0x83c0, 0x145e,
+ 0x83c1, 0x1448,
+ 0x83c2, 0x4638,
+ 0x83c5, 0x145d,
+ 0x83c6, 0x463b,
+ 0x83c7, 0x0716,
+ 0x83c8, 0x463c,
+ 0x83ca, 0x0904,
+ 0x83cb, 0x463e,
+ 0x83cc, 0x0929,
+ 0x83cd, 0x463f,
+ 0x83cf, 0x0781,
+ 0x83d0, 0x4641,
+ 0x83d4, 0x1456,
+ 0x83d5, 0x4645,
+ 0x83d6, 0x1451,
+ 0x83d7, 0x4646,
+ 0x83d8, 0x144b,
+ 0x83d9, 0x4647,
+ 0x83dc, 0x0492,
+ 0x83dd, 0x144f,
+ 0x83de, 0x464a,
+ 0x83df, 0x1457,
+ 0x83e0, 0x046b,
+ 0x83e1, 0x1461,
+ 0x83e2, 0x464b,
+ 0x83e5, 0x144a,
+ 0x83e6, 0x464e,
+ 0x83e9, 0x0bef,
+ 0x83ea, 0x145c,
+ 0x83eb, 0x4651,
+ 0x83ef, 0x1f4d,
+ 0x83f0, 0x1460,
+ 0x83f1, 0x0a2b,
+ 0x83f2, 0x0663,
+ 0x83f3, 0x4655,
+ 0x83f8, 0x145a,
+ 0x83fa, 0x465a,
+ 0x83fd, 0x1450,
+ 0x83fe, 0x465d,
+ 0x8400, 0x465f,
+ 0x8401, 0x1449,
+ 0x8402, 0x4660,
+ 0x8403, 0x1459,
+ 0x8404, 0x0e24,
+ 0x8405, 0x4661,
+ 0x8406, 0x1455,
+ 0x8407, 0x2334,
+ 0x8408, 0x4662,
+ 0x840a, 0x1ff1,
+ 0x840b, 0x144e,
+ 0x840c, 0x0acd,
+ 0x840d, 0x0bdb,
+ 0x840e, 0x0ebd,
+ 0x840f, 0x1458,
+ 0x8410, 0x4664,
+ 0x8411, 0x1454,
+ 0x8412, 0x4665,
+ 0x8418, 0x144d,
+ 0x8419, 0x466b,
+ 0x841c, 0x1452,
+ 0x841d, 0x0a83,
+ 0x841e, 0x466e,
+ 0x8424, 0x108e,
+ 0x8426, 0x145f,
+ 0x8427, 0x0f61,
+ 0x8428, 0x0cd3,
+ 0x8429, 0x4674,
+ 0x842c, 0x218b,
+ 0x842d, 0x4677,
+ 0x8431, 0x1472,
+ 0x8432, 0x467b,
+ 0x8435, 0x2349,
+ 0x8436, 0x467e,
+ 0x8438, 0x1453,
+ 0x8439, 0x4680,
+ 0x843c, 0x146c,
+ 0x843d, 0x0a8b,
+ 0x843e, 0x4683,
+ 0x8446, 0x146d,
+ 0x8447, 0x468b,
+ 0x8449, 0x220b,
+ 0x844a, 0x468d,
+ 0x8451, 0x1463,
+ 0x8452, 0x2346,
+ 0x8453, 0x4694,
+ 0x8457, 0x11f7,
+ 0x8458, 0x4698,
+ 0x8459, 0x1465,
+ 0x845a, 0x1464,
+ 0x845b, 0x06eb,
+ 0x845c, 0x1462,
+ 0x845d, 0x4699,
+ 0x8461, 0x0bee,
+ 0x8462, 0x469d,
+ 0x8463, 0x05ec,
+ 0x8464, 0x2347,
+ 0x8465, 0x469e,
+ 0x8466, 0x2193,
+ 0x8467, 0x469f,
+ 0x8469, 0x146e,
+ 0x846a, 0x46a1,
+ 0x846b, 0x07b0,
+ 0x846c, 0x1124,
+ 0x846d, 0x1473,
+ 0x846e, 0x46a2,
+ 0x846f, 0x26a1,
+ 0x8470, 0x46a3,
+ 0x8471, 0x0553,
+ 0x8472, 0x46a4,
+ 0x8473, 0x1466,
+ 0x8474, 0x46a5,
+ 0x8475, 0x0988,
+ 0x8476, 0x146f,
+ 0x8477, 0x1f62,
+ 0x8478, 0x146b,
+ 0x8479, 0x46a6,
+ 0x847a, 0x1469,
+ 0x847b, 0x46a7,
+ 0x8482, 0x05ba,
+ 0x8483, 0x46ae,
+ 0x8487, 0x1467,
+ 0x8489, 0x146a,
+ 0x848a, 0x46b2,
+ 0x848b, 0x0880,
+ 0x848c, 0x1470,
+ 0x848d, 0x46b3,
+ 0x848e, 0x1471,
+ 0x848f, 0x46b4,
+ 0x8493, 0x234d,
+ 0x8494, 0x2348,
+ 0x8495, 0x46b8,
+ 0x8497, 0x1481,
+ 0x8498, 0x46ba,
+ 0x8499, 0x0ace,
+ 0x849a, 0x46bb,
+ 0x849c, 0x0dd7,
+ 0x849d, 0x46bd,
+ 0x84a1, 0x147e,
+ 0x84a2, 0x46c1,
+ 0x84af, 0x1297,
+ 0x84b0, 0x46ce,
+ 0x84b2, 0x0bf0,
+ 0x84b3, 0x46d0,
+ 0x84b4, 0x1480,
+ 0x84b5, 0x46d1,
+ 0x84b8, 0x1195,
+ 0x84b9, 0x147f,
+ 0x84ba, 0x147c,
+ 0x84bb, 0x46d4,
+ 0x84bc, 0x1e60,
+ 0x84bd, 0x1478,
+ 0x84be, 0x46d5,
+ 0x84bf, 0x147b,
+ 0x84c0, 0x2345,
+ 0x84c1, 0x1474,
+ 0x84c2, 0x46d6,
+ 0x84c4, 0x0fb9,
+ 0x84c5, 0x46d8,
+ 0x84c9, 0x0cb3,
+ 0x84ca, 0x147a,
+ 0x84cb, 0x1f12,
+ 0x84cc, 0x46dc,
+ 0x84cd, 0x1475,
+ 0x84ce, 0x46dd,
+ 0x84d0, 0x1476,
+ 0x84d1, 0x0de7,
+ 0x84d2, 0x46df,
+ 0x84d3, 0x1479,
+ 0x84d4, 0x46e0,
+ 0x84d6, 0x0436,
+ 0x84d7, 0x46e2,
+ 0x84dd, 0x09a1,
+ 0x84de, 0x46e8,
+ 0x84df, 0x082e,
+ 0x84e0, 0x147d,
+ 0x84e1, 0x46e9,
+ 0x84e3, 0x1483,
+ 0x84e4, 0x46eb,
+ 0x84e5, 0x1482,
+ 0x84e6, 0x1477,
+ 0x84e7, 0x46ec,
+ 0x84ec, 0x0baf,
+ 0x84ed, 0x46f1,
+ 0x84ee, 0x2018,
+ 0x84ef, 0x2335,
+ 0x84f0, 0x1487,
+ 0x84f1, 0x46f2,
+ 0x84fc, 0x148e,
+ 0x84fd, 0x233c,
+ 0x84fe, 0x46fd,
+ 0x84ff, 0x148d,
+ 0x8500, 0x46fe,
+ 0x850c, 0x1484,
+ 0x850d, 0x470a,
+ 0x8511, 0x0af4,
+ 0x8512, 0x470e,
+ 0x8513, 0x0aa2,
+ 0x8514, 0x266f,
+ 0x8515, 0x470f,
+ 0x8517, 0x1182,
+ 0x8518, 0x4711,
+ 0x851a, 0x0ec4,
+ 0x851b, 0x4713,
+ 0x851e, 0x2351,
+ 0x851f, 0x1489,
+ 0x8520, 0x4716,
+ 0x8521, 0x0493,
+ 0x8522, 0x4717,
+ 0x8523, 0x1fa0,
+ 0x8524, 0x4718,
+ 0x8526, 0x2338,
+ 0x8527, 0x471a,
+ 0x852b, 0x0b4b,
+ 0x852c, 0x0d76,
+ 0x852d, 0x221b,
+ 0x852e, 0x471e,
+ 0x8537, 0x0c3b,
+ 0x8538, 0x1486,
+ 0x8539, 0x1488,
+ 0x853a, 0x148a,
+ 0x853b, 0x148c,
+ 0x853c, 0x03b5,
+ 0x853d, 0x0437,
+ 0x853e, 0x4727,
+ 0x8541, 0x2342,
+ 0x8542, 0x472a,
+ 0x8543, 0x1496,
+ 0x8544, 0x472b,
+ 0x8546, 0x234f,
+ 0x8547, 0x472d,
+ 0x8548, 0x1490,
+ 0x8549, 0x0887,
+ 0x854a, 0x0cca,
+ 0x854b, 0x472e,
+ 0x854e, 0x233d,
+ 0x854f, 0x4731,
+ 0x8552, 0x2344,
+ 0x8553, 0x2331,
+ 0x8554, 0x4734,
+ 0x8555, 0x234b,
+ 0x8556, 0x148b,
+ 0x8557, 0x4735,
+ 0x8558, 0x233b,
+ 0x8559, 0x148f,
+ 0x855a, 0x4736,
+ 0x855e, 0x1493,
+ 0x855f, 0x473a,
+ 0x8562, 0x2350,
+ 0x8563, 0x473d,
+ 0x8564, 0x1492,
+ 0x8565, 0x473e,
+ 0x8568, 0x1491,
+ 0x8569, 0x1eb4,
+ 0x856a, 0x21a6,
+ 0x856b, 0x4741,
+ 0x856d, 0x21cb,
+ 0x856e, 0x4743,
+ 0x8572, 0x1497,
+ 0x8573, 0x4747,
+ 0x8574, 0x110f,
+ 0x8575, 0x4748,
+ 0x8577, 0x2355,
+ 0x8578, 0x474a,
+ 0x8579, 0x149d,
+ 0x857a, 0x1494,
+ 0x857b, 0x1498,
+ 0x857c, 0x474b,
+ 0x857e, 0x09c4,
+ 0x857f, 0x474d,
+ 0x8584, 0x040a,
+ 0x8585, 0x14a0,
+ 0x8586, 0x4752,
+ 0x8587, 0x149b,
+ 0x8588, 0x233e,
+ 0x8589, 0x4753,
+ 0x858a, 0x1f74,
+ 0x858b, 0x4754,
+ 0x858c, 0x2330,
+ 0x858d, 0x4755,
+ 0x858f, 0x149c,
+ 0x8590, 0x4757,
+ 0x8591, 0x2680,
+ 0x8592, 0x4758,
+ 0x8594, 0x20da,
+ 0x8595, 0x475a,
+ 0x859b, 0x0fcf,
+ 0x859c, 0x149f,
+ 0x859d, 0x4760,
+ 0x859f, 0x234a,
+ 0x85a0, 0x4762,
+ 0x85a4, 0x1499,
+ 0x85a5, 0x4766,
+ 0x85a6, 0x1f91,
+ 0x85a7, 0x4767,
+ 0x85a8, 0x149a,
+ 0x85a9, 0x2107,
+ 0x85aa, 0x0f88,
+ 0x85ab, 0x4768,
+ 0x85ae, 0x149e,
+ 0x85af, 0x0d84,
+ 0x85b0, 0x14a3,
+ 0x85b1, 0x476b,
+ 0x85b7, 0x14a2,
+ 0x85b8, 0x4771,
+ 0x85b9, 0x14a1,
+ 0x85ba, 0x233f,
+ 0x85bb, 0x4772,
+ 0x85c1, 0x14a5,
+ 0x85c2, 0x4778,
+ 0x85c9, 0x08b6,
+ 0x85ca, 0x477f,
+ 0x85cd, 0x1ff4,
+ 0x85ce, 0x2343,
+ 0x85cf, 0x049f,
+ 0x85d0, 0x0aef,
+ 0x85d1, 0x4782,
+ 0x85d3, 0x14a4,
+ 0x85d4, 0x4784,
+ 0x85d5, 0x0b7b,
+ 0x85d6, 0x4785,
+ 0x85dc, 0x14a6,
+ 0x85dd, 0x2212,
+ 0x85de, 0x478b,
+ 0x85e4, 0x0e2c,
+ 0x85e5, 0x2207,
+ 0x85e6, 0x4791,
+ 0x85e9, 0x0647,
+ 0x85ea, 0x2359,
+ 0x85eb, 0x4794,
+ 0x85f4, 0x2254,
+ 0x85f5, 0x479d,
+ 0x85f6, 0x2332,
+ 0x85f7, 0x479e,
+ 0x85f9, 0x1e26,
+ 0x85fa, 0x2357,
+ 0x85fb, 0x1128,
+ 0x85fc, 0x47a0,
+ 0x85ff, 0x14a7,
+ 0x8600, 0x47a3,
+ 0x8604, 0x2358,
+ 0x8605, 0x14a9,
+ 0x8606, 0x2042,
+ 0x8607, 0x2153,
+ 0x8608, 0x47a7,
+ 0x860b, 0x20bb,
+ 0x860c, 0x47aa,
+ 0x8611, 0x0b05,
+ 0x8612, 0x47af,
+ 0x8616, 0x14ab,
+ 0x8617, 0x47b3,
+ 0x861a, 0x235a,
+ 0x861b, 0x47b6,
+ 0x861e, 0x2356,
+ 0x861f, 0x47b9,
+ 0x8622, 0x2337,
+ 0x8623, 0x47bc,
+ 0x8627, 0x14a8,
+ 0x8628, 0x47c0,
+ 0x8629, 0x14aa,
+ 0x862a, 0x47c1,
+ 0x862d, 0x1ff9,
+ 0x862e, 0x47c4,
+ 0x8638, 0x115b,
+ 0x8639, 0x47ce,
+ 0x863a, 0x2353,
+ 0x863b, 0x47cf,
+ 0x863c, 0x14ac,
+ 0x863d, 0x47d0,
+ 0x863f, 0x2061,
+ 0x8640, 0x47d2,
+ 0x864d, 0x1bf0,
+ 0x864e, 0x07b7,
+ 0x864f, 0x0a59,
+ 0x8650, 0x0b71,
+ 0x8651, 0x0a6e,
+ 0x8652, 0x47df,
+ 0x8654, 0x1bf1,
+ 0x8655, 0x1e95,
+ 0x8656, 0x47e1,
+ 0x865a, 0x0fb4,
+ 0x865b, 0x47e5,
+ 0x865c, 0x2049,
+ 0x865d, 0x47e6,
+ 0x865e, 0x10c2,
+ 0x865f, 0x1f42,
+ 0x8660, 0x47e7,
+ 0x8662, 0x196d,
+ 0x8663, 0x47e9,
+ 0x8667, 0x1fe8,
+ 0x8668, 0x47ed,
+ 0x866b, 0x050b,
+ 0x866c, 0x1bf2,
+ 0x866d, 0x47f0,
+ 0x866e, 0x1bf3,
+ 0x866f, 0x47f1,
+ 0x8671, 0x0d44,
+ 0x8672, 0x47f3,
+ 0x8679, 0x079e,
+ 0x867a, 0x1bf5,
+ 0x867b, 0x1bf7,
+ 0x867c, 0x1bf6,
+ 0x867d, 0x0dd9,
+ 0x867e, 0x0f27,
+ 0x867f, 0x1bf4,
+ 0x8680, 0x0d4b,
+ 0x8681, 0x1056,
+ 0x8682, 0x0a93,
+ 0x8683, 0x47fa,
+ 0x868a, 0x0ed2,
+ 0x868b, 0x1bfa,
+ 0x868c, 0x0401,
+ 0x868d, 0x1bf9,
+ 0x868e, 0x4801,
+ 0x8693, 0x1c00,
+ 0x8694, 0x4806,
+ 0x8695, 0x0496,
+ 0x8696, 0x4807,
+ 0x869c, 0x0fea,
+ 0x869d, 0x1bfc,
+ 0x869e, 0x480d,
+ 0x86a3, 0x1bfe,
+ 0x86a4, 0x112c,
+ 0x86a5, 0x4812,
+ 0x86a7, 0x1bfd,
+ 0x86a8, 0x1bf8,
+ 0x86a9, 0x1c01,
+ 0x86aa, 0x1bff,
+ 0x86ab, 0x4814,
+ 0x86ac, 0x1bfb,
+ 0x86ad, 0x4815,
+ 0x86af, 0x1c09,
+ 0x86b0, 0x1c06,
+ 0x86b1, 0x1c08,
+ 0x86b2, 0x4817,
+ 0x86b4, 0x1c0c,
+ 0x86b5, 0x1c04,
+ 0x86b6, 0x1c02,
+ 0x86b7, 0x4819,
+ 0x86ba, 0x1c07,
+ 0x86bb, 0x481c,
+ 0x86c0, 0x11fa,
+ 0x86c1, 0x4821,
+ 0x86c4, 0x1c03,
+ 0x86c5, 0x4824,
+ 0x86c6, 0x0c76,
+ 0x86c7, 0x0d18,
+ 0x86c8, 0x4825,
+ 0x86c9, 0x1c0a,
+ 0x86ca, 0x071f,
+ 0x86cb, 0x0591,
+ 0x86cc, 0x4826,
+ 0x86ce, 0x1c05,
+ 0x86cf, 0x1c0b,
+ 0x86d0, 0x1c12,
+ 0x86d1, 0x1c18,
+ 0x86d2, 0x4828,
+ 0x86d4, 0x07ec,
+ 0x86d5, 0x482a,
+ 0x86d8, 0x1c17,
+ 0x86d9, 0x0e8d,
+ 0x86da, 0x482d,
+ 0x86db, 0x11ea,
+ 0x86dc, 0x482e,
+ 0x86de, 0x1c14,
+ 0x86df, 0x1c16,
+ 0x86e0, 0x4830,
+ 0x86e4, 0x06ed,
+ 0x86e5, 0x4834,
+ 0x86e9, 0x1c0d,
+ 0x86ea, 0x4838,
+ 0x86ed, 0x1c10,
+ 0x86ee, 0x0aa0,
+ 0x86ef, 0x483b,
+ 0x86f0, 0x117e,
+ 0x86f1, 0x1c0e,
+ 0x86f3, 0x1c11,
+ 0x86f4, 0x1c15,
+ 0x86f5, 0x483c,
+ 0x86f8, 0x1c1b,
+ 0x86f9, 0x10a1,
+ 0x86fa, 0x25da,
+ 0x86fb, 0x483f,
+ 0x86fe, 0x0629,
+ 0x86ff, 0x4842,
+ 0x8700, 0x0d88,
+ 0x8701, 0x4843,
+ 0x8702, 0x0681,
+ 0x8703, 0x1c19,
+ 0x8704, 0x4844,
+ 0x8706, 0x25d7,
+ 0x8707, 0x1c1a,
+ 0x8708, 0x1c1c,
+ 0x8709, 0x1c1f,
+ 0x870a, 0x1c1d,
+ 0x870b, 0x4846,
+ 0x870d, 0x1c1e,
+ 0x870e, 0x4848,
+ 0x8712, 0x0ffa,
+ 0x8713, 0x1c13,
+ 0x8714, 0x484c,
+ 0x8715, 0x0e7a,
+ 0x8716, 0x484d,
+ 0x8717, 0x0ede,
+ 0x8718, 0x11a8,
+ 0x8719, 0x484e,
+ 0x871a, 0x1c25,
+ 0x871b, 0x484f,
+ 0x871c, 0x0ae0,
+ 0x871d, 0x4850,
+ 0x871e, 0x1c22,
+ 0x871f, 0x4851,
+ 0x8721, 0x099a,
+ 0x8722, 0x1c2e,
+ 0x8723, 0x1c20,
+ 0x8724, 0x4853,
+ 0x8725, 0x1c23,
+ 0x8726, 0x4854,
+ 0x8729, 0x1c2a,
+ 0x872a, 0x4857,
+ 0x872e, 0x1c24,
+ 0x872f, 0x485b,
+ 0x8731, 0x1c29,
+ 0x8732, 0x485d,
+ 0x8734, 0x1c28,
+ 0x8735, 0x485f,
+ 0x8737, 0x1c2b,
+ 0x8738, 0x4861,
+ 0x873b, 0x1c21,
+ 0x873c, 0x4864,
+ 0x873e, 0x1c26,
+ 0x873f, 0x1c2c,
+ 0x8740, 0x4866,
+ 0x8747, 0x1091,
+ 0x8748, 0x1c27,
+ 0x8749, 0x04bc,
+ 0x874a, 0x486d,
+ 0x874c, 0x1c34,
+ 0x874d, 0x486f,
+ 0x874e, 0x0f76,
+ 0x874f, 0x4870,
+ 0x8753, 0x1c37,
+ 0x8754, 0x4874,
+ 0x8755, 0x212e,
+ 0x8756, 0x4875,
+ 0x8757, 0x07dd,
+ 0x8758, 0x4876,
+ 0x8759, 0x1c3b,
+ 0x875a, 0x4877,
+ 0x8760, 0x1c32,
+ 0x8761, 0x487d,
+ 0x8763, 0x1c38,
+ 0x8764, 0x1c3a,
+ 0x8765, 0x1c3c,
+ 0x8766, 0x21b2,
+ 0x8767, 0x487f,
+ 0x876e, 0x1c35,
+ 0x876f, 0x4886,
+ 0x8770, 0x1c33,
+ 0x8771, 0x4887,
+ 0x8774, 0x07b2,
+ 0x8775, 0x488a,
+ 0x8776, 0x05dc,
+ 0x8777, 0x488b,
+ 0x8778, 0x219e,
+ 0x8779, 0x488c,
+ 0x877b, 0x1c31,
+ 0x877c, 0x1c39,
+ 0x877d, 0x1c2f,
+ 0x877f, 0x488e,
+ 0x8782, 0x1c2d,
+ 0x8783, 0x1c46,
+ 0x8784, 0x25dc,
+ 0x8785, 0x1c43,
+ 0x8786, 0x4891,
+ 0x8788, 0x1c42,
+ 0x8789, 0x4893,
+ 0x878b, 0x1c36,
+ 0x878c, 0x4895,
+ 0x878d, 0x0cb5,
+ 0x878e, 0x4896,
+ 0x8793, 0x1c3d,
+ 0x8794, 0x489b,
+ 0x8797, 0x1c45,
+ 0x8798, 0x489e,
+ 0x879e, 0x206c,
+ 0x879f, 0x0afd,
+ 0x87a0, 0x48a4,
+ 0x87a2, 0x2226,
+ 0x87a3, 0x48a6,
+ 0x87a8, 0x1c3f,
+ 0x87a9, 0x48ab,
+ 0x87ab, 0x1c47,
+ 0x87ac, 0x1c49,
+ 0x87ad, 0x1c44,
+ 0x87ae, 0x48ad,
+ 0x87af, 0x1c3e,
+ 0x87b0, 0x48ae,
+ 0x87b3, 0x1c4b,
+ 0x87b4, 0x48b1,
+ 0x87b5, 0x1c4a,
+ 0x87b6, 0x48b2,
+ 0x87ba, 0x0a84,
+ 0x87bb, 0x25e0,
+ 0x87bc, 0x48b6,
+ 0x87bd, 0x1c4e,
+ 0x87be, 0x48b7,
+ 0x87c0, 0x1c50,
+ 0x87c1, 0x48b9,
+ 0x87c4, 0x227b,
+ 0x87c5, 0x48bc,
+ 0x87c6, 0x1c41,
+ 0x87c7, 0x48bd,
+ 0x87c8, 0x25de,
+ 0x87c9, 0x48be,
+ 0x87ca, 0x1c51,
+ 0x87cb, 0x1c4c,
+ 0x87cc, 0x48bf,
+ 0x87ce, 0x25e1,
+ 0x87cf, 0x48c1,
+ 0x87d1, 0x1c4f,
+ 0x87d2, 0x1c40,
+ 0x87d3, 0x1c4d,
+ 0x87d4, 0x48c3,
+ 0x87db, 0x1c52,
+ 0x87dc, 0x48ca,
+ 0x87e0, 0x1c54,
+ 0x87e1, 0x48ce,
+ 0x87e3, 0x25d5,
+ 0x87e4, 0x48d0,
+ 0x87e5, 0x1c48,
+ 0x87e6, 0x48d1,
+ 0x87ea, 0x1c53,
+ 0x87eb, 0x48d5,
+ 0x87ec, 0x1e6b,
+ 0x87ed, 0x48d6,
+ 0x87ee, 0x1c55,
+ 0x87ef, 0x25db,
+ 0x87f0, 0x48d7,
+ 0x87f2, 0x1e89,
+ 0x87f3, 0x48d9,
+ 0x87f6, 0x25d9,
+ 0x87f7, 0x48dc,
+ 0x87f9, 0x0f82,
+ 0x87fa, 0x48de,
+ 0x87fb, 0x2211,
+ 0x87fc, 0x48df,
+ 0x87fe, 0x1c58,
+ 0x87ff, 0x48e1,
+ 0x8800, 0x48e2,
+ 0x8803, 0x130d,
+ 0x8804, 0x48e5,
+ 0x8805, 0x2229,
+ 0x8806, 0x25d6,
+ 0x8807, 0x48e6,
+ 0x880a, 0x1c59,
+ 0x880b, 0x48e9,
+ 0x8810, 0x25dd,
+ 0x8811, 0x25df,
+ 0x8812, 0x48ee,
+ 0x8813, 0x1c57,
+ 0x8814, 0x48ef,
+ 0x8815, 0x0cbf,
+ 0x8816, 0x1c56,
+ 0x8817, 0x48f0,
+ 0x881b, 0x1c5a,
+ 0x881c, 0x48f4,
+ 0x881f, 0x1fef,
+ 0x8820, 0x48f7,
+ 0x8821, 0x1c5b,
+ 0x8822, 0x0543,
+ 0x8823, 0x25d8,
+ 0x8824, 0x48f8,
+ 0x8831, 0x1f29,
+ 0x8832, 0x1a8d,
+ 0x8833, 0x4905,
+ 0x8836, 0x1e5b,
+ 0x8837, 0x4908,
+ 0x8839, 0x1c5c,
+ 0x883a, 0x490a,
+ 0x883b, 0x2076,
+ 0x883c, 0x1c5d,
+ 0x883d, 0x490b,
+ 0x8840, 0x0fd3,
+ 0x8841, 0x490e,
+ 0x8844, 0x1caa,
+ 0x8845, 0x0f91,
+ 0x8846, 0x2297,
+ 0x8847, 0x4911,
+ 0x884a, 0x2690,
+ 0x884b, 0x4914,
+ 0x884c, 0x0f9b,
+ 0x884d, 0x1005,
+ 0x884e, 0x4915,
+ 0x8853, 0x213f,
+ 0x8854, 0x0f3b,
+ 0x8855, 0x491a,
+ 0x8857, 0x08a7,
+ 0x8858, 0x491c,
+ 0x8859, 0x0fec,
+ 0x885a, 0x491d,
+ 0x885b, 0x2198,
+ 0x885c, 0x491e,
+ 0x885d, 0x1e88,
+ 0x885e, 0x491f,
+ 0x8861, 0x0799,
+ 0x8862, 0x15ed,
+ 0x8863, 0x1049,
+ 0x8864, 0x1ba6,
+ 0x8865, 0x0480,
+ 0x8866, 0x4922,
+ 0x8868, 0x0456,
+ 0x8869, 0x1ba7,
+ 0x886a, 0x4924,
+ 0x886b, 0x0cf9,
+ 0x886c, 0x04e9,
+ 0x886d, 0x4925,
+ 0x886e, 0x1306,
+ 0x886f, 0x4926,
+ 0x8870, 0x0d9a,
+ 0x8871, 0x4927,
+ 0x8872, 0x1ba8,
+ 0x8873, 0x4928,
+ 0x8877, 0x11d3,
+ 0x8878, 0x492c,
+ 0x8879, 0x228c,
+ 0x887a, 0x492d,
+ 0x887d, 0x1ba9,
+ 0x887e, 0x1cbe,
+ 0x887f, 0x1baa,
+ 0x8880, 0x4930,
+ 0x8881, 0x10ef,
+ 0x8882, 0x1bab,
+ 0x8883, 0x4931,
+ 0x8884, 0x03cb,
+ 0x8885, 0x1cbf,
+ 0x8886, 0x4932,
+ 0x8888, 0x1cc0,
+ 0x8889, 0x4934,
+ 0x888b, 0x057f,
+ 0x888c, 0x4936,
+ 0x888d, 0x0b9c,
+ 0x888e, 0x4937,
+ 0x8892, 0x0e0e,
+ 0x8893, 0x493b,
+ 0x8896, 0x0faf,
+ 0x8897, 0x493e,
+ 0x889c, 0x0e91,
+ 0x889d, 0x4943,
+ 0x88a2, 0x1bac,
+ 0x88a3, 0x4948,
+ 0x88a4, 0x1307,
+ 0x88a5, 0x4949,
+ 0x88ab, 0x0424,
+ 0x88ac, 0x494f,
+ 0x88ad, 0x0f1b,
+ 0x88ae, 0x4950,
+ 0x88b1, 0x069f,
+ 0x88b2, 0x4953,
+ 0x88b7, 0x1bae,
+ 0x88b8, 0x4958,
+ 0x88bc, 0x1baf,
+ 0x88bd, 0x495c,
+ 0x88c1, 0x048a,
+ 0x88c2, 0x0a1a,
+ 0x88c3, 0x4960,
+ 0x88c5, 0x120d,
+ 0x88c6, 0x1bad,
+ 0x88c7, 0x4962,
+ 0x88c9, 0x1bb0,
+ 0x88ca, 0x25f1,
+ 0x88cb, 0x4964,
+ 0x88ce, 0x1bb2,
+ 0x88cf, 0x200c,
+ 0x88d0, 0x4967,
+ 0x88d2, 0x130a,
+ 0x88d3, 0x4969,
+ 0x88d4, 0x1068,
+ 0x88d5, 0x10e6,
+ 0x88d6, 0x496a,
+ 0x88d8, 0x1cc1,
+ 0x88d9, 0x0c94,
+ 0x88da, 0x496c,
+ 0x88dc, 0x1e58,
+ 0x88dd, 0x22ac,
+ 0x88de, 0x496e,
+ 0x88df, 0x1cc2,
+ 0x88e0, 0x496f,
+ 0x88e2, 0x1bb1,
+ 0x88e3, 0x1bb3,
+ 0x88e4, 0x0970,
+ 0x88e5, 0x1bb4,
+ 0x88e6, 0x4971,
+ 0x88e8, 0x1bb8,
+ 0x88e9, 0x4973,
+ 0x88f0, 0x1bba,
+ 0x88f1, 0x1bb5,
+ 0x88f2, 0x497a,
+ 0x88f3, 0x0d0a,
+ 0x88f4, 0x0ba2,
+ 0x88f5, 0x497b,
+ 0x88f8, 0x0a8a,
+ 0x88f9, 0x0755,
+ 0x88fa, 0x497e,
+ 0x88fc, 0x1bb7,
+ 0x88fd, 0x26a7,
+ 0x88fe, 0x1bb9,
+ 0x88ff, 0x4980,
+ 0x8900, 0x4981,
+ 0x8902, 0x072c,
+ 0x8903, 0x4983,
+ 0x8907, 0x2676,
+ 0x8908, 0x4987,
+ 0x890a, 0x1bbf,
+ 0x890b, 0x4989,
+ 0x8910, 0x078d,
+ 0x8911, 0x498e,
+ 0x8912, 0x0408,
+ 0x8913, 0x1bbd,
+ 0x8914, 0x498f,
+ 0x8919, 0x1bbc,
+ 0x891a, 0x1bb6,
+ 0x891b, 0x1bbe,
+ 0x891c, 0x4994,
+ 0x8921, 0x1bbb,
+ 0x8922, 0x4999,
+ 0x8925, 0x0cc7,
+ 0x8926, 0x499c,
+ 0x892a, 0x0e7b,
+ 0x892b, 0x1bc1,
+ 0x892c, 0x49a0,
+ 0x8930, 0x1739,
+ 0x8931, 0x49a4,
+ 0x8932, 0x1fe1,
+ 0x8933, 0x25bb,
+ 0x8934, 0x1bc0,
+ 0x8935, 0x49a5,
+ 0x8936, 0x1bc2,
+ 0x8937, 0x49a6,
+ 0x8938, 0x25be,
+ 0x8939, 0x49a7,
+ 0x893b, 0x22dd,
+ 0x893c, 0x49a9,
+ 0x8941, 0x1bc3,
+ 0x8942, 0x49ae,
+ 0x8944, 0x0f52,
+ 0x8945, 0x49b0,
+ 0x8947, 0x25bd,
+ 0x8948, 0x49b2,
+ 0x8956, 0x1e2a,
+ 0x8957, 0x49c0,
+ 0x895d, 0x25bc,
+ 0x895e, 0x1cc3,
+ 0x895f, 0x08c4,
+ 0x8960, 0x25ba,
+ 0x8961, 0x49c6,
+ 0x8964, 0x25bf,
+ 0x8965, 0x49c9,
+ 0x8966, 0x1bc4,
+ 0x8967, 0x49ca,
+ 0x896a, 0x2187,
+ 0x896b, 0x49cd,
+ 0x896c, 0x266b,
+ 0x896d, 0x49ce,
+ 0x896f, 0x1e7f,
+ 0x8970, 0x49d0,
+ 0x8972, 0x21ad,
+ 0x8973, 0x49d2,
+ 0x897b, 0x1bc5,
+ 0x897c, 0x49da,
+ 0x897f, 0x0f06,
+ 0x8980, 0x49dd,
+ 0x8981, 0x1031,
+ 0x8982, 0x49de,
+ 0x8983, 0x1bdf,
+ 0x8984, 0x49df,
+ 0x8986, 0x06ad,
+ 0x8987, 0x49e1,
+ 0x898b, 0x1f96,
+ 0x898c, 0x49e5,
+ 0x898f, 0x1f32,
+ 0x8990, 0x49e8,
+ 0x8993, 0x2084,
+ 0x8994, 0x49eb,
+ 0x8996, 0x2136,
+ 0x8997, 0x49ed,
+ 0x8998, 0x24b8,
+ 0x8999, 0x49ee,
+ 0x89a1, 0x24ba,
+ 0x89a2, 0x49f6,
+ 0x89a6, 0x24bc,
+ 0x89a7, 0x49fa,
+ 0x89aa, 0x20e4,
+ 0x89ab, 0x49fd,
+ 0x89ac, 0x24b9,
+ 0x89ad, 0x49fe,
+ 0x89af, 0x24bd,
+ 0x89b0, 0x4a00,
+ 0x89b2, 0x24be,
+ 0x89b3, 0x4a02,
+ 0x89b7, 0x24bf,
+ 0x89b8, 0x4a06,
+ 0x89ba, 0x1fd2,
+ 0x89bb, 0x4a08,
+ 0x89bd, 0x1ffd,
+ 0x89be, 0x4a0a,
+ 0x89bf, 0x24bb,
+ 0x89c0, 0x1f2d,
+ 0x89c1, 0x086e,
+ 0x89c2, 0x0734,
+ 0x89c3, 0x4a0b,
+ 0x89c4, 0x073f,
+ 0x89c5, 0x0ade,
+ 0x89c6, 0x0d6a,
+ 0x89c7, 0x193a,
+ 0x89c8, 0x09ab,
+ 0x89c9, 0x0924,
+ 0x89ca, 0x193b,
+ 0x89cd, 0x4a0c,
+ 0x89ce, 0x193e,
+ 0x89d2, 0x0898,
+ 0x89d3, 0x4a0d,
+ 0x89d6, 0x1d57,
+ 0x89d7, 0x4a10,
+ 0x89da, 0x1d59,
+ 0x89db, 0x4a13,
+ 0x89dc, 0x1d5a,
+ 0x89dd, 0x4a14,
+ 0x89de, 0x1d58,
+ 0x89df, 0x4a15,
+ 0x89e3, 0x08b3,
+ 0x89e4, 0x4a19,
+ 0x89e5, 0x1d5b,
+ 0x89e6, 0x0528,
+ 0x89e7, 0x4a1a,
+ 0x89eb, 0x1d5c,
+ 0x89ec, 0x4a1e,
+ 0x89ef, 0x1d5d,
+ 0x89f0, 0x4a21,
+ 0x89f3, 0x19c0,
+ 0x89f4, 0x2609,
+ 0x89f5, 0x4a24,
+ 0x89f6, 0x260a,
+ 0x89f7, 0x4a25,
+ 0x89f8, 0x1e94,
+ 0x89f9, 0x4a26,
+ 0x8a00, 0x0ffd,
+ 0x8a01, 0x22df,
+ 0x8a02, 0x1ecb,
+ 0x8a03, 0x1f0d,
+ 0x8a04, 0x4a2d,
+ 0x8a07, 0x12fe,
+ 0x8a08, 0x1f77,
+ 0x8a09, 0x4a30,
+ 0x8a0a, 0x21eb,
+ 0x8a0b, 0x4a31,
+ 0x8a0c, 0x22e1,
+ 0x8a0d, 0x4a32,
+ 0x8a0e, 0x216f,
+ 0x8a0f, 0x4a33,
+ 0x8a10, 0x22e0,
+ 0x8a11, 0x4a34,
+ 0x8a13, 0x21ea,
+ 0x8a14, 0x4a36,
+ 0x8a15, 0x22e2,
+ 0x8a16, 0x20cb,
+ 0x8a17, 0x4a37,
+ 0x8a18, 0x1f78,
+ 0x8a19, 0x4a38,
+ 0x8a1b, 0x1ee2,
+ 0x8a1c, 0x4a3a,
+ 0x8a1d, 0x21f2,
+ 0x8a1e, 0x4a3b,
+ 0x8a1f, 0x2150,
+ 0x8a20, 0x4a3c,
+ 0x8a23, 0x1fd3,
+ 0x8a24, 0x4a3f,
+ 0x8a25, 0x22e5,
+ 0x8a26, 0x4a40,
+ 0x8a2a, 0x1ef2,
+ 0x8a2b, 0x4a44,
+ 0x8a2d, 0x211f,
+ 0x8a2e, 0x4a46,
+ 0x8a31, 0x21dd,
+ 0x8a32, 0x4a49,
+ 0x8a34, 0x2154,
+ 0x8a35, 0x4a4b,
+ 0x8a36, 0x22e7,
+ 0x8a37, 0x4a4c,
+ 0x8a3a, 0x2282,
+ 0x8a3b, 0x4a4f,
+ 0x8a3e, 0x1d5e,
+ 0x8a3f, 0x4a52,
+ 0x8a41, 0x22e6,
+ 0x8a42, 0x4a54,
+ 0x8a46, 0x22e8,
+ 0x8a47, 0x4a58,
+ 0x8a48, 0x1a84,
+ 0x8a49, 0x4a59,
+ 0x8a4e, 0x22e4,
+ 0x8a4f, 0x4a5e,
+ 0x8a50, 0x226a,
+ 0x8a51, 0x4a5f,
+ 0x8a52, 0x22eb,
+ 0x8a53, 0x4a60,
+ 0x8a54, 0x22e9,
+ 0x8a55, 0x20bd,
+ 0x8a56, 0x4a61,
+ 0x8a58, 0x22ea,
+ 0x8a59, 0x4a63,
+ 0x8a5b, 0x22bd,
+ 0x8a5c, 0x4a65,
+ 0x8a5e, 0x1e9e,
+ 0x8a5f, 0x4a67,
+ 0x8a61, 0x22f6,
+ 0x8a62, 0x21e7,
+ 0x8a63, 0x2216,
+ 0x8a64, 0x4a69,
+ 0x8a66, 0x2137,
+ 0x8a67, 0x4a6b,
+ 0x8a69, 0x212c,
+ 0x8a6a, 0x4a6d,
+ 0x8a6b, 0x1e68,
+ 0x8a6c, 0x22f2,
+ 0x8a6d, 0x1f37,
+ 0x8a6e, 0x22f3,
+ 0x8a6f, 0x4a6e,
+ 0x8a70, 0x22ef,
+ 0x8a71, 0x1f50,
+ 0x8a72, 0x1f10,
+ 0x8a73, 0x21c8,
+ 0x8a74, 0x4a6f,
+ 0x8a75, 0x22f1,
+ 0x8a76, 0x4a70,
+ 0x8a79, 0x1153,
+ 0x8a7a, 0x4a73,
+ 0x8a7c, 0x22f0,
+ 0x8a7d, 0x4a75,
+ 0x8a7f, 0x22ee,
+ 0x8a80, 0x4a77,
+ 0x8a84, 0x22ed,
+ 0x8a85, 0x229e,
+ 0x8a86, 0x22ec,
+ 0x8a87, 0x1fe2,
+ 0x8a88, 0x4a7b,
+ 0x8a89, 0x10e3,
+ 0x8a8a, 0x0e2f,
+ 0x8a8b, 0x4a7c,
+ 0x8a8d, 0x20fe,
+ 0x8a8e, 0x4a7e,
+ 0x8a91, 0x22f9,
+ 0x8a93, 0x0d5b,
+ 0x8a94, 0x4a81,
+ 0x8a95, 0x1eaf,
+ 0x8a96, 0x4a82,
+ 0x8a98, 0x2236,
+ 0x8a99, 0x4a84,
+ 0x8a9a, 0x22f7,
+ 0x8a9b, 0x4a85,
+ 0x8a9e, 0x223d,
+ 0x8a9f, 0x4a88,
+ 0x8aa0, 0x1e82,
+ 0x8aa1, 0x1fb6,
+ 0x8aa2, 0x4a89,
+ 0x8aa3, 0x21a4,
+ 0x8aa4, 0x21aa,
+ 0x8aa5, 0x22f8,
+ 0x8aa6, 0x2151,
+ 0x8aa7, 0x4a8a,
+ 0x8aa8, 0x1f60,
+ 0x8aa9, 0x4a8b,
+ 0x8aac, 0x2147,
+ 0x8aad, 0x4a8e,
+ 0x8ab0, 0x2145,
+ 0x8ab1, 0x4a91,
+ 0x8ab2, 0x1fdc,
+ 0x8ab3, 0x4a92,
+ 0x8ab6, 0x2301,
+ 0x8ab7, 0x4a95,
+ 0x8ab9, 0x1ef5,
+ 0x8aba, 0x4a97,
+ 0x8abc, 0x2218,
+ 0x8abd, 0x4a99,
+ 0x8abf, 0x1ec6,
+ 0x8ac0, 0x4a9b,
+ 0x8ac2, 0x2300,
+ 0x8ac3, 0x4a9d,
+ 0x8ac4, 0x22b4,
+ 0x8ac5, 0x4a9e,
+ 0x8ac7, 0x2169,
+ 0x8ac8, 0x4aa0,
+ 0x8ac9, 0x22fd,
+ 0x8aca, 0x4aa1,
+ 0x8acb, 0x20ea,
+ 0x8acc, 0x4aa2,
+ 0x8acd, 0x22f4,
+ 0x8ace, 0x4aa3,
+ 0x8acf, 0x22fb,
+ 0x8ad0, 0x4aa4,
+ 0x8ad1, 0x22fc,
+ 0x8ad2, 0x2027,
+ 0x8ad3, 0x4aa5,
+ 0x8ad6, 0x2060,
+ 0x8ad7, 0x22ff,
+ 0x8ad8, 0x4aa8,
+ 0x8adb, 0x22fe,
+ 0x8adc, 0x1ec7,
+ 0x8add, 0x4aab,
+ 0x8ade, 0x230c,
+ 0x8adf, 0x4aac,
+ 0x8ae2, 0x22f5,
+ 0x8ae3, 0x4aaf,
+ 0x8ae4, 0x2306,
+ 0x8ae5, 0x4ab0,
+ 0x8ae6, 0x230a,
+ 0x8ae7, 0x21d3,
+ 0x8ae8, 0x4ab1,
+ 0x8aeb, 0x2303,
+ 0x8aec, 0x4ab4,
+ 0x8aed, 0x2307,
+ 0x8aee, 0x230b,
+ 0x8aef, 0x4ab5,
+ 0x8af1, 0x1f5f,
+ 0x8af2, 0x4ab7,
+ 0x8af3, 0x2309,
+ 0x8af4, 0x4ab8,
+ 0x8af6, 0x2302,
+ 0x8af7, 0x1f04,
+ 0x8af8, 0x229d,
+ 0x8af9, 0x4aba,
+ 0x8afa, 0x21fb,
+ 0x8afb, 0x4abb,
+ 0x8afc, 0x2308,
+ 0x8afd, 0x4abc,
+ 0x8afe, 0x20ac,
+ 0x8aff, 0x4abd,
+ 0x8b00, 0x208e,
+ 0x8b01, 0x2305,
+ 0x8b02, 0x2197,
+ 0x8b03, 0x4abe,
+ 0x8b04, 0x2171,
+ 0x8b05, 0x2298,
+ 0x8b06, 0x4abf,
+ 0x8b07, 0x173c,
+ 0x8b08, 0x4ac0,
+ 0x8b0a, 0x1f57,
+ 0x8b0b, 0x4ac2,
+ 0x8b0e, 0x2082,
+ 0x8b0f, 0x4ac5,
+ 0x8b10, 0x2311,
+ 0x8b11, 0x4ac6,
+ 0x8b14, 0x2304,
+ 0x8b15, 0x4ac9,
+ 0x8b16, 0x230f,
+ 0x8b17, 0x1e35,
+ 0x8b18, 0x4aca,
+ 0x8b19, 0x20d1,
+ 0x8b1a, 0x2310,
+ 0x8b1b, 0x1fa3,
+ 0x8b1c, 0x4acb,
+ 0x8b1d, 0x21d6,
+ 0x8b1e, 0x4acc,
+ 0x8b21, 0x2206,
+ 0x8b22, 0x4acf,
+ 0x8b26, 0x1d5f,
+ 0x8b27, 0x4ad3,
+ 0x8b28, 0x230d,
+ 0x8b29, 0x4ad4,
+ 0x8b2b, 0x2312,
+ 0x8b2c, 0x208d,
+ 0x8b2d, 0x2313,
+ 0x8b2e, 0x4ad6,
+ 0x8b33, 0x22e3,
+ 0x8b34, 0x4adb,
+ 0x8b39, 0x1fba,
+ 0x8b3a, 0x4ae0,
+ 0x8b3e, 0x2078,
+ 0x8b3f, 0x4ae4,
+ 0x8b49, 0x2288,
+ 0x8b4a, 0x4aee,
+ 0x8b4e, 0x2316,
+ 0x8b4f, 0x1f6b,
+ 0x8b50, 0x4af2,
+ 0x8b56, 0x2314,
+ 0x8b57, 0x4af8,
+ 0x8b58, 0x2130,
+ 0x8b59, 0x2315,
+ 0x8b5a, 0x2168,
+ 0x8b5b, 0x4af9,
+ 0x8b5c, 0x20c4,
+ 0x8b5d, 0x4afa,
+ 0x8b66, 0x08de,
+ 0x8b67, 0x4b03,
+ 0x8b6b, 0x2318,
+ 0x8b6c, 0x0bc8,
+ 0x8b6d, 0x4b07,
+ 0x8b6f, 0x2219,
+ 0x8b70, 0x2217,
+ 0x8b71, 0x4b09,
+ 0x8b74, 0x20d5,
+ 0x8b75, 0x4b0c,
+ 0x8b77, 0x1f4a,
+ 0x8b78, 0x4b0e,
+ 0x8b7d, 0x2240,
+ 0x8b7e, 0x4b13,
+ 0x8b80, 0x1ed3,
+ 0x8b81, 0x4b15,
+ 0x8b8a, 0x1e49,
+ 0x8b8b, 0x4b1e,
+ 0x8b8e, 0x261b,
+ 0x8b8f, 0x4b21,
+ 0x8b92, 0x1e6d,
+ 0x8b93, 0x20f8,
+ 0x8b94, 0x4b24,
+ 0x8b95, 0x1ffb,
+ 0x8b96, 0x2319,
+ 0x8b97, 0x4b25,
+ 0x8b9c, 0x230e,
+ 0x8b9d, 0x4b2a,
+ 0x8b9e, 0x2317,
+ 0x8b9f, 0x4b2b,
+ 0x8ba0, 0x1317,
+ 0x8ba1, 0x0839,
+ 0x8ba2, 0x05e8,
+ 0x8ba3, 0x06b7,
+ 0x8ba4, 0x0caa,
+ 0x8ba5, 0x0818,
+ 0x8ba6, 0x1318,
+ 0x8ba8, 0x0e29,
+ 0x8ba9, 0x0c9e,
+ 0x8baa, 0x131a,
+ 0x8bab, 0x0c1c,
+ 0x8bac, 0x4b2c,
+ 0x8bad, 0x0fde,
+ 0x8bae, 0x1070,
+ 0x8baf, 0x0fdf,
+ 0x8bb0, 0x083a,
+ 0x8bb1, 0x4b2d,
+ 0x8bb2, 0x0883,
+ 0x8bb3, 0x07f9,
+ 0x8bb4, 0x131b,
+ 0x8bb6, 0x0ff1,
+ 0x8bb7, 0x131d,
+ 0x8bb8, 0x0fb8,
+ 0x8bb9, 0x062e,
+ 0x8bba, 0x0a82,
+ 0x8bbb, 0x4b2e,
+ 0x8bbc, 0x0dc4,
+ 0x8bbd, 0x068a,
+ 0x8bbe, 0x0d21,
+ 0x8bbf, 0x0660,
+ 0x8bc0, 0x0926,
+ 0x8bc1, 0x11a3,
+ 0x8bc2, 0x131e,
+ 0x8bc4, 0x0bdf,
+ 0x8bc5, 0x1244,
+ 0x8bc6, 0x0d4d,
+ 0x8bc7, 0x4b2f,
+ 0x8bc8, 0x114a,
+ 0x8bc9, 0x0dd4,
+ 0x8bca, 0x1190,
+ 0x8bcb, 0x1320,
+ 0x8bcc, 0x11de,
+ 0x8bcd, 0x054d,
+ 0x8bce, 0x1322,
+ 0x8bcf, 0x1321,
+ 0x8bd0, 0x4b30,
+ 0x8bd1, 0x1072,
+ 0x8bd2, 0x1323,
+ 0x8bd5, 0x0d6b,
+ 0x8bd6, 0x1326,
+ 0x8bd7, 0x0d42,
+ 0x8bd8, 0x1327,
+ 0x8bda, 0x04f4,
+ 0x8bdb, 0x11ee,
+ 0x8bdc, 0x1329,
+ 0x8bdd, 0x07c5,
+ 0x8bde, 0x058f,
+ 0x8bdf, 0x132a,
+ 0x8be1, 0x0747,
+ 0x8be2, 0x0fd8,
+ 0x8be3, 0x106f,
+ 0x8be4, 0x132c,
+ 0x8be5, 0x06be,
+ 0x8be6, 0x0f57,
+ 0x8be7, 0x04b6,
+ 0x8be8, 0x132d,
+ 0x8bea, 0x4b31,
+ 0x8beb, 0x08bc,
+ 0x8bec, 0x0eeb,
+ 0x8bed, 0x10d4,
+ 0x8bee, 0x132f,
+ 0x8bef, 0x0f02,
+ 0x8bf0, 0x1330,
+ 0x8bf1, 0x10ba,
+ 0x8bf2, 0x07fa,
+ 0x8bf3, 0x1331,
+ 0x8bf4, 0x0daa,
+ 0x8bf5, 0x0dc5,
+ 0x8bf6, 0x1332,
+ 0x8bf7, 0x0c68,
+ 0x8bf8, 0x11ed,
+ 0x8bf9, 0x1333,
+ 0x8bfa, 0x0b76,
+ 0x8bfb, 0x0600,
+ 0x8bfc, 0x1334,
+ 0x8bfd, 0x0669,
+ 0x8bfe, 0x095b,
+ 0x8bff, 0x1335,
+ 0x8c00, 0x1336,
+ 0x8c01, 0x0da2,
+ 0x8c02, 0x1337,
+ 0x8c03, 0x05d8,
+ 0x8c04, 0x1338,
+ 0x8c05, 0x0a0b,
+ 0x8c06, 0x1218,
+ 0x8c07, 0x1339,
+ 0x8c08, 0x0e0b,
+ 0x8c09, 0x4b32,
+ 0x8c0a, 0x1071,
+ 0x8c0b, 0x0b14,
+ 0x8c0c, 0x133a,
+ 0x8c0d, 0x05de,
+ 0x8c0e, 0x07e6,
+ 0x8c0f, 0x133b,
+ 0x8c10, 0x0f7e,
+ 0x8c11, 0x133c,
+ 0x8c13, 0x0ecc,
+ 0x8c14, 0x133e,
+ 0x8c17, 0x04be,
+ 0x8c18, 0x1343,
+ 0x8c19, 0x1341,
+ 0x8c1a, 0x1011,
+ 0x8c1b, 0x1342,
+ 0x8c1c, 0x0ada,
+ 0x8c1d, 0x1344,
+ 0x8c1e, 0x4b33,
+ 0x8c1f, 0x1345,
+ 0x8c22, 0x0f86,
+ 0x8c23, 0x102c,
+ 0x8c24, 0x0404,
+ 0x8c25, 0x1348,
+ 0x8c26, 0x0c28,
+ 0x8c27, 0x1349,
+ 0x8c28, 0x08c8,
+ 0x8c29, 0x0aa6,
+ 0x8c2a, 0x134a,
+ 0x8c2c, 0x0b02,
+ 0x8c2d, 0x0e0a,
+ 0x8c2e, 0x134c,
+ 0x8c30, 0x09a9,
+ 0x8c31, 0x0bf6,
+ 0x8c32, 0x134e,
+ 0x8c34, 0x0c31,
+ 0x8c35, 0x1350,
+ 0x8c37, 0x0721,
+ 0x8c38, 0x4b34,
+ 0x8c41, 0x0802,
+ 0x8c42, 0x4b3d,
+ 0x8c46, 0x05f8,
+ 0x8c47, 0x1cf6,
+ 0x8c48, 0x20c8,
+ 0x8c49, 0x1cf7,
+ 0x8c4a, 0x4b41,
+ 0x8c4c, 0x0e94,
+ 0x8c4d, 0x4b43,
+ 0x8c50, 0x1efd,
+ 0x8c51, 0x4b46,
+ 0x8c55, 0x1d15,
+ 0x8c56, 0x4b4a,
+ 0x8c5a, 0x1990,
+ 0x8c5b, 0x4b4e,
+ 0x8c61, 0x0f60,
+ 0x8c62, 0x07d4,
+ 0x8c63, 0x4b54,
+ 0x8c6a, 0x0777,
+ 0x8c6b, 0x10e8,
+ 0x8c6c, 0x4b5b,
+ 0x8c73, 0x15dd,
+ 0x8c74, 0x4b62,
+ 0x8c78, 0x1d50,
+ 0x8c79, 0x0413,
+ 0x8c7a, 0x04b9,
+ 0x8c7b, 0x4b66,
+ 0x8c82, 0x1d51,
+ 0x8c83, 0x4b6d,
+ 0x8c85, 0x1d53,
+ 0x8c86, 0x4b6f,
+ 0x8c89, 0x0788,
+ 0x8c8a, 0x1d52,
+ 0x8c8b, 0x4b72,
+ 0x8c8c, 0x0ab7,
+ 0x8c8d, 0x4b73,
+ 0x8c94, 0x1d55,
+ 0x8c95, 0x4b7a,
+ 0x8c98, 0x1d54,
+ 0x8c99, 0x4b7d,
+ 0x8c9d, 0x1e3b,
+ 0x8c9e, 0x227f,
+ 0x8c9f, 0x4b81,
+ 0x8ca0, 0x1f0c,
+ 0x8ca1, 0x1e59,
+ 0x8ca2, 0x1f24,
+ 0x8ca3, 0x4b82,
+ 0x8ca7, 0x20ba,
+ 0x8ca8, 0x1f65,
+ 0x8ca9, 0x1ef0,
+ 0x8caa, 0x2164,
+ 0x8cab, 0x1f30,
+ 0x8cac, 0x2261,
+ 0x8cad, 0x4b86,
+ 0x8caf, 0x22a2,
+ 0x8cb0, 0x24ab,
+ 0x8cb1, 0x4b88,
+ 0x8cb2, 0x24af,
+ 0x8cb3, 0x1ee8,
+ 0x8cb4, 0x1f39,
+ 0x8cb5, 0x4b89,
+ 0x8cb6, 0x1e48,
+ 0x8cb7, 0x2070,
+ 0x8cb8, 0x1ea8,
+ 0x8cb9, 0x4b8a,
+ 0x8cba, 0x24ac,
+ 0x8cbb, 0x1ef7,
+ 0x8cbc, 0x2176,
+ 0x8cbd, 0x24ad,
+ 0x8cbe, 0x4b8b,
+ 0x8cbf, 0x207b,
+ 0x8cc0, 0x1f45,
+ 0x8cc1, 0x24aa,
+ 0x8cc2, 0x204b,
+ 0x8cc3, 0x202f,
+ 0x8cc4, 0x1f5a,
+ 0x8cc5, 0x24b0,
+ 0x8cc6, 0x4b8c,
+ 0x8cc7, 0x22b7,
+ 0x8cc8, 0x1f7f,
+ 0x8cc9, 0x4b8d,
+ 0x8cca, 0x2265,
+ 0x8ccb, 0x4b8e,
+ 0x8cd1, 0x24b2,
+ 0x8cd2, 0x211b,
+ 0x8cd3, 0x1e51,
+ 0x8cd4, 0x4b94,
+ 0x8cd5, 0x24b4,
+ 0x8cd6, 0x4b95,
+ 0x8cda, 0x24b3,
+ 0x8cdb, 0x4b99,
+ 0x8cdc, 0x1e9f,
+ 0x8cdd, 0x4b9a,
+ 0x8cde, 0x2118,
+ 0x8cdf, 0x4b9b,
+ 0x8ce0, 0x20b4,
+ 0x8ce1, 0x23af,
+ 0x8ce2, 0x21bb,
+ 0x8ce3, 0x2072,
+ 0x8ce4, 0x1f95,
+ 0x8ce5, 0x4b9c,
+ 0x8ce6, 0x1f0a,
+ 0x8ce7, 0x24b6,
+ 0x8ce8, 0x4b9d,
+ 0x8cea, 0x2291,
+ 0x8ceb, 0x24b5,
+ 0x8cec, 0x2278,
+ 0x8ced, 0x1ed4,
+ 0x8cee, 0x4b9f,
+ 0x8cf4, 0x1ff3,
+ 0x8cf5, 0x4ba5,
+ 0x8cfa, 0x22a9,
+ 0x8cfb, 0x24b7,
+ 0x8cfc, 0x1f28,
+ 0x8cfd, 0x2109,
+ 0x8cfe, 0x22c7,
+ 0x8cff, 0x4baa,
+ 0x8d00, 0x4bab,
+ 0x8d04, 0x24ae,
+ 0x8d05, 0x22b1,
+ 0x8d06, 0x4baf,
+ 0x8d08, 0x2266,
+ 0x8d09, 0x4bb1,
+ 0x8d0a, 0x225b,
+ 0x8d0b, 0x22c4,
+ 0x8d0c, 0x4bb2,
+ 0x8d0d, 0x2115,
+ 0x8d0e, 0x4bb3,
+ 0x8d0f, 0x222a,
+ 0x8d10, 0x24b1,
+ 0x8d11, 0x4bb4,
+ 0x8d16, 0x213d,
+ 0x8d17, 0x4bb9,
+ 0x8d1b, 0x1f15,
+ 0x8d1c, 0x225c,
+ 0x8d1d, 0x041d,
+ 0x8d1e, 0x118b,
+ 0x8d1f, 0x06b5,
+ 0x8d20, 0x4bbd,
+ 0x8d21, 0x070a,
+ 0x8d22, 0x048d,
+ 0x8d23, 0x1133,
+ 0x8d24, 0x0f3a,
+ 0x8d25, 0x03e7,
+ 0x8d26, 0x116c,
+ 0x8d27, 0x080a,
+ 0x8d28, 0x11c9,
+ 0x8d29, 0x0654,
+ 0x8d2a, 0x0e03,
+ 0x8d2b, 0x0bd5,
+ 0x8d2c, 0x044a,
+ 0x8d2d, 0x0713,
+ 0x8d2e, 0x11fb,
+ 0x8d2f, 0x073a,
+ 0x8d30, 0x063e,
+ 0x8d31, 0x086d,
+ 0x8d32, 0x192c,
+ 0x8d34, 0x0e4c,
+ 0x8d35, 0x074c,
+ 0x8d36, 0x192e,
+ 0x8d37, 0x057e,
+ 0x8d38, 0x0ab8,
+ 0x8d39, 0x066e,
+ 0x8d3a, 0x078f,
+ 0x8d3b, 0x192f,
+ 0x8d3c, 0x1137,
+ 0x8d3d, 0x1930,
+ 0x8d3e, 0x0849,
+ 0x8d3f, 0x07f4,
+ 0x8d40, 0x1931,
+ 0x8d41, 0x0a27,
+ 0x8d42, 0x0a5f,
+ 0x8d43, 0x1122,
+ 0x8d44, 0x1227,
+ 0x8d45, 0x1932,
+ 0x8d47, 0x1936,
+ 0x8d48, 0x1934,
+ 0x8d4a, 0x0d17,
+ 0x8d4b, 0x06ae,
+ 0x8d4c, 0x0603,
+ 0x8d4d, 0x1937,
+ 0x8d4e, 0x0d81,
+ 0x8d4f, 0x0d06,
+ 0x8d50, 0x0550,
+ 0x8d51, 0x4bbe,
+ 0x8d53, 0x163b,
+ 0x8d54, 0x0ba3,
+ 0x8d55, 0x1938,
+ 0x8d56, 0x09a0,
+ 0x8d57, 0x4bc0,
+ 0x8d58, 0x1215,
+ 0x8d59, 0x1939,
+ 0x8d5a, 0x1209,
+ 0x8d5b, 0x0cd7,
+ 0x8d5c, 0x1289,
+ 0x8d5d, 0x1283,
+ 0x8d5e, 0x1121,
+ 0x8d5f, 0x4bc1,
+ 0x8d60, 0x113c,
+ 0x8d61, 0x0cfd,
+ 0x8d62, 0x1093,
+ 0x8d63, 0x06ce,
+ 0x8d64, 0x0505,
+ 0x8d65, 0x4bc2,
+ 0x8d66, 0x0d1b,
+ 0x8d67, 0x1cf4,
+ 0x8d68, 0x4bc3,
+ 0x8d6b, 0x078c,
+ 0x8d6c, 0x4bc6,
+ 0x8d6d, 0x1cf5,
+ 0x8d6e, 0x4bc7,
+ 0x8d70, 0x123c,
+ 0x8d71, 0x4bc9,
+ 0x8d73, 0x1cef,
+ 0x8d74, 0x06ab,
+ 0x8d75, 0x1175,
+ 0x8d76, 0x06ca,
+ 0x8d77, 0x0c0f,
+ 0x8d78, 0x4bcb,
+ 0x8d81, 0x04e8,
+ 0x8d82, 0x4bd4,
+ 0x8d84, 0x1cf0,
+ 0x8d85, 0x04d1,
+ 0x8d86, 0x4bd6,
+ 0x8d8a, 0x1100,
+ 0x8d8b, 0x0c74,
+ 0x8d8c, 0x4bda,
+ 0x8d91, 0x1cf2,
+ 0x8d92, 0x4bdf,
+ 0x8d94, 0x1cf1,
+ 0x8d95, 0x1f14,
+ 0x8d96, 0x4be1,
+ 0x8d99, 0x227a,
+ 0x8d9a, 0x4be4,
+ 0x8d9f, 0x0e1e,
+ 0x8da0, 0x4be9,
+ 0x8da3, 0x0c7f,
+ 0x8da4, 0x4bec,
+ 0x8da8, 0x20ee,
+ 0x8da9, 0x4bf0,
+ 0x8db1, 0x1cf3,
+ 0x8db2, 0x25f8,
+ 0x8db3, 0x1240,
+ 0x8db4, 0x0b80,
+ 0x8db5, 0x1d1c,
+ 0x8db6, 0x4bf8,
+ 0x8db8, 0x1d17,
+ 0x8db9, 0x4bfa,
+ 0x8dba, 0x1d1f,
+ 0x8dbb, 0x4bfb,
+ 0x8dbc, 0x1d1e,
+ 0x8dbd, 0x4bfc,
+ 0x8dbe, 0x11b9,
+ 0x8dbf, 0x1d1d,
+ 0x8dc0, 0x4bfd,
+ 0x8dc3, 0x1101,
+ 0x8dc4, 0x1d20,
+ 0x8dc5, 0x4c00,
+ 0x8dc6, 0x1d28,
+ 0x8dc7, 0x4c01,
+ 0x8dcb, 0x03da,
+ 0x8dcc, 0x05d9,
+ 0x8dcd, 0x4c05,
+ 0x8dce, 0x1d25,
+ 0x8dd0, 0x4c06,
+ 0x8dd1, 0x0b9d,
+ 0x8dd2, 0x4c07,
+ 0x8dd6, 0x1d21,
+ 0x8dd8, 0x4c0b,
+ 0x8dda, 0x1d23,
+ 0x8ddb, 0x1d27,
+ 0x8ddc, 0x4c0d,
+ 0x8ddd, 0x090f,
+ 0x8dde, 0x1d24,
+ 0x8ddf, 0x06f5,
+ 0x8de0, 0x4c0e,
+ 0x8de3, 0x1d2c,
+ 0x8de4, 0x1d2f,
+ 0x8de5, 0x4c11,
+ 0x8de8, 0x0974,
+ 0x8de9, 0x4c14,
+ 0x8dea, 0x074b,
+ 0x8deb, 0x1d18,
+ 0x8dec, 0x1d29,
+ 0x8ded, 0x4c15,
+ 0x8def, 0x0a5e,
+ 0x8df0, 0x4c17,
+ 0x8df3, 0x0e4b,
+ 0x8df4, 0x4c1a,
+ 0x8df5, 0x086c,
+ 0x8df6, 0x4c1b,
+ 0x8df7, 0x1d2a,
+ 0x8df9, 0x1d2d,
+ 0x8dfa, 0x0624,
+ 0x8dfb, 0x1d2e,
+ 0x8dfc, 0x4c1c,
+ 0x8dfd, 0x1d31,
+ 0x8dfe, 0x4c1d,
+ 0x8e00, 0x4c1f,
+ 0x8e05, 0x1d19,
+ 0x8e06, 0x4c24,
+ 0x8e09, 0x1d30,
+ 0x8e0a, 0x10a0,
+ 0x8e0b, 0x4c27,
+ 0x8e0c, 0x0511,
+ 0x8e0d, 0x4c28,
+ 0x8e0f, 0x0df7,
+ 0x8e10, 0x1f94,
+ 0x8e11, 0x4c2a,
+ 0x8e14, 0x1d32,
+ 0x8e15, 0x4c2d,
+ 0x8e1d, 0x1d33,
+ 0x8e1e, 0x0910,
+ 0x8e1f, 0x1d34,
+ 0x8e20, 0x4c35,
+ 0x8e22, 0x0e32,
+ 0x8e23, 0x1d37,
+ 0x8e24, 0x4c37,
+ 0x8e29, 0x048f,
+ 0x8e2a, 0x1236,
+ 0x8e2b, 0x4c3c,
+ 0x8e2c, 0x1d35,
+ 0x8e2d, 0x4c3d,
+ 0x8e2e, 0x1d36,
+ 0x8e2f, 0x1d38,
+ 0x8e30, 0x4c3e,
+ 0x8e31, 0x1d3e,
+ 0x8e32, 0x4c3f,
+ 0x8e34, 0x2230,
+ 0x8e35, 0x1d3c,
+ 0x8e36, 0x4c41,
+ 0x8e39, 0x1d3b,
+ 0x8e3a, 0x1d39,
+ 0x8e3b, 0x4c44,
+ 0x8e3d, 0x1d3d,
+ 0x8e3e, 0x4c46,
+ 0x8e40, 0x1d3a,
+ 0x8e41, 0x1d40,
+ 0x8e43, 0x4c48,
+ 0x8e44, 0x0e36,
+ 0x8e45, 0x4c49,
+ 0x8e47, 0x173b,
+ 0x8e48, 0x0599,
+ 0x8e49, 0x1d3f,
+ 0x8e4a, 0x1d44,
+ 0x8e4b, 0x0df6,
+ 0x8e4c, 0x25fd,
+ 0x8e4d, 0x4c4b,
+ 0x8e51, 0x1d42,
+ 0x8e53, 0x4c4f,
+ 0x8e55, 0x2600,
+ 0x8e56, 0x4c51,
+ 0x8e59, 0x1d1a,
+ 0x8e5a, 0x4c54,
+ 0x8e63, 0x2606,
+ 0x8e64, 0x4c5d,
+ 0x8e66, 0x042d,
+ 0x8e67, 0x4c5f,
+ 0x8e69, 0x1d1b,
+ 0x8e6a, 0x4c61,
+ 0x8e6c, 0x05a6,
+ 0x8e6d, 0x04ab,
+ 0x8e6e, 0x4c63,
+ 0x8e6f, 0x1d48,
+ 0x8e70, 0x1d45,
+ 0x8e71, 0x4c64,
+ 0x8e72, 0x0616,
+ 0x8e73, 0x4c65,
+ 0x8e74, 0x1d49,
+ 0x8e75, 0x4c66,
+ 0x8e76, 0x1d46,
+ 0x8e77, 0x4c67,
+ 0x8e7a, 0x25ff,
+ 0x8e7b, 0x4c6a,
+ 0x8e7c, 0x1d47,
+ 0x8e7d, 0x4c6b,
+ 0x8e7f, 0x055d,
+ 0x8e80, 0x4c6d,
+ 0x8e81, 0x112d,
+ 0x8e82, 0x4c6e,
+ 0x8e85, 0x1d4a,
+ 0x8e86, 0x4c71,
+ 0x8e87, 0x051e,
+ 0x8e88, 0x4c72,
+ 0x8e89, 0x25fc,
+ 0x8e8a, 0x1e8c,
+ 0x8e8b, 0x2602,
+ 0x8e8c, 0x4c73,
+ 0x8e8d, 0x224d,
+ 0x8e8e, 0x4c74,
+ 0x8e8f, 0x1d4b,
+ 0x8e90, 0x1d4d,
+ 0x8e91, 0x2604,
+ 0x8e92, 0x25fe,
+ 0x8e93, 0x2603,
+ 0x8e94, 0x1d4c,
+ 0x8e95, 0x4c75,
+ 0x8e9a, 0x2601,
+ 0x8e9b, 0x4c7a,
+ 0x8e9c, 0x1d4e,
+ 0x8e9d, 0x4c7b,
+ 0x8e9e, 0x1d4f,
+ 0x8e9f, 0x4c7c,
+ 0x8ea1, 0x2605,
+ 0x8ea2, 0x4c7e,
+ 0x8ea5, 0x1ea3,
+ 0x8ea6, 0x2608,
+ 0x8ea7, 0x4c81,
+ 0x8eaa, 0x2607,
+ 0x8eab, 0x0d26,
+ 0x8eac, 0x0703,
+ 0x8ead, 0x4c84,
+ 0x8eaf, 0x0c78,
+ 0x8eb0, 0x4c86,
+ 0x8eb2, 0x0622,
+ 0x8eb3, 0x4c88,
+ 0x8eba, 0x0e1c,
+ 0x8ebb, 0x4c8f,
+ 0x8ec0, 0x20f0,
+ 0x8ec1, 0x4c94,
+ 0x8eca, 0x1e7b,
+ 0x8ecb, 0x2267,
+ 0x8ecc, 0x1f36,
+ 0x8ecd, 0x1fd6,
+ 0x8ece, 0x18f8,
+ 0x8ecf, 0x4c9d,
+ 0x8ed2, 0x21e0,
+ 0x8ed3, 0x4ca0,
+ 0x8ed4, 0x248c,
+ 0x8ed5, 0x4ca1,
+ 0x8edb, 0x248d,
+ 0x8edc, 0x4ca7,
+ 0x8edf, 0x2102,
+ 0x8ee0, 0x4caa,
+ 0x8ee4, 0x2494,
+ 0x8ee5, 0x4cae,
+ 0x8eeb, 0x2493,
+ 0x8eec, 0x4cb4,
+ 0x8ef2, 0x248e,
+ 0x8ef3, 0x4cba,
+ 0x8ef8, 0x2299,
+ 0x8ef9, 0x2491,
+ 0x8efa, 0x2496,
+ 0x8efb, 0x248f,
+ 0x8efc, 0x2492,
+ 0x8efd, 0x4cbf,
+ 0x8efe, 0x2497,
+ 0x8eff, 0x4cc0,
+ 0x8f00, 0x4cc1,
+ 0x8f03, 0x1fb1,
+ 0x8f04, 0x4cc4,
+ 0x8f05, 0x249a,
+ 0x8f06, 0x4cc5,
+ 0x8f07, 0x2499,
+ 0x8f08, 0x4cc6,
+ 0x8f09, 0x2258,
+ 0x8f0a, 0x2498,
+ 0x8f0b, 0x4cc7,
+ 0x8f12, 0x249b,
+ 0x8f13, 0x4cce,
+ 0x8f14, 0x1f09,
+ 0x8f15, 0x20e6,
+ 0x8f16, 0x4ccf,
+ 0x8f1b, 0x2026,
+ 0x8f1c, 0x249f,
+ 0x8f1d, 0x1f59,
+ 0x8f1e, 0x249d,
+ 0x8f20, 0x4cd4,
+ 0x8f25, 0x1f3b,
+ 0x8f26, 0x249c,
+ 0x8f27, 0x4cd9,
+ 0x8f29, 0x1e3a,
+ 0x8f2a, 0x205b,
+ 0x8f2b, 0x4cdb,
+ 0x8f2f, 0x1f70,
+ 0x8f30, 0x4cdf,
+ 0x8f33, 0x24a0,
+ 0x8f34, 0x4ce2,
+ 0x8f38, 0x213b,
+ 0x8f39, 0x4ce6,
+ 0x8f3b, 0x1f07,
+ 0x8f3c, 0x4ce8,
+ 0x8f3e, 0x2270,
+ 0x8f3f, 0x2237,
+ 0x8f40, 0x4cea,
+ 0x8f42, 0x24d2,
+ 0x8f43, 0x4cec,
+ 0x8f44, 0x21b3,
+ 0x8f45, 0x2245,
+ 0x8f46, 0x24a1,
+ 0x8f47, 0x4ced,
+ 0x8f49, 0x22a8,
+ 0x8f4a, 0x4cef,
+ 0x8f4d, 0x227c,
+ 0x8f4e, 0x1fb0,
+ 0x8f4f, 0x4cf2,
+ 0x8f54, 0x24a2,
+ 0x8f55, 0x4cf7,
+ 0x8f5f, 0x1f46,
+ 0x8f60, 0x4d01,
+ 0x8f61, 0x2380,
+ 0x8f62, 0x2495,
+ 0x8f63, 0x4d02,
+ 0x8f64, 0x2490,
+ 0x8f65, 0x4d03,
+ 0x8f66, 0x04da,
+ 0x8f67, 0x1141,
+ 0x8f68, 0x0745,
+ 0x8f69, 0x0fc4,
+ 0x8f6a, 0x4d04,
+ 0x8f6b, 0x18e1,
+ 0x8f6c, 0x1207,
+ 0x8f6d, 0x18e2,
+ 0x8f6e, 0x0a7d,
+ 0x8f6f, 0x0cc8,
+ 0x8f70, 0x079b,
+ 0x8f71, 0x18e3,
+ 0x8f74, 0x11e0,
+ 0x8f75, 0x18e6,
+ 0x8f77, 0x18e9,
+ 0x8f78, 0x18e8,
+ 0x8f79, 0x18ea,
+ 0x8f7b, 0x0c5e,
+ 0x8f7c, 0x18ec,
+ 0x8f7d, 0x111b,
+ 0x8f7e, 0x18ed,
+ 0x8f7f, 0x089f,
+ 0x8f80, 0x4d05,
+ 0x8f81, 0x18ee,
+ 0x8f83, 0x08a0,
+ 0x8f84, 0x18f0,
+ 0x8f85, 0x06a3,
+ 0x8f86, 0x0a07,
+ 0x8f87, 0x18f1,
+ 0x8f88, 0x041b,
+ 0x8f89, 0x07e9,
+ 0x8f8a, 0x074e,
+ 0x8f8b, 0x18f2,
+ 0x8f8c, 0x4d06,
+ 0x8f8d, 0x18f3,
+ 0x8f90, 0x0695,
+ 0x8f91, 0x0820,
+ 0x8f92, 0x4d07,
+ 0x8f93, 0x0d7b,
+ 0x8f94, 0x1574,
+ 0x8f95, 0x10f2,
+ 0x8f96, 0x0f2a,
+ 0x8f97, 0x1158,
+ 0x8f98, 0x18f6,
+ 0x8f99, 0x117f,
+ 0x8f9a, 0x18f7,
+ 0x8f9b, 0x0f8c,
+ 0x8f9c, 0x0715,
+ 0x8f9d, 0x4d08,
+ 0x8f9e, 0x054a,
+ 0x8f9f, 0x0442,
+ 0x8fa0, 0x4d09,
+ 0x8fa3, 0x099c,
+ 0x8fa4, 0x4d0c,
+ 0x8fa6, 0x1e30,
+ 0x8fa7, 0x4d0e,
+ 0x8fa8, 0x044f,
+ 0x8faa, 0x4d0f,
+ 0x8fab, 0x0451,
+ 0x8fac, 0x4d10,
+ 0x8fad, 0x1e9d,
+ 0x8fae, 0x1e4b,
+ 0x8faf, 0x1e4a,
+ 0x8fb0, 0x04e2,
+ 0x8fb1, 0x0cc3,
+ 0x8fb2, 0x20aa,
+ 0x8fb3, 0x4d11,
+ 0x8fb6, 0x173d,
+ 0x8fb7, 0x4d14,
+ 0x8fb9, 0x0448,
+ 0x8fba, 0x4d16,
+ 0x8fbd, 0x0a12,
+ 0x8fbe, 0x0572,
+ 0x8fbf, 0x4d19,
+ 0x8fc1, 0x0c25,
+ 0x8fc2, 0x10bd,
+ 0x8fc3, 0x4d1b,
+ 0x8fc4, 0x0c18,
+ 0x8fc5, 0x0fe1,
+ 0x8fc6, 0x4d1c,
+ 0x8fc7, 0x0756,
+ 0x8fc8, 0x0a9c,
+ 0x8fc9, 0x4d1d,
+ 0x8fce, 0x1092,
+ 0x8fcf, 0x4d22,
+ 0x8fd0, 0x110e,
+ 0x8fd1, 0x08cd,
+ 0x8fd2, 0x4d23,
+ 0x8fd3, 0x173e,
+ 0x8fd4, 0x0652,
+ 0x8fd5, 0x173f,
+ 0x8fd6, 0x4d24,
+ 0x8fd8, 0x07ce,
+ 0x8fd9, 0x1183,
+ 0x8fda, 0x4d26,
+ 0x8fdb, 0x08c9,
+ 0x8fdc, 0x10f9,
+ 0x8fdd, 0x0eb4,
+ 0x8fde, 0x09f5,
+ 0x8fdf, 0x04fe,
+ 0x8fe0, 0x4d27,
+ 0x8fe2, 0x0e49,
+ 0x8fe3, 0x4d29,
+ 0x8fe4, 0x1742,
+ 0x8fe5, 0x1740,
+ 0x8fe6, 0x1744,
+ 0x8fe7, 0x4d2a,
+ 0x8fe8, 0x1746,
+ 0x8fe9, 0x1743,
+ 0x8fea, 0x05b0,
+ 0x8feb, 0x0be7,
+ 0x8fec, 0x4d2b,
+ 0x8fed, 0x05dd,
+ 0x8fee, 0x1741,
+ 0x8fef, 0x4d2c,
+ 0x8ff0, 0x0d8d,
+ 0x8ff1, 0x4d2d,
+ 0x8ff3, 0x1745,
+ 0x8ff4, 0x267b,
+ 0x8ff5, 0x4d2f,
+ 0x8ff7, 0x0ad9,
+ 0x8ff8, 0x042e,
+ 0x8ff9, 0x0816,
+ 0x8ffa, 0x4d31,
+ 0x8ffd, 0x1214,
+ 0x8ffe, 0x4d34,
+ 0x9000, 0x0e7c,
+ 0x9001, 0x0dc2,
+ 0x9002, 0x0d61,
+ 0x9003, 0x0e26,
+ 0x9004, 0x1748,
+ 0x9005, 0x1747,
+ 0x9006, 0x0b49,
+ 0x9007, 0x4d36,
+ 0x9009, 0x0fca,
+ 0x900a, 0x0fe0,
+ 0x900b, 0x1749,
+ 0x900c, 0x4d38,
+ 0x900d, 0x174c,
+ 0x900e, 0x4d39,
+ 0x900f, 0x0e69,
+ 0x9010, 0x11ef,
+ 0x9011, 0x174b,
+ 0x9012, 0x05be,
+ 0x9013, 0x4d3a,
+ 0x9014, 0x0e6f,
+ 0x9015, 0x23f2,
+ 0x9016, 0x174d,
+ 0x9017, 0x05f9,
+ 0x9018, 0x4d3b,
+ 0x9019, 0x227e,
+ 0x901a, 0x0e59,
+ 0x901b, 0x073d,
+ 0x901c, 0x4d3c,
+ 0x901d, 0x0d5c,
+ 0x901e, 0x04f6,
+ 0x901f, 0x0dce,
+ 0x9020, 0x112f,
+ 0x9021, 0x174e,
+ 0x9022, 0x0687,
+ 0x9023, 0x2019,
+ 0x9024, 0x4d3d,
+ 0x9026, 0x174a,
+ 0x9027, 0x4d3f,
+ 0x902d, 0x1751,
+ 0x902e, 0x0581,
+ 0x902f, 0x1752,
+ 0x9030, 0x4d45,
+ 0x9032, 0x1fbb,
+ 0x9033, 0x4d47,
+ 0x9035, 0x174f,
+ 0x9037, 0x4d49,
+ 0x9038, 0x1064,
+ 0x9039, 0x4d4a,
+ 0x903b, 0x0a86,
+ 0x903c, 0x042f,
+ 0x903d, 0x4d4c,
+ 0x903e, 0x10c7,
+ 0x903f, 0x4d4d,
+ 0x9041, 0x061c,
+ 0x9042, 0x0de1,
+ 0x9043, 0x4d4f,
+ 0x9044, 0x1753,
+ 0x9045, 0x4d50,
+ 0x9047, 0x10db,
+ 0x9048, 0x4d52,
+ 0x904b, 0x2253,
+ 0x904c, 0x4d55,
+ 0x904d, 0x0452,
+ 0x904e, 0x1f3e,
+ 0x904f, 0x0633,
+ 0x9050, 0x1756,
+ 0x9051, 0x1754,
+ 0x9053, 0x05a1,
+ 0x9054, 0x1ea6,
+ 0x9055, 0x218e,
+ 0x9056, 0x4d56,
+ 0x9057, 0x104c,
+ 0x9058, 0x1758,
+ 0x9059, 0x4d57,
+ 0x905b, 0x175a,
+ 0x905c, 0x21ec,
+ 0x905d, 0x4d59,
+ 0x905e, 0x1ebe,
+ 0x905f, 0x4d5a,
+ 0x9060, 0x224a,
+ 0x9061, 0x4d5b,
+ 0x9062, 0x1759,
+ 0x9063, 0x0c2f,
+ 0x9064, 0x4d5c,
+ 0x9065, 0x102a,
+ 0x9066, 0x4d5d,
+ 0x9068, 0x1757,
+ 0x9069, 0x2133,
+ 0x906a, 0x4d5f,
+ 0x906d, 0x1125,
+ 0x906e, 0x117b,
+ 0x906f, 0x4d62,
+ 0x9072, 0x1e84,
+ 0x9073, 0x4d65,
+ 0x9074, 0x175c,
+ 0x9075, 0x124e,
+ 0x9076, 0x4d66,
+ 0x9077, 0x20cf,
+ 0x9078, 0x21e2,
+ 0x9079, 0x4d67,
+ 0x907a, 0x220f,
+ 0x907b, 0x4d68,
+ 0x907c, 0x2029,
+ 0x907d, 0x175d,
+ 0x907e, 0x4d69,
+ 0x907f, 0x0445,
+ 0x9080, 0x1024,
+ 0x9081, 0x2073,
+ 0x9082, 0x175e,
+ 0x9083, 0x1760,
+ 0x9084, 0x1f55,
+ 0x9085, 0x4d6a,
+ 0x9087, 0x23f1,
+ 0x9088, 0x175f,
+ 0x9089, 0x4d6c,
+ 0x908a, 0x1e46,
+ 0x908b, 0x1761,
+ 0x908c, 0x4d6d,
+ 0x908f, 0x2063,
+ 0x9090, 0x23f3,
+ 0x9091, 0x105f,
+ 0x9092, 0x4d70,
+ 0x9093, 0x05ac,
+ 0x9094, 0x4d71,
+ 0x9095, 0x1817,
+ 0x9096, 0x4d72,
+ 0x9097, 0x1367,
+ 0x9098, 0x4d73,
+ 0x9099, 0x136a,
+ 0x909a, 0x4d74,
+ 0x909b, 0x1368,
+ 0x909c, 0x4d75,
+ 0x909d, 0x1369,
+ 0x909e, 0x4d76,
+ 0x90a1, 0x136c,
+ 0x90a2, 0x0f9a,
+ 0x90a3, 0x0b2a,
+ 0x90a4, 0x4d79,
+ 0x90a6, 0x03f9,
+ 0x90a7, 0x4d7b,
+ 0x90aa, 0x0f7b,
+ 0x90ab, 0x4d7e,
+ 0x90ac, 0x136b,
+ 0x90ad, 0x4d7f,
+ 0x90ae, 0x10af,
+ 0x90af, 0x0761,
+ 0x90b0, 0x1372,
+ 0x90b1, 0x0c6e,
+ 0x90b2, 0x4d80,
+ 0x90b3, 0x136e,
+ 0x90b4, 0x136d,
+ 0x90b5, 0x0d14,
+ 0x90b6, 0x136f,
+ 0x90b7, 0x4d81,
+ 0x90b8, 0x1371,
+ 0x90b9, 0x123b,
+ 0x90ba, 0x1370,
+ 0x90bb, 0x0a23,
+ 0x90bc, 0x4d82,
+ 0x90be, 0x1375,
+ 0x90bf, 0x4d84,
+ 0x90c1, 0x10d9,
+ 0x90c2, 0x4d86,
+ 0x90c4, 0x1377,
+ 0x90c5, 0x1374,
+ 0x90c6, 0x4d88,
+ 0x90c7, 0x1378,
+ 0x90c8, 0x4d89,
+ 0x90ca, 0x088d,
+ 0x90cb, 0x4d8b,
+ 0x90ce, 0x09b4,
+ 0x90cf, 0x1373,
+ 0x90d0, 0x1376,
+ 0x90d1, 0x11a2,
+ 0x90d2, 0x4d8e,
+ 0x90d3, 0x1379,
+ 0x90d4, 0x4d8f,
+ 0x90d7, 0x137d,
+ 0x90d8, 0x4d92,
+ 0x90db, 0x137e,
+ 0x90dc, 0x137c,
+ 0x90dd, 0x0779,
+ 0x90de, 0x4d95,
+ 0x90df, 0x231e,
+ 0x90e0, 0x4d96,
+ 0x90e1, 0x0931,
+ 0x90e2, 0x137b,
+ 0x90e3, 0x4d97,
+ 0x90e6, 0x137a,
+ 0x90e7, 0x110a,
+ 0x90e8, 0x0486,
+ 0x90e9, 0x4d9a,
+ 0x90eb, 0x137f,
+ 0x90ec, 0x4d9c,
+ 0x90ed, 0x0752,
+ 0x90ee, 0x4d9d,
+ 0x90ef, 0x1380,
+ 0x90f0, 0x4d9e,
+ 0x90f4, 0x04e0,
+ 0x90f5, 0x2233,
+ 0x90f6, 0x4da2,
+ 0x90f8, 0x0587,
+ 0x90f9, 0x4da4,
+ 0x90fd, 0x05fb,
+ 0x90fe, 0x1381,
+ 0x90ff, 0x4da8,
+ 0x9100, 0x4da9,
+ 0x9102, 0x0634,
+ 0x9103, 0x4dab,
+ 0x9104, 0x1382,
+ 0x9105, 0x4dac,
+ 0x9106, 0x2320,
+ 0x9107, 0x4dad,
+ 0x9109, 0x21c7,
+ 0x910a, 0x4daf,
+ 0x9112, 0x22bc,
+ 0x9113, 0x4db7,
+ 0x9114, 0x231c,
+ 0x9115, 0x4db8,
+ 0x9116, 0x2251,
+ 0x9117, 0x4db9,
+ 0x9119, 0x0432,
+ 0x911a, 0x4dbb,
+ 0x911e, 0x1384,
+ 0x911f, 0x4dbf,
+ 0x9122, 0x1383,
+ 0x9123, 0x1385,
+ 0x9124, 0x4dc2,
+ 0x9127, 0x1ebb,
+ 0x9128, 0x4dc5,
+ 0x912d, 0x2287,
+ 0x912e, 0x4dca,
+ 0x912f, 0x1387,
+ 0x9130, 0x202d,
+ 0x9131, 0x1386,
+ 0x9132, 0x1eab,
+ 0x9133, 0x4dcb,
+ 0x9134, 0x231d,
+ 0x9135, 0x4dcc,
+ 0x9136, 0x231f,
+ 0x9137, 0x4dcd,
+ 0x9139, 0x1388,
+ 0x913a, 0x231b,
+ 0x913b, 0x4dcf,
+ 0x9143, 0x1389,
+ 0x9144, 0x4dd7,
+ 0x9146, 0x138a,
+ 0x9147, 0x4dd9,
+ 0x9148, 0x2321,
+ 0x9149, 0x10b4,
+ 0x914a, 0x1cf8,
+ 0x914b, 0x0c72,
+ 0x914c, 0x1220,
+ 0x914d, 0x0ba5,
+ 0x914e, 0x1cfa,
+ 0x9150, 0x1cf9,
+ 0x9151, 0x4dda,
+ 0x9152, 0x08f5,
+ 0x9153, 0x4ddb,
+ 0x9157, 0x0fba,
+ 0x9158, 0x4ddf,
+ 0x915a, 0x0670,
+ 0x915b, 0x4de1,
+ 0x915d, 0x1110,
+ 0x915e, 0x0dfd,
+ 0x915f, 0x4de3,
+ 0x9161, 0x1cfe,
+ 0x9162, 0x1cfd,
+ 0x9163, 0x075f,
+ 0x9164, 0x1cfc,
+ 0x9165, 0x0dcb,
+ 0x9166, 0x4de5,
+ 0x9169, 0x1d00,
+ 0x916a, 0x09bd,
+ 0x916b, 0x4de8,
+ 0x916c, 0x050f,
+ 0x916d, 0x4de9,
+ 0x916e, 0x0e5b,
+ 0x916f, 0x1d01,
+ 0x9170, 0x1cff,
+ 0x9171, 0x0885,
+ 0x9172, 0x1d04,
+ 0x9173, 0x4dea,
+ 0x9174, 0x1d05,
+ 0x9175, 0x089e,
+ 0x9176, 0x0abd,
+ 0x9177, 0x096e,
+ 0x9178, 0x0dd6,
+ 0x9179, 0x1d06,
+ 0x917a, 0x4deb,
+ 0x917d, 0x1d02,
+ 0x917f, 0x0b53,
+ 0x9180, 0x4dee,
+ 0x9185, 0x1d08,
+ 0x9186, 0x4df3,
+ 0x9187, 0x053f,
+ 0x9188, 0x4df4,
+ 0x9189, 0x124a,
+ 0x918a, 0x4df5,
+ 0x918b, 0x055a,
+ 0x918c, 0x1d07,
+ 0x918d, 0x1d0a,
+ 0x918e, 0x4df6,
+ 0x9190, 0x1d09,
+ 0x9191, 0x1d0b,
+ 0x9192, 0x0f9c,
+ 0x9193, 0x4df8,
+ 0x9196, 0x2255,
+ 0x9197, 0x4dfb,
+ 0x919a, 0x0ad6,
+ 0x919b, 0x0c84,
+ 0x919c, 0x1e8f,
+ 0x919d, 0x4dfe,
+ 0x91a2, 0x1d0c,
+ 0x91a4, 0x4e03,
+ 0x91aa, 0x1d0e,
+ 0x91ab, 0x220c,
+ 0x91ac, 0x1fa4,
+ 0x91ad, 0x1d0f,
+ 0x91b0, 0x4e09,
+ 0x91b4, 0x1d13,
+ 0x91b5, 0x1d12,
+ 0x91b6, 0x4e0d,
+ 0x91ba, 0x1d14,
+ 0x91bb, 0x4e11,
+ 0x91c0, 0x209b,
+ 0x91c1, 0x21d8,
+ 0x91c2, 0x4e16,
+ 0x91c3, 0x25fa,
+ 0x91c4, 0x4e17,
+ 0x91c5, 0x25f9,
+ 0x91c6, 0x4e18,
+ 0x91c7, 0x0490,
+ 0x91c8, 0x4e19,
+ 0x91c9, 0x10b9,
+ 0x91ca, 0x0d64,
+ 0x91cb, 0x2134,
+ 0x91cc, 0x09da,
+ 0x91cd, 0x11d7,
+ 0x91ce, 0x1037,
+ 0x91cf, 0x0a08,
+ 0x91d0, 0x4e1a,
+ 0x91d1, 0x08c1,
+ 0x91d2, 0x24f3,
+ 0x91d5, 0x24f8,
+ 0x91d6, 0x4e1b,
+ 0x91d7, 0x24f7,
+ 0x91d8, 0x1ec8,
+ 0x91d9, 0x24f6,
+ 0x91da, 0x4e1c,
+ 0x91dc, 0x06a5,
+ 0x91dd, 0x2280,
+ 0x91de, 0x4e1e,
+ 0x91e3, 0x1ec5,
+ 0x91e4, 0x24fb,
+ 0x91e5, 0x4e23,
+ 0x91e7, 0x24fa,
+ 0x91e8, 0x4e25,
+ 0x91e9, 0x1eed,
+ 0x91ea, 0x4e26,
+ 0x91f5, 0x24fd,
+ 0x91f6, 0x4e31,
+ 0x91f7, 0x24f9,
+ 0x91f8, 0x4e32,
+ 0x91f9, 0x24fe,
+ 0x91fa, 0x20cd,
+ 0x91fb, 0x4e33,
+ 0x9200, 0x2508,
+ 0x9201, 0x2504,
+ 0x9202, 0x4e38,
+ 0x9204, 0x2506,
+ 0x9205, 0x4e3a,
+ 0x9208, 0x24ff,
+ 0x9209, 0x2090,
+ 0x920a, 0x4e3d,
+ 0x920d, 0x1edd,
+ 0x920e, 0x1f25,
+ 0x920f, 0x4e40,
+ 0x9210, 0x2503,
+ 0x9211, 0x2502,
+ 0x9212, 0x4e41,
+ 0x9214, 0x1e7a,
+ 0x9215, 0x20a6,
+ 0x9216, 0x4e43,
+ 0x921e, 0x1fd5,
+ 0x921f, 0x4e4b,
+ 0x9223, 0x1f11,
+ 0x9224, 0x4e4f,
+ 0x9225, 0x2507,
+ 0x9226, 0x2500,
+ 0x9227, 0x2505,
+ 0x9228, 0x4e50,
+ 0x922e, 0x2519,
+ 0x922f, 0x4e56,
+ 0x9230, 0x2515,
+ 0x9231, 0x4e57,
+ 0x9233, 0x250c,
+ 0x9234, 0x2031,
+ 0x9235, 0x4e59,
+ 0x9237, 0x250b,
+ 0x9238, 0x250f,
+ 0x9239, 0x251a,
+ 0x923a, 0x2509,
+ 0x923b, 0x4e5b,
+ 0x923d, 0x250e,
+ 0x923e, 0x2234,
+ 0x923f, 0x2513,
+ 0x9240, 0x1f80,
+ 0x9241, 0x4e5d,
+ 0x9245, 0x2501,
+ 0x9246, 0x4e61,
+ 0x9248, 0x2517,
+ 0x9249, 0x2516,
+ 0x924a, 0x4e63,
+ 0x924d, 0x2518,
+ 0x924e, 0x4e66,
+ 0x9251, 0x1e56,
+ 0x9252, 0x4e69,
+ 0x9255, 0x250d,
+ 0x9256, 0x4e6c,
+ 0x9257, 0x20d3,
+ 0x9258, 0x4e6d,
+ 0x925a, 0x207a,
+ 0x925b, 0x20ce,
+ 0x925c, 0x4e6f,
+ 0x925e, 0x2510,
+ 0x925f, 0x4e71,
+ 0x9262, 0x1e55,
+ 0x9263, 0x4e74,
+ 0x9266, 0x250a,
+ 0x9267, 0x4e77,
+ 0x926c, 0x2511,
+ 0x926e, 0x4e7c,
+ 0x9274, 0x086b,
+ 0x9275, 0x4e82,
+ 0x9278, 0x1faa,
+ 0x9279, 0x4e85,
+ 0x927a, 0x251e,
+ 0x927b, 0x1f1f,
+ 0x927c, 0x4e86,
+ 0x927f, 0x252d,
+ 0x9280, 0x221d,
+ 0x9281, 0x4e89,
+ 0x9283, 0x2532,
+ 0x9284, 0x4e8b,
+ 0x9285, 0x217b,
+ 0x9286, 0x4e8c,
+ 0x928e, 0x1d80,
+ 0x928f, 0x4e94,
+ 0x9291, 0x21af,
+ 0x9292, 0x4e96,
+ 0x9293, 0x252c,
+ 0x9294, 0x4e97,
+ 0x9296, 0x2528,
+ 0x9297, 0x4e99,
+ 0x9298, 0x208c,
+ 0x9299, 0x4e9a,
+ 0x929a, 0x252f,
+ 0x929b, 0x4e9b,
+ 0x929c, 0x21bc,
+ 0x929d, 0x4e9c,
+ 0x92a0, 0x251d,
+ 0x92a1, 0x4e9f,
+ 0x92a3, 0x2535,
+ 0x92a4, 0x4ea1,
+ 0x92a5, 0x220d,
+ 0x92a6, 0x2526,
+ 0x92a7, 0x4ea2,
+ 0x92a8, 0x2534,
+ 0x92a9, 0x252a,
+ 0x92aa, 0x251f,
+ 0x92ab, 0x2531,
+ 0x92ac, 0x251c,
+ 0x92ad, 0x4ea3,
+ 0x92ae, 0x1d81,
+ 0x92af, 0x4ea4,
+ 0x92b1, 0x2525,
+ 0x92b2, 0x4ea6,
+ 0x92b7, 0x21cd,
+ 0x92b8, 0x4eab,
+ 0x92b9, 0x21da,
+ 0x92ba, 0x4eac,
+ 0x92bb, 0x2172,
+ 0x92bc, 0x253e,
+ 0x92bd, 0x4ead,
+ 0x92c1, 0x204f,
+ 0x92c2, 0x4eb1,
+ 0x92c3, 0x2543,
+ 0x92c4, 0x4eb2,
+ 0x92c5, 0x21d7,
+ 0x92c6, 0x4eb3,
+ 0x92c7, 0x1e3c,
+ 0x92c8, 0x1d82,
+ 0x92c9, 0x4eb4,
+ 0x92cc, 0x2529,
+ 0x92cd, 0x4eb7,
+ 0x92cf, 0x2521,
+ 0x92d0, 0x4eb9,
+ 0x92d2, 0x1eff,
+ 0x92d3, 0x4ebb,
+ 0x92dd, 0x253f,
+ 0x92de, 0x4ec5,
+ 0x92df, 0x2544,
+ 0x92e0, 0x4ec6,
+ 0x92e3, 0x2523,
+ 0x92e4, 0x1e90,
+ 0x92e5, 0x253a,
+ 0x92e6, 0x2545,
+ 0x92e7, 0x4ec9,
+ 0x92e8, 0x253d,
+ 0x92e9, 0x4eca,
+ 0x92ea, 0x20c1,
+ 0x92eb, 0x4ecb,
+ 0x92ed, 0x2103,
+ 0x92ee, 0x2520,
+ 0x92ef, 0x253c,
+ 0x92f0, 0x253b,
+ 0x92f1, 0x2538,
+ 0x92f2, 0x4ecd,
+ 0x92f6, 0x2540,
+ 0x92f7, 0x4ed1,
+ 0x92f8, 0x1fcd,
+ 0x92f9, 0x4ed2,
+ 0x92fc, 0x1f18,
+ 0x92fd, 0x4ed5,
+ 0x9300, 0x4ed8,
+ 0x9301, 0x254b,
+ 0x9302, 0x4ed9,
+ 0x9306, 0x2547,
+ 0x9307, 0x254f,
+ 0x9309, 0x4edd,
+ 0x9310, 0x22b0,
+ 0x9311, 0x4ee4,
+ 0x9312, 0x2546,
+ 0x9313, 0x4ee5,
+ 0x9315, 0x254c,
+ 0x9316, 0x4ee7,
+ 0x9318, 0x1e9a,
+ 0x9319, 0x2552,
+ 0x931a, 0x2530,
+ 0x931b, 0x2549,
+ 0x931c, 0x4ee9,
+ 0x931f, 0x2551,
+ 0x9320, 0x1eca,
+ 0x9321, 0x4eec,
+ 0x9322, 0x20d2,
+ 0x9323, 0x4eed,
+ 0x9326, 0x1fb8,
+ 0x9327, 0x4ef0,
+ 0x9328, 0x2079,
+ 0x9329, 0x4ef1,
+ 0x932b, 0x21ab,
+ 0x932c, 0x4ef3,
+ 0x932e, 0x254d,
+ 0x932f, 0x1ea5,
+ 0x9330, 0x4ef5,
+ 0x9332, 0x204c,
+ 0x9333, 0x2080,
+ 0x9334, 0x4ef7,
+ 0x9336, 0x266d,
+ 0x9337, 0x4ef9,
+ 0x9338, 0x2537,
+ 0x9339, 0x4efa,
+ 0x933e, 0x1d83,
+ 0x933f, 0x4eff,
+ 0x9340, 0x254a,
+ 0x9341, 0x21b8,
+ 0x9342, 0x4f00,
+ 0x9343, 0x254e,
+ 0x9344, 0x4f01,
+ 0x9346, 0x24fc,
+ 0x9347, 0x2554,
+ 0x9348, 0x4f03,
+ 0x934b, 0x1f3c,
+ 0x934c, 0x4f06,
+ 0x934d, 0x1ed5,
+ 0x934e, 0x4f07,
+ 0x9354, 0x2556,
+ 0x9355, 0x4f0d,
+ 0x9358, 0x2268,
+ 0x9359, 0x4f10,
+ 0x935b, 0x1ed6,
+ 0x935c, 0x4f12,
+ 0x9364, 0x2557,
+ 0x9365, 0x2553,
+ 0x9366, 0x4f1a,
+ 0x9369, 0x2548,
+ 0x936a, 0x1d84,
+ 0x936b, 0x4f1d,
+ 0x936c, 0x20dc,
+ 0x936d, 0x4f1e,
+ 0x9370, 0x2559,
+ 0x9371, 0x4f21,
+ 0x9375, 0x1f97,
+ 0x9376, 0x2555,
+ 0x9377, 0x4f25,
+ 0x937a, 0x227d,
+ 0x937b, 0x4f28,
+ 0x937e, 0x257e,
+ 0x937f, 0x4f2b,
+ 0x9382, 0x207c,
+ 0x9383, 0x4f2e,
+ 0x9384, 0x255a,
+ 0x9385, 0x4f2f,
+ 0x9387, 0x255e,
+ 0x9388, 0x4f31,
+ 0x938a, 0x1e34,
+ 0x938b, 0x4f33,
+ 0x938f, 0x1d86,
+ 0x9390, 0x4f37,
+ 0x9396, 0x215e,
+ 0x9397, 0x4f3d,
+ 0x9398, 0x2560,
+ 0x9399, 0x4f3e,
+ 0x93a2, 0x21a2,
+ 0x93a3, 0x2354,
+ 0x93a4, 0x4f47,
+ 0x93a6, 0x2563,
+ 0x93a7, 0x2527,
+ 0x93a8, 0x4f49,
+ 0x93a9, 0x252e,
+ 0x93aa, 0x2558,
+ 0x93ab, 0x4f4a,
+ 0x93ac, 0x1f1b,
+ 0x93ad, 0x4f4b,
+ 0x93ae, 0x2283,
+ 0x93af, 0x4f4c,
+ 0x93b0, 0x2564,
+ 0x93b1, 0x4f4d,
+ 0x93b3, 0x20a0,
+ 0x93b4, 0x4f4f,
+ 0x93b5, 0x2565,
+ 0x93b6, 0x4f50,
+ 0x93b8, 0x2561,
+ 0x93b9, 0x4f52,
+ 0x93bf, 0x2562,
+ 0x93c0, 0x4f58,
+ 0x93c3, 0x256c,
+ 0x93c4, 0x4f5b,
+ 0x93c7, 0x256d,
+ 0x93c8, 0x2020,
+ 0x93c9, 0x4f5e,
+ 0x93ca, 0x1d85,
+ 0x93cb, 0x4f5f,
+ 0x93cc, 0x255f,
+ 0x93cd, 0x256a,
+ 0x93ce, 0x4f60,
+ 0x93d1, 0x256e,
+ 0x93d2, 0x4f63,
+ 0x93d6, 0x1e01,
+ 0x93d7, 0x2539,
+ 0x93d8, 0x255c,
+ 0x93d9, 0x4f67,
+ 0x93dc, 0x2568,
+ 0x93de, 0x256b,
+ 0x93df, 0x1e6f,
+ 0x93e0, 0x4f6a,
+ 0x93e1, 0x1fc4,
+ 0x93e2, 0x2567,
+ 0x93e3, 0x4f6b,
+ 0x93e4, 0x255b,
+ 0x93e5, 0x4f6c,
+ 0x93e8, 0x261d,
+ 0x93e9, 0x4f6f,
+ 0x93f5, 0x252b,
+ 0x93f6, 0x4f7b,
+ 0x93f7, 0x2571,
+ 0x93f8, 0x4f7c,
+ 0x93f9, 0x2577,
+ 0x93fa, 0x4f7d,
+ 0x9400, 0x4f83,
+ 0x9403, 0x2522,
+ 0x9404, 0x4f86,
+ 0x940b, 0x2533,
+ 0x940c, 0x4f8d,
+ 0x9410, 0x202a,
+ 0x9411, 0x4f91,
+ 0x9412, 0x2536,
+ 0x9413, 0x2573,
+ 0x9414, 0x256f,
+ 0x9415, 0x4f92,
+ 0x9418, 0x2293,
+ 0x9419, 0x2578,
+ 0x941a, 0x4f95,
+ 0x941d, 0x2570,
+ 0x941e, 0x4f98,
+ 0x9420, 0x2575,
+ 0x9421, 0x4f9a,
+ 0x9426, 0x2541,
+ 0x9428, 0x255d,
+ 0x9429, 0x4f9f,
+ 0x942e, 0x201a,
+ 0x942f, 0x4fa4,
+ 0x9432, 0x257a,
+ 0x9433, 0x2006,
+ 0x9434, 0x4fa7,
+ 0x9435, 0x2177,
+ 0x9436, 0x4fa8,
+ 0x9438, 0x251b,
+ 0x9439, 0x4faa,
+ 0x943a, 0x2524,
+ 0x943b, 0x4fab,
+ 0x943e, 0x1d87,
+ 0x943f, 0x257b,
+ 0x9440, 0x4fae,
+ 0x9444, 0x22a3,
+ 0x9445, 0x4fb2,
+ 0x944a, 0x2579,
+ 0x944b, 0x4fb7,
+ 0x944c, 0x2566,
+ 0x944d, 0x4fb8,
+ 0x9452, 0x1f93,
+ 0x9453, 0x4fbd,
+ 0x9454, 0x257c,
+ 0x9455, 0x4fbe,
+ 0x9460, 0x2514,
+ 0x9461, 0x4fc9,
+ 0x9463, 0x257d,
+ 0x9464, 0x4fcb,
+ 0x9465, 0x2572,
+ 0x9466, 0x4fcc,
+ 0x946b, 0x1d88,
+ 0x946c, 0x4fd1,
+ 0x946d, 0x2574,
+ 0x946e, 0x4fd2,
+ 0x9470, 0x224e,
+ 0x9471, 0x4fd4,
+ 0x9472, 0x21c6,
+ 0x9473, 0x4fd5,
+ 0x9477, 0x209f,
+ 0x9478, 0x4fd9,
+ 0x9479, 0x2576,
+ 0x947a, 0x4fda,
+ 0x947c, 0x2064,
+ 0x947d, 0x22bf,
+ 0x947e, 0x261c,
+ 0x947f, 0x225e,
+ 0x9480, 0x4fdc,
+ 0x9485, 0x1a8e,
+ 0x9488, 0x118c,
+ 0x9489, 0x05e3,
+ 0x948a, 0x1a92,
+ 0x948b, 0x1a91,
+ 0x948c, 0x1a93,
+ 0x948e, 0x0c22,
+ 0x948f, 0x1a95,
+ 0x9491, 0x4fe1,
+ 0x9492, 0x064d,
+ 0x9493, 0x05d7,
+ 0x9494, 0x1a97,
+ 0x9495, 0x1a99,
+ 0x9496, 0x4fe2,
+ 0x9497, 0x1a98,
+ 0x9498, 0x4fe3,
+ 0x9499, 0x06c1,
+ 0x949a, 0x1a9a,
+ 0x949d, 0x061a,
+ 0x949e, 0x04d3,
+ 0x949f, 0x11d2,
+ 0x94a0, 0x0b29,
+ 0x94a1, 0x041e,
+ 0x94a2, 0x06d1,
+ 0x94a3, 0x1a9d,
+ 0x94a5, 0x1102,
+ 0x94a6, 0x0c52,
+ 0x94a7, 0x092a,
+ 0x94a8, 0x0ee8,
+ 0x94a9, 0x070c,
+ 0x94aa, 0x1aa0,
+ 0x94ab, 0x1a9f,
+ 0x94ac, 0x1aa2,
+ 0x94ad, 0x1aa1,
+ 0x94ae, 0x0b66,
+ 0x94af, 0x1aa3,
+ 0x94b1, 0x0c2b,
+ 0x94b2, 0x1aa5,
+ 0x94b3, 0x0c2c,
+ 0x94b4, 0x1aa6,
+ 0x94b5, 0x046e,
+ 0x94b6, 0x1aa7,
+ 0x94bb, 0x1247,
+ 0x94bc, 0x1aac,
+ 0x94be, 0x084b,
+ 0x94bf, 0x1aae,
+ 0x94c0, 0x10b0,
+ 0x94c1, 0x0e4d,
+ 0x94c2, 0x0473,
+ 0x94c3, 0x0a2e,
+ 0x94c4, 0x1aaf,
+ 0x94c5, 0x0c23,
+ 0x94c6, 0x0ab2,
+ 0x94c7, 0x4fe4,
+ 0x94c8, 0x1ab0,
+ 0x94cf, 0x4fe5,
+ 0x94d0, 0x1ab7,
+ 0x94d3, 0x4fe6,
+ 0x94d5, 0x1aba,
+ 0x94d8, 0x1abe,
+ 0x94d9, 0x1abd,
+ 0x94da, 0x4fe8,
+ 0x94db, 0x1abf,
+ 0x94dc, 0x0e5e,
+ 0x94dd, 0x0a68,
+ 0x94de, 0x1ac0,
+ 0x94e1, 0x1142,
+ 0x94e2, 0x1ac3,
+ 0x94e3, 0x0f20,
+ 0x94e4, 0x1ac4,
+ 0x94e6, 0x4fe9,
+ 0x94e7, 0x1ac6,
+ 0x94e9, 0x1ac9,
+ 0x94ea, 0x1ac8,
+ 0x94eb, 0x1aca,
+ 0x94ec, 0x06f0,
+ 0x94ed, 0x0aff,
+ 0x94ee, 0x1acb,
+ 0x94f0, 0x0893,
+ 0x94f1, 0x1046,
+ 0x94f2, 0x04c0,
+ 0x94f3, 0x1acd,
+ 0x94f6, 0x107f,
+ 0x94f7, 0x1ad0,
+ 0x94f8, 0x11fc,
+ 0x94f9, 0x1ad1,
+ 0x94fa, 0x0beb,
+ 0x94fb, 0x4fea,
+ 0x94fc, 0x1ad2,
+ 0x94fe, 0x09fd,
+ 0x94ff, 0x1ad4,
+ 0x9500, 0x0f67,
+ 0x9501, 0x0ded,
+ 0x9502, 0x1ad6,
+ 0x9503, 0x1ad5,
+ 0x9504, 0x051f,
+ 0x9505, 0x0751,
+ 0x9506, 0x1ad7,
+ 0x9508, 0x0fad,
+ 0x9509, 0x1ad9,
+ 0x950b, 0x0683,
+ 0x950c, 0x0f8a,
+ 0x950d, 0x1adb,
+ 0x9510, 0x0ccc,
+ 0x9511, 0x0e33,
+ 0x9512, 0x1ade,
+ 0x9517, 0x1181,
+ 0x9518, 0x1ae3,
+ 0x9519, 0x0570,
+ 0x951a, 0x0aaf,
+ 0x951b, 0x1ae4,
+ 0x951c, 0x4feb,
+ 0x951d, 0x1ae5,
+ 0x9520, 0x4fec,
+ 0x9521, 0x0f0c,
+ 0x9522, 0x1ae8,
+ 0x9523, 0x0a87,
+ 0x9524, 0x053b,
+ 0x9525, 0x1213,
+ 0x9526, 0x08c6,
+ 0x9527, 0x4fed,
+ 0x9528, 0x0f34,
+ 0x9529, 0x1aeb,
+ 0x952a, 0x1ae9,
+ 0x952c, 0x1aec,
+ 0x952d, 0x05e6,
+ 0x952e, 0x086f,
+ 0x952f, 0x0911,
+ 0x9530, 0x0ad1,
+ 0x9531, 0x1aed,
+ 0x9533, 0x4fee,
+ 0x9534, 0x1aef,
+ 0x9535, 0x1af7,
+ 0x9536, 0x1af0,
+ 0x9539, 0x0c3f,
+ 0x953a, 0x1b19,
+ 0x953b, 0x060c,
+ 0x953c, 0x1af3,
+ 0x953d, 0x4fef,
+ 0x953e, 0x1af4,
+ 0x9540, 0x0605,
+ 0x9541, 0x0ac3,
+ 0x9542, 0x1af6,
+ 0x9543, 0x4ff0,
+ 0x9544, 0x1af8,
+ 0x9547, 0x1193,
+ 0x9548, 0x4ff1,
+ 0x9549, 0x1afb,
+ 0x954a, 0x0b5a,
+ 0x954b, 0x4ff2,
+ 0x954c, 0x1afc,
+ 0x954d, 0x0b5b,
+ 0x954e, 0x1afd,
+ 0x9550, 0x06df,
+ 0x9551, 0x0402,
+ 0x9552, 0x1aff,
+ 0x9555, 0x4ff3,
+ 0x9556, 0x1b02,
+ 0x955a, 0x4ff4,
+ 0x955b, 0x1b06,
+ 0x955c, 0x08e4,
+ 0x955d, 0x1b09,
+ 0x955e, 0x1b07,
+ 0x9560, 0x4ff5,
+ 0x9561, 0x1b0a,
+ 0x9563, 0x0a16,
+ 0x9564, 0x1b0c,
+ 0x956d, 0x09c3,
+ 0x956e, 0x4ff6,
+ 0x956f, 0x1b15,
+ 0x9570, 0x09f6,
+ 0x9571, 0x1b16,
+ 0x9574, 0x4ff7,
+ 0x9576, 0x0f4f,
+ 0x9577, 0x1e75,
+ 0x9578, 0x4ff9,
+ 0x957f, 0x04c9,
+ 0x9580, 0x207d,
+ 0x9581, 0x5000,
+ 0x9582, 0x23bf,
+ 0x9583, 0x2113,
+ 0x9584, 0x5001,
+ 0x9586, 0x23c0,
+ 0x9587, 0x5003,
+ 0x9589, 0x1e45,
+ 0x958a, 0x5005,
+ 0x958b, 0x1fd8,
+ 0x958c, 0x23c4,
+ 0x958d, 0x5006,
+ 0x958e, 0x23c2,
+ 0x958f, 0x2104,
+ 0x9590, 0x5007,
+ 0x9591, 0x21bd,
+ 0x9592, 0x5008,
+ 0x9593, 0x1f87,
+ 0x9594, 0x23c3,
+ 0x9595, 0x5009,
+ 0x9598, 0x2269,
+ 0x9599, 0x500c,
+ 0x95a1, 0x1f43,
+ 0x95a2, 0x5014,
+ 0x95a3, 0x1f1e,
+ 0x95a4, 0x2679,
+ 0x95a5, 0x1eeb,
+ 0x95a6, 0x5015,
+ 0x95a8, 0x1f35,
+ 0x95a9, 0x208a,
+ 0x95aa, 0x5017,
+ 0x95ab, 0x23c7,
+ 0x95ac, 0x23c9,
+ 0x95ad, 0x23c6,
+ 0x95ae, 0x5018,
+ 0x95b2, 0x224f,
+ 0x95b3, 0x501c,
+ 0x95b6, 0x23cb,
+ 0x95b7, 0x501f,
+ 0x95b9, 0x21f3,
+ 0x95ba, 0x5021,
+ 0x95bb, 0x21f7,
+ 0x95bc, 0x23cf,
+ 0x95bd, 0x23ce,
+ 0x95be, 0x23ca,
+ 0x95bf, 0x23cd,
+ 0x95c0, 0x5022,
+ 0x95c3, 0x23d0,
+ 0x95c4, 0x5025,
+ 0x95c6, 0x266c,
+ 0x95c7, 0x5027,
+ 0x95c8, 0x23c1,
+ 0x95c9, 0x5028,
+ 0x95ca, 0x1fee,
+ 0x95cb, 0x23d1,
+ 0x95cc, 0x1ff8,
+ 0x95cd, 0x5029,
+ 0x95d0, 0x23d3,
+ 0x95d1, 0x502c,
+ 0x95d4, 0x23d2,
+ 0x95d5, 0x23d4,
+ 0x95d6, 0x1e98,
+ 0x95d7, 0x502f,
+ 0x95dc, 0x1f2c,
+ 0x95dd, 0x5034,
+ 0x95de, 0x23d5,
+ 0x95df, 0x5035,
+ 0x95e1, 0x1e71,
+ 0x95e2, 0x2691,
+ 0x95e3, 0x5037,
+ 0x95e5, 0x23c5,
+ 0x95e6, 0x5039,
+ 0x95e8, 0x0aca,
+ 0x95e9, 0x1685,
+ 0x95ea, 0x0cfa,
+ 0x95eb, 0x1686,
+ 0x95ec, 0x503b,
+ 0x95ed, 0x043e,
+ 0x95ee, 0x0ed9,
+ 0x95ef, 0x0536,
+ 0x95f0, 0x0ccd,
+ 0x95f1, 0x1687,
+ 0x95f2, 0x0f3d,
+ 0x95f3, 0x1688,
+ 0x95f4, 0x0857,
+ 0x95f5, 0x1689,
+ 0x95f7, 0x0acb,
+ 0x95f8, 0x1143,
+ 0x95f9, 0x0b39,
+ 0x95fa, 0x0744,
+ 0x95fb, 0x0ed4,
+ 0x95fc, 0x168b,
+ 0x95fd, 0x0afb,
+ 0x95fe, 0x168c,
+ 0x95ff, 0x503c,
+ 0x9600, 0x0644,
+ 0x9601, 0x06ee,
+ 0x9602, 0x0789,
+ 0x9603, 0x168d,
+ 0x9605, 0x1107,
+ 0x9606, 0x168f,
+ 0x9607, 0x503d,
+ 0x9608, 0x1690,
+ 0x9609, 0x0ff4,
+ 0x960a, 0x1691,
+ 0x960e, 0x0fff,
+ 0x960f, 0x1695,
+ 0x9610, 0x04c2,
+ 0x9611, 0x09a6,
+ 0x9612, 0x1696,
+ 0x9613, 0x503e,
+ 0x9614, 0x0996,
+ 0x9615, 0x1697,
+ 0x9618, 0x503f,
+ 0x9619, 0x169a,
+ 0x961b, 0x5040,
+ 0x961c, 0x06b2,
+ 0x961d, 0x1354,
+ 0x961e, 0x5041,
+ 0x961f, 0x0612,
+ 0x9620, 0x5042,
+ 0x9621, 0x1356,
+ 0x9622, 0x1355,
+ 0x9623, 0x5043,
+ 0x962a, 0x1358,
+ 0x962b, 0x504a,
+ 0x962e, 0x0cc9,
+ 0x962f, 0x504d,
+ 0x9631, 0x1357,
+ 0x9632, 0x065d,
+ 0x9633, 0x101d,
+ 0x9634, 0x107c,
+ 0x9635, 0x1194,
+ 0x9636, 0x08a8,
+ 0x9637, 0x504f,
+ 0x963b, 0x1245,
+ 0x963c, 0x135a,
+ 0x963d, 0x1359,
+ 0x963e, 0x5053,
+ 0x963f, 0x03ad,
+ 0x9640, 0x0e84,
+ 0x9641, 0x5054,
+ 0x9642, 0x135b,
+ 0x9643, 0x5055,
+ 0x9644, 0x06b8,
+ 0x9645, 0x083d,
+ 0x9646, 0x0a64,
+ 0x9647, 0x0a4b,
+ 0x9648, 0x04e7,
+ 0x9649, 0x135c,
+ 0x964a, 0x5056,
+ 0x964b, 0x0a51,
+ 0x964c, 0x0b13,
+ 0x964d, 0x0886,
+ 0x964e, 0x5057,
+ 0x9650, 0x0f4b,
+ 0x9651, 0x5059,
+ 0x9654, 0x135d,
+ 0x9655, 0x0cfb,
+ 0x9656, 0x505c,
+ 0x9658, 0x231a,
+ 0x9659, 0x505e,
+ 0x965b, 0x0446,
+ 0x965c, 0x5060,
+ 0x965d, 0x2114,
+ 0x965e, 0x5061,
+ 0x965f, 0x135e,
+ 0x9660, 0x5062,
+ 0x9661, 0x05f7,
+ 0x9662, 0x10fd,
+ 0x9663, 0x2284,
+ 0x9664, 0x0522,
+ 0x9665, 0x5063,
+ 0x9667, 0x135f,
+ 0x9668, 0x110c,
+ 0x9669, 0x0f42,
+ 0x966a, 0x0ba4,
+ 0x966b, 0x5065,
+ 0x966c, 0x1360,
+ 0x966d, 0x5066,
+ 0x9670, 0x221c,
+ 0x9671, 0x5069,
+ 0x9672, 0x1361,
+ 0x9673, 0x1e7e,
+ 0x9674, 0x1362,
+ 0x9675, 0x0a33,
+ 0x9676, 0x0e28,
+ 0x9677, 0x0f4a,
+ 0x9678, 0x204d,
+ 0x9679, 0x506a,
+ 0x967d, 0x2201,
+ 0x967e, 0x506e,
+ 0x9685, 0x10cc,
+ 0x9686, 0x0a48,
+ 0x9687, 0x5075,
+ 0x9688, 0x1363,
+ 0x9689, 0x5076,
+ 0x968a, 0x1ed9,
+ 0x968b, 0x0dda,
+ 0x968c, 0x5077,
+ 0x968d, 0x1364,
+ 0x968e, 0x1fb2,
+ 0x968f, 0x0ddb,
+ 0x9690, 0x1085,
+ 0x9691, 0x5078,
+ 0x9694, 0x06ef,
+ 0x9695, 0x2252,
+ 0x9696, 0x507b,
+ 0x9697, 0x1365,
+ 0x9698, 0x03ba,
+ 0x9699, 0x0f23,
+ 0x969a, 0x507c,
+ 0x969b, 0x1f79,
+ 0x969c, 0x1170,
+ 0x969d, 0x507d,
+ 0x96a7, 0x0de2,
+ 0x96a8, 0x2157,
+ 0x96a9, 0x5087,
+ 0x96aa, 0x21bf,
+ 0x96ab, 0x5088,
+ 0x96b0, 0x1366,
+ 0x96b1, 0x221f,
+ 0x96b2, 0x508d,
+ 0x96b3, 0x1684,
+ 0x96b4, 0x203d,
+ 0x96b5, 0x508e,
+ 0x96b6, 0x09ee,
+ 0x96b7, 0x508f,
+ 0x96b8, 0x2015,
+ 0x96b9, 0x1d79,
+ 0x96ba, 0x5090,
+ 0x96bb, 0x26a5,
+ 0x96bc, 0x1d7a,
+ 0x96be, 0x0b34,
+ 0x96bf, 0x5091,
+ 0x96c0, 0x0c93,
+ 0x96c1, 0x100c,
+ 0x96c2, 0x5092,
+ 0x96c4, 0x0fa6,
+ 0x96c5, 0x0fee,
+ 0x96c6, 0x0822,
+ 0x96c7, 0x0726,
+ 0x96c8, 0x5094,
+ 0x96c9, 0x1b1c,
+ 0x96ca, 0x5095,
+ 0x96cc, 0x0549,
+ 0x96cd, 0x109f,
+ 0x96ce, 0x1d7c,
+ 0x96cf, 0x0520,
+ 0x96d0, 0x5097,
+ 0x96d2, 0x1d7d,
+ 0x96d3, 0x5099,
+ 0x96d5, 0x05d2,
+ 0x96d6, 0x2156,
+ 0x96d7, 0x509b,
+ 0x96d9, 0x2144,
+ 0x96da, 0x509d,
+ 0x96db, 0x1e91,
+ 0x96dc, 0x2257,
+ 0x96dd, 0x509e,
+ 0x96e0, 0x1d7f,
+ 0x96e1, 0x50a1,
+ 0x96e2, 0x200a,
+ 0x96e3, 0x2092,
+ 0x96e4, 0x50a2,
+ 0x96e8, 0x10cf,
+ 0x96e9, 0x1d61,
+ 0x96ea, 0x0fd2,
+ 0x96eb, 0x50a6,
+ 0x96ef, 0x1d63,
+ 0x96f0, 0x50aa,
+ 0x96f2, 0x2250,
+ 0x96f3, 0x1d62,
+ 0x96f4, 0x50ac,
+ 0x96f6, 0x0a2c,
+ 0x96f7, 0x09c2,
+ 0x96f8, 0x50ae,
+ 0x96f9, 0x040b,
+ 0x96fa, 0x50af,
+ 0x96fb, 0x1ec3,
+ 0x96fc, 0x50b0,
+ 0x96fe, 0x0efc,
+ 0x96ff, 0x50b2,
+ 0x9700, 0x0fb3,
+ 0x9701, 0x1d65,
+ 0x9702, 0x50b3,
+ 0x9704, 0x0f63,
+ 0x9705, 0x50b5,
+ 0x9706, 0x1d64,
+ 0x9707, 0x1191,
+ 0x9708, 0x1d66,
+ 0x9709, 0x0abe,
+ 0x970a, 0x50b6,
+ 0x970d, 0x0809,
+ 0x970e, 0x1d68,
+ 0x970f, 0x1d67,
+ 0x9710, 0x50b9,
+ 0x9713, 0x0b41,
+ 0x9714, 0x50bc,
+ 0x9716, 0x0a21,
+ 0x9717, 0x50be,
+ 0x971c, 0x0d9f,
+ 0x971d, 0x50c3,
+ 0x971e, 0x0f29,
+ 0x971f, 0x50c4,
+ 0x9727, 0x21a8,
+ 0x9728, 0x50cc,
+ 0x972a, 0x1d69,
+ 0x972b, 0x50ce,
+ 0x972d, 0x1d6a,
+ 0x972e, 0x50d0,
+ 0x9730, 0x1d6b,
+ 0x9731, 0x50d2,
+ 0x9732, 0x0a5d,
+ 0x9733, 0x50d3,
+ 0x9738, 0x03df,
+ 0x9739, 0x0bba,
+ 0x973a, 0x50d8,
+ 0x973d, 0x260d,
+ 0x973e, 0x1d6c,
+ 0x973f, 0x50db,
+ 0x9742, 0x260c,
+ 0x9743, 0x50de,
+ 0x9744, 0x260e,
+ 0x9745, 0x50df,
+ 0x9748, 0x2032,
+ 0x9749, 0x50e2,
+ 0x9752, 0x0c5d,
+ 0x9753, 0x1d60,
+ 0x9754, 0x50eb,
+ 0x9756, 0x08e7,
+ 0x9757, 0x50ed,
+ 0x9759, 0x08e1,
+ 0x975a, 0x260b,
+ 0x975b, 0x05c6,
+ 0x975c, 0x50ef,
+ 0x975e, 0x0664,
+ 0x975f, 0x50f1,
+ 0x9760, 0x094c,
+ 0x9761, 0x0ad7,
+ 0x9762, 0x0aeb,
+ 0x9763, 0x50f2,
+ 0x9765, 0x1282,
+ 0x9766, 0x50f4,
+ 0x9768, 0x22c3,
+ 0x9769, 0x06ea,
+ 0x976a, 0x50f6,
+ 0x9773, 0x08ca,
+ 0x9774, 0x0fce,
+ 0x9775, 0x50ff,
+ 0x9776, 0x03db,
+ 0x9777, 0x5100,
+ 0x977c, 0x1dc8,
+ 0x977d, 0x5105,
+ 0x9785, 0x1dc9,
+ 0x9786, 0x510d,
+ 0x978b, 0x0f77,
+ 0x978c, 0x5112,
+ 0x978d, 0x03bb,
+ 0x978e, 0x5113,
+ 0x978f, 0x1f23,
+ 0x9790, 0x5114,
+ 0x9791, 0x1dca,
+ 0x9793, 0x5115,
+ 0x9794, 0x1dcc,
+ 0x9795, 0x5116,
+ 0x9798, 0x0c47,
+ 0x9799, 0x5119,
+ 0x97a0, 0x08fe,
+ 0x97a1, 0x5120,
+ 0x97a3, 0x1dcf,
+ 0x97a4, 0x5122,
+ 0x97a6, 0x2695,
+ 0x97a7, 0x5124,
+ 0x97ab, 0x1dce,
+ 0x97ac, 0x5128,
+ 0x97ad, 0x0447,
+ 0x97ae, 0x5129,
+ 0x97af, 0x1dcd,
+ 0x97b0, 0x512a,
+ 0x97b2, 0x1dd0,
+ 0x97b3, 0x512c,
+ 0x97b4, 0x1dd1,
+ 0x97b5, 0x512d,
+ 0x97bd, 0x265e,
+ 0x97be, 0x5135,
+ 0x97c3, 0x265d,
+ 0x97c4, 0x513a,
+ 0x97c6, 0x2692,
+ 0x97c7, 0x513c,
+ 0x97c9, 0x265f,
+ 0x97ca, 0x513e,
+ 0x97cb, 0x218d,
+ 0x97cc, 0x20fd,
+ 0x97cd, 0x513f,
+ 0x97d3, 0x1f40,
+ 0x97d4, 0x5145,
+ 0x97d9, 0x2465,
+ 0x97da, 0x514a,
+ 0x97dc, 0x2467,
+ 0x97dd, 0x514c,
+ 0x97de, 0x2466,
+ 0x97df, 0x514d,
+ 0x97e6, 0x0eb3,
+ 0x97e7, 0x0ca8,
+ 0x97e8, 0x5154,
+ 0x97e9, 0x0762,
+ 0x97ea, 0x184e,
+ 0x97ed, 0x08f1,
+ 0x97ee, 0x5155,
+ 0x97f3, 0x107b,
+ 0x97f4, 0x515a,
+ 0x97f5, 0x1112,
+ 0x97f6, 0x0d11,
+ 0x97f7, 0x515b,
+ 0x97ff, 0x21c9,
+ 0x9800, 0x5163,
+ 0x9801, 0x2209,
+ 0x9802, 0x1ec9,
+ 0x9803, 0x20e9,
+ 0x9804, 0x5164,
+ 0x9805, 0x21ca,
+ 0x9806, 0x2146,
+ 0x9807, 0x25c5,
+ 0x9808, 0x21dc,
+ 0x9809, 0x5165,
+ 0x980a, 0x245e,
+ 0x980b, 0x5166,
+ 0x980c, 0x214f,
+ 0x980d, 0x5167,
+ 0x980e, 0x25c6,
+ 0x9810, 0x2241,
+ 0x9811, 0x218a,
+ 0x9812, 0x1e2f,
+ 0x9813, 0x1edc,
+ 0x9814, 0x5168,
+ 0x9817, 0x20bf,
+ 0x9818, 0x2034,
+ 0x9819, 0x516b,
+ 0x981c, 0x25c9,
+ 0x981d, 0x516e,
+ 0x9821, 0x25c8,
+ 0x9822, 0x5172,
+ 0x9824, 0x220e,
+ 0x9825, 0x5174,
+ 0x9826, 0x25cb,
+ 0x9827, 0x5175,
+ 0x982d, 0x217d,
+ 0x982e, 0x517b,
+ 0x9830, 0x1f7e,
+ 0x9831, 0x517d,
+ 0x9837, 0x25cc,
+ 0x9838, 0x1fc3,
+ 0x9839, 0x5183,
+ 0x983b, 0x20b9,
+ 0x983c, 0x5185,
+ 0x983d, 0x2181,
+ 0x983e, 0x5186,
+ 0x9846, 0x1fda,
+ 0x9847, 0x518e,
+ 0x984c, 0x2173,
+ 0x984d, 0x1ee1,
+ 0x984e, 0x25cd,
+ 0x984f, 0x5193,
+ 0x9853, 0x25ce,
+ 0x9854, 0x21f6,
+ 0x9855, 0x5197,
+ 0x9858, 0x224b,
+ 0x9859, 0x25d1,
+ 0x985a, 0x519a,
+ 0x985b, 0x1ec0,
+ 0x985c, 0x519b,
+ 0x985e, 0x2008,
+ 0x985f, 0x519d,
+ 0x9862, 0x25d0,
+ 0x9863, 0x51a0,
+ 0x9865, 0x25d2,
+ 0x9866, 0x51a2,
+ 0x9867, 0x1f2a,
+ 0x9868, 0x51a3,
+ 0x986b, 0x1e72,
+ 0x986c, 0x25d3,
+ 0x986d, 0x51a6,
+ 0x986f, 0x21be,
+ 0x9870, 0x25d4,
+ 0x9871, 0x2044,
+ 0x9872, 0x51a8,
+ 0x9873, 0x25cf,
+ 0x9874, 0x20f3,
+ 0x9875, 0x103a,
+ 0x9876, 0x05e4,
+ 0x9877, 0x0c67,
+ 0x9878, 0x1be0,
+ 0x9879, 0x0f5b,
+ 0x987a, 0x0da8,
+ 0x987b, 0x0fb6,
+ 0x987c, 0x1827,
+ 0x987d, 0x0e98,
+ 0x987e, 0x0724,
+ 0x987f, 0x0618,
+ 0x9880, 0x1be1,
+ 0x9881, 0x03ef,
+ 0x9882, 0x0dc1,
+ 0x9883, 0x1be2,
+ 0x9884, 0x10e7,
+ 0x9885, 0x0a54,
+ 0x9886, 0x0a35,
+ 0x9887, 0x0be3,
+ 0x9888, 0x08e0,
+ 0x9889, 0x1be3,
+ 0x988a, 0x0848,
+ 0x988b, 0x51a9,
+ 0x988c, 0x1be4,
+ 0x988e, 0x51aa,
+ 0x988f, 0x1be6,
+ 0x9890, 0x104a,
+ 0x9891, 0x0bd4,
+ 0x9892, 0x51ab,
+ 0x9893, 0x0e78,
+ 0x9894, 0x1be7,
+ 0x9895, 0x51ac,
+ 0x9896, 0x1096,
+ 0x9897, 0x0952,
+ 0x9898, 0x0e35,
+ 0x9899, 0x51ad,
+ 0x989a, 0x1be8,
+ 0x989c, 0x0ffe,
+ 0x989d, 0x062d,
+ 0x989e, 0x1bea,
+ 0x98a0, 0x05c0,
+ 0x98a1, 0x1bec,
+ 0x98a3, 0x51ae,
+ 0x98a4, 0x04c3,
+ 0x98a5, 0x1bee,
+ 0x98a7, 0x0c82,
+ 0x98a8, 0x1f00,
+ 0x98a9, 0x51af,
+ 0x98ae, 0x24cc,
+ 0x98b0, 0x51b4,
+ 0x98b1, 0x2698,
+ 0x98b2, 0x51b5,
+ 0x98b3, 0x2678,
+ 0x98b4, 0x51b6,
+ 0x98b6, 0x24ce,
+ 0x98b7, 0x51b8,
+ 0x98bc, 0x24cf,
+ 0x98bd, 0x51bd,
+ 0x98c4, 0x20b8,
+ 0x98c5, 0x51c4,
+ 0x98c6, 0x24d0,
+ 0x98c7, 0x51c5,
+ 0x98c8, 0x24d1,
+ 0x98c9, 0x51c6,
+ 0x98ce, 0x0684,
+ 0x98cf, 0x51cb,
+ 0x98d1, 0x19b7,
+ 0x98d4, 0x51cd,
+ 0x98d5, 0x19ba,
+ 0x98d6, 0x51ce,
+ 0x98d8, 0x0bcd,
+ 0x98d9, 0x19bb,
+ 0x98db, 0x1ef4,
+ 0x98dc, 0x51d0,
+ 0x98de, 0x0666,
+ 0x98df, 0x0d4a,
+ 0x98e0, 0x239b,
+ 0x98e1, 0x51d2,
+ 0x98e2, 0x267e,
+ 0x98e3, 0x51d3,
+ 0x98e7, 0x161a,
+ 0x98e8, 0x1de7,
+ 0x98e9, 0x239d,
+ 0x98ea, 0x239f,
+ 0x98ec, 0x51d7,
+ 0x98ed, 0x23a1,
+ 0x98ee, 0x51d8,
+ 0x98ef, 0x1ef1,
+ 0x98f0, 0x51d9,
+ 0x98f2, 0x221e,
+ 0x98f3, 0x51db,
+ 0x98f4, 0x23a2,
+ 0x98f5, 0x51dc,
+ 0x98fc, 0x214b,
+ 0x98fd, 0x1e36,
+ 0x98fe, 0x2135,
+ 0x98ff, 0x51e3,
+ 0x9900, 0x51e4,
+ 0x9903, 0x1fad,
+ 0x9904, 0x51e7,
+ 0x9905, 0x1e53,
+ 0x9906, 0x51e8,
+ 0x9909, 0x23a3,
+ 0x990a, 0x2203,
+ 0x990b, 0x51eb,
+ 0x990c, 0x1ee7,
+ 0x990d, 0x1de8,
+ 0x990e, 0x51ec,
+ 0x9910, 0x0494,
+ 0x9911, 0x23a4,
+ 0x9912, 0x2097,
+ 0x9913, 0x1ee4,
+ 0x9914, 0x51ee,
+ 0x9918, 0x2238,
+ 0x9919, 0x51f2,
+ 0x991b, 0x23a5,
+ 0x991c, 0x51f4,
+ 0x991e, 0x1f9a,
+ 0x991f, 0x51f6,
+ 0x9921, 0x21c3,
+ 0x9922, 0x51f8,
+ 0x9928, 0x1f2e,
+ 0x9929, 0x51fe,
+ 0x992e, 0x1de9,
+ 0x992f, 0x5203,
+ 0x9933, 0x239c,
+ 0x9934, 0x5207,
+ 0x9937, 0x23a6,
+ 0x9938, 0x520a,
+ 0x993c, 0x239e,
+ 0x993d, 0x520e,
+ 0x993e, 0x2035,
+ 0x993f, 0x23a7,
+ 0x9940, 0x520f,
+ 0x9943, 0x23a8,
+ 0x9944, 0x5212,
+ 0x9945, 0x2075,
+ 0x9946, 0x5213,
+ 0x9948, 0x23a9,
+ 0x994b, 0x1feb,
+ 0x994c, 0x23ac,
+ 0x994d, 0x5215,
+ 0x9951, 0x1f6a,
+ 0x9952, 0x20f9,
+ 0x9953, 0x5219,
+ 0x9954, 0x1deb,
+ 0x9955, 0x1dea,
+ 0x9956, 0x521a,
+ 0x9957, 0x2666,
+ 0x9958, 0x521b,
+ 0x995c, 0x2667,
+ 0x995d, 0x521f,
+ 0x995e, 0x1e6c,
+ 0x995f, 0x5220,
+ 0x9962, 0x23ad,
+ 0x9963, 0x161d,
+ 0x9964, 0x5223,
+ 0x9965, 0x0815,
+ 0x9966, 0x5224,
+ 0x9967, 0x161e,
+ 0x996d, 0x0656,
+ 0x996e, 0x1082,
+ 0x996f, 0x0875,
+ 0x9970, 0x0d65,
+ 0x9971, 0x040e,
+ 0x9972, 0x0dbc,
+ 0x9973, 0x5225,
+ 0x9974, 0x1624,
+ 0x9975, 0x063b,
+ 0x9976, 0x0c9f,
+ 0x9977, 0x1625,
+ 0x9978, 0x5226,
+ 0x997a, 0x0899,
+ 0x997b, 0x5228,
+ 0x997c, 0x0466,
+ 0x997d, 0x1626,
+ 0x997e, 0x5229,
+ 0x997f, 0x0635,
+ 0x9980, 0x1627,
+ 0x9981, 0x0b3c,
+ 0x9982, 0x522a,
+ 0x9984, 0x1628,
+ 0x9985, 0x0f47,
+ 0x9986, 0x0736,
+ 0x9987, 0x1629,
+ 0x9988, 0x098c,
+ 0x9989, 0x522c,
+ 0x998a, 0x162a,
+ 0x998b, 0x04bd,
+ 0x998c, 0x522d,
+ 0x998d, 0x162b,
+ 0x998e, 0x522e,
+ 0x998f, 0x0a3c,
+ 0x9990, 0x162c,
+ 0x9992, 0x0a9f,
+ 0x9993, 0x162e,
+ 0x9996, 0x0d6e,
+ 0x9997, 0x126e,
+ 0x9998, 0x12f9,
+ 0x9999, 0x0f50,
+ 0x999a, 0x522f,
+ 0x99a5, 0x1b2b,
+ 0x99a6, 0x523a,
+ 0x99a8, 0x13de,
+ 0x99a9, 0x523c,
+ 0x99ac, 0x206d,
+ 0x99ad, 0x2242,
+ 0x99ae, 0x1f02,
+ 0x99af, 0x523f,
+ 0x99b1, 0x2183,
+ 0x99b2, 0x5241,
+ 0x99b3, 0x1e85,
+ 0x99b4, 0x21e9,
+ 0x99b5, 0x5242,
+ 0x99c1, 0x1e57,
+ 0x99c2, 0x524e,
+ 0x99d0, 0x22a5,
+ 0x99d1, 0x2407,
+ 0x99d2, 0x1fca,
+ 0x99d3, 0x525c,
+ 0x99d4, 0x2402,
+ 0x99d5, 0x1f82,
+ 0x99d6, 0x525d,
+ 0x99d8, 0x2408,
+ 0x99d9, 0x2404,
+ 0x99da, 0x525f,
+ 0x99db, 0x2131,
+ 0x99dc, 0x5260,
+ 0x99dd, 0x2184,
+ 0x99de, 0x5261,
+ 0x99df, 0x2403,
+ 0x99e0, 0x5262,
+ 0x99e1, 0x206e,
+ 0x99e2, 0x240b,
+ 0x99e3, 0x5263,
+ 0x99ed, 0x1f3f,
+ 0x99ee, 0x526d,
+ 0x99f1, 0x2067,
+ 0x99f2, 0x5270,
+ 0x99ff, 0x1fd7,
+ 0x9a00, 0x527d,
+ 0x9a01, 0x1e83,
+ 0x9a02, 0x527e,
+ 0x9a05, 0x240f,
+ 0x9a06, 0x5281,
+ 0x9a0d, 0x240e,
+ 0x9a0e, 0x20c7,
+ 0x9a0f, 0x240d,
+ 0x9a10, 0x5288,
+ 0x9a16, 0x2412,
+ 0x9a17, 0x528e,
+ 0x9a19, 0x20b7,
+ 0x9a1a, 0x5290,
+ 0x9a2b, 0x23f0,
+ 0x9a2c, 0x52a1,
+ 0x9a2d, 0x2411,
+ 0x9a2e, 0x2414,
+ 0x9a2f, 0x52a2,
+ 0x9a30, 0x2170,
+ 0x9a31, 0x52a3,
+ 0x9a36, 0x2405,
+ 0x9a37, 0x210c,
+ 0x9a38, 0x2415,
+ 0x9a39, 0x52a8,
+ 0x9a3e, 0x2066,
+ 0x9a3f, 0x52ad,
+ 0x9a40, 0x2352,
+ 0x9a41, 0x2413,
+ 0x9a42, 0x2410,
+ 0x9a43, 0x2416,
+ 0x9a45, 0x20f1,
+ 0x9a46, 0x52ae,
+ 0x9a4a, 0x240a,
+ 0x9a4b, 0x52b2,
+ 0x9a4d, 0x2409,
+ 0x9a4e, 0x52b4,
+ 0x9a4f, 0x2418,
+ 0x9a50, 0x52b5,
+ 0x9a55, 0x1fa7,
+ 0x9a56, 0x52ba,
+ 0x9a57, 0x21fc,
+ 0x9a58, 0x52bb,
+ 0x9a5a, 0x1fc1,
+ 0x9a5b, 0x2406,
+ 0x9a5c, 0x52bd,
+ 0x9a5f, 0x229c,
+ 0x9a60, 0x52c0,
+ 0x9a62, 0x204e,
+ 0x9a63, 0x52c2,
+ 0x9a64, 0x241a,
+ 0x9a65, 0x2419,
+ 0x9a66, 0x52c3,
+ 0x9a6a, 0x240c,
+ 0x9a6b, 0x52c7,
+ 0x9a6c, 0x0a94,
+ 0x9a6d, 0x10e9,
+ 0x9a6e, 0x0e85,
+ 0x9a6f, 0x0fda,
+ 0x9a70, 0x0500,
+ 0x9a71, 0x0c7a,
+ 0x9a72, 0x52c8,
+ 0x9a73, 0x047c,
+ 0x9a74, 0x0a66,
+ 0x9a75, 0x17ba,
+ 0x9a76, 0x0d52,
+ 0x9a77, 0x17bb,
+ 0x9a79, 0x0903,
+ 0x9a7a, 0x17bd,
+ 0x9a7b, 0x1201,
+ 0x9a7c, 0x0e86,
+ 0x9a7d, 0x17bf,
+ 0x9a7e, 0x0850,
+ 0x9a7f, 0x17be,
+ 0x9a80, 0x17c0,
+ 0x9a82, 0x0a95,
+ 0x9a83, 0x52c9,
+ 0x9a84, 0x088f,
+ 0x9a85, 0x17c2,
+ 0x9a86, 0x0a8d,
+ 0x9a87, 0x075e,
+ 0x9a88, 0x17c3,
+ 0x9a89, 0x52ca,
+ 0x9a8a, 0x17c4,
+ 0x9a8b, 0x04f7,
+ 0x9a8c, 0x1012,
+ 0x9a8d, 0x52cb,
+ 0x9a8f, 0x0932,
+ 0x9a90, 0x17c5,
+ 0x9a91, 0x0c0e,
+ 0x9a92, 0x17c6,
+ 0x9a94, 0x52cd,
+ 0x9a96, 0x17c8,
+ 0x9a97, 0x0bcc,
+ 0x9a98, 0x17c9,
+ 0x9a99, 0x52cf,
+ 0x9a9a, 0x0ce0,
+ 0x9a9b, 0x17ca,
+ 0x9a9e, 0x1735,
+ 0x9a9f, 0x17cd,
+ 0x9aa1, 0x0a89,
+ 0x9aa2, 0x17cf,
+ 0x9aa4, 0x11e7,
+ 0x9aa5, 0x17d1,
+ 0x9aa6, 0x52d0,
+ 0x9aa7, 0x17d2,
+ 0x9aa8, 0x0720,
+ 0x9aa9, 0x52d1,
+ 0x9aaf, 0x1e29,
+ 0x9ab0, 0x1dd3,
+ 0x9ab1, 0x1dd2,
+ 0x9ab2, 0x52d7,
+ 0x9ab6, 0x1dd6,
+ 0x9ab7, 0x1dd4,
+ 0x9ab8, 0x0758,
+ 0x9ab9, 0x52db,
+ 0x9aba, 0x1dd7,
+ 0x9abb, 0x52dc,
+ 0x9abc, 0x1dd8,
+ 0x9abd, 0x52dd,
+ 0x9ac0, 0x1dda,
+ 0x9ac1, 0x1dd9,
+ 0x9ac2, 0x1ddc,
+ 0x9ac3, 0x52e0,
+ 0x9ac5, 0x1ddb,
+ 0x9ac6, 0x52e2,
+ 0x9acb, 0x1ddd,
+ 0x9acd, 0x52e7,
+ 0x9acf, 0x2661,
+ 0x9ad0, 0x52e9,
+ 0x9ad1, 0x1ddf,
+ 0x9ad2, 0x26a4,
+ 0x9ad3, 0x0ddd,
+ 0x9ad4, 0x2174,
+ 0x9ad5, 0x2663,
+ 0x9ad6, 0x2662,
+ 0x9ad7, 0x52ea,
+ 0x9ad8, 0x06da,
+ 0x9ad9, 0x52eb,
+ 0x9adf, 0x1dec,
+ 0x9ae0, 0x52f1,
+ 0x9ae1, 0x1ded,
+ 0x9ae2, 0x52f2,
+ 0x9ae6, 0x1dee,
+ 0x9ae7, 0x52f6,
+ 0x9aeb, 0x1df0,
+ 0x9aec, 0x52fa,
+ 0x9aed, 0x1df2,
+ 0x9aee, 0x2675,
+ 0x9aef, 0x1def,
+ 0x9af0, 0x52fb,
+ 0x9af9, 0x1df3,
+ 0x9afa, 0x5304,
+ 0x9afb, 0x1df1,
+ 0x9afc, 0x5305,
+ 0x9b00, 0x5309,
+ 0x9b03, 0x1234,
+ 0x9b04, 0x530c,
+ 0x9b06, 0x214c,
+ 0x9b07, 0x530e,
+ 0x9b08, 0x1df4,
+ 0x9b09, 0x530f,
+ 0x9b0d, 0x267a,
+ 0x9b0e, 0x5313,
+ 0x9b0f, 0x1df5,
+ 0x9b10, 0x5314,
+ 0x9b13, 0x1df6,
+ 0x9b14, 0x5317,
+ 0x9b1a, 0x26a0,
+ 0x9b1b, 0x531d,
+ 0x9b1f, 0x1df7,
+ 0x9b20, 0x5321,
+ 0x9b22, 0x2668,
+ 0x9b23, 0x1df8,
+ 0x9b24, 0x5323,
+ 0x9b25, 0x1ed0,
+ 0x9b26, 0x5324,
+ 0x9b27, 0x2096,
+ 0x9b28, 0x5325,
+ 0x9b29, 0x23cc,
+ 0x9b2a, 0x5326,
+ 0x9b2e, 0x23c8,
+ 0x9b2f, 0x139b,
+ 0x9b30, 0x532a,
+ 0x9b31, 0x223e,
+ 0x9b32, 0x1260,
+ 0x9b33, 0x532b,
+ 0x9b3b, 0x1773,
+ 0x9b3c, 0x0746,
+ 0x9b3d, 0x5333,
+ 0x9b41, 0x098a,
+ 0x9b42, 0x07ff,
+ 0x9b43, 0x1de1,
+ 0x9b44, 0x0be6,
+ 0x9b45, 0x1de0,
+ 0x9b46, 0x5337,
+ 0x9b47, 0x1de2,
+ 0x9b48, 0x1de4,
+ 0x9b49, 0x1de3,
+ 0x9b4a, 0x5338,
+ 0x9b4d, 0x1de5,
+ 0x9b4e, 0x2665,
+ 0x9b4f, 0x0ec9,
+ 0x9b50, 0x533b,
+ 0x9b51, 0x1de6,
+ 0x9b52, 0x533c,
+ 0x9b54, 0x0b0a,
+ 0x9b55, 0x533e,
+ 0x9b58, 0x2664,
+ 0x9b59, 0x5341,
+ 0x9b5a, 0x2239,
+ 0x9b5b, 0x5342,
+ 0x9b6f, 0x204a,
+ 0x9b70, 0x5356,
+ 0x9b74, 0x261f,
+ 0x9b75, 0x535a,
+ 0x9b77, 0x261e,
+ 0x9b78, 0x535c,
+ 0x9b81, 0x2620,
+ 0x9b82, 0x5365,
+ 0x9b83, 0x2621,
+ 0x9b84, 0x5366,
+ 0x9b8e, 0x2622,
+ 0x9b8f, 0x5370,
+ 0x9b90, 0x2627,
+ 0x9b91, 0x1e39,
+ 0x9b92, 0x2625,
+ 0x9b93, 0x5371,
+ 0x9b9a, 0x2629,
+ 0x9b9b, 0x5378,
+ 0x9b9d, 0x262e,
+ 0x9b9e, 0x262b,
+ 0x9b9f, 0x537a,
+ 0x9baa, 0x262a,
+ 0x9bab, 0x262d,
+ 0x9bac, 0x5385,
+ 0x9bad, 0x2628,
+ 0x9bae, 0x21b9,
+ 0x9baf, 0x5386,
+ 0x9bc0, 0x2636,
+ 0x9bc1, 0x2630,
+ 0x9bc2, 0x5397,
+ 0x9bc7, 0x2638,
+ 0x9bc8, 0x539c,
+ 0x9bc9, 0x200d,
+ 0x9bca, 0x2637,
+ 0x9bcb, 0x539d,
+ 0x9bd4, 0x2645,
+ 0x9bd5, 0x53a6,
+ 0x9bd6, 0x263a,
+ 0x9bd7, 0x53a7,
+ 0x9bdb, 0x2643,
+ 0x9bdc, 0x53ab,
+ 0x9bdd, 0x2640,
+ 0x9bde, 0x53ac,
+ 0x9be1, 0x263d,
+ 0x9be2, 0x2641,
+ 0x9be3, 0x53af,
+ 0x9be4, 0x263e,
+ 0x9be5, 0x53b0,
+ 0x9be7, 0x263f,
+ 0x9be8, 0x1fc0,
+ 0x9be9, 0x53b2,
+ 0x9bea, 0x263b,
+ 0x9bec, 0x53b3,
+ 0x9bf0, 0x2642,
+ 0x9bf1, 0x53b7,
+ 0x9bf4, 0x2644,
+ 0x9bf5, 0x53ba,
+ 0x9bfd, 0x2639,
+ 0x9bfe, 0x53c2,
+ 0x9bff, 0x264c,
+ 0x9c00, 0x53c3,
+ 0x9c08, 0x2647,
+ 0x9c09, 0x264b,
+ 0x9c0a, 0x53cb,
+ 0x9c0d, 0x2649,
+ 0x9c0e, 0x53ce,
+ 0x9c10, 0x2648,
+ 0x9c11, 0x53d0,
+ 0x9c12, 0x264a,
+ 0x9c13, 0x2108,
+ 0x9c14, 0x53d1,
+ 0x9c20, 0x264d,
+ 0x9c21, 0x53dd,
+ 0x9c23, 0x2634,
+ 0x9c24, 0x53df,
+ 0x9c25, 0x2651,
+ 0x9c26, 0x53e0,
+ 0x9c28, 0x2650,
+ 0x9c29, 0x2652,
+ 0x9c2a, 0x53e2,
+ 0x9c2d, 0x264f,
+ 0x9c2e, 0x53e5,
+ 0x9c31, 0x2632,
+ 0x9c32, 0x264e,
+ 0x9c33, 0x2653,
+ 0x9c34, 0x53e8,
+ 0x9c35, 0x2657,
+ 0x9c36, 0x53e9,
+ 0x9c37, 0x2635,
+ 0x9c38, 0x53ea,
+ 0x9c39, 0x2633,
+ 0x9c3a, 0x53eb,
+ 0x9c3b, 0x2656,
+ 0x9c3c, 0x53ec,
+ 0x9c3e, 0x2654,
+ 0x9c3f, 0x53ee,
+ 0x9c45, 0x2658,
+ 0x9c46, 0x53f4,
+ 0x9c48, 0x2655,
+ 0x9c49, 0x1e4d,
+ 0x9c4a, 0x53f6,
+ 0x9c52, 0x265b,
+ 0x9c53, 0x53fe,
+ 0x9c54, 0x265a,
+ 0x9c55, 0x53ff,
+ 0x9c56, 0x2659,
+ 0x9c57, 0x202e,
+ 0x9c58, 0x262f,
+ 0x9c59, 0x5400,
+ 0x9c5d, 0x2646,
+ 0x9c5e, 0x5404,
+ 0x9c5f, 0x2626,
+ 0x9c60, 0x5405,
+ 0x9c67, 0x265c,
+ 0x9c68, 0x540c,
+ 0x9c6d, 0x262c,
+ 0x9c6e, 0x5411,
+ 0x9c78, 0x2623,
+ 0x9c79, 0x541b,
+ 0x9c7a, 0x2631,
+ 0x9c7b, 0x541c,
+ 0x9c7c, 0x10c8,
+ 0x9c7d, 0x541d,
+ 0x9c7f, 0x1d89,
+ 0x9c80, 0x541f,
+ 0x9c81, 0x0a5a,
+ 0x9c82, 0x1d8a,
+ 0x9c83, 0x5420,
+ 0x9c85, 0x1d8b,
+ 0x9c89, 0x5422,
+ 0x9c8b, 0x1d90,
+ 0x9c8c, 0x5424,
+ 0x9c8d, 0x0414,
+ 0x9c8e, 0x1d91,
+ 0x9c8f, 0x5425,
+ 0x9c90, 0x1d92,
+ 0x9c93, 0x5426,
+ 0x9c94, 0x1d95,
+ 0x9c96, 0x5427,
+ 0x9c9a, 0x1d97,
+ 0x9c9c, 0x0f37,
+ 0x9c9d, 0x542b,
+ 0x9c9e, 0x1d99,
+ 0x9ca4, 0x09db,
+ 0x9ca5, 0x1d9f,
+ 0x9caa, 0x542c,
+ 0x9cab, 0x1da4,
+ 0x9cac, 0x542d,
+ 0x9cad, 0x1da5,
+ 0x9caf, 0x542e,
+ 0x9cb0, 0x1da7,
+ 0x9cb8, 0x08d7,
+ 0x9cb9, 0x542f,
+ 0x9cba, 0x1daf,
+ 0x9cbe, 0x5430,
+ 0x9cc3, 0x0cd5,
+ 0x9cc4, 0x1db3,
+ 0x9cc8, 0x5435,
+ 0x9cca, 0x1db7,
+ 0x9cd1, 0x5437,
+ 0x9cd3, 0x1dbe,
+ 0x9cd6, 0x0457,
+ 0x9cd7, 0x1dc1,
+ 0x9cda, 0x5439,
+ 0x9cdc, 0x1dc4,
+ 0x9cde, 0x0a24,
+ 0x9cdf, 0x1dc6,
+ 0x9ce0, 0x543b,
+ 0x9ce2, 0x1dc7,
+ 0x9ce3, 0x543d,
+ 0x9ce5, 0x209c,
+ 0x9ce6, 0x543f,
+ 0x9ce9, 0x2580,
+ 0x9cea, 0x5442,
+ 0x9cec, 0x22dc,
+ 0x9ced, 0x5444,
+ 0x9cf3, 0x1f05,
+ 0x9cf4, 0x208b,
+ 0x9cf5, 0x544a,
+ 0x9cf6, 0x2581,
+ 0x9cf7, 0x544b,
+ 0x9d00, 0x5454,
+ 0x9d06, 0x2583,
+ 0x9d07, 0x2582,
+ 0x9d08, 0x545a,
+ 0x9d09, 0x21ee,
+ 0x9d0a, 0x545b,
+ 0x9d15, 0x2182,
+ 0x9d16, 0x5466,
+ 0x9d1b, 0x2243,
+ 0x9d1c, 0x546b,
+ 0x9d1d, 0x2587,
+ 0x9d1e, 0x546c,
+ 0x9d1f, 0x2588,
+ 0x9d20, 0x546d,
+ 0x9d23, 0x2584,
+ 0x9d24, 0x5470,
+ 0x9d26, 0x21fd,
+ 0x9d27, 0x5472,
+ 0x9d28, 0x21ef,
+ 0x9d29, 0x5473,
+ 0x9d2f, 0x258a,
+ 0x9d30, 0x258c,
+ 0x9d31, 0x5479,
+ 0x9d3b, 0x1f47,
+ 0x9d3c, 0x5483,
+ 0x9d3f, 0x1f1d,
+ 0x9d40, 0x5486,
+ 0x9d42, 0x258d,
+ 0x9d43, 0x5488,
+ 0x9d51, 0x1fd0,
+ 0x9d52, 0x2592,
+ 0x9d53, 0x258f,
+ 0x9d54, 0x5496,
+ 0x9d5c, 0x2594,
+ 0x9d5d, 0x1ee0,
+ 0x9d5e, 0x549e,
+ 0x9d60, 0x2591,
+ 0x9d61, 0x2595,
+ 0x9d62, 0x54a0,
+ 0x9d6a, 0x2597,
+ 0x9d6b, 0x54a8,
+ 0x9d6c, 0x20b6,
+ 0x9d6d, 0x54a9,
+ 0x9d6f, 0x2598,
+ 0x9d70, 0x54ab,
+ 0x9d72, 0x20f6,
+ 0x9d73, 0x54ad,
+ 0x9d87, 0x2585,
+ 0x9d88, 0x54c1,
+ 0x9d89, 0x2599,
+ 0x9d8a, 0x54c2,
+ 0x9d93, 0x2596,
+ 0x9d94, 0x54cb,
+ 0x9d98, 0x259a,
+ 0x9d99, 0x54cf,
+ 0x9d9a, 0x259b,
+ 0x9d9b, 0x54d0,
+ 0x9da5, 0x259d,
+ 0x9da6, 0x54da,
+ 0x9da9, 0x259e,
+ 0x9daa, 0x54dd,
+ 0x9daf, 0x234c,
+ 0x9db0, 0x54e2,
+ 0x9db4, 0x1f44,
+ 0x9db5, 0x54e6,
+ 0x9dbb, 0x2660,
+ 0x9dbc, 0x25a0,
+ 0x9dbd, 0x54ec,
+ 0x9dc0, 0x259c,
+ 0x9dc1, 0x54ef,
+ 0x9dc2, 0x259f,
+ 0x9dc3, 0x54f0,
+ 0x9dc4, 0x1f6c,
+ 0x9dc5, 0x54f1,
+ 0x9dd3, 0x25a2,
+ 0x9dd4, 0x54ff,
+ 0x9dd7, 0x20ae,
+ 0x9dd8, 0x5502,
+ 0x9dd9, 0x258b,
+ 0x9dda, 0x25a3,
+ 0x9ddb, 0x5503,
+ 0x9de5, 0x2589,
+ 0x9de6, 0x25a5,
+ 0x9de7, 0x550d,
+ 0x9def, 0x25a4,
+ 0x9df0, 0x5515,
+ 0x9df2, 0x25a6,
+ 0x9df3, 0x2593,
+ 0x9df4, 0x5517,
+ 0x9df8, 0x25a7,
+ 0x9df9, 0x2222,
+ 0x9dfa, 0x25a9,
+ 0x9dfb, 0x551b,
+ 0x9e00, 0x5520,
+ 0x9e0c, 0x25a8,
+ 0x9e0d, 0x552c,
+ 0x9e15, 0x2586,
+ 0x9e16, 0x5534,
+ 0x9e1a, 0x25a1,
+ 0x9e1b, 0x25aa,
+ 0x9e1c, 0x5538,
+ 0x9e1d, 0x2590,
+ 0x9e1e, 0x258e,
+ 0x9e1f, 0x0b54,
+ 0x9e20, 0x1b35,
+ 0x9e21, 0x0819,
+ 0x9e22, 0x1b36,
+ 0x9e23, 0x0afe,
+ 0x9e24, 0x5539,
+ 0x9e25, 0x0b79,
+ 0x9e26, 0x0fe4,
+ 0x9e27, 0x553a,
+ 0x9e28, 0x1b37,
+ 0x9e2d, 0x0fe5,
+ 0x9e2e, 0x553b,
+ 0x9e2f, 0x1015,
+ 0x9e30, 0x553c,
+ 0x9e31, 0x1b3d,
+ 0x9e32, 0x1b3c,
+ 0x9e33, 0x10ea,
+ 0x9e34, 0x553d,
+ 0x9e35, 0x0e83,
+ 0x9e36, 0x1b3e,
+ 0x9e37, 0x1b40,
+ 0x9e38, 0x1b3f,
+ 0x9e39, 0x1b41,
+ 0x9e3b, 0x553e,
+ 0x9e3d, 0x06e6,
+ 0x9e3e, 0x1b43,
+ 0x9e3f, 0x079f,
+ 0x9e40, 0x5540,
+ 0x9e41, 0x1b44,
+ 0x9e43, 0x0918,
+ 0x9e44, 0x1b46,
+ 0x9e45, 0x062b,
+ 0x9e46, 0x1b47,
+ 0x9e4a, 0x0c90,
+ 0x9e4b, 0x1b4b,
+ 0x9e4d, 0x5541,
+ 0x9e4e, 0x1b4d,
+ 0x9e4f, 0x0bb5,
+ 0x9e50, 0x5542,
+ 0x9e51, 0x1b4e,
+ 0x9e52, 0x5543,
+ 0x9e55, 0x1b4f,
+ 0x9e56, 0x5546,
+ 0x9e57, 0x1b50,
+ 0x9e58, 0x1dd5,
+ 0x9e59, 0x5547,
+ 0x9e5a, 0x1b51,
+ 0x9e5d, 0x5548,
+ 0x9e5e, 0x1b54,
+ 0x9e5f, 0x5549,
+ 0x9e63, 0x1b55,
+ 0x9e64, 0x078e,
+ 0x9e65, 0x554d,
+ 0x9e66, 0x1b56,
+ 0x9e6d, 0x1b5e,
+ 0x9e6e, 0x554e,
+ 0x9e70, 0x108a,
+ 0x9e71, 0x1b5d,
+ 0x9e72, 0x5550,
+ 0x9e73, 0x1b5f,
+ 0x9e74, 0x5551,
+ 0x9e75, 0x2688,
+ 0x9e76, 0x5552,
+ 0x9e79, 0x269e,
+ 0x9e7a, 0x25fb,
+ 0x9e7b, 0x5555,
+ 0x9e7c, 0x1f8c,
+ 0x9e7d, 0x21f4,
+ 0x9e7e, 0x1d16,
+ 0x9e7f, 0x0a60,
+ 0x9e80, 0x5556,
+ 0x9e82, 0x1dfc,
+ 0x9e83, 0x5558,
+ 0x9e87, 0x1dfd,
+ 0x9e89, 0x555c,
+ 0x9e8b, 0x1dff,
+ 0x9e8c, 0x555e,
+ 0x9e92, 0x1e00,
+ 0x9e93, 0x0a5b,
+ 0x9e94, 0x5564,
+ 0x9e97, 0x200f,
+ 0x9e98, 0x5567,
+ 0x9e9d, 0x1e02,
+ 0x9e9e, 0x556c,
+ 0x9e9f, 0x1e03,
+ 0x9ea0, 0x556d,
+ 0x9ea5, 0x2071,
+ 0x9ea6, 0x0a9a,
+ 0x9ea7, 0x5572,
+ 0x9ea9, 0x25f7,
+ 0x9eaa, 0x5574,
+ 0x9eaf, 0x2696,
+ 0x9eb0, 0x5579,
+ 0x9eb4, 0x1cee,
+ 0x9eb5, 0x268f,
+ 0x9eb6, 0x557d,
+ 0x9eb8, 0x1ced,
+ 0x9eb9, 0x557f,
+ 0x9ebb, 0x0a90,
+ 0x9ebc, 0x5581,
+ 0x9ebd, 0x1df9,
+ 0x9ebf, 0x5582,
+ 0x9ec4, 0x07db,
+ 0x9ec5, 0x5587,
+ 0x9ec9, 0x12f8,
+ 0x9eca, 0x558b,
+ 0x9ecc, 0x22da,
+ 0x9ecd, 0x0d89,
+ 0x9ece, 0x09d3,
+ 0x9ecf, 0x1b2a,
+ 0x9ed0, 0x558d,
+ 0x9ed1, 0x0791,
+ 0x9ed2, 0x558e,
+ 0x9ed4, 0x0c2a,
+ 0x9ed5, 0x5590,
+ 0x9ed8, 0x0b0f,
+ 0x9ed9, 0x5593,
+ 0x9edb, 0x1e04,
+ 0x9ede, 0x1ec1,
+ 0x9edf, 0x1e08,
+ 0x9ee0, 0x1e07,
+ 0x9ee1, 0x5595,
+ 0x9ee2, 0x1e09,
+ 0x9ee3, 0x5596,
+ 0x9ee5, 0x1e0c,
+ 0x9ee6, 0x5598,
+ 0x9ee7, 0x1e0b,
+ 0x9ee8, 0x1eb3,
+ 0x9ee9, 0x1e0a,
+ 0x9eea, 0x1e0d,
+ 0x9eeb, 0x5599,
+ 0x9eef, 0x1e0e,
+ 0x9ef0, 0x559d,
+ 0x9ef2, 0x266a,
+ 0x9ef3, 0x559f,
+ 0x9ef4, 0x268a,
+ 0x9ef5, 0x55a0,
+ 0x9ef7, 0x2669,
+ 0x9ef8, 0x55a2,
+ 0x9ef9, 0x1a55,
+ 0x9efa, 0x55a3,
+ 0x9efb, 0x1a56,
+ 0x9efd, 0x2618,
+ 0x9efe, 0x1d76,
+ 0x9eff, 0x2619,
+ 0x9f00, 0x55a4,
+ 0x9f09, 0x261a,
+ 0x9f0a, 0x55ad,
+ 0x9f0b, 0x1d77,
+ 0x9f0c, 0x55ae,
+ 0x9f0d, 0x1d78,
+ 0x9f0e, 0x05e5,
+ 0x9f0f, 0x55af,
+ 0x9f10, 0x1274,
+ 0x9f11, 0x55b0,
+ 0x9f13, 0x071d,
+ 0x9f14, 0x55b2,
+ 0x9f15, 0x2673,
+ 0x9f16, 0x55b3,
+ 0x9f17, 0x1271,
+ 0x9f18, 0x55b4,
+ 0x9f19, 0x13df,
+ 0x9f1a, 0x55b5,
+ 0x9f20, 0x0d8a,
+ 0x9f21, 0x55bb,
+ 0x9f22, 0x1e0f,
+ 0x9f23, 0x55bc,
+ 0x9f2c, 0x1e10,
+ 0x9f2d, 0x55c5,
+ 0x9f2f, 0x1e11,
+ 0x9f30, 0x55c7,
+ 0x9f37, 0x1e13,
+ 0x9f38, 0x55ce,
+ 0x9f39, 0x1e12,
+ 0x9f3a, 0x55cf,
+ 0x9f3b, 0x0430,
+ 0x9f3c, 0x55d0,
+ 0x9f3d, 0x1e14,
+ 0x9f3f, 0x55d1,
+ 0x9f44, 0x1e16,
+ 0x9f45, 0x55d6,
+ 0x9f4a, 0x20c6,
+ 0x9f4b, 0x226b,
+ 0x9f4c, 0x55db,
+ 0x9f4f, 0x24d3,
+ 0x9f50, 0x0c0a,
+ 0x9f51, 0x19c2,
+ 0x9f52, 0x1e86,
+ 0x9f53, 0x55de,
+ 0x9f54, 0x260f,
+ 0x9f55, 0x55df,
+ 0x9f59, 0x2611,
+ 0x9f5a, 0x55e3,
+ 0x9f5c, 0x2613,
+ 0x9f5d, 0x55e5,
+ 0x9f5f, 0x2610,
+ 0x9f60, 0x2612,
+ 0x9f61, 0x2030,
+ 0x9f62, 0x55e7,
+ 0x9f63, 0x2671,
+ 0x9f64, 0x55e8,
+ 0x9f66, 0x2614,
+ 0x9f67, 0x55ea,
+ 0x9f6a, 0x2616,
+ 0x9f6b, 0x55ed,
+ 0x9f6c, 0x2615,
+ 0x9f6d, 0x55ee,
+ 0x9f72, 0x20f2,
+ 0x9f73, 0x55f3,
+ 0x9f77, 0x2617,
+ 0x9f78, 0x55f7,
+ 0x9f7f, 0x0502,
+ 0x9f80, 0x1d6d,
+ 0x9f81, 0x55fe,
+ 0x9f83, 0x1d6e,
+ 0x9f84, 0x0a2d,
+ 0x9f85, 0x1d6f,
+ 0x9f8b, 0x0c7e,
+ 0x9f8c, 0x1d75,
+ 0x9f8d, 0x2037,
+ 0x9f8e, 0x5600,
+ 0x9f90, 0x20b3,
+ 0x9f91, 0x5602,
+ 0x9f94, 0x1f22,
+ 0x9f95, 0x24ed,
+ 0x9f96, 0x5605,
+ 0x9f99, 0x0a43,
+ 0x9f9a, 0x0701,
+ 0x9f9b, 0x1a54,
+ 0x9f9c, 0x1f34,
+ 0x9f9d, 0x5608,
+ 0x9f9f, 0x0743,
+ 0x9fa0, 0x12f3,
+ 0x9fa1, 0x560a,
+ 0xe7e7, 0x274b,
+ 0xe815, 0x561f,
+ 0xf92c, 0x560f,
+ 0xfa0d, 0x5610,
+ 0xfa11, 0x5613,
+ 0xfa13, 0x5614,
+ 0xfa18, 0x5616,
+ 0xfa1f, 0x5617,
+ 0xfa23, 0x561a,
+ 0xfa27, 0x561c,
+ 0xfe30, 0x271d,
+ 0xfe49, 0x272b,
+ 0xfe54, 0x2735,
+ 0xfe59, 0x2739,
+ 0xfe68, 0x2747,
+ 0xff01, 0x0106,
+ 0xff04, 0x00a6,
+ 0xff05, 0x010a,
+ 0xff5e, 0x006a,
+ 0xffe0, 0x00a8,
+ 0xffe2, 0x271e,
+ 0xffe3, 0x0163,
+ 0xffe4, 0x271f,
+ 0xffe5, 0x0109,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12UniGBUCS2HEnc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12UniGBUCS2HMap2, 13461
+};
+
+static Gushort gb12UniGBUCS2VMap2[26970] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x00a4, 0x00a7,
+ 0x00a7, 0x00ab,
+ 0x00a8, 0x0066,
+ 0x00b0, 0x00a2,
+ 0x00b1, 0x007f,
+ 0x00d7, 0x0080,
+ 0x00e0, 0x029f,
+ 0x00e1, 0x029d,
+ 0x00e8, 0x02a3,
+ 0x00e9, 0x02a1,
+ 0x00ea, 0x02b5,
+ 0x00ec, 0x02a7,
+ 0x00ed, 0x02a5,
+ 0x00f2, 0x02ab,
+ 0x00f3, 0x02a9,
+ 0x00f7, 0x0081,
+ 0x00f9, 0x02af,
+ 0x00fa, 0x02ad,
+ 0x00fc, 0x02b4,
+ 0x0101, 0x029c,
+ 0x0113, 0x02a0,
+ 0x011b, 0x02a2,
+ 0x012b, 0x02a4,
+ 0x014d, 0x02a8,
+ 0x016b, 0x02ac,
+ 0x01ce, 0x029e,
+ 0x01d0, 0x02a6,
+ 0x01d2, 0x02aa,
+ 0x01d4, 0x02ae,
+ 0x01d6, 0x02b0,
+ 0x01d8, 0x02b1,
+ 0x01da, 0x02b2,
+ 0x01dc, 0x02b3,
+ 0x02c7, 0x0065,
+ 0x02c9, 0x0064,
+ 0x02ca, 0x26b3,
+ 0x02d9, 0x26b5,
+ 0x0391, 0x020d,
+ 0x03a3, 0x021e,
+ 0x03b1, 0x0225,
+ 0x03c3, 0x0236,
+ 0x0401, 0x0260,
+ 0x0410, 0x025a,
+ 0x0416, 0x0261,
+ 0x0436, 0x0282,
+ 0x0451, 0x0281,
+ 0x1e3f, 0x02b7,
+ 0x2010, 0x2722,
+ 0x2013, 0x26b6,
+ 0x2014, 0x0069,
+ 0x2015, 0x26b7,
+ 0x2016, 0x006b,
+ 0x2018, 0x006d,
+ 0x201c, 0x006f,
+ 0x2025, 0x26b8,
+ 0x2026, 0x006c,
+ 0x2030, 0x00aa,
+ 0x2032, 0x00a3,
+ 0x2035, 0x26b9,
+ 0x203b, 0x00b8,
+ 0x2103, 0x00a5,
+ 0x2105, 0x26ba,
+ 0x2109, 0x26bb,
+ 0x2116, 0x00ac,
+ 0x2121, 0x2720,
+ 0x2160, 0x00fa,
+ 0x2170, 0x26a9,
+ 0x2190, 0x00ba,
+ 0x2192, 0x00b9,
+ 0x2193, 0x00bc,
+ 0x2196, 0x26bc,
+ 0x2208, 0x0089,
+ 0x220f, 0x0086,
+ 0x2211, 0x0085,
+ 0x2215, 0x26c0,
+ 0x221a, 0x008b,
+ 0x221d, 0x0097,
+ 0x221e, 0x009d,
+ 0x221f, 0x26c1,
+ 0x2220, 0x008e,
+ 0x2223, 0x26c2,
+ 0x2225, 0x008d,
+ 0x2227, 0x0083,
+ 0x2229, 0x0088,
+ 0x222a, 0x0087,
+ 0x222b, 0x0091,
+ 0x222e, 0x0092,
+ 0x2234, 0x009f,
+ 0x2235, 0x009e,
+ 0x2236, 0x0082,
+ 0x2237, 0x008a,
+ 0x223d, 0x0096,
+ 0x2248, 0x0095,
+ 0x224c, 0x0094,
+ 0x2252, 0x26c3,
+ 0x2260, 0x0098,
+ 0x2261, 0x0093,
+ 0x2264, 0x009b,
+ 0x2266, 0x26c4,
+ 0x226e, 0x0099,
+ 0x2295, 0x2704,
+ 0x2299, 0x0090,
+ 0x22a5, 0x008c,
+ 0x22bf, 0x26c6,
+ 0x22ef, 0x006c,
+ 0x2312, 0x008f,
+ 0x2460, 0x00e6,
+ 0x2474, 0x00d2,
+ 0x2488, 0x00be,
+ 0x2500, 0x02e2,
+ 0x2550, 0x26c7,
+ 0x2581, 0x26eb,
+ 0x2593, 0x26fa,
+ 0x25a0, 0x00b5,
+ 0x25a1, 0x00b4,
+ 0x25b2, 0x00b7,
+ 0x25b3, 0x00b6,
+ 0x25bc, 0x26fd,
+ 0x25c6, 0x00b3,
+ 0x25c7, 0x00b2,
+ 0x25cb, 0x00af,
+ 0x25ce, 0x00b1,
+ 0x25cf, 0x00b0,
+ 0x25e2, 0x26ff,
+ 0x2605, 0x00ae,
+ 0x2606, 0x00ad,
+ 0x2609, 0x2703,
+ 0x2640, 0x00a1,
+ 0x2642, 0x00a0,
+ 0x3000, 0x0060,
+ 0x3003, 0x0067,
+ 0x3005, 0x0068,
+ 0x3006, 0x2728,
+ 0x3007, 0x1e17,
+ 0x3008, 0x0073,
+ 0x3010, 0x007d,
+ 0x3012, 0x2705,
+ 0x3013, 0x00bd,
+ 0x3014, 0x0071,
+ 0x3016, 0x007b,
+ 0x301d, 0x2706,
+ 0x3021, 0x2708,
+ 0x3041, 0x0164,
+ 0x309b, 0x2724,
+ 0x309d, 0x2729,
+ 0x30a1, 0x01b7,
+ 0x30fb, 0x0063,
+ 0x30fc, 0x2723,
+ 0x30fd, 0x2726,
+ 0x3105, 0x02bc,
+ 0x3220, 0x00f0,
+ 0x3231, 0x2721,
+ 0x32a3, 0x2711,
+ 0x338e, 0x2712,
+ 0x339c, 0x2714,
+ 0x33a1, 0x2717,
+ 0x33c4, 0x2718,
+ 0x33ce, 0x2719,
+ 0x33d1, 0x271a,
+ 0x33d5, 0x271c,
+ 0x4e00, 0x1042,
+ 0x4e01, 0x05e0,
+ 0x4e02, 0x2758,
+ 0x4e03, 0x0bfe,
+ 0x4e04, 0x2759,
+ 0x4e07, 0x0ea3,
+ 0x4e08, 0x116a,
+ 0x4e09, 0x0cd8,
+ 0x4e0a, 0x0d08,
+ 0x4e0b, 0x0f2f,
+ 0x4e0c, 0x1258,
+ 0x4e0d, 0x0482,
+ 0x4e0e, 0x10d0,
+ 0x4e0f, 0x275c,
+ 0x4e10, 0x125a,
+ 0x4e11, 0x0518,
+ 0x4e12, 0x275d,
+ 0x4e13, 0x1205,
+ 0x4e14, 0x0c4f,
+ 0x4e15, 0x125d,
+ 0x4e16, 0x0d57,
+ 0x4e17, 0x275e,
+ 0x4e18, 0x0c6d,
+ 0x4e19, 0x0464,
+ 0x4e1a, 0x103c,
+ 0x4e1b, 0x0557,
+ 0x4e1c, 0x05ea,
+ 0x4e1d, 0x0db4,
+ 0x4e1e, 0x125f,
+ 0x4e1f, 0x275f,
+ 0x4e22, 0x05e9,
+ 0x4e23, 0x2762,
+ 0x4e24, 0x0a06,
+ 0x4e25, 0x0ff8,
+ 0x4e26, 0x2763,
+ 0x4e27, 0x0cde,
+ 0x4e28, 0x1263,
+ 0x4e29, 0x2764,
+ 0x4e2a, 0x06f1,
+ 0x4e2b, 0x0fe7,
+ 0x4e2c, 0x169c,
+ 0x4e2d, 0x11cf,
+ 0x4e2e, 0x2765,
+ 0x4e30, 0x067e,
+ 0x4e31, 0x2767,
+ 0x4e32, 0x0531,
+ 0x4e33, 0x2768,
+ 0x4e34, 0x0a22,
+ 0x4e35, 0x2769,
+ 0x4e36, 0x1272,
+ 0x4e37, 0x276a,
+ 0x4e38, 0x0e99,
+ 0x4e39, 0x0585,
+ 0x4e3a, 0x0eb9,
+ 0x4e3b, 0x11f6,
+ 0x4e3c, 0x276b,
+ 0x4e3d, 0x09e1,
+ 0x4e3e, 0x0908,
+ 0x4e3f, 0x1265,
+ 0x4e40, 0x276c,
+ 0x4e43, 0x0b2e,
+ 0x4e44, 0x276f,
+ 0x4e45, 0x08f2,
+ 0x4e46, 0x2770,
+ 0x4e47, 0x1267,
+ 0x4e48, 0x0ab9,
+ 0x4e49, 0x106c,
+ 0x4e4a, 0x2771,
+ 0x4e4b, 0x11ad,
+ 0x4e4c, 0x0ee9,
+ 0x4e4d, 0x1148,
+ 0x4e4e, 0x07ac,
+ 0x4e4f, 0x0643,
+ 0x4e50, 0x09c1,
+ 0x4e51, 0x2772,
+ 0x4e52, 0x0bd8,
+ 0x4e53, 0x0b93,
+ 0x4e54, 0x0c44,
+ 0x4e55, 0x2773,
+ 0x4e56, 0x072d,
+ 0x4e57, 0x2774,
+ 0x4e58, 0x04f0,
+ 0x4e59, 0x1059,
+ 0x4e5a, 0x2775,
+ 0x4e5c, 0x1275,
+ 0x4e5d, 0x08f4,
+ 0x4e5e, 0x0c11,
+ 0x4e5f, 0x1039,
+ 0x4e60, 0x0f1d,
+ 0x4e61, 0x0f54,
+ 0x4e62, 0x2777,
+ 0x4e66, 0x0d80,
+ 0x4e67, 0x277b,
+ 0x4e69, 0x1276,
+ 0x4e6a, 0x277d,
+ 0x4e70, 0x0a99,
+ 0x4e71, 0x0a79,
+ 0x4e72, 0x2783,
+ 0x4e73, 0x0cc4,
+ 0x4e74, 0x2784,
+ 0x4e7e, 0x0c29,
+ 0x4e7f, 0x278e,
+ 0x4e82, 0x2059,
+ 0x4e83, 0x2791,
+ 0x4e86, 0x0a14,
+ 0x4e87, 0x2794,
+ 0x4e88, 0x10cd,
+ 0x4e89, 0x119a,
+ 0x4e8a, 0x2795,
+ 0x4e8b, 0x0d59,
+ 0x4e8c, 0x063d,
+ 0x4e8d, 0x1257,
+ 0x4e8e, 0x10bf,
+ 0x4e8f, 0x0984,
+ 0x4e90, 0x2796,
+ 0x4e91, 0x1109,
+ 0x4e92, 0x07ba,
+ 0x4e93, 0x1277,
+ 0x4e94, 0x0ef4,
+ 0x4e95, 0x08dd,
+ 0x4e96, 0x2797,
+ 0x4e98, 0x125e,
+ 0x4e99, 0x2799,
+ 0x4e9a, 0x0ff0,
+ 0x4e9b, 0x0f74,
+ 0x4e9c, 0x279a,
+ 0x4e9e, 0x21f1,
+ 0x4e9f, 0x1273,
+ 0x4ea0, 0x1303,
+ 0x4ea1, 0x0ea7,
+ 0x4ea2, 0x0947,
+ 0x4ea3, 0x279c,
+ 0x4ea4, 0x088c,
+ 0x4ea5, 0x075c,
+ 0x4ea6, 0x1067,
+ 0x4ea7, 0x04c1,
+ 0x4ea8, 0x0797,
+ 0x4ea9, 0x0b19,
+ 0x4eaa, 0x279d,
+ 0x4eab, 0x0f5a,
+ 0x4eac, 0x08d8,
+ 0x4ead, 0x0e55,
+ 0x4eae, 0x0a0a,
+ 0x4eaf, 0x279e,
+ 0x4eb2, 0x0c54,
+ 0x4eb3, 0x1305,
+ 0x4eb4, 0x27a1,
+ 0x4eb5, 0x1308,
+ 0x4eb6, 0x27a2,
+ 0x4eba, 0x0ca6,
+ 0x4ebb, 0x129f,
+ 0x4ebc, 0x27a6,
+ 0x4ebf, 0x1061,
+ 0x4ec0, 0x0d49,
+ 0x4ec1, 0x0ca5,
+ 0x4ec2, 0x12a2,
+ 0x4ec3, 0x12a0,
+ 0x4ec4, 0x127c,
+ 0x4ec5, 0x08c7,
+ 0x4ec6, 0x0bec,
+ 0x4ec7, 0x0515,
+ 0x4ec8, 0x27a9,
+ 0x4ec9, 0x12a1,
+ 0x4eca, 0x08c2,
+ 0x4ecb, 0x08ba,
+ 0x4ecc, 0x27aa,
+ 0x4ecd, 0x0caf,
+ 0x4ece, 0x0556,
+ 0x4ecf, 0x27ab,
+ 0x4ed1, 0x0a7f,
+ 0x4ed2, 0x27ad,
+ 0x4ed3, 0x049d,
+ 0x4ed4, 0x122d,
+ 0x4ed5, 0x0d62,
+ 0x4ed6, 0x0df0,
+ 0x4ed7, 0x116d,
+ 0x4ed8, 0x06b1,
+ 0x4ed9, 0x0f36,
+ 0x4eda, 0x27ae,
+ 0x4edd, 0x12ee,
+ 0x4ede, 0x12a6,
+ 0x4edf, 0x0c27,
+ 0x4ee0, 0x27b1,
+ 0x4ee1, 0x12a4,
+ 0x4ee2, 0x27b2,
+ 0x4ee3, 0x057d,
+ 0x4ee4, 0x0a37,
+ 0x4ee5, 0x105b,
+ 0x4ee6, 0x27b3,
+ 0x4ee8, 0x12a3,
+ 0x4ee9, 0x27b5,
+ 0x4eea, 0x104e,
+ 0x4eeb, 0x12a5,
+ 0x4eec, 0x0acc,
+ 0x4eed, 0x27b6,
+ 0x4ef0, 0x101f,
+ 0x4ef1, 0x27b9,
+ 0x4ef2, 0x11d8,
+ 0x4ef3, 0x12a8,
+ 0x4ef4, 0x27ba,
+ 0x4ef5, 0x12ab,
+ 0x4ef6, 0x0871,
+ 0x4ef7, 0x084e,
+ 0x4ef8, 0x27bb,
+ 0x4efb, 0x0ca9,
+ 0x4efc, 0x27be,
+ 0x4efd, 0x067a,
+ 0x4efe, 0x27bf,
+ 0x4eff, 0x065f,
+ 0x4f00, 0x27c0,
+ 0x4f01, 0x0c12,
+ 0x4f02, 0x27c1,
+ 0x4f09, 0x12ae,
+ 0x4f0a, 0x1048,
+ 0x4f0b, 0x27c8,
+ 0x4f0d, 0x0ef8,
+ 0x4f0e, 0x0832,
+ 0x4f0f, 0x0699,
+ 0x4f10, 0x0642,
+ 0x4f11, 0x0fa8,
+ 0x4f12, 0x27ca,
+ 0x4f17, 0x11d9,
+ 0x4f18, 0x10aa,
+ 0x4f19, 0x0804,
+ 0x4f1a, 0x07f6,
+ 0x4f1b, 0x12a7,
+ 0x4f1c, 0x27cf,
+ 0x4f1e, 0x0cda,
+ 0x4f1f, 0x0ebf,
+ 0x4f20, 0x052e,
+ 0x4f21, 0x27d1,
+ 0x4f22, 0x12a9,
+ 0x4f23, 0x27d2,
+ 0x4f24, 0x0d04,
+ 0x4f25, 0x12ac,
+ 0x4f26, 0x0a7e,
+ 0x4f27, 0x12ad,
+ 0x4f28, 0x27d3,
+ 0x4f2a, 0x0ec0,
+ 0x4f2b, 0x12af,
+ 0x4f2c, 0x27d5,
+ 0x4f2f, 0x0475,
+ 0x4f30, 0x0719,
+ 0x4f31, 0x27d8,
+ 0x4f32, 0x12b7,
+ 0x4f33, 0x27d9,
+ 0x4f34, 0x03f4,
+ 0x4f35, 0x27da,
+ 0x4f36, 0x0a2f,
+ 0x4f37, 0x27db,
+ 0x4f38, 0x0d25,
+ 0x4f39, 0x27dc,
+ 0x4f3a, 0x0dba,
+ 0x4f3b, 0x27dd,
+ 0x4f3c, 0x0dbb,
+ 0x4f3d, 0x12b8,
+ 0x4f3e, 0x27de,
+ 0x4f43, 0x05c9,
+ 0x4f44, 0x27e3,
+ 0x4f46, 0x058c,
+ 0x4f47, 0x27e5,
+ 0x4f4d, 0x0eca,
+ 0x4f4e, 0x05ae,
+ 0x4f4f, 0x11fe,
+ 0x4f50, 0x1251,
+ 0x4f51, 0x10b8,
+ 0x4f52, 0x27eb,
+ 0x4f53, 0x0e38,
+ 0x4f54, 0x27ec,
+ 0x4f55, 0x0785,
+ 0x4f56, 0x27ed,
+ 0x4f57, 0x12b6,
+ 0x4f58, 0x12f0,
+ 0x4f59, 0x10c5,
+ 0x4f5a, 0x12b3,
+ 0x4f5b, 0x068d,
+ 0x4f5c, 0x1254,
+ 0x4f5d, 0x12b4,
+ 0x4f5e, 0x12b0,
+ 0x4f5f, 0x12b5,
+ 0x4f60, 0x0b46,
+ 0x4f61, 0x27ee,
+ 0x4f63, 0x109b,
+ 0x4f64, 0x12aa,
+ 0x4f65, 0x12f1,
+ 0x4f66, 0x27f0,
+ 0x4f67, 0x12b1,
+ 0x4f68, 0x27f1,
+ 0x4f69, 0x0ba6,
+ 0x4f6a, 0x27f2,
+ 0x4f6c, 0x09bb,
+ 0x4f6d, 0x27f4,
+ 0x4f6f, 0x1019,
+ 0x4f70, 0x03e6,
+ 0x4f71, 0x27f6,
+ 0x4f73, 0x0844,
+ 0x4f74, 0x12ba,
+ 0x4f75, 0x27f8,
+ 0x4f76, 0x12b9,
+ 0x4f77, 0x27f9,
+ 0x4f7b, 0x12c0,
+ 0x4f7c, 0x12c2,
+ 0x4f7d, 0x27fd,
+ 0x4f7e, 0x12bf,
+ 0x4f7f, 0x0d50,
+ 0x4f80, 0x27fe,
+ 0x4f83, 0x12bd,
+ 0x4f84, 0x11b5,
+ 0x4f85, 0x2801,
+ 0x4f86, 0x1ff2,
+ 0x4f87, 0x2802,
+ 0x4f88, 0x0503,
+ 0x4f89, 0x12bc,
+ 0x4f8a, 0x2803,
+ 0x4f8b, 0x09e8,
+ 0x4f8c, 0x2804,
+ 0x4f8d, 0x0d63,
+ 0x4f8e, 0x2805,
+ 0x4f8f, 0x12be,
+ 0x4f90, 0x2806,
+ 0x4f91, 0x12bb,
+ 0x4f92, 0x2807,
+ 0x4f94, 0x12c4,
+ 0x4f95, 0x2809,
+ 0x4f96, 0x205d,
+ 0x4f97, 0x05f0,
+ 0x4f98, 0x280a,
+ 0x4f9b, 0x0702,
+ 0x4f9c, 0x280d,
+ 0x4f9d, 0x1047,
+ 0x4f9e, 0x280e,
+ 0x4fa0, 0x0f2d,
+ 0x4fa1, 0x2810,
+ 0x4fa3, 0x0a69,
+ 0x4fa4, 0x2812,
+ 0x4fa5, 0x0895,
+ 0x4fa6, 0x118d,
+ 0x4fa7, 0x04a7,
+ 0x4fa8, 0x0c45,
+ 0x4fa9, 0x0978,
+ 0x4faa, 0x12c1,
+ 0x4fab, 0x2813,
+ 0x4fac, 0x12c3,
+ 0x4fad, 0x2814,
+ 0x4fae, 0x0ef9,
+ 0x4faf, 0x07a5,
+ 0x4fb0, 0x2815,
+ 0x4fb5, 0x0c53,
+ 0x4fb6, 0x281a,
+ 0x4fbf, 0x044c,
+ 0x4fc0, 0x2823,
+ 0x4fc2, 0x269c,
+ 0x4fc3, 0x055c,
+ 0x4fc4, 0x062c,
+ 0x4fc5, 0x12c8,
+ 0x4fc6, 0x2825,
+ 0x4fca, 0x092e,
+ 0x4fcb, 0x2829,
+ 0x4fce, 0x12f2,
+ 0x4fcf, 0x0c4b,
+ 0x4fd0, 0x09e9,
+ 0x4fd1, 0x12cc,
+ 0x4fd2, 0x282c,
+ 0x4fd7, 0x0dcc,
+ 0x4fd8, 0x069a,
+ 0x4fd9, 0x2831,
+ 0x4fda, 0x12c9,
+ 0x4fdb, 0x2832,
+ 0x4fdc, 0x12cb,
+ 0x4fdd, 0x040c,
+ 0x4fde, 0x10c6,
+ 0x4fdf, 0x12cd,
+ 0x4fe0, 0x21b5,
+ 0x4fe1, 0x0f90,
+ 0x4fe2, 0x2833,
+ 0x4fe3, 0x12ca,
+ 0x4fe4, 0x2834,
+ 0x4fe6, 0x12c5,
+ 0x4fe7, 0x2836,
+ 0x4fe8, 0x12c6,
+ 0x4fe9, 0x09f2,
+ 0x4fea, 0x12c7,
+ 0x4feb, 0x2837,
+ 0x4fed, 0x0866,
+ 0x4fee, 0x0fa9,
+ 0x4fef, 0x06a4,
+ 0x4ff0, 0x2839,
+ 0x4ff1, 0x0912,
+ 0x4ff2, 0x283a,
+ 0x4ff3, 0x12d1,
+ 0x4ff4, 0x283b,
+ 0x4ff8, 0x12ce,
+ 0x4ff9, 0x283f,
+ 0x4ffa, 0x03be,
+ 0x4ffb, 0x2840,
+ 0x4ffe, 0x12d6,
+ 0x4fff, 0x2843,
+ 0x5000, 0x22cc,
+ 0x5001, 0x2844,
+ 0x5006, 0x2016,
+ 0x5007, 0x2849,
+ 0x5009, 0x1e62,
+ 0x500a, 0x284b,
+ 0x500b, 0x1f20,
+ 0x500c, 0x12d8,
+ 0x500d, 0x041f,
+ 0x500e, 0x284c,
+ 0x500f, 0x12d3,
+ 0x5010, 0x284d,
+ 0x5011, 0x207f,
+ 0x5012, 0x059a,
+ 0x5013, 0x284e,
+ 0x5014, 0x0922,
+ 0x5015, 0x284f,
+ 0x5018, 0x0e1b,
+ 0x5019, 0x07a9,
+ 0x501a, 0x1057,
+ 0x501b, 0x2852,
+ 0x501c, 0x12d7,
+ 0x501d, 0x2853,
+ 0x501f, 0x08b9,
+ 0x5020, 0x2855,
+ 0x5021, 0x04d0,
+ 0x5022, 0x2856,
+ 0x5025, 0x12d9,
+ 0x5026, 0x091a,
+ 0x5027, 0x2859,
+ 0x5028, 0x12da,
+ 0x5029, 0x12cf,
+ 0x502a, 0x0b42,
+ 0x502b, 0x205c,
+ 0x502c, 0x12d2,
+ 0x502d, 0x12d5,
+ 0x502e, 0x12d4,
+ 0x502f, 0x285a,
+ 0x503a, 0x114f,
+ 0x503b, 0x2865,
+ 0x503c, 0x11b4,
+ 0x503d, 0x2866,
+ 0x503e, 0x0c60,
+ 0x503f, 0x2867,
+ 0x5043, 0x12dc,
+ 0x5044, 0x286b,
+ 0x5047, 0x084c,
+ 0x5048, 0x12de,
+ 0x5049, 0x2194,
+ 0x504a, 0x286e,
+ 0x504c, 0x12d0,
+ 0x504d, 0x2870,
+ 0x504e, 0x12df,
+ 0x504f, 0x0bca,
+ 0x5050, 0x2871,
+ 0x5055, 0x12dd,
+ 0x5056, 0x2876,
+ 0x505a, 0x1253,
+ 0x505b, 0x287a,
+ 0x505c, 0x0e54,
+ 0x505d, 0x287b,
+ 0x5065, 0x0872,
+ 0x5066, 0x2883,
+ 0x506c, 0x12e0,
+ 0x506d, 0x2889,
+ 0x5074, 0x1e65,
+ 0x5075, 0x2281,
+ 0x5076, 0x0b7d,
+ 0x5077, 0x0e66,
+ 0x5078, 0x2890,
+ 0x507b, 0x12e1,
+ 0x507c, 0x2893,
+ 0x507e, 0x12db,
+ 0x507f, 0x04ca,
+ 0x5080, 0x098b,
+ 0x5081, 0x2895,
+ 0x5085, 0x06b0,
+ 0x5086, 0x2899,
+ 0x5088, 0x09e7,
+ 0x5089, 0x289b,
+ 0x508d, 0x0403,
+ 0x508e, 0x289f,
+ 0x5096, 0x22cd,
+ 0x5097, 0x28a7,
+ 0x5098, 0x210a,
+ 0x5099, 0x1e3e,
+ 0x509a, 0x28a8,
+ 0x50a2, 0x267f,
+ 0x50a3, 0x0579,
+ 0x50a4, 0x28b0,
+ 0x50a5, 0x12e2,
+ 0x50a6, 0x28b1,
+ 0x50a7, 0x12e3,
+ 0x50a8, 0x0525,
+ 0x50a9, 0x12e4,
+ 0x50aa, 0x28b2,
+ 0x50ac, 0x0562,
+ 0x50ad, 0x222e,
+ 0x50ae, 0x28b4,
+ 0x50b2, 0x03cc,
+ 0x50b3, 0x1e96,
+ 0x50b4, 0x22cb,
+ 0x50b5, 0x226c,
+ 0x50b6, 0x28b8,
+ 0x50b7, 0x2117,
+ 0x50b8, 0x28b9,
+ 0x50ba, 0x12e5,
+ 0x50bb, 0x0cee,
+ 0x50bc, 0x28bb,
+ 0x50be, 0x20e8,
+ 0x50bf, 0x28bd,
+ 0x50c2, 0x22d4,
+ 0x50c3, 0x28c0,
+ 0x50c5, 0x1fb9,
+ 0x50c6, 0x28c2,
+ 0x50c9, 0x22d8,
+ 0x50ca, 0x28c5,
+ 0x50cf, 0x0f5e,
+ 0x50d0, 0x28ca,
+ 0x50d1, 0x20df,
+ 0x50d2, 0x28cb,
+ 0x50d5, 0x20c2,
+ 0x50d6, 0x12e6,
+ 0x50d7, 0x28ce,
+ 0x50da, 0x0a0e,
+ 0x50db, 0x28d1,
+ 0x50de, 0x2195,
+ 0x50df, 0x28d4,
+ 0x50e5, 0x1fac,
+ 0x50e6, 0x12ea,
+ 0x50e7, 0x0ce7,
+ 0x50e8, 0x22d3,
+ 0x50e9, 0x28da,
+ 0x50ec, 0x12e9,
+ 0x50ed, 0x12e8,
+ 0x50ee, 0x12eb,
+ 0x50ef, 0x28dd,
+ 0x50f3, 0x0dd0,
+ 0x50f4, 0x28e1,
+ 0x50f5, 0x087a,
+ 0x50f6, 0x28e2,
+ 0x50f9, 0x1f81,
+ 0x50fa, 0x28e5,
+ 0x50fb, 0x0bc6,
+ 0x50fc, 0x28e6,
+ 0x5100, 0x2210,
+ 0x5101, 0x28ea,
+ 0x5102, 0x22cf,
+ 0x5103, 0x28eb,
+ 0x5104, 0x2213,
+ 0x5105, 0x28ec,
+ 0x5106, 0x12e7,
+ 0x5107, 0x12ec,
+ 0x5108, 0x1fe4,
+ 0x5109, 0x1f90,
+ 0x510a, 0x28ed,
+ 0x510b, 0x12ed,
+ 0x510c, 0x28ee,
+ 0x5110, 0x22d6,
+ 0x5111, 0x28f2,
+ 0x5112, 0x0cc0,
+ 0x5113, 0x28f3,
+ 0x5114, 0x22d0,
+ 0x5115, 0x22ce,
+ 0x5116, 0x28f4,
+ 0x5118, 0x2681,
+ 0x5119, 0x28f6,
+ 0x511f, 0x1e76,
+ 0x5120, 0x28fc,
+ 0x5121, 0x09c7,
+ 0x5122, 0x28fd,
+ 0x512a, 0x2231,
+ 0x512b, 0x2905,
+ 0x5132, 0x1e93,
+ 0x5133, 0x290c,
+ 0x5137, 0x22d2,
+ 0x5138, 0x2910,
+ 0x513a, 0x22d7,
+ 0x513b, 0x22d5,
+ 0x513c, 0x22d1,
+ 0x513d, 0x2912,
+ 0x513f, 0x0638,
+ 0x5140, 0x1259,
+ 0x5141, 0x110d,
+ 0x5142, 0x2914,
+ 0x5143, 0x10ed,
+ 0x5144, 0x0fa1,
+ 0x5145, 0x0509,
+ 0x5146, 0x1178,
+ 0x5147, 0x2915,
+ 0x5148, 0x0f35,
+ 0x5149, 0x073b,
+ 0x514a, 0x2916,
+ 0x514b, 0x0958,
+ 0x514c, 0x2917,
+ 0x514d, 0x0ae7,
+ 0x514e, 0x2918,
+ 0x5151, 0x0611,
+ 0x5152, 0x1ee5,
+ 0x5153, 0x291b,
+ 0x5154, 0x0e74,
+ 0x5155, 0x1302,
+ 0x5156, 0x1304,
+ 0x5157, 0x291c,
+ 0x515a, 0x0594,
+ 0x515b, 0x291f,
+ 0x515c, 0x05f4,
+ 0x515d, 0x2920,
+ 0x5162, 0x08d3,
+ 0x5163, 0x2925,
+ 0x5165, 0x0cc6,
+ 0x5166, 0x2927,
+ 0x5168, 0x0c86,
+ 0x5169, 0x2025,
+ 0x516a, 0x2929,
+ 0x516b, 0x03d6,
+ 0x516c, 0x0704,
+ 0x516d, 0x0a42,
+ 0x516e, 0x12f6,
+ 0x516f, 0x292a,
+ 0x5170, 0x09a7,
+ 0x5171, 0x070b,
+ 0x5172, 0x292b,
+ 0x5173, 0x0731,
+ 0x5174, 0x0f96,
+ 0x5175, 0x0461,
+ 0x5176, 0x0c03,
+ 0x5177, 0x090e,
+ 0x5178, 0x05c5,
+ 0x5179, 0x1225,
+ 0x517a, 0x292c,
+ 0x517b, 0x1021,
+ 0x517c, 0x0859,
+ 0x517d, 0x0d75,
+ 0x517e, 0x292d,
+ 0x5180, 0x0830,
+ 0x5181, 0x12fa,
+ 0x5182, 0x129d,
+ 0x5183, 0x292f,
+ 0x5185, 0x0b3d,
+ 0x5186, 0x2931,
+ 0x5188, 0x06cf,
+ 0x5189, 0x0c98,
+ 0x518a, 0x2933,
+ 0x518c, 0x04a8,
+ 0x518d, 0x111c,
+ 0x518e, 0x2935,
+ 0x5192, 0x0ab5,
+ 0x5193, 0x2939,
+ 0x5195, 0x0ae6,
+ 0x5196, 0x1314,
+ 0x5197, 0x0cba,
+ 0x5198, 0x293b,
+ 0x5199, 0x0f7f,
+ 0x519a, 0x293c,
+ 0x519b, 0x092b,
+ 0x519c, 0x0b6a,
+ 0x519d, 0x293d,
+ 0x51a0, 0x0733,
+ 0x51a1, 0x2940,
+ 0x51a2, 0x1315,
+ 0x51a3, 0x2941,
+ 0x51a4, 0x10ec,
+ 0x51a5, 0x1316,
+ 0x51a6, 0x2942,
+ 0x51ab, 0x130f,
+ 0x51ac, 0x05eb,
+ 0x51ad, 0x2947,
+ 0x51af, 0x0688,
+ 0x51b0, 0x0462,
+ 0x51b1, 0x1310,
+ 0x51b2, 0x050a,
+ 0x51b3, 0x0925,
+ 0x51b4, 0x2949,
+ 0x51b5, 0x0983,
+ 0x51b6, 0x1038,
+ 0x51b7, 0x09cf,
+ 0x51b8, 0x294a,
+ 0x51bb, 0x05f2,
+ 0x51bc, 0x1312,
+ 0x51bd, 0x1311,
+ 0x51be, 0x294d,
+ 0x51c0, 0x08ea,
+ 0x51c1, 0x294f,
+ 0x51c4, 0x0bff,
+ 0x51c5, 0x2952,
+ 0x51c6, 0x1219,
+ 0x51c7, 0x1313,
+ 0x51c8, 0x2953,
+ 0x51c9, 0x0a02,
+ 0x51ca, 0x2954,
+ 0x51cb, 0x05d3,
+ 0x51cc, 0x0a31,
+ 0x51cd, 0x1ecf,
+ 0x51ce, 0x2955,
+ 0x51cf, 0x0868,
+ 0x51d0, 0x2956,
+ 0x51d1, 0x0558,
+ 0x51d2, 0x2957,
+ 0x51db, 0x0a26,
+ 0x51dc, 0x2960,
+ 0x51dd, 0x0b60,
+ 0x51de, 0x2961,
+ 0x51e0, 0x082b,
+ 0x51e1, 0x064f,
+ 0x51e2, 0x2963,
+ 0x51e4, 0x068c,
+ 0x51e5, 0x2965,
+ 0x51eb, 0x1300,
+ 0x51ec, 0x296b,
+ 0x51ed, 0x0bdd,
+ 0x51ee, 0x296c,
+ 0x51ef, 0x093a,
+ 0x51f0, 0x07e0,
+ 0x51f1, 0x1fd9,
+ 0x51f2, 0x296d,
+ 0x51f3, 0x05ab,
+ 0x51f4, 0x296e,
+ 0x51f5, 0x1399,
+ 0x51f6, 0x0fa2,
+ 0x51f7, 0x296f,
+ 0x51f8, 0x0e6a,
+ 0x51f9, 0x03c7,
+ 0x51fa, 0x051b,
+ 0x51fb, 0x080c,
+ 0x51fc, 0x139a,
+ 0x51fd, 0x0766,
+ 0x51fe, 0x2970,
+ 0x51ff, 0x1127,
+ 0x5200, 0x0597,
+ 0x5201, 0x05d4,
+ 0x5202, 0x128c,
+ 0x5203, 0x0cab,
+ 0x5204, 0x2971,
+ 0x5206, 0x0673,
+ 0x5207, 0x0c4d,
+ 0x5208, 0x128d,
+ 0x5209, 0x2973,
+ 0x520a, 0x093c,
+ 0x520b, 0x2974,
+ 0x520d, 0x138b,
+ 0x520e, 0x128e,
+ 0x520f, 0x2976,
+ 0x5211, 0x0f97,
+ 0x5212, 0x07c3,
+ 0x5213, 0x2978,
+ 0x5216, 0x196e,
+ 0x5217, 0x0a19,
+ 0x5218, 0x0a3e,
+ 0x5219, 0x1135,
+ 0x521a, 0x06d0,
+ 0x521b, 0x0537,
+ 0x521c, 0x297b,
+ 0x521d, 0x051a,
+ 0x521e, 0x297c,
+ 0x5220, 0x0cf7,
+ 0x5221, 0x297e,
+ 0x5224, 0x0b91,
+ 0x5225, 0x2981,
+ 0x5228, 0x0b9a,
+ 0x5229, 0x09e6,
+ 0x522a, 0x2984,
+ 0x522b, 0x0459,
+ 0x522c, 0x2985,
+ 0x522d, 0x128f,
+ 0x522e, 0x0727,
+ 0x522f, 0x2986,
+ 0x5230, 0x059e,
+ 0x5231, 0x2987,
+ 0x5233, 0x1290,
+ 0x5234, 0x2989,
+ 0x5236, 0x11c5,
+ 0x5237, 0x0d97,
+ 0x5238, 0x0c8a,
+ 0x5239, 0x0ceb,
+ 0x523a, 0x054f,
+ 0x523b, 0x0959,
+ 0x523c, 0x298b,
+ 0x523d, 0x074d,
+ 0x523e, 0x298c,
+ 0x523f, 0x1291,
+ 0x5241, 0x0626,
+ 0x5242, 0x0834,
+ 0x5243, 0x0e3d,
+ 0x5244, 0x22c8,
+ 0x5245, 0x298d,
+ 0x5247, 0x2263,
+ 0x5248, 0x298f,
+ 0x524a, 0x0f64,
+ 0x524b, 0x2683,
+ 0x524c, 0x1293,
+ 0x524d, 0x0c2d,
+ 0x524e, 0x2991,
+ 0x5250, 0x0729,
+ 0x5251, 0x0874,
+ 0x5252, 0x2993,
+ 0x5254, 0x0e31,
+ 0x5255, 0x2995,
+ 0x5256, 0x0be9,
+ 0x5257, 0x2996,
+ 0x525b, 0x1f17,
+ 0x525c, 0x1296,
+ 0x525d, 0x299a,
+ 0x525e, 0x1294,
+ 0x525f, 0x299b,
+ 0x5261, 0x1295,
+ 0x5262, 0x299d,
+ 0x5265, 0x0409,
+ 0x5266, 0x29a0,
+ 0x5267, 0x0916,
+ 0x5268, 0x29a1,
+ 0x5269, 0x0d3a,
+ 0x526a, 0x0867,
+ 0x526b, 0x29a2,
+ 0x526e, 0x1f2b,
+ 0x526f, 0x06ac,
+ 0x5270, 0x29a5,
+ 0x5272, 0x06e9,
+ 0x5273, 0x29a7,
+ 0x5274, 0x22ca,
+ 0x5275, 0x1e99,
+ 0x5276, 0x29a8,
+ 0x527d, 0x1298,
+ 0x527e, 0x29af,
+ 0x527f, 0x089c,
+ 0x5280, 0x29b0,
+ 0x5281, 0x129a,
+ 0x5282, 0x1299,
+ 0x5283, 0x1f4f,
+ 0x5284, 0x29b1,
+ 0x5287, 0x1fcf,
+ 0x5288, 0x0bbd,
+ 0x5289, 0x2036,
+ 0x528a, 0x1f3a,
+ 0x528b, 0x29b4,
+ 0x528c, 0x22c9,
+ 0x528d, 0x1f99,
+ 0x528e, 0x29b5,
+ 0x5290, 0x129b,
+ 0x5291, 0x1f75,
+ 0x5292, 0x29b7,
+ 0x5293, 0x129c,
+ 0x5294, 0x29b8,
+ 0x529b, 0x09ef,
+ 0x529c, 0x29bf,
+ 0x529d, 0x0c8b,
+ 0x529e, 0x03f7,
+ 0x529f, 0x06ff,
+ 0x52a0, 0x0846,
+ 0x52a1, 0x0f00,
+ 0x52a2, 0x138d,
+ 0x52a3, 0x0a1c,
+ 0x52a4, 0x29c0,
+ 0x52a8, 0x05ee,
+ 0x52a9, 0x11f9,
+ 0x52aa, 0x0b6d,
+ 0x52ab, 0x08aa,
+ 0x52ac, 0x138e,
+ 0x52ae, 0x29c4,
+ 0x52b1, 0x09e3,
+ 0x52b2, 0x08d1,
+ 0x52b3, 0x09b8,
+ 0x52b4, 0x29c7,
+ 0x52be, 0x1390,
+ 0x52bf, 0x0d5d,
+ 0x52c0, 0x29d1,
+ 0x52c1, 0x1fbe,
+ 0x52c2, 0x29d2,
+ 0x52c3, 0x0471,
+ 0x52c4, 0x29d3,
+ 0x52c7, 0x10a7,
+ 0x52c8, 0x29d6,
+ 0x52c9, 0x0ae8,
+ 0x52ca, 0x29d7,
+ 0x52cb, 0x0fd4,
+ 0x52cc, 0x29d8,
+ 0x52d0, 0x1392,
+ 0x52d1, 0x29dc,
+ 0x52d2, 0x09c0,
+ 0x52d3, 0x29dd,
+ 0x52d5, 0x1ecd,
+ 0x52d6, 0x1393,
+ 0x52d7, 0x29df,
+ 0x52d8, 0x093e,
+ 0x52d9, 0x21a9,
+ 0x52da, 0x29e0,
+ 0x52db, 0x21e6,
+ 0x52dc, 0x29e1,
+ 0x52dd, 0x2127,
+ 0x52de, 0x2003,
+ 0x52df, 0x0b1f,
+ 0x52e0, 0x29e2,
+ 0x52e2, 0x2132,
+ 0x52e3, 0x29e4,
+ 0x52e4, 0x0c57,
+ 0x52e5, 0x29e5,
+ 0x52f0, 0x1394,
+ 0x52f1, 0x2323,
+ 0x52f2, 0x29f0,
+ 0x52f5, 0x2011,
+ 0x52f6, 0x29f3,
+ 0x52f8, 0x20f5,
+ 0x52f9, 0x12fc,
+ 0x52fa, 0x0d10,
+ 0x52fb, 0x29f5,
+ 0x52fe, 0x070d,
+ 0x52ff, 0x0eff,
+ 0x5300, 0x110b,
+ 0x5301, 0x29f8,
+ 0x5305, 0x0407,
+ 0x5306, 0x0555,
+ 0x5307, 0x29fc,
+ 0x5308, 0x0fa4,
+ 0x5309, 0x29fd,
+ 0x530d, 0x12fd,
+ 0x530e, 0x2a01,
+ 0x530f, 0x14b5,
+ 0x5310, 0x12ff,
+ 0x5311, 0x2a02,
+ 0x5315, 0x1266,
+ 0x5316, 0x07c4,
+ 0x5317, 0x041a,
+ 0x5318, 0x2a06,
+ 0x5319, 0x04fc,
+ 0x531a, 0x1284,
+ 0x531b, 0x2a07,
+ 0x531d, 0x1114,
+ 0x531e, 0x2a09,
+ 0x5320, 0x0884,
+ 0x5321, 0x097c,
+ 0x5322, 0x2a0b,
+ 0x5323, 0x0f28,
+ 0x5324, 0x2a0c,
+ 0x5326, 0x1286,
+ 0x5327, 0x2a0e,
+ 0x532a, 0x0668,
+ 0x532b, 0x2a11,
+ 0x532d, 0x22c5,
+ 0x532e, 0x1287,
+ 0x532f, 0x1f5e,
+ 0x5330, 0x2a13,
+ 0x5331, 0x22c6,
+ 0x5332, 0x2a14,
+ 0x5339, 0x0bc4,
+ 0x533a, 0x0c75,
+ 0x533b, 0x1044,
+ 0x533c, 0x2a1b,
+ 0x533e, 0x1288,
+ 0x533f, 0x0b47,
+ 0x5340, 0x20ef,
+ 0x5341, 0x0d45,
+ 0x5342, 0x2a1d,
+ 0x5343, 0x0c24,
+ 0x5344, 0x2a1e,
+ 0x5345, 0x125c,
+ 0x5346, 0x2a1f,
+ 0x5347, 0x0d36,
+ 0x5348, 0x0ef6,
+ 0x5349, 0x07f1,
+ 0x534a, 0x03f6,
+ 0x534b, 0x2a20,
+ 0x534e, 0x07bf,
+ 0x534f, 0x0f78,
+ 0x5350, 0x2a23,
+ 0x5351, 0x0419,
+ 0x5352, 0x1241,
+ 0x5353, 0x121c,
+ 0x5354, 0x21d0,
+ 0x5355, 0x0586,
+ 0x5356, 0x0a9b,
+ 0x5357, 0x0b32,
+ 0x5358, 0x2a24,
+ 0x535a, 0x0470,
+ 0x535b, 0x2a26,
+ 0x535c, 0x047e,
+ 0x535d, 0x2a27,
+ 0x535e, 0x044e,
+ 0x535f, 0x14fa,
+ 0x5360, 0x115d,
+ 0x5361, 0x0935,
+ 0x5362, 0x0a53,
+ 0x5363, 0x128b,
+ 0x5364, 0x0a58,
+ 0x5365, 0x2a28,
+ 0x5366, 0x128a,
+ 0x5367, 0x0ee3,
+ 0x5368, 0x2a29,
+ 0x5369, 0x1352,
+ 0x536a, 0x2a2a,
+ 0x536b, 0x0ecf,
+ 0x536c, 0x2a2b,
+ 0x536e, 0x126a,
+ 0x536f, 0x0ab3,
+ 0x5370, 0x1086,
+ 0x5371, 0x0eb2,
+ 0x5372, 0x2a2d,
+ 0x5373, 0x0827,
+ 0x5374, 0x0c8f,
+ 0x5375, 0x0a78,
+ 0x5376, 0x2a2e,
+ 0x5377, 0x091c,
+ 0x5378, 0x0f81,
+ 0x5379, 0x2a2f,
+ 0x537a, 0x1353,
+ 0x537b, 0x2a30,
+ 0x537f, 0x0c61,
+ 0x5380, 0x2a34,
+ 0x5382, 0x04cc,
+ 0x5383, 0x2a36,
+ 0x5384, 0x0631,
+ 0x5385, 0x0e4f,
+ 0x5386, 0x09e5,
+ 0x5387, 0x2a37,
+ 0x5389, 0x09e2,
+ 0x538a, 0x2a39,
+ 0x538b, 0x0fe2,
+ 0x538c, 0x100a,
+ 0x538d, 0x127d,
+ 0x538e, 0x2a3a,
+ 0x5395, 0x04a5,
+ 0x5396, 0x2a41,
+ 0x5398, 0x09d0,
+ 0x5399, 0x22c1,
+ 0x539a, 0x07a8,
+ 0x539b, 0x2a43,
+ 0x539d, 0x127e,
+ 0x539e, 0x2a45,
+ 0x539f, 0x10f0,
+ 0x53a0, 0x1e64,
+ 0x53a1, 0x2a46,
+ 0x53a2, 0x0f4e,
+ 0x53a3, 0x127f,
+ 0x53a4, 0x2a47,
+ 0x53a5, 0x1280,
+ 0x53a6, 0x0f30,
+ 0x53a7, 0x2a48,
+ 0x53a8, 0x051d,
+ 0x53a9, 0x08f6,
+ 0x53aa, 0x2a49,
+ 0x53ad, 0x21f9,
+ 0x53ae, 0x1281,
+ 0x53af, 0x2a4c,
+ 0x53b2, 0x2010,
+ 0x53b3, 0x2a4f,
+ 0x53b4, 0x22c2,
+ 0x53b5, 0x2a50,
+ 0x53b6, 0x139c,
+ 0x53b7, 0x2a51,
+ 0x53bb, 0x0c80,
+ 0x53bc, 0x2a55,
+ 0x53bf, 0x0f45,
+ 0x53c0, 0x2a58,
+ 0x53c1, 0x0cd9,
+ 0x53c2, 0x0495,
+ 0x53c3, 0x1e5a,
+ 0x53c4, 0x2a59,
+ 0x53c8, 0x10bb,
+ 0x53c9, 0x04ad,
+ 0x53ca, 0x0823,
+ 0x53cb, 0x10b6,
+ 0x53cc, 0x0da0,
+ 0x53cd, 0x0651,
+ 0x53ce, 0x2a5d,
+ 0x53d1, 0x063f,
+ 0x53d2, 0x2a60,
+ 0x53d4, 0x0d7c,
+ 0x53d5, 0x2a62,
+ 0x53d6, 0x0c7c,
+ 0x53d7, 0x0d73,
+ 0x53d8, 0x044d,
+ 0x53d9, 0x0fbb,
+ 0x53da, 0x2a63,
+ 0x53db, 0x0b92,
+ 0x53dc, 0x2a64,
+ 0x53df, 0x1395,
+ 0x53e0, 0x05df,
+ 0x53e1, 0x2a67,
+ 0x53e2, 0x1ea2,
+ 0x53e3, 0x0967,
+ 0x53e4, 0x071e,
+ 0x53e5, 0x0913,
+ 0x53e6, 0x0a36,
+ 0x53e7, 0x2a68,
+ 0x53e8, 0x14fe,
+ 0x53e9, 0x14fd,
+ 0x53ea, 0x11ba,
+ 0x53eb, 0x08a1,
+ 0x53ec, 0x117a,
+ 0x53ed, 0x03d3,
+ 0x53ee, 0x05e2,
+ 0x53ef, 0x0956,
+ 0x53f0, 0x0dfb,
+ 0x53f1, 0x14fb,
+ 0x53f2, 0x0d4e,
+ 0x53f3, 0x10b7,
+ 0x53f4, 0x2a69,
+ 0x53f5, 0x1285,
+ 0x53f6, 0x103d,
+ 0x53f7, 0x077c,
+ 0x53f8, 0x0db3,
+ 0x53f9, 0x0e11,
+ 0x53fa, 0x2a6a,
+ 0x53fb, 0x14ff,
+ 0x53fc, 0x05d1,
+ 0x53fd, 0x14fc,
+ 0x53fe, 0x2a6b,
+ 0x5400, 0x2a6d,
+ 0x5401, 0x10da,
+ 0x5402, 0x2a6e,
+ 0x5403, 0x04f9,
+ 0x5404, 0x06f2,
+ 0x5405, 0x2a6f,
+ 0x5406, 0x1502,
+ 0x5407, 0x2a70,
+ 0x5408, 0x0786,
+ 0x5409, 0x081d,
+ 0x540a, 0x05d6,
+ 0x540b, 0x2a71,
+ 0x540c, 0x0e5d,
+ 0x540d, 0x0b00,
+ 0x540e, 0x07aa,
+ 0x540f, 0x09df,
+ 0x5410, 0x0e73,
+ 0x5411, 0x0f5f,
+ 0x5412, 0x1500,
+ 0x5413, 0x0f32,
+ 0x5414, 0x2a72,
+ 0x5415, 0x0a67,
+ 0x5416, 0x1501,
+ 0x5417, 0x0a97,
+ 0x5418, 0x2a73,
+ 0x541b, 0x092c,
+ 0x541c, 0x2a76,
+ 0x541d, 0x0a28,
+ 0x541e, 0x0e7d,
+ 0x541f, 0x107e,
+ 0x5420, 0x066a,
+ 0x5421, 0x1509,
+ 0x5422, 0x2a77,
+ 0x5423, 0x150c,
+ 0x5424, 0x2a78,
+ 0x5426, 0x068e,
+ 0x5427, 0x03d4,
+ 0x5428, 0x0615,
+ 0x5429, 0x0671,
+ 0x542a, 0x2a7a,
+ 0x542b, 0x0763,
+ 0x542c, 0x0e50,
+ 0x542d, 0x0961,
+ 0x542e, 0x0da6,
+ 0x542f, 0x0c13,
+ 0x5430, 0x2a7b,
+ 0x5431, 0x11a7,
+ 0x5432, 0x150d,
+ 0x5433, 0x2a7c,
+ 0x5434, 0x0ef1,
+ 0x5435, 0x04d8,
+ 0x5436, 0x2a7d,
+ 0x5438, 0x0f0b,
+ 0x5439, 0x0538,
+ 0x543a, 0x2a7f,
+ 0x543b, 0x0ed6,
+ 0x543c, 0x07a7,
+ 0x543d, 0x2a80,
+ 0x543e, 0x0ef0,
+ 0x543f, 0x2a81,
+ 0x5440, 0x0fe6,
+ 0x5441, 0x2a82,
+ 0x5443, 0x1508,
+ 0x5444, 0x2a84,
+ 0x5446, 0x0577,
+ 0x5447, 0x2a86,
+ 0x5448, 0x04ef,
+ 0x5449, 0x2a87,
+ 0x544a, 0x06e1,
+ 0x544b, 0x1503,
+ 0x544c, 0x2a88,
+ 0x5450, 0x0b28,
+ 0x5451, 0x2a8c,
+ 0x5452, 0x1504,
+ 0x5455, 0x0b7c,
+ 0x5456, 0x1507,
+ 0x5457, 0x150a,
+ 0x5458, 0x10f4,
+ 0x5459, 0x150b,
+ 0x545a, 0x2a8d,
+ 0x545b, 0x0c37,
+ 0x545c, 0x0ee7,
+ 0x545d, 0x2a8e,
+ 0x5462, 0x0b3b,
+ 0x5463, 0x2a93,
+ 0x5464, 0x1512,
+ 0x5465, 0x2a94,
+ 0x5466, 0x1517,
+ 0x5467, 0x2a95,
+ 0x5468, 0x11db,
+ 0x5469, 0x2a96,
+ 0x5471, 0x1511,
+ 0x5472, 0x1522,
+ 0x5473, 0x0ec5,
+ 0x5474, 0x2a9e,
+ 0x5475, 0x077e,
+ 0x5476, 0x1516,
+ 0x5477, 0x1510,
+ 0x5478, 0x0b9f,
+ 0x5479, 0x2a9f,
+ 0x547b, 0x0d24,
+ 0x547c, 0x07ab,
+ 0x547d, 0x0b01,
+ 0x547e, 0x2aa1,
+ 0x5480, 0x0906,
+ 0x5481, 0x2aa3,
+ 0x5482, 0x150e,
+ 0x5483, 0x2aa4,
+ 0x5484, 0x1515,
+ 0x5485, 0x2aa5,
+ 0x5486, 0x0b99,
+ 0x5487, 0x2aa6,
+ 0x548b, 0x1147,
+ 0x548c, 0x0784,
+ 0x548d, 0x2aaa,
+ 0x548e, 0x08fb,
+ 0x548f, 0x10a2,
+ 0x5490, 0x06bb,
+ 0x5491, 0x2aab,
+ 0x5492, 0x11e3,
+ 0x5493, 0x2aac,
+ 0x5494, 0x150f,
+ 0x5495, 0x0717,
+ 0x5496, 0x0934,
+ 0x5497, 0x2aad,
+ 0x5499, 0x0a45,
+ 0x549a, 0x1513,
+ 0x549c, 0x2aaf,
+ 0x549d, 0x1518,
+ 0x549e, 0x2ab0,
+ 0x54a3, 0x1523,
+ 0x54a4, 0x152d,
+ 0x54a5, 0x2ab5,
+ 0x54a6, 0x151f,
+ 0x54a7, 0x151e,
+ 0x54a8, 0x1226,
+ 0x54a9, 0x152b,
+ 0x54ab, 0x1767,
+ 0x54ac, 0x102e,
+ 0x54ad, 0x151a,
+ 0x54ae, 0x2ab6,
+ 0x54af, 0x0936,
+ 0x54b0, 0x2ab7,
+ 0x54b1, 0x111e,
+ 0x54b2, 0x2ab8,
+ 0x54b3, 0x0955,
+ 0x54b4, 0x151c,
+ 0x54b5, 0x2ab9,
+ 0x54b8, 0x0f39,
+ 0x54b9, 0x2abc,
+ 0x54bb, 0x1525,
+ 0x54bc, 0x236d,
+ 0x54bd, 0x0ff3,
+ 0x54be, 0x2abe,
+ 0x54bf, 0x1526,
+ 0x54c0, 0x03b2,
+ 0x54c1, 0x0bd6,
+ 0x54c2, 0x151b,
+ 0x54c3, 0x2abf,
+ 0x54c4, 0x079c,
+ 0x54c5, 0x2ac0,
+ 0x54c6, 0x061e,
+ 0x54c7, 0x0e8c,
+ 0x54c8, 0x0757,
+ 0x54c9, 0x1118,
+ 0x54ca, 0x2ac1,
+ 0x54cc, 0x1527,
+ 0x54cd, 0x0f59,
+ 0x54ce, 0x03b0,
+ 0x54cf, 0x152f,
+ 0x54d0, 0x1519,
+ 0x54d1, 0x0fef,
+ 0x54d2, 0x151d,
+ 0x54d3, 0x1520,
+ 0x54d5, 0x1524,
+ 0x54d6, 0x2ac3,
+ 0x54d7, 0x07be,
+ 0x54d8, 0x2ac4,
+ 0x54d9, 0x1528,
+ 0x54db, 0x2ac5,
+ 0x54dc, 0x152a,
+ 0x54dd, 0x152e,
+ 0x54de, 0x1530,
+ 0x54df, 0x1099,
+ 0x54e0, 0x2ac6,
+ 0x54e1, 0x2247,
+ 0x54e2, 0x2ac7,
+ 0x54e5, 0x06e2,
+ 0x54e6, 0x0b77,
+ 0x54e7, 0x1532,
+ 0x54e8, 0x0d13,
+ 0x54e9, 0x09f1,
+ 0x54ea, 0x0b27,
+ 0x54eb, 0x2aca,
+ 0x54ed, 0x096b,
+ 0x54ee, 0x0f65,
+ 0x54ef, 0x2acc,
+ 0x54f2, 0x117d,
+ 0x54f3, 0x1536,
+ 0x54f4, 0x2acf,
+ 0x54fa, 0x047f,
+ 0x54fb, 0x2ad5,
+ 0x54fc, 0x0796,
+ 0x54fd, 0x1534,
+ 0x54fe, 0x2ad6,
+ 0x54ff, 0x1391,
+ 0x5500, 0x2ad7,
+ 0x5501, 0x100d,
+ 0x5502, 0x2ad8,
+ 0x5504, 0x236c,
+ 0x5505, 0x2ada,
+ 0x5506, 0x0de9,
+ 0x5507, 0x0540,
+ 0x5508, 0x2adb,
+ 0x5509, 0x03b1,
+ 0x550a, 0x2adc,
+ 0x550f, 0x1539,
+ 0x5510, 0x0e19,
+ 0x5511, 0x153a,
+ 0x5512, 0x2ae1,
+ 0x5514, 0x1535,
+ 0x5515, 0x2ae3,
+ 0x551b, 0x1531,
+ 0x551c, 0x2ae9,
+ 0x5520, 0x1533,
+ 0x5521, 0x2aed,
+ 0x5522, 0x1537,
+ 0x5524, 0x07d2,
+ 0x5525, 0x2aee,
+ 0x5527, 0x153b,
+ 0x5528, 0x2af0,
+ 0x552a, 0x153c,
+ 0x552b, 0x2af2,
+ 0x552c, 0x07b8,
+ 0x552d, 0x2af3,
+ 0x552e, 0x0d72,
+ 0x552f, 0x0eb7,
+ 0x5530, 0x154d,
+ 0x5531, 0x04cf,
+ 0x5532, 0x2af4,
+ 0x5533, 0x154c,
+ 0x5534, 0x2af5,
+ 0x5537, 0x1547,
+ 0x5538, 0x2af8,
+ 0x553c, 0x1546,
+ 0x553d, 0x2afc,
+ 0x553e, 0x0e8a,
+ 0x553f, 0x1544,
+ 0x5540, 0x2afd,
+ 0x5541, 0x1542,
+ 0x5542, 0x2afe,
+ 0x5543, 0x095d,
+ 0x5544, 0x1221,
+ 0x5545, 0x2aff,
+ 0x5546, 0x0d05,
+ 0x5547, 0x2b00,
+ 0x5549, 0x1540,
+ 0x554a, 0x03ac,
+ 0x554b, 0x2b02,
+ 0x554f, 0x219c,
+ 0x5550, 0x1545,
+ 0x5551, 0x2b06,
+ 0x5553, 0x20c9,
+ 0x5554, 0x2b08,
+ 0x5555, 0x1543,
+ 0x5556, 0x1548,
+ 0x5557, 0x2b09,
+ 0x555c, 0x154e,
+ 0x555d, 0x2b0e,
+ 0x555e, 0x21f0,
+ 0x555f, 0x2b0f,
+ 0x5561, 0x0665,
+ 0x5562, 0x2b11,
+ 0x5564, 0x0bc0,
+ 0x5565, 0x0cef,
+ 0x5566, 0x099d,
+ 0x5567, 0x153d,
+ 0x5568, 0x2b13,
+ 0x556a, 0x0b7f,
+ 0x556b, 0x2b15,
+ 0x556c, 0x127a,
+ 0x556d, 0x1541,
+ 0x556e, 0x0b59,
+ 0x556f, 0x2b16,
+ 0x5575, 0x1549,
+ 0x5578, 0x0f70,
+ 0x5579, 0x2b1c,
+ 0x557b, 0x155a,
+ 0x557c, 0x0e37,
+ 0x557d, 0x2b1e,
+ 0x557e, 0x1557,
+ 0x557f, 0x2b1f,
+ 0x5580, 0x0933,
+ 0x5581, 0x1555,
+ 0x5582, 0x0ec8,
+ 0x5583, 0x1551,
+ 0x5584, 0x0cff,
+ 0x5585, 0x2b20,
+ 0x5587, 0x0999,
+ 0x5588, 0x1554,
+ 0x5589, 0x07a4,
+ 0x558a, 0x0767,
+ 0x558b, 0x154f,
+ 0x558c, 0x2b22,
+ 0x558f, 0x153e,
+ 0x5590, 0x2b25,
+ 0x5591, 0x1559,
+ 0x5592, 0x2b26,
+ 0x5594, 0x155e,
+ 0x5595, 0x2b28,
+ 0x5598, 0x0530,
+ 0x5599, 0x155f,
+ 0x559a, 0x2b2b,
+ 0x559c, 0x0f1f,
+ 0x559d, 0x077f,
+ 0x559e, 0x2b2d,
+ 0x559f, 0x1556,
+ 0x55a0, 0x2b2e,
+ 0x55a7, 0x0fc5,
+ 0x55a8, 0x2b35,
+ 0x55aa, 0x210b,
+ 0x55ab, 0x2b37,
+ 0x55ac, 0x20de,
+ 0x55ad, 0x2b38,
+ 0x55ae, 0x1eaa,
+ 0x55af, 0x2b39,
+ 0x55b1, 0x1552,
+ 0x55b2, 0x222c,
+ 0x55b3, 0x113e,
+ 0x55b4, 0x2b3b,
+ 0x55b5, 0x153f,
+ 0x55b6, 0x2b3c,
+ 0x55b7, 0x0ba8,
+ 0x55b8, 0x2b3d,
+ 0x55b9, 0x1553,
+ 0x55ba, 0x2b3e,
+ 0x55bb, 0x10dc,
+ 0x55bc, 0x2b3f,
+ 0x55bd, 0x155c,
+ 0x55bf, 0x2b40,
+ 0x55c4, 0x156a,
+ 0x55c5, 0x0fac,
+ 0x55c6, 0x20d8,
+ 0x55c7, 0x22c0,
+ 0x55c8, 0x2b45,
+ 0x55c9, 0x1562,
+ 0x55ca, 0x2b46,
+ 0x55cc, 0x156f,
+ 0x55ce, 0x206f,
+ 0x55cf, 0x2b48,
+ 0x55d1, 0x1564,
+ 0x55d2, 0x1550,
+ 0x55d3, 0x0cdd,
+ 0x55d4, 0x1567,
+ 0x55d5, 0x2b4a,
+ 0x55d6, 0x1558,
+ 0x55d7, 0x2b4b,
+ 0x55da, 0x21a1,
+ 0x55db, 0x2b4e,
+ 0x55dc, 0x0d5f,
+ 0x55dd, 0x1569,
+ 0x55de, 0x2b4f,
+ 0x55df, 0x155b,
+ 0x55e0, 0x2b50,
+ 0x55e1, 0x0eda,
+ 0x55e2, 0x2b51,
+ 0x55e3, 0x0db8,
+ 0x55e4, 0x1573,
+ 0x55e5, 0x156c,
+ 0x55e6, 0x1568,
+ 0x55e7, 0x2b52,
+ 0x55e8, 0x1571,
+ 0x55e9, 0x2379,
+ 0x55ea, 0x1560,
+ 0x55eb, 0x1565,
+ 0x55ed, 0x2b53,
+ 0x55ef, 0x156b,
+ 0x55f0, 0x2b55,
+ 0x55f2, 0x156d,
+ 0x55f4, 0x2b57,
+ 0x55f5, 0x1572,
+ 0x55f6, 0x2372,
+ 0x55f7, 0x1561,
+ 0x55f8, 0x2b58,
+ 0x55fd, 0x0dc9,
+ 0x55fe, 0x157b,
+ 0x55ff, 0x2b5d,
+ 0x5600, 0x157c,
+ 0x5601, 0x1578,
+ 0x5602, 0x2b5e,
+ 0x5606, 0x216a,
+ 0x5607, 0x2b62,
+ 0x5608, 0x1576,
+ 0x5609, 0x0841,
+ 0x560a, 0x2b63,
+ 0x560c, 0x1577,
+ 0x560d, 0x237c,
+ 0x560e, 0x06bd,
+ 0x560f, 0x127b,
+ 0x5610, 0x2b65,
+ 0x5614, 0x20b0,
+ 0x5615, 0x2b69,
+ 0x5616, 0x237a,
+ 0x5617, 0x1e74,
+ 0x5618, 0x0fb5,
+ 0x5619, 0x2b6a,
+ 0x561b, 0x0a96,
+ 0x561c, 0x2377,
+ 0x561d, 0x2b6c,
+ 0x561e, 0x1575,
+ 0x561f, 0x1563,
+ 0x5620, 0x2b6d,
+ 0x5623, 0x157a,
+ 0x5624, 0x1579,
+ 0x5625, 0x2b70,
+ 0x5627, 0x157d,
+ 0x5628, 0x2b72,
+ 0x5629, 0x1f4c,
+ 0x562a, 0x2b73,
+ 0x562c, 0x1582,
+ 0x562d, 0x157e,
+ 0x562e, 0x2378,
+ 0x562f, 0x21cf,
+ 0x5630, 0x2368,
+ 0x5631, 0x11f5,
+ 0x5632, 0x04d5,
+ 0x5633, 0x2b75,
+ 0x5634, 0x1249,
+ 0x5635, 0x2371,
+ 0x5636, 0x0db0,
+ 0x5637, 0x2b76,
+ 0x5638, 0x2369,
+ 0x5639, 0x1580,
+ 0x563a, 0x2b77,
+ 0x563b, 0x0f0a,
+ 0x563c, 0x2b78,
+ 0x563f, 0x0790,
+ 0x5640, 0x2b7b,
+ 0x5641, 0x2674,
+ 0x5642, 0x2b7c,
+ 0x564c, 0x1587,
+ 0x564d, 0x1583,
+ 0x564e, 0x1034,
+ 0x564f, 0x2b86,
+ 0x5654, 0x1588,
+ 0x5655, 0x2b8b,
+ 0x5657, 0x1581,
+ 0x5658, 0x157f,
+ 0x5659, 0x1585,
+ 0x565a, 0x2b8d,
+ 0x565c, 0x1586,
+ 0x565d, 0x236f,
+ 0x565e, 0x2b8f,
+ 0x5660, 0x2370,
+ 0x5661, 0x2b91,
+ 0x5662, 0x1584,
+ 0x5663, 0x2b92,
+ 0x5664, 0x158a,
+ 0x5665, 0x2376,
+ 0x5666, 0x2373,
+ 0x5667, 0x2b93,
+ 0x5668, 0x0c16,
+ 0x5669, 0x1262,
+ 0x566a, 0x112e,
+ 0x566b, 0x158c,
+ 0x566c, 0x0d60,
+ 0x566d, 0x2b94,
+ 0x566f, 0x237f,
+ 0x5670, 0x2b96,
+ 0x5671, 0x158b,
+ 0x5672, 0x2374,
+ 0x5673, 0x2b97,
+ 0x5674, 0x20b5,
+ 0x5675, 0x2b98,
+ 0x5676, 0x06bc,
+ 0x5677, 0x2b99,
+ 0x5678, 0x1edb,
+ 0x5679, 0x2672,
+ 0x567a, 0x2b9a,
+ 0x567b, 0x158d,
+ 0x567d, 0x2b9b,
+ 0x5680, 0x236e,
+ 0x5681, 0x2b9e,
+ 0x5685, 0x158f,
+ 0x5686, 0x1589,
+ 0x5687, 0x21b7,
+ 0x5688, 0x2ba2,
+ 0x568c, 0x2375,
+ 0x568d, 0x2ba6,
+ 0x568e, 0x0776,
+ 0x568f, 0x0e3a,
+ 0x5690, 0x2ba7,
+ 0x5693, 0x1590,
+ 0x5694, 0x2baa,
+ 0x5695, 0x2382,
+ 0x5696, 0x2bab,
+ 0x5699, 0x209e,
+ 0x569a, 0x2bae,
+ 0x56a3, 0x0f66,
+ 0x56a4, 0x2bb7,
+ 0x56a6, 0x236b,
+ 0x56a7, 0x2bb9,
+ 0x56a8, 0x2039,
+ 0x56a9, 0x2bba,
+ 0x56ae, 0x269f,
+ 0x56af, 0x1591,
+ 0x56b0, 0x2bbf,
+ 0x56b3, 0x237d,
+ 0x56b4, 0x21f5,
+ 0x56b5, 0x2bc2,
+ 0x56b6, 0x2381,
+ 0x56b7, 0x0c9d,
+ 0x56b8, 0x2bc3,
+ 0x56bc, 0x0891,
+ 0x56bd, 0x2bc7,
+ 0x56c0, 0x237b,
+ 0x56c1, 0x237e,
+ 0x56c2, 0x21cc,
+ 0x56c3, 0x2bca,
+ 0x56c5, 0x22db,
+ 0x56c6, 0x2bcc,
+ 0x56c8, 0x236a,
+ 0x56c9, 0x2689,
+ 0x56ca, 0x0b35,
+ 0x56cb, 0x2bce,
+ 0x56cc, 0x2697,
+ 0x56cd, 0x2bcf,
+ 0x56d1, 0x22a1,
+ 0x56d2, 0x2bd3,
+ 0x56d4, 0x1592,
+ 0x56d5, 0x2bd5,
+ 0x56d7, 0x1593,
+ 0x56d8, 0x2bd7,
+ 0x56da, 0x0c71,
+ 0x56db, 0x0db9,
+ 0x56dc, 0x2bd9,
+ 0x56dd, 0x1594,
+ 0x56de, 0x07ed,
+ 0x56df, 0x126c,
+ 0x56e0, 0x1079,
+ 0x56e1, 0x1595,
+ 0x56e2, 0x0e76,
+ 0x56e3, 0x2bda,
+ 0x56e4, 0x0619,
+ 0x56e5, 0x2bdb,
+ 0x56eb, 0x1597,
+ 0x56ec, 0x2be1,
+ 0x56ed, 0x10f3,
+ 0x56ee, 0x2be2,
+ 0x56f0, 0x0992,
+ 0x56f1, 0x0554,
+ 0x56f2, 0x2be4,
+ 0x56f4, 0x0eb6,
+ 0x56f5, 0x1596,
+ 0x56f6, 0x2be6,
+ 0x56f9, 0x1598,
+ 0x56fa, 0x0725,
+ 0x56fb, 0x2be9,
+ 0x56fd, 0x0753,
+ 0x56fe, 0x0e6d,
+ 0x56ff, 0x1599,
+ 0x5700, 0x2beb,
+ 0x5703, 0x0bf3,
+ 0x5704, 0x159a,
+ 0x5705, 0x2bee,
+ 0x5706, 0x10f5,
+ 0x5707, 0x2383,
+ 0x5708, 0x0c81,
+ 0x5709, 0x159c,
+ 0x570a, 0x159b,
+ 0x570b, 0x1f3d,
+ 0x570c, 0x2bef,
+ 0x570d, 0x218f,
+ 0x570e, 0x2bf0,
+ 0x5712, 0x2246,
+ 0x5713, 0x2248,
+ 0x5714, 0x2bf4,
+ 0x5716, 0x217e,
+ 0x5717, 0x2bf6,
+ 0x5718, 0x2180,
+ 0x5719, 0x2bf7,
+ 0x571c, 0x159d,
+ 0x571d, 0x2bfa,
+ 0x571f, 0x0e72,
+ 0x5720, 0x2bfc,
+ 0x5723, 0x0d3c,
+ 0x5724, 0x2bff,
+ 0x5728, 0x111d,
+ 0x5729, 0x13a7,
+ 0x572a, 0x13a9,
+ 0x572b, 0x2c03,
+ 0x572c, 0x13a8,
+ 0x572d, 0x0740,
+ 0x572e, 0x13ac,
+ 0x5730, 0x05b9,
+ 0x5731, 0x2c04,
+ 0x5733, 0x13aa,
+ 0x5734, 0x2c06,
+ 0x5739, 0x13ab,
+ 0x573a, 0x04c6,
+ 0x573b, 0x13af,
+ 0x573c, 0x2c0b,
+ 0x573e, 0x080d,
+ 0x573f, 0x2c0d,
+ 0x5740, 0x11b6,
+ 0x5741, 0x2c0e,
+ 0x5742, 0x13b0,
+ 0x5743, 0x2c0f,
+ 0x5747, 0x0928,
+ 0x5748, 0x2c13,
+ 0x574a, 0x0658,
+ 0x574b, 0x2c15,
+ 0x574c, 0x13a0,
+ 0x574d, 0x0e01,
+ 0x574e, 0x093f,
+ 0x574f, 0x07ca,
+ 0x5750, 0x1255,
+ 0x5751, 0x0960,
+ 0x5752, 0x2c16,
+ 0x5757, 0x0976,
+ 0x5758, 0x2c1b,
+ 0x575a, 0x0854,
+ 0x575b, 0x0e06,
+ 0x575c, 0x13ae,
+ 0x575d, 0x03de,
+ 0x575e, 0x0efa,
+ 0x575f, 0x0675,
+ 0x5760, 0x1216,
+ 0x5761, 0x0be1,
+ 0x5762, 0x2c1d,
+ 0x5764, 0x098f,
+ 0x5765, 0x2c1f,
+ 0x5766, 0x0e0c,
+ 0x5767, 0x2c20,
+ 0x5768, 0x13b7,
+ 0x5769, 0x13b1,
+ 0x576a, 0x0bd9,
+ 0x576b, 0x13b3,
+ 0x576c, 0x2c21,
+ 0x576d, 0x13b8,
+ 0x576e, 0x2c22,
+ 0x576f, 0x0bb8,
+ 0x5770, 0x2c23,
+ 0x5773, 0x13ba,
+ 0x5774, 0x2c26,
+ 0x5776, 0x13b9,
+ 0x5777, 0x094d,
+ 0x5778, 0x2c28,
+ 0x577b, 0x13b6,
+ 0x577c, 0x13b5,
+ 0x577d, 0x2c2b,
+ 0x5782, 0x053c,
+ 0x5783, 0x0997,
+ 0x5784, 0x0a49,
+ 0x5785, 0x13b2,
+ 0x5786, 0x13b4,
+ 0x5787, 0x2c30,
+ 0x578b, 0x0f98,
+ 0x578c, 0x13bd,
+ 0x578d, 0x2c34,
+ 0x5792, 0x09c8,
+ 0x5793, 0x13c2,
+ 0x5794, 0x2c39,
+ 0x579b, 0x0621,
+ 0x579c, 0x2c40,
+ 0x57a0, 0x13c3,
+ 0x57a1, 0x13a2,
+ 0x57a2, 0x0711,
+ 0x57a3, 0x10ee,
+ 0x57a4, 0x13bc,
+ 0x57a5, 0x2c44,
+ 0x57a6, 0x095e,
+ 0x57a7, 0x13c0,
+ 0x57a8, 0x2c45,
+ 0x57a9, 0x13a1,
+ 0x57aa, 0x2c46,
+ 0x57ab, 0x05c7,
+ 0x57ac, 0x2c47,
+ 0x57ad, 0x13bb,
+ 0x57ae, 0x0972,
+ 0x57af, 0x2c48,
+ 0x57b2, 0x13be,
+ 0x57b3, 0x2c4b,
+ 0x57b4, 0x13c1,
+ 0x57b5, 0x2c4c,
+ 0x57b8, 0x13c9,
+ 0x57b9, 0x2c4f,
+ 0x57c2, 0x06fa,
+ 0x57c3, 0x03ae,
+ 0x57c4, 0x2c58,
+ 0x57cb, 0x0a98,
+ 0x57cc, 0x2c5f,
+ 0x57ce, 0x04ec,
+ 0x57cf, 0x13bf,
+ 0x57d0, 0x2c61,
+ 0x57d2, 0x13c8,
+ 0x57d3, 0x2c63,
+ 0x57d4, 0x0bf1,
+ 0x57d5, 0x13c4,
+ 0x57d6, 0x2c64,
+ 0x57d8, 0x13c5,
+ 0x57d9, 0x13c7,
+ 0x57da, 0x13c6,
+ 0x57db, 0x2c66,
+ 0x57dd, 0x13ce,
+ 0x57de, 0x2c68,
+ 0x57df, 0x10d7,
+ 0x57e0, 0x0481,
+ 0x57e1, 0x232a,
+ 0x57e2, 0x2c69,
+ 0x57e4, 0x13cd,
+ 0x57e5, 0x2c6b,
+ 0x57ed, 0x13d2,
+ 0x57ee, 0x2c73,
+ 0x57ef, 0x13cb,
+ 0x57f0, 0x2c74,
+ 0x57f4, 0x13ca,
+ 0x57f5, 0x2c78,
+ 0x57f7, 0x228b,
+ 0x57f8, 0x13cc,
+ 0x57f9, 0x0ba1,
+ 0x57fa, 0x080e,
+ 0x57fb, 0x2c7a,
+ 0x57fd, 0x13d1,
+ 0x57fe, 0x2c7c,
+ 0x5800, 0x13d3,
+ 0x5801, 0x2c7e,
+ 0x5802, 0x0e16,
+ 0x5803, 0x2c7f,
+ 0x5805, 0x1f85,
+ 0x5806, 0x0610,
+ 0x5807, 0x144c,
+ 0x5808, 0x2c81,
+ 0x580a, 0x2325,
+ 0x580b, 0x13cf,
+ 0x580c, 0x2c83,
+ 0x580d, 0x13d0,
+ 0x580e, 0x2c84,
+ 0x5811, 0x0c32,
+ 0x5812, 0x2c87,
+ 0x5815, 0x0628,
+ 0x5816, 0x232c,
+ 0x5817, 0x2c8a,
+ 0x5819, 0x13d5,
+ 0x581a, 0x2c8c,
+ 0x581d, 0x232e,
+ 0x581e, 0x13d4,
+ 0x581f, 0x2c8f,
+ 0x5820, 0x13d7,
+ 0x5821, 0x040d,
+ 0x5822, 0x2c90,
+ 0x5824, 0x05ad,
+ 0x5825, 0x2c92,
+ 0x582a, 0x093d,
+ 0x582b, 0x2c97,
+ 0x582f, 0x2205,
+ 0x5830, 0x1008,
+ 0x5831, 0x1e38,
+ 0x5832, 0x2c9b,
+ 0x5834, 0x1e73,
+ 0x5835, 0x0601,
+ 0x5836, 0x2c9d,
+ 0x5844, 0x13d6,
+ 0x5845, 0x2cab,
+ 0x584a, 0x1fe3,
+ 0x584b, 0x2339,
+ 0x584c, 0x0def,
+ 0x584d, 0x19a3,
+ 0x584e, 0x2cb0,
+ 0x584f, 0x232b,
+ 0x5850, 0x2cb1,
+ 0x5851, 0x0dd1,
+ 0x5852, 0x232d,
+ 0x5853, 0x2cb2,
+ 0x5854, 0x0df3,
+ 0x5855, 0x2cb3,
+ 0x5857, 0x217f,
+ 0x5858, 0x0e14,
+ 0x5859, 0x2cb5,
+ 0x585e, 0x0cd6,
+ 0x585f, 0x2cba,
+ 0x5862, 0x21a7,
+ 0x5863, 0x2cbd,
+ 0x5864, 0x232f,
+ 0x5865, 0x13d8,
+ 0x5866, 0x2cbe,
+ 0x586b, 0x0e41,
+ 0x586c, 0x13d9,
+ 0x586d, 0x2cc3,
+ 0x5875, 0x1e7d,
+ 0x5876, 0x2ccb,
+ 0x5879, 0x20d6,
+ 0x587a, 0x2cce,
+ 0x587e, 0x13a3,
+ 0x587f, 0x2cd2,
+ 0x5880, 0x13dd,
+ 0x5881, 0x13da,
+ 0x5882, 0x2cd3,
+ 0x5883, 0x08e2,
+ 0x5884, 0x2cd4,
+ 0x5885, 0x0d92,
+ 0x5886, 0x2cd5,
+ 0x5889, 0x13db,
+ 0x588a, 0x1ec2,
+ 0x588b, 0x2cd8,
+ 0x5892, 0x0d03,
+ 0x5893, 0x0b1c,
+ 0x5894, 0x2cdf,
+ 0x5899, 0x0c3a,
+ 0x589a, 0x13dc,
+ 0x589b, 0x2ce4,
+ 0x589c, 0x22b2,
+ 0x589d, 0x2ce5,
+ 0x589e, 0x1139,
+ 0x589f, 0x0fb1,
+ 0x58a0, 0x2ce6,
+ 0x58a8, 0x0b0e,
+ 0x58a9, 0x0614,
+ 0x58aa, 0x2cee,
+ 0x58ae, 0x1edf,
+ 0x58af, 0x2cf2,
+ 0x58b3, 0x1ef9,
+ 0x58b4, 0x2cf6,
+ 0x58bb, 0x20d9,
+ 0x58bc, 0x13a4,
+ 0x58bd, 0x2cfd,
+ 0x58be, 0x1fdd,
+ 0x58bf, 0x2cfe,
+ 0x58c1, 0x0443,
+ 0x58c2, 0x2d00,
+ 0x58c5, 0x13a5,
+ 0x58c6, 0x2d03,
+ 0x58c7, 0x2167,
+ 0x58c8, 0x2d04,
+ 0x58d1, 0x13a6,
+ 0x58d2, 0x2d0d,
+ 0x58d3, 0x21ed,
+ 0x58d4, 0x2d0e,
+ 0x58d5, 0x0775,
+ 0x58d6, 0x2d0f,
+ 0x58d8, 0x2007,
+ 0x58d9, 0x2326,
+ 0x58da, 0x2329,
+ 0x58db, 0x2d11,
+ 0x58de, 0x1f52,
+ 0x58df, 0x203b,
+ 0x58e0, 0x2328,
+ 0x58e1, 0x2d14,
+ 0x58e2, 0x2327,
+ 0x58e3, 0x2d15,
+ 0x58e4, 0x0c9b,
+ 0x58e5, 0x2d16,
+ 0x58e9, 0x1e2b,
+ 0x58ea, 0x2d1a,
+ 0x58eb, 0x0d56,
+ 0x58ec, 0x0ca4,
+ 0x58ed, 0x2d1b,
+ 0x58ee, 0x1210,
+ 0x58ef, 0x22ae,
+ 0x58f0, 0x0d32,
+ 0x58f1, 0x2d1c,
+ 0x58f3, 0x0954,
+ 0x58f4, 0x2d1e,
+ 0x58f6, 0x07af,
+ 0x58f7, 0x2d20,
+ 0x58f9, 0x1043,
+ 0x58fa, 0x1f49,
+ 0x58fb, 0x2d22,
+ 0x58fd, 0x2138,
+ 0x58fe, 0x2d24,
+ 0x5900, 0x2d26,
+ 0x5902, 0x161c,
+ 0x5903, 0x2d28,
+ 0x5904, 0x0529,
+ 0x5905, 0x2d29,
+ 0x5907, 0x0421,
+ 0x5908, 0x2d2b,
+ 0x590d, 0x06af,
+ 0x590e, 0x2d30,
+ 0x590f, 0x0f31,
+ 0x5910, 0x2d31,
+ 0x5914, 0x12fb,
+ 0x5915, 0x0f13,
+ 0x5916, 0x0e93,
+ 0x5917, 0x2d35,
+ 0x5919, 0x1301,
+ 0x591a, 0x061f,
+ 0x591b, 0x2d37,
+ 0x591c, 0x1040,
+ 0x591d, 0x2d38,
+ 0x591f, 0x0714,
+ 0x5920, 0x2d3a,
+ 0x5922, 0x2081,
+ 0x5923, 0x2d3c,
+ 0x5924, 0x161b,
+ 0x5925, 0x1619,
+ 0x5926, 0x2d3d,
+ 0x5927, 0x0576,
+ 0x5928, 0x2d3e,
+ 0x5929, 0x0e3f,
+ 0x592a, 0x0dfe,
+ 0x592b, 0x068f,
+ 0x592c, 0x2d3f,
+ 0x592d, 0x1268,
+ 0x592e, 0x1014,
+ 0x592f, 0x0772,
+ 0x5930, 0x2d40,
+ 0x5931, 0x0d3e,
+ 0x5932, 0x2d41,
+ 0x5934, 0x0e68,
+ 0x5935, 0x2d43,
+ 0x5937, 0x104b,
+ 0x5938, 0x0971,
+ 0x5939, 0x0843,
+ 0x593a, 0x0620,
+ 0x593b, 0x2d45,
+ 0x593c, 0x14af,
+ 0x593d, 0x2d46,
+ 0x593e, 0x1f7c,
+ 0x593f, 0x2d47,
+ 0x5941, 0x14b0,
+ 0x5942, 0x138c,
+ 0x5943, 0x2d49,
+ 0x5944, 0x1002,
+ 0x5945, 0x2d4a,
+ 0x5947, 0x0c05,
+ 0x5948, 0x0b31,
+ 0x5949, 0x068b,
+ 0x594a, 0x2d4c,
+ 0x594b, 0x0679,
+ 0x594c, 0x2d4d,
+ 0x594e, 0x0989,
+ 0x594f, 0x123d,
+ 0x5950, 0x2d4f,
+ 0x5951, 0x0c14,
+ 0x5952, 0x2d50,
+ 0x5954, 0x0425,
+ 0x5955, 0x14b2,
+ 0x5956, 0x0882,
+ 0x5957, 0x0e2a,
+ 0x5958, 0x14b4,
+ 0x5959, 0x2d52,
+ 0x595a, 0x14b3,
+ 0x595b, 0x2d53,
+ 0x5960, 0x05cd,
+ 0x5961, 0x2d58,
+ 0x5962, 0x0d16,
+ 0x5963, 0x2d59,
+ 0x5965, 0x03cd,
+ 0x5966, 0x2d5b,
+ 0x5969, 0x235b,
+ 0x596a, 0x1ede,
+ 0x596b, 0x2d5e,
+ 0x596c, 0x1fa2,
+ 0x596d, 0x2d5f,
+ 0x596e, 0x1efa,
+ 0x596f, 0x2d60,
+ 0x5973, 0x0b6f,
+ 0x5974, 0x0b6c,
+ 0x5975, 0x2d64,
+ 0x5976, 0x0b2f,
+ 0x5977, 0x2d65,
+ 0x5978, 0x085c,
+ 0x5979, 0x0df2,
+ 0x597a, 0x2d66,
+ 0x597d, 0x077a,
+ 0x597e, 0x2d69,
+ 0x5981, 0x1775,
+ 0x5982, 0x0cc2,
+ 0x5983, 0x1776,
+ 0x5984, 0x0eae,
+ 0x5985, 0x2d6c,
+ 0x5986, 0x120e,
+ 0x5987, 0x06b9,
+ 0x5988, 0x0a8f,
+ 0x5989, 0x2d6d,
+ 0x598a, 0x0cac,
+ 0x598b, 0x2d6e,
+ 0x598d, 0x1777,
+ 0x598e, 0x2d70,
+ 0x5992, 0x0609,
+ 0x5993, 0x083e,
+ 0x5994, 0x2d74,
+ 0x5996, 0x1026,
+ 0x5997, 0x177b,
+ 0x5998, 0x2d76,
+ 0x5999, 0x0af3,
+ 0x599a, 0x2d77,
+ 0x599d, 0x22ad,
+ 0x599e, 0x177e,
+ 0x599f, 0x2d7a,
+ 0x59a3, 0x177a,
+ 0x59a4, 0x177f,
+ 0x59a5, 0x0e88,
+ 0x59a6, 0x2d7e,
+ 0x59a8, 0x065e,
+ 0x59a9, 0x1778,
+ 0x59ab, 0x177d,
+ 0x59ac, 0x2d80,
+ 0x59ae, 0x0b40,
+ 0x59af, 0x1782,
+ 0x59b0, 0x2d82,
+ 0x59b2, 0x1781,
+ 0x59b3, 0x2d84,
+ 0x59b9, 0x0ac8,
+ 0x59ba, 0x2d8a,
+ 0x59bb, 0x0bfd,
+ 0x59bc, 0x2d8b,
+ 0x59be, 0x1784,
+ 0x59bf, 0x2d8d,
+ 0x59c6, 0x0b1a,
+ 0x59c7, 0x2d94,
+ 0x59ca, 0x177c,
+ 0x59cb, 0x0d53,
+ 0x59cc, 0x2d97,
+ 0x59d0, 0x08b4,
+ 0x59d1, 0x071c,
+ 0x59d2, 0x1780,
+ 0x59d3, 0x0fa0,
+ 0x59d4, 0x0ebe,
+ 0x59d5, 0x2d9b,
+ 0x59d7, 0x1783,
+ 0x59d8, 0x178a,
+ 0x59d9, 0x2d9d,
+ 0x59da, 0x102d,
+ 0x59db, 0x2d9e,
+ 0x59dc, 0x087b,
+ 0x59dd, 0x1787,
+ 0x59de, 0x2d9f,
+ 0x59e3, 0x1789,
+ 0x59e4, 0x2da4,
+ 0x59e5, 0x09bc,
+ 0x59e6, 0x2da5,
+ 0x59e8, 0x1053,
+ 0x59e9, 0x2da7,
+ 0x59ec, 0x081a,
+ 0x59ed, 0x2daa,
+ 0x59f9, 0x178b,
+ 0x59fa, 0x2db6,
+ 0x59fb, 0x107d,
+ 0x59fc, 0x2db7,
+ 0x59ff, 0x1228,
+ 0x5a00, 0x2dba,
+ 0x5a01, 0x0eaf,
+ 0x5a02, 0x2dbb,
+ 0x5a03, 0x0e8f,
+ 0x5a04, 0x0a4d,
+ 0x5a05, 0x1785,
+ 0x5a07, 0x0890,
+ 0x5a08, 0x1788,
+ 0x5a09, 0x178d,
+ 0x5a0a, 0x2dbc,
+ 0x5a0c, 0x178c,
+ 0x5a0d, 0x2dbe,
+ 0x5a11, 0x1790,
+ 0x5a12, 0x2dc2,
+ 0x5a13, 0x1792,
+ 0x5a14, 0x2dc3,
+ 0x5a18, 0x0b52,
+ 0x5a19, 0x2dc7,
+ 0x5a1c, 0x0b2b,
+ 0x5a1d, 0x2dca,
+ 0x5a1f, 0x0919,
+ 0x5a20, 0x0d28,
+ 0x5a21, 0x2dcc,
+ 0x5a23, 0x1791,
+ 0x5a24, 0x2dce,
+ 0x5a25, 0x062f,
+ 0x5a26, 0x2dcf,
+ 0x5a29, 0x0ae9,
+ 0x5a2a, 0x2dd2,
+ 0x5a31, 0x10ce,
+ 0x5a32, 0x178e,
+ 0x5a33, 0x2dd9,
+ 0x5a34, 0x178f,
+ 0x5a35, 0x2dda,
+ 0x5a36, 0x0c7d,
+ 0x5a37, 0x2ddb,
+ 0x5a3c, 0x1797,
+ 0x5a3d, 0x2de0,
+ 0x5a40, 0x1793,
+ 0x5a41, 0x203f,
+ 0x5a42, 0x2de3,
+ 0x5a46, 0x0be4,
+ 0x5a47, 0x2de7,
+ 0x5a49, 0x0ea2,
+ 0x5a4a, 0x1795,
+ 0x5a4b, 0x2de9,
+ 0x5a55, 0x1796,
+ 0x5a56, 0x2df3,
+ 0x5a5a, 0x07fe,
+ 0x5a5b, 0x2df7,
+ 0x5a62, 0x1798,
+ 0x5a63, 0x2dfe,
+ 0x5a66, 0x1f0e,
+ 0x5a67, 0x1794,
+ 0x5a68, 0x2e01,
+ 0x5a6a, 0x09a2,
+ 0x5a6b, 0x2e03,
+ 0x5a6d, 0x23f9,
+ 0x5a6e, 0x2e05,
+ 0x5a74, 0x1089,
+ 0x5a75, 0x1799,
+ 0x5a76, 0x0d2d,
+ 0x5a77, 0x179d,
+ 0x5a78, 0x2e0b,
+ 0x5a7a, 0x179e,
+ 0x5a7b, 0x2e0d,
+ 0x5a7f, 0x0fc1,
+ 0x5a80, 0x2e11,
+ 0x5a92, 0x0ac2,
+ 0x5a93, 0x2e23,
+ 0x5a9a, 0x0ac9,
+ 0x5a9b, 0x179c,
+ 0x5a9c, 0x2e2a,
+ 0x5aa7, 0x23fc,
+ 0x5aa8, 0x2e35,
+ 0x5aaa, 0x179b,
+ 0x5aab, 0x2e37,
+ 0x5ab2, 0x17a1,
+ 0x5ab3, 0x0f1e,
+ 0x5ab4, 0x2e3e,
+ 0x5ab5, 0x19a4,
+ 0x5ab6, 0x2e3f,
+ 0x5ab8, 0x17a4,
+ 0x5ab9, 0x2e41,
+ 0x5abd, 0x2069,
+ 0x5abe, 0x179f,
+ 0x5abf, 0x2e45,
+ 0x5ac1, 0x0851,
+ 0x5ac2, 0x0ce2,
+ 0x5ac3, 0x2e47,
+ 0x5ac9, 0x0828,
+ 0x5aca, 0x2e4d,
+ 0x5acc, 0x0f40,
+ 0x5acd, 0x2e4f,
+ 0x5ad2, 0x17a2,
+ 0x5ad3, 0x2e54,
+ 0x5ad4, 0x17a3,
+ 0x5ad5, 0x2e55,
+ 0x5ad6, 0x17a8,
+ 0x5ad7, 0x23f7,
+ 0x5ad8, 0x17aa,
+ 0x5ad9, 0x2e56,
+ 0x5adc, 0x17ab,
+ 0x5add, 0x2e59,
+ 0x5ae0, 0x17a5,
+ 0x5ae1, 0x05b6,
+ 0x5ae2, 0x2e5c,
+ 0x5ae3, 0x17a6,
+ 0x5ae4, 0x2e5d,
+ 0x5ae6, 0x17a9,
+ 0x5ae7, 0x2e5f,
+ 0x5ae9, 0x0b3e,
+ 0x5aea, 0x2e61,
+ 0x5aeb, 0x17a0,
+ 0x5aec, 0x2e62,
+ 0x5af1, 0x17a7,
+ 0x5af2, 0x2e67,
+ 0x5af5, 0x23f6,
+ 0x5af6, 0x2e6a,
+ 0x5afb, 0x23fd,
+ 0x5afc, 0x2e6f,
+ 0x5b00, 0x23f8,
+ 0x5b01, 0x2e73,
+ 0x5b08, 0x23fa,
+ 0x5b09, 0x17ac,
+ 0x5b0a, 0x2e7a,
+ 0x5b0b, 0x23fe,
+ 0x5b0c, 0x1fa8,
+ 0x5b0d, 0x2e7b,
+ 0x5b16, 0x17ae,
+ 0x5b17, 0x17ad,
+ 0x5b18, 0x2e84,
+ 0x5b19, 0x2401,
+ 0x5b1a, 0x2e85,
+ 0x5b21, 0x23ff,
+ 0x5b22, 0x2e8c,
+ 0x5b2a, 0x2400,
+ 0x5b2b, 0x2e94,
+ 0x5b30, 0x2221,
+ 0x5b31, 0x2e99,
+ 0x5b32, 0x17af,
+ 0x5b33, 0x2e9a,
+ 0x5b34, 0x130c,
+ 0x5b35, 0x2e9b,
+ 0x5b37, 0x17b0,
+ 0x5b38, 0x2122,
+ 0x5b39, 0x2e9d,
+ 0x5b40, 0x17b1,
+ 0x5b41, 0x2ea4,
+ 0x5b4c, 0x23fb,
+ 0x5b4d, 0x2eaf,
+ 0x5b50, 0x1230,
+ 0x5b51, 0x17b7,
+ 0x5b52, 0x2eb2,
+ 0x5b53, 0x17b8,
+ 0x5b54, 0x0964,
+ 0x5b55, 0x1113,
+ 0x5b56, 0x2eb3,
+ 0x5b57, 0x1233,
+ 0x5b58, 0x0569,
+ 0x5b59, 0x0de4,
+ 0x5b5a, 0x17b4,
+ 0x5b5b, 0x1279,
+ 0x5b5c, 0x122b,
+ 0x5b5d, 0x0f6d,
+ 0x5b5e, 0x2eb4,
+ 0x5b5f, 0x0ad4,
+ 0x5b60, 0x2eb5,
+ 0x5b62, 0x17b9,
+ 0x5b63, 0x0831,
+ 0x5b64, 0x071b,
+ 0x5b65, 0x17b5,
+ 0x5b66, 0x0fd0,
+ 0x5b67, 0x2eb7,
+ 0x5b69, 0x0759,
+ 0x5b6a, 0x0a76,
+ 0x5b6b, 0x215a,
+ 0x5b6c, 0x1261,
+ 0x5b6d, 0x2eb9,
+ 0x5b70, 0x0d82,
+ 0x5b71, 0x176a,
+ 0x5b72, 0x2ebc,
+ 0x5b73, 0x17b6,
+ 0x5b74, 0x2ebd,
+ 0x5b75, 0x0692,
+ 0x5b76, 0x2ebe,
+ 0x5b78, 0x21e5,
+ 0x5b79, 0x2ec0,
+ 0x5b7a, 0x0cc1,
+ 0x5b7b, 0x2ec1,
+ 0x5b7d, 0x0b58,
+ 0x5b7e, 0x2ec3,
+ 0x5b7f, 0x2057,
+ 0x5b80, 0x172e,
+ 0x5b81, 0x0b61,
+ 0x5b82, 0x2ec4,
+ 0x5b83, 0x0df1,
+ 0x5b84, 0x172f,
+ 0x5b85, 0x114d,
+ 0x5b86, 0x2ec5,
+ 0x5b87, 0x10d3,
+ 0x5b88, 0x0d6f,
+ 0x5b89, 0x03bd,
+ 0x5b8a, 0x2ec6,
+ 0x5b8b, 0x0dc3,
+ 0x5b8c, 0x0e9b,
+ 0x5b8d, 0x2ec7,
+ 0x5b8f, 0x07a1,
+ 0x5b90, 0x2ec9,
+ 0x5b93, 0x1731,
+ 0x5b94, 0x2ecc,
+ 0x5b95, 0x1730,
+ 0x5b96, 0x2ecd,
+ 0x5b97, 0x1237,
+ 0x5b98, 0x0732,
+ 0x5b99, 0x11e5,
+ 0x5b9a, 0x05e7,
+ 0x5b9b, 0x0ea1,
+ 0x5b9c, 0x1052,
+ 0x5b9d, 0x040f,
+ 0x5b9e, 0x0d4c,
+ 0x5b9f, 0x2ece,
+ 0x5ba0, 0x050d,
+ 0x5ba1, 0x0d2c,
+ 0x5ba2, 0x095a,
+ 0x5ba3, 0x0fc6,
+ 0x5ba4, 0x0d69,
+ 0x5ba5, 0x1732,
+ 0x5ba6, 0x07d7,
+ 0x5ba7, 0x2ecf,
+ 0x5baa, 0x0f49,
+ 0x5bab, 0x0705,
+ 0x5bac, 0x2ed2,
+ 0x5bb0, 0x111a,
+ 0x5bb1, 0x2ed6,
+ 0x5bb3, 0x075d,
+ 0x5bb4, 0x1010,
+ 0x5bb5, 0x0f69,
+ 0x5bb6, 0x0845,
+ 0x5bb7, 0x2ed8,
+ 0x5bb8, 0x1733,
+ 0x5bb9, 0x0cb8,
+ 0x5bba, 0x2ed9,
+ 0x5bbd, 0x097a,
+ 0x5bbe, 0x045f,
+ 0x5bbf, 0x0dd3,
+ 0x5bc0, 0x2edc,
+ 0x5bc2, 0x0838,
+ 0x5bc3, 0x2ede,
+ 0x5bc4, 0x0837,
+ 0x5bc5, 0x1081,
+ 0x5bc6, 0x0ae1,
+ 0x5bc7, 0x0969,
+ 0x5bc8, 0x2edf,
+ 0x5bcc, 0x06b6,
+ 0x5bcd, 0x2ee3,
+ 0x5bd0, 0x0ac7,
+ 0x5bd1, 0x2ee6,
+ 0x5bd2, 0x0765,
+ 0x5bd3, 0x10e5,
+ 0x5bd4, 0x2ee7,
+ 0x5bdd, 0x0c5b,
+ 0x5bde, 0x0b12,
+ 0x5bdf, 0x04b3,
+ 0x5be0, 0x2ef0,
+ 0x5be1, 0x072a,
+ 0x5be2, 0x20e5,
+ 0x5be3, 0x2ef1,
+ 0x5be4, 0x1737,
+ 0x5be5, 0x0a11,
+ 0x5be6, 0x212f,
+ 0x5be7, 0x20a3,
+ 0x5be8, 0x1150,
+ 0x5be9, 0x2121,
+ 0x5bea, 0x2ef2,
+ 0x5beb, 0x21d4,
+ 0x5bec, 0x1fe5,
+ 0x5bed, 0x2ef3,
+ 0x5bee, 0x1738,
+ 0x5bef, 0x2ef4,
+ 0x5bf0, 0x173a,
+ 0x5bf1, 0x2ef5,
+ 0x5bf5, 0x1e8a,
+ 0x5bf6, 0x1e37,
+ 0x5bf7, 0x2ef9,
+ 0x5bf8, 0x056a,
+ 0x5bf9, 0x0613,
+ 0x5bfa, 0x0db7,
+ 0x5bfb, 0x0fd9,
+ 0x5bfc, 0x059d,
+ 0x5bfd, 0x2efa,
+ 0x5bff, 0x0d70,
+ 0x5c00, 0x2efc,
+ 0x5c01, 0x067f,
+ 0x5c02, 0x2efd,
+ 0x5c04, 0x0d1d,
+ 0x5c05, 0x2eff,
+ 0x5c06, 0x087c,
+ 0x5c07, 0x1f9e,
+ 0x5c08, 0x22a6,
+ 0x5c09, 0x0ecd,
+ 0x5c0a, 0x124d,
+ 0x5c0b, 0x21e8,
+ 0x5c0c, 0x2f00,
+ 0x5c0d, 0x1eda,
+ 0x5c0e, 0x1eb9,
+ 0x5c0f, 0x0f6c,
+ 0x5c10, 0x2f01,
+ 0x5c11, 0x0d12,
+ 0x5c12, 0x2f02,
+ 0x5c14, 0x063a,
+ 0x5c15, 0x17b2,
+ 0x5c16, 0x0855,
+ 0x5c17, 0x2f04,
+ 0x5c18, 0x04e3,
+ 0x5c19, 0x2f05,
+ 0x5c1a, 0x0d09,
+ 0x5c1b, 0x2f06,
+ 0x5c1c, 0x17b3,
+ 0x5c1d, 0x04c7,
+ 0x5c1e, 0x2f07,
+ 0x5c22, 0x14b6,
+ 0x5c23, 0x2f0b,
+ 0x5c24, 0x10ad,
+ 0x5c25, 0x14b7,
+ 0x5c26, 0x2f0c,
+ 0x5c27, 0x1029,
+ 0x5c28, 0x2f0d,
+ 0x5c2c, 0x14b8,
+ 0x5c2d, 0x2f11,
+ 0x5c31, 0x08fc,
+ 0x5c32, 0x2f15,
+ 0x5c34, 0x14b9,
+ 0x5c35, 0x2f17,
+ 0x5c37, 0x235c,
+ 0x5c38, 0x0d43,
+ 0x5c39, 0x1083,
+ 0x5c3a, 0x0504,
+ 0x5c3b, 0x1766,
+ 0x5c3c, 0x0b44,
+ 0x5c3d, 0x08d0,
+ 0x5c3e, 0x0ec1,
+ 0x5c3f, 0x0b55,
+ 0x5c40, 0x0905,
+ 0x5c41, 0x0bc7,
+ 0x5c42, 0x04aa,
+ 0x5c43, 0x2f19,
+ 0x5c45, 0x0902,
+ 0x5c46, 0x2f1b,
+ 0x5c48, 0x0c79,
+ 0x5c49, 0x0e3e,
+ 0x5c4a, 0x08bd,
+ 0x5c4b, 0x0eec,
+ 0x5c4c, 0x2f1d,
+ 0x5c4e, 0x0d51,
+ 0x5c4f, 0x0be0,
+ 0x5c50, 0x1768,
+ 0x5c51, 0x0f87,
+ 0x5c52, 0x2f1f,
+ 0x5c55, 0x115a,
+ 0x5c56, 0x2f22,
+ 0x5c59, 0x1769,
+ 0x5c5a, 0x2f25,
+ 0x5c5e, 0x0d8b,
+ 0x5c5f, 0x2f29,
+ 0x5c60, 0x0e71,
+ 0x5c61, 0x0a6c,
+ 0x5c62, 0x2050,
+ 0x5c63, 0x176b,
+ 0x5c64, 0x1e67,
+ 0x5c65, 0x0a6b,
+ 0x5c66, 0x176c,
+ 0x5c67, 0x2f2a,
+ 0x5c68, 0x23f4,
+ 0x5c69, 0x2f2b,
+ 0x5c6c, 0x213e,
+ 0x5c6d, 0x2f2e,
+ 0x5c6e, 0x1774,
+ 0x5c6f, 0x0e7e,
+ 0x5c70, 0x2f2f,
+ 0x5c71, 0x0cf6,
+ 0x5c72, 0x2f30,
+ 0x5c79, 0x1060,
+ 0x5c7a, 0x15ac,
+ 0x5c7b, 0x2f37,
+ 0x5c7f, 0x10d1,
+ 0x5c80, 0x2f3b,
+ 0x5c81, 0x0ddf,
+ 0x5c82, 0x0c10,
+ 0x5c83, 0x2f3c,
+ 0x5c88, 0x15b0,
+ 0x5c89, 0x2f41,
+ 0x5c8c, 0x15ab,
+ 0x5c8d, 0x15ad,
+ 0x5c8e, 0x2f44,
+ 0x5c90, 0x15ae,
+ 0x5c91, 0x15b3,
+ 0x5c92, 0x2f46,
+ 0x5c94, 0x04b4,
+ 0x5c95, 0x2f48,
+ 0x5c96, 0x15af,
+ 0x5c97, 0x06d5,
+ 0x5c98, 0x15b1,
+ 0x5c9a, 0x15b4,
+ 0x5c9b, 0x059b,
+ 0x5c9c, 0x15b5,
+ 0x5c9d, 0x2f49,
+ 0x5ca1, 0x1f16,
+ 0x5ca2, 0x15b7,
+ 0x5ca3, 0x15bc,
+ 0x5ca4, 0x2f4d,
+ 0x5ca9, 0x0ffb,
+ 0x5caa, 0x2f52,
+ 0x5cab, 0x15ba,
+ 0x5cac, 0x15b9,
+ 0x5cad, 0x0a34,
+ 0x5cae, 0x2f53,
+ 0x5cb1, 0x15bb,
+ 0x5cb2, 0x2f56,
+ 0x5cb3, 0x1103,
+ 0x5cb4, 0x2f57,
+ 0x5cb5, 0x15b6,
+ 0x5cb6, 0x2f58,
+ 0x5cb7, 0x15be,
+ 0x5cb8, 0x03c1,
+ 0x5cb9, 0x2f59,
+ 0x5cbd, 0x15b8,
+ 0x5cbe, 0x2f5d,
+ 0x5cbf, 0x0986,
+ 0x5cc0, 0x2f5e,
+ 0x5cc1, 0x15bd,
+ 0x5cc2, 0x2f5f,
+ 0x5cc4, 0x15bf,
+ 0x5cc5, 0x2f61,
+ 0x5ccb, 0x15c2,
+ 0x5ccc, 0x2f67,
+ 0x5cd2, 0x15c0,
+ 0x5cd3, 0x2f6d,
+ 0x5cd9, 0x11c4,
+ 0x5cda, 0x2f73,
+ 0x5ce1, 0x0f2c,
+ 0x5ce2, 0x2f7a,
+ 0x5ce4, 0x15c1,
+ 0x5ce5, 0x15c3,
+ 0x5ce6, 0x0a74,
+ 0x5ce7, 0x2f7c,
+ 0x5ce8, 0x062a,
+ 0x5ce9, 0x2f7d,
+ 0x5cea, 0x10dd,
+ 0x5ceb, 0x2f7e,
+ 0x5ced, 0x0c4a,
+ 0x5cee, 0x2f80,
+ 0x5cf0, 0x0682,
+ 0x5cf1, 0x2f82,
+ 0x5cf4, 0x2389,
+ 0x5cf5, 0x2f85,
+ 0x5cf6, 0x1eb7,
+ 0x5cf7, 0x2f86,
+ 0x5cfb, 0x092d,
+ 0x5cfc, 0x2f8a,
+ 0x5cfd, 0x21b4,
+ 0x5cfe, 0x2f8b,
+ 0x5d00, 0x2f8d,
+ 0x5d02, 0x15c4,
+ 0x5d04, 0x2f8f,
+ 0x5d06, 0x15cb,
+ 0x5d07, 0x050c,
+ 0x5d08, 0x2f91,
+ 0x5d0d, 0x238f,
+ 0x5d0e, 0x0c08,
+ 0x5d0f, 0x2f96,
+ 0x5d14, 0x0561,
+ 0x5d15, 0x2f9b,
+ 0x5d16, 0x0feb,
+ 0x5d17, 0x1f1a,
+ 0x5d18, 0x2f9c,
+ 0x5d1b, 0x15cc,
+ 0x5d1c, 0x2f9f,
+ 0x5d1e, 0x15ca,
+ 0x5d1f, 0x2fa1,
+ 0x5d24, 0x15c9,
+ 0x5d25, 0x2fa6,
+ 0x5d26, 0x15c7,
+ 0x5d27, 0x15c6,
+ 0x5d28, 0x2fa7,
+ 0x5d29, 0x0429,
+ 0x5d2a, 0x2fa8,
+ 0x5d2c, 0x238b,
+ 0x5d2d, 0x1159,
+ 0x5d2e, 0x15c8,
+ 0x5d2f, 0x2faa,
+ 0x5d34, 0x15cf,
+ 0x5d35, 0x2faf,
+ 0x5d3d, 0x15d0,
+ 0x5d3e, 0x15ce,
+ 0x5d3f, 0x2fb7,
+ 0x5d47, 0x1b22,
+ 0x5d48, 0x2fbf,
+ 0x5d4a, 0x15d7,
+ 0x5d4b, 0x15d6,
+ 0x5d4c, 0x0c33,
+ 0x5d4d, 0x2fc1,
+ 0x5d50, 0x238a,
+ 0x5d51, 0x2fc4,
+ 0x5d58, 0x15cd,
+ 0x5d59, 0x2fcb,
+ 0x5d5b, 0x15d2,
+ 0x5d5c, 0x2fcd,
+ 0x5d5d, 0x15d4,
+ 0x5d5e, 0x2fce,
+ 0x5d69, 0x15d8,
+ 0x5d6a, 0x2fd9,
+ 0x5d6b, 0x15d5,
+ 0x5d6c, 0x15d1,
+ 0x5d6d, 0x2fda,
+ 0x5d6f, 0x15d3,
+ 0x5d70, 0x2fdc,
+ 0x5d74, 0x15d9,
+ 0x5d75, 0x2fe0,
+ 0x5d81, 0x2391,
+ 0x5d82, 0x15da,
+ 0x5d83, 0x2fec,
+ 0x5d84, 0x2271,
+ 0x5d85, 0x2fed,
+ 0x5d87, 0x2388,
+ 0x5d88, 0x2fef,
+ 0x5d97, 0x238e,
+ 0x5d98, 0x2ffe,
+ 0x5d99, 0x15db,
+ 0x5d9a, 0x2fff,
+ 0x5d9d, 0x15dc,
+ 0x5d9e, 0x3002,
+ 0x5da0, 0x238d,
+ 0x5da1, 0x3004,
+ 0x5da7, 0x238c,
+ 0x5da8, 0x300a,
+ 0x5db7, 0x15de,
+ 0x5db8, 0x2390,
+ 0x5db9, 0x3019,
+ 0x5dba, 0x2033,
+ 0x5dbb, 0x301a,
+ 0x5dbc, 0x223c,
+ 0x5dbd, 0x301b,
+ 0x5dc5, 0x15df,
+ 0x5dc6, 0x3023,
+ 0x5dcb, 0x1fe9,
+ 0x5dcc, 0x3028,
+ 0x5dcd, 0x0eb0,
+ 0x5dce, 0x3029,
+ 0x5dd2, 0x2055,
+ 0x5dd3, 0x302d,
+ 0x5dd4, 0x2392,
+ 0x5dd5, 0x302e,
+ 0x5ddb, 0x1815,
+ 0x5ddc, 0x3034,
+ 0x5ddd, 0x052b,
+ 0x5dde, 0x11dc,
+ 0x5ddf, 0x3035,
+ 0x5de1, 0x0fdb,
+ 0x5de2, 0x04d7,
+ 0x5de3, 0x3037,
+ 0x5de5, 0x06fd,
+ 0x5de6, 0x1250,
+ 0x5de7, 0x0c46,
+ 0x5de8, 0x090d,
+ 0x5de9, 0x0707,
+ 0x5dea, 0x3039,
+ 0x5deb, 0x0ee6,
+ 0x5dec, 0x303a,
+ 0x5dee, 0x04b5,
+ 0x5def, 0x139f,
+ 0x5df0, 0x2324,
+ 0x5df1, 0x082d,
+ 0x5df2, 0x1058,
+ 0x5df3, 0x0dbd,
+ 0x5df4, 0x03d8,
+ 0x5df5, 0x303c,
+ 0x5df7, 0x0f5c,
+ 0x5df8, 0x303e,
+ 0x5dfd, 0x12f7,
+ 0x5dfe, 0x08be,
+ 0x5dff, 0x3043,
+ 0x5e00, 0x3044,
+ 0x5e01, 0x043b,
+ 0x5e02, 0x0d67,
+ 0x5e03, 0x0483,
+ 0x5e04, 0x3045,
+ 0x5e05, 0x0d9c,
+ 0x5e06, 0x0648,
+ 0x5e07, 0x3046,
+ 0x5e08, 0x0d3d,
+ 0x5e09, 0x3047,
+ 0x5e0c, 0x0f10,
+ 0x5e0d, 0x304a,
+ 0x5e0f, 0x159e,
+ 0x5e10, 0x116b,
+ 0x5e11, 0x15a1,
+ 0x5e12, 0x304c,
+ 0x5e14, 0x15a0,
+ 0x5e15, 0x0b82,
+ 0x5e16, 0x0e4e,
+ 0x5e17, 0x304e,
+ 0x5e18, 0x09fa,
+ 0x5e19, 0x159f,
+ 0x5e1a, 0x11e2,
+ 0x5e1b, 0x0476,
+ 0x5e1c, 0x11c3,
+ 0x5e1d, 0x05bc,
+ 0x5e1e, 0x304f,
+ 0x5e25, 0x2143,
+ 0x5e26, 0x057b,
+ 0x5e27, 0x11a0,
+ 0x5e28, 0x3056,
+ 0x5e2b, 0x2129,
+ 0x5e2c, 0x3059,
+ 0x5e2d, 0x0f1c,
+ 0x5e2e, 0x03fa,
+ 0x5e2f, 0x305a,
+ 0x5e31, 0x15a2,
+ 0x5e32, 0x305c,
+ 0x5e33, 0x2277,
+ 0x5e34, 0x305d,
+ 0x5e36, 0x1ea7,
+ 0x5e37, 0x15a5,
+ 0x5e38, 0x04c8,
+ 0x5e39, 0x305f,
+ 0x5e3b, 0x15a3,
+ 0x5e3d, 0x0ab6,
+ 0x5e3e, 0x3061,
+ 0x5e40, 0x2285,
+ 0x5e41, 0x3063,
+ 0x5e42, 0x0ae2,
+ 0x5e43, 0x2384,
+ 0x5e44, 0x15a6,
+ 0x5e45, 0x0696,
+ 0x5e46, 0x3064,
+ 0x5e4c, 0x07e4,
+ 0x5e4d, 0x306a,
+ 0x5e54, 0x15a7,
+ 0x5e55, 0x0b1e,
+ 0x5e56, 0x3071,
+ 0x5e57, 0x2387,
+ 0x5e58, 0x2386,
+ 0x5e59, 0x3072,
+ 0x5e5b, 0x15a8,
+ 0x5e5c, 0x3074,
+ 0x5e5e, 0x15a9,
+ 0x5e5f, 0x2290,
+ 0x5e60, 0x3076,
+ 0x5e61, 0x15aa,
+ 0x5e62, 0x0534,
+ 0x5e63, 0x1e44,
+ 0x5e64, 0x3077,
+ 0x5e6b, 0x1e32,
+ 0x5e6c, 0x2385,
+ 0x5e6d, 0x307e,
+ 0x5e72, 0x06c4,
+ 0x5e73, 0x0bdc,
+ 0x5e74, 0x0b4d,
+ 0x5e75, 0x3083,
+ 0x5e76, 0x0469,
+ 0x5e77, 0x3084,
+ 0x5e78, 0x0f9d,
+ 0x5e79, 0x1f13,
+ 0x5e7a, 0x1813,
+ 0x5e7b, 0x07d8,
+ 0x5e7c, 0x10bc,
+ 0x5e7d, 0x10a9,
+ 0x5e7e, 0x1f73,
+ 0x5e7f, 0x073c,
+ 0x5e80, 0x1631,
+ 0x5e81, 0x3085,
+ 0x5e84, 0x120c,
+ 0x5e85, 0x3088,
+ 0x5e86, 0x0c69,
+ 0x5e87, 0x043c,
+ 0x5e88, 0x3089,
+ 0x5e8a, 0x0535,
+ 0x5e8b, 0x1633,
+ 0x5e8c, 0x308b,
+ 0x5e8f, 0x0fbd,
+ 0x5e90, 0x0a55,
+ 0x5e91, 0x1632,
+ 0x5e92, 0x308e,
+ 0x5e93, 0x096f,
+ 0x5e94, 0x108b,
+ 0x5e95, 0x05b8,
+ 0x5e96, 0x1634,
+ 0x5e97, 0x05cb,
+ 0x5e98, 0x308f,
+ 0x5e99, 0x0af2,
+ 0x5e9a, 0x06f8,
+ 0x5e9b, 0x3090,
+ 0x5e9c, 0x06a9,
+ 0x5e9d, 0x3091,
+ 0x5e9e, 0x0b94,
+ 0x5e9f, 0x066c,
+ 0x5ea0, 0x1636,
+ 0x5ea1, 0x3092,
+ 0x5ea5, 0x1635,
+ 0x5ea6, 0x0607,
+ 0x5ea7, 0x1256,
+ 0x5ea8, 0x3096,
+ 0x5eab, 0x1fe0,
+ 0x5eac, 0x3099,
+ 0x5ead, 0x0e56,
+ 0x5eae, 0x309a,
+ 0x5eb3, 0x163a,
+ 0x5eb4, 0x309f,
+ 0x5eb5, 0x1638,
+ 0x5eb6, 0x0d93,
+ 0x5eb7, 0x0942,
+ 0x5eb8, 0x109e,
+ 0x5eb9, 0x1637,
+ 0x5eba, 0x30a0,
+ 0x5ebe, 0x1639,
+ 0x5ebf, 0x30a4,
+ 0x5ec9, 0x09f7,
+ 0x5eca, 0x09b3,
+ 0x5ecb, 0x30ae,
+ 0x5ed1, 0x163d,
+ 0x5ed2, 0x163c,
+ 0x5ed3, 0x0995,
+ 0x5ed4, 0x30b4,
+ 0x5ed6, 0x0a17,
+ 0x5ed7, 0x30b6,
+ 0x5edb, 0x163e,
+ 0x5edc, 0x30ba,
+ 0x5edf, 0x2087,
+ 0x5ee0, 0x1e78,
+ 0x5ee1, 0x23ae,
+ 0x5ee2, 0x1ef6,
+ 0x5ee3, 0x1f31,
+ 0x5ee4, 0x30bd,
+ 0x5ee8, 0x163f,
+ 0x5ee9, 0x30c1,
+ 0x5eea, 0x1640,
+ 0x5eeb, 0x30c2,
+ 0x5eec, 0x2045,
+ 0x5eed, 0x30c3,
+ 0x5ef3, 0x2178,
+ 0x5ef4, 0x1398,
+ 0x5ef5, 0x30c9,
+ 0x5ef6, 0x0ffc,
+ 0x5ef7, 0x0e53,
+ 0x5ef8, 0x30ca,
+ 0x5efa, 0x0879,
+ 0x5efb, 0x30cc,
+ 0x5efe, 0x14ad,
+ 0x5eff, 0x125b,
+ 0x5f00, 0x0937,
+ 0x5f01, 0x139d,
+ 0x5f02, 0x1073,
+ 0x5f03, 0x0c19,
+ 0x5f04, 0x0b6b,
+ 0x5f05, 0x30cf,
+ 0x5f08, 0x14ae,
+ 0x5f09, 0x30d2,
+ 0x5f0a, 0x0440,
+ 0x5f0b, 0x14f6,
+ 0x5f0c, 0x30d3,
+ 0x5f0f, 0x0d54,
+ 0x5f10, 0x30d6,
+ 0x5f11, 0x14f9,
+ 0x5f12, 0x30d7,
+ 0x5f13, 0x0706,
+ 0x5f14, 0x30d8,
+ 0x5f15, 0x1084,
+ 0x5f16, 0x30d9,
+ 0x5f17, 0x06a0,
+ 0x5f18, 0x07a2,
+ 0x5f19, 0x30da,
+ 0x5f1b, 0x04ff,
+ 0x5f1c, 0x30dc,
+ 0x5f1f, 0x05bd,
+ 0x5f20, 0x1166,
+ 0x5f21, 0x30df,
+ 0x5f25, 0x0adb,
+ 0x5f26, 0x0f3f,
+ 0x5f27, 0x07b6,
+ 0x5f28, 0x30e3,
+ 0x5f29, 0x176f,
+ 0x5f2a, 0x176e,
+ 0x5f2b, 0x30e4,
+ 0x5f2d, 0x1770,
+ 0x5f2e, 0x30e6,
+ 0x5f2f, 0x0e95,
+ 0x5f30, 0x30e7,
+ 0x5f31, 0x0cd0,
+ 0x5f32, 0x30e8,
+ 0x5f33, 0x23f5,
+ 0x5f34, 0x30e9,
+ 0x5f35, 0x2275,
+ 0x5f36, 0x30ea,
+ 0x5f39, 0x0590,
+ 0x5f3a, 0x0c3c,
+ 0x5f3b, 0x30ed,
+ 0x5f3c, 0x1772,
+ 0x5f3d, 0x30ee,
+ 0x5f40, 0x19be,
+ 0x5f41, 0x30f1,
+ 0x5f46, 0x266e,
+ 0x5f47, 0x30f6,
+ 0x5f48, 0x1eb0,
+ 0x5f49, 0x30f7,
+ 0x5f4c, 0x2083,
+ 0x5f4d, 0x30fa,
+ 0x5f4e, 0x2188,
+ 0x5f4f, 0x30fb,
+ 0x5f50, 0x1762,
+ 0x5f51, 0x30fc,
+ 0x5f52, 0x0742,
+ 0x5f53, 0x0592,
+ 0x5f54, 0x30fd,
+ 0x5f55, 0x0a63,
+ 0x5f56, 0x1764,
+ 0x5f57, 0x1763,
+ 0x5f58, 0x1765,
+ 0x5f59, 0x267c,
+ 0x5f5a, 0x30fe,
+ 0x5f5d, 0x1054,
+ 0x5f5e, 0x3101,
+ 0x5f61, 0x15ee,
+ 0x5f62, 0x0f99,
+ 0x5f63, 0x3104,
+ 0x5f64, 0x0e5f,
+ 0x5f65, 0x3105,
+ 0x5f66, 0x100e,
+ 0x5f67, 0x3106,
+ 0x5f69, 0x0491,
+ 0x5f6a, 0x0454,
+ 0x5f6b, 0x3108,
+ 0x5f6c, 0x045b,
+ 0x5f6d, 0x0bae,
+ 0x5f6e, 0x3109,
+ 0x5f70, 0x1164,
+ 0x5f71, 0x1095,
+ 0x5f72, 0x310b,
+ 0x5f73, 0x15e0,
+ 0x5f74, 0x310c,
+ 0x5f77, 0x15e1,
+ 0x5f78, 0x310f,
+ 0x5f79, 0x1062,
+ 0x5f7a, 0x3110,
+ 0x5f7b, 0x04de,
+ 0x5f7c, 0x0434,
+ 0x5f7d, 0x3111,
+ 0x5f80, 0x0eaa,
+ 0x5f81, 0x1198,
+ 0x5f82, 0x15e2,
+ 0x5f83, 0x3114,
+ 0x5f84, 0x08e5,
+ 0x5f85, 0x0580,
+ 0x5f86, 0x3115,
+ 0x5f87, 0x15e3,
+ 0x5f88, 0x0793,
+ 0x5f89, 0x15e4,
+ 0x5f8a, 0x07c7,
+ 0x5f8b, 0x0a70,
+ 0x5f8c, 0x15e5,
+ 0x5f8d, 0x3116,
+ 0x5f90, 0x0fb7,
+ 0x5f91, 0x1fc5,
+ 0x5f92, 0x0e6e,
+ 0x5f93, 0x3119,
+ 0x5f95, 0x15e6,
+ 0x5f96, 0x311b,
+ 0x5f97, 0x05a4,
+ 0x5f98, 0x0b88,
+ 0x5f99, 0x15e7,
+ 0x5f9a, 0x311c,
+ 0x5f9c, 0x15e8,
+ 0x5f9d, 0x311e,
+ 0x5f9e, 0x1ea1,
+ 0x5f9f, 0x311f,
+ 0x5fa0, 0x2393,
+ 0x5fa1, 0x10de,
+ 0x5fa2, 0x3120,
+ 0x5fa8, 0x15e9,
+ 0x5fa9, 0x1f0b,
+ 0x5faa, 0x0fd6,
+ 0x5fab, 0x3126,
+ 0x5fad, 0x15ea,
+ 0x5fae, 0x0eb1,
+ 0x5faf, 0x3128,
+ 0x5fb5, 0x15eb,
+ 0x5fb6, 0x312e,
+ 0x5fb7, 0x05a3,
+ 0x5fb8, 0x312f,
+ 0x5fb9, 0x1e7c,
+ 0x5fba, 0x3130,
+ 0x5fbc, 0x15ec,
+ 0x5fbd, 0x07ea,
+ 0x5fbe, 0x3132,
+ 0x5fc3, 0x0f8f,
+ 0x5fc4, 0x1642,
+ 0x5fc5, 0x0441,
+ 0x5fc6, 0x106b,
+ 0x5fc7, 0x3137,
+ 0x5fc9, 0x1643,
+ 0x5fca, 0x3139,
+ 0x5fcc, 0x083c,
+ 0x5fcd, 0x0ca7,
+ 0x5fce, 0x313b,
+ 0x5fcf, 0x1645,
+ 0x5fd0, 0x1a0c,
+ 0x5fd1, 0x1a0b,
+ 0x5fd2, 0x14f7,
+ 0x5fd3, 0x313c,
+ 0x5fd6, 0x1644,
+ 0x5fd7, 0x11bd,
+ 0x5fd8, 0x0ead,
+ 0x5fd9, 0x0aab,
+ 0x5fda, 0x313f,
+ 0x5fdd, 0x1683,
+ 0x5fde, 0x3142,
+ 0x5fe0, 0x11d1,
+ 0x5fe1, 0x1649,
+ 0x5fe2, 0x3144,
+ 0x5fe4, 0x164a,
+ 0x5fe5, 0x3146,
+ 0x5fe7, 0x10ac,
+ 0x5fe8, 0x3148,
+ 0x5fea, 0x164e,
+ 0x5feb, 0x0979,
+ 0x5fec, 0x314a,
+ 0x5fed, 0x164f,
+ 0x5fee, 0x1647,
+ 0x5fef, 0x314b,
+ 0x5ff1, 0x04e5,
+ 0x5ff2, 0x314d,
+ 0x5ff5, 0x0b51,
+ 0x5ff6, 0x3150,
+ 0x5ff8, 0x1650,
+ 0x5ff9, 0x3152,
+ 0x5ffb, 0x0f8e,
+ 0x5ffc, 0x3154,
+ 0x5ffd, 0x07ad,
+ 0x5ffe, 0x164b,
+ 0x5fff, 0x067b,
+ 0x6000, 0x07c8,
+ 0x6001, 0x0dff,
+ 0x6002, 0x0dc0,
+ 0x6003, 0x1646,
+ 0x6004, 0x1648,
+ 0x6005, 0x164c,
+ 0x6007, 0x3155,
+ 0x600a, 0x1659,
+ 0x600b, 0x3158,
+ 0x600d, 0x1656,
+ 0x600e, 0x1138,
+ 0x600f, 0x1655,
+ 0x6010, 0x315a,
+ 0x6012, 0x0b6e,
+ 0x6013, 0x315c,
+ 0x6014, 0x119b,
+ 0x6015, 0x0b83,
+ 0x6016, 0x0487,
+ 0x6017, 0x315d,
+ 0x6019, 0x1651,
+ 0x601a, 0x315f,
+ 0x601b, 0x1654,
+ 0x601c, 0x09f8,
+ 0x601d, 0x0db1,
+ 0x601e, 0x3160,
+ 0x6020, 0x0582,
+ 0x6021, 0x165b,
+ 0x6022, 0x3162,
+ 0x6025, 0x0824,
+ 0x6026, 0x1653,
+ 0x6027, 0x0f9f,
+ 0x6028, 0x10fc,
+ 0x6029, 0x1657,
+ 0x602a, 0x072f,
+ 0x602b, 0x1658,
+ 0x602c, 0x3165,
+ 0x602f, 0x0c50,
+ 0x6030, 0x3168,
+ 0x6035, 0x1652,
+ 0x6036, 0x316d,
+ 0x603b, 0x1239,
+ 0x603c, 0x1a0d,
+ 0x603d, 0x3172,
+ 0x603f, 0x165a,
+ 0x6040, 0x3174,
+ 0x6041, 0x1a11,
+ 0x6042, 0x1660,
+ 0x6043, 0x0d68,
+ 0x6044, 0x3175,
+ 0x604b, 0x09fe,
+ 0x604c, 0x317c,
+ 0x604d, 0x07e5,
+ 0x604e, 0x317d,
+ 0x6050, 0x0963,
+ 0x6051, 0x317f,
+ 0x6052, 0x079a,
+ 0x6053, 0x3180,
+ 0x6055, 0x0d96,
+ 0x6056, 0x3182,
+ 0x6059, 0x1a12,
+ 0x605a, 0x1a0f,
+ 0x605b, 0x3185,
+ 0x605d, 0x1a0e,
+ 0x605e, 0x3187,
+ 0x6062, 0x07eb,
+ 0x6063, 0x1a13,
+ 0x6064, 0x0fbf,
+ 0x6065, 0x318b,
+ 0x6067, 0x1a10,
+ 0x6068, 0x0795,
+ 0x6069, 0x0636,
+ 0x606a, 0x1661,
+ 0x606b, 0x05f1,
+ 0x606c, 0x0e44,
+ 0x606d, 0x0700,
+ 0x606e, 0x318d,
+ 0x606f, 0x0f0f,
+ 0x6070, 0x0c1e,
+ 0x6071, 0x318e,
+ 0x6073, 0x095f,
+ 0x6074, 0x3190,
+ 0x6076, 0x0630,
+ 0x6077, 0x3192,
+ 0x6078, 0x165c,
+ 0x607a, 0x165f,
+ 0x607b, 0x165e,
+ 0x607c, 0x0b38,
+ 0x607d, 0x1662,
+ 0x607e, 0x3193,
+ 0x607f, 0x10a6,
+ 0x6080, 0x3194,
+ 0x6083, 0x1667,
+ 0x6084, 0x0c41,
+ 0x6085, 0x3197,
+ 0x6089, 0x0f11,
+ 0x608a, 0x319b,
+ 0x608c, 0x1669,
+ 0x608d, 0x076e,
+ 0x608e, 0x319d,
+ 0x6092, 0x1668,
+ 0x6093, 0x31a1,
+ 0x6094, 0x07ef,
+ 0x6095, 0x31a2,
+ 0x6096, 0x1663,
+ 0x6097, 0x31a3,
+ 0x609a, 0x1664,
+ 0x609b, 0x166a,
+ 0x609c, 0x31a6,
+ 0x609d, 0x1666,
+ 0x609e, 0x31a7,
+ 0x609f, 0x0f01,
+ 0x60a0, 0x10ab,
+ 0x60a1, 0x31a8,
+ 0x60a3, 0x07d1,
+ 0x60a4, 0x31aa,
+ 0x60a6, 0x1106,
+ 0x60a7, 0x31ac,
+ 0x60a8, 0x0b5d,
+ 0x60a9, 0x31ad,
+ 0x60ab, 0x1a14,
+ 0x60ac, 0x0fc7,
+ 0x60ad, 0x1665,
+ 0x60ae, 0x31af,
+ 0x60af, 0x0afa,
+ 0x60b0, 0x31b0,
+ 0x60b1, 0x166d,
+ 0x60b2, 0x0418,
+ 0x60b3, 0x31b1,
+ 0x60b4, 0x1672,
+ 0x60b5, 0x23b4,
+ 0x60b6, 0x207e,
+ 0x60b7, 0x31b2,
+ 0x60b8, 0x0835,
+ 0x60b9, 0x31b3,
+ 0x60bb, 0x166c,
+ 0x60bc, 0x05a0,
+ 0x60bd, 0x31b5,
+ 0x60c5, 0x0c66,
+ 0x60c6, 0x1670,
+ 0x60c7, 0x31bd,
+ 0x60ca, 0x08d9,
+ 0x60cb, 0x0ea0,
+ 0x60cc, 0x31c0,
+ 0x60d1, 0x0808,
+ 0x60d2, 0x31c5,
+ 0x60d5, 0x0e3b,
+ 0x60d6, 0x31c8,
+ 0x60d8, 0x166f,
+ 0x60d9, 0x31ca,
+ 0x60da, 0x1671,
+ 0x60db, 0x31cb,
+ 0x60dc, 0x0f14,
+ 0x60dd, 0x166e,
+ 0x60de, 0x31cc,
+ 0x60df, 0x0eb8,
+ 0x60e0, 0x07f2,
+ 0x60e1, 0x1ee3,
+ 0x60e2, 0x31cd,
+ 0x60e6, 0x05cc,
+ 0x60e7, 0x0914,
+ 0x60e8, 0x0499,
+ 0x60e9, 0x04f2,
+ 0x60ea, 0x31d1,
+ 0x60eb, 0x0422,
+ 0x60ec, 0x166b,
+ 0x60ed, 0x0498,
+ 0x60ee, 0x058d,
+ 0x60ef, 0x0738,
+ 0x60f0, 0x0627,
+ 0x60f1, 0x2095,
+ 0x60f2, 0x23bb,
+ 0x60f3, 0x0f58,
+ 0x60f4, 0x1677,
+ 0x60f5, 0x31d2,
+ 0x60f6, 0x07e1,
+ 0x60f7, 0x31d3,
+ 0x60f9, 0x0ca2,
+ 0x60fa, 0x0f95,
+ 0x60fb, 0x23b9,
+ 0x60fc, 0x31d5,
+ 0x6100, 0x1678,
+ 0x6101, 0x0513,
+ 0x6102, 0x31d9,
+ 0x6106, 0x1a15,
+ 0x6107, 0x31dd,
+ 0x6108, 0x10df,
+ 0x6109, 0x10c9,
+ 0x610a, 0x31de,
+ 0x610d, 0x1a16,
+ 0x610e, 0x1679,
+ 0x610f, 0x1069,
+ 0x6110, 0x31e1,
+ 0x6115, 0x1675,
+ 0x6116, 0x31e6,
+ 0x611a, 0x10c3,
+ 0x611b, 0x1e28,
+ 0x611c, 0x23bd,
+ 0x611d, 0x31ea,
+ 0x611f, 0x06cb,
+ 0x6120, 0x1673,
+ 0x6121, 0x31ec,
+ 0x6123, 0x1676,
+ 0x6124, 0x067c,
+ 0x6125, 0x31ee,
+ 0x6126, 0x1674,
+ 0x6127, 0x098d,
+ 0x6128, 0x31ef,
+ 0x612b, 0x167a,
+ 0x612c, 0x31f2,
+ 0x6134, 0x23b5,
+ 0x6135, 0x31fa,
+ 0x6137, 0x23ba,
+ 0x6138, 0x31fc,
+ 0x613e, 0x23b3,
+ 0x613f, 0x10fb,
+ 0x6140, 0x3202,
+ 0x6148, 0x054b,
+ 0x6149, 0x320a,
+ 0x614a, 0x167b,
+ 0x614b, 0x2162,
+ 0x614c, 0x07da,
+ 0x614d, 0x320b,
+ 0x614e, 0x0d30,
+ 0x614f, 0x320c,
+ 0x6151, 0x0d1e,
+ 0x6152, 0x320e,
+ 0x6155, 0x0b20,
+ 0x6156, 0x3211,
+ 0x6158, 0x1e5e,
+ 0x6159, 0x3213,
+ 0x615a, 0x1e5d,
+ 0x615b, 0x3214,
+ 0x615d, 0x1a17,
+ 0x615e, 0x3216,
+ 0x615f, 0x23b7,
+ 0x6160, 0x3217,
+ 0x6162, 0x0aa4,
+ 0x6163, 0x1f2f,
+ 0x6164, 0x24df,
+ 0x6165, 0x3219,
+ 0x6167, 0x07f0,
+ 0x6168, 0x093b,
+ 0x6169, 0x321b,
+ 0x616a, 0x23b2,
+ 0x616b, 0x214e,
+ 0x616c, 0x321c,
+ 0x616e, 0x2052,
+ 0x616f, 0x321e,
+ 0x6170, 0x0ece,
+ 0x6171, 0x321f,
+ 0x6173, 0x23bc,
+ 0x6174, 0x3221,
+ 0x6175, 0x167c,
+ 0x6176, 0x20eb,
+ 0x6177, 0x0943,
+ 0x6178, 0x3222,
+ 0x6182, 0x2232,
+ 0x6183, 0x322c,
+ 0x618a, 0x1e3f,
+ 0x618b, 0x0458,
+ 0x618c, 0x3233,
+ 0x618e, 0x113a,
+ 0x618f, 0x3235,
+ 0x6190, 0x201b,
+ 0x6191, 0x20bc,
+ 0x6192, 0x23be,
+ 0x6193, 0x3236,
+ 0x6194, 0x167e,
+ 0x6195, 0x3237,
+ 0x619a, 0x1eae,
+ 0x619b, 0x323c,
+ 0x619d, 0x1a19,
+ 0x619e, 0x323e,
+ 0x61a4, 0x1efb,
+ 0x61a5, 0x3244,
+ 0x61a7, 0x167f,
+ 0x61a8, 0x0760,
+ 0x61a9, 0x1a18,
+ 0x61aa, 0x3246,
+ 0x61ab, 0x2089,
+ 0x61ac, 0x167d,
+ 0x61ad, 0x3247,
+ 0x61ae, 0x23b1,
+ 0x61af, 0x3248,
+ 0x61b2, 0x21c4,
+ 0x61b3, 0x324b,
+ 0x61b6, 0x2214,
+ 0x61b7, 0x1680,
+ 0x61b8, 0x324e,
+ 0x61be, 0x076d,
+ 0x61bf, 0x3254,
+ 0x61c2, 0x05ed,
+ 0x61c3, 0x3257,
+ 0x61c7, 0x1fde,
+ 0x61c8, 0x0f83,
+ 0x61c9, 0x2223,
+ 0x61ca, 0x03ce,
+ 0x61cb, 0x1a1a,
+ 0x61cc, 0x23b6,
+ 0x61cd, 0x325b,
+ 0x61d1, 0x1a1b,
+ 0x61d2, 0x09ac,
+ 0x61d3, 0x325f,
+ 0x61d4, 0x1681,
+ 0x61d5, 0x3260,
+ 0x61de, 0x268c,
+ 0x61df, 0x24de,
+ 0x61e0, 0x3269,
+ 0x61e3, 0x24e0,
+ 0x61e4, 0x326c,
+ 0x61e6, 0x0b74,
+ 0x61e7, 0x326e,
+ 0x61e8, 0x23b8,
+ 0x61e9, 0x326f,
+ 0x61f2, 0x1e81,
+ 0x61f3, 0x3278,
+ 0x61f5, 0x1682,
+ 0x61f6, 0x1ffe,
+ 0x61f7, 0x1f51,
+ 0x61f8, 0x21e1,
+ 0x61f9, 0x327a,
+ 0x61fa, 0x23b0,
+ 0x61fb, 0x327b,
+ 0x61fc, 0x1fce,
+ 0x61fd, 0x327c,
+ 0x61fe, 0x211e,
+ 0x61ff, 0x13e0,
+ 0x6200, 0x2021,
+ 0x6201, 0x327d,
+ 0x6206, 0x1a1c,
+ 0x6207, 0x24e1,
+ 0x6208, 0x06e5,
+ 0x6209, 0x3282,
+ 0x620a, 0x0efb,
+ 0x620b, 0x18f9,
+ 0x620c, 0x0fb2,
+ 0x620d, 0x0d90,
+ 0x620e, 0x0cb1,
+ 0x620f, 0x0f24,
+ 0x6210, 0x04ee,
+ 0x6211, 0x0ee1,
+ 0x6212, 0x08b5,
+ 0x6213, 0x3283,
+ 0x6214, 0x24a3,
+ 0x6215, 0x169e,
+ 0x6216, 0x0807,
+ 0x6217, 0x18fa,
+ 0x6218, 0x115e,
+ 0x6219, 0x3284,
+ 0x621a, 0x0bfc,
+ 0x621b, 0x18fb,
+ 0x621c, 0x3285,
+ 0x621f, 0x18fc,
+ 0x6220, 0x3288,
+ 0x6221, 0x18fe,
+ 0x6222, 0x18fd,
+ 0x6223, 0x3289,
+ 0x6224, 0x1900,
+ 0x6225, 0x18ff,
+ 0x6226, 0x328a,
+ 0x6227, 0x24a4,
+ 0x6228, 0x328b,
+ 0x622a, 0x08a9,
+ 0x622b, 0x328d,
+ 0x622c, 0x1901,
+ 0x622d, 0x328e,
+ 0x622e, 0x0a65,
+ 0x622f, 0x328f,
+ 0x6230, 0x2273,
+ 0x6231, 0x3290,
+ 0x6232, 0x21b0,
+ 0x6233, 0x0544,
+ 0x6234, 0x057a,
+ 0x6235, 0x3291,
+ 0x6237, 0x07bc,
+ 0x6238, 0x3293,
+ 0x623d, 0x19f4,
+ 0x623e, 0x19f3,
+ 0x623f, 0x065c,
+ 0x6240, 0x0dee,
+ 0x6241, 0x044b,
+ 0x6242, 0x3298,
+ 0x6243, 0x19f5,
+ 0x6244, 0x3299,
+ 0x6247, 0x0d01,
+ 0x6248, 0x19f6,
+ 0x624a, 0x329c,
+ 0x624b, 0x0d6d,
+ 0x624c, 0x14ba,
+ 0x624d, 0x048c,
+ 0x624e, 0x113d,
+ 0x624f, 0x329d,
+ 0x6251, 0x0bea,
+ 0x6252, 0x03d2,
+ 0x6253, 0x0575,
+ 0x6254, 0x0cae,
+ 0x6255, 0x329f,
+ 0x6258, 0x0e81,
+ 0x6259, 0x32a2,
+ 0x625b, 0x0945,
+ 0x625c, 0x32a4,
+ 0x6263, 0x0968,
+ 0x6264, 0x32ab,
+ 0x6266, 0x0c21,
+ 0x6267, 0x11b3,
+ 0x6268, 0x32ad,
+ 0x6269, 0x0994,
+ 0x626a, 0x14bb,
+ 0x626b, 0x0ce1,
+ 0x626c, 0x1018,
+ 0x626d, 0x0b65,
+ 0x626e, 0x03f2,
+ 0x626f, 0x04db,
+ 0x6270, 0x0ca0,
+ 0x6271, 0x32ae,
+ 0x6273, 0x03ed,
+ 0x6274, 0x32b0,
+ 0x6276, 0x0693,
+ 0x6277, 0x32b2,
+ 0x6279, 0x0bbb,
+ 0x627a, 0x32b4,
+ 0x627c, 0x0632,
+ 0x627d, 0x32b6,
+ 0x627e, 0x1173,
+ 0x627f, 0x04f5,
+ 0x6280, 0x082f,
+ 0x6281, 0x32b7,
+ 0x6284, 0x04d2,
+ 0x6285, 0x32ba,
+ 0x6289, 0x0920,
+ 0x628a, 0x03dc,
+ 0x628b, 0x32be,
+ 0x6291, 0x105d,
+ 0x6292, 0x0d7a,
+ 0x6293, 0x1202,
+ 0x6294, 0x32c4,
+ 0x6295, 0x0e67,
+ 0x6296, 0x05f5,
+ 0x6297, 0x0946,
+ 0x6298, 0x117c,
+ 0x6299, 0x32c5,
+ 0x629a, 0x06a2,
+ 0x629b, 0x0b98,
+ 0x629c, 0x32c6,
+ 0x629f, 0x14bc,
+ 0x62a0, 0x0966,
+ 0x62a1, 0x0a7c,
+ 0x62a2, 0x0c3d,
+ 0x62a3, 0x32c9,
+ 0x62a4, 0x07b9,
+ 0x62a5, 0x0411,
+ 0x62a6, 0x32ca,
+ 0x62a8, 0x0bab,
+ 0x62a9, 0x32cc,
+ 0x62ab, 0x0bbc,
+ 0x62ac, 0x0dfa,
+ 0x62ad, 0x32ce,
+ 0x62b1, 0x0410,
+ 0x62b2, 0x32d2,
+ 0x62b5, 0x05b7,
+ 0x62b6, 0x32d5,
+ 0x62b9, 0x0b0b,
+ 0x62ba, 0x32d8,
+ 0x62bb, 0x14bd,
+ 0x62bc, 0x0fe3,
+ 0x62bd, 0x050e,
+ 0x62be, 0x32d9,
+ 0x62bf, 0x0af7,
+ 0x62c0, 0x32da,
+ 0x62c2, 0x0694,
+ 0x62c3, 0x32dc,
+ 0x62c4, 0x11f3,
+ 0x62c5, 0x0584,
+ 0x62c6, 0x04b7,
+ 0x62c7, 0x0b17,
+ 0x62c8, 0x0b4c,
+ 0x62c9, 0x0998,
+ 0x62ca, 0x14be,
+ 0x62cb, 0x32dd,
+ 0x62cc, 0x03f3,
+ 0x62cd, 0x0b85,
+ 0x62ce, 0x0a29,
+ 0x62cf, 0x32de,
+ 0x62d0, 0x072e,
+ 0x62d1, 0x32df,
+ 0x62d2, 0x090b,
+ 0x62d3, 0x0e89,
+ 0x62d4, 0x03d9,
+ 0x62d5, 0x32e0,
+ 0x62d6, 0x0e80,
+ 0x62d7, 0x14c0,
+ 0x62d8, 0x08ff,
+ 0x62d9, 0x121b,
+ 0x62da, 0x14bf,
+ 0x62db, 0x1171,
+ 0x62dc, 0x03e8,
+ 0x62dd, 0x32e1,
+ 0x62df, 0x0b45,
+ 0x62e0, 0x32e3,
+ 0x62e2, 0x0a4a,
+ 0x62e3, 0x0863,
+ 0x62e4, 0x32e5,
+ 0x62e5, 0x109a,
+ 0x62e6, 0x09a4,
+ 0x62e7, 0x0b62,
+ 0x62e8, 0x046d,
+ 0x62e9, 0x1134,
+ 0x62ea, 0x32e6,
+ 0x62ec, 0x0993,
+ 0x62ed, 0x0d5a,
+ 0x62ee, 0x14c1,
+ 0x62ef, 0x119d,
+ 0x62f0, 0x32e8,
+ 0x62f1, 0x0709,
+ 0x62f2, 0x32e9,
+ 0x62f3, 0x0c88,
+ 0x62f4, 0x0d9e,
+ 0x62f5, 0x32ea,
+ 0x62f6, 0x14c3,
+ 0x62f7, 0x094a,
+ 0x62f8, 0x32eb,
+ 0x62fc, 0x0bd3,
+ 0x62fd, 0x1204,
+ 0x62fe, 0x0d47,
+ 0x62ff, 0x0b26,
+ 0x6300, 0x32ef,
+ 0x6301, 0x04fb,
+ 0x6302, 0x072b,
+ 0x6303, 0x32f0,
+ 0x6307, 0x11b7,
+ 0x6308, 0x194e,
+ 0x6309, 0x03bf,
+ 0x630a, 0x32f4,
+ 0x630e, 0x0973,
+ 0x630f, 0x32f8,
+ 0x6311, 0x0e47,
+ 0x6312, 0x32fa,
+ 0x6316, 0x0e8b,
+ 0x6317, 0x32fe,
+ 0x631a, 0x11be,
+ 0x631b, 0x0a75,
+ 0x631c, 0x3301,
+ 0x631d, 0x0edd,
+ 0x631e, 0x0df5,
+ 0x631f, 0x0f79,
+ 0x6320, 0x0b36,
+ 0x6321, 0x0593,
+ 0x6322, 0x14c2,
+ 0x6323, 0x1196,
+ 0x6324, 0x082a,
+ 0x6325, 0x07e8,
+ 0x6326, 0x3302,
+ 0x6328, 0x03af,
+ 0x6329, 0x3304,
+ 0x632a, 0x0b73,
+ 0x632b, 0x056f,
+ 0x632c, 0x3305,
+ 0x632f, 0x1192,
+ 0x6330, 0x3308,
+ 0x6332, 0x194f,
+ 0x6333, 0x330a,
+ 0x6339, 0x14c4,
+ 0x633a, 0x0e57,
+ 0x633b, 0x3310,
+ 0x633d, 0x0e9d,
+ 0x633e, 0x21d1,
+ 0x633f, 0x3312,
+ 0x6342, 0x0ef5,
+ 0x6343, 0x14c6,
+ 0x6344, 0x3315,
+ 0x6345, 0x0e62,
+ 0x6346, 0x0991,
+ 0x6347, 0x3316,
+ 0x6349, 0x121a,
+ 0x634a, 0x3318,
+ 0x634b, 0x14c5,
+ 0x634c, 0x03d1,
+ 0x634d, 0x076b,
+ 0x634e, 0x0d0c,
+ 0x634f, 0x0b56,
+ 0x6350, 0x0917,
+ 0x6351, 0x3319,
+ 0x6355, 0x047d,
+ 0x6356, 0x331d,
+ 0x635e, 0x09b7,
+ 0x635f, 0x0de5,
+ 0x6360, 0x3325,
+ 0x6361, 0x0864,
+ 0x6362, 0x07d0,
+ 0x6363, 0x0598,
+ 0x6364, 0x3326,
+ 0x6367, 0x0bb6,
+ 0x6368, 0x211c,
+ 0x6369, 0x14d0,
+ 0x636a, 0x3329,
+ 0x636b, 0x235d,
+ 0x636c, 0x332a,
+ 0x636d, 0x14cd,
+ 0x636e, 0x090c,
+ 0x636f, 0x332b,
+ 0x6371, 0x14c9,
+ 0x6372, 0x2682,
+ 0x6373, 0x332d,
+ 0x6376, 0x053a,
+ 0x6377, 0x08ae,
+ 0x6378, 0x3330,
+ 0x637a, 0x14ca,
+ 0x637b, 0x0b50,
+ 0x637c, 0x3332,
+ 0x6380, 0x0f33,
+ 0x6381, 0x3336,
+ 0x6382, 0x05c1,
+ 0x6383, 0x210d,
+ 0x6384, 0x205a,
+ 0x6385, 0x3337,
+ 0x6387, 0x061d,
+ 0x6388, 0x0d71,
+ 0x6389, 0x05d5,
+ 0x638a, 0x14cf,
+ 0x638b, 0x3339,
+ 0x638c, 0x1167,
+ 0x638d, 0x333a,
+ 0x638e, 0x14cb,
+ 0x638f, 0x0e20,
+ 0x6390, 0x0c1d,
+ 0x6391, 0x333b,
+ 0x6392, 0x0b86,
+ 0x6393, 0x333c,
+ 0x6396, 0x103b,
+ 0x6397, 0x333f,
+ 0x6398, 0x0921,
+ 0x6399, 0x3340,
+ 0x63a0, 0x0a7a,
+ 0x63a1, 0x3347,
+ 0x63a2, 0x0e10,
+ 0x63a3, 0x04dd,
+ 0x63a4, 0x3348,
+ 0x63a5, 0x08a4,
+ 0x63a6, 0x3349,
+ 0x63a7, 0x0965,
+ 0x63a8, 0x0e77,
+ 0x63a9, 0x1003,
+ 0x63aa, 0x056e,
+ 0x63ab, 0x334a,
+ 0x63ac, 0x14ce,
+ 0x63ad, 0x14c7,
+ 0x63ae, 0x14d1,
+ 0x63af, 0x334b,
+ 0x63b0, 0x1950,
+ 0x63b1, 0x334c,
+ 0x63b3, 0x0a57,
+ 0x63b4, 0x14cc,
+ 0x63b5, 0x334e,
+ 0x63b7, 0x11bf,
+ 0x63b8, 0x0588,
+ 0x63b9, 0x3350,
+ 0x63ba, 0x04bb,
+ 0x63bb, 0x3351,
+ 0x63bc, 0x14d2,
+ 0x63bd, 0x3352,
+ 0x63be, 0x14dc,
+ 0x63bf, 0x3353,
+ 0x63c0, 0x1f8d,
+ 0x63c1, 0x3354,
+ 0x63c4, 0x14d7,
+ 0x63c5, 0x3357,
+ 0x63c6, 0x14db,
+ 0x63c7, 0x3358,
+ 0x63c9, 0x0cbb,
+ 0x63ca, 0x335a,
+ 0x63cd, 0x123e,
+ 0x63ce, 0x14d9,
+ 0x63cf, 0x0aed,
+ 0x63d0, 0x0e34,
+ 0x63d1, 0x335d,
+ 0x63d2, 0x04ac,
+ 0x63d3, 0x335e,
+ 0x63d6, 0x1045,
+ 0x63d7, 0x3361,
+ 0x63da, 0x21ff,
+ 0x63db, 0x3364,
+ 0x63de, 0x14d8,
+ 0x63df, 0x3367,
+ 0x63e0, 0x14d5,
+ 0x63e1, 0x0ee4,
+ 0x63e2, 0x3368,
+ 0x63e3, 0x052a,
+ 0x63e4, 0x3369,
+ 0x63e9, 0x0938,
+ 0x63ea, 0x08ed,
+ 0x63eb, 0x336e,
+ 0x63ed, 0x08a3,
+ 0x63ee, 0x1f58,
+ 0x63ef, 0x3370,
+ 0x63f2, 0x14d3,
+ 0x63f3, 0x3373,
+ 0x63f4, 0x10f1,
+ 0x63f5, 0x3374,
+ 0x63f6, 0x14c8,
+ 0x63f7, 0x3375,
+ 0x63f8, 0x14d4,
+ 0x63f9, 0x3376,
+ 0x63fd, 0x09aa,
+ 0x63fe, 0x337a,
+ 0x63ff, 0x14d6,
+ 0x6400, 0x04ba,
+ 0x6401, 0x06e4,
+ 0x6402, 0x0a4e,
+ 0x6403, 0x337b,
+ 0x6405, 0x0892,
+ 0x6406, 0x337d,
+ 0x640b, 0x14df,
+ 0x640c, 0x14e2,
+ 0x640d, 0x215b,
+ 0x640e, 0x3382,
+ 0x640f, 0x0472,
+ 0x6410, 0x0527,
+ 0x6411, 0x3383,
+ 0x6413, 0x056d,
+ 0x6414, 0x0cdf,
+ 0x6415, 0x3385,
+ 0x6417, 0x1eb6,
+ 0x6418, 0x3387,
+ 0x641b, 0x14e0,
+ 0x641c, 0x0dc6,
+ 0x641d, 0x338a,
+ 0x641e, 0x06de,
+ 0x641f, 0x338b,
+ 0x6420, 0x14e1,
+ 0x6421, 0x14e4,
+ 0x6422, 0x338c,
+ 0x6426, 0x14e3,
+ 0x6427, 0x3390,
+ 0x642a, 0x0e15,
+ 0x642b, 0x3393,
+ 0x642c, 0x03ec,
+ 0x642d, 0x0571,
+ 0x642e, 0x3394,
+ 0x6434, 0x1736,
+ 0x6435, 0x339a,
+ 0x6436, 0x20db,
+ 0x6437, 0x339b,
+ 0x643a, 0x0f7a,
+ 0x643b, 0x339e,
+ 0x643d, 0x04b2,
+ 0x643e, 0x33a0,
+ 0x643f, 0x1951,
+ 0x6440, 0x33a1,
+ 0x6441, 0x14de,
+ 0x6442, 0x33a2,
+ 0x6444, 0x0d1c,
+ 0x6445, 0x14dd,
+ 0x6446, 0x03e5,
+ 0x6447, 0x1028,
+ 0x6448, 0x0460,
+ 0x6449, 0x33a4,
+ 0x644a, 0x0e02,
+ 0x644b, 0x33a5,
+ 0x6451, 0x2360,
+ 0x6452, 0x14da,
+ 0x6453, 0x33ab,
+ 0x6454, 0x0d99,
+ 0x6455, 0x33ac,
+ 0x6458, 0x114b,
+ 0x6459, 0x33af,
+ 0x645c, 0x2361,
+ 0x645d, 0x33b2,
+ 0x645e, 0x14e5,
+ 0x645f, 0x2040,
+ 0x6460, 0x33b3,
+ 0x6467, 0x0560,
+ 0x6468, 0x33ba,
+ 0x6469, 0x0b09,
+ 0x646a, 0x33bb,
+ 0x646d, 0x14e7,
+ 0x646e, 0x33be,
+ 0x646f, 0x228e,
+ 0x6470, 0x33bf,
+ 0x6473, 0x1fdf,
+ 0x6474, 0x33c2,
+ 0x6476, 0x235e,
+ 0x6477, 0x33c4,
+ 0x6478, 0x0b03,
+ 0x647a, 0x14e9,
+ 0x647b, 0x1e6a,
+ 0x647c, 0x33c5,
+ 0x6482, 0x0a15,
+ 0x6483, 0x33cb,
+ 0x6484, 0x14e6,
+ 0x6485, 0x091e,
+ 0x6486, 0x33cc,
+ 0x6487, 0x0bd1,
+ 0x6488, 0x2002,
+ 0x6489, 0x33cd,
+ 0x6491, 0x04ea,
+ 0x6492, 0x0cd1,
+ 0x6493, 0x2093,
+ 0x6494, 0x33d5,
+ 0x6495, 0x0daf,
+ 0x6496, 0x14e8,
+ 0x6497, 0x33d6,
+ 0x6499, 0x14ec,
+ 0x649a, 0x33d8,
+ 0x649e, 0x120f,
+ 0x649f, 0x235f,
+ 0x64a0, 0x33dc,
+ 0x64a3, 0x1eac,
+ 0x64a4, 0x04dc,
+ 0x64a5, 0x1e54,
+ 0x64a6, 0x33df,
+ 0x64a9, 0x0a0c,
+ 0x64aa, 0x33e2,
+ 0x64ab, 0x1f08,
+ 0x64ac, 0x0c48,
+ 0x64ad, 0x046c,
+ 0x64ae, 0x056c,
+ 0x64af, 0x33e3,
+ 0x64b0, 0x1208,
+ 0x64b1, 0x33e4,
+ 0x64b2, 0x20c0,
+ 0x64b3, 0x2362,
+ 0x64b4, 0x33e5,
+ 0x64b5, 0x0b4f,
+ 0x64b6, 0x33e6,
+ 0x64b7, 0x14ea,
+ 0x64b9, 0x33e7,
+ 0x64ba, 0x14ed,
+ 0x64bb, 0x2160,
+ 0x64bc, 0x076a,
+ 0x64bd, 0x33e8,
+ 0x64be, 0x219d,
+ 0x64bf, 0x1f8e,
+ 0x64c0, 0x14ee,
+ 0x64c1, 0x222d,
+ 0x64c2, 0x09c9,
+ 0x64c3, 0x33e9,
+ 0x64c4, 0x2047,
+ 0x64c5, 0x0cfc,
+ 0x64c6, 0x33ea,
+ 0x64c7, 0x2262,
+ 0x64c8, 0x33eb,
+ 0x64ca, 0x1f67,
+ 0x64cb, 0x1eb2,
+ 0x64cc, 0x33ed,
+ 0x64cd, 0x04a0,
+ 0x64ce, 0x0c63,
+ 0x64cf, 0x33ee,
+ 0x64d0, 0x14ef,
+ 0x64d1, 0x33ef,
+ 0x64d2, 0x0c59,
+ 0x64d3, 0x33f0,
+ 0x64d4, 0x1ea9,
+ 0x64d5, 0x33f1,
+ 0x64d7, 0x14f0,
+ 0x64d8, 0x1952,
+ 0x64d9, 0x33f3,
+ 0x64da, 0x1fcc,
+ 0x64db, 0x33f4,
+ 0x64de, 0x0dc8,
+ 0x64df, 0x33f7,
+ 0x64e0, 0x1f72,
+ 0x64e1, 0x33f8,
+ 0x64e2, 0x14f2,
+ 0x64e3, 0x33f9,
+ 0x64e4, 0x14f1,
+ 0x64e5, 0x33fa,
+ 0x64e6, 0x0488,
+ 0x64e7, 0x33fb,
+ 0x64ec, 0x2098,
+ 0x64ed, 0x3400,
+ 0x64ef, 0x1e52,
+ 0x64f0, 0x20a4,
+ 0x64f1, 0x1f1c,
+ 0x64f2, 0x228f,
+ 0x64f3, 0x3402,
+ 0x64f4, 0x1fed,
+ 0x64f5, 0x3403,
+ 0x64f7, 0x2365,
+ 0x64f8, 0x3405,
+ 0x64fa, 0x1e2d,
+ 0x64fb, 0x2152,
+ 0x64fc, 0x2366,
+ 0x64fd, 0x3407,
+ 0x64fe, 0x20fa,
+ 0x64ff, 0x3408,
+ 0x6500, 0x0b8b,
+ 0x6501, 0x3409,
+ 0x6504, 0x2363,
+ 0x6505, 0x340c,
+ 0x6506, 0x209a,
+ 0x6507, 0x340d,
+ 0x6509, 0x14f3,
+ 0x650a, 0x340f,
+ 0x650f, 0x203c,
+ 0x6510, 0x3414,
+ 0x6512, 0x111f,
+ 0x6513, 0x3416,
+ 0x6514, 0x1ff6,
+ 0x6515, 0x3417,
+ 0x6516, 0x2364,
+ 0x6517, 0x3418,
+ 0x6518, 0x0c9c,
+ 0x6519, 0x1e69,
+ 0x651a, 0x3419,
+ 0x651b, 0x2367,
+ 0x651c, 0x341a,
+ 0x651d, 0x211d,
+ 0x651e, 0x341b,
+ 0x6522, 0x2259,
+ 0x6523, 0x2056,
+ 0x6524, 0x2163,
+ 0x6525, 0x14f4,
+ 0x6526, 0x341f,
+ 0x652a, 0x1fa9,
+ 0x652b, 0x091f,
+ 0x652c, 0x1ffc,
+ 0x652d, 0x3423,
+ 0x652e, 0x14f5,
+ 0x652f, 0x11a6,
+ 0x6530, 0x3424,
+ 0x6534, 0x1909,
+ 0x6535, 0x1966,
+ 0x6536, 0x0d6c,
+ 0x6537, 0x3428,
+ 0x6538, 0x12b2,
+ 0x6539, 0x06bf,
+ 0x653a, 0x3429,
+ 0x653b, 0x06fe,
+ 0x653c, 0x342a,
+ 0x653e, 0x0662,
+ 0x653f, 0x119f,
+ 0x6540, 0x342c,
+ 0x6545, 0x0723,
+ 0x6546, 0x3431,
+ 0x6548, 0x0f72,
+ 0x6549, 0x1ccb,
+ 0x654a, 0x3433,
+ 0x654c, 0x05b1,
+ 0x654d, 0x3435,
+ 0x654f, 0x0af9,
+ 0x6550, 0x3437,
+ 0x6551, 0x08f7,
+ 0x6552, 0x3438,
+ 0x6555, 0x1967,
+ 0x6556, 0x03c8,
+ 0x6557, 0x1e2e,
+ 0x6558, 0x343b,
+ 0x6559, 0x089d,
+ 0x655a, 0x343c,
+ 0x655b, 0x09fb,
+ 0x655c, 0x343d,
+ 0x655d, 0x043f,
+ 0x655e, 0x04cd,
+ 0x655f, 0x343e,
+ 0x6562, 0x06cd,
+ 0x6563, 0x0cdb,
+ 0x6564, 0x3441,
+ 0x6566, 0x0617,
+ 0x6567, 0x3443,
+ 0x656b, 0x1968,
+ 0x656c, 0x08e3,
+ 0x656d, 0x3447,
+ 0x6570, 0x0d94,
+ 0x6571, 0x344a,
+ 0x6572, 0x0c40,
+ 0x6573, 0x344b,
+ 0x6574, 0x119c,
+ 0x6575, 0x1ebc,
+ 0x6576, 0x344c,
+ 0x6577, 0x0690,
+ 0x6578, 0x2142,
+ 0x6579, 0x344d,
+ 0x6582, 0x201e,
+ 0x6583, 0x1e43,
+ 0x6584, 0x3456,
+ 0x6587, 0x0ed3,
+ 0x6588, 0x3459,
+ 0x658b, 0x114c,
+ 0x658c, 0x045c,
+ 0x658d, 0x345c,
+ 0x6590, 0x19c1,
+ 0x6591, 0x03ea,
+ 0x6592, 0x345f,
+ 0x6593, 0x19c3,
+ 0x6594, 0x3460,
+ 0x6595, 0x24d4,
+ 0x6596, 0x3461,
+ 0x6597, 0x05f6,
+ 0x6598, 0x3462,
+ 0x6599, 0x0a18,
+ 0x659a, 0x3463,
+ 0x659b, 0x1d56,
+ 0x659c, 0x0f7c,
+ 0x659d, 0x3464,
+ 0x659f, 0x1186,
+ 0x65a0, 0x3466,
+ 0x65a1, 0x0ee2,
+ 0x65a2, 0x3467,
+ 0x65a4, 0x08c0,
+ 0x65a5, 0x0507,
+ 0x65a6, 0x3469,
+ 0x65a7, 0x06a6,
+ 0x65a8, 0x346a,
+ 0x65a9, 0x1157,
+ 0x65aa, 0x346b,
+ 0x65ab, 0x1a29,
+ 0x65ac, 0x226f,
+ 0x65ad, 0x060e,
+ 0x65ae, 0x346c,
+ 0x65af, 0x0dae,
+ 0x65b0, 0x0f8d,
+ 0x65b1, 0x346d,
+ 0x65b7, 0x1ed7,
+ 0x65b8, 0x3473,
+ 0x65b9, 0x065a,
+ 0x65ba, 0x3474,
+ 0x65bc, 0x19c4,
+ 0x65bd, 0x0d40,
+ 0x65be, 0x3476,
+ 0x65c1, 0x0b95,
+ 0x65c2, 0x3479,
+ 0x65c3, 0x19c7,
+ 0x65c4, 0x19c6,
+ 0x65c5, 0x0a6a,
+ 0x65c6, 0x19c5,
+ 0x65c7, 0x347a,
+ 0x65cb, 0x0fc8,
+ 0x65cc, 0x19c8,
+ 0x65cd, 0x347e,
+ 0x65ce, 0x19c9,
+ 0x65cf, 0x1242,
+ 0x65d0, 0x347f,
+ 0x65d2, 0x19ca,
+ 0x65d3, 0x3481,
+ 0x65d6, 0x19cb,
+ 0x65d7, 0x0c0b,
+ 0x65d8, 0x3484,
+ 0x65e0, 0x0eed,
+ 0x65e1, 0x348c,
+ 0x65e2, 0x083b,
+ 0x65e3, 0x348d,
+ 0x65e5, 0x0cb0,
+ 0x65e6, 0x058a,
+ 0x65e7, 0x08f8,
+ 0x65e8, 0x11bb,
+ 0x65e9, 0x112a,
+ 0x65ea, 0x348f,
+ 0x65ec, 0x0fd7,
+ 0x65ed, 0x0fbc,
+ 0x65ee, 0x190a,
+ 0x65f1, 0x076c,
+ 0x65f2, 0x3491,
+ 0x65f6, 0x0d48,
+ 0x65f7, 0x0982,
+ 0x65f8, 0x3495,
+ 0x65fa, 0x0eab,
+ 0x65fb, 0x3497,
+ 0x6600, 0x1912,
+ 0x6601, 0x349c,
+ 0x6602, 0x03c5,
+ 0x6603, 0x1910,
+ 0x6604, 0x349d,
+ 0x6606, 0x0990,
+ 0x6607, 0x349f,
+ 0x660a, 0x190d,
+ 0x660b, 0x34a2,
+ 0x660c, 0x04c4,
+ 0x660d, 0x34a3,
+ 0x660e, 0x0afc,
+ 0x660f, 0x07fd,
+ 0x6610, 0x34a4,
+ 0x6613, 0x105e,
+ 0x6614, 0x0f03,
+ 0x6615, 0x1911,
+ 0x6616, 0x34a7,
+ 0x6619, 0x190e,
+ 0x661a, 0x34aa,
+ 0x661d, 0x1915,
+ 0x661e, 0x34ad,
+ 0x661f, 0x0f92,
+ 0x6620, 0x1098,
+ 0x6621, 0x34ae,
+ 0x6625, 0x053d,
+ 0x6626, 0x34b2,
+ 0x6627, 0x0ac6,
+ 0x6628, 0x124f,
+ 0x6629, 0x34b3,
+ 0x662d, 0x1172,
+ 0x662e, 0x34b7,
+ 0x662f, 0x0d5e,
+ 0x6630, 0x34b8,
+ 0x6631, 0x1917,
+ 0x6632, 0x34b9,
+ 0x6634, 0x1916,
+ 0x6635, 0x1919,
+ 0x6636, 0x1918,
+ 0x6637, 0x34bb,
+ 0x663c, 0x11e6,
+ 0x663d, 0x34c0,
+ 0x663e, 0x0f41,
+ 0x663f, 0x34c1,
+ 0x6641, 0x191d,
+ 0x6642, 0x212d,
+ 0x6643, 0x07e3,
+ 0x6644, 0x34c3,
+ 0x664b, 0x08cb,
+ 0x664c, 0x0d07,
+ 0x664d, 0x34ca,
+ 0x664f, 0x191e,
+ 0x6650, 0x34cc,
+ 0x6652, 0x0cf2,
+ 0x6653, 0x0f6b,
+ 0x6654, 0x191c,
+ 0x6655, 0x1111,
+ 0x6656, 0x191f,
+ 0x6657, 0x1921,
+ 0x6658, 0x34ce,
+ 0x665a, 0x0e9e,
+ 0x665b, 0x34d0,
+ 0x665d, 0x229b,
+ 0x665e, 0x34d2,
+ 0x665f, 0x191b,
+ 0x6660, 0x34d3,
+ 0x6661, 0x1920,
+ 0x6662, 0x34d4,
+ 0x6664, 0x0efd,
+ 0x6665, 0x34d6,
+ 0x6666, 0x07f3,
+ 0x6667, 0x34d7,
+ 0x6668, 0x04e4,
+ 0x6669, 0x34d8,
+ 0x666e, 0x0bf4,
+ 0x666f, 0x08df,
+ 0x6670, 0x0f09,
+ 0x6671, 0x34dd,
+ 0x6674, 0x0c64,
+ 0x6675, 0x34e0,
+ 0x6676, 0x08d6,
+ 0x6677, 0x1922,
+ 0x6678, 0x34e1,
+ 0x667a, 0x11c6,
+ 0x667b, 0x34e3,
+ 0x667e, 0x0a09,
+ 0x667f, 0x34e6,
+ 0x6682, 0x1120,
+ 0x6683, 0x34e9,
+ 0x6684, 0x1923,
+ 0x6685, 0x34ea,
+ 0x6687, 0x0f2b,
+ 0x6688, 0x2256,
+ 0x6689, 0x24a8,
+ 0x668a, 0x34ec,
+ 0x668c, 0x1924,
+ 0x668d, 0x34ee,
+ 0x6691, 0x0d85,
+ 0x6692, 0x34f2,
+ 0x6696, 0x0b70,
+ 0x6697, 0x03c0,
+ 0x6698, 0x34f6,
+ 0x669d, 0x1926,
+ 0x669e, 0x34fb,
+ 0x66a2, 0x1e79,
+ 0x66a3, 0x34ff,
+ 0x66a7, 0x1925,
+ 0x66a8, 0x1cdd,
+ 0x66a9, 0x3503,
+ 0x66ab, 0x225a,
+ 0x66ac, 0x3505,
+ 0x66ae, 0x0b1d,
+ 0x66af, 0x3507,
+ 0x66b4, 0x0412,
+ 0x66b5, 0x350c,
+ 0x66b9, 0x175b,
+ 0x66ba, 0x3510,
+ 0x66be, 0x1927,
+ 0x66bf, 0x3514,
+ 0x66c4, 0x24a7,
+ 0x66c5, 0x3519,
+ 0x66c6, 0x2686,
+ 0x66c7, 0x24a6,
+ 0x66c8, 0x351a,
+ 0x66c9, 0x21ce,
+ 0x66ca, 0x351b,
+ 0x66d6, 0x24a9,
+ 0x66d7, 0x3527,
+ 0x66d9, 0x0d86,
+ 0x66da, 0x3529,
+ 0x66db, 0x1928,
+ 0x66dd, 0x0bf7,
+ 0x66de, 0x352a,
+ 0x66e0, 0x1fe7,
+ 0x66e1, 0x352c,
+ 0x66e6, 0x192a,
+ 0x66e7, 0x3531,
+ 0x66e9, 0x192b,
+ 0x66ea, 0x3533,
+ 0x66ec, 0x2112,
+ 0x66ed, 0x3535,
+ 0x66f0, 0x10fe,
+ 0x66f1, 0x3538,
+ 0x66f2, 0x0c77,
+ 0x66f3, 0x103e,
+ 0x66f4, 0x06f7,
+ 0x66f5, 0x3539,
+ 0x66f7, 0x1914,
+ 0x66f8, 0x213c,
+ 0x66f9, 0x04a3,
+ 0x66fa, 0x353b,
+ 0x66fc, 0x0aa3,
+ 0x66fd, 0x353d,
+ 0x66fe, 0x113b,
+ 0x66ff, 0x0e39,
+ 0x6700, 0x124b,
+ 0x6701, 0x353e,
+ 0x6703, 0x1f5c,
+ 0x6704, 0x3540,
+ 0x6708, 0x1105,
+ 0x6709, 0x10b5,
+ 0x670a, 0x1973,
+ 0x670b, 0x0bb4,
+ 0x670c, 0x3544,
+ 0x670d, 0x069b,
+ 0x670e, 0x3545,
+ 0x6710, 0x1984,
+ 0x6711, 0x3547,
+ 0x6714, 0x0dac,
+ 0x6715, 0x198e,
+ 0x6716, 0x354a,
+ 0x6717, 0x09b5,
+ 0x6718, 0x354b,
+ 0x671b, 0x0eac,
+ 0x671c, 0x354e,
+ 0x671d, 0x04d4,
+ 0x671e, 0x354f,
+ 0x671f, 0x0bf9,
+ 0x6720, 0x3550,
+ 0x6726, 0x19ac,
+ 0x6727, 0x24c4,
+ 0x6728, 0x0b21,
+ 0x6729, 0x3556,
+ 0x672a, 0x0ec3,
+ 0x672b, 0x0b0c,
+ 0x672c, 0x0427,
+ 0x672d, 0x1140,
+ 0x672e, 0x3557,
+ 0x672f, 0x0d8c,
+ 0x6730, 0x3558,
+ 0x6731, 0x11eb,
+ 0x6732, 0x3559,
+ 0x6734, 0x0bf2,
+ 0x6735, 0x0623,
+ 0x6736, 0x355b,
+ 0x673a, 0x080f,
+ 0x673b, 0x355f,
+ 0x673d, 0x0fab,
+ 0x673e, 0x3561,
+ 0x6740, 0x0cea,
+ 0x6741, 0x3563,
+ 0x6742, 0x1116,
+ 0x6743, 0x0c83,
+ 0x6744, 0x3564,
+ 0x6746, 0x06c6,
+ 0x6747, 0x3566,
+ 0x6748, 0x1854,
+ 0x6749, 0x0cf5,
+ 0x674a, 0x3567,
+ 0x674c, 0x1851,
+ 0x674d, 0x3569,
+ 0x674e, 0x09d9,
+ 0x674f, 0x0f9e,
+ 0x6750, 0x048b,
+ 0x6751, 0x0568,
+ 0x6752, 0x356a,
+ 0x6753, 0x1852,
+ 0x6754, 0x356b,
+ 0x6756, 0x1169,
+ 0x6757, 0x356d,
+ 0x675c, 0x0604,
+ 0x675d, 0x3572,
+ 0x675e, 0x1853,
+ 0x675f, 0x0d8f,
+ 0x6760, 0x06d7,
+ 0x6761, 0x0e48,
+ 0x6762, 0x3573,
+ 0x6765, 0x099f,
+ 0x6766, 0x3576,
+ 0x6768, 0x1017,
+ 0x6769, 0x1855,
+ 0x676a, 0x1858,
+ 0x676b, 0x3578,
+ 0x676d, 0x0773,
+ 0x676e, 0x357a,
+ 0x676f, 0x0416,
+ 0x6770, 0x08ad,
+ 0x6771, 0x1ecc,
+ 0x6772, 0x190f,
+ 0x6773, 0x1859,
+ 0x6774, 0x357b,
+ 0x6775, 0x185c,
+ 0x6776, 0x357c,
+ 0x6777, 0x1861,
+ 0x6778, 0x357d,
+ 0x677c, 0x1862,
+ 0x677d, 0x3581,
+ 0x677e, 0x0dbe,
+ 0x677f, 0x03f0,
+ 0x6780, 0x3582,
+ 0x6781, 0x081e,
+ 0x6782, 0x3583,
+ 0x6784, 0x0712,
+ 0x6785, 0x3585,
+ 0x6787, 0x1857,
+ 0x6788, 0x3587,
+ 0x6789, 0x0ea8,
+ 0x678a, 0x3588,
+ 0x678b, 0x1860,
+ 0x678c, 0x3589,
+ 0x6790, 0x0f05,
+ 0x6791, 0x358d,
+ 0x6795, 0x118e,
+ 0x6796, 0x3591,
+ 0x6797, 0x0a1f,
+ 0x6798, 0x185a,
+ 0x6799, 0x3592,
+ 0x679a, 0x0abb,
+ 0x679b, 0x3593,
+ 0x679c, 0x0754,
+ 0x679d, 0x11a5,
+ 0x679e, 0x185e,
+ 0x679f, 0x3594,
+ 0x67a2, 0x0d77,
+ 0x67a3, 0x1129,
+ 0x67a4, 0x3597,
+ 0x67a5, 0x1856,
+ 0x67a6, 0x3598,
+ 0x67a7, 0x185b,
+ 0x67a8, 0x185d,
+ 0x67a9, 0x3599,
+ 0x67aa, 0x0c36,
+ 0x67ab, 0x0680,
+ 0x67ac, 0x359a,
+ 0x67ad, 0x185f,
+ 0x67ae, 0x359b,
+ 0x67af, 0x096a,
+ 0x67b0, 0x1868,
+ 0x67b1, 0x359c,
+ 0x67b3, 0x186d,
+ 0x67b4, 0x359e,
+ 0x67b5, 0x186b,
+ 0x67b6, 0x084f,
+ 0x67b7, 0x0842,
+ 0x67b8, 0x1871,
+ 0x67b9, 0x359f,
+ 0x67c1, 0x1874,
+ 0x67c2, 0x35a7,
+ 0x67c3, 0x1870,
+ 0x67c4, 0x0463,
+ 0x67c5, 0x35a8,
+ 0x67cf, 0x03e3,
+ 0x67d0, 0x0b16,
+ 0x67d1, 0x06c7,
+ 0x67d2, 0x0c01,
+ 0x67d3, 0x0c99,
+ 0x67d4, 0x0cbc,
+ 0x67d5, 0x35b2,
+ 0x67d8, 0x1865,
+ 0x67d9, 0x186a,
+ 0x67da, 0x186c,
+ 0x67db, 0x35b5,
+ 0x67dc, 0x074a,
+ 0x67dd, 0x186e,
+ 0x67de, 0x1252,
+ 0x67df, 0x35b6,
+ 0x67e0, 0x0b5e,
+ 0x67e1, 0x35b7,
+ 0x67e2, 0x1872,
+ 0x67e3, 0x35b8,
+ 0x67e5, 0x04b0,
+ 0x67e6, 0x35ba,
+ 0x67e9, 0x1867,
+ 0x67ea, 0x35bd,
+ 0x67ec, 0x0860,
+ 0x67ed, 0x35bf,
+ 0x67ef, 0x094f,
+ 0x67f0, 0x1863,
+ 0x67f1, 0x11f8,
+ 0x67f2, 0x35c1,
+ 0x67f3, 0x0a41,
+ 0x67f4, 0x04b8,
+ 0x67f5, 0x35c2,
+ 0x67fd, 0x1875,
+ 0x67fe, 0x35ca,
+ 0x67ff, 0x0d58,
+ 0x6800, 0x186f,
+ 0x6801, 0x35cb,
+ 0x6805, 0x1145,
+ 0x6806, 0x35cf,
+ 0x6807, 0x0453,
+ 0x6808, 0x115c,
+ 0x6809, 0x1864,
+ 0x680a, 0x1866,
+ 0x680b, 0x05ef,
+ 0x680c, 0x1869,
+ 0x680d, 0x35d0,
+ 0x680e, 0x1873,
+ 0x680f, 0x09a3,
+ 0x6810, 0x35d1,
+ 0x6811, 0x0d8e,
+ 0x6812, 0x35d2,
+ 0x6813, 0x0d9d,
+ 0x6814, 0x35d3,
+ 0x6816, 0x0bfb,
+ 0x6817, 0x09e0,
+ 0x6818, 0x35d5,
+ 0x681d, 0x187f,
+ 0x681e, 0x35da,
+ 0x6821, 0x0f6e,
+ 0x6822, 0x35dd,
+ 0x6829, 0x1888,
+ 0x682a, 0x11e9,
+ 0x682b, 0x35e4,
+ 0x6832, 0x1876,
+ 0x6834, 0x35eb,
+ 0x6837, 0x1022,
+ 0x6838, 0x0782,
+ 0x6839, 0x06f4,
+ 0x683a, 0x35ee,
+ 0x683c, 0x06ec,
+ 0x683d, 0x1117,
+ 0x683e, 0x1885,
+ 0x683f, 0x35f0,
+ 0x6840, 0x1884,
+ 0x6841, 0x1882,
+ 0x6842, 0x0749,
+ 0x6843, 0x0e25,
+ 0x6844, 0x187c,
+ 0x6845, 0x0eb5,
+ 0x6846, 0x097f,
+ 0x6847, 0x35f1,
+ 0x6848, 0x03c3,
+ 0x6849, 0x1887,
+ 0x684a, 0x1886,
+ 0x684b, 0x35f2,
+ 0x684c, 0x121d,
+ 0x684d, 0x35f3,
+ 0x684e, 0x187a,
+ 0x684f, 0x35f4,
+ 0x6850, 0x0e5a,
+ 0x6851, 0x0cdc,
+ 0x6852, 0x35f5,
+ 0x6853, 0x07cd,
+ 0x6854, 0x08ac,
+ 0x6855, 0x1880,
+ 0x6856, 0x35f6,
+ 0x6860, 0x1878,
+ 0x6862, 0x187b,
+ 0x6863, 0x0596,
+ 0x6864, 0x187d,
+ 0x6865, 0x0c42,
+ 0x6866, 0x1881,
+ 0x6867, 0x1883,
+ 0x6868, 0x0881,
+ 0x6869, 0x120b,
+ 0x686a, 0x3600,
+ 0x686b, 0x188e,
+ 0x686c, 0x3601,
+ 0x6874, 0x188b,
+ 0x6875, 0x3609,
+ 0x6876, 0x0e61,
+ 0x6877, 0x188c,
+ 0x6878, 0x360a,
+ 0x6881, 0x0a03,
+ 0x6882, 0x3613,
+ 0x6883, 0x187e,
+ 0x6884, 0x3614,
+ 0x6885, 0x0abc,
+ 0x6886, 0x03fb,
+ 0x6887, 0x3615,
+ 0x688f, 0x188a,
+ 0x6890, 0x361d,
+ 0x6893, 0x188d,
+ 0x6894, 0x3620,
+ 0x6897, 0x06fc,
+ 0x6898, 0x246a,
+ 0x6899, 0x3623,
+ 0x689d, 0x2175,
+ 0x689e, 0x3627,
+ 0x689f, 0x246d,
+ 0x68a0, 0x3628,
+ 0x68a2, 0x0d0b,
+ 0x68a3, 0x362a,
+ 0x68a6, 0x0ad3,
+ 0x68a7, 0x0eef,
+ 0x68a8, 0x09d1,
+ 0x68a9, 0x362d,
+ 0x68ad, 0x0de8,
+ 0x68ae, 0x3631,
+ 0x68af, 0x0e30,
+ 0x68b0, 0x0f80,
+ 0x68b1, 0x3632,
+ 0x68b3, 0x0d78,
+ 0x68b4, 0x3634,
+ 0x68b5, 0x1889,
+ 0x68b6, 0x3635,
+ 0x68c0, 0x085f,
+ 0x68c1, 0x363f,
+ 0x68c2, 0x188f,
+ 0x68c3, 0x3640,
+ 0x68c9, 0x0ae3,
+ 0x68ca, 0x3646,
+ 0x68cb, 0x0c04,
+ 0x68cc, 0x3647,
+ 0x68cd, 0x0750,
+ 0x68ce, 0x3648,
+ 0x68d2, 0x03ff,
+ 0x68d3, 0x364c,
+ 0x68d5, 0x1235,
+ 0x68d6, 0x246b,
+ 0x68d7, 0x225f,
+ 0x68d8, 0x081f,
+ 0x68d9, 0x364e,
+ 0x68da, 0x0bb0,
+ 0x68db, 0x364f,
+ 0x68df, 0x1ece,
+ 0x68e0, 0x0e17,
+ 0x68e1, 0x3653,
+ 0x68e3, 0x189a,
+ 0x68e4, 0x3655,
+ 0x68e7, 0x2272,
+ 0x68e8, 0x3658,
+ 0x68ee, 0x0ce6,
+ 0x68ef, 0x365e,
+ 0x68f0, 0x1896,
+ 0x68f1, 0x09cd,
+ 0x68f2, 0x365f,
+ 0x68f5, 0x0950,
+ 0x68f6, 0x3662,
+ 0x68f9, 0x1894,
+ 0x68fa, 0x0730,
+ 0x68fb, 0x3665,
+ 0x68fc, 0x1891,
+ 0x68fd, 0x3666,
+ 0x6900, 0x3669,
+ 0x6901, 0x1898,
+ 0x6902, 0x366a,
+ 0x6905, 0x1055,
+ 0x6906, 0x366d,
+ 0x690b, 0x1897,
+ 0x690c, 0x3672,
+ 0x690d, 0x11b1,
+ 0x690e, 0x1212,
+ 0x690f, 0x2473,
+ 0x6910, 0x189b,
+ 0x6911, 0x3673,
+ 0x6912, 0x0888,
+ 0x6913, 0x3674,
+ 0x691f, 0x1892,
+ 0x6921, 0x3680,
+ 0x6924, 0x1895,
+ 0x6925, 0x3683,
+ 0x692d, 0x0e87,
+ 0x692e, 0x368b,
+ 0x6930, 0x1033,
+ 0x6931, 0x368d,
+ 0x6934, 0x18a6,
+ 0x6935, 0x3690,
+ 0x6939, 0x189d,
+ 0x693a, 0x3694,
+ 0x693d, 0x052d,
+ 0x693e, 0x3697,
+ 0x693f, 0x053e,
+ 0x6940, 0x3698,
+ 0x6942, 0x189f,
+ 0x6943, 0x369a,
+ 0x694a, 0x21fe,
+ 0x694b, 0x36a1,
+ 0x6953, 0x1efe,
+ 0x6954, 0x0f73,
+ 0x6955, 0x36a9,
+ 0x6957, 0x1899,
+ 0x6958, 0x36ab,
+ 0x695a, 0x0523,
+ 0x695b, 0x36ad,
+ 0x695d, 0x18a0,
+ 0x695e, 0x09ce,
+ 0x695f, 0x36af,
+ 0x6960, 0x189e,
+ 0x6961, 0x36b0,
+ 0x6963, 0x18ad,
+ 0x6964, 0x36b2,
+ 0x6966, 0x18ac,
+ 0x6967, 0x36b4,
+ 0x6968, 0x2475,
+ 0x6969, 0x36b5,
+ 0x696b, 0x18a2,
+ 0x696c, 0x36b7,
+ 0x696d, 0x220a,
+ 0x696e, 0x1890,
+ 0x696f, 0x36b8,
+ 0x6971, 0x189c,
+ 0x6972, 0x36ba,
+ 0x6975, 0x1f6f,
+ 0x6976, 0x36bd,
+ 0x6977, 0x0939,
+ 0x6978, 0x18a5,
+ 0x6979, 0x18ae,
+ 0x697a, 0x36be,
+ 0x697c, 0x0a4c,
+ 0x697d, 0x36c0,
+ 0x6980, 0x18a3,
+ 0x6981, 0x36c3,
+ 0x6982, 0x06c0,
+ 0x6983, 0x36c4,
+ 0x6984, 0x18a1,
+ 0x6985, 0x36c5,
+ 0x6986, 0x10c1,
+ 0x6987, 0x18a8,
+ 0x6989, 0x18ab,
+ 0x698a, 0x36c6,
+ 0x698d, 0x18bb,
+ 0x698e, 0x36c9,
+ 0x6994, 0x09b1,
+ 0x6995, 0x18b9,
+ 0x6996, 0x36cf,
+ 0x6998, 0x18a4,
+ 0x6999, 0x36d1,
+ 0x699b, 0x18af,
+ 0x699c, 0x03fc,
+ 0x699d, 0x36d3,
+ 0x69a7, 0x18b0,
+ 0x69a8, 0x1146,
+ 0x69a9, 0x36dd,
+ 0x69aa, 0x2468,
+ 0x69ab, 0x18b2,
+ 0x69ac, 0x36de,
+ 0x69ad, 0x18b3,
+ 0x69ae, 0x2100,
+ 0x69af, 0x36df,
+ 0x69b1, 0x18b5,
+ 0x69b2, 0x36e1,
+ 0x69b4, 0x0a3a,
+ 0x69b5, 0x36e3,
+ 0x69b7, 0x0c91,
+ 0x69b8, 0x36e5,
+ 0x69bb, 0x18b1,
+ 0x69bc, 0x36e8,
+ 0x69bf, 0x2476,
+ 0x69c0, 0x36eb,
+ 0x69c1, 0x18b6,
+ 0x69c2, 0x36ec,
+ 0x69ca, 0x18b7,
+ 0x69cb, 0x1f27,
+ 0x69cc, 0x18a7,
+ 0x69cd, 0x20d7,
+ 0x69ce, 0x18aa,
+ 0x69cf, 0x36f4,
+ 0x69d0, 0x07c6,
+ 0x69d1, 0x36f5,
+ 0x69d4, 0x18b4,
+ 0x69d5, 0x36f8,
+ 0x69db, 0x086a,
+ 0x69dc, 0x36fe,
+ 0x69df, 0x18b8,
+ 0x69e0, 0x18ba,
+ 0x69e1, 0x3701,
+ 0x69e7, 0x247c,
+ 0x69e8, 0x3707,
+ 0x69ed, 0x18be,
+ 0x69ee, 0x370c,
+ 0x69f2, 0x18c2,
+ 0x69f3, 0x1fa1,
+ 0x69f4, 0x3710,
+ 0x69fd, 0x04a2,
+ 0x69fe, 0x3719,
+ 0x69ff, 0x18bc,
+ 0x6a00, 0x371a,
+ 0x6a01, 0x22aa,
+ 0x6a02, 0x2005,
+ 0x6a03, 0x371b,
+ 0x6a05, 0x246c,
+ 0x6a06, 0x371d,
+ 0x6a0a, 0x064b,
+ 0x6a0b, 0x3721,
+ 0x6a13, 0x203e,
+ 0x6a14, 0x3729,
+ 0x6a17, 0x18bf,
+ 0x6a19, 0x1e4c,
+ 0x6a1a, 0x372c,
+ 0x6a1e, 0x213a,
+ 0x6a1f, 0x1162,
+ 0x6a20, 0x3730,
+ 0x6a21, 0x0b06,
+ 0x6a22, 0x3731,
+ 0x6a23, 0x2204,
+ 0x6a24, 0x3732,
+ 0x6a28, 0x18cc,
+ 0x6a29, 0x3736,
+ 0x6a2a, 0x0798,
+ 0x6a2b, 0x3737,
+ 0x6a2f, 0x18bd,
+ 0x6a30, 0x373b,
+ 0x6a31, 0x1088,
+ 0x6a32, 0x373c,
+ 0x6a35, 0x18c8,
+ 0x6a36, 0x373f,
+ 0x6a38, 0x20c3,
+ 0x6a39, 0x2140,
+ 0x6a3a, 0x2477,
+ 0x6a3b, 0x3741,
+ 0x6a3d, 0x18cb,
+ 0x6a3e, 0x18c4,
+ 0x6a3f, 0x3743,
+ 0x6a44, 0x18c3,
+ 0x6a45, 0x3748,
+ 0x6a47, 0x0c3e,
+ 0x6a48, 0x2474,
+ 0x6a49, 0x374a,
+ 0x6a4b, 0x20dd,
+ 0x6a4c, 0x374c,
+ 0x6a50, 0x18c6,
+ 0x6a51, 0x3750,
+ 0x6a58, 0x18cd,
+ 0x6a59, 0x04ed,
+ 0x6a5a, 0x3757,
+ 0x6a5b, 0x18c7,
+ 0x6a5c, 0x3758,
+ 0x6a5f, 0x1f68,
+ 0x6a60, 0x375b,
+ 0x6a61, 0x0f5d,
+ 0x6a62, 0x2185,
+ 0x6a63, 0x375c,
+ 0x6a65, 0x18c1,
+ 0x6a66, 0x375e,
+ 0x6a71, 0x051c,
+ 0x6a72, 0x3769,
+ 0x6a79, 0x18ca,
+ 0x6a7a, 0x3770,
+ 0x6a7c, 0x18ce,
+ 0x6a7d, 0x3772,
+ 0x6a80, 0x0e07,
+ 0x6a81, 0x3775,
+ 0x6a84, 0x0f1a,
+ 0x6a85, 0x3778,
+ 0x6a89, 0x2472,
+ 0x6a8a, 0x377c,
+ 0x6a8e, 0x18c9,
+ 0x6a8f, 0x3780,
+ 0x6a90, 0x18d0,
+ 0x6a91, 0x18cf,
+ 0x6a92, 0x3781,
+ 0x6a94, 0x1eb5,
+ 0x6a95, 0x3783,
+ 0x6a97, 0x18d2,
+ 0x6a98, 0x3785,
+ 0x6a9c, 0x2478,
+ 0x6a9d, 0x3789,
+ 0x6aa0, 0x18c5,
+ 0x6aa1, 0x378c,
+ 0x6aa2, 0x1f8b,
+ 0x6aa3, 0x2484,
+ 0x6aa4, 0x378d,
+ 0x6aa9, 0x18d1,
+ 0x6aaa, 0x3792,
+ 0x6aab, 0x18d3,
+ 0x6aac, 0x0acf,
+ 0x6aad, 0x3793,
+ 0x6aaf, 0x2699,
+ 0x6ab0, 0x3795,
+ 0x6ab3, 0x2482,
+ 0x6ab4, 0x3798,
+ 0x6ab8, 0x20a1,
+ 0x6ab9, 0x379c,
+ 0x6abb, 0x1f92,
+ 0x6abc, 0x379e,
+ 0x6ac3, 0x1f38,
+ 0x6ac4, 0x37a5,
+ 0x6ad3, 0x2485,
+ 0x6ad4, 0x37b4,
+ 0x6ada, 0x2480,
+ 0x6adb, 0x246e,
+ 0x6adc, 0x37ba,
+ 0x6add, 0x247b,
+ 0x6ade, 0x2486,
+ 0x6adf, 0x2471,
+ 0x6ae0, 0x37bb,
+ 0x6ae7, 0x2483,
+ 0x6ae8, 0x2470,
+ 0x6ae9, 0x37c2,
+ 0x6aea, 0x2469,
+ 0x6aeb, 0x37c3,
+ 0x6aec, 0x247f,
+ 0x6aed, 0x37c4,
+ 0x6af3, 0x246f,
+ 0x6af4, 0x37ca,
+ 0x6af8, 0x2481,
+ 0x6af9, 0x37ce,
+ 0x6afb, 0x2220,
+ 0x6afc, 0x37d0,
+ 0x6b00, 0x37d4,
+ 0x6b04, 0x1ff5,
+ 0x6b05, 0x37d8,
+ 0x6b0a, 0x20f4,
+ 0x6b0b, 0x37dd,
+ 0x6b0f, 0x247d,
+ 0x6b10, 0x37e1,
+ 0x6b12, 0x2479,
+ 0x6b13, 0x37e3,
+ 0x6b16, 0x247e,
+ 0x6b17, 0x37e6,
+ 0x6b1e, 0x247a,
+ 0x6b1f, 0x37ed,
+ 0x6b20, 0x0c34,
+ 0x6b21, 0x0551,
+ 0x6b22, 0x07cb,
+ 0x6b23, 0x0f8b,
+ 0x6b24, 0x19b1,
+ 0x6b25, 0x37ee,
+ 0x6b27, 0x0b78,
+ 0x6b28, 0x37f0,
+ 0x6b32, 0x10e0,
+ 0x6b33, 0x37fa,
+ 0x6b37, 0x19b2,
+ 0x6b38, 0x37fe,
+ 0x6b39, 0x19b3,
+ 0x6b3a, 0x0bfa,
+ 0x6b3b, 0x37ff,
+ 0x6b3d, 0x20e3,
+ 0x6b3e, 0x097b,
+ 0x6b3f, 0x3801,
+ 0x6b43, 0x19b4,
+ 0x6b44, 0x3805,
+ 0x6b46, 0x19b5,
+ 0x6b47, 0x0f75,
+ 0x6b48, 0x3807,
+ 0x6b49, 0x0c35,
+ 0x6b4a, 0x3808,
+ 0x6b4c, 0x06e3,
+ 0x6b4d, 0x380a,
+ 0x6b50, 0x20ad,
+ 0x6b51, 0x380d,
+ 0x6b59, 0x19b6,
+ 0x6b5a, 0x3815,
+ 0x6b5f, 0x24cb,
+ 0x6b60, 0x381a,
+ 0x6b61, 0x1f53,
+ 0x6b62, 0x11b8,
+ 0x6b63, 0x119e,
+ 0x6b64, 0x054e,
+ 0x6b65, 0x0484,
+ 0x6b66, 0x0ef3,
+ 0x6b67, 0x0c06,
+ 0x6b68, 0x381b,
+ 0x6b6a, 0x0e92,
+ 0x6b6b, 0x381d,
+ 0x6b72, 0x2159,
+ 0x6b73, 0x3824,
+ 0x6b77, 0x2013,
+ 0x6b78, 0x1f33,
+ 0x6b79, 0x0578,
+ 0x6b7a, 0x3828,
+ 0x6b7b, 0x0db5,
+ 0x6b7c, 0x0852,
+ 0x6b7d, 0x3829,
+ 0x6b81, 0x18d6,
+ 0x6b83, 0x1013,
+ 0x6b84, 0x18d9,
+ 0x6b85, 0x382d,
+ 0x6b86, 0x057c,
+ 0x6b87, 0x18d8,
+ 0x6b88, 0x382e,
+ 0x6b89, 0x0fdc,
+ 0x6b8a, 0x0d79,
+ 0x6b8b, 0x0497,
+ 0x6b8c, 0x382f,
+ 0x6b8d, 0x18dc,
+ 0x6b8e, 0x3830,
+ 0x6b92, 0x18da,
+ 0x6b94, 0x3834,
+ 0x6b96, 0x11b2,
+ 0x6b97, 0x3836,
+ 0x6b98, 0x1e5c,
+ 0x6b99, 0x3837,
+ 0x6b9a, 0x18dd,
+ 0x6b9c, 0x3838,
+ 0x6b9e, 0x2488,
+ 0x6b9f, 0x383a,
+ 0x6ba1, 0x18df,
+ 0x6ba2, 0x383c,
+ 0x6ba4, 0x2487,
+ 0x6ba5, 0x383e,
+ 0x6baa, 0x18e0,
+ 0x6bab, 0x248a,
+ 0x6bac, 0x3843,
+ 0x6bae, 0x2489,
+ 0x6baf, 0x248b,
+ 0x6bb0, 0x3845,
+ 0x6bb2, 0x1f83,
+ 0x6bb3, 0x19bd,
+ 0x6bb4, 0x0b7a,
+ 0x6bb5, 0x060d,
+ 0x6bb6, 0x3847,
+ 0x6bb7, 0x107a,
+ 0x6bb8, 0x3848,
+ 0x6bba, 0x210f,
+ 0x6bbb, 0x1fdb,
+ 0x6bbc, 0x384a,
+ 0x6bbf, 0x05cf,
+ 0x6bc0, 0x384d,
+ 0x6bc1, 0x07ee,
+ 0x6bc2, 0x19bf,
+ 0x6bc3, 0x384e,
+ 0x6bc5, 0x106a,
+ 0x6bc6, 0x20af,
+ 0x6bc7, 0x3850,
+ 0x6bcb, 0x0ef2,
+ 0x6bcc, 0x3854,
+ 0x6bcd, 0x0b1b,
+ 0x6bce, 0x3855,
+ 0x6bcf, 0x0ac4,
+ 0x6bd0, 0x3856,
+ 0x6bd2, 0x05fd,
+ 0x6bd3, 0x126f,
+ 0x6bd4, 0x0431,
+ 0x6bd5, 0x0438,
+ 0x6bd6, 0x043a,
+ 0x6bd7, 0x0bbf,
+ 0x6bd8, 0x3858,
+ 0x6bd9, 0x0439,
+ 0x6bda, 0x3859,
+ 0x6bdb, 0x0ab0,
+ 0x6bdc, 0x385a,
+ 0x6be1, 0x1152,
+ 0x6be2, 0x385f,
+ 0x6bea, 0x1954,
+ 0x6beb, 0x0778,
+ 0x6bec, 0x3867,
+ 0x6bef, 0x0e0d,
+ 0x6bf0, 0x386a,
+ 0x6bf3, 0x1955,
+ 0x6bf4, 0x386d,
+ 0x6bf5, 0x1957,
+ 0x6bf6, 0x386e,
+ 0x6bf9, 0x1958,
+ 0x6bfa, 0x3871,
+ 0x6bfd, 0x1956,
+ 0x6bfe, 0x3874,
+ 0x6bff, 0x24c0,
+ 0x6c00, 0x3875,
+ 0x6c05, 0x1959,
+ 0x6c06, 0x195b,
+ 0x6c07, 0x195a,
+ 0x6c08, 0x226d,
+ 0x6c09, 0x387a,
+ 0x6c0c, 0x24c1,
+ 0x6c0d, 0x195c,
+ 0x6c0e, 0x387d,
+ 0x6c0f, 0x0d66,
+ 0x6c10, 0x126b,
+ 0x6c11, 0x0af6,
+ 0x6c12, 0x387e,
+ 0x6c13, 0x0aaa,
+ 0x6c14, 0x0c17,
+ 0x6c15, 0x195d,
+ 0x6c16, 0x0b2d,
+ 0x6c17, 0x387f,
+ 0x6c18, 0x195e,
+ 0x6c1b, 0x0672,
+ 0x6c1c, 0x3880,
+ 0x6c1f, 0x0697,
+ 0x6c20, 0x3883,
+ 0x6c21, 0x1961,
+ 0x6c22, 0x0c5f,
+ 0x6c23, 0x20ca,
+ 0x6c24, 0x1963,
+ 0x6c25, 0x3884,
+ 0x6c26, 0x075b,
+ 0x6c27, 0x101e,
+ 0x6c28, 0x03bc,
+ 0x6c29, 0x1962,
+ 0x6c2a, 0x1964,
+ 0x6c2b, 0x20e7,
+ 0x6c2c, 0x24c2,
+ 0x6c2d, 0x3885,
+ 0x6c2e, 0x058b,
+ 0x6c2f, 0x0a6f,
+ 0x6c30, 0x0c65,
+ 0x6c31, 0x3886,
+ 0x6c32, 0x1965,
+ 0x6c33, 0x3887,
+ 0x6c34, 0x0da3,
+ 0x6c35, 0x169f,
+ 0x6c36, 0x3888,
+ 0x6c38, 0x10a5,
+ 0x6c39, 0x388a,
+ 0x6c3d, 0x12ef,
+ 0x6c3e, 0x388e,
+ 0x6c40, 0x0e52,
+ 0x6c41, 0x11ac,
+ 0x6c42, 0x0c70,
+ 0x6c43, 0x3890,
+ 0x6c46, 0x12f4,
+ 0x6c47, 0x07f8,
+ 0x6c48, 0x3893,
+ 0x6c49, 0x0771,
+ 0x6c4a, 0x16a2,
+ 0x6c4b, 0x3894,
+ 0x6c50, 0x0f18,
+ 0x6c51, 0x3899,
+ 0x6c54, 0x16a0,
+ 0x6c55, 0x0d00,
+ 0x6c56, 0x389c,
+ 0x6c57, 0x0770,
+ 0x6c58, 0x389d,
+ 0x6c5b, 0x0fdd,
+ 0x6c5c, 0x16a1,
+ 0x6c5d, 0x0cc5,
+ 0x6c5e, 0x0708,
+ 0x6c5f, 0x087e,
+ 0x6c60, 0x04fd,
+ 0x6c61, 0x0eea,
+ 0x6c62, 0x38a0,
+ 0x6c64, 0x0e13,
+ 0x6c65, 0x38a2,
+ 0x6c68, 0x16a8,
+ 0x6c6a, 0x0ea5,
+ 0x6c6b, 0x38a5,
+ 0x6c70, 0x0e00,
+ 0x6c71, 0x38aa,
+ 0x6c72, 0x0826,
+ 0x6c73, 0x38ab,
+ 0x6c74, 0x16aa,
+ 0x6c75, 0x38ac,
+ 0x6c76, 0x16ab,
+ 0x6c77, 0x38ad,
+ 0x6c79, 0x0fa5,
+ 0x6c7a, 0x38af,
+ 0x6c7d, 0x0c1a,
+ 0x6c7e, 0x0677,
+ 0x6c7f, 0x38b2,
+ 0x6c81, 0x0c5c,
+ 0x6c82, 0x1051,
+ 0x6c83, 0x0ee5,
+ 0x6c84, 0x38b4,
+ 0x6c85, 0x16a4,
+ 0x6c86, 0x16ac,
+ 0x6c87, 0x38b5,
+ 0x6c88, 0x0d2b,
+ 0x6c89, 0x04e6,
+ 0x6c8a, 0x38b6,
+ 0x6c8c, 0x16a7,
+ 0x6c8d, 0x38b8,
+ 0x6c8f, 0x0c02,
+ 0x6c90, 0x16a5,
+ 0x6c91, 0x38ba,
+ 0x6c93, 0x1a1f,
+ 0x6c94, 0x16a6,
+ 0x6c95, 0x38bc,
+ 0x6c99, 0x0cec,
+ 0x6c9a, 0x38c0,
+ 0x6c9b, 0x0ba7,
+ 0x6c9c, 0x38c1,
+ 0x6c9f, 0x070e,
+ 0x6ca0, 0x38c4,
+ 0x6ca1, 0x0ac0,
+ 0x6ca2, 0x38c5,
+ 0x6ca3, 0x16a3,
+ 0x6ca4, 0x0b7e,
+ 0x6ca5, 0x09ed,
+ 0x6ca6, 0x0a80,
+ 0x6ca7, 0x049e,
+ 0x6ca8, 0x38c6,
+ 0x6ca9, 0x16ad,
+ 0x6caa, 0x07bb,
+ 0x6cab, 0x0b10,
+ 0x6cac, 0x38c7,
+ 0x6cad, 0x16b0,
+ 0x6cae, 0x0909,
+ 0x6caf, 0x38c8,
+ 0x6cb1, 0x16bb,
+ 0x6cb2, 0x16b5,
+ 0x6cb3, 0x078a,
+ 0x6cb4, 0x38ca,
+ 0x6cb8, 0x066d,
+ 0x6cb9, 0x10b2,
+ 0x6cba, 0x38ce,
+ 0x6cbb, 0x11cd,
+ 0x6cbc, 0x1174,
+ 0x6cbd, 0x071a,
+ 0x6cbe, 0x1155,
+ 0x6cbf, 0x1001,
+ 0x6cc0, 0x38cf,
+ 0x6cc4, 0x0f84,
+ 0x6cc5, 0x0c73,
+ 0x6cc6, 0x38d3,
+ 0x6cc9, 0x0c85,
+ 0x6cca, 0x047b,
+ 0x6ccb, 0x38d6,
+ 0x6ccc, 0x0adf,
+ 0x6ccd, 0x38d7,
+ 0x6cd0, 0x16ae,
+ 0x6cd1, 0x38da,
+ 0x6cd3, 0x16bc,
+ 0x6cd4, 0x16af,
+ 0x6cd5, 0x0645,
+ 0x6cd6, 0x16b7,
+ 0x6cd7, 0x16b4,
+ 0x6cd8, 0x38dc,
+ 0x6cdb, 0x0657,
+ 0x6cdc, 0x38df,
+ 0x6cde, 0x0b63,
+ 0x6cdf, 0x38e1,
+ 0x6ce0, 0x16b6,
+ 0x6ce1, 0x0b9e,
+ 0x6ce2, 0x046f,
+ 0x6ce3, 0x0c1b,
+ 0x6ce4, 0x38e2,
+ 0x6ce5, 0x0b43,
+ 0x6ce6, 0x38e3,
+ 0x6ce8, 0x11ff,
+ 0x6ce9, 0x38e5,
+ 0x6cea, 0x09cc,
+ 0x6ceb, 0x16b9,
+ 0x6cec, 0x38e6,
+ 0x6cee, 0x16ba,
+ 0x6cef, 0x16bd,
+ 0x6cf0, 0x0dfc,
+ 0x6cf1, 0x16b3,
+ 0x6cf2, 0x38e8,
+ 0x6cf3, 0x10a3,
+ 0x6cf4, 0x38e9,
+ 0x6cf5, 0x042c,
+ 0x6cf6, 0x1a20,
+ 0x6cf7, 0x16b1,
+ 0x6cf9, 0x38ea,
+ 0x6cfa, 0x16b8,
+ 0x6cfb, 0x0f85,
+ 0x6cfc, 0x0be2,
+ 0x6cfd, 0x1136,
+ 0x6cfe, 0x16be,
+ 0x6cff, 0x38eb,
+ 0x6d00, 0x38ec,
+ 0x6d01, 0x08b1,
+ 0x6d02, 0x38ed,
+ 0x6d04, 0x16c5,
+ 0x6d05, 0x38ef,
+ 0x6d07, 0x16c4,
+ 0x6d08, 0x38f1,
+ 0x6d0b, 0x101c,
+ 0x6d0c, 0x16c1,
+ 0x6d0d, 0x38f4,
+ 0x6d0e, 0x16c7,
+ 0x6d0f, 0x38f5,
+ 0x6d12, 0x0cd2,
+ 0x6d13, 0x38f8,
+ 0x6d17, 0x0f21,
+ 0x6d18, 0x38fc,
+ 0x6d19, 0x16c6,
+ 0x6d1a, 0x16cc,
+ 0x6d1b, 0x0a8c,
+ 0x6d1c, 0x38fd,
+ 0x6d1e, 0x05f3,
+ 0x6d1f, 0x38ff,
+ 0x6d25, 0x08c3,
+ 0x6d26, 0x3905,
+ 0x6d27, 0x16c0,
+ 0x6d28, 0x3906,
+ 0x6d2a, 0x07a0,
+ 0x6d2b, 0x16c8,
+ 0x6d2c, 0x3908,
+ 0x6d2e, 0x16ca,
+ 0x6d2f, 0x390a,
+ 0x6d31, 0x063c,
+ 0x6d32, 0x11dd,
+ 0x6d33, 0x16d0,
+ 0x6d34, 0x390c,
+ 0x6d35, 0x16cb,
+ 0x6d36, 0x390d,
+ 0x6d39, 0x16bf,
+ 0x6d3a, 0x3910,
+ 0x6d3b, 0x0803,
+ 0x6d3c, 0x0e8e,
+ 0x6d3d, 0x0c1f,
+ 0x6d3e, 0x0b8a,
+ 0x6d3f, 0x3911,
+ 0x6d41, 0x0a40,
+ 0x6d42, 0x3913,
+ 0x6d43, 0x16c2,
+ 0x6d44, 0x3914,
+ 0x6d45, 0x0c30,
+ 0x6d46, 0x087d,
+ 0x6d47, 0x088e,
+ 0x6d48, 0x16c3,
+ 0x6d49, 0x3915,
+ 0x6d4a, 0x1224,
+ 0x6d4b, 0x04a9,
+ 0x6d4c, 0x3916,
+ 0x6d4d, 0x16c9,
+ 0x6d4e, 0x0836,
+ 0x6d4f, 0x16cd,
+ 0x6d50, 0x3917,
+ 0x6d51, 0x0800,
+ 0x6d52, 0x16ce,
+ 0x6d53, 0x0b69,
+ 0x6d54, 0x16cf,
+ 0x6d55, 0x3918,
+ 0x6d59, 0x1184,
+ 0x6d5a, 0x0930,
+ 0x6d5b, 0x391c,
+ 0x6d5c, 0x16d8,
+ 0x6d5d, 0x391d,
+ 0x6d5e, 0x16d5,
+ 0x6d5f, 0x391e,
+ 0x6d60, 0x16d9,
+ 0x6d61, 0x391f,
+ 0x6d63, 0x16db,
+ 0x6d64, 0x3921,
+ 0x6d66, 0x0bf5,
+ 0x6d67, 0x3923,
+ 0x6d69, 0x077d,
+ 0x6d6a, 0x09b6,
+ 0x6d6b, 0x3925,
+ 0x6d6e, 0x069c,
+ 0x6d6f, 0x16d2,
+ 0x6d70, 0x3928,
+ 0x6d74, 0x10e4,
+ 0x6d75, 0x392c,
+ 0x6d77, 0x075a,
+ 0x6d78, 0x08cf,
+ 0x6d79, 0x23dc,
+ 0x6d7a, 0x392e,
+ 0x6d7c, 0x16da,
+ 0x6d7d, 0x3930,
+ 0x6d82, 0x0e70,
+ 0x6d83, 0x3935,
+ 0x6d85, 0x0b5c,
+ 0x6d86, 0x3937,
+ 0x6d87, 0x23db,
+ 0x6d88, 0x0f68,
+ 0x6d89, 0x0d1f,
+ 0x6d8a, 0x3938,
+ 0x6d8c, 0x10a4,
+ 0x6d8d, 0x393a,
+ 0x6d8e, 0x0f3e,
+ 0x6d8f, 0x393b,
+ 0x6d91, 0x16d1,
+ 0x6d92, 0x393d,
+ 0x6d93, 0x16d6,
+ 0x6d95, 0x0e3c,
+ 0x6d96, 0x393e,
+ 0x6d9b, 0x0e21,
+ 0x6d9c, 0x3943,
+ 0x6d9d, 0x09bf,
+ 0x6d9e, 0x16d3,
+ 0x6d9f, 0x09f9,
+ 0x6da0, 0x16d4,
+ 0x6da1, 0x0edf,
+ 0x6da2, 0x3944,
+ 0x6da3, 0x07d6,
+ 0x6da4, 0x05b4,
+ 0x6da5, 0x3945,
+ 0x6da6, 0x0cce,
+ 0x6da7, 0x0878,
+ 0x6da8, 0x1168,
+ 0x6da9, 0x0ce5,
+ 0x6daa, 0x069d,
+ 0x6dab, 0x16e8,
+ 0x6dac, 0x3946,
+ 0x6dae, 0x16ea,
+ 0x6daf, 0x0fed,
+ 0x6db0, 0x3948,
+ 0x6db2, 0x1041,
+ 0x6db3, 0x394a,
+ 0x6db5, 0x0764,
+ 0x6db6, 0x394c,
+ 0x6db8, 0x078b,
+ 0x6db9, 0x394e,
+ 0x6dbf, 0x16e1,
+ 0x6dc0, 0x05ce,
+ 0x6dc1, 0x3954,
+ 0x6dc4, 0x122a,
+ 0x6dc5, 0x16de,
+ 0x6dc6, 0x0f6a,
+ 0x6dc7, 0x16dd,
+ 0x6dc8, 0x3957,
+ 0x6dcb, 0x0a25,
+ 0x6dcc, 0x0e1d,
+ 0x6dcd, 0x395a,
+ 0x6dd1, 0x0d7e,
+ 0x6dd2, 0x395e,
+ 0x6dd6, 0x0b3a,
+ 0x6dd7, 0x3962,
+ 0x6dd8, 0x0e27,
+ 0x6dd9, 0x16e6,
+ 0x6dda, 0x3963,
+ 0x6ddd, 0x16e5,
+ 0x6dde, 0x16df,
+ 0x6ddf, 0x3966,
+ 0x6de0, 0x16e2,
+ 0x6de1, 0x058e,
+ 0x6de2, 0x3967,
+ 0x6de4, 0x10be,
+ 0x6de5, 0x3969,
+ 0x6de6, 0x16e4,
+ 0x6de7, 0x396a,
+ 0x6dea, 0x205e,
+ 0x6deb, 0x1080,
+ 0x6dec, 0x0566,
+ 0x6ded, 0x396d,
+ 0x6dee, 0x07c9,
+ 0x6def, 0x396e,
+ 0x6df1, 0x0d27,
+ 0x6df2, 0x3970,
+ 0x6df3, 0x0541,
+ 0x6df4, 0x3971,
+ 0x6df5, 0x2244,
+ 0x6df6, 0x23e2,
+ 0x6df7, 0x0801,
+ 0x6df8, 0x3972,
+ 0x6df9, 0x0ff6,
+ 0x6dfa, 0x20d4,
+ 0x6dfb, 0x0e40,
+ 0x6dfc, 0x1a21,
+ 0x6dfd, 0x3973,
+ 0x6e00, 0x3976,
+ 0x6e05, 0x0c62,
+ 0x6e06, 0x397b,
+ 0x6e0a, 0x10eb,
+ 0x6e0b, 0x397f,
+ 0x6e0c, 0x16e9,
+ 0x6e0d, 0x1232,
+ 0x6e0e, 0x16e0,
+ 0x6e0f, 0x3980,
+ 0x6e10, 0x0876,
+ 0x6e11, 0x16e3,
+ 0x6e12, 0x3981,
+ 0x6e14, 0x10cb,
+ 0x6e15, 0x3983,
+ 0x6e16, 0x16e7,
+ 0x6e17, 0x0d31,
+ 0x6e18, 0x3984,
+ 0x6e1a, 0x16dc,
+ 0x6e1b, 0x3986,
+ 0x6e1d, 0x10ca,
+ 0x6e1e, 0x3988,
+ 0x6e20, 0x0c7b,
+ 0x6e21, 0x0608,
+ 0x6e22, 0x398a,
+ 0x6e23, 0x113f,
+ 0x6e24, 0x047a,
+ 0x6e25, 0x16f5,
+ 0x6e26, 0x219f,
+ 0x6e27, 0x398b,
+ 0x6e29, 0x0ed1,
+ 0x6e2a, 0x398d,
+ 0x6e2b, 0x16eb,
+ 0x6e2c, 0x1e66,
+ 0x6e2d, 0x0ecb,
+ 0x6e2e, 0x398e,
+ 0x6e2f, 0x06d6,
+ 0x6e30, 0x398f,
+ 0x6e32, 0x16f4,
+ 0x6e33, 0x3991,
+ 0x6e34, 0x0957,
+ 0x6e35, 0x3992,
+ 0x6e38, 0x10b3,
+ 0x6e39, 0x3995,
+ 0x6e3a, 0x0af1,
+ 0x6e3b, 0x3996,
+ 0x6e3e, 0x1f63,
+ 0x6e3f, 0x3999,
+ 0x6e43, 0x0b89,
+ 0x6e44, 0x16f6,
+ 0x6e45, 0x399d,
+ 0x6e4d, 0x0e75,
+ 0x6e4e, 0x16ed,
+ 0x6e4f, 0x39a5,
+ 0x6e53, 0x16f2,
+ 0x6e55, 0x39a9,
+ 0x6e56, 0x07b5,
+ 0x6e57, 0x39aa,
+ 0x6e58, 0x0f53,
+ 0x6e59, 0x39ab,
+ 0x6e5b, 0x1160,
+ 0x6e5c, 0x39ad,
+ 0x6e5e, 0x23dd,
+ 0x6e5f, 0x16f0,
+ 0x6e60, 0x39af,
+ 0x6e6b, 0x16ee,
+ 0x6e6c, 0x39ba,
+ 0x6e6e, 0x16ec,
+ 0x6e6f, 0x216b,
+ 0x6e70, 0x39bc,
+ 0x6e7e, 0x0e96,
+ 0x6e7f, 0x0d41,
+ 0x6e80, 0x39ca,
+ 0x6e83, 0x098e,
+ 0x6e84, 0x39cd,
+ 0x6e85, 0x0877,
+ 0x6e86, 0x16f1,
+ 0x6e87, 0x39ce,
+ 0x6e89, 0x06c3,
+ 0x6e8a, 0x39d0,
+ 0x6e8f, 0x1705,
+ 0x6e90, 0x10f7,
+ 0x6e91, 0x39d5,
+ 0x6e96, 0x22b5,
+ 0x6e97, 0x39da,
+ 0x6e98, 0x16f9,
+ 0x6e99, 0x39db,
+ 0x6e9c, 0x0a38,
+ 0x6e9d, 0x1f26,
+ 0x6e9e, 0x39de,
+ 0x6e9f, 0x1707,
+ 0x6ea0, 0x39df,
+ 0x6ea2, 0x106e,
+ 0x6ea3, 0x39e1,
+ 0x6ea5, 0x16fd,
+ 0x6ea6, 0x39e3,
+ 0x6ea7, 0x16fe,
+ 0x6ea8, 0x39e4,
+ 0x6eaa, 0x0f17,
+ 0x6eab, 0x39e6,
+ 0x6eaf, 0x0dd2,
+ 0x6eb0, 0x39ea,
+ 0x6eb1, 0x16f8,
+ 0x6eb2, 0x16ef,
+ 0x6eb3, 0x39eb,
+ 0x6eb4, 0x1703,
+ 0x6eb5, 0x39ec,
+ 0x6eb6, 0x0cb7,
+ 0x6eb7, 0x1701,
+ 0x6eb8, 0x39ed,
+ 0x6eba, 0x0b4a,
+ 0x6ebb, 0x1700,
+ 0x6ebc, 0x39ef,
+ 0x6ebd, 0x16ff,
+ 0x6ebe, 0x39f0,
+ 0x6ec1, 0x0521,
+ 0x6ec2, 0x1706,
+ 0x6ec3, 0x39f3,
+ 0x6ec4, 0x1e63,
+ 0x6ec5, 0x2088,
+ 0x6ec6, 0x39f4,
+ 0x6ec7, 0x05c2,
+ 0x6ec8, 0x39f5,
+ 0x6ecb, 0x1229,
+ 0x6ecc, 0x1ebd,
+ 0x6ecd, 0x39f8,
+ 0x6ece, 0x2341,
+ 0x6ecf, 0x1704,
+ 0x6ed0, 0x39f9,
+ 0x6ed1, 0x07c1,
+ 0x6ed2, 0x39fa,
+ 0x6ed3, 0x122f,
+ 0x6ed4, 0x0e22,
+ 0x6ed5, 0x19a8,
+ 0x6ed6, 0x39fb,
+ 0x6ed7, 0x1702,
+ 0x6ed8, 0x39fc,
+ 0x6eda, 0x074f,
+ 0x6edb, 0x39fe,
+ 0x6ede, 0x11cc,
+ 0x6edf, 0x16f7,
+ 0x6ee0, 0x16fa,
+ 0x6ee1, 0x0aa1,
+ 0x6ee2, 0x16fc,
+ 0x6ee3, 0x3a01,
+ 0x6ee4, 0x0a72,
+ 0x6ee5, 0x09af,
+ 0x6ee6, 0x0a77,
+ 0x6ee7, 0x3a02,
+ 0x6ee8, 0x045e,
+ 0x6ee9, 0x0e05,
+ 0x6eea, 0x3a03,
+ 0x6eec, 0x1f4b,
+ 0x6eed, 0x3a05,
+ 0x6eef, 0x2292,
+ 0x6ef0, 0x3a07,
+ 0x6ef2, 0x2124,
+ 0x6ef3, 0x3a09,
+ 0x6ef4, 0x05af,
+ 0x6ef5, 0x3a0a,
+ 0x6ef7, 0x2048,
+ 0x6ef8, 0x23e0,
+ 0x6ef9, 0x170d,
+ 0x6efa, 0x3a0c,
+ 0x6eff, 0x2077,
+ 0x6f00, 0x3a11,
+ 0x6f01, 0x223a,
+ 0x6f02, 0x0bce,
+ 0x6f03, 0x3a12,
+ 0x6f06, 0x0c00,
+ 0x6f07, 0x3a15,
+ 0x6f09, 0x1713,
+ 0x6f0a, 0x3a17,
+ 0x6f0f, 0x0a50,
+ 0x6f10, 0x3a1c,
+ 0x6f13, 0x09d7,
+ 0x6f14, 0x1006,
+ 0x6f15, 0x170c,
+ 0x6f16, 0x3a1f,
+ 0x6f1a, 0x20b1,
+ 0x6f1b, 0x3a23,
+ 0x6f20, 0x0b11,
+ 0x6f21, 0x3a28,
+ 0x6f22, 0x1f41,
+ 0x6f23, 0x201c,
+ 0x6f24, 0x170b,
+ 0x6f25, 0x3a29,
+ 0x6f29, 0x1714,
+ 0x6f2a, 0x1712,
+ 0x6f2b, 0x0aa5,
+ 0x6f2c, 0x22b8,
+ 0x6f2d, 0x16fb,
+ 0x6f2e, 0x3a2d,
+ 0x6f2f, 0x170e,
+ 0x6f30, 0x3a2e,
+ 0x6f31, 0x0d95,
+ 0x6f32, 0x2276,
+ 0x6f33, 0x1165,
+ 0x6f34, 0x3a2f,
+ 0x6f36, 0x170f,
+ 0x6f37, 0x3a31,
+ 0x6f38, 0x1f9b,
+ 0x6f39, 0x3a32,
+ 0x6f3e, 0x1023,
+ 0x6f3f, 0x1f9f,
+ 0x6f40, 0x3a37,
+ 0x6f41, 0x25ca,
+ 0x6f42, 0x3a38,
+ 0x6f46, 0x1709,
+ 0x6f48, 0x3a3c,
+ 0x6f4b, 0x1710,
+ 0x6f4c, 0x3a3f,
+ 0x6f4d, 0x0eba,
+ 0x6f4e, 0x3a40,
+ 0x6f51, 0x20be,
+ 0x6f52, 0x3a43,
+ 0x6f54, 0x1fb4,
+ 0x6f55, 0x3a45,
+ 0x6f58, 0x0b8c,
+ 0x6f59, 0x23d7,
+ 0x6f5a, 0x3a48,
+ 0x6f5c, 0x0c2e,
+ 0x6f5d, 0x3a4a,
+ 0x6f5e, 0x0a61,
+ 0x6f5f, 0x3a4b,
+ 0x6f62, 0x1708,
+ 0x6f63, 0x3a4e,
+ 0x6f64, 0x2105,
+ 0x6f65, 0x3a4f,
+ 0x6f66, 0x0a13,
+ 0x6f67, 0x3a50,
+ 0x6f6d, 0x0e09,
+ 0x6f6e, 0x04d6,
+ 0x6f6f, 0x23e1,
+ 0x6f70, 0x1fec,
+ 0x6f71, 0x3a56,
+ 0x6f72, 0x1719,
+ 0x6f73, 0x3a57,
+ 0x6f74, 0x1711,
+ 0x6f75, 0x3a58,
+ 0x6f77, 0x23ea,
+ 0x6f78, 0x1718,
+ 0x6f79, 0x3a5a,
+ 0x6f7a, 0x171b,
+ 0x6f7b, 0x3a5b,
+ 0x6f7c, 0x171a,
+ 0x6f7d, 0x3a5c,
+ 0x6f7f, 0x23e3,
+ 0x6f80, 0x210e,
+ 0x6f81, 0x3a5e,
+ 0x6f84, 0x04f3,
+ 0x6f85, 0x3a61,
+ 0x6f86, 0x1fa6,
+ 0x6f87, 0x2004,
+ 0x6f88, 0x04df,
+ 0x6f89, 0x1715,
+ 0x6f8a, 0x3a62,
+ 0x6f8c, 0x1717,
+ 0x6f8d, 0x1716,
+ 0x6f8e, 0x0bad,
+ 0x6f8f, 0x3a64,
+ 0x6f97, 0x1f9d,
+ 0x6f98, 0x3a6c,
+ 0x6f9c, 0x09a8,
+ 0x6f9d, 0x3a70,
+ 0x6fa0, 0x23e5,
+ 0x6fa1, 0x112b,
+ 0x6fa2, 0x3a73,
+ 0x6fa4, 0x2264,
+ 0x6fa5, 0x3a75,
+ 0x6fa7, 0x171e,
+ 0x6fa8, 0x3a77,
+ 0x6fa9, 0x24e2,
+ 0x6faa, 0x3a78,
+ 0x6fae, 0x23de,
+ 0x6faf, 0x3a7c,
+ 0x6fb1, 0x1ec4,
+ 0x6fb2, 0x3a7e,
+ 0x6fb3, 0x03cf,
+ 0x6fb4, 0x3a7f,
+ 0x6fb6, 0x1720,
+ 0x6fb7, 0x3a81,
+ 0x6fb9, 0x171f,
+ 0x6fba, 0x3a83,
+ 0x6fc0, 0x0817,
+ 0x6fc1, 0x22b6,
+ 0x6fc2, 0x1721,
+ 0x6fc3, 0x20a9,
+ 0x6fc4, 0x3a89,
+ 0x6fc9, 0x171d,
+ 0x6fca, 0x3a8e,
+ 0x6fd1, 0x171c,
+ 0x6fd2, 0x045d,
+ 0x6fd3, 0x3a95,
+ 0x6fd5, 0x212b,
+ 0x6fd6, 0x3a97,
+ 0x6fd8, 0x20a5,
+ 0x6fd9, 0x3a99,
+ 0x6fdb, 0x268b,
+ 0x6fdc, 0x3a9b,
+ 0x6fde, 0x1724,
+ 0x6fdf, 0x1f76,
+ 0x6fe0, 0x1725,
+ 0x6fe1, 0x1722,
+ 0x6fe2, 0x3a9d,
+ 0x6fe4, 0x216d,
+ 0x6fe5, 0x3a9f,
+ 0x6feb, 0x2001,
+ 0x6fec, 0x3aa5,
+ 0x6fee, 0x1723,
+ 0x6fef, 0x1726,
+ 0x6ff0, 0x2191,
+ 0x6ff1, 0x1e50,
+ 0x6ff2, 0x3aa7,
+ 0x6ffa, 0x1f9c,
+ 0x6ffb, 0x3aaf,
+ 0x6ffc, 0x23da,
+ 0x6ffd, 0x3ab0,
+ 0x6ffe, 0x2053,
+ 0x6fff, 0x3ab1,
+ 0x7000, 0x3ab2,
+ 0x7005, 0x23e9,
+ 0x7006, 0x23e4,
+ 0x7007, 0x3ab7,
+ 0x7009, 0x21d5,
+ 0x700a, 0x3ab9,
+ 0x700b, 0x23e6,
+ 0x700c, 0x3aba,
+ 0x700f, 0x23df,
+ 0x7010, 0x3abd,
+ 0x7011, 0x0bf8,
+ 0x7012, 0x3abe,
+ 0x7015, 0x1e4f,
+ 0x7016, 0x3ac1,
+ 0x7018, 0x23d9,
+ 0x7019, 0x3ac3,
+ 0x701a, 0x1727,
+ 0x701b, 0x1729,
+ 0x701c, 0x3ac4,
+ 0x701d, 0x2014,
+ 0x701e, 0x3ac5,
+ 0x701f, 0x23ec,
+ 0x7020, 0x23eb,
+ 0x7021, 0x3ac6,
+ 0x7023, 0x1728,
+ 0x7024, 0x3ac8,
+ 0x7027, 0x23d8,
+ 0x7028, 0x23ee,
+ 0x7029, 0x3acb,
+ 0x7030, 0x268e,
+ 0x7031, 0x3ad2,
+ 0x7032, 0x23ed,
+ 0x7033, 0x3ad3,
+ 0x7035, 0x172b,
+ 0x7036, 0x3ad5,
+ 0x7039, 0x172a,
+ 0x703a, 0x3ad8,
+ 0x703e, 0x1ffa,
+ 0x703f, 0x3adc,
+ 0x7043, 0x23d6,
+ 0x7044, 0x23e8,
+ 0x7045, 0x3ae0,
+ 0x704c, 0x0739,
+ 0x704d, 0x3ae7,
+ 0x704f, 0x172c,
+ 0x7050, 0x3ae9,
+ 0x7051, 0x2106,
+ 0x7052, 0x3aea,
+ 0x7055, 0x200b,
+ 0x7056, 0x3aed,
+ 0x7058, 0x2166,
+ 0x7059, 0x3aef,
+ 0x705d, 0x23ef,
+ 0x705e, 0x172d,
+ 0x705f, 0x3af3,
+ 0x7063, 0x2189,
+ 0x7064, 0x2058,
+ 0x7065, 0x3af7,
+ 0x7067, 0x23e7,
+ 0x7068, 0x3af9,
+ 0x706b, 0x0805,
+ 0x706c, 0x19ef,
+ 0x706d, 0x0af5,
+ 0x706e, 0x3afc,
+ 0x706f, 0x05a7,
+ 0x7070, 0x07e7,
+ 0x7071, 0x3afd,
+ 0x7075, 0x0a32,
+ 0x7076, 0x1131,
+ 0x7077, 0x3b01,
+ 0x7078, 0x08f3,
+ 0x7079, 0x3b02,
+ 0x707c, 0x1223,
+ 0x707d, 0x3b05,
+ 0x707e, 0x1119,
+ 0x707f, 0x049a,
+ 0x7080, 0x19cc,
+ 0x7081, 0x3b06,
+ 0x7085, 0x1913,
+ 0x7086, 0x3b0a,
+ 0x7089, 0x0a56,
+ 0x708a, 0x0539,
+ 0x708b, 0x3b0d,
+ 0x708e, 0x1000,
+ 0x708f, 0x3b10,
+ 0x7092, 0x04d9,
+ 0x7093, 0x3b13,
+ 0x7094, 0x0c8d,
+ 0x7095, 0x0948,
+ 0x7096, 0x19ce,
+ 0x7097, 0x3b14,
+ 0x7099, 0x11ca,
+ 0x709a, 0x3b16,
+ 0x709c, 0x19cd,
+ 0x709d, 0x19cf,
+ 0x709e, 0x3b18,
+ 0x70ab, 0x19d3,
+ 0x70ac, 0x0915,
+ 0x70ad, 0x0e12,
+ 0x70ae, 0x0b9b,
+ 0x70af, 0x08eb,
+ 0x70b0, 0x3b25,
+ 0x70b1, 0x19d4,
+ 0x70b2, 0x3b26,
+ 0x70b3, 0x0467,
+ 0x70b4, 0x3b27,
+ 0x70b7, 0x19d2,
+ 0x70b8, 0x1149,
+ 0x70b9, 0x05c4,
+ 0x70ba, 0x3b2a,
+ 0x70bb, 0x19d0,
+ 0x70bc, 0x09ff,
+ 0x70bd, 0x0508,
+ 0x70be, 0x3b2b,
+ 0x70c0, 0x19d1,
+ 0x70c1, 0x0dad,
+ 0x70c2, 0x09ae,
+ 0x70c3, 0x0e51,
+ 0x70c4, 0x3b2d,
+ 0x70c8, 0x0a1b,
+ 0x70c9, 0x3b31,
+ 0x70ca, 0x19d6,
+ 0x70cb, 0x3b32,
+ 0x70cf, 0x21a3,
+ 0x70d0, 0x3b36,
+ 0x70d8, 0x079d,
+ 0x70d9, 0x09be,
+ 0x70da, 0x3b3e,
+ 0x70db, 0x11f1,
+ 0x70dc, 0x3b3f,
+ 0x70df, 0x0ff5,
+ 0x70e0, 0x3b42,
+ 0x70e4, 0x094b,
+ 0x70e5, 0x3b46,
+ 0x70e6, 0x0650,
+ 0x70e7, 0x0d0e,
+ 0x70e8, 0x19d5,
+ 0x70e9, 0x07f7,
+ 0x70ea, 0x3b47,
+ 0x70eb, 0x0e1f,
+ 0x70ec, 0x08ce,
+ 0x70ed, 0x0ca3,
+ 0x70ee, 0x3b48,
+ 0x70ef, 0x0f16,
+ 0x70f0, 0x3b49,
+ 0x70f4, 0x217a,
+ 0x70f5, 0x3b4d,
+ 0x70f7, 0x0e9a,
+ 0x70f8, 0x3b4f,
+ 0x70f9, 0x0bac,
+ 0x70fa, 0x3b50,
+ 0x70fd, 0x0686,
+ 0x70fe, 0x3b53,
+ 0x7100, 0x3b55,
+ 0x7109, 0x0ff2,
+ 0x710a, 0x076f,
+ 0x710b, 0x3b5e,
+ 0x7110, 0x19d7,
+ 0x7111, 0x3b63,
+ 0x7113, 0x19d8,
+ 0x7114, 0x3b65,
+ 0x7115, 0x07d5,
+ 0x7116, 0x19d9,
+ 0x7117, 0x3b66,
+ 0x7118, 0x19f0,
+ 0x7119, 0x0423,
+ 0x711a, 0x0676,
+ 0x711b, 0x3b67,
+ 0x7121, 0x21a5,
+ 0x7122, 0x3b6d,
+ 0x7126, 0x088a,
+ 0x7127, 0x3b71,
+ 0x712f, 0x19da,
+ 0x7130, 0x100f,
+ 0x7131, 0x19db,
+ 0x7132, 0x3b79,
+ 0x7136, 0x0c96,
+ 0x7137, 0x3b7d,
+ 0x7145, 0x19df,
+ 0x7146, 0x3b8b,
+ 0x7149, 0x2022,
+ 0x714a, 0x19e1,
+ 0x714b, 0x3b8e,
+ 0x714c, 0x07e2,
+ 0x714d, 0x3b8f,
+ 0x714e, 0x0858,
+ 0x714f, 0x3b90,
+ 0x7152, 0x24d6,
+ 0x7153, 0x3b93,
+ 0x715c, 0x19dd,
+ 0x715d, 0x3b9c,
+ 0x715e, 0x0cf0,
+ 0x715f, 0x3b9d,
+ 0x7162, 0x233a,
+ 0x7163, 0x3ba0,
+ 0x7164, 0x0abf,
+ 0x7165, 0x3ba1,
+ 0x7166, 0x19f1,
+ 0x7167, 0x1176,
+ 0x7168, 0x19de,
+ 0x7169, 0x1eee,
+ 0x716a, 0x3ba2,
+ 0x716c, 0x24d5,
+ 0x716d, 0x3ba4,
+ 0x716e, 0x11f2,
+ 0x716f, 0x3ba5,
+ 0x7172, 0x19e0,
+ 0x7173, 0x19dc,
+ 0x7174, 0x3ba8,
+ 0x7178, 0x19e2,
+ 0x7179, 0x3bac,
+ 0x717a, 0x19e3,
+ 0x717b, 0x3bad,
+ 0x717d, 0x0cf8,
+ 0x717e, 0x3baf,
+ 0x7184, 0x0f15,
+ 0x7185, 0x3bb5,
+ 0x718a, 0x0fa7,
+ 0x718b, 0x3bba,
+ 0x718f, 0x0fd5,
+ 0x7190, 0x3bbe,
+ 0x7192, 0x2228,
+ 0x7193, 0x3bc0,
+ 0x7194, 0x0cb6,
+ 0x7195, 0x3bc1,
+ 0x7197, 0x24d7,
+ 0x7198, 0x19e4,
+ 0x7199, 0x0f04,
+ 0x719a, 0x3bc3,
+ 0x719f, 0x0d83,
+ 0x71a0, 0x19e8,
+ 0x71a1, 0x3bc8,
+ 0x71a8, 0x19e7,
+ 0x71a9, 0x3bcf,
+ 0x71ac, 0x03c9,
+ 0x71ad, 0x3bd2,
+ 0x71b1, 0x20fc,
+ 0x71b2, 0x3bd6,
+ 0x71b3, 0x19e5,
+ 0x71b4, 0x3bd7,
+ 0x71b5, 0x19e6,
+ 0x71b6, 0x3bd8,
+ 0x71b9, 0x19f2,
+ 0x71ba, 0x3bdb,
+ 0x71be, 0x1e87,
+ 0x71bf, 0x3bdf,
+ 0x71c1, 0x24d8,
+ 0x71c2, 0x3be1,
+ 0x71c3, 0x0c97,
+ 0x71c4, 0x3be2,
+ 0x71c8, 0x1eba,
+ 0x71c9, 0x3be6,
+ 0x71ce, 0x0a10,
+ 0x71cf, 0x3beb,
+ 0x71d2, 0x2119,
+ 0x71d3, 0x3bee,
+ 0x71d4, 0x19ea,
+ 0x71d5, 0x1009,
+ 0x71d6, 0x3bef,
+ 0x71d9, 0x216c,
+ 0x71da, 0x3bf2,
+ 0x71dc, 0x24d9,
+ 0x71dd, 0x3bf4,
+ 0x71df, 0x2227,
+ 0x71e0, 0x19e9,
+ 0x71e1, 0x3bf6,
+ 0x71e5, 0x1132,
+ 0x71e6, 0x1e5f,
+ 0x71e7, 0x19eb,
+ 0x71e8, 0x3bfa,
+ 0x71ed, 0x229f,
+ 0x71ee, 0x1396,
+ 0x71ef, 0x3bff,
+ 0x71f4, 0x1f5d,
+ 0x71f5, 0x3c04,
+ 0x71f9, 0x19ec,
+ 0x71fa, 0x3c08,
+ 0x71fc, 0x1fbc,
+ 0x71fd, 0x3c0a,
+ 0x71fe, 0x24da,
+ 0x71ff, 0x3c0b,
+ 0x7200, 0x3c0c,
+ 0x7206, 0x0415,
+ 0x7207, 0x3c12,
+ 0x720d, 0x2149,
+ 0x720e, 0x3c18,
+ 0x7210, 0x2046,
+ 0x7211, 0x3c1a,
+ 0x721b, 0x2000,
+ 0x721c, 0x3c24,
+ 0x721d, 0x19ed,
+ 0x721e, 0x3c25,
+ 0x7228, 0x19ee,
+ 0x7229, 0x3c2f,
+ 0x722a, 0x1203,
+ 0x722b, 0x3c30,
+ 0x722c, 0x0b81,
+ 0x722d, 0x3c31,
+ 0x7230, 0x196c,
+ 0x7231, 0x03b9,
+ 0x7232, 0x2190,
+ 0x7233, 0x3c34,
+ 0x7235, 0x0923,
+ 0x7236, 0x06b3,
+ 0x7237, 0x1036,
+ 0x7238, 0x03e1,
+ 0x7239, 0x05da,
+ 0x723a, 0x2208,
+ 0x723b, 0x1269,
+ 0x723c, 0x3c36,
+ 0x723d, 0x0da1,
+ 0x723e, 0x1ee6,
+ 0x723f, 0x169d,
+ 0x7240, 0x3c37,
+ 0x7247, 0x0bcb,
+ 0x7248, 0x03f1,
+ 0x7249, 0x3c3e,
+ 0x724c, 0x0b87,
+ 0x724d, 0x1969,
+ 0x724e, 0x3c41,
+ 0x7252, 0x196a,
+ 0x7253, 0x3c45,
+ 0x7256, 0x196b,
+ 0x7257, 0x3c48,
+ 0x7258, 0x24c3,
+ 0x7259, 0x0fe9,
+ 0x725a, 0x3c49,
+ 0x725b, 0x0b64,
+ 0x725c, 0x3c4a,
+ 0x725d, 0x1944,
+ 0x725e, 0x3c4b,
+ 0x725f, 0x0b15,
+ 0x7260, 0x3c4c,
+ 0x7261, 0x0b18,
+ 0x7262, 0x09b9,
+ 0x7263, 0x3c4d,
+ 0x7266, 0x1945,
+ 0x7267, 0x0b24,
+ 0x7268, 0x3c50,
+ 0x7269, 0x0efe,
+ 0x726a, 0x3c51,
+ 0x726e, 0x1942,
+ 0x726f, 0x1946,
+ 0x7270, 0x3c55,
+ 0x7272, 0x0d35,
+ 0x7273, 0x3c57,
+ 0x7275, 0x0c20,
+ 0x7276, 0x3c59,
+ 0x7279, 0x0e2b,
+ 0x727a, 0x0f0d,
+ 0x727b, 0x3c5c,
+ 0x727d, 0x20cc,
+ 0x727e, 0x1947,
+ 0x7280, 0x0f19,
+ 0x7281, 0x09d2,
+ 0x7282, 0x3c5e,
+ 0x7284, 0x1949,
+ 0x7285, 0x3c60,
+ 0x728a, 0x05fe,
+ 0x728b, 0x194a,
+ 0x728c, 0x3c65,
+ 0x728d, 0x194b,
+ 0x728e, 0x3c66,
+ 0x728f, 0x194c,
+ 0x7290, 0x3c67,
+ 0x7292, 0x194d,
+ 0x7293, 0x3c69,
+ 0x7296, 0x2340,
+ 0x7297, 0x3c6c,
+ 0x729f, 0x1943,
+ 0x72a0, 0x3c74,
+ 0x72a2, 0x1ed1,
+ 0x72a3, 0x3c76,
+ 0x72a7, 0x21ac,
+ 0x72a8, 0x3c7a,
+ 0x72ac, 0x0c89,
+ 0x72ad, 0x15ef,
+ 0x72ae, 0x3c7e,
+ 0x72af, 0x0655,
+ 0x72b0, 0x15f0,
+ 0x72b1, 0x3c7f,
+ 0x72b4, 0x15f1,
+ 0x72b5, 0x3c82,
+ 0x72b6, 0x1211,
+ 0x72b7, 0x15f2,
+ 0x72b9, 0x10b1,
+ 0x72ba, 0x3c83,
+ 0x72c0, 0x22af,
+ 0x72c1, 0x15f5,
+ 0x72c2, 0x097e,
+ 0x72c3, 0x15f4,
+ 0x72c4, 0x05b3,
+ 0x72c5, 0x3c89,
+ 0x72c8, 0x0420,
+ 0x72c9, 0x3c8c,
+ 0x72cd, 0x15f7,
+ 0x72ce, 0x15f6,
+ 0x72cf, 0x3c90,
+ 0x72d0, 0x07b3,
+ 0x72d1, 0x3c91,
+ 0x72d2, 0x15f8,
+ 0x72d3, 0x3c92,
+ 0x72d7, 0x0710,
+ 0x72d8, 0x3c96,
+ 0x72d9, 0x0900,
+ 0x72da, 0x3c97,
+ 0x72de, 0x0b5f,
+ 0x72df, 0x3c9b,
+ 0x72e0, 0x0794,
+ 0x72e1, 0x0897,
+ 0x72e2, 0x3c9c,
+ 0x72e8, 0x15f9,
+ 0x72e9, 0x15fb,
+ 0x72ea, 0x3ca2,
+ 0x72ec, 0x05ff,
+ 0x72ed, 0x0f2e,
+ 0x72ee, 0x0d3f,
+ 0x72ef, 0x15fa,
+ 0x72f0, 0x1199,
+ 0x72f1, 0x10e1,
+ 0x72f2, 0x15fc,
+ 0x72f3, 0x1600,
+ 0x72f4, 0x15fd,
+ 0x72f5, 0x3ca4,
+ 0x72f7, 0x15fe,
+ 0x72f8, 0x09d5,
+ 0x72f9, 0x21b6,
+ 0x72fa, 0x1602,
+ 0x72fc, 0x09b2,
+ 0x72fd, 0x1e3d,
+ 0x72fe, 0x3ca6,
+ 0x7300, 0x3ca8,
+ 0x7301, 0x15ff,
+ 0x7302, 0x3ca9,
+ 0x7303, 0x1601,
+ 0x7304, 0x3caa,
+ 0x730a, 0x1607,
+ 0x730b, 0x3cb0,
+ 0x730e, 0x0a1d,
+ 0x730f, 0x3cb3,
+ 0x7313, 0x1605,
+ 0x7314, 0x3cb7,
+ 0x7315, 0x160a,
+ 0x7316, 0x04c5,
+ 0x7317, 0x1604,
+ 0x7318, 0x3cb8,
+ 0x731b, 0x0ad2,
+ 0x731c, 0x0489,
+ 0x731d, 0x1609,
+ 0x731e, 0x1608,
+ 0x731f, 0x3cbb,
+ 0x7321, 0x1606,
+ 0x7322, 0x160b,
+ 0x7323, 0x3cbd,
+ 0x7325, 0x160d,
+ 0x7326, 0x3cbf,
+ 0x7329, 0x0f94,
+ 0x732a, 0x11ec,
+ 0x732b, 0x0aad,
+ 0x732c, 0x160e,
+ 0x732d, 0x3cc2,
+ 0x732e, 0x0f44,
+ 0x732f, 0x3cc3,
+ 0x7331, 0x1610,
+ 0x7332, 0x3cc5,
+ 0x7334, 0x07a6,
+ 0x7335, 0x3cc7,
+ 0x7336, 0x2235,
+ 0x7337, 0x18d4,
+ 0x7338, 0x160f,
+ 0x7339, 0x160c,
+ 0x733a, 0x3cc8,
+ 0x733b, 0x2397,
+ 0x733c, 0x3cc9,
+ 0x733e, 0x07c0,
+ 0x733f, 0x10f6,
+ 0x7340, 0x3ccb,
+ 0x7341, 0x2395,
+ 0x7342, 0x3ccc,
+ 0x7344, 0x223f,
+ 0x7345, 0x212a,
+ 0x7346, 0x3cce,
+ 0x734d, 0x1612,
+ 0x734e, 0x3cd5,
+ 0x7350, 0x1611,
+ 0x7351, 0x3cd7,
+ 0x7352, 0x18d5,
+ 0x7353, 0x3cd8,
+ 0x7357, 0x1613,
+ 0x7358, 0x3cdc,
+ 0x7360, 0x1614,
+ 0x7361, 0x3ce4,
+ 0x7368, 0x1ed2,
+ 0x7369, 0x3ceb,
+ 0x736a, 0x2396,
+ 0x736b, 0x2398,
+ 0x736c, 0x1615,
+ 0x736d, 0x0df4,
+ 0x736e, 0x3cec,
+ 0x736f, 0x1616,
+ 0x7370, 0x20a2,
+ 0x7371, 0x3ced,
+ 0x7372, 0x1f64,
+ 0x7373, 0x3cee,
+ 0x7375, 0x202b,
+ 0x7376, 0x3cf0,
+ 0x7377, 0x2394,
+ 0x7378, 0x2139,
+ 0x7379, 0x3cf1,
+ 0x737a, 0x215f,
+ 0x737b, 0x21c1,
+ 0x737c, 0x239a,
+ 0x737d, 0x3cf2,
+ 0x737e, 0x1617,
+ 0x737f, 0x3cf3,
+ 0x7380, 0x2399,
+ 0x7381, 0x3cf4,
+ 0x7384, 0x0fc9,
+ 0x7385, 0x3cf7,
+ 0x7387, 0x0a71,
+ 0x7388, 0x3cf9,
+ 0x7389, 0x10d6,
+ 0x738a, 0x3cfa,
+ 0x738b, 0x0ea6,
+ 0x738c, 0x3cfb,
+ 0x738e, 0x1818,
+ 0x738f, 0x3cfd,
+ 0x7391, 0x1819,
+ 0x7392, 0x3cff,
+ 0x7396, 0x08f0,
+ 0x7397, 0x3d03,
+ 0x739b, 0x0a91,
+ 0x739c, 0x3d07,
+ 0x739f, 0x181c,
+ 0x73a0, 0x3d0a,
+ 0x73a2, 0x181b,
+ 0x73a3, 0x3d0c,
+ 0x73a9, 0x0e97,
+ 0x73aa, 0x3d12,
+ 0x73ab, 0x0aba,
+ 0x73ac, 0x3d13,
+ 0x73ae, 0x181a,
+ 0x73af, 0x07cc,
+ 0x73b0, 0x0f43,
+ 0x73b1, 0x3d15,
+ 0x73b2, 0x0a2a,
+ 0x73b3, 0x1821,
+ 0x73b4, 0x3d16,
+ 0x73b7, 0x1820,
+ 0x73b8, 0x3d19,
+ 0x73ba, 0x182c,
+ 0x73bb, 0x046a,
+ 0x73bc, 0x3d1b,
+ 0x73c0, 0x1822,
+ 0x73c1, 0x3d1f,
+ 0x73c2, 0x181e,
+ 0x73c3, 0x3d20,
+ 0x73c8, 0x1824,
+ 0x73c9, 0x1823,
+ 0x73ca, 0x0cf3,
+ 0x73cb, 0x3d25,
+ 0x73cd, 0x1185,
+ 0x73ce, 0x3d27,
+ 0x73cf, 0x181d,
+ 0x73d0, 0x0646,
+ 0x73d1, 0x181f,
+ 0x73d2, 0x3d28,
+ 0x73d9, 0x1826,
+ 0x73da, 0x3d2f,
+ 0x73de, 0x182b,
+ 0x73df, 0x3d33,
+ 0x73e0, 0x11e8,
+ 0x73e1, 0x3d34,
+ 0x73e5, 0x1825,
+ 0x73e6, 0x3d38,
+ 0x73e7, 0x182a,
+ 0x73e8, 0x3d39,
+ 0x73e9, 0x1829,
+ 0x73ea, 0x3d3a,
+ 0x73ed, 0x03eb,
+ 0x73ee, 0x3d3d,
+ 0x73f2, 0x182d,
+ 0x73f3, 0x3d41,
+ 0x73fe, 0x21c0,
+ 0x73ff, 0x3d4c,
+ 0x7400, 0x3d4d,
+ 0x7403, 0x0c6f,
+ 0x7404, 0x3d50,
+ 0x7405, 0x09b0,
+ 0x7406, 0x09d8,
+ 0x7407, 0x3d51,
+ 0x7409, 0x0a39,
+ 0x740a, 0x1828,
+ 0x740b, 0x3d53,
+ 0x740f, 0x182e,
+ 0x7410, 0x0deb,
+ 0x7411, 0x3d57,
+ 0x741a, 0x1838,
+ 0x741b, 0x1837,
+ 0x741c, 0x3d60,
+ 0x7422, 0x121e,
+ 0x7423, 0x3d66,
+ 0x7425, 0x1832,
+ 0x7426, 0x1831,
+ 0x7427, 0x3d68,
+ 0x7428, 0x1833,
+ 0x7429, 0x3d69,
+ 0x742a, 0x182f,
+ 0x742b, 0x3d6a,
+ 0x742c, 0x1836,
+ 0x742d, 0x3d6b,
+ 0x742e, 0x1835,
+ 0x742f, 0x3d6c,
+ 0x7430, 0x1834,
+ 0x7431, 0x3d6d,
+ 0x7433, 0x0a1e,
+ 0x7434, 0x0c56,
+ 0x7435, 0x0bbe,
+ 0x7436, 0x0b84,
+ 0x7437, 0x3d6f,
+ 0x743c, 0x0c6a,
+ 0x743d, 0x3d74,
+ 0x743f, 0x2460,
+ 0x7440, 0x3d76,
+ 0x7441, 0x1839,
+ 0x7442, 0x3d77,
+ 0x744b, 0x245c,
+ 0x744c, 0x3d80,
+ 0x7455, 0x183c,
+ 0x7456, 0x3d89,
+ 0x7457, 0x183b,
+ 0x7458, 0x3d8a,
+ 0x7459, 0x183d,
+ 0x745a, 0x07ae,
+ 0x745b, 0x1830,
+ 0x745c, 0x183a,
+ 0x745d, 0x3d8b,
+ 0x745e, 0x0ccb,
+ 0x745f, 0x0ce3,
+ 0x7460, 0x3d8c,
+ 0x7463, 0x215d,
+ 0x7464, 0x3d8f,
+ 0x7469, 0x2225,
+ 0x746a, 0x206a,
+ 0x746b, 0x3d94,
+ 0x746d, 0x183f,
+ 0x746e, 0x3d96,
+ 0x7470, 0x073e,
+ 0x7471, 0x3d98,
+ 0x7476, 0x1027,
+ 0x7477, 0x183e,
+ 0x7478, 0x3d9d,
+ 0x747e, 0x1840,
+ 0x747f, 0x3da3,
+ 0x7480, 0x1843,
+ 0x7482, 0x3da4,
+ 0x7483, 0x09f0,
+ 0x7484, 0x3da5,
+ 0x7487, 0x1845,
+ 0x7488, 0x3da8,
+ 0x7489, 0x2461,
+ 0x748a, 0x3da9,
+ 0x748b, 0x1846,
+ 0x748c, 0x3daa,
+ 0x748e, 0x1842,
+ 0x748f, 0x3dac,
+ 0x7490, 0x184a,
+ 0x7491, 0x3dad,
+ 0x749c, 0x1841,
+ 0x749d, 0x3db8,
+ 0x749e, 0x1847,
+ 0x749f, 0x3db9,
+ 0x74a3, 0x245b,
+ 0x74a4, 0x3dbd,
+ 0x74a6, 0x2462,
+ 0x74a7, 0x184b,
+ 0x74a8, 0x1848,
+ 0x74aa, 0x3dbf,
+ 0x74b0, 0x1f54,
+ 0x74b1, 0x3dc5,
+ 0x74ba, 0x184d,
+ 0x74bb, 0x3dce,
+ 0x74bd, 0x245f,
+ 0x74be, 0x3dd0,
+ 0x74ca, 0x20ec,
+ 0x74cb, 0x3ddc,
+ 0x74cf, 0x245d,
+ 0x74d0, 0x3de0,
+ 0x74d2, 0x184c,
+ 0x74d3, 0x3de2,
+ 0x74d4, 0x2463,
+ 0x74d5, 0x3de3,
+ 0x74da, 0x2464,
+ 0x74db, 0x3de8,
+ 0x74dc, 0x0728,
+ 0x74dd, 0x3de9,
+ 0x74de, 0x1b32,
+ 0x74df, 0x3dea,
+ 0x74e0, 0x1b33,
+ 0x74e1, 0x3deb,
+ 0x74e2, 0x0bcf,
+ 0x74e3, 0x03f5,
+ 0x74e4, 0x0c9a,
+ 0x74e5, 0x3dec,
+ 0x74e6, 0x0e90,
+ 0x74e7, 0x3ded,
+ 0x74ee, 0x0edc,
+ 0x74ef, 0x1903,
+ 0x74f0, 0x3df4,
+ 0x74f4, 0x1904,
+ 0x74f5, 0x3df8,
+ 0x74f6, 0x0bde,
+ 0x74f7, 0x054c,
+ 0x74f8, 0x3df9,
+ 0x74ff, 0x1905,
+ 0x7500, 0x3e00,
+ 0x7504, 0x1188,
+ 0x7505, 0x3e04,
+ 0x750c, 0x24a5,
+ 0x750d, 0x1485,
+ 0x750e, 0x3e0b,
+ 0x750f, 0x1906,
+ 0x7510, 0x3e0c,
+ 0x7511, 0x1907,
+ 0x7512, 0x3e0d,
+ 0x7513, 0x1908,
+ 0x7514, 0x3e0e,
+ 0x7518, 0x06c5,
+ 0x7519, 0x14f8,
+ 0x751a, 0x0d2e,
+ 0x751b, 0x3e12,
+ 0x751c, 0x0e43,
+ 0x751d, 0x3e13,
+ 0x751f, 0x0d33,
+ 0x7520, 0x3e15,
+ 0x7523, 0x1e70,
+ 0x7524, 0x3e18,
+ 0x7525, 0x0d34,
+ 0x7526, 0x3e19,
+ 0x7528, 0x10a8,
+ 0x7529, 0x0d9b,
+ 0x752a, 0x3e1b,
+ 0x752b, 0x06a1,
+ 0x752c, 0x1b34,
+ 0x752d, 0x042b,
+ 0x752e, 0x3e1c,
+ 0x752f, 0x1734,
+ 0x7530, 0x0e42,
+ 0x7531, 0x10ae,
+ 0x7532, 0x084a,
+ 0x7533, 0x0d23,
+ 0x7534, 0x3e1d,
+ 0x7535, 0x05c8,
+ 0x7536, 0x3e1e,
+ 0x7537, 0x0b33,
+ 0x7538, 0x05ca,
+ 0x7539, 0x3e1f,
+ 0x753a, 0x1a78,
+ 0x753b, 0x07c2,
+ 0x753c, 0x3e20,
+ 0x753e, 0x1816,
+ 0x753f, 0x3e22,
+ 0x7540, 0x1a79,
+ 0x7541, 0x3e23,
+ 0x7545, 0x04ce,
+ 0x7546, 0x3e27,
+ 0x7548, 0x1a7c,
+ 0x7549, 0x3e29,
+ 0x754b, 0x1a7b,
+ 0x754c, 0x08b8,
+ 0x754d, 0x3e2b,
+ 0x754e, 0x1a7a,
+ 0x754f, 0x0ec6,
+ 0x7550, 0x3e2c,
+ 0x7554, 0x0b90,
+ 0x7555, 0x3e30,
+ 0x7559, 0x0a3d,
+ 0x755a, 0x139e,
+ 0x755b, 0x1a7d,
+ 0x755c, 0x0fbe,
+ 0x755d, 0x208f,
+ 0x755e, 0x3e34,
+ 0x7562, 0x1e42,
+ 0x7563, 0x3e38,
+ 0x7565, 0x0a7b,
+ 0x7566, 0x0c07,
+ 0x7567, 0x3e3a,
+ 0x756a, 0x0649,
+ 0x756b, 0x1f4e,
+ 0x756c, 0x3e3d,
+ 0x7572, 0x1a7e,
+ 0x7573, 0x3e43,
+ 0x7574, 0x0510,
+ 0x7575, 0x3e44,
+ 0x7576, 0x1eb1,
+ 0x7577, 0x3e45,
+ 0x7578, 0x0810,
+ 0x7579, 0x1a7f,
+ 0x757a, 0x3e46,
+ 0x757f, 0x1814,
+ 0x7580, 0x3e4b,
+ 0x7583, 0x1a80,
+ 0x7584, 0x3e4e,
+ 0x7586, 0x087f,
+ 0x7587, 0x1e8b,
+ 0x7588, 0x3e50,
+ 0x758b, 0x1bc6,
+ 0x758c, 0x3e53,
+ 0x758f, 0x0d7f,
+ 0x7590, 0x3e56,
+ 0x7591, 0x1050,
+ 0x7592, 0x1b60,
+ 0x7593, 0x3e57,
+ 0x7594, 0x1b61,
+ 0x7595, 0x3e58,
+ 0x7596, 0x1b62,
+ 0x7597, 0x0a0f,
+ 0x7598, 0x3e59,
+ 0x7599, 0x06e8,
+ 0x759a, 0x08fd,
+ 0x759b, 0x3e5a,
+ 0x759d, 0x1b64,
+ 0x759e, 0x3e5c,
+ 0x759f, 0x0b72,
+ 0x75a0, 0x1b63,
+ 0x75a1, 0x101a,
+ 0x75a2, 0x3e5d,
+ 0x75a3, 0x1b66,
+ 0x75a4, 0x03d7,
+ 0x75a5, 0x08bb,
+ 0x75a6, 0x3e5e,
+ 0x75ab, 0x1066,
+ 0x75ac, 0x1b65,
+ 0x75ad, 0x3e63,
+ 0x75ae, 0x0532,
+ 0x75af, 0x0685,
+ 0x75b0, 0x1b6c,
+ 0x75b1, 0x1b6b,
+ 0x75b2, 0x0bc2,
+ 0x75b3, 0x1b67,
+ 0x75b5, 0x0546,
+ 0x75b6, 0x3e64,
+ 0x75b8, 0x1b69,
+ 0x75b9, 0x118f,
+ 0x75ba, 0x3e66,
+ 0x75bc, 0x0e2e,
+ 0x75bd, 0x0901,
+ 0x75be, 0x0825,
+ 0x75bf, 0x3e68,
+ 0x75c2, 0x1b6e,
+ 0x75c3, 0x1b6d,
+ 0x75c4, 0x1b6a,
+ 0x75c5, 0x0468,
+ 0x75c6, 0x3e6b,
+ 0x75c7, 0x11a1,
+ 0x75c8, 0x109d,
+ 0x75c9, 0x08e6,
+ 0x75ca, 0x0c87,
+ 0x75cb, 0x3e6c,
+ 0x75cd, 0x1b70,
+ 0x75ce, 0x3e6e,
+ 0x75d2, 0x1020,
+ 0x75d3, 0x3e72,
+ 0x75d4, 0x11cb,
+ 0x75d5, 0x0792,
+ 0x75d6, 0x1b6f,
+ 0x75d7, 0x3e73,
+ 0x75d8, 0x05fa,
+ 0x75d9, 0x1fc6,
+ 0x75da, 0x3e74,
+ 0x75db, 0x0e65,
+ 0x75dc, 0x3e75,
+ 0x75de, 0x0bc5,
+ 0x75df, 0x3e77,
+ 0x75e2, 0x09ea,
+ 0x75e3, 0x1b71,
+ 0x75e4, 0x1b74,
+ 0x75e5, 0x3e7a,
+ 0x75e6, 0x1b73,
+ 0x75e7, 0x1b76,
+ 0x75e8, 0x1b72,
+ 0x75e9, 0x3e7b,
+ 0x75ea, 0x07d3,
+ 0x75eb, 0x1b75,
+ 0x75ec, 0x3e7c,
+ 0x75f0, 0x0e08,
+ 0x75f1, 0x1b78,
+ 0x75f2, 0x3e80,
+ 0x75f4, 0x04fa,
+ 0x75f5, 0x3e82,
+ 0x75f9, 0x043d,
+ 0x75fa, 0x3e86,
+ 0x75fc, 0x1b79,
+ 0x75fd, 0x3e88,
+ 0x75ff, 0x1b7a,
+ 0x7600, 0x1b7c,
+ 0x7601, 0x0564,
+ 0x7602, 0x25ae,
+ 0x7603, 0x1b77,
+ 0x7604, 0x3e8a,
+ 0x7605, 0x1b7d,
+ 0x7606, 0x3e8b,
+ 0x760a, 0x1b80,
+ 0x760b, 0x1f01,
+ 0x760c, 0x1b7e,
+ 0x760d, 0x2200,
+ 0x760e, 0x3e8f,
+ 0x7610, 0x1b7b,
+ 0x7611, 0x3e91,
+ 0x7615, 0x1b83,
+ 0x7616, 0x3e95,
+ 0x7617, 0x1b7f,
+ 0x7618, 0x1b82,
+ 0x7619, 0x1b84,
+ 0x761a, 0x3e96,
+ 0x761b, 0x1b85,
+ 0x761c, 0x3e97,
+ 0x761e, 0x25b2,
+ 0x761f, 0x0ed0,
+ 0x7620, 0x1b88,
+ 0x7621, 0x1e97,
+ 0x7622, 0x1b87,
+ 0x7623, 0x3e99,
+ 0x7624, 0x0a3f,
+ 0x7625, 0x1b81,
+ 0x7626, 0x0d74,
+ 0x7627, 0x20ab,
+ 0x7628, 0x3e9a,
+ 0x7629, 0x0574,
+ 0x762a, 0x045a,
+ 0x762b, 0x0e04,
+ 0x762c, 0x3e9b,
+ 0x762d, 0x1b8a,
+ 0x762e, 0x3e9c,
+ 0x7630, 0x1b8b,
+ 0x7631, 0x3e9e,
+ 0x7633, 0x1b90,
+ 0x7634, 0x116f,
+ 0x7635, 0x1b8d,
+ 0x7636, 0x3ea0,
+ 0x7638, 0x0c8e,
+ 0x7639, 0x3ea2,
+ 0x763b, 0x25b3,
+ 0x763c, 0x1b86,
+ 0x763d, 0x3ea4,
+ 0x763e, 0x1b8f,
+ 0x763f, 0x1b8c,
+ 0x7640, 0x1b89,
+ 0x7641, 0x3ea5,
+ 0x7642, 0x2028,
+ 0x7643, 0x1b8e,
+ 0x7644, 0x3ea6,
+ 0x7646, 0x25af,
+ 0x7648, 0x3ea8,
+ 0x7649, 0x25b1,
+ 0x764a, 0x3ea9,
+ 0x764c, 0x03b4,
+ 0x764d, 0x1b91,
+ 0x764e, 0x3eab,
+ 0x7654, 0x1b93,
+ 0x7655, 0x3eb1,
+ 0x7656, 0x1b95,
+ 0x7657, 0x3eb2,
+ 0x7658, 0x25ac,
+ 0x7659, 0x3eb3,
+ 0x765c, 0x1b94,
+ 0x765d, 0x3eb6,
+ 0x765e, 0x1b92,
+ 0x765f, 0x1e4e,
+ 0x7660, 0x3eb7,
+ 0x7662, 0x2202,
+ 0x7663, 0x0fcb,
+ 0x7664, 0x25ab,
+ 0x7665, 0x2286,
+ 0x7666, 0x3eb9,
+ 0x7667, 0x25ad,
+ 0x7668, 0x3eba,
+ 0x7669, 0x25b6,
+ 0x766a, 0x3ebb,
+ 0x766b, 0x1b96,
+ 0x766c, 0x21e3,
+ 0x766d, 0x25b4,
+ 0x766f, 0x1b97,
+ 0x7670, 0x222f,
+ 0x7671, 0x2165,
+ 0x7672, 0x25b7,
+ 0x7673, 0x3ebc,
+ 0x7678, 0x0748,
+ 0x7679, 0x3ec1,
+ 0x767b, 0x05a8,
+ 0x767c, 0x1ee9,
+ 0x767d, 0x03e2,
+ 0x767e, 0x03e4,
+ 0x767f, 0x3ec3,
+ 0x7682, 0x1130,
+ 0x7683, 0x3ec6,
+ 0x7684, 0x05a5,
+ 0x7685, 0x3ec7,
+ 0x7686, 0x08a5,
+ 0x7687, 0x07df,
+ 0x7688, 0x1b2d,
+ 0x7689, 0x3ec8,
+ 0x768b, 0x06d9,
+ 0x768c, 0x3eca,
+ 0x768e, 0x1b2e,
+ 0x768f, 0x3ecc,
+ 0x7691, 0x03b3,
+ 0x7692, 0x3ece,
+ 0x7693, 0x1b2f,
+ 0x7694, 0x3ecf,
+ 0x7696, 0x0e9f,
+ 0x7697, 0x3ed1,
+ 0x7699, 0x1b30,
+ 0x769a, 0x1e25,
+ 0x769b, 0x3ed3,
+ 0x76a4, 0x1b31,
+ 0x76a5, 0x3edc,
+ 0x76ae, 0x0bc3,
+ 0x76af, 0x3ee5,
+ 0x76b1, 0x11e4,
+ 0x76b2, 0x1bc8,
+ 0x76b3, 0x3ee7,
+ 0x76b4, 0x1bc9,
+ 0x76b5, 0x3ee8,
+ 0x76b8, 0x25c0,
+ 0x76b9, 0x3eeb,
+ 0x76ba, 0x229a,
+ 0x76bb, 0x3eec,
+ 0x76bf, 0x0af8,
+ 0x76c0, 0x3ef0,
+ 0x76c2, 0x10c0,
+ 0x76c3, 0x3ef2,
+ 0x76c5, 0x11d0,
+ 0x76c6, 0x0ba9,
+ 0x76c7, 0x3ef4,
+ 0x76c8, 0x1094,
+ 0x76c9, 0x3ef5,
+ 0x76ca, 0x106d,
+ 0x76cb, 0x3ef6,
+ 0x76cd, 0x1a8b,
+ 0x76ce, 0x03c6,
+ 0x76cf, 0x1156,
+ 0x76d0, 0x0ff7,
+ 0x76d1, 0x0853,
+ 0x76d2, 0x0787,
+ 0x76d3, 0x3ef8,
+ 0x76d4, 0x0985,
+ 0x76d5, 0x3ef9,
+ 0x76d6, 0x06c2,
+ 0x76d7, 0x05a2,
+ 0x76d8, 0x0b8d,
+ 0x76d9, 0x3efa,
+ 0x76db, 0x0d39,
+ 0x76dc, 0x3efc,
+ 0x76de, 0x226e,
+ 0x76df, 0x0ad0,
+ 0x76e0, 0x3efe,
+ 0x76e1, 0x1fbd,
+ 0x76e2, 0x3eff,
+ 0x76e3, 0x1f84,
+ 0x76e4, 0x20b2,
+ 0x76e5, 0x1a8c,
+ 0x76e6, 0x3f00,
+ 0x76e7, 0x2043,
+ 0x76e8, 0x3f01,
+ 0x76ee, 0x0b22,
+ 0x76ef, 0x05e1,
+ 0x76f0, 0x3f07,
+ 0x76f1, 0x1a58,
+ 0x76f2, 0x0aa9,
+ 0x76f3, 0x3f08,
+ 0x76f4, 0x11b0,
+ 0x76f5, 0x3f09,
+ 0x76f8, 0x0f4d,
+ 0x76f9, 0x1a5b,
+ 0x76fa, 0x3f0c,
+ 0x76fc, 0x0b8f,
+ 0x76fd, 0x3f0e,
+ 0x76fe, 0x061b,
+ 0x76ff, 0x3f0f,
+ 0x7700, 0x3f10,
+ 0x7701, 0x0d38,
+ 0x7702, 0x3f11,
+ 0x7704, 0x1a59,
+ 0x7705, 0x3f13,
+ 0x7707, 0x1a5c,
+ 0x7709, 0x0ac1,
+ 0x770a, 0x3f15,
+ 0x770b, 0x0941,
+ 0x770c, 0x3f16,
+ 0x770d, 0x1a5a,
+ 0x770e, 0x3f17,
+ 0x7719, 0x1a60,
+ 0x771a, 0x1a5e,
+ 0x771b, 0x3f22,
+ 0x771f, 0x1187,
+ 0x7720, 0x0ae4,
+ 0x7721, 0x3f26,
+ 0x7722, 0x1a5f,
+ 0x7723, 0x3f27,
+ 0x7726, 0x1a62,
+ 0x7727, 0x3f2a,
+ 0x7728, 0x1144,
+ 0x7729, 0x0fcc,
+ 0x772a, 0x3f2b,
+ 0x772d, 0x1a61,
+ 0x772e, 0x3f2e,
+ 0x772f, 0x0ad5,
+ 0x7730, 0x3f2f,
+ 0x7735, 0x1a63,
+ 0x7736, 0x0981,
+ 0x7737, 0x091b,
+ 0x7738, 0x1a64,
+ 0x7739, 0x3f34,
+ 0x773a, 0x0e4a,
+ 0x773b, 0x3f35,
+ 0x773c, 0x1004,
+ 0x773d, 0x3f36,
+ 0x7740, 0x1222,
+ 0x7741, 0x1197,
+ 0x7742, 0x3f39,
+ 0x7743, 0x1a68,
+ 0x7744, 0x3f3a,
+ 0x7747, 0x1a67,
+ 0x7748, 0x3f3d,
+ 0x774f, 0x2684,
+ 0x7750, 0x1a65,
+ 0x7752, 0x3f44,
+ 0x775a, 0x1a69,
+ 0x775b, 0x08d5,
+ 0x775c, 0x3f4c,
+ 0x775e, 0x24ef,
+ 0x775f, 0x3f4e,
+ 0x7761, 0x0da4,
+ 0x7762, 0x1a6b,
+ 0x7763, 0x05fc,
+ 0x7764, 0x3f50,
+ 0x7765, 0x1a6c,
+ 0x7766, 0x0b23,
+ 0x7767, 0x3f51,
+ 0x7768, 0x1a6a,
+ 0x7769, 0x3f52,
+ 0x776b, 0x08af,
+ 0x776c, 0x048e,
+ 0x776d, 0x3f54,
+ 0x7779, 0x0602,
+ 0x777a, 0x3f60,
+ 0x777d, 0x1a6f,
+ 0x777e, 0x1270,
+ 0x777f, 0x1a6d,
+ 0x7780, 0x1a70,
+ 0x7781, 0x3f63,
+ 0x7784, 0x0aee,
+ 0x7785, 0x0517,
+ 0x7786, 0x3f66,
+ 0x778c, 0x1a71,
+ 0x778d, 0x1a6e,
+ 0x778e, 0x0f26,
+ 0x778f, 0x3f6c,
+ 0x7791, 0x1a72,
+ 0x7792, 0x0a9e,
+ 0x7793, 0x3f6e,
+ 0x7798, 0x24ee,
+ 0x7799, 0x3f73,
+ 0x779e, 0x2074,
+ 0x779f, 0x1a73,
+ 0x77a1, 0x3f78,
+ 0x77a2, 0x1495,
+ 0x77a3, 0x3f79,
+ 0x77a5, 0x0bd2,
+ 0x77a6, 0x3f7b,
+ 0x77a7, 0x0c43,
+ 0x77a8, 0x3f7c,
+ 0x77a9, 0x11f4,
+ 0x77aa, 0x05aa,
+ 0x77ab, 0x3f7d,
+ 0x77ac, 0x0da7,
+ 0x77ad, 0x2687,
+ 0x77ae, 0x3f7e,
+ 0x77b0, 0x1a75,
+ 0x77b1, 0x3f80,
+ 0x77b3, 0x0e5c,
+ 0x77b4, 0x3f82,
+ 0x77b5, 0x1a76,
+ 0x77b6, 0x3f83,
+ 0x77bb, 0x1151,
+ 0x77bc, 0x24f0,
+ 0x77bd, 0x1a77,
+ 0x77be, 0x3f88,
+ 0x77bf, 0x1d7e,
+ 0x77c0, 0x3f89,
+ 0x77c7, 0x268d,
+ 0x77c8, 0x3f90,
+ 0x77cd, 0x1397,
+ 0x77ce, 0x3f95,
+ 0x77d7, 0x0526,
+ 0x77d8, 0x3f9e,
+ 0x77da, 0x22a0,
+ 0x77db, 0x0ab1,
+ 0x77dc, 0x1bca,
+ 0x77dd, 0x3fa0,
+ 0x77e2, 0x0d4f,
+ 0x77e3, 0x105a,
+ 0x77e4, 0x3fa5,
+ 0x77e5, 0x11a9,
+ 0x77e6, 0x3fa6,
+ 0x77e7, 0x1b1a,
+ 0x77e8, 0x3fa7,
+ 0x77e9, 0x0907,
+ 0x77ea, 0x3fa8,
+ 0x77eb, 0x0894,
+ 0x77ec, 0x1b1b,
+ 0x77ed, 0x060b,
+ 0x77ee, 0x03b6,
+ 0x77ef, 0x1fab,
+ 0x77f0, 0x3fa9,
+ 0x77f3, 0x0d46,
+ 0x77f4, 0x3fac,
+ 0x77f6, 0x1a22,
+ 0x77f7, 0x3fae,
+ 0x77f8, 0x1a23,
+ 0x77f9, 0x3faf,
+ 0x77fd, 0x0f08,
+ 0x77fe, 0x064c,
+ 0x77ff, 0x0980,
+ 0x7800, 0x1a24,
+ 0x7801, 0x0a92,
+ 0x7802, 0x0ce9,
+ 0x7803, 0x3fb3,
+ 0x7809, 0x1a25,
+ 0x780a, 0x3fb9,
+ 0x780c, 0x0c15,
+ 0x780d, 0x0940,
+ 0x780e, 0x3fbb,
+ 0x7811, 0x1a28,
+ 0x7812, 0x0bb9,
+ 0x7813, 0x3fbe,
+ 0x7814, 0x0ff9,
+ 0x7815, 0x3fbf,
+ 0x7816, 0x1206,
+ 0x7817, 0x1a26,
+ 0x7819, 0x3fc0,
+ 0x781a, 0x100b,
+ 0x781b, 0x3fc1,
+ 0x781c, 0x1a2b,
+ 0x781e, 0x3fc2,
+ 0x781f, 0x1a30,
+ 0x7820, 0x3fc3,
+ 0x7823, 0x1a34,
+ 0x7824, 0x3fc6,
+ 0x7825, 0x1a32,
+ 0x7826, 0x1a3a,
+ 0x7827, 0x1189,
+ 0x7828, 0x3fc7,
+ 0x7829, 0x1a35,
+ 0x782a, 0x3fc8,
+ 0x782c, 0x1a33,
+ 0x782d, 0x1a2a,
+ 0x782e, 0x3fca,
+ 0x7830, 0x0baa,
+ 0x7831, 0x3fcc,
+ 0x7834, 0x0be5,
+ 0x7835, 0x3fcf,
+ 0x7837, 0x0d22,
+ 0x7838, 0x1115,
+ 0x7839, 0x1a2d,
+ 0x783c, 0x1a31,
+ 0x783d, 0x3fd1,
+ 0x783e, 0x09e4,
+ 0x783f, 0x3fd2,
+ 0x7840, 0x0524,
+ 0x7841, 0x3fd3,
+ 0x7843, 0x26a8,
+ 0x7844, 0x3fd5,
+ 0x7845, 0x0741,
+ 0x7846, 0x3fd6,
+ 0x7847, 0x1a3c,
+ 0x7848, 0x3fd7,
+ 0x784c, 0x1a3d,
+ 0x784d, 0x3fdb,
+ 0x784e, 0x1a36,
+ 0x784f, 0x3fdc,
+ 0x7850, 0x1a3b,
+ 0x7851, 0x3fdd,
+ 0x7852, 0x0f07,
+ 0x7853, 0x3fde,
+ 0x7855, 0x0dab,
+ 0x7856, 0x1a38,
+ 0x7858, 0x3fe0,
+ 0x785d, 0x0f62,
+ 0x785e, 0x3fe5,
+ 0x7864, 0x24e9,
+ 0x7865, 0x3feb,
+ 0x7868, 0x24e5,
+ 0x7869, 0x3fee,
+ 0x786a, 0x1a3e,
+ 0x786b, 0x0a3b,
+ 0x786c, 0x1097,
+ 0x786d, 0x1a37,
+ 0x786e, 0x0c92,
+ 0x786f, 0x21fa,
+ 0x7870, 0x3fef,
+ 0x7877, 0x0862,
+ 0x7878, 0x3ff6,
+ 0x787c, 0x0bb1,
+ 0x787d, 0x3ffa,
+ 0x7887, 0x1a42,
+ 0x7888, 0x4004,
+ 0x7889, 0x05d0,
+ 0x788a, 0x4005,
+ 0x788c, 0x0a5c,
+ 0x788d, 0x03b8,
+ 0x788e, 0x0dde,
+ 0x788f, 0x4007,
+ 0x7891, 0x0417,
+ 0x7892, 0x4009,
+ 0x7893, 0x1a40,
+ 0x7894, 0x400a,
+ 0x7897, 0x0e9c,
+ 0x7898, 0x05c3,
+ 0x7899, 0x400d,
+ 0x789a, 0x1a41,
+ 0x789b, 0x1a3f,
+ 0x789c, 0x1a43,
+ 0x789d, 0x400e,
+ 0x789f, 0x05db,
+ 0x78a0, 0x4010,
+ 0x78a1, 0x1a44,
+ 0x78a2, 0x4011,
+ 0x78a3, 0x1a45,
+ 0x78a4, 0x4012,
+ 0x78a5, 0x1a48,
+ 0x78a6, 0x4013,
+ 0x78a7, 0x0435,
+ 0x78a8, 0x4014,
+ 0x78a9, 0x2148,
+ 0x78aa, 0x4015,
+ 0x78ad, 0x24e4,
+ 0x78ae, 0x4018,
+ 0x78b0, 0x0bb7,
+ 0x78b1, 0x0861,
+ 0x78b2, 0x1a46,
+ 0x78b3, 0x0e0f,
+ 0x78b4, 0x04b1,
+ 0x78b5, 0x401a,
+ 0x78b8, 0x24e6,
+ 0x78b9, 0x1a47,
+ 0x78ba, 0x20f7,
+ 0x78bb, 0x401d,
+ 0x78bc, 0x206b,
+ 0x78bd, 0x401e,
+ 0x78be, 0x0b4e,
+ 0x78bf, 0x401f,
+ 0x78c1, 0x0548,
+ 0x78c2, 0x4021,
+ 0x78c5, 0x0400,
+ 0x78c6, 0x4024,
+ 0x78c9, 0x1a4b,
+ 0x78ca, 0x09c5,
+ 0x78cb, 0x056b,
+ 0x78cc, 0x4027,
+ 0x78d0, 0x0b8e,
+ 0x78d1, 0x402b,
+ 0x78d4, 0x1a49,
+ 0x78d5, 0x0951,
+ 0x78d6, 0x402e,
+ 0x78d9, 0x1a4a,
+ 0x78da, 0x22a7,
+ 0x78db, 0x4031,
+ 0x78e3, 0x24ec,
+ 0x78e4, 0x4039,
+ 0x78e7, 0x24eb,
+ 0x78e8, 0x0b08,
+ 0x78e9, 0x403c,
+ 0x78ec, 0x1a4c,
+ 0x78ed, 0x403f,
+ 0x78ef, 0x24e3,
+ 0x78f0, 0x4041,
+ 0x78f2, 0x1a4d,
+ 0x78f3, 0x4043,
+ 0x78f4, 0x1a4f,
+ 0x78f5, 0x4044,
+ 0x78f7, 0x0a20,
+ 0x78f8, 0x4046,
+ 0x78fa, 0x07dc,
+ 0x78fb, 0x4048,
+ 0x78fd, 0x24ea,
+ 0x78fe, 0x404a,
+ 0x7900, 0x404c,
+ 0x7901, 0x0889,
+ 0x7902, 0x404d,
+ 0x7905, 0x1a4e,
+ 0x7906, 0x4050,
+ 0x790e, 0x1e92,
+ 0x790f, 0x4058,
+ 0x7913, 0x1a50,
+ 0x7914, 0x405c,
+ 0x7919, 0x1e27,
+ 0x791a, 0x4061,
+ 0x791e, 0x1a52,
+ 0x791f, 0x4065,
+ 0x7924, 0x1a51,
+ 0x7925, 0x406a,
+ 0x7926, 0x1fe6,
+ 0x7927, 0x406b,
+ 0x792a, 0x24e7,
+ 0x792b, 0x2012,
+ 0x792c, 0x1eec,
+ 0x792d, 0x406e,
+ 0x7931, 0x24e8,
+ 0x7932, 0x4072,
+ 0x7934, 0x1a53,
+ 0x7935, 0x4074,
+ 0x793a, 0x0d55,
+ 0x793b, 0x19f8,
+ 0x793c, 0x09dc,
+ 0x793d, 0x4079,
+ 0x793e, 0x0d20,
+ 0x793f, 0x407a,
+ 0x7940, 0x19f9,
+ 0x7941, 0x0c0d,
+ 0x7942, 0x407b,
+ 0x7946, 0x19fa,
+ 0x7947, 0x407f,
+ 0x7948, 0x0c0c,
+ 0x7949, 0x19fb,
+ 0x794a, 0x4080,
+ 0x7953, 0x19fe,
+ 0x7954, 0x4089,
+ 0x7956, 0x1243,
+ 0x7957, 0x1a01,
+ 0x7958, 0x408b,
+ 0x795a, 0x19ff,
+ 0x795b, 0x19fc,
+ 0x795d, 0x1200,
+ 0x795e, 0x0d2a,
+ 0x795f, 0x0de3,
+ 0x7960, 0x1a02,
+ 0x7961, 0x408d,
+ 0x7962, 0x1a00,
+ 0x7963, 0x408e,
+ 0x7965, 0x0f56,
+ 0x7966, 0x4090,
+ 0x7967, 0x1a04,
+ 0x7968, 0x0bd0,
+ 0x7969, 0x4091,
+ 0x796d, 0x0833,
+ 0x796e, 0x4095,
+ 0x796f, 0x1a03,
+ 0x7970, 0x4096,
+ 0x7977, 0x059c,
+ 0x7978, 0x080b,
+ 0x7979, 0x409d,
+ 0x797a, 0x1a05,
+ 0x797b, 0x409e,
+ 0x7980, 0x130b,
+ 0x7981, 0x08cc,
+ 0x7982, 0x40a3,
+ 0x7984, 0x0a62,
+ 0x7985, 0x1a06,
+ 0x7986, 0x40a5,
+ 0x798a, 0x1a07,
+ 0x798b, 0x40a9,
+ 0x798d, 0x1f66,
+ 0x798e, 0x24dc,
+ 0x798f, 0x069e,
+ 0x7990, 0x40ab,
+ 0x799a, 0x1a08,
+ 0x799b, 0x40b5,
+ 0x79a6, 0x26a2,
+ 0x79a7, 0x1a09,
+ 0x79a8, 0x40c0,
+ 0x79aa, 0x24dd,
+ 0x79ab, 0x40c2,
+ 0x79ae, 0x200e,
+ 0x79af, 0x40c5,
+ 0x79b0, 0x24db,
+ 0x79b1, 0x1eb8,
+ 0x79b2, 0x40c6,
+ 0x79b3, 0x1a0a,
+ 0x79b4, 0x40c7,
+ 0x79b9, 0x10d2,
+ 0x79ba, 0x1264,
+ 0x79bb, 0x09d6,
+ 0x79bc, 0x40cc,
+ 0x79bd, 0x0c5a,
+ 0x79be, 0x0783,
+ 0x79bf, 0x40cd,
+ 0x79c0, 0x0fae,
+ 0x79c1, 0x0db2,
+ 0x79c2, 0x40ce,
+ 0x79c3, 0x0e6b,
+ 0x79c4, 0x40cf,
+ 0x79c6, 0x06cc,
+ 0x79c7, 0x40d1,
+ 0x79c9, 0x0465,
+ 0x79ca, 0x40d3,
+ 0x79cb, 0x0c6c,
+ 0x79cc, 0x40d4,
+ 0x79cd, 0x11d5,
+ 0x79ce, 0x40d5,
+ 0x79d1, 0x0953,
+ 0x79d2, 0x0af0,
+ 0x79d3, 0x40d8,
+ 0x79d5, 0x1b1d,
+ 0x79d6, 0x40da,
+ 0x79d8, 0x0add,
+ 0x79d9, 0x40dc,
+ 0x79df, 0x123f,
+ 0x79e0, 0x40e2,
+ 0x79e3, 0x1b1f,
+ 0x79e4, 0x04f8,
+ 0x79e5, 0x40e5,
+ 0x79e6, 0x0c55,
+ 0x79e7, 0x1016,
+ 0x79e8, 0x40e6,
+ 0x79e9, 0x11c7,
+ 0x79ea, 0x40e7,
+ 0x79eb, 0x1b20,
+ 0x79ec, 0x40e8,
+ 0x79ed, 0x1b1e,
+ 0x79ee, 0x40e9,
+ 0x79ef, 0x0812,
+ 0x79f0, 0x04eb,
+ 0x79f1, 0x40ea,
+ 0x79f8, 0x08a6,
+ 0x79f9, 0x40f1,
+ 0x79fb, 0x104d,
+ 0x79fc, 0x40f3,
+ 0x79fd, 0x07f5,
+ 0x79fe, 0x40f4,
+ 0x7a00, 0x0f0e,
+ 0x7a01, 0x40f6,
+ 0x7a02, 0x1b24,
+ 0x7a03, 0x1b23,
+ 0x7a04, 0x40f7,
+ 0x7a06, 0x1b21,
+ 0x7a07, 0x40f9,
+ 0x7a0b, 0x04f1,
+ 0x7a0c, 0x40fd,
+ 0x7a0d, 0x0d0d,
+ 0x7a0e, 0x0da5,
+ 0x7a0f, 0x40fe,
+ 0x7a14, 0x1b26,
+ 0x7a15, 0x4103,
+ 0x7a17, 0x03e9,
+ 0x7a18, 0x4105,
+ 0x7a1a, 0x11c8,
+ 0x7a1b, 0x4107,
+ 0x7a1e, 0x1b25,
+ 0x7a1f, 0x410a,
+ 0x7a20, 0x0512,
+ 0x7a21, 0x410b,
+ 0x7a23, 0x1d8f,
+ 0x7a24, 0x410d,
+ 0x7a2e, 0x2295,
+ 0x7a2f, 0x4117,
+ 0x7a31, 0x1e80,
+ 0x7a32, 0x4119,
+ 0x7a33, 0x0ed7,
+ 0x7a34, 0x411a,
+ 0x7a37, 0x1b28,
+ 0x7a38, 0x411d,
+ 0x7a39, 0x1b27,
+ 0x7a3a, 0x411e,
+ 0x7a3b, 0x059f,
+ 0x7a3c, 0x084d,
+ 0x7a3d, 0x0811,
+ 0x7a3e, 0x411f,
+ 0x7a3f, 0x06e0,
+ 0x7a40, 0x2677,
+ 0x7a41, 0x4120,
+ 0x7a46, 0x0b25,
+ 0x7a47, 0x4125,
+ 0x7a4c, 0x2624,
+ 0x7a4d, 0x1f69,
+ 0x7a4e, 0x222b,
+ 0x7a4f, 0x412a,
+ 0x7a51, 0x1b29,
+ 0x7a52, 0x412c,
+ 0x7a57, 0x0de0,
+ 0x7a58, 0x4131,
+ 0x7a61, 0x257f,
+ 0x7a62, 0x1f5b,
+ 0x7a63, 0x413a,
+ 0x7a69, 0x219b,
+ 0x7a6a, 0x4140,
+ 0x7a6b, 0x267d,
+ 0x7a6c, 0x4141,
+ 0x7a70, 0x1b2c,
+ 0x7a71, 0x4145,
+ 0x7a74, 0x0fd1,
+ 0x7a75, 0x4148,
+ 0x7a76, 0x08ee,
+ 0x7a77, 0x0c6b,
+ 0x7a78, 0x1b9a,
+ 0x7a7a, 0x0962,
+ 0x7a7b, 0x4149,
+ 0x7a7f, 0x052c,
+ 0x7a80, 0x1b9c,
+ 0x7a81, 0x0e6c,
+ 0x7a82, 0x414d,
+ 0x7a83, 0x0c51,
+ 0x7a84, 0x114e,
+ 0x7a85, 0x414e,
+ 0x7a86, 0x1b9d,
+ 0x7a87, 0x414f,
+ 0x7a88, 0x1b9e,
+ 0x7a89, 0x4150,
+ 0x7a8d, 0x0c4c,
+ 0x7a8e, 0x4154,
+ 0x7a91, 0x102b,
+ 0x7a92, 0x11ce,
+ 0x7a93, 0x4157,
+ 0x7a95, 0x1b9f,
+ 0x7a96, 0x08a2,
+ 0x7a97, 0x0533,
+ 0x7a98, 0x08ec,
+ 0x7a99, 0x4159,
+ 0x7a9c, 0x055f,
+ 0x7a9d, 0x0ee0,
+ 0x7a9e, 0x415c,
+ 0x7a9f, 0x096c,
+ 0x7aa0, 0x1ba1,
+ 0x7aa1, 0x415d,
+ 0x7aa5, 0x0987,
+ 0x7aa6, 0x1ba0,
+ 0x7aa7, 0x4161,
+ 0x7aa8, 0x1ba3,
+ 0x7aa9, 0x21a0,
+ 0x7aaa, 0x2186,
+ 0x7aab, 0x4162,
+ 0x7aac, 0x1ba2,
+ 0x7aad, 0x1ba4,
+ 0x7aae, 0x20ed,
+ 0x7aaf, 0x4163,
+ 0x7ab3, 0x1ba5,
+ 0x7ab4, 0x4167,
+ 0x7ab6, 0x25b9,
+ 0x7ab7, 0x4169,
+ 0x7aba, 0x1fea,
+ 0x7abb, 0x416c,
+ 0x7abf, 0x0a47,
+ 0x7ac0, 0x4170,
+ 0x7ac4, 0x1ea4,
+ 0x7ac5, 0x20e1,
+ 0x7ac6, 0x4174,
+ 0x7ac7, 0x25b8,
+ 0x7ac8, 0x2260,
+ 0x7ac9, 0x4175,
+ 0x7aca, 0x20e2,
+ 0x7acb, 0x09eb,
+ 0x7acc, 0x4176,
+ 0x7ad6, 0x0d91,
+ 0x7ad7, 0x4180,
+ 0x7ad9, 0x115f,
+ 0x7ada, 0x4182,
+ 0x7ade, 0x08e9,
+ 0x7adf, 0x08e8,
+ 0x7ae0, 0x1163,
+ 0x7ae1, 0x4186,
+ 0x7ae3, 0x092f,
+ 0x7ae4, 0x4188,
+ 0x7ae5, 0x0e60,
+ 0x7ae6, 0x1b99,
+ 0x7ae7, 0x4189,
+ 0x7aea, 0x2141,
+ 0x7aeb, 0x418c,
+ 0x7aed, 0x08b0,
+ 0x7aee, 0x418e,
+ 0x7aef, 0x060a,
+ 0x7af0, 0x418f,
+ 0x7af6, 0x1fc7,
+ 0x7af7, 0x4195,
+ 0x7af9, 0x11f0,
+ 0x7afa, 0x1c63,
+ 0x7afb, 0x4197,
+ 0x7afd, 0x1c64,
+ 0x7afe, 0x4199,
+ 0x7aff, 0x06c8,
+ 0x7b00, 0x419a,
+ 0x7b03, 0x1c66,
+ 0x7b05, 0x419d,
+ 0x7b06, 0x03d5,
+ 0x7b07, 0x419e,
+ 0x7b08, 0x1c65,
+ 0x7b09, 0x419f,
+ 0x7b0a, 0x1c69,
+ 0x7b0b, 0x0de6,
+ 0x7b0c, 0x41a0,
+ 0x7b0f, 0x1c6b,
+ 0x7b10, 0x41a3,
+ 0x7b11, 0x0f71,
+ 0x7b12, 0x41a4,
+ 0x7b14, 0x0433,
+ 0x7b15, 0x1c68,
+ 0x7b16, 0x41a6,
+ 0x7b19, 0x1c6f,
+ 0x7b1a, 0x41a9,
+ 0x7b1b, 0x05b2,
+ 0x7b1c, 0x41aa,
+ 0x7b1e, 0x1c77,
+ 0x7b1f, 0x41ac,
+ 0x7b20, 0x1c72,
+ 0x7b21, 0x41ad,
+ 0x7b24, 0x1c74,
+ 0x7b25, 0x1c73,
+ 0x7b26, 0x0698,
+ 0x7b27, 0x41b0,
+ 0x7b28, 0x0428,
+ 0x7b29, 0x41b1,
+ 0x7b2a, 0x1c6e,
+ 0x7b2b, 0x1c6a,
+ 0x7b2c, 0x05bb,
+ 0x7b2d, 0x41b2,
+ 0x7b2e, 0x1c70,
+ 0x7b2f, 0x41b3,
+ 0x7b31, 0x1c71,
+ 0x7b32, 0x41b5,
+ 0x7b33, 0x1c75,
+ 0x7b34, 0x41b6,
+ 0x7b38, 0x1c6d,
+ 0x7b39, 0x41ba,
+ 0x7b3a, 0x0856,
+ 0x7b3b, 0x41bb,
+ 0x7b3c, 0x0a46,
+ 0x7b3d, 0x41bc,
+ 0x7b3e, 0x1c76,
+ 0x7b3f, 0x41bd,
+ 0x7b45, 0x1c7a,
+ 0x7b46, 0x1e41,
+ 0x7b47, 0x1c6c,
+ 0x7b48, 0x41c3,
+ 0x7b49, 0x05a9,
+ 0x7b4a, 0x41c4,
+ 0x7b4b, 0x08bf,
+ 0x7b4c, 0x1c7c,
+ 0x7b4d, 0x41c5,
+ 0x7b4f, 0x0641,
+ 0x7b50, 0x097d,
+ 0x7b51, 0x11fd,
+ 0x7b52, 0x0e63,
+ 0x7b53, 0x41c7,
+ 0x7b54, 0x0573,
+ 0x7b55, 0x41c8,
+ 0x7b56, 0x04a6,
+ 0x7b57, 0x41c9,
+ 0x7b58, 0x1c78,
+ 0x7b59, 0x41ca,
+ 0x7b5a, 0x1c79,
+ 0x7b5b, 0x0cf1,
+ 0x7b5c, 0x41cb,
+ 0x7b5d, 0x1c7d,
+ 0x7b5e, 0x41cc,
+ 0x7b60, 0x1c7e,
+ 0x7b61, 0x41ce,
+ 0x7b62, 0x1c81,
+ 0x7b63, 0x41cf,
+ 0x7b67, 0x25e4,
+ 0x7b68, 0x41d3,
+ 0x7b6e, 0x1c7f,
+ 0x7b6f, 0x41d9,
+ 0x7b71, 0x1c83,
+ 0x7b72, 0x1c82,
+ 0x7b73, 0x41db,
+ 0x7b75, 0x1c7b,
+ 0x7b76, 0x41dd,
+ 0x7b77, 0x0977,
+ 0x7b78, 0x41de,
+ 0x7b79, 0x0514,
+ 0x7b7a, 0x41df,
+ 0x7b7b, 0x1c80,
+ 0x7b7c, 0x41e0,
+ 0x7b7e, 0x0c26,
+ 0x7b7f, 0x41e2,
+ 0x7b80, 0x0865,
+ 0x7b81, 0x41e3,
+ 0x7b85, 0x1c8b,
+ 0x7b86, 0x41e7,
+ 0x7b8b, 0x1f86,
+ 0x7b8c, 0x41ec,
+ 0x7b8d, 0x0718,
+ 0x7b8e, 0x41ed,
+ 0x7b90, 0x1c84,
+ 0x7b91, 0x41ef,
+ 0x7b94, 0x0474,
+ 0x7b95, 0x0813,
+ 0x7b96, 0x41f2,
+ 0x7b97, 0x0dd8,
+ 0x7b98, 0x41f3,
+ 0x7b9c, 0x1c8d,
+ 0x7b9d, 0x1c89,
+ 0x7b9e, 0x41f7,
+ 0x7ba1, 0x0735,
+ 0x7ba2, 0x1c8e,
+ 0x7ba3, 0x41fa,
+ 0x7ba6, 0x1c85,
+ 0x7ba8, 0x1c8a,
+ 0x7ba9, 0x0a88,
+ 0x7baa, 0x1c8c,
+ 0x7bab, 0x1c8f,
+ 0x7bac, 0x1c88,
+ 0x7bad, 0x0870,
+ 0x7bae, 0x41fd,
+ 0x7bb1, 0x0f51,
+ 0x7bb2, 0x4200,
+ 0x7bb4, 0x1c90,
+ 0x7bb5, 0x4202,
+ 0x7bb8, 0x1c87,
+ 0x7bb9, 0x4205,
+ 0x7bc0, 0x1fb3,
+ 0x7bc1, 0x1c92,
+ 0x7bc2, 0x420c,
+ 0x7bc4, 0x1eef,
+ 0x7bc5, 0x420e,
+ 0x7bc6, 0x120a,
+ 0x7bc7, 0x0bc9,
+ 0x7bc8, 0x420f,
+ 0x7bc9, 0x22a4,
+ 0x7bca, 0x4210,
+ 0x7bcb, 0x25e8,
+ 0x7bcc, 0x1c93,
+ 0x7bcd, 0x4211,
+ 0x7bd1, 0x1c91,
+ 0x7bd2, 0x4215,
+ 0x7bd3, 0x0a4f,
+ 0x7bd4, 0x4216,
+ 0x7bd9, 0x06d8,
+ 0x7bda, 0x1c95,
+ 0x7bdb, 0x421b,
+ 0x7bdd, 0x1c94,
+ 0x7bde, 0x421d,
+ 0x7be1, 0x055e,
+ 0x7be2, 0x4220,
+ 0x7be4, 0x25e3,
+ 0x7be5, 0x1c96,
+ 0x7be7, 0x4222,
+ 0x7be9, 0x2111,
+ 0x7bea, 0x1c98,
+ 0x7beb, 0x4224,
+ 0x7bee, 0x09a5,
+ 0x7bef, 0x4227,
+ 0x7bf1, 0x09d4,
+ 0x7bf2, 0x4229,
+ 0x7bf3, 0x25e6,
+ 0x7bf4, 0x422a,
+ 0x7bf7, 0x0bb2,
+ 0x7bf8, 0x422d,
+ 0x7bfc, 0x1c9b,
+ 0x7bfd, 0x4231,
+ 0x7bfe, 0x1c9a,
+ 0x7bff, 0x4232,
+ 0x7c00, 0x25e7,
+ 0x7c01, 0x4233,
+ 0x7c07, 0x055b,
+ 0x7c08, 0x4239,
+ 0x7c0b, 0x1c9e,
+ 0x7c0c, 0x1c99,
+ 0x7c0d, 0x2041,
+ 0x7c0e, 0x423c,
+ 0x7c0f, 0x1c9c,
+ 0x7c10, 0x423d,
+ 0x7c16, 0x1c9d,
+ 0x7c17, 0x4243,
+ 0x7c1e, 0x25ea,
+ 0x7c1f, 0x1c9f,
+ 0x7c20, 0x424a,
+ 0x7c21, 0x1f8f,
+ 0x7c22, 0x424b,
+ 0x7c23, 0x25ec,
+ 0x7c24, 0x424c,
+ 0x7c26, 0x1ca1,
+ 0x7c27, 0x07de,
+ 0x7c28, 0x424e,
+ 0x7c2a, 0x1ca0,
+ 0x7c2b, 0x25eb,
+ 0x7c2c, 0x4250,
+ 0x7c38, 0x1ca2,
+ 0x7c39, 0x425c,
+ 0x7c3d, 0x20d0,
+ 0x7c3e, 0x201d,
+ 0x7c3f, 0x0485,
+ 0x7c40, 0x1ca4,
+ 0x7c41, 0x1ca3,
+ 0x7c42, 0x4260,
+ 0x7c43, 0x1ff7,
+ 0x7c44, 0x4261,
+ 0x7c4c, 0x1e8d,
+ 0x7c4d, 0x0821,
+ 0x7c4e, 0x4269,
+ 0x7c5c, 0x25e9,
+ 0x7c5d, 0x4277,
+ 0x7c5f, 0x25ee,
+ 0x7c60, 0x203a,
+ 0x7c61, 0x4279,
+ 0x7c64, 0x2693,
+ 0x7c65, 0x427c,
+ 0x7c69, 0x25e5,
+ 0x7c6a, 0x25ed,
+ 0x7c6b, 0x4280,
+ 0x7c6c, 0x2009,
+ 0x7c6d, 0x4281,
+ 0x7c6e, 0x2065,
+ 0x7c6f, 0x4282,
+ 0x7c72, 0x26a3,
+ 0x7c73, 0x0adc,
+ 0x7c74, 0x12f5,
+ 0x7c75, 0x4285,
+ 0x7c7b, 0x09cb,
+ 0x7c7c, 0x1cca,
+ 0x7c7d, 0x122e,
+ 0x7c7e, 0x428b,
+ 0x7c89, 0x0678,
+ 0x7c8a, 0x4296,
+ 0x7c91, 0x1ccc,
+ 0x7c92, 0x09ec,
+ 0x7c93, 0x429d,
+ 0x7c95, 0x0be8,
+ 0x7c96, 0x429f,
+ 0x7c97, 0x0559,
+ 0x7c98, 0x1154,
+ 0x7c99, 0x42a0,
+ 0x7c9c, 0x1cce,
+ 0x7c9d, 0x1ccd,
+ 0x7c9e, 0x1ccf,
+ 0x7c9f, 0x0dcf,
+ 0x7ca0, 0x42a3,
+ 0x7ca2, 0x1cd0,
+ 0x7ca3, 0x42a5,
+ 0x7ca4, 0x1104,
+ 0x7ca5, 0x11df,
+ 0x7ca6, 0x42a6,
+ 0x7caa, 0x067d,
+ 0x7cab, 0x42aa,
+ 0x7cae, 0x0a01,
+ 0x7caf, 0x42ad,
+ 0x7cb1, 0x0a04,
+ 0x7cb2, 0x1cd1,
+ 0x7cb3, 0x08db,
+ 0x7cb4, 0x42af,
+ 0x7cb9, 0x0565,
+ 0x7cba, 0x42b4,
+ 0x7cbc, 0x1cd2,
+ 0x7cbe, 0x08da,
+ 0x7cbf, 0x42b6,
+ 0x7cc1, 0x1cd4,
+ 0x7cc2, 0x42b8,
+ 0x7cc5, 0x1cd9,
+ 0x7cc6, 0x42bb,
+ 0x7cc7, 0x1cd5,
+ 0x7cc8, 0x1cd8,
+ 0x7cc9, 0x42bc,
+ 0x7cca, 0x07b4,
+ 0x7ccb, 0x42bd,
+ 0x7ccc, 0x1cd6,
+ 0x7cce, 0x42be,
+ 0x7cd5, 0x06dd,
+ 0x7cd6, 0x0e1a,
+ 0x7cd7, 0x1cda,
+ 0x7cd8, 0x42c5,
+ 0x7cd9, 0x04a1,
+ 0x7cda, 0x42c6,
+ 0x7cdc, 0x0ad8,
+ 0x7cdd, 0x25f5,
+ 0x7cde, 0x1efc,
+ 0x7cdf, 0x1126,
+ 0x7ce0, 0x0944,
+ 0x7ce1, 0x42c8,
+ 0x7ce7, 0x2024,
+ 0x7ce8, 0x1cdb,
+ 0x7ce9, 0x42ce,
+ 0x7cef, 0x0b75,
+ 0x7cf0, 0x269b,
+ 0x7cf1, 0x42d4,
+ 0x7cf2, 0x25f3,
+ 0x7cf3, 0x42d5,
+ 0x7cf4, 0x22d9,
+ 0x7cf5, 0x42d6,
+ 0x7cf6, 0x25f4,
+ 0x7cf7, 0x42d7,
+ 0x7cf8, 0x1ce7,
+ 0x7cf9, 0x241b,
+ 0x7cfa, 0x42d8,
+ 0x7cfb, 0x0f22,
+ 0x7cfc, 0x42d9,
+ 0x7cfe, 0x1fc8,
+ 0x7cff, 0x42db,
+ 0x7d00, 0x1f7b,
+ 0x7d01, 0x42dc,
+ 0x7d02, 0x241d,
+ 0x7d03, 0x42dd,
+ 0x7d04, 0x224c,
+ 0x7d05, 0x1f48,
+ 0x7d06, 0x241c,
+ 0x7d07, 0x241e,
+ 0x7d09, 0x20ff,
+ 0x7d0a, 0x0ed8,
+ 0x7d0b, 0x219a,
+ 0x7d0c, 0x42de,
+ 0x7d0d, 0x2091,
+ 0x7d0e, 0x42df,
+ 0x7d10, 0x20a7,
+ 0x7d11, 0x42e1,
+ 0x7d13, 0x2423,
+ 0x7d14, 0x1e9b,
+ 0x7d15, 0x2422,
+ 0x7d16, 0x42e3,
+ 0x7d17, 0x2110,
+ 0x7d18, 0x42e4,
+ 0x7d19, 0x228d,
+ 0x7d1a, 0x1f71,
+ 0x7d1b, 0x1ef8,
+ 0x7d1c, 0x2421,
+ 0x7d1d, 0x42e5,
+ 0x7d20, 0x0dcd,
+ 0x7d21, 0x1ef3,
+ 0x7d22, 0x0dec,
+ 0x7d23, 0x42e8,
+ 0x7d27, 0x08c5,
+ 0x7d28, 0x42ec,
+ 0x7d2b, 0x122c,
+ 0x7d2c, 0x42ef,
+ 0x7d2f, 0x09c6,
+ 0x7d30, 0x21b1,
+ 0x7d31, 0x2426,
+ 0x7d32, 0x2425,
+ 0x7d33, 0x2120,
+ 0x7d34, 0x42f2,
+ 0x7d39, 0x211a,
+ 0x7d3a, 0x2424,
+ 0x7d3b, 0x42f7,
+ 0x7d3c, 0x2428,
+ 0x7d3d, 0x42f8,
+ 0x7d3f, 0x242a,
+ 0x7d40, 0x2429,
+ 0x7d41, 0x42fa,
+ 0x7d42, 0x2294,
+ 0x7d43, 0x42fb,
+ 0x7d44, 0x22be,
+ 0x7d45, 0x42fc,
+ 0x7d46, 0x1e31,
+ 0x7d47, 0x42fd,
+ 0x7d4e, 0x242c,
+ 0x7d4f, 0x4304,
+ 0x7d50, 0x1fb5,
+ 0x7d51, 0x4305,
+ 0x7d5d, 0x242b,
+ 0x7d5e, 0x1faf,
+ 0x7d5f, 0x4311,
+ 0x7d61, 0x2068,
+ 0x7d62, 0x21e4,
+ 0x7d63, 0x4313,
+ 0x7d66, 0x1f21,
+ 0x7d67, 0x4316,
+ 0x7d68, 0x2101,
+ 0x7d69, 0x4317,
+ 0x7d6e, 0x0fc0,
+ 0x7d6f, 0x431c,
+ 0x7d71, 0x217c,
+ 0x7d72, 0x214a,
+ 0x7d73, 0x242d,
+ 0x7d74, 0x431e,
+ 0x7d76, 0x1fd4,
+ 0x7d77, 0x1ce8,
+ 0x7d78, 0x4320,
+ 0x7d79, 0x1fd1,
+ 0x7d7a, 0x4321,
+ 0x7d81, 0x1e33,
+ 0x7d82, 0x4328,
+ 0x7d83, 0x242f,
+ 0x7d84, 0x4329,
+ 0x7d86, 0x242e,
+ 0x7d87, 0x432b,
+ 0x7d88, 0x2430,
+ 0x7d89, 0x21db,
+ 0x7d8a, 0x432c,
+ 0x7d8f, 0x2158,
+ 0x7d90, 0x4331,
+ 0x7d93, 0x1fc2,
+ 0x7d94, 0x4334,
+ 0x7d9c, 0x22b9,
+ 0x7d9d, 0x433c,
+ 0x7d9e, 0x2436,
+ 0x7d9f, 0x433d,
+ 0x7da2, 0x1e8e,
+ 0x7da3, 0x2439,
+ 0x7da4, 0x4340,
+ 0x7da6, 0x1ce9,
+ 0x7da7, 0x4342,
+ 0x7dab, 0x21c5,
+ 0x7dac, 0x2437,
+ 0x7dad, 0x2192,
+ 0x7dae, 0x1cea,
+ 0x7daf, 0x4346,
+ 0x7db0, 0x243a,
+ 0x7db1, 0x1f19,
+ 0x7db2, 0x218c,
+ 0x7db3, 0x1e40,
+ 0x7db4, 0x22b3,
+ 0x7db5, 0x4347,
+ 0x7db8, 0x205f,
+ 0x7db9, 0x2438,
+ 0x7dba, 0x2432,
+ 0x7dbb, 0x2274,
+ 0x7dbc, 0x434a,
+ 0x7dbd, 0x1e9c,
+ 0x7dbe, 0x2431,
+ 0x7dbf, 0x2085,
+ 0x7dc0, 0x434b,
+ 0x7dc4, 0x2435,
+ 0x7dc5, 0x434f,
+ 0x7dc7, 0x243b,
+ 0x7dc8, 0x4351,
+ 0x7dca, 0x1fb7,
+ 0x7dcb, 0x2433,
+ 0x7dcc, 0x4353,
+ 0x7dd1, 0x2054,
+ 0x7dd2, 0x21de,
+ 0x7dd3, 0x4358,
+ 0x7dd4, 0x2434,
+ 0x7dd5, 0x4359,
+ 0x7dd7, 0x243d,
+ 0x7dd8, 0x1f89,
+ 0x7dd9, 0x243c,
+ 0x7dda, 0x435b,
+ 0x7ddd, 0x1f6e,
+ 0x7dde, 0x1ed8,
+ 0x7ddf, 0x435e,
+ 0x7de0, 0x1ebf,
+ 0x7de1, 0x2445,
+ 0x7de2, 0x435f,
+ 0x7de3, 0x2249,
+ 0x7de4, 0x4360,
+ 0x7de6, 0x2441,
+ 0x7de7, 0x4362,
+ 0x7de8, 0x1e47,
+ 0x7de9, 0x1f56,
+ 0x7dea, 0x4363,
+ 0x7dec, 0x2086,
+ 0x7ded, 0x4365,
+ 0x7def, 0x2196,
+ 0x7df0, 0x4367,
+ 0x7df1, 0x2443,
+ 0x7df2, 0x243f,
+ 0x7df3, 0x4368,
+ 0x7df4, 0x2023,
+ 0x7df5, 0x4369,
+ 0x7df6, 0x2442,
+ 0x7df7, 0x436a,
+ 0x7df9, 0x243e,
+ 0x7dfa, 0x436c,
+ 0x7dfb, 0x26a6,
+ 0x7dfc, 0x436d,
+ 0x7e00, 0x4371,
+ 0x7e08, 0x234e,
+ 0x7e09, 0x2446,
+ 0x7e0a, 0x244b,
+ 0x7e0b, 0x2444,
+ 0x7e0c, 0x4379,
+ 0x7e10, 0x2427,
+ 0x7e11, 0x244c,
+ 0x7e12, 0x437d,
+ 0x7e1b, 0x1f0f,
+ 0x7e1c, 0x4386,
+ 0x7e1d, 0x2447,
+ 0x7e1e, 0x2449,
+ 0x7e1f, 0x2448,
+ 0x7e20, 0x4387,
+ 0x7e23, 0x21c2,
+ 0x7e24, 0x438a,
+ 0x7e27, 0x216e,
+ 0x7e28, 0x438d,
+ 0x7e2b, 0x1f03,
+ 0x7e2c, 0x4390,
+ 0x7e2d, 0x244a,
+ 0x7e2e, 0x215c,
+ 0x7e2f, 0x4391,
+ 0x7e31, 0x22bb,
+ 0x7e32, 0x2450,
+ 0x7e33, 0x4393,
+ 0x7e34, 0x2694,
+ 0x7e35, 0x244f,
+ 0x7e36, 0x25f6,
+ 0x7e37, 0x2051,
+ 0x7e38, 0x4394,
+ 0x7e39, 0x244e,
+ 0x7e3a, 0x4395,
+ 0x7e3b, 0x1dfb,
+ 0x7e3c, 0x4396,
+ 0x7e3d, 0x22ba,
+ 0x7e3e, 0x1f6d,
+ 0x7e3f, 0x4397,
+ 0x7e41, 0x064e,
+ 0x7e42, 0x4399,
+ 0x7e45, 0x2452,
+ 0x7e46, 0x2451,
+ 0x7e47, 0x1ceb,
+ 0x7e48, 0x439c,
+ 0x7e52, 0x2455,
+ 0x7e53, 0x43a6,
+ 0x7e54, 0x2289,
+ 0x7e55, 0x2116,
+ 0x7e56, 0x43a7,
+ 0x7e5a, 0x2454,
+ 0x7e5b, 0x43ab,
+ 0x7e5e, 0x20fb,
+ 0x7e5f, 0x43ae,
+ 0x7e62, 0x2440,
+ 0x7e63, 0x43b1,
+ 0x7e69, 0x2126,
+ 0x7e6a, 0x1f61,
+ 0x7e6b, 0x269d,
+ 0x7e6c, 0x43b7,
+ 0x7e6d, 0x1f8a,
+ 0x7e6e, 0x2456,
+ 0x7e6f, 0x2459,
+ 0x7e70, 0x2458,
+ 0x7e71, 0x43b8,
+ 0x7e73, 0x1fae,
+ 0x7e74, 0x43ba,
+ 0x7e79, 0x221a,
+ 0x7e7a, 0x43bf,
+ 0x7e7c, 0x1f7a,
+ 0x7e7d, 0x244d,
+ 0x7e7e, 0x2457,
+ 0x7e7f, 0x43c1,
+ 0x7e82, 0x1248,
+ 0x7e83, 0x43c4,
+ 0x7e88, 0x2453,
+ 0x7e89, 0x43c9,
+ 0x7e8a, 0x2420,
+ 0x7e8b, 0x43ca,
+ 0x7e8c, 0x21df,
+ 0x7e8d, 0x2685,
+ 0x7e8e, 0x43cb,
+ 0x7e8f, 0x1e6e,
+ 0x7e90, 0x43cc,
+ 0x7e93, 0x2224,
+ 0x7e94, 0x2670,
+ 0x7e95, 0x43cf,
+ 0x7e96, 0x21ba,
+ 0x7e97, 0x43d0,
+ 0x7e98, 0x245a,
+ 0x7e99, 0x43d1,
+ 0x7e9b, 0x1cec,
+ 0x7e9c, 0x1fff,
+ 0x7e9d, 0x43d3,
+ 0x7e9f, 0x17d3,
+ 0x7ea0, 0x08ef,
+ 0x7ea1, 0x17d4,
+ 0x7ea2, 0x07a3,
+ 0x7ea3, 0x17d5,
+ 0x7ea4, 0x0f38,
+ 0x7ea5, 0x17d6,
+ 0x7ea6, 0x10ff,
+ 0x7ea7, 0x0829,
+ 0x7ea8, 0x17d7,
+ 0x7eaa, 0x0840,
+ 0x7eab, 0x0cad,
+ 0x7eac, 0x0ec2,
+ 0x7ead, 0x17d9,
+ 0x7eae, 0x43d5,
+ 0x7eaf, 0x0542,
+ 0x7eb0, 0x17da,
+ 0x7eb1, 0x0ced,
+ 0x7eb2, 0x06d4,
+ 0x7eb3, 0x0b2c,
+ 0x7eb4, 0x43d6,
+ 0x7eb5, 0x123a,
+ 0x7eb6, 0x0a81,
+ 0x7eb7, 0x0674,
+ 0x7eb8, 0x11bc,
+ 0x7eb9, 0x0ed5,
+ 0x7eba, 0x0661,
+ 0x7ebb, 0x43d7,
+ 0x7ebd, 0x0b67,
+ 0x7ebe, 0x17db,
+ 0x7ebf, 0x0f4c,
+ 0x7ec0, 0x17dc,
+ 0x7ec3, 0x0a00,
+ 0x7ec4, 0x1246,
+ 0x7ec5, 0x0d29,
+ 0x7ec6, 0x0f25,
+ 0x7ec7, 0x11ae,
+ 0x7ec8, 0x11d4,
+ 0x7ec9, 0x17df,
+ 0x7eca, 0x03f8,
+ 0x7ecb, 0x17e0,
+ 0x7ecd, 0x0d15,
+ 0x7ece, 0x1076,
+ 0x7ecf, 0x08dc,
+ 0x7ed0, 0x17e2,
+ 0x7ed1, 0x03fe,
+ 0x7ed2, 0x0cb9,
+ 0x7ed3, 0x08b2,
+ 0x7ed4, 0x17e3,
+ 0x7ed5, 0x0ca1,
+ 0x7ed6, 0x43d9,
+ 0x7ed7, 0x17e4,
+ 0x7ed8, 0x07fb,
+ 0x7ed9, 0x06f3,
+ 0x7eda, 0x0fcd,
+ 0x7edb, 0x17e5,
+ 0x7edc, 0x0a8e,
+ 0x7edd, 0x0927,
+ 0x7ede, 0x089b,
+ 0x7edf, 0x0e64,
+ 0x7ee0, 0x17e6,
+ 0x7ee2, 0x091d,
+ 0x7ee3, 0x0fb0,
+ 0x7ee4, 0x43da,
+ 0x7ee5, 0x0ddc,
+ 0x7ee6, 0x0e23,
+ 0x7ee7, 0x083f,
+ 0x7ee8, 0x17e8,
+ 0x7ee9, 0x081b,
+ 0x7eea, 0x0fc2,
+ 0x7eeb, 0x17e9,
+ 0x7eec, 0x43db,
+ 0x7eed, 0x0fc3,
+ 0x7eee, 0x17ea,
+ 0x7ef0, 0x0545,
+ 0x7ef1, 0x17ec,
+ 0x7ef3, 0x0d37,
+ 0x7ef4, 0x0ebb,
+ 0x7ef5, 0x0ae5,
+ 0x7ef6, 0x17ef,
+ 0x7ef7, 0x042a,
+ 0x7ef8, 0x0516,
+ 0x7ef9, 0x43dc,
+ 0x7efa, 0x17f0,
+ 0x7efc, 0x1238,
+ 0x7efd, 0x1161,
+ 0x7efe, 0x17f2,
+ 0x7eff, 0x0a73,
+ 0x7f00, 0x1217,
+ 0x7f01, 0x17f3,
+ 0x7f04, 0x085d,
+ 0x7f05, 0x0aea,
+ 0x7f06, 0x09ad,
+ 0x7f07, 0x17f6,
+ 0x7f09, 0x081c,
+ 0x7f0a, 0x43dd,
+ 0x7f0b, 0x17f8,
+ 0x7f0d, 0x17ee,
+ 0x7f0e, 0x060f,
+ 0x7f0f, 0x17fa,
+ 0x7f10, 0x43de,
+ 0x7f11, 0x17fb,
+ 0x7f13, 0x07cf,
+ 0x7f14, 0x05bf,
+ 0x7f15, 0x0a6d,
+ 0x7f16, 0x0449,
+ 0x7f17, 0x17fd,
+ 0x7f18, 0x10f8,
+ 0x7f19, 0x17fe,
+ 0x7f1a, 0x06ba,
+ 0x7f1b, 0x1800,
+ 0x7f1c, 0x17ff,
+ 0x7f1d, 0x0689,
+ 0x7f1e, 0x43df,
+ 0x7f1f, 0x1801,
+ 0x7f20, 0x04bf,
+ 0x7f21, 0x1802,
+ 0x7f28, 0x108c,
+ 0x7f29, 0x0dea,
+ 0x7f2a, 0x1809,
+ 0x7f2e, 0x0d02,
+ 0x7f2f, 0x180d,
+ 0x7f34, 0x089a,
+ 0x7f35, 0x1812,
+ 0x7f36, 0x1c5e,
+ 0x7f37, 0x43e0,
+ 0x7f38, 0x06d2,
+ 0x7f39, 0x43e1,
+ 0x7f3a, 0x0c8c,
+ 0x7f3b, 0x43e2,
+ 0x7f42, 0x1c5f,
+ 0x7f43, 0x43e9,
+ 0x7f44, 0x1c60,
+ 0x7f46, 0x43ea,
+ 0x7f4c, 0x25e2,
+ 0x7f4d, 0x43f0,
+ 0x7f4e, 0x269a,
+ 0x7f4f, 0x43f1,
+ 0x7f50, 0x0737,
+ 0x7f51, 0x0ea9,
+ 0x7f52, 0x43f2,
+ 0x7f54, 0x129e,
+ 0x7f55, 0x0768,
+ 0x7f56, 0x43f4,
+ 0x7f57, 0x0a85,
+ 0x7f58, 0x1a81,
+ 0x7f59, 0x43f5,
+ 0x7f5a, 0x0640,
+ 0x7f5b, 0x43f6,
+ 0x7f5f, 0x1a83,
+ 0x7f60, 0x43fa,
+ 0x7f61, 0x1a82,
+ 0x7f62, 0x03e0,
+ 0x7f63, 0x43fb,
+ 0x7f68, 0x1a85,
+ 0x7f69, 0x1177,
+ 0x7f6a, 0x124c,
+ 0x7f6b, 0x4400,
+ 0x7f6e, 0x11c2,
+ 0x7f6f, 0x4403,
+ 0x7f70, 0x1eea,
+ 0x7f71, 0x1a87,
+ 0x7f72, 0x0d87,
+ 0x7f73, 0x4404,
+ 0x7f74, 0x1a86,
+ 0x7f75, 0x4405,
+ 0x7f77, 0x1e2c,
+ 0x7f78, 0x4407,
+ 0x7f79, 0x1a88,
+ 0x7f7a, 0x4408,
+ 0x7f7e, 0x1a8a,
+ 0x7f7f, 0x440c,
+ 0x7f81, 0x1a89,
+ 0x7f82, 0x440e,
+ 0x7f85, 0x2062,
+ 0x7f86, 0x24f1,
+ 0x7f87, 0x4411,
+ 0x7f88, 0x24f2,
+ 0x7f89, 0x4412,
+ 0x7f8a, 0x101b,
+ 0x7f8b, 0x4413,
+ 0x7f8c, 0x0c39,
+ 0x7f8d, 0x4414,
+ 0x7f8e, 0x0ac5,
+ 0x7f8f, 0x4415,
+ 0x7f94, 0x06dc,
+ 0x7f95, 0x441a,
+ 0x7f9a, 0x0a30,
+ 0x7f9b, 0x441f,
+ 0x7f9d, 0x1cc4,
+ 0x7f9e, 0x0faa,
+ 0x7f9f, 0x1cc5,
+ 0x7fa0, 0x4421,
+ 0x7fa1, 0x0f48,
+ 0x7fa2, 0x4422,
+ 0x7fa4, 0x0c95,
+ 0x7fa5, 0x25f2,
+ 0x7fa6, 0x4424,
+ 0x7fa7, 0x1cc6,
+ 0x7fa8, 0x4425,
+ 0x7fa9, 0x2215,
+ 0x7faa, 0x4426,
+ 0x7faf, 0x1cc7,
+ 0x7fb1, 0x442b,
+ 0x7fb2, 0x1cc9,
+ 0x7fb3, 0x442c,
+ 0x7fb8, 0x130e,
+ 0x7fb9, 0x06f9,
+ 0x7fba, 0x4431,
+ 0x7fbc, 0x176d,
+ 0x7fbd, 0x10d5,
+ 0x7fbe, 0x4433,
+ 0x7fbf, 0x1cde,
+ 0x7fc0, 0x4434,
+ 0x7fc1, 0x0edb,
+ 0x7fc2, 0x4435,
+ 0x7fc5, 0x0506,
+ 0x7fc6, 0x4438,
+ 0x7fca, 0x1b98,
+ 0x7fcb, 0x443c,
+ 0x7fcc, 0x1075,
+ 0x7fcd, 0x443d,
+ 0x7fce, 0x1cdf,
+ 0x7fcf, 0x443e,
+ 0x7fd2, 0x21ae,
+ 0x7fd3, 0x4441,
+ 0x7fd4, 0x0f55,
+ 0x7fd5, 0x1ce0,
+ 0x7fd6, 0x4442,
+ 0x7fd8, 0x0c49,
+ 0x7fd9, 0x4444,
+ 0x7fdf, 0x05b5,
+ 0x7fe0, 0x0567,
+ 0x7fe1, 0x1ce2,
+ 0x7fe2, 0x444a,
+ 0x7fe5, 0x1ce1,
+ 0x7fe6, 0x1ce3,
+ 0x7fe7, 0x444d,
+ 0x7fe9, 0x1ce4,
+ 0x7fea, 0x444f,
+ 0x7fee, 0x1ce5,
+ 0x7fef, 0x4453,
+ 0x7ff0, 0x0769,
+ 0x7ff1, 0x03ca,
+ 0x7ff2, 0x4454,
+ 0x7ff3, 0x1ce6,
+ 0x7ff4, 0x4455,
+ 0x7ff9, 0x20e0,
+ 0x7ffa, 0x445a,
+ 0x7ffb, 0x064a,
+ 0x7ffc, 0x1074,
+ 0x7ffd, 0x445b,
+ 0x8000, 0x1032,
+ 0x8001, 0x09ba,
+ 0x8002, 0x445e,
+ 0x8003, 0x0949,
+ 0x8004, 0x1953,
+ 0x8005, 0x1180,
+ 0x8006, 0x191a,
+ 0x8007, 0x445f,
+ 0x800b, 0x1bd7,
+ 0x800c, 0x0637,
+ 0x800d, 0x0d98,
+ 0x800e, 0x4463,
+ 0x8010, 0x0b30,
+ 0x8011, 0x4465,
+ 0x8012, 0x1bcb,
+ 0x8013, 0x4466,
+ 0x8014, 0x1bcc,
+ 0x8015, 0x06f6,
+ 0x8016, 0x1bcd,
+ 0x8017, 0x077b,
+ 0x8018, 0x1108,
+ 0x8019, 0x03dd,
+ 0x801a, 0x4467,
+ 0x801c, 0x1bce,
+ 0x801d, 0x4469,
+ 0x8020, 0x1bcf,
+ 0x8021, 0x446c,
+ 0x8022, 0x1bd0,
+ 0x8023, 0x446d,
+ 0x8025, 0x1bd1,
+ 0x8028, 0x1bd5,
+ 0x8029, 0x1bd4,
+ 0x802a, 0x0b96,
+ 0x802b, 0x446f,
+ 0x802c, 0x25c2,
+ 0x802d, 0x4470,
+ 0x802e, 0x25c1,
+ 0x802f, 0x4471,
+ 0x8031, 0x1bd6,
+ 0x8032, 0x4473,
+ 0x8033, 0x0639,
+ 0x8034, 0x4474,
+ 0x8035, 0x1bd8,
+ 0x8036, 0x1035,
+ 0x8037, 0x14b1,
+ 0x8038, 0x0dbf,
+ 0x8039, 0x4475,
+ 0x803b, 0x0501,
+ 0x803c, 0x4477,
+ 0x803d, 0x0583,
+ 0x803e, 0x4478,
+ 0x803f, 0x06fb,
+ 0x8040, 0x4479,
+ 0x8042, 0x0b57,
+ 0x8043, 0x1bd9,
+ 0x8044, 0x447b,
+ 0x8046, 0x1bda,
+ 0x8047, 0x447d,
+ 0x804a, 0x0a0d,
+ 0x804b, 0x0a44,
+ 0x804c, 0x11af,
+ 0x804d, 0x1bdb,
+ 0x804e, 0x4480,
+ 0x8052, 0x1bdc,
+ 0x8053, 0x4484,
+ 0x8054, 0x09f3,
+ 0x8055, 0x4485,
+ 0x8056, 0x2128,
+ 0x8057, 0x4486,
+ 0x8058, 0x0bd7,
+ 0x8059, 0x4487,
+ 0x805a, 0x090a,
+ 0x805b, 0x4488,
+ 0x805e, 0x2199,
+ 0x805f, 0x448b,
+ 0x8069, 0x1bdd,
+ 0x806a, 0x0552,
+ 0x806b, 0x4495,
+ 0x806f, 0x2017,
+ 0x8070, 0x1ea0,
+ 0x8071, 0x1bde,
+ 0x8072, 0x2125,
+ 0x8073, 0x214d,
+ 0x8074, 0x4499,
+ 0x8075, 0x25c4,
+ 0x8076, 0x209d,
+ 0x8077, 0x228a,
+ 0x8078, 0x449a,
+ 0x8079, 0x25c3,
+ 0x807a, 0x449b,
+ 0x807d, 0x2179,
+ 0x807e, 0x2038,
+ 0x807f, 0x1a1e,
+ 0x8080, 0x1a1d,
+ 0x8081, 0x449e,
+ 0x8083, 0x0dd5,
+ 0x8084, 0x1065,
+ 0x8085, 0x2155,
+ 0x8086, 0x0db6,
+ 0x8087, 0x1179,
+ 0x8088, 0x44a0,
+ 0x8089, 0x0cbd,
+ 0x808a, 0x44a1,
+ 0x808b, 0x09ca,
+ 0x808c, 0x0814,
+ 0x808d, 0x44a2,
+ 0x8093, 0x1971,
+ 0x8094, 0x44a8,
+ 0x8096, 0x0f6f,
+ 0x8097, 0x44aa,
+ 0x8098, 0x11e1,
+ 0x8099, 0x44ab,
+ 0x809a, 0x0606,
+ 0x809b, 0x06d3,
+ 0x809c, 0x1970,
+ 0x809d, 0x06c9,
+ 0x809e, 0x44ac,
+ 0x809f, 0x196f,
+ 0x80a0, 0x04cb,
+ 0x80a1, 0x0722,
+ 0x80a2, 0x11aa,
+ 0x80a3, 0x44ad,
+ 0x80a4, 0x0691,
+ 0x80a5, 0x0667,
+ 0x80a6, 0x44ae,
+ 0x80a9, 0x085a,
+ 0x80aa, 0x065b,
+ 0x80ab, 0x1976,
+ 0x80ac, 0x44b1,
+ 0x80ad, 0x1977,
+ 0x80ae, 0x03c4,
+ 0x80af, 0x095c,
+ 0x80b0, 0x44b2,
+ 0x80b1, 0x1975,
+ 0x80b2, 0x10e2,
+ 0x80b3, 0x44b3,
+ 0x80b4, 0x1978,
+ 0x80b5, 0x44b4,
+ 0x80b7, 0x1979,
+ 0x80b8, 0x44b6,
+ 0x80ba, 0x066b,
+ 0x80bb, 0x44b8,
+ 0x80bc, 0x1972,
+ 0x80bd, 0x1974,
+ 0x80be, 0x0d2f,
+ 0x80bf, 0x11d6,
+ 0x80c0, 0x116e,
+ 0x80c1, 0x0f7d,
+ 0x80c2, 0x197f,
+ 0x80c3, 0x0ec7,
+ 0x80c4, 0x1980,
+ 0x80c5, 0x44b9,
+ 0x80c6, 0x0589,
+ 0x80c7, 0x44ba,
+ 0x80cc, 0x041c,
+ 0x80cd, 0x1982,
+ 0x80ce, 0x0df8,
+ 0x80cf, 0x44bf,
+ 0x80d6, 0x0b97,
+ 0x80d7, 0x1983,
+ 0x80d8, 0x44c6,
+ 0x80d9, 0x1981,
+ 0x80da, 0x0ba0,
+ 0x80db, 0x197e,
+ 0x80dc, 0x0d3b,
+ 0x80dd, 0x1985,
+ 0x80de, 0x0406,
+ 0x80df, 0x44c7,
+ 0x80e1, 0x07b1,
+ 0x80e2, 0x44c9,
+ 0x80e4, 0x126d,
+ 0x80e5, 0x1bc7,
+ 0x80e6, 0x44cb,
+ 0x80e7, 0x197a,
+ 0x80eb, 0x1986,
+ 0x80ec, 0x179a,
+ 0x80ed, 0x1989,
+ 0x80ee, 0x44cc,
+ 0x80ef, 0x0975,
+ 0x80f0, 0x104f,
+ 0x80f1, 0x1987,
+ 0x80f2, 0x198c,
+ 0x80f3, 0x06e7,
+ 0x80f4, 0x1988,
+ 0x80f5, 0x44cd,
+ 0x80f6, 0x088b,
+ 0x80f7, 0x44ce,
+ 0x80f8, 0x0fa3,
+ 0x80f9, 0x44cf,
+ 0x80fa, 0x03c2,
+ 0x80fb, 0x44d0,
+ 0x80fc, 0x198d,
+ 0x80fd, 0x0b3f,
+ 0x80fe, 0x44d1,
+ 0x8100, 0x44d3,
+ 0x8102, 0x11ab,
+ 0x8103, 0x44d5,
+ 0x8105, 0x21d2,
+ 0x8106, 0x0563,
+ 0x8107, 0x44d7,
+ 0x8109, 0x0a9d,
+ 0x810a, 0x082c,
+ 0x810b, 0x44d9,
+ 0x810d, 0x198a,
+ 0x810f, 0x1123,
+ 0x8110, 0x0c09,
+ 0x8111, 0x0b37,
+ 0x8112, 0x198f,
+ 0x8113, 0x0b68,
+ 0x8114, 0x1309,
+ 0x8115, 0x44db,
+ 0x8116, 0x0478,
+ 0x8117, 0x44dc,
+ 0x8118, 0x1994,
+ 0x8119, 0x44dd,
+ 0x811a, 0x0896,
+ 0x811b, 0x24c7,
+ 0x811c, 0x44de,
+ 0x811e, 0x1992,
+ 0x811f, 0x44e0,
+ 0x812c, 0x1993,
+ 0x812d, 0x44ed,
+ 0x812f, 0x06a7,
+ 0x8130, 0x44ef,
+ 0x8131, 0x0e82,
+ 0x8132, 0x1995,
+ 0x8133, 0x44f0,
+ 0x8136, 0x1991,
+ 0x8137, 0x44f3,
+ 0x8138, 0x09fc,
+ 0x8139, 0x2279,
+ 0x813a, 0x44f4,
+ 0x813e, 0x0bc1,
+ 0x813f, 0x44f8,
+ 0x8146, 0x0e46,
+ 0x8147, 0x44ff,
+ 0x8148, 0x1996,
+ 0x8149, 0x4500,
+ 0x814a, 0x099b,
+ 0x814b, 0x103f,
+ 0x814c, 0x1997,
+ 0x814d, 0x4501,
+ 0x814e, 0x2123,
+ 0x814f, 0x4502,
+ 0x8150, 0x06aa,
+ 0x8151, 0x06a8,
+ 0x8152, 0x4503,
+ 0x8153, 0x1998,
+ 0x8154, 0x0c38,
+ 0x8155, 0x0ea4,
+ 0x8156, 0x24c5,
+ 0x8157, 0x4504,
+ 0x8159, 0x199a,
+ 0x815b, 0x4506,
+ 0x8160, 0x199d,
+ 0x8161, 0x24c9,
+ 0x8162, 0x450b,
+ 0x8165, 0x0f93,
+ 0x8166, 0x2094,
+ 0x8167, 0x19a2,
+ 0x8168, 0x450e,
+ 0x8169, 0x199e,
+ 0x816a, 0x450f,
+ 0x816b, 0x2296,
+ 0x816c, 0x4510,
+ 0x816d, 0x19a1,
+ 0x816e, 0x0cd4,
+ 0x816f, 0x4511,
+ 0x8170, 0x1025,
+ 0x8171, 0x199c,
+ 0x8172, 0x4512,
+ 0x8174, 0x1999,
+ 0x8175, 0x4514,
+ 0x8178, 0x1e77,
+ 0x8179, 0x06b4,
+ 0x817a, 0x0f46,
+ 0x817b, 0x0b48,
+ 0x817c, 0x199f,
+ 0x817e, 0x0e2d,
+ 0x817f, 0x0e79,
+ 0x8180, 0x03fd,
+ 0x8181, 0x4517,
+ 0x8182, 0x19a6,
+ 0x8183, 0x4518,
+ 0x8188, 0x19a5,
+ 0x8189, 0x451d,
+ 0x818a, 0x0479,
+ 0x818b, 0x451e,
+ 0x818f, 0x06db,
+ 0x8190, 0x4522,
+ 0x8191, 0x19a7,
+ 0x8192, 0x4523,
+ 0x8198, 0x0455,
+ 0x8199, 0x4529,
+ 0x819a, 0x1f06,
+ 0x819b, 0x0e18,
+ 0x819c, 0x0b07,
+ 0x819d, 0x0f12,
+ 0x819e, 0x452a,
+ 0x81a0, 0x1fa5,
+ 0x81a1, 0x452c,
+ 0x81a3, 0x19a9,
+ 0x81a4, 0x452e,
+ 0x81a6, 0x19b0,
+ 0x81a7, 0x4530,
+ 0x81a8, 0x0bb3,
+ 0x81a9, 0x2099,
+ 0x81aa, 0x19aa,
+ 0x81ab, 0x4531,
+ 0x81b3, 0x0cfe,
+ 0x81b4, 0x4539,
+ 0x81ba, 0x1641,
+ 0x81bb, 0x19ae,
+ 0x81bc, 0x453f,
+ 0x81bd, 0x1ead,
+ 0x81be, 0x24c8,
+ 0x81bf, 0x20a8,
+ 0x81c0, 0x0e7f,
+ 0x81c1, 0x19af,
+ 0x81c2, 0x0444,
+ 0x81c3, 0x109c,
+ 0x81c4, 0x4540,
+ 0x81c6, 0x1063,
+ 0x81c7, 0x4542,
+ 0x81c9, 0x201f,
+ 0x81ca, 0x19ad,
+ 0x81cb, 0x4544,
+ 0x81cc, 0x19ab,
+ 0x81cd, 0x20c5,
+ 0x81ce, 0x4545,
+ 0x81cf, 0x24ca,
+ 0x81d0, 0x4546,
+ 0x81d8, 0x1ff0,
+ 0x81d9, 0x454e,
+ 0x81da, 0x24c6,
+ 0x81db, 0x454f,
+ 0x81df, 0x225d,
+ 0x81e0, 0x22de,
+ 0x81e1, 0x4553,
+ 0x81e3, 0x04e1,
+ 0x81e4, 0x4555,
+ 0x81e7, 0x1902,
+ 0x81e8, 0x202c,
+ 0x81e9, 0x4558,
+ 0x81ea, 0x1231,
+ 0x81eb, 0x4559,
+ 0x81ec, 0x1ca9,
+ 0x81ed, 0x0519,
+ 0x81ee, 0x455a,
+ 0x81f3, 0x11c0,
+ 0x81f5, 0x455f,
+ 0x81fa, 0x2161,
+ 0x81fb, 0x118a,
+ 0x81fc, 0x08f9,
+ 0x81fd, 0x4564,
+ 0x81fe, 0x1ca5,
+ 0x81ff, 0x4565,
+ 0x8200, 0x102f,
+ 0x8201, 0x1ca6,
+ 0x8203, 0x4566,
+ 0x8204, 0x1ca8,
+ 0x8205, 0x08fa,
+ 0x8206, 0x10c4,
+ 0x8207, 0x223b,
+ 0x8208, 0x21d9,
+ 0x8209, 0x1fcb,
+ 0x820a, 0x1fc9,
+ 0x820b, 0x4567,
+ 0x820c, 0x0d19,
+ 0x820e, 0x4568,
+ 0x8210, 0x1c62,
+ 0x8211, 0x456a,
+ 0x8212, 0x0d7d,
+ 0x8213, 0x456b,
+ 0x8214, 0x0e45,
+ 0x8215, 0x456c,
+ 0x821b, 0x1618,
+ 0x821c, 0x0da9,
+ 0x821d, 0x4572,
+ 0x821e, 0x0ef7,
+ 0x821f, 0x11da,
+ 0x8220, 0x4573,
+ 0x8221, 0x1cab,
+ 0x8224, 0x4574,
+ 0x8228, 0x1cb0,
+ 0x8229, 0x4578,
+ 0x822a, 0x0774,
+ 0x822b, 0x1cb1,
+ 0x822c, 0x03ee,
+ 0x822d, 0x1cae,
+ 0x822e, 0x4579,
+ 0x822f, 0x1caf,
+ 0x8230, 0x0873,
+ 0x8231, 0x049c,
+ 0x8232, 0x457a,
+ 0x8233, 0x1cb4,
+ 0x8235, 0x0625,
+ 0x8236, 0x0477,
+ 0x8237, 0x0f3c,
+ 0x8238, 0x1cb2,
+ 0x8239, 0x052f,
+ 0x823a, 0x457b,
+ 0x823b, 0x1cb3,
+ 0x823c, 0x457c,
+ 0x823e, 0x1cb6,
+ 0x823f, 0x457e,
+ 0x8244, 0x1cb7,
+ 0x8245, 0x4583,
+ 0x8247, 0x0e58,
+ 0x8248, 0x4585,
+ 0x8249, 0x1cb8,
+ 0x824a, 0x4586,
+ 0x824b, 0x1cb9,
+ 0x824c, 0x4587,
+ 0x824f, 0x1cba,
+ 0x8250, 0x458a,
+ 0x8258, 0x0dc7,
+ 0x8259, 0x1e61,
+ 0x825a, 0x1cbb,
+ 0x825b, 0x4592,
+ 0x825f, 0x1cbc,
+ 0x8260, 0x4596,
+ 0x8264, 0x25ef,
+ 0x8265, 0x459a,
+ 0x8266, 0x1f98,
+ 0x8267, 0x459b,
+ 0x8268, 0x1cbd,
+ 0x8269, 0x459c,
+ 0x826b, 0x25f0,
+ 0x826c, 0x459e,
+ 0x826e, 0x1cdc,
+ 0x826f, 0x0a05,
+ 0x8270, 0x085b,
+ 0x8271, 0x1f88,
+ 0x8272, 0x0ce4,
+ 0x8273, 0x1007,
+ 0x8274, 0x1771,
+ 0x8275, 0x45a0,
+ 0x8277, 0x21f8,
+ 0x8278, 0x45a2,
+ 0x8279, 0x13e1,
+ 0x827a, 0x105c,
+ 0x827b, 0x45a3,
+ 0x827d, 0x13e2,
+ 0x827e, 0x03b7,
+ 0x827f, 0x13e3,
+ 0x8280, 0x45a5,
+ 0x8282, 0x08ab,
+ 0x8283, 0x45a7,
+ 0x8284, 0x13e7,
+ 0x8285, 0x45a8,
+ 0x8288, 0x1278,
+ 0x8289, 0x45ab,
+ 0x828a, 0x13e5,
+ 0x828b, 0x10d8,
+ 0x828c, 0x45ac,
+ 0x828d, 0x0d0f,
+ 0x828e, 0x13e8,
+ 0x828f, 0x13e4,
+ 0x8290, 0x45ad,
+ 0x8291, 0x13e9,
+ 0x8292, 0x0aa7,
+ 0x8293, 0x45ae,
+ 0x8297, 0x13ea,
+ 0x8298, 0x13f3,
+ 0x8299, 0x13eb,
+ 0x829a, 0x45b2,
+ 0x829c, 0x0eee,
+ 0x829d, 0x11a4,
+ 0x829e, 0x45b4,
+ 0x829f, 0x13fd,
+ 0x82a0, 0x45b5,
+ 0x82a1, 0x13fb,
+ 0x82a2, 0x45b6,
+ 0x82a4, 0x1400,
+ 0x82a5, 0x08b7,
+ 0x82a6, 0x0a52,
+ 0x82a7, 0x45b8,
+ 0x82a8, 0x13e6,
+ 0x82a9, 0x13f9,
+ 0x82aa, 0x13fc,
+ 0x82ab, 0x13ec,
+ 0x82ac, 0x066f,
+ 0x82ad, 0x03d0,
+ 0x82ae, 0x13f5,
+ 0x82af, 0x0f89,
+ 0x82b0, 0x13ef,
+ 0x82b1, 0x07bd,
+ 0x82b2, 0x45b9,
+ 0x82b3, 0x0659,
+ 0x82b4, 0x13fa,
+ 0x82b5, 0x45ba,
+ 0x82b7, 0x13f4,
+ 0x82b8, 0x13ed,
+ 0x82b9, 0x0c58,
+ 0x82ba, 0x45bc,
+ 0x82bb, 0x2322,
+ 0x82bc, 0x45bd,
+ 0x82bd, 0x0fe8,
+ 0x82be, 0x13ee,
+ 0x82bf, 0x45be,
+ 0x82c1, 0x13f8,
+ 0x82c2, 0x45c0,
+ 0x82c4, 0x13fe,
+ 0x82c5, 0x45c2,
+ 0x82c7, 0x0ebc,
+ 0x82c8, 0x13f0,
+ 0x82c9, 0x45c4,
+ 0x82ca, 0x13f1,
+ 0x82cb, 0x13f6,
+ 0x82cd, 0x049b,
+ 0x82ce, 0x13ff,
+ 0x82cf, 0x0dca,
+ 0x82d0, 0x45c5,
+ 0x82d1, 0x10fa,
+ 0x82d2, 0x1409,
+ 0x82d3, 0x140d,
+ 0x82d4, 0x0df9,
+ 0x82d5, 0x1414,
+ 0x82d6, 0x45c6,
+ 0x82d7, 0x0aec,
+ 0x82d8, 0x140a,
+ 0x82d9, 0x45c7,
+ 0x82db, 0x094e,
+ 0x82dc, 0x1407,
+ 0x82dd, 0x45c9,
+ 0x82de, 0x0405,
+ 0x82df, 0x070f,
+ 0x82e0, 0x1413,
+ 0x82e1, 0x1401,
+ 0x82e2, 0x45ca,
+ 0x82e3, 0x13f2,
+ 0x82e4, 0x1404,
+ 0x82e5, 0x0ccf,
+ 0x82e6, 0x096d,
+ 0x82e7, 0x2336,
+ 0x82e8, 0x45cb,
+ 0x82eb, 0x0cf4,
+ 0x82ec, 0x45ce,
+ 0x82ef, 0x0426,
+ 0x82f0, 0x45d1,
+ 0x82f1, 0x1087,
+ 0x82f2, 0x45d2,
+ 0x82f4, 0x1408,
+ 0x82f5, 0x45d4,
+ 0x82f7, 0x1403,
+ 0x82f8, 0x45d6,
+ 0x82f9, 0x0bda,
+ 0x82fa, 0x45d7,
+ 0x82fb, 0x140c,
+ 0x82fc, 0x45d8,
+ 0x8300, 0x45dc,
+ 0x8301, 0x121f,
+ 0x8302, 0x0ab4,
+ 0x8303, 0x0653,
+ 0x8304, 0x0c4e,
+ 0x8305, 0x0aae,
+ 0x8306, 0x1410,
+ 0x8307, 0x1406,
+ 0x8308, 0x1419,
+ 0x8309, 0x1402,
+ 0x830a, 0x45dd,
+ 0x830c, 0x140b,
+ 0x830d, 0x45df,
+ 0x830e, 0x08d4,
+ 0x830f, 0x1405,
+ 0x8310, 0x45e0,
+ 0x8311, 0x140e,
+ 0x8312, 0x45e1,
+ 0x8314, 0x1411,
+ 0x8316, 0x45e3,
+ 0x8317, 0x1426,
+ 0x8318, 0x45e4,
+ 0x831a, 0x140f,
+ 0x831b, 0x142e,
+ 0x831c, 0x1415,
+ 0x831d, 0x45e6,
+ 0x8327, 0x085e,
+ 0x8328, 0x0547,
+ 0x8329, 0x45f0,
+ 0x832b, 0x0aa8,
+ 0x832c, 0x04ae,
+ 0x832d, 0x1428,
+ 0x832e, 0x45f2,
+ 0x832f, 0x1420,
+ 0x8330, 0x45f3,
+ 0x8331, 0x141d,
+ 0x8332, 0x45f4,
+ 0x8333, 0x142a,
+ 0x8334, 0x141c,
+ 0x8335, 0x1077,
+ 0x8336, 0x04af,
+ 0x8337, 0x45f5,
+ 0x8338, 0x0cb2,
+ 0x8339, 0x0cbe,
+ 0x833a, 0x1429,
+ 0x833b, 0x45f6,
+ 0x833c, 0x141b,
+ 0x833d, 0x45f7,
+ 0x8340, 0x1425,
+ 0x8341, 0x45fa,
+ 0x8343, 0x1423,
+ 0x8344, 0x45fc,
+ 0x8346, 0x08d2,
+ 0x8347, 0x1422,
+ 0x8348, 0x45fe,
+ 0x8349, 0x04a4,
+ 0x834a, 0x45ff,
+ 0x834f, 0x1421,
+ 0x8350, 0x0869,
+ 0x8351, 0x1416,
+ 0x8352, 0x07d9,
+ 0x8353, 0x4604,
+ 0x8354, 0x09de,
+ 0x8355, 0x4605,
+ 0x835a, 0x0847,
+ 0x835b, 0x1417,
+ 0x835d, 0x460a,
+ 0x835e, 0x141f,
+ 0x835f, 0x1424,
+ 0x8360, 0x1427,
+ 0x8361, 0x0595,
+ 0x8362, 0x460b,
+ 0x8363, 0x0cb4,
+ 0x8364, 0x07fc,
+ 0x8365, 0x142c,
+ 0x8366, 0x142b,
+ 0x8367, 0x1090,
+ 0x8368, 0x142d,
+ 0x8369, 0x142f,
+ 0x836a, 0x1431,
+ 0x836b, 0x1078,
+ 0x836c, 0x1430,
+ 0x836d, 0x1432,
+ 0x836f, 0x1030,
+ 0x8370, 0x460c,
+ 0x8377, 0x0780,
+ 0x8378, 0x1435,
+ 0x8379, 0x4613,
+ 0x837b, 0x1442,
+ 0x837c, 0x143d,
+ 0x837d, 0x1440,
+ 0x837e, 0x4615,
+ 0x8385, 0x143c,
+ 0x8386, 0x0bed,
+ 0x8387, 0x461c,
+ 0x8389, 0x09dd,
+ 0x838a, 0x22ab,
+ 0x838b, 0x461e,
+ 0x838e, 0x0ce8,
+ 0x838f, 0x4621,
+ 0x8392, 0x141a,
+ 0x8393, 0x143a,
+ 0x8394, 0x4624,
+ 0x8396, 0x1fbf,
+ 0x8397, 0x4626,
+ 0x8398, 0x1443,
+ 0x8399, 0x4627,
+ 0x839b, 0x141e,
+ 0x839c, 0x143b,
+ 0x839d, 0x4629,
+ 0x839e, 0x1444,
+ 0x839f, 0x462a,
+ 0x83a0, 0x1438,
+ 0x83a1, 0x462b,
+ 0x83a2, 0x1f7d,
+ 0x83a3, 0x462c,
+ 0x83a7, 0x2333,
+ 0x83a8, 0x1445,
+ 0x83a9, 0x143f,
+ 0x83aa, 0x1439,
+ 0x83ab, 0x0b0d,
+ 0x83ac, 0x4630,
+ 0x83b0, 0x1434,
+ 0x83b1, 0x099e,
+ 0x83b2, 0x09f4,
+ 0x83b3, 0x1436,
+ 0x83b5, 0x4634,
+ 0x83b6, 0x143e,
+ 0x83b7, 0x0806,
+ 0x83b8, 0x1441,
+ 0x83b9, 0x108d,
+ 0x83ba, 0x1446,
+ 0x83bb, 0x4635,
+ 0x83bc, 0x1447,
+ 0x83bd, 0x0aac,
+ 0x83be, 0x4636,
+ 0x83c0, 0x145e,
+ 0x83c1, 0x1448,
+ 0x83c2, 0x4638,
+ 0x83c5, 0x145d,
+ 0x83c6, 0x463b,
+ 0x83c7, 0x0716,
+ 0x83c8, 0x463c,
+ 0x83ca, 0x0904,
+ 0x83cb, 0x463e,
+ 0x83cc, 0x0929,
+ 0x83cd, 0x463f,
+ 0x83cf, 0x0781,
+ 0x83d0, 0x4641,
+ 0x83d4, 0x1456,
+ 0x83d5, 0x4645,
+ 0x83d6, 0x1451,
+ 0x83d7, 0x4646,
+ 0x83d8, 0x144b,
+ 0x83d9, 0x4647,
+ 0x83dc, 0x0492,
+ 0x83dd, 0x144f,
+ 0x83de, 0x464a,
+ 0x83df, 0x1457,
+ 0x83e0, 0x046b,
+ 0x83e1, 0x1461,
+ 0x83e2, 0x464b,
+ 0x83e5, 0x144a,
+ 0x83e6, 0x464e,
+ 0x83e9, 0x0bef,
+ 0x83ea, 0x145c,
+ 0x83eb, 0x4651,
+ 0x83ef, 0x1f4d,
+ 0x83f0, 0x1460,
+ 0x83f1, 0x0a2b,
+ 0x83f2, 0x0663,
+ 0x83f3, 0x4655,
+ 0x83f8, 0x145a,
+ 0x83fa, 0x465a,
+ 0x83fd, 0x1450,
+ 0x83fe, 0x465d,
+ 0x8400, 0x465f,
+ 0x8401, 0x1449,
+ 0x8402, 0x4660,
+ 0x8403, 0x1459,
+ 0x8404, 0x0e24,
+ 0x8405, 0x4661,
+ 0x8406, 0x1455,
+ 0x8407, 0x2334,
+ 0x8408, 0x4662,
+ 0x840a, 0x1ff1,
+ 0x840b, 0x144e,
+ 0x840c, 0x0acd,
+ 0x840d, 0x0bdb,
+ 0x840e, 0x0ebd,
+ 0x840f, 0x1458,
+ 0x8410, 0x4664,
+ 0x8411, 0x1454,
+ 0x8412, 0x4665,
+ 0x8418, 0x144d,
+ 0x8419, 0x466b,
+ 0x841c, 0x1452,
+ 0x841d, 0x0a83,
+ 0x841e, 0x466e,
+ 0x8424, 0x108e,
+ 0x8426, 0x145f,
+ 0x8427, 0x0f61,
+ 0x8428, 0x0cd3,
+ 0x8429, 0x4674,
+ 0x842c, 0x218b,
+ 0x842d, 0x4677,
+ 0x8431, 0x1472,
+ 0x8432, 0x467b,
+ 0x8435, 0x2349,
+ 0x8436, 0x467e,
+ 0x8438, 0x1453,
+ 0x8439, 0x4680,
+ 0x843c, 0x146c,
+ 0x843d, 0x0a8b,
+ 0x843e, 0x4683,
+ 0x8446, 0x146d,
+ 0x8447, 0x468b,
+ 0x8449, 0x220b,
+ 0x844a, 0x468d,
+ 0x8451, 0x1463,
+ 0x8452, 0x2346,
+ 0x8453, 0x4694,
+ 0x8457, 0x11f7,
+ 0x8458, 0x4698,
+ 0x8459, 0x1465,
+ 0x845a, 0x1464,
+ 0x845b, 0x06eb,
+ 0x845c, 0x1462,
+ 0x845d, 0x4699,
+ 0x8461, 0x0bee,
+ 0x8462, 0x469d,
+ 0x8463, 0x05ec,
+ 0x8464, 0x2347,
+ 0x8465, 0x469e,
+ 0x8466, 0x2193,
+ 0x8467, 0x469f,
+ 0x8469, 0x146e,
+ 0x846a, 0x46a1,
+ 0x846b, 0x07b0,
+ 0x846c, 0x1124,
+ 0x846d, 0x1473,
+ 0x846e, 0x46a2,
+ 0x846f, 0x26a1,
+ 0x8470, 0x46a3,
+ 0x8471, 0x0553,
+ 0x8472, 0x46a4,
+ 0x8473, 0x1466,
+ 0x8474, 0x46a5,
+ 0x8475, 0x0988,
+ 0x8476, 0x146f,
+ 0x8477, 0x1f62,
+ 0x8478, 0x146b,
+ 0x8479, 0x46a6,
+ 0x847a, 0x1469,
+ 0x847b, 0x46a7,
+ 0x8482, 0x05ba,
+ 0x8483, 0x46ae,
+ 0x8487, 0x1467,
+ 0x8489, 0x146a,
+ 0x848a, 0x46b2,
+ 0x848b, 0x0880,
+ 0x848c, 0x1470,
+ 0x848d, 0x46b3,
+ 0x848e, 0x1471,
+ 0x848f, 0x46b4,
+ 0x8493, 0x234d,
+ 0x8494, 0x2348,
+ 0x8495, 0x46b8,
+ 0x8497, 0x1481,
+ 0x8498, 0x46ba,
+ 0x8499, 0x0ace,
+ 0x849a, 0x46bb,
+ 0x849c, 0x0dd7,
+ 0x849d, 0x46bd,
+ 0x84a1, 0x147e,
+ 0x84a2, 0x46c1,
+ 0x84af, 0x1297,
+ 0x84b0, 0x46ce,
+ 0x84b2, 0x0bf0,
+ 0x84b3, 0x46d0,
+ 0x84b4, 0x1480,
+ 0x84b5, 0x46d1,
+ 0x84b8, 0x1195,
+ 0x84b9, 0x147f,
+ 0x84ba, 0x147c,
+ 0x84bb, 0x46d4,
+ 0x84bc, 0x1e60,
+ 0x84bd, 0x1478,
+ 0x84be, 0x46d5,
+ 0x84bf, 0x147b,
+ 0x84c0, 0x2345,
+ 0x84c1, 0x1474,
+ 0x84c2, 0x46d6,
+ 0x84c4, 0x0fb9,
+ 0x84c5, 0x46d8,
+ 0x84c9, 0x0cb3,
+ 0x84ca, 0x147a,
+ 0x84cb, 0x1f12,
+ 0x84cc, 0x46dc,
+ 0x84cd, 0x1475,
+ 0x84ce, 0x46dd,
+ 0x84d0, 0x1476,
+ 0x84d1, 0x0de7,
+ 0x84d2, 0x46df,
+ 0x84d3, 0x1479,
+ 0x84d4, 0x46e0,
+ 0x84d6, 0x0436,
+ 0x84d7, 0x46e2,
+ 0x84dd, 0x09a1,
+ 0x84de, 0x46e8,
+ 0x84df, 0x082e,
+ 0x84e0, 0x147d,
+ 0x84e1, 0x46e9,
+ 0x84e3, 0x1483,
+ 0x84e4, 0x46eb,
+ 0x84e5, 0x1482,
+ 0x84e6, 0x1477,
+ 0x84e7, 0x46ec,
+ 0x84ec, 0x0baf,
+ 0x84ed, 0x46f1,
+ 0x84ee, 0x2018,
+ 0x84ef, 0x2335,
+ 0x84f0, 0x1487,
+ 0x84f1, 0x46f2,
+ 0x84fc, 0x148e,
+ 0x84fd, 0x233c,
+ 0x84fe, 0x46fd,
+ 0x84ff, 0x148d,
+ 0x8500, 0x46fe,
+ 0x850c, 0x1484,
+ 0x850d, 0x470a,
+ 0x8511, 0x0af4,
+ 0x8512, 0x470e,
+ 0x8513, 0x0aa2,
+ 0x8514, 0x266f,
+ 0x8515, 0x470f,
+ 0x8517, 0x1182,
+ 0x8518, 0x4711,
+ 0x851a, 0x0ec4,
+ 0x851b, 0x4713,
+ 0x851e, 0x2351,
+ 0x851f, 0x1489,
+ 0x8520, 0x4716,
+ 0x8521, 0x0493,
+ 0x8522, 0x4717,
+ 0x8523, 0x1fa0,
+ 0x8524, 0x4718,
+ 0x8526, 0x2338,
+ 0x8527, 0x471a,
+ 0x852b, 0x0b4b,
+ 0x852c, 0x0d76,
+ 0x852d, 0x221b,
+ 0x852e, 0x471e,
+ 0x8537, 0x0c3b,
+ 0x8538, 0x1486,
+ 0x8539, 0x1488,
+ 0x853a, 0x148a,
+ 0x853b, 0x148c,
+ 0x853c, 0x03b5,
+ 0x853d, 0x0437,
+ 0x853e, 0x4727,
+ 0x8541, 0x2342,
+ 0x8542, 0x472a,
+ 0x8543, 0x1496,
+ 0x8544, 0x472b,
+ 0x8546, 0x234f,
+ 0x8547, 0x472d,
+ 0x8548, 0x1490,
+ 0x8549, 0x0887,
+ 0x854a, 0x0cca,
+ 0x854b, 0x472e,
+ 0x854e, 0x233d,
+ 0x854f, 0x4731,
+ 0x8552, 0x2344,
+ 0x8553, 0x2331,
+ 0x8554, 0x4734,
+ 0x8555, 0x234b,
+ 0x8556, 0x148b,
+ 0x8557, 0x4735,
+ 0x8558, 0x233b,
+ 0x8559, 0x148f,
+ 0x855a, 0x4736,
+ 0x855e, 0x1493,
+ 0x855f, 0x473a,
+ 0x8562, 0x2350,
+ 0x8563, 0x473d,
+ 0x8564, 0x1492,
+ 0x8565, 0x473e,
+ 0x8568, 0x1491,
+ 0x8569, 0x1eb4,
+ 0x856a, 0x21a6,
+ 0x856b, 0x4741,
+ 0x856d, 0x21cb,
+ 0x856e, 0x4743,
+ 0x8572, 0x1497,
+ 0x8573, 0x4747,
+ 0x8574, 0x110f,
+ 0x8575, 0x4748,
+ 0x8577, 0x2355,
+ 0x8578, 0x474a,
+ 0x8579, 0x149d,
+ 0x857a, 0x1494,
+ 0x857b, 0x1498,
+ 0x857c, 0x474b,
+ 0x857e, 0x09c4,
+ 0x857f, 0x474d,
+ 0x8584, 0x040a,
+ 0x8585, 0x14a0,
+ 0x8586, 0x4752,
+ 0x8587, 0x149b,
+ 0x8588, 0x233e,
+ 0x8589, 0x4753,
+ 0x858a, 0x1f74,
+ 0x858b, 0x4754,
+ 0x858c, 0x2330,
+ 0x858d, 0x4755,
+ 0x858f, 0x149c,
+ 0x8590, 0x4757,
+ 0x8591, 0x2680,
+ 0x8592, 0x4758,
+ 0x8594, 0x20da,
+ 0x8595, 0x475a,
+ 0x859b, 0x0fcf,
+ 0x859c, 0x149f,
+ 0x859d, 0x4760,
+ 0x859f, 0x234a,
+ 0x85a0, 0x4762,
+ 0x85a4, 0x1499,
+ 0x85a5, 0x4766,
+ 0x85a6, 0x1f91,
+ 0x85a7, 0x4767,
+ 0x85a8, 0x149a,
+ 0x85a9, 0x2107,
+ 0x85aa, 0x0f88,
+ 0x85ab, 0x4768,
+ 0x85ae, 0x149e,
+ 0x85af, 0x0d84,
+ 0x85b0, 0x14a3,
+ 0x85b1, 0x476b,
+ 0x85b7, 0x14a2,
+ 0x85b8, 0x4771,
+ 0x85b9, 0x14a1,
+ 0x85ba, 0x233f,
+ 0x85bb, 0x4772,
+ 0x85c1, 0x14a5,
+ 0x85c2, 0x4778,
+ 0x85c9, 0x08b6,
+ 0x85ca, 0x477f,
+ 0x85cd, 0x1ff4,
+ 0x85ce, 0x2343,
+ 0x85cf, 0x049f,
+ 0x85d0, 0x0aef,
+ 0x85d1, 0x4782,
+ 0x85d3, 0x14a4,
+ 0x85d4, 0x4784,
+ 0x85d5, 0x0b7b,
+ 0x85d6, 0x4785,
+ 0x85dc, 0x14a6,
+ 0x85dd, 0x2212,
+ 0x85de, 0x478b,
+ 0x85e4, 0x0e2c,
+ 0x85e5, 0x2207,
+ 0x85e6, 0x4791,
+ 0x85e9, 0x0647,
+ 0x85ea, 0x2359,
+ 0x85eb, 0x4794,
+ 0x85f4, 0x2254,
+ 0x85f5, 0x479d,
+ 0x85f6, 0x2332,
+ 0x85f7, 0x479e,
+ 0x85f9, 0x1e26,
+ 0x85fa, 0x2357,
+ 0x85fb, 0x1128,
+ 0x85fc, 0x47a0,
+ 0x85ff, 0x14a7,
+ 0x8600, 0x47a3,
+ 0x8604, 0x2358,
+ 0x8605, 0x14a9,
+ 0x8606, 0x2042,
+ 0x8607, 0x2153,
+ 0x8608, 0x47a7,
+ 0x860b, 0x20bb,
+ 0x860c, 0x47aa,
+ 0x8611, 0x0b05,
+ 0x8612, 0x47af,
+ 0x8616, 0x14ab,
+ 0x8617, 0x47b3,
+ 0x861a, 0x235a,
+ 0x861b, 0x47b6,
+ 0x861e, 0x2356,
+ 0x861f, 0x47b9,
+ 0x8622, 0x2337,
+ 0x8623, 0x47bc,
+ 0x8627, 0x14a8,
+ 0x8628, 0x47c0,
+ 0x8629, 0x14aa,
+ 0x862a, 0x47c1,
+ 0x862d, 0x1ff9,
+ 0x862e, 0x47c4,
+ 0x8638, 0x115b,
+ 0x8639, 0x47ce,
+ 0x863a, 0x2353,
+ 0x863b, 0x47cf,
+ 0x863c, 0x14ac,
+ 0x863d, 0x47d0,
+ 0x863f, 0x2061,
+ 0x8640, 0x47d2,
+ 0x864d, 0x1bf0,
+ 0x864e, 0x07b7,
+ 0x864f, 0x0a59,
+ 0x8650, 0x0b71,
+ 0x8651, 0x0a6e,
+ 0x8652, 0x47df,
+ 0x8654, 0x1bf1,
+ 0x8655, 0x1e95,
+ 0x8656, 0x47e1,
+ 0x865a, 0x0fb4,
+ 0x865b, 0x47e5,
+ 0x865c, 0x2049,
+ 0x865d, 0x47e6,
+ 0x865e, 0x10c2,
+ 0x865f, 0x1f42,
+ 0x8660, 0x47e7,
+ 0x8662, 0x196d,
+ 0x8663, 0x47e9,
+ 0x8667, 0x1fe8,
+ 0x8668, 0x47ed,
+ 0x866b, 0x050b,
+ 0x866c, 0x1bf2,
+ 0x866d, 0x47f0,
+ 0x866e, 0x1bf3,
+ 0x866f, 0x47f1,
+ 0x8671, 0x0d44,
+ 0x8672, 0x47f3,
+ 0x8679, 0x079e,
+ 0x867a, 0x1bf5,
+ 0x867b, 0x1bf7,
+ 0x867c, 0x1bf6,
+ 0x867d, 0x0dd9,
+ 0x867e, 0x0f27,
+ 0x867f, 0x1bf4,
+ 0x8680, 0x0d4b,
+ 0x8681, 0x1056,
+ 0x8682, 0x0a93,
+ 0x8683, 0x47fa,
+ 0x868a, 0x0ed2,
+ 0x868b, 0x1bfa,
+ 0x868c, 0x0401,
+ 0x868d, 0x1bf9,
+ 0x868e, 0x4801,
+ 0x8693, 0x1c00,
+ 0x8694, 0x4806,
+ 0x8695, 0x0496,
+ 0x8696, 0x4807,
+ 0x869c, 0x0fea,
+ 0x869d, 0x1bfc,
+ 0x869e, 0x480d,
+ 0x86a3, 0x1bfe,
+ 0x86a4, 0x112c,
+ 0x86a5, 0x4812,
+ 0x86a7, 0x1bfd,
+ 0x86a8, 0x1bf8,
+ 0x86a9, 0x1c01,
+ 0x86aa, 0x1bff,
+ 0x86ab, 0x4814,
+ 0x86ac, 0x1bfb,
+ 0x86ad, 0x4815,
+ 0x86af, 0x1c09,
+ 0x86b0, 0x1c06,
+ 0x86b1, 0x1c08,
+ 0x86b2, 0x4817,
+ 0x86b4, 0x1c0c,
+ 0x86b5, 0x1c04,
+ 0x86b6, 0x1c02,
+ 0x86b7, 0x4819,
+ 0x86ba, 0x1c07,
+ 0x86bb, 0x481c,
+ 0x86c0, 0x11fa,
+ 0x86c1, 0x4821,
+ 0x86c4, 0x1c03,
+ 0x86c5, 0x4824,
+ 0x86c6, 0x0c76,
+ 0x86c7, 0x0d18,
+ 0x86c8, 0x4825,
+ 0x86c9, 0x1c0a,
+ 0x86ca, 0x071f,
+ 0x86cb, 0x0591,
+ 0x86cc, 0x4826,
+ 0x86ce, 0x1c05,
+ 0x86cf, 0x1c0b,
+ 0x86d0, 0x1c12,
+ 0x86d1, 0x1c18,
+ 0x86d2, 0x4828,
+ 0x86d4, 0x07ec,
+ 0x86d5, 0x482a,
+ 0x86d8, 0x1c17,
+ 0x86d9, 0x0e8d,
+ 0x86da, 0x482d,
+ 0x86db, 0x11ea,
+ 0x86dc, 0x482e,
+ 0x86de, 0x1c14,
+ 0x86df, 0x1c16,
+ 0x86e0, 0x4830,
+ 0x86e4, 0x06ed,
+ 0x86e5, 0x4834,
+ 0x86e9, 0x1c0d,
+ 0x86ea, 0x4838,
+ 0x86ed, 0x1c10,
+ 0x86ee, 0x0aa0,
+ 0x86ef, 0x483b,
+ 0x86f0, 0x117e,
+ 0x86f1, 0x1c0e,
+ 0x86f3, 0x1c11,
+ 0x86f4, 0x1c15,
+ 0x86f5, 0x483c,
+ 0x86f8, 0x1c1b,
+ 0x86f9, 0x10a1,
+ 0x86fa, 0x25da,
+ 0x86fb, 0x483f,
+ 0x86fe, 0x0629,
+ 0x86ff, 0x4842,
+ 0x8700, 0x0d88,
+ 0x8701, 0x4843,
+ 0x8702, 0x0681,
+ 0x8703, 0x1c19,
+ 0x8704, 0x4844,
+ 0x8706, 0x25d7,
+ 0x8707, 0x1c1a,
+ 0x8708, 0x1c1c,
+ 0x8709, 0x1c1f,
+ 0x870a, 0x1c1d,
+ 0x870b, 0x4846,
+ 0x870d, 0x1c1e,
+ 0x870e, 0x4848,
+ 0x8712, 0x0ffa,
+ 0x8713, 0x1c13,
+ 0x8714, 0x484c,
+ 0x8715, 0x0e7a,
+ 0x8716, 0x484d,
+ 0x8717, 0x0ede,
+ 0x8718, 0x11a8,
+ 0x8719, 0x484e,
+ 0x871a, 0x1c25,
+ 0x871b, 0x484f,
+ 0x871c, 0x0ae0,
+ 0x871d, 0x4850,
+ 0x871e, 0x1c22,
+ 0x871f, 0x4851,
+ 0x8721, 0x099a,
+ 0x8722, 0x1c2e,
+ 0x8723, 0x1c20,
+ 0x8724, 0x4853,
+ 0x8725, 0x1c23,
+ 0x8726, 0x4854,
+ 0x8729, 0x1c2a,
+ 0x872a, 0x4857,
+ 0x872e, 0x1c24,
+ 0x872f, 0x485b,
+ 0x8731, 0x1c29,
+ 0x8732, 0x485d,
+ 0x8734, 0x1c28,
+ 0x8735, 0x485f,
+ 0x8737, 0x1c2b,
+ 0x8738, 0x4861,
+ 0x873b, 0x1c21,
+ 0x873c, 0x4864,
+ 0x873e, 0x1c26,
+ 0x873f, 0x1c2c,
+ 0x8740, 0x4866,
+ 0x8747, 0x1091,
+ 0x8748, 0x1c27,
+ 0x8749, 0x04bc,
+ 0x874a, 0x486d,
+ 0x874c, 0x1c34,
+ 0x874d, 0x486f,
+ 0x874e, 0x0f76,
+ 0x874f, 0x4870,
+ 0x8753, 0x1c37,
+ 0x8754, 0x4874,
+ 0x8755, 0x212e,
+ 0x8756, 0x4875,
+ 0x8757, 0x07dd,
+ 0x8758, 0x4876,
+ 0x8759, 0x1c3b,
+ 0x875a, 0x4877,
+ 0x8760, 0x1c32,
+ 0x8761, 0x487d,
+ 0x8763, 0x1c38,
+ 0x8764, 0x1c3a,
+ 0x8765, 0x1c3c,
+ 0x8766, 0x21b2,
+ 0x8767, 0x487f,
+ 0x876e, 0x1c35,
+ 0x876f, 0x4886,
+ 0x8770, 0x1c33,
+ 0x8771, 0x4887,
+ 0x8774, 0x07b2,
+ 0x8775, 0x488a,
+ 0x8776, 0x05dc,
+ 0x8777, 0x488b,
+ 0x8778, 0x219e,
+ 0x8779, 0x488c,
+ 0x877b, 0x1c31,
+ 0x877c, 0x1c39,
+ 0x877d, 0x1c2f,
+ 0x877f, 0x488e,
+ 0x8782, 0x1c2d,
+ 0x8783, 0x1c46,
+ 0x8784, 0x25dc,
+ 0x8785, 0x1c43,
+ 0x8786, 0x4891,
+ 0x8788, 0x1c42,
+ 0x8789, 0x4893,
+ 0x878b, 0x1c36,
+ 0x878c, 0x4895,
+ 0x878d, 0x0cb5,
+ 0x878e, 0x4896,
+ 0x8793, 0x1c3d,
+ 0x8794, 0x489b,
+ 0x8797, 0x1c45,
+ 0x8798, 0x489e,
+ 0x879e, 0x206c,
+ 0x879f, 0x0afd,
+ 0x87a0, 0x48a4,
+ 0x87a2, 0x2226,
+ 0x87a3, 0x48a6,
+ 0x87a8, 0x1c3f,
+ 0x87a9, 0x48ab,
+ 0x87ab, 0x1c47,
+ 0x87ac, 0x1c49,
+ 0x87ad, 0x1c44,
+ 0x87ae, 0x48ad,
+ 0x87af, 0x1c3e,
+ 0x87b0, 0x48ae,
+ 0x87b3, 0x1c4b,
+ 0x87b4, 0x48b1,
+ 0x87b5, 0x1c4a,
+ 0x87b6, 0x48b2,
+ 0x87ba, 0x0a84,
+ 0x87bb, 0x25e0,
+ 0x87bc, 0x48b6,
+ 0x87bd, 0x1c4e,
+ 0x87be, 0x48b7,
+ 0x87c0, 0x1c50,
+ 0x87c1, 0x48b9,
+ 0x87c4, 0x227b,
+ 0x87c5, 0x48bc,
+ 0x87c6, 0x1c41,
+ 0x87c7, 0x48bd,
+ 0x87c8, 0x25de,
+ 0x87c9, 0x48be,
+ 0x87ca, 0x1c51,
+ 0x87cb, 0x1c4c,
+ 0x87cc, 0x48bf,
+ 0x87ce, 0x25e1,
+ 0x87cf, 0x48c1,
+ 0x87d1, 0x1c4f,
+ 0x87d2, 0x1c40,
+ 0x87d3, 0x1c4d,
+ 0x87d4, 0x48c3,
+ 0x87db, 0x1c52,
+ 0x87dc, 0x48ca,
+ 0x87e0, 0x1c54,
+ 0x87e1, 0x48ce,
+ 0x87e3, 0x25d5,
+ 0x87e4, 0x48d0,
+ 0x87e5, 0x1c48,
+ 0x87e6, 0x48d1,
+ 0x87ea, 0x1c53,
+ 0x87eb, 0x48d5,
+ 0x87ec, 0x1e6b,
+ 0x87ed, 0x48d6,
+ 0x87ee, 0x1c55,
+ 0x87ef, 0x25db,
+ 0x87f0, 0x48d7,
+ 0x87f2, 0x1e89,
+ 0x87f3, 0x48d9,
+ 0x87f6, 0x25d9,
+ 0x87f7, 0x48dc,
+ 0x87f9, 0x0f82,
+ 0x87fa, 0x48de,
+ 0x87fb, 0x2211,
+ 0x87fc, 0x48df,
+ 0x87fe, 0x1c58,
+ 0x87ff, 0x48e1,
+ 0x8800, 0x48e2,
+ 0x8803, 0x130d,
+ 0x8804, 0x48e5,
+ 0x8805, 0x2229,
+ 0x8806, 0x25d6,
+ 0x8807, 0x48e6,
+ 0x880a, 0x1c59,
+ 0x880b, 0x48e9,
+ 0x8810, 0x25dd,
+ 0x8811, 0x25df,
+ 0x8812, 0x48ee,
+ 0x8813, 0x1c57,
+ 0x8814, 0x48ef,
+ 0x8815, 0x0cbf,
+ 0x8816, 0x1c56,
+ 0x8817, 0x48f0,
+ 0x881b, 0x1c5a,
+ 0x881c, 0x48f4,
+ 0x881f, 0x1fef,
+ 0x8820, 0x48f7,
+ 0x8821, 0x1c5b,
+ 0x8822, 0x0543,
+ 0x8823, 0x25d8,
+ 0x8824, 0x48f8,
+ 0x8831, 0x1f29,
+ 0x8832, 0x1a8d,
+ 0x8833, 0x4905,
+ 0x8836, 0x1e5b,
+ 0x8837, 0x4908,
+ 0x8839, 0x1c5c,
+ 0x883a, 0x490a,
+ 0x883b, 0x2076,
+ 0x883c, 0x1c5d,
+ 0x883d, 0x490b,
+ 0x8840, 0x0fd3,
+ 0x8841, 0x490e,
+ 0x8844, 0x1caa,
+ 0x8845, 0x0f91,
+ 0x8846, 0x2297,
+ 0x8847, 0x4911,
+ 0x884a, 0x2690,
+ 0x884b, 0x4914,
+ 0x884c, 0x0f9b,
+ 0x884d, 0x1005,
+ 0x884e, 0x4915,
+ 0x8853, 0x213f,
+ 0x8854, 0x0f3b,
+ 0x8855, 0x491a,
+ 0x8857, 0x08a7,
+ 0x8858, 0x491c,
+ 0x8859, 0x0fec,
+ 0x885a, 0x491d,
+ 0x885b, 0x2198,
+ 0x885c, 0x491e,
+ 0x885d, 0x1e88,
+ 0x885e, 0x491f,
+ 0x8861, 0x0799,
+ 0x8862, 0x15ed,
+ 0x8863, 0x1049,
+ 0x8864, 0x1ba6,
+ 0x8865, 0x0480,
+ 0x8866, 0x4922,
+ 0x8868, 0x0456,
+ 0x8869, 0x1ba7,
+ 0x886a, 0x4924,
+ 0x886b, 0x0cf9,
+ 0x886c, 0x04e9,
+ 0x886d, 0x4925,
+ 0x886e, 0x1306,
+ 0x886f, 0x4926,
+ 0x8870, 0x0d9a,
+ 0x8871, 0x4927,
+ 0x8872, 0x1ba8,
+ 0x8873, 0x4928,
+ 0x8877, 0x11d3,
+ 0x8878, 0x492c,
+ 0x8879, 0x228c,
+ 0x887a, 0x492d,
+ 0x887d, 0x1ba9,
+ 0x887e, 0x1cbe,
+ 0x887f, 0x1baa,
+ 0x8880, 0x4930,
+ 0x8881, 0x10ef,
+ 0x8882, 0x1bab,
+ 0x8883, 0x4931,
+ 0x8884, 0x03cb,
+ 0x8885, 0x1cbf,
+ 0x8886, 0x4932,
+ 0x8888, 0x1cc0,
+ 0x8889, 0x4934,
+ 0x888b, 0x057f,
+ 0x888c, 0x4936,
+ 0x888d, 0x0b9c,
+ 0x888e, 0x4937,
+ 0x8892, 0x0e0e,
+ 0x8893, 0x493b,
+ 0x8896, 0x0faf,
+ 0x8897, 0x493e,
+ 0x889c, 0x0e91,
+ 0x889d, 0x4943,
+ 0x88a2, 0x1bac,
+ 0x88a3, 0x4948,
+ 0x88a4, 0x1307,
+ 0x88a5, 0x4949,
+ 0x88ab, 0x0424,
+ 0x88ac, 0x494f,
+ 0x88ad, 0x0f1b,
+ 0x88ae, 0x4950,
+ 0x88b1, 0x069f,
+ 0x88b2, 0x4953,
+ 0x88b7, 0x1bae,
+ 0x88b8, 0x4958,
+ 0x88bc, 0x1baf,
+ 0x88bd, 0x495c,
+ 0x88c1, 0x048a,
+ 0x88c2, 0x0a1a,
+ 0x88c3, 0x4960,
+ 0x88c5, 0x120d,
+ 0x88c6, 0x1bad,
+ 0x88c7, 0x4962,
+ 0x88c9, 0x1bb0,
+ 0x88ca, 0x25f1,
+ 0x88cb, 0x4964,
+ 0x88ce, 0x1bb2,
+ 0x88cf, 0x200c,
+ 0x88d0, 0x4967,
+ 0x88d2, 0x130a,
+ 0x88d3, 0x4969,
+ 0x88d4, 0x1068,
+ 0x88d5, 0x10e6,
+ 0x88d6, 0x496a,
+ 0x88d8, 0x1cc1,
+ 0x88d9, 0x0c94,
+ 0x88da, 0x496c,
+ 0x88dc, 0x1e58,
+ 0x88dd, 0x22ac,
+ 0x88de, 0x496e,
+ 0x88df, 0x1cc2,
+ 0x88e0, 0x496f,
+ 0x88e2, 0x1bb1,
+ 0x88e3, 0x1bb3,
+ 0x88e4, 0x0970,
+ 0x88e5, 0x1bb4,
+ 0x88e6, 0x4971,
+ 0x88e8, 0x1bb8,
+ 0x88e9, 0x4973,
+ 0x88f0, 0x1bba,
+ 0x88f1, 0x1bb5,
+ 0x88f2, 0x497a,
+ 0x88f3, 0x0d0a,
+ 0x88f4, 0x0ba2,
+ 0x88f5, 0x497b,
+ 0x88f8, 0x0a8a,
+ 0x88f9, 0x0755,
+ 0x88fa, 0x497e,
+ 0x88fc, 0x1bb7,
+ 0x88fd, 0x26a7,
+ 0x88fe, 0x1bb9,
+ 0x88ff, 0x4980,
+ 0x8900, 0x4981,
+ 0x8902, 0x072c,
+ 0x8903, 0x4983,
+ 0x8907, 0x2676,
+ 0x8908, 0x4987,
+ 0x890a, 0x1bbf,
+ 0x890b, 0x4989,
+ 0x8910, 0x078d,
+ 0x8911, 0x498e,
+ 0x8912, 0x0408,
+ 0x8913, 0x1bbd,
+ 0x8914, 0x498f,
+ 0x8919, 0x1bbc,
+ 0x891a, 0x1bb6,
+ 0x891b, 0x1bbe,
+ 0x891c, 0x4994,
+ 0x8921, 0x1bbb,
+ 0x8922, 0x4999,
+ 0x8925, 0x0cc7,
+ 0x8926, 0x499c,
+ 0x892a, 0x0e7b,
+ 0x892b, 0x1bc1,
+ 0x892c, 0x49a0,
+ 0x8930, 0x1739,
+ 0x8931, 0x49a4,
+ 0x8932, 0x1fe1,
+ 0x8933, 0x25bb,
+ 0x8934, 0x1bc0,
+ 0x8935, 0x49a5,
+ 0x8936, 0x1bc2,
+ 0x8937, 0x49a6,
+ 0x8938, 0x25be,
+ 0x8939, 0x49a7,
+ 0x893b, 0x22dd,
+ 0x893c, 0x49a9,
+ 0x8941, 0x1bc3,
+ 0x8942, 0x49ae,
+ 0x8944, 0x0f52,
+ 0x8945, 0x49b0,
+ 0x8947, 0x25bd,
+ 0x8948, 0x49b2,
+ 0x8956, 0x1e2a,
+ 0x8957, 0x49c0,
+ 0x895d, 0x25bc,
+ 0x895e, 0x1cc3,
+ 0x895f, 0x08c4,
+ 0x8960, 0x25ba,
+ 0x8961, 0x49c6,
+ 0x8964, 0x25bf,
+ 0x8965, 0x49c9,
+ 0x8966, 0x1bc4,
+ 0x8967, 0x49ca,
+ 0x896a, 0x2187,
+ 0x896b, 0x49cd,
+ 0x896c, 0x266b,
+ 0x896d, 0x49ce,
+ 0x896f, 0x1e7f,
+ 0x8970, 0x49d0,
+ 0x8972, 0x21ad,
+ 0x8973, 0x49d2,
+ 0x897b, 0x1bc5,
+ 0x897c, 0x49da,
+ 0x897f, 0x0f06,
+ 0x8980, 0x49dd,
+ 0x8981, 0x1031,
+ 0x8982, 0x49de,
+ 0x8983, 0x1bdf,
+ 0x8984, 0x49df,
+ 0x8986, 0x06ad,
+ 0x8987, 0x49e1,
+ 0x898b, 0x1f96,
+ 0x898c, 0x49e5,
+ 0x898f, 0x1f32,
+ 0x8990, 0x49e8,
+ 0x8993, 0x2084,
+ 0x8994, 0x49eb,
+ 0x8996, 0x2136,
+ 0x8997, 0x49ed,
+ 0x8998, 0x24b8,
+ 0x8999, 0x49ee,
+ 0x89a1, 0x24ba,
+ 0x89a2, 0x49f6,
+ 0x89a6, 0x24bc,
+ 0x89a7, 0x49fa,
+ 0x89aa, 0x20e4,
+ 0x89ab, 0x49fd,
+ 0x89ac, 0x24b9,
+ 0x89ad, 0x49fe,
+ 0x89af, 0x24bd,
+ 0x89b0, 0x4a00,
+ 0x89b2, 0x24be,
+ 0x89b3, 0x4a02,
+ 0x89b7, 0x24bf,
+ 0x89b8, 0x4a06,
+ 0x89ba, 0x1fd2,
+ 0x89bb, 0x4a08,
+ 0x89bd, 0x1ffd,
+ 0x89be, 0x4a0a,
+ 0x89bf, 0x24bb,
+ 0x89c0, 0x1f2d,
+ 0x89c1, 0x086e,
+ 0x89c2, 0x0734,
+ 0x89c3, 0x4a0b,
+ 0x89c4, 0x073f,
+ 0x89c5, 0x0ade,
+ 0x89c6, 0x0d6a,
+ 0x89c7, 0x193a,
+ 0x89c8, 0x09ab,
+ 0x89c9, 0x0924,
+ 0x89ca, 0x193b,
+ 0x89cd, 0x4a0c,
+ 0x89ce, 0x193e,
+ 0x89d2, 0x0898,
+ 0x89d3, 0x4a0d,
+ 0x89d6, 0x1d57,
+ 0x89d7, 0x4a10,
+ 0x89da, 0x1d59,
+ 0x89db, 0x4a13,
+ 0x89dc, 0x1d5a,
+ 0x89dd, 0x4a14,
+ 0x89de, 0x1d58,
+ 0x89df, 0x4a15,
+ 0x89e3, 0x08b3,
+ 0x89e4, 0x4a19,
+ 0x89e5, 0x1d5b,
+ 0x89e6, 0x0528,
+ 0x89e7, 0x4a1a,
+ 0x89eb, 0x1d5c,
+ 0x89ec, 0x4a1e,
+ 0x89ef, 0x1d5d,
+ 0x89f0, 0x4a21,
+ 0x89f3, 0x19c0,
+ 0x89f4, 0x2609,
+ 0x89f5, 0x4a24,
+ 0x89f6, 0x260a,
+ 0x89f7, 0x4a25,
+ 0x89f8, 0x1e94,
+ 0x89f9, 0x4a26,
+ 0x8a00, 0x0ffd,
+ 0x8a01, 0x22df,
+ 0x8a02, 0x1ecb,
+ 0x8a03, 0x1f0d,
+ 0x8a04, 0x4a2d,
+ 0x8a07, 0x12fe,
+ 0x8a08, 0x1f77,
+ 0x8a09, 0x4a30,
+ 0x8a0a, 0x21eb,
+ 0x8a0b, 0x4a31,
+ 0x8a0c, 0x22e1,
+ 0x8a0d, 0x4a32,
+ 0x8a0e, 0x216f,
+ 0x8a0f, 0x4a33,
+ 0x8a10, 0x22e0,
+ 0x8a11, 0x4a34,
+ 0x8a13, 0x21ea,
+ 0x8a14, 0x4a36,
+ 0x8a15, 0x22e2,
+ 0x8a16, 0x20cb,
+ 0x8a17, 0x4a37,
+ 0x8a18, 0x1f78,
+ 0x8a19, 0x4a38,
+ 0x8a1b, 0x1ee2,
+ 0x8a1c, 0x4a3a,
+ 0x8a1d, 0x21f2,
+ 0x8a1e, 0x4a3b,
+ 0x8a1f, 0x2150,
+ 0x8a20, 0x4a3c,
+ 0x8a23, 0x1fd3,
+ 0x8a24, 0x4a3f,
+ 0x8a25, 0x22e5,
+ 0x8a26, 0x4a40,
+ 0x8a2a, 0x1ef2,
+ 0x8a2b, 0x4a44,
+ 0x8a2d, 0x211f,
+ 0x8a2e, 0x4a46,
+ 0x8a31, 0x21dd,
+ 0x8a32, 0x4a49,
+ 0x8a34, 0x2154,
+ 0x8a35, 0x4a4b,
+ 0x8a36, 0x22e7,
+ 0x8a37, 0x4a4c,
+ 0x8a3a, 0x2282,
+ 0x8a3b, 0x4a4f,
+ 0x8a3e, 0x1d5e,
+ 0x8a3f, 0x4a52,
+ 0x8a41, 0x22e6,
+ 0x8a42, 0x4a54,
+ 0x8a46, 0x22e8,
+ 0x8a47, 0x4a58,
+ 0x8a48, 0x1a84,
+ 0x8a49, 0x4a59,
+ 0x8a4e, 0x22e4,
+ 0x8a4f, 0x4a5e,
+ 0x8a50, 0x226a,
+ 0x8a51, 0x4a5f,
+ 0x8a52, 0x22eb,
+ 0x8a53, 0x4a60,
+ 0x8a54, 0x22e9,
+ 0x8a55, 0x20bd,
+ 0x8a56, 0x4a61,
+ 0x8a58, 0x22ea,
+ 0x8a59, 0x4a63,
+ 0x8a5b, 0x22bd,
+ 0x8a5c, 0x4a65,
+ 0x8a5e, 0x1e9e,
+ 0x8a5f, 0x4a67,
+ 0x8a61, 0x22f6,
+ 0x8a62, 0x21e7,
+ 0x8a63, 0x2216,
+ 0x8a64, 0x4a69,
+ 0x8a66, 0x2137,
+ 0x8a67, 0x4a6b,
+ 0x8a69, 0x212c,
+ 0x8a6a, 0x4a6d,
+ 0x8a6b, 0x1e68,
+ 0x8a6c, 0x22f2,
+ 0x8a6d, 0x1f37,
+ 0x8a6e, 0x22f3,
+ 0x8a6f, 0x4a6e,
+ 0x8a70, 0x22ef,
+ 0x8a71, 0x1f50,
+ 0x8a72, 0x1f10,
+ 0x8a73, 0x21c8,
+ 0x8a74, 0x4a6f,
+ 0x8a75, 0x22f1,
+ 0x8a76, 0x4a70,
+ 0x8a79, 0x1153,
+ 0x8a7a, 0x4a73,
+ 0x8a7c, 0x22f0,
+ 0x8a7d, 0x4a75,
+ 0x8a7f, 0x22ee,
+ 0x8a80, 0x4a77,
+ 0x8a84, 0x22ed,
+ 0x8a85, 0x229e,
+ 0x8a86, 0x22ec,
+ 0x8a87, 0x1fe2,
+ 0x8a88, 0x4a7b,
+ 0x8a89, 0x10e3,
+ 0x8a8a, 0x0e2f,
+ 0x8a8b, 0x4a7c,
+ 0x8a8d, 0x20fe,
+ 0x8a8e, 0x4a7e,
+ 0x8a91, 0x22f9,
+ 0x8a93, 0x0d5b,
+ 0x8a94, 0x4a81,
+ 0x8a95, 0x1eaf,
+ 0x8a96, 0x4a82,
+ 0x8a98, 0x2236,
+ 0x8a99, 0x4a84,
+ 0x8a9a, 0x22f7,
+ 0x8a9b, 0x4a85,
+ 0x8a9e, 0x223d,
+ 0x8a9f, 0x4a88,
+ 0x8aa0, 0x1e82,
+ 0x8aa1, 0x1fb6,
+ 0x8aa2, 0x4a89,
+ 0x8aa3, 0x21a4,
+ 0x8aa4, 0x21aa,
+ 0x8aa5, 0x22f8,
+ 0x8aa6, 0x2151,
+ 0x8aa7, 0x4a8a,
+ 0x8aa8, 0x1f60,
+ 0x8aa9, 0x4a8b,
+ 0x8aac, 0x2147,
+ 0x8aad, 0x4a8e,
+ 0x8ab0, 0x2145,
+ 0x8ab1, 0x4a91,
+ 0x8ab2, 0x1fdc,
+ 0x8ab3, 0x4a92,
+ 0x8ab6, 0x2301,
+ 0x8ab7, 0x4a95,
+ 0x8ab9, 0x1ef5,
+ 0x8aba, 0x4a97,
+ 0x8abc, 0x2218,
+ 0x8abd, 0x4a99,
+ 0x8abf, 0x1ec6,
+ 0x8ac0, 0x4a9b,
+ 0x8ac2, 0x2300,
+ 0x8ac3, 0x4a9d,
+ 0x8ac4, 0x22b4,
+ 0x8ac5, 0x4a9e,
+ 0x8ac7, 0x2169,
+ 0x8ac8, 0x4aa0,
+ 0x8ac9, 0x22fd,
+ 0x8aca, 0x4aa1,
+ 0x8acb, 0x20ea,
+ 0x8acc, 0x4aa2,
+ 0x8acd, 0x22f4,
+ 0x8ace, 0x4aa3,
+ 0x8acf, 0x22fb,
+ 0x8ad0, 0x4aa4,
+ 0x8ad1, 0x22fc,
+ 0x8ad2, 0x2027,
+ 0x8ad3, 0x4aa5,
+ 0x8ad6, 0x2060,
+ 0x8ad7, 0x22ff,
+ 0x8ad8, 0x4aa8,
+ 0x8adb, 0x22fe,
+ 0x8adc, 0x1ec7,
+ 0x8add, 0x4aab,
+ 0x8ade, 0x230c,
+ 0x8adf, 0x4aac,
+ 0x8ae2, 0x22f5,
+ 0x8ae3, 0x4aaf,
+ 0x8ae4, 0x2306,
+ 0x8ae5, 0x4ab0,
+ 0x8ae6, 0x230a,
+ 0x8ae7, 0x21d3,
+ 0x8ae8, 0x4ab1,
+ 0x8aeb, 0x2303,
+ 0x8aec, 0x4ab4,
+ 0x8aed, 0x2307,
+ 0x8aee, 0x230b,
+ 0x8aef, 0x4ab5,
+ 0x8af1, 0x1f5f,
+ 0x8af2, 0x4ab7,
+ 0x8af3, 0x2309,
+ 0x8af4, 0x4ab8,
+ 0x8af6, 0x2302,
+ 0x8af7, 0x1f04,
+ 0x8af8, 0x229d,
+ 0x8af9, 0x4aba,
+ 0x8afa, 0x21fb,
+ 0x8afb, 0x4abb,
+ 0x8afc, 0x2308,
+ 0x8afd, 0x4abc,
+ 0x8afe, 0x20ac,
+ 0x8aff, 0x4abd,
+ 0x8b00, 0x208e,
+ 0x8b01, 0x2305,
+ 0x8b02, 0x2197,
+ 0x8b03, 0x4abe,
+ 0x8b04, 0x2171,
+ 0x8b05, 0x2298,
+ 0x8b06, 0x4abf,
+ 0x8b07, 0x173c,
+ 0x8b08, 0x4ac0,
+ 0x8b0a, 0x1f57,
+ 0x8b0b, 0x4ac2,
+ 0x8b0e, 0x2082,
+ 0x8b0f, 0x4ac5,
+ 0x8b10, 0x2311,
+ 0x8b11, 0x4ac6,
+ 0x8b14, 0x2304,
+ 0x8b15, 0x4ac9,
+ 0x8b16, 0x230f,
+ 0x8b17, 0x1e35,
+ 0x8b18, 0x4aca,
+ 0x8b19, 0x20d1,
+ 0x8b1a, 0x2310,
+ 0x8b1b, 0x1fa3,
+ 0x8b1c, 0x4acb,
+ 0x8b1d, 0x21d6,
+ 0x8b1e, 0x4acc,
+ 0x8b21, 0x2206,
+ 0x8b22, 0x4acf,
+ 0x8b26, 0x1d5f,
+ 0x8b27, 0x4ad3,
+ 0x8b28, 0x230d,
+ 0x8b29, 0x4ad4,
+ 0x8b2b, 0x2312,
+ 0x8b2c, 0x208d,
+ 0x8b2d, 0x2313,
+ 0x8b2e, 0x4ad6,
+ 0x8b33, 0x22e3,
+ 0x8b34, 0x4adb,
+ 0x8b39, 0x1fba,
+ 0x8b3a, 0x4ae0,
+ 0x8b3e, 0x2078,
+ 0x8b3f, 0x4ae4,
+ 0x8b49, 0x2288,
+ 0x8b4a, 0x4aee,
+ 0x8b4e, 0x2316,
+ 0x8b4f, 0x1f6b,
+ 0x8b50, 0x4af2,
+ 0x8b56, 0x2314,
+ 0x8b57, 0x4af8,
+ 0x8b58, 0x2130,
+ 0x8b59, 0x2315,
+ 0x8b5a, 0x2168,
+ 0x8b5b, 0x4af9,
+ 0x8b5c, 0x20c4,
+ 0x8b5d, 0x4afa,
+ 0x8b66, 0x08de,
+ 0x8b67, 0x4b03,
+ 0x8b6b, 0x2318,
+ 0x8b6c, 0x0bc8,
+ 0x8b6d, 0x4b07,
+ 0x8b6f, 0x2219,
+ 0x8b70, 0x2217,
+ 0x8b71, 0x4b09,
+ 0x8b74, 0x20d5,
+ 0x8b75, 0x4b0c,
+ 0x8b77, 0x1f4a,
+ 0x8b78, 0x4b0e,
+ 0x8b7d, 0x2240,
+ 0x8b7e, 0x4b13,
+ 0x8b80, 0x1ed3,
+ 0x8b81, 0x4b15,
+ 0x8b8a, 0x1e49,
+ 0x8b8b, 0x4b1e,
+ 0x8b8e, 0x261b,
+ 0x8b8f, 0x4b21,
+ 0x8b92, 0x1e6d,
+ 0x8b93, 0x20f8,
+ 0x8b94, 0x4b24,
+ 0x8b95, 0x1ffb,
+ 0x8b96, 0x2319,
+ 0x8b97, 0x4b25,
+ 0x8b9c, 0x230e,
+ 0x8b9d, 0x4b2a,
+ 0x8b9e, 0x2317,
+ 0x8b9f, 0x4b2b,
+ 0x8ba0, 0x1317,
+ 0x8ba1, 0x0839,
+ 0x8ba2, 0x05e8,
+ 0x8ba3, 0x06b7,
+ 0x8ba4, 0x0caa,
+ 0x8ba5, 0x0818,
+ 0x8ba6, 0x1318,
+ 0x8ba8, 0x0e29,
+ 0x8ba9, 0x0c9e,
+ 0x8baa, 0x131a,
+ 0x8bab, 0x0c1c,
+ 0x8bac, 0x4b2c,
+ 0x8bad, 0x0fde,
+ 0x8bae, 0x1070,
+ 0x8baf, 0x0fdf,
+ 0x8bb0, 0x083a,
+ 0x8bb1, 0x4b2d,
+ 0x8bb2, 0x0883,
+ 0x8bb3, 0x07f9,
+ 0x8bb4, 0x131b,
+ 0x8bb6, 0x0ff1,
+ 0x8bb7, 0x131d,
+ 0x8bb8, 0x0fb8,
+ 0x8bb9, 0x062e,
+ 0x8bba, 0x0a82,
+ 0x8bbb, 0x4b2e,
+ 0x8bbc, 0x0dc4,
+ 0x8bbd, 0x068a,
+ 0x8bbe, 0x0d21,
+ 0x8bbf, 0x0660,
+ 0x8bc0, 0x0926,
+ 0x8bc1, 0x11a3,
+ 0x8bc2, 0x131e,
+ 0x8bc4, 0x0bdf,
+ 0x8bc5, 0x1244,
+ 0x8bc6, 0x0d4d,
+ 0x8bc7, 0x4b2f,
+ 0x8bc8, 0x114a,
+ 0x8bc9, 0x0dd4,
+ 0x8bca, 0x1190,
+ 0x8bcb, 0x1320,
+ 0x8bcc, 0x11de,
+ 0x8bcd, 0x054d,
+ 0x8bce, 0x1322,
+ 0x8bcf, 0x1321,
+ 0x8bd0, 0x4b30,
+ 0x8bd1, 0x1072,
+ 0x8bd2, 0x1323,
+ 0x8bd5, 0x0d6b,
+ 0x8bd6, 0x1326,
+ 0x8bd7, 0x0d42,
+ 0x8bd8, 0x1327,
+ 0x8bda, 0x04f4,
+ 0x8bdb, 0x11ee,
+ 0x8bdc, 0x1329,
+ 0x8bdd, 0x07c5,
+ 0x8bde, 0x058f,
+ 0x8bdf, 0x132a,
+ 0x8be1, 0x0747,
+ 0x8be2, 0x0fd8,
+ 0x8be3, 0x106f,
+ 0x8be4, 0x132c,
+ 0x8be5, 0x06be,
+ 0x8be6, 0x0f57,
+ 0x8be7, 0x04b6,
+ 0x8be8, 0x132d,
+ 0x8bea, 0x4b31,
+ 0x8beb, 0x08bc,
+ 0x8bec, 0x0eeb,
+ 0x8bed, 0x10d4,
+ 0x8bee, 0x132f,
+ 0x8bef, 0x0f02,
+ 0x8bf0, 0x1330,
+ 0x8bf1, 0x10ba,
+ 0x8bf2, 0x07fa,
+ 0x8bf3, 0x1331,
+ 0x8bf4, 0x0daa,
+ 0x8bf5, 0x0dc5,
+ 0x8bf6, 0x1332,
+ 0x8bf7, 0x0c68,
+ 0x8bf8, 0x11ed,
+ 0x8bf9, 0x1333,
+ 0x8bfa, 0x0b76,
+ 0x8bfb, 0x0600,
+ 0x8bfc, 0x1334,
+ 0x8bfd, 0x0669,
+ 0x8bfe, 0x095b,
+ 0x8bff, 0x1335,
+ 0x8c00, 0x1336,
+ 0x8c01, 0x0da2,
+ 0x8c02, 0x1337,
+ 0x8c03, 0x05d8,
+ 0x8c04, 0x1338,
+ 0x8c05, 0x0a0b,
+ 0x8c06, 0x1218,
+ 0x8c07, 0x1339,
+ 0x8c08, 0x0e0b,
+ 0x8c09, 0x4b32,
+ 0x8c0a, 0x1071,
+ 0x8c0b, 0x0b14,
+ 0x8c0c, 0x133a,
+ 0x8c0d, 0x05de,
+ 0x8c0e, 0x07e6,
+ 0x8c0f, 0x133b,
+ 0x8c10, 0x0f7e,
+ 0x8c11, 0x133c,
+ 0x8c13, 0x0ecc,
+ 0x8c14, 0x133e,
+ 0x8c17, 0x04be,
+ 0x8c18, 0x1343,
+ 0x8c19, 0x1341,
+ 0x8c1a, 0x1011,
+ 0x8c1b, 0x1342,
+ 0x8c1c, 0x0ada,
+ 0x8c1d, 0x1344,
+ 0x8c1e, 0x4b33,
+ 0x8c1f, 0x1345,
+ 0x8c22, 0x0f86,
+ 0x8c23, 0x102c,
+ 0x8c24, 0x0404,
+ 0x8c25, 0x1348,
+ 0x8c26, 0x0c28,
+ 0x8c27, 0x1349,
+ 0x8c28, 0x08c8,
+ 0x8c29, 0x0aa6,
+ 0x8c2a, 0x134a,
+ 0x8c2c, 0x0b02,
+ 0x8c2d, 0x0e0a,
+ 0x8c2e, 0x134c,
+ 0x8c30, 0x09a9,
+ 0x8c31, 0x0bf6,
+ 0x8c32, 0x134e,
+ 0x8c34, 0x0c31,
+ 0x8c35, 0x1350,
+ 0x8c37, 0x0721,
+ 0x8c38, 0x4b34,
+ 0x8c41, 0x0802,
+ 0x8c42, 0x4b3d,
+ 0x8c46, 0x05f8,
+ 0x8c47, 0x1cf6,
+ 0x8c48, 0x20c8,
+ 0x8c49, 0x1cf7,
+ 0x8c4a, 0x4b41,
+ 0x8c4c, 0x0e94,
+ 0x8c4d, 0x4b43,
+ 0x8c50, 0x1efd,
+ 0x8c51, 0x4b46,
+ 0x8c55, 0x1d15,
+ 0x8c56, 0x4b4a,
+ 0x8c5a, 0x1990,
+ 0x8c5b, 0x4b4e,
+ 0x8c61, 0x0f60,
+ 0x8c62, 0x07d4,
+ 0x8c63, 0x4b54,
+ 0x8c6a, 0x0777,
+ 0x8c6b, 0x10e8,
+ 0x8c6c, 0x4b5b,
+ 0x8c73, 0x15dd,
+ 0x8c74, 0x4b62,
+ 0x8c78, 0x1d50,
+ 0x8c79, 0x0413,
+ 0x8c7a, 0x04b9,
+ 0x8c7b, 0x4b66,
+ 0x8c82, 0x1d51,
+ 0x8c83, 0x4b6d,
+ 0x8c85, 0x1d53,
+ 0x8c86, 0x4b6f,
+ 0x8c89, 0x0788,
+ 0x8c8a, 0x1d52,
+ 0x8c8b, 0x4b72,
+ 0x8c8c, 0x0ab7,
+ 0x8c8d, 0x4b73,
+ 0x8c94, 0x1d55,
+ 0x8c95, 0x4b7a,
+ 0x8c98, 0x1d54,
+ 0x8c99, 0x4b7d,
+ 0x8c9d, 0x1e3b,
+ 0x8c9e, 0x227f,
+ 0x8c9f, 0x4b81,
+ 0x8ca0, 0x1f0c,
+ 0x8ca1, 0x1e59,
+ 0x8ca2, 0x1f24,
+ 0x8ca3, 0x4b82,
+ 0x8ca7, 0x20ba,
+ 0x8ca8, 0x1f65,
+ 0x8ca9, 0x1ef0,
+ 0x8caa, 0x2164,
+ 0x8cab, 0x1f30,
+ 0x8cac, 0x2261,
+ 0x8cad, 0x4b86,
+ 0x8caf, 0x22a2,
+ 0x8cb0, 0x24ab,
+ 0x8cb1, 0x4b88,
+ 0x8cb2, 0x24af,
+ 0x8cb3, 0x1ee8,
+ 0x8cb4, 0x1f39,
+ 0x8cb5, 0x4b89,
+ 0x8cb6, 0x1e48,
+ 0x8cb7, 0x2070,
+ 0x8cb8, 0x1ea8,
+ 0x8cb9, 0x4b8a,
+ 0x8cba, 0x24ac,
+ 0x8cbb, 0x1ef7,
+ 0x8cbc, 0x2176,
+ 0x8cbd, 0x24ad,
+ 0x8cbe, 0x4b8b,
+ 0x8cbf, 0x207b,
+ 0x8cc0, 0x1f45,
+ 0x8cc1, 0x24aa,
+ 0x8cc2, 0x204b,
+ 0x8cc3, 0x202f,
+ 0x8cc4, 0x1f5a,
+ 0x8cc5, 0x24b0,
+ 0x8cc6, 0x4b8c,
+ 0x8cc7, 0x22b7,
+ 0x8cc8, 0x1f7f,
+ 0x8cc9, 0x4b8d,
+ 0x8cca, 0x2265,
+ 0x8ccb, 0x4b8e,
+ 0x8cd1, 0x24b2,
+ 0x8cd2, 0x211b,
+ 0x8cd3, 0x1e51,
+ 0x8cd4, 0x4b94,
+ 0x8cd5, 0x24b4,
+ 0x8cd6, 0x4b95,
+ 0x8cda, 0x24b3,
+ 0x8cdb, 0x4b99,
+ 0x8cdc, 0x1e9f,
+ 0x8cdd, 0x4b9a,
+ 0x8cde, 0x2118,
+ 0x8cdf, 0x4b9b,
+ 0x8ce0, 0x20b4,
+ 0x8ce1, 0x23af,
+ 0x8ce2, 0x21bb,
+ 0x8ce3, 0x2072,
+ 0x8ce4, 0x1f95,
+ 0x8ce5, 0x4b9c,
+ 0x8ce6, 0x1f0a,
+ 0x8ce7, 0x24b6,
+ 0x8ce8, 0x4b9d,
+ 0x8cea, 0x2291,
+ 0x8ceb, 0x24b5,
+ 0x8cec, 0x2278,
+ 0x8ced, 0x1ed4,
+ 0x8cee, 0x4b9f,
+ 0x8cf4, 0x1ff3,
+ 0x8cf5, 0x4ba5,
+ 0x8cfa, 0x22a9,
+ 0x8cfb, 0x24b7,
+ 0x8cfc, 0x1f28,
+ 0x8cfd, 0x2109,
+ 0x8cfe, 0x22c7,
+ 0x8cff, 0x4baa,
+ 0x8d00, 0x4bab,
+ 0x8d04, 0x24ae,
+ 0x8d05, 0x22b1,
+ 0x8d06, 0x4baf,
+ 0x8d08, 0x2266,
+ 0x8d09, 0x4bb1,
+ 0x8d0a, 0x225b,
+ 0x8d0b, 0x22c4,
+ 0x8d0c, 0x4bb2,
+ 0x8d0d, 0x2115,
+ 0x8d0e, 0x4bb3,
+ 0x8d0f, 0x222a,
+ 0x8d10, 0x24b1,
+ 0x8d11, 0x4bb4,
+ 0x8d16, 0x213d,
+ 0x8d17, 0x4bb9,
+ 0x8d1b, 0x1f15,
+ 0x8d1c, 0x225c,
+ 0x8d1d, 0x041d,
+ 0x8d1e, 0x118b,
+ 0x8d1f, 0x06b5,
+ 0x8d20, 0x4bbd,
+ 0x8d21, 0x070a,
+ 0x8d22, 0x048d,
+ 0x8d23, 0x1133,
+ 0x8d24, 0x0f3a,
+ 0x8d25, 0x03e7,
+ 0x8d26, 0x116c,
+ 0x8d27, 0x080a,
+ 0x8d28, 0x11c9,
+ 0x8d29, 0x0654,
+ 0x8d2a, 0x0e03,
+ 0x8d2b, 0x0bd5,
+ 0x8d2c, 0x044a,
+ 0x8d2d, 0x0713,
+ 0x8d2e, 0x11fb,
+ 0x8d2f, 0x073a,
+ 0x8d30, 0x063e,
+ 0x8d31, 0x086d,
+ 0x8d32, 0x192c,
+ 0x8d34, 0x0e4c,
+ 0x8d35, 0x074c,
+ 0x8d36, 0x192e,
+ 0x8d37, 0x057e,
+ 0x8d38, 0x0ab8,
+ 0x8d39, 0x066e,
+ 0x8d3a, 0x078f,
+ 0x8d3b, 0x192f,
+ 0x8d3c, 0x1137,
+ 0x8d3d, 0x1930,
+ 0x8d3e, 0x0849,
+ 0x8d3f, 0x07f4,
+ 0x8d40, 0x1931,
+ 0x8d41, 0x0a27,
+ 0x8d42, 0x0a5f,
+ 0x8d43, 0x1122,
+ 0x8d44, 0x1227,
+ 0x8d45, 0x1932,
+ 0x8d47, 0x1936,
+ 0x8d48, 0x1934,
+ 0x8d4a, 0x0d17,
+ 0x8d4b, 0x06ae,
+ 0x8d4c, 0x0603,
+ 0x8d4d, 0x1937,
+ 0x8d4e, 0x0d81,
+ 0x8d4f, 0x0d06,
+ 0x8d50, 0x0550,
+ 0x8d51, 0x4bbe,
+ 0x8d53, 0x163b,
+ 0x8d54, 0x0ba3,
+ 0x8d55, 0x1938,
+ 0x8d56, 0x09a0,
+ 0x8d57, 0x4bc0,
+ 0x8d58, 0x1215,
+ 0x8d59, 0x1939,
+ 0x8d5a, 0x1209,
+ 0x8d5b, 0x0cd7,
+ 0x8d5c, 0x1289,
+ 0x8d5d, 0x1283,
+ 0x8d5e, 0x1121,
+ 0x8d5f, 0x4bc1,
+ 0x8d60, 0x113c,
+ 0x8d61, 0x0cfd,
+ 0x8d62, 0x1093,
+ 0x8d63, 0x06ce,
+ 0x8d64, 0x0505,
+ 0x8d65, 0x4bc2,
+ 0x8d66, 0x0d1b,
+ 0x8d67, 0x1cf4,
+ 0x8d68, 0x4bc3,
+ 0x8d6b, 0x078c,
+ 0x8d6c, 0x4bc6,
+ 0x8d6d, 0x1cf5,
+ 0x8d6e, 0x4bc7,
+ 0x8d70, 0x123c,
+ 0x8d71, 0x4bc9,
+ 0x8d73, 0x1cef,
+ 0x8d74, 0x06ab,
+ 0x8d75, 0x1175,
+ 0x8d76, 0x06ca,
+ 0x8d77, 0x0c0f,
+ 0x8d78, 0x4bcb,
+ 0x8d81, 0x04e8,
+ 0x8d82, 0x4bd4,
+ 0x8d84, 0x1cf0,
+ 0x8d85, 0x04d1,
+ 0x8d86, 0x4bd6,
+ 0x8d8a, 0x1100,
+ 0x8d8b, 0x0c74,
+ 0x8d8c, 0x4bda,
+ 0x8d91, 0x1cf2,
+ 0x8d92, 0x4bdf,
+ 0x8d94, 0x1cf1,
+ 0x8d95, 0x1f14,
+ 0x8d96, 0x4be1,
+ 0x8d99, 0x227a,
+ 0x8d9a, 0x4be4,
+ 0x8d9f, 0x0e1e,
+ 0x8da0, 0x4be9,
+ 0x8da3, 0x0c7f,
+ 0x8da4, 0x4bec,
+ 0x8da8, 0x20ee,
+ 0x8da9, 0x4bf0,
+ 0x8db1, 0x1cf3,
+ 0x8db2, 0x25f8,
+ 0x8db3, 0x1240,
+ 0x8db4, 0x0b80,
+ 0x8db5, 0x1d1c,
+ 0x8db6, 0x4bf8,
+ 0x8db8, 0x1d17,
+ 0x8db9, 0x4bfa,
+ 0x8dba, 0x1d1f,
+ 0x8dbb, 0x4bfb,
+ 0x8dbc, 0x1d1e,
+ 0x8dbd, 0x4bfc,
+ 0x8dbe, 0x11b9,
+ 0x8dbf, 0x1d1d,
+ 0x8dc0, 0x4bfd,
+ 0x8dc3, 0x1101,
+ 0x8dc4, 0x1d20,
+ 0x8dc5, 0x4c00,
+ 0x8dc6, 0x1d28,
+ 0x8dc7, 0x4c01,
+ 0x8dcb, 0x03da,
+ 0x8dcc, 0x05d9,
+ 0x8dcd, 0x4c05,
+ 0x8dce, 0x1d25,
+ 0x8dd0, 0x4c06,
+ 0x8dd1, 0x0b9d,
+ 0x8dd2, 0x4c07,
+ 0x8dd6, 0x1d21,
+ 0x8dd8, 0x4c0b,
+ 0x8dda, 0x1d23,
+ 0x8ddb, 0x1d27,
+ 0x8ddc, 0x4c0d,
+ 0x8ddd, 0x090f,
+ 0x8dde, 0x1d24,
+ 0x8ddf, 0x06f5,
+ 0x8de0, 0x4c0e,
+ 0x8de3, 0x1d2c,
+ 0x8de4, 0x1d2f,
+ 0x8de5, 0x4c11,
+ 0x8de8, 0x0974,
+ 0x8de9, 0x4c14,
+ 0x8dea, 0x074b,
+ 0x8deb, 0x1d18,
+ 0x8dec, 0x1d29,
+ 0x8ded, 0x4c15,
+ 0x8def, 0x0a5e,
+ 0x8df0, 0x4c17,
+ 0x8df3, 0x0e4b,
+ 0x8df4, 0x4c1a,
+ 0x8df5, 0x086c,
+ 0x8df6, 0x4c1b,
+ 0x8df7, 0x1d2a,
+ 0x8df9, 0x1d2d,
+ 0x8dfa, 0x0624,
+ 0x8dfb, 0x1d2e,
+ 0x8dfc, 0x4c1c,
+ 0x8dfd, 0x1d31,
+ 0x8dfe, 0x4c1d,
+ 0x8e00, 0x4c1f,
+ 0x8e05, 0x1d19,
+ 0x8e06, 0x4c24,
+ 0x8e09, 0x1d30,
+ 0x8e0a, 0x10a0,
+ 0x8e0b, 0x4c27,
+ 0x8e0c, 0x0511,
+ 0x8e0d, 0x4c28,
+ 0x8e0f, 0x0df7,
+ 0x8e10, 0x1f94,
+ 0x8e11, 0x4c2a,
+ 0x8e14, 0x1d32,
+ 0x8e15, 0x4c2d,
+ 0x8e1d, 0x1d33,
+ 0x8e1e, 0x0910,
+ 0x8e1f, 0x1d34,
+ 0x8e20, 0x4c35,
+ 0x8e22, 0x0e32,
+ 0x8e23, 0x1d37,
+ 0x8e24, 0x4c37,
+ 0x8e29, 0x048f,
+ 0x8e2a, 0x1236,
+ 0x8e2b, 0x4c3c,
+ 0x8e2c, 0x1d35,
+ 0x8e2d, 0x4c3d,
+ 0x8e2e, 0x1d36,
+ 0x8e2f, 0x1d38,
+ 0x8e30, 0x4c3e,
+ 0x8e31, 0x1d3e,
+ 0x8e32, 0x4c3f,
+ 0x8e34, 0x2230,
+ 0x8e35, 0x1d3c,
+ 0x8e36, 0x4c41,
+ 0x8e39, 0x1d3b,
+ 0x8e3a, 0x1d39,
+ 0x8e3b, 0x4c44,
+ 0x8e3d, 0x1d3d,
+ 0x8e3e, 0x4c46,
+ 0x8e40, 0x1d3a,
+ 0x8e41, 0x1d40,
+ 0x8e43, 0x4c48,
+ 0x8e44, 0x0e36,
+ 0x8e45, 0x4c49,
+ 0x8e47, 0x173b,
+ 0x8e48, 0x0599,
+ 0x8e49, 0x1d3f,
+ 0x8e4a, 0x1d44,
+ 0x8e4b, 0x0df6,
+ 0x8e4c, 0x25fd,
+ 0x8e4d, 0x4c4b,
+ 0x8e51, 0x1d42,
+ 0x8e53, 0x4c4f,
+ 0x8e55, 0x2600,
+ 0x8e56, 0x4c51,
+ 0x8e59, 0x1d1a,
+ 0x8e5a, 0x4c54,
+ 0x8e63, 0x2606,
+ 0x8e64, 0x4c5d,
+ 0x8e66, 0x042d,
+ 0x8e67, 0x4c5f,
+ 0x8e69, 0x1d1b,
+ 0x8e6a, 0x4c61,
+ 0x8e6c, 0x05a6,
+ 0x8e6d, 0x04ab,
+ 0x8e6e, 0x4c63,
+ 0x8e6f, 0x1d48,
+ 0x8e70, 0x1d45,
+ 0x8e71, 0x4c64,
+ 0x8e72, 0x0616,
+ 0x8e73, 0x4c65,
+ 0x8e74, 0x1d49,
+ 0x8e75, 0x4c66,
+ 0x8e76, 0x1d46,
+ 0x8e77, 0x4c67,
+ 0x8e7a, 0x25ff,
+ 0x8e7b, 0x4c6a,
+ 0x8e7c, 0x1d47,
+ 0x8e7d, 0x4c6b,
+ 0x8e7f, 0x055d,
+ 0x8e80, 0x4c6d,
+ 0x8e81, 0x112d,
+ 0x8e82, 0x4c6e,
+ 0x8e85, 0x1d4a,
+ 0x8e86, 0x4c71,
+ 0x8e87, 0x051e,
+ 0x8e88, 0x4c72,
+ 0x8e89, 0x25fc,
+ 0x8e8a, 0x1e8c,
+ 0x8e8b, 0x2602,
+ 0x8e8c, 0x4c73,
+ 0x8e8d, 0x224d,
+ 0x8e8e, 0x4c74,
+ 0x8e8f, 0x1d4b,
+ 0x8e90, 0x1d4d,
+ 0x8e91, 0x2604,
+ 0x8e92, 0x25fe,
+ 0x8e93, 0x2603,
+ 0x8e94, 0x1d4c,
+ 0x8e95, 0x4c75,
+ 0x8e9a, 0x2601,
+ 0x8e9b, 0x4c7a,
+ 0x8e9c, 0x1d4e,
+ 0x8e9d, 0x4c7b,
+ 0x8e9e, 0x1d4f,
+ 0x8e9f, 0x4c7c,
+ 0x8ea1, 0x2605,
+ 0x8ea2, 0x4c7e,
+ 0x8ea5, 0x1ea3,
+ 0x8ea6, 0x2608,
+ 0x8ea7, 0x4c81,
+ 0x8eaa, 0x2607,
+ 0x8eab, 0x0d26,
+ 0x8eac, 0x0703,
+ 0x8ead, 0x4c84,
+ 0x8eaf, 0x0c78,
+ 0x8eb0, 0x4c86,
+ 0x8eb2, 0x0622,
+ 0x8eb3, 0x4c88,
+ 0x8eba, 0x0e1c,
+ 0x8ebb, 0x4c8f,
+ 0x8ec0, 0x20f0,
+ 0x8ec1, 0x4c94,
+ 0x8eca, 0x1e7b,
+ 0x8ecb, 0x2267,
+ 0x8ecc, 0x1f36,
+ 0x8ecd, 0x1fd6,
+ 0x8ece, 0x18f8,
+ 0x8ecf, 0x4c9d,
+ 0x8ed2, 0x21e0,
+ 0x8ed3, 0x4ca0,
+ 0x8ed4, 0x248c,
+ 0x8ed5, 0x4ca1,
+ 0x8edb, 0x248d,
+ 0x8edc, 0x4ca7,
+ 0x8edf, 0x2102,
+ 0x8ee0, 0x4caa,
+ 0x8ee4, 0x2494,
+ 0x8ee5, 0x4cae,
+ 0x8eeb, 0x2493,
+ 0x8eec, 0x4cb4,
+ 0x8ef2, 0x248e,
+ 0x8ef3, 0x4cba,
+ 0x8ef8, 0x2299,
+ 0x8ef9, 0x2491,
+ 0x8efa, 0x2496,
+ 0x8efb, 0x248f,
+ 0x8efc, 0x2492,
+ 0x8efd, 0x4cbf,
+ 0x8efe, 0x2497,
+ 0x8eff, 0x4cc0,
+ 0x8f00, 0x4cc1,
+ 0x8f03, 0x1fb1,
+ 0x8f04, 0x4cc4,
+ 0x8f05, 0x249a,
+ 0x8f06, 0x4cc5,
+ 0x8f07, 0x2499,
+ 0x8f08, 0x4cc6,
+ 0x8f09, 0x2258,
+ 0x8f0a, 0x2498,
+ 0x8f0b, 0x4cc7,
+ 0x8f12, 0x249b,
+ 0x8f13, 0x4cce,
+ 0x8f14, 0x1f09,
+ 0x8f15, 0x20e6,
+ 0x8f16, 0x4ccf,
+ 0x8f1b, 0x2026,
+ 0x8f1c, 0x249f,
+ 0x8f1d, 0x1f59,
+ 0x8f1e, 0x249d,
+ 0x8f20, 0x4cd4,
+ 0x8f25, 0x1f3b,
+ 0x8f26, 0x249c,
+ 0x8f27, 0x4cd9,
+ 0x8f29, 0x1e3a,
+ 0x8f2a, 0x205b,
+ 0x8f2b, 0x4cdb,
+ 0x8f2f, 0x1f70,
+ 0x8f30, 0x4cdf,
+ 0x8f33, 0x24a0,
+ 0x8f34, 0x4ce2,
+ 0x8f38, 0x213b,
+ 0x8f39, 0x4ce6,
+ 0x8f3b, 0x1f07,
+ 0x8f3c, 0x4ce8,
+ 0x8f3e, 0x2270,
+ 0x8f3f, 0x2237,
+ 0x8f40, 0x4cea,
+ 0x8f42, 0x24d2,
+ 0x8f43, 0x4cec,
+ 0x8f44, 0x21b3,
+ 0x8f45, 0x2245,
+ 0x8f46, 0x24a1,
+ 0x8f47, 0x4ced,
+ 0x8f49, 0x22a8,
+ 0x8f4a, 0x4cef,
+ 0x8f4d, 0x227c,
+ 0x8f4e, 0x1fb0,
+ 0x8f4f, 0x4cf2,
+ 0x8f54, 0x24a2,
+ 0x8f55, 0x4cf7,
+ 0x8f5f, 0x1f46,
+ 0x8f60, 0x4d01,
+ 0x8f61, 0x2380,
+ 0x8f62, 0x2495,
+ 0x8f63, 0x4d02,
+ 0x8f64, 0x2490,
+ 0x8f65, 0x4d03,
+ 0x8f66, 0x04da,
+ 0x8f67, 0x1141,
+ 0x8f68, 0x0745,
+ 0x8f69, 0x0fc4,
+ 0x8f6a, 0x4d04,
+ 0x8f6b, 0x18e1,
+ 0x8f6c, 0x1207,
+ 0x8f6d, 0x18e2,
+ 0x8f6e, 0x0a7d,
+ 0x8f6f, 0x0cc8,
+ 0x8f70, 0x079b,
+ 0x8f71, 0x18e3,
+ 0x8f74, 0x11e0,
+ 0x8f75, 0x18e6,
+ 0x8f77, 0x18e9,
+ 0x8f78, 0x18e8,
+ 0x8f79, 0x18ea,
+ 0x8f7b, 0x0c5e,
+ 0x8f7c, 0x18ec,
+ 0x8f7d, 0x111b,
+ 0x8f7e, 0x18ed,
+ 0x8f7f, 0x089f,
+ 0x8f80, 0x4d05,
+ 0x8f81, 0x18ee,
+ 0x8f83, 0x08a0,
+ 0x8f84, 0x18f0,
+ 0x8f85, 0x06a3,
+ 0x8f86, 0x0a07,
+ 0x8f87, 0x18f1,
+ 0x8f88, 0x041b,
+ 0x8f89, 0x07e9,
+ 0x8f8a, 0x074e,
+ 0x8f8b, 0x18f2,
+ 0x8f8c, 0x4d06,
+ 0x8f8d, 0x18f3,
+ 0x8f90, 0x0695,
+ 0x8f91, 0x0820,
+ 0x8f92, 0x4d07,
+ 0x8f93, 0x0d7b,
+ 0x8f94, 0x1574,
+ 0x8f95, 0x10f2,
+ 0x8f96, 0x0f2a,
+ 0x8f97, 0x1158,
+ 0x8f98, 0x18f6,
+ 0x8f99, 0x117f,
+ 0x8f9a, 0x18f7,
+ 0x8f9b, 0x0f8c,
+ 0x8f9c, 0x0715,
+ 0x8f9d, 0x4d08,
+ 0x8f9e, 0x054a,
+ 0x8f9f, 0x0442,
+ 0x8fa0, 0x4d09,
+ 0x8fa3, 0x099c,
+ 0x8fa4, 0x4d0c,
+ 0x8fa6, 0x1e30,
+ 0x8fa7, 0x4d0e,
+ 0x8fa8, 0x044f,
+ 0x8faa, 0x4d0f,
+ 0x8fab, 0x0451,
+ 0x8fac, 0x4d10,
+ 0x8fad, 0x1e9d,
+ 0x8fae, 0x1e4b,
+ 0x8faf, 0x1e4a,
+ 0x8fb0, 0x04e2,
+ 0x8fb1, 0x0cc3,
+ 0x8fb2, 0x20aa,
+ 0x8fb3, 0x4d11,
+ 0x8fb6, 0x173d,
+ 0x8fb7, 0x4d14,
+ 0x8fb9, 0x0448,
+ 0x8fba, 0x4d16,
+ 0x8fbd, 0x0a12,
+ 0x8fbe, 0x0572,
+ 0x8fbf, 0x4d19,
+ 0x8fc1, 0x0c25,
+ 0x8fc2, 0x10bd,
+ 0x8fc3, 0x4d1b,
+ 0x8fc4, 0x0c18,
+ 0x8fc5, 0x0fe1,
+ 0x8fc6, 0x4d1c,
+ 0x8fc7, 0x0756,
+ 0x8fc8, 0x0a9c,
+ 0x8fc9, 0x4d1d,
+ 0x8fce, 0x1092,
+ 0x8fcf, 0x4d22,
+ 0x8fd0, 0x110e,
+ 0x8fd1, 0x08cd,
+ 0x8fd2, 0x4d23,
+ 0x8fd3, 0x173e,
+ 0x8fd4, 0x0652,
+ 0x8fd5, 0x173f,
+ 0x8fd6, 0x4d24,
+ 0x8fd8, 0x07ce,
+ 0x8fd9, 0x1183,
+ 0x8fda, 0x4d26,
+ 0x8fdb, 0x08c9,
+ 0x8fdc, 0x10f9,
+ 0x8fdd, 0x0eb4,
+ 0x8fde, 0x09f5,
+ 0x8fdf, 0x04fe,
+ 0x8fe0, 0x4d27,
+ 0x8fe2, 0x0e49,
+ 0x8fe3, 0x4d29,
+ 0x8fe4, 0x1742,
+ 0x8fe5, 0x1740,
+ 0x8fe6, 0x1744,
+ 0x8fe7, 0x4d2a,
+ 0x8fe8, 0x1746,
+ 0x8fe9, 0x1743,
+ 0x8fea, 0x05b0,
+ 0x8feb, 0x0be7,
+ 0x8fec, 0x4d2b,
+ 0x8fed, 0x05dd,
+ 0x8fee, 0x1741,
+ 0x8fef, 0x4d2c,
+ 0x8ff0, 0x0d8d,
+ 0x8ff1, 0x4d2d,
+ 0x8ff3, 0x1745,
+ 0x8ff4, 0x267b,
+ 0x8ff5, 0x4d2f,
+ 0x8ff7, 0x0ad9,
+ 0x8ff8, 0x042e,
+ 0x8ff9, 0x0816,
+ 0x8ffa, 0x4d31,
+ 0x8ffd, 0x1214,
+ 0x8ffe, 0x4d34,
+ 0x9000, 0x0e7c,
+ 0x9001, 0x0dc2,
+ 0x9002, 0x0d61,
+ 0x9003, 0x0e26,
+ 0x9004, 0x1748,
+ 0x9005, 0x1747,
+ 0x9006, 0x0b49,
+ 0x9007, 0x4d36,
+ 0x9009, 0x0fca,
+ 0x900a, 0x0fe0,
+ 0x900b, 0x1749,
+ 0x900c, 0x4d38,
+ 0x900d, 0x174c,
+ 0x900e, 0x4d39,
+ 0x900f, 0x0e69,
+ 0x9010, 0x11ef,
+ 0x9011, 0x174b,
+ 0x9012, 0x05be,
+ 0x9013, 0x4d3a,
+ 0x9014, 0x0e6f,
+ 0x9015, 0x23f2,
+ 0x9016, 0x174d,
+ 0x9017, 0x05f9,
+ 0x9018, 0x4d3b,
+ 0x9019, 0x227e,
+ 0x901a, 0x0e59,
+ 0x901b, 0x073d,
+ 0x901c, 0x4d3c,
+ 0x901d, 0x0d5c,
+ 0x901e, 0x04f6,
+ 0x901f, 0x0dce,
+ 0x9020, 0x112f,
+ 0x9021, 0x174e,
+ 0x9022, 0x0687,
+ 0x9023, 0x2019,
+ 0x9024, 0x4d3d,
+ 0x9026, 0x174a,
+ 0x9027, 0x4d3f,
+ 0x902d, 0x1751,
+ 0x902e, 0x0581,
+ 0x902f, 0x1752,
+ 0x9030, 0x4d45,
+ 0x9032, 0x1fbb,
+ 0x9033, 0x4d47,
+ 0x9035, 0x174f,
+ 0x9037, 0x4d49,
+ 0x9038, 0x1064,
+ 0x9039, 0x4d4a,
+ 0x903b, 0x0a86,
+ 0x903c, 0x042f,
+ 0x903d, 0x4d4c,
+ 0x903e, 0x10c7,
+ 0x903f, 0x4d4d,
+ 0x9041, 0x061c,
+ 0x9042, 0x0de1,
+ 0x9043, 0x4d4f,
+ 0x9044, 0x1753,
+ 0x9045, 0x4d50,
+ 0x9047, 0x10db,
+ 0x9048, 0x4d52,
+ 0x904b, 0x2253,
+ 0x904c, 0x4d55,
+ 0x904d, 0x0452,
+ 0x904e, 0x1f3e,
+ 0x904f, 0x0633,
+ 0x9050, 0x1756,
+ 0x9051, 0x1754,
+ 0x9053, 0x05a1,
+ 0x9054, 0x1ea6,
+ 0x9055, 0x218e,
+ 0x9056, 0x4d56,
+ 0x9057, 0x104c,
+ 0x9058, 0x1758,
+ 0x9059, 0x4d57,
+ 0x905b, 0x175a,
+ 0x905c, 0x21ec,
+ 0x905d, 0x4d59,
+ 0x905e, 0x1ebe,
+ 0x905f, 0x4d5a,
+ 0x9060, 0x224a,
+ 0x9061, 0x4d5b,
+ 0x9062, 0x1759,
+ 0x9063, 0x0c2f,
+ 0x9064, 0x4d5c,
+ 0x9065, 0x102a,
+ 0x9066, 0x4d5d,
+ 0x9068, 0x1757,
+ 0x9069, 0x2133,
+ 0x906a, 0x4d5f,
+ 0x906d, 0x1125,
+ 0x906e, 0x117b,
+ 0x906f, 0x4d62,
+ 0x9072, 0x1e84,
+ 0x9073, 0x4d65,
+ 0x9074, 0x175c,
+ 0x9075, 0x124e,
+ 0x9076, 0x4d66,
+ 0x9077, 0x20cf,
+ 0x9078, 0x21e2,
+ 0x9079, 0x4d67,
+ 0x907a, 0x220f,
+ 0x907b, 0x4d68,
+ 0x907c, 0x2029,
+ 0x907d, 0x175d,
+ 0x907e, 0x4d69,
+ 0x907f, 0x0445,
+ 0x9080, 0x1024,
+ 0x9081, 0x2073,
+ 0x9082, 0x175e,
+ 0x9083, 0x1760,
+ 0x9084, 0x1f55,
+ 0x9085, 0x4d6a,
+ 0x9087, 0x23f1,
+ 0x9088, 0x175f,
+ 0x9089, 0x4d6c,
+ 0x908a, 0x1e46,
+ 0x908b, 0x1761,
+ 0x908c, 0x4d6d,
+ 0x908f, 0x2063,
+ 0x9090, 0x23f3,
+ 0x9091, 0x105f,
+ 0x9092, 0x4d70,
+ 0x9093, 0x05ac,
+ 0x9094, 0x4d71,
+ 0x9095, 0x1817,
+ 0x9096, 0x4d72,
+ 0x9097, 0x1367,
+ 0x9098, 0x4d73,
+ 0x9099, 0x136a,
+ 0x909a, 0x4d74,
+ 0x909b, 0x1368,
+ 0x909c, 0x4d75,
+ 0x909d, 0x1369,
+ 0x909e, 0x4d76,
+ 0x90a1, 0x136c,
+ 0x90a2, 0x0f9a,
+ 0x90a3, 0x0b2a,
+ 0x90a4, 0x4d79,
+ 0x90a6, 0x03f9,
+ 0x90a7, 0x4d7b,
+ 0x90aa, 0x0f7b,
+ 0x90ab, 0x4d7e,
+ 0x90ac, 0x136b,
+ 0x90ad, 0x4d7f,
+ 0x90ae, 0x10af,
+ 0x90af, 0x0761,
+ 0x90b0, 0x1372,
+ 0x90b1, 0x0c6e,
+ 0x90b2, 0x4d80,
+ 0x90b3, 0x136e,
+ 0x90b4, 0x136d,
+ 0x90b5, 0x0d14,
+ 0x90b6, 0x136f,
+ 0x90b7, 0x4d81,
+ 0x90b8, 0x1371,
+ 0x90b9, 0x123b,
+ 0x90ba, 0x1370,
+ 0x90bb, 0x0a23,
+ 0x90bc, 0x4d82,
+ 0x90be, 0x1375,
+ 0x90bf, 0x4d84,
+ 0x90c1, 0x10d9,
+ 0x90c2, 0x4d86,
+ 0x90c4, 0x1377,
+ 0x90c5, 0x1374,
+ 0x90c6, 0x4d88,
+ 0x90c7, 0x1378,
+ 0x90c8, 0x4d89,
+ 0x90ca, 0x088d,
+ 0x90cb, 0x4d8b,
+ 0x90ce, 0x09b4,
+ 0x90cf, 0x1373,
+ 0x90d0, 0x1376,
+ 0x90d1, 0x11a2,
+ 0x90d2, 0x4d8e,
+ 0x90d3, 0x1379,
+ 0x90d4, 0x4d8f,
+ 0x90d7, 0x137d,
+ 0x90d8, 0x4d92,
+ 0x90db, 0x137e,
+ 0x90dc, 0x137c,
+ 0x90dd, 0x0779,
+ 0x90de, 0x4d95,
+ 0x90df, 0x231e,
+ 0x90e0, 0x4d96,
+ 0x90e1, 0x0931,
+ 0x90e2, 0x137b,
+ 0x90e3, 0x4d97,
+ 0x90e6, 0x137a,
+ 0x90e7, 0x110a,
+ 0x90e8, 0x0486,
+ 0x90e9, 0x4d9a,
+ 0x90eb, 0x137f,
+ 0x90ec, 0x4d9c,
+ 0x90ed, 0x0752,
+ 0x90ee, 0x4d9d,
+ 0x90ef, 0x1380,
+ 0x90f0, 0x4d9e,
+ 0x90f4, 0x04e0,
+ 0x90f5, 0x2233,
+ 0x90f6, 0x4da2,
+ 0x90f8, 0x0587,
+ 0x90f9, 0x4da4,
+ 0x90fd, 0x05fb,
+ 0x90fe, 0x1381,
+ 0x90ff, 0x4da8,
+ 0x9100, 0x4da9,
+ 0x9102, 0x0634,
+ 0x9103, 0x4dab,
+ 0x9104, 0x1382,
+ 0x9105, 0x4dac,
+ 0x9106, 0x2320,
+ 0x9107, 0x4dad,
+ 0x9109, 0x21c7,
+ 0x910a, 0x4daf,
+ 0x9112, 0x22bc,
+ 0x9113, 0x4db7,
+ 0x9114, 0x231c,
+ 0x9115, 0x4db8,
+ 0x9116, 0x2251,
+ 0x9117, 0x4db9,
+ 0x9119, 0x0432,
+ 0x911a, 0x4dbb,
+ 0x911e, 0x1384,
+ 0x911f, 0x4dbf,
+ 0x9122, 0x1383,
+ 0x9123, 0x1385,
+ 0x9124, 0x4dc2,
+ 0x9127, 0x1ebb,
+ 0x9128, 0x4dc5,
+ 0x912d, 0x2287,
+ 0x912e, 0x4dca,
+ 0x912f, 0x1387,
+ 0x9130, 0x202d,
+ 0x9131, 0x1386,
+ 0x9132, 0x1eab,
+ 0x9133, 0x4dcb,
+ 0x9134, 0x231d,
+ 0x9135, 0x4dcc,
+ 0x9136, 0x231f,
+ 0x9137, 0x4dcd,
+ 0x9139, 0x1388,
+ 0x913a, 0x231b,
+ 0x913b, 0x4dcf,
+ 0x9143, 0x1389,
+ 0x9144, 0x4dd7,
+ 0x9146, 0x138a,
+ 0x9147, 0x4dd9,
+ 0x9148, 0x2321,
+ 0x9149, 0x10b4,
+ 0x914a, 0x1cf8,
+ 0x914b, 0x0c72,
+ 0x914c, 0x1220,
+ 0x914d, 0x0ba5,
+ 0x914e, 0x1cfa,
+ 0x9150, 0x1cf9,
+ 0x9151, 0x4dda,
+ 0x9152, 0x08f5,
+ 0x9153, 0x4ddb,
+ 0x9157, 0x0fba,
+ 0x9158, 0x4ddf,
+ 0x915a, 0x0670,
+ 0x915b, 0x4de1,
+ 0x915d, 0x1110,
+ 0x915e, 0x0dfd,
+ 0x915f, 0x4de3,
+ 0x9161, 0x1cfe,
+ 0x9162, 0x1cfd,
+ 0x9163, 0x075f,
+ 0x9164, 0x1cfc,
+ 0x9165, 0x0dcb,
+ 0x9166, 0x4de5,
+ 0x9169, 0x1d00,
+ 0x916a, 0x09bd,
+ 0x916b, 0x4de8,
+ 0x916c, 0x050f,
+ 0x916d, 0x4de9,
+ 0x916e, 0x0e5b,
+ 0x916f, 0x1d01,
+ 0x9170, 0x1cff,
+ 0x9171, 0x0885,
+ 0x9172, 0x1d04,
+ 0x9173, 0x4dea,
+ 0x9174, 0x1d05,
+ 0x9175, 0x089e,
+ 0x9176, 0x0abd,
+ 0x9177, 0x096e,
+ 0x9178, 0x0dd6,
+ 0x9179, 0x1d06,
+ 0x917a, 0x4deb,
+ 0x917d, 0x1d02,
+ 0x917f, 0x0b53,
+ 0x9180, 0x4dee,
+ 0x9185, 0x1d08,
+ 0x9186, 0x4df3,
+ 0x9187, 0x053f,
+ 0x9188, 0x4df4,
+ 0x9189, 0x124a,
+ 0x918a, 0x4df5,
+ 0x918b, 0x055a,
+ 0x918c, 0x1d07,
+ 0x918d, 0x1d0a,
+ 0x918e, 0x4df6,
+ 0x9190, 0x1d09,
+ 0x9191, 0x1d0b,
+ 0x9192, 0x0f9c,
+ 0x9193, 0x4df8,
+ 0x9196, 0x2255,
+ 0x9197, 0x4dfb,
+ 0x919a, 0x0ad6,
+ 0x919b, 0x0c84,
+ 0x919c, 0x1e8f,
+ 0x919d, 0x4dfe,
+ 0x91a2, 0x1d0c,
+ 0x91a4, 0x4e03,
+ 0x91aa, 0x1d0e,
+ 0x91ab, 0x220c,
+ 0x91ac, 0x1fa4,
+ 0x91ad, 0x1d0f,
+ 0x91b0, 0x4e09,
+ 0x91b4, 0x1d13,
+ 0x91b5, 0x1d12,
+ 0x91b6, 0x4e0d,
+ 0x91ba, 0x1d14,
+ 0x91bb, 0x4e11,
+ 0x91c0, 0x209b,
+ 0x91c1, 0x21d8,
+ 0x91c2, 0x4e16,
+ 0x91c3, 0x25fa,
+ 0x91c4, 0x4e17,
+ 0x91c5, 0x25f9,
+ 0x91c6, 0x4e18,
+ 0x91c7, 0x0490,
+ 0x91c8, 0x4e19,
+ 0x91c9, 0x10b9,
+ 0x91ca, 0x0d64,
+ 0x91cb, 0x2134,
+ 0x91cc, 0x09da,
+ 0x91cd, 0x11d7,
+ 0x91ce, 0x1037,
+ 0x91cf, 0x0a08,
+ 0x91d0, 0x4e1a,
+ 0x91d1, 0x08c1,
+ 0x91d2, 0x24f3,
+ 0x91d5, 0x24f8,
+ 0x91d6, 0x4e1b,
+ 0x91d7, 0x24f7,
+ 0x91d8, 0x1ec8,
+ 0x91d9, 0x24f6,
+ 0x91da, 0x4e1c,
+ 0x91dc, 0x06a5,
+ 0x91dd, 0x2280,
+ 0x91de, 0x4e1e,
+ 0x91e3, 0x1ec5,
+ 0x91e4, 0x24fb,
+ 0x91e5, 0x4e23,
+ 0x91e7, 0x24fa,
+ 0x91e8, 0x4e25,
+ 0x91e9, 0x1eed,
+ 0x91ea, 0x4e26,
+ 0x91f5, 0x24fd,
+ 0x91f6, 0x4e31,
+ 0x91f7, 0x24f9,
+ 0x91f8, 0x4e32,
+ 0x91f9, 0x24fe,
+ 0x91fa, 0x20cd,
+ 0x91fb, 0x4e33,
+ 0x9200, 0x2508,
+ 0x9201, 0x2504,
+ 0x9202, 0x4e38,
+ 0x9204, 0x2506,
+ 0x9205, 0x4e3a,
+ 0x9208, 0x24ff,
+ 0x9209, 0x2090,
+ 0x920a, 0x4e3d,
+ 0x920d, 0x1edd,
+ 0x920e, 0x1f25,
+ 0x920f, 0x4e40,
+ 0x9210, 0x2503,
+ 0x9211, 0x2502,
+ 0x9212, 0x4e41,
+ 0x9214, 0x1e7a,
+ 0x9215, 0x20a6,
+ 0x9216, 0x4e43,
+ 0x921e, 0x1fd5,
+ 0x921f, 0x4e4b,
+ 0x9223, 0x1f11,
+ 0x9224, 0x4e4f,
+ 0x9225, 0x2507,
+ 0x9226, 0x2500,
+ 0x9227, 0x2505,
+ 0x9228, 0x4e50,
+ 0x922e, 0x2519,
+ 0x922f, 0x4e56,
+ 0x9230, 0x2515,
+ 0x9231, 0x4e57,
+ 0x9233, 0x250c,
+ 0x9234, 0x2031,
+ 0x9235, 0x4e59,
+ 0x9237, 0x250b,
+ 0x9238, 0x250f,
+ 0x9239, 0x251a,
+ 0x923a, 0x2509,
+ 0x923b, 0x4e5b,
+ 0x923d, 0x250e,
+ 0x923e, 0x2234,
+ 0x923f, 0x2513,
+ 0x9240, 0x1f80,
+ 0x9241, 0x4e5d,
+ 0x9245, 0x2501,
+ 0x9246, 0x4e61,
+ 0x9248, 0x2517,
+ 0x9249, 0x2516,
+ 0x924a, 0x4e63,
+ 0x924d, 0x2518,
+ 0x924e, 0x4e66,
+ 0x9251, 0x1e56,
+ 0x9252, 0x4e69,
+ 0x9255, 0x250d,
+ 0x9256, 0x4e6c,
+ 0x9257, 0x20d3,
+ 0x9258, 0x4e6d,
+ 0x925a, 0x207a,
+ 0x925b, 0x20ce,
+ 0x925c, 0x4e6f,
+ 0x925e, 0x2510,
+ 0x925f, 0x4e71,
+ 0x9262, 0x1e55,
+ 0x9263, 0x4e74,
+ 0x9266, 0x250a,
+ 0x9267, 0x4e77,
+ 0x926c, 0x2511,
+ 0x926e, 0x4e7c,
+ 0x9274, 0x086b,
+ 0x9275, 0x4e82,
+ 0x9278, 0x1faa,
+ 0x9279, 0x4e85,
+ 0x927a, 0x251e,
+ 0x927b, 0x1f1f,
+ 0x927c, 0x4e86,
+ 0x927f, 0x252d,
+ 0x9280, 0x221d,
+ 0x9281, 0x4e89,
+ 0x9283, 0x2532,
+ 0x9284, 0x4e8b,
+ 0x9285, 0x217b,
+ 0x9286, 0x4e8c,
+ 0x928e, 0x1d80,
+ 0x928f, 0x4e94,
+ 0x9291, 0x21af,
+ 0x9292, 0x4e96,
+ 0x9293, 0x252c,
+ 0x9294, 0x4e97,
+ 0x9296, 0x2528,
+ 0x9297, 0x4e99,
+ 0x9298, 0x208c,
+ 0x9299, 0x4e9a,
+ 0x929a, 0x252f,
+ 0x929b, 0x4e9b,
+ 0x929c, 0x21bc,
+ 0x929d, 0x4e9c,
+ 0x92a0, 0x251d,
+ 0x92a1, 0x4e9f,
+ 0x92a3, 0x2535,
+ 0x92a4, 0x4ea1,
+ 0x92a5, 0x220d,
+ 0x92a6, 0x2526,
+ 0x92a7, 0x4ea2,
+ 0x92a8, 0x2534,
+ 0x92a9, 0x252a,
+ 0x92aa, 0x251f,
+ 0x92ab, 0x2531,
+ 0x92ac, 0x251c,
+ 0x92ad, 0x4ea3,
+ 0x92ae, 0x1d81,
+ 0x92af, 0x4ea4,
+ 0x92b1, 0x2525,
+ 0x92b2, 0x4ea6,
+ 0x92b7, 0x21cd,
+ 0x92b8, 0x4eab,
+ 0x92b9, 0x21da,
+ 0x92ba, 0x4eac,
+ 0x92bb, 0x2172,
+ 0x92bc, 0x253e,
+ 0x92bd, 0x4ead,
+ 0x92c1, 0x204f,
+ 0x92c2, 0x4eb1,
+ 0x92c3, 0x2543,
+ 0x92c4, 0x4eb2,
+ 0x92c5, 0x21d7,
+ 0x92c6, 0x4eb3,
+ 0x92c7, 0x1e3c,
+ 0x92c8, 0x1d82,
+ 0x92c9, 0x4eb4,
+ 0x92cc, 0x2529,
+ 0x92cd, 0x4eb7,
+ 0x92cf, 0x2521,
+ 0x92d0, 0x4eb9,
+ 0x92d2, 0x1eff,
+ 0x92d3, 0x4ebb,
+ 0x92dd, 0x253f,
+ 0x92de, 0x4ec5,
+ 0x92df, 0x2544,
+ 0x92e0, 0x4ec6,
+ 0x92e3, 0x2523,
+ 0x92e4, 0x1e90,
+ 0x92e5, 0x253a,
+ 0x92e6, 0x2545,
+ 0x92e7, 0x4ec9,
+ 0x92e8, 0x253d,
+ 0x92e9, 0x4eca,
+ 0x92ea, 0x20c1,
+ 0x92eb, 0x4ecb,
+ 0x92ed, 0x2103,
+ 0x92ee, 0x2520,
+ 0x92ef, 0x253c,
+ 0x92f0, 0x253b,
+ 0x92f1, 0x2538,
+ 0x92f2, 0x4ecd,
+ 0x92f6, 0x2540,
+ 0x92f7, 0x4ed1,
+ 0x92f8, 0x1fcd,
+ 0x92f9, 0x4ed2,
+ 0x92fc, 0x1f18,
+ 0x92fd, 0x4ed5,
+ 0x9300, 0x4ed8,
+ 0x9301, 0x254b,
+ 0x9302, 0x4ed9,
+ 0x9306, 0x2547,
+ 0x9307, 0x254f,
+ 0x9309, 0x4edd,
+ 0x9310, 0x22b0,
+ 0x9311, 0x4ee4,
+ 0x9312, 0x2546,
+ 0x9313, 0x4ee5,
+ 0x9315, 0x254c,
+ 0x9316, 0x4ee7,
+ 0x9318, 0x1e9a,
+ 0x9319, 0x2552,
+ 0x931a, 0x2530,
+ 0x931b, 0x2549,
+ 0x931c, 0x4ee9,
+ 0x931f, 0x2551,
+ 0x9320, 0x1eca,
+ 0x9321, 0x4eec,
+ 0x9322, 0x20d2,
+ 0x9323, 0x4eed,
+ 0x9326, 0x1fb8,
+ 0x9327, 0x4ef0,
+ 0x9328, 0x2079,
+ 0x9329, 0x4ef1,
+ 0x932b, 0x21ab,
+ 0x932c, 0x4ef3,
+ 0x932e, 0x254d,
+ 0x932f, 0x1ea5,
+ 0x9330, 0x4ef5,
+ 0x9332, 0x204c,
+ 0x9333, 0x2080,
+ 0x9334, 0x4ef7,
+ 0x9336, 0x266d,
+ 0x9337, 0x4ef9,
+ 0x9338, 0x2537,
+ 0x9339, 0x4efa,
+ 0x933e, 0x1d83,
+ 0x933f, 0x4eff,
+ 0x9340, 0x254a,
+ 0x9341, 0x21b8,
+ 0x9342, 0x4f00,
+ 0x9343, 0x254e,
+ 0x9344, 0x4f01,
+ 0x9346, 0x24fc,
+ 0x9347, 0x2554,
+ 0x9348, 0x4f03,
+ 0x934b, 0x1f3c,
+ 0x934c, 0x4f06,
+ 0x934d, 0x1ed5,
+ 0x934e, 0x4f07,
+ 0x9354, 0x2556,
+ 0x9355, 0x4f0d,
+ 0x9358, 0x2268,
+ 0x9359, 0x4f10,
+ 0x935b, 0x1ed6,
+ 0x935c, 0x4f12,
+ 0x9364, 0x2557,
+ 0x9365, 0x2553,
+ 0x9366, 0x4f1a,
+ 0x9369, 0x2548,
+ 0x936a, 0x1d84,
+ 0x936b, 0x4f1d,
+ 0x936c, 0x20dc,
+ 0x936d, 0x4f1e,
+ 0x9370, 0x2559,
+ 0x9371, 0x4f21,
+ 0x9375, 0x1f97,
+ 0x9376, 0x2555,
+ 0x9377, 0x4f25,
+ 0x937a, 0x227d,
+ 0x937b, 0x4f28,
+ 0x937e, 0x257e,
+ 0x937f, 0x4f2b,
+ 0x9382, 0x207c,
+ 0x9383, 0x4f2e,
+ 0x9384, 0x255a,
+ 0x9385, 0x4f2f,
+ 0x9387, 0x255e,
+ 0x9388, 0x4f31,
+ 0x938a, 0x1e34,
+ 0x938b, 0x4f33,
+ 0x938f, 0x1d86,
+ 0x9390, 0x4f37,
+ 0x9396, 0x215e,
+ 0x9397, 0x4f3d,
+ 0x9398, 0x2560,
+ 0x9399, 0x4f3e,
+ 0x93a2, 0x21a2,
+ 0x93a3, 0x2354,
+ 0x93a4, 0x4f47,
+ 0x93a6, 0x2563,
+ 0x93a7, 0x2527,
+ 0x93a8, 0x4f49,
+ 0x93a9, 0x252e,
+ 0x93aa, 0x2558,
+ 0x93ab, 0x4f4a,
+ 0x93ac, 0x1f1b,
+ 0x93ad, 0x4f4b,
+ 0x93ae, 0x2283,
+ 0x93af, 0x4f4c,
+ 0x93b0, 0x2564,
+ 0x93b1, 0x4f4d,
+ 0x93b3, 0x20a0,
+ 0x93b4, 0x4f4f,
+ 0x93b5, 0x2565,
+ 0x93b6, 0x4f50,
+ 0x93b8, 0x2561,
+ 0x93b9, 0x4f52,
+ 0x93bf, 0x2562,
+ 0x93c0, 0x4f58,
+ 0x93c3, 0x256c,
+ 0x93c4, 0x4f5b,
+ 0x93c7, 0x256d,
+ 0x93c8, 0x2020,
+ 0x93c9, 0x4f5e,
+ 0x93ca, 0x1d85,
+ 0x93cb, 0x4f5f,
+ 0x93cc, 0x255f,
+ 0x93cd, 0x256a,
+ 0x93ce, 0x4f60,
+ 0x93d1, 0x256e,
+ 0x93d2, 0x4f63,
+ 0x93d6, 0x1e01,
+ 0x93d7, 0x2539,
+ 0x93d8, 0x255c,
+ 0x93d9, 0x4f67,
+ 0x93dc, 0x2568,
+ 0x93de, 0x256b,
+ 0x93df, 0x1e6f,
+ 0x93e0, 0x4f6a,
+ 0x93e1, 0x1fc4,
+ 0x93e2, 0x2567,
+ 0x93e3, 0x4f6b,
+ 0x93e4, 0x255b,
+ 0x93e5, 0x4f6c,
+ 0x93e8, 0x261d,
+ 0x93e9, 0x4f6f,
+ 0x93f5, 0x252b,
+ 0x93f6, 0x4f7b,
+ 0x93f7, 0x2571,
+ 0x93f8, 0x4f7c,
+ 0x93f9, 0x2577,
+ 0x93fa, 0x4f7d,
+ 0x9400, 0x4f83,
+ 0x9403, 0x2522,
+ 0x9404, 0x4f86,
+ 0x940b, 0x2533,
+ 0x940c, 0x4f8d,
+ 0x9410, 0x202a,
+ 0x9411, 0x4f91,
+ 0x9412, 0x2536,
+ 0x9413, 0x2573,
+ 0x9414, 0x256f,
+ 0x9415, 0x4f92,
+ 0x9418, 0x2293,
+ 0x9419, 0x2578,
+ 0x941a, 0x4f95,
+ 0x941d, 0x2570,
+ 0x941e, 0x4f98,
+ 0x9420, 0x2575,
+ 0x9421, 0x4f9a,
+ 0x9426, 0x2541,
+ 0x9428, 0x255d,
+ 0x9429, 0x4f9f,
+ 0x942e, 0x201a,
+ 0x942f, 0x4fa4,
+ 0x9432, 0x257a,
+ 0x9433, 0x2006,
+ 0x9434, 0x4fa7,
+ 0x9435, 0x2177,
+ 0x9436, 0x4fa8,
+ 0x9438, 0x251b,
+ 0x9439, 0x4faa,
+ 0x943a, 0x2524,
+ 0x943b, 0x4fab,
+ 0x943e, 0x1d87,
+ 0x943f, 0x257b,
+ 0x9440, 0x4fae,
+ 0x9444, 0x22a3,
+ 0x9445, 0x4fb2,
+ 0x944a, 0x2579,
+ 0x944b, 0x4fb7,
+ 0x944c, 0x2566,
+ 0x944d, 0x4fb8,
+ 0x9452, 0x1f93,
+ 0x9453, 0x4fbd,
+ 0x9454, 0x257c,
+ 0x9455, 0x4fbe,
+ 0x9460, 0x2514,
+ 0x9461, 0x4fc9,
+ 0x9463, 0x257d,
+ 0x9464, 0x4fcb,
+ 0x9465, 0x2572,
+ 0x9466, 0x4fcc,
+ 0x946b, 0x1d88,
+ 0x946c, 0x4fd1,
+ 0x946d, 0x2574,
+ 0x946e, 0x4fd2,
+ 0x9470, 0x224e,
+ 0x9471, 0x4fd4,
+ 0x9472, 0x21c6,
+ 0x9473, 0x4fd5,
+ 0x9477, 0x209f,
+ 0x9478, 0x4fd9,
+ 0x9479, 0x2576,
+ 0x947a, 0x4fda,
+ 0x947c, 0x2064,
+ 0x947d, 0x22bf,
+ 0x947e, 0x261c,
+ 0x947f, 0x225e,
+ 0x9480, 0x4fdc,
+ 0x9485, 0x1a8e,
+ 0x9488, 0x118c,
+ 0x9489, 0x05e3,
+ 0x948a, 0x1a92,
+ 0x948b, 0x1a91,
+ 0x948c, 0x1a93,
+ 0x948e, 0x0c22,
+ 0x948f, 0x1a95,
+ 0x9491, 0x4fe1,
+ 0x9492, 0x064d,
+ 0x9493, 0x05d7,
+ 0x9494, 0x1a97,
+ 0x9495, 0x1a99,
+ 0x9496, 0x4fe2,
+ 0x9497, 0x1a98,
+ 0x9498, 0x4fe3,
+ 0x9499, 0x06c1,
+ 0x949a, 0x1a9a,
+ 0x949d, 0x061a,
+ 0x949e, 0x04d3,
+ 0x949f, 0x11d2,
+ 0x94a0, 0x0b29,
+ 0x94a1, 0x041e,
+ 0x94a2, 0x06d1,
+ 0x94a3, 0x1a9d,
+ 0x94a5, 0x1102,
+ 0x94a6, 0x0c52,
+ 0x94a7, 0x092a,
+ 0x94a8, 0x0ee8,
+ 0x94a9, 0x070c,
+ 0x94aa, 0x1aa0,
+ 0x94ab, 0x1a9f,
+ 0x94ac, 0x1aa2,
+ 0x94ad, 0x1aa1,
+ 0x94ae, 0x0b66,
+ 0x94af, 0x1aa3,
+ 0x94b1, 0x0c2b,
+ 0x94b2, 0x1aa5,
+ 0x94b3, 0x0c2c,
+ 0x94b4, 0x1aa6,
+ 0x94b5, 0x046e,
+ 0x94b6, 0x1aa7,
+ 0x94bb, 0x1247,
+ 0x94bc, 0x1aac,
+ 0x94be, 0x084b,
+ 0x94bf, 0x1aae,
+ 0x94c0, 0x10b0,
+ 0x94c1, 0x0e4d,
+ 0x94c2, 0x0473,
+ 0x94c3, 0x0a2e,
+ 0x94c4, 0x1aaf,
+ 0x94c5, 0x0c23,
+ 0x94c6, 0x0ab2,
+ 0x94c7, 0x4fe4,
+ 0x94c8, 0x1ab0,
+ 0x94cf, 0x4fe5,
+ 0x94d0, 0x1ab7,
+ 0x94d3, 0x4fe6,
+ 0x94d5, 0x1aba,
+ 0x94d8, 0x1abe,
+ 0x94d9, 0x1abd,
+ 0x94da, 0x4fe8,
+ 0x94db, 0x1abf,
+ 0x94dc, 0x0e5e,
+ 0x94dd, 0x0a68,
+ 0x94de, 0x1ac0,
+ 0x94e1, 0x1142,
+ 0x94e2, 0x1ac3,
+ 0x94e3, 0x0f20,
+ 0x94e4, 0x1ac4,
+ 0x94e6, 0x4fe9,
+ 0x94e7, 0x1ac6,
+ 0x94e9, 0x1ac9,
+ 0x94ea, 0x1ac8,
+ 0x94eb, 0x1aca,
+ 0x94ec, 0x06f0,
+ 0x94ed, 0x0aff,
+ 0x94ee, 0x1acb,
+ 0x94f0, 0x0893,
+ 0x94f1, 0x1046,
+ 0x94f2, 0x04c0,
+ 0x94f3, 0x1acd,
+ 0x94f6, 0x107f,
+ 0x94f7, 0x1ad0,
+ 0x94f8, 0x11fc,
+ 0x94f9, 0x1ad1,
+ 0x94fa, 0x0beb,
+ 0x94fb, 0x4fea,
+ 0x94fc, 0x1ad2,
+ 0x94fe, 0x09fd,
+ 0x94ff, 0x1ad4,
+ 0x9500, 0x0f67,
+ 0x9501, 0x0ded,
+ 0x9502, 0x1ad6,
+ 0x9503, 0x1ad5,
+ 0x9504, 0x051f,
+ 0x9505, 0x0751,
+ 0x9506, 0x1ad7,
+ 0x9508, 0x0fad,
+ 0x9509, 0x1ad9,
+ 0x950b, 0x0683,
+ 0x950c, 0x0f8a,
+ 0x950d, 0x1adb,
+ 0x9510, 0x0ccc,
+ 0x9511, 0x0e33,
+ 0x9512, 0x1ade,
+ 0x9517, 0x1181,
+ 0x9518, 0x1ae3,
+ 0x9519, 0x0570,
+ 0x951a, 0x0aaf,
+ 0x951b, 0x1ae4,
+ 0x951c, 0x4feb,
+ 0x951d, 0x1ae5,
+ 0x9520, 0x4fec,
+ 0x9521, 0x0f0c,
+ 0x9522, 0x1ae8,
+ 0x9523, 0x0a87,
+ 0x9524, 0x053b,
+ 0x9525, 0x1213,
+ 0x9526, 0x08c6,
+ 0x9527, 0x4fed,
+ 0x9528, 0x0f34,
+ 0x9529, 0x1aeb,
+ 0x952a, 0x1ae9,
+ 0x952c, 0x1aec,
+ 0x952d, 0x05e6,
+ 0x952e, 0x086f,
+ 0x952f, 0x0911,
+ 0x9530, 0x0ad1,
+ 0x9531, 0x1aed,
+ 0x9533, 0x4fee,
+ 0x9534, 0x1aef,
+ 0x9535, 0x1af7,
+ 0x9536, 0x1af0,
+ 0x9539, 0x0c3f,
+ 0x953a, 0x1b19,
+ 0x953b, 0x060c,
+ 0x953c, 0x1af3,
+ 0x953d, 0x4fef,
+ 0x953e, 0x1af4,
+ 0x9540, 0x0605,
+ 0x9541, 0x0ac3,
+ 0x9542, 0x1af6,
+ 0x9543, 0x4ff0,
+ 0x9544, 0x1af8,
+ 0x9547, 0x1193,
+ 0x9548, 0x4ff1,
+ 0x9549, 0x1afb,
+ 0x954a, 0x0b5a,
+ 0x954b, 0x4ff2,
+ 0x954c, 0x1afc,
+ 0x954d, 0x0b5b,
+ 0x954e, 0x1afd,
+ 0x9550, 0x06df,
+ 0x9551, 0x0402,
+ 0x9552, 0x1aff,
+ 0x9555, 0x4ff3,
+ 0x9556, 0x1b02,
+ 0x955a, 0x4ff4,
+ 0x955b, 0x1b06,
+ 0x955c, 0x08e4,
+ 0x955d, 0x1b09,
+ 0x955e, 0x1b07,
+ 0x9560, 0x4ff5,
+ 0x9561, 0x1b0a,
+ 0x9563, 0x0a16,
+ 0x9564, 0x1b0c,
+ 0x956d, 0x09c3,
+ 0x956e, 0x4ff6,
+ 0x956f, 0x1b15,
+ 0x9570, 0x09f6,
+ 0x9571, 0x1b16,
+ 0x9574, 0x4ff7,
+ 0x9576, 0x0f4f,
+ 0x9577, 0x1e75,
+ 0x9578, 0x4ff9,
+ 0x957f, 0x04c9,
+ 0x9580, 0x207d,
+ 0x9581, 0x5000,
+ 0x9582, 0x23bf,
+ 0x9583, 0x2113,
+ 0x9584, 0x5001,
+ 0x9586, 0x23c0,
+ 0x9587, 0x5003,
+ 0x9589, 0x1e45,
+ 0x958a, 0x5005,
+ 0x958b, 0x1fd8,
+ 0x958c, 0x23c4,
+ 0x958d, 0x5006,
+ 0x958e, 0x23c2,
+ 0x958f, 0x2104,
+ 0x9590, 0x5007,
+ 0x9591, 0x21bd,
+ 0x9592, 0x5008,
+ 0x9593, 0x1f87,
+ 0x9594, 0x23c3,
+ 0x9595, 0x5009,
+ 0x9598, 0x2269,
+ 0x9599, 0x500c,
+ 0x95a1, 0x1f43,
+ 0x95a2, 0x5014,
+ 0x95a3, 0x1f1e,
+ 0x95a4, 0x2679,
+ 0x95a5, 0x1eeb,
+ 0x95a6, 0x5015,
+ 0x95a8, 0x1f35,
+ 0x95a9, 0x208a,
+ 0x95aa, 0x5017,
+ 0x95ab, 0x23c7,
+ 0x95ac, 0x23c9,
+ 0x95ad, 0x23c6,
+ 0x95ae, 0x5018,
+ 0x95b2, 0x224f,
+ 0x95b3, 0x501c,
+ 0x95b6, 0x23cb,
+ 0x95b7, 0x501f,
+ 0x95b9, 0x21f3,
+ 0x95ba, 0x5021,
+ 0x95bb, 0x21f7,
+ 0x95bc, 0x23cf,
+ 0x95bd, 0x23ce,
+ 0x95be, 0x23ca,
+ 0x95bf, 0x23cd,
+ 0x95c0, 0x5022,
+ 0x95c3, 0x23d0,
+ 0x95c4, 0x5025,
+ 0x95c6, 0x266c,
+ 0x95c7, 0x5027,
+ 0x95c8, 0x23c1,
+ 0x95c9, 0x5028,
+ 0x95ca, 0x1fee,
+ 0x95cb, 0x23d1,
+ 0x95cc, 0x1ff8,
+ 0x95cd, 0x5029,
+ 0x95d0, 0x23d3,
+ 0x95d1, 0x502c,
+ 0x95d4, 0x23d2,
+ 0x95d5, 0x23d4,
+ 0x95d6, 0x1e98,
+ 0x95d7, 0x502f,
+ 0x95dc, 0x1f2c,
+ 0x95dd, 0x5034,
+ 0x95de, 0x23d5,
+ 0x95df, 0x5035,
+ 0x95e1, 0x1e71,
+ 0x95e2, 0x2691,
+ 0x95e3, 0x5037,
+ 0x95e5, 0x23c5,
+ 0x95e6, 0x5039,
+ 0x95e8, 0x0aca,
+ 0x95e9, 0x1685,
+ 0x95ea, 0x0cfa,
+ 0x95eb, 0x1686,
+ 0x95ec, 0x503b,
+ 0x95ed, 0x043e,
+ 0x95ee, 0x0ed9,
+ 0x95ef, 0x0536,
+ 0x95f0, 0x0ccd,
+ 0x95f1, 0x1687,
+ 0x95f2, 0x0f3d,
+ 0x95f3, 0x1688,
+ 0x95f4, 0x0857,
+ 0x95f5, 0x1689,
+ 0x95f7, 0x0acb,
+ 0x95f8, 0x1143,
+ 0x95f9, 0x0b39,
+ 0x95fa, 0x0744,
+ 0x95fb, 0x0ed4,
+ 0x95fc, 0x168b,
+ 0x95fd, 0x0afb,
+ 0x95fe, 0x168c,
+ 0x95ff, 0x503c,
+ 0x9600, 0x0644,
+ 0x9601, 0x06ee,
+ 0x9602, 0x0789,
+ 0x9603, 0x168d,
+ 0x9605, 0x1107,
+ 0x9606, 0x168f,
+ 0x9607, 0x503d,
+ 0x9608, 0x1690,
+ 0x9609, 0x0ff4,
+ 0x960a, 0x1691,
+ 0x960e, 0x0fff,
+ 0x960f, 0x1695,
+ 0x9610, 0x04c2,
+ 0x9611, 0x09a6,
+ 0x9612, 0x1696,
+ 0x9613, 0x503e,
+ 0x9614, 0x0996,
+ 0x9615, 0x1697,
+ 0x9618, 0x503f,
+ 0x9619, 0x169a,
+ 0x961b, 0x5040,
+ 0x961c, 0x06b2,
+ 0x961d, 0x1354,
+ 0x961e, 0x5041,
+ 0x961f, 0x0612,
+ 0x9620, 0x5042,
+ 0x9621, 0x1356,
+ 0x9622, 0x1355,
+ 0x9623, 0x5043,
+ 0x962a, 0x1358,
+ 0x962b, 0x504a,
+ 0x962e, 0x0cc9,
+ 0x962f, 0x504d,
+ 0x9631, 0x1357,
+ 0x9632, 0x065d,
+ 0x9633, 0x101d,
+ 0x9634, 0x107c,
+ 0x9635, 0x1194,
+ 0x9636, 0x08a8,
+ 0x9637, 0x504f,
+ 0x963b, 0x1245,
+ 0x963c, 0x135a,
+ 0x963d, 0x1359,
+ 0x963e, 0x5053,
+ 0x963f, 0x03ad,
+ 0x9640, 0x0e84,
+ 0x9641, 0x5054,
+ 0x9642, 0x135b,
+ 0x9643, 0x5055,
+ 0x9644, 0x06b8,
+ 0x9645, 0x083d,
+ 0x9646, 0x0a64,
+ 0x9647, 0x0a4b,
+ 0x9648, 0x04e7,
+ 0x9649, 0x135c,
+ 0x964a, 0x5056,
+ 0x964b, 0x0a51,
+ 0x964c, 0x0b13,
+ 0x964d, 0x0886,
+ 0x964e, 0x5057,
+ 0x9650, 0x0f4b,
+ 0x9651, 0x5059,
+ 0x9654, 0x135d,
+ 0x9655, 0x0cfb,
+ 0x9656, 0x505c,
+ 0x9658, 0x231a,
+ 0x9659, 0x505e,
+ 0x965b, 0x0446,
+ 0x965c, 0x5060,
+ 0x965d, 0x2114,
+ 0x965e, 0x5061,
+ 0x965f, 0x135e,
+ 0x9660, 0x5062,
+ 0x9661, 0x05f7,
+ 0x9662, 0x10fd,
+ 0x9663, 0x2284,
+ 0x9664, 0x0522,
+ 0x9665, 0x5063,
+ 0x9667, 0x135f,
+ 0x9668, 0x110c,
+ 0x9669, 0x0f42,
+ 0x966a, 0x0ba4,
+ 0x966b, 0x5065,
+ 0x966c, 0x1360,
+ 0x966d, 0x5066,
+ 0x9670, 0x221c,
+ 0x9671, 0x5069,
+ 0x9672, 0x1361,
+ 0x9673, 0x1e7e,
+ 0x9674, 0x1362,
+ 0x9675, 0x0a33,
+ 0x9676, 0x0e28,
+ 0x9677, 0x0f4a,
+ 0x9678, 0x204d,
+ 0x9679, 0x506a,
+ 0x967d, 0x2201,
+ 0x967e, 0x506e,
+ 0x9685, 0x10cc,
+ 0x9686, 0x0a48,
+ 0x9687, 0x5075,
+ 0x9688, 0x1363,
+ 0x9689, 0x5076,
+ 0x968a, 0x1ed9,
+ 0x968b, 0x0dda,
+ 0x968c, 0x5077,
+ 0x968d, 0x1364,
+ 0x968e, 0x1fb2,
+ 0x968f, 0x0ddb,
+ 0x9690, 0x1085,
+ 0x9691, 0x5078,
+ 0x9694, 0x06ef,
+ 0x9695, 0x2252,
+ 0x9696, 0x507b,
+ 0x9697, 0x1365,
+ 0x9698, 0x03ba,
+ 0x9699, 0x0f23,
+ 0x969a, 0x507c,
+ 0x969b, 0x1f79,
+ 0x969c, 0x1170,
+ 0x969d, 0x507d,
+ 0x96a7, 0x0de2,
+ 0x96a8, 0x2157,
+ 0x96a9, 0x5087,
+ 0x96aa, 0x21bf,
+ 0x96ab, 0x5088,
+ 0x96b0, 0x1366,
+ 0x96b1, 0x221f,
+ 0x96b2, 0x508d,
+ 0x96b3, 0x1684,
+ 0x96b4, 0x203d,
+ 0x96b5, 0x508e,
+ 0x96b6, 0x09ee,
+ 0x96b7, 0x508f,
+ 0x96b8, 0x2015,
+ 0x96b9, 0x1d79,
+ 0x96ba, 0x5090,
+ 0x96bb, 0x26a5,
+ 0x96bc, 0x1d7a,
+ 0x96be, 0x0b34,
+ 0x96bf, 0x5091,
+ 0x96c0, 0x0c93,
+ 0x96c1, 0x100c,
+ 0x96c2, 0x5092,
+ 0x96c4, 0x0fa6,
+ 0x96c5, 0x0fee,
+ 0x96c6, 0x0822,
+ 0x96c7, 0x0726,
+ 0x96c8, 0x5094,
+ 0x96c9, 0x1b1c,
+ 0x96ca, 0x5095,
+ 0x96cc, 0x0549,
+ 0x96cd, 0x109f,
+ 0x96ce, 0x1d7c,
+ 0x96cf, 0x0520,
+ 0x96d0, 0x5097,
+ 0x96d2, 0x1d7d,
+ 0x96d3, 0x5099,
+ 0x96d5, 0x05d2,
+ 0x96d6, 0x2156,
+ 0x96d7, 0x509b,
+ 0x96d9, 0x2144,
+ 0x96da, 0x509d,
+ 0x96db, 0x1e91,
+ 0x96dc, 0x2257,
+ 0x96dd, 0x509e,
+ 0x96e0, 0x1d7f,
+ 0x96e1, 0x50a1,
+ 0x96e2, 0x200a,
+ 0x96e3, 0x2092,
+ 0x96e4, 0x50a2,
+ 0x96e8, 0x10cf,
+ 0x96e9, 0x1d61,
+ 0x96ea, 0x0fd2,
+ 0x96eb, 0x50a6,
+ 0x96ef, 0x1d63,
+ 0x96f0, 0x50aa,
+ 0x96f2, 0x2250,
+ 0x96f3, 0x1d62,
+ 0x96f4, 0x50ac,
+ 0x96f6, 0x0a2c,
+ 0x96f7, 0x09c2,
+ 0x96f8, 0x50ae,
+ 0x96f9, 0x040b,
+ 0x96fa, 0x50af,
+ 0x96fb, 0x1ec3,
+ 0x96fc, 0x50b0,
+ 0x96fe, 0x0efc,
+ 0x96ff, 0x50b2,
+ 0x9700, 0x0fb3,
+ 0x9701, 0x1d65,
+ 0x9702, 0x50b3,
+ 0x9704, 0x0f63,
+ 0x9705, 0x50b5,
+ 0x9706, 0x1d64,
+ 0x9707, 0x1191,
+ 0x9708, 0x1d66,
+ 0x9709, 0x0abe,
+ 0x970a, 0x50b6,
+ 0x970d, 0x0809,
+ 0x970e, 0x1d68,
+ 0x970f, 0x1d67,
+ 0x9710, 0x50b9,
+ 0x9713, 0x0b41,
+ 0x9714, 0x50bc,
+ 0x9716, 0x0a21,
+ 0x9717, 0x50be,
+ 0x971c, 0x0d9f,
+ 0x971d, 0x50c3,
+ 0x971e, 0x0f29,
+ 0x971f, 0x50c4,
+ 0x9727, 0x21a8,
+ 0x9728, 0x50cc,
+ 0x972a, 0x1d69,
+ 0x972b, 0x50ce,
+ 0x972d, 0x1d6a,
+ 0x972e, 0x50d0,
+ 0x9730, 0x1d6b,
+ 0x9731, 0x50d2,
+ 0x9732, 0x0a5d,
+ 0x9733, 0x50d3,
+ 0x9738, 0x03df,
+ 0x9739, 0x0bba,
+ 0x973a, 0x50d8,
+ 0x973d, 0x260d,
+ 0x973e, 0x1d6c,
+ 0x973f, 0x50db,
+ 0x9742, 0x260c,
+ 0x9743, 0x50de,
+ 0x9744, 0x260e,
+ 0x9745, 0x50df,
+ 0x9748, 0x2032,
+ 0x9749, 0x50e2,
+ 0x9752, 0x0c5d,
+ 0x9753, 0x1d60,
+ 0x9754, 0x50eb,
+ 0x9756, 0x08e7,
+ 0x9757, 0x50ed,
+ 0x9759, 0x08e1,
+ 0x975a, 0x260b,
+ 0x975b, 0x05c6,
+ 0x975c, 0x50ef,
+ 0x975e, 0x0664,
+ 0x975f, 0x50f1,
+ 0x9760, 0x094c,
+ 0x9761, 0x0ad7,
+ 0x9762, 0x0aeb,
+ 0x9763, 0x50f2,
+ 0x9765, 0x1282,
+ 0x9766, 0x50f4,
+ 0x9768, 0x22c3,
+ 0x9769, 0x06ea,
+ 0x976a, 0x50f6,
+ 0x9773, 0x08ca,
+ 0x9774, 0x0fce,
+ 0x9775, 0x50ff,
+ 0x9776, 0x03db,
+ 0x9777, 0x5100,
+ 0x977c, 0x1dc8,
+ 0x977d, 0x5105,
+ 0x9785, 0x1dc9,
+ 0x9786, 0x510d,
+ 0x978b, 0x0f77,
+ 0x978c, 0x5112,
+ 0x978d, 0x03bb,
+ 0x978e, 0x5113,
+ 0x978f, 0x1f23,
+ 0x9790, 0x5114,
+ 0x9791, 0x1dca,
+ 0x9793, 0x5115,
+ 0x9794, 0x1dcc,
+ 0x9795, 0x5116,
+ 0x9798, 0x0c47,
+ 0x9799, 0x5119,
+ 0x97a0, 0x08fe,
+ 0x97a1, 0x5120,
+ 0x97a3, 0x1dcf,
+ 0x97a4, 0x5122,
+ 0x97a6, 0x2695,
+ 0x97a7, 0x5124,
+ 0x97ab, 0x1dce,
+ 0x97ac, 0x5128,
+ 0x97ad, 0x0447,
+ 0x97ae, 0x5129,
+ 0x97af, 0x1dcd,
+ 0x97b0, 0x512a,
+ 0x97b2, 0x1dd0,
+ 0x97b3, 0x512c,
+ 0x97b4, 0x1dd1,
+ 0x97b5, 0x512d,
+ 0x97bd, 0x265e,
+ 0x97be, 0x5135,
+ 0x97c3, 0x265d,
+ 0x97c4, 0x513a,
+ 0x97c6, 0x2692,
+ 0x97c7, 0x513c,
+ 0x97c9, 0x265f,
+ 0x97ca, 0x513e,
+ 0x97cb, 0x218d,
+ 0x97cc, 0x20fd,
+ 0x97cd, 0x513f,
+ 0x97d3, 0x1f40,
+ 0x97d4, 0x5145,
+ 0x97d9, 0x2465,
+ 0x97da, 0x514a,
+ 0x97dc, 0x2467,
+ 0x97dd, 0x514c,
+ 0x97de, 0x2466,
+ 0x97df, 0x514d,
+ 0x97e6, 0x0eb3,
+ 0x97e7, 0x0ca8,
+ 0x97e8, 0x5154,
+ 0x97e9, 0x0762,
+ 0x97ea, 0x184e,
+ 0x97ed, 0x08f1,
+ 0x97ee, 0x5155,
+ 0x97f3, 0x107b,
+ 0x97f4, 0x515a,
+ 0x97f5, 0x1112,
+ 0x97f6, 0x0d11,
+ 0x97f7, 0x515b,
+ 0x97ff, 0x21c9,
+ 0x9800, 0x5163,
+ 0x9801, 0x2209,
+ 0x9802, 0x1ec9,
+ 0x9803, 0x20e9,
+ 0x9804, 0x5164,
+ 0x9805, 0x21ca,
+ 0x9806, 0x2146,
+ 0x9807, 0x25c5,
+ 0x9808, 0x21dc,
+ 0x9809, 0x5165,
+ 0x980a, 0x245e,
+ 0x980b, 0x5166,
+ 0x980c, 0x214f,
+ 0x980d, 0x5167,
+ 0x980e, 0x25c6,
+ 0x9810, 0x2241,
+ 0x9811, 0x218a,
+ 0x9812, 0x1e2f,
+ 0x9813, 0x1edc,
+ 0x9814, 0x5168,
+ 0x9817, 0x20bf,
+ 0x9818, 0x2034,
+ 0x9819, 0x516b,
+ 0x981c, 0x25c9,
+ 0x981d, 0x516e,
+ 0x9821, 0x25c8,
+ 0x9822, 0x5172,
+ 0x9824, 0x220e,
+ 0x9825, 0x5174,
+ 0x9826, 0x25cb,
+ 0x9827, 0x5175,
+ 0x982d, 0x217d,
+ 0x982e, 0x517b,
+ 0x9830, 0x1f7e,
+ 0x9831, 0x517d,
+ 0x9837, 0x25cc,
+ 0x9838, 0x1fc3,
+ 0x9839, 0x5183,
+ 0x983b, 0x20b9,
+ 0x983c, 0x5185,
+ 0x983d, 0x2181,
+ 0x983e, 0x5186,
+ 0x9846, 0x1fda,
+ 0x9847, 0x518e,
+ 0x984c, 0x2173,
+ 0x984d, 0x1ee1,
+ 0x984e, 0x25cd,
+ 0x984f, 0x5193,
+ 0x9853, 0x25ce,
+ 0x9854, 0x21f6,
+ 0x9855, 0x5197,
+ 0x9858, 0x224b,
+ 0x9859, 0x25d1,
+ 0x985a, 0x519a,
+ 0x985b, 0x1ec0,
+ 0x985c, 0x519b,
+ 0x985e, 0x2008,
+ 0x985f, 0x519d,
+ 0x9862, 0x25d0,
+ 0x9863, 0x51a0,
+ 0x9865, 0x25d2,
+ 0x9866, 0x51a2,
+ 0x9867, 0x1f2a,
+ 0x9868, 0x51a3,
+ 0x986b, 0x1e72,
+ 0x986c, 0x25d3,
+ 0x986d, 0x51a6,
+ 0x986f, 0x21be,
+ 0x9870, 0x25d4,
+ 0x9871, 0x2044,
+ 0x9872, 0x51a8,
+ 0x9873, 0x25cf,
+ 0x9874, 0x20f3,
+ 0x9875, 0x103a,
+ 0x9876, 0x05e4,
+ 0x9877, 0x0c67,
+ 0x9878, 0x1be0,
+ 0x9879, 0x0f5b,
+ 0x987a, 0x0da8,
+ 0x987b, 0x0fb6,
+ 0x987c, 0x1827,
+ 0x987d, 0x0e98,
+ 0x987e, 0x0724,
+ 0x987f, 0x0618,
+ 0x9880, 0x1be1,
+ 0x9881, 0x03ef,
+ 0x9882, 0x0dc1,
+ 0x9883, 0x1be2,
+ 0x9884, 0x10e7,
+ 0x9885, 0x0a54,
+ 0x9886, 0x0a35,
+ 0x9887, 0x0be3,
+ 0x9888, 0x08e0,
+ 0x9889, 0x1be3,
+ 0x988a, 0x0848,
+ 0x988b, 0x51a9,
+ 0x988c, 0x1be4,
+ 0x988e, 0x51aa,
+ 0x988f, 0x1be6,
+ 0x9890, 0x104a,
+ 0x9891, 0x0bd4,
+ 0x9892, 0x51ab,
+ 0x9893, 0x0e78,
+ 0x9894, 0x1be7,
+ 0x9895, 0x51ac,
+ 0x9896, 0x1096,
+ 0x9897, 0x0952,
+ 0x9898, 0x0e35,
+ 0x9899, 0x51ad,
+ 0x989a, 0x1be8,
+ 0x989c, 0x0ffe,
+ 0x989d, 0x062d,
+ 0x989e, 0x1bea,
+ 0x98a0, 0x05c0,
+ 0x98a1, 0x1bec,
+ 0x98a3, 0x51ae,
+ 0x98a4, 0x04c3,
+ 0x98a5, 0x1bee,
+ 0x98a7, 0x0c82,
+ 0x98a8, 0x1f00,
+ 0x98a9, 0x51af,
+ 0x98ae, 0x24cc,
+ 0x98b0, 0x51b4,
+ 0x98b1, 0x2698,
+ 0x98b2, 0x51b5,
+ 0x98b3, 0x2678,
+ 0x98b4, 0x51b6,
+ 0x98b6, 0x24ce,
+ 0x98b7, 0x51b8,
+ 0x98bc, 0x24cf,
+ 0x98bd, 0x51bd,
+ 0x98c4, 0x20b8,
+ 0x98c5, 0x51c4,
+ 0x98c6, 0x24d0,
+ 0x98c7, 0x51c5,
+ 0x98c8, 0x24d1,
+ 0x98c9, 0x51c6,
+ 0x98ce, 0x0684,
+ 0x98cf, 0x51cb,
+ 0x98d1, 0x19b7,
+ 0x98d4, 0x51cd,
+ 0x98d5, 0x19ba,
+ 0x98d6, 0x51ce,
+ 0x98d8, 0x0bcd,
+ 0x98d9, 0x19bb,
+ 0x98db, 0x1ef4,
+ 0x98dc, 0x51d0,
+ 0x98de, 0x0666,
+ 0x98df, 0x0d4a,
+ 0x98e0, 0x239b,
+ 0x98e1, 0x51d2,
+ 0x98e2, 0x267e,
+ 0x98e3, 0x51d3,
+ 0x98e7, 0x161a,
+ 0x98e8, 0x1de7,
+ 0x98e9, 0x239d,
+ 0x98ea, 0x239f,
+ 0x98ec, 0x51d7,
+ 0x98ed, 0x23a1,
+ 0x98ee, 0x51d8,
+ 0x98ef, 0x1ef1,
+ 0x98f0, 0x51d9,
+ 0x98f2, 0x221e,
+ 0x98f3, 0x51db,
+ 0x98f4, 0x23a2,
+ 0x98f5, 0x51dc,
+ 0x98fc, 0x214b,
+ 0x98fd, 0x1e36,
+ 0x98fe, 0x2135,
+ 0x98ff, 0x51e3,
+ 0x9900, 0x51e4,
+ 0x9903, 0x1fad,
+ 0x9904, 0x51e7,
+ 0x9905, 0x1e53,
+ 0x9906, 0x51e8,
+ 0x9909, 0x23a3,
+ 0x990a, 0x2203,
+ 0x990b, 0x51eb,
+ 0x990c, 0x1ee7,
+ 0x990d, 0x1de8,
+ 0x990e, 0x51ec,
+ 0x9910, 0x0494,
+ 0x9911, 0x23a4,
+ 0x9912, 0x2097,
+ 0x9913, 0x1ee4,
+ 0x9914, 0x51ee,
+ 0x9918, 0x2238,
+ 0x9919, 0x51f2,
+ 0x991b, 0x23a5,
+ 0x991c, 0x51f4,
+ 0x991e, 0x1f9a,
+ 0x991f, 0x51f6,
+ 0x9921, 0x21c3,
+ 0x9922, 0x51f8,
+ 0x9928, 0x1f2e,
+ 0x9929, 0x51fe,
+ 0x992e, 0x1de9,
+ 0x992f, 0x5203,
+ 0x9933, 0x239c,
+ 0x9934, 0x5207,
+ 0x9937, 0x23a6,
+ 0x9938, 0x520a,
+ 0x993c, 0x239e,
+ 0x993d, 0x520e,
+ 0x993e, 0x2035,
+ 0x993f, 0x23a7,
+ 0x9940, 0x520f,
+ 0x9943, 0x23a8,
+ 0x9944, 0x5212,
+ 0x9945, 0x2075,
+ 0x9946, 0x5213,
+ 0x9948, 0x23a9,
+ 0x994b, 0x1feb,
+ 0x994c, 0x23ac,
+ 0x994d, 0x5215,
+ 0x9951, 0x1f6a,
+ 0x9952, 0x20f9,
+ 0x9953, 0x5219,
+ 0x9954, 0x1deb,
+ 0x9955, 0x1dea,
+ 0x9956, 0x521a,
+ 0x9957, 0x2666,
+ 0x9958, 0x521b,
+ 0x995c, 0x2667,
+ 0x995d, 0x521f,
+ 0x995e, 0x1e6c,
+ 0x995f, 0x5220,
+ 0x9962, 0x23ad,
+ 0x9963, 0x161d,
+ 0x9964, 0x5223,
+ 0x9965, 0x0815,
+ 0x9966, 0x5224,
+ 0x9967, 0x161e,
+ 0x996d, 0x0656,
+ 0x996e, 0x1082,
+ 0x996f, 0x0875,
+ 0x9970, 0x0d65,
+ 0x9971, 0x040e,
+ 0x9972, 0x0dbc,
+ 0x9973, 0x5225,
+ 0x9974, 0x1624,
+ 0x9975, 0x063b,
+ 0x9976, 0x0c9f,
+ 0x9977, 0x1625,
+ 0x9978, 0x5226,
+ 0x997a, 0x0899,
+ 0x997b, 0x5228,
+ 0x997c, 0x0466,
+ 0x997d, 0x1626,
+ 0x997e, 0x5229,
+ 0x997f, 0x0635,
+ 0x9980, 0x1627,
+ 0x9981, 0x0b3c,
+ 0x9982, 0x522a,
+ 0x9984, 0x1628,
+ 0x9985, 0x0f47,
+ 0x9986, 0x0736,
+ 0x9987, 0x1629,
+ 0x9988, 0x098c,
+ 0x9989, 0x522c,
+ 0x998a, 0x162a,
+ 0x998b, 0x04bd,
+ 0x998c, 0x522d,
+ 0x998d, 0x162b,
+ 0x998e, 0x522e,
+ 0x998f, 0x0a3c,
+ 0x9990, 0x162c,
+ 0x9992, 0x0a9f,
+ 0x9993, 0x162e,
+ 0x9996, 0x0d6e,
+ 0x9997, 0x126e,
+ 0x9998, 0x12f9,
+ 0x9999, 0x0f50,
+ 0x999a, 0x522f,
+ 0x99a5, 0x1b2b,
+ 0x99a6, 0x523a,
+ 0x99a8, 0x13de,
+ 0x99a9, 0x523c,
+ 0x99ac, 0x206d,
+ 0x99ad, 0x2242,
+ 0x99ae, 0x1f02,
+ 0x99af, 0x523f,
+ 0x99b1, 0x2183,
+ 0x99b2, 0x5241,
+ 0x99b3, 0x1e85,
+ 0x99b4, 0x21e9,
+ 0x99b5, 0x5242,
+ 0x99c1, 0x1e57,
+ 0x99c2, 0x524e,
+ 0x99d0, 0x22a5,
+ 0x99d1, 0x2407,
+ 0x99d2, 0x1fca,
+ 0x99d3, 0x525c,
+ 0x99d4, 0x2402,
+ 0x99d5, 0x1f82,
+ 0x99d6, 0x525d,
+ 0x99d8, 0x2408,
+ 0x99d9, 0x2404,
+ 0x99da, 0x525f,
+ 0x99db, 0x2131,
+ 0x99dc, 0x5260,
+ 0x99dd, 0x2184,
+ 0x99de, 0x5261,
+ 0x99df, 0x2403,
+ 0x99e0, 0x5262,
+ 0x99e1, 0x206e,
+ 0x99e2, 0x240b,
+ 0x99e3, 0x5263,
+ 0x99ed, 0x1f3f,
+ 0x99ee, 0x526d,
+ 0x99f1, 0x2067,
+ 0x99f2, 0x5270,
+ 0x99ff, 0x1fd7,
+ 0x9a00, 0x527d,
+ 0x9a01, 0x1e83,
+ 0x9a02, 0x527e,
+ 0x9a05, 0x240f,
+ 0x9a06, 0x5281,
+ 0x9a0d, 0x240e,
+ 0x9a0e, 0x20c7,
+ 0x9a0f, 0x240d,
+ 0x9a10, 0x5288,
+ 0x9a16, 0x2412,
+ 0x9a17, 0x528e,
+ 0x9a19, 0x20b7,
+ 0x9a1a, 0x5290,
+ 0x9a2b, 0x23f0,
+ 0x9a2c, 0x52a1,
+ 0x9a2d, 0x2411,
+ 0x9a2e, 0x2414,
+ 0x9a2f, 0x52a2,
+ 0x9a30, 0x2170,
+ 0x9a31, 0x52a3,
+ 0x9a36, 0x2405,
+ 0x9a37, 0x210c,
+ 0x9a38, 0x2415,
+ 0x9a39, 0x52a8,
+ 0x9a3e, 0x2066,
+ 0x9a3f, 0x52ad,
+ 0x9a40, 0x2352,
+ 0x9a41, 0x2413,
+ 0x9a42, 0x2410,
+ 0x9a43, 0x2416,
+ 0x9a45, 0x20f1,
+ 0x9a46, 0x52ae,
+ 0x9a4a, 0x240a,
+ 0x9a4b, 0x52b2,
+ 0x9a4d, 0x2409,
+ 0x9a4e, 0x52b4,
+ 0x9a4f, 0x2418,
+ 0x9a50, 0x52b5,
+ 0x9a55, 0x1fa7,
+ 0x9a56, 0x52ba,
+ 0x9a57, 0x21fc,
+ 0x9a58, 0x52bb,
+ 0x9a5a, 0x1fc1,
+ 0x9a5b, 0x2406,
+ 0x9a5c, 0x52bd,
+ 0x9a5f, 0x229c,
+ 0x9a60, 0x52c0,
+ 0x9a62, 0x204e,
+ 0x9a63, 0x52c2,
+ 0x9a64, 0x241a,
+ 0x9a65, 0x2419,
+ 0x9a66, 0x52c3,
+ 0x9a6a, 0x240c,
+ 0x9a6b, 0x52c7,
+ 0x9a6c, 0x0a94,
+ 0x9a6d, 0x10e9,
+ 0x9a6e, 0x0e85,
+ 0x9a6f, 0x0fda,
+ 0x9a70, 0x0500,
+ 0x9a71, 0x0c7a,
+ 0x9a72, 0x52c8,
+ 0x9a73, 0x047c,
+ 0x9a74, 0x0a66,
+ 0x9a75, 0x17ba,
+ 0x9a76, 0x0d52,
+ 0x9a77, 0x17bb,
+ 0x9a79, 0x0903,
+ 0x9a7a, 0x17bd,
+ 0x9a7b, 0x1201,
+ 0x9a7c, 0x0e86,
+ 0x9a7d, 0x17bf,
+ 0x9a7e, 0x0850,
+ 0x9a7f, 0x17be,
+ 0x9a80, 0x17c0,
+ 0x9a82, 0x0a95,
+ 0x9a83, 0x52c9,
+ 0x9a84, 0x088f,
+ 0x9a85, 0x17c2,
+ 0x9a86, 0x0a8d,
+ 0x9a87, 0x075e,
+ 0x9a88, 0x17c3,
+ 0x9a89, 0x52ca,
+ 0x9a8a, 0x17c4,
+ 0x9a8b, 0x04f7,
+ 0x9a8c, 0x1012,
+ 0x9a8d, 0x52cb,
+ 0x9a8f, 0x0932,
+ 0x9a90, 0x17c5,
+ 0x9a91, 0x0c0e,
+ 0x9a92, 0x17c6,
+ 0x9a94, 0x52cd,
+ 0x9a96, 0x17c8,
+ 0x9a97, 0x0bcc,
+ 0x9a98, 0x17c9,
+ 0x9a99, 0x52cf,
+ 0x9a9a, 0x0ce0,
+ 0x9a9b, 0x17ca,
+ 0x9a9e, 0x1735,
+ 0x9a9f, 0x17cd,
+ 0x9aa1, 0x0a89,
+ 0x9aa2, 0x17cf,
+ 0x9aa4, 0x11e7,
+ 0x9aa5, 0x17d1,
+ 0x9aa6, 0x52d0,
+ 0x9aa7, 0x17d2,
+ 0x9aa8, 0x0720,
+ 0x9aa9, 0x52d1,
+ 0x9aaf, 0x1e29,
+ 0x9ab0, 0x1dd3,
+ 0x9ab1, 0x1dd2,
+ 0x9ab2, 0x52d7,
+ 0x9ab6, 0x1dd6,
+ 0x9ab7, 0x1dd4,
+ 0x9ab8, 0x0758,
+ 0x9ab9, 0x52db,
+ 0x9aba, 0x1dd7,
+ 0x9abb, 0x52dc,
+ 0x9abc, 0x1dd8,
+ 0x9abd, 0x52dd,
+ 0x9ac0, 0x1dda,
+ 0x9ac1, 0x1dd9,
+ 0x9ac2, 0x1ddc,
+ 0x9ac3, 0x52e0,
+ 0x9ac5, 0x1ddb,
+ 0x9ac6, 0x52e2,
+ 0x9acb, 0x1ddd,
+ 0x9acd, 0x52e7,
+ 0x9acf, 0x2661,
+ 0x9ad0, 0x52e9,
+ 0x9ad1, 0x1ddf,
+ 0x9ad2, 0x26a4,
+ 0x9ad3, 0x0ddd,
+ 0x9ad4, 0x2174,
+ 0x9ad5, 0x2663,
+ 0x9ad6, 0x2662,
+ 0x9ad7, 0x52ea,
+ 0x9ad8, 0x06da,
+ 0x9ad9, 0x52eb,
+ 0x9adf, 0x1dec,
+ 0x9ae0, 0x52f1,
+ 0x9ae1, 0x1ded,
+ 0x9ae2, 0x52f2,
+ 0x9ae6, 0x1dee,
+ 0x9ae7, 0x52f6,
+ 0x9aeb, 0x1df0,
+ 0x9aec, 0x52fa,
+ 0x9aed, 0x1df2,
+ 0x9aee, 0x2675,
+ 0x9aef, 0x1def,
+ 0x9af0, 0x52fb,
+ 0x9af9, 0x1df3,
+ 0x9afa, 0x5304,
+ 0x9afb, 0x1df1,
+ 0x9afc, 0x5305,
+ 0x9b00, 0x5309,
+ 0x9b03, 0x1234,
+ 0x9b04, 0x530c,
+ 0x9b06, 0x214c,
+ 0x9b07, 0x530e,
+ 0x9b08, 0x1df4,
+ 0x9b09, 0x530f,
+ 0x9b0d, 0x267a,
+ 0x9b0e, 0x5313,
+ 0x9b0f, 0x1df5,
+ 0x9b10, 0x5314,
+ 0x9b13, 0x1df6,
+ 0x9b14, 0x5317,
+ 0x9b1a, 0x26a0,
+ 0x9b1b, 0x531d,
+ 0x9b1f, 0x1df7,
+ 0x9b20, 0x5321,
+ 0x9b22, 0x2668,
+ 0x9b23, 0x1df8,
+ 0x9b24, 0x5323,
+ 0x9b25, 0x1ed0,
+ 0x9b26, 0x5324,
+ 0x9b27, 0x2096,
+ 0x9b28, 0x5325,
+ 0x9b29, 0x23cc,
+ 0x9b2a, 0x5326,
+ 0x9b2e, 0x23c8,
+ 0x9b2f, 0x139b,
+ 0x9b30, 0x532a,
+ 0x9b31, 0x223e,
+ 0x9b32, 0x1260,
+ 0x9b33, 0x532b,
+ 0x9b3b, 0x1773,
+ 0x9b3c, 0x0746,
+ 0x9b3d, 0x5333,
+ 0x9b41, 0x098a,
+ 0x9b42, 0x07ff,
+ 0x9b43, 0x1de1,
+ 0x9b44, 0x0be6,
+ 0x9b45, 0x1de0,
+ 0x9b46, 0x5337,
+ 0x9b47, 0x1de2,
+ 0x9b48, 0x1de4,
+ 0x9b49, 0x1de3,
+ 0x9b4a, 0x5338,
+ 0x9b4d, 0x1de5,
+ 0x9b4e, 0x2665,
+ 0x9b4f, 0x0ec9,
+ 0x9b50, 0x533b,
+ 0x9b51, 0x1de6,
+ 0x9b52, 0x533c,
+ 0x9b54, 0x0b0a,
+ 0x9b55, 0x533e,
+ 0x9b58, 0x2664,
+ 0x9b59, 0x5341,
+ 0x9b5a, 0x2239,
+ 0x9b5b, 0x5342,
+ 0x9b6f, 0x204a,
+ 0x9b70, 0x5356,
+ 0x9b74, 0x261f,
+ 0x9b75, 0x535a,
+ 0x9b77, 0x261e,
+ 0x9b78, 0x535c,
+ 0x9b81, 0x2620,
+ 0x9b82, 0x5365,
+ 0x9b83, 0x2621,
+ 0x9b84, 0x5366,
+ 0x9b8e, 0x2622,
+ 0x9b8f, 0x5370,
+ 0x9b90, 0x2627,
+ 0x9b91, 0x1e39,
+ 0x9b92, 0x2625,
+ 0x9b93, 0x5371,
+ 0x9b9a, 0x2629,
+ 0x9b9b, 0x5378,
+ 0x9b9d, 0x262e,
+ 0x9b9e, 0x262b,
+ 0x9b9f, 0x537a,
+ 0x9baa, 0x262a,
+ 0x9bab, 0x262d,
+ 0x9bac, 0x5385,
+ 0x9bad, 0x2628,
+ 0x9bae, 0x21b9,
+ 0x9baf, 0x5386,
+ 0x9bc0, 0x2636,
+ 0x9bc1, 0x2630,
+ 0x9bc2, 0x5397,
+ 0x9bc7, 0x2638,
+ 0x9bc8, 0x539c,
+ 0x9bc9, 0x200d,
+ 0x9bca, 0x2637,
+ 0x9bcb, 0x539d,
+ 0x9bd4, 0x2645,
+ 0x9bd5, 0x53a6,
+ 0x9bd6, 0x263a,
+ 0x9bd7, 0x53a7,
+ 0x9bdb, 0x2643,
+ 0x9bdc, 0x53ab,
+ 0x9bdd, 0x2640,
+ 0x9bde, 0x53ac,
+ 0x9be1, 0x263d,
+ 0x9be2, 0x2641,
+ 0x9be3, 0x53af,
+ 0x9be4, 0x263e,
+ 0x9be5, 0x53b0,
+ 0x9be7, 0x263f,
+ 0x9be8, 0x1fc0,
+ 0x9be9, 0x53b2,
+ 0x9bea, 0x263b,
+ 0x9bec, 0x53b3,
+ 0x9bf0, 0x2642,
+ 0x9bf1, 0x53b7,
+ 0x9bf4, 0x2644,
+ 0x9bf5, 0x53ba,
+ 0x9bfd, 0x2639,
+ 0x9bfe, 0x53c2,
+ 0x9bff, 0x264c,
+ 0x9c00, 0x53c3,
+ 0x9c08, 0x2647,
+ 0x9c09, 0x264b,
+ 0x9c0a, 0x53cb,
+ 0x9c0d, 0x2649,
+ 0x9c0e, 0x53ce,
+ 0x9c10, 0x2648,
+ 0x9c11, 0x53d0,
+ 0x9c12, 0x264a,
+ 0x9c13, 0x2108,
+ 0x9c14, 0x53d1,
+ 0x9c20, 0x264d,
+ 0x9c21, 0x53dd,
+ 0x9c23, 0x2634,
+ 0x9c24, 0x53df,
+ 0x9c25, 0x2651,
+ 0x9c26, 0x53e0,
+ 0x9c28, 0x2650,
+ 0x9c29, 0x2652,
+ 0x9c2a, 0x53e2,
+ 0x9c2d, 0x264f,
+ 0x9c2e, 0x53e5,
+ 0x9c31, 0x2632,
+ 0x9c32, 0x264e,
+ 0x9c33, 0x2653,
+ 0x9c34, 0x53e8,
+ 0x9c35, 0x2657,
+ 0x9c36, 0x53e9,
+ 0x9c37, 0x2635,
+ 0x9c38, 0x53ea,
+ 0x9c39, 0x2633,
+ 0x9c3a, 0x53eb,
+ 0x9c3b, 0x2656,
+ 0x9c3c, 0x53ec,
+ 0x9c3e, 0x2654,
+ 0x9c3f, 0x53ee,
+ 0x9c45, 0x2658,
+ 0x9c46, 0x53f4,
+ 0x9c48, 0x2655,
+ 0x9c49, 0x1e4d,
+ 0x9c4a, 0x53f6,
+ 0x9c52, 0x265b,
+ 0x9c53, 0x53fe,
+ 0x9c54, 0x265a,
+ 0x9c55, 0x53ff,
+ 0x9c56, 0x2659,
+ 0x9c57, 0x202e,
+ 0x9c58, 0x262f,
+ 0x9c59, 0x5400,
+ 0x9c5d, 0x2646,
+ 0x9c5e, 0x5404,
+ 0x9c5f, 0x2626,
+ 0x9c60, 0x5405,
+ 0x9c67, 0x265c,
+ 0x9c68, 0x540c,
+ 0x9c6d, 0x262c,
+ 0x9c6e, 0x5411,
+ 0x9c78, 0x2623,
+ 0x9c79, 0x541b,
+ 0x9c7a, 0x2631,
+ 0x9c7b, 0x541c,
+ 0x9c7c, 0x10c8,
+ 0x9c7d, 0x541d,
+ 0x9c7f, 0x1d89,
+ 0x9c80, 0x541f,
+ 0x9c81, 0x0a5a,
+ 0x9c82, 0x1d8a,
+ 0x9c83, 0x5420,
+ 0x9c85, 0x1d8b,
+ 0x9c89, 0x5422,
+ 0x9c8b, 0x1d90,
+ 0x9c8c, 0x5424,
+ 0x9c8d, 0x0414,
+ 0x9c8e, 0x1d91,
+ 0x9c8f, 0x5425,
+ 0x9c90, 0x1d92,
+ 0x9c93, 0x5426,
+ 0x9c94, 0x1d95,
+ 0x9c96, 0x5427,
+ 0x9c9a, 0x1d97,
+ 0x9c9c, 0x0f37,
+ 0x9c9d, 0x542b,
+ 0x9c9e, 0x1d99,
+ 0x9ca4, 0x09db,
+ 0x9ca5, 0x1d9f,
+ 0x9caa, 0x542c,
+ 0x9cab, 0x1da4,
+ 0x9cac, 0x542d,
+ 0x9cad, 0x1da5,
+ 0x9caf, 0x542e,
+ 0x9cb0, 0x1da7,
+ 0x9cb8, 0x08d7,
+ 0x9cb9, 0x542f,
+ 0x9cba, 0x1daf,
+ 0x9cbe, 0x5430,
+ 0x9cc3, 0x0cd5,
+ 0x9cc4, 0x1db3,
+ 0x9cc8, 0x5435,
+ 0x9cca, 0x1db7,
+ 0x9cd1, 0x5437,
+ 0x9cd3, 0x1dbe,
+ 0x9cd6, 0x0457,
+ 0x9cd7, 0x1dc1,
+ 0x9cda, 0x5439,
+ 0x9cdc, 0x1dc4,
+ 0x9cde, 0x0a24,
+ 0x9cdf, 0x1dc6,
+ 0x9ce0, 0x543b,
+ 0x9ce2, 0x1dc7,
+ 0x9ce3, 0x543d,
+ 0x9ce5, 0x209c,
+ 0x9ce6, 0x543f,
+ 0x9ce9, 0x2580,
+ 0x9cea, 0x5442,
+ 0x9cec, 0x22dc,
+ 0x9ced, 0x5444,
+ 0x9cf3, 0x1f05,
+ 0x9cf4, 0x208b,
+ 0x9cf5, 0x544a,
+ 0x9cf6, 0x2581,
+ 0x9cf7, 0x544b,
+ 0x9d00, 0x5454,
+ 0x9d06, 0x2583,
+ 0x9d07, 0x2582,
+ 0x9d08, 0x545a,
+ 0x9d09, 0x21ee,
+ 0x9d0a, 0x545b,
+ 0x9d15, 0x2182,
+ 0x9d16, 0x5466,
+ 0x9d1b, 0x2243,
+ 0x9d1c, 0x546b,
+ 0x9d1d, 0x2587,
+ 0x9d1e, 0x546c,
+ 0x9d1f, 0x2588,
+ 0x9d20, 0x546d,
+ 0x9d23, 0x2584,
+ 0x9d24, 0x5470,
+ 0x9d26, 0x21fd,
+ 0x9d27, 0x5472,
+ 0x9d28, 0x21ef,
+ 0x9d29, 0x5473,
+ 0x9d2f, 0x258a,
+ 0x9d30, 0x258c,
+ 0x9d31, 0x5479,
+ 0x9d3b, 0x1f47,
+ 0x9d3c, 0x5483,
+ 0x9d3f, 0x1f1d,
+ 0x9d40, 0x5486,
+ 0x9d42, 0x258d,
+ 0x9d43, 0x5488,
+ 0x9d51, 0x1fd0,
+ 0x9d52, 0x2592,
+ 0x9d53, 0x258f,
+ 0x9d54, 0x5496,
+ 0x9d5c, 0x2594,
+ 0x9d5d, 0x1ee0,
+ 0x9d5e, 0x549e,
+ 0x9d60, 0x2591,
+ 0x9d61, 0x2595,
+ 0x9d62, 0x54a0,
+ 0x9d6a, 0x2597,
+ 0x9d6b, 0x54a8,
+ 0x9d6c, 0x20b6,
+ 0x9d6d, 0x54a9,
+ 0x9d6f, 0x2598,
+ 0x9d70, 0x54ab,
+ 0x9d72, 0x20f6,
+ 0x9d73, 0x54ad,
+ 0x9d87, 0x2585,
+ 0x9d88, 0x54c1,
+ 0x9d89, 0x2599,
+ 0x9d8a, 0x54c2,
+ 0x9d93, 0x2596,
+ 0x9d94, 0x54cb,
+ 0x9d98, 0x259a,
+ 0x9d99, 0x54cf,
+ 0x9d9a, 0x259b,
+ 0x9d9b, 0x54d0,
+ 0x9da5, 0x259d,
+ 0x9da6, 0x54da,
+ 0x9da9, 0x259e,
+ 0x9daa, 0x54dd,
+ 0x9daf, 0x234c,
+ 0x9db0, 0x54e2,
+ 0x9db4, 0x1f44,
+ 0x9db5, 0x54e6,
+ 0x9dbb, 0x2660,
+ 0x9dbc, 0x25a0,
+ 0x9dbd, 0x54ec,
+ 0x9dc0, 0x259c,
+ 0x9dc1, 0x54ef,
+ 0x9dc2, 0x259f,
+ 0x9dc3, 0x54f0,
+ 0x9dc4, 0x1f6c,
+ 0x9dc5, 0x54f1,
+ 0x9dd3, 0x25a2,
+ 0x9dd4, 0x54ff,
+ 0x9dd7, 0x20ae,
+ 0x9dd8, 0x5502,
+ 0x9dd9, 0x258b,
+ 0x9dda, 0x25a3,
+ 0x9ddb, 0x5503,
+ 0x9de5, 0x2589,
+ 0x9de6, 0x25a5,
+ 0x9de7, 0x550d,
+ 0x9def, 0x25a4,
+ 0x9df0, 0x5515,
+ 0x9df2, 0x25a6,
+ 0x9df3, 0x2593,
+ 0x9df4, 0x5517,
+ 0x9df8, 0x25a7,
+ 0x9df9, 0x2222,
+ 0x9dfa, 0x25a9,
+ 0x9dfb, 0x551b,
+ 0x9e00, 0x5520,
+ 0x9e0c, 0x25a8,
+ 0x9e0d, 0x552c,
+ 0x9e15, 0x2586,
+ 0x9e16, 0x5534,
+ 0x9e1a, 0x25a1,
+ 0x9e1b, 0x25aa,
+ 0x9e1c, 0x5538,
+ 0x9e1d, 0x2590,
+ 0x9e1e, 0x258e,
+ 0x9e1f, 0x0b54,
+ 0x9e20, 0x1b35,
+ 0x9e21, 0x0819,
+ 0x9e22, 0x1b36,
+ 0x9e23, 0x0afe,
+ 0x9e24, 0x5539,
+ 0x9e25, 0x0b79,
+ 0x9e26, 0x0fe4,
+ 0x9e27, 0x553a,
+ 0x9e28, 0x1b37,
+ 0x9e2d, 0x0fe5,
+ 0x9e2e, 0x553b,
+ 0x9e2f, 0x1015,
+ 0x9e30, 0x553c,
+ 0x9e31, 0x1b3d,
+ 0x9e32, 0x1b3c,
+ 0x9e33, 0x10ea,
+ 0x9e34, 0x553d,
+ 0x9e35, 0x0e83,
+ 0x9e36, 0x1b3e,
+ 0x9e37, 0x1b40,
+ 0x9e38, 0x1b3f,
+ 0x9e39, 0x1b41,
+ 0x9e3b, 0x553e,
+ 0x9e3d, 0x06e6,
+ 0x9e3e, 0x1b43,
+ 0x9e3f, 0x079f,
+ 0x9e40, 0x5540,
+ 0x9e41, 0x1b44,
+ 0x9e43, 0x0918,
+ 0x9e44, 0x1b46,
+ 0x9e45, 0x062b,
+ 0x9e46, 0x1b47,
+ 0x9e4a, 0x0c90,
+ 0x9e4b, 0x1b4b,
+ 0x9e4d, 0x5541,
+ 0x9e4e, 0x1b4d,
+ 0x9e4f, 0x0bb5,
+ 0x9e50, 0x5542,
+ 0x9e51, 0x1b4e,
+ 0x9e52, 0x5543,
+ 0x9e55, 0x1b4f,
+ 0x9e56, 0x5546,
+ 0x9e57, 0x1b50,
+ 0x9e58, 0x1dd5,
+ 0x9e59, 0x5547,
+ 0x9e5a, 0x1b51,
+ 0x9e5d, 0x5548,
+ 0x9e5e, 0x1b54,
+ 0x9e5f, 0x5549,
+ 0x9e63, 0x1b55,
+ 0x9e64, 0x078e,
+ 0x9e65, 0x554d,
+ 0x9e66, 0x1b56,
+ 0x9e6d, 0x1b5e,
+ 0x9e6e, 0x554e,
+ 0x9e70, 0x108a,
+ 0x9e71, 0x1b5d,
+ 0x9e72, 0x5550,
+ 0x9e73, 0x1b5f,
+ 0x9e74, 0x5551,
+ 0x9e75, 0x2688,
+ 0x9e76, 0x5552,
+ 0x9e79, 0x269e,
+ 0x9e7a, 0x25fb,
+ 0x9e7b, 0x5555,
+ 0x9e7c, 0x1f8c,
+ 0x9e7d, 0x21f4,
+ 0x9e7e, 0x1d16,
+ 0x9e7f, 0x0a60,
+ 0x9e80, 0x5556,
+ 0x9e82, 0x1dfc,
+ 0x9e83, 0x5558,
+ 0x9e87, 0x1dfd,
+ 0x9e89, 0x555c,
+ 0x9e8b, 0x1dff,
+ 0x9e8c, 0x555e,
+ 0x9e92, 0x1e00,
+ 0x9e93, 0x0a5b,
+ 0x9e94, 0x5564,
+ 0x9e97, 0x200f,
+ 0x9e98, 0x5567,
+ 0x9e9d, 0x1e02,
+ 0x9e9e, 0x556c,
+ 0x9e9f, 0x1e03,
+ 0x9ea0, 0x556d,
+ 0x9ea5, 0x2071,
+ 0x9ea6, 0x0a9a,
+ 0x9ea7, 0x5572,
+ 0x9ea9, 0x25f7,
+ 0x9eaa, 0x5574,
+ 0x9eaf, 0x2696,
+ 0x9eb0, 0x5579,
+ 0x9eb4, 0x1cee,
+ 0x9eb5, 0x268f,
+ 0x9eb6, 0x557d,
+ 0x9eb8, 0x1ced,
+ 0x9eb9, 0x557f,
+ 0x9ebb, 0x0a90,
+ 0x9ebc, 0x5581,
+ 0x9ebd, 0x1df9,
+ 0x9ebf, 0x5582,
+ 0x9ec4, 0x07db,
+ 0x9ec5, 0x5587,
+ 0x9ec9, 0x12f8,
+ 0x9eca, 0x558b,
+ 0x9ecc, 0x22da,
+ 0x9ecd, 0x0d89,
+ 0x9ece, 0x09d3,
+ 0x9ecf, 0x1b2a,
+ 0x9ed0, 0x558d,
+ 0x9ed1, 0x0791,
+ 0x9ed2, 0x558e,
+ 0x9ed4, 0x0c2a,
+ 0x9ed5, 0x5590,
+ 0x9ed8, 0x0b0f,
+ 0x9ed9, 0x5593,
+ 0x9edb, 0x1e04,
+ 0x9ede, 0x1ec1,
+ 0x9edf, 0x1e08,
+ 0x9ee0, 0x1e07,
+ 0x9ee1, 0x5595,
+ 0x9ee2, 0x1e09,
+ 0x9ee3, 0x5596,
+ 0x9ee5, 0x1e0c,
+ 0x9ee6, 0x5598,
+ 0x9ee7, 0x1e0b,
+ 0x9ee8, 0x1eb3,
+ 0x9ee9, 0x1e0a,
+ 0x9eea, 0x1e0d,
+ 0x9eeb, 0x5599,
+ 0x9eef, 0x1e0e,
+ 0x9ef0, 0x559d,
+ 0x9ef2, 0x266a,
+ 0x9ef3, 0x559f,
+ 0x9ef4, 0x268a,
+ 0x9ef5, 0x55a0,
+ 0x9ef7, 0x2669,
+ 0x9ef8, 0x55a2,
+ 0x9ef9, 0x1a55,
+ 0x9efa, 0x55a3,
+ 0x9efb, 0x1a56,
+ 0x9efd, 0x2618,
+ 0x9efe, 0x1d76,
+ 0x9eff, 0x2619,
+ 0x9f00, 0x55a4,
+ 0x9f09, 0x261a,
+ 0x9f0a, 0x55ad,
+ 0x9f0b, 0x1d77,
+ 0x9f0c, 0x55ae,
+ 0x9f0d, 0x1d78,
+ 0x9f0e, 0x05e5,
+ 0x9f0f, 0x55af,
+ 0x9f10, 0x1274,
+ 0x9f11, 0x55b0,
+ 0x9f13, 0x071d,
+ 0x9f14, 0x55b2,
+ 0x9f15, 0x2673,
+ 0x9f16, 0x55b3,
+ 0x9f17, 0x1271,
+ 0x9f18, 0x55b4,
+ 0x9f19, 0x13df,
+ 0x9f1a, 0x55b5,
+ 0x9f20, 0x0d8a,
+ 0x9f21, 0x55bb,
+ 0x9f22, 0x1e0f,
+ 0x9f23, 0x55bc,
+ 0x9f2c, 0x1e10,
+ 0x9f2d, 0x55c5,
+ 0x9f2f, 0x1e11,
+ 0x9f30, 0x55c7,
+ 0x9f37, 0x1e13,
+ 0x9f38, 0x55ce,
+ 0x9f39, 0x1e12,
+ 0x9f3a, 0x55cf,
+ 0x9f3b, 0x0430,
+ 0x9f3c, 0x55d0,
+ 0x9f3d, 0x1e14,
+ 0x9f3f, 0x55d1,
+ 0x9f44, 0x1e16,
+ 0x9f45, 0x55d6,
+ 0x9f4a, 0x20c6,
+ 0x9f4b, 0x226b,
+ 0x9f4c, 0x55db,
+ 0x9f4f, 0x24d3,
+ 0x9f50, 0x0c0a,
+ 0x9f51, 0x19c2,
+ 0x9f52, 0x1e86,
+ 0x9f53, 0x55de,
+ 0x9f54, 0x260f,
+ 0x9f55, 0x55df,
+ 0x9f59, 0x2611,
+ 0x9f5a, 0x55e3,
+ 0x9f5c, 0x2613,
+ 0x9f5d, 0x55e5,
+ 0x9f5f, 0x2610,
+ 0x9f60, 0x2612,
+ 0x9f61, 0x2030,
+ 0x9f62, 0x55e7,
+ 0x9f63, 0x2671,
+ 0x9f64, 0x55e8,
+ 0x9f66, 0x2614,
+ 0x9f67, 0x55ea,
+ 0x9f6a, 0x2616,
+ 0x9f6b, 0x55ed,
+ 0x9f6c, 0x2615,
+ 0x9f6d, 0x55ee,
+ 0x9f72, 0x20f2,
+ 0x9f73, 0x55f3,
+ 0x9f77, 0x2617,
+ 0x9f78, 0x55f7,
+ 0x9f7f, 0x0502,
+ 0x9f80, 0x1d6d,
+ 0x9f81, 0x55fe,
+ 0x9f83, 0x1d6e,
+ 0x9f84, 0x0a2d,
+ 0x9f85, 0x1d6f,
+ 0x9f8b, 0x0c7e,
+ 0x9f8c, 0x1d75,
+ 0x9f8d, 0x2037,
+ 0x9f8e, 0x5600,
+ 0x9f90, 0x20b3,
+ 0x9f91, 0x5602,
+ 0x9f94, 0x1f22,
+ 0x9f95, 0x24ed,
+ 0x9f96, 0x5605,
+ 0x9f99, 0x0a43,
+ 0x9f9a, 0x0701,
+ 0x9f9b, 0x1a54,
+ 0x9f9c, 0x1f34,
+ 0x9f9d, 0x5608,
+ 0x9f9f, 0x0743,
+ 0x9fa0, 0x12f3,
+ 0x9fa1, 0x560a,
+ 0xe7e7, 0x274b,
+ 0xe815, 0x561f,
+ 0xf92c, 0x560f,
+ 0xfa0d, 0x5610,
+ 0xfa11, 0x5613,
+ 0xfa13, 0x5614,
+ 0xfa18, 0x5616,
+ 0xfa1f, 0x5617,
+ 0xfa23, 0x561a,
+ 0xfa27, 0x561c,
+ 0xfe30, 0x271d,
+ 0xfe49, 0x272b,
+ 0xfe54, 0x2735,
+ 0xfe59, 0x2739,
+ 0xfe68, 0x2747,
+ 0xff01, 0x0106,
+ 0xff04, 0x00a6,
+ 0xff05, 0x010a,
+ 0xff5e, 0x006a,
+ 0xffe0, 0x00a8,
+ 0xffe2, 0x271e,
+ 0xffe3, 0x0163,
+ 0xffe4, 0x271f,
+ 0xffe5, 0x0109,
+ 0x2014, 0x0256,
+ 0x2026, 0x0257,
+ 0x2225, 0x1e1c,
+ 0x3001, 0x023f,
+ 0x3002, 0x023e,
+ 0x3008, 0x0248,
+ 0x3010, 0x0252,
+ 0x3013, 0x1e1a,
+ 0x3014, 0x0246,
+ 0x3016, 0x0250,
+ 0xff01, 0x0242,
+ 0xff08, 0x0244,
+ 0xff0c, 0x023d,
+ 0xff0e, 0x1e1b,
+ 0xff1a, 0x0240,
+ 0xff1d, 0x1e1c,
+ 0xff1f, 0x0243,
+ 0xff3b, 0x1e1d,
+ 0xff3d, 0x1e1e,
+ 0xff3f, 0x0258,
+ 0xff5b, 0x0254,
+ 0xff5d, 0x0255,
+ 0xff5e, 0x1e18,
+ 0xffe3, 0x1e1f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12UniGBUCS2VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12UniGBUCS2VMap2, 13485
+};
+
+static Gushort gb12AdobeGB12VMap2[178] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0x2300, 0x2300,
+ 0x2400, 0x2400,
+ 0x2500, 0x2500,
+ 0x2600, 0x2600,
+ 0x2700, 0x2700,
+ 0x2800, 0x2800,
+ 0x2900, 0x2900,
+ 0x2a00, 0x2a00,
+ 0x2b00, 0x2b00,
+ 0x2c00, 0x2c00,
+ 0x2d00, 0x2d00,
+ 0x2e00, 0x2e00,
+ 0x2f00, 0x2f00,
+ 0x3000, 0x3000,
+ 0x3100, 0x3100,
+ 0x3200, 0x3200,
+ 0x3300, 0x3300,
+ 0x3400, 0x3400,
+ 0x3500, 0x3500,
+ 0x3600, 0x3600,
+ 0x3700, 0x3700,
+ 0x3800, 0x3800,
+ 0x3900, 0x3900,
+ 0x3a00, 0x3a00,
+ 0x3b00, 0x3b00,
+ 0x3c00, 0x3c00,
+ 0x3d00, 0x3d00,
+ 0x3e00, 0x3e00,
+ 0x3f00, 0x3f00,
+ 0x4000, 0x4000,
+ 0x4100, 0x4100,
+ 0x4200, 0x4200,
+ 0x4300, 0x4300,
+ 0x4400, 0x4400,
+ 0x4500, 0x4500,
+ 0x4600, 0x4600,
+ 0x4700, 0x4700,
+ 0x4800, 0x4800,
+ 0x4900, 0x4900,
+ 0x4a00, 0x4a00,
+ 0x4b00, 0x4b00,
+ 0x4c00, 0x4c00,
+ 0x4d00, 0x4d00,
+ 0x4e00, 0x4e00,
+ 0x4f00, 0x4f00,
+ 0x5000, 0x5000,
+ 0x5100, 0x5100,
+ 0x5200, 0x5200,
+ 0x5300, 0x5300,
+ 0x5400, 0x5400,
+ 0x5500, 0x5500,
+ 0x5600, 0x5600,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 gb12AdobeGB12VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ gb12AdobeGB12VMap2, 89
+};
+
+static struct {
+ char *name;
+ GfxFontEncoding16 *enc;
+} gfxGB12Tab[] = {
+ { "Adobe-GB1-0", &gb12AdobeGB10Enc16 },
+ { "Adobe-GB1-1", &gb12AdobeGB11Enc16 },
+ { "Adobe-GB1-2", &gb12AdobeGB12Enc16 },
+ { "GB-EUC-H", &gb12GBEUCHEnc16 },
+ { "GB-EUC-V", &gb12GBEUCVEnc16 },
+ { "GB-H", &gb12GBHEnc16 },
+ { "GB-V", &gb12GBVEnc16 },
+ { "GBK-EUC-H", &gb12GBKEUCHEnc16 },
+ { "GBK-EUC-V", &gb12GBKEUCVEnc16 },
+ { "GBT-EUC-H", &gb12GBTEUCHEnc16 },
+ { "GBT-EUC-V", &gb12GBTEUCVEnc16 },
+ { "GBT-H", &gb12GBTHEnc16 },
+ { "GBT-V", &gb12GBTVEnc16 },
+ { "GBTpc-EUC-H", &gb12GBTpcEUCHEnc16 },
+ { "GBTpc-EUC-V", &gb12GBTpcEUCVEnc16 },
+ { "GBpc-EUC-H", &gb12GBpcEUCHEnc16 },
+ { "GBpc-EUC-V", &gb12GBpcEUCVEnc16 },
+ { "UniGB-UCS2-H", &gb12UniGBUCS2HEnc16 },
+ { "UniGB-UCS2-V", &gb12UniGBUCS2VEnc16 },
+ { "Identity-H", &gb12AdobeGB12Enc16 },
+ { "Identity-V", &gb12AdobeGB12VEnc16 },
+ { NULL, NULL }
+};
+
+#endif
diff --git a/pdftops/GHash.cxx b/pdftops/GHash.cxx
new file mode 100644
index 000000000..4e25ce168
--- /dev/null
+++ b/pdftops/GHash.cxx
@@ -0,0 +1,241 @@
+//========================================================================
+//
+// GHash.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "GString.h"
+#include "GHash.h"
+
+//------------------------------------------------------------------------
+
+struct GHashBucket {
+ GString *key;
+ void *val;
+ GHashBucket *next;
+};
+
+struct GHashIter {
+ int h;
+ GHashBucket *p;
+};
+
+//------------------------------------------------------------------------
+
+GHash::GHash(GBool deleteKeysA) {
+ int h;
+
+ deleteKeys = deleteKeysA;
+ size = 7;
+ tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
+ for (h = 0; h < size; ++h) {
+ tab[h] = NULL;
+ }
+ len = 0;
+}
+
+GHash::~GHash() {
+ GHashBucket *p;
+ int h;
+
+ for (h = 0; h < size; ++h) {
+ while (tab[h]) {
+ p = tab[h];
+ tab[h] = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ delete p;
+ }
+ }
+ gfree(tab);
+}
+
+void GHash::add(GString *key, void *val) {
+ GHashBucket **oldTab;
+ GHashBucket *p;
+ int oldSize, i, h;
+
+ // expand the table if necessary
+ if (len >= size) {
+ oldSize = size;
+ oldTab = tab;
+ size = 2*size + 1;
+ tab = (GHashBucket **)gmalloc(size * sizeof(GHashBucket *));
+ for (h = 0; h < size; ++h) {
+ tab[h] = NULL;
+ }
+ for (i = 0; i < oldSize; ++i) {
+ while (oldTab[i]) {
+ p = oldTab[i];
+ oldTab[i] = oldTab[i]->next;
+ h = hash(p->key);
+ p->next = tab[h];
+ tab[h] = p;
+ }
+ }
+ gfree(oldTab);
+ }
+
+ // add the new symbol
+ p = new GHashBucket;
+ p->key = key;
+ p->val = val;
+ h = hash(key);
+ p->next = tab[h];
+ tab[h] = p;
+ ++len;
+}
+
+void *GHash::lookup(GString *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ return p->val;
+}
+
+void *GHash::lookup(const char *key) {
+ GHashBucket *p;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ return p->val;
+}
+
+void *GHash::remove(GString *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ void *val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val;
+ delete p;
+ --len;
+ return val;
+}
+
+void *GHash::remove(const char *key) {
+ GHashBucket *p;
+ GHashBucket **q;
+ void *val;
+ int h;
+
+ if (!(p = find(key, &h))) {
+ return NULL;
+ }
+ q = &tab[h];
+ while (*q != p) {
+ q = &((*q)->next);
+ }
+ *q = p->next;
+ if (deleteKeys) {
+ delete p->key;
+ }
+ val = p->val;
+ delete p;
+ --len;
+ return val;
+}
+
+void GHash::startIter(GHashIter **iter) {
+ *iter = new GHashIter;
+ (*iter)->h = -1;
+ (*iter)->p = NULL;
+}
+
+GBool GHash::getNext(GHashIter **iter, GString **key, void **val) {
+ if (!*iter) {
+ return gFalse;
+ }
+ if ((*iter)->p) {
+ (*iter)->p = (*iter)->p->next;
+ }
+ while (!(*iter)->p) {
+ if (++(*iter)->h == size) {
+ delete *iter;
+ *iter = NULL;
+ return gFalse;
+ }
+ (*iter)->p = tab[(*iter)->h];
+ }
+ *key = (*iter)->p->key;
+ *val = (*iter)->p->val;
+ return gTrue;
+}
+
+void GHash::killIter(GHashIter **iter) {
+ delete *iter;
+ *iter = NULL;
+}
+
+GHashBucket *GHash::find(GString *key, int *h) {
+ GHashBucket *p;
+
+ *h = hash(key);
+ for (p = tab[*h]; p; p = p->next) {
+ if (!p->key->cmp(key)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+GHashBucket *GHash::find(const char *key, int *h) {
+ GHashBucket *p;
+
+ *h = hash(key);
+ for (p = tab[*h]; p; p = p->next) {
+ if (!p->key->cmp(key)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+int GHash::hash(GString *key) {
+ const char *p;
+ unsigned int h;
+ int i;
+
+ h = 0;
+ for (p = key->getCString(), i = 0; i < key->getLength(); ++p, ++i) {
+ h = 17 * h + (int)(*p & 0xff);
+ }
+ return (int)(h % size);
+}
+
+int GHash::hash(const char *key) {
+ const char *p;
+ unsigned int h;
+
+ h = 0;
+ for (p = key; *p; ++p) {
+ h = 17 * h + (int)(*p & 0xff);
+ }
+ return (int)(h % size);
+}
diff --git a/pdftops/GHash.h b/pdftops/GHash.h
new file mode 100644
index 000000000..f768e8b82
--- /dev/null
+++ b/pdftops/GHash.h
@@ -0,0 +1,69 @@
+//========================================================================
+//
+// GHash.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GHASH_H
+#define GHASH_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+class GString;
+struct GHashBucket;
+struct GHashIter;
+
+//------------------------------------------------------------------------
+
+class GHash {
+public:
+
+ GHash(GBool deleteKeysA = gFalse);
+ ~GHash();
+ void add(GString *key, void *val);
+ void *lookup(GString *key);
+ void *lookup(const char *key);
+ void *remove(GString *key);
+ void *remove(const char *key);
+ int getLength() { return len; }
+ void startIter(GHashIter **iter);
+ GBool getNext(GHashIter **iter, GString **key, void **val);
+ void killIter(GHashIter **iter);
+
+private:
+
+ GHashBucket *find(GString *key, int *h);
+ GHashBucket *find(const char *key, int *h);
+ int hash(GString *key);
+ int hash(const char *key);
+
+ GBool deleteKeys; // set if key strings should be deleted
+ int size; // number of buckets
+ int len; // number of entries
+ GHashBucket **tab;
+};
+
+#define deleteGHash(hash, T) \
+ do { \
+ GHash *_hash = (hash); \
+ { \
+ GHashIter *_iter; \
+ GString *_key; \
+ void *_p; \
+ _hash->startIter(&_iter); \
+ while (_hash->getNext(&_iter, &_key, &_p)) { \
+ delete (T*)_p; \
+ } \
+ delete _hash; \
+ } \
+ } while(0)
+
+#endif
diff --git a/pdftops/GList.cxx b/pdftops/GList.cxx
new file mode 100644
index 000000000..50c9bcfa7
--- /dev/null
+++ b/pdftops/GList.cxx
@@ -0,0 +1,92 @@
+//========================================================================
+//
+// GList.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "GList.h"
+
+//------------------------------------------------------------------------
+// GList
+//------------------------------------------------------------------------
+
+GList::GList() {
+ size = 8;
+ data = (void **)gmalloc(size * sizeof(void*));
+ length = 0;
+ inc = 0;
+}
+
+GList::GList(int sizeA) {
+ size = sizeA;
+ data = (void **)gmalloc(size * sizeof(void*));
+ length = 0;
+ inc = 0;
+}
+
+GList::~GList() {
+ gfree(data);
+}
+
+void GList::append(void *p) {
+ if (length >= size) {
+ expand();
+ }
+ data[length++] = p;
+}
+
+void GList::append(GList *list) {
+ int i;
+
+ while (length + list->length > size) {
+ expand();
+ }
+ for (i = 0; i < list->length; ++i) {
+ data[length++] = list->data[i];
+ }
+}
+
+void GList::insert(int i, void *p) {
+ if (length >= size) {
+ expand();
+ }
+ if (i < length) {
+ memmove(data+i+1, data+i, (length - i) * sizeof(void *));
+ }
+ data[i] = p;
+ ++length;
+}
+
+void *GList::del(int i) {
+ void *p;
+
+ p = data[i];
+ if (i < length - 1) {
+ memmove(data+i, data+i+1, (length - i - 1) * sizeof(void *));
+ }
+ --length;
+ if (size - length >= ((inc > 0) ? inc : size/2)) {
+ shrink();
+ }
+ return p;
+}
+
+void GList::expand() {
+ size += (inc > 0) ? inc : size;
+ data = (void **)grealloc(data, size * sizeof(void*));
+}
+
+void GList::shrink() {
+ size -= (inc > 0) ? inc : size/2;
+ data = (void **)grealloc(data, size * sizeof(void*));
+}
diff --git a/pdftops/GList.h b/pdftops/GList.h
new file mode 100644
index 000000000..3ef17e33e
--- /dev/null
+++ b/pdftops/GList.h
@@ -0,0 +1,91 @@
+//========================================================================
+//
+// GList.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GLIST_H
+#define GLIST_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+// GList
+//------------------------------------------------------------------------
+
+class GList {
+public:
+
+ // Create an empty list.
+ GList();
+
+ // Create an empty list with space for <size1> elements.
+ GList(int sizeA);
+
+ // Destructor - does not free pointed-to objects.
+ ~GList();
+
+ //----- general
+
+ // Get the number of elements.
+ int getLength() { return length; }
+
+ //----- ordered list support
+
+ // Return the <i>th element.
+ // Assumes 0 <= i < length.
+ void *get(int i) { return data[i]; }
+
+ // Append an element to the end of the list.
+ void append(void *p);
+
+ // Append another list to the end of this one.
+ void append(GList *list);
+
+ // Insert an element at index <i>.
+ // Assumes 0 <= i <= length.
+ void insert(int i, void *p);
+
+ // Deletes and returns the element at index <i>.
+ // Assumes 0 <= i < length.
+ void *del(int i);
+
+ //----- control
+
+ // Set allocation increment to <inc>. If inc > 0, that many
+ // elements will be allocated every time the list is expanded.
+ // If inc <= 0, the list will be doubled in size.
+ void setAllocIncr(int incA) { inc = incA; }
+
+private:
+
+ void expand();
+ void shrink();
+
+ void **data; // the list elements
+ int size; // size of data array
+ int length; // number of elements on list
+ int inc; // allocation increment
+};
+
+#define deleteGList(list, T) \
+ do { \
+ GList *_list = (list); \
+ { \
+ int _i; \
+ for (_i = 0; _i < _list->getLength(); ++_i) { \
+ delete (T*)_list->get(_i); \
+ } \
+ delete _list; \
+ } \
+ } while (0)
+
+#endif
diff --git a/pdftops/GString.cxx b/pdftops/GString.cxx
new file mode 100644
index 000000000..f17599aa3
--- /dev/null
+++ b/pdftops/GString.cxx
@@ -0,0 +1,236 @@
+//========================================================================
+//
+// GString.cc
+//
+// Simple variable-length string type.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include "gtypes.h"
+#include "GString.h"
+
+static inline int size(int len) {
+ int delta;
+
+ delta = len < 256 ? 7 : 255;
+ return ((len + 1) + delta) & ~delta;
+}
+
+inline void GString::resize(int length1) {
+ char *s1;
+
+ if (!s) {
+ s = new char[size(length1)];
+ } else if (size(length1) != size(length)) {
+ s1 = new char[size(length1)];
+ memcpy(s1, s, length + 1);
+ delete[] s;
+ s = s1;
+ }
+}
+
+GString::GString() {
+ s = NULL;
+ resize(length = 0);
+ s[0] = '\0';
+}
+
+GString::GString(const char *sA) {
+ int n = strlen(sA);
+
+ s = NULL;
+ resize(length = n);
+ memcpy(s, sA, n + 1);
+}
+
+GString::GString(const char *sA, int lengthA) {
+ s = NULL;
+ resize(length = lengthA);
+ memcpy(s, sA, length * sizeof(char));
+ s[length] = '\0';
+}
+
+GString::GString(GString *str, int idx, int lengthA) {
+ s = NULL;
+ resize(length = lengthA);
+ memcpy(s, str->getCString() + idx, length);
+ s[length] = '\0';
+}
+
+GString::GString(GString *str) {
+ s = NULL;
+ resize(length = str->getLength());
+ memcpy(s, str->getCString(), length + 1);
+}
+
+GString::GString(GString *str1, GString *str2) {
+ int n1 = str1->getLength();
+ int n2 = str2->getLength();
+
+ s = NULL;
+ resize(length = n1 + n2);
+ memcpy(s, str1->getCString(), n1);
+ memcpy(s + n1, str2->getCString(), n2 + 1);
+}
+
+GString *GString::fromInt(int x) {
+ char buf[24]; // enough space for 64-bit ints plus a little extra
+ GBool neg;
+ Guint y;
+ int i;
+
+ i = 24;
+ if (x == 0) {
+ buf[--i] = '0';
+ } else {
+ if ((neg = x < 0)) {
+ y = (Guint)-x;
+ } else {
+ y = (Guint)x;
+ }
+ while (i > 0 && y > 0) {
+ buf[--i] = '0' + y % 10;
+ y /= 10;
+ }
+ if (neg && i > 0) {
+ buf[--i] = '-';
+ }
+ }
+ return new GString(buf + i, 24 - i);
+}
+
+GString::~GString() {
+ delete[] s;
+}
+
+GString *GString::clear() {
+ s[length = 0] = '\0';
+ resize(0);
+ return this;
+}
+
+GString *GString::append(char c) {
+ resize(length + 1);
+ s[length++] = c;
+ s[length] = '\0';
+ return this;
+}
+
+GString *GString::append(GString *str) {
+ int n = str->getLength();
+
+ resize(length + n);
+ memcpy(s + length, str->getCString(), n + 1);
+ length += n;
+ return this;
+}
+
+GString *GString::append(const char *str) {
+ int n = strlen(str);
+
+ resize(length + n);
+ memcpy(s + length, str, n + 1);
+ length += n;
+ return this;
+}
+
+GString *GString::append(const char *str, int lengthA) {
+ resize(length + lengthA);
+ memcpy(s + length, str, lengthA);
+ length += lengthA;
+ s[length] = '\0';
+ return this;
+}
+
+GString *GString::insert(int i, char c) {
+ int j;
+
+ resize(length + 1);
+ for (j = length + 1; j > i; --j)
+ s[j] = s[j-1];
+ s[i] = c;
+ ++length;
+ return this;
+}
+
+GString *GString::insert(int i, GString *str) {
+ int n = str->getLength();
+ int j;
+
+ resize(length + n);
+ for (j = length; j >= i; --j)
+ s[j+n] = s[j];
+ memcpy(s+i, str->getCString(), n);
+ length += n;
+ return this;
+}
+
+GString *GString::insert(int i, const char *str) {
+ int n = strlen(str);
+ int j;
+
+ resize(length + n);
+ for (j = length; j >= i; --j)
+ s[j+n] = s[j];
+ memcpy(s+i, str, n);
+ length += n;
+ return this;
+}
+
+GString *GString::insert(int i, const char *str, int lengthA) {
+ int j;
+
+ resize(length + lengthA);
+ for (j = length; j >= i; --j)
+ s[j+lengthA] = s[j];
+ memcpy(s+i, str, lengthA);
+ length += lengthA;
+ return this;
+}
+
+GString *GString::del(int i, int n) {
+ int j;
+
+ if (n > 0) {
+ if (i + n > length) {
+ n = length - i;
+ }
+ for (j = i; j <= length - n; ++j) {
+ s[j] = s[j + n];
+ }
+ resize(length -= n);
+ }
+ return this;
+}
+
+GString *GString::upperCase() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ if (islower(s[i]))
+ s[i] = toupper(s[i]);
+ }
+ return this;
+}
+
+GString *GString::lowerCase() {
+ int i;
+
+ for (i = 0; i < length; ++i) {
+ if (isupper(s[i]))
+ s[i] = tolower(s[i]);
+ }
+ return this;
+}
diff --git a/pdftops/GString.h b/pdftops/GString.h
new file mode 100644
index 000000000..7fec9cc0f
--- /dev/null
+++ b/pdftops/GString.h
@@ -0,0 +1,100 @@
+//========================================================================
+//
+// GString.h
+//
+// Simple variable-length string type.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GSTRING_H
+#define GSTRING_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <string.h>
+
+class GString {
+public:
+
+ // Create an empty string.
+ GString();
+
+ // Create a string from a C string.
+ GString(const char *sA);
+
+ // Create a string from <lengthA> chars at <sA>. This string
+ // can contain null characters.
+ GString(const char *sA, int lengthA);
+
+ // Create a string from <lengthA> chars at <idx> in <str>.
+ GString(GString *str, int idx, int lengthA);
+
+ // Copy a string.
+ GString(GString *str);
+ GString *copy() { return new GString(this); }
+
+ // Concatenate two strings.
+ GString(GString *str1, GString *str2);
+
+ // Convert an integer to a string.
+ static GString *fromInt(int x);
+
+ // Destructor.
+ ~GString();
+
+ // Get length.
+ int getLength() { return length; }
+
+ // Get C string.
+ char *getCString() { return s; }
+
+ // Get <i>th character.
+ char getChar(int i) { return s[i]; }
+
+ // Change <i>th character.
+ void setChar(int i, char c) { s[i] = c; }
+
+ // Clear string to zero length.
+ GString *clear();
+
+ // Append a character or string.
+ GString *append(char c);
+ GString *append(GString *str);
+ GString *append(const char *str);
+ GString *append(const char *str, int lengthA);
+
+ // Insert a character or string.
+ GString *insert(int i, char c);
+ GString *insert(int i, GString *str);
+ GString *insert(int i, const char *str);
+ GString *insert(int i, const char *str, int lengthA);
+
+ // Delete a character or range of characters.
+ GString *del(int i, int n = 1);
+
+ // Convert string to all-upper/all-lower case.
+ GString *upperCase();
+ GString *lowerCase();
+
+ // Compare two strings: -1:< 0:= +1:>
+ // These functions assume the strings do not contain null characters.
+ int cmp(GString *str) { return strcmp(s, str->getCString()); }
+ int cmpN(GString *str, int n) { return strncmp(s, str->getCString(), n); }
+ int cmp(const char *sA) { return strcmp(s, sA); }
+ int cmpN(const char *sA, int n) { return strncmp(s, sA, n); }
+
+private:
+
+ int length;
+ char *s;
+
+ void resize(int length1);
+};
+
+#endif
diff --git a/pdftops/Gfx.cxx b/pdftops/Gfx.cxx
new file mode 100644
index 000000000..26596f0dc
--- /dev/null
+++ b/pdftops/Gfx.cxx
@@ -0,0 +1,3101 @@
+//========================================================================
+//
+// Gfx.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include "gmem.h"
+#include "GlobalParams.h"
+#include "CharTypes.h"
+#include "Object.h"
+#include "Array.h"
+#include "Dict.h"
+#include "Stream.h"
+#include "Lexer.h"
+#include "Parser.h"
+#include "GfxFont.h"
+#include "GfxState.h"
+#include "OutputDev.h"
+#include "Page.h"
+#include "Error.h"
+#include "Gfx.h"
+
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+//------------------------------------------------------------------------
+// constants
+//------------------------------------------------------------------------
+
+// Max recursive depth for a function shading fill.
+#define functionMaxDepth 6
+
+// Max delta allowed in any color component for a function shading fill.
+#define functionColorDelta (1 / 256.0)
+
+// Max number of splits along the t axis for an axial shading fill.
+#define axialMaxSplits 256
+
+// Max delta allowed in any color component for an axial shading fill.
+#define axialColorDelta (1 / 256.0)
+
+// Max number of splits along the t axis for a radial shading fill.
+#define radialMaxSplits 256
+
+// Max delta allowed in any color component for a radial shading fill.
+#define radialColorDelta (1 / 256.0)
+
+//------------------------------------------------------------------------
+// Operator table
+//------------------------------------------------------------------------
+
+#ifdef WIN32 // this works around a bug in the VC7 compiler
+# pragma optimize("",off)
+#endif
+
+Operator Gfx::opTab[] = {
+ {"\"", 3, {tchkNum, tchkNum, tchkString},
+ &Gfx::opMoveSetShowText},
+ {"'", 1, {tchkString},
+ &Gfx::opMoveShowText},
+ {"B", 0, {tchkNone},
+ &Gfx::opFillStroke},
+ {"B*", 0, {tchkNone},
+ &Gfx::opEOFillStroke},
+ {"BDC", 2, {tchkName, tchkProps},
+ &Gfx::opBeginMarkedContent},
+ {"BI", 0, {tchkNone},
+ &Gfx::opBeginImage},
+ {"BMC", 1, {tchkName},
+ &Gfx::opBeginMarkedContent},
+ {"BT", 0, {tchkNone},
+ &Gfx::opBeginText},
+ {"BX", 0, {tchkNone},
+ &Gfx::opBeginIgnoreUndef},
+ {"CS", 1, {tchkName},
+ &Gfx::opSetStrokeColorSpace},
+ {"DP", 2, {tchkName, tchkProps},
+ &Gfx::opMarkPoint},
+ {"Do", 1, {tchkName},
+ &Gfx::opXObject},
+ {"EI", 0, {tchkNone},
+ &Gfx::opEndImage},
+ {"EMC", 0, {tchkNone},
+ &Gfx::opEndMarkedContent},
+ {"ET", 0, {tchkNone},
+ &Gfx::opEndText},
+ {"EX", 0, {tchkNone},
+ &Gfx::opEndIgnoreUndef},
+ {"F", 0, {tchkNone},
+ &Gfx::opFill},
+ {"G", 1, {tchkNum},
+ &Gfx::opSetStrokeGray},
+ {"ID", 0, {tchkNone},
+ &Gfx::opImageData},
+ {"J", 1, {tchkInt},
+ &Gfx::opSetLineCap},
+ {"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetStrokeCMYKColor},
+ {"M", 1, {tchkNum},
+ &Gfx::opSetMiterLimit},
+ {"MP", 1, {tchkName},
+ &Gfx::opMarkPoint},
+ {"Q", 0, {tchkNone},
+ &Gfx::opRestore},
+ {"RG", 3, {tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetStrokeRGBColor},
+ {"S", 0, {tchkNone},
+ &Gfx::opStroke},
+ {"SC", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetStrokeColor},
+ {"SCN", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
+ tchkSCN},
+ &Gfx::opSetStrokeColorN},
+ {"T*", 0, {tchkNone},
+ &Gfx::opTextNextLine},
+ {"TD", 2, {tchkNum, tchkNum},
+ &Gfx::opTextMoveSet},
+ {"TJ", 1, {tchkArray},
+ &Gfx::opShowSpaceText},
+ {"TL", 1, {tchkNum},
+ &Gfx::opSetTextLeading},
+ {"Tc", 1, {tchkNum},
+ &Gfx::opSetCharSpacing},
+ {"Td", 2, {tchkNum, tchkNum},
+ &Gfx::opTextMove},
+ {"Tf", 2, {tchkName, tchkNum},
+ &Gfx::opSetFont},
+ {"Tj", 1, {tchkString},
+ &Gfx::opShowText},
+ {"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
+ tchkNum, tchkNum},
+ &Gfx::opSetTextMatrix},
+ {"Tr", 1, {tchkInt},
+ &Gfx::opSetTextRender},
+ {"Ts", 1, {tchkNum},
+ &Gfx::opSetTextRise},
+ {"Tw", 1, {tchkNum},
+ &Gfx::opSetWordSpacing},
+ {"Tz", 1, {tchkNum},
+ &Gfx::opSetHorizScaling},
+ {"W", 0, {tchkNone},
+ &Gfx::opClip},
+ {"W*", 0, {tchkNone},
+ &Gfx::opEOClip},
+ {"b", 0, {tchkNone},
+ &Gfx::opCloseFillStroke},
+ {"b*", 0, {tchkNone},
+ &Gfx::opCloseEOFillStroke},
+ {"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
+ tchkNum, tchkNum},
+ &Gfx::opCurveTo},
+ {"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
+ tchkNum, tchkNum},
+ &Gfx::opConcat},
+ {"cs", 1, {tchkName},
+ &Gfx::opSetFillColorSpace},
+ {"d", 2, {tchkArray, tchkNum},
+ &Gfx::opSetDash},
+ {"d0", 2, {tchkNum, tchkNum},
+ &Gfx::opSetCharWidth},
+ {"d1", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
+ tchkNum, tchkNum},
+ &Gfx::opSetCacheDevice},
+ {"f", 0, {tchkNone},
+ &Gfx::opFill},
+ {"f*", 0, {tchkNone},
+ &Gfx::opEOFill},
+ {"g", 1, {tchkNum},
+ &Gfx::opSetFillGray},
+ {"gs", 1, {tchkName},
+ &Gfx::opSetExtGState},
+ {"h", 0, {tchkNone},
+ &Gfx::opClosePath},
+ {"i", 1, {tchkNum},
+ &Gfx::opSetFlat},
+ {"j", 1, {tchkInt},
+ &Gfx::opSetLineJoin},
+ {"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetFillCMYKColor},
+ {"l", 2, {tchkNum, tchkNum},
+ &Gfx::opLineTo},
+ {"m", 2, {tchkNum, tchkNum},
+ &Gfx::opMoveTo},
+ {"n", 0, {tchkNone},
+ &Gfx::opEndPath},
+ {"q", 0, {tchkNone},
+ &Gfx::opSave},
+ {"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opRectangle},
+ {"rg", 3, {tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetFillRGBColor},
+ {"ri", 1, {tchkName},
+ &Gfx::opSetRenderingIntent},
+ {"s", 0, {tchkNone},
+ &Gfx::opCloseStroke},
+ {"sc", -4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opSetFillColor},
+ {"scn", -5, {tchkSCN, tchkSCN, tchkSCN, tchkSCN,
+ tchkSCN},
+ &Gfx::opSetFillColorN},
+ {"sh", 1, {tchkName},
+ &Gfx::opShFill},
+ {"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opCurveTo1},
+ {"w", 1, {tchkNum},
+ &Gfx::opSetLineWidth},
+ {"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
+ &Gfx::opCurveTo2},
+};
+
+#ifdef WIN32 // this works around a bug in the VC7 compiler
+# pragma optimize("",on)
+#endif
+
+#define numOps (sizeof(opTab) / sizeof(Operator))
+
+//------------------------------------------------------------------------
+// GfxResources
+//------------------------------------------------------------------------
+
+GfxResources::GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA) {
+ Object obj1, obj2;
+ Ref r;
+
+ if (resDict) {
+
+ // build font dictionary
+ fonts = NULL;
+ resDict->lookupNF("Font", &obj1);
+ if (obj1.isRef()) {
+ obj1.fetch(xref, &obj2);
+ if (obj2.isDict()) {
+ r = obj1.getRef();
+ fonts = new GfxFontDict(xref, &r, obj2.getDict());
+ }
+ obj2.free();
+ } else if (obj1.isDict()) {
+ fonts = new GfxFontDict(xref, NULL, obj1.getDict());
+ }
+ obj1.free();
+
+ // get XObject dictionary
+ resDict->lookup("XObject", &xObjDict);
+
+ // get color space dictionary
+ resDict->lookup("ColorSpace", &colorSpaceDict);
+
+ // get pattern dictionary
+ resDict->lookup("Pattern", &patternDict);
+
+ // get shading dictionary
+ resDict->lookup("Shading", &shadingDict);
+
+ // get graphics state parameter dictionary
+ resDict->lookup("ExtGState", &gStateDict);
+
+ } else {
+ fonts = NULL;
+ xObjDict.initNull();
+ colorSpaceDict.initNull();
+ patternDict.initNull();
+ shadingDict.initNull();
+ gStateDict.initNull();
+ }
+
+ next = nextA;
+}
+
+GfxResources::~GfxResources() {
+ if (fonts) {
+ delete fonts;
+ }
+ xObjDict.free();
+ colorSpaceDict.free();
+ patternDict.free();
+ shadingDict.free();
+ gStateDict.free();
+}
+
+GfxFont *GfxResources::lookupFont(char *name) {
+ GfxFont *font;
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->fonts) {
+ if ((font = resPtr->fonts->lookup(name)))
+ return font;
+ }
+ }
+ error(-1, "Unknown font tag '%s'", name);
+ return NULL;
+}
+
+GBool GfxResources::lookupXObject(char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->xObjDict.isDict()) {
+ if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
+ return gTrue;
+ obj->free();
+ }
+ }
+ error(-1, "XObject '%s' is unknown", name);
+ return gFalse;
+}
+
+GBool GfxResources::lookupXObjectNF(char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->xObjDict.isDict()) {
+ if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
+ return gTrue;
+ obj->free();
+ }
+ }
+ error(-1, "XObject '%s' is unknown", name);
+ return gFalse;
+}
+
+void GfxResources::lookupColorSpace(char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->colorSpaceDict.isDict()) {
+ if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
+ return;
+ }
+ obj->free();
+ }
+ }
+ obj->initNull();
+}
+
+GfxPattern *GfxResources::lookupPattern(char *name) {
+ GfxResources *resPtr;
+ GfxPattern *pattern;
+ Object obj;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->patternDict.isDict()) {
+ if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
+ pattern = GfxPattern::parse(&obj);
+ obj.free();
+ return pattern;
+ }
+ obj.free();
+ }
+ }
+ error(-1, "Unknown pattern '%s'", name);
+ return NULL;
+}
+
+GfxShading *GfxResources::lookupShading(char *name) {
+ GfxResources *resPtr;
+ GfxShading *shading;
+ Object obj;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->shadingDict.isDict()) {
+ if (!resPtr->shadingDict.dictLookup(name, &obj)->isNull()) {
+ shading = GfxShading::parse(&obj);
+ obj.free();
+ return shading;
+ }
+ obj.free();
+ }
+ }
+ error(-1, "Unknown shading '%s'", name);
+ return NULL;
+}
+
+GBool GfxResources::lookupGState(char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->gStateDict.isDict()) {
+ if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
+ return gTrue;
+ }
+ obj->free();
+ }
+ }
+ error(-1, "ExtGState '%s' is unknown", name);
+ return gFalse;
+}
+
+//------------------------------------------------------------------------
+// Gfx
+//------------------------------------------------------------------------
+
+Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+ double hDPI, double vDPI, PDFRectangle *box, GBool crop,
+ PDFRectangle *cropBox, int rotate,
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
+ int i;
+
+ xref = xrefA;
+ subPage = gFalse;
+ printCommands = globalParams->getPrintCommands();
+
+ // start the resource stack
+ res = new GfxResources(xref, resDict, NULL);
+
+ // initialize
+ out = outA;
+ state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown());
+ fontChanged = gFalse;
+ clip = clipNone;
+ ignoreUndef = 0;
+ out->startPage(pageNum, state);
+ out->setDefaultCTM(state->getCTM());
+ out->updateAll(state);
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = state->getCTM()[i];
+ }
+ formDepth = 0;
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
+
+ // set crop box
+ if (crop) {
+ state->moveTo(cropBox->x1, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y2);
+ state->lineTo(cropBox->x1, cropBox->y2);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+}
+
+Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data),
+ void *abortCheckCbkDataA) {
+ int i;
+
+ xref = xrefA;
+ subPage = gTrue;
+ printCommands = globalParams->getPrintCommands();
+
+ // start the resource stack
+ res = new GfxResources(xref, resDict, NULL);
+
+ // initialize
+ out = outA;
+ state = new GfxState(72, 72, box, 0, gFalse);
+ fontChanged = gFalse;
+ clip = clipNone;
+ ignoreUndef = 0;
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = state->getCTM()[i];
+ }
+ formDepth = 0;
+ abortCheckCbk = abortCheckCbkA;
+ abortCheckCbkData = abortCheckCbkDataA;
+
+ // set crop box
+ if (crop) {
+ state->moveTo(cropBox->x1, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y1);
+ state->lineTo(cropBox->x2, cropBox->y2);
+ state->lineTo(cropBox->x1, cropBox->y2);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+}
+
+Gfx::~Gfx() {
+ while (state->hasSaves()) {
+ restoreState();
+ }
+ if (!subPage) {
+ out->endPage();
+ }
+ while (res) {
+ popResources();
+ }
+ if (state) {
+ delete state;
+ }
+}
+
+void Gfx::display(Object *obj, GBool topLevel) {
+ Object obj2;
+ int i;
+
+ if (obj->isArray()) {
+ for (i = 0; i < obj->arrayGetLength(); ++i) {
+ obj->arrayGet(i, &obj2);
+ if (!obj2.isStream()) {
+ error(-1, "Weird page contents");
+ obj2.free();
+ return;
+ }
+ obj2.free();
+ }
+ } else if (!obj->isStream()) {
+ error(-1, "Weird page contents");
+ return;
+ }
+ parser = new Parser(xref, new Lexer(xref, obj));
+ go(topLevel);
+ delete parser;
+ parser = NULL;
+}
+
+void Gfx::go(GBool topLevel) {
+ Object obj;
+ Object args[maxArgs];
+ int numArgs, i;
+ int lastAbortCheck;
+
+ // scan a sequence of objects
+ updateLevel = lastAbortCheck = 0;
+ numArgs = 0;
+ parser->getObj(&obj);
+ while (!obj.isEOF()) {
+
+ // got a command - execute it
+ if (obj.isCmd()) {
+ if (printCommands) {
+ fputs("DEBUG2: ", stderr);
+ obj.print(stderr);
+ for (i = 0; i < numArgs; ++i) {
+ putc(' ', stderr);
+ args[i].print(stderr);
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+ execOp(&obj, args, numArgs);
+ obj.free();
+ for (i = 0; i < numArgs; ++i)
+ args[i].free();
+ numArgs = 0;
+
+ // periodically update display
+ if (++updateLevel >= 20000) {
+ out->dump();
+ updateLevel = 0;
+ }
+
+ // check for an abort
+ if (abortCheckCbk) {
+ if (updateLevel - lastAbortCheck > 10) {
+ if ((*abortCheckCbk)(abortCheckCbkData)) {
+ break;
+ }
+ lastAbortCheck = updateLevel;
+ }
+ }
+
+ // got an argument - save it
+ } else if (numArgs < maxArgs) {
+ args[numArgs++] = obj;
+
+ // too many arguments - something is wrong
+ } else {
+ error(getPos(), "Too many args in content stream");
+ if (printCommands) {
+ fputs("DEBUG2: throwing away arg: ", stderr);
+ obj.print(stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+ obj.free();
+ }
+
+ // grab the next object
+ parser->getObj(&obj);
+ }
+ obj.free();
+
+ // args at end with no command
+ if (numArgs > 0) {
+ error(getPos(), "Leftover args in content stream");
+ if (printCommands) {
+ fprintf(stderr, "DEBUG2: %d leftovers:", numArgs);
+ for (i = 0; i < numArgs; ++i) {
+ putc(' ', stderr);
+ args[i].print(stderr);
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+ for (i = 0; i < numArgs; ++i)
+ args[i].free();
+ }
+
+ // update display
+ if (topLevel && updateLevel > 0) {
+ out->dump();
+ }
+}
+
+void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
+ Operator *op;
+ char *name;
+ Object *argPtr;
+ int i;
+
+ // find operator
+ name = cmd->getCmd();
+ if (!(op = findOp(name))) {
+ if (ignoreUndef == 0)
+ error(getPos(), "Unknown operator '%s'", name);
+ return;
+ }
+
+ // type check args
+ argPtr = args;
+ if (op->numArgs >= 0) {
+ if (numArgs < op->numArgs) {
+ error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
+ return;
+ }
+ if (numArgs > op->numArgs) {
+#if 0
+ error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name);
+#endif
+ argPtr += numArgs - op->numArgs;
+ numArgs = op->numArgs;
+ }
+ } else {
+ if (numArgs > -op->numArgs) {
+ error(getPos(), "Too many (%d) args to '%s' operator",
+ numArgs, name);
+ return;
+ }
+ }
+ for (i = 0; i < numArgs; ++i) {
+ if (!checkArg(&argPtr[i], op->tchk[i])) {
+ error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)",
+ i, name, argPtr[i].getTypeName());
+ return;
+ }
+ }
+
+ // do it
+ (this->*op->func)(argPtr, numArgs);
+}
+
+Operator *Gfx::findOp(char *name) {
+ int a, b, m, cmp;
+
+ a = -1;
+ b = numOps;
+ // invariant: opTab[a] < name < opTab[b]
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ cmp = strcmp(opTab[m].name, name);
+ if (cmp < 0)
+ a = m;
+ else if (cmp > 0)
+ b = m;
+ else
+ a = b = m;
+ }
+ if (cmp != 0)
+ return NULL;
+ return &opTab[a];
+}
+
+GBool Gfx::checkArg(Object *arg, TchkType type) {
+ switch (type) {
+ case tchkBool: return arg->isBool();
+ case tchkInt: return arg->isInt();
+ case tchkNum: return arg->isNum();
+ case tchkString: return arg->isString();
+ case tchkName: return arg->isName();
+ case tchkArray: return arg->isArray();
+ case tchkProps: return arg->isDict() || arg->isName();
+ case tchkSCN: return arg->isNum() || arg->isName();
+ case tchkNone: return gFalse;
+ }
+ return gFalse;
+}
+
+int Gfx::getPos() {
+ return parser ? parser->getPos() : -1;
+}
+
+//------------------------------------------------------------------------
+// graphics state operators
+//------------------------------------------------------------------------
+
+void Gfx::opSave(Object args[], int numArgs) {
+ saveState();
+}
+
+void Gfx::opRestore(Object args[], int numArgs) {
+ restoreState();
+}
+
+void Gfx::opConcat(Object args[], int numArgs) {
+ state->concatCTM(args[0].getNum(), args[1].getNum(),
+ args[2].getNum(), args[3].getNum(),
+ args[4].getNum(), args[5].getNum());
+ out->updateCTM(state, args[0].getNum(), args[1].getNum(),
+ args[2].getNum(), args[3].getNum(),
+ args[4].getNum(), args[5].getNum());
+ fontChanged = gTrue;
+}
+
+void Gfx::opSetDash(Object args[], int numArgs) {
+ Array *a;
+ int length;
+ Object obj;
+ double *dash;
+ int i;
+
+ a = args[0].getArray();
+ length = a->getLength();
+ if (length == 0) {
+ dash = NULL;
+ } else {
+ dash = (double *)gmalloc(length * sizeof(double));
+ for (i = 0; i < length; ++i) {
+ dash[i] = a->get(i, &obj)->getNum();
+ obj.free();
+ }
+ }
+ state->setLineDash(dash, length, args[1].getNum());
+ out->updateLineDash(state);
+}
+
+void Gfx::opSetFlat(Object args[], int numArgs) {
+ state->setFlatness((int)args[0].getNum());
+ out->updateFlatness(state);
+}
+
+void Gfx::opSetLineJoin(Object args[], int numArgs) {
+ state->setLineJoin(args[0].getInt());
+ out->updateLineJoin(state);
+}
+
+void Gfx::opSetLineCap(Object args[], int numArgs) {
+ state->setLineCap(args[0].getInt());
+ out->updateLineCap(state);
+}
+
+void Gfx::opSetMiterLimit(Object args[], int numArgs) {
+ state->setMiterLimit(args[0].getNum());
+ out->updateMiterLimit(state);
+}
+
+void Gfx::opSetLineWidth(Object args[], int numArgs) {
+ state->setLineWidth(args[0].getNum());
+ out->updateLineWidth(state);
+}
+
+void Gfx::opSetExtGState(Object args[], int numArgs) {
+ Object obj1, obj2;
+
+ if (!res->lookupGState(args[0].getName(), &obj1)) {
+ return;
+ }
+ if (!obj1.isDict()) {
+ error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
+ obj1.free();
+ return;
+ }
+ if (obj1.dictLookup("ca", &obj2)->isNum()) {
+ state->setFillOpacity(obj2.getNum());
+ out->updateFillOpacity(state);
+ }
+ obj2.free();
+ if (obj1.dictLookup("CA", &obj2)->isNum()) {
+ state->setStrokeOpacity(obj2.getNum());
+ out->updateStrokeOpacity(state);
+ }
+ obj2.free();
+ obj1.free();
+}
+
+void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
+}
+
+//------------------------------------------------------------------------
+// color operators
+//------------------------------------------------------------------------
+
+void Gfx::opSetFillGray(Object args[], int numArgs) {
+ GfxColor color;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ color.c[0] = args[0].getNum();
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+}
+
+void Gfx::opSetStrokeGray(Object args[], int numArgs) {
+ GfxColor color;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+ color.c[0] = args[0].getNum();
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+}
+
+void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+ for (i = 0; i < 4; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+}
+
+void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
+ for (i = 0; i < 4; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+}
+
+void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ for (i = 0; i < 3; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+}
+
+void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+ for (i = 0; i < 3; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+}
+
+void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
+ Object obj;
+ GfxColorSpace *colorSpace;
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ res->lookupColorSpace(args[0].getName(), &obj);
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0]);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj);
+ }
+ obj.free();
+ if (colorSpace) {
+ state->setFillColorSpace(colorSpace);
+ } else {
+ error(getPos(), "Bad color space (fill)");
+ }
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ color.c[i] = 0;
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+}
+
+void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
+ Object obj;
+ GfxColorSpace *colorSpace;
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ res->lookupColorSpace(args[0].getName(), &obj);
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0]);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj);
+ }
+ obj.free();
+ if (colorSpace) {
+ state->setStrokeColorSpace(colorSpace);
+ } else {
+ error(getPos(), "Bad color space (stroke)");
+ }
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ color.c[i] = 0;
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+}
+
+void Gfx::opSetFillColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ for (i = 0; i < numArgs; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+}
+
+void Gfx::opSetStrokeColor(Object args[], int numArgs) {
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ for (i = 0; i < numArgs; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+}
+
+void Gfx::opSetFillColorN(Object args[], int numArgs) {
+ GfxColor color;
+ GfxPattern *pattern;
+ int i;
+
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ if (numArgs > 1) {
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+ }
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+ state->setFillPattern(pattern);
+ }
+
+ } else {
+ state->setFillPattern(NULL);
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+ }
+}
+
+void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
+ GfxColor color;
+ GfxPattern *pattern;
+ int i;
+
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ if (numArgs > 1) {
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+ }
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+ state->setStrokePattern(pattern);
+ }
+
+ } else {
+ state->setStrokePattern(NULL);
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+ }
+}
+
+//------------------------------------------------------------------------
+// path segment operators
+//------------------------------------------------------------------------
+
+void Gfx::opMoveTo(Object args[], int numArgs) {
+ state->moveTo(args[0].getNum(), args[1].getNum());
+}
+
+void Gfx::opLineTo(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ error(getPos(), "No current point in lineto");
+ return;
+ }
+ state->lineTo(args[0].getNum(), args[1].getNum());
+}
+
+void Gfx::opCurveTo(Object args[], int numArgs) {
+ double x1, y1, x2, y2, x3, y3;
+
+ if (!state->isCurPt()) {
+ error(getPos(), "No current point in curveto");
+ return;
+ }
+ x1 = args[0].getNum();
+ y1 = args[1].getNum();
+ x2 = args[2].getNum();
+ y2 = args[3].getNum();
+ x3 = args[4].getNum();
+ y3 = args[5].getNum();
+ state->curveTo(x1, y1, x2, y2, x3, y3);
+}
+
+void Gfx::opCurveTo1(Object args[], int numArgs) {
+ double x1, y1, x2, y2, x3, y3;
+
+ if (!state->isCurPt()) {
+ error(getPos(), "No current point in curveto1");
+ return;
+ }
+ x1 = state->getCurX();
+ y1 = state->getCurY();
+ x2 = args[0].getNum();
+ y2 = args[1].getNum();
+ x3 = args[2].getNum();
+ y3 = args[3].getNum();
+ state->curveTo(x1, y1, x2, y2, x3, y3);
+}
+
+void Gfx::opCurveTo2(Object args[], int numArgs) {
+ double x1, y1, x2, y2, x3, y3;
+
+ if (!state->isCurPt()) {
+ error(getPos(), "No current point in curveto2");
+ return;
+ }
+ x1 = args[0].getNum();
+ y1 = args[1].getNum();
+ x2 = args[2].getNum();
+ y2 = args[3].getNum();
+ x3 = x2;
+ y3 = y2;
+ state->curveTo(x1, y1, x2, y2, x3, y3);
+}
+
+void Gfx::opRectangle(Object args[], int numArgs) {
+ double x, y, w, h;
+
+ x = args[0].getNum();
+ y = args[1].getNum();
+ w = args[2].getNum();
+ h = args[3].getNum();
+ state->moveTo(x, y);
+ state->lineTo(x + w, y);
+ state->lineTo(x + w, y + h);
+ state->lineTo(x, y + h);
+ state->closePath();
+}
+
+void Gfx::opClosePath(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ error(getPos(), "No current point in closepath");
+ return;
+ }
+ state->closePath();
+}
+
+//------------------------------------------------------------------------
+// path painting operators
+//------------------------------------------------------------------------
+
+void Gfx::opEndPath(Object args[], int numArgs) {
+ doEndPath();
+}
+
+void Gfx::opStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in stroke");
+ return;
+ }
+ if (state->isPath())
+ out->stroke(state);
+ doEndPath();
+}
+
+void Gfx::opCloseStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in closepath/stroke");
+ return;
+ }
+ if (state->isPath()) {
+ state->closePath();
+ out->stroke(state);
+ }
+ doEndPath();
+}
+
+void Gfx::opFill(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in fill");
+ return;
+ }
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ }
+ doEndPath();
+}
+
+void Gfx::opEOFill(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in eofill");
+ return;
+ }
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ }
+ doEndPath();
+}
+
+void Gfx::opFillStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in fill/stroke");
+ return;
+ }
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ out->stroke(state);
+ }
+ doEndPath();
+}
+
+void Gfx::opCloseFillStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in closepath/fill/stroke");
+ return;
+ }
+ if (state->isPath()) {
+ state->closePath();
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ out->stroke(state);
+ }
+ doEndPath();
+}
+
+void Gfx::opEOFillStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in eofill/stroke");
+ return;
+ }
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ out->stroke(state);
+ }
+ doEndPath();
+}
+
+void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
+ if (!state->isCurPt()) {
+ //error(getPos(), "No path in closepath/eofill/stroke");
+ return;
+ }
+ if (state->isPath()) {
+ state->closePath();
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ out->stroke(state);
+ }
+ doEndPath();
+}
+
+void Gfx::doPatternFill(GBool eoFill) {
+ GfxPattern *pattern;
+
+ // this is a bit of a kludge -- patterns can be really slow, so we
+ // skip them if we're only doing text extraction, since they almost
+ // certainly don't contain any text
+ if (!out->needNonText()) {
+ return;
+ }
+
+ if (!(pattern = state->getFillPattern())) {
+ return;
+ }
+ switch (pattern->getType()) {
+ case 1:
+ doTilingPatternFill((GfxTilingPattern *)pattern, eoFill);
+ break;
+ case 2:
+ doShadingPatternFill((GfxShadingPattern *)pattern, eoFill);
+ break;
+ default:
+ error(getPos(), "Unimplemented pattern type (%d) in fill",
+ pattern->getType());
+ break;
+ }
+ }
+
+void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) {
+ GfxPatternColorSpace *patCS;
+ GfxColorSpace *cs;
+ double xMin, yMin, xMax, yMax, x, y, x1, y1;
+ double cxMin, cyMin, cxMax, cyMax;
+ int xi0, yi0, xi1, yi1, xi, yi;
+ double *ctm, *btm, *ptm;
+ double m[6], ictm[6], m1[6], imb[6];
+ double det;
+ double xstep, ystep;
+ int i;
+
+ // get color space
+ patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
+
+ // construct a (pattern space) -> (current space) transform matrix
+ ctm = state->getCTM();
+ btm = baseMatrix;
+ ptm = tPat->getMatrix();
+ // iCTM = invert CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ // m1 = PTM * BTM = PTM * base transform matrix
+ m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
+ m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
+ m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
+ m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
+ m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
+ m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
+ // m = m1 * iCTM = (PTM * BTM) * (iCTM)
+ m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
+ m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
+ m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
+ m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
+ m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
+ m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
+
+ // construct a (base space) -> (pattern space) transform matrix
+ det = 1 / (m1[0] * m1[3] - m1[1] * m1[2]);
+ imb[0] = m1[3] * det;
+ imb[1] = -m1[1] * det;
+ imb[2] = -m1[2] * det;
+ imb[3] = m1[0] * det;
+ imb[4] = (m1[2] * m1[5] - m1[3] * m1[4]) * det;
+ imb[5] = (m1[1] * m1[4] - m1[0] * m1[5]) * det;
+
+ // save current graphics state
+ saveState();
+
+ // set underlying color space (for uncolored tiling patterns); set
+ // various other parameters (stroke color, line width) to match
+ // Adobe's behavior
+ if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
+ state->setFillColorSpace(cs->copy());
+ state->setStrokeColorSpace(cs->copy());
+ state->setStrokeColor(state->getFillColor());
+ } else {
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+ }
+ state->setFillPattern(NULL);
+ out->updateFillColor(state);
+ state->setStrokePattern(NULL);
+ out->updateStrokeColor(state);
+ state->setLineWidth(0);
+ out->updateLineWidth(state);
+
+ // clip to current path
+ state->clip();
+ if (eoFill) {
+ out->eoClip(state);
+ } else {
+ out->clip(state);
+ }
+ state->clearPath();
+
+ // transform clip region bbox to pattern space
+ state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
+ xMin = xMax = cxMin * imb[0] + cyMin * imb[2] + imb[4];
+ yMin = yMax = cxMin * imb[1] + cyMin * imb[3] + imb[5];
+ x1 = cxMin * imb[0] + cyMax * imb[2] + imb[4];
+ y1 = cxMin * imb[1] + cyMax * imb[3] + imb[5];
+ if (x1 < xMin) {
+ xMin = x1;
+ } else if (x1 > xMax) {
+ xMax = x1;
+ }
+ if (y1 < yMin) {
+ yMin = y1;
+ } else if (y1 > yMax) {
+ yMax = y1;
+ }
+ x1 = cxMax * imb[0] + cyMin * imb[2] + imb[4];
+ y1 = cxMax * imb[1] + cyMin * imb[3] + imb[5];
+ if (x1 < xMin) {
+ xMin = x1;
+ } else if (x1 > xMax) {
+ xMax = x1;
+ }
+ if (y1 < yMin) {
+ yMin = y1;
+ } else if (y1 > yMax) {
+ yMax = y1;
+ }
+ x1 = cxMax * imb[0] + cyMax * imb[2] + imb[4];
+ y1 = cxMax * imb[1] + cyMax * imb[3] + imb[5];
+ if (x1 < xMin) {
+ xMin = x1;
+ } else if (x1 > xMax) {
+ xMax = x1;
+ }
+ if (y1 < yMin) {
+ yMin = y1;
+ } else if (y1 > yMax) {
+ yMax = y1;
+ }
+
+ // draw the pattern
+ //~ this should treat negative steps differently -- start at right/top
+ //~ edge instead of left/bottom (?)
+ xstep = fabs(tPat->getXStep());
+ ystep = fabs(tPat->getYStep());
+ xi0 = (int)floor(xMin / xstep);
+ xi1 = (int)ceil(xMax / xstep);
+ yi0 = (int)floor(yMin / ystep);
+ yi1 = (int)ceil(yMax / ystep);
+ for (i = 0; i < 4; ++i) {
+ m1[i] = m[i];
+ }
+ for (yi = yi0; yi < yi1; ++yi) {
+ for (xi = xi0; xi < xi1; ++xi) {
+ x = xi * xstep - tPat->getBBox()[0];
+ y = yi * ystep - tPat->getBBox()[1];
+ m1[4] = x * m[0] + y * m[2] + m[4];
+ m1[5] = x * m[1] + y * m[3] + m[5];
+ doForm1(tPat->getContentStream(), tPat->getResDict(),
+ m1, tPat->getBBox());
+ }
+ }
+
+ // restore graphics state
+ restoreState();
+}
+
+void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) {
+ GfxShading *shading;
+ double *ctm, *btm, *ptm;
+ double m[6], ictm[6], m1[6];
+ double xMin, yMin, xMax, yMax;
+ double det;
+
+ shading = sPat->getShading();
+
+ // save current graphics state
+ saveState();
+
+ // clip to bbox
+ if (shading->getHasBBox()) {
+ shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+
+ // clip to current path
+ state->clip();
+ if (eoFill) {
+ out->eoClip(state);
+ } else {
+ out->clip(state);
+ }
+ state->clearPath();
+
+ // construct a (pattern space) -> (current space) transform matrix
+ ctm = state->getCTM();
+ btm = baseMatrix;
+ ptm = sPat->getMatrix();
+ // iCTM = invert CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ // m1 = PTM * BTM = PTM * base transform matrix
+ m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
+ m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
+ m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
+ m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
+ m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
+ m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
+ // m = m1 * iCTM = (PTM * BTM) * (iCTM)
+ m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
+ m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
+ m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
+ m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
+ m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
+ m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
+
+ // set the new matrix
+ state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
+ out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
+
+ // set the color space
+ state->setFillColorSpace(shading->getColorSpace()->copy());
+
+ // do shading type-specific operations
+ switch (shading->getType()) {
+ case 1:
+ doFunctionShFill((GfxFunctionShading *)shading);
+ break;
+ case 2:
+ doAxialShFill((GfxAxialShading *)shading);
+ break;
+ case 3:
+ doRadialShFill((GfxRadialShading *)shading);
+ break;
+ }
+
+ // restore graphics state
+ restoreState();
+}
+
+void Gfx::opShFill(Object args[], int numArgs) {
+ GfxShading *shading;
+ double xMin, yMin, xMax, yMax;
+
+ if (!(shading = res->lookupShading(args[0].getName()))) {
+ return;
+ }
+
+ // save current graphics state
+ saveState();
+
+ // clip to bbox
+ if (shading->getHasBBox()) {
+ shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+ state->moveTo(xMin, yMin);
+ state->lineTo(xMax, yMin);
+ state->lineTo(xMax, yMax);
+ state->lineTo(xMin, yMax);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+ }
+
+ // set the color space
+ state->setFillColorSpace(shading->getColorSpace()->copy());
+
+ // do shading type-specific operations
+ switch (shading->getType()) {
+ case 1:
+ doFunctionShFill((GfxFunctionShading *)shading);
+ break;
+ case 2:
+ doAxialShFill((GfxAxialShading *)shading);
+ break;
+ case 3:
+ doRadialShFill((GfxRadialShading *)shading);
+ break;
+ }
+
+ // restore graphics state
+ restoreState();
+
+ delete shading;
+}
+
+void Gfx::doFunctionShFill(GfxFunctionShading *shading) {
+ double x0, y0, x1, y1;
+ GfxColor colors[4];
+
+ shading->getDomain(&x0, &y0, &x1, &y1);
+ shading->getColor(x0, y0, &colors[0]);
+ shading->getColor(x0, y1, &colors[1]);
+ shading->getColor(x1, y0, &colors[2]);
+ shading->getColor(x1, y1, &colors[3]);
+ doFunctionShFill1(shading, x0, y0, x1, y1, colors, 0);
+}
+
+void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
+ double x0, double y0,
+ double x1, double y1,
+ GfxColor *colors, int depth) {
+ GfxColor fillColor;
+ GfxColor color0M, color1M, colorM0, colorM1, colorMM;
+ GfxColor colors2[4];
+ double *matrix;
+ double xM, yM;
+ int nComps, i, j;
+
+ nComps = shading->getColorSpace()->getNComps();
+ matrix = shading->getMatrix();
+
+ // compare the four corner colors
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < nComps; ++j) {
+ if (fabs(colors[i].c[j] - colors[(i+1)&3].c[j]) > functionColorDelta) {
+ break;
+ }
+ }
+ if (j < nComps) {
+ break;
+ }
+ }
+
+ // center of the rectangle
+ xM = 0.5 * (x0 + x1);
+ yM = 0.5 * (y0 + y1);
+
+ // the four corner colors are close (or we hit the recursive limit)
+ // -- fill the rectangle; but require at least one subdivision
+ // (depth==0) to avoid problems when the four outer corners of the
+ // shaded region are the same color
+ if ((i == 4 && depth > 0) || depth == functionMaxDepth) {
+
+ // use the center color
+ shading->getColor(xM, yM, &fillColor);
+ state->setFillColor(&fillColor);
+ out->updateFillColor(state);
+
+ // fill the rectangle
+ state->moveTo(x0 * matrix[0] + y0 * matrix[2] + matrix[4],
+ x0 * matrix[1] + y0 * matrix[3] + matrix[5]);
+ state->lineTo(x1 * matrix[0] + y0 * matrix[2] + matrix[4],
+ x1 * matrix[1] + y0 * matrix[3] + matrix[5]);
+ state->lineTo(x1 * matrix[0] + y1 * matrix[2] + matrix[4],
+ x1 * matrix[1] + y1 * matrix[3] + matrix[5]);
+ state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4],
+ x0 * matrix[1] + y1 * matrix[3] + matrix[5]);
+ state->closePath();
+ out->fill(state);
+ state->clearPath();
+
+ // the four corner colors are not close enough -- subdivide the
+ // rectangle
+ } else {
+
+ // colors[0] colorM0 colors[2]
+ // (x0,y0) (xM,y0) (x1,y0)
+ // +----------+----------+
+ // | | |
+ // | UL | UR |
+ // color0M | colorMM | color1M
+ // (x0,yM) +----------+----------+ (x1,yM)
+ // | (xM,yM) |
+ // | LL | LR |
+ // | | |
+ // +----------+----------+
+ // colors[1] colorM1 colors[3]
+ // (x0,y1) (xM,y1) (x1,y1)
+
+ shading->getColor(x0, yM, &color0M);
+ shading->getColor(x1, yM, &color1M);
+ shading->getColor(xM, y0, &colorM0);
+ shading->getColor(xM, y1, &colorM1);
+ shading->getColor(xM, yM, &colorMM);
+
+ // upper-left sub-rectangle
+ colors2[0] = colors[0];
+ colors2[1] = color0M;
+ colors2[2] = colorM0;
+ colors2[3] = colorMM;
+ doFunctionShFill1(shading, x0, y0, xM, yM, colors2, depth + 1);
+
+ // lower-left sub-rectangle
+ colors2[0] = color0M;
+ colors2[1] = colors[1];
+ colors2[2] = colorMM;
+ colors2[3] = colorM1;
+ doFunctionShFill1(shading, x0, yM, xM, y1, colors2, depth + 1);
+
+ // upper-right sub-rectangle
+ colors2[0] = colorM0;
+ colors2[1] = colorMM;
+ colors2[2] = colors[2];
+ colors2[3] = color1M;
+ doFunctionShFill1(shading, xM, y0, x1, yM, colors2, depth + 1);
+
+ // lower-right sub-rectangle
+ colors2[0] = colorMM;
+ colors2[1] = colorM1;
+ colors2[2] = color1M;
+ colors2[3] = colors[3];
+ doFunctionShFill1(shading, xM, yM, x1, y1, colors2, depth + 1);
+ }
+}
+
+void Gfx::doAxialShFill(GfxAxialShading *shading) {
+ double xMin, yMin, xMax, yMax;
+ double x0, y0, x1, y1;
+ double dx, dy, mul;
+ double tMin, tMax, t, tx, ty;
+ double s[4], sMin, sMax, tmp;
+ double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
+ double t0, t1, tt;
+ double ta[axialMaxSplits + 1];
+ int next[axialMaxSplits + 1];
+ GfxColor color0, color1;
+ int nComps;
+ int i, j, k, kk;
+
+ // get the clip region bbox
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+
+ // compute min and max t values, based on the four corners of the
+ // clip region bbox
+ shading->getCoords(&x0, &y0, &x1, &y1);
+ dx = x1 - x0;
+ dy = y1 - y0;
+ mul = 1 / (dx * dx + dy * dy);
+ tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
+ t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
+ if (t < tMin) {
+ tMin = t;
+ } else if (t > tMax) {
+ tMax = t;
+ }
+ if (tMin < 0 && !shading->getExtend0()) {
+ tMin = 0;
+ }
+ if (tMax > 1 && !shading->getExtend1()) {
+ tMax = 1;
+ }
+
+ // get the function domain
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+
+ // Traverse the t axis and do the shading.
+ //
+ // For each point (tx, ty) on the t axis, consider a line through
+ // that point perpendicular to the t axis:
+ //
+ // x(s) = tx + s * -dy --> s = (x - tx) / -dy
+ // y(s) = ty + s * dx --> s = (y - ty) / dx
+ //
+ // Then look at the intersection of this line with the bounding box
+ // (xMin, yMin, xMax, yMax). In the general case, there are four
+ // intersection points:
+ //
+ // s0 = (xMin - tx) / -dy
+ // s1 = (xMax - tx) / -dy
+ // s2 = (yMin - ty) / dx
+ // s3 = (yMax - ty) / dx
+ //
+ // and we want the middle two s values.
+ //
+ // In the case where dx = 0, take s0 and s1; in the case where dy =
+ // 0, take s2 and s3.
+ //
+ // Each filled polygon is bounded by two of these line segments
+ // perpdendicular to the t axis.
+ //
+ // The t axis is bisected into smaller regions until the color
+ // difference across a region is small enough, and then the region
+ // is painted with a single color.
+
+ // set up: require at least one split to avoid problems when the two
+ // ends of the t axis have the same color
+ nComps = shading->getColorSpace()->getNComps();
+ ta[0] = tMin;
+ next[0] = axialMaxSplits / 2;
+ ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax);
+ next[axialMaxSplits / 2] = axialMaxSplits;
+ ta[axialMaxSplits] = tMax;
+
+ // compute the color at t = tMin
+ if (tMin < 0) {
+ tt = t0;
+ } else if (tMin > 1) {
+ tt = t1;
+ } else {
+ tt = t0 + (t1 - t0) * tMin;
+ }
+ shading->getColor(tt, &color0);
+
+ // compute the coordinates of the point on the t axis at t = tMin;
+ // then compute the intersection of the perpendicular line with the
+ // bounding box
+ tx = x0 + tMin * dx;
+ ty = y0 + tMin * dy;
+ if (dx == 0 && dy == 0) {
+ sMin = sMax = 0;
+ } if (dx == 0) {
+ sMin = (xMin - tx) / -dy;
+ sMax = (xMax - tx) / -dy;
+ if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+ } else if (dy == 0) {
+ sMin = (yMin - ty) / dx;
+ sMax = (yMax - ty) / dx;
+ if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+ } else {
+ s[0] = (yMin - ty) / dx;
+ s[1] = (yMax - ty) / dx;
+ s[2] = (xMin - tx) / -dy;
+ s[3] = (xMax - tx) / -dy;
+ for (j = 0; j < 3; ++j) {
+ kk = j;
+ for (k = j + 1; k < 4; ++k) {
+ if (s[k] < s[kk]) {
+ kk = k;
+ }
+ }
+ tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+ }
+ sMin = s[1];
+ sMax = s[2];
+ }
+ ux0 = tx - sMin * dy;
+ uy0 = ty + sMin * dx;
+ vx0 = tx - sMax * dy;
+ vy0 = ty + sMax * dx;
+
+ i = 0;
+ while (i < axialMaxSplits) {
+
+ // bisect until color difference is small enough or we hit the
+ // bisection limit
+ j = next[i];
+ while (j > i + 1) {
+ if (ta[j] < 0) {
+ tt = t0;
+ } else if (ta[j] > 1) {
+ tt = t1;
+ } else {
+ tt = t0 + (t1 - t0) * ta[j];
+ }
+ shading->getColor(tt, &color1);
+ for (k = 0; k < nComps; ++k) {
+ if (fabs(color1.c[k] - color0.c[k]) > axialColorDelta) {
+ break;
+ }
+ }
+ if (k == nComps) {
+ break;
+ }
+ k = (i + j) / 2;
+ ta[k] = 0.5 * (ta[i] + ta[j]);
+ next[i] = k;
+ next[k] = j;
+ j = k;
+ }
+
+ // use the average of the colors of the two sides of the region
+ for (k = 0; k < nComps; ++k) {
+ color0.c[k] = 0.5 * (color0.c[k] + color1.c[k]);
+ }
+
+ // compute the coordinates of the point on the t axis; then
+ // compute the intersection of the perpendicular line with the
+ // bounding box
+ tx = x0 + ta[j] * dx;
+ ty = y0 + ta[j] * dy;
+ if (dx == 0 && dy == 0) {
+ sMin = sMax = 0;
+ } if (dx == 0) {
+ sMin = (xMin - tx) / -dy;
+ sMax = (xMax - tx) / -dy;
+ if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+ } else if (dy == 0) {
+ sMin = (yMin - ty) / dx;
+ sMax = (yMax - ty) / dx;
+ if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; }
+ } else {
+ s[0] = (yMin - ty) / dx;
+ s[1] = (yMax - ty) / dx;
+ s[2] = (xMin - tx) / -dy;
+ s[3] = (xMax - tx) / -dy;
+ for (j = 0; j < 3; ++j) {
+ kk = j;
+ for (k = j + 1; k < 4; ++k) {
+ if (s[k] < s[kk]) {
+ kk = k;
+ }
+ }
+ tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
+ }
+ sMin = s[1];
+ sMax = s[2];
+ }
+ ux1 = tx - sMin * dy;
+ uy1 = ty + sMin * dx;
+ vx1 = tx - sMax * dy;
+ vy1 = ty + sMax * dx;
+
+ // set the color
+ state->setFillColor(&color0);
+ out->updateFillColor(state);
+
+ // fill the region
+ state->moveTo(ux0, uy0);
+ state->lineTo(vx0, vy0);
+ state->lineTo(vx1, vy1);
+ state->lineTo(ux1, uy1);
+ state->closePath();
+ out->fill(state);
+ state->clearPath();
+
+ // set up for next region
+ ux0 = ux1;
+ uy0 = uy1;
+ vx0 = vx1;
+ vy0 = vy1;
+ color0 = color1;
+ i = next[i];
+ }
+}
+
+void Gfx::doRadialShFill(GfxRadialShading *shading) {
+ double sMin, sMax, xMin, yMin, xMax, yMax;
+ double x0, y0, r0, x1, y1, r1, t0, t1;
+ int nComps;
+ GfxColor colorA, colorB;
+ double xa, ya, xb, yb, ra, rb;
+ double ta, tb, sa, sb;
+ int ia, ib, k, n;
+ double *ctm;
+ double angle, t;
+
+ // get the shading info
+ shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+ t0 = shading->getDomain0();
+ t1 = shading->getDomain1();
+ nComps = shading->getColorSpace()->getNComps();
+
+ // compute the (possibly extended) s range
+ sMin = 0;
+ sMax = 1;
+ if (shading->getExtend0()) {
+ if (r0 < r1) {
+ // extend the smaller end
+ sMin = -r0 / (r1 - r0);
+ } else {
+ // extend the larger end
+ //~ this computes the diagonal of the bounding box -- we should
+ //~ really compute the intersection of the moving/expanding
+ //~ circles with each of the four corners and look for the max
+ //~ radius
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ sMin = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ if (sMin > 0) {
+ sMin = 0;
+ } else if (sMin < -20) {
+ // sanity check
+ sMin = -20;
+ }
+ }
+ }
+ if (shading->getExtend1()) {
+ if (r1 < r0) {
+ // extend the smaller end
+ sMax = -r0 / (r1 - r0);
+ } else if (r1 > r0) {
+ // extend the larger end
+ state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+ sMax = (sqrt((xMax - xMin) * (xMax - xMin) +
+ (yMax - yMin) * (yMax - yMin)) - r0) / (r1 - r0);
+ if (sMax < 1) {
+ sMin = 1;
+ } else if (sMax > 20) {
+ // sanity check
+ sMax = 20;
+ }
+ }
+ }
+
+ // compute the number of steps into which circles must be divided to
+ // achieve a curve flatness of 0.1 pixel in device space for the
+ // largest circle (note that "device space" is 72 dpi when generating
+ // PostScript, hence the relatively small 0.1 pixel accuracy)
+ ctm = state->getCTM();
+ t = fabs(ctm[0]);
+ if (fabs(ctm[1]) > t) {
+ t = fabs(ctm[1]);
+ }
+ if (fabs(ctm[2]) > t) {
+ t = fabs(ctm[2]);
+ }
+ if (fabs(ctm[3]) > t) {
+ t = fabs(ctm[3]);
+ }
+ if (r0 > r1) {
+ t *= r0;
+ } else {
+ t *= r1;
+ }
+ if (t < 1) {
+ n = 3;
+ } else {
+ n = (int)(M_PI / acos(1 - 0.1 / t));
+ if (n < 3) {
+ n = 3;
+ } else if (n > 200) {
+ n = 200;
+ }
+ }
+
+ // Traverse the t axis and do the shading.
+ //
+ // This generates and fills a series of rings. Each ring is defined
+ // by two circles:
+ // sa, ta, xa, ya, ra, colorA
+ // sb, tb, xb, yb, rb, colorB
+ //
+ // The s/t axis is divided into radialMaxSplits parts; these parts
+ // are combined as much as possible while respecting the
+ // radialColorDelta parameter.
+
+ // setup for the start circle
+ ia = 0;
+ sa = sMin;
+ ta = t0 + sa * (t1 - t0);
+ xa = x0 + sa * (x1 - x0);
+ ya = y0 + sa * (y1 - y0);
+ ra = r0 + sa * (r1 - r0);
+ if (ta < t0) {
+ shading->getColor(t0, &colorA);
+ } else if (ta > t1) {
+ shading->getColor(t1, &colorA);
+ } else {
+ shading->getColor(ta, &colorA);
+ }
+
+ while (ia < radialMaxSplits) {
+
+ // go as far along the t axis (toward t1) as we can, such that the
+ // color difference is within the tolerance (radialColorDelta) --
+ // this uses bisection (between the current value, t, and t1),
+ // limited to radialMaxSplits points along the t axis; require at
+ // least one split to avoid problems when the innermost and
+ // outermost colors are the same
+ ib = radialMaxSplits;
+ sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ if (tb < t0) {
+ shading->getColor(t0, &colorB);
+ } else if (tb > t1) {
+ shading->getColor(t1, &colorB);
+ } else {
+ shading->getColor(tb, &colorB);
+ }
+ while (ib - ia > 1) {
+ for (k = 0; k < nComps; ++k) {
+ if (fabs(colorB.c[k] - colorA.c[k]) > radialColorDelta) {
+ break;
+ }
+ }
+ if (k == nComps && ib < radialMaxSplits) {
+ break;
+ }
+ ib = (ia + ib) / 2;
+ sb = sMin + ((double)ib / (double)radialMaxSplits) * (sMax - sMin);
+ tb = t0 + sb * (t1 - t0);
+ if (tb < t0) {
+ shading->getColor(t0, &colorB);
+ } else if (tb > t1) {
+ shading->getColor(t1, &colorB);
+ } else {
+ shading->getColor(tb, &colorB);
+ }
+ }
+
+ // compute center and radius of the circle
+ xb = x0 + sb * (x1 - x0);
+ yb = y0 + sb * (y1 - y0);
+ rb = r0 + sb * (r1 - r0);
+
+ // use the average of the colors at the two circles
+ for (k = 0; k < nComps; ++k) {
+ colorA.c[k] = 0.5 * (colorA.c[k] + colorB.c[k]);
+ }
+ state->setFillColor(&colorA);
+ out->updateFillColor(state);
+
+ // construct path for first circle
+ state->moveTo(xa + ra, ya);
+ for (k = 1; k < n; ++k) {
+ angle = ((double)k / (double)n) * 2 * M_PI;
+ state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+ }
+ state->closePath();
+
+ // construct and append path for second circle
+ state->moveTo(xb + rb, yb);
+ for (k = 1; k < n; ++k) {
+ angle = ((double)k / (double)n) * 2 * M_PI;
+ state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
+ }
+ state->closePath();
+
+ // fill the ring
+ out->eoFill(state);
+ state->clearPath();
+
+ // step to the next value of t
+ ia = ib;
+ sa = sb;
+ ta = tb;
+ xa = xb;
+ ya = yb;
+ ra = rb;
+ colorA = colorB;
+ }
+}
+
+void Gfx::doEndPath() {
+ if (state->isCurPt() && clip != clipNone) {
+ state->clip();
+ if (clip == clipNormal) {
+ out->clip(state);
+ } else {
+ out->eoClip(state);
+ }
+ }
+ clip = clipNone;
+ state->clearPath();
+}
+
+//------------------------------------------------------------------------
+// path clipping operators
+//------------------------------------------------------------------------
+
+void Gfx::opClip(Object args[], int numArgs) {
+ clip = clipNormal;
+}
+
+void Gfx::opEOClip(Object args[], int numArgs) {
+ clip = clipEO;
+}
+
+//------------------------------------------------------------------------
+// text object operators
+//------------------------------------------------------------------------
+
+void Gfx::opBeginText(Object args[], int numArgs) {
+ state->setTextMat(1, 0, 0, 1, 0, 0);
+ state->textMoveTo(0, 0);
+ out->updateTextMat(state);
+ out->updateTextPos(state);
+ fontChanged = gTrue;
+}
+
+void Gfx::opEndText(Object args[], int numArgs) {
+ out->endTextObject(state);
+}
+
+//------------------------------------------------------------------------
+// text state operators
+//------------------------------------------------------------------------
+
+void Gfx::opSetCharSpacing(Object args[], int numArgs) {
+ state->setCharSpace(args[0].getNum());
+ out->updateCharSpace(state);
+}
+
+void Gfx::opSetFont(Object args[], int numArgs) {
+ GfxFont *font;
+
+ if (!(font = res->lookupFont(args[0].getName()))) {
+ return;
+ }
+ if (printCommands) {
+ fprintf(stderr, "DEBUG2: font: tag=%s name='%s' %g\n",
+ font->getTag()->getCString(),
+ font->getName() ? font->getName()->getCString() : "???",
+ args[1].getNum());
+ fflush(stderr);
+ }
+ state->setFont(font, args[1].getNum());
+ fontChanged = gTrue;
+}
+
+void Gfx::opSetTextLeading(Object args[], int numArgs) {
+ state->setLeading(args[0].getNum());
+}
+
+void Gfx::opSetTextRender(Object args[], int numArgs) {
+ state->setRender(args[0].getInt());
+ out->updateRender(state);
+}
+
+void Gfx::opSetTextRise(Object args[], int numArgs) {
+ state->setRise(args[0].getNum());
+ out->updateRise(state);
+}
+
+void Gfx::opSetWordSpacing(Object args[], int numArgs) {
+ state->setWordSpace(args[0].getNum());
+ out->updateWordSpace(state);
+}
+
+void Gfx::opSetHorizScaling(Object args[], int numArgs) {
+ state->setHorizScaling(args[0].getNum());
+ out->updateHorizScaling(state);
+ fontChanged = gTrue;
+}
+
+//------------------------------------------------------------------------
+// text positioning operators
+//------------------------------------------------------------------------
+
+void Gfx::opTextMove(Object args[], int numArgs) {
+ double tx, ty;
+
+ tx = state->getLineX() + args[0].getNum();
+ ty = state->getLineY() + args[1].getNum();
+ state->textMoveTo(tx, ty);
+ out->updateTextPos(state);
+}
+
+void Gfx::opTextMoveSet(Object args[], int numArgs) {
+ double tx, ty;
+
+ tx = state->getLineX() + args[0].getNum();
+ ty = args[1].getNum();
+ state->setLeading(-ty);
+ ty += state->getLineY();
+ state->textMoveTo(tx, ty);
+ out->updateTextPos(state);
+}
+
+void Gfx::opSetTextMatrix(Object args[], int numArgs) {
+ state->setTextMat(args[0].getNum(), args[1].getNum(),
+ args[2].getNum(), args[3].getNum(),
+ args[4].getNum(), args[5].getNum());
+ state->textMoveTo(0, 0);
+ out->updateTextMat(state);
+ out->updateTextPos(state);
+ fontChanged = gTrue;
+}
+
+void Gfx::opTextNextLine(Object args[], int numArgs) {
+ double tx, ty;
+
+ tx = state->getLineX();
+ ty = state->getLineY() - state->getLeading();
+ state->textMoveTo(tx, ty);
+ out->updateTextPos(state);
+}
+
+//------------------------------------------------------------------------
+// text string operators
+//------------------------------------------------------------------------
+
+void Gfx::opShowText(Object args[], int numArgs) {
+ if (!state->getFont()) {
+ error(getPos(), "No font in show");
+ return;
+ }
+ if (fontChanged) {
+ out->updateFont(state);
+ fontChanged = gFalse;
+ }
+ doShowText(args[0].getString());
+}
+
+void Gfx::opMoveShowText(Object args[], int numArgs) {
+ double tx, ty;
+
+ if (!state->getFont()) {
+ error(getPos(), "No font in move/show");
+ return;
+ }
+ if (fontChanged) {
+ out->updateFont(state);
+ fontChanged = gFalse;
+ }
+ tx = state->getLineX();
+ ty = state->getLineY() - state->getLeading();
+ state->textMoveTo(tx, ty);
+ out->updateTextPos(state);
+ doShowText(args[0].getString());
+}
+
+void Gfx::opMoveSetShowText(Object args[], int numArgs) {
+ double tx, ty;
+
+ if (!state->getFont()) {
+ error(getPos(), "No font in move/set/show");
+ return;
+ }
+ if (fontChanged) {
+ out->updateFont(state);
+ fontChanged = gFalse;
+ }
+ state->setWordSpace(args[0].getNum());
+ state->setCharSpace(args[1].getNum());
+ tx = state->getLineX();
+ ty = state->getLineY() - state->getLeading();
+ state->textMoveTo(tx, ty);
+ out->updateWordSpace(state);
+ out->updateCharSpace(state);
+ out->updateTextPos(state);
+ doShowText(args[2].getString());
+}
+
+void Gfx::opShowSpaceText(Object args[], int numArgs) {
+ Array *a;
+ Object obj;
+ int wMode;
+ int i;
+
+ if (!state->getFont()) {
+ error(getPos(), "No font in show/space");
+ return;
+ }
+ if (fontChanged) {
+ out->updateFont(state);
+ fontChanged = gFalse;
+ }
+ wMode = state->getFont()->getWMode();
+ a = args[0].getArray();
+ for (i = 0; i < a->getLength(); ++i) {
+ a->get(i, &obj);
+ if (obj.isNum()) {
+ if (wMode) {
+ state->textShift(0, -obj.getNum() * 0.001 * state->getFontSize());
+ } else {
+ state->textShift(-obj.getNum() * 0.001 * state->getFontSize(), 0);
+ }
+ out->updateTextShift(state, obj.getNum());
+ } else if (obj.isString()) {
+ doShowText(obj.getString());
+ } else {
+ error(getPos(), "Element of show/space array must be number or string");
+ }
+ obj.free();
+ }
+}
+
+void Gfx::doShowText(GString *s) {
+ GfxFont *font;
+ int wMode;
+ double riseX, riseY;
+ CharCode code;
+ Unicode u[8];
+ double x, y, dx, dy, dx2, dy2, curX, curY, tdx, tdy, lineX, lineY;
+ double originX, originY, tOriginX, tOriginY;
+ double oldCTM[6], newCTM[6];
+ double *mat;
+ Object charProc;
+ Dict *resDict;
+ Parser *oldParser;
+ char *p;
+ int len, n, uLen, nChars, nSpaces, i;
+
+ font = state->getFont();
+ wMode = font->getWMode();
+
+ if (out->useDrawChar()) {
+ out->beginString(state, s);
+ }
+
+ // handle a Type 3 char
+ if (font->getType() == fontType3 && out->interpretType3Chars()) {
+ mat = state->getCTM();
+ for (i = 0; i < 6; ++i) {
+ oldCTM[i] = mat[i];
+ }
+ mat = state->getTextMat();
+ newCTM[0] = mat[0] * oldCTM[0] + mat[1] * oldCTM[2];
+ newCTM[1] = mat[0] * oldCTM[1] + mat[1] * oldCTM[3];
+ newCTM[2] = mat[2] * oldCTM[0] + mat[3] * oldCTM[2];
+ newCTM[3] = mat[2] * oldCTM[1] + mat[3] * oldCTM[3];
+ mat = font->getFontMatrix();
+ newCTM[0] = mat[0] * newCTM[0] + mat[1] * newCTM[2];
+ newCTM[1] = mat[0] * newCTM[1] + mat[1] * newCTM[3];
+ newCTM[2] = mat[2] * newCTM[0] + mat[3] * newCTM[2];
+ newCTM[3] = mat[2] * newCTM[1] + mat[3] * newCTM[3];
+ newCTM[0] *= state->getFontSize();
+ newCTM[3] *= state->getFontSize();
+ newCTM[0] *= state->getHorizScaling();
+ newCTM[2] *= state->getHorizScaling();
+ state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
+ curX = state->getCurX();
+ curY = state->getCurY();
+ lineX = state->getLineX();
+ lineY = state->getLineY();
+ oldParser = parser;
+ p = s->getCString();
+ len = s->getLength();
+ while (len > 0) {
+ n = font->getNextChar(p, len, &code,
+ u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+ &dx, &dy, &originX, &originY);
+ dx = dx * state->getFontSize() + state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ dx *= state->getHorizScaling();
+ dy *= state->getFontSize();
+ state->textTransformDelta(dx, dy, &tdx, &tdy);
+ state->transform(curX + riseX, curY + riseY, &x, &y);
+ saveState();
+ state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
+ //~ out->updateCTM(???)
+ if (!out->beginType3Char(state, code, u, uLen)) {
+ ((Gfx8BitFont *)font)->getCharProc(code, &charProc);
+ if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
+ pushResources(resDict);
+ }
+ if (charProc.isStream()) {
+ display(&charProc, gFalse);
+ } else {
+ error(getPos(), "Missing or bad Type3 CharProc entry");
+ }
+ out->endType3Char(state);
+ if (resDict) {
+ popResources();
+ }
+ charProc.free();
+ }
+ restoreState();
+ // GfxState::restore() does *not* restore the current position,
+ // so we deal with it here using (curX, curY) and (lineX, lineY)
+ curX += tdx;
+ curY += tdy;
+ state->moveTo(curX, curY);
+ state->textSetPos(lineX, lineY);
+ p += n;
+ len -= n;
+ }
+ parser = oldParser;
+
+ } else if (out->useDrawChar()) {
+ state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
+ p = s->getCString();
+ len = s->getLength();
+ while (len > 0) {
+ n = font->getNextChar(p, len, &code,
+ u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+ &dx, &dy, &originX, &originY);
+ if (wMode) {
+ dx *= state->getFontSize();
+ dy = dy * state->getFontSize() + state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dy += state->getWordSpace();
+ }
+ } else {
+ dx = dx * state->getFontSize() + state->getCharSpace();
+ if (n == 1 && *p == ' ') {
+ dx += state->getWordSpace();
+ }
+ dx *= state->getHorizScaling();
+ dy *= state->getFontSize();
+ }
+ state->textTransformDelta(dx, dy, &tdx, &tdy);
+ originX *= state->getFontSize();
+ originY *= state->getFontSize();
+ state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
+ out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
+ tdx, tdy, tOriginX, tOriginY, code, u, uLen);
+ state->shift(tdx, tdy);
+ p += n;
+ len -= n;
+ }
+
+ } else {
+ dx = dy = 0;
+ p = s->getCString();
+ len = s->getLength();
+ nChars = nSpaces = 0;
+ while (len > 0) {
+ n = font->getNextChar(p, len, &code,
+ u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+ &dx2, &dy2, &originX, &originY);
+ dx += dx2;
+ dy += dy2;
+ if (n == 1 && *p == ' ') {
+ ++nSpaces;
+ }
+ ++nChars;
+ p += n;
+ len -= n;
+ }
+ if (wMode) {
+ dx *= state->getFontSize();
+ dy = dy * state->getFontSize()
+ + nChars * state->getCharSpace()
+ + nSpaces * state->getWordSpace();
+ } else {
+ dx = dx * state->getFontSize()
+ + nChars * state->getCharSpace()
+ + nSpaces * state->getWordSpace();
+ dx *= state->getHorizScaling();
+ dy *= state->getFontSize();
+ }
+ state->textTransformDelta(dx, dy, &tdx, &tdy);
+ out->drawString(state, s);
+ state->shift(tdx, tdy);
+ }
+
+ if (out->useDrawChar()) {
+ out->endString(state);
+ }
+
+ updateLevel += 10 * s->getLength();
+}
+
+//------------------------------------------------------------------------
+// XObject operators
+//------------------------------------------------------------------------
+
+void Gfx::opXObject(Object args[], int numArgs) {
+ Object obj1, obj2, obj3, refObj;
+#if OPI_SUPPORT
+ Object opiDict;
+#endif
+
+ if (!res->lookupXObject(args[0].getName(), &obj1)) {
+ return;
+ }
+ if (!obj1.isStream()) {
+ error(getPos(), "XObject '%s' is wrong type", args[0].getName());
+ obj1.free();
+ return;
+ }
+#if OPI_SUPPORT
+ obj1.streamGetDict()->lookup("OPI", &opiDict);
+ if (opiDict.isDict()) {
+ out->opiBegin(state, opiDict.getDict());
+ }
+#endif
+ obj1.streamGetDict()->lookup("Subtype", &obj2);
+ if (obj2.isName("Image")) {
+ res->lookupXObjectNF(args[0].getName(), &refObj);
+ doImage(&refObj, obj1.getStream(), gFalse);
+ refObj.free();
+ } else if (obj2.isName("Form")) {
+ doForm(&obj1);
+ } else if (obj2.isName("PS")) {
+ obj1.streamGetDict()->lookup("Level1", &obj3);
+ out->psXObject(obj1.getStream(),
+ obj3.isStream() ? obj3.getStream() : (Stream *)NULL);
+ } else if (obj2.isName()) {
+ error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
+ } else {
+ error(getPos(), "XObject subtype is missing or wrong type");
+ }
+ obj2.free();
+#if OPI_SUPPORT
+ if (opiDict.isDict()) {
+ out->opiEnd(state, opiDict.getDict());
+ }
+ opiDict.free();
+#endif
+ obj1.free();
+}
+
+void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
+ Dict *dict;
+ int width, height;
+ int bits;
+ GBool mask;
+ GBool invert;
+ GfxColorSpace *colorSpace;
+ GfxImageColorMap *colorMap;
+ Object maskObj;
+ GBool haveMask;
+ int maskColors[2*gfxColorMaxComps];
+ Object obj1, obj2;
+ int i;
+
+ // get stream dict
+ dict = str->getDict();
+
+ // get size
+ dict->lookup("Width", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("W", &obj1);
+ }
+ if (!obj1.isInt())
+ goto err2;
+ width = obj1.getInt();
+ obj1.free();
+ dict->lookup("Height", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("H", &obj1);
+ }
+ if (!obj1.isInt())
+ goto err2;
+ height = obj1.getInt();
+ obj1.free();
+
+ // image or mask?
+ dict->lookup("ImageMask", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("IM", &obj1);
+ }
+ mask = gFalse;
+ if (obj1.isBool())
+ mask = obj1.getBool();
+ else if (!obj1.isNull())
+ goto err2;
+ obj1.free();
+
+ // bit depth
+ dict->lookup("BitsPerComponent", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("BPC", &obj1);
+ }
+ if (obj1.isInt()) {
+ bits = obj1.getInt();
+ } else if (mask) {
+ bits = 1;
+ } else {
+ goto err2;
+ }
+ obj1.free();
+
+ // display a mask
+ if (mask) {
+
+ // check for inverted mask
+ if (bits != 1)
+ goto err1;
+ invert = gFalse;
+ dict->lookup("Decode", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("D", &obj1);
+ }
+ if (obj1.isArray()) {
+ obj1.arrayGet(0, &obj2);
+ if (obj2.isInt() && obj2.getInt() == 1)
+ invert = gTrue;
+ obj2.free();
+ } else if (!obj1.isNull()) {
+ goto err2;
+ }
+ obj1.free();
+
+ // draw it
+ out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+
+ } else {
+
+ // get color space and color map
+ dict->lookup("ColorSpace", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("CS", &obj1);
+ }
+ if (obj1.isName()) {
+ res->lookupColorSpace(obj1.getName(), &obj2);
+ if (!obj2.isNull()) {
+ obj1.free();
+ obj1 = obj2;
+ } else {
+ obj2.free();
+ }
+ }
+ colorSpace = GfxColorSpace::parse(&obj1);
+ obj1.free();
+ if (!colorSpace) {
+ goto err1;
+ }
+ dict->lookup("Decode", &obj1);
+ if (obj1.isNull()) {
+ obj1.free();
+ dict->lookup("D", &obj1);
+ }
+ colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
+ obj1.free();
+ if (!colorMap->isOk()) {
+ delete colorMap;
+ goto err1;
+ }
+
+ // get the mask
+ haveMask = gFalse;
+ dict->lookup("Mask", &maskObj);
+ if (maskObj.isArray()) {
+ for (i = 0;
+ i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps;
+ ++i) {
+ maskObj.arrayGet(i, &obj1);
+ maskColors[i] = obj1.getInt();
+ obj1.free();
+ }
+ haveMask = gTrue;
+ }
+
+ // draw it
+ out->drawImage(state, ref, str, width, height, colorMap,
+ haveMask ? maskColors : (int *)NULL, inlineImg);
+ delete colorMap;
+
+ maskObj.free();
+ }
+
+ if ((i = width * height) > 1000) {
+ i = 1000;
+ }
+ updateLevel += i;
+
+ return;
+
+ err2:
+ obj1.free();
+ err1:
+ error(getPos(), "Bad image parameters");
+}
+
+void Gfx::doForm(Object *str) {
+ Dict *dict;
+ Object matrixObj, bboxObj;
+ double m[6], bbox[6];
+ Object resObj;
+ Dict *resDict;
+ Object obj1;
+ int i;
+
+ // check for excessive recursion
+ if (formDepth > 20) {
+ return;
+ }
+
+ // get stream dict
+ dict = str->streamGetDict();
+
+ // check form type
+ dict->lookup("FormType", &obj1);
+ if (!(obj1.isInt() && obj1.getInt() == 1)) {
+ error(getPos(), "Unknown form type");
+ }
+ obj1.free();
+
+ // get bounding box
+ dict->lookup("BBox", &bboxObj);
+ if (!bboxObj.isArray()) {
+ matrixObj.free();
+ bboxObj.free();
+ error(getPos(), "Bad form bounding box");
+ return;
+ }
+ for (i = 0; i < 4; ++i) {
+ bboxObj.arrayGet(i, &obj1);
+ bbox[i] = obj1.getNum();
+ obj1.free();
+ }
+ bboxObj.free();
+
+ // get matrix
+ dict->lookup("Matrix", &matrixObj);
+ if (matrixObj.isArray()) {
+ for (i = 0; i < 6; ++i) {
+ matrixObj.arrayGet(i, &obj1);
+ m[i] = obj1.getNum();
+ obj1.free();
+ }
+ } else {
+ m[0] = 1; m[1] = 0;
+ m[2] = 0; m[3] = 1;
+ m[4] = 0; m[5] = 0;
+ }
+ matrixObj.free();
+
+ // get resources
+ dict->lookup("Resources", &resObj);
+ resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
+
+ // draw it
+ ++formDepth;
+ doForm1(str, resDict, m, bbox);
+ --formDepth;
+
+ resObj.free();
+}
+
+void Gfx::doAnnot(Object *str, double xMin, double yMin,
+ double xMax, double yMax) {
+ Dict *dict, *resDict;
+ Object matrixObj, bboxObj, resObj, flagsObj, subTypeObj;
+ Object obj1;
+ double m[6], bbox[6], ictm[6];
+ double *ctm;
+ double formX0, formY0, formX1, formY1;
+ double annotX0, annotY0, annotX1, annotY1;
+ double det, x, y, sx, sy;
+ int i, flags;
+
+ // get stream dict
+ dict = str->streamGetDict();
+
+ // get annotation flags and only print annotations that are hidden or
+ // don't have the print bit set.
+ dict->lookup("F", &flagsObj);
+ if (flagsObj.isInt()) {
+ flags = flagsObj.getInt();
+ } else {
+ // Print anything that doesn't have any flags set...
+ flags = 4;
+ }
+ flagsObj.free();
+
+ fprintf(stderr, "DEBUG: pdftops: doAnnot found annotation with flags = %x\n",
+ flags);
+
+ subTypeObj.free();
+
+ if ((flags & 2) == 2 || (flags & 4) == 0) {
+ // Don't print hidden or no-print annotations...
+ return;
+ }
+
+ // get the form bounding box
+ dict->lookup("BBox", &bboxObj);
+ if (!bboxObj.isArray()) {
+ bboxObj.free();
+ error(getPos(), "Bad form bounding box");
+ return;
+ }
+ for (i = 0; i < 4; ++i) {
+ bboxObj.arrayGet(i, &obj1);
+ bbox[i] = obj1.getNum();
+ obj1.free();
+ }
+ bboxObj.free();
+
+ // get the form matrix
+ dict->lookup("Matrix", &matrixObj);
+ if (matrixObj.isArray()) {
+ for (i = 0; i < 6; ++i) {
+ matrixObj.arrayGet(i, &obj1);
+ m[i] = obj1.getNum();
+ obj1.free();
+ }
+ } else {
+ m[0] = 1; m[1] = 0;
+ m[2] = 0; m[3] = 1;
+ m[4] = 0; m[5] = 0;
+ }
+ matrixObj.free();
+
+ // transform the form bbox from form space to user space
+ formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
+ formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
+ formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
+ formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
+
+ // transform the annotation bbox from default user space to user
+ // space: (bbox * baseMatrix) * iCTM
+ ctm = state->getCTM();
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4];
+ y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5];
+ annotX0 = ictm[0] * x + ictm[2] * y + ictm[4];
+ annotY0 = ictm[1] * x + ictm[3] * y + ictm[5];
+ x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4];
+ y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5];
+ annotX1 = ictm[0] * x + ictm[2] * y + ictm[4];
+ annotY1 = ictm[1] * x + ictm[3] * y + ictm[5];
+
+ // swap min/max coords
+ if (formX0 > formX1) {
+ x = formX0; formX0 = formX1; formX1 = x;
+ }
+ if (formY0 > formY1) {
+ y = formY0; formY0 = formY1; formY1 = y;
+ }
+ if (annotX0 > annotX1) {
+ x = annotX0; annotX0 = annotX1; annotX1 = x;
+ }
+ if (annotY0 > annotY1) {
+ y = annotY0; annotY0 = annotY1; annotY1 = y;
+ }
+
+ // scale the form to fit the annotation bbox
+ if (formX1 == formX0) {
+ // this shouldn't happen
+ sx = 1;
+ } else {
+ sx = (annotX1 - annotX0) / (formX1 - formX0);
+ }
+ if (formY1 == formY0) {
+ // this shouldn't happen
+ sy = 1;
+ } else {
+ sy = (annotY1 - annotY0) / (formY1 - formY0);
+ }
+ m[0] *= sx;
+ m[2] *= sx;
+ m[4] = (m[4] - formX0) * sx + annotX0;
+ m[1] *= sy;
+ m[3] *= sy;
+ m[5] = (m[5] - formY0) * sy + annotY0;
+
+ // get resources
+ dict->lookup("Resources", &resObj);
+ resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
+
+ // draw it
+ doForm1(str, resDict, m, bbox);
+
+ resObj.free();
+ bboxObj.free();
+}
+
+void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
+ Parser *oldParser;
+ double oldBaseMatrix[6];
+ int i;
+
+ // push new resources on stack
+ pushResources(resDict);
+
+ // save current graphics state
+ saveState();
+
+ // kill any pre-existing path
+ state->clearPath();
+
+ // save current parser
+ oldParser = parser;
+
+ // set form transformation matrix
+ state->concatCTM(matrix[0], matrix[1], matrix[2],
+ matrix[3], matrix[4], matrix[5]);
+ out->updateCTM(state, matrix[0], matrix[1], matrix[2],
+ matrix[3], matrix[4], matrix[5]);
+
+ // set new base matrix
+ for (i = 0; i < 6; ++i) {
+ oldBaseMatrix[i] = baseMatrix[i];
+ baseMatrix[i] = state->getCTM()[i];
+ }
+
+ // set form bounding box
+ state->moveTo(bbox[0], bbox[1]);
+ state->lineTo(bbox[2], bbox[1]);
+ state->lineTo(bbox[2], bbox[3]);
+ state->lineTo(bbox[0], bbox[3]);
+ state->closePath();
+ state->clip();
+ out->clip(state);
+ state->clearPath();
+
+ // draw the form
+ display(str, gFalse);
+
+ // restore base matrix
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = oldBaseMatrix[i];
+ }
+
+ // restore parser
+ parser = oldParser;
+
+ // restore graphics state
+ restoreState();
+
+ // pop resource stack
+ popResources();
+
+ return;
+}
+
+//------------------------------------------------------------------------
+// in-line image operators
+//------------------------------------------------------------------------
+
+void Gfx::opBeginImage(Object args[], int numArgs) {
+ Stream *str;
+ int c1, c2;
+
+ // build dict/stream
+ str = buildImageStream();
+
+ // display the image
+ if (str) {
+ doImage(NULL, str, gTrue);
+
+ // skip 'EI' tag
+ c1 = str->getBaseStream()->getChar();
+ c2 = str->getBaseStream()->getChar();
+ while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) {
+ c1 = c2;
+ c2 = str->getBaseStream()->getChar();
+ }
+ delete str;
+ }
+}
+
+Stream *Gfx::buildImageStream() {
+ Object dict;
+ Object obj;
+ char *key;
+ Stream *str;
+
+ // build dictionary
+ dict.initDict(xref);
+ parser->getObj(&obj);
+ while (!obj.isCmd("ID") && !obj.isEOF()) {
+ if (!obj.isName()) {
+ error(getPos(), "Inline image dictionary key must be a name object");
+ obj.free();
+ } else {
+ key = copyString(obj.getName());
+ obj.free();
+ parser->getObj(&obj);
+ if (obj.isEOF() || obj.isError()) {
+ gfree(key);
+ break;
+ }
+ dict.dictAdd(key, &obj);
+ }
+ parser->getObj(&obj);
+ }
+ if (obj.isEOF()) {
+ error(getPos(), "End of file in inline image");
+ obj.free();
+ dict.free();
+ return NULL;
+ }
+ obj.free();
+
+ // make stream
+ str = new EmbedStream(parser->getStream(), &dict);
+ str = str->addFilters(&dict);
+
+ return str;
+}
+
+void Gfx::opImageData(Object args[], int numArgs) {
+ error(getPos(), "Internal: got 'ID' operator");
+}
+
+void Gfx::opEndImage(Object args[], int numArgs) {
+ error(getPos(), "Internal: got 'EI' operator");
+}
+
+//------------------------------------------------------------------------
+// type 3 font operators
+//------------------------------------------------------------------------
+
+void Gfx::opSetCharWidth(Object args[], int numArgs) {
+ out->type3D0(state, args[0].getNum(), args[1].getNum());
+}
+
+void Gfx::opSetCacheDevice(Object args[], int numArgs) {
+ out->type3D1(state, args[0].getNum(), args[1].getNum(),
+ args[2].getNum(), args[3].getNum(),
+ args[4].getNum(), args[5].getNum());
+}
+
+//------------------------------------------------------------------------
+// compatibility operators
+//------------------------------------------------------------------------
+
+void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
+ ++ignoreUndef;
+}
+
+void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
+ if (ignoreUndef > 0)
+ --ignoreUndef;
+}
+
+//------------------------------------------------------------------------
+// marked content operators
+//------------------------------------------------------------------------
+
+void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
+ if (printCommands) {
+ fprintf(stderr, "DEBUG2: marked content: %s ", args[0].getName());
+ if (numArgs == 2)
+ args[2].print(stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+}
+
+void Gfx::opEndMarkedContent(Object args[], int numArgs) {
+}
+
+void Gfx::opMarkPoint(Object args[], int numArgs) {
+ if (printCommands) {
+ fprintf(stderr, "DEBUG2: mark point: %s ", args[0].getName());
+ if (numArgs == 2)
+ args[2].print(stderr);
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+}
+
+//------------------------------------------------------------------------
+// misc
+//------------------------------------------------------------------------
+
+void Gfx::saveState() {
+ out->saveState(state);
+ state = state->save();
+}
+
+void Gfx::restoreState() {
+ state = state->restore();
+ out->restoreState(state);
+}
+
+void Gfx::pushResources(Dict *resDict) {
+ res = new GfxResources(xref, resDict, res);
+}
+
+void Gfx::popResources() {
+ GfxResources *resPtr;
+
+ resPtr = res->getNext();
+ delete res;
+ res = resPtr;
+}
diff --git a/pdftops/Gfx.h b/pdftops/Gfx.h
new file mode 100644
index 000000000..fc2c32e52
--- /dev/null
+++ b/pdftops/Gfx.h
@@ -0,0 +1,280 @@
+//========================================================================
+//
+// Gfx.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GFX_H
+#define GFX_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+class GString;
+class XRef;
+class Array;
+class Stream;
+class Parser;
+class Dict;
+class OutputDev;
+class GfxFontDict;
+class GfxFont;
+class GfxPattern;
+class GfxTilingPattern;
+class GfxShadingPattern;
+class GfxShading;
+class GfxFunctionShading;
+class GfxAxialShading;
+class GfxRadialShading;
+class GfxState;
+class GfxColor;
+class Gfx;
+class PDFRectangle;
+
+//------------------------------------------------------------------------
+// Gfx
+//------------------------------------------------------------------------
+
+enum GfxClipType {
+ clipNone,
+ clipNormal,
+ clipEO
+};
+
+enum TchkType {
+ tchkBool, // boolean
+ tchkInt, // integer
+ tchkNum, // number (integer or real)
+ tchkString, // string
+ tchkName, // name
+ tchkArray, // array
+ tchkProps, // properties (dictionary or name)
+ tchkSCN, // scn/SCN args (number of name)
+ tchkNone // used to avoid empty initializer lists
+};
+
+#define maxArgs 8
+
+struct Operator {
+ char name[4];
+ int numArgs;
+ TchkType tchk[maxArgs];
+ void (Gfx::*func)(Object args[], int numArgs);
+};
+
+class GfxResources {
+public:
+
+ GfxResources(XRef *xref, Dict *resDict, GfxResources *nextA);
+ ~GfxResources();
+
+ GfxFont *lookupFont(char *name);
+ GBool lookupXObject(char *name, Object *obj);
+ GBool lookupXObjectNF(char *name, Object *obj);
+ void lookupColorSpace(char *name, Object *obj);
+ GfxPattern *lookupPattern(char *name);
+ GfxShading *lookupShading(char *name);
+ GBool lookupGState(char *name, Object *obj);
+
+ GfxResources *getNext() { return next; }
+
+private:
+
+ GfxFontDict *fonts;
+ Object xObjDict;
+ Object colorSpaceDict;
+ Object patternDict;
+ Object shadingDict;
+ Object gStateDict;
+ GfxResources *next;
+};
+
+class Gfx {
+public:
+
+ // Constructor for regular output.
+ Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict,
+ double hDPI, double vDPI, PDFRectangle *box, GBool crop,
+ PDFRectangle *cropBox, int rotate,
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
+
+ // Constructor for a sub-page object.
+ Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
+ PDFRectangle *box, GBool crop, PDFRectangle *cropBox,
+ GBool (*abortCheckCbkA)(void *data) = NULL,
+ void *abortCheckCbkDataA = NULL);
+
+ ~Gfx();
+
+ // Interpret a stream or array of streams.
+ void display(Object *obj, GBool topLevel = gTrue);
+
+ // Display an annotation, given its appearance (a Form XObject) and
+ // bounding box (in default user space).
+ void doAnnot(Object *str, double xMin, double yMin,
+ double xMax, double yMax);
+
+ // Save graphics state.
+ void saveState();
+
+ // Restore graphics state.
+ void restoreState();
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ OutputDev *out; // output device
+ GBool subPage; // is this a sub-page object?
+ GBool printCommands; // print the drawing commands (for debugging)
+ GfxResources *res; // resource stack
+ int updateLevel;
+
+ GfxState *state; // current graphics state
+ GBool fontChanged; // set if font or text matrix has changed
+ GfxClipType clip; // do a clip?
+ int ignoreUndef; // current BX/EX nesting level
+ double baseMatrix[6]; // default matrix for most recent
+ // page/form/pattern
+ int formDepth;
+
+ Parser *parser; // parser for page content stream(s)
+
+ GBool // callback to check for an abort
+ (*abortCheckCbk)(void *data);
+ void *abortCheckCbkData;
+
+ static Operator opTab[]; // table of operators
+
+ void go(GBool topLevel);
+ void execOp(Object *cmd, Object args[], int numArgs);
+ Operator *findOp(char *name);
+ GBool checkArg(Object *arg, TchkType type);
+ int getPos();
+
+ // graphics state operators
+ void opSave(Object args[], int numArgs);
+ void opRestore(Object args[], int numArgs);
+ void opConcat(Object args[], int numArgs);
+ void opSetDash(Object args[], int numArgs);
+ void opSetFlat(Object args[], int numArgs);
+ void opSetLineJoin(Object args[], int numArgs);
+ void opSetLineCap(Object args[], int numArgs);
+ void opSetMiterLimit(Object args[], int numArgs);
+ void opSetLineWidth(Object args[], int numArgs);
+ void opSetExtGState(Object args[], int numArgs);
+ void opSetRenderingIntent(Object args[], int numArgs);
+
+ // color operators
+ void opSetFillGray(Object args[], int numArgs);
+ void opSetStrokeGray(Object args[], int numArgs);
+ void opSetFillCMYKColor(Object args[], int numArgs);
+ void opSetStrokeCMYKColor(Object args[], int numArgs);
+ void opSetFillRGBColor(Object args[], int numArgs);
+ void opSetStrokeRGBColor(Object args[], int numArgs);
+ void opSetFillColorSpace(Object args[], int numArgs);
+ void opSetStrokeColorSpace(Object args[], int numArgs);
+ void opSetFillColor(Object args[], int numArgs);
+ void opSetStrokeColor(Object args[], int numArgs);
+ void opSetFillColorN(Object args[], int numArgs);
+ void opSetStrokeColorN(Object args[], int numArgs);
+
+ // path segment operators
+ void opMoveTo(Object args[], int numArgs);
+ void opLineTo(Object args[], int numArgs);
+ void opCurveTo(Object args[], int numArgs);
+ void opCurveTo1(Object args[], int numArgs);
+ void opCurveTo2(Object args[], int numArgs);
+ void opRectangle(Object args[], int numArgs);
+ void opClosePath(Object args[], int numArgs);
+
+ // path painting operators
+ void opEndPath(Object args[], int numArgs);
+ void opStroke(Object args[], int numArgs);
+ void opCloseStroke(Object args[], int numArgs);
+ void opFill(Object args[], int numArgs);
+ void opEOFill(Object args[], int numArgs);
+ void opFillStroke(Object args[], int numArgs);
+ void opCloseFillStroke(Object args[], int numArgs);
+ void opEOFillStroke(Object args[], int numArgs);
+ void opCloseEOFillStroke(Object args[], int numArgs);
+ void doPatternFill(GBool eoFill);
+ void doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill);
+ void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill);
+ void opShFill(Object args[], int numArgs);
+ void doFunctionShFill(GfxFunctionShading *shading);
+ void doFunctionShFill1(GfxFunctionShading *shading,
+ double x0, double y0,
+ double x1, double y1,
+ GfxColor *colors, int depth);
+ void doAxialShFill(GfxAxialShading *shading);
+ void doRadialShFill(GfxRadialShading *shading);
+ void doEndPath();
+
+ // path clipping operators
+ void opClip(Object args[], int numArgs);
+ void opEOClip(Object args[], int numArgs);
+
+ // text object operators
+ void opBeginText(Object args[], int numArgs);
+ void opEndText(Object args[], int numArgs);
+
+ // text state operators
+ void opSetCharSpacing(Object args[], int numArgs);
+ void opSetFont(Object args[], int numArgs);
+ void opSetTextLeading(Object args[], int numArgs);
+ void opSetTextRender(Object args[], int numArgs);
+ void opSetTextRise(Object args[], int numArgs);
+ void opSetWordSpacing(Object args[], int numArgs);
+ void opSetHorizScaling(Object args[], int numArgs);
+
+ // text positioning operators
+ void opTextMove(Object args[], int numArgs);
+ void opTextMoveSet(Object args[], int numArgs);
+ void opSetTextMatrix(Object args[], int numArgs);
+ void opTextNextLine(Object args[], int numArgs);
+
+ // text string operators
+ void opShowText(Object args[], int numArgs);
+ void opMoveShowText(Object args[], int numArgs);
+ void opMoveSetShowText(Object args[], int numArgs);
+ void opShowSpaceText(Object args[], int numArgs);
+ void doShowText(GString *s);
+
+ // XObject operators
+ void opXObject(Object args[], int numArgs);
+ void doImage(Object *ref, Stream *str, GBool inlineImg);
+ void doForm(Object *str);
+ void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox);
+
+ // in-line image operators
+ void opBeginImage(Object args[], int numArgs);
+ Stream *buildImageStream();
+ void opImageData(Object args[], int numArgs);
+ void opEndImage(Object args[], int numArgs);
+
+ // type 3 font operators
+ void opSetCharWidth(Object args[], int numArgs);
+ void opSetCacheDevice(Object args[], int numArgs);
+
+ // compatibility operators
+ void opBeginIgnoreUndef(Object args[], int numArgs);
+ void opEndIgnoreUndef(Object args[], int numArgs);
+
+ // marked content operators
+ void opBeginMarkedContent(Object args[], int numArgs);
+ void opEndMarkedContent(Object args[], int numArgs);
+ void opMarkPoint(Object args[], int numArgs);
+
+ void pushResources(Dict *resDict);
+ void popResources();
+};
+
+#endif
diff --git a/pdftops/GfxFont.cxx b/pdftops/GfxFont.cxx
new file mode 100644
index 000000000..8d8c5d77b
--- /dev/null
+++ b/pdftops/GfxFont.cxx
@@ -0,0 +1,1480 @@
+//========================================================================
+//
+// GfxFont.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "gmem.h"
+#include "GHash.h"
+#include "Error.h"
+#include "Object.h"
+#include "Dict.h"
+#include "GlobalParams.h"
+#include "CMap.h"
+#include "CharCodeToUnicode.h"
+#include "FontEncodingTables.h"
+#include "BuiltinFontTables.h"
+#include "FontFile.h"
+#include "GfxFont.h"
+
+//------------------------------------------------------------------------
+
+struct StdFontMapEntry {
+ const char *altName;
+ const char *properName;
+};
+
+// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
+// providing Widths and a FontDescriptor, so we munge the names into
+// the proper Base14 names. This table is from implementation note 44
+// in the PDF 1.4 spec, with some additions based on empirical
+// evidence.
+static StdFontMapEntry stdFontMap[] = {
+ { "Arial", "Helvetica" },
+ { "Arial,Bold", "Helvetica-Bold" },
+ { "Arial,BoldItalic", "Helvetica-BoldOblique" },
+ { "Arial,Italic", "Helvetica-Oblique" },
+ { "Arial-Bold", "Helvetica-Bold" },
+ { "Arial-BoldItalic", "Helvetica-BoldOblique" },
+ { "Arial-BoldItalicMT", "Helvetica-BoldOblique" },
+ { "Arial-BoldMT", "Helvetica-Bold" },
+ { "Arial-Italic", "Helvetica-Oblique" },
+ { "Arial-ItalicMT", "Helvetica-Oblique" },
+ { "ArialMT", "Helvetica" },
+ { "Courier,Bold", "Courier-Bold" },
+ { "Courier,Italic", "Courier-Oblique" },
+ { "Courier,BoldItalic", "Courier-BoldOblique" },
+ { "CourierNew", "Courier" },
+ { "CourierNew,Bold", "Courier-Bold" },
+ { "CourierNew,BoldItalic", "Courier-BoldOblique" },
+ { "CourierNew,Italic", "Courier-Oblique" },
+ { "CourierNew-Bold", "Courier-Bold" },
+ { "CourierNew-BoldItalic", "Courier-BoldOblique" },
+ { "CourierNew-Italic", "Courier-Oblique" },
+ { "CourierNewPS-BoldItalicMT", "Courier-BoldOblique" },
+ { "CourierNewPS-BoldMT", "Courier-Bold" },
+ { "CourierNewPS-ItalicMT", "Courier-Oblique" },
+ { "CourierNewPSMT", "Courier" },
+ { "Helvetica,Bold", "Helvetica-Bold" },
+ { "Helvetica,BoldItalic", "Helvetica-BoldOblique" },
+ { "Helvetica,Italic", "Helvetica-Oblique" },
+ { "Helvetica-BoldItalic", "Helvetica-BoldOblique" },
+ { "Helvetica-Italic", "Helvetica-Oblique" },
+ { "Symbol,Bold", "Symbol" },
+ { "Symbol,BoldItalic", "Symbol" },
+ { "Symbol,Italic", "Symbol" },
+ { "TimesNewRoman", "Times-Roman" },
+ { "TimesNewRoman,Bold", "Times-Bold" },
+ { "TimesNewRoman,BoldItalic", "Times-BoldItalic" },
+ { "TimesNewRoman,Italic", "Times-Italic" },
+ { "TimesNewRoman-Bold", "Times-Bold" },
+ { "TimesNewRoman-BoldItalic", "Times-BoldItalic" },
+ { "TimesNewRoman-Italic", "Times-Italic" },
+ { "TimesNewRomanPS", "Times-Roman" },
+ { "TimesNewRomanPS-Bold", "Times-Bold" },
+ { "TimesNewRomanPS-BoldItalic", "Times-BoldItalic" },
+ { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
+ { "TimesNewRomanPS-BoldMT", "Times-Bold" },
+ { "TimesNewRomanPS-Italic", "Times-Italic" },
+ { "TimesNewRomanPS-ItalicMT", "Times-Italic" },
+ { "TimesNewRomanPSMT", "Times-Roman" }
+};
+
+//------------------------------------------------------------------------
+// GfxFont
+//------------------------------------------------------------------------
+
+GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict) {
+ GString *nameA;
+ GfxFont *font;
+ Object obj1;
+
+ // get base font name
+ nameA = NULL;
+ fontDict->lookup("BaseFont", &obj1);
+ if (obj1.isName()) {
+ nameA = new GString(obj1.getName());
+ }
+ obj1.free();
+
+ // get font type
+ font = NULL;
+ fontDict->lookup("Subtype", &obj1);
+ if (obj1.isName("Type1") || obj1.isName("MMType1")) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
+ } else if (obj1.isName("Type1C")) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
+ } else if (obj1.isName("Type3")) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
+ } else if (obj1.isName("TrueType")) {
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
+ } else if (obj1.isName("Type0")) {
+ font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
+ } else {
+ error(-1, "Unknown font type: '%s'",
+ obj1.isName() ? obj1.getName() : "???");
+ font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
+ }
+ obj1.free();
+
+ return font;
+}
+
+GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA) {
+ ok = gFalse;
+ tag = new GString(tagA);
+ id = idA;
+ name = nameA;
+ origName = nameA;
+ embFontName = NULL;
+ extFontFile = NULL;
+}
+
+GfxFont::~GfxFont() {
+ delete tag;
+ if (origName && origName != name) {
+ delete origName;
+ }
+ if (name) {
+ delete name;
+ }
+ if (embFontName) {
+ delete embFontName;
+ }
+ if (extFontFile) {
+ delete extFontFile;
+ }
+}
+
+void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
+ Object obj1, obj2, obj3, obj4;
+ double t;
+ int i;
+
+ // assume Times-Roman by default (for substitution purposes)
+ flags = fontSerif;
+
+ embFontID.num = -1;
+ embFontID.gen = -1;
+ missingWidth = 0;
+
+ if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
+
+ // get flags
+ if (obj1.dictLookup("Flags", &obj2)->isInt()) {
+ flags = obj2.getInt();
+ }
+ obj2.free();
+
+ // get name
+ obj1.dictLookup("FontName", &obj2);
+ if (obj2.isName()) {
+ embFontName = new GString(obj2.getName());
+ }
+ obj2.free();
+
+ // look for embedded font file
+ if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
+ if (type == fontType1) {
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ }
+ obj2.free();
+ if (embFontID.num == -1 &&
+ obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
+ if (type == fontTrueType || type == fontCIDType2) {
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ }
+ obj2.free();
+ if (embFontID.num == -1 &&
+ obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
+ if (obj2.fetch(xref, &obj3)->isStream()) {
+ obj3.streamGetDict()->lookup("Subtype", &obj4);
+ if (obj4.isName("Type1")) {
+ if (type == fontType1) {
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ } else if (obj4.isName("Type1C")) {
+ if (type == fontType1) {
+ type = fontType1C;
+ embFontID = obj2.getRef();
+ } else if (type == fontType1C) {
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ } else if (obj4.isName("TrueType")) {
+ if (type == fontTrueType) {
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ } else if (obj4.isName("CIDFontType0C")) {
+ if (type == fontCIDType0) {
+ type = fontCIDType0C;
+ embFontID = obj2.getRef();
+ } else {
+ error(-1, "Mismatch between font type and embedded font file");
+ }
+ } else {
+ error(-1, "Unknown embedded font type '%s'",
+ obj4.isName() ? obj4.getName() : "???");
+ }
+ obj4.free();
+ }
+ obj3.free();
+ }
+ obj2.free();
+
+ // look for MissingWidth
+ obj1.dictLookup("MissingWidth", &obj2);
+ if (obj2.isNum()) {
+ missingWidth = obj2.getNum();
+ }
+ obj2.free();
+
+ // get Ascent and Descent
+ obj1.dictLookup("Ascent", &obj2);
+ if (obj2.isNum()) {
+ t = 0.001 * obj2.getNum();
+ // some broken font descriptors set ascent and descent to 0
+ if (t != 0) {
+ ascent = t;
+ }
+ }
+ obj2.free();
+ obj1.dictLookup("Descent", &obj2);
+ if (obj2.isNum()) {
+ t = 0.001 * obj2.getNum();
+ // some broken font descriptors set ascent and descent to 0
+ if (t != 0) {
+ descent = t;
+ }
+ // some broken font descriptors specify a positive descent
+ if (descent > 0) {
+ descent = -descent;
+ }
+ }
+ obj2.free();
+
+ // font FontBBox
+ if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
+ for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
+ if (obj2.arrayGet(i, &obj3)->isNum()) {
+ fontBBox[i] = 0.001 * obj3.getNum();
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+
+ }
+ obj1.free();
+}
+
+CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
+ CharCodeToUnicode *ctu) {
+ GString *buf;
+ Object obj1;
+ int c;
+
+ if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
+ obj1.free();
+ return NULL;
+ }
+ buf = new GString();
+ obj1.streamReset();
+ while ((c = obj1.streamGetChar()) != EOF) {
+ buf->append(c);
+ }
+ obj1.streamClose();
+ obj1.free();
+ if (ctu) {
+ ctu->mergeCMap(buf, nBits);
+ } else {
+ ctu = CharCodeToUnicode::parseCMap(buf, nBits);
+ }
+ delete buf;
+ return ctu;
+}
+
+void GfxFont::findExtFontFile() {
+ static const char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
+ static const char *ttExts[] = { ".ttf", NULL };
+
+ if (name) {
+ if (type == fontType1) {
+ extFontFile = globalParams->findFontFile(name, type1Exts);
+ } else if (type == fontTrueType) {
+ extFontFile = globalParams->findFontFile(name, ttExts);
+ }
+ }
+}
+
+char *GfxFont::readExtFontFile(int *len) {
+ FILE *f;
+ char *buf;
+
+ if (!(f = fopen(extFontFile->getCString(), "rb"))) {
+ error(-1, "External font file '%s' vanished", extFontFile->getCString());
+ return NULL;
+ }
+ fseek(f, 0, SEEK_END);
+ *len = (int)ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = (char *)gmalloc(*len);
+ if ((int)fread(buf, 1, *len, f) != *len) {
+ error(-1, "Error reading external font file '%s'",
+ extFontFile->getCString());
+ }
+ fclose(f);
+ return buf;
+}
+
+char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
+ char *buf;
+ Object obj1, obj2;
+ Stream *str;
+ int c;
+ int size, i;
+
+ obj1.initRef(embFontID.num, embFontID.gen);
+ obj1.fetch(xref, &obj2);
+ if (!obj2.isStream()) {
+ error(-1, "Embedded font file is not a stream");
+ obj2.free();
+ obj1.free();
+ embFontID.num = -1;
+ return NULL;
+ }
+ str = obj2.getStream();
+
+ buf = NULL;
+ i = size = 0;
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ if (i == size) {
+ size += 4096;
+ buf = (char *)grealloc(buf, size);
+ }
+ buf[i++] = c;
+ }
+ *len = i;
+ str->close();
+
+ obj2.free();
+ obj1.free();
+
+ return buf;
+}
+
+//------------------------------------------------------------------------
+// Gfx8BitFont
+//------------------------------------------------------------------------
+
+Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
+ GfxFontType typeA, Dict *fontDict):
+ GfxFont(tagA, idA, nameA)
+{
+ BuiltinFont *builtinFont;
+ const char **baseEnc;
+ GBool baseEncFromFontFile;
+ char *buf;
+ int len;
+ FontFile *fontFile;
+ int code, code2;
+ const char *charName;
+ GBool missing, hex;
+ Unicode toUnicode[256];
+ CharCodeToUnicode *utu, *ctu2;
+ Unicode uBuf[8];
+ double mul;
+ int firstChar, lastChar;
+ Gushort w;
+ Object obj1, obj2, obj3;
+ int n, i, a, b, m;
+
+ type = typeA;
+ ctu = NULL;
+
+ // do font name substitution for various aliases of the Base 14 font
+ // names
+ if (name) {
+ a = 0;
+ b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
+ // invariant: stdFontMap[a].altName <= name < stdFontMap[b].altName
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (name->cmp(stdFontMap[m].altName) >= 0) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ if (!name->cmp(stdFontMap[a].altName)) {
+ name = new GString(stdFontMap[a].properName);
+ }
+ }
+
+ // is it a built-in font?
+ builtinFont = NULL;
+ if (name) {
+ for (i = 0; i < nBuiltinFonts; ++i) {
+ if (!name->cmp(builtinFonts[i].name)) {
+ builtinFont = &builtinFonts[i];
+ break;
+ }
+ }
+ }
+
+ // default ascent/descent values
+ if (builtinFont) {
+ ascent = 0.001 * builtinFont->ascent;
+ descent = 0.001 * builtinFont->descent;
+ fontBBox[0] = 0.001 * builtinFont->bbox[0];
+ fontBBox[1] = 0.001 * builtinFont->bbox[1];
+ fontBBox[2] = 0.001 * builtinFont->bbox[2];
+ fontBBox[3] = 0.001 * builtinFont->bbox[3];
+ } else {
+ ascent = 0.95;
+ descent = -0.35;
+ fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
+ }
+
+ // get info from font descriptor
+ readFontDescriptor(xref, fontDict);
+
+ // look for an external font file
+ findExtFontFile();
+
+ // get font matrix
+ fontMat[0] = fontMat[3] = 1;
+ fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
+ if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
+ for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ fontMat[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ // get Type 3 bounding box, font definition, and resources
+ if (type == fontType3) {
+ if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
+ for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ fontBBox[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+ if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
+ error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
+ charProcs.free();
+ }
+ if (!fontDict->lookup("Resources", &resources)->isDict()) {
+ resources.free();
+ }
+ }
+
+ //----- build the font encoding -----
+
+ // Encodings start with a base encoding, which can come from
+ // (in order of priority):
+ // 1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
+ // - MacRoman / MacExpert / WinAnsi / Standard
+ // 2. embedded or external font file
+ // 3. default:
+ // - builtin --> builtin encoding
+ // - TrueType --> MacRomanEncoding
+ // - others --> StandardEncoding
+ // and then add a list of differences (if any) from
+ // FontDict.Encoding.Differences.
+
+ // check FontDict for base encoding
+ hasEncoding = gFalse;
+ usesMacRomanEnc = gFalse;
+ baseEnc = NULL;
+ baseEncFromFontFile = gFalse;
+ fontDict->lookup("Encoding", &obj1);
+ if (obj1.isDict()) {
+ obj1.dictLookup("BaseEncoding", &obj2);
+ if (obj2.isName("MacRomanEncoding")) {
+ hasEncoding = gTrue;
+ usesMacRomanEnc = gTrue;
+ baseEnc = macRomanEncoding;
+ } else if (obj2.isName("MacExpertEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = macExpertEncoding;
+ } else if (obj2.isName("WinAnsiEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = winAnsiEncoding;
+ } else if (obj2.isName("StandardEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = standardEncoding;
+ }
+ obj2.free();
+ } else if (obj1.isName("MacRomanEncoding")) {
+ hasEncoding = gTrue;
+ usesMacRomanEnc = gTrue;
+ baseEnc = macRomanEncoding;
+ } else if (obj1.isName("MacExpertEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = macExpertEncoding;
+ } else if (obj1.isName("WinAnsiEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = winAnsiEncoding;
+ } else if (obj1.isName("StandardEncoding")) {
+ hasEncoding = gTrue;
+ baseEnc = standardEncoding;
+ }
+
+ // check embedded or external font file for base encoding
+ // (only for Type 1 fonts - trying to get an encoding out of a
+ // TrueType font is a losing proposition)
+ fontFile = NULL;
+ buf = NULL;
+ if ((type == fontType1 || type == fontType1C) &&
+ (extFontFile || embFontID.num >= 0)) {
+ if (extFontFile) {
+ buf = readExtFontFile(&len);
+ } else {
+ buf = readEmbFontFile(xref, &len);
+ }
+ if (buf) {
+ if (type == fontType1C && !strncmp(buf, "%!", 2)) {
+ // various tools (including Adobe's) occasionally embed Type 1
+ // fonts but label them Type 1C
+ type = fontType1;
+ }
+ if (type == fontType1) {
+ fontFile = new Type1FontFile(buf, len);
+ } else {
+ fontFile = new Type1CFontFile(buf, len);
+ if (!((Type1CFontFile *)fontFile)->isOk()) {
+ delete fontFile;
+ fontFile = NULL;
+ }
+ }
+ if (fontFile && fontFile->getName()) {
+ if (embFontName) {
+ delete embFontName;
+ }
+ embFontName = new GString(fontFile->getName());
+ }
+ if (fontFile && !baseEnc) {
+ baseEnc = fontFile->getEncoding();
+ baseEncFromFontFile = gTrue;
+ }
+ gfree(buf);
+ }
+ }
+
+ // get default base encoding
+ if (!baseEnc) {
+ if (builtinFont) {
+ baseEnc = builtinFont->defaultBaseEnc;
+ hasEncoding = gTrue;
+ } else if (type == fontTrueType) {
+ baseEnc = winAnsiEncoding;
+ } else {
+ baseEnc = standardEncoding;
+ }
+ }
+
+ // copy the base encoding
+ for (i = 0; i < 256; ++i) {
+ enc[i] = baseEnc[i];
+ if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
+ enc[i] = copyString(baseEnc[i]);
+ }
+ }
+
+ // merge differences into encoding
+ if (obj1.isDict()) {
+ obj1.dictLookup("Differences", &obj2);
+ if (obj2.isArray()) {
+ hasEncoding = gTrue;
+ code = 0;
+ for (i = 0; i < obj2.arrayGetLength(); ++i) {
+ obj2.arrayGet(i, &obj3);
+ if (obj3.isInt()) {
+ code = obj3.getInt();
+ } else if (obj3.isName()) {
+ if (code >= 0 && code < 256) {
+ if (encFree[code]) {
+ gfree((void *)enc[code]);
+ }
+ enc[code] = copyString(obj3.getName());
+ encFree[code] = gTrue;
+ }
+ ++code;
+ } else {
+ error(-1, "Wrong type in font encoding resource differences (%s)",
+ obj3.getTypeName());
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ }
+ obj1.free();
+ if (fontFile) {
+ delete fontFile;
+ }
+
+ //----- build the mapping to Unicode -----
+
+ // pass 1: use the name-to-Unicode mapping table
+ missing = hex = gFalse;
+ for (code = 0; code < 256; ++code) {
+ if ((charName = enc[code])) {
+ if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
+ strcmp(charName, ".notdef")) {
+ // if it wasn't in the name-to-Unicode table, check for a
+ // name that looks like 'Axx' or 'xx', where 'A' is any letter
+ // and 'xx' is two hex digits
+ if ((strlen(charName) == 3 &&
+ isalpha(charName[0]) &&
+ isxdigit(charName[1]) && isxdigit(charName[2]) &&
+ ((charName[1] >= 'a' && charName[1] <= 'f') ||
+ (charName[1] >= 'A' && charName[1] <= 'F') ||
+ (charName[2] >= 'a' && charName[2] <= 'f') ||
+ (charName[2] >= 'A' && charName[2] <= 'F'))) ||
+ (strlen(charName) == 2 &&
+ isxdigit(charName[0]) && isxdigit(charName[1]) &&
+ ((charName[0] >= 'a' && charName[0] <= 'f') ||
+ (charName[0] >= 'A' && charName[0] <= 'F') ||
+ (charName[1] >= 'a' && charName[1] <= 'f') ||
+ (charName[1] >= 'A' && charName[1] <= 'F')))) {
+ hex = gTrue;
+ }
+ missing = gTrue;
+ }
+ } else {
+ toUnicode[code] = 0;
+ }
+ }
+
+ // pass 2: try to fill in the missing chars, looking for names of
+ // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
+ // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
+ // decimal digits
+ if (missing && globalParams->getMapNumericCharNames()) {
+ for (code = 0; code < 256; ++code) {
+ if ((charName = enc[code]) && !toUnicode[code] &&
+ strcmp(charName, ".notdef")) {
+ n = strlen(charName);
+ code2 = -1;
+ if (hex && n == 3 && isalpha(charName[0]) &&
+ isxdigit(charName[1]) && isxdigit(charName[2])) {
+ sscanf(charName+1, "%x", &code2);
+ } else if (hex && n == 2 &&
+ isxdigit(charName[0]) && isxdigit(charName[1])) {
+ sscanf(charName, "%x", &code2);
+ } else if (!hex && n >= 2 && n <= 4 &&
+ isdigit(charName[0]) && isdigit(charName[1])) {
+ code2 = atoi(charName);
+ } else if (n >= 3 && n <= 5 &&
+ isdigit(charName[1]) && isdigit(charName[2])) {
+ code2 = atoi(charName+1);
+ } else if (n >= 4 && n <= 6 &&
+ isdigit(charName[2]) && isdigit(charName[3])) {
+ code2 = atoi(charName+2);
+ }
+ if (code2 >= 0 && code2 <= 0xff) {
+ toUnicode[code] = (Unicode)code2;
+ }
+ }
+ }
+ }
+
+ // construct the char code -> Unicode mapping object
+ ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
+
+ // merge in a ToUnicode CMap, if there is one -- this overwrites
+ // existing entries in ctu, i.e., the ToUnicode CMap takes
+ // precedence, but the other encoding info is allowed to fill in any
+ // holes
+ readToUnicodeCMap(fontDict, 8, ctu);
+
+ // look for a Unicode-to-Unicode mapping
+ if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
+ for (i = 0; i < 256; ++i) {
+ toUnicode[i] = 0;
+ }
+ ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
+ for (i = 0; i < 256; ++i) {
+ n = ctu->mapToUnicode((CharCode)i, uBuf, 8);
+ if (n >= 1) {
+ n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
+ if (n >= 1) {
+ ctu2->setMapping((CharCode)i, uBuf, n);
+ }
+ }
+ }
+ utu->decRefCnt();
+ delete ctu;
+ ctu = ctu2;
+ }
+
+ //----- get the character widths -----
+
+ // initialize all widths
+ for (code = 0; code < 256; ++code) {
+ widths[code] = missingWidth * 0.001;
+ }
+
+ // use widths from font dict, if present
+ fontDict->lookup("FirstChar", &obj1);
+ firstChar = obj1.isInt() ? obj1.getInt() : 0;
+ obj1.free();
+ if (firstChar < 0 || firstChar > 255) {
+ firstChar = 0;
+ }
+ fontDict->lookup("LastChar", &obj1);
+ lastChar = obj1.isInt() ? obj1.getInt() : 255;
+ obj1.free();
+ if (lastChar < 0 || lastChar > 255) {
+ lastChar = 255;
+ }
+ mul = (type == fontType3) ? fontMat[0] : 0.001;
+ fontDict->lookup("Widths", &obj1);
+ if (obj1.isArray()) {
+ flags |= fontFixedWidth;
+ if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
+ lastChar = firstChar + obj1.arrayGetLength() - 1;
+ }
+ for (code = firstChar; code <= lastChar; ++code) {
+ obj1.arrayGet(code - firstChar, &obj2);
+ if (obj2.isNum()) {
+ widths[code] = obj2.getNum() * mul;
+ if (widths[code] != widths[firstChar]) {
+ flags &= ~fontFixedWidth;
+ }
+ }
+ obj2.free();
+ }
+
+ // use widths from built-in font
+ } else if (builtinFont) {
+ // this is a kludge for broken PDF files that encode char 32
+ // as .notdef
+ if (builtinFont->widths->getWidth("space", &w)) {
+ widths[32] = 0.001 * w;
+ }
+ for (code = 0; code < 256; ++code) {
+ if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
+ widths[code] = 0.001 * w;
+ }
+ }
+
+ // couldn't find widths -- use defaults
+ } else {
+ // this is technically an error -- the Widths entry is required
+ // for all but the Base-14 fonts -- but certain PDF generators
+ // apparently don't include widths for Arial and TimesNewRoman
+ if (isFixedWidth()) {
+ i = 0;
+ } else if (isSerif()) {
+ i = 8;
+ } else {
+ i = 4;
+ }
+ if (isBold()) {
+ i += 2;
+ }
+ if (isItalic()) {
+ i += 1;
+ }
+ builtinFont = builtinFontSubst[i];
+ // this is a kludge for broken PDF files that encode char 32
+ // as .notdef
+ if (builtinFont->widths->getWidth("space", &w)) {
+ widths[32] = 0.001 * w;
+ }
+ for (code = 0; code < 256; ++code) {
+ if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
+ widths[code] = 0.001 * w;
+ }
+ }
+ }
+ obj1.free();
+
+ ok = gTrue;
+}
+
+Gfx8BitFont::~Gfx8BitFont() {
+ int i;
+
+ for (i = 0; i < 256; ++i) {
+ if (encFree[i] && enc[i]) {
+ gfree((void *)enc[i]);
+ }
+ }
+ ctu->decRefCnt();
+ if (charProcs.isDict()) {
+ charProcs.free();
+ }
+ if (resources.isDict()) {
+ resources.free();
+ }
+}
+
+int Gfx8BitFont::getNextChar(const char *s, int len, CharCode *code,
+ Unicode *u, int uSize, int *uLen,
+ double *dx, double *dy, double *ox, double *oy) {
+ CharCode c;
+
+ *code = c = (CharCode)(*s & 0xff);
+ *uLen = ctu->mapToUnicode(c, u, uSize);
+ *dx = widths[c];
+ *dy = *ox = *oy = 0;
+ return 1;
+}
+
+CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
+ ctu->incRefCnt();
+ return ctu;
+}
+
+Gushort *Gfx8BitFont::getCodeToGIDMap(TrueTypeFontFile *ff) {
+ Gushort *map;
+ int cmapPlatform, cmapEncoding;
+ int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
+ GBool useMacRoman, useUnicode;
+ GHash *nameToGID;
+ const char *charName;
+ Unicode u;
+ int code, i, n;
+
+ map = (Gushort *)gmalloc(256 * sizeof(Gushort));
+ for (i = 0; i < 256; ++i) {
+ map[i] = 0;
+ }
+
+ // To match up with the Adobe-defined behaviour, we choose a cmap
+ // like this:
+ // 1. If the PDF font has an encoding:
+ // 1a. If the PDF font specified MacRomanEncoding and the
+ // TrueType font has a Macintosh Roman cmap, use it, and
+ // reverse map the char names through MacRomanEncoding to
+ // get char codes.
+ // 1b. If the TrueType font has a Microsoft Unicode cmap or a
+ // non-Microsoft Unicode cmap, use it, and use the Unicode
+ // indexes, not the char codes.
+ // 1c. If the PDF font is symbolic and the TrueType font has a
+ // Microsoft Symbol cmap, use it, and use char codes
+ // directly (possibly with an offset of 0xf000).
+ // 1d. If the TrueType font has a Macintosh Roman cmap, use it,
+ // as in case 1a.
+ // 2. If the PDF font does not have an encoding:
+ // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
+ // and use char codes directly (possibly with an offset of
+ // 0xf000).
+ // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
+ // and use char codes directly (possible with an offset of
+ // 0xf000).
+ // 3. If none of these rules apply, use the first cmap and hope for
+ // the best (this shouldn't happen).
+ unicodeCmap = macRomanCmap = msSymbolCmap = -1;
+ for (i = 0; i < ff->getNumCmaps(); ++i) {
+ cmapPlatform = ff->getCmapPlatform(i);
+ cmapEncoding = ff->getCmapEncoding(i);
+ if ((cmapPlatform == 3 && cmapEncoding == 1) ||
+ cmapPlatform == 0) {
+ unicodeCmap = i;
+ } else if (cmapPlatform == 1 && cmapEncoding == 0) {
+ macRomanCmap = i;
+ } else if (cmapPlatform == 3 && cmapEncoding == 0) {
+ msSymbolCmap = i;
+ }
+ }
+ cmap = 0;
+ useMacRoman = gFalse;
+ useUnicode = gFalse;
+ if (hasEncoding) {
+ if (usesMacRomanEnc && macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ useMacRoman = gTrue;
+ } else if (unicodeCmap >= 0) {
+ cmap = unicodeCmap;
+ useUnicode = gTrue;
+ } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
+ cmap = msSymbolCmap;
+ } else if (macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ useMacRoman = gTrue;
+ }
+ } else {
+ if (macRomanCmap >= 0) {
+ cmap = macRomanCmap;
+ } else if (msSymbolCmap >= 0) {
+ cmap = msSymbolCmap;
+ }
+ }
+
+ // reverse map the char names through MacRomanEncoding, then map the
+ // char codes through the cmap
+ if (useMacRoman) {
+ for (i = 0; i < 256; ++i) {
+ if ((charName = enc[i])) {
+ if ((code = globalParams->getMacRomanCharCode(charName))) {
+ map[i] = ff->mapCodeToGID(cmap, code);
+ }
+ }
+ }
+
+ // map Unicode through the cmap
+ } else if (useUnicode) {
+ for (i = 0; i < 256; ++i) {
+ if ((n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
+ map[i] = ff->mapCodeToGID(cmap, u);
+ }
+ }
+
+ // map the char codes through the cmap, possibly with an offset of
+ // 0xf000
+ } else {
+ for (i = 0; i < 256; ++i) {
+ if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
+ map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
+ }
+ }
+ }
+
+ // try the TrueType 'post' table to handle any unmapped characters
+ if ((nameToGID = ff->getNameToGID())) {
+ for (i = 0; i < 256; ++i) {
+ if (!map[i] && (charName = enc[i])) {
+ map[i] = (Gushort)(int)nameToGID->lookup(charName);
+ }
+ }
+ delete nameToGID;
+ }
+
+ return map;
+}
+
+Dict *Gfx8BitFont::getCharProcs() {
+ return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
+}
+
+Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
+ if (charProcs.isDict()) {
+ charProcs.dictLookup(enc[code], proc);
+ } else {
+ proc->initNull();
+ }
+ return proc;
+}
+
+Dict *Gfx8BitFont::getResources() {
+ return resources.isDict() ? resources.getDict() : (Dict *)NULL;
+}
+
+//------------------------------------------------------------------------
+// GfxCIDFont
+//------------------------------------------------------------------------
+
+static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
+ return ((GfxFontCIDWidthExcep *)w1)->first -
+ ((GfxFontCIDWidthExcep *)w2)->first;
+}
+
+static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
+ return ((GfxFontCIDWidthExcepV *)w1)->first -
+ ((GfxFontCIDWidthExcepV *)w2)->first;
+}
+
+GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
+ Dict *fontDict):
+ GfxFont(tagA, idA, nameA)
+{
+ Dict *desFontDict;
+ GString *collection, *cMapName;
+ Object desFontDictObj;
+ Object obj1, obj2, obj3, obj4, obj5, obj6;
+ int c1, c2;
+ int excepsSize, i, j, k;
+
+ ascent = 0.95;
+ descent = -0.35;
+ fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
+ cMap = NULL;
+ ctu = NULL;
+ widths.defWidth = 1.0;
+ widths.defHeight = -1.0;
+ widths.defVY = 0.880;
+ widths.exceps = NULL;
+ widths.nExceps = 0;
+ widths.excepsV = NULL;
+ widths.nExcepsV = 0;
+ cidToGID = NULL;
+ cidToGIDLen = 0;
+
+ // get the descendant font
+ if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
+ error(-1, "Missing DescendantFonts entry in Type 0 font");
+ obj1.free();
+ goto err1;
+ }
+ if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
+ error(-1, "Bad descendant font in Type 0 font");
+ goto err3;
+ }
+ obj1.free();
+ desFontDict = desFontDictObj.getDict();
+
+ // font type
+ if (!desFontDict->lookup("Subtype", &obj1)) {
+ error(-1, "Missing Subtype entry in Type 0 descendant font");
+ goto err3;
+ }
+ if (obj1.isName("CIDFontType0")) {
+ type = fontCIDType0;
+ } else if (obj1.isName("CIDFontType2")) {
+ type = fontCIDType2;
+ } else {
+ error(-1, "Unknown Type 0 descendant font type '%s'",
+ obj1.isName() ? obj1.getName() : "???");
+ goto err3;
+ }
+ obj1.free();
+
+ // get info from font descriptor
+ readFontDescriptor(xref, desFontDict);
+
+ // look for an external font file
+ findExtFontFile();
+
+ //----- encoding info -----
+
+ // char collection
+ if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
+ error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
+ goto err3;
+ }
+ obj1.dictLookup("Registry", &obj2);
+ obj1.dictLookup("Ordering", &obj3);
+ if (!obj2.isString() || !obj3.isString()) {
+ error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
+ goto err4;
+ }
+ collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
+ obj3.free();
+ obj2.free();
+ obj1.free();
+
+ // look for a ToUnicode CMap
+ if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
+
+ // the "Adobe-Identity" and "Adobe-UCS" collections don't have
+ // cidToUnicode files
+ if (collection->cmp("Adobe-Identity") &&
+ collection->cmp("Adobe-UCS")) {
+
+ // look for a user-supplied .cidToUnicode file
+ if (!(ctu = globalParams->getCIDToUnicode(collection))) {
+ error(-1, "Unknown character collection '%s'",
+ collection->getCString());
+ delete collection;
+ goto err2;
+ }
+ }
+ }
+
+ // encoding (i.e., CMap)
+ //~ need to handle a CMap stream here
+ //~ also need to deal with the UseCMap entry in the stream dict
+ if (!fontDict->lookup("Encoding", &obj1)->isName()) {
+ error(-1, "Missing or invalid Encoding entry in Type 0 font");
+ delete collection;
+ goto err3;
+ }
+ cMapName = new GString(obj1.getName());
+ obj1.free();
+ if (!(cMap = globalParams->getCMap(collection, cMapName))) {
+ error(-1, "Unknown CMap '%s' for character collection '%s'",
+ cMapName->getCString(), collection->getCString());
+ delete collection;
+ delete cMapName;
+ goto err2;
+ }
+ delete collection;
+ delete cMapName;
+
+ // CIDToGIDMap (for embedded TrueType fonts)
+ if (type == fontCIDType2) {
+ desFontDict->lookup("CIDToGIDMap", &obj1);
+ if (obj1.isStream()) {
+ cidToGIDLen = 0;
+ i = 64;
+ cidToGID = (Gushort *)gmalloc(i * sizeof(Gushort));
+ obj1.streamReset();
+ while ((c1 = obj1.streamGetChar()) != EOF &&
+ (c2 = obj1.streamGetChar()) != EOF) {
+ if (cidToGIDLen == i) {
+ i *= 2;
+ cidToGID = (Gushort *)grealloc(cidToGID, i * sizeof(Gushort));
+ }
+ cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
+ }
+ } else if (!obj1.isName("Identity") && !obj1.isNull()) {
+ error(-1, "Invalid CIDToGIDMap entry in CID font");
+ }
+ obj1.free();
+ }
+
+ //----- character metrics -----
+
+ // default char width
+ if (desFontDict->lookup("DW", &obj1)->isInt()) {
+ widths.defWidth = obj1.getInt() * 0.001;
+ }
+ obj1.free();
+
+ // char width exceptions
+ if (desFontDict->lookup("W", &obj1)->isArray()) {
+ excepsSize = 0;
+ i = 0;
+ while (i + 1 < obj1.arrayGetLength()) {
+ obj1.arrayGet(i, &obj2);
+ obj1.arrayGet(i + 1, &obj3);
+ if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
+ if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
+ if (widths.nExceps == excepsSize) {
+ excepsSize += 16;
+ widths.exceps = (GfxFontCIDWidthExcep *)
+ grealloc(widths.exceps,
+ excepsSize * sizeof(GfxFontCIDWidthExcep));
+ }
+ widths.exceps[widths.nExceps].first = obj2.getInt();
+ widths.exceps[widths.nExceps].last = obj3.getInt();
+ widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
+ ++widths.nExceps;
+ } else {
+ error(-1, "Bad widths array in Type 0 font");
+ }
+ obj4.free();
+ i += 3;
+ } else if (obj2.isInt() && obj3.isArray()) {
+ if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
+ excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
+ widths.exceps = (GfxFontCIDWidthExcep *)
+ grealloc(widths.exceps,
+ excepsSize * sizeof(GfxFontCIDWidthExcep));
+ }
+ j = obj2.getInt();
+ for (k = 0; k < obj3.arrayGetLength(); ++k) {
+ if (obj3.arrayGet(k, &obj4)->isNum()) {
+ widths.exceps[widths.nExceps].first = j;
+ widths.exceps[widths.nExceps].last = j;
+ widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
+ ++j;
+ ++widths.nExceps;
+ } else {
+ error(-1, "Bad widths array in Type 0 font");
+ }
+ obj4.free();
+ }
+ i += 2;
+ } else {
+ error(-1, "Bad widths array in Type 0 font");
+ ++i;
+ }
+ obj3.free();
+ obj2.free();
+ }
+ qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
+ &cmpWidthExcep);
+ }
+ obj1.free();
+
+ // default metrics for vertical font
+ if (desFontDict->lookup("DW2", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ if (obj1.arrayGet(0, &obj2)->isNum()) {
+ widths.defVY = obj2.getNum() * 0.001;
+ }
+ obj2.free();
+ if (obj1.arrayGet(1, &obj2)->isNum()) {
+ widths.defHeight = obj2.getNum() * 0.001;
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ // char metric exceptions for vertical font
+ if (desFontDict->lookup("W2", &obj1)->isArray()) {
+ excepsSize = 0;
+ i = 0;
+ while (i + 1 < obj1.arrayGetLength()) {
+ obj1.arrayGet(i, &obj2);
+ obj1.arrayGet(i+ 1, &obj3);
+ if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
+ if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
+ obj1.arrayGet(i + 3, &obj5)->isNum() &&
+ obj1.arrayGet(i + 4, &obj6)->isNum()) {
+ if (widths.nExcepsV == excepsSize) {
+ excepsSize += 16;
+ widths.excepsV = (GfxFontCIDWidthExcepV *)
+ grealloc(widths.excepsV,
+ excepsSize * sizeof(GfxFontCIDWidthExcepV));
+ }
+ widths.excepsV[widths.nExcepsV].first = obj2.getInt();
+ widths.excepsV[widths.nExcepsV].last = obj3.getInt();
+ widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
+ widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
+ widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
+ ++widths.nExcepsV;
+ } else {
+ error(-1, "Bad widths (W2) array in Type 0 font");
+ }
+ obj6.free();
+ obj5.free();
+ obj4.free();
+ i += 5;
+ } else if (obj2.isInt() && obj3.isArray()) {
+ if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
+ excepsSize =
+ (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
+ widths.excepsV = (GfxFontCIDWidthExcepV *)
+ grealloc(widths.excepsV,
+ excepsSize * sizeof(GfxFontCIDWidthExcepV));
+ }
+ j = obj2.getInt();
+ for (k = 0; k < obj3.arrayGetLength(); k += 3) {
+ if (obj3.arrayGet(k, &obj4)->isNum() &&
+ obj3.arrayGet(k+1, &obj5)->isNum() &&
+ obj3.arrayGet(k+2, &obj6)->isNum()) {
+ widths.excepsV[widths.nExceps].first = j;
+ widths.excepsV[widths.nExceps].last = j;
+ widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
+ widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001;
+ widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001;
+ ++j;
+ ++widths.nExcepsV;
+ } else {
+ error(-1, "Bad widths (W2) array in Type 0 font");
+ }
+ obj6.free();
+ obj5.free();
+ obj4.free();
+ }
+ i += 2;
+ } else {
+ error(-1, "Bad widths (W2) array in Type 0 font");
+ ++i;
+ }
+ obj3.free();
+ obj2.free();
+ }
+ qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
+ &cmpWidthExcepV);
+ }
+ obj1.free();
+
+ desFontDictObj.free();
+ ok = gTrue;
+ return;
+
+ err4:
+ obj3.free();
+ obj2.free();
+ err3:
+ obj1.free();
+ err2:
+ desFontDictObj.free();
+ err1:;
+}
+
+GfxCIDFont::~GfxCIDFont() {
+ if (cMap) {
+ cMap->decRefCnt();
+ }
+ if (ctu) {
+ ctu->decRefCnt();
+ }
+ gfree(widths.exceps);
+ gfree(widths.excepsV);
+ if (cidToGID) {
+ gfree(cidToGID);
+ }
+}
+
+int GfxCIDFont::getNextChar(const char *s, int len, CharCode *code,
+ Unicode *u, int uSize, int *uLen,
+ double *dx, double *dy, double *ox, double *oy) {
+ CID cid;
+ double w, h, vx, vy;
+ int n, a, b, m;
+
+ if (!cMap) {
+ *code = 0;
+ *uLen = 0;
+ *dx = *dy = 0;
+ return 1;
+ }
+
+ *code = (CharCode)(cid = cMap->getCID(s, len, &n));
+ if (ctu) {
+ *uLen = ctu->mapToUnicode(cid, u, uSize);
+ } else {
+ *uLen = 0;
+ }
+
+ // horizontal
+ if (cMap->getWMode() == 0) {
+ w = widths.defWidth;
+ h = vx = vy = 0;
+ if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
+ a = 0;
+ b = widths.nExceps;
+ // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (widths.exceps[m].first <= cid) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ if (cid <= widths.exceps[a].last) {
+ w = widths.exceps[a].width;
+ }
+ }
+
+ // vertical
+ } else {
+ w = 0;
+ h = widths.defHeight;
+ vx = widths.defWidth / 2;
+ vy = widths.defVY;
+ if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
+ a = 0;
+ b = widths.nExcepsV;
+ // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (widths.excepsV[m].last <= cid) {
+ a = m;
+ } else {
+ b = m;
+ }
+ }
+ if (cid <= widths.excepsV[a].last) {
+ h = widths.excepsV[a].height;
+ vx = widths.excepsV[a].vx;
+ vy = widths.excepsV[a].vy;
+ }
+ }
+ }
+
+ *dx = w;
+ *dy = h;
+ *ox = vx;
+ *oy = vy;
+
+ return n;
+}
+
+int GfxCIDFont::getWMode() {
+ return cMap ? cMap->getWMode() : 0;
+}
+
+CharCodeToUnicode *GfxCIDFont::getToUnicode() {
+ ctu->incRefCnt();
+ return ctu;
+}
+
+GString *GfxCIDFont::getCollection() {
+ return cMap ? cMap->getCollection() : (GString *)NULL;
+}
+
+//------------------------------------------------------------------------
+// GfxFontDict
+//------------------------------------------------------------------------
+
+GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
+ int i;
+ Object obj1, obj2;
+ Ref r;
+
+ numFonts = fontDict->getLength();
+ fonts = (GfxFont **)gmalloc(numFonts * sizeof(GfxFont *));
+ for (i = 0; i < numFonts; ++i) {
+ fontDict->getValNF(i, &obj1);
+ obj1.fetch(xref, &obj2);
+ if (obj2.isDict()) {
+ if (obj1.isRef()) {
+ r = obj1.getRef();
+ } else {
+ // no indirect reference for this font, so invent a unique one
+ // (legal generation numbers are five digits, so any 6-digit
+ // number would be safe)
+ r.num = i;
+ if (fontDictRef) {
+ r.gen = 100000 + fontDictRef->num;
+ } else {
+ r.gen = 999999;
+ }
+ }
+ fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
+ r, obj2.getDict());
+ if (fonts[i] && !fonts[i]->isOk()) {
+ delete fonts[i];
+ fonts[i] = NULL;
+ }
+ } else {
+ error(-1, "font resource is not a dictionary");
+ fonts[i] = NULL;
+ }
+ obj1.free();
+ obj2.free();
+ }
+}
+
+GfxFontDict::~GfxFontDict() {
+ int i;
+
+ for (i = 0; i < numFonts; ++i) {
+ if (fonts[i]) {
+ delete fonts[i];
+ }
+ }
+ gfree(fonts);
+}
+
+GfxFont *GfxFontDict::lookup(const char *tag) {
+ int i;
+
+ for (i = 0; i < numFonts; ++i) {
+ if (fonts[i] && fonts[i]->matches(tag)) {
+ return fonts[i];
+ }
+ }
+ return NULL;
+}
diff --git a/pdftops/GfxFont.h b/pdftops/GfxFont.h
new file mode 100644
index 000000000..c70065467
--- /dev/null
+++ b/pdftops/GfxFont.h
@@ -0,0 +1,315 @@
+//========================================================================
+//
+// GfxFont.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GFXFONT_H
+#define GFXFONT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "GString.h"
+#include "Object.h"
+#include "CharTypes.h"
+
+class Dict;
+class CMap;
+class CharCodeToUnicode;
+class TrueTypeFontFile;
+struct GfxFontCIDWidths;
+
+//------------------------------------------------------------------------
+// GfxFontType
+//------------------------------------------------------------------------
+
+enum GfxFontType {
+ //----- Gfx8BitFont
+ fontUnknownType,
+ fontType1,
+ fontType1C,
+ fontType3,
+ fontTrueType,
+ //----- GfxCIDFont
+ fontCIDType0,
+ fontCIDType0C,
+ fontCIDType2
+};
+
+//------------------------------------------------------------------------
+// GfxFontCIDWidths
+//------------------------------------------------------------------------
+
+struct GfxFontCIDWidthExcep {
+ CID first; // this record applies to
+ CID last; // CIDs <first>..<last>
+ double width; // char width
+};
+
+struct GfxFontCIDWidthExcepV {
+ CID first; // this record applies to
+ CID last; // CIDs <first>..<last>
+ double height; // char height
+ double vx, vy; // origin position
+};
+
+struct GfxFontCIDWidths {
+ double defWidth; // default char width
+ double defHeight; // default char height
+ double defVY; // default origin position
+ GfxFontCIDWidthExcep *exceps; // exceptions
+ int nExceps; // number of valid entries in exceps
+ GfxFontCIDWidthExcepV * // exceptions for vertical font
+ excepsV;
+ int nExcepsV; // number of valid entries in excepsV
+};
+
+//------------------------------------------------------------------------
+// GfxFont
+//------------------------------------------------------------------------
+
+#define fontFixedWidth (1 << 0)
+#define fontSerif (1 << 1)
+#define fontSymbolic (1 << 2)
+#define fontItalic (1 << 6)
+#define fontBold (1 << 18)
+
+class GfxFont {
+public:
+
+ // Build a GfxFont object.
+ static GfxFont *makeFont(XRef *xref, const char *tagA, Ref idA, Dict *fontDict);
+
+ GfxFont(const char *tagA, Ref idA, GString *nameA);
+
+ virtual ~GfxFont();
+
+ GBool isOk() { return ok; }
+
+ // Get font tag.
+ GString *getTag() { return tag; }
+
+ // Get font dictionary ID.
+ Ref *getID() { return &id; }
+
+ // Does this font match the tag?
+ GBool matches(const char *tagA) { return !tag->cmp(tagA); }
+
+ // Get base font name.
+ GString *getName() { return name; }
+
+ // Get the original font name (ignornig any munging that might have
+ // been done to map to a canonical Base-14 font name).
+ GString *getOrigName() { return origName; }
+
+ // Get font type.
+ GfxFontType getType() { return type; }
+ virtual GBool isCIDFont() { return gFalse; }
+
+ // Get embedded font ID, i.e., a ref for the font file stream.
+ // Returns false if there is no embedded font.
+ GBool getEmbeddedFontID(Ref *embID)
+ { *embID = embFontID; return embFontID.num >= 0; }
+
+ // Get the PostScript font name for the embedded font. Returns
+ // NULL if there is no embedded font.
+ GString *getEmbeddedFontName() { return embFontName; }
+
+ // Get the name of the external font file. Returns NULL if there
+ // is no external font file.
+ GString *getExtFontFile() { return extFontFile; }
+
+ // Get font descriptor flags.
+ GBool isFixedWidth() { return flags & fontFixedWidth; }
+ GBool isSerif() { return flags & fontSerif; }
+ GBool isSymbolic() { return flags & fontSymbolic; }
+ GBool isItalic() { return flags & fontItalic; }
+ GBool isBold() { return flags & fontBold; }
+
+ // Return the font matrix.
+ double *getFontMatrix() { return fontMat; }
+
+ // Return the font bounding box.
+ double *getFontBBox() { return fontBBox; }
+
+ // Return the ascent and descent values.
+ double getAscent() { return ascent; }
+ double getDescent() { return descent; }
+
+ // Return the writing mode (0=horizontal, 1=vertical).
+ virtual int getWMode() { return 0; }
+
+ // Read an external or embedded font file into a buffer.
+ char *readExtFontFile(int *len);
+ char *readEmbFontFile(XRef *xref, int *len);
+
+ // Get the next char from a string <s> of <len> bytes, returning the
+ // char <code>, its Unicode mapping <u>, its displacement vector
+ // (<dx>, <dy>), and its origin offset vector (<ox>, <oy>). <uSize>
+ // is the number of entries available in <u>, and <uLen> is set to
+ // the number actually used. Returns the number of bytes used by
+ // the char code.
+ virtual int getNextChar(const char *s, int len, CharCode *code,
+ Unicode *u, int uSize, int *uLen,
+ double *dx, double *dy, double *ox, double *oy) = 0;
+
+protected:
+
+ void readFontDescriptor(XRef *xref, Dict *fontDict);
+ CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits,
+ CharCodeToUnicode *ctu);
+ void findExtFontFile();
+
+ GString *tag; // PDF font tag
+ Ref id; // reference (used as unique ID)
+ GString *name; // font name
+ GString *origName; // original font name
+ GfxFontType type; // type of font
+ int flags; // font descriptor flags
+ GString *embFontName; // name of embedded font
+ Ref embFontID; // ref to embedded font file stream
+ GString *extFontFile; // external font file name
+ double fontMat[6]; // font matrix (Type 3 only)
+ double fontBBox[4]; // font bounding box (Type 3 only)
+ double missingWidth; // "default" width
+ double ascent; // max height above baseline
+ double descent; // max depth below baseline
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// Gfx8BitFont
+//------------------------------------------------------------------------
+
+class Gfx8BitFont: public GfxFont {
+public:
+
+ Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
+ GfxFontType typeA, Dict *fontDict);
+
+ virtual ~Gfx8BitFont();
+
+ virtual int getNextChar(const char *s, int len, CharCode *code,
+ Unicode *u, int uSize, int *uLen,
+ double *dx, double *dy, double *ox, double *oy);
+
+ // Return the encoding.
+ const char **getEncoding() { return enc; }
+
+ // Return the Unicode map.
+ CharCodeToUnicode *getToUnicode();
+
+ // Return the character name associated with <code>.
+ const char *getCharName(int code) { return enc[code]; }
+
+ // Returns true if the PDF font specified an encoding.
+ GBool getHasEncoding() { return hasEncoding; }
+
+ // Returns true if the PDF font specified MacRomanEncoding.
+ GBool getUsesMacRomanEnc() { return usesMacRomanEnc; }
+
+ // Get width of a character.
+ double getWidth(Guchar c) { return widths[c]; }
+
+ // Return a char code-to-GID mapping for the provided font file.
+ // (This is only useful for TrueType fonts.)
+ Gushort *getCodeToGIDMap(TrueTypeFontFile *ff);
+
+ // Return the Type 3 CharProc dictionary, or NULL if none.
+ Dict *getCharProcs();
+
+ // Return the Type 3 CharProc for the character associated with <code>.
+ Object *getCharProc(int code, Object *proc);
+
+ // Return the Type 3 Resources dictionary, or NULL if none.
+ Dict *getResources();
+
+private:
+
+ const char *enc[256]; // char code --> char name
+ char encFree[256]; // boolean for each char name: if set,
+ // the string is malloc'ed
+ CharCodeToUnicode *ctu; // char code --> Unicode
+ GBool hasEncoding;
+ GBool usesMacRomanEnc;
+ double widths[256]; // character widths
+ Object charProcs; // Type 3 CharProcs dictionary
+ Object resources; // Type 3 Resources dictionary
+};
+
+//------------------------------------------------------------------------
+// GfxCIDFont
+//------------------------------------------------------------------------
+
+class GfxCIDFont: public GfxFont {
+public:
+
+ GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
+ Dict *fontDict);
+
+ virtual ~GfxCIDFont();
+
+ virtual GBool isCIDFont() { return gTrue; }
+
+ virtual int getNextChar(const char *s, int len, CharCode *code,
+ Unicode *u, int uSize, int *uLen,
+ double *dx, double *dy, double *ox, double *oy);
+
+ // Return the writing mode (0=horizontal, 1=vertical).
+ virtual int getWMode();
+
+ // Return the Unicode map.
+ CharCodeToUnicode *getToUnicode();
+
+ // Get the collection name (<registry>-<ordering>).
+ GString *getCollection();
+
+ // Return the CID-to-GID mapping table. These should only be called
+ // if type is fontCIDType2.
+ Gushort *getCIDToGID() { return cidToGID; }
+ int getCIDToGIDLen() { return cidToGIDLen; }
+
+private:
+
+ CMap *cMap; // char code --> CID
+ CharCodeToUnicode *ctu; // CID --> Unicode
+ GfxFontCIDWidths widths; // character widths
+ Gushort *cidToGID; // CID --> GID mapping (for embedded
+ // TrueType fonts)
+ int cidToGIDLen;
+};
+
+//------------------------------------------------------------------------
+// GfxFontDict
+//------------------------------------------------------------------------
+
+class GfxFontDict {
+public:
+
+ // Build the font dictionary, given the PDF font dictionary.
+ GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict);
+
+ // Destructor.
+ ~GfxFontDict();
+
+ // Get the specified font.
+ GfxFont *lookup(const char *tag);
+
+ // Iterative access.
+ int getNumFonts() { return numFonts; }
+ GfxFont *getFont(int i) { return fonts[i]; }
+
+private:
+
+ GfxFont **fonts; // list of fonts
+ int numFonts; // number of fonts
+};
+
+#endif
diff --git a/pdftops/GfxState.cxx b/pdftops/GfxState.cxx
new file mode 100644
index 000000000..89c9b5bc9
--- /dev/null
+++ b/pdftops/GfxState.cxx
@@ -0,0 +1,2762 @@
+//========================================================================
+//
+// GfxState.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <math.h>
+#include <string.h> // for memcpy()
+#include "gmem.h"
+#include "Error.h"
+#include "Object.h"
+#include "Array.h"
+#include "Page.h"
+#include "GfxState.h"
+
+//------------------------------------------------------------------------
+
+static inline double clip01(double x) {
+ return (x < 0) ? 0 : ((x > 1) ? 1 : x);
+}
+
+//------------------------------------------------------------------------
+
+static const char *gfxColorSpaceModeNames[] = {
+ "DeviceGray",
+ "CalGray",
+ "DeviceRGB",
+ "CalRGB",
+ "DeviceCMYK",
+ "Lab",
+ "ICCBased",
+ "Indexed",
+ "Separation",
+ "DeviceN",
+ "Pattern"
+};
+
+#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
+
+//------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+GfxColorSpace::GfxColorSpace() {
+}
+
+GfxColorSpace::~GfxColorSpace() {
+}
+
+GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
+ GfxColorSpace *cs;
+ Object obj1;
+
+ cs = NULL;
+ if (csObj->isName()) {
+ if (csObj->isName("DeviceGray") || csObj->isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (csObj->isName("Pattern")) {
+ cs = new GfxPatternColorSpace(NULL);
+ } else {
+ error(-1, "Bad color space '%s'", csObj->getName());
+ }
+ } else if (csObj->isArray()) {
+ csObj->arrayGet(0, &obj1);
+ if (obj1.isName("DeviceGray") || obj1.isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (obj1.isName("CalGray")) {
+ cs = GfxCalGrayColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("CalRGB")) {
+ cs = GfxCalRGBColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Lab")) {
+ cs = GfxLabColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("ICCBased")) {
+ cs = GfxICCBasedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Indexed") || obj1.isName("I")) {
+ cs = GfxIndexedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Separation")) {
+ cs = GfxSeparationColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("DeviceN")) {
+ cs = GfxDeviceNColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Pattern")) {
+ cs = GfxPatternColorSpace::parse(csObj->getArray());
+ } else {
+ error(-1, "Bad color space");
+ }
+ obj1.free();
+ } else {
+ error(-1, "Bad color space - expected name or array");
+ }
+ return cs;
+}
+
+void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < getNComps(); ++i) {
+ decodeLow[i] = 0;
+ decodeRange[i] = 1;
+ }
+}
+
+int GfxColorSpace::getNumColorSpaceModes() {
+ return nGfxColorSpaceModes;
+}
+
+const char *GfxColorSpace::getColorSpaceModeName(int idx) {
+ return gfxColorSpaceModeNames[idx];
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
+}
+
+GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
+ return new GfxDeviceGrayColorSpace();
+}
+
+void GfxDeviceGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxCalGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ gamma = 1;
+}
+
+GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::copy() {
+ GfxCalGrayColorSpace *cs;
+
+ cs = new GfxCalGrayColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gamma = gamma;
+ return cs;
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
+ GfxCalGrayColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalGray color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxCalGrayColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
+ cs->gamma = obj2.getNum();
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxCalGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
+}
+
+GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
+ return new GfxDeviceRGBColorSpace();
+}
+
+void GfxDeviceRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
+}
+
+void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
+}
+
+void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ gammaR = gammaG = gammaB = 1;
+ mat[0] = 1; mat[1] = 0; mat[2] = 0;
+ mat[3] = 0; mat[4] = 1; mat[5] = 0;
+ mat[6] = 0; mat[7] = 0; mat[8] = 1;
+}
+
+GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
+}
+
+GfxColorSpace *GfxCalRGBColorSpace::copy() {
+ GfxCalRGBColorSpace *cs;
+ int i;
+
+ cs = new GfxCalRGBColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gammaR = gammaR;
+ cs->gammaG = gammaG;
+ cs->gammaB = gammaB;
+ for (i = 0; i < 9; ++i) {
+ cs->mat[i] = mat[i];
+ }
+ return cs;
+}
+
+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
+ GfxCalRGBColorSpace *cs;
+ Object obj1, obj2, obj3;
+ int i;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalRGB color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxCalRGBColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->gammaR = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->gammaG = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->gammaB = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 9) {
+ for (i = 0; i < 9; ++i) {
+ obj2.arrayGet(i, &obj3);
+ cs->mat[i] = obj3.getNum();
+ obj3.free();
+ }
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxCalRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
+}
+
+GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
+ return new GfxDeviceCMYKColorSpace();
+}
+
+void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(1 - color->c[3]
+ - 0.299 * color->c[0]
+ - 0.587 * color->c[1]
+ - 0.114 * color->c[2]);
+}
+
+void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ double c, m, y, aw, ac, am, ay, ar, ag, ab;
+
+ c = clip01(color->c[0] + color->c[3]);
+ m = clip01(color->c[1] + color->c[3]);
+ y = clip01(color->c[2] + color->c[3]);
+ aw = (1-c) * (1-m) * (1-y);
+ ac = c * (1-m) * (1-y);
+ am = (1-c) * m * (1-y);
+ ay = (1-c) * (1-m) * y;
+ ar = (1-c) * m * y;
+ ag = c * (1-m) * y;
+ ab = c * m * (1-y);
+ rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar);
+ rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag);
+ rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag +
+ 0.4863*ab);
+}
+
+void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = clip01(color->c[0]);
+ cmyk->m = clip01(color->c[1]);
+ cmyk->y = clip01(color->c[2]);
+ cmyk->k = clip01(color->c[3]);
+}
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
+// Language Reference, Third Edition.
+static double xyzrgb[3][3] = {
+ { 3.240449, -1.537136, -0.498531 },
+ { -0.969265, 1.876011, 0.041556 },
+ { 0.055643, -0.204026, 1.057229 }
+};
+
+GfxLabColorSpace::GfxLabColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ aMin = bMin = -100;
+ aMax = bMax = 100;
+}
+
+GfxLabColorSpace::~GfxLabColorSpace() {
+}
+
+GfxColorSpace *GfxLabColorSpace::copy() {
+ GfxLabColorSpace *cs;
+
+ cs = new GfxLabColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->aMin = aMin;
+ cs->aMax = aMax;
+ cs->bMin = bMin;
+ cs->bMax = bMax;
+ cs->kr = kr;
+ cs->kg = kg;
+ cs->kb = kb;
+ return cs;
+}
+
+GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
+ GfxLabColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad Lab color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxLabColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 4) {
+ obj2.arrayGet(0, &obj3);
+ cs->aMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->aMax = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->bMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(3, &obj3);
+ cs->bMax = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ obj1.free();
+
+ cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
+ xyzrgb[0][1] * cs->whiteY +
+ xyzrgb[0][2] * cs->whiteZ);
+ cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
+ xyzrgb[1][1] * cs->whiteY +
+ xyzrgb[1][2] * cs->whiteZ);
+ cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
+ xyzrgb[2][1] * cs->whiteY +
+ xyzrgb[2][2] * cs->whiteZ);
+
+ return cs;
+}
+
+void GfxLabColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxRGB rgb;
+
+ getRGB(color, &rgb);
+ *gray = clip01(0.299 * rgb.r +
+ 0.587 * rgb.g +
+ 0.114 * rgb.b);
+}
+
+void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ double X, Y, Z;
+ double t1, t2;
+ double r, g, b;
+
+ // convert L*a*b* to CIE 1931 XYZ color space
+ t1 = (color->c[0] + 16) / 116;
+ t2 = t1 + color->c[1] / 500;
+ if (t2 >= (6.0 / 29.0)) {
+ X = t2 * t2 * t2;
+ } else {
+ X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
+ }
+ X *= whiteX;
+ if (t1 >= (6.0 / 29.0)) {
+ Y = t1 * t1 * t1;
+ } else {
+ Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
+ }
+ Y *= whiteY;
+ t2 = t1 - color->c[2] / 200;
+ if (t2 >= (6.0 / 29.0)) {
+ Z = t2 * t2 * t2;
+ } else {
+ Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
+ }
+ Z *= whiteZ;
+
+ // convert XYZ to RGB, including gamut mapping and gamma correction
+ r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
+ g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
+ b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
+ rgb->r = pow(clip01(r * kr), 0.5);
+ rgb->g = pow(clip01(g * kg), 0.5);
+ rgb->b = pow(clip01(b * kb), 0.5);
+}
+
+void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxRGB rgb;
+ double c, m, y, k;
+
+ getRGB(color, &rgb);
+ c = clip01(1 - rgb.r);
+ m = clip01(1 - rgb.g);
+ y = clip01(1 - rgb.b);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = 100;
+ decodeLow[1] = aMin;
+ decodeRange[1] = aMax - aMin;
+ decodeLow[2] = bMin;
+ decodeRange[2] = bMax - bMin;
+}
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
+ Ref *iccProfileStreamA) {
+ nComps = nCompsA;
+ alt = altA;
+ iccProfileStream = *iccProfileStreamA;
+ rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
+ rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
+}
+
+GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
+ delete alt;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::copy() {
+ GfxICCBasedColorSpace *cs;
+ int i;
+
+ cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
+ for (i = 0; i < 4; ++i) {
+ cs->rangeMin[i] = rangeMin[i];
+ cs->rangeMax[i] = rangeMax[i];
+ }
+ return cs;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
+ GfxICCBasedColorSpace *cs;
+ Ref iccProfileStreamA;
+ int nCompsA;
+ GfxColorSpace *altA;
+ Dict *dict;
+ Object obj1, obj2, obj3;
+ int i;
+
+ arr->getNF(1, &obj1);
+ if (obj1.isRef()) {
+ iccProfileStreamA = obj1.getRef();
+ } else {
+ iccProfileStreamA.num = 0;
+ iccProfileStreamA.gen = 0;
+ }
+ obj1.free();
+ arr->get(1, &obj1);
+ if (!obj1.isStream()) {
+ error(-1, "Bad ICCBased color space (stream)");
+ obj1.free();
+ return NULL;
+ }
+ dict = obj1.streamGetDict();
+ if (!dict->lookup("N", &obj2)->isInt()) {
+ error(-1, "Bad ICCBased color space (N)");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
+ nCompsA = obj2.getInt();
+ obj2.free();
+ if (nCompsA > gfxColorMaxComps) {
+ error(-1, "ICCBased color space with too many (%d > %d) components",
+ nCompsA, gfxColorMaxComps);
+ nCompsA = gfxColorMaxComps;
+ }
+ if (dict->lookup("Alternate", &obj2)->isNull() ||
+ !(altA = GfxColorSpace::parse(&obj2))) {
+ switch (nCompsA) {
+ case 1:
+ altA = new GfxDeviceGrayColorSpace();
+ break;
+ case 3:
+ altA = new GfxDeviceRGBColorSpace();
+ break;
+ case 4:
+ altA = new GfxDeviceCMYKColorSpace();
+ break;
+ default:
+ error(-1, "Bad ICCBased color space - invalid N");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
+ }
+ obj2.free();
+ cs = new GfxICCBasedColorSpace(nCompsA, altA, &iccProfileStreamA);
+ if (dict->lookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2 * nCompsA) {
+ for (i = 0; i < nCompsA; ++i) {
+ obj2.arrayGet(2*i, &obj3);
+ cs->rangeMin[i] = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2*i+1, &obj3);
+ cs->rangeMax[i] = obj3.getNum();
+ obj3.free();
+ }
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxICCBasedColorSpace::getGray(GfxColor *color, double *gray) {
+ alt->getGray(color, gray);
+}
+
+void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ alt->getRGB(color, rgb);
+}
+
+void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ alt->getCMYK(color, cmyk);
+}
+
+void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ decodeLow[i] = rangeMin[i];
+ decodeRange[i] = rangeMax[i] - rangeMin[i];
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxIndexedColorSpace
+//------------------------------------------------------------------------
+
+GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *baseA,
+ int indexHighA) {
+ base = baseA;
+ indexHigh = indexHighA;
+ lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
+ sizeof(Guchar));
+}
+
+GfxIndexedColorSpace::~GfxIndexedColorSpace() {
+ delete base;
+ gfree(lookup);
+}
+
+GfxColorSpace *GfxIndexedColorSpace::copy() {
+ GfxIndexedColorSpace *cs;
+
+ cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
+ memcpy(cs->lookup, lookup,
+ (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
+ return cs;
+}
+
+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
+ GfxIndexedColorSpace *cs;
+ GfxColorSpace *baseA;
+ int indexHighA;
+ Object obj1;
+ int x;
+ char *s;
+ int n, i, j;
+
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Indexed color space");
+ goto err1;
+ }
+ arr->get(1, &obj1);
+ if (!(baseA = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Indexed color space (base color space)");
+ goto err2;
+ }
+ obj1.free();
+ if (!arr->get(2, &obj1)->isInt()) {
+ error(-1, "Bad Indexed color space (hival)");
+ delete baseA;
+ goto err2;
+ }
+ indexHighA = obj1.getInt();
+ if (indexHighA < 0 || indexHighA > 255) {
+ // the PDF spec requires indexHigh to be in [0,255] -- allowing
+ // values larger than 255 creates a security hole: if nComps *
+ // indexHigh is greater than 2^31, the loop below may overwrite
+ // past the end of the array
+ error(-1, "Bad Indexed color space (invalid indexHigh value)");
+ delete baseA;
+ goto err2;
+ }
+ obj1.free();
+ cs = new GfxIndexedColorSpace(baseA, indexHighA);
+ arr->get(3, &obj1);
+ n = baseA->getNComps();
+ if (obj1.isStream()) {
+ obj1.streamReset();
+ for (i = 0; i <= indexHighA; ++i) {
+ for (j = 0; j < n; ++j) {
+ if ((x = obj1.streamGetChar()) == EOF) {
+ error(-1, "Bad Indexed color space (lookup table stream too short)");
+ goto err3;
+ }
+ cs->lookup[i*n + j] = (Guchar)x;
+ }
+ }
+ obj1.streamClose();
+ } else if (obj1.isString()) {
+ if (obj1.getString()->getLength() < (indexHighA + 1) * n) {
+ error(-1, "Bad Indexed color space (lookup table string too short)");
+ goto err3;
+ }
+ s = obj1.getString()->getCString();
+ for (i = 0; i <= indexHighA; ++i) {
+ for (j = 0; j < n; ++j) {
+ cs->lookup[i*n + j] = (Guchar)*s++;
+ }
+ }
+ } else {
+ error(-1, "Bad Indexed color space (lookup table)");
+ goto err3;
+ }
+ obj1.free();
+ return cs;
+
+ err3:
+ delete cs;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+GfxColor *GfxIndexedColorSpace::mapColorToBase(GfxColor *color,
+ GfxColor *baseColor) {
+ Guchar *p;
+ double low[gfxColorMaxComps], range[gfxColorMaxComps];
+ int n, i;
+
+ n = base->getNComps();
+ base->getDefaultRanges(low, range, indexHigh);
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ baseColor->c[i] = low[i] + (p[i] / 255.0) * range[i];
+ }
+ return baseColor;
+}
+
+void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ base->getGray(mapColorToBase(color, &color2), gray);
+}
+
+void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ base->getRGB(mapColorToBase(color, &color2), rgb);
+}
+
+void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ base->getCMYK(mapColorToBase(color, &color2), cmyk);
+}
+
+void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = maxImgPixel;
+}
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
+ GfxColorSpace *altA,
+ Function *funcA) {
+ name = nameA;
+ alt = altA;
+ func = funcA;
+}
+
+GfxSeparationColorSpace::~GfxSeparationColorSpace() {
+ delete name;
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxSeparationColorSpace::copy() {
+ return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
+}
+
+//~ handle the 'All' and 'None' colorants
+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
+ GfxSeparationColorSpace *cs;
+ GString *nameA;
+ GfxColorSpace *altA;
+ Function *funcA;
+ Object obj1;
+
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Separation color space");
+ goto err1;
+ }
+ if (!arr->get(1, &obj1)->isName()) {
+ error(-1, "Bad Separation color space (name)");
+ goto err2;
+ }
+ nameA = new GString(obj1.getName());
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(altA = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Separation color space (alternate color space)");
+ goto err3;
+ }
+ obj1.free();
+ arr->get(3, &obj1);
+ if (!(funcA = Function::parse(&obj1))) {
+ goto err4;
+ }
+ obj1.free();
+ cs = new GfxSeparationColorSpace(nameA, altA, funcA);
+ return cs;
+
+ err4:
+ delete altA;
+ err3:
+ delete nameA;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxSeparationColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
+ GfxColorSpace *altA,
+ Function *funcA) {
+ nComps = nCompsA;
+ alt = altA;
+ func = funcA;
+}
+
+GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ delete names[i];
+ }
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxDeviceNColorSpace::copy() {
+ GfxDeviceNColorSpace *cs;
+ int i;
+
+ cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
+ for (i = 0; i < nComps; ++i) {
+ cs->names[i] = names[i]->copy();
+ }
+ return cs;
+}
+
+//~ handle the 'None' colorant
+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
+ GfxDeviceNColorSpace *cs;
+ int nCompsA;
+ GString *namesA[gfxColorMaxComps];
+ GfxColorSpace *altA;
+ Function *funcA;
+ Object obj1, obj2;
+ int i;
+
+ if (arr->getLength() != 4 && arr->getLength() != 5) {
+ error(-1, "Bad DeviceN color space");
+ goto err1;
+ }
+ if (!arr->get(1, &obj1)->isArray()) {
+ error(-1, "Bad DeviceN color space (names)");
+ goto err2;
+ }
+ nCompsA = obj1.arrayGetLength();
+ if (nCompsA > gfxColorMaxComps) {
+ error(-1, "DeviceN color space with too many (%d > %d) components",
+ nCompsA, gfxColorMaxComps);
+ nCompsA = gfxColorMaxComps;
+ }
+ for (i = 0; i < nCompsA; ++i) {
+ if (!obj1.arrayGet(i, &obj2)->isName()) {
+ error(-1, "Bad DeviceN color space (names)");
+ obj2.free();
+ goto err2;
+ }
+ namesA[i] = new GString(obj2.getName());
+ obj2.free();
+ }
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(altA = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad DeviceN color space (alternate color space)");
+ goto err3;
+ }
+ obj1.free();
+ arr->get(3, &obj1);
+ if (!(funcA = Function::parse(&obj1))) {
+ goto err4;
+ }
+ obj1.free();
+ cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+ for (i = 0; i < nCompsA; ++i) {
+ cs->names[i] = namesA[i];
+ }
+ return cs;
+
+ err4:
+ delete altA;
+ err3:
+ for (i = 0; i < nCompsA; ++i) {
+ delete namesA[i];
+ }
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxDeviceNColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
+}
+
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) {
+ under = underA;
+}
+
+GfxPatternColorSpace::~GfxPatternColorSpace() {
+ if (under) {
+ delete under;
+ }
+}
+
+GfxColorSpace *GfxPatternColorSpace::copy() {
+ return new GfxPatternColorSpace(under ? under->copy() :
+ (GfxColorSpace *)NULL);
+}
+
+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
+ GfxPatternColorSpace *cs;
+ GfxColorSpace *underA;
+ Object obj1;
+
+ if (arr->getLength() != 1 && arr->getLength() != 2) {
+ error(-1, "Bad Pattern color space");
+ return NULL;
+ }
+ underA = NULL;
+ if (arr->getLength() == 2) {
+ arr->get(1, &obj1);
+ if (!(underA = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Pattern color space (underlying color space)");
+ obj1.free();
+ return NULL;
+ }
+ obj1.free();
+ }
+ cs = new GfxPatternColorSpace(underA);
+ return cs;
+}
+
+void GfxPatternColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = 0;
+}
+
+void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = 0;
+}
+
+void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = 1;
+}
+
+//------------------------------------------------------------------------
+// Pattern
+//------------------------------------------------------------------------
+
+GfxPattern::GfxPattern(int typeA) {
+ type = typeA;
+}
+
+GfxPattern::~GfxPattern() {
+}
+
+GfxPattern *GfxPattern::parse(Object *obj) {
+ GfxPattern *pattern;
+ Object obj1;
+
+ if (obj->isDict()) {
+ obj->dictLookup("PatternType", &obj1);
+ } else if (obj->isStream()) {
+ obj->streamGetDict()->lookup("PatternType", &obj1);
+ } else {
+ return NULL;
+ }
+ pattern = NULL;
+ if (obj1.isInt() && obj1.getInt() == 1) {
+ pattern = GfxTilingPattern::parse(obj);
+ } else if (obj1.isInt() && obj1.getInt() == 2) {
+ pattern = GfxShadingPattern::parse(obj);
+ }
+ obj1.free();
+ return pattern;
+}
+
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+GfxTilingPattern *GfxTilingPattern::parse(Object *patObj) {
+ GfxTilingPattern *pat;
+ Dict *dict;
+ int paintTypeA, tilingTypeA;
+ double bboxA[4], matrixA[6];
+ double xStepA, yStepA;
+ Object resDictA;
+ Object obj1, obj2;
+ int i;
+
+ if (!patObj->isStream()) {
+ return NULL;
+ }
+ dict = patObj->streamGetDict();
+
+ if (dict->lookup("PaintType", &obj1)->isInt()) {
+ paintTypeA = obj1.getInt();
+ } else {
+ paintTypeA = 1;
+ error(-1, "Invalid or missing PaintType in pattern");
+ }
+ obj1.free();
+ if (dict->lookup("TilingType", &obj1)->isInt()) {
+ tilingTypeA = obj1.getInt();
+ } else {
+ tilingTypeA = 1;
+ error(-1, "Invalid or missing TilingType in pattern");
+ }
+ obj1.free();
+ bboxA[0] = bboxA[1] = 0;
+ bboxA[2] = bboxA[3] = 1;
+ if (dict->lookup("BBox", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ for (i = 0; i < 4; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ bboxA[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ } else {
+ error(-1, "Invalid or missing BBox in pattern");
+ }
+ obj1.free();
+ if (dict->lookup("XStep", &obj1)->isNum()) {
+ xStepA = obj1.getNum();
+ } else {
+ xStepA = 1;
+ error(-1, "Invalid or missing XStep in pattern");
+ }
+ obj1.free();
+ if (dict->lookup("YStep", &obj1)->isNum()) {
+ yStepA = obj1.getNum();
+ } else {
+ yStepA = 1;
+ error(-1, "Invalid or missing YStep in pattern");
+ }
+ obj1.free();
+ if (!dict->lookup("Resources", &resDictA)->isDict()) {
+ resDictA.free();
+ resDictA.initNull();
+ error(-1, "Invalid or missing Resources in pattern");
+ }
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ for (i = 0; i < 6; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ matrixA[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ pat = new GfxTilingPattern(paintTypeA, tilingTypeA, bboxA, xStepA, yStepA,
+ &resDictA, matrixA, patObj);
+ resDictA.free();
+ return pat;
+}
+
+GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA,
+ double *bboxA, double xStepA, double yStepA,
+ Object *resDictA, double *matrixA,
+ Object *contentStreamA):
+ GfxPattern(1)
+{
+ int i;
+
+ paintType = paintTypeA;
+ tilingType = tilingTypeA;
+ for (i = 0; i < 4; ++i) {
+ bbox[i] = bboxA[i];
+ }
+ xStep = xStepA;
+ yStep = yStepA;
+ resDictA->copy(&resDict);
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+ contentStreamA->copy(&contentStream);
+}
+
+GfxTilingPattern::~GfxTilingPattern() {
+ resDict.free();
+ contentStream.free();
+}
+
+GfxPattern *GfxTilingPattern::copy() {
+ return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep,
+ &resDict, matrix, &contentStream);
+}
+
+//------------------------------------------------------------------------
+// GfxShadingPattern
+//------------------------------------------------------------------------
+
+GfxShadingPattern *GfxShadingPattern::parse(Object *patObj) {
+ Dict *dict;
+ GfxShading *shadingA;
+ double matrixA[6];
+ Object obj1, obj2;
+ int i;
+
+ if (!patObj->isDict()) {
+ return NULL;
+ }
+ dict = patObj->getDict();
+
+ dict->lookup("Shading", &obj1);
+ shadingA = GfxShading::parse(&obj1);
+ obj1.free();
+ if (!shadingA) {
+ return NULL;
+ }
+
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ for (i = 0; i < 6; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ matrixA[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ }
+ obj1.free();
+
+ return new GfxShadingPattern(shadingA, matrixA);
+}
+
+GfxShadingPattern::GfxShadingPattern(GfxShading *shadingA, double *matrixA):
+ GfxPattern(2)
+{
+ int i;
+
+ shading = shadingA;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+}
+
+GfxShadingPattern::~GfxShadingPattern() {
+ delete shading;
+}
+
+GfxPattern *GfxShadingPattern::copy() {
+ return new GfxShadingPattern(shading->copy(), matrix);
+}
+
+//------------------------------------------------------------------------
+// GfxShading
+//------------------------------------------------------------------------
+
+GfxShading::GfxShading(int typeA) {
+ type = typeA;
+ colorSpace = NULL;
+}
+
+GfxShading::GfxShading(GfxShading *shading) {
+ int i;
+
+ type = shading->type;
+ colorSpace = shading->colorSpace->copy();
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ background.c[i] = shading->background.c[i];
+ }
+ hasBackground = shading->hasBackground;
+ xMin = shading->xMin;
+ yMin = shading->yMin;
+ xMax = shading->xMax;
+ yMax = shading->yMax;
+ hasBBox = shading->hasBBox;
+}
+
+GfxShading::~GfxShading() {
+ if (colorSpace) {
+ delete colorSpace;
+}
+}
+
+GfxShading *GfxShading::parse(Object *obj) {
+ GfxShading *shading;
+ Dict *dict;
+ int typeA;
+ Object obj1;
+
+ if (obj->isDict()) {
+ dict = obj->getDict();
+ } else if (obj->isStream()) {
+ dict = obj->streamGetDict();
+ } else {
+ return NULL;
+ }
+
+ if (!dict->lookup("ShadingType", &obj1)->isInt()) {
+ error(-1, "Invalid ShadingType in shading dictionary");
+ obj1.free();
+ return NULL;
+ }
+ typeA = obj1.getInt();
+ obj1.free();
+
+ switch (typeA) {
+ case 1:
+ shading = GfxFunctionShading::parse(dict);
+ break;
+ case 2:
+ shading = GfxAxialShading::parse(dict);
+ break;
+ case 3:
+ shading = GfxRadialShading::parse(dict);
+ break;
+ default:
+ error(-1, "Unimplemented shading type %d", typeA);
+ goto err1;
+ }
+
+ return shading;
+
+ err1:
+ return NULL;
+}
+
+GBool GfxShading::init(Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
+ dict->lookup("ColorSpace", &obj1);
+ if (!(colorSpace = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad color space in shading dictionary");
+ obj1.free();
+ return gFalse;
+ }
+ obj1.free();
+
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ background.c[i] = 0;
+ }
+ hasBackground = gFalse;
+ if (dict->lookup("Background", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == colorSpace->getNComps()) {
+ hasBackground = gTrue;
+ for (i = 0; i < colorSpace->getNComps(); ++i) {
+ background.c[i] = obj1.arrayGet(i, &obj2)->getNum();
+ obj2.free();
+ }
+ } else {
+ error(-1, "Bad Background in shading dictionary");
+ }
+ }
+ obj1.free();
+
+ xMin = yMin = xMax = yMax = 0;
+ hasBBox = gFalse;
+ if (dict->lookup("BBox", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() == 4) {
+ hasBBox = gTrue;
+ xMin = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ yMin = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ xMax = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ yMax = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Bad BBox in shading dictionary");
+ }
+ }
+ obj1.free();
+
+ return gTrue;
+ }
+
+//------------------------------------------------------------------------
+// GfxFunctionShading
+//------------------------------------------------------------------------
+
+GfxFunctionShading::GfxFunctionShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double *matrixA,
+ Function **funcsA, int nFuncsA):
+ GfxShading(1)
+{
+ int i;
+
+ x0 = x0A;
+ y0 = y0A;
+ x1 = x1A;
+ y1 = y1A;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = matrixA[i];
+ }
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+}
+
+GfxFunctionShading::GfxFunctionShading(GfxFunctionShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ for (i = 0; i < 6; ++i) {
+ matrix[i] = shading->matrix[i];
+ }
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+}
+
+GfxFunctionShading::~GfxFunctionShading() {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxFunctionShading *GfxFunctionShading::parse(Dict *dict) {
+ GfxFunctionShading *shading;
+ double x0A, y0A, x1A, y1A;
+ double matrixA[6];
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = 0;
+ x1A = y1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ matrixA[0] = 1; matrixA[1] = 0;
+ matrixA[2] = 0; matrixA[3] = 1;
+ matrixA[4] = 0; matrixA[5] = 0;
+ if (dict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ matrixA[0] = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ matrixA[1] = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ matrixA[2] = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ matrixA[3] = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ matrixA[4] = obj1.arrayGet(4, &obj2)->getNum();
+ obj2.free();
+ matrixA[5] = obj1.arrayGet(5, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ goto err2;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ goto err1;
+ }
+ }
+ obj1.free();
+
+ shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA,
+ funcsA, nFuncsA);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
+
+ err2:
+ obj2.free();
+ err1:
+ obj1.free();
+ return NULL;
+}
+
+GfxShading *GfxFunctionShading::copy() {
+ return new GfxFunctionShading(this);
+}
+
+void GfxFunctionShading::getColor(double x, double y, GfxColor *color) {
+ double in[2];
+ int i;
+
+ in[0] = x;
+ in[1] = y;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(in, &color->c[i]);
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxAxialShading
+//------------------------------------------------------------------------
+
+GfxAxialShading::GfxAxialShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A):
+ GfxShading(2)
+{
+ int i;
+
+ x0 = x0A;
+ y0 = y0A;
+ x1 = x1A;
+ y1 = y1A;
+ t0 = t0A;
+ t1 = t1A;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+ extend0 = extend0A;
+ extend1 = extend1A;
+}
+
+GfxAxialShading::GfxAxialShading(GfxAxialShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ t0 = shading->t0;
+ y1 = shading->t1;
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+ extend0 = shading->extend0;
+ extend1 = shading->extend1;
+}
+
+GfxAxialShading::~GfxAxialShading() {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxAxialShading *GfxAxialShading::parse(Dict *dict) {
+ GfxAxialShading *shading;
+ double x0A, y0A, x1A, y1A;
+ double t0A, t1A;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ GBool extend0A, extend1A;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = x1A = y1A = 0;
+ if (dict->lookup("Coords", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Missing or invalid Coords in shading dictionary");
+ goto err1;
+ }
+ obj1.free();
+
+ t0A = 0;
+ t1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ t0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ t1A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
+ }
+ }
+ obj1.free();
+
+ extend0A = extend1A = gFalse;
+ if (dict->lookup("Extend", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ extend0A = obj1.arrayGet(0, &obj2)->getBool();
+ obj2.free();
+ extend1A = obj1.arrayGet(1, &obj2)->getBool();
+ obj2.free();
+ }
+ obj1.free();
+
+ shading = new GfxAxialShading(x0A, y0A, x1A, y1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
+
+ err1:
+ return NULL;
+}
+
+GfxShading *GfxAxialShading::copy() {
+ return new GfxAxialShading(this);
+}
+
+void GfxAxialShading::getColor(double t, GfxColor *color) {
+ int i;
+
+ // NB: there can be one function with n outputs or n functions with
+ // one output each (where n = number of color components)
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(&t, &color->c[i]);
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxRadialShading
+//------------------------------------------------------------------------
+
+GfxRadialShading::GfxRadialShading(double x0A, double y0A, double r0A,
+ double x1A, double y1A, double r1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A):
+ GfxShading(3)
+{
+ int i;
+
+ x0 = x0A;
+ y0 = y0A;
+ r0 = r0A;
+ x1 = x1A;
+ y1 = y1A;
+ r1 = r1A;
+ t0 = t0A;
+ t1 = t1A;
+ nFuncs = nFuncsA;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = funcsA[i];
+ }
+ extend0 = extend0A;
+ extend1 = extend1A;
+}
+
+GfxRadialShading::GfxRadialShading(GfxRadialShading *shading):
+ GfxShading(shading)
+{
+ int i;
+
+ x0 = shading->x0;
+ y0 = shading->y0;
+ r0 = shading->r0;
+ x1 = shading->x1;
+ y1 = shading->y1;
+ r1 = shading->r1;
+ t0 = shading->t0;
+ y1 = shading->t1;
+ nFuncs = shading->nFuncs;
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i] = shading->funcs[i]->copy();
+ }
+ extend0 = shading->extend0;
+ extend1 = shading->extend1;
+}
+
+GfxRadialShading::~GfxRadialShading() {
+ int i;
+
+ for (i = 0; i < nFuncs; ++i) {
+ delete funcs[i];
+ }
+}
+
+GfxRadialShading *GfxRadialShading::parse(Dict *dict) {
+ GfxRadialShading *shading;
+ double x0A, y0A, r0A, x1A, y1A, r1A;
+ double t0A, t1A;
+ Function *funcsA[gfxColorMaxComps];
+ int nFuncsA;
+ GBool extend0A, extend1A;
+ Object obj1, obj2;
+ int i;
+
+ x0A = y0A = r0A = x1A = y1A = r1A = 0;
+ if (dict->lookup("Coords", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ x0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ y0A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ r0A = obj1.arrayGet(2, &obj2)->getNum();
+ obj2.free();
+ x1A = obj1.arrayGet(3, &obj2)->getNum();
+ obj2.free();
+ y1A = obj1.arrayGet(4, &obj2)->getNum();
+ obj2.free();
+ r1A = obj1.arrayGet(5, &obj2)->getNum();
+ obj2.free();
+ } else {
+ error(-1, "Missing or invalid Coords in shading dictionary");
+ goto err1;
+ }
+ obj1.free();
+
+ t0A = 0;
+ t1A = 1;
+ if (dict->lookup("Domain", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ t0A = obj1.arrayGet(0, &obj2)->getNum();
+ obj2.free();
+ t1A = obj1.arrayGet(1, &obj2)->getNum();
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Function", &obj1);
+ if (obj1.isArray()) {
+ nFuncsA = obj1.arrayGetLength();
+ if (nFuncsA > gfxColorMaxComps) {
+ error(-1, "Invalid Function array in shading dictionary");
+ goto err1;
+ }
+ for (i = 0; i < nFuncsA; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!(funcsA[i] = Function::parse(&obj2))) {
+ obj1.free();
+ obj2.free();
+ goto err1;
+ }
+ obj2.free();
+ }
+ } else {
+ nFuncsA = 1;
+ if (!(funcsA[0] = Function::parse(&obj1))) {
+ obj1.free();
+ goto err1;
+ }
+ }
+ obj1.free();
+
+ extend0A = extend1A = gFalse;
+ if (dict->lookup("Extend", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 2) {
+ extend0A = obj1.arrayGet(0, &obj2)->getBool();
+ obj2.free();
+ extend1A = obj1.arrayGet(1, &obj2)->getBool();
+ obj2.free();
+ }
+ obj1.free();
+
+ shading = new GfxRadialShading(x0A, y0A, r0A, x1A, y1A, r1A, t0A, t1A,
+ funcsA, nFuncsA, extend0A, extend1A);
+ if (!shading->init(dict)) {
+ delete shading;
+ return NULL;
+ }
+ return shading;
+
+ err1:
+ return NULL;
+}
+
+GfxShading *GfxRadialShading::copy() {
+ return new GfxRadialShading(this);
+}
+
+void GfxRadialShading::getColor(double t, GfxColor *color) {
+ int i;
+
+ // NB: there can be one function with n outputs or n functions with
+ // one output each (where n = number of color components)
+ for (i = 0; i < nFuncs; ++i) {
+ funcs[i]->transform(&t, &color->c[i]);
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxImageColorMap
+//------------------------------------------------------------------------
+
+GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
+ GfxColorSpace *colorSpaceA) {
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *sepCS;
+ int maxPixel, indexHigh;
+ Guchar *lookup2;
+ Function *sepFunc;
+ Object obj;
+ double x[gfxColorMaxComps];
+ double y[gfxColorMaxComps];
+ int i, j, k;
+
+ ok = gTrue;
+
+ // bits per component and color space
+ bits = bitsA;
+ maxPixel = (1 << bits) - 1;
+ colorSpace = colorSpaceA;
+
+ // get decode map
+ if (decode->isNull()) {
+ nComps = colorSpace->getNComps();
+ colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
+ } else if (decode->isArray()) {
+ nComps = decode->arrayGetLength() / 2;
+ if (nComps != colorSpace->getNComps()) {
+ goto err1;
+ }
+ for (i = 0; i < nComps; ++i) {
+ decode->arrayGet(2*i, &obj);
+ if (!obj.isNum()) {
+ goto err2;
+ }
+ decodeLow[i] = obj.getNum();
+ obj.free();
+ decode->arrayGet(2*i+1, &obj);
+ if (!obj.isNum()) {
+ goto err2;
+ }
+ decodeRange[i] = obj.getNum() - decodeLow[i];
+ obj.free();
+ }
+ } else {
+ goto err1;
+ }
+
+ // Construct a lookup table -- this stores pre-computed decoded
+ // values for each component, i.e., the result of applying the
+ // decode mapping to each possible image pixel component value.
+ //
+ // Optimization: for Indexed and Separation color spaces (which have
+ // only one component), we store color values in the lookup table
+ // rather than component values.
+ colorSpace2 = NULL;
+ nComps2 = 0;
+ if (colorSpace->getMode() == csIndexed) {
+ // Note that indexHigh may not be the same as maxPixel --
+ // Distiller will remove unused palette entries, resulting in
+ // indexHigh < maxPixel.
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ colorSpace2 = indexedCS->getBase();
+ indexHigh = indexedCS->getIndexHigh();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+ lookup2 = indexedCS->getLookup();
+ colorSpace2->getDefaultRanges(x, y, indexHigh);
+ for (i = 0; i <= indexHigh; ++i) {
+ j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[j*nComps2 + k] = x[k] + (lookup2[i*nComps2 + k] / 255.0) * y[k];
+ }
+ }
+ } else if (colorSpace->getMode() == csSeparation) {
+ sepCS = (GfxSeparationColorSpace *)colorSpace;
+ colorSpace2 = sepCS->getAlt();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
+ sepFunc = sepCS->getFunc();
+ for (i = 0; i <= maxPixel; ++i) {
+ x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+ sepFunc->transform(x, y);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[i*nComps2 + k] = y[k];
+ }
+ }
+ } else {
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
+ for (i = 0; i <= maxPixel; ++i) {
+ for (k = 0; k < nComps; ++k) {
+ lookup[i*nComps + k] = decodeLow[k] +
+ (i * decodeRange[k]) / maxPixel;
+ }
+ }
+ }
+
+ return;
+
+ err2:
+ obj.free();
+ err1:
+ ok = gFalse;
+}
+
+GfxImageColorMap::GfxImageColorMap(GfxImageColorMap *colorMap) {
+ int n, i;
+
+ colorSpace = colorMap->colorSpace->copy();
+ bits = colorMap->bits;
+ nComps = colorMap->nComps;
+ nComps2 = colorMap->nComps2;
+ colorSpace2 = NULL;
+ lookup = NULL;
+ if (colorSpace->getMode() == csIndexed) {
+ colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase();
+ n = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
+ n = (n + 1) * nComps2 * sizeof(double);
+ } else if (colorSpace->getMode() == csSeparation) {
+ colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt();
+ n = (1 << bits) - 1;
+ n = (n + 1) * nComps2 * sizeof(double);
+ } else {
+ n = (1 << bits) - 1;
+ n = (n + 1) * nComps * sizeof(double);
+ }
+ lookup = (double *)gmalloc(n);
+ memcpy(lookup, colorMap->lookup, n);
+ for (i = 0; i < nComps; ++i) {
+ decodeLow[i] = colorMap->decodeLow[i];
+ decodeRange[i] = colorMap->decodeRange[i];
+ }
+ ok = gTrue;
+}
+
+GfxImageColorMap::~GfxImageColorMap() {
+ delete colorSpace;
+ gfree(lookup);
+}
+
+void GfxImageColorMap::getGray(Guchar *x, double *gray) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getGray(&color, gray);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getGray(&color, gray);
+ }
+}
+
+void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getRGB(&color, rgb);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getRGB(&color, rgb);
+ }
+}
+
+void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getCMYK(&color, cmyk);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getCMYK(&color, cmyk);
+ }
+}
+
+void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) {
+ int maxPixel, i;
+
+ maxPixel = (1 << bits) - 1;
+ for (i = 0; i < nComps; ++i) {
+ color->c[i] = decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel;
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxSubpath and GfxPath
+//------------------------------------------------------------------------
+
+GfxSubpath::GfxSubpath(double x1, double y1) {
+ size = 16;
+ x = (double *)gmalloc(size * sizeof(double));
+ y = (double *)gmalloc(size * sizeof(double));
+ curve = (GBool *)gmalloc(size * sizeof(GBool));
+ n = 1;
+ x[0] = x1;
+ y[0] = y1;
+ curve[0] = gFalse;
+ closed = gFalse;
+}
+
+GfxSubpath::~GfxSubpath() {
+ gfree(x);
+ gfree(y);
+ gfree(curve);
+}
+
+// Used for copy().
+GfxSubpath::GfxSubpath(GfxSubpath *subpath) {
+ size = subpath->size;
+ n = subpath->n;
+ x = (double *)gmalloc(size * sizeof(double));
+ y = (double *)gmalloc(size * sizeof(double));
+ curve = (GBool *)gmalloc(size * sizeof(GBool));
+ memcpy(x, subpath->x, n * sizeof(double));
+ memcpy(y, subpath->y, n * sizeof(double));
+ memcpy(curve, subpath->curve, n * sizeof(GBool));
+ closed = subpath->closed;
+}
+
+void GfxSubpath::lineTo(double x1, double y1) {
+ if (n >= size) {
+ size += 16;
+ x = (double *)grealloc(x, size * sizeof(double));
+ y = (double *)grealloc(y, size * sizeof(double));
+ curve = (GBool *)grealloc(curve, size * sizeof(GBool));
+ }
+ x[n] = x1;
+ y[n] = y1;
+ curve[n] = gFalse;
+ ++n;
+}
+
+void GfxSubpath::curveTo(double x1, double y1, double x2, double y2,
+ double x3, double y3) {
+ if (n+3 > size) {
+ size += 16;
+ x = (double *)grealloc(x, size * sizeof(double));
+ y = (double *)grealloc(y, size * sizeof(double));
+ curve = (GBool *)grealloc(curve, size * sizeof(GBool));
+ }
+ x[n] = x1;
+ y[n] = y1;
+ x[n+1] = x2;
+ y[n+1] = y2;
+ x[n+2] = x3;
+ y[n+2] = y3;
+ curve[n] = curve[n+1] = gTrue;
+ curve[n+2] = gFalse;
+ n += 3;
+}
+
+void GfxSubpath::close() {
+ if (x[n-1] != x[0] || y[n-1] != y[0]) {
+ lineTo(x[0], y[0]);
+ }
+ closed = gTrue;
+}
+
+void GfxSubpath::offset(double dx, double dy) {
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ x[i] += dx;
+ y[i] += dy;
+ }
+}
+
+GfxPath::GfxPath() {
+ justMoved = gFalse;
+ size = 16;
+ n = 0;
+ firstX = firstY = 0;
+ subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
+}
+
+GfxPath::~GfxPath() {
+ int i;
+
+ for (i = 0; i < n; ++i)
+ delete subpaths[i];
+ gfree(subpaths);
+}
+
+// Used for copy().
+GfxPath::GfxPath(GBool justMoved1, double firstX1, double firstY1,
+ GfxSubpath **subpaths1, int n1, int size1) {
+ int i;
+
+ justMoved = justMoved1;
+ firstX = firstX1;
+ firstY = firstY1;
+ size = size1;
+ n = n1;
+ subpaths = (GfxSubpath **)gmalloc(size * sizeof(GfxSubpath *));
+ for (i = 0; i < n; ++i)
+ subpaths[i] = subpaths1[i]->copy();
+}
+
+void GfxPath::moveTo(double x, double y) {
+ justMoved = gTrue;
+ firstX = x;
+ firstY = y;
+}
+
+void GfxPath::lineTo(double x, double y) {
+ if (justMoved) {
+ if (n >= size) {
+ size += 16;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ ++n;
+ justMoved = gFalse;
+ }
+ subpaths[n-1]->lineTo(x, y);
+}
+
+void GfxPath::curveTo(double x1, double y1, double x2, double y2,
+ double x3, double y3) {
+ if (justMoved) {
+ if (n >= size) {
+ size += 16;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ ++n;
+ justMoved = gFalse;
+ }
+ subpaths[n-1]->curveTo(x1, y1, x2, y2, x3, y3);
+}
+
+void GfxPath::close() {
+ // this is necessary to handle the pathological case of
+ // moveto/closepath/clip, which defines an empty clipping region
+ if (justMoved) {
+ if (n >= size) {
+ size += 16;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ subpaths[n] = new GfxSubpath(firstX, firstY);
+ ++n;
+ justMoved = gFalse;
+ }
+ subpaths[n-1]->close();
+}
+
+void GfxPath::append(GfxPath *path) {
+ int i;
+
+ if (n + path->n > size) {
+ size = n + path->n;
+ subpaths = (GfxSubpath **)
+ grealloc(subpaths, size * sizeof(GfxSubpath *));
+ }
+ for (i = 0; i < path->n; ++i) {
+ subpaths[n++] = path->subpaths[i]->copy();
+ }
+ justMoved = gFalse;
+}
+
+void GfxPath::offset(double dx, double dy) {
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ subpaths[i]->offset(dx, dy);
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxState
+//------------------------------------------------------------------------
+
+GfxState::GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+ int rotate, GBool upsideDown) {
+ double kx, ky;
+
+ px1 = pageBox->x1;
+ py1 = pageBox->y1;
+ px2 = pageBox->x2;
+ py2 = pageBox->y2;
+ kx = hDPI / 72.0;
+ ky = vDPI / 72.0;
+ if (rotate == 90) {
+ ctm[0] = 0;
+ ctm[1] = upsideDown ? ky : -ky;
+ ctm[2] = kx;
+ ctm[3] = 0;
+ ctm[4] = -kx * py1;
+ ctm[5] = ky * (upsideDown ? -px1 : px2);
+ pageWidth = kx * (py2 - py1);
+ pageHeight = ky * (px2 - px1);
+ } else if (rotate == 180) {
+ ctm[0] = -kx;
+ ctm[1] = 0;
+ ctm[2] = 0;
+ ctm[3] = upsideDown ? ky : -ky;
+ ctm[4] = kx * px2;
+ ctm[5] = ky * (upsideDown ? -py1 : py2);
+ pageWidth = kx * (px2 - px1);
+ pageHeight = ky * (py2 - py1);
+ } else if (rotate == 270) {
+ ctm[0] = 0;
+ ctm[1] = upsideDown ? -ky : ky;
+ ctm[2] = -kx;
+ ctm[3] = 0;
+ ctm[4] = kx * py2;
+ ctm[5] = ky * (upsideDown ? px2 : -px1);
+ pageWidth = kx * (py2 - py1);
+ pageHeight = ky * (px2 - px1);
+ } else {
+ ctm[0] = kx;
+ ctm[1] = 0;
+ ctm[2] = 0;
+ ctm[3] = upsideDown ? -ky : ky;
+ ctm[4] = -kx * px1;
+ ctm[5] = ky * (upsideDown ? py2 : -py1);
+ pageWidth = kx * (px2 - px1);
+ pageHeight = ky * (py2 - py1);
+ }
+
+ fillColorSpace = new GfxDeviceGrayColorSpace();
+ strokeColorSpace = new GfxDeviceGrayColorSpace();
+ fillColor.c[0] = 0;
+ strokeColor.c[0] = 0;
+ fillPattern = NULL;
+ strokePattern = NULL;
+ fillOpacity = 1;
+ strokeOpacity = 1;
+
+ lineWidth = 1;
+ lineDash = NULL;
+ lineDashLength = 0;
+ lineDashStart = 0;
+ flatness = 1;
+ lineJoin = 0;
+ lineCap = 0;
+ miterLimit = 10;
+
+ font = NULL;
+ fontSize = 0;
+ textMat[0] = 1; textMat[1] = 0;
+ textMat[2] = 0; textMat[3] = 1;
+ textMat[4] = 0; textMat[5] = 0;
+ charSpace = 0;
+ wordSpace = 0;
+ horizScaling = 1;
+ leading = 0;
+ rise = 0;
+ render = 0;
+
+ path = new GfxPath();
+ curX = curY = 0;
+ lineX = lineY = 0;
+
+ clipXMin = 0;
+ clipYMin = 0;
+ clipXMax = pageWidth;
+ clipYMax = pageHeight;
+
+ saved = NULL;
+}
+
+GfxState::~GfxState() {
+ if (fillColorSpace) {
+ delete fillColorSpace;
+ }
+ if (strokeColorSpace) {
+ delete strokeColorSpace;
+ }
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ if (strokePattern) {
+ delete strokePattern;
+ }
+ gfree(lineDash);
+ if (path) {
+ // this gets set to NULL by restore()
+ delete path;
+ }
+ if (saved) {
+ delete saved;
+ }
+}
+
+// Used for copy();
+GfxState::GfxState(GfxState *state) {
+ memcpy(this, state, sizeof(GfxState));
+ if (fillColorSpace) {
+ fillColorSpace = state->fillColorSpace->copy();
+ }
+ if (strokeColorSpace) {
+ strokeColorSpace = state->strokeColorSpace->copy();
+ }
+ if (fillPattern) {
+ fillPattern = state->fillPattern->copy();
+ }
+ if (strokePattern) {
+ strokePattern = state->strokePattern->copy();
+ }
+ if (lineDashLength > 0) {
+ lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
+ memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
+ }
+ saved = NULL;
+}
+
+void GfxState::getUserClipBBox(double *xMin, double *yMin,
+ double *xMax, double *yMax) {
+ double ictm[6];
+ double xMin1, yMin1, xMax1, yMax1, det, tx, ty;
+
+ // invert the CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+
+ // transform all four corners of the clip bbox; find the min and max
+ // x and y values
+ xMin1 = xMax1 = clipXMin * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ yMin1 = yMax1 = clipXMin * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ tx = clipXMin * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMin * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMin * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMin * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+ tx = clipXMax * ictm[0] + clipYMax * ictm[2] + ictm[4];
+ ty = clipXMax * ictm[1] + clipYMax * ictm[3] + ictm[5];
+ if (tx < xMin1) {
+ xMin1 = tx;
+ } else if (tx > xMax1) {
+ xMax1 = tx;
+ }
+ if (ty < yMin1) {
+ yMin1 = ty;
+ } else if (ty > yMax1) {
+ yMax1 = ty;
+ }
+
+ *xMin = xMin1;
+ *yMin = yMin1;
+ *xMax = xMax1;
+ *yMax = yMax1;
+}
+
+double GfxState::transformWidth(double w) {
+ double x, y;
+
+ x = ctm[0] + ctm[2];
+ y = ctm[1] + ctm[3];
+ return w * sqrt(0.5 * (x * x + y * y));
+}
+
+double GfxState::getTransformedFontSize() {
+ double x1, y1, x2, y2;
+
+ x1 = textMat[2] * fontSize;
+ y1 = textMat[3] * fontSize;
+ x2 = ctm[0] * x1 + ctm[2] * y1;
+ y2 = ctm[1] * x1 + ctm[3] * y1;
+ return sqrt(x2 * x2 + y2 * y2);
+}
+
+void GfxState::getFontTransMat(double *m11, double *m12,
+ double *m21, double *m22) {
+ *m11 = (textMat[0] * ctm[0] + textMat[1] * ctm[2]) * fontSize;
+ *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize;
+ *m21 = (textMat[2] * ctm[0] + textMat[3] * ctm[2]) * fontSize;
+ *m22 = (textMat[2] * ctm[1] + textMat[3] * ctm[3]) * fontSize;
+}
+
+void GfxState::setCTM(double a, double b, double c,
+ double d, double e, double f) {
+ int i;
+
+ ctm[0] = a;
+ ctm[1] = b;
+ ctm[2] = c;
+ ctm[3] = d;
+ ctm[4] = e;
+ ctm[5] = f;
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > 1e10) {
+ ctm[i] = 1e10;
+ } else if (ctm[i] < -1e10) {
+ ctm[i] = -1e10;
+ }
+ }
+}
+
+void GfxState::concatCTM(double a, double b, double c,
+ double d, double e, double f) {
+ double a1 = ctm[0];
+ double b1 = ctm[1];
+ double c1 = ctm[2];
+ double d1 = ctm[3];
+ int i;
+
+ ctm[0] = a * a1 + b * c1;
+ ctm[1] = a * b1 + b * d1;
+ ctm[2] = c * a1 + d * c1;
+ ctm[3] = c * b1 + d * d1;
+ ctm[4] = e * a1 + f * c1 + ctm[4];
+ ctm[5] = e * b1 + f * d1 + ctm[5];
+
+ // avoid FP exceptions on badly messed up PDF files
+ for (i = 0; i < 6; ++i) {
+ if (ctm[i] > 1e10) {
+ ctm[i] = 1e10;
+ } else if (ctm[i] < -1e10) {
+ ctm[i] = -1e10;
+ }
+ }
+}
+
+void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
+ if (fillColorSpace) {
+ delete fillColorSpace;
+ }
+ fillColorSpace = colorSpace;
+}
+
+void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
+ if (strokeColorSpace) {
+ delete strokeColorSpace;
+ }
+ strokeColorSpace = colorSpace;
+}
+
+void GfxState::setFillPattern(GfxPattern *pattern) {
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ fillPattern = pattern;
+}
+
+void GfxState::setStrokePattern(GfxPattern *pattern) {
+ if (strokePattern) {
+ delete strokePattern;
+ }
+ strokePattern = pattern;
+}
+
+void GfxState::setLineDash(double *dash, int length, double start) {
+ if (lineDash)
+ gfree(lineDash);
+ lineDash = dash;
+ lineDashLength = length;
+ lineDashStart = start;
+}
+
+void GfxState::clearPath() {
+ delete path;
+ path = new GfxPath();
+}
+
+void GfxState::clip() {
+ double xMin, yMin, xMax, yMax, x, y;
+ GfxSubpath *subpath;
+ int i, j;
+
+ xMin = xMax = yMin = yMax = 0; // make gcc happy
+ for (i = 0; i < path->getNumSubpaths(); ++i) {
+ subpath = path->getSubpath(i);
+ for (j = 0; j < subpath->getNumPoints(); ++j) {
+ transform(subpath->getX(j), subpath->getY(j), &x, &y);
+ if (i == 0 && j == 0) {
+ xMin = xMax = x;
+ yMin = yMax = y;
+ } else {
+ if (x < xMin) {
+ xMin = x;
+ } else if (x > xMax) {
+ xMax = x;
+ }
+ if (y < yMin) {
+ yMin = y;
+ } else if (y > yMax) {
+ yMax = y;
+ }
+ }
+ }
+ }
+ if (xMin > clipXMin) {
+ clipXMin = xMin;
+ }
+ if (yMin > clipYMin) {
+ clipYMin = yMin;
+ }
+ if (xMax < clipXMax) {
+ clipXMax = xMax;
+ }
+ if (yMax < clipYMax) {
+ clipYMax = yMax;
+ }
+}
+
+void GfxState::textShift(double tx, double ty) {
+ double dx, dy;
+
+ textTransformDelta(tx, ty, &dx, &dy);
+ curX += dx;
+ curY += dy;
+}
+
+void GfxState::shift(double dx, double dy) {
+ curX += dx;
+ curY += dy;
+}
+
+GfxState *GfxState::save() {
+ GfxState *newState;
+
+ newState = copy();
+ newState->saved = this;
+ return newState;
+}
+
+GfxState *GfxState::restore() {
+ GfxState *oldState;
+
+ if (saved) {
+ oldState = saved;
+
+ // these attributes aren't saved/restored by the q/Q operators
+ oldState->path = path;
+ oldState->curX = curX;
+ oldState->curY = curY;
+ oldState->lineX = lineX;
+ oldState->lineY = lineY;
+
+ path = NULL;
+ saved = NULL;
+ delete this;
+
+ } else {
+ oldState = this;
+ }
+
+ return oldState;
+}
diff --git a/pdftops/GfxState.h b/pdftops/GfxState.h
new file mode 100644
index 000000000..fa4983c20
--- /dev/null
+++ b/pdftops/GfxState.h
@@ -0,0 +1,1055 @@
+//========================================================================
+//
+// GfxState.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GFXSTATE_H
+#define GFXSTATE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "Function.h"
+
+class Array;
+class GfxFont;
+class PDFRectangle;
+class GfxShading;
+
+//------------------------------------------------------------------------
+// GfxColor
+//------------------------------------------------------------------------
+
+#define gfxColorMaxComps funcMaxOutputs
+
+struct GfxColor {
+ double c[gfxColorMaxComps];
+};
+
+//------------------------------------------------------------------------
+// GfxRGB
+//------------------------------------------------------------------------
+
+struct GfxRGB {
+ double r, g, b;
+};
+
+//------------------------------------------------------------------------
+// GfxCMYK
+//------------------------------------------------------------------------
+
+struct GfxCMYK {
+ double c, m, y, k;
+};
+
+//------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+// NB: The nGfxColorSpaceModes constant and the gfxColorSpaceModeNames
+// array defined in GfxState.cc must match this enum.
+enum GfxColorSpaceMode {
+ csDeviceGray,
+ csCalGray,
+ csDeviceRGB,
+ csCalRGB,
+ csDeviceCMYK,
+ csLab,
+ csICCBased,
+ csIndexed,
+ csSeparation,
+ csDeviceN,
+ csPattern
+};
+
+class GfxColorSpace {
+public:
+
+ GfxColorSpace();
+ virtual ~GfxColorSpace();
+ virtual GfxColorSpace *copy() = 0;
+ virtual GfxColorSpaceMode getMode() = 0;
+
+ // Construct a color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Object *csObj);
+
+ // Convert to gray, RGB, or CMYK.
+ virtual void getGray(GfxColor *color, double *gray) = 0;
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
+
+ // Return the number of color components.
+ virtual int getNComps() = 0;
+
+ // Return the default ranges for each component, assuming an image
+ // with a max pixel value of <maxImgPixel>.
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Return the number of color space modes
+ static int getNumColorSpaceModes();
+
+ // Return the name of the <idx>th color space mode.
+ static const char *getColorSpaceModeName(int idx);
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceGrayColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceGrayColorSpace();
+ virtual ~GfxDeviceGrayColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceGray; }
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxCalGrayColorSpace
+//------------------------------------------------------------------------
+
+class GfxCalGrayColorSpace: public GfxColorSpace {
+public:
+
+ GfxCalGrayColorSpace();
+ virtual ~GfxCalGrayColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csCalGray; }
+
+ // Construct a CalGray color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ // CalGray-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getGamma() { return gamma; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double gamma; // gamma value
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceRGBColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceRGBColorSpace();
+ virtual ~GfxDeviceRGBColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceRGB; }
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 3; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxCalRGBColorSpace: public GfxColorSpace {
+public:
+
+ GfxCalRGBColorSpace();
+ virtual ~GfxCalRGBColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csCalRGB; }
+
+ // Construct a CalRGB color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 3; }
+
+ // CalRGB-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getGammaR() { return gammaR; }
+ double getGammaG() { return gammaG; }
+ double getGammaB() { return gammaB; }
+ double *getMatrix() { return mat; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double gammaR, gammaG, gammaB; // gamma values
+ double mat[9]; // ABC -> XYZ transform matrix
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceCMYKColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceCMYKColorSpace();
+ virtual ~GfxDeviceCMYKColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; }
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 4; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+class GfxLabColorSpace: public GfxColorSpace {
+public:
+
+ GfxLabColorSpace();
+ virtual ~GfxLabColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csLab; }
+
+ // Construct a Lab color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 3; }
+
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Lab-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getAMin() { return aMin; }
+ double getAMax() { return aMax; }
+ double getBMin() { return bMin; }
+ double getBMax() { return bMax; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double aMin, aMax, bMin, bMax; // range for the a and b components
+ double kr, kg, kb; // gamut mapping mulitpliers
+};
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+class GfxICCBasedColorSpace: public GfxColorSpace {
+public:
+
+ GfxICCBasedColorSpace(int nCompsA, GfxColorSpace *altA,
+ Ref *iccProfileStreamA);
+ virtual ~GfxICCBasedColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csICCBased; }
+
+ // Construct an ICCBased color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return nComps; }
+
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // ICCBased-specific access.
+ GfxColorSpace *getAlt() { return alt; }
+
+private:
+
+ int nComps; // number of color components (1, 3, or 4)
+ GfxColorSpace *alt; // alternate color space
+ double rangeMin[4]; // min values for each component
+ double rangeMax[4]; // max values for each component
+ Ref iccProfileStream; // the ICC profile
+};
+
+//------------------------------------------------------------------------
+// GfxIndexedColorSpace
+//------------------------------------------------------------------------
+
+class GfxIndexedColorSpace: public GfxColorSpace {
+public:
+
+ GfxIndexedColorSpace(GfxColorSpace *baseA, int indexHighA);
+ virtual ~GfxIndexedColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csIndexed; }
+
+ // Construct a Lab color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Indexed-specific access.
+ GfxColorSpace *getBase() { return base; }
+ int getIndexHigh() { return indexHigh; }
+ Guchar *getLookup() { return lookup; }
+ GfxColor *mapColorToBase(GfxColor *color, GfxColor *baseColor);
+
+private:
+
+ GfxColorSpace *base; // base color space
+ int indexHigh; // max pixel value
+ Guchar *lookup; // lookup table
+};
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+class GfxSeparationColorSpace: public GfxColorSpace {
+public:
+
+ GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
+ Function *funcA);
+ virtual ~GfxSeparationColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csSeparation; }
+
+ // Construct a Separation color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ // Separation-specific access.
+ GString *getName() { return name; }
+ GfxColorSpace *getAlt() { return alt; }
+ Function *getFunc() { return func; }
+
+private:
+
+ GString *name; // colorant name
+ GfxColorSpace *alt; // alternate color space
+ Function *func; // tint transform (into alternate color space)
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceNColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func);
+ virtual ~GfxDeviceNColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceN; }
+
+ // Construct a DeviceN color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return nComps; }
+
+ // DeviceN-specific access.
+ GString *getColorantName(int i) { return names[i]; }
+ GfxColorSpace *getAlt() { return alt; }
+ Function *getTintTransformFunc() { return func; }
+
+private:
+
+ int nComps; // number of components
+ GString // colorant names
+ *names[gfxColorMaxComps];
+ GfxColorSpace *alt; // alternate color space
+ Function *func; // tint transform (into alternate color space)
+
+};
+
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+class GfxPatternColorSpace: public GfxColorSpace {
+public:
+
+ GfxPatternColorSpace(GfxColorSpace *underA);
+ virtual ~GfxPatternColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csPattern; }
+
+ // Construct a Pattern color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 0; }
+
+ // Pattern-specific access.
+ GfxColorSpace *getUnder() { return under; }
+
+private:
+
+ GfxColorSpace *under; // underlying color space (for uncolored
+ // patterns)
+};
+
+//------------------------------------------------------------------------
+// GfxPattern
+//------------------------------------------------------------------------
+
+class GfxPattern {
+public:
+
+ GfxPattern(int typeA);
+ virtual ~GfxPattern();
+
+ static GfxPattern *parse(Object *obj);
+
+ virtual GfxPattern *copy() = 0;
+
+ int getType() { return type; }
+
+private:
+
+ int type;
+};
+
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+class GfxTilingPattern: public GfxPattern {
+public:
+
+ static GfxTilingPattern *parse(Object *patObj);
+ virtual ~GfxTilingPattern();
+
+ virtual GfxPattern *copy();
+
+ int getPaintType() { return paintType; }
+ int getTilingType() { return tilingType; }
+ double *getBBox() { return bbox; }
+ double getXStep() { return xStep; }
+ double getYStep() { return yStep; }
+ Dict *getResDict()
+ { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
+ double *getMatrix() { return matrix; }
+ Object *getContentStream() { return &contentStream; }
+
+private:
+
+ GfxTilingPattern(int paintTypeA, int tilingTypeA,
+ double *bboxA, double xStepA, double yStepA,
+ Object *resDictA, double *matrixA,
+ Object *contentStreamA);
+
+ int paintType;
+ int tilingType;
+ double bbox[4];
+ double xStep, yStep;
+ Object resDict;
+ double matrix[6];
+ Object contentStream;
+};
+
+//------------------------------------------------------------------------
+// GfxShadingPattern
+//------------------------------------------------------------------------
+
+class GfxShadingPattern: public GfxPattern {
+public:
+
+ static GfxShadingPattern *parse(Object *patObj);
+ virtual ~GfxShadingPattern();
+
+ virtual GfxPattern *copy();
+
+ GfxShading *getShading() { return shading; }
+ double *getMatrix() { return matrix; }
+
+private:
+
+ GfxShadingPattern(GfxShading *shadingA, double *matrixA);
+
+ GfxShading *shading;
+ double matrix[6];
+};
+
+//------------------------------------------------------------------------
+// GfxShading
+//------------------------------------------------------------------------
+
+class GfxShading {
+public:
+
+ GfxShading(int typeA);
+ GfxShading(GfxShading *shading);
+ virtual ~GfxShading();
+
+ static GfxShading *parse(Object *obj);
+
+ virtual GfxShading *copy() = 0;
+
+ int getType() { return type; }
+ GfxColorSpace *getColorSpace() { return colorSpace; }
+ GfxColor *getBackground() { return &background; }
+ GBool getHasBackground() { return hasBackground; }
+ void getBBox(double *xMinA, double *yMinA, double *xMaxA, double *yMaxA)
+ { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
+ GBool getHasBBox() { return hasBBox; }
+
+protected:
+
+ GBool init(Dict *dict);
+
+ int type;
+ GfxColorSpace *colorSpace;
+ GfxColor background;
+ GBool hasBackground;
+ double xMin, yMin, xMax, yMax;
+ GBool hasBBox;
+};
+
+//------------------------------------------------------------------------
+// GfxFunctionShading
+//------------------------------------------------------------------------
+
+class GfxFunctionShading: public GfxShading {
+public:
+
+ GfxFunctionShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double *matrixA,
+ Function **funcsA, int nFuncsA);
+ GfxFunctionShading(GfxFunctionShading *shading);
+ virtual ~GfxFunctionShading();
+
+ static GfxFunctionShading *parse(Dict *dict);
+
+ virtual GfxShading *copy();
+
+ void getDomain(double *x0A, double *y0A, double *x1A, double *y1A)
+ { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
+ double *getMatrix() { return matrix; }
+ void getColor(double x, double y, GfxColor *color);
+
+private:
+
+ double x0, y0, x1, y1;
+ double matrix[6];
+ Function *funcs[gfxColorMaxComps];
+ int nFuncs;
+};
+
+//------------------------------------------------------------------------
+// GfxAxialShading
+//------------------------------------------------------------------------
+
+class GfxAxialShading: public GfxShading {
+public:
+
+ GfxAxialShading(double x0A, double y0A,
+ double x1A, double y1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A);
+ GfxAxialShading(GfxAxialShading *shading);
+ virtual ~GfxAxialShading();
+
+ static GfxAxialShading *parse(Dict *dict);
+
+ virtual GfxShading *copy();
+
+ void getCoords(double *x0A, double *y0A, double *x1A, double *y1A)
+ { *x0A = x0; *y0A = y0; *x1A = x1; *y1A = y1; }
+ double getDomain0() { return t0; }
+ double getDomain1() { return t1; }
+ void getColor(double t, GfxColor *color);
+ GBool getExtend0() { return extend0; }
+ GBool getExtend1() { return extend1; }
+
+private:
+
+ double x0, y0, x1, y1;
+ double t0, t1;
+ Function *funcs[gfxColorMaxComps];
+ int nFuncs;
+ GBool extend0, extend1;
+};
+
+//------------------------------------------------------------------------
+// GfxRadialShading
+//------------------------------------------------------------------------
+
+class GfxRadialShading: public GfxShading {
+public:
+
+ GfxRadialShading(double x0A, double y0A, double r0A,
+ double x1A, double y1A, double r1A,
+ double t0A, double t1A,
+ Function **funcsA, int nFuncsA,
+ GBool extend0A, GBool extend1A);
+ GfxRadialShading(GfxRadialShading *shading);
+ virtual ~GfxRadialShading();
+
+ static GfxRadialShading *parse(Dict *dict);
+
+ virtual GfxShading *copy();
+
+ void getCoords(double *x0A, double *y0A, double *r0A,
+ double *x1A, double *y1A, double *r1A)
+ { *x0A = x0; *y0A = y0; *r0A = r0; *x1A = x1; *y1A = y1; *r1A = r1; }
+ double getDomain0() { return t0; }
+ double getDomain1() { return t1; }
+ void getColor(double t, GfxColor *color);
+ GBool getExtend0() { return extend0; }
+ GBool getExtend1() { return extend1; }
+
+private:
+
+ double x0, y0, r0, x1, y1, r1;
+ double t0, t1;
+ Function *funcs[gfxColorMaxComps];
+ int nFuncs;
+ GBool extend0, extend1;
+};
+
+//------------------------------------------------------------------------
+// GfxImageColorMap
+//------------------------------------------------------------------------
+
+class GfxImageColorMap {
+public:
+
+ // Constructor.
+ GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA);
+
+ // Destructor.
+ ~GfxImageColorMap();
+
+ // Return a copy of this color map.
+ GfxImageColorMap *copy() { return new GfxImageColorMap(this); }
+
+ // Is color map valid?
+ GBool isOk() { return ok; }
+
+ // Get the color space.
+ GfxColorSpace *getColorSpace() { return colorSpace; }
+
+ // Get stream decoding info.
+ int getNumPixelComps() { return nComps; }
+ int getBits() { return bits; }
+
+ // Get decode table.
+ double getDecodeLow(int i) { return decodeLow[i]; }
+ double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
+
+ // Convert an image pixel to a color.
+ void getGray(Guchar *x, double *gray);
+ void getRGB(Guchar *x, GfxRGB *rgb);
+ void getCMYK(Guchar *x, GfxCMYK *cmyk);
+ void getColor(Guchar *x, GfxColor *color);
+
+private:
+
+ GfxImageColorMap(GfxImageColorMap *colorMap);
+
+ GfxColorSpace *colorSpace; // the image color space
+ int bits; // bits per component
+ int nComps; // number of components in a pixel
+ GfxColorSpace *colorSpace2; // secondary color space
+ int nComps2; // number of components in colorSpace2
+ double *lookup; // lookup table
+ double // minimum values for each component
+ decodeLow[gfxColorMaxComps];
+ double // max - min value for each component
+ decodeRange[gfxColorMaxComps];
+ GBool ok;
+};
+
+//------------------------------------------------------------------------
+// GfxSubpath and GfxPath
+//------------------------------------------------------------------------
+
+class GfxSubpath {
+public:
+
+ // Constructor.
+ GfxSubpath(double x1, double y1);
+
+ // Destructor.
+ ~GfxSubpath();
+
+ // Copy.
+ GfxSubpath *copy() { return new GfxSubpath(this); }
+
+ // Get points.
+ int getNumPoints() { return n; }
+ double getX(int i) { return x[i]; }
+ double getY(int i) { return y[i]; }
+ GBool getCurve(int i) { return curve[i]; }
+
+ // Get last point.
+ double getLastX() { return x[n-1]; }
+ double getLastY() { return y[n-1]; }
+
+ // Add a line segment.
+ void lineTo(double x1, double y1);
+
+ // Add a Bezier curve.
+ void curveTo(double x1, double y1, double x2, double y2,
+ double x3, double y3);
+
+ // Close the subpath.
+ void close();
+ GBool isClosed() { return closed; }
+
+ // Add (<dx>, <dy>) to each point in the subpath.
+ void offset(double dx, double dy);
+
+private:
+
+ double *x, *y; // points
+ GBool *curve; // curve[i] => point i is a control point
+ // for a Bezier curve
+ int n; // number of points
+ int size; // size of x/y arrays
+ GBool closed; // set if path is closed
+
+ GfxSubpath(GfxSubpath *subpath);
+};
+
+class GfxPath {
+public:
+
+ // Constructor.
+ GfxPath();
+
+ // Destructor.
+ ~GfxPath();
+
+ // Copy.
+ GfxPath *copy()
+ { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); }
+
+ // Is there a current point?
+ GBool isCurPt() { return n > 0 || justMoved; }
+
+ // Is the path non-empty, i.e., is there at least one segment?
+ GBool isPath() { return n > 0; }
+
+ // Get subpaths.
+ int getNumSubpaths() { return n; }
+ GfxSubpath *getSubpath(int i) { return subpaths[i]; }
+
+ // Get last point on last subpath.
+ double getLastX() { return subpaths[n-1]->getLastX(); }
+ double getLastY() { return subpaths[n-1]->getLastY(); }
+
+ // Move the current point.
+ void moveTo(double x, double y);
+
+ // Add a segment to the last subpath.
+ void lineTo(double x, double y);
+
+ // Add a Bezier curve to the last subpath
+ void curveTo(double x1, double y1, double x2, double y2,
+ double x3, double y3);
+
+ // Close the last subpath.
+ void close();
+
+ // Append <path> to <this>.
+ void append(GfxPath *path);
+
+ // Add (<dx>, <dy>) to each point in the path.
+ void offset(double dx, double dy);
+
+private:
+
+ GBool justMoved; // set if a new subpath was just started
+ double firstX, firstY; // first point in new subpath
+ GfxSubpath **subpaths; // subpaths
+ int n; // number of subpaths
+ int size; // size of subpaths array
+
+ GfxPath(GBool justMoved1, double firstX1, double firstY1,
+ GfxSubpath **subpaths1, int n1, int size1);
+};
+
+//------------------------------------------------------------------------
+// GfxState
+//------------------------------------------------------------------------
+
+class GfxState {
+public:
+
+ // Construct a default GfxState, for a device with resolution <hDPI>
+ // x <vDPI>, page box <pageBox>, page rotation <rotate>, and
+ // coordinate system specified by <upsideDown>.
+ GfxState(double hDPI, double vDPI, PDFRectangle *pageBox,
+ int rotate, GBool upsideDown);
+
+ // Destructor.
+ ~GfxState();
+
+ // Copy.
+ GfxState *copy() { return new GfxState(this); }
+
+ // Accessors.
+ double *getCTM() { return ctm; }
+ double getX1() { return px1; }
+ double getY1() { return py1; }
+ double getX2() { return px2; }
+ double getY2() { return py2; }
+ double getPageWidth() { return pageWidth; }
+ double getPageHeight() { return pageHeight; }
+ GfxColor *getFillColor() { return &fillColor; }
+ GfxColor *getStrokeColor() { return &strokeColor; }
+ void getFillGray(double *gray)
+ { fillColorSpace->getGray(&fillColor, gray); }
+ void getStrokeGray(double *gray)
+ { strokeColorSpace->getGray(&strokeColor, gray); }
+ void getFillRGB(GfxRGB *rgb)
+ { fillColorSpace->getRGB(&fillColor, rgb); }
+ void getStrokeRGB(GfxRGB *rgb)
+ { strokeColorSpace->getRGB(&strokeColor, rgb); }
+ void getFillCMYK(GfxCMYK *cmyk)
+ { fillColorSpace->getCMYK(&fillColor, cmyk); }
+ void getStrokeCMYK(GfxCMYK *cmyk)
+ { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
+ GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
+ GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
+ GfxPattern *getFillPattern() { return fillPattern; }
+ GfxPattern *getStrokePattern() { return strokePattern; }
+ double getFillOpacity() { return fillOpacity; }
+ double getStrokeOpacity() { return strokeOpacity; }
+ double getLineWidth() { return lineWidth; }
+ void getLineDash(double **dash, int *length, double *start)
+ { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
+ int getFlatness() { return flatness; }
+ int getLineJoin() { return lineJoin; }
+ int getLineCap() { return lineCap; }
+ double getMiterLimit() { return miterLimit; }
+ GfxFont *getFont() { return font; }
+ double getFontSize() { return fontSize; }
+ double *getTextMat() { return textMat; }
+ double getCharSpace() { return charSpace; }
+ double getWordSpace() { return wordSpace; }
+ double getHorizScaling() { return horizScaling; }
+ double getLeading() { return leading; }
+ double getRise() { return rise; }
+ int getRender() { return render; }
+ GfxPath *getPath() { return path; }
+ double getCurX() { return curX; }
+ double getCurY() { return curY; }
+ void getClipBBox(double *xMin, double *yMin, double *xMax, double *yMax)
+ { *xMin = clipXMin; *yMin = clipYMin; *xMax = clipXMax; *yMax = clipYMax; }
+ void getUserClipBBox(double *xMin, double *yMin, double *xMax, double *yMax);
+ double getLineX() { return lineX; }
+ double getLineY() { return lineY; }
+
+ // Is there a current point/path?
+ GBool isCurPt() { return path->isCurPt(); }
+ GBool isPath() { return path->isPath(); }
+
+ // Transforms.
+ void transform(double x1, double y1, double *x2, double *y2)
+ { *x2 = ctm[0] * x1 + ctm[2] * y1 + ctm[4];
+ *y2 = ctm[1] * x1 + ctm[3] * y1 + ctm[5]; }
+ void transformDelta(double x1, double y1, double *x2, double *y2)
+ { *x2 = ctm[0] * x1 + ctm[2] * y1;
+ *y2 = ctm[1] * x1 + ctm[3] * y1; }
+ void textTransform(double x1, double y1, double *x2, double *y2)
+ { *x2 = textMat[0] * x1 + textMat[2] * y1 + textMat[4];
+ *y2 = textMat[1] * x1 + textMat[3] * y1 + textMat[5]; }
+ void textTransformDelta(double x1, double y1, double *x2, double *y2)
+ { *x2 = textMat[0] * x1 + textMat[2] * y1;
+ *y2 = textMat[1] * x1 + textMat[3] * y1; }
+ double transformWidth(double w);
+ double getTransformedLineWidth()
+ { return transformWidth(lineWidth); }
+ double getTransformedFontSize();
+ void getFontTransMat(double *m11, double *m12, double *m21, double *m22);
+
+ // Change state parameters.
+ void setCTM(double a, double b, double c,
+ double d, double e, double f);
+ void concatCTM(double a, double b, double c,
+ double d, double e, double f);
+ void setFillColorSpace(GfxColorSpace *colorSpace);
+ void setStrokeColorSpace(GfxColorSpace *colorSpace);
+ void setFillColor(GfxColor *color) { fillColor = *color; }
+ void setStrokeColor(GfxColor *color) { strokeColor = *color; }
+ void setFillPattern(GfxPattern *pattern);
+ void setStrokePattern(GfxPattern *pattern);
+ void setFillOpacity(double opac) { fillOpacity = opac; }
+ void setStrokeOpacity(double opac) { strokeOpacity = opac; }
+ void setLineWidth(double width) { lineWidth = width; }
+ void setLineDash(double *dash, int length, double start);
+ void setFlatness(int flatness1) { flatness = flatness1; }
+ void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
+ void setLineCap(int lineCap1) { lineCap = lineCap1; }
+ void setMiterLimit(double limit) { miterLimit = limit; }
+ void setFont(GfxFont *fontA, double fontSizeA)
+ { font = fontA; fontSize = fontSizeA; }
+ void setTextMat(double a, double b, double c,
+ double d, double e, double f)
+ { textMat[0] = a; textMat[1] = b; textMat[2] = c;
+ textMat[3] = d; textMat[4] = e; textMat[5] = f; }
+ void setCharSpace(double space)
+ { charSpace = space; }
+ void setWordSpace(double space)
+ { wordSpace = space; }
+ void setHorizScaling(double scale)
+ { horizScaling = 0.01 * scale; }
+ void setLeading(double leadingA)
+ { leading = leadingA; }
+ void setRise(double riseA)
+ { rise = riseA; }
+ void setRender(int renderA)
+ { render = renderA; }
+
+ // Add to path.
+ void moveTo(double x, double y)
+ { path->moveTo(curX = x, curY = y); }
+ void lineTo(double x, double y)
+ { path->lineTo(curX = x, curY = y); }
+ void curveTo(double x1, double y1, double x2, double y2,
+ double x3, double y3)
+ { path->curveTo(x1, y1, x2, y2, curX = x3, curY = y3); }
+ void closePath()
+ { path->close(); curX = path->getLastX(); curY = path->getLastY(); }
+ void clearPath();
+
+ // Update clip region.
+ void clip();
+
+ // Text position.
+ void textSetPos(double tx, double ty) { lineX = tx; lineY = ty; }
+ void textMoveTo(double tx, double ty)
+ { lineX = tx; lineY = ty; textTransform(tx, ty, &curX, &curY); }
+ void textShift(double tx, double ty);
+ void shift(double dx, double dy);
+
+ // Push/pop GfxState on/off stack.
+ GfxState *save();
+ GfxState *restore();
+ GBool hasSaves() { return saved != NULL; }
+
+private:
+
+ double ctm[6]; // coord transform matrix
+ double px1, py1, px2, py2; // page corners (user coords)
+ double pageWidth, pageHeight; // page size (pixels)
+
+ GfxColorSpace *fillColorSpace; // fill color space
+ GfxColorSpace *strokeColorSpace; // stroke color space
+ GfxColor fillColor; // fill color
+ GfxColor strokeColor; // stroke color
+ GfxPattern *fillPattern; // fill pattern
+ GfxPattern *strokePattern; // stroke pattern
+ double fillOpacity; // fill opacity
+ double strokeOpacity; // stroke opacity
+
+ double lineWidth; // line width
+ double *lineDash; // line dash
+ int lineDashLength;
+ double lineDashStart;
+ int flatness; // curve flatness
+ int lineJoin; // line join style
+ int lineCap; // line cap style
+ double miterLimit; // line miter limit
+
+ GfxFont *font; // font
+ double fontSize; // font size
+ double textMat[6]; // text matrix
+ double charSpace; // character spacing
+ double wordSpace; // word spacing
+ double horizScaling; // horizontal scaling
+ double leading; // text leading
+ double rise; // text rise
+ int render; // text rendering mode
+
+ GfxPath *path; // array of path elements
+ double curX, curY; // current point (user coords)
+ double lineX, lineY; // start of current text line (text coords)
+
+ double clipXMin, clipYMin, // bounding box for clip region
+ clipXMax, clipYMax;
+
+ GfxState *saved; // next GfxState on stack
+
+ GfxState(GfxState *state);
+};
+
+#endif
diff --git a/pdftops/GlobalParams.cxx b/pdftops/GlobalParams.cxx
new file mode 100644
index 000000000..ca923ec33
--- /dev/null
+++ b/pdftops/GlobalParams.cxx
@@ -0,0 +1,1556 @@
+//========================================================================
+//
+// GlobalParams.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#if HAVE_PAPER_H
+#include <paper.h>
+#endif
+#include "gmem.h"
+#include "GString.h"
+#include "GList.h"
+#include "GHash.h"
+#include "gfile.h"
+#include "Error.h"
+#include "NameToCharCode.h"
+#include "CharCodeToUnicode.h"
+#include "UnicodeMap.h"
+#include "CMap.h"
+#include "BuiltinFontTables.h"
+#include "FontEncodingTables.h"
+#include "GlobalParams.h"
+
+#if MULTITHREADED
+# define lockGlobalParams gLockMutex(&mutex)
+# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
+# define lockCMapCache gLockMutex(&cMapCacheMutex)
+# define unlockGlobalParams gUnlockMutex(&mutex)
+# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
+# define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
+#else
+# define lockGlobalParams
+# define lockUnicodeMapCache
+# define lockCMapCache
+# define unlockGlobalParams
+# define unlockUnicodeMapCache
+# define unlockCMapCache
+#endif
+
+#include "NameToUnicodeTable.h"
+#include "UnicodeMapTables.h"
+#include "DisplayFontTable.h"
+#include "UTF8.h"
+
+//------------------------------------------------------------------------
+
+#define cidToUnicodeCacheSize 4
+#define unicodeToUnicodeCacheSize 4
+
+//------------------------------------------------------------------------
+
+GlobalParams *globalParams = NULL;
+
+//------------------------------------------------------------------------
+// DisplayFontParam
+//------------------------------------------------------------------------
+
+DisplayFontParam::DisplayFontParam(GString *nameA,
+ DisplayFontParamKind kindA) {
+ name = nameA;
+ kind = kindA;
+ switch (kind) {
+ case displayFontX:
+ x.xlfd = NULL;
+ x.encoding = NULL;
+ break;
+ case displayFontT1:
+ t1.fileName = NULL;
+ break;
+ case displayFontTT:
+ tt.fileName = NULL;
+ break;
+ }
+}
+
+DisplayFontParam::DisplayFontParam(const char *nameA, const char *xlfdA, const char *encodingA) {
+ name = new GString(nameA);
+ kind = displayFontX;
+ x.xlfd = new GString(xlfdA);
+ x.encoding = new GString(encodingA);
+}
+
+DisplayFontParam::~DisplayFontParam() {
+ delete name;
+ switch (kind) {
+ case displayFontX:
+ if (x.xlfd) {
+ delete x.xlfd;
+ }
+ if (x.encoding) {
+ delete x.encoding;
+ }
+ break;
+ case displayFontT1:
+ if (t1.fileName) {
+ delete t1.fileName;
+ }
+ break;
+ case displayFontTT:
+ if (tt.fileName) {
+ delete tt.fileName;
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------
+// PSFontParam
+//------------------------------------------------------------------------
+
+PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
+ GString *psFontNameA, GString *encodingA) {
+ pdfFontName = pdfFontNameA;
+ wMode = wModeA;
+ psFontName = psFontNameA;
+ encoding = encodingA;
+}
+
+PSFontParam::~PSFontParam() {
+ delete pdfFontName;
+ delete psFontName;
+ if (encoding) {
+ delete encoding;
+ }
+}
+
+//------------------------------------------------------------------------
+// parsing
+//------------------------------------------------------------------------
+
+GlobalParams::GlobalParams(const char *cfgFileName) {
+ UnicodeMap *map;
+ DisplayFontParam *dfp;
+ GString *fileName;
+ FILE *f;
+ int i;
+
+#if MULTITHREADED
+ gInitMutex(&mutex);
+ gInitMutex(&unicodeMapCacheMutex);
+ gInitMutex(&cMapCacheMutex);
+#endif
+
+ initBuiltinFontTables();
+
+ // scan the encoding in reverse because we want the lowest-numbered
+ // index for each char name ('space' is encoded twice)
+ macRomanReverseMap = new NameToCharCode();
+ for (i = 255; i >= 0; --i) {
+ if (macRomanEncoding[i]) {
+ macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
+ }
+ }
+
+ nameToUnicode = new NameToCharCode();
+ cidToUnicodes = new GHash(gTrue);
+ unicodeToUnicodes = new GHash(gTrue);
+ residentUnicodeMaps = new GHash();
+ unicodeMaps = new GHash(gTrue);
+ cMapDirs = new GHash(gTrue);
+ toUnicodeDirs = new GList();
+ displayFonts = new GHash();
+ displayCIDFonts = new GHash();
+ displayNamedCIDFonts = new GHash();
+#if HAVE_PAPER_H
+ const char *paperName;
+ const struct paper *paperType;
+ paperinit();
+ if ((paperName = systempapername())) {
+ paperType = paperinfo(paperName);
+ psPaperWidth = (int)paperpswidth(paperType);
+ psPaperHeight = (int)paperpsheight(paperType);
+ } else {
+ error(-1, "No paper information available - using defaults");
+ psPaperWidth = defPaperWidth;
+ psPaperHeight = defPaperHeight;
+ }
+ paperdone();
+#else
+ psPaperWidth = defPaperWidth;
+ psPaperHeight = defPaperHeight;
+#endif
+ psLeft = 0;
+ psBottom = 0;
+ psRight = psPaperWidth;
+ psTop = psPaperHeight;
+ psDuplex = gFalse;
+ psLevel = psLevel2;
+ psFile = NULL;
+ psFonts = new GHash();
+ psNamedFonts16 = new GList();
+ psFonts16 = new GList();
+ psEmbedType1 = gTrue;
+ psEmbedTrueType = gTrue;
+ psEmbedCIDPostScript = gTrue;
+ psEmbedCIDTrueType = gTrue;
+ psOPI = gFalse;
+ psASCIIHex = gFalse;
+ textEncoding = new GString("Latin1");
+#if defined(WIN32)
+ textEOL = eolDOS;
+#elif defined(MACOS)
+ textEOL = eolMac;
+#else
+ textEOL = eolUnix;
+#endif
+ textPageBreaks = gTrue;
+ textKeepTinyChars = gFalse;
+ fontDirs = new GList();
+ initialZoom = new GString("125");
+ t1libControl = fontRastAALow;
+ freetypeControl = fontRastAALow;
+ urlCommand = NULL;
+ movieCommand = NULL;
+ mapNumericCharNames = gTrue;
+ printCommands = gFalse;
+ errQuiet = gFalse;
+
+ cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
+ unicodeToUnicodeCache =
+ new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
+ unicodeMapCache = new UnicodeMapCache();
+ cMapCache = new CMapCache();
+
+ // set up the initial nameToUnicode table
+ for (i = 0; nameToUnicodeTab[i].name; ++i) {
+ nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
+ }
+
+ // set up the residentUnicodeMaps table
+ map = new UnicodeMap("Latin1", gFalse,
+ latin1UnicodeMapRanges, latin1UnicodeMapLen);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("ASCII7", gFalse,
+ ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("Symbol", gFalse,
+ symbolUnicodeMapRanges, symbolUnicodeMapLen);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
+ zapfDingbatsUnicodeMapLen);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+ map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
+ residentUnicodeMaps->add(map->getEncodingName(), map);
+
+ // default displayFonts table
+ for (i = 0; displayFontTab[i].name; ++i) {
+ dfp = new DisplayFontParam(displayFontTab[i].name,
+ displayFontTab[i].xlfd,
+ displayFontTab[i].encoding);
+ displayFonts->add(dfp->name, dfp);
+ }
+
+ // look for a user config file, then a system-wide config file
+ f = NULL;
+ fileName = NULL;
+ if (cfgFileName && cfgFileName[0]) {
+ fileName = new GString(cfgFileName);
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ delete fileName;
+ }
+ }
+ if (!f) {
+ fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ delete fileName;
+ }
+ }
+ if (!f) {
+#if defined(WIN32) && !defined(__CYGWIN32__)
+ char buf[512];
+ i = GetModuleFileName(NULL, buf, sizeof(buf));
+ if (i <= 0 || i >= sizeof(buf)) {
+ // error or path too long for buffer - just use the current dir
+ buf[0] = '\0';
+ }
+ fileName = grabPath(buf);
+ appendToPath(fileName, xpdfSysConfigFile);
+#else
+ fileName = new GString(xpdfSysConfigFile);
+#endif
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ delete fileName;
+ }
+ }
+ if (f) {
+ parseFile(fileName, f);
+ delete fileName;
+ fclose(f);
+ }
+}
+
+void GlobalParams::parseFile(GString *fileName, FILE *f) {
+ int line;
+ GList *tokens;
+ GString *cmd, *incFile;
+ char *p1, *p2;
+ char buf[512];
+ FILE *f2;
+
+ line = 1;
+ while (getLine(buf, sizeof(buf) - 1, f)) {
+
+ // break the line into tokens
+ tokens = new GList();
+ p1 = buf;
+ while (*p1) {
+ for (; *p1 && isspace(*p1); ++p1) ;
+ if (!*p1) {
+ break;
+ }
+ if (*p1 == '"' || *p1 == '\'') {
+ for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
+ ++p1;
+ } else {
+ for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
+ }
+ tokens->append(new GString(p1, p2 - p1));
+ p1 = *p2 ? p2 + 1 : p2;
+ }
+
+ if (tokens->getLength() > 0 &&
+ ((GString *)tokens->get(0))->getChar(0) != '#') {
+ cmd = (GString *)tokens->get(0);
+ if (!cmd->cmp("include")) {
+ if (tokens->getLength() == 2) {
+ incFile = (GString *)tokens->get(1);
+ if ((f2 = fopen(incFile->getCString(), "r"))) {
+ parseFile(incFile, f2);
+ fclose(f2);
+ } else {
+ error(-1, "Couldn't find included config file: '%s' (%s:%d)",
+ incFile->getCString(), fileName->getCString(), line);
+ }
+ } else {
+ error(-1, "Bad 'include' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+ } else if (!cmd->cmp("nameToUnicode")) {
+ parseNameToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("cidToUnicode")) {
+ parseCIDToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeToUnicode")) {
+ parseUnicodeToUnicode(tokens, fileName, line);
+ } else if (!cmd->cmp("unicodeMap")) {
+ parseUnicodeMap(tokens, fileName, line);
+ } else if (!cmd->cmp("cMapDir")) {
+ parseCMapDir(tokens, fileName, line);
+ } else if (!cmd->cmp("toUnicodeDir")) {
+ parseToUnicodeDir(tokens, fileName, line);
+ } else if (!cmd->cmp("displayFontX")) {
+ parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
+ } else if (!cmd->cmp("displayFontT1")) {
+ parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayFontTT")) {
+ parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontX")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontX, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontX")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontX, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontT1")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontT1")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontT1, fileName, line);
+ } else if (!cmd->cmp("displayNamedCIDFontTT")) {
+ parseDisplayFont(tokens, displayNamedCIDFonts,
+ displayFontTT, fileName, line);
+ } else if (!cmd->cmp("displayCIDFontTT")) {
+ parseDisplayFont(tokens, displayCIDFonts,
+ displayFontTT, fileName, line);
+ } else if (!cmd->cmp("psFile")) {
+ parsePSFile(tokens, fileName, line);
+ } else if (!cmd->cmp("psFont")) {
+ parsePSFont(tokens, fileName, line);
+ } else if (!cmd->cmp("psNamedFont16")) {
+ parsePSFont16("psNamedFont16", psNamedFonts16,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psFont16")) {
+ parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
+ } else if (!cmd->cmp("psPaperSize")) {
+ parsePSPaperSize(tokens, fileName, line);
+ } else if (!cmd->cmp("psDuplex")) {
+ parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
+ } else if (!cmd->cmp("psLevel")) {
+ parsePSLevel(tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedType1Fonts")) {
+ parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
+ parseYesNo("psEmbedTrueType", &psEmbedTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
+ parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
+ parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("psOPI")) {
+ parseYesNo("psOPI", &psOPI, tokens, fileName, line);
+ } else if (!cmd->cmp("psASCIIHex")) {
+ parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
+ } else if (!cmd->cmp("textEncoding")) {
+ parseTextEncoding(tokens, fileName, line);
+ } else if (!cmd->cmp("textEOL")) {
+ parseTextEOL(tokens, fileName, line);
+ } else if (!cmd->cmp("textPageBreaks")) {
+ parseYesNo("textPageBreaks", &textPageBreaks,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("textKeepTinyChars")) {
+ parseYesNo("textKeepTinyChars", &textKeepTinyChars,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("fontDir")) {
+ parseFontDir(tokens, fileName, line);
+ } else if (!cmd->cmp("initialZoom")) {
+ parseInitialZoom(tokens, fileName, line);
+ } else if (!cmd->cmp("t1libControl")) {
+ parseFontRastControl("t1libControl", &t1libControl,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("freetypeControl")) {
+ parseFontRastControl("freetypeControl", &freetypeControl,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("urlCommand")) {
+ parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
+ } else if (!cmd->cmp("movieCommand")) {
+ parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
+ } else if (!cmd->cmp("mapNumericCharNames")) {
+ parseYesNo("mapNumericCharNames", &mapNumericCharNames,
+ tokens, fileName, line);
+ } else if (!cmd->cmp("printCommands")) {
+ parseYesNo("printCommands", &printCommands, tokens, fileName, line);
+ } else if (!cmd->cmp("errQuiet")) {
+ parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
+ } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
+ error(-1, "Unknown config file command");
+ error(-1, "-- the config file format has changed since Xpdf 0.9x");
+ } else {
+ error(-1, "Unknown config file command '%s' (%s:%d)",
+ cmd->getCString(), fileName->getCString(), line);
+ }
+ }
+
+ deleteGList(tokens, GString);
+ ++line;
+ }
+}
+
+void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
+ int line) {
+ GString *name;
+ char *tok1, *tok2;
+ FILE *f;
+ char buf[256];
+ int line2;
+ Unicode u;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ name = (GString *)tokens->get(1);
+ if (!(f = fopen(name->getCString(), "r"))) {
+ error(-1, "Couldn't open 'nameToUnicode' file '%s'",
+ name->getCString());
+ return;
+ }
+ line2 = 1;
+ while (getLine(buf, sizeof(buf), f)) {
+ tok1 = strtok(buf, " \t\r\n");
+ tok2 = strtok(NULL, " \t\r\n");
+ if (tok1 && tok2) {
+ sscanf(tok1, "%x", &u);
+ nameToUnicode->add(tok2, u);
+ } else {
+ error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
+ }
+ ++line2;
+ }
+ fclose(f);
+}
+
+void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
+ int line) {
+ GString *collection, *name, *old;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ collection = (GString *)tokens->get(1);
+ name = (GString *)tokens->get(2);
+ if ((old = (GString *)cidToUnicodes->remove(collection))) {
+ delete old;
+ }
+ cidToUnicodes->add(collection->copy(), name->copy());
+}
+
+void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
+ int line) {
+ GString *font, *file, *old;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ font = (GString *)tokens->get(1);
+ file = (GString *)tokens->get(2);
+ if ((old = (GString *)unicodeToUnicodes->remove(font))) {
+ delete old;
+ }
+ unicodeToUnicodes->add(font->copy(), file->copy());
+}
+
+void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
+ int line) {
+ GString *encodingName, *name, *old;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ encodingName = (GString *)tokens->get(1);
+ name = (GString *)tokens->get(2);
+ if ((old = (GString *)unicodeMaps->remove(encodingName))) {
+ delete old;
+ }
+ unicodeMaps->add(encodingName->copy(), name->copy());
+}
+
+void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
+ GString *collection, *dir;
+ GList *list;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'cMapDir' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ collection = (GString *)tokens->get(1);
+ dir = (GString *)tokens->get(2);
+ if (!(list = (GList *)cMapDirs->lookup(collection))) {
+ list = new GList();
+ cMapDirs->add(collection->copy(), list);
+ }
+ list->append(dir->copy());
+}
+
+void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
+}
+
+void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
+ DisplayFontParamKind kind,
+ GString *fileName, int line) {
+ DisplayFontParam *param, *old;
+
+ if (tokens->getLength() < 2) {
+ goto err1;
+ }
+ param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
+
+ switch (kind) {
+ case displayFontX:
+ if (tokens->getLength() != 4) {
+ goto err2;
+ }
+ param->x.xlfd = ((GString *)tokens->get(2))->copy();
+ param->x.encoding = ((GString *)tokens->get(3))->copy();
+ break;
+ case displayFontT1:
+ if (tokens->getLength() != 3) {
+ goto err2;
+ }
+ param->t1.fileName = ((GString *)tokens->get(2))->copy();
+ break;
+ case displayFontTT:
+ if (tokens->getLength() != 3) {
+ goto err2;
+ }
+ param->tt.fileName = ((GString *)tokens->get(2))->copy();
+ break;
+ }
+
+ if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
+ delete old;
+ }
+ fontHash->add(param->name, param);
+ return;
+
+ err2:
+ delete param;
+ err1:
+ error(-1, "Bad 'display*Font*' config file command (%s:%d)",
+ fileName->getCString(), line);
+}
+
+void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
+ int line) {
+ GString *tok;
+
+ if (tokens->getLength() == 2) {
+ tok = (GString *)tokens->get(1);
+ if (!setPSPaperSize(tok->getCString())) {
+ error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+ } else if (tokens->getLength() == 3) {
+ tok = (GString *)tokens->get(1);
+ psPaperWidth = atoi(tok->getCString());
+ tok = (GString *)tokens->get(2);
+ psPaperHeight = atoi(tok->getCString());
+ } else {
+ error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+}
+
+void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
+ GString *tok;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'psLevel' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (!tok->cmp("level1")) {
+ psLevel = psLevel1;
+ } else if (!tok->cmp("level1sep")) {
+ psLevel = psLevel1Sep;
+ } else if (!tok->cmp("level2")) {
+ psLevel = psLevel2;
+ } else if (!tok->cmp("level2sep")) {
+ psLevel = psLevel2Sep;
+ } else if (!tok->cmp("level3")) {
+ psLevel = psLevel3;
+ } else if (!tok->cmp("level3Sep")) {
+ psLevel = psLevel3Sep;
+ } else {
+ error(-1, "Bad 'psLevel' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+}
+
+void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'psFile' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ if (psFile) {
+ delete psFile;
+ }
+ psFile = ((GString *)tokens->get(1))->copy();
+}
+
+void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
+ PSFontParam *param;
+
+ if (tokens->getLength() != 3) {
+ error(-1, "Bad 'psFont' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
+ ((GString *)tokens->get(2))->copy(), NULL);
+ psFonts->add(param->pdfFontName, param);
+}
+
+void GlobalParams::parsePSFont16(const char *cmdName, GList *fontList,
+ GList *tokens, GString *fileName, int line) {
+ PSFontParam *param;
+ int wMode;
+ GString *tok;
+
+ if (tokens->getLength() != 5) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(2);
+ if (!tok->cmp("H")) {
+ wMode = 0;
+ } else if (!tok->cmp("V")) {
+ wMode = 1;
+ } else {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ param = new PSFontParam(((GString *)tokens->get(1))->copy(),
+ wMode,
+ ((GString *)tokens->get(3))->copy(),
+ ((GString *)tokens->get(4))->copy());
+ fontList->append(param);
+}
+
+void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
+ int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'textEncoding' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ delete textEncoding;
+ textEncoding = ((GString *)tokens->get(1))->copy();
+}
+
+void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
+ GString *tok;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'textEOL' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (!tok->cmp("unix")) {
+ textEOL = eolUnix;
+ } else if (!tok->cmp("dos")) {
+ textEOL = eolDOS;
+ } else if (!tok->cmp("mac")) {
+ textEOL = eolMac;
+ } else {
+ error(-1, "Bad 'textEOL' config file command (%s:%d)",
+ fileName->getCString(), line);
+ }
+}
+
+void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'fontDir' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ fontDirs->append(((GString *)tokens->get(1))->copy());
+}
+
+void GlobalParams::parseInitialZoom(GList *tokens,
+ GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad 'initialZoom' config file command (%s:%d)",
+ fileName->getCString(), line);
+ return;
+ }
+ delete initialZoom;
+ initialZoom = ((GString *)tokens->get(1))->copy();
+}
+
+void GlobalParams::parseFontRastControl(const char *cmdName, FontRastControl *val,
+ GList *tokens, GString *fileName,
+ int line) {
+ GString *tok;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (!setFontRastControl(val, tok->getCString())) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ }
+}
+
+void GlobalParams::parseCommand(const char *cmdName, GString **val,
+ GList *tokens, GString *fileName, int line) {
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ if (*val) {
+ delete *val;
+ }
+ *val = ((GString *)tokens->get(1))->copy();
+}
+
+void GlobalParams::parseYesNo(const char *cmdName, GBool *flag,
+ GList *tokens, GString *fileName, int line) {
+ GString *tok;
+
+ if (tokens->getLength() != 2) {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ return;
+ }
+ tok = (GString *)tokens->get(1);
+ if (!tok->cmp("yes")) {
+ *flag = gTrue;
+ } else if (!tok->cmp("no")) {
+ *flag = gFalse;
+ } else {
+ error(-1, "Bad '%s' config file command (%s:%d)",
+ cmdName, fileName->getCString(), line);
+ }
+}
+
+GlobalParams::~GlobalParams() {
+ GHashIter *iter;
+ GString *key;
+ GList *list;
+
+ freeBuiltinFontTables();
+
+ delete macRomanReverseMap;
+
+ delete nameToUnicode;
+ deleteGHash(cidToUnicodes, GString);
+ deleteGHash(unicodeToUnicodes, GString);
+ deleteGHash(residentUnicodeMaps, UnicodeMap);
+ deleteGHash(unicodeMaps, GString);
+ deleteGList(toUnicodeDirs, GString);
+ deleteGHash(displayFonts, DisplayFontParam);
+ deleteGHash(displayCIDFonts, DisplayFontParam);
+ deleteGHash(displayNamedCIDFonts, DisplayFontParam);
+ if (psFile) {
+ delete psFile;
+ }
+ deleteGHash(psFonts, PSFontParam);
+ deleteGList(psNamedFonts16, PSFontParam);
+ deleteGList(psFonts16, PSFontParam);
+ delete textEncoding;
+ deleteGList(fontDirs, GString);
+ delete initialZoom;
+ if (urlCommand) {
+ delete urlCommand;
+ }
+ if (movieCommand) {
+ delete movieCommand;
+ }
+
+ cMapDirs->startIter(&iter);
+ while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
+ deleteGList(list, GString);
+ }
+ delete cMapDirs;
+
+ delete cidToUnicodeCache;
+ delete unicodeToUnicodeCache;
+ delete unicodeMapCache;
+ delete cMapCache;
+
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+ gDestroyMutex(&unicodeMapCacheMutex);
+ gDestroyMutex(&cMapCacheMutex);
+#endif
+}
+
+//------------------------------------------------------------------------
+// accessors
+//------------------------------------------------------------------------
+
+CharCode GlobalParams::getMacRomanCharCode(const char *charName) {
+ // no need to lock - macRomanReverseMap is constant
+ return macRomanReverseMap->lookup(charName);
+}
+
+Unicode GlobalParams::mapNameToUnicode(const char *charName) {
+ // no need to lock - nameToUnicode is constant
+ return nameToUnicode->lookup(charName);
+}
+
+UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
+ UnicodeMap *map;
+
+ lockGlobalParams;
+ map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
+ unlockGlobalParams;
+ if (map) {
+ map->incRefCnt();
+ }
+ return map;
+}
+
+FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
+ GString *fileName;
+ FILE *f;
+
+ lockGlobalParams;
+ if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
+ f = fopen(fileName->getCString(), "r");
+ } else {
+ f = NULL;
+ }
+ unlockGlobalParams;
+ return f;
+}
+
+FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
+ GList *list;
+ GString *dir;
+ GString *fileName;
+ FILE *f;
+ int i;
+
+ lockGlobalParams;
+ if (!(list = (GList *)cMapDirs->lookup(collection))) {
+ unlockGlobalParams;
+ return NULL;
+ }
+ for (i = 0; i < list->getLength(); ++i) {
+ dir = (GString *)list->get(i);
+ fileName = appendToPath(dir->copy(), cMapName->getCString());
+ f = fopen(fileName->getCString(), "r");
+ delete fileName;
+ if (f) {
+ unlockGlobalParams;
+ return f;
+ }
+ }
+ unlockGlobalParams;
+ return NULL;
+}
+
+FILE *GlobalParams::findToUnicodeFile(GString *name) {
+ GString *dir, *fileName;
+ FILE *f;
+ int i;
+
+ lockGlobalParams;
+ for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
+ dir = (GString *)toUnicodeDirs->get(i);
+ fileName = appendToPath(dir->copy(), name->getCString());
+ f = fopen(fileName->getCString(), "r");
+ delete fileName;
+ if (f) {
+ unlockGlobalParams;
+ return f;
+ }
+ }
+ unlockGlobalParams;
+ return NULL;
+}
+
+DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
+ DisplayFontParam *dfp;
+
+ lockGlobalParams;
+ dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
+ unlockGlobalParams;
+ return dfp;
+}
+
+DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
+ GString *collection) {
+ DisplayFontParam *dfp;
+
+ lockGlobalParams;
+ if (!fontName ||
+ !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
+ dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
+ }
+ unlockGlobalParams;
+ return dfp;
+}
+
+GString *GlobalParams::getPSFile() {
+ GString *s;
+
+ lockGlobalParams;
+ s = psFile ? psFile->copy() : (GString *)NULL;
+ unlockGlobalParams;
+ return s;
+}
+
+void GlobalParams::getPSImageableArea(int &left, int &bottom, int &right, int &top) {
+ lockGlobalParams;
+ left = psLeft;
+ bottom = psBottom;
+ right = psRight;
+ top = psTop;
+ unlockGlobalParams;
+}
+
+
+int GlobalParams::getPSPaperWidth() {
+ int w;
+
+ lockGlobalParams;
+ w = psPaperWidth;
+ unlockGlobalParams;
+ return w;
+}
+
+int GlobalParams::getPSPaperHeight() {
+ int h;
+
+ lockGlobalParams;
+ h = psPaperHeight;
+ unlockGlobalParams;
+ return h;
+}
+
+GBool GlobalParams::getPSDuplex() {
+ GBool d;
+
+ lockGlobalParams;
+ d = psDuplex;
+ unlockGlobalParams;
+ return d;
+}
+
+GBool GlobalParams::getPSFit() {
+ GBool d;
+
+ lockGlobalParams;
+ d = psFit;
+ unlockGlobalParams;
+ return d;
+}
+
+PSLevel GlobalParams::getPSLevel() {
+ PSLevel level;
+
+ lockGlobalParams;
+ level = psLevel;
+ unlockGlobalParams;
+ return level;
+}
+
+PSFontParam *GlobalParams::getPSFont(GString *fontName) {
+ PSFontParam *p;
+
+ lockGlobalParams;
+ p = (PSFontParam *)psFonts->lookup(fontName);
+ unlockGlobalParams;
+ return p;
+}
+
+PSFontParam *GlobalParams::getPSFont16(GString *fontName,
+ GString *collection, int wMode) {
+ PSFontParam *p;
+ int i;
+
+ lockGlobalParams;
+ p = NULL;
+ if (fontName) {
+ for (i = 0; i < psNamedFonts16->getLength(); ++i) {
+ p = (PSFontParam *)psNamedFonts16->get(i);
+ if (!p->pdfFontName->cmp(fontName) &&
+ p->wMode == wMode) {
+ break;
+ }
+ p = NULL;
+ }
+ }
+ if (!p && collection) {
+ for (i = 0; i < psFonts16->getLength(); ++i) {
+ p = (PSFontParam *)psFonts16->get(i);
+ if (!p->pdfFontName->cmp(collection) &&
+ p->wMode == wMode) {
+ break;
+ }
+ p = NULL;
+ }
+ }
+ unlockGlobalParams;
+ return p;
+}
+
+GBool GlobalParams::getPSEmbedType1() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedType1;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedTrueType() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedTrueType;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedCIDPostScript() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedCIDPostScript;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSEmbedCIDTrueType() {
+ GBool e;
+
+ lockGlobalParams;
+ e = psEmbedCIDTrueType;
+ unlockGlobalParams;
+ return e;
+}
+
+GBool GlobalParams::getPSOPI() {
+ GBool opi;
+
+ lockGlobalParams;
+ opi = psOPI;
+ unlockGlobalParams;
+ return opi;
+}
+
+GBool GlobalParams::getPSASCIIHex() {
+ GBool ah;
+
+ lockGlobalParams;
+ ah = psASCIIHex;
+ unlockGlobalParams;
+ return ah;
+}
+
+GString *GlobalParams::getTextEncodingName() {
+ GString *s;
+
+ lockGlobalParams;
+ s = textEncoding->copy();
+ unlockGlobalParams;
+ return s;
+}
+
+EndOfLineKind GlobalParams::getTextEOL() {
+ EndOfLineKind eol;
+
+ lockGlobalParams;
+ eol = textEOL;
+ unlockGlobalParams;
+ return eol;
+}
+
+GBool GlobalParams::getTextPageBreaks() {
+ GBool pageBreaks;
+
+ lockGlobalParams;
+ pageBreaks = textPageBreaks;
+ unlockGlobalParams;
+ return pageBreaks;
+}
+
+GBool GlobalParams::getTextKeepTinyChars() {
+ GBool tiny;
+
+ lockGlobalParams;
+ tiny = textKeepTinyChars;
+ unlockGlobalParams;
+ return tiny;
+}
+
+GString *GlobalParams::findFontFile(GString *fontName,
+ const char **exts) {
+ GString *dir, *fileName;
+ const char **ext;
+ FILE *f;
+ int i;
+
+ lockGlobalParams;
+ for (i = 0; i < fontDirs->getLength(); ++i) {
+ dir = (GString *)fontDirs->get(i);
+ for (ext = exts; *ext; ++ext) {
+ fileName = appendToPath(dir->copy(), fontName->getCString());
+ fileName->append(*ext);
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ unlockGlobalParams;
+ return fileName;
+ }
+ delete fileName;
+ }
+ }
+ unlockGlobalParams;
+ return NULL;
+}
+
+GString *GlobalParams::getInitialZoom() {
+ GString *s;
+
+ lockGlobalParams;
+ s = initialZoom->copy();
+ unlockGlobalParams;
+ return s;
+}
+
+FontRastControl GlobalParams::getT1libControl() {
+ FontRastControl c;
+
+ lockGlobalParams;
+ c = t1libControl;
+ unlockGlobalParams;
+ return c;
+}
+
+FontRastControl GlobalParams::getFreeTypeControl() {
+ FontRastControl c;
+
+ lockGlobalParams;
+ c = freetypeControl;
+ unlockGlobalParams;
+ return c;
+}
+
+GBool GlobalParams::getMapNumericCharNames() {
+ GBool map;
+
+ lockGlobalParams;
+ map = mapNumericCharNames;
+ unlockGlobalParams;
+ return map;
+}
+
+GBool GlobalParams::getPrintCommands() {
+ GBool p;
+
+ lockGlobalParams;
+ p = printCommands;
+ unlockGlobalParams;
+ return p;
+}
+
+GBool GlobalParams::getErrQuiet() {
+ GBool q;
+
+ lockGlobalParams;
+ q = errQuiet;
+ unlockGlobalParams;
+ return q;
+}
+
+CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
+ GString *fileName;
+ CharCodeToUnicode *ctu;
+
+ lockGlobalParams;
+ if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
+ if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
+ (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
+ cidToUnicodeCache->add(ctu);
+ }
+ }
+ unlockGlobalParams;
+ return ctu;
+}
+
+CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
+ CharCodeToUnicode *ctu;
+ GHashIter *iter;
+ GString *fontPattern, *fileName;
+
+ lockGlobalParams;
+ fileName = NULL;
+ unicodeToUnicodes->startIter(&iter);
+ while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
+ if (strstr(fontName->getCString(), fontPattern->getCString())) {
+ unicodeToUnicodes->killIter(&iter);
+ break;
+ }
+ fileName = NULL;
+ }
+ if (fileName) {
+ if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
+ if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
+ unicodeToUnicodeCache->add(ctu);
+ }
+ }
+ } else {
+ ctu = NULL;
+ }
+ unlockGlobalParams;
+ return ctu;
+}
+
+UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
+ return getUnicodeMap2(encodingName);
+}
+
+UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
+ UnicodeMap *map;
+
+ if (!(map = getResidentUnicodeMap(encodingName))) {
+ lockUnicodeMapCache;
+ map = unicodeMapCache->getUnicodeMap(encodingName);
+ unlockUnicodeMapCache;
+ }
+ return map;
+}
+
+CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
+ CMap *cMap;
+
+ lockCMapCache;
+ cMap = cMapCache->getCMap(collection, cMapName);
+ unlockCMapCache;
+ return cMap;
+}
+
+UnicodeMap *GlobalParams::getTextEncoding() {
+ return getUnicodeMap2(textEncoding);
+}
+
+//------------------------------------------------------------------------
+// functions to set parameters
+//------------------------------------------------------------------------
+
+void GlobalParams::addDisplayFont(DisplayFontParam *param) {
+ DisplayFontParam *old;
+
+ lockGlobalParams;
+ if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
+ delete old;
+ }
+ displayFonts->add(param->name, param);
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSFile(const char *file) {
+ lockGlobalParams;
+ if (psFile) {
+ delete psFile;
+ }
+ psFile = new GString(file);
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSImageableArea(int left, int bottom, int right, int top) {
+ lockGlobalParams;
+ psLeft = left;
+ psBottom = bottom;
+ psRight = right;
+ psTop = top;
+ unlockGlobalParams;
+}
+
+GBool GlobalParams::setPSPaperSize(const char *size) {
+ lockGlobalParams;
+ if (!strcmp(size, "match")) {
+ psPaperWidth = psPaperHeight = -1;
+ } else if (!strcmp(size, "letter")) {
+ psPaperWidth = 612;
+ psPaperHeight = 792;
+ } else if (!strcmp(size, "legal")) {
+ psPaperWidth = 612;
+ psPaperHeight = 1008;
+ } else if (!strcmp(size, "A4")) {
+ psPaperWidth = 595;
+ psPaperHeight = 842;
+ } else if (!strcmp(size, "A3")) {
+ psPaperWidth = 842;
+ psPaperHeight = 1190;
+ } else if (!strcmp(size, "Universal")) {
+ psPaperWidth = 595;
+ psPaperHeight = 792;
+ } else {
+ unlockGlobalParams;
+ return gFalse;
+ }
+ psLeft = 0;
+ psBottom = 0;
+ psRight = psPaperWidth;
+ psTop = psPaperHeight;
+ unlockGlobalParams;
+ return gTrue;
+}
+
+void GlobalParams::setPSPaperWidth(int width) {
+ lockGlobalParams;
+ psPaperWidth = width;
+ psLeft = 0;
+ psRight = psPaperWidth;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSPaperHeight(int height) {
+ lockGlobalParams;
+ psPaperHeight = height;
+ psBottom = 0;
+ psTop = psPaperHeight;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSDuplex(GBool duplex) {
+ lockGlobalParams;
+ psDuplex = duplex;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSFit(GBool fit) {
+ lockGlobalParams;
+ psFit = fit;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSLevel(PSLevel level) {
+ lockGlobalParams;
+ psLevel = level;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSEmbedType1(GBool embed) {
+ lockGlobalParams;
+ psEmbedType1 = embed;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSEmbedTrueType(GBool embed) {
+ lockGlobalParams;
+ psEmbedTrueType = embed;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
+ lockGlobalParams;
+ psEmbedCIDPostScript = embed;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
+ lockGlobalParams;
+ psEmbedCIDTrueType = embed;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSOPI(GBool opi) {
+ lockGlobalParams;
+ psOPI = opi;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPSASCIIHex(GBool hex) {
+ lockGlobalParams;
+ psASCIIHex = hex;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setTextEncoding(const char *encodingName) {
+ lockGlobalParams;
+ delete textEncoding;
+ textEncoding = new GString(encodingName);
+ unlockGlobalParams;
+}
+
+GBool GlobalParams::setTextEOL(const char *s) {
+ lockGlobalParams;
+ if (!strcmp(s, "unix")) {
+ textEOL = eolUnix;
+ } else if (!strcmp(s, "dos")) {
+ textEOL = eolDOS;
+ } else if (!strcmp(s, "mac")) {
+ textEOL = eolMac;
+ } else {
+ unlockGlobalParams;
+ return gFalse;
+ }
+ unlockGlobalParams;
+ return gTrue;
+}
+
+void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
+ lockGlobalParams;
+ textPageBreaks = pageBreaks;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setTextKeepTinyChars(GBool keep) {
+ lockGlobalParams;
+ textKeepTinyChars = keep;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setInitialZoom(const char *s) {
+ lockGlobalParams;
+ delete initialZoom;
+ initialZoom = new GString(s);
+ unlockGlobalParams;
+}
+
+GBool GlobalParams::setT1libControl(const char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = setFontRastControl(&t1libControl, s);
+ unlockGlobalParams;
+ return ok;
+}
+
+GBool GlobalParams::setFreeTypeControl(const char *s) {
+ GBool ok;
+
+ lockGlobalParams;
+ ok = setFontRastControl(&freetypeControl, s);
+ unlockGlobalParams;
+ return ok;
+}
+
+GBool GlobalParams::setFontRastControl(FontRastControl *val, const char *s) {
+ lockGlobalParams;
+ if (!strcmp(s, "none")) {
+ *val = fontRastNone;
+ } else if (!strcmp(s, "plain")) {
+ *val = fontRastPlain;
+ } else if (!strcmp(s, "low")) {
+ *val = fontRastAALow;
+ } else if (!strcmp(s, "high")) {
+ *val = fontRastAAHigh;
+ } else {
+ unlockGlobalParams;
+ return gFalse;
+ }
+ unlockGlobalParams;
+ return gTrue;
+}
+
+void GlobalParams::setMapNumericCharNames(GBool map) {
+ lockGlobalParams;
+ mapNumericCharNames = map;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setPrintCommands(GBool printCommandsA) {
+ lockGlobalParams;
+ printCommands = printCommandsA;
+ unlockGlobalParams;
+}
+
+void GlobalParams::setErrQuiet(GBool errQuietA) {
+ lockGlobalParams;
+ errQuiet = errQuietA;
+ unlockGlobalParams;
+}
diff --git a/pdftops/GlobalParams.h b/pdftops/GlobalParams.h
new file mode 100644
index 000000000..913a1fd59
--- /dev/null
+++ b/pdftops/GlobalParams.h
@@ -0,0 +1,313 @@
+//========================================================================
+//
+// GlobalParams.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GLOBALPARAMS_H
+#define GLOBALPARAMS_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "gtypes.h"
+#include "CharTypes.h"
+
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
+class GString;
+class GList;
+class GHash;
+class NameToCharCode;
+class CharCodeToUnicode;
+class CharCodeToUnicodeCache;
+class UnicodeMap;
+class UnicodeMapCache;
+class CMap;
+class CMapCache;
+class GlobalParams;
+
+//------------------------------------------------------------------------
+
+// The global parameters object.
+extern GlobalParams *globalParams;
+
+//------------------------------------------------------------------------
+
+enum DisplayFontParamKind {
+ displayFontX,
+ displayFontT1,
+ displayFontTT
+};
+
+class DisplayFontParam {
+public:
+
+ GString *name; // font name for 8-bit fonts and named
+ // CID fonts; collection name for
+ // generic CID fonts
+ DisplayFontParamKind kind;
+ union {
+ struct {
+ GString *xlfd;
+ GString *encoding;
+ } x;
+ struct {
+ GString *fileName;
+ } t1;
+ struct {
+ GString *fileName;
+ } tt;
+ };
+
+ DisplayFontParam(GString *nameA, DisplayFontParamKind kindA);
+ DisplayFontParam(const char *nameA, const char *xlfdA, const char *encodingA);
+ ~DisplayFontParam();
+};
+
+// Font rasterizer control.
+enum FontRastControl {
+ fontRastNone, // don't use this rasterizer
+ fontRastPlain, // use it, without anti-aliasing
+ fontRastAALow, // use it, with low-level anti-aliasing
+ fontRastAAHigh // use it, with high-level anti-aliasing
+};
+
+//------------------------------------------------------------------------
+
+class PSFontParam {
+public:
+
+ GString *pdfFontName; // PDF font name for 8-bit fonts and
+ // named 16-bit fonts; char collection
+ // name for generic 16-bit fonts
+ int wMode; // writing mode (0=horiz, 1=vert) for
+ // 16-bit fonts
+ GString *psFontName; // PostScript font name
+ GString *encoding; // encoding, for 16-bit fonts only
+
+ PSFontParam(GString *pdfFontNameA, int wModeA,
+ GString *psFontNameA, GString *encodingA);
+ ~PSFontParam();
+};
+
+//------------------------------------------------------------------------
+
+enum PSLevel {
+ psLevel1,
+ psLevel1Sep,
+ psLevel2,
+ psLevel2Sep,
+ psLevel3,
+ psLevel3Sep
+};
+
+//------------------------------------------------------------------------
+
+enum EndOfLineKind {
+ eolUnix, // LF
+ eolDOS, // CR+LF
+ eolMac // CR
+};
+
+//------------------------------------------------------------------------
+
+class GlobalParams {
+public:
+
+ // Initialize the global parameters by attempting to read a config
+ // file.
+ GlobalParams(const char *cfgFileName);
+
+ ~GlobalParams();
+
+ //----- accessors
+
+ CharCode getMacRomanCharCode(const char *charName);
+
+ Unicode mapNameToUnicode(const char *charName);
+ UnicodeMap *getResidentUnicodeMap(GString *encodingName);
+ FILE *getUnicodeMapFile(GString *encodingName);
+ FILE *findCMapFile(GString *collection, GString *cMapName);
+ FILE *findToUnicodeFile(GString *name);
+ DisplayFontParam *getDisplayFont(GString *fontName);
+ DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection);
+ GString *getPSFile();
+ void getPSImageableArea(int &left, int &bottom, int &right, int &top);
+ int getPSPaperWidth();
+ int getPSPaperHeight();
+ GBool getPSDuplex();
+ GBool getPSFit();
+ PSLevel getPSLevel();
+ PSFontParam *getPSFont(GString *fontName);
+ PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode);
+ GBool getPSEmbedType1();
+ GBool getPSEmbedTrueType();
+ GBool getPSEmbedCIDPostScript();
+ GBool getPSEmbedCIDTrueType();
+ GBool getPSOPI();
+ GBool getPSASCIIHex();
+ GString *getTextEncodingName();
+ EndOfLineKind getTextEOL();
+ GBool getTextPageBreaks();
+ GBool getTextKeepTinyChars();
+ GString *findFontFile(GString *fontName, const char **exts);
+ GString *getInitialZoom();
+ FontRastControl getT1libControl();
+ FontRastControl getFreeTypeControl();
+ GString *getURLCommand() { return urlCommand; }
+ GString *getMovieCommand() { return movieCommand; }
+ GBool getMapNumericCharNames();
+ GBool getPrintCommands();
+ GBool getErrQuiet();
+
+ CharCodeToUnicode *getCIDToUnicode(GString *collection);
+ CharCodeToUnicode *getUnicodeToUnicode(GString *fontName);
+ UnicodeMap *getUnicodeMap(GString *encodingName);
+ CMap *getCMap(GString *collection, GString *cMapName);
+ UnicodeMap *getTextEncoding();
+
+ //----- functions to set parameters
+
+ void addDisplayFont(DisplayFontParam *param);
+ void setPSFile(const char *file);
+ GBool setPSPaperSize(const char *size);
+ void setPSImageableArea(int left, int bottom, int right, int top);
+ void setPSPaperWidth(int width);
+ void setPSPaperHeight(int height);
+ void setPSDuplex(GBool duplex);
+ void setPSFit(GBool fit);
+ void setPSLevel(PSLevel level);
+ void setPSEmbedType1(GBool embed);
+ void setPSEmbedTrueType(GBool embed);
+ void setPSEmbedCIDPostScript(GBool embed);
+ void setPSEmbedCIDTrueType(GBool embed);
+ void setPSOPI(GBool opi);
+ void setPSASCIIHex(GBool hex);
+ void setTextEncoding(const char *encodingName);
+ GBool setTextEOL(const char *s);
+ void setTextPageBreaks(GBool pageBreaks);
+ void setTextKeepTinyChars(GBool keep);
+ void setInitialZoom(const char *s);
+ GBool setT1libControl(const char *s);
+ GBool setFreeTypeControl(const char *s);
+ void setMapNumericCharNames(GBool map);
+ void setPrintCommands(GBool printCommandsA);
+ void setErrQuiet(GBool errQuietA);
+
+private:
+
+ void parseFile(GString *fileName, FILE *f);
+ void parseNameToUnicode(GList *tokens, GString *fileName, int line);
+ void parseCIDToUnicode(GList *tokens, GString *fileName, int line);
+ void parseUnicodeToUnicode(GList *tokens, GString *fileName, int line);
+ void parseUnicodeMap(GList *tokens, GString *fileName, int line);
+ void parseCMapDir(GList *tokens, GString *fileName, int line);
+ void parseToUnicodeDir(GList *tokens, GString *fileName, int line);
+ void parseDisplayFont(GList *tokens, GHash *fontHash,
+ DisplayFontParamKind kind,
+ GString *fileName, int line);
+ void parsePSFile(GList *tokens, GString *fileName, int line);
+ void parsePSPaperSize(GList *tokens, GString *fileName, int line);
+ void parsePSLevel(GList *tokens, GString *fileName, int line);
+ void parsePSFont(GList *tokens, GString *fileName, int line);
+ void parsePSFont16(const char *cmdName, GList *fontList,
+ GList *tokens, GString *fileName, int line);
+ void parseTextEncoding(GList *tokens, GString *fileName, int line);
+ void parseTextEOL(GList *tokens, GString *fileName, int line);
+ void parseFontDir(GList *tokens, GString *fileName, int line);
+ void parseInitialZoom(GList *tokens, GString *fileName, int line);
+ void parseFontRastControl(const char *cmdName, FontRastControl *val,
+ GList *tokens, GString *fileName, int line);
+ void parseCommand(const char *cmdName, GString **val,
+ GList *tokens, GString *fileName, int line);
+ void parseYesNo(const char *cmdName, GBool *flag,
+ GList *tokens, GString *fileName, int line);
+ UnicodeMap *getUnicodeMap2(GString *encodingName);
+ GBool setFontRastControl(FontRastControl *val, const char *s);
+
+ //----- static tables
+
+ NameToCharCode * // mapping from char name to
+ macRomanReverseMap; // MacRomanEncoding index
+
+ //----- user-modifiable settings
+
+ NameToCharCode * // mapping from char name to Unicode
+ nameToUnicode;
+ GHash *cidToUnicodes; // files for mappings from char collections
+ // to Unicode, indexed by collection name
+ // [GString]
+ GHash *unicodeToUnicodes; // files for Unicode-to-Unicode mappings,
+ // indexed by font name pattern [GString]
+ GHash *residentUnicodeMaps; // mappings from Unicode to char codes,
+ // indexed by encoding name [UnicodeMap]
+ GHash *unicodeMaps; // files for mappings from Unicode to char
+ // codes, indexed by encoding name [GString]
+ GHash *cMapDirs; // list of CMap dirs, indexed by collection
+ // name [GList[GString]]
+ GList *toUnicodeDirs; // list of ToUnicode CMap dirs [GString]
+ GHash *displayFonts; // display font info, indexed by font name
+ // [DisplayFontParam]
+ GHash *displayCIDFonts; // display CID font info, indexed by
+ // collection [DisplayFontParam]
+ GHash *displayNamedCIDFonts; // display CID font info, indexed by
+ // font name [DisplayFontParam]
+ GString *psFile; // PostScript file or command (for xpdf)
+ int psPaperWidth; // paper size, in PostScript points, for
+ int psPaperHeight; // PostScript output
+ int psLeft; // imageable area, in PostScript points,
+ int psBottom; // for PostScript output
+ int psRight; // ...
+ int psTop; // ...
+ GBool psDuplex; // enable duplexing in PostScript?
+ GBool psFit; // fit pages to device?
+ PSLevel psLevel; // PostScript level to generate
+ GHash *psFonts; // PostScript font info, indexed by PDF
+ // font name [PSFontParam]
+ GList *psNamedFonts16; // named 16-bit fonts [PSFontParam]
+ GList *psFonts16; // generic 16-bit fonts [PSFontParam]
+ GBool psEmbedType1; // embed Type 1 fonts?
+ GBool psEmbedTrueType; // embed TrueType fonts?
+ GBool psEmbedCIDPostScript; // embed CID PostScript fonts?
+ GBool psEmbedCIDTrueType; // embed CID TrueType fonts?
+ GBool psOPI; // generate PostScript OPI comments?
+ GBool psASCIIHex; // use ASCIIHex instead of ASCII85?
+ GString *textEncoding; // encoding (unicodeMap) to use for text
+ // output
+ EndOfLineKind textEOL; // type of EOL marker to use for text
+ // output
+ GBool textPageBreaks; // insert end-of-page markers?
+ GBool textKeepTinyChars; // keep all characters in text output
+ GList *fontDirs; // list of font dirs [GString]
+ GString *initialZoom; // initial zoom level
+ FontRastControl t1libControl; // t1lib rasterization mode
+ FontRastControl // FreeType rasterization mode
+ freetypeControl;
+ GString *urlCommand; // command executed for URL links
+ GString *movieCommand; // command executed for movie annotations
+ GBool mapNumericCharNames; // map numeric char names (from font subsets)?
+ GBool printCommands; // print the drawing commands
+ GBool errQuiet; // suppress error messages?
+
+ CharCodeToUnicodeCache *cidToUnicodeCache;
+ CharCodeToUnicodeCache *unicodeToUnicodeCache;
+ UnicodeMapCache *unicodeMapCache;
+ CMapCache *cMapCache;
+
+#if MULTITHREADED
+ GMutex mutex;
+ GMutex unicodeMapCacheMutex;
+ GMutex cMapCacheMutex;
+#endif
+};
+
+#endif
diff --git a/pdftops/JBIG2Stream.cxx b/pdftops/JBIG2Stream.cxx
new file mode 100644
index 000000000..4716a16e4
--- /dev/null
+++ b/pdftops/JBIG2Stream.cxx
@@ -0,0 +1,3658 @@
+//========================================================================
+//
+// JBIG2Stream.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include "GList.h"
+#include "Error.h"
+#include "JBIG2Stream.h"
+
+//~ share these tables
+#include "Stream-CCITT.h"
+
+//------------------------------------------------------------------------
+
+static int contextSize[4] = { 16, 13, 10, 10 };
+static int refContextSize[2] = { 13, 10 };
+
+//------------------------------------------------------------------------
+// JBIG2ArithmeticDecoderStats
+//------------------------------------------------------------------------
+
+class JBIG2ArithmeticDecoderStats {
+public:
+
+ JBIG2ArithmeticDecoderStats(int contextSizeA);
+ ~JBIG2ArithmeticDecoderStats();
+ JBIG2ArithmeticDecoderStats *copy();
+ void reset();
+ int getContextSize() { return contextSize; }
+ void copyFrom(JBIG2ArithmeticDecoderStats *stats);
+
+private:
+
+ Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx]
+ int contextSize;
+
+ friend class JBIG2ArithmeticDecoder;
+};
+
+JBIG2ArithmeticDecoderStats::JBIG2ArithmeticDecoderStats(int contextSizeA) {
+ contextSize = contextSizeA;
+ cxTab = (Guchar *)gmalloc((1 << contextSize) * sizeof(Guchar));
+ reset();
+}
+
+JBIG2ArithmeticDecoderStats::~JBIG2ArithmeticDecoderStats() {
+ gfree(cxTab);
+}
+
+JBIG2ArithmeticDecoderStats *JBIG2ArithmeticDecoderStats::copy() {
+ JBIG2ArithmeticDecoderStats *stats;
+
+ stats = new JBIG2ArithmeticDecoderStats(contextSize);
+ memcpy(stats->cxTab, cxTab, 1 << contextSize);
+ return stats;
+}
+
+void JBIG2ArithmeticDecoderStats::reset() {
+ memset(cxTab, 0, 1 << contextSize);
+}
+
+void JBIG2ArithmeticDecoderStats::copyFrom(
+ JBIG2ArithmeticDecoderStats *stats) {
+ memcpy(cxTab, stats->cxTab, 1 << contextSize);
+}
+
+//------------------------------------------------------------------------
+// JBIG2ArithmeticDecoder
+//------------------------------------------------------------------------
+
+class JBIG2ArithmeticDecoder {
+public:
+
+ JBIG2ArithmeticDecoder();
+ ~JBIG2ArithmeticDecoder();
+ void setStream(Stream *strA) { str = strA; }
+ void start();
+ int decodeBit(Guint context, JBIG2ArithmeticDecoderStats *stats);
+ int decodeByte(Guint context, JBIG2ArithmeticDecoderStats *stats);
+
+ // Returns false for OOB, otherwise sets *<x> and returns true.
+ GBool decodeInt(int *x, JBIG2ArithmeticDecoderStats *stats);
+
+ Guint decodeIAID(Guint codeLen,
+ JBIG2ArithmeticDecoderStats *stats);
+
+private:
+
+ int decodeIntBit(JBIG2ArithmeticDecoderStats *stats);
+ void byteIn();
+
+ static Guint qeTab[47];
+ static int nmpsTab[47];
+ static int nlpsTab[47];
+ static int switchTab[47];
+
+ Guint buf0, buf1;
+ Guint c, a;
+ int ct;
+
+ Guint prev; // for the integer decoder
+
+ Stream *str;
+};
+
+Guint JBIG2ArithmeticDecoder::qeTab[47] = {
+ 0x56010000, 0x34010000, 0x18010000, 0x0AC10000,
+ 0x05210000, 0x02210000, 0x56010000, 0x54010000,
+ 0x48010000, 0x38010000, 0x30010000, 0x24010000,
+ 0x1C010000, 0x16010000, 0x56010000, 0x54010000,
+ 0x51010000, 0x48010000, 0x38010000, 0x34010000,
+ 0x30010000, 0x28010000, 0x24010000, 0x22010000,
+ 0x1C010000, 0x18010000, 0x16010000, 0x14010000,
+ 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000,
+ 0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
+ 0x02210000, 0x01410000, 0x01110000, 0x00850000,
+ 0x00490000, 0x00250000, 0x00150000, 0x00090000,
+ 0x00050000, 0x00010000, 0x56010000
+};
+
+int JBIG2ArithmeticDecoder::nmpsTab[47] = {
+ 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46
+};
+
+int JBIG2ArithmeticDecoder::nlpsTab[47] = {
+ 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14,
+ 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46
+};
+
+int JBIG2ArithmeticDecoder::switchTab[47] = {
+ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+JBIG2ArithmeticDecoder::JBIG2ArithmeticDecoder() {
+ str = NULL;
+}
+
+JBIG2ArithmeticDecoder::~JBIG2ArithmeticDecoder() {
+}
+
+void JBIG2ArithmeticDecoder::start() {
+ buf0 = (Guint)str->getChar() & 0xff;
+ buf1 = (Guint)str->getChar() & 0xff;
+
+ // INITDEC
+ c = (buf0 ^ 0xff) << 16;
+ byteIn();
+ c <<= 7;
+ ct -= 7;
+ a = 0x80000000;
+}
+
+int JBIG2ArithmeticDecoder::decodeBit(Guint context,
+ JBIG2ArithmeticDecoderStats *stats) {
+ int bit;
+ Guint qe;
+ int iCX, mpsCX;
+
+ iCX = stats->cxTab[context] >> 1;
+ mpsCX = stats->cxTab[context] & 1;
+ qe = qeTab[iCX];
+ a -= qe;
+ if (c < a) {
+ if (a & 0x80000000) {
+ bit = mpsCX;
+ } else {
+ // MPS_EXCHANGE
+ if (a < qe) {
+ bit = 1 - mpsCX;
+ if (switchTab[iCX]) {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
+ } else {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
+ }
+ } else {
+ bit = mpsCX;
+ stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
+ }
+ // RENORMD
+ do {
+ if (ct == 0) {
+ byteIn();
+ }
+ a <<= 1;
+ c <<= 1;
+ --ct;
+ } while (!(a & 0x80000000));
+ }
+ } else {
+ c -= a;
+ // LPS_EXCHANGE
+ if (a < qe) {
+ bit = mpsCX;
+ stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
+ } else {
+ bit = 1 - mpsCX;
+ if (switchTab[iCX]) {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
+ } else {
+ stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
+ }
+ }
+ a = qe;
+ // RENORMD
+ do {
+ if (ct == 0) {
+ byteIn();
+ }
+ a <<= 1;
+ c <<= 1;
+ --ct;
+ } while (!(a & 0x80000000));
+ }
+ return bit;
+}
+
+int JBIG2ArithmeticDecoder::decodeByte(Guint context,
+ JBIG2ArithmeticDecoderStats *stats) {
+ int byte;
+ int i;
+
+ byte = 0;
+ for (i = 0; i < 8; ++i) {
+ byte = (byte << 1) | decodeBit(context, stats);
+ }
+ return byte;
+}
+
+GBool JBIG2ArithmeticDecoder::decodeInt(int *x,
+ JBIG2ArithmeticDecoderStats *stats) {
+ int s;
+ Guint v;
+ int i;
+
+ prev = 1;
+ s = decodeIntBit(stats);
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ if (decodeIntBit(stats)) {
+ v = 0;
+ for (i = 0; i < 32; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 4436;
+ } else {
+ v = 0;
+ for (i = 0; i < 12; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 340;
+ }
+ } else {
+ v = 0;
+ for (i = 0; i < 8; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 84;
+ }
+ } else {
+ v = 0;
+ for (i = 0; i < 6; ++i) {
+ v = (v << 1) | decodeIntBit(stats);
+ }
+ v += 20;
+ }
+ } else {
+ v = decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ v += 4;
+ }
+ } else {
+ v = decodeIntBit(stats);
+ v = (v << 1) | decodeIntBit(stats);
+ }
+
+ if (s) {
+ if (v == 0) {
+ return gFalse;
+ }
+ *x = -(int)v;
+ } else {
+ *x = (int)v;
+ }
+ return gTrue;
+}
+
+int JBIG2ArithmeticDecoder::decodeIntBit(JBIG2ArithmeticDecoderStats *stats) {
+ int bit;
+
+ bit = decodeBit(prev, stats);
+ if (prev < 0x100) {
+ prev = (prev << 1) | bit;
+ } else {
+ prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
+ }
+ return bit;
+}
+
+Guint JBIG2ArithmeticDecoder::decodeIAID(Guint codeLen,
+ JBIG2ArithmeticDecoderStats *stats) {
+ Guint i;
+ int bit;
+
+ prev = 1;
+ for (i = 0; i < codeLen; ++i) {
+ bit = decodeBit(prev, stats);
+ prev = (prev << 1) | bit;
+ }
+ return prev - (1 << codeLen);
+}
+
+void JBIG2ArithmeticDecoder::byteIn() {
+ if (buf0 == 0xff) {
+ if (buf1 > 0x8f) {
+ ct = 8;
+ } else {
+ buf0 = buf1;
+ buf1 = (Guint)str->getChar() & 0xff;
+ c = c + 0xfe00 - (buf0 << 9);
+ ct = 7;
+ }
+ } else {
+ buf0 = buf1;
+ buf1 = (Guint)str->getChar() & 0xff;
+ c = c + 0xff00 - (buf0 << 8);
+ ct = 8;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2HuffmanTable
+//------------------------------------------------------------------------
+
+#define jbig2HuffmanLOW 0xfffffffd
+#define jbig2HuffmanOOB 0xfffffffe
+#define jbig2HuffmanEOT 0xffffffff
+
+struct JBIG2HuffmanTable {
+ int val;
+ Guint prefixLen;
+ Guint rangeLen; // can also be LOW, OOB, or EOT
+ Guint prefix;
+};
+
+JBIG2HuffmanTable huffTableA[] = {
+ { 0, 1, 4, 0x000 },
+ { 16, 2, 8, 0x002 },
+ { 272, 3, 16, 0x006 },
+ { 65808, 3, 32, 0x007 },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableB[] = {
+ { 0, 1, 0, 0x000 },
+ { 1, 2, 0, 0x002 },
+ { 2, 3, 0, 0x006 },
+ { 3, 4, 3, 0x00e },
+ { 11, 5, 6, 0x01e },
+ { 75, 6, 32, 0x03e },
+ { 0, 6, jbig2HuffmanOOB, 0x03f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableC[] = {
+ { 0, 1, 0, 0x000 },
+ { 1, 2, 0, 0x002 },
+ { 2, 3, 0, 0x006 },
+ { 3, 4, 3, 0x00e },
+ { 11, 5, 6, 0x01e },
+ { 0, 6, jbig2HuffmanOOB, 0x03e },
+ { 75, 7, 32, 0x0fe },
+ { -256, 8, 8, 0x0fe },
+ { -257, 8, jbig2HuffmanLOW, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableD[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 0, 0x006 },
+ { 4, 4, 3, 0x00e },
+ { 12, 5, 6, 0x01e },
+ { 76, 5, 32, 0x01f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableE[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 0, 0x006 },
+ { 4, 4, 3, 0x00e },
+ { 12, 5, 6, 0x01e },
+ { 76, 6, 32, 0x03e },
+ { -255, 7, 8, 0x07e },
+ { -256, 7, jbig2HuffmanLOW, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableF[] = {
+ { 0, 2, 7, 0x000 },
+ { 128, 3, 7, 0x002 },
+ { 256, 3, 8, 0x003 },
+ { -1024, 4, 9, 0x008 },
+ { -512, 4, 8, 0x009 },
+ { -256, 4, 7, 0x00a },
+ { -32, 4, 5, 0x00b },
+ { 512, 4, 9, 0x00c },
+ { 1024, 4, 10, 0x00d },
+ { -2048, 5, 10, 0x01c },
+ { -128, 5, 6, 0x01d },
+ { -64, 5, 5, 0x01e },
+ { -2049, 6, jbig2HuffmanLOW, 0x03e },
+ { 2048, 6, 32, 0x03f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableG[] = {
+ { -512, 3, 8, 0x000 },
+ { 256, 3, 8, 0x001 },
+ { 512, 3, 9, 0x002 },
+ { 1024, 3, 10, 0x003 },
+ { -1024, 4, 9, 0x008 },
+ { -256, 4, 7, 0x009 },
+ { -32, 4, 5, 0x00a },
+ { 0, 4, 5, 0x00b },
+ { 128, 4, 7, 0x00c },
+ { -128, 5, 6, 0x01a },
+ { -64, 5, 5, 0x01b },
+ { 32, 5, 5, 0x01c },
+ { 64, 5, 6, 0x01d },
+ { -1025, 5, jbig2HuffmanLOW, 0x01e },
+ { 2048, 5, 32, 0x01f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableH[] = {
+ { 0, 2, 1, 0x000 },
+ { 0, 2, jbig2HuffmanOOB, 0x001 },
+ { 4, 3, 4, 0x004 },
+ { -1, 4, 0, 0x00a },
+ { 22, 4, 4, 0x00b },
+ { 38, 4, 5, 0x00c },
+ { 2, 5, 0, 0x01a },
+ { 70, 5, 6, 0x01b },
+ { 134, 5, 7, 0x01c },
+ { 3, 6, 0, 0x03a },
+ { 20, 6, 1, 0x03b },
+ { 262, 6, 7, 0x03c },
+ { 646, 6, 10, 0x03d },
+ { -2, 7, 0, 0x07c },
+ { 390, 7, 8, 0x07d },
+ { -15, 8, 3, 0x0fc },
+ { -5, 8, 1, 0x0fd },
+ { -7, 9, 1, 0x1fc },
+ { -3, 9, 0, 0x1fd },
+ { -16, 9, jbig2HuffmanLOW, 0x1fe },
+ { 1670, 9, 32, 0x1ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableI[] = {
+ { 0, 2, jbig2HuffmanOOB, 0x000 },
+ { -1, 3, 1, 0x002 },
+ { 1, 3, 1, 0x003 },
+ { 7, 3, 5, 0x004 },
+ { -3, 4, 1, 0x00a },
+ { 43, 4, 5, 0x00b },
+ { 75, 4, 6, 0x00c },
+ { 3, 5, 1, 0x01a },
+ { 139, 5, 7, 0x01b },
+ { 267, 5, 8, 0x01c },
+ { 5, 6, 1, 0x03a },
+ { 39, 6, 2, 0x03b },
+ { 523, 6, 8, 0x03c },
+ { 1291, 6, 11, 0x03d },
+ { -5, 7, 1, 0x07c },
+ { 779, 7, 9, 0x07d },
+ { -31, 8, 4, 0x0fc },
+ { -11, 8, 2, 0x0fd },
+ { -15, 9, 2, 0x1fc },
+ { -7, 9, 1, 0x1fd },
+ { -32, 9, jbig2HuffmanLOW, 0x1fe },
+ { 3339, 9, 32, 0x1ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableJ[] = {
+ { -2, 2, 2, 0x000 },
+ { 6, 2, 6, 0x001 },
+ { 0, 2, jbig2HuffmanOOB, 0x002 },
+ { -3, 5, 0, 0x018 },
+ { 2, 5, 0, 0x019 },
+ { 70, 5, 5, 0x01a },
+ { 3, 6, 0, 0x036 },
+ { 102, 6, 5, 0x037 },
+ { 134, 6, 6, 0x038 },
+ { 198, 6, 7, 0x039 },
+ { 326, 6, 8, 0x03a },
+ { 582, 6, 9, 0x03b },
+ { 1094, 6, 10, 0x03c },
+ { -21, 7, 4, 0x07a },
+ { -4, 7, 0, 0x07b },
+ { 4, 7, 0, 0x07c },
+ { 2118, 7, 11, 0x07d },
+ { -5, 8, 0, 0x0fc },
+ { 5, 8, 0, 0x0fd },
+ { -22, 8, jbig2HuffmanLOW, 0x0fe },
+ { 4166, 8, 32, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableK[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 1, 0x002 },
+ { 4, 4, 0, 0x00c },
+ { 5, 4, 1, 0x00d },
+ { 7, 5, 1, 0x01c },
+ { 9, 5, 2, 0x01d },
+ { 13, 6, 2, 0x03c },
+ { 17, 7, 2, 0x07a },
+ { 21, 7, 3, 0x07b },
+ { 29, 7, 4, 0x07c },
+ { 45, 7, 5, 0x07d },
+ { 77, 7, 6, 0x07e },
+ { 141, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableL[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 2, 0, 0x002 },
+ { 3, 3, 1, 0x006 },
+ { 5, 5, 0, 0x01c },
+ { 6, 5, 1, 0x01d },
+ { 8, 6, 1, 0x03c },
+ { 10, 7, 0, 0x07a },
+ { 11, 7, 1, 0x07b },
+ { 13, 7, 2, 0x07c },
+ { 17, 7, 3, 0x07d },
+ { 25, 7, 4, 0x07e },
+ { 41, 8, 5, 0x0fe },
+ { 73, 8, 32, 0x0ff },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableM[] = {
+ { 1, 1, 0, 0x000 },
+ { 2, 3, 0, 0x004 },
+ { 7, 3, 3, 0x005 },
+ { 3, 4, 0, 0x00c },
+ { 5, 4, 1, 0x00d },
+ { 4, 5, 0, 0x01c },
+ { 15, 6, 1, 0x03a },
+ { 17, 6, 2, 0x03b },
+ { 21, 6, 3, 0x03c },
+ { 29, 6, 4, 0x03d },
+ { 45, 6, 5, 0x03e },
+ { 77, 7, 6, 0x07e },
+ { 141, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableN[] = {
+ { 0, 1, 0, 0x000 },
+ { -2, 3, 0, 0x004 },
+ { -1, 3, 0, 0x005 },
+ { 1, 3, 0, 0x006 },
+ { 2, 3, 0, 0x007 },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+JBIG2HuffmanTable huffTableO[] = {
+ { 0, 1, 0, 0x000 },
+ { -1, 3, 0, 0x004 },
+ { 1, 3, 0, 0x005 },
+ { -2, 4, 0, 0x00c },
+ { 2, 4, 0, 0x00d },
+ { -4, 5, 1, 0x01c },
+ { 3, 5, 1, 0x01d },
+ { -8, 6, 2, 0x03c },
+ { 5, 6, 2, 0x03d },
+ { -24, 7, 4, 0x07c },
+ { 9, 7, 4, 0x07d },
+ { -25, 7, jbig2HuffmanLOW, 0x07e },
+ { 25, 7, 32, 0x07f },
+ { 0, 0, jbig2HuffmanEOT, 0 }
+};
+
+//------------------------------------------------------------------------
+// JBIG2HuffmanDecoder
+//------------------------------------------------------------------------
+
+class JBIG2HuffmanDecoder {
+public:
+
+ JBIG2HuffmanDecoder();
+ ~JBIG2HuffmanDecoder();
+ void setStream(Stream *strA) { str = strA; }
+
+ void reset();
+
+ // Returns false for OOB, otherwise sets *<x> and returns true.
+ GBool decodeInt(int *x, JBIG2HuffmanTable *table);
+
+ Guint readBits(Guint n);
+ Guint readBit();
+
+ // Sort the table by prefix length and assign prefix values.
+ void buildTable(JBIG2HuffmanTable *table, Guint len);
+
+private:
+
+ Stream *str;
+ Guint buf;
+ Guint bufLen;
+};
+
+JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
+ str = NULL;
+ reset();
+}
+
+JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
+}
+
+void JBIG2HuffmanDecoder::reset() {
+ buf = 0;
+ bufLen = 0;
+}
+
+//~ optimize this
+GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
+ Guint i, len, prefix;
+
+ i = 0;
+ len = 0;
+ prefix = 0;
+ while (table[i].rangeLen != jbig2HuffmanEOT) {
+ while (len < table[i].prefixLen) {
+ prefix = (prefix << 1) | readBit();
+ ++len;
+ }
+ if (prefix == table[i].prefix) {
+ if (table[i].rangeLen == jbig2HuffmanOOB) {
+ return gFalse;
+ }
+ if (table[i].rangeLen == jbig2HuffmanLOW) {
+ *x = table[i].val - readBits(32);
+ } else if (table[i].rangeLen > 0) {
+ *x = table[i].val + readBits(table[i].rangeLen);
+ } else {
+ *x = table[i].val;
+ }
+ return gTrue;
+ }
+ ++i;
+ }
+ return gFalse;
+}
+
+Guint JBIG2HuffmanDecoder::readBits(Guint n) {
+ Guint x, mask, nLeft;
+
+ mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
+ if (bufLen >= n) {
+ x = (buf >> (bufLen - n)) & mask;
+ bufLen -= n;
+ } else {
+ x = buf & ((1 << bufLen) - 1);
+ nLeft = n - bufLen;
+ bufLen = 0;
+ while (nLeft >= 8) {
+ x = (x << 8) | (str->getChar() & 0xff);
+ nLeft -= 8;
+ }
+ if (nLeft > 0) {
+ buf = str->getChar();
+ bufLen = 8 - nLeft;
+ x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
+ }
+ }
+ return x;
+}
+
+Guint JBIG2HuffmanDecoder::readBit() {
+ if (bufLen == 0) {
+ buf = str->getChar();
+ bufLen = 8;
+ }
+ --bufLen;
+ return (buf >> bufLen) & 1;
+}
+
+void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
+ Guint i, j, k, prefix;
+ JBIG2HuffmanTable tab;
+
+ // stable selection sort:
+ // - entries with prefixLen > 0, in ascending prefixLen order
+ // - entry with prefixLen = 0, rangeLen = EOT
+ // - all other entries with prefixLen = 0
+ // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
+ for (i = 0; i < len; ++i) {
+ for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
+ if (j == len) {
+ break;
+ }
+ for (k = j + 1; k < len; ++k) {
+ if (table[k].prefixLen > 0 &&
+ table[k].prefixLen < table[j].prefixLen) {
+ j = k;
+ }
+ }
+ if (j != i) {
+ tab = table[j];
+ for (k = j; k > i; --k) {
+ table[k] = table[k - 1];
+ }
+ table[i] = tab;
+ }
+ }
+ table[i] = table[len];
+
+ // assign prefixes
+ i = 0;
+ prefix = 0;
+ table[i++].prefix = prefix++;
+ for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
+ prefix <<= table[i].prefixLen - table[i-1].prefixLen;
+ table[i].prefix = prefix++;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2MMRDecoder
+//------------------------------------------------------------------------
+
+class JBIG2MMRDecoder {
+public:
+
+ JBIG2MMRDecoder();
+ ~JBIG2MMRDecoder();
+ void setStream(Stream *strA) { str = strA; }
+ void reset();
+ int get2DCode();
+ int getBlackCode();
+ int getWhiteCode();
+ Guint get24Bits();
+ void skipTo(Guint length);
+
+private:
+
+ Stream *str;
+ Guint buf;
+ Guint bufLen;
+ Guint nBytesRead;
+};
+
+JBIG2MMRDecoder::JBIG2MMRDecoder() {
+ str = NULL;
+ reset();
+}
+
+JBIG2MMRDecoder::~JBIG2MMRDecoder() {
+}
+
+void JBIG2MMRDecoder::reset() {
+ buf = 0;
+ bufLen = 0;
+ nBytesRead = 0;
+}
+
+int JBIG2MMRDecoder::get2DCode() {
+ CCITTCode *p;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ p = &twoDimTab1[(buf >> 1) & 0x7f];
+ } else if (bufLen == 8) {
+ p = &twoDimTab1[(buf >> 1) & 0x7f];
+ } else {
+ p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
+ if (p->bits < 0 || p->bits > (int)bufLen) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
+ }
+ }
+ if (p->bits < 0) {
+ error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
+ return 0;
+ }
+ bufLen -= p->bits;
+ return p->n;
+}
+
+int JBIG2MMRDecoder::getWhiteCode() {
+ CCITTCode *p;
+ Guint code;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ }
+ while (1) {
+ if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
+ if (bufLen <= 12) {
+ code = buf << (12 - bufLen);
+ } else {
+ code = buf >> (bufLen - 12);
+ }
+ p = &whiteTab1[code & 0x1f];
+ } else {
+ if (bufLen <= 9) {
+ code = buf << (9 - bufLen);
+ } else {
+ code = buf >> (bufLen - 9);
+ }
+ p = &whiteTab2[code & 0x1ff];
+ }
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
+ bufLen -= p->bits;
+ return p->n;
+ }
+ if (bufLen >= 12) {
+ break;
+ }
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ error(str->getPos(), "Bad white code in JBIG2 MMR stream");
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ --bufLen;
+ return 1;
+}
+
+int JBIG2MMRDecoder::getBlackCode() {
+ CCITTCode *p;
+ Guint code;
+
+ if (bufLen == 0) {
+ buf = str->getChar() & 0xff;
+ bufLen = 8;
+ ++nBytesRead;
+ }
+ while (1) {
+ if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
+ if (bufLen <= 13) {
+ code = buf << (13 - bufLen);
+ } else {
+ code = buf >> (bufLen - 13);
+ }
+ p = &blackTab1[code & 0x7f];
+ } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
+ if (bufLen <= 12) {
+ code = buf << (12 - bufLen);
+ } else {
+ code = buf >> (bufLen - 12);
+ }
+ p = &blackTab2[(code & 0xff) - 64];
+ } else {
+ if (bufLen <= 6) {
+ code = buf << (6 - bufLen);
+ } else {
+ code = buf >> (bufLen - 6);
+ }
+ p = &blackTab3[code & 0x3f];
+ }
+ if (p->bits > 0 && p->bits <= (int)bufLen) {
+ bufLen -= p->bits;
+ return p->n;
+ }
+ if (bufLen >= 13) {
+ break;
+ }
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ error(str->getPos(), "Bad black code in JBIG2 MMR stream");
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ --bufLen;
+ return 1;
+}
+
+Guint JBIG2MMRDecoder::get24Bits() {
+ while (bufLen < 24) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bufLen += 8;
+ ++nBytesRead;
+ }
+ return (buf >> (bufLen - 24)) & 0xffffff;
+}
+
+void JBIG2MMRDecoder::skipTo(Guint length) {
+ while (nBytesRead < length) {
+ str->getChar();
+ ++nBytesRead;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2Segment
+//------------------------------------------------------------------------
+
+enum JBIG2SegmentType {
+ jbig2SegBitmap,
+ jbig2SegSymbolDict,
+ jbig2SegPatternDict,
+ jbig2SegCodeTable
+};
+
+class JBIG2Segment {
+public:
+
+ JBIG2Segment(Guint segNumA) { segNum = segNumA; }
+ virtual ~JBIG2Segment() {}
+ void setSegNum(Guint segNumA) { segNum = segNumA; }
+ Guint getSegNum() { return segNum; }
+ virtual JBIG2SegmentType getType() = 0;
+
+private:
+
+ Guint segNum;
+};
+
+//------------------------------------------------------------------------
+// JBIG2Bitmap
+//------------------------------------------------------------------------
+
+struct JBIG2BitmapPtr {
+ Guchar *p;
+ int shift;
+ int x;
+};
+
+class JBIG2Bitmap: public JBIG2Segment {
+public:
+
+ JBIG2Bitmap(Guint segNumA, int wA, int hA);
+ virtual ~JBIG2Bitmap();
+ virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
+ JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
+ JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
+ void expand(int newH, Guint pixel);
+ void clearToZero();
+ void clearToOne();
+ int getWidth() { return w; }
+ int getHeight() { return h; }
+ int getPixel(int x, int y)
+ { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
+ (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
+ void setPixel(int x, int y)
+ { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
+ void clearPixel(int x, int y)
+ { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
+ void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
+ int nextPixel(JBIG2BitmapPtr *ptr);
+ void duplicateRow(int yDest, int ySrc);
+ void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
+ Guchar *getDataPtr() { return data; }
+ int getDataSize() { return h * line; }
+
+private:
+
+ JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
+
+ int w, h, line;
+ Guchar *data;
+};
+
+JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
+ JBIG2Segment(segNumA)
+{
+ w = wA;
+ h = hA;
+ line = (wA + 7) >> 3;
+ data = (Guchar *)gmalloc(h * line);
+}
+
+JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
+ JBIG2Segment(segNumA)
+{
+ w = bitmap->w;
+ h = bitmap->h;
+ line = bitmap->line;
+ data = (Guchar *)gmalloc(h * line);
+ memcpy(data, bitmap->data, h * line);
+}
+
+JBIG2Bitmap::~JBIG2Bitmap() {
+ gfree(data);
+}
+
+//~ optimize this
+JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
+ JBIG2Bitmap *slice;
+ Guint xx, yy;
+
+ slice = new JBIG2Bitmap(0, wA, hA);
+ slice->clearToZero();
+ for (yy = 0; yy < hA; ++yy) {
+ for (xx = 0; xx < wA; ++xx) {
+ if (getPixel(x + xx, y + yy)) {
+ slice->setPixel(xx, yy);
+ }
+ }
+ }
+ return slice;
+}
+
+void JBIG2Bitmap::expand(int newH, Guint pixel) {
+ if (newH <= h) {
+ return;
+ }
+ data = (Guchar *)grealloc(data, newH * line);
+ if (pixel) {
+ memset(data + h * line, 0xff, (newH - h) * line);
+ } else {
+ memset(data + h * line, 0x00, (newH - h) * line);
+ }
+ h = newH;
+}
+
+void JBIG2Bitmap::clearToZero() {
+ memset(data, 0, h * line);
+}
+
+void JBIG2Bitmap::clearToOne() {
+ memset(data, 0xff, h * line);
+}
+
+inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
+ if (y < 0 || y >= h || x >= w) {
+ ptr->p = NULL;
+ } else if (x < 0) {
+ ptr->p = &data[y * line];
+ ptr->shift = 7;
+ ptr->x = x;
+ } else {
+ ptr->p = &data[y * line + (x >> 3)];
+ ptr->shift = 7 - (x & 7);
+ ptr->x = x;
+ }
+}
+
+inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
+ int pix;
+
+ if (!ptr->p) {
+ pix = 0;
+ } else if (ptr->x < 0) {
+ ++ptr->x;
+ pix = 0;
+ } else {
+ pix = (*ptr->p >> ptr->shift) & 1;
+ if (++ptr->x == w) {
+ ptr->p = NULL;
+ } else if (ptr->shift == 0) {
+ ++ptr->p;
+ ptr->shift = 7;
+ } else {
+ --ptr->shift;
+ }
+ }
+ return pix;
+}
+
+void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
+ memcpy(data + yDest * line, data + ySrc * line, line);
+}
+
+void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
+ Guint combOp) {
+ int x0, x1, y0, y1, xx, yy;
+ Guchar *srcPtr, *destPtr;
+ Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
+ GBool oneByte;
+
+ if (y < 0) {
+ y0 = -y;
+ } else {
+ y0 = 0;
+ }
+ if (y + bitmap->h > h) {
+ y1 = h - y;
+ } else {
+ y1 = bitmap->h;
+ }
+ if (y0 >= y1) {
+ return;
+ }
+
+ if (x >= 0) {
+ x0 = x & ~7;
+ } else {
+ x0 = 0;
+ }
+ x1 = x + bitmap->w;
+ if (x1 > w) {
+ x1 = w;
+ }
+ if (x0 >= x1) {
+ return;
+ }
+
+ s1 = x & 7;
+ s2 = 8 - s1;
+ m1 = 0xff >> (x1 & 7);
+ m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
+ m3 = (0xff >> s1) & m2;
+
+ oneByte = x0 == ((x1 - 1) & ~7);
+
+ for (yy = y0; yy < y1; ++yy) {
+
+ // one byte per line -- need to mask both left and right side
+ if (oneByte) {
+ if (x >= 0) {
+ destPtr = data + (y + yy) * line + (x >> 3);
+ srcPtr = bitmap->data + yy * bitmap->line;
+ dest = *destPtr;
+ src1 = *srcPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= (src1 >> s1) & m2;
+ break;
+ case 1: // and
+ dest &= ((0xff00 | src1) >> s1) | m1;
+ break;
+ case 2: // xor
+ dest ^= (src1 >> s1) & m2;
+ break;
+ case 3: // xnor
+ dest ^= ((src1 ^ 0xff) >> s1) & m2;
+ break;
+ case 4: // replace
+ dest = (dest & ~m3) | ((src1 >> s1) & m3);
+ break;
+ }
+ *destPtr = dest;
+ } else {
+ destPtr = data + (y + yy) * line;
+ srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
+ dest = *destPtr;
+ src1 = *srcPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= src1 & m2;
+ break;
+ case 1: // and
+ dest &= src1 | m1;
+ break;
+ case 2: // xor
+ dest ^= src1 & m2;
+ break;
+ case 3: // xnor
+ dest ^= (src1 ^ 0xff) & m2;
+ break;
+ case 4: // replace
+ dest = (src1 & m2) | (dest & m1);
+ break;
+ }
+ *destPtr = dest;
+ }
+
+ // multiple bytes per line -- need to mask left side of left-most
+ // byte and right side of right-most byte
+ } else {
+
+ // left-most byte
+ if (x >= 0) {
+ destPtr = data + (y + yy) * line + (x >> 3);
+ srcPtr = bitmap->data + yy * bitmap->line;
+ src1 = *srcPtr++;
+ dest = *destPtr;
+ switch (combOp) {
+ case 0: // or
+ dest |= src1 >> s1;
+ break;
+ case 1: // and
+ dest &= (0xff00 | src1) >> s1;
+ break;
+ case 2: // xor
+ dest ^= src1 >> s1;
+ break;
+ case 3: // xnor
+ dest ^= (src1 ^ 0xff) >> s1;
+ break;
+ case 4: // replace
+ dest = (dest & (0xff << s2)) | (src1 >> s1);
+ break;
+ }
+ *destPtr++ = dest;
+ xx = x0 + 8;
+ } else {
+ destPtr = data + (y + yy) * line;
+ srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
+ src1 = *srcPtr++;
+ xx = x0;
+ }
+
+ // middle bytes
+ for (; xx < x1 - 8; xx += 8) {
+ dest = *destPtr;
+ src0 = src1;
+ src1 = *srcPtr++;
+ src = (((src0 << 8) | src1) >> s1) & 0xff;
+ switch (combOp) {
+ case 0: // or
+ dest |= src;
+ break;
+ case 1: // and
+ dest &= src;
+ break;
+ case 2: // xor
+ dest ^= src;
+ break;
+ case 3: // xnor
+ dest ^= src ^ 0xff;
+ break;
+ case 4: // replace
+ dest = src;
+ break;
+ }
+ *destPtr++ = dest;
+ }
+
+ // right-most byte
+ dest = *destPtr;
+ src0 = src1;
+ src1 = *srcPtr++;
+ src = (((src0 << 8) | src1) >> s1) & 0xff;
+ switch (combOp) {
+ case 0: // or
+ dest |= src & m2;
+ break;
+ case 1: // and
+ dest &= src | m1;
+ break;
+ case 2: // xor
+ dest ^= src & m2;
+ break;
+ case 3: // xnor
+ dest ^= (src ^ 0xff) & m2;
+ break;
+ case 4: // replace
+ dest = (src & m2) | (dest & m1);
+ break;
+ }
+ *destPtr = dest;
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2SymbolDict
+//------------------------------------------------------------------------
+
+class JBIG2SymbolDict: public JBIG2Segment {
+public:
+
+ JBIG2SymbolDict(Guint segNumA, Guint sizeA);
+ virtual ~JBIG2SymbolDict();
+ virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
+ Guint getSize() { return size; }
+ void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
+ JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
+ void setGenericRegionStats(JBIG2ArithmeticDecoderStats *stats)
+ { genericRegionStats = stats; }
+ void setRefinementRegionStats(JBIG2ArithmeticDecoderStats *stats)
+ { refinementRegionStats = stats; }
+ JBIG2ArithmeticDecoderStats *getGenericRegionStats()
+ { return genericRegionStats; }
+ JBIG2ArithmeticDecoderStats *getRefinementRegionStats()
+ { return refinementRegionStats; }
+
+private:
+
+ Guint size;
+ JBIG2Bitmap **bitmaps;
+ JBIG2ArithmeticDecoderStats *genericRegionStats;
+ JBIG2ArithmeticDecoderStats *refinementRegionStats;
+};
+
+JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
+ JBIG2Segment(segNumA)
+{
+ size = sizeA;
+ bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
+ genericRegionStats = NULL;
+ refinementRegionStats = NULL;
+}
+
+JBIG2SymbolDict::~JBIG2SymbolDict() {
+ Guint i;
+
+ for (i = 0; i < size; ++i) {
+ delete bitmaps[i];
+ }
+ gfree(bitmaps);
+ if (genericRegionStats) {
+ delete genericRegionStats;
+ }
+ if (refinementRegionStats) {
+ delete refinementRegionStats;
+ }
+}
+
+//------------------------------------------------------------------------
+// JBIG2PatternDict
+//------------------------------------------------------------------------
+
+class JBIG2PatternDict: public JBIG2Segment {
+public:
+
+ JBIG2PatternDict(Guint segNumA, Guint sizeA);
+ virtual ~JBIG2PatternDict();
+ virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
+ Guint getSize() { return size; }
+ void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
+ JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
+
+private:
+
+ Guint size;
+ JBIG2Bitmap **bitmaps;
+};
+
+JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
+ JBIG2Segment(segNumA)
+{
+ size = sizeA;
+ bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
+}
+
+JBIG2PatternDict::~JBIG2PatternDict() {
+ Guint i;
+
+ for (i = 0; i < size; ++i) {
+ delete bitmaps[i];
+ }
+ gfree(bitmaps);
+}
+
+//------------------------------------------------------------------------
+// JBIG2CodeTable
+//------------------------------------------------------------------------
+
+class JBIG2CodeTable: public JBIG2Segment {
+public:
+
+ JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
+ virtual ~JBIG2CodeTable();
+ virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
+ JBIG2HuffmanTable *getHuffTable() { return table; }
+
+private:
+
+ JBIG2HuffmanTable *table;
+};
+
+JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
+ JBIG2Segment(segNumA)
+{
+ table = tableA;
+}
+
+JBIG2CodeTable::~JBIG2CodeTable() {
+ gfree(table);
+}
+
+//------------------------------------------------------------------------
+// JBIG2Stream
+//------------------------------------------------------------------------
+
+JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
+ FilterStream(strA)
+{
+ pageBitmap = NULL;
+
+ arithDecoder = new JBIG2ArithmeticDecoder();
+ genericRegionStats = new JBIG2ArithmeticDecoderStats(1);
+ refinementRegionStats = new JBIG2ArithmeticDecoderStats(1);
+ iadhStats = new JBIG2ArithmeticDecoderStats(9);
+ iadwStats = new JBIG2ArithmeticDecoderStats(9);
+ iaexStats = new JBIG2ArithmeticDecoderStats(9);
+ iaaiStats = new JBIG2ArithmeticDecoderStats(9);
+ iadtStats = new JBIG2ArithmeticDecoderStats(9);
+ iaitStats = new JBIG2ArithmeticDecoderStats(9);
+ iafsStats = new JBIG2ArithmeticDecoderStats(9);
+ iadsStats = new JBIG2ArithmeticDecoderStats(9);
+ iardxStats = new JBIG2ArithmeticDecoderStats(9);
+ iardyStats = new JBIG2ArithmeticDecoderStats(9);
+ iardwStats = new JBIG2ArithmeticDecoderStats(9);
+ iardhStats = new JBIG2ArithmeticDecoderStats(9);
+ iariStats = new JBIG2ArithmeticDecoderStats(9);
+ iaidStats = new JBIG2ArithmeticDecoderStats(1);
+ huffDecoder = new JBIG2HuffmanDecoder();
+ mmrDecoder = new JBIG2MMRDecoder();
+
+ segments = globalSegments = new GList();
+ if (globalsStream->isStream()) {
+ curStr = globalsStream->getStream();
+ curStr->reset();
+ arithDecoder->setStream(curStr);
+ huffDecoder->setStream(curStr);
+ mmrDecoder->setStream(curStr);
+ readSegments();
+ }
+
+ segments = NULL;
+ curStr = NULL;
+ dataPtr = dataEnd = NULL;
+}
+
+JBIG2Stream::~JBIG2Stream() {
+ delete arithDecoder;
+ delete genericRegionStats;
+ delete refinementRegionStats;
+ delete iadhStats;
+ delete iadwStats;
+ delete iaexStats;
+ delete iaaiStats;
+ delete iadtStats;
+ delete iaitStats;
+ delete iafsStats;
+ delete iadsStats;
+ delete iardxStats;
+ delete iardyStats;
+ delete iardwStats;
+ delete iardhStats;
+ delete iariStats;
+ delete iaidStats;
+ delete huffDecoder;
+ delete mmrDecoder;
+ if (pageBitmap) {
+ delete pageBitmap;
+ }
+ if (segments) {
+ deleteGList(segments, JBIG2Segment);
+ }
+ if (globalSegments) {
+ deleteGList(globalSegments, JBIG2Segment);
+ }
+ delete str;
+}
+
+void JBIG2Stream::reset() {
+ if (pageBitmap) {
+ delete pageBitmap;
+ pageBitmap = NULL;
+ }
+ if (segments) {
+ deleteGList(segments, JBIG2Segment);
+ }
+ segments = new GList();
+
+ curStr = str;
+ curStr->reset();
+ arithDecoder->setStream(curStr);
+ huffDecoder->setStream(curStr);
+ mmrDecoder->setStream(curStr);
+ readSegments();
+
+ if (pageBitmap) {
+ dataPtr = pageBitmap->getDataPtr();
+ dataEnd = dataPtr + pageBitmap->getDataSize();
+ } else {
+ dataPtr = NULL;
+ }
+}
+
+int JBIG2Stream::getChar() {
+ if (dataPtr && dataPtr < dataEnd) {
+ return (*dataPtr++ ^ 0xff) & 0xff;
+ }
+ return EOF;
+}
+
+int JBIG2Stream::lookChar() {
+ if (dataPtr && dataPtr < dataEnd) {
+ return (*dataPtr ^ 0xff) & 0xff;
+ }
+ return EOF;
+}
+
+GString *JBIG2Stream::getPSFilter(const char *indent) {
+ return NULL;
+}
+
+GBool JBIG2Stream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+void JBIG2Stream::readSegments() {
+ Guint segNum, segFlags, segType, page, segLength;
+ Guint refFlags, nRefSegs;
+ Guint *refSegs;
+ int c1, c2, c3;
+ Guint i;
+
+ while (readULong(&segNum)) {
+
+ // segment header flags
+ if (!readUByte(&segFlags)) {
+ goto eofError1;
+ }
+ segType = segFlags & 0x3f;
+
+ // referred-to segment count and retention flags
+ if (!readUByte(&refFlags)) {
+ goto eofError1;
+ }
+ nRefSegs = refFlags >> 5;
+ if (nRefSegs == 7) {
+ if ((c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ goto eofError1;
+ }
+ refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
+ nRefSegs = refFlags & 0x1fffffff;
+ for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
+ c1 = curStr->getChar();
+ }
+ }
+
+ // referred-to segment numbers
+ refSegs = (Guint *)gmalloc(nRefSegs * sizeof(Guint));
+ if (segNum <= 256) {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readUByte(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ } else if (segNum <= 65536) {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readUWord(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ } else {
+ for (i = 0; i < nRefSegs; ++i) {
+ if (!readULong(&refSegs[i])) {
+ goto eofError2;
+ }
+ }
+ }
+
+ // segment page association
+ if (segFlags & 0x40) {
+ if (!readULong(&page)) {
+ goto eofError2;
+ }
+ } else {
+ if (!readUByte(&page)) {
+ goto eofError2;
+ }
+ }
+
+ // segment data length
+ if (!readULong(&segLength)) {
+ goto eofError2;
+ }
+
+ // read the segment data
+ switch (segType) {
+ case 0:
+ readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs);
+ break;
+ case 4:
+ readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
+ break;
+ case 6:
+ readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
+ break;
+ case 7:
+ readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
+ break;
+ case 16:
+ readPatternDictSeg(segNum, segLength);
+ break;
+ case 20:
+ readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 22:
+ readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 23:
+ readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 36:
+ readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
+ break;
+ case 38:
+ readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
+ break;
+ case 39:
+ readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
+ break;
+ case 40:
+ readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 42:
+ readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 43:
+ readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
+ refSegs, nRefSegs);
+ break;
+ case 48:
+ readPageInfoSeg(segLength);
+ break;
+ case 50:
+ readEndOfStripeSeg(segLength);
+ break;
+ case 52:
+ readProfilesSeg(segLength);
+ break;
+ case 53:
+ readCodeTableSeg(segNum, segLength);
+ break;
+ case 62:
+ readExtensionSeg(segLength);
+ break;
+ default:
+ error(getPos(), "Unknown segment type in JBIG2 stream");
+ for (i = 0; i < segLength; ++i) {
+ if ((c1 = curStr->getChar()) == EOF) {
+ goto eofError2;
+ }
+ }
+ break;
+ }
+
+ gfree(refSegs);
+ }
+
+ return;
+
+ eofError2:
+ gfree(refSegs);
+ eofError1:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2SymbolDict *symbolDict;
+ JBIG2HuffmanTable *huffDHTable, *huffDWTable;
+ JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
+ JBIG2Segment *seg;
+ GList *codeTables;
+ JBIG2SymbolDict *inputSymbolDict;
+ Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
+ Guint huffDH, huffDW, huffBMSize, huffAggInst;
+ Guint contextUsed, contextRetained;
+ int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
+ Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
+ JBIG2Bitmap **bitmaps;
+ JBIG2Bitmap *collBitmap, *refBitmap;
+ Guint *symWidths;
+ Guint symHeight, symWidth, totalWidth, x, symID;
+ int dh, dw, refAggNum, refDX, refDY, bmSize;
+ GBool ex;
+ int run, cnt;
+ Guint i, j, k;
+ Guchar *p;
+
+ // symbol dictionary flags
+ if (!readUWord(&flags)) {
+ goto eofError;
+ }
+ sdTemplate = (flags >> 10) & 3;
+ sdrTemplate = (flags >> 12) & 1;
+ huff = flags & 1;
+ refAgg = (flags >> 1) & 1;
+ huffDH = (flags >> 2) & 3;
+ huffDW = (flags >> 4) & 3;
+ huffBMSize = (flags >> 6) & 1;
+ huffAggInst = (flags >> 7) & 1;
+ contextUsed = (flags >> 8) & 1;
+ contextRetained = (flags >> 9) & 1;
+
+ // symbol dictionary AT flags
+ if (!huff) {
+ if (sdTemplate == 0) {
+ if (!readByte(&sdATX[0]) ||
+ !readByte(&sdATY[0]) ||
+ !readByte(&sdATX[1]) ||
+ !readByte(&sdATY[1]) ||
+ !readByte(&sdATX[2]) ||
+ !readByte(&sdATY[2]) ||
+ !readByte(&sdATX[3]) ||
+ !readByte(&sdATY[3])) {
+ goto eofError;
+ }
+ } else {
+ if (!readByte(&sdATX[0]) ||
+ !readByte(&sdATY[0])) {
+ goto eofError;
+ }
+ }
+ }
+
+ // symbol dictionary refinement AT flags
+ if (refAgg && !sdrTemplate) {
+ if (!readByte(&sdrATX[0]) ||
+ !readByte(&sdrATY[0]) ||
+ !readByte(&sdrATX[1]) ||
+ !readByte(&sdrATY[1])) {
+ goto eofError;
+ }
+ }
+
+ // SDNUMEXSYMS and SDNUMNEWSYMS
+ if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
+ goto eofError;
+ }
+
+ // get referenced segments: input symbol dictionaries and code tables
+ codeTables = new GList();
+ numInputSyms = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
+ } else if (seg->getType() == jbig2SegCodeTable) {
+ codeTables->append(seg);
+ }
+ }
+
+ // compute symbol code length
+ symCodeLen = 0;
+ i = 1;
+ while (i < numInputSyms + numNewSyms) {
+ ++symCodeLen;
+ i <<= 1;
+ }
+
+ // get the input symbol bitmaps
+ bitmaps = (JBIG2Bitmap **)gmalloc((numInputSyms + numNewSyms) *
+ sizeof(JBIG2Bitmap *));
+ k = 0;
+ inputSymbolDict = NULL;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ inputSymbolDict = (JBIG2SymbolDict *)seg;
+ for (j = 0; j < inputSymbolDict->getSize(); ++j) {
+ bitmaps[k++] = inputSymbolDict->getBitmap(j);
+ }
+ }
+ }
+
+ // get the Huffman tables
+ huffDHTable = huffDWTable = NULL; // make gcc happy
+ huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
+ i = 0;
+ if (huff) {
+ if (huffDH == 0) {
+ huffDHTable = huffTableD;
+ } else if (huffDH == 1) {
+ huffDHTable = huffTableE;
+ } else {
+ huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDW == 0) {
+ huffDWTable = huffTableB;
+ } else if (huffDW == 1) {
+ huffDWTable = huffTableC;
+ } else {
+ huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffBMSize == 0) {
+ huffBMSizeTable = huffTableA;
+ } else {
+ huffBMSizeTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffAggInst == 0) {
+ huffAggInstTable = huffTableA;
+ } else {
+ huffAggInstTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ }
+ delete codeTables;
+
+ // set up the Huffman decoder
+ if (huff) {
+ huffDecoder->reset();
+
+ // set up the arithmetic decoder
+ } else {
+ if (contextUsed && inputSymbolDict) {
+ resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
+ } else {
+ resetGenericStats(sdTemplate, NULL);
+ }
+ resetIntStats(symCodeLen);
+ arithDecoder->start();
+ }
+
+ // set up the arithmetic decoder for refinement/aggregation
+ if (refAgg) {
+ if (contextUsed && inputSymbolDict) {
+ resetRefinementStats(sdrTemplate,
+ inputSymbolDict->getRefinementRegionStats());
+ } else {
+ resetRefinementStats(sdrTemplate, NULL);
+ }
+ }
+
+ // allocate symbol widths storage
+ symWidths = NULL;
+ if (huff && !refAgg) {
+ symWidths = (Guint *)gmalloc(numNewSyms * sizeof(Guint));
+ }
+
+ symHeight = 0;
+ i = 0;
+ while (i < numNewSyms) {
+
+ // read the height class delta height
+ if (huff) {
+ huffDecoder->decodeInt(&dh, huffDHTable);
+ } else {
+ arithDecoder->decodeInt(&dh, iadhStats);
+ }
+ symHeight += dh;
+ symWidth = 0;
+ totalWidth = 0;
+ j = i;
+
+ // read the symbols in this height class
+ while (1) {
+
+ // read the delta width
+ if (huff) {
+ if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&dw, iadwStats)) {
+ break;
+ }
+ }
+ symWidth += dw;
+
+ // using a collective bitmap, so don't read a bitmap here
+ if (huff && !refAgg) {
+ symWidths[i] = symWidth;
+ totalWidth += symWidth;
+
+ // refinement/aggregate coding
+ } else if (refAgg) {
+ if (huff) {
+ if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
+ break;
+ }
+ }
+#if 0 //~ This special case was added about a year before the final draft
+ //~ of the JBIG2 spec was released. I have encountered some old
+ //~ JBIG2 images that predate it.
+ if (0) {
+#else
+ if (refAggNum == 1) {
+#endif
+ if (huff) {
+ symID = huffDecoder->readBits(symCodeLen);
+ huffDecoder->decodeInt(&refDX, huffTableO);
+ huffDecoder->decodeInt(&refDY, huffTableO);
+ huffDecoder->decodeInt(&bmSize, huffTableA);
+ huffDecoder->reset();
+ arithDecoder->start();
+ } else {
+ symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
+ arithDecoder->decodeInt(&refDX, iardxStats);
+ arithDecoder->decodeInt(&refDY, iardyStats);
+ }
+ refBitmap = bitmaps[symID];
+ bitmaps[numInputSyms + i] =
+ readGenericRefinementRegion(symWidth, symHeight,
+ sdrTemplate, gFalse,
+ refBitmap, refDX, refDY,
+ sdrATX, sdrATY);
+ //~ do we need to use the bmSize value here (in Huffman mode)?
+ } else {
+ bitmaps[numInputSyms + i] =
+ readTextRegion(huff, gTrue, symWidth, symHeight,
+ refAggNum, 0, numInputSyms + i, NULL,
+ symCodeLen, bitmaps, 0, 0, 0, 1, 0,
+ huffTableF, huffTableH, huffTableK, huffTableO,
+ huffTableO, huffTableO, huffTableO, huffTableA,
+ sdrTemplate, sdrATX, sdrATY);
+ }
+
+ // non-ref/agg coding
+ } else {
+ bitmaps[numInputSyms + i] =
+ readGenericBitmap(gFalse, symWidth, symHeight,
+ sdTemplate, gFalse, gFalse, NULL,
+ sdATX, sdATY, 0);
+ }
+
+ ++i;
+ }
+
+ // read the collective bitmap
+ if (huff && !refAgg) {
+ huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
+ huffDecoder->reset();
+ if (bmSize == 0) {
+ collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
+ bmSize = symHeight * ((totalWidth + 7) >> 3);
+ p = collBitmap->getDataPtr();
+ for (k = 0; k < (Guint)bmSize; ++k) {
+ *p++ = curStr->getChar();
+ }
+ } else {
+ collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
+ 0, gFalse, gFalse, NULL, NULL, NULL,
+ bmSize);
+ }
+ x = 0;
+ for (; j < i; ++j) {
+ bitmaps[numInputSyms + j] =
+ collBitmap->getSlice(x, 0, symWidths[j], symHeight);
+ x += symWidths[j];
+ }
+ delete collBitmap;
+ }
+ }
+
+ // create the symbol dict object
+ symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
+
+ // exported symbol list
+ i = j = 0;
+ ex = gFalse;
+ while (i < numInputSyms + numNewSyms) {
+ if (huff) {
+ huffDecoder->decodeInt(&run, huffTableA);
+ } else {
+ arithDecoder->decodeInt(&run, iaexStats);
+ }
+ if (ex) {
+ for (cnt = 0; cnt < run; ++cnt) {
+ symbolDict->setBitmap(j++, bitmaps[i++]->copy());
+ }
+ } else {
+ i += run;
+ }
+ ex = !ex;
+ }
+
+ for (i = 0; i < numNewSyms; ++i) {
+ delete bitmaps[numInputSyms + i];
+ }
+ gfree(bitmaps);
+ if (symWidths) {
+ gfree(symWidths);
+ }
+
+ // save the arithmetic decoder stats
+ if (!huff && contextRetained) {
+ symbolDict->setGenericRegionStats(genericRegionStats->copy());
+ if (refAgg) {
+ symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
+ }
+ }
+
+ // store the new symbol dict
+ segments->append(symbolDict);
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2Bitmap *bitmap;
+ JBIG2HuffmanTable runLengthTab[36];
+ JBIG2HuffmanTable *symCodeTab;
+ JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
+ JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
+ JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
+ JBIG2Segment *seg;
+ GList *codeTables;
+ JBIG2SymbolDict *symbolDict;
+ JBIG2Bitmap **syms;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, huff, refine, logStrips, refCorner, transposed;
+ Guint combOp, defPixel, templ;
+ int sOffset;
+ Guint huffFlags, huffFS, huffDS, huffDT;
+ Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
+ Guint numInstances, numSyms, symCodeLen;
+ int atx[2], aty[2];
+ Guint i, k, kk;
+ int j;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the text region header
+ if (!readUWord(&flags)) {
+ goto eofError;
+ }
+ huff = flags & 1;
+ refine = (flags >> 1) & 1;
+ logStrips = (flags >> 2) & 3;
+ refCorner = (flags >> 4) & 3;
+ transposed = (flags >> 6) & 1;
+ combOp = (flags >> 7) & 3;
+ defPixel = (flags >> 9) & 1;
+ sOffset = (flags >> 10) & 0x1f;
+ if (sOffset & 0x10) {
+ sOffset |= -1 - 0x0f;
+ }
+ templ = (flags >> 15) & 1;
+ huffFS = huffDS = huffDT = 0; // make gcc happy
+ huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
+ if (huff) {
+ if (!readUWord(&huffFlags)) {
+ goto eofError;
+ }
+ huffFS = huffFlags & 3;
+ huffDS = (huffFlags >> 2) & 3;
+ huffDT = (huffFlags >> 4) & 3;
+ huffRDW = (huffFlags >> 6) & 3;
+ huffRDH = (huffFlags >> 8) & 3;
+ huffRDX = (huffFlags >> 10) & 3;
+ huffRDY = (huffFlags >> 12) & 3;
+ huffRSize = (huffFlags >> 14) & 1;
+ }
+ if (refine && templ == 0) {
+ if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
+ !readByte(&atx[1]) || !readByte(&aty[1])) {
+ goto eofError;
+ }
+ }
+ if (!readULong(&numInstances)) {
+ goto eofError;
+ }
+
+ // get symbol dictionaries and tables
+ codeTables = new GList();
+ numSyms = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ numSyms += ((JBIG2SymbolDict *)seg)->getSize();
+ } else if (seg->getType() == jbig2SegCodeTable) {
+ codeTables->append(seg);
+ }
+ }
+ symCodeLen = 0;
+ i = 1;
+ while (i < numSyms) {
+ ++symCodeLen;
+ i <<= 1;
+ }
+
+ // get the symbol bitmaps
+ syms = (JBIG2Bitmap **)gmalloc(numSyms * sizeof(JBIG2Bitmap *));
+ kk = 0;
+ for (i = 0; i < nRefSegs; ++i) {
+ seg = findSegment(refSegs[i]);
+ if (seg->getType() == jbig2SegSymbolDict) {
+ symbolDict = (JBIG2SymbolDict *)seg;
+ for (k = 0; k < symbolDict->getSize(); ++k) {
+ syms[kk++] = symbolDict->getBitmap(k);
+ }
+ }
+ }
+
+ // get the Huffman tables
+ huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
+ huffRDWTable = huffRDHTable = NULL; // make gcc happy
+ huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
+ i = 0;
+ if (huff) {
+ if (huffFS == 0) {
+ huffFSTable = huffTableF;
+ } else if (huffFS == 1) {
+ huffFSTable = huffTableG;
+ } else {
+ huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDS == 0) {
+ huffDSTable = huffTableH;
+ } else if (huffDS == 1) {
+ huffDSTable = huffTableI;
+ } else if (huffDS == 2) {
+ huffDSTable = huffTableJ;
+ } else {
+ huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffDT == 0) {
+ huffDTTable = huffTableK;
+ } else if (huffDT == 1) {
+ huffDTTable = huffTableL;
+ } else if (huffDT == 2) {
+ huffDTTable = huffTableM;
+ } else {
+ huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDW == 0) {
+ huffRDWTable = huffTableN;
+ } else if (huffRDW == 1) {
+ huffRDWTable = huffTableO;
+ } else {
+ huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDH == 0) {
+ huffRDHTable = huffTableN;
+ } else if (huffRDH == 1) {
+ huffRDHTable = huffTableO;
+ } else {
+ huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDX == 0) {
+ huffRDXTable = huffTableN;
+ } else if (huffRDX == 1) {
+ huffRDXTable = huffTableO;
+ } else {
+ huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRDY == 0) {
+ huffRDYTable = huffTableN;
+ } else if (huffRDY == 1) {
+ huffRDYTable = huffTableO;
+ } else {
+ huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ if (huffRSize == 0) {
+ huffRSizeTable = huffTableA;
+ } else {
+ huffRSizeTable =
+ ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
+ }
+ }
+ delete codeTables;
+
+ // symbol ID Huffman decoding table
+ if (huff) {
+ huffDecoder->reset();
+ for (i = 0; i < 32; ++i) {
+ runLengthTab[i].val = i;
+ runLengthTab[i].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[i].rangeLen = 0;
+ }
+ runLengthTab[32].val = 0x103;
+ runLengthTab[32].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[32].rangeLen = 2;
+ runLengthTab[33].val = 0x203;
+ runLengthTab[33].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[33].rangeLen = 3;
+ runLengthTab[34].val = 0x20b;
+ runLengthTab[34].prefixLen = huffDecoder->readBits(4);
+ runLengthTab[34].rangeLen = 7;
+ runLengthTab[35].prefixLen = 0;
+ runLengthTab[35].rangeLen = jbig2HuffmanEOT;
+ huffDecoder->buildTable(runLengthTab, 35);
+ symCodeTab = (JBIG2HuffmanTable *)gmalloc((numSyms + 1) *
+ sizeof(JBIG2HuffmanTable));
+ for (i = 0; i < numSyms; ++i) {
+ symCodeTab[i].val = i;
+ symCodeTab[i].rangeLen = 0;
+ }
+ i = 0;
+ while (i < numSyms) {
+ huffDecoder->decodeInt(&j, runLengthTab);
+ if (j > 0x200) {
+ for (j -= 0x200; j && i < numSyms; --j) {
+ symCodeTab[i++].prefixLen = 0;
+ }
+ } else if (j > 0x100) {
+ for (j -= 0x100; j && i < numSyms; --j) {
+ symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
+ ++i;
+ }
+ } else {
+ symCodeTab[i++].prefixLen = j;
+ }
+ }
+ symCodeTab[numSyms].prefixLen = 0;
+ symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
+ huffDecoder->buildTable(symCodeTab, numSyms);
+ huffDecoder->reset();
+
+ // set up the arithmetic decoder
+ } else {
+ symCodeTab = NULL;
+ resetIntStats(symCodeLen);
+ arithDecoder->start();
+ }
+ if (refine) {
+ resetRefinementStats(templ, NULL);
+ }
+
+ bitmap = readTextRegion(huff, refine, w, h, numInstances,
+ logStrips, numSyms, symCodeTab, symCodeLen, syms,
+ defPixel, combOp, transposed, refCorner, sOffset,
+ huffFSTable, huffDSTable, huffDTTable,
+ huffRDWTable, huffRDHTable,
+ huffRDXTable, huffRDYTable, huffRSizeTable,
+ templ, atx, aty);
+
+ gfree(syms);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ // clean up the Huffman decoder
+ if (huff) {
+ gfree(symCodeTab);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
+ int w, int h,
+ Guint numInstances,
+ Guint logStrips,
+ int numSyms,
+ JBIG2HuffmanTable *symCodeTab,
+ Guint symCodeLen,
+ JBIG2Bitmap **syms,
+ Guint defPixel, Guint combOp,
+ Guint transposed, Guint refCorner,
+ int sOffset,
+ JBIG2HuffmanTable *huffFSTable,
+ JBIG2HuffmanTable *huffDSTable,
+ JBIG2HuffmanTable *huffDTTable,
+ JBIG2HuffmanTable *huffRDWTable,
+ JBIG2HuffmanTable *huffRDHTable,
+ JBIG2HuffmanTable *huffRDXTable,
+ JBIG2HuffmanTable *huffRDYTable,
+ JBIG2HuffmanTable *huffRSizeTable,
+ Guint templ,
+ int *atx, int *aty) {
+ JBIG2Bitmap *bitmap;
+ JBIG2Bitmap *symbolBitmap;
+ Guint strips;
+ int t, dt, tt, s, ds, sFirst, j;
+ int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
+ Guint symID, inst, bw, bh;
+
+ strips = 1 << logStrips;
+
+ // allocate the bitmap
+ bitmap = new JBIG2Bitmap(0, w, h);
+ if (defPixel) {
+ bitmap->clearToOne();
+ } else {
+ bitmap->clearToZero();
+ }
+
+ // decode initial T value
+ if (huff) {
+ huffDecoder->decodeInt(&t, huffDTTable);
+ } else {
+ arithDecoder->decodeInt(&t, iadtStats);
+ }
+ t *= -(int)strips;
+
+ inst = 0;
+ sFirst = 0;
+ while (inst < numInstances) {
+
+ // decode delta-T
+ if (huff) {
+ huffDecoder->decodeInt(&dt, huffDTTable);
+ } else {
+ arithDecoder->decodeInt(&dt, iadtStats);
+ }
+ t += dt * strips;
+
+ // first S value
+ if (huff) {
+ huffDecoder->decodeInt(&ds, huffFSTable);
+ } else {
+ arithDecoder->decodeInt(&ds, iafsStats);
+ }
+ sFirst += ds;
+ s = sFirst;
+
+ // read the instances
+ while (1) {
+
+ // T value
+ if (strips == 1) {
+ dt = 0;
+ } else if (huff) {
+ dt = huffDecoder->readBits(logStrips);
+ } else {
+ arithDecoder->decodeInt(&dt, iaitStats);
+ }
+ tt = t + dt;
+
+ // symbol ID
+ if (huff) {
+ if (symCodeTab) {
+ huffDecoder->decodeInt(&j, symCodeTab);
+ symID = (Guint)j;
+ } else {
+ symID = huffDecoder->readBits(symCodeLen);
+ }
+ } else {
+ symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
+ }
+
+ // get the symbol bitmap
+ symbolBitmap = NULL;
+ if (refine) {
+ if (huff) {
+ ri = (int)huffDecoder->readBit();
+ } else {
+ arithDecoder->decodeInt(&ri, iariStats);
+ }
+ } else {
+ ri = 0;
+ }
+ if (ri) {
+ if (huff) {
+ huffDecoder->decodeInt(&rdw, huffRDWTable);
+ huffDecoder->decodeInt(&rdh, huffRDHTable);
+ huffDecoder->decodeInt(&rdx, huffRDXTable);
+ huffDecoder->decodeInt(&rdy, huffRDYTable);
+ huffDecoder->decodeInt(&bmSize, huffRSizeTable);
+ huffDecoder->reset();
+ arithDecoder->start();
+ } else {
+ arithDecoder->decodeInt(&rdw, iardwStats);
+ arithDecoder->decodeInt(&rdh, iardhStats);
+ arithDecoder->decodeInt(&rdx, iardxStats);
+ arithDecoder->decodeInt(&rdy, iardyStats);
+ }
+ refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
+ refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
+
+ symbolBitmap =
+ readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
+ rdh + syms[symID]->getHeight(),
+ templ, gFalse, syms[symID],
+ refDX, refDY, atx, aty);
+ //~ do we need to use the bmSize value here (in Huffman mode)?
+ } else {
+ symbolBitmap = syms[symID];
+ }
+
+ // combine the symbol bitmap into the region bitmap
+ //~ something is wrong here - refCorner shouldn't degenerate into
+ //~ two cases
+ bw = symbolBitmap->getWidth() - 1;
+ bh = symbolBitmap->getHeight() - 1;
+ if (transposed) {
+ switch (refCorner) {
+ case 0: // bottom left
+ bitmap->combine(symbolBitmap, tt, s, combOp);
+ break;
+ case 1: // top left
+ bitmap->combine(symbolBitmap, tt, s, combOp);
+ break;
+ case 2: // bottom right
+ bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ break;
+ case 3: // top right
+ bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ break;
+ }
+ s += bh;
+ } else {
+ switch (refCorner) {
+ case 0: // bottom left
+ bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ break;
+ case 1: // top left
+ bitmap->combine(symbolBitmap, s, tt, combOp);
+ break;
+ case 2: // bottom right
+ bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ break;
+ case 3: // top right
+ bitmap->combine(symbolBitmap, s, tt, combOp);
+ break;
+ }
+ s += bw;
+ }
+ if (ri) {
+ delete symbolBitmap;
+ }
+
+ // next instance
+ ++inst;
+
+ // next S value
+ if (huff) {
+ if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
+ break;
+ }
+ } else {
+ if (!arithDecoder->decodeInt(&ds, iadsStats)) {
+ break;
+ }
+ }
+ s += sOffset + ds;
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
+ JBIG2PatternDict *patternDict;
+ JBIG2Bitmap *bitmap;
+ Guint flags, patternW, patternH, grayMax, templ, mmr;
+ int atx[4], aty[4];
+ Guint i, x;
+
+ // halftone dictionary flags, pattern width and height, max gray value
+ if (!readUByte(&flags) ||
+ !readUByte(&patternW) ||
+ !readUByte(&patternH) ||
+ !readULong(&grayMax)) {
+ goto eofError;
+ }
+ templ = (flags >> 1) & 3;
+ mmr = flags & 1;
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // read the bitmap
+ atx[0] = -(int)patternW; aty[0] = 0;
+ atx[1] = -3; aty[1] = -1;
+ atx[2] = 2; aty[2] = -2;
+ atx[3] = -2; aty[3] = -2;
+ bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
+ templ, gFalse, gFalse, NULL,
+ atx, aty, length - 7);
+
+ // create the pattern dict object
+ patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
+
+ // split up the bitmap
+ x = 0;
+ for (i = 0; i <= grayMax; ++i) {
+ patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
+ x += patternW;
+ }
+
+ // free memory
+ delete bitmap;
+
+ // store the new pattern dict
+ segments->append(patternDict);
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs) {
+ JBIG2Bitmap *bitmap;
+ JBIG2Segment *seg;
+ JBIG2PatternDict *patternDict;
+ JBIG2Bitmap *skipBitmap;
+ Guint *grayImg;
+ JBIG2Bitmap *grayBitmap;
+ JBIG2Bitmap *patternBitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, mmr, templ, enableSkip, combOp;
+ Guint gridW, gridH, stepX, stepY, patW, patH;
+ int atx[4], aty[4];
+ int gridX, gridY, xx, yy, bit, j;
+ Guint bpp, m, n, i;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the halftone region header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ mmr = flags & 1;
+ templ = (flags >> 1) & 3;
+ enableSkip = (flags >> 3) & 1;
+ combOp = (flags >> 4) & 7;
+ if (!readULong(&gridW) || !readULong(&gridH) ||
+ !readLong(&gridX) || !readLong(&gridY) ||
+ !readUWord(&stepX) || !readUWord(&stepY)) {
+ goto eofError;
+ }
+
+ // get pattern dictionary
+ if (nRefSegs != 1) {
+ error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ return;
+ }
+ seg = findSegment(refSegs[0]);
+ if (seg->getType() != jbig2SegPatternDict) {
+ error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
+ return;
+ }
+ patternDict = (JBIG2PatternDict *)seg;
+ bpp = 0;
+ i = 1;
+ while (i < patternDict->getSize()) {
+ ++bpp;
+ i <<= 1;
+ }
+ patW = patternDict->getBitmap(0)->getWidth();
+ patH = patternDict->getBitmap(0)->getHeight();
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // allocate the bitmap
+ bitmap = new JBIG2Bitmap(segNum, w, h);
+ if (flags & 0x80) { // HDEFPIXEL
+ bitmap->clearToOne();
+ } else {
+ bitmap->clearToZero();
+ }
+
+ // compute the skip bitmap
+ skipBitmap = NULL;
+ if (enableSkip) {
+ skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
+ skipBitmap->clearToZero();
+ for (m = 0; m < gridH; ++m) {
+ xx = gridX + m * stepY;
+ yy = gridY + m * stepX;
+ for (n = 0; n < gridW; ++n) {
+ if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
+ ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
+ skipBitmap->setPixel(n, m);
+ }
+ }
+ }
+ }
+
+ // read the gray-scale image
+ grayImg = (Guint *)gmalloc(gridW * gridH * sizeof(Guint));
+ memset(grayImg, 0, gridW * gridH * sizeof(Guint));
+ atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
+ atx[1] = -3; aty[1] = -1;
+ atx[2] = 2; aty[2] = -2;
+ atx[3] = -2; aty[3] = -2;
+ for (j = bpp - 1; j >= 0; --j) {
+ grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
+ enableSkip, skipBitmap, atx, aty, -1);
+ i = 0;
+ for (m = 0; m < gridH; ++m) {
+ for (n = 0; n < gridW; ++n) {
+ bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
+ grayImg[i] = (grayImg[i] << 1) | bit;
+ ++i;
+ }
+ }
+ delete grayBitmap;
+ }
+
+ // decode the image
+ i = 0;
+ for (m = 0; m < gridH; ++m) {
+ xx = gridX + m * stepY;
+ yy = gridY + m * stepX;
+ for (n = 0; n < gridW; ++n) {
+ if (!(enableSkip && skipBitmap->getPixel(n, m))) {
+ patternBitmap = patternDict->getBitmap(grayImg[i]);
+ bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
+ }
+ xx += stepX;
+ yy -= stepY;
+ ++i;
+ }
+ }
+
+ gfree(grayImg);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ segments->append(bitmap);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length) {
+ JBIG2Bitmap *bitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, mmr, templ, tpgdOn;
+ int atx[4], aty[4];
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the generic region segment header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ mmr = flags & 1;
+ templ = (flags >> 1) & 3;
+ tpgdOn = (flags >> 3) & 1;
+
+ // AT flags
+ if (!mmr) {
+ if (templ == 0) {
+ if (!readByte(&atx[0]) ||
+ !readByte(&aty[0]) ||
+ !readByte(&atx[1]) ||
+ !readByte(&aty[1]) ||
+ !readByte(&atx[2]) ||
+ !readByte(&aty[2]) ||
+ !readByte(&atx[3]) ||
+ !readByte(&aty[3])) {
+ goto eofError;
+ }
+ } else {
+ if (!readByte(&atx[0]) ||
+ !readByte(&aty[0])) {
+ goto eofError;
+ }
+ }
+ }
+
+ // set up the arithmetic decoder
+ if (!mmr) {
+ resetGenericStats(templ, NULL);
+ arithDecoder->start();
+ }
+
+ // read the bitmap
+ bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
+ NULL, atx, aty, mmr ? 0 : length - 18);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
+ int templ, GBool tpgdOn,
+ GBool useSkip, JBIG2Bitmap *skip,
+ int *atx, int *aty,
+ int mmrDataLength) {
+ JBIG2Bitmap *bitmap;
+ GBool ltp;
+ Guint ltpCX, cx, cx0, cx1, cx2;
+ JBIG2BitmapPtr cxPtr0, cxPtr1;
+ JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
+ int *refLine, *codingLine;
+ int code1, code2, code3;
+ int x, y, a0, pix, i, refI, codingI;
+
+ bitmap = new JBIG2Bitmap(0, w, h);
+ bitmap->clearToZero();
+
+ //----- MMR decode
+
+ if (mmr) {
+
+ mmrDecoder->reset();
+ refLine = (int *)gmalloc((w + 2) * sizeof(int));
+ codingLine = (int *)gmalloc((w + 2) * sizeof(int));
+ codingLine[0] = codingLine[1] = w;
+
+ for (y = 0; y < h; ++y) {
+
+ // copy coding line to ref line
+ for (i = 0; codingLine[i] < w; ++i) {
+ refLine[i] = codingLine[i];
+ }
+ refLine[i] = refLine[i + 1] = w;
+
+ // decode a line
+ refI = 0; // b1 = refLine[refI]
+ codingI = 0; // a1 = codingLine[codingI]
+ a0 = 0;
+ do {
+ code1 = mmrDecoder->get2DCode();
+ switch (code1) {
+ case twoDimPass:
+ if (refLine[refI] < w) {
+ a0 = refLine[refI + 1];
+ refI += 2;
+ }
+ break;
+ case twoDimHoriz:
+ if (codingI & 1) {
+ code1 = 0;
+ do {
+ code1 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ code2 = 0;
+ do {
+ code2 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ } else {
+ code1 = 0;
+ do {
+ code1 += code3 = mmrDecoder->getWhiteCode();
+ } while (code3 >= 64);
+ code2 = 0;
+ do {
+ code2 += code3 = mmrDecoder->getBlackCode();
+ } while (code3 >= 64);
+ }
+ if (code1 > 0 || code2 > 0) {
+ a0 = codingLine[codingI++] = a0 + code1;
+ a0 = codingLine[codingI++] = a0 + code2;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVert0:
+ a0 = codingLine[codingI++] = refLine[refI];
+ if (refLine[refI] < w) {
+ ++refI;
+ }
+ break;
+ case twoDimVertR1:
+ a0 = codingLine[codingI++] = refLine[refI] + 1;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertR2:
+ a0 = codingLine[codingI++] = refLine[refI] + 2;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertR3:
+ a0 = codingLine[codingI++] = refLine[refI] + 3;
+ if (refLine[refI] < w) {
+ ++refI;
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ }
+ break;
+ case twoDimVertL1:
+ a0 = codingLine[codingI++] = refLine[refI] - 1;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ case twoDimVertL2:
+ a0 = codingLine[codingI++] = refLine[refI] - 2;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ case twoDimVertL3:
+ a0 = codingLine[codingI++] = refLine[refI] - 3;
+ if (refI > 0) {
+ --refI;
+ } else {
+ ++refI;
+ }
+ while (refLine[refI] <= a0 && refLine[refI] < w) {
+ refI += 2;
+ }
+ break;
+ default:
+ error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
+ break;
+ }
+ } while (a0 < w);
+ codingLine[codingI++] = w;
+
+ // convert the run lengths to a bitmap line
+ i = 0;
+ while (codingLine[i] < w) {
+ for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
+ bitmap->setPixel(x, y);
+ }
+ i += 2;
+ }
+ }
+
+ if (mmrDataLength >= 0) {
+ mmrDecoder->skipTo(mmrDataLength);
+ } else {
+ if (mmrDecoder->get24Bits() != 0x001001) {
+ error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
+ }
+ }
+
+ gfree(refLine);
+ gfree(codingLine);
+
+ //----- arithmetic decode
+
+ } else {
+ // set up the typical row context
+ ltpCX = 0; // make gcc happy
+ if (tpgdOn) {
+ switch (templ) {
+ case 0:
+ ltpCX = 0x3953; // 001 11001 0101 0011
+ break;
+ case 1:
+ ltpCX = 0x079a; // 0011 11001 101 0
+ break;
+ case 2:
+ ltpCX = 0x0e3; // 001 1100 01 1
+ break;
+ case 3:
+ ltpCX = 0x18a; // 01100 0101 1
+ break;
+ }
+ }
+
+ ltp = 0;
+ cx = cx0 = cx1 = cx2 = 0; // make gcc happy
+ for (y = 0; y < h; ++y) {
+
+ // check for a "typical" (duplicate) row
+ if (tpgdOn) {
+ if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
+ ltp = !ltp;
+ }
+ if (ltp) {
+ bitmap->duplicateRow(y, y-1);
+ continue;
+ }
+ }
+
+ switch (templ) {
+ case 0:
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+ bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
+ bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
+ bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
+ (bitmap->nextPixel(&atPtr0) << 3) |
+ (bitmap->nextPixel(&atPtr1) << 2) |
+ (bitmap->nextPixel(&atPtr2) << 1) |
+ bitmap->nextPixel(&atPtr3);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
+ }
+ break;
+
+ case 1:
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x07;
+ }
+ break;
+
+ case 2:
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-2, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
+ cx2 = ((cx2 << 1) | pix) & 0x03;
+ }
+ break;
+
+ case 3:
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr1);
+ cx1 = bitmap->nextPixel(&cxPtr1);
+ cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
+ cx2 = 0;
+ bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
+
+ // decode the row
+ for (x = 0; x < w; ++x) {
+
+ // build the context
+ cx = (cx1 << 5) | (cx2 << 1) |
+ bitmap->nextPixel(&atPtr0);
+
+ // check for a skipped pixel
+ if (useSkip && skip->getPixel(x, y)) {
+ pix = 0;
+
+ // decode the pixel
+ } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+
+ // update the context
+ cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
+ cx2 = ((cx2 << 1) | pix) & 0x0f;
+ }
+ break;
+ }
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs,
+ Guint nRefSegs) {
+ JBIG2Bitmap *bitmap, *refBitmap;
+ Guint w, h, x, y, segInfoFlags, extCombOp;
+ Guint flags, templ, tpgrOn;
+ int atx[2], aty[2];
+ JBIG2Segment *seg;
+
+ // region segment info field
+ if (!readULong(&w) || !readULong(&h) ||
+ !readULong(&x) || !readULong(&y) ||
+ !readUByte(&segInfoFlags)) {
+ goto eofError;
+ }
+ extCombOp = segInfoFlags & 7;
+
+ // rest of the generic refinement region segment header
+ if (!readUByte(&flags)) {
+ goto eofError;
+ }
+ templ = flags & 1;
+ tpgrOn = (flags >> 1) & 1;
+
+ // AT flags
+ if (!templ) {
+ if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
+ !readByte(&atx[1]) || !readByte(&aty[1])) {
+ goto eofError;
+ }
+ }
+
+ // resize the page bitmap if needed
+ if (nRefSegs == 0 || imm) {
+ if (pageH == 0xffffffff && y + h > curPageH) {
+ pageBitmap->expand(y + h, pageDefPixel);
+ }
+ }
+
+ // get referenced bitmap
+ if (nRefSegs > 1) {
+ error(getPos(), "Bad reference in JBIG2 generic refinement segment");
+ return;
+ }
+ if (nRefSegs == 1) {
+ seg = findSegment(refSegs[0]);
+ if (seg->getType() != jbig2SegBitmap) {
+ error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
+ return;
+ }
+ refBitmap = (JBIG2Bitmap *)seg;
+ } else {
+ refBitmap = pageBitmap->getSlice(x, y, w, h);
+ }
+
+ // set up the arithmetic decoder
+ resetRefinementStats(templ, NULL);
+ arithDecoder->start();
+
+ // read
+ bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
+ refBitmap, 0, 0, atx, aty);
+
+ // combine the region bitmap into the page bitmap
+ if (imm) {
+ pageBitmap->combine(bitmap, x, y, extCombOp);
+ delete bitmap;
+
+ // store the region bitmap
+ } else {
+ bitmap->setSegNum(segNum);
+ segments->append(bitmap);
+ }
+
+ // delete the referenced bitmap
+ if (nRefSegs == 1) {
+ discardSegment(refSegs[0]);
+ } else {
+ delete refBitmap;
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
+ int templ, GBool tpgrOn,
+ JBIG2Bitmap *refBitmap,
+ int refDX, int refDY,
+ int *atx, int *aty) {
+ JBIG2Bitmap *bitmap;
+ GBool ltp;
+ Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
+ JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
+ JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
+ int x, y, pix;
+
+ bitmap = new JBIG2Bitmap(0, w, h);
+ bitmap->clearToZero();
+
+ // set up the typical row context
+ if (templ) {
+ ltpCX = 0x008;
+ } else {
+ ltpCX = 0x0010;
+ }
+
+ ltp = 0;
+ for (y = 0; y < h; ++y) {
+
+ if (templ) {
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(-1, y, &cxPtr1);
+ refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
+ cx3 = refBitmap->nextPixel(&cxPtr3);
+ cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
+ refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
+ cx4 = refBitmap->nextPixel(&cxPtr4);
+
+ // set up the typical prediction context
+ tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
+ if (tpgrOn) {
+ refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
+ tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
+ tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
+ tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ }
+
+ for (x = 0; x < w; ++x) {
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
+ cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
+ cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
+
+ if (tpgrOn) {
+ // update the typical predictor context
+ tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
+ tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
+ tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
+
+ // check for a "typical" pixel
+ if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
+ ltp = !ltp;
+ }
+ if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
+ bitmap->clearPixel(x, y);
+ continue;
+ } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
+ bitmap->setPixel(x, y);
+ continue;
+ }
+ }
+
+ // build the context
+ cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
+ (refBitmap->nextPixel(&cxPtr2) << 5) |
+ (cx3 << 2) | cx4;
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+ }
+
+ } else {
+
+ // set up the context
+ bitmap->getPixelPtr(0, y-1, &cxPtr0);
+ cx0 = bitmap->nextPixel(&cxPtr0);
+ bitmap->getPixelPtr(-1, y, &cxPtr1);
+ refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
+ cx2 = refBitmap->nextPixel(&cxPtr2);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
+ cx3 = refBitmap->nextPixel(&cxPtr3);
+ cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
+ cx4 = refBitmap->nextPixel(&cxPtr4);
+ cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
+ bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
+ refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
+
+ // set up the typical prediction context
+ tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
+ if (tpgrOn) {
+ refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
+ tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
+ refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
+ tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
+ refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
+ tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
+ }
+
+ for (x = 0; x < w; ++x) {
+
+ // update the context
+ cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
+ cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
+ cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
+ cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
+
+ if (tpgrOn) {
+ // update the typical predictor context
+ tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
+ tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
+ tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
+
+ // check for a "typical" pixel
+ if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
+ ltp = !ltp;
+ }
+ if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
+ bitmap->clearPixel(x, y);
+ continue;
+ } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
+ bitmap->setPixel(x, y);
+ continue;
+ }
+ }
+
+ // build the context
+ cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
+ (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
+ (bitmap->nextPixel(&cxPtr5) << 1) |
+ refBitmap->nextPixel(&cxPtr6);
+
+ // decode the pixel
+ if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
+ bitmap->setPixel(x, y);
+ }
+ }
+ }
+ }
+
+ return bitmap;
+}
+
+void JBIG2Stream::readPageInfoSeg(Guint length) {
+ Guint xRes, yRes, flags, striping;
+
+ if (!readULong(&pageW) || !readULong(&pageH) ||
+ !readULong(&xRes) || !readULong(&yRes) ||
+ !readUByte(&flags) || !readUWord(&striping)) {
+ goto eofError;
+ }
+ pageDefPixel = (flags >> 2) & 1;
+ defCombOp = (flags >> 3) & 3;
+
+ // allocate the page bitmap
+ if (pageH == 0xffffffff) {
+ curPageH = striping & 0x7fff;
+ } else {
+ curPageH = pageH;
+ }
+ pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
+
+ // default pixel value
+ if (pageDefPixel) {
+ pageBitmap->clearToOne();
+ } else {
+ pageBitmap->clearToZero();
+ }
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readEndOfStripeSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+void JBIG2Stream::readProfilesSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
+ JBIG2HuffmanTable *huffTab;
+ Guint flags, oob, prefixBits, rangeBits;
+ int lowVal, highVal, val;
+ Guint huffTabSize, i;
+
+ if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
+ goto eofError;
+ }
+ oob = flags & 1;
+ prefixBits = ((flags >> 1) & 7) + 1;
+ rangeBits = ((flags >> 4) & 7) + 1;
+
+ huffDecoder->reset();
+ huffTabSize = 8;
+ huffTab = (JBIG2HuffmanTable *)
+ gmalloc(huffTabSize * sizeof(JBIG2HuffmanTable));
+ i = 0;
+ val = lowVal;
+ while (val < highVal) {
+ if (i == huffTabSize) {
+ huffTabSize *= 2;
+ huffTab = (JBIG2HuffmanTable *)
+ grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
+ }
+ huffTab[i].val = val;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
+ val += 1 << huffTab[i].rangeLen;
+ ++i;
+ }
+ if (i + oob + 3 > huffTabSize) {
+ huffTabSize = i + oob + 3;
+ huffTab = (JBIG2HuffmanTable *)
+ grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
+ }
+ huffTab[i].val = lowVal - 1;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = jbig2HuffmanLOW;
+ ++i;
+ huffTab[i].val = highVal;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = 32;
+ ++i;
+ if (oob) {
+ huffTab[i].val = 0;
+ huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
+ huffTab[i].rangeLen = jbig2HuffmanOOB;
+ ++i;
+ }
+ huffTab[i].val = 0;
+ huffTab[i].prefixLen = 0;
+ huffTab[i].rangeLen = jbig2HuffmanEOT;
+ huffDecoder->buildTable(huffTab, i);
+
+ // create and store the new table segment
+ segments->append(new JBIG2CodeTable(segNum, huffTab));
+
+ return;
+
+ eofError:
+ error(getPos(), "Unexpected EOF in JBIG2 stream");
+}
+
+void JBIG2Stream::readExtensionSeg(Guint length) {
+ Guint i;
+
+ // skip the segment
+ for (i = 0; i < length; ++i) {
+ curStr->getChar();
+ }
+}
+
+JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
+ JBIG2Segment *seg;
+ int i;
+
+ for (i = 0; i < globalSegments->getLength(); ++i) {
+ seg = (JBIG2Segment *)globalSegments->get(i);
+ if (seg->getSegNum() == segNum) {
+ return seg;
+ }
+ }
+ for (i = 0; i < segments->getLength(); ++i) {
+ seg = (JBIG2Segment *)segments->get(i);
+ if (seg->getSegNum() == segNum) {
+ return seg;
+ }
+ }
+ return NULL;
+}
+
+void JBIG2Stream::discardSegment(Guint segNum) {
+ JBIG2Segment *seg;
+ int i;
+
+ for (i = 0; i < globalSegments->getLength(); ++i) {
+ seg = (JBIG2Segment *)globalSegments->get(i);
+ if (seg->getSegNum() == segNum) {
+ globalSegments->del(i);
+ return;
+ }
+ }
+ for (i = 0; i < segments->getLength(); ++i) {
+ seg = (JBIG2Segment *)segments->get(i);
+ if (seg->getSegNum() == segNum) {
+ segments->del(i);
+ return;
+ }
+ }
+}
+
+void JBIG2Stream::resetGenericStats(Guint templ,
+ JBIG2ArithmeticDecoderStats *prevStats) {
+ int size;
+
+ size = contextSize[templ];
+ if (prevStats && prevStats->getContextSize() == size) {
+ if (genericRegionStats->getContextSize() == size) {
+ genericRegionStats->copyFrom(prevStats);
+ } else {
+ delete genericRegionStats;
+ genericRegionStats = prevStats->copy();
+ }
+ } else {
+ if (genericRegionStats->getContextSize() == size) {
+ genericRegionStats->reset();
+ } else {
+ delete genericRegionStats;
+ genericRegionStats = new JBIG2ArithmeticDecoderStats(size);
+ }
+ }
+}
+
+void JBIG2Stream::resetRefinementStats(
+ Guint templ,
+ JBIG2ArithmeticDecoderStats *prevStats) {
+ int size;
+
+ size = refContextSize[templ];
+ if (prevStats && prevStats->getContextSize() == size) {
+ if (refinementRegionStats->getContextSize() == size) {
+ refinementRegionStats->copyFrom(prevStats);
+ } else {
+ delete refinementRegionStats;
+ refinementRegionStats = prevStats->copy();
+ }
+ } else {
+ if (refinementRegionStats->getContextSize() == size) {
+ refinementRegionStats->reset();
+ } else {
+ delete refinementRegionStats;
+ refinementRegionStats = new JBIG2ArithmeticDecoderStats(size);
+ }
+ }
+}
+
+void JBIG2Stream::resetIntStats(int symCodeLen) {
+ iadhStats->reset();
+ iadwStats->reset();
+ iaexStats->reset();
+ iaaiStats->reset();
+ iadtStats->reset();
+ iaitStats->reset();
+ iafsStats->reset();
+ iadsStats->reset();
+ iardxStats->reset();
+ iardyStats->reset();
+ iardwStats->reset();
+ iardhStats->reset();
+ iariStats->reset();
+ if (iaidStats->getContextSize() == symCodeLen + 1) {
+ iaidStats->reset();
+ } else {
+ delete iaidStats;
+ iaidStats = new JBIG2ArithmeticDecoderStats(symCodeLen + 1);
+ }
+}
+
+GBool JBIG2Stream::readUByte(Guint *x) {
+ int c0;
+
+ if ((c0 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)c0;
+ return gTrue;
+}
+
+GBool JBIG2Stream::readByte(int *x) {
+ int c0;
+
+ if ((c0 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = c0;
+ if (c0 & 0x80) {
+ *x |= -1 - 0xff;
+ }
+ return gTrue;
+}
+
+GBool JBIG2Stream::readUWord(Guint *x) {
+ int c0, c1;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 8) | c1);
+ return gTrue;
+}
+
+GBool JBIG2Stream::readULong(Guint *x) {
+ int c0, c1, c2, c3;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+ return gTrue;
+}
+
+GBool JBIG2Stream::readLong(int *x) {
+ int c0, c1, c2, c3;
+
+ if ((c0 = curStr->getChar()) == EOF ||
+ (c1 = curStr->getChar()) == EOF ||
+ (c2 = curStr->getChar()) == EOF ||
+ (c3 = curStr->getChar()) == EOF) {
+ return gFalse;
+ }
+ *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
+ if (c0 & 0x80) {
+ *x |= -1 - (int)0xffffffff;
+ }
+ return gTrue;
+}
diff --git a/pdftops/JBIG2Stream.h b/pdftops/JBIG2Stream.h
new file mode 100644
index 000000000..d4b389c39
--- /dev/null
+++ b/pdftops/JBIG2Stream.h
@@ -0,0 +1,143 @@
+//========================================================================
+//
+// JBIG2Stream.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef JBIG2STREAM_H
+#define JBIG2STREAM_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+#include "Stream.h"
+
+class GList;
+class JBIG2Segment;
+class JBIG2Bitmap;
+class JBIG2ArithmeticDecoder;
+class JBIG2ArithmeticDecoderStats;
+class JBIG2HuffmanDecoder;
+struct JBIG2HuffmanTable;
+class JBIG2MMRDecoder;
+
+//------------------------------------------------------------------------
+
+class JBIG2Stream: public FilterStream {
+public:
+
+ JBIG2Stream(Stream *strA, Object *globalsStream);
+ virtual ~JBIG2Stream();
+ virtual StreamKind getKind() { return strJBIG2; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ void readSegments();
+ void readSymbolDictSeg(Guint segNum, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ void readTextRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ JBIG2Bitmap *readTextRegion(GBool huff, GBool refine,
+ int w, int h,
+ Guint numInstances,
+ Guint logStrips,
+ int numSyms,
+ JBIG2HuffmanTable *symCodeTab,
+ Guint symCodeLen,
+ JBIG2Bitmap **syms,
+ Guint defPixel, Guint combOp,
+ Guint transposed, Guint refCorner,
+ int sOffset,
+ JBIG2HuffmanTable *huffFSTable,
+ JBIG2HuffmanTable *huffDSTable,
+ JBIG2HuffmanTable *huffDTTable,
+ JBIG2HuffmanTable *huffRDWTable,
+ JBIG2HuffmanTable *huffRDHTable,
+ JBIG2HuffmanTable *huffRDXTable,
+ JBIG2HuffmanTable *huffRDYTable,
+ JBIG2HuffmanTable *huffRSizeTable,
+ Guint templ,
+ int *atx, int *aty);
+ void readPatternDictSeg(Guint segNum, Guint length);
+ void readHalftoneRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs, Guint nRefSegs);
+ void readGenericRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length);
+ JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h,
+ int templ, GBool tpgdOn,
+ GBool useSkip, JBIG2Bitmap *skip,
+ int *atx, int *aty,
+ int mmrDataLength);
+ void readGenericRefinementRegionSeg(Guint segNum, GBool imm,
+ GBool lossless, Guint length,
+ Guint *refSegs,
+ Guint nRefSegs);
+ JBIG2Bitmap *readGenericRefinementRegion(int w, int h,
+ int templ, GBool tpgrOn,
+ JBIG2Bitmap *refBitmap,
+ int refDX, int refDY,
+ int *atx, int *aty);
+ void readPageInfoSeg(Guint length);
+ void readEndOfStripeSeg(Guint length);
+ void readProfilesSeg(Guint length);
+ void readCodeTableSeg(Guint segNum, Guint length);
+ void readExtensionSeg(Guint length);
+ JBIG2Segment *findSegment(Guint segNum);
+ void discardSegment(Guint segNum);
+ void resetGenericStats(Guint templ,
+ JBIG2ArithmeticDecoderStats *prevStats);
+ void resetRefinementStats(Guint templ,
+ JBIG2ArithmeticDecoderStats *prevStats);
+ void resetIntStats(int symCodeLen);
+ GBool readUByte(Guint *x);
+ GBool readByte(int *x);
+ GBool readUWord(Guint *x);
+ GBool readULong(Guint *x);
+ GBool readLong(int *x);
+
+ Guint pageW, pageH, curPageH;
+ Guint pageDefPixel;
+ JBIG2Bitmap *pageBitmap;
+ Guint defCombOp;
+ GList *segments; // [JBIG2Segment]
+ GList *globalSegments; // [JBIG2Segment]
+ Stream *curStr;
+ Guchar *dataPtr;
+ Guchar *dataEnd;
+
+ JBIG2ArithmeticDecoder *arithDecoder;
+ JBIG2ArithmeticDecoderStats *genericRegionStats;
+ JBIG2ArithmeticDecoderStats *refinementRegionStats;
+ JBIG2ArithmeticDecoderStats *iadhStats;
+ JBIG2ArithmeticDecoderStats *iadwStats;
+ JBIG2ArithmeticDecoderStats *iaexStats;
+ JBIG2ArithmeticDecoderStats *iaaiStats;
+ JBIG2ArithmeticDecoderStats *iadtStats;
+ JBIG2ArithmeticDecoderStats *iaitStats;
+ JBIG2ArithmeticDecoderStats *iafsStats;
+ JBIG2ArithmeticDecoderStats *iadsStats;
+ JBIG2ArithmeticDecoderStats *iardxStats;
+ JBIG2ArithmeticDecoderStats *iardyStats;
+ JBIG2ArithmeticDecoderStats *iardwStats;
+ JBIG2ArithmeticDecoderStats *iardhStats;
+ JBIG2ArithmeticDecoderStats *iariStats;
+ JBIG2ArithmeticDecoderStats *iaidStats;
+ JBIG2HuffmanDecoder *huffDecoder;
+ JBIG2MMRDecoder *mmrDecoder;
+};
+
+#endif
diff --git a/pdftops/Japan12CMapInfo.h b/pdftops/Japan12CMapInfo.h
new file mode 100644
index 000000000..ae4ef9c9d
--- /dev/null
+++ b/pdftops/Japan12CMapInfo.h
@@ -0,0 +1,31362 @@
+//========================================================================
+//
+// Japan12CMapInfo.h
+//
+// This file was automatically generated by makeCMapInfo.
+//
+// Copyright 1998 Derek B. Noonburg
+//
+//========================================================================
+
+#ifndef JAPAN12CMAPINFO_H
+#define JAPAN12CMAPINFO_H
+
+static Gushort japan1278EUCHMap2[1252] = {
+ 0x0000, 0x0000,
+ 0x8ea0, 0x0146,
+ 0xa1a1, 0x0279,
+ 0xa2a1, 0x02d7,
+ 0xa3b0, 0x030c,
+ 0xa3c1, 0x0316,
+ 0xa3e1, 0x0330,
+ 0xa4a1, 0x034a,
+ 0xa5a1, 0x039d,
+ 0xa6a1, 0x03f3,
+ 0xa6c1, 0x040b,
+ 0xa7a1, 0x0423,
+ 0xa7d1, 0x0444,
+ 0xb0a1, 0x0465,
+ 0xb0a2, 0x1dd1,
+ 0xb0a3, 0x0467,
+ 0xb0a9, 0x204a,
+ 0xb0aa, 0x046e,
+ 0xb0b2, 0x1f19,
+ 0xb0b3, 0x1ca2,
+ 0xb0b4, 0x0478,
+ 0xb0bb, 0x1dd2,
+ 0xb0bc, 0x0480,
+ 0xb0ee, 0x1dd3,
+ 0xb0ef, 0x04b3,
+ 0xb0f3, 0x1dd4,
+ 0xb0f4, 0x04b8,
+ 0xb0fc, 0x1dd5,
+ 0xb0fd, 0x04c1,
+ 0xb1a1, 0x04c3,
+ 0xb1aa, 0x1dd6,
+ 0xb1ab, 0x04cd,
+ 0xb1b5, 0x1dd7,
+ 0xb1b6, 0x04d8,
+ 0xb1b9, 0x1dd8,
+ 0xb1ba, 0x04dc,
+ 0xb1bd, 0x1dda,
+ 0xb1be, 0x04e0,
+ 0xb1c2, 0x1ddb,
+ 0xb1c3, 0x04e5,
+ 0xb1eb, 0x1ddc,
+ 0xb1ec, 0x050e,
+ 0xb2a1, 0x0521,
+ 0xb2a8, 0x1ddd,
+ 0xb2a9, 0x1cc9,
+ 0xb2aa, 0x1dde,
+ 0xb2ab, 0x052b,
+ 0xb2e0, 0x1ddf,
+ 0xb2e1, 0x0561,
+ 0xb2fa, 0x1de0,
+ 0xb2fb, 0x057b,
+ 0xb2fd, 0x1de1,
+ 0xb2fe, 0x057e,
+ 0xb3a1, 0x057f,
+ 0xb3a2, 0x1de2,
+ 0xb3a3, 0x0581,
+ 0xb3c2, 0x1961,
+ 0xb3c3, 0x05a1,
+ 0xb3c9, 0x139f,
+ 0xb3ca, 0x05a8,
+ 0xb3e5, 0x1de3,
+ 0xb3e6, 0x05c4,
+ 0xb3eb, 0x1de4,
+ 0xb3ec, 0x05ca,
+ 0xb3f3, 0x1de5,
+ 0xb3f4, 0x05d2,
+ 0xb3f6, 0x1731,
+ 0xb3f7, 0x05d5,
+ 0xb3fa, 0x1de6,
+ 0xb3fb, 0x05d9,
+ 0xb4a1, 0x05dd,
+ 0xb4c2, 0x1de7,
+ 0xb4c3, 0x1572,
+ 0xb4c4, 0x0600,
+ 0xb4cd, 0x1de8,
+ 0xb4ce, 0x060a,
+ 0xb4d2, 0x1a20,
+ 0xb4d3, 0x060f,
+ 0xb4e5, 0x1de9,
+ 0xb4e6, 0x0622,
+ 0xb5a1, 0x063b,
+ 0xb5ab, 0x1dea,
+ 0xb5ac, 0x0646,
+ 0xb5c0, 0x1deb,
+ 0xb5c1, 0x065b,
+ 0xb6a1, 0x0699,
+ 0xb6a2, 0x1dec,
+ 0xb6a3, 0x069b,
+ 0xb6aa, 0x1ded,
+ 0xb6ab, 0x06a3,
+ 0xb6c6, 0x1d32,
+ 0xb6c7, 0x06bf,
+ 0xb6cf, 0x1dee,
+ 0xb6d0, 0x06c8,
+ 0xb6ed, 0x1def,
+ 0xb6ee, 0x06e6,
+ 0xb6f4, 0x1df0,
+ 0xb6f5, 0x06ed,
+ 0xb6fb, 0x1df1,
+ 0xb6fc, 0x06f4,
+ 0xb6fd, 0x1df2,
+ 0xb6fe, 0x06f6,
+ 0xb7a1, 0x06f7,
+ 0xb7a4, 0x1df3,
+ 0xb7a5, 0x06fb,
+ 0xb7b7, 0x1df4,
+ 0xb7b8, 0x070e,
+ 0xb7c5, 0x1df5,
+ 0xb7c6, 0x071c,
+ 0xb7ce, 0x1df6,
+ 0xb7cf, 0x0725,
+ 0xb7d2, 0x1df7,
+ 0xb7d3, 0x0729,
+ 0xb7d5, 0x1df8,
+ 0xb7d6, 0x072c,
+ 0xb7db, 0x1c0d,
+ 0xb7dc, 0x0732,
+ 0xb7e4, 0x1df9,
+ 0xb7e5, 0x073b,
+ 0xb7f1, 0x1dfa,
+ 0xb7f2, 0x0748,
+ 0xb7f9, 0x1dfb,
+ 0xb7fa, 0x0750,
+ 0xb7fe, 0x1dfc,
+ 0xb8a1, 0x0755,
+ 0xb8b4, 0x1dfd,
+ 0xb8b5, 0x0769,
+ 0xb8c1, 0x1dfe,
+ 0xb8c2, 0x0776,
+ 0xb9a1, 0x07b3,
+ 0xb9ab, 0x1dff,
+ 0xb9ac, 0x07be,
+ 0xb9b7, 0x1e00,
+ 0xb9b8, 0x07ca,
+ 0xb9c2, 0x1e01,
+ 0xb9c3, 0x07d5,
+ 0xb9dc, 0x16dd,
+ 0xb9dd, 0x07ef,
+ 0xb9ed, 0x1e02,
+ 0xb9ee, 0x0800,
+ 0xb9f4, 0x1e03,
+ 0xb9f5, 0x0807,
+ 0xb9f9, 0x1e04,
+ 0xb9fa, 0x080c,
+ 0xbaa1, 0x0811,
+ 0xbad3, 0x1e05,
+ 0xbad4, 0x0844,
+ 0xbae7, 0x1e06,
+ 0xbae8, 0x0858,
+ 0xbaf4, 0x1e07,
+ 0xbaf5, 0x0865,
+ 0xbba1, 0x086f,
+ 0xbba7, 0x1e08,
+ 0xbba8, 0x0876,
+ 0xbbaa, 0x1e09,
+ 0xbbab, 0x0879,
+ 0xbbac, 0x1e0a,
+ 0xbbad, 0x087b,
+ 0xbbb9, 0x1e0b,
+ 0xbbba, 0x0888,
+ 0xbca1, 0x08cd,
+ 0xbcc8, 0x1e0d,
+ 0xbcc9, 0x1929,
+ 0xbcca, 0x08f6,
+ 0xbcd7, 0x1e0e,
+ 0xbcd8, 0x0904,
+ 0xbcdd, 0x1e0f,
+ 0xbcdf, 0x090b,
+ 0xbda1, 0x092b,
+ 0xbdab, 0x1e11,
+ 0xbdac, 0x0936,
+ 0xbdb6, 0x1e12,
+ 0xbdb7, 0x0941,
+ 0xbdec, 0x1e13,
+ 0xbdee, 0x0978,
+ 0xbdf2, 0x1e15,
+ 0xbdf4, 0x097e,
+ 0xbea1, 0x0989,
+ 0xbea5, 0x1e17,
+ 0xbea6, 0x098e,
+ 0xbeb3, 0x1e18,
+ 0xbeb4, 0x099c,
+ 0xbebf, 0x1e19,
+ 0xbec0, 0x09a8,
+ 0xbed5, 0x1e1a,
+ 0xbed6, 0x09be,
+ 0xbedf, 0x1e1b,
+ 0xbee0, 0x09c8,
+ 0xbee4, 0x1e1c,
+ 0xbee5, 0x09cd,
+ 0xbfa1, 0x09e7,
+ 0xbfaa, 0x1e1d,
+ 0xbfab, 0x09f1,
+ 0xbfd9, 0x1e1e,
+ 0xbfda, 0x0a20,
+ 0xbfe0, 0x1e1f,
+ 0xbfe1, 0x0a27,
+ 0xbfe9, 0x1e20,
+ 0xbfea, 0x0a30,
+ 0xc0a1, 0x0a45,
+ 0xc0a2, 0x1e21,
+ 0xc0a3, 0x0a47,
+ 0xc0c2, 0x1e22,
+ 0xc0c3, 0x0a67,
+ 0xc0e6, 0x1e23,
+ 0xc0e7, 0x0a8b,
+ 0xc0f1, 0x1e24,
+ 0xc0f3, 0x0a97,
+ 0xc0f9, 0x1e26,
+ 0xc0fb, 0x0a9f,
+ 0xc1a1, 0x0aa3,
+ 0xc1a7, 0x1e28,
+ 0xc1a8, 0x1a6e,
+ 0xc1a9, 0x0aab,
+ 0xc1b9, 0x1e29,
+ 0xc1ba, 0x0abc,
+ 0xc1cc, 0x1e2a,
+ 0xc1cd, 0x0acf,
+ 0xc1cf, 0x1e2b,
+ 0xc1d0, 0x0ad2,
+ 0xc1df, 0x1e2c,
+ 0xc1e0, 0x0ae2,
+ 0xc1e9, 0x1e2d,
+ 0xc1ea, 0x0aec,
+ 0xc2a1, 0x0b01,
+ 0xc2bd, 0x1e2e,
+ 0xc2be, 0x0b1e,
+ 0xc2cd, 0x1e2f,
+ 0xc2ce, 0x0b2e,
+ 0xc2dc, 0x1e30,
+ 0xc2dd, 0x0b3d,
+ 0xc2e3, 0x1e31,
+ 0xc2e4, 0x0b44,
+ 0xc2ef, 0x1e32,
+ 0xc2f0, 0x0b50,
+ 0xc2f5, 0x1e33,
+ 0xc2f7, 0x0b57,
+ 0xc2fd, 0x1e35,
+ 0xc2fe, 0x0b5e,
+ 0xc3a1, 0x0b5f,
+ 0xc3a7, 0x1e36,
+ 0xc3a8, 0x0b66,
+ 0xc3a9, 0x1e37,
+ 0xc3ab, 0x0b69,
+ 0xc3ad, 0x1e39,
+ 0xc3af, 0x0b6d,
+ 0xc3bd, 0x1e3b,
+ 0xc3be, 0x0b7c,
+ 0xc3f0, 0x1e3c,
+ 0xc3f1, 0x0baf,
+ 0xc3f5, 0x1e3d,
+ 0xc3f6, 0x0bb4,
+ 0xc3fc, 0x1e3e,
+ 0xc3fd, 0x0bbb,
+ 0xc4a1, 0x0bbd,
+ 0xc4bd, 0x1e3f,
+ 0xc4be, 0x0bda,
+ 0xc4c8, 0x1e40,
+ 0xc4c9, 0x0be5,
+ 0xc4ca, 0x1e41,
+ 0xc4cb, 0x0be7,
+ 0xc4cd, 0x1e42,
+ 0xc4ce, 0x0bea,
+ 0xc4cf, 0x1e43,
+ 0xc4d0, 0x0bec,
+ 0xc4d4, 0x204b,
+ 0xc4d5, 0x0bf1,
+ 0xc4db, 0x11b5,
+ 0xc4dc, 0x0bf8,
+ 0xc5a1, 0x0c1b,
+ 0xc5a2, 0x1e44,
+ 0xc5a3, 0x0c1d,
+ 0xc5a7, 0x1e45,
+ 0xc5a8, 0x0c22,
+ 0xc5ae, 0x1e46,
+ 0xc5af, 0x0c29,
+ 0xc5b6, 0x1e47,
+ 0xc5b7, 0x0c31,
+ 0xc5bf, 0x1e48,
+ 0xc5c0, 0x0c3a,
+ 0xc5c8, 0x1e49,
+ 0xc5c9, 0x0c43,
+ 0xc5cb, 0x1e4a,
+ 0xc5cc, 0x0c46,
+ 0xc5d1, 0x1e4b,
+ 0xc5d3, 0x0c4d,
+ 0xc5d7, 0x16df,
+ 0xc5d8, 0x0c52,
+ 0xc5e4, 0x1e4d,
+ 0xc5e5, 0x0c5f,
+ 0xc5ee, 0x1450,
+ 0xc5ef, 0x0c69,
+ 0xc5f3, 0x1536,
+ 0xc5f4, 0x0c6e,
+ 0xc5f8, 0x1e4e,
+ 0xc5f9, 0x0c73,
+ 0xc6a1, 0x0c79,
+ 0xc6be, 0x1e4f,
+ 0xc6bf, 0x0c97,
+ 0xc6c2, 0x1e50,
+ 0xc6c3, 0x0c9b,
+ 0xc6d4, 0x1e51,
+ 0xc6d6, 0x0cae,
+ 0xc6db, 0x1e53,
+ 0xc6dd, 0x0cb5,
+ 0xc6e1, 0x1e55,
+ 0xc6e2, 0x0cba,
+ 0xc6e6, 0x1e56,
+ 0xc6e8, 0x0cc0,
+ 0xc6ea, 0x1e58,
+ 0xc6eb, 0x0cc3,
+ 0xc6f6, 0x1aed,
+ 0xc6f7, 0x0ccf,
+ 0xc7a1, 0x0cd7,
+ 0xc7a9, 0x1e59,
+ 0xc7aa, 0x0ce0,
+ 0xc7b9, 0x1e5a,
+ 0xc7ba, 0x0cf0,
+ 0xc7d7, 0x1e5b,
+ 0xc7d8, 0x0d0e,
+ 0xc7e7, 0x1e5c,
+ 0xc7e8, 0x1989,
+ 0xc7e9, 0x1e5d,
+ 0xc7ea, 0x0d20,
+ 0xc7ed, 0x1e5e,
+ 0xc7ee, 0x0d24,
+ 0xc8a1, 0x0d35,
+ 0xc8a4, 0x1e5f,
+ 0xc8a5, 0x0d39,
+ 0xc8ae, 0x1e60,
+ 0xc8af, 0x0d43,
+ 0xc8b0, 0x1e61,
+ 0xc8b1, 0x0d45,
+ 0xc8d4, 0x1e62,
+ 0xc8d5, 0x0d69,
+ 0xc8e2, 0x1e63,
+ 0xc8e3, 0x0d77,
+ 0xc8f5, 0x1e64,
+ 0xc8f6, 0x0d8a,
+ 0xc9a1, 0x0d93,
+ 0xc9a2, 0x1e65,
+ 0xc9a4, 0x0d96,
+ 0xc9af, 0x1e67,
+ 0xc9b0, 0x143b,
+ 0xc9b1, 0x0da3,
+ 0xc9b2, 0x1e68,
+ 0xc9b3, 0x0da5,
+ 0xc9b5, 0x1e69,
+ 0xc9b6, 0x0da8,
+ 0xc9c0, 0x1e6a,
+ 0xc9c1, 0x0db3,
+ 0xc9ce, 0x1e6b,
+ 0xc9cf, 0x0dc1,
+ 0xc9d1, 0x1e6c,
+ 0xc9d2, 0x0dc4,
+ 0xcaa1, 0x0df1,
+ 0xcac3, 0x1e6d,
+ 0xcac4, 0x0e14,
+ 0xcacd, 0x1e6e,
+ 0xcace, 0x0e1e,
+ 0xcada, 0x1e6f,
+ 0xcadb, 0x0e2b,
+ 0xcaf9, 0x1e70,
+ 0xcafa, 0x0e4a,
+ 0xcba1, 0x0e4f,
+ 0xcba2, 0x1e71,
+ 0xcba3, 0x0e51,
+ 0xcba9, 0x1e72,
+ 0xcbaa, 0x0e58,
+ 0xcbcb, 0x1e73,
+ 0xcbcc, 0x0e7a,
+ 0xcbea, 0x1d33,
+ 0xcbeb, 0x0e99,
+ 0xcbf0, 0x1e74,
+ 0xcbf1, 0x0e9f,
+ 0xcbf8, 0x1f2c,
+ 0xcbf9, 0x102f,
+ 0xcbfa, 0x0ea8,
+ 0xcca1, 0x0ead,
+ 0xcccd, 0x1e75,
+ 0xccce, 0x0eda,
+ 0xccd9, 0x1e76,
+ 0xccda, 0x0ee6,
+ 0xccdf, 0x1e77,
+ 0xcce0, 0x0eec,
+ 0xcce2, 0x1e78,
+ 0xcce3, 0x0eef,
+ 0xccf9, 0x1935,
+ 0xccfa, 0x1e79,
+ 0xccfb, 0x0f07,
+ 0xccfc, 0x1e7a,
+ 0xccfd, 0x0f09,
+ 0xccfe, 0x1e7b,
+ 0xcda1, 0x0f0b,
+ 0xcdb2, 0x1e7c,
+ 0xcdb3, 0x0f1d,
+ 0xcdd0, 0x1e7d,
+ 0xcdd1, 0x0f3b,
+ 0xcdd4, 0x1e7e,
+ 0xcdd5, 0x0f3f,
+ 0xcdda, 0x1d34,
+ 0xcddb, 0x0f45,
+ 0xcde9, 0x1e7f,
+ 0xcdea, 0x0f54,
+ 0xcea1, 0x0f69,
+ 0xcecb, 0x1e80,
+ 0xcecc, 0x0f94,
+ 0xcefa, 0x1e81,
+ 0xcefc, 0x0fc4,
+ 0xcfa1, 0x1e83,
+ 0xcfa2, 0x0fc8,
+ 0xcfb1, 0x1e84,
+ 0xcfb2, 0x0fd8,
+ 0xcfb6, 0x1777,
+ 0xcfb7, 0x0fdd,
+ 0xcfb9, 0x1e85,
+ 0xcfba, 0x0fe0,
+ 0xd0a1, 0x0ffa,
+ 0xd0d6, 0x0ea7,
+ 0xd0d7, 0x1030,
+ 0xd1a1, 0x1058,
+ 0xd1bd, 0x1e86,
+ 0xd1be, 0x1075,
+ 0xd1c7, 0x1e87,
+ 0xd1c8, 0x107f,
+ 0xd1cb, 0x1e88,
+ 0xd1cc, 0x1083,
+ 0xd1cd, 0x1e89,
+ 0xd1ce, 0x1085,
+ 0xd2a1, 0x10b6,
+ 0xd3a1, 0x1114,
+ 0xd3b0, 0x1e8a,
+ 0xd3b1, 0x1124,
+ 0xd3ba, 0x1e8b,
+ 0xd3bb, 0x112e,
+ 0xd3de, 0x1e8d,
+ 0xd3df, 0x1152,
+ 0xd3eb, 0x1e8e,
+ 0xd3ec, 0x115f,
+ 0xd4a1, 0x1172,
+ 0xd4c4, 0x1e8f,
+ 0xd4c5, 0x1196,
+ 0xd4e4, 0x0bf7,
+ 0xd4e5, 0x11b6,
+ 0xd5a1, 0x11d0,
+ 0xd5bd, 0x1e90,
+ 0xd5be, 0x11ed,
+ 0xd5e3, 0x1e91,
+ 0xd5e4, 0x1213,
+ 0xd6a1, 0x122e,
+ 0xd6a2, 0x1e92,
+ 0xd6a3, 0x1230,
+ 0xd7a1, 0x128c,
+ 0xd8a1, 0x12ea,
+ 0xd8a4, 0x1e94,
+ 0xd8a5, 0x12ee,
+ 0xd9a1, 0x1348,
+ 0xd9e0, 0x1e95,
+ 0xd9e1, 0x1388,
+ 0xd9ec, 0x1e96,
+ 0xd9ed, 0x1394,
+ 0xd9f8, 0x05a7,
+ 0xd9f9, 0x13a0,
+ 0xdaa1, 0x13a6,
+ 0xdab9, 0x1e97,
+ 0xdaba, 0x13bf,
+ 0xdacd, 0x1e98,
+ 0xdace, 0x13d3,
+ 0xdba1, 0x1404,
+ 0xdbc5, 0x1e99,
+ 0xdbc6, 0x1429,
+ 0xdbca, 0x1e9a,
+ 0xdbcb, 0x142e,
+ 0xdbd8, 0x0da2,
+ 0xdbd9, 0x143c,
+ 0xdbeb, 0x1e9b,
+ 0xdbec, 0x144f,
+ 0xdbed, 0x0c68,
+ 0xdbee, 0x1451,
+ 0xdbf4, 0x1e9c,
+ 0xdbf5, 0x1458,
+ 0xdca1, 0x1462,
+ 0xdda1, 0x14c0,
+ 0xdea1, 0x151e,
+ 0xdeb9, 0x0c6d,
+ 0xdeba, 0x1537,
+ 0xded0, 0x1e9d,
+ 0xded1, 0x154e,
+ 0xdef5, 0x05ff,
+ 0xdef6, 0x1573,
+ 0xdfa1, 0x157c,
+ 0xe0a1, 0x15da,
+ 0xe0a6, 0x1e9f,
+ 0xe0a7, 0x15e0,
+ 0xe0df, 0x1ea0,
+ 0xe0e0, 0x1619,
+ 0xe0f6, 0x1d35,
+ 0xe0f7, 0x1630,
+ 0xe1a1, 0x1638,
+ 0xe1ab, 0x1ea1,
+ 0xe1ac, 0x1643,
+ 0xe1b0, 0x1ea2,
+ 0xe1b2, 0x1649,
+ 0xe2a1, 0x1696,
+ 0xe2ab, 0x1ea4,
+ 0xe2ac, 0x16a1,
+ 0xe2e8, 0x07ee,
+ 0xe2e9, 0x16de,
+ 0xe2ea, 0x0c51,
+ 0xe2eb, 0x16e0,
+ 0xe2ef, 0x1ea5,
+ 0xe2f0, 0x16e5,
+ 0xe3a1, 0x16f4,
+ 0xe3ca, 0x1ea6,
+ 0xe3cb, 0x171e,
+ 0xe3d4, 0x1ea7,
+ 0xe3d5, 0x1728,
+ 0xe3de, 0x05d4,
+ 0xe3df, 0x1732,
+ 0xe4a1, 0x1752,
+ 0xe4b9, 0x1ea8,
+ 0xe4ba, 0x176b,
+ 0xe4c6, 0x0fdc,
+ 0xe4c7, 0x1778,
+ 0xe4e4, 0x1ea9,
+ 0xe4e5, 0x1796,
+ 0xe4ee, 0x1eaa,
+ 0xe4ef, 0x17a0,
+ 0xe5a1, 0x17b0,
+ 0xe5b9, 0x1eab,
+ 0xe5ba, 0x17c9,
+ 0xe5bb, 0x1eac,
+ 0xe5bc, 0x17cb,
+ 0xe5c6, 0x1ead,
+ 0xe5c7, 0x17d6,
+ 0xe6a1, 0x180e,
+ 0xe6c6, 0x1eae,
+ 0xe6c7, 0x1834,
+ 0xe7a1, 0x186c,
+ 0xe7e4, 0x1eaf,
+ 0xe7e5, 0x18b0,
+ 0xe7e9, 0x1eb0,
+ 0xe7ea, 0x18b5,
+ 0xe7f2, 0x1eb1,
+ 0xe7f3, 0x18be,
+ 0xe8a1, 0x18ca,
+ 0xe8b4, 0x1eb2,
+ 0xe8b5, 0x18de,
+ 0xe8bb, 0x1eb3,
+ 0xe8bc, 0x18e5,
+ 0xe8f4, 0x1eb4,
+ 0xe8f5, 0x191e,
+ 0xe9a1, 0x1928,
+ 0xe9a2, 0x08f5,
+ 0xe9a3, 0x192a,
+ 0xe9ae, 0x0f05,
+ 0xe9af, 0x1936,
+ 0xe9da, 0x05a0,
+ 0xe9db, 0x1962,
+ 0xeaa1, 0x1986,
+ 0xeaa4, 0x0d1e,
+ 0xeaa5, 0x198a,
+ 0xeaa7, 0x1eb6,
+ 0xeaa8, 0x198d,
+ 0xeabd, 0x1eb7,
+ 0xeabe, 0x19a3,
+ 0xeaef, 0x1eb8,
+ 0xeaf0, 0x19d5,
+ 0xeba1, 0x19e4,
+ 0xebb2, 0x1eb9,
+ 0xebb3, 0x19f6,
+ 0xebdd, 0x060e,
+ 0xebde, 0x1a21,
+ 0xebe6, 0x1eba,
+ 0xebe7, 0x1a2a,
+ 0xebf6, 0x1ebb,
+ 0xebf7, 0x1a3a,
+ 0xeca1, 0x1a42,
+ 0xeccd, 0x0aaa,
+ 0xecce, 0x1a6f,
+ 0xece9, 0x1ebc,
+ 0xecea, 0x1a8b,
+ 0xecf4, 0x1ebd,
+ 0xecf5, 0x1a96,
+ 0xeda1, 0x1aa0,
+ 0xedce, 0x1ebe,
+ 0xedcf, 0x1ace,
+ 0xedec, 0x1ebf,
+ 0xeded, 0x1aec,
+ 0xedee, 0x1ec0,
+ 0xedef, 0x1aee,
+ 0xeea1, 0x1afe,
+ 0xeea9, 0x1ec1,
+ 0xeeaa, 0x1b07,
+ 0xeebd, 0x1ec2,
+ 0xeebe, 0x1b1b,
+ 0xeed7, 0x1ec3,
+ 0xeed8, 0x1b35,
+ 0xefa1, 0x1b5c,
+ 0xf0a1, 0x1bba,
+ 0xf0c5, 0x1ec6,
+ 0xf0c6, 0x1bdf,
+ 0xf0d1, 0x1ec7,
+ 0xf0d2, 0x1beb,
+ 0xf0d7, 0x1ec8,
+ 0xf0d8, 0x1bf1,
+ 0xf0f4, 0x0731,
+ 0xf0f5, 0x1ec9,
+ 0xf0f6, 0x1c0f,
+ 0xf1a1, 0x1c18,
+ 0xf2a1, 0x1c76,
+ 0xf2ad, 0x1eca,
+ 0xf2ae, 0x1c83,
+ 0xf2bc, 0x1ecb,
+ 0xf2bd, 0x1c92,
+ 0xf2cd, 0x0477,
+ 0xf2ce, 0x1ecc,
+ 0xf2cf, 0x1ca4,
+ 0xf2f4, 0x0529,
+ 0xf2f5, 0x1cca,
+ 0xf3a1, 0x1cd4,
+ 0xf3d1, 0x1ecd,
+ 0xf3d2, 0x1d05,
+ 0xf3fd, 0x1ece,
+ 0xf3fe, 0x1d31,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278EUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278EUCHMap2, 626
+};
+
+static Gushort japan1278EUCVMap2[1306] = {
+ 0x0000, 0x0000,
+ 0x8ea0, 0x0146,
+ 0xa1a1, 0x0279,
+ 0xa2a1, 0x02d7,
+ 0xa3b0, 0x030c,
+ 0xa3c1, 0x0316,
+ 0xa3e1, 0x0330,
+ 0xa4a1, 0x034a,
+ 0xa5a1, 0x039d,
+ 0xa6a1, 0x03f3,
+ 0xa6c1, 0x040b,
+ 0xa7a1, 0x0423,
+ 0xa7d1, 0x0444,
+ 0xb0a1, 0x0465,
+ 0xb0a2, 0x1dd1,
+ 0xb0a3, 0x0467,
+ 0xb0a9, 0x204a,
+ 0xb0aa, 0x046e,
+ 0xb0b2, 0x1f19,
+ 0xb0b3, 0x1ca2,
+ 0xb0b4, 0x0478,
+ 0xb0bb, 0x1dd2,
+ 0xb0bc, 0x0480,
+ 0xb0ee, 0x1dd3,
+ 0xb0ef, 0x04b3,
+ 0xb0f3, 0x1dd4,
+ 0xb0f4, 0x04b8,
+ 0xb0fc, 0x1dd5,
+ 0xb0fd, 0x04c1,
+ 0xb1a1, 0x04c3,
+ 0xb1aa, 0x1dd6,
+ 0xb1ab, 0x04cd,
+ 0xb1b5, 0x1dd7,
+ 0xb1b6, 0x04d8,
+ 0xb1b9, 0x1dd8,
+ 0xb1ba, 0x04dc,
+ 0xb1bd, 0x1dda,
+ 0xb1be, 0x04e0,
+ 0xb1c2, 0x1ddb,
+ 0xb1c3, 0x04e5,
+ 0xb1eb, 0x1ddc,
+ 0xb1ec, 0x050e,
+ 0xb2a1, 0x0521,
+ 0xb2a8, 0x1ddd,
+ 0xb2a9, 0x1cc9,
+ 0xb2aa, 0x1dde,
+ 0xb2ab, 0x052b,
+ 0xb2e0, 0x1ddf,
+ 0xb2e1, 0x0561,
+ 0xb2fa, 0x1de0,
+ 0xb2fb, 0x057b,
+ 0xb2fd, 0x1de1,
+ 0xb2fe, 0x057e,
+ 0xb3a1, 0x057f,
+ 0xb3a2, 0x1de2,
+ 0xb3a3, 0x0581,
+ 0xb3c2, 0x1961,
+ 0xb3c3, 0x05a1,
+ 0xb3c9, 0x139f,
+ 0xb3ca, 0x05a8,
+ 0xb3e5, 0x1de3,
+ 0xb3e6, 0x05c4,
+ 0xb3eb, 0x1de4,
+ 0xb3ec, 0x05ca,
+ 0xb3f3, 0x1de5,
+ 0xb3f4, 0x05d2,
+ 0xb3f6, 0x1731,
+ 0xb3f7, 0x05d5,
+ 0xb3fa, 0x1de6,
+ 0xb3fb, 0x05d9,
+ 0xb4a1, 0x05dd,
+ 0xb4c2, 0x1de7,
+ 0xb4c3, 0x1572,
+ 0xb4c4, 0x0600,
+ 0xb4cd, 0x1de8,
+ 0xb4ce, 0x060a,
+ 0xb4d2, 0x1a20,
+ 0xb4d3, 0x060f,
+ 0xb4e5, 0x1de9,
+ 0xb4e6, 0x0622,
+ 0xb5a1, 0x063b,
+ 0xb5ab, 0x1dea,
+ 0xb5ac, 0x0646,
+ 0xb5c0, 0x1deb,
+ 0xb5c1, 0x065b,
+ 0xb6a1, 0x0699,
+ 0xb6a2, 0x1dec,
+ 0xb6a3, 0x069b,
+ 0xb6aa, 0x1ded,
+ 0xb6ab, 0x06a3,
+ 0xb6c6, 0x1d32,
+ 0xb6c7, 0x06bf,
+ 0xb6cf, 0x1dee,
+ 0xb6d0, 0x06c8,
+ 0xb6ed, 0x1def,
+ 0xb6ee, 0x06e6,
+ 0xb6f4, 0x1df0,
+ 0xb6f5, 0x06ed,
+ 0xb6fb, 0x1df1,
+ 0xb6fc, 0x06f4,
+ 0xb6fd, 0x1df2,
+ 0xb6fe, 0x06f6,
+ 0xb7a1, 0x06f7,
+ 0xb7a4, 0x1df3,
+ 0xb7a5, 0x06fb,
+ 0xb7b7, 0x1df4,
+ 0xb7b8, 0x070e,
+ 0xb7c5, 0x1df5,
+ 0xb7c6, 0x071c,
+ 0xb7ce, 0x1df6,
+ 0xb7cf, 0x0725,
+ 0xb7d2, 0x1df7,
+ 0xb7d3, 0x0729,
+ 0xb7d5, 0x1df8,
+ 0xb7d6, 0x072c,
+ 0xb7db, 0x1c0d,
+ 0xb7dc, 0x0732,
+ 0xb7e4, 0x1df9,
+ 0xb7e5, 0x073b,
+ 0xb7f1, 0x1dfa,
+ 0xb7f2, 0x0748,
+ 0xb7f9, 0x1dfb,
+ 0xb7fa, 0x0750,
+ 0xb7fe, 0x1dfc,
+ 0xb8a1, 0x0755,
+ 0xb8b4, 0x1dfd,
+ 0xb8b5, 0x0769,
+ 0xb8c1, 0x1dfe,
+ 0xb8c2, 0x0776,
+ 0xb9a1, 0x07b3,
+ 0xb9ab, 0x1dff,
+ 0xb9ac, 0x07be,
+ 0xb9b7, 0x1e00,
+ 0xb9b8, 0x07ca,
+ 0xb9c2, 0x1e01,
+ 0xb9c3, 0x07d5,
+ 0xb9dc, 0x16dd,
+ 0xb9dd, 0x07ef,
+ 0xb9ed, 0x1e02,
+ 0xb9ee, 0x0800,
+ 0xb9f4, 0x1e03,
+ 0xb9f5, 0x0807,
+ 0xb9f9, 0x1e04,
+ 0xb9fa, 0x080c,
+ 0xbaa1, 0x0811,
+ 0xbad3, 0x1e05,
+ 0xbad4, 0x0844,
+ 0xbae7, 0x1e06,
+ 0xbae8, 0x0858,
+ 0xbaf4, 0x1e07,
+ 0xbaf5, 0x0865,
+ 0xbba1, 0x086f,
+ 0xbba7, 0x1e08,
+ 0xbba8, 0x0876,
+ 0xbbaa, 0x1e09,
+ 0xbbab, 0x0879,
+ 0xbbac, 0x1e0a,
+ 0xbbad, 0x087b,
+ 0xbbb9, 0x1e0b,
+ 0xbbba, 0x0888,
+ 0xbca1, 0x08cd,
+ 0xbcc8, 0x1e0d,
+ 0xbcc9, 0x1929,
+ 0xbcca, 0x08f6,
+ 0xbcd7, 0x1e0e,
+ 0xbcd8, 0x0904,
+ 0xbcdd, 0x1e0f,
+ 0xbcdf, 0x090b,
+ 0xbda1, 0x092b,
+ 0xbdab, 0x1e11,
+ 0xbdac, 0x0936,
+ 0xbdb6, 0x1e12,
+ 0xbdb7, 0x0941,
+ 0xbdec, 0x1e13,
+ 0xbdee, 0x0978,
+ 0xbdf2, 0x1e15,
+ 0xbdf4, 0x097e,
+ 0xbea1, 0x0989,
+ 0xbea5, 0x1e17,
+ 0xbea6, 0x098e,
+ 0xbeb3, 0x1e18,
+ 0xbeb4, 0x099c,
+ 0xbebf, 0x1e19,
+ 0xbec0, 0x09a8,
+ 0xbed5, 0x1e1a,
+ 0xbed6, 0x09be,
+ 0xbedf, 0x1e1b,
+ 0xbee0, 0x09c8,
+ 0xbee4, 0x1e1c,
+ 0xbee5, 0x09cd,
+ 0xbfa1, 0x09e7,
+ 0xbfaa, 0x1e1d,
+ 0xbfab, 0x09f1,
+ 0xbfd9, 0x1e1e,
+ 0xbfda, 0x0a20,
+ 0xbfe0, 0x1e1f,
+ 0xbfe1, 0x0a27,
+ 0xbfe9, 0x1e20,
+ 0xbfea, 0x0a30,
+ 0xc0a1, 0x0a45,
+ 0xc0a2, 0x1e21,
+ 0xc0a3, 0x0a47,
+ 0xc0c2, 0x1e22,
+ 0xc0c3, 0x0a67,
+ 0xc0e6, 0x1e23,
+ 0xc0e7, 0x0a8b,
+ 0xc0f1, 0x1e24,
+ 0xc0f3, 0x0a97,
+ 0xc0f9, 0x1e26,
+ 0xc0fb, 0x0a9f,
+ 0xc1a1, 0x0aa3,
+ 0xc1a7, 0x1e28,
+ 0xc1a8, 0x1a6e,
+ 0xc1a9, 0x0aab,
+ 0xc1b9, 0x1e29,
+ 0xc1ba, 0x0abc,
+ 0xc1cc, 0x1e2a,
+ 0xc1cd, 0x0acf,
+ 0xc1cf, 0x1e2b,
+ 0xc1d0, 0x0ad2,
+ 0xc1df, 0x1e2c,
+ 0xc1e0, 0x0ae2,
+ 0xc1e9, 0x1e2d,
+ 0xc1ea, 0x0aec,
+ 0xc2a1, 0x0b01,
+ 0xc2bd, 0x1e2e,
+ 0xc2be, 0x0b1e,
+ 0xc2cd, 0x1e2f,
+ 0xc2ce, 0x0b2e,
+ 0xc2dc, 0x1e30,
+ 0xc2dd, 0x0b3d,
+ 0xc2e3, 0x1e31,
+ 0xc2e4, 0x0b44,
+ 0xc2ef, 0x1e32,
+ 0xc2f0, 0x0b50,
+ 0xc2f5, 0x1e33,
+ 0xc2f7, 0x0b57,
+ 0xc2fd, 0x1e35,
+ 0xc2fe, 0x0b5e,
+ 0xc3a1, 0x0b5f,
+ 0xc3a7, 0x1e36,
+ 0xc3a8, 0x0b66,
+ 0xc3a9, 0x1e37,
+ 0xc3ab, 0x0b69,
+ 0xc3ad, 0x1e39,
+ 0xc3af, 0x0b6d,
+ 0xc3bd, 0x1e3b,
+ 0xc3be, 0x0b7c,
+ 0xc3f0, 0x1e3c,
+ 0xc3f1, 0x0baf,
+ 0xc3f5, 0x1e3d,
+ 0xc3f6, 0x0bb4,
+ 0xc3fc, 0x1e3e,
+ 0xc3fd, 0x0bbb,
+ 0xc4a1, 0x0bbd,
+ 0xc4bd, 0x1e3f,
+ 0xc4be, 0x0bda,
+ 0xc4c8, 0x1e40,
+ 0xc4c9, 0x0be5,
+ 0xc4ca, 0x1e41,
+ 0xc4cb, 0x0be7,
+ 0xc4cd, 0x1e42,
+ 0xc4ce, 0x0bea,
+ 0xc4cf, 0x1e43,
+ 0xc4d0, 0x0bec,
+ 0xc4d4, 0x204b,
+ 0xc4d5, 0x0bf1,
+ 0xc4db, 0x11b5,
+ 0xc4dc, 0x0bf8,
+ 0xc5a1, 0x0c1b,
+ 0xc5a2, 0x1e44,
+ 0xc5a3, 0x0c1d,
+ 0xc5a7, 0x1e45,
+ 0xc5a8, 0x0c22,
+ 0xc5ae, 0x1e46,
+ 0xc5af, 0x0c29,
+ 0xc5b6, 0x1e47,
+ 0xc5b7, 0x0c31,
+ 0xc5bf, 0x1e48,
+ 0xc5c0, 0x0c3a,
+ 0xc5c8, 0x1e49,
+ 0xc5c9, 0x0c43,
+ 0xc5cb, 0x1e4a,
+ 0xc5cc, 0x0c46,
+ 0xc5d1, 0x1e4b,
+ 0xc5d3, 0x0c4d,
+ 0xc5d7, 0x16df,
+ 0xc5d8, 0x0c52,
+ 0xc5e4, 0x1e4d,
+ 0xc5e5, 0x0c5f,
+ 0xc5ee, 0x1450,
+ 0xc5ef, 0x0c69,
+ 0xc5f3, 0x1536,
+ 0xc5f4, 0x0c6e,
+ 0xc5f8, 0x1e4e,
+ 0xc5f9, 0x0c73,
+ 0xc6a1, 0x0c79,
+ 0xc6be, 0x1e4f,
+ 0xc6bf, 0x0c97,
+ 0xc6c2, 0x1e50,
+ 0xc6c3, 0x0c9b,
+ 0xc6d4, 0x1e51,
+ 0xc6d6, 0x0cae,
+ 0xc6db, 0x1e53,
+ 0xc6dd, 0x0cb5,
+ 0xc6e1, 0x1e55,
+ 0xc6e2, 0x0cba,
+ 0xc6e6, 0x1e56,
+ 0xc6e8, 0x0cc0,
+ 0xc6ea, 0x1e58,
+ 0xc6eb, 0x0cc3,
+ 0xc6f6, 0x1aed,
+ 0xc6f7, 0x0ccf,
+ 0xc7a1, 0x0cd7,
+ 0xc7a9, 0x1e59,
+ 0xc7aa, 0x0ce0,
+ 0xc7b9, 0x1e5a,
+ 0xc7ba, 0x0cf0,
+ 0xc7d7, 0x1e5b,
+ 0xc7d8, 0x0d0e,
+ 0xc7e7, 0x1e5c,
+ 0xc7e8, 0x1989,
+ 0xc7e9, 0x1e5d,
+ 0xc7ea, 0x0d20,
+ 0xc7ed, 0x1e5e,
+ 0xc7ee, 0x0d24,
+ 0xc8a1, 0x0d35,
+ 0xc8a4, 0x1e5f,
+ 0xc8a5, 0x0d39,
+ 0xc8ae, 0x1e60,
+ 0xc8af, 0x0d43,
+ 0xc8b0, 0x1e61,
+ 0xc8b1, 0x0d45,
+ 0xc8d4, 0x1e62,
+ 0xc8d5, 0x0d69,
+ 0xc8e2, 0x1e63,
+ 0xc8e3, 0x0d77,
+ 0xc8f5, 0x1e64,
+ 0xc8f6, 0x0d8a,
+ 0xc9a1, 0x0d93,
+ 0xc9a2, 0x1e65,
+ 0xc9a4, 0x0d96,
+ 0xc9af, 0x1e67,
+ 0xc9b0, 0x143b,
+ 0xc9b1, 0x0da3,
+ 0xc9b2, 0x1e68,
+ 0xc9b3, 0x0da5,
+ 0xc9b5, 0x1e69,
+ 0xc9b6, 0x0da8,
+ 0xc9c0, 0x1e6a,
+ 0xc9c1, 0x0db3,
+ 0xc9ce, 0x1e6b,
+ 0xc9cf, 0x0dc1,
+ 0xc9d1, 0x1e6c,
+ 0xc9d2, 0x0dc4,
+ 0xcaa1, 0x0df1,
+ 0xcac3, 0x1e6d,
+ 0xcac4, 0x0e14,
+ 0xcacd, 0x1e6e,
+ 0xcace, 0x0e1e,
+ 0xcada, 0x1e6f,
+ 0xcadb, 0x0e2b,
+ 0xcaf9, 0x1e70,
+ 0xcafa, 0x0e4a,
+ 0xcba1, 0x0e4f,
+ 0xcba2, 0x1e71,
+ 0xcba3, 0x0e51,
+ 0xcba9, 0x1e72,
+ 0xcbaa, 0x0e58,
+ 0xcbcb, 0x1e73,
+ 0xcbcc, 0x0e7a,
+ 0xcbea, 0x1d33,
+ 0xcbeb, 0x0e99,
+ 0xcbf0, 0x1e74,
+ 0xcbf1, 0x0e9f,
+ 0xcbf8, 0x1f2c,
+ 0xcbf9, 0x102f,
+ 0xcbfa, 0x0ea8,
+ 0xcca1, 0x0ead,
+ 0xcccd, 0x1e75,
+ 0xccce, 0x0eda,
+ 0xccd9, 0x1e76,
+ 0xccda, 0x0ee6,
+ 0xccdf, 0x1e77,
+ 0xcce0, 0x0eec,
+ 0xcce2, 0x1e78,
+ 0xcce3, 0x0eef,
+ 0xccf9, 0x1935,
+ 0xccfa, 0x1e79,
+ 0xccfb, 0x0f07,
+ 0xccfc, 0x1e7a,
+ 0xccfd, 0x0f09,
+ 0xccfe, 0x1e7b,
+ 0xcda1, 0x0f0b,
+ 0xcdb2, 0x1e7c,
+ 0xcdb3, 0x0f1d,
+ 0xcdd0, 0x1e7d,
+ 0xcdd1, 0x0f3b,
+ 0xcdd4, 0x1e7e,
+ 0xcdd5, 0x0f3f,
+ 0xcdda, 0x1d34,
+ 0xcddb, 0x0f45,
+ 0xcde9, 0x1e7f,
+ 0xcdea, 0x0f54,
+ 0xcea1, 0x0f69,
+ 0xcecb, 0x1e80,
+ 0xcecc, 0x0f94,
+ 0xcefa, 0x1e81,
+ 0xcefc, 0x0fc4,
+ 0xcfa1, 0x1e83,
+ 0xcfa2, 0x0fc8,
+ 0xcfb1, 0x1e84,
+ 0xcfb2, 0x0fd8,
+ 0xcfb6, 0x1777,
+ 0xcfb7, 0x0fdd,
+ 0xcfb9, 0x1e85,
+ 0xcfba, 0x0fe0,
+ 0xd0a1, 0x0ffa,
+ 0xd0d6, 0x0ea7,
+ 0xd0d7, 0x1030,
+ 0xd1a1, 0x1058,
+ 0xd1bd, 0x1e86,
+ 0xd1be, 0x1075,
+ 0xd1c7, 0x1e87,
+ 0xd1c8, 0x107f,
+ 0xd1cb, 0x1e88,
+ 0xd1cc, 0x1083,
+ 0xd1cd, 0x1e89,
+ 0xd1ce, 0x1085,
+ 0xd2a1, 0x10b6,
+ 0xd3a1, 0x1114,
+ 0xd3b0, 0x1e8a,
+ 0xd3b1, 0x1124,
+ 0xd3ba, 0x1e8b,
+ 0xd3bb, 0x112e,
+ 0xd3de, 0x1e8d,
+ 0xd3df, 0x1152,
+ 0xd3eb, 0x1e8e,
+ 0xd3ec, 0x115f,
+ 0xd4a1, 0x1172,
+ 0xd4c4, 0x1e8f,
+ 0xd4c5, 0x1196,
+ 0xd4e4, 0x0bf7,
+ 0xd4e5, 0x11b6,
+ 0xd5a1, 0x11d0,
+ 0xd5bd, 0x1e90,
+ 0xd5be, 0x11ed,
+ 0xd5e3, 0x1e91,
+ 0xd5e4, 0x1213,
+ 0xd6a1, 0x122e,
+ 0xd6a2, 0x1e92,
+ 0xd6a3, 0x1230,
+ 0xd7a1, 0x128c,
+ 0xd8a1, 0x12ea,
+ 0xd8a4, 0x1e94,
+ 0xd8a5, 0x12ee,
+ 0xd9a1, 0x1348,
+ 0xd9e0, 0x1e95,
+ 0xd9e1, 0x1388,
+ 0xd9ec, 0x1e96,
+ 0xd9ed, 0x1394,
+ 0xd9f8, 0x05a7,
+ 0xd9f9, 0x13a0,
+ 0xdaa1, 0x13a6,
+ 0xdab9, 0x1e97,
+ 0xdaba, 0x13bf,
+ 0xdacd, 0x1e98,
+ 0xdace, 0x13d3,
+ 0xdba1, 0x1404,
+ 0xdbc5, 0x1e99,
+ 0xdbc6, 0x1429,
+ 0xdbca, 0x1e9a,
+ 0xdbcb, 0x142e,
+ 0xdbd8, 0x0da2,
+ 0xdbd9, 0x143c,
+ 0xdbeb, 0x1e9b,
+ 0xdbec, 0x144f,
+ 0xdbed, 0x0c68,
+ 0xdbee, 0x1451,
+ 0xdbf4, 0x1e9c,
+ 0xdbf5, 0x1458,
+ 0xdca1, 0x1462,
+ 0xdda1, 0x14c0,
+ 0xdea1, 0x151e,
+ 0xdeb9, 0x0c6d,
+ 0xdeba, 0x1537,
+ 0xded0, 0x1e9d,
+ 0xded1, 0x154e,
+ 0xdef5, 0x05ff,
+ 0xdef6, 0x1573,
+ 0xdfa1, 0x157c,
+ 0xe0a1, 0x15da,
+ 0xe0a6, 0x1e9f,
+ 0xe0a7, 0x15e0,
+ 0xe0df, 0x1ea0,
+ 0xe0e0, 0x1619,
+ 0xe0f6, 0x1d35,
+ 0xe0f7, 0x1630,
+ 0xe1a1, 0x1638,
+ 0xe1ab, 0x1ea1,
+ 0xe1ac, 0x1643,
+ 0xe1b0, 0x1ea2,
+ 0xe1b2, 0x1649,
+ 0xe2a1, 0x1696,
+ 0xe2ab, 0x1ea4,
+ 0xe2ac, 0x16a1,
+ 0xe2e8, 0x07ee,
+ 0xe2e9, 0x16de,
+ 0xe2ea, 0x0c51,
+ 0xe2eb, 0x16e0,
+ 0xe2ef, 0x1ea5,
+ 0xe2f0, 0x16e5,
+ 0xe3a1, 0x16f4,
+ 0xe3ca, 0x1ea6,
+ 0xe3cb, 0x171e,
+ 0xe3d4, 0x1ea7,
+ 0xe3d5, 0x1728,
+ 0xe3de, 0x05d4,
+ 0xe3df, 0x1732,
+ 0xe4a1, 0x1752,
+ 0xe4b9, 0x1ea8,
+ 0xe4ba, 0x176b,
+ 0xe4c6, 0x0fdc,
+ 0xe4c7, 0x1778,
+ 0xe4e4, 0x1ea9,
+ 0xe4e5, 0x1796,
+ 0xe4ee, 0x1eaa,
+ 0xe4ef, 0x17a0,
+ 0xe5a1, 0x17b0,
+ 0xe5b9, 0x1eab,
+ 0xe5ba, 0x17c9,
+ 0xe5bb, 0x1eac,
+ 0xe5bc, 0x17cb,
+ 0xe5c6, 0x1ead,
+ 0xe5c7, 0x17d6,
+ 0xe6a1, 0x180e,
+ 0xe6c6, 0x1eae,
+ 0xe6c7, 0x1834,
+ 0xe7a1, 0x186c,
+ 0xe7e4, 0x1eaf,
+ 0xe7e5, 0x18b0,
+ 0xe7e9, 0x1eb0,
+ 0xe7ea, 0x18b5,
+ 0xe7f2, 0x1eb1,
+ 0xe7f3, 0x18be,
+ 0xe8a1, 0x18ca,
+ 0xe8b4, 0x1eb2,
+ 0xe8b5, 0x18de,
+ 0xe8bb, 0x1eb3,
+ 0xe8bc, 0x18e5,
+ 0xe8f4, 0x1eb4,
+ 0xe8f5, 0x191e,
+ 0xe9a1, 0x1928,
+ 0xe9a2, 0x08f5,
+ 0xe9a3, 0x192a,
+ 0xe9ae, 0x0f05,
+ 0xe9af, 0x1936,
+ 0xe9da, 0x05a0,
+ 0xe9db, 0x1962,
+ 0xeaa1, 0x1986,
+ 0xeaa4, 0x0d1e,
+ 0xeaa5, 0x198a,
+ 0xeaa7, 0x1eb6,
+ 0xeaa8, 0x198d,
+ 0xeabd, 0x1eb7,
+ 0xeabe, 0x19a3,
+ 0xeaef, 0x1eb8,
+ 0xeaf0, 0x19d5,
+ 0xeba1, 0x19e4,
+ 0xebb2, 0x1eb9,
+ 0xebb3, 0x19f6,
+ 0xebdd, 0x060e,
+ 0xebde, 0x1a21,
+ 0xebe6, 0x1eba,
+ 0xebe7, 0x1a2a,
+ 0xebf6, 0x1ebb,
+ 0xebf7, 0x1a3a,
+ 0xeca1, 0x1a42,
+ 0xeccd, 0x0aaa,
+ 0xecce, 0x1a6f,
+ 0xece9, 0x1ebc,
+ 0xecea, 0x1a8b,
+ 0xecf4, 0x1ebd,
+ 0xecf5, 0x1a96,
+ 0xeda1, 0x1aa0,
+ 0xedce, 0x1ebe,
+ 0xedcf, 0x1ace,
+ 0xedec, 0x1ebf,
+ 0xeded, 0x1aec,
+ 0xedee, 0x1ec0,
+ 0xedef, 0x1aee,
+ 0xeea1, 0x1afe,
+ 0xeea9, 0x1ec1,
+ 0xeeaa, 0x1b07,
+ 0xeebd, 0x1ec2,
+ 0xeebe, 0x1b1b,
+ 0xeed7, 0x1ec3,
+ 0xeed8, 0x1b35,
+ 0xefa1, 0x1b5c,
+ 0xf0a1, 0x1bba,
+ 0xf0c5, 0x1ec6,
+ 0xf0c6, 0x1bdf,
+ 0xf0d1, 0x1ec7,
+ 0xf0d2, 0x1beb,
+ 0xf0d7, 0x1ec8,
+ 0xf0d8, 0x1bf1,
+ 0xf0f4, 0x0731,
+ 0xf0f5, 0x1ec9,
+ 0xf0f6, 0x1c0f,
+ 0xf1a1, 0x1c18,
+ 0xf2a1, 0x1c76,
+ 0xf2ad, 0x1eca,
+ 0xf2ae, 0x1c83,
+ 0xf2bc, 0x1ecb,
+ 0xf2bd, 0x1c92,
+ 0xf2cd, 0x0477,
+ 0xf2ce, 0x1ecc,
+ 0xf2cf, 0x1ca4,
+ 0xf2f4, 0x0529,
+ 0xf2f5, 0x1cca,
+ 0xf3a1, 0x1cd4,
+ 0xf3d1, 0x1ecd,
+ 0xf3d2, 0x1d05,
+ 0xf3fd, 0x1ece,
+ 0xf3fe, 0x1d31,
+ 0xa1a2, 0x1ecf,
+ 0xa1b1, 0x1ed1,
+ 0xa1bc, 0x1ed3,
+ 0xa1c1, 0x1ed6,
+ 0xa1ca, 0x1edb,
+ 0xa1e1, 0x1eed,
+ 0xa4a1, 0x1eee,
+ 0xa4a3, 0x1eef,
+ 0xa4a5, 0x1ef0,
+ 0xa4a7, 0x1ef1,
+ 0xa4a9, 0x1ef2,
+ 0xa4c3, 0x1ef3,
+ 0xa4e3, 0x1ef4,
+ 0xa4e5, 0x1ef5,
+ 0xa4e7, 0x1ef6,
+ 0xa4ee, 0x1ef7,
+ 0xa5a1, 0x1ef8,
+ 0xa5a3, 0x1ef9,
+ 0xa5a5, 0x1efa,
+ 0xa5a7, 0x1efb,
+ 0xa5a9, 0x1efc,
+ 0xa5c3, 0x1efd,
+ 0xa5e3, 0x1efe,
+ 0xa5e5, 0x1eff,
+ 0xa5e7, 0x1f00,
+ 0xa5ee, 0x1f01,
+ 0xa5f5, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278EUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278EUCVMap2, 653
+};
+
+static Gushort japan1278HMap2[1250] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3029, 0x204a,
+ 0x302a, 0x046e,
+ 0x3032, 0x1f19,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313d, 0x1dda,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x4454, 0x204b,
+ 0x4455, 0x0bf1,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b78, 0x1f2c,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278HMap2, 625
+};
+
+static Gushort japan1278RKSJHMap2[1252] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88a7, 0x204a,
+ 0x88a8, 0x046e,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d2, 0x204b,
+ 0x92d3, 0x0bf1,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278RKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278RKSJHMap2, 626
+};
+
+static Gushort japan1278RKSJVMap2[1306] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88a7, 0x204a,
+ 0x88a8, 0x046e,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d2, 0x204b,
+ 0x92d3, 0x0bf1,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0x8141, 0x1ecf,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278RKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278RKSJVMap2, 653
+};
+
+static Gushort japan1278VMap2[1304] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3029, 0x204a,
+ 0x302a, 0x046e,
+ 0x3032, 0x1f19,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313d, 0x1dda,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x4454, 0x204b,
+ 0x4455, 0x0bf1,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b78, 0x1f2c,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x2122, 0x1ecf,
+ 0x2131, 0x1ed1,
+ 0x213c, 0x1ed3,
+ 0x2141, 0x1ed6,
+ 0x214a, 0x1edb,
+ 0x2161, 0x1eed,
+ 0x2421, 0x1eee,
+ 0x2423, 0x1eef,
+ 0x2425, 0x1ef0,
+ 0x2427, 0x1ef1,
+ 0x2429, 0x1ef2,
+ 0x2443, 0x1ef3,
+ 0x2463, 0x1ef4,
+ 0x2465, 0x1ef5,
+ 0x2467, 0x1ef6,
+ 0x246e, 0x1ef7,
+ 0x2521, 0x1ef8,
+ 0x2523, 0x1ef9,
+ 0x2525, 0x1efa,
+ 0x2527, 0x1efb,
+ 0x2529, 0x1efc,
+ 0x2543, 0x1efd,
+ 0x2563, 0x1efe,
+ 0x2565, 0x1eff,
+ 0x2567, 0x1f00,
+ 0x256e, 0x1f01,
+ 0x2575, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278VMap2, 652
+};
+
+static Gushort japan1278msRKSJHMap2[1424] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88a7, 0x204a,
+ 0x88a8, 0x046e,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d2, 0x204b,
+ 0x92d3, 0x0bf1,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278msRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0277, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278msRKSJHMap2, 712
+};
+
+static Gushort japan1278msRKSJVMap2[1580] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88a7, 0x204a,
+ 0x88a8, 0x046e,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d2, 0x204b,
+ 0x92d3, 0x0bf1,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0x8141, 0x1ecf,
+ 0x8143, 0x204c,
+ 0x8144, 0x2052,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x81a8, 0x02e3,
+ 0x81a9, 0x02e2,
+ 0x81aa, 0x02e0,
+ 0x81ac, 0x204e,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0x849f, 0x1d39,
+ 0x84a0, 0x1d37,
+ 0x84a1, 0x1d47,
+ 0x84a2, 0x1d4f,
+ 0x84a3, 0x1d4b,
+ 0x84a4, 0x1d43,
+ 0x84a5, 0x1d63,
+ 0x84a6, 0x1d5b,
+ 0x84a7, 0x1d6b,
+ 0x84a8, 0x1d53,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d3a,
+ 0x84ab, 0x1d38,
+ 0x84ac, 0x1d4a,
+ 0x84ad, 0x1d52,
+ 0x84ae, 0x1d4e,
+ 0x84af, 0x1d46,
+ 0x84b0, 0x1d6a,
+ 0x84b1, 0x1d62,
+ 0x84b2, 0x1d72,
+ 0x84b3, 0x1d5a,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d66,
+ 0x84b6, 0x1d5f,
+ 0x84b7, 0x1d6e,
+ 0x84b8, 0x1d57,
+ 0x84b9, 0x1d79,
+ 0x84ba, 0x1d67,
+ 0x84bb, 0x1d5c,
+ 0x84bc, 0x1d6f,
+ 0x84bd, 0x1d54,
+ 0x84be, 0x1d76,
+ 0x875f, 0x1f04,
+ 0x8761, 0x2089,
+ 0x8762, 0x1f07,
+ 0x8763, 0x2093,
+ 0x8764, 0x1f09,
+ 0x8765, 0x2092,
+ 0x8766, 0x1f0b,
+ 0x8768, 0x2098,
+ 0x8769, 0x1f0e,
+ 0x876b, 0x209c,
+ 0x876c, 0x1f11,
+ 0x876e, 0x209d,
+ 0x8780, 0x1f14,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1278msRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0277, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1278msRKSJVMap2, 790
+};
+
+static Gushort japan1283pvRKSJHMap2[436] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8540, 0x00e8,
+ 0x8580, 0x0186,
+ 0x8581, 0x0128,
+ 0x859f, 0x0147,
+ 0x85de, 0x0187,
+ 0x8640, 0x01a6,
+ 0x8680, 0x01e5,
+ 0x8692, 0x0127,
+ 0x8693, 0x01f7,
+ 0x86a2, 0x1d37,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8780, 0x1db8,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xeb40, 0x0279,
+ 0xeb41, 0x1ecf,
+ 0xeb43, 0x027c,
+ 0xeb50, 0x1ed1,
+ 0xeb52, 0x028b,
+ 0xeb5b, 0x1ed3,
+ 0xeb5e, 0x0297,
+ 0xeb60, 0x1ed6,
+ 0xeb65, 0x029e,
+ 0xeb69, 0x1edb,
+ 0xeb7b, 0x02b4,
+ 0xeb80, 0x02b8,
+ 0xeb81, 0x1eed,
+ 0xeb82, 0x02ba,
+ 0xebb8, 0x02e5,
+ 0xebc8, 0x02ed,
+ 0xebda, 0x02f4,
+ 0xebf0, 0x0303,
+ 0xebfc, 0x030b,
+ 0xec4f, 0x030c,
+ 0xec60, 0x0316,
+ 0xec81, 0x0330,
+ 0xec9f, 0x1eee,
+ 0xeca0, 0x034b,
+ 0xeca1, 0x1eef,
+ 0xeca2, 0x034d,
+ 0xeca3, 0x1ef0,
+ 0xeca4, 0x034f,
+ 0xeca5, 0x1ef1,
+ 0xeca6, 0x0351,
+ 0xeca7, 0x1ef2,
+ 0xeca8, 0x0353,
+ 0xecc1, 0x1ef3,
+ 0xecc2, 0x036d,
+ 0xece1, 0x1ef4,
+ 0xece2, 0x038d,
+ 0xece3, 0x1ef5,
+ 0xece4, 0x038f,
+ 0xece5, 0x1ef6,
+ 0xece6, 0x0391,
+ 0xecec, 0x1ef7,
+ 0xeced, 0x0398,
+ 0xed40, 0x1ef8,
+ 0xed41, 0x039e,
+ 0xed42, 0x1ef9,
+ 0xed43, 0x03a0,
+ 0xed44, 0x1efa,
+ 0xed45, 0x03a2,
+ 0xed46, 0x1efb,
+ 0xed47, 0x03a4,
+ 0xed48, 0x1efc,
+ 0xed49, 0x03a6,
+ 0xed62, 0x1efd,
+ 0xed63, 0x03c0,
+ 0xed80, 0x03dc,
+ 0xed83, 0x1efe,
+ 0xed84, 0x03e0,
+ 0xed85, 0x1eff,
+ 0xed86, 0x03e2,
+ 0xed87, 0x1f00,
+ 0xed88, 0x03e4,
+ 0xed8e, 0x1f01,
+ 0xed8f, 0x03eb,
+ 0xed95, 0x1f02,
+ 0xed9f, 0x03f3,
+ 0xedbf, 0x040b,
+ 0xee40, 0x1d83,
+ 0xee5f, 0x1f04,
+ 0xee6f, 0x1db1,
+ 0xee80, 0x1f14,
+ 0xee82, 0x1dba,
+ 0xee90, 0x02fa,
+ 0xee91, 0x02f9,
+ 0xee92, 0x0301,
+ 0xee93, 0x1dc8,
+ 0xee9a, 0x0300,
+ 0xee9b, 0x1dcf,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1283pvRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0098, 0x00e4, 0x007c },
+ japan1283pvRKSJHMap2, 218
+};
+
+static Gushort japan1290msRKSJHMap2[340] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290msRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0277, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1290msRKSJHMap2, 170
+};
+
+static Gushort japan1290msRKSJVMap2[496] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0x8141, 0x1ecf,
+ 0x8143, 0x204c,
+ 0x8144, 0x2052,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x81a8, 0x02e3,
+ 0x81a9, 0x02e2,
+ 0x81aa, 0x02e0,
+ 0x81ac, 0x204e,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0x849f, 0x1d39,
+ 0x84a0, 0x1d37,
+ 0x84a1, 0x1d47,
+ 0x84a2, 0x1d4f,
+ 0x84a3, 0x1d4b,
+ 0x84a4, 0x1d43,
+ 0x84a5, 0x1d63,
+ 0x84a6, 0x1d5b,
+ 0x84a7, 0x1d6b,
+ 0x84a8, 0x1d53,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d3a,
+ 0x84ab, 0x1d38,
+ 0x84ac, 0x1d4a,
+ 0x84ad, 0x1d52,
+ 0x84ae, 0x1d4e,
+ 0x84af, 0x1d46,
+ 0x84b0, 0x1d6a,
+ 0x84b1, 0x1d62,
+ 0x84b2, 0x1d72,
+ 0x84b3, 0x1d5a,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d66,
+ 0x84b6, 0x1d5f,
+ 0x84b7, 0x1d6e,
+ 0x84b8, 0x1d57,
+ 0x84b9, 0x1d79,
+ 0x84ba, 0x1d67,
+ 0x84bb, 0x1d5c,
+ 0x84bc, 0x1d6f,
+ 0x84bd, 0x1d54,
+ 0x84be, 0x1d76,
+ 0x875f, 0x1f04,
+ 0x8761, 0x2089,
+ 0x8762, 0x1f07,
+ 0x8763, 0x2093,
+ 0x8764, 0x1f09,
+ 0x8765, 0x2092,
+ 0x8766, 0x1f0b,
+ 0x8768, 0x2098,
+ 0x8769, 0x1f0e,
+ 0x876b, 0x209c,
+ 0x876c, 0x1f11,
+ 0x876e, 0x209d,
+ 0x8780, 0x1f14,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290msRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0277, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1290msRKSJVMap2, 248
+};
+
+static Gushort japan1290mspRKSJHMap2[340] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290mspRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1290mspRKSJHMap2, 170
+};
+
+static Gushort japan1290mspRKSJVMap2[496] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x8761, 0x1f66,
+ 0x8762, 0x1da4,
+ 0x8763, 0x1f68,
+ 0x8764, 0x1da6,
+ 0x8765, 0x1f6a,
+ 0x8766, 0x1da8,
+ 0x8768, 0x1f6c,
+ 0x8769, 0x1dab,
+ 0x876b, 0x1f6b,
+ 0x876c, 0x1dae,
+ 0x876e, 0x1f6f,
+ 0x876f, 0x1db1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8784, 0x1f77,
+ 0x8785, 0x1dbd,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xfa40, 0x1f9c,
+ 0xfa4a, 0x1d97,
+ 0xfa54, 0x02ef,
+ 0xfa55, 0x1f45,
+ 0xfa58, 0x1dc2,
+ 0xfa59, 0x1dba,
+ 0xfa5a, 0x1f77,
+ 0xfa5b, 0x0300,
+ 0xfa5c, 0x20a7,
+ 0xfa80, 0x20ca,
+ 0xfad0, 0x07c9,
+ 0xfad1, 0x211a,
+ 0xfb40, 0x2146,
+ 0xfb80, 0x2185,
+ 0xfc40, 0x2202,
+ 0x8141, 0x1ecf,
+ 0x8143, 0x204c,
+ 0x8144, 0x2052,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x81a8, 0x02e3,
+ 0x81a9, 0x02e2,
+ 0x81aa, 0x02e0,
+ 0x81ac, 0x204e,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0x849f, 0x1d39,
+ 0x84a0, 0x1d37,
+ 0x84a1, 0x1d47,
+ 0x84a2, 0x1d4f,
+ 0x84a3, 0x1d4b,
+ 0x84a4, 0x1d43,
+ 0x84a5, 0x1d63,
+ 0x84a6, 0x1d5b,
+ 0x84a7, 0x1d6b,
+ 0x84a8, 0x1d53,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d3a,
+ 0x84ab, 0x1d38,
+ 0x84ac, 0x1d4a,
+ 0x84ad, 0x1d52,
+ 0x84ae, 0x1d4e,
+ 0x84af, 0x1d46,
+ 0x84b0, 0x1d6a,
+ 0x84b1, 0x1d62,
+ 0x84b2, 0x1d72,
+ 0x84b3, 0x1d5a,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d66,
+ 0x84b6, 0x1d5f,
+ 0x84b7, 0x1d6e,
+ 0x84b8, 0x1d57,
+ 0x84b9, 0x1d79,
+ 0x84ba, 0x1d67,
+ 0x84bb, 0x1d5c,
+ 0x84bc, 0x1d6f,
+ 0x84bd, 0x1d54,
+ 0x84be, 0x1d76,
+ 0x875f, 0x1f04,
+ 0x8761, 0x2089,
+ 0x8762, 0x1f07,
+ 0x8763, 0x2093,
+ 0x8764, 0x1f09,
+ 0x8765, 0x2092,
+ 0x8766, 0x1f0b,
+ 0x8768, 0x2098,
+ 0x8769, 0x1f0e,
+ 0x876b, 0x209c,
+ 0x876c, 0x1f11,
+ 0x876e, 0x209d,
+ 0x8780, 0x1f14,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290mspRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan1290mspRKSJVMap2, 248
+};
+
+static Gushort japan1290pvRKSJHMap2[518] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8540, 0x1d83,
+ 0x855e, 0x1f87,
+ 0x857c, 0x205e,
+ 0x8580, 0x2061,
+ 0x8591, 0x1f7d,
+ 0x859f, 0x1d97,
+ 0x85a9, 0x2021,
+ 0x85ab, 0x2067,
+ 0x85b3, 0x1f9c,
+ 0x85bd, 0x206a,
+ 0x85db, 0x1fb0,
+ 0x8640, 0x1db1,
+ 0x8641, 0x1ffa,
+ 0x8642, 0x1db2,
+ 0x8643, 0x1f54,
+ 0x8644, 0x1f56,
+ 0x8645, 0x206f,
+ 0x8646, 0x1db7,
+ 0x8647, 0x1f57,
+ 0x8648, 0x1db3,
+ 0x8649, 0x1f55,
+ 0x864a, 0x1db4,
+ 0x864b, 0x2070,
+ 0x864c, 0x1db5,
+ 0x864e, 0x1f65,
+ 0x864f, 0x1f58,
+ 0x8656, 0x2071,
+ 0x8657, 0x1f64,
+ 0x8658, 0x1f62,
+ 0x865a, 0x1f5f,
+ 0x865d, 0x2072,
+ 0x869b, 0x1dba,
+ 0x869e, 0x2073,
+ 0x869f, 0x1f52,
+ 0x86a0, 0x1f50,
+ 0x86a2, 0x1f53,
+ 0x86a3, 0x2013,
+ 0x86a4, 0x2015,
+ 0x86a5, 0x2014,
+ 0x86a6, 0x2016,
+ 0x86b3, 0x1f7a,
+ 0x86b4, 0x1f78,
+ 0x86b5, 0x2074,
+ 0x86c7, 0x201b,
+ 0x86cb, 0x2075,
+ 0x86cf, 0x1f4e,
+ 0x86d0, 0x1f4d,
+ 0x86d1, 0x1f4c,
+ 0x86d2, 0x1f4b,
+ 0x86d3, 0x200e,
+ 0x8740, 0x2005,
+ 0x8747, 0x1fd6,
+ 0x8748, 0x200c,
+ 0x8749, 0x1fd1,
+ 0x874a, 0x1fca,
+ 0x874b, 0x1dc4,
+ 0x874c, 0x1fd7,
+ 0x874d, 0x1dc2,
+ 0x874e, 0x1fd2,
+ 0x874f, 0x1fcd,
+ 0x8750, 0x1dc3,
+ 0x8751, 0x1fd5,
+ 0x8752, 0x1fd3,
+ 0x8753, 0x1fcf,
+ 0x8754, 0x1fd4,
+ 0x8755, 0x1fd0,
+ 0x8756, 0x1fcb,
+ 0x8758, 0x1fce,
+ 0x8791, 0x207d,
+ 0x8793, 0x1dbd,
+ 0x8798, 0x1fda,
+ 0x8799, 0x1fe5,
+ 0x879a, 0x207f,
+ 0x879b, 0x1fde,
+ 0x879c, 0x1fff,
+ 0x879d, 0x2080,
+ 0x879e, 0x201f,
+ 0x879f, 0x1da1,
+ 0x87a0, 0x1f66,
+ 0x87a1, 0x1da4,
+ 0x87a2, 0x1da2,
+ 0x87a3, 0x1f67,
+ 0x87a4, 0x1ff7,
+ 0x87a5, 0x2087,
+ 0x87a7, 0x1f6a,
+ 0x87a8, 0x1da8,
+ 0x87a9, 0x1f68,
+ 0x87ab, 0x1da6,
+ 0x87ac, 0x1da9,
+ 0x87ad, 0x1daf,
+ 0x87ae, 0x1f6e,
+ 0x87af, 0x1f6c,
+ 0x87b0, 0x1dab,
+ 0x87b1, 0x1f6d,
+ 0x87b2, 0x1f6b,
+ 0x87b3, 0x1dac,
+ 0x87b4, 0x1f6f,
+ 0x87b5, 0x1dae,
+ 0x87bd, 0x1f70,
+ 0x87be, 0x1f73,
+ 0x87c0, 0x1f71,
+ 0x87e5, 0x1dc5,
+ 0x87e8, 0x2083,
+ 0x87fa, 0x1f76,
+ 0x87fb, 0x2081,
+ 0x8840, 0x1dc8,
+ 0x8841, 0x1dcd,
+ 0x8854, 0x1db8,
+ 0x8868, 0x1f16,
+ 0x886a, 0x2079,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xeb41, 0x1ecf,
+ 0xeb50, 0x1ed1,
+ 0xeb5b, 0x1ed3,
+ 0xeb60, 0x1ed6,
+ 0xeb69, 0x1edb,
+ 0xeb81, 0x1eed,
+ 0xec9f, 0x1eee,
+ 0xeca1, 0x1eef,
+ 0xeca3, 0x1ef0,
+ 0xeca5, 0x1ef1,
+ 0xeca7, 0x1ef2,
+ 0xecc1, 0x1ef3,
+ 0xece1, 0x1ef4,
+ 0xece3, 0x1ef5,
+ 0xece5, 0x1ef6,
+ 0xecec, 0x1ef7,
+ 0xed40, 0x1ef8,
+ 0xed42, 0x1ef9,
+ 0xed44, 0x1efa,
+ 0xed46, 0x1efb,
+ 0xed48, 0x1efc,
+ 0xed62, 0x1efd,
+ 0xed83, 0x1efe,
+ 0xed85, 0x1eff,
+ 0xed87, 0x1f00,
+ 0xed8e, 0x1f01,
+ 0xed95, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290pvRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0098, 0x00e4, 0x007c },
+ japan1290pvRKSJHMap2, 259
+};
+
+static Gushort japan1290pvRKSJVMap2[620] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x8540, 0x1d83,
+ 0x855e, 0x1f87,
+ 0x857c, 0x205e,
+ 0x8580, 0x2061,
+ 0x8591, 0x1f7d,
+ 0x859f, 0x1d97,
+ 0x85a9, 0x2021,
+ 0x85ab, 0x2067,
+ 0x85b3, 0x1f9c,
+ 0x85bd, 0x206a,
+ 0x85db, 0x1fb0,
+ 0x8640, 0x1db1,
+ 0x8641, 0x1ffa,
+ 0x8642, 0x1db2,
+ 0x8643, 0x1f54,
+ 0x8644, 0x1f56,
+ 0x8645, 0x206f,
+ 0x8646, 0x1db7,
+ 0x8647, 0x1f57,
+ 0x8648, 0x1db3,
+ 0x8649, 0x1f55,
+ 0x864a, 0x1db4,
+ 0x864b, 0x2070,
+ 0x864c, 0x1db5,
+ 0x864e, 0x1f65,
+ 0x864f, 0x1f58,
+ 0x8656, 0x2071,
+ 0x8657, 0x1f64,
+ 0x8658, 0x1f62,
+ 0x865a, 0x1f5f,
+ 0x865d, 0x2072,
+ 0x869b, 0x1dba,
+ 0x869e, 0x2073,
+ 0x869f, 0x1f52,
+ 0x86a0, 0x1f50,
+ 0x86a2, 0x1f53,
+ 0x86a3, 0x2013,
+ 0x86a4, 0x2015,
+ 0x86a5, 0x2014,
+ 0x86a6, 0x2016,
+ 0x86b3, 0x1f7a,
+ 0x86b4, 0x1f78,
+ 0x86b5, 0x2074,
+ 0x86c7, 0x201b,
+ 0x86cb, 0x2075,
+ 0x86cf, 0x1f4e,
+ 0x86d0, 0x1f4d,
+ 0x86d1, 0x1f4c,
+ 0x86d2, 0x1f4b,
+ 0x86d3, 0x200e,
+ 0x8740, 0x2005,
+ 0x8747, 0x1fd6,
+ 0x8748, 0x200c,
+ 0x8749, 0x1fd1,
+ 0x874a, 0x1fca,
+ 0x874b, 0x1dc4,
+ 0x874c, 0x1fd7,
+ 0x874d, 0x1dc2,
+ 0x874e, 0x1fd2,
+ 0x874f, 0x1fcd,
+ 0x8750, 0x1dc3,
+ 0x8751, 0x1fd5,
+ 0x8752, 0x1fd3,
+ 0x8753, 0x1fcf,
+ 0x8754, 0x1fd4,
+ 0x8755, 0x1fd0,
+ 0x8756, 0x1fcb,
+ 0x8758, 0x1fce,
+ 0x8791, 0x207d,
+ 0x8793, 0x1dbd,
+ 0x8798, 0x1fda,
+ 0x8799, 0x1fe5,
+ 0x879a, 0x207f,
+ 0x879b, 0x1fde,
+ 0x879c, 0x1fff,
+ 0x879d, 0x2080,
+ 0x879e, 0x201f,
+ 0x879f, 0x1da1,
+ 0x87a0, 0x1f66,
+ 0x87a1, 0x1da4,
+ 0x87a2, 0x1da2,
+ 0x87a3, 0x1f67,
+ 0x87a4, 0x1ff7,
+ 0x87a5, 0x2087,
+ 0x87a7, 0x1f6a,
+ 0x87a8, 0x1da8,
+ 0x87a9, 0x1f68,
+ 0x87ab, 0x1da6,
+ 0x87ac, 0x1da9,
+ 0x87ad, 0x1daf,
+ 0x87ae, 0x1f6e,
+ 0x87af, 0x1f6c,
+ 0x87b0, 0x1dab,
+ 0x87b1, 0x1f6d,
+ 0x87b2, 0x1f6b,
+ 0x87b3, 0x1dac,
+ 0x87b4, 0x1f6f,
+ 0x87b5, 0x1dae,
+ 0x87bd, 0x1f70,
+ 0x87be, 0x1f73,
+ 0x87c0, 0x1f71,
+ 0x87e5, 0x1dc5,
+ 0x87e8, 0x2083,
+ 0x87fa, 0x1f76,
+ 0x87fb, 0x2081,
+ 0x8840, 0x1dc8,
+ 0x8841, 0x1dcd,
+ 0x8854, 0x1db8,
+ 0x8868, 0x1f16,
+ 0x886a, 0x2079,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xeb41, 0x1ecf,
+ 0xeb50, 0x1ed1,
+ 0xeb5b, 0x1ed3,
+ 0xeb60, 0x1ed6,
+ 0xeb69, 0x1edb,
+ 0xeb81, 0x1eed,
+ 0xec9f, 0x1eee,
+ 0xeca1, 0x1eef,
+ 0xeca3, 0x1ef0,
+ 0xeca5, 0x1ef1,
+ 0xeca7, 0x1ef2,
+ 0xecc1, 0x1ef3,
+ 0xece1, 0x1ef4,
+ 0xece3, 0x1ef5,
+ 0xece5, 0x1ef6,
+ 0xecec, 0x1ef7,
+ 0xed40, 0x1ef8,
+ 0xed42, 0x1ef9,
+ 0xed44, 0x1efa,
+ 0xed46, 0x1efb,
+ 0xed48, 0x1efc,
+ 0xed62, 0x1efd,
+ 0xed83, 0x1efe,
+ 0xed85, 0x1eff,
+ 0xed87, 0x1f00,
+ 0xed8e, 0x1f01,
+ 0xed95, 0x1f02,
+ 0x8141, 0x1ecf,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0x879f, 0x1f04,
+ 0x87a0, 0x2089,
+ 0x87a1, 0x1f07,
+ 0x87a2, 0x1f05,
+ 0x87a3, 0x208a,
+ 0x87a4, 0x208d,
+ 0x87a6, 0x2091,
+ 0x87a8, 0x1f0b,
+ 0x87a9, 0x2093,
+ 0x87ab, 0x1f09,
+ 0x87ac, 0x1f0c,
+ 0x87ad, 0x1f12,
+ 0x87ae, 0x2097,
+ 0x87b0, 0x1f0e,
+ 0x87b1, 0x209b,
+ 0x87b3, 0x1f0f,
+ 0x87b4, 0x209d,
+ 0x87b5, 0x1f11,
+ 0x87bd, 0x209e,
+ 0x87be, 0x20a1,
+ 0x87bf, 0x20a4,
+ 0x87c0, 0x20a6,
+ 0x87c1, 0x20a5,
+ 0x87fa, 0x2084,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan1290pvRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010,
+ 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018,
+ 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0000,
+ 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0098, 0x00e4, 0x007c },
+ japan1290pvRKSJVMap2, 310
+};
+
+static Gushort japan12AddHMap2[1266] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2474, 0x1f16,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2821, 0x1d37,
+ 0x2822, 0x1d39,
+ 0x2823, 0x1d43,
+ 0x2824, 0x1d47,
+ 0x2825, 0x1d4f,
+ 0x2826, 0x1d4b,
+ 0x2827, 0x1d53,
+ 0x2828, 0x1d63,
+ 0x2829, 0x1d5b,
+ 0x282a, 0x1d6b,
+ 0x282b, 0x1d73,
+ 0x282c, 0x1d38,
+ 0x282d, 0x1d3a,
+ 0x282e, 0x1d46,
+ 0x282f, 0x1d4a,
+ 0x2830, 0x1d52,
+ 0x2831, 0x1d4e,
+ 0x2832, 0x1d5a,
+ 0x2833, 0x1d6a,
+ 0x2834, 0x1d62,
+ 0x2835, 0x1d72,
+ 0x2836, 0x1d82,
+ 0x2837, 0x1d57,
+ 0x2838, 0x1d66,
+ 0x2839, 0x1d5f,
+ 0x283a, 0x1d6e,
+ 0x283b, 0x1d76,
+ 0x283c, 0x1d54,
+ 0x283d, 0x1d67,
+ 0x283e, 0x1d5c,
+ 0x283f, 0x1d6f,
+ 0x2840, 0x1d79,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3032, 0x1f19,
+ 0x3033, 0x0477,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3071, 0x1f1a,
+ 0x3072, 0x04b6,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3133, 0x1f1b,
+ 0x3134, 0x04d6,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1f1c,
+ 0x313a, 0x04dc,
+ 0x313d, 0x1dda,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x0529,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x3267, 0x1f1d,
+ 0x3268, 0x0568,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x05ff,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3562, 0x1f1e,
+ 0x3563, 0x067d,
+ 0x3568, 0x1f1f,
+ 0x3569, 0x0683,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3642, 0x1f20,
+ 0x3643, 0x06bb,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x377d, 0x1f21,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3b41, 0x1f22,
+ 0x3b42, 0x0890,
+ 0x3c21, 0x08cd,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x08f5,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6d, 0x0977,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1f23,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4072, 0x0a96,
+ 0x4079, 0x1e26,
+ 0x407a, 0x1f24,
+ 0x407b, 0x0a9f,
+ 0x407c, 0x1f25,
+ 0x407e, 0x0aa2,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x0aaa,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x4237, 0x1f27,
+ 0x4238, 0x0b18,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432a, 0x0b68,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1f28,
+ 0x4552, 0x1e4c,
+ 0x4553, 0x0c4d,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4655, 0x0cad,
+ 0x465b, 0x1e53,
+ 0x465c, 0x0cb4,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1ec0,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x1f29,
+ 0x472b, 0x0ce1,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x0d1e,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4840, 0x1f2a,
+ 0x4841, 0x0d55,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x0da2,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a53, 0x1f2b,
+ 0x4a54, 0x0e24,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b78, 0x1f2c,
+ 0x4b79, 0x0ea7,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x1f2d,
+ 0x4e7d, 0x0fc5,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5121, 0x1058,
+ 0x5122, 0x1f2e,
+ 0x5123, 0x105a,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5238, 0x1f2f,
+ 0x5239, 0x10ce,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5348, 0x1f30,
+ 0x5349, 0x113c,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x1f31,
+ 0x536d, 0x1160,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1f32,
+ 0x5446, 0x1197,
+ 0x546c, 0x1f33,
+ 0x546d, 0x11be,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5578, 0x1f34,
+ 0x5579, 0x1228,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x567d, 0x1f35,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5928, 0x1f37,
+ 0x5929, 0x1350,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a7a, 0x1f38,
+ 0x5a7b, 0x1400,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5d61, 0x1f39,
+ 0x5d62, 0x1501,
+ 0x5e21, 0x151e,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e56, 0x1f3a,
+ 0x5e57, 0x1554,
+ 0x5e76, 0x1f3b,
+ 0x5e77, 0x1574,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6221, 0x1696,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x6359, 0x1f3c,
+ 0x635a, 0x172d,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6440, 0x1f3d,
+ 0x6441, 0x1772,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6649, 0x1f3e,
+ 0x664a, 0x1837,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x684d, 0x1f3f,
+ 0x684e, 0x18f7,
+ 0x6921, 0x1928,
+ 0x697e, 0x1f40,
+ 0x6a21, 0x1986,
+ 0x6a3c, 0x1f41,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6c21, 0x1a42,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7121, 0x1c18,
+ 0x7159, 0x1f43,
+ 0x715a, 0x1c51,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1f44,
+ 0x7353, 0x1d06,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x7421, 0x1d32,
+ 0x7425, 0x205c,
+ 0x7721, 0x1f45,
+ 0x7727, 0x1f48,
+ 0x7728, 0x0300,
+ 0x7729, 0x02fa,
+ 0x772a, 0x02f9,
+ 0x772e, 0x1f49,
+ 0x773c, 0x1db1,
+ 0x773f, 0x1f54,
+ 0x7740, 0x1db7,
+ 0x7741, 0x1f55,
+ 0x7744, 0x1db4,
+ 0x7747, 0x1f58,
+ 0x7751, 0x0303,
+ 0x7752, 0x1f62,
+ 0x7753, 0x0304,
+ 0x7754, 0x1f63,
+ 0x7757, 0x1f65,
+ 0x7759, 0x1da4,
+ 0x775a, 0x1da1,
+ 0x775b, 0x1f66,
+ 0x775c, 0x1da2,
+ 0x775d, 0x1f67,
+ 0x7760, 0x1da6,
+ 0x7761, 0x1f6a,
+ 0x7762, 0x1da8,
+ 0x7763, 0x1dac,
+ 0x7764, 0x1f6b,
+ 0x7765, 0x1dae,
+ 0x7766, 0x1dab,
+ 0x7767, 0x1f6c,
+ 0x7769, 0x1daf,
+ 0x776a, 0x1f6e,
+ 0x7774, 0x1f75,
+ 0x777a, 0x1dba,
+ 0x777b, 0x1f7b,
+ 0x777e, 0x1f7c,
+ 0x7829, 0x1f7d,
+ 0x7834, 0x1f87,
+ 0x7849, 0x1d83,
+ 0x785d, 0x1f9b,
+ 0x785e, 0x1d97,
+ 0x786b, 0x1f9c,
+ 0x7921, 0x1fb0,
+ 0x7945, 0x1f16,
+ 0x7949, 0x1fca,
+ 0x794b, 0x1dc4,
+ 0x794c, 0x1fcc,
+ 0x794f, 0x1dc3,
+ 0x7950, 0x1fcf,
+ 0x7955, 0x1dc2,
+ 0x7956, 0x1fd4,
+ 0x795d, 0x1fd8,
+ 0x796f, 0x1fe6,
+ 0x7d21, 0x1ecf,
+ 0x7d23, 0x204c,
+ 0x7d24, 0x2052,
+ 0x7d25, 0x1ed1,
+ 0x7d2f, 0x205a,
+ 0x7d30, 0x2053,
+ 0x7d31, 0x2058,
+ 0x7d32, 0x2055,
+ 0x7d33, 0x1edb,
+ 0x7d45, 0x1eee,
+ 0x7d5b, 0x2048,
+ 0x7d6d, 0x02e0,
+ 0x7d71, 0x1ff6,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AddHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AddHMap2, 633
+};
+
+static Gushort japan12AddRKSJHMap2[1270] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x82f2, 0x1f16,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x0477,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88ef, 0x1f1a,
+ 0x88f0, 0x04b6,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8952, 0x1f1b,
+ 0x8953, 0x04d6,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1f1c,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x0529,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89e5, 0x1f1d,
+ 0x89e6, 0x0568,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a80, 0x05be,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x05ff,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8b82, 0x1f1e,
+ 0x8b83, 0x067d,
+ 0x8b88, 0x1f1f,
+ 0x8b89, 0x0683,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc0, 0x1f20,
+ 0x8bc1, 0x06bb,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c80, 0x0736,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c9d, 0x1f21,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e60, 0x1f22,
+ 0x8e61, 0x0890,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x08f5,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8d, 0x0977,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1f23,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f0, 0x0a96,
+ 0x90f7, 0x1e26,
+ 0x90f8, 0x1f24,
+ 0x90f9, 0x0a9f,
+ 0x90fa, 0x1f25,
+ 0x90fc, 0x0aa2,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x0aaa,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91b5, 0x1f27,
+ 0x91b6, 0x0b18,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x9249, 0x0b68,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1f28,
+ 0x9371, 0x1e4c,
+ 0x9372, 0x0c4d,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d3, 0x0cad,
+ 0x93d9, 0x1e53,
+ 0x93da, 0x0cb4,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1ec0,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x1f29,
+ 0x944a, 0x0ce1,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x0d1e,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94be, 0x1f2a,
+ 0x94bf, 0x0d55,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x0da2,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d1, 0x1f2b,
+ 0x95d2, 0x0e24,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x0ea7,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x1f2d,
+ 0x97fb, 0x0fc5,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9941, 0x1f2e,
+ 0x9942, 0x105a,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x99b6, 0x1f2f,
+ 0x99b7, 0x10ce,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a67, 0x1f30,
+ 0x9a68, 0x113c,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x1f31,
+ 0x9a8d, 0x1160,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1f32,
+ 0x9ac4, 0x1197,
+ 0x9aea, 0x1f33,
+ 0x9aeb, 0x11be,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9b98, 0x1f34,
+ 0x9b99, 0x1228,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9bfb, 0x1f35,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d47, 0x1f37,
+ 0x9d48, 0x1350,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9df8, 0x1f38,
+ 0x9df9, 0x1400,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9f81, 0x1f39,
+ 0x9f82, 0x1501,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9fd4, 0x1f3a,
+ 0x9fd5, 0x1554,
+ 0x9ff4, 0x1f3b,
+ 0x9ff5, 0x1574,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe093, 0x1e9e,
+ 0xe094, 0x15cf,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe180, 0x1677,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe278, 0x1f3c,
+ 0xe279, 0x172d,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2be, 0x1f3d,
+ 0xe2bf, 0x1772,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c7, 0x1f3e,
+ 0xe3c8, 0x1837,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4cb, 0x1f3f,
+ 0xe4cc, 0x18f7,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe59e, 0x1f40,
+ 0xe59f, 0x1986,
+ 0xe5ba, 0x1f41,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe940, 0x1c18,
+ 0xe978, 0x1f43,
+ 0xe979, 0x1c51,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1f44,
+ 0xea72, 0x1d06,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xeaa3, 0x205c,
+ 0xec40, 0x1f45,
+ 0xec46, 0x1f48,
+ 0xec47, 0x0300,
+ 0xec48, 0x02fa,
+ 0xec49, 0x02f9,
+ 0xec4d, 0x1f49,
+ 0xec5b, 0x1db1,
+ 0xec5e, 0x1f54,
+ 0xec5f, 0x1db7,
+ 0xec60, 0x1f55,
+ 0xec63, 0x1db4,
+ 0xec66, 0x1f58,
+ 0xec70, 0x0303,
+ 0xec71, 0x1f62,
+ 0xec72, 0x0304,
+ 0xec73, 0x1f63,
+ 0xec76, 0x1f65,
+ 0xec78, 0x1da4,
+ 0xec79, 0x1da1,
+ 0xec7a, 0x1f66,
+ 0xec7b, 0x1da2,
+ 0xec7c, 0x1f67,
+ 0xec80, 0x1da6,
+ 0xec81, 0x1f6a,
+ 0xec82, 0x1da8,
+ 0xec83, 0x1dac,
+ 0xec84, 0x1f6b,
+ 0xec85, 0x1dae,
+ 0xec86, 0x1dab,
+ 0xec87, 0x1f6c,
+ 0xec89, 0x1daf,
+ 0xec8a, 0x1f6e,
+ 0xec94, 0x1f75,
+ 0xec9a, 0x1dba,
+ 0xec9b, 0x1f7b,
+ 0xec9e, 0x1f7c,
+ 0xeca7, 0x1f7d,
+ 0xecb2, 0x1f87,
+ 0xecc7, 0x1d83,
+ 0xecdb, 0x1f9b,
+ 0xecdc, 0x1d97,
+ 0xece9, 0x1f9c,
+ 0xed40, 0x1fb0,
+ 0xed64, 0x1f16,
+ 0xed68, 0x1fca,
+ 0xed6a, 0x1dc4,
+ 0xed6b, 0x1fcc,
+ 0xed6e, 0x1dc3,
+ 0xed6f, 0x1fcf,
+ 0xed74, 0x1dc2,
+ 0xed75, 0x1fd4,
+ 0xed7c, 0x1fd8,
+ 0xed80, 0x1fdb,
+ 0xed8f, 0x1fe6,
+ 0xef40, 0x1ecf,
+ 0xef42, 0x204c,
+ 0xef43, 0x2052,
+ 0xef44, 0x1ed1,
+ 0xef4e, 0x205a,
+ 0xef4f, 0x2053,
+ 0xef50, 0x2058,
+ 0xef51, 0x2055,
+ 0xef52, 0x1edb,
+ 0xef64, 0x1eee,
+ 0xef7a, 0x2048,
+ 0xef8d, 0x02e0,
+ 0xef91, 0x1ff6,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AddRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AddRKSJHMap2, 635
+};
+
+static Gushort japan12AddRKSJVMap2[1384] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x82f2, 0x1f16,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88b0, 0x1f19,
+ 0x88b1, 0x0477,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88ef, 0x1f1a,
+ 0x88f0, 0x04b6,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8952, 0x1f1b,
+ 0x8953, 0x04d6,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1f1c,
+ 0x8959, 0x04dc,
+ 0x895c, 0x1dda,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x0529,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89e5, 0x1f1d,
+ 0x89e6, 0x0568,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a80, 0x05be,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x05ff,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8b82, 0x1f1e,
+ 0x8b83, 0x067d,
+ 0x8b88, 0x1f1f,
+ 0x8b89, 0x0683,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc0, 0x1f20,
+ 0x8bc1, 0x06bb,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c80, 0x0736,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c9d, 0x1f21,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e60, 0x1f22,
+ 0x8e61, 0x0890,
+ 0x8e80, 0x08ae,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x08f5,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8d, 0x0977,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1f23,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f0, 0x0a96,
+ 0x90f7, 0x1e26,
+ 0x90f8, 0x1f24,
+ 0x90f9, 0x0a9f,
+ 0x90fa, 0x1f25,
+ 0x90fc, 0x0aa2,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x0aaa,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91b5, 0x1f27,
+ 0x91b6, 0x0b18,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x9249, 0x0b68,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1f28,
+ 0x9371, 0x1e4c,
+ 0x9372, 0x0c4d,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d3, 0x0cad,
+ 0x93d9, 0x1e53,
+ 0x93da, 0x0cb4,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1ec0,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x1f29,
+ 0x944a, 0x0ce1,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x0d1e,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94be, 0x1f2a,
+ 0x94bf, 0x0d55,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x0da2,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d1, 0x1f2b,
+ 0x95d2, 0x0e24,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9698, 0x1f2c,
+ 0x9699, 0x0ea7,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x1f2d,
+ 0x97fb, 0x0fc5,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9941, 0x1f2e,
+ 0x9942, 0x105a,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x99b6, 0x1f2f,
+ 0x99b7, 0x10ce,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a67, 0x1f30,
+ 0x9a68, 0x113c,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x1f31,
+ 0x9a8d, 0x1160,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1f32,
+ 0x9ac4, 0x1197,
+ 0x9aea, 0x1f33,
+ 0x9aeb, 0x11be,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9b98, 0x1f34,
+ 0x9b99, 0x1228,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9bfb, 0x1f35,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d47, 0x1f37,
+ 0x9d48, 0x1350,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9df8, 0x1f38,
+ 0x9df9, 0x1400,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9f81, 0x1f39,
+ 0x9f82, 0x1501,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9fd4, 0x1f3a,
+ 0x9fd5, 0x1554,
+ 0x9ff4, 0x1f3b,
+ 0x9ff5, 0x1574,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe093, 0x1e9e,
+ 0xe094, 0x15cf,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe180, 0x1677,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe278, 0x1f3c,
+ 0xe279, 0x172d,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2be, 0x1f3d,
+ 0xe2bf, 0x1772,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c7, 0x1f3e,
+ 0xe3c8, 0x1837,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4cb, 0x1f3f,
+ 0xe4cc, 0x18f7,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe59e, 0x1f40,
+ 0xe59f, 0x1986,
+ 0xe5ba, 0x1f41,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe940, 0x1c18,
+ 0xe978, 0x1f43,
+ 0xe979, 0x1c51,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1f44,
+ 0xea72, 0x1d06,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xeaa3, 0x205c,
+ 0xec40, 0x1f45,
+ 0xec46, 0x1f48,
+ 0xec47, 0x0300,
+ 0xec48, 0x02fa,
+ 0xec49, 0x02f9,
+ 0xec4d, 0x1f49,
+ 0xec5b, 0x1db1,
+ 0xec5e, 0x1f54,
+ 0xec5f, 0x1db7,
+ 0xec60, 0x1f55,
+ 0xec63, 0x1db4,
+ 0xec66, 0x1f58,
+ 0xec70, 0x0303,
+ 0xec71, 0x1f62,
+ 0xec72, 0x0304,
+ 0xec73, 0x1f63,
+ 0xec76, 0x1f65,
+ 0xec78, 0x1da4,
+ 0xec79, 0x1da1,
+ 0xec7a, 0x1f66,
+ 0xec7b, 0x1da2,
+ 0xec7c, 0x1f67,
+ 0xec80, 0x1da6,
+ 0xec81, 0x1f6a,
+ 0xec82, 0x1da8,
+ 0xec83, 0x1dac,
+ 0xec84, 0x1f6b,
+ 0xec85, 0x1dae,
+ 0xec86, 0x1dab,
+ 0xec87, 0x1f6c,
+ 0xec89, 0x1daf,
+ 0xec8a, 0x1f6e,
+ 0xec94, 0x1f75,
+ 0xec9a, 0x1dba,
+ 0xec9b, 0x1f7b,
+ 0xec9e, 0x1f7c,
+ 0xeca7, 0x1f7d,
+ 0xecb2, 0x1f87,
+ 0xecc7, 0x1d83,
+ 0xecdb, 0x1f9b,
+ 0xecdc, 0x1d97,
+ 0xece9, 0x1f9c,
+ 0xed40, 0x1fb0,
+ 0xed64, 0x1f16,
+ 0xed68, 0x1fca,
+ 0xed6a, 0x1dc4,
+ 0xed6b, 0x1fcc,
+ 0xed6e, 0x1dc3,
+ 0xed6f, 0x1fcf,
+ 0xed74, 0x1dc2,
+ 0xed75, 0x1fd4,
+ 0xed7c, 0x1fd8,
+ 0xed80, 0x1fdb,
+ 0xed8f, 0x1fe6,
+ 0xef40, 0x1ecf,
+ 0xef42, 0x204c,
+ 0xef43, 0x2052,
+ 0xef44, 0x1ed1,
+ 0xef4e, 0x205a,
+ 0xef4f, 0x2053,
+ 0xef50, 0x2058,
+ 0xef51, 0x2055,
+ 0xef52, 0x1edb,
+ 0xef64, 0x1eee,
+ 0xef7a, 0x2048,
+ 0xef8d, 0x02e0,
+ 0xef91, 0x1ff6,
+ 0x8141, 0x1ecf,
+ 0x8143, 0x204c,
+ 0x8144, 0x2052,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8165, 0x205a,
+ 0x8166, 0x2053,
+ 0x8167, 0x2058,
+ 0x8168, 0x2055,
+ 0x8169, 0x1edb,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x82f3, 0x2048,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0xec78, 0x1f07,
+ 0xec79, 0x1f04,
+ 0xec7a, 0x2089,
+ 0xec7b, 0x1f05,
+ 0xec7c, 0x208a,
+ 0xec7d, 0x2093,
+ 0xec80, 0x1f09,
+ 0xec81, 0x2092,
+ 0xec82, 0x1f0b,
+ 0xec83, 0x1f0f,
+ 0xec84, 0x209c,
+ 0xec85, 0x1f11,
+ 0xec86, 0x1f0e,
+ 0xec87, 0x2098,
+ 0xec88, 0x209b,
+ 0xec89, 0x1f12,
+ 0xec8a, 0x2097,
+ 0xec8b, 0x209d,
+ 0xec8d, 0x20a6,
+ 0xec8e, 0x20a5,
+ 0xec8f, 0x20a1,
+ 0xec90, 0x20a4,
+ 0xec95, 0x2084,
+ 0xef92, 0x208d,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AddRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AddRKSJVMap2, 692
+};
+
+static Gushort japan12AddVMap2[1380] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2474, 0x1f16,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2821, 0x1d37,
+ 0x2822, 0x1d39,
+ 0x2823, 0x1d43,
+ 0x2824, 0x1d47,
+ 0x2825, 0x1d4f,
+ 0x2826, 0x1d4b,
+ 0x2827, 0x1d53,
+ 0x2828, 0x1d63,
+ 0x2829, 0x1d5b,
+ 0x282a, 0x1d6b,
+ 0x282b, 0x1d73,
+ 0x282c, 0x1d38,
+ 0x282d, 0x1d3a,
+ 0x282e, 0x1d46,
+ 0x282f, 0x1d4a,
+ 0x2830, 0x1d52,
+ 0x2831, 0x1d4e,
+ 0x2832, 0x1d5a,
+ 0x2833, 0x1d6a,
+ 0x2834, 0x1d62,
+ 0x2835, 0x1d72,
+ 0x2836, 0x1d82,
+ 0x2837, 0x1d57,
+ 0x2838, 0x1d66,
+ 0x2839, 0x1d5f,
+ 0x283a, 0x1d6e,
+ 0x283b, 0x1d76,
+ 0x283c, 0x1d54,
+ 0x283d, 0x1d67,
+ 0x283e, 0x1d5c,
+ 0x283f, 0x1d6f,
+ 0x2840, 0x1d79,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3032, 0x1f19,
+ 0x3033, 0x0477,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3071, 0x1f1a,
+ 0x3072, 0x04b6,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3133, 0x1f1b,
+ 0x3134, 0x04d6,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1f1c,
+ 0x313a, 0x04dc,
+ 0x313d, 0x1dda,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x0529,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x3267, 0x1f1d,
+ 0x3268, 0x0568,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x05ff,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3562, 0x1f1e,
+ 0x3563, 0x067d,
+ 0x3568, 0x1f1f,
+ 0x3569, 0x0683,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3642, 0x1f20,
+ 0x3643, 0x06bb,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x377d, 0x1f21,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3b41, 0x1f22,
+ 0x3b42, 0x0890,
+ 0x3c21, 0x08cd,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x08f5,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6d, 0x0977,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1f23,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4072, 0x0a96,
+ 0x4079, 0x1e26,
+ 0x407a, 0x1f24,
+ 0x407b, 0x0a9f,
+ 0x407c, 0x1f25,
+ 0x407e, 0x0aa2,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x0aaa,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x4237, 0x1f27,
+ 0x4238, 0x0b18,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432a, 0x0b68,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1f28,
+ 0x4552, 0x1e4c,
+ 0x4553, 0x0c4d,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4655, 0x0cad,
+ 0x465b, 0x1e53,
+ 0x465c, 0x0cb4,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1ec0,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x1f29,
+ 0x472b, 0x0ce1,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x0d1e,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4840, 0x1f2a,
+ 0x4841, 0x0d55,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x0da2,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a53, 0x1f2b,
+ 0x4a54, 0x0e24,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b78, 0x1f2c,
+ 0x4b79, 0x0ea7,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x1f2d,
+ 0x4e7d, 0x0fc5,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5121, 0x1058,
+ 0x5122, 0x1f2e,
+ 0x5123, 0x105a,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5238, 0x1f2f,
+ 0x5239, 0x10ce,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5348, 0x1f30,
+ 0x5349, 0x113c,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x1f31,
+ 0x536d, 0x1160,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1f32,
+ 0x5446, 0x1197,
+ 0x546c, 0x1f33,
+ 0x546d, 0x11be,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5578, 0x1f34,
+ 0x5579, 0x1228,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x567d, 0x1f35,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5928, 0x1f37,
+ 0x5929, 0x1350,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a7a, 0x1f38,
+ 0x5a7b, 0x1400,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5d61, 0x1f39,
+ 0x5d62, 0x1501,
+ 0x5e21, 0x151e,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e56, 0x1f3a,
+ 0x5e57, 0x1554,
+ 0x5e76, 0x1f3b,
+ 0x5e77, 0x1574,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6221, 0x1696,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x6359, 0x1f3c,
+ 0x635a, 0x172d,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6440, 0x1f3d,
+ 0x6441, 0x1772,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6649, 0x1f3e,
+ 0x664a, 0x1837,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x684d, 0x1f3f,
+ 0x684e, 0x18f7,
+ 0x6921, 0x1928,
+ 0x697e, 0x1f40,
+ 0x6a21, 0x1986,
+ 0x6a3c, 0x1f41,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6c21, 0x1a42,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7121, 0x1c18,
+ 0x7159, 0x1f43,
+ 0x715a, 0x1c51,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1f44,
+ 0x7353, 0x1d06,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x7421, 0x1d32,
+ 0x7425, 0x205c,
+ 0x7721, 0x1f45,
+ 0x7727, 0x1f48,
+ 0x7728, 0x0300,
+ 0x7729, 0x02fa,
+ 0x772a, 0x02f9,
+ 0x772e, 0x1f49,
+ 0x773c, 0x1db1,
+ 0x773f, 0x1f54,
+ 0x7740, 0x1db7,
+ 0x7741, 0x1f55,
+ 0x7744, 0x1db4,
+ 0x7747, 0x1f58,
+ 0x7751, 0x0303,
+ 0x7752, 0x1f62,
+ 0x7753, 0x0304,
+ 0x7754, 0x1f63,
+ 0x7757, 0x1f65,
+ 0x7759, 0x1da4,
+ 0x775a, 0x1da1,
+ 0x775b, 0x1f66,
+ 0x775c, 0x1da2,
+ 0x775d, 0x1f67,
+ 0x7760, 0x1da6,
+ 0x7761, 0x1f6a,
+ 0x7762, 0x1da8,
+ 0x7763, 0x1dac,
+ 0x7764, 0x1f6b,
+ 0x7765, 0x1dae,
+ 0x7766, 0x1dab,
+ 0x7767, 0x1f6c,
+ 0x7769, 0x1daf,
+ 0x776a, 0x1f6e,
+ 0x7774, 0x1f75,
+ 0x777a, 0x1dba,
+ 0x777b, 0x1f7b,
+ 0x777e, 0x1f7c,
+ 0x7829, 0x1f7d,
+ 0x7834, 0x1f87,
+ 0x7849, 0x1d83,
+ 0x785d, 0x1f9b,
+ 0x785e, 0x1d97,
+ 0x786b, 0x1f9c,
+ 0x7921, 0x1fb0,
+ 0x7945, 0x1f16,
+ 0x7949, 0x1fca,
+ 0x794b, 0x1dc4,
+ 0x794c, 0x1fcc,
+ 0x794f, 0x1dc3,
+ 0x7950, 0x1fcf,
+ 0x7955, 0x1dc2,
+ 0x7956, 0x1fd4,
+ 0x795d, 0x1fd8,
+ 0x796f, 0x1fe6,
+ 0x7d21, 0x1ecf,
+ 0x7d23, 0x204c,
+ 0x7d24, 0x2052,
+ 0x7d25, 0x1ed1,
+ 0x7d2f, 0x205a,
+ 0x7d30, 0x2053,
+ 0x7d31, 0x2058,
+ 0x7d32, 0x2055,
+ 0x7d33, 0x1edb,
+ 0x7d45, 0x1eee,
+ 0x7d5b, 0x2048,
+ 0x7d6d, 0x02e0,
+ 0x7d71, 0x1ff6,
+ 0x2122, 0x1ecf,
+ 0x2124, 0x204c,
+ 0x2125, 0x2052,
+ 0x2131, 0x1ed1,
+ 0x213c, 0x1ed3,
+ 0x2141, 0x1ed6,
+ 0x2146, 0x205a,
+ 0x2147, 0x2053,
+ 0x2148, 0x2058,
+ 0x2149, 0x2055,
+ 0x214a, 0x1edb,
+ 0x2421, 0x1eee,
+ 0x2423, 0x1eef,
+ 0x2425, 0x1ef0,
+ 0x2427, 0x1ef1,
+ 0x2429, 0x1ef2,
+ 0x2443, 0x1ef3,
+ 0x2463, 0x1ef4,
+ 0x2465, 0x1ef5,
+ 0x2467, 0x1ef6,
+ 0x246e, 0x1ef7,
+ 0x2475, 0x2048,
+ 0x2521, 0x1ef8,
+ 0x2523, 0x1ef9,
+ 0x2525, 0x1efa,
+ 0x2527, 0x1efb,
+ 0x2529, 0x1efc,
+ 0x2543, 0x1efd,
+ 0x2563, 0x1efe,
+ 0x2565, 0x1eff,
+ 0x2567, 0x1f00,
+ 0x256e, 0x1f01,
+ 0x2575, 0x1f02,
+ 0x7759, 0x1f07,
+ 0x775a, 0x1f04,
+ 0x775b, 0x2089,
+ 0x775c, 0x1f05,
+ 0x775d, 0x208a,
+ 0x775e, 0x2093,
+ 0x7760, 0x1f09,
+ 0x7761, 0x2092,
+ 0x7762, 0x1f0b,
+ 0x7763, 0x1f0f,
+ 0x7764, 0x209c,
+ 0x7765, 0x1f11,
+ 0x7766, 0x1f0e,
+ 0x7767, 0x2098,
+ 0x7768, 0x209b,
+ 0x7769, 0x1f12,
+ 0x776a, 0x2097,
+ 0x776b, 0x209d,
+ 0x776d, 0x20a6,
+ 0x776e, 0x20a5,
+ 0x776f, 0x20a1,
+ 0x7770, 0x20a4,
+ 0x7775, 0x2084,
+ 0x7d72, 0x208d,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AddVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AddVMap2, 690
+};
+
+static Gushort japan12AdobeJapan10Map2[70] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AdobeJapan10Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AdobeJapan10Map2, 35
+};
+
+static Gushort japan12AdobeJapan11Map2[70] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AdobeJapan11Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AdobeJapan11Map2, 35
+};
+
+static Gushort japan12AdobeJapan12Map2[74] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AdobeJapan12Enc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AdobeJapan12Map2, 37
+};
+
+static Gushort japan12EUCHMap2[242] = {
+ 0x0000, 0x0000,
+ 0x8ea0, 0x0146,
+ 0xa1a1, 0x0279,
+ 0xa2a1, 0x02d7,
+ 0xa2ba, 0x02e5,
+ 0xa2ca, 0x02ed,
+ 0xa2dc, 0x02f4,
+ 0xa2f2, 0x0303,
+ 0xa2fe, 0x030b,
+ 0xa3b0, 0x030c,
+ 0xa3c1, 0x0316,
+ 0xa3e1, 0x0330,
+ 0xa4a1, 0x034a,
+ 0xa5a1, 0x039d,
+ 0xa6a1, 0x03f3,
+ 0xa6c1, 0x040b,
+ 0xa7a1, 0x0423,
+ 0xa7d1, 0x0444,
+ 0xa8a1, 0x1d37,
+ 0xa8a2, 0x1d39,
+ 0xa8a3, 0x1d43,
+ 0xa8a4, 0x1d47,
+ 0xa8a5, 0x1d4f,
+ 0xa8a6, 0x1d4b,
+ 0xa8a7, 0x1d53,
+ 0xa8a8, 0x1d63,
+ 0xa8a9, 0x1d5b,
+ 0xa8aa, 0x1d6b,
+ 0xa8ab, 0x1d73,
+ 0xa8ac, 0x1d38,
+ 0xa8ad, 0x1d3a,
+ 0xa8ae, 0x1d46,
+ 0xa8af, 0x1d4a,
+ 0xa8b0, 0x1d52,
+ 0xa8b1, 0x1d4e,
+ 0xa8b2, 0x1d5a,
+ 0xa8b3, 0x1d6a,
+ 0xa8b4, 0x1d62,
+ 0xa8b5, 0x1d72,
+ 0xa8b6, 0x1d82,
+ 0xa8b7, 0x1d57,
+ 0xa8b8, 0x1d66,
+ 0xa8b9, 0x1d5f,
+ 0xa8ba, 0x1d6e,
+ 0xa8bb, 0x1d76,
+ 0xa8bc, 0x1d54,
+ 0xa8bd, 0x1d67,
+ 0xa8be, 0x1d5c,
+ 0xa8bf, 0x1d6f,
+ 0xa8c0, 0x1d79,
+ 0xb0a1, 0x0465,
+ 0xb1a1, 0x04c3,
+ 0xb2a1, 0x0521,
+ 0xb3a1, 0x057f,
+ 0xb4a1, 0x05dd,
+ 0xb5a1, 0x063b,
+ 0xb6a1, 0x0699,
+ 0xb7a1, 0x06f7,
+ 0xb8a1, 0x0755,
+ 0xb9a1, 0x07b3,
+ 0xbaa1, 0x0811,
+ 0xbba1, 0x086f,
+ 0xbca1, 0x08cd,
+ 0xbda1, 0x092b,
+ 0xbea1, 0x0989,
+ 0xbfa1, 0x09e7,
+ 0xc0a1, 0x0a45,
+ 0xc1a1, 0x0aa3,
+ 0xc2a1, 0x0b01,
+ 0xc3a1, 0x0b5f,
+ 0xc4a1, 0x0bbd,
+ 0xc5a1, 0x0c1b,
+ 0xc6a1, 0x0c79,
+ 0xc7a1, 0x0cd7,
+ 0xc8a1, 0x0d35,
+ 0xc9a1, 0x0d93,
+ 0xcaa1, 0x0df1,
+ 0xcba1, 0x0e4f,
+ 0xcca1, 0x0ead,
+ 0xcda1, 0x0f0b,
+ 0xcea1, 0x0f69,
+ 0xcfa1, 0x0fc7,
+ 0xd0a1, 0x0ffa,
+ 0xd1a1, 0x1058,
+ 0xd2a1, 0x10b6,
+ 0xd3a1, 0x1114,
+ 0xd4a1, 0x1172,
+ 0xd5a1, 0x11d0,
+ 0xd6a1, 0x122e,
+ 0xd7a1, 0x128c,
+ 0xd8a1, 0x12ea,
+ 0xd9a1, 0x1348,
+ 0xdaa1, 0x13a6,
+ 0xdba1, 0x1404,
+ 0xdca1, 0x1462,
+ 0xdda1, 0x14c0,
+ 0xdea1, 0x151e,
+ 0xdfa1, 0x157c,
+ 0xe0a1, 0x15da,
+ 0xe1a1, 0x1638,
+ 0xe2a1, 0x1696,
+ 0xe3a1, 0x16f4,
+ 0xe4a1, 0x1752,
+ 0xe5a1, 0x17b0,
+ 0xe6a1, 0x180e,
+ 0xe7a1, 0x186c,
+ 0xe8a1, 0x18ca,
+ 0xe9a1, 0x1928,
+ 0xeaa1, 0x1986,
+ 0xeba1, 0x19e4,
+ 0xeca1, 0x1a42,
+ 0xeda1, 0x1aa0,
+ 0xeea1, 0x1afe,
+ 0xefa1, 0x1b5c,
+ 0xf0a1, 0x1bba,
+ 0xf1a1, 0x1c18,
+ 0xf2a1, 0x1c76,
+ 0xf3a1, 0x1cd4,
+ 0xf4a1, 0x1d32,
+ 0xf4a5, 0x205c,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12EUCHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12EUCHMap2, 121
+};
+
+static Gushort japan12EUCVMap2[296] = {
+ 0x0000, 0x0000,
+ 0x8ea0, 0x0146,
+ 0xa1a1, 0x0279,
+ 0xa2a1, 0x02d7,
+ 0xa2ba, 0x02e5,
+ 0xa2ca, 0x02ed,
+ 0xa2dc, 0x02f4,
+ 0xa2f2, 0x0303,
+ 0xa2fe, 0x030b,
+ 0xa3b0, 0x030c,
+ 0xa3c1, 0x0316,
+ 0xa3e1, 0x0330,
+ 0xa4a1, 0x034a,
+ 0xa5a1, 0x039d,
+ 0xa6a1, 0x03f3,
+ 0xa6c1, 0x040b,
+ 0xa7a1, 0x0423,
+ 0xa7d1, 0x0444,
+ 0xa8a1, 0x1d37,
+ 0xa8a2, 0x1d39,
+ 0xa8a3, 0x1d43,
+ 0xa8a4, 0x1d47,
+ 0xa8a5, 0x1d4f,
+ 0xa8a6, 0x1d4b,
+ 0xa8a7, 0x1d53,
+ 0xa8a8, 0x1d63,
+ 0xa8a9, 0x1d5b,
+ 0xa8aa, 0x1d6b,
+ 0xa8ab, 0x1d73,
+ 0xa8ac, 0x1d38,
+ 0xa8ad, 0x1d3a,
+ 0xa8ae, 0x1d46,
+ 0xa8af, 0x1d4a,
+ 0xa8b0, 0x1d52,
+ 0xa8b1, 0x1d4e,
+ 0xa8b2, 0x1d5a,
+ 0xa8b3, 0x1d6a,
+ 0xa8b4, 0x1d62,
+ 0xa8b5, 0x1d72,
+ 0xa8b6, 0x1d82,
+ 0xa8b7, 0x1d57,
+ 0xa8b8, 0x1d66,
+ 0xa8b9, 0x1d5f,
+ 0xa8ba, 0x1d6e,
+ 0xa8bb, 0x1d76,
+ 0xa8bc, 0x1d54,
+ 0xa8bd, 0x1d67,
+ 0xa8be, 0x1d5c,
+ 0xa8bf, 0x1d6f,
+ 0xa8c0, 0x1d79,
+ 0xb0a1, 0x0465,
+ 0xb1a1, 0x04c3,
+ 0xb2a1, 0x0521,
+ 0xb3a1, 0x057f,
+ 0xb4a1, 0x05dd,
+ 0xb5a1, 0x063b,
+ 0xb6a1, 0x0699,
+ 0xb7a1, 0x06f7,
+ 0xb8a1, 0x0755,
+ 0xb9a1, 0x07b3,
+ 0xbaa1, 0x0811,
+ 0xbba1, 0x086f,
+ 0xbca1, 0x08cd,
+ 0xbda1, 0x092b,
+ 0xbea1, 0x0989,
+ 0xbfa1, 0x09e7,
+ 0xc0a1, 0x0a45,
+ 0xc1a1, 0x0aa3,
+ 0xc2a1, 0x0b01,
+ 0xc3a1, 0x0b5f,
+ 0xc4a1, 0x0bbd,
+ 0xc5a1, 0x0c1b,
+ 0xc6a1, 0x0c79,
+ 0xc7a1, 0x0cd7,
+ 0xc8a1, 0x0d35,
+ 0xc9a1, 0x0d93,
+ 0xcaa1, 0x0df1,
+ 0xcba1, 0x0e4f,
+ 0xcca1, 0x0ead,
+ 0xcda1, 0x0f0b,
+ 0xcea1, 0x0f69,
+ 0xcfa1, 0x0fc7,
+ 0xd0a1, 0x0ffa,
+ 0xd1a1, 0x1058,
+ 0xd2a1, 0x10b6,
+ 0xd3a1, 0x1114,
+ 0xd4a1, 0x1172,
+ 0xd5a1, 0x11d0,
+ 0xd6a1, 0x122e,
+ 0xd7a1, 0x128c,
+ 0xd8a1, 0x12ea,
+ 0xd9a1, 0x1348,
+ 0xdaa1, 0x13a6,
+ 0xdba1, 0x1404,
+ 0xdca1, 0x1462,
+ 0xdda1, 0x14c0,
+ 0xdea1, 0x151e,
+ 0xdfa1, 0x157c,
+ 0xe0a1, 0x15da,
+ 0xe1a1, 0x1638,
+ 0xe2a1, 0x1696,
+ 0xe3a1, 0x16f4,
+ 0xe4a1, 0x1752,
+ 0xe5a1, 0x17b0,
+ 0xe6a1, 0x180e,
+ 0xe7a1, 0x186c,
+ 0xe8a1, 0x18ca,
+ 0xe9a1, 0x1928,
+ 0xeaa1, 0x1986,
+ 0xeba1, 0x19e4,
+ 0xeca1, 0x1a42,
+ 0xeda1, 0x1aa0,
+ 0xeea1, 0x1afe,
+ 0xefa1, 0x1b5c,
+ 0xf0a1, 0x1bba,
+ 0xf1a1, 0x1c18,
+ 0xf2a1, 0x1c76,
+ 0xf3a1, 0x1cd4,
+ 0xf4a1, 0x1d32,
+ 0xf4a5, 0x205c,
+ 0xa1a2, 0x1ecf,
+ 0xa1b1, 0x1ed1,
+ 0xa1bc, 0x1ed3,
+ 0xa1c1, 0x1ed6,
+ 0xa1ca, 0x1edb,
+ 0xa1e1, 0x1eed,
+ 0xa4a1, 0x1eee,
+ 0xa4a3, 0x1eef,
+ 0xa4a5, 0x1ef0,
+ 0xa4a7, 0x1ef1,
+ 0xa4a9, 0x1ef2,
+ 0xa4c3, 0x1ef3,
+ 0xa4e3, 0x1ef4,
+ 0xa4e5, 0x1ef5,
+ 0xa4e7, 0x1ef6,
+ 0xa4ee, 0x1ef7,
+ 0xa5a1, 0x1ef8,
+ 0xa5a3, 0x1ef9,
+ 0xa5a5, 0x1efa,
+ 0xa5a7, 0x1efb,
+ 0xa5a9, 0x1efc,
+ 0xa5c3, 0x1efd,
+ 0xa5e3, 0x1efe,
+ 0xa5e5, 0x1eff,
+ 0xa5e7, 0x1f00,
+ 0xa5ee, 0x1f01,
+ 0xa5f5, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12EUCVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12EUCVMap2, 148
+};
+
+static Gushort japan12ExtHMap2[1326] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2169, 0x1d36,
+ 0x216a, 0x02c2,
+ 0x2221, 0x02d7,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2921, 0x00e8,
+ 0x2960, 0x0186,
+ 0x2961, 0x0128,
+ 0x2a21, 0x0147,
+ 0x2a60, 0x0187,
+ 0x2b21, 0x01a6,
+ 0x2b72, 0x0127,
+ 0x2b73, 0x01f7,
+ 0x2c24, 0x1d37,
+ 0x2d21, 0x1d83,
+ 0x2d40, 0x1da1,
+ 0x2d5f, 0x2083,
+ 0x2d60, 0x1db8,
+ 0x2d70, 0x02fa,
+ 0x2d71, 0x02f9,
+ 0x2d72, 0x0301,
+ 0x2d73, 0x1dc8,
+ 0x2d7a, 0x0300,
+ 0x2d7b, 0x1dcf,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313c, 0x1dd9,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c38, 0x1e0c,
+ 0x3c39, 0x08e5,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5350, 0x1e8c,
+ 0x5351, 0x1144,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5672, 0x1e93,
+ 0x5673, 0x1280,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x693c, 0x1eb5,
+ 0x693d, 0x1944,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x6f65, 0x1ec4,
+ 0x6f66, 0x1ba1,
+ 0x7021, 0x1bba,
+ 0x7033, 0x1ec5,
+ 0x7034, 0x1bcd,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x7921, 0x20a7,
+ 0x7a21, 0x2105,
+ 0x7a36, 0x07c9,
+ 0x7a37, 0x211a,
+ 0x7b21, 0x2162,
+ 0x7c21, 0x21c0,
+ 0x7c71, 0x1f9c,
+ 0x7c7b, 0x02ef,
+ 0x7c7c, 0x1f45,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12ExtHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12ExtHMap2, 663
+};
+
+static Gushort japan12ExtRKSJHMap2[1330] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x8189, 0x1d36,
+ 0x818a, 0x02c2,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x8540, 0x00e8,
+ 0x8580, 0x0186,
+ 0x8581, 0x0128,
+ 0x859f, 0x0147,
+ 0x85de, 0x0187,
+ 0x8640, 0x01a6,
+ 0x8680, 0x01e5,
+ 0x8692, 0x0127,
+ 0x8693, 0x01f7,
+ 0x86a2, 0x1d37,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895b, 0x1dd9,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8eb6, 0x1e0c,
+ 0x8eb7, 0x08e5,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a6f, 0x1e8c,
+ 0x9a70, 0x1144,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9bf0, 0x1e93,
+ 0x9bf1, 0x1280,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe093, 0x1e9e,
+ 0xe094, 0x15cf,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe55b, 0x1eb5,
+ 0xe55c, 0x1944,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe885, 0x1ec4,
+ 0xe886, 0x1ba1,
+ 0xe8b1, 0x1ec5,
+ 0xe8b2, 0x1bcd,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12ExtRKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12ExtRKSJHMap2, 665
+};
+
+static Gushort japan12ExtRKSJVMap2[1408] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x8189, 0x1d36,
+ 0x818a, 0x02c2,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x8540, 0x00e8,
+ 0x8580, 0x0186,
+ 0x8581, 0x0128,
+ 0x859f, 0x0147,
+ 0x85de, 0x0187,
+ 0x8640, 0x01a6,
+ 0x8680, 0x01e5,
+ 0x8692, 0x0127,
+ 0x8693, 0x01f7,
+ 0x86a2, 0x1d37,
+ 0x8740, 0x1d83,
+ 0x875f, 0x1da1,
+ 0x877e, 0x2083,
+ 0x8780, 0x1db8,
+ 0x8790, 0x02fa,
+ 0x8791, 0x02f9,
+ 0x8792, 0x0301,
+ 0x8793, 0x1dc8,
+ 0x879a, 0x0300,
+ 0x879b, 0x1dcf,
+ 0x889f, 0x0465,
+ 0x88a0, 0x1dd1,
+ 0x88a1, 0x0467,
+ 0x88b1, 0x1ca2,
+ 0x88b2, 0x0478,
+ 0x88b9, 0x1dd2,
+ 0x88ba, 0x0480,
+ 0x88ec, 0x1dd3,
+ 0x88ed, 0x04b3,
+ 0x88f1, 0x1dd4,
+ 0x88f2, 0x04b8,
+ 0x88fa, 0x1dd5,
+ 0x88fb, 0x04c1,
+ 0x8940, 0x04c3,
+ 0x8949, 0x1dd6,
+ 0x894a, 0x04cd,
+ 0x8954, 0x1dd7,
+ 0x8955, 0x04d8,
+ 0x8958, 0x1dd8,
+ 0x8959, 0x04dc,
+ 0x895b, 0x1dd9,
+ 0x895d, 0x04e0,
+ 0x8961, 0x1ddb,
+ 0x8962, 0x04e5,
+ 0x8980, 0x0502,
+ 0x898b, 0x1ddc,
+ 0x898c, 0x050e,
+ 0x89a6, 0x1ddd,
+ 0x89a7, 0x1cc9,
+ 0x89a8, 0x1dde,
+ 0x89a9, 0x052b,
+ 0x89de, 0x1ddf,
+ 0x89df, 0x0561,
+ 0x89f8, 0x1de0,
+ 0x89f9, 0x057b,
+ 0x89fb, 0x1de1,
+ 0x89fc, 0x057e,
+ 0x8a40, 0x057f,
+ 0x8a41, 0x1de2,
+ 0x8a42, 0x0581,
+ 0x8a61, 0x1961,
+ 0x8a62, 0x05a1,
+ 0x8a68, 0x139f,
+ 0x8a69, 0x05a8,
+ 0x8a80, 0x05be,
+ 0x8a85, 0x1de3,
+ 0x8a86, 0x05c4,
+ 0x8a8b, 0x1de4,
+ 0x8a8c, 0x05ca,
+ 0x8a93, 0x1de5,
+ 0x8a94, 0x05d2,
+ 0x8a96, 0x1731,
+ 0x8a97, 0x05d5,
+ 0x8a9a, 0x1de6,
+ 0x8a9b, 0x05d9,
+ 0x8ac0, 0x1de7,
+ 0x8ac1, 0x1572,
+ 0x8ac2, 0x0600,
+ 0x8acb, 0x1de8,
+ 0x8acc, 0x060a,
+ 0x8ad0, 0x1a20,
+ 0x8ad1, 0x060f,
+ 0x8ae3, 0x1de9,
+ 0x8ae4, 0x0622,
+ 0x8b40, 0x063b,
+ 0x8b4a, 0x1dea,
+ 0x8b4b, 0x0646,
+ 0x8b5f, 0x1deb,
+ 0x8b60, 0x065b,
+ 0x8b80, 0x067a,
+ 0x8ba0, 0x1dec,
+ 0x8ba1, 0x069b,
+ 0x8ba8, 0x1ded,
+ 0x8ba9, 0x06a3,
+ 0x8bc4, 0x1d32,
+ 0x8bc5, 0x06bf,
+ 0x8bcd, 0x1dee,
+ 0x8bce, 0x06c8,
+ 0x8beb, 0x1def,
+ 0x8bec, 0x06e6,
+ 0x8bf2, 0x1df0,
+ 0x8bf3, 0x06ed,
+ 0x8bf9, 0x1df1,
+ 0x8bfa, 0x06f4,
+ 0x8bfb, 0x1df2,
+ 0x8bfc, 0x06f6,
+ 0x8c40, 0x06f7,
+ 0x8c43, 0x1df3,
+ 0x8c44, 0x06fb,
+ 0x8c56, 0x1df4,
+ 0x8c57, 0x070e,
+ 0x8c64, 0x1df5,
+ 0x8c65, 0x071c,
+ 0x8c6d, 0x1df6,
+ 0x8c6e, 0x0725,
+ 0x8c71, 0x1df7,
+ 0x8c72, 0x0729,
+ 0x8c74, 0x1df8,
+ 0x8c75, 0x072c,
+ 0x8c7a, 0x1c0d,
+ 0x8c7b, 0x0732,
+ 0x8c80, 0x0736,
+ 0x8c84, 0x1df9,
+ 0x8c85, 0x073b,
+ 0x8c91, 0x1dfa,
+ 0x8c92, 0x0748,
+ 0x8c99, 0x1dfb,
+ 0x8c9a, 0x0750,
+ 0x8c9e, 0x1dfc,
+ 0x8c9f, 0x0755,
+ 0x8cb2, 0x1dfd,
+ 0x8cb3, 0x0769,
+ 0x8cbf, 0x1dfe,
+ 0x8cc0, 0x0776,
+ 0x8d40, 0x07b3,
+ 0x8d4a, 0x1dff,
+ 0x8d4b, 0x07be,
+ 0x8d56, 0x1e00,
+ 0x8d57, 0x07ca,
+ 0x8d61, 0x1e01,
+ 0x8d62, 0x07d5,
+ 0x8d7b, 0x16dd,
+ 0x8d7c, 0x07ef,
+ 0x8d80, 0x07f2,
+ 0x8d8d, 0x1e02,
+ 0x8d8e, 0x0800,
+ 0x8d94, 0x1e03,
+ 0x8d95, 0x0807,
+ 0x8d99, 0x1e04,
+ 0x8d9a, 0x080c,
+ 0x8dd1, 0x1e05,
+ 0x8dd2, 0x0844,
+ 0x8de5, 0x1e06,
+ 0x8de6, 0x0858,
+ 0x8df2, 0x1e07,
+ 0x8df3, 0x0865,
+ 0x8e40, 0x086f,
+ 0x8e46, 0x1e08,
+ 0x8e47, 0x0876,
+ 0x8e49, 0x1e09,
+ 0x8e4a, 0x0879,
+ 0x8e4b, 0x1e0a,
+ 0x8e4c, 0x087b,
+ 0x8e58, 0x1e0b,
+ 0x8e59, 0x0888,
+ 0x8e80, 0x08ae,
+ 0x8eb6, 0x1e0c,
+ 0x8eb7, 0x08e5,
+ 0x8ec6, 0x1e0d,
+ 0x8ec7, 0x1929,
+ 0x8ec8, 0x08f6,
+ 0x8ed5, 0x1e0e,
+ 0x8ed6, 0x0904,
+ 0x8edb, 0x1e0f,
+ 0x8edd, 0x090b,
+ 0x8f40, 0x092b,
+ 0x8f4a, 0x1e11,
+ 0x8f4b, 0x0936,
+ 0x8f55, 0x1e12,
+ 0x8f56, 0x0941,
+ 0x8f80, 0x096a,
+ 0x8f8c, 0x1e13,
+ 0x8f8e, 0x0978,
+ 0x8f92, 0x1e15,
+ 0x8f94, 0x097e,
+ 0x8fa3, 0x1e17,
+ 0x8fa4, 0x098e,
+ 0x8fb1, 0x1e18,
+ 0x8fb2, 0x099c,
+ 0x8fbd, 0x1e19,
+ 0x8fbe, 0x09a8,
+ 0x8fd3, 0x1e1a,
+ 0x8fd4, 0x09be,
+ 0x8fdd, 0x1e1b,
+ 0x8fde, 0x09c8,
+ 0x8fe2, 0x1e1c,
+ 0x8fe3, 0x09cd,
+ 0x9040, 0x09e7,
+ 0x9049, 0x1e1d,
+ 0x904a, 0x09f1,
+ 0x9078, 0x1e1e,
+ 0x9079, 0x0a20,
+ 0x9080, 0x1e1f,
+ 0x9081, 0x0a27,
+ 0x9089, 0x1e20,
+ 0x908a, 0x0a30,
+ 0x90a0, 0x1e21,
+ 0x90a1, 0x0a47,
+ 0x90c0, 0x1e22,
+ 0x90c1, 0x0a67,
+ 0x90e4, 0x1e23,
+ 0x90e5, 0x0a8b,
+ 0x90ef, 0x1e24,
+ 0x90f1, 0x0a97,
+ 0x90f7, 0x1e26,
+ 0x90f9, 0x0a9f,
+ 0x9140, 0x0aa3,
+ 0x9146, 0x1e28,
+ 0x9147, 0x1a6e,
+ 0x9148, 0x0aab,
+ 0x9158, 0x1e29,
+ 0x9159, 0x0abc,
+ 0x916b, 0x1e2a,
+ 0x916c, 0x0acf,
+ 0x916e, 0x1e2b,
+ 0x916f, 0x0ad2,
+ 0x917e, 0x1e2c,
+ 0x9180, 0x0ae2,
+ 0x9189, 0x1e2d,
+ 0x918a, 0x0aec,
+ 0x91bb, 0x1e2e,
+ 0x91bc, 0x0b1e,
+ 0x91cb, 0x1e2f,
+ 0x91cc, 0x0b2e,
+ 0x91da, 0x1e30,
+ 0x91db, 0x0b3d,
+ 0x91e1, 0x1e31,
+ 0x91e2, 0x0b44,
+ 0x91ed, 0x1e32,
+ 0x91ee, 0x0b50,
+ 0x91f3, 0x1e33,
+ 0x91f5, 0x0b57,
+ 0x91fb, 0x1e35,
+ 0x91fc, 0x0b5e,
+ 0x9240, 0x0b5f,
+ 0x9246, 0x1e36,
+ 0x9247, 0x0b66,
+ 0x9248, 0x1e37,
+ 0x924a, 0x0b69,
+ 0x924c, 0x1e39,
+ 0x924e, 0x0b6d,
+ 0x925c, 0x1e3b,
+ 0x925d, 0x0b7c,
+ 0x9280, 0x0b9e,
+ 0x9290, 0x1e3c,
+ 0x9291, 0x0baf,
+ 0x9295, 0x1e3d,
+ 0x9296, 0x0bb4,
+ 0x929c, 0x1e3e,
+ 0x929d, 0x0bbb,
+ 0x92bb, 0x1e3f,
+ 0x92bc, 0x0bda,
+ 0x92c6, 0x1e40,
+ 0x92c7, 0x0be5,
+ 0x92c8, 0x1e41,
+ 0x92c9, 0x0be7,
+ 0x92cb, 0x1e42,
+ 0x92cc, 0x0bea,
+ 0x92cd, 0x1e43,
+ 0x92ce, 0x0bec,
+ 0x92d9, 0x11b5,
+ 0x92da, 0x0bf8,
+ 0x9340, 0x0c1b,
+ 0x9341, 0x1e44,
+ 0x9342, 0x0c1d,
+ 0x9346, 0x1e45,
+ 0x9347, 0x0c22,
+ 0x934d, 0x1e46,
+ 0x934e, 0x0c29,
+ 0x9355, 0x1e47,
+ 0x9356, 0x0c31,
+ 0x935e, 0x1e48,
+ 0x935f, 0x0c3a,
+ 0x9367, 0x1e49,
+ 0x9368, 0x0c43,
+ 0x936a, 0x1e4a,
+ 0x936b, 0x0c46,
+ 0x9370, 0x1e4b,
+ 0x9372, 0x0c4d,
+ 0x9376, 0x16df,
+ 0x9377, 0x0c52,
+ 0x9380, 0x0c5a,
+ 0x9384, 0x1e4d,
+ 0x9385, 0x0c5f,
+ 0x938e, 0x1450,
+ 0x938f, 0x0c69,
+ 0x9393, 0x1536,
+ 0x9394, 0x0c6e,
+ 0x9398, 0x1e4e,
+ 0x9399, 0x0c73,
+ 0x93bc, 0x1e4f,
+ 0x93bd, 0x0c97,
+ 0x93c0, 0x1e50,
+ 0x93c1, 0x0c9b,
+ 0x93d2, 0x1e51,
+ 0x93d4, 0x0cae,
+ 0x93d9, 0x1e53,
+ 0x93db, 0x0cb5,
+ 0x93df, 0x1e55,
+ 0x93e0, 0x0cba,
+ 0x93e4, 0x1e56,
+ 0x93e6, 0x0cc0,
+ 0x93e8, 0x1e58,
+ 0x93e9, 0x0cc3,
+ 0x93f4, 0x1aed,
+ 0x93f5, 0x0ccf,
+ 0x9440, 0x0cd7,
+ 0x9448, 0x1e59,
+ 0x9449, 0x0ce0,
+ 0x9458, 0x1e5a,
+ 0x9459, 0x0cf0,
+ 0x9476, 0x1e5b,
+ 0x9477, 0x0d0e,
+ 0x9480, 0x0d16,
+ 0x9487, 0x1e5c,
+ 0x9488, 0x1989,
+ 0x9489, 0x1e5d,
+ 0x948a, 0x0d20,
+ 0x948d, 0x1e5e,
+ 0x948e, 0x0d24,
+ 0x94a2, 0x1e5f,
+ 0x94a3, 0x0d39,
+ 0x94ac, 0x1e60,
+ 0x94ad, 0x0d43,
+ 0x94ae, 0x1e61,
+ 0x94af, 0x0d45,
+ 0x94d2, 0x1e62,
+ 0x94d3, 0x0d69,
+ 0x94e0, 0x1e63,
+ 0x94e1, 0x0d77,
+ 0x94f3, 0x1e64,
+ 0x94f4, 0x0d8a,
+ 0x9540, 0x0d93,
+ 0x9541, 0x1e65,
+ 0x9543, 0x0d96,
+ 0x954e, 0x1e67,
+ 0x954f, 0x143b,
+ 0x9550, 0x0da3,
+ 0x9551, 0x1e68,
+ 0x9552, 0x0da5,
+ 0x9554, 0x1e69,
+ 0x9555, 0x0da8,
+ 0x955f, 0x1e6a,
+ 0x9560, 0x0db3,
+ 0x956d, 0x1e6b,
+ 0x956e, 0x0dc1,
+ 0x9570, 0x1e6c,
+ 0x9571, 0x0dc4,
+ 0x9580, 0x0dd2,
+ 0x95c1, 0x1e6d,
+ 0x95c2, 0x0e14,
+ 0x95cb, 0x1e6e,
+ 0x95cc, 0x0e1e,
+ 0x95d8, 0x1e6f,
+ 0x95d9, 0x0e2b,
+ 0x95f7, 0x1e70,
+ 0x95f8, 0x0e4a,
+ 0x9640, 0x0e4f,
+ 0x9641, 0x1e71,
+ 0x9642, 0x0e51,
+ 0x9648, 0x1e72,
+ 0x9649, 0x0e58,
+ 0x966a, 0x1e73,
+ 0x966b, 0x0e7a,
+ 0x9680, 0x0e8e,
+ 0x968a, 0x1d33,
+ 0x968b, 0x0e99,
+ 0x9690, 0x1e74,
+ 0x9691, 0x0e9f,
+ 0x9699, 0x102f,
+ 0x969a, 0x0ea8,
+ 0x96cb, 0x1e75,
+ 0x96cc, 0x0eda,
+ 0x96d7, 0x1e76,
+ 0x96d8, 0x0ee6,
+ 0x96dd, 0x1e77,
+ 0x96de, 0x0eec,
+ 0x96e0, 0x1e78,
+ 0x96e1, 0x0eef,
+ 0x96f7, 0x1935,
+ 0x96f8, 0x1e79,
+ 0x96f9, 0x0f07,
+ 0x96fa, 0x1e7a,
+ 0x96fb, 0x0f09,
+ 0x96fc, 0x1e7b,
+ 0x9740, 0x0f0b,
+ 0x9751, 0x1e7c,
+ 0x9752, 0x0f1d,
+ 0x976f, 0x1e7d,
+ 0x9770, 0x0f3b,
+ 0x9773, 0x1e7e,
+ 0x9774, 0x0f3f,
+ 0x9779, 0x1d34,
+ 0x977a, 0x0f45,
+ 0x9780, 0x0f4a,
+ 0x9789, 0x1e7f,
+ 0x978a, 0x0f54,
+ 0x97c9, 0x1e80,
+ 0x97ca, 0x0f94,
+ 0x97f8, 0x1e81,
+ 0x97fa, 0x0fc4,
+ 0x9840, 0x1e83,
+ 0x9841, 0x0fc8,
+ 0x9850, 0x1e84,
+ 0x9851, 0x0fd8,
+ 0x9855, 0x1777,
+ 0x9856, 0x0fdd,
+ 0x9858, 0x1e85,
+ 0x9859, 0x0fe0,
+ 0x989f, 0x0ffa,
+ 0x98d4, 0x0ea7,
+ 0x98d5, 0x1030,
+ 0x9940, 0x1058,
+ 0x995c, 0x1e86,
+ 0x995d, 0x1075,
+ 0x9966, 0x1e87,
+ 0x9967, 0x107f,
+ 0x996a, 0x1e88,
+ 0x996b, 0x1083,
+ 0x996c, 0x1e89,
+ 0x996d, 0x1085,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a4f, 0x1e8a,
+ 0x9a50, 0x1124,
+ 0x9a59, 0x1e8b,
+ 0x9a5a, 0x112e,
+ 0x9a6f, 0x1e8c,
+ 0x9a70, 0x1144,
+ 0x9a7d, 0x1e8d,
+ 0x9a7e, 0x1152,
+ 0x9a80, 0x1153,
+ 0x9a8b, 0x1e8e,
+ 0x9a8c, 0x115f,
+ 0x9ac2, 0x1e8f,
+ 0x9ac3, 0x1196,
+ 0x9ae2, 0x0bf7,
+ 0x9ae3, 0x11b6,
+ 0x9b40, 0x11d0,
+ 0x9b5c, 0x1e90,
+ 0x9b5d, 0x11ed,
+ 0x9b80, 0x120f,
+ 0x9b83, 0x1e91,
+ 0x9b84, 0x1213,
+ 0x9ba0, 0x1e92,
+ 0x9ba1, 0x1230,
+ 0x9bf0, 0x1e93,
+ 0x9bf1, 0x1280,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9ca2, 0x1e94,
+ 0x9ca3, 0x12ee,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1e95,
+ 0x9d81, 0x1388,
+ 0x9d8c, 0x1e96,
+ 0x9d8d, 0x1394,
+ 0x9d98, 0x05a7,
+ 0x9d99, 0x13a0,
+ 0x9db7, 0x1e97,
+ 0x9db8, 0x13bf,
+ 0x9dcb, 0x1e98,
+ 0x9dcc, 0x13d3,
+ 0x9e40, 0x1404,
+ 0x9e64, 0x1e99,
+ 0x9e65, 0x1429,
+ 0x9e69, 0x1e9a,
+ 0x9e6a, 0x142e,
+ 0x9e77, 0x0da2,
+ 0x9e78, 0x143c,
+ 0x9e80, 0x1443,
+ 0x9e8b, 0x1e9b,
+ 0x9e8c, 0x144f,
+ 0x9e8d, 0x0c68,
+ 0x9e8e, 0x1451,
+ 0x9e94, 0x1e9c,
+ 0x9e95, 0x1458,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0x9fb7, 0x0c6d,
+ 0x9fb8, 0x1537,
+ 0x9fce, 0x1e9d,
+ 0x9fcf, 0x154e,
+ 0x9ff3, 0x05ff,
+ 0x9ff4, 0x1573,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe093, 0x1e9e,
+ 0xe094, 0x15cf,
+ 0xe0a4, 0x1e9f,
+ 0xe0a5, 0x15e0,
+ 0xe0dd, 0x1ea0,
+ 0xe0de, 0x1619,
+ 0xe0f4, 0x1d35,
+ 0xe0f5, 0x1630,
+ 0xe140, 0x1638,
+ 0xe14a, 0x1ea1,
+ 0xe14b, 0x1643,
+ 0xe14f, 0x1ea2,
+ 0xe151, 0x1649,
+ 0xe180, 0x1677,
+ 0xe1a9, 0x1ea4,
+ 0xe1aa, 0x16a1,
+ 0xe1e6, 0x07ee,
+ 0xe1e7, 0x16de,
+ 0xe1e8, 0x0c51,
+ 0xe1e9, 0x16e0,
+ 0xe1ed, 0x1ea5,
+ 0xe1ee, 0x16e5,
+ 0xe240, 0x16f4,
+ 0xe269, 0x1ea6,
+ 0xe26a, 0x171e,
+ 0xe273, 0x1ea7,
+ 0xe274, 0x1728,
+ 0xe27d, 0x05d4,
+ 0xe27e, 0x1732,
+ 0xe280, 0x1733,
+ 0xe2b7, 0x1ea8,
+ 0xe2b8, 0x176b,
+ 0xe2c4, 0x0fdc,
+ 0xe2c5, 0x1778,
+ 0xe2e2, 0x1ea9,
+ 0xe2e3, 0x1796,
+ 0xe2ec, 0x1eaa,
+ 0xe2ed, 0x17a0,
+ 0xe340, 0x17b0,
+ 0xe358, 0x1eab,
+ 0xe359, 0x17c9,
+ 0xe35a, 0x1eac,
+ 0xe35b, 0x17cb,
+ 0xe365, 0x1ead,
+ 0xe366, 0x17d6,
+ 0xe380, 0x17ef,
+ 0xe3c4, 0x1eae,
+ 0xe3c5, 0x1834,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe484, 0x1eaf,
+ 0xe485, 0x18b0,
+ 0xe489, 0x1eb0,
+ 0xe48a, 0x18b5,
+ 0xe492, 0x1eb1,
+ 0xe493, 0x18be,
+ 0xe4b2, 0x1eb2,
+ 0xe4b3, 0x18de,
+ 0xe4b9, 0x1eb3,
+ 0xe4ba, 0x18e5,
+ 0xe4f2, 0x1eb4,
+ 0xe4f3, 0x191e,
+ 0xe540, 0x1928,
+ 0xe541, 0x08f5,
+ 0xe542, 0x192a,
+ 0xe54d, 0x0f05,
+ 0xe54e, 0x1936,
+ 0xe55b, 0x1eb5,
+ 0xe55c, 0x1944,
+ 0xe579, 0x05a0,
+ 0xe57a, 0x1962,
+ 0xe580, 0x1967,
+ 0xe5a2, 0x0d1e,
+ 0xe5a3, 0x198a,
+ 0xe5a5, 0x1eb6,
+ 0xe5a6, 0x198d,
+ 0xe5bb, 0x1eb7,
+ 0xe5bc, 0x19a3,
+ 0xe5ed, 0x1eb8,
+ 0xe5ee, 0x19d5,
+ 0xe640, 0x19e4,
+ 0xe651, 0x1eb9,
+ 0xe652, 0x19f6,
+ 0xe67c, 0x060e,
+ 0xe67d, 0x1a21,
+ 0xe680, 0x1a23,
+ 0xe686, 0x1eba,
+ 0xe687, 0x1a2a,
+ 0xe696, 0x1ebb,
+ 0xe697, 0x1a3a,
+ 0xe6cb, 0x0aaa,
+ 0xe6cc, 0x1a6f,
+ 0xe6e7, 0x1ebc,
+ 0xe6e8, 0x1a8b,
+ 0xe6f2, 0x1ebd,
+ 0xe6f3, 0x1a96,
+ 0xe740, 0x1aa0,
+ 0xe76d, 0x1ebe,
+ 0xe76e, 0x1ace,
+ 0xe780, 0x1adf,
+ 0xe78c, 0x1ebf,
+ 0xe78d, 0x1aec,
+ 0xe78e, 0x1ec0,
+ 0xe78f, 0x1aee,
+ 0xe7a7, 0x1ec1,
+ 0xe7a8, 0x1b07,
+ 0xe7bb, 0x1ec2,
+ 0xe7bc, 0x1b1b,
+ 0xe7d5, 0x1ec3,
+ 0xe7d6, 0x1b35,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe885, 0x1ec4,
+ 0xe886, 0x1ba1,
+ 0xe8b1, 0x1ec5,
+ 0xe8b2, 0x1bcd,
+ 0xe8c3, 0x1ec6,
+ 0xe8c4, 0x1bdf,
+ 0xe8cf, 0x1ec7,
+ 0xe8d0, 0x1beb,
+ 0xe8d5, 0x1ec8,
+ 0xe8d6, 0x1bf1,
+ 0xe8f2, 0x0731,
+ 0xe8f3, 0x1ec9,
+ 0xe8f4, 0x1c0f,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xe9ab, 0x1eca,
+ 0xe9ac, 0x1c83,
+ 0xe9ba, 0x1ecb,
+ 0xe9bb, 0x1c92,
+ 0xe9cb, 0x0477,
+ 0xe9cc, 0x1ecc,
+ 0xe9cd, 0x1ca4,
+ 0xe9f2, 0x0529,
+ 0xe9f3, 0x1cca,
+ 0xea40, 0x1cd4,
+ 0xea70, 0x1ecd,
+ 0xea71, 0x1d05,
+ 0xea80, 0x1d13,
+ 0xea9d, 0x1ece,
+ 0xea9e, 0x1d31,
+ 0xed40, 0x20a7,
+ 0xed80, 0x20e6,
+ 0xedb4, 0x07c9,
+ 0xedb5, 0x211a,
+ 0xee40, 0x2162,
+ 0xee80, 0x21a1,
+ 0xeeef, 0x1f9c,
+ 0xeef9, 0x02ef,
+ 0xeefa, 0x1f45,
+ 0x8141, 0x1ecf,
+ 0x8143, 0x204c,
+ 0x8144, 0x2052,
+ 0x814a, 0x2050,
+ 0x814b, 0x204f,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8165, 0x2059,
+ 0x8166, 0x2054,
+ 0x8167, 0x2057,
+ 0x8168, 0x2056,
+ 0x8169, 0x1edb,
+ 0x818b, 0x204d,
+ 0x818c, 0x2051,
+ 0x818d, 0x205b,
+ 0x81ac, 0x204e,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0x875f, 0x1f04,
+ 0x8780, 0x1f14,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12ExtRKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12ExtRKSJVMap2, 704
+};
+
+static Gushort japan12ExtVMap2[1404] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2169, 0x1d36,
+ 0x216a, 0x02c2,
+ 0x2221, 0x02d7,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2921, 0x00e8,
+ 0x2960, 0x0186,
+ 0x2961, 0x0128,
+ 0x2a21, 0x0147,
+ 0x2a60, 0x0187,
+ 0x2b21, 0x01a6,
+ 0x2b72, 0x0127,
+ 0x2b73, 0x01f7,
+ 0x2c24, 0x1d37,
+ 0x2d21, 0x1d83,
+ 0x2d40, 0x1da1,
+ 0x2d5f, 0x2083,
+ 0x2d60, 0x1db8,
+ 0x2d70, 0x02fa,
+ 0x2d71, 0x02f9,
+ 0x2d72, 0x0301,
+ 0x2d73, 0x1dc8,
+ 0x2d7a, 0x0300,
+ 0x2d7b, 0x1dcf,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313c, 0x1dd9,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c38, 0x1e0c,
+ 0x3c39, 0x08e5,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5350, 0x1e8c,
+ 0x5351, 0x1144,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5672, 0x1e93,
+ 0x5673, 0x1280,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x693c, 0x1eb5,
+ 0x693d, 0x1944,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x6f65, 0x1ec4,
+ 0x6f66, 0x1ba1,
+ 0x7021, 0x1bba,
+ 0x7033, 0x1ec5,
+ 0x7034, 0x1bcd,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x7921, 0x20a7,
+ 0x7a21, 0x2105,
+ 0x7a36, 0x07c9,
+ 0x7a37, 0x211a,
+ 0x7b21, 0x2162,
+ 0x7c21, 0x21c0,
+ 0x7c71, 0x1f9c,
+ 0x7c7b, 0x02ef,
+ 0x7c7c, 0x1f45,
+ 0x2122, 0x1ecf,
+ 0x2124, 0x204c,
+ 0x2125, 0x2052,
+ 0x212b, 0x2050,
+ 0x212c, 0x204f,
+ 0x213c, 0x1ed3,
+ 0x2141, 0x1ed6,
+ 0x2146, 0x2059,
+ 0x2147, 0x2054,
+ 0x2148, 0x2057,
+ 0x2149, 0x2056,
+ 0x214a, 0x1edb,
+ 0x216b, 0x204d,
+ 0x216c, 0x2051,
+ 0x216d, 0x205b,
+ 0x222e, 0x204e,
+ 0x2421, 0x1eee,
+ 0x2423, 0x1eef,
+ 0x2425, 0x1ef0,
+ 0x2427, 0x1ef1,
+ 0x2429, 0x1ef2,
+ 0x2443, 0x1ef3,
+ 0x2463, 0x1ef4,
+ 0x2465, 0x1ef5,
+ 0x2467, 0x1ef6,
+ 0x246e, 0x1ef7,
+ 0x2521, 0x1ef8,
+ 0x2523, 0x1ef9,
+ 0x2525, 0x1efa,
+ 0x2527, 0x1efb,
+ 0x2529, 0x1efc,
+ 0x2543, 0x1efd,
+ 0x2563, 0x1efe,
+ 0x2565, 0x1eff,
+ 0x2567, 0x1f00,
+ 0x256e, 0x1f01,
+ 0x2575, 0x1f02,
+ 0x2d40, 0x1f04,
+ 0x2d60, 0x1f14,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12ExtVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12ExtVMap2, 702
+};
+
+static Gushort japan12HMap2[240] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2821, 0x1d37,
+ 0x2822, 0x1d39,
+ 0x2823, 0x1d43,
+ 0x2824, 0x1d47,
+ 0x2825, 0x1d4f,
+ 0x2826, 0x1d4b,
+ 0x2827, 0x1d53,
+ 0x2828, 0x1d63,
+ 0x2829, 0x1d5b,
+ 0x282a, 0x1d6b,
+ 0x282b, 0x1d73,
+ 0x282c, 0x1d38,
+ 0x282d, 0x1d3a,
+ 0x282e, 0x1d46,
+ 0x282f, 0x1d4a,
+ 0x2830, 0x1d52,
+ 0x2831, 0x1d4e,
+ 0x2832, 0x1d5a,
+ 0x2833, 0x1d6a,
+ 0x2834, 0x1d62,
+ 0x2835, 0x1d72,
+ 0x2836, 0x1d82,
+ 0x2837, 0x1d57,
+ 0x2838, 0x1d66,
+ 0x2839, 0x1d5f,
+ 0x283a, 0x1d6e,
+ 0x283b, 0x1d76,
+ 0x283c, 0x1d54,
+ 0x283d, 0x1d67,
+ 0x283e, 0x1d5c,
+ 0x283f, 0x1d6f,
+ 0x2840, 0x1d79,
+ 0x3021, 0x0465,
+ 0x3121, 0x04c3,
+ 0x3221, 0x0521,
+ 0x3321, 0x057f,
+ 0x3421, 0x05dd,
+ 0x3521, 0x063b,
+ 0x3621, 0x0699,
+ 0x3721, 0x06f7,
+ 0x3821, 0x0755,
+ 0x3921, 0x07b3,
+ 0x3a21, 0x0811,
+ 0x3b21, 0x086f,
+ 0x3c21, 0x08cd,
+ 0x3d21, 0x092b,
+ 0x3e21, 0x0989,
+ 0x3f21, 0x09e7,
+ 0x4021, 0x0a45,
+ 0x4121, 0x0aa3,
+ 0x4221, 0x0b01,
+ 0x4321, 0x0b5f,
+ 0x4421, 0x0bbd,
+ 0x4521, 0x0c1b,
+ 0x4621, 0x0c79,
+ 0x4721, 0x0cd7,
+ 0x4821, 0x0d35,
+ 0x4921, 0x0d93,
+ 0x4a21, 0x0df1,
+ 0x4b21, 0x0e4f,
+ 0x4c21, 0x0ead,
+ 0x4d21, 0x0f0b,
+ 0x4e21, 0x0f69,
+ 0x4f21, 0x0fc7,
+ 0x5021, 0x0ffa,
+ 0x5121, 0x1058,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5421, 0x1172,
+ 0x5521, 0x11d0,
+ 0x5621, 0x122e,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5921, 0x1348,
+ 0x5a21, 0x13a6,
+ 0x5b21, 0x1404,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5f21, 0x157c,
+ 0x6021, 0x15da,
+ 0x6121, 0x1638,
+ 0x6221, 0x1696,
+ 0x6321, 0x16f4,
+ 0x6421, 0x1752,
+ 0x6521, 0x17b0,
+ 0x6621, 0x180e,
+ 0x6721, 0x186c,
+ 0x6821, 0x18ca,
+ 0x6921, 0x1928,
+ 0x6a21, 0x1986,
+ 0x6b21, 0x19e4,
+ 0x6c21, 0x1a42,
+ 0x6d21, 0x1aa0,
+ 0x6e21, 0x1afe,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x7321, 0x1cd4,
+ 0x7421, 0x1d32,
+ 0x7425, 0x205c,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12HEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12HMap2, 120
+};
+
+static Gushort japan12HankakuMap2[4] = {
+ 0x0000, 0x0000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12HankakuEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x00e7, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x0204, 0x0205,
+ 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020b, 0x020c, 0x020d,
+ 0x0156, 0x020e, 0x020f, 0x0210, 0x0211, 0x0212, 0x0213, 0x0214,
+ 0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021a, 0x021b, 0x021c,
+ 0x0000, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x021d, 0x021e, 0x021f, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224,
+ 0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022a, 0x022b, 0x022c,
+ 0x022d, 0x022e, 0x022f, 0x0230, 0x0231, 0x0232, 0x0233, 0x0234,
+ 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x023a, 0x0184, 0x0185 },
+ japan12HankakuMap2, 2
+};
+
+static Gushort japan12HiraganaMap2[4] = {
+ 0x0000, 0x0000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12HiraganaEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0203, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x0204, 0x0205,
+ 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020b, 0x020c, 0x020d,
+ 0x0156, 0x020e, 0x020f, 0x0210, 0x0211, 0x0212, 0x0213, 0x0214,
+ 0x0215, 0x0216, 0x0217, 0x0218, 0x0219, 0x021a, 0x021b, 0x021c,
+ 0x021d, 0x021e, 0x021f, 0x0220, 0x0221, 0x0222, 0x0223, 0x0224,
+ 0x0225, 0x0226, 0x0227, 0x0228, 0x0229, 0x022a, 0x022b, 0x022c,
+ 0x022d, 0x022e, 0x022f, 0x0230, 0x0231, 0x0232, 0x0233, 0x0234,
+ 0x0235, 0x0236, 0x0237, 0x0238, 0x0239, 0x023a, 0x0184, 0x0185,
+ 0x023b, 0x023c, 0x023d, 0x0000, 0x0000, 0x0000, 0x023e, 0x023f,
+ 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,
+ 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f,
+ 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12HiraganaMap2, 2
+};
+
+static Gushort japan12KatakanaMap2[4] = {
+ 0x0000, 0x0000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12KatakanaEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0187, 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e,
+ 0x018f, 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196,
+ 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
+ 0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12KatakanaMap2, 2
+};
+
+static Gushort japan12NWPHMap2[1522] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2169, 0x1d36,
+ 0x216a, 0x02c2,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2921, 0x00e8,
+ 0x2960, 0x0186,
+ 0x2961, 0x0128,
+ 0x2a21, 0x0147,
+ 0x2a60, 0x0187,
+ 0x2b21, 0x01a6,
+ 0x2b72, 0x0127,
+ 0x2b73, 0x01f7,
+ 0x2c24, 0x1d37,
+ 0x2d21, 0x1d83,
+ 0x2d40, 0x1da1,
+ 0x2d60, 0x1db8,
+ 0x2d70, 0x02fa,
+ 0x2d71, 0x02f9,
+ 0x2d72, 0x0301,
+ 0x2d73, 0x1dc8,
+ 0x2d7a, 0x0300,
+ 0x2d7b, 0x1dcf,
+ 0x2e21, 0x0282,
+ 0x2e22, 0x02a1,
+ 0x2e23, 0x0305,
+ 0x2e24, 0x02c8,
+ 0x2e25, 0x02cb,
+ 0x2e26, 0x02cd,
+ 0x2e27, 0x029f,
+ 0x2e28, 0x02a2,
+ 0x2e2a, 0x02ce,
+ 0x2e2b, 0x02b4,
+ 0x2e2c, 0x027c,
+ 0x2e2d, 0x02b5,
+ 0x2e2e, 0x027d,
+ 0x2e2f, 0x0297,
+ 0x2e30, 0x030c,
+ 0x2e3a, 0x027f,
+ 0x2e3c, 0x02bb,
+ 0x2e3d, 0x02b9,
+ 0x2e3e, 0x02bc,
+ 0x2e3f, 0x0281,
+ 0x2e40, 0x02cf,
+ 0x2e41, 0x0316,
+ 0x2e5b, 0x02a6,
+ 0x2e5c, 0x02c7,
+ 0x2e5d, 0x02a7,
+ 0x2e5e, 0x0288,
+ 0x2e5f, 0x028a,
+ 0x2e60, 0x0286,
+ 0x2e61, 0x0330,
+ 0x2e7b, 0x02a8,
+ 0x2e7c, 0x029b,
+ 0x2e7d, 0x02a9,
+ 0x2e7e, 0x0289,
+ 0x2f21, 0x027b,
+ 0x2f22, 0x02ae,
+ 0x2f24, 0x027a,
+ 0x2f25, 0x027e,
+ 0x2f26, 0x03ee,
+ 0x2f27, 0x039d,
+ 0x2f28, 0x039f,
+ 0x2f29, 0x03a1,
+ 0x2f2a, 0x03a3,
+ 0x2f2b, 0x03a5,
+ 0x2f2c, 0x03df,
+ 0x2f2d, 0x03e1,
+ 0x2f2e, 0x03e3,
+ 0x2f2f, 0x03bf,
+ 0x2f30, 0x0294,
+ 0x2f31, 0x039e,
+ 0x2f32, 0x03a0,
+ 0x2f33, 0x03a2,
+ 0x2f34, 0x03a4,
+ 0x2f35, 0x03a6,
+ 0x2f37, 0x03a9,
+ 0x2f38, 0x03ab,
+ 0x2f39, 0x03ad,
+ 0x2f3a, 0x03af,
+ 0x2f3b, 0x03b1,
+ 0x2f3c, 0x03b3,
+ 0x2f3d, 0x03b5,
+ 0x2f3e, 0x03b7,
+ 0x2f3f, 0x03b9,
+ 0x2f40, 0x03bb,
+ 0x2f41, 0x03bd,
+ 0x2f42, 0x03c0,
+ 0x2f43, 0x03c2,
+ 0x2f44, 0x03c4,
+ 0x2f45, 0x03c6,
+ 0x2f4b, 0x03ce,
+ 0x2f4c, 0x03d1,
+ 0x2f4d, 0x03d4,
+ 0x2f4e, 0x03d7,
+ 0x2f4f, 0x03da,
+ 0x2f54, 0x03e0,
+ 0x2f55, 0x03e2,
+ 0x2f56, 0x03e4,
+ 0x2f5c, 0x03eb,
+ 0x2f5d, 0x03ef,
+ 0x2f5e, 0x0283,
+ 0x2f60, 0x03ec,
+ 0x2f62, 0x03ea,
+ 0x2f63, 0x03f1,
+ 0x2f65, 0x03f0,
+ 0x2f66, 0x03a8,
+ 0x2f67, 0x03aa,
+ 0x2f68, 0x03ac,
+ 0x2f69, 0x03ae,
+ 0x2f6a, 0x03b0,
+ 0x2f6b, 0x03b2,
+ 0x2f6c, 0x03b4,
+ 0x2f6d, 0x03b6,
+ 0x2f6e, 0x03b8,
+ 0x2f6f, 0x03ba,
+ 0x2f70, 0x03bc,
+ 0x2f71, 0x03be,
+ 0x2f72, 0x03c1,
+ 0x2f73, 0x03c3,
+ 0x2f74, 0x03c5,
+ 0x2f75, 0x03cc,
+ 0x2f77, 0x03cf,
+ 0x2f79, 0x03d2,
+ 0x2f7b, 0x03d5,
+ 0x2f7d, 0x03d8,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313c, 0x1dd9,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c38, 0x1e0c,
+ 0x3c39, 0x08e5,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5350, 0x1e8c,
+ 0x5351, 0x1144,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5672, 0x1e93,
+ 0x5673, 0x1280,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x693c, 0x1eb5,
+ 0x693d, 0x1944,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x6f65, 0x1ec4,
+ 0x6f66, 0x1ba1,
+ 0x7021, 0x1bba,
+ 0x7033, 0x1ec5,
+ 0x7034, 0x1bcd,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12NWPHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12NWPHMap2, 761
+};
+
+static Gushort japan12NWPVMap2[1618] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2169, 0x1d36,
+ 0x216a, 0x02c2,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2921, 0x00e8,
+ 0x2960, 0x0186,
+ 0x2961, 0x0128,
+ 0x2a21, 0x0147,
+ 0x2a60, 0x0187,
+ 0x2b21, 0x01a6,
+ 0x2b72, 0x0127,
+ 0x2b73, 0x01f7,
+ 0x2c24, 0x1d37,
+ 0x2d21, 0x1d83,
+ 0x2d40, 0x1da1,
+ 0x2d60, 0x1db8,
+ 0x2d70, 0x02fa,
+ 0x2d71, 0x02f9,
+ 0x2d72, 0x0301,
+ 0x2d73, 0x1dc8,
+ 0x2d7a, 0x0300,
+ 0x2d7b, 0x1dcf,
+ 0x2e21, 0x0282,
+ 0x2e22, 0x02a1,
+ 0x2e23, 0x0305,
+ 0x2e24, 0x02c8,
+ 0x2e25, 0x02cb,
+ 0x2e26, 0x02cd,
+ 0x2e27, 0x029f,
+ 0x2e28, 0x02a2,
+ 0x2e2a, 0x02ce,
+ 0x2e2b, 0x02b4,
+ 0x2e2c, 0x027c,
+ 0x2e2d, 0x02b5,
+ 0x2e2e, 0x027d,
+ 0x2e2f, 0x0297,
+ 0x2e30, 0x030c,
+ 0x2e3a, 0x027f,
+ 0x2e3c, 0x02bb,
+ 0x2e3d, 0x02b9,
+ 0x2e3e, 0x02bc,
+ 0x2e3f, 0x0281,
+ 0x2e40, 0x02cf,
+ 0x2e41, 0x0316,
+ 0x2e5b, 0x02a6,
+ 0x2e5c, 0x02c7,
+ 0x2e5d, 0x02a7,
+ 0x2e5e, 0x0288,
+ 0x2e5f, 0x028a,
+ 0x2e60, 0x0286,
+ 0x2e61, 0x0330,
+ 0x2e7b, 0x02a8,
+ 0x2e7c, 0x029b,
+ 0x2e7d, 0x02a9,
+ 0x2e7e, 0x0289,
+ 0x2f21, 0x027b,
+ 0x2f22, 0x02ae,
+ 0x2f24, 0x027a,
+ 0x2f25, 0x027e,
+ 0x2f26, 0x03ee,
+ 0x2f27, 0x039d,
+ 0x2f28, 0x039f,
+ 0x2f29, 0x03a1,
+ 0x2f2a, 0x03a3,
+ 0x2f2b, 0x03a5,
+ 0x2f2c, 0x03df,
+ 0x2f2d, 0x03e1,
+ 0x2f2e, 0x03e3,
+ 0x2f2f, 0x03bf,
+ 0x2f30, 0x0294,
+ 0x2f31, 0x039e,
+ 0x2f32, 0x03a0,
+ 0x2f33, 0x03a2,
+ 0x2f34, 0x03a4,
+ 0x2f35, 0x03a6,
+ 0x2f37, 0x03a9,
+ 0x2f38, 0x03ab,
+ 0x2f39, 0x03ad,
+ 0x2f3a, 0x03af,
+ 0x2f3b, 0x03b1,
+ 0x2f3c, 0x03b3,
+ 0x2f3d, 0x03b5,
+ 0x2f3e, 0x03b7,
+ 0x2f3f, 0x03b9,
+ 0x2f40, 0x03bb,
+ 0x2f41, 0x03bd,
+ 0x2f42, 0x03c0,
+ 0x2f43, 0x03c2,
+ 0x2f44, 0x03c4,
+ 0x2f45, 0x03c6,
+ 0x2f4b, 0x03ce,
+ 0x2f4c, 0x03d1,
+ 0x2f4d, 0x03d4,
+ 0x2f4e, 0x03d7,
+ 0x2f4f, 0x03da,
+ 0x2f54, 0x03e0,
+ 0x2f55, 0x03e2,
+ 0x2f56, 0x03e4,
+ 0x2f5c, 0x03eb,
+ 0x2f5d, 0x03ef,
+ 0x2f5e, 0x0283,
+ 0x2f60, 0x03ec,
+ 0x2f62, 0x03ea,
+ 0x2f63, 0x03f1,
+ 0x2f65, 0x03f0,
+ 0x2f66, 0x03a8,
+ 0x2f67, 0x03aa,
+ 0x2f68, 0x03ac,
+ 0x2f69, 0x03ae,
+ 0x2f6a, 0x03b0,
+ 0x2f6b, 0x03b2,
+ 0x2f6c, 0x03b4,
+ 0x2f6d, 0x03b6,
+ 0x2f6e, 0x03b8,
+ 0x2f6f, 0x03ba,
+ 0x2f70, 0x03bc,
+ 0x2f71, 0x03be,
+ 0x2f72, 0x03c1,
+ 0x2f73, 0x03c3,
+ 0x2f74, 0x03c5,
+ 0x2f75, 0x03cc,
+ 0x2f77, 0x03cf,
+ 0x2f79, 0x03d2,
+ 0x2f7b, 0x03d5,
+ 0x2f7d, 0x03d8,
+ 0x3021, 0x0465,
+ 0x3022, 0x1dd1,
+ 0x3023, 0x0467,
+ 0x3033, 0x1ca2,
+ 0x3034, 0x0478,
+ 0x303b, 0x1dd2,
+ 0x303c, 0x0480,
+ 0x306e, 0x1dd3,
+ 0x306f, 0x04b3,
+ 0x3073, 0x1dd4,
+ 0x3074, 0x04b8,
+ 0x307c, 0x1dd5,
+ 0x307d, 0x04c1,
+ 0x3121, 0x04c3,
+ 0x312a, 0x1dd6,
+ 0x312b, 0x04cd,
+ 0x3135, 0x1dd7,
+ 0x3136, 0x04d8,
+ 0x3139, 0x1dd8,
+ 0x313a, 0x04dc,
+ 0x313c, 0x1dd9,
+ 0x313e, 0x04e0,
+ 0x3142, 0x1ddb,
+ 0x3143, 0x04e5,
+ 0x316b, 0x1ddc,
+ 0x316c, 0x050e,
+ 0x3221, 0x0521,
+ 0x3228, 0x1ddd,
+ 0x3229, 0x1cc9,
+ 0x322a, 0x1dde,
+ 0x322b, 0x052b,
+ 0x3260, 0x1ddf,
+ 0x3261, 0x0561,
+ 0x327a, 0x1de0,
+ 0x327b, 0x057b,
+ 0x327d, 0x1de1,
+ 0x327e, 0x057e,
+ 0x3321, 0x057f,
+ 0x3322, 0x1de2,
+ 0x3323, 0x0581,
+ 0x3342, 0x1961,
+ 0x3343, 0x05a1,
+ 0x3349, 0x139f,
+ 0x334a, 0x05a8,
+ 0x3365, 0x1de3,
+ 0x3366, 0x05c4,
+ 0x336b, 0x1de4,
+ 0x336c, 0x05ca,
+ 0x3373, 0x1de5,
+ 0x3374, 0x05d2,
+ 0x3376, 0x1731,
+ 0x3377, 0x05d5,
+ 0x337a, 0x1de6,
+ 0x337b, 0x05d9,
+ 0x3421, 0x05dd,
+ 0x3442, 0x1de7,
+ 0x3443, 0x1572,
+ 0x3444, 0x0600,
+ 0x344d, 0x1de8,
+ 0x344e, 0x060a,
+ 0x3452, 0x1a20,
+ 0x3453, 0x060f,
+ 0x3465, 0x1de9,
+ 0x3466, 0x0622,
+ 0x3521, 0x063b,
+ 0x352b, 0x1dea,
+ 0x352c, 0x0646,
+ 0x3540, 0x1deb,
+ 0x3541, 0x065b,
+ 0x3621, 0x0699,
+ 0x3622, 0x1dec,
+ 0x3623, 0x069b,
+ 0x362a, 0x1ded,
+ 0x362b, 0x06a3,
+ 0x3646, 0x1d32,
+ 0x3647, 0x06bf,
+ 0x364f, 0x1dee,
+ 0x3650, 0x06c8,
+ 0x366d, 0x1def,
+ 0x366e, 0x06e6,
+ 0x3674, 0x1df0,
+ 0x3675, 0x06ed,
+ 0x367b, 0x1df1,
+ 0x367c, 0x06f4,
+ 0x367d, 0x1df2,
+ 0x367e, 0x06f6,
+ 0x3721, 0x06f7,
+ 0x3724, 0x1df3,
+ 0x3725, 0x06fb,
+ 0x3737, 0x1df4,
+ 0x3738, 0x070e,
+ 0x3745, 0x1df5,
+ 0x3746, 0x071c,
+ 0x374e, 0x1df6,
+ 0x374f, 0x0725,
+ 0x3752, 0x1df7,
+ 0x3753, 0x0729,
+ 0x3755, 0x1df8,
+ 0x3756, 0x072c,
+ 0x375b, 0x1c0d,
+ 0x375c, 0x0732,
+ 0x3764, 0x1df9,
+ 0x3765, 0x073b,
+ 0x3771, 0x1dfa,
+ 0x3772, 0x0748,
+ 0x3779, 0x1dfb,
+ 0x377a, 0x0750,
+ 0x377e, 0x1dfc,
+ 0x3821, 0x0755,
+ 0x3834, 0x1dfd,
+ 0x3835, 0x0769,
+ 0x3841, 0x1dfe,
+ 0x3842, 0x0776,
+ 0x3921, 0x07b3,
+ 0x392b, 0x1dff,
+ 0x392c, 0x07be,
+ 0x3937, 0x1e00,
+ 0x3938, 0x07ca,
+ 0x3942, 0x1e01,
+ 0x3943, 0x07d5,
+ 0x395c, 0x16dd,
+ 0x395d, 0x07ef,
+ 0x396d, 0x1e02,
+ 0x396e, 0x0800,
+ 0x3974, 0x1e03,
+ 0x3975, 0x0807,
+ 0x3979, 0x1e04,
+ 0x397a, 0x080c,
+ 0x3a21, 0x0811,
+ 0x3a53, 0x1e05,
+ 0x3a54, 0x0844,
+ 0x3a67, 0x1e06,
+ 0x3a68, 0x0858,
+ 0x3a74, 0x1e07,
+ 0x3a75, 0x0865,
+ 0x3b21, 0x086f,
+ 0x3b27, 0x1e08,
+ 0x3b28, 0x0876,
+ 0x3b2a, 0x1e09,
+ 0x3b2b, 0x0879,
+ 0x3b2c, 0x1e0a,
+ 0x3b2d, 0x087b,
+ 0x3b39, 0x1e0b,
+ 0x3b3a, 0x0888,
+ 0x3c21, 0x08cd,
+ 0x3c38, 0x1e0c,
+ 0x3c39, 0x08e5,
+ 0x3c48, 0x1e0d,
+ 0x3c49, 0x1929,
+ 0x3c4a, 0x08f6,
+ 0x3c57, 0x1e0e,
+ 0x3c58, 0x0904,
+ 0x3c5d, 0x1e0f,
+ 0x3c5f, 0x090b,
+ 0x3d21, 0x092b,
+ 0x3d2b, 0x1e11,
+ 0x3d2c, 0x0936,
+ 0x3d36, 0x1e12,
+ 0x3d37, 0x0941,
+ 0x3d6c, 0x1e13,
+ 0x3d6e, 0x0978,
+ 0x3d72, 0x1e15,
+ 0x3d74, 0x097e,
+ 0x3e21, 0x0989,
+ 0x3e25, 0x1e17,
+ 0x3e26, 0x098e,
+ 0x3e33, 0x1e18,
+ 0x3e34, 0x099c,
+ 0x3e3f, 0x1e19,
+ 0x3e40, 0x09a8,
+ 0x3e55, 0x1e1a,
+ 0x3e56, 0x09be,
+ 0x3e5f, 0x1e1b,
+ 0x3e60, 0x09c8,
+ 0x3e64, 0x1e1c,
+ 0x3e65, 0x09cd,
+ 0x3f21, 0x09e7,
+ 0x3f2a, 0x1e1d,
+ 0x3f2b, 0x09f1,
+ 0x3f59, 0x1e1e,
+ 0x3f5a, 0x0a20,
+ 0x3f60, 0x1e1f,
+ 0x3f61, 0x0a27,
+ 0x3f69, 0x1e20,
+ 0x3f6a, 0x0a30,
+ 0x4021, 0x0a45,
+ 0x4022, 0x1e21,
+ 0x4023, 0x0a47,
+ 0x4042, 0x1e22,
+ 0x4043, 0x0a67,
+ 0x4066, 0x1e23,
+ 0x4067, 0x0a8b,
+ 0x4071, 0x1e24,
+ 0x4073, 0x0a97,
+ 0x4079, 0x1e26,
+ 0x407b, 0x0a9f,
+ 0x4121, 0x0aa3,
+ 0x4127, 0x1e28,
+ 0x4128, 0x1a6e,
+ 0x4129, 0x0aab,
+ 0x4139, 0x1e29,
+ 0x413a, 0x0abc,
+ 0x414c, 0x1e2a,
+ 0x414d, 0x0acf,
+ 0x414f, 0x1e2b,
+ 0x4150, 0x0ad2,
+ 0x415f, 0x1e2c,
+ 0x4160, 0x0ae2,
+ 0x4169, 0x1e2d,
+ 0x416a, 0x0aec,
+ 0x4221, 0x0b01,
+ 0x423d, 0x1e2e,
+ 0x423e, 0x0b1e,
+ 0x424d, 0x1e2f,
+ 0x424e, 0x0b2e,
+ 0x425c, 0x1e30,
+ 0x425d, 0x0b3d,
+ 0x4263, 0x1e31,
+ 0x4264, 0x0b44,
+ 0x426f, 0x1e32,
+ 0x4270, 0x0b50,
+ 0x4275, 0x1e33,
+ 0x4277, 0x0b57,
+ 0x427d, 0x1e35,
+ 0x427e, 0x0b5e,
+ 0x4321, 0x0b5f,
+ 0x4327, 0x1e36,
+ 0x4328, 0x0b66,
+ 0x4329, 0x1e37,
+ 0x432b, 0x0b69,
+ 0x432d, 0x1e39,
+ 0x432f, 0x0b6d,
+ 0x433d, 0x1e3b,
+ 0x433e, 0x0b7c,
+ 0x4370, 0x1e3c,
+ 0x4371, 0x0baf,
+ 0x4375, 0x1e3d,
+ 0x4376, 0x0bb4,
+ 0x437c, 0x1e3e,
+ 0x437d, 0x0bbb,
+ 0x4421, 0x0bbd,
+ 0x443d, 0x1e3f,
+ 0x443e, 0x0bda,
+ 0x4448, 0x1e40,
+ 0x4449, 0x0be5,
+ 0x444a, 0x1e41,
+ 0x444b, 0x0be7,
+ 0x444d, 0x1e42,
+ 0x444e, 0x0bea,
+ 0x444f, 0x1e43,
+ 0x4450, 0x0bec,
+ 0x445b, 0x11b5,
+ 0x445c, 0x0bf8,
+ 0x4521, 0x0c1b,
+ 0x4522, 0x1e44,
+ 0x4523, 0x0c1d,
+ 0x4527, 0x1e45,
+ 0x4528, 0x0c22,
+ 0x452e, 0x1e46,
+ 0x452f, 0x0c29,
+ 0x4536, 0x1e47,
+ 0x4537, 0x0c31,
+ 0x453f, 0x1e48,
+ 0x4540, 0x0c3a,
+ 0x4548, 0x1e49,
+ 0x4549, 0x0c43,
+ 0x454b, 0x1e4a,
+ 0x454c, 0x0c46,
+ 0x4551, 0x1e4b,
+ 0x4553, 0x0c4d,
+ 0x4557, 0x16df,
+ 0x4558, 0x0c52,
+ 0x4564, 0x1e4d,
+ 0x4565, 0x0c5f,
+ 0x456e, 0x1450,
+ 0x456f, 0x0c69,
+ 0x4573, 0x1536,
+ 0x4574, 0x0c6e,
+ 0x4578, 0x1e4e,
+ 0x4579, 0x0c73,
+ 0x4621, 0x0c79,
+ 0x463e, 0x1e4f,
+ 0x463f, 0x0c97,
+ 0x4642, 0x1e50,
+ 0x4643, 0x0c9b,
+ 0x4654, 0x1e51,
+ 0x4656, 0x0cae,
+ 0x465b, 0x1e53,
+ 0x465d, 0x0cb5,
+ 0x4661, 0x1e55,
+ 0x4662, 0x0cba,
+ 0x4666, 0x1e56,
+ 0x4668, 0x0cc0,
+ 0x466a, 0x1e58,
+ 0x466b, 0x0cc3,
+ 0x4676, 0x1aed,
+ 0x4677, 0x0ccf,
+ 0x4721, 0x0cd7,
+ 0x4729, 0x1e59,
+ 0x472a, 0x0ce0,
+ 0x4739, 0x1e5a,
+ 0x473a, 0x0cf0,
+ 0x4757, 0x1e5b,
+ 0x4758, 0x0d0e,
+ 0x4767, 0x1e5c,
+ 0x4768, 0x1989,
+ 0x4769, 0x1e5d,
+ 0x476a, 0x0d20,
+ 0x476d, 0x1e5e,
+ 0x476e, 0x0d24,
+ 0x4821, 0x0d35,
+ 0x4824, 0x1e5f,
+ 0x4825, 0x0d39,
+ 0x482e, 0x1e60,
+ 0x482f, 0x0d43,
+ 0x4830, 0x1e61,
+ 0x4831, 0x0d45,
+ 0x4854, 0x1e62,
+ 0x4855, 0x0d69,
+ 0x4862, 0x1e63,
+ 0x4863, 0x0d77,
+ 0x4875, 0x1e64,
+ 0x4876, 0x0d8a,
+ 0x4921, 0x0d93,
+ 0x4922, 0x1e65,
+ 0x4924, 0x0d96,
+ 0x492f, 0x1e67,
+ 0x4930, 0x143b,
+ 0x4931, 0x0da3,
+ 0x4932, 0x1e68,
+ 0x4933, 0x0da5,
+ 0x4935, 0x1e69,
+ 0x4936, 0x0da8,
+ 0x4940, 0x1e6a,
+ 0x4941, 0x0db3,
+ 0x494e, 0x1e6b,
+ 0x494f, 0x0dc1,
+ 0x4951, 0x1e6c,
+ 0x4952, 0x0dc4,
+ 0x4a21, 0x0df1,
+ 0x4a43, 0x1e6d,
+ 0x4a44, 0x0e14,
+ 0x4a4d, 0x1e6e,
+ 0x4a4e, 0x0e1e,
+ 0x4a5a, 0x1e6f,
+ 0x4a5b, 0x0e2b,
+ 0x4a79, 0x1e70,
+ 0x4a7a, 0x0e4a,
+ 0x4b21, 0x0e4f,
+ 0x4b22, 0x1e71,
+ 0x4b23, 0x0e51,
+ 0x4b29, 0x1e72,
+ 0x4b2a, 0x0e58,
+ 0x4b4b, 0x1e73,
+ 0x4b4c, 0x0e7a,
+ 0x4b6a, 0x1d33,
+ 0x4b6b, 0x0e99,
+ 0x4b70, 0x1e74,
+ 0x4b71, 0x0e9f,
+ 0x4b79, 0x102f,
+ 0x4b7a, 0x0ea8,
+ 0x4c21, 0x0ead,
+ 0x4c4d, 0x1e75,
+ 0x4c4e, 0x0eda,
+ 0x4c59, 0x1e76,
+ 0x4c5a, 0x0ee6,
+ 0x4c5f, 0x1e77,
+ 0x4c60, 0x0eec,
+ 0x4c62, 0x1e78,
+ 0x4c63, 0x0eef,
+ 0x4c79, 0x1935,
+ 0x4c7a, 0x1e79,
+ 0x4c7b, 0x0f07,
+ 0x4c7c, 0x1e7a,
+ 0x4c7d, 0x0f09,
+ 0x4c7e, 0x1e7b,
+ 0x4d21, 0x0f0b,
+ 0x4d32, 0x1e7c,
+ 0x4d33, 0x0f1d,
+ 0x4d50, 0x1e7d,
+ 0x4d51, 0x0f3b,
+ 0x4d54, 0x1e7e,
+ 0x4d55, 0x0f3f,
+ 0x4d5a, 0x1d34,
+ 0x4d5b, 0x0f45,
+ 0x4d69, 0x1e7f,
+ 0x4d6a, 0x0f54,
+ 0x4e21, 0x0f69,
+ 0x4e4b, 0x1e80,
+ 0x4e4c, 0x0f94,
+ 0x4e7a, 0x1e81,
+ 0x4e7c, 0x0fc4,
+ 0x4f21, 0x1e83,
+ 0x4f22, 0x0fc8,
+ 0x4f31, 0x1e84,
+ 0x4f32, 0x0fd8,
+ 0x4f36, 0x1777,
+ 0x4f37, 0x0fdd,
+ 0x4f39, 0x1e85,
+ 0x4f3a, 0x0fe0,
+ 0x5021, 0x0ffa,
+ 0x5056, 0x0ea7,
+ 0x5057, 0x1030,
+ 0x5121, 0x1058,
+ 0x513d, 0x1e86,
+ 0x513e, 0x1075,
+ 0x5147, 0x1e87,
+ 0x5148, 0x107f,
+ 0x514b, 0x1e88,
+ 0x514c, 0x1083,
+ 0x514d, 0x1e89,
+ 0x514e, 0x1085,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5330, 0x1e8a,
+ 0x5331, 0x1124,
+ 0x533a, 0x1e8b,
+ 0x533b, 0x112e,
+ 0x5350, 0x1e8c,
+ 0x5351, 0x1144,
+ 0x535e, 0x1e8d,
+ 0x535f, 0x1152,
+ 0x536b, 0x1e8e,
+ 0x536c, 0x115f,
+ 0x5421, 0x1172,
+ 0x5444, 0x1e8f,
+ 0x5445, 0x1196,
+ 0x5464, 0x0bf7,
+ 0x5465, 0x11b6,
+ 0x5521, 0x11d0,
+ 0x553d, 0x1e90,
+ 0x553e, 0x11ed,
+ 0x5563, 0x1e91,
+ 0x5564, 0x1213,
+ 0x5621, 0x122e,
+ 0x5622, 0x1e92,
+ 0x5623, 0x1230,
+ 0x5672, 0x1e93,
+ 0x5673, 0x1280,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5824, 0x1e94,
+ 0x5825, 0x12ee,
+ 0x5921, 0x1348,
+ 0x5960, 0x1e95,
+ 0x5961, 0x1388,
+ 0x596c, 0x1e96,
+ 0x596d, 0x1394,
+ 0x5978, 0x05a7,
+ 0x5979, 0x13a0,
+ 0x5a21, 0x13a6,
+ 0x5a39, 0x1e97,
+ 0x5a3a, 0x13bf,
+ 0x5a4d, 0x1e98,
+ 0x5a4e, 0x13d3,
+ 0x5b21, 0x1404,
+ 0x5b45, 0x1e99,
+ 0x5b46, 0x1429,
+ 0x5b4a, 0x1e9a,
+ 0x5b4b, 0x142e,
+ 0x5b58, 0x0da2,
+ 0x5b59, 0x143c,
+ 0x5b6b, 0x1e9b,
+ 0x5b6c, 0x144f,
+ 0x5b6d, 0x0c68,
+ 0x5b6e, 0x1451,
+ 0x5b74, 0x1e9c,
+ 0x5b75, 0x1458,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5e39, 0x0c6d,
+ 0x5e3a, 0x1537,
+ 0x5e50, 0x1e9d,
+ 0x5e51, 0x154e,
+ 0x5e75, 0x05ff,
+ 0x5e76, 0x1573,
+ 0x5f21, 0x157c,
+ 0x5f73, 0x1e9e,
+ 0x5f74, 0x15cf,
+ 0x6021, 0x15da,
+ 0x6026, 0x1e9f,
+ 0x6027, 0x15e0,
+ 0x605f, 0x1ea0,
+ 0x6060, 0x1619,
+ 0x6076, 0x1d35,
+ 0x6077, 0x1630,
+ 0x6121, 0x1638,
+ 0x612b, 0x1ea1,
+ 0x612c, 0x1643,
+ 0x6130, 0x1ea2,
+ 0x6132, 0x1649,
+ 0x6221, 0x1696,
+ 0x622b, 0x1ea4,
+ 0x622c, 0x16a1,
+ 0x6268, 0x07ee,
+ 0x6269, 0x16de,
+ 0x626a, 0x0c51,
+ 0x626b, 0x16e0,
+ 0x626f, 0x1ea5,
+ 0x6270, 0x16e5,
+ 0x6321, 0x16f4,
+ 0x634a, 0x1ea6,
+ 0x634b, 0x171e,
+ 0x6354, 0x1ea7,
+ 0x6355, 0x1728,
+ 0x635e, 0x05d4,
+ 0x635f, 0x1732,
+ 0x6421, 0x1752,
+ 0x6439, 0x1ea8,
+ 0x643a, 0x176b,
+ 0x6446, 0x0fdc,
+ 0x6447, 0x1778,
+ 0x6464, 0x1ea9,
+ 0x6465, 0x1796,
+ 0x646e, 0x1eaa,
+ 0x646f, 0x17a0,
+ 0x6521, 0x17b0,
+ 0x6539, 0x1eab,
+ 0x653a, 0x17c9,
+ 0x653b, 0x1eac,
+ 0x653c, 0x17cb,
+ 0x6546, 0x1ead,
+ 0x6547, 0x17d6,
+ 0x6621, 0x180e,
+ 0x6646, 0x1eae,
+ 0x6647, 0x1834,
+ 0x6721, 0x186c,
+ 0x6764, 0x1eaf,
+ 0x6765, 0x18b0,
+ 0x6769, 0x1eb0,
+ 0x676a, 0x18b5,
+ 0x6772, 0x1eb1,
+ 0x6773, 0x18be,
+ 0x6821, 0x18ca,
+ 0x6834, 0x1eb2,
+ 0x6835, 0x18de,
+ 0x683b, 0x1eb3,
+ 0x683c, 0x18e5,
+ 0x6874, 0x1eb4,
+ 0x6875, 0x191e,
+ 0x6921, 0x1928,
+ 0x6922, 0x08f5,
+ 0x6923, 0x192a,
+ 0x692e, 0x0f05,
+ 0x692f, 0x1936,
+ 0x693c, 0x1eb5,
+ 0x693d, 0x1944,
+ 0x695a, 0x05a0,
+ 0x695b, 0x1962,
+ 0x6a21, 0x1986,
+ 0x6a24, 0x0d1e,
+ 0x6a25, 0x198a,
+ 0x6a27, 0x1eb6,
+ 0x6a28, 0x198d,
+ 0x6a3d, 0x1eb7,
+ 0x6a3e, 0x19a3,
+ 0x6a6f, 0x1eb8,
+ 0x6a70, 0x19d5,
+ 0x6b21, 0x19e4,
+ 0x6b32, 0x1eb9,
+ 0x6b33, 0x19f6,
+ 0x6b5d, 0x060e,
+ 0x6b5e, 0x1a21,
+ 0x6b66, 0x1eba,
+ 0x6b67, 0x1a2a,
+ 0x6b76, 0x1ebb,
+ 0x6b77, 0x1a3a,
+ 0x6c21, 0x1a42,
+ 0x6c4d, 0x0aaa,
+ 0x6c4e, 0x1a6f,
+ 0x6c69, 0x1ebc,
+ 0x6c6a, 0x1a8b,
+ 0x6c74, 0x1ebd,
+ 0x6c75, 0x1a96,
+ 0x6d21, 0x1aa0,
+ 0x6d4e, 0x1ebe,
+ 0x6d4f, 0x1ace,
+ 0x6d6c, 0x1ebf,
+ 0x6d6d, 0x1aec,
+ 0x6d6e, 0x1ec0,
+ 0x6d6f, 0x1aee,
+ 0x6e21, 0x1afe,
+ 0x6e29, 0x1ec1,
+ 0x6e2a, 0x1b07,
+ 0x6e3d, 0x1ec2,
+ 0x6e3e, 0x1b1b,
+ 0x6e57, 0x1ec3,
+ 0x6e58, 0x1b35,
+ 0x6f21, 0x1b5c,
+ 0x6f65, 0x1ec4,
+ 0x6f66, 0x1ba1,
+ 0x7021, 0x1bba,
+ 0x7033, 0x1ec5,
+ 0x7034, 0x1bcd,
+ 0x7045, 0x1ec6,
+ 0x7046, 0x1bdf,
+ 0x7051, 0x1ec7,
+ 0x7052, 0x1beb,
+ 0x7057, 0x1ec8,
+ 0x7058, 0x1bf1,
+ 0x7074, 0x0731,
+ 0x7075, 0x1ec9,
+ 0x7076, 0x1c0f,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x722d, 0x1eca,
+ 0x722e, 0x1c83,
+ 0x723c, 0x1ecb,
+ 0x723d, 0x1c92,
+ 0x724d, 0x0477,
+ 0x724e, 0x1ecc,
+ 0x724f, 0x1ca4,
+ 0x7274, 0x0529,
+ 0x7275, 0x1cca,
+ 0x7321, 0x1cd4,
+ 0x7351, 0x1ecd,
+ 0x7352, 0x1d05,
+ 0x737d, 0x1ece,
+ 0x737e, 0x1d31,
+ 0x2122, 0x1ecf,
+ 0x2124, 0x204c,
+ 0x2125, 0x2052,
+ 0x212b, 0x2050,
+ 0x212c, 0x204f,
+ 0x213c, 0x1ed3,
+ 0x2141, 0x1ed6,
+ 0x2146, 0x2059,
+ 0x2147, 0x2054,
+ 0x2148, 0x2057,
+ 0x2149, 0x2056,
+ 0x214a, 0x1edb,
+ 0x216b, 0x204d,
+ 0x216c, 0x2051,
+ 0x216d, 0x205b,
+ 0x222e, 0x204e,
+ 0x2421, 0x1eee,
+ 0x2423, 0x1eef,
+ 0x2425, 0x1ef0,
+ 0x2427, 0x1ef1,
+ 0x2429, 0x1ef2,
+ 0x2443, 0x1ef3,
+ 0x2463, 0x1ef4,
+ 0x2465, 0x1ef5,
+ 0x2467, 0x1ef6,
+ 0x246e, 0x1ef7,
+ 0x2521, 0x1ef8,
+ 0x2523, 0x1ef9,
+ 0x2525, 0x1efa,
+ 0x2527, 0x1efb,
+ 0x2529, 0x1efc,
+ 0x2543, 0x1efd,
+ 0x2563, 0x1efe,
+ 0x2565, 0x1eff,
+ 0x2567, 0x1f00,
+ 0x256e, 0x1f01,
+ 0x2575, 0x1f02,
+ 0x2d40, 0x1f04,
+ 0x2d60, 0x1f14,
+ 0x2f21, 0x1ed0,
+ 0x2f22, 0x1ee7,
+ 0x2f24, 0x1ecf,
+ 0x2f27, 0x1ef8,
+ 0x2f2c, 0x1efe,
+ 0x2f2f, 0x1efd,
+ 0x2f30, 0x1ed3,
+ 0x2f5e, 0x2050,
+ 0x2f5f, 0x204f,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12NWPVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12NWPVMap2, 809
+};
+
+static Gushort japan12RKSJHMap2[244] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12RKSJHEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12RKSJHMap2, 122
+};
+
+static Gushort japan12RKSJVMap2[298] = {
+ 0x0000, 0x0000,
+ 0x8140, 0x0279,
+ 0x8180, 0x02b8,
+ 0x81b8, 0x02e5,
+ 0x81c8, 0x02ed,
+ 0x81da, 0x02f4,
+ 0x81f0, 0x0303,
+ 0x81fc, 0x030b,
+ 0x824f, 0x030c,
+ 0x8260, 0x0316,
+ 0x8281, 0x0330,
+ 0x829f, 0x034a,
+ 0x8340, 0x039d,
+ 0x8380, 0x03dc,
+ 0x839f, 0x03f3,
+ 0x83bf, 0x040b,
+ 0x8440, 0x0423,
+ 0x8470, 0x0444,
+ 0x8480, 0x0453,
+ 0x849f, 0x1d37,
+ 0x84a0, 0x1d39,
+ 0x84a1, 0x1d43,
+ 0x84a2, 0x1d47,
+ 0x84a3, 0x1d4f,
+ 0x84a4, 0x1d4b,
+ 0x84a5, 0x1d53,
+ 0x84a6, 0x1d63,
+ 0x84a7, 0x1d5b,
+ 0x84a8, 0x1d6b,
+ 0x84a9, 0x1d73,
+ 0x84aa, 0x1d38,
+ 0x84ab, 0x1d3a,
+ 0x84ac, 0x1d46,
+ 0x84ad, 0x1d4a,
+ 0x84ae, 0x1d52,
+ 0x84af, 0x1d4e,
+ 0x84b0, 0x1d5a,
+ 0x84b1, 0x1d6a,
+ 0x84b2, 0x1d62,
+ 0x84b3, 0x1d72,
+ 0x84b4, 0x1d82,
+ 0x84b5, 0x1d57,
+ 0x84b6, 0x1d66,
+ 0x84b7, 0x1d5f,
+ 0x84b8, 0x1d6e,
+ 0x84b9, 0x1d76,
+ 0x84ba, 0x1d54,
+ 0x84bb, 0x1d67,
+ 0x84bc, 0x1d5c,
+ 0x84bd, 0x1d6f,
+ 0x84be, 0x1d79,
+ 0x889f, 0x0465,
+ 0x8940, 0x04c3,
+ 0x8980, 0x0502,
+ 0x8a40, 0x057f,
+ 0x8a80, 0x05be,
+ 0x8b40, 0x063b,
+ 0x8b80, 0x067a,
+ 0x8c40, 0x06f7,
+ 0x8c80, 0x0736,
+ 0x8d40, 0x07b3,
+ 0x8d80, 0x07f2,
+ 0x8e40, 0x086f,
+ 0x8e80, 0x08ae,
+ 0x8f40, 0x092b,
+ 0x8f80, 0x096a,
+ 0x9040, 0x09e7,
+ 0x9080, 0x0a26,
+ 0x9140, 0x0aa3,
+ 0x9180, 0x0ae2,
+ 0x9240, 0x0b5f,
+ 0x9280, 0x0b9e,
+ 0x9340, 0x0c1b,
+ 0x9380, 0x0c5a,
+ 0x9440, 0x0cd7,
+ 0x9480, 0x0d16,
+ 0x9540, 0x0d93,
+ 0x9580, 0x0dd2,
+ 0x9640, 0x0e4f,
+ 0x9680, 0x0e8e,
+ 0x9740, 0x0f0b,
+ 0x9780, 0x0f4a,
+ 0x9840, 0x0fc7,
+ 0x989f, 0x0ffa,
+ 0x9940, 0x1058,
+ 0x9980, 0x1097,
+ 0x9a40, 0x1114,
+ 0x9a80, 0x1153,
+ 0x9b40, 0x11d0,
+ 0x9b80, 0x120f,
+ 0x9c40, 0x128c,
+ 0x9c80, 0x12cb,
+ 0x9d40, 0x1348,
+ 0x9d80, 0x1387,
+ 0x9e40, 0x1404,
+ 0x9e80, 0x1443,
+ 0x9f40, 0x14c0,
+ 0x9f80, 0x14ff,
+ 0xe040, 0x157c,
+ 0xe080, 0x15bb,
+ 0xe140, 0x1638,
+ 0xe180, 0x1677,
+ 0xe240, 0x16f4,
+ 0xe280, 0x1733,
+ 0xe340, 0x17b0,
+ 0xe380, 0x17ef,
+ 0xe440, 0x186c,
+ 0xe480, 0x18ab,
+ 0xe540, 0x1928,
+ 0xe580, 0x1967,
+ 0xe640, 0x19e4,
+ 0xe680, 0x1a23,
+ 0xe740, 0x1aa0,
+ 0xe780, 0x1adf,
+ 0xe840, 0x1b5c,
+ 0xe880, 0x1b9b,
+ 0xe940, 0x1c18,
+ 0xe980, 0x1c57,
+ 0xea40, 0x1cd4,
+ 0xea80, 0x1d13,
+ 0xeaa3, 0x205c,
+ 0x8141, 0x1ecf,
+ 0x8150, 0x1ed1,
+ 0x815b, 0x1ed3,
+ 0x8160, 0x1ed6,
+ 0x8169, 0x1edb,
+ 0x8181, 0x1eed,
+ 0x829f, 0x1eee,
+ 0x82a1, 0x1eef,
+ 0x82a3, 0x1ef0,
+ 0x82a5, 0x1ef1,
+ 0x82a7, 0x1ef2,
+ 0x82c1, 0x1ef3,
+ 0x82e1, 0x1ef4,
+ 0x82e3, 0x1ef5,
+ 0x82e5, 0x1ef6,
+ 0x82ec, 0x1ef7,
+ 0x8340, 0x1ef8,
+ 0x8342, 0x1ef9,
+ 0x8344, 0x1efa,
+ 0x8346, 0x1efb,
+ 0x8348, 0x1efc,
+ 0x8362, 0x1efd,
+ 0x8383, 0x1efe,
+ 0x8385, 0x1eff,
+ 0x8387, 0x1f00,
+ 0x838e, 0x1f01,
+ 0x8395, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12RKSJVEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014c, 0x014d,
+ 0x014e, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, 0x0155,
+ 0x0156, 0x0157, 0x0158, 0x0159, 0x015a, 0x015b, 0x015c, 0x015d,
+ 0x015e, 0x015f, 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165,
+ 0x0166, 0x0167, 0x0168, 0x0169, 0x016a, 0x016b, 0x016c, 0x016d,
+ 0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
+ 0x0176, 0x0177, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d,
+ 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12RKSJVMap2, 149
+};
+
+static Gushort japan12RomanMap2[4] = {
+ 0x0000, 0x0000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12RomanEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee,
+ 0x00ef, 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6,
+ 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe,
+ 0x00ff, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106,
+ 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e,
+ 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116,
+ 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e,
+ 0x011f, 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0126,
+ 0x0127, 0x0128, 0x0129, 0x012a, 0x012b, 0x012c, 0x012d, 0x012e,
+ 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136,
+ 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d, 0x013e,
+ 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12RomanMap2, 2
+};
+
+static Gushort japan12UniJISUCS2HMap2[13926] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x005c, 0x0061,
+ 0x005d, 0x003e,
+ 0x00a1, 0x0065,
+ 0x00a4, 0x006b,
+ 0x00a5, 0x003d,
+ 0x00a6, 0x0063,
+ 0x00a7, 0x02d0,
+ 0x00a8, 0x0287,
+ 0x00a9, 0x0098,
+ 0x00aa, 0x008c,
+ 0x00ab, 0x006d,
+ 0x00ac, 0x0099,
+ 0x00ad, 0x0097,
+ 0x00ae, 0x009a,
+ 0x00af, 0x0081,
+ 0x00b0, 0x02c3,
+ 0x00b1, 0x02b6,
+ 0x00b2, 0x009d,
+ 0x00b4, 0x0285,
+ 0x00b5, 0x009f,
+ 0x00b6, 0x030a,
+ 0x00b7, 0x0075,
+ 0x00b8, 0x0086,
+ 0x00b9, 0x00a0,
+ 0x00ba, 0x0090,
+ 0x00bb, 0x007b,
+ 0x00bc, 0x00a1,
+ 0x00bf, 0x007e,
+ 0x00c0, 0x00a4,
+ 0x00c6, 0x008b,
+ 0x00c7, 0x00aa,
+ 0x00d7, 0x02b7,
+ 0x00d8, 0x008e,
+ 0x00d9, 0x00bb,
+ 0x00df, 0x0096,
+ 0x00e0, 0x00c1,
+ 0x00e6, 0x0091,
+ 0x00e7, 0x00c7,
+ 0x00f7, 0x02b8,
+ 0x00f8, 0x0094,
+ 0x00f9, 0x00d8,
+ 0x0131, 0x0092,
+ 0x0141, 0x008d,
+ 0x0142, 0x0093,
+ 0x0152, 0x008f,
+ 0x0153, 0x0095,
+ 0x0160, 0x00df,
+ 0x0161, 0x00e3,
+ 0x0178, 0x00e0,
+ 0x017d, 0x00e1,
+ 0x017e, 0x00e5,
+ 0x01c0, 0x0063,
+ 0x0300, 0x0041,
+ 0x0301, 0x007f,
+ 0x0303, 0x005f,
+ 0x0304, 0x0081,
+ 0x0305, 0x00e2,
+ 0x0306, 0x0082,
+ 0x030a, 0x0085,
+ 0x030b, 0x0087,
+ 0x030c, 0x0089,
+ 0x0327, 0x0086,
+ 0x0328, 0x0088,
+ 0x0332, 0x0040,
+ 0x0336, 0x008a,
+ 0x0361, 0x02f6,
+ 0x0391, 0x03f3,
+ 0x03a3, 0x0404,
+ 0x03b1, 0x040b,
+ 0x03c3, 0x041c,
+ 0x0401, 0x0429,
+ 0x0410, 0x0423,
+ 0x0416, 0x042a,
+ 0x0436, 0x044b,
+ 0x0451, 0x044a,
+ 0x2002, 0x00e7,
+ 0x2003, 0x0279,
+ 0x2010, 0x000e,
+ 0x2011, 0x000e,
+ 0x2012, 0x0072,
+ 0x2013, 0x0072,
+ 0x2014, 0x008a,
+ 0x2015, 0x0295,
+ 0x2016, 0x029a,
+ 0x2018, 0x029e,
+ 0x201a, 0x0078,
+ 0x201c, 0x02a0,
+ 0x201e, 0x0079,
+ 0x2020, 0x0308,
+ 0x2022, 0x0077,
+ 0x2025, 0x029d,
+ 0x2026, 0x029c,
+ 0x2030, 0x0304,
+ 0x2032, 0x02c4,
+ 0x2039, 0x006e,
+ 0x203b, 0x02de,
+ 0x203e, 0x0145,
+ 0x2044, 0x0068,
+ 0x20dd, 0x030b,
+ 0x2103, 0x02c6,
+ 0x2109, 0x2071,
+ 0x2113, 0x1f59,
+ 0x2116, 0x1dba,
+ 0x2121, 0x1f77,
+ 0x2122, 0x00e4,
+ 0x212b, 0x0303,
+ 0x2160, 0x1d97,
+ 0x216a, 0x2021,
+ 0x2170, 0x1f9c,
+ 0x217a, 0x206a,
+ 0x217f, 0x206f,
+ 0x2190, 0x02e1,
+ 0x2192, 0x02e0,
+ 0x2193, 0x02e3,
+ 0x21c4, 0x2076,
+ 0x21c6, 0x2075,
+ 0x21d2, 0x02f0,
+ 0x21d4, 0x02f1,
+ 0x21e6, 0x1f4d,
+ 0x21e7, 0x1f4c,
+ 0x21e8, 0x1f4e,
+ 0x21e9, 0x1f4b,
+ 0x2200, 0x02f2,
+ 0x2202, 0x02f7,
+ 0x2203, 0x02f3,
+ 0x2207, 0x02f8,
+ 0x2208, 0x02e5,
+ 0x220b, 0x02e6,
+ 0x2211, 0x1dc9,
+ 0x2212, 0x02b5,
+ 0x221a, 0x02fd,
+ 0x221d, 0x02ff,
+ 0x221e, 0x02bf,
+ 0x221f, 0x1dcd,
+ 0x2220, 0x02f4,
+ 0x2225, 0x029a,
+ 0x2227, 0x02ed,
+ 0x2229, 0x02ec,
+ 0x222a, 0x02eb,
+ 0x222b, 0x0301,
+ 0x222d, 0x2003,
+ 0x222e, 0x1dc8,
+ 0x2234, 0x02c0,
+ 0x2235, 0x0300,
+ 0x223c, 0x0299,
+ 0x223d, 0x02fe,
+ 0x2252, 0x02fa,
+ 0x2260, 0x02ba,
+ 0x2261, 0x02f9,
+ 0x2266, 0x02bd,
+ 0x226a, 0x02fb,
+ 0x2282, 0x02e9,
+ 0x2286, 0x02e7,
+ 0x22a5, 0x02f5,
+ 0x22bf, 0x1dce,
+ 0x22ee, 0x1ed9,
+ 0x22ef, 0x029c,
+ 0x2312, 0x02f6,
+ 0x2460, 0x1d83,
+ 0x2474, 0x1f87,
+ 0x2488, 0x1f7e,
+ 0x249c, 0x1fb0,
+ 0x24ea, 0x2020,
+ 0x2500, 0x1d37,
+ 0x2550, 0x203b,
+ 0x255e, 0x203c,
+ 0x2561, 0x203e,
+ 0x256a, 0x203d,
+ 0x256d, 0x2037,
+ 0x256f, 0x203a,
+ 0x2570, 0x2039,
+ 0x2571, 0x2045,
+ 0x2581, 0x2026,
+ 0x2589, 0x2034,
+ 0x258a, 0x2033,
+ 0x258b, 0x2032,
+ 0x258c, 0x2031,
+ 0x258d, 0x2030,
+ 0x258e, 0x202f,
+ 0x258f, 0x202e,
+ 0x2594, 0x2035,
+ 0x25a0, 0x02d9,
+ 0x25a1, 0x02d8,
+ 0x25a2, 0x1f4f,
+ 0x25b2, 0x02db,
+ 0x25b3, 0x02da,
+ 0x25b7, 0x1f4a,
+ 0x25bc, 0x02dd,
+ 0x25bd, 0x02dc,
+ 0x25c1, 0x1f49,
+ 0x25c6, 0x02d7,
+ 0x25c7, 0x02d6,
+ 0x25c9, 0x2012,
+ 0x25cb, 0x02d3,
+ 0x25ce, 0x02d5,
+ 0x25cf, 0x02d4,
+ 0x25e2, 0x203f,
+ 0x25e4, 0x2042,
+ 0x25e5, 0x2041,
+ 0x25ef, 0x030b,
+ 0x2600, 0x2017,
+ 0x2605, 0x02d2,
+ 0x2606, 0x02d1,
+ 0x260e, 0x1f78,
+ 0x261c, 0x201c,
+ 0x261e, 0x201b,
+ 0x261f, 0x201e,
+ 0x2640, 0x02c2,
+ 0x2642, 0x02c1,
+ 0x2660, 0x2013,
+ 0x2661, 0x1f51,
+ 0x2662, 0x1f53,
+ 0x2663, 0x2015,
+ 0x2664, 0x1f52,
+ 0x2665, 0x2014,
+ 0x2666, 0x2016,
+ 0x2667, 0x1f50,
+ 0x266a, 0x0307,
+ 0x266d, 0x0306,
+ 0x266f, 0x0305,
+ 0x2776, 0x205e,
+ 0x27a1, 0x200e,
+ 0x3000, 0x0279,
+ 0x3003, 0x028f,
+ 0x3004, 0x2074,
+ 0x3005, 0x0291,
+ 0x3008, 0x02aa,
+ 0x3012, 0x02df,
+ 0x3013, 0x02e4,
+ 0x3014, 0x02a4,
+ 0x301c, 0x0299,
+ 0x301d, 0x1db8,
+ 0x301f, 0x1db9,
+ 0x3020, 0x1f7a,
+ 0x3036, 0x1f79,
+ 0x3041, 0x034a,
+ 0x3094, 0x1f16,
+ 0x309b, 0x0283,
+ 0x309d, 0x028d,
+ 0x30a1, 0x039d,
+ 0x30f7, 0x2079,
+ 0x30fb, 0x027e,
+ 0x30fc, 0x0294,
+ 0x30fd, 0x028b,
+ 0x322a, 0x2006,
+ 0x3230, 0x2005,
+ 0x3231, 0x1dc2,
+ 0x3233, 0x1fcf,
+ 0x3234, 0x1fcd,
+ 0x3235, 0x1fd4,
+ 0x3236, 0x1fd3,
+ 0x3237, 0x200c,
+ 0x3238, 0x1fce,
+ 0x3239, 0x1dc4,
+ 0x323a, 0x1fd7,
+ 0x323b, 0x1fd5,
+ 0x323c, 0x1fd0,
+ 0x323d, 0x1fcb,
+ 0x323e, 0x1fd2,
+ 0x323f, 0x1fcc,
+ 0x3240, 0x1fd6,
+ 0x3241, 0x200d,
+ 0x3242, 0x1fd1,
+ 0x3243, 0x1fca,
+ 0x3291, 0x1fe1,
+ 0x3292, 0x1fe0,
+ 0x3293, 0x1fe2,
+ 0x3294, 0x1fdc,
+ 0x3296, 0x1fe5,
+ 0x3298, 0x1fde,
+ 0x3299, 0x201f,
+ 0x329d, 0x207f,
+ 0x329e, 0x1fff,
+ 0x32a4, 0x1dbd,
+ 0x32a9, 0x1fda,
+ 0x32aa, 0x1fdd,
+ 0x32ab, 0x1fdf,
+ 0x32ac, 0x1fe3,
+ 0x32ad, 0x1fd9,
+ 0x32ae, 0x1fe4,
+ 0x32af, 0x1fdb,
+ 0x32b0, 0x1fd8,
+ 0x3300, 0x1f70,
+ 0x3303, 0x1f6a,
+ 0x3305, 0x1ff7,
+ 0x330d, 0x1dab,
+ 0x3314, 0x1da2,
+ 0x3315, 0x1f69,
+ 0x3316, 0x1f67,
+ 0x3318, 0x1f68,
+ 0x331e, 0x1f73,
+ 0x3322, 0x1f66,
+ 0x3323, 0x1f6b,
+ 0x3326, 0x1dac,
+ 0x3327, 0x1da6,
+ 0x332a, 0x1f74,
+ 0x332b, 0x1dae,
+ 0x3331, 0x1f71,
+ 0x3333, 0x2087,
+ 0x3336, 0x1da8,
+ 0x3339, 0x1f6e,
+ 0x333b, 0x1f6f,
+ 0x3342, 0x1f6d,
+ 0x3347, 0x1f72,
+ 0x3349, 0x1da1,
+ 0x334a, 0x1daf,
+ 0x334d, 0x1da4,
+ 0x334e, 0x2088,
+ 0x3351, 0x1da9,
+ 0x3357, 0x1f6c,
+ 0x337b, 0x2083,
+ 0x337c, 0x1dc7,
+ 0x337d, 0x1dc6,
+ 0x337e, 0x1dc5,
+ 0x337f, 0x1f76,
+ 0x3385, 0x1f5f,
+ 0x3388, 0x2000,
+ 0x338e, 0x1db4,
+ 0x3390, 0x1f63,
+ 0x3396, 0x1f65,
+ 0x3397, 0x1f58,
+ 0x3398, 0x1f5a,
+ 0x339c, 0x1db1,
+ 0x339f, 0x1ffa,
+ 0x33a0, 0x1f54,
+ 0x33a1, 0x1db7,
+ 0x33a2, 0x1f55,
+ 0x33a3, 0x1ffb,
+ 0x33a4, 0x1f56,
+ 0x33a6, 0x1ffc,
+ 0x33b0, 0x1f5e,
+ 0x33b1, 0x1f5d,
+ 0x33b2, 0x1f5c,
+ 0x33b3, 0x1f5b,
+ 0x33c4, 0x1db6,
+ 0x33c8, 0x2002,
+ 0x33cb, 0x1f62,
+ 0x33cc, 0x1ff6,
+ 0x33cd, 0x1dbb,
+ 0x33d4, 0x1f64,
+ 0x4e00, 0x04b0,
+ 0x4e01, 0x0bb8,
+ 0x4e03, 0x08e3,
+ 0x4e07, 0x0eaa,
+ 0x4e08, 0x09ce,
+ 0x4e09, 0x087e,
+ 0x4e0a, 0x09cd,
+ 0x4e0b, 0x053c,
+ 0x4e0d, 0x0dc6,
+ 0x4e0e, 0x0f29,
+ 0x4e10, 0x0ffb,
+ 0x4e11, 0x04d1,
+ 0x4e14, 0x05cc,
+ 0x4e15, 0x0ffc,
+ 0x4e16, 0x0a48,
+ 0x4e17, 0x10d7,
+ 0x4e18, 0x0670,
+ 0x4e19, 0x0e0a,
+ 0x4e1e, 0x09cf,
+ 0x4e21, 0x0f86,
+ 0x4e26, 0x0e12,
+ 0x4e28, 0x20b3,
+ 0x4e2a, 0x0ffd,
+ 0x4e2d, 0x0ba4,
+ 0x4e31, 0x0ffe,
+ 0x4e32, 0x06f2,
+ 0x4e36, 0x0fff,
+ 0x4e38, 0x0619,
+ 0x4e39, 0x0b6e,
+ 0x4e3b, 0x0913,
+ 0x4e3c, 0x1000,
+ 0x4e3f, 0x1001,
+ 0x4e42, 0x1002,
+ 0x4e43, 0x0ceb,
+ 0x4e45, 0x0671,
+ 0x4e4b, 0x0ced,
+ 0x4e4d, 0x0cbb,
+ 0x4e4e, 0x0777,
+ 0x4e4f, 0x0e61,
+ 0x4e55, 0x1950,
+ 0x4e56, 0x1003,
+ 0x4e57, 0x09d0,
+ 0x4e58, 0x1004,
+ 0x4e59, 0x0535,
+ 0x4e5d, 0x06dd,
+ 0x4e5e, 0x07a4,
+ 0x4e5f, 0x0ef5,
+ 0x4e62, 0x1233,
+ 0x4e71, 0x0f5a,
+ 0x4e73, 0x0cd5,
+ 0x4e7e, 0x05e1,
+ 0x4e80, 0x064f,
+ 0x4e82, 0x1005,
+ 0x4e85, 0x1006,
+ 0x4e86, 0x0f83,
+ 0x4e88, 0x0f27,
+ 0x4e89, 0x0aea,
+ 0x4e8a, 0x1008,
+ 0x4e8b, 0x08c4,
+ 0x4e8c, 0x0ccb,
+ 0x4e8e, 0x100b,
+ 0x4e91, 0x04e0,
+ 0x4e92, 0x0793,
+ 0x4e94, 0x0792,
+ 0x4e95, 0x04aa,
+ 0x4e98, 0x0ff1,
+ 0x4e99, 0x0ff0,
+ 0x4e9b, 0x0823,
+ 0x4e9c, 0x0465,
+ 0x4e9e, 0x100c,
+ 0x4ea1, 0x0e62,
+ 0x4ea2, 0x100f,
+ 0x4ea4, 0x07a6,
+ 0x4ea5, 0x04ab,
+ 0x4ea6, 0x0ea0,
+ 0x4ea8, 0x0696,
+ 0x4eab, 0x0697,
+ 0x4ead, 0x0bfe,
+ 0x4eae, 0x0f84,
+ 0x4eb0, 0x1010,
+ 0x4eb3, 0x1011,
+ 0x4eb6, 0x1012,
+ 0x4eba, 0x0a13,
+ 0x4ec0, 0x0944,
+ 0x4ec1, 0x0a14,
+ 0x4ec2, 0x1017,
+ 0x4ec4, 0x1015,
+ 0x4ec6, 0x1016,
+ 0x4ec7, 0x0672,
+ 0x4eca, 0x0813,
+ 0x4ecb, 0x0570,
+ 0x4ecd, 0x1014,
+ 0x4ece, 0x1013,
+ 0x4ecf, 0x0df9,
+ 0x4ed4, 0x0894,
+ 0x4ed5, 0x0893,
+ 0x4ed6, 0x0b1e,
+ 0x4ed7, 0x1018,
+ 0x4ed8, 0x0dc7,
+ 0x4ed9, 0x0a8b,
+ 0x4edd, 0x0290,
+ 0x4ede, 0x1019,
+ 0x4edf, 0x101b,
+ 0x4ee1, 0x20b4,
+ 0x4ee3, 0x0b45,
+ 0x4ee4, 0x0fa9,
+ 0x4ee5, 0x048e,
+ 0x4eed, 0x101a,
+ 0x4eee, 0x053e,
+ 0x4ef0, 0x06bc,
+ 0x4ef2, 0x0ba5,
+ 0x4ef6, 0x0745,
+ 0x4ef7, 0x101c,
+ 0x4efb, 0x0cda,
+ 0x4efc, 0x20b5,
+ 0x4f00, 0x20b6,
+ 0x4f01, 0x0627,
+ 0x4f03, 0x20b7,
+ 0x4f09, 0x101d,
+ 0x4f0a, 0x048f,
+ 0x4f0d, 0x0794,
+ 0x4f0e, 0x0628,
+ 0x4f0f, 0x0dec,
+ 0x4f10, 0x0d46,
+ 0x4f11, 0x0673,
+ 0x4f1a, 0x0571,
+ 0x4f1c, 0x1040,
+ 0x4f1d, 0x0c3b,
+ 0x4f2f, 0x0d22,
+ 0x4f30, 0x101f,
+ 0x4f34, 0x0d50,
+ 0x4f36, 0x0faa,
+ 0x4f38, 0x09f3,
+ 0x4f39, 0x20b8,
+ 0x4f3a, 0x0895,
+ 0x4f3c, 0x08c5,
+ 0x4f3d, 0x0540,
+ 0x4f43, 0x0bed,
+ 0x4f46, 0x0b60,
+ 0x4f47, 0x1023,
+ 0x4f4d, 0x0490,
+ 0x4f4e, 0x0bff,
+ 0x4f4f, 0x0945,
+ 0x4f50, 0x0824,
+ 0x4f51, 0x0f0e,
+ 0x4f53, 0x0b2e,
+ 0x4f55, 0x053f,
+ 0x4f56, 0x20b9,
+ 0x4f57, 0x1022,
+ 0x4f59, 0x0f28,
+ 0x4f5a, 0x101e,
+ 0x4f5b, 0x1020,
+ 0x4f5c, 0x085e,
+ 0x4f5d, 0x1021,
+ 0x4f5e, 0x11d3,
+ 0x4f69, 0x1029,
+ 0x4f6f, 0x102c,
+ 0x4f70, 0x102a,
+ 0x4f73, 0x0542,
+ 0x4f75, 0x0e0b,
+ 0x4f76, 0x1024,
+ 0x4f7b, 0x1028,
+ 0x4f7c, 0x07a7,
+ 0x4f7f, 0x0896,
+ 0x4f83, 0x05e2,
+ 0x4f86, 0x102d,
+ 0x4f88, 0x1025,
+ 0x4f8a, 0x20bb,
+ 0x4f8b, 0x0fab,
+ 0x4f8d, 0x08c6,
+ 0x4f8f, 0x1026,
+ 0x4f91, 0x102b,
+ 0x4f92, 0x20ba,
+ 0x4f94, 0x20bd,
+ 0x4f96, 0x102e,
+ 0x4f98, 0x1027,
+ 0x4f9a, 0x20bc,
+ 0x4f9b, 0x0699,
+ 0x4f9d, 0x0491,
+ 0x4fa0, 0x069a,
+ 0x4fa1, 0x0541,
+ 0x4fab, 0x11d4,
+ 0x4fad, 0x0ea7,
+ 0x4fae, 0x0de0,
+ 0x4faf, 0x07a8,
+ 0x4fb5, 0x09f5,
+ 0x4fb6, 0x0f7f,
+ 0x4fbf, 0x0e28,
+ 0x4fc2, 0x070e,
+ 0x4fc3, 0x0b05,
+ 0x4fc4, 0x0564,
+ 0x4fc9, 0x20ac,
+ 0x4fca, 0x095d,
+ 0x4fcd, 0x20be,
+ 0x4fce, 0x1032,
+ 0x4fd0, 0x1037,
+ 0x4fd1, 0x1035,
+ 0x4fd4, 0x1030,
+ 0x4fd7, 0x0b0f,
+ 0x4fd8, 0x1033,
+ 0x4fda, 0x1036,
+ 0x4fdb, 0x1034,
+ 0x4fdd, 0x0e2d,
+ 0x4fdf, 0x1031,
+ 0x4fe0, 0x1dec,
+ 0x4fe1, 0x09f4,
+ 0x4fe3, 0x0ea1,
+ 0x4fe4, 0x1038,
+ 0x4fee, 0x092e,
+ 0x4fef, 0x1046,
+ 0x4ff3, 0x0d06,
+ 0x4ff5, 0x0da8,
+ 0x4ff6, 0x1041,
+ 0x4ff8, 0x0e40,
+ 0x4ffa, 0x0536,
+ 0x4ffe, 0x1045,
+ 0x4fff, 0x20c1,
+ 0x5005, 0x103f,
+ 0x5006, 0x1048,
+ 0x5009, 0x0ad4,
+ 0x500b, 0x0778,
+ 0x500d, 0x0d12,
+ 0x500f, 0x1600,
+ 0x5011, 0x1047,
+ 0x5012, 0x0c57,
+ 0x5014, 0x103c,
+ 0x5016, 0x07aa,
+ 0x5019, 0x07a9,
+ 0x501a, 0x103a,
+ 0x501e, 0x20c2,
+ 0x501f, 0x0906,
+ 0x5021, 0x1042,
+ 0x5022, 0x20c0,
+ 0x5023, 0x0e3f,
+ 0x5024, 0x0b8b,
+ 0x5025, 0x103e,
+ 0x5026, 0x0747,
+ 0x5028, 0x103b,
+ 0x5029, 0x1043,
+ 0x502a, 0x103d,
+ 0x502b, 0x0f99,
+ 0x502c, 0x1044,
+ 0x502d, 0x0fe7,
+ 0x5036, 0x06de,
+ 0x5039, 0x0746,
+ 0x5040, 0x20bf,
+ 0x5042, 0x20c5,
+ 0x5043, 0x1049,
+ 0x5046, 0x20c3,
+ 0x5047, 0x104a,
+ 0x5048, 0x104e,
+ 0x5049, 0x0492,
+ 0x504f, 0x0e20,
+ 0x5050, 0x104d,
+ 0x5055, 0x104c,
+ 0x5056, 0x1050,
+ 0x505a, 0x104f,
+ 0x505c, 0x0c00,
+ 0x5065, 0x0748,
+ 0x506c, 0x1051,
+ 0x5070, 0x20c4,
+ 0x5072, 0x08f1,
+ 0x5074, 0x0b06,
+ 0x5075, 0x0c01,
+ 0x5076, 0x06ee,
+ 0x5078, 0x1052,
+ 0x507d, 0x0650,
+ 0x5080, 0x1053,
+ 0x5085, 0x1055,
+ 0x508d, 0x0e63,
+ 0x5091, 0x073c,
+ 0x5094, 0x20c6,
+ 0x5098, 0x087f,
+ 0x5099, 0x0d8b,
+ 0x509a, 0x1054,
+ 0x50ac, 0x0835,
+ 0x50ad, 0x0f2d,
+ 0x50b2, 0x1057,
+ 0x50b3, 0x105a,
+ 0x50b4, 0x1056,
+ 0x50b5, 0x0834,
+ 0x50b7, 0x0987,
+ 0x50be, 0x070f,
+ 0x50c2, 0x105b,
+ 0x50c5, 0x06c7,
+ 0x50c9, 0x1058,
+ 0x50cd, 0x0c87,
+ 0x50cf, 0x0afe,
+ 0x50d1, 0x069b,
+ 0x50d5, 0x0e7b,
+ 0x50d6, 0x105c,
+ 0x50d8, 0x20c8,
+ 0x50da, 0x0f85,
+ 0x50de, 0x105d,
+ 0x50e3, 0x1060,
+ 0x50e5, 0x105e,
+ 0x50e7, 0x0ad0,
+ 0x50ed, 0x105f,
+ 0x50ee, 0x1061,
+ 0x50f4, 0x20c7,
+ 0x50f5, 0x1063,
+ 0x50f9, 0x1062,
+ 0x50fb, 0x0e18,
+ 0x5100, 0x0651,
+ 0x5101, 0x1065,
+ 0x5104, 0x052f,
+ 0x5109, 0x1064,
+ 0x5112, 0x0920,
+ 0x5114, 0x1069,
+ 0x5115, 0x1068,
+ 0x5116, 0x1067,
+ 0x5118, 0x102f,
+ 0x511a, 0x106a,
+ 0x511f, 0x0988,
+ 0x5121, 0x106b,
+ 0x512a, 0x0f0f,
+ 0x5132, 0x0ee5,
+ 0x5137, 0x106d,
+ 0x513a, 0x106c,
+ 0x513b, 0x106f,
+ 0x513c, 0x106e,
+ 0x513f, 0x1070,
+ 0x5141, 0x04b8,
+ 0x5143, 0x0769,
+ 0x5144, 0x0711,
+ 0x5145, 0x0946,
+ 0x5146, 0x0bb9,
+ 0x5147, 0x069c,
+ 0x5148, 0x0a8c,
+ 0x5149, 0x07ab,
+ 0x514a, 0x20c9,
+ 0x514b, 0x0800,
+ 0x514c, 0x1073,
+ 0x514d, 0x0ed4,
+ 0x514e, 0x0c40,
+ 0x5150, 0x08c7,
+ 0x5152, 0x1072,
+ 0x5154, 0x1074,
+ 0x515a, 0x0c58,
+ 0x515c, 0x05d3,
+ 0x5162, 0x1075,
+ 0x5164, 0x20ca,
+ 0x5165, 0x0cd6,
+ 0x5168, 0x0ab6,
+ 0x5169, 0x1077,
+ 0x516b, 0x0d40,
+ 0x516c, 0x07ac,
+ 0x516d, 0x0fe1,
+ 0x516e, 0x1079,
+ 0x5171, 0x069e,
+ 0x5175, 0x0e0c,
+ 0x5176, 0x0b16,
+ 0x5177, 0x06e9,
+ 0x5178, 0x0c2f,
+ 0x517c, 0x0749,
+ 0x5180, 0x107a,
+ 0x5182, 0x107b,
+ 0x5185, 0x0cba,
+ 0x5186, 0x0501,
+ 0x5189, 0x107e,
+ 0x518a, 0x086d,
+ 0x518c, 0x107d,
+ 0x518d, 0x0836,
+ 0x518f, 0x107f,
+ 0x5190, 0x185b,
+ 0x5191, 0x1080,
+ 0x5192, 0x0e6f,
+ 0x5193, 0x1081,
+ 0x5195, 0x1082,
+ 0x5197, 0x09d1,
+ 0x5199, 0x08f8,
+ 0x519d, 0x20cb,
+ 0x51a0, 0x05e3,
+ 0x51a2, 0x1086,
+ 0x51a4, 0x1084,
+ 0x51a5, 0x0ec9,
+ 0x51a6, 0x1085,
+ 0x51a8, 0x0dcc,
+ 0x51a9, 0x1087,
+ 0x51ac, 0x0c59,
+ 0x51b0, 0x108d,
+ 0x51b1, 0x108b,
+ 0x51b3, 0x108a,
+ 0x51b4, 0x0853,
+ 0x51b5, 0x108e,
+ 0x51b6, 0x0ef6,
+ 0x51b7, 0x0fac,
+ 0x51bd, 0x108f,
+ 0x51be, 0x20cc,
+ 0x51c4, 0x0a4c,
+ 0x51c5, 0x1090,
+ 0x51c6, 0x0964,
+ 0x51c9, 0x1091,
+ 0x51cb, 0x0bba,
+ 0x51cc, 0x0f87,
+ 0x51cd, 0x0c5a,
+ 0x51d6, 0x10da,
+ 0x51db, 0x1092,
+ 0x51dc, 0x205c,
+ 0x51dd, 0x06bd,
+ 0x51e0, 0x1093,
+ 0x51e1, 0x0e8c,
+ 0x51e6, 0x0972,
+ 0x51e7, 0x0b5c,
+ 0x51e9, 0x1095,
+ 0x51ea, 0x0cbc,
+ 0x51ec, 0x20cd,
+ 0x51ed, 0x1096,
+ 0x51f0, 0x1097,
+ 0x51f1, 0x058c,
+ 0x51f5, 0x1098,
+ 0x51f6, 0x069f,
+ 0x51f8, 0x0ca4,
+ 0x51f9, 0x051c,
+ 0x51fa, 0x095a,
+ 0x51fd, 0x0d35,
+ 0x51fe, 0x1099,
+ 0x5200, 0x0c5b,
+ 0x5203, 0x0a15,
+ 0x5204, 0x109a,
+ 0x5206, 0x0dfc,
+ 0x5207, 0x0a7e,
+ 0x5208, 0x05de,
+ 0x520a, 0x05e5,
+ 0x520b, 0x109b,
+ 0x520e, 0x109d,
+ 0x5211, 0x0710,
+ 0x5214, 0x109c,
+ 0x5215, 0x20ce,
+ 0x5217, 0x0fbb,
+ 0x521d, 0x0973,
+ 0x5224, 0x0d51,
+ 0x5225, 0x0e1c,
+ 0x5227, 0x109e,
+ 0x5229, 0x0f62,
+ 0x522a, 0x109f,
+ 0x522e, 0x10a0,
+ 0x5230, 0x0c78,
+ 0x5233, 0x10a1,
+ 0x5236, 0x0a4d,
+ 0x5237, 0x086e,
+ 0x5238, 0x074a,
+ 0x5239, 0x10a2,
+ 0x523a, 0x0897,
+ 0x523b, 0x0801,
+ 0x5243, 0x0c02,
+ 0x5244, 0x10a4,
+ 0x5247, 0x0b07,
+ 0x524a, 0x085f,
+ 0x524b, 0x10a5,
+ 0x524d, 0x0ab2,
+ 0x524f, 0x10a3,
+ 0x5254, 0x10a8,
+ 0x5256, 0x0e64,
+ 0x525b, 0x07f6,
+ 0x525d, 0x1e5e,
+ 0x525e, 0x10a7,
+ 0x5263, 0x074b,
+ 0x5264, 0x084e,
+ 0x5265, 0x0d23,
+ 0x5269, 0x10ab,
+ 0x526a, 0x10a9,
+ 0x526f, 0x0ded,
+ 0x5270, 0x09d2,
+ 0x5271, 0x10b2,
+ 0x5272, 0x05c2,
+ 0x5273, 0x10ac,
+ 0x5274, 0x10aa,
+ 0x5275, 0x0ad1,
+ 0x527d, 0x10ae,
+ 0x527f, 0x10ad,
+ 0x5283, 0x05a2,
+ 0x5287, 0x0736,
+ 0x5288, 0x10b3,
+ 0x5289, 0x0f75,
+ 0x528d, 0x10af,
+ 0x5291, 0x10b4,
+ 0x5292, 0x10b1,
+ 0x5294, 0x10b0,
+ 0x529b, 0x0f97,
+ 0x529c, 0x20cf,
+ 0x529f, 0x07ad,
+ 0x52a0, 0x0543,
+ 0x52a3, 0x0fbc,
+ 0x52a6, 0x20d0,
+ 0x52a9, 0x097f,
+ 0x52aa, 0x0c52,
+ 0x52ab, 0x07f7,
+ 0x52ac, 0x10b7,
+ 0x52af, 0x217d,
+ 0x52b1, 0x0fad,
+ 0x52b4, 0x0fd1,
+ 0x52b5, 0x10ba,
+ 0x52b9, 0x07ae,
+ 0x52bc, 0x10b9,
+ 0x52be, 0x058d,
+ 0x52c0, 0x20d1,
+ 0x52c1, 0x10bb,
+ 0x52c3, 0x0e84,
+ 0x52c5, 0x0bd8,
+ 0x52c7, 0x0f10,
+ 0x52c9, 0x0e29,
+ 0x52cd, 0x10bc,
+ 0x52d2, 0x1bee,
+ 0x52d5, 0x0c88,
+ 0x52d7, 0x10bd,
+ 0x52d8, 0x05e6,
+ 0x52d9, 0x0ebf,
+ 0x52db, 0x20d2,
+ 0x52dd, 0x0989,
+ 0x52de, 0x10be,
+ 0x52df, 0x0e37,
+ 0x52e0, 0x10c2,
+ 0x52e2, 0x0a4e,
+ 0x52e3, 0x10bf,
+ 0x52e4, 0x06c8,
+ 0x52e6, 0x10c0,
+ 0x52e7, 0x05e7,
+ 0x52f2, 0x0704,
+ 0x52f3, 0x10c3,
+ 0x52f5, 0x10c4,
+ 0x52f8, 0x10c5,
+ 0x52fa, 0x0907,
+ 0x52fe, 0x07af,
+ 0x52ff, 0x0eea,
+ 0x5300, 0x20d3,
+ 0x5301, 0x0ef4,
+ 0x5302, 0x0ccf,
+ 0x5305, 0x0e41,
+ 0x5306, 0x10c7,
+ 0x5307, 0x20d4,
+ 0x5308, 0x10c8,
+ 0x530d, 0x10ca,
+ 0x530f, 0x10cc,
+ 0x5310, 0x10cb,
+ 0x5315, 0x10cd,
+ 0x5316, 0x053d,
+ 0x5317, 0x0e7a,
+ 0x5319, 0x086c,
+ 0x531a, 0x10ce,
+ 0x531d, 0x0adb,
+ 0x5320, 0x098a,
+ 0x5321, 0x06a1,
+ 0x5323, 0x10cf,
+ 0x5324, 0x20d5,
+ 0x532a, 0x0d6f,
+ 0x532f, 0x10d0,
+ 0x5331, 0x10d1,
+ 0x5333, 0x10d2,
+ 0x5338, 0x10d3,
+ 0x5339, 0x0d96,
+ 0x533a, 0x06e0,
+ 0x533b, 0x04a9,
+ 0x533f, 0x0c97,
+ 0x5340, 0x10d4,
+ 0x5341, 0x0947,
+ 0x5343, 0x0a8d,
+ 0x5345, 0x10d6,
+ 0x5346, 0x10d5,
+ 0x5347, 0x098b,
+ 0x5348, 0x0795,
+ 0x5349, 0x10d8,
+ 0x534a, 0x0d52,
+ 0x534d, 0x10d9,
+ 0x5351, 0x0d70,
+ 0x5352, 0x0b14,
+ 0x5353, 0x0b4e,
+ 0x5354, 0x06a0,
+ 0x5357, 0x0cc6,
+ 0x5358, 0x0b6f,
+ 0x535a, 0x0d24,
+ 0x535c, 0x0e7c,
+ 0x535e, 0x10db,
+ 0x5360, 0x0a8e,
+ 0x5366, 0x070b,
+ 0x5369, 0x10dc,
+ 0x536e, 0x10dd,
+ 0x536f, 0x04ce,
+ 0x5370, 0x04b9,
+ 0x5371, 0x0629,
+ 0x5372, 0x20d6,
+ 0x5373, 0x0b08,
+ 0x5374, 0x066b,
+ 0x5375, 0x0f5b,
+ 0x5377, 0x10e0,
+ 0x5378, 0x0537,
+ 0x537b, 0x10df,
+ 0x537f, 0x06a2,
+ 0x5382, 0x10e1,
+ 0x5384, 0x0efd,
+ 0x5393, 0x20d7,
+ 0x5396, 0x10e2,
+ 0x5398, 0x0f9a,
+ 0x539a, 0x07b0,
+ 0x539f, 0x076a,
+ 0x53a0, 0x10e3,
+ 0x53a5, 0x10e5,
+ 0x53a6, 0x10e4,
+ 0x53a8, 0x0a25,
+ 0x53a9, 0x04db,
+ 0x53ad, 0x0500,
+ 0x53ae, 0x10e6,
+ 0x53b0, 0x10e7,
+ 0x53b2, 0x20d8,
+ 0x53b3, 0x076b,
+ 0x53b6, 0x10e8,
+ 0x53bb, 0x0688,
+ 0x53c2, 0x0880,
+ 0x53c3, 0x10e9,
+ 0x53c8, 0x0ea2,
+ 0x53c9, 0x0825,
+ 0x53ca, 0x0674,
+ 0x53cb, 0x0f11,
+ 0x53cc, 0x0ad2,
+ 0x53cd, 0x0d53,
+ 0x53ce, 0x0929,
+ 0x53d4, 0x0951,
+ 0x53d6, 0x0914,
+ 0x53d7, 0x0921,
+ 0x53d9, 0x0980,
+ 0x53db, 0x0d54,
+ 0x53dd, 0x20d9,
+ 0x53df, 0x10ec,
+ 0x53e1, 0x04e5,
+ 0x53e2, 0x0ad3,
+ 0x53e3, 0x07b1,
+ 0x53e4, 0x0779,
+ 0x53e5, 0x06df,
+ 0x53e8, 0x10f0,
+ 0x53e9, 0x0b5f,
+ 0x53ea, 0x0b5e,
+ 0x53eb, 0x06a3,
+ 0x53ec, 0x098c,
+ 0x53ed, 0x10f1,
+ 0x53ee, 0x10ef,
+ 0x53ef, 0x0544,
+ 0x53f0, 0x0b46,
+ 0x53f1, 0x08e4,
+ 0x53f2, 0x0899,
+ 0x53f3, 0x04c8,
+ 0x53f6, 0x05ce,
+ 0x53f7, 0x07f8,
+ 0x53f8, 0x0898,
+ 0x53fa, 0x10f2,
+ 0x5401, 0x10f3,
+ 0x5403, 0x0663,
+ 0x5404, 0x05a4,
+ 0x5408, 0x07f9,
+ 0x5409, 0x0662,
+ 0x540a, 0x0bfb,
+ 0x540b, 0x04c7,
+ 0x540c, 0x0c89,
+ 0x540d, 0x0eca,
+ 0x540e, 0x07b3,
+ 0x540f, 0x0f63,
+ 0x5410, 0x0c41,
+ 0x5411, 0x07b2,
+ 0x541b, 0x0705,
+ 0x541d, 0x10fc,
+ 0x541f, 0x06db,
+ 0x5420, 0x0e78,
+ 0x5426, 0x0d71,
+ 0x5429, 0x10fb,
+ 0x542b, 0x061a,
+ 0x542c, 0x10f6,
+ 0x542e, 0x10f9,
+ 0x5436, 0x10fa,
+ 0x5438, 0x0675,
+ 0x5439, 0x0a27,
+ 0x543b, 0x0dfd,
+ 0x543c, 0x10f8,
+ 0x543d, 0x10f4,
+ 0x543e, 0x0797,
+ 0x5440, 0x10f5,
+ 0x5442, 0x0fca,
+ 0x5446, 0x0e42,
+ 0x5448, 0x0c04,
+ 0x5449, 0x0796,
+ 0x544a, 0x0802,
+ 0x544e, 0x10fd,
+ 0x5451, 0x0cb5,
+ 0x545f, 0x1101,
+ 0x5468, 0x092a,
+ 0x546a, 0x0922,
+ 0x5470, 0x1104,
+ 0x5471, 0x1102,
+ 0x5473, 0x0eaf,
+ 0x5475, 0x10ff,
+ 0x5476, 0x1108,
+ 0x5477, 0x1103,
+ 0x547b, 0x1106,
+ 0x547c, 0x077a,
+ 0x547d, 0x0ecb,
+ 0x5480, 0x1107,
+ 0x5484, 0x1109,
+ 0x5486, 0x110b,
+ 0x548a, 0x20dc,
+ 0x548b, 0x0860,
+ 0x548c, 0x0fe8,
+ 0x548e, 0x1100,
+ 0x548f, 0x10fe,
+ 0x5490, 0x110a,
+ 0x5492, 0x1105,
+ 0x549c, 0x20db,
+ 0x54a2, 0x110d,
+ 0x54a4, 0x1116,
+ 0x54a5, 0x110f,
+ 0x54a8, 0x1113,
+ 0x54a9, 0x20dd,
+ 0x54ab, 0x1114,
+ 0x54ac, 0x1110,
+ 0x54af, 0x1131,
+ 0x54b2, 0x0859,
+ 0x54b3, 0x058f,
+ 0x54b8, 0x110e,
+ 0x54bc, 0x1118,
+ 0x54bd, 0x04ba,
+ 0x54be, 0x1117,
+ 0x54c0, 0x0469,
+ 0x54c1, 0x0dbc,
+ 0x54c2, 0x1115,
+ 0x54c4, 0x1111,
+ 0x54c7, 0x110c,
+ 0x54c8, 0x1112,
+ 0x54c9, 0x0838,
+ 0x54d8, 0x1119,
+ 0x54e1, 0x04bb,
+ 0x54e2, 0x1122,
+ 0x54e5, 0x111a,
+ 0x54e8, 0x098d,
+ 0x54e9, 0x0e97,
+ 0x54ed, 0x1120,
+ 0x54ee, 0x111f,
+ 0x54f2, 0x0c29,
+ 0x54fa, 0x1121,
+ 0x54fd, 0x111e,
+ 0x54ff, 0x20de,
+ 0x5504, 0x04d6,
+ 0x5506, 0x0826,
+ 0x5507, 0x09f6,
+ 0x550f, 0x111c,
+ 0x5510, 0x0c5c,
+ 0x5514, 0x111d,
+ 0x5516, 0x0466,
+ 0x552e, 0x1127,
+ 0x552f, 0x0f0d,
+ 0x5531, 0x098f,
+ 0x5533, 0x112d,
+ 0x5538, 0x112c,
+ 0x5539, 0x1123,
+ 0x553e, 0x0b23,
+ 0x5540, 0x1124,
+ 0x5544, 0x0b4f,
+ 0x5545, 0x1129,
+ 0x5546, 0x098e,
+ 0x554c, 0x1126,
+ 0x554f, 0x0ef0,
+ 0x5553, 0x0712,
+ 0x5556, 0x112a,
+ 0x555c, 0x1128,
+ 0x555d, 0x112e,
+ 0x555e, 0x1dd1,
+ 0x5563, 0x1125,
+ 0x557b, 0x1134,
+ 0x557c, 0x1139,
+ 0x557e, 0x1135,
+ 0x5580, 0x1130,
+ 0x5583, 0x113a,
+ 0x5584, 0x0ab3,
+ 0x5586, 0x20df,
+ 0x5587, 0x113c,
+ 0x5589, 0x07b4,
+ 0x558a, 0x1132,
+ 0x558b, 0x0bbb,
+ 0x5598, 0x1136,
+ 0x5599, 0x112f,
+ 0x559a, 0x05e9,
+ 0x559c, 0x062a,
+ 0x559d, 0x05c3,
+ 0x559e, 0x1137,
+ 0x559f, 0x1133,
+ 0x55a7, 0x074c,
+ 0x55a8, 0x113d,
+ 0x55a9, 0x113b,
+ 0x55aa, 0x0ad5,
+ 0x55ab, 0x0664,
+ 0x55ac, 0x06a4,
+ 0x55ae, 0x1138,
+ 0x55b0, 0x06ec,
+ 0x55b6, 0x04e6,
+ 0x55c4, 0x1141,
+ 0x55c5, 0x113f,
+ 0x55c7, 0x1178,
+ 0x55d4, 0x1144,
+ 0x55da, 0x113e,
+ 0x55dc, 0x1142,
+ 0x55df, 0x1140,
+ 0x55e3, 0x089a,
+ 0x55e4, 0x1143,
+ 0x55f7, 0x1146,
+ 0x55f9, 0x114b,
+ 0x55fd, 0x1149,
+ 0x55fe, 0x1148,
+ 0x5606, 0x0b70,
+ 0x5609, 0x0545,
+ 0x5614, 0x1145,
+ 0x5616, 0x1147,
+ 0x5617, 0x0990,
+ 0x5618, 0x04d5,
+ 0x561b, 0x114a,
+ 0x5629, 0x055e,
+ 0x562f, 0x1155,
+ 0x5631, 0x09e4,
+ 0x5632, 0x1151,
+ 0x5634, 0x114f,
+ 0x5636, 0x1150,
+ 0x5638, 0x1152,
+ 0x5642, 0x04df,
+ 0x564c, 0x0abb,
+ 0x564e, 0x114c,
+ 0x5650, 0x114d,
+ 0x5653, 0x1f1b,
+ 0x565b, 0x05d8,
+ 0x5664, 0x1154,
+ 0x5668, 0x062b,
+ 0x566a, 0x1157,
+ 0x566b, 0x1153,
+ 0x566c, 0x1156,
+ 0x5674, 0x0dfe,
+ 0x5678, 0x0cad,
+ 0x567a, 0x0d4c,
+ 0x5680, 0x1159,
+ 0x5686, 0x1158,
+ 0x5687, 0x05a3,
+ 0x568a, 0x115a,
+ 0x568f, 0x115d,
+ 0x5694, 0x115c,
+ 0x5699, 0x1de6,
+ 0x56a0, 0x115b,
+ 0x56a2, 0x0cef,
+ 0x56a5, 0x115e,
+ 0x56ae, 0x115f,
+ 0x56b4, 0x1161,
+ 0x56b6, 0x1160,
+ 0x56bc, 0x1163,
+ 0x56c0, 0x1166,
+ 0x56c1, 0x1164,
+ 0x56c2, 0x1162,
+ 0x56c3, 0x1165,
+ 0x56c8, 0x1167,
+ 0x56ca, 0x1e5a,
+ 0x56ce, 0x1168,
+ 0x56d1, 0x1169,
+ 0x56d3, 0x116a,
+ 0x56d7, 0x116b,
+ 0x56d8, 0x107c,
+ 0x56da, 0x0928,
+ 0x56db, 0x089b,
+ 0x56de, 0x0573,
+ 0x56e0, 0x04bc,
+ 0x56e3, 0x0b82,
+ 0x56ee, 0x116c,
+ 0x56f0, 0x0814,
+ 0x56f2, 0x0493,
+ 0x56f3, 0x0a24,
+ 0x56f9, 0x116d,
+ 0x56fa, 0x077b,
+ 0x56fd, 0x0803,
+ 0x56ff, 0x116f,
+ 0x5700, 0x116e,
+ 0x5703, 0x0e30,
+ 0x5704, 0x1170,
+ 0x5708, 0x1172,
+ 0x5709, 0x1171,
+ 0x570b, 0x1173,
+ 0x570d, 0x1174,
+ 0x570f, 0x074d,
+ 0x5712, 0x0502,
+ 0x5713, 0x1175,
+ 0x5716, 0x1177,
+ 0x5718, 0x1176,
+ 0x571c, 0x1179,
+ 0x571f, 0x0c54,
+ 0x5726, 0x117a,
+ 0x5727, 0x0479,
+ 0x5728, 0x084f,
+ 0x572d, 0x0713,
+ 0x5730, 0x0b8d,
+ 0x5737, 0x117b,
+ 0x573b, 0x117e,
+ 0x5740, 0x117f,
+ 0x5742, 0x0854,
+ 0x5747, 0x06c9,
+ 0x574a, 0x0e65,
+ 0x574e, 0x117d,
+ 0x574f, 0x1180,
+ 0x5750, 0x0831,
+ 0x5751, 0x07b5,
+ 0x5759, 0x20e0,
+ 0x5761, 0x1184,
+ 0x5764, 0x0815,
+ 0x5765, 0x20e1,
+ 0x5766, 0x0b71,
+ 0x5769, 0x1181,
+ 0x576a, 0x0bf6,
+ 0x577f, 0x1185,
+ 0x5782, 0x0a28,
+ 0x5788, 0x1183,
+ 0x5789, 0x1186,
+ 0x578b, 0x0715,
+ 0x5793, 0x1187,
+ 0x57a0, 0x1188,
+ 0x57a2, 0x07b6,
+ 0x57a3, 0x059e,
+ 0x57a4, 0x118a,
+ 0x57aa, 0x118b,
+ 0x57ac, 0x20e2,
+ 0x57b0, 0x118c,
+ 0x57b3, 0x1189,
+ 0x57c0, 0x1182,
+ 0x57c3, 0x118d,
+ 0x57c6, 0x118e,
+ 0x57c7, 0x20e4,
+ 0x57c8, 0x20e3,
+ 0x57cb, 0x0e92,
+ 0x57ce, 0x09d3,
+ 0x57d2, 0x1190,
+ 0x57d4, 0x118f,
+ 0x57d6, 0x1193,
+ 0x57dc, 0x0cee,
+ 0x57df, 0x04ac,
+ 0x57e0, 0x0dc8,
+ 0x57e3, 0x1194,
+ 0x57f4, 0x09e5,
+ 0x57f7, 0x08e5,
+ 0x57f9, 0x0d13,
+ 0x57fa, 0x062c,
+ 0x57fc, 0x085b,
+ 0x5800, 0x0e87,
+ 0x5802, 0x0c8a,
+ 0x5805, 0x074e,
+ 0x5806, 0x0b2f,
+ 0x580a, 0x1192,
+ 0x580b, 0x1195,
+ 0x5815, 0x0b24,
+ 0x5819, 0x1196,
+ 0x581d, 0x1197,
+ 0x5821, 0x1199,
+ 0x5824, 0x0c05,
+ 0x582a, 0x05ea,
+ 0x582f, 0x1d32,
+ 0x5830, 0x0503,
+ 0x5831, 0x0e43,
+ 0x5834, 0x09d4,
+ 0x5835, 0x0c42,
+ 0x583a, 0x0856,
+ 0x583d, 0x119f,
+ 0x5840, 0x0e0d,
+ 0x5841, 0x0fa5,
+ 0x584a, 0x0574,
+ 0x584b, 0x119b,
+ 0x5851, 0x0abc,
+ 0x5852, 0x119e,
+ 0x5854, 0x0c5d,
+ 0x5857, 0x0c43,
+ 0x5858, 0x0c5e,
+ 0x5859, 0x0d4d,
+ 0x585a, 0x0be9,
+ 0x585e, 0x0839,
+ 0x5861, 0x1e47,
+ 0x5862, 0x119a,
+ 0x5869, 0x0518,
+ 0x586b, 0x0c30,
+ 0x5870, 0x119c,
+ 0x5872, 0x1198,
+ 0x5875, 0x0a16,
+ 0x5879, 0x11a0,
+ 0x587e, 0x0958,
+ 0x5883, 0x06a5,
+ 0x5885, 0x11a1,
+ 0x5893, 0x0e38,
+ 0x5897, 0x0aff,
+ 0x589c, 0x0be2,
+ 0x589e, 0x20e7,
+ 0x589f, 0x11a3,
+ 0x58a8, 0x0e7d,
+ 0x58ab, 0x11a4,
+ 0x58ae, 0x11a9,
+ 0x58b2, 0x20e8,
+ 0x58b3, 0x0dff,
+ 0x58b8, 0x11a8,
+ 0x58b9, 0x11a2,
+ 0x58ba, 0x11a5,
+ 0x58bb, 0x11a7,
+ 0x58be, 0x0816,
+ 0x58c1, 0x0e19,
+ 0x58c5, 0x11aa,
+ 0x58c7, 0x0b83,
+ 0x58ca, 0x0575,
+ 0x58cc, 0x09d5,
+ 0x58d1, 0x11ac,
+ 0x58d3, 0x11ab,
+ 0x58d5, 0x07fa,
+ 0x58d7, 0x11ad,
+ 0x58d8, 0x11af,
+ 0x58d9, 0x11ae,
+ 0x58dc, 0x11b1,
+ 0x58de, 0x11a6,
+ 0x58df, 0x11b3,
+ 0x58e4, 0x11b2,
+ 0x58e5, 0x11b0,
+ 0x58eb, 0x089c,
+ 0x58ec, 0x0a17,
+ 0x58ee, 0x0ad6,
+ 0x58ef, 0x11b4,
+ 0x58f0, 0x0a60,
+ 0x58f1, 0x04b1,
+ 0x58f2, 0x0d1a,
+ 0x58f7, 0x0bf7,
+ 0x58f9, 0x11b6,
+ 0x58fa, 0x11b5,
+ 0x58fb, 0x11b7,
+ 0x5902, 0x11ba,
+ 0x5909, 0x0e21,
+ 0x590a, 0x11bb,
+ 0x590b, 0x20e9,
+ 0x590f, 0x0546,
+ 0x5910, 0x11bc,
+ 0x5915, 0x0f26,
+ 0x5916, 0x058e,
+ 0x5918, 0x10de,
+ 0x5919, 0x0952,
+ 0x591a, 0x0b1f,
+ 0x591b, 0x11bd,
+ 0x591c, 0x0ef7,
+ 0x5922, 0x0ec0,
+ 0x5925, 0x11bf,
+ 0x5927, 0x0b47,
+ 0x5929, 0x0c31,
+ 0x592a, 0x0b20,
+ 0x592b, 0x0dc9,
+ 0x592c, 0x11c0,
+ 0x592e, 0x051d,
+ 0x5931, 0x08e6,
+ 0x5932, 0x11c2,
+ 0x5937, 0x0494,
+ 0x5938, 0x11c3,
+ 0x593e, 0x11c4,
+ 0x5944, 0x0504,
+ 0x5947, 0x062d,
+ 0x5948, 0x0cb8,
+ 0x5949, 0x0e44,
+ 0x594e, 0x11c8,
+ 0x594f, 0x0ad7,
+ 0x5950, 0x11c7,
+ 0x5951, 0x0716,
+ 0x5953, 0x20ea,
+ 0x5954, 0x0e89,
+ 0x5955, 0x11c6,
+ 0x5957, 0x0c5f,
+ 0x5958, 0x11ca,
+ 0x595a, 0x11c9,
+ 0x595b, 0x20eb,
+ 0x595d, 0x20ec,
+ 0x5960, 0x11cc,
+ 0x5962, 0x11cb,
+ 0x5963, 0x20ed,
+ 0x5965, 0x051e,
+ 0x5967, 0x11cd,
+ 0x5968, 0x0991,
+ 0x5969, 0x11cf,
+ 0x596a, 0x0b63,
+ 0x596c, 0x11ce,
+ 0x596e, 0x0e03,
+ 0x5973, 0x0981,
+ 0x5974, 0x0c55,
+ 0x5978, 0x11d0,
+ 0x597d, 0x07b7,
+ 0x5981, 0x11d1,
+ 0x5982, 0x0cd7,
+ 0x5983, 0x0d72,
+ 0x5984, 0x0edd,
+ 0x598a, 0x0cdb,
+ 0x598d, 0x11da,
+ 0x5993, 0x0652,
+ 0x5996, 0x0f2f,
+ 0x5999, 0x0ebb,
+ 0x599b, 0x1239,
+ 0x599d, 0x11d2,
+ 0x59a3, 0x11d5,
+ 0x59a4, 0x20ee,
+ 0x59a5, 0x0b25,
+ 0x59a8, 0x0e66,
+ 0x59ac, 0x0c44,
+ 0x59b2, 0x11d6,
+ 0x59b9, 0x0e93,
+ 0x59ba, 0x20ef,
+ 0x59bb, 0x083a,
+ 0x59be, 0x0992,
+ 0x59c6, 0x11d7,
+ 0x59c9, 0x089e,
+ 0x59cb, 0x089d,
+ 0x59d0, 0x047d,
+ 0x59d1, 0x077c,
+ 0x59d3, 0x0a4f,
+ 0x59d4, 0x0495,
+ 0x59d9, 0x11db,
+ 0x59dc, 0x11d9,
+ 0x59e5, 0x04da,
+ 0x59e6, 0x05eb,
+ 0x59e8, 0x11d8,
+ 0x59ea, 0x0ed1,
+ 0x59eb, 0x0da3,
+ 0x59f6, 0x046c,
+ 0x59fb, 0x04bd,
+ 0x59ff, 0x089f,
+ 0x5a01, 0x0496,
+ 0x5a03, 0x0467,
+ 0x5a09, 0x11e1,
+ 0x5a11, 0x11df,
+ 0x5a18, 0x0ec8,
+ 0x5a1a, 0x11e2,
+ 0x5a1c, 0x11e0,
+ 0x5a1f, 0x11de,
+ 0x5a20, 0x09f7,
+ 0x5a25, 0x11dd,
+ 0x5a29, 0x0e2a,
+ 0x5a2f, 0x0798,
+ 0x5a35, 0x11e6,
+ 0x5a3c, 0x0993,
+ 0x5a40, 0x11e3,
+ 0x5a41, 0x0fd2,
+ 0x5a46, 0x0d02,
+ 0x5a49, 0x11e5,
+ 0x5a5a, 0x0817,
+ 0x5a62, 0x11e8,
+ 0x5a66, 0x0dca,
+ 0x5a6a, 0x11e9,
+ 0x5a6c, 0x11e4,
+ 0x5a7f, 0x0ec7,
+ 0x5a92, 0x0d14,
+ 0x5a9a, 0x11ea,
+ 0x5a9b, 0x0da4,
+ 0x5abc, 0x11eb,
+ 0x5abd, 0x11ef,
+ 0x5abe, 0x11ec,
+ 0x5ac1, 0x0547,
+ 0x5ac2, 0x11ee,
+ 0x5ac9, 0x08e7,
+ 0x5acb, 0x11ed,
+ 0x5acc, 0x074f,
+ 0x5ad0, 0x11fb,
+ 0x5ad6, 0x11f4,
+ 0x5ad7, 0x11f1,
+ 0x5ae1, 0x0ba2,
+ 0x5ae3, 0x11f0,
+ 0x5ae6, 0x11f2,
+ 0x5ae9, 0x11f3,
+ 0x5afa, 0x11f5,
+ 0x5b09, 0x062e,
+ 0x5b0b, 0x11f8,
+ 0x5b0c, 0x11f7,
+ 0x5b16, 0x11f9,
+ 0x5b22, 0x09d6,
+ 0x5b2a, 0x11fc,
+ 0x5b2c, 0x0bf8,
+ 0x5b30, 0x04e7,
+ 0x5b32, 0x11fa,
+ 0x5b36, 0x11fd,
+ 0x5b3e, 0x11fe,
+ 0x5b40, 0x1201,
+ 0x5b43, 0x11ff,
+ 0x5b45, 0x1200,
+ 0x5b50, 0x08a0,
+ 0x5b51, 0x1202,
+ 0x5b54, 0x07b8,
+ 0x5b55, 0x1203,
+ 0x5b56, 0x20f0,
+ 0x5b57, 0x08c8,
+ 0x5b58, 0x0b18,
+ 0x5b5a, 0x1204,
+ 0x5b5c, 0x08a8,
+ 0x5b5d, 0x07b9,
+ 0x5b5f, 0x0ede,
+ 0x5b63, 0x0642,
+ 0x5b64, 0x077d,
+ 0x5b65, 0x1206,
+ 0x5b66, 0x05b6,
+ 0x5b69, 0x1207,
+ 0x5b6b, 0x0b19,
+ 0x5b70, 0x1208,
+ 0x5b71, 0x1230,
+ 0x5b73, 0x1209,
+ 0x5b75, 0x120a,
+ 0x5b78, 0x120b,
+ 0x5b7a, 0x120d,
+ 0x5b80, 0x120e,
+ 0x5b83, 0x120f,
+ 0x5b85, 0x0b50,
+ 0x5b87, 0x04c9,
+ 0x5b88, 0x0915,
+ 0x5b89, 0x0486,
+ 0x5b8b, 0x0ad9,
+ 0x5b8c, 0x05ec,
+ 0x5b8d, 0x08e1,
+ 0x5b8f, 0x07ba,
+ 0x5b95, 0x0c60,
+ 0x5b97, 0x092b,
+ 0x5b98, 0x05ed,
+ 0x5b99, 0x0ba6,
+ 0x5b9a, 0x0c06,
+ 0x5b9b, 0x047c,
+ 0x5b9c, 0x0653,
+ 0x5b9d, 0x0e45,
+ 0x5b9f, 0x08ee,
+ 0x5ba2, 0x066c,
+ 0x5ba3, 0x0a8f,
+ 0x5ba4, 0x08e8,
+ 0x5ba5, 0x0f12,
+ 0x5ba6, 0x1210,
+ 0x5bae, 0x0676,
+ 0x5bb0, 0x083b,
+ 0x5bb3, 0x0590,
+ 0x5bb4, 0x0505,
+ 0x5bb5, 0x0994,
+ 0x5bb6, 0x0548,
+ 0x5bb8, 0x1211,
+ 0x5bb9, 0x0f30,
+ 0x5bbf, 0x0953,
+ 0x5bc0, 0x20f1,
+ 0x5bc2, 0x0910,
+ 0x5bc3, 0x1212,
+ 0x5bc4, 0x062f,
+ 0x5bc5, 0x0caa,
+ 0x5bc6, 0x0eb5,
+ 0x5bc7, 0x1213,
+ 0x5bc9, 0x1214,
+ 0x5bcc, 0x0dcb,
+ 0x5bd0, 0x1216,
+ 0x5bd2, 0x05e4,
+ 0x5bd3, 0x06ef,
+ 0x5bd4, 0x1215,
+ 0x5bd8, 0x20f3,
+ 0x5bdb, 0x05ee,
+ 0x5bdd, 0x09f8,
+ 0x5bde, 0x121a,
+ 0x5bdf, 0x086f,
+ 0x5be1, 0x0549,
+ 0x5be2, 0x1219,
+ 0x5be4, 0x1217,
+ 0x5be5, 0x121b,
+ 0x5be6, 0x1218,
+ 0x5be7, 0x0ce1,
+ 0x5be8, 0x148e,
+ 0x5be9, 0x09f9,
+ 0x5beb, 0x121c,
+ 0x5bec, 0x20f4,
+ 0x5bee, 0x0f88,
+ 0x5bf0, 0x121d,
+ 0x5bf3, 0x121f,
+ 0x5bf5, 0x0bbc,
+ 0x5bf6, 0x121e,
+ 0x5bf8, 0x0a47,
+ 0x5bfa, 0x08c9,
+ 0x5bfe, 0x0b30,
+ 0x5bff, 0x0923,
+ 0x5c01, 0x0de7,
+ 0x5c02, 0x0a90,
+ 0x5c04, 0x08f9,
+ 0x5c05, 0x1220,
+ 0x5c06, 0x0995,
+ 0x5c07, 0x1221,
+ 0x5c09, 0x0497,
+ 0x5c0a, 0x0b1a,
+ 0x5c0b, 0x0a18,
+ 0x5c0d, 0x1223,
+ 0x5c0e, 0x0c8b,
+ 0x5c0f, 0x0996,
+ 0x5c11, 0x0997,
+ 0x5c13, 0x1224,
+ 0x5c16, 0x0a91,
+ 0x5c1a, 0x0998,
+ 0x5c1e, 0x20f5,
+ 0x5c20, 0x1225,
+ 0x5c22, 0x1226,
+ 0x5c24, 0x0eec,
+ 0x5c28, 0x1227,
+ 0x5c2d, 0x06be,
+ 0x5c31, 0x092c,
+ 0x5c38, 0x1228,
+ 0x5c3a, 0x0908,
+ 0x5c3b, 0x09f2,
+ 0x5c3c, 0x0ccc,
+ 0x5c3d, 0x0a1a,
+ 0x5c3e, 0x0d8c,
+ 0x5c3f, 0x0cd8,
+ 0x5c40, 0x06c1,
+ 0x5c41, 0x122a,
+ 0x5c45, 0x0689,
+ 0x5c46, 0x122b,
+ 0x5c48, 0x06f6,
+ 0x5c4a, 0x0ca7,
+ 0x5c4b, 0x0530,
+ 0x5c4d, 0x08a1,
+ 0x5c4e, 0x122c,
+ 0x5c4f, 0x122f,
+ 0x5c50, 0x122e,
+ 0x5c51, 0x06f5,
+ 0x5c53, 0x122d,
+ 0x5c55, 0x0c32,
+ 0x5c5b, 0x1e92,
+ 0x5c5e, 0x0b10,
+ 0x5c60, 0x0c45,
+ 0x5c61, 0x08f4,
+ 0x5c62, 0x1e0d,
+ 0x5c64, 0x0ada,
+ 0x5c65, 0x0f64,
+ 0x5c6c, 0x1231,
+ 0x5c6e, 0x1232,
+ 0x5c6f, 0x0cae,
+ 0x5c71, 0x0881,
+ 0x5c76, 0x1234,
+ 0x5c79, 0x1235,
+ 0x5c8c, 0x1236,
+ 0x5c90, 0x0630,
+ 0x5c91, 0x1237,
+ 0x5c94, 0x1238,
+ 0x5ca1, 0x052c,
+ 0x5ca6, 0x20f6,
+ 0x5ca8, 0x0abd,
+ 0x5ca9, 0x0620,
+ 0x5cab, 0x123a,
+ 0x5cac, 0x0eb4,
+ 0x5cb1, 0x0b32,
+ 0x5cb3, 0x05b7,
+ 0x5cb6, 0x123c,
+ 0x5cb7, 0x123e,
+ 0x5cb8, 0x061b,
+ 0x5cba, 0x20f7,
+ 0x5cbb, 0x123b,
+ 0x5cbc, 0x123d,
+ 0x5cbe, 0x1240,
+ 0x5cc5, 0x123f,
+ 0x5cc7, 0x1241,
+ 0x5cd9, 0x1242,
+ 0x5ce0, 0x0c95,
+ 0x5ce1, 0x06a6,
+ 0x5ce8, 0x0565,
+ 0x5ce9, 0x1243,
+ 0x5cea, 0x1248,
+ 0x5ced, 0x1246,
+ 0x5cef, 0x0e47,
+ 0x5cf0, 0x0e46,
+ 0x5cf5, 0x20f8,
+ 0x5cf6, 0x0c61,
+ 0x5cfa, 0x1245,
+ 0x5cfb, 0x095e,
+ 0x5cfd, 0x1244,
+ 0x5d07, 0x0a38,
+ 0x5d0b, 0x1249,
+ 0x5d0e, 0x085a,
+ 0x5d11, 0x124f,
+ 0x5d14, 0x1250,
+ 0x5d15, 0x124a,
+ 0x5d16, 0x0591,
+ 0x5d17, 0x124b,
+ 0x5d18, 0x1254,
+ 0x5d19, 0x1253,
+ 0x5d1a, 0x1252,
+ 0x5d1b, 0x124e,
+ 0x5d1f, 0x124d,
+ 0x5d22, 0x1251,
+ 0x5d27, 0x20f9,
+ 0x5d29, 0x0e48,
+ 0x5d42, 0x20fc,
+ 0x5d4b, 0x1258,
+ 0x5d4c, 0x1255,
+ 0x5d4e, 0x1257,
+ 0x5d50, 0x0f5c,
+ 0x5d52, 0x1256,
+ 0x5d53, 0x20fa,
+ 0x5d5c, 0x124c,
+ 0x5d69, 0x0a39,
+ 0x5d6c, 0x1259,
+ 0x5d6d, 0x20fd,
+ 0x5d6f, 0x0827,
+ 0x5d73, 0x125a,
+ 0x5d76, 0x125b,
+ 0x5d82, 0x125e,
+ 0x5d84, 0x125d,
+ 0x5d87, 0x125c,
+ 0x5d8b, 0x0c62,
+ 0x5d8c, 0x1247,
+ 0x5d90, 0x1264,
+ 0x5d9d, 0x1260,
+ 0x5da2, 0x125f,
+ 0x5dac, 0x1261,
+ 0x5dae, 0x1262,
+ 0x5db7, 0x1265,
+ 0x5db8, 0x20fe,
+ 0x5dba, 0x0fae,
+ 0x5dbc, 0x1266,
+ 0x5dbd, 0x1263,
+ 0x5dc9, 0x1267,
+ 0x5dcc, 0x061c,
+ 0x5dcd, 0x1268,
+ 0x5dd0, 0x2100,
+ 0x5dd2, 0x126a,
+ 0x5dd3, 0x1269,
+ 0x5dd6, 0x126b,
+ 0x5ddb, 0x126c,
+ 0x5ddd, 0x0a92,
+ 0x5dde, 0x092d,
+ 0x5de1, 0x096e,
+ 0x5de3, 0x0ae5,
+ 0x5de5, 0x07bb,
+ 0x5de6, 0x0828,
+ 0x5de7, 0x07bc,
+ 0x5de8, 0x068a,
+ 0x5deb, 0x126d,
+ 0x5dee, 0x0829,
+ 0x5df1, 0x077e,
+ 0x5df2, 0x126e,
+ 0x5df3, 0x0eb2,
+ 0x5df4, 0x0cf9,
+ 0x5df5, 0x126f,
+ 0x5df7, 0x07bd,
+ 0x5dfb, 0x05e8,
+ 0x5dfd, 0x0b65,
+ 0x5dfe, 0x06ca,
+ 0x5e02, 0x08a2,
+ 0x5e03, 0x0dcd,
+ 0x5e06, 0x0d55,
+ 0x5e0b, 0x1270,
+ 0x5e0c, 0x0631,
+ 0x5e11, 0x1273,
+ 0x5e16, 0x0bbd,
+ 0x5e19, 0x1272,
+ 0x5e1a, 0x1271,
+ 0x5e1b, 0x1274,
+ 0x5e1d, 0x0c07,
+ 0x5e25, 0x0a29,
+ 0x5e2b, 0x08a3,
+ 0x5e2d, 0x0a6e,
+ 0x5e2f, 0x0b33,
+ 0x5e30, 0x063c,
+ 0x5e33, 0x0bbe,
+ 0x5e36, 0x1275,
+ 0x5e38, 0x09d7,
+ 0x5e3d, 0x0e67,
+ 0x5e40, 0x1279,
+ 0x5e43, 0x1278,
+ 0x5e44, 0x1277,
+ 0x5e45, 0x0def,
+ 0x5e47, 0x1280,
+ 0x5e4c, 0x0e88,
+ 0x5e4e, 0x127a,
+ 0x5e54, 0x127c,
+ 0x5e55, 0x0e99,
+ 0x5e57, 0x127b,
+ 0x5e5f, 0x127d,
+ 0x5e61, 0x0d3c,
+ 0x5e62, 0x127e,
+ 0x5e63, 0x0e0e,
+ 0x5e64, 0x127f,
+ 0x5e72, 0x05ef,
+ 0x5e73, 0x0e0f,
+ 0x5e74, 0x0ce5,
+ 0x5e75, 0x1281,
+ 0x5e78, 0x07be,
+ 0x5e79, 0x05f0,
+ 0x5e7a, 0x1283,
+ 0x5e7b, 0x076c,
+ 0x5e7c, 0x0f2e,
+ 0x5e7d, 0x0f13,
+ 0x5e7e, 0x0632,
+ 0x5e7f, 0x1285,
+ 0x5e81, 0x0bbf,
+ 0x5e83, 0x07bf,
+ 0x5e84, 0x0999,
+ 0x5e87, 0x0d73,
+ 0x5e8a, 0x099a,
+ 0x5e8f, 0x0982,
+ 0x5e95, 0x0c08,
+ 0x5e96, 0x0e49,
+ 0x5e97, 0x0c33,
+ 0x5e9a, 0x07c0,
+ 0x5e9c, 0x0dce,
+ 0x5ea0, 0x1286,
+ 0x5ea6, 0x0c53,
+ 0x5ea7, 0x0832,
+ 0x5eab, 0x077f,
+ 0x5ead, 0x0c09,
+ 0x5eb5, 0x0487,
+ 0x5eb6, 0x0978,
+ 0x5eb7, 0x07c1,
+ 0x5eb8, 0x0f31,
+ 0x5ec1, 0x1287,
+ 0x5ec3, 0x0d07,
+ 0x5ec8, 0x1289,
+ 0x5ec9, 0x0fbf,
+ 0x5eca, 0x0fd3,
+ 0x5ecf, 0x128b,
+ 0x5ed0, 0x128a,
+ 0x5ed3, 0x05a5,
+ 0x5ed6, 0x128c,
+ 0x5eda, 0x128f,
+ 0x5edd, 0x128e,
+ 0x5edf, 0x0db2,
+ 0x5ee0, 0x099b,
+ 0x5ee1, 0x1292,
+ 0x5ee2, 0x1291,
+ 0x5ee3, 0x128d,
+ 0x5ee8, 0x1293,
+ 0x5eec, 0x1295,
+ 0x5ef0, 0x1298,
+ 0x5ef1, 0x1296,
+ 0x5ef3, 0x1297,
+ 0x5ef4, 0x1299,
+ 0x5ef6, 0x0506,
+ 0x5ef7, 0x0c0a,
+ 0x5ef8, 0x129a,
+ 0x5efa, 0x0750,
+ 0x5efb, 0x0576,
+ 0x5efc, 0x0cec,
+ 0x5efe, 0x129b,
+ 0x5eff, 0x0cd3,
+ 0x5f01, 0x0e2b,
+ 0x5f03, 0x129c,
+ 0x5f04, 0x0fd4,
+ 0x5f09, 0x129d,
+ 0x5f0a, 0x0e10,
+ 0x5f0b, 0x12a0,
+ 0x5f0c, 0x0ffa,
+ 0x5f0d, 0x100a,
+ 0x5f0f, 0x08dc,
+ 0x5f10, 0x0ccd,
+ 0x5f11, 0x12a1,
+ 0x5f13, 0x0677,
+ 0x5f14, 0x0bc0,
+ 0x5f15, 0x04be,
+ 0x5f16, 0x12a2,
+ 0x5f17, 0x0df6,
+ 0x5f18, 0x07c2,
+ 0x5f1b, 0x0b8e,
+ 0x5f1f, 0x0c0b,
+ 0x5f21, 0x2101,
+ 0x5f25, 0x0efb,
+ 0x5f26, 0x076d,
+ 0x5f27, 0x0780,
+ 0x5f29, 0x12a3,
+ 0x5f2d, 0x12a4,
+ 0x5f2f, 0x12aa,
+ 0x5f31, 0x0911,
+ 0x5f34, 0x2102,
+ 0x5f35, 0x0bc1,
+ 0x5f37, 0x06a7,
+ 0x5f38, 0x12a5,
+ 0x5f3c, 0x0d9d,
+ 0x5f3e, 0x0b84,
+ 0x5f41, 0x12a6,
+ 0x5f45, 0x20b2,
+ 0x5f48, 0x12a7,
+ 0x5f4a, 0x06a8,
+ 0x5f4c, 0x12a8,
+ 0x5f4e, 0x12a9,
+ 0x5f51, 0x12ab,
+ 0x5f53, 0x0c70,
+ 0x5f56, 0x12ac,
+ 0x5f59, 0x12ae,
+ 0x5f5c, 0x129f,
+ 0x5f5d, 0x129e,
+ 0x5f61, 0x12af,
+ 0x5f62, 0x0717,
+ 0x5f66, 0x0d99,
+ 0x5f67, 0x2103,
+ 0x5f69, 0x083c,
+ 0x5f6a, 0x0da9,
+ 0x5f6b, 0x0bc2,
+ 0x5f6c, 0x0dbd,
+ 0x5f6d, 0x12b0,
+ 0x5f70, 0x099c,
+ 0x5f71, 0x04e8,
+ 0x5f73, 0x12b1,
+ 0x5f77, 0x12b2,
+ 0x5f79, 0x0efe,
+ 0x5f7c, 0x0d74,
+ 0x5f7f, 0x12b5,
+ 0x5f80, 0x051f,
+ 0x5f81, 0x0a50,
+ 0x5f82, 0x12b4,
+ 0x5f83, 0x12b3,
+ 0x5f84, 0x0718,
+ 0x5f85, 0x0b34,
+ 0x5f87, 0x12b9,
+ 0x5f88, 0x12b7,
+ 0x5f8a, 0x12b6,
+ 0x5f8b, 0x0f6f,
+ 0x5f8c, 0x0799,
+ 0x5f90, 0x0983,
+ 0x5f91, 0x12b8,
+ 0x5f92, 0x0c46,
+ 0x5f93, 0x0948,
+ 0x5f97, 0x0c98,
+ 0x5f98, 0x12bc,
+ 0x5f99, 0x12bb,
+ 0x5f9e, 0x12ba,
+ 0x5fa0, 0x12bd,
+ 0x5fa1, 0x079a,
+ 0x5fa8, 0x12be,
+ 0x5fa9, 0x0dee,
+ 0x5faa, 0x0965,
+ 0x5fad, 0x12bf,
+ 0x5fae, 0x0d8d,
+ 0x5fb3, 0x0c99,
+ 0x5fb4, 0x0bc3,
+ 0x5fb7, 0x2104,
+ 0x5fb9, 0x0c2a,
+ 0x5fbc, 0x12c0,
+ 0x5fbd, 0x0645,
+ 0x5fc3, 0x09fa,
+ 0x5fc5, 0x0d9e,
+ 0x5fcc, 0x0633,
+ 0x5fcd, 0x0cdc,
+ 0x5fd6, 0x12c1,
+ 0x5fd7, 0x08a4,
+ 0x5fd8, 0x0e68,
+ 0x5fdc, 0x0520,
+ 0x5fdd, 0x12c6,
+ 0x5fde, 0x2105,
+ 0x5fe0, 0x0ba7,
+ 0x5fe4, 0x12c3,
+ 0x5feb, 0x0577,
+ 0x5ff0, 0x12f6,
+ 0x5ff1, 0x12c5,
+ 0x5ff5, 0x0ce6,
+ 0x5ff8, 0x12c4,
+ 0x5ffb, 0x12c2,
+ 0x5ffd, 0x080c,
+ 0x5fff, 0x12c8,
+ 0x600e, 0x12ce,
+ 0x600f, 0x12d4,
+ 0x6010, 0x12cc,
+ 0x6012, 0x0c56,
+ 0x6015, 0x12d1,
+ 0x6016, 0x0dcf,
+ 0x6019, 0x12cb,
+ 0x601b, 0x12d0,
+ 0x601c, 0x0faf,
+ 0x601d, 0x08a5,
+ 0x6020, 0x0b35,
+ 0x6021, 0x12c9,
+ 0x6025, 0x0678,
+ 0x6026, 0x12d3,
+ 0x6027, 0x0a51,
+ 0x6028, 0x0507,
+ 0x6029, 0x12cd,
+ 0x602a, 0x0578,
+ 0x602b, 0x12d2,
+ 0x602f, 0x06a9,
+ 0x6031, 0x12cf,
+ 0x603a, 0x12d5,
+ 0x6041, 0x12d7,
+ 0x6042, 0x12e1,
+ 0x6043, 0x12df,
+ 0x6046, 0x12dc,
+ 0x604a, 0x12db,
+ 0x604b, 0x0fc0,
+ 0x604d, 0x12dd,
+ 0x6050, 0x06aa,
+ 0x6052, 0x07c3,
+ 0x6055, 0x0984,
+ 0x6059, 0x12e4,
+ 0x605a, 0x12d6,
+ 0x605d, 0x2106,
+ 0x605f, 0x12da,
+ 0x6060, 0x12ca,
+ 0x6062, 0x057a,
+ 0x6063, 0x12de,
+ 0x6064, 0x12e0,
+ 0x6065, 0x0b8f,
+ 0x6068, 0x0818,
+ 0x6069, 0x0538,
+ 0x606a, 0x12d8,
+ 0x606b, 0x12e3,
+ 0x606c, 0x12e2,
+ 0x606d, 0x06ab,
+ 0x606f, 0x0b09,
+ 0x6070, 0x05c4,
+ 0x6075, 0x0719,
+ 0x6077, 0x12d9,
+ 0x6081, 0x12e5,
+ 0x6083, 0x12e8,
+ 0x6084, 0x12ea,
+ 0x6085, 0x2107,
+ 0x6089, 0x08e9,
+ 0x608a, 0x2108,
+ 0x608b, 0x12f0,
+ 0x608c, 0x0c0c,
+ 0x608d, 0x12e6,
+ 0x6092, 0x12ee,
+ 0x6094, 0x0579,
+ 0x6096, 0x12ec,
+ 0x609a, 0x12e9,
+ 0x609b, 0x12eb,
+ 0x609f, 0x079b,
+ 0x60a0, 0x0f14,
+ 0x60a3, 0x05f1,
+ 0x60a6, 0x04fb,
+ 0x60a7, 0x12ef,
+ 0x60a9, 0x0cf0,
+ 0x60aa, 0x0471,
+ 0x60b2, 0x0d75,
+ 0x60b3, 0x12c7,
+ 0x60b4, 0x12f5,
+ 0x60b5, 0x12f9,
+ 0x60b6, 0x0ef1,
+ 0x60b8, 0x12f2,
+ 0x60bc, 0x0c63,
+ 0x60bd, 0x12f7,
+ 0x60c5, 0x09d8,
+ 0x60c6, 0x12f8,
+ 0x60c7, 0x0caf,
+ 0x60d1, 0x0fed,
+ 0x60d3, 0x12f4,
+ 0x60d5, 0x210a,
+ 0x60d8, 0x12fa,
+ 0x60da, 0x080d,
+ 0x60dc, 0x0a6f,
+ 0x60de, 0x2109,
+ 0x60df, 0x0498,
+ 0x60e0, 0x12f3,
+ 0x60e1, 0x12f1,
+ 0x60e3, 0x0adc,
+ 0x60e7, 0x12e7,
+ 0x60e8, 0x0882,
+ 0x60f0, 0x0b26,
+ 0x60f1, 0x1306,
+ 0x60f2, 0x210c,
+ 0x60f3, 0x0add,
+ 0x60f4, 0x1301,
+ 0x60f6, 0x12fe,
+ 0x60f9, 0x0912,
+ 0x60fa, 0x1302,
+ 0x60fb, 0x1305,
+ 0x6100, 0x1300,
+ 0x6101, 0x092f,
+ 0x6103, 0x1303,
+ 0x6106, 0x12fd,
+ 0x6108, 0x0f08,
+ 0x6109, 0x0f07,
+ 0x610d, 0x1307,
+ 0x610f, 0x0499,
+ 0x6111, 0x210d,
+ 0x6115, 0x12fc,
+ 0x611a, 0x06ea,
+ 0x611b, 0x046a,
+ 0x611f, 0x05f2,
+ 0x6120, 0x210b,
+ 0x6121, 0x1304,
+ 0x6127, 0x130c,
+ 0x6128, 0x130b,
+ 0x612c, 0x1310,
+ 0x6130, 0x210f,
+ 0x6134, 0x1311,
+ 0x6137, 0x210e,
+ 0x613c, 0x130f,
+ 0x613d, 0x1312,
+ 0x613e, 0x130a,
+ 0x613f, 0x130e,
+ 0x6142, 0x1313,
+ 0x6144, 0x1314,
+ 0x6147, 0x1309,
+ 0x6148, 0x08ca,
+ 0x614a, 0x130d,
+ 0x614b, 0x0b36,
+ 0x614c, 0x07c4,
+ 0x614d, 0x12fb,
+ 0x614e, 0x09fb,
+ 0x6153, 0x1321,
+ 0x6155, 0x0e39,
+ 0x6158, 0x1317,
+ 0x615d, 0x1320,
+ 0x615f, 0x131f,
+ 0x6162, 0x0eab,
+ 0x6163, 0x05f3,
+ 0x6165, 0x131d,
+ 0x6167, 0x071b,
+ 0x6168, 0x0592,
+ 0x616b, 0x131a,
+ 0x616e, 0x0f80,
+ 0x616f, 0x131c,
+ 0x6170, 0x049a,
+ 0x6171, 0x131e,
+ 0x6173, 0x1315,
+ 0x6174, 0x131b,
+ 0x6175, 0x1322,
+ 0x6176, 0x071a,
+ 0x6177, 0x1316,
+ 0x617e, 0x0f47,
+ 0x6182, 0x0f15,
+ 0x6187, 0x1325,
+ 0x618a, 0x1329,
+ 0x618e, 0x0b00,
+ 0x6190, 0x0fc1,
+ 0x6191, 0x132a,
+ 0x6194, 0x1327,
+ 0x6196, 0x1324,
+ 0x6198, 0x2110,
+ 0x6199, 0x1323,
+ 0x619a, 0x1328,
+ 0x61a4, 0x0e00,
+ 0x61a7, 0x0c8c,
+ 0x61a9, 0x071c,
+ 0x61ab, 0x132b,
+ 0x61ac, 0x1326,
+ 0x61ae, 0x132c,
+ 0x61b2, 0x0751,
+ 0x61b6, 0x0531,
+ 0x61ba, 0x1334,
+ 0x61be, 0x05f4,
+ 0x61c3, 0x1332,
+ 0x61c6, 0x1333,
+ 0x61c7, 0x0819,
+ 0x61c8, 0x1331,
+ 0x61c9, 0x132f,
+ 0x61ca, 0x132e,
+ 0x61cb, 0x1335,
+ 0x61cc, 0x132d,
+ 0x61cd, 0x1337,
+ 0x61d0, 0x057b,
+ 0x61e3, 0x1339,
+ 0x61e6, 0x1338,
+ 0x61f2, 0x0bc4,
+ 0x61f4, 0x133c,
+ 0x61f6, 0x133a,
+ 0x61f7, 0x1330,
+ 0x61f8, 0x0752,
+ 0x61fa, 0x133b,
+ 0x61fc, 0x133f,
+ 0x61fd, 0x133e,
+ 0x61fe, 0x1340,
+ 0x61ff, 0x133d,
+ 0x6200, 0x1341,
+ 0x6208, 0x1342,
+ 0x620a, 0x0e3a,
+ 0x620c, 0x1345,
+ 0x620d, 0x1344,
+ 0x620e, 0x0949,
+ 0x6210, 0x0a52,
+ 0x6211, 0x0566,
+ 0x6212, 0x057c,
+ 0x6213, 0x2111,
+ 0x6214, 0x1346,
+ 0x6216, 0x0483,
+ 0x621a, 0x0a70,
+ 0x621b, 0x1347,
+ 0x621d, 0x1a64,
+ 0x621e, 0x1348,
+ 0x621f, 0x0737,
+ 0x6221, 0x1349,
+ 0x6226, 0x0a93,
+ 0x622a, 0x134a,
+ 0x622e, 0x134b,
+ 0x622f, 0x0654,
+ 0x6230, 0x134c,
+ 0x6232, 0x134d,
+ 0x6234, 0x0b37,
+ 0x6238, 0x0781,
+ 0x623b, 0x0eed,
+ 0x623f, 0x0e6a,
+ 0x6240, 0x0974,
+ 0x6241, 0x134f,
+ 0x6247, 0x0a94,
+ 0x6248, 0x1b1a,
+ 0x6249, 0x0d76,
+ 0x624b, 0x0916,
+ 0x624d, 0x083d,
+ 0x624e, 0x1350,
+ 0x6253, 0x0b27,
+ 0x6255, 0x0df7,
+ 0x6258, 0x0b51,
+ 0x625b, 0x1353,
+ 0x625e, 0x1351,
+ 0x6260, 0x1354,
+ 0x6263, 0x1352,
+ 0x6268, 0x1355,
+ 0x626e, 0x0e01,
+ 0x6271, 0x047b,
+ 0x6276, 0x0dd0,
+ 0x6279, 0x0d77,
+ 0x627c, 0x1356,
+ 0x627e, 0x1359,
+ 0x627f, 0x099d,
+ 0x6280, 0x0655,
+ 0x6282, 0x1357,
+ 0x6283, 0x135e,
+ 0x6284, 0x099e,
+ 0x6289, 0x1358,
+ 0x628a, 0x0cfa,
+ 0x6291, 0x0f48,
+ 0x6292, 0x135a,
+ 0x6294, 0x135f,
+ 0x6295, 0x0c64,
+ 0x6296, 0x135c,
+ 0x6297, 0x07c5,
+ 0x6298, 0x0a82,
+ 0x629b, 0x136d,
+ 0x629c, 0x0d48,
+ 0x629e, 0x0b52,
+ 0x62a6, 0x2112,
+ 0x62ab, 0x0d78,
+ 0x62ac, 0x13b2,
+ 0x62b1, 0x0e4a,
+ 0x62b5, 0x0c0d,
+ 0x62b9, 0x0ea3,
+ 0x62bb, 0x1362,
+ 0x62bc, 0x0521,
+ 0x62bd, 0x0ba8,
+ 0x62c2, 0x136b,
+ 0x62c5, 0x0b72,
+ 0x62c6, 0x1365,
+ 0x62c7, 0x136c,
+ 0x62c8, 0x1367,
+ 0x62c9, 0x136e,
+ 0x62ca, 0x136a,
+ 0x62cc, 0x1369,
+ 0x62cd, 0x0d25,
+ 0x62cf, 0x1363,
+ 0x62d0, 0x057d,
+ 0x62d1, 0x1361,
+ 0x62d2, 0x068b,
+ 0x62d3, 0x0b53,
+ 0x62d4, 0x135d,
+ 0x62d7, 0x1360,
+ 0x62d8, 0x07c6,
+ 0x62d9, 0x0a7f,
+ 0x62db, 0x099f,
+ 0x62dc, 0x1368,
+ 0x62dd, 0x0d08,
+ 0x62e0, 0x068c,
+ 0x62e1, 0x05a6,
+ 0x62ec, 0x05c5,
+ 0x62ed, 0x09e7,
+ 0x62ee, 0x1370,
+ 0x62ef, 0x1375,
+ 0x62f1, 0x1371,
+ 0x62f3, 0x0753,
+ 0x62f5, 0x1376,
+ 0x62f6, 0x0870,
+ 0x62f7, 0x07fb,
+ 0x62fe, 0x0930,
+ 0x62ff, 0x1364,
+ 0x6301, 0x08cb,
+ 0x6302, 0x1373,
+ 0x6307, 0x08a6,
+ 0x6308, 0x1374,
+ 0x6309, 0x0488,
+ 0x630c, 0x136f,
+ 0x6311, 0x0bc5,
+ 0x6319, 0x068d,
+ 0x631f, 0x06ac,
+ 0x6327, 0x1372,
+ 0x6328, 0x046b,
+ 0x632b, 0x0833,
+ 0x632f, 0x09fc,
+ 0x633a, 0x0c0e,
+ 0x633d, 0x0d68,
+ 0x633e, 0x1378,
+ 0x633f, 0x0ae0,
+ 0x6349, 0x0b0a,
+ 0x634c, 0x0879,
+ 0x634d, 0x1379,
+ 0x634f, 0x137b,
+ 0x6350, 0x1377,
+ 0x6355, 0x0e31,
+ 0x6357, 0x0bd9,
+ 0x635c, 0x0ade,
+ 0x6367, 0x0e4b,
+ 0x6368, 0x08fa,
+ 0x6369, 0x1387,
+ 0x636b, 0x1386,
+ 0x636e, 0x0a3e,
+ 0x6372, 0x0754,
+ 0x6376, 0x1380,
+ 0x6377, 0x09a1,
+ 0x637a, 0x0cc0,
+ 0x637b, 0x0ce7,
+ 0x6380, 0x137e,
+ 0x6383, 0x0adf,
+ 0x6388, 0x0924,
+ 0x6389, 0x1383,
+ 0x638c, 0x09a0,
+ 0x638e, 0x137d,
+ 0x638f, 0x1382,
+ 0x6392, 0x0d09,
+ 0x6396, 0x137c,
+ 0x6398, 0x06f7,
+ 0x639b, 0x05bb,
+ 0x639f, 0x1384,
+ 0x63a0, 0x0f73,
+ 0x63a1, 0x083e,
+ 0x63a2, 0x0b73,
+ 0x63a3, 0x1381,
+ 0x63a5, 0x0a80,
+ 0x63a7, 0x07c7,
+ 0x63a8, 0x0a2a,
+ 0x63a9, 0x0508,
+ 0x63aa, 0x0abe,
+ 0x63ab, 0x137f,
+ 0x63ac, 0x065f,
+ 0x63b2, 0x071d,
+ 0x63b4, 0x0beb,
+ 0x63b5, 0x1385,
+ 0x63bb, 0x0ae1,
+ 0x63be, 0x1388,
+ 0x63c0, 0x138a,
+ 0x63c3, 0x0b17,
+ 0x63c4, 0x1390,
+ 0x63c6, 0x138b,
+ 0x63c9, 0x138d,
+ 0x63cf, 0x0db3,
+ 0x63d0, 0x0c0f,
+ 0x63d2, 0x138e,
+ 0x63d6, 0x0f16,
+ 0x63da, 0x0f32,
+ 0x63db, 0x05f5,
+ 0x63e1, 0x0472,
+ 0x63e3, 0x138c,
+ 0x63e9, 0x1389,
+ 0x63ee, 0x0634,
+ 0x63f4, 0x0509,
+ 0x63f5, 0x2113,
+ 0x63f6, 0x138f,
+ 0x63fa, 0x0f33,
+ 0x6406, 0x1393,
+ 0x640d, 0x0b1b,
+ 0x640f, 0x139a,
+ 0x6413, 0x1394,
+ 0x6414, 0x1e2c,
+ 0x6416, 0x1391,
+ 0x6417, 0x1398,
+ 0x641c, 0x137a,
+ 0x6426, 0x1395,
+ 0x6428, 0x1399,
+ 0x642c, 0x0d56,
+ 0x642d, 0x0c65,
+ 0x6434, 0x1392,
+ 0x6436, 0x1396,
+ 0x643a, 0x071e,
+ 0x643e, 0x0861,
+ 0x6442, 0x0a81,
+ 0x644e, 0x139e,
+ 0x6451, 0x1e43,
+ 0x6458, 0x0c20,
+ 0x6460, 0x2114,
+ 0x6467, 0x139b,
+ 0x6469, 0x0e8e,
+ 0x646f, 0x139c,
+ 0x6476, 0x139d,
+ 0x6478, 0x0eda,
+ 0x647a, 0x0a46,
+ 0x6483, 0x0738,
+ 0x6488, 0x13a4,
+ 0x6492, 0x0883,
+ 0x6493, 0x13a1,
+ 0x6495, 0x13a0,
+ 0x649a, 0x0ce8,
+ 0x649d, 0x2115,
+ 0x649e, 0x0c8d,
+ 0x64a4, 0x0c2b,
+ 0x64a5, 0x13a2,
+ 0x64a9, 0x13a3,
+ 0x64ab, 0x0de1,
+ 0x64ad, 0x0cfb,
+ 0x64ae, 0x0871,
+ 0x64b0, 0x0a95,
+ 0x64b2, 0x0e7e,
+ 0x64b9, 0x05a7,
+ 0x64bb, 0x13aa,
+ 0x64bc, 0x13a5,
+ 0x64c1, 0x0f34,
+ 0x64c2, 0x13ac,
+ 0x64c5, 0x13a8,
+ 0x64c7, 0x13a9,
+ 0x64cd, 0x0ae2,
+ 0x64ce, 0x2116,
+ 0x64d2, 0x13a7,
+ 0x64d4, 0x1366,
+ 0x64d8, 0x13ab,
+ 0x64da, 0x13a6,
+ 0x64e0, 0x13b0,
+ 0x64e2, 0x0c21,
+ 0x64e3, 0x13b3,
+ 0x64e6, 0x0872,
+ 0x64e7, 0x13ae,
+ 0x64ec, 0x0656,
+ 0x64ef, 0x13b4,
+ 0x64f1, 0x13ad,
+ 0x64f2, 0x13b8,
+ 0x64f4, 0x13b7,
+ 0x64f6, 0x13b6,
+ 0x64fa, 0x13b9,
+ 0x64fd, 0x13bb,
+ 0x64fe, 0x09d9,
+ 0x6500, 0x13ba,
+ 0x6505, 0x13be,
+ 0x6518, 0x13bc,
+ 0x651c, 0x13bd,
+ 0x651d, 0x1397,
+ 0x6522, 0x1e97,
+ 0x6523, 0x13c0,
+ 0x6524, 0x13bf,
+ 0x652a, 0x139f,
+ 0x652b, 0x13c1,
+ 0x652c, 0x13b5,
+ 0x652f, 0x08a7,
+ 0x6534, 0x13c2,
+ 0x6536, 0x13c5,
+ 0x6537, 0x13c4,
+ 0x6538, 0x13c6,
+ 0x6539, 0x057e,
+ 0x653b, 0x07c8,
+ 0x653e, 0x0e4c,
+ 0x653f, 0x0a53,
+ 0x6545, 0x0782,
+ 0x6548, 0x13c8,
+ 0x654d, 0x13cb,
+ 0x654e, 0x2117,
+ 0x654f, 0x0dc4,
+ 0x6551, 0x0679,
+ 0x6555, 0x13ca,
+ 0x6556, 0x13c9,
+ 0x6557, 0x0d0a,
+ 0x6558, 0x13cc,
+ 0x6559, 0x06ad,
+ 0x655d, 0x13ce,
+ 0x655e, 0x13cd,
+ 0x6562, 0x05f6,
+ 0x6563, 0x0884,
+ 0x6566, 0x0cb0,
+ 0x656c, 0x071f,
+ 0x6570, 0x0a3a,
+ 0x6572, 0x13cf,
+ 0x6574, 0x0a54,
+ 0x6575, 0x0c22,
+ 0x6577, 0x0dd1,
+ 0x6578, 0x13d0,
+ 0x6582, 0x13d1,
+ 0x6587, 0x0e08,
+ 0x6588, 0x120c,
+ 0x6589, 0x0a6a,
+ 0x658c, 0x0dbe,
+ 0x658e, 0x0848,
+ 0x6590, 0x0d79,
+ 0x6591, 0x0d57,
+ 0x6597, 0x0c47,
+ 0x6599, 0x0f89,
+ 0x659b, 0x13d4,
+ 0x659c, 0x08fc,
+ 0x659f, 0x13d5,
+ 0x65a1, 0x047a,
+ 0x65a4, 0x06cc,
+ 0x65a5, 0x0a71,
+ 0x65a7, 0x0dd2,
+ 0x65ab, 0x13d6,
+ 0x65ac, 0x0890,
+ 0x65ad, 0x0b85,
+ 0x65af, 0x08a9,
+ 0x65b0, 0x09fd,
+ 0x65b7, 0x13d7,
+ 0x65b9, 0x0e4d,
+ 0x65bc, 0x0519,
+ 0x65bd, 0x08aa,
+ 0x65c1, 0x13da,
+ 0x65c3, 0x13d8,
+ 0x65c4, 0x13db,
+ 0x65c5, 0x0f81,
+ 0x65c6, 0x13d9,
+ 0x65cb, 0x0a9f,
+ 0x65cc, 0x13dc,
+ 0x65cf, 0x0b12,
+ 0x65d2, 0x13dd,
+ 0x65d7, 0x0636,
+ 0x65d9, 0x13df,
+ 0x65db, 0x13de,
+ 0x65e0, 0x13e0,
+ 0x65e2, 0x0637,
+ 0x65e5, 0x0cd4,
+ 0x65e6, 0x0b74,
+ 0x65e7, 0x0686,
+ 0x65e8, 0x08ab,
+ 0x65e9, 0x0ae3,
+ 0x65ec, 0x0966,
+ 0x65ed, 0x0474,
+ 0x65f1, 0x13e2,
+ 0x65fa, 0x0522,
+ 0x65fb, 0x13e6,
+ 0x6600, 0x2118,
+ 0x6602, 0x07c9,
+ 0x6603, 0x13e5,
+ 0x6606, 0x081b,
+ 0x6607, 0x09a2,
+ 0x6609, 0x211a,
+ 0x660a, 0x13e4,
+ 0x660c, 0x09a3,
+ 0x660e, 0x0ecc,
+ 0x660f, 0x081a,
+ 0x6613, 0x049b,
+ 0x6614, 0x0a72,
+ 0x6615, 0x2119,
+ 0x661c, 0x13eb,
+ 0x661e, 0x211c,
+ 0x661f, 0x0a55,
+ 0x6620, 0x04e9,
+ 0x6624, 0x211d,
+ 0x6625, 0x095f,
+ 0x6627, 0x0e94,
+ 0x6628, 0x0862,
+ 0x662d, 0x09a4,
+ 0x662e, 0x211b,
+ 0x662f, 0x0a4b,
+ 0x6631, 0x20ae,
+ 0x6634, 0x13ea,
+ 0x6635, 0x13e8,
+ 0x663b, 0x1e00,
+ 0x663c, 0x0ba9,
+ 0x663f, 0x1409,
+ 0x6641, 0x13ef,
+ 0x6642, 0x08cc,
+ 0x6643, 0x07ca,
+ 0x6644, 0x13ed,
+ 0x6649, 0x13ee,
+ 0x664b, 0x09fe,
+ 0x664f, 0x13ec,
+ 0x6652, 0x087d,
+ 0x6657, 0x211f,
+ 0x6659, 0x2120,
+ 0x665d, 0x13f1,
+ 0x665e, 0x13f0,
+ 0x665f, 0x13f5,
+ 0x6662, 0x13f6,
+ 0x6664, 0x13f2,
+ 0x6665, 0x211e,
+ 0x6666, 0x0580,
+ 0x6667, 0x13f3,
+ 0x6669, 0x0d69,
+ 0x666e, 0x0dd3,
+ 0x666f, 0x0720,
+ 0x6670, 0x13f7,
+ 0x6673, 0x2122,
+ 0x6674, 0x0a56,
+ 0x6676, 0x09a5,
+ 0x667a, 0x0b90,
+ 0x6681, 0x06bf,
+ 0x6683, 0x13f8,
+ 0x6684, 0x13fc,
+ 0x6687, 0x054b,
+ 0x6688, 0x13f9,
+ 0x6689, 0x13fb,
+ 0x668e, 0x13fa,
+ 0x6691, 0x0975,
+ 0x6696, 0x0b86,
+ 0x6697, 0x0489,
+ 0x6698, 0x13fd,
+ 0x6699, 0x2123,
+ 0x669d, 0x13fe,
+ 0x66a0, 0x2124,
+ 0x66a2, 0x0bc6,
+ 0x66a6, 0x0fb9,
+ 0x66ab, 0x0891,
+ 0x66ae, 0x0e3b,
+ 0x66b2, 0x2125,
+ 0x66b4, 0x0e6b,
+ 0x66b8, 0x1405,
+ 0x66b9, 0x1400,
+ 0x66bc, 0x1403,
+ 0x66be, 0x1402,
+ 0x66bf, 0x2126,
+ 0x66c1, 0x13ff,
+ 0x66c4, 0x1404,
+ 0x66c7, 0x0cb6,
+ 0x66c9, 0x1401,
+ 0x66d6, 0x1406,
+ 0x66d9, 0x0976,
+ 0x66da, 0x1407,
+ 0x66dc, 0x0f35,
+ 0x66dd, 0x0d2e,
+ 0x66e0, 0x1408,
+ 0x66e6, 0x140a,
+ 0x66e9, 0x140b,
+ 0x66f0, 0x140c,
+ 0x66f2, 0x06c2,
+ 0x66f3, 0x04ea,
+ 0x66f4, 0x07cb,
+ 0x66f5, 0x140d,
+ 0x66f7, 0x140e,
+ 0x66f8, 0x097b,
+ 0x66f9, 0x0ae4,
+ 0x66fa, 0x2127,
+ 0x66fb, 0x20b1,
+ 0x66fc, 0x10ed,
+ 0x66fd, 0x0ac0,
+ 0x66fe, 0x0abf,
+ 0x66ff, 0x0b38,
+ 0x6700, 0x0837,
+ 0x6703, 0x104b,
+ 0x6708, 0x0744,
+ 0x6709, 0x0f17,
+ 0x670b, 0x0e4e,
+ 0x670d, 0x0df0,
+ 0x670e, 0x2128,
+ 0x670f, 0x140f,
+ 0x6714, 0x0863,
+ 0x6715, 0x0bdb,
+ 0x6716, 0x1410,
+ 0x6717, 0x0fd5,
+ 0x671b, 0x0e6c,
+ 0x671d, 0x0bc7,
+ 0x671e, 0x1411,
+ 0x671f, 0x0638,
+ 0x6726, 0x1412,
+ 0x6728, 0x0ee6,
+ 0x672a, 0x0eb0,
+ 0x672b, 0x0ea4,
+ 0x672c, 0x0e8a,
+ 0x672d, 0x0873,
+ 0x672e, 0x1415,
+ 0x6731, 0x0917,
+ 0x6734, 0x0e7f,
+ 0x6736, 0x1417,
+ 0x6737, 0x141a,
+ 0x6738, 0x1419,
+ 0x673a, 0x0635,
+ 0x673d, 0x067a,
+ 0x673f, 0x1416,
+ 0x6741, 0x1418,
+ 0x6746, 0x141b,
+ 0x6749, 0x0a3f,
+ 0x674e, 0x0f65,
+ 0x674f, 0x048d,
+ 0x6750, 0x0850,
+ 0x6751, 0x0b1c,
+ 0x6753, 0x0909,
+ 0x6756, 0x09db,
+ 0x6759, 0x141e,
+ 0x675c, 0x0c48,
+ 0x675e, 0x141c,
+ 0x675f, 0x0b0b,
+ 0x6760, 0x141d,
+ 0x6761, 0x09da,
+ 0x6762, 0x0ee9,
+ 0x6763, 0x141f,
+ 0x6765, 0x0f52,
+ 0x6766, 0x212a,
+ 0x676a, 0x1425,
+ 0x676d, 0x07cc,
+ 0x676f, 0x0d0b,
+ 0x6770, 0x1422,
+ 0x6771, 0x0c66,
+ 0x6772, 0x13e3,
+ 0x6773, 0x13e7,
+ 0x6775, 0x0669,
+ 0x6777, 0x0cfd,
+ 0x677c, 0x1424,
+ 0x677e, 0x09a6,
+ 0x677f, 0x0d58,
+ 0x6785, 0x142a,
+ 0x6787, 0x0d8e,
+ 0x6789, 0x1421,
+ 0x678b, 0x1427,
+ 0x678c, 0x1426,
+ 0x6790, 0x0a73,
+ 0x6795, 0x0e9b,
+ 0x6797, 0x0f9b,
+ 0x679a, 0x0e95,
+ 0x679c, 0x054c,
+ 0x679d, 0x08ac,
+ 0x67a0, 0x0fee,
+ 0x67a1, 0x1429,
+ 0x67a2, 0x0a3b,
+ 0x67a6, 0x1428,
+ 0x67a9, 0x1423,
+ 0x67af, 0x0783,
+ 0x67b3, 0x142f,
+ 0x67b4, 0x142d,
+ 0x67b6, 0x054d,
+ 0x67b7, 0x142b,
+ 0x67b8, 0x1431,
+ 0x67b9, 0x1437,
+ 0x67bb, 0x212b,
+ 0x67c0, 0x212d,
+ 0x67c1, 0x0b28,
+ 0x67c4, 0x0e11,
+ 0x67c6, 0x1439,
+ 0x67ca, 0x0d94,
+ 0x67ce, 0x1438,
+ 0x67cf, 0x0d26,
+ 0x67d0, 0x0e6d,
+ 0x67d1, 0x05f7,
+ 0x67d3, 0x0a9b,
+ 0x67d4, 0x094a,
+ 0x67d8, 0x0bef,
+ 0x67da, 0x0f18,
+ 0x67dd, 0x1434,
+ 0x67de, 0x1433,
+ 0x67e2, 0x1435,
+ 0x67e4, 0x1432,
+ 0x67e7, 0x143a,
+ 0x67e9, 0x1430,
+ 0x67ec, 0x142e,
+ 0x67ee, 0x1436,
+ 0x67ef, 0x142c,
+ 0x67f1, 0x0baa,
+ 0x67f3, 0x0f04,
+ 0x67f4, 0x08f2,
+ 0x67f5, 0x0864,
+ 0x67fb, 0x082a,
+ 0x67fe, 0x0e9d,
+ 0x67ff, 0x059f,
+ 0x6801, 0x212e,
+ 0x6802, 0x0bea,
+ 0x6803, 0x0ca2,
+ 0x6804, 0x04eb,
+ 0x6805, 0x1e07,
+ 0x6813, 0x0a96,
+ 0x6816, 0x0a58,
+ 0x6817, 0x0700,
+ 0x681e, 0x143c,
+ 0x6821, 0x07cd,
+ 0x6822, 0x05da,
+ 0x6829, 0x143e,
+ 0x682a, 0x05d2,
+ 0x682b, 0x1444,
+ 0x6832, 0x1441,
+ 0x6834, 0x0a97,
+ 0x6838, 0x05a9,
+ 0x6839, 0x081c,
+ 0x683c, 0x05a8,
+ 0x683d, 0x083f,
+ 0x6840, 0x143f,
+ 0x6841, 0x073b,
+ 0x6842, 0x0721,
+ 0x6843, 0x0c67,
+ 0x6844, 0x212f,
+ 0x6846, 0x143d,
+ 0x6848, 0x048a,
+ 0x684d, 0x1440,
+ 0x684e, 0x1442,
+ 0x6850, 0x06c5,
+ 0x6851, 0x0702,
+ 0x6852, 0x212c,
+ 0x6853, 0x05f8,
+ 0x6854, 0x0665,
+ 0x6859, 0x1445,
+ 0x685c, 0x0869,
+ 0x685d, 0x0e9f,
+ 0x685f, 0x0885,
+ 0x6863, 0x1446,
+ 0x6867, 0x0da2,
+ 0x6874, 0x1452,
+ 0x6876, 0x0533,
+ 0x6877, 0x1447,
+ 0x687e, 0x1458,
+ 0x687f, 0x1448,
+ 0x6881, 0x0f8a,
+ 0x6883, 0x144f,
+ 0x6885, 0x0d15,
+ 0x688d, 0x1457,
+ 0x688e, 0x1e9c,
+ 0x688f, 0x144a,
+ 0x6893, 0x0478,
+ 0x6894, 0x144c,
+ 0x6897, 0x07ce,
+ 0x689b, 0x144e,
+ 0x689d, 0x144d,
+ 0x689f, 0x1449,
+ 0x68a0, 0x1454,
+ 0x68a2, 0x09a7,
+ 0x68a6, 0x11be,
+ 0x68a7, 0x079c,
+ 0x68a8, 0x0f66,
+ 0x68ad, 0x144b,
+ 0x68af, 0x0c10,
+ 0x68b0, 0x0581,
+ 0x68b1, 0x081d,
+ 0x68b3, 0x1443,
+ 0x68b5, 0x1453,
+ 0x68b6, 0x05bf,
+ 0x68b9, 0x1451,
+ 0x68ba, 0x1455,
+ 0x68bc, 0x0c68,
+ 0x68c4, 0x063a,
+ 0x68c6, 0x1473,
+ 0x68c8, 0x20af,
+ 0x68c9, 0x0ed5,
+ 0x68ca, 0x145a,
+ 0x68cb, 0x0639,
+ 0x68cd, 0x1461,
+ 0x68cf, 0x2130,
+ 0x68d2, 0x0e6e,
+ 0x68d4, 0x1462,
+ 0x68d5, 0x1464,
+ 0x68d7, 0x1468,
+ 0x68d8, 0x145c,
+ 0x68da, 0x0b68,
+ 0x68df, 0x0c69,
+ 0x68e0, 0x146c,
+ 0x68e1, 0x145f,
+ 0x68e3, 0x1469,
+ 0x68e7, 0x1463,
+ 0x68ee, 0x09ff,
+ 0x68ef, 0x146d,
+ 0x68f2, 0x0a57,
+ 0x68f9, 0x146b,
+ 0x68fa, 0x05f9,
+ 0x6900, 0x0ff6,
+ 0x6901, 0x1459,
+ 0x6904, 0x1467,
+ 0x6905, 0x049c,
+ 0x6908, 0x145b,
+ 0x690b, 0x0ec6,
+ 0x690c, 0x1460,
+ 0x690d, 0x09e8,
+ 0x690e, 0x0be3,
+ 0x690f, 0x1456,
+ 0x6912, 0x1466,
+ 0x6919, 0x0a40,
+ 0x691a, 0x1470,
+ 0x691b, 0x05cf,
+ 0x691c, 0x0755,
+ 0x6921, 0x1472,
+ 0x6922, 0x145d,
+ 0x6923, 0x1471,
+ 0x6925, 0x146a,
+ 0x6926, 0x145e,
+ 0x6928, 0x146e,
+ 0x692a, 0x146f,
+ 0x6930, 0x1480,
+ 0x6934, 0x0ca6,
+ 0x6936, 0x1465,
+ 0x6939, 0x147c,
+ 0x693d, 0x147e,
+ 0x693f, 0x0bf4,
+ 0x694a, 0x0f36,
+ 0x6953, 0x0de8,
+ 0x6954, 0x1479,
+ 0x6955, 0x0b2a,
+ 0x6959, 0x147f,
+ 0x695a, 0x0ac1,
+ 0x695c, 0x1476,
+ 0x695d, 0x1483,
+ 0x695e, 0x1482,
+ 0x6960, 0x0cc7,
+ 0x6961, 0x1481,
+ 0x6962, 0x0cc2,
+ 0x6968, 0x2132,
+ 0x696a, 0x1485,
+ 0x696b, 0x1478,
+ 0x696d, 0x06c0,
+ 0x696e, 0x147b,
+ 0x696f, 0x0967,
+ 0x6973, 0x0d16,
+ 0x6974, 0x147d,
+ 0x6975, 0x06c3,
+ 0x6977, 0x1475,
+ 0x6978, 0x1477,
+ 0x6979, 0x1474,
+ 0x697c, 0x0fd6,
+ 0x697d, 0x05b8,
+ 0x697e, 0x147a,
+ 0x6981, 0x1484,
+ 0x6982, 0x0593,
+ 0x698a, 0x0857,
+ 0x698e, 0x04ff,
+ 0x6991, 0x1495,
+ 0x6994, 0x0fd7,
+ 0x6995, 0x1498,
+ 0x6998, 0x2134,
+ 0x699b, 0x0a00,
+ 0x699c, 0x1497,
+ 0x69a0, 0x1496,
+ 0x69a7, 0x1493,
+ 0x69ae, 0x1487,
+ 0x69b1, 0x14a4,
+ 0x69b2, 0x1486,
+ 0x69b4, 0x1499,
+ 0x69bb, 0x1491,
+ 0x69be, 0x148c,
+ 0x69bf, 0x1489,
+ 0x69c1, 0x148a,
+ 0x69c3, 0x1492,
+ 0x69c7, 0x1d33,
+ 0x69ca, 0x148f,
+ 0x69cb, 0x07cf,
+ 0x69cc, 0x0be4,
+ 0x69cd, 0x0ae6,
+ 0x69ce, 0x148d,
+ 0x69d0, 0x1488,
+ 0x69d3, 0x148b,
+ 0x69d8, 0x0f37,
+ 0x69d9, 0x0e98,
+ 0x69dd, 0x1490,
+ 0x69de, 0x149a,
+ 0x69e2, 0x2135,
+ 0x69e7, 0x14a2,
+ 0x69e8, 0x149b,
+ 0x69eb, 0x14a8,
+ 0x69ed, 0x14a6,
+ 0x69f2, 0x14a1,
+ 0x69f9, 0x14a0,
+ 0x69fb, 0x0bec,
+ 0x69fd, 0x0ae7,
+ 0x69ff, 0x149e,
+ 0x6a02, 0x149c,
+ 0x6a05, 0x14a3,
+ 0x6a0a, 0x14a9,
+ 0x6a0b, 0x0d89,
+ 0x6a0c, 0x14af,
+ 0x6a12, 0x14aa,
+ 0x6a13, 0x14ad,
+ 0x6a14, 0x14a7,
+ 0x6a17, 0x0bb2,
+ 0x6a19, 0x0daa,
+ 0x6a1b, 0x149d,
+ 0x6a1e, 0x14a5,
+ 0x6a1f, 0x09a8,
+ 0x6a21, 0x0edb,
+ 0x6a22, 0x14b9,
+ 0x6a23, 0x14ac,
+ 0x6a29, 0x0756,
+ 0x6a2a, 0x0523,
+ 0x6a2b, 0x05bd,
+ 0x6a2e, 0x1494,
+ 0x6a30, 0x2136,
+ 0x6a35, 0x09a9,
+ 0x6a36, 0x14b1,
+ 0x6a38, 0x14b8,
+ 0x6a39, 0x0925,
+ 0x6a3a, 0x05d0,
+ 0x6a3d, 0x0b6c,
+ 0x6a44, 0x14ae,
+ 0x6a46, 0x2138,
+ 0x6a47, 0x14b3,
+ 0x6a48, 0x14b7,
+ 0x6a4b, 0x06ae,
+ 0x6a58, 0x0666,
+ 0x6a59, 0x14b5,
+ 0x6a5f, 0x063b,
+ 0x6a61, 0x0ca3,
+ 0x6a62, 0x14b4,
+ 0x6a66, 0x14b6,
+ 0x6a6b, 0x2137,
+ 0x6a72, 0x14b0,
+ 0x6a73, 0x2139,
+ 0x6a78, 0x14b2,
+ 0x6a7e, 0x213a,
+ 0x6a7f, 0x05be,
+ 0x6a80, 0x0b87,
+ 0x6a84, 0x14bd,
+ 0x6a8d, 0x14bb,
+ 0x6a8e, 0x079d,
+ 0x6a90, 0x14ba,
+ 0x6a97, 0x14c0,
+ 0x6a9c, 0x143b,
+ 0x6aa0, 0x14bc,
+ 0x6aa2, 0x14be,
+ 0x6aaa, 0x14cb,
+ 0x6aac, 0x14c7,
+ 0x6aae, 0x1450,
+ 0x6ab3, 0x14c6,
+ 0x6ab8, 0x14c5,
+ 0x6abb, 0x14c2,
+ 0x6ac1, 0x14ab,
+ 0x6ac2, 0x14c4,
+ 0x6ac3, 0x14c3,
+ 0x6ad1, 0x14c9,
+ 0x6ad3, 0x0fcc,
+ 0x6ada, 0x14cc,
+ 0x6adb, 0x06f3,
+ 0x6ade, 0x14c8,
+ 0x6adf, 0x14ca,
+ 0x6ae2, 0x213b,
+ 0x6ae4, 0x213c,
+ 0x6ae8, 0x0d3b,
+ 0x6aea, 0x14cd,
+ 0x6afa, 0x14d1,
+ 0x6afb, 0x14ce,
+ 0x6b04, 0x0f5d,
+ 0x6b05, 0x14cf,
+ 0x6b0a, 0x149f,
+ 0x6b12, 0x14d2,
+ 0x6b16, 0x14d3,
+ 0x6b1d, 0x04d7,
+ 0x6b1f, 0x14d5,
+ 0x6b20, 0x073d,
+ 0x6b21, 0x08cd,
+ 0x6b23, 0x06cd,
+ 0x6b27, 0x0524,
+ 0x6b32, 0x0f49,
+ 0x6b37, 0x14d7,
+ 0x6b38, 0x14d6,
+ 0x6b39, 0x14d9,
+ 0x6b3a, 0x0657,
+ 0x6b3d, 0x06ce,
+ 0x6b3e, 0x05fa,
+ 0x6b43, 0x14dc,
+ 0x6b47, 0x14db,
+ 0x6b49, 0x14dd,
+ 0x6b4c, 0x054e,
+ 0x6b4e, 0x0b75,
+ 0x6b50, 0x14de,
+ 0x6b53, 0x05fb,
+ 0x6b54, 0x14e0,
+ 0x6b59, 0x14df,
+ 0x6b5b, 0x14e1,
+ 0x6b5f, 0x14e2,
+ 0x6b61, 0x14e3,
+ 0x6b62, 0x08ad,
+ 0x6b63, 0x0a59,
+ 0x6b64, 0x0811,
+ 0x6b66, 0x0de2,
+ 0x6b69, 0x0e32,
+ 0x6b6a, 0x0fea,
+ 0x6b6f, 0x08c3,
+ 0x6b73, 0x0840,
+ 0x6b74, 0x0fba,
+ 0x6b78, 0x14e4,
+ 0x6b7b, 0x08ae,
+ 0x6b7f, 0x14e6,
+ 0x6b83, 0x14e9,
+ 0x6b84, 0x14e8,
+ 0x6b86, 0x0e86,
+ 0x6b89, 0x0968,
+ 0x6b8a, 0x0918,
+ 0x6b8b, 0x0892,
+ 0x6b8d, 0x14ea,
+ 0x6b95, 0x14ec,
+ 0x6b96, 0x09e9,
+ 0x6b98, 0x14eb,
+ 0x6b9e, 0x14ed,
+ 0x6ba4, 0x14ee,
+ 0x6baa, 0x14ef,
+ 0x6baf, 0x14f1,
+ 0x6bb1, 0x14f3,
+ 0x6bb2, 0x14f2,
+ 0x6bb3, 0x14f4,
+ 0x6bb4, 0x0525,
+ 0x6bb5, 0x0b88,
+ 0x6bb7, 0x14f5,
+ 0x6bba, 0x0874,
+ 0x6bbb, 0x05aa,
+ 0x6bbc, 0x14f6,
+ 0x6bbf, 0x0c3c,
+ 0x6bc0, 0x119d,
+ 0x6bc5, 0x063d,
+ 0x6bc6, 0x14f7,
+ 0x6bcb, 0x14f8,
+ 0x6bcd, 0x0e3c,
+ 0x6bce, 0x0e96,
+ 0x6bd2, 0x0c9f,
+ 0x6bd3, 0x14f9,
+ 0x6bd4, 0x0d7a,
+ 0x6bd6, 0x213d,
+ 0x6bd8, 0x0d8f,
+ 0x6bdb, 0x0edf,
+ 0x6bdf, 0x14fa,
+ 0x6beb, 0x14fc,
+ 0x6bec, 0x14fb,
+ 0x6bef, 0x14fe,
+ 0x6bf3, 0x14fd,
+ 0x6c08, 0x1500,
+ 0x6c0f, 0x08af,
+ 0x6c11, 0x0ebd,
+ 0x6c13, 0x1501,
+ 0x6c17, 0x063e,
+ 0x6c1b, 0x1503,
+ 0x6c23, 0x1505,
+ 0x6c24, 0x1504,
+ 0x6c34, 0x0a2b,
+ 0x6c37, 0x0dab,
+ 0x6c38, 0x04ec,
+ 0x6c3e, 0x0d59,
+ 0x6c3f, 0x213e,
+ 0x6c40, 0x0c11,
+ 0x6c41, 0x094b,
+ 0x6c42, 0x067b,
+ 0x6c4e, 0x0d5a,
+ 0x6c50, 0x08da,
+ 0x6c55, 0x1507,
+ 0x6c57, 0x05fc,
+ 0x6c5a, 0x051a,
+ 0x6c5c, 0x213f,
+ 0x6c5d, 0x0cca,
+ 0x6c5e, 0x1506,
+ 0x6c5f, 0x07d0,
+ 0x6c60, 0x0b91,
+ 0x6c62, 0x1508,
+ 0x6c68, 0x1510,
+ 0x6c6a, 0x1509,
+ 0x6c6f, 0x2141,
+ 0x6c70, 0x0b21,
+ 0x6c72, 0x067c,
+ 0x6c73, 0x1511,
+ 0x6c7a, 0x073e,
+ 0x6c7d, 0x063f,
+ 0x6c7e, 0x150f,
+ 0x6c81, 0x150d,
+ 0x6c82, 0x150a,
+ 0x6c83, 0x0f4a,
+ 0x6c86, 0x2140,
+ 0x6c88, 0x0bdc,
+ 0x6c8c, 0x0cb1,
+ 0x6c8d, 0x150b,
+ 0x6c90, 0x1513,
+ 0x6c92, 0x1512,
+ 0x6c93, 0x06f9,
+ 0x6c96, 0x052d,
+ 0x6c99, 0x082b,
+ 0x6c9a, 0x150c,
+ 0x6c9b, 0x150e,
+ 0x6ca1, 0x0e85,
+ 0x6ca2, 0x0b54,
+ 0x6cab, 0x0ea5,
+ 0x6cae, 0x151b,
+ 0x6cb1, 0x151c,
+ 0x6cb3, 0x054f,
+ 0x6cb8, 0x0df8,
+ 0x6cb9, 0x0f09,
+ 0x6cba, 0x151e,
+ 0x6cbb, 0x08cf,
+ 0x6cbc, 0x09aa,
+ 0x6cbd, 0x1517,
+ 0x6cbe, 0x151d,
+ 0x6cbf, 0x050a,
+ 0x6cc1, 0x06af,
+ 0x6cc4, 0x1514,
+ 0x6cc5, 0x1519,
+ 0x6cc9, 0x0a98,
+ 0x6cca, 0x0d27,
+ 0x6ccc, 0x0d7b,
+ 0x6cd3, 0x1516,
+ 0x6cd5, 0x0e4f,
+ 0x6cd7, 0x1518,
+ 0x6cd9, 0x1521,
+ 0x6cda, 0x2142,
+ 0x6cdb, 0x151f,
+ 0x6cdd, 0x151a,
+ 0x6ce1, 0x0e50,
+ 0x6ce2, 0x0cfe,
+ 0x6ce3, 0x067d,
+ 0x6ce5, 0x0c1f,
+ 0x6ce8, 0x0bab,
+ 0x6cea, 0x1522,
+ 0x6cef, 0x1520,
+ 0x6cf0, 0x0b39,
+ 0x6cf1, 0x1515,
+ 0x6cf3, 0x04ed,
+ 0x6d04, 0x2143,
+ 0x6d0b, 0x0f38,
+ 0x6d0c, 0x152d,
+ 0x6d12, 0x152c,
+ 0x6d17, 0x0a9a,
+ 0x6d19, 0x1529,
+ 0x6d1b, 0x0f56,
+ 0x6d1e, 0x0c8e,
+ 0x6d1f, 0x1523,
+ 0x6d25, 0x0be1,
+ 0x6d29, 0x04ee,
+ 0x6d2a, 0x07d1,
+ 0x6d2b, 0x1526,
+ 0x6d32, 0x0931,
+ 0x6d33, 0x152b,
+ 0x6d35, 0x152a,
+ 0x6d36, 0x1525,
+ 0x6d38, 0x1528,
+ 0x6d3b, 0x05c6,
+ 0x6d3d, 0x1527,
+ 0x6d3e, 0x0cff,
+ 0x6d41, 0x0f76,
+ 0x6d44, 0x09dc,
+ 0x6d45, 0x0a99,
+ 0x6d59, 0x1533,
+ 0x6d5a, 0x1531,
+ 0x6d5c, 0x0dbf,
+ 0x6d63, 0x152e,
+ 0x6d64, 0x1530,
+ 0x6d66, 0x04dc,
+ 0x6d69, 0x07d2,
+ 0x6d6a, 0x0fd8,
+ 0x6d6c, 0x059b,
+ 0x6d6e, 0x0dd4,
+ 0x6d6f, 0x2145,
+ 0x6d74, 0x0f4b,
+ 0x6d77, 0x0582,
+ 0x6d78, 0x0a01,
+ 0x6d79, 0x1532,
+ 0x6d85, 0x1537,
+ 0x6d87, 0x2144,
+ 0x6d88, 0x09ab,
+ 0x6d8c, 0x0f1a,
+ 0x6d8e, 0x1534,
+ 0x6d93, 0x152f,
+ 0x6d95, 0x1535,
+ 0x6d96, 0x2146,
+ 0x6d99, 0x0fa6,
+ 0x6d9b, 0x0c6d,
+ 0x6d9c, 0x0c9a,
+ 0x6dac, 0x2147,
+ 0x6daf, 0x0594,
+ 0x6db2, 0x04f7,
+ 0x6db5, 0x153b,
+ 0x6db8, 0x153e,
+ 0x6dbc, 0x0f8b,
+ 0x6dc0, 0x0f4e,
+ 0x6dc5, 0x1545,
+ 0x6dc6, 0x153f,
+ 0x6dc7, 0x153c,
+ 0x6dcb, 0x0f9c,
+ 0x6dcc, 0x1542,
+ 0x6dcf, 0x2148,
+ 0x6dd1, 0x0954,
+ 0x6dd2, 0x1544,
+ 0x6dd5, 0x1549,
+ 0x6dd8, 0x0c6b,
+ 0x6dd9, 0x1547,
+ 0x6dde, 0x1541,
+ 0x6de1, 0x0b76,
+ 0x6de4, 0x1548,
+ 0x6de6, 0x153d,
+ 0x6de8, 0x1543,
+ 0x6dea, 0x154a,
+ 0x6deb, 0x04c0,
+ 0x6dec, 0x1540,
+ 0x6dee, 0x154b,
+ 0x6df1, 0x0a02,
+ 0x6df2, 0x214a,
+ 0x6df3, 0x0969,
+ 0x6df5, 0x0df5,
+ 0x6df7, 0x081e,
+ 0x6df8, 0x2149,
+ 0x6df9, 0x1538,
+ 0x6dfa, 0x1546,
+ 0x6dfb, 0x0c34,
+ 0x6dfc, 0x214b,
+ 0x6e05, 0x0a5a,
+ 0x6e07, 0x05c7,
+ 0x6e08, 0x0841,
+ 0x6e09, 0x09ac,
+ 0x6e0a, 0x153a,
+ 0x6e0b, 0x094c,
+ 0x6e13, 0x0722,
+ 0x6e15, 0x1539,
+ 0x6e19, 0x154f,
+ 0x6e1a, 0x0977,
+ 0x6e1b, 0x076e,
+ 0x6e1d, 0x155e,
+ 0x6e1f, 0x1558,
+ 0x6e20, 0x068e,
+ 0x6e21, 0x0c49,
+ 0x6e23, 0x1553,
+ 0x6e24, 0x155c,
+ 0x6e25, 0x0473,
+ 0x6e26, 0x04d4,
+ 0x6e27, 0x214e,
+ 0x6e29, 0x0539,
+ 0x6e2b, 0x1555,
+ 0x6e2c, 0x0b0c,
+ 0x6e2d, 0x154c,
+ 0x6e2e, 0x154e,
+ 0x6e2f, 0x07d3,
+ 0x6e38, 0x155f,
+ 0x6e39, 0x214c,
+ 0x6e3a, 0x155a,
+ 0x6e3c, 0x214f,
+ 0x6e3e, 0x1552,
+ 0x6e43, 0x1559,
+ 0x6e4a, 0x0eb7,
+ 0x6e4d, 0x1557,
+ 0x6e4e, 0x155b,
+ 0x6e56, 0x0784,
+ 0x6e58, 0x09ad,
+ 0x6e5b, 0x0b77,
+ 0x6e5c, 0x214d,
+ 0x6e5f, 0x1551,
+ 0x6e67, 0x0f19,
+ 0x6e6b, 0x1554,
+ 0x6e6e, 0x154d,
+ 0x6e6f, 0x0c6c,
+ 0x6e72, 0x1550,
+ 0x6e76, 0x1556,
+ 0x6e7e, 0x0ff7,
+ 0x6e7f, 0x08ea,
+ 0x6e80, 0x0eac,
+ 0x6e82, 0x1560,
+ 0x6e8c, 0x0d42,
+ 0x6e8f, 0x156c,
+ 0x6e90, 0x076f,
+ 0x6e96, 0x096a,
+ 0x6e98, 0x1562,
+ 0x6e9c, 0x0f77,
+ 0x6e9d, 0x07d4,
+ 0x6e9f, 0x156f,
+ 0x6ea2, 0x04b2,
+ 0x6ea5, 0x156d,
+ 0x6eaa, 0x1561,
+ 0x6eaf, 0x1567,
+ 0x6eb2, 0x1569,
+ 0x6eb6, 0x0f39,
+ 0x6eb7, 0x1564,
+ 0x6eba, 0x0c28,
+ 0x6ebd, 0x1566,
+ 0x6ebf, 0x2150,
+ 0x6ec2, 0x156e,
+ 0x6ec4, 0x1568,
+ 0x6ec5, 0x0ed3,
+ 0x6ec9, 0x1563,
+ 0x6ecb, 0x08ce,
+ 0x6ecc, 0x157b,
+ 0x6ed1, 0x05c8,
+ 0x6ed3, 0x1565,
+ 0x6ed4, 0x156a,
+ 0x6edd, 0x0b4c,
+ 0x6ede, 0x0b3a,
+ 0x6eec, 0x1573,
+ 0x6eef, 0x1579,
+ 0x6ef2, 0x1577,
+ 0x6ef4, 0x0c23,
+ 0x6ef7, 0x157e,
+ 0x6ef8, 0x1574,
+ 0x6efe, 0x1575,
+ 0x6eff, 0x155d,
+ 0x6f01, 0x0693,
+ 0x6f02, 0x0dac,
+ 0x6f06, 0x08eb,
+ 0x6f09, 0x0809,
+ 0x6f0f, 0x0fd9,
+ 0x6f11, 0x1571,
+ 0x6f13, 0x157d,
+ 0x6f14, 0x050b,
+ 0x6f15, 0x0ae8,
+ 0x6f20, 0x0d2f,
+ 0x6f22, 0x05fd,
+ 0x6f23, 0x0fc2,
+ 0x6f2b, 0x0ead,
+ 0x6f2c, 0x0bee,
+ 0x6f31, 0x1578,
+ 0x6f32, 0x157a,
+ 0x6f38, 0x0ab4,
+ 0x6f3e, 0x157c,
+ 0x6f3f, 0x1576,
+ 0x6f41, 0x1570,
+ 0x6f45, 0x05ff,
+ 0x6f51, 0x1e60,
+ 0x6f54, 0x073f,
+ 0x6f58, 0x158a,
+ 0x6f5b, 0x1585,
+ 0x6f5c, 0x0a9c,
+ 0x6f5f, 0x05c1,
+ 0x6f64, 0x096b,
+ 0x6f66, 0x158e,
+ 0x6f6d, 0x1587,
+ 0x6f6e, 0x0bc8,
+ 0x6f6f, 0x1584,
+ 0x6f70, 0x0bf5,
+ 0x6f74, 0x15a7,
+ 0x6f78, 0x1581,
+ 0x6f7a, 0x1580,
+ 0x6f7c, 0x1589,
+ 0x6f80, 0x1583,
+ 0x6f81, 0x1582,
+ 0x6f82, 0x1588,
+ 0x6f84, 0x0a45,
+ 0x6f86, 0x157f,
+ 0x6f88, 0x2151,
+ 0x6f8e, 0x158b,
+ 0x6f91, 0x158c,
+ 0x6f97, 0x05fe,
+ 0x6fa1, 0x1591,
+ 0x6fa3, 0x1590,
+ 0x6fa4, 0x1592,
+ 0x6faa, 0x1595,
+ 0x6fb1, 0x0c3d,
+ 0x6fb3, 0x158f,
+ 0x6fb5, 0x2152,
+ 0x6fb9, 0x1593,
+ 0x6fc0, 0x0739,
+ 0x6fc1, 0x0b59,
+ 0x6fc2, 0x158d,
+ 0x6fc3, 0x0cf1,
+ 0x6fc6, 0x1594,
+ 0x6fd4, 0x1599,
+ 0x6fd5, 0x1597,
+ 0x6fd8, 0x159a,
+ 0x6fdb, 0x159d,
+ 0x6fdf, 0x1596,
+ 0x6fe0, 0x07fc,
+ 0x6fe1, 0x0cde,
+ 0x6fe4, 0x1536,
+ 0x6feb, 0x0f5e,
+ 0x6fec, 0x1598,
+ 0x6fee, 0x159c,
+ 0x6fef, 0x0b55,
+ 0x6ff1, 0x159b,
+ 0x6ff3, 0x1586,
+ 0x6ff5, 0x2153,
+ 0x6ff6, 0x1ba4,
+ 0x6ffa, 0x15a0,
+ 0x6ffe, 0x15a4,
+ 0x7001, 0x15a2,
+ 0x7005, 0x2154,
+ 0x7006, 0x1e50,
+ 0x7007, 0x2155,
+ 0x7009, 0x159e,
+ 0x700b, 0x159f,
+ 0x700f, 0x15a3,
+ 0x7011, 0x15a1,
+ 0x7015, 0x0dc0,
+ 0x7018, 0x15a9,
+ 0x701a, 0x15a6,
+ 0x701b, 0x15a5,
+ 0x701d, 0x15a8,
+ 0x701e, 0x0cac,
+ 0x701f, 0x15aa,
+ 0x7026, 0x0bb3,
+ 0x7027, 0x0b4d,
+ 0x7028, 0x2156,
+ 0x702c, 0x0a49,
+ 0x7030, 0x15ab,
+ 0x7032, 0x15ad,
+ 0x703e, 0x15ac,
+ 0x704c, 0x1572,
+ 0x7051, 0x15ae,
+ 0x7058, 0x0cbf,
+ 0x7063, 0x15af,
+ 0x706b, 0x0550,
+ 0x706f, 0x0c6e,
+ 0x7070, 0x0583,
+ 0x7078, 0x067e,
+ 0x707c, 0x090a,
+ 0x707d, 0x0842,
+ 0x7085, 0x2157,
+ 0x7089, 0x0fcd,
+ 0x708a, 0x0a2c,
+ 0x708e, 0x050c,
+ 0x7092, 0x15b1,
+ 0x7099, 0x15b0,
+ 0x70ab, 0x2158,
+ 0x70ac, 0x15b4,
+ 0x70ad, 0x0b78,
+ 0x70ae, 0x15b7,
+ 0x70af, 0x15b2,
+ 0x70b3, 0x15b6,
+ 0x70b8, 0x15b5,
+ 0x70b9, 0x0c3a,
+ 0x70ba, 0x049d,
+ 0x70bb, 0x20ad,
+ 0x70c8, 0x0fbd,
+ 0x70cb, 0x15b9,
+ 0x70cf, 0x04ca,
+ 0x70d9, 0x15bb,
+ 0x70dd, 0x15ba,
+ 0x70df, 0x15b8,
+ 0x70f1, 0x15b3,
+ 0x70f9, 0x0e51,
+ 0x70fd, 0x15bd,
+ 0x7104, 0x215a,
+ 0x7109, 0x15bc,
+ 0x710f, 0x2159,
+ 0x7114, 0x050d,
+ 0x7119, 0x15bf,
+ 0x711a, 0x0e02,
+ 0x711c, 0x15be,
+ 0x7121, 0x0ec1,
+ 0x7126, 0x09af,
+ 0x7130, 0x1ddc,
+ 0x7136, 0x0ab5,
+ 0x713c, 0x09ae,
+ 0x7146, 0x215c,
+ 0x7149, 0x0fc3,
+ 0x714c, 0x15c5,
+ 0x714e, 0x0a9d,
+ 0x7155, 0x15c1,
+ 0x7156, 0x15c6,
+ 0x7159, 0x050e,
+ 0x715c, 0x215b,
+ 0x7162, 0x15c4,
+ 0x7164, 0x0d17,
+ 0x7165, 0x15c0,
+ 0x7166, 0x15c3,
+ 0x7167, 0x09b0,
+ 0x7169, 0x0d65,
+ 0x716c, 0x15c7,
+ 0x716e, 0x08fd,
+ 0x717d, 0x0a9e,
+ 0x7184, 0x15ca,
+ 0x7188, 0x15c2,
+ 0x718a, 0x06fd,
+ 0x718f, 0x15c8,
+ 0x7194, 0x0f3a,
+ 0x7195, 0x15cb,
+ 0x7199, 0x205d,
+ 0x719f, 0x0959,
+ 0x71a8, 0x15cc,
+ 0x71ac, 0x15cd,
+ 0x71b1, 0x0ce4,
+ 0x71b9, 0x15cf,
+ 0x71be, 0x15d0,
+ 0x71c1, 0x215f,
+ 0x71c3, 0x0ce9,
+ 0x71c8, 0x0c6f,
+ 0x71c9, 0x15d2,
+ 0x71ce, 0x15d4,
+ 0x71d0, 0x0f9d,
+ 0x71d2, 0x15d1,
+ 0x71d4, 0x15d3,
+ 0x71d5, 0x050f,
+ 0x71d7, 0x15ce,
+ 0x71df, 0x114e,
+ 0x71e0, 0x15d5,
+ 0x71e5, 0x0ae9,
+ 0x71e6, 0x0886,
+ 0x71e7, 0x15d7,
+ 0x71ec, 0x15d6,
+ 0x71ed, 0x09ea,
+ 0x71ee, 0x10ee,
+ 0x71f5, 0x15d8,
+ 0x71f9, 0x15da,
+ 0x71fb, 0x15c9,
+ 0x71fc, 0x15d9,
+ 0x71fe, 0x2160,
+ 0x71ff, 0x15db,
+ 0x7206, 0x0d30,
+ 0x720d, 0x15dc,
+ 0x7210, 0x15dd,
+ 0x721b, 0x15de,
+ 0x7228, 0x15df,
+ 0x722a, 0x0bfa,
+ 0x722c, 0x15e1,
+ 0x722d, 0x15e0,
+ 0x7230, 0x15e2,
+ 0x7232, 0x15e3,
+ 0x7235, 0x090b,
+ 0x7236, 0x0dd5,
+ 0x723a, 0x0ef8,
+ 0x723b, 0x15e4,
+ 0x723d, 0x0ad8,
+ 0x723e, 0x08d0,
+ 0x723f, 0x15e6,
+ 0x7246, 0x15e8,
+ 0x7247, 0x0e22,
+ 0x7248, 0x0d5b,
+ 0x724b, 0x15e9,
+ 0x724c, 0x0d0d,
+ 0x7252, 0x0bc9,
+ 0x7258, 0x15ea,
+ 0x7259, 0x0567,
+ 0x725b, 0x0687,
+ 0x725d, 0x0ed2,
+ 0x725f, 0x0ec2,
+ 0x7261, 0x0534,
+ 0x7262, 0x0fda,
+ 0x7267, 0x0e80,
+ 0x7269, 0x0dfa,
+ 0x7272, 0x0a5b,
+ 0x7274, 0x15eb,
+ 0x7279, 0x0c9b,
+ 0x727d, 0x0757,
+ 0x727e, 0x15ec,
+ 0x7280, 0x0844,
+ 0x7281, 0x15ee,
+ 0x7282, 0x15ed,
+ 0x7287, 0x15ef,
+ 0x7292, 0x15f0,
+ 0x7296, 0x15f1,
+ 0x72a0, 0x0658,
+ 0x72a2, 0x15f2,
+ 0x72a7, 0x15f3,
+ 0x72ac, 0x0758,
+ 0x72af, 0x0d5c,
+ 0x72b1, 0x2161,
+ 0x72b2, 0x15f5,
+ 0x72b6, 0x09dd,
+ 0x72b9, 0x15f4,
+ 0x72be, 0x2162,
+ 0x72c2, 0x06b0,
+ 0x72c3, 0x15f6,
+ 0x72c4, 0x15f8,
+ 0x72c6, 0x15f7,
+ 0x72ce, 0x15f9,
+ 0x72d0, 0x0785,
+ 0x72d2, 0x15fa,
+ 0x72d7, 0x06e1,
+ 0x72d9, 0x0ac2,
+ 0x72db, 0x080f,
+ 0x72e0, 0x15fc,
+ 0x72e2, 0x15fb,
+ 0x72e9, 0x0919,
+ 0x72ec, 0x0ca0,
+ 0x72ed, 0x06b1,
+ 0x72f7, 0x15ff,
+ 0x72f8, 0x0b6a,
+ 0x72f9, 0x15fe,
+ 0x72fc, 0x0fdb,
+ 0x72fd, 0x0d18,
+ 0x730a, 0x1602,
+ 0x7316, 0x1604,
+ 0x7317, 0x1601,
+ 0x731b, 0x0ee0,
+ 0x731c, 0x1603,
+ 0x731d, 0x1605,
+ 0x731f, 0x0f8c,
+ 0x7324, 0x2163,
+ 0x7325, 0x1609,
+ 0x7329, 0x1608,
+ 0x732a, 0x0bb4,
+ 0x732b, 0x0ce3,
+ 0x732e, 0x0759,
+ 0x732f, 0x1607,
+ 0x7334, 0x1606,
+ 0x7336, 0x0f1b,
+ 0x733e, 0x160a,
+ 0x733f, 0x0510,
+ 0x7344, 0x0808,
+ 0x7345, 0x08b0,
+ 0x734e, 0x160b,
+ 0x7357, 0x160e,
+ 0x7363, 0x094d,
+ 0x7368, 0x1610,
+ 0x736a, 0x160f,
+ 0x7370, 0x1611,
+ 0x7372, 0x05ab,
+ 0x7375, 0x1613,
+ 0x7377, 0x2165,
+ 0x7378, 0x1612,
+ 0x737a, 0x1615,
+ 0x737b, 0x1614,
+ 0x7384, 0x0770,
+ 0x7387, 0x0f70,
+ 0x7389, 0x06c4,
+ 0x738b, 0x0526,
+ 0x7396, 0x06e2,
+ 0x73a9, 0x061d,
+ 0x73b2, 0x0fb0,
+ 0x73b3, 0x1617,
+ 0x73bb, 0x1619,
+ 0x73bd, 0x2166,
+ 0x73c0, 0x161a,
+ 0x73c2, 0x0551,
+ 0x73c8, 0x1616,
+ 0x73c9, 0x2167,
+ 0x73ca, 0x0887,
+ 0x73cd, 0x0bdd,
+ 0x73ce, 0x1618,
+ 0x73d2, 0x216a,
+ 0x73d6, 0x2168,
+ 0x73de, 0x161d,
+ 0x73e0, 0x091a,
+ 0x73e3, 0x2169,
+ 0x73e5, 0x161b,
+ 0x73ea, 0x0714,
+ 0x73ed, 0x0d5d,
+ 0x73ee, 0x161c,
+ 0x73f1, 0x1637,
+ 0x73f5, 0x216c,
+ 0x73f8, 0x1622,
+ 0x73fe, 0x0771,
+ 0x7403, 0x067f,
+ 0x7405, 0x161f,
+ 0x7406, 0x0f67,
+ 0x7407, 0x216b,
+ 0x7409, 0x0f78,
+ 0x7422, 0x0b56,
+ 0x7425, 0x1621,
+ 0x7426, 0x216d,
+ 0x7429, 0x216f,
+ 0x742a, 0x216e,
+ 0x742e, 0x2170,
+ 0x7432, 0x1623,
+ 0x7433, 0x0f9e,
+ 0x7434, 0x06cf,
+ 0x7435, 0x0d90,
+ 0x7436, 0x0d00,
+ 0x743a, 0x1624,
+ 0x743f, 0x1626,
+ 0x7441, 0x1629,
+ 0x7455, 0x1625,
+ 0x7459, 0x1628,
+ 0x745a, 0x079e,
+ 0x745b, 0x04ef,
+ 0x745c, 0x162a,
+ 0x745e, 0x0a36,
+ 0x745f, 0x1627,
+ 0x7460, 0x0fa4,
+ 0x7462, 0x2171,
+ 0x7463, 0x162d,
+ 0x7464, 0x1d35,
+ 0x7469, 0x162b,
+ 0x746a, 0x162e,
+ 0x746f, 0x1620,
+ 0x7470, 0x162c,
+ 0x7473, 0x082c,
+ 0x7476, 0x162f,
+ 0x747e, 0x1630,
+ 0x7483, 0x0f68,
+ 0x7489, 0x2172,
+ 0x748b, 0x1631,
+ 0x749e, 0x1632,
+ 0x749f, 0x2173,
+ 0x74a2, 0x161e,
+ 0x74a7, 0x1633,
+ 0x74b0, 0x0600,
+ 0x74bd, 0x08d1,
+ 0x74ca, 0x1634,
+ 0x74cf, 0x1635,
+ 0x74d4, 0x1636,
+ 0x74dc, 0x04dd,
+ 0x74e0, 0x1638,
+ 0x74e2, 0x0dad,
+ 0x74e3, 0x1639,
+ 0x74e6, 0x05e0,
+ 0x74e7, 0x163a,
+ 0x74e9, 0x163b,
+ 0x74ee, 0x163c,
+ 0x74f0, 0x163e,
+ 0x74f2, 0x163d,
+ 0x74f6, 0x0dc5,
+ 0x74f7, 0x1641,
+ 0x74f8, 0x1640,
+ 0x7501, 0x2174,
+ 0x7503, 0x1643,
+ 0x7504, 0x1642,
+ 0x7505, 0x1644,
+ 0x750c, 0x1645,
+ 0x750d, 0x1647,
+ 0x750e, 0x1646,
+ 0x7511, 0x080b,
+ 0x7513, 0x1649,
+ 0x7515, 0x1648,
+ 0x7518, 0x0601,
+ 0x751a, 0x0a19,
+ 0x751c, 0x0c36,
+ 0x751e, 0x164a,
+ 0x751f, 0x0a5c,
+ 0x7523, 0x0888,
+ 0x7525, 0x051b,
+ 0x7526, 0x164b,
+ 0x7528, 0x0f3b,
+ 0x752b, 0x0e33,
+ 0x752c, 0x164c,
+ 0x752f, 0x20f2,
+ 0x7530, 0x0c3e,
+ 0x7531, 0x0f1d,
+ 0x7532, 0x07d5,
+ 0x7533, 0x0a03,
+ 0x7537, 0x0b89,
+ 0x7538, 0x10c9,
+ 0x753a, 0x0bca,
+ 0x753b, 0x0568,
+ 0x753c, 0x164d,
+ 0x7544, 0x164e,
+ 0x7546, 0x1653,
+ 0x7549, 0x1651,
+ 0x754a, 0x1650,
+ 0x754b, 0x13c7,
+ 0x754c, 0x0584,
+ 0x754d, 0x164f,
+ 0x754f, 0x049e,
+ 0x7551, 0x0d3e,
+ 0x7554, 0x0d5e,
+ 0x7559, 0x0f79,
+ 0x755a, 0x1654,
+ 0x755b, 0x1652,
+ 0x755c, 0x0b9a,
+ 0x755d, 0x0a4a,
+ 0x7560, 0x0d3f,
+ 0x7562, 0x0d9f,
+ 0x7564, 0x1656,
+ 0x7565, 0x0f74,
+ 0x7566, 0x0723,
+ 0x7567, 0x1657,
+ 0x7569, 0x1655,
+ 0x756a, 0x0d6a,
+ 0x756b, 0x1658,
+ 0x756d, 0x1659,
+ 0x756f, 0x2175,
+ 0x7570, 0x049f,
+ 0x7573, 0x09de,
+ 0x7574, 0x165e,
+ 0x7576, 0x165b,
+ 0x7577, 0x0cc5,
+ 0x7578, 0x165a,
+ 0x757f, 0x0640,
+ 0x7582, 0x1661,
+ 0x7586, 0x165c,
+ 0x7589, 0x1660,
+ 0x758a, 0x165f,
+ 0x758b, 0x0d97,
+ 0x758e, 0x0ac4,
+ 0x758f, 0x0ac3,
+ 0x7591, 0x0659,
+ 0x7594, 0x1662,
+ 0x759a, 0x1663,
+ 0x759d, 0x1664,
+ 0x75a3, 0x1666,
+ 0x75a5, 0x1665,
+ 0x75ab, 0x04f8,
+ 0x75b1, 0x166e,
+ 0x75b2, 0x0d7c,
+ 0x75b3, 0x1668,
+ 0x75b5, 0x166a,
+ 0x75b8, 0x166c,
+ 0x75b9, 0x0a04,
+ 0x75bc, 0x166d,
+ 0x75bd, 0x166b,
+ 0x75be, 0x08ec,
+ 0x75c2, 0x1667,
+ 0x75c3, 0x1669,
+ 0x75c5, 0x0db4,
+ 0x75c7, 0x09b1,
+ 0x75ca, 0x1670,
+ 0x75cd, 0x166f,
+ 0x75d2, 0x1671,
+ 0x75d4, 0x08d2,
+ 0x75d5, 0x081f,
+ 0x75d8, 0x0c71,
+ 0x75d9, 0x1672,
+ 0x75db, 0x0be7,
+ 0x75de, 0x1674,
+ 0x75e2, 0x0f69,
+ 0x75e3, 0x1673,
+ 0x75e9, 0x0aeb,
+ 0x75f0, 0x1679,
+ 0x75f2, 0x167b,
+ 0x75f4, 0x0b92,
+ 0x75fa, 0x167a,
+ 0x75fc, 0x1677,
+ 0x75fe, 0x1675,
+ 0x7601, 0x1678,
+ 0x7609, 0x167f,
+ 0x760b, 0x167d,
+ 0x760d, 0x167e,
+ 0x761f, 0x1680,
+ 0x7620, 0x1682,
+ 0x7624, 0x1685,
+ 0x7626, 0x1e2d,
+ 0x7627, 0x1681,
+ 0x7630, 0x1687,
+ 0x7634, 0x1686,
+ 0x763b, 0x1688,
+ 0x7642, 0x0f8d,
+ 0x7646, 0x168b,
+ 0x7647, 0x1689,
+ 0x764c, 0x061e,
+ 0x7652, 0x0f0a,
+ 0x7656, 0x0e1a,
+ 0x7658, 0x168d,
+ 0x765c, 0x168c,
+ 0x7661, 0x168e,
+ 0x7667, 0x1693,
+ 0x7668, 0x1690,
+ 0x766c, 0x1694,
+ 0x7670, 0x1695,
+ 0x7672, 0x1696,
+ 0x7676, 0x1697,
+ 0x7678, 0x1698,
+ 0x767a, 0x0d43,
+ 0x767b, 0x0c4a,
+ 0x767c, 0x1699,
+ 0x767d, 0x0d28,
+ 0x767e, 0x0da6,
+ 0x7680, 0x169a,
+ 0x7682, 0x2176,
+ 0x7683, 0x169b,
+ 0x7684, 0x0c24,
+ 0x7686, 0x0585,
+ 0x7687, 0x07d6,
+ 0x7688, 0x169c,
+ 0x768b, 0x169d,
+ 0x768e, 0x169e,
+ 0x7690, 0x0877,
+ 0x7693, 0x16a0,
+ 0x7696, 0x169f,
+ 0x7699, 0x16a1,
+ 0x769b, 0x2179,
+ 0x769c, 0x2177,
+ 0x769e, 0x2178,
+ 0x76a6, 0x217a,
+ 0x76ae, 0x0d7d,
+ 0x76b0, 0x16a3,
+ 0x76b4, 0x16a4,
+ 0x76b7, 0x1d1c,
+ 0x76b8, 0x16a5,
+ 0x76bf, 0x087c,
+ 0x76c2, 0x16a8,
+ 0x76c3, 0x0d0c,
+ 0x76c6, 0x0e8d,
+ 0x76c8, 0x04f0,
+ 0x76ca, 0x04f9,
+ 0x76cd, 0x16a9,
+ 0x76d2, 0x16ab,
+ 0x76d6, 0x16aa,
+ 0x76d7, 0x0c6a,
+ 0x76db, 0x0a5d,
+ 0x76dc, 0x14d8,
+ 0x76de, 0x16ac,
+ 0x76df, 0x0ecd,
+ 0x76e1, 0x16ad,
+ 0x76e3, 0x0602,
+ 0x76e4, 0x0d6b,
+ 0x76e5, 0x16ae,
+ 0x76e7, 0x16af,
+ 0x76ea, 0x16b0,
+ 0x76ee, 0x0ee8,
+ 0x76f2, 0x0ee1,
+ 0x76f4, 0x0bda,
+ 0x76f8, 0x0aec,
+ 0x76fb, 0x16b2,
+ 0x76fe, 0x096c,
+ 0x7701, 0x09b2,
+ 0x7704, 0x16b5,
+ 0x7707, 0x16b4,
+ 0x7708, 0x16b3,
+ 0x7709, 0x0d91,
+ 0x770b, 0x0603,
+ 0x770c, 0x075d,
+ 0x771b, 0x16bb,
+ 0x771e, 0x16b8,
+ 0x771f, 0x0a05,
+ 0x7720, 0x0ebe,
+ 0x7724, 0x16b7,
+ 0x7725, 0x16b9,
+ 0x7729, 0x16b6,
+ 0x7737, 0x16bc,
+ 0x773a, 0x0bcb,
+ 0x773c, 0x061f,
+ 0x7740, 0x0ba3,
+ 0x7746, 0x217c,
+ 0x7747, 0x16be,
+ 0x775a, 0x16bf,
+ 0x775b, 0x16c2,
+ 0x7761, 0x0a2d,
+ 0x7762, 0x1ec5,
+ 0x7763, 0x0c9c,
+ 0x7765, 0x16c3,
+ 0x7766, 0x0e81,
+ 0x7768, 0x16c0,
+ 0x776b, 0x16c1,
+ 0x7779, 0x16c6,
+ 0x777e, 0x16c5,
+ 0x777f, 0x16c4,
+ 0x778b, 0x16c8,
+ 0x778e, 0x16c7,
+ 0x7791, 0x16c9,
+ 0x779e, 0x16cb,
+ 0x77a0, 0x16ca,
+ 0x77a5, 0x0e1d,
+ 0x77ac, 0x0960,
+ 0x77ad, 0x0f8e,
+ 0x77b0, 0x16cc,
+ 0x77b3, 0x0c8f,
+ 0x77b6, 0x16cd,
+ 0x77b9, 0x16ce,
+ 0x77bb, 0x16d2,
+ 0x77bc, 0x16d0,
+ 0x77bf, 0x16cf,
+ 0x77c7, 0x16d3,
+ 0x77cd, 0x16d4,
+ 0x77d7, 0x16d5,
+ 0x77da, 0x16d6,
+ 0x77db, 0x0ec3,
+ 0x77dc, 0x16d7,
+ 0x77e2, 0x0efc,
+ 0x77e3, 0x16d8,
+ 0x77e5, 0x0b8c,
+ 0x77e7, 0x0d20,
+ 0x77e9, 0x06e3,
+ 0x77ed, 0x0b79,
+ 0x77ee, 0x16d9,
+ 0x77ef, 0x06b2,
+ 0x77f3, 0x0a74,
+ 0x77fc, 0x16da,
+ 0x7802, 0x082d,
+ 0x780c, 0x16db,
+ 0x7812, 0x16dc,
+ 0x7814, 0x075a,
+ 0x7815, 0x0845,
+ 0x7820, 0x16de,
+ 0x7821, 0x217e,
+ 0x7825, 0x0c50,
+ 0x7826, 0x0846,
+ 0x7827, 0x0668,
+ 0x7832, 0x0e52,
+ 0x7834, 0x0d01,
+ 0x783a, 0x0c51,
+ 0x783f, 0x07ee,
+ 0x7845, 0x16e0,
+ 0x784e, 0x217f,
+ 0x785d, 0x09b3,
+ 0x7864, 0x2180,
+ 0x786b, 0x0f7a,
+ 0x786c, 0x07d7,
+ 0x786f, 0x075b,
+ 0x7872, 0x0d37,
+ 0x7874, 0x16e2,
+ 0x787a, 0x2181,
+ 0x787c, 0x16e4,
+ 0x7881, 0x079f,
+ 0x7886, 0x16e3,
+ 0x7887, 0x0c12,
+ 0x788c, 0x16e6,
+ 0x788d, 0x0595,
+ 0x788e, 0x16e1,
+ 0x7891, 0x0d7e,
+ 0x7893, 0x04d2,
+ 0x7895, 0x085c,
+ 0x7897, 0x0ff8,
+ 0x789a, 0x16e5,
+ 0x78a3, 0x16e7,
+ 0x78a7, 0x0e1b,
+ 0x78a9, 0x0a7d,
+ 0x78aa, 0x16e9,
+ 0x78af, 0x16ea,
+ 0x78b5, 0x16e8,
+ 0x78ba, 0x05ac,
+ 0x78bc, 0x16f0,
+ 0x78be, 0x16ef,
+ 0x78c1, 0x08d3,
+ 0x78c5, 0x16f1,
+ 0x78c6, 0x16ec,
+ 0x78ca, 0x16f2,
+ 0x78cb, 0x16ed,
+ 0x78d0, 0x0d6c,
+ 0x78d1, 0x16eb,
+ 0x78d4, 0x16ee,
+ 0x78da, 0x16f5,
+ 0x78e7, 0x16f4,
+ 0x78e8, 0x0e8f,
+ 0x78ec, 0x16f3,
+ 0x78ef, 0x04af,
+ 0x78f4, 0x16f7,
+ 0x78fd, 0x16f6,
+ 0x7901, 0x09b4,
+ 0x7907, 0x16f8,
+ 0x790e, 0x0ac5,
+ 0x7911, 0x16fa,
+ 0x7912, 0x16f9,
+ 0x7919, 0x16fb,
+ 0x7926, 0x16dd,
+ 0x792a, 0x16df,
+ 0x792b, 0x16fd,
+ 0x792c, 0x16fc,
+ 0x7930, 0x2182,
+ 0x793a, 0x08d4,
+ 0x793c, 0x0fb1,
+ 0x793e, 0x08fe,
+ 0x7940, 0x16fe,
+ 0x7941, 0x070d,
+ 0x7947, 0x065a,
+ 0x7948, 0x0641,
+ 0x7949, 0x08b1,
+ 0x7950, 0x0f1e,
+ 0x7953, 0x1704,
+ 0x7955, 0x1703,
+ 0x7956, 0x0ac6,
+ 0x7957, 0x1700,
+ 0x795a, 0x1702,
+ 0x795d, 0x0955,
+ 0x795e, 0x0a06,
+ 0x795f, 0x1701,
+ 0x7960, 0x16ff,
+ 0x7962, 0x0ce0,
+ 0x7965, 0x09b5,
+ 0x7968, 0x0dae,
+ 0x796d, 0x0847,
+ 0x7977, 0x0c72,
+ 0x797a, 0x1705,
+ 0x797f, 0x1706,
+ 0x7980, 0x171c,
+ 0x7981, 0x06d0,
+ 0x7984, 0x0fe3,
+ 0x7985, 0x0ab7,
+ 0x798a, 0x1707,
+ 0x798d, 0x0552,
+ 0x798e, 0x0c13,
+ 0x798f, 0x0df1,
+ 0x7994, 0x2186,
+ 0x799b, 0x2188,
+ 0x799d, 0x1708,
+ 0x79a6, 0x0694,
+ 0x79a7, 0x1709,
+ 0x79aa, 0x170b,
+ 0x79ae, 0x170c,
+ 0x79b0, 0x0cdf,
+ 0x79b1, 0x1e4e,
+ 0x79b3, 0x170d,
+ 0x79b9, 0x170e,
+ 0x79bd, 0x06d1,
+ 0x79be, 0x0553,
+ 0x79bf, 0x0c9d,
+ 0x79c0, 0x0932,
+ 0x79c1, 0x08b2,
+ 0x79c9, 0x1710,
+ 0x79cb, 0x0933,
+ 0x79d1, 0x054a,
+ 0x79d2, 0x0db5,
+ 0x79d5, 0x1711,
+ 0x79d8, 0x0d7f,
+ 0x79df, 0x0ac7,
+ 0x79e1, 0x1714,
+ 0x79e3, 0x1715,
+ 0x79e4, 0x0d1f,
+ 0x79e6, 0x0a07,
+ 0x79e7, 0x1712,
+ 0x79e9, 0x0b9f,
+ 0x79ec, 0x1713,
+ 0x79f0, 0x09b6,
+ 0x79fb, 0x04a0,
+ 0x7a00, 0x0643,
+ 0x7a08, 0x1716,
+ 0x7a0b, 0x0c14,
+ 0x7a0d, 0x1717,
+ 0x7a0e, 0x0a6b,
+ 0x7a14, 0x0eb9,
+ 0x7a17, 0x0d95,
+ 0x7a18, 0x1718,
+ 0x7a1a, 0x0b93,
+ 0x7a1c, 0x0f8f,
+ 0x7a1f, 0x171b,
+ 0x7a20, 0x171a,
+ 0x7a2e, 0x091b,
+ 0x7a31, 0x171d,
+ 0x7a32, 0x04b4,
+ 0x7a37, 0x1720,
+ 0x7a3b, 0x171e,
+ 0x7a3c, 0x0554,
+ 0x7a3d, 0x0724,
+ 0x7a3e, 0x171f,
+ 0x7a3f, 0x07d8,
+ 0x7a40, 0x0804,
+ 0x7a42, 0x0e36,
+ 0x7a43, 0x1721,
+ 0x7a46, 0x0e82,
+ 0x7a49, 0x1723,
+ 0x7a4d, 0x0a75,
+ 0x7a4e, 0x04f1,
+ 0x7a4f, 0x053a,
+ 0x7a50, 0x0470,
+ 0x7a57, 0x1722,
+ 0x7a61, 0x1724,
+ 0x7a63, 0x09df,
+ 0x7a69, 0x1726,
+ 0x7a6b, 0x05ad,
+ 0x7a70, 0x1728,
+ 0x7a74, 0x0740,
+ 0x7a76, 0x0680,
+ 0x7a79, 0x1729,
+ 0x7a7a, 0x06ed,
+ 0x7a7d, 0x172a,
+ 0x7a7f, 0x0aa0,
+ 0x7a81, 0x0ca5,
+ 0x7a83, 0x0a84,
+ 0x7a84, 0x0865,
+ 0x7a88, 0x172b,
+ 0x7a92, 0x0ba0,
+ 0x7a93, 0x0aed,
+ 0x7a95, 0x172d,
+ 0x7a96, 0x172f,
+ 0x7a97, 0x172c,
+ 0x7a98, 0x172e,
+ 0x7a9f, 0x06f8,
+ 0x7aa9, 0x1730,
+ 0x7aaa, 0x06fc,
+ 0x7aae, 0x0681,
+ 0x7aaf, 0x0f3c,
+ 0x7ab0, 0x1732,
+ 0x7ab6, 0x1733,
+ 0x7aba, 0x04d0,
+ 0x7abf, 0x1736,
+ 0x7ac3, 0x05d4,
+ 0x7ac4, 0x1735,
+ 0x7ac5, 0x1734,
+ 0x7ac7, 0x1738,
+ 0x7ac8, 0x1731,
+ 0x7aca, 0x1739,
+ 0x7acb, 0x0f71,
+ 0x7acd, 0x173a,
+ 0x7acf, 0x173b,
+ 0x7ad1, 0x2189,
+ 0x7ad2, 0x11c5,
+ 0x7ad3, 0x173d,
+ 0x7ad5, 0x173c,
+ 0x7ad9, 0x173e,
+ 0x7adc, 0x0f7d,
+ 0x7add, 0x1740,
+ 0x7adf, 0x1c08,
+ 0x7ae0, 0x09b7,
+ 0x7ae1, 0x1741,
+ 0x7ae3, 0x0961,
+ 0x7ae5, 0x0c90,
+ 0x7ae6, 0x1743,
+ 0x7ae7, 0x218a,
+ 0x7aea, 0x0b66,
+ 0x7aeb, 0x218c,
+ 0x7aed, 0x1744,
+ 0x7aef, 0x0b7a,
+ 0x7af0, 0x1745,
+ 0x7af6, 0x069d,
+ 0x7af8, 0x1076,
+ 0x7af9, 0x0b9b,
+ 0x7afa, 0x08df,
+ 0x7aff, 0x0604,
+ 0x7b02, 0x1746,
+ 0x7b04, 0x1753,
+ 0x7b06, 0x1749,
+ 0x7b08, 0x0682,
+ 0x7b0a, 0x1748,
+ 0x7b0b, 0x1755,
+ 0x7b0f, 0x1747,
+ 0x7b11, 0x09b8,
+ 0x7b18, 0x174b,
+ 0x7b1b, 0x0c25,
+ 0x7b1e, 0x174d,
+ 0x7b20, 0x05bc,
+ 0x7b25, 0x0a20,
+ 0x7b26, 0x0dd6,
+ 0x7b28, 0x174f,
+ 0x7b2c, 0x0b48,
+ 0x7b33, 0x174a,
+ 0x7b35, 0x174e,
+ 0x7b36, 0x1750,
+ 0x7b39, 0x086b,
+ 0x7b45, 0x1757,
+ 0x7b46, 0x0da0,
+ 0x7b48, 0x0d3a,
+ 0x7b49, 0x0c73,
+ 0x7b4b, 0x06d2,
+ 0x7b4c, 0x1756,
+ 0x7b4d, 0x1754,
+ 0x7b4f, 0x0d49,
+ 0x7b50, 0x1751,
+ 0x7b51, 0x0b9c,
+ 0x7b52, 0x0c75,
+ 0x7b54, 0x0c74,
+ 0x7b56, 0x0866,
+ 0x7b5d, 0x1769,
+ 0x7b65, 0x1759,
+ 0x7b67, 0x175b,
+ 0x7b6c, 0x175e,
+ 0x7b6e, 0x175f,
+ 0x7b70, 0x175c,
+ 0x7b74, 0x175a,
+ 0x7b75, 0x1758,
+ 0x7b7a, 0x1752,
+ 0x7b86, 0x0e1f,
+ 0x7b87, 0x0555,
+ 0x7b8b, 0x1766,
+ 0x7b8d, 0x1763,
+ 0x7b8f, 0x1768,
+ 0x7b92, 0x1767,
+ 0x7b94, 0x0d29,
+ 0x7b95, 0x0eb3,
+ 0x7b97, 0x0889,
+ 0x7b98, 0x1761,
+ 0x7b99, 0x176a,
+ 0x7b9a, 0x1765,
+ 0x7b9c, 0x1764,
+ 0x7b9d, 0x1760,
+ 0x7b9e, 0x218d,
+ 0x7b9f, 0x1762,
+ 0x7ba1, 0x0605,
+ 0x7baa, 0x0b7b,
+ 0x7bad, 0x0aa1,
+ 0x7bb1, 0x0d36,
+ 0x7bb4, 0x176f,
+ 0x7bb8, 0x0d38,
+ 0x7bc0, 0x0a85,
+ 0x7bc1, 0x176c,
+ 0x7bc4, 0x0d63,
+ 0x7bc6, 0x1770,
+ 0x7bc7, 0x0e23,
+ 0x7bc9, 0x0b99,
+ 0x7bcb, 0x176b,
+ 0x7bcc, 0x176d,
+ 0x7bcf, 0x176e,
+ 0x7bdd, 0x1771,
+ 0x7be0, 0x08f0,
+ 0x7be4, 0x0c9e,
+ 0x7be5, 0x1776,
+ 0x7be6, 0x1775,
+ 0x7be9, 0x1772,
+ 0x7bed, 0x0fdc,
+ 0x7bf3, 0x177b,
+ 0x7bf6, 0x177f,
+ 0x7bf7, 0x177c,
+ 0x7c00, 0x1778,
+ 0x7c07, 0x1779,
+ 0x7c0d, 0x177e,
+ 0x7c11, 0x1773,
+ 0x7c12, 0x10ea,
+ 0x7c13, 0x177a,
+ 0x7c14, 0x1774,
+ 0x7c17, 0x177d,
+ 0x7c1e, 0x1e3b,
+ 0x7c1f, 0x1783,
+ 0x7c21, 0x0606,
+ 0x7c23, 0x1780,
+ 0x7c27, 0x1781,
+ 0x7c2a, 0x1782,
+ 0x7c2b, 0x1785,
+ 0x7c37, 0x1784,
+ 0x7c38, 0x0d8a,
+ 0x7c3d, 0x1786,
+ 0x7c3e, 0x0fc4,
+ 0x7c3f, 0x0e3d,
+ 0x7c40, 0x178b,
+ 0x7c43, 0x1788,
+ 0x7c4c, 0x1787,
+ 0x7c4d, 0x0a76,
+ 0x7c4f, 0x178a,
+ 0x7c50, 0x178c,
+ 0x7c54, 0x1789,
+ 0x7c56, 0x1790,
+ 0x7c58, 0x178d,
+ 0x7c5f, 0x178e,
+ 0x7c60, 0x1777,
+ 0x7c64, 0x178f,
+ 0x7c65, 0x1791,
+ 0x7c6c, 0x1792,
+ 0x7c73, 0x0e16,
+ 0x7c75, 0x1793,
+ 0x7c7e, 0x0eee,
+ 0x7c81, 0x06c6,
+ 0x7c82, 0x06ff,
+ 0x7c83, 0x1794,
+ 0x7c89, 0x0e04,
+ 0x7c8b, 0x0a2e,
+ 0x7c8d, 0x0ebc,
+ 0x7c90, 0x1795,
+ 0x7c92, 0x0f7b,
+ 0x7c95, 0x0d2a,
+ 0x7c97, 0x0ac8,
+ 0x7c98, 0x0cea,
+ 0x7c9b, 0x0957,
+ 0x7c9f, 0x0484,
+ 0x7ca1, 0x179a,
+ 0x7ca2, 0x1798,
+ 0x7ca4, 0x1796,
+ 0x7ca5, 0x05dd,
+ 0x7ca7, 0x09b9,
+ 0x7ca8, 0x179b,
+ 0x7cab, 0x1799,
+ 0x7cad, 0x1797,
+ 0x7cae, 0x179f,
+ 0x7cb1, 0x179e,
+ 0x7cb2, 0x179d,
+ 0x7cb3, 0x179c,
+ 0x7cb9, 0x17a0,
+ 0x7cbd, 0x17a1,
+ 0x7cbe, 0x0a5e,
+ 0x7cc0, 0x17a2,
+ 0x7cc2, 0x17a4,
+ 0x7cc5, 0x17a3,
+ 0x7cca, 0x0786,
+ 0x7cce, 0x0aba,
+ 0x7cd2, 0x17a6,
+ 0x7cd6, 0x0c76,
+ 0x7cd8, 0x17a5,
+ 0x7cdc, 0x17a7,
+ 0x7cde, 0x0e05,
+ 0x7cdf, 0x0aee,
+ 0x7ce0, 0x07d9,
+ 0x7ce2, 0x17a8,
+ 0x7ce7, 0x0f90,
+ 0x7cef, 0x17aa,
+ 0x7cf2, 0x17ab,
+ 0x7cf4, 0x17ac,
+ 0x7cf6, 0x17ad,
+ 0x7cf8, 0x08b3,
+ 0x7cfa, 0x17ae,
+ 0x7cfb, 0x0725,
+ 0x7cfe, 0x0684,
+ 0x7d00, 0x0644,
+ 0x7d02, 0x17b0,
+ 0x7d04, 0x0eff,
+ 0x7d05, 0x07da,
+ 0x7d06, 0x17af,
+ 0x7d0a, 0x17b3,
+ 0x7d0b, 0x0ef2,
+ 0x7d0d, 0x0cf2,
+ 0x7d10, 0x0da5,
+ 0x7d14, 0x096d,
+ 0x7d15, 0x17b2,
+ 0x7d17, 0x08ff,
+ 0x7d18, 0x07db,
+ 0x7d19, 0x08b4,
+ 0x7d1a, 0x0683,
+ 0x7d1b, 0x0e06,
+ 0x7d1c, 0x17b1,
+ 0x7d20, 0x0ac9,
+ 0x7d21, 0x0e70,
+ 0x7d22, 0x0867,
+ 0x7d2b, 0x08b5,
+ 0x7d2c, 0x0bf9,
+ 0x7d2e, 0x17b6,
+ 0x7d2f, 0x0fa7,
+ 0x7d30, 0x0849,
+ 0x7d32, 0x17b7,
+ 0x7d33, 0x0a08,
+ 0x7d35, 0x17b9,
+ 0x7d39, 0x09ba,
+ 0x7d3a, 0x0820,
+ 0x7d3f, 0x17b8,
+ 0x7d42, 0x0934,
+ 0x7d43, 0x0772,
+ 0x7d44, 0x0aca,
+ 0x7d45, 0x17b4,
+ 0x7d46, 0x17ba,
+ 0x7d48, 0x218f,
+ 0x7d4b, 0x17b5,
+ 0x7d4c, 0x0726,
+ 0x7d4e, 0x17bd,
+ 0x7d4f, 0x17c1,
+ 0x7d50, 0x0741,
+ 0x7d56, 0x17bc,
+ 0x7d5b, 0x17c5,
+ 0x7d5c, 0x2190,
+ 0x7d5e, 0x07dc,
+ 0x7d61, 0x0f57,
+ 0x7d62, 0x0480,
+ 0x7d63, 0x17c2,
+ 0x7d66, 0x0685,
+ 0x7d68, 0x17bf,
+ 0x7d6e, 0x17c0,
+ 0x7d71, 0x0c77,
+ 0x7d72, 0x17be,
+ 0x7d73, 0x17bb,
+ 0x7d75, 0x0586,
+ 0x7d76, 0x0a88,
+ 0x7d79, 0x075c,
+ 0x7d7d, 0x17c7,
+ 0x7d89, 0x17c4,
+ 0x7d8f, 0x17c6,
+ 0x7d93, 0x17c3,
+ 0x7d99, 0x0727,
+ 0x7d9a, 0x0b13,
+ 0x7d9b, 0x17c8,
+ 0x7d9c, 0x0af0,
+ 0x7d9f, 0x17d5,
+ 0x7da0, 0x2192,
+ 0x7da2, 0x17d1,
+ 0x7da3, 0x17cb,
+ 0x7dab, 0x17cf,
+ 0x7dac, 0x0926,
+ 0x7dad, 0x04a1,
+ 0x7dae, 0x17ca,
+ 0x7daf, 0x17d2,
+ 0x7db0, 0x17d6,
+ 0x7db1, 0x07dd,
+ 0x7db2, 0x0ee2,
+ 0x7db4, 0x0bf2,
+ 0x7db5, 0x17cc,
+ 0x7db7, 0x2191,
+ 0x7db8, 0x17d4,
+ 0x7dba, 0x17c9,
+ 0x7dbb, 0x0b7c,
+ 0x7dbd, 0x17ce,
+ 0x7dbe, 0x0481,
+ 0x7dbf, 0x0ed6,
+ 0x7dc7, 0x17cd,
+ 0x7dca, 0x06d3,
+ 0x7dcb, 0x0d80,
+ 0x7dcf, 0x0aef,
+ 0x7dd1, 0x0f98,
+ 0x7dd2, 0x0979,
+ 0x7dd5, 0x17fd,
+ 0x7dd6, 0x2193,
+ 0x7dd8, 0x17d7,
+ 0x7dda, 0x0aa2,
+ 0x7ddc, 0x17d3,
+ 0x7ddd, 0x17d8,
+ 0x7dde, 0x17da,
+ 0x7de0, 0x0c15,
+ 0x7de1, 0x17dd,
+ 0x7de4, 0x17d9,
+ 0x7de8, 0x0e24,
+ 0x7de9, 0x0607,
+ 0x7dec, 0x0ed7,
+ 0x7def, 0x04a2,
+ 0x7df2, 0x17dc,
+ 0x7df4, 0x0fc5,
+ 0x7dfb, 0x17db,
+ 0x7e01, 0x0511,
+ 0x7e04, 0x0cc4,
+ 0x7e05, 0x17de,
+ 0x7e09, 0x17e5,
+ 0x7e0a, 0x17df,
+ 0x7e0b, 0x17e6,
+ 0x7e12, 0x17e2,
+ 0x7e1b, 0x0d31,
+ 0x7e1e, 0x08f6,
+ 0x7e1f, 0x17e4,
+ 0x7e21, 0x17e1,
+ 0x7e22, 0x17e7,
+ 0x7e23, 0x17e0,
+ 0x7e26, 0x094e,
+ 0x7e2b, 0x0e53,
+ 0x7e2e, 0x0956,
+ 0x7e31, 0x17e3,
+ 0x7e32, 0x17ef,
+ 0x7e35, 0x17eb,
+ 0x7e37, 0x17ee,
+ 0x7e39, 0x17ec,
+ 0x7e3a, 0x17f0,
+ 0x7e3b, 0x17ea,
+ 0x7e3d, 0x17d0,
+ 0x7e3e, 0x0a77,
+ 0x7e41, 0x0d5f,
+ 0x7e43, 0x17ed,
+ 0x7e46, 0x17e8,
+ 0x7e4a, 0x0aa3,
+ 0x7e4b, 0x0728,
+ 0x7e4d, 0x0935,
+ 0x7e52, 0x2194,
+ 0x7e54, 0x09eb,
+ 0x7e55, 0x0ab8,
+ 0x7e56, 0x17f3,
+ 0x7e59, 0x17f5,
+ 0x7e5d, 0x17f2,
+ 0x7e5e, 0x17f4,
+ 0x7e61, 0x1e11,
+ 0x7e66, 0x17e9,
+ 0x7e67, 0x17f1,
+ 0x7e69, 0x17f9,
+ 0x7e6a, 0x17f8,
+ 0x7e6b, 0x1df7,
+ 0x7e6d, 0x0ea8,
+ 0x7e70, 0x0701,
+ 0x7e79, 0x17f7,
+ 0x7e7b, 0x17fb,
+ 0x7e7c, 0x17fa,
+ 0x7e7d, 0x17fe,
+ 0x7e7f, 0x1800,
+ 0x7e82, 0x088a,
+ 0x7e83, 0x17fc,
+ 0x7e88, 0x1801,
+ 0x7e8a, 0x20a7,
+ 0x7e8c, 0x1803,
+ 0x7e8e, 0x1809,
+ 0x7e8f, 0x0c35,
+ 0x7e90, 0x1805,
+ 0x7e92, 0x1804,
+ 0x7e93, 0x1806,
+ 0x7e96, 0x1808,
+ 0x7e9b, 0x180a,
+ 0x7f36, 0x0608,
+ 0x7f38, 0x180c,
+ 0x7f3a, 0x180d,
+ 0x7f45, 0x180e,
+ 0x7f47, 0x2195,
+ 0x7f4c, 0x180f,
+ 0x7f50, 0x1812,
+ 0x7f54, 0x1815,
+ 0x7f55, 0x1814,
+ 0x7f58, 0x1816,
+ 0x7f5f, 0x1817,
+ 0x7f67, 0x181b,
+ 0x7f68, 0x1819,
+ 0x7f6a, 0x0851,
+ 0x7f6b, 0x0729,
+ 0x7f6e, 0x0b94,
+ 0x7f70, 0x0d47,
+ 0x7f72, 0x097a,
+ 0x7f75, 0x0d03,
+ 0x7f77, 0x0d81,
+ 0x7f78, 0x181c,
+ 0x7f79, 0x1336,
+ 0x7f82, 0x181d,
+ 0x7f83, 0x181f,
+ 0x7f85, 0x0f4f,
+ 0x7f86, 0x181e,
+ 0x7f87, 0x1821,
+ 0x7f88, 0x1820,
+ 0x7f8a, 0x0f3d,
+ 0x7f8c, 0x1822,
+ 0x7f8e, 0x0d92,
+ 0x7f94, 0x1823,
+ 0x7f9a, 0x1826,
+ 0x7f9d, 0x1825,
+ 0x7f9e, 0x1824,
+ 0x7fa1, 0x2196,
+ 0x7fa3, 0x1827,
+ 0x7fa4, 0x0708,
+ 0x7fa8, 0x0aa4,
+ 0x7fa9, 0x065b,
+ 0x7fae, 0x182b,
+ 0x7faf, 0x1828,
+ 0x7fb2, 0x1829,
+ 0x7fb6, 0x182c,
+ 0x7fb8, 0x182d,
+ 0x7fb9, 0x182a,
+ 0x7fbd, 0x04cb,
+ 0x7fc1, 0x0527,
+ 0x7fc5, 0x182f,
+ 0x7fca, 0x1831,
+ 0x7fcc, 0x0f4c,
+ 0x7fd2, 0x0936,
+ 0x7fd4, 0x1833,
+ 0x7fd5, 0x1832,
+ 0x7fe0, 0x0a2f,
+ 0x7fe1, 0x1834,
+ 0x7fe6, 0x1835,
+ 0x7fe9, 0x1836,
+ 0x7feb, 0x0621,
+ 0x7ff0, 0x0609,
+ 0x7ff3, 0x1837,
+ 0x7ff9, 0x1838,
+ 0x7ffb, 0x0e8b,
+ 0x7ffc, 0x0f4d,
+ 0x8000, 0x0f3e,
+ 0x8001, 0x0fdd,
+ 0x8003, 0x07df,
+ 0x8004, 0x183b,
+ 0x8005, 0x0900,
+ 0x8006, 0x183a,
+ 0x800b, 0x183c,
+ 0x800c, 0x08d5,
+ 0x8010, 0x0b31,
+ 0x8012, 0x183d,
+ 0x8015, 0x07de,
+ 0x8017, 0x0ee3,
+ 0x8018, 0x183e,
+ 0x801c, 0x1840,
+ 0x8021, 0x1841,
+ 0x8028, 0x1842,
+ 0x8033, 0x08d6,
+ 0x8036, 0x0ef9,
+ 0x803b, 0x1844,
+ 0x803d, 0x0b7d,
+ 0x803f, 0x1843,
+ 0x8046, 0x1846,
+ 0x804a, 0x1845,
+ 0x8052, 0x1847,
+ 0x8056, 0x0a5f,
+ 0x8058, 0x1848,
+ 0x805a, 0x1849,
+ 0x805e, 0x0e09,
+ 0x805f, 0x184a,
+ 0x8061, 0x0af1,
+ 0x8062, 0x184b,
+ 0x8068, 0x184c,
+ 0x806f, 0x0fc6,
+ 0x8070, 0x184f,
+ 0x8072, 0x184e,
+ 0x8073, 0x184d,
+ 0x8074, 0x0bcc,
+ 0x8076, 0x1850,
+ 0x8077, 0x09ec,
+ 0x8079, 0x1851,
+ 0x807d, 0x1852,
+ 0x807e, 0x0fde,
+ 0x807f, 0x1853,
+ 0x8084, 0x1854,
+ 0x8085, 0x1856,
+ 0x8086, 0x1855,
+ 0x8087, 0x0d39,
+ 0x8089, 0x0cd1,
+ 0x808b, 0x0fe4,
+ 0x808c, 0x0d3d,
+ 0x8093, 0x1858,
+ 0x8096, 0x09bb,
+ 0x8098, 0x0d9c,
+ 0x809a, 0x1859,
+ 0x809b, 0x1857,
+ 0x809d, 0x060a,
+ 0x80a1, 0x0788,
+ 0x80a2, 0x08b6,
+ 0x80a5, 0x0d82,
+ 0x80a9, 0x075e,
+ 0x80aa, 0x0e71,
+ 0x80ac, 0x185c,
+ 0x80ad, 0x185a,
+ 0x80af, 0x07e0,
+ 0x80b1, 0x07e1,
+ 0x80b2, 0x04ad,
+ 0x80b4, 0x0858,
+ 0x80ba, 0x0d0f,
+ 0x80c3, 0x04a3,
+ 0x80c4, 0x1861,
+ 0x80c6, 0x0b7e,
+ 0x80cc, 0x0d0e,
+ 0x80ce, 0x0b3b,
+ 0x80d6, 0x1863,
+ 0x80d9, 0x185f,
+ 0x80da, 0x1862,
+ 0x80db, 0x185d,
+ 0x80dd, 0x1860,
+ 0x80de, 0x0e54,
+ 0x80e1, 0x0789,
+ 0x80e4, 0x04c1,
+ 0x80e5, 0x185e,
+ 0x80ef, 0x1865,
+ 0x80f1, 0x1866,
+ 0x80f4, 0x0c91,
+ 0x80f8, 0x06b3,
+ 0x80fc, 0x1871,
+ 0x80fd, 0x0cf3,
+ 0x8102, 0x08b7,
+ 0x8105, 0x06b4,
+ 0x8106, 0x0a6c,
+ 0x8107, 0x0fec,
+ 0x8108, 0x0eba,
+ 0x8109, 0x1864,
+ 0x810a, 0x0a78,
+ 0x811a, 0x066d,
+ 0x811b, 0x1867,
+ 0x8123, 0x1869,
+ 0x8129, 0x1868,
+ 0x812f, 0x186a,
+ 0x8131, 0x0b64,
+ 0x8133, 0x0cf4,
+ 0x8139, 0x0bcd,
+ 0x813e, 0x186e,
+ 0x8146, 0x186d,
+ 0x814b, 0x186b,
+ 0x814e, 0x0a1b,
+ 0x8150, 0x0dd7,
+ 0x8151, 0x1870,
+ 0x8153, 0x186f,
+ 0x8154, 0x07e2,
+ 0x8155, 0x0ff9,
+ 0x815f, 0x1880,
+ 0x8165, 0x1874,
+ 0x816b, 0x091c,
+ 0x816e, 0x1873,
+ 0x8170, 0x080a,
+ 0x8171, 0x1872,
+ 0x8174, 0x1876,
+ 0x8178, 0x0bce,
+ 0x8179, 0x0df2,
+ 0x817a, 0x0aa5,
+ 0x817f, 0x0b3c,
+ 0x8180, 0x187a,
+ 0x8182, 0x187b,
+ 0x8183, 0x1877,
+ 0x8188, 0x1878,
+ 0x818a, 0x1879,
+ 0x818f, 0x07e3,
+ 0x8193, 0x1881,
+ 0x8195, 0x187d,
+ 0x819a, 0x0dd8,
+ 0x819c, 0x0e9a,
+ 0x819d, 0x0d9a,
+ 0x81a0, 0x187c,
+ 0x81a3, 0x187f,
+ 0x81a4, 0x187e,
+ 0x81a8, 0x0e72,
+ 0x81a9, 0x1882,
+ 0x81b0, 0x1883,
+ 0x81b3, 0x0ab9,
+ 0x81b5, 0x1884,
+ 0x81b8, 0x1886,
+ 0x81ba, 0x188a,
+ 0x81bd, 0x1887,
+ 0x81be, 0x1885,
+ 0x81bf, 0x0cf5,
+ 0x81c0, 0x1888,
+ 0x81c2, 0x1889,
+ 0x81c6, 0x0532,
+ 0x81c8, 0x1890,
+ 0x81c9, 0x188b,
+ 0x81cd, 0x188c,
+ 0x81d1, 0x188d,
+ 0x81d3, 0x0b01,
+ 0x81d8, 0x188f,
+ 0x81d9, 0x188e,
+ 0x81da, 0x1891,
+ 0x81df, 0x1892,
+ 0x81e3, 0x0a09,
+ 0x81e5, 0x0569,
+ 0x81e7, 0x1894,
+ 0x81e8, 0x0f9f,
+ 0x81ea, 0x08d7,
+ 0x81ed, 0x0937,
+ 0x81f3, 0x08b8,
+ 0x81f4, 0x0b95,
+ 0x81fa, 0x1895,
+ 0x81fc, 0x04d3,
+ 0x81fe, 0x1897,
+ 0x8201, 0x1898,
+ 0x8205, 0x189a,
+ 0x8207, 0x189b,
+ 0x8208, 0x06b5,
+ 0x8209, 0x13af,
+ 0x820a, 0x189c,
+ 0x820c, 0x0a89,
+ 0x820d, 0x189d,
+ 0x820e, 0x08f7,
+ 0x8210, 0x189e,
+ 0x8212, 0x1009,
+ 0x8216, 0x189f,
+ 0x8217, 0x0e2e,
+ 0x8218, 0x0618,
+ 0x821b, 0x0aa6,
+ 0x821c, 0x0962,
+ 0x821e, 0x0de3,
+ 0x821f, 0x0938,
+ 0x8229, 0x18a0,
+ 0x822a, 0x07e4,
+ 0x822b, 0x18a1,
+ 0x822c, 0x0d60,
+ 0x822e, 0x18af,
+ 0x8233, 0x18a3,
+ 0x8235, 0x0b29,
+ 0x8236, 0x0d2b,
+ 0x8237, 0x0773,
+ 0x8238, 0x18a2,
+ 0x8239, 0x0aa7,
+ 0x8240, 0x18a4,
+ 0x8247, 0x0c16,
+ 0x8258, 0x18a6,
+ 0x8259, 0x18a5,
+ 0x825a, 0x18a8,
+ 0x825d, 0x18a7,
+ 0x825f, 0x18a9,
+ 0x8262, 0x18ab,
+ 0x8264, 0x18aa,
+ 0x8266, 0x060b,
+ 0x8268, 0x18ac,
+ 0x826a, 0x18ad,
+ 0x826e, 0x0821,
+ 0x826f, 0x0f91,
+ 0x8271, 0x18b0,
+ 0x8272, 0x09ed,
+ 0x8276, 0x0512,
+ 0x8277, 0x18b1,
+ 0x827e, 0x18b3,
+ 0x828b, 0x04b6,
+ 0x828d, 0x18b4,
+ 0x8292, 0x18b5,
+ 0x8299, 0x0dd9,
+ 0x829d, 0x08f3,
+ 0x829f, 0x18b7,
+ 0x82a5, 0x0587,
+ 0x82a6, 0x0476,
+ 0x82ab, 0x18b6,
+ 0x82ac, 0x18b9,
+ 0x82ad, 0x0d04,
+ 0x82af, 0x0a0a,
+ 0x82b1, 0x0556,
+ 0x82b3, 0x0e55,
+ 0x82b8, 0x0733,
+ 0x82b9, 0x06d4,
+ 0x82bb, 0x18b8,
+ 0x82bd, 0x056a,
+ 0x82c5, 0x05df,
+ 0x82d1, 0x0513,
+ 0x82d2, 0x18bd,
+ 0x82d3, 0x0fb2,
+ 0x82d4, 0x0b3d,
+ 0x82d7, 0x0db6,
+ 0x82d9, 0x18c9,
+ 0x82db, 0x0557,
+ 0x82dc, 0x18c7,
+ 0x82de, 0x18c5,
+ 0x82df, 0x18bc,
+ 0x82e1, 0x18ba,
+ 0x82e3, 0x18bb,
+ 0x82e5, 0x090f,
+ 0x82e6, 0x06e4,
+ 0x82e7, 0x0bb5,
+ 0x82eb, 0x0ca9,
+ 0x82f1, 0x04f3,
+ 0x82f3, 0x18bf,
+ 0x82f4, 0x18be,
+ 0x82f9, 0x18c4,
+ 0x82fa, 0x18c0,
+ 0x82fb, 0x18c3,
+ 0x8301, 0x2198,
+ 0x8302, 0x0edc,
+ 0x8303, 0x18c2,
+ 0x8304, 0x0558,
+ 0x8305, 0x05db,
+ 0x8306, 0x18c6,
+ 0x8309, 0x18c8,
+ 0x830e, 0x072a,
+ 0x8316, 0x18cc,
+ 0x8317, 0x18d5,
+ 0x831c, 0x046f,
+ 0x8323, 0x18dd,
+ 0x8328, 0x04b5,
+ 0x832b, 0x18d4,
+ 0x832f, 0x18d3,
+ 0x8331, 0x18ce,
+ 0x8332, 0x18cd,
+ 0x8334, 0x18cb,
+ 0x8335, 0x18ca,
+ 0x8336, 0x0ba1,
+ 0x8338, 0x0b5b,
+ 0x8339, 0x18d0,
+ 0x8340, 0x18cf,
+ 0x8345, 0x18d2,
+ 0x8349, 0x0af2,
+ 0x834a, 0x072b,
+ 0x834f, 0x04e3,
+ 0x8350, 0x18d1,
+ 0x8352, 0x07e5,
+ 0x8358, 0x0af3,
+ 0x8362, 0x2199,
+ 0x8373, 0x18e3,
+ 0x8375, 0x18e4,
+ 0x8377, 0x0559,
+ 0x837b, 0x052e,
+ 0x837c, 0x18e1,
+ 0x837f, 0x219a,
+ 0x8385, 0x18d7,
+ 0x8387, 0x18df,
+ 0x8389, 0x18e6,
+ 0x838a, 0x18e0,
+ 0x838e, 0x18de,
+ 0x8393, 0x18c1,
+ 0x8396, 0x18dc,
+ 0x839a, 0x18d8,
+ 0x839e, 0x060c,
+ 0x839f, 0x18da,
+ 0x83a0, 0x18e5,
+ 0x83a2, 0x18db,
+ 0x83a8, 0x18e7,
+ 0x83aa, 0x18d9,
+ 0x83ab, 0x0d32,
+ 0x83b1, 0x0f53,
+ 0x83b5, 0x18e2,
+ 0x83bd, 0x18f8,
+ 0x83c1, 0x18f0,
+ 0x83c5, 0x0a41,
+ 0x83c7, 0x219b,
+ 0x83ca, 0x0660,
+ 0x83cc, 0x06d5,
+ 0x83ce, 0x18eb,
+ 0x83d3, 0x055b,
+ 0x83d6, 0x09bc,
+ 0x83d8, 0x18ee,
+ 0x83dc, 0x084a,
+ 0x83df, 0x0c4b,
+ 0x83e0, 0x18f3,
+ 0x83e9, 0x0e3e,
+ 0x83eb, 0x18ea,
+ 0x83ef, 0x055a,
+ 0x83f0, 0x078a,
+ 0x83f1, 0x0d9b,
+ 0x83f2, 0x18f4,
+ 0x83f4, 0x18e8,
+ 0x83f6, 0x219c,
+ 0x83f7, 0x18f1,
+ 0x83fb, 0x18fb,
+ 0x83fd, 0x18ec,
+ 0x8403, 0x18ed,
+ 0x8404, 0x0c92,
+ 0x8407, 0x18f2,
+ 0x840a, 0x1e7f,
+ 0x840b, 0x18ef,
+ 0x840c, 0x0e56,
+ 0x840d, 0x18f5,
+ 0x840e, 0x04a4,
+ 0x8413, 0x18e9,
+ 0x8420, 0x18f7,
+ 0x8422, 0x18f6,
+ 0x8429, 0x0d21,
+ 0x842a, 0x18fd,
+ 0x842c, 0x1908,
+ 0x8431, 0x05dc,
+ 0x8435, 0x190b,
+ 0x8438, 0x18f9,
+ 0x843c, 0x18fe,
+ 0x843d, 0x0f58,
+ 0x8446, 0x1907,
+ 0x8448, 0x219d,
+ 0x8449, 0x0f3f,
+ 0x844e, 0x0f72,
+ 0x8457, 0x0bb6,
+ 0x845b, 0x05c9,
+ 0x8461, 0x0de4,
+ 0x8462, 0x190d,
+ 0x8463, 0x0c79,
+ 0x8466, 0x0475,
+ 0x8469, 0x1906,
+ 0x846b, 0x1902,
+ 0x846c, 0x0af4,
+ 0x846d, 0x18fc,
+ 0x846e, 0x1904,
+ 0x846f, 0x1909,
+ 0x8471, 0x0ce2,
+ 0x8475, 0x046e,
+ 0x8477, 0x1901,
+ 0x8479, 0x190a,
+ 0x847a, 0x0dea,
+ 0x8482, 0x1905,
+ 0x8484, 0x1900,
+ 0x848b, 0x09bd,
+ 0x8490, 0x0939,
+ 0x8494, 0x08d8,
+ 0x8499, 0x0ee4,
+ 0x849c, 0x0db9,
+ 0x849f, 0x1910,
+ 0x84a1, 0x1919,
+ 0x84ad, 0x1903,
+ 0x84b2, 0x05d5,
+ 0x84b4, 0x219e,
+ 0x84b8, 0x09e0,
+ 0x84b9, 0x190e,
+ 0x84bb, 0x1913,
+ 0x84bc, 0x0af5,
+ 0x84bf, 0x190f,
+ 0x84c1, 0x1916,
+ 0x84c4, 0x0b9d,
+ 0x84c6, 0x1917,
+ 0x84c9, 0x0f40,
+ 0x84ca, 0x190c,
+ 0x84cb, 0x0596,
+ 0x84cd, 0x1912,
+ 0x84d0, 0x1915,
+ 0x84d1, 0x0eb8,
+ 0x84d6, 0x1918,
+ 0x84d9, 0x1911,
+ 0x84da, 0x1914,
+ 0x84dc, 0x20ab,
+ 0x84ec, 0x0e57,
+ 0x84ee, 0x0fc7,
+ 0x84f4, 0x191c,
+ 0x84fc, 0x1923,
+ 0x84ff, 0x191b,
+ 0x8500, 0x08ef,
+ 0x8506, 0x18fa,
+ 0x8511, 0x0e1e,
+ 0x8513, 0x0eae,
+ 0x8514, 0x1922,
+ 0x8515, 0x1921,
+ 0x8517, 0x191d,
+ 0x851a, 0x04d8,
+ 0x851f, 0x1920,
+ 0x8521, 0x191a,
+ 0x8523, 0x1e1a,
+ 0x8526, 0x0bf1,
+ 0x852c, 0x191f,
+ 0x852d, 0x04c2,
+ 0x8535, 0x0b02,
+ 0x853d, 0x0e13,
+ 0x853e, 0x1eb5,
+ 0x8540, 0x1924,
+ 0x8541, 0x1928,
+ 0x8543, 0x0d6d,
+ 0x8548, 0x1927,
+ 0x8549, 0x09be,
+ 0x854a, 0x08f5,
+ 0x854b, 0x192a,
+ 0x854e, 0x06b6,
+ 0x8553, 0x219f,
+ 0x8555, 0x192b,
+ 0x8557, 0x0deb,
+ 0x8558, 0x1926,
+ 0x8559, 0x21a0,
+ 0x855a, 0x18ff,
+ 0x8563, 0x1925,
+ 0x8568, 0x0ff5,
+ 0x8569, 0x0c7a,
+ 0x856a, 0x0de5,
+ 0x856b, 0x21a1,
+ 0x856d, 0x1932,
+ 0x8577, 0x1938,
+ 0x857e, 0x1939,
+ 0x8580, 0x192c,
+ 0x8584, 0x0d2c,
+ 0x8587, 0x1936,
+ 0x8588, 0x192e,
+ 0x858a, 0x1930,
+ 0x8590, 0x193a,
+ 0x8591, 0x192f,
+ 0x8594, 0x1933,
+ 0x8597, 0x0514,
+ 0x8599, 0x0cbd,
+ 0x859b, 0x1934,
+ 0x859c, 0x1937,
+ 0x85a4, 0x192d,
+ 0x85a6, 0x0aa8,
+ 0x85a8, 0x1931,
+ 0x85a9, 0x0875,
+ 0x85aa, 0x0a0b,
+ 0x85ab, 0x0706,
+ 0x85ac, 0x0f00,
+ 0x85ae, 0x0f05,
+ 0x85af, 0x097c,
+ 0x85b0, 0x21a3,
+ 0x85b9, 0x193e,
+ 0x85ba, 0x193c,
+ 0x85c1, 0x0ff4,
+ 0x85c9, 0x193b,
+ 0x85cd, 0x0f5f,
+ 0x85cf, 0x193d,
+ 0x85d0, 0x193f,
+ 0x85d5, 0x1940,
+ 0x85dc, 0x1943,
+ 0x85dd, 0x1941,
+ 0x85e4, 0x0c7b,
+ 0x85e5, 0x1942,
+ 0x85e9, 0x0d61,
+ 0x85ea, 0x1935,
+ 0x85f7, 0x097d,
+ 0x85f9, 0x1944,
+ 0x85fa, 0x1949,
+ 0x85fb, 0x0af6,
+ 0x85fe, 0x1948,
+ 0x8602, 0x1929,
+ 0x8606, 0x194a,
+ 0x8607, 0x0acb,
+ 0x860a, 0x1945,
+ 0x860b, 0x1947,
+ 0x8613, 0x1946,
+ 0x8616, 0x14d0,
+ 0x8617, 0x14c1,
+ 0x861a, 0x194c,
+ 0x8622, 0x194b,
+ 0x862d, 0x0f60,
+ 0x862f, 0x16b1,
+ 0x8630, 0x194d,
+ 0x863f, 0x194e,
+ 0x864d, 0x194f,
+ 0x864e, 0x078b,
+ 0x8650, 0x066e,
+ 0x8654, 0x1951,
+ 0x8655, 0x1094,
+ 0x865a, 0x068f,
+ 0x865c, 0x0f82,
+ 0x865e, 0x06eb,
+ 0x865f, 0x1952,
+ 0x8667, 0x1953,
+ 0x866b, 0x0bac,
+ 0x8671, 0x1954,
+ 0x8679, 0x0cd2,
+ 0x867b, 0x047e,
+ 0x868a, 0x0563,
+ 0x868b, 0x1959,
+ 0x8693, 0x1955,
+ 0x8695, 0x088b,
+ 0x86a3, 0x1956,
+ 0x86a4, 0x0cf8,
+ 0x86a9, 0x1957,
+ 0x86ab, 0x1962,
+ 0x86af, 0x195c,
+ 0x86b0, 0x195f,
+ 0x86b6, 0x195b,
+ 0x86c4, 0x195d,
+ 0x86c6, 0x195e,
+ 0x86c7, 0x0904,
+ 0x86c9, 0x1960,
+ 0x86cb, 0x0b7f,
+ 0x86cd, 0x072c,
+ 0x86ce, 0x05a0,
+ 0x86d4, 0x1963,
+ 0x86d9, 0x059d,
+ 0x86db, 0x1968,
+ 0x86de, 0x1964,
+ 0x86df, 0x1967,
+ 0x86e4, 0x0d4e,
+ 0x86e9, 0x1965,
+ 0x86ec, 0x1966,
+ 0x86ed, 0x0dba,
+ 0x86ee, 0x0d6e,
+ 0x86ef, 0x1969,
+ 0x86f8, 0x0b5d,
+ 0x86f9, 0x1973,
+ 0x86fb, 0x196f,
+ 0x86fe, 0x056b,
+ 0x8700, 0x196d,
+ 0x8702, 0x0e58,
+ 0x8703, 0x196e,
+ 0x8706, 0x196b,
+ 0x8708, 0x196c,
+ 0x8709, 0x1971,
+ 0x870a, 0x1974,
+ 0x870d, 0x1972,
+ 0x8711, 0x1970,
+ 0x8712, 0x196a,
+ 0x8718, 0x0b96,
+ 0x871a, 0x197b,
+ 0x871c, 0x0eb6,
+ 0x8725, 0x1979,
+ 0x8729, 0x197a,
+ 0x8734, 0x1975,
+ 0x8737, 0x1977,
+ 0x873b, 0x1978,
+ 0x873f, 0x1976,
+ 0x8749, 0x0a8a,
+ 0x874b, 0x0fdf,
+ 0x874c, 0x197f,
+ 0x874e, 0x1980,
+ 0x8753, 0x1986,
+ 0x8755, 0x09f0,
+ 0x8757, 0x1982,
+ 0x8759, 0x1985,
+ 0x875f, 0x197d,
+ 0x8760, 0x197c,
+ 0x8763, 0x1987,
+ 0x8766, 0x055c,
+ 0x8768, 0x1983,
+ 0x876a, 0x1988,
+ 0x876e, 0x1984,
+ 0x8774, 0x1981,
+ 0x8776, 0x0bcf,
+ 0x8778, 0x197e,
+ 0x877f, 0x0d1e,
+ 0x8782, 0x198c,
+ 0x878d, 0x0f25,
+ 0x879f, 0x198b,
+ 0x87a2, 0x198a,
+ 0x87ab, 0x1993,
+ 0x87af, 0x198d,
+ 0x87b3, 0x1995,
+ 0x87ba, 0x0f50,
+ 0x87bb, 0x1998,
+ 0x87bd, 0x198f,
+ 0x87c0, 0x1990,
+ 0x87c4, 0x1994,
+ 0x87c6, 0x1997,
+ 0x87c7, 0x1996,
+ 0x87cb, 0x198e,
+ 0x87d0, 0x1991,
+ 0x87d2, 0x19a2,
+ 0x87e0, 0x199b,
+ 0x87ec, 0x1e23,
+ 0x87ef, 0x1999,
+ 0x87f2, 0x199a,
+ 0x87f6, 0x199f,
+ 0x87f9, 0x0588,
+ 0x87fb, 0x065c,
+ 0x87fe, 0x199e,
+ 0x8805, 0x1989,
+ 0x8807, 0x21a6,
+ 0x880d, 0x199d,
+ 0x880e, 0x19a1,
+ 0x880f, 0x199c,
+ 0x8811, 0x19a3,
+ 0x8815, 0x19a5,
+ 0x8816, 0x19a4,
+ 0x881f, 0x1e85,
+ 0x8821, 0x19a7,
+ 0x8822, 0x19a6,
+ 0x8823, 0x1961,
+ 0x8827, 0x19ab,
+ 0x8831, 0x19a8,
+ 0x8836, 0x19a9,
+ 0x8839, 0x19aa,
+ 0x883b, 0x19ac,
+ 0x8840, 0x0742,
+ 0x8842, 0x19ae,
+ 0x8844, 0x19ad,
+ 0x8846, 0x093a,
+ 0x884c, 0x07e6,
+ 0x884d, 0x1524,
+ 0x8852, 0x19af,
+ 0x8853, 0x095b,
+ 0x8857, 0x0597,
+ 0x8859, 0x19b0,
+ 0x885b, 0x04f4,
+ 0x885d, 0x09bf,
+ 0x885e, 0x19b1,
+ 0x8861, 0x07e7,
+ 0x8862, 0x19b2,
+ 0x8863, 0x04a5,
+ 0x8868, 0x0daf,
+ 0x886b, 0x19b3,
+ 0x8870, 0x0a30,
+ 0x8872, 0x19ba,
+ 0x8875, 0x19b7,
+ 0x8877, 0x0bad,
+ 0x887d, 0x19b8,
+ 0x887e, 0x19b5,
+ 0x887f, 0x06d6,
+ 0x8881, 0x19b4,
+ 0x8882, 0x19bb,
+ 0x8888, 0x070c,
+ 0x888b, 0x0b3e,
+ 0x888d, 0x19c1,
+ 0x8892, 0x19bd,
+ 0x8896, 0x0b15,
+ 0x8897, 0x19bc,
+ 0x8899, 0x19bf,
+ 0x889e, 0x19b6,
+ 0x88a2, 0x19c0,
+ 0x88a4, 0x19c2,
+ 0x88ab, 0x0d83,
+ 0x88ae, 0x19be,
+ 0x88b0, 0x19c3,
+ 0x88b1, 0x19c5,
+ 0x88b4, 0x0787,
+ 0x88b5, 0x19b9,
+ 0x88b7, 0x0485,
+ 0x88bf, 0x19c4,
+ 0x88c1, 0x084b,
+ 0x88c2, 0x0fbe,
+ 0x88c3, 0x19c6,
+ 0x88c5, 0x0af7,
+ 0x88cf, 0x0f6a,
+ 0x88d4, 0x19c8,
+ 0x88d5, 0x0f1f,
+ 0x88d8, 0x19c9,
+ 0x88dc, 0x0e34,
+ 0x88dd, 0x19cb,
+ 0x88df, 0x0830,
+ 0x88e1, 0x0f6b,
+ 0x88e8, 0x19d0,
+ 0x88f2, 0x19d1,
+ 0x88f3, 0x09c0,
+ 0x88f4, 0x19cf,
+ 0x88f5, 0x21a7,
+ 0x88f8, 0x0f51,
+ 0x88f9, 0x19cc,
+ 0x88fc, 0x19ce,
+ 0x88fd, 0x0a61,
+ 0x88fe, 0x0a44,
+ 0x8902, 0x19cd,
+ 0x8904, 0x19d2,
+ 0x8907, 0x0df3,
+ 0x890a, 0x19d4,
+ 0x890c, 0x19d3,
+ 0x8910, 0x05ca,
+ 0x8912, 0x0e59,
+ 0x8913, 0x19d5,
+ 0x891c, 0x20a8,
+ 0x891d, 0x19e1,
+ 0x891e, 0x19d7,
+ 0x8925, 0x19d8,
+ 0x892a, 0x19d9,
+ 0x8936, 0x19de,
+ 0x8938, 0x19df,
+ 0x893b, 0x19dd,
+ 0x8941, 0x19db,
+ 0x8943, 0x19d6,
+ 0x8944, 0x19dc,
+ 0x894c, 0x19e0,
+ 0x894d, 0x1bd0,
+ 0x8956, 0x0528,
+ 0x895e, 0x19e3,
+ 0x895f, 0x06d7,
+ 0x8960, 0x19e2,
+ 0x8964, 0x19e5,
+ 0x8966, 0x19e4,
+ 0x896a, 0x19e7,
+ 0x896d, 0x19e6,
+ 0x896f, 0x19e8,
+ 0x8972, 0x093b,
+ 0x8974, 0x19e9,
+ 0x8977, 0x19ea,
+ 0x897e, 0x19eb,
+ 0x897f, 0x0a62,
+ 0x8981, 0x0f41,
+ 0x8983, 0x19ec,
+ 0x8986, 0x0df4,
+ 0x8987, 0x0cfc,
+ 0x8988, 0x19ed,
+ 0x898a, 0x19ee,
+ 0x898b, 0x075f,
+ 0x898f, 0x0646,
+ 0x8993, 0x19ef,
+ 0x8996, 0x08b9,
+ 0x8997, 0x0cf7,
+ 0x8998, 0x19f0,
+ 0x899a, 0x05ae,
+ 0x89a1, 0x19f1,
+ 0x89a6, 0x19f3,
+ 0x89a7, 0x0f61,
+ 0x89a9, 0x19f2,
+ 0x89aa, 0x0a0c,
+ 0x89ac, 0x19f4,
+ 0x89af, 0x19f5,
+ 0x89b2, 0x19f6,
+ 0x89b3, 0x060d,
+ 0x89ba, 0x19f7,
+ 0x89bd, 0x19f8,
+ 0x89bf, 0x19f9,
+ 0x89d2, 0x05af,
+ 0x89da, 0x19fb,
+ 0x89dc, 0x19fc,
+ 0x89e3, 0x0572,
+ 0x89e6, 0x09ee,
+ 0x89e7, 0x19fe,
+ 0x89f4, 0x19ff,
+ 0x89f8, 0x1a00,
+ 0x8a00, 0x0774,
+ 0x8a02, 0x0c17,
+ 0x8a03, 0x1a01,
+ 0x8a08, 0x072d,
+ 0x8a0a, 0x0a1c,
+ 0x8a0c, 0x1a04,
+ 0x8a0e, 0x0c7c,
+ 0x8a10, 0x1a03,
+ 0x8a12, 0x21a8,
+ 0x8a13, 0x0707,
+ 0x8a16, 0x1a02,
+ 0x8a17, 0x0b57,
+ 0x8a18, 0x0647,
+ 0x8a1b, 0x1a05,
+ 0x8a1d, 0x1a06,
+ 0x8a1f, 0x09c1,
+ 0x8a23, 0x0743,
+ 0x8a25, 0x1a07,
+ 0x8a2a, 0x0e5a,
+ 0x8a2d, 0x0a83,
+ 0x8a31, 0x0690,
+ 0x8a33, 0x0f01,
+ 0x8a34, 0x0acc,
+ 0x8a36, 0x1a08,
+ 0x8a37, 0x21a9,
+ 0x8a3a, 0x0a0d,
+ 0x8a3b, 0x0bae,
+ 0x8a3c, 0x09c2,
+ 0x8a41, 0x1a09,
+ 0x8a46, 0x1a0c,
+ 0x8a48, 0x1a0d,
+ 0x8a50, 0x082e,
+ 0x8a51, 0x0b22,
+ 0x8a52, 0x1a0b,
+ 0x8a54, 0x09c3,
+ 0x8a55, 0x0db0,
+ 0x8a5b, 0x1a0a,
+ 0x8a5e, 0x08ba,
+ 0x8a60, 0x04f5,
+ 0x8a62, 0x1a11,
+ 0x8a63, 0x072e,
+ 0x8a66, 0x08bc,
+ 0x8a69, 0x08bb,
+ 0x8a6b, 0x0ff3,
+ 0x8a6c, 0x1a10,
+ 0x8a6d, 0x1a0f,
+ 0x8a6e, 0x0aa9,
+ 0x8a70, 0x0667,
+ 0x8a71, 0x0fe9,
+ 0x8a72, 0x0598,
+ 0x8a73, 0x09c4,
+ 0x8a79, 0x21aa,
+ 0x8a7c, 0x1a0e,
+ 0x8a82, 0x1a13,
+ 0x8a84, 0x1a14,
+ 0x8a85, 0x1a12,
+ 0x8a87, 0x078c,
+ 0x8a89, 0x0f2a,
+ 0x8a8c, 0x08bd,
+ 0x8a8d, 0x0cdd,
+ 0x8a91, 0x1a17,
+ 0x8a93, 0x0a64,
+ 0x8a95, 0x0b80,
+ 0x8a98, 0x0f20,
+ 0x8a9a, 0x1a1a,
+ 0x8a9e, 0x07a0,
+ 0x8aa0, 0x0a63,
+ 0x8aa1, 0x1a16,
+ 0x8aa3, 0x1a1b,
+ 0x8aa4, 0x07a1,
+ 0x8aa5, 0x1a18,
+ 0x8aa7, 0x21ab,
+ 0x8aa8, 0x1a15,
+ 0x8aac, 0x0a86,
+ 0x8aad, 0x0ca1,
+ 0x8ab0, 0x0b6d,
+ 0x8ab2, 0x055d,
+ 0x8ab9, 0x0d84,
+ 0x8abc, 0x065d,
+ 0x8abe, 0x21ac,
+ 0x8abf, 0x0bd0,
+ 0x8ac2, 0x1a1e,
+ 0x8ac4, 0x1a1c,
+ 0x8ac7, 0x0b8a,
+ 0x8acb, 0x0a65,
+ 0x8acc, 0x060e,
+ 0x8acd, 0x1a1d,
+ 0x8acf, 0x0a21,
+ 0x8ad2, 0x0f92,
+ 0x8ad6, 0x0fe6,
+ 0x8ada, 0x1a1f,
+ 0x8adb, 0x1a2a,
+ 0x8adc, 0x0bd1,
+ 0x8ade, 0x1a29,
+ 0x8adf, 0x21ad,
+ 0x8ae0, 0x1a26,
+ 0x8ae1, 0x1a2e,
+ 0x8ae2, 0x1a27,
+ 0x8ae4, 0x1a23,
+ 0x8ae6, 0x0c18,
+ 0x8ae7, 0x1a22,
+ 0x8aeb, 0x1a20,
+ 0x8aed, 0x0f0b,
+ 0x8aee, 0x08be,
+ 0x8af1, 0x1a24,
+ 0x8af3, 0x1a21,
+ 0x8af6, 0x21af,
+ 0x8af7, 0x1a28,
+ 0x8af8, 0x097e,
+ 0x8afa, 0x0775,
+ 0x8afe, 0x0b5a,
+ 0x8b00, 0x0e73,
+ 0x8b01, 0x04fc,
+ 0x8b02, 0x04a6,
+ 0x8b04, 0x0c7d,
+ 0x8b07, 0x1a2c,
+ 0x8b0c, 0x1a2b,
+ 0x8b0e, 0x0cbe,
+ 0x8b10, 0x1a30,
+ 0x8b14, 0x1a25,
+ 0x8b16, 0x1a2f,
+ 0x8b17, 0x1a31,
+ 0x8b19, 0x0760,
+ 0x8b1a, 0x1a2d,
+ 0x8b1b, 0x07e8,
+ 0x8b1d, 0x0901,
+ 0x8b20, 0x1a32,
+ 0x8b21, 0x0f42,
+ 0x8b26, 0x1a35,
+ 0x8b28, 0x1a38,
+ 0x8b2b, 0x1a36,
+ 0x8b2c, 0x0da7,
+ 0x8b33, 0x1a33,
+ 0x8b39, 0x06d8,
+ 0x8b3e, 0x1a37,
+ 0x8b41, 0x1a39,
+ 0x8b49, 0x1a3d,
+ 0x8b4c, 0x1a3a,
+ 0x8b4e, 0x1a3c,
+ 0x8b4f, 0x1a3b,
+ 0x8b53, 0x21b0,
+ 0x8b56, 0x1a3e,
+ 0x8b58, 0x08dd,
+ 0x8b5a, 0x1a40,
+ 0x8b5b, 0x1a3f,
+ 0x8b5c, 0x0dda,
+ 0x8b5f, 0x1a42,
+ 0x8b66, 0x072f,
+ 0x8b6b, 0x1a41,
+ 0x8b6c, 0x1a43,
+ 0x8b6f, 0x1a44,
+ 0x8b70, 0x065e,
+ 0x8b71, 0x182e,
+ 0x8b72, 0x09e1,
+ 0x8b74, 0x1a45,
+ 0x8b77, 0x07a2,
+ 0x8b7d, 0x1a46,
+ 0x8b7f, 0x21b1,
+ 0x8b80, 0x1a47,
+ 0x8b83, 0x088c,
+ 0x8b8a, 0x13d3,
+ 0x8b8c, 0x1a48,
+ 0x8b8e, 0x1a49,
+ 0x8b90, 0x093c,
+ 0x8b92, 0x1a4a,
+ 0x8b96, 0x1a4c,
+ 0x8b99, 0x1a4d,
+ 0x8c37, 0x0b69,
+ 0x8c3a, 0x1a4f,
+ 0x8c3f, 0x1a51,
+ 0x8c41, 0x1a50,
+ 0x8c46, 0x0c7e,
+ 0x8c48, 0x1a52,
+ 0x8c4a, 0x0e5b,
+ 0x8c4c, 0x1a53,
+ 0x8c4e, 0x1a54,
+ 0x8c50, 0x1a55,
+ 0x8c55, 0x1a56,
+ 0x8c5a, 0x0cb2,
+ 0x8c61, 0x09c5,
+ 0x8c62, 0x1a57,
+ 0x8c6a, 0x07fd,
+ 0x8c6b, 0x1007,
+ 0x8c6c, 0x1a58,
+ 0x8c78, 0x1a59,
+ 0x8c79, 0x0db1,
+ 0x8c7a, 0x1a5a,
+ 0x8c7c, 0x1a62,
+ 0x8c82, 0x1a5b,
+ 0x8c85, 0x1a5d,
+ 0x8c89, 0x1a5c,
+ 0x8c8a, 0x1a5e,
+ 0x8c8c, 0x0e74,
+ 0x8c8d, 0x1a5f,
+ 0x8c94, 0x1a61,
+ 0x8c98, 0x1a63,
+ 0x8c9d, 0x058b,
+ 0x8c9e, 0x0c03,
+ 0x8ca0, 0x0ddb,
+ 0x8ca1, 0x0852,
+ 0x8ca2, 0x07e9,
+ 0x8ca7, 0x0dc1,
+ 0x8ca8, 0x055f,
+ 0x8ca9, 0x0d62,
+ 0x8caa, 0x1a66,
+ 0x8cab, 0x060f,
+ 0x8cac, 0x0a79,
+ 0x8cad, 0x1a65,
+ 0x8cae, 0x1a6a,
+ 0x8caf, 0x0bb7,
+ 0x8cb0, 0x0eef,
+ 0x8cb2, 0x1a68,
+ 0x8cb4, 0x0648,
+ 0x8cb6, 0x1a6b,
+ 0x8cb7, 0x0d19,
+ 0x8cb8, 0x0b3f,
+ 0x8cbb, 0x0d85,
+ 0x8cbc, 0x0c37,
+ 0x8cbd, 0x1a67,
+ 0x8cbf, 0x0e75,
+ 0x8cc0, 0x056c,
+ 0x8cc1, 0x1a6d,
+ 0x8cc2, 0x0fce,
+ 0x8cc3, 0x0bde,
+ 0x8cc4, 0x0feb,
+ 0x8cc7, 0x08bf,
+ 0x8cc8, 0x1a6c,
+ 0x8cca, 0x0b11,
+ 0x8ccd, 0x1a7d,
+ 0x8cce, 0x0aaa,
+ 0x8cd1, 0x0cd0,
+ 0x8cd3, 0x0dc2,
+ 0x8cda, 0x1a70,
+ 0x8cdb, 0x088d,
+ 0x8cdc, 0x08c0,
+ 0x8cde, 0x09c6,
+ 0x8ce0, 0x0d1b,
+ 0x8ce2, 0x0761,
+ 0x8ce3, 0x1a6f,
+ 0x8ce4, 0x1a6e,
+ 0x8ce6, 0x0ddc,
+ 0x8cea, 0x08ed,
+ 0x8ced, 0x0c4c,
+ 0x8cf0, 0x21b2,
+ 0x8cf4, 0x21b3,
+ 0x8cfa, 0x1a72,
+ 0x8cfc, 0x07ea,
+ 0x8cfd, 0x1a71,
+ 0x8d04, 0x1a74,
+ 0x8d07, 0x1a77,
+ 0x8d08, 0x0b03,
+ 0x8d0a, 0x1a76,
+ 0x8d0b, 0x0622,
+ 0x8d0d, 0x1a79,
+ 0x8d0f, 0x1a78,
+ 0x8d10, 0x1a7a,
+ 0x8d12, 0x21b4,
+ 0x8d13, 0x1a7c,
+ 0x8d14, 0x1a7e,
+ 0x8d16, 0x1a7f,
+ 0x8d64, 0x0a7a,
+ 0x8d66, 0x08fb,
+ 0x8d67, 0x1a80,
+ 0x8d6b, 0x05b0,
+ 0x8d6d, 0x1a81,
+ 0x8d70, 0x0af8,
+ 0x8d71, 0x1a82,
+ 0x8d73, 0x1a83,
+ 0x8d74, 0x0ddd,
+ 0x8d76, 0x21b5,
+ 0x8d77, 0x0649,
+ 0x8d81, 0x1a84,
+ 0x8d85, 0x0bd2,
+ 0x8d8a, 0x04fd,
+ 0x8d99, 0x1a85,
+ 0x8da3, 0x091d,
+ 0x8da8, 0x0a3c,
+ 0x8db3, 0x0b0d,
+ 0x8dba, 0x1a88,
+ 0x8dbe, 0x1a87,
+ 0x8dc2, 0x1a86,
+ 0x8dcb, 0x1a8e,
+ 0x8dcc, 0x1a8c,
+ 0x8dcf, 0x1a89,
+ 0x8dd6, 0x1a8b,
+ 0x8dda, 0x1a8a,
+ 0x8ddb, 0x1a8d,
+ 0x8ddd, 0x0691,
+ 0x8ddf, 0x1a91,
+ 0x8de1, 0x0a7b,
+ 0x8de3, 0x1a92,
+ 0x8de8, 0x078d,
+ 0x8dea, 0x1a8f,
+ 0x8def, 0x0fcf,
+ 0x8df3, 0x0bd3,
+ 0x8df5, 0x0aab,
+ 0x8dfc, 0x1a93,
+ 0x8dff, 0x1a96,
+ 0x8e08, 0x1a94,
+ 0x8e0a, 0x0f43,
+ 0x8e0f, 0x0c7f,
+ 0x8e10, 0x1a99,
+ 0x8e1d, 0x1a97,
+ 0x8e1f, 0x1a9a,
+ 0x8e2a, 0x1aa8,
+ 0x8e30, 0x1a9d,
+ 0x8e34, 0x1a9e,
+ 0x8e35, 0x1a9c,
+ 0x8e42, 0x1a9b,
+ 0x8e44, 0x0c19,
+ 0x8e47, 0x1aa0,
+ 0x8e48, 0x1aa4,
+ 0x8e49, 0x1aa1,
+ 0x8e4a, 0x1a9f,
+ 0x8e4c, 0x1aa2,
+ 0x8e50, 0x1aa3,
+ 0x8e55, 0x1aaa,
+ 0x8e59, 0x1aa5,
+ 0x8e5f, 0x0a7c,
+ 0x8e60, 0x1aa7,
+ 0x8e63, 0x1aa9,
+ 0x8e64, 0x1aa6,
+ 0x8e72, 0x1aac,
+ 0x8e74, 0x093d,
+ 0x8e76, 0x1aab,
+ 0x8e7c, 0x1aad,
+ 0x8e81, 0x1aae,
+ 0x8e84, 0x1ab1,
+ 0x8e85, 0x1ab0,
+ 0x8e87, 0x1aaf,
+ 0x8e8a, 0x1ab3,
+ 0x8e8b, 0x1ab2,
+ 0x8e8d, 0x0f02,
+ 0x8e91, 0x1ab5,
+ 0x8e93, 0x1ab4,
+ 0x8e94, 0x1ab6,
+ 0x8e99, 0x1ab7,
+ 0x8ea1, 0x1ab9,
+ 0x8eaa, 0x1ab8,
+ 0x8eab, 0x0a0e,
+ 0x8eac, 0x1aba,
+ 0x8eaf, 0x06e5,
+ 0x8eb0, 0x1abb,
+ 0x8eb1, 0x1abd,
+ 0x8ebe, 0x1abe,
+ 0x8ec0, 0x1def,
+ 0x8ec5, 0x1abf,
+ 0x8ec6, 0x1abc,
+ 0x8ec8, 0x1ac0,
+ 0x8eca, 0x0902,
+ 0x8ecb, 0x1ac1,
+ 0x8ecc, 0x064a,
+ 0x8ecd, 0x0709,
+ 0x8ecf, 0x21b7,
+ 0x8ed2, 0x0762,
+ 0x8edb, 0x1ac2,
+ 0x8edf, 0x0cc8,
+ 0x8ee2, 0x0c38,
+ 0x8ee3, 0x1ac3,
+ 0x8eeb, 0x1ac6,
+ 0x8ef8, 0x08e0,
+ 0x8efb, 0x1ac5,
+ 0x8efc, 0x1ac4,
+ 0x8efd, 0x0730,
+ 0x8efe, 0x1ac7,
+ 0x8f03, 0x05b1,
+ 0x8f05, 0x1ac9,
+ 0x8f09, 0x084c,
+ 0x8f0a, 0x1ac8,
+ 0x8f0c, 0x1ad1,
+ 0x8f12, 0x1acb,
+ 0x8f13, 0x1acd,
+ 0x8f14, 0x0e35,
+ 0x8f15, 0x1aca,
+ 0x8f19, 0x1acc,
+ 0x8f1b, 0x1ad0,
+ 0x8f1c, 0x1ace,
+ 0x8f1d, 0x064b,
+ 0x8f1f, 0x1acf,
+ 0x8f26, 0x1ad2,
+ 0x8f29, 0x0d10,
+ 0x8f2a, 0x0fa0,
+ 0x8f2f, 0x093e,
+ 0x8f33, 0x1ad3,
+ 0x8f38, 0x0f0c,
+ 0x8f39, 0x1ad5,
+ 0x8f3b, 0x1ad4,
+ 0x8f3e, 0x1ad8,
+ 0x8f3f, 0x0f2b,
+ 0x8f42, 0x1ad7,
+ 0x8f44, 0x05cb,
+ 0x8f45, 0x1ad6,
+ 0x8f46, 0x1adb,
+ 0x8f49, 0x1ada,
+ 0x8f4c, 0x1ad9,
+ 0x8f4d, 0x0c2c,
+ 0x8f4e, 0x1adc,
+ 0x8f57, 0x1add,
+ 0x8f5c, 0x1ade,
+ 0x8f5f, 0x07fe,
+ 0x8f61, 0x06fb,
+ 0x8f62, 0x1adf,
+ 0x8f9b, 0x0a0f,
+ 0x8f9c, 0x1ae2,
+ 0x8f9e, 0x08d9,
+ 0x8f9f, 0x1ae3,
+ 0x8fa3, 0x1ae4,
+ 0x8fa7, 0x10b6,
+ 0x8fa8, 0x10b5,
+ 0x8fad, 0x1ae5,
+ 0x8fae, 0x17ff,
+ 0x8faf, 0x1ae6,
+ 0x8fb0, 0x0b62,
+ 0x8fb1, 0x09f1,
+ 0x8fb2, 0x0cf6,
+ 0x8fb7, 0x1ae7,
+ 0x8fba, 0x0e25,
+ 0x8fbb, 0x0bf0,
+ 0x8fbc, 0x0810,
+ 0x8fbf, 0x0b67,
+ 0x8fc2, 0x04cc,
+ 0x8fc4, 0x0ea6,
+ 0x8fc5, 0x0a1d,
+ 0x8fce, 0x0734,
+ 0x8fd1, 0x06d9,
+ 0x8fd4, 0x0e26,
+ 0x8fda, 0x1ae8,
+ 0x8fe2, 0x1aea,
+ 0x8fe5, 0x1ae9,
+ 0x8fe6, 0x0560,
+ 0x8fe9, 0x0cce,
+ 0x8fea, 0x1aeb,
+ 0x8feb, 0x0d2d,
+ 0x8fed, 0x0c2d,
+ 0x8fef, 0x1aec,
+ 0x8ff0, 0x095c,
+ 0x8ff4, 0x1aee,
+ 0x8ff7, 0x0ece,
+ 0x8ff8, 0x1afd,
+ 0x8ff9, 0x1af0,
+ 0x8ffd, 0x0be5,
+ 0x9000, 0x0b40,
+ 0x9001, 0x0af9,
+ 0x9003, 0x0c80,
+ 0x9005, 0x1aef,
+ 0x9006, 0x066f,
+ 0x900b, 0x1af8,
+ 0x900d, 0x1af5,
+ 0x900e, 0x1b02,
+ 0x900f, 0x0c81,
+ 0x9010, 0x0b9e,
+ 0x9011, 0x1af2,
+ 0x9013, 0x0c1a,
+ 0x9014, 0x0c4d,
+ 0x9015, 0x1af3,
+ 0x9016, 0x1af7,
+ 0x9017, 0x0a26,
+ 0x9019, 0x0d1d,
+ 0x901a, 0x0be8,
+ 0x901d, 0x0a66,
+ 0x901e, 0x1af6,
+ 0x901f, 0x0b0e,
+ 0x9020, 0x0b04,
+ 0x9021, 0x1af4,
+ 0x9022, 0x046d,
+ 0x9023, 0x0fc8,
+ 0x9027, 0x1af9,
+ 0x902e, 0x0b41,
+ 0x9031, 0x093f,
+ 0x9032, 0x0a10,
+ 0x9035, 0x1afb,
+ 0x9036, 0x1afa,
+ 0x9038, 0x04b3,
+ 0x9039, 0x1afc,
+ 0x903c, 0x0da1,
+ 0x903e, 0x1b04,
+ 0x9041, 0x0cb3,
+ 0x9042, 0x0a31,
+ 0x9045, 0x0b97,
+ 0x9047, 0x06f0,
+ 0x9049, 0x1b03,
+ 0x904a, 0x0f21,
+ 0x904b, 0x04e1,
+ 0x904d, 0x0e27,
+ 0x904e, 0x0561,
+ 0x904f, 0x1afe,
+ 0x9053, 0x0c93,
+ 0x9054, 0x0b61,
+ 0x9055, 0x04a7,
+ 0x9056, 0x1b05,
+ 0x9058, 0x1b06,
+ 0x9059, 0x1d34,
+ 0x905c, 0x0b1d,
+ 0x905e, 0x1b07,
+ 0x9060, 0x0515,
+ 0x9061, 0x0ace,
+ 0x9063, 0x0763,
+ 0x9065, 0x0f44,
+ 0x9067, 0x21ba,
+ 0x9068, 0x1b08,
+ 0x9069, 0x0c26,
+ 0x906d, 0x0afa,
+ 0x906e, 0x0903,
+ 0x906f, 0x1b09,
+ 0x9072, 0x1b0c,
+ 0x9075, 0x096f,
+ 0x9076, 0x1b0a,
+ 0x9077, 0x0aad,
+ 0x9078, 0x0aac,
+ 0x907a, 0x04a8,
+ 0x907c, 0x0f93,
+ 0x907d, 0x1b0e,
+ 0x907f, 0x0d86,
+ 0x9080, 0x1b10,
+ 0x9081, 0x1b0f,
+ 0x9082, 0x1b0d,
+ 0x9083, 0x1737,
+ 0x9084, 0x0610,
+ 0x9087, 0x1aed,
+ 0x9089, 0x1b12,
+ 0x908a, 0x1b11,
+ 0x908f, 0x1b13,
+ 0x9091, 0x0f22,
+ 0x90a3, 0x0cb9,
+ 0x90a6, 0x0e5c,
+ 0x90a8, 0x1b14,
+ 0x90aa, 0x0905,
+ 0x90af, 0x1b15,
+ 0x90b1, 0x1b16,
+ 0x90b5, 0x1b17,
+ 0x90b8, 0x0c1b,
+ 0x90c1, 0x04ae,
+ 0x90ca, 0x07eb,
+ 0x90ce, 0x0fe0,
+ 0x90db, 0x1b1b,
+ 0x90de, 0x21bb,
+ 0x90e1, 0x070a,
+ 0x90e2, 0x1b18,
+ 0x90e4, 0x1b19,
+ 0x90e8, 0x0de6,
+ 0x90ed, 0x05b2,
+ 0x90f5, 0x0f23,
+ 0x90f7, 0x06b7,
+ 0x90fd, 0x0c4e,
+ 0x9102, 0x1b1c,
+ 0x9112, 0x1b1d,
+ 0x9115, 0x21bd,
+ 0x9119, 0x1b1e,
+ 0x9127, 0x21be,
+ 0x912d, 0x0c1c,
+ 0x9130, 0x1b20,
+ 0x9132, 0x1b1f,
+ 0x9149, 0x0cab,
+ 0x914a, 0x1b21,
+ 0x914b, 0x0940,
+ 0x914c, 0x090c,
+ 0x914d, 0x0d11,
+ 0x914e, 0x0baf,
+ 0x9152, 0x091e,
+ 0x9154, 0x0a32,
+ 0x9156, 0x1b22,
+ 0x9158, 0x1b23,
+ 0x9162, 0x0a23,
+ 0x9163, 0x1b24,
+ 0x9165, 0x1b25,
+ 0x9169, 0x1b26,
+ 0x916a, 0x0f59,
+ 0x916c, 0x0941,
+ 0x9172, 0x1b28,
+ 0x9173, 0x1b27,
+ 0x9175, 0x07ec,
+ 0x9177, 0x0805,
+ 0x9178, 0x088e,
+ 0x9182, 0x1b2b,
+ 0x9187, 0x0970,
+ 0x9189, 0x1b2a,
+ 0x918b, 0x1b29,
+ 0x918d, 0x0b49,
+ 0x9190, 0x07a3,
+ 0x9192, 0x0a67,
+ 0x9197, 0x0d44,
+ 0x919c, 0x0943,
+ 0x91a2, 0x1b2c,
+ 0x91a4, 0x09c7,
+ 0x91aa, 0x1b2f,
+ 0x91ab, 0x1b2d,
+ 0x91ac, 0x1e1b,
+ 0x91af, 0x1b2e,
+ 0x91b1, 0x1e61,
+ 0x91b4, 0x1b31,
+ 0x91b5, 0x1b30,
+ 0x91b8, 0x09e2,
+ 0x91ba, 0x1b32,
+ 0x91c0, 0x1b33,
+ 0x91c6, 0x0d64,
+ 0x91c7, 0x0843,
+ 0x91c8, 0x090d,
+ 0x91c9, 0x1b35,
+ 0x91cb, 0x1b36,
+ 0x91cc, 0x0f6c,
+ 0x91cd, 0x094f,
+ 0x91ce, 0x0efa,
+ 0x91cf, 0x0f94,
+ 0x91d0, 0x1b37,
+ 0x91d1, 0x06da,
+ 0x91d6, 0x1b38,
+ 0x91d7, 0x21c0,
+ 0x91d8, 0x0c1d,
+ 0x91da, 0x21bf,
+ 0x91db, 0x1b3b,
+ 0x91dc, 0x05d6,
+ 0x91dd, 0x0a11,
+ 0x91de, 0x21c1,
+ 0x91df, 0x1b39,
+ 0x91e1, 0x1b3a,
+ 0x91e3, 0x0bfc,
+ 0x91e4, 0x21c4,
+ 0x91e6, 0x0e83,
+ 0x91e7, 0x06f4,
+ 0x91ed, 0x21c2,
+ 0x91f5, 0x1b3d,
+ 0x91fc, 0x1b3c,
+ 0x91ff, 0x1b40,
+ 0x9206, 0x21c6,
+ 0x920a, 0x21c8,
+ 0x920d, 0x0cb7,
+ 0x920e, 0x05a1,
+ 0x9210, 0x21c7,
+ 0x9211, 0x1b44,
+ 0x9214, 0x1b41,
+ 0x9215, 0x1b43,
+ 0x921e, 0x1b3f,
+ 0x9229, 0x1b8a,
+ 0x922c, 0x1b42,
+ 0x9234, 0x0fb3,
+ 0x9237, 0x078e,
+ 0x9239, 0x21cf,
+ 0x923a, 0x21c9,
+ 0x923c, 0x21cb,
+ 0x923f, 0x1b4c,
+ 0x9240, 0x21ca,
+ 0x9244, 0x0c2e,
+ 0x9245, 0x1b47,
+ 0x9248, 0x1b4a,
+ 0x9249, 0x1b48,
+ 0x924b, 0x1b4d,
+ 0x924e, 0x21cc,
+ 0x9250, 0x1b4e,
+ 0x9251, 0x21ce,
+ 0x9257, 0x1b46,
+ 0x9259, 0x21cd,
+ 0x925a, 0x1b53,
+ 0x925b, 0x0516,
+ 0x925e, 0x1b45,
+ 0x9262, 0x0d41,
+ 0x9264, 0x1b49,
+ 0x9266, 0x09c8,
+ 0x9267, 0x21d0,
+ 0x9271, 0x07ed,
+ 0x9277, 0x21d2,
+ 0x927e, 0x0e76,
+ 0x9280, 0x06dc,
+ 0x9283, 0x0950,
+ 0x9285, 0x0c94,
+ 0x9288, 0x20aa,
+ 0x9291, 0x0aaf,
+ 0x9293, 0x1b51,
+ 0x9295, 0x1b4b,
+ 0x9296, 0x1b50,
+ 0x9298, 0x0ecf,
+ 0x929a, 0x0bd4,
+ 0x929b, 0x1b52,
+ 0x929c, 0x1b4f,
+ 0x92a7, 0x21d1,
+ 0x92ad, 0x0aae,
+ 0x92b7, 0x1b56,
+ 0x92b9, 0x1b55,
+ 0x92cf, 0x1b54,
+ 0x92d0, 0x21d7,
+ 0x92d2, 0x0e5d,
+ 0x92d3, 0x21db,
+ 0x92d5, 0x21d9,
+ 0x92d7, 0x21d5,
+ 0x92d9, 0x21d6,
+ 0x92e0, 0x21da,
+ 0x92e4, 0x0985,
+ 0x92e7, 0x21d4,
+ 0x92e9, 0x1b57,
+ 0x92ea, 0x0e2f,
+ 0x92ed, 0x04f6,
+ 0x92f2, 0x0db8,
+ 0x92f3, 0x0bb0,
+ 0x92f8, 0x0692,
+ 0x92f9, 0x20b0,
+ 0x92fa, 0x1b59,
+ 0x92fb, 0x21de,
+ 0x92fc, 0x07ef,
+ 0x92ff, 0x21e1,
+ 0x9302, 0x21e3,
+ 0x9306, 0x087a,
+ 0x930f, 0x1b58,
+ 0x9310, 0x0a33,
+ 0x9318, 0x0a34,
+ 0x9319, 0x1b5c,
+ 0x931a, 0x1b5e,
+ 0x931d, 0x21e2,
+ 0x931e, 0x21e0,
+ 0x9320, 0x09e3,
+ 0x9321, 0x21dd,
+ 0x9322, 0x1b5d,
+ 0x9323, 0x1b5f,
+ 0x9325, 0x21dc,
+ 0x9326, 0x06cb,
+ 0x9328, 0x0db7,
+ 0x932b, 0x090e,
+ 0x932c, 0x0fc9,
+ 0x932e, 0x1b5b,
+ 0x932f, 0x0868,
+ 0x9332, 0x0fe5,
+ 0x9335, 0x1b61,
+ 0x933a, 0x1b60,
+ 0x933b, 0x1b62,
+ 0x9344, 0x1b5a,
+ 0x9348, 0x20a9,
+ 0x934b, 0x0cc1,
+ 0x934d, 0x0c4f,
+ 0x9354, 0x0bf3,
+ 0x9356, 0x1b67,
+ 0x9357, 0x21e5,
+ 0x935b, 0x0b81,
+ 0x935c, 0x1b63,
+ 0x9360, 0x1b64,
+ 0x936c, 0x0703,
+ 0x936e, 0x1b66,
+ 0x9370, 0x21e4,
+ 0x9375, 0x0764,
+ 0x937c, 0x1b65,
+ 0x937e, 0x09c9,
+ 0x938c, 0x05d7,
+ 0x9394, 0x1b6b,
+ 0x9396, 0x082f,
+ 0x9397, 0x0afb,
+ 0x939a, 0x0be6,
+ 0x93a4, 0x21e6,
+ 0x93a7, 0x0599,
+ 0x93ac, 0x1b69,
+ 0x93ae, 0x0bdf,
+ 0x93b0, 0x1b68,
+ 0x93b9, 0x1b6c,
+ 0x93c3, 0x1b72,
+ 0x93c6, 0x21e7,
+ 0x93c8, 0x1b75,
+ 0x93d0, 0x1b74,
+ 0x93d1, 0x0c27,
+ 0x93d6, 0x1b6d,
+ 0x93d8, 0x1b71,
+ 0x93dd, 0x1b73,
+ 0x93de, 0x21e8,
+ 0x93e1, 0x06b8,
+ 0x93e4, 0x1b76,
+ 0x93e5, 0x1b70,
+ 0x93e8, 0x1b6f,
+ 0x93f8, 0x21e9,
+ 0x9403, 0x1b7a,
+ 0x9407, 0x1b7b,
+ 0x9410, 0x1b7c,
+ 0x9413, 0x1b79,
+ 0x9414, 0x1b78,
+ 0x9418, 0x09ca,
+ 0x9419, 0x0c82,
+ 0x941a, 0x1b77,
+ 0x9421, 0x1b80,
+ 0x942b, 0x1b7e,
+ 0x9431, 0x21ea,
+ 0x9435, 0x1b7f,
+ 0x9436, 0x1b7d,
+ 0x9438, 0x0b58,
+ 0x943a, 0x1b81,
+ 0x9441, 0x1b82,
+ 0x9444, 0x1b84,
+ 0x9445, 0x21eb,
+ 0x9448, 0x21ec,
+ 0x9451, 0x0611,
+ 0x9452, 0x1b83,
+ 0x9453, 0x0f06,
+ 0x945a, 0x1b8f,
+ 0x945b, 0x1b85,
+ 0x945e, 0x1b88,
+ 0x9460, 0x1b86,
+ 0x9462, 0x1b87,
+ 0x946a, 0x1b89,
+ 0x9470, 0x1b8b,
+ 0x9475, 0x1b8c,
+ 0x9477, 0x1b8d,
+ 0x947c, 0x1b90,
+ 0x947d, 0x1b8e,
+ 0x947e, 0x1b91,
+ 0x947f, 0x1b93,
+ 0x9481, 0x1b92,
+ 0x9577, 0x0bd5,
+ 0x9580, 0x0ef3,
+ 0x9582, 0x1b94,
+ 0x9583, 0x0ab0,
+ 0x9587, 0x1b95,
+ 0x9589, 0x0e14,
+ 0x958a, 0x1b96,
+ 0x958b, 0x0589,
+ 0x958f, 0x04de,
+ 0x9591, 0x0613,
+ 0x9592, 0x21ed,
+ 0x9593, 0x0612,
+ 0x9594, 0x1b97,
+ 0x9596, 0x1b98,
+ 0x9598, 0x1b99,
+ 0x95a0, 0x1b9b,
+ 0x95a2, 0x0614,
+ 0x95a3, 0x05b3,
+ 0x95a4, 0x07f0,
+ 0x95a5, 0x0d4a,
+ 0x95a7, 0x1b9d,
+ 0x95a8, 0x1b9c,
+ 0x95ad, 0x1b9e,
+ 0x95b2, 0x04fe,
+ 0x95b9, 0x1ba1,
+ 0x95bb, 0x1ba0,
+ 0x95bc, 0x1b9f,
+ 0x95be, 0x1ba2,
+ 0x95c3, 0x1ba5,
+ 0x95c7, 0x048b,
+ 0x95ca, 0x1ba3,
+ 0x95cc, 0x1ba7,
+ 0x95cd, 0x1ba6,
+ 0x95d4, 0x1ba9,
+ 0x95d5, 0x1ba8,
+ 0x95d6, 0x1baa,
+ 0x95d8, 0x0c86,
+ 0x95dc, 0x1bab,
+ 0x95e1, 0x1bac,
+ 0x95e2, 0x1bae,
+ 0x95e5, 0x1bad,
+ 0x961c, 0x0dde,
+ 0x9621, 0x1baf,
+ 0x9628, 0x1bb0,
+ 0x962a, 0x0855,
+ 0x962e, 0x1bb1,
+ 0x9632, 0x0e77,
+ 0x963b, 0x0acd,
+ 0x963f, 0x0468,
+ 0x9640, 0x0b2b,
+ 0x9642, 0x1bb3,
+ 0x9644, 0x0ddf,
+ 0x964b, 0x1bb6,
+ 0x964c, 0x1bb4,
+ 0x964d, 0x07f1,
+ 0x964f, 0x1bb5,
+ 0x9650, 0x0776,
+ 0x965b, 0x0e15,
+ 0x965c, 0x1bb8,
+ 0x965d, 0x1bba,
+ 0x965e, 0x1bb9,
+ 0x965f, 0x1bbb,
+ 0x9662, 0x04c3,
+ 0x9663, 0x0a1e,
+ 0x9664, 0x0986,
+ 0x9665, 0x0615,
+ 0x9666, 0x1bbc,
+ 0x966a, 0x0d1c,
+ 0x966c, 0x1bbe,
+ 0x9670, 0x04c4,
+ 0x9672, 0x1bbd,
+ 0x9673, 0x0be0,
+ 0x9675, 0x0f95,
+ 0x9676, 0x0c83,
+ 0x9677, 0x1bb7,
+ 0x9678, 0x0f6e,
+ 0x967a, 0x0765,
+ 0x967d, 0x0f45,
+ 0x9685, 0x06f1,
+ 0x9686, 0x0f7c,
+ 0x9688, 0x06fe,
+ 0x968a, 0x0b42,
+ 0x968b, 0x186c,
+ 0x968d, 0x1bbf,
+ 0x968e, 0x058a,
+ 0x968f, 0x0a35,
+ 0x9694, 0x05b4,
+ 0x9695, 0x1bc1,
+ 0x9697, 0x1bc2,
+ 0x9698, 0x1bc0,
+ 0x9699, 0x073a,
+ 0x969b, 0x084d,
+ 0x969c, 0x09cb,
+ 0x969d, 0x21f0,
+ 0x96a0, 0x04c5,
+ 0x96a3, 0x0fa1,
+ 0x96a7, 0x1bc4,
+ 0x96a8, 0x1b0b,
+ 0x96aa, 0x1bc3,
+ 0x96af, 0x21f1,
+ 0x96b0, 0x1bc7,
+ 0x96b1, 0x1bc5,
+ 0x96b4, 0x1bc8,
+ 0x96b6, 0x1bc9,
+ 0x96b7, 0x0fb4,
+ 0x96b8, 0x1bca,
+ 0x96bb, 0x0a6d,
+ 0x96bc, 0x0d4f,
+ 0x96c0, 0x0a43,
+ 0x96c1, 0x0623,
+ 0x96c4, 0x0f24,
+ 0x96c5, 0x056d,
+ 0x96c6, 0x0942,
+ 0x96c7, 0x078f,
+ 0x96c9, 0x1bce,
+ 0x96cb, 0x1bcd,
+ 0x96cc, 0x08c1,
+ 0x96cd, 0x1bcf,
+ 0x96ce, 0x1bcc,
+ 0x96d1, 0x0876,
+ 0x96d5, 0x1bd3,
+ 0x96d6, 0x1992,
+ 0x96d9, 0x10eb,
+ 0x96db, 0x0a3d,
+ 0x96dc, 0x1bd1,
+ 0x96e2, 0x0f6d,
+ 0x96e3, 0x0cc9,
+ 0x96e8, 0x04cd,
+ 0x96ea, 0x0a87,
+ 0x96eb, 0x08e2,
+ 0x96f0, 0x0e07,
+ 0x96f2, 0x04e2,
+ 0x96f6, 0x0fb5,
+ 0x96f7, 0x0f55,
+ 0x96f9, 0x1bd4,
+ 0x96fb, 0x0c3f,
+ 0x9700, 0x0927,
+ 0x9704, 0x1bd5,
+ 0x9706, 0x1bd6,
+ 0x9707, 0x0a12,
+ 0x9708, 0x1bd7,
+ 0x970a, 0x0fb6,
+ 0x970d, 0x1bd2,
+ 0x970e, 0x1bd9,
+ 0x970f, 0x1bdb,
+ 0x9711, 0x1bda,
+ 0x9713, 0x1bd8,
+ 0x9716, 0x1bdc,
+ 0x9719, 0x1bdd,
+ 0x971c, 0x0afc,
+ 0x971e, 0x0562,
+ 0x9724, 0x1bde,
+ 0x9727, 0x0ec4,
+ 0x972a, 0x1bdf,
+ 0x9730, 0x1be0,
+ 0x9732, 0x0fd0,
+ 0x9733, 0x21f2,
+ 0x9738, 0x1414,
+ 0x9739, 0x1be1,
+ 0x973b, 0x21f3,
+ 0x973d, 0x1be2,
+ 0x9742, 0x1be7,
+ 0x9743, 0x21f4,
+ 0x9744, 0x1be4,
+ 0x9746, 0x1be5,
+ 0x9748, 0x1be6,
+ 0x9749, 0x1be8,
+ 0x974d, 0x21f5,
+ 0x974f, 0x21f6,
+ 0x9751, 0x21f7,
+ 0x9752, 0x0a68,
+ 0x9755, 0x21f8,
+ 0x9756, 0x0f03,
+ 0x9759, 0x0a69,
+ 0x975c, 0x1be9,
+ 0x975e, 0x0d87,
+ 0x9760, 0x1bea,
+ 0x9761, 0x1d06,
+ 0x9762, 0x0ed8,
+ 0x9764, 0x1beb,
+ 0x9766, 0x1bec,
+ 0x9768, 0x1bed,
+ 0x9769, 0x05b5,
+ 0x976b, 0x1bef,
+ 0x976d, 0x0a1f,
+ 0x9771, 0x1bf0,
+ 0x9774, 0x06fa,
+ 0x9779, 0x1bf1,
+ 0x977a, 0x1bf5,
+ 0x977c, 0x1bf3,
+ 0x9781, 0x1bf4,
+ 0x9784, 0x05d1,
+ 0x9785, 0x1bf2,
+ 0x9786, 0x1bf6,
+ 0x978b, 0x1bf7,
+ 0x978d, 0x048c,
+ 0x978f, 0x1bf8,
+ 0x9798, 0x09cc,
+ 0x979c, 0x1bfa,
+ 0x97a0, 0x0661,
+ 0x97a3, 0x1bfd,
+ 0x97a6, 0x1bfc,
+ 0x97a8, 0x1bfb,
+ 0x97ab, 0x1a34,
+ 0x97ad, 0x0e2c,
+ 0x97b3, 0x1bfe,
+ 0x97c3, 0x1c00,
+ 0x97c6, 0x1c01,
+ 0x97c8, 0x1c02,
+ 0x97cb, 0x1c03,
+ 0x97d3, 0x0616,
+ 0x97dc, 0x1c04,
+ 0x97ed, 0x1c05,
+ 0x97ee, 0x0cd9,
+ 0x97f2, 0x1c07,
+ 0x97f3, 0x053b,
+ 0x97f5, 0x1c0a,
+ 0x97f6, 0x1c09,
+ 0x97fb, 0x04c6,
+ 0x97ff, 0x06b9,
+ 0x9801, 0x0e17,
+ 0x9802, 0x0bd6,
+ 0x9803, 0x0812,
+ 0x9805, 0x07f2,
+ 0x9806, 0x0971,
+ 0x9808, 0x0a22,
+ 0x980c, 0x1c0c,
+ 0x980f, 0x1c0b,
+ 0x9810, 0x0f2c,
+ 0x9811, 0x0624,
+ 0x9812, 0x0d66,
+ 0x9813, 0x0cb4,
+ 0x9817, 0x0a42,
+ 0x9818, 0x0f96,
+ 0x981a, 0x0731,
+ 0x9821, 0x1c0f,
+ 0x9824, 0x1c0e,
+ 0x982c, 0x0e79,
+ 0x982d, 0x0c84,
+ 0x9830, 0x1e73,
+ 0x9834, 0x04f2,
+ 0x9837, 0x1c10,
+ 0x9838, 0x1c0d,
+ 0x983b, 0x0dc3,
+ 0x983c, 0x0f54,
+ 0x983d, 0x1c11,
+ 0x9846, 0x1c12,
+ 0x984b, 0x1c14,
+ 0x984c, 0x0b4a,
+ 0x984d, 0x05b9,
+ 0x984f, 0x1c13,
+ 0x9854, 0x0625,
+ 0x9855, 0x0766,
+ 0x9857, 0x21f9,
+ 0x9858, 0x0626,
+ 0x985a, 0x1e48,
+ 0x985b, 0x0c39,
+ 0x985e, 0x0fa8,
+ 0x9865, 0x21fa,
+ 0x9867, 0x0790,
+ 0x986b, 0x1c15,
+ 0x986f, 0x1c16,
+ 0x9873, 0x1c1a,
+ 0x9874, 0x1c19,
+ 0x98a8, 0x0de9,
+ 0x98aa, 0x1c1b,
+ 0x98af, 0x1c1c,
+ 0x98b1, 0x1c1d,
+ 0x98b6, 0x1c1e,
+ 0x98c3, 0x1c20,
+ 0x98c4, 0x1c1f,
+ 0x98c6, 0x1c21,
+ 0x98db, 0x0d88,
+ 0x98dc, 0x1839,
+ 0x98df, 0x09ef,
+ 0x98e2, 0x064c,
+ 0x98e9, 0x1c22,
+ 0x98eb, 0x1c23,
+ 0x98ed, 0x10c1,
+ 0x98ee, 0x14da,
+ 0x98ef, 0x0d67,
+ 0x98f2, 0x04bf,
+ 0x98f4, 0x047f,
+ 0x98fc, 0x08c2,
+ 0x98fd, 0x0e5e,
+ 0x98fe, 0x09e6,
+ 0x9903, 0x1c24,
+ 0x9905, 0x0eeb,
+ 0x9909, 0x1c25,
+ 0x990a, 0x0f46,
+ 0x990c, 0x04e4,
+ 0x9910, 0x088f,
+ 0x9912, 0x1c26,
+ 0x9913, 0x056e,
+ 0x9914, 0x1c27,
+ 0x9918, 0x1c28,
+ 0x991d, 0x1c2a,
+ 0x9920, 0x1c2d,
+ 0x9921, 0x1c29,
+ 0x9924, 0x1c2c,
+ 0x9927, 0x21fd,
+ 0x9928, 0x0617,
+ 0x992c, 0x1c2e,
+ 0x992e, 0x1c2f,
+ 0x993d, 0x1c30,
+ 0x9942, 0x1c32,
+ 0x9945, 0x1c34,
+ 0x9949, 0x1c33,
+ 0x994b, 0x1c36,
+ 0x994c, 0x1c39,
+ 0x9950, 0x1c35,
+ 0x9951, 0x1c37,
+ 0x9955, 0x1c3a,
+ 0x9957, 0x06ba,
+ 0x9996, 0x091f,
+ 0x9997, 0x1c3b,
+ 0x9999, 0x07f3,
+ 0x999e, 0x21ff,
+ 0x99a5, 0x1c3d,
+ 0x99a8, 0x059c,
+ 0x99ac, 0x0d05,
+ 0x99ad, 0x1c3e,
+ 0x99b3, 0x0b98,
+ 0x99b4, 0x0cc3,
+ 0x99bc, 0x1c40,
+ 0x99c1, 0x0d33,
+ 0x99c4, 0x0b2c,
+ 0x99c5, 0x04fa,
+ 0x99c6, 0x06e6,
+ 0x99c8, 0x06e7,
+ 0x99d0, 0x0bb1,
+ 0x99d1, 0x1c45,
+ 0x99d2, 0x06e8,
+ 0x99d5, 0x056f,
+ 0x99d8, 0x1c44,
+ 0x99db, 0x1c42,
+ 0x99dd, 0x1c43,
+ 0x99df, 0x1c41,
+ 0x99e2, 0x1c4f,
+ 0x99ed, 0x1c46,
+ 0x99f1, 0x1c48,
+ 0x99f8, 0x1c4b,
+ 0x99fb, 0x1c4a,
+ 0x99ff, 0x0963,
+ 0x9a01, 0x1c4c,
+ 0x9a05, 0x1c4e,
+ 0x9a0e, 0x064d,
+ 0x9a0f, 0x1c4d,
+ 0x9a12, 0x0afd,
+ 0x9a13, 0x0767,
+ 0x9a19, 0x1c50,
+ 0x9a28, 0x0b2d,
+ 0x9a2b, 0x1c51,
+ 0x9a30, 0x0c85,
+ 0x9a37, 0x1c52,
+ 0x9a3e, 0x1c57,
+ 0x9a40, 0x1c55,
+ 0x9a42, 0x1c54,
+ 0x9a43, 0x1c56,
+ 0x9a45, 0x1c53,
+ 0x9a4d, 0x1c59,
+ 0x9a4e, 0x2200,
+ 0x9a52, 0x1e2f,
+ 0x9a55, 0x1c58,
+ 0x9a57, 0x1c5b,
+ 0x9a5a, 0x06bb,
+ 0x9a5b, 0x1c5a,
+ 0x9a5f, 0x1c5c,
+ 0x9a62, 0x1c5d,
+ 0x9a64, 0x1c5f,
+ 0x9a65, 0x1c5e,
+ 0x9a69, 0x1c60,
+ 0x9a6a, 0x1c62,
+ 0x9a6b, 0x1c61,
+ 0x9aa8, 0x080e,
+ 0x9aad, 0x1c63,
+ 0x9ab0, 0x1c64,
+ 0x9ab8, 0x059a,
+ 0x9abc, 0x1c65,
+ 0x9ac0, 0x1c66,
+ 0x9ac4, 0x0a37,
+ 0x9acf, 0x1c67,
+ 0x9ad1, 0x1c68,
+ 0x9ad3, 0x1c69,
+ 0x9ad8, 0x07f4,
+ 0x9ad9, 0x2201,
+ 0x9adc, 0x2202,
+ 0x9ade, 0x1c6b,
+ 0x9ae2, 0x1c6d,
+ 0x9ae6, 0x1c6f,
+ 0x9aea, 0x0d45,
+ 0x9aeb, 0x1c71,
+ 0x9aed, 0x0d98,
+ 0x9aee, 0x1c72,
+ 0x9aef, 0x1c70,
+ 0x9af1, 0x1c74,
+ 0x9af4, 0x1c73,
+ 0x9af7, 0x1c75,
+ 0x9afb, 0x1c76,
+ 0x9b06, 0x1c77,
+ 0x9b18, 0x1c78,
+ 0x9b1a, 0x1c79,
+ 0x9b1f, 0x1c7a,
+ 0x9b22, 0x1c7b,
+ 0x9b25, 0x1c7d,
+ 0x9b27, 0x1c7e,
+ 0x9b2e, 0x1c82,
+ 0x9b31, 0x14d4,
+ 0x9b32, 0x1c84,
+ 0x9b3b, 0x17a9,
+ 0x9b3c, 0x064e,
+ 0x9b41, 0x057f,
+ 0x9b42, 0x0822,
+ 0x9b43, 0x1c86,
+ 0x9b44, 0x1c85,
+ 0x9b45, 0x0eb1,
+ 0x9b4d, 0x1c88,
+ 0x9b4f, 0x1c87,
+ 0x9b51, 0x1c8a,
+ 0x9b54, 0x0e90,
+ 0x9b58, 0x1c8b,
+ 0x9b5a, 0x0695,
+ 0x9b6f, 0x0fcb,
+ 0x9b72, 0x2204,
+ 0x9b74, 0x1c8c,
+ 0x9b75, 0x2203,
+ 0x9b83, 0x1c8e,
+ 0x9b8e, 0x0482,
+ 0x9b8f, 0x2205,
+ 0x9b91, 0x1c8f,
+ 0x9b92, 0x0dfb,
+ 0x9b93, 0x1c8d,
+ 0x9b96, 0x1c90,
+ 0x9b9f, 0x1c92,
+ 0x9ba8, 0x1c94,
+ 0x9baa, 0x0e9c,
+ 0x9bab, 0x087b,
+ 0x9bad, 0x086a,
+ 0x9bae, 0x0ab1,
+ 0x9bb1, 0x2206,
+ 0x9bb4, 0x1c95,
+ 0x9bb9, 0x1c98,
+ 0x9bbb, 0x2207,
+ 0x9bc0, 0x1c96,
+ 0x9bc6, 0x1c99,
+ 0x9bc9, 0x07a5,
+ 0x9bca, 0x1c97,
+ 0x9bcf, 0x1c9a,
+ 0x9bd1, 0x1c9b,
+ 0x9bd4, 0x1ca0,
+ 0x9bd6, 0x0878,
+ 0x9bdb, 0x0b44,
+ 0x9be1, 0x1ca1,
+ 0x9be2, 0x1c9e,
+ 0x9be3, 0x1c9d,
+ 0x9be4, 0x1c9f,
+ 0x9be8, 0x0735,
+ 0x9bf0, 0x1ca5,
+ 0x9bf1, 0x1ca4,
+ 0x9bf2, 0x1ca3,
+ 0x9bf5, 0x0477,
+ 0x9c00, 0x2208,
+ 0x9c04, 0x1caf,
+ 0x9c06, 0x1cab,
+ 0x9c08, 0x1cac,
+ 0x9c09, 0x1ca8,
+ 0x9c0a, 0x1cae,
+ 0x9c0c, 0x1caa,
+ 0x9c0d, 0x05c0,
+ 0x9c10, 0x0ff2,
+ 0x9c12, 0x1cad,
+ 0x9c13, 0x1ca9,
+ 0x9c14, 0x1ca7,
+ 0x9c15, 0x1ca6,
+ 0x9c1b, 0x1cb1,
+ 0x9c21, 0x1cb4,
+ 0x9c24, 0x1cb3,
+ 0x9c25, 0x1cb2,
+ 0x9c2d, 0x0dbb,
+ 0x9c2e, 0x1cb0,
+ 0x9c2f, 0x04b7,
+ 0x9c30, 0x1cb5,
+ 0x9c32, 0x1cb7,
+ 0x9c39, 0x05cd,
+ 0x9c3a, 0x1ca2,
+ 0x9c3b, 0x04d9,
+ 0x9c3e, 0x1cb9,
+ 0x9c46, 0x1cb8,
+ 0x9c47, 0x1cb6,
+ 0x9c48, 0x0b6b,
+ 0x9c52, 0x0e9e,
+ 0x9c57, 0x0fa2,
+ 0x9c5a, 0x1cba,
+ 0x9c60, 0x1cbb,
+ 0x9c67, 0x1cbc,
+ 0x9c76, 0x1cbd,
+ 0x9c78, 0x1cbe,
+ 0x9ce5, 0x0bd7,
+ 0x9ce7, 0x1cbf,
+ 0x9ce9, 0x0d4b,
+ 0x9ceb, 0x1cc4,
+ 0x9cec, 0x1cc0,
+ 0x9cf0, 0x1cc1,
+ 0x9cf3, 0x0e5f,
+ 0x9cf4, 0x0ed0,
+ 0x9cf6, 0x0ca8,
+ 0x9d03, 0x1cc5,
+ 0x9d06, 0x1cc6,
+ 0x9d07, 0x0c96,
+ 0x9d08, 0x1cc3,
+ 0x9d09, 0x1cc2,
+ 0x9d0e, 0x052a,
+ 0x9d12, 0x1cce,
+ 0x9d15, 0x1ccd,
+ 0x9d1b, 0x0517,
+ 0x9d1f, 0x1ccb,
+ 0x9d23, 0x1cca,
+ 0x9d26, 0x1cc8,
+ 0x9d28, 0x05d9,
+ 0x9d2a, 0x1cc7,
+ 0x9d2b, 0x08de,
+ 0x9d2c, 0x0529,
+ 0x9d3b, 0x07f5,
+ 0x9d3e, 0x1cd1,
+ 0x9d3f, 0x1cd0,
+ 0x9d41, 0x1ccf,
+ 0x9d44, 0x1ccc,
+ 0x9d46, 0x1cd2,
+ 0x9d48, 0x1cd3,
+ 0x9d50, 0x1cd8,
+ 0x9d51, 0x1cd7,
+ 0x9d59, 0x1cd9,
+ 0x9d5c, 0x04cf,
+ 0x9d5d, 0x1cd4,
+ 0x9d60, 0x0806,
+ 0x9d61, 0x0ec5,
+ 0x9d64, 0x1cd6,
+ 0x9d6b, 0x220a,
+ 0x9d6c, 0x0e60,
+ 0x9d6f, 0x1cde,
+ 0x9d70, 0x2209,
+ 0x9d72, 0x1cda,
+ 0x9d7a, 0x1cdf,
+ 0x9d87, 0x1cdc,
+ 0x9d89, 0x1cdb,
+ 0x9d8f, 0x0732,
+ 0x9d9a, 0x1ce0,
+ 0x9da4, 0x1ce1,
+ 0x9da9, 0x1ce2,
+ 0x9dab, 0x1cdd,
+ 0x9daf, 0x1cc9,
+ 0x9db2, 0x1ce3,
+ 0x9db4, 0x0bfd,
+ 0x9db8, 0x1ce7,
+ 0x9dba, 0x1ce8,
+ 0x9dbb, 0x1ce6,
+ 0x9dc1, 0x1ce5,
+ 0x9dc2, 0x1ceb,
+ 0x9dc4, 0x1ce4,
+ 0x9dc6, 0x1ce9,
+ 0x9dcf, 0x1cea,
+ 0x9dd3, 0x1ced,
+ 0x9dd7, 0x1dde,
+ 0x9dd9, 0x1cec,
+ 0x9de6, 0x1cef,
+ 0x9ded, 0x1cf0,
+ 0x9def, 0x1cf1,
+ 0x9df2, 0x0fef,
+ 0x9df8, 0x1cee,
+ 0x9df9, 0x0b4b,
+ 0x9dfa, 0x085d,
+ 0x9dfd, 0x1cf2,
+ 0x9e19, 0x220c,
+ 0x9e1a, 0x1cf3,
+ 0x9e1e, 0x1cf5,
+ 0x9e75, 0x1cf6,
+ 0x9e78, 0x0768,
+ 0x9e79, 0x1cf7,
+ 0x9e7c, 0x1dfd,
+ 0x9e7d, 0x1cf8,
+ 0x9e7f, 0x08db,
+ 0x9e81, 0x1cf9,
+ 0x9e88, 0x1cfa,
+ 0x9e8b, 0x1cfb,
+ 0x9e91, 0x1cff,
+ 0x9e92, 0x1cfd,
+ 0x9e93, 0x0fe2,
+ 0x9e95, 0x1cfe,
+ 0x9e97, 0x0fb7,
+ 0x9e9d, 0x1d00,
+ 0x9e9f, 0x0fa3,
+ 0x9ea5, 0x1d01,
+ 0x9ea6, 0x0d34,
+ 0x9ea9, 0x1d02,
+ 0x9eaa, 0x1d04,
+ 0x9ead, 0x1d05,
+ 0x9eb4, 0x1e02,
+ 0x9eb5, 0x1e75,
+ 0x9eb8, 0x1d03,
+ 0x9eb9, 0x07ff,
+ 0x9eba, 0x0ed9,
+ 0x9ebb, 0x0e91,
+ 0x9ebc, 0x1284,
+ 0x9ebe, 0x14ff,
+ 0x9ebf, 0x0ea9,
+ 0x9ec4, 0x052b,
+ 0x9ecc, 0x1d07,
+ 0x9ecd, 0x066a,
+ 0x9ece, 0x1d08,
+ 0x9ed1, 0x220d,
+ 0x9ed2, 0x0807,
+ 0x9ed4, 0x1d0b,
+ 0x9ed8, 0x160d,
+ 0x9ed9, 0x0ee7,
+ 0x9edb, 0x0b43,
+ 0x9edc, 0x1d0c,
+ 0x9edd, 0x1d0e,
+ 0x9ede, 0x1d0d,
+ 0x9ee0, 0x1d0f,
+ 0x9ee5, 0x1d10,
+ 0x9ee8, 0x1d11,
+ 0x9eef, 0x1d12,
+ 0x9ef4, 0x1d13,
+ 0x9ef6, 0x1d14,
+ 0x9ef9, 0x1d16,
+ 0x9efb, 0x1d17,
+ 0x9f07, 0x1d1a,
+ 0x9f0e, 0x0c1e,
+ 0x9f13, 0x0791,
+ 0x9f15, 0x1d1d,
+ 0x9f20, 0x0acf,
+ 0x9f21, 0x1d1e,
+ 0x9f2c, 0x1d1f,
+ 0x9f3b, 0x0d93,
+ 0x9f3e, 0x1d20,
+ 0x9f4a, 0x1d21,
+ 0x9f4b, 0x170a,
+ 0x9f4e, 0x1a7b,
+ 0x9f4f, 0x1c06,
+ 0x9f52, 0x1d22,
+ 0x9f54, 0x1d23,
+ 0x9f5f, 0x1d25,
+ 0x9f62, 0x0fb8,
+ 0x9f63, 0x1d24,
+ 0x9f66, 0x1d28,
+ 0x9f6a, 0x1d2b,
+ 0x9f6c, 0x1d2a,
+ 0x9f72, 0x1d2d,
+ 0x9f76, 0x1d2e,
+ 0x9f77, 0x1d2c,
+ 0x9f8d, 0x0f7e,
+ 0x9f95, 0x1d2f,
+ 0x9f9c, 0x1d30,
+ 0x9f9d, 0x1727,
+ 0x9fa0, 0x1d31,
+ 0xf929, 0x2129,
+ 0xf9dc, 0x21ee,
+ 0xfa0e, 0x20da,
+ 0xfa0f, 0x20e5,
+ 0xfa11, 0x20fb,
+ 0xfa12, 0x2121,
+ 0xfa13, 0x2131,
+ 0xfa14, 0x2133,
+ 0xfa15, 0x215e,
+ 0xfa16, 0x2164,
+ 0xfa17, 0x217b,
+ 0xfa18, 0x2183,
+ 0xfa1b, 0x2187,
+ 0xfa1c, 0x218b,
+ 0xfa1d, 0x218e,
+ 0xfa1e, 0x2197,
+ 0xfa1f, 0x21a2,
+ 0xfa20, 0x21a4,
+ 0xfa22, 0x21ae,
+ 0xfa23, 0x21b6,
+ 0xfa24, 0x21b8,
+ 0xfa26, 0x21bc,
+ 0xfa27, 0x21d8,
+ 0xfa28, 0x21df,
+ 0xfa29, 0x21ef,
+ 0xfa2a, 0x21fb,
+ 0xfa2c, 0x21fe,
+ 0xfa2d, 0x220b,
+ 0xfb01, 0x0070,
+ 0xfe30, 0x1eda,
+ 0xfe31, 0x1ed4,
+ 0xfe33, 0x1ed2,
+ 0xfe35, 0x1edb,
+ 0xfe37, 0x1ee1,
+ 0xfe39, 0x1edd,
+ 0xfe3b, 0x1eeb,
+ 0xfe3d, 0x1ee5,
+ 0xfe3f, 0x1ee3,
+ 0xfe41, 0x1ee7,
+ 0xff01, 0x0282,
+ 0xff02, 0x1f47,
+ 0xff03, 0x02cc,
+ 0xff04, 0x02c8,
+ 0xff05, 0x02cb,
+ 0xff06, 0x02cd,
+ 0xff07, 0x1f46,
+ 0xff08, 0x02a2,
+ 0xff0a, 0x02ce,
+ 0xff0b, 0x02b4,
+ 0xff0c, 0x027c,
+ 0xff0d, 0x0296,
+ 0xff0e, 0x027d,
+ 0xff0f, 0x0297,
+ 0xff10, 0x030c,
+ 0xff1a, 0x027f,
+ 0xff1c, 0x02bb,
+ 0xff1d, 0x02b9,
+ 0xff1e, 0x02bc,
+ 0xff1f, 0x0281,
+ 0xff20, 0x02cf,
+ 0xff21, 0x0316,
+ 0xff3b, 0x02a6,
+ 0xff3c, 0x0298,
+ 0xff3d, 0x02a7,
+ 0xff3e, 0x0288,
+ 0xff3f, 0x028a,
+ 0xff40, 0x0286,
+ 0xff41, 0x0330,
+ 0xff5b, 0x02a8,
+ 0xff5c, 0x029b,
+ 0xff5d, 0x02a9,
+ 0xff5e, 0x0299,
+ 0xff61, 0x0147,
+ 0xffe0, 0x02c9,
+ 0xffe2, 0x02ef,
+ 0xffe3, 0x0289,
+ 0xffe4, 0x1f45,
+ 0xffe5, 0x02c7,
+ 0xffe8, 0x0143,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12UniJISUCS2HEnc16 = {
+ 0,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12UniJISUCS2HMap2, 6963
+};
+
+static Gushort japan12UniJISUCS2VMap2[14216] = {
+ 0x0000, 0x0000,
+ 0x0020, 0x0001,
+ 0x005c, 0x0061,
+ 0x005d, 0x003e,
+ 0x00a1, 0x0065,
+ 0x00a4, 0x006b,
+ 0x00a5, 0x003d,
+ 0x00a6, 0x0063,
+ 0x00a7, 0x02d0,
+ 0x00a8, 0x0287,
+ 0x00a9, 0x0098,
+ 0x00aa, 0x008c,
+ 0x00ab, 0x006d,
+ 0x00ac, 0x0099,
+ 0x00ad, 0x0097,
+ 0x00ae, 0x009a,
+ 0x00af, 0x0081,
+ 0x00b0, 0x02c3,
+ 0x00b1, 0x02b6,
+ 0x00b2, 0x009d,
+ 0x00b4, 0x0285,
+ 0x00b5, 0x009f,
+ 0x00b6, 0x030a,
+ 0x00b7, 0x0075,
+ 0x00b8, 0x0086,
+ 0x00b9, 0x00a0,
+ 0x00ba, 0x0090,
+ 0x00bb, 0x007b,
+ 0x00bc, 0x00a1,
+ 0x00bf, 0x007e,
+ 0x00c0, 0x00a4,
+ 0x00c6, 0x008b,
+ 0x00c7, 0x00aa,
+ 0x00d7, 0x02b7,
+ 0x00d8, 0x008e,
+ 0x00d9, 0x00bb,
+ 0x00df, 0x0096,
+ 0x00e0, 0x00c1,
+ 0x00e6, 0x0091,
+ 0x00e7, 0x00c7,
+ 0x00f7, 0x02b8,
+ 0x00f8, 0x0094,
+ 0x00f9, 0x00d8,
+ 0x0131, 0x0092,
+ 0x0141, 0x008d,
+ 0x0142, 0x0093,
+ 0x0152, 0x008f,
+ 0x0153, 0x0095,
+ 0x0160, 0x00df,
+ 0x0161, 0x00e3,
+ 0x0178, 0x00e0,
+ 0x017d, 0x00e1,
+ 0x017e, 0x00e5,
+ 0x01c0, 0x0063,
+ 0x0300, 0x0041,
+ 0x0301, 0x007f,
+ 0x0303, 0x005f,
+ 0x0304, 0x0081,
+ 0x0305, 0x00e2,
+ 0x0306, 0x0082,
+ 0x030a, 0x0085,
+ 0x030b, 0x0087,
+ 0x030c, 0x0089,
+ 0x0327, 0x0086,
+ 0x0328, 0x0088,
+ 0x0332, 0x0040,
+ 0x0336, 0x008a,
+ 0x0361, 0x02f6,
+ 0x0391, 0x03f3,
+ 0x03a3, 0x0404,
+ 0x03b1, 0x040b,
+ 0x03c3, 0x041c,
+ 0x0401, 0x0429,
+ 0x0410, 0x0423,
+ 0x0416, 0x042a,
+ 0x0436, 0x044b,
+ 0x0451, 0x044a,
+ 0x2002, 0x00e7,
+ 0x2003, 0x0279,
+ 0x2010, 0x000e,
+ 0x2011, 0x000e,
+ 0x2012, 0x0072,
+ 0x2013, 0x0072,
+ 0x2014, 0x008a,
+ 0x2015, 0x0295,
+ 0x2016, 0x029a,
+ 0x2018, 0x029e,
+ 0x201a, 0x0078,
+ 0x201c, 0x02a0,
+ 0x201e, 0x0079,
+ 0x2020, 0x0308,
+ 0x2022, 0x0077,
+ 0x2025, 0x029d,
+ 0x2026, 0x029c,
+ 0x2030, 0x0304,
+ 0x2032, 0x02c4,
+ 0x2039, 0x006e,
+ 0x203b, 0x02de,
+ 0x203e, 0x0145,
+ 0x2044, 0x0068,
+ 0x20dd, 0x030b,
+ 0x2103, 0x02c6,
+ 0x2109, 0x2071,
+ 0x2113, 0x1f59,
+ 0x2116, 0x1dba,
+ 0x2121, 0x1f77,
+ 0x2122, 0x00e4,
+ 0x212b, 0x0303,
+ 0x2160, 0x1d97,
+ 0x216a, 0x2021,
+ 0x2170, 0x1f9c,
+ 0x217a, 0x206a,
+ 0x217f, 0x206f,
+ 0x2190, 0x02e1,
+ 0x2192, 0x02e0,
+ 0x2193, 0x02e3,
+ 0x21c4, 0x2076,
+ 0x21c6, 0x2075,
+ 0x21d2, 0x02f0,
+ 0x21d4, 0x02f1,
+ 0x21e6, 0x1f4d,
+ 0x21e7, 0x1f4c,
+ 0x21e8, 0x1f4e,
+ 0x21e9, 0x1f4b,
+ 0x2200, 0x02f2,
+ 0x2202, 0x02f7,
+ 0x2203, 0x02f3,
+ 0x2207, 0x02f8,
+ 0x2208, 0x02e5,
+ 0x220b, 0x02e6,
+ 0x2211, 0x1dc9,
+ 0x2212, 0x02b5,
+ 0x221a, 0x02fd,
+ 0x221d, 0x02ff,
+ 0x221e, 0x02bf,
+ 0x221f, 0x1dcd,
+ 0x2220, 0x02f4,
+ 0x2225, 0x029a,
+ 0x2227, 0x02ed,
+ 0x2229, 0x02ec,
+ 0x222a, 0x02eb,
+ 0x222b, 0x0301,
+ 0x222d, 0x2003,
+ 0x222e, 0x1dc8,
+ 0x2234, 0x02c0,
+ 0x2235, 0x0300,
+ 0x223c, 0x0299,
+ 0x223d, 0x02fe,
+ 0x2252, 0x02fa,
+ 0x2260, 0x02ba,
+ 0x2261, 0x02f9,
+ 0x2266, 0x02bd,
+ 0x226a, 0x02fb,
+ 0x2282, 0x02e9,
+ 0x2286, 0x02e7,
+ 0x22a5, 0x02f5,
+ 0x22bf, 0x1dce,
+ 0x22ee, 0x1ed9,
+ 0x22ef, 0x029c,
+ 0x2312, 0x02f6,
+ 0x2460, 0x1d83,
+ 0x2474, 0x1f87,
+ 0x2488, 0x1f7e,
+ 0x249c, 0x1fb0,
+ 0x24ea, 0x2020,
+ 0x2500, 0x1d37,
+ 0x2550, 0x203b,
+ 0x255e, 0x203c,
+ 0x2561, 0x203e,
+ 0x256a, 0x203d,
+ 0x256d, 0x2037,
+ 0x256f, 0x203a,
+ 0x2570, 0x2039,
+ 0x2571, 0x2045,
+ 0x2581, 0x2026,
+ 0x2589, 0x2034,
+ 0x258a, 0x2033,
+ 0x258b, 0x2032,
+ 0x258c, 0x2031,
+ 0x258d, 0x2030,
+ 0x258e, 0x202f,
+ 0x258f, 0x202e,
+ 0x2594, 0x2035,
+ 0x25a0, 0x02d9,
+ 0x25a1, 0x02d8,
+ 0x25a2, 0x1f4f,
+ 0x25b2, 0x02db,
+ 0x25b3, 0x02da,
+ 0x25b7, 0x1f4a,
+ 0x25bc, 0x02dd,
+ 0x25bd, 0x02dc,
+ 0x25c1, 0x1f49,
+ 0x25c6, 0x02d7,
+ 0x25c7, 0x02d6,
+ 0x25c9, 0x2012,
+ 0x25cb, 0x02d3,
+ 0x25ce, 0x02d5,
+ 0x25cf, 0x02d4,
+ 0x25e2, 0x203f,
+ 0x25e4, 0x2042,
+ 0x25e5, 0x2041,
+ 0x25ef, 0x030b,
+ 0x2600, 0x2017,
+ 0x2605, 0x02d2,
+ 0x2606, 0x02d1,
+ 0x260e, 0x1f78,
+ 0x261c, 0x201c,
+ 0x261e, 0x201b,
+ 0x261f, 0x201e,
+ 0x2640, 0x02c2,
+ 0x2642, 0x02c1,
+ 0x2660, 0x2013,
+ 0x2661, 0x1f51,
+ 0x2662, 0x1f53,
+ 0x2663, 0x2015,
+ 0x2664, 0x1f52,
+ 0x2665, 0x2014,
+ 0x2666, 0x2016,
+ 0x2667, 0x1f50,
+ 0x266a, 0x0307,
+ 0x266d, 0x0306,
+ 0x266f, 0x0305,
+ 0x2776, 0x205e,
+ 0x27a1, 0x200e,
+ 0x3000, 0x0279,
+ 0x3003, 0x028f,
+ 0x3004, 0x2074,
+ 0x3005, 0x0291,
+ 0x3008, 0x02aa,
+ 0x3012, 0x02df,
+ 0x3013, 0x02e4,
+ 0x3014, 0x02a4,
+ 0x301c, 0x0299,
+ 0x301d, 0x1db8,
+ 0x301f, 0x1db9,
+ 0x3020, 0x1f7a,
+ 0x3036, 0x1f79,
+ 0x3041, 0x034a,
+ 0x3094, 0x1f16,
+ 0x309b, 0x0283,
+ 0x309d, 0x028d,
+ 0x30a1, 0x039d,
+ 0x30f7, 0x2079,
+ 0x30fb, 0x027e,
+ 0x30fc, 0x0294,
+ 0x30fd, 0x028b,
+ 0x322a, 0x2006,
+ 0x3230, 0x2005,
+ 0x3231, 0x1dc2,
+ 0x3233, 0x1fcf,
+ 0x3234, 0x1fcd,
+ 0x3235, 0x1fd4,
+ 0x3236, 0x1fd3,
+ 0x3237, 0x200c,
+ 0x3238, 0x1fce,
+ 0x3239, 0x1dc4,
+ 0x323a, 0x1fd7,
+ 0x323b, 0x1fd5,
+ 0x323c, 0x1fd0,
+ 0x323d, 0x1fcb,
+ 0x323e, 0x1fd2,
+ 0x323f, 0x1fcc,
+ 0x3240, 0x1fd6,
+ 0x3241, 0x200d,
+ 0x3242, 0x1fd1,
+ 0x3243, 0x1fca,
+ 0x3291, 0x1fe1,
+ 0x3292, 0x1fe0,
+ 0x3293, 0x1fe2,
+ 0x3294, 0x1fdc,
+ 0x3296, 0x1fe5,
+ 0x3298, 0x1fde,
+ 0x3299, 0x201f,
+ 0x329d, 0x207f,
+ 0x329e, 0x1fff,
+ 0x32a4, 0x1dbd,
+ 0x32a9, 0x1fda,
+ 0x32aa, 0x1fdd,
+ 0x32ab, 0x1fdf,
+ 0x32ac, 0x1fe3,
+ 0x32ad, 0x1fd9,
+ 0x32ae, 0x1fe4,
+ 0x32af, 0x1fdb,
+ 0x32b0, 0x1fd8,
+ 0x3300, 0x1f70,
+ 0x3303, 0x1f6a,
+ 0x3305, 0x1ff7,
+ 0x330d, 0x1dab,
+ 0x3314, 0x1da2,
+ 0x3315, 0x1f69,
+ 0x3316, 0x1f67,
+ 0x3318, 0x1f68,
+ 0x331e, 0x1f73,
+ 0x3322, 0x1f66,
+ 0x3323, 0x1f6b,
+ 0x3326, 0x1dac,
+ 0x3327, 0x1da6,
+ 0x332a, 0x1f74,
+ 0x332b, 0x1dae,
+ 0x3331, 0x1f71,
+ 0x3333, 0x2087,
+ 0x3336, 0x1da8,
+ 0x3339, 0x1f6e,
+ 0x333b, 0x1f6f,
+ 0x3342, 0x1f6d,
+ 0x3347, 0x1f72,
+ 0x3349, 0x1da1,
+ 0x334a, 0x1daf,
+ 0x334d, 0x1da4,
+ 0x334e, 0x2088,
+ 0x3351, 0x1da9,
+ 0x3357, 0x1f6c,
+ 0x337b, 0x2083,
+ 0x337c, 0x1dc7,
+ 0x337d, 0x1dc6,
+ 0x337e, 0x1dc5,
+ 0x337f, 0x1f76,
+ 0x3385, 0x1f5f,
+ 0x3388, 0x2000,
+ 0x338e, 0x1db4,
+ 0x3390, 0x1f63,
+ 0x3396, 0x1f65,
+ 0x3397, 0x1f58,
+ 0x3398, 0x1f5a,
+ 0x339c, 0x1db1,
+ 0x339f, 0x1ffa,
+ 0x33a0, 0x1f54,
+ 0x33a1, 0x1db7,
+ 0x33a2, 0x1f55,
+ 0x33a3, 0x1ffb,
+ 0x33a4, 0x1f56,
+ 0x33a6, 0x1ffc,
+ 0x33b0, 0x1f5e,
+ 0x33b1, 0x1f5d,
+ 0x33b2, 0x1f5c,
+ 0x33b3, 0x1f5b,
+ 0x33c4, 0x1db6,
+ 0x33c8, 0x2002,
+ 0x33cb, 0x1f62,
+ 0x33cc, 0x1ff6,
+ 0x33cd, 0x1dbb,
+ 0x33d4, 0x1f64,
+ 0x4e00, 0x04b0,
+ 0x4e01, 0x0bb8,
+ 0x4e03, 0x08e3,
+ 0x4e07, 0x0eaa,
+ 0x4e08, 0x09ce,
+ 0x4e09, 0x087e,
+ 0x4e0a, 0x09cd,
+ 0x4e0b, 0x053c,
+ 0x4e0d, 0x0dc6,
+ 0x4e0e, 0x0f29,
+ 0x4e10, 0x0ffb,
+ 0x4e11, 0x04d1,
+ 0x4e14, 0x05cc,
+ 0x4e15, 0x0ffc,
+ 0x4e16, 0x0a48,
+ 0x4e17, 0x10d7,
+ 0x4e18, 0x0670,
+ 0x4e19, 0x0e0a,
+ 0x4e1e, 0x09cf,
+ 0x4e21, 0x0f86,
+ 0x4e26, 0x0e12,
+ 0x4e28, 0x20b3,
+ 0x4e2a, 0x0ffd,
+ 0x4e2d, 0x0ba4,
+ 0x4e31, 0x0ffe,
+ 0x4e32, 0x06f2,
+ 0x4e36, 0x0fff,
+ 0x4e38, 0x0619,
+ 0x4e39, 0x0b6e,
+ 0x4e3b, 0x0913,
+ 0x4e3c, 0x1000,
+ 0x4e3f, 0x1001,
+ 0x4e42, 0x1002,
+ 0x4e43, 0x0ceb,
+ 0x4e45, 0x0671,
+ 0x4e4b, 0x0ced,
+ 0x4e4d, 0x0cbb,
+ 0x4e4e, 0x0777,
+ 0x4e4f, 0x0e61,
+ 0x4e55, 0x1950,
+ 0x4e56, 0x1003,
+ 0x4e57, 0x09d0,
+ 0x4e58, 0x1004,
+ 0x4e59, 0x0535,
+ 0x4e5d, 0x06dd,
+ 0x4e5e, 0x07a4,
+ 0x4e5f, 0x0ef5,
+ 0x4e62, 0x1233,
+ 0x4e71, 0x0f5a,
+ 0x4e73, 0x0cd5,
+ 0x4e7e, 0x05e1,
+ 0x4e80, 0x064f,
+ 0x4e82, 0x1005,
+ 0x4e85, 0x1006,
+ 0x4e86, 0x0f83,
+ 0x4e88, 0x0f27,
+ 0x4e89, 0x0aea,
+ 0x4e8a, 0x1008,
+ 0x4e8b, 0x08c4,
+ 0x4e8c, 0x0ccb,
+ 0x4e8e, 0x100b,
+ 0x4e91, 0x04e0,
+ 0x4e92, 0x0793,
+ 0x4e94, 0x0792,
+ 0x4e95, 0x04aa,
+ 0x4e98, 0x0ff1,
+ 0x4e99, 0x0ff0,
+ 0x4e9b, 0x0823,
+ 0x4e9c, 0x0465,
+ 0x4e9e, 0x100c,
+ 0x4ea1, 0x0e62,
+ 0x4ea2, 0x100f,
+ 0x4ea4, 0x07a6,
+ 0x4ea5, 0x04ab,
+ 0x4ea6, 0x0ea0,
+ 0x4ea8, 0x0696,
+ 0x4eab, 0x0697,
+ 0x4ead, 0x0bfe,
+ 0x4eae, 0x0f84,
+ 0x4eb0, 0x1010,
+ 0x4eb3, 0x1011,
+ 0x4eb6, 0x1012,
+ 0x4eba, 0x0a13,
+ 0x4ec0, 0x0944,
+ 0x4ec1, 0x0a14,
+ 0x4ec2, 0x1017,
+ 0x4ec4, 0x1015,
+ 0x4ec6, 0x1016,
+ 0x4ec7, 0x0672,
+ 0x4eca, 0x0813,
+ 0x4ecb, 0x0570,
+ 0x4ecd, 0x1014,
+ 0x4ece, 0x1013,
+ 0x4ecf, 0x0df9,
+ 0x4ed4, 0x0894,
+ 0x4ed5, 0x0893,
+ 0x4ed6, 0x0b1e,
+ 0x4ed7, 0x1018,
+ 0x4ed8, 0x0dc7,
+ 0x4ed9, 0x0a8b,
+ 0x4edd, 0x0290,
+ 0x4ede, 0x1019,
+ 0x4edf, 0x101b,
+ 0x4ee1, 0x20b4,
+ 0x4ee3, 0x0b45,
+ 0x4ee4, 0x0fa9,
+ 0x4ee5, 0x048e,
+ 0x4eed, 0x101a,
+ 0x4eee, 0x053e,
+ 0x4ef0, 0x06bc,
+ 0x4ef2, 0x0ba5,
+ 0x4ef6, 0x0745,
+ 0x4ef7, 0x101c,
+ 0x4efb, 0x0cda,
+ 0x4efc, 0x20b5,
+ 0x4f00, 0x20b6,
+ 0x4f01, 0x0627,
+ 0x4f03, 0x20b7,
+ 0x4f09, 0x101d,
+ 0x4f0a, 0x048f,
+ 0x4f0d, 0x0794,
+ 0x4f0e, 0x0628,
+ 0x4f0f, 0x0dec,
+ 0x4f10, 0x0d46,
+ 0x4f11, 0x0673,
+ 0x4f1a, 0x0571,
+ 0x4f1c, 0x1040,
+ 0x4f1d, 0x0c3b,
+ 0x4f2f, 0x0d22,
+ 0x4f30, 0x101f,
+ 0x4f34, 0x0d50,
+ 0x4f36, 0x0faa,
+ 0x4f38, 0x09f3,
+ 0x4f39, 0x20b8,
+ 0x4f3a, 0x0895,
+ 0x4f3c, 0x08c5,
+ 0x4f3d, 0x0540,
+ 0x4f43, 0x0bed,
+ 0x4f46, 0x0b60,
+ 0x4f47, 0x1023,
+ 0x4f4d, 0x0490,
+ 0x4f4e, 0x0bff,
+ 0x4f4f, 0x0945,
+ 0x4f50, 0x0824,
+ 0x4f51, 0x0f0e,
+ 0x4f53, 0x0b2e,
+ 0x4f55, 0x053f,
+ 0x4f56, 0x20b9,
+ 0x4f57, 0x1022,
+ 0x4f59, 0x0f28,
+ 0x4f5a, 0x101e,
+ 0x4f5b, 0x1020,
+ 0x4f5c, 0x085e,
+ 0x4f5d, 0x1021,
+ 0x4f5e, 0x11d3,
+ 0x4f69, 0x1029,
+ 0x4f6f, 0x102c,
+ 0x4f70, 0x102a,
+ 0x4f73, 0x0542,
+ 0x4f75, 0x0e0b,
+ 0x4f76, 0x1024,
+ 0x4f7b, 0x1028,
+ 0x4f7c, 0x07a7,
+ 0x4f7f, 0x0896,
+ 0x4f83, 0x05e2,
+ 0x4f86, 0x102d,
+ 0x4f88, 0x1025,
+ 0x4f8a, 0x20bb,
+ 0x4f8b, 0x0fab,
+ 0x4f8d, 0x08c6,
+ 0x4f8f, 0x1026,
+ 0x4f91, 0x102b,
+ 0x4f92, 0x20ba,
+ 0x4f94, 0x20bd,
+ 0x4f96, 0x102e,
+ 0x4f98, 0x1027,
+ 0x4f9a, 0x20bc,
+ 0x4f9b, 0x0699,
+ 0x4f9d, 0x0491,
+ 0x4fa0, 0x069a,
+ 0x4fa1, 0x0541,
+ 0x4fab, 0x11d4,
+ 0x4fad, 0x0ea7,
+ 0x4fae, 0x0de0,
+ 0x4faf, 0x07a8,
+ 0x4fb5, 0x09f5,
+ 0x4fb6, 0x0f7f,
+ 0x4fbf, 0x0e28,
+ 0x4fc2, 0x070e,
+ 0x4fc3, 0x0b05,
+ 0x4fc4, 0x0564,
+ 0x4fc9, 0x20ac,
+ 0x4fca, 0x095d,
+ 0x4fcd, 0x20be,
+ 0x4fce, 0x1032,
+ 0x4fd0, 0x1037,
+ 0x4fd1, 0x1035,
+ 0x4fd4, 0x1030,
+ 0x4fd7, 0x0b0f,
+ 0x4fd8, 0x1033,
+ 0x4fda, 0x1036,
+ 0x4fdb, 0x1034,
+ 0x4fdd, 0x0e2d,
+ 0x4fdf, 0x1031,
+ 0x4fe0, 0x1dec,
+ 0x4fe1, 0x09f4,
+ 0x4fe3, 0x0ea1,
+ 0x4fe4, 0x1038,
+ 0x4fee, 0x092e,
+ 0x4fef, 0x1046,
+ 0x4ff3, 0x0d06,
+ 0x4ff5, 0x0da8,
+ 0x4ff6, 0x1041,
+ 0x4ff8, 0x0e40,
+ 0x4ffa, 0x0536,
+ 0x4ffe, 0x1045,
+ 0x4fff, 0x20c1,
+ 0x5005, 0x103f,
+ 0x5006, 0x1048,
+ 0x5009, 0x0ad4,
+ 0x500b, 0x0778,
+ 0x500d, 0x0d12,
+ 0x500f, 0x1600,
+ 0x5011, 0x1047,
+ 0x5012, 0x0c57,
+ 0x5014, 0x103c,
+ 0x5016, 0x07aa,
+ 0x5019, 0x07a9,
+ 0x501a, 0x103a,
+ 0x501e, 0x20c2,
+ 0x501f, 0x0906,
+ 0x5021, 0x1042,
+ 0x5022, 0x20c0,
+ 0x5023, 0x0e3f,
+ 0x5024, 0x0b8b,
+ 0x5025, 0x103e,
+ 0x5026, 0x0747,
+ 0x5028, 0x103b,
+ 0x5029, 0x1043,
+ 0x502a, 0x103d,
+ 0x502b, 0x0f99,
+ 0x502c, 0x1044,
+ 0x502d, 0x0fe7,
+ 0x5036, 0x06de,
+ 0x5039, 0x0746,
+ 0x5040, 0x20bf,
+ 0x5042, 0x20c5,
+ 0x5043, 0x1049,
+ 0x5046, 0x20c3,
+ 0x5047, 0x104a,
+ 0x5048, 0x104e,
+ 0x5049, 0x0492,
+ 0x504f, 0x0e20,
+ 0x5050, 0x104d,
+ 0x5055, 0x104c,
+ 0x5056, 0x1050,
+ 0x505a, 0x104f,
+ 0x505c, 0x0c00,
+ 0x5065, 0x0748,
+ 0x506c, 0x1051,
+ 0x5070, 0x20c4,
+ 0x5072, 0x08f1,
+ 0x5074, 0x0b06,
+ 0x5075, 0x0c01,
+ 0x5076, 0x06ee,
+ 0x5078, 0x1052,
+ 0x507d, 0x0650,
+ 0x5080, 0x1053,
+ 0x5085, 0x1055,
+ 0x508d, 0x0e63,
+ 0x5091, 0x073c,
+ 0x5094, 0x20c6,
+ 0x5098, 0x087f,
+ 0x5099, 0x0d8b,
+ 0x509a, 0x1054,
+ 0x50ac, 0x0835,
+ 0x50ad, 0x0f2d,
+ 0x50b2, 0x1057,
+ 0x50b3, 0x105a,
+ 0x50b4, 0x1056,
+ 0x50b5, 0x0834,
+ 0x50b7, 0x0987,
+ 0x50be, 0x070f,
+ 0x50c2, 0x105b,
+ 0x50c5, 0x06c7,
+ 0x50c9, 0x1058,
+ 0x50cd, 0x0c87,
+ 0x50cf, 0x0afe,
+ 0x50d1, 0x069b,
+ 0x50d5, 0x0e7b,
+ 0x50d6, 0x105c,
+ 0x50d8, 0x20c8,
+ 0x50da, 0x0f85,
+ 0x50de, 0x105d,
+ 0x50e3, 0x1060,
+ 0x50e5, 0x105e,
+ 0x50e7, 0x0ad0,
+ 0x50ed, 0x105f,
+ 0x50ee, 0x1061,
+ 0x50f4, 0x20c7,
+ 0x50f5, 0x1063,
+ 0x50f9, 0x1062,
+ 0x50fb, 0x0e18,
+ 0x5100, 0x0651,
+ 0x5101, 0x1065,
+ 0x5104, 0x052f,
+ 0x5109, 0x1064,
+ 0x5112, 0x0920,
+ 0x5114, 0x1069,
+ 0x5115, 0x1068,
+ 0x5116, 0x1067,
+ 0x5118, 0x102f,
+ 0x511a, 0x106a,
+ 0x511f, 0x0988,
+ 0x5121, 0x106b,
+ 0x512a, 0x0f0f,
+ 0x5132, 0x0ee5,
+ 0x5137, 0x106d,
+ 0x513a, 0x106c,
+ 0x513b, 0x106f,
+ 0x513c, 0x106e,
+ 0x513f, 0x1070,
+ 0x5141, 0x04b8,
+ 0x5143, 0x0769,
+ 0x5144, 0x0711,
+ 0x5145, 0x0946,
+ 0x5146, 0x0bb9,
+ 0x5147, 0x069c,
+ 0x5148, 0x0a8c,
+ 0x5149, 0x07ab,
+ 0x514a, 0x20c9,
+ 0x514b, 0x0800,
+ 0x514c, 0x1073,
+ 0x514d, 0x0ed4,
+ 0x514e, 0x0c40,
+ 0x5150, 0x08c7,
+ 0x5152, 0x1072,
+ 0x5154, 0x1074,
+ 0x515a, 0x0c58,
+ 0x515c, 0x05d3,
+ 0x5162, 0x1075,
+ 0x5164, 0x20ca,
+ 0x5165, 0x0cd6,
+ 0x5168, 0x0ab6,
+ 0x5169, 0x1077,
+ 0x516b, 0x0d40,
+ 0x516c, 0x07ac,
+ 0x516d, 0x0fe1,
+ 0x516e, 0x1079,
+ 0x5171, 0x069e,
+ 0x5175, 0x0e0c,
+ 0x5176, 0x0b16,
+ 0x5177, 0x06e9,
+ 0x5178, 0x0c2f,
+ 0x517c, 0x0749,
+ 0x5180, 0x107a,
+ 0x5182, 0x107b,
+ 0x5185, 0x0cba,
+ 0x5186, 0x0501,
+ 0x5189, 0x107e,
+ 0x518a, 0x086d,
+ 0x518c, 0x107d,
+ 0x518d, 0x0836,
+ 0x518f, 0x107f,
+ 0x5190, 0x185b,
+ 0x5191, 0x1080,
+ 0x5192, 0x0e6f,
+ 0x5193, 0x1081,
+ 0x5195, 0x1082,
+ 0x5197, 0x09d1,
+ 0x5199, 0x08f8,
+ 0x519d, 0x20cb,
+ 0x51a0, 0x05e3,
+ 0x51a2, 0x1086,
+ 0x51a4, 0x1084,
+ 0x51a5, 0x0ec9,
+ 0x51a6, 0x1085,
+ 0x51a8, 0x0dcc,
+ 0x51a9, 0x1087,
+ 0x51ac, 0x0c59,
+ 0x51b0, 0x108d,
+ 0x51b1, 0x108b,
+ 0x51b3, 0x108a,
+ 0x51b4, 0x0853,
+ 0x51b5, 0x108e,
+ 0x51b6, 0x0ef6,
+ 0x51b7, 0x0fac,
+ 0x51bd, 0x108f,
+ 0x51be, 0x20cc,
+ 0x51c4, 0x0a4c,
+ 0x51c5, 0x1090,
+ 0x51c6, 0x0964,
+ 0x51c9, 0x1091,
+ 0x51cb, 0x0bba,
+ 0x51cc, 0x0f87,
+ 0x51cd, 0x0c5a,
+ 0x51d6, 0x10da,
+ 0x51db, 0x1092,
+ 0x51dc, 0x205c,
+ 0x51dd, 0x06bd,
+ 0x51e0, 0x1093,
+ 0x51e1, 0x0e8c,
+ 0x51e6, 0x0972,
+ 0x51e7, 0x0b5c,
+ 0x51e9, 0x1095,
+ 0x51ea, 0x0cbc,
+ 0x51ec, 0x20cd,
+ 0x51ed, 0x1096,
+ 0x51f0, 0x1097,
+ 0x51f1, 0x058c,
+ 0x51f5, 0x1098,
+ 0x51f6, 0x069f,
+ 0x51f8, 0x0ca4,
+ 0x51f9, 0x051c,
+ 0x51fa, 0x095a,
+ 0x51fd, 0x0d35,
+ 0x51fe, 0x1099,
+ 0x5200, 0x0c5b,
+ 0x5203, 0x0a15,
+ 0x5204, 0x109a,
+ 0x5206, 0x0dfc,
+ 0x5207, 0x0a7e,
+ 0x5208, 0x05de,
+ 0x520a, 0x05e5,
+ 0x520b, 0x109b,
+ 0x520e, 0x109d,
+ 0x5211, 0x0710,
+ 0x5214, 0x109c,
+ 0x5215, 0x20ce,
+ 0x5217, 0x0fbb,
+ 0x521d, 0x0973,
+ 0x5224, 0x0d51,
+ 0x5225, 0x0e1c,
+ 0x5227, 0x109e,
+ 0x5229, 0x0f62,
+ 0x522a, 0x109f,
+ 0x522e, 0x10a0,
+ 0x5230, 0x0c78,
+ 0x5233, 0x10a1,
+ 0x5236, 0x0a4d,
+ 0x5237, 0x086e,
+ 0x5238, 0x074a,
+ 0x5239, 0x10a2,
+ 0x523a, 0x0897,
+ 0x523b, 0x0801,
+ 0x5243, 0x0c02,
+ 0x5244, 0x10a4,
+ 0x5247, 0x0b07,
+ 0x524a, 0x085f,
+ 0x524b, 0x10a5,
+ 0x524d, 0x0ab2,
+ 0x524f, 0x10a3,
+ 0x5254, 0x10a8,
+ 0x5256, 0x0e64,
+ 0x525b, 0x07f6,
+ 0x525d, 0x1e5e,
+ 0x525e, 0x10a7,
+ 0x5263, 0x074b,
+ 0x5264, 0x084e,
+ 0x5265, 0x0d23,
+ 0x5269, 0x10ab,
+ 0x526a, 0x10a9,
+ 0x526f, 0x0ded,
+ 0x5270, 0x09d2,
+ 0x5271, 0x10b2,
+ 0x5272, 0x05c2,
+ 0x5273, 0x10ac,
+ 0x5274, 0x10aa,
+ 0x5275, 0x0ad1,
+ 0x527d, 0x10ae,
+ 0x527f, 0x10ad,
+ 0x5283, 0x05a2,
+ 0x5287, 0x0736,
+ 0x5288, 0x10b3,
+ 0x5289, 0x0f75,
+ 0x528d, 0x10af,
+ 0x5291, 0x10b4,
+ 0x5292, 0x10b1,
+ 0x5294, 0x10b0,
+ 0x529b, 0x0f97,
+ 0x529c, 0x20cf,
+ 0x529f, 0x07ad,
+ 0x52a0, 0x0543,
+ 0x52a3, 0x0fbc,
+ 0x52a6, 0x20d0,
+ 0x52a9, 0x097f,
+ 0x52aa, 0x0c52,
+ 0x52ab, 0x07f7,
+ 0x52ac, 0x10b7,
+ 0x52af, 0x217d,
+ 0x52b1, 0x0fad,
+ 0x52b4, 0x0fd1,
+ 0x52b5, 0x10ba,
+ 0x52b9, 0x07ae,
+ 0x52bc, 0x10b9,
+ 0x52be, 0x058d,
+ 0x52c0, 0x20d1,
+ 0x52c1, 0x10bb,
+ 0x52c3, 0x0e84,
+ 0x52c5, 0x0bd8,
+ 0x52c7, 0x0f10,
+ 0x52c9, 0x0e29,
+ 0x52cd, 0x10bc,
+ 0x52d2, 0x1bee,
+ 0x52d5, 0x0c88,
+ 0x52d7, 0x10bd,
+ 0x52d8, 0x05e6,
+ 0x52d9, 0x0ebf,
+ 0x52db, 0x20d2,
+ 0x52dd, 0x0989,
+ 0x52de, 0x10be,
+ 0x52df, 0x0e37,
+ 0x52e0, 0x10c2,
+ 0x52e2, 0x0a4e,
+ 0x52e3, 0x10bf,
+ 0x52e4, 0x06c8,
+ 0x52e6, 0x10c0,
+ 0x52e7, 0x05e7,
+ 0x52f2, 0x0704,
+ 0x52f3, 0x10c3,
+ 0x52f5, 0x10c4,
+ 0x52f8, 0x10c5,
+ 0x52fa, 0x0907,
+ 0x52fe, 0x07af,
+ 0x52ff, 0x0eea,
+ 0x5300, 0x20d3,
+ 0x5301, 0x0ef4,
+ 0x5302, 0x0ccf,
+ 0x5305, 0x0e41,
+ 0x5306, 0x10c7,
+ 0x5307, 0x20d4,
+ 0x5308, 0x10c8,
+ 0x530d, 0x10ca,
+ 0x530f, 0x10cc,
+ 0x5310, 0x10cb,
+ 0x5315, 0x10cd,
+ 0x5316, 0x053d,
+ 0x5317, 0x0e7a,
+ 0x5319, 0x086c,
+ 0x531a, 0x10ce,
+ 0x531d, 0x0adb,
+ 0x5320, 0x098a,
+ 0x5321, 0x06a1,
+ 0x5323, 0x10cf,
+ 0x5324, 0x20d5,
+ 0x532a, 0x0d6f,
+ 0x532f, 0x10d0,
+ 0x5331, 0x10d1,
+ 0x5333, 0x10d2,
+ 0x5338, 0x10d3,
+ 0x5339, 0x0d96,
+ 0x533a, 0x06e0,
+ 0x533b, 0x04a9,
+ 0x533f, 0x0c97,
+ 0x5340, 0x10d4,
+ 0x5341, 0x0947,
+ 0x5343, 0x0a8d,
+ 0x5345, 0x10d6,
+ 0x5346, 0x10d5,
+ 0x5347, 0x098b,
+ 0x5348, 0x0795,
+ 0x5349, 0x10d8,
+ 0x534a, 0x0d52,
+ 0x534d, 0x10d9,
+ 0x5351, 0x0d70,
+ 0x5352, 0x0b14,
+ 0x5353, 0x0b4e,
+ 0x5354, 0x06a0,
+ 0x5357, 0x0cc6,
+ 0x5358, 0x0b6f,
+ 0x535a, 0x0d24,
+ 0x535c, 0x0e7c,
+ 0x535e, 0x10db,
+ 0x5360, 0x0a8e,
+ 0x5366, 0x070b,
+ 0x5369, 0x10dc,
+ 0x536e, 0x10dd,
+ 0x536f, 0x04ce,
+ 0x5370, 0x04b9,
+ 0x5371, 0x0629,
+ 0x5372, 0x20d6,
+ 0x5373, 0x0b08,
+ 0x5374, 0x066b,
+ 0x5375, 0x0f5b,
+ 0x5377, 0x10e0,
+ 0x5378, 0x0537,
+ 0x537b, 0x10df,
+ 0x537f, 0x06a2,
+ 0x5382, 0x10e1,
+ 0x5384, 0x0efd,
+ 0x5393, 0x20d7,
+ 0x5396, 0x10e2,
+ 0x5398, 0x0f9a,
+ 0x539a, 0x07b0,
+ 0x539f, 0x076a,
+ 0x53a0, 0x10e3,
+ 0x53a5, 0x10e5,
+ 0x53a6, 0x10e4,
+ 0x53a8, 0x0a25,
+ 0x53a9, 0x04db,
+ 0x53ad, 0x0500,
+ 0x53ae, 0x10e6,
+ 0x53b0, 0x10e7,
+ 0x53b2, 0x20d8,
+ 0x53b3, 0x076b,
+ 0x53b6, 0x10e8,
+ 0x53bb, 0x0688,
+ 0x53c2, 0x0880,
+ 0x53c3, 0x10e9,
+ 0x53c8, 0x0ea2,
+ 0x53c9, 0x0825,
+ 0x53ca, 0x0674,
+ 0x53cb, 0x0f11,
+ 0x53cc, 0x0ad2,
+ 0x53cd, 0x0d53,
+ 0x53ce, 0x0929,
+ 0x53d4, 0x0951,
+ 0x53d6, 0x0914,
+ 0x53d7, 0x0921,
+ 0x53d9, 0x0980,
+ 0x53db, 0x0d54,
+ 0x53dd, 0x20d9,
+ 0x53df, 0x10ec,
+ 0x53e1, 0x04e5,
+ 0x53e2, 0x0ad3,
+ 0x53e3, 0x07b1,
+ 0x53e4, 0x0779,
+ 0x53e5, 0x06df,
+ 0x53e8, 0x10f0,
+ 0x53e9, 0x0b5f,
+ 0x53ea, 0x0b5e,
+ 0x53eb, 0x06a3,
+ 0x53ec, 0x098c,
+ 0x53ed, 0x10f1,
+ 0x53ee, 0x10ef,
+ 0x53ef, 0x0544,
+ 0x53f0, 0x0b46,
+ 0x53f1, 0x08e4,
+ 0x53f2, 0x0899,
+ 0x53f3, 0x04c8,
+ 0x53f6, 0x05ce,
+ 0x53f7, 0x07f8,
+ 0x53f8, 0x0898,
+ 0x53fa, 0x10f2,
+ 0x5401, 0x10f3,
+ 0x5403, 0x0663,
+ 0x5404, 0x05a4,
+ 0x5408, 0x07f9,
+ 0x5409, 0x0662,
+ 0x540a, 0x0bfb,
+ 0x540b, 0x04c7,
+ 0x540c, 0x0c89,
+ 0x540d, 0x0eca,
+ 0x540e, 0x07b3,
+ 0x540f, 0x0f63,
+ 0x5410, 0x0c41,
+ 0x5411, 0x07b2,
+ 0x541b, 0x0705,
+ 0x541d, 0x10fc,
+ 0x541f, 0x06db,
+ 0x5420, 0x0e78,
+ 0x5426, 0x0d71,
+ 0x5429, 0x10fb,
+ 0x542b, 0x061a,
+ 0x542c, 0x10f6,
+ 0x542e, 0x10f9,
+ 0x5436, 0x10fa,
+ 0x5438, 0x0675,
+ 0x5439, 0x0a27,
+ 0x543b, 0x0dfd,
+ 0x543c, 0x10f8,
+ 0x543d, 0x10f4,
+ 0x543e, 0x0797,
+ 0x5440, 0x10f5,
+ 0x5442, 0x0fca,
+ 0x5446, 0x0e42,
+ 0x5448, 0x0c04,
+ 0x5449, 0x0796,
+ 0x544a, 0x0802,
+ 0x544e, 0x10fd,
+ 0x5451, 0x0cb5,
+ 0x545f, 0x1101,
+ 0x5468, 0x092a,
+ 0x546a, 0x0922,
+ 0x5470, 0x1104,
+ 0x5471, 0x1102,
+ 0x5473, 0x0eaf,
+ 0x5475, 0x10ff,
+ 0x5476, 0x1108,
+ 0x5477, 0x1103,
+ 0x547b, 0x1106,
+ 0x547c, 0x077a,
+ 0x547d, 0x0ecb,
+ 0x5480, 0x1107,
+ 0x5484, 0x1109,
+ 0x5486, 0x110b,
+ 0x548a, 0x20dc,
+ 0x548b, 0x0860,
+ 0x548c, 0x0fe8,
+ 0x548e, 0x1100,
+ 0x548f, 0x10fe,
+ 0x5490, 0x110a,
+ 0x5492, 0x1105,
+ 0x549c, 0x20db,
+ 0x54a2, 0x110d,
+ 0x54a4, 0x1116,
+ 0x54a5, 0x110f,
+ 0x54a8, 0x1113,
+ 0x54a9, 0x20dd,
+ 0x54ab, 0x1114,
+ 0x54ac, 0x1110,
+ 0x54af, 0x1131,
+ 0x54b2, 0x0859,
+ 0x54b3, 0x058f,
+ 0x54b8, 0x110e,
+ 0x54bc, 0x1118,
+ 0x54bd, 0x04ba,
+ 0x54be, 0x1117,
+ 0x54c0, 0x0469,
+ 0x54c1, 0x0dbc,
+ 0x54c2, 0x1115,
+ 0x54c4, 0x1111,
+ 0x54c7, 0x110c,
+ 0x54c8, 0x1112,
+ 0x54c9, 0x0838,
+ 0x54d8, 0x1119,
+ 0x54e1, 0x04bb,
+ 0x54e2, 0x1122,
+ 0x54e5, 0x111a,
+ 0x54e8, 0x098d,
+ 0x54e9, 0x0e97,
+ 0x54ed, 0x1120,
+ 0x54ee, 0x111f,
+ 0x54f2, 0x0c29,
+ 0x54fa, 0x1121,
+ 0x54fd, 0x111e,
+ 0x54ff, 0x20de,
+ 0x5504, 0x04d6,
+ 0x5506, 0x0826,
+ 0x5507, 0x09f6,
+ 0x550f, 0x111c,
+ 0x5510, 0x0c5c,
+ 0x5514, 0x111d,
+ 0x5516, 0x0466,
+ 0x552e, 0x1127,
+ 0x552f, 0x0f0d,
+ 0x5531, 0x098f,
+ 0x5533, 0x112d,
+ 0x5538, 0x112c,
+ 0x5539, 0x1123,
+ 0x553e, 0x0b23,
+ 0x5540, 0x1124,
+ 0x5544, 0x0b4f,
+ 0x5545, 0x1129,
+ 0x5546, 0x098e,
+ 0x554c, 0x1126,
+ 0x554f, 0x0ef0,
+ 0x5553, 0x0712,
+ 0x5556, 0x112a,
+ 0x555c, 0x1128,
+ 0x555d, 0x112e,
+ 0x555e, 0x1dd1,
+ 0x5563, 0x1125,
+ 0x557b, 0x1134,
+ 0x557c, 0x1139,
+ 0x557e, 0x1135,
+ 0x5580, 0x1130,
+ 0x5583, 0x113a,
+ 0x5584, 0x0ab3,
+ 0x5586, 0x20df,
+ 0x5587, 0x113c,
+ 0x5589, 0x07b4,
+ 0x558a, 0x1132,
+ 0x558b, 0x0bbb,
+ 0x5598, 0x1136,
+ 0x5599, 0x112f,
+ 0x559a, 0x05e9,
+ 0x559c, 0x062a,
+ 0x559d, 0x05c3,
+ 0x559e, 0x1137,
+ 0x559f, 0x1133,
+ 0x55a7, 0x074c,
+ 0x55a8, 0x113d,
+ 0x55a9, 0x113b,
+ 0x55aa, 0x0ad5,
+ 0x55ab, 0x0664,
+ 0x55ac, 0x06a4,
+ 0x55ae, 0x1138,
+ 0x55b0, 0x06ec,
+ 0x55b6, 0x04e6,
+ 0x55c4, 0x1141,
+ 0x55c5, 0x113f,
+ 0x55c7, 0x1178,
+ 0x55d4, 0x1144,
+ 0x55da, 0x113e,
+ 0x55dc, 0x1142,
+ 0x55df, 0x1140,
+ 0x55e3, 0x089a,
+ 0x55e4, 0x1143,
+ 0x55f7, 0x1146,
+ 0x55f9, 0x114b,
+ 0x55fd, 0x1149,
+ 0x55fe, 0x1148,
+ 0x5606, 0x0b70,
+ 0x5609, 0x0545,
+ 0x5614, 0x1145,
+ 0x5616, 0x1147,
+ 0x5617, 0x0990,
+ 0x5618, 0x04d5,
+ 0x561b, 0x114a,
+ 0x5629, 0x055e,
+ 0x562f, 0x1155,
+ 0x5631, 0x09e4,
+ 0x5632, 0x1151,
+ 0x5634, 0x114f,
+ 0x5636, 0x1150,
+ 0x5638, 0x1152,
+ 0x5642, 0x04df,
+ 0x564c, 0x0abb,
+ 0x564e, 0x114c,
+ 0x5650, 0x114d,
+ 0x5653, 0x1f1b,
+ 0x565b, 0x05d8,
+ 0x5664, 0x1154,
+ 0x5668, 0x062b,
+ 0x566a, 0x1157,
+ 0x566b, 0x1153,
+ 0x566c, 0x1156,
+ 0x5674, 0x0dfe,
+ 0x5678, 0x0cad,
+ 0x567a, 0x0d4c,
+ 0x5680, 0x1159,
+ 0x5686, 0x1158,
+ 0x5687, 0x05a3,
+ 0x568a, 0x115a,
+ 0x568f, 0x115d,
+ 0x5694, 0x115c,
+ 0x5699, 0x1de6,
+ 0x56a0, 0x115b,
+ 0x56a2, 0x0cef,
+ 0x56a5, 0x115e,
+ 0x56ae, 0x115f,
+ 0x56b4, 0x1161,
+ 0x56b6, 0x1160,
+ 0x56bc, 0x1163,
+ 0x56c0, 0x1166,
+ 0x56c1, 0x1164,
+ 0x56c2, 0x1162,
+ 0x56c3, 0x1165,
+ 0x56c8, 0x1167,
+ 0x56ca, 0x1e5a,
+ 0x56ce, 0x1168,
+ 0x56d1, 0x1169,
+ 0x56d3, 0x116a,
+ 0x56d7, 0x116b,
+ 0x56d8, 0x107c,
+ 0x56da, 0x0928,
+ 0x56db, 0x089b,
+ 0x56de, 0x0573,
+ 0x56e0, 0x04bc,
+ 0x56e3, 0x0b82,
+ 0x56ee, 0x116c,
+ 0x56f0, 0x0814,
+ 0x56f2, 0x0493,
+ 0x56f3, 0x0a24,
+ 0x56f9, 0x116d,
+ 0x56fa, 0x077b,
+ 0x56fd, 0x0803,
+ 0x56ff, 0x116f,
+ 0x5700, 0x116e,
+ 0x5703, 0x0e30,
+ 0x5704, 0x1170,
+ 0x5708, 0x1172,
+ 0x5709, 0x1171,
+ 0x570b, 0x1173,
+ 0x570d, 0x1174,
+ 0x570f, 0x074d,
+ 0x5712, 0x0502,
+ 0x5713, 0x1175,
+ 0x5716, 0x1177,
+ 0x5718, 0x1176,
+ 0x571c, 0x1179,
+ 0x571f, 0x0c54,
+ 0x5726, 0x117a,
+ 0x5727, 0x0479,
+ 0x5728, 0x084f,
+ 0x572d, 0x0713,
+ 0x5730, 0x0b8d,
+ 0x5737, 0x117b,
+ 0x573b, 0x117e,
+ 0x5740, 0x117f,
+ 0x5742, 0x0854,
+ 0x5747, 0x06c9,
+ 0x574a, 0x0e65,
+ 0x574e, 0x117d,
+ 0x574f, 0x1180,
+ 0x5750, 0x0831,
+ 0x5751, 0x07b5,
+ 0x5759, 0x20e0,
+ 0x5761, 0x1184,
+ 0x5764, 0x0815,
+ 0x5765, 0x20e1,
+ 0x5766, 0x0b71,
+ 0x5769, 0x1181,
+ 0x576a, 0x0bf6,
+ 0x577f, 0x1185,
+ 0x5782, 0x0a28,
+ 0x5788, 0x1183,
+ 0x5789, 0x1186,
+ 0x578b, 0x0715,
+ 0x5793, 0x1187,
+ 0x57a0, 0x1188,
+ 0x57a2, 0x07b6,
+ 0x57a3, 0x059e,
+ 0x57a4, 0x118a,
+ 0x57aa, 0x118b,
+ 0x57ac, 0x20e2,
+ 0x57b0, 0x118c,
+ 0x57b3, 0x1189,
+ 0x57c0, 0x1182,
+ 0x57c3, 0x118d,
+ 0x57c6, 0x118e,
+ 0x57c7, 0x20e4,
+ 0x57c8, 0x20e3,
+ 0x57cb, 0x0e92,
+ 0x57ce, 0x09d3,
+ 0x57d2, 0x1190,
+ 0x57d4, 0x118f,
+ 0x57d6, 0x1193,
+ 0x57dc, 0x0cee,
+ 0x57df, 0x04ac,
+ 0x57e0, 0x0dc8,
+ 0x57e3, 0x1194,
+ 0x57f4, 0x09e5,
+ 0x57f7, 0x08e5,
+ 0x57f9, 0x0d13,
+ 0x57fa, 0x062c,
+ 0x57fc, 0x085b,
+ 0x5800, 0x0e87,
+ 0x5802, 0x0c8a,
+ 0x5805, 0x074e,
+ 0x5806, 0x0b2f,
+ 0x580a, 0x1192,
+ 0x580b, 0x1195,
+ 0x5815, 0x0b24,
+ 0x5819, 0x1196,
+ 0x581d, 0x1197,
+ 0x5821, 0x1199,
+ 0x5824, 0x0c05,
+ 0x582a, 0x05ea,
+ 0x582f, 0x1d32,
+ 0x5830, 0x0503,
+ 0x5831, 0x0e43,
+ 0x5834, 0x09d4,
+ 0x5835, 0x0c42,
+ 0x583a, 0x0856,
+ 0x583d, 0x119f,
+ 0x5840, 0x0e0d,
+ 0x5841, 0x0fa5,
+ 0x584a, 0x0574,
+ 0x584b, 0x119b,
+ 0x5851, 0x0abc,
+ 0x5852, 0x119e,
+ 0x5854, 0x0c5d,
+ 0x5857, 0x0c43,
+ 0x5858, 0x0c5e,
+ 0x5859, 0x0d4d,
+ 0x585a, 0x0be9,
+ 0x585e, 0x0839,
+ 0x5861, 0x1e47,
+ 0x5862, 0x119a,
+ 0x5869, 0x0518,
+ 0x586b, 0x0c30,
+ 0x5870, 0x119c,
+ 0x5872, 0x1198,
+ 0x5875, 0x0a16,
+ 0x5879, 0x11a0,
+ 0x587e, 0x0958,
+ 0x5883, 0x06a5,
+ 0x5885, 0x11a1,
+ 0x5893, 0x0e38,
+ 0x5897, 0x0aff,
+ 0x589c, 0x0be2,
+ 0x589e, 0x20e7,
+ 0x589f, 0x11a3,
+ 0x58a8, 0x0e7d,
+ 0x58ab, 0x11a4,
+ 0x58ae, 0x11a9,
+ 0x58b2, 0x20e8,
+ 0x58b3, 0x0dff,
+ 0x58b8, 0x11a8,
+ 0x58b9, 0x11a2,
+ 0x58ba, 0x11a5,
+ 0x58bb, 0x11a7,
+ 0x58be, 0x0816,
+ 0x58c1, 0x0e19,
+ 0x58c5, 0x11aa,
+ 0x58c7, 0x0b83,
+ 0x58ca, 0x0575,
+ 0x58cc, 0x09d5,
+ 0x58d1, 0x11ac,
+ 0x58d3, 0x11ab,
+ 0x58d5, 0x07fa,
+ 0x58d7, 0x11ad,
+ 0x58d8, 0x11af,
+ 0x58d9, 0x11ae,
+ 0x58dc, 0x11b1,
+ 0x58de, 0x11a6,
+ 0x58df, 0x11b3,
+ 0x58e4, 0x11b2,
+ 0x58e5, 0x11b0,
+ 0x58eb, 0x089c,
+ 0x58ec, 0x0a17,
+ 0x58ee, 0x0ad6,
+ 0x58ef, 0x11b4,
+ 0x58f0, 0x0a60,
+ 0x58f1, 0x04b1,
+ 0x58f2, 0x0d1a,
+ 0x58f7, 0x0bf7,
+ 0x58f9, 0x11b6,
+ 0x58fa, 0x11b5,
+ 0x58fb, 0x11b7,
+ 0x5902, 0x11ba,
+ 0x5909, 0x0e21,
+ 0x590a, 0x11bb,
+ 0x590b, 0x20e9,
+ 0x590f, 0x0546,
+ 0x5910, 0x11bc,
+ 0x5915, 0x0f26,
+ 0x5916, 0x058e,
+ 0x5918, 0x10de,
+ 0x5919, 0x0952,
+ 0x591a, 0x0b1f,
+ 0x591b, 0x11bd,
+ 0x591c, 0x0ef7,
+ 0x5922, 0x0ec0,
+ 0x5925, 0x11bf,
+ 0x5927, 0x0b47,
+ 0x5929, 0x0c31,
+ 0x592a, 0x0b20,
+ 0x592b, 0x0dc9,
+ 0x592c, 0x11c0,
+ 0x592e, 0x051d,
+ 0x5931, 0x08e6,
+ 0x5932, 0x11c2,
+ 0x5937, 0x0494,
+ 0x5938, 0x11c3,
+ 0x593e, 0x11c4,
+ 0x5944, 0x0504,
+ 0x5947, 0x062d,
+ 0x5948, 0x0cb8,
+ 0x5949, 0x0e44,
+ 0x594e, 0x11c8,
+ 0x594f, 0x0ad7,
+ 0x5950, 0x11c7,
+ 0x5951, 0x0716,
+ 0x5953, 0x20ea,
+ 0x5954, 0x0e89,
+ 0x5955, 0x11c6,
+ 0x5957, 0x0c5f,
+ 0x5958, 0x11ca,
+ 0x595a, 0x11c9,
+ 0x595b, 0x20eb,
+ 0x595d, 0x20ec,
+ 0x5960, 0x11cc,
+ 0x5962, 0x11cb,
+ 0x5963, 0x20ed,
+ 0x5965, 0x051e,
+ 0x5967, 0x11cd,
+ 0x5968, 0x0991,
+ 0x5969, 0x11cf,
+ 0x596a, 0x0b63,
+ 0x596c, 0x11ce,
+ 0x596e, 0x0e03,
+ 0x5973, 0x0981,
+ 0x5974, 0x0c55,
+ 0x5978, 0x11d0,
+ 0x597d, 0x07b7,
+ 0x5981, 0x11d1,
+ 0x5982, 0x0cd7,
+ 0x5983, 0x0d72,
+ 0x5984, 0x0edd,
+ 0x598a, 0x0cdb,
+ 0x598d, 0x11da,
+ 0x5993, 0x0652,
+ 0x5996, 0x0f2f,
+ 0x5999, 0x0ebb,
+ 0x599b, 0x1239,
+ 0x599d, 0x11d2,
+ 0x59a3, 0x11d5,
+ 0x59a4, 0x20ee,
+ 0x59a5, 0x0b25,
+ 0x59a8, 0x0e66,
+ 0x59ac, 0x0c44,
+ 0x59b2, 0x11d6,
+ 0x59b9, 0x0e93,
+ 0x59ba, 0x20ef,
+ 0x59bb, 0x083a,
+ 0x59be, 0x0992,
+ 0x59c6, 0x11d7,
+ 0x59c9, 0x089e,
+ 0x59cb, 0x089d,
+ 0x59d0, 0x047d,
+ 0x59d1, 0x077c,
+ 0x59d3, 0x0a4f,
+ 0x59d4, 0x0495,
+ 0x59d9, 0x11db,
+ 0x59dc, 0x11d9,
+ 0x59e5, 0x04da,
+ 0x59e6, 0x05eb,
+ 0x59e8, 0x11d8,
+ 0x59ea, 0x0ed1,
+ 0x59eb, 0x0da3,
+ 0x59f6, 0x046c,
+ 0x59fb, 0x04bd,
+ 0x59ff, 0x089f,
+ 0x5a01, 0x0496,
+ 0x5a03, 0x0467,
+ 0x5a09, 0x11e1,
+ 0x5a11, 0x11df,
+ 0x5a18, 0x0ec8,
+ 0x5a1a, 0x11e2,
+ 0x5a1c, 0x11e0,
+ 0x5a1f, 0x11de,
+ 0x5a20, 0x09f7,
+ 0x5a25, 0x11dd,
+ 0x5a29, 0x0e2a,
+ 0x5a2f, 0x0798,
+ 0x5a35, 0x11e6,
+ 0x5a3c, 0x0993,
+ 0x5a40, 0x11e3,
+ 0x5a41, 0x0fd2,
+ 0x5a46, 0x0d02,
+ 0x5a49, 0x11e5,
+ 0x5a5a, 0x0817,
+ 0x5a62, 0x11e8,
+ 0x5a66, 0x0dca,
+ 0x5a6a, 0x11e9,
+ 0x5a6c, 0x11e4,
+ 0x5a7f, 0x0ec7,
+ 0x5a92, 0x0d14,
+ 0x5a9a, 0x11ea,
+ 0x5a9b, 0x0da4,
+ 0x5abc, 0x11eb,
+ 0x5abd, 0x11ef,
+ 0x5abe, 0x11ec,
+ 0x5ac1, 0x0547,
+ 0x5ac2, 0x11ee,
+ 0x5ac9, 0x08e7,
+ 0x5acb, 0x11ed,
+ 0x5acc, 0x074f,
+ 0x5ad0, 0x11fb,
+ 0x5ad6, 0x11f4,
+ 0x5ad7, 0x11f1,
+ 0x5ae1, 0x0ba2,
+ 0x5ae3, 0x11f0,
+ 0x5ae6, 0x11f2,
+ 0x5ae9, 0x11f3,
+ 0x5afa, 0x11f5,
+ 0x5b09, 0x062e,
+ 0x5b0b, 0x11f8,
+ 0x5b0c, 0x11f7,
+ 0x5b16, 0x11f9,
+ 0x5b22, 0x09d6,
+ 0x5b2a, 0x11fc,
+ 0x5b2c, 0x0bf8,
+ 0x5b30, 0x04e7,
+ 0x5b32, 0x11fa,
+ 0x5b36, 0x11fd,
+ 0x5b3e, 0x11fe,
+ 0x5b40, 0x1201,
+ 0x5b43, 0x11ff,
+ 0x5b45, 0x1200,
+ 0x5b50, 0x08a0,
+ 0x5b51, 0x1202,
+ 0x5b54, 0x07b8,
+ 0x5b55, 0x1203,
+ 0x5b56, 0x20f0,
+ 0x5b57, 0x08c8,
+ 0x5b58, 0x0b18,
+ 0x5b5a, 0x1204,
+ 0x5b5c, 0x08a8,
+ 0x5b5d, 0x07b9,
+ 0x5b5f, 0x0ede,
+ 0x5b63, 0x0642,
+ 0x5b64, 0x077d,
+ 0x5b65, 0x1206,
+ 0x5b66, 0x05b6,
+ 0x5b69, 0x1207,
+ 0x5b6b, 0x0b19,
+ 0x5b70, 0x1208,
+ 0x5b71, 0x1230,
+ 0x5b73, 0x1209,
+ 0x5b75, 0x120a,
+ 0x5b78, 0x120b,
+ 0x5b7a, 0x120d,
+ 0x5b80, 0x120e,
+ 0x5b83, 0x120f,
+ 0x5b85, 0x0b50,
+ 0x5b87, 0x04c9,
+ 0x5b88, 0x0915,
+ 0x5b89, 0x0486,
+ 0x5b8b, 0x0ad9,
+ 0x5b8c, 0x05ec,
+ 0x5b8d, 0x08e1,
+ 0x5b8f, 0x07ba,
+ 0x5b95, 0x0c60,
+ 0x5b97, 0x092b,
+ 0x5b98, 0x05ed,
+ 0x5b99, 0x0ba6,
+ 0x5b9a, 0x0c06,
+ 0x5b9b, 0x047c,
+ 0x5b9c, 0x0653,
+ 0x5b9d, 0x0e45,
+ 0x5b9f, 0x08ee,
+ 0x5ba2, 0x066c,
+ 0x5ba3, 0x0a8f,
+ 0x5ba4, 0x08e8,
+ 0x5ba5, 0x0f12,
+ 0x5ba6, 0x1210,
+ 0x5bae, 0x0676,
+ 0x5bb0, 0x083b,
+ 0x5bb3, 0x0590,
+ 0x5bb4, 0x0505,
+ 0x5bb5, 0x0994,
+ 0x5bb6, 0x0548,
+ 0x5bb8, 0x1211,
+ 0x5bb9, 0x0f30,
+ 0x5bbf, 0x0953,
+ 0x5bc0, 0x20f1,
+ 0x5bc2, 0x0910,
+ 0x5bc3, 0x1212,
+ 0x5bc4, 0x062f,
+ 0x5bc5, 0x0caa,
+ 0x5bc6, 0x0eb5,
+ 0x5bc7, 0x1213,
+ 0x5bc9, 0x1214,
+ 0x5bcc, 0x0dcb,
+ 0x5bd0, 0x1216,
+ 0x5bd2, 0x05e4,
+ 0x5bd3, 0x06ef,
+ 0x5bd4, 0x1215,
+ 0x5bd8, 0x20f3,
+ 0x5bdb, 0x05ee,
+ 0x5bdd, 0x09f8,
+ 0x5bde, 0x121a,
+ 0x5bdf, 0x086f,
+ 0x5be1, 0x0549,
+ 0x5be2, 0x1219,
+ 0x5be4, 0x1217,
+ 0x5be5, 0x121b,
+ 0x5be6, 0x1218,
+ 0x5be7, 0x0ce1,
+ 0x5be8, 0x148e,
+ 0x5be9, 0x09f9,
+ 0x5beb, 0x121c,
+ 0x5bec, 0x20f4,
+ 0x5bee, 0x0f88,
+ 0x5bf0, 0x121d,
+ 0x5bf3, 0x121f,
+ 0x5bf5, 0x0bbc,
+ 0x5bf6, 0x121e,
+ 0x5bf8, 0x0a47,
+ 0x5bfa, 0x08c9,
+ 0x5bfe, 0x0b30,
+ 0x5bff, 0x0923,
+ 0x5c01, 0x0de7,
+ 0x5c02, 0x0a90,
+ 0x5c04, 0x08f9,
+ 0x5c05, 0x1220,
+ 0x5c06, 0x0995,
+ 0x5c07, 0x1221,
+ 0x5c09, 0x0497,
+ 0x5c0a, 0x0b1a,
+ 0x5c0b, 0x0a18,
+ 0x5c0d, 0x1223,
+ 0x5c0e, 0x0c8b,
+ 0x5c0f, 0x0996,
+ 0x5c11, 0x0997,
+ 0x5c13, 0x1224,
+ 0x5c16, 0x0a91,
+ 0x5c1a, 0x0998,
+ 0x5c1e, 0x20f5,
+ 0x5c20, 0x1225,
+ 0x5c22, 0x1226,
+ 0x5c24, 0x0eec,
+ 0x5c28, 0x1227,
+ 0x5c2d, 0x06be,
+ 0x5c31, 0x092c,
+ 0x5c38, 0x1228,
+ 0x5c3a, 0x0908,
+ 0x5c3b, 0x09f2,
+ 0x5c3c, 0x0ccc,
+ 0x5c3d, 0x0a1a,
+ 0x5c3e, 0x0d8c,
+ 0x5c3f, 0x0cd8,
+ 0x5c40, 0x06c1,
+ 0x5c41, 0x122a,
+ 0x5c45, 0x0689,
+ 0x5c46, 0x122b,
+ 0x5c48, 0x06f6,
+ 0x5c4a, 0x0ca7,
+ 0x5c4b, 0x0530,
+ 0x5c4d, 0x08a1,
+ 0x5c4e, 0x122c,
+ 0x5c4f, 0x122f,
+ 0x5c50, 0x122e,
+ 0x5c51, 0x06f5,
+ 0x5c53, 0x122d,
+ 0x5c55, 0x0c32,
+ 0x5c5b, 0x1e92,
+ 0x5c5e, 0x0b10,
+ 0x5c60, 0x0c45,
+ 0x5c61, 0x08f4,
+ 0x5c62, 0x1e0d,
+ 0x5c64, 0x0ada,
+ 0x5c65, 0x0f64,
+ 0x5c6c, 0x1231,
+ 0x5c6e, 0x1232,
+ 0x5c6f, 0x0cae,
+ 0x5c71, 0x0881,
+ 0x5c76, 0x1234,
+ 0x5c79, 0x1235,
+ 0x5c8c, 0x1236,
+ 0x5c90, 0x0630,
+ 0x5c91, 0x1237,
+ 0x5c94, 0x1238,
+ 0x5ca1, 0x052c,
+ 0x5ca6, 0x20f6,
+ 0x5ca8, 0x0abd,
+ 0x5ca9, 0x0620,
+ 0x5cab, 0x123a,
+ 0x5cac, 0x0eb4,
+ 0x5cb1, 0x0b32,
+ 0x5cb3, 0x05b7,
+ 0x5cb6, 0x123c,
+ 0x5cb7, 0x123e,
+ 0x5cb8, 0x061b,
+ 0x5cba, 0x20f7,
+ 0x5cbb, 0x123b,
+ 0x5cbc, 0x123d,
+ 0x5cbe, 0x1240,
+ 0x5cc5, 0x123f,
+ 0x5cc7, 0x1241,
+ 0x5cd9, 0x1242,
+ 0x5ce0, 0x0c95,
+ 0x5ce1, 0x06a6,
+ 0x5ce8, 0x0565,
+ 0x5ce9, 0x1243,
+ 0x5cea, 0x1248,
+ 0x5ced, 0x1246,
+ 0x5cef, 0x0e47,
+ 0x5cf0, 0x0e46,
+ 0x5cf5, 0x20f8,
+ 0x5cf6, 0x0c61,
+ 0x5cfa, 0x1245,
+ 0x5cfb, 0x095e,
+ 0x5cfd, 0x1244,
+ 0x5d07, 0x0a38,
+ 0x5d0b, 0x1249,
+ 0x5d0e, 0x085a,
+ 0x5d11, 0x124f,
+ 0x5d14, 0x1250,
+ 0x5d15, 0x124a,
+ 0x5d16, 0x0591,
+ 0x5d17, 0x124b,
+ 0x5d18, 0x1254,
+ 0x5d19, 0x1253,
+ 0x5d1a, 0x1252,
+ 0x5d1b, 0x124e,
+ 0x5d1f, 0x124d,
+ 0x5d22, 0x1251,
+ 0x5d27, 0x20f9,
+ 0x5d29, 0x0e48,
+ 0x5d42, 0x20fc,
+ 0x5d4b, 0x1258,
+ 0x5d4c, 0x1255,
+ 0x5d4e, 0x1257,
+ 0x5d50, 0x0f5c,
+ 0x5d52, 0x1256,
+ 0x5d53, 0x20fa,
+ 0x5d5c, 0x124c,
+ 0x5d69, 0x0a39,
+ 0x5d6c, 0x1259,
+ 0x5d6d, 0x20fd,
+ 0x5d6f, 0x0827,
+ 0x5d73, 0x125a,
+ 0x5d76, 0x125b,
+ 0x5d82, 0x125e,
+ 0x5d84, 0x125d,
+ 0x5d87, 0x125c,
+ 0x5d8b, 0x0c62,
+ 0x5d8c, 0x1247,
+ 0x5d90, 0x1264,
+ 0x5d9d, 0x1260,
+ 0x5da2, 0x125f,
+ 0x5dac, 0x1261,
+ 0x5dae, 0x1262,
+ 0x5db7, 0x1265,
+ 0x5db8, 0x20fe,
+ 0x5dba, 0x0fae,
+ 0x5dbc, 0x1266,
+ 0x5dbd, 0x1263,
+ 0x5dc9, 0x1267,
+ 0x5dcc, 0x061c,
+ 0x5dcd, 0x1268,
+ 0x5dd0, 0x2100,
+ 0x5dd2, 0x126a,
+ 0x5dd3, 0x1269,
+ 0x5dd6, 0x126b,
+ 0x5ddb, 0x126c,
+ 0x5ddd, 0x0a92,
+ 0x5dde, 0x092d,
+ 0x5de1, 0x096e,
+ 0x5de3, 0x0ae5,
+ 0x5de5, 0x07bb,
+ 0x5de6, 0x0828,
+ 0x5de7, 0x07bc,
+ 0x5de8, 0x068a,
+ 0x5deb, 0x126d,
+ 0x5dee, 0x0829,
+ 0x5df1, 0x077e,
+ 0x5df2, 0x126e,
+ 0x5df3, 0x0eb2,
+ 0x5df4, 0x0cf9,
+ 0x5df5, 0x126f,
+ 0x5df7, 0x07bd,
+ 0x5dfb, 0x05e8,
+ 0x5dfd, 0x0b65,
+ 0x5dfe, 0x06ca,
+ 0x5e02, 0x08a2,
+ 0x5e03, 0x0dcd,
+ 0x5e06, 0x0d55,
+ 0x5e0b, 0x1270,
+ 0x5e0c, 0x0631,
+ 0x5e11, 0x1273,
+ 0x5e16, 0x0bbd,
+ 0x5e19, 0x1272,
+ 0x5e1a, 0x1271,
+ 0x5e1b, 0x1274,
+ 0x5e1d, 0x0c07,
+ 0x5e25, 0x0a29,
+ 0x5e2b, 0x08a3,
+ 0x5e2d, 0x0a6e,
+ 0x5e2f, 0x0b33,
+ 0x5e30, 0x063c,
+ 0x5e33, 0x0bbe,
+ 0x5e36, 0x1275,
+ 0x5e38, 0x09d7,
+ 0x5e3d, 0x0e67,
+ 0x5e40, 0x1279,
+ 0x5e43, 0x1278,
+ 0x5e44, 0x1277,
+ 0x5e45, 0x0def,
+ 0x5e47, 0x1280,
+ 0x5e4c, 0x0e88,
+ 0x5e4e, 0x127a,
+ 0x5e54, 0x127c,
+ 0x5e55, 0x0e99,
+ 0x5e57, 0x127b,
+ 0x5e5f, 0x127d,
+ 0x5e61, 0x0d3c,
+ 0x5e62, 0x127e,
+ 0x5e63, 0x0e0e,
+ 0x5e64, 0x127f,
+ 0x5e72, 0x05ef,
+ 0x5e73, 0x0e0f,
+ 0x5e74, 0x0ce5,
+ 0x5e75, 0x1281,
+ 0x5e78, 0x07be,
+ 0x5e79, 0x05f0,
+ 0x5e7a, 0x1283,
+ 0x5e7b, 0x076c,
+ 0x5e7c, 0x0f2e,
+ 0x5e7d, 0x0f13,
+ 0x5e7e, 0x0632,
+ 0x5e7f, 0x1285,
+ 0x5e81, 0x0bbf,
+ 0x5e83, 0x07bf,
+ 0x5e84, 0x0999,
+ 0x5e87, 0x0d73,
+ 0x5e8a, 0x099a,
+ 0x5e8f, 0x0982,
+ 0x5e95, 0x0c08,
+ 0x5e96, 0x0e49,
+ 0x5e97, 0x0c33,
+ 0x5e9a, 0x07c0,
+ 0x5e9c, 0x0dce,
+ 0x5ea0, 0x1286,
+ 0x5ea6, 0x0c53,
+ 0x5ea7, 0x0832,
+ 0x5eab, 0x077f,
+ 0x5ead, 0x0c09,
+ 0x5eb5, 0x0487,
+ 0x5eb6, 0x0978,
+ 0x5eb7, 0x07c1,
+ 0x5eb8, 0x0f31,
+ 0x5ec1, 0x1287,
+ 0x5ec3, 0x0d07,
+ 0x5ec8, 0x1289,
+ 0x5ec9, 0x0fbf,
+ 0x5eca, 0x0fd3,
+ 0x5ecf, 0x128b,
+ 0x5ed0, 0x128a,
+ 0x5ed3, 0x05a5,
+ 0x5ed6, 0x128c,
+ 0x5eda, 0x128f,
+ 0x5edd, 0x128e,
+ 0x5edf, 0x0db2,
+ 0x5ee0, 0x099b,
+ 0x5ee1, 0x1292,
+ 0x5ee2, 0x1291,
+ 0x5ee3, 0x128d,
+ 0x5ee8, 0x1293,
+ 0x5eec, 0x1295,
+ 0x5ef0, 0x1298,
+ 0x5ef1, 0x1296,
+ 0x5ef3, 0x1297,
+ 0x5ef4, 0x1299,
+ 0x5ef6, 0x0506,
+ 0x5ef7, 0x0c0a,
+ 0x5ef8, 0x129a,
+ 0x5efa, 0x0750,
+ 0x5efb, 0x0576,
+ 0x5efc, 0x0cec,
+ 0x5efe, 0x129b,
+ 0x5eff, 0x0cd3,
+ 0x5f01, 0x0e2b,
+ 0x5f03, 0x129c,
+ 0x5f04, 0x0fd4,
+ 0x5f09, 0x129d,
+ 0x5f0a, 0x0e10,
+ 0x5f0b, 0x12a0,
+ 0x5f0c, 0x0ffa,
+ 0x5f0d, 0x100a,
+ 0x5f0f, 0x08dc,
+ 0x5f10, 0x0ccd,
+ 0x5f11, 0x12a1,
+ 0x5f13, 0x0677,
+ 0x5f14, 0x0bc0,
+ 0x5f15, 0x04be,
+ 0x5f16, 0x12a2,
+ 0x5f17, 0x0df6,
+ 0x5f18, 0x07c2,
+ 0x5f1b, 0x0b8e,
+ 0x5f1f, 0x0c0b,
+ 0x5f21, 0x2101,
+ 0x5f25, 0x0efb,
+ 0x5f26, 0x076d,
+ 0x5f27, 0x0780,
+ 0x5f29, 0x12a3,
+ 0x5f2d, 0x12a4,
+ 0x5f2f, 0x12aa,
+ 0x5f31, 0x0911,
+ 0x5f34, 0x2102,
+ 0x5f35, 0x0bc1,
+ 0x5f37, 0x06a7,
+ 0x5f38, 0x12a5,
+ 0x5f3c, 0x0d9d,
+ 0x5f3e, 0x0b84,
+ 0x5f41, 0x12a6,
+ 0x5f45, 0x20b2,
+ 0x5f48, 0x12a7,
+ 0x5f4a, 0x06a8,
+ 0x5f4c, 0x12a8,
+ 0x5f4e, 0x12a9,
+ 0x5f51, 0x12ab,
+ 0x5f53, 0x0c70,
+ 0x5f56, 0x12ac,
+ 0x5f59, 0x12ae,
+ 0x5f5c, 0x129f,
+ 0x5f5d, 0x129e,
+ 0x5f61, 0x12af,
+ 0x5f62, 0x0717,
+ 0x5f66, 0x0d99,
+ 0x5f67, 0x2103,
+ 0x5f69, 0x083c,
+ 0x5f6a, 0x0da9,
+ 0x5f6b, 0x0bc2,
+ 0x5f6c, 0x0dbd,
+ 0x5f6d, 0x12b0,
+ 0x5f70, 0x099c,
+ 0x5f71, 0x04e8,
+ 0x5f73, 0x12b1,
+ 0x5f77, 0x12b2,
+ 0x5f79, 0x0efe,
+ 0x5f7c, 0x0d74,
+ 0x5f7f, 0x12b5,
+ 0x5f80, 0x051f,
+ 0x5f81, 0x0a50,
+ 0x5f82, 0x12b4,
+ 0x5f83, 0x12b3,
+ 0x5f84, 0x0718,
+ 0x5f85, 0x0b34,
+ 0x5f87, 0x12b9,
+ 0x5f88, 0x12b7,
+ 0x5f8a, 0x12b6,
+ 0x5f8b, 0x0f6f,
+ 0x5f8c, 0x0799,
+ 0x5f90, 0x0983,
+ 0x5f91, 0x12b8,
+ 0x5f92, 0x0c46,
+ 0x5f93, 0x0948,
+ 0x5f97, 0x0c98,
+ 0x5f98, 0x12bc,
+ 0x5f99, 0x12bb,
+ 0x5f9e, 0x12ba,
+ 0x5fa0, 0x12bd,
+ 0x5fa1, 0x079a,
+ 0x5fa8, 0x12be,
+ 0x5fa9, 0x0dee,
+ 0x5faa, 0x0965,
+ 0x5fad, 0x12bf,
+ 0x5fae, 0x0d8d,
+ 0x5fb3, 0x0c99,
+ 0x5fb4, 0x0bc3,
+ 0x5fb7, 0x2104,
+ 0x5fb9, 0x0c2a,
+ 0x5fbc, 0x12c0,
+ 0x5fbd, 0x0645,
+ 0x5fc3, 0x09fa,
+ 0x5fc5, 0x0d9e,
+ 0x5fcc, 0x0633,
+ 0x5fcd, 0x0cdc,
+ 0x5fd6, 0x12c1,
+ 0x5fd7, 0x08a4,
+ 0x5fd8, 0x0e68,
+ 0x5fdc, 0x0520,
+ 0x5fdd, 0x12c6,
+ 0x5fde, 0x2105,
+ 0x5fe0, 0x0ba7,
+ 0x5fe4, 0x12c3,
+ 0x5feb, 0x0577,
+ 0x5ff0, 0x12f6,
+ 0x5ff1, 0x12c5,
+ 0x5ff5, 0x0ce6,
+ 0x5ff8, 0x12c4,
+ 0x5ffb, 0x12c2,
+ 0x5ffd, 0x080c,
+ 0x5fff, 0x12c8,
+ 0x600e, 0x12ce,
+ 0x600f, 0x12d4,
+ 0x6010, 0x12cc,
+ 0x6012, 0x0c56,
+ 0x6015, 0x12d1,
+ 0x6016, 0x0dcf,
+ 0x6019, 0x12cb,
+ 0x601b, 0x12d0,
+ 0x601c, 0x0faf,
+ 0x601d, 0x08a5,
+ 0x6020, 0x0b35,
+ 0x6021, 0x12c9,
+ 0x6025, 0x0678,
+ 0x6026, 0x12d3,
+ 0x6027, 0x0a51,
+ 0x6028, 0x0507,
+ 0x6029, 0x12cd,
+ 0x602a, 0x0578,
+ 0x602b, 0x12d2,
+ 0x602f, 0x06a9,
+ 0x6031, 0x12cf,
+ 0x603a, 0x12d5,
+ 0x6041, 0x12d7,
+ 0x6042, 0x12e1,
+ 0x6043, 0x12df,
+ 0x6046, 0x12dc,
+ 0x604a, 0x12db,
+ 0x604b, 0x0fc0,
+ 0x604d, 0x12dd,
+ 0x6050, 0x06aa,
+ 0x6052, 0x07c3,
+ 0x6055, 0x0984,
+ 0x6059, 0x12e4,
+ 0x605a, 0x12d6,
+ 0x605d, 0x2106,
+ 0x605f, 0x12da,
+ 0x6060, 0x12ca,
+ 0x6062, 0x057a,
+ 0x6063, 0x12de,
+ 0x6064, 0x12e0,
+ 0x6065, 0x0b8f,
+ 0x6068, 0x0818,
+ 0x6069, 0x0538,
+ 0x606a, 0x12d8,
+ 0x606b, 0x12e3,
+ 0x606c, 0x12e2,
+ 0x606d, 0x06ab,
+ 0x606f, 0x0b09,
+ 0x6070, 0x05c4,
+ 0x6075, 0x0719,
+ 0x6077, 0x12d9,
+ 0x6081, 0x12e5,
+ 0x6083, 0x12e8,
+ 0x6084, 0x12ea,
+ 0x6085, 0x2107,
+ 0x6089, 0x08e9,
+ 0x608a, 0x2108,
+ 0x608b, 0x12f0,
+ 0x608c, 0x0c0c,
+ 0x608d, 0x12e6,
+ 0x6092, 0x12ee,
+ 0x6094, 0x0579,
+ 0x6096, 0x12ec,
+ 0x609a, 0x12e9,
+ 0x609b, 0x12eb,
+ 0x609f, 0x079b,
+ 0x60a0, 0x0f14,
+ 0x60a3, 0x05f1,
+ 0x60a6, 0x04fb,
+ 0x60a7, 0x12ef,
+ 0x60a9, 0x0cf0,
+ 0x60aa, 0x0471,
+ 0x60b2, 0x0d75,
+ 0x60b3, 0x12c7,
+ 0x60b4, 0x12f5,
+ 0x60b5, 0x12f9,
+ 0x60b6, 0x0ef1,
+ 0x60b8, 0x12f2,
+ 0x60bc, 0x0c63,
+ 0x60bd, 0x12f7,
+ 0x60c5, 0x09d8,
+ 0x60c6, 0x12f8,
+ 0x60c7, 0x0caf,
+ 0x60d1, 0x0fed,
+ 0x60d3, 0x12f4,
+ 0x60d5, 0x210a,
+ 0x60d8, 0x12fa,
+ 0x60da, 0x080d,
+ 0x60dc, 0x0a6f,
+ 0x60de, 0x2109,
+ 0x60df, 0x0498,
+ 0x60e0, 0x12f3,
+ 0x60e1, 0x12f1,
+ 0x60e3, 0x0adc,
+ 0x60e7, 0x12e7,
+ 0x60e8, 0x0882,
+ 0x60f0, 0x0b26,
+ 0x60f1, 0x1306,
+ 0x60f2, 0x210c,
+ 0x60f3, 0x0add,
+ 0x60f4, 0x1301,
+ 0x60f6, 0x12fe,
+ 0x60f9, 0x0912,
+ 0x60fa, 0x1302,
+ 0x60fb, 0x1305,
+ 0x6100, 0x1300,
+ 0x6101, 0x092f,
+ 0x6103, 0x1303,
+ 0x6106, 0x12fd,
+ 0x6108, 0x0f08,
+ 0x6109, 0x0f07,
+ 0x610d, 0x1307,
+ 0x610f, 0x0499,
+ 0x6111, 0x210d,
+ 0x6115, 0x12fc,
+ 0x611a, 0x06ea,
+ 0x611b, 0x046a,
+ 0x611f, 0x05f2,
+ 0x6120, 0x210b,
+ 0x6121, 0x1304,
+ 0x6127, 0x130c,
+ 0x6128, 0x130b,
+ 0x612c, 0x1310,
+ 0x6130, 0x210f,
+ 0x6134, 0x1311,
+ 0x6137, 0x210e,
+ 0x613c, 0x130f,
+ 0x613d, 0x1312,
+ 0x613e, 0x130a,
+ 0x613f, 0x130e,
+ 0x6142, 0x1313,
+ 0x6144, 0x1314,
+ 0x6147, 0x1309,
+ 0x6148, 0x08ca,
+ 0x614a, 0x130d,
+ 0x614b, 0x0b36,
+ 0x614c, 0x07c4,
+ 0x614d, 0x12fb,
+ 0x614e, 0x09fb,
+ 0x6153, 0x1321,
+ 0x6155, 0x0e39,
+ 0x6158, 0x1317,
+ 0x615d, 0x1320,
+ 0x615f, 0x131f,
+ 0x6162, 0x0eab,
+ 0x6163, 0x05f3,
+ 0x6165, 0x131d,
+ 0x6167, 0x071b,
+ 0x6168, 0x0592,
+ 0x616b, 0x131a,
+ 0x616e, 0x0f80,
+ 0x616f, 0x131c,
+ 0x6170, 0x049a,
+ 0x6171, 0x131e,
+ 0x6173, 0x1315,
+ 0x6174, 0x131b,
+ 0x6175, 0x1322,
+ 0x6176, 0x071a,
+ 0x6177, 0x1316,
+ 0x617e, 0x0f47,
+ 0x6182, 0x0f15,
+ 0x6187, 0x1325,
+ 0x618a, 0x1329,
+ 0x618e, 0x0b00,
+ 0x6190, 0x0fc1,
+ 0x6191, 0x132a,
+ 0x6194, 0x1327,
+ 0x6196, 0x1324,
+ 0x6198, 0x2110,
+ 0x6199, 0x1323,
+ 0x619a, 0x1328,
+ 0x61a4, 0x0e00,
+ 0x61a7, 0x0c8c,
+ 0x61a9, 0x071c,
+ 0x61ab, 0x132b,
+ 0x61ac, 0x1326,
+ 0x61ae, 0x132c,
+ 0x61b2, 0x0751,
+ 0x61b6, 0x0531,
+ 0x61ba, 0x1334,
+ 0x61be, 0x05f4,
+ 0x61c3, 0x1332,
+ 0x61c6, 0x1333,
+ 0x61c7, 0x0819,
+ 0x61c8, 0x1331,
+ 0x61c9, 0x132f,
+ 0x61ca, 0x132e,
+ 0x61cb, 0x1335,
+ 0x61cc, 0x132d,
+ 0x61cd, 0x1337,
+ 0x61d0, 0x057b,
+ 0x61e3, 0x1339,
+ 0x61e6, 0x1338,
+ 0x61f2, 0x0bc4,
+ 0x61f4, 0x133c,
+ 0x61f6, 0x133a,
+ 0x61f7, 0x1330,
+ 0x61f8, 0x0752,
+ 0x61fa, 0x133b,
+ 0x61fc, 0x133f,
+ 0x61fd, 0x133e,
+ 0x61fe, 0x1340,
+ 0x61ff, 0x133d,
+ 0x6200, 0x1341,
+ 0x6208, 0x1342,
+ 0x620a, 0x0e3a,
+ 0x620c, 0x1345,
+ 0x620d, 0x1344,
+ 0x620e, 0x0949,
+ 0x6210, 0x0a52,
+ 0x6211, 0x0566,
+ 0x6212, 0x057c,
+ 0x6213, 0x2111,
+ 0x6214, 0x1346,
+ 0x6216, 0x0483,
+ 0x621a, 0x0a70,
+ 0x621b, 0x1347,
+ 0x621d, 0x1a64,
+ 0x621e, 0x1348,
+ 0x621f, 0x0737,
+ 0x6221, 0x1349,
+ 0x6226, 0x0a93,
+ 0x622a, 0x134a,
+ 0x622e, 0x134b,
+ 0x622f, 0x0654,
+ 0x6230, 0x134c,
+ 0x6232, 0x134d,
+ 0x6234, 0x0b37,
+ 0x6238, 0x0781,
+ 0x623b, 0x0eed,
+ 0x623f, 0x0e6a,
+ 0x6240, 0x0974,
+ 0x6241, 0x134f,
+ 0x6247, 0x0a94,
+ 0x6248, 0x1b1a,
+ 0x6249, 0x0d76,
+ 0x624b, 0x0916,
+ 0x624d, 0x083d,
+ 0x624e, 0x1350,
+ 0x6253, 0x0b27,
+ 0x6255, 0x0df7,
+ 0x6258, 0x0b51,
+ 0x625b, 0x1353,
+ 0x625e, 0x1351,
+ 0x6260, 0x1354,
+ 0x6263, 0x1352,
+ 0x6268, 0x1355,
+ 0x626e, 0x0e01,
+ 0x6271, 0x047b,
+ 0x6276, 0x0dd0,
+ 0x6279, 0x0d77,
+ 0x627c, 0x1356,
+ 0x627e, 0x1359,
+ 0x627f, 0x099d,
+ 0x6280, 0x0655,
+ 0x6282, 0x1357,
+ 0x6283, 0x135e,
+ 0x6284, 0x099e,
+ 0x6289, 0x1358,
+ 0x628a, 0x0cfa,
+ 0x6291, 0x0f48,
+ 0x6292, 0x135a,
+ 0x6294, 0x135f,
+ 0x6295, 0x0c64,
+ 0x6296, 0x135c,
+ 0x6297, 0x07c5,
+ 0x6298, 0x0a82,
+ 0x629b, 0x136d,
+ 0x629c, 0x0d48,
+ 0x629e, 0x0b52,
+ 0x62a6, 0x2112,
+ 0x62ab, 0x0d78,
+ 0x62ac, 0x13b2,
+ 0x62b1, 0x0e4a,
+ 0x62b5, 0x0c0d,
+ 0x62b9, 0x0ea3,
+ 0x62bb, 0x1362,
+ 0x62bc, 0x0521,
+ 0x62bd, 0x0ba8,
+ 0x62c2, 0x136b,
+ 0x62c5, 0x0b72,
+ 0x62c6, 0x1365,
+ 0x62c7, 0x136c,
+ 0x62c8, 0x1367,
+ 0x62c9, 0x136e,
+ 0x62ca, 0x136a,
+ 0x62cc, 0x1369,
+ 0x62cd, 0x0d25,
+ 0x62cf, 0x1363,
+ 0x62d0, 0x057d,
+ 0x62d1, 0x1361,
+ 0x62d2, 0x068b,
+ 0x62d3, 0x0b53,
+ 0x62d4, 0x135d,
+ 0x62d7, 0x1360,
+ 0x62d8, 0x07c6,
+ 0x62d9, 0x0a7f,
+ 0x62db, 0x099f,
+ 0x62dc, 0x1368,
+ 0x62dd, 0x0d08,
+ 0x62e0, 0x068c,
+ 0x62e1, 0x05a6,
+ 0x62ec, 0x05c5,
+ 0x62ed, 0x09e7,
+ 0x62ee, 0x1370,
+ 0x62ef, 0x1375,
+ 0x62f1, 0x1371,
+ 0x62f3, 0x0753,
+ 0x62f5, 0x1376,
+ 0x62f6, 0x0870,
+ 0x62f7, 0x07fb,
+ 0x62fe, 0x0930,
+ 0x62ff, 0x1364,
+ 0x6301, 0x08cb,
+ 0x6302, 0x1373,
+ 0x6307, 0x08a6,
+ 0x6308, 0x1374,
+ 0x6309, 0x0488,
+ 0x630c, 0x136f,
+ 0x6311, 0x0bc5,
+ 0x6319, 0x068d,
+ 0x631f, 0x06ac,
+ 0x6327, 0x1372,
+ 0x6328, 0x046b,
+ 0x632b, 0x0833,
+ 0x632f, 0x09fc,
+ 0x633a, 0x0c0e,
+ 0x633d, 0x0d68,
+ 0x633e, 0x1378,
+ 0x633f, 0x0ae0,
+ 0x6349, 0x0b0a,
+ 0x634c, 0x0879,
+ 0x634d, 0x1379,
+ 0x634f, 0x137b,
+ 0x6350, 0x1377,
+ 0x6355, 0x0e31,
+ 0x6357, 0x0bd9,
+ 0x635c, 0x0ade,
+ 0x6367, 0x0e4b,
+ 0x6368, 0x08fa,
+ 0x6369, 0x1387,
+ 0x636b, 0x1386,
+ 0x636e, 0x0a3e,
+ 0x6372, 0x0754,
+ 0x6376, 0x1380,
+ 0x6377, 0x09a1,
+ 0x637a, 0x0cc0,
+ 0x637b, 0x0ce7,
+ 0x6380, 0x137e,
+ 0x6383, 0x0adf,
+ 0x6388, 0x0924,
+ 0x6389, 0x1383,
+ 0x638c, 0x09a0,
+ 0x638e, 0x137d,
+ 0x638f, 0x1382,
+ 0x6392, 0x0d09,
+ 0x6396, 0x137c,
+ 0x6398, 0x06f7,
+ 0x639b, 0x05bb,
+ 0x639f, 0x1384,
+ 0x63a0, 0x0f73,
+ 0x63a1, 0x083e,
+ 0x63a2, 0x0b73,
+ 0x63a3, 0x1381,
+ 0x63a5, 0x0a80,
+ 0x63a7, 0x07c7,
+ 0x63a8, 0x0a2a,
+ 0x63a9, 0x0508,
+ 0x63aa, 0x0abe,
+ 0x63ab, 0x137f,
+ 0x63ac, 0x065f,
+ 0x63b2, 0x071d,
+ 0x63b4, 0x0beb,
+ 0x63b5, 0x1385,
+ 0x63bb, 0x0ae1,
+ 0x63be, 0x1388,
+ 0x63c0, 0x138a,
+ 0x63c3, 0x0b17,
+ 0x63c4, 0x1390,
+ 0x63c6, 0x138b,
+ 0x63c9, 0x138d,
+ 0x63cf, 0x0db3,
+ 0x63d0, 0x0c0f,
+ 0x63d2, 0x138e,
+ 0x63d6, 0x0f16,
+ 0x63da, 0x0f32,
+ 0x63db, 0x05f5,
+ 0x63e1, 0x0472,
+ 0x63e3, 0x138c,
+ 0x63e9, 0x1389,
+ 0x63ee, 0x0634,
+ 0x63f4, 0x0509,
+ 0x63f5, 0x2113,
+ 0x63f6, 0x138f,
+ 0x63fa, 0x0f33,
+ 0x6406, 0x1393,
+ 0x640d, 0x0b1b,
+ 0x640f, 0x139a,
+ 0x6413, 0x1394,
+ 0x6414, 0x1e2c,
+ 0x6416, 0x1391,
+ 0x6417, 0x1398,
+ 0x641c, 0x137a,
+ 0x6426, 0x1395,
+ 0x6428, 0x1399,
+ 0x642c, 0x0d56,
+ 0x642d, 0x0c65,
+ 0x6434, 0x1392,
+ 0x6436, 0x1396,
+ 0x643a, 0x071e,
+ 0x643e, 0x0861,
+ 0x6442, 0x0a81,
+ 0x644e, 0x139e,
+ 0x6451, 0x1e43,
+ 0x6458, 0x0c20,
+ 0x6460, 0x2114,
+ 0x6467, 0x139b,
+ 0x6469, 0x0e8e,
+ 0x646f, 0x139c,
+ 0x6476, 0x139d,
+ 0x6478, 0x0eda,
+ 0x647a, 0x0a46,
+ 0x6483, 0x0738,
+ 0x6488, 0x13a4,
+ 0x6492, 0x0883,
+ 0x6493, 0x13a1,
+ 0x6495, 0x13a0,
+ 0x649a, 0x0ce8,
+ 0x649d, 0x2115,
+ 0x649e, 0x0c8d,
+ 0x64a4, 0x0c2b,
+ 0x64a5, 0x13a2,
+ 0x64a9, 0x13a3,
+ 0x64ab, 0x0de1,
+ 0x64ad, 0x0cfb,
+ 0x64ae, 0x0871,
+ 0x64b0, 0x0a95,
+ 0x64b2, 0x0e7e,
+ 0x64b9, 0x05a7,
+ 0x64bb, 0x13aa,
+ 0x64bc, 0x13a5,
+ 0x64c1, 0x0f34,
+ 0x64c2, 0x13ac,
+ 0x64c5, 0x13a8,
+ 0x64c7, 0x13a9,
+ 0x64cd, 0x0ae2,
+ 0x64ce, 0x2116,
+ 0x64d2, 0x13a7,
+ 0x64d4, 0x1366,
+ 0x64d8, 0x13ab,
+ 0x64da, 0x13a6,
+ 0x64e0, 0x13b0,
+ 0x64e2, 0x0c21,
+ 0x64e3, 0x13b3,
+ 0x64e6, 0x0872,
+ 0x64e7, 0x13ae,
+ 0x64ec, 0x0656,
+ 0x64ef, 0x13b4,
+ 0x64f1, 0x13ad,
+ 0x64f2, 0x13b8,
+ 0x64f4, 0x13b7,
+ 0x64f6, 0x13b6,
+ 0x64fa, 0x13b9,
+ 0x64fd, 0x13bb,
+ 0x64fe, 0x09d9,
+ 0x6500, 0x13ba,
+ 0x6505, 0x13be,
+ 0x6518, 0x13bc,
+ 0x651c, 0x13bd,
+ 0x651d, 0x1397,
+ 0x6522, 0x1e97,
+ 0x6523, 0x13c0,
+ 0x6524, 0x13bf,
+ 0x652a, 0x139f,
+ 0x652b, 0x13c1,
+ 0x652c, 0x13b5,
+ 0x652f, 0x08a7,
+ 0x6534, 0x13c2,
+ 0x6536, 0x13c5,
+ 0x6537, 0x13c4,
+ 0x6538, 0x13c6,
+ 0x6539, 0x057e,
+ 0x653b, 0x07c8,
+ 0x653e, 0x0e4c,
+ 0x653f, 0x0a53,
+ 0x6545, 0x0782,
+ 0x6548, 0x13c8,
+ 0x654d, 0x13cb,
+ 0x654e, 0x2117,
+ 0x654f, 0x0dc4,
+ 0x6551, 0x0679,
+ 0x6555, 0x13ca,
+ 0x6556, 0x13c9,
+ 0x6557, 0x0d0a,
+ 0x6558, 0x13cc,
+ 0x6559, 0x06ad,
+ 0x655d, 0x13ce,
+ 0x655e, 0x13cd,
+ 0x6562, 0x05f6,
+ 0x6563, 0x0884,
+ 0x6566, 0x0cb0,
+ 0x656c, 0x071f,
+ 0x6570, 0x0a3a,
+ 0x6572, 0x13cf,
+ 0x6574, 0x0a54,
+ 0x6575, 0x0c22,
+ 0x6577, 0x0dd1,
+ 0x6578, 0x13d0,
+ 0x6582, 0x13d1,
+ 0x6587, 0x0e08,
+ 0x6588, 0x120c,
+ 0x6589, 0x0a6a,
+ 0x658c, 0x0dbe,
+ 0x658e, 0x0848,
+ 0x6590, 0x0d79,
+ 0x6591, 0x0d57,
+ 0x6597, 0x0c47,
+ 0x6599, 0x0f89,
+ 0x659b, 0x13d4,
+ 0x659c, 0x08fc,
+ 0x659f, 0x13d5,
+ 0x65a1, 0x047a,
+ 0x65a4, 0x06cc,
+ 0x65a5, 0x0a71,
+ 0x65a7, 0x0dd2,
+ 0x65ab, 0x13d6,
+ 0x65ac, 0x0890,
+ 0x65ad, 0x0b85,
+ 0x65af, 0x08a9,
+ 0x65b0, 0x09fd,
+ 0x65b7, 0x13d7,
+ 0x65b9, 0x0e4d,
+ 0x65bc, 0x0519,
+ 0x65bd, 0x08aa,
+ 0x65c1, 0x13da,
+ 0x65c3, 0x13d8,
+ 0x65c4, 0x13db,
+ 0x65c5, 0x0f81,
+ 0x65c6, 0x13d9,
+ 0x65cb, 0x0a9f,
+ 0x65cc, 0x13dc,
+ 0x65cf, 0x0b12,
+ 0x65d2, 0x13dd,
+ 0x65d7, 0x0636,
+ 0x65d9, 0x13df,
+ 0x65db, 0x13de,
+ 0x65e0, 0x13e0,
+ 0x65e2, 0x0637,
+ 0x65e5, 0x0cd4,
+ 0x65e6, 0x0b74,
+ 0x65e7, 0x0686,
+ 0x65e8, 0x08ab,
+ 0x65e9, 0x0ae3,
+ 0x65ec, 0x0966,
+ 0x65ed, 0x0474,
+ 0x65f1, 0x13e2,
+ 0x65fa, 0x0522,
+ 0x65fb, 0x13e6,
+ 0x6600, 0x2118,
+ 0x6602, 0x07c9,
+ 0x6603, 0x13e5,
+ 0x6606, 0x081b,
+ 0x6607, 0x09a2,
+ 0x6609, 0x211a,
+ 0x660a, 0x13e4,
+ 0x660c, 0x09a3,
+ 0x660e, 0x0ecc,
+ 0x660f, 0x081a,
+ 0x6613, 0x049b,
+ 0x6614, 0x0a72,
+ 0x6615, 0x2119,
+ 0x661c, 0x13eb,
+ 0x661e, 0x211c,
+ 0x661f, 0x0a55,
+ 0x6620, 0x04e9,
+ 0x6624, 0x211d,
+ 0x6625, 0x095f,
+ 0x6627, 0x0e94,
+ 0x6628, 0x0862,
+ 0x662d, 0x09a4,
+ 0x662e, 0x211b,
+ 0x662f, 0x0a4b,
+ 0x6631, 0x20ae,
+ 0x6634, 0x13ea,
+ 0x6635, 0x13e8,
+ 0x663b, 0x1e00,
+ 0x663c, 0x0ba9,
+ 0x663f, 0x1409,
+ 0x6641, 0x13ef,
+ 0x6642, 0x08cc,
+ 0x6643, 0x07ca,
+ 0x6644, 0x13ed,
+ 0x6649, 0x13ee,
+ 0x664b, 0x09fe,
+ 0x664f, 0x13ec,
+ 0x6652, 0x087d,
+ 0x6657, 0x211f,
+ 0x6659, 0x2120,
+ 0x665d, 0x13f1,
+ 0x665e, 0x13f0,
+ 0x665f, 0x13f5,
+ 0x6662, 0x13f6,
+ 0x6664, 0x13f2,
+ 0x6665, 0x211e,
+ 0x6666, 0x0580,
+ 0x6667, 0x13f3,
+ 0x6669, 0x0d69,
+ 0x666e, 0x0dd3,
+ 0x666f, 0x0720,
+ 0x6670, 0x13f7,
+ 0x6673, 0x2122,
+ 0x6674, 0x0a56,
+ 0x6676, 0x09a5,
+ 0x667a, 0x0b90,
+ 0x6681, 0x06bf,
+ 0x6683, 0x13f8,
+ 0x6684, 0x13fc,
+ 0x6687, 0x054b,
+ 0x6688, 0x13f9,
+ 0x6689, 0x13fb,
+ 0x668e, 0x13fa,
+ 0x6691, 0x0975,
+ 0x6696, 0x0b86,
+ 0x6697, 0x0489,
+ 0x6698, 0x13fd,
+ 0x6699, 0x2123,
+ 0x669d, 0x13fe,
+ 0x66a0, 0x2124,
+ 0x66a2, 0x0bc6,
+ 0x66a6, 0x0fb9,
+ 0x66ab, 0x0891,
+ 0x66ae, 0x0e3b,
+ 0x66b2, 0x2125,
+ 0x66b4, 0x0e6b,
+ 0x66b8, 0x1405,
+ 0x66b9, 0x1400,
+ 0x66bc, 0x1403,
+ 0x66be, 0x1402,
+ 0x66bf, 0x2126,
+ 0x66c1, 0x13ff,
+ 0x66c4, 0x1404,
+ 0x66c7, 0x0cb6,
+ 0x66c9, 0x1401,
+ 0x66d6, 0x1406,
+ 0x66d9, 0x0976,
+ 0x66da, 0x1407,
+ 0x66dc, 0x0f35,
+ 0x66dd, 0x0d2e,
+ 0x66e0, 0x1408,
+ 0x66e6, 0x140a,
+ 0x66e9, 0x140b,
+ 0x66f0, 0x140c,
+ 0x66f2, 0x06c2,
+ 0x66f3, 0x04ea,
+ 0x66f4, 0x07cb,
+ 0x66f5, 0x140d,
+ 0x66f7, 0x140e,
+ 0x66f8, 0x097b,
+ 0x66f9, 0x0ae4,
+ 0x66fa, 0x2127,
+ 0x66fb, 0x20b1,
+ 0x66fc, 0x10ed,
+ 0x66fd, 0x0ac0,
+ 0x66fe, 0x0abf,
+ 0x66ff, 0x0b38,
+ 0x6700, 0x0837,
+ 0x6703, 0x104b,
+ 0x6708, 0x0744,
+ 0x6709, 0x0f17,
+ 0x670b, 0x0e4e,
+ 0x670d, 0x0df0,
+ 0x670e, 0x2128,
+ 0x670f, 0x140f,
+ 0x6714, 0x0863,
+ 0x6715, 0x0bdb,
+ 0x6716, 0x1410,
+ 0x6717, 0x0fd5,
+ 0x671b, 0x0e6c,
+ 0x671d, 0x0bc7,
+ 0x671e, 0x1411,
+ 0x671f, 0x0638,
+ 0x6726, 0x1412,
+ 0x6728, 0x0ee6,
+ 0x672a, 0x0eb0,
+ 0x672b, 0x0ea4,
+ 0x672c, 0x0e8a,
+ 0x672d, 0x0873,
+ 0x672e, 0x1415,
+ 0x6731, 0x0917,
+ 0x6734, 0x0e7f,
+ 0x6736, 0x1417,
+ 0x6737, 0x141a,
+ 0x6738, 0x1419,
+ 0x673a, 0x0635,
+ 0x673d, 0x067a,
+ 0x673f, 0x1416,
+ 0x6741, 0x1418,
+ 0x6746, 0x141b,
+ 0x6749, 0x0a3f,
+ 0x674e, 0x0f65,
+ 0x674f, 0x048d,
+ 0x6750, 0x0850,
+ 0x6751, 0x0b1c,
+ 0x6753, 0x0909,
+ 0x6756, 0x09db,
+ 0x6759, 0x141e,
+ 0x675c, 0x0c48,
+ 0x675e, 0x141c,
+ 0x675f, 0x0b0b,
+ 0x6760, 0x141d,
+ 0x6761, 0x09da,
+ 0x6762, 0x0ee9,
+ 0x6763, 0x141f,
+ 0x6765, 0x0f52,
+ 0x6766, 0x212a,
+ 0x676a, 0x1425,
+ 0x676d, 0x07cc,
+ 0x676f, 0x0d0b,
+ 0x6770, 0x1422,
+ 0x6771, 0x0c66,
+ 0x6772, 0x13e3,
+ 0x6773, 0x13e7,
+ 0x6775, 0x0669,
+ 0x6777, 0x0cfd,
+ 0x677c, 0x1424,
+ 0x677e, 0x09a6,
+ 0x677f, 0x0d58,
+ 0x6785, 0x142a,
+ 0x6787, 0x0d8e,
+ 0x6789, 0x1421,
+ 0x678b, 0x1427,
+ 0x678c, 0x1426,
+ 0x6790, 0x0a73,
+ 0x6795, 0x0e9b,
+ 0x6797, 0x0f9b,
+ 0x679a, 0x0e95,
+ 0x679c, 0x054c,
+ 0x679d, 0x08ac,
+ 0x67a0, 0x0fee,
+ 0x67a1, 0x1429,
+ 0x67a2, 0x0a3b,
+ 0x67a6, 0x1428,
+ 0x67a9, 0x1423,
+ 0x67af, 0x0783,
+ 0x67b3, 0x142f,
+ 0x67b4, 0x142d,
+ 0x67b6, 0x054d,
+ 0x67b7, 0x142b,
+ 0x67b8, 0x1431,
+ 0x67b9, 0x1437,
+ 0x67bb, 0x212b,
+ 0x67c0, 0x212d,
+ 0x67c1, 0x0b28,
+ 0x67c4, 0x0e11,
+ 0x67c6, 0x1439,
+ 0x67ca, 0x0d94,
+ 0x67ce, 0x1438,
+ 0x67cf, 0x0d26,
+ 0x67d0, 0x0e6d,
+ 0x67d1, 0x05f7,
+ 0x67d3, 0x0a9b,
+ 0x67d4, 0x094a,
+ 0x67d8, 0x0bef,
+ 0x67da, 0x0f18,
+ 0x67dd, 0x1434,
+ 0x67de, 0x1433,
+ 0x67e2, 0x1435,
+ 0x67e4, 0x1432,
+ 0x67e7, 0x143a,
+ 0x67e9, 0x1430,
+ 0x67ec, 0x142e,
+ 0x67ee, 0x1436,
+ 0x67ef, 0x142c,
+ 0x67f1, 0x0baa,
+ 0x67f3, 0x0f04,
+ 0x67f4, 0x08f2,
+ 0x67f5, 0x0864,
+ 0x67fb, 0x082a,
+ 0x67fe, 0x0e9d,
+ 0x67ff, 0x059f,
+ 0x6801, 0x212e,
+ 0x6802, 0x0bea,
+ 0x6803, 0x0ca2,
+ 0x6804, 0x04eb,
+ 0x6805, 0x1e07,
+ 0x6813, 0x0a96,
+ 0x6816, 0x0a58,
+ 0x6817, 0x0700,
+ 0x681e, 0x143c,
+ 0x6821, 0x07cd,
+ 0x6822, 0x05da,
+ 0x6829, 0x143e,
+ 0x682a, 0x05d2,
+ 0x682b, 0x1444,
+ 0x6832, 0x1441,
+ 0x6834, 0x0a97,
+ 0x6838, 0x05a9,
+ 0x6839, 0x081c,
+ 0x683c, 0x05a8,
+ 0x683d, 0x083f,
+ 0x6840, 0x143f,
+ 0x6841, 0x073b,
+ 0x6842, 0x0721,
+ 0x6843, 0x0c67,
+ 0x6844, 0x212f,
+ 0x6846, 0x143d,
+ 0x6848, 0x048a,
+ 0x684d, 0x1440,
+ 0x684e, 0x1442,
+ 0x6850, 0x06c5,
+ 0x6851, 0x0702,
+ 0x6852, 0x212c,
+ 0x6853, 0x05f8,
+ 0x6854, 0x0665,
+ 0x6859, 0x1445,
+ 0x685c, 0x0869,
+ 0x685d, 0x0e9f,
+ 0x685f, 0x0885,
+ 0x6863, 0x1446,
+ 0x6867, 0x0da2,
+ 0x6874, 0x1452,
+ 0x6876, 0x0533,
+ 0x6877, 0x1447,
+ 0x687e, 0x1458,
+ 0x687f, 0x1448,
+ 0x6881, 0x0f8a,
+ 0x6883, 0x144f,
+ 0x6885, 0x0d15,
+ 0x688d, 0x1457,
+ 0x688e, 0x1e9c,
+ 0x688f, 0x144a,
+ 0x6893, 0x0478,
+ 0x6894, 0x144c,
+ 0x6897, 0x07ce,
+ 0x689b, 0x144e,
+ 0x689d, 0x144d,
+ 0x689f, 0x1449,
+ 0x68a0, 0x1454,
+ 0x68a2, 0x09a7,
+ 0x68a6, 0x11be,
+ 0x68a7, 0x079c,
+ 0x68a8, 0x0f66,
+ 0x68ad, 0x144b,
+ 0x68af, 0x0c10,
+ 0x68b0, 0x0581,
+ 0x68b1, 0x081d,
+ 0x68b3, 0x1443,
+ 0x68b5, 0x1453,
+ 0x68b6, 0x05bf,
+ 0x68b9, 0x1451,
+ 0x68ba, 0x1455,
+ 0x68bc, 0x0c68,
+ 0x68c4, 0x063a,
+ 0x68c6, 0x1473,
+ 0x68c8, 0x20af,
+ 0x68c9, 0x0ed5,
+ 0x68ca, 0x145a,
+ 0x68cb, 0x0639,
+ 0x68cd, 0x1461,
+ 0x68cf, 0x2130,
+ 0x68d2, 0x0e6e,
+ 0x68d4, 0x1462,
+ 0x68d5, 0x1464,
+ 0x68d7, 0x1468,
+ 0x68d8, 0x145c,
+ 0x68da, 0x0b68,
+ 0x68df, 0x0c69,
+ 0x68e0, 0x146c,
+ 0x68e1, 0x145f,
+ 0x68e3, 0x1469,
+ 0x68e7, 0x1463,
+ 0x68ee, 0x09ff,
+ 0x68ef, 0x146d,
+ 0x68f2, 0x0a57,
+ 0x68f9, 0x146b,
+ 0x68fa, 0x05f9,
+ 0x6900, 0x0ff6,
+ 0x6901, 0x1459,
+ 0x6904, 0x1467,
+ 0x6905, 0x049c,
+ 0x6908, 0x145b,
+ 0x690b, 0x0ec6,
+ 0x690c, 0x1460,
+ 0x690d, 0x09e8,
+ 0x690e, 0x0be3,
+ 0x690f, 0x1456,
+ 0x6912, 0x1466,
+ 0x6919, 0x0a40,
+ 0x691a, 0x1470,
+ 0x691b, 0x05cf,
+ 0x691c, 0x0755,
+ 0x6921, 0x1472,
+ 0x6922, 0x145d,
+ 0x6923, 0x1471,
+ 0x6925, 0x146a,
+ 0x6926, 0x145e,
+ 0x6928, 0x146e,
+ 0x692a, 0x146f,
+ 0x6930, 0x1480,
+ 0x6934, 0x0ca6,
+ 0x6936, 0x1465,
+ 0x6939, 0x147c,
+ 0x693d, 0x147e,
+ 0x693f, 0x0bf4,
+ 0x694a, 0x0f36,
+ 0x6953, 0x0de8,
+ 0x6954, 0x1479,
+ 0x6955, 0x0b2a,
+ 0x6959, 0x147f,
+ 0x695a, 0x0ac1,
+ 0x695c, 0x1476,
+ 0x695d, 0x1483,
+ 0x695e, 0x1482,
+ 0x6960, 0x0cc7,
+ 0x6961, 0x1481,
+ 0x6962, 0x0cc2,
+ 0x6968, 0x2132,
+ 0x696a, 0x1485,
+ 0x696b, 0x1478,
+ 0x696d, 0x06c0,
+ 0x696e, 0x147b,
+ 0x696f, 0x0967,
+ 0x6973, 0x0d16,
+ 0x6974, 0x147d,
+ 0x6975, 0x06c3,
+ 0x6977, 0x1475,
+ 0x6978, 0x1477,
+ 0x6979, 0x1474,
+ 0x697c, 0x0fd6,
+ 0x697d, 0x05b8,
+ 0x697e, 0x147a,
+ 0x6981, 0x1484,
+ 0x6982, 0x0593,
+ 0x698a, 0x0857,
+ 0x698e, 0x04ff,
+ 0x6991, 0x1495,
+ 0x6994, 0x0fd7,
+ 0x6995, 0x1498,
+ 0x6998, 0x2134,
+ 0x699b, 0x0a00,
+ 0x699c, 0x1497,
+ 0x69a0, 0x1496,
+ 0x69a7, 0x1493,
+ 0x69ae, 0x1487,
+ 0x69b1, 0x14a4,
+ 0x69b2, 0x1486,
+ 0x69b4, 0x1499,
+ 0x69bb, 0x1491,
+ 0x69be, 0x148c,
+ 0x69bf, 0x1489,
+ 0x69c1, 0x148a,
+ 0x69c3, 0x1492,
+ 0x69c7, 0x1d33,
+ 0x69ca, 0x148f,
+ 0x69cb, 0x07cf,
+ 0x69cc, 0x0be4,
+ 0x69cd, 0x0ae6,
+ 0x69ce, 0x148d,
+ 0x69d0, 0x1488,
+ 0x69d3, 0x148b,
+ 0x69d8, 0x0f37,
+ 0x69d9, 0x0e98,
+ 0x69dd, 0x1490,
+ 0x69de, 0x149a,
+ 0x69e2, 0x2135,
+ 0x69e7, 0x14a2,
+ 0x69e8, 0x149b,
+ 0x69eb, 0x14a8,
+ 0x69ed, 0x14a6,
+ 0x69f2, 0x14a1,
+ 0x69f9, 0x14a0,
+ 0x69fb, 0x0bec,
+ 0x69fd, 0x0ae7,
+ 0x69ff, 0x149e,
+ 0x6a02, 0x149c,
+ 0x6a05, 0x14a3,
+ 0x6a0a, 0x14a9,
+ 0x6a0b, 0x0d89,
+ 0x6a0c, 0x14af,
+ 0x6a12, 0x14aa,
+ 0x6a13, 0x14ad,
+ 0x6a14, 0x14a7,
+ 0x6a17, 0x0bb2,
+ 0x6a19, 0x0daa,
+ 0x6a1b, 0x149d,
+ 0x6a1e, 0x14a5,
+ 0x6a1f, 0x09a8,
+ 0x6a21, 0x0edb,
+ 0x6a22, 0x14b9,
+ 0x6a23, 0x14ac,
+ 0x6a29, 0x0756,
+ 0x6a2a, 0x0523,
+ 0x6a2b, 0x05bd,
+ 0x6a2e, 0x1494,
+ 0x6a30, 0x2136,
+ 0x6a35, 0x09a9,
+ 0x6a36, 0x14b1,
+ 0x6a38, 0x14b8,
+ 0x6a39, 0x0925,
+ 0x6a3a, 0x05d0,
+ 0x6a3d, 0x0b6c,
+ 0x6a44, 0x14ae,
+ 0x6a46, 0x2138,
+ 0x6a47, 0x14b3,
+ 0x6a48, 0x14b7,
+ 0x6a4b, 0x06ae,
+ 0x6a58, 0x0666,
+ 0x6a59, 0x14b5,
+ 0x6a5f, 0x063b,
+ 0x6a61, 0x0ca3,
+ 0x6a62, 0x14b4,
+ 0x6a66, 0x14b6,
+ 0x6a6b, 0x2137,
+ 0x6a72, 0x14b0,
+ 0x6a73, 0x2139,
+ 0x6a78, 0x14b2,
+ 0x6a7e, 0x213a,
+ 0x6a7f, 0x05be,
+ 0x6a80, 0x0b87,
+ 0x6a84, 0x14bd,
+ 0x6a8d, 0x14bb,
+ 0x6a8e, 0x079d,
+ 0x6a90, 0x14ba,
+ 0x6a97, 0x14c0,
+ 0x6a9c, 0x143b,
+ 0x6aa0, 0x14bc,
+ 0x6aa2, 0x14be,
+ 0x6aaa, 0x14cb,
+ 0x6aac, 0x14c7,
+ 0x6aae, 0x1450,
+ 0x6ab3, 0x14c6,
+ 0x6ab8, 0x14c5,
+ 0x6abb, 0x14c2,
+ 0x6ac1, 0x14ab,
+ 0x6ac2, 0x14c4,
+ 0x6ac3, 0x14c3,
+ 0x6ad1, 0x14c9,
+ 0x6ad3, 0x0fcc,
+ 0x6ada, 0x14cc,
+ 0x6adb, 0x06f3,
+ 0x6ade, 0x14c8,
+ 0x6adf, 0x14ca,
+ 0x6ae2, 0x213b,
+ 0x6ae4, 0x213c,
+ 0x6ae8, 0x0d3b,
+ 0x6aea, 0x14cd,
+ 0x6afa, 0x14d1,
+ 0x6afb, 0x14ce,
+ 0x6b04, 0x0f5d,
+ 0x6b05, 0x14cf,
+ 0x6b0a, 0x149f,
+ 0x6b12, 0x14d2,
+ 0x6b16, 0x14d3,
+ 0x6b1d, 0x04d7,
+ 0x6b1f, 0x14d5,
+ 0x6b20, 0x073d,
+ 0x6b21, 0x08cd,
+ 0x6b23, 0x06cd,
+ 0x6b27, 0x0524,
+ 0x6b32, 0x0f49,
+ 0x6b37, 0x14d7,
+ 0x6b38, 0x14d6,
+ 0x6b39, 0x14d9,
+ 0x6b3a, 0x0657,
+ 0x6b3d, 0x06ce,
+ 0x6b3e, 0x05fa,
+ 0x6b43, 0x14dc,
+ 0x6b47, 0x14db,
+ 0x6b49, 0x14dd,
+ 0x6b4c, 0x054e,
+ 0x6b4e, 0x0b75,
+ 0x6b50, 0x14de,
+ 0x6b53, 0x05fb,
+ 0x6b54, 0x14e0,
+ 0x6b59, 0x14df,
+ 0x6b5b, 0x14e1,
+ 0x6b5f, 0x14e2,
+ 0x6b61, 0x14e3,
+ 0x6b62, 0x08ad,
+ 0x6b63, 0x0a59,
+ 0x6b64, 0x0811,
+ 0x6b66, 0x0de2,
+ 0x6b69, 0x0e32,
+ 0x6b6a, 0x0fea,
+ 0x6b6f, 0x08c3,
+ 0x6b73, 0x0840,
+ 0x6b74, 0x0fba,
+ 0x6b78, 0x14e4,
+ 0x6b7b, 0x08ae,
+ 0x6b7f, 0x14e6,
+ 0x6b83, 0x14e9,
+ 0x6b84, 0x14e8,
+ 0x6b86, 0x0e86,
+ 0x6b89, 0x0968,
+ 0x6b8a, 0x0918,
+ 0x6b8b, 0x0892,
+ 0x6b8d, 0x14ea,
+ 0x6b95, 0x14ec,
+ 0x6b96, 0x09e9,
+ 0x6b98, 0x14eb,
+ 0x6b9e, 0x14ed,
+ 0x6ba4, 0x14ee,
+ 0x6baa, 0x14ef,
+ 0x6baf, 0x14f1,
+ 0x6bb1, 0x14f3,
+ 0x6bb2, 0x14f2,
+ 0x6bb3, 0x14f4,
+ 0x6bb4, 0x0525,
+ 0x6bb5, 0x0b88,
+ 0x6bb7, 0x14f5,
+ 0x6bba, 0x0874,
+ 0x6bbb, 0x05aa,
+ 0x6bbc, 0x14f6,
+ 0x6bbf, 0x0c3c,
+ 0x6bc0, 0x119d,
+ 0x6bc5, 0x063d,
+ 0x6bc6, 0x14f7,
+ 0x6bcb, 0x14f8,
+ 0x6bcd, 0x0e3c,
+ 0x6bce, 0x0e96,
+ 0x6bd2, 0x0c9f,
+ 0x6bd3, 0x14f9,
+ 0x6bd4, 0x0d7a,
+ 0x6bd6, 0x213d,
+ 0x6bd8, 0x0d8f,
+ 0x6bdb, 0x0edf,
+ 0x6bdf, 0x14fa,
+ 0x6beb, 0x14fc,
+ 0x6bec, 0x14fb,
+ 0x6bef, 0x14fe,
+ 0x6bf3, 0x14fd,
+ 0x6c08, 0x1500,
+ 0x6c0f, 0x08af,
+ 0x6c11, 0x0ebd,
+ 0x6c13, 0x1501,
+ 0x6c17, 0x063e,
+ 0x6c1b, 0x1503,
+ 0x6c23, 0x1505,
+ 0x6c24, 0x1504,
+ 0x6c34, 0x0a2b,
+ 0x6c37, 0x0dab,
+ 0x6c38, 0x04ec,
+ 0x6c3e, 0x0d59,
+ 0x6c3f, 0x213e,
+ 0x6c40, 0x0c11,
+ 0x6c41, 0x094b,
+ 0x6c42, 0x067b,
+ 0x6c4e, 0x0d5a,
+ 0x6c50, 0x08da,
+ 0x6c55, 0x1507,
+ 0x6c57, 0x05fc,
+ 0x6c5a, 0x051a,
+ 0x6c5c, 0x213f,
+ 0x6c5d, 0x0cca,
+ 0x6c5e, 0x1506,
+ 0x6c5f, 0x07d0,
+ 0x6c60, 0x0b91,
+ 0x6c62, 0x1508,
+ 0x6c68, 0x1510,
+ 0x6c6a, 0x1509,
+ 0x6c6f, 0x2141,
+ 0x6c70, 0x0b21,
+ 0x6c72, 0x067c,
+ 0x6c73, 0x1511,
+ 0x6c7a, 0x073e,
+ 0x6c7d, 0x063f,
+ 0x6c7e, 0x150f,
+ 0x6c81, 0x150d,
+ 0x6c82, 0x150a,
+ 0x6c83, 0x0f4a,
+ 0x6c86, 0x2140,
+ 0x6c88, 0x0bdc,
+ 0x6c8c, 0x0cb1,
+ 0x6c8d, 0x150b,
+ 0x6c90, 0x1513,
+ 0x6c92, 0x1512,
+ 0x6c93, 0x06f9,
+ 0x6c96, 0x052d,
+ 0x6c99, 0x082b,
+ 0x6c9a, 0x150c,
+ 0x6c9b, 0x150e,
+ 0x6ca1, 0x0e85,
+ 0x6ca2, 0x0b54,
+ 0x6cab, 0x0ea5,
+ 0x6cae, 0x151b,
+ 0x6cb1, 0x151c,
+ 0x6cb3, 0x054f,
+ 0x6cb8, 0x0df8,
+ 0x6cb9, 0x0f09,
+ 0x6cba, 0x151e,
+ 0x6cbb, 0x08cf,
+ 0x6cbc, 0x09aa,
+ 0x6cbd, 0x1517,
+ 0x6cbe, 0x151d,
+ 0x6cbf, 0x050a,
+ 0x6cc1, 0x06af,
+ 0x6cc4, 0x1514,
+ 0x6cc5, 0x1519,
+ 0x6cc9, 0x0a98,
+ 0x6cca, 0x0d27,
+ 0x6ccc, 0x0d7b,
+ 0x6cd3, 0x1516,
+ 0x6cd5, 0x0e4f,
+ 0x6cd7, 0x1518,
+ 0x6cd9, 0x1521,
+ 0x6cda, 0x2142,
+ 0x6cdb, 0x151f,
+ 0x6cdd, 0x151a,
+ 0x6ce1, 0x0e50,
+ 0x6ce2, 0x0cfe,
+ 0x6ce3, 0x067d,
+ 0x6ce5, 0x0c1f,
+ 0x6ce8, 0x0bab,
+ 0x6cea, 0x1522,
+ 0x6cef, 0x1520,
+ 0x6cf0, 0x0b39,
+ 0x6cf1, 0x1515,
+ 0x6cf3, 0x04ed,
+ 0x6d04, 0x2143,
+ 0x6d0b, 0x0f38,
+ 0x6d0c, 0x152d,
+ 0x6d12, 0x152c,
+ 0x6d17, 0x0a9a,
+ 0x6d19, 0x1529,
+ 0x6d1b, 0x0f56,
+ 0x6d1e, 0x0c8e,
+ 0x6d1f, 0x1523,
+ 0x6d25, 0x0be1,
+ 0x6d29, 0x04ee,
+ 0x6d2a, 0x07d1,
+ 0x6d2b, 0x1526,
+ 0x6d32, 0x0931,
+ 0x6d33, 0x152b,
+ 0x6d35, 0x152a,
+ 0x6d36, 0x1525,
+ 0x6d38, 0x1528,
+ 0x6d3b, 0x05c6,
+ 0x6d3d, 0x1527,
+ 0x6d3e, 0x0cff,
+ 0x6d41, 0x0f76,
+ 0x6d44, 0x09dc,
+ 0x6d45, 0x0a99,
+ 0x6d59, 0x1533,
+ 0x6d5a, 0x1531,
+ 0x6d5c, 0x0dbf,
+ 0x6d63, 0x152e,
+ 0x6d64, 0x1530,
+ 0x6d66, 0x04dc,
+ 0x6d69, 0x07d2,
+ 0x6d6a, 0x0fd8,
+ 0x6d6c, 0x059b,
+ 0x6d6e, 0x0dd4,
+ 0x6d6f, 0x2145,
+ 0x6d74, 0x0f4b,
+ 0x6d77, 0x0582,
+ 0x6d78, 0x0a01,
+ 0x6d79, 0x1532,
+ 0x6d85, 0x1537,
+ 0x6d87, 0x2144,
+ 0x6d88, 0x09ab,
+ 0x6d8c, 0x0f1a,
+ 0x6d8e, 0x1534,
+ 0x6d93, 0x152f,
+ 0x6d95, 0x1535,
+ 0x6d96, 0x2146,
+ 0x6d99, 0x0fa6,
+ 0x6d9b, 0x0c6d,
+ 0x6d9c, 0x0c9a,
+ 0x6dac, 0x2147,
+ 0x6daf, 0x0594,
+ 0x6db2, 0x04f7,
+ 0x6db5, 0x153b,
+ 0x6db8, 0x153e,
+ 0x6dbc, 0x0f8b,
+ 0x6dc0, 0x0f4e,
+ 0x6dc5, 0x1545,
+ 0x6dc6, 0x153f,
+ 0x6dc7, 0x153c,
+ 0x6dcb, 0x0f9c,
+ 0x6dcc, 0x1542,
+ 0x6dcf, 0x2148,
+ 0x6dd1, 0x0954,
+ 0x6dd2, 0x1544,
+ 0x6dd5, 0x1549,
+ 0x6dd8, 0x0c6b,
+ 0x6dd9, 0x1547,
+ 0x6dde, 0x1541,
+ 0x6de1, 0x0b76,
+ 0x6de4, 0x1548,
+ 0x6de6, 0x153d,
+ 0x6de8, 0x1543,
+ 0x6dea, 0x154a,
+ 0x6deb, 0x04c0,
+ 0x6dec, 0x1540,
+ 0x6dee, 0x154b,
+ 0x6df1, 0x0a02,
+ 0x6df2, 0x214a,
+ 0x6df3, 0x0969,
+ 0x6df5, 0x0df5,
+ 0x6df7, 0x081e,
+ 0x6df8, 0x2149,
+ 0x6df9, 0x1538,
+ 0x6dfa, 0x1546,
+ 0x6dfb, 0x0c34,
+ 0x6dfc, 0x214b,
+ 0x6e05, 0x0a5a,
+ 0x6e07, 0x05c7,
+ 0x6e08, 0x0841,
+ 0x6e09, 0x09ac,
+ 0x6e0a, 0x153a,
+ 0x6e0b, 0x094c,
+ 0x6e13, 0x0722,
+ 0x6e15, 0x1539,
+ 0x6e19, 0x154f,
+ 0x6e1a, 0x0977,
+ 0x6e1b, 0x076e,
+ 0x6e1d, 0x155e,
+ 0x6e1f, 0x1558,
+ 0x6e20, 0x068e,
+ 0x6e21, 0x0c49,
+ 0x6e23, 0x1553,
+ 0x6e24, 0x155c,
+ 0x6e25, 0x0473,
+ 0x6e26, 0x04d4,
+ 0x6e27, 0x214e,
+ 0x6e29, 0x0539,
+ 0x6e2b, 0x1555,
+ 0x6e2c, 0x0b0c,
+ 0x6e2d, 0x154c,
+ 0x6e2e, 0x154e,
+ 0x6e2f, 0x07d3,
+ 0x6e38, 0x155f,
+ 0x6e39, 0x214c,
+ 0x6e3a, 0x155a,
+ 0x6e3c, 0x214f,
+ 0x6e3e, 0x1552,
+ 0x6e43, 0x1559,
+ 0x6e4a, 0x0eb7,
+ 0x6e4d, 0x1557,
+ 0x6e4e, 0x155b,
+ 0x6e56, 0x0784,
+ 0x6e58, 0x09ad,
+ 0x6e5b, 0x0b77,
+ 0x6e5c, 0x214d,
+ 0x6e5f, 0x1551,
+ 0x6e67, 0x0f19,
+ 0x6e6b, 0x1554,
+ 0x6e6e, 0x154d,
+ 0x6e6f, 0x0c6c,
+ 0x6e72, 0x1550,
+ 0x6e76, 0x1556,
+ 0x6e7e, 0x0ff7,
+ 0x6e7f, 0x08ea,
+ 0x6e80, 0x0eac,
+ 0x6e82, 0x1560,
+ 0x6e8c, 0x0d42,
+ 0x6e8f, 0x156c,
+ 0x6e90, 0x076f,
+ 0x6e96, 0x096a,
+ 0x6e98, 0x1562,
+ 0x6e9c, 0x0f77,
+ 0x6e9d, 0x07d4,
+ 0x6e9f, 0x156f,
+ 0x6ea2, 0x04b2,
+ 0x6ea5, 0x156d,
+ 0x6eaa, 0x1561,
+ 0x6eaf, 0x1567,
+ 0x6eb2, 0x1569,
+ 0x6eb6, 0x0f39,
+ 0x6eb7, 0x1564,
+ 0x6eba, 0x0c28,
+ 0x6ebd, 0x1566,
+ 0x6ebf, 0x2150,
+ 0x6ec2, 0x156e,
+ 0x6ec4, 0x1568,
+ 0x6ec5, 0x0ed3,
+ 0x6ec9, 0x1563,
+ 0x6ecb, 0x08ce,
+ 0x6ecc, 0x157b,
+ 0x6ed1, 0x05c8,
+ 0x6ed3, 0x1565,
+ 0x6ed4, 0x156a,
+ 0x6edd, 0x0b4c,
+ 0x6ede, 0x0b3a,
+ 0x6eec, 0x1573,
+ 0x6eef, 0x1579,
+ 0x6ef2, 0x1577,
+ 0x6ef4, 0x0c23,
+ 0x6ef7, 0x157e,
+ 0x6ef8, 0x1574,
+ 0x6efe, 0x1575,
+ 0x6eff, 0x155d,
+ 0x6f01, 0x0693,
+ 0x6f02, 0x0dac,
+ 0x6f06, 0x08eb,
+ 0x6f09, 0x0809,
+ 0x6f0f, 0x0fd9,
+ 0x6f11, 0x1571,
+ 0x6f13, 0x157d,
+ 0x6f14, 0x050b,
+ 0x6f15, 0x0ae8,
+ 0x6f20, 0x0d2f,
+ 0x6f22, 0x05fd,
+ 0x6f23, 0x0fc2,
+ 0x6f2b, 0x0ead,
+ 0x6f2c, 0x0bee,
+ 0x6f31, 0x1578,
+ 0x6f32, 0x157a,
+ 0x6f38, 0x0ab4,
+ 0x6f3e, 0x157c,
+ 0x6f3f, 0x1576,
+ 0x6f41, 0x1570,
+ 0x6f45, 0x05ff,
+ 0x6f51, 0x1e60,
+ 0x6f54, 0x073f,
+ 0x6f58, 0x158a,
+ 0x6f5b, 0x1585,
+ 0x6f5c, 0x0a9c,
+ 0x6f5f, 0x05c1,
+ 0x6f64, 0x096b,
+ 0x6f66, 0x158e,
+ 0x6f6d, 0x1587,
+ 0x6f6e, 0x0bc8,
+ 0x6f6f, 0x1584,
+ 0x6f70, 0x0bf5,
+ 0x6f74, 0x15a7,
+ 0x6f78, 0x1581,
+ 0x6f7a, 0x1580,
+ 0x6f7c, 0x1589,
+ 0x6f80, 0x1583,
+ 0x6f81, 0x1582,
+ 0x6f82, 0x1588,
+ 0x6f84, 0x0a45,
+ 0x6f86, 0x157f,
+ 0x6f88, 0x2151,
+ 0x6f8e, 0x158b,
+ 0x6f91, 0x158c,
+ 0x6f97, 0x05fe,
+ 0x6fa1, 0x1591,
+ 0x6fa3, 0x1590,
+ 0x6fa4, 0x1592,
+ 0x6faa, 0x1595,
+ 0x6fb1, 0x0c3d,
+ 0x6fb3, 0x158f,
+ 0x6fb5, 0x2152,
+ 0x6fb9, 0x1593,
+ 0x6fc0, 0x0739,
+ 0x6fc1, 0x0b59,
+ 0x6fc2, 0x158d,
+ 0x6fc3, 0x0cf1,
+ 0x6fc6, 0x1594,
+ 0x6fd4, 0x1599,
+ 0x6fd5, 0x1597,
+ 0x6fd8, 0x159a,
+ 0x6fdb, 0x159d,
+ 0x6fdf, 0x1596,
+ 0x6fe0, 0x07fc,
+ 0x6fe1, 0x0cde,
+ 0x6fe4, 0x1536,
+ 0x6feb, 0x0f5e,
+ 0x6fec, 0x1598,
+ 0x6fee, 0x159c,
+ 0x6fef, 0x0b55,
+ 0x6ff1, 0x159b,
+ 0x6ff3, 0x1586,
+ 0x6ff5, 0x2153,
+ 0x6ff6, 0x1ba4,
+ 0x6ffa, 0x15a0,
+ 0x6ffe, 0x15a4,
+ 0x7001, 0x15a2,
+ 0x7005, 0x2154,
+ 0x7006, 0x1e50,
+ 0x7007, 0x2155,
+ 0x7009, 0x159e,
+ 0x700b, 0x159f,
+ 0x700f, 0x15a3,
+ 0x7011, 0x15a1,
+ 0x7015, 0x0dc0,
+ 0x7018, 0x15a9,
+ 0x701a, 0x15a6,
+ 0x701b, 0x15a5,
+ 0x701d, 0x15a8,
+ 0x701e, 0x0cac,
+ 0x701f, 0x15aa,
+ 0x7026, 0x0bb3,
+ 0x7027, 0x0b4d,
+ 0x7028, 0x2156,
+ 0x702c, 0x0a49,
+ 0x7030, 0x15ab,
+ 0x7032, 0x15ad,
+ 0x703e, 0x15ac,
+ 0x704c, 0x1572,
+ 0x7051, 0x15ae,
+ 0x7058, 0x0cbf,
+ 0x7063, 0x15af,
+ 0x706b, 0x0550,
+ 0x706f, 0x0c6e,
+ 0x7070, 0x0583,
+ 0x7078, 0x067e,
+ 0x707c, 0x090a,
+ 0x707d, 0x0842,
+ 0x7085, 0x2157,
+ 0x7089, 0x0fcd,
+ 0x708a, 0x0a2c,
+ 0x708e, 0x050c,
+ 0x7092, 0x15b1,
+ 0x7099, 0x15b0,
+ 0x70ab, 0x2158,
+ 0x70ac, 0x15b4,
+ 0x70ad, 0x0b78,
+ 0x70ae, 0x15b7,
+ 0x70af, 0x15b2,
+ 0x70b3, 0x15b6,
+ 0x70b8, 0x15b5,
+ 0x70b9, 0x0c3a,
+ 0x70ba, 0x049d,
+ 0x70bb, 0x20ad,
+ 0x70c8, 0x0fbd,
+ 0x70cb, 0x15b9,
+ 0x70cf, 0x04ca,
+ 0x70d9, 0x15bb,
+ 0x70dd, 0x15ba,
+ 0x70df, 0x15b8,
+ 0x70f1, 0x15b3,
+ 0x70f9, 0x0e51,
+ 0x70fd, 0x15bd,
+ 0x7104, 0x215a,
+ 0x7109, 0x15bc,
+ 0x710f, 0x2159,
+ 0x7114, 0x050d,
+ 0x7119, 0x15bf,
+ 0x711a, 0x0e02,
+ 0x711c, 0x15be,
+ 0x7121, 0x0ec1,
+ 0x7126, 0x09af,
+ 0x7130, 0x1ddc,
+ 0x7136, 0x0ab5,
+ 0x713c, 0x09ae,
+ 0x7146, 0x215c,
+ 0x7149, 0x0fc3,
+ 0x714c, 0x15c5,
+ 0x714e, 0x0a9d,
+ 0x7155, 0x15c1,
+ 0x7156, 0x15c6,
+ 0x7159, 0x050e,
+ 0x715c, 0x215b,
+ 0x7162, 0x15c4,
+ 0x7164, 0x0d17,
+ 0x7165, 0x15c0,
+ 0x7166, 0x15c3,
+ 0x7167, 0x09b0,
+ 0x7169, 0x0d65,
+ 0x716c, 0x15c7,
+ 0x716e, 0x08fd,
+ 0x717d, 0x0a9e,
+ 0x7184, 0x15ca,
+ 0x7188, 0x15c2,
+ 0x718a, 0x06fd,
+ 0x718f, 0x15c8,
+ 0x7194, 0x0f3a,
+ 0x7195, 0x15cb,
+ 0x7199, 0x205d,
+ 0x719f, 0x0959,
+ 0x71a8, 0x15cc,
+ 0x71ac, 0x15cd,
+ 0x71b1, 0x0ce4,
+ 0x71b9, 0x15cf,
+ 0x71be, 0x15d0,
+ 0x71c1, 0x215f,
+ 0x71c3, 0x0ce9,
+ 0x71c8, 0x0c6f,
+ 0x71c9, 0x15d2,
+ 0x71ce, 0x15d4,
+ 0x71d0, 0x0f9d,
+ 0x71d2, 0x15d1,
+ 0x71d4, 0x15d3,
+ 0x71d5, 0x050f,
+ 0x71d7, 0x15ce,
+ 0x71df, 0x114e,
+ 0x71e0, 0x15d5,
+ 0x71e5, 0x0ae9,
+ 0x71e6, 0x0886,
+ 0x71e7, 0x15d7,
+ 0x71ec, 0x15d6,
+ 0x71ed, 0x09ea,
+ 0x71ee, 0x10ee,
+ 0x71f5, 0x15d8,
+ 0x71f9, 0x15da,
+ 0x71fb, 0x15c9,
+ 0x71fc, 0x15d9,
+ 0x71fe, 0x2160,
+ 0x71ff, 0x15db,
+ 0x7206, 0x0d30,
+ 0x720d, 0x15dc,
+ 0x7210, 0x15dd,
+ 0x721b, 0x15de,
+ 0x7228, 0x15df,
+ 0x722a, 0x0bfa,
+ 0x722c, 0x15e1,
+ 0x722d, 0x15e0,
+ 0x7230, 0x15e2,
+ 0x7232, 0x15e3,
+ 0x7235, 0x090b,
+ 0x7236, 0x0dd5,
+ 0x723a, 0x0ef8,
+ 0x723b, 0x15e4,
+ 0x723d, 0x0ad8,
+ 0x723e, 0x08d0,
+ 0x723f, 0x15e6,
+ 0x7246, 0x15e8,
+ 0x7247, 0x0e22,
+ 0x7248, 0x0d5b,
+ 0x724b, 0x15e9,
+ 0x724c, 0x0d0d,
+ 0x7252, 0x0bc9,
+ 0x7258, 0x15ea,
+ 0x7259, 0x0567,
+ 0x725b, 0x0687,
+ 0x725d, 0x0ed2,
+ 0x725f, 0x0ec2,
+ 0x7261, 0x0534,
+ 0x7262, 0x0fda,
+ 0x7267, 0x0e80,
+ 0x7269, 0x0dfa,
+ 0x7272, 0x0a5b,
+ 0x7274, 0x15eb,
+ 0x7279, 0x0c9b,
+ 0x727d, 0x0757,
+ 0x727e, 0x15ec,
+ 0x7280, 0x0844,
+ 0x7281, 0x15ee,
+ 0x7282, 0x15ed,
+ 0x7287, 0x15ef,
+ 0x7292, 0x15f0,
+ 0x7296, 0x15f1,
+ 0x72a0, 0x0658,
+ 0x72a2, 0x15f2,
+ 0x72a7, 0x15f3,
+ 0x72ac, 0x0758,
+ 0x72af, 0x0d5c,
+ 0x72b1, 0x2161,
+ 0x72b2, 0x15f5,
+ 0x72b6, 0x09dd,
+ 0x72b9, 0x15f4,
+ 0x72be, 0x2162,
+ 0x72c2, 0x06b0,
+ 0x72c3, 0x15f6,
+ 0x72c4, 0x15f8,
+ 0x72c6, 0x15f7,
+ 0x72ce, 0x15f9,
+ 0x72d0, 0x0785,
+ 0x72d2, 0x15fa,
+ 0x72d7, 0x06e1,
+ 0x72d9, 0x0ac2,
+ 0x72db, 0x080f,
+ 0x72e0, 0x15fc,
+ 0x72e2, 0x15fb,
+ 0x72e9, 0x0919,
+ 0x72ec, 0x0ca0,
+ 0x72ed, 0x06b1,
+ 0x72f7, 0x15ff,
+ 0x72f8, 0x0b6a,
+ 0x72f9, 0x15fe,
+ 0x72fc, 0x0fdb,
+ 0x72fd, 0x0d18,
+ 0x730a, 0x1602,
+ 0x7316, 0x1604,
+ 0x7317, 0x1601,
+ 0x731b, 0x0ee0,
+ 0x731c, 0x1603,
+ 0x731d, 0x1605,
+ 0x731f, 0x0f8c,
+ 0x7324, 0x2163,
+ 0x7325, 0x1609,
+ 0x7329, 0x1608,
+ 0x732a, 0x0bb4,
+ 0x732b, 0x0ce3,
+ 0x732e, 0x0759,
+ 0x732f, 0x1607,
+ 0x7334, 0x1606,
+ 0x7336, 0x0f1b,
+ 0x733e, 0x160a,
+ 0x733f, 0x0510,
+ 0x7344, 0x0808,
+ 0x7345, 0x08b0,
+ 0x734e, 0x160b,
+ 0x7357, 0x160e,
+ 0x7363, 0x094d,
+ 0x7368, 0x1610,
+ 0x736a, 0x160f,
+ 0x7370, 0x1611,
+ 0x7372, 0x05ab,
+ 0x7375, 0x1613,
+ 0x7377, 0x2165,
+ 0x7378, 0x1612,
+ 0x737a, 0x1615,
+ 0x737b, 0x1614,
+ 0x7384, 0x0770,
+ 0x7387, 0x0f70,
+ 0x7389, 0x06c4,
+ 0x738b, 0x0526,
+ 0x7396, 0x06e2,
+ 0x73a9, 0x061d,
+ 0x73b2, 0x0fb0,
+ 0x73b3, 0x1617,
+ 0x73bb, 0x1619,
+ 0x73bd, 0x2166,
+ 0x73c0, 0x161a,
+ 0x73c2, 0x0551,
+ 0x73c8, 0x1616,
+ 0x73c9, 0x2167,
+ 0x73ca, 0x0887,
+ 0x73cd, 0x0bdd,
+ 0x73ce, 0x1618,
+ 0x73d2, 0x216a,
+ 0x73d6, 0x2168,
+ 0x73de, 0x161d,
+ 0x73e0, 0x091a,
+ 0x73e3, 0x2169,
+ 0x73e5, 0x161b,
+ 0x73ea, 0x0714,
+ 0x73ed, 0x0d5d,
+ 0x73ee, 0x161c,
+ 0x73f1, 0x1637,
+ 0x73f5, 0x216c,
+ 0x73f8, 0x1622,
+ 0x73fe, 0x0771,
+ 0x7403, 0x067f,
+ 0x7405, 0x161f,
+ 0x7406, 0x0f67,
+ 0x7407, 0x216b,
+ 0x7409, 0x0f78,
+ 0x7422, 0x0b56,
+ 0x7425, 0x1621,
+ 0x7426, 0x216d,
+ 0x7429, 0x216f,
+ 0x742a, 0x216e,
+ 0x742e, 0x2170,
+ 0x7432, 0x1623,
+ 0x7433, 0x0f9e,
+ 0x7434, 0x06cf,
+ 0x7435, 0x0d90,
+ 0x7436, 0x0d00,
+ 0x743a, 0x1624,
+ 0x743f, 0x1626,
+ 0x7441, 0x1629,
+ 0x7455, 0x1625,
+ 0x7459, 0x1628,
+ 0x745a, 0x079e,
+ 0x745b, 0x04ef,
+ 0x745c, 0x162a,
+ 0x745e, 0x0a36,
+ 0x745f, 0x1627,
+ 0x7460, 0x0fa4,
+ 0x7462, 0x2171,
+ 0x7463, 0x162d,
+ 0x7464, 0x1d35,
+ 0x7469, 0x162b,
+ 0x746a, 0x162e,
+ 0x746f, 0x1620,
+ 0x7470, 0x162c,
+ 0x7473, 0x082c,
+ 0x7476, 0x162f,
+ 0x747e, 0x1630,
+ 0x7483, 0x0f68,
+ 0x7489, 0x2172,
+ 0x748b, 0x1631,
+ 0x749e, 0x1632,
+ 0x749f, 0x2173,
+ 0x74a2, 0x161e,
+ 0x74a7, 0x1633,
+ 0x74b0, 0x0600,
+ 0x74bd, 0x08d1,
+ 0x74ca, 0x1634,
+ 0x74cf, 0x1635,
+ 0x74d4, 0x1636,
+ 0x74dc, 0x04dd,
+ 0x74e0, 0x1638,
+ 0x74e2, 0x0dad,
+ 0x74e3, 0x1639,
+ 0x74e6, 0x05e0,
+ 0x74e7, 0x163a,
+ 0x74e9, 0x163b,
+ 0x74ee, 0x163c,
+ 0x74f0, 0x163e,
+ 0x74f2, 0x163d,
+ 0x74f6, 0x0dc5,
+ 0x74f7, 0x1641,
+ 0x74f8, 0x1640,
+ 0x7501, 0x2174,
+ 0x7503, 0x1643,
+ 0x7504, 0x1642,
+ 0x7505, 0x1644,
+ 0x750c, 0x1645,
+ 0x750d, 0x1647,
+ 0x750e, 0x1646,
+ 0x7511, 0x080b,
+ 0x7513, 0x1649,
+ 0x7515, 0x1648,
+ 0x7518, 0x0601,
+ 0x751a, 0x0a19,
+ 0x751c, 0x0c36,
+ 0x751e, 0x164a,
+ 0x751f, 0x0a5c,
+ 0x7523, 0x0888,
+ 0x7525, 0x051b,
+ 0x7526, 0x164b,
+ 0x7528, 0x0f3b,
+ 0x752b, 0x0e33,
+ 0x752c, 0x164c,
+ 0x752f, 0x20f2,
+ 0x7530, 0x0c3e,
+ 0x7531, 0x0f1d,
+ 0x7532, 0x07d5,
+ 0x7533, 0x0a03,
+ 0x7537, 0x0b89,
+ 0x7538, 0x10c9,
+ 0x753a, 0x0bca,
+ 0x753b, 0x0568,
+ 0x753c, 0x164d,
+ 0x7544, 0x164e,
+ 0x7546, 0x1653,
+ 0x7549, 0x1651,
+ 0x754a, 0x1650,
+ 0x754b, 0x13c7,
+ 0x754c, 0x0584,
+ 0x754d, 0x164f,
+ 0x754f, 0x049e,
+ 0x7551, 0x0d3e,
+ 0x7554, 0x0d5e,
+ 0x7559, 0x0f79,
+ 0x755a, 0x1654,
+ 0x755b, 0x1652,
+ 0x755c, 0x0b9a,
+ 0x755d, 0x0a4a,
+ 0x7560, 0x0d3f,
+ 0x7562, 0x0d9f,
+ 0x7564, 0x1656,
+ 0x7565, 0x0f74,
+ 0x7566, 0x0723,
+ 0x7567, 0x1657,
+ 0x7569, 0x1655,
+ 0x756a, 0x0d6a,
+ 0x756b, 0x1658,
+ 0x756d, 0x1659,
+ 0x756f, 0x2175,
+ 0x7570, 0x049f,
+ 0x7573, 0x09de,
+ 0x7574, 0x165e,
+ 0x7576, 0x165b,
+ 0x7577, 0x0cc5,
+ 0x7578, 0x165a,
+ 0x757f, 0x0640,
+ 0x7582, 0x1661,
+ 0x7586, 0x165c,
+ 0x7589, 0x1660,
+ 0x758a, 0x165f,
+ 0x758b, 0x0d97,
+ 0x758e, 0x0ac4,
+ 0x758f, 0x0ac3,
+ 0x7591, 0x0659,
+ 0x7594, 0x1662,
+ 0x759a, 0x1663,
+ 0x759d, 0x1664,
+ 0x75a3, 0x1666,
+ 0x75a5, 0x1665,
+ 0x75ab, 0x04f8,
+ 0x75b1, 0x166e,
+ 0x75b2, 0x0d7c,
+ 0x75b3, 0x1668,
+ 0x75b5, 0x166a,
+ 0x75b8, 0x166c,
+ 0x75b9, 0x0a04,
+ 0x75bc, 0x166d,
+ 0x75bd, 0x166b,
+ 0x75be, 0x08ec,
+ 0x75c2, 0x1667,
+ 0x75c3, 0x1669,
+ 0x75c5, 0x0db4,
+ 0x75c7, 0x09b1,
+ 0x75ca, 0x1670,
+ 0x75cd, 0x166f,
+ 0x75d2, 0x1671,
+ 0x75d4, 0x08d2,
+ 0x75d5, 0x081f,
+ 0x75d8, 0x0c71,
+ 0x75d9, 0x1672,
+ 0x75db, 0x0be7,
+ 0x75de, 0x1674,
+ 0x75e2, 0x0f69,
+ 0x75e3, 0x1673,
+ 0x75e9, 0x0aeb,
+ 0x75f0, 0x1679,
+ 0x75f2, 0x167b,
+ 0x75f4, 0x0b92,
+ 0x75fa, 0x167a,
+ 0x75fc, 0x1677,
+ 0x75fe, 0x1675,
+ 0x7601, 0x1678,
+ 0x7609, 0x167f,
+ 0x760b, 0x167d,
+ 0x760d, 0x167e,
+ 0x761f, 0x1680,
+ 0x7620, 0x1682,
+ 0x7624, 0x1685,
+ 0x7626, 0x1e2d,
+ 0x7627, 0x1681,
+ 0x7630, 0x1687,
+ 0x7634, 0x1686,
+ 0x763b, 0x1688,
+ 0x7642, 0x0f8d,
+ 0x7646, 0x168b,
+ 0x7647, 0x1689,
+ 0x764c, 0x061e,
+ 0x7652, 0x0f0a,
+ 0x7656, 0x0e1a,
+ 0x7658, 0x168d,
+ 0x765c, 0x168c,
+ 0x7661, 0x168e,
+ 0x7667, 0x1693,
+ 0x7668, 0x1690,
+ 0x766c, 0x1694,
+ 0x7670, 0x1695,
+ 0x7672, 0x1696,
+ 0x7676, 0x1697,
+ 0x7678, 0x1698,
+ 0x767a, 0x0d43,
+ 0x767b, 0x0c4a,
+ 0x767c, 0x1699,
+ 0x767d, 0x0d28,
+ 0x767e, 0x0da6,
+ 0x7680, 0x169a,
+ 0x7682, 0x2176,
+ 0x7683, 0x169b,
+ 0x7684, 0x0c24,
+ 0x7686, 0x0585,
+ 0x7687, 0x07d6,
+ 0x7688, 0x169c,
+ 0x768b, 0x169d,
+ 0x768e, 0x169e,
+ 0x7690, 0x0877,
+ 0x7693, 0x16a0,
+ 0x7696, 0x169f,
+ 0x7699, 0x16a1,
+ 0x769b, 0x2179,
+ 0x769c, 0x2177,
+ 0x769e, 0x2178,
+ 0x76a6, 0x217a,
+ 0x76ae, 0x0d7d,
+ 0x76b0, 0x16a3,
+ 0x76b4, 0x16a4,
+ 0x76b7, 0x1d1c,
+ 0x76b8, 0x16a5,
+ 0x76bf, 0x087c,
+ 0x76c2, 0x16a8,
+ 0x76c3, 0x0d0c,
+ 0x76c6, 0x0e8d,
+ 0x76c8, 0x04f0,
+ 0x76ca, 0x04f9,
+ 0x76cd, 0x16a9,
+ 0x76d2, 0x16ab,
+ 0x76d6, 0x16aa,
+ 0x76d7, 0x0c6a,
+ 0x76db, 0x0a5d,
+ 0x76dc, 0x14d8,
+ 0x76de, 0x16ac,
+ 0x76df, 0x0ecd,
+ 0x76e1, 0x16ad,
+ 0x76e3, 0x0602,
+ 0x76e4, 0x0d6b,
+ 0x76e5, 0x16ae,
+ 0x76e7, 0x16af,
+ 0x76ea, 0x16b0,
+ 0x76ee, 0x0ee8,
+ 0x76f2, 0x0ee1,
+ 0x76f4, 0x0bda,
+ 0x76f8, 0x0aec,
+ 0x76fb, 0x16b2,
+ 0x76fe, 0x096c,
+ 0x7701, 0x09b2,
+ 0x7704, 0x16b5,
+ 0x7707, 0x16b4,
+ 0x7708, 0x16b3,
+ 0x7709, 0x0d91,
+ 0x770b, 0x0603,
+ 0x770c, 0x075d,
+ 0x771b, 0x16bb,
+ 0x771e, 0x16b8,
+ 0x771f, 0x0a05,
+ 0x7720, 0x0ebe,
+ 0x7724, 0x16b7,
+ 0x7725, 0x16b9,
+ 0x7729, 0x16b6,
+ 0x7737, 0x16bc,
+ 0x773a, 0x0bcb,
+ 0x773c, 0x061f,
+ 0x7740, 0x0ba3,
+ 0x7746, 0x217c,
+ 0x7747, 0x16be,
+ 0x775a, 0x16bf,
+ 0x775b, 0x16c2,
+ 0x7761, 0x0a2d,
+ 0x7762, 0x1ec5,
+ 0x7763, 0x0c9c,
+ 0x7765, 0x16c3,
+ 0x7766, 0x0e81,
+ 0x7768, 0x16c0,
+ 0x776b, 0x16c1,
+ 0x7779, 0x16c6,
+ 0x777e, 0x16c5,
+ 0x777f, 0x16c4,
+ 0x778b, 0x16c8,
+ 0x778e, 0x16c7,
+ 0x7791, 0x16c9,
+ 0x779e, 0x16cb,
+ 0x77a0, 0x16ca,
+ 0x77a5, 0x0e1d,
+ 0x77ac, 0x0960,
+ 0x77ad, 0x0f8e,
+ 0x77b0, 0x16cc,
+ 0x77b3, 0x0c8f,
+ 0x77b6, 0x16cd,
+ 0x77b9, 0x16ce,
+ 0x77bb, 0x16d2,
+ 0x77bc, 0x16d0,
+ 0x77bf, 0x16cf,
+ 0x77c7, 0x16d3,
+ 0x77cd, 0x16d4,
+ 0x77d7, 0x16d5,
+ 0x77da, 0x16d6,
+ 0x77db, 0x0ec3,
+ 0x77dc, 0x16d7,
+ 0x77e2, 0x0efc,
+ 0x77e3, 0x16d8,
+ 0x77e5, 0x0b8c,
+ 0x77e7, 0x0d20,
+ 0x77e9, 0x06e3,
+ 0x77ed, 0x0b79,
+ 0x77ee, 0x16d9,
+ 0x77ef, 0x06b2,
+ 0x77f3, 0x0a74,
+ 0x77fc, 0x16da,
+ 0x7802, 0x082d,
+ 0x780c, 0x16db,
+ 0x7812, 0x16dc,
+ 0x7814, 0x075a,
+ 0x7815, 0x0845,
+ 0x7820, 0x16de,
+ 0x7821, 0x217e,
+ 0x7825, 0x0c50,
+ 0x7826, 0x0846,
+ 0x7827, 0x0668,
+ 0x7832, 0x0e52,
+ 0x7834, 0x0d01,
+ 0x783a, 0x0c51,
+ 0x783f, 0x07ee,
+ 0x7845, 0x16e0,
+ 0x784e, 0x217f,
+ 0x785d, 0x09b3,
+ 0x7864, 0x2180,
+ 0x786b, 0x0f7a,
+ 0x786c, 0x07d7,
+ 0x786f, 0x075b,
+ 0x7872, 0x0d37,
+ 0x7874, 0x16e2,
+ 0x787a, 0x2181,
+ 0x787c, 0x16e4,
+ 0x7881, 0x079f,
+ 0x7886, 0x16e3,
+ 0x7887, 0x0c12,
+ 0x788c, 0x16e6,
+ 0x788d, 0x0595,
+ 0x788e, 0x16e1,
+ 0x7891, 0x0d7e,
+ 0x7893, 0x04d2,
+ 0x7895, 0x085c,
+ 0x7897, 0x0ff8,
+ 0x789a, 0x16e5,
+ 0x78a3, 0x16e7,
+ 0x78a7, 0x0e1b,
+ 0x78a9, 0x0a7d,
+ 0x78aa, 0x16e9,
+ 0x78af, 0x16ea,
+ 0x78b5, 0x16e8,
+ 0x78ba, 0x05ac,
+ 0x78bc, 0x16f0,
+ 0x78be, 0x16ef,
+ 0x78c1, 0x08d3,
+ 0x78c5, 0x16f1,
+ 0x78c6, 0x16ec,
+ 0x78ca, 0x16f2,
+ 0x78cb, 0x16ed,
+ 0x78d0, 0x0d6c,
+ 0x78d1, 0x16eb,
+ 0x78d4, 0x16ee,
+ 0x78da, 0x16f5,
+ 0x78e7, 0x16f4,
+ 0x78e8, 0x0e8f,
+ 0x78ec, 0x16f3,
+ 0x78ef, 0x04af,
+ 0x78f4, 0x16f7,
+ 0x78fd, 0x16f6,
+ 0x7901, 0x09b4,
+ 0x7907, 0x16f8,
+ 0x790e, 0x0ac5,
+ 0x7911, 0x16fa,
+ 0x7912, 0x16f9,
+ 0x7919, 0x16fb,
+ 0x7926, 0x16dd,
+ 0x792a, 0x16df,
+ 0x792b, 0x16fd,
+ 0x792c, 0x16fc,
+ 0x7930, 0x2182,
+ 0x793a, 0x08d4,
+ 0x793c, 0x0fb1,
+ 0x793e, 0x08fe,
+ 0x7940, 0x16fe,
+ 0x7941, 0x070d,
+ 0x7947, 0x065a,
+ 0x7948, 0x0641,
+ 0x7949, 0x08b1,
+ 0x7950, 0x0f1e,
+ 0x7953, 0x1704,
+ 0x7955, 0x1703,
+ 0x7956, 0x0ac6,
+ 0x7957, 0x1700,
+ 0x795a, 0x1702,
+ 0x795d, 0x0955,
+ 0x795e, 0x0a06,
+ 0x795f, 0x1701,
+ 0x7960, 0x16ff,
+ 0x7962, 0x0ce0,
+ 0x7965, 0x09b5,
+ 0x7968, 0x0dae,
+ 0x796d, 0x0847,
+ 0x7977, 0x0c72,
+ 0x797a, 0x1705,
+ 0x797f, 0x1706,
+ 0x7980, 0x171c,
+ 0x7981, 0x06d0,
+ 0x7984, 0x0fe3,
+ 0x7985, 0x0ab7,
+ 0x798a, 0x1707,
+ 0x798d, 0x0552,
+ 0x798e, 0x0c13,
+ 0x798f, 0x0df1,
+ 0x7994, 0x2186,
+ 0x799b, 0x2188,
+ 0x799d, 0x1708,
+ 0x79a6, 0x0694,
+ 0x79a7, 0x1709,
+ 0x79aa, 0x170b,
+ 0x79ae, 0x170c,
+ 0x79b0, 0x0cdf,
+ 0x79b1, 0x1e4e,
+ 0x79b3, 0x170d,
+ 0x79b9, 0x170e,
+ 0x79bd, 0x06d1,
+ 0x79be, 0x0553,
+ 0x79bf, 0x0c9d,
+ 0x79c0, 0x0932,
+ 0x79c1, 0x08b2,
+ 0x79c9, 0x1710,
+ 0x79cb, 0x0933,
+ 0x79d1, 0x054a,
+ 0x79d2, 0x0db5,
+ 0x79d5, 0x1711,
+ 0x79d8, 0x0d7f,
+ 0x79df, 0x0ac7,
+ 0x79e1, 0x1714,
+ 0x79e3, 0x1715,
+ 0x79e4, 0x0d1f,
+ 0x79e6, 0x0a07,
+ 0x79e7, 0x1712,
+ 0x79e9, 0x0b9f,
+ 0x79ec, 0x1713,
+ 0x79f0, 0x09b6,
+ 0x79fb, 0x04a0,
+ 0x7a00, 0x0643,
+ 0x7a08, 0x1716,
+ 0x7a0b, 0x0c14,
+ 0x7a0d, 0x1717,
+ 0x7a0e, 0x0a6b,
+ 0x7a14, 0x0eb9,
+ 0x7a17, 0x0d95,
+ 0x7a18, 0x1718,
+ 0x7a1a, 0x0b93,
+ 0x7a1c, 0x0f8f,
+ 0x7a1f, 0x171b,
+ 0x7a20, 0x171a,
+ 0x7a2e, 0x091b,
+ 0x7a31, 0x171d,
+ 0x7a32, 0x04b4,
+ 0x7a37, 0x1720,
+ 0x7a3b, 0x171e,
+ 0x7a3c, 0x0554,
+ 0x7a3d, 0x0724,
+ 0x7a3e, 0x171f,
+ 0x7a3f, 0x07d8,
+ 0x7a40, 0x0804,
+ 0x7a42, 0x0e36,
+ 0x7a43, 0x1721,
+ 0x7a46, 0x0e82,
+ 0x7a49, 0x1723,
+ 0x7a4d, 0x0a75,
+ 0x7a4e, 0x04f1,
+ 0x7a4f, 0x053a,
+ 0x7a50, 0x0470,
+ 0x7a57, 0x1722,
+ 0x7a61, 0x1724,
+ 0x7a63, 0x09df,
+ 0x7a69, 0x1726,
+ 0x7a6b, 0x05ad,
+ 0x7a70, 0x1728,
+ 0x7a74, 0x0740,
+ 0x7a76, 0x0680,
+ 0x7a79, 0x1729,
+ 0x7a7a, 0x06ed,
+ 0x7a7d, 0x172a,
+ 0x7a7f, 0x0aa0,
+ 0x7a81, 0x0ca5,
+ 0x7a83, 0x0a84,
+ 0x7a84, 0x0865,
+ 0x7a88, 0x172b,
+ 0x7a92, 0x0ba0,
+ 0x7a93, 0x0aed,
+ 0x7a95, 0x172d,
+ 0x7a96, 0x172f,
+ 0x7a97, 0x172c,
+ 0x7a98, 0x172e,
+ 0x7a9f, 0x06f8,
+ 0x7aa9, 0x1730,
+ 0x7aaa, 0x06fc,
+ 0x7aae, 0x0681,
+ 0x7aaf, 0x0f3c,
+ 0x7ab0, 0x1732,
+ 0x7ab6, 0x1733,
+ 0x7aba, 0x04d0,
+ 0x7abf, 0x1736,
+ 0x7ac3, 0x05d4,
+ 0x7ac4, 0x1735,
+ 0x7ac5, 0x1734,
+ 0x7ac7, 0x1738,
+ 0x7ac8, 0x1731,
+ 0x7aca, 0x1739,
+ 0x7acb, 0x0f71,
+ 0x7acd, 0x173a,
+ 0x7acf, 0x173b,
+ 0x7ad1, 0x2189,
+ 0x7ad2, 0x11c5,
+ 0x7ad3, 0x173d,
+ 0x7ad5, 0x173c,
+ 0x7ad9, 0x173e,
+ 0x7adc, 0x0f7d,
+ 0x7add, 0x1740,
+ 0x7adf, 0x1c08,
+ 0x7ae0, 0x09b7,
+ 0x7ae1, 0x1741,
+ 0x7ae3, 0x0961,
+ 0x7ae5, 0x0c90,
+ 0x7ae6, 0x1743,
+ 0x7ae7, 0x218a,
+ 0x7aea, 0x0b66,
+ 0x7aeb, 0x218c,
+ 0x7aed, 0x1744,
+ 0x7aef, 0x0b7a,
+ 0x7af0, 0x1745,
+ 0x7af6, 0x069d,
+ 0x7af8, 0x1076,
+ 0x7af9, 0x0b9b,
+ 0x7afa, 0x08df,
+ 0x7aff, 0x0604,
+ 0x7b02, 0x1746,
+ 0x7b04, 0x1753,
+ 0x7b06, 0x1749,
+ 0x7b08, 0x0682,
+ 0x7b0a, 0x1748,
+ 0x7b0b, 0x1755,
+ 0x7b0f, 0x1747,
+ 0x7b11, 0x09b8,
+ 0x7b18, 0x174b,
+ 0x7b1b, 0x0c25,
+ 0x7b1e, 0x174d,
+ 0x7b20, 0x05bc,
+ 0x7b25, 0x0a20,
+ 0x7b26, 0x0dd6,
+ 0x7b28, 0x174f,
+ 0x7b2c, 0x0b48,
+ 0x7b33, 0x174a,
+ 0x7b35, 0x174e,
+ 0x7b36, 0x1750,
+ 0x7b39, 0x086b,
+ 0x7b45, 0x1757,
+ 0x7b46, 0x0da0,
+ 0x7b48, 0x0d3a,
+ 0x7b49, 0x0c73,
+ 0x7b4b, 0x06d2,
+ 0x7b4c, 0x1756,
+ 0x7b4d, 0x1754,
+ 0x7b4f, 0x0d49,
+ 0x7b50, 0x1751,
+ 0x7b51, 0x0b9c,
+ 0x7b52, 0x0c75,
+ 0x7b54, 0x0c74,
+ 0x7b56, 0x0866,
+ 0x7b5d, 0x1769,
+ 0x7b65, 0x1759,
+ 0x7b67, 0x175b,
+ 0x7b6c, 0x175e,
+ 0x7b6e, 0x175f,
+ 0x7b70, 0x175c,
+ 0x7b74, 0x175a,
+ 0x7b75, 0x1758,
+ 0x7b7a, 0x1752,
+ 0x7b86, 0x0e1f,
+ 0x7b87, 0x0555,
+ 0x7b8b, 0x1766,
+ 0x7b8d, 0x1763,
+ 0x7b8f, 0x1768,
+ 0x7b92, 0x1767,
+ 0x7b94, 0x0d29,
+ 0x7b95, 0x0eb3,
+ 0x7b97, 0x0889,
+ 0x7b98, 0x1761,
+ 0x7b99, 0x176a,
+ 0x7b9a, 0x1765,
+ 0x7b9c, 0x1764,
+ 0x7b9d, 0x1760,
+ 0x7b9e, 0x218d,
+ 0x7b9f, 0x1762,
+ 0x7ba1, 0x0605,
+ 0x7baa, 0x0b7b,
+ 0x7bad, 0x0aa1,
+ 0x7bb1, 0x0d36,
+ 0x7bb4, 0x176f,
+ 0x7bb8, 0x0d38,
+ 0x7bc0, 0x0a85,
+ 0x7bc1, 0x176c,
+ 0x7bc4, 0x0d63,
+ 0x7bc6, 0x1770,
+ 0x7bc7, 0x0e23,
+ 0x7bc9, 0x0b99,
+ 0x7bcb, 0x176b,
+ 0x7bcc, 0x176d,
+ 0x7bcf, 0x176e,
+ 0x7bdd, 0x1771,
+ 0x7be0, 0x08f0,
+ 0x7be4, 0x0c9e,
+ 0x7be5, 0x1776,
+ 0x7be6, 0x1775,
+ 0x7be9, 0x1772,
+ 0x7bed, 0x0fdc,
+ 0x7bf3, 0x177b,
+ 0x7bf6, 0x177f,
+ 0x7bf7, 0x177c,
+ 0x7c00, 0x1778,
+ 0x7c07, 0x1779,
+ 0x7c0d, 0x177e,
+ 0x7c11, 0x1773,
+ 0x7c12, 0x10ea,
+ 0x7c13, 0x177a,
+ 0x7c14, 0x1774,
+ 0x7c17, 0x177d,
+ 0x7c1e, 0x1e3b,
+ 0x7c1f, 0x1783,
+ 0x7c21, 0x0606,
+ 0x7c23, 0x1780,
+ 0x7c27, 0x1781,
+ 0x7c2a, 0x1782,
+ 0x7c2b, 0x1785,
+ 0x7c37, 0x1784,
+ 0x7c38, 0x0d8a,
+ 0x7c3d, 0x1786,
+ 0x7c3e, 0x0fc4,
+ 0x7c3f, 0x0e3d,
+ 0x7c40, 0x178b,
+ 0x7c43, 0x1788,
+ 0x7c4c, 0x1787,
+ 0x7c4d, 0x0a76,
+ 0x7c4f, 0x178a,
+ 0x7c50, 0x178c,
+ 0x7c54, 0x1789,
+ 0x7c56, 0x1790,
+ 0x7c58, 0x178d,
+ 0x7c5f, 0x178e,
+ 0x7c60, 0x1777,
+ 0x7c64, 0x178f,
+ 0x7c65, 0x1791,
+ 0x7c6c, 0x1792,
+ 0x7c73, 0x0e16,
+ 0x7c75, 0x1793,
+ 0x7c7e, 0x0eee,
+ 0x7c81, 0x06c6,
+ 0x7c82, 0x06ff,
+ 0x7c83, 0x1794,
+ 0x7c89, 0x0e04,
+ 0x7c8b, 0x0a2e,
+ 0x7c8d, 0x0ebc,
+ 0x7c90, 0x1795,
+ 0x7c92, 0x0f7b,
+ 0x7c95, 0x0d2a,
+ 0x7c97, 0x0ac8,
+ 0x7c98, 0x0cea,
+ 0x7c9b, 0x0957,
+ 0x7c9f, 0x0484,
+ 0x7ca1, 0x179a,
+ 0x7ca2, 0x1798,
+ 0x7ca4, 0x1796,
+ 0x7ca5, 0x05dd,
+ 0x7ca7, 0x09b9,
+ 0x7ca8, 0x179b,
+ 0x7cab, 0x1799,
+ 0x7cad, 0x1797,
+ 0x7cae, 0x179f,
+ 0x7cb1, 0x179e,
+ 0x7cb2, 0x179d,
+ 0x7cb3, 0x179c,
+ 0x7cb9, 0x17a0,
+ 0x7cbd, 0x17a1,
+ 0x7cbe, 0x0a5e,
+ 0x7cc0, 0x17a2,
+ 0x7cc2, 0x17a4,
+ 0x7cc5, 0x17a3,
+ 0x7cca, 0x0786,
+ 0x7cce, 0x0aba,
+ 0x7cd2, 0x17a6,
+ 0x7cd6, 0x0c76,
+ 0x7cd8, 0x17a5,
+ 0x7cdc, 0x17a7,
+ 0x7cde, 0x0e05,
+ 0x7cdf, 0x0aee,
+ 0x7ce0, 0x07d9,
+ 0x7ce2, 0x17a8,
+ 0x7ce7, 0x0f90,
+ 0x7cef, 0x17aa,
+ 0x7cf2, 0x17ab,
+ 0x7cf4, 0x17ac,
+ 0x7cf6, 0x17ad,
+ 0x7cf8, 0x08b3,
+ 0x7cfa, 0x17ae,
+ 0x7cfb, 0x0725,
+ 0x7cfe, 0x0684,
+ 0x7d00, 0x0644,
+ 0x7d02, 0x17b0,
+ 0x7d04, 0x0eff,
+ 0x7d05, 0x07da,
+ 0x7d06, 0x17af,
+ 0x7d0a, 0x17b3,
+ 0x7d0b, 0x0ef2,
+ 0x7d0d, 0x0cf2,
+ 0x7d10, 0x0da5,
+ 0x7d14, 0x096d,
+ 0x7d15, 0x17b2,
+ 0x7d17, 0x08ff,
+ 0x7d18, 0x07db,
+ 0x7d19, 0x08b4,
+ 0x7d1a, 0x0683,
+ 0x7d1b, 0x0e06,
+ 0x7d1c, 0x17b1,
+ 0x7d20, 0x0ac9,
+ 0x7d21, 0x0e70,
+ 0x7d22, 0x0867,
+ 0x7d2b, 0x08b5,
+ 0x7d2c, 0x0bf9,
+ 0x7d2e, 0x17b6,
+ 0x7d2f, 0x0fa7,
+ 0x7d30, 0x0849,
+ 0x7d32, 0x17b7,
+ 0x7d33, 0x0a08,
+ 0x7d35, 0x17b9,
+ 0x7d39, 0x09ba,
+ 0x7d3a, 0x0820,
+ 0x7d3f, 0x17b8,
+ 0x7d42, 0x0934,
+ 0x7d43, 0x0772,
+ 0x7d44, 0x0aca,
+ 0x7d45, 0x17b4,
+ 0x7d46, 0x17ba,
+ 0x7d48, 0x218f,
+ 0x7d4b, 0x17b5,
+ 0x7d4c, 0x0726,
+ 0x7d4e, 0x17bd,
+ 0x7d4f, 0x17c1,
+ 0x7d50, 0x0741,
+ 0x7d56, 0x17bc,
+ 0x7d5b, 0x17c5,
+ 0x7d5c, 0x2190,
+ 0x7d5e, 0x07dc,
+ 0x7d61, 0x0f57,
+ 0x7d62, 0x0480,
+ 0x7d63, 0x17c2,
+ 0x7d66, 0x0685,
+ 0x7d68, 0x17bf,
+ 0x7d6e, 0x17c0,
+ 0x7d71, 0x0c77,
+ 0x7d72, 0x17be,
+ 0x7d73, 0x17bb,
+ 0x7d75, 0x0586,
+ 0x7d76, 0x0a88,
+ 0x7d79, 0x075c,
+ 0x7d7d, 0x17c7,
+ 0x7d89, 0x17c4,
+ 0x7d8f, 0x17c6,
+ 0x7d93, 0x17c3,
+ 0x7d99, 0x0727,
+ 0x7d9a, 0x0b13,
+ 0x7d9b, 0x17c8,
+ 0x7d9c, 0x0af0,
+ 0x7d9f, 0x17d5,
+ 0x7da0, 0x2192,
+ 0x7da2, 0x17d1,
+ 0x7da3, 0x17cb,
+ 0x7dab, 0x17cf,
+ 0x7dac, 0x0926,
+ 0x7dad, 0x04a1,
+ 0x7dae, 0x17ca,
+ 0x7daf, 0x17d2,
+ 0x7db0, 0x17d6,
+ 0x7db1, 0x07dd,
+ 0x7db2, 0x0ee2,
+ 0x7db4, 0x0bf2,
+ 0x7db5, 0x17cc,
+ 0x7db7, 0x2191,
+ 0x7db8, 0x17d4,
+ 0x7dba, 0x17c9,
+ 0x7dbb, 0x0b7c,
+ 0x7dbd, 0x17ce,
+ 0x7dbe, 0x0481,
+ 0x7dbf, 0x0ed6,
+ 0x7dc7, 0x17cd,
+ 0x7dca, 0x06d3,
+ 0x7dcb, 0x0d80,
+ 0x7dcf, 0x0aef,
+ 0x7dd1, 0x0f98,
+ 0x7dd2, 0x0979,
+ 0x7dd5, 0x17fd,
+ 0x7dd6, 0x2193,
+ 0x7dd8, 0x17d7,
+ 0x7dda, 0x0aa2,
+ 0x7ddc, 0x17d3,
+ 0x7ddd, 0x17d8,
+ 0x7dde, 0x17da,
+ 0x7de0, 0x0c15,
+ 0x7de1, 0x17dd,
+ 0x7de4, 0x17d9,
+ 0x7de8, 0x0e24,
+ 0x7de9, 0x0607,
+ 0x7dec, 0x0ed7,
+ 0x7def, 0x04a2,
+ 0x7df2, 0x17dc,
+ 0x7df4, 0x0fc5,
+ 0x7dfb, 0x17db,
+ 0x7e01, 0x0511,
+ 0x7e04, 0x0cc4,
+ 0x7e05, 0x17de,
+ 0x7e09, 0x17e5,
+ 0x7e0a, 0x17df,
+ 0x7e0b, 0x17e6,
+ 0x7e12, 0x17e2,
+ 0x7e1b, 0x0d31,
+ 0x7e1e, 0x08f6,
+ 0x7e1f, 0x17e4,
+ 0x7e21, 0x17e1,
+ 0x7e22, 0x17e7,
+ 0x7e23, 0x17e0,
+ 0x7e26, 0x094e,
+ 0x7e2b, 0x0e53,
+ 0x7e2e, 0x0956,
+ 0x7e31, 0x17e3,
+ 0x7e32, 0x17ef,
+ 0x7e35, 0x17eb,
+ 0x7e37, 0x17ee,
+ 0x7e39, 0x17ec,
+ 0x7e3a, 0x17f0,
+ 0x7e3b, 0x17ea,
+ 0x7e3d, 0x17d0,
+ 0x7e3e, 0x0a77,
+ 0x7e41, 0x0d5f,
+ 0x7e43, 0x17ed,
+ 0x7e46, 0x17e8,
+ 0x7e4a, 0x0aa3,
+ 0x7e4b, 0x0728,
+ 0x7e4d, 0x0935,
+ 0x7e52, 0x2194,
+ 0x7e54, 0x09eb,
+ 0x7e55, 0x0ab8,
+ 0x7e56, 0x17f3,
+ 0x7e59, 0x17f5,
+ 0x7e5d, 0x17f2,
+ 0x7e5e, 0x17f4,
+ 0x7e61, 0x1e11,
+ 0x7e66, 0x17e9,
+ 0x7e67, 0x17f1,
+ 0x7e69, 0x17f9,
+ 0x7e6a, 0x17f8,
+ 0x7e6b, 0x1df7,
+ 0x7e6d, 0x0ea8,
+ 0x7e70, 0x0701,
+ 0x7e79, 0x17f7,
+ 0x7e7b, 0x17fb,
+ 0x7e7c, 0x17fa,
+ 0x7e7d, 0x17fe,
+ 0x7e7f, 0x1800,
+ 0x7e82, 0x088a,
+ 0x7e83, 0x17fc,
+ 0x7e88, 0x1801,
+ 0x7e8a, 0x20a7,
+ 0x7e8c, 0x1803,
+ 0x7e8e, 0x1809,
+ 0x7e8f, 0x0c35,
+ 0x7e90, 0x1805,
+ 0x7e92, 0x1804,
+ 0x7e93, 0x1806,
+ 0x7e96, 0x1808,
+ 0x7e9b, 0x180a,
+ 0x7f36, 0x0608,
+ 0x7f38, 0x180c,
+ 0x7f3a, 0x180d,
+ 0x7f45, 0x180e,
+ 0x7f47, 0x2195,
+ 0x7f4c, 0x180f,
+ 0x7f50, 0x1812,
+ 0x7f54, 0x1815,
+ 0x7f55, 0x1814,
+ 0x7f58, 0x1816,
+ 0x7f5f, 0x1817,
+ 0x7f67, 0x181b,
+ 0x7f68, 0x1819,
+ 0x7f6a, 0x0851,
+ 0x7f6b, 0x0729,
+ 0x7f6e, 0x0b94,
+ 0x7f70, 0x0d47,
+ 0x7f72, 0x097a,
+ 0x7f75, 0x0d03,
+ 0x7f77, 0x0d81,
+ 0x7f78, 0x181c,
+ 0x7f79, 0x1336,
+ 0x7f82, 0x181d,
+ 0x7f83, 0x181f,
+ 0x7f85, 0x0f4f,
+ 0x7f86, 0x181e,
+ 0x7f87, 0x1821,
+ 0x7f88, 0x1820,
+ 0x7f8a, 0x0f3d,
+ 0x7f8c, 0x1822,
+ 0x7f8e, 0x0d92,
+ 0x7f94, 0x1823,
+ 0x7f9a, 0x1826,
+ 0x7f9d, 0x1825,
+ 0x7f9e, 0x1824,
+ 0x7fa1, 0x2196,
+ 0x7fa3, 0x1827,
+ 0x7fa4, 0x0708,
+ 0x7fa8, 0x0aa4,
+ 0x7fa9, 0x065b,
+ 0x7fae, 0x182b,
+ 0x7faf, 0x1828,
+ 0x7fb2, 0x1829,
+ 0x7fb6, 0x182c,
+ 0x7fb8, 0x182d,
+ 0x7fb9, 0x182a,
+ 0x7fbd, 0x04cb,
+ 0x7fc1, 0x0527,
+ 0x7fc5, 0x182f,
+ 0x7fca, 0x1831,
+ 0x7fcc, 0x0f4c,
+ 0x7fd2, 0x0936,
+ 0x7fd4, 0x1833,
+ 0x7fd5, 0x1832,
+ 0x7fe0, 0x0a2f,
+ 0x7fe1, 0x1834,
+ 0x7fe6, 0x1835,
+ 0x7fe9, 0x1836,
+ 0x7feb, 0x0621,
+ 0x7ff0, 0x0609,
+ 0x7ff3, 0x1837,
+ 0x7ff9, 0x1838,
+ 0x7ffb, 0x0e8b,
+ 0x7ffc, 0x0f4d,
+ 0x8000, 0x0f3e,
+ 0x8001, 0x0fdd,
+ 0x8003, 0x07df,
+ 0x8004, 0x183b,
+ 0x8005, 0x0900,
+ 0x8006, 0x183a,
+ 0x800b, 0x183c,
+ 0x800c, 0x08d5,
+ 0x8010, 0x0b31,
+ 0x8012, 0x183d,
+ 0x8015, 0x07de,
+ 0x8017, 0x0ee3,
+ 0x8018, 0x183e,
+ 0x801c, 0x1840,
+ 0x8021, 0x1841,
+ 0x8028, 0x1842,
+ 0x8033, 0x08d6,
+ 0x8036, 0x0ef9,
+ 0x803b, 0x1844,
+ 0x803d, 0x0b7d,
+ 0x803f, 0x1843,
+ 0x8046, 0x1846,
+ 0x804a, 0x1845,
+ 0x8052, 0x1847,
+ 0x8056, 0x0a5f,
+ 0x8058, 0x1848,
+ 0x805a, 0x1849,
+ 0x805e, 0x0e09,
+ 0x805f, 0x184a,
+ 0x8061, 0x0af1,
+ 0x8062, 0x184b,
+ 0x8068, 0x184c,
+ 0x806f, 0x0fc6,
+ 0x8070, 0x184f,
+ 0x8072, 0x184e,
+ 0x8073, 0x184d,
+ 0x8074, 0x0bcc,
+ 0x8076, 0x1850,
+ 0x8077, 0x09ec,
+ 0x8079, 0x1851,
+ 0x807d, 0x1852,
+ 0x807e, 0x0fde,
+ 0x807f, 0x1853,
+ 0x8084, 0x1854,
+ 0x8085, 0x1856,
+ 0x8086, 0x1855,
+ 0x8087, 0x0d39,
+ 0x8089, 0x0cd1,
+ 0x808b, 0x0fe4,
+ 0x808c, 0x0d3d,
+ 0x8093, 0x1858,
+ 0x8096, 0x09bb,
+ 0x8098, 0x0d9c,
+ 0x809a, 0x1859,
+ 0x809b, 0x1857,
+ 0x809d, 0x060a,
+ 0x80a1, 0x0788,
+ 0x80a2, 0x08b6,
+ 0x80a5, 0x0d82,
+ 0x80a9, 0x075e,
+ 0x80aa, 0x0e71,
+ 0x80ac, 0x185c,
+ 0x80ad, 0x185a,
+ 0x80af, 0x07e0,
+ 0x80b1, 0x07e1,
+ 0x80b2, 0x04ad,
+ 0x80b4, 0x0858,
+ 0x80ba, 0x0d0f,
+ 0x80c3, 0x04a3,
+ 0x80c4, 0x1861,
+ 0x80c6, 0x0b7e,
+ 0x80cc, 0x0d0e,
+ 0x80ce, 0x0b3b,
+ 0x80d6, 0x1863,
+ 0x80d9, 0x185f,
+ 0x80da, 0x1862,
+ 0x80db, 0x185d,
+ 0x80dd, 0x1860,
+ 0x80de, 0x0e54,
+ 0x80e1, 0x0789,
+ 0x80e4, 0x04c1,
+ 0x80e5, 0x185e,
+ 0x80ef, 0x1865,
+ 0x80f1, 0x1866,
+ 0x80f4, 0x0c91,
+ 0x80f8, 0x06b3,
+ 0x80fc, 0x1871,
+ 0x80fd, 0x0cf3,
+ 0x8102, 0x08b7,
+ 0x8105, 0x06b4,
+ 0x8106, 0x0a6c,
+ 0x8107, 0x0fec,
+ 0x8108, 0x0eba,
+ 0x8109, 0x1864,
+ 0x810a, 0x0a78,
+ 0x811a, 0x066d,
+ 0x811b, 0x1867,
+ 0x8123, 0x1869,
+ 0x8129, 0x1868,
+ 0x812f, 0x186a,
+ 0x8131, 0x0b64,
+ 0x8133, 0x0cf4,
+ 0x8139, 0x0bcd,
+ 0x813e, 0x186e,
+ 0x8146, 0x186d,
+ 0x814b, 0x186b,
+ 0x814e, 0x0a1b,
+ 0x8150, 0x0dd7,
+ 0x8151, 0x1870,
+ 0x8153, 0x186f,
+ 0x8154, 0x07e2,
+ 0x8155, 0x0ff9,
+ 0x815f, 0x1880,
+ 0x8165, 0x1874,
+ 0x816b, 0x091c,
+ 0x816e, 0x1873,
+ 0x8170, 0x080a,
+ 0x8171, 0x1872,
+ 0x8174, 0x1876,
+ 0x8178, 0x0bce,
+ 0x8179, 0x0df2,
+ 0x817a, 0x0aa5,
+ 0x817f, 0x0b3c,
+ 0x8180, 0x187a,
+ 0x8182, 0x187b,
+ 0x8183, 0x1877,
+ 0x8188, 0x1878,
+ 0x818a, 0x1879,
+ 0x818f, 0x07e3,
+ 0x8193, 0x1881,
+ 0x8195, 0x187d,
+ 0x819a, 0x0dd8,
+ 0x819c, 0x0e9a,
+ 0x819d, 0x0d9a,
+ 0x81a0, 0x187c,
+ 0x81a3, 0x187f,
+ 0x81a4, 0x187e,
+ 0x81a8, 0x0e72,
+ 0x81a9, 0x1882,
+ 0x81b0, 0x1883,
+ 0x81b3, 0x0ab9,
+ 0x81b5, 0x1884,
+ 0x81b8, 0x1886,
+ 0x81ba, 0x188a,
+ 0x81bd, 0x1887,
+ 0x81be, 0x1885,
+ 0x81bf, 0x0cf5,
+ 0x81c0, 0x1888,
+ 0x81c2, 0x1889,
+ 0x81c6, 0x0532,
+ 0x81c8, 0x1890,
+ 0x81c9, 0x188b,
+ 0x81cd, 0x188c,
+ 0x81d1, 0x188d,
+ 0x81d3, 0x0b01,
+ 0x81d8, 0x188f,
+ 0x81d9, 0x188e,
+ 0x81da, 0x1891,
+ 0x81df, 0x1892,
+ 0x81e3, 0x0a09,
+ 0x81e5, 0x0569,
+ 0x81e7, 0x1894,
+ 0x81e8, 0x0f9f,
+ 0x81ea, 0x08d7,
+ 0x81ed, 0x0937,
+ 0x81f3, 0x08b8,
+ 0x81f4, 0x0b95,
+ 0x81fa, 0x1895,
+ 0x81fc, 0x04d3,
+ 0x81fe, 0x1897,
+ 0x8201, 0x1898,
+ 0x8205, 0x189a,
+ 0x8207, 0x189b,
+ 0x8208, 0x06b5,
+ 0x8209, 0x13af,
+ 0x820a, 0x189c,
+ 0x820c, 0x0a89,
+ 0x820d, 0x189d,
+ 0x820e, 0x08f7,
+ 0x8210, 0x189e,
+ 0x8212, 0x1009,
+ 0x8216, 0x189f,
+ 0x8217, 0x0e2e,
+ 0x8218, 0x0618,
+ 0x821b, 0x0aa6,
+ 0x821c, 0x0962,
+ 0x821e, 0x0de3,
+ 0x821f, 0x0938,
+ 0x8229, 0x18a0,
+ 0x822a, 0x07e4,
+ 0x822b, 0x18a1,
+ 0x822c, 0x0d60,
+ 0x822e, 0x18af,
+ 0x8233, 0x18a3,
+ 0x8235, 0x0b29,
+ 0x8236, 0x0d2b,
+ 0x8237, 0x0773,
+ 0x8238, 0x18a2,
+ 0x8239, 0x0aa7,
+ 0x8240, 0x18a4,
+ 0x8247, 0x0c16,
+ 0x8258, 0x18a6,
+ 0x8259, 0x18a5,
+ 0x825a, 0x18a8,
+ 0x825d, 0x18a7,
+ 0x825f, 0x18a9,
+ 0x8262, 0x18ab,
+ 0x8264, 0x18aa,
+ 0x8266, 0x060b,
+ 0x8268, 0x18ac,
+ 0x826a, 0x18ad,
+ 0x826e, 0x0821,
+ 0x826f, 0x0f91,
+ 0x8271, 0x18b0,
+ 0x8272, 0x09ed,
+ 0x8276, 0x0512,
+ 0x8277, 0x18b1,
+ 0x827e, 0x18b3,
+ 0x828b, 0x04b6,
+ 0x828d, 0x18b4,
+ 0x8292, 0x18b5,
+ 0x8299, 0x0dd9,
+ 0x829d, 0x08f3,
+ 0x829f, 0x18b7,
+ 0x82a5, 0x0587,
+ 0x82a6, 0x0476,
+ 0x82ab, 0x18b6,
+ 0x82ac, 0x18b9,
+ 0x82ad, 0x0d04,
+ 0x82af, 0x0a0a,
+ 0x82b1, 0x0556,
+ 0x82b3, 0x0e55,
+ 0x82b8, 0x0733,
+ 0x82b9, 0x06d4,
+ 0x82bb, 0x18b8,
+ 0x82bd, 0x056a,
+ 0x82c5, 0x05df,
+ 0x82d1, 0x0513,
+ 0x82d2, 0x18bd,
+ 0x82d3, 0x0fb2,
+ 0x82d4, 0x0b3d,
+ 0x82d7, 0x0db6,
+ 0x82d9, 0x18c9,
+ 0x82db, 0x0557,
+ 0x82dc, 0x18c7,
+ 0x82de, 0x18c5,
+ 0x82df, 0x18bc,
+ 0x82e1, 0x18ba,
+ 0x82e3, 0x18bb,
+ 0x82e5, 0x090f,
+ 0x82e6, 0x06e4,
+ 0x82e7, 0x0bb5,
+ 0x82eb, 0x0ca9,
+ 0x82f1, 0x04f3,
+ 0x82f3, 0x18bf,
+ 0x82f4, 0x18be,
+ 0x82f9, 0x18c4,
+ 0x82fa, 0x18c0,
+ 0x82fb, 0x18c3,
+ 0x8301, 0x2198,
+ 0x8302, 0x0edc,
+ 0x8303, 0x18c2,
+ 0x8304, 0x0558,
+ 0x8305, 0x05db,
+ 0x8306, 0x18c6,
+ 0x8309, 0x18c8,
+ 0x830e, 0x072a,
+ 0x8316, 0x18cc,
+ 0x8317, 0x18d5,
+ 0x831c, 0x046f,
+ 0x8323, 0x18dd,
+ 0x8328, 0x04b5,
+ 0x832b, 0x18d4,
+ 0x832f, 0x18d3,
+ 0x8331, 0x18ce,
+ 0x8332, 0x18cd,
+ 0x8334, 0x18cb,
+ 0x8335, 0x18ca,
+ 0x8336, 0x0ba1,
+ 0x8338, 0x0b5b,
+ 0x8339, 0x18d0,
+ 0x8340, 0x18cf,
+ 0x8345, 0x18d2,
+ 0x8349, 0x0af2,
+ 0x834a, 0x072b,
+ 0x834f, 0x04e3,
+ 0x8350, 0x18d1,
+ 0x8352, 0x07e5,
+ 0x8358, 0x0af3,
+ 0x8362, 0x2199,
+ 0x8373, 0x18e3,
+ 0x8375, 0x18e4,
+ 0x8377, 0x0559,
+ 0x837b, 0x052e,
+ 0x837c, 0x18e1,
+ 0x837f, 0x219a,
+ 0x8385, 0x18d7,
+ 0x8387, 0x18df,
+ 0x8389, 0x18e6,
+ 0x838a, 0x18e0,
+ 0x838e, 0x18de,
+ 0x8393, 0x18c1,
+ 0x8396, 0x18dc,
+ 0x839a, 0x18d8,
+ 0x839e, 0x060c,
+ 0x839f, 0x18da,
+ 0x83a0, 0x18e5,
+ 0x83a2, 0x18db,
+ 0x83a8, 0x18e7,
+ 0x83aa, 0x18d9,
+ 0x83ab, 0x0d32,
+ 0x83b1, 0x0f53,
+ 0x83b5, 0x18e2,
+ 0x83bd, 0x18f8,
+ 0x83c1, 0x18f0,
+ 0x83c5, 0x0a41,
+ 0x83c7, 0x219b,
+ 0x83ca, 0x0660,
+ 0x83cc, 0x06d5,
+ 0x83ce, 0x18eb,
+ 0x83d3, 0x055b,
+ 0x83d6, 0x09bc,
+ 0x83d8, 0x18ee,
+ 0x83dc, 0x084a,
+ 0x83df, 0x0c4b,
+ 0x83e0, 0x18f3,
+ 0x83e9, 0x0e3e,
+ 0x83eb, 0x18ea,
+ 0x83ef, 0x055a,
+ 0x83f0, 0x078a,
+ 0x83f1, 0x0d9b,
+ 0x83f2, 0x18f4,
+ 0x83f4, 0x18e8,
+ 0x83f6, 0x219c,
+ 0x83f7, 0x18f1,
+ 0x83fb, 0x18fb,
+ 0x83fd, 0x18ec,
+ 0x8403, 0x18ed,
+ 0x8404, 0x0c92,
+ 0x8407, 0x18f2,
+ 0x840a, 0x1e7f,
+ 0x840b, 0x18ef,
+ 0x840c, 0x0e56,
+ 0x840d, 0x18f5,
+ 0x840e, 0x04a4,
+ 0x8413, 0x18e9,
+ 0x8420, 0x18f7,
+ 0x8422, 0x18f6,
+ 0x8429, 0x0d21,
+ 0x842a, 0x18fd,
+ 0x842c, 0x1908,
+ 0x8431, 0x05dc,
+ 0x8435, 0x190b,
+ 0x8438, 0x18f9,
+ 0x843c, 0x18fe,
+ 0x843d, 0x0f58,
+ 0x8446, 0x1907,
+ 0x8448, 0x219d,
+ 0x8449, 0x0f3f,
+ 0x844e, 0x0f72,
+ 0x8457, 0x0bb6,
+ 0x845b, 0x05c9,
+ 0x8461, 0x0de4,
+ 0x8462, 0x190d,
+ 0x8463, 0x0c79,
+ 0x8466, 0x0475,
+ 0x8469, 0x1906,
+ 0x846b, 0x1902,
+ 0x846c, 0x0af4,
+ 0x846d, 0x18fc,
+ 0x846e, 0x1904,
+ 0x846f, 0x1909,
+ 0x8471, 0x0ce2,
+ 0x8475, 0x046e,
+ 0x8477, 0x1901,
+ 0x8479, 0x190a,
+ 0x847a, 0x0dea,
+ 0x8482, 0x1905,
+ 0x8484, 0x1900,
+ 0x848b, 0x09bd,
+ 0x8490, 0x0939,
+ 0x8494, 0x08d8,
+ 0x8499, 0x0ee4,
+ 0x849c, 0x0db9,
+ 0x849f, 0x1910,
+ 0x84a1, 0x1919,
+ 0x84ad, 0x1903,
+ 0x84b2, 0x05d5,
+ 0x84b4, 0x219e,
+ 0x84b8, 0x09e0,
+ 0x84b9, 0x190e,
+ 0x84bb, 0x1913,
+ 0x84bc, 0x0af5,
+ 0x84bf, 0x190f,
+ 0x84c1, 0x1916,
+ 0x84c4, 0x0b9d,
+ 0x84c6, 0x1917,
+ 0x84c9, 0x0f40,
+ 0x84ca, 0x190c,
+ 0x84cb, 0x0596,
+ 0x84cd, 0x1912,
+ 0x84d0, 0x1915,
+ 0x84d1, 0x0eb8,
+ 0x84d6, 0x1918,
+ 0x84d9, 0x1911,
+ 0x84da, 0x1914,
+ 0x84dc, 0x20ab,
+ 0x84ec, 0x0e57,
+ 0x84ee, 0x0fc7,
+ 0x84f4, 0x191c,
+ 0x84fc, 0x1923,
+ 0x84ff, 0x191b,
+ 0x8500, 0x08ef,
+ 0x8506, 0x18fa,
+ 0x8511, 0x0e1e,
+ 0x8513, 0x0eae,
+ 0x8514, 0x1922,
+ 0x8515, 0x1921,
+ 0x8517, 0x191d,
+ 0x851a, 0x04d8,
+ 0x851f, 0x1920,
+ 0x8521, 0x191a,
+ 0x8523, 0x1e1a,
+ 0x8526, 0x0bf1,
+ 0x852c, 0x191f,
+ 0x852d, 0x04c2,
+ 0x8535, 0x0b02,
+ 0x853d, 0x0e13,
+ 0x853e, 0x1eb5,
+ 0x8540, 0x1924,
+ 0x8541, 0x1928,
+ 0x8543, 0x0d6d,
+ 0x8548, 0x1927,
+ 0x8549, 0x09be,
+ 0x854a, 0x08f5,
+ 0x854b, 0x192a,
+ 0x854e, 0x06b6,
+ 0x8553, 0x219f,
+ 0x8555, 0x192b,
+ 0x8557, 0x0deb,
+ 0x8558, 0x1926,
+ 0x8559, 0x21a0,
+ 0x855a, 0x18ff,
+ 0x8563, 0x1925,
+ 0x8568, 0x0ff5,
+ 0x8569, 0x0c7a,
+ 0x856a, 0x0de5,
+ 0x856b, 0x21a1,
+ 0x856d, 0x1932,
+ 0x8577, 0x1938,
+ 0x857e, 0x1939,
+ 0x8580, 0x192c,
+ 0x8584, 0x0d2c,
+ 0x8587, 0x1936,
+ 0x8588, 0x192e,
+ 0x858a, 0x1930,
+ 0x8590, 0x193a,
+ 0x8591, 0x192f,
+ 0x8594, 0x1933,
+ 0x8597, 0x0514,
+ 0x8599, 0x0cbd,
+ 0x859b, 0x1934,
+ 0x859c, 0x1937,
+ 0x85a4, 0x192d,
+ 0x85a6, 0x0aa8,
+ 0x85a8, 0x1931,
+ 0x85a9, 0x0875,
+ 0x85aa, 0x0a0b,
+ 0x85ab, 0x0706,
+ 0x85ac, 0x0f00,
+ 0x85ae, 0x0f05,
+ 0x85af, 0x097c,
+ 0x85b0, 0x21a3,
+ 0x85b9, 0x193e,
+ 0x85ba, 0x193c,
+ 0x85c1, 0x0ff4,
+ 0x85c9, 0x193b,
+ 0x85cd, 0x0f5f,
+ 0x85cf, 0x193d,
+ 0x85d0, 0x193f,
+ 0x85d5, 0x1940,
+ 0x85dc, 0x1943,
+ 0x85dd, 0x1941,
+ 0x85e4, 0x0c7b,
+ 0x85e5, 0x1942,
+ 0x85e9, 0x0d61,
+ 0x85ea, 0x1935,
+ 0x85f7, 0x097d,
+ 0x85f9, 0x1944,
+ 0x85fa, 0x1949,
+ 0x85fb, 0x0af6,
+ 0x85fe, 0x1948,
+ 0x8602, 0x1929,
+ 0x8606, 0x194a,
+ 0x8607, 0x0acb,
+ 0x860a, 0x1945,
+ 0x860b, 0x1947,
+ 0x8613, 0x1946,
+ 0x8616, 0x14d0,
+ 0x8617, 0x14c1,
+ 0x861a, 0x194c,
+ 0x8622, 0x194b,
+ 0x862d, 0x0f60,
+ 0x862f, 0x16b1,
+ 0x8630, 0x194d,
+ 0x863f, 0x194e,
+ 0x864d, 0x194f,
+ 0x864e, 0x078b,
+ 0x8650, 0x066e,
+ 0x8654, 0x1951,
+ 0x8655, 0x1094,
+ 0x865a, 0x068f,
+ 0x865c, 0x0f82,
+ 0x865e, 0x06eb,
+ 0x865f, 0x1952,
+ 0x8667, 0x1953,
+ 0x866b, 0x0bac,
+ 0x8671, 0x1954,
+ 0x8679, 0x0cd2,
+ 0x867b, 0x047e,
+ 0x868a, 0x0563,
+ 0x868b, 0x1959,
+ 0x8693, 0x1955,
+ 0x8695, 0x088b,
+ 0x86a3, 0x1956,
+ 0x86a4, 0x0cf8,
+ 0x86a9, 0x1957,
+ 0x86ab, 0x1962,
+ 0x86af, 0x195c,
+ 0x86b0, 0x195f,
+ 0x86b6, 0x195b,
+ 0x86c4, 0x195d,
+ 0x86c6, 0x195e,
+ 0x86c7, 0x0904,
+ 0x86c9, 0x1960,
+ 0x86cb, 0x0b7f,
+ 0x86cd, 0x072c,
+ 0x86ce, 0x05a0,
+ 0x86d4, 0x1963,
+ 0x86d9, 0x059d,
+ 0x86db, 0x1968,
+ 0x86de, 0x1964,
+ 0x86df, 0x1967,
+ 0x86e4, 0x0d4e,
+ 0x86e9, 0x1965,
+ 0x86ec, 0x1966,
+ 0x86ed, 0x0dba,
+ 0x86ee, 0x0d6e,
+ 0x86ef, 0x1969,
+ 0x86f8, 0x0b5d,
+ 0x86f9, 0x1973,
+ 0x86fb, 0x196f,
+ 0x86fe, 0x056b,
+ 0x8700, 0x196d,
+ 0x8702, 0x0e58,
+ 0x8703, 0x196e,
+ 0x8706, 0x196b,
+ 0x8708, 0x196c,
+ 0x8709, 0x1971,
+ 0x870a, 0x1974,
+ 0x870d, 0x1972,
+ 0x8711, 0x1970,
+ 0x8712, 0x196a,
+ 0x8718, 0x0b96,
+ 0x871a, 0x197b,
+ 0x871c, 0x0eb6,
+ 0x8725, 0x1979,
+ 0x8729, 0x197a,
+ 0x8734, 0x1975,
+ 0x8737, 0x1977,
+ 0x873b, 0x1978,
+ 0x873f, 0x1976,
+ 0x8749, 0x0a8a,
+ 0x874b, 0x0fdf,
+ 0x874c, 0x197f,
+ 0x874e, 0x1980,
+ 0x8753, 0x1986,
+ 0x8755, 0x09f0,
+ 0x8757, 0x1982,
+ 0x8759, 0x1985,
+ 0x875f, 0x197d,
+ 0x8760, 0x197c,
+ 0x8763, 0x1987,
+ 0x8766, 0x055c,
+ 0x8768, 0x1983,
+ 0x876a, 0x1988,
+ 0x876e, 0x1984,
+ 0x8774, 0x1981,
+ 0x8776, 0x0bcf,
+ 0x8778, 0x197e,
+ 0x877f, 0x0d1e,
+ 0x8782, 0x198c,
+ 0x878d, 0x0f25,
+ 0x879f, 0x198b,
+ 0x87a2, 0x198a,
+ 0x87ab, 0x1993,
+ 0x87af, 0x198d,
+ 0x87b3, 0x1995,
+ 0x87ba, 0x0f50,
+ 0x87bb, 0x1998,
+ 0x87bd, 0x198f,
+ 0x87c0, 0x1990,
+ 0x87c4, 0x1994,
+ 0x87c6, 0x1997,
+ 0x87c7, 0x1996,
+ 0x87cb, 0x198e,
+ 0x87d0, 0x1991,
+ 0x87d2, 0x19a2,
+ 0x87e0, 0x199b,
+ 0x87ec, 0x1e23,
+ 0x87ef, 0x1999,
+ 0x87f2, 0x199a,
+ 0x87f6, 0x199f,
+ 0x87f9, 0x0588,
+ 0x87fb, 0x065c,
+ 0x87fe, 0x199e,
+ 0x8805, 0x1989,
+ 0x8807, 0x21a6,
+ 0x880d, 0x199d,
+ 0x880e, 0x19a1,
+ 0x880f, 0x199c,
+ 0x8811, 0x19a3,
+ 0x8815, 0x19a5,
+ 0x8816, 0x19a4,
+ 0x881f, 0x1e85,
+ 0x8821, 0x19a7,
+ 0x8822, 0x19a6,
+ 0x8823, 0x1961,
+ 0x8827, 0x19ab,
+ 0x8831, 0x19a8,
+ 0x8836, 0x19a9,
+ 0x8839, 0x19aa,
+ 0x883b, 0x19ac,
+ 0x8840, 0x0742,
+ 0x8842, 0x19ae,
+ 0x8844, 0x19ad,
+ 0x8846, 0x093a,
+ 0x884c, 0x07e6,
+ 0x884d, 0x1524,
+ 0x8852, 0x19af,
+ 0x8853, 0x095b,
+ 0x8857, 0x0597,
+ 0x8859, 0x19b0,
+ 0x885b, 0x04f4,
+ 0x885d, 0x09bf,
+ 0x885e, 0x19b1,
+ 0x8861, 0x07e7,
+ 0x8862, 0x19b2,
+ 0x8863, 0x04a5,
+ 0x8868, 0x0daf,
+ 0x886b, 0x19b3,
+ 0x8870, 0x0a30,
+ 0x8872, 0x19ba,
+ 0x8875, 0x19b7,
+ 0x8877, 0x0bad,
+ 0x887d, 0x19b8,
+ 0x887e, 0x19b5,
+ 0x887f, 0x06d6,
+ 0x8881, 0x19b4,
+ 0x8882, 0x19bb,
+ 0x8888, 0x070c,
+ 0x888b, 0x0b3e,
+ 0x888d, 0x19c1,
+ 0x8892, 0x19bd,
+ 0x8896, 0x0b15,
+ 0x8897, 0x19bc,
+ 0x8899, 0x19bf,
+ 0x889e, 0x19b6,
+ 0x88a2, 0x19c0,
+ 0x88a4, 0x19c2,
+ 0x88ab, 0x0d83,
+ 0x88ae, 0x19be,
+ 0x88b0, 0x19c3,
+ 0x88b1, 0x19c5,
+ 0x88b4, 0x0787,
+ 0x88b5, 0x19b9,
+ 0x88b7, 0x0485,
+ 0x88bf, 0x19c4,
+ 0x88c1, 0x084b,
+ 0x88c2, 0x0fbe,
+ 0x88c3, 0x19c6,
+ 0x88c5, 0x0af7,
+ 0x88cf, 0x0f6a,
+ 0x88d4, 0x19c8,
+ 0x88d5, 0x0f1f,
+ 0x88d8, 0x19c9,
+ 0x88dc, 0x0e34,
+ 0x88dd, 0x19cb,
+ 0x88df, 0x0830,
+ 0x88e1, 0x0f6b,
+ 0x88e8, 0x19d0,
+ 0x88f2, 0x19d1,
+ 0x88f3, 0x09c0,
+ 0x88f4, 0x19cf,
+ 0x88f5, 0x21a7,
+ 0x88f8, 0x0f51,
+ 0x88f9, 0x19cc,
+ 0x88fc, 0x19ce,
+ 0x88fd, 0x0a61,
+ 0x88fe, 0x0a44,
+ 0x8902, 0x19cd,
+ 0x8904, 0x19d2,
+ 0x8907, 0x0df3,
+ 0x890a, 0x19d4,
+ 0x890c, 0x19d3,
+ 0x8910, 0x05ca,
+ 0x8912, 0x0e59,
+ 0x8913, 0x19d5,
+ 0x891c, 0x20a8,
+ 0x891d, 0x19e1,
+ 0x891e, 0x19d7,
+ 0x8925, 0x19d8,
+ 0x892a, 0x19d9,
+ 0x8936, 0x19de,
+ 0x8938, 0x19df,
+ 0x893b, 0x19dd,
+ 0x8941, 0x19db,
+ 0x8943, 0x19d6,
+ 0x8944, 0x19dc,
+ 0x894c, 0x19e0,
+ 0x894d, 0x1bd0,
+ 0x8956, 0x0528,
+ 0x895e, 0x19e3,
+ 0x895f, 0x06d7,
+ 0x8960, 0x19e2,
+ 0x8964, 0x19e5,
+ 0x8966, 0x19e4,
+ 0x896a, 0x19e7,
+ 0x896d, 0x19e6,
+ 0x896f, 0x19e8,
+ 0x8972, 0x093b,
+ 0x8974, 0x19e9,
+ 0x8977, 0x19ea,
+ 0x897e, 0x19eb,
+ 0x897f, 0x0a62,
+ 0x8981, 0x0f41,
+ 0x8983, 0x19ec,
+ 0x8986, 0x0df4,
+ 0x8987, 0x0cfc,
+ 0x8988, 0x19ed,
+ 0x898a, 0x19ee,
+ 0x898b, 0x075f,
+ 0x898f, 0x0646,
+ 0x8993, 0x19ef,
+ 0x8996, 0x08b9,
+ 0x8997, 0x0cf7,
+ 0x8998, 0x19f0,
+ 0x899a, 0x05ae,
+ 0x89a1, 0x19f1,
+ 0x89a6, 0x19f3,
+ 0x89a7, 0x0f61,
+ 0x89a9, 0x19f2,
+ 0x89aa, 0x0a0c,
+ 0x89ac, 0x19f4,
+ 0x89af, 0x19f5,
+ 0x89b2, 0x19f6,
+ 0x89b3, 0x060d,
+ 0x89ba, 0x19f7,
+ 0x89bd, 0x19f8,
+ 0x89bf, 0x19f9,
+ 0x89d2, 0x05af,
+ 0x89da, 0x19fb,
+ 0x89dc, 0x19fc,
+ 0x89e3, 0x0572,
+ 0x89e6, 0x09ee,
+ 0x89e7, 0x19fe,
+ 0x89f4, 0x19ff,
+ 0x89f8, 0x1a00,
+ 0x8a00, 0x0774,
+ 0x8a02, 0x0c17,
+ 0x8a03, 0x1a01,
+ 0x8a08, 0x072d,
+ 0x8a0a, 0x0a1c,
+ 0x8a0c, 0x1a04,
+ 0x8a0e, 0x0c7c,
+ 0x8a10, 0x1a03,
+ 0x8a12, 0x21a8,
+ 0x8a13, 0x0707,
+ 0x8a16, 0x1a02,
+ 0x8a17, 0x0b57,
+ 0x8a18, 0x0647,
+ 0x8a1b, 0x1a05,
+ 0x8a1d, 0x1a06,
+ 0x8a1f, 0x09c1,
+ 0x8a23, 0x0743,
+ 0x8a25, 0x1a07,
+ 0x8a2a, 0x0e5a,
+ 0x8a2d, 0x0a83,
+ 0x8a31, 0x0690,
+ 0x8a33, 0x0f01,
+ 0x8a34, 0x0acc,
+ 0x8a36, 0x1a08,
+ 0x8a37, 0x21a9,
+ 0x8a3a, 0x0a0d,
+ 0x8a3b, 0x0bae,
+ 0x8a3c, 0x09c2,
+ 0x8a41, 0x1a09,
+ 0x8a46, 0x1a0c,
+ 0x8a48, 0x1a0d,
+ 0x8a50, 0x082e,
+ 0x8a51, 0x0b22,
+ 0x8a52, 0x1a0b,
+ 0x8a54, 0x09c3,
+ 0x8a55, 0x0db0,
+ 0x8a5b, 0x1a0a,
+ 0x8a5e, 0x08ba,
+ 0x8a60, 0x04f5,
+ 0x8a62, 0x1a11,
+ 0x8a63, 0x072e,
+ 0x8a66, 0x08bc,
+ 0x8a69, 0x08bb,
+ 0x8a6b, 0x0ff3,
+ 0x8a6c, 0x1a10,
+ 0x8a6d, 0x1a0f,
+ 0x8a6e, 0x0aa9,
+ 0x8a70, 0x0667,
+ 0x8a71, 0x0fe9,
+ 0x8a72, 0x0598,
+ 0x8a73, 0x09c4,
+ 0x8a79, 0x21aa,
+ 0x8a7c, 0x1a0e,
+ 0x8a82, 0x1a13,
+ 0x8a84, 0x1a14,
+ 0x8a85, 0x1a12,
+ 0x8a87, 0x078c,
+ 0x8a89, 0x0f2a,
+ 0x8a8c, 0x08bd,
+ 0x8a8d, 0x0cdd,
+ 0x8a91, 0x1a17,
+ 0x8a93, 0x0a64,
+ 0x8a95, 0x0b80,
+ 0x8a98, 0x0f20,
+ 0x8a9a, 0x1a1a,
+ 0x8a9e, 0x07a0,
+ 0x8aa0, 0x0a63,
+ 0x8aa1, 0x1a16,
+ 0x8aa3, 0x1a1b,
+ 0x8aa4, 0x07a1,
+ 0x8aa5, 0x1a18,
+ 0x8aa7, 0x21ab,
+ 0x8aa8, 0x1a15,
+ 0x8aac, 0x0a86,
+ 0x8aad, 0x0ca1,
+ 0x8ab0, 0x0b6d,
+ 0x8ab2, 0x055d,
+ 0x8ab9, 0x0d84,
+ 0x8abc, 0x065d,
+ 0x8abe, 0x21ac,
+ 0x8abf, 0x0bd0,
+ 0x8ac2, 0x1a1e,
+ 0x8ac4, 0x1a1c,
+ 0x8ac7, 0x0b8a,
+ 0x8acb, 0x0a65,
+ 0x8acc, 0x060e,
+ 0x8acd, 0x1a1d,
+ 0x8acf, 0x0a21,
+ 0x8ad2, 0x0f92,
+ 0x8ad6, 0x0fe6,
+ 0x8ada, 0x1a1f,
+ 0x8adb, 0x1a2a,
+ 0x8adc, 0x0bd1,
+ 0x8ade, 0x1a29,
+ 0x8adf, 0x21ad,
+ 0x8ae0, 0x1a26,
+ 0x8ae1, 0x1a2e,
+ 0x8ae2, 0x1a27,
+ 0x8ae4, 0x1a23,
+ 0x8ae6, 0x0c18,
+ 0x8ae7, 0x1a22,
+ 0x8aeb, 0x1a20,
+ 0x8aed, 0x0f0b,
+ 0x8aee, 0x08be,
+ 0x8af1, 0x1a24,
+ 0x8af3, 0x1a21,
+ 0x8af6, 0x21af,
+ 0x8af7, 0x1a28,
+ 0x8af8, 0x097e,
+ 0x8afa, 0x0775,
+ 0x8afe, 0x0b5a,
+ 0x8b00, 0x0e73,
+ 0x8b01, 0x04fc,
+ 0x8b02, 0x04a6,
+ 0x8b04, 0x0c7d,
+ 0x8b07, 0x1a2c,
+ 0x8b0c, 0x1a2b,
+ 0x8b0e, 0x0cbe,
+ 0x8b10, 0x1a30,
+ 0x8b14, 0x1a25,
+ 0x8b16, 0x1a2f,
+ 0x8b17, 0x1a31,
+ 0x8b19, 0x0760,
+ 0x8b1a, 0x1a2d,
+ 0x8b1b, 0x07e8,
+ 0x8b1d, 0x0901,
+ 0x8b20, 0x1a32,
+ 0x8b21, 0x0f42,
+ 0x8b26, 0x1a35,
+ 0x8b28, 0x1a38,
+ 0x8b2b, 0x1a36,
+ 0x8b2c, 0x0da7,
+ 0x8b33, 0x1a33,
+ 0x8b39, 0x06d8,
+ 0x8b3e, 0x1a37,
+ 0x8b41, 0x1a39,
+ 0x8b49, 0x1a3d,
+ 0x8b4c, 0x1a3a,
+ 0x8b4e, 0x1a3c,
+ 0x8b4f, 0x1a3b,
+ 0x8b53, 0x21b0,
+ 0x8b56, 0x1a3e,
+ 0x8b58, 0x08dd,
+ 0x8b5a, 0x1a40,
+ 0x8b5b, 0x1a3f,
+ 0x8b5c, 0x0dda,
+ 0x8b5f, 0x1a42,
+ 0x8b66, 0x072f,
+ 0x8b6b, 0x1a41,
+ 0x8b6c, 0x1a43,
+ 0x8b6f, 0x1a44,
+ 0x8b70, 0x065e,
+ 0x8b71, 0x182e,
+ 0x8b72, 0x09e1,
+ 0x8b74, 0x1a45,
+ 0x8b77, 0x07a2,
+ 0x8b7d, 0x1a46,
+ 0x8b7f, 0x21b1,
+ 0x8b80, 0x1a47,
+ 0x8b83, 0x088c,
+ 0x8b8a, 0x13d3,
+ 0x8b8c, 0x1a48,
+ 0x8b8e, 0x1a49,
+ 0x8b90, 0x093c,
+ 0x8b92, 0x1a4a,
+ 0x8b96, 0x1a4c,
+ 0x8b99, 0x1a4d,
+ 0x8c37, 0x0b69,
+ 0x8c3a, 0x1a4f,
+ 0x8c3f, 0x1a51,
+ 0x8c41, 0x1a50,
+ 0x8c46, 0x0c7e,
+ 0x8c48, 0x1a52,
+ 0x8c4a, 0x0e5b,
+ 0x8c4c, 0x1a53,
+ 0x8c4e, 0x1a54,
+ 0x8c50, 0x1a55,
+ 0x8c55, 0x1a56,
+ 0x8c5a, 0x0cb2,
+ 0x8c61, 0x09c5,
+ 0x8c62, 0x1a57,
+ 0x8c6a, 0x07fd,
+ 0x8c6b, 0x1007,
+ 0x8c6c, 0x1a58,
+ 0x8c78, 0x1a59,
+ 0x8c79, 0x0db1,
+ 0x8c7a, 0x1a5a,
+ 0x8c7c, 0x1a62,
+ 0x8c82, 0x1a5b,
+ 0x8c85, 0x1a5d,
+ 0x8c89, 0x1a5c,
+ 0x8c8a, 0x1a5e,
+ 0x8c8c, 0x0e74,
+ 0x8c8d, 0x1a5f,
+ 0x8c94, 0x1a61,
+ 0x8c98, 0x1a63,
+ 0x8c9d, 0x058b,
+ 0x8c9e, 0x0c03,
+ 0x8ca0, 0x0ddb,
+ 0x8ca1, 0x0852,
+ 0x8ca2, 0x07e9,
+ 0x8ca7, 0x0dc1,
+ 0x8ca8, 0x055f,
+ 0x8ca9, 0x0d62,
+ 0x8caa, 0x1a66,
+ 0x8cab, 0x060f,
+ 0x8cac, 0x0a79,
+ 0x8cad, 0x1a65,
+ 0x8cae, 0x1a6a,
+ 0x8caf, 0x0bb7,
+ 0x8cb0, 0x0eef,
+ 0x8cb2, 0x1a68,
+ 0x8cb4, 0x0648,
+ 0x8cb6, 0x1a6b,
+ 0x8cb7, 0x0d19,
+ 0x8cb8, 0x0b3f,
+ 0x8cbb, 0x0d85,
+ 0x8cbc, 0x0c37,
+ 0x8cbd, 0x1a67,
+ 0x8cbf, 0x0e75,
+ 0x8cc0, 0x056c,
+ 0x8cc1, 0x1a6d,
+ 0x8cc2, 0x0fce,
+ 0x8cc3, 0x0bde,
+ 0x8cc4, 0x0feb,
+ 0x8cc7, 0x08bf,
+ 0x8cc8, 0x1a6c,
+ 0x8cca, 0x0b11,
+ 0x8ccd, 0x1a7d,
+ 0x8cce, 0x0aaa,
+ 0x8cd1, 0x0cd0,
+ 0x8cd3, 0x0dc2,
+ 0x8cda, 0x1a70,
+ 0x8cdb, 0x088d,
+ 0x8cdc, 0x08c0,
+ 0x8cde, 0x09c6,
+ 0x8ce0, 0x0d1b,
+ 0x8ce2, 0x0761,
+ 0x8ce3, 0x1a6f,
+ 0x8ce4, 0x1a6e,
+ 0x8ce6, 0x0ddc,
+ 0x8cea, 0x08ed,
+ 0x8ced, 0x0c4c,
+ 0x8cf0, 0x21b2,
+ 0x8cf4, 0x21b3,
+ 0x8cfa, 0x1a72,
+ 0x8cfc, 0x07ea,
+ 0x8cfd, 0x1a71,
+ 0x8d04, 0x1a74,
+ 0x8d07, 0x1a77,
+ 0x8d08, 0x0b03,
+ 0x8d0a, 0x1a76,
+ 0x8d0b, 0x0622,
+ 0x8d0d, 0x1a79,
+ 0x8d0f, 0x1a78,
+ 0x8d10, 0x1a7a,
+ 0x8d12, 0x21b4,
+ 0x8d13, 0x1a7c,
+ 0x8d14, 0x1a7e,
+ 0x8d16, 0x1a7f,
+ 0x8d64, 0x0a7a,
+ 0x8d66, 0x08fb,
+ 0x8d67, 0x1a80,
+ 0x8d6b, 0x05b0,
+ 0x8d6d, 0x1a81,
+ 0x8d70, 0x0af8,
+ 0x8d71, 0x1a82,
+ 0x8d73, 0x1a83,
+ 0x8d74, 0x0ddd,
+ 0x8d76, 0x21b5,
+ 0x8d77, 0x0649,
+ 0x8d81, 0x1a84,
+ 0x8d85, 0x0bd2,
+ 0x8d8a, 0x04fd,
+ 0x8d99, 0x1a85,
+ 0x8da3, 0x091d,
+ 0x8da8, 0x0a3c,
+ 0x8db3, 0x0b0d,
+ 0x8dba, 0x1a88,
+ 0x8dbe, 0x1a87,
+ 0x8dc2, 0x1a86,
+ 0x8dcb, 0x1a8e,
+ 0x8dcc, 0x1a8c,
+ 0x8dcf, 0x1a89,
+ 0x8dd6, 0x1a8b,
+ 0x8dda, 0x1a8a,
+ 0x8ddb, 0x1a8d,
+ 0x8ddd, 0x0691,
+ 0x8ddf, 0x1a91,
+ 0x8de1, 0x0a7b,
+ 0x8de3, 0x1a92,
+ 0x8de8, 0x078d,
+ 0x8dea, 0x1a8f,
+ 0x8def, 0x0fcf,
+ 0x8df3, 0x0bd3,
+ 0x8df5, 0x0aab,
+ 0x8dfc, 0x1a93,
+ 0x8dff, 0x1a96,
+ 0x8e08, 0x1a94,
+ 0x8e0a, 0x0f43,
+ 0x8e0f, 0x0c7f,
+ 0x8e10, 0x1a99,
+ 0x8e1d, 0x1a97,
+ 0x8e1f, 0x1a9a,
+ 0x8e2a, 0x1aa8,
+ 0x8e30, 0x1a9d,
+ 0x8e34, 0x1a9e,
+ 0x8e35, 0x1a9c,
+ 0x8e42, 0x1a9b,
+ 0x8e44, 0x0c19,
+ 0x8e47, 0x1aa0,
+ 0x8e48, 0x1aa4,
+ 0x8e49, 0x1aa1,
+ 0x8e4a, 0x1a9f,
+ 0x8e4c, 0x1aa2,
+ 0x8e50, 0x1aa3,
+ 0x8e55, 0x1aaa,
+ 0x8e59, 0x1aa5,
+ 0x8e5f, 0x0a7c,
+ 0x8e60, 0x1aa7,
+ 0x8e63, 0x1aa9,
+ 0x8e64, 0x1aa6,
+ 0x8e72, 0x1aac,
+ 0x8e74, 0x093d,
+ 0x8e76, 0x1aab,
+ 0x8e7c, 0x1aad,
+ 0x8e81, 0x1aae,
+ 0x8e84, 0x1ab1,
+ 0x8e85, 0x1ab0,
+ 0x8e87, 0x1aaf,
+ 0x8e8a, 0x1ab3,
+ 0x8e8b, 0x1ab2,
+ 0x8e8d, 0x0f02,
+ 0x8e91, 0x1ab5,
+ 0x8e93, 0x1ab4,
+ 0x8e94, 0x1ab6,
+ 0x8e99, 0x1ab7,
+ 0x8ea1, 0x1ab9,
+ 0x8eaa, 0x1ab8,
+ 0x8eab, 0x0a0e,
+ 0x8eac, 0x1aba,
+ 0x8eaf, 0x06e5,
+ 0x8eb0, 0x1abb,
+ 0x8eb1, 0x1abd,
+ 0x8ebe, 0x1abe,
+ 0x8ec0, 0x1def,
+ 0x8ec5, 0x1abf,
+ 0x8ec6, 0x1abc,
+ 0x8ec8, 0x1ac0,
+ 0x8eca, 0x0902,
+ 0x8ecb, 0x1ac1,
+ 0x8ecc, 0x064a,
+ 0x8ecd, 0x0709,
+ 0x8ecf, 0x21b7,
+ 0x8ed2, 0x0762,
+ 0x8edb, 0x1ac2,
+ 0x8edf, 0x0cc8,
+ 0x8ee2, 0x0c38,
+ 0x8ee3, 0x1ac3,
+ 0x8eeb, 0x1ac6,
+ 0x8ef8, 0x08e0,
+ 0x8efb, 0x1ac5,
+ 0x8efc, 0x1ac4,
+ 0x8efd, 0x0730,
+ 0x8efe, 0x1ac7,
+ 0x8f03, 0x05b1,
+ 0x8f05, 0x1ac9,
+ 0x8f09, 0x084c,
+ 0x8f0a, 0x1ac8,
+ 0x8f0c, 0x1ad1,
+ 0x8f12, 0x1acb,
+ 0x8f13, 0x1acd,
+ 0x8f14, 0x0e35,
+ 0x8f15, 0x1aca,
+ 0x8f19, 0x1acc,
+ 0x8f1b, 0x1ad0,
+ 0x8f1c, 0x1ace,
+ 0x8f1d, 0x064b,
+ 0x8f1f, 0x1acf,
+ 0x8f26, 0x1ad2,
+ 0x8f29, 0x0d10,
+ 0x8f2a, 0x0fa0,
+ 0x8f2f, 0x093e,
+ 0x8f33, 0x1ad3,
+ 0x8f38, 0x0f0c,
+ 0x8f39, 0x1ad5,
+ 0x8f3b, 0x1ad4,
+ 0x8f3e, 0x1ad8,
+ 0x8f3f, 0x0f2b,
+ 0x8f42, 0x1ad7,
+ 0x8f44, 0x05cb,
+ 0x8f45, 0x1ad6,
+ 0x8f46, 0x1adb,
+ 0x8f49, 0x1ada,
+ 0x8f4c, 0x1ad9,
+ 0x8f4d, 0x0c2c,
+ 0x8f4e, 0x1adc,
+ 0x8f57, 0x1add,
+ 0x8f5c, 0x1ade,
+ 0x8f5f, 0x07fe,
+ 0x8f61, 0x06fb,
+ 0x8f62, 0x1adf,
+ 0x8f9b, 0x0a0f,
+ 0x8f9c, 0x1ae2,
+ 0x8f9e, 0x08d9,
+ 0x8f9f, 0x1ae3,
+ 0x8fa3, 0x1ae4,
+ 0x8fa7, 0x10b6,
+ 0x8fa8, 0x10b5,
+ 0x8fad, 0x1ae5,
+ 0x8fae, 0x17ff,
+ 0x8faf, 0x1ae6,
+ 0x8fb0, 0x0b62,
+ 0x8fb1, 0x09f1,
+ 0x8fb2, 0x0cf6,
+ 0x8fb7, 0x1ae7,
+ 0x8fba, 0x0e25,
+ 0x8fbb, 0x0bf0,
+ 0x8fbc, 0x0810,
+ 0x8fbf, 0x0b67,
+ 0x8fc2, 0x04cc,
+ 0x8fc4, 0x0ea6,
+ 0x8fc5, 0x0a1d,
+ 0x8fce, 0x0734,
+ 0x8fd1, 0x06d9,
+ 0x8fd4, 0x0e26,
+ 0x8fda, 0x1ae8,
+ 0x8fe2, 0x1aea,
+ 0x8fe5, 0x1ae9,
+ 0x8fe6, 0x0560,
+ 0x8fe9, 0x0cce,
+ 0x8fea, 0x1aeb,
+ 0x8feb, 0x0d2d,
+ 0x8fed, 0x0c2d,
+ 0x8fef, 0x1aec,
+ 0x8ff0, 0x095c,
+ 0x8ff4, 0x1aee,
+ 0x8ff7, 0x0ece,
+ 0x8ff8, 0x1afd,
+ 0x8ff9, 0x1af0,
+ 0x8ffd, 0x0be5,
+ 0x9000, 0x0b40,
+ 0x9001, 0x0af9,
+ 0x9003, 0x0c80,
+ 0x9005, 0x1aef,
+ 0x9006, 0x066f,
+ 0x900b, 0x1af8,
+ 0x900d, 0x1af5,
+ 0x900e, 0x1b02,
+ 0x900f, 0x0c81,
+ 0x9010, 0x0b9e,
+ 0x9011, 0x1af2,
+ 0x9013, 0x0c1a,
+ 0x9014, 0x0c4d,
+ 0x9015, 0x1af3,
+ 0x9016, 0x1af7,
+ 0x9017, 0x0a26,
+ 0x9019, 0x0d1d,
+ 0x901a, 0x0be8,
+ 0x901d, 0x0a66,
+ 0x901e, 0x1af6,
+ 0x901f, 0x0b0e,
+ 0x9020, 0x0b04,
+ 0x9021, 0x1af4,
+ 0x9022, 0x046d,
+ 0x9023, 0x0fc8,
+ 0x9027, 0x1af9,
+ 0x902e, 0x0b41,
+ 0x9031, 0x093f,
+ 0x9032, 0x0a10,
+ 0x9035, 0x1afb,
+ 0x9036, 0x1afa,
+ 0x9038, 0x04b3,
+ 0x9039, 0x1afc,
+ 0x903c, 0x0da1,
+ 0x903e, 0x1b04,
+ 0x9041, 0x0cb3,
+ 0x9042, 0x0a31,
+ 0x9045, 0x0b97,
+ 0x9047, 0x06f0,
+ 0x9049, 0x1b03,
+ 0x904a, 0x0f21,
+ 0x904b, 0x04e1,
+ 0x904d, 0x0e27,
+ 0x904e, 0x0561,
+ 0x904f, 0x1afe,
+ 0x9053, 0x0c93,
+ 0x9054, 0x0b61,
+ 0x9055, 0x04a7,
+ 0x9056, 0x1b05,
+ 0x9058, 0x1b06,
+ 0x9059, 0x1d34,
+ 0x905c, 0x0b1d,
+ 0x905e, 0x1b07,
+ 0x9060, 0x0515,
+ 0x9061, 0x0ace,
+ 0x9063, 0x0763,
+ 0x9065, 0x0f44,
+ 0x9067, 0x21ba,
+ 0x9068, 0x1b08,
+ 0x9069, 0x0c26,
+ 0x906d, 0x0afa,
+ 0x906e, 0x0903,
+ 0x906f, 0x1b09,
+ 0x9072, 0x1b0c,
+ 0x9075, 0x096f,
+ 0x9076, 0x1b0a,
+ 0x9077, 0x0aad,
+ 0x9078, 0x0aac,
+ 0x907a, 0x04a8,
+ 0x907c, 0x0f93,
+ 0x907d, 0x1b0e,
+ 0x907f, 0x0d86,
+ 0x9080, 0x1b10,
+ 0x9081, 0x1b0f,
+ 0x9082, 0x1b0d,
+ 0x9083, 0x1737,
+ 0x9084, 0x0610,
+ 0x9087, 0x1aed,
+ 0x9089, 0x1b12,
+ 0x908a, 0x1b11,
+ 0x908f, 0x1b13,
+ 0x9091, 0x0f22,
+ 0x90a3, 0x0cb9,
+ 0x90a6, 0x0e5c,
+ 0x90a8, 0x1b14,
+ 0x90aa, 0x0905,
+ 0x90af, 0x1b15,
+ 0x90b1, 0x1b16,
+ 0x90b5, 0x1b17,
+ 0x90b8, 0x0c1b,
+ 0x90c1, 0x04ae,
+ 0x90ca, 0x07eb,
+ 0x90ce, 0x0fe0,
+ 0x90db, 0x1b1b,
+ 0x90de, 0x21bb,
+ 0x90e1, 0x070a,
+ 0x90e2, 0x1b18,
+ 0x90e4, 0x1b19,
+ 0x90e8, 0x0de6,
+ 0x90ed, 0x05b2,
+ 0x90f5, 0x0f23,
+ 0x90f7, 0x06b7,
+ 0x90fd, 0x0c4e,
+ 0x9102, 0x1b1c,
+ 0x9112, 0x1b1d,
+ 0x9115, 0x21bd,
+ 0x9119, 0x1b1e,
+ 0x9127, 0x21be,
+ 0x912d, 0x0c1c,
+ 0x9130, 0x1b20,
+ 0x9132, 0x1b1f,
+ 0x9149, 0x0cab,
+ 0x914a, 0x1b21,
+ 0x914b, 0x0940,
+ 0x914c, 0x090c,
+ 0x914d, 0x0d11,
+ 0x914e, 0x0baf,
+ 0x9152, 0x091e,
+ 0x9154, 0x0a32,
+ 0x9156, 0x1b22,
+ 0x9158, 0x1b23,
+ 0x9162, 0x0a23,
+ 0x9163, 0x1b24,
+ 0x9165, 0x1b25,
+ 0x9169, 0x1b26,
+ 0x916a, 0x0f59,
+ 0x916c, 0x0941,
+ 0x9172, 0x1b28,
+ 0x9173, 0x1b27,
+ 0x9175, 0x07ec,
+ 0x9177, 0x0805,
+ 0x9178, 0x088e,
+ 0x9182, 0x1b2b,
+ 0x9187, 0x0970,
+ 0x9189, 0x1b2a,
+ 0x918b, 0x1b29,
+ 0x918d, 0x0b49,
+ 0x9190, 0x07a3,
+ 0x9192, 0x0a67,
+ 0x9197, 0x0d44,
+ 0x919c, 0x0943,
+ 0x91a2, 0x1b2c,
+ 0x91a4, 0x09c7,
+ 0x91aa, 0x1b2f,
+ 0x91ab, 0x1b2d,
+ 0x91ac, 0x1e1b,
+ 0x91af, 0x1b2e,
+ 0x91b1, 0x1e61,
+ 0x91b4, 0x1b31,
+ 0x91b5, 0x1b30,
+ 0x91b8, 0x09e2,
+ 0x91ba, 0x1b32,
+ 0x91c0, 0x1b33,
+ 0x91c6, 0x0d64,
+ 0x91c7, 0x0843,
+ 0x91c8, 0x090d,
+ 0x91c9, 0x1b35,
+ 0x91cb, 0x1b36,
+ 0x91cc, 0x0f6c,
+ 0x91cd, 0x094f,
+ 0x91ce, 0x0efa,
+ 0x91cf, 0x0f94,
+ 0x91d0, 0x1b37,
+ 0x91d1, 0x06da,
+ 0x91d6, 0x1b38,
+ 0x91d7, 0x21c0,
+ 0x91d8, 0x0c1d,
+ 0x91da, 0x21bf,
+ 0x91db, 0x1b3b,
+ 0x91dc, 0x05d6,
+ 0x91dd, 0x0a11,
+ 0x91de, 0x21c1,
+ 0x91df, 0x1b39,
+ 0x91e1, 0x1b3a,
+ 0x91e3, 0x0bfc,
+ 0x91e4, 0x21c4,
+ 0x91e6, 0x0e83,
+ 0x91e7, 0x06f4,
+ 0x91ed, 0x21c2,
+ 0x91f5, 0x1b3d,
+ 0x91fc, 0x1b3c,
+ 0x91ff, 0x1b40,
+ 0x9206, 0x21c6,
+ 0x920a, 0x21c8,
+ 0x920d, 0x0cb7,
+ 0x920e, 0x05a1,
+ 0x9210, 0x21c7,
+ 0x9211, 0x1b44,
+ 0x9214, 0x1b41,
+ 0x9215, 0x1b43,
+ 0x921e, 0x1b3f,
+ 0x9229, 0x1b8a,
+ 0x922c, 0x1b42,
+ 0x9234, 0x0fb3,
+ 0x9237, 0x078e,
+ 0x9239, 0x21cf,
+ 0x923a, 0x21c9,
+ 0x923c, 0x21cb,
+ 0x923f, 0x1b4c,
+ 0x9240, 0x21ca,
+ 0x9244, 0x0c2e,
+ 0x9245, 0x1b47,
+ 0x9248, 0x1b4a,
+ 0x9249, 0x1b48,
+ 0x924b, 0x1b4d,
+ 0x924e, 0x21cc,
+ 0x9250, 0x1b4e,
+ 0x9251, 0x21ce,
+ 0x9257, 0x1b46,
+ 0x9259, 0x21cd,
+ 0x925a, 0x1b53,
+ 0x925b, 0x0516,
+ 0x925e, 0x1b45,
+ 0x9262, 0x0d41,
+ 0x9264, 0x1b49,
+ 0x9266, 0x09c8,
+ 0x9267, 0x21d0,
+ 0x9271, 0x07ed,
+ 0x9277, 0x21d2,
+ 0x927e, 0x0e76,
+ 0x9280, 0x06dc,
+ 0x9283, 0x0950,
+ 0x9285, 0x0c94,
+ 0x9288, 0x20aa,
+ 0x9291, 0x0aaf,
+ 0x9293, 0x1b51,
+ 0x9295, 0x1b4b,
+ 0x9296, 0x1b50,
+ 0x9298, 0x0ecf,
+ 0x929a, 0x0bd4,
+ 0x929b, 0x1b52,
+ 0x929c, 0x1b4f,
+ 0x92a7, 0x21d1,
+ 0x92ad, 0x0aae,
+ 0x92b7, 0x1b56,
+ 0x92b9, 0x1b55,
+ 0x92cf, 0x1b54,
+ 0x92d0, 0x21d7,
+ 0x92d2, 0x0e5d,
+ 0x92d3, 0x21db,
+ 0x92d5, 0x21d9,
+ 0x92d7, 0x21d5,
+ 0x92d9, 0x21d6,
+ 0x92e0, 0x21da,
+ 0x92e4, 0x0985,
+ 0x92e7, 0x21d4,
+ 0x92e9, 0x1b57,
+ 0x92ea, 0x0e2f,
+ 0x92ed, 0x04f6,
+ 0x92f2, 0x0db8,
+ 0x92f3, 0x0bb0,
+ 0x92f8, 0x0692,
+ 0x92f9, 0x20b0,
+ 0x92fa, 0x1b59,
+ 0x92fb, 0x21de,
+ 0x92fc, 0x07ef,
+ 0x92ff, 0x21e1,
+ 0x9302, 0x21e3,
+ 0x9306, 0x087a,
+ 0x930f, 0x1b58,
+ 0x9310, 0x0a33,
+ 0x9318, 0x0a34,
+ 0x9319, 0x1b5c,
+ 0x931a, 0x1b5e,
+ 0x931d, 0x21e2,
+ 0x931e, 0x21e0,
+ 0x9320, 0x09e3,
+ 0x9321, 0x21dd,
+ 0x9322, 0x1b5d,
+ 0x9323, 0x1b5f,
+ 0x9325, 0x21dc,
+ 0x9326, 0x06cb,
+ 0x9328, 0x0db7,
+ 0x932b, 0x090e,
+ 0x932c, 0x0fc9,
+ 0x932e, 0x1b5b,
+ 0x932f, 0x0868,
+ 0x9332, 0x0fe5,
+ 0x9335, 0x1b61,
+ 0x933a, 0x1b60,
+ 0x933b, 0x1b62,
+ 0x9344, 0x1b5a,
+ 0x9348, 0x20a9,
+ 0x934b, 0x0cc1,
+ 0x934d, 0x0c4f,
+ 0x9354, 0x0bf3,
+ 0x9356, 0x1b67,
+ 0x9357, 0x21e5,
+ 0x935b, 0x0b81,
+ 0x935c, 0x1b63,
+ 0x9360, 0x1b64,
+ 0x936c, 0x0703,
+ 0x936e, 0x1b66,
+ 0x9370, 0x21e4,
+ 0x9375, 0x0764,
+ 0x937c, 0x1b65,
+ 0x937e, 0x09c9,
+ 0x938c, 0x05d7,
+ 0x9394, 0x1b6b,
+ 0x9396, 0x082f,
+ 0x9397, 0x0afb,
+ 0x939a, 0x0be6,
+ 0x93a4, 0x21e6,
+ 0x93a7, 0x0599,
+ 0x93ac, 0x1b69,
+ 0x93ae, 0x0bdf,
+ 0x93b0, 0x1b68,
+ 0x93b9, 0x1b6c,
+ 0x93c3, 0x1b72,
+ 0x93c6, 0x21e7,
+ 0x93c8, 0x1b75,
+ 0x93d0, 0x1b74,
+ 0x93d1, 0x0c27,
+ 0x93d6, 0x1b6d,
+ 0x93d8, 0x1b71,
+ 0x93dd, 0x1b73,
+ 0x93de, 0x21e8,
+ 0x93e1, 0x06b8,
+ 0x93e4, 0x1b76,
+ 0x93e5, 0x1b70,
+ 0x93e8, 0x1b6f,
+ 0x93f8, 0x21e9,
+ 0x9403, 0x1b7a,
+ 0x9407, 0x1b7b,
+ 0x9410, 0x1b7c,
+ 0x9413, 0x1b79,
+ 0x9414, 0x1b78,
+ 0x9418, 0x09ca,
+ 0x9419, 0x0c82,
+ 0x941a, 0x1b77,
+ 0x9421, 0x1b80,
+ 0x942b, 0x1b7e,
+ 0x9431, 0x21ea,
+ 0x9435, 0x1b7f,
+ 0x9436, 0x1b7d,
+ 0x9438, 0x0b58,
+ 0x943a, 0x1b81,
+ 0x9441, 0x1b82,
+ 0x9444, 0x1b84,
+ 0x9445, 0x21eb,
+ 0x9448, 0x21ec,
+ 0x9451, 0x0611,
+ 0x9452, 0x1b83,
+ 0x9453, 0x0f06,
+ 0x945a, 0x1b8f,
+ 0x945b, 0x1b85,
+ 0x945e, 0x1b88,
+ 0x9460, 0x1b86,
+ 0x9462, 0x1b87,
+ 0x946a, 0x1b89,
+ 0x9470, 0x1b8b,
+ 0x9475, 0x1b8c,
+ 0x9477, 0x1b8d,
+ 0x947c, 0x1b90,
+ 0x947d, 0x1b8e,
+ 0x947e, 0x1b91,
+ 0x947f, 0x1b93,
+ 0x9481, 0x1b92,
+ 0x9577, 0x0bd5,
+ 0x9580, 0x0ef3,
+ 0x9582, 0x1b94,
+ 0x9583, 0x0ab0,
+ 0x9587, 0x1b95,
+ 0x9589, 0x0e14,
+ 0x958a, 0x1b96,
+ 0x958b, 0x0589,
+ 0x958f, 0x04de,
+ 0x9591, 0x0613,
+ 0x9592, 0x21ed,
+ 0x9593, 0x0612,
+ 0x9594, 0x1b97,
+ 0x9596, 0x1b98,
+ 0x9598, 0x1b99,
+ 0x95a0, 0x1b9b,
+ 0x95a2, 0x0614,
+ 0x95a3, 0x05b3,
+ 0x95a4, 0x07f0,
+ 0x95a5, 0x0d4a,
+ 0x95a7, 0x1b9d,
+ 0x95a8, 0x1b9c,
+ 0x95ad, 0x1b9e,
+ 0x95b2, 0x04fe,
+ 0x95b9, 0x1ba1,
+ 0x95bb, 0x1ba0,
+ 0x95bc, 0x1b9f,
+ 0x95be, 0x1ba2,
+ 0x95c3, 0x1ba5,
+ 0x95c7, 0x048b,
+ 0x95ca, 0x1ba3,
+ 0x95cc, 0x1ba7,
+ 0x95cd, 0x1ba6,
+ 0x95d4, 0x1ba9,
+ 0x95d5, 0x1ba8,
+ 0x95d6, 0x1baa,
+ 0x95d8, 0x0c86,
+ 0x95dc, 0x1bab,
+ 0x95e1, 0x1bac,
+ 0x95e2, 0x1bae,
+ 0x95e5, 0x1bad,
+ 0x961c, 0x0dde,
+ 0x9621, 0x1baf,
+ 0x9628, 0x1bb0,
+ 0x962a, 0x0855,
+ 0x962e, 0x1bb1,
+ 0x9632, 0x0e77,
+ 0x963b, 0x0acd,
+ 0x963f, 0x0468,
+ 0x9640, 0x0b2b,
+ 0x9642, 0x1bb3,
+ 0x9644, 0x0ddf,
+ 0x964b, 0x1bb6,
+ 0x964c, 0x1bb4,
+ 0x964d, 0x07f1,
+ 0x964f, 0x1bb5,
+ 0x9650, 0x0776,
+ 0x965b, 0x0e15,
+ 0x965c, 0x1bb8,
+ 0x965d, 0x1bba,
+ 0x965e, 0x1bb9,
+ 0x965f, 0x1bbb,
+ 0x9662, 0x04c3,
+ 0x9663, 0x0a1e,
+ 0x9664, 0x0986,
+ 0x9665, 0x0615,
+ 0x9666, 0x1bbc,
+ 0x966a, 0x0d1c,
+ 0x966c, 0x1bbe,
+ 0x9670, 0x04c4,
+ 0x9672, 0x1bbd,
+ 0x9673, 0x0be0,
+ 0x9675, 0x0f95,
+ 0x9676, 0x0c83,
+ 0x9677, 0x1bb7,
+ 0x9678, 0x0f6e,
+ 0x967a, 0x0765,
+ 0x967d, 0x0f45,
+ 0x9685, 0x06f1,
+ 0x9686, 0x0f7c,
+ 0x9688, 0x06fe,
+ 0x968a, 0x0b42,
+ 0x968b, 0x186c,
+ 0x968d, 0x1bbf,
+ 0x968e, 0x058a,
+ 0x968f, 0x0a35,
+ 0x9694, 0x05b4,
+ 0x9695, 0x1bc1,
+ 0x9697, 0x1bc2,
+ 0x9698, 0x1bc0,
+ 0x9699, 0x073a,
+ 0x969b, 0x084d,
+ 0x969c, 0x09cb,
+ 0x969d, 0x21f0,
+ 0x96a0, 0x04c5,
+ 0x96a3, 0x0fa1,
+ 0x96a7, 0x1bc4,
+ 0x96a8, 0x1b0b,
+ 0x96aa, 0x1bc3,
+ 0x96af, 0x21f1,
+ 0x96b0, 0x1bc7,
+ 0x96b1, 0x1bc5,
+ 0x96b4, 0x1bc8,
+ 0x96b6, 0x1bc9,
+ 0x96b7, 0x0fb4,
+ 0x96b8, 0x1bca,
+ 0x96bb, 0x0a6d,
+ 0x96bc, 0x0d4f,
+ 0x96c0, 0x0a43,
+ 0x96c1, 0x0623,
+ 0x96c4, 0x0f24,
+ 0x96c5, 0x056d,
+ 0x96c6, 0x0942,
+ 0x96c7, 0x078f,
+ 0x96c9, 0x1bce,
+ 0x96cb, 0x1bcd,
+ 0x96cc, 0x08c1,
+ 0x96cd, 0x1bcf,
+ 0x96ce, 0x1bcc,
+ 0x96d1, 0x0876,
+ 0x96d5, 0x1bd3,
+ 0x96d6, 0x1992,
+ 0x96d9, 0x10eb,
+ 0x96db, 0x0a3d,
+ 0x96dc, 0x1bd1,
+ 0x96e2, 0x0f6d,
+ 0x96e3, 0x0cc9,
+ 0x96e8, 0x04cd,
+ 0x96ea, 0x0a87,
+ 0x96eb, 0x08e2,
+ 0x96f0, 0x0e07,
+ 0x96f2, 0x04e2,
+ 0x96f6, 0x0fb5,
+ 0x96f7, 0x0f55,
+ 0x96f9, 0x1bd4,
+ 0x96fb, 0x0c3f,
+ 0x9700, 0x0927,
+ 0x9704, 0x1bd5,
+ 0x9706, 0x1bd6,
+ 0x9707, 0x0a12,
+ 0x9708, 0x1bd7,
+ 0x970a, 0x0fb6,
+ 0x970d, 0x1bd2,
+ 0x970e, 0x1bd9,
+ 0x970f, 0x1bdb,
+ 0x9711, 0x1bda,
+ 0x9713, 0x1bd8,
+ 0x9716, 0x1bdc,
+ 0x9719, 0x1bdd,
+ 0x971c, 0x0afc,
+ 0x971e, 0x0562,
+ 0x9724, 0x1bde,
+ 0x9727, 0x0ec4,
+ 0x972a, 0x1bdf,
+ 0x9730, 0x1be0,
+ 0x9732, 0x0fd0,
+ 0x9733, 0x21f2,
+ 0x9738, 0x1414,
+ 0x9739, 0x1be1,
+ 0x973b, 0x21f3,
+ 0x973d, 0x1be2,
+ 0x9742, 0x1be7,
+ 0x9743, 0x21f4,
+ 0x9744, 0x1be4,
+ 0x9746, 0x1be5,
+ 0x9748, 0x1be6,
+ 0x9749, 0x1be8,
+ 0x974d, 0x21f5,
+ 0x974f, 0x21f6,
+ 0x9751, 0x21f7,
+ 0x9752, 0x0a68,
+ 0x9755, 0x21f8,
+ 0x9756, 0x0f03,
+ 0x9759, 0x0a69,
+ 0x975c, 0x1be9,
+ 0x975e, 0x0d87,
+ 0x9760, 0x1bea,
+ 0x9761, 0x1d06,
+ 0x9762, 0x0ed8,
+ 0x9764, 0x1beb,
+ 0x9766, 0x1bec,
+ 0x9768, 0x1bed,
+ 0x9769, 0x05b5,
+ 0x976b, 0x1bef,
+ 0x976d, 0x0a1f,
+ 0x9771, 0x1bf0,
+ 0x9774, 0x06fa,
+ 0x9779, 0x1bf1,
+ 0x977a, 0x1bf5,
+ 0x977c, 0x1bf3,
+ 0x9781, 0x1bf4,
+ 0x9784, 0x05d1,
+ 0x9785, 0x1bf2,
+ 0x9786, 0x1bf6,
+ 0x978b, 0x1bf7,
+ 0x978d, 0x048c,
+ 0x978f, 0x1bf8,
+ 0x9798, 0x09cc,
+ 0x979c, 0x1bfa,
+ 0x97a0, 0x0661,
+ 0x97a3, 0x1bfd,
+ 0x97a6, 0x1bfc,
+ 0x97a8, 0x1bfb,
+ 0x97ab, 0x1a34,
+ 0x97ad, 0x0e2c,
+ 0x97b3, 0x1bfe,
+ 0x97c3, 0x1c00,
+ 0x97c6, 0x1c01,
+ 0x97c8, 0x1c02,
+ 0x97cb, 0x1c03,
+ 0x97d3, 0x0616,
+ 0x97dc, 0x1c04,
+ 0x97ed, 0x1c05,
+ 0x97ee, 0x0cd9,
+ 0x97f2, 0x1c07,
+ 0x97f3, 0x053b,
+ 0x97f5, 0x1c0a,
+ 0x97f6, 0x1c09,
+ 0x97fb, 0x04c6,
+ 0x97ff, 0x06b9,
+ 0x9801, 0x0e17,
+ 0x9802, 0x0bd6,
+ 0x9803, 0x0812,
+ 0x9805, 0x07f2,
+ 0x9806, 0x0971,
+ 0x9808, 0x0a22,
+ 0x980c, 0x1c0c,
+ 0x980f, 0x1c0b,
+ 0x9810, 0x0f2c,
+ 0x9811, 0x0624,
+ 0x9812, 0x0d66,
+ 0x9813, 0x0cb4,
+ 0x9817, 0x0a42,
+ 0x9818, 0x0f96,
+ 0x981a, 0x0731,
+ 0x9821, 0x1c0f,
+ 0x9824, 0x1c0e,
+ 0x982c, 0x0e79,
+ 0x982d, 0x0c84,
+ 0x9830, 0x1e73,
+ 0x9834, 0x04f2,
+ 0x9837, 0x1c10,
+ 0x9838, 0x1c0d,
+ 0x983b, 0x0dc3,
+ 0x983c, 0x0f54,
+ 0x983d, 0x1c11,
+ 0x9846, 0x1c12,
+ 0x984b, 0x1c14,
+ 0x984c, 0x0b4a,
+ 0x984d, 0x05b9,
+ 0x984f, 0x1c13,
+ 0x9854, 0x0625,
+ 0x9855, 0x0766,
+ 0x9857, 0x21f9,
+ 0x9858, 0x0626,
+ 0x985a, 0x1e48,
+ 0x985b, 0x0c39,
+ 0x985e, 0x0fa8,
+ 0x9865, 0x21fa,
+ 0x9867, 0x0790,
+ 0x986b, 0x1c15,
+ 0x986f, 0x1c16,
+ 0x9873, 0x1c1a,
+ 0x9874, 0x1c19,
+ 0x98a8, 0x0de9,
+ 0x98aa, 0x1c1b,
+ 0x98af, 0x1c1c,
+ 0x98b1, 0x1c1d,
+ 0x98b6, 0x1c1e,
+ 0x98c3, 0x1c20,
+ 0x98c4, 0x1c1f,
+ 0x98c6, 0x1c21,
+ 0x98db, 0x0d88,
+ 0x98dc, 0x1839,
+ 0x98df, 0x09ef,
+ 0x98e2, 0x064c,
+ 0x98e9, 0x1c22,
+ 0x98eb, 0x1c23,
+ 0x98ed, 0x10c1,
+ 0x98ee, 0x14da,
+ 0x98ef, 0x0d67,
+ 0x98f2, 0x04bf,
+ 0x98f4, 0x047f,
+ 0x98fc, 0x08c2,
+ 0x98fd, 0x0e5e,
+ 0x98fe, 0x09e6,
+ 0x9903, 0x1c24,
+ 0x9905, 0x0eeb,
+ 0x9909, 0x1c25,
+ 0x990a, 0x0f46,
+ 0x990c, 0x04e4,
+ 0x9910, 0x088f,
+ 0x9912, 0x1c26,
+ 0x9913, 0x056e,
+ 0x9914, 0x1c27,
+ 0x9918, 0x1c28,
+ 0x991d, 0x1c2a,
+ 0x9920, 0x1c2d,
+ 0x9921, 0x1c29,
+ 0x9924, 0x1c2c,
+ 0x9927, 0x21fd,
+ 0x9928, 0x0617,
+ 0x992c, 0x1c2e,
+ 0x992e, 0x1c2f,
+ 0x993d, 0x1c30,
+ 0x9942, 0x1c32,
+ 0x9945, 0x1c34,
+ 0x9949, 0x1c33,
+ 0x994b, 0x1c36,
+ 0x994c, 0x1c39,
+ 0x9950, 0x1c35,
+ 0x9951, 0x1c37,
+ 0x9955, 0x1c3a,
+ 0x9957, 0x06ba,
+ 0x9996, 0x091f,
+ 0x9997, 0x1c3b,
+ 0x9999, 0x07f3,
+ 0x999e, 0x21ff,
+ 0x99a5, 0x1c3d,
+ 0x99a8, 0x059c,
+ 0x99ac, 0x0d05,
+ 0x99ad, 0x1c3e,
+ 0x99b3, 0x0b98,
+ 0x99b4, 0x0cc3,
+ 0x99bc, 0x1c40,
+ 0x99c1, 0x0d33,
+ 0x99c4, 0x0b2c,
+ 0x99c5, 0x04fa,
+ 0x99c6, 0x06e6,
+ 0x99c8, 0x06e7,
+ 0x99d0, 0x0bb1,
+ 0x99d1, 0x1c45,
+ 0x99d2, 0x06e8,
+ 0x99d5, 0x056f,
+ 0x99d8, 0x1c44,
+ 0x99db, 0x1c42,
+ 0x99dd, 0x1c43,
+ 0x99df, 0x1c41,
+ 0x99e2, 0x1c4f,
+ 0x99ed, 0x1c46,
+ 0x99f1, 0x1c48,
+ 0x99f8, 0x1c4b,
+ 0x99fb, 0x1c4a,
+ 0x99ff, 0x0963,
+ 0x9a01, 0x1c4c,
+ 0x9a05, 0x1c4e,
+ 0x9a0e, 0x064d,
+ 0x9a0f, 0x1c4d,
+ 0x9a12, 0x0afd,
+ 0x9a13, 0x0767,
+ 0x9a19, 0x1c50,
+ 0x9a28, 0x0b2d,
+ 0x9a2b, 0x1c51,
+ 0x9a30, 0x0c85,
+ 0x9a37, 0x1c52,
+ 0x9a3e, 0x1c57,
+ 0x9a40, 0x1c55,
+ 0x9a42, 0x1c54,
+ 0x9a43, 0x1c56,
+ 0x9a45, 0x1c53,
+ 0x9a4d, 0x1c59,
+ 0x9a4e, 0x2200,
+ 0x9a52, 0x1e2f,
+ 0x9a55, 0x1c58,
+ 0x9a57, 0x1c5b,
+ 0x9a5a, 0x06bb,
+ 0x9a5b, 0x1c5a,
+ 0x9a5f, 0x1c5c,
+ 0x9a62, 0x1c5d,
+ 0x9a64, 0x1c5f,
+ 0x9a65, 0x1c5e,
+ 0x9a69, 0x1c60,
+ 0x9a6a, 0x1c62,
+ 0x9a6b, 0x1c61,
+ 0x9aa8, 0x080e,
+ 0x9aad, 0x1c63,
+ 0x9ab0, 0x1c64,
+ 0x9ab8, 0x059a,
+ 0x9abc, 0x1c65,
+ 0x9ac0, 0x1c66,
+ 0x9ac4, 0x0a37,
+ 0x9acf, 0x1c67,
+ 0x9ad1, 0x1c68,
+ 0x9ad3, 0x1c69,
+ 0x9ad8, 0x07f4,
+ 0x9ad9, 0x2201,
+ 0x9adc, 0x2202,
+ 0x9ade, 0x1c6b,
+ 0x9ae2, 0x1c6d,
+ 0x9ae6, 0x1c6f,
+ 0x9aea, 0x0d45,
+ 0x9aeb, 0x1c71,
+ 0x9aed, 0x0d98,
+ 0x9aee, 0x1c72,
+ 0x9aef, 0x1c70,
+ 0x9af1, 0x1c74,
+ 0x9af4, 0x1c73,
+ 0x9af7, 0x1c75,
+ 0x9afb, 0x1c76,
+ 0x9b06, 0x1c77,
+ 0x9b18, 0x1c78,
+ 0x9b1a, 0x1c79,
+ 0x9b1f, 0x1c7a,
+ 0x9b22, 0x1c7b,
+ 0x9b25, 0x1c7d,
+ 0x9b27, 0x1c7e,
+ 0x9b2e, 0x1c82,
+ 0x9b31, 0x14d4,
+ 0x9b32, 0x1c84,
+ 0x9b3b, 0x17a9,
+ 0x9b3c, 0x064e,
+ 0x9b41, 0x057f,
+ 0x9b42, 0x0822,
+ 0x9b43, 0x1c86,
+ 0x9b44, 0x1c85,
+ 0x9b45, 0x0eb1,
+ 0x9b4d, 0x1c88,
+ 0x9b4f, 0x1c87,
+ 0x9b51, 0x1c8a,
+ 0x9b54, 0x0e90,
+ 0x9b58, 0x1c8b,
+ 0x9b5a, 0x0695,
+ 0x9b6f, 0x0fcb,
+ 0x9b72, 0x2204,
+ 0x9b74, 0x1c8c,
+ 0x9b75, 0x2203,
+ 0x9b83, 0x1c8e,
+ 0x9b8e, 0x0482,
+ 0x9b8f, 0x2205,
+ 0x9b91, 0x1c8f,
+ 0x9b92, 0x0dfb,
+ 0x9b93, 0x1c8d,
+ 0x9b96, 0x1c90,
+ 0x9b9f, 0x1c92,
+ 0x9ba8, 0x1c94,
+ 0x9baa, 0x0e9c,
+ 0x9bab, 0x087b,
+ 0x9bad, 0x086a,
+ 0x9bae, 0x0ab1,
+ 0x9bb1, 0x2206,
+ 0x9bb4, 0x1c95,
+ 0x9bb9, 0x1c98,
+ 0x9bbb, 0x2207,
+ 0x9bc0, 0x1c96,
+ 0x9bc6, 0x1c99,
+ 0x9bc9, 0x07a5,
+ 0x9bca, 0x1c97,
+ 0x9bcf, 0x1c9a,
+ 0x9bd1, 0x1c9b,
+ 0x9bd4, 0x1ca0,
+ 0x9bd6, 0x0878,
+ 0x9bdb, 0x0b44,
+ 0x9be1, 0x1ca1,
+ 0x9be2, 0x1c9e,
+ 0x9be3, 0x1c9d,
+ 0x9be4, 0x1c9f,
+ 0x9be8, 0x0735,
+ 0x9bf0, 0x1ca5,
+ 0x9bf1, 0x1ca4,
+ 0x9bf2, 0x1ca3,
+ 0x9bf5, 0x0477,
+ 0x9c00, 0x2208,
+ 0x9c04, 0x1caf,
+ 0x9c06, 0x1cab,
+ 0x9c08, 0x1cac,
+ 0x9c09, 0x1ca8,
+ 0x9c0a, 0x1cae,
+ 0x9c0c, 0x1caa,
+ 0x9c0d, 0x05c0,
+ 0x9c10, 0x0ff2,
+ 0x9c12, 0x1cad,
+ 0x9c13, 0x1ca9,
+ 0x9c14, 0x1ca7,
+ 0x9c15, 0x1ca6,
+ 0x9c1b, 0x1cb1,
+ 0x9c21, 0x1cb4,
+ 0x9c24, 0x1cb3,
+ 0x9c25, 0x1cb2,
+ 0x9c2d, 0x0dbb,
+ 0x9c2e, 0x1cb0,
+ 0x9c2f, 0x04b7,
+ 0x9c30, 0x1cb5,
+ 0x9c32, 0x1cb7,
+ 0x9c39, 0x05cd,
+ 0x9c3a, 0x1ca2,
+ 0x9c3b, 0x04d9,
+ 0x9c3e, 0x1cb9,
+ 0x9c46, 0x1cb8,
+ 0x9c47, 0x1cb6,
+ 0x9c48, 0x0b6b,
+ 0x9c52, 0x0e9e,
+ 0x9c57, 0x0fa2,
+ 0x9c5a, 0x1cba,
+ 0x9c60, 0x1cbb,
+ 0x9c67, 0x1cbc,
+ 0x9c76, 0x1cbd,
+ 0x9c78, 0x1cbe,
+ 0x9ce5, 0x0bd7,
+ 0x9ce7, 0x1cbf,
+ 0x9ce9, 0x0d4b,
+ 0x9ceb, 0x1cc4,
+ 0x9cec, 0x1cc0,
+ 0x9cf0, 0x1cc1,
+ 0x9cf3, 0x0e5f,
+ 0x9cf4, 0x0ed0,
+ 0x9cf6, 0x0ca8,
+ 0x9d03, 0x1cc5,
+ 0x9d06, 0x1cc6,
+ 0x9d07, 0x0c96,
+ 0x9d08, 0x1cc3,
+ 0x9d09, 0x1cc2,
+ 0x9d0e, 0x052a,
+ 0x9d12, 0x1cce,
+ 0x9d15, 0x1ccd,
+ 0x9d1b, 0x0517,
+ 0x9d1f, 0x1ccb,
+ 0x9d23, 0x1cca,
+ 0x9d26, 0x1cc8,
+ 0x9d28, 0x05d9,
+ 0x9d2a, 0x1cc7,
+ 0x9d2b, 0x08de,
+ 0x9d2c, 0x0529,
+ 0x9d3b, 0x07f5,
+ 0x9d3e, 0x1cd1,
+ 0x9d3f, 0x1cd0,
+ 0x9d41, 0x1ccf,
+ 0x9d44, 0x1ccc,
+ 0x9d46, 0x1cd2,
+ 0x9d48, 0x1cd3,
+ 0x9d50, 0x1cd8,
+ 0x9d51, 0x1cd7,
+ 0x9d59, 0x1cd9,
+ 0x9d5c, 0x04cf,
+ 0x9d5d, 0x1cd4,
+ 0x9d60, 0x0806,
+ 0x9d61, 0x0ec5,
+ 0x9d64, 0x1cd6,
+ 0x9d6b, 0x220a,
+ 0x9d6c, 0x0e60,
+ 0x9d6f, 0x1cde,
+ 0x9d70, 0x2209,
+ 0x9d72, 0x1cda,
+ 0x9d7a, 0x1cdf,
+ 0x9d87, 0x1cdc,
+ 0x9d89, 0x1cdb,
+ 0x9d8f, 0x0732,
+ 0x9d9a, 0x1ce0,
+ 0x9da4, 0x1ce1,
+ 0x9da9, 0x1ce2,
+ 0x9dab, 0x1cdd,
+ 0x9daf, 0x1cc9,
+ 0x9db2, 0x1ce3,
+ 0x9db4, 0x0bfd,
+ 0x9db8, 0x1ce7,
+ 0x9dba, 0x1ce8,
+ 0x9dbb, 0x1ce6,
+ 0x9dc1, 0x1ce5,
+ 0x9dc2, 0x1ceb,
+ 0x9dc4, 0x1ce4,
+ 0x9dc6, 0x1ce9,
+ 0x9dcf, 0x1cea,
+ 0x9dd3, 0x1ced,
+ 0x9dd7, 0x1dde,
+ 0x9dd9, 0x1cec,
+ 0x9de6, 0x1cef,
+ 0x9ded, 0x1cf0,
+ 0x9def, 0x1cf1,
+ 0x9df2, 0x0fef,
+ 0x9df8, 0x1cee,
+ 0x9df9, 0x0b4b,
+ 0x9dfa, 0x085d,
+ 0x9dfd, 0x1cf2,
+ 0x9e19, 0x220c,
+ 0x9e1a, 0x1cf3,
+ 0x9e1e, 0x1cf5,
+ 0x9e75, 0x1cf6,
+ 0x9e78, 0x0768,
+ 0x9e79, 0x1cf7,
+ 0x9e7c, 0x1dfd,
+ 0x9e7d, 0x1cf8,
+ 0x9e7f, 0x08db,
+ 0x9e81, 0x1cf9,
+ 0x9e88, 0x1cfa,
+ 0x9e8b, 0x1cfb,
+ 0x9e91, 0x1cff,
+ 0x9e92, 0x1cfd,
+ 0x9e93, 0x0fe2,
+ 0x9e95, 0x1cfe,
+ 0x9e97, 0x0fb7,
+ 0x9e9d, 0x1d00,
+ 0x9e9f, 0x0fa3,
+ 0x9ea5, 0x1d01,
+ 0x9ea6, 0x0d34,
+ 0x9ea9, 0x1d02,
+ 0x9eaa, 0x1d04,
+ 0x9ead, 0x1d05,
+ 0x9eb4, 0x1e02,
+ 0x9eb5, 0x1e75,
+ 0x9eb8, 0x1d03,
+ 0x9eb9, 0x07ff,
+ 0x9eba, 0x0ed9,
+ 0x9ebb, 0x0e91,
+ 0x9ebc, 0x1284,
+ 0x9ebe, 0x14ff,
+ 0x9ebf, 0x0ea9,
+ 0x9ec4, 0x052b,
+ 0x9ecc, 0x1d07,
+ 0x9ecd, 0x066a,
+ 0x9ece, 0x1d08,
+ 0x9ed1, 0x220d,
+ 0x9ed2, 0x0807,
+ 0x9ed4, 0x1d0b,
+ 0x9ed8, 0x160d,
+ 0x9ed9, 0x0ee7,
+ 0x9edb, 0x0b43,
+ 0x9edc, 0x1d0c,
+ 0x9edd, 0x1d0e,
+ 0x9ede, 0x1d0d,
+ 0x9ee0, 0x1d0f,
+ 0x9ee5, 0x1d10,
+ 0x9ee8, 0x1d11,
+ 0x9eef, 0x1d12,
+ 0x9ef4, 0x1d13,
+ 0x9ef6, 0x1d14,
+ 0x9ef9, 0x1d16,
+ 0x9efb, 0x1d17,
+ 0x9f07, 0x1d1a,
+ 0x9f0e, 0x0c1e,
+ 0x9f13, 0x0791,
+ 0x9f15, 0x1d1d,
+ 0x9f20, 0x0acf,
+ 0x9f21, 0x1d1e,
+ 0x9f2c, 0x1d1f,
+ 0x9f3b, 0x0d93,
+ 0x9f3e, 0x1d20,
+ 0x9f4a, 0x1d21,
+ 0x9f4b, 0x170a,
+ 0x9f4e, 0x1a7b,
+ 0x9f4f, 0x1c06,
+ 0x9f52, 0x1d22,
+ 0x9f54, 0x1d23,
+ 0x9f5f, 0x1d25,
+ 0x9f62, 0x0fb8,
+ 0x9f63, 0x1d24,
+ 0x9f66, 0x1d28,
+ 0x9f6a, 0x1d2b,
+ 0x9f6c, 0x1d2a,
+ 0x9f72, 0x1d2d,
+ 0x9f76, 0x1d2e,
+ 0x9f77, 0x1d2c,
+ 0x9f8d, 0x0f7e,
+ 0x9f95, 0x1d2f,
+ 0x9f9c, 0x1d30,
+ 0x9f9d, 0x1727,
+ 0x9fa0, 0x1d31,
+ 0xf929, 0x2129,
+ 0xf9dc, 0x21ee,
+ 0xfa0e, 0x20da,
+ 0xfa0f, 0x20e5,
+ 0xfa11, 0x20fb,
+ 0xfa12, 0x2121,
+ 0xfa13, 0x2131,
+ 0xfa14, 0x2133,
+ 0xfa15, 0x215e,
+ 0xfa16, 0x2164,
+ 0xfa17, 0x217b,
+ 0xfa18, 0x2183,
+ 0xfa1b, 0x2187,
+ 0xfa1c, 0x218b,
+ 0xfa1d, 0x218e,
+ 0xfa1e, 0x2197,
+ 0xfa1f, 0x21a2,
+ 0xfa20, 0x21a4,
+ 0xfa22, 0x21ae,
+ 0xfa23, 0x21b6,
+ 0xfa24, 0x21b8,
+ 0xfa26, 0x21bc,
+ 0xfa27, 0x21d8,
+ 0xfa28, 0x21df,
+ 0xfa29, 0x21ef,
+ 0xfa2a, 0x21fb,
+ 0xfa2c, 0x21fe,
+ 0xfa2d, 0x220b,
+ 0xfb01, 0x0070,
+ 0xfe30, 0x1eda,
+ 0xfe31, 0x1ed4,
+ 0xfe33, 0x1ed2,
+ 0xfe35, 0x1edb,
+ 0xfe37, 0x1ee1,
+ 0xfe39, 0x1edd,
+ 0xfe3b, 0x1eeb,
+ 0xfe3d, 0x1ee5,
+ 0xfe3f, 0x1ee3,
+ 0xfe41, 0x1ee7,
+ 0xff01, 0x0282,
+ 0xff02, 0x1f47,
+ 0xff03, 0x02cc,
+ 0xff04, 0x02c8,
+ 0xff05, 0x02cb,
+ 0xff06, 0x02cd,
+ 0xff07, 0x1f46,
+ 0xff08, 0x02a2,
+ 0xff0a, 0x02ce,
+ 0xff0b, 0x02b4,
+ 0xff0c, 0x027c,
+ 0xff0d, 0x0296,
+ 0xff0e, 0x027d,
+ 0xff0f, 0x0297,
+ 0xff10, 0x030c,
+ 0xff1a, 0x027f,
+ 0xff1c, 0x02bb,
+ 0xff1d, 0x02b9,
+ 0xff1e, 0x02bc,
+ 0xff1f, 0x0281,
+ 0xff20, 0x02cf,
+ 0xff21, 0x0316,
+ 0xff3b, 0x02a6,
+ 0xff3c, 0x0298,
+ 0xff3d, 0x02a7,
+ 0xff3e, 0x0288,
+ 0xff3f, 0x028a,
+ 0xff40, 0x0286,
+ 0xff41, 0x0330,
+ 0xff5b, 0x02a8,
+ 0xff5c, 0x029b,
+ 0xff5d, 0x02a9,
+ 0xff5e, 0x0299,
+ 0xff61, 0x0147,
+ 0xffe0, 0x02c9,
+ 0xffe2, 0x02ef,
+ 0xffe3, 0x0289,
+ 0xffe4, 0x1f45,
+ 0xffe5, 0x02c7,
+ 0xffe8, 0x0143,
+ 0x00b0, 0x204d,
+ 0x2015, 0x1ed4,
+ 0x2016, 0x1ed7,
+ 0x2018, 0x2059,
+ 0x201c, 0x2057,
+ 0x2025, 0x1eda,
+ 0x2026, 0x1ed9,
+ 0x2032, 0x2051,
+ 0x2033, 0x205b,
+ 0x2190, 0x02e2,
+ 0x2191, 0x02e0,
+ 0x2192, 0x02e3,
+ 0x2193, 0x02e1,
+ 0x2225, 0x1ed7,
+ 0x223c, 0x1ed6,
+ 0x22ef, 0x1ed9,
+ 0x2500, 0x1d39,
+ 0x2502, 0x1d37,
+ 0x2504, 0x1d3d,
+ 0x2506, 0x1d3b,
+ 0x2508, 0x1d41,
+ 0x250a, 0x1d3f,
+ 0x250c, 0x1d47,
+ 0x250d, 0x1d49,
+ 0x250e, 0x1d48,
+ 0x250f, 0x1d4a,
+ 0x2510, 0x1d4f,
+ 0x2511, 0x1d51,
+ 0x2512, 0x1d50,
+ 0x2513, 0x1d52,
+ 0x2514, 0x1d43,
+ 0x2515, 0x1d45,
+ 0x2516, 0x1d44,
+ 0x2517, 0x1d46,
+ 0x2518, 0x1d4b,
+ 0x2519, 0x1d4d,
+ 0x251a, 0x1d4c,
+ 0x251b, 0x1d4e,
+ 0x251c, 0x1d63,
+ 0x251d, 0x1d67,
+ 0x251e, 0x1d65,
+ 0x251f, 0x1d64,
+ 0x2520, 0x1d66,
+ 0x2521, 0x1d69,
+ 0x2522, 0x1d68,
+ 0x2523, 0x1d6a,
+ 0x2525, 0x1d6f,
+ 0x2526, 0x1d6d,
+ 0x2527, 0x1d6c,
+ 0x2528, 0x1d6e,
+ 0x2529, 0x1d71,
+ 0x252a, 0x1d70,
+ 0x252b, 0x1d72,
+ 0x252c, 0x1d5b,
+ 0x252d, 0x1d5d,
+ 0x2530, 0x1d5c,
+ 0x2531, 0x1d60,
+ 0x2534, 0x1d53,
+ 0x2535, 0x1d55,
+ 0x2538, 0x1d54,
+ 0x2539, 0x1d58,
+ 0x253d, 0x1d77,
+ 0x2540, 0x1d75,
+ 0x2541, 0x1d74,
+ 0x2542, 0x1d76,
+ 0x2543, 0x1d7b,
+ 0x2544, 0x1d7d,
+ 0x2545, 0x1d7a,
+ 0x2546, 0x1d7c,
+ 0x2547, 0x1d81,
+ 0x2548, 0x1d80,
+ 0x2549, 0x1d7e,
+ 0x3001, 0x1ecf,
+ 0x3008, 0x1ee3,
+ 0x3013, 0x204e,
+ 0x3014, 0x1edd,
+ 0x301c, 0x1ed6,
+ 0x301d, 0x1f14,
+ 0x301f, 0x1f15,
+ 0x3041, 0x1eee,
+ 0x3043, 0x1eef,
+ 0x3045, 0x1ef0,
+ 0x3047, 0x1ef1,
+ 0x3049, 0x1ef2,
+ 0x3063, 0x1ef3,
+ 0x3083, 0x1ef4,
+ 0x3085, 0x1ef5,
+ 0x3087, 0x1ef6,
+ 0x308e, 0x1ef7,
+ 0x309b, 0x2050,
+ 0x309c, 0x204f,
+ 0x30a1, 0x1ef8,
+ 0x30a3, 0x1ef9,
+ 0x30a5, 0x1efa,
+ 0x30a7, 0x1efb,
+ 0x30a9, 0x1efc,
+ 0x30c3, 0x1efd,
+ 0x30e3, 0x1efe,
+ 0x30e5, 0x1eff,
+ 0x30e7, 0x1f00,
+ 0x30ee, 0x1f01,
+ 0x30f5, 0x1f02,
+ 0x30fc, 0x1ed3,
+ 0x3300, 0x209e,
+ 0x3303, 0x2092,
+ 0x3305, 0x208d,
+ 0x330d, 0x1f0e,
+ 0x3314, 0x1f05,
+ 0x3315, 0x2094,
+ 0x3316, 0x208a,
+ 0x3318, 0x2093,
+ 0x331e, 0x20a1,
+ 0x3322, 0x2089,
+ 0x3323, 0x209c,
+ 0x3326, 0x1f0f,
+ 0x3327, 0x1f09,
+ 0x332a, 0x20a4,
+ 0x332b, 0x1f11,
+ 0x3331, 0x20a6,
+ 0x3333, 0x208e,
+ 0x3336, 0x1f0b,
+ 0x3339, 0x2097,
+ 0x333b, 0x209d,
+ 0x3342, 0x209b,
+ 0x3347, 0x20a5,
+ 0x3349, 0x1f04,
+ 0x334a, 0x1f12,
+ 0x334d, 0x1f07,
+ 0x334e, 0x2091,
+ 0x3351, 0x1f0c,
+ 0x3357, 0x2098,
+ 0x337f, 0x2084,
+ 0xff08, 0x1edb,
+ 0xff0c, 0x204c,
+ 0xff0d, 0x1ed5,
+ 0xff0e, 0x2052,
+ 0xff1d, 0x1eed,
+ 0xff3b, 0x1edf,
+ 0xff3d, 0x1ee0,
+ 0xff3f, 0x1ed2,
+ 0xff5b, 0x1ee1,
+ 0xff5c, 0x1ed8,
+ 0xff5d, 0x1ee2,
+ 0xff5e, 0x1ed6,
+ 0xffe3, 0x1ed1,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12UniJISUCS2VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12UniJISUCS2VMap2, 7108
+};
+
+static Gushort japan12VMap2[294] = {
+ 0x0000, 0x0000,
+ 0x2121, 0x0279,
+ 0x2221, 0x02d7,
+ 0x223a, 0x02e5,
+ 0x224a, 0x02ed,
+ 0x225c, 0x02f4,
+ 0x2272, 0x0303,
+ 0x227e, 0x030b,
+ 0x2330, 0x030c,
+ 0x2341, 0x0316,
+ 0x2361, 0x0330,
+ 0x2421, 0x034a,
+ 0x2521, 0x039d,
+ 0x2621, 0x03f3,
+ 0x2641, 0x040b,
+ 0x2721, 0x0423,
+ 0x2751, 0x0444,
+ 0x2821, 0x1d37,
+ 0x2822, 0x1d39,
+ 0x2823, 0x1d43,
+ 0x2824, 0x1d47,
+ 0x2825, 0x1d4f,
+ 0x2826, 0x1d4b,
+ 0x2827, 0x1d53,
+ 0x2828, 0x1d63,
+ 0x2829, 0x1d5b,
+ 0x282a, 0x1d6b,
+ 0x282b, 0x1d73,
+ 0x282c, 0x1d38,
+ 0x282d, 0x1d3a,
+ 0x282e, 0x1d46,
+ 0x282f, 0x1d4a,
+ 0x2830, 0x1d52,
+ 0x2831, 0x1d4e,
+ 0x2832, 0x1d5a,
+ 0x2833, 0x1d6a,
+ 0x2834, 0x1d62,
+ 0x2835, 0x1d72,
+ 0x2836, 0x1d82,
+ 0x2837, 0x1d57,
+ 0x2838, 0x1d66,
+ 0x2839, 0x1d5f,
+ 0x283a, 0x1d6e,
+ 0x283b, 0x1d76,
+ 0x283c, 0x1d54,
+ 0x283d, 0x1d67,
+ 0x283e, 0x1d5c,
+ 0x283f, 0x1d6f,
+ 0x2840, 0x1d79,
+ 0x3021, 0x0465,
+ 0x3121, 0x04c3,
+ 0x3221, 0x0521,
+ 0x3321, 0x057f,
+ 0x3421, 0x05dd,
+ 0x3521, 0x063b,
+ 0x3621, 0x0699,
+ 0x3721, 0x06f7,
+ 0x3821, 0x0755,
+ 0x3921, 0x07b3,
+ 0x3a21, 0x0811,
+ 0x3b21, 0x086f,
+ 0x3c21, 0x08cd,
+ 0x3d21, 0x092b,
+ 0x3e21, 0x0989,
+ 0x3f21, 0x09e7,
+ 0x4021, 0x0a45,
+ 0x4121, 0x0aa3,
+ 0x4221, 0x0b01,
+ 0x4321, 0x0b5f,
+ 0x4421, 0x0bbd,
+ 0x4521, 0x0c1b,
+ 0x4621, 0x0c79,
+ 0x4721, 0x0cd7,
+ 0x4821, 0x0d35,
+ 0x4921, 0x0d93,
+ 0x4a21, 0x0df1,
+ 0x4b21, 0x0e4f,
+ 0x4c21, 0x0ead,
+ 0x4d21, 0x0f0b,
+ 0x4e21, 0x0f69,
+ 0x4f21, 0x0fc7,
+ 0x5021, 0x0ffa,
+ 0x5121, 0x1058,
+ 0x5221, 0x10b6,
+ 0x5321, 0x1114,
+ 0x5421, 0x1172,
+ 0x5521, 0x11d0,
+ 0x5621, 0x122e,
+ 0x5721, 0x128c,
+ 0x5821, 0x12ea,
+ 0x5921, 0x1348,
+ 0x5a21, 0x13a6,
+ 0x5b21, 0x1404,
+ 0x5c21, 0x1462,
+ 0x5d21, 0x14c0,
+ 0x5e21, 0x151e,
+ 0x5f21, 0x157c,
+ 0x6021, 0x15da,
+ 0x6121, 0x1638,
+ 0x6221, 0x1696,
+ 0x6321, 0x16f4,
+ 0x6421, 0x1752,
+ 0x6521, 0x17b0,
+ 0x6621, 0x180e,
+ 0x6721, 0x186c,
+ 0x6821, 0x18ca,
+ 0x6921, 0x1928,
+ 0x6a21, 0x1986,
+ 0x6b21, 0x19e4,
+ 0x6c21, 0x1a42,
+ 0x6d21, 0x1aa0,
+ 0x6e21, 0x1afe,
+ 0x6f21, 0x1b5c,
+ 0x7021, 0x1bba,
+ 0x7121, 0x1c18,
+ 0x7221, 0x1c76,
+ 0x7321, 0x1cd4,
+ 0x7421, 0x1d32,
+ 0x7425, 0x205c,
+ 0x2122, 0x1ecf,
+ 0x2131, 0x1ed1,
+ 0x213c, 0x1ed3,
+ 0x2141, 0x1ed6,
+ 0x214a, 0x1edb,
+ 0x2161, 0x1eed,
+ 0x2421, 0x1eee,
+ 0x2423, 0x1eef,
+ 0x2425, 0x1ef0,
+ 0x2427, 0x1ef1,
+ 0x2429, 0x1ef2,
+ 0x2443, 0x1ef3,
+ 0x2463, 0x1ef4,
+ 0x2465, 0x1ef5,
+ 0x2467, 0x1ef6,
+ 0x246e, 0x1ef7,
+ 0x2521, 0x1ef8,
+ 0x2523, 0x1ef9,
+ 0x2525, 0x1efa,
+ 0x2527, 0x1efb,
+ 0x2529, 0x1efc,
+ 0x2543, 0x1efd,
+ 0x2563, 0x1efe,
+ 0x2565, 0x1eff,
+ 0x2567, 0x1f00,
+ 0x256e, 0x1f01,
+ 0x2575, 0x1f02,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12VEnc16 = {
+ 1,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12VMap2, 147
+};
+
+static Gushort japan12WPSymbolMap2[4] = {
+ 0x0000, 0x0000,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12WPSymbolEnc16 = {
+ 0,
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x1f78, 0x1f7a, 0x1fff, 0x2004, 0x1f7d, 0x1f7e, 0x1f7f,
+ 0x1f80, 0x1f81, 0x1f82, 0x1f83, 0x1f84, 0x1f85, 0x1f86, 0x1f87,
+ 0x1f88, 0x1f89, 0x1f8a, 0x1f8b, 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f,
+ 0x1f90, 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa0, 0x1fa1, 0x1fa2,
+ 0x1fa3, 0x1fa4, 0x1fa5, 0x1ffa, 0x1f54, 0x1f55, 0x1ffb, 0x1f56,
+ 0x1f57, 0x1ffc, 0x1f65, 0x1f58, 0x1f59, 0x1f5a, 0x1ffd, 0x1ffe,
+ 0x2000, 0x2001, 0x1edb, 0x1edc, 0x1ed6, 0x2002, 0x1f63, 0x1f5b,
+ 0x1f5c, 0x1f5d, 0x2003, 0x1fb0, 0x1fb1, 0x1fb2, 0x1fb3, 0x1fb4,
+ 0x1fb5, 0x1fb6, 0x1fb7, 0x1fb8, 0x1fb9, 0x1fba, 0x1fbb, 0x1fbc,
+ 0x1fbd, 0x1fbe, 0x1fbf, 0x1fc0, 0x1fc1, 0x1fc2, 0x1fc3, 0x1fc4,
+ 0x1fc5, 0x1fc6, 0x1fc7, 0x1fc8, 0x1fc9, 0x2005, 0x2006, 0x2007,
+ 0x2008, 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x1fd7, 0x0000,
+ 0x0000, 0x200e, 0x200f, 0x2010, 0x2011, 0x2012, 0x2013, 0x2014,
+ 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b, 0x201c,
+ 0x201d, 0x201e, 0x1f79, 0x201f, 0x2020, 0x2021, 0x2022, 0x2023,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12WPSymbolMap2, 2
+};
+
+static Gushort japan12AdobeJapan12VMap2[74] = {
+ 0x0000, 0x0000,
+ 0x0000, 0x0000,
+ 0x0100, 0x0100,
+ 0x0200, 0x0200,
+ 0x0300, 0x0300,
+ 0x0400, 0x0400,
+ 0x0500, 0x0500,
+ 0x0600, 0x0600,
+ 0x0700, 0x0700,
+ 0x0800, 0x0800,
+ 0x0900, 0x0900,
+ 0x0a00, 0x0a00,
+ 0x0b00, 0x0b00,
+ 0x0c00, 0x0c00,
+ 0x0d00, 0x0d00,
+ 0x0e00, 0x0e00,
+ 0x0f00, 0x0f00,
+ 0x1000, 0x1000,
+ 0x1100, 0x1100,
+ 0x1200, 0x1200,
+ 0x1300, 0x1300,
+ 0x1400, 0x1400,
+ 0x1500, 0x1500,
+ 0x1600, 0x1600,
+ 0x1700, 0x1700,
+ 0x1800, 0x1800,
+ 0x1900, 0x1900,
+ 0x1a00, 0x1a00,
+ 0x1b00, 0x1b00,
+ 0x1c00, 0x1c00,
+ 0x1d00, 0x1d00,
+ 0x1e00, 0x1e00,
+ 0x1f00, 0x1f00,
+ 0x2000, 0x2000,
+ 0x2100, 0x2100,
+ 0x2200, 0x2200,
+ 0xffff, 0x0000
+};
+
+static GfxFontEncoding16 japan12AdobeJapan12VEnc16 = {
+ 1,
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
+ japan12AdobeJapan12VMap2, 37
+};
+
+static struct {
+ char *name;
+ GfxFontEncoding16 *enc;
+} gfxJapan12Tab[] = {
+ { "78-EUC-H", &japan1278EUCHEnc16 },
+ { "78-EUC-V", &japan1278EUCVEnc16 },
+ { "78-H", &japan1278HEnc16 },
+ { "78-RKSJ-H", &japan1278RKSJHEnc16 },
+ { "78-RKSJ-V", &japan1278RKSJVEnc16 },
+ { "78-V", &japan1278VEnc16 },
+ { "78ms-RKSJ-H", &japan1278msRKSJHEnc16 },
+ { "78ms-RKSJ-V", &japan1278msRKSJVEnc16 },
+ { "83pv-RKSJ-H", &japan1283pvRKSJHEnc16 },
+ { "90ms-RKSJ-H", &japan1290msRKSJHEnc16 },
+ { "90ms-RKSJ-V", &japan1290msRKSJVEnc16 },
+ { "90msp-RKSJ-H", &japan1290mspRKSJHEnc16 },
+ { "90msp-RKSJ-V", &japan1290mspRKSJVEnc16 },
+ { "90pv-RKSJ-H", &japan1290pvRKSJHEnc16 },
+ { "90pv-RKSJ-V", &japan1290pvRKSJVEnc16 },
+ { "Add-H", &japan12AddHEnc16 },
+ { "Add-RKSJ-H", &japan12AddRKSJHEnc16 },
+ { "Add-RKSJ-V", &japan12AddRKSJVEnc16 },
+ { "Add-V", &japan12AddVEnc16 },
+ { "Adobe-Japan1-0", &japan12AdobeJapan10Enc16 },
+ { "Adobe-Japan1-1", &japan12AdobeJapan11Enc16 },
+ { "Adobe-Japan1-2", &japan12AdobeJapan12Enc16 },
+ { "EUC-H", &japan12EUCHEnc16 },
+ { "EUC-V", &japan12EUCVEnc16 },
+ { "Ext-H", &japan12ExtHEnc16 },
+ { "Ext-RKSJ-H", &japan12ExtRKSJHEnc16 },
+ { "Ext-RKSJ-V", &japan12ExtRKSJVEnc16 },
+ { "Ext-V", &japan12ExtVEnc16 },
+ { "H", &japan12HEnc16 },
+ { "Hankaku", &japan12HankakuEnc16 },
+ { "Hiragana", &japan12HiraganaEnc16 },
+ { "Katakana", &japan12KatakanaEnc16 },
+ { "NWP-H", &japan12NWPHEnc16 },
+ { "NWP-V", &japan12NWPVEnc16 },
+ { "RKSJ-H", &japan12RKSJHEnc16 },
+ { "RKSJ-V", &japan12RKSJVEnc16 },
+ { "Roman", &japan12RomanEnc16 },
+ { "UniJIS-UCS2-H", &japan12UniJISUCS2HEnc16 },
+ { "UniJIS-UCS2-V", &japan12UniJISUCS2VEnc16 },
+ { "V", &japan12VEnc16 },
+ { "WP-Symbol", &japan12WPSymbolEnc16 },
+ { "Identity-H", &japan12AdobeJapan12Enc16 },
+ { "Identity-V", &japan12AdobeJapan12VEnc16 },
+ { NULL, NULL }
+};
+
+#endif
diff --git a/pdftops/Japan12ToRKSJ.h b/pdftops/Japan12ToRKSJ.h
new file mode 100644
index 000000000..5ca62c30c
--- /dev/null
+++ b/pdftops/Japan12ToRKSJ.h
@@ -0,0 +1,1038 @@
+static Gushort japan12ToRKSJ[8286] = {
+ 0x0020, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026,
+ 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e,
+ 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036,
+ 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e,
+ 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046,
+ 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e,
+ 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056,
+ 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e,
+ 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066,
+ 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e,
+ 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076,
+ 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
+ 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030,
+ 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038,
+ 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
+ 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+ 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+ 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+ 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060,
+ 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068,
+ 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070,
+ 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+ 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x00a0, 0x00a1,
+ 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9,
+ 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, 0x00b1,
+ 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9,
+ 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, 0x00c0, 0x00c1,
+ 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9,
+ 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1,
+ 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9,
+ 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x8140, 0x8141, 0x8142, 0x8143, 0x8144, 0x8145, 0x8146,
+ 0x8147, 0x8148, 0x8149, 0x814a, 0x814b, 0x814c, 0x814d, 0x814e,
+ 0x814f, 0x8150, 0x8151, 0x8152, 0x8153, 0x8154, 0x8155, 0x8156,
+ 0x8157, 0x8158, 0x8159, 0x815a, 0x815b, 0x815c, 0x815d, 0x815e,
+ 0x815f, 0x8160, 0x8161, 0x8162, 0x8163, 0x8164, 0x8165, 0x8166,
+ 0x8167, 0x8168, 0x8169, 0x816a, 0x816b, 0x816c, 0x816d, 0x816e,
+ 0x816f, 0x8170, 0x8171, 0x8172, 0x8173, 0x8174, 0x8175, 0x8176,
+ 0x8177, 0x8178, 0x8179, 0x817a, 0x817b, 0x817c, 0x817d, 0x817e,
+ 0x8180, 0x8181, 0x8182, 0x8183, 0x8184, 0x8185, 0x8186, 0x8187,
+ 0x8188, 0x8189, 0x818a, 0x818b, 0x818c, 0x818d, 0x818e, 0x818f,
+ 0x8190, 0x8191, 0x8192, 0x8193, 0x8194, 0x8195, 0x8196, 0x8197,
+ 0x8198, 0x8199, 0x819a, 0x819b, 0x819c, 0x819d, 0x819e, 0x819f,
+ 0x81a0, 0x81a1, 0x81a2, 0x81a3, 0x81a4, 0x81a5, 0x81a6, 0x81a7,
+ 0x81a8, 0x81a9, 0x81aa, 0x81ab, 0x81ac, 0x81b8, 0x81b9, 0x81ba,
+ 0x81bb, 0x81bc, 0x81bd, 0x81be, 0x81bf, 0x81c8, 0x81c9, 0x81ca,
+ 0x81cb, 0x81cc, 0x81cd, 0x81ce, 0x81da, 0x81db, 0x81dc, 0x81dd,
+ 0x81de, 0x81df, 0x81e0, 0x81e1, 0x81e2, 0x81e3, 0x81e4, 0x81e5,
+ 0x81e6, 0x81e7, 0x81e8, 0x81f0, 0x81f1, 0x81f2, 0x81f3, 0x81f4,
+ 0x81f5, 0x81f6, 0x81f7, 0x81fc, 0x824f, 0x8250, 0x8251, 0x8252,
+ 0x8253, 0x8254, 0x8255, 0x8256, 0x8257, 0x8258, 0x8260, 0x8261,
+ 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, 0x8267, 0x8268, 0x8269,
+ 0x826a, 0x826b, 0x826c, 0x826d, 0x826e, 0x826f, 0x8270, 0x8271,
+ 0x8272, 0x8273, 0x8274, 0x8275, 0x8276, 0x8277, 0x8278, 0x8279,
+ 0x8281, 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, 0x8288,
+ 0x8289, 0x828a, 0x828b, 0x828c, 0x828d, 0x828e, 0x828f, 0x8290,
+ 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, 0x8298,
+ 0x8299, 0x829a, 0x829f, 0x82a0, 0x82a1, 0x82a2, 0x82a3, 0x82a4,
+ 0x82a5, 0x82a6, 0x82a7, 0x82a8, 0x82a9, 0x82aa, 0x82ab, 0x82ac,
+ 0x82ad, 0x82ae, 0x82af, 0x82b0, 0x82b1, 0x82b2, 0x82b3, 0x82b4,
+ 0x82b5, 0x82b6, 0x82b7, 0x82b8, 0x82b9, 0x82ba, 0x82bb, 0x82bc,
+ 0x82bd, 0x82be, 0x82bf, 0x82c0, 0x82c1, 0x82c2, 0x82c3, 0x82c4,
+ 0x82c5, 0x82c6, 0x82c7, 0x82c8, 0x82c9, 0x82ca, 0x82cb, 0x82cc,
+ 0x82cd, 0x82ce, 0x82cf, 0x82d0, 0x82d1, 0x82d2, 0x82d3, 0x82d4,
+ 0x82d5, 0x82d6, 0x82d7, 0x82d8, 0x82d9, 0x82da, 0x82db, 0x82dc,
+ 0x82dd, 0x82de, 0x82df, 0x82e0, 0x82e1, 0x82e2, 0x82e3, 0x82e4,
+ 0x82e5, 0x82e6, 0x82e7, 0x82e8, 0x82e9, 0x82ea, 0x82eb, 0x82ec,
+ 0x82ed, 0x82ee, 0x82ef, 0x82f0, 0x82f1, 0x8340, 0x8341, 0x8342,
+ 0x8343, 0x8344, 0x8345, 0x8346, 0x8347, 0x8348, 0x8349, 0x834a,
+ 0x834b, 0x834c, 0x834d, 0x834e, 0x834f, 0x8350, 0x8351, 0x8352,
+ 0x8353, 0x8354, 0x8355, 0x8356, 0x8357, 0x8358, 0x8359, 0x835a,
+ 0x835b, 0x835c, 0x835d, 0x835e, 0x835f, 0x8360, 0x8361, 0x8362,
+ 0x8363, 0x8364, 0x8365, 0x8366, 0x8367, 0x8368, 0x8369, 0x836a,
+ 0x836b, 0x836c, 0x836d, 0x836e, 0x836f, 0x8370, 0x8371, 0x8372,
+ 0x8373, 0x8374, 0x8375, 0x8376, 0x8377, 0x8378, 0x8379, 0x837a,
+ 0x837b, 0x837c, 0x837d, 0x837e, 0x8380, 0x8381, 0x8382, 0x8383,
+ 0x8384, 0x8385, 0x8386, 0x8387, 0x8388, 0x8389, 0x838a, 0x838b,
+ 0x838c, 0x838d, 0x838e, 0x838f, 0x8390, 0x8391, 0x8392, 0x8393,
+ 0x8394, 0x8395, 0x8396, 0x839f, 0x83a0, 0x83a1, 0x83a2, 0x83a3,
+ 0x83a4, 0x83a5, 0x83a6, 0x83a7, 0x83a8, 0x83a9, 0x83aa, 0x83ab,
+ 0x83ac, 0x83ad, 0x83ae, 0x83af, 0x83b0, 0x83b1, 0x83b2, 0x83b3,
+ 0x83b4, 0x83b5, 0x83b6, 0x83bf, 0x83c0, 0x83c1, 0x83c2, 0x83c3,
+ 0x83c4, 0x83c5, 0x83c6, 0x83c7, 0x83c8, 0x83c9, 0x83ca, 0x83cb,
+ 0x83cc, 0x83cd, 0x83ce, 0x83cf, 0x83d0, 0x83d1, 0x83d2, 0x83d3,
+ 0x83d4, 0x83d5, 0x83d6, 0x8440, 0x8441, 0x8442, 0x8443, 0x8444,
+ 0x8445, 0x8446, 0x8447, 0x8448, 0x8449, 0x844a, 0x844b, 0x844c,
+ 0x844d, 0x844e, 0x844f, 0x8450, 0x8451, 0x8452, 0x8453, 0x8454,
+ 0x8455, 0x8456, 0x8457, 0x8458, 0x8459, 0x845a, 0x845b, 0x845c,
+ 0x845d, 0x845e, 0x845f, 0x8460, 0x8470, 0x8471, 0x8472, 0x8473,
+ 0x8474, 0x8475, 0x8476, 0x8477, 0x8478, 0x8479, 0x847a, 0x847b,
+ 0x847c, 0x847d, 0x847e, 0x8480, 0x8481, 0x8482, 0x8483, 0x8484,
+ 0x8485, 0x8486, 0x8487, 0x8488, 0x8489, 0x848a, 0x848b, 0x848c,
+ 0x848d, 0x848e, 0x848f, 0x8490, 0x8491, 0x889f, 0x88a0, 0x88a1,
+ 0x88a2, 0x88a3, 0x88a4, 0x88a5, 0x88a6, 0x88a7, 0x88a8, 0x88a9,
+ 0x88aa, 0x88ab, 0x88ac, 0x88ad, 0x88ae, 0x88af, 0x88b0, 0x88b1,
+ 0x88b2, 0x88b3, 0x88b4, 0x88b5, 0x88b6, 0x88b7, 0x88b8, 0x88b9,
+ 0x88ba, 0x88bb, 0x88bc, 0x88bd, 0x88be, 0x88bf, 0x88c0, 0x88c1,
+ 0x88c2, 0x88c3, 0x88c4, 0x88c5, 0x88c6, 0x88c7, 0x88c8, 0x88c9,
+ 0x88ca, 0x88cb, 0x88cc, 0x88cd, 0x88ce, 0x88cf, 0x88d0, 0x88d1,
+ 0x88d2, 0x88d3, 0x88d4, 0x88d5, 0x88d6, 0x88d7, 0x88d8, 0x88d9,
+ 0x88da, 0x88db, 0x88dc, 0x88dd, 0x88de, 0x88df, 0x88e0, 0x88e1,
+ 0x88e2, 0x88e3, 0x88e4, 0x88e5, 0x88e6, 0x88e7, 0x88e8, 0x88e9,
+ 0x88ea, 0x88eb, 0x88ec, 0x88ed, 0x88ee, 0x88ef, 0x88f0, 0x88f1,
+ 0x88f2, 0x88f3, 0x88f4, 0x88f5, 0x88f6, 0x88f7, 0x88f8, 0x88f9,
+ 0x88fa, 0x88fb, 0x88fc, 0x8940, 0x8941, 0x8942, 0x8943, 0x8944,
+ 0x8945, 0x8946, 0x8947, 0x8948, 0x8949, 0x894a, 0x894b, 0x894c,
+ 0x894d, 0x894e, 0x894f, 0x8950, 0x8951, 0x8952, 0x8953, 0x8954,
+ 0x8955, 0x8956, 0x8957, 0x8958, 0x8959, 0x895a, 0x895b, 0x895c,
+ 0x895d, 0x895e, 0x895f, 0x8960, 0x8961, 0x8962, 0x8963, 0x8964,
+ 0x8965, 0x8966, 0x8967, 0x8968, 0x8969, 0x896a, 0x896b, 0x896c,
+ 0x896d, 0x896e, 0x896f, 0x8970, 0x8971, 0x8972, 0x8973, 0x8974,
+ 0x8975, 0x8976, 0x8977, 0x8978, 0x8979, 0x897a, 0x897b, 0x897c,
+ 0x897d, 0x897e, 0x8980, 0x8981, 0x8982, 0x8983, 0x8984, 0x8985,
+ 0x8986, 0x8987, 0x8988, 0x8989, 0x898a, 0x898b, 0x898c, 0x898d,
+ 0x898e, 0x898f, 0x8990, 0x8991, 0x8992, 0x8993, 0x8994, 0x8995,
+ 0x8996, 0x8997, 0x8998, 0x8999, 0x899a, 0x899b, 0x899c, 0x899d,
+ 0x899e, 0x899f, 0x89a0, 0x89a1, 0x89a2, 0x89a3, 0x89a4, 0x89a5,
+ 0x89a6, 0x89a7, 0x89a8, 0x89a9, 0x89aa, 0x89ab, 0x89ac, 0x89ad,
+ 0x89ae, 0x89af, 0x89b0, 0x89b1, 0x89b2, 0x89b3, 0x89b4, 0x89b5,
+ 0x89b6, 0x89b7, 0x89b8, 0x89b9, 0x89ba, 0x89bb, 0x89bc, 0x89bd,
+ 0x89be, 0x89bf, 0x89c0, 0x89c1, 0x89c2, 0x89c3, 0x89c4, 0x89c5,
+ 0x89c6, 0x89c7, 0x89c8, 0x89c9, 0x89ca, 0x89cb, 0x89cc, 0x89cd,
+ 0x89ce, 0x89cf, 0x89d0, 0x89d1, 0x89d2, 0x89d3, 0x89d4, 0x89d5,
+ 0x89d6, 0x89d7, 0x89d8, 0x89d9, 0x89da, 0x89db, 0x89dc, 0x89dd,
+ 0x89de, 0x89df, 0x89e0, 0x89e1, 0x89e2, 0x89e3, 0x89e4, 0x89e5,
+ 0x89e6, 0x89e7, 0x89e8, 0x89e9, 0x89ea, 0x89eb, 0x89ec, 0x89ed,
+ 0x89ee, 0x89ef, 0x89f0, 0x89f1, 0x89f2, 0x89f3, 0x89f4, 0x89f5,
+ 0x89f6, 0x89f7, 0x89f8, 0x89f9, 0x89fa, 0x89fb, 0x89fc, 0x8a40,
+ 0x8a41, 0x8a42, 0x8a43, 0x8a44, 0x8a45, 0x8a46, 0x8a47, 0x8a48,
+ 0x8a49, 0x8a4a, 0x8a4b, 0x8a4c, 0x8a4d, 0x8a4e, 0x8a4f, 0x8a50,
+ 0x8a51, 0x8a52, 0x8a53, 0x8a54, 0x8a55, 0x8a56, 0x8a57, 0x8a58,
+ 0x8a59, 0x8a5a, 0x8a5b, 0x8a5c, 0x8a5d, 0x8a5e, 0x8a5f, 0x8a60,
+ 0x8a61, 0x8a62, 0x8a63, 0x8a64, 0x8a65, 0x8a66, 0x8a67, 0x8a68,
+ 0x8a69, 0x8a6a, 0x8a6b, 0x8a6c, 0x8a6d, 0x8a6e, 0x8a6f, 0x8a70,
+ 0x8a71, 0x8a72, 0x8a73, 0x8a74, 0x8a75, 0x8a76, 0x8a77, 0x8a78,
+ 0x8a79, 0x8a7a, 0x8a7b, 0x8a7c, 0x8a7d, 0x8a7e, 0x8a80, 0x8a81,
+ 0x8a82, 0x8a83, 0x8a84, 0x8a85, 0x8a86, 0x8a87, 0x8a88, 0x8a89,
+ 0x8a8a, 0x8a8b, 0x8a8c, 0x8a8d, 0x8a8e, 0x8a8f, 0x8a90, 0x8a91,
+ 0x8a92, 0x8a93, 0x8a94, 0x8a95, 0x8a96, 0x8a97, 0x8a98, 0x8a99,
+ 0x8a9a, 0x8a9b, 0x8a9c, 0x8a9d, 0x8a9e, 0x8a9f, 0x8aa0, 0x8aa1,
+ 0x8aa2, 0x8aa3, 0x8aa4, 0x8aa5, 0x8aa6, 0x8aa7, 0x8aa8, 0x8aa9,
+ 0x8aaa, 0x8aab, 0x8aac, 0x8aad, 0x8aae, 0x8aaf, 0x8ab0, 0x8ab1,
+ 0x8ab2, 0x8ab3, 0x8ab4, 0x8ab5, 0x8ab6, 0x8ab7, 0x8ab8, 0x8ab9,
+ 0x8aba, 0x8abb, 0x8abc, 0x8abd, 0x8abe, 0x8abf, 0x8ac0, 0x8ac1,
+ 0x8ac2, 0x8ac3, 0x8ac4, 0x8ac5, 0x8ac6, 0x8ac7, 0x8ac8, 0x8ac9,
+ 0x8aca, 0x8acb, 0x8acc, 0x8acd, 0x8ace, 0x8acf, 0x8ad0, 0x8ad1,
+ 0x8ad2, 0x8ad3, 0x8ad4, 0x8ad5, 0x8ad6, 0x8ad7, 0x8ad8, 0x8ad9,
+ 0x8ada, 0x8adb, 0x8adc, 0x8add, 0x8ade, 0x8adf, 0x8ae0, 0x8ae1,
+ 0x8ae2, 0x8ae3, 0x8ae4, 0x8ae5, 0x8ae6, 0x8ae7, 0x8ae8, 0x8ae9,
+ 0x8aea, 0x8aeb, 0x8aec, 0x8aed, 0x8aee, 0x8aef, 0x8af0, 0x8af1,
+ 0x8af2, 0x8af3, 0x8af4, 0x8af5, 0x8af6, 0x8af7, 0x8af8, 0x8af9,
+ 0x8afa, 0x8afb, 0x8afc, 0x8b40, 0x8b41, 0x8b42, 0x8b43, 0x8b44,
+ 0x8b45, 0x8b46, 0x8b47, 0x8b48, 0x8b49, 0x8b4a, 0x8b4b, 0x8b4c,
+ 0x8b4d, 0x8b4e, 0x8b4f, 0x8b50, 0x8b51, 0x8b52, 0x8b53, 0x8b54,
+ 0x8b55, 0x8b56, 0x8b57, 0x8b58, 0x8b59, 0x8b5a, 0x8b5b, 0x8b5c,
+ 0x8b5d, 0x8b5e, 0x8b5f, 0x8b60, 0x8b61, 0x8b62, 0x8b63, 0x8b64,
+ 0x8b65, 0x8b66, 0x8b67, 0x8b68, 0x8b69, 0x8b6a, 0x8b6b, 0x8b6c,
+ 0x8b6d, 0x8b6e, 0x8b6f, 0x8b70, 0x8b71, 0x8b72, 0x8b73, 0x8b74,
+ 0x8b75, 0x8b76, 0x8b77, 0x8b78, 0x8b79, 0x8b7a, 0x8b7b, 0x8b7c,
+ 0x8b7d, 0x8b7e, 0x8b80, 0x8b81, 0x8b82, 0x8b83, 0x8b84, 0x8b85,
+ 0x8b86, 0x8b87, 0x8b88, 0x8b89, 0x8b8a, 0x8b8b, 0x8b8c, 0x8b8d,
+ 0x8b8e, 0x8b8f, 0x8b90, 0x8b91, 0x8b92, 0x8b93, 0x8b94, 0x8b95,
+ 0x8b96, 0x8b97, 0x8b98, 0x8b99, 0x8b9a, 0x8b9b, 0x8b9c, 0x8b9d,
+ 0x8b9e, 0x8b9f, 0x8ba0, 0x8ba1, 0x8ba2, 0x8ba3, 0x8ba4, 0x8ba5,
+ 0x8ba6, 0x8ba7, 0x8ba8, 0x8ba9, 0x8baa, 0x8bab, 0x8bac, 0x8bad,
+ 0x8bae, 0x8baf, 0x8bb0, 0x8bb1, 0x8bb2, 0x8bb3, 0x8bb4, 0x8bb5,
+ 0x8bb6, 0x8bb7, 0x8bb8, 0x8bb9, 0x8bba, 0x8bbb, 0x8bbc, 0x8bbd,
+ 0x8bbe, 0x8bbf, 0x8bc0, 0x8bc1, 0x8bc2, 0x8bc3, 0x8bc4, 0x8bc5,
+ 0x8bc6, 0x8bc7, 0x8bc8, 0x8bc9, 0x8bca, 0x8bcb, 0x8bcc, 0x8bcd,
+ 0x8bce, 0x8bcf, 0x8bd0, 0x8bd1, 0x8bd2, 0x8bd3, 0x8bd4, 0x8bd5,
+ 0x8bd6, 0x8bd7, 0x8bd8, 0x8bd9, 0x8bda, 0x8bdb, 0x8bdc, 0x8bdd,
+ 0x8bde, 0x8bdf, 0x8be0, 0x8be1, 0x8be2, 0x8be3, 0x8be4, 0x8be5,
+ 0x8be6, 0x8be7, 0x8be8, 0x8be9, 0x8bea, 0x8beb, 0x8bec, 0x8bed,
+ 0x8bee, 0x8bef, 0x8bf0, 0x8bf1, 0x8bf2, 0x8bf3, 0x8bf4, 0x8bf5,
+ 0x8bf6, 0x8bf7, 0x8bf8, 0x8bf9, 0x8bfa, 0x8bfb, 0x8bfc, 0x8c40,
+ 0x8c41, 0x8c42, 0x8c43, 0x8c44, 0x8c45, 0x8c46, 0x8c47, 0x8c48,
+ 0x8c49, 0x8c4a, 0x8c4b, 0x8c4c, 0x8c4d, 0x8c4e, 0x8c4f, 0x8c50,
+ 0x8c51, 0x8c52, 0x8c53, 0x8c54, 0x8c55, 0x8c56, 0x8c57, 0x8c58,
+ 0x8c59, 0x8c5a, 0x8c5b, 0x8c5c, 0x8c5d, 0x8c5e, 0x8c5f, 0x8c60,
+ 0x8c61, 0x8c62, 0x8c63, 0x8c64, 0x8c65, 0x8c66, 0x8c67, 0x8c68,
+ 0x8c69, 0x8c6a, 0x8c6b, 0x8c6c, 0x8c6d, 0x8c6e, 0x8c6f, 0x8c70,
+ 0x8c71, 0x8c72, 0x8c73, 0x8c74, 0x8c75, 0x8c76, 0x8c77, 0x8c78,
+ 0x8c79, 0x8c7a, 0x8c7b, 0x8c7c, 0x8c7d, 0x8c7e, 0x8c80, 0x8c81,
+ 0x8c82, 0x8c83, 0x8c84, 0x8c85, 0x8c86, 0x8c87, 0x8c88, 0x8c89,
+ 0x8c8a, 0x8c8b, 0x8c8c, 0x8c8d, 0x8c8e, 0x8c8f, 0x8c90, 0x8c91,
+ 0x8c92, 0x8c93, 0x8c94, 0x8c95, 0x8c96, 0x8c97, 0x8c98, 0x8c99,
+ 0x8c9a, 0x8c9b, 0x8c9c, 0x8c9d, 0x8c9e, 0x8c9f, 0x8ca0, 0x8ca1,
+ 0x8ca2, 0x8ca3, 0x8ca4, 0x8ca5, 0x8ca6, 0x8ca7, 0x8ca8, 0x8ca9,
+ 0x8caa, 0x8cab, 0x8cac, 0x8cad, 0x8cae, 0x8caf, 0x8cb0, 0x8cb1,
+ 0x8cb2, 0x8cb3, 0x8cb4, 0x8cb5, 0x8cb6, 0x8cb7, 0x8cb8, 0x8cb9,
+ 0x8cba, 0x8cbb, 0x8cbc, 0x8cbd, 0x8cbe, 0x8cbf, 0x8cc0, 0x8cc1,
+ 0x8cc2, 0x8cc3, 0x8cc4, 0x8cc5, 0x8cc6, 0x8cc7, 0x8cc8, 0x8cc9,
+ 0x8cca, 0x8ccb, 0x8ccc, 0x8ccd, 0x8cce, 0x8ccf, 0x8cd0, 0x8cd1,
+ 0x8cd2, 0x8cd3, 0x8cd4, 0x8cd5, 0x8cd6, 0x8cd7, 0x8cd8, 0x8cd9,
+ 0x8cda, 0x8cdb, 0x8cdc, 0x8cdd, 0x8cde, 0x8cdf, 0x8ce0, 0x8ce1,
+ 0x8ce2, 0x8ce3, 0x8ce4, 0x8ce5, 0x8ce6, 0x8ce7, 0x8ce8, 0x8ce9,
+ 0x8cea, 0x8ceb, 0x8cec, 0x8ced, 0x8cee, 0x8cef, 0x8cf0, 0x8cf1,
+ 0x8cf2, 0x8cf3, 0x8cf4, 0x8cf5, 0x8cf6, 0x8cf7, 0x8cf8, 0x8cf9,
+ 0x8cfa, 0x8cfb, 0x8cfc, 0x8d40, 0x8d41, 0x8d42, 0x8d43, 0x8d44,
+ 0x8d45, 0x8d46, 0x8d47, 0x8d48, 0x8d49, 0x8d4a, 0x8d4b, 0x8d4c,
+ 0x8d4d, 0x8d4e, 0x8d4f, 0x8d50, 0x8d51, 0x8d52, 0x8d53, 0x8d54,
+ 0x8d55, 0x8d56, 0x8d57, 0x8d58, 0x8d59, 0x8d5a, 0x8d5b, 0x8d5c,
+ 0x8d5d, 0x8d5e, 0x8d5f, 0x8d60, 0x8d61, 0x8d62, 0x8d63, 0x8d64,
+ 0x8d65, 0x8d66, 0x8d67, 0x8d68, 0x8d69, 0x8d6a, 0x8d6b, 0x8d6c,
+ 0x8d6d, 0x8d6e, 0x8d6f, 0x8d70, 0x8d71, 0x8d72, 0x8d73, 0x8d74,
+ 0x8d75, 0x8d76, 0x8d77, 0x8d78, 0x8d79, 0x8d7a, 0x8d7b, 0x8d7c,
+ 0x8d7d, 0x8d7e, 0x8d80, 0x8d81, 0x8d82, 0x8d83, 0x8d84, 0x8d85,
+ 0x8d86, 0x8d87, 0x8d88, 0x8d89, 0x8d8a, 0x8d8b, 0x8d8c, 0x8d8d,
+ 0x8d8e, 0x8d8f, 0x8d90, 0x8d91, 0x8d92, 0x8d93, 0x8d94, 0x8d95,
+ 0x8d96, 0x8d97, 0x8d98, 0x8d99, 0x8d9a, 0x8d9b, 0x8d9c, 0x8d9d,
+ 0x8d9e, 0x8d9f, 0x8da0, 0x8da1, 0x8da2, 0x8da3, 0x8da4, 0x8da5,
+ 0x8da6, 0x8da7, 0x8da8, 0x8da9, 0x8daa, 0x8dab, 0x8dac, 0x8dad,
+ 0x8dae, 0x8daf, 0x8db0, 0x8db1, 0x8db2, 0x8db3, 0x8db4, 0x8db5,
+ 0x8db6, 0x8db7, 0x8db8, 0x8db9, 0x8dba, 0x8dbb, 0x8dbc, 0x8dbd,
+ 0x8dbe, 0x8dbf, 0x8dc0, 0x8dc1, 0x8dc2, 0x8dc3, 0x8dc4, 0x8dc5,
+ 0x8dc6, 0x8dc7, 0x8dc8, 0x8dc9, 0x8dca, 0x8dcb, 0x8dcc, 0x8dcd,
+ 0x8dce, 0x8dcf, 0x8dd0, 0x8dd1, 0x8dd2, 0x8dd3, 0x8dd4, 0x8dd5,
+ 0x8dd6, 0x8dd7, 0x8dd8, 0x8dd9, 0x8dda, 0x8ddb, 0x8ddc, 0x8ddd,
+ 0x8dde, 0x8ddf, 0x8de0, 0x8de1, 0x8de2, 0x8de3, 0x8de4, 0x8de5,
+ 0x8de6, 0x8de7, 0x8de8, 0x8de9, 0x8dea, 0x8deb, 0x8dec, 0x8ded,
+ 0x8dee, 0x8def, 0x8df0, 0x8df1, 0x8df2, 0x8df3, 0x8df4, 0x8df5,
+ 0x8df6, 0x8df7, 0x8df8, 0x8df9, 0x8dfa, 0x8dfb, 0x8dfc, 0x8e40,
+ 0x8e41, 0x8e42, 0x8e43, 0x8e44, 0x8e45, 0x8e46, 0x8e47, 0x8e48,
+ 0x8e49, 0x8e4a, 0x8e4b, 0x8e4c, 0x8e4d, 0x8e4e, 0x8e4f, 0x8e50,
+ 0x8e51, 0x8e52, 0x8e53, 0x8e54, 0x8e55, 0x8e56, 0x8e57, 0x8e58,
+ 0x8e59, 0x8e5a, 0x8e5b, 0x8e5c, 0x8e5d, 0x8e5e, 0x8e5f, 0x8e60,
+ 0x8e61, 0x8e62, 0x8e63, 0x8e64, 0x8e65, 0x8e66, 0x8e67, 0x8e68,
+ 0x8e69, 0x8e6a, 0x8e6b, 0x8e6c, 0x8e6d, 0x8e6e, 0x8e6f, 0x8e70,
+ 0x8e71, 0x8e72, 0x8e73, 0x8e74, 0x8e75, 0x8e76, 0x8e77, 0x8e78,
+ 0x8e79, 0x8e7a, 0x8e7b, 0x8e7c, 0x8e7d, 0x8e7e, 0x8e80, 0x8e81,
+ 0x8e82, 0x8e83, 0x8e84, 0x8e85, 0x8e86, 0x8e87, 0x8e88, 0x8e89,
+ 0x8e8a, 0x8e8b, 0x8e8c, 0x8e8d, 0x8e8e, 0x8e8f, 0x8e90, 0x8e91,
+ 0x8e92, 0x8e93, 0x8e94, 0x8e95, 0x8e96, 0x8e97, 0x8e98, 0x8e99,
+ 0x8e9a, 0x8e9b, 0x8e9c, 0x8e9d, 0x8e9e, 0x8e9f, 0x8ea0, 0x8ea1,
+ 0x8ea2, 0x8ea3, 0x8ea4, 0x8ea5, 0x8ea6, 0x8ea7, 0x8ea8, 0x8ea9,
+ 0x8eaa, 0x8eab, 0x8eac, 0x8ead, 0x8eae, 0x8eaf, 0x8eb0, 0x8eb1,
+ 0x8eb2, 0x8eb3, 0x8eb4, 0x8eb5, 0x8eb6, 0x8eb7, 0x8eb8, 0x8eb9,
+ 0x8eba, 0x8ebb, 0x8ebc, 0x8ebd, 0x8ebe, 0x8ebf, 0x8ec0, 0x8ec1,
+ 0x8ec2, 0x8ec3, 0x8ec4, 0x8ec5, 0x8ec6, 0x8ec7, 0x8ec8, 0x8ec9,
+ 0x8eca, 0x8ecb, 0x8ecc, 0x8ecd, 0x8ece, 0x8ecf, 0x8ed0, 0x8ed1,
+ 0x8ed2, 0x8ed3, 0x8ed4, 0x8ed5, 0x8ed6, 0x8ed7, 0x8ed8, 0x8ed9,
+ 0x8eda, 0x8edb, 0x8edc, 0x8edd, 0x8ede, 0x8edf, 0x8ee0, 0x8ee1,
+ 0x8ee2, 0x8ee3, 0x8ee4, 0x8ee5, 0x8ee6, 0x8ee7, 0x8ee8, 0x8ee9,
+ 0x8eea, 0x8eeb, 0x8eec, 0x8eed, 0x8eee, 0x8eef, 0x8ef0, 0x8ef1,
+ 0x8ef2, 0x8ef3, 0x8ef4, 0x8ef5, 0x8ef6, 0x8ef7, 0x8ef8, 0x8ef9,
+ 0x8efa, 0x8efb, 0x8efc, 0x8f40, 0x8f41, 0x8f42, 0x8f43, 0x8f44,
+ 0x8f45, 0x8f46, 0x8f47, 0x8f48, 0x8f49, 0x8f4a, 0x8f4b, 0x8f4c,
+ 0x8f4d, 0x8f4e, 0x8f4f, 0x8f50, 0x8f51, 0x8f52, 0x8f53, 0x8f54,
+ 0x8f55, 0x8f56, 0x8f57, 0x8f58, 0x8f59, 0x8f5a, 0x8f5b, 0x8f5c,
+ 0x8f5d, 0x8f5e, 0x8f5f, 0x8f60, 0x8f61, 0x8f62, 0x8f63, 0x8f64,
+ 0x8f65, 0x8f66, 0x8f67, 0x8f68, 0x8f69, 0x8f6a, 0x8f6b, 0x8f6c,
+ 0x8f6d, 0x8f6e, 0x8f6f, 0x8f70, 0x8f71, 0x8f72, 0x8f73, 0x8f74,
+ 0x8f75, 0x8f76, 0x8f77, 0x8f78, 0x8f79, 0x8f7a, 0x8f7b, 0x8f7c,
+ 0x8f7d, 0x8f7e, 0x8f80, 0x8f81, 0x8f82, 0x8f83, 0x8f84, 0x8f85,
+ 0x8f86, 0x8f87, 0x8f88, 0x8f89, 0x8f8a, 0x8f8b, 0x8f8c, 0x8f8d,
+ 0x8f8e, 0x8f8f, 0x8f90, 0x8f91, 0x8f92, 0x8f93, 0x8f94, 0x8f95,
+ 0x8f96, 0x8f97, 0x8f98, 0x8f99, 0x8f9a, 0x8f9b, 0x8f9c, 0x8f9d,
+ 0x8f9e, 0x8f9f, 0x8fa0, 0x8fa1, 0x8fa2, 0x8fa3, 0x8fa4, 0x8fa5,
+ 0x8fa6, 0x8fa7, 0x8fa8, 0x8fa9, 0x8faa, 0x8fab, 0x8fac, 0x8fad,
+ 0x8fae, 0x8faf, 0x8fb0, 0x8fb1, 0x8fb2, 0x8fb3, 0x8fb4, 0x8fb5,
+ 0x8fb6, 0x8fb7, 0x8fb8, 0x8fb9, 0x8fba, 0x8fbb, 0x8fbc, 0x8fbd,
+ 0x8fbe, 0x8fbf, 0x8fc0, 0x8fc1, 0x8fc2, 0x8fc3, 0x8fc4, 0x8fc5,
+ 0x8fc6, 0x8fc7, 0x8fc8, 0x8fc9, 0x8fca, 0x8fcb, 0x8fcc, 0x8fcd,
+ 0x8fce, 0x8fcf, 0x8fd0, 0x8fd1, 0x8fd2, 0x8fd3, 0x8fd4, 0x8fd5,
+ 0x8fd6, 0x8fd7, 0x8fd8, 0x8fd9, 0x8fda, 0x8fdb, 0x8fdc, 0x8fdd,
+ 0x8fde, 0x8fdf, 0x8fe0, 0x8fe1, 0x8fe2, 0x8fe3, 0x8fe4, 0x8fe5,
+ 0x8fe6, 0x8fe7, 0x8fe8, 0x8fe9, 0x8fea, 0x8feb, 0x8fec, 0x8fed,
+ 0x8fee, 0x8fef, 0x8ff0, 0x8ff1, 0x8ff2, 0x8ff3, 0x8ff4, 0x8ff5,
+ 0x8ff6, 0x8ff7, 0x8ff8, 0x8ff9, 0x8ffa, 0x8ffb, 0x8ffc, 0x9040,
+ 0x9041, 0x9042, 0x9043, 0x9044, 0x9045, 0x9046, 0x9047, 0x9048,
+ 0x9049, 0x904a, 0x904b, 0x904c, 0x904d, 0x904e, 0x904f, 0x9050,
+ 0x9051, 0x9052, 0x9053, 0x9054, 0x9055, 0x9056, 0x9057, 0x9058,
+ 0x9059, 0x905a, 0x905b, 0x905c, 0x905d, 0x905e, 0x905f, 0x9060,
+ 0x9061, 0x9062, 0x9063, 0x9064, 0x9065, 0x9066, 0x9067, 0x9068,
+ 0x9069, 0x906a, 0x906b, 0x906c, 0x906d, 0x906e, 0x906f, 0x9070,
+ 0x9071, 0x9072, 0x9073, 0x9074, 0x9075, 0x9076, 0x9077, 0x9078,
+ 0x9079, 0x907a, 0x907b, 0x907c, 0x907d, 0x907e, 0x9080, 0x9081,
+ 0x9082, 0x9083, 0x9084, 0x9085, 0x9086, 0x9087, 0x9088, 0x9089,
+ 0x908a, 0x908b, 0x908c, 0x908d, 0x908e, 0x908f, 0x9090, 0x9091,
+ 0x9092, 0x9093, 0x9094, 0x9095, 0x9096, 0x9097, 0x9098, 0x9099,
+ 0x909a, 0x909b, 0x909c, 0x909d, 0x909e, 0x909f, 0x90a0, 0x90a1,
+ 0x90a2, 0x90a3, 0x90a4, 0x90a5, 0x90a6, 0x90a7, 0x90a8, 0x90a9,
+ 0x90aa, 0x90ab, 0x90ac, 0x90ad, 0x90ae, 0x90af, 0x90b0, 0x90b1,
+ 0x90b2, 0x90b3, 0x90b4, 0x90b5, 0x90b6, 0x90b7, 0x90b8, 0x90b9,
+ 0x90ba, 0x90bb, 0x90bc, 0x90bd, 0x90be, 0x90bf, 0x90c0, 0x90c1,
+ 0x90c2, 0x90c3, 0x90c4, 0x90c5, 0x90c6, 0x90c7, 0x90c8, 0x90c9,
+ 0x90ca, 0x90cb, 0x90cc, 0x90cd, 0x90ce, 0x90cf, 0x90d0, 0x90d1,
+ 0x90d2, 0x90d3, 0x90d4, 0x90d5, 0x90d6, 0x90d7, 0x90d8, 0x90d9,
+ 0x90da, 0x90db, 0x90dc, 0x90dd, 0x90de, 0x90df, 0x90e0, 0x90e1,
+ 0x90e2, 0x90e3, 0x90e4, 0x90e5, 0x90e6, 0x90e7, 0x90e8, 0x90e9,
+ 0x90ea, 0x90eb, 0x90ec, 0x90ed, 0x90ee, 0x90ef, 0x90f0, 0x90f1,
+ 0x90f2, 0x90f3, 0x90f4, 0x90f5, 0x90f6, 0x90f7, 0x90f8, 0x90f9,
+ 0x90fa, 0x90fb, 0x90fc, 0x9140, 0x9141, 0x9142, 0x9143, 0x9144,
+ 0x9145, 0x9146, 0x9147, 0x9148, 0x9149, 0x914a, 0x914b, 0x914c,
+ 0x914d, 0x914e, 0x914f, 0x9150, 0x9151, 0x9152, 0x9153, 0x9154,
+ 0x9155, 0x9156, 0x9157, 0x9158, 0x9159, 0x915a, 0x915b, 0x915c,
+ 0x915d, 0x915e, 0x915f, 0x9160, 0x9161, 0x9162, 0x9163, 0x9164,
+ 0x9165, 0x9166, 0x9167, 0x9168, 0x9169, 0x916a, 0x916b, 0x916c,
+ 0x916d, 0x916e, 0x916f, 0x9170, 0x9171, 0x9172, 0x9173, 0x9174,
+ 0x9175, 0x9176, 0x9177, 0x9178, 0x9179, 0x917a, 0x917b, 0x917c,
+ 0x917d, 0x917e, 0x9180, 0x9181, 0x9182, 0x9183, 0x9184, 0x9185,
+ 0x9186, 0x9187, 0x9188, 0x9189, 0x918a, 0x918b, 0x918c, 0x918d,
+ 0x918e, 0x918f, 0x9190, 0x9191, 0x9192, 0x9193, 0x9194, 0x9195,
+ 0x9196, 0x9197, 0x9198, 0x9199, 0x919a, 0x919b, 0x919c, 0x919d,
+ 0x919e, 0x919f, 0x91a0, 0x91a1, 0x91a2, 0x91a3, 0x91a4, 0x91a5,
+ 0x91a6, 0x91a7, 0x91a8, 0x91a9, 0x91aa, 0x91ab, 0x91ac, 0x91ad,
+ 0x91ae, 0x91af, 0x91b0, 0x91b1, 0x91b2, 0x91b3, 0x91b4, 0x91b5,
+ 0x91b6, 0x91b7, 0x91b8, 0x91b9, 0x91ba, 0x91bb, 0x91bc, 0x91bd,
+ 0x91be, 0x91bf, 0x91c0, 0x91c1, 0x91c2, 0x91c3, 0x91c4, 0x91c5,
+ 0x91c6, 0x91c7, 0x91c8, 0x91c9, 0x91ca, 0x91cb, 0x91cc, 0x91cd,
+ 0x91ce, 0x91cf, 0x91d0, 0x91d1, 0x91d2, 0x91d3, 0x91d4, 0x91d5,
+ 0x91d6, 0x91d7, 0x91d8, 0x91d9, 0x91da, 0x91db, 0x91dc, 0x91dd,
+ 0x91de, 0x91df, 0x91e0, 0x91e1, 0x91e2, 0x91e3, 0x91e4, 0x91e5,
+ 0x91e6, 0x91e7, 0x91e8, 0x91e9, 0x91ea, 0x91eb, 0x91ec, 0x91ed,
+ 0x91ee, 0x91ef, 0x91f0, 0x91f1, 0x91f2, 0x91f3, 0x91f4, 0x91f5,
+ 0x91f6, 0x91f7, 0x91f8, 0x91f9, 0x91fa, 0x91fb, 0x91fc, 0x9240,
+ 0x9241, 0x9242, 0x9243, 0x9244, 0x9245, 0x9246, 0x9247, 0x9248,
+ 0x9249, 0x924a, 0x924b, 0x924c, 0x924d, 0x924e, 0x924f, 0x9250,
+ 0x9251, 0x9252, 0x9253, 0x9254, 0x9255, 0x9256, 0x9257, 0x9258,
+ 0x9259, 0x925a, 0x925b, 0x925c, 0x925d, 0x925e, 0x925f, 0x9260,
+ 0x9261, 0x9262, 0x9263, 0x9264, 0x9265, 0x9266, 0x9267, 0x9268,
+ 0x9269, 0x926a, 0x926b, 0x926c, 0x926d, 0x926e, 0x926f, 0x9270,
+ 0x9271, 0x9272, 0x9273, 0x9274, 0x9275, 0x9276, 0x9277, 0x9278,
+ 0x9279, 0x927a, 0x927b, 0x927c, 0x927d, 0x927e, 0x9280, 0x9281,
+ 0x9282, 0x9283, 0x9284, 0x9285, 0x9286, 0x9287, 0x9288, 0x9289,
+ 0x928a, 0x928b, 0x928c, 0x928d, 0x928e, 0x928f, 0x9290, 0x9291,
+ 0x9292, 0x9293, 0x9294, 0x9295, 0x9296, 0x9297, 0x9298, 0x9299,
+ 0x929a, 0x929b, 0x929c, 0x929d, 0x929e, 0x929f, 0x92a0, 0x92a1,
+ 0x92a2, 0x92a3, 0x92a4, 0x92a5, 0x92a6, 0x92a7, 0x92a8, 0x92a9,
+ 0x92aa, 0x92ab, 0x92ac, 0x92ad, 0x92ae, 0x92af, 0x92b0, 0x92b1,
+ 0x92b2, 0x92b3, 0x92b4, 0x92b5, 0x92b6, 0x92b7, 0x92b8, 0x92b9,
+ 0x92ba, 0x92bb, 0x92bc, 0x92bd, 0x92be, 0x92bf, 0x92c0, 0x92c1,
+ 0x92c2, 0x92c3, 0x92c4, 0x92c5, 0x92c6, 0x92c7, 0x92c8, 0x92c9,
+ 0x92ca, 0x92cb, 0x92cc, 0x92cd, 0x92ce, 0x92cf, 0x92d0, 0x92d1,
+ 0x92d2, 0x92d3, 0x92d4, 0x92d5, 0x92d6, 0x92d7, 0x92d8, 0x92d9,
+ 0x92da, 0x92db, 0x92dc, 0x92dd, 0x92de, 0x92df, 0x92e0, 0x92e1,
+ 0x92e2, 0x92e3, 0x92e4, 0x92e5, 0x92e6, 0x92e7, 0x92e8, 0x92e9,
+ 0x92ea, 0x92eb, 0x92ec, 0x92ed, 0x92ee, 0x92ef, 0x92f0, 0x92f1,
+ 0x92f2, 0x92f3, 0x92f4, 0x92f5, 0x92f6, 0x92f7, 0x92f8, 0x92f9,
+ 0x92fa, 0x92fb, 0x92fc, 0x9340, 0x9341, 0x9342, 0x9343, 0x9344,
+ 0x9345, 0x9346, 0x9347, 0x9348, 0x9349, 0x934a, 0x934b, 0x934c,
+ 0x934d, 0x934e, 0x934f, 0x9350, 0x9351, 0x9352, 0x9353, 0x9354,
+ 0x9355, 0x9356, 0x9357, 0x9358, 0x9359, 0x935a, 0x935b, 0x935c,
+ 0x935d, 0x935e, 0x935f, 0x9360, 0x9361, 0x9362, 0x9363, 0x9364,
+ 0x9365, 0x9366, 0x9367, 0x9368, 0x9369, 0x936a, 0x936b, 0x936c,
+ 0x936d, 0x936e, 0x936f, 0x9370, 0x9371, 0x9372, 0x9373, 0x9374,
+ 0x9375, 0x9376, 0x9377, 0x9378, 0x9379, 0x937a, 0x937b, 0x937c,
+ 0x937d, 0x937e, 0x9380, 0x9381, 0x9382, 0x9383, 0x9384, 0x9385,
+ 0x9386, 0x9387, 0x9388, 0x9389, 0x938a, 0x938b, 0x938c, 0x938d,
+ 0x938e, 0x938f, 0x9390, 0x9391, 0x9392, 0x9393, 0x9394, 0x9395,
+ 0x9396, 0x9397, 0x9398, 0x9399, 0x939a, 0x939b, 0x939c, 0x939d,
+ 0x939e, 0x939f, 0x93a0, 0x93a1, 0x93a2, 0x93a3, 0x93a4, 0x93a5,
+ 0x93a6, 0x93a7, 0x93a8, 0x93a9, 0x93aa, 0x93ab, 0x93ac, 0x93ad,
+ 0x93ae, 0x93af, 0x93b0, 0x93b1, 0x93b2, 0x93b3, 0x93b4, 0x93b5,
+ 0x93b6, 0x93b7, 0x93b8, 0x93b9, 0x93ba, 0x93bb, 0x93bc, 0x93bd,
+ 0x93be, 0x93bf, 0x93c0, 0x93c1, 0x93c2, 0x93c3, 0x93c4, 0x93c5,
+ 0x93c6, 0x93c7, 0x93c8, 0x93c9, 0x93ca, 0x93cb, 0x93cc, 0x93cd,
+ 0x93ce, 0x93cf, 0x93d0, 0x93d1, 0x93d2, 0x93d3, 0x93d4, 0x93d5,
+ 0x93d6, 0x93d7, 0x93d8, 0x93d9, 0x93da, 0x93db, 0x93dc, 0x93dd,
+ 0x93de, 0x93df, 0x93e0, 0x93e1, 0x93e2, 0x93e3, 0x93e4, 0x93e5,
+ 0x93e6, 0x93e7, 0x93e8, 0x93e9, 0x93ea, 0x93eb, 0x93ec, 0x93ed,
+ 0x93ee, 0x93ef, 0x93f0, 0x93f1, 0x93f2, 0x93f3, 0x93f4, 0x93f5,
+ 0x93f6, 0x93f7, 0x93f8, 0x93f9, 0x93fa, 0x93fb, 0x93fc, 0x9440,
+ 0x9441, 0x9442, 0x9443, 0x9444, 0x9445, 0x9446, 0x9447, 0x9448,
+ 0x9449, 0x944a, 0x944b, 0x944c, 0x944d, 0x944e, 0x944f, 0x9450,
+ 0x9451, 0x9452, 0x9453, 0x9454, 0x9455, 0x9456, 0x9457, 0x9458,
+ 0x9459, 0x945a, 0x945b, 0x945c, 0x945d, 0x945e, 0x945f, 0x9460,
+ 0x9461, 0x9462, 0x9463, 0x9464, 0x9465, 0x9466, 0x9467, 0x9468,
+ 0x9469, 0x946a, 0x946b, 0x946c, 0x946d, 0x946e, 0x946f, 0x9470,
+ 0x9471, 0x9472, 0x9473, 0x9474, 0x9475, 0x9476, 0x9477, 0x9478,
+ 0x9479, 0x947a, 0x947b, 0x947c, 0x947d, 0x947e, 0x9480, 0x9481,
+ 0x9482, 0x9483, 0x9484, 0x9485, 0x9486, 0x9487, 0x9488, 0x9489,
+ 0x948a, 0x948b, 0x948c, 0x948d, 0x948e, 0x948f, 0x9490, 0x9491,
+ 0x9492, 0x9493, 0x9494, 0x9495, 0x9496, 0x9497, 0x9498, 0x9499,
+ 0x949a, 0x949b, 0x949c, 0x949d, 0x949e, 0x949f, 0x94a0, 0x94a1,
+ 0x94a2, 0x94a3, 0x94a4, 0x94a5, 0x94a6, 0x94a7, 0x94a8, 0x94a9,
+ 0x94aa, 0x94ab, 0x94ac, 0x94ad, 0x94ae, 0x94af, 0x94b0, 0x94b1,
+ 0x94b2, 0x94b3, 0x94b4, 0x94b5, 0x94b6, 0x94b7, 0x94b8, 0x94b9,
+ 0x94ba, 0x94bb, 0x94bc, 0x94bd, 0x94be, 0x94bf, 0x94c0, 0x94c1,
+ 0x94c2, 0x94c3, 0x94c4, 0x94c5, 0x94c6, 0x94c7, 0x94c8, 0x94c9,
+ 0x94ca, 0x94cb, 0x94cc, 0x94cd, 0x94ce, 0x94cf, 0x94d0, 0x94d1,
+ 0x94d2, 0x94d3, 0x94d4, 0x94d5, 0x94d6, 0x94d7, 0x94d8, 0x94d9,
+ 0x94da, 0x94db, 0x94dc, 0x94dd, 0x94de, 0x94df, 0x94e0, 0x94e1,
+ 0x94e2, 0x94e3, 0x94e4, 0x94e5, 0x94e6, 0x94e7, 0x94e8, 0x94e9,
+ 0x94ea, 0x94eb, 0x94ec, 0x94ed, 0x94ee, 0x94ef, 0x94f0, 0x94f1,
+ 0x94f2, 0x94f3, 0x94f4, 0x94f5, 0x94f6, 0x94f7, 0x94f8, 0x94f9,
+ 0x94fa, 0x94fb, 0x94fc, 0x9540, 0x9541, 0x9542, 0x9543, 0x9544,
+ 0x9545, 0x9546, 0x9547, 0x9548, 0x9549, 0x954a, 0x954b, 0x954c,
+ 0x954d, 0x954e, 0x954f, 0x9550, 0x9551, 0x9552, 0x9553, 0x9554,
+ 0x9555, 0x9556, 0x9557, 0x9558, 0x9559, 0x955a, 0x955b, 0x955c,
+ 0x955d, 0x955e, 0x955f, 0x9560, 0x9561, 0x9562, 0x9563, 0x9564,
+ 0x9565, 0x9566, 0x9567, 0x9568, 0x9569, 0x956a, 0x956b, 0x956c,
+ 0x956d, 0x956e, 0x956f, 0x9570, 0x9571, 0x9572, 0x9573, 0x9574,
+ 0x9575, 0x9576, 0x9577, 0x9578, 0x9579, 0x957a, 0x957b, 0x957c,
+ 0x957d, 0x957e, 0x9580, 0x9581, 0x9582, 0x9583, 0x9584, 0x9585,
+ 0x9586, 0x9587, 0x9588, 0x9589, 0x958a, 0x958b, 0x958c, 0x958d,
+ 0x958e, 0x958f, 0x9590, 0x9591, 0x9592, 0x9593, 0x9594, 0x9595,
+ 0x9596, 0x9597, 0x9598, 0x9599, 0x959a, 0x959b, 0x959c, 0x959d,
+ 0x959e, 0x959f, 0x95a0, 0x95a1, 0x95a2, 0x95a3, 0x95a4, 0x95a5,
+ 0x95a6, 0x95a7, 0x95a8, 0x95a9, 0x95aa, 0x95ab, 0x95ac, 0x95ad,
+ 0x95ae, 0x95af, 0x95b0, 0x95b1, 0x95b2, 0x95b3, 0x95b4, 0x95b5,
+ 0x95b6, 0x95b7, 0x95b8, 0x95b9, 0x95ba, 0x95bb, 0x95bc, 0x95bd,
+ 0x95be, 0x95bf, 0x95c0, 0x95c1, 0x95c2, 0x95c3, 0x95c4, 0x95c5,
+ 0x95c6, 0x95c7, 0x95c8, 0x95c9, 0x95ca, 0x95cb, 0x95cc, 0x95cd,
+ 0x95ce, 0x95cf, 0x95d0, 0x95d1, 0x95d2, 0x95d3, 0x95d4, 0x95d5,
+ 0x95d6, 0x95d7, 0x95d8, 0x95d9, 0x95da, 0x95db, 0x95dc, 0x95dd,
+ 0x95de, 0x95df, 0x95e0, 0x95e1, 0x95e2, 0x95e3, 0x95e4, 0x95e5,
+ 0x95e6, 0x95e7, 0x95e8, 0x95e9, 0x95ea, 0x95eb, 0x95ec, 0x95ed,
+ 0x95ee, 0x95ef, 0x95f0, 0x95f1, 0x95f2, 0x95f3, 0x95f4, 0x95f5,
+ 0x95f6, 0x95f7, 0x95f8, 0x95f9, 0x95fa, 0x95fb, 0x95fc, 0x9640,
+ 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9646, 0x9647, 0x9648,
+ 0x9649, 0x964a, 0x964b, 0x964c, 0x964d, 0x964e, 0x964f, 0x9650,
+ 0x9651, 0x9652, 0x9653, 0x9654, 0x9655, 0x9656, 0x9657, 0x9658,
+ 0x9659, 0x965a, 0x965b, 0x965c, 0x965d, 0x965e, 0x965f, 0x9660,
+ 0x9661, 0x9662, 0x9663, 0x9664, 0x9665, 0x9666, 0x9667, 0x9668,
+ 0x9669, 0x966a, 0x966b, 0x966c, 0x966d, 0x966e, 0x966f, 0x9670,
+ 0x9671, 0x9672, 0x9673, 0x9674, 0x9675, 0x9676, 0x9677, 0x9678,
+ 0x9679, 0x967a, 0x967b, 0x967c, 0x967d, 0x967e, 0x9680, 0x9681,
+ 0x9682, 0x9683, 0x9684, 0x9685, 0x9686, 0x9687, 0x9688, 0x9689,
+ 0x968a, 0x968b, 0x968c, 0x968d, 0x968e, 0x968f, 0x9690, 0x9691,
+ 0x9692, 0x9693, 0x9694, 0x9695, 0x9696, 0x9697, 0x9698, 0x9699,
+ 0x969a, 0x969b, 0x969c, 0x969d, 0x969e, 0x969f, 0x96a0, 0x96a1,
+ 0x96a2, 0x96a3, 0x96a4, 0x96a5, 0x96a6, 0x96a7, 0x96a8, 0x96a9,
+ 0x96aa, 0x96ab, 0x96ac, 0x96ad, 0x96ae, 0x96af, 0x96b0, 0x96b1,
+ 0x96b2, 0x96b3, 0x96b4, 0x96b5, 0x96b6, 0x96b7, 0x96b8, 0x96b9,
+ 0x96ba, 0x96bb, 0x96bc, 0x96bd, 0x96be, 0x96bf, 0x96c0, 0x96c1,
+ 0x96c2, 0x96c3, 0x96c4, 0x96c5, 0x96c6, 0x96c7, 0x96c8, 0x96c9,
+ 0x96ca, 0x96cb, 0x96cc, 0x96cd, 0x96ce, 0x96cf, 0x96d0, 0x96d1,
+ 0x96d2, 0x96d3, 0x96d4, 0x96d5, 0x96d6, 0x96d7, 0x96d8, 0x96d9,
+ 0x96da, 0x96db, 0x96dc, 0x96dd, 0x96de, 0x96df, 0x96e0, 0x96e1,
+ 0x96e2, 0x96e3, 0x96e4, 0x96e5, 0x96e6, 0x96e7, 0x96e8, 0x96e9,
+ 0x96ea, 0x96eb, 0x96ec, 0x96ed, 0x96ee, 0x96ef, 0x96f0, 0x96f1,
+ 0x96f2, 0x96f3, 0x96f4, 0x96f5, 0x96f6, 0x96f7, 0x96f8, 0x96f9,
+ 0x96fa, 0x96fb, 0x96fc, 0x9740, 0x9741, 0x9742, 0x9743, 0x9744,
+ 0x9745, 0x9746, 0x9747, 0x9748, 0x9749, 0x974a, 0x974b, 0x974c,
+ 0x974d, 0x974e, 0x974f, 0x9750, 0x9751, 0x9752, 0x9753, 0x9754,
+ 0x9755, 0x9756, 0x9757, 0x9758, 0x9759, 0x975a, 0x975b, 0x975c,
+ 0x975d, 0x975e, 0x975f, 0x9760, 0x9761, 0x9762, 0x9763, 0x9764,
+ 0x9765, 0x9766, 0x9767, 0x9768, 0x9769, 0x976a, 0x976b, 0x976c,
+ 0x976d, 0x976e, 0x976f, 0x9770, 0x9771, 0x9772, 0x9773, 0x9774,
+ 0x9775, 0x9776, 0x9777, 0x9778, 0x9779, 0x977a, 0x977b, 0x977c,
+ 0x977d, 0x977e, 0x9780, 0x9781, 0x9782, 0x9783, 0x9784, 0x9785,
+ 0x9786, 0x9787, 0x9788, 0x9789, 0x978a, 0x978b, 0x978c, 0x978d,
+ 0x978e, 0x978f, 0x9790, 0x9791, 0x9792, 0x9793, 0x9794, 0x9795,
+ 0x9796, 0x9797, 0x9798, 0x9799, 0x979a, 0x979b, 0x979c, 0x979d,
+ 0x979e, 0x979f, 0x97a0, 0x97a1, 0x97a2, 0x97a3, 0x97a4, 0x97a5,
+ 0x97a6, 0x97a7, 0x97a8, 0x97a9, 0x97aa, 0x97ab, 0x97ac, 0x97ad,
+ 0x97ae, 0x97af, 0x97b0, 0x97b1, 0x97b2, 0x97b3, 0x97b4, 0x97b5,
+ 0x97b6, 0x97b7, 0x97b8, 0x97b9, 0x97ba, 0x97bb, 0x97bc, 0x97bd,
+ 0x97be, 0x97bf, 0x97c0, 0x97c1, 0x97c2, 0x97c3, 0x97c4, 0x97c5,
+ 0x97c6, 0x97c7, 0x97c8, 0x97c9, 0x97ca, 0x97cb, 0x97cc, 0x97cd,
+ 0x97ce, 0x97cf, 0x97d0, 0x97d1, 0x97d2, 0x97d3, 0x97d4, 0x97d5,
+ 0x97d6, 0x97d7, 0x97d8, 0x97d9, 0x97da, 0x97db, 0x97dc, 0x97dd,
+ 0x97de, 0x97df, 0x97e0, 0x97e1, 0x97e2, 0x97e3, 0x97e4, 0x97e5,
+ 0x97e6, 0x97e7, 0x97e8, 0x97e9, 0x97ea, 0x97eb, 0x97ec, 0x97ed,
+ 0x97ee, 0x97ef, 0x97f0, 0x97f1, 0x97f2, 0x97f3, 0x97f4, 0x97f5,
+ 0x97f6, 0x97f7, 0x97f8, 0x97f9, 0x97fa, 0x97fb, 0x97fc, 0x9840,
+ 0x9841, 0x9842, 0x9843, 0x9844, 0x9845, 0x9846, 0x9847, 0x9848,
+ 0x9849, 0x984a, 0x984b, 0x984c, 0x984d, 0x984e, 0x984f, 0x9850,
+ 0x9851, 0x9852, 0x9853, 0x9854, 0x9855, 0x9856, 0x9857, 0x9858,
+ 0x9859, 0x985a, 0x985b, 0x985c, 0x985d, 0x985e, 0x985f, 0x9860,
+ 0x9861, 0x9862, 0x9863, 0x9864, 0x9865, 0x9866, 0x9867, 0x9868,
+ 0x9869, 0x986a, 0x986b, 0x986c, 0x986d, 0x986e, 0x986f, 0x9870,
+ 0x9871, 0x9872, 0x989f, 0x98a0, 0x98a1, 0x98a2, 0x98a3, 0x98a4,
+ 0x98a5, 0x98a6, 0x98a7, 0x98a8, 0x98a9, 0x98aa, 0x98ab, 0x98ac,
+ 0x98ad, 0x98ae, 0x98af, 0x98b0, 0x98b1, 0x98b2, 0x98b3, 0x98b4,
+ 0x98b5, 0x98b6, 0x98b7, 0x98b8, 0x98b9, 0x98ba, 0x98bb, 0x98bc,
+ 0x98bd, 0x98be, 0x98bf, 0x98c0, 0x98c1, 0x98c2, 0x98c3, 0x98c4,
+ 0x98c5, 0x98c6, 0x98c7, 0x98c8, 0x98c9, 0x98ca, 0x98cb, 0x98cc,
+ 0x98cd, 0x98ce, 0x98cf, 0x98d0, 0x98d1, 0x98d2, 0x98d3, 0x98d4,
+ 0x98d5, 0x98d6, 0x98d7, 0x98d8, 0x98d9, 0x98da, 0x98db, 0x98dc,
+ 0x98dd, 0x98de, 0x98df, 0x98e0, 0x98e1, 0x98e2, 0x98e3, 0x98e4,
+ 0x98e5, 0x98e6, 0x98e7, 0x98e8, 0x98e9, 0x98ea, 0x98eb, 0x98ec,
+ 0x98ed, 0x98ee, 0x98ef, 0x98f0, 0x98f1, 0x98f2, 0x98f3, 0x98f4,
+ 0x98f5, 0x98f6, 0x98f7, 0x98f8, 0x98f9, 0x98fa, 0x98fb, 0x98fc,
+ 0x9940, 0x9941, 0x9942, 0x9943, 0x9944, 0x9945, 0x9946, 0x9947,
+ 0x9948, 0x9949, 0x994a, 0x994b, 0x994c, 0x994d, 0x994e, 0x994f,
+ 0x9950, 0x9951, 0x9952, 0x9953, 0x9954, 0x9955, 0x9956, 0x9957,
+ 0x9958, 0x9959, 0x995a, 0x995b, 0x995c, 0x995d, 0x995e, 0x995f,
+ 0x9960, 0x9961, 0x9962, 0x9963, 0x9964, 0x9965, 0x9966, 0x9967,
+ 0x9968, 0x9969, 0x996a, 0x996b, 0x996c, 0x996d, 0x996e, 0x996f,
+ 0x9970, 0x9971, 0x9972, 0x9973, 0x9974, 0x9975, 0x9976, 0x9977,
+ 0x9978, 0x9979, 0x997a, 0x997b, 0x997c, 0x997d, 0x997e, 0x9980,
+ 0x9981, 0x9982, 0x9983, 0x9984, 0x9985, 0x9986, 0x9987, 0x9988,
+ 0x9989, 0x998a, 0x998b, 0x998c, 0x998d, 0x998e, 0x998f, 0x9990,
+ 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998,
+ 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x999e, 0x999f, 0x99a0,
+ 0x99a1, 0x99a2, 0x99a3, 0x99a4, 0x99a5, 0x99a6, 0x99a7, 0x99a8,
+ 0x99a9, 0x99aa, 0x99ab, 0x99ac, 0x99ad, 0x99ae, 0x99af, 0x99b0,
+ 0x99b1, 0x99b2, 0x99b3, 0x99b4, 0x99b5, 0x99b6, 0x99b7, 0x99b8,
+ 0x99b9, 0x99ba, 0x99bb, 0x99bc, 0x99bd, 0x99be, 0x99bf, 0x99c0,
+ 0x99c1, 0x99c2, 0x99c3, 0x99c4, 0x99c5, 0x99c6, 0x99c7, 0x99c8,
+ 0x99c9, 0x99ca, 0x99cb, 0x99cc, 0x99cd, 0x99ce, 0x99cf, 0x99d0,
+ 0x99d1, 0x99d2, 0x99d3, 0x99d4, 0x99d5, 0x99d6, 0x99d7, 0x99d8,
+ 0x99d9, 0x99da, 0x99db, 0x99dc, 0x99dd, 0x99de, 0x99df, 0x99e0,
+ 0x99e1, 0x99e2, 0x99e3, 0x99e4, 0x99e5, 0x99e6, 0x99e7, 0x99e8,
+ 0x99e9, 0x99ea, 0x99eb, 0x99ec, 0x99ed, 0x99ee, 0x99ef, 0x99f0,
+ 0x99f1, 0x99f2, 0x99f3, 0x99f4, 0x99f5, 0x99f6, 0x99f7, 0x99f8,
+ 0x99f9, 0x99fa, 0x99fb, 0x99fc, 0x9a40, 0x9a41, 0x9a42, 0x9a43,
+ 0x9a44, 0x9a45, 0x9a46, 0x9a47, 0x9a48, 0x9a49, 0x9a4a, 0x9a4b,
+ 0x9a4c, 0x9a4d, 0x9a4e, 0x9a4f, 0x9a50, 0x9a51, 0x9a52, 0x9a53,
+ 0x9a54, 0x9a55, 0x9a56, 0x9a57, 0x9a58, 0x9a59, 0x9a5a, 0x9a5b,
+ 0x9a5c, 0x9a5d, 0x9a5e, 0x9a5f, 0x9a60, 0x9a61, 0x9a62, 0x9a63,
+ 0x9a64, 0x9a65, 0x9a66, 0x9a67, 0x9a68, 0x9a69, 0x9a6a, 0x9a6b,
+ 0x9a6c, 0x9a6d, 0x9a6e, 0x9a6f, 0x9a70, 0x9a71, 0x9a72, 0x9a73,
+ 0x9a74, 0x9a75, 0x9a76, 0x9a77, 0x9a78, 0x9a79, 0x9a7a, 0x9a7b,
+ 0x9a7c, 0x9a7d, 0x9a7e, 0x9a80, 0x9a81, 0x9a82, 0x9a83, 0x9a84,
+ 0x9a85, 0x9a86, 0x9a87, 0x9a88, 0x9a89, 0x9a8a, 0x9a8b, 0x9a8c,
+ 0x9a8d, 0x9a8e, 0x9a8f, 0x9a90, 0x9a91, 0x9a92, 0x9a93, 0x9a94,
+ 0x9a95, 0x9a96, 0x9a97, 0x9a98, 0x9a99, 0x9a9a, 0x9a9b, 0x9a9c,
+ 0x9a9d, 0x9a9e, 0x9a9f, 0x9aa0, 0x9aa1, 0x9aa2, 0x9aa3, 0x9aa4,
+ 0x9aa5, 0x9aa6, 0x9aa7, 0x9aa8, 0x9aa9, 0x9aaa, 0x9aab, 0x9aac,
+ 0x9aad, 0x9aae, 0x9aaf, 0x9ab0, 0x9ab1, 0x9ab2, 0x9ab3, 0x9ab4,
+ 0x9ab5, 0x9ab6, 0x9ab7, 0x9ab8, 0x9ab9, 0x9aba, 0x9abb, 0x9abc,
+ 0x9abd, 0x9abe, 0x9abf, 0x9ac0, 0x9ac1, 0x9ac2, 0x9ac3, 0x9ac4,
+ 0x9ac5, 0x9ac6, 0x9ac7, 0x9ac8, 0x9ac9, 0x9aca, 0x9acb, 0x9acc,
+ 0x9acd, 0x9ace, 0x9acf, 0x9ad0, 0x9ad1, 0x9ad2, 0x9ad3, 0x9ad4,
+ 0x9ad5, 0x9ad6, 0x9ad7, 0x9ad8, 0x9ad9, 0x9ada, 0x9adb, 0x9adc,
+ 0x9add, 0x9ade, 0x9adf, 0x9ae0, 0x9ae1, 0x9ae2, 0x9ae3, 0x9ae4,
+ 0x9ae5, 0x9ae6, 0x9ae7, 0x9ae8, 0x9ae9, 0x9aea, 0x9aeb, 0x9aec,
+ 0x9aed, 0x9aee, 0x9aef, 0x9af0, 0x9af1, 0x9af2, 0x9af3, 0x9af4,
+ 0x9af5, 0x9af6, 0x9af7, 0x9af8, 0x9af9, 0x9afa, 0x9afb, 0x9afc,
+ 0x9b40, 0x9b41, 0x9b42, 0x9b43, 0x9b44, 0x9b45, 0x9b46, 0x9b47,
+ 0x9b48, 0x9b49, 0x9b4a, 0x9b4b, 0x9b4c, 0x9b4d, 0x9b4e, 0x9b4f,
+ 0x9b50, 0x9b51, 0x9b52, 0x9b53, 0x9b54, 0x9b55, 0x9b56, 0x9b57,
+ 0x9b58, 0x9b59, 0x9b5a, 0x9b5b, 0x9b5c, 0x9b5d, 0x9b5e, 0x9b5f,
+ 0x9b60, 0x9b61, 0x9b62, 0x9b63, 0x9b64, 0x9b65, 0x9b66, 0x9b67,
+ 0x9b68, 0x9b69, 0x9b6a, 0x9b6b, 0x9b6c, 0x9b6d, 0x9b6e, 0x9b6f,
+ 0x9b70, 0x9b71, 0x9b72, 0x9b73, 0x9b74, 0x9b75, 0x9b76, 0x9b77,
+ 0x9b78, 0x9b79, 0x9b7a, 0x9b7b, 0x9b7c, 0x9b7d, 0x9b7e, 0x9b80,
+ 0x9b81, 0x9b82, 0x9b83, 0x9b84, 0x9b85, 0x9b86, 0x9b87, 0x9b88,
+ 0x9b89, 0x9b8a, 0x9b8b, 0x9b8c, 0x9b8d, 0x9b8e, 0x9b8f, 0x9b90,
+ 0x9b91, 0x9b92, 0x9b93, 0x9b94, 0x9b95, 0x9b96, 0x9b97, 0x9b98,
+ 0x9b99, 0x9b9a, 0x9b9b, 0x9b9c, 0x9b9d, 0x9b9e, 0x9b9f, 0x9ba0,
+ 0x9ba1, 0x9ba2, 0x9ba3, 0x9ba4, 0x9ba5, 0x9ba6, 0x9ba7, 0x9ba8,
+ 0x9ba9, 0x9baa, 0x9bab, 0x9bac, 0x9bad, 0x9bae, 0x9baf, 0x9bb0,
+ 0x9bb1, 0x9bb2, 0x9bb3, 0x9bb4, 0x9bb5, 0x9bb6, 0x9bb7, 0x9bb8,
+ 0x9bb9, 0x9bba, 0x9bbb, 0x9bbc, 0x9bbd, 0x9bbe, 0x9bbf, 0x9bc0,
+ 0x9bc1, 0x9bc2, 0x9bc3, 0x9bc4, 0x9bc5, 0x9bc6, 0x9bc7, 0x9bc8,
+ 0x9bc9, 0x9bca, 0x9bcb, 0x9bcc, 0x9bcd, 0x9bce, 0x9bcf, 0x9bd0,
+ 0x9bd1, 0x9bd2, 0x9bd3, 0x9bd4, 0x9bd5, 0x9bd6, 0x9bd7, 0x9bd8,
+ 0x9bd9, 0x9bda, 0x9bdb, 0x9bdc, 0x9bdd, 0x9bde, 0x9bdf, 0x9be0,
+ 0x9be1, 0x9be2, 0x9be3, 0x9be4, 0x9be5, 0x9be6, 0x9be7, 0x9be8,
+ 0x9be9, 0x9bea, 0x9beb, 0x9bec, 0x9bed, 0x9bee, 0x9bef, 0x9bf0,
+ 0x9bf1, 0x9bf2, 0x9bf3, 0x9bf4, 0x9bf5, 0x9bf6, 0x9bf7, 0x9bf8,
+ 0x9bf9, 0x9bfa, 0x9bfb, 0x9bfc, 0x9c40, 0x9c41, 0x9c42, 0x9c43,
+ 0x9c44, 0x9c45, 0x9c46, 0x9c47, 0x9c48, 0x9c49, 0x9c4a, 0x9c4b,
+ 0x9c4c, 0x9c4d, 0x9c4e, 0x9c4f, 0x9c50, 0x9c51, 0x9c52, 0x9c53,
+ 0x9c54, 0x9c55, 0x9c56, 0x9c57, 0x9c58, 0x9c59, 0x9c5a, 0x9c5b,
+ 0x9c5c, 0x9c5d, 0x9c5e, 0x9c5f, 0x9c60, 0x9c61, 0x9c62, 0x9c63,
+ 0x9c64, 0x9c65, 0x9c66, 0x9c67, 0x9c68, 0x9c69, 0x9c6a, 0x9c6b,
+ 0x9c6c, 0x9c6d, 0x9c6e, 0x9c6f, 0x9c70, 0x9c71, 0x9c72, 0x9c73,
+ 0x9c74, 0x9c75, 0x9c76, 0x9c77, 0x9c78, 0x9c79, 0x9c7a, 0x9c7b,
+ 0x9c7c, 0x9c7d, 0x9c7e, 0x9c80, 0x9c81, 0x9c82, 0x9c83, 0x9c84,
+ 0x9c85, 0x9c86, 0x9c87, 0x9c88, 0x9c89, 0x9c8a, 0x9c8b, 0x9c8c,
+ 0x9c8d, 0x9c8e, 0x9c8f, 0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94,
+ 0x9c95, 0x9c96, 0x9c97, 0x9c98, 0x9c99, 0x9c9a, 0x9c9b, 0x9c9c,
+ 0x9c9d, 0x9c9e, 0x9c9f, 0x9ca0, 0x9ca1, 0x9ca2, 0x9ca3, 0x9ca4,
+ 0x9ca5, 0x9ca6, 0x9ca7, 0x9ca8, 0x9ca9, 0x9caa, 0x9cab, 0x9cac,
+ 0x9cad, 0x9cae, 0x9caf, 0x9cb0, 0x9cb1, 0x9cb2, 0x9cb3, 0x9cb4,
+ 0x9cb5, 0x9cb6, 0x9cb7, 0x9cb8, 0x9cb9, 0x9cba, 0x9cbb, 0x9cbc,
+ 0x9cbd, 0x9cbe, 0x9cbf, 0x9cc0, 0x9cc1, 0x9cc2, 0x9cc3, 0x9cc4,
+ 0x9cc5, 0x9cc6, 0x9cc7, 0x9cc8, 0x9cc9, 0x9cca, 0x9ccb, 0x9ccc,
+ 0x9ccd, 0x9cce, 0x9ccf, 0x9cd0, 0x9cd1, 0x9cd2, 0x9cd3, 0x9cd4,
+ 0x9cd5, 0x9cd6, 0x9cd7, 0x9cd8, 0x9cd9, 0x9cda, 0x9cdb, 0x9cdc,
+ 0x9cdd, 0x9cde, 0x9cdf, 0x9ce0, 0x9ce1, 0x9ce2, 0x9ce3, 0x9ce4,
+ 0x9ce5, 0x9ce6, 0x9ce7, 0x9ce8, 0x9ce9, 0x9cea, 0x9ceb, 0x9cec,
+ 0x9ced, 0x9cee, 0x9cef, 0x9cf0, 0x9cf1, 0x9cf2, 0x9cf3, 0x9cf4,
+ 0x9cf5, 0x9cf6, 0x9cf7, 0x9cf8, 0x9cf9, 0x9cfa, 0x9cfb, 0x9cfc,
+ 0x9d40, 0x9d41, 0x9d42, 0x9d43, 0x9d44, 0x9d45, 0x9d46, 0x9d47,
+ 0x9d48, 0x9d49, 0x9d4a, 0x9d4b, 0x9d4c, 0x9d4d, 0x9d4e, 0x9d4f,
+ 0x9d50, 0x9d51, 0x9d52, 0x9d53, 0x9d54, 0x9d55, 0x9d56, 0x9d57,
+ 0x9d58, 0x9d59, 0x9d5a, 0x9d5b, 0x9d5c, 0x9d5d, 0x9d5e, 0x9d5f,
+ 0x9d60, 0x9d61, 0x9d62, 0x9d63, 0x9d64, 0x9d65, 0x9d66, 0x9d67,
+ 0x9d68, 0x9d69, 0x9d6a, 0x9d6b, 0x9d6c, 0x9d6d, 0x9d6e, 0x9d6f,
+ 0x9d70, 0x9d71, 0x9d72, 0x9d73, 0x9d74, 0x9d75, 0x9d76, 0x9d77,
+ 0x9d78, 0x9d79, 0x9d7a, 0x9d7b, 0x9d7c, 0x9d7d, 0x9d7e, 0x9d80,
+ 0x9d81, 0x9d82, 0x9d83, 0x9d84, 0x9d85, 0x9d86, 0x9d87, 0x9d88,
+ 0x9d89, 0x9d8a, 0x9d8b, 0x9d8c, 0x9d8d, 0x9d8e, 0x9d8f, 0x9d90,
+ 0x9d91, 0x9d92, 0x9d93, 0x9d94, 0x9d95, 0x9d96, 0x9d97, 0x9d98,
+ 0x9d99, 0x9d9a, 0x9d9b, 0x9d9c, 0x9d9d, 0x9d9e, 0x9d9f, 0x9da0,
+ 0x9da1, 0x9da2, 0x9da3, 0x9da4, 0x9da5, 0x9da6, 0x9da7, 0x9da8,
+ 0x9da9, 0x9daa, 0x9dab, 0x9dac, 0x9dad, 0x9dae, 0x9daf, 0x9db0,
+ 0x9db1, 0x9db2, 0x9db3, 0x9db4, 0x9db5, 0x9db6, 0x9db7, 0x9db8,
+ 0x9db9, 0x9dba, 0x9dbb, 0x9dbc, 0x9dbd, 0x9dbe, 0x9dbf, 0x9dc0,
+ 0x9dc1, 0x9dc2, 0x9dc3, 0x9dc4, 0x9dc5, 0x9dc6, 0x9dc7, 0x9dc8,
+ 0x9dc9, 0x9dca, 0x9dcb, 0x9dcc, 0x9dcd, 0x9dce, 0x9dcf, 0x9dd0,
+ 0x9dd1, 0x9dd2, 0x9dd3, 0x9dd4, 0x9dd5, 0x9dd6, 0x9dd7, 0x9dd8,
+ 0x9dd9, 0x9dda, 0x9ddb, 0x9ddc, 0x9ddd, 0x9dde, 0x9ddf, 0x9de0,
+ 0x9de1, 0x9de2, 0x9de3, 0x9de4, 0x9de5, 0x9de6, 0x9de7, 0x9de8,
+ 0x9de9, 0x9dea, 0x9deb, 0x9dec, 0x9ded, 0x9dee, 0x9def, 0x9df0,
+ 0x9df1, 0x9df2, 0x9df3, 0x9df4, 0x9df5, 0x9df6, 0x9df7, 0x9df8,
+ 0x9df9, 0x9dfa, 0x9dfb, 0x9dfc, 0x9e40, 0x9e41, 0x9e42, 0x9e43,
+ 0x9e44, 0x9e45, 0x9e46, 0x9e47, 0x9e48, 0x9e49, 0x9e4a, 0x9e4b,
+ 0x9e4c, 0x9e4d, 0x9e4e, 0x9e4f, 0x9e50, 0x9e51, 0x9e52, 0x9e53,
+ 0x9e54, 0x9e55, 0x9e56, 0x9e57, 0x9e58, 0x9e59, 0x9e5a, 0x9e5b,
+ 0x9e5c, 0x9e5d, 0x9e5e, 0x9e5f, 0x9e60, 0x9e61, 0x9e62, 0x9e63,
+ 0x9e64, 0x9e65, 0x9e66, 0x9e67, 0x9e68, 0x9e69, 0x9e6a, 0x9e6b,
+ 0x9e6c, 0x9e6d, 0x9e6e, 0x9e6f, 0x9e70, 0x9e71, 0x9e72, 0x9e73,
+ 0x9e74, 0x9e75, 0x9e76, 0x9e77, 0x9e78, 0x9e79, 0x9e7a, 0x9e7b,
+ 0x9e7c, 0x9e7d, 0x9e7e, 0x9e80, 0x9e81, 0x9e82, 0x9e83, 0x9e84,
+ 0x9e85, 0x9e86, 0x9e87, 0x9e88, 0x9e89, 0x9e8a, 0x9e8b, 0x9e8c,
+ 0x9e8d, 0x9e8e, 0x9e8f, 0x9e90, 0x9e91, 0x9e92, 0x9e93, 0x9e94,
+ 0x9e95, 0x9e96, 0x9e97, 0x9e98, 0x9e99, 0x9e9a, 0x9e9b, 0x9e9c,
+ 0x9e9d, 0x9e9e, 0x9e9f, 0x9ea0, 0x9ea1, 0x9ea2, 0x9ea3, 0x9ea4,
+ 0x9ea5, 0x9ea6, 0x9ea7, 0x9ea8, 0x9ea9, 0x9eaa, 0x9eab, 0x9eac,
+ 0x9ead, 0x9eae, 0x9eaf, 0x9eb0, 0x9eb1, 0x9eb2, 0x9eb3, 0x9eb4,
+ 0x9eb5, 0x9eb6, 0x9eb7, 0x9eb8, 0x9eb9, 0x9eba, 0x9ebb, 0x9ebc,
+ 0x9ebd, 0x9ebe, 0x9ebf, 0x9ec0, 0x9ec1, 0x9ec2, 0x9ec3, 0x9ec4,
+ 0x9ec5, 0x9ec6, 0x9ec7, 0x9ec8, 0x9ec9, 0x9eca, 0x9ecb, 0x9ecc,
+ 0x9ecd, 0x9ece, 0x9ecf, 0x9ed0, 0x9ed1, 0x9ed2, 0x9ed3, 0x9ed4,
+ 0x9ed5, 0x9ed6, 0x9ed7, 0x9ed8, 0x9ed9, 0x9eda, 0x9edb, 0x9edc,
+ 0x9edd, 0x9ede, 0x9edf, 0x9ee0, 0x9ee1, 0x9ee2, 0x9ee3, 0x9ee4,
+ 0x9ee5, 0x9ee6, 0x9ee7, 0x9ee8, 0x9ee9, 0x9eea, 0x9eeb, 0x9eec,
+ 0x9eed, 0x9eee, 0x9eef, 0x9ef0, 0x9ef1, 0x9ef2, 0x9ef3, 0x9ef4,
+ 0x9ef5, 0x9ef6, 0x9ef7, 0x9ef8, 0x9ef9, 0x9efa, 0x9efb, 0x9efc,
+ 0x9f40, 0x9f41, 0x9f42, 0x9f43, 0x9f44, 0x9f45, 0x9f46, 0x9f47,
+ 0x9f48, 0x9f49, 0x9f4a, 0x9f4b, 0x9f4c, 0x9f4d, 0x9f4e, 0x9f4f,
+ 0x9f50, 0x9f51, 0x9f52, 0x9f53, 0x9f54, 0x9f55, 0x9f56, 0x9f57,
+ 0x9f58, 0x9f59, 0x9f5a, 0x9f5b, 0x9f5c, 0x9f5d, 0x9f5e, 0x9f5f,
+ 0x9f60, 0x9f61, 0x9f62, 0x9f63, 0x9f64, 0x9f65, 0x9f66, 0x9f67,
+ 0x9f68, 0x9f69, 0x9f6a, 0x9f6b, 0x9f6c, 0x9f6d, 0x9f6e, 0x9f6f,
+ 0x9f70, 0x9f71, 0x9f72, 0x9f73, 0x9f74, 0x9f75, 0x9f76, 0x9f77,
+ 0x9f78, 0x9f79, 0x9f7a, 0x9f7b, 0x9f7c, 0x9f7d, 0x9f7e, 0x9f80,
+ 0x9f81, 0x9f82, 0x9f83, 0x9f84, 0x9f85, 0x9f86, 0x9f87, 0x9f88,
+ 0x9f89, 0x9f8a, 0x9f8b, 0x9f8c, 0x9f8d, 0x9f8e, 0x9f8f, 0x9f90,
+ 0x9f91, 0x9f92, 0x9f93, 0x9f94, 0x9f95, 0x9f96, 0x9f97, 0x9f98,
+ 0x9f99, 0x9f9a, 0x9f9b, 0x9f9c, 0x9f9d, 0x9f9e, 0x9f9f, 0x9fa0,
+ 0x9fa1, 0x9fa2, 0x9fa3, 0x9fa4, 0x9fa5, 0x9fa6, 0x9fa7, 0x9fa8,
+ 0x9fa9, 0x9faa, 0x9fab, 0x9fac, 0x9fad, 0x9fae, 0x9faf, 0x9fb0,
+ 0x9fb1, 0x9fb2, 0x9fb3, 0x9fb4, 0x9fb5, 0x9fb6, 0x9fb7, 0x9fb8,
+ 0x9fb9, 0x9fba, 0x9fbb, 0x9fbc, 0x9fbd, 0x9fbe, 0x9fbf, 0x9fc0,
+ 0x9fc1, 0x9fc2, 0x9fc3, 0x9fc4, 0x9fc5, 0x9fc6, 0x9fc7, 0x9fc8,
+ 0x9fc9, 0x9fca, 0x9fcb, 0x9fcc, 0x9fcd, 0x9fce, 0x9fcf, 0x9fd0,
+ 0x9fd1, 0x9fd2, 0x9fd3, 0x9fd4, 0x9fd5, 0x9fd6, 0x9fd7, 0x9fd8,
+ 0x9fd9, 0x9fda, 0x9fdb, 0x9fdc, 0x9fdd, 0x9fde, 0x9fdf, 0x9fe0,
+ 0x9fe1, 0x9fe2, 0x9fe3, 0x9fe4, 0x9fe5, 0x9fe6, 0x9fe7, 0x9fe8,
+ 0x9fe9, 0x9fea, 0x9feb, 0x9fec, 0x9fed, 0x9fee, 0x9fef, 0x9ff0,
+ 0x9ff1, 0x9ff2, 0x9ff3, 0x9ff4, 0x9ff5, 0x9ff6, 0x9ff7, 0x9ff8,
+ 0x9ff9, 0x9ffa, 0x9ffb, 0x9ffc, 0xe040, 0xe041, 0xe042, 0xe043,
+ 0xe044, 0xe045, 0xe046, 0xe047, 0xe048, 0xe049, 0xe04a, 0xe04b,
+ 0xe04c, 0xe04d, 0xe04e, 0xe04f, 0xe050, 0xe051, 0xe052, 0xe053,
+ 0xe054, 0xe055, 0xe056, 0xe057, 0xe058, 0xe059, 0xe05a, 0xe05b,
+ 0xe05c, 0xe05d, 0xe05e, 0xe05f, 0xe060, 0xe061, 0xe062, 0xe063,
+ 0xe064, 0xe065, 0xe066, 0xe067, 0xe068, 0xe069, 0xe06a, 0xe06b,
+ 0xe06c, 0xe06d, 0xe06e, 0xe06f, 0xe070, 0xe071, 0xe072, 0xe073,
+ 0xe074, 0xe075, 0xe076, 0xe077, 0xe078, 0xe079, 0xe07a, 0xe07b,
+ 0xe07c, 0xe07d, 0xe07e, 0xe080, 0xe081, 0xe082, 0xe083, 0xe084,
+ 0xe085, 0xe086, 0xe087, 0xe088, 0xe089, 0xe08a, 0xe08b, 0xe08c,
+ 0xe08d, 0xe08e, 0xe08f, 0xe090, 0xe091, 0xe092, 0xe093, 0xe094,
+ 0xe095, 0xe096, 0xe097, 0xe098, 0xe099, 0xe09a, 0xe09b, 0xe09c,
+ 0xe09d, 0xe09e, 0xe09f, 0xe0a0, 0xe0a1, 0xe0a2, 0xe0a3, 0xe0a4,
+ 0xe0a5, 0xe0a6, 0xe0a7, 0xe0a8, 0xe0a9, 0xe0aa, 0xe0ab, 0xe0ac,
+ 0xe0ad, 0xe0ae, 0xe0af, 0xe0b0, 0xe0b1, 0xe0b2, 0xe0b3, 0xe0b4,
+ 0xe0b5, 0xe0b6, 0xe0b7, 0xe0b8, 0xe0b9, 0xe0ba, 0xe0bb, 0xe0bc,
+ 0xe0bd, 0xe0be, 0xe0bf, 0xe0c0, 0xe0c1, 0xe0c2, 0xe0c3, 0xe0c4,
+ 0xe0c5, 0xe0c6, 0xe0c7, 0xe0c8, 0xe0c9, 0xe0ca, 0xe0cb, 0xe0cc,
+ 0xe0cd, 0xe0ce, 0xe0cf, 0xe0d0, 0xe0d1, 0xe0d2, 0xe0d3, 0xe0d4,
+ 0xe0d5, 0xe0d6, 0xe0d7, 0xe0d8, 0xe0d9, 0xe0da, 0xe0db, 0xe0dc,
+ 0xe0dd, 0xe0de, 0xe0df, 0xe0e0, 0xe0e1, 0xe0e2, 0xe0e3, 0xe0e4,
+ 0xe0e5, 0xe0e6, 0xe0e7, 0xe0e8, 0xe0e9, 0xe0ea, 0xe0eb, 0xe0ec,
+ 0xe0ed, 0xe0ee, 0xe0ef, 0xe0f0, 0xe0f1, 0xe0f2, 0xe0f3, 0xe0f4,
+ 0xe0f5, 0xe0f6, 0xe0f7, 0xe0f8, 0xe0f9, 0xe0fa, 0xe0fb, 0xe0fc,
+ 0xe140, 0xe141, 0xe142, 0xe143, 0xe144, 0xe145, 0xe146, 0xe147,
+ 0xe148, 0xe149, 0xe14a, 0xe14b, 0xe14c, 0xe14d, 0xe14e, 0xe14f,
+ 0xe150, 0xe151, 0xe152, 0xe153, 0xe154, 0xe155, 0xe156, 0xe157,
+ 0xe158, 0xe159, 0xe15a, 0xe15b, 0xe15c, 0xe15d, 0xe15e, 0xe15f,
+ 0xe160, 0xe161, 0xe162, 0xe163, 0xe164, 0xe165, 0xe166, 0xe167,
+ 0xe168, 0xe169, 0xe16a, 0xe16b, 0xe16c, 0xe16d, 0xe16e, 0xe16f,
+ 0xe170, 0xe171, 0xe172, 0xe173, 0xe174, 0xe175, 0xe176, 0xe177,
+ 0xe178, 0xe179, 0xe17a, 0xe17b, 0xe17c, 0xe17d, 0xe17e, 0xe180,
+ 0xe181, 0xe182, 0xe183, 0xe184, 0xe185, 0xe186, 0xe187, 0xe188,
+ 0xe189, 0xe18a, 0xe18b, 0xe18c, 0xe18d, 0xe18e, 0xe18f, 0xe190,
+ 0xe191, 0xe192, 0xe193, 0xe194, 0xe195, 0xe196, 0xe197, 0xe198,
+ 0xe199, 0xe19a, 0xe19b, 0xe19c, 0xe19d, 0xe19e, 0xe19f, 0xe1a0,
+ 0xe1a1, 0xe1a2, 0xe1a3, 0xe1a4, 0xe1a5, 0xe1a6, 0xe1a7, 0xe1a8,
+ 0xe1a9, 0xe1aa, 0xe1ab, 0xe1ac, 0xe1ad, 0xe1ae, 0xe1af, 0xe1b0,
+ 0xe1b1, 0xe1b2, 0xe1b3, 0xe1b4, 0xe1b5, 0xe1b6, 0xe1b7, 0xe1b8,
+ 0xe1b9, 0xe1ba, 0xe1bb, 0xe1bc, 0xe1bd, 0xe1be, 0xe1bf, 0xe1c0,
+ 0xe1c1, 0xe1c2, 0xe1c3, 0xe1c4, 0xe1c5, 0xe1c6, 0xe1c7, 0xe1c8,
+ 0xe1c9, 0xe1ca, 0xe1cb, 0xe1cc, 0xe1cd, 0xe1ce, 0xe1cf, 0xe1d0,
+ 0xe1d1, 0xe1d2, 0xe1d3, 0xe1d4, 0xe1d5, 0xe1d6, 0xe1d7, 0xe1d8,
+ 0xe1d9, 0xe1da, 0xe1db, 0xe1dc, 0xe1dd, 0xe1de, 0xe1df, 0xe1e0,
+ 0xe1e1, 0xe1e2, 0xe1e3, 0xe1e4, 0xe1e5, 0xe1e6, 0xe1e7, 0xe1e8,
+ 0xe1e9, 0xe1ea, 0xe1eb, 0xe1ec, 0xe1ed, 0xe1ee, 0xe1ef, 0xe1f0,
+ 0xe1f1, 0xe1f2, 0xe1f3, 0xe1f4, 0xe1f5, 0xe1f6, 0xe1f7, 0xe1f8,
+ 0xe1f9, 0xe1fa, 0xe1fb, 0xe1fc, 0xe240, 0xe241, 0xe242, 0xe243,
+ 0xe244, 0xe245, 0xe246, 0xe247, 0xe248, 0xe249, 0xe24a, 0xe24b,
+ 0xe24c, 0xe24d, 0xe24e, 0xe24f, 0xe250, 0xe251, 0xe252, 0xe253,
+ 0xe254, 0xe255, 0xe256, 0xe257, 0xe258, 0xe259, 0xe25a, 0xe25b,
+ 0xe25c, 0xe25d, 0xe25e, 0xe25f, 0xe260, 0xe261, 0xe262, 0xe263,
+ 0xe264, 0xe265, 0xe266, 0xe267, 0xe268, 0xe269, 0xe26a, 0xe26b,
+ 0xe26c, 0xe26d, 0xe26e, 0xe26f, 0xe270, 0xe271, 0xe272, 0xe273,
+ 0xe274, 0xe275, 0xe276, 0xe277, 0xe278, 0xe279, 0xe27a, 0xe27b,
+ 0xe27c, 0xe27d, 0xe27e, 0xe280, 0xe281, 0xe282, 0xe283, 0xe284,
+ 0xe285, 0xe286, 0xe287, 0xe288, 0xe289, 0xe28a, 0xe28b, 0xe28c,
+ 0xe28d, 0xe28e, 0xe28f, 0xe290, 0xe291, 0xe292, 0xe293, 0xe294,
+ 0xe295, 0xe296, 0xe297, 0xe298, 0xe299, 0xe29a, 0xe29b, 0xe29c,
+ 0xe29d, 0xe29e, 0xe29f, 0xe2a0, 0xe2a1, 0xe2a2, 0xe2a3, 0xe2a4,
+ 0xe2a5, 0xe2a6, 0xe2a7, 0xe2a8, 0xe2a9, 0xe2aa, 0xe2ab, 0xe2ac,
+ 0xe2ad, 0xe2ae, 0xe2af, 0xe2b0, 0xe2b1, 0xe2b2, 0xe2b3, 0xe2b4,
+ 0xe2b5, 0xe2b6, 0xe2b7, 0xe2b8, 0xe2b9, 0xe2ba, 0xe2bb, 0xe2bc,
+ 0xe2bd, 0xe2be, 0xe2bf, 0xe2c0, 0xe2c1, 0xe2c2, 0xe2c3, 0xe2c4,
+ 0xe2c5, 0xe2c6, 0xe2c7, 0xe2c8, 0xe2c9, 0xe2ca, 0xe2cb, 0xe2cc,
+ 0xe2cd, 0xe2ce, 0xe2cf, 0xe2d0, 0xe2d1, 0xe2d2, 0xe2d3, 0xe2d4,
+ 0xe2d5, 0xe2d6, 0xe2d7, 0xe2d8, 0xe2d9, 0xe2da, 0xe2db, 0xe2dc,
+ 0xe2dd, 0xe2de, 0xe2df, 0xe2e0, 0xe2e1, 0xe2e2, 0xe2e3, 0xe2e4,
+ 0xe2e5, 0xe2e6, 0xe2e7, 0xe2e8, 0xe2e9, 0xe2ea, 0xe2eb, 0xe2ec,
+ 0xe2ed, 0xe2ee, 0xe2ef, 0xe2f0, 0xe2f1, 0xe2f2, 0xe2f3, 0xe2f4,
+ 0xe2f5, 0xe2f6, 0xe2f7, 0xe2f8, 0xe2f9, 0xe2fa, 0xe2fb, 0xe2fc,
+ 0xe340, 0xe341, 0xe342, 0xe343, 0xe344, 0xe345, 0xe346, 0xe347,
+ 0xe348, 0xe349, 0xe34a, 0xe34b, 0xe34c, 0xe34d, 0xe34e, 0xe34f,
+ 0xe350, 0xe351, 0xe352, 0xe353, 0xe354, 0xe355, 0xe356, 0xe357,
+ 0xe358, 0xe359, 0xe35a, 0xe35b, 0xe35c, 0xe35d, 0xe35e, 0xe35f,
+ 0xe360, 0xe361, 0xe362, 0xe363, 0xe364, 0xe365, 0xe366, 0xe367,
+ 0xe368, 0xe369, 0xe36a, 0xe36b, 0xe36c, 0xe36d, 0xe36e, 0xe36f,
+ 0xe370, 0xe371, 0xe372, 0xe373, 0xe374, 0xe375, 0xe376, 0xe377,
+ 0xe378, 0xe379, 0xe37a, 0xe37b, 0xe37c, 0xe37d, 0xe37e, 0xe380,
+ 0xe381, 0xe382, 0xe383, 0xe384, 0xe385, 0xe386, 0xe387, 0xe388,
+ 0xe389, 0xe38a, 0xe38b, 0xe38c, 0xe38d, 0xe38e, 0xe38f, 0xe390,
+ 0xe391, 0xe392, 0xe393, 0xe394, 0xe395, 0xe396, 0xe397, 0xe398,
+ 0xe399, 0xe39a, 0xe39b, 0xe39c, 0xe39d, 0xe39e, 0xe39f, 0xe3a0,
+ 0xe3a1, 0xe3a2, 0xe3a3, 0xe3a4, 0xe3a5, 0xe3a6, 0xe3a7, 0xe3a8,
+ 0xe3a9, 0xe3aa, 0xe3ab, 0xe3ac, 0xe3ad, 0xe3ae, 0xe3af, 0xe3b0,
+ 0xe3b1, 0xe3b2, 0xe3b3, 0xe3b4, 0xe3b5, 0xe3b6, 0xe3b7, 0xe3b8,
+ 0xe3b9, 0xe3ba, 0xe3bb, 0xe3bc, 0xe3bd, 0xe3be, 0xe3bf, 0xe3c0,
+ 0xe3c1, 0xe3c2, 0xe3c3, 0xe3c4, 0xe3c5, 0xe3c6, 0xe3c7, 0xe3c8,
+ 0xe3c9, 0xe3ca, 0xe3cb, 0xe3cc, 0xe3cd, 0xe3ce, 0xe3cf, 0xe3d0,
+ 0xe3d1, 0xe3d2, 0xe3d3, 0xe3d4, 0xe3d5, 0xe3d6, 0xe3d7, 0xe3d8,
+ 0xe3d9, 0xe3da, 0xe3db, 0xe3dc, 0xe3dd, 0xe3de, 0xe3df, 0xe3e0,
+ 0xe3e1, 0xe3e2, 0xe3e3, 0xe3e4, 0xe3e5, 0xe3e6, 0xe3e7, 0xe3e8,
+ 0xe3e9, 0xe3ea, 0xe3eb, 0xe3ec, 0xe3ed, 0xe3ee, 0xe3ef, 0xe3f0,
+ 0xe3f1, 0xe3f2, 0xe3f3, 0xe3f4, 0xe3f5, 0xe3f6, 0xe3f7, 0xe3f8,
+ 0xe3f9, 0xe3fa, 0xe3fb, 0xe3fc, 0xe440, 0xe441, 0xe442, 0xe443,
+ 0xe444, 0xe445, 0xe446, 0xe447, 0xe448, 0xe449, 0xe44a, 0xe44b,
+ 0xe44c, 0xe44d, 0xe44e, 0xe44f, 0xe450, 0xe451, 0xe452, 0xe453,
+ 0xe454, 0xe455, 0xe456, 0xe457, 0xe458, 0xe459, 0xe45a, 0xe45b,
+ 0xe45c, 0xe45d, 0xe45e, 0xe45f, 0xe460, 0xe461, 0xe462, 0xe463,
+ 0xe464, 0xe465, 0xe466, 0xe467, 0xe468, 0xe469, 0xe46a, 0xe46b,
+ 0xe46c, 0xe46d, 0xe46e, 0xe46f, 0xe470, 0xe471, 0xe472, 0xe473,
+ 0xe474, 0xe475, 0xe476, 0xe477, 0xe478, 0xe479, 0xe47a, 0xe47b,
+ 0xe47c, 0xe47d, 0xe47e, 0xe480, 0xe481, 0xe482, 0xe483, 0xe484,
+ 0xe485, 0xe486, 0xe487, 0xe488, 0xe489, 0xe48a, 0xe48b, 0xe48c,
+ 0xe48d, 0xe48e, 0xe48f, 0xe490, 0xe491, 0xe492, 0xe493, 0xe494,
+ 0xe495, 0xe496, 0xe497, 0xe498, 0xe499, 0xe49a, 0xe49b, 0xe49c,
+ 0xe49d, 0xe49e, 0xe49f, 0xe4a0, 0xe4a1, 0xe4a2, 0xe4a3, 0xe4a4,
+ 0xe4a5, 0xe4a6, 0xe4a7, 0xe4a8, 0xe4a9, 0xe4aa, 0xe4ab, 0xe4ac,
+ 0xe4ad, 0xe4ae, 0xe4af, 0xe4b0, 0xe4b1, 0xe4b2, 0xe4b3, 0xe4b4,
+ 0xe4b5, 0xe4b6, 0xe4b7, 0xe4b8, 0xe4b9, 0xe4ba, 0xe4bb, 0xe4bc,
+ 0xe4bd, 0xe4be, 0xe4bf, 0xe4c0, 0xe4c1, 0xe4c2, 0xe4c3, 0xe4c4,
+ 0xe4c5, 0xe4c6, 0xe4c7, 0xe4c8, 0xe4c9, 0xe4ca, 0xe4cb, 0xe4cc,
+ 0xe4cd, 0xe4ce, 0xe4cf, 0xe4d0, 0xe4d1, 0xe4d2, 0xe4d3, 0xe4d4,
+ 0xe4d5, 0xe4d6, 0xe4d7, 0xe4d8, 0xe4d9, 0xe4da, 0xe4db, 0xe4dc,
+ 0xe4dd, 0xe4de, 0xe4df, 0xe4e0, 0xe4e1, 0xe4e2, 0xe4e3, 0xe4e4,
+ 0xe4e5, 0xe4e6, 0xe4e7, 0xe4e8, 0xe4e9, 0xe4ea, 0xe4eb, 0xe4ec,
+ 0xe4ed, 0xe4ee, 0xe4ef, 0xe4f0, 0xe4f1, 0xe4f2, 0xe4f3, 0xe4f4,
+ 0xe4f5, 0xe4f6, 0xe4f7, 0xe4f8, 0xe4f9, 0xe4fa, 0xe4fb, 0xe4fc,
+ 0xe540, 0xe541, 0xe542, 0xe543, 0xe544, 0xe545, 0xe546, 0xe547,
+ 0xe548, 0xe549, 0xe54a, 0xe54b, 0xe54c, 0xe54d, 0xe54e, 0xe54f,
+ 0xe550, 0xe551, 0xe552, 0xe553, 0xe554, 0xe555, 0xe556, 0xe557,
+ 0xe558, 0xe559, 0xe55a, 0xe55b, 0xe55c, 0xe55d, 0xe55e, 0xe55f,
+ 0xe560, 0xe561, 0xe562, 0xe563, 0xe564, 0xe565, 0xe566, 0xe567,
+ 0xe568, 0xe569, 0xe56a, 0xe56b, 0xe56c, 0xe56d, 0xe56e, 0xe56f,
+ 0xe570, 0xe571, 0xe572, 0xe573, 0xe574, 0xe575, 0xe576, 0xe577,
+ 0xe578, 0xe579, 0xe57a, 0xe57b, 0xe57c, 0xe57d, 0xe57e, 0xe580,
+ 0xe581, 0xe582, 0xe583, 0xe584, 0xe585, 0xe586, 0xe587, 0xe588,
+ 0xe589, 0xe58a, 0xe58b, 0xe58c, 0xe58d, 0xe58e, 0xe58f, 0xe590,
+ 0xe591, 0xe592, 0xe593, 0xe594, 0xe595, 0xe596, 0xe597, 0xe598,
+ 0xe599, 0xe59a, 0xe59b, 0xe59c, 0xe59d, 0xe59e, 0xe59f, 0xe5a0,
+ 0xe5a1, 0xe5a2, 0xe5a3, 0xe5a4, 0xe5a5, 0xe5a6, 0xe5a7, 0xe5a8,
+ 0xe5a9, 0xe5aa, 0xe5ab, 0xe5ac, 0xe5ad, 0xe5ae, 0xe5af, 0xe5b0,
+ 0xe5b1, 0xe5b2, 0xe5b3, 0xe5b4, 0xe5b5, 0xe5b6, 0xe5b7, 0xe5b8,
+ 0xe5b9, 0xe5ba, 0xe5bb, 0xe5bc, 0xe5bd, 0xe5be, 0xe5bf, 0xe5c0,
+ 0xe5c1, 0xe5c2, 0xe5c3, 0xe5c4, 0xe5c5, 0xe5c6, 0xe5c7, 0xe5c8,
+ 0xe5c9, 0xe5ca, 0xe5cb, 0xe5cc, 0xe5cd, 0xe5ce, 0xe5cf, 0xe5d0,
+ 0xe5d1, 0xe5d2, 0xe5d3, 0xe5d4, 0xe5d5, 0xe5d6, 0xe5d7, 0xe5d8,
+ 0xe5d9, 0xe5da, 0xe5db, 0xe5dc, 0xe5dd, 0xe5de, 0xe5df, 0xe5e0,
+ 0xe5e1, 0xe5e2, 0xe5e3, 0xe5e4, 0xe5e5, 0xe5e6, 0xe5e7, 0xe5e8,
+ 0xe5e9, 0xe5ea, 0xe5eb, 0xe5ec, 0xe5ed, 0xe5ee, 0xe5ef, 0xe5f0,
+ 0xe5f1, 0xe5f2, 0xe5f3, 0xe5f4, 0xe5f5, 0xe5f6, 0xe5f7, 0xe5f8,
+ 0xe5f9, 0xe5fa, 0xe5fb, 0xe5fc, 0xe640, 0xe641, 0xe642, 0xe643,
+ 0xe644, 0xe645, 0xe646, 0xe647, 0xe648, 0xe649, 0xe64a, 0xe64b,
+ 0xe64c, 0xe64d, 0xe64e, 0xe64f, 0xe650, 0xe651, 0xe652, 0xe653,
+ 0xe654, 0xe655, 0xe656, 0xe657, 0xe658, 0xe659, 0xe65a, 0xe65b,
+ 0xe65c, 0xe65d, 0xe65e, 0xe65f, 0xe660, 0xe661, 0xe662, 0xe663,
+ 0xe664, 0xe665, 0xe666, 0xe667, 0xe668, 0xe669, 0xe66a, 0xe66b,
+ 0xe66c, 0xe66d, 0xe66e, 0xe66f, 0xe670, 0xe671, 0xe672, 0xe673,
+ 0xe674, 0xe675, 0xe676, 0xe677, 0xe678, 0xe679, 0xe67a, 0xe67b,
+ 0xe67c, 0xe67d, 0xe67e, 0xe680, 0xe681, 0xe682, 0xe683, 0xe684,
+ 0xe685, 0xe686, 0xe687, 0xe688, 0xe689, 0xe68a, 0xe68b, 0xe68c,
+ 0xe68d, 0xe68e, 0xe68f, 0xe690, 0xe691, 0xe692, 0xe693, 0xe694,
+ 0xe695, 0xe696, 0xe697, 0xe698, 0xe699, 0xe69a, 0xe69b, 0xe69c,
+ 0xe69d, 0xe69e, 0xe69f, 0xe6a0, 0xe6a1, 0xe6a2, 0xe6a3, 0xe6a4,
+ 0xe6a5, 0xe6a6, 0xe6a7, 0xe6a8, 0xe6a9, 0xe6aa, 0xe6ab, 0xe6ac,
+ 0xe6ad, 0xe6ae, 0xe6af, 0xe6b0, 0xe6b1, 0xe6b2, 0xe6b3, 0xe6b4,
+ 0xe6b5, 0xe6b6, 0xe6b7, 0xe6b8, 0xe6b9, 0xe6ba, 0xe6bb, 0xe6bc,
+ 0xe6bd, 0xe6be, 0xe6bf, 0xe6c0, 0xe6c1, 0xe6c2, 0xe6c3, 0xe6c4,
+ 0xe6c5, 0xe6c6, 0xe6c7, 0xe6c8, 0xe6c9, 0xe6ca, 0xe6cb, 0xe6cc,
+ 0xe6cd, 0xe6ce, 0xe6cf, 0xe6d0, 0xe6d1, 0xe6d2, 0xe6d3, 0xe6d4,
+ 0xe6d5, 0xe6d6, 0xe6d7, 0xe6d8, 0xe6d9, 0xe6da, 0xe6db, 0xe6dc,
+ 0xe6dd, 0xe6de, 0xe6df, 0xe6e0, 0xe6e1, 0xe6e2, 0xe6e3, 0xe6e4,
+ 0xe6e5, 0xe6e6, 0xe6e7, 0xe6e8, 0xe6e9, 0xe6ea, 0xe6eb, 0xe6ec,
+ 0xe6ed, 0xe6ee, 0xe6ef, 0xe6f0, 0xe6f1, 0xe6f2, 0xe6f3, 0xe6f4,
+ 0xe6f5, 0xe6f6, 0xe6f7, 0xe6f8, 0xe6f9, 0xe6fa, 0xe6fb, 0xe6fc,
+ 0xe740, 0xe741, 0xe742, 0xe743, 0xe744, 0xe745, 0xe746, 0xe747,
+ 0xe748, 0xe749, 0xe74a, 0xe74b, 0xe74c, 0xe74d, 0xe74e, 0xe74f,
+ 0xe750, 0xe751, 0xe752, 0xe753, 0xe754, 0xe755, 0xe756, 0xe757,
+ 0xe758, 0xe759, 0xe75a, 0xe75b, 0xe75c, 0xe75d, 0xe75e, 0xe75f,
+ 0xe760, 0xe761, 0xe762, 0xe763, 0xe764, 0xe765, 0xe766, 0xe767,
+ 0xe768, 0xe769, 0xe76a, 0xe76b, 0xe76c, 0xe76d, 0xe76e, 0xe76f,
+ 0xe770, 0xe771, 0xe772, 0xe773, 0xe774, 0xe775, 0xe776, 0xe777,
+ 0xe778, 0xe779, 0xe77a, 0xe77b, 0xe77c, 0xe77d, 0xe77e, 0xe780,
+ 0xe781, 0xe782, 0xe783, 0xe784, 0xe785, 0xe786, 0xe787, 0xe788,
+ 0xe789, 0xe78a, 0xe78b, 0xe78c, 0xe78d, 0xe78e, 0xe78f, 0xe790,
+ 0xe791, 0xe792, 0xe793, 0xe794, 0xe795, 0xe796, 0xe797, 0xe798,
+ 0xe799, 0xe79a, 0xe79b, 0xe79c, 0xe79d, 0xe79e, 0xe79f, 0xe7a0,
+ 0xe7a1, 0xe7a2, 0xe7a3, 0xe7a4, 0xe7a5, 0xe7a6, 0xe7a7, 0xe7a8,
+ 0xe7a9, 0xe7aa, 0xe7ab, 0xe7ac, 0xe7ad, 0xe7ae, 0xe7af, 0xe7b0,
+ 0xe7b1, 0xe7b2, 0xe7b3, 0xe7b4, 0xe7b5, 0xe7b6, 0xe7b7, 0xe7b8,
+ 0xe7b9, 0xe7ba, 0xe7bb, 0xe7bc, 0xe7bd, 0xe7be, 0xe7bf, 0xe7c0,
+ 0xe7c1, 0xe7c2, 0xe7c3, 0xe7c4, 0xe7c5, 0xe7c6, 0xe7c7, 0xe7c8,
+ 0xe7c9, 0xe7ca, 0xe7cb, 0xe7cc, 0xe7cd, 0xe7ce, 0xe7cf, 0xe7d0,
+ 0xe7d1, 0xe7d2, 0xe7d3, 0xe7d4, 0xe7d5, 0xe7d6, 0xe7d7, 0xe7d8,
+ 0xe7d9, 0xe7da, 0xe7db, 0xe7dc, 0xe7dd, 0xe7de, 0xe7df, 0xe7e0,
+ 0xe7e1, 0xe7e2, 0xe7e3, 0xe7e4, 0xe7e5, 0xe7e6, 0xe7e7, 0xe7e8,
+ 0xe7e9, 0xe7ea, 0xe7eb, 0xe7ec, 0xe7ed, 0xe7ee, 0xe7ef, 0xe7f0,
+ 0xe7f1, 0xe7f2, 0xe7f3, 0xe7f4, 0xe7f5, 0xe7f6, 0xe7f7, 0xe7f8,
+ 0xe7f9, 0xe7fa, 0xe7fb, 0xe7fc, 0xe840, 0xe841, 0xe842, 0xe843,
+ 0xe844, 0xe845, 0xe846, 0xe847, 0xe848, 0xe849, 0xe84a, 0xe84b,
+ 0xe84c, 0xe84d, 0xe84e, 0xe84f, 0xe850, 0xe851, 0xe852, 0xe853,
+ 0xe854, 0xe855, 0xe856, 0xe857, 0xe858, 0xe859, 0xe85a, 0xe85b,
+ 0xe85c, 0xe85d, 0xe85e, 0xe85f, 0xe860, 0xe861, 0xe862, 0xe863,
+ 0xe864, 0xe865, 0xe866, 0xe867, 0xe868, 0xe869, 0xe86a, 0xe86b,
+ 0xe86c, 0xe86d, 0xe86e, 0xe86f, 0xe870, 0xe871, 0xe872, 0xe873,
+ 0xe874, 0xe875, 0xe876, 0xe877, 0xe878, 0xe879, 0xe87a, 0xe87b,
+ 0xe87c, 0xe87d, 0xe87e, 0xe880, 0xe881, 0xe882, 0xe883, 0xe884,
+ 0xe885, 0xe886, 0xe887, 0xe888, 0xe889, 0xe88a, 0xe88b, 0xe88c,
+ 0xe88d, 0xe88e, 0xe88f, 0xe890, 0xe891, 0xe892, 0xe893, 0xe894,
+ 0xe895, 0xe896, 0xe897, 0xe898, 0xe899, 0xe89a, 0xe89b, 0xe89c,
+ 0xe89d, 0xe89e, 0xe89f, 0xe8a0, 0xe8a1, 0xe8a2, 0xe8a3, 0xe8a4,
+ 0xe8a5, 0xe8a6, 0xe8a7, 0xe8a8, 0xe8a9, 0xe8aa, 0xe8ab, 0xe8ac,
+ 0xe8ad, 0xe8ae, 0xe8af, 0xe8b0, 0xe8b1, 0xe8b2, 0xe8b3, 0xe8b4,
+ 0xe8b5, 0xe8b6, 0xe8b7, 0xe8b8, 0xe8b9, 0xe8ba, 0xe8bb, 0xe8bc,
+ 0xe8bd, 0xe8be, 0xe8bf, 0xe8c0, 0xe8c1, 0xe8c2, 0xe8c3, 0xe8c4,
+ 0xe8c5, 0xe8c6, 0xe8c7, 0xe8c8, 0xe8c9, 0xe8ca, 0xe8cb, 0xe8cc,
+ 0xe8cd, 0xe8ce, 0xe8cf, 0xe8d0, 0xe8d1, 0xe8d2, 0xe8d3, 0xe8d4,
+ 0xe8d5, 0xe8d6, 0xe8d7, 0xe8d8, 0xe8d9, 0xe8da, 0xe8db, 0xe8dc,
+ 0xe8dd, 0xe8de, 0xe8df, 0xe8e0, 0xe8e1, 0xe8e2, 0xe8e3, 0xe8e4,
+ 0xe8e5, 0xe8e6, 0xe8e7, 0xe8e8, 0xe8e9, 0xe8ea, 0xe8eb, 0xe8ec,
+ 0xe8ed, 0xe8ee, 0xe8ef, 0xe8f0, 0xe8f1, 0xe8f2, 0xe8f3, 0xe8f4,
+ 0xe8f5, 0xe8f6, 0xe8f7, 0xe8f8, 0xe8f9, 0xe8fa, 0xe8fb, 0xe8fc,
+ 0xe940, 0xe941, 0xe942, 0xe943, 0xe944, 0xe945, 0xe946, 0xe947,
+ 0xe948, 0xe949, 0xe94a, 0xe94b, 0xe94c, 0xe94d, 0xe94e, 0xe94f,
+ 0xe950, 0xe951, 0xe952, 0xe953, 0xe954, 0xe955, 0xe956, 0xe957,
+ 0xe958, 0xe959, 0xe95a, 0xe95b, 0xe95c, 0xe95d, 0xe95e, 0xe95f,
+ 0xe960, 0xe961, 0xe962, 0xe963, 0xe964, 0xe965, 0xe966, 0xe967,
+ 0xe968, 0xe969, 0xe96a, 0xe96b, 0xe96c, 0xe96d, 0xe96e, 0xe96f,
+ 0xe970, 0xe971, 0xe972, 0xe973, 0xe974, 0xe975, 0xe976, 0xe977,
+ 0xe978, 0xe979, 0xe97a, 0xe97b, 0xe97c, 0xe97d, 0xe97e, 0xe980,
+ 0xe981, 0xe982, 0xe983, 0xe984, 0xe985, 0xe986, 0xe987, 0xe988,
+ 0xe989, 0xe98a, 0xe98b, 0xe98c, 0xe98d, 0xe98e, 0xe98f, 0xe990,
+ 0xe991, 0xe992, 0xe993, 0xe994, 0xe995, 0xe996, 0xe997, 0xe998,
+ 0xe999, 0xe99a, 0xe99b, 0xe99c, 0xe99d, 0xe99e, 0xe99f, 0xe9a0,
+ 0xe9a1, 0xe9a2, 0xe9a3, 0xe9a4, 0xe9a5, 0xe9a6, 0xe9a7, 0xe9a8,
+ 0xe9a9, 0xe9aa, 0xe9ab, 0xe9ac, 0xe9ad, 0xe9ae, 0xe9af, 0xe9b0,
+ 0xe9b1, 0xe9b2, 0xe9b3, 0xe9b4, 0xe9b5, 0xe9b6, 0xe9b7, 0xe9b8,
+ 0xe9b9, 0xe9ba, 0xe9bb, 0xe9bc, 0xe9bd, 0xe9be, 0xe9bf, 0xe9c0,
+ 0xe9c1, 0xe9c2, 0xe9c3, 0xe9c4, 0xe9c5, 0xe9c6, 0xe9c7, 0xe9c8,
+ 0xe9c9, 0xe9ca, 0xe9cb, 0xe9cc, 0xe9cd, 0xe9ce, 0xe9cf, 0xe9d0,
+ 0xe9d1, 0xe9d2, 0xe9d3, 0xe9d4, 0xe9d5, 0xe9d6, 0xe9d7, 0xe9d8,
+ 0xe9d9, 0xe9da, 0xe9db, 0xe9dc, 0xe9dd, 0xe9de, 0xe9df, 0xe9e0,
+ 0xe9e1, 0xe9e2, 0xe9e3, 0xe9e4, 0xe9e5, 0xe9e6, 0xe9e7, 0xe9e8,
+ 0xe9e9, 0xe9ea, 0xe9eb, 0xe9ec, 0xe9ed, 0xe9ee, 0xe9ef, 0xe9f0,
+ 0xe9f1, 0xe9f2, 0xe9f3, 0xe9f4, 0xe9f5, 0xe9f6, 0xe9f7, 0xe9f8,
+ 0xe9f9, 0xe9fa, 0xe9fb, 0xe9fc, 0xea40, 0xea41, 0xea42, 0xea43,
+ 0xea44, 0xea45, 0xea46, 0xea47, 0xea48, 0xea49, 0xea4a, 0xea4b,
+ 0xea4c, 0xea4d, 0xea4e, 0xea4f, 0xea50, 0xea51, 0xea52, 0xea53,
+ 0xea54, 0xea55, 0xea56, 0xea57, 0xea58, 0xea59, 0xea5a, 0xea5b,
+ 0xea5c, 0xea5d, 0xea5e, 0xea5f, 0xea60, 0xea61, 0xea62, 0xea63,
+ 0xea64, 0xea65, 0xea66, 0xea67, 0xea68, 0xea69, 0xea6a, 0xea6b,
+ 0xea6c, 0xea6d, 0xea6e, 0xea6f, 0xea70, 0xea71, 0xea72, 0xea73,
+ 0xea74, 0xea75, 0xea76, 0xea77, 0xea78, 0xea79, 0xea7a, 0xea7b,
+ 0xea7c, 0xea7d, 0xea7e, 0xea80, 0xea81, 0xea82, 0xea83, 0xea84,
+ 0xea85, 0xea86, 0xea87, 0xea88, 0xea89, 0xea8a, 0xea8b, 0xea8c,
+ 0xea8d, 0xea8e, 0xea8f, 0xea90, 0xea91, 0xea92, 0xea93, 0xea94,
+ 0xea95, 0xea96, 0xea97, 0xea98, 0xea99, 0xea9a, 0xea9b, 0xea9c,
+ 0xea9d, 0xea9e, 0xea9f, 0xeaa0, 0xeaa1, 0xeaa2, 0x0020, 0x849f,
+ 0x84aa, 0x84a0, 0x84ab, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x84a1, 0x0020, 0x0020, 0x84ac, 0x84a2,
+ 0x0020, 0x0020, 0x84ad, 0x84a4, 0x0020, 0x0020, 0x84af, 0x84a3,
+ 0x0020, 0x0020, 0x84ae, 0x84a5, 0x84ba, 0x0020, 0x0020, 0x84b5,
+ 0x0020, 0x0020, 0x84b0, 0x84a7, 0x84bc, 0x0020, 0x0020, 0x84b7,
+ 0x0020, 0x0020, 0x84b2, 0x84a6, 0x0020, 0x0020, 0x84b6, 0x84bb,
+ 0x0020, 0x0020, 0x84b1, 0x84a8, 0x0020, 0x0020, 0x84b8, 0x84bd,
+ 0x0020, 0x0020, 0x84b3, 0x84a9, 0x0020, 0x0020, 0x84b9, 0x0020,
+ 0x0020, 0x84be, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x84b4, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x0020, 0x0020, 0x0020, 0x0020, 0xeaa3, 0xeaa4
+};
diff --git a/pdftops/Lexer.cxx b/pdftops/Lexer.cxx
new file mode 100644
index 000000000..5ee492a52
--- /dev/null
+++ b/pdftops/Lexer.cxx
@@ -0,0 +1,474 @@
+//========================================================================
+//
+// Lexer.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include "Lexer.h"
+#include "Error.h"
+
+//------------------------------------------------------------------------
+
+// A '1' in this array means the character is white space. A '1' or
+// '2' means the character ends a name or command.
+static char specialChars[256] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
+ 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
+};
+
+//------------------------------------------------------------------------
+// Lexer
+//------------------------------------------------------------------------
+
+Lexer::Lexer(XRef *xref, Stream *str) {
+ Object obj;
+
+ curStr.initStream(str);
+ streams = new Array(xref);
+ streams->add(curStr.copy(&obj));
+ strPtr = 0;
+ freeArray = gTrue;
+ curStr.streamReset();
+}
+
+Lexer::Lexer(XRef *xref, Object *obj) {
+ Object obj2;
+
+ if (obj->isStream()) {
+ streams = new Array(xref);
+ freeArray = gTrue;
+ streams->add(obj->copy(&obj2));
+ } else {
+ streams = obj->getArray();
+ freeArray = gFalse;
+ }
+ strPtr = 0;
+ if (streams->getLength() > 0) {
+ streams->get(strPtr, &curStr);
+ curStr.streamReset();
+ }
+}
+
+Lexer::~Lexer() {
+ if (!curStr.isNone()) {
+ curStr.streamClose();
+ curStr.free();
+ }
+ if (freeArray) {
+ delete streams;
+ }
+}
+
+int Lexer::getChar() {
+ int c;
+
+ c = EOF;
+ while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
+ curStr.streamClose();
+ curStr.free();
+ ++strPtr;
+ if (strPtr < streams->getLength()) {
+ streams->get(strPtr, &curStr);
+ curStr.streamReset();
+ }
+ }
+ return c;
+}
+
+int Lexer::lookChar() {
+ if (curStr.isNone()) {
+ return EOF;
+ }
+ return curStr.streamLookChar();
+}
+
+Object *Lexer::getObj(Object *obj) {
+ char *p;
+ int c, c2;
+ GBool comment, neg, done;
+ int numParen;
+ int xi;
+ double xf, scale;
+ GString *s;
+ int n, m;
+
+ // skip whitespace and comments
+ comment = gFalse;
+ while (1) {
+ if ((c = getChar()) == EOF) {
+ return obj->initEOF();
+ }
+ if (comment) {
+ if (c == '\r' || c == '\n')
+ comment = gFalse;
+ } else if (c == '%') {
+ comment = gTrue;
+ } else if (specialChars[c] != 1) {
+ break;
+ }
+ }
+
+ // start reading token
+ switch (c) {
+
+ // number
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '-': case '.':
+ neg = gFalse;
+ xi = 0;
+ if (c == '-') {
+ neg = gTrue;
+ } else if (c == '.') {
+ goto doReal;
+ } else {
+ xi = c - '0';
+ }
+ while (1) {
+ c = lookChar();
+ if (isdigit(c)) {
+ getChar();
+ xi = xi * 10 + (c - '0');
+ } else if (c == '.') {
+ getChar();
+ goto doReal;
+ } else {
+ break;
+ }
+ }
+ if (neg)
+ xi = -xi;
+ obj->initInt(xi);
+ break;
+ doReal:
+ xf = xi;
+ scale = 0.1;
+ while (1) {
+ c = lookChar();
+ if (!isdigit(c)) {
+ break;
+ }
+ getChar();
+ xf = xf + scale * (c - '0');
+ scale *= 0.1;
+ }
+ if (neg)
+ xf = -xf;
+ obj->initReal(xf);
+ break;
+
+ // string
+ case '(':
+ p = tokBuf;
+ n = 0;
+ numParen = 1;
+ done = gFalse;
+ s = NULL;
+ do {
+ c2 = EOF;
+ switch (c = getChar()) {
+
+ case EOF:
+#if 0
+ // This breaks some PDF files, e.g., ones from Photoshop.
+ case '\r':
+ case '\n':
+#endif
+ error(getPos(), "Unterminated string");
+ done = gTrue;
+ break;
+
+ case '(':
+ ++numParen;
+ c2 = c;
+ break;
+
+ case ')':
+ if (--numParen == 0) {
+ done = gTrue;
+ } else {
+ c2 = c;
+ }
+ break;
+
+ case '\\':
+ switch (c = getChar()) {
+ case 'n':
+ c2 = '\n';
+ break;
+ case 'r':
+ c2 = '\r';
+ break;
+ case 't':
+ c2 = '\t';
+ break;
+ case 'b':
+ c2 = '\b';
+ break;
+ case 'f':
+ c2 = '\f';
+ break;
+ case '\\':
+ case '(':
+ case ')':
+ c2 = c;
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c2 = c - '0';
+ c = lookChar();
+ if (c >= '0' && c <= '7') {
+ getChar();
+ c2 = (c2 << 3) + (c - '0');
+ c = lookChar();
+ if (c >= '0' && c <= '7') {
+ getChar();
+ c2 = (c2 << 3) + (c - '0');
+ }
+ }
+ break;
+ case '\r':
+ c = lookChar();
+ if (c == '\n') {
+ getChar();
+ }
+ break;
+ case '\n':
+ break;
+ case EOF:
+ error(getPos(), "Unterminated string");
+ done = gTrue;
+ break;
+ default:
+ c2 = c;
+ break;
+ }
+ break;
+
+ default:
+ c2 = c;
+ break;
+ }
+
+ if (c2 != EOF) {
+ if (n == tokBufSize) {
+ if (!s)
+ s = new GString(tokBuf, tokBufSize);
+ else
+ s->append(tokBuf, tokBufSize);
+ p = tokBuf;
+ n = 0;
+ }
+ *p++ = (char)c2;
+ ++n;
+ }
+ } while (!done);
+ if (!s)
+ s = new GString(tokBuf, n);
+ else
+ s->append(tokBuf, n);
+ obj->initString(s);
+ break;
+
+ // name
+ case '/':
+ p = tokBuf;
+ n = 0;
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
+ getChar();
+ if (c == '#') {
+ c2 = lookChar();
+ if (c2 >= '0' && c2 <= '9') {
+ c = c2 - '0';
+ } else if (c2 >= 'A' && c2 <= 'F') {
+ c = c2 - 'A' + 10;
+ } else if (c2 >= 'a' && c2 <= 'f') {
+ c = c2 - 'a' + 10;
+ } else {
+ goto notEscChar;
+ }
+ getChar();
+ c <<= 4;
+ c2 = getChar();
+ if (c2 >= '0' && c2 <= '9') {
+ c += c2 - '0';
+ } else if (c2 >= 'A' && c2 <= 'F') {
+ c += c2 - 'A' + 10;
+ } else if (c2 >= 'a' && c2 <= 'f') {
+ c += c2 - 'a' + 10;
+ } else {
+ error(getPos(), "Illegal digit in hex char in name");
+ }
+ }
+ notEscChar:
+ if (++n == tokBufSize) {
+ error(getPos(), "Name token too long");
+ break;
+ }
+ *p++ = c;
+ }
+ *p = '\0';
+ obj->initName(tokBuf);
+ break;
+
+ // array punctuation
+ case '[':
+ case ']':
+ tokBuf[0] = c;
+ tokBuf[1] = '\0';
+ obj->initCmd(tokBuf);
+ break;
+
+ // hex string or dict punctuation
+ case '<':
+ c = lookChar();
+
+ // dict punctuation
+ if (c == '<') {
+ getChar();
+ tokBuf[0] = tokBuf[1] = '<';
+ tokBuf[2] = '\0';
+ obj->initCmd(tokBuf);
+
+ // hex string
+ } else {
+ p = tokBuf;
+ m = n = 0;
+ c2 = 0;
+ s = NULL;
+ while (1) {
+ c = getChar();
+ if (c == '>') {
+ break;
+ } else if (c == EOF) {
+ error(getPos(), "Unterminated hex string");
+ break;
+ } else if (specialChars[c] != 1) {
+ c2 = c2 << 4;
+ if (c >= '0' && c <= '9')
+ c2 += c - '0';
+ else if (c >= 'A' && c <= 'F')
+ c2 += c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ c2 += c - 'a' + 10;
+ else
+ error(getPos(), "Illegal character <%02x> in hex string", c);
+ if (++m == 2) {
+ if (n == tokBufSize) {
+ if (!s)
+ s = new GString(tokBuf, tokBufSize);
+ else
+ s->append(tokBuf, tokBufSize);
+ p = tokBuf;
+ n = 0;
+ }
+ *p++ = (char)c2;
+ ++n;
+ c2 = 0;
+ m = 0;
+ }
+ }
+ }
+ if (!s)
+ s = new GString(tokBuf, n);
+ else
+ s->append(tokBuf, n);
+ if (m == 1)
+ s->append((char)(c2 << 4));
+ obj->initString(s);
+ }
+ break;
+
+ // dict punctuation
+ case '>':
+ c = lookChar();
+ if (c == '>') {
+ getChar();
+ tokBuf[0] = tokBuf[1] = '>';
+ tokBuf[2] = '\0';
+ obj->initCmd(tokBuf);
+ } else {
+ error(getPos(), "Illegal character '>'");
+ obj->initError();
+ }
+ break;
+
+ // error
+ case ')':
+ case '{':
+ case '}':
+ error(getPos(), "Illegal character '%c'", c);
+ obj->initError();
+ break;
+
+ // command
+ default:
+ p = tokBuf;
+ *p++ = c;
+ n = 1;
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
+ getChar();
+ if (++n == tokBufSize) {
+ error(getPos(), "Command token too long");
+ break;
+ }
+ *p++ = c;
+ }
+ *p = '\0';
+ if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
+ obj->initBool(gTrue);
+ } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
+ obj->initBool(gFalse);
+ } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
+ obj->initNull();
+ } else {
+ obj->initCmd(tokBuf);
+ }
+ break;
+ }
+
+ return obj;
+}
+
+void Lexer::skipToNextLine() {
+ int c;
+
+ while (1) {
+ c = getChar();
+ if (c == EOF || c == '\n') {
+ return;
+ }
+ if (c == '\r') {
+ if ((c = lookChar()) == '\n') {
+ getChar();
+ }
+ return;
+ }
+ }
+}
diff --git a/pdftops/Lexer.h b/pdftops/Lexer.h
new file mode 100644
index 000000000..653496d78
--- /dev/null
+++ b/pdftops/Lexer.h
@@ -0,0 +1,77 @@
+//========================================================================
+//
+// Lexer.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef LEXER_H
+#define LEXER_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+#include "Stream.h"
+
+class XRef;
+
+#define tokBufSize 128 // size of token buffer
+
+//------------------------------------------------------------------------
+// Lexer
+//------------------------------------------------------------------------
+
+class Lexer {
+public:
+
+ // Construct a lexer for a single stream. Deletes the stream when
+ // lexer is deleted.
+ Lexer(XRef *xref, Stream *str);
+
+ // Construct a lexer for a stream or array of streams (assumes obj
+ // is either a stream or array of streams).
+ Lexer(XRef *xref, Object *obj);
+
+ // Destructor.
+ ~Lexer();
+
+ // Get the next object from the input stream.
+ Object *getObj(Object *obj);
+
+ // Skip to the beginning of the next line in the input stream.
+ void skipToNextLine();
+
+ // Skip over one character.
+ void skipChar() { getChar(); }
+
+ // Get stream.
+ Stream *getStream()
+ { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); }
+
+ // Get current position in file. This is only used for error
+ // messages, so it returns an int instead of a Guint.
+ int getPos()
+ { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); }
+
+ // Set position in file.
+ void setPos(Guint pos, int dir = 0)
+ { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); }
+
+private:
+
+ int getChar();
+ int lookChar();
+
+ Array *streams; // array of input streams
+ int strPtr; // index of current stream
+ Object curStr; // current stream
+ GBool freeArray; // should lexer free the streams array?
+ char tokBuf[tokBufSize]; // temporary token buffer
+};
+
+#endif
diff --git a/pdftops/Link.cxx b/pdftops/Link.cxx
new file mode 100644
index 000000000..28d8b02ea
--- /dev/null
+++ b/pdftops/Link.cxx
@@ -0,0 +1,849 @@
+//========================================================================
+//
+// Link.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include "gmem.h"
+#include "GString.h"
+#include "Error.h"
+#include "Object.h"
+#include "Array.h"
+#include "Dict.h"
+#include "Link.h"
+
+//------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+LinkAction *LinkAction::parseDest(Object *obj) {
+ LinkAction *action;
+
+ action = new LinkGoTo(obj);
+ if (!action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
+ LinkAction *action;
+ Object obj2, obj3, obj4;
+
+ if (!obj->isDict()) {
+ error(-1, "Bad annotation action");
+ return NULL;
+ }
+
+ obj->dictLookup("S", &obj2);
+
+ // GoTo action
+ if (obj2.isName("GoTo")) {
+ obj->dictLookup("D", &obj3);
+ action = new LinkGoTo(&obj3);
+ obj3.free();
+
+ // GoToR action
+ } else if (obj2.isName("GoToR")) {
+ obj->dictLookup("F", &obj3);
+ obj->dictLookup("D", &obj4);
+ action = new LinkGoToR(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // Launch action
+ } else if (obj2.isName("Launch")) {
+ action = new LinkLaunch(obj);
+
+ // URI action
+ } else if (obj2.isName("URI")) {
+ obj->dictLookup("URI", &obj3);
+ action = new LinkURI(&obj3, baseURI);
+ obj3.free();
+
+ // Named action
+ } else if (obj2.isName("Named")) {
+ obj->dictLookup("N", &obj3);
+ action = new LinkNamed(&obj3);
+ obj3.free();
+
+ // Movie action
+ } else if (obj2.isName("Movie")) {
+ obj->dictLookupNF("Annot", &obj3);
+ obj->dictLookup("T", &obj4);
+ action = new LinkMovie(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // unknown action
+ } else if (obj2.isName()) {
+ action = new LinkUnknown(obj2.getName());
+
+ // action is missing or wrong type
+ } else {
+ error(-1, "Bad annotation action");
+ action = NULL;
+ }
+
+ obj2.free();
+
+ if (action && !action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
+ GString *name;
+ Object obj1;
+
+ name = NULL;
+
+ // string
+ if (fileSpecObj->isString()) {
+ name = fileSpecObj->getString()->copy();
+
+ // dictionary
+ } else if (fileSpecObj->isDict()) {
+ if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
+ obj1.free();
+ fileSpecObj->dictLookup("F", &obj1);
+ }
+ if (obj1.isString())
+ name = obj1.getString()->copy();
+ else
+ error(-1, "Illegal file spec in link");
+ obj1.free();
+
+ // error
+ } else {
+ error(-1, "Illegal file spec in link");
+ }
+
+ return name;
+}
+
+//------------------------------------------------------------------------
+// LinkDest
+//------------------------------------------------------------------------
+
+LinkDest::LinkDest(Array *a) {
+ Object obj1, obj2;
+
+ // initialize fields
+ left = bottom = right = top = zoom = 0;
+ ok = gFalse;
+
+ // get page
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
+ return;
+ }
+ a->getNF(0, &obj1);
+ if (obj1.isInt()) {
+ pageNum = obj1.getInt() + 1;
+ pageIsRef = gFalse;
+ } else if (obj1.isRef()) {
+ pageRef.num = obj1.getRefNum();
+ pageRef.gen = obj1.getRefGen();
+ pageIsRef = gTrue;
+ } else {
+ error(-1, "Bad annotation destination");
+ goto err2;
+ }
+ obj1.free();
+
+ // get destination type
+ a->get(1, &obj1);
+
+ // XYZ link
+ if (obj1.isName("XYZ")) {
+ kind = destXYZ;
+ if (a->getLength() < 3) {
+ changeLeft = gFalse;
+ } else {
+ a->get(2, &obj2);
+ if (obj2.isNull()) {
+ changeLeft = gFalse;
+ } else if (obj2.isNum()) {
+ changeLeft = gTrue;
+ left = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
+ }
+ if (a->getLength() < 4) {
+ changeTop = gFalse;
+ } else {
+ a->get(3, &obj2);
+ if (obj2.isNull()) {
+ changeTop = gFalse;
+ } else if (obj2.isNum()) {
+ changeTop = gTrue;
+ top = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
+ }
+ if (a->getLength() < 5) {
+ changeZoom = gFalse;
+ } else {
+ a->get(4, &obj2);
+ if (obj2.isNull()) {
+ changeZoom = gFalse;
+ } else if (obj2.isNum()) {
+ changeZoom = gTrue;
+ zoom = obj2.getNum();
+ } else {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ obj2.free();
+ }
+
+ // Fit link
+ } else if (obj1.isName("Fit")) {
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFit;
+
+ // FitH link
+ } else if (obj1.isName("FitH")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitH;
+ if (!a->get(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ top = obj2.getNum();
+ obj2.free();
+
+ // FitV link
+ } else if (obj1.isName("FitV")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitV;
+ if (!a->get(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ left = obj2.getNum();
+ obj2.free();
+
+ // FitR link
+ } else if (obj1.isName("FitR")) {
+ if (a->getLength() < 6) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitR;
+ if (!a->get(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ left = obj2.getNum();
+ obj2.free();
+ if (!a->get(3, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ bottom = obj2.getNum();
+ obj2.free();
+ if (!a->get(4, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ right = obj2.getNum();
+ obj2.free();
+ if (!a->get(5, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ top = obj2.getNum();
+ obj2.free();
+
+ // FitB link
+ } else if (obj1.isName("FitB")) {
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitB;
+
+ // FitBH link
+ } else if (obj1.isName("FitBH")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitBH;
+ if (!a->get(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ top = obj2.getNum();
+ obj2.free();
+
+ // FitBV link
+ } else if (obj1.isName("FitBV")) {
+ if (a->getLength() < 3) {
+ error(-1, "Annotation destination array is too short");
+ goto err2;
+ }
+ kind = destFitBV;
+ if (!a->get(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation destination position");
+ goto err1;
+ }
+ left = obj2.getNum();
+ obj2.free();
+
+ // unknown link kind
+ } else {
+ error(-1, "Unknown annotation destination type");
+ goto err2;
+ }
+
+ obj1.free();
+ ok = gTrue;
+ return;
+
+ err1:
+ obj2.free();
+ err2:
+ obj1.free();
+}
+
+LinkDest::LinkDest(LinkDest *dest) {
+ kind = dest->kind;
+ pageIsRef = dest->pageIsRef;
+ if (pageIsRef)
+ pageRef = dest->pageRef;
+ else
+ pageNum = dest->pageNum;
+ left = dest->left;
+ bottom = dest->bottom;
+ right = dest->right;
+ top = dest->top;
+ zoom = dest->zoom;
+ changeLeft = dest->changeLeft;
+ changeTop = dest->changeTop;
+ changeZoom = dest->changeZoom;
+ ok = gTrue;
+}
+
+//------------------------------------------------------------------------
+// LinkGoTo
+//------------------------------------------------------------------------
+
+LinkGoTo::LinkGoTo(Object *destObj) {
+ dest = NULL;
+ namedDest = NULL;
+
+ // named destination
+ if (destObj->isName()) {
+ namedDest = new GString(destObj->getName());
+ } else if (destObj->isString()) {
+ namedDest = destObj->getString()->copy();
+
+ // destination dictionary
+ } else if (destObj->isArray()) {
+ dest = new LinkDest(destObj->getArray());
+ if (!dest->isOk()) {
+ delete dest;
+ dest = NULL;
+ }
+
+ // error
+ } else {
+ error(-1, "Illegal annotation destination");
+ }
+}
+
+LinkGoTo::~LinkGoTo() {
+ if (dest)
+ delete dest;
+ if (namedDest)
+ delete namedDest;
+}
+
+//------------------------------------------------------------------------
+// LinkGoToR
+//------------------------------------------------------------------------
+
+LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
+ dest = NULL;
+ namedDest = NULL;
+
+ // get file name
+ fileName = getFileSpecName(fileSpecObj);
+
+ // named destination
+ if (destObj->isName()) {
+ namedDest = new GString(destObj->getName());
+ } else if (destObj->isString()) {
+ namedDest = destObj->getString()->copy();
+
+ // destination dictionary
+ } else if (destObj->isArray()) {
+ dest = new LinkDest(destObj->getArray());
+ if (!dest->isOk()) {
+ delete dest;
+ dest = NULL;
+ }
+
+ // error
+ } else {
+ error(-1, "Illegal annotation destination");
+ }
+}
+
+LinkGoToR::~LinkGoToR() {
+ if (fileName)
+ delete fileName;
+ if (dest)
+ delete dest;
+ if (namedDest)
+ delete namedDest;
+}
+
+
+//------------------------------------------------------------------------
+// LinkLaunch
+//------------------------------------------------------------------------
+
+LinkLaunch::LinkLaunch(Object *actionObj) {
+ Object obj1, obj2;
+
+ fileName = NULL;
+ params = NULL;
+
+ if (actionObj->isDict()) {
+ if (!actionObj->dictLookup("F", &obj1)->isNull()) {
+ fileName = getFileSpecName(&obj1);
+ } else {
+ obj1.free();
+#ifdef WIN32
+ if (actionObj->dictLookup("Win", &obj1)->isDict()) {
+ obj1.dictLookup("F", &obj2);
+ fileName = getFileSpecName(&obj2);
+ obj2.free();
+ if (obj1.dictLookup("P", &obj2)->isString()) {
+ params = obj2.getString()->copy();
+ }
+ obj2.free();
+ } else {
+ error(-1, "Bad launch-type link action");
+ }
+#else
+ //~ This hasn't been defined by Adobe yet, so assume it looks
+ //~ just like the Win dictionary until they say otherwise.
+ if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
+ obj1.dictLookup("F", &obj2);
+ fileName = getFileSpecName(&obj2);
+ obj2.free();
+ if (obj1.dictLookup("P", &obj2)->isString()) {
+ params = obj2.getString()->copy();
+ }
+ obj2.free();
+ } else {
+ error(-1, "Bad launch-type link action");
+ }
+#endif
+ }
+ obj1.free();
+ }
+}
+
+LinkLaunch::~LinkLaunch() {
+ if (fileName)
+ delete fileName;
+ if (params)
+ delete params;
+}
+
+//------------------------------------------------------------------------
+// LinkURI
+//------------------------------------------------------------------------
+
+LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
+ GString *uri2;
+ int n;
+ char c;
+
+ uri = NULL;
+ if (uriObj->isString()) {
+ uri2 = uriObj->getString()->copy();
+ if (baseURI) {
+ n = strcspn(uri2->getCString(), "/:");
+ if (n == uri2->getLength() || uri2->getChar(n) == '/') {
+ uri = baseURI->copy();
+ c = uri->getChar(uri->getLength() - 1);
+ if (c == '/' || c == '?') {
+ if (uri2->getChar(0) == '/') {
+ uri2->del(0);
+ }
+ } else {
+ if (uri2->getChar(0) != '/') {
+ uri->append('/');
+ }
+ }
+ uri->append(uri2);
+ delete uri2;
+ } else {
+ uri = uri2;
+ }
+ } else {
+ uri = uri2;
+ }
+ } else {
+ error(-1, "Illegal URI-type link");
+ }
+}
+
+LinkURI::~LinkURI() {
+ if (uri)
+ delete uri;
+}
+
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+LinkNamed::LinkNamed(Object *nameObj) {
+ name = NULL;
+ if (nameObj->isName()) {
+ name = new GString(nameObj->getName());
+ }
+}
+
+LinkNamed::~LinkNamed() {
+ if (name) {
+ delete name;
+ }
+}
+
+//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
+ annotRef.num = -1;
+ title = NULL;
+ if (annotObj->isRef()) {
+ annotRef = annotObj->getRef();
+ } else if (titleObj->isString()) {
+ title = titleObj->getString()->copy();
+ } else {
+ error(-1, "Movie action is missing both the Annot and T keys");
+ }
+}
+
+LinkMovie::~LinkMovie() {
+ if (title) {
+ delete title;
+ }
+}
+
+//------------------------------------------------------------------------
+// LinkUnknown
+//------------------------------------------------------------------------
+
+LinkUnknown::LinkUnknown(char *actionA) {
+ action = new GString(actionA);
+}
+
+LinkUnknown::~LinkUnknown() {
+ delete action;
+}
+
+//------------------------------------------------------------------------
+// LinkBorderStyle
+//------------------------------------------------------------------------
+
+LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA,
+ double *dashA, int dashLengthA,
+ double rA, double gA, double bA) {
+ type = typeA;
+ width = widthA;
+ dash = dashA;
+ dashLength = dashLengthA;
+ r = rA;
+ g = gA;
+ b = bA;
+}
+
+LinkBorderStyle::~LinkBorderStyle() {
+ if (dash) {
+ gfree(dash);
+ }
+}
+
+//------------------------------------------------------------------------
+// Link
+//------------------------------------------------------------------------
+
+Link::Link(Dict *dict, GString *baseURI) {
+ Object obj1, obj2, obj3;
+ LinkBorderType borderType;
+ double borderWidth;
+ double *borderDash;
+ int borderDashLength;
+ double borderR, borderG, borderB;
+ double t;
+ int i;
+
+ borderStyle = NULL;
+ action = NULL;
+ ok = gFalse;
+
+ // get rectangle
+ if (!dict->lookup("Rect", &obj1)->isArray()) {
+ error(-1, "Annotation rectangle is wrong type");
+ goto err2;
+ }
+ if (!obj1.arrayGet(0, &obj2)->isNum()) {
+ error(-1, "Bad annotation rectangle");
+ goto err1;
+ }
+ x1 = obj2.getNum();
+ obj2.free();
+ if (!obj1.arrayGet(1, &obj2)->isNum()) {
+ error(-1, "Bad annotation rectangle");
+ goto err1;
+ }
+ y1 = obj2.getNum();
+ obj2.free();
+ if (!obj1.arrayGet(2, &obj2)->isNum()) {
+ error(-1, "Bad annotation rectangle");
+ goto err1;
+ }
+ x2 = obj2.getNum();
+ obj2.free();
+ if (!obj1.arrayGet(3, &obj2)->isNum()) {
+ error(-1, "Bad annotation rectangle");
+ goto err1;
+ }
+ y2 = obj2.getNum();
+ obj2.free();
+ obj1.free();
+ if (x1 > x2) {
+ t = x1;
+ x1 = x2;
+ x2 = t;
+ }
+ if (y1 > y2) {
+ t = y1;
+ y1 = y2;
+ y2 = t;
+ }
+
+ // get the border style info
+ borderType = linkBorderSolid;
+ borderWidth = 1;
+ borderDash = NULL;
+ borderDashLength = 0;
+ borderR = 0;
+ borderG = 0;
+ borderB = 1;
+ if (dict->lookup("BS", &obj1)->isDict()) {
+ if (obj1.dictLookup("S", &obj2)->isName()) {
+ if (obj2.isName("S")) {
+ borderType = linkBorderSolid;
+ } else if (obj2.isName("D")) {
+ borderType = linkBorderDashed;
+ } else if (obj2.isName("B")) {
+ borderType = linkBorderEmbossed;
+ } else if (obj2.isName("I")) {
+ borderType = linkBorderEngraved;
+ } else if (obj2.isName("U")) {
+ borderType = linkBorderUnderlined;
+ }
+ }
+ obj2.free();
+ if (obj1.dictLookup("W", &obj2)->isNum()) {
+ borderWidth = obj2.getNum();
+ }
+ obj2.free();
+ if (obj1.dictLookup("D", &obj2)->isArray()) {
+ borderDashLength = obj2.arrayGetLength();
+ borderDash = (double *)gmalloc(borderDashLength * sizeof(double));
+ for (i = 0; i < borderDashLength; ++i) {
+ if (obj2.arrayGet(i, &obj3)->isNum()) {
+ borderDash[i] = obj3.getNum();
+ } else {
+ borderDash[i] = 1;
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ } else {
+ obj1.free();
+ if (dict->lookup("Border", &obj1)->isArray()) {
+ if (obj1.arrayGetLength() >= 3) {
+ if (obj1.arrayGet(2, &obj2)->isNum()) {
+ borderWidth = obj2.getNum();
+ }
+ obj2.free();
+ if (obj1.arrayGetLength() >= 4) {
+ if (obj1.arrayGet(3, &obj2)->isArray()) {
+ borderType = linkBorderDashed;
+ borderDashLength = obj2.arrayGetLength();
+ borderDash = (double *)gmalloc(borderDashLength * sizeof(double));
+ for (i = 0; i < borderDashLength; ++i) {
+ if (obj2.arrayGet(i, &obj3)->isNum()) {
+ borderDash[i] = obj3.getNum();
+ } else {
+ borderDash[i] = 1;
+ }
+ obj3.free();
+ }
+ }
+ obj2.free();
+ }
+ }
+ }
+ }
+ obj1.free();
+ if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
+ if (obj1.arrayGet(0, &obj2)->isNum()) {
+ borderR = obj2.getNum();
+ }
+ obj1.free();
+ if (obj1.arrayGet(1, &obj2)->isNum()) {
+ borderG = obj2.getNum();
+ }
+ obj1.free();
+ if (obj1.arrayGet(2, &obj2)->isNum()) {
+ borderB = obj2.getNum();
+ }
+ obj1.free();
+ }
+ obj1.free();
+ borderStyle = new LinkBorderStyle(borderType, borderWidth,
+ borderDash, borderDashLength,
+ borderR, borderG, borderB);
+
+ // look for destination
+ if (!dict->lookup("Dest", &obj1)->isNull()) {
+ action = LinkAction::parseDest(&obj1);
+
+ // look for action
+ } else {
+ obj1.free();
+ if (dict->lookup("A", &obj1)->isDict()) {
+ action = LinkAction::parseAction(&obj1, baseURI);
+ }
+ }
+ obj1.free();
+
+ // check for bad action
+ if (action) {
+ ok = gTrue;
+ }
+
+ return;
+
+ err1:
+ obj2.free();
+ err2:
+ obj1.free();
+}
+
+Link::~Link() {
+ if (borderStyle) {
+ delete borderStyle;
+ }
+ if (action) {
+ delete action;
+}
+}
+
+//------------------------------------------------------------------------
+// Links
+//------------------------------------------------------------------------
+
+Links::Links(Object *annots, GString *baseURI) {
+ Link *link;
+ Object obj1, obj2;
+ int size;
+ int i;
+
+ links = NULL;
+ size = 0;
+ numLinks = 0;
+
+ if (annots->isArray()) {
+ for (i = 0; i < annots->arrayGetLength(); ++i) {
+ if (annots->arrayGet(i, &obj1)->isDict()) {
+ if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
+ link = new Link(obj1.getDict(), baseURI);
+ if (link->isOk()) {
+ if (numLinks >= size) {
+ size += 16;
+ links = (Link **)grealloc(links, size * sizeof(Link *));
+ }
+ links[numLinks++] = link;
+ } else {
+ delete link;
+ }
+ }
+ obj2.free();
+ }
+ obj1.free();
+ }
+ }
+}
+
+Links::~Links() {
+ int i;
+
+ for (i = 0; i < numLinks; ++i)
+ delete links[i];
+ gfree(links);
+}
+
+LinkAction *Links::find(double x, double y) {
+ int i;
+
+ for (i = numLinks - 1; i >= 0; --i) {
+ if (links[i]->inRect(x, y)) {
+ return links[i]->getAction();
+ }
+ }
+ return NULL;
+}
+
+GBool Links::onLink(double x, double y) {
+ int i;
+
+ for (i = 0; i < numLinks; ++i) {
+ if (links[i]->inRect(x, y))
+ return gTrue;
+ }
+ return gFalse;
+}
diff --git a/pdftops/Link.h b/pdftops/Link.h
new file mode 100644
index 000000000..160b2b8cb
--- /dev/null
+++ b/pdftops/Link.h
@@ -0,0 +1,409 @@
+//========================================================================
+//
+// Link.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef LINK_H
+#define LINK_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+
+class GString;
+class Array;
+class Dict;
+
+//------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+enum LinkActionKind {
+ actionGoTo, // go to destination
+ actionGoToR, // go to destination in new file
+ actionLaunch, // launch app (or open document)
+ actionURI, // URI
+ actionNamed, // named action
+ actionMovie, // movie action
+ actionUnknown // anything else
+};
+
+class LinkAction {
+public:
+
+ // Destructor.
+ virtual ~LinkAction() {}
+
+ // Was the LinkAction created successfully?
+ virtual GBool isOk() = 0;
+
+ // Check link action type.
+ virtual LinkActionKind getKind() = 0;
+
+ // Parse a destination (old-style action) name, string, or array.
+ static LinkAction *parseDest(Object *obj);
+
+ // Parse an action dictionary.
+ static LinkAction *parseAction(Object *obj, GString *baseURI = NULL);
+
+ // Extract a file name from a file specification (string or
+ // dictionary).
+ static GString *getFileSpecName(Object *fileSpecObj);
+};
+
+//------------------------------------------------------------------------
+// LinkDest
+//------------------------------------------------------------------------
+
+enum LinkDestKind {
+ destXYZ,
+ destFit,
+ destFitH,
+ destFitV,
+ destFitR,
+ destFitB,
+ destFitBH,
+ destFitBV
+};
+
+class LinkDest {
+public:
+
+ // Build a LinkDest from the array.
+ LinkDest(Array *a);
+
+ // Copy a LinkDest.
+ LinkDest *copy() { return new LinkDest(this); }
+
+ // Was the LinkDest created successfully?
+ GBool isOk() { return ok; }
+
+ // Accessors.
+ LinkDestKind getKind() { return kind; }
+ GBool isPageRef() { return pageIsRef; }
+ int getPageNum() { return pageNum; }
+ Ref getPageRef() { return pageRef; }
+ double getLeft() { return left; }
+ double getBottom() { return bottom; }
+ double getRight() { return right; }
+ double getTop() { return top; }
+ double getZoom() { return zoom; }
+ GBool getChangeLeft() { return changeLeft; }
+ GBool getChangeTop() { return changeTop; }
+ GBool getChangeZoom() { return changeZoom; }
+
+private:
+
+ LinkDestKind kind; // destination type
+ GBool pageIsRef; // is the page a reference or number?
+ union {
+ Ref pageRef; // reference to page
+ int pageNum; // one-relative page number
+ };
+ double left, bottom; // position
+ double right, top;
+ double zoom; // zoom factor
+ GBool changeLeft, changeTop; // for destXYZ links, which position
+ GBool changeZoom; // components to change
+ GBool ok; // set if created successfully
+
+ LinkDest(LinkDest *dest);
+};
+
+//------------------------------------------------------------------------
+// LinkGoTo
+//------------------------------------------------------------------------
+
+class LinkGoTo: public LinkAction {
+public:
+
+ // Build a LinkGoTo from a destination (dictionary, name, or string).
+ LinkGoTo(Object *destObj);
+
+ // Destructor.
+ virtual ~LinkGoTo();
+
+ // Was the LinkGoTo created successfully?
+ virtual GBool isOk() { return dest || namedDest; }
+
+ // Accessors.
+ virtual LinkActionKind getKind() { return actionGoTo; }
+ LinkDest *getDest() { return dest; }
+ GString *getNamedDest() { return namedDest; }
+
+private:
+
+ LinkDest *dest; // regular destination (NULL for remote
+ // link with bad destination)
+ GString *namedDest; // named destination (only one of dest and
+ // and namedDest may be non-NULL)
+};
+
+//------------------------------------------------------------------------
+// LinkGoToR
+//------------------------------------------------------------------------
+
+class LinkGoToR: public LinkAction {
+public:
+
+ // Build a LinkGoToR from a file spec (dictionary) and destination
+ // (dictionary, name, or string).
+ LinkGoToR(Object *fileSpecObj, Object *destObj);
+
+ // Destructor.
+ virtual ~LinkGoToR();
+
+ // Was the LinkGoToR created successfully?
+ virtual GBool isOk() { return fileName && (dest || namedDest); }
+
+ // Accessors.
+ virtual LinkActionKind getKind() { return actionGoToR; }
+ GString *getFileName() { return fileName; }
+ LinkDest *getDest() { return dest; }
+ GString *getNamedDest() { return namedDest; }
+
+private:
+
+ GString *fileName; // file name
+ LinkDest *dest; // regular destination (NULL for remote
+ // link with bad destination)
+ GString *namedDest; // named destination (only one of dest and
+ // and namedDest may be non-NULL)
+};
+
+//------------------------------------------------------------------------
+// LinkLaunch
+//------------------------------------------------------------------------
+
+class LinkLaunch: public LinkAction {
+public:
+
+ // Build a LinkLaunch from an action dictionary.
+ LinkLaunch(Object *actionObj);
+
+ // Destructor.
+ virtual ~LinkLaunch();
+
+ // Was the LinkLaunch created successfully?
+ virtual GBool isOk() { return fileName != NULL; }
+
+ // Accessors.
+ virtual LinkActionKind getKind() { return actionLaunch; }
+ GString *getFileName() { return fileName; }
+ GString *getParams() { return params; }
+
+private:
+
+ GString *fileName; // file name
+ GString *params; // parameters
+};
+
+//------------------------------------------------------------------------
+// LinkURI
+//------------------------------------------------------------------------
+
+class LinkURI: public LinkAction {
+public:
+
+ // Build a LinkURI given the URI (string) and base URI.
+ LinkURI(Object *uriObj, GString *baseURI);
+
+ // Destructor.
+ virtual ~LinkURI();
+
+ // Was the LinkURI created successfully?
+ virtual GBool isOk() { return uri != NULL; }
+
+ // Accessors.
+ virtual LinkActionKind getKind() { return actionURI; }
+ GString *getURI() { return uri; }
+
+private:
+
+ GString *uri; // the URI
+};
+
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+class LinkNamed: public LinkAction {
+public:
+
+ // Build a LinkNamed given the action name.
+ LinkNamed(Object *nameObj);
+
+ virtual ~LinkNamed();
+
+ virtual GBool isOk() { return name != NULL; }
+
+ virtual LinkActionKind getKind() { return actionNamed; }
+ GString *getName() { return name; }
+
+private:
+
+ GString *name;
+};
+
+//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+class LinkMovie: public LinkAction {
+public:
+
+ LinkMovie(Object *annotObj, Object *titleObj);
+
+ virtual ~LinkMovie();
+
+ virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; }
+
+ virtual LinkActionKind getKind() { return actionMovie; }
+ GBool hasAnnotRef() { return annotRef.num >= 0; }
+ Ref *getAnnotRef() { return &annotRef; }
+ GString *getTitle() { return title; }
+
+private:
+
+ Ref annotRef;
+ GString *title;
+};
+
+//------------------------------------------------------------------------
+// LinkUnknown
+//------------------------------------------------------------------------
+
+class LinkUnknown: public LinkAction {
+public:
+
+ // Build a LinkUnknown with the specified action type.
+ LinkUnknown(char *actionA);
+
+ // Destructor.
+ virtual ~LinkUnknown();
+
+ // Was the LinkUnknown create successfully?
+ virtual GBool isOk() { return action != NULL; }
+
+ // Accessors.
+ virtual LinkActionKind getKind() { return actionUnknown; }
+ GString *getAction() { return action; }
+
+private:
+
+ GString *action; // action subtype
+};
+
+//------------------------------------------------------------------------
+// LinkBorderStyle
+//------------------------------------------------------------------------
+
+enum LinkBorderType {
+ linkBorderSolid,
+ linkBorderDashed,
+ linkBorderEmbossed,
+ linkBorderEngraved,
+ linkBorderUnderlined
+};
+
+class LinkBorderStyle {
+public:
+
+ LinkBorderStyle(LinkBorderType typeA, double widthA,
+ double *dashA, int dashLengthA,
+ double rA, double gA, double bA);
+ ~LinkBorderStyle();
+
+ LinkBorderType getType() { return type; }
+ double getWidth() { return width; }
+ void getDash(double **dashA, int *dashLengthA)
+ { *dashA = dash; *dashLengthA = dashLength; }
+ void getColor(double *rA, double *gA, double *bA)
+ { *rA = r; *gA = g; *bA = b; }
+
+private:
+
+ LinkBorderType type;
+ double width;
+ double *dash;
+ int dashLength;
+ double r, g, b;
+};
+
+//------------------------------------------------------------------------
+// Link
+//------------------------------------------------------------------------
+
+class Link {
+public:
+
+ // Construct a link, given its dictionary.
+ Link(Dict *dict, GString *baseURI);
+
+ // Destructor.
+ ~Link();
+
+ // Was the link created successfully?
+ GBool isOk() { return ok; }
+
+ // Check if point is inside the link rectangle.
+ GBool inRect(double x, double y)
+ { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
+
+ // Get action.
+ LinkAction *getAction() { return action; }
+
+ // Get the link rectangle.
+ void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
+ { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
+
+ // Get the border style info.
+ LinkBorderStyle *getBorderStyle() { return borderStyle; }
+
+private:
+
+ double x1, y1; // lower left corner
+ double x2, y2; // upper right corner
+ LinkBorderStyle *borderStyle; // border style
+ LinkAction *action; // action
+ GBool ok; // is link valid?
+};
+
+//------------------------------------------------------------------------
+// Links
+//------------------------------------------------------------------------
+
+class Links {
+public:
+
+ // Extract links from array of annotations.
+ Links(Object *annots, GString *baseURI);
+
+ // Destructor.
+ ~Links();
+
+ // Iterate through list of links.
+ int getNumLinks() { return numLinks; }
+ Link *getLink(int i) { return links[i]; }
+
+ // If point <x>,<y> is in a link, return the associated action;
+ // else return NULL.
+ LinkAction *find(double x, double y);
+
+ // Return true if <x>,<y> is in a link.
+ GBool onLink(double x, double y);
+
+private:
+
+ Link **links;
+ int numLinks;
+};
+
+#endif
diff --git a/pdftops/Makefile b/pdftops/Makefile
new file mode 100644
index 000000000..9a6385cca
--- /dev/null
+++ b/pdftops/Makefile
@@ -0,0 +1,127 @@
+#
+# "$Id$"
+#
+# pdftops filter Makefile for the Common UNIX Printing System (CUPS).
+#
+# CUPS filter changes Copyright 1997-2004 by Easy Software Products.
+# Xpdf code Copyright 1996-1999 by Derek B. Noonburg
+#
+
+
+include ../Makedefs
+
+#
+# Object files...
+#
+
+LIBOBJS = \
+ Annot.o \
+ Array.o \
+ BuiltinFont.o \
+ BuiltinFontTables.o \
+ Catalog.o \
+ CharCodeToUnicode.o \
+ CMap.o \
+ Decrypt.o \
+ Dict.o \
+ Error.o \
+ FontEncoding.o \
+ FontEncodingTables.o \
+ FontFile.o \
+ Function.o \
+ gfile.o \
+ Gfx.o \
+ GfxFont.o \
+ GfxState.o \
+ GHash.o \
+ GList.o \
+ GlobalParams.o \
+ gmem.o \
+ gmempp.o \
+ GString.o \
+ JBIG2Stream.o \
+ Lexer.o \
+ Link.o \
+ NameToCharCode.o \
+ Object.o \
+ Outline.o \
+ OutputDev.o \
+ Page.o \
+ Params.o \
+ parseargs.o \
+ Parser.o \
+ PDFDoc.o \
+ PDFDocEncoding.o \
+ PSOutputDev.o \
+ PSTokenizer.o \
+ Stream.o \
+ UnicodeMap.o \
+ XRef.o
+
+
+OBJS = pdftops.o $(LIBOBJS)
+
+#
+# Make everything...
+#
+
+all: pdftops
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS)
+ $(RM) libxpdf.a
+ $(RM) pdftops
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.cxx) gmem.c parseargs.c >/dev/null 2>&1
+
+
+#
+# Install the filter...
+#
+
+install: all
+ $(INSTALL_DIR) $(SERVERBIN)/filter
+ $(INSTALL_BIN) pdftops $(SERVERBIN)/filter
+
+
+#
+# pdftops
+#
+
+pdftops: libxpdf.a pdftops.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CXX) $(LDFLAGS) -o $@ pdftops.o libxpdf.a $(LIBS) $(CXXLIBS) -lm
+
+
+#
+# libxpdf.a
+#
+
+libxpdf.a: $(LIBOBJS)
+ echo Archiving $@...
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $(LIBOBJS)
+ $(RANLIB) $@
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/pdftops/NameToCharCode.cxx b/pdftops/NameToCharCode.cxx
new file mode 100644
index 000000000..d3603258a
--- /dev/null
+++ b/pdftops/NameToCharCode.cxx
@@ -0,0 +1,116 @@
+//========================================================================
+//
+// NameToCharCode.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <string.h>
+#include "gmem.h"
+#include "NameToCharCode.h"
+
+//------------------------------------------------------------------------
+
+struct NameToCharCodeEntry {
+ char *name;
+ CharCode c;
+};
+
+//------------------------------------------------------------------------
+
+NameToCharCode::NameToCharCode() {
+ int i;
+
+ size = 31;
+ len = 0;
+ tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
+ for (i = 0; i < size; ++i) {
+ tab[i].name = NULL;
+ }
+}
+
+NameToCharCode::~NameToCharCode() {
+ int i;
+
+ for (i = 0; i < size; ++i) {
+ if (tab[i].name) {
+ gfree(tab[i].name);
+ }
+ }
+ gfree(tab);
+}
+
+void NameToCharCode::add(const char *name, CharCode c) {
+ NameToCharCodeEntry *oldTab;
+ int h, i, oldSize;
+
+ // expand the table if necessary
+ if (len >= size / 2) {
+ oldSize = size;
+ oldTab = tab;
+ size = 2*size + 1;
+ tab = (NameToCharCodeEntry *)gmalloc(size * sizeof(NameToCharCodeEntry));
+ for (h = 0; h < size; ++h) {
+ tab[h].name = NULL;
+ }
+ for (i = 0; i < oldSize; ++i) {
+ if (oldTab[i].name) {
+ h = hash(oldTab[i].name);
+ while (tab[h].name) {
+ if (++h == size) {
+ h = 0;
+ }
+ }
+ tab[h] = oldTab[i];
+ }
+ }
+ gfree(oldTab);
+ }
+
+ // add the new name
+ h = hash(name);
+ while (tab[h].name && strcmp(tab[h].name, name)) {
+ if (++h == size) {
+ h = 0;
+ }
+ }
+ if (!tab[h].name) {
+ tab[h].name = copyString(name);
+ }
+ tab[h].c = c;
+
+ ++len;
+}
+
+CharCode NameToCharCode::lookup(const char *name) {
+ int h;
+
+ h = hash(name);
+ while (tab[h].name) {
+ if (!strcmp(tab[h].name, name)) {
+ return tab[h].c;
+ }
+ if (++h == size) {
+ h = 0;
+ }
+ }
+ return 0;
+}
+
+int NameToCharCode::hash(const char *name) {
+ const char *p;
+ unsigned int h;
+
+ h = 0;
+ for (p = name; *p; ++p) {
+ h = 17 * h + (int)(*p & 0xff);
+ }
+ return (int)(h % size);
+}
diff --git a/pdftops/NameToCharCode.h b/pdftops/NameToCharCode.h
new file mode 100644
index 000000000..d5ab3a3a1
--- /dev/null
+++ b/pdftops/NameToCharCode.h
@@ -0,0 +1,42 @@
+//========================================================================
+//
+// NameToCharCode.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef NAMETOCHARCODE_H
+#define NAMETOCHARCODE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "CharTypes.h"
+
+struct NameToCharCodeEntry;
+
+//------------------------------------------------------------------------
+
+class NameToCharCode {
+public:
+
+ NameToCharCode();
+ ~NameToCharCode();
+
+ void add(const char *name, CharCode c);
+ CharCode lookup(const char *name);
+
+private:
+
+ int hash(const char *name);
+
+ NameToCharCodeEntry *tab;
+ int size;
+ int len;
+};
+
+#endif
diff --git a/pdftops/NameToUnicodeTable.h b/pdftops/NameToUnicodeTable.h
new file mode 100644
index 000000000..6c24d12b3
--- /dev/null
+++ b/pdftops/NameToUnicodeTable.h
@@ -0,0 +1,1097 @@
+//========================================================================
+//
+// NameToUnicodeTable.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+static struct {
+ Unicode u;
+ const char *name;
+} nameToUnicodeTab[] = {
+ {0x0021, "!"},
+ {0x0023, "#"},
+ {0x0024, "$"},
+ {0x0025, "%"},
+ {0x0026, "&"},
+ {0x0027, "'"},
+ {0x0028, "("},
+ {0x0029, ")"},
+ {0x002a, "*"},
+ {0x002b, "+"},
+ {0x002c, ","},
+ {0x002d, "-"},
+ {0x002e, "."},
+ {0x002f, "/"},
+ {0x0030, "0"},
+ {0x0031, "1"},
+ {0x0032, "2"},
+ {0x0033, "3"},
+ {0x0034, "4"},
+ {0x0035, "5"},
+ {0x0036, "6"},
+ {0x0037, "7"},
+ {0x0038, "8"},
+ {0x0039, "9"},
+ {0x003a, ":"},
+ {0x003b, ";"},
+ {0x003c, "<"},
+ {0x003d, "="},
+ {0x003e, ">"},
+ {0x003f, "?"},
+ {0x0040, "@"},
+ {0x0041, "A"},
+ {0x00c6, "AE"},
+ {0x01fc, "AEacute"},
+ {0x00c6, "AEsmall"},
+ {0x00c1, "Aacute"},
+ {0x00c1, "Aacutesmall"},
+ {0x0102, "Abreve"},
+ {0x00c2, "Acircumflex"},
+ {0x00c2, "Acircumflexsmall"},
+ {0xf6c9, "Acute"},
+ {0xf6c9, "Acutesmall"},
+ {0x00c4, "Adieresis"},
+ {0x00c4, "Adieresissmall"},
+ {0x00c0, "Agrave"},
+ {0x00c0, "Agravesmall"},
+ {0x0391, "Alpha"},
+ {0x0386, "Alphatonos"},
+ {0x0100, "Amacron"},
+ {0x0104, "Aogonek"},
+ {0x00c5, "Aring"},
+ {0x01fa, "Aringacute"},
+ {0x00c5, "Aringsmall"},
+ {0x0041, "Asmall"},
+ {0x00c3, "Atilde"},
+ {0x00c3, "Atildesmall"},
+ {0x0042, "B"},
+ {0x0392, "Beta"},
+ {0xf6f4, "Brevesmall"},
+ {0x0042, "Bsmall"},
+ {0x0043, "C"},
+ {0x0106, "Cacute"},
+ {0xf6ca, "Caron"},
+ {0xf6ca, "Caronsmall"},
+ {0x010c, "Ccaron"},
+ {0x00c7, "Ccedilla"},
+ {0x00c7, "Ccedillasmall"},
+ {0x0108, "Ccircumflex"},
+ {0x010a, "Cdotaccent"},
+ {0xf7b8, "Cedillasmall"},
+ {0x03a7, "Chi"},
+ {0xf6f6, "Circumflexsmall"},
+ {0x0043, "Csmall"},
+ {0x0044, "D"},
+ {0x010e, "Dcaron"},
+ {0x0110, "Dcroat"},
+ {0x2206, "Delta"},
+ {0xf6cb, "Dieresis"},
+ {0xf6cc, "DieresisAcute"},
+ {0xf6cd, "DieresisGrave"},
+ {0xf6cb, "Dieresissmall"},
+ {0xf6f7, "Dotaccentsmall"},
+ {0x0044, "Dsmall"},
+ {0x0045, "E"},
+ {0x00c9, "Eacute"},
+ {0x00c9, "Eacutesmall"},
+ {0x0114, "Ebreve"},
+ {0x011a, "Ecaron"},
+ {0x00ca, "Ecircumflex"},
+ {0x00ca, "Ecircumflexsmall"},
+ {0x00cb, "Edieresis"},
+ {0x00cb, "Edieresissmall"},
+ {0x0116, "Edotaccent"},
+ {0x00c8, "Egrave"},
+ {0x00c8, "Egravesmall"},
+ {0x0112, "Emacron"},
+ {0x014a, "Eng"},
+ {0x0118, "Eogonek"},
+ {0x0395, "Epsilon"},
+ {0x0388, "Epsilontonos"},
+ {0x0045, "Esmall"},
+ {0x0397, "Eta"},
+ {0x0389, "Etatonos"},
+ {0x00d0, "Eth"},
+ {0x00d0, "Ethsmall"},
+ {0x20ac, "Euro"},
+ {0x0046, "F"},
+ {0x0046, "Fsmall"},
+ {0x0047, "G"},
+ {0x0393, "Gamma"},
+ {0x011e, "Gbreve"},
+ {0x01e6, "Gcaron"},
+ {0x011c, "Gcircumflex"},
+ {0x0122, "Gcommaaccent"},
+ {0x0120, "Gdotaccent"},
+ {0xf6ce, "Grave"},
+ {0xf6ce, "Gravesmall"},
+ {0x0047, "Gsmall"},
+ {0x0048, "H"},
+ {0x25cf, "H18533"},
+ {0x25aa, "H18543"},
+ {0x25ab, "H18551"},
+ {0x25a1, "H22073"},
+ {0x0126, "Hbar"},
+ {0x0124, "Hcircumflex"},
+ {0x0048, "Hsmall"},
+ {0xf6cf, "Hungarumlaut"},
+ {0xf6cf, "Hungarumlautsmall"},
+ {0x0049, "I"},
+ {0x0132, "IJ"},
+ {0x00cd, "Iacute"},
+ {0x00cd, "Iacutesmall"},
+ {0x012c, "Ibreve"},
+ {0x00ce, "Icircumflex"},
+ {0x00ce, "Icircumflexsmall"},
+ {0x00cf, "Idieresis"},
+ {0x00cf, "Idieresissmall"},
+ {0x0130, "Idotaccent"},
+ {0x2111, "Ifraktur"},
+ {0x00cc, "Igrave"},
+ {0x00cc, "Igravesmall"},
+ {0x012a, "Imacron"},
+ {0x012e, "Iogonek"},
+ {0x0399, "Iota"},
+ {0x03aa, "Iotadieresis"},
+ {0x038a, "Iotatonos"},
+ {0x0049, "Ismall"},
+ {0x0128, "Itilde"},
+ {0x004a, "J"},
+ {0x0134, "Jcircumflex"},
+ {0x004a, "Jsmall"},
+ {0x004b, "K"},
+ {0x039a, "Kappa"},
+ {0x0136, "Kcommaaccent"},
+ {0x004b, "Ksmall"},
+ {0x004c, "L"},
+ {0xf6bf, "LL"},
+ {0x0139, "Lacute"},
+ {0x039b, "Lambda"},
+ {0x013d, "Lcaron"},
+ {0x013b, "Lcommaaccent"},
+ {0x013f, "Ldot"},
+ {0x0141, "Lslash"},
+ {0x0141, "Lslashsmall"},
+ {0x004c, "Lsmall"},
+ {0x004d, "M"},
+ {0xf6d0, "Macron"},
+ {0xf6d0, "Macronsmall"},
+ {0x004d, "Msmall"},
+ {0x039c, "Mu"},
+ {0x004e, "N"},
+ {0x0143, "Nacute"},
+ {0x0147, "Ncaron"},
+ {0x0145, "Ncommaaccent"},
+ {0x004e, "Nsmall"},
+ {0x00d1, "Ntilde"},
+ {0x00d1, "Ntildesmall"},
+ {0x039d, "Nu"},
+ {0x004f, "O"},
+ {0x0152, "OE"},
+ {0x0152, "OEsmall"},
+ {0x00d3, "Oacute"},
+ {0x00d3, "Oacutesmall"},
+ {0x014e, "Obreve"},
+ {0x00d4, "Ocircumflex"},
+ {0x00d4, "Ocircumflexsmall"},
+ {0x00d6, "Odieresis"},
+ {0x00d6, "Odieresissmall"},
+ {0xf6fb, "Ogoneksmall"},
+ {0x00d2, "Ograve"},
+ {0x00d2, "Ogravesmall"},
+ {0x01a0, "Ohorn"},
+ {0x0150, "Ohungarumlaut"},
+ {0x014c, "Omacron"},
+ {0x2126, "Omega"},
+ {0x038f, "Omegatonos"},
+ {0x039f, "Omicron"},
+ {0x038c, "Omicrontonos"},
+ {0x00d8, "Oslash"},
+ {0x01fe, "Oslashacute"},
+ {0x00d8, "Oslashsmall"},
+ {0x004f, "Osmall"},
+ {0x00d5, "Otilde"},
+ {0x00d5, "Otildesmall"},
+ {0x0050, "P"},
+ {0x03a6, "Phi"},
+ {0x03a0, "Pi"},
+ {0x03a8, "Psi"},
+ {0x0050, "Psmall"},
+ {0x0051, "Q"},
+ {0x0051, "Qsmall"},
+ {0x0052, "R"},
+ {0x0154, "Racute"},
+ {0x0158, "Rcaron"},
+ {0x0156, "Rcommaaccent"},
+ {0x211c, "Rfraktur"},
+ {0x03a1, "Rho"},
+ {0xf6fc, "Ringsmall"},
+ {0x0052, "Rsmall"},
+ {0x0053, "S"},
+ {0x250c, "SF010000"},
+ {0x2514, "SF020000"},
+ {0x2510, "SF030000"},
+ {0x2518, "SF040000"},
+ {0x253c, "SF050000"},
+ {0x252c, "SF060000"},
+ {0x2534, "SF070000"},
+ {0x251c, "SF080000"},
+ {0x2524, "SF090000"},
+ {0x2500, "SF100000"},
+ {0x2502, "SF110000"},
+ {0x2561, "SF190000"},
+ {0x2562, "SF200000"},
+ {0x2556, "SF210000"},
+ {0x2555, "SF220000"},
+ {0x2563, "SF230000"},
+ {0x2551, "SF240000"},
+ {0x2557, "SF250000"},
+ {0x255d, "SF260000"},
+ {0x255c, "SF270000"},
+ {0x255b, "SF280000"},
+ {0x255e, "SF360000"},
+ {0x255f, "SF370000"},
+ {0x255a, "SF380000"},
+ {0x2554, "SF390000"},
+ {0x2569, "SF400000"},
+ {0x2566, "SF410000"},
+ {0x2560, "SF420000"},
+ {0x2550, "SF430000"},
+ {0x256c, "SF440000"},
+ {0x2567, "SF450000"},
+ {0x2568, "SF460000"},
+ {0x2564, "SF470000"},
+ {0x2565, "SF480000"},
+ {0x2559, "SF490000"},
+ {0x2558, "SF500000"},
+ {0x2552, "SF510000"},
+ {0x2553, "SF520000"},
+ {0x256b, "SF530000"},
+ {0x256a, "SF540000"},
+ {0x015a, "Sacute"},
+ {0x0160, "Scaron"},
+ {0x0160, "Scaronsmall"},
+ {0x015e, "Scedilla"},
+ {0x015c, "Scircumflex"},
+ {0x0218, "Scommaaccent"},
+ {0x03a3, "Sigma"},
+ {0x0053, "Ssmall"},
+ {0x0054, "T"},
+ {0x03a4, "Tau"},
+ {0x0166, "Tbar"},
+ {0x0164, "Tcaron"},
+ {0x0162, "Tcommaaccent"},
+ {0x0398, "Theta"},
+ {0x00de, "Thorn"},
+ {0x00de, "Thornsmall"},
+ {0xf6fe, "Tildesmall"},
+ {0x0054, "Tsmall"},
+ {0x0055, "U"},
+ {0x00da, "Uacute"},
+ {0x00da, "Uacutesmall"},
+ {0x016c, "Ubreve"},
+ {0x00db, "Ucircumflex"},
+ {0x00db, "Ucircumflexsmall"},
+ {0x00dc, "Udieresis"},
+ {0x00dc, "Udieresissmall"},
+ {0x00d9, "Ugrave"},
+ {0x00d9, "Ugravesmall"},
+ {0x01af, "Uhorn"},
+ {0x0170, "Uhungarumlaut"},
+ {0x016a, "Umacron"},
+ {0x0172, "Uogonek"},
+ {0x03a5, "Upsilon"},
+ {0x03d2, "Upsilon1"},
+ {0x03ab, "Upsilondieresis"},
+ {0x038e, "Upsilontonos"},
+ {0x016e, "Uring"},
+ {0x0055, "Usmall"},
+ {0x0168, "Utilde"},
+ {0x0056, "V"},
+ {0x0056, "Vsmall"},
+ {0x0057, "W"},
+ {0x1e82, "Wacute"},
+ {0x0174, "Wcircumflex"},
+ {0x1e84, "Wdieresis"},
+ {0x1e80, "Wgrave"},
+ {0x0057, "Wsmall"},
+ {0x0058, "X"},
+ {0x039e, "Xi"},
+ {0x0058, "Xsmall"},
+ {0x0059, "Y"},
+ {0x00dd, "Yacute"},
+ {0x00dd, "Yacutesmall"},
+ {0x0176, "Ycircumflex"},
+ {0x0178, "Ydieresis"},
+ {0x0178, "Ydieresissmall"},
+ {0x1ef2, "Ygrave"},
+ {0x0059, "Ysmall"},
+ {0x005a, "Z"},
+ {0x0179, "Zacute"},
+ {0x017d, "Zcaron"},
+ {0x017d, "Zcaronsmall"},
+ {0x017b, "Zdotaccent"},
+ {0x0396, "Zeta"},
+ {0x005a, "Zsmall"},
+ {0x0022, "\""},
+ {0x005c, "\\"},
+ {0x005d, "]"},
+ {0x005e, "^"},
+ {0x005f, "_"},
+ {0x0060, "`"},
+ {0x0061, "a"},
+ {0x00e1, "aacute"},
+ {0x0103, "abreve"},
+ {0x00e2, "acircumflex"},
+ {0x00b4, "acute"},
+ {0x0301, "acutecomb"},
+ {0x00e4, "adieresis"},
+ {0x00e6, "ae"},
+ {0x01fd, "aeacute"},
+ {0x2015, "afii00208"},
+ {0x0410, "afii10017"},
+ {0x0411, "afii10018"},
+ {0x0412, "afii10019"},
+ {0x0413, "afii10020"},
+ {0x0414, "afii10021"},
+ {0x0415, "afii10022"},
+ {0x0401, "afii10023"},
+ {0x0416, "afii10024"},
+ {0x0417, "afii10025"},
+ {0x0418, "afii10026"},
+ {0x0419, "afii10027"},
+ {0x041a, "afii10028"},
+ {0x041b, "afii10029"},
+ {0x041c, "afii10030"},
+ {0x041d, "afii10031"},
+ {0x041e, "afii10032"},
+ {0x041f, "afii10033"},
+ {0x0420, "afii10034"},
+ {0x0421, "afii10035"},
+ {0x0422, "afii10036"},
+ {0x0423, "afii10037"},
+ {0x0424, "afii10038"},
+ {0x0425, "afii10039"},
+ {0x0426, "afii10040"},
+ {0x0427, "afii10041"},
+ {0x0428, "afii10042"},
+ {0x0429, "afii10043"},
+ {0x042a, "afii10044"},
+ {0x042b, "afii10045"},
+ {0x042c, "afii10046"},
+ {0x042d, "afii10047"},
+ {0x042e, "afii10048"},
+ {0x042f, "afii10049"},
+ {0x0490, "afii10050"},
+ {0x0402, "afii10051"},
+ {0x0403, "afii10052"},
+ {0x0404, "afii10053"},
+ {0x0405, "afii10054"},
+ {0x0406, "afii10055"},
+ {0x0407, "afii10056"},
+ {0x0408, "afii10057"},
+ {0x0409, "afii10058"},
+ {0x040a, "afii10059"},
+ {0x040b, "afii10060"},
+ {0x040c, "afii10061"},
+ {0x040e, "afii10062"},
+ {0xf6c4, "afii10063"},
+ {0xf6c5, "afii10064"},
+ {0x0430, "afii10065"},
+ {0x0431, "afii10066"},
+ {0x0432, "afii10067"},
+ {0x0433, "afii10068"},
+ {0x0434, "afii10069"},
+ {0x0435, "afii10070"},
+ {0x0451, "afii10071"},
+ {0x0436, "afii10072"},
+ {0x0437, "afii10073"},
+ {0x0438, "afii10074"},
+ {0x0439, "afii10075"},
+ {0x043a, "afii10076"},
+ {0x043b, "afii10077"},
+ {0x043c, "afii10078"},
+ {0x043d, "afii10079"},
+ {0x043e, "afii10080"},
+ {0x043f, "afii10081"},
+ {0x0440, "afii10082"},
+ {0x0441, "afii10083"},
+ {0x0442, "afii10084"},
+ {0x0443, "afii10085"},
+ {0x0444, "afii10086"},
+ {0x0445, "afii10087"},
+ {0x0446, "afii10088"},
+ {0x0447, "afii10089"},
+ {0x0448, "afii10090"},
+ {0x0449, "afii10091"},
+ {0x044a, "afii10092"},
+ {0x044b, "afii10093"},
+ {0x044c, "afii10094"},
+ {0x044d, "afii10095"},
+ {0x044e, "afii10096"},
+ {0x044f, "afii10097"},
+ {0x0491, "afii10098"},
+ {0x0452, "afii10099"},
+ {0x0453, "afii10100"},
+ {0x0454, "afii10101"},
+ {0x0455, "afii10102"},
+ {0x0456, "afii10103"},
+ {0x0457, "afii10104"},
+ {0x0458, "afii10105"},
+ {0x0459, "afii10106"},
+ {0x045a, "afii10107"},
+ {0x045b, "afii10108"},
+ {0x045c, "afii10109"},
+ {0x045e, "afii10110"},
+ {0x040f, "afii10145"},
+ {0x0462, "afii10146"},
+ {0x0472, "afii10147"},
+ {0x0474, "afii10148"},
+ {0xf6c6, "afii10192"},
+ {0x045f, "afii10193"},
+ {0x0463, "afii10194"},
+ {0x0473, "afii10195"},
+ {0x0475, "afii10196"},
+ {0xf6c7, "afii10831"},
+ {0xf6c8, "afii10832"},
+ {0x04d9, "afii10846"},
+ {0x200e, "afii299"},
+ {0x200f, "afii300"},
+ {0x200d, "afii301"},
+ {0x066a, "afii57381"},
+ {0x060c, "afii57388"},
+ {0x0660, "afii57392"},
+ {0x0661, "afii57393"},
+ {0x0662, "afii57394"},
+ {0x0663, "afii57395"},
+ {0x0664, "afii57396"},
+ {0x0665, "afii57397"},
+ {0x0666, "afii57398"},
+ {0x0667, "afii57399"},
+ {0x0668, "afii57400"},
+ {0x0669, "afii57401"},
+ {0x061b, "afii57403"},
+ {0x061f, "afii57407"},
+ {0x0621, "afii57409"},
+ {0x0622, "afii57410"},
+ {0x0623, "afii57411"},
+ {0x0624, "afii57412"},
+ {0x0625, "afii57413"},
+ {0x0626, "afii57414"},
+ {0x0627, "afii57415"},
+ {0x0628, "afii57416"},
+ {0x0629, "afii57417"},
+ {0x062a, "afii57418"},
+ {0x062b, "afii57419"},
+ {0x062c, "afii57420"},
+ {0x062d, "afii57421"},
+ {0x062e, "afii57422"},
+ {0x062f, "afii57423"},
+ {0x0630, "afii57424"},
+ {0x0631, "afii57425"},
+ {0x0632, "afii57426"},
+ {0x0633, "afii57427"},
+ {0x0634, "afii57428"},
+ {0x0635, "afii57429"},
+ {0x0636, "afii57430"},
+ {0x0637, "afii57431"},
+ {0x0638, "afii57432"},
+ {0x0639, "afii57433"},
+ {0x063a, "afii57434"},
+ {0x0640, "afii57440"},
+ {0x0641, "afii57441"},
+ {0x0642, "afii57442"},
+ {0x0643, "afii57443"},
+ {0x0644, "afii57444"},
+ {0x0645, "afii57445"},
+ {0x0646, "afii57446"},
+ {0x0648, "afii57448"},
+ {0x0649, "afii57449"},
+ {0x064a, "afii57450"},
+ {0x064b, "afii57451"},
+ {0x064c, "afii57452"},
+ {0x064d, "afii57453"},
+ {0x064e, "afii57454"},
+ {0x064f, "afii57455"},
+ {0x0650, "afii57456"},
+ {0x0651, "afii57457"},
+ {0x0652, "afii57458"},
+ {0x0647, "afii57470"},
+ {0x06a4, "afii57505"},
+ {0x067e, "afii57506"},
+ {0x0686, "afii57507"},
+ {0x0698, "afii57508"},
+ {0x06af, "afii57509"},
+ {0x0679, "afii57511"},
+ {0x0688, "afii57512"},
+ {0x0691, "afii57513"},
+ {0x06ba, "afii57514"},
+ {0x06d2, "afii57519"},
+ {0x06d5, "afii57534"},
+ {0x20aa, "afii57636"},
+ {0x05be, "afii57645"},
+ {0x05c3, "afii57658"},
+ {0x05d0, "afii57664"},
+ {0x05d1, "afii57665"},
+ {0x05d2, "afii57666"},
+ {0x05d3, "afii57667"},
+ {0x05d4, "afii57668"},
+ {0x05d5, "afii57669"},
+ {0x05d6, "afii57670"},
+ {0x05d7, "afii57671"},
+ {0x05d8, "afii57672"},
+ {0x05d9, "afii57673"},
+ {0x05da, "afii57674"},
+ {0x05db, "afii57675"},
+ {0x05dc, "afii57676"},
+ {0x05dd, "afii57677"},
+ {0x05de, "afii57678"},
+ {0x05df, "afii57679"},
+ {0x05e0, "afii57680"},
+ {0x05e1, "afii57681"},
+ {0x05e2, "afii57682"},
+ {0x05e3, "afii57683"},
+ {0x05e4, "afii57684"},
+ {0x05e5, "afii57685"},
+ {0x05e6, "afii57686"},
+ {0x05e7, "afii57687"},
+ {0x05e8, "afii57688"},
+ {0x05e9, "afii57689"},
+ {0x05ea, "afii57690"},
+ {0xfb2a, "afii57694"},
+ {0xfb2b, "afii57695"},
+ {0xfb4b, "afii57700"},
+ {0xfb1f, "afii57705"},
+ {0x05f0, "afii57716"},
+ {0x05f1, "afii57717"},
+ {0x05f2, "afii57718"},
+ {0xfb35, "afii57723"},
+ {0x05b4, "afii57793"},
+ {0x05b5, "afii57794"},
+ {0x05b6, "afii57795"},
+ {0x05bb, "afii57796"},
+ {0x05b8, "afii57797"},
+ {0x05b7, "afii57798"},
+ {0x05b0, "afii57799"},
+ {0x05b2, "afii57800"},
+ {0x05b1, "afii57801"},
+ {0x05b3, "afii57802"},
+ {0x05c2, "afii57803"},
+ {0x05c1, "afii57804"},
+ {0x05b9, "afii57806"},
+ {0x05bc, "afii57807"},
+ {0x05bd, "afii57839"},
+ {0x05bf, "afii57841"},
+ {0x05c0, "afii57842"},
+ {0x02bc, "afii57929"},
+ {0x2105, "afii61248"},
+ {0x2113, "afii61289"},
+ {0x2116, "afii61352"},
+ {0x202c, "afii61573"},
+ {0x202d, "afii61574"},
+ {0x202e, "afii61575"},
+ {0x200c, "afii61664"},
+ {0x066d, "afii63167"},
+ {0x02bd, "afii64937"},
+ {0x00e0, "agrave"},
+ {0x2135, "aleph"},
+ {0x03b1, "alpha"},
+ {0x03ac, "alphatonos"},
+ {0x0101, "amacron"},
+ {0x0026, "ampersand"},
+ {0x0026, "ampersandsmall"},
+ {0x2220, "angle"},
+ {0x2329, "angleleft"},
+ {0x232a, "angleright"},
+ {0x0387, "anoteleia"},
+ {0x0105, "aogonek"},
+ {0x2248, "approxequal"},
+ {0x00e5, "aring"},
+ {0x01fb, "aringacute"},
+ {0x2194, "arrowboth"},
+ {0x21d4, "arrowdblboth"},
+ {0x21d3, "arrowdbldown"},
+ {0x21d0, "arrowdblleft"},
+ {0x21d2, "arrowdblright"},
+ {0x21d1, "arrowdblup"},
+ {0x2193, "arrowdown"},
+ {0xf8e7, "arrowhorizex"},
+ {0x2190, "arrowleft"},
+ {0x2192, "arrowright"},
+ {0x2191, "arrowup"},
+ {0x2195, "arrowupdn"},
+ {0x21a8, "arrowupdnbse"},
+ {0xf8e6, "arrowvertex"},
+ {0x005e, "asciicircum"},
+ {0x007e, "asciitilde"},
+ {0x002a, "asterisk"},
+ {0x2217, "asteriskmath"},
+ {0xf6e9, "asuperior"},
+ {0x0040, "at"},
+ {0x00e3, "atilde"},
+ {0x0062, "b"},
+ {0x005c, "backslash"},
+ {0x007c, "bar"},
+ {0x03b2, "beta"},
+ {0x2588, "block"},
+ {0xf8f4, "braceex"},
+ {0x007b, "braceleft"},
+ {0xf8f3, "braceleftbt"},
+ {0xf8f2, "braceleftmid"},
+ {0xf8f1, "bracelefttp"},
+ {0x007d, "braceright"},
+ {0xf8fe, "bracerightbt"},
+ {0xf8fd, "bracerightmid"},
+ {0xf8fc, "bracerighttp"},
+ {0x005b, "bracketleft"},
+ {0xf8f0, "bracketleftbt"},
+ {0xf8ef, "bracketleftex"},
+ {0xf8ee, "bracketlefttp"},
+ {0x005d, "bracketright"},
+ {0xf8fb, "bracketrightbt"},
+ {0xf8fa, "bracketrightex"},
+ {0xf8f9, "bracketrighttp"},
+ {0x02d8, "breve"},
+ {0x00a6, "brokenbar"},
+ {0xf6ea, "bsuperior"},
+ {0x2022, "bullet"},
+ {0x0063, "c"},
+ {0x0107, "cacute"},
+ {0x02c7, "caron"},
+ {0x21b5, "carriagereturn"},
+ {0x010d, "ccaron"},
+ {0x00e7, "ccedilla"},
+ {0x0109, "ccircumflex"},
+ {0x010b, "cdotaccent"},
+ {0x00b8, "cedilla"},
+ {0x00a2, "cent"},
+ {0xf6df, "centinferior"},
+ {0x00a2, "centoldstyle"},
+ {0xf6e0, "centsuperior"},
+ {0x03c7, "chi"},
+ {0x25cb, "circle"},
+ {0x2297, "circlemultiply"},
+ {0x2295, "circleplus"},
+ {0x02c6, "circumflex"},
+ {0x2663, "club"},
+ {0x003a, "colon"},
+ {0x20a1, "colonmonetary"},
+ {0x002c, "comma"},
+ {0xf6c3, "commaaccent"},
+ {0xf6e1, "commainferior"},
+ {0xf6e2, "commasuperior"},
+ {0x2245, "congruent"},
+ {0x00a9, "copyright"},
+ {0x00a9, "copyrightsans"},
+ {0x00a9, "copyrightserif"},
+ {0x00a4, "currency"},
+ {0xf6d1, "cyrBreve"},
+ {0xf6d2, "cyrFlex"},
+ {0xf6d4, "cyrbreve"},
+ {0xf6d5, "cyrflex"},
+ {0x0064, "d"},
+ {0x2020, "dagger"},
+ {0x2021, "daggerdbl"},
+ {0xf6d3, "dblGrave"},
+ {0xf6d6, "dblgrave"},
+ {0x010f, "dcaron"},
+ {0x0111, "dcroat"},
+ {0x00b0, "degree"},
+ {0x03b4, "delta"},
+ {0x2666, "diamond"},
+ {0x00a8, "dieresis"},
+ {0xf6d7, "dieresisacute"},
+ {0xf6d8, "dieresisgrave"},
+ {0x0385, "dieresistonos"},
+ {0x00f7, "divide"},
+ {0x2593, "dkshade"},
+ {0x2584, "dnblock"},
+ {0x0024, "dollar"},
+ {0xf6e3, "dollarinferior"},
+ {0x0024, "dollaroldstyle"},
+ {0xf6e4, "dollarsuperior"},
+ {0x20ab, "dong"},
+ {0x02d9, "dotaccent"},
+ {0x0323, "dotbelowcomb"},
+ {0x0131, "dotlessi"},
+ {0xf6be, "dotlessj"},
+ {0x22c5, "dotmath"},
+ {0xf6eb, "dsuperior"},
+ {0x0065, "e"},
+ {0x00e9, "eacute"},
+ {0x0115, "ebreve"},
+ {0x011b, "ecaron"},
+ {0x00ea, "ecircumflex"},
+ {0x00eb, "edieresis"},
+ {0x0117, "edotaccent"},
+ {0x00e8, "egrave"},
+ {0x0038, "eight"},
+ {0x2088, "eightinferior"},
+ {0x0038, "eightoldstyle"},
+ {0x2078, "eightsuperior"},
+ {0x2208, "element"},
+ {0x2026, "ellipsis"},
+ {0x0113, "emacron"},
+ {0x2014, "emdash"},
+ {0x2205, "emptyset"},
+ {0x2013, "endash"},
+ {0x014b, "eng"},
+ {0x0119, "eogonek"},
+ {0x03b5, "epsilon"},
+ {0x03ad, "epsilontonos"},
+ {0x003d, "equal"},
+ {0x2261, "equivalence"},
+ {0x212e, "estimated"},
+ {0xf6ec, "esuperior"},
+ {0x03b7, "eta"},
+ {0x03ae, "etatonos"},
+ {0x00f0, "eth"},
+ {0x0021, "exclam"},
+ {0x203c, "exclamdbl"},
+ {0x00a1, "exclamdown"},
+ {0x00a1, "exclamdownsmall"},
+ {0x0021, "exclamleft"},
+ {0x0021, "exclamsmall"},
+ {0x2203, "existential"},
+ {0x0066, "f"},
+ {0x2640, "female"},
+ {0xfb00, "ff"},
+ {0xfb03, "ffi"},
+ {0xfb04, "ffl"},
+ {0xfb01, "fi"},
+ {0x2012, "figuredash"},
+ {0x25a0, "filledbox"},
+ {0x25ac, "filledrect"},
+ {0x0035, "five"},
+ {0x215d, "fiveeighths"},
+ {0x2085, "fiveinferior"},
+ {0x0035, "fiveoldstyle"},
+ {0x2075, "fivesuperior"},
+ {0xfb02, "fl"},
+ {0x0192, "florin"},
+ {0x0034, "four"},
+ {0x2084, "fourinferior"},
+ {0x0034, "fouroldstyle"},
+ {0x2074, "foursuperior"},
+ {0x2044, "fraction"},
+ {0x20a3, "franc"},
+ {0x0067, "g"},
+ {0x03b3, "gamma"},
+ {0x011f, "gbreve"},
+ {0x01e7, "gcaron"},
+ {0x011d, "gcircumflex"},
+ {0x0123, "gcommaaccent"},
+ {0x0121, "gdotaccent"},
+ {0x00df, "germandbls"},
+ {0x2207, "gradient"},
+ {0x0060, "grave"},
+ {0x0300, "gravecomb"},
+ {0x003e, "greater"},
+ {0x2265, "greaterequal"},
+ {0x00ab, "guillemotleft"},
+ {0x00bb, "guillemotright"},
+ {0x2039, "guilsinglleft"},
+ {0x203a, "guilsinglright"},
+ {0x0068, "h"},
+ {0x0127, "hbar"},
+ {0x0125, "hcircumflex"},
+ {0x2665, "heart"},
+ {0x0309, "hookabovecomb"},
+ {0x2302, "house"},
+ {0x02dd, "hungarumlaut"},
+ {0x002d, "hyphen"},
+ {0xf6e5, "hypheninferior"},
+ {0xf6e6, "hyphensuperior"},
+ {0x0069, "i"},
+ {0x00ed, "iacute"},
+ {0x012d, "ibreve"},
+ {0x00ee, "icircumflex"},
+ {0x00ef, "idieresis"},
+ {0x00ec, "igrave"},
+ {0x0133, "ij"},
+ {0x012b, "imacron"},
+ {0x221e, "infinity"},
+ {0x222b, "integral"},
+ {0x2321, "integralbt"},
+ {0xf8f5, "integralex"},
+ {0x2320, "integraltp"},
+ {0x2229, "intersection"},
+ {0x25d8, "invbullet"},
+ {0x25d9, "invcircle"},
+ {0x263b, "invsmileface"},
+ {0x012f, "iogonek"},
+ {0x03b9, "iota"},
+ {0x03ca, "iotadieresis"},
+ {0x0390, "iotadieresistonos"},
+ {0x03af, "iotatonos"},
+ {0xf6ed, "isuperior"},
+ {0x0129, "itilde"},
+ {0x006a, "j"},
+ {0x0135, "jcircumflex"},
+ {0x006b, "k"},
+ {0x03ba, "kappa"},
+ {0x0137, "kcommaaccent"},
+ {0x0138, "kgreenlandic"},
+ {0x006c, "l"},
+ {0x013a, "lacute"},
+ {0x03bb, "lambda"},
+ {0x013e, "lcaron"},
+ {0x013c, "lcommaaccent"},
+ {0x0140, "ldot"},
+ {0x003c, "less"},
+ {0x2264, "lessequal"},
+ {0x258c, "lfblock"},
+ {0x20a4, "lira"},
+ {0xf6c0, "ll"},
+ {0x2227, "logicaland"},
+ {0x00ac, "logicalnot"},
+ {0x2228, "logicalor"},
+ {0x017f, "longs"},
+ {0x25ca, "lozenge"},
+ {0x0142, "lslash"},
+ {0xf6ee, "lsuperior"},
+ {0x2591, "ltshade"},
+ {0x006d, "m"},
+ {0x00af, "macron"},
+ {0x2642, "male"},
+ {0x2212, "minus"},
+ {0x2032, "minute"},
+ {0xf6ef, "msuperior"},
+ {0x00b5, "mu"},
+ {0x00d7, "multiply"},
+ {0x266a, "musicalnote"},
+ {0x266b, "musicalnotedbl"},
+ {0x006e, "n"},
+ {0x0144, "nacute"},
+ {0x0149, "napostrophe"},
+ {0x00a0, "nbspace"},
+ {0x0148, "ncaron"},
+ {0x0146, "ncommaaccent"},
+ {0x0039, "nine"},
+ {0x2089, "nineinferior"},
+ {0x0039, "nineoldstyle"},
+ {0x2079, "ninesuperior"},
+ {0x00a0, "nonbreakingspace"},
+ {0x2209, "notelement"},
+ {0x2260, "notequal"},
+ {0x2284, "notsubset"},
+ {0x207f, "nsuperior"},
+ {0x00f1, "ntilde"},
+ {0x03bd, "nu"},
+ {0x0023, "numbersign"},
+ {0x006f, "o"},
+ {0x00f3, "oacute"},
+ {0x014f, "obreve"},
+ {0x00f4, "ocircumflex"},
+ {0x00f6, "odieresis"},
+ {0x0153, "oe"},
+ {0x02db, "ogonek"},
+ {0x00f2, "ograve"},
+ {0x01a1, "ohorn"},
+ {0x0151, "ohungarumlaut"},
+ {0x014d, "omacron"},
+ {0x03c9, "omega"},
+ {0x03d6, "omega1"},
+ {0x03ce, "omegatonos"},
+ {0x03bf, "omicron"},
+ {0x03cc, "omicrontonos"},
+ {0x0031, "one"},
+ {0x2024, "onedotenleader"},
+ {0x215b, "oneeighth"},
+ {0xf6dc, "onefitted"},
+ {0x00bd, "onehalf"},
+ {0x2081, "oneinferior"},
+ {0x0031, "oneoldstyle"},
+ {0x00bc, "onequarter"},
+ {0x00b9, "onesuperior"},
+ {0x2153, "onethird"},
+ {0x25e6, "openbullet"},
+ {0x00aa, "ordfeminine"},
+ {0x00ba, "ordmasculine"},
+ {0x221f, "orthogonal"},
+ {0x00f8, "oslash"},
+ {0x01ff, "oslashacute"},
+ {0xf6f0, "osuperior"},
+ {0x00f5, "otilde"},
+ {0x0070, "p"},
+ {0x00b6, "paragraph"},
+ {0x0028, "parenleft"},
+ {0xf8ed, "parenleftbt"},
+ {0xf8ec, "parenleftex"},
+ {0x208d, "parenleftinferior"},
+ {0x207d, "parenleftsuperior"},
+ {0xf8eb, "parenlefttp"},
+ {0x0029, "parenright"},
+ {0xf8f8, "parenrightbt"},
+ {0xf8f7, "parenrightex"},
+ {0x208e, "parenrightinferior"},
+ {0x207e, "parenrightsuperior"},
+ {0xf8f6, "parenrighttp"},
+ {0x2202, "partialdiff"},
+ {0x0025, "percent"},
+ {0x002e, "period"},
+ {0x00b7, "periodcentered"},
+ {0xf6e7, "periodinferior"},
+ {0xf6e8, "periodsuperior"},
+ {0x22a5, "perpendicular"},
+ {0x2030, "perthousand"},
+ {0x20a7, "peseta"},
+ {0x03c6, "phi"},
+ {0x03d5, "phi1"},
+ {0x03c0, "pi"},
+ {0x002b, "plus"},
+ {0x00b1, "plusminus"},
+ {0x211e, "prescription"},
+ {0x220f, "product"},
+ {0x2282, "propersubset"},
+ {0x2283, "propersuperset"},
+ {0x221d, "proportional"},
+ {0x03c8, "psi"},
+ {0x0071, "q"},
+ {0x003f, "question"},
+ {0x00bf, "questiondown"},
+ {0x00bf, "questiondownsmall"},
+ {0x003f, "questionsmall"},
+ {0x0022, "quotedbl"},
+ {0x201e, "quotedblbase"},
+ {0x201c, "quotedblleft"},
+ {0x201d, "quotedblright"},
+ {0x2018, "quoteleft"},
+ {0x201b, "quotereversed"},
+ {0x2019, "quoteright"},
+ {0x201a, "quotesinglbase"},
+ {0x0027, "quotesingle"},
+ {0x0072, "r"},
+ {0x0155, "racute"},
+ {0x221a, "radical"},
+ {0xf8e5, "radicalex"},
+ {0x0159, "rcaron"},
+ {0x0157, "rcommaaccent"},
+ {0x2286, "reflexsubset"},
+ {0x2287, "reflexsuperset"},
+ {0x00ae, "registered"},
+ {0x00ae, "registersans"},
+ {0x00ae, "registerserif"},
+ {0x2310, "revlogicalnot"},
+ {0x03c1, "rho"},
+ {0x02da, "ring"},
+ {0xf6f1, "rsuperior"},
+ {0x2590, "rtblock"},
+ {0xf6dd, "rupiah"},
+ {0x0073, "s"},
+ {0x015b, "sacute"},
+ {0x0161, "scaron"},
+ {0x015f, "scedilla"},
+ {0x015d, "scircumflex"},
+ {0x0219, "scommaaccent"},
+ {0x2033, "second"},
+ {0x00a7, "section"},
+ {0x003b, "semicolon"},
+ {0x0037, "seven"},
+ {0x215e, "seveneighths"},
+ {0x2087, "seveninferior"},
+ {0x0037, "sevenoldstyle"},
+ {0x2077, "sevensuperior"},
+ {0x2592, "shade"},
+ {0x03c3, "sigma"},
+ {0x03c2, "sigma1"},
+ {0x223c, "similar"},
+ {0x0036, "six"},
+ {0x2086, "sixinferior"},
+ {0x0036, "sixoldstyle"},
+ {0x2076, "sixsuperior"},
+ {0x002f, "slash"},
+ {0x263a, "smileface"},
+ {0x0020, "space"},
+ {0x2660, "spade"},
+ {0xf6f2, "ssuperior"},
+ {0x00a3, "sterling"},
+ {0x220b, "suchthat"},
+ {0x2211, "summation"},
+ {0x263c, "sun"},
+ {0x0074, "t"},
+ {0x03c4, "tau"},
+ {0x0167, "tbar"},
+ {0x0165, "tcaron"},
+ {0x0163, "tcommaaccent"},
+ {0x2234, "therefore"},
+ {0x03b8, "theta"},
+ {0x03d1, "theta1"},
+ {0x00fe, "thorn"},
+ {0x0033, "three"},
+ {0x215c, "threeeighths"},
+ {0x2083, "threeinferior"},
+ {0x0033, "threeoldstyle"},
+ {0x00be, "threequarters"},
+ {0xf6de, "threequartersemdash"},
+ {0x00b3, "threesuperior"},
+ {0x02dc, "tilde"},
+ {0x0303, "tildecomb"},
+ {0x0384, "tonos"},
+ {0x2122, "trademark"},
+ {0x2122, "trademarksans"},
+ {0x2122, "trademarkserif"},
+ {0x25bc, "triagdn"},
+ {0x25c4, "triaglf"},
+ {0x25ba, "triagrt"},
+ {0x25b2, "triagup"},
+ {0xf6f3, "tsuperior"},
+ {0x0032, "two"},
+ {0x2025, "twodotenleader"},
+ {0x2082, "twoinferior"},
+ {0x0032, "twooldstyle"},
+ {0x00b2, "twosuperior"},
+ {0x2154, "twothirds"},
+ {0x0075, "u"},
+ {0x00fa, "uacute"},
+ {0x016d, "ubreve"},
+ {0x00fb, "ucircumflex"},
+ {0x00fc, "udieresis"},
+ {0x00f9, "ugrave"},
+ {0x01b0, "uhorn"},
+ {0x0171, "uhungarumlaut"},
+ {0x016b, "umacron"},
+ {0x005f, "underscore"},
+ {0x2017, "underscoredbl"},
+ {0x222a, "union"},
+ {0x2200, "universal"},
+ {0x0173, "uogonek"},
+ {0x2580, "upblock"},
+ {0x03c5, "upsilon"},
+ {0x03cb, "upsilondieresis"},
+ {0x03b0, "upsilondieresistonos"},
+ {0x03cd, "upsilontonos"},
+ {0x016f, "uring"},
+ {0x0169, "utilde"},
+ {0x0076, "v"},
+ {0x0077, "w"},
+ {0x1e83, "wacute"},
+ {0x0175, "wcircumflex"},
+ {0x1e85, "wdieresis"},
+ {0x2118, "weierstrass"},
+ {0x1e81, "wgrave"},
+ {0x0078, "x"},
+ {0x03be, "xi"},
+ {0x0079, "y"},
+ {0x00fd, "yacute"},
+ {0x0177, "ycircumflex"},
+ {0x00ff, "ydieresis"},
+ {0x00a5, "yen"},
+ {0x1ef3, "ygrave"},
+ {0x007a, "z"},
+ {0x017a, "zacute"},
+ {0x017e, "zcaron"},
+ {0x017c, "zdotaccent"},
+ {0x0030, "zero"},
+ {0x2080, "zeroinferior"},
+ {0x0030, "zerooldstyle"},
+ {0x2070, "zerosuperior"},
+ {0x03b6, "zeta"},
+ {0x007b, "{"},
+ {0x007c, "|"},
+ {0x007d, "}"},
+ {0x007e, "~"},
+ { 0, NULL }
+};
diff --git a/pdftops/Object.cxx b/pdftops/Object.cxx
new file mode 100644
index 000000000..3d14fb3f1
--- /dev/null
+++ b/pdftops/Object.cxx
@@ -0,0 +1,224 @@
+//========================================================================
+//
+// Object.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include "Object.h"
+#include "Array.h"
+#include "Dict.h"
+#include "Error.h"
+#include "Stream.h"
+#include "XRef.h"
+
+//------------------------------------------------------------------------
+// Object
+//------------------------------------------------------------------------
+
+const char *objTypeNames[numObjTypes] = {
+ "boolean",
+ "integer",
+ "real",
+ "string",
+ "name",
+ "null",
+ "array",
+ "dictionary",
+ "stream",
+ "ref",
+ "cmd",
+ "error",
+ "eof",
+ "none"
+};
+
+#ifdef DEBUG_MEM
+int Object::numAlloc[numObjTypes] =
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+#endif
+
+Object *Object::initArray(XRef *xref) {
+ initObj(objArray);
+ array = new Array(xref);
+ return this;
+}
+
+Object *Object::initDict(XRef *xref) {
+ initObj(objDict);
+ dict = new Dict(xref);
+ return this;
+}
+
+Object *Object::initStream(Stream *streamA) {
+ initObj(objStream);
+ stream = streamA;
+ return this;
+}
+
+Object *Object::copy(Object *obj) {
+ *obj = *this;
+ switch (type) {
+ case objString:
+ obj->string = string->copy();
+ break;
+ case objName:
+ obj->name = copyString(name);
+ break;
+ case objArray:
+ array->incRef();
+ break;
+ case objDict:
+ dict->incRef();
+ break;
+ case objStream:
+ stream->incRef();
+ break;
+ case objCmd:
+ obj->cmd = copyString(cmd);
+ break;
+ default:
+ break;
+ }
+#ifdef DEBUG_MEM
+ ++numAlloc[type];
+#endif
+ return obj;
+}
+
+Object *Object::fetch(XRef *xref, Object *obj) {
+ return (type == objRef && xref) ?
+ xref->fetch(ref.num, ref.gen, obj) : copy(obj);
+}
+
+void Object::free() {
+ switch (type) {
+ case objString:
+ delete string;
+ break;
+ case objName:
+ gfree(name);
+ break;
+ case objArray:
+ if (!array->decRef()) {
+ delete array;
+ }
+ break;
+ case objDict:
+ if (!dict->decRef()) {
+ delete dict;
+ }
+ break;
+ case objStream:
+ if (!stream->decRef()) {
+ delete stream;
+ }
+ break;
+ case objCmd:
+ gfree(cmd);
+ break;
+ default:
+ break;
+ }
+#ifdef DEBUG_MEM
+ --numAlloc[type];
+#endif
+ type = objNone;
+}
+
+const char *Object::getTypeName() {
+ return objTypeNames[type];
+}
+
+void Object::print(FILE *f) {
+ Object obj;
+ int i;
+
+ switch (type) {
+ case objBool:
+ fprintf(f, "%s", booln ? "true" : "false");
+ break;
+ case objInt:
+ fprintf(f, "%d", intg);
+ break;
+ case objReal:
+ fprintf(f, "%g", real);
+ break;
+ case objString:
+ fprintf(f, "(");
+ fwrite(string->getCString(), 1, string->getLength(), f);
+ fprintf(f, ")");
+ break;
+ case objName:
+ fprintf(f, "/%s", name);
+ break;
+ case objNull:
+ fprintf(f, "null");
+ break;
+ case objArray:
+ fprintf(f, "[");
+ for (i = 0; i < arrayGetLength(); ++i) {
+ if (i > 0)
+ fprintf(f, " ");
+ arrayGetNF(i, &obj);
+ obj.print(f);
+ obj.free();
+ }
+ fprintf(f, "]");
+ break;
+ case objDict:
+ fprintf(f, "<<");
+ for (i = 0; i < dictGetLength(); ++i) {
+ fprintf(f, " /%s ", dictGetKey(i));
+ dictGetValNF(i, &obj);
+ obj.print(f);
+ obj.free();
+ }
+ fprintf(f, " >>");
+ break;
+ case objStream:
+ fprintf(f, "<stream>");
+ break;
+ case objRef:
+ fprintf(f, "%d %d R", ref.num, ref.gen);
+ break;
+ case objCmd:
+ fprintf(f, "%s", cmd);
+ break;
+ case objError:
+ fprintf(f, "<error>");
+ break;
+ case objEOF:
+ fprintf(f, "<EOF>");
+ break;
+ case objNone:
+ fprintf(f, "<none>");
+ break;
+ }
+}
+
+void Object::memCheck(FILE *f) {
+#ifdef DEBUG_MEM
+ int i;
+ int t;
+
+ t = 0;
+ for (i = 0; i < numObjTypes; ++i)
+ t += numAlloc[i];
+ if (t > 0) {
+ fprintf(f, "Allocated objects:\n");
+ for (i = 0; i < numObjTypes; ++i) {
+ if (numAlloc[i] > 0)
+ fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
+ }
+ }
+#endif
+}
diff --git a/pdftops/Object.h b/pdftops/Object.h
new file mode 100644
index 000000000..61b7f6f10
--- /dev/null
+++ b/pdftops/Object.h
@@ -0,0 +1,302 @@
+//========================================================================
+//
+// Object.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef OBJECT_H
+#define OBJECT_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "gtypes.h"
+#include "gmem.h"
+#include "GString.h"
+
+class XRef;
+class Array;
+class Dict;
+class Stream;
+
+//------------------------------------------------------------------------
+// Ref
+//------------------------------------------------------------------------
+
+struct Ref {
+ int num; // object number
+ int gen; // generation number
+};
+
+//------------------------------------------------------------------------
+// object types
+//------------------------------------------------------------------------
+
+enum ObjType {
+ // simple objects
+ objBool, // boolean
+ objInt, // integer
+ objReal, // real
+ objString, // string
+ objName, // name
+ objNull, // null
+
+ // complex objects
+ objArray, // array
+ objDict, // dictionary
+ objStream, // stream
+ objRef, // indirect reference
+
+ // special objects
+ objCmd, // command name
+ objError, // error return from Lexer
+ objEOF, // end of file return from Lexer
+ objNone // uninitialized object
+};
+
+#define numObjTypes 14 // total number of object types
+
+//------------------------------------------------------------------------
+// Object
+//------------------------------------------------------------------------
+
+#ifdef DEBUG_MEM
+#define initObj(t) ++numAlloc[type = t]
+#else
+#define initObj(t) type = t
+#endif
+
+class Object {
+public:
+
+ // Default constructor.
+ Object():
+ type(objNone) {}
+
+ // Initialize an object.
+ Object *initBool(GBool boolnA)
+ { initObj(objBool); booln = boolnA; return this; }
+ Object *initInt(int intgA)
+ { initObj(objInt); intg = intgA; return this; }
+ Object *initReal(double realA)
+ { initObj(objReal); real = realA; return this; }
+ Object *initString(GString *stringA)
+ { initObj(objString); string = stringA; return this; }
+ Object *initName(const char *nameA)
+ { initObj(objName); name = copyString(nameA); return this; }
+ Object *initNull()
+ { initObj(objNull); return this; }
+ Object *initArray(XRef *xref);
+ Object *initDict(XRef *xref);
+ Object *initStream(Stream *streamA);
+ Object *initRef(int numA, int genA)
+ { initObj(objRef); ref.num = numA; ref.gen = genA; return this; }
+ Object *initCmd(const char *cmdA)
+ { initObj(objCmd); cmd = copyString(cmdA); return this; }
+ Object *initError()
+ { initObj(objError); return this; }
+ Object *initEOF()
+ { initObj(objEOF); return this; }
+
+ // Copy an object.
+ Object *copy(Object *obj);
+
+ // If object is a Ref, fetch and return the referenced object.
+ // Otherwise, return a copy of the object.
+ Object *fetch(XRef *xref, Object *obj);
+
+ // Free object contents.
+ void free();
+
+ // Type checking.
+ ObjType getType() { return type; }
+ GBool isBool() { return type == objBool; }
+ GBool isInt() { return type == objInt; }
+ GBool isReal() { return type == objReal; }
+ GBool isNum() { return type == objInt || type == objReal; }
+ GBool isString() { return type == objString; }
+ GBool isName() { return type == objName; }
+ GBool isNull() { return type == objNull; }
+ GBool isArray() { return type == objArray; }
+ GBool isDict() { return type == objDict; }
+ GBool isStream() { return type == objStream; }
+ GBool isRef() { return type == objRef; }
+ GBool isCmd() { return type == objCmd; }
+ GBool isError() { return type == objError; }
+ GBool isEOF() { return type == objEOF; }
+ GBool isNone() { return type == objNone; }
+
+ // Special type checking.
+ GBool isName(const char *nameA)
+ { return type == objName && !strcmp(name, nameA); }
+ GBool isDict(const char *dictType);
+ GBool isStream(const char *dictType);
+ GBool isCmd(const char *cmdA)
+ { return type == objCmd && !strcmp(cmd, cmdA); }
+
+ // Accessors. NB: these assume object is of correct type.
+ GBool getBool() { return booln; }
+ int getInt() { return intg; }
+ double getReal() { return real; }
+ double getNum() { return type == objInt ? (double)intg : real; }
+ GString *getString() { return string; }
+ char *getName() { return name; }
+ Array *getArray() { return array; }
+ Dict *getDict() { return dict; }
+ Stream *getStream() { return stream; }
+ Ref getRef() { return ref; }
+ int getRefNum() { return ref.num; }
+ int getRefGen() { return ref.gen; }
+ char *getCmd() { return cmd; }
+
+ // Array accessors.
+ int arrayGetLength();
+ void arrayAdd(Object *elem);
+ Object *arrayGet(int i, Object *obj);
+ Object *arrayGetNF(int i, Object *obj);
+
+ // Dict accessors.
+ int dictGetLength();
+ void dictAdd(const char *key, Object *val);
+ GBool dictIs(const char *dictType);
+ Object *dictLookup(const char *key, Object *obj);
+ Object *dictLookupNF(const char *key, Object *obj);
+ const char *dictGetKey(int i);
+ Object *dictGetVal(int i, Object *obj);
+ Object *dictGetValNF(int i, Object *obj);
+
+ // Stream accessors.
+ GBool streamIs(const char *dictType);
+ void streamReset();
+ void streamClose();
+ int streamGetChar();
+ int streamLookChar();
+ char *streamGetLine(char *buf, int size);
+ Guint streamGetPos();
+ void streamSetPos(Guint pos, int dir = 0);
+ Dict *streamGetDict();
+
+ // Output.
+ const char *getTypeName();
+ void print(FILE *f = stdout);
+
+ // Memory testing.
+ static void memCheck(FILE *f);
+
+private:
+
+ ObjType type; // object type
+ union { // value for each type:
+ GBool booln; // boolean
+ int intg; // integer
+ double real; // real
+ GString *string; // string
+ char *name; // name
+ Array *array; // array
+ Dict *dict; // dictionary
+ Stream *stream; // stream
+ Ref ref; // indirect reference
+ char *cmd; // command
+ };
+
+#ifdef DEBUG_MEM
+ static int // number of each type of object
+ numAlloc[numObjTypes]; // currently allocated
+#endif
+};
+
+//------------------------------------------------------------------------
+// Array accessors.
+//------------------------------------------------------------------------
+
+#include "Array.h"
+
+inline int Object::arrayGetLength()
+ { return array->getLength(); }
+
+inline void Object::arrayAdd(Object *elem)
+ { array->add(elem); }
+
+inline Object *Object::arrayGet(int i, Object *obj)
+ { return array->get(i, obj); }
+
+inline Object *Object::arrayGetNF(int i, Object *obj)
+ { return array->getNF(i, obj); }
+
+//------------------------------------------------------------------------
+// Dict accessors.
+//------------------------------------------------------------------------
+
+#include "Dict.h"
+
+inline int Object::dictGetLength()
+ { return dict->getLength(); }
+
+inline void Object::dictAdd(const char *key, Object *val)
+ { dict->add(key, val); }
+
+inline GBool Object::dictIs(const char *dictType)
+ { return dict->is(dictType); }
+
+inline GBool Object::isDict(const char *dictType)
+ { return type == objDict && dictIs(dictType); }
+
+inline Object *Object::dictLookup(const char *key, Object *obj)
+ { return dict->lookup(key, obj); }
+
+inline Object *Object::dictLookupNF(const char *key, Object *obj)
+ { return dict->lookupNF(key, obj); }
+
+inline const char *Object::dictGetKey(int i)
+ { return dict->getKey(i); }
+
+inline Object *Object::dictGetVal(int i, Object *obj)
+ { return dict->getVal(i, obj); }
+
+inline Object *Object::dictGetValNF(int i, Object *obj)
+ { return dict->getValNF(i, obj); }
+
+//------------------------------------------------------------------------
+// Stream accessors.
+//------------------------------------------------------------------------
+
+#include "Stream.h"
+
+inline GBool Object::streamIs(const char *dictType)
+ { return stream->getDict()->is(dictType); }
+
+inline GBool Object::isStream(const char *dictType)
+ { return type == objStream && streamIs(dictType); }
+
+inline void Object::streamReset()
+ { stream->reset(); }
+
+inline void Object::streamClose()
+ { stream->close(); }
+
+inline int Object::streamGetChar()
+ { return stream->getChar(); }
+
+inline int Object::streamLookChar()
+ { return stream->lookChar(); }
+
+inline char *Object::streamGetLine(char *buf, int size)
+ { return stream->getLine(buf, size); }
+
+inline Guint Object::streamGetPos()
+ { return stream->getPos(); }
+
+inline void Object::streamSetPos(Guint pos, int dir)
+ { stream->setPos(pos, dir); }
+
+inline Dict *Object::streamGetDict()
+ { return stream->getDict(); }
+
+#endif
diff --git a/pdftops/Outline.cxx b/pdftops/Outline.cxx
new file mode 100644
index 000000000..83463e021
--- /dev/null
+++ b/pdftops/Outline.cxx
@@ -0,0 +1,140 @@
+//========================================================================
+//
+// Outline.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include "gmem.h"
+#include "GString.h"
+#include "GList.h"
+#include "Link.h"
+#include "PDFDocEncoding.h"
+#include "Outline.h"
+
+//------------------------------------------------------------------------
+
+Outline::Outline(Object *outlineObj, XRef *xref) {
+ Object first;
+
+ items = NULL;
+ if (!outlineObj->isDict()) {
+ return;
+ }
+ items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
+ xref);
+ first.free();
+}
+
+Outline::~Outline() {
+ if (items) {
+ deleteGList(items, OutlineItem);
+ }
+}
+
+//------------------------------------------------------------------------
+
+OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
+ Object obj1;
+ GString *s;
+ int i;
+
+ xref = xrefA;
+ title = NULL;
+ action = NULL;
+ kids = NULL;
+
+ if (dict->lookup("Title", &obj1)->isString()) {
+ s = obj1.getString();
+ if ((s->getChar(0) & 0xff) == 0xfe &&
+ (s->getChar(1) & 0xff) == 0xff) {
+ titleLen = (s->getLength() - 2) / 2;
+ title = (Unicode *)gmalloc(titleLen * sizeof(Unicode));
+ for (i = 0; i < titleLen; ++i) {
+ title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
+ (s->getChar(3 + 2*i) & 0xff);
+ }
+ } else {
+ titleLen = s->getLength();
+ title = (Unicode *)gmalloc(titleLen * sizeof(Unicode));
+ for (i = 0; i < titleLen; ++i) {
+ title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
+ }
+ }
+ }
+ obj1.free();
+
+ if (!dict->lookup("Dest", &obj1)->isNull()) {
+ action = LinkAction::parseDest(&obj1);
+ } else {
+ obj1.free();
+ if (dict->lookup("A", &obj1)) {
+ action = LinkAction::parseAction(&obj1);
+ }
+ }
+ obj1.free();
+
+ dict->lookupNF("First", &firstRef);
+ dict->lookupNF("Next", &nextRef);
+
+ startsOpen = gFalse;
+ if (dict->lookup("Count", &obj1)->isInt()) {
+ if (obj1.getInt() > 0) {
+ startsOpen = gTrue;
+ }
+ }
+ obj1.free();
+}
+
+OutlineItem::~OutlineItem() {
+ close();
+ if (title) {
+ gfree(title);
+ }
+ if (action) {
+ delete action;
+ }
+ firstRef.free();
+ nextRef.free();
+}
+
+GList *OutlineItem::readItemList(Object *itemRef, XRef *xrefA) {
+ GList *items;
+ OutlineItem *item;
+ Object obj;
+ Object *p;
+
+ items = new GList();
+ p = itemRef;
+ while (p->isRef()) {
+ if (!p->fetch(xrefA, &obj)->isDict()) {
+ obj.free();
+ break;
+ }
+ item = new OutlineItem(obj.getDict(), xrefA);
+ obj.free();
+ items->append(item);
+ p = &item->nextRef;
+ }
+ return items;
+}
+
+void OutlineItem::open() {
+ if (!kids) {
+ kids = readItemList(&firstRef, xref);
+ }
+}
+
+void OutlineItem::close() {
+ if (kids) {
+ deleteGList(kids, OutlineItem);
+ kids = NULL;
+ }
+}
diff --git a/pdftops/Outline.h b/pdftops/Outline.h
new file mode 100644
index 000000000..237cb184c
--- /dev/null
+++ b/pdftops/Outline.h
@@ -0,0 +1,74 @@
+//========================================================================
+//
+// Outline.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef OUTLINE_H
+#define OUTLINE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+#include "CharTypes.h"
+
+class GString;
+class GList;
+class XRef;
+class LinkAction;
+
+//------------------------------------------------------------------------
+
+class Outline {
+public:
+
+ Outline(Object *outlineObj, XRef *xref);
+ ~Outline();
+
+ GList *getItems() { return items; }
+
+private:
+
+ GList *items; // NULL if document has no outline
+ // [OutlineItem]
+};
+
+//------------------------------------------------------------------------
+
+class OutlineItem {
+public:
+
+ OutlineItem(Dict *dict, XRef *xrefA);
+ ~OutlineItem();
+
+ static GList *readItemList(Object *itemRef, XRef *xrefA);
+
+ void open();
+ void close();
+
+ Unicode *getTitle() { return title; }
+ int getTitleLength() { return titleLen; }
+ LinkAction *getAction() { return action; }
+ GBool isOpen() { return startsOpen; }
+ GBool hasKids() { return firstRef.isRef(); }
+ GList *getKids() { return kids; }
+
+private:
+
+ XRef *xref;
+ Unicode *title;
+ int titleLen;
+ LinkAction *action;
+ Object firstRef;
+ Object nextRef;
+ GBool startsOpen;
+ GList *kids; // NULL unless this item is open [OutlineItem]
+};
+
+#endif
diff --git a/pdftops/OutputDev.cxx b/pdftops/OutputDev.cxx
new file mode 100644
index 000000000..26e05c700
--- /dev/null
+++ b/pdftops/OutputDev.cxx
@@ -0,0 +1,103 @@
+//========================================================================
+//
+// OutputDev.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include "Object.h"
+#include "Stream.h"
+#include "GfxState.h"
+#include "OutputDev.h"
+
+//------------------------------------------------------------------------
+// OutputDev
+//------------------------------------------------------------------------
+
+void OutputDev::setDefaultCTM(double *ctm) {
+ int i;
+ double det;
+
+ for (i = 0; i < 6; ++i) {
+ defCTM[i] = ctm[i];
+ }
+ det = 1 / (defCTM[0] * defCTM[3] - defCTM[1] * defCTM[2]);
+ defICTM[0] = defCTM[3] * det;
+ defICTM[1] = -defCTM[1] * det;
+ defICTM[2] = -defCTM[2] * det;
+ defICTM[3] = defCTM[0] * det;
+ defICTM[4] = (defCTM[2] * defCTM[5] - defCTM[3] * defCTM[4]) * det;
+ defICTM[5] = (defCTM[1] * defCTM[4] - defCTM[0] * defCTM[5]) * det;
+}
+
+void OutputDev::cvtDevToUser(double dx, double dy, double *ux, double *uy) {
+ *ux = defICTM[0] * dx + defICTM[2] * dy + defICTM[4];
+ *uy = defICTM[1] * dx + defICTM[3] * dy + defICTM[5];
+}
+
+void OutputDev::cvtUserToDev(double ux, double uy, int *dx, int *dy) {
+ *dx = (int)(defCTM[0] * ux + defCTM[2] * uy + defCTM[4] + 0.5);
+ *dy = (int)(defCTM[1] * ux + defCTM[3] * uy + defCTM[5] + 0.5);
+}
+
+void OutputDev::updateAll(GfxState *state) {
+ updateLineDash(state);
+ updateFlatness(state);
+ updateLineJoin(state);
+ updateLineCap(state);
+ updateMiterLimit(state);
+ updateLineWidth(state);
+ updateFillColor(state);
+ updateStrokeColor(state);
+ updateFont(state);
+}
+
+GBool OutputDev::beginType3Char(GfxState *state,
+ CharCode code, Unicode *u, int uLen) {
+ return gFalse;
+}
+
+void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg) {
+ int i, j;
+
+ if (inlineImg) {
+ str->reset();
+ j = height * ((width + 7) / 8);
+ for (i = 0; i < j; ++i)
+ str->getChar();
+ str->close();
+ }
+}
+
+void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
+ int *maskColors, GBool inlineImg) {
+ int i, j;
+
+ if (inlineImg) {
+ str->reset();
+ j = height * ((width * colorMap->getNumPixelComps() *
+ colorMap->getBits() + 7) / 8);
+ for (i = 0; i < j; ++i)
+ str->getChar();
+ str->close();
+ }
+}
+
+#if OPI_SUPPORT
+void OutputDev::opiBegin(GfxState *state, Dict *opiDict) {
+}
+
+void OutputDev::opiEnd(GfxState *state, Dict *opiDict) {
+}
+#endif
diff --git a/pdftops/OutputDev.h b/pdftops/OutputDev.h
new file mode 100644
index 000000000..9b2e53eb5
--- /dev/null
+++ b/pdftops/OutputDev.h
@@ -0,0 +1,161 @@
+//========================================================================
+//
+// OutputDev.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef OUTPUTDEV_H
+#define OUTPUTDEV_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "CharTypes.h"
+
+class GString;
+class GfxState;
+class GfxColorSpace;
+class GfxImageColorMap;
+class Stream;
+class Link;
+class Catalog;
+
+//------------------------------------------------------------------------
+// OutputDev
+//------------------------------------------------------------------------
+
+class OutputDev {
+public:
+
+ // Constructor.
+ OutputDev() {}
+
+ // Destructor.
+ virtual ~OutputDev() {}
+
+ //----- get info about output device
+
+ // Does this device use upside-down coordinates?
+ // (Upside-down means (0,0) is the top left corner of the page.)
+ virtual GBool upsideDown() = 0;
+
+ // Does this device use drawChar() or drawString()?
+ virtual GBool useDrawChar() = 0;
+
+ // Does this device use beginType3Char/endType3Char? Otherwise,
+ // text in Type 3 fonts will be drawn with drawChar/drawString.
+ virtual GBool interpretType3Chars() = 0;
+
+ // Does this device need non-text content?
+ virtual GBool needNonText() { return gTrue; }
+
+ //----- initialization and control
+
+ // Set default transform matrix.
+ virtual void setDefaultCTM(double *ctm);
+
+ // Start a page.
+ virtual void startPage(int pageNum, GfxState *state) {}
+
+ // End a page.
+ virtual void endPage() {}
+
+ // Dump page contents to display.
+ virtual void dump() {}
+
+ //----- coordinate conversion
+
+ // Convert between device and user coordinates.
+ virtual void cvtDevToUser(double dx, double dy, double *ux, double *uy);
+ virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
+
+ //----- link borders
+ virtual void drawLink(Link *link, Catalog *catalog) {}
+
+ //----- save/restore graphics state
+ virtual void saveState(GfxState *state) {}
+ virtual void restoreState(GfxState *state) {}
+
+ //----- update graphics state
+ virtual void updateAll(GfxState *state);
+ virtual void updateCTM(GfxState *state, double m11, double m12,
+ double m21, double m22, double m31, double m32) {}
+ virtual void updateLineDash(GfxState *state) {}
+ virtual void updateFlatness(GfxState *state) {}
+ virtual void updateLineJoin(GfxState *state) {}
+ virtual void updateLineCap(GfxState *state) {}
+ virtual void updateMiterLimit(GfxState *state) {}
+ virtual void updateLineWidth(GfxState *state) {}
+ virtual void updateFillColor(GfxState *state) {}
+ virtual void updateStrokeColor(GfxState *state) {}
+ virtual void updateFillOpacity(GfxState *state) {}
+ virtual void updateStrokeOpacity(GfxState *state) {}
+
+ //----- update text state
+ virtual void updateFont(GfxState *state) {}
+ virtual void updateTextMat(GfxState *state) {}
+ virtual void updateCharSpace(GfxState *state) {}
+ virtual void updateRender(GfxState *state) {}
+ virtual void updateRise(GfxState *state) {}
+ virtual void updateWordSpace(GfxState *state) {}
+ virtual void updateHorizScaling(GfxState *state) {}
+ virtual void updateTextPos(GfxState *state) {}
+ virtual void updateTextShift(GfxState *state, double shift) {}
+
+ //----- path painting
+ virtual void stroke(GfxState *state) {}
+ virtual void fill(GfxState *state) {}
+ virtual void eoFill(GfxState *state) {}
+
+ //----- path clipping
+ virtual void clip(GfxState *state) {}
+ virtual void eoClip(GfxState *state) {}
+
+ //----- text drawing
+ virtual void beginString(GfxState *state, GString *s) {}
+ virtual void endString(GfxState *state) {}
+ virtual void drawChar(GfxState *state, double x, double y,
+ double dx, double dy,
+ double originX, double originY,
+ CharCode code, Unicode *u, int uLen) {}
+ virtual void drawString(GfxState *state, GString *s) {}
+ virtual GBool beginType3Char(GfxState *state,
+ CharCode code, Unicode *u, int uLen);
+ virtual void endType3Char(GfxState *state) {}
+ virtual void endTextObject(GfxState *state) {}
+
+ //----- image drawing
+ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg);
+ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
+ int *maskColors, GBool inlineImg);
+
+#if OPI_SUPPORT
+ //----- OPI functions
+ virtual void opiBegin(GfxState *state, Dict *opiDict);
+ virtual void opiEnd(GfxState *state, Dict *opiDict);
+#endif
+
+ //----- Type 3 font operators
+ virtual void type3D0(GfxState *state, double wx, double wy) {}
+ virtual void type3D1(GfxState *state, double wx, double wy,
+ double llx, double lly, double urx, double ury) {}
+
+ //----- PostScript XObjects
+ virtual void psXObject(Stream *psStream, Stream *level1Stream) {}
+
+private:
+
+ double defCTM[6]; // default coordinate transform matrix
+ double defICTM[6]; // inverse of default CTM
+};
+
+#endif
diff --git a/pdftops/PDFDoc.cxx b/pdftops/PDFDoc.cxx
new file mode 100644
index 000000000..dc47f17f2
--- /dev/null
+++ b/pdftops/PDFDoc.cxx
@@ -0,0 +1,303 @@
+//========================================================================
+//
+// PDFDoc.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include "GString.h"
+#include "config.h"
+#include "GlobalParams.h"
+#include "Page.h"
+#include "Catalog.h"
+#include "Stream.h"
+#include "XRef.h"
+#include "Link.h"
+#include "OutputDev.h"
+#include "Error.h"
+#include "ErrorCodes.h"
+#include "Lexer.h"
+#include "Parser.h"
+#ifndef DISABLE_OUTLINE
+#include "Outline.h"
+#endif
+#include "PDFDoc.h"
+
+//------------------------------------------------------------------------
+
+#define headerSearchSize 1024 // read this many bytes at beginning of
+ // file to look for '%PDF'
+
+//------------------------------------------------------------------------
+// PDFDoc
+//------------------------------------------------------------------------
+
+PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
+ GString *userPassword) {
+ Object obj;
+ GString *fileName1, *fileName2;
+
+ ok = gFalse;
+ errCode = errNone;
+
+ file = NULL;
+ str = NULL;
+ xref = NULL;
+ catalog = NULL;
+ links = NULL;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
+
+ fileName = fileNameA;
+ fileName1 = fileName;
+
+
+ // try to open file
+ fileName2 = NULL;
+#ifdef VMS
+ if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
+ error(-1, "Couldn't open file '%s'", fileName1->getCString());
+ errCode = errOpenFile;
+ return;
+ }
+#else
+ if (!(file = fopen(fileName1->getCString(), "rb"))) {
+ fileName2 = fileName->copy();
+ fileName2->lowerCase();
+ if (!(file = fopen(fileName2->getCString(), "rb"))) {
+ fileName2->upperCase();
+ if (!(file = fopen(fileName2->getCString(), "rb"))) {
+ error(-1, "Couldn't open file '%s'", fileName->getCString());
+ delete fileName2;
+ errCode = errOpenFile;
+ return;
+ }
+ }
+ delete fileName2;
+ }
+#endif
+
+ // create stream
+ obj.initNull();
+ str = new FileStream(file, 0, gFalse, 0, &obj);
+
+ ok = setup(ownerPassword, userPassword);
+}
+
+PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
+ GString *userPassword) {
+ ok = gFalse;
+ errCode = errNone;
+ fileName = NULL;
+ file = NULL;
+ str = strA;
+ xref = NULL;
+ catalog = NULL;
+ links = NULL;
+#ifndef DISABLE_OUTLINE
+ outline = NULL;
+#endif
+ ok = setup(ownerPassword, userPassword);
+}
+
+GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
+ str->reset();
+
+ // check header
+ checkHeader();
+
+ // read xref table
+ xref = new XRef(str, ownerPassword, userPassword);
+ if (!xref->isOk()) {
+ error(-1, "Couldn't read xref table");
+ errCode = xref->getErrorCode();
+ return gFalse;
+ }
+
+ // read catalog
+ catalog = new Catalog(xref);
+ if (!catalog->isOk()) {
+ error(-1, "Couldn't read page catalog");
+ errCode = errBadCatalog;
+ return gFalse;
+ }
+
+#ifndef DISABLE_OUTLINE
+ // read outline
+ outline = new Outline(catalog->getOutline(), xref);
+#endif
+
+ // done
+ return gTrue;
+}
+
+PDFDoc::~PDFDoc() {
+#ifndef DISABLE_OUTLINE
+ if (outline) {
+ delete outline;
+ }
+#endif
+ if (catalog) {
+ delete catalog;
+ }
+ if (xref) {
+ delete xref;
+ }
+ if (str) {
+ delete str;
+ }
+ if (file) {
+ fclose(file);
+ }
+ if (fileName) {
+ delete fileName;
+ }
+ if (links) {
+ delete links;
+ }
+}
+
+// Check for a PDF header on this stream. Skip past some garbage
+// if necessary.
+void PDFDoc::checkHeader() {
+ char hdrBuf[headerSearchSize+1];
+ char *p;
+ int i;
+
+ pdfVersion = 0;
+ for (i = 0; i < headerSearchSize; ++i) {
+ hdrBuf[i] = str->getChar();
+ }
+ hdrBuf[headerSearchSize] = '\0';
+ for (i = 0; i < headerSearchSize - 5; ++i) {
+ if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
+ break;
+ }
+ }
+ if (i >= headerSearchSize - 5) {
+ error(-1, "May not be a PDF file (continuing anyway)");
+ return;
+ }
+ str->moveStart(i);
+ p = strtok(&hdrBuf[i+5], " \t\n\r");
+ pdfVersion = atof(p);
+ if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
+ pdfVersion > supportedPDFVersionNum + 0.0001) {
+ error(-1, "PDF version %s -- xpdf supports version %s"
+ " (continuing anyway)", p, supportedPDFVersionStr);
+ }
+}
+
+void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
+ int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ Page *p;
+
+ if (globalParams->getPrintCommands()) {
+ fprintf(stderr, "DEBUG2: ***** page %d *****\n", page);
+ }
+ p = catalog->getPage(page);
+ if (doLinks) {
+ if (links) {
+ delete links;
+ }
+ getLinks(p);
+ p->display(out, hDPI, vDPI, rotate, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
+ } else {
+ p->display(out, hDPI, vDPI, rotate, NULL, catalog,
+ abortCheckCbk, abortCheckCbkData);
+ }
+}
+
+void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
+ double hDPI, double vDPI, int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ int page;
+
+ for (page = firstPage; page <= lastPage; ++page) {
+ displayPage(out, page, hDPI, vDPI, rotate, doLinks,
+ abortCheckCbk, abortCheckCbkData);
+ }
+}
+
+void PDFDoc::displayPageSlice(OutputDev *out, int page,
+ double hDPI, double vDPI,
+ int rotate, int sliceX, int sliceY,
+ int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ Page *p;
+
+ p = catalog->getPage(page);
+ p->displaySlice(out, hDPI, vDPI, rotate, sliceX, sliceY, sliceW, sliceH,
+ NULL, catalog, abortCheckCbk, abortCheckCbkData);
+}
+
+GBool PDFDoc::isLinearized() {
+ Parser *parser;
+ Object obj1, obj2, obj3, obj4, obj5;
+ GBool lin;
+
+ lin = gFalse;
+ obj1.initNull();
+ parser = new Parser(xref,
+ new Lexer(xref,
+ str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
+ parser->getObj(&obj1);
+ parser->getObj(&obj2);
+ parser->getObj(&obj3);
+ parser->getObj(&obj4);
+ if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
+ obj4.isDict()) {
+ obj4.dictLookup("Linearized", &obj5);
+ if (obj5.isNum() && obj5.getNum() > 0) {
+ lin = gTrue;
+ }
+ obj5.free();
+ }
+ obj4.free();
+ obj3.free();
+ obj2.free();
+ obj1.free();
+ delete parser;
+ return lin;
+}
+
+GBool PDFDoc::saveAs(GString *name) {
+ FILE *f;
+ int c;
+
+ if (!(f = fopen(name->getCString(), "wb"))) {
+ error(-1, "Couldn't open file '%s'", name->getCString());
+ return gFalse;
+ }
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ fputc(c, f);
+ }
+ str->close();
+ fclose(f);
+ return gTrue;
+}
+
+void PDFDoc::getLinks(Page *page) {
+ Object obj;
+
+ links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
+ obj.free();
+}
diff --git a/pdftops/PDFDoc.h b/pdftops/PDFDoc.h
new file mode 100644
index 000000000..31240e27c
--- /dev/null
+++ b/pdftops/PDFDoc.h
@@ -0,0 +1,172 @@
+//========================================================================
+//
+// PDFDoc.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PDFDOC_H
+#define PDFDOC_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "XRef.h"
+#include "Link.h"
+#include "Catalog.h"
+#include "Page.h"
+
+class GString;
+class BaseStream;
+class OutputDev;
+class Links;
+class LinkAction;
+class LinkDest;
+class Outline;
+
+//------------------------------------------------------------------------
+// PDFDoc
+//------------------------------------------------------------------------
+
+class PDFDoc {
+public:
+
+ PDFDoc(GString *fileNameA, GString *ownerPassword = NULL,
+ GString *userPassword = NULL);
+ PDFDoc(BaseStream *strA, GString *ownerPassword = NULL,
+ GString *userPassword = NULL);
+ ~PDFDoc();
+
+ // Was PDF document successfully opened?
+ GBool isOk() { return ok; }
+
+ // Get the error code (if isOk() returns false).
+ int getErrorCode() { return errCode; }
+
+ // Get file name.
+ GString *getFileName() { return fileName; }
+
+ // Get the xref table.
+ XRef *getXRef() { return xref; }
+
+ // Get catalog.
+ Catalog *getCatalog() { return catalog; }
+
+ // Get base stream.
+ BaseStream *getBaseStream() { return str; }
+
+ // Get page parameters.
+ double getPageWidth(int page)
+ { return catalog->getPage(page)->getWidth(); }
+ double getPageHeight(int page)
+ { return catalog->getPage(page)->getHeight(); }
+ int getPageRotate(int page)
+ { return catalog->getPage(page)->getRotate(); }
+
+ // Get number of pages.
+ int getNumPages() { return catalog->getNumPages(); }
+
+ // Return the contents of the metadata stream, or NULL if there is
+ // no metadata.
+ GString *readMetadata() { return catalog->readMetadata(); }
+
+ // Return the structure tree root object.
+ Object *getStructTreeRoot() { return catalog->getStructTreeRoot(); }
+
+ // Display a page.
+ void displayPage(OutputDev *out, int page, double hDPI, double vDPI,
+ int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display a range of pages.
+ void displayPages(OutputDev *out, int firstPage, int lastPage,
+ double hDPI, double vDPI, int rotate, GBool doLinks,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displayPageSlice(OutputDev *out, int page,
+ double hDPI, double vDPI,
+ int rotate, int sliceX, int sliceY,
+ int sliceW, int sliceH,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Find a page, given its object ID. Returns page number, or 0 if
+ // not found.
+ int findPage(int num, int gen) { return catalog->findPage(num, gen); }
+
+ // If point <x>,<y> is in a link, return the associated action;
+ // else return NULL.
+ LinkAction *findLink(double x, double y)
+ { return links ? links->find(x, y) : (LinkAction *)NULL; }
+
+ // Return true if <x>,<y> is in a link.
+ GBool onLink(double x, double y) { return links->onLink(x, y); }
+
+ // Find a named destination. Returns the link destination, or
+ // NULL if <name> is not a destination.
+ LinkDest *findDest(GString *name)
+ { return catalog->findDest(name); }
+
+#ifndef DISABLE_OUTLINE
+ // Return the outline object.
+ Outline *getOutline() { return outline; }
+#endif
+
+ // Is the file encrypted?
+ GBool isEncrypted() { return xref->isEncrypted(); }
+
+ // Check various permissions.
+ GBool okToPrint(GBool ignoreOwnerPW = gFalse)
+ { return xref->okToPrint(ignoreOwnerPW); }
+ GBool okToChange(GBool ignoreOwnerPW = gFalse)
+ { return xref->okToChange(ignoreOwnerPW); }
+ GBool okToCopy(GBool ignoreOwnerPW = gFalse)
+ { return xref->okToCopy(ignoreOwnerPW); }
+ GBool okToAddNotes(GBool ignoreOwnerPW = gFalse)
+ { return xref->okToAddNotes(ignoreOwnerPW); }
+
+ // Is this document linearized?
+ GBool isLinearized();
+
+ // Return the document's Info dictionary (if any).
+ Object *getDocInfo(Object *obj) { return xref->getDocInfo(obj); }
+ Object *getDocInfoNF(Object *obj) { return xref->getDocInfoNF(obj); }
+
+ // Return the PDF version specified by the file.
+ double getPDFVersion() { return pdfVersion; }
+
+ // Save this file with another name.
+ GBool saveAs(GString *name);
+
+
+private:
+
+ GBool setup(GString *ownerPassword, GString *userPassword);
+ void checkHeader();
+ void getLinks(Page *page);
+
+ GString *fileName;
+ FILE *file;
+ BaseStream *str;
+ double pdfVersion;
+ XRef *xref;
+ Catalog *catalog;
+ Links *links;
+#ifndef DISABLE_OUTLINE
+ Outline *outline;
+#endif
+
+
+ GBool ok;
+ int errCode;
+};
+
+#endif
diff --git a/pdftops/PDFDocEncoding.cxx b/pdftops/PDFDocEncoding.cxx
new file mode 100644
index 000000000..89dc38283
--- /dev/null
+++ b/pdftops/PDFDocEncoding.cxx
@@ -0,0 +1,44 @@
+//========================================================================
+//
+// PDFDocEncoding.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include "PDFDocEncoding.h"
+
+Unicode pdfDocEncoding[256] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10
+ 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, // 20
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, // 30
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, // 40
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, // 50
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, // 60
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, // 70
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
+ 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, // 80
+ 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
+ 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, // 90
+ 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000,
+ 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, // a0
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, // b0
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, // c0
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, // d0
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, // e0
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, // f0
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+};
diff --git a/pdftops/PDFDocEncoding.h b/pdftops/PDFDocEncoding.h
new file mode 100644
index 000000000..3259d3e10
--- /dev/null
+++ b/pdftops/PDFDocEncoding.h
@@ -0,0 +1,16 @@
+//========================================================================
+//
+// PDFDocEncoding.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PDFDOCENCODING_H
+#define PDFDOCENCODING_H
+
+#include "CharTypes.h"
+
+extern Unicode pdfDocEncoding[256];
+
+#endif
diff --git a/pdftops/PSOutputDev.cxx b/pdftops/PSOutputDev.cxx
new file mode 100644
index 000000000..5d3e8a47e
--- /dev/null
+++ b/pdftops/PSOutputDev.cxx
@@ -0,0 +1,3618 @@
+//========================================================================
+//
+// PSOutputDev.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <math.h>
+#include "GString.h"
+#include "GList.h"
+#include "config.h"
+#include "GlobalParams.h"
+#include "Object.h"
+#include "Error.h"
+#include "Function.h"
+#include "Gfx.h"
+#include "GfxState.h"
+#include "GfxFont.h"
+#include "UnicodeMap.h"
+#include "FontFile.h"
+#include "Catalog.h"
+#include "Page.h"
+#include "Stream.h"
+#include "Annot.h"
+#include "PSOutputDev.h"
+
+#ifdef MACOS
+// needed for setting type/creator of MacOS files
+#include "ICSupport.h"
+#endif
+
+//------------------------------------------------------------------------
+// PostScript prolog and setup
+//------------------------------------------------------------------------
+
+static const char *prolog[] = {
+ "/xpdf 75 dict def xpdf begin",
+ "% PDF special state",
+ "/pdfDictSize 15 def",
+ "~1",
+ "/pdfStates 64 array def",
+ " 0 1 63 {",
+ " pdfStates exch pdfDictSize dict",
+ " dup /pdfStateIdx 3 index put",
+ " put",
+ " } for",
+ "~a",
+ "/pdfSetup {",
+#if 0 /* NOT FOR CUPS */
+ " 3 1 roll 2 array astore",
+ " /setpagedevice where {",
+ " pop 3 dict begin",
+ " /PageSize exch def",
+ " /ImagingBBox null def",
+ " /Policies 1 dict dup begin /PageSize 3 def end def",
+ " { /Duplex true def } if",
+ " currentdict end setpagedevice",
+ " } {",
+ " pop pop",
+ " } ifelse",
+#else
+ " pop pop pop",
+#endif /* 0 */
+ "} def",
+ "~1",
+ "/pdfOpNames [",
+ " /pdfFill /pdfStroke /pdfLastFill /pdfLastStroke",
+ " /pdfTextMat /pdfFontSize /pdfCharSpacing /pdfTextRender",
+ " /pdfTextRise /pdfWordSpacing /pdfHorizScaling /pdfTextClipPath",
+ "] def",
+ "~a",
+ "/pdfStartPage {",
+ "~1",
+ " pdfStates 0 get begin",
+ "~2",
+ " pdfDictSize dict begin",
+ "~a",
+ " /pdfFill [0] def",
+ " /pdfStroke [0] def",
+ " /pdfLastFill false def",
+ " /pdfLastStroke false def",
+ " /pdfTextMat [1 0 0 1 0 0] def",
+ " /pdfFontSize 0 def",
+ " /pdfCharSpacing 0 def",
+ " /pdfTextRender 0 def",
+ " /pdfTextRise 0 def",
+ " /pdfWordSpacing 0 def",
+ " /pdfHorizScaling 1 def",
+ " /pdfTextClipPath [] def",
+ "} def",
+ "/pdfEndPage { end } def",
+ "% separation convention operators",
+ "/findcmykcustomcolor where {",
+ " pop",
+ "}{",
+ " /findcmykcustomcolor { 5 array astore } def",
+ "} ifelse",
+ "/setcustomcolor where {",
+ " pop",
+ "}{",
+ " /setcustomcolor {",
+ " exch",
+ " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+ " 0 4 getinterval cvx",
+ " [ exch /dup load exch { mul exch dup } /forall load",
+ " /pop load dup ] cvx",
+ " ] setcolorspace setcolor",
+ " } def",
+ "} ifelse",
+ "/customcolorimage where {",
+ " pop",
+ "}{",
+ " /customcolorimage {",
+ " gsave",
+ " [ exch /Separation exch dup 4 get exch /DeviceCMYK exch",
+ " 0 4 getinterval",
+ " [ exch /dup load exch { mul exch dup } /forall load",
+ " /pop load dup ] cvx",
+ " ] setcolorspace",
+ " 10 dict begin",
+ " /ImageType 1 def",
+ " /DataSource exch def",
+ " /ImageMatrix exch def",
+ " /BitsPerComponent exch def",
+ " /Height exch def",
+ " /Width exch def",
+ " /Decode [1 0] def",
+ " currentdict end",
+ " image",
+ " grestore",
+ " } def",
+ "} ifelse",
+ "% PDF color state",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStroke aload length",
+ " dup 1 eq {",
+ " pop setgray",
+ " }{",
+ " dup 3 eq {",
+ " pop setrgbcolor",
+ " }{",
+ " 4 eq {",
+ " setcmykcolor",
+ " }{",
+ " findcmykcustomcolor exch setcustomcolor",
+ " } ifelse",
+ " } ifelse",
+ " } ifelse",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFill aload length",
+ " dup 1 eq {",
+ " pop setgray",
+ " }{",
+ " dup 3 eq {",
+ " pop setrgbcolor",
+ " }{",
+ " 4 eq {",
+ " setcmykcolor",
+ " }{",
+ " findcmykcustomcolor exch setcustomcolor",
+ " } ifelse",
+ " } ifelse",
+ " } ifelse",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
+ "% build a font",
+ "/pdfMakeFont {",
+ " 4 3 roll findfont",
+ " 4 2 roll matrix scale makefont",
+ " dup length dict begin",
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall",
+ " /Encoding exch def",
+ " currentdict",
+ " end",
+ " definefont pop",
+ "} def",
+ "/pdfMakeFont16 {",
+ " exch findfont",
+ " dup length dict begin",
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall",
+ " /WMode exch def",
+ " currentdict",
+ " end",
+ " definefont pop",
+ "} def",
+ "/pdfMakeFont16L3 {",
+ " 1 index /CIDFont resourcestatus {",
+ " pop pop 1 index /CIDFont findresource /CIDFontType known",
+ " } {",
+ " false",
+ " } ifelse",
+ " {",
+ " 0 eq { /Identity-H } { /Identity-V } ifelse",
+ " exch 1 array astore composefont pop",
+ " } {",
+ " pdfMakeFont16",
+ " } ifelse",
+ "} def",
+ "% graphics state operators",
+ "~1",
+ "/q {",
+ " gsave",
+ " pdfOpNames length 1 sub -1 0 { pdfOpNames exch get load } for",
+ " pdfStates pdfStateIdx 1 add get begin",
+ " pdfOpNames { exch def } forall",
+ "} def",
+ "~2",
+ "/q { gsave pdfDictSize dict begin } def",
+ "~a",
+ "/Q { end grestore } def",
+ "/cm { concat } def",
+ "/d { setdash } def",
+ "/i { setflat } def",
+ "/j { setlinejoin } def",
+ "/J { setlinecap } def",
+ "/M { setmiterlimit } def",
+ "/w { setlinewidth } def",
+ "% color operators",
+ "/g { dup 1 array astore /pdfFill exch def setgray",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/G { dup 1 array astore /pdfStroke exch def setgray",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/ck { 6 copy 6 array astore /pdfFill exch def",
+ " findcmykcustomcolor exch setcustomcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/CK { 6 copy 6 array astore /pdfStroke exch def",
+ " findcmykcustomcolor exch setcustomcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "% path segment operators",
+ "/m { moveto } def",
+ "/l { lineto } def",
+ "/c { curveto } def",
+ "/re { 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto",
+ " neg 0 rlineto closepath } def",
+ "/h { closepath } def",
+ "% path painting operators",
+ "/S { sCol stroke } def",
+ "/Sf { fCol stroke } def",
+ "/f { fCol fill } def",
+ "/f* { fCol eofill } def",
+ "% clipping operators",
+ "/W { clip newpath } def",
+ "/W* { eoclip newpath } def",
+ "% text state operators",
+ "/Tc { /pdfCharSpacing exch def } def",
+ "/Tf { dup /pdfFontSize exch def",
+ " dup pdfHorizScaling mul exch matrix scale",
+ " pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put",
+ " exch findfont exch makefont setfont } def",
+ "/Tr { /pdfTextRender exch def } def",
+ "/Ts { /pdfTextRise exch def } def",
+ "/Tw { /pdfWordSpacing exch def } def",
+ "/Tz { /pdfHorizScaling exch def } def",
+ "% text positioning operators",
+ "/Td { pdfTextMat transform moveto } def",
+ "/Tm { /pdfTextMat exch def } def",
+ "% text string operators",
+ "/cshow where {",
+ " pop",
+ " /cshow2 {",
+ " dup {",
+ " pop pop",
+ " 1 string dup 0 3 index put 3 index exec",
+ " } exch cshow",
+ " pop pop",
+ " } def",
+ "}{",
+ " /cshow2 {",
+ " currentfont /FontType get 0 eq {",
+ " 0 2 2 index length 1 sub {",
+ " 2 copy get exch 1 add 2 index exch get",
+ " 2 copy exch 256 mul add",
+ " 2 string dup 0 6 5 roll put dup 1 5 4 roll put",
+ " 3 index exec",
+ " } for",
+ " } {",
+ " dup {",
+ " 1 string dup 0 3 index put 3 index exec",
+ " } forall",
+ " } ifelse",
+ " pop pop",
+ " } def",
+ "} ifelse",
+ "/awcp {", // awidthcharpath
+ " exch {",
+ " false charpath",
+ " 5 index 5 index rmoveto",
+ " 6 index eq { 7 index 7 index rmoveto } if",
+ " } exch cshow2",
+ " 6 {pop} repeat",
+ "} def",
+ "/Tj {",
+ " fCol", // because stringwidth has to draw Type 3 chars
+ " 1 index stringwidth pdfTextMat idtransform pop",
+ " sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
+ " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
+ " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
+ " pdfTextMat dtransform",
+ " 6 5 roll Tj1",
+ "} def",
+ "/Tj16 {",
+ " fCol", // because stringwidth has to draw Type 3 chars
+ " 2 index stringwidth pdfTextMat idtransform pop",
+ " sub exch div",
+ " pdfWordSpacing pdfHorizScaling mul 0 pdfTextMat dtransform 32",
+ " 4 3 roll pdfCharSpacing pdfHorizScaling mul add 0",
+ " pdfTextMat dtransform",
+ " 6 5 roll Tj1",
+ "} def",
+ "/Tj16V {",
+ " fCol", // because stringwidth has to draw Type 3 chars
+ " 2 index stringwidth pdfTextMat idtransform exch pop",
+ " sub exch div",
+ " 0 pdfWordSpacing pdfTextMat dtransform 32",
+ " 4 3 roll pdfCharSpacing add 0 exch",
+ " pdfTextMat dtransform",
+ " 6 5 roll Tj1",
+ "} def",
+ "/Tj1 {",
+ " 0 pdfTextRise pdfTextMat dtransform rmoveto",
+ " currentpoint 8 2 roll",
+ " pdfTextRender 1 and 0 eq {",
+ " 6 copy awidthshow",
+ " } if",
+ " pdfTextRender 3 and dup 1 eq exch 2 eq or {",
+ " 7 index 7 index moveto",
+ " 6 copy",
+ " currentfont /FontType get 3 eq { fCol } { sCol } ifelse",
+ " false awcp currentpoint stroke moveto",
+ " } if",
+ " pdfTextRender 4 and 0 ne {",
+ " 8 6 roll moveto",
+ " false awcp",
+ " /pdfTextClipPath [ pdfTextClipPath aload pop",
+ " {/moveto cvx}",
+ " {/lineto cvx}",
+ " {/curveto cvx}",
+ " {/closepath cvx}",
+ " pathforall ] def",
+ " currentpoint newpath moveto",
+ " } {",
+ " 8 {pop} repeat",
+ " } ifelse",
+ " 0 pdfTextRise neg pdfTextMat dtransform rmoveto",
+ "} def",
+ "/TJm { pdfFontSize 0.001 mul mul neg 0",
+ " pdfTextMat dtransform rmoveto } def",
+ "/TJmV { pdfFontSize 0.001 mul mul neg 0 exch",
+ " pdfTextMat dtransform rmoveto } def",
+ "/Tclip { pdfTextClipPath cvx exec clip newpath",
+ " /pdfTextClipPath [] def } def",
+ "% Level 1 image operators",
+ "/pdfIm1 {",
+ " /pdfImBuf1 4 index string def",
+ " { currentfile pdfImBuf1 readhexstring pop } image",
+ "} def",
+ "/pdfIm1Sep {",
+ " /pdfImBuf1 4 index string def",
+ " /pdfImBuf2 4 index string def",
+ " /pdfImBuf3 4 index string def",
+ " /pdfImBuf4 4 index string def",
+ " { currentfile pdfImBuf1 readhexstring pop }",
+ " { currentfile pdfImBuf2 readhexstring pop }",
+ " { currentfile pdfImBuf3 readhexstring pop }",
+ " { currentfile pdfImBuf4 readhexstring pop }",
+ " true 4 colorimage",
+ "} def",
+ "/pdfImM1 {",
+ " /pdfImBuf1 4 index 7 add 8 idiv string def",
+ " { currentfile pdfImBuf1 readhexstring pop } imagemask",
+ "} def",
+ "% Level 2 image operators",
+ "/pdfImBuf 100 string def",
+ "/pdfIm {",
+ " image",
+ " { currentfile pdfImBuf readline",
+ " not { pop exit } if",
+ " (%-EOD-) eq { exit } if } loop",
+ "} def",
+ "/pdfImSep {",
+ " findcmykcustomcolor exch",
+ " dup /Width get /pdfImBuf1 exch string def",
+ " dup /Decode get aload pop 1 index sub /pdfImDecodeRange exch def",
+ " /pdfImDecodeLow exch def",
+ " begin Width Height BitsPerComponent ImageMatrix DataSource end",
+ " /pdfImData exch def",
+ " { pdfImData pdfImBuf1 readstring pop",
+ " 0 1 2 index length 1 sub {",
+ " 1 index exch 2 copy get",
+ " pdfImDecodeRange mul 255 div pdfImDecodeLow add round cvi",
+ " 255 exch sub put",
+ " } for }",
+ " 6 5 roll customcolorimage",
+ " { currentfile pdfImBuf readline",
+ " not { pop exit } if",
+ " (%-EOD-) eq { exit } if } loop",
+ "} def",
+ "/pdfImM {",
+ " fCol imagemask",
+ " { currentfile pdfImBuf readline",
+ " not { pop exit } if",
+ " (%-EOD-) eq { exit } if } loop",
+ "} def",
+ "end",
+ NULL
+};
+
+static const char *cmapProlog[] = {
+ "/CIDInit /ProcSet findresource begin",
+ "10 dict begin",
+ " begincmap",
+ " /CMapType 1 def",
+ " /CMapName /Identity-H def",
+ " /CIDSystemInfo 3 dict dup begin",
+ " /Registry (Adobe) def",
+ " /Ordering (Identity) def",
+ " /Supplement 0 def",
+ " end def",
+ " 1 begincodespacerange",
+ " <0000> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 0",
+ " endcidrange",
+ " endcmap",
+ " currentdict CMapName exch /CMap defineresource pop",
+ "end",
+ "10 dict begin",
+ " begincmap",
+ " /CMapType 1 def",
+ " /CMapName /Identity-V def",
+ " /CIDSystemInfo 3 dict dup begin",
+ " /Registry (Adobe) def",
+ " /Ordering (Identity) def",
+ " /Supplement 0 def",
+ " end def",
+ " /WMode 1 def",
+ " 1 begincodespacerange",
+ " <0000> <ffff>",
+ " endcodespacerange",
+ " 0 usefont",
+ " 1 begincidrange",
+ " <0000> <ffff> 0",
+ " endcidrange",
+ " endcmap",
+ " currentdict CMapName exch /CMap defineresource pop",
+ "end",
+ "end",
+ NULL
+};
+
+//------------------------------------------------------------------------
+// Fonts
+//------------------------------------------------------------------------
+
+struct PSSubstFont {
+ const char *psName; // PostScript name
+ double mWidth; // width of 'm' character
+};
+
+static const char *psFonts[] = {
+ "Courier",
+ "Courier-Bold",
+ "Courier-Oblique",
+ "Courier-BoldOblique",
+ "Helvetica",
+ "Helvetica-Bold",
+ "Helvetica-Oblique",
+ "Helvetica-BoldOblique",
+ "Symbol",
+ "Times-Roman",
+ "Times-Bold",
+ "Times-Italic",
+ "Times-BoldItalic",
+ "ZapfDingbats",
+ NULL
+};
+
+static PSSubstFont psSubstFonts[] = {
+ {"Helvetica", 0.833},
+ {"Helvetica-Oblique", 0.833},
+ {"Helvetica-Bold", 0.889},
+ {"Helvetica-BoldOblique", 0.889},
+ {"Times-Roman", 0.788},
+ {"Times-Italic", 0.722},
+ {"Times-Bold", 0.833},
+ {"Times-BoldItalic", 0.778},
+ {"Courier", 0.600},
+ {"Courier-Oblique", 0.600},
+ {"Courier-Bold", 0.600},
+ {"Courier-BoldOblique", 0.600}
+};
+
+// Encoding info for substitute 16-bit font
+struct PSFont16Enc {
+ Ref fontID;
+ GString *enc;
+};
+
+//------------------------------------------------------------------------
+// process colors
+//------------------------------------------------------------------------
+
+#define psProcessCyan 1
+#define psProcessMagenta 2
+#define psProcessYellow 4
+#define psProcessBlack 8
+#define psProcessCMYK 15
+
+//------------------------------------------------------------------------
+// PSOutCustomColor
+//------------------------------------------------------------------------
+
+class PSOutCustomColor {
+public:
+
+ PSOutCustomColor(double cA, double mA,
+ double yA, double kA, GString *nameA);
+ ~PSOutCustomColor();
+
+ double c, m, y, k;
+ GString *name;
+ PSOutCustomColor *next;
+};
+
+PSOutCustomColor::PSOutCustomColor(double cA, double mA,
+ double yA, double kA, GString *nameA) {
+ c = cA;
+ m = mA;
+ y = yA;
+ k = kA;
+ name = nameA;
+ next = NULL;
+}
+
+PSOutCustomColor::~PSOutCustomColor() {
+ delete name;
+}
+
+//------------------------------------------------------------------------
+// PSOutputDev
+//------------------------------------------------------------------------
+
+extern "C" {
+typedef void (*SignalFunc)(int);
+}
+
+static void outputToFile(void *stream, const char *data, int len) {
+ fwrite(data, 1, len, (FILE *)stream);
+}
+
+PSOutputDev::PSOutputDev(const char *fileName, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA, int paperHeightA,
+ GBool manualCtrlA) {
+ FILE *f;
+ PSFileType fileTypeA;
+
+ underlayCbk = NULL;
+ underlayCbkData = NULL;
+ overlayCbk = NULL;
+ overlayCbkData = NULL;
+
+ fontIDs = NULL;
+ fontFileIDs = NULL;
+ fontFileNames = NULL;
+ font16Enc = NULL;
+ xobjStack = NULL;
+ embFontList = NULL;
+ customColors = NULL;
+ haveTextClip = gFalse;
+ t3String = NULL;
+
+ // open file or pipe
+ if (!strcmp(fileName, "-")) {
+ fileTypeA = psStdout;
+ f = stdout;
+ } else if (fileName[0] == '|') {
+ fileTypeA = psPipe;
+#ifdef HAVE_POPEN
+#ifndef WIN32
+ signal(SIGPIPE, (SignalFunc)SIG_IGN);
+#endif
+ if (!(f = popen(fileName + 1, "w"))) {
+ error(-1, "Couldn't run print command '%s'", fileName);
+ ok = gFalse;
+ return;
+ }
+#else
+ error(-1, "Print commands are not supported ('%s')", fileName);
+ ok = gFalse;
+ return;
+#endif
+ } else {
+ fileTypeA = psFile;
+ if (!(f = fopen(fileName, "w"))) {
+ error(-1, "Couldn't open PostScript file '%s'", fileName);
+ ok = gFalse;
+ return;
+ }
+ }
+
+ init(outputToFile, f, fileTypeA,
+ xrefA, catalog, firstPage, lastPage, modeA,
+ paperWidthA, paperHeightA, manualCtrlA);
+}
+
+PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
+ XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA, int paperHeightA,
+ GBool manualCtrlA) {
+ fontIDs = NULL;
+ fontFileIDs = NULL;
+ fontFileNames = NULL;
+ font16Enc = NULL;
+ xobjStack = NULL;
+ embFontList = NULL;
+ customColors = NULL;
+ haveTextClip = gFalse;
+ t3String = NULL;
+
+ init(outputFuncA, outputStreamA, psGeneric,
+ xrefA, catalog, firstPage, lastPage, modeA,
+ paperWidthA, paperHeightA, manualCtrlA);
+}
+
+void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
+ PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA, int paperHeightA,
+ GBool manualCtrlA) {
+ Page *page;
+
+ // initialize
+ ok = gTrue;
+ outputFunc = outputFuncA;
+ outputStream = outputStreamA;
+ fileType = fileTypeA;
+ xref = xrefA;
+ level = globalParams->getPSLevel();
+ mode = modeA;
+ paperWidth = paperWidthA;
+ paperHeight = paperHeightA;
+ if (paperWidth == 0) {
+ paperWidth = globalParams->getPSPaperWidth();
+ }
+ if (paperHeight == 0) {
+ paperHeight = globalParams->getPSPaperHeight();
+ }
+ if (paperWidth < 0 || paperHeight < 0) {
+ page = catalog->getPage(firstPage);
+ paperWidth = (int)(page->getWidth() + 0.5);
+ paperHeight = (int)(page->getHeight() + 0.5);
+ }
+ manualCtrl = manualCtrlA;
+ if (mode == psModeForm) {
+ lastPage = firstPage;
+ }
+ processColors = 0;
+ inType3Char = gFalse;
+
+#if OPI_SUPPORT
+ // initialize OPI nesting levels
+ opi13Nest = 0;
+ opi20Nest = 0;
+#endif
+
+ // initialize fontIDs, fontFileIDs, and fontFileNames lists
+ fontIDSize = 64;
+ fontIDLen = 0;
+ fontIDs = (Ref *)gmalloc(fontIDSize * sizeof(Ref));
+ fontFileIDSize = 64;
+ fontFileIDLen = 0;
+ fontFileIDs = (Ref *)gmalloc(fontFileIDSize * sizeof(Ref));
+ fontFileNameSize = 64;
+ fontFileNameLen = 0;
+ fontFileNames = (GString **)gmalloc(fontFileNameSize * sizeof(GString *));
+ nextTrueTypeNum = 0;
+ font16EncLen = 0;
+ font16EncSize = 0;
+
+ xobjStack = new GList();
+ numSaves = 0;
+
+ // initialize embedded font resource comment list
+ embFontList = new GString();
+
+ if (!manualCtrl) {
+ writeHeader(firstPage, lastPage, catalog->getPage(firstPage)->getBox());
+ if (mode != psModeForm) {
+ writePS("%%BeginProlog\n");
+ }
+ writeXpdfProcset();
+ if (mode != psModeForm) {
+ writePS("%%EndProlog\n");
+ writePS("%%BeginSetup\n");
+ }
+ writeDocSetup(catalog, firstPage, lastPage);
+ if (mode != psModeForm) {
+ writePS("%%EndSetup\n");
+ }
+ }
+
+ // initialize sequential page number
+ seqPage = 1;
+}
+
+PSOutputDev::~PSOutputDev() {
+ PSOutCustomColor *cc;
+ int i;
+
+ if (ok) {
+ if (!manualCtrl) {
+ writePS("%%Trailer\n");
+ writeTrailer();
+ if (mode != psModeForm) {
+ writePS("%%EOF\n");
+ }
+ }
+ if (fileType == psFile) {
+#ifdef MACOS
+ ICS_MapRefNumAndAssign((short)((FILE *)outputStream)->handle);
+#endif
+ fclose((FILE *)outputStream);
+ }
+#ifdef HAVE_POPEN
+ else if (fileType == psPipe) {
+ pclose((FILE *)outputStream);
+#ifndef WIN32
+ signal(SIGPIPE, (SignalFunc)SIG_DFL);
+#endif
+ }
+#endif
+ }
+ if (embFontList) {
+ delete embFontList;
+ }
+ if (fontIDs) {
+ gfree(fontIDs);
+ }
+ if (fontFileIDs) {
+ gfree(fontFileIDs);
+ }
+ if (fontFileNames) {
+ for (i = 0; i < fontFileNameLen; ++i) {
+ delete fontFileNames[i];
+ }
+ gfree(fontFileNames);
+ }
+ if (font16Enc) {
+ for (i = 0; i < font16EncLen; ++i) {
+ delete font16Enc[i].enc;
+ }
+ gfree(font16Enc);
+ }
+ if (xobjStack) {
+ delete xobjStack;
+ }
+ while (customColors) {
+ cc = customColors;
+ customColors = cc->next;
+ delete cc;
+ }
+}
+
+void PSOutputDev::writeHeader(int firstPage, int lastPage, PDFRectangle *box) {
+ switch (mode) {
+ case psModePS:
+ writePS("%!PS-Adobe-3.0\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
+ }
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePSFmt("%%%%DocumentMedia: plain %d %d 0 () ()\n",
+ paperWidth, paperHeight);
+ writePSFmt("%%%%BoundingBox: 0 0 %d %d\n", paperWidth, paperHeight);
+ writePSFmt("%%%%Pages: %d\n", lastPage - firstPage + 1);
+ writePSFmt("%%%%BoundingBox: 0 0 %d %d\n", paperWidth, paperHeight);
+ writePS("%%EndComments\n");
+ writePS("%%BeginDefaults\n");
+ writePS("%%PageMedia: plain\n");
+ writePS("%%EndDefaults\n");
+ break;
+ case psModeEPS:
+ writePS("%!PS-Adobe-3.0 EPSF-3.0\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
+ }
+ writePSFmt("%%%%BoundingBox: %d %d %d %d\n",
+ (int)floor(box->x1), (int)floor(box->y1),
+ (int)ceil(box->x2), (int)ceil(box->y2));
+ if (floor(box->x1) != ceil(box->x1) ||
+ floor(box->y1) != ceil(box->y1) ||
+ floor(box->x2) != ceil(box->x2) ||
+ floor(box->y2) != ceil(box->y2)) {
+ writePSFmt("%%%%HiResBoundingBox: %g %g %g %g\n",
+ box->x1, box->y1, box->x2, box->y2);
+ }
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePS("%%EndComments\n");
+ break;
+ case psModeForm:
+ writePS("%!PS-Adobe-3.0 Resource-Form\n");
+ writePSFmt("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
+ writePSFmt("%%%%LanguageLevel: %d\n",
+ (level == psLevel1 || level == psLevel1Sep) ? 1 :
+ (level == psLevel2 || level == psLevel2Sep) ? 2 : 3);
+ if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors: (atend)\n");
+ writePS("%%DocumentCustomColors: (atend)\n");
+ }
+ writePS("%%DocumentSuppliedResources: (atend)\n");
+ writePS("%%EndComments\n");
+ writePS("32 dict dup begin\n");
+ writePSFmt("/BBox [%d %d %d %d] def\n",
+ (int)box->x1, (int)box->y1, (int)box->x2, (int)box->y2);
+ writePS("/FormType 1 def\n");
+ writePS("/Matrix [1 0 0 1 0 0] def\n");
+ break;
+ }
+ }
+
+void PSOutputDev::writeXpdfProcset() {
+ char prologLevel;
+ const char **p;
+
+ writePSFmt("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
+ prologLevel = 'a';
+ for (p = prolog; *p; ++p) {
+ if ((*p)[0] == '~' && (*p)[1] == '1') {
+ prologLevel = '1';
+ } else if ((*p)[0] == '~' && (*p)[1] == '2') {
+ prologLevel = '2';
+ } else if ((*p)[0] == '~' && (*p)[1] == 'a') {
+ prologLevel = 'a';
+ } else if (prologLevel == 'a' ||
+ (prologLevel == '1' && level < psLevel2) ||
+ (prologLevel == '2' && level >= psLevel2)) {
+ writePSFmt("%s\n", *p);
+ }
+ }
+ writePS("%%EndResource\n");
+
+ if (level >= psLevel3) {
+ for (p = cmapProlog; *p; ++p) {
+ writePSFmt("%s\n", *p);
+ }
+ }
+ }
+
+void PSOutputDev::writeDocSetup(Catalog *catalog,
+ int firstPage, int lastPage) {
+ Page *page;
+ Dict *resDict;
+ Annots *annots;
+ Object obj1, obj2;
+ int pg, i;
+
+ if (mode == psModeForm) {
+ // swap the form and xpdf dicts
+ writePS("xpdf end begin dup begin\n");
+ } else {
+ writePS("xpdf begin\n");
+ }
+ for (pg = firstPage; pg <= lastPage; ++pg) {
+ page = catalog->getPage(pg);
+ if ((resDict = page->getResourceDict())) {
+ setupResources(resDict);
+ }
+ annots = new Annots(xref, page->getAnnots(&obj1));
+ obj1.free();
+ for (i = 0; i < annots->getNumAnnots(); ++i) {
+ if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
+ obj1.streamGetDict()->lookup("Resources", &obj2);
+ if (obj2.isDict()) {
+ setupResources(obj2.getDict());
+ }
+ obj2.free();
+ }
+ obj1.free();
+ }
+ delete annots;
+ }
+ if (mode != psModeForm) {
+ if (mode != psModeEPS && !manualCtrl) {
+ writePSFmt("%d %d %s pdfSetup\n",
+ paperWidth, paperHeight,
+ globalParams->getPSDuplex() ? "true" : "false");
+ }
+#if OPI_SUPPORT
+ if (globalParams->getPSOPI()) {
+ writePS("/opiMatrix matrix currentmatrix def\n");
+ }
+#endif
+ }
+ }
+
+void PSOutputDev::writePageTrailer() {
+ if (mode != psModeForm) {
+ writePS("pdfEndPage\n");
+ }
+}
+
+void PSOutputDev::writeTrailer() {
+ PSOutCustomColor *cc;
+
+ if (mode == psModeForm) {
+ writePS("/Foo exch /Form defineresource pop\n");
+ } else {
+ writePS("end\n");
+ writePS("%%DocumentSuppliedResources:\n");
+ writePS(embFontList->getCString());
+ if (level == psLevel1Sep || level == psLevel2Sep ||
+ level == psLevel3Sep) {
+ writePS("%%DocumentProcessColors:");
+ if (processColors & psProcessCyan) {
+ writePS(" Cyan");
+ }
+ if (processColors & psProcessMagenta) {
+ writePS(" Magenta");
+ }
+ if (processColors & psProcessYellow) {
+ writePS(" Yellow");
+ }
+ if (processColors & psProcessBlack) {
+ writePS(" Black");
+ }
+ writePS("\n");
+ writePS("%%DocumentCustomColors:");
+ for (cc = customColors; cc; cc = cc->next) {
+ writePSFmt(" (%s)", cc->name->getCString());
+ }
+ writePS("\n");
+ writePS("%%CMYKCustomColor:\n");
+ for (cc = customColors; cc; cc = cc->next) {
+ writePSFmt("%%%%+ %g %g %g %g (%s)\n",
+ cc->c, cc->m, cc->y, cc->k, cc->name->getCString());
+ }
+ }
+ }
+}
+
+void PSOutputDev::setupResources(Dict *resDict) {
+ Object xObjDict, xObjRef, xObj, resObj;
+ Ref ref0, ref1;
+ GBool skip;
+ int i, j;
+
+ setupFonts(resDict);
+ setupImages(resDict);
+
+ resDict->lookup("XObject", &xObjDict);
+ if (xObjDict.isDict()) {
+ for (i = 0; i < xObjDict.dictGetLength(); ++i) {
+
+ // avoid infinite recursion on XObjects
+ skip = gFalse;
+ if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) {
+ ref0 = xObjRef.getRef();
+ for (j = 0; j < xobjStack->getLength(); ++j) {
+ ref1 = *(Ref *)xobjStack->get(j);
+ if (ref1.num == ref0.num && ref1.gen == ref0.gen) {
+ skip = gTrue;
+ break;
+ }
+ }
+ if (!skip) {
+ xobjStack->append(&ref0);
+ }
+ }
+ if (!skip) {
+
+ // process the XObject's resource dictionary
+ xObjDict.dictGetVal(i, &xObj);
+ if (xObj.isStream()) {
+ xObj.streamGetDict()->lookup("Resources", &resObj);
+ if (resObj.isDict()) {
+ setupResources(resObj.getDict());
+ }
+ resObj.free();
+ }
+ xObj.free();
+ }
+
+ if (xObjRef.isRef() && !skip) {
+ xobjStack->del(xobjStack->getLength() - 1);
+ }
+ xObjRef.free();
+ }
+ }
+ xObjDict.free();
+}
+
+void PSOutputDev::setupFonts(Dict *resDict) {
+ Object obj1, obj2;
+ Ref r;
+ GfxFontDict *gfxFontDict;
+ GfxFont *font;
+ int i;
+
+ gfxFontDict = NULL;
+ resDict->lookupNF("Font", &obj1);
+ if (obj1.isRef()) {
+ obj1.fetch(xref, &obj2);
+ if (obj2.isDict()) {
+ r = obj1.getRef();
+ gfxFontDict = new GfxFontDict(xref, &r, obj2.getDict());
+ }
+ obj2.free();
+ } else if (obj1.isDict()) {
+ gfxFontDict = new GfxFontDict(xref, NULL, obj1.getDict());
+ }
+ if (gfxFontDict) {
+ for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
+ font = gfxFontDict->getFont(i);
+ setupFont(font, resDict);
+ }
+ delete gfxFontDict;
+ }
+ obj1.free();
+}
+
+void PSOutputDev::setupFont(GfxFont *font, Dict *parentResDict) {
+ Ref fontFileID;
+ GString *name;
+ PSFontParam *fontParam;
+ GString *psName;
+ char type3Name[64], buf[16];
+ GBool subst;
+ UnicodeMap *uMap;
+ const char *charName;
+ double xs, ys;
+ int code;
+ double w1, w2;
+ double *fm;
+ int i, j;
+
+ // check if font is already set up
+ for (i = 0; i < fontIDLen; ++i) {
+ if (fontIDs[i].num == font->getID()->num &&
+ fontIDs[i].gen == font->getID()->gen) {
+ return;
+ }
+ }
+
+ // add entry to fontIDs list
+ if (fontIDLen >= fontIDSize) {
+ fontIDSize += 64;
+ fontIDs = (Ref *)grealloc(fontIDs, fontIDSize * sizeof(Ref));
+ }
+ fontIDs[fontIDLen++] = *font->getID();
+
+ xs = ys = 1;
+ subst = gFalse;
+
+ // check for resident 8-bit font
+ if (font->getName() &&
+ (fontParam = globalParams->getPSFont(font->getName()))) {
+ psName = new GString(fontParam->psFontName->getCString());
+
+ // check for embedded Type 1 font
+ } else if (globalParams->getPSEmbedType1() &&
+ font->getType() == fontType1 &&
+ font->getEmbeddedFontID(&fontFileID)) {
+ psName = filterPSName(font->getEmbeddedFontName());
+ setupEmbeddedType1Font(&fontFileID, psName);
+
+ // check for embedded Type 1C font
+ } else if (globalParams->getPSEmbedType1() &&
+ font->getType() == fontType1C &&
+ font->getEmbeddedFontID(&fontFileID)) {
+ psName = filterPSName(font->getEmbeddedFontName());
+ setupEmbeddedType1CFont(font, &fontFileID, psName);
+
+ // check for external Type 1 font file
+ } else if (globalParams->getPSEmbedType1() &&
+ font->getType() == fontType1 &&
+ font->getExtFontFile()) {
+ // this assumes that the PS font name matches the PDF font name
+ psName = font->getName()->copy();
+ setupExternalType1Font(font->getExtFontFile(), psName);
+
+ // check for embedded TrueType font
+ } else if (globalParams->getPSEmbedTrueType() &&
+ font->getType() == fontTrueType &&
+ font->getEmbeddedFontID(&fontFileID)) {
+ psName = filterPSName(font->getEmbeddedFontName());
+ setupEmbeddedTrueTypeFont(font, &fontFileID, psName);
+
+ // check for external TrueType font file
+ } else if (globalParams->getPSEmbedTrueType() &&
+ font->getType() == fontTrueType &&
+ font->getExtFontFile()) {
+ psName = filterPSName(font->getName());
+ setupExternalTrueTypeFont(font, psName);
+
+ // check for embedded CID PostScript font
+ } else if (globalParams->getPSEmbedCIDPostScript() &&
+ font->getType() == fontCIDType0C &&
+ font->getEmbeddedFontID(&fontFileID)) {
+ psName = filterPSName(font->getEmbeddedFontName());
+ setupEmbeddedCIDType0Font(font, &fontFileID, psName);
+
+ // check for embedded CID TrueType font
+ } else if (globalParams->getPSEmbedCIDTrueType() &&
+ font->getType() == fontCIDType2 &&
+ font->getEmbeddedFontID(&fontFileID)) {
+ psName = filterPSName(font->getEmbeddedFontName());
+ setupEmbeddedCIDTrueTypeFont(font, &fontFileID, psName);
+
+ } else if (font->getType() == fontType3) {
+ sprintf(type3Name, "T3_%d_%d",
+ font->getID()->num, font->getID()->gen);
+ psName = new GString(type3Name);
+ setupType3Font(font, psName, parentResDict);
+
+ // do 8-bit font substitution
+ } else if (!font->isCIDFont()) {
+ subst = gTrue;
+ name = font->getName();
+ psName = NULL;
+ if (name) {
+ for (i = 0; psFonts[i]; ++i) {
+ if (name->cmp(psFonts[i]) == 0) {
+ psName = new GString(psFonts[i]);
+ break;
+ }
+ }
+ }
+ if (!psName) {
+ if (font->isFixedWidth()) {
+ i = 8;
+ } else if (font->isSerif()) {
+ i = 4;
+ } else {
+ i = 0;
+ }
+ if (font->isBold()) {
+ i += 2;
+ }
+ if (font->isItalic()) {
+ i += 1;
+ }
+ psName = new GString(psSubstFonts[i].psName);
+ for (code = 0; code < 256; ++code) {
+ if ((charName = ((Gfx8BitFont *)font)->getCharName(code)) &&
+ charName[0] == 'm' && charName[1] == '\0') {
+ break;
+ }
+ }
+ if (code < 256) {
+ w1 = ((Gfx8BitFont *)font)->getWidth(code);
+ } else {
+ w1 = 0;
+ }
+ w2 = psSubstFonts[i].mWidth;
+ xs = w1 / w2;
+ if (xs < 0.1) {
+ xs = 1;
+ }
+ if (font->getType() == fontType3) {
+ // This is a hack which makes it possible to substitute for some
+ // Type 3 fonts. The problem is that it's impossible to know what
+ // the base coordinate system used in the font is without actually
+ // rendering the font.
+ ys = xs;
+ fm = font->getFontMatrix();
+ if (fm[0] != 0) {
+ ys *= fm[3] / fm[0];
+ }
+ } else {
+ ys = 1;
+ }
+ }
+
+ // do 16-bit font substitution
+ } else if ((fontParam = globalParams->
+ getPSFont16(font->getName(),
+ ((GfxCIDFont *)font)->getCollection(),
+ font->getWMode()))) {
+ subst = gTrue;
+ psName = fontParam->psFontName->copy();
+ if (font16EncLen >= font16EncSize) {
+ font16EncSize += 16;
+ font16Enc = (PSFont16Enc *)grealloc(font16Enc,
+ font16EncSize * sizeof(PSFont16Enc));
+ }
+ font16Enc[font16EncLen].fontID = *font->getID();
+ font16Enc[font16EncLen].enc = fontParam->encoding->copy();
+ if ((uMap = globalParams->getUnicodeMap(font16Enc[font16EncLen].enc))) {
+ uMap->decRefCnt();
+ ++font16EncLen;
+ } else {
+ error(-1, "Couldn't find Unicode map for 16-bit font encoding '%s'",
+ font16Enc[font16EncLen].enc->getCString());
+ }
+
+ // give up - can't do anything with this font
+ } else {
+ error(-1, "Couldn't find a font to substitute for '%s' ('%s' character collection)",
+ font->getName() ? font->getName()->getCString() : "(unnamed)",
+ ((GfxCIDFont *)font)->getCollection()
+ ? ((GfxCIDFont *)font)->getCollection()->getCString()
+ : "(unknown)");
+ return;
+ }
+
+ // generate PostScript code to set up the font
+ if (font->isCIDFont()) {
+ if (level == psLevel3 || level == psLevel3Sep) {
+ writePSFmt("/F%d_%d /%s %d pdfMakeFont16L3\n",
+ font->getID()->num, font->getID()->gen, psName->getCString(),
+ font->getWMode());
+ } else {
+ writePSFmt("/F%d_%d /%s %d pdfMakeFont16\n",
+ font->getID()->num, font->getID()->gen, psName->getCString(),
+ font->getWMode());
+ }
+ } else {
+ writePSFmt("/F%d_%d /%s %g %g\n",
+ font->getID()->num, font->getID()->gen, psName->getCString(),
+ xs, ys);
+ for (i = 0; i < 256; i += 8) {
+ writePSFmt((i == 0) ? "[ " : " ");
+ for (j = 0; j < 8; ++j) {
+ if (font->getType() == fontTrueType &&
+ !subst &&
+ !((Gfx8BitFont *)font)->getHasEncoding()) {
+ sprintf(buf, "c%02x", i+j);
+ charName = buf;
+ } else {
+ charName = ((Gfx8BitFont *)font)->getCharName(i+j);
+ // this is a kludge for broken PDF files that encode char 32
+ // as .notdef
+ if (i+j == 32 && charName && !strcmp(charName, ".notdef")) {
+ charName = "space";
+ }
+ }
+ writePS("/");
+ writePSName(charName ? charName : ".notdef");
+ }
+ writePS((i == 256-8) ? "]\n" : "\n");
+ }
+ writePS("pdfMakeFont\n");
+ }
+
+ delete psName;
+}
+
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, GString *psName) {
+ static char hexChar[17] = "0123456789abcdef";
+ Object refObj, strObj, obj1, obj2, obj3;
+ Dict *dict;
+ int length1, length2, length3;
+ int c;
+ int start[4];
+ GBool binMode;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileIDLen; ++i) {
+ if (fontFileIDs[i].num == id->num &&
+ fontFileIDs[i].gen == id->gen)
+ return;
+ }
+
+ // add entry to fontFileIDs list
+ if (fontFileIDLen >= fontFileIDSize) {
+ fontFileIDSize += 64;
+ fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+ }
+ fontFileIDs[fontFileIDLen++] = *id;
+
+ // get the font stream and info
+ refObj.initRef(id->num, id->gen);
+ refObj.fetch(xref, &strObj);
+ refObj.free();
+ if (!strObj.isStream()) {
+ error(-1, "Embedded font file object is not a stream");
+ goto err1;
+ }
+ if (!(dict = strObj.streamGetDict())) {
+ error(-1, "Embedded font stream is missing its dictionary");
+ goto err1;
+ }
+ dict->lookup("Length1", &obj1);
+ dict->lookup("Length2", &obj2);
+ dict->lookup("Length3", &obj3);
+ if (!obj1.isInt() || !obj2.isInt() || !obj3.isInt()) {
+ error(-1, "Missing length fields in embedded font stream dictionary");
+ obj1.free();
+ obj2.free();
+ obj3.free();
+ goto err1;
+ }
+ length1 = obj1.getInt();
+ length2 = obj2.getInt();
+ length3 = obj3.getInt();
+ obj1.free();
+ obj2.free();
+ obj3.free();
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // copy ASCII portion of font
+ strObj.streamReset();
+ for (i = 0; i < length1 && (c = strObj.streamGetChar()) != EOF; ++i) {
+ writePSChar(c);
+ }
+
+ // figure out if encrypted portion is binary or ASCII
+ binMode = gFalse;
+ for (i = 0; i < 4; ++i) {
+ start[i] = strObj.streamGetChar();
+ if (start[i] == EOF) {
+ error(-1, "Unexpected end of file in embedded font stream");
+ goto err1;
+ }
+ if (!((start[i] >= '0' && start[i] <= '9') ||
+ (start[i] >= 'A' && start[i] <= 'F') ||
+ (start[i] >= 'a' && start[i] <= 'f')))
+ binMode = gTrue;
+ }
+
+ // convert binary data to ASCII
+ if (binMode) {
+ for (i = 0; i < 4; ++i) {
+ writePSChar(hexChar[(start[i] >> 4) & 0x0f]);
+ writePSChar(hexChar[start[i] & 0x0f]);
+ }
+ // if Length2 is incorrect (too small), font data gets chopped, so
+ // we take a few extra characters from the trailer just in case
+ length2 += length3 >= 8 ? 8 : length3;
+ while (i < length2) {
+ if ((c = strObj.streamGetChar()) == EOF) {
+ break;
+ }
+ writePSChar(hexChar[(c >> 4) & 0x0f]);
+ writePSChar(hexChar[c & 0x0f]);
+ if (++i % 32 == 0) {
+ writePSChar('\n');
+ }
+ }
+ if (i % 32 > 0) {
+ writePSChar('\n');
+ }
+
+ // already in ASCII format -- just copy it
+ } else {
+ for (i = 0; i < 4; ++i) {
+ writePSChar(start[i]);
+ }
+ for (i = 4; i < length2; ++i) {
+ if ((c = strObj.streamGetChar()) == EOF) {
+ break;
+ }
+ writePSChar(c);
+ }
+ }
+
+ // write padding and "cleartomark"
+ for (i = 0; i < 8; ++i) {
+ writePS("00000000000000000000000000000000"
+ "00000000000000000000000000000000\n");
+ }
+ writePS("cleartomark\n");
+
+ // ending comment
+ writePS("%%EndResource\n");
+
+ err1:
+ strObj.streamClose();
+ strObj.free();
+}
+
+//~ This doesn't handle .pfb files or binary eexec data (which only
+//~ happens in pfb files?).
+void PSOutputDev::setupExternalType1Font(GString *fileName, GString *psName) {
+ FILE *fontFile;
+ int c;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileNameLen; ++i) {
+ if (!fontFileNames[i]->cmp(fileName)) {
+ return;
+ }
+ }
+
+ // add entry to fontFileNames list
+ if (fontFileNameLen >= fontFileNameSize) {
+ fontFileNameSize += 64;
+ fontFileNames = (GString **)grealloc(fontFileNames,
+ fontFileNameSize * sizeof(GString *));
+ }
+ fontFileNames[fontFileNameLen++] = fileName->copy();
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // copy the font file
+ if (!(fontFile = fopen(fileName->getCString(), "rb"))) {
+ error(-1, "Couldn't open external font file");
+ return;
+ }
+ while ((c = fgetc(fontFile)) != EOF) {
+ writePSChar(c);
+ }
+ fclose(fontFile);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
+ GString *psName) {
+ char *fontBuf;
+ int fontLen;
+ Type1CFontFile *t1cFile;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileIDLen; ++i) {
+ if (fontFileIDs[i].num == id->num &&
+ fontFileIDs[i].gen == id->gen)
+ return;
+ }
+
+ // add entry to fontFileIDs list
+ if (fontFileIDLen >= fontFileIDSize) {
+ fontFileIDSize += 64;
+ fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+ }
+ fontFileIDs[fontFileIDLen++] = *id;
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 1 font
+ fontBuf = font->readEmbFontFile(xref, &fontLen);
+ t1cFile = new Type1CFontFile(fontBuf, fontLen);
+ if (t1cFile->isOk()) {
+ t1cFile->convertToType1(outputFunc, outputStream);
+ }
+ delete t1cFile;
+ gfree(fontBuf);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id,
+ GString *psName) {
+ char unique[32];
+ char *fontBuf;
+ int fontLen;
+ TrueTypeFontFile *ttFile;
+ Gushort *codeToGID;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileIDLen; ++i) {
+ if (fontFileIDs[i].num == id->num &&
+ fontFileIDs[i].gen == id->gen) {
+ sprintf(unique, "_%d", nextTrueTypeNum++);
+ psName->append(unique);
+ break;
+ }
+ }
+
+ // add entry to fontFileIDs list
+ if (i == fontFileIDLen) {
+ if (fontFileIDLen >= fontFileIDSize) {
+ fontFileIDSize += 64;
+ fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+ }
+ fontFileIDs[fontFileIDLen++] = *id;
+ }
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 42 font
+ fontBuf = font->readEmbFontFile(xref, &fontLen);
+ ttFile = new TrueTypeFontFile(fontBuf, fontLen);
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
+ ttFile->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getEncoding(),
+ ((Gfx8BitFont *)font)->getHasEncoding(),
+ codeToGID,
+ outputFunc, outputStream);
+ gfree(codeToGID);
+ delete ttFile;
+ gfree(fontBuf);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupExternalTrueTypeFont(GfxFont *font, GString *psName) {
+ char unique[32];
+ GString *fileName;
+ char *fontBuf;
+ int fontLen;
+ TrueTypeFontFile *ttFile;
+ Gushort *codeToGID;
+ int i;
+
+ // check if font is already embedded
+ fileName = font->getExtFontFile();
+ for (i = 0; i < fontFileNameLen; ++i) {
+ if (!fontFileNames[i]->cmp(fileName)) {
+ sprintf(unique, "_%d", nextTrueTypeNum++);
+ psName->append(unique);
+ break;
+ }
+ }
+
+ // add entry to fontFileNames list
+ if (i == fontFileNameLen) {
+ if (fontFileNameLen >= fontFileNameSize) {
+ fontFileNameSize += 64;
+ fontFileNames =
+ (GString **)grealloc(fontFileNames,
+ fontFileNameSize * sizeof(GString *));
+ }
+ }
+ fontFileNames[fontFileNameLen++] = fileName->copy();
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 42 font
+ fontBuf = font->readExtFontFile(&fontLen);
+ ttFile = new TrueTypeFontFile(fontBuf, fontLen);
+ codeToGID = ((Gfx8BitFont *)font)->getCodeToGIDMap(ttFile);
+ ttFile->convertToType42(psName->getCString(),
+ ((Gfx8BitFont *)font)->getEncoding(),
+ ((Gfx8BitFont *)font)->getHasEncoding(),
+ codeToGID,
+ outputFunc, outputStream);
+ delete ttFile;
+ gfree(fontBuf);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupEmbeddedCIDType0Font(GfxFont *font, Ref *id,
+ GString *psName) {
+ char *fontBuf;
+ int fontLen;
+ Type1CFontFile *t1cFile;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileIDLen; ++i) {
+ if (fontFileIDs[i].num == id->num &&
+ fontFileIDs[i].gen == id->gen)
+ return;
+ }
+
+ // add entry to fontFileIDs list
+ if (fontFileIDLen >= fontFileIDSize) {
+ fontFileIDSize += 64;
+ fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+ }
+ fontFileIDs[fontFileIDLen++] = *id;
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ fontBuf = font->readEmbFontFile(xref, &fontLen);
+ t1cFile = new Type1CFontFile(fontBuf, fontLen);
+ if (t1cFile->isOk()) {
+ if (globalParams->getPSLevel() >= psLevel3) {
+ // Level 3: use a CID font
+ t1cFile->convertToCIDType0(psName->getCString(),
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ t1cFile->convertToType0(psName->getCString(), outputFunc, outputStream);
+ }
+ }
+ delete t1cFile;
+ gfree(fontBuf);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id,
+ GString *psName) {
+ char *fontBuf;
+ int fontLen;
+ TrueTypeFontFile *ttFile;
+ int i;
+
+ // check if font is already embedded
+ for (i = 0; i < fontFileIDLen; ++i) {
+ if (fontFileIDs[i].num == id->num &&
+ fontFileIDs[i].gen == id->gen)
+ return;
+ }
+
+ // add entry to fontFileIDs list
+ if (fontFileIDLen >= fontFileIDSize) {
+ fontFileIDSize += 64;
+ fontFileIDs = (Ref *)grealloc(fontFileIDs, fontFileIDSize * sizeof(Ref));
+ }
+ fontFileIDs[fontFileIDLen++] = *id;
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // convert it to a Type 0 font
+ fontBuf = font->readEmbFontFile(xref, &fontLen);
+ ttFile = new TrueTypeFontFile(fontBuf, fontLen);
+ if (globalParams->getPSLevel() >= psLevel3) {
+ ttFile->convertToCIDType2(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ } else {
+ // otherwise: use a non-CID composite font
+ ttFile->convertToType0(psName->getCString(),
+ ((GfxCIDFont *)font)->getCIDToGID(),
+ ((GfxCIDFont *)font)->getCIDToGIDLen(),
+ outputFunc, outputStream);
+ }
+ delete ttFile;
+ gfree(fontBuf);
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupType3Font(GfxFont *font, GString *psName,
+ Dict *parentResDict) {
+ Dict *resDict;
+ Dict *charProcs;
+ Object charProc;
+ Gfx *gfx;
+ PDFRectangle box;
+ double *m;
+ char buf[256];
+ int i;
+
+ // set up resources used by font
+ if ((resDict = ((Gfx8BitFont *)font)->getResources())) {
+ inType3Char = gTrue;
+ setupResources(resDict);
+ inType3Char = gFalse;
+ } else {
+ resDict = parentResDict;
+ }
+
+ // beginning comment
+ writePSFmt("%%%%BeginResource: font %s\n", psName->getCString());
+ embFontList->append("%%+ font ");
+ embFontList->append(psName->getCString());
+ embFontList->append("\n");
+
+ // font dictionary
+ writePS("7 dict begin\n");
+ writePS("/FontType 3 def\n");
+ m = font->getFontMatrix();
+ writePSFmt("/FontMatrix [%g %g %g %g %g %g] def\n",
+ m[0], m[1], m[2], m[3], m[4], m[5]);
+ m = font->getFontBBox();
+ writePSFmt("/FontBBox [%g %g %g %g] def\n",
+ m[0], m[1], m[2], m[3]);
+ writePS("/Encoding 256 array def\n");
+ writePS(" 0 1 255 { Encoding exch /.notdef put } for\n");
+ writePS("/BuildGlyph {\n");
+ writePS(" exch /CharProcs get exch\n");
+ writePS(" 2 copy known not { pop /.notdef } if\n");
+ writePS(" get exec\n");
+ writePS("} bind def\n");
+ writePS("/BuildChar {\n");
+ writePS(" 1 index /Encoding get exch get\n");
+ writePS(" 1 index /BuildGlyph get exec\n");
+ writePS("} bind def\n");
+ if ((charProcs = ((Gfx8BitFont *)font)->getCharProcs())) {
+ writePSFmt("/CharProcs %d dict def\n", charProcs->getLength());
+ writePS("CharProcs begin\n");
+ box.x1 = m[0];
+ box.y1 = m[1];
+ box.x2 = m[2];
+ box.y2 = m[3];
+ gfx = new Gfx(xref, this, resDict, &box, gFalse, NULL);
+ inType3Char = gTrue;
+ t3Cacheable = gFalse;
+ for (i = 0; i < charProcs->getLength(); ++i) {
+ writePS("/");
+ writePSName(charProcs->getKey(i));
+ writePS(" {\n");
+ gfx->display(charProcs->getVal(i, &charProc));
+ charProc.free();
+ if (t3String) {
+ if (t3Cacheable) {
+ sprintf(buf, "%g %g %g %g %g %g setcachedevice\n",
+ t3WX, t3WY, t3LLX, t3LLY, t3URX, t3URY);
+ } else {
+ sprintf(buf, "%g %g setcharwidth\n", t3WX, t3WY);
+ }
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ (*outputFunc)(outputStream, t3String->getCString(),
+ t3String->getLength());
+ delete t3String;
+ t3String = NULL;
+ }
+ (*outputFunc)(outputStream, "Q\n", 2);
+ writePS("} def\n");
+ }
+ inType3Char = gFalse;
+ delete gfx;
+ writePS("end\n");
+ }
+ writePS("currentdict end\n");
+ writePSFmt("/%s exch definefont pop\n", psName->getCString());
+
+ // ending comment
+ writePS("%%EndResource\n");
+}
+
+void PSOutputDev::setupImages(Dict *resDict) {
+ Object xObjDict, xObj, xObjRef, subtypeObj;
+ int i;
+
+ if (!(mode == psModeForm || inType3Char)) {
+ return;
+ }
+
+ resDict->lookup("XObject", &xObjDict);
+ if (xObjDict.isDict()) {
+ for (i = 0; i < xObjDict.dictGetLength(); ++i) {
+ xObjDict.dictGetValNF(i, &xObjRef);
+ xObjDict.dictGetVal(i, &xObj);
+ if (xObj.isStream()) {
+ xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
+ if (subtypeObj.isName("Image")) {
+ if (xObjRef.isRef()) {
+ setupImage(xObjRef.getRef(), xObj.getStream());
+ } else {
+ error(-1, "Image in resource dict is not an indirect reference");
+ }
+ }
+ subtypeObj.free();
+ }
+ xObj.free();
+ xObjRef.free();
+ }
+ }
+ xObjDict.free();
+}
+
+void PSOutputDev::setupImage(Ref id, Stream *str) {
+ int c;
+ int size, line, col, i;
+
+ // construct an encoder stream
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+
+ // compute image data size
+ str->reset();
+ col = size = 0;
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ ++col;
+ } else {
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ ++col;
+ }
+ }
+ if (col > 225) {
+ ++size;
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ ++size;
+ writePSFmt("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
+ str->close();
+
+ // write the data into the array
+ str->reset();
+ line = col = 0;
+ writePS("dup 0 <~");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ }
+ }
+ // each line is: "dup nnnnn <~...data...~> put<eol>"
+ // so max data length = 255 - 20 = 235
+ // chunks are 1 or 4 bytes each, so we have to stop at 232
+ // but make it 225 just to be safe
+ if (col > 225) {
+ writePS("~> put\n");
+ ++line;
+ writePSFmt("dup %d <~", line);
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ writePS("~> put\n");
+ writePS("pop\n");
+ str->close();
+
+ delete str;
+}
+
+void PSOutputDev::startPage(int pageNum, GfxState *state) {
+ int x1, y1, x2, y2;
+ int imageWidth, imageHeight;
+ int left, bottom, right, top;
+ double width, height, t;
+
+ if (globalParams->getPSFit()) {
+ globalParams->getPSImageableArea(left, bottom, right, top);
+ } else {
+ left = bottom = 0;
+ right = globalParams->getPSPaperWidth();
+ top = globalParams->getPSPaperHeight();
+ }
+
+ imageWidth = right - left;
+ imageHeight = top - bottom;
+
+ switch (mode) {
+
+ case psModePS:
+ writePSFmt("%%%%Page: %d %d\n", pageNum, seqPage);
+
+ // possibly rotate, translate, and scale page
+ x1 = (int)(state->getX1() + 0.5);
+ y1 = (int)(state->getY1() + 0.5);
+ x2 = (int)(state->getX2() + 0.5);
+ y2 = (int)(state->getY2() + 0.5);
+ writePSFmt("%%%%PageBoundingBox: %d %d %d %d\n",
+ (int)floor((float)x1), (int)floor((float)y1),
+ (int)ceil((float)x2), (int)ceil((float)y2));
+ writePS("%%BeginPageSetup\n");
+ width = x2 - x1;
+ height = y2 - y1;
+ tx = 0;
+ ty = 0;
+ if (width > height && width > imageWidth) {
+ landscape = gTrue;
+ writePSFmt("%%%%PageOrientation: %s\n",
+ state->getCTM()[0] ? "Landscape" : "Portrait");
+ writePS("pdfStartPage\n");
+ writePS("90 rotate\n");
+ ty = -globalParams->getPSPaperWidth();
+ t = width;
+ width = height;
+ height = t;
+ } else {
+ landscape = gFalse;
+ writePSFmt("%%%%PageOrientation: %s\n",
+ state->getCTM()[0] ? "Portrait" : "Landscape");
+ writePS("pdfStartPage\n");
+ }
+ if (globalParams->getPSFit()) {
+ xScale = (double)imageWidth / (double)width;
+ yScale = (double)imageHeight / (double)height;
+ if (yScale < xScale) {
+ xScale = yScale;
+ } else {
+ yScale = xScale;
+ }
+ } else {
+ xScale = yScale = 1;
+ }
+ if (globalParams->getPSFit()) {
+ tx -= x1 * xScale;
+ ty -= y1 * yScale;
+ width *= xScale;
+ height *= yScale;
+ }
+ tx += left;
+ ty += bottom;
+ if (width < imageWidth) {
+ if(landscape) {
+ ty += (imageWidth - width) / 2;
+ } else {
+ tx += (imageWidth - width) / 2;
+ }
+ }
+ if (height < imageHeight) {
+ if(landscape) {
+ tx += (imageHeight - height) / 2;
+ } else {
+ ty += (imageHeight - height) / 2;
+ }
+ }
+ if (tx != 0 || ty != 0) {
+ writePSFmt("%g %g translate\n", tx, ty);
+ }
+ if (xScale != 1) {
+ writePSFmt("%0.4f %0.4f scale\n", xScale, xScale);
+ }
+
+ writePS("%%EndPageSetup\n");
+ ++seqPage;
+ break;
+
+ case psModeEPS:
+ writePS("pdfStartPage\n");
+ tx = ty = 0;
+ xScale = yScale = 1;
+ landscape = gFalse;
+ break;
+
+ case psModeForm:
+ writePS("/PaintProc {\n");
+ writePS("begin xpdf begin\n");
+ writePS("pdfStartPage\n");
+ tx = ty = 0;
+ xScale = yScale = 1;
+ landscape = gFalse;
+ break;
+ }
+
+ if (underlayCbk) {
+ (*underlayCbk)(this, underlayCbkData);
+ }
+}
+
+void PSOutputDev::endPage() {
+ if (overlayCbk) {
+ (*overlayCbk)(this, overlayCbkData);
+ }
+
+
+ if (mode == psModeForm) {
+ writePS("pdfEndPage\n");
+ writePS("end end\n");
+ writePS("} def\n");
+ writePS("end end\n");
+ } else {
+ if (!manualCtrl) {
+ writePS("showpage\n");
+ writePS("%%PageTrailer\n");
+ writePageTrailer();
+ }
+ }
+}
+
+void PSOutputDev::saveState(GfxState *state) {
+ writePS("q\n");
+ ++numSaves;
+}
+
+void PSOutputDev::restoreState(GfxState *state) {
+ writePS("Q\n");
+ --numSaves;
+}
+
+void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
+ double m21, double m22, double m31, double m32) {
+ writePSFmt("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
+}
+
+void PSOutputDev::updateLineDash(GfxState *state) {
+ double *dash;
+ double start;
+ int length, i;
+
+ state->getLineDash(&dash, &length, &start);
+ writePS("[");
+ for (i = 0; i < length; ++i)
+ writePSFmt("%g%s", dash[i], (i == length-1) ? "" : " ");
+ writePSFmt("] %g d\n", start);
+}
+
+void PSOutputDev::updateFlatness(GfxState *state) {
+ writePSFmt("%d i\n", state->getFlatness());
+}
+
+void PSOutputDev::updateLineJoin(GfxState *state) {
+ writePSFmt("%d j\n", state->getLineJoin());
+}
+
+void PSOutputDev::updateLineCap(GfxState *state) {
+ writePSFmt("%d J\n", state->getLineCap());
+}
+
+void PSOutputDev::updateMiterLimit(GfxState *state) {
+ writePSFmt("%g M\n", state->getMiterLimit());
+}
+
+void PSOutputDev::updateLineWidth(GfxState *state) {
+ writePSFmt("%g w\n", state->getLineWidth());
+}
+
+void PSOutputDev::updateFillColor(GfxState *state) {
+ GfxColor color;
+ double gray;
+ GfxRGB rgb;
+ GfxCMYK cmyk;
+ GfxSeparationColorSpace *sepCS;
+
+ switch (level) {
+ case psLevel1:
+ state->getFillGray(&gray);
+ writePSFmt("%g g\n", gray);
+ break;
+ case psLevel1Sep:
+ state->getFillCMYK(&cmyk);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getFillColorSpace()->getMode() == csDeviceCMYK) {
+ state->getFillCMYK(&cmyk);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ } else {
+ state->getFillRGB(&rgb);
+ if (rgb.r == rgb.g && rgb.g == rgb.b) {
+ writePSFmt("%g g\n", rgb.r);
+ } else {
+ writePSFmt("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+ }
+ }
+ break;
+ case psLevel2Sep:
+ case psLevel3Sep:
+ if (state->getFillColorSpace()->getMode() == csSeparation) {
+ sepCS = (GfxSeparationColorSpace *)state->getFillColorSpace();
+ color.c[0] = 1;
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("%g %g %g %g %g (%s) ck\n",
+ state->getFillColor()->c[0],
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
+ addCustomColor(sepCS);
+ } else {
+ state->getFillCMYK(&cmyk);
+ writePSFmt("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ break;
+ }
+ t3Cacheable = gFalse;
+}
+
+void PSOutputDev::updateStrokeColor(GfxState *state) {
+ GfxColor color;
+ double gray;
+ GfxRGB rgb;
+ GfxCMYK cmyk;
+ GfxSeparationColorSpace *sepCS;
+
+ switch (level) {
+ case psLevel1:
+ state->getStrokeGray(&gray);
+ writePSFmt("%g G\n", gray);
+ break;
+ case psLevel1Sep:
+ state->getStrokeCMYK(&cmyk);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ break;
+ case psLevel2:
+ case psLevel3:
+ if (state->getStrokeColorSpace()->getMode() == csDeviceCMYK) {
+ state->getStrokeCMYK(&cmyk);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ } else {
+ state->getStrokeRGB(&rgb);
+ if (rgb.r == rgb.g && rgb.g == rgb.b) {
+ writePSFmt("%g G\n", rgb.r);
+ } else {
+ writePSFmt("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+ }
+ }
+ break;
+ case psLevel2Sep:
+ case psLevel3Sep:
+ if (state->getStrokeColorSpace()->getMode() == csSeparation) {
+ sepCS = (GfxSeparationColorSpace *)state->getStrokeColorSpace();
+ color.c[0] = 1;
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("%g %g %g %g %g (%s) CK\n",
+ state->getStrokeColor()->c[0],
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
+ addCustomColor(sepCS);
+ } else {
+ state->getStrokeCMYK(&cmyk);
+ writePSFmt("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ break;
+ }
+ t3Cacheable = gFalse;
+}
+
+void PSOutputDev::addProcessColor(double c, double m, double y, double k) {
+ if (c > 0) {
+ processColors |= psProcessCyan;
+ }
+ if (m > 0) {
+ processColors |= psProcessMagenta;
+ }
+ if (y > 0) {
+ processColors |= psProcessYellow;
+ }
+ if (k > 0) {
+ processColors |= psProcessBlack;
+ }
+}
+
+void PSOutputDev::addCustomColor(GfxSeparationColorSpace *sepCS) {
+ PSOutCustomColor *cc;
+ GfxColor color;
+ GfxCMYK cmyk;
+
+ for (cc = customColors; cc; cc = cc->next) {
+ if (!cc->name->cmp(sepCS->getName())) {
+ return;
+ }
+ }
+ color.c[0] = 1;
+ sepCS->getCMYK(&color, &cmyk);
+ cc = new PSOutCustomColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->copy());
+ cc->next = customColors;
+ customColors = cc;
+}
+
+void PSOutputDev::updateFont(GfxState *state) {
+ if (state->getFont()) {
+ writePSFmt("/F%d_%d %g Tf\n",
+ state->getFont()->getID()->num, state->getFont()->getID()->gen,
+ state->getFontSize());
+ }
+}
+
+void PSOutputDev::updateTextMat(GfxState *state) {
+ double *mat;
+
+ mat = state->getTextMat();
+ writePSFmt("[%g %g %g %g %g %g] Tm\n",
+ mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+}
+
+void PSOutputDev::updateCharSpace(GfxState *state) {
+ writePSFmt("%g Tc\n", state->getCharSpace());
+}
+
+void PSOutputDev::updateRender(GfxState *state) {
+ int rm;
+
+ rm = state->getRender();
+ writePSFmt("%d Tr\n", rm);
+ rm &= 3;
+ if (rm != 0 && rm != 3) {
+ t3Cacheable = gFalse;
+ }
+}
+
+void PSOutputDev::updateRise(GfxState *state) {
+ writePSFmt("%g Ts\n", state->getRise());
+}
+
+void PSOutputDev::updateWordSpace(GfxState *state) {
+ writePSFmt("%g Tw\n", state->getWordSpace());
+}
+
+void PSOutputDev::updateHorizScaling(GfxState *state) {
+ writePSFmt("%g Tz\n", state->getHorizScaling());
+}
+
+void PSOutputDev::updateTextPos(GfxState *state) {
+ writePSFmt("%g %g Td\n", state->getLineX(), state->getLineY());
+}
+
+void PSOutputDev::updateTextShift(GfxState *state, double shift) {
+ if (state->getFont()->getWMode()) {
+ writePSFmt("%g TJmV\n", shift);
+ } else {
+ writePSFmt("%g TJm\n", shift);
+ }
+}
+
+void PSOutputDev::stroke(GfxState *state) {
+ doPath(state->getPath());
+ if (t3String) {
+ // if we're construct a cacheable Type 3 glyph, we need to do
+ // everything in the fill color
+ writePS("Sf\n");
+ } else {
+ writePS("S\n");
+ }
+}
+
+void PSOutputDev::fill(GfxState *state) {
+ doPath(state->getPath());
+ writePS("f\n");
+}
+
+void PSOutputDev::eoFill(GfxState *state) {
+ doPath(state->getPath());
+ writePS("f*\n");
+}
+
+void PSOutputDev::clip(GfxState *state) {
+ doPath(state->getPath());
+ writePS("W\n");
+}
+
+void PSOutputDev::eoClip(GfxState *state) {
+ doPath(state->getPath());
+ writePS("W*\n");
+}
+
+void PSOutputDev::doPath(GfxPath *path) {
+ GfxSubpath *subpath;
+ double x0, y0, x1, y1, x2, y2, x3, y3, x4, y4;
+ int n, m, i, j;
+
+ n = path->getNumSubpaths();
+
+ if (n == 1 && path->getSubpath(0)->getNumPoints() == 5) {
+ subpath = path->getSubpath(0);
+ x0 = subpath->getX(0);
+ y0 = subpath->getY(0);
+ x4 = subpath->getX(4);
+ y4 = subpath->getY(4);
+ if (x4 == x0 && y4 == y0) {
+ x1 = subpath->getX(1);
+ y1 = subpath->getY(1);
+ x2 = subpath->getX(2);
+ y2 = subpath->getY(2);
+ x3 = subpath->getX(3);
+ y3 = subpath->getY(3);
+ if (x0 == x1 && x2 == x3 && y0 == y3 && y1 == y2) {
+ writePSFmt("%g %g %g %g re\n",
+ x0 < x2 ? x0 : x2, y0 < y1 ? y0 : y1,
+ fabs(x2 - x0), fabs(y1 - y0));
+ return;
+ } else if (x0 == x3 && x1 == x2 && y0 == y1 && y2 == y3) {
+ writePSFmt("%g %g %g %g re\n",
+ x0 < x1 ? x0 : x1, y0 < y2 ? y0 : y2,
+ fabs(x1 - x0), fabs(y2 - y0));
+ return;
+ }
+ }
+ }
+
+ for (i = 0; i < n; ++i) {
+ subpath = path->getSubpath(i);
+ m = subpath->getNumPoints();
+ writePSFmt("%g %g m\n", subpath->getX(0), subpath->getY(0));
+ j = 1;
+ while (j < m) {
+ if (subpath->getCurve(j)) {
+ writePSFmt("%g %g %g %g %g %g c\n", subpath->getX(j), subpath->getY(j),
+ subpath->getX(j+1), subpath->getY(j+1),
+ subpath->getX(j+2), subpath->getY(j+2));
+ j += 3;
+ } else {
+ writePSFmt("%g %g l\n", subpath->getX(j), subpath->getY(j));
+ ++j;
+ }
+ }
+ if (subpath->isClosed()) {
+ writePS("h\n");
+ }
+ }
+}
+
+void PSOutputDev::drawString(GfxState *state, GString *s) {
+ GfxFont *font;
+ int wMode;
+ GString *s2;
+ double dx, dy, dx2, dy2, originX, originY;
+ char *p;
+ UnicodeMap *uMap;
+ CharCode code;
+ Unicode u[8];
+ char buf[8];
+ int len, nChars, uLen, n, m, i, j;
+
+ // check for invisible text -- this is used by Acrobat Capture
+ if (state->getRender() == 3) {
+ return;
+ }
+
+ // ignore empty strings
+ if (s->getLength() == 0) {
+ return;
+ }
+
+ // get the font
+ if (!(font = state->getFont())) {
+ return;
+ }
+ wMode = font->getWMode();
+
+ // check for a subtitute 16-bit font
+ uMap = NULL;
+ if (font->isCIDFont()) {
+ for (i = 0; i < font16EncLen; ++i) {
+ if (font->getID()->num == font16Enc[i].fontID.num &&
+ font->getID()->gen == font16Enc[i].fontID.gen) {
+ uMap = globalParams->getUnicodeMap(font16Enc[i].enc);
+ break;
+ }
+ }
+ }
+
+ // compute width of chars in string, ignoring char spacing and word
+ // spacing -- the Tj operator will adjust for the metrics of the
+ // font that's actually used
+ dx = dy = 0;
+ nChars = 0;
+ p = s->getCString();
+ len = s->getLength();
+ if (font->isCIDFont()) {
+ s2 = new GString();
+ } else {
+ s2 = s;
+ }
+ while (len > 0) {
+ n = font->getNextChar(p, len, &code,
+ u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+ &dx2, &dy2, &originX, &originY);
+ if (font->isCIDFont()) {
+ if (uMap) {
+ for (i = 0; i < uLen; ++i) {
+ m = uMap->mapUnicode(u[i], buf, (int)sizeof(buf));
+ for (j = 0; j < m; ++j) {
+ s2->append(buf[j]);
+ }
+ }
+ //~ this really needs to get the number of chars in the target
+ //~ encoding - which may be more than the number of Unicode
+ //~ chars
+ nChars += uLen;
+ } else {
+ s2->append((char)((code >> 8) & 0xff));
+ s2->append((char)(code & 0xff));
+ ++nChars;
+ }
+ }
+ dx += dx2;
+ dy += dy2;
+ p += n;
+ len -= n;
+ }
+ dx *= state->getFontSize() * state->getHorizScaling();
+ dy *= state->getFontSize();
+ if (uMap) {
+ uMap->decRefCnt();
+ }
+
+ if (s2->getLength() > 0) {
+ writePSString(s2);
+ if (font->isCIDFont()) {
+ if (wMode) {
+ writePSFmt(" %d %g Tj16V\n", nChars, dy);
+ } else {
+ writePSFmt(" %d %g Tj16\n", nChars, dx);
+ }
+ } else {
+ writePSFmt(" %g Tj\n", dx);
+ }
+ }
+ if (font->isCIDFont()) {
+ delete s2;
+ }
+
+ if (state->getRender() & 4) {
+ haveTextClip = gTrue;
+ }
+}
+
+void PSOutputDev::endTextObject(GfxState *state) {
+ if (haveTextClip) {
+ writePS("Tclip\n");
+ haveTextClip = gFalse;
+ }
+}
+
+void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg) {
+ int len;
+
+ len = height * ((width + 7) / 8);
+ if (level == psLevel1 || level == psLevel1Sep) {
+ doImageL1(NULL, invert, inlineImg, str, width, height, len);
+ } else {
+ doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
+ }
+}
+
+void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
+ int *maskColors, GBool inlineImg) {
+ int len;
+
+ len = height * ((width * colorMap->getNumPixelComps() *
+ colorMap->getBits() + 7) / 8);
+ switch (level) {
+ case psLevel1:
+ doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
+ break;
+ case psLevel1Sep:
+ //~ handle indexed, separation, ... color spaces
+ doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len);
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ case psLevel3:
+ case psLevel3Sep:
+ doImageL2(ref, colorMap, gFalse, inlineImg, str, width, height, len);
+ break;
+ }
+ t3Cacheable = gFalse;
+}
+
+void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len) {
+ ImageStream *imgStr;
+ Guchar pixBuf[gfxColorMaxComps];
+ double gray;
+ int x, y, i;
+
+ // width, height, matrix, bits per component
+ if (colorMap) {
+ writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
+ width, height,
+ width, -height, height);
+ } else {
+ writePSFmt("%d %d %s [%d 0 0 %d 0 %d] pdfImM1\n",
+ width, height, invert ? "true" : "false",
+ width, -height, height);
+ }
+
+ // image
+ if (colorMap) {
+
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
+
+ // process the data stream
+ i = 0;
+ for (y = 0; y < height; ++y) {
+
+ // write the line
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getGray(pixBuf, &gray);
+ writePSFmt("%02x", (int)(gray * 255 + 0.5));
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
+ }
+ }
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ delete imgStr;
+
+ // imagemask
+ } else {
+ str->reset();
+ i = 0;
+ for (y = 0; y < height; ++y) {
+ for (x = 0; x < width; x += 8) {
+ writePSFmt("%02x", str->getChar() & 0xff);
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
+ }
+ }
+ if (i != 0) {
+ writePSChar('\n');
+ }
+ str->close();
+ }
+}
+
+void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len) {
+ ImageStream *imgStr;
+ Guchar *lineBuf;
+ Guchar pixBuf[gfxColorMaxComps];
+ GfxCMYK cmyk;
+ int x, y, i, comp;
+
+ // width, height, matrix, bits per component
+ writePSFmt("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
+ width, height,
+ width, -height, height);
+
+ // allocate a line buffer
+ lineBuf = (Guchar *)gmalloc(4 * width);
+
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
+
+ // process the data stream
+ i = 0;
+ for (y = 0; y < height; ++y) {
+
+ // read the line
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ lineBuf[4*x+0] = (int)(255 * cmyk.c + 0.5);
+ lineBuf[4*x+1] = (int)(255 * cmyk.m + 0.5);
+ lineBuf[4*x+2] = (int)(255 * cmyk.y + 0.5);
+ lineBuf[4*x+3] = (int)(255 * cmyk.k + 0.5);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+
+ // write one line of each color component
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < width; ++x) {
+ writePSFmt("%02x", lineBuf[4*x + comp]);
+ if (++i == 32) {
+ writePSChar('\n');
+ i = 0;
+ }
+ }
+ }
+ }
+
+ if (i != 0) {
+ writePSChar('\n');
+ }
+
+ delete imgStr;
+ gfree(lineBuf);
+}
+
+void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len) {
+ GString *s;
+ int n, numComps;
+ GBool useRLE, useASCII, useCompressed;
+ GfxSeparationColorSpace *sepCS;
+ GfxColor color;
+ GfxCMYK cmyk;
+ int c;
+ int line, col, i;
+
+ // color space
+ if (colorMap) {
+ dumpColorSpaceL2(colorMap->getColorSpace());
+ writePS(" setcolorspace\n");
+ }
+
+ // set up the image data
+ if (mode == psModeForm || inType3Char) {
+ if (inlineImg) {
+ // create an array
+ str = new FixedLengthEncoder(str, len);
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ str->reset();
+ line = col = 0;
+ writePS("[<~");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ writePSChar(c);
+ ++col;
+ } else {
+ writePSChar(c);
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ writePSChar(c);
+ ++col;
+ }
+ }
+ // each line is: "dup nnnnn <~...data...~> put<eol>"
+ // so max data length = 255 - 20 = 235
+ // chunks are 1 or 4 bytes each, so we have to stop at 232
+ // but make it 225 just to be safe
+ if (col > 225) {
+ writePS("~>\n");
+ ++line;
+ writePSFmt("<~", line);
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ writePS("~>]\n");
+ writePS("0\n");
+ str->close();
+ delete str;
+ } else {
+ // set up to use the array already created by setupImages()
+ writePSFmt("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
+ }
+ }
+
+ // image dictionary
+ writePS("<<\n /ImageType 1\n");
+
+ // width, height, matrix, bits per component
+ writePSFmt(" /Width %d\n", width);
+ writePSFmt(" /Height %d\n", height);
+ writePSFmt(" /ImageMatrix [%d 0 0 %d 0 %d]\n", width, -height, height);
+ writePSFmt(" /BitsPerComponent %d\n",
+ colorMap ? colorMap->getBits() : 1);
+
+ // decode
+ if (colorMap) {
+ writePS(" /Decode [");
+ if (colorMap->getColorSpace()->getMode() == csSeparation) {
+ //~ this is a kludge -- see comment in dumpColorSpaceL2
+ n = (1 << colorMap->getBits()) - 1;
+ writePSFmt("%g %g", colorMap->getDecodeLow(0) * n,
+ colorMap->getDecodeHigh(0) * n);
+ } else {
+ numComps = colorMap->getNumPixelComps();
+ for (i = 0; i < numComps; ++i) {
+ if (i > 0) {
+ writePS(" ");
+ }
+ writePSFmt("%g %g", colorMap->getDecodeLow(i),
+ colorMap->getDecodeHigh(i));
+ }
+ }
+ writePS("]\n");
+ } else {
+ writePSFmt(" /Decode [%d %d]\n", invert ? 1 : 0, invert ? 0 : 1);
+ }
+
+ if (mode == psModeForm || inType3Char) {
+
+ // data source
+ writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
+
+ // end of image dictionary
+ writePSFmt(">>\n%s\n", colorMap ? "image" : "imagemask");
+
+ // get rid of the array and index
+ writePS("pop pop\n");
+
+ } else {
+
+ // data source
+ writePS(" /DataSource currentfile\n");
+ s = str->getPSFilter(level < psLevel2 ? 1 : level < psLevel3 ? 2 : 3,
+ " ");
+ if (inlineImg || !s) {
+ useRLE = gTrue;
+ useASCII = gTrue;
+ useCompressed = gFalse;
+ } else {
+ useRLE = gFalse;
+ useASCII = str->isBinary();
+ useCompressed = gTrue;
+ }
+ if (useASCII) {
+ writePSFmt(" /ASCII%sDecode filter\n",
+ globalParams->getPSASCIIHex() ? "Hex" : "85");
+ }
+ if (useRLE) {
+ writePS(" /RunLengthDecode filter\n");
+ }
+ if (useCompressed) {
+ writePS(s->getCString());
+ }
+ if (s) {
+ delete s;
+ }
+
+ // cut off inline image streams at appropriate length
+ if (inlineImg) {
+ str = new FixedLengthEncoder(str, len);
+ } else if (useCompressed) {
+ str = str->getBaseStream();
+ }
+
+ // add RunLengthEncode and ASCIIHex/85 encode filters
+ if (useRLE) {
+ str = new RunLengthEncoder(str);
+ }
+ if (useASCII) {
+ if (globalParams->getPSASCIIHex()) {
+ str = new ASCIIHexEncoder(str);
+ } else {
+ str = new ASCII85Encoder(str);
+ }
+ }
+
+ // end of image dictionary
+ writePS(">>\n");
+#if OPI_SUPPORT
+ if (opi13Nest) {
+ if (inlineImg) {
+ // this can't happen -- OPI dictionaries are in XObjects
+ error(-1, "Internal: OPI in inline image");
+ n = 0;
+ } else {
+ // need to read the stream to count characters -- the length
+ // is data-dependent (because of ASCII and RLE filters)
+ str->reset();
+ n = 0;
+ while ((c = str->getChar()) != EOF) {
+ ++n;
+ }
+ str->close();
+ }
+ // +6/7 for "pdfIm\n" / "pdfImM\n"
+ // +8 for newline + trailer
+ n += colorMap ? 14 : 15;
+ writePSFmt("%%%%BeginData: %d Hex Bytes\n", n);
+ }
+#endif
+ if ((level == psLevel2Sep || level == psLevel3Sep) && colorMap &&
+ colorMap->getColorSpace()->getMode() == csSeparation) {
+ color.c[0] = 1;
+ sepCS = (GfxSeparationColorSpace *)colorMap->getColorSpace();
+ sepCS->getCMYK(&color, &cmyk);
+ writePSFmt("%g %g %g %g (%s) pdfImSep\n",
+ cmyk.c, cmyk.m, cmyk.y, cmyk.k,
+ sepCS->getName()->getCString());
+ } else {
+ writePSFmt("%s\n", colorMap ? "pdfIm" : "pdfImM");
+ }
+
+ // copy the stream data
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
+
+ // add newline and trailer to the end
+ writePSChar('\n');
+ writePS("%-EOD-\n");
+#if OPI_SUPPORT
+ if (opi13Nest) {
+ writePS("%%EndData\n");
+ }
+#endif
+
+ // delete encoders
+ if (useRLE || useASCII || inlineImg) {
+ delete str;
+ }
+ }
+}
+
+void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
+ GfxCalGrayColorSpace *calGrayCS;
+ GfxCalRGBColorSpace *calRGBCS;
+ GfxLabColorSpace *labCS;
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *separationCS;
+ GfxColorSpace *baseCS;
+ Guchar *lookup, *p;
+ double x[gfxColorMaxComps], y[gfxColorMaxComps];
+ GfxColor color;
+ GfxCMYK cmyk;
+ Function *func;
+ int n, numComps, numAltComps;
+ int byte;
+ int i, j, k;
+
+ switch (colorSpace->getMode()) {
+
+ case csDeviceGray:
+ writePS("/DeviceGray");
+ processColors |= psProcessBlack;
+ break;
+
+ case csCalGray:
+ calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
+ writePS("[/CIEBasedA <<\n");
+ writePSFmt(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
+ writePSFmt(" /MatrixA [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calGrayCS->getBlackX(), calGrayCS->getBlackY(),
+ calGrayCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessBlack;
+ break;
+
+ case csDeviceRGB:
+ writePS("/DeviceRGB");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csCalRGB:
+ calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePSFmt(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
+ calRGBCS->getGammaR(), calRGBCS->getGammaG(),
+ calRGBCS->getGammaB());
+ writePSFmt(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
+ calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
+ calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
+ calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
+ calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
+ calRGBCS->getMatrix()[8]);
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
+ calRGBCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ calRGBCS->getBlackX(), calRGBCS->getBlackY(),
+ calRGBCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csDeviceCMYK:
+ writePS("/DeviceCMYK");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csLab:
+ labCS = (GfxLabColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePSFmt(" /RangeABC [0 100 %g %g %g %g]\n",
+ labCS->getAMin(), labCS->getAMax(),
+ labCS->getBMin(), labCS->getBMax());
+ writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
+ writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
+ writePS(" /DecodeLMN\n");
+ writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteX());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteY());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePSFmt(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
+ labCS->getWhiteZ());
+ writePSFmt(" /WhitePoint [%g %g %g]\n",
+ labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+ writePSFmt(" /BlackPoint [%g %g %g]\n",
+ labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+ writePS(">>]");
+ processColors |= psProcessCMYK;
+ break;
+
+ case csICCBased:
+ dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csIndexed:
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ baseCS = indexedCS->getBase();
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(baseCS);
+ n = indexedCS->getIndexHigh();
+ numComps = baseCS->getNComps();
+ lookup = indexedCS->getLookup();
+ writePSFmt(" %d <\n", n);
+ if (baseCS->getMode() == csDeviceN) {
+ func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
+ numAltComps = ((GfxDeviceNColorSpace *)baseCS)->getAlt()->getNComps();
+ p = lookup;
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ x[k] = *p++ / 255.0;
+ }
+ func->transform(x, y);
+ for (k = 0; k < numAltComps; ++k) {
+ byte = (int)(y[k] * 255 + 0.5);
+ if (byte < 0) {
+ byte = 0;
+ } else if (byte > 255) {
+ byte = 255;
+ }
+ writePSFmt("%02x", byte);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ writePS("\n");
+ }
+ } else {
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("%02x", lookup[j * numComps + k]);
+ }
+ color.c[0] = j;
+ indexedCS->getCMYK(&color, &cmyk);
+ addProcessColor(cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ }
+ writePS("\n");
+ }
+ }
+ writePS(">]");
+ break;
+
+ case csSeparation:
+ //~ this is a kludge -- the correct thing would to ouput a
+ //~ separation color space, with the specified alternate color
+ //~ space and tint transform
+ separationCS = (GfxSeparationColorSpace *)colorSpace;
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(separationCS->getAlt());
+ writePS(" 255 <\n");
+ numComps = separationCS->getAlt()->getNComps();
+ for (i = 0; i <= 255; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= 255; ++j) {
+ x[0] = (double)j / 255.0;
+ separationCS->getFunc()->transform(x, y);
+ for (k = 0; k < numComps; ++k) {
+ writePSFmt("%02x", (int)(255 * y[k] + 0.5));
+ }
+ }
+ writePS("\n");
+ }
+ writePS(">]");
+#if 0 //~ this shouldn't be here since the PS file doesn't actually refer
+ //~ to this colorant (it's converted to CMYK instead)
+ addCustomColor(separationCS);
+#endif
+ break;
+
+ case csDeviceN:
+ // DeviceN color spaces are a Level 3 PostScript feature.
+ dumpColorSpaceL2(((GfxDeviceNColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csPattern:
+ //~ unimplemented
+ break;
+
+ }
+}
+
+#if OPI_SUPPORT
+void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
+ Object dict;
+
+ if (globalParams->getPSOPI()) {
+ opiDict->lookup("2.0", &dict);
+ if (dict.isDict()) {
+ opiBegin20(state, dict.getDict());
+ dict.free();
+ } else {
+ dict.free();
+ opiDict->lookup("1.3", &dict);
+ if (dict.isDict()) {
+ opiBegin13(state, dict.getDict());
+ }
+ dict.free();
+ }
+ }
+}
+
+void PSOutputDev::opiBegin20(GfxState *state, Dict *dict) {
+ Object obj1, obj2, obj3, obj4;
+ double width, height, left, right, top, bottom;
+ int w, h;
+ int i;
+
+ writePS("%%BeginOPI: 2.0\n");
+ writePS("%%Distilled\n");
+
+ dict->lookup("F", &obj1);
+ if (getFileSpec(&obj1, &obj2)) {
+ writePSFmt("%%%%ImageFileName: %s\n",
+ obj2.getString()->getCString());
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("MainImage", &obj1);
+ if (obj1.isString()) {
+ writePSFmt("%%%%MainImage: %s\n", obj1.getString()->getCString());
+ }
+ obj1.free();
+
+ //~ ignoring 'Tags' entry
+ //~ need to use writePSString() and deal with >255-char lines
+
+ dict->lookup("Size", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ width = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ height = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%%%ImageDimensions: %g %g\n", width, height);
+ }
+ obj1.free();
+
+ dict->lookup("CropRect", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj1.arrayGet(0, &obj2);
+ left = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ top = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ right = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ bottom = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%%%ImageCropRect: %g %g %g %g\n", left, top, right, bottom);
+ }
+ obj1.free();
+
+ dict->lookup("Overprint", &obj1);
+ if (obj1.isBool()) {
+ writePSFmt("%%%%ImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ }
+ obj1.free();
+
+ dict->lookup("Inks", &obj1);
+ if (obj1.isName()) {
+ writePSFmt("%%%%ImageInks: %s\n", obj1.getName());
+ } else if (obj1.isArray() && obj1.arrayGetLength() >= 1) {
+ obj1.arrayGet(0, &obj2);
+ if (obj2.isName()) {
+ writePSFmt("%%%%ImageInks: %s %d",
+ obj2.getName(), (obj1.arrayGetLength() - 1) / 2);
+ for (i = 1; i+1 < obj1.arrayGetLength(); i += 2) {
+ obj1.arrayGet(i, &obj3);
+ obj1.arrayGet(i+1, &obj4);
+ if (obj3.isString() && obj4.isNum()) {
+ writePS(" ");
+ writePSString(obj3.getString());
+ writePSFmt(" %g", obj4.getNum());
+ }
+ obj3.free();
+ obj4.free();
+ }
+ writePS("\n");
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ writePS("gsave\n");
+
+ writePS("%%BeginIncludedImage\n");
+
+ dict->lookup("IncludedImageDimensions", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ w = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ h = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%%%IncludedImageDimensions: %d %d\n", w, h);
+ }
+ obj1.free();
+
+ dict->lookup("IncludedImageQuality", &obj1);
+ if (obj1.isNum()) {
+ writePSFmt("%%%%IncludedImageQuality: %g\n", obj1.getNum());
+ }
+ obj1.free();
+
+ ++opi20Nest;
+}
+
+void PSOutputDev::opiBegin13(GfxState *state, Dict *dict) {
+ Object obj1, obj2;
+ int left, right, top, bottom, samples, bits, width, height;
+ double c, m, y, k;
+ double llx, lly, ulx, uly, urx, ury, lrx, lry;
+ double tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry;
+ double horiz, vert;
+ int i, j;
+
+ writePS("save\n");
+ writePS("/opiMatrix2 matrix currentmatrix def\n");
+ writePS("opiMatrix setmatrix\n");
+
+ dict->lookup("F", &obj1);
+ if (getFileSpec(&obj1, &obj2)) {
+ writePSFmt("%%ALDImageFileName: %s\n",
+ obj2.getString()->getCString());
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("CropRect", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ obj1.arrayGet(0, &obj2);
+ left = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ top = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ right = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ bottom = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%ALDImageCropRect: %d %d %d %d\n", left, top, right, bottom);
+ }
+ obj1.free();
+
+ dict->lookup("Color", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 5) {
+ obj1.arrayGet(0, &obj2);
+ c = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ m = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ y = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ k = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(4, &obj2);
+ if (obj2.isString()) {
+ writePSFmt("%%ALDImageColor: %g %g %g %g ", c, m, y, k);
+ writePSString(obj2.getString());
+ writePS("\n");
+ }
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("ColorType", &obj1);
+ if (obj1.isName()) {
+ writePSFmt("%%ALDImageColorType: %s\n", obj1.getName());
+ }
+ obj1.free();
+
+ //~ ignores 'Comments' entry
+ //~ need to handle multiple lines
+
+ dict->lookup("CropFixed", &obj1);
+ if (obj1.isArray()) {
+ obj1.arrayGet(0, &obj2);
+ ulx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ uly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ lrx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ lry = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%ALDImageCropFixed: %g %g %g %g\n", ulx, uly, lrx, lry);
+ }
+ obj1.free();
+
+ dict->lookup("GrayMap", &obj1);
+ if (obj1.isArray()) {
+ writePS("%ALDImageGrayMap:");
+ for (i = 0; i < obj1.arrayGetLength(); i += 16) {
+ if (i > 0) {
+ writePS("\n%%+");
+ }
+ for (j = 0; j < 16 && i+j < obj1.arrayGetLength(); ++j) {
+ obj1.arrayGet(i+j, &obj2);
+ writePSFmt(" %d", obj2.getInt());
+ obj2.free();
+ }
+ }
+ writePS("\n");
+ }
+ obj1.free();
+
+ dict->lookup("ID", &obj1);
+ if (obj1.isString()) {
+ writePSFmt("%%ALDImageID: %s\n", obj1.getString()->getCString());
+ }
+ obj1.free();
+
+ dict->lookup("ImageType", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ samples = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ bits = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%ALDImageType: %d %d\n", samples, bits);
+ }
+ obj1.free();
+
+ dict->lookup("Overprint", &obj1);
+ if (obj1.isBool()) {
+ writePSFmt("%%ALDImageOverprint: %s\n", obj1.getBool() ? "true" : "false");
+ }
+ obj1.free();
+
+ dict->lookup("Position", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 8) {
+ obj1.arrayGet(0, &obj2);
+ llx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ lly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ ulx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ uly = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(4, &obj2);
+ urx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(5, &obj2);
+ ury = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(6, &obj2);
+ lrx = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(7, &obj2);
+ lry = obj2.getNum();
+ obj2.free();
+ opiTransform(state, llx, lly, &tllx, &tlly);
+ opiTransform(state, ulx, uly, &tulx, &tuly);
+ opiTransform(state, urx, ury, &turx, &tury);
+ opiTransform(state, lrx, lry, &tlrx, &tlry);
+ writePSFmt("%%ALDImagePosition: %g %g %g %g %g %g %g %g\n",
+ tllx, tlly, tulx, tuly, turx, tury, tlrx, tlry);
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Resolution", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ horiz = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ vert = obj2.getNum();
+ obj2.free();
+ writePSFmt("%%ALDImageResoution: %g %g\n", horiz, vert);
+ obj2.free();
+ }
+ obj1.free();
+
+ dict->lookup("Size", &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 2) {
+ obj1.arrayGet(0, &obj2);
+ width = obj2.getInt();
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ height = obj2.getInt();
+ obj2.free();
+ writePSFmt("%%ALDImageDimensions: %d %d\n", width, height);
+ }
+ obj1.free();
+
+ //~ ignoring 'Tags' entry
+ //~ need to use writePSString() and deal with >255-char lines
+
+ dict->lookup("Tint", &obj1);
+ if (obj1.isNum()) {
+ writePSFmt("%%ALDImageTint: %g\n", obj1.getNum());
+ }
+ obj1.free();
+
+ dict->lookup("Transparency", &obj1);
+ if (obj1.isBool()) {
+ writePSFmt("%%ALDImageTransparency: %s\n", obj1.getBool() ? "true" : "false");
+ }
+ obj1.free();
+
+ writePS("%%BeginObject: image\n");
+ writePS("opiMatrix2 setmatrix\n");
+ ++opi13Nest;
+}
+
+// Convert PDF user space coordinates to PostScript default user space
+// coordinates. This has to account for both the PDF CTM and the
+// PSOutputDev page-fitting transform.
+void PSOutputDev::opiTransform(GfxState *state, double x0, double y0,
+ double *x1, double *y1) {
+ double t;
+
+ state->transform(x0, y0, x1, y1);
+ *x1 += tx;
+ *y1 += ty;
+ if (landscape) {
+ t = *x1;
+ *x1 = -*y1;
+ *y1 = t;
+ }
+ *x1 *= xScale;
+ *y1 *= yScale;
+}
+
+void PSOutputDev::opiEnd(GfxState *state, Dict *opiDict) {
+ Object dict;
+
+ if (globalParams->getPSOPI()) {
+ opiDict->lookup("2.0", &dict);
+ if (dict.isDict()) {
+ writePS("%%EndIncludedImage\n");
+ writePS("%%EndOPI\n");
+ writePS("grestore\n");
+ --opi20Nest;
+ dict.free();
+ } else {
+ dict.free();
+ opiDict->lookup("1.3", &dict);
+ if (dict.isDict()) {
+ writePS("%%EndObject\n");
+ writePS("restore\n");
+ --opi13Nest;
+ }
+ dict.free();
+ }
+ }
+}
+
+GBool PSOutputDev::getFileSpec(Object *fileSpec, Object *fileName) {
+ if (fileSpec->isString()) {
+ fileSpec->copy(fileName);
+ return gTrue;
+ }
+ if (fileSpec->isDict()) {
+ fileSpec->dictLookup("DOS", fileName);
+ if (fileName->isString()) {
+ return gTrue;
+ }
+ fileName->free();
+ fileSpec->dictLookup("Mac", fileName);
+ if (fileName->isString()) {
+ return gTrue;
+ }
+ fileName->free();
+ fileSpec->dictLookup("Unix", fileName);
+ if (fileName->isString()) {
+ return gTrue;
+ }
+ fileName->free();
+ fileSpec->dictLookup("F", fileName);
+ if (fileName->isString()) {
+ return gTrue;
+ }
+ fileName->free();
+ }
+ return gFalse;
+}
+#endif // OPI_SUPPORT
+
+void PSOutputDev::type3D0(GfxState *state, double wx, double wy) {
+ writePSFmt("%g %g setcharwidth\n", wx, wy);
+ writePS("q\n");
+}
+
+void PSOutputDev::type3D1(GfxState *state, double wx, double wy,
+ double llx, double lly, double urx, double ury) {
+ t3WX = wx;
+ t3WY = wy;
+ t3LLX = llx;
+ t3LLY = lly;
+ t3URX = urx;
+ t3URY = ury;
+ t3String = new GString();
+ writePS("q\n");
+ t3Cacheable = gTrue;
+}
+
+void PSOutputDev::psXObject(Stream *psStream, Stream *level1Stream) {
+ Stream *str;
+ int c;
+
+ if ((level == psLevel1 || level == psLevel1Sep) && level1Stream) {
+ str = level1Stream;
+ } else {
+ str = psStream;
+ }
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ writePSChar(c);
+ }
+ str->close();
+}
+
+void PSOutputDev::writePSChar(char c) {
+ if (t3String) {
+ t3String->append(c);
+ } else {
+ (*outputFunc)(outputStream, &c, 1);
+ }
+}
+
+void PSOutputDev::writePS(const char *s) {
+ if (t3String) {
+ t3String->append(s);
+ } else {
+ (*outputFunc)(outputStream, s, strlen(s));
+ }
+}
+
+void PSOutputDev::writePSFmt(const char *fmt, ...) {
+ va_list args;
+ char buf[512];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ if (t3String) {
+ t3String->append(buf);
+ } else {
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+}
+
+void PSOutputDev::writePSString(GString *s) {
+ Guchar *p;
+ int n;
+ char buf[8];
+
+ writePSChar('(');
+ for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
+ if (*p == '(' || *p == ')' || *p == '\\') {
+ writePSChar('\\');
+ writePSChar((char)*p);
+ } else if (*p < 0x20 || *p >= 0x80) {
+ sprintf(buf, "\\%03o", *p);
+ if (t3String) {
+ t3String->append(buf);
+ } else {
+ (*outputFunc)(outputStream, buf, strlen(buf));
+ }
+ } else {
+ writePSChar((char)*p);
+ }
+ }
+ writePSChar(')');
+}
+
+void PSOutputDev::writePSName(const char *s) {
+ const char *p;
+ char c;
+
+ p = s;
+ while ((c = *p++)) {
+ if (c <= (char)0x20 || c >= (char)0x7f ||
+ c == '(' || c == ')' || c == '<' || c == '>' ||
+ c == '[' || c == ']' || c == '{' || c == '}' ||
+ c == '/' || c == '%') {
+ writePSFmt("#%02x", c & 0xff);
+ } else {
+ writePSChar(c);
+ }
+ }
+}
+
+GString *PSOutputDev::filterPSName(GString *name) {
+ GString *name2;
+ char buf[8];
+ int i;
+ char c;
+
+ name2 = new GString();
+
+ // ghostscript chokes on names that begin with out-of-limits
+ // numbers, e.g., 1e4foo is handled correctly (as a name), but
+ // 1e999foo generates a limitcheck error
+ c = name->getChar(0);
+ if (c >= '0' && c <= '9') {
+ name2->append('f');
+ }
+
+ for (i = 0; i < name->getLength(); ++i) {
+ c = name->getChar(i);
+ if (c <= (char)0x20 || c >= (char)0x7f ||
+ c == '(' || c == ')' || c == '<' || c == '>' ||
+ c == '[' || c == ']' || c == '{' || c == '}' ||
+ c == '/' || c == '%') {
+ sprintf(buf, "#%02x", c & 0xff);
+ name2->append(buf);
+ } else {
+ name2->append(c);
+ }
+ }
+ return name2;
+}
diff --git a/pdftops/PSOutputDev.h b/pdftops/PSOutputDev.h
new file mode 100644
index 000000000..1bc90ff1a
--- /dev/null
+++ b/pdftops/PSOutputDev.h
@@ -0,0 +1,296 @@
+//========================================================================
+//
+// PSOutputDev.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PSOUTPUTDEV_H
+#define PSOUTPUTDEV_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stddef.h>
+#include "config.h"
+#include "Object.h"
+#include "GlobalParams.h"
+#include "OutputDev.h"
+
+class GfxPath;
+class GfxFont;
+class GfxColorSpace;
+class GfxSeparationColorSpace;
+class PDFRectangle;
+struct PSFont16Enc;
+class PSOutCustomColor;
+
+//------------------------------------------------------------------------
+// PSOutputDev
+//------------------------------------------------------------------------
+
+enum PSOutMode {
+ psModePS,
+ psModeEPS,
+ psModeForm
+};
+
+enum PSFileType {
+ psFile, // write to file
+ psPipe, // write to pipe
+ psStdout, // write to stdout
+ psGeneric // write to a generic stream
+};
+
+typedef void (*PSOutputFunc)(void *stream, const char *data, int len);
+
+class PSOutputDev: public OutputDev {
+public:
+
+ // Open a PostScript output file, and write the prolog.
+ PSOutputDev(const char *fileName, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA = 0, int paperHeightA = 0,
+ GBool manualCtrlA = gFalse);
+
+ // Open a PSOutputDev that will write to a generic stream.
+ PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
+ XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA = 0, int paperHeightA = 0,
+ GBool manualCtrlA = gFalse);
+
+ // Destructor -- writes the trailer and closes the file.
+ virtual ~PSOutputDev();
+
+ // Check if file was successfully created.
+ virtual GBool isOk() { return ok; }
+
+ //---- get info about output device
+
+ // Does this device use upside-down coordinates?
+ // (Upside-down means (0,0) is the top left corner of the page.)
+ virtual GBool upsideDown() { return gFalse; }
+
+ // Does this device use drawChar() or drawString()?
+ virtual GBool useDrawChar() { return gFalse; }
+
+ // Does this device use beginType3Char/endType3Char? Otherwise,
+ // text in Type 3 fonts will be drawn with drawChar/drawString.
+ virtual GBool interpretType3Chars() { return gFalse; }
+
+ //----- header/trailer (used only if manualCtrl is true)
+
+ // Write the document-level header.
+ void writeHeader(int firstPage, int lastPage, PDFRectangle *box);
+
+ // Write the Xpdf procset.
+ void writeXpdfProcset();
+
+ // Write the document-level setup.
+ void writeDocSetup(Catalog *catalog, int firstPage, int lastPage);
+
+ // Write the setup for the current page.
+ void writePageSetup();
+
+ // Write the trailer for the current page.
+ void writePageTrailer();
+
+ // Write the document trailer.
+ void writeTrailer();
+
+ //----- initialization and control
+
+ // Start a page.
+ virtual void startPage(int pageNum, GfxState *state);
+
+ // End a page.
+ virtual void endPage();
+
+ //----- save/restore graphics state
+ virtual void saveState(GfxState *state);
+ virtual void restoreState(GfxState *state);
+
+ //----- update graphics state
+ virtual void updateCTM(GfxState *state, double m11, double m12,
+ double m21, double m22, double m31, double m32);
+ virtual void updateLineDash(GfxState *state);
+ virtual void updateFlatness(GfxState *state);
+ virtual void updateLineJoin(GfxState *state);
+ virtual void updateLineCap(GfxState *state);
+ virtual void updateMiterLimit(GfxState *state);
+ virtual void updateLineWidth(GfxState *state);
+ virtual void updateFillColor(GfxState *state);
+ virtual void updateStrokeColor(GfxState *state);
+
+ //----- update text state
+ virtual void updateFont(GfxState *state);
+ virtual void updateTextMat(GfxState *state);
+ virtual void updateCharSpace(GfxState *state);
+ virtual void updateRender(GfxState *state);
+ virtual void updateRise(GfxState *state);
+ virtual void updateWordSpace(GfxState *state);
+ virtual void updateHorizScaling(GfxState *state);
+ virtual void updateTextPos(GfxState *state);
+ virtual void updateTextShift(GfxState *state, double shift);
+
+ //----- path painting
+ virtual void stroke(GfxState *state);
+ virtual void fill(GfxState *state);
+ virtual void eoFill(GfxState *state);
+
+ //----- path clipping
+ virtual void clip(GfxState *state);
+ virtual void eoClip(GfxState *state);
+
+ //----- text drawing
+ virtual void drawString(GfxState *state, GString *s);
+ virtual void endTextObject(GfxState *state);
+
+ //----- image drawing
+ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GBool invert,
+ GBool inlineImg);
+ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
+ int *maskColors, GBool inlineImg);
+
+#if OPI_SUPPORT
+ //----- OPI functions
+ virtual void opiBegin(GfxState *state, Dict *opiDict);
+ virtual void opiEnd(GfxState *state, Dict *opiDict);
+#endif
+
+ //----- Type 3 font operators
+ virtual void type3D0(GfxState *state, double wx, double wy);
+ virtual void type3D1(GfxState *state, double wx, double wy,
+ double llx, double lly, double urx, double ury);
+
+ //----- PostScript XObjects
+ virtual void psXObject(Stream *psStream, Stream *level1Stream);
+
+ //----- miscellaneous
+ void setUnderlayCbk(void (*cbk)(PSOutputDev *psOut, void *data),
+ void *data)
+ { underlayCbk = cbk; underlayCbkData = data; }
+ void setOverlayCbk(void (*cbk)(PSOutputDev *psOut, void *data),
+ void *data)
+ { overlayCbk = cbk; overlayCbkData = data; }
+
+private:
+
+ void init(PSOutputFunc outputFuncA, void *outputStreamA,
+ PSFileType fileTypeA, XRef *xrefA, Catalog *catalog,
+ int firstPage, int lastPage, PSOutMode modeA,
+ int paperWidthA, int paperHeightA,
+ GBool manualCtrlA);
+ void setupResources(Dict *resDict);
+ void setupFonts(Dict *resDict);
+ void setupFont(GfxFont *font, Dict *parentResDict);
+ void setupEmbeddedType1Font(Ref *id, GString *psName);
+ void setupExternalType1Font(GString *fileName, GString *psName);
+ void setupEmbeddedType1CFont(GfxFont *font, Ref *id, GString *psName);
+ void setupEmbeddedTrueTypeFont(GfxFont *font, Ref *id, GString *psName);
+ void setupExternalTrueTypeFont(GfxFont *font, GString *psName);
+ void setupEmbeddedCIDType0Font(GfxFont *font, Ref *id, GString *psName);
+ void setupEmbeddedCIDTrueTypeFont(GfxFont *font, Ref *id, GString *psName);
+ void setupType3Font(GfxFont *font, GString *psName, Dict *parentResDict);
+ void setupImages(Dict *resDict);
+ void setupImage(Ref id, Stream *str);
+ void addProcessColor(double c, double m, double y, double k);
+ void addCustomColor(GfxSeparationColorSpace *sepCS);
+ void doPath(GfxPath *path);
+ void doImageL1(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len);
+ void doImageL1Sep(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len);
+ void doImageL2(Object *ref, GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len);
+ void dumpColorSpaceL2(GfxColorSpace *colorSpace);
+#if OPI_SUPPORT
+ void opiBegin20(GfxState *state, Dict *dict);
+ void opiBegin13(GfxState *state, Dict *dict);
+ void opiTransform(GfxState *state, double x0, double y0,
+ double *x1, double *y1);
+ GBool getFileSpec(Object *fileSpec, Object *fileName);
+#endif
+ void writePSChar(char c);
+ void writePS(const char *s);
+ void writePSFmt(const char *fmt, ...);
+ void writePSString(GString *s);
+ void writePSName(const char *s);
+ GString *filterPSName(GString *name);
+
+ PSLevel level; // PostScript level (1, 2, separation)
+ PSOutMode mode; // PostScript mode (PS, EPS, form)
+ int paperWidth; // width of paper, in pts
+ int paperHeight; // height of paper, in pts
+
+ PSOutputFunc outputFunc;
+ void *outputStream;
+ PSFileType fileType; // file / pipe / stdout
+ GBool manualCtrl;
+ int seqPage; // current sequential page number
+ void (*underlayCbk)(PSOutputDev *psOut, void *data);
+ void *underlayCbkData;
+ void (*overlayCbk)(PSOutputDev *psOut, void *data);
+ void *overlayCbkData;
+
+ XRef *xref; // the xref table for this PDF file
+
+ Ref *fontIDs; // list of object IDs of all used fonts
+ int fontIDLen; // number of entries in fontIDs array
+ int fontIDSize; // size of fontIDs array
+ Ref *fontFileIDs; // list of object IDs of all embedded fonts
+ int fontFileIDLen; // number of entries in fontFileIDs array
+ int fontFileIDSize; // size of fontFileIDs array
+ GString **fontFileNames; // list of names of all embedded external fonts
+ int fontFileNameLen; // number of entries in fontFileNames array
+ int fontFileNameSize; // size of fontFileNames array
+ int nextTrueTypeNum; // next unique number to append to a TrueType
+ // font name
+ PSFont16Enc *font16Enc; // encodings for substitute 16-bit fonts
+ int font16EncLen; // number of entries in font16Enc array
+ int font16EncSize; // size of font16Enc array
+ GList *xobjStack; // stack of XObject dicts currently being
+ // processed
+ int numSaves; // current number of gsaves
+
+ double tx, ty; // global translation
+ double xScale, yScale; // global scaling
+ GBool landscape; // true for landscape, false for portrait
+
+ GString *embFontList; // resource comments for embedded fonts
+
+ int processColors; // used process colors
+ PSOutCustomColor // used custom colors
+ *customColors;
+
+ GBool haveTextClip; // set if text has been drawn with a
+ // clipping render mode
+
+ GBool inType3Char; // inside a Type 3 CharProc
+ GString *t3String; // Type 3 content string
+ double t3WX, t3WY, // Type 3 character parameters
+ t3LLX, t3LLY, t3URX, t3URY;
+ GBool t3Cacheable; // cleared if char is not cacheable
+
+#if OPI_SUPPORT
+ int opi13Nest; // nesting level of OPI 1.3 objects
+ int opi20Nest; // nesting level of OPI 2.0 objects
+#endif
+
+ GBool ok; // set up ok?
+
+
+ friend class WinPDFPrinter;
+};
+
+#endif
diff --git a/pdftops/PSTokenizer.cxx b/pdftops/PSTokenizer.cxx
new file mode 100644
index 000000000..834b0ca2d
--- /dev/null
+++ b/pdftops/PSTokenizer.cxx
@@ -0,0 +1,135 @@
+//========================================================================
+//
+// PSTokenizer.cc
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "PSTokenizer.h"
+
+//------------------------------------------------------------------------
+
+// A '1' in this array means the character is white space. A '1' or
+// '2' means the character ends a name or command.
+static char specialChars[256] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
+ 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
+};
+
+//------------------------------------------------------------------------
+
+PSTokenizer::PSTokenizer(int (*getCharFuncA)(void *), void *dataA) {
+ getCharFunc = getCharFuncA;
+ data = dataA;
+ charBuf = -1;
+}
+
+PSTokenizer::~PSTokenizer() {
+}
+
+GBool PSTokenizer::getToken(char *buf, int size, int *length) {
+ GBool comment, backslash;
+ int c;
+ int i;
+
+ // skip whitespace and comments
+ comment = gFalse;
+ while (1) {
+ if ((c = getChar()) == EOF) {
+ buf[0] = '\0';
+ *length = 0;
+ return gFalse;
+ }
+ if (comment) {
+ if (c == '\x0a' || c == '\x0d') {
+ comment = gFalse;
+ }
+ } else if (c == '%') {
+ comment = gTrue;
+ } else if (specialChars[c] != 1) {
+ break;
+ }
+ }
+
+ // read a token
+ i = 0;
+ buf[i++] = c;
+ if (c == '(') {
+ backslash = gFalse;
+ while ((c = lookChar()) != EOF) {
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ getChar();
+ if (c == '\\') {
+ backslash = gTrue;
+ } else if (!backslash && c == ')') {
+ break;
+ } else {
+ backslash = gFalse;
+ }
+ }
+ } else if (c == '<') {
+ while ((c = lookChar()) != EOF) {
+ getChar();
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ if (c == '>') {
+ break;
+ }
+ }
+ } else if (c != '[' && c != ']') {
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
+ getChar();
+ if (i < size - 1) {
+ buf[i++] = c;
+ }
+ }
+ }
+ buf[i] = '\0';
+ *length = i;
+
+ return gTrue;
+}
+
+int PSTokenizer::lookChar() {
+ if (charBuf < 0) {
+ charBuf = (*getCharFunc)(data);
+ }
+ return charBuf;
+}
+
+int PSTokenizer::getChar() {
+ int c;
+
+ if (charBuf < 0) {
+ charBuf = (*getCharFunc)(data);
+ }
+ c = charBuf;
+ charBuf = -1;
+ return c;
+}
diff --git a/pdftops/PSTokenizer.h b/pdftops/PSTokenizer.h
new file mode 100644
index 000000000..d8d347618
--- /dev/null
+++ b/pdftops/PSTokenizer.h
@@ -0,0 +1,41 @@
+//========================================================================
+//
+// PSTokenizer.h
+//
+// Copyright 2002-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PSTOKENIZER_H
+#define PSTOKENIZER_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+
+//------------------------------------------------------------------------
+
+class PSTokenizer {
+public:
+
+ PSTokenizer(int (*getCharFuncA)(void *), void *dataA);
+ ~PSTokenizer();
+
+ // Get the next PostScript token. Returns false at end-of-stream.
+ GBool getToken(char *buf, int size, int *length);
+
+private:
+
+ int lookChar();
+ int getChar();
+
+ int (*getCharFunc)(void *);
+ void *data;
+ int charBuf;
+};
+
+#endif
diff --git a/pdftops/Page.cxx b/pdftops/Page.cxx
new file mode 100644
index 000000000..90b0602a9
--- /dev/null
+++ b/pdftops/Page.cxx
@@ -0,0 +1,349 @@
+//========================================================================
+//
+// Page.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include "GlobalParams.h"
+#include "Object.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Link.h"
+#include "OutputDev.h"
+#ifndef PDF_PARSER_ONLY
+#include "Gfx.h"
+#include "Annot.h"
+#endif
+#include "Error.h"
+#include "Page.h"
+
+//------------------------------------------------------------------------
+// PageAttrs
+//------------------------------------------------------------------------
+
+PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
+ Object obj1;
+ double w, h;
+
+ // get old/default values
+ if (attrs) {
+ mediaBox = attrs->mediaBox;
+ cropBox = attrs->cropBox;
+ haveCropBox = attrs->haveCropBox;
+ rotate = attrs->rotate;
+ attrs->resources.copy(&resources);
+ } else {
+ // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
+ // but some (non-compliant) PDF files don't specify a MediaBox
+ mediaBox.x1 = 0;
+ mediaBox.y1 = 0;
+ mediaBox.x2 = 612;
+ mediaBox.y2 = 792;
+ cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
+ haveCropBox = gFalse;
+ rotate = 0;
+ resources.initNull();
+ }
+
+ // media box
+ readBox(dict, "MediaBox", &mediaBox);
+
+ // crop box
+ if (readBox(dict, "CropBox", &cropBox)) {
+ haveCropBox = gTrue;
+ }
+ if (!haveCropBox) {
+ cropBox = mediaBox;
+ }
+
+ // if the MediaBox is excessively larger than the CropBox,
+ // just use the CropBox
+ limitToCropBox = gFalse;
+ if (haveCropBox) {
+ w = 0.25 * (cropBox.x2 - cropBox.x1);
+ h = 0.25 * (cropBox.y2 - cropBox.y1);
+ if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
+ (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
+ limitToCropBox = gTrue;
+ }
+ }
+
+ // other boxes
+ bleedBox = cropBox;
+ readBox(dict, "BleedBox", &bleedBox);
+ trimBox = cropBox;
+ readBox(dict, "TrimBox", &trimBox);
+ artBox = cropBox;
+ readBox(dict, "ArtBox", &artBox);
+
+ // rotate
+ dict->lookup("Rotate", &obj1);
+ if (obj1.isInt()) {
+ rotate = obj1.getInt();
+ }
+ obj1.free();
+ while (rotate < 0) {
+ rotate += 360;
+ }
+ while (rotate >= 360) {
+ rotate -= 360;
+ }
+
+ // misc attributes
+ dict->lookup("LastModified", &lastModified);
+ dict->lookup("BoxColorInfo", &boxColorInfo);
+ dict->lookup("Group", &group);
+ dict->lookup("Metadata", &metadata);
+ dict->lookup("PieceInfo", &pieceInfo);
+ dict->lookup("SeparationInfo", &separationInfo);
+
+ // resource dictionary
+ dict->lookup("Resources", &obj1);
+ if (obj1.isDict()) {
+ resources.free();
+ obj1.copy(&resources);
+ }
+ obj1.free();
+}
+
+PageAttrs::~PageAttrs() {
+ lastModified.free();
+ boxColorInfo.free();
+ group.free();
+ metadata.free();
+ pieceInfo.free();
+ separationInfo.free();
+ resources.free();
+}
+
+GBool PageAttrs::readBox(Dict *dict, const char *key, PDFRectangle *box) {
+ PDFRectangle tmp;
+ Object obj1, obj2;
+ GBool ok;
+
+ dict->lookup(key, &obj1);
+ if (obj1.isArray() && obj1.arrayGetLength() == 4) {
+ ok = gTrue;
+ obj1.arrayGet(0, &obj2);
+ if (obj2.isNum()) {
+ tmp.x1 = obj2.getNum();
+ } else {
+ ok = gFalse;
+ }
+ obj2.free();
+ obj1.arrayGet(1, &obj2);
+ if (obj2.isNum()) {
+ tmp.y1 = obj2.getNum();
+ } else {
+ ok = gFalse;
+ }
+ obj2.free();
+ obj1.arrayGet(2, &obj2);
+ if (obj2.isNum()) {
+ tmp.x2 = obj2.getNum();
+ } else {
+ ok = gFalse;
+ }
+ obj2.free();
+ obj1.arrayGet(3, &obj2);
+ if (obj2.isNum()) {
+ tmp.y2 = obj2.getNum();
+ } else {
+ ok = gFalse;
+ }
+ obj2.free();
+ if (ok) {
+ *box = tmp;
+ }
+ } else {
+ ok = gFalse;
+ }
+ obj1.free();
+ return ok;
+}
+
+//------------------------------------------------------------------------
+// Page
+//------------------------------------------------------------------------
+
+Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
+ ok = gTrue;
+ xref = xrefA;
+ num = numA;
+
+ // get attributes
+ attrs = attrsA;
+
+ // annotations
+ pageDict->lookupNF("Annots", &annots);
+ if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
+ error(-1, "Page annotations object (page %d) is wrong type (%s)",
+ num, annots.getTypeName());
+ annots.free();
+ goto err2;
+ }
+
+ // contents
+ pageDict->lookupNF("Contents", &contents);
+ if (!(contents.isRef() || contents.isArray() ||
+ contents.isNull())) {
+ error(-1, "Page contents object (page %d) is wrong type (%s)",
+ num, contents.getTypeName());
+ contents.free();
+ goto err1;
+ }
+
+ return;
+
+ err2:
+ annots.initNull();
+ err1:
+ contents.initNull();
+ ok = gFalse;
+}
+
+Page::~Page() {
+ delete attrs;
+ annots.free();
+ contents.free();
+}
+
+void Page::display(OutputDev *out, double hDPI, double vDPI, int rotate,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+ displaySlice(out, hDPI, vDPI, rotate, -1, -1, -1, -1, links, catalog,
+ abortCheckCbk, abortCheckCbkData);
+}
+
+void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data),
+ void *abortCheckCbkData) {
+#ifndef PDF_PARSER_ONLY
+ PDFRectangle *mediaBox, *cropBox;
+ PDFRectangle box;
+ Gfx *gfx;
+ Object obj;
+ Link *link;
+ Annots *annotList;
+ double kx, ky;
+ int i;
+
+ rotate += getRotate();
+ if (rotate >= 360) {
+ rotate -= 360;
+ } else if (rotate < 0) {
+ rotate += 360;
+ }
+
+ mediaBox = getBox();
+ if (sliceW >= 0 && sliceH >= 0) {
+ kx = 72.0 / hDPI;
+ ky = 72.0 / vDPI;
+ if (rotate == 90) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x1 + ky * sliceY;
+ box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+ } else {
+ box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - ky * sliceY;
+ }
+ box.y1 = mediaBox->y1 + kx * sliceX;
+ box.y2 = mediaBox->y1 + kx * (sliceX + sliceW);
+ } else if (rotate == 180) {
+ box.x1 = mediaBox->x2 - kx * (sliceX + sliceW);
+ box.x2 = mediaBox->x2 - kx * sliceX;
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y1 + ky * sliceY;
+ box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+ } else {
+ box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - ky * sliceY;
+ }
+ } else if (rotate == 270) {
+ if (out->upsideDown()) {
+ box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
+ box.x2 = mediaBox->x2 - ky * sliceY;
+ } else {
+ box.x1 = mediaBox->x1 + ky * sliceY;
+ box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
+ }
+ box.y1 = mediaBox->y2 - kx * (sliceX + sliceW);
+ box.y2 = mediaBox->y2 - kx * sliceX;
+ } else {
+ box.x1 = mediaBox->x1 + kx * sliceX;
+ box.x2 = mediaBox->x1 + kx * (sliceX + sliceW);
+ if (out->upsideDown()) {
+ box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
+ box.y2 = mediaBox->y2 - ky * sliceY;
+ } else {
+ box.y1 = mediaBox->y1 + ky * sliceY;
+ box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
+ }
+ }
+ } else {
+ box = *mediaBox;
+ }
+ cropBox = getCropBox();
+
+ if (globalParams->getPrintCommands()) {
+ fprintf(stderr, "DEBUG2: ***** MediaBox = ll:%g,%g ur:%g,%g\n",
+ box.x1, box.y1, box.x2, box.y2);
+ if (isCropped()) {
+ fprintf(stderr, "DEBUG2: ***** CropBox = ll:%g,%g ur:%g,%g\n",
+ cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
+ }
+ fprintf(stderr, "DEBUG2: ***** Rotate = %d\n", attrs->getRotate());
+ }
+
+ gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
+ hDPI, vDPI, &box, isCropped(), cropBox, rotate,
+ abortCheckCbk, abortCheckCbkData);
+ contents.fetch(xref, &obj);
+ if (!obj.isNull()) {
+ gfx->saveState();
+ gfx->display(&obj);
+ gfx->restoreState();
+ }
+ obj.free();
+
+ // draw links
+ if (links) {
+ gfx->saveState();
+ for (i = 0; i < links->getNumLinks(); ++i) {
+ link = links->getLink(i);
+ out->drawLink(link, catalog);
+ }
+ gfx->restoreState();
+ out->dump();
+ }
+
+ // draw non-link annotations
+ annotList = new Annots(xref, annots.fetch(xref, &obj));
+ obj.free();
+ if (annotList->getNumAnnots() > 0) {
+ if (globalParams->getPrintCommands()) {
+ fprintf(stderr, "DEBUG2: ***** Annotations\n");
+ }
+ for (i = 0; i < annotList->getNumAnnots(); ++i) {
+ annotList->getAnnot(i)->draw(gfx);
+ }
+ out->dump();
+ }
+ delete annotList;
+
+ delete gfx;
+#endif
+}
diff --git a/pdftops/Page.h b/pdftops/Page.h
new file mode 100644
index 000000000..727082351
--- /dev/null
+++ b/pdftops/Page.h
@@ -0,0 +1,166 @@
+//========================================================================
+//
+// Page.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PAGE_H
+#define PAGE_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Object.h"
+
+class Dict;
+class XRef;
+class OutputDev;
+class Links;
+class Catalog;
+
+//------------------------------------------------------------------------
+
+class PDFRectangle {
+public:
+ double x1, y1, x2, y2;
+
+ PDFRectangle() { x1 = y1 = x2 = y2 = 0; }
+ PDFRectangle(double x1A, double y1A, double x2A, double y2A)
+ { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
+ GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
+};
+
+//------------------------------------------------------------------------
+// PageAttrs
+//------------------------------------------------------------------------
+
+class PageAttrs {
+public:
+
+ // Construct a new PageAttrs object by merging a dictionary
+ // (of type Pages or Page) into another PageAttrs object. If
+ // <attrs> is NULL, uses defaults.
+ PageAttrs(PageAttrs *attrs, Dict *dict);
+
+ // Destructor.
+ ~PageAttrs();
+
+ // Accessors.
+ PDFRectangle *getBox() { return limitToCropBox ? &cropBox : &mediaBox; }
+ PDFRectangle *getMediaBox() { return &mediaBox; }
+ PDFRectangle *getCropBox() { return &cropBox; }
+ GBool isCropped() { return haveCropBox; }
+ PDFRectangle *getBleedBox() { return &bleedBox; }
+ PDFRectangle *getTrimBox() { return &trimBox; }
+ PDFRectangle *getArtBox() { return &artBox; }
+ int getRotate() { return rotate; }
+ GString *getLastModified()
+ { return lastModified.isString()
+ ? lastModified.getString() : (GString *)NULL; }
+ Dict *getBoxColorInfo()
+ { return boxColorInfo.isDict() ? boxColorInfo.getDict() : (Dict *)NULL; }
+ Dict *getGroup()
+ { return group.isDict() ? group.getDict() : (Dict *)NULL; }
+ Stream *getMetadata()
+ { return metadata.isStream() ? metadata.getStream() : (Stream *)NULL; }
+ Dict *getPieceInfo()
+ { return pieceInfo.isDict() ? pieceInfo.getDict() : (Dict *)NULL; }
+ Dict *getSeparationInfo()
+ { return separationInfo.isDict()
+ ? separationInfo.getDict() : (Dict *)NULL; }
+ Dict *getResourceDict()
+ { return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
+
+private:
+
+ GBool readBox(Dict *dict, const char *key, PDFRectangle *box);
+
+ PDFRectangle mediaBox;
+ PDFRectangle cropBox;
+ GBool haveCropBox;
+ GBool limitToCropBox;
+ PDFRectangle bleedBox;
+ PDFRectangle trimBox;
+ PDFRectangle artBox;
+ int rotate;
+ Object lastModified;
+ Object boxColorInfo;
+ Object group;
+ Object metadata;
+ Object pieceInfo;
+ Object separationInfo;
+ Object resources;
+};
+
+//------------------------------------------------------------------------
+// Page
+//------------------------------------------------------------------------
+
+class Page {
+public:
+
+ // Constructor.
+ Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA);
+
+ // Destructor.
+ ~Page();
+
+ // Is page valid?
+ GBool isOk() { return ok; }
+
+ // Get page parameters.
+ PDFRectangle *getBox() { return attrs->getBox(); }
+ PDFRectangle *getMediaBox() { return attrs->getMediaBox(); }
+ PDFRectangle *getCropBox() { return attrs->getCropBox(); }
+ GBool isCropped() { return attrs->isCropped(); }
+ double getWidth() { return attrs->getBox()->x2 - attrs->getBox()->x1; }
+ double getHeight() { return attrs->getBox()->y2 - attrs->getBox()->y1; }
+ PDFRectangle *getBleedBox() { return attrs->getBleedBox(); }
+ PDFRectangle *getTrimBox() { return attrs->getTrimBox(); }
+ PDFRectangle *getArtBox() { return attrs->getArtBox(); }
+ int getRotate() { return attrs->getRotate(); }
+ GString *getLastModified() { return attrs->getLastModified(); }
+ Dict *getBoxColorInfo() { return attrs->getBoxColorInfo(); }
+ Dict *getGroup() { return attrs->getGroup(); }
+ Stream *getMetadata() { return attrs->getMetadata(); }
+ Dict *getPieceInfo() { return attrs->getPieceInfo(); }
+ Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
+
+ // Get resource dictionary.
+ Dict *getResourceDict() { return attrs->getResourceDict(); }
+
+ // Get annotations array.
+ Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
+
+ // Get contents.
+ Object *getContents(Object *obj) { return contents.fetch(xref, obj); }
+
+ // Display a page.
+ void display(OutputDev *out, double hDPI, double vDPI, int rotate,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+ // Display part of a page.
+ void displaySlice(OutputDev *out, double hDPI, double vDPI, int rotate,
+ int sliceX, int sliceY, int sliceW, int sliceH,
+ Links *links, Catalog *catalog,
+ GBool (*abortCheckCbk)(void *data) = NULL,
+ void *abortCheckCbkData = NULL);
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ int num; // page number
+ PageAttrs *attrs; // page attributes
+ Object annots; // annotations array
+ Object contents; // page contents
+ GBool ok; // true if page is valid
+};
+
+#endif
diff --git a/pdftops/Params.cxx b/pdftops/Params.cxx
new file mode 100644
index 000000000..8536da20d
--- /dev/null
+++ b/pdftops/Params.cxx
@@ -0,0 +1,90 @@
+//========================================================================
+//
+// Params.cc
+//
+// Copyright 1996 Derek B. Noonburg
+//
+//========================================================================
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include "gtypes.h"
+#include "gmem.h"
+#include "GString.h"
+#include "gfile.h"
+#include "Params.h"
+
+char **fontPath = NULL;
+static int fontPathLen, fontPathSize;
+
+DevFontMapEntry *devFontMap = NULL;
+static int devFontMapLen, devFontMapSize;
+
+void initParams(char *userConfigFile, char *sysConfigFile) {
+ GString *fileName;
+ FILE *f;
+ char buf[256];
+ char *p, *q;
+
+ // initialize font path and font map
+ fontPath = (char **)gmalloc((fontPathSize = 8) * sizeof(char *));
+ fontPath[fontPathLen = 0] = NULL;
+ devFontMap = (DevFontMapEntry *)gmalloc((devFontMapSize = 8) *
+ sizeof(DevFontMapEntry));
+ devFontMap[devFontMapLen = 0].pdfFont = NULL;
+
+ // read config file
+ fileName = appendToPath(getHomeDir(), userConfigFile);
+ if (!(f = fopen(fileName->getCString(), "r"))) {
+ f = fopen(sysConfigFile, "r");
+ }
+ if (f) {
+ while (fgets(buf, sizeof(buf)-1, f)) {
+ buf[sizeof(buf)-1] = '\0';
+ p = strtok(buf, " \t\n\r");
+ if (p && !strcmp(p, "fontpath")) {
+ if (fontPathLen+1 >= fontPathSize)
+ fontPath = (char **)
+ grealloc(fontPath, (fontPathSize += 8) * sizeof(char *));
+ p = strtok(NULL, " \t\n\r");
+ fontPath[fontPathLen++] = copyString(p);
+ } else if (p && !strcmp(p, "fontmap")) {
+ if (devFontMapLen+1 >= devFontMapSize)
+ devFontMap = (DevFontMapEntry *)
+ grealloc(devFontMap,
+ (devFontMapSize += 8) * sizeof(DevFontMapEntry));
+ p = strtok(NULL, " \t\n\r");
+ devFontMap[devFontMapLen].pdfFont = copyString(p);
+ p = strtok(NULL, "\t\n\r");
+ while (*p == ' ')
+ ++p;
+ for (q = p + strlen(p) - 1; q >= p && *q == ' '; --q) ;
+ q[1] = '\0';
+ devFontMap[devFontMapLen++].devFont = copyString(p);
+ }
+ }
+ fclose(f);
+ fontPath[fontPathLen] = NULL;
+ devFontMap[devFontMapLen].pdfFont = NULL;
+ }
+ delete fileName;
+}
+
+void freeParams() {
+ int i;
+
+ if (fontPath) {
+ for (i = 0; i < fontPathLen; ++i)
+ gfree(fontPath[i]);
+ gfree(fontPath);
+ }
+ if (devFontMap) {
+ for (i = 0; i < devFontMapLen; ++i) {
+ gfree(devFontMap[i].pdfFont);
+ gfree(devFontMap[i].devFont);
+ }
+ gfree(devFontMap);
+ }
+}
diff --git a/pdftops/Params.h b/pdftops/Params.h
new file mode 100644
index 000000000..1d8ce3828
--- /dev/null
+++ b/pdftops/Params.h
@@ -0,0 +1,38 @@
+//========================================================================
+//
+// Params.h
+//
+// Copyright 1996 Derek B. Noonburg
+//
+//========================================================================
+
+#ifndef PARAMS_H
+#define PARAMS_H
+
+#include "gtypes.h"
+
+// If this is set, error messages will be silently discarded.
+extern GBool errQuiet;
+
+// Font search path.
+extern char **fontPath;
+
+// Mapping from PDF font name to device font name.
+struct DevFontMapEntry {
+ char *pdfFont;
+ char *devFont;
+};
+extern DevFontMapEntry *devFontMap;
+
+//------------------------------------------------------------------------
+
+// Initialize font path and font map, and read configuration file. If
+// <userConfigFile> exists, read it; else if <sysConfigFile> exists,
+// read it. <userConfigFile> is relative to the user's home
+// directory; <sysConfigFile> should be an absolute path.
+extern void initParams(char *userConfigFile, char *sysConfigFile);
+
+// Free memory used for font path and font map.
+extern void freeParams();
+
+#endif
diff --git a/pdftops/Parser.cxx b/pdftops/Parser.cxx
new file mode 100644
index 000000000..77169ca08
--- /dev/null
+++ b/pdftops/Parser.cxx
@@ -0,0 +1,231 @@
+//========================================================================
+//
+// Parser.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stddef.h>
+#include "Object.h"
+#include "Array.h"
+#include "Dict.h"
+#include "Parser.h"
+#include "XRef.h"
+#include "Error.h"
+#ifndef NO_DECRYPTION
+#include "Decrypt.h"
+#endif
+
+Parser::Parser(XRef *xrefA, Lexer *lexerA) {
+ xref = xrefA;
+ lexer = lexerA;
+ inlineImg = 0;
+ lexer->getObj(&buf1);
+ lexer->getObj(&buf2);
+}
+
+Parser::~Parser() {
+ buf1.free();
+ buf2.free();
+ delete lexer;
+}
+
+#ifndef NO_DECRYPTION
+Object *Parser::getObj(Object *obj,
+ Guchar *fileKey, int keyLength,
+ int objNum, int objGen) {
+#else
+Object *Parser::getObj(Object *obj) {
+#endif
+ char *key;
+ Stream *str;
+ Object obj2;
+ int num;
+#ifndef NO_DECRYPTION
+ Decrypt *decrypt;
+ GString *s;
+ char *p;
+ int i;
+#endif
+
+ // refill buffer after inline image data
+ if (inlineImg == 2) {
+ buf1.free();
+ buf2.free();
+ lexer->getObj(&buf1);
+ lexer->getObj(&buf2);
+ inlineImg = 0;
+ }
+
+ // array
+ if (buf1.isCmd("[")) {
+ shift();
+ obj->initArray(xref);
+ while (!buf1.isCmd("]") && !buf1.isEOF())
+#ifndef NO_DECRYPTION
+ obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen));
+#else
+ obj->arrayAdd(getObj(&obj2));
+#endif
+ if (buf1.isEOF())
+ error(getPos(), "End of file inside array");
+ shift();
+
+ // dictionary or stream
+ } else if (buf1.isCmd("<<")) {
+ shift();
+ obj->initDict(xref);
+ while (!buf1.isCmd(">>") && !buf1.isEOF()) {
+ if (!buf1.isName()) {
+ error(getPos(), "Dictionary key must be a name object");
+ shift();
+ } else {
+ key = copyString(buf1.getName());
+ shift();
+ if (buf1.isEOF() || buf1.isError()) {
+ gfree(key);
+ break;
+ }
+#ifndef NO_DECRYPTION
+ obj->dictAdd(key, getObj(&obj2, fileKey, keyLength, objNum, objGen));
+#else
+ obj->dictAdd(key, getObj(&obj2));
+#endif
+ }
+ }
+ if (buf1.isEOF())
+ error(getPos(), "End of file inside dictionary");
+ if (buf2.isCmd("stream")) {
+ if ((str = makeStream(obj))) {
+ obj->initStream(str);
+#ifndef NO_DECRYPTION
+ if (fileKey) {
+ str->getBaseStream()->doDecryption(fileKey, keyLength,
+ objNum, objGen);
+ }
+#endif
+ } else {
+ obj->free();
+ obj->initError();
+ }
+ } else {
+ shift();
+ }
+
+ // indirect reference or integer
+ } else if (buf1.isInt()) {
+ num = buf1.getInt();
+ shift();
+ if (buf1.isInt() && buf2.isCmd("R")) {
+ obj->initRef(num, buf1.getInt());
+ shift();
+ shift();
+ } else {
+ obj->initInt(num);
+ }
+
+#ifndef NO_DECRYPTION
+ // string
+ } else if (buf1.isString() && fileKey) {
+ buf1.copy(obj);
+ s = obj->getString();
+ decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
+ for (i = 0, p = obj->getString()->getCString();
+ i < s->getLength();
+ ++i, ++p) {
+ *p = decrypt->decryptByte(*p);
+ }
+ delete decrypt;
+ shift();
+#endif
+
+ // simple object
+ } else {
+ buf1.copy(obj);
+ shift();
+ }
+
+ return obj;
+}
+
+Stream *Parser::makeStream(Object *dict) {
+ Object obj;
+ Stream *str;
+ Guint pos, endPos, length;
+
+ // get stream start position
+ lexer->skipToNextLine();
+ pos = lexer->getPos();
+
+ // get length
+ dict->dictLookup("Length", &obj);
+ if (obj.isInt()) {
+ length = (Guint)obj.getInt();
+ obj.free();
+ } else {
+ error(getPos(), "Bad 'Length' attribute in stream");
+ obj.free();
+ return NULL;
+ }
+
+ // check for length in damaged file
+ if (xref->getStreamEnd(pos, &endPos)) {
+ length = endPos - pos;
+ }
+
+ // in badly damaged PDF files, we can run off the end of the input
+ // stream immediately after the "stream" token
+ if (!lexer->getStream()) {
+ return NULL;
+ }
+
+ // make base stream
+ str = lexer->getStream()->getBaseStream()->makeSubStream(pos, gTrue,
+ length, dict);
+
+ // get filters
+ str = str->addFilters(dict);
+
+ // skip over stream data
+ lexer->setPos(pos + length);
+
+ // refill token buffers and check for 'endstream'
+ shift(); // kill '>>'
+ shift(); // kill 'stream'
+ if (buf1.isCmd("endstream")) {
+ shift();
+ } else {
+ error(getPos(), "Missing 'endstream'");
+ str->ignoreLength();
+ }
+
+ return str;
+}
+
+void Parser::shift() {
+ if (inlineImg > 0) {
+ if (inlineImg < 2) {
+ ++inlineImg;
+ } else {
+ // in a damaged content stream, if 'ID' shows up in the middle
+ // of a dictionary, we need to reset
+ inlineImg = 0;
+ }
+ } else if (buf2.isCmd("ID")) {
+ lexer->skipChar(); // skip char after 'ID' command
+ inlineImg = 1;
+ }
+ buf1.free();
+ buf1 = buf2;
+ if (inlineImg > 0) // don't buffer inline image data
+ buf2.initNull();
+ else
+ lexer->getObj(&buf2);
+}
diff --git a/pdftops/Parser.h b/pdftops/Parser.h
new file mode 100644
index 000000000..47d4f50e5
--- /dev/null
+++ b/pdftops/Parser.h
@@ -0,0 +1,60 @@
+//========================================================================
+//
+// Parser.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "Lexer.h"
+
+//------------------------------------------------------------------------
+// Parser
+//------------------------------------------------------------------------
+
+class Parser {
+public:
+
+ // Constructor.
+ Parser(XRef *xrefA, Lexer *lexerA);
+
+ // Destructor.
+ ~Parser();
+
+ // Get the next object from the input stream.
+#ifndef NO_DECRYPTION
+ Object *getObj(Object *obj,
+ Guchar *fileKey = NULL, int keyLength = 0,
+ int objNum = 0, int objGen = 0);
+#else
+ Object *getObj(Object *obj);
+#endif
+
+ // Get stream.
+ Stream *getStream() { return lexer->getStream(); }
+
+ // Get current position in file.
+ int getPos() { return lexer->getPos(); }
+
+private:
+
+ XRef *xref; // the xref table for this PDF file
+ Lexer *lexer; // input stream
+ Object buf1, buf2; // next two tokens
+ int inlineImg; // set when inline image data is encountered
+
+ Stream *makeStream(Object *dict);
+ void shift();
+};
+
+#endif
+
diff --git a/pdftops/README b/pdftops/README
new file mode 100644
index 000000000..f089d05d6
--- /dev/null
+++ b/pdftops/README
@@ -0,0 +1,446 @@
+Xpdf
+====
+
+version 2.02
+2003-mar-24
+
+The Xpdf software and documentation are
+copyright 1996-2003 Glyph & Cog, LLC.
+
+Email: derekn@foolabs.com
+WWW: http://www.foolabs.com/xpdf/
+
+The PDF data structures, operators, and specification are
+copyright 1985-2001 Adobe Systems Inc.
+
+
+What is Xpdf?
+-------------
+
+Xpdf is an open source viewer for Portable Document Format (PDF)
+files. (These are also sometimes also called 'Acrobat' files, from
+the name of Adobe's PDF software.) The Xpdf project also includes a
+PDF text extractor, PDF-to-PostScript converter, and various other
+utilities.
+
+Xpdf runs under the X Window System on UNIX, VMS, and OS/2. The non-X
+components (pdftops, pdftotext, etc.) also run on Win32 systems and
+should run on pretty much any system with a decent C++ compiler.
+
+Xpdf is designed to be small and efficient. It can use Type 1,
+TrueType, or standard X fonts.
+
+
+Distribution
+------------
+
+Xpdf is licensed under the GNU General Public License (GPL), version
+2. In my opinion, the GPL is a convoluted, confusing, ambiguous mess.
+But it's also pervasive, and I'm sick of arguing. And even if it is
+confusing, the basic idea is good.
+
+In order to cut down on the confusion a little bit, here are some
+informal clarifications:
+
+- I don't mind if you redistribute Xpdf in source and/or binary form,
+ as long as you include all of the documentation: README, man pages
+ (or help files), and COPYING. (Note that the README file contains a
+ pointer to a web page with the source code.)
+
+- Selling a CD-ROM that contains Xpdf is fine with me, as long as it
+ includes the documentation. I wouldn't mind receiving a sample
+ copy, but it's not necessary.
+
+- If you make useful changes to Xpdf, please make the source code
+ available -- post it on a web site, email it to me, whatever.
+
+If you're interested in commercial licensing, please see the Glyph &
+Cog web site:
+
+ http://www.glyphandcog.com/
+
+
+Compatibility
+-------------
+
+Xpdf is developed and tested on a Linux 2.2 x86 system.
+
+In addition, it has been compiled by others on Solaris, AIX, HP-UX,
+SCO UnixWare, Digital Unix, Irix, and numerous other Unix
+implementations, as well as VMS and OS/2. It should work on pretty
+much any system which runs X11 and has Unix-like libraries. You'll
+need ANSI C++ and C compilers to compile it.
+
+The non-X components of Xpdf (pdftops, pdftotext, pdfinfo, pdffonts,
+pdfimages) can also be compiled on Win32 systems. See the Xpdf web
+page for details.
+
+If you compile Xpdf for a system not listed on the web page, please
+let me know. If you're willing to make your binary available by ftp
+or on the web, I'll be happy to add a link from the Xpdf web page. I
+have decided not to host any binaries I didn't compile myself (for
+disk space and support reasons).
+
+If you can't get Xpdf to compile on your system, send me email and
+I'll try to help.
+
+Xpdf has been ported to the Acorn, Amiga, BeOS, and EPOC. See the
+Xpdf web page for links.
+
+
+Getting Xpdf
+------------
+
+The latest version is available from:
+
+ http://www.foolabs.com/xpdf/
+
+or:
+
+ ftp://ftp.foolabs.com/pub/xpdf/
+
+Source code and several precompiled executables are available.
+
+Announcements of new versions are posted to several newsgroups
+(comp.text.pdf, comp.os.linux.announce, and others) and emailed to a
+list of people. If you'd like to receive email notification of new
+versions, just let me know.
+
+
+Running Xpdf
+------------
+
+To run xpdf, simply type:
+
+ xpdf file.pdf
+
+To generate a PostScript file, hit the "print" button in xpdf, or run
+pdftops:
+
+ pdftops file.pdf
+
+To generate a plain text file, run pdftotext:
+
+ pdftotext file.pdf
+
+There are four additional utilities (which are fully described in
+their man pages):
+
+ pdfinfo -- dumps a PDF file's Info dictionary (plus some other
+ useful information)
+ pdffonts -- lists the fonts used in a PDF file along with various
+ information for each font
+ pdftopbm -- converts a PDF file to a series of PBM-format bitmaps
+ pdfimages -- extracts the images from a PDF file
+
+Command line options and many other details are described in the man
+pages (xpdf.1, etc.) and the VMS help files (xpdf.hlp, etc.).
+
+
+Upgrading from Xpdf 0.9x
+------------------------
+
+WARNING: Xpdf 1.x switched to a completely different config file setup
+than Xpdf 0.9x.
+
+Many of the configuration options that used to be X resources have
+been moved into the Xpdf config file. There are also lots of new and
+improved options. If you're upgrading from Xpdf 0.9x, please read
+through the sample config file (doc/sample-xpdfrc) and the xpdfrc(5)
+man page.
+
+The Asian language support has been pulled out into separate packages,
+loaded at run time. This is much cleaner than the 0.9x approach -- it
+makes the base distribution smaller, allows the language support
+packages to be upgraded separately, and lets users customize Xpdf for
+other text encodings without modifying the source. See the web site
+(http://www.foolabs.com/xpdf) for info on downloading the language
+support packages.
+
+All of the Xpdf tools, including the X viewer and the command line
+programs, read the same config file. They first attempt to read the
+user's personal config file:
+
+ $HOME/.xpdfrc
+
+If it is not found, the Xpdf tools read a system-wide config file,
+typically something like:
+
+ /usr/local/etc/xpdfrc
+
+(this location can be customized when building Xpdf).
+
+The Win32 command line tools look in the directory containing the
+executable, e.g.:
+
+ C:/Program Files/Xpdf/xpdfrc
+
+Xpdf comes with a "sample-xpdfrc" file in the doc directory. This is
+a good starting point for constructing your own config file.
+
+For full details, please see the xpdfrc(5) man page.
+
+
+Fonts
+-----
+
+By default, Xpdf will use X server fonts. It requires the following
+fonts:
+
+* Courier: medium-r, bold-r, medium-o, and bold-o
+* Helvetica: medium-r, bold-r, medium-o, and bold-o
+* Times: medium-r, bold-r, medium-i, and bold-i
+* Symbol: medium-r
+* Zapf Dingbats: medium-r
+
+Most X installations should already have all of these fonts (except
+maybe Zapf Dingbats).
+
+If Xpdf is built with support for t1lib (or FreeType 2), you can get
+much higher quality text by using Type 1 fonts instead of X server
+fonts. For example, you can use the Type 1 fonts that come with
+ghostscript. To do this, add the following lines to the xpdfrc file
+(e.g., /usr/local/etc/xpdfrc or $HOME/.xpdfrc):
+
+displayFontT1 Times-Roman /usr/local/share/ghostscript/fonts/n021003l.pfb
+displayFontT1 Times-Italic /usr/local/share/ghostscript/fonts/n021023l.pfb
+displayFontT1 Times-Bold /usr/local/share/ghostscript/fonts/n021004l.pfb
+displayFontT1 Times-BoldItalic /usr/local/share/ghostscript/fonts/n021024l.pfb
+displayFontT1 Helvetica /usr/local/share/ghostscript/fonts/n019003l.pfb
+displayFontT1 Helvetica-Oblique /usr/local/share/ghostscript/fonts/n019023l.pfb
+displayFontT1 Helvetica-Bold /usr/local/share/ghostscript/fonts/n019004l.pfb
+displayFontT1 Helvetica-BoldOblique /usr/local/share/ghostscript/fonts/n019024l.pfb
+displayFontT1 Courier /usr/local/share/ghostscript/fonts/n022003l.pfb
+displayFontT1 Courier-Oblique /usr/local/share/ghostscript/fonts/n022023l.pfb
+displayFontT1 Courier-Bold /usr/local/share/ghostscript/fonts/n022004l.pfb
+displayFontT1 Courier-BoldOblique /usr/local/share/ghostscript/fonts/n022024l.pfb
+displayFontT1 Symbol /usr/local/share/ghostscript/fonts/s050000l.pfb
+displayFontT1 ZapfDingbats /usr/local/share/ghostscript/fonts/d050000l.pfb
+
+You will need to replace '/usr/local/share/ghostscript/fonts' with the
+appropriate path on your system.
+
+
+Compiling Xpdf
+--------------
+
+See the separate file, INSTALL.
+
+
+Bugs
+----
+
+If you find a bug in Xpdf, i.e., if it prints an error message,
+crashes, or incorrectly displays a document, and you don't see that
+bug listed here, please send me email, with a pointer (URL, ftp site,
+etc.) to the PDF file.
+
+
+Acknowledgments
+---------------
+
+Thanks to:
+
+* Patrick Voigt for help with the remote server code.
+* Patrick Moreau, Martin P.J. Zinser, and David Mathog for the VMS
+ port.
+* David Boldt and Rick Rodgers for sample man pages.
+* Brendan Miller for the icon idea.
+* Olly Betts for help testing pdftotext.
+* Peter Ganten for the OS/2 port.
+* Michael Richmond for the Win32 port of pdftops and pdftotext and the
+ xpdf/cygwin/XFree86 build instructions.
+* Frank M. Siegert for improvements in the PostScript code.
+* Leo Smiers for the decryption patches.
+* Rainer Menzner for creating t1lib, and for helping me adapt it to
+ xpdf.
+* Pine Tree Systems A/S for funding the OPI and EPS support in
+ pdftops.
+* Easy Software Products for funding the "sh" operator support.
+* Tom Kacvinsky for help with FreeType and for being my interface to
+ the FreeType team.
+* Theppitak Karoonboonyanan for help with Thai support.
+* Leonard Rosenthol for help and contributions on a bunch of things.
+* Alexandros Diamantidis and Maria Adaloglou for help with Greek
+ support.
+* Lawrence Lai for help with the CJK Unicode maps.
+
+Various people have contributed modifications made for use by the
+pdftex project:
+
+* Han The Thanh
+* Martin Schröder of ArtCom GmbH
+
+
+References
+----------
+
+Adobe Systems Inc., _PDF Reference: Adobe Portable Document Format
+version 1.4_, 3nd ed.
+Addison-Wesley, 2001, ISBN 0-201-75839-3.
+http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDFReference.pdf
+[The printed manual for PDF version 1.4.]
+
+Adobe Systems Inc., _Portable Document Format: Changes from Version
+1.3 to 1.4_, Adobe Developer Support Technical Note #5409.
+June 11, 2001.
+http://partners.adobe.com/asn/developer/acrosdk/docs/filefmtspecs/PDF14Deltas.pdf
+[Updates for PDF 1.4.]
+
+Adobe Systems Inc., _PostScript Language Reference_, 3rd ed.
+Addison-Wesley, 1999, ISBN 0-201-37922-8.
+[The official PostScript manual.]
+
+Adobe Systems, Inc., _The Type 42 Font Format Specification_,
+Adobe Developer Support Technical Specification #5012. 1998.
+http://partners.adobe.com/asn/developer/pdfs/tn/5012.Type42_Spec.pdf
+[Type 42 is the format used to embed TrueType fonts in PostScript
+files.]
+
+Adobe Systems, Inc., _Adobe CMap and CIDFont Files Specification_,
+Adobe Developer Support Technical Specification #5014. 1995.
+http://www.adobe.com/supportservice/devrelations/PDFS/TN/5014.CIDFont_Spec.pdf
+[CMap file format needed for Japanese and Chinese font support.]
+
+Adobe Systems, Inc., _Adobe-Japan1-4 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5078.
+2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5078.CID_Glyph.pdf
+[The Adobe Japanese character set.]
+
+Adobe Systems, Inc., _Adobe-GB1-4 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5079.
+2000.
+http://partners.adobe.com/asn/developer/pdfs/tn/5079.Adobe-GB1-4.pdf
+[The Adobe Chinese GB (simplified) character set.]
+
+Adobe Systems, Inc., _Adobe-CNS1-3 Character Collection for
+CID-Keyed Fonts_, Adobe Developer Support Technical Note #5080.
+2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5080.CNS_CharColl.pdf
+[The Adobe Chinese CNS (traditional) character set.]
+
+Adobe Systems Inc., _Supporting the DCT Filters in PostScript Level
+2_, Adobe Developer Support Technical Note #5116. 1992.
+http://www.adobe.com/supportservice/devrelations/PDFS/TN/5116.PS2_DCT.PDF
+[Description of the DCTDecode filter parameters.]
+
+Adobe Systems Inc., _Open Prepress Interface (OPI) Specification -
+Version 2.0_, Adobe Developer Support Technical Note #5660. 2000.
+http://partners.adobe.com/asn/developer/PDFS/TN/5660.OPI_2.0.pdf
+
+Adobe Systems Inc., CMap files.
+ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/
+[The actual CMap files for the 16-bit CJK encodings.]
+
+Adobe Systems Inc., Unicode glyph lists.
+http://partners.adobe.com/asn/developer/type/unicodegn.html
+http://partners.adobe.com/asn/developer/type/glyphlist.txt
+http://partners.adobe.com/asn/developer/type/corporateuse.txt
+http://partners.adobe.com/asn/developer/type/zapfdingbats.txt
+[Mappings between character names to Unicode.]
+
+Aldus Corp., _OPI: Open Prepress Interface Specification 1.3_. 1993.
+http://partners.adobe.com/asn/developer/PDFS/TN/OPI_13.pdf
+
+Anonymous, RC4 source code.
+ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz
+ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz
+[This is the algorithm used to encrypt PDF files.]
+
+T. Boutell, et al., "PNG (Portable Network Graphics) Specification,
+Version 1.0. RFC 2083.
+[PDF uses the PNG filter algorithms.]
+
+CCITT, "Information Technology - Digital Compression and Coding of
+Continuous-tone Still Images - Requirements and Guidelines", CCITT
+Recommendation T.81.
+http://www.w3.org/Graphics/JPEG/
+[The official JPEG spec.]
+
+A. Chernov, "Registration of a Cyrillic Character Set". RFC 1489.
+[Documentation for the KOI8-R Cyrillic encoding.]
+
+Roman Czyborra, "The ISO 8859 Alphabet Soup".
+http://czyborra.com/charsets/iso8859.html
+[Documentation on the various ISO 859 encodings.]
+
+L. Peter Deutsch, "ZLIB Compressed Data Format Specification version
+3.3". RFC 1950.
+[Information on the general format used in FlateDecode streams.]
+
+L. Peter Deutsch, "DEFLATE Compressed Data Format Specification
+version 1.3". RFC 1951.
+[The definition of the compression algorithm used in FlateDecode
+streams.]
+
+Jim Flowers, "X Logical Font Description Conventions", Version 1.5, X
+Consortium Standard, X Version 11, Release 6.1.
+ftp://ftp.x.org/pub/R6.1/xc/doc/hardcopy/XLFD/xlfd.PS.Z
+[The official specification of X font descriptors, including font
+transformation matrices.]
+
+Foley, van Dam, Feiner, and Hughes, _Computer Graphics: Principles and
+Practice_, 2nd ed. Addison-Wesley, 1990, ISBN 0-201-12110-7.
+[Colorspace conversion functions, Bezier spline math.]
+
+Robert L. Hummel, _Programmer's Technical Reference: Data and Fax
+Communications_. Ziff-Davis Press, 1993, ISBN 1-56276-077-7.
+[CCITT Group 3 and 4 fax decoding.]
+
+ISO/IEC, _Information technology -- Lossy/lossless coding of bi-level
+images_. ISO/IEC 14492, First edition (2001-12-15).
+http://webstore.ansi.org/
+[The official JBIG2 standard. The final draft of this spec is
+available from http://www.jpeg.org/jbighomepage.html.]
+
+ITU, "Standardization of Group 3 facsimile terminals for document
+transmission", ITU-T Recommendation T.4, 1999.
+ITU, "Facsimile coding schemes and coding control functions for Group 4
+facsimile apparatus", ITU-T Recommendation T.6, 1993.
+http://www.itu.int/
+[The official Group 3 and 4 fax standards - used by the CCITTFaxDecode
+stream, as well as the JBIG2Decode stream.]
+
+Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, "Practical
+Fast 1-D DCT Algorithms with 11 Multiplications". IEEE Intl. Conf. on
+Acoustics, Speech & Signal Processing, 1989, 988-991.
+[The fast IDCT algorithm used in the DCTDecode filter.]
+
+Microsoft, _TrueType 1.0 Font Files_, rev. 1.66. 1995.
+http://www.microsoft.com/typography/tt/tt.htm
+[The TrueType font spec (in MS Word format, naturally).]
+
+Thai Industrial Standard, "Standard for Thai Character Codes for
+Computers", TIS-620-2533 (1990).
+http://www.nectec.or.th/it-standards/std620/std620.htm
+[The TIS-620 Thai encoding.]
+
+P. Peterlin, "ISO 8859-2 (Latin 2) Resources".
+http://sizif.mf.uni-lj.si/linux/cee/iso8859-2.html
+[This is a web page with all sorts of useful Latin-2 character set and
+font information.]
+
+Charles Poynton, "Color FAQ".
+http://www.inforamp.net/~poynton/ColorFAQ.html
+[The mapping from the CIE 1931 (XYZ) color space to RGB.]
+
+R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321.
+[MD5 is used in PDF document encryption.]
+
+Unicode Consortium, "Unicode Home Page".
+http://www.unicode.org/
+[Online copy of the Unicode spec.]
+
+W3C Recommendation, "PNG (Portable Network Graphics) Specification
+Version 1.0".
+http://www.w3.org/Graphics/PNG/
+[Defines the PNG image predictor.]
+
+Gregory K. Wallace, "The JPEG Still Picture Compression Standard".
+ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz
+[Good description of the JPEG standard. Also published in CACM, April
+1991, and submitted to IEEE Transactions on Consumer Electronics.]
+
+F. Yergeau, "UTF-8, a transformation format of ISO 10646". RFC 2279.
+[A commonly used Unicode encoding.]
diff --git a/pdftops/Stream-CCITT.h b/pdftops/Stream-CCITT.h
new file mode 100644
index 000000000..c4458fe71
--- /dev/null
+++ b/pdftops/Stream-CCITT.h
@@ -0,0 +1,459 @@
+//========================================================================
+//
+// Stream-CCITT.h
+//
+// Tables for CCITT Fax decoding.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+struct CCITTCode {
+ short bits;
+ short n;
+};
+
+#define ccittEOL -2
+
+//------------------------------------------------------------------------
+// 2D codes
+//------------------------------------------------------------------------
+
+#define twoDimPass 0
+#define twoDimHoriz 1
+#define twoDimVert0 2
+#define twoDimVertR1 3
+#define twoDimVertL1 4
+#define twoDimVertR2 5
+#define twoDimVertL2 6
+#define twoDimVertR3 7
+#define twoDimVertL3 8
+
+// 1-7 bit codes
+static CCITTCode twoDimTab1[128] = {
+ {-1, -1}, {-1, -1}, // 000000x
+ {7, twoDimVertL3}, // 0000010
+ {7, twoDimVertR3}, // 0000011
+ {6, twoDimVertL2}, {6, twoDimVertL2}, // 000010x
+ {6, twoDimVertR2}, {6, twoDimVertR2}, // 000011x
+ {4, twoDimPass}, {4, twoDimPass}, // 0001xxx
+ {4, twoDimPass}, {4, twoDimPass},
+ {4, twoDimPass}, {4, twoDimPass},
+ {4, twoDimPass}, {4, twoDimPass},
+ {3, twoDimHoriz}, {3, twoDimHoriz}, // 001xxxx
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimHoriz}, {3, twoDimHoriz},
+ {3, twoDimVertL1}, {3, twoDimVertL1}, // 010xxxx
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertL1}, {3, twoDimVertL1},
+ {3, twoDimVertR1}, {3, twoDimVertR1}, // 011xxxx
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {3, twoDimVertR1}, {3, twoDimVertR1},
+ {1, twoDimVert0}, {1, twoDimVert0}, // 1xxxxxx
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0},
+ {1, twoDimVert0}, {1, twoDimVert0}
+};
+
+//------------------------------------------------------------------------
+// white run lengths
+//------------------------------------------------------------------------
+
+// 11-12 bit codes (upper 7 bits are 0)
+static CCITTCode whiteTab1[32] = {
+ {-1, -1}, // 00000
+ {12, ccittEOL}, // 00001
+ {-1, -1}, {-1, -1}, // 0001x
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 001xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 010xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 011xx
+ {11, 1792}, {11, 1792}, // 1000x
+ {12, 1984}, // 10010
+ {12, 2048}, // 10011
+ {12, 2112}, // 10100
+ {12, 2176}, // 10101
+ {12, 2240}, // 10110
+ {12, 2304}, // 10111
+ {11, 1856}, {11, 1856}, // 1100x
+ {11, 1920}, {11, 1920}, // 1101x
+ {12, 2368}, // 11100
+ {12, 2432}, // 11101
+ {12, 2496}, // 11110
+ {12, 2560} // 11111
+};
+
+// 1-9 bit codes
+static CCITTCode whiteTab2[512] = {
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000000xx
+ {8, 29}, {8, 29}, // 00000010x
+ {8, 30}, {8, 30}, // 00000011x
+ {8, 45}, {8, 45}, // 00000100x
+ {8, 46}, {8, 46}, // 00000101x
+ {7, 22}, {7, 22}, {7, 22}, {7, 22}, // 0000011xx
+ {7, 23}, {7, 23}, {7, 23}, {7, 23}, // 0000100xx
+ {8, 47}, {8, 47}, // 00001010x
+ {8, 48}, {8, 48}, // 00001011x
+ {6, 13}, {6, 13}, {6, 13}, {6, 13}, // 000011xxx
+ {6, 13}, {6, 13}, {6, 13}, {6, 13},
+ {7, 20}, {7, 20}, {7, 20}, {7, 20}, // 0001000xx
+ {8, 33}, {8, 33}, // 00010010x
+ {8, 34}, {8, 34}, // 00010011x
+ {8, 35}, {8, 35}, // 00010100x
+ {8, 36}, {8, 36}, // 00010101x
+ {8, 37}, {8, 37}, // 00010110x
+ {8, 38}, {8, 38}, // 00010111x
+ {7, 19}, {7, 19}, {7, 19}, {7, 19}, // 0001100xx
+ {8, 31}, {8, 31}, // 00011010x
+ {8, 32}, {8, 32}, // 00011011x
+ {6, 1}, {6, 1}, {6, 1}, {6, 1}, // 000111xxx
+ {6, 1}, {6, 1}, {6, 1}, {6, 1},
+ {6, 12}, {6, 12}, {6, 12}, {6, 12}, // 001000xxx
+ {6, 12}, {6, 12}, {6, 12}, {6, 12},
+ {8, 53}, {8, 53}, // 00100100x
+ {8, 54}, {8, 54}, // 00100101x
+ {7, 26}, {7, 26}, {7, 26}, {7, 26}, // 0010011xx
+ {8, 39}, {8, 39}, // 00101000x
+ {8, 40}, {8, 40}, // 00101001x
+ {8, 41}, {8, 41}, // 00101010x
+ {8, 42}, {8, 42}, // 00101011x
+ {8, 43}, {8, 43}, // 00101100x
+ {8, 44}, {8, 44}, // 00101101x
+ {7, 21}, {7, 21}, {7, 21}, {7, 21}, // 0010111xx
+ {7, 28}, {7, 28}, {7, 28}, {7, 28}, // 0011000xx
+ {8, 61}, {8, 61}, // 00110010x
+ {8, 62}, {8, 62}, // 00110011x
+ {8, 63}, {8, 63}, // 00110100x
+ {8, 0}, {8, 0}, // 00110101x
+ {8, 320}, {8, 320}, // 00110110x
+ {8, 384}, {8, 384}, // 00110111x
+ {5, 10}, {5, 10}, {5, 10}, {5, 10}, // 00111xxxx
+ {5, 10}, {5, 10}, {5, 10}, {5, 10},
+ {5, 10}, {5, 10}, {5, 10}, {5, 10},
+ {5, 10}, {5, 10}, {5, 10}, {5, 10},
+ {5, 11}, {5, 11}, {5, 11}, {5, 11}, // 01000xxxx
+ {5, 11}, {5, 11}, {5, 11}, {5, 11},
+ {5, 11}, {5, 11}, {5, 11}, {5, 11},
+ {5, 11}, {5, 11}, {5, 11}, {5, 11},
+ {7, 27}, {7, 27}, {7, 27}, {7, 27}, // 0100100xx
+ {8, 59}, {8, 59}, // 01001010x
+ {8, 60}, {8, 60}, // 01001011x
+ {9, 1472}, // 010011000
+ {9, 1536}, // 010011001
+ {9, 1600}, // 010011010
+ {9, 1728}, // 010011011
+ {7, 18}, {7, 18}, {7, 18}, {7, 18}, // 0100111xx
+ {7, 24}, {7, 24}, {7, 24}, {7, 24}, // 0101000xx
+ {8, 49}, {8, 49}, // 01010010x
+ {8, 50}, {8, 50}, // 01010011x
+ {8, 51}, {8, 51}, // 01010100x
+ {8, 52}, {8, 52}, // 01010101x
+ {7, 25}, {7, 25}, {7, 25}, {7, 25}, // 0101011xx
+ {8, 55}, {8, 55}, // 01011000x
+ {8, 56}, {8, 56}, // 01011001x
+ {8, 57}, {8, 57}, // 01011010x
+ {8, 58}, {8, 58}, // 01011011x
+ {6, 192}, {6, 192}, {6, 192}, {6, 192}, // 010111xxx
+ {6, 192}, {6, 192}, {6, 192}, {6, 192},
+ {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664}, // 011000xxx
+ {6, 1664}, {6, 1664}, {6, 1664}, {6, 1664},
+ {8, 448}, {8, 448}, // 01100100x
+ {8, 512}, {8, 512}, // 01100101x
+ {9, 704}, // 011001100
+ {9, 768}, // 011001101
+ {8, 640}, {8, 640}, // 01100111x
+ {8, 576}, {8, 576}, // 01101000x
+ {9, 832}, // 011010010
+ {9, 896}, // 011010011
+ {9, 960}, // 011010100
+ {9, 1024}, // 011010101
+ {9, 1088}, // 011010110
+ {9, 1152}, // 011010111
+ {9, 1216}, // 011011000
+ {9, 1280}, // 011011001
+ {9, 1344}, // 011011010
+ {9, 1408}, // 011011011
+ {7, 256}, {7, 256}, {7, 256}, {7, 256}, // 0110111xx
+ {4, 2}, {4, 2}, {4, 2}, {4, 2}, // 0111xxxxx
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 2}, {4, 2}, {4, 2}, {4, 2},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3}, // 1000xxxxx
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {4, 3}, {4, 3}, {4, 3}, {4, 3},
+ {5, 128}, {5, 128}, {5, 128}, {5, 128}, // 10010xxxx
+ {5, 128}, {5, 128}, {5, 128}, {5, 128},
+ {5, 128}, {5, 128}, {5, 128}, {5, 128},
+ {5, 128}, {5, 128}, {5, 128}, {5, 128},
+ {5, 8}, {5, 8}, {5, 8}, {5, 8}, // 10011xxxx
+ {5, 8}, {5, 8}, {5, 8}, {5, 8},
+ {5, 8}, {5, 8}, {5, 8}, {5, 8},
+ {5, 8}, {5, 8}, {5, 8}, {5, 8},
+ {5, 9}, {5, 9}, {5, 9}, {5, 9}, // 10100xxxx
+ {5, 9}, {5, 9}, {5, 9}, {5, 9},
+ {5, 9}, {5, 9}, {5, 9}, {5, 9},
+ {5, 9}, {5, 9}, {5, 9}, {5, 9},
+ {6, 16}, {6, 16}, {6, 16}, {6, 16}, // 101010xxx
+ {6, 16}, {6, 16}, {6, 16}, {6, 16},
+ {6, 17}, {6, 17}, {6, 17}, {6, 17}, // 101011xxx
+ {6, 17}, {6, 17}, {6, 17}, {6, 17},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4}, // 1011xxxxx
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {4, 4}, {4, 4}, {4, 4},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 1100xxxxx
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {4, 5}, {4, 5}, {4, 5}, {4, 5},
+ {6, 14}, {6, 14}, {6, 14}, {6, 14}, // 110100xxx
+ {6, 14}, {6, 14}, {6, 14}, {6, 14},
+ {6, 15}, {6, 15}, {6, 15}, {6, 15}, // 110101xxx
+ {6, 15}, {6, 15}, {6, 15}, {6, 15},
+ {5, 64}, {5, 64}, {5, 64}, {5, 64}, // 11011xxxx
+ {5, 64}, {5, 64}, {5, 64}, {5, 64},
+ {5, 64}, {5, 64}, {5, 64}, {5, 64},
+ {5, 64}, {5, 64}, {5, 64}, {5, 64},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 1110xxxxx
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7}, // 1111xxxxx
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7},
+ {4, 7}, {4, 7}, {4, 7}, {4, 7}
+};
+
+//------------------------------------------------------------------------
+// black run lengths
+//------------------------------------------------------------------------
+
+// 10-13 bit codes (upper 6 bits are 0)
+static CCITTCode blackTab1[128] = {
+ {-1, -1}, {-1, -1}, // 000000000000x
+ {12, ccittEOL}, {12, ccittEOL}, // 000000000001x
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000001xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000010xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000011xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000100xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000101xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000110xx
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 00000000111xx
+ {11, 1792}, {11, 1792}, {11, 1792}, {11, 1792}, // 00000001000xx
+ {12, 1984}, {12, 1984}, // 000000010010x
+ {12, 2048}, {12, 2048}, // 000000010011x
+ {12, 2112}, {12, 2112}, // 000000010100x
+ {12, 2176}, {12, 2176}, // 000000010101x
+ {12, 2240}, {12, 2240}, // 000000010110x
+ {12, 2304}, {12, 2304}, // 000000010111x
+ {11, 1856}, {11, 1856}, {11, 1856}, {11, 1856}, // 00000001100xx
+ {11, 1920}, {11, 1920}, {11, 1920}, {11, 1920}, // 00000001101xx
+ {12, 2368}, {12, 2368}, // 000000011100x
+ {12, 2432}, {12, 2432}, // 000000011101x
+ {12, 2496}, {12, 2496}, // 000000011110x
+ {12, 2560}, {12, 2560}, // 000000011111x
+ {10, 18}, {10, 18}, {10, 18}, {10, 18}, // 0000001000xxx
+ {10, 18}, {10, 18}, {10, 18}, {10, 18},
+ {12, 52}, {12, 52}, // 000000100100x
+ {13, 640}, // 0000001001010
+ {13, 704}, // 0000001001011
+ {13, 768}, // 0000001001100
+ {13, 832}, // 0000001001101
+ {12, 55}, {12, 55}, // 000000100111x
+ {12, 56}, {12, 56}, // 000000101000x
+ {13, 1280}, // 0000001010010
+ {13, 1344}, // 0000001010011
+ {13, 1408}, // 0000001010100
+ {13, 1472}, // 0000001010101
+ {12, 59}, {12, 59}, // 000000101011x
+ {12, 60}, {12, 60}, // 000000101100x
+ {13, 1536}, // 0000001011010
+ {13, 1600}, // 0000001011011
+ {11, 24}, {11, 24}, {11, 24}, {11, 24}, // 00000010111xx
+ {11, 25}, {11, 25}, {11, 25}, {11, 25}, // 00000011000xx
+ {13, 1664}, // 0000001100100
+ {13, 1728}, // 0000001100101
+ {12, 320}, {12, 320}, // 000000110011x
+ {12, 384}, {12, 384}, // 000000110100x
+ {12, 448}, {12, 448}, // 000000110101x
+ {13, 512}, // 0000001101100
+ {13, 576}, // 0000001101101
+ {12, 53}, {12, 53}, // 000000110111x
+ {12, 54}, {12, 54}, // 000000111000x
+ {13, 896}, // 0000001110010
+ {13, 960}, // 0000001110011
+ {13, 1024}, // 0000001110100
+ {13, 1088}, // 0000001110101
+ {13, 1152}, // 0000001110110
+ {13, 1216}, // 0000001110111
+ {10, 64}, {10, 64}, {10, 64}, {10, 64}, // 0000001111xxx
+ {10, 64}, {10, 64}, {10, 64}, {10, 64}
+};
+
+// 7-12 bit codes (upper 4 bits are 0)
+static CCITTCode blackTab2[192] = {
+ {8, 13}, {8, 13}, {8, 13}, {8, 13}, // 00000100xxxx
+ {8, 13}, {8, 13}, {8, 13}, {8, 13},
+ {8, 13}, {8, 13}, {8, 13}, {8, 13},
+ {8, 13}, {8, 13}, {8, 13}, {8, 13},
+ {11, 23}, {11, 23}, // 00000101000x
+ {12, 50}, // 000001010010
+ {12, 51}, // 000001010011
+ {12, 44}, // 000001010100
+ {12, 45}, // 000001010101
+ {12, 46}, // 000001010110
+ {12, 47}, // 000001010111
+ {12, 57}, // 000001011000
+ {12, 58}, // 000001011001
+ {12, 61}, // 000001011010
+ {12, 256}, // 000001011011
+ {10, 16}, {10, 16}, {10, 16}, {10, 16}, // 0000010111xx
+ {10, 17}, {10, 17}, {10, 17}, {10, 17}, // 0000011000xx
+ {12, 48}, // 000001100100
+ {12, 49}, // 000001100101
+ {12, 62}, // 000001100110
+ {12, 63}, // 000001100111
+ {12, 30}, // 000001101000
+ {12, 31}, // 000001101001
+ {12, 32}, // 000001101010
+ {12, 33}, // 000001101011
+ {12, 40}, // 000001101100
+ {12, 41}, // 000001101101
+ {11, 22}, {11, 22}, // 00000110111x
+ {8, 14}, {8, 14}, {8, 14}, {8, 14}, // 00000111xxxx
+ {8, 14}, {8, 14}, {8, 14}, {8, 14},
+ {8, 14}, {8, 14}, {8, 14}, {8, 14},
+ {8, 14}, {8, 14}, {8, 14}, {8, 14},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10}, // 0000100xxxxx
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 10}, {7, 10}, {7, 10}, {7, 10},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11}, // 0000101xxxxx
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {7, 11}, {7, 11}, {7, 11}, {7, 11},
+ {9, 15}, {9, 15}, {9, 15}, {9, 15}, // 000011000xxx
+ {9, 15}, {9, 15}, {9, 15}, {9, 15},
+ {12, 128}, // 000011001000
+ {12, 192}, // 000011001001
+ {12, 26}, // 000011001010
+ {12, 27}, // 000011001011
+ {12, 28}, // 000011001100
+ {12, 29}, // 000011001101
+ {11, 19}, {11, 19}, // 00001100111x
+ {11, 20}, {11, 20}, // 00001101000x
+ {12, 34}, // 000011010010
+ {12, 35}, // 000011010011
+ {12, 36}, // 000011010100
+ {12, 37}, // 000011010101
+ {12, 38}, // 000011010110
+ {12, 39}, // 000011010111
+ {11, 21}, {11, 21}, // 00001101100x
+ {12, 42}, // 000011011010
+ {12, 43}, // 000011011011
+ {10, 0}, {10, 0}, {10, 0}, {10, 0}, // 0000110111xx
+ {7, 12}, {7, 12}, {7, 12}, {7, 12}, // 0000111xxxxx
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12},
+ {7, 12}, {7, 12}, {7, 12}, {7, 12}
+};
+
+// 2-6 bit codes
+static CCITTCode blackTab3[64] = {
+ {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, // 0000xx
+ {6, 9}, // 000100
+ {6, 8}, // 000101
+ {5, 7}, {5, 7}, // 00011x
+ {4, 6}, {4, 6}, {4, 6}, {4, 6}, // 0010xx
+ {4, 5}, {4, 5}, {4, 5}, {4, 5}, // 0011xx
+ {3, 1}, {3, 1}, {3, 1}, {3, 1}, // 010xxx
+ {3, 1}, {3, 1}, {3, 1}, {3, 1},
+ {3, 4}, {3, 4}, {3, 4}, {3, 4}, // 011xxx
+ {3, 4}, {3, 4}, {3, 4}, {3, 4},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, // 10xxxx
+ {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}, // 11xxxx
+ {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2},
+ {2, 2}, {2, 2}, {2, 2}, {2, 2}
+};
diff --git a/pdftops/Stream.cxx b/pdftops/Stream.cxx
new file mode 100644
index 000000000..d67a874b0
--- /dev/null
+++ b/pdftops/Stream.cxx
@@ -0,0 +1,3969 @@
+//========================================================================
+//
+// Stream.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+#include "gmem.h"
+#include "gfile.h"
+#include "config.h"
+#include "Error.h"
+#include "Object.h"
+#ifndef NO_DECRYPTION
+#include "Decrypt.h"
+#endif
+#include "Stream.h"
+#include "JBIG2Stream.h"
+#include "Stream-CCITT.h"
+
+#ifdef __DJGPP__
+static GBool setDJSYSFLAGS = gFalse;
+#endif
+
+#ifdef VMS
+#ifdef __GNUC__
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// Stream (base class)
+//------------------------------------------------------------------------
+
+Stream::Stream() {
+ ref = 1;
+}
+
+Stream::~Stream() {
+}
+
+void Stream::close() {
+}
+
+int Stream::getRawChar() {
+ error(-1, "Internal: called getRawChar() on non-predictor stream");
+ return EOF;
+}
+
+char *Stream::getLine(char *buf, int size) {
+ int i;
+ int c;
+
+ if (lookChar() == EOF)
+ return NULL;
+ for (i = 0; i < size - 1; ++i) {
+ c = getChar();
+ if (c == EOF || c == '\n')
+ break;
+ if (c == '\r') {
+ if ((c = lookChar()) == '\n')
+ getChar();
+ break;
+ }
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+ return buf;
+}
+
+GString *Stream::getPSFilter(int psLevel, const char *indent) {
+ return new GString();
+}
+
+Stream *Stream::addFilters(Object *dict) {
+ Object obj, obj2;
+ Object params, params2;
+ Stream *str;
+ int i;
+
+ str = this;
+ dict->dictLookup("Filter", &obj);
+ if (obj.isNull()) {
+ obj.free();
+ dict->dictLookup("F", &obj);
+ }
+ dict->dictLookup("DecodeParms", &params);
+ if (params.isNull()) {
+ params.free();
+ dict->dictLookup("DP", &params);
+ }
+ if (obj.isName()) {
+ str = makeFilter(obj.getName(), str, &params);
+ } else if (obj.isArray()) {
+ for (i = 0; i < obj.arrayGetLength(); ++i) {
+ obj.arrayGet(i, &obj2);
+ if (params.isArray())
+ params.arrayGet(i, &params2);
+ else
+ params2.initNull();
+ if (obj2.isName()) {
+ str = makeFilter(obj2.getName(), str, &params2);
+ } else {
+ error(getPos(), "Bad filter name");
+ str = new EOFStream(str);
+ }
+ obj2.free();
+ params2.free();
+ }
+ } else if (!obj.isNull()) {
+ error(getPos(), "Bad 'Filter' attribute in stream");
+ }
+ obj.free();
+ params.free();
+
+ return str;
+}
+
+Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
+ int pred; // parameters
+ int colors;
+ int bits;
+ int early;
+ int encoding;
+ GBool endOfLine, byteAlign, endOfBlock, black;
+ int columns, rows;
+ Object globals, obj;
+
+ if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
+ str = new ASCIIHexStream(str);
+ } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
+ str = new ASCII85Stream(str);
+ } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
+ pred = 1;
+ columns = 1;
+ colors = 1;
+ bits = 8;
+ early = 1;
+ if (params->isDict()) {
+ params->dictLookup("Predictor", &obj);
+ if (obj.isInt())
+ pred = obj.getInt();
+ obj.free();
+ params->dictLookup("Columns", &obj);
+ if (obj.isInt())
+ columns = obj.getInt();
+ obj.free();
+ params->dictLookup("Colors", &obj);
+ if (obj.isInt())
+ colors = obj.getInt();
+ obj.free();
+ params->dictLookup("BitsPerComponent", &obj);
+ if (obj.isInt())
+ bits = obj.getInt();
+ obj.free();
+ params->dictLookup("EarlyChange", &obj);
+ if (obj.isInt())
+ early = obj.getInt();
+ obj.free();
+ }
+ str = new LZWStream(str, pred, columns, colors, bits, early);
+ } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
+ str = new RunLengthStream(str);
+ } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
+ encoding = 0;
+ endOfLine = gFalse;
+ byteAlign = gFalse;
+ columns = 1728;
+ rows = 0;
+ endOfBlock = gTrue;
+ black = gFalse;
+ if (params->isDict()) {
+ params->dictLookup("K", &obj);
+ if (obj.isInt()) {
+ encoding = obj.getInt();
+ }
+ obj.free();
+ params->dictLookup("EndOfLine", &obj);
+ if (obj.isBool()) {
+ endOfLine = obj.getBool();
+ }
+ obj.free();
+ params->dictLookup("EncodedByteAlign", &obj);
+ if (obj.isBool()) {
+ byteAlign = obj.getBool();
+ }
+ obj.free();
+ params->dictLookup("Columns", &obj);
+ if (obj.isInt()) {
+ columns = obj.getInt();
+ }
+ obj.free();
+ params->dictLookup("Rows", &obj);
+ if (obj.isInt()) {
+ rows = obj.getInt();
+ }
+ obj.free();
+ params->dictLookup("EndOfBlock", &obj);
+ if (obj.isBool()) {
+ endOfBlock = obj.getBool();
+ }
+ obj.free();
+ params->dictLookup("BlackIs1", &obj);
+ if (obj.isBool()) {
+ black = obj.getBool();
+ }
+ obj.free();
+ }
+ str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
+ columns, rows, endOfBlock, black);
+ } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
+ str = new DCTStream(str);
+ } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
+ pred = 1;
+ columns = 1;
+ colors = 1;
+ bits = 8;
+ if (params->isDict()) {
+ params->dictLookup("Predictor", &obj);
+ if (obj.isInt())
+ pred = obj.getInt();
+ obj.free();
+ params->dictLookup("Columns", &obj);
+ if (obj.isInt())
+ columns = obj.getInt();
+ obj.free();
+ params->dictLookup("Colors", &obj);
+ if (obj.isInt())
+ colors = obj.getInt();
+ obj.free();
+ params->dictLookup("BitsPerComponent", &obj);
+ if (obj.isInt())
+ bits = obj.getInt();
+ obj.free();
+ }
+ str = new FlateStream(str, pred, columns, colors, bits);
+ } else if (!strcmp(name, "JBIG2Decode")) {
+ if (params->isDict()) {
+ params->dictLookup("JBIG2Globals", &globals);
+ }
+ str = new JBIG2Stream(str, &globals);
+ globals.free();
+ } else {
+ error(getPos(), "Unknown filter '%s'", name);
+ str = new EOFStream(str);
+ }
+ return str;
+}
+
+//------------------------------------------------------------------------
+// BaseStream
+//------------------------------------------------------------------------
+
+BaseStream::BaseStream(Object *dictA) {
+ dict = *dictA;
+#ifndef NO_DECRYPTION
+ decrypt = NULL;
+#endif
+}
+
+BaseStream::~BaseStream() {
+ dict.free();
+#ifndef NO_DECRYPTION
+ if (decrypt)
+ delete decrypt;
+#endif
+}
+
+#ifndef NO_DECRYPTION
+void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen) {
+ decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
+}
+#endif
+
+//------------------------------------------------------------------------
+// FilterStream
+//------------------------------------------------------------------------
+
+FilterStream::FilterStream(Stream *strA) {
+ str = strA;
+}
+
+FilterStream::~FilterStream() {
+}
+
+void FilterStream::close() {
+ str->close();
+}
+
+void FilterStream::setPos(Guint pos, int dir) {
+ error(-1, "Internal: called setPos() on FilterStream");
+}
+
+//------------------------------------------------------------------------
+// ImageStream
+//------------------------------------------------------------------------
+
+ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
+ int imgLineSize;
+
+ str = strA;
+ width = widthA;
+ nComps = nCompsA;
+ nBits = nBitsA;
+
+ nVals = width * nComps;
+ if (nBits == 1) {
+ imgLineSize = (nVals + 7) & ~7;
+ } else {
+ imgLineSize = nVals;
+ }
+ imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
+ imgIdx = nVals;
+}
+
+ImageStream::~ImageStream() {
+ gfree(imgLine);
+}
+
+void ImageStream::reset() {
+ str->reset();
+}
+
+GBool ImageStream::getPixel(Guchar *pix) {
+ int i;
+
+ if (imgIdx >= nVals) {
+ getLine();
+ imgIdx = 0;
+ }
+ for (i = 0; i < nComps; ++i) {
+ pix[i] = imgLine[imgIdx++];
+ }
+ return gTrue;
+}
+
+Guchar *ImageStream::getLine() {
+ Gulong buf, bitMask;
+ int bits;
+ int c;
+ int i;
+
+ if (nBits == 1) {
+ for (i = 0; i < nVals; i += 8) {
+ c = str->getChar();
+ imgLine[i+0] = (Guchar)((c >> 7) & 1);
+ imgLine[i+1] = (Guchar)((c >> 6) & 1);
+ imgLine[i+2] = (Guchar)((c >> 5) & 1);
+ imgLine[i+3] = (Guchar)((c >> 4) & 1);
+ imgLine[i+4] = (Guchar)((c >> 3) & 1);
+ imgLine[i+5] = (Guchar)((c >> 2) & 1);
+ imgLine[i+6] = (Guchar)((c >> 1) & 1);
+ imgLine[i+7] = (Guchar)(c & 1);
+ }
+ } else if (nBits == 8) {
+ for (i = 0; i < nVals; ++i) {
+ imgLine[i] = str->getChar();
+ }
+ } else {
+ bitMask = (1 << nBits) - 1;
+ buf = 0;
+ bits = 0;
+ for (i = 0; i < nVals; ++i) {
+ if (bits < nBits) {
+ buf = (buf << 8) | (str->getChar() & 0xff);
+ bits += 8;
+ }
+ imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
+ bits -= nBits;
+ }
+ }
+ return imgLine;
+}
+
+void ImageStream::skipLine() {
+ int n, i;
+
+ n = (nVals * nBits + 7) >> 3;
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+}
+
+//------------------------------------------------------------------------
+// StreamPredictor
+//------------------------------------------------------------------------
+
+StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
+ int widthA, int nCompsA, int nBitsA) {
+ str = strA;
+ predictor = predictorA;
+ width = widthA;
+ nComps = nCompsA;
+ nBits = nBitsA;
+
+ nVals = width * nComps;
+ pixBytes = (nComps * nBits + 7) >> 3;
+ rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
+ predLine = (Guchar *)gmalloc(rowBytes);
+ memset(predLine, 0, rowBytes);
+ predIdx = rowBytes;
+}
+
+StreamPredictor::~StreamPredictor() {
+ gfree(predLine);
+}
+
+int StreamPredictor::lookChar() {
+ if (predIdx >= rowBytes) {
+ if (!getNextLine()) {
+ return EOF;
+ }
+ }
+ return predLine[predIdx];
+}
+
+int StreamPredictor::getChar() {
+ if (predIdx >= rowBytes) {
+ if (!getNextLine()) {
+ return EOF;
+ }
+ }
+ return predLine[predIdx++];
+}
+
+GBool StreamPredictor::getNextLine() {
+ int curPred;
+ Guchar upLeftBuf[4];
+ int left, up, upLeft, p, pa, pb, pc;
+ int c;
+ Gulong inBuf, outBuf, bitMask;
+ int inBits, outBits;
+ int i, j, k;
+
+ // get PNG optimum predictor number
+ if (predictor == 15) {
+ if ((curPred = str->getRawChar()) == EOF) {
+ return gFalse;
+ }
+ curPred += 10;
+ } else {
+ curPred = predictor;
+ }
+
+ // read the raw line, apply PNG (byte) predictor
+ upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
+ for (i = pixBytes; i < rowBytes; ++i) {
+ upLeftBuf[3] = upLeftBuf[2];
+ upLeftBuf[2] = upLeftBuf[1];
+ upLeftBuf[1] = upLeftBuf[0];
+ upLeftBuf[0] = predLine[i];
+ if ((c = str->getRawChar()) == EOF) {
+ return gFalse;
+ }
+ switch (curPred) {
+ case 11: // PNG sub
+ predLine[i] = predLine[i - pixBytes] + (Guchar)c;
+ break;
+ case 12: // PNG up
+ predLine[i] = predLine[i] + (Guchar)c;
+ break;
+ case 13: // PNG average
+ predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
+ (Guchar)c;
+ break;
+ case 14: // PNG Paeth
+ left = predLine[i - pixBytes];
+ up = predLine[i];
+ upLeft = upLeftBuf[pixBytes];
+ p = left + up - upLeft;
+ if ((pa = p - left) < 0)
+ pa = -pa;
+ if ((pb = p - up) < 0)
+ pb = -pb;
+ if ((pc = p - upLeft) < 0)
+ pc = -pc;
+ if (pa <= pb && pa <= pc)
+ predLine[i] = left + (Guchar)c;
+ else if (pb <= pc)
+ predLine[i] = up + (Guchar)c;
+ else
+ predLine[i] = upLeft + (Guchar)c;
+ break;
+ case 10: // PNG none
+ default: // no predictor or TIFF predictor
+ predLine[i] = (Guchar)c;
+ break;
+ }
+ }
+
+ // apply TIFF (component) predictor
+ if (predictor == 2) {
+ if (nBits == 1) {
+ inBuf = predLine[pixBytes - 1];
+ for (i = pixBytes; i < rowBytes; i += 8) {
+ // 1-bit add is just xor
+ inBuf = (inBuf << 8) | predLine[i];
+ predLine[i] ^= inBuf >> nComps;
+ }
+ } else if (nBits == 8) {
+ for (i = pixBytes; i < rowBytes; ++i) {
+ predLine[i] += predLine[i - nComps];
+ }
+ } else {
+ upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
+ bitMask = (1 << nBits) - 1;
+ inBuf = outBuf = 0;
+ inBits = outBits = 0;
+ j = k = pixBytes;
+ for (i = 0; i < nVals; ++i) {
+ if (inBits < nBits) {
+ inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
+ inBits += 8;
+ }
+ upLeftBuf[3] = upLeftBuf[2];
+ upLeftBuf[2] = upLeftBuf[1];
+ upLeftBuf[1] = upLeftBuf[0];
+ upLeftBuf[0] = (upLeftBuf[nComps] +
+ (inBuf >> (inBits - nBits))) & bitMask;
+ outBuf = (outBuf << nBits) | upLeftBuf[0];
+ inBits -= nBits;
+ outBits += nBits;
+ if (outBits > 8) {
+ predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
+ }
+ }
+ if (outBits > 0) {
+ predLine[k++] = (Guchar)(outBuf << (8 - outBits));
+ }
+ }
+ }
+
+ // reset to start of line
+ predIdx = pixBytes;
+
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+// FileStream
+//------------------------------------------------------------------------
+
+FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA):
+ BaseStream(dictA) {
+ f = fA;
+ start = startA;
+ limited = limitedA;
+ length = lengthA;
+ bufPtr = bufEnd = buf;
+ bufPos = start;
+ savePos = 0;
+ saved = gFalse;
+}
+
+FileStream::~FileStream() {
+ close();
+}
+
+Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA) {
+ return new FileStream(f, startA, limitedA, lengthA, dictA);
+}
+
+void FileStream::reset() {
+#if HAVE_FSEEKO
+ savePos = (Guint)ftello(f);
+ fseeko(f, start, SEEK_SET);
+#elif HAVE_FSEEK64
+ savePos = (Guint)ftell64(f);
+ fseek64(f, start, SEEK_SET);
+#else
+ savePos = (Guint)ftell(f);
+ fseek(f, start, SEEK_SET);
+#endif
+ saved = gTrue;
+ bufPtr = bufEnd = buf;
+ bufPos = start;
+#ifndef NO_DECRYPTION
+ if (decrypt)
+ decrypt->reset();
+#endif
+}
+
+void FileStream::close() {
+ if (saved) {
+#if HAVE_FSEEKO
+ fseeko(f, savePos, SEEK_SET);
+#elif HAVE_FSEEK64
+ fseek64(f, savePos, SEEK_SET);
+#else
+ fseek(f, savePos, SEEK_SET);
+#endif
+ saved = gFalse;
+ }
+}
+
+GBool FileStream::fillBuf() {
+ int n;
+#ifndef NO_DECRYPTION
+ char *p;
+#endif
+
+ bufPos += bufEnd - buf;
+ bufPtr = bufEnd = buf;
+ if (limited && bufPos >= start + length) {
+ return gFalse;
+ }
+ if (limited && bufPos + fileStreamBufSize > start + length) {
+ n = start + length - bufPos;
+ } else {
+ n = fileStreamBufSize;
+ }
+ n = fread(buf, 1, n, f);
+ bufEnd = buf + n;
+ if (bufPtr >= bufEnd) {
+ return gFalse;
+ }
+#ifndef NO_DECRYPTION
+ if (decrypt) {
+ for (p = buf; p < bufEnd; ++p) {
+ *p = (char)decrypt->decryptByte((Guchar)*p);
+ }
+ }
+#endif
+ return gTrue;
+}
+
+void FileStream::setPos(Guint pos, int dir) {
+ Guint size;
+
+ if (dir >= 0) {
+#if HAVE_FSEEKO
+ fseeko(f, pos, SEEK_SET);
+#elif HAVE_FSEEK64
+ fseek64(f, pos, SEEK_SET);
+#else
+ fseek(f, pos, SEEK_SET);
+#endif
+ bufPos = pos;
+ } else {
+#if HAVE_FSEEKO
+ fseeko(f, 0, SEEK_END);
+ size = (Guint)ftello(f);
+#elif HAVE_FSEEK64
+ fseek64(f, 0, SEEK_END);
+ size = (Guint)ftell64(f);
+#else
+ fseek(f, 0, SEEK_END);
+ size = (Guint)ftell(f);
+#endif
+ if (pos > size)
+ pos = (Guint)size;
+#ifdef __CYGWIN32__
+ //~ work around a bug in cygwin's implementation of fseek
+ rewind(f);
+#endif
+#if HAVE_FSEEKO
+ fseeko(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftello(f);
+#elif HAVE_FSEEK64
+ fseek64(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftell64(f);
+#else
+ fseek(f, -(int)pos, SEEK_END);
+ bufPos = (Guint)ftell(f);
+#endif
+ }
+ bufPtr = bufEnd = buf;
+}
+
+void FileStream::moveStart(int delta) {
+ start += delta;
+ bufPtr = bufEnd = buf;
+ bufPos = start;
+}
+
+//------------------------------------------------------------------------
+// MemStream
+//------------------------------------------------------------------------
+
+MemStream::MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA):
+ BaseStream(dictA) {
+ buf = bufA;
+ start = startA;
+ length = lengthA;
+ bufEnd = buf + start + length;
+ bufPtr = buf + start;
+ needFree = gFalse;
+}
+
+MemStream::~MemStream() {
+ if (needFree) {
+ gfree(buf);
+ }
+}
+
+Stream *MemStream::makeSubStream(Guint startA, GBool limited,
+ Guint lengthA, Object *dictA) {
+ MemStream *subStr;
+ Guint newLength;
+
+ if (!limited || startA + lengthA > start + length) {
+ newLength = start + length - startA;
+ } else {
+ newLength = lengthA;
+ }
+ subStr = new MemStream(buf, startA, newLength, dictA);
+ return subStr;
+}
+
+void MemStream::reset() {
+ bufPtr = buf + start;
+#ifndef NO_DECRYPTION
+ if (decrypt) {
+ decrypt->reset();
+ }
+#endif
+}
+
+void MemStream::close() {
+}
+
+void MemStream::setPos(Guint pos, int dir) {
+ Guint i;
+
+ if (dir >= 0) {
+ i = pos;
+ } else {
+ i = start + length - pos;
+ }
+ if (i < start) {
+ i = start;
+ } else if (i > start + length) {
+ i = start + length;
+ }
+ bufPtr = buf + i;
+}
+
+void MemStream::moveStart(int delta) {
+ start += delta;
+ bufPtr = buf + start;
+}
+
+#ifndef NO_DECRYPTION
+void MemStream::doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen) {
+ char *newBuf;
+ char *p, *q;
+
+ this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
+ if (decrypt) {
+ newBuf = (char *)gmalloc(length);
+ for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) {
+ *q = (char)decrypt->decryptByte((Guchar)*p);
+ }
+ bufEnd = newBuf + length;
+ bufPtr = newBuf + (bufPtr - (buf + start));
+ start = 0;
+ buf = newBuf;
+ needFree = gTrue;
+ }
+}
+#endif
+
+//------------------------------------------------------------------------
+// EmbedStream
+//------------------------------------------------------------------------
+
+EmbedStream::EmbedStream(Stream *strA, Object *dictA):
+ BaseStream(dictA) {
+ str = strA;
+}
+
+EmbedStream::~EmbedStream() {
+}
+
+Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dictA) {
+ error(-1, "Internal: called makeSubStream() on EmbedStream");
+ return NULL;
+}
+
+void EmbedStream::setPos(Guint pos, int dir) {
+ error(-1, "Internal: called setPos() on EmbedStream");
+}
+
+Guint EmbedStream::getStart() {
+ error(-1, "Internal: called getStart() on EmbedStream");
+ return 0;
+}
+
+void EmbedStream::moveStart(int delta) {
+ error(-1, "Internal: called moveStart() on EmbedStream");
+}
+
+//------------------------------------------------------------------------
+// ASCIIHexStream
+//------------------------------------------------------------------------
+
+ASCIIHexStream::ASCIIHexStream(Stream *strA):
+ FilterStream(strA) {
+ buf = EOF;
+ eof = gFalse;
+}
+
+ASCIIHexStream::~ASCIIHexStream() {
+ delete str;
+}
+
+void ASCIIHexStream::reset() {
+ str->reset();
+ buf = EOF;
+ eof = gFalse;
+}
+
+int ASCIIHexStream::lookChar() {
+ int c1, c2, x;
+
+ if (buf != EOF)
+ return buf;
+ if (eof) {
+ buf = EOF;
+ return EOF;
+ }
+ do {
+ c1 = str->getChar();
+ } while (isspace(c1));
+ if (c1 == '>') {
+ eof = gTrue;
+ buf = EOF;
+ return buf;
+ }
+ do {
+ c2 = str->getChar();
+ } while (isspace(c2));
+ if (c2 == '>') {
+ eof = gTrue;
+ c2 = '0';
+ }
+ if (c1 >= '0' && c1 <= '9') {
+ x = (c1 - '0') << 4;
+ } else if (c1 >= 'A' && c1 <= 'F') {
+ x = (c1 - 'A' + 10) << 4;
+ } else if (c1 >= 'a' && c1 <= 'f') {
+ x = (c1 - 'a' + 10) << 4;
+ } else if (c1 == EOF) {
+ eof = gTrue;
+ x = 0;
+ } else {
+ error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
+ x = 0;
+ }
+ if (c2 >= '0' && c2 <= '9') {
+ x += c2 - '0';
+ } else if (c2 >= 'A' && c2 <= 'F') {
+ x += c2 - 'A' + 10;
+ } else if (c2 >= 'a' && c2 <= 'f') {
+ x += c2 - 'a' + 10;
+ } else if (c2 == EOF) {
+ eof = gTrue;
+ x = 0;
+ } else {
+ error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
+ }
+ buf = x & 0xff;
+ return buf;
+}
+
+GString *ASCIIHexStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("/ASCIIHexDecode filter\n");
+ return s;
+}
+
+GBool ASCIIHexStream::isBinary(GBool last) {
+ return str->isBinary(gFalse);
+}
+
+//------------------------------------------------------------------------
+// ASCII85Stream
+//------------------------------------------------------------------------
+
+ASCII85Stream::ASCII85Stream(Stream *strA):
+ FilterStream(strA) {
+ index = n = 0;
+ eof = gFalse;
+}
+
+ASCII85Stream::~ASCII85Stream() {
+ delete str;
+}
+
+void ASCII85Stream::reset() {
+ str->reset();
+ index = n = 0;
+ eof = gFalse;
+}
+
+int ASCII85Stream::lookChar() {
+ int k;
+ Gulong t;
+
+ if (index >= n) {
+ if (eof)
+ return EOF;
+ index = 0;
+ do {
+ c[0] = str->getChar();
+ } while (c[0] == '\n' || c[0] == '\r');
+ if (c[0] == '~' || c[0] == EOF) {
+ eof = gTrue;
+ n = 0;
+ return EOF;
+ } else if (c[0] == 'z') {
+ b[0] = b[1] = b[2] = b[3] = 0;
+ n = 4;
+ } else {
+ for (k = 1; k < 5; ++k) {
+ do {
+ c[k] = str->getChar();
+ } while (c[k] == '\n' || c[k] == '\r');
+ if (c[k] == '~' || c[k] == EOF)
+ break;
+ }
+ n = k - 1;
+ if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
+ for (++k; k < 5; ++k)
+ c[k] = 0x21 + 84;
+ eof = gTrue;
+ }
+ t = 0;
+ for (k = 0; k < 5; ++k)
+ t = t * 85 + (c[k] - 0x21);
+ for (k = 3; k >= 0; --k) {
+ b[k] = (int)(t & 0xff);
+ t >>= 8;
+ }
+ }
+ }
+ return b[index];
+}
+
+GString *ASCII85Stream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("/ASCII85Decode filter\n");
+ return s;
+}
+
+GBool ASCII85Stream::isBinary(GBool last) {
+ return str->isBinary(gFalse);
+}
+
+//------------------------------------------------------------------------
+// LZWStream
+//------------------------------------------------------------------------
+
+LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
+ int bits, int earlyA):
+ FilterStream(strA) {
+ if (predictor != 1) {
+ pred = new StreamPredictor(this, predictor, columns, colors, bits);
+ } else {
+ pred = NULL;
+ }
+ early = earlyA;
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
+}
+
+LZWStream::~LZWStream() {
+ if (pred) {
+ delete pred;
+ }
+ delete str;
+}
+
+int LZWStream::getChar() {
+ if (pred) {
+ return pred->getChar();
+ }
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
+}
+
+int LZWStream::lookChar() {
+ if (pred) {
+ return pred->lookChar();
+ }
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex];
+}
+
+int LZWStream::getRawChar() {
+ if (eof) {
+ return EOF;
+ }
+ if (seqIndex >= seqLength) {
+ if (!processNextCode()) {
+ return EOF;
+ }
+ }
+ return seqBuf[seqIndex++];
+}
+
+void LZWStream::reset() {
+ str->reset();
+ eof = gFalse;
+ inputBits = 0;
+ clearTable();
+}
+
+GBool LZWStream::processNextCode() {
+ int code;
+ int nextLength;
+ int i, j;
+
+ // check for EOF
+ if (eof) {
+ return gFalse;
+ }
+
+ // check for eod and clear-table codes
+ start:
+ code = getCode();
+ if (code == EOF || code == 257) {
+ eof = gTrue;
+ return gFalse;
+ }
+ if (code == 256) {
+ clearTable();
+ goto start;
+ }
+ if (nextCode >= 4097) {
+ error(getPos(), "Bad LZW stream - expected clear-table code");
+ clearTable();
+ }
+
+ // process the next code
+ nextLength = seqLength + 1;
+ if (code < 256) {
+ seqBuf[0] = code;
+ seqLength = 1;
+ } else if (code < nextCode) {
+ seqLength = table[code].length;
+ for (i = seqLength - 1, j = code; i > 0; --i) {
+ seqBuf[i] = table[j].tail;
+ j = table[j].head;
+ }
+ seqBuf[0] = j;
+ } else if (code == nextCode) {
+ seqBuf[seqLength] = newChar;
+ ++seqLength;
+ } else {
+ error(getPos(), "Bad LZW stream - unexpected code");
+ eof = gTrue;
+ return gFalse;
+ }
+ newChar = seqBuf[0];
+ if (first) {
+ first = gFalse;
+ } else {
+ table[nextCode].length = nextLength;
+ table[nextCode].head = prevCode;
+ table[nextCode].tail = newChar;
+ ++nextCode;
+ if (nextCode + early == 512)
+ nextBits = 10;
+ else if (nextCode + early == 1024)
+ nextBits = 11;
+ else if (nextCode + early == 2048)
+ nextBits = 12;
+ }
+ prevCode = code;
+
+ // reset buffer
+ seqIndex = 0;
+
+ return gTrue;
+}
+
+void LZWStream::clearTable() {
+ nextCode = 258;
+ nextBits = 9;
+ seqIndex = seqLength = 0;
+ first = gTrue;
+}
+
+int LZWStream::getCode() {
+ int c;
+ int code;
+
+ while (inputBits < nextBits) {
+ if ((c = str->getChar()) == EOF)
+ return EOF;
+ inputBuf = (inputBuf << 8) | (c & 0xff);
+ inputBits += 8;
+ }
+ code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
+ inputBits -= nextBits;
+ return code;
+}
+
+GString *LZWStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 2 || pred) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("/LZWDecode filter\n");
+ return s;
+}
+
+GBool LZWStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+//------------------------------------------------------------------------
+// RunLengthStream
+//------------------------------------------------------------------------
+
+RunLengthStream::RunLengthStream(Stream *strA):
+ FilterStream(strA) {
+ bufPtr = bufEnd = buf;
+ eof = gFalse;
+}
+
+RunLengthStream::~RunLengthStream() {
+ delete str;
+}
+
+void RunLengthStream::reset() {
+ str->reset();
+ bufPtr = bufEnd = buf;
+ eof = gFalse;
+}
+
+GString *RunLengthStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("/RunLengthDecode filter\n");
+ return s;
+}
+
+GBool RunLengthStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+GBool RunLengthStream::fillBuf() {
+ int c;
+ int n, i;
+
+ if (eof)
+ return gFalse;
+ c = str->getChar();
+ if (c == 0x80 || c == EOF) {
+ eof = gTrue;
+ return gFalse;
+ }
+ if (c < 0x80) {
+ n = c + 1;
+ for (i = 0; i < n; ++i)
+ buf[i] = (char)str->getChar();
+ } else {
+ n = 0x101 - c;
+ c = str->getChar();
+ for (i = 0; i < n; ++i)
+ buf[i] = (char)c;
+ }
+ bufPtr = buf;
+ bufEnd = buf + n;
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+// CCITTFaxStream
+//------------------------------------------------------------------------
+
+CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
+ GBool byteAlignA, int columnsA, int rowsA,
+ GBool endOfBlockA, GBool blackA):
+ FilterStream(strA) {
+ encoding = encodingA;
+ endOfLine = endOfLineA;
+ byteAlign = byteAlignA;
+ columns = columnsA;
+ rows = rowsA;
+ endOfBlock = endOfBlockA;
+ black = blackA;
+ refLine = (short *)gmalloc((columns + 3) * sizeof(short));
+ codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
+
+ eof = gFalse;
+ row = 0;
+ nextLine2D = encoding < 0;
+ inputBits = 0;
+ codingLine[0] = 0;
+ codingLine[1] = refLine[2] = columns;
+ a0 = 1;
+
+ buf = EOF;
+}
+
+CCITTFaxStream::~CCITTFaxStream() {
+ delete str;
+ gfree(refLine);
+ gfree(codingLine);
+}
+
+void CCITTFaxStream::reset() {
+ int n;
+
+ str->reset();
+ eof = gFalse;
+ row = 0;
+ nextLine2D = encoding < 0;
+ inputBits = 0;
+ codingLine[0] = 0;
+ codingLine[1] = refLine[2] = columns;
+ a0 = 1;
+ buf = EOF;
+
+ // get initial end-of-line marker and 2D encoding tag
+ if (endOfBlock) {
+ if (lookBits(12) == 0x001) {
+ eatBits(12);
+ }
+ } else {
+ for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
+ if (n == 11 && lookBits(12) == 0x001) {
+ eatBits(12);
+ }
+ }
+ if (encoding > 0) {
+ nextLine2D = !lookBits(1);
+ eatBits(1);
+ }
+}
+
+int CCITTFaxStream::lookChar() {
+ short code1, code2, code3;
+ int a0New;
+#if 0
+ GBool err;
+#endif
+ GBool gotEOL;
+ int ret;
+ int bits, i;
+
+ // if at eof just return EOF
+ if (eof && codingLine[a0] >= columns) {
+ return EOF;
+ }
+
+ // read the next row
+#if 0
+ err = gFalse;
+#endif
+ if (codingLine[a0] >= columns) {
+
+ // 2-D encoding
+ if (nextLine2D) {
+ for (i = 0; codingLine[i] < columns; ++i)
+ refLine[i] = codingLine[i];
+ refLine[i] = refLine[i + 1] = columns;
+ b1 = 1;
+ a0New = codingLine[a0 = 0] = 0;
+ do {
+ code1 = getTwoDimCode();
+ switch (code1) {
+ case twoDimPass:
+ if (refLine[b1] < columns) {
+ a0New = refLine[b1 + 1];
+ b1 += 2;
+ }
+ break;
+ case twoDimHoriz:
+ if ((a0 & 1) == 0) {
+ code1 = code2 = 0;
+ do {
+ code1 += code3 = getWhiteCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = getBlackCode();
+ } while (code3 >= 64);
+ } else {
+ code1 = code2 = 0;
+ do {
+ code1 += code3 = getBlackCode();
+ } while (code3 >= 64);
+ do {
+ code2 += code3 = getWhiteCode();
+ } while (code3 >= 64);
+ }
+ if (code1 > 0 || code2 > 0) {
+ codingLine[a0 + 1] = a0New + code1;
+ ++a0;
+ a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
+ ++a0;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
+ break;
+ case twoDimVert0:
+ a0New = codingLine[++a0] = refLine[b1];
+ if (refLine[b1] < columns) {
+ ++b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
+ break;
+ case twoDimVertR1:
+ a0New = codingLine[++a0] = refLine[b1] + 1;
+ if (refLine[b1] < columns) {
+ ++b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
+ break;
+ case twoDimVertL1:
+ a0New = codingLine[++a0] = refLine[b1] - 1;
+ --b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ break;
+ case twoDimVertR2:
+ a0New = codingLine[++a0] = refLine[b1] + 2;
+ if (refLine[b1] < columns) {
+ ++b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
+ break;
+ case twoDimVertL2:
+ a0New = codingLine[++a0] = refLine[b1] - 2;
+ --b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ break;
+ case twoDimVertR3:
+ a0New = codingLine[++a0] = refLine[b1] + 3;
+ if (refLine[b1] < columns) {
+ ++b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ }
+ break;
+ case twoDimVertL3:
+ a0New = codingLine[++a0] = refLine[b1] - 3;
+ --b1;
+ while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
+ b1 += 2;
+ break;
+ case EOF:
+ eof = gTrue;
+ codingLine[a0 = 0] = columns;
+ return EOF;
+ default:
+ error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
+#if 0
+ err = gTrue;
+ break;
+#else
+ eof = gTrue;
+ return EOF;
+#endif
+ }
+ } while (codingLine[a0] < columns);
+
+ // 1-D encoding
+ } else {
+ codingLine[a0 = 0] = 0;
+ while (1) {
+ code1 = 0;
+ do {
+ code1 += code3 = getWhiteCode();
+ } while (code3 >= 64);
+ codingLine[a0+1] = codingLine[a0] + code1;
+ ++a0;
+ if (codingLine[a0] >= columns)
+ break;
+ code2 = 0;
+ do {
+ code2 += code3 = getBlackCode();
+ } while (code3 >= 64);
+ codingLine[a0+1] = codingLine[a0] + code2;
+ ++a0;
+ if (codingLine[a0] >= columns)
+ break;
+ }
+ }
+
+ if (codingLine[a0] != columns) {
+ error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
+#if 0
+ err = gTrue;
+#endif
+ }
+
+ // byte-align the row
+ if (byteAlign) {
+ inputBits &= ~7;
+ }
+
+ // check for end-of-line marker, skipping over any extra zero bits
+ gotEOL = gFalse;
+ if (!endOfBlock && row == rows - 1) {
+ eof = gTrue;
+ } else {
+ code1 = lookBits(12);
+ while (code1 == 0) {
+ eatBits(1);
+ code1 = lookBits(12);
+ }
+ if (code1 == 0x001) {
+ eatBits(12);
+ gotEOL = gTrue;
+ } else if (code1 == EOF) {
+ eof = gTrue;
+ }
+ }
+
+ // get 2D encoding tag
+ if (!eof && encoding > 0) {
+ nextLine2D = !lookBits(1);
+ eatBits(1);
+ }
+
+ // check for end-of-block marker
+ if (endOfBlock && gotEOL) {
+ code1 = lookBits(12);
+ if (code1 == 0x001) {
+ eatBits(12);
+ if (encoding > 0) {
+ lookBits(1);
+ eatBits(1);
+ }
+ if (encoding >= 0) {
+ for (i = 0; i < 4; ++i) {
+ code1 = lookBits(12);
+ if (code1 != 0x001) {
+ error(getPos(), "Bad RTC code in CCITTFax stream");
+ }
+ eatBits(12);
+ if (encoding > 0) {
+ lookBits(1);
+ eatBits(1);
+ }
+ }
+ }
+ eof = gTrue;
+ }
+ }
+
+#if 0
+ // This looks for an end-of-line marker after an error, however
+ // some (most?) CCITT streams in PDF files don't use end-of-line
+ // markers, and the just-plow-on technique works better in those
+ // cases.
+ else if (err) {
+ do {
+ if (code1 == EOF) {
+ eof = gTrue;
+ return EOF;
+ }
+ eatBits(1);
+ code1 = lookBits(13);
+ } while ((code1 >> 1) != 0x001);
+ eatBits(12);
+ codingLine[++a0] = columns;
+ if (encoding > 0) {
+ eatBits(1);
+ nextLine2D = !(code1 & 1);
+ }
+ }
+#endif
+
+ a0 = 0;
+ outputBits = codingLine[1] - codingLine[0];
+ if (outputBits == 0) {
+ a0 = 1;
+ outputBits = codingLine[2] - codingLine[1];
+ }
+
+ ++row;
+ }
+
+ // get a byte
+ if (outputBits >= 8) {
+ ret = ((a0 & 1) == 0) ? 0xff : 0x00;
+ if ((outputBits -= 8) == 0) {
+ ++a0;
+ if (codingLine[a0] < columns) {
+ outputBits = codingLine[a0 + 1] - codingLine[a0];
+ }
+ }
+ } else {
+ bits = 8;
+ ret = 0;
+ do {
+ if (outputBits > bits) {
+ i = bits;
+ bits = 0;
+ if ((a0 & 1) == 0) {
+ ret |= 0xff >> (8 - i);
+ }
+ outputBits -= i;
+ } else {
+ i = outputBits;
+ bits -= outputBits;
+ if ((a0 & 1) == 0) {
+ ret |= (0xff >> (8 - i)) << bits;
+ }
+ outputBits = 0;
+ ++a0;
+ if (codingLine[a0] < columns) {
+ outputBits = codingLine[a0 + 1] - codingLine[a0];
+ }
+ }
+ } while (bits > 0 && codingLine[a0] < columns);
+ }
+ buf = black ? (ret ^ 0xff) : ret;
+ return buf;
+}
+
+short CCITTFaxStream::getTwoDimCode() {
+ short code;
+ CCITTCode *p;
+ int n;
+
+ code = 0; // make gcc happy
+ if (endOfBlock) {
+ code = lookBits(7);
+ p = &twoDimTab1[code];
+ if (p->bits > 0) {
+ eatBits(p->bits);
+ return p->n;
+ }
+ } else {
+ for (n = 1; n <= 7; ++n) {
+ code = lookBits(n);
+ if (n < 7) {
+ code <<= 7 - n;
+ }
+ p = &twoDimTab1[code];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ }
+ error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
+ return EOF;
+}
+
+short CCITTFaxStream::getWhiteCode() {
+ short code;
+ CCITTCode *p;
+ int n;
+
+ code = 0; // make gcc happy
+ if (endOfBlock) {
+ code = lookBits(12);
+ if ((code >> 5) == 0) {
+ p = &whiteTab1[code];
+ } else {
+ p = &whiteTab2[code >> 3];
+ }
+ if (p->bits > 0) {
+ eatBits(p->bits);
+ return p->n;
+ }
+ } else {
+ for (n = 1; n <= 9; ++n) {
+ code = lookBits(n);
+ if (n < 9) {
+ code <<= 9 - n;
+ }
+ p = &whiteTab2[code];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ for (n = 11; n <= 12; ++n) {
+ code = lookBits(n);
+ if (n < 12) {
+ code <<= 12 - n;
+ }
+ p = &whiteTab1[code];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ }
+ error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ eatBits(1);
+ return 1;
+}
+
+short CCITTFaxStream::getBlackCode() {
+ short code;
+ CCITTCode *p;
+ int n;
+
+ code = 0; // make gcc happy
+ if (endOfBlock) {
+ code = lookBits(13);
+ if ((code >> 7) == 0) {
+ p = &blackTab1[code];
+ } else if ((code >> 9) == 0) {
+ p = &blackTab2[(code >> 1) - 64];
+ } else {
+ p = &blackTab3[code >> 7];
+ }
+ if (p->bits > 0) {
+ eatBits(p->bits);
+ return p->n;
+ }
+ } else {
+ for (n = 2; n <= 6; ++n) {
+ code = lookBits(n);
+ if (n < 6) {
+ code <<= 6 - n;
+ }
+ p = &blackTab3[code];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ for (n = 7; n <= 12; ++n) {
+ code = lookBits(n);
+ if (n < 12) {
+ code <<= 12 - n;
+ }
+ if (code >= 64) {
+ p = &blackTab2[code - 64];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ }
+ for (n = 10; n <= 13; ++n) {
+ code = lookBits(n);
+ if (n < 13) {
+ code <<= 13 - n;
+ }
+ p = &blackTab1[code];
+ if (p->bits == n) {
+ eatBits(n);
+ return p->n;
+ }
+ }
+ }
+ error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ eatBits(1);
+ return 1;
+}
+
+short CCITTFaxStream::lookBits(int n) {
+ int c;
+
+ while (inputBits < n) {
+ if ((c = str->getChar()) == EOF) {
+ if (inputBits == 0) {
+ return EOF;
+ }
+ // near the end of the stream, the caller may ask for more bits
+ // than are available, but there may still be a valid code in
+ // however many bits are available -- we need to return correct
+ // data in this case
+ return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
+ }
+ inputBuf = (inputBuf << 8) + c;
+ inputBits += 8;
+ }
+ return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
+}
+
+GString *CCITTFaxStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+ char s1[50];
+
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("<< ");
+ if (encoding != 0) {
+ sprintf(s1, "/K %d ", encoding);
+ s->append(s1);
+ }
+ if (endOfLine) {
+ s->append("/EndOfLine true ");
+ }
+ if (byteAlign) {
+ s->append("/EncodedByteAlign true ");
+ }
+ sprintf(s1, "/Columns %d ", columns);
+ s->append(s1);
+ if (rows != 0) {
+ sprintf(s1, "/Rows %d ", rows);
+ s->append(s1);
+ }
+ if (!endOfBlock) {
+ s->append("/EndOfBlock false ");
+ }
+ if (black) {
+ s->append("/BlackIs1 true ");
+ }
+ s->append(">> /CCITTFaxDecode filter\n");
+ return s;
+}
+
+GBool CCITTFaxStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+//------------------------------------------------------------------------
+// DCTStream
+//------------------------------------------------------------------------
+
+// IDCT constants (20.12 fixed point format)
+#define dctCos1 4017 // cos(pi/16)
+#define dctSin1 799 // sin(pi/16)
+#define dctCos3 3406 // cos(3*pi/16)
+#define dctSin3 2276 // sin(3*pi/16)
+#define dctCos6 1567 // cos(6*pi/16)
+#define dctSin6 3784 // sin(6*pi/16)
+#define dctSqrt2 5793 // sqrt(2)
+#define dctSqrt1d2 2896 // sqrt(2) / 2
+
+// color conversion parameters (16.16 fixed point format)
+#define dctCrToR 91881 // 1.4020
+#define dctCbToG -22553 // -0.3441363
+#define dctCrToG -46802 // -0.71413636
+#define dctCbToB 116130 // 1.772
+
+// clip [-256,511] --> [0,255]
+#define dctClipOffset 256
+static Guchar dctClip[768];
+static int dctClipInit = 0;
+
+// zig zag decode map
+static int dctZigZag[64] = {
+ 0,
+ 1, 8,
+ 16, 9, 2,
+ 3, 10, 17, 24,
+ 32, 25, 18, 11, 4,
+ 5, 12, 19, 26, 33, 40,
+ 48, 41, 34, 27, 20, 13, 6,
+ 7, 14, 21, 28, 35, 42, 49, 56,
+ 57, 50, 43, 36, 29, 22, 15,
+ 23, 30, 37, 44, 51, 58,
+ 59, 52, 45, 38, 31,
+ 39, 46, 53, 60,
+ 61, 54, 47,
+ 55, 62,
+ 63
+};
+
+DCTStream::DCTStream(Stream *strA):
+ FilterStream(strA) {
+ int i, j;
+
+ progressive = interleaved = gFalse;
+ width = height = 0;
+ mcuWidth = mcuHeight = 0;
+ numComps = 0;
+ comp = 0;
+ x = y = dy = 0;
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 32; ++j) {
+ rowBuf[i][j] = NULL;
+ }
+ frameBuf[i] = NULL;
+ }
+
+ if (!dctClipInit) {
+ for (i = -256; i < 0; ++i)
+ dctClip[dctClipOffset + i] = 0;
+ for (i = 0; i < 256; ++i)
+ dctClip[dctClipOffset + i] = i;
+ for (i = 256; i < 512; ++i)
+ dctClip[dctClipOffset + i] = 255;
+ dctClipInit = 1;
+ }
+}
+
+DCTStream::~DCTStream() {
+ int i, j;
+
+ delete str;
+ if (progressive || !interleaved) {
+ for (i = 0; i < numComps; ++i) {
+ gfree(frameBuf[i]);
+ }
+ } else {
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ gfree(rowBuf[i][j]);
+ }
+ }
+ }
+}
+
+void DCTStream::reset() {
+ int minHSample, minVSample;
+ int i, j;
+
+ str->reset();
+
+ progressive = interleaved = gFalse;
+ width = height = 0;
+ numComps = 0;
+ numQuantTables = 0;
+ numDCHuffTables = 0;
+ numACHuffTables = 0;
+ colorXform = 0;
+ gotJFIFMarker = gFalse;
+ gotAdobeMarker = gFalse;
+ restartInterval = 0;
+
+ if (!readHeader()) {
+ y = height;
+ return;
+ }
+
+ // compute MCU size
+ mcuWidth = minHSample = compInfo[0].hSample;
+ mcuHeight = minVSample = compInfo[0].vSample;
+ for (i = 1; i < numComps; ++i) {
+ if (compInfo[i].hSample < minHSample)
+ minHSample = compInfo[i].hSample;
+ if (compInfo[i].vSample < minVSample)
+ minVSample = compInfo[i].vSample;
+ if (compInfo[i].hSample > mcuWidth)
+ mcuWidth = compInfo[i].hSample;
+ if (compInfo[i].vSample > mcuHeight)
+ mcuHeight = compInfo[i].vSample;
+ }
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].hSample /= minHSample;
+ compInfo[i].vSample /= minVSample;
+ }
+ mcuWidth = (mcuWidth / minHSample) * 8;
+ mcuHeight = (mcuHeight / minVSample) * 8;
+
+ // figure out color transform
+ if (!gotAdobeMarker && numComps == 3) {
+ if (gotJFIFMarker) {
+ colorXform = 1;
+ } else if (compInfo[0].id == 82 && compInfo[1].id == 71 &&
+ compInfo[2].id == 66) { // ASCII "RGB"
+ colorXform = 0;
+ } else {
+ colorXform = 1;
+ }
+ }
+
+ if (progressive || !interleaved) {
+
+ // allocate a buffer for the whole image
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
+ for (i = 0; i < numComps; ++i) {
+ frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
+ memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
+ }
+
+ // read the image data
+ do {
+ restartMarker = 0xd0;
+ restart();
+ readScan();
+ } while (readHeader());
+
+ // decode
+ decodeImage();
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+
+ } else {
+
+ // allocate a buffer for one row of MCUs
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
+ for (i = 0; i < numComps; ++i) {
+ for (j = 0; j < mcuHeight; ++j) {
+ rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
+ }
+ }
+
+ // initialize counters
+ comp = 0;
+ x = 0;
+ y = 0;
+ dy = mcuHeight;
+
+ restartMarker = 0xd0;
+ restart();
+ }
+}
+
+int DCTStream::getChar() {
+ int c;
+
+ if (y >= height) {
+ return EOF;
+ }
+ if (progressive || !interleaved) {
+ c = frameBuf[comp][y * bufWidth + x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ }
+ }
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
+ x = 0;
+ dy = 0;
+ }
+ c = rowBuf[comp][dy][x];
+ if (++comp == numComps) {
+ comp = 0;
+ if (++x == width) {
+ x = 0;
+ ++y;
+ ++dy;
+ if (y == height) {
+ readTrailer();
+ }
+ }
+ }
+ }
+ return c;
+}
+
+int DCTStream::lookChar() {
+ if (y >= height) {
+ return EOF;
+ }
+ if (progressive || !interleaved) {
+ return frameBuf[comp][y * bufWidth + x];
+ } else {
+ if (dy >= mcuHeight) {
+ if (!readMCURow()) {
+ y = height;
+ return EOF;
+ }
+ comp = 0;
+ x = 0;
+ dy = 0;
+ }
+ return rowBuf[comp][dy][x];
+ }
+}
+
+void DCTStream::restart() {
+ int i;
+
+ inputBits = 0;
+ restartCtr = restartInterval;
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].prevDC = 0;
+ }
+ eobRun = 0;
+}
+
+// Read one row of MCUs from a sequential JPEG stream.
+GBool DCTStream::readMCURow() {
+ int data1[64];
+ Guchar data2[64];
+ Guchar *p1, *p2;
+ int pY, pCb, pCr, pR, pG, pB;
+ int h, v, horiz, vert, hSub, vSub;
+ int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
+ int c;
+
+ for (x1 = 0; x1 < width; x1 += mcuWidth) {
+
+ // deal with restart marker
+ if (restartInterval > 0 && restartCtr == 0) {
+ c = readMarker();
+ if (c != restartMarker) {
+ error(getPos(), "Bad DCT data: incorrect restart marker");
+ return gFalse;
+ }
+ if (++restartMarker == 0xd8)
+ restartMarker = 0xd0;
+ restart();
+ }
+
+ // read one MCU
+ for (cc = 0; cc < numComps; ++cc) {
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ hSub = horiz / 8;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) {
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data1)) {
+ return gFalse;
+ }
+ transformDataUnit(quantTables[compInfo[cc].quantTable],
+ data1, data2);
+ if (hSub == 1 && vSub == 1) {
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1 = &rowBuf[cc][y2+y3][x1+x2];
+ p1[0] = data2[i];
+ p1[1] = data2[i+1];
+ p1[2] = data2[i+2];
+ p1[3] = data2[i+3];
+ p1[4] = data2[i+4];
+ p1[5] = data2[i+5];
+ p1[6] = data2[i+6];
+ p1[7] = data2[i+7];
+ }
+ } else if (hSub == 2 && vSub == 2) {
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
+ p1 = &rowBuf[cc][y2+y3][x1+x2];
+ p2 = &rowBuf[cc][y2+y3+1][x1+x2];
+ p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
+ p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
+ p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
+ p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
+ p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
+ p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
+ p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
+ p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
+ }
+ } else {
+ i = 0;
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
+ for (y5 = 0; y5 < vSub; ++y5)
+ for (x5 = 0; x5 < hSub; ++x5)
+ rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
+ ++i;
+ }
+ }
+ }
+ }
+ }
+ }
+ --restartCtr;
+
+ // color space conversion
+ if (colorXform) {
+ // convert YCbCr to RGB
+ if (numComps == 3) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = rowBuf[0][y2][x1+x2];
+ pCb = rowBuf[1][y2][x1+x2] - 128;
+ pCr = rowBuf[2][y2][x1+x2] - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
+ rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
+ }
+ }
+ // convert YCbCrK to CMYK (K is passed through unchanged)
+ } else if (numComps == 4) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = rowBuf[0][y2][x1+x2];
+ pCb = rowBuf[1][y2][x1+x2] - 128;
+ pCr = rowBuf[2][y2][x1+x2] - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
+ rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
+ }
+ }
+ }
+ }
+ }
+ return gTrue;
+}
+
+// Read one scan from a progressive or non-interleaved JPEG stream.
+void DCTStream::readScan() {
+ int data[64];
+ int x1, y1, dx1, dy1, x2, y2, y3, cc, i;
+ int h, v, horiz, vert, vSub;
+ int *p1;
+ int c;
+
+ if (scanInfo.numComps == 1) {
+ for (cc = 0; cc < numComps; ++cc) {
+ if (scanInfo.comp[cc]) {
+ break;
+ }
+ }
+ dx1 = mcuWidth / compInfo[cc].hSample;
+ dy1 = mcuHeight / compInfo[cc].vSample;
+ } else {
+ dx1 = mcuWidth;
+ dy1 = mcuHeight;
+ }
+
+ for (y1 = 0; y1 < height; y1 += dy1) {
+ for (x1 = 0; x1 < width; x1 += dx1) {
+
+ // deal with restart marker
+ if (restartInterval > 0 && restartCtr == 0) {
+ c = readMarker();
+ if (c != restartMarker) {
+ error(getPos(), "Bad DCT data: incorrect restart marker");
+ return;
+ }
+ if (++restartMarker == 0xd8) {
+ restartMarker = 0xd0;
+ }
+ restart();
+ }
+
+ // read one MCU
+ for (cc = 0; cc < numComps; ++cc) {
+ if (!scanInfo.comp[cc]) {
+ continue;
+ }
+
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < dy1; y2 += vert) {
+ for (x2 = 0; x2 < dx1; x2 += horiz) {
+
+ // pull out the current values
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ data[i] = p1[0];
+ data[i+1] = p1[1];
+ data[i+2] = p1[2];
+ data[i+3] = p1[3];
+ data[i+4] = p1[4];
+ data[i+5] = p1[5];
+ data[i+6] = p1[6];
+ data[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // read one data unit
+ if (progressive) {
+ if (!readProgressiveDataUnit(
+ &dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ } else {
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
+ &acHuffTables[scanInfo.acHuffTable[cc]],
+ &compInfo[cc].prevDC,
+ data)) {
+ return;
+ }
+ }
+
+ // add the data unit into frameBuf
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = data[i];
+ p1[1] = data[i+1];
+ p1[2] = data[i+2];
+ p1[3] = data[i+3];
+ p1[4] = data[i+4];
+ p1[5] = data[i+5];
+ p1[6] = data[i+6];
+ p1[7] = data[i+7];
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ --restartCtr;
+ }
+ }
+}
+
+// Read one data unit from a sequential JPEG stream.
+GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]) {
+ int run, size, amp;
+ int c;
+ int i, j;
+
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
+ return gFalse;
+ }
+ if (size > 0) {
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ } else {
+ amp = 0;
+ }
+ data[0] = *prevDC += amp;
+ for (i = 1; i < 64; ++i) {
+ data[i] = 0;
+ }
+ i = 1;
+ while (i < 64) {
+ run = 0;
+ while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
+ run += 0x10;
+ }
+ if (c == 9999) {
+ return gFalse;
+ }
+ if (c == 0x00) {
+ break;
+ } else {
+ run += (c >> 4) & 0x0f;
+ size = c & 0x0f;
+ amp = readAmp(size);
+ if (amp == 9999) {
+ return gFalse;
+ }
+ i += run;
+ if (i < 64) {
+ j = dctZigZag[i++];
+ data[j] = amp;
+ }
+ }
+ }
+ return gTrue;
+}
+
+// Read one data unit from a sequential JPEG stream.
+GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]) {
+ int run, size, amp, bit, c;
+ int i, j, k;
+
+ // get the DC coefficient
+ i = scanInfo.firstCoeff;
+ if (i == 0) {
+ if (scanInfo.ah == 0) {
+ if ((size = readHuffSym(dcHuffTable)) == 9999) {
+ return gFalse;
+ }
+ if (size > 0) {
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ } else {
+ amp = 0;
+ }
+ data[0] += (*prevDC += amp) << scanInfo.al;
+ } else {
+ if ((bit = readBit()) == 9999) {
+ return gFalse;
+ }
+ data[0] += bit << scanInfo.al;
+ }
+ ++i;
+ }
+ if (scanInfo.lastCoeff == 0) {
+ return gTrue;
+ }
+
+ // check for an EOB run
+ if (eobRun > 0) {
+ while (i <= scanInfo.lastCoeff) {
+ j = dctZigZag[i++];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+ --eobRun;
+ return gTrue;
+ }
+
+ // read the AC coefficients
+ while (i <= scanInfo.lastCoeff) {
+ if ((c = readHuffSym(acHuffTable)) == 9999) {
+ return gFalse;
+ }
+
+ // ZRL
+ if (c == 0xf0) {
+ k = 0;
+ while (k < 16) {
+ j = dctZigZag[i++];
+ if (data[j] == 0) {
+ ++k;
+ } else {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+
+ // EOB run
+ } else if ((c & 0x0f) == 0x00) {
+ j = c >> 4;
+ eobRun = 0;
+ for (k = 0; k < j; ++k) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ eobRun = (eobRun << 1) | bit;
+ }
+ eobRun += 1 << j;
+ while (i <= scanInfo.lastCoeff) {
+ j = dctZigZag[i++];
+ if (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ }
+ }
+ --eobRun;
+ break;
+
+ // zero run and one AC coefficient
+ } else {
+ run = (c >> 4) & 0x0f;
+ size = c & 0x0f;
+ if ((amp = readAmp(size)) == 9999) {
+ return gFalse;
+ }
+ k = 0;
+ do {
+ j = dctZigZag[i++];
+ while (data[j] != 0) {
+ if ((bit = readBit()) == EOF) {
+ return gFalse;
+ }
+ if (bit) {
+ data[j] += 1 << scanInfo.al;
+ }
+ j = dctZigZag[i++];
+ }
+ ++k;
+ } while (k <= run);
+ data[j] = amp << scanInfo.al;
+ }
+ }
+
+ return gTrue;
+}
+
+// Decode a progressive JPEG image.
+void DCTStream::decodeImage() {
+ int dataIn[64];
+ Guchar dataOut[64];
+ Guchar *quantTable;
+ int pY, pCb, pCr, pR, pG, pB;
+ int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
+ int h, v, horiz, vert, hSub, vSub;
+ int *p0, *p1, *p2;
+
+ for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
+ for (cc = 0; cc < numComps; ++cc) {
+ quantTable = quantTables[compInfo[cc].quantTable];
+ h = compInfo[cc].hSample;
+ v = compInfo[cc].vSample;
+ horiz = mcuWidth / h;
+ vert = mcuHeight / v;
+ hSub = horiz / 8;
+ vSub = vert / 8;
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) {
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
+
+ // pull out the coded data unit
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ dataIn[i] = p1[0];
+ dataIn[i+1] = p1[1];
+ dataIn[i+2] = p1[2];
+ dataIn[i+3] = p1[3];
+ dataIn[i+4] = p1[4];
+ dataIn[i+5] = p1[5];
+ dataIn[i+6] = p1[6];
+ dataIn[i+7] = p1[7];
+ p1 += bufWidth * vSub;
+ }
+
+ // transform
+ transformDataUnit(quantTable, dataIn, dataOut);
+
+ // store back into frameBuf, doing replication for
+ // subsampled components
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
+ if (hSub == 1 && vSub == 1) {
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
+ p1[0] = dataOut[i] & 0xff;
+ p1[1] = dataOut[i+1] & 0xff;
+ p1[2] = dataOut[i+2] & 0xff;
+ p1[3] = dataOut[i+3] & 0xff;
+ p1[4] = dataOut[i+4] & 0xff;
+ p1[5] = dataOut[i+5] & 0xff;
+ p1[6] = dataOut[i+6] & 0xff;
+ p1[7] = dataOut[i+7] & 0xff;
+ p1 += bufWidth;
+ }
+ } else if (hSub == 2 && vSub == 2) {
+ p2 = p1 + bufWidth;
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
+ p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
+ p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
+ p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
+ p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
+ p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
+ p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
+ p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
+ p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
+ p1 += bufWidth * 2;
+ p2 += bufWidth * 2;
+ }
+ } else {
+ i = 0;
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
+ p2 = p1 + x4;
+ for (y5 = 0; y5 < vSub; ++y5) {
+ for (x5 = 0; x5 < hSub; ++x5) {
+ p2[x5] = dataOut[i] & 0xff;
+ }
+ p2 += bufWidth;
+ }
+ ++i;
+ }
+ p1 += bufWidth * vSub;
+ }
+ }
+ }
+ }
+ }
+
+ // color space conversion
+ if (colorXform) {
+ // convert YCbCr to RGB
+ if (numComps == 3) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = dctClip[dctClipOffset + pB];
+ }
+ }
+ // convert YCbCrK to CMYK (K is passed through unchanged)
+ } else if (numComps == 4) {
+ for (y2 = 0; y2 < mcuHeight; ++y2) {
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
+ for (x2 = 0; x2 < mcuWidth; ++x2) {
+ pY = *p0;
+ pCb = *p1 - 128;
+ pCr = *p2 - 128;
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
+ *p0++ = 255 - dctClip[dctClipOffset + pR];
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
+ 32768) >> 16;
+ *p1++ = 255 - dctClip[dctClipOffset + pG];
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
+ *p2++ = 255 - dctClip[dctClipOffset + pB];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Transform one data unit -- this performs the dequantization and
+// IDCT steps. This IDCT algorithm is taken from:
+// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
+// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
+// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
+// 988-991.
+// The stage numbers mentioned in the comments refer to Figure 1 in this
+// paper.
+void DCTStream::transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]) {
+ int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ int *p;
+ int i;
+
+ // dequant
+ for (i = 0; i < 64; ++i) {
+ dataIn[i] *= quantTable[i];
+ }
+
+ // inverse DCT on rows
+ for (i = 0; i < 64; i += 8) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
+ p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
+ t = (dctSqrt2 * p[0] + 512) >> 10;
+ p[0] = t;
+ p[1] = t;
+ p[2] = t;
+ p[3] = t;
+ p[4] = t;
+ p[5] = t;
+ p[6] = t;
+ p[7] = t;
+ continue;
+ }
+
+ // stage 4
+ v0 = (dctSqrt2 * p[0] + 128) >> 8;
+ v1 = (dctSqrt2 * p[4] + 128) >> 8;
+ v2 = p[2];
+ v3 = p[6];
+ v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
+ v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
+ v5 = p[3] << 4;
+ v6 = p[5] << 4;
+
+ // stage 3
+ t = (v0 - v1+ 1) >> 1;
+ v0 = (v0 + v1 + 1) >> 1;
+ v1 = t;
+ t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
+ v3 = t;
+ t = (v4 - v6 + 1) >> 1;
+ v4 = (v4 + v6 + 1) >> 1;
+ v6 = t;
+ t = (v7 + v5 + 1) >> 1;
+ v5 = (v7 - v5 + 1) >> 1;
+ v7 = t;
+
+ // stage 2
+ t = (v0 - v3 + 1) >> 1;
+ v0 = (v0 + v3 + 1) >> 1;
+ v3 = t;
+ t = (v1 - v2 + 1) >> 1;
+ v1 = (v1 + v2 + 1) >> 1;
+ v2 = t;
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+ v7 = t;
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+ v6 = t;
+
+ // stage 1
+ p[0] = v0 + v7;
+ p[7] = v0 - v7;
+ p[1] = v1 + v6;
+ p[6] = v1 - v6;
+ p[2] = v2 + v5;
+ p[5] = v2 - v5;
+ p[3] = v3 + v4;
+ p[4] = v3 - v4;
+ }
+
+ // inverse DCT on columns
+ for (i = 0; i < 8; ++i) {
+ p = dataIn + i;
+
+ // check for all-zero AC coefficients
+ if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
+ p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
+ t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+ p[0*8] = t;
+ p[1*8] = t;
+ p[2*8] = t;
+ p[3*8] = t;
+ p[4*8] = t;
+ p[5*8] = t;
+ p[6*8] = t;
+ p[7*8] = t;
+ continue;
+ }
+
+ // stage 4
+ v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
+ v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
+ v2 = p[2*8];
+ v3 = p[6*8];
+ v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
+ v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
+ v5 = p[3*8];
+ v6 = p[5*8];
+
+ // stage 3
+ t = (v0 - v1 + 1) >> 1;
+ v0 = (v0 + v1 + 1) >> 1;
+ v1 = t;
+ t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
+ v3 = t;
+ t = (v4 - v6 + 1) >> 1;
+ v4 = (v4 + v6 + 1) >> 1;
+ v6 = t;
+ t = (v7 + v5 + 1) >> 1;
+ v5 = (v7 - v5 + 1) >> 1;
+ v7 = t;
+
+ // stage 2
+ t = (v0 - v3 + 1) >> 1;
+ v0 = (v0 + v3 + 1) >> 1;
+ v3 = t;
+ t = (v1 - v2 + 1) >> 1;
+ v1 = (v1 + v2 + 1) >> 1;
+ v2 = t;
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+ v7 = t;
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+ v6 = t;
+
+ // stage 1
+ p[0*8] = v0 + v7;
+ p[7*8] = v0 - v7;
+ p[1*8] = v1 + v6;
+ p[6*8] = v1 - v6;
+ p[2*8] = v2 + v5;
+ p[5*8] = v2 - v5;
+ p[3*8] = v3 + v4;
+ p[4*8] = v3 - v4;
+ }
+
+ // convert to 8-bit integers
+ for (i = 0; i < 64; ++i) {
+ dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
+ }
+}
+
+int DCTStream::readHuffSym(DCTHuffTable *table) {
+ Gushort code;
+ int bit;
+ int codeBits;
+
+ code = 0;
+ codeBits = 0;
+ do {
+ // add a bit to the code
+ if ((bit = readBit()) == EOF)
+ return 9999;
+ code = (code << 1) + bit;
+ ++codeBits;
+
+ // look up code
+ if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
+ code -= table->firstCode[codeBits];
+ return table->sym[table->firstSym[codeBits] + code];
+ }
+ } while (codeBits < 16);
+
+ error(getPos(), "Bad Huffman code in DCT stream");
+ return 9999;
+}
+
+int DCTStream::readAmp(int size) {
+ int amp, bit;
+ int bits;
+
+ amp = 0;
+ for (bits = 0; bits < size; ++bits) {
+ if ((bit = readBit()) == EOF)
+ return 9999;
+ amp = (amp << 1) + bit;
+ }
+ if (amp < (1 << (size - 1)))
+ amp -= (1 << size) - 1;
+ return amp;
+}
+
+int DCTStream::readBit() {
+ int bit;
+ int c, c2;
+
+ if (inputBits == 0) {
+ if ((c = str->getChar()) == EOF)
+ return EOF;
+ if (c == 0xff) {
+ do {
+ c2 = str->getChar();
+ } while (c2 == 0xff);
+ if (c2 != 0x00) {
+ error(getPos(), "Bad DCT data: missing 00 after ff");
+ return EOF;
+ }
+ }
+ inputBuf = c;
+ inputBits = 8;
+ }
+ bit = (inputBuf >> (inputBits - 1)) & 1;
+ --inputBits;
+ return bit;
+}
+
+GBool DCTStream::readHeader() {
+ GBool doScan;
+ int n;
+ int c = 0;
+ int i;
+
+ // read headers
+ doScan = gFalse;
+ while (!doScan) {
+ c = readMarker();
+ switch (c) {
+ case 0xc0: // SOF0
+ if (!readBaselineSOF()) {
+ return gFalse;
+ }
+ break;
+ case 0xc2: // SOF2
+ if (!readProgressiveSOF()) {
+ return gFalse;
+ }
+ break;
+ case 0xc4: // DHT
+ if (!readHuffmanTables()) {
+ return gFalse;
+ }
+ break;
+ case 0xd8: // SOI
+ break;
+ case 0xd9: // EOI
+ return gFalse;
+ case 0xda: // SOS
+ if (!readScanInfo()) {
+ return gFalse;
+ }
+ doScan = gTrue;
+ break;
+ case 0xdb: // DQT
+ if (!readQuantTables()) {
+ return gFalse;
+ }
+ break;
+ case 0xdd: // DRI
+ if (!readRestartInterval()) {
+ return gFalse;
+ }
+ break;
+ case 0xe0: // APP0
+ if (!readJFIFMarker()) {
+ return gFalse;
+ }
+ break;
+ case 0xee: // APP14
+ if (!readAdobeMarker()) {
+ return gFalse;
+ }
+ break;
+ case EOF:
+ error(getPos(), "Bad DCT header");
+ return gFalse;
+ default:
+ // skip APPn / COM / etc.
+ if (c >= 0xe0) {
+ n = read16() - 2;
+ for (i = 0; i < n; ++i) {
+ str->getChar();
+ }
+ } else {
+ error(getPos(), "Unknown DCT marker <%02x>", c);
+ return gFalse;
+ }
+ break;
+ }
+ }
+
+ return gTrue;
+}
+
+GBool DCTStream::readBaselineSOF() {
+ int length;
+ int prec;
+ int i;
+ int c;
+
+ length = read16();
+ prec = str->getChar();
+ height = read16();
+ width = read16();
+ numComps = str->getChar();
+ if (prec != 8) {
+ error(getPos(), "Bad DCT precision %d", prec);
+ return gFalse;
+ }
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].id = str->getChar();
+ c = str->getChar();
+ compInfo[i].hSample = (c >> 4) & 0x0f;
+ compInfo[i].vSample = c & 0x0f;
+ compInfo[i].quantTable = str->getChar();
+ }
+ progressive = gFalse;
+ return gTrue;
+}
+
+GBool DCTStream::readProgressiveSOF() {
+ int length;
+ int prec;
+ int i;
+ int c;
+
+ length = read16();
+ prec = str->getChar();
+ height = read16();
+ width = read16();
+ numComps = str->getChar();
+ if (prec != 8) {
+ error(getPos(), "Bad DCT precision %d", prec);
+ return gFalse;
+ }
+ for (i = 0; i < numComps; ++i) {
+ compInfo[i].id = str->getChar();
+ c = str->getChar();
+ compInfo[i].hSample = (c >> 4) & 0x0f;
+ compInfo[i].vSample = c & 0x0f;
+ compInfo[i].quantTable = str->getChar();
+ }
+ progressive = gTrue;
+ return gTrue;
+}
+
+GBool DCTStream::readScanInfo() {
+ int length;
+ int id, c;
+ int i, j;
+
+ length = read16() - 2;
+ scanInfo.numComps = str->getChar();
+ --length;
+ if (length != 2 * scanInfo.numComps + 3) {
+ error(getPos(), "Bad DCT scan info block");
+ return gFalse;
+ }
+ interleaved = scanInfo.numComps == numComps;
+ for (j = 0; j < numComps; ++j) {
+ scanInfo.comp[j] = gFalse;
+ }
+ for (i = 0; i < scanInfo.numComps; ++i) {
+ id = str->getChar();
+ // some (broken) DCT streams reuse ID numbers, but at least they
+ // keep the components in order, so we check compInfo[i] first to
+ // work around the problem
+ if (id == compInfo[i].id) {
+ j = i;
+ } else {
+ for (j = 0; j < numComps; ++j) {
+ if (id == compInfo[j].id) {
+ break;
+ }
+ }
+ if (j == numComps) {
+ error(getPos(), "Bad DCT component ID in scan info block");
+ return gFalse;
+ }
+ }
+ scanInfo.comp[j] = gTrue;
+ c = str->getChar();
+ scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
+ scanInfo.acHuffTable[j] = c & 0x0f;
+ }
+ scanInfo.firstCoeff = str->getChar();
+ scanInfo.lastCoeff = str->getChar();
+ c = str->getChar();
+ scanInfo.ah = (c >> 4) & 0x0f;
+ scanInfo.al = c & 0x0f;
+ return gTrue;
+}
+
+GBool DCTStream::readQuantTables() {
+ int length;
+ int i;
+ int index;
+
+ length = read16() - 2;
+ while (length > 0) {
+ index = str->getChar();
+ if ((index & 0xf0) || index >= 4) {
+ error(getPos(), "Bad DCT quantization table");
+ return gFalse;
+ }
+ if (index == numQuantTables)
+ numQuantTables = index + 1;
+ for (i = 0; i < 64; ++i)
+ quantTables[index][dctZigZag[i]] = str->getChar();
+ length -= 65;
+ }
+ return gTrue;
+}
+
+GBool DCTStream::readHuffmanTables() {
+ DCTHuffTable *tbl;
+ int length;
+ int index;
+ Gushort code;
+ Guchar sym;
+ int i;
+ int c;
+
+ length = read16() - 2;
+ while (length > 0) {
+ index = str->getChar();
+ --length;
+ if ((index & 0x0f) >= 4) {
+ error(getPos(), "Bad DCT Huffman table");
+ return gFalse;
+ }
+ if (index & 0x10) {
+ index &= 0x0f;
+ if (index >= numACHuffTables)
+ numACHuffTables = index+1;
+ tbl = &acHuffTables[index];
+ } else {
+ if (index >= numDCHuffTables)
+ numDCHuffTables = index+1;
+ tbl = &dcHuffTables[index];
+ }
+ sym = 0;
+ code = 0;
+ for (i = 1; i <= 16; ++i) {
+ c = str->getChar();
+ tbl->firstSym[i] = sym;
+ tbl->firstCode[i] = code;
+ tbl->numCodes[i] = c;
+ sym += c;
+ code = (code + c) << 1;
+ }
+ length -= 16;
+ for (i = 0; i < sym; ++i)
+ tbl->sym[i] = str->getChar();
+ length -= sym;
+ }
+ return gTrue;
+}
+
+GBool DCTStream::readRestartInterval() {
+ int length;
+
+ length = read16();
+ if (length != 4) {
+ error(getPos(), "Bad DCT restart interval");
+ return gFalse;
+ }
+ restartInterval = read16();
+ return gTrue;
+}
+
+GBool DCTStream::readJFIFMarker() {
+ int length, i;
+ char buf[5];
+ int c;
+
+ length = read16();
+ length -= 2;
+ if (length >= 5) {
+ for (i = 0; i < 5; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ error(getPos(), "Bad DCT APP0 marker");
+ return gFalse;
+ }
+ buf[i] = c;
+ }
+ length -= 5;
+ if (!memcmp(buf, "JFIF\0", 5)) {
+ gotJFIFMarker = gTrue;
+ }
+ }
+ while (length > 0) {
+ if (str->getChar() == EOF) {
+ error(getPos(), "Bad DCT APP0 marker");
+ return gFalse;
+ }
+ --length;
+ }
+ return gTrue;
+}
+
+GBool DCTStream::readAdobeMarker() {
+ int length, i;
+ char buf[12];
+ int c;
+
+ length = read16();
+ if (length < 14) {
+ goto err;
+ }
+ for (i = 0; i < 12; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ goto err;
+ }
+ buf[i] = c;
+ }
+ if (strncmp(buf, "Adobe", 5)) {
+ goto err;
+ }
+ colorXform = buf[11];
+ gotAdobeMarker = gTrue;
+ for (i = 14; i < length; ++i) {
+ if (str->getChar() == EOF) {
+ goto err;
+ }
+ }
+ return gTrue;
+
+ err:
+ error(getPos(), "Bad DCT Adobe APP14 marker");
+ return gFalse;
+}
+
+GBool DCTStream::readTrailer() {
+ int c;
+
+ c = readMarker();
+ if (c != 0xd9) { // EOI
+ error(getPos(), "Bad DCT trailer");
+ return gFalse;
+ }
+ return gTrue;
+}
+
+int DCTStream::readMarker() {
+ int c;
+
+ do {
+ do {
+ c = str->getChar();
+ } while (c != 0xff);
+ do {
+ c = str->getChar();
+ } while (c == 0xff);
+ } while (c == 0x00);
+ return c;
+}
+
+int DCTStream::read16() {
+ int c1, c2;
+
+ if ((c1 = str->getChar()) == EOF)
+ return EOF;
+ if ((c2 = str->getChar()) == EOF)
+ return EOF;
+ return (c1 << 8) + c2;
+}
+
+GString *DCTStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 2) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("<< >> /DCTDecode filter\n");
+ return s;
+}
+
+GBool DCTStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+//------------------------------------------------------------------------
+// FlateStream
+//------------------------------------------------------------------------
+
+int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+};
+
+FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
+ {0, 3},
+ {0, 4},
+ {0, 5},
+ {0, 6},
+ {0, 7},
+ {0, 8},
+ {0, 9},
+ {0, 10},
+ {1, 11},
+ {1, 13},
+ {1, 15},
+ {1, 17},
+ {2, 19},
+ {2, 23},
+ {2, 27},
+ {2, 31},
+ {3, 35},
+ {3, 43},
+ {3, 51},
+ {3, 59},
+ {4, 67},
+ {4, 83},
+ {4, 99},
+ {4, 115},
+ {5, 131},
+ {5, 163},
+ {5, 195},
+ {5, 227},
+ {0, 258}
+};
+
+FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
+ { 0, 1},
+ { 0, 2},
+ { 0, 3},
+ { 0, 4},
+ { 1, 5},
+ { 1, 7},
+ { 2, 9},
+ { 2, 13},
+ { 3, 17},
+ { 3, 25},
+ { 4, 33},
+ { 4, 49},
+ { 5, 65},
+ { 5, 97},
+ { 6, 129},
+ { 6, 193},
+ { 7, 257},
+ { 7, 385},
+ { 8, 513},
+ { 8, 769},
+ { 9, 1025},
+ { 9, 1537},
+ {10, 2049},
+ {10, 3073},
+ {11, 4097},
+ {11, 6145},
+ {12, 8193},
+ {12, 12289},
+ {13, 16385},
+ {13, 24577}
+};
+
+FlateStream::FlateStream(Stream *strA, int predictor, int columns,
+ int colors, int bits):
+ FilterStream(strA) {
+ if (predictor != 1) {
+ pred = new StreamPredictor(this, predictor, columns, colors, bits);
+ } else {
+ pred = NULL;
+ }
+ litCodeTab.codes = NULL;
+ distCodeTab.codes = NULL;
+}
+
+FlateStream::~FlateStream() {
+ gfree(litCodeTab.codes);
+ gfree(distCodeTab.codes);
+ if (pred) {
+ delete pred;
+ }
+ delete str;
+}
+
+void FlateStream::reset() {
+ int cmf, flg;
+
+ index = 0;
+ remain = 0;
+ codeBuf = 0;
+ codeSize = 0;
+ compressedBlock = gFalse;
+ endOfBlock = gTrue;
+ eof = gTrue;
+
+ str->reset();
+
+ // read header
+ //~ need to look at window size?
+ endOfBlock = eof = gTrue;
+ cmf = str->getChar();
+ flg = str->getChar();
+ if (cmf == EOF || flg == EOF)
+ return;
+ if ((cmf & 0x0f) != 0x08) {
+ error(getPos(), "Unknown compression method in flate stream");
+ return;
+ }
+ if ((((cmf << 8) + flg) % 31) != 0) {
+ error(getPos(), "Bad FCHECK in flate stream");
+ return;
+ }
+ if (flg & 0x20) {
+ error(getPos(), "FDICT bit set in flate stream");
+ return;
+ }
+
+ eof = gFalse;
+}
+
+int FlateStream::getChar() {
+ int c;
+
+ if (pred) {
+ return pred->getChar();
+ }
+ while (remain == 0) {
+ if (endOfBlock && eof)
+ return EOF;
+ readSome();
+ }
+ c = buf[index];
+ index = (index + 1) & flateMask;
+ --remain;
+ return c;
+}
+
+int FlateStream::lookChar() {
+ int c;
+
+ if (pred) {
+ return pred->lookChar();
+ }
+ while (remain == 0) {
+ if (endOfBlock && eof)
+ return EOF;
+ readSome();
+ }
+ c = buf[index];
+ return c;
+}
+
+int FlateStream::getRawChar() {
+ int c;
+
+ while (remain == 0) {
+ if (endOfBlock && eof)
+ return EOF;
+ readSome();
+ }
+ c = buf[index];
+ index = (index + 1) & flateMask;
+ --remain;
+ return c;
+}
+
+GString *FlateStream::getPSFilter(int psLevel, const char *indent) {
+ GString *s;
+
+ if (psLevel < 3 || pred) {
+ return NULL;
+ }
+ if (!(s = str->getPSFilter(psLevel, indent))) {
+ return NULL;
+ }
+ s->append(indent)->append("<< >> /FlateDecode filter\n");
+ return s;
+}
+
+GBool FlateStream::isBinary(GBool last) {
+ return str->isBinary(gTrue);
+}
+
+void FlateStream::readSome() {
+ int code1, code2;
+ int len, dist;
+ int i, j, k;
+ int c;
+
+ if (endOfBlock) {
+ if (!startBlock())
+ return;
+ }
+
+ if (compressedBlock) {
+ if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
+ goto err;
+ if (code1 < 256) {
+ buf[index] = code1;
+ remain = 1;
+ } else if (code1 == 256) {
+ endOfBlock = gTrue;
+ remain = 0;
+ } else {
+ code1 -= 257;
+ code2 = lengthDecode[code1].bits;
+ if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
+ goto err;
+ len = lengthDecode[code1].first + code2;
+ if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
+ goto err;
+ code2 = distDecode[code1].bits;
+ if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
+ goto err;
+ dist = distDecode[code1].first + code2;
+ i = index;
+ j = (index - dist) & flateMask;
+ for (k = 0; k < len; ++k) {
+ buf[i] = buf[j];
+ i = (i + 1) & flateMask;
+ j = (j + 1) & flateMask;
+ }
+ remain = len;
+ }
+
+ } else {
+ len = (blockLen < flateWindow) ? blockLen : flateWindow;
+ for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
+ if ((c = str->getChar()) == EOF) {
+ endOfBlock = eof = gTrue;
+ break;
+ }
+ buf[j] = c & 0xff;
+ }
+ remain = i;
+ blockLen -= len;
+ if (blockLen == 0)
+ endOfBlock = gTrue;
+ }
+
+ return;
+
+err:
+ error(getPos(), "Unexpected end of file in flate stream");
+ endOfBlock = eof = gTrue;
+ remain = 0;
+}
+
+GBool FlateStream::startBlock() {
+ int blockHdr;
+ int c;
+ int check;
+
+ // free the code tables from the previous block
+ gfree(litCodeTab.codes);
+ litCodeTab.codes = NULL;
+ gfree(distCodeTab.codes);
+ distCodeTab.codes = NULL;
+
+ // read block header
+ blockHdr = getCodeWord(3);
+ if (blockHdr & 1)
+ eof = gTrue;
+ blockHdr >>= 1;
+
+ // uncompressed block
+ if (blockHdr == 0) {
+ compressedBlock = gFalse;
+ if ((c = str->getChar()) == EOF)
+ goto err;
+ blockLen = c & 0xff;
+ if ((c = str->getChar()) == EOF)
+ goto err;
+ blockLen |= (c & 0xff) << 8;
+ if ((c = str->getChar()) == EOF)
+ goto err;
+ check = c & 0xff;
+ if ((c = str->getChar()) == EOF)
+ goto err;
+ check |= (c & 0xff) << 8;
+ if (check != (~blockLen & 0xffff))
+ error(getPos(), "Bad uncompressed block length in flate stream");
+ codeBuf = 0;
+ codeSize = 0;
+
+ // compressed block with fixed codes
+ } else if (blockHdr == 1) {
+ compressedBlock = gTrue;
+ loadFixedCodes();
+
+ // compressed block with dynamic codes
+ } else if (blockHdr == 2) {
+ compressedBlock = gTrue;
+ if (!readDynamicCodes()) {
+ goto err;
+ }
+
+ // unknown block type
+ } else {
+ goto err;
+ }
+
+ endOfBlock = gFalse;
+ return gTrue;
+
+err:
+ error(getPos(), "Bad block header in flate stream");
+ endOfBlock = eof = gTrue;
+ return gFalse;
+}
+
+void FlateStream::loadFixedCodes() {
+ int i;
+
+ // build the literal code table
+ for (i = 0; i <= 143; ++i) {
+ codeLengths[i] = 8;
+ }
+ for (i = 144; i <= 255; ++i) {
+ codeLengths[i] = 9;
+ }
+ for (i = 256; i <= 279; ++i) {
+ codeLengths[i] = 7;
+ }
+ for (i = 280; i <= 287; ++i) {
+ codeLengths[i] = 8;
+ }
+ compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
+
+ // build the distance code table
+ for (i = 0; i < flateMaxDistCodes; ++i) {
+ codeLengths[i] = 5;
+ }
+ compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
+}
+
+GBool FlateStream::readDynamicCodes() {
+ int numCodeLenCodes;
+ int numLitCodes;
+ int numDistCodes;
+ int codeLenCodeLengths[flateMaxCodeLenCodes];
+ FlateHuffmanTab codeLenCodeTab;
+ int len, repeat, code;
+ int i;
+
+ codeLenCodeTab.codes = NULL;
+
+ // read lengths
+ if ((numLitCodes = getCodeWord(5)) == EOF) {
+ goto err;
+ }
+ numLitCodes += 257;
+ if ((numDistCodes = getCodeWord(5)) == EOF) {
+ goto err;
+ }
+ numDistCodes += 1;
+ if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
+ goto err;
+ }
+ numCodeLenCodes += 4;
+ if (numLitCodes > flateMaxLitCodes ||
+ numDistCodes > flateMaxDistCodes ||
+ numCodeLenCodes > flateMaxCodeLenCodes) {
+ goto err;
+ }
+
+ // build the code length code table
+ for (i = 0; i < flateMaxCodeLenCodes; ++i) {
+ codeLenCodeLengths[i] = 0;
+ }
+ for (i = 0; i < numCodeLenCodes; ++i) {
+ if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
+ goto err;
+ }
+ }
+ compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
+
+ // build the literal and distance code tables
+ len = 0;
+ repeat = 0;
+ i = 0;
+ while (i < numLitCodes + numDistCodes) {
+ if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
+ goto err;
+ }
+ if (code == 16) {
+ if ((repeat = getCodeWord(2)) == EOF) {
+ goto err;
+ }
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = len;
+ }
+ } else if (code == 17) {
+ if ((repeat = getCodeWord(3)) == EOF) {
+ goto err;
+ }
+ repeat += 3;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
+ len = 0;
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
+ } else if (code == 18) {
+ if ((repeat = getCodeWord(7)) == EOF) {
+ goto err;
+ }
+ repeat += 11;
+ if (i + repeat > numLitCodes + numDistCodes) {
+ goto err;
+ }
+ len = 0;
+ for (; repeat > 0; --repeat) {
+ codeLengths[i++] = 0;
+ }
+ } else {
+ codeLengths[i++] = len = code;
+ }
+ }
+ compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
+ compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
+
+ gfree(codeLenCodeTab.codes);
+ return gTrue;
+
+err:
+ error(getPos(), "Bad dynamic code table in flate stream");
+ gfree(codeLenCodeTab.codes);
+ return gFalse;
+}
+
+// Convert an array <lengths> of <n> lengths, in value order, into a
+// Huffman code lookup table.
+void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
+ int tabSize, len, code, code2, skip, val, i, t;
+
+ // find max code length
+ tab->maxLen = 0;
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] > tab->maxLen) {
+ tab->maxLen = lengths[val];
+ }
+ }
+
+ // allocate the table
+ tabSize = 1 << tab->maxLen;
+ tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
+
+ // clear the table
+ for (i = 0; i < tabSize; ++i) {
+ tab->codes[i].len = 0;
+ tab->codes[i].val = 0;
+ }
+
+ // build the table
+ for (len = 1, code = 0, skip = 2;
+ len <= tab->maxLen;
+ ++len, code <<= 1, skip <<= 1) {
+ for (val = 0; val < n; ++val) {
+ if (lengths[val] == len) {
+
+ // bit-reverse the code
+ code2 = 0;
+ t = code;
+ for (i = 0; i < len; ++i) {
+ code2 = (code2 << 1) | (t & 1);
+ t >>= 1;
+ }
+
+ // fill in the table entries
+ for (i = code2; i < tabSize; i += skip) {
+ tab->codes[i].len = (Gushort)len;
+ tab->codes[i].val = (Gushort)val;
+ }
+
+ ++code;
+ }
+ }
+ }
+}
+
+int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
+ FlateCode *code;
+ int c;
+
+ while (codeSize < tab->maxLen) {
+ if ((c = str->getChar()) == EOF) {
+ break;
+ }
+ codeBuf |= (c & 0xff) << codeSize;
+ codeSize += 8;
+ }
+ code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
+ if (codeSize == 0 || codeSize < code->len || code->len == 0) {
+ return EOF;
+ }
+ codeBuf >>= code->len;
+ codeSize -= code->len;
+ return (int)code->val;
+}
+
+int FlateStream::getCodeWord(int bits) {
+ int c;
+
+ while (codeSize < bits) {
+ if ((c = str->getChar()) == EOF)
+ return EOF;
+ codeBuf |= (c & 0xff) << codeSize;
+ codeSize += 8;
+ }
+ c = codeBuf & ((1 << bits) - 1);
+ codeBuf >>= bits;
+ codeSize -= bits;
+ return c;
+}
+
+//------------------------------------------------------------------------
+// EOFStream
+//------------------------------------------------------------------------
+
+EOFStream::EOFStream(Stream *strA):
+ FilterStream(strA) {
+}
+
+EOFStream::~EOFStream() {
+ delete str;
+}
+
+//------------------------------------------------------------------------
+// FixedLengthEncoder
+//------------------------------------------------------------------------
+
+FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
+ FilterStream(strA) {
+ length = lengthA;
+ count = 0;
+}
+
+FixedLengthEncoder::~FixedLengthEncoder() {
+ if (str->isEncoder())
+ delete str;
+}
+
+void FixedLengthEncoder::reset() {
+ str->reset();
+ count = 0;
+}
+
+int FixedLengthEncoder::getChar() {
+ if (length >= 0 && count >= length)
+ return EOF;
+ ++count;
+ return str->getChar();
+}
+
+int FixedLengthEncoder::lookChar() {
+ if (length >= 0 && count >= length)
+ return EOF;
+ return str->getChar();
+}
+
+//------------------------------------------------------------------------
+// ASCIIHexEncoder
+//------------------------------------------------------------------------
+
+ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
+ FilterStream(strA) {
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+ASCIIHexEncoder::~ASCIIHexEncoder() {
+ if (str->isEncoder()) {
+ delete str;
+ }
+}
+
+void ASCIIHexEncoder::reset() {
+ str->reset();
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+GBool ASCIIHexEncoder::fillBuf() {
+ static const char hex[] = "0123456789abcdef";
+ int c;
+
+ if (eof) {
+ return gFalse;
+ }
+ bufPtr = bufEnd = buf;
+ if ((c = str->getChar()) == EOF) {
+ *bufEnd++ = '>';
+ eof = gTrue;
+ } else {
+ if (lineLen >= 64) {
+ *bufEnd++ = '\n';
+ lineLen = 0;
+ }
+ *bufEnd++ = hex[(c >> 4) & 0x0f];
+ *bufEnd++ = hex[c & 0x0f];
+ lineLen += 2;
+ }
+ return gTrue;
+}
+
+//------------------------------------------------------------------------
+// ASCII85Encoder
+//------------------------------------------------------------------------
+
+ASCII85Encoder::ASCII85Encoder(Stream *strA):
+ FilterStream(strA) {
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+ASCII85Encoder::~ASCII85Encoder() {
+ if (str->isEncoder())
+ delete str;
+}
+
+void ASCII85Encoder::reset() {
+ str->reset();
+ bufPtr = bufEnd = buf;
+ lineLen = 0;
+ eof = gFalse;
+}
+
+GBool ASCII85Encoder::fillBuf() {
+ Gulong t;
+ char buf1[5];
+ int c;
+ int n, i;
+
+ if (eof)
+ return gFalse;
+ t = 0;
+ for (n = 0; n < 4; ++n) {
+ if ((c = str->getChar()) == EOF)
+ break;
+ t = (t << 8) + c;
+ }
+ bufPtr = bufEnd = buf;
+ if (n > 0) {
+ if (n == 4 && t == 0) {
+ *bufEnd++ = 'z';
+ if (++lineLen == 65) {
+ *bufEnd++ = '\n';
+ lineLen = 0;
+ }
+ } else {
+ if (n < 4)
+ t <<= 8 * (4 - n);
+ for (i = 4; i >= 0; --i) {
+ buf1[i] = (char)(t % 85 + 0x21);
+ t /= 85;
+ }
+ for (i = 0; i <= n; ++i) {
+ *bufEnd++ = buf1[i];
+ if (++lineLen == 65) {
+ *bufEnd++ = '\n';
+ lineLen = 0;
+ }
+ }
+ }
+ }
+ if (n < 4) {
+ *bufEnd++ = '~';
+ *bufEnd++ = '>';
+ eof = gTrue;
+ }
+ return bufPtr < bufEnd;
+}
+
+//------------------------------------------------------------------------
+// RunLengthEncoder
+//------------------------------------------------------------------------
+
+RunLengthEncoder::RunLengthEncoder(Stream *strA):
+ FilterStream(strA) {
+ bufPtr = bufEnd = nextEnd = buf;
+ eof = gFalse;
+}
+
+RunLengthEncoder::~RunLengthEncoder() {
+ if (str->isEncoder())
+ delete str;
+}
+
+void RunLengthEncoder::reset() {
+ str->reset();
+ bufPtr = bufEnd = nextEnd = buf;
+ eof = gFalse;
+}
+
+//
+// When fillBuf finishes, buf[] looks like this:
+// +-----+--------------+-----------------+--
+// + tag | ... data ... | next 0, 1, or 2 |
+// +-----+--------------+-----------------+--
+// ^ ^ ^
+// bufPtr bufEnd nextEnd
+//
+GBool RunLengthEncoder::fillBuf() {
+ int c, c1, c2;
+ int n;
+
+ // already hit EOF?
+ if (eof)
+ return gFalse;
+
+ // grab two bytes
+ if (nextEnd < bufEnd + 1) {
+ if ((c1 = str->getChar()) == EOF) {
+ eof = gTrue;
+ return gFalse;
+ }
+ } else {
+ c1 = bufEnd[0] & 0xff;
+ }
+ if (nextEnd < bufEnd + 2) {
+ if ((c2 = str->getChar()) == EOF) {
+ eof = gTrue;
+ buf[0] = 0;
+ buf[1] = c1;
+ bufPtr = buf;
+ bufEnd = &buf[2];
+ return gTrue;
+ }
+ } else {
+ c2 = bufEnd[1] & 0xff;
+ }
+
+ // check for repeat
+ c = 0; // make gcc happy
+ if (c1 == c2) {
+ n = 2;
+ while (n < 128 && (c = str->getChar()) == c1)
+ ++n;
+ buf[0] = (char)(257 - n);
+ buf[1] = c1;
+ bufEnd = &buf[2];
+ if (c == EOF) {
+ eof = gTrue;
+ } else if (n < 128) {
+ buf[2] = c;
+ nextEnd = &buf[3];
+ } else {
+ nextEnd = bufEnd;
+ }
+
+ // get up to 128 chars
+ } else {
+ buf[1] = c1;
+ buf[2] = c2;
+ n = 2;
+ while (n < 128) {
+ if ((c = str->getChar()) == EOF) {
+ eof = gTrue;
+ break;
+ }
+ ++n;
+ buf[n] = c;
+ if (buf[n] == buf[n-1])
+ break;
+ }
+ if (buf[n] == buf[n-1]) {
+ buf[0] = (char)(n-2-1);
+ bufEnd = &buf[n-1];
+ nextEnd = &buf[n+1];
+ } else {
+ buf[0] = (char)(n-1);
+ bufEnd = nextEnd = &buf[n+1];
+ }
+ }
+ bufPtr = buf;
+ return gTrue;
+}
diff --git a/pdftops/Stream.h b/pdftops/Stream.h
new file mode 100644
index 000000000..a602ff592
--- /dev/null
+++ b/pdftops/Stream.h
@@ -0,0 +1,842 @@
+//========================================================================
+//
+// Stream.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef STREAM_H
+#define STREAM_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include <stdio.h>
+#include "gtypes.h"
+#include "Object.h"
+
+#ifndef NO_DECRYPTION
+class Decrypt;
+#endif
+class BaseStream;
+
+//------------------------------------------------------------------------
+
+enum StreamKind {
+ strFile,
+ strASCIIHex,
+ strASCII85,
+ strLZW,
+ strRunLength,
+ strCCITTFax,
+ strDCT,
+ strFlate,
+ strJBIG2,
+ strWeird // internal-use stream types
+};
+
+//------------------------------------------------------------------------
+// Stream (base class)
+//------------------------------------------------------------------------
+
+class Stream {
+public:
+
+ // Constructor.
+ Stream();
+
+ // Destructor.
+ virtual ~Stream();
+
+ // Reference counting.
+ int incRef() { return ++ref; }
+ int decRef() { return --ref; }
+
+ // Get kind of stream.
+ virtual StreamKind getKind() = 0;
+
+ // Reset stream to beginning.
+ virtual void reset() = 0;
+
+ // Close down the stream.
+ virtual void close();
+
+ // Get next char from stream.
+ virtual int getChar() = 0;
+
+ // Peek at next char in stream.
+ virtual int lookChar() = 0;
+
+ // Get next char from stream without using the predictor.
+ // This is only used by StreamPredictor.
+ virtual int getRawChar();
+
+ // Get next line from stream.
+ virtual char *getLine(char *buf, int size);
+
+ // Get current position in file.
+ virtual int getPos() = 0;
+
+ // Go to a position in the stream. If <dir> is negative, the
+ // position is from the end of the file; otherwise the position is
+ // from the start of the file.
+ virtual void setPos(Guint pos, int dir = 0) = 0;
+
+ // Get PostScript command for the filter(s).
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+
+ // Does this stream type potentially contain non-printable chars?
+ virtual GBool isBinary(GBool last = gTrue) = 0;
+
+ // Get the BaseStream or EmbedStream of this stream.
+ virtual BaseStream *getBaseStream() = 0;
+
+ // Get the dictionary associated with this stream.
+ virtual Dict *getDict() = 0;
+
+ // Is this an encoding filter?
+ virtual GBool isEncoder() { return gFalse; }
+
+ // Add filters to this stream according to the parameters in <dict>.
+ // Returns the new stream.
+ Stream *addFilters(Object *dict);
+
+ // Tell this stream to ignore any length limitation -- this only
+ // applies to BaseStream subclasses, and is used as a hack to work
+ // around broken PDF files with incorrect stream lengths.
+ virtual void ignoreLength() {}
+
+private:
+
+ Stream *makeFilter(const char *name, Stream *str, Object *params);
+
+ int ref; // reference count
+};
+
+//------------------------------------------------------------------------
+// BaseStream
+//
+// This is the base class for all streams that read directly from a file.
+//------------------------------------------------------------------------
+
+class BaseStream: public Stream {
+public:
+
+ BaseStream(Object *dictA);
+ virtual ~BaseStream();
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dict) = 0;
+ virtual void setPos(Guint pos, int dir = 0) = 0;
+ virtual BaseStream *getBaseStream() { return this; }
+ virtual Dict *getDict() { return dict.getDict(); }
+
+ // Get/set position of first byte of stream within the file.
+ virtual Guint getStart() = 0;
+ virtual void moveStart(int delta) = 0;
+
+#ifndef NO_DECRYPTION
+ // Set decryption for this stream.
+ virtual void doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen);
+#endif
+
+#ifndef NO_DECRYPTION
+protected:
+
+ Decrypt *decrypt;
+#endif
+
+private:
+
+ Object dict;
+};
+
+//------------------------------------------------------------------------
+// FilterStream
+//
+// This is the base class for all streams that filter another stream.
+//------------------------------------------------------------------------
+
+class FilterStream: public Stream {
+public:
+
+ FilterStream(Stream *strA);
+ virtual ~FilterStream();
+ virtual void close();
+ virtual int getPos() { return str->getPos(); }
+ virtual void setPos(Guint pos, int dir = 0);
+ virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
+ virtual Dict *getDict() { return str->getDict(); }
+ virtual void ignoreLength() { str->ignoreLength(); }
+
+protected:
+
+ Stream *str;
+};
+
+//------------------------------------------------------------------------
+// ImageStream
+//------------------------------------------------------------------------
+
+class ImageStream {
+public:
+
+ // Create an image stream object for an image with the specified
+ // parameters. Note that these are the actual image parameters,
+ // which may be different from the predictor parameters.
+ ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
+
+ ~ImageStream();
+
+ // Reset the stream.
+ void reset();
+
+ // Gets the next pixel from the stream. <pix> should be able to hold
+ // at least nComps elements. Returns false at end of file.
+ GBool getPixel(Guchar *pix);
+
+ // Returns a pointer to the next line of pixels. Returns NULL at
+ // end of file.
+ Guchar *getLine();
+
+ // Skip an entire line from the image.
+ void skipLine();
+
+private:
+
+ Stream *str; // base stream
+ int width; // pixels per line
+ int nComps; // components per pixel
+ int nBits; // bits per component
+ int nVals; // components per line
+ Guchar *imgLine; // line buffer
+ int imgIdx; // current index in imgLine
+};
+
+//------------------------------------------------------------------------
+// StreamPredictor
+//------------------------------------------------------------------------
+
+class StreamPredictor {
+public:
+
+ // Create a predictor object. Note that the parameters are for the
+ // predictor, and may not match the actual image parameters.
+ StreamPredictor(Stream *strA, int predictorA,
+ int widthA, int nCompsA, int nBitsA);
+
+ ~StreamPredictor();
+
+ int lookChar();
+ int getChar();
+
+private:
+
+ GBool getNextLine();
+
+ Stream *str; // base stream
+ int predictor; // predictor
+ int width; // pixels per line
+ int nComps; // components per pixel
+ int nBits; // bits per component
+ int nVals; // components per line
+ int pixBytes; // bytes per pixel
+ int rowBytes; // bytes per line
+ Guchar *predLine; // line buffer
+ int predIdx; // current index in predLine
+};
+
+//------------------------------------------------------------------------
+// FileStream
+//------------------------------------------------------------------------
+
+#define fileStreamBufSize 256
+
+class FileStream: public BaseStream {
+public:
+
+ FileStream(FILE *fA, Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA);
+ virtual ~FileStream();
+ virtual Stream *makeSubStream(Guint startA, GBool limitedA,
+ Guint lengthA, Object *dictA);
+ virtual StreamKind getKind() { return strFile; }
+ virtual void reset();
+ virtual void close();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual int getPos() { return bufPos + (bufPtr - buf); }
+ virtual void setPos(Guint pos, int dir = 0);
+ virtual GBool isBinary(GBool last = gTrue) { return last; }
+ virtual void ignoreLength() { limited = gFalse; }
+ virtual Guint getStart() { return start; }
+ virtual void moveStart(int delta);
+
+private:
+
+ GBool fillBuf();
+
+ FILE *f;
+ Guint start;
+ GBool limited;
+ Guint length;
+ char buf[fileStreamBufSize];
+ char *bufPtr;
+ char *bufEnd;
+ Guint bufPos;
+ int savePos;
+ GBool saved;
+};
+
+//------------------------------------------------------------------------
+// MemStream
+//------------------------------------------------------------------------
+
+class MemStream: public BaseStream {
+public:
+
+ MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
+ virtual ~MemStream();
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint lengthA, Object *dictA);
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual void close();
+ virtual int getChar()
+ { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
+ virtual int lookChar()
+ { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
+ virtual int getPos() { return (int)(bufPtr - buf); }
+ virtual void setPos(Guint pos, int dir = 0);
+ virtual GBool isBinary(GBool last = gTrue) { return last; }
+ virtual Guint getStart() { return start; }
+ virtual void moveStart(int delta);
+#ifndef NO_DECRYPTION
+ virtual void doDecryption(Guchar *fileKey, int keyLength,
+ int objNum, int objGen);
+#endif
+
+private:
+
+ char *buf;
+ Guint start;
+ Guint length;
+ char *bufEnd;
+ char *bufPtr;
+ GBool needFree;
+};
+
+//------------------------------------------------------------------------
+// EmbedStream
+//
+// This is a special stream type used for embedded streams (inline
+// images). It reads directly from the base stream -- after the
+// EmbedStream is deleted, reads from the base stream will proceed where
+// the BaseStream left off. Note that this is very different behavior
+// that creating a new FileStream (using makeSubStream).
+//------------------------------------------------------------------------
+
+class EmbedStream: public BaseStream {
+public:
+
+ EmbedStream(Stream *strA, Object *dictA);
+ virtual ~EmbedStream();
+ virtual Stream *makeSubStream(Guint start, GBool limited,
+ Guint length, Object *dictA);
+ virtual StreamKind getKind() { return str->getKind(); }
+ virtual void reset() {}
+ virtual int getChar() { return str->getChar(); }
+ virtual int lookChar() { return str->lookChar(); }
+ virtual int getPos() { return str->getPos(); }
+ virtual void setPos(Guint pos, int dir = 0);
+ virtual GBool isBinary(GBool last = gTrue) { return last; }
+ virtual Guint getStart();
+ virtual void moveStart(int delta);
+
+private:
+
+ Stream *str;
+};
+
+//------------------------------------------------------------------------
+// ASCIIHexStream
+//------------------------------------------------------------------------
+
+class ASCIIHexStream: public FilterStream {
+public:
+
+ ASCIIHexStream(Stream *strA);
+ virtual ~ASCIIHexStream();
+ virtual StreamKind getKind() { return strASCIIHex; }
+ virtual void reset();
+ virtual int getChar()
+ { int c = lookChar(); buf = EOF; return c; }
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ int buf;
+ GBool eof;
+};
+
+//------------------------------------------------------------------------
+// ASCII85Stream
+//------------------------------------------------------------------------
+
+class ASCII85Stream: public FilterStream {
+public:
+
+ ASCII85Stream(Stream *strA);
+ virtual ~ASCII85Stream();
+ virtual StreamKind getKind() { return strASCII85; }
+ virtual void reset();
+ virtual int getChar()
+ { int ch = lookChar(); ++index; return ch; }
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ int c[5];
+ int b[4];
+ int index, n;
+ GBool eof;
+};
+
+//------------------------------------------------------------------------
+// LZWStream
+//------------------------------------------------------------------------
+
+class LZWStream: public FilterStream {
+public:
+
+ LZWStream(Stream *strA, int predictor, int columns, int colors,
+ int bits, int earlyA);
+ virtual ~LZWStream();
+ virtual StreamKind getKind() { return strLZW; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual int getRawChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ StreamPredictor *pred; // predictor
+ int early; // early parameter
+ GBool eof; // true if at eof
+ int inputBuf; // input buffer
+ int inputBits; // number of bits in input buffer
+ struct { // decoding table
+ int length;
+ int head;
+ Guchar tail;
+ } table[4097];
+ int nextCode; // next code to be used
+ int nextBits; // number of bits in next code word
+ int prevCode; // previous code used in stream
+ int newChar; // next char to be added to table
+ Guchar seqBuf[4097]; // buffer for current sequence
+ int seqLength; // length of current sequence
+ int seqIndex; // index into current sequence
+ GBool first; // first code after a table clear
+
+ GBool processNextCode();
+ void clearTable();
+ int getCode();
+};
+
+//------------------------------------------------------------------------
+// RunLengthStream
+//------------------------------------------------------------------------
+
+class RunLengthStream: public FilterStream {
+public:
+
+ RunLengthStream(Stream *strA);
+ virtual ~RunLengthStream();
+ virtual StreamKind getKind() { return strRunLength; }
+ virtual void reset();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ char buf[128]; // buffer
+ char *bufPtr; // next char to read
+ char *bufEnd; // end of buffer
+ GBool eof;
+
+ GBool fillBuf();
+};
+
+//------------------------------------------------------------------------
+// CCITTFaxStream
+//------------------------------------------------------------------------
+
+struct CCITTCodeTable;
+
+class CCITTFaxStream: public FilterStream {
+public:
+
+ CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
+ GBool byteAlignA, int columnsA, int rowsA,
+ GBool endOfBlockA, GBool blackA);
+ virtual ~CCITTFaxStream();
+ virtual StreamKind getKind() { return strCCITTFax; }
+ virtual void reset();
+ virtual int getChar()
+ { int c = lookChar(); buf = EOF; return c; }
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ int encoding; // 'K' parameter
+ GBool endOfLine; // 'EndOfLine' parameter
+ GBool byteAlign; // 'EncodedByteAlign' parameter
+ int columns; // 'Columns' parameter
+ int rows; // 'Rows' parameter
+ GBool endOfBlock; // 'EndOfBlock' parameter
+ GBool black; // 'BlackIs1' parameter
+ GBool eof; // true if at eof
+ GBool nextLine2D; // true if next line uses 2D encoding
+ int row; // current row
+ int inputBuf; // input buffer
+ int inputBits; // number of bits in input buffer
+ short *refLine; // reference line changing elements
+ int b1; // index into refLine
+ short *codingLine; // coding line changing elements
+ int a0; // index into codingLine
+ int outputBits; // remaining ouput bits
+ int buf; // character buffer
+
+ short getTwoDimCode();
+ short getWhiteCode();
+ short getBlackCode();
+ short lookBits(int n);
+ void eatBits(int n) { inputBits -= n; }
+};
+
+//------------------------------------------------------------------------
+// DCTStream
+//------------------------------------------------------------------------
+
+// DCT component info
+struct DCTCompInfo {
+ int id; // component ID
+ int hSample, vSample; // horiz/vert sampling resolutions
+ int quantTable; // quantization table number
+ int prevDC; // DC coefficient accumulator
+};
+
+struct DCTScanInfo {
+ GBool comp[4]; // comp[i] is set if component i is
+ // included in this scan
+ int numComps; // number of components in the scan
+ int dcHuffTable[4]; // DC Huffman table numbers
+ int acHuffTable[4]; // AC Huffman table numbers
+ int firstCoeff, lastCoeff; // first and last DCT coefficient
+ int ah, al; // successive approximation parameters
+};
+
+// DCT Huffman decoding table
+struct DCTHuffTable {
+ Guchar firstSym[17]; // first symbol for this bit length
+ Gushort firstCode[17]; // first code for this bit length
+ Gushort numCodes[17]; // number of codes of this bit length
+ Guchar sym[256]; // symbols
+};
+
+class DCTStream: public FilterStream {
+public:
+
+ DCTStream(Stream *strA);
+ virtual ~DCTStream();
+ virtual StreamKind getKind() { return strDCT; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+ Stream *getRawStream() { return str; }
+
+private:
+
+ GBool progressive; // set if in progressive mode
+ GBool interleaved; // set if in interleaved mode
+ int width, height; // image size
+ int mcuWidth, mcuHeight; // size of min coding unit, in data units
+ int bufWidth, bufHeight; // frameBuf size
+ DCTCompInfo compInfo[4]; // info for each component
+ DCTScanInfo scanInfo; // info for the current scan
+ int numComps; // number of components in image
+ int colorXform; // need YCbCr-to-RGB transform?
+ GBool gotJFIFMarker; // set if APP0 JFIF marker was present
+ GBool gotAdobeMarker; // set if APP14 Adobe marker was present
+ int restartInterval; // restart interval, in MCUs
+ Guchar quantTables[4][64]; // quantization tables
+ int numQuantTables; // number of quantization tables
+ DCTHuffTable dcHuffTables[4]; // DC Huffman tables
+ DCTHuffTable acHuffTables[4]; // AC Huffman tables
+ int numDCHuffTables; // number of DC Huffman tables
+ int numACHuffTables; // number of AC Huffman tables
+ Guchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
+ int *frameBuf[4]; // buffer for frame (progressive mode)
+ int comp, x, y, dy; // current position within image/MCU
+ int restartCtr; // MCUs left until restart
+ int restartMarker; // next restart marker
+ int eobRun; // number of EOBs left in the current run
+ int inputBuf; // input buffer for variable length codes
+ int inputBits; // number of valid bits in input buffer
+
+ void restart();
+ GBool readMCURow();
+ void readScan();
+ GBool readDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+ DCTHuffTable *acHuffTable,
+ int *prevDC, int data[64]);
+ void decodeImage();
+ void transformDataUnit(Guchar *quantTable,
+ int dataIn[64], Guchar dataOut[64]);
+ int readHuffSym(DCTHuffTable *table);
+ int readAmp(int size);
+ int readBit();
+ GBool readHeader();
+ GBool readBaselineSOF();
+ GBool readProgressiveSOF();
+ GBool readScanInfo();
+ GBool readQuantTables();
+ GBool readHuffmanTables();
+ GBool readRestartInterval();
+ GBool readJFIFMarker();
+ GBool readAdobeMarker();
+ GBool readTrailer();
+ int readMarker();
+ int read16();
+};
+
+//------------------------------------------------------------------------
+// FlateStream
+//------------------------------------------------------------------------
+
+#define flateWindow 32768 // buffer size
+#define flateMask (flateWindow-1)
+#define flateMaxHuffman 15 // max Huffman code length
+#define flateMaxCodeLenCodes 19 // max # code length codes
+#define flateMaxLitCodes 288 // max # literal codes
+#define flateMaxDistCodes 30 // max # distance codes
+
+// Huffman code table entry
+struct FlateCode {
+ Gushort len; // code length, in bits
+ Gushort val; // value represented by this code
+};
+
+struct FlateHuffmanTab {
+ FlateCode *codes;
+ int maxLen;
+};
+
+// Decoding info for length and distance code words
+struct FlateDecode {
+ int bits; // # extra bits
+ int first; // first length/distance
+};
+
+class FlateStream: public FilterStream {
+public:
+
+ FlateStream(Stream *strA, int predictor, int columns,
+ int colors, int bits);
+ virtual ~FlateStream();
+ virtual StreamKind getKind() { return strFlate; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual int getRawChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent);
+ virtual GBool isBinary(GBool last = gTrue);
+
+private:
+
+ StreamPredictor *pred; // predictor
+ Guchar buf[flateWindow]; // output data buffer
+ int index; // current index into output buffer
+ int remain; // number valid bytes in output buffer
+ int codeBuf; // input buffer
+ int codeSize; // number of bits in input buffer
+ int // literal and distance code lengths
+ codeLengths[flateMaxLitCodes + flateMaxDistCodes];
+ FlateHuffmanTab litCodeTab; // literal code table
+ FlateHuffmanTab distCodeTab; // distance code table
+ GBool compressedBlock; // set if reading a compressed block
+ int blockLen; // remaining length of uncompressed block
+ GBool endOfBlock; // set when end of block is reached
+ GBool eof; // set when end of stream is reached
+
+ static int // code length code reordering
+ codeLenCodeMap[flateMaxCodeLenCodes];
+ static FlateDecode // length decoding info
+ lengthDecode[flateMaxLitCodes-257];
+ static FlateDecode // distance decoding info
+ distDecode[flateMaxDistCodes];
+
+ void readSome();
+ GBool startBlock();
+ void loadFixedCodes();
+ GBool readDynamicCodes();
+ void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
+ int getHuffmanCodeWord(FlateHuffmanTab *tab);
+ int getCodeWord(int bits);
+};
+
+//------------------------------------------------------------------------
+// EOFStream
+//------------------------------------------------------------------------
+
+class EOFStream: public FilterStream {
+public:
+
+ EOFStream(Stream *strA);
+ virtual ~EOFStream();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset() {}
+ virtual int getChar() { return EOF; }
+ virtual int lookChar() { return EOF; }
+ virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+};
+
+//------------------------------------------------------------------------
+// FixedLengthEncoder
+//------------------------------------------------------------------------
+
+class FixedLengthEncoder: public FilterStream {
+public:
+
+ FixedLengthEncoder(Stream *strA, int lengthA);
+ ~FixedLengthEncoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar();
+ virtual int lookChar();
+ virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ int length;
+ int count;
+};
+
+//------------------------------------------------------------------------
+// ASCIIHexEncoder
+//------------------------------------------------------------------------
+
+class ASCIIHexEncoder: public FilterStream {
+public:
+
+ ASCIIHexEncoder(Stream *strA);
+ virtual ~ASCIIHexEncoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ char buf[4];
+ char *bufPtr;
+ char *bufEnd;
+ int lineLen;
+ GBool eof;
+
+ GBool fillBuf();
+};
+
+//------------------------------------------------------------------------
+// ASCII85Encoder
+//------------------------------------------------------------------------
+
+class ASCII85Encoder: public FilterStream {
+public:
+
+ ASCII85Encoder(Stream *strA);
+ virtual ~ASCII85Encoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ char buf[8];
+ char *bufPtr;
+ char *bufEnd;
+ int lineLen;
+ GBool eof;
+
+ GBool fillBuf();
+};
+
+//------------------------------------------------------------------------
+// RunLengthEncoder
+//------------------------------------------------------------------------
+
+class RunLengthEncoder: public FilterStream {
+public:
+
+ RunLengthEncoder(Stream *strA);
+ virtual ~RunLengthEncoder();
+ virtual StreamKind getKind() { return strWeird; }
+ virtual void reset();
+ virtual int getChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+ virtual int lookChar()
+ { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+ virtual GString *getPSFilter(int psLevel, const char *indent) { return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+ char buf[131];
+ char *bufPtr;
+ char *bufEnd;
+ char *nextEnd;
+ GBool eof;
+
+ GBool fillBuf();
+};
+
+#endif
diff --git a/pdftops/UTF8.h b/pdftops/UTF8.h
new file mode 100644
index 000000000..8536dbf94
--- /dev/null
+++ b/pdftops/UTF8.h
@@ -0,0 +1,56 @@
+//========================================================================
+//
+// UTF8.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+static int mapUTF8(Unicode u, char *buf, int bufSize) {
+ if (u <= 0x0000007f) {
+ if (bufSize < 1) {
+ return 0;
+ }
+ buf[0] = (char)u;
+ return 1;
+ } else if (u <= 0x000007ff) {
+ if (bufSize < 2) {
+ return 0;
+ }
+ buf[0] = (char)(0xc0 + (u >> 6));
+ buf[1] = (char)(0x80 + (u & 0x3f));
+ return 2;
+ } else if (u <= 0x0000ffff) {
+ if (bufSize < 3) {
+ return 0;
+ }
+ buf[0] = (char)(0xe0 + (u >> 12));
+ buf[1] = (char)(0x80 + ((u >> 6) & 0x3f));
+ buf[2] = (char)(0x80 + (u & 0x3f));
+ return 3;
+ } else if (u <= 0x0010ffff) {
+ if (bufSize < 4) {
+ return 0;
+ }
+ buf[0] = (char)(0xf0 + (u >> 18));
+ buf[1] = (char)(0x80 + ((u >> 12) & 0x3f));
+ buf[2] = (char)(0x80 + ((u >> 6) & 0x3f));
+ buf[3] = (char)(0x80 + (u & 0x3f));
+ return 4;
+ } else {
+ return 0;
+ }
+}
+
+static int mapUCS2(Unicode u, char *buf, int bufSize) {
+ if (u <= 0xffff) {
+ if (bufSize < 2) {
+ return 0;
+ }
+ buf[0] = (char)((u >> 8) & 0xff);
+ buf[1] = (char)(u & 0xff);
+ return 2;
+ } else {
+ return 0;
+ }
+}
diff --git a/pdftops/UnicodeMap.cxx b/pdftops/UnicodeMap.cxx
new file mode 100644
index 000000000..e77b11c6e
--- /dev/null
+++ b/pdftops/UnicodeMap.cxx
@@ -0,0 +1,293 @@
+//========================================================================
+//
+// UnicodeMap.cc
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "gmem.h"
+#include "gfile.h"
+#include "GString.h"
+#include "GList.h"
+#include "Error.h"
+#include "GlobalParams.h"
+#include "UnicodeMap.h"
+
+//------------------------------------------------------------------------
+
+#define maxExtCode 16
+
+struct UnicodeMapExt {
+ Unicode u; // Unicode char
+ char code[maxExtCode];
+ Guint nBytes;
+};
+
+//------------------------------------------------------------------------
+
+UnicodeMap *UnicodeMap::parse(GString *encodingNameA) {
+ FILE *f;
+ UnicodeMap *map;
+ UnicodeMapRange *range;
+ UnicodeMapExt *eMap;
+ int size, eMapsSize;
+ char buf[256];
+ int line, nBytes, i, x;
+ char *tok1, *tok2, *tok3;
+
+ if (!(f = globalParams->getUnicodeMapFile(encodingNameA))) {
+ error(-1, "Couldn't find unicodeMap file for the '%s' encoding",
+ encodingNameA->getCString());
+ return NULL;
+ }
+
+ map = new UnicodeMap(encodingNameA->copy());
+
+ size = 8;
+ map->ranges = (UnicodeMapRange *)gmalloc(size * sizeof(UnicodeMapRange));
+ eMapsSize = 0;
+
+ line = 1;
+ while (getLine(buf, sizeof(buf), f)) {
+ if ((tok1 = strtok(buf, " \t\r\n")) &&
+ (tok2 = strtok(NULL, " \t\r\n"))) {
+ if (!(tok3 = strtok(NULL, " \t\r\n"))) {
+ tok3 = tok2;
+ tok2 = tok1;
+ }
+ nBytes = strlen(tok3) / 2;
+ if (nBytes <= 4) {
+ if (map->len == size) {
+ size *= 2;
+ map->ranges = (UnicodeMapRange *)
+ grealloc(map->ranges, size * sizeof(UnicodeMapRange));
+ }
+ range = &map->ranges[map->len];
+ sscanf(tok1, "%x", &range->start);
+ sscanf(tok2, "%x", &range->end);
+ sscanf(tok3, "%x", &range->code);
+ range->nBytes = nBytes;
+ ++map->len;
+ } else if (tok2 == tok1) {
+ if (map->eMapsLen == eMapsSize) {
+ eMapsSize += 16;
+ map->eMaps = (UnicodeMapExt *)
+ grealloc(map->eMaps, eMapsSize * sizeof(UnicodeMapExt));
+ }
+ eMap = &map->eMaps[map->eMapsLen];
+ sscanf(tok1, "%x", &eMap->u);
+ for (i = 0; i < nBytes; ++i) {
+ sscanf(tok3 + i*2, "%2x", &x);
+ eMap->code[i] = (char)x;
+ }
+ eMap->nBytes = nBytes;
+ ++map->eMapsLen;
+ } else {
+ error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
+ line, encodingNameA->getCString());
+ }
+ } else {
+ error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding",
+ line, encodingNameA->getCString());
+ }
+ ++line;
+ }
+
+ fclose(f);
+
+ return map;
+}
+
+UnicodeMap::UnicodeMap(GString *encodingNameA) {
+ encodingName = encodingNameA;
+ unicodeOut = gFalse;
+ kind = unicodeMapUser;
+ ranges = NULL;
+ len = 0;
+ eMaps = NULL;
+ eMapsLen = 0;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapRange *rangesA, int lenA) {
+ encodingName = new GString(encodingNameA);
+ unicodeOut = unicodeOutA;
+ kind = unicodeMapResident;
+ ranges = rangesA;
+ len = lenA;
+ eMaps = NULL;
+ eMapsLen = 0;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+UnicodeMap::UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapFunc funcA) {
+ encodingName = new GString(encodingNameA);
+ unicodeOut = unicodeOutA;
+ kind = unicodeMapFunc;
+ func = funcA;
+ eMaps = NULL;
+ eMapsLen = 0;
+ refCnt = 1;
+#if MULTITHREADED
+ gInitMutex(&mutex);
+#endif
+}
+
+UnicodeMap::~UnicodeMap() {
+ delete encodingName;
+ if (kind == unicodeMapUser && ranges) {
+ gfree(ranges);
+ }
+ if (eMaps) {
+ gfree(eMaps);
+ }
+#if MULTITHREADED
+ gDestroyMutex(&mutex);
+#endif
+}
+
+void UnicodeMap::incRefCnt() {
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ ++refCnt;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+}
+
+void UnicodeMap::decRefCnt() {
+ GBool done;
+
+#if MULTITHREADED
+ gLockMutex(&mutex);
+#endif
+ done = --refCnt == 0;
+#if MULTITHREADED
+ gUnlockMutex(&mutex);
+#endif
+ if (done) {
+ delete this;
+ }
+}
+
+GBool UnicodeMap::match(GString *encodingNameA) {
+ return !encodingName->cmp(encodingNameA);
+}
+
+int UnicodeMap::mapUnicode(Unicode u, char *buf, int bufSize) {
+ int a, b, m, n, i, j;
+ Guint code;
+
+ if (kind == unicodeMapFunc) {
+ return (*func)(u, buf, bufSize);
+ }
+
+ a = 0;
+ b = len;
+ if (u >= ranges[a].start) {
+ // invariant: ranges[a].start <= u < ranges[b].start
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (u >= ranges[m].start) {
+ a = m;
+ } else if (u < ranges[m].start) {
+ b = m;
+ }
+ }
+ if (u <= ranges[a].end) {
+ n = ranges[a].nBytes;
+ if (n > bufSize) {
+ return 0;
+ }
+ code = ranges[a].code + (u - ranges[a].start);
+ for (i = n - 1; i >= 0; --i) {
+ buf[i] = (char)(code & 0xff);
+ code >>= 8;
+ }
+ return n;
+ }
+ }
+
+ for (i = 0; i < eMapsLen; ++i) {
+ if (eMaps[i].u == u) {
+ n = eMaps[i].nBytes;
+ for (j = 0; j < n; ++j) {
+ buf[j] = eMaps[i].code[j];
+ }
+ return n;
+ }
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+
+UnicodeMapCache::UnicodeMapCache() {
+ int i;
+
+ for (i = 0; i < unicodeMapCacheSize; ++i) {
+ cache[i] = NULL;
+ }
+}
+
+UnicodeMapCache::~UnicodeMapCache() {
+ int i;
+
+ for (i = 0; i < unicodeMapCacheSize; ++i) {
+ if (cache[i]) {
+ cache[i]->decRefCnt();
+ }
+ }
+}
+
+UnicodeMap *UnicodeMapCache::getUnicodeMap(GString *encodingName) {
+ UnicodeMap *map;
+ int i, j;
+
+ if (cache[0] && cache[0]->match(encodingName)) {
+ cache[0]->incRefCnt();
+ return cache[0];
+ }
+ for (i = 1; i < unicodeMapCacheSize; ++i) {
+ if (cache[i] && cache[i]->match(encodingName)) {
+ map = cache[i];
+ for (j = i; j >= 1; --j) {
+ cache[j] = cache[j - 1];
+ }
+ cache[0] = map;
+ map->incRefCnt();
+ return map;
+ }
+ }
+ if ((map = UnicodeMap::parse(encodingName))) {
+ if (cache[unicodeMapCacheSize - 1]) {
+ cache[unicodeMapCacheSize - 1]->decRefCnt();
+ }
+ for (j = unicodeMapCacheSize - 1; j >= 1; --j) {
+ cache[j] = cache[j - 1];
+ }
+ cache[0] = map;
+ map->incRefCnt();
+ return map;
+ }
+ return NULL;
+}
diff --git a/pdftops/UnicodeMap.h b/pdftops/UnicodeMap.h
new file mode 100644
index 000000000..d61e0cebc
--- /dev/null
+++ b/pdftops/UnicodeMap.h
@@ -0,0 +1,123 @@
+//========================================================================
+//
+// UnicodeMap.h
+//
+// Mapping from Unicode to an encoding.
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef UNICODEMAP_H
+#define UNICODEMAP_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "CharTypes.h"
+
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
+class GString;
+
+//------------------------------------------------------------------------
+
+enum UnicodeMapKind {
+ unicodeMapUser, // read from a file
+ unicodeMapResident, // static list of ranges
+ unicodeMapFunc // function pointer
+};
+
+typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize);
+
+struct UnicodeMapRange {
+ Unicode start, end; // range of Unicode chars
+ Guint code, nBytes; // first output code
+};
+
+struct UnicodeMapExt;
+
+//------------------------------------------------------------------------
+
+class UnicodeMap {
+public:
+
+ // Create the UnicodeMap specified by <encodingName>. Sets the
+ // initial reference count to 1. Returns NULL on failure.
+ static UnicodeMap *parse(GString *encodingNameA);
+
+ // Create a resident UnicodeMap.
+ UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapRange *rangesA, int lenA);
+
+ // Create a resident UnicodeMap that uses a function instead of a
+ // list of ranges.
+ UnicodeMap(const char *encodingNameA, GBool unicodeOutA,
+ UnicodeMapFunc funcA);
+
+ ~UnicodeMap();
+
+ void incRefCnt();
+ void decRefCnt();
+
+ GString *getEncodingName() { return encodingName; }
+
+ GBool isUnicode() { return unicodeOut; }
+
+ // Return true if this UnicodeMap matches the specified
+ // <encodingNameA>.
+ GBool match(GString *encodingNameA);
+
+ // Map Unicode to the target encoding. Fills in <buf> with the
+ // output and returns the number of bytes used. Output will be
+ // truncated at <bufSize> bytes. No string terminator is written.
+ // Returns 0 if no mapping is found.
+ int mapUnicode(Unicode u, char *buf, int bufSize);
+
+private:
+
+ UnicodeMap(GString *encodingNameA);
+
+ GString *encodingName;
+ UnicodeMapKind kind;
+ GBool unicodeOut;
+ union {
+ UnicodeMapRange *ranges; // (user, resident)
+ UnicodeMapFunc func; // (func)
+ };
+ int len; // (user, resident)
+ UnicodeMapExt *eMaps; // (user)
+ int eMapsLen; // (user)
+ int refCnt;
+#ifdef MULTITHREADED
+ GMutex mutex;
+#endif
+};
+
+//------------------------------------------------------------------------
+
+#define unicodeMapCacheSize 4
+
+class UnicodeMapCache {
+public:
+
+ UnicodeMapCache();
+ ~UnicodeMapCache();
+
+ // Get the UnicodeMap for <encodingName>. Increments its reference
+ // count; there will be one reference for the cache plus one for the
+ // caller of this function. Returns NULL on failure.
+ UnicodeMap *getUnicodeMap(GString *encodingName);
+
+private:
+
+ UnicodeMap *cache[unicodeMapCacheSize];
+};
+
+#endif
diff --git a/pdftops/UnicodeMapTables.h b/pdftops/UnicodeMapTables.h
new file mode 100644
index 000000000..9c5103461
--- /dev/null
+++ b/pdftops/UnicodeMapTables.h
@@ -0,0 +1,361 @@
+//========================================================================
+//
+// UnicodeMapTables.h
+//
+// Copyright 2001-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+static UnicodeMapRange latin1UnicodeMapRanges[] = {
+ { 0x000a, 0x000a, 0x0a, 1 },
+ { 0x000c, 0x000d, 0x0c, 1 },
+ { 0x0020, 0x007e, 0x20, 1 },
+ { 0x00a0, 0x00a0, 0x20, 1 },
+ { 0x00a1, 0x00ac, 0xa1, 1 },
+ { 0x00ae, 0x00ff, 0xae, 1 },
+ { 0x010c, 0x010c, 0x43, 1 },
+ { 0x010d, 0x010d, 0x63, 1 },
+ { 0x0131, 0x0131, 0x69, 1 },
+ { 0x0141, 0x0141, 0x4c, 1 },
+ { 0x0142, 0x0142, 0x6c, 1 },
+ { 0x0152, 0x0152, 0x4f45, 2 },
+ { 0x0153, 0x0153, 0x6f65, 2 },
+ { 0x0160, 0x0160, 0x53, 1 },
+ { 0x0161, 0x0161, 0x73, 1 },
+ { 0x0178, 0x0178, 0x59, 1 },
+ { 0x017d, 0x017d, 0x5a, 1 },
+ { 0x017e, 0x017e, 0x7a, 1 },
+ { 0x02c6, 0x02c6, 0x5e, 1 },
+ { 0x02da, 0x02da, 0xb0, 1 },
+ { 0x02dc, 0x02dc, 0x7e, 1 },
+ { 0x2013, 0x2013, 0xad, 1 },
+ { 0x2014, 0x2014, 0x2d2d, 2 },
+ { 0x2018, 0x2018, 0x60, 1 },
+ { 0x2019, 0x2019, 0x27, 1 },
+ { 0x201a, 0x201a, 0x2c, 1 },
+ { 0x201c, 0x201c, 0x22, 1 },
+ { 0x201d, 0x201d, 0x22, 1 },
+ { 0x201e, 0x201e, 0x2c2c, 2 },
+ { 0x2022, 0x2022, 0xb7, 1 },
+ { 0x2026, 0x2026, 0x2e2e2e, 3 },
+ { 0x2039, 0x2039, 0x3c, 1 },
+ { 0x203a, 0x203a, 0x3e, 1 },
+ { 0x2044, 0x2044, 0x2f, 1 },
+ { 0x2122, 0x2122, 0x544d, 2 },
+ { 0x2212, 0x2212, 0x2d, 1 },
+ { 0xf6f9, 0xf6f9, 0x4c, 1 },
+ { 0xf6fa, 0xf6fa, 0x4f45, 2 },
+ { 0xf6fc, 0xf6fc, 0xb0, 1 },
+ { 0xf6fd, 0xf6fd, 0x53, 1 },
+ { 0xf6fe, 0xf6fe, 0x7e, 1 },
+ { 0xf6ff, 0xf6ff, 0x5a, 1 },
+ { 0xf721, 0xf721, 0x21, 1 },
+ { 0xf724, 0xf724, 0x24, 1 },
+ { 0xf726, 0xf726, 0x26, 1 },
+ { 0xf730, 0xf739, 0x30, 1 },
+ { 0xf73f, 0xf73f, 0x3f, 1 },
+ { 0xf761, 0xf77a, 0x41, 1 },
+ { 0xf7a1, 0xf7a2, 0xa1, 1 },
+ { 0xf7bf, 0xf7bf, 0xbf, 1 },
+ { 0xf7e0, 0xf7f6, 0xc0, 1 },
+ { 0xf7f8, 0xf7fe, 0xd8, 1 },
+ { 0xf7ff, 0xf7ff, 0x59, 1 },
+ { 0xfb00, 0xfb00, 0x6666, 2 },
+ { 0xfb01, 0xfb01, 0x6669, 2 },
+ { 0xfb02, 0xfb02, 0x666c, 2 },
+ { 0xfb03, 0xfb03, 0x666669, 3 },
+ { 0xfb04, 0xfb04, 0x66666c, 3 }
+};
+#define latin1UnicodeMapLen (sizeof(latin1UnicodeMapRanges) / sizeof(UnicodeMapRange))
+
+static UnicodeMapRange ascii7UnicodeMapRanges[] = {
+ { 0x000a, 0x000a, 0x0a, 1 },
+ { 0x000c, 0x000d, 0x0c, 1 },
+ { 0x0020, 0x005f, 0x20, 1 },
+ { 0x0061, 0x007e, 0x61, 1 },
+ { 0x00a6, 0x00a6, 0x7c, 1 },
+ { 0x00a9, 0x00a9, 0x286329, 3 },
+ { 0x00ae, 0x00ae, 0x285229, 3 },
+ { 0x00b7, 0x00b7, 0x2a, 1 },
+ { 0x00bc, 0x00bc, 0x312f34, 3 },
+ { 0x00bd, 0x00bd, 0x312f32, 3 },
+ { 0x00be, 0x00be, 0x332f34, 3 },
+ { 0x00c0, 0x00c0, 0x41, 1 },
+ { 0x00c1, 0x00c1, 0x41, 1 },
+ { 0x00c2, 0x00c2, 0x41, 1 },
+ { 0x00c3, 0x00c3, 0x41, 1 },
+ { 0x00c4, 0x00c4, 0x41, 1 },
+ { 0x00c5, 0x00c5, 0x41, 1 },
+ { 0x00c6, 0x00c6, 0x4145, 2 },
+ { 0x00c7, 0x00c7, 0x43, 1 },
+ { 0x00c8, 0x00c8, 0x45, 1 },
+ { 0x00c9, 0x00c9, 0x45, 1 },
+ { 0x00ca, 0x00ca, 0x45, 1 },
+ { 0x00cb, 0x00cb, 0x45, 1 },
+ { 0x00cc, 0x00cc, 0x49, 1 },
+ { 0x00cd, 0x00cd, 0x49, 1 },
+ { 0x00ce, 0x00ce, 0x49, 1 },
+ { 0x00cf, 0x00cf, 0x49, 1 },
+ { 0x00d1, 0x00d2, 0x4e, 1 },
+ { 0x00d3, 0x00d3, 0x4f, 1 },
+ { 0x00d4, 0x00d4, 0x4f, 1 },
+ { 0x00d5, 0x00d5, 0x4f, 1 },
+ { 0x00d6, 0x00d6, 0x4f, 1 },
+ { 0x00d7, 0x00d7, 0x78, 1 },
+ { 0x00d8, 0x00d8, 0x4f, 1 },
+ { 0x00d9, 0x00d9, 0x55, 1 },
+ { 0x00da, 0x00da, 0x55, 1 },
+ { 0x00db, 0x00db, 0x55, 1 },
+ { 0x00dc, 0x00dc, 0x55, 1 },
+ { 0x00dd, 0x00dd, 0x59, 1 },
+ { 0x00e0, 0x00e0, 0x61, 1 },
+ { 0x00e1, 0x00e1, 0x61, 1 },
+ { 0x00e2, 0x00e2, 0x61, 1 },
+ { 0x00e3, 0x00e3, 0x61, 1 },
+ { 0x00e4, 0x00e4, 0x61, 1 },
+ { 0x00e5, 0x00e5, 0x61, 1 },
+ { 0x00e6, 0x00e6, 0x6165, 2 },
+ { 0x00e7, 0x00e7, 0x63, 1 },
+ { 0x00e8, 0x00e8, 0x65, 1 },
+ { 0x00e9, 0x00e9, 0x65, 1 },
+ { 0x00ea, 0x00ea, 0x65, 1 },
+ { 0x00eb, 0x00eb, 0x65, 1 },
+ { 0x00ec, 0x00ec, 0x69, 1 },
+ { 0x00ed, 0x00ed, 0x69, 1 },
+ { 0x00ee, 0x00ee, 0x69, 1 },
+ { 0x00ef, 0x00ef, 0x69, 1 },
+ { 0x00f1, 0x00f2, 0x6e, 1 },
+ { 0x00f3, 0x00f3, 0x6f, 1 },
+ { 0x00f4, 0x00f4, 0x6f, 1 },
+ { 0x00f5, 0x00f5, 0x6f, 1 },
+ { 0x00f6, 0x00f6, 0x6f, 1 },
+ { 0x00f7, 0x00f7, 0x2f, 1 },
+ { 0x00f8, 0x00f8, 0x6f, 1 },
+ { 0x00f9, 0x00f9, 0x75, 1 },
+ { 0x00fa, 0x00fa, 0x75, 1 },
+ { 0x00fb, 0x00fb, 0x75, 1 },
+ { 0x00fc, 0x00fc, 0x75, 1 },
+ { 0x00fd, 0x00fd, 0x79, 1 },
+ { 0x00ff, 0x00ff, 0x79, 1 },
+ { 0x0131, 0x0131, 0x69, 1 },
+ { 0x0141, 0x0141, 0x4c, 1 },
+ { 0x0152, 0x0152, 0x4f45, 2 },
+ { 0x0153, 0x0153, 0x6f65, 2 },
+ { 0x0160, 0x0160, 0x53, 1 },
+ { 0x0178, 0x0178, 0x59, 1 },
+ { 0x017d, 0x017d, 0x5a, 1 },
+ { 0x2013, 0x2013, 0x2d, 1 },
+ { 0x2014, 0x2014, 0x2d2d, 2 },
+ { 0x2018, 0x2018, 0x60, 1 },
+ { 0x2019, 0x2019, 0x27, 1 },
+ { 0x201c, 0x201c, 0x22, 1 },
+ { 0x201d, 0x201d, 0x22, 1 },
+ { 0x2022, 0x2022, 0x2a, 1 },
+ { 0x2026, 0x2026, 0x2e2e2e, 3 },
+ { 0x2122, 0x2122, 0x544d, 2 },
+ { 0x2212, 0x2212, 0x2d, 1 },
+ { 0xf6f9, 0xf6f9, 0x4c, 1 },
+ { 0xf6fa, 0xf6fa, 0x4f45, 2 },
+ { 0xf6fd, 0xf6fd, 0x53, 1 },
+ { 0xf6fe, 0xf6fe, 0x7e, 1 },
+ { 0xf6ff, 0xf6ff, 0x5a, 1 },
+ { 0xf721, 0xf721, 0x21, 1 },
+ { 0xf724, 0xf724, 0x24, 1 },
+ { 0xf726, 0xf726, 0x26, 1 },
+ { 0xf730, 0xf739, 0x30, 1 },
+ { 0xf73f, 0xf73f, 0x3f, 1 },
+ { 0xf761, 0xf77a, 0x41, 1 },
+ { 0xf7e0, 0xf7e0, 0x41, 1 },
+ { 0xf7e1, 0xf7e1, 0x41, 1 },
+ { 0xf7e2, 0xf7e2, 0x41, 1 },
+ { 0xf7e3, 0xf7e3, 0x41, 1 },
+ { 0xf7e4, 0xf7e4, 0x41, 1 },
+ { 0xf7e5, 0xf7e5, 0x41, 1 },
+ { 0xf7e6, 0xf7e6, 0x4145, 2 },
+ { 0xf7e7, 0xf7e7, 0x43, 1 },
+ { 0xf7e8, 0xf7e8, 0x45, 1 },
+ { 0xf7e9, 0xf7e9, 0x45, 1 },
+ { 0xf7ea, 0xf7ea, 0x45, 1 },
+ { 0xf7eb, 0xf7eb, 0x45, 1 },
+ { 0xf7ec, 0xf7ec, 0x49, 1 },
+ { 0xf7ed, 0xf7ed, 0x49, 1 },
+ { 0xf7ee, 0xf7ee, 0x49, 1 },
+ { 0xf7ef, 0xf7ef, 0x49, 1 },
+ { 0xf7f1, 0xf7f2, 0x4e, 1 },
+ { 0xf7f3, 0xf7f3, 0x4f, 1 },
+ { 0xf7f4, 0xf7f4, 0x4f, 1 },
+ { 0xf7f5, 0xf7f5, 0x4f, 1 },
+ { 0xf7f6, 0xf7f6, 0x4f, 1 },
+ { 0xf7f8, 0xf7f8, 0x4f, 1 },
+ { 0xf7f9, 0xf7f9, 0x55, 1 },
+ { 0xf7fa, 0xf7fa, 0x55, 1 },
+ { 0xf7fb, 0xf7fb, 0x55, 1 },
+ { 0xf7fc, 0xf7fc, 0x55, 1 },
+ { 0xf7fd, 0xf7fd, 0x59, 1 },
+ { 0xf7ff, 0xf7ff, 0x59, 1 },
+ { 0xfb00, 0xfb00, 0x6666, 2 },
+ { 0xfb01, 0xfb01, 0x6669, 2 },
+ { 0xfb02, 0xfb02, 0x666c, 2 },
+ { 0xfb03, 0xfb03, 0x666669, 3 },
+ { 0xfb04, 0xfb04, 0x66666c, 3 }
+};
+#define ascii7UnicodeMapLen (sizeof(ascii7UnicodeMapRanges) / sizeof(UnicodeMapRange))
+
+static UnicodeMapRange symbolUnicodeMapRanges[] = {
+ { 0x0020, 0x0021, 0x20, 1 },
+ { 0x0023, 0x0023, 0x23, 1 },
+ { 0x0025, 0x0026, 0x25, 1 },
+ { 0x0028, 0x0029, 0x28, 1 },
+ { 0x002b, 0x002c, 0x2b, 1 },
+ { 0x002e, 0x003f, 0x2e, 1 },
+ { 0x005b, 0x005b, 0x5b, 1 },
+ { 0x005d, 0x005d, 0x5d, 1 },
+ { 0x005f, 0x005f, 0x5f, 1 },
+ { 0x007b, 0x007d, 0x7b, 1 },
+ { 0x00ac, 0x00ac, 0xd8, 1 },
+ { 0x00b0, 0x00b1, 0xb0, 1 },
+ { 0x00b5, 0x00b5, 0x6d, 1 },
+ { 0x00d7, 0x00d7, 0xb4, 1 },
+ { 0x00f7, 0x00f7, 0xb8, 1 },
+ { 0x0192, 0x0192, 0xa6, 1 },
+ { 0x0391, 0x0392, 0x41, 1 },
+ { 0x0393, 0x0393, 0x47, 1 },
+ { 0x0395, 0x0395, 0x45, 1 },
+ { 0x0396, 0x0396, 0x5a, 1 },
+ { 0x0397, 0x0397, 0x48, 1 },
+ { 0x0398, 0x0398, 0x51, 1 },
+ { 0x0399, 0x0399, 0x49, 1 },
+ { 0x039a, 0x039d, 0x4b, 1 },
+ { 0x039e, 0x039e, 0x58, 1 },
+ { 0x039f, 0x03a0, 0x4f, 1 },
+ { 0x03a1, 0x03a1, 0x52, 1 },
+ { 0x03a3, 0x03a5, 0x53, 1 },
+ { 0x03a6, 0x03a6, 0x46, 1 },
+ { 0x03a7, 0x03a7, 0x43, 1 },
+ { 0x03a8, 0x03a8, 0x59, 1 },
+ { 0x03b1, 0x03b2, 0x61, 1 },
+ { 0x03b3, 0x03b3, 0x67, 1 },
+ { 0x03b4, 0x03b5, 0x64, 1 },
+ { 0x03b6, 0x03b6, 0x7a, 1 },
+ { 0x03b7, 0x03b7, 0x68, 1 },
+ { 0x03b8, 0x03b8, 0x71, 1 },
+ { 0x03b9, 0x03b9, 0x69, 1 },
+ { 0x03ba, 0x03bb, 0x6b, 1 },
+ { 0x03bd, 0x03bd, 0x6e, 1 },
+ { 0x03be, 0x03be, 0x78, 1 },
+ { 0x03bf, 0x03c0, 0x6f, 1 },
+ { 0x03c1, 0x03c1, 0x72, 1 },
+ { 0x03c2, 0x03c2, 0x56, 1 },
+ { 0x03c3, 0x03c5, 0x73, 1 },
+ { 0x03c6, 0x03c6, 0x66, 1 },
+ { 0x03c7, 0x03c7, 0x63, 1 },
+ { 0x03c8, 0x03c8, 0x79, 1 },
+ { 0x03c9, 0x03c9, 0x77, 1 },
+ { 0x03d1, 0x03d1, 0x4a, 1 },
+ { 0x03d2, 0x03d2, 0xa1, 1 },
+ { 0x03d5, 0x03d5, 0x6a, 1 },
+ { 0x03d6, 0x03d6, 0x76, 1 },
+ { 0x2022, 0x2022, 0xb7, 1 },
+ { 0x2026, 0x2026, 0xbc, 1 },
+ { 0x2032, 0x2032, 0xa2, 1 },
+ { 0x2033, 0x2033, 0xb2, 1 },
+ { 0x2044, 0x2044, 0xa4, 1 },
+ { 0x2111, 0x2111, 0xc1, 1 },
+ { 0x2118, 0x2118, 0xc3, 1 },
+ { 0x211c, 0x211c, 0xc2, 1 },
+ { 0x2126, 0x2126, 0x57, 1 },
+ { 0x2135, 0x2135, 0xc0, 1 },
+ { 0x2190, 0x2193, 0xac, 1 },
+ { 0x2194, 0x2194, 0xab, 1 },
+ { 0x21b5, 0x21b5, 0xbf, 1 },
+ { 0x21d0, 0x21d3, 0xdc, 1 },
+ { 0x21d4, 0x21d4, 0xdb, 1 },
+ { 0x2200, 0x2200, 0x22, 1 },
+ { 0x2202, 0x2202, 0xb6, 1 },
+ { 0x2203, 0x2203, 0x24, 1 },
+ { 0x2205, 0x2205, 0xc6, 1 },
+ { 0x2206, 0x2206, 0x44, 1 },
+ { 0x2207, 0x2207, 0xd1, 1 },
+ { 0x2208, 0x2209, 0xce, 1 },
+ { 0x220b, 0x220b, 0x27, 1 },
+ { 0x220f, 0x220f, 0xd5, 1 },
+ { 0x2211, 0x2211, 0xe5, 1 },
+ { 0x2212, 0x2212, 0x2d, 1 },
+ { 0x2217, 0x2217, 0x2a, 1 },
+ { 0x221a, 0x221a, 0xd6, 1 },
+ { 0x221d, 0x221d, 0xb5, 1 },
+ { 0x221e, 0x221e, 0xa5, 1 },
+ { 0x2220, 0x2220, 0xd0, 1 },
+ { 0x2227, 0x2228, 0xd9, 1 },
+ { 0x2229, 0x222a, 0xc7, 1 },
+ { 0x222b, 0x222b, 0xf2, 1 },
+ { 0x2234, 0x2234, 0x5c, 1 },
+ { 0x223c, 0x223c, 0x7e, 1 },
+ { 0x2245, 0x2245, 0x40, 1 },
+ { 0x2248, 0x2248, 0xbb, 1 },
+ { 0x2260, 0x2261, 0xb9, 1 },
+ { 0x2264, 0x2264, 0xa3, 1 },
+ { 0x2265, 0x2265, 0xb3, 1 },
+ { 0x2282, 0x2282, 0xcc, 1 },
+ { 0x2283, 0x2283, 0xc9, 1 },
+ { 0x2284, 0x2284, 0xcb, 1 },
+ { 0x2286, 0x2286, 0xcd, 1 },
+ { 0x2287, 0x2287, 0xca, 1 },
+ { 0x2295, 0x2295, 0xc5, 1 },
+ { 0x2297, 0x2297, 0xc4, 1 },
+ { 0x22a5, 0x22a5, 0x5e, 1 },
+ { 0x22c5, 0x22c5, 0xd7, 1 },
+ { 0x2320, 0x2320, 0xf3, 1 },
+ { 0x2321, 0x2321, 0xf5, 1 },
+ { 0x2329, 0x2329, 0xe1, 1 },
+ { 0x232a, 0x232a, 0xf1, 1 },
+ { 0x25ca, 0x25ca, 0xe0, 1 },
+ { 0x2660, 0x2660, 0xaa, 1 },
+ { 0x2663, 0x2663, 0xa7, 1 },
+ { 0x2665, 0x2665, 0xa9, 1 },
+ { 0x2666, 0x2666, 0xa8, 1 },
+ { 0xf6d9, 0xf6d9, 0xd3, 1 },
+ { 0xf6da, 0xf6da, 0xd2, 1 },
+ { 0xf6db, 0xf6db, 0xd4, 1 },
+ { 0xf8e5, 0xf8e5, 0x60, 1 },
+ { 0xf8e6, 0xf8e7, 0xbd, 1 },
+ { 0xf8e8, 0xf8ea, 0xe2, 1 },
+ { 0xf8eb, 0xf8f4, 0xe6, 1 },
+ { 0xf8f5, 0xf8f5, 0xf4, 1 },
+ { 0xf8f6, 0xf8fe, 0xf6, 1 }
+};
+#define symbolUnicodeMapLen (sizeof(symbolUnicodeMapRanges) / sizeof(UnicodeMapRange))
+
+static UnicodeMapRange zapfDingbatsUnicodeMapRanges[] = {
+ { 0x0020, 0x0020, 0x20, 1 },
+ { 0x2192, 0x2192, 0xd5, 1 },
+ { 0x2194, 0x2195, 0xd6, 1 },
+ { 0x2460, 0x2469, 0xac, 1 },
+ { 0x25a0, 0x25a0, 0x6e, 1 },
+ { 0x25b2, 0x25b2, 0x73, 1 },
+ { 0x25bc, 0x25bc, 0x74, 1 },
+ { 0x25c6, 0x25c6, 0x75, 1 },
+ { 0x25cf, 0x25cf, 0x6c, 1 },
+ { 0x25d7, 0x25d7, 0x77, 1 },
+ { 0x2605, 0x2605, 0x48, 1 },
+ { 0x260e, 0x260e, 0x25, 1 },
+ { 0x261b, 0x261b, 0x2a, 1 },
+ { 0x261e, 0x261e, 0x2b, 1 },
+ { 0x2660, 0x2660, 0xab, 1 },
+ { 0x2663, 0x2663, 0xa8, 1 },
+ { 0x2665, 0x2665, 0xaa, 1 },
+ { 0x2666, 0x2666, 0xa9, 1 },
+ { 0x2701, 0x2704, 0x21, 1 },
+ { 0x2706, 0x2709, 0x26, 1 },
+ { 0x270c, 0x2727, 0x2c, 1 },
+ { 0x2729, 0x274b, 0x49, 1 },
+ { 0x274d, 0x274d, 0x6d, 1 },
+ { 0x274f, 0x2752, 0x6f, 1 },
+ { 0x2756, 0x2756, 0x76, 1 },
+ { 0x2758, 0x275e, 0x78, 1 },
+ { 0x2761, 0x2767, 0xa1, 1 },
+ { 0x2776, 0x2794, 0xb6, 1 },
+ { 0x2798, 0x27af, 0xd8, 1 },
+ { 0x27b1, 0x27be, 0xf1, 1 }
+};
+#define zapfDingbatsUnicodeMapLen (sizeof(zapfDingbatsUnicodeMapRanges) / sizeof(UnicodeMapRange))
diff --git a/pdftops/XRef.cxx b/pdftops/XRef.cxx
new file mode 100644
index 000000000..4e5738dcf
--- /dev/null
+++ b/pdftops/XRef.cxx
@@ -0,0 +1,709 @@
+//========================================================================
+//
+// XRef.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include "gmem.h"
+#include "Object.h"
+#include "Stream.h"
+#include "Lexer.h"
+#include "Parser.h"
+#include "Dict.h"
+#ifndef NO_DECRYPTION
+#include "Decrypt.h"
+#endif
+#include "Error.h"
+#include "ErrorCodes.h"
+#include "XRef.h"
+
+//------------------------------------------------------------------------
+
+#define xrefSearchSize 1024 // read this many bytes at end of file
+ // to look for 'startxref'
+
+#ifndef NO_DECRYPTION
+//------------------------------------------------------------------------
+// Permission bits
+//------------------------------------------------------------------------
+
+#define permPrint (1<<2)
+#define permChange (1<<3)
+#define permCopy (1<<4)
+#define permNotes (1<<5)
+#define defPermFlags 0xfffc
+#endif
+
+//------------------------------------------------------------------------
+// XRef
+//------------------------------------------------------------------------
+
+XRef::XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword) {
+ Guint pos;
+ int i;
+
+ ok = gTrue;
+ errCode = errNone;
+ size = 0;
+ entries = NULL;
+ streamEnds = NULL;
+ streamEndsLen = 0;
+
+ // read the trailer
+ str = strA;
+ start = str->getStart();
+ pos = readTrailer();
+
+ // if there was a problem with the trailer,
+ // try to reconstruct the xref table
+ if (pos == 0) {
+ if (!(ok = constructXRef())) {
+ errCode = errDamaged;
+ return;
+ }
+
+ // trailer is ok - read the xref table
+ } else {
+ if (size*sizeof(XRefEntry)/sizeof(XRefEntry) != size) {
+ error(-1, "Invalid 'size' inside xref table.");
+ ok = gFalse;
+ errCode = errDamaged;
+ return;
+ }
+ entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
+ for (i = 0; i < size; ++i) {
+ entries[i].offset = 0xffffffff;
+ entries[i].used = gFalse;
+ }
+ while (readXRef(&pos)) ;
+
+ // if there was a problem with the xref table,
+ // try to reconstruct it
+ if (!ok) {
+ gfree(entries);
+ size = 0;
+ entries = NULL;
+ if (!(ok = constructXRef())) {
+ errCode = errDamaged;
+ return;
+ }
+ }
+ }
+
+ // now set the trailer dictionary's xref pointer so we can fetch
+ // indirect objects from it
+ trailerDict.getDict()->setXRef(this);
+
+ // check for encryption
+#ifndef NO_DECRYPTION
+ encrypted = gFalse;
+#endif
+ if (checkEncrypted(ownerPassword, userPassword)) {
+ ok = gFalse;
+ errCode = errEncrypted;
+ return;
+ }
+}
+
+XRef::~XRef() {
+ gfree(entries);
+ trailerDict.free();
+ if (streamEnds) {
+ gfree(streamEnds);
+ }
+}
+
+// Read startxref position, xref table size, and root. Returns
+// first xref position.
+Guint XRef::readTrailer() {
+ Parser *parser;
+ Object obj;
+ char buf[xrefSearchSize+1];
+ int n;
+ Guint pos, pos1;
+ char *p;
+ int c;
+ int i;
+
+ // read last xrefSearchSize bytes
+ str->setPos(xrefSearchSize, -1);
+ for (n = 0; n < xrefSearchSize; ++n) {
+ if ((c = str->getChar()) == EOF) {
+ break;
+ }
+ buf[n] = c;
+ }
+ buf[n] = '\0';
+
+ // find startxref
+ for (i = n - 9; i >= 0; --i) {
+ if (!strncmp(&buf[i], "startxref", 9)) {
+ break;
+ }
+ }
+ if (i < 0) {
+ goto err1;
+ }
+ for (p = &buf[i+9]; isspace(*p); ++p) ;
+ pos = lastXRefPos = strToUnsigned(p);
+
+ // find trailer dict by looking after first xref table
+ // (NB: we can't just use the trailer dict at the end of the file --
+ // this won't work for linearized files.)
+ str->setPos(start + pos);
+ for (i = 0; i < 4; ++i) {
+ buf[i] = str->getChar();
+ }
+ if (strncmp(buf, "xref", 4)) {
+ goto err1;
+ }
+ pos1 = pos + 4;
+ while (1) {
+ str->setPos(start + pos1);
+ for (i = 0; i < 35; ++i) {
+ if ((c = str->getChar()) == EOF) {
+ goto err1;
+ }
+ buf[i] = c;
+ }
+ if (!strncmp(buf, "trailer", 7)) {
+ break;
+ }
+ p = buf;
+ while (isspace(*p)) ++p;
+ while ('0' <= *p && *p <= '9') ++p;
+ while (isspace(*p)) ++p;
+ n = atoi(p);
+ while ('0' <= *p && *p <= '9') ++p;
+ while (isspace(*p)) ++p;
+ if (p == buf) {
+ goto err1;
+ }
+ pos1 += (p - buf) + n * 20;
+ }
+ pos1 += 7;
+
+ // read trailer dict
+ obj.initNull();
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(start + pos1, gFalse, 0, &obj)));
+ parser->getObj(&trailerDict);
+ if (trailerDict.isDict()) {
+ trailerDict.dictLookupNF("Size", &obj);
+ if (obj.isInt()) {
+ size = obj.getInt();
+ } else {
+ goto err3;
+ }
+ obj.free();
+ trailerDict.dictLookupNF("Root", &obj);
+ if (obj.isRef()) {
+ rootNum = obj.getRefNum();
+ rootGen = obj.getRefGen();
+ } else {
+ goto err3;
+ }
+ obj.free();
+ } else {
+ goto err2;
+ }
+ delete parser;
+
+ // return first xref position
+ return pos;
+
+ err3:
+ obj.free();
+ err2:
+ trailerDict.free();
+ delete parser;
+ err1:
+ size = 0;
+ return 0;
+}
+
+// Read an xref table and the prev pointer from the trailer.
+GBool XRef::readXRef(Guint *pos) {
+ Parser *parser;
+ Object obj, obj2;
+ char s[20];
+ GBool more;
+ int first, newSize, n, i, j;
+ int c;
+
+ // seek to xref in stream
+ str->setPos(start + *pos);
+
+ // make sure it's an xref table
+ while ((c = str->getChar()) != EOF && isspace(c)) ;
+ s[0] = (char)c;
+ s[1] = (char)str->getChar();
+ s[2] = (char)str->getChar();
+ s[3] = (char)str->getChar();
+ if (!(s[0] == 'x' && s[1] == 'r' && s[2] == 'e' && s[3] == 'f')) {
+ goto err2;
+ }
+
+ // read xref
+ while (1) {
+ while ((c = str->lookChar()) != EOF && isspace(c)) {
+ str->getChar();
+ }
+ if (c == 't') {
+ break;
+ }
+ for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
+ s[i] = (char)c;
+ }
+ if (i == 0) {
+ goto err2;
+ }
+ s[i] = '\0';
+ first = atoi(s);
+ while ((c = str->lookChar()) != EOF && isspace(c)) {
+ str->getChar();
+ }
+ for (i = 0; (c = str->getChar()) != EOF && isdigit(c) && i < 20; ++i) {
+ s[i] = (char)c;
+ }
+ if (i == 0) {
+ goto err2;
+ }
+ s[i] = '\0';
+ n = atoi(s);
+ while ((c = str->lookChar()) != EOF && isspace(c)) {
+ str->getChar();
+ }
+ // check for buggy PDF files with an incorrect (too small) xref
+ // table size
+ if (first + n > size) {
+ newSize = first + n;
+ if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+ error(-1, "Invalid 'newSize'");
+ goto err2;
+ }
+ entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
+ for (i = size; i < newSize; ++i) {
+ entries[i].offset = 0xffffffff;
+ entries[i].used = gFalse;
+ }
+ size = newSize;
+ }
+ for (i = first; i < first + n; ++i) {
+ for (j = 0; j < 20; ++j) {
+ if ((c = str->getChar()) == EOF) {
+ goto err2;
+ }
+ s[j] = (char)c;
+ }
+ if (entries[i].offset == 0xffffffff) {
+ s[10] = '\0';
+ entries[i].offset = strToUnsigned(s);
+ s[16] = '\0';
+ entries[i].gen = atoi(&s[11]);
+ if (s[17] == 'n') {
+ entries[i].used = gTrue;
+ } else if (s[17] == 'f') {
+ entries[i].used = gFalse;
+ } else {
+ goto err2;
+ }
+ // PDF files of patents from the IBM Intellectual Property
+ // Network have a bug: the xref table claims to start at 1
+ // instead of 0.
+ if (i == 1 && first == 1 &&
+ entries[1].offset == 0 && entries[1].gen == 65535 &&
+ !entries[1].used) {
+ i = first = 0;
+ entries[0] = entries[1];
+ entries[1].offset = 0xffffffff;
+ }
+ }
+ }
+ }
+
+ // read prev pointer from trailer dictionary
+ obj.initNull();
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(str->getPos(), gFalse, 0, &obj)));
+ parser->getObj(&obj);
+ if (!obj.isCmd("trailer")) {
+ goto err1;
+ }
+ obj.free();
+ parser->getObj(&obj);
+ if (!obj.isDict()) {
+ goto err1;
+ }
+ obj.getDict()->lookupNF("Prev", &obj2);
+ if (obj2.isInt()) {
+ *pos = (Guint)obj2.getInt();
+ more = gTrue;
+ } else if (obj2.isRef()) {
+ // certain buggy PDF generators generate "/Prev NNN 0 R" instead
+ // of "/Prev NNN"
+ *pos = (Guint)obj2.getRefNum();
+ more = gTrue;
+ } else {
+ more = gFalse;
+ }
+ obj.free();
+ obj2.free();
+
+ delete parser;
+ return more;
+
+ err1:
+ obj.free();
+ err2:
+ ok = gFalse;
+ return gFalse;
+}
+
+// Attempt to construct an xref table for a damaged file.
+GBool XRef::constructXRef() {
+ Parser *parser;
+ Object obj;
+ char buf[256];
+ Guint pos;
+ int num, gen;
+ int newSize;
+ int streamEndsSize;
+ char *p;
+ int i;
+ GBool gotRoot;
+
+ error(0, "PDF file is damaged - attempting to reconstruct xref table...");
+ gotRoot = gFalse;
+ streamEndsLen = streamEndsSize = 0;
+
+ str->reset();
+ while (1) {
+ pos = str->getPos();
+ if (!str->getLine(buf, 256)) {
+ break;
+ }
+ p = buf;
+
+ // got trailer dictionary
+ if (!strncmp(p, "trailer", 7)) {
+ gotRoot = gFalse;
+ obj.initNull();
+ parser = new Parser(NULL,
+ new Lexer(NULL,
+ str->makeSubStream(start + pos + 7, gFalse, 0, &obj)));
+ if (!trailerDict.isNone()) {
+ trailerDict.free();
+ }
+ parser->getObj(&trailerDict);
+ if (trailerDict.isDict()) {
+ trailerDict.dictLookupNF("Root", &obj);
+ if (obj.isRef()) {
+ rootNum = obj.getRefNum();
+ rootGen = obj.getRefGen();
+ gotRoot = gTrue;
+ }
+ obj.free();
+ } else {
+ trailerDict.free();
+ }
+ delete parser;
+
+ // look for object
+ } else if (isdigit(*p)) {
+ num = atoi(p);
+ do {
+ ++p;
+ } while (*p && isdigit(*p));
+ if (isspace(*p)) {
+ do {
+ ++p;
+ } while (*p && isspace(*p));
+ if (isdigit(*p)) {
+ gen = atoi(p);
+ do {
+ ++p;
+ } while (*p && isdigit(*p));
+ if (isspace(*p)) {
+ do {
+ ++p;
+ } while (*p && isspace(*p));
+ if (!strncmp(p, "obj", 3)) {
+ if (num >= size) {
+ newSize = (num + 1 + 255) & ~255;
+ if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+ error(-1, "Invalid 'obj' parameters.");
+ return gFalse;
+ }
+ entries = (XRefEntry *)
+ grealloc(entries, newSize * sizeof(XRefEntry));
+ for (i = size; i < newSize; ++i) {
+ entries[i].offset = 0xffffffff;
+ entries[i].used = gFalse;
+ }
+ size = newSize;
+ }
+ if (!entries[num].used || gen >= entries[num].gen) {
+ entries[num].offset = pos - start;
+ entries[num].gen = gen;
+ entries[num].used = gTrue;
+ }
+ }
+ }
+ }
+ }
+
+ } else if (!strncmp(p, "endstream", 9)) {
+ if (streamEndsLen == streamEndsSize) {
+ streamEndsSize += 64;
+ if (streamEndsSize*sizeof(int)/sizeof(int) != streamEndsSize) {
+ error(-1, "Invalid 'endstream' parameter.");
+ return gFalse;
+ }
+
+ streamEnds = (Guint *)grealloc(streamEnds,
+ streamEndsSize * sizeof(int));
+ }
+ streamEnds[streamEndsLen++] = pos;
+ }
+ }
+
+ if (gotRoot)
+ return gTrue;
+
+ error(-1, "Couldn't find trailer dictionary");
+ return gFalse;
+}
+
+#ifndef NO_DECRYPTION
+GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
+ Object encrypt, filterObj, versionObj, revisionObj, lengthObj;
+ Object ownerKey, userKey, permissions, fileID, fileID1;
+ GBool encrypted1;
+ GBool ret;
+
+ keyLength = 0;
+ encVersion = encRevision = 0;
+ ret = gFalse;
+
+ permFlags = defPermFlags;
+ ownerPasswordOk = gFalse;
+ trailerDict.dictLookup("Encrypt", &encrypt);
+ if ((encrypted1 = encrypt.isDict())) {
+ ret = gTrue;
+ encrypt.dictLookup("Filter", &filterObj);
+ if (filterObj.isName("Standard")) {
+ encrypt.dictLookup("V", &versionObj);
+ encrypt.dictLookup("R", &revisionObj);
+ encrypt.dictLookup("Length", &lengthObj);
+ encrypt.dictLookup("O", &ownerKey);
+ encrypt.dictLookup("U", &userKey);
+ encrypt.dictLookup("P", &permissions);
+ trailerDict.dictLookup("ID", &fileID);
+ if (versionObj.isInt() &&
+ revisionObj.isInt() &&
+ ownerKey.isString() && ownerKey.getString()->getLength() == 32 &&
+ userKey.isString() && userKey.getString()->getLength() == 32 &&
+ permissions.isInt() &&
+ fileID.isArray()) {
+ encVersion = versionObj.getInt();
+ encRevision = revisionObj.getInt();
+ if (lengthObj.isInt()) {
+ keyLength = lengthObj.getInt() / 8;
+ } else {
+ keyLength = 5;
+ }
+ permFlags = permissions.getInt();
+ if (encVersion >= 1 && encVersion <= 2 &&
+ encRevision >= 2 && encRevision <= 3) {
+ fileID.arrayGet(0, &fileID1);
+ if (fileID1.isString()) {
+ if (Decrypt::makeFileKey(encVersion, encRevision, keyLength,
+ ownerKey.getString(), userKey.getString(),
+ permFlags, fileID1.getString(),
+ ownerPassword, userPassword, fileKey,
+ &ownerPasswordOk)) {
+ if (ownerPassword && !ownerPasswordOk) {
+ error(-1, "Incorrect owner password");
+ }
+ ret = gFalse;
+ } else {
+ error(-1, "Incorrect password");
+ }
+ } else {
+ error(-1, "Weird encryption info");
+ }
+ fileID1.free();
+ } else {
+ error(-1, "Unsupported version/revision (%d/%d) of Standard security handler",
+ encVersion, encRevision);
+ }
+ } else {
+ error(-1, "Weird encryption info");
+ }
+ fileID.free();
+ permissions.free();
+ userKey.free();
+ ownerKey.free();
+ lengthObj.free();
+ revisionObj.free();
+ versionObj.free();
+ } else {
+ error(-1, "Unknown security handler '%s'",
+ filterObj.isName() ? filterObj.getName() : "???");
+ }
+ filterObj.free();
+ }
+ encrypt.free();
+
+ // this flag has to be set *after* we read the O/U/P strings
+ encrypted = encrypted1;
+
+ return ret;
+}
+#else
+GBool XRef::checkEncrypted(GString *ownerPassword, GString *userPassword) {
+ Object obj;
+ GBool encrypted;
+
+ trailerDict.dictLookup("Encrypt", &obj);
+ if ((encrypted = !obj.isNull())) {
+ error(-1, "PDF file is encrypted and this version of the Xpdf tools");
+ error(-1, "was built without decryption support.");
+ }
+ obj.free();
+ return encrypted;
+}
+#endif
+
+GBool XRef::okToPrint(GBool ignoreOwnerPW) {
+#ifndef NO_DECRYPTION
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permPrint);
+#else
+ return gTrue;
+#endif
+}
+
+GBool XRef::okToChange(GBool ignoreOwnerPW) {
+#ifndef NO_DECRYPTION
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permChange);
+#else
+ return gTrue;
+#endif
+}
+
+GBool XRef::okToCopy(GBool ignoreOwnerPW) {
+#ifndef NO_DECRYPTION
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permCopy);
+#else
+ return gTrue;
+#endif
+}
+
+GBool XRef::okToAddNotes(GBool ignoreOwnerPW) {
+#ifndef NO_DECRYPTION
+ return (!ignoreOwnerPW && ownerPasswordOk) || (permFlags & permNotes);
+#else
+ return gTrue;
+#endif
+}
+
+Object *XRef::fetch(int num, int gen, Object *obj) {
+ XRefEntry *e;
+ Parser *parser;
+ Object obj1, obj2, obj3;
+
+ // check for bogus ref - this can happen in corrupted PDF files
+ if (num < 0 || num >= size) {
+ obj->initNull();
+ return obj;
+ }
+
+ e = &entries[num];
+ if (e->gen == gen && e->offset != 0xffffffff) {
+ obj1.initNull();
+ parser = new Parser(this,
+ new Lexer(this,
+ str->makeSubStream(start + e->offset, gFalse, 0, &obj1)));
+ parser->getObj(&obj1);
+ parser->getObj(&obj2);
+ parser->getObj(&obj3);
+ if (obj1.isInt() && obj1.getInt() == num &&
+ obj2.isInt() && obj2.getInt() == gen &&
+ obj3.isCmd("obj")) {
+#ifndef NO_DECRYPTION
+ parser->getObj(obj, encrypted ? fileKey : (Guchar *)NULL, keyLength,
+ num, gen);
+#else
+ parser->getObj(obj);
+#endif
+ } else {
+ obj->initNull();
+ }
+ obj1.free();
+ obj2.free();
+ obj3.free();
+ delete parser;
+ } else {
+ obj->initNull();
+ }
+ return obj;
+}
+
+Object *XRef::getDocInfo(Object *obj) {
+ return trailerDict.dictLookup("Info", obj);
+}
+
+// Added for the pdftex project.
+Object *XRef::getDocInfoNF(Object *obj) {
+ return trailerDict.dictLookupNF("Info", obj);
+}
+
+GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) {
+ int a, b, m;
+
+ if (streamEndsLen == 0 ||
+ streamStart > streamEnds[streamEndsLen - 1]) {
+ return gFalse;
+ }
+
+ a = -1;
+ b = streamEndsLen - 1;
+ // invariant: streamEnds[a] < streamStart <= streamEnds[b]
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (streamStart <= streamEnds[m]) {
+ b = m;
+ } else {
+ a = m;
+ }
+ }
+ *streamEnd = streamEnds[b];
+ return gTrue;
+}
+
+Guint XRef::strToUnsigned(char *s) {
+ Guint x;
+ char *p;
+ int i;
+
+ x = 0;
+ for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) {
+ x = 10 * x + (*p - '0');
+ }
+ return x;
+}
diff --git a/pdftops/XRef.h b/pdftops/XRef.h
new file mode 100644
index 000000000..feedeb2e9
--- /dev/null
+++ b/pdftops/XRef.h
@@ -0,0 +1,123 @@
+//========================================================================
+//
+// XRef.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef XREF_H
+#define XREF_H
+
+#include <config.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "gtypes.h"
+#include "Object.h"
+
+class Dict;
+class Stream;
+
+//------------------------------------------------------------------------
+// XRef
+//------------------------------------------------------------------------
+
+struct XRefEntry {
+ Guint offset;
+ int gen;
+ GBool used;
+};
+
+class XRef {
+public:
+
+ // Constructor. Read xref table from stream.
+ XRef(BaseStream *strA, GString *ownerPassword, GString *userPassword);
+
+ // Destructor.
+ ~XRef();
+
+ // Is xref table valid?
+ GBool isOk() { return ok; }
+
+ // Get the error code (if isOk() returns false).
+ int getErrorCode() { return errCode; }
+
+ // Is the file encrypted?
+#ifndef NO_DECRYPTION
+ GBool isEncrypted() { return encrypted; }
+#else
+ GBool isEncrypted() { return gFalse; }
+#endif
+
+ // Check various permissions.
+ GBool okToPrint(GBool ignoreOwnerPW = gFalse);
+ GBool okToChange(GBool ignoreOwnerPW = gFalse);
+ GBool okToCopy(GBool ignoreOwnerPW = gFalse);
+ GBool okToAddNotes(GBool ignoreOwnerPW = gFalse);
+
+ // Get catalog object.
+ Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); }
+
+ // Fetch an indirect reference.
+ Object *fetch(int num, int gen, Object *obj);
+
+ // Return the document's Info dictionary (if any).
+ Object *getDocInfo(Object *obj);
+ Object *getDocInfoNF(Object *obj);
+
+ // Return the number of objects in the xref table.
+ int getNumObjects() { return size; }
+
+ // Return the offset of the last xref table.
+ Guint getLastXRefPos() { return lastXRefPos; }
+
+ // Return the catalog object reference.
+ int getRootNum() { return rootNum; }
+ int getRootGen() { return rootGen; }
+
+ // Get end position for a stream in a damaged file.
+ // Returns false if unknown or file is not damaged.
+ GBool getStreamEnd(Guint streamStart, Guint *streamEnd);
+
+ // Direct access.
+ int getSize() { return size; }
+ XRefEntry *getEntry(int i) { return &entries[i]; }
+ Object *getTrailerDict() { return &trailerDict; }
+
+private:
+
+ BaseStream *str; // input stream
+ Guint start; // offset in file (to allow for garbage
+ // at beginning of file)
+ XRefEntry *entries; // xref entries
+ int size; // size of <entries> array
+ int rootNum, rootGen; // catalog dict
+ GBool ok; // true if xref table is valid
+ int errCode; // error code (if <ok> is false)
+ Object trailerDict; // trailer dictionary
+ Guint lastXRefPos; // offset of last xref table
+ Guint *streamEnds; // 'endstream' positions - only used in
+ // damaged files
+ int streamEndsLen; // number of valid entries in streamEnds
+#ifndef NO_DECRYPTION
+ GBool encrypted; // true if file is encrypted
+ int encVersion; // encryption algorithm
+ int encRevision; // security handler revision
+ int keyLength; // length of key, in bytes
+ int permFlags; // permission bits
+ Guchar fileKey[16]; // file decryption key
+ GBool ownerPasswordOk; // true if owner password is correct
+#endif
+
+ Guint readTrailer();
+ GBool readXRef(Guint *pos);
+ GBool constructXRef();
+ GBool checkEncrypted(GString *ownerPassword, GString *userPassword);
+ Guint strToUnsigned(char *s);
+};
+
+#endif
diff --git a/pdftops/config.h b/pdftops/config.h
new file mode 100644
index 000000000..ef08a7fe4
--- /dev/null
+++ b/pdftops/config.h
@@ -0,0 +1,110 @@
+//========================================================================
+//
+// config.h
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+//------------------------------------------------------------------------
+// version
+//------------------------------------------------------------------------
+
+// xpdf version
+#define xpdfVersion "2.03"
+#define xpdfVersionNum 2.03
+#define xpdfMajorVersion 2
+#define xpdfMinorVersion 3
+#define xpdfMajorVersionStr "2"
+#define xpdfMinorVersionStr "3"
+
+// supported PDF version
+#define supportedPDFVersionStr "1.4"
+#define supportedPDFVersionNum 1.4
+
+// copyright notice
+#define xpdfCopyright "Copyright 1996-2003 Glyph & Cog, LLC"
+
+// Windows resource file stuff
+#define winxpdfVersion "WinXpdf 2.03"
+#define xpdfCopyrightAmp "Copyright 1996-2003 Glyph && Cog, LLC"
+
+//------------------------------------------------------------------------
+// paper size
+//------------------------------------------------------------------------
+
+// default paper size (in points) for PostScript output
+#ifdef A4_PAPER
+#define defPaperWidth 595 // ISO A4 (210x297 mm)
+#define defPaperHeight 842
+#else
+#define defPaperWidth 612 // American letter (8.5x11")
+#define defPaperHeight 792
+#endif
+
+//------------------------------------------------------------------------
+// config file (xpdfrc) path
+//------------------------------------------------------------------------
+
+// user config file name, relative to the user's home directory
+#if defined(VMS) || (defined(WIN32) && !defined(__CYGWIN32__))
+#define xpdfUserConfigFile "xpdfrc"
+#else
+#define xpdfUserConfigFile ".xpdfrc"
+#endif
+
+// system config file name (set via the configure script)
+#ifdef SYSTEM_XPDFRC
+#define xpdfSysConfigFile SYSTEM_XPDFRC
+#else
+// under Windows, we get the directory with the executable and then
+// append this file name
+#define xpdfSysConfigFile "xpdfrc"
+#endif
+
+//------------------------------------------------------------------------
+// X-related constants
+//------------------------------------------------------------------------
+
+// default maximum size of color cube to allocate
+#define defaultRGBCube 5
+
+// number of fonts (combined t1lib, FreeType, X server) to cache
+#define xOutFontCacheSize 64
+
+// number of Type 3 fonts to cache
+#define xOutT3FontCacheSize 8
+
+//------------------------------------------------------------------------
+// popen
+//------------------------------------------------------------------------
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define popen _popen
+#define pclose _pclose
+#endif
+
+#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS)
+#define POPEN_READ_MODE "rb"
+#else
+#define POPEN_READ_MODE "r"
+#endif
+
+//------------------------------------------------------------------------
+// Win32 stuff
+//------------------------------------------------------------------------
+
+#ifdef CDECL
+#undef CDECL
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define CDECL __cdecl
+#else
+#define CDECL
+#endif
+
+#endif
diff --git a/pdftops/gfile.cxx b/pdftops/gfile.cxx
new file mode 100644
index 000000000..a2664da09
--- /dev/null
+++ b/pdftops/gfile.cxx
@@ -0,0 +1,708 @@
+//========================================================================
+//
+// gfile.cc
+//
+// Miscellaneous file and directory name manipulation.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+
+#ifdef WIN32
+ extern "C" {
+# ifndef _MSC_VER
+# include <kpathsea/win32lib.h>
+# endif
+ }
+#else // !WIN32
+# if defined(MACOS)
+# include <sys/stat.h>
+# elif !defined(ACORN)
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# endif
+# include <limits.h>
+# include <string.h>
+# if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
+# include <pwd.h>
+# endif
+# if defined(VMS) && (__DECCXX_VER < 50200000)
+# include <unixlib.h>
+# endif
+#endif // WIN32
+#include "GString.h"
+#include "gfile.h"
+
+// Some systems don't define this, so just make it something reasonably
+// large.
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+//------------------------------------------------------------------------
+
+GString *getHomeDir() {
+#ifdef VMS
+ //---------- VMS ----------
+ return new GString("SYS$LOGIN:");
+
+#elif defined(__EMX__) || defined(WIN32)
+ //---------- OS/2+EMX and Win32 ----------
+ char *s;
+ GString *ret;
+
+ if ((s = getenv("HOME")))
+ ret = new GString(s);
+ else
+ ret = new GString(".");
+ return ret;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ return new GString("@");
+
+#elif defined(MACOS)
+ //---------- MacOS ----------
+ return new GString(":");
+
+#else
+ //---------- Unix ----------
+ char *s;
+ struct passwd *pw;
+ GString *ret;
+
+ if ((s = getenv("HOME"))) {
+ ret = new GString(s);
+ } else {
+ if ((s = getenv("USER")))
+ pw = getpwnam(s);
+ else
+ pw = getpwuid(getuid());
+ if (pw)
+ ret = new GString(pw->pw_dir);
+ else
+ ret = new GString(".");
+ }
+ return ret;
+#endif
+}
+
+GString *getCurrentDir() {
+ char buf[PATH_MAX+1];
+
+#if defined(__EMX__)
+ if (_getcwd2(buf, sizeof(buf)))
+#elif defined(WIN32)
+ if (GetCurrentDirectory(sizeof(buf), buf))
+#elif defined(ACORN)
+ if (strcpy(buf, "@"))
+#elif defined(MACOS)
+ if (strcpy(buf, ":"))
+#else
+ if (getcwd(buf, sizeof(buf)))
+#endif
+ return new GString(buf);
+ return new GString();
+}
+
+GString *appendToPath(GString *path, const char *fileName) {
+#if defined(VMS)
+ //---------- VMS ----------
+ //~ this should handle everything necessary for file
+ //~ requesters, but it's certainly not complete
+ char *p0, *p1, *p2;
+ char *q1;
+
+ p0 = path->getCString();
+ p1 = p0 + path->getLength() - 1;
+ if (!strcmp(fileName, "-")) {
+ if (*p1 == ']') {
+ for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
+ if (*p2 == '[')
+ ++p2;
+ path->del(p2 - p0, p1 - p2);
+ } else if (*p1 == ':') {
+ path->append("[-]");
+ } else {
+ path->clear();
+ path->append("[-]");
+ }
+ } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
+ if (*p1 == ']') {
+ path->insert(p1 - p0, '.');
+ path->insert(p1 - p0 + 1, fileName, q1 - fileName);
+ } else if (*p1 == ':') {
+ path->append('[');
+ path->append(']');
+ path->append(fileName, q1 - fileName);
+ } else {
+ path->clear();
+ path->append(fileName, q1 - fileName);
+ }
+ } else {
+ if (*p1 != ']' && *p1 != ':')
+ path->clear();
+ path->append(fileName);
+ }
+ return path;
+
+#elif defined(WIN32)
+ //---------- Win32 ----------
+ GString *tmp;
+ char buf[256];
+ char *fp;
+
+ tmp = new GString(path);
+ tmp->append('/');
+ tmp->append(fileName);
+ GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
+ delete tmp;
+ path->clear();
+ path->append(buf);
+ return path;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ char *p;
+ int i;
+
+ path->append(".");
+ i = path->getLength();
+ path->append(fileName);
+ for (p = path->getCString() + i; *p; ++p) {
+ if (*p == '/') {
+ *p = '.';
+ } else if (*p == '.') {
+ *p = '/';
+ }
+ }
+ return path;
+
+#elif defined(MACOS)
+ //---------- MacOS ----------
+ char *p;
+ int i;
+
+ path->append(":");
+ i = path->getLength();
+ path->append(fileName);
+ for (p = path->getCString() + i; *p; ++p) {
+ if (*p == '/') {
+ *p = ':';
+ } else if (*p == '.') {
+ *p = ':';
+ }
+ }
+ return path;
+
+#elif defined(__EMX__)
+ //---------- OS/2+EMX ----------
+ int i;
+
+ // appending "." does nothing
+ if (!strcmp(fileName, "."))
+ return path;
+
+ // appending ".." goes up one directory
+ if (!strcmp(fileName, "..")) {
+ for (i = path->getLength() - 2; i >= 0; --i) {
+ if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
+ path->getChar(i) == ':')
+ break;
+ }
+ if (i <= 0) {
+ if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
+ path->del(1, path->getLength() - 1);
+ } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
+ path->del(2, path->getLength() - 2);
+ } else {
+ path->clear();
+ path->append("..");
+ }
+ } else {
+ if (path->getChar(i-1) == ':')
+ ++i;
+ path->del(i, path->getLength() - i);
+ }
+ return path;
+ }
+
+ // otherwise, append "/" and new path component
+ if (path->getLength() > 0 &&
+ path->getChar(path->getLength() - 1) != '/' &&
+ path->getChar(path->getLength() - 1) != '\\')
+ path->append('/');
+ path->append(fileName);
+ return path;
+
+#else
+ //---------- Unix ----------
+ int i;
+
+ // appending "." does nothing
+ if (!strcmp(fileName, "."))
+ return path;
+
+ // appending ".." goes up one directory
+ if (!strcmp(fileName, "..")) {
+ for (i = path->getLength() - 2; i >= 0; --i) {
+ if (path->getChar(i) == '/')
+ break;
+ }
+ if (i <= 0) {
+ if (path->getChar(0) == '/') {
+ path->del(1, path->getLength() - 1);
+ } else {
+ path->clear();
+ path->append("..");
+ }
+ } else {
+ path->del(i, path->getLength() - i);
+ }
+ return path;
+ }
+
+ // otherwise, append "/" and new path component
+ if (path->getLength() > 0 &&
+ path->getChar(path->getLength() - 1) != '/')
+ path->append('/');
+ path->append(fileName);
+ return path;
+#endif
+}
+
+GString *grabPath(const char *fileName) {
+#ifdef VMS
+ //---------- VMS ----------
+ char *p;
+
+ if ((p = strrchr(fileName, ']')))
+ return new GString(fileName, p + 1 - fileName);
+ if ((p = strrchr(fileName, ':')))
+ return new GString(fileName, p + 1 - fileName);
+ return new GString();
+
+#elif defined(__EMX__) || defined(WIN32)
+ //---------- OS/2+EMX and Win32 ----------
+ char *p;
+
+ if ((p = strrchr(fileName, '/')))
+ return new GString(fileName, p - fileName);
+ if ((p = strrchr(fileName, '\\')))
+ return new GString(fileName, p - fileName);
+ if ((p = strrchr(fileName, ':')))
+ return new GString(fileName, p + 1 - fileName);
+ return new GString();
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ char *p;
+
+ if ((p = strrchr(fileName, '.')))
+ return new GString(fileName, p - fileName);
+ return new GString();
+
+#elif defined(MACOS)
+ //---------- MacOS ----------
+ char *p;
+
+ if ((p = strrchr(fileName, ':')))
+ return new GString(fileName, p - fileName);
+ return new GString();
+
+#else
+ //---------- Unix ----------
+ const char *p;
+
+ if ((p = strrchr(fileName, '/')))
+ return new GString(fileName, p - fileName);
+ return new GString();
+#endif
+}
+
+GBool isAbsolutePath(const char *path) {
+#ifdef VMS
+ //---------- VMS ----------
+ return strchr(path, ':') ||
+ (path[0] == '[' && path[1] != '.' && path[1] != '-');
+
+#elif defined(__EMX__) || defined(WIN32)
+ //---------- OS/2+EMX and Win32 ----------
+ return path[0] == '/' || path[0] == '\\' || path[1] == ':';
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ return path[0] == '$';
+
+#elif defined(MACOS)
+ //---------- MacOS ----------
+ return path[0] != ':';
+
+#else
+ //---------- Unix ----------
+ return path[0] == '/';
+#endif
+}
+
+GString *makePathAbsolute(GString *path) {
+#ifdef VMS
+ //---------- VMS ----------
+ char buf[PATH_MAX+1];
+
+ if (!isAbsolutePath(path->getCString())) {
+ if (getcwd(buf, sizeof(buf))) {
+ path->insert(0, buf);
+ }
+ }
+ return path;
+
+#elif defined(WIN32)
+ //---------- Win32 ----------
+ char buf[_MAX_PATH];
+ char *fp;
+
+ buf[0] = '\0';
+ if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
+ path->clear();
+ return path;
+ }
+ path->clear();
+ path->append(buf);
+ return path;
+
+#elif defined(ACORN)
+ //---------- RISCOS ----------
+ path->insert(0, '@');
+ return path;
+
+#elif defined(MACOS)
+ //---------- MacOS ----------
+ path->del(0, 1);
+ return path;
+
+#else
+ //---------- Unix and OS/2+EMX ----------
+ struct passwd *pw;
+ char buf[PATH_MAX+1];
+ GString *s;
+ char *p1, *p2;
+ int n;
+
+ if (path->getChar(0) == '~') {
+ if (path->getChar(1) == '/' ||
+#ifdef __EMX__
+ path->getChar(1) == '\\' ||
+#endif
+ path->getLength() == 1) {
+ path->del(0, 1);
+ s = getHomeDir();
+ path->insert(0, s);
+ delete s;
+ } else {
+ p1 = path->getCString() + 1;
+#ifdef __EMX__
+ for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
+#else
+ for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
+#endif
+ if ((n = p2 - p1) > PATH_MAX)
+ n = PATH_MAX;
+ strncpy(buf, p1, n);
+ buf[n] = '\0';
+ if ((pw = getpwnam(buf))) {
+ path->del(0, p2 - p1 + 1);
+ path->insert(0, pw->pw_dir);
+ }
+ }
+ } else if (!isAbsolutePath(path->getCString())) {
+ if (getcwd(buf, sizeof(buf))) {
+#ifndef __EMX__
+ path->insert(0, '/');
+#endif
+ path->insert(0, buf);
+ }
+ }
+ return path;
+#endif
+}
+
+time_t getModTime(const char *fileName) {
+#ifdef WIN32
+ //~ should implement this, but it's (currently) only used in xpdf
+ return 0;
+#else
+ struct stat statBuf;
+
+ if (stat(fileName, &statBuf)) {
+ return 0;
+ }
+ return statBuf.st_mtime;
+#endif
+}
+
+#if 0 // MRS: This function is apparently no longer used...
+GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext) {
+#if defined(WIN32)
+ //---------- Win32 ----------
+ char *s;
+
+ if (!(s = _tempnam(getenv("TEMP"), NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ free(s);
+ if (ext) {
+ (*name)->append(ext);
+ }
+ if (!(*f = fopen((*name)->getCString(), mode))) {
+ delete (*name);
+ return gFalse;
+ }
+ return gTrue;
+#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
+ //---------- non-Unix ----------
+ char *s;
+
+ // There is a security hole here: an attacker can create a symlink
+ // with this file name after the tmpnam call and before the fopen
+ // call. I will happily accept fixes to this function for non-Unix
+ // OSs.
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ if (ext) {
+ (*name)->append(ext);
+ }
+ if (!(*f = fopen((*name)->getCString(), mode))) {
+ delete (*name);
+ return gFalse;
+ }
+ return gTrue;
+#else
+ //---------- Unix ----------
+ char *s;
+ int fd;
+
+ if (ext) {
+#if HAVE_MKSTEMPS
+ if ((s = getenv("TMPDIR"))) {
+ *name = new GString(s);
+ } else {
+ *name = new GString("/tmp");
+ }
+ (*name)->append("/XXXXXX")->append(ext);
+ fd = mkstemps((*name)->getCString(), strlen(ext));
+#else
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ (*name)->append(ext);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#endif
+ } else {
+#if HAVE_MKSTEMP
+ if ((s = getenv("TMPDIR"))) {
+ *name = new GString(s);
+ } else {
+ *name = new GString("/tmp");
+ }
+ (*name)->append("/XXXXXX");
+ fd = mkstemp((*name)->getCString());
+#else // HAVE_MKSTEMP
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+#endif // HAVE_MKSTEMP
+ }
+ if (fd < 0 || !(*f = fdopen(fd, mode))) {
+ delete *name;
+ return gFalse;
+ }
+ return gTrue;
+#endif
+}
+#endif // 0
+
+GBool executeCommand(const char *cmd) {
+#ifdef VMS
+ return system(cmd) ? gTrue : gFalse;
+#else
+ return system(cmd) ? gFalse : gTrue;
+#endif
+}
+
+char *getLine(char *buf, int size, FILE *f) {
+ int c, i;
+
+ i = 0;
+ while (i < size - 1) {
+ if ((c = fgetc(f)) == EOF) {
+ break;
+ }
+ buf[i++] = (char)c;
+ if (c == '\x0a') {
+ break;
+ }
+ if (c == '\x0d') {
+ c = fgetc(f);
+ if (c == '\x0a' && i < size - 1) {
+ buf[i++] = (char)c;
+ } else if (c != EOF) {
+ ungetc(c, f);
+ }
+ break;
+ }
+ }
+ buf[i] = '\0';
+ if (i == 0) {
+ return NULL;
+ }
+ return buf;
+}
+
+//------------------------------------------------------------------------
+// GDir and GDirEntry
+//------------------------------------------------------------------------
+
+GDirEntry::GDirEntry(const char *dirPath, const char *nameA, GBool doStat) {
+#ifdef VMS
+ char *p;
+#elif defined(WIN32)
+ int fa;
+ GString *s;
+#elif defined(ACORN)
+#else
+ struct stat st;
+ GString *s;
+#endif
+
+ name = new GString(nameA);
+ dir = gFalse;
+ if (doStat) {
+#ifdef VMS
+ if (!strcmp(nameA, "-") ||
+ ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
+ dir = gTrue;
+#elif defined(ACORN)
+#else
+ s = new GString(dirPath);
+ appendToPath(s, nameA);
+#ifdef WIN32
+ fa = GetFileAttributes(s->getCString());
+ dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
+#else
+ if (stat(s->getCString(), &st) == 0)
+ dir = S_ISDIR(st.st_mode);
+#endif
+ delete s;
+#endif
+ }
+}
+
+GDirEntry::~GDirEntry() {
+ delete name;
+}
+
+GDir::GDir(const char *name, GBool doStatA) {
+ path = new GString(name);
+ doStat = doStatA;
+#if defined(WIN32)
+ GString *tmp;
+
+ tmp = path->copy();
+ tmp->append("/*.*");
+ hnd = FindFirstFile(tmp->getCString(), &ffd);
+ delete tmp;
+#elif defined(ACORN)
+#elif defined(MACOS)
+#else
+ dir = opendir(name);
+#ifdef VMS
+ needParent = strchr(name, '[') != NULL;
+#endif
+#endif
+}
+
+GDir::~GDir() {
+ delete path;
+#if defined(WIN32)
+ if (hnd) {
+ FindClose(hnd);
+ hnd = NULL;
+ }
+#elif defined(ACORN)
+#elif defined(MACOS)
+#else
+ if (dir)
+ closedir(dir);
+#endif
+}
+
+GDirEntry *GDir::getNextEntry() {
+ GDirEntry *e;
+
+#if defined(WIN32)
+ e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
+ if (hnd && !FindNextFile(hnd, &ffd)) {
+ FindClose(hnd);
+ hnd = NULL;
+ }
+#elif defined(ACORN)
+#elif defined(MACOS)
+#elif defined(VMS)
+ struct dirent *ent;
+ e = NULL;
+ if (dir) {
+ if (needParent) {
+ e = new GDirEntry(path->getCString(), "-", doStat);
+ needParent = gFalse;
+ return e;
+ }
+ ent = readdir(dir);
+ if (ent) {
+ e = new GDirEntry(path->getCString(), ent->d_name, doStat);
+ }
+ }
+#else
+ struct dirent *ent;
+ e = NULL;
+ if (dir) {
+ ent = readdir(dir);
+ if (ent && !strcmp(ent->d_name, ".")) {
+ ent = readdir(dir);
+ }
+ if (ent) {
+ e = new GDirEntry(path->getCString(), ent->d_name, doStat);
+ }
+ }
+#endif
+
+ return e;
+}
+
+void GDir::rewind() {
+#ifdef WIN32
+ GString *tmp;
+
+ if (hnd)
+ FindClose(hnd);
+ tmp = path->copy();
+ tmp->append("/*.*");
+ hnd = FindFirstFile(tmp->getCString(), &ffd);
+#elif defined(ACORN)
+#elif defined(MACOS)
+#else
+ if (dir)
+ rewinddir(dir);
+#ifdef VMS
+ needParent = strchr(path->getCString(), '[') != NULL;
+#endif
+#endif
+}
diff --git a/pdftops/gfile.h b/pdftops/gfile.h
new file mode 100644
index 000000000..f5d592de3
--- /dev/null
+++ b/pdftops/gfile.h
@@ -0,0 +1,138 @@
+//========================================================================
+//
+// gfile.h
+//
+// Miscellaneous file and directory name manipulation.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#ifndef GFILE_H
+#define GFILE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#if defined(WIN32)
+# include <sys/stat.h>
+# ifdef FPTEX
+# include <win32lib.h>
+# else
+# include <windows.h>
+# endif
+#elif defined(ACORN)
+#elif defined(MACOS)
+# include <ctime.h>
+#else
+# include <unistd.h>
+# include <sys/types.h>
+# ifdef VMS
+# include "vms_dirent.h"
+# elif HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(d) strlen((d)->d_name)
+# else
+# define dirent direct
+# define NAMLEN(d) (d)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+# endif
+#endif
+#include "gtypes.h"
+
+class GString;
+
+//------------------------------------------------------------------------
+
+// Get home directory path.
+extern GString *getHomeDir();
+
+// Get current directory.
+extern GString *getCurrentDir();
+
+// Append a file name to a path string. <path> may be an empty
+// string, denoting the current directory). Returns <path>.
+extern GString *appendToPath(GString *path, const char *fileName);
+
+// Grab the path from the front of the file name. If there is no
+// directory component in <fileName>, returns an empty string.
+extern GString *grabPath(const char *fileName);
+
+// Is this an absolute path or file name?
+extern GBool isAbsolutePath(const char *path);
+
+// Make this path absolute by prepending current directory (if path is
+// relative) or prepending user's directory (if path starts with '~').
+extern GString *makePathAbsolute(GString *path);
+
+// Get the modification time for <fileName>. Returns 0 if there is an
+// error.
+extern time_t getModTime(char *fileName);
+
+// Create a temporary file and open it for writing. If <ext> is not
+// NULL, it will be used as the file name extension. Returns both the
+// name and the file pointer. For security reasons, all writing
+// should be done to the returned file pointer; the file may be
+// reopened later for reading, but not for writing. The <mode> string
+// should be "w" or "wb". Returns true on success.
+extern GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext);
+
+// Execute <command>. Returns true on success.
+extern GBool executeCommand(const char *cmd);
+
+// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line
+// conventions.
+extern char *getLine(char *buf, int size, FILE *f);
+
+//------------------------------------------------------------------------
+// GDir and GDirEntry
+//------------------------------------------------------------------------
+
+class GDirEntry {
+public:
+
+ GDirEntry(const char *dirPath, const char *nameA, GBool doStat);
+ ~GDirEntry();
+ GString *getName() { return name; }
+ GBool isDir() { return dir; }
+
+private:
+
+ GString *name; // dir/file name
+ GBool dir; // is it a directory?
+};
+
+class GDir {
+public:
+
+ GDir(const char *name, GBool doStatA = gTrue);
+ ~GDir();
+ GDirEntry *getNextEntry();
+ void rewind();
+
+private:
+
+ GString *path; // directory path
+ GBool doStat; // call stat() for each entry?
+#if defined(WIN32)
+ WIN32_FIND_DATA ffd;
+ HANDLE hnd;
+#elif defined(ACORN)
+#elif defined(MACOS)
+#else
+ DIR *dir; // the DIR structure from opendir()
+#ifdef VMS
+ GBool needParent; // need to return an entry for [-]
+#endif
+#endif
+};
+
+#endif
diff --git a/pdftops/gmem.c b/pdftops/gmem.c
new file mode 100644
index 000000000..35bcc46f8
--- /dev/null
+++ b/pdftops/gmem.c
@@ -0,0 +1,204 @@
+/*
+ * gmem.c
+ *
+ * Memory routines with out-of-memory checking.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include "gmem.h"
+
+#ifdef DEBUG_MEM
+
+typedef struct _GMemHdr {
+ int size;
+ int index;
+ struct _GMemHdr *next;
+} GMemHdr;
+
+#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
+#define gMemTrlSize (sizeof(long))
+
+#if gmemTrlSize==8
+#define gMemDeadVal 0xdeadbeefdeadbeefUL
+#else
+#define gMemDeadVal 0xdeadbeefUL
+#endif
+
+/* round data size so trailer will be aligned */
+#define gMemDataSize(size) \
+ ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
+
+#define gMemNLists 64
+#define gMemListShift 4
+#define gMemListMask (gMemNLists - 1)
+static GMemHdr *gMemList[gMemNLists] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static int gMemIndex = 0;
+static int gMemAlloc = 0;
+
+#endif /* DEBUG_MEM */
+
+void *gmalloc(int size) {
+#ifdef DEBUG_MEM
+ int size1;
+ char *mem;
+ GMemHdr *hdr;
+ void *data;
+ int lst;
+ unsigned long *trl, *p;
+
+ if (size == 0)
+ return NULL;
+ size1 = gMemDataSize(size);
+ if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ hdr = (GMemHdr *)mem;
+ data = (void *)(mem + gMemHdrSize);
+ trl = (unsigned long *)(mem + gMemHdrSize + size1);
+ hdr->size = size;
+ hdr->index = gMemIndex++;
+ lst = ((int)hdr >> gMemListShift) & gMemListMask;
+ hdr->next = gMemList[lst];
+ gMemList[lst] = hdr;
+ ++gMemAlloc;
+ for (p = (unsigned long *)data; p <= trl; ++p)
+ *p = gMemDeadVal;
+ return data;
+#else
+ void *p;
+
+ if (size == 0)
+ return NULL;
+ if (!(p = malloc(size))) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return p;
+#endif
+}
+
+void *grealloc(void *p, int size) {
+#ifdef DEBUG_MEM
+ GMemHdr *hdr;
+ void *q;
+ int oldSize;
+
+ if (size == 0) {
+ if (p)
+ gfree(p);
+ return NULL;
+ }
+ if (p) {
+ hdr = (GMemHdr *)((char *)p - gMemHdrSize);
+ oldSize = hdr->size;
+ q = gmalloc(size);
+ memcpy(q, p, size < oldSize ? size : oldSize);
+ gfree(p);
+ } else {
+ q = gmalloc(size);
+ }
+ return q;
+#else
+ void *q;
+
+ if (size == 0) {
+ if (p)
+ free(p);
+ return NULL;
+ }
+ if (p)
+ q = realloc(p, size);
+ else
+ q = malloc(size);
+ if (!q) {
+ fprintf(stderr, "Out of memory\n");
+ exit(1);
+ }
+ return q;
+#endif
+}
+
+void gfree(void *p) {
+#ifdef DEBUG_MEM
+ int size;
+ GMemHdr *hdr;
+ GMemHdr *prevHdr, *q;
+ int lst;
+ unsigned long *trl, *clr;
+
+ if (p) {
+ hdr = (GMemHdr *)((char *)p - gMemHdrSize);
+ lst = ((int)hdr >> gMemListShift) & gMemListMask;
+ for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) {
+ if (q == hdr)
+ break;
+ }
+ if (q) {
+ if (prevHdr)
+ prevHdr->next = hdr->next;
+ else
+ gMemList[lst] = hdr->next;
+ --gMemAlloc;
+ size = gMemDataSize(hdr->size);
+ trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
+ if (*trl != gMemDeadVal) {
+ fprintf(stderr, "Overwrite past end of block %d at address %p\n",
+ hdr->index, p);
+ }
+ for (clr = (unsigned long *)hdr; clr <= trl; ++clr)
+ *clr = gMemDeadVal;
+ free(hdr);
+ } else {
+ fprintf(stderr, "Attempted to free bad address %p\n", p);
+ }
+ }
+#else
+ if (p)
+ free(p);
+#endif
+}
+
+#ifdef DEBUG_MEM
+void gMemReport(FILE *f) {
+ GMemHdr *p;
+ int lst;
+
+ fprintf(f, "%d memory allocations in all\n", gMemIndex);
+ if (gMemAlloc > 0) {
+ fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
+ fprintf(f, " index size\n");
+ fprintf(f, "-------- --------\n");
+ for (lst = 0; lst < gMemNLists; ++lst) {
+ for (p = gMemList[lst]; p; p = p->next)
+ fprintf(f, "%8d %8d\n", p->index, p->size);
+ }
+ } else {
+ fprintf(f, "No memory blocks left allocated\n");
+ }
+}
+#endif
+
+char *copyString(const char *s) {
+ char *s1;
+
+ s1 = (char *)gmalloc(strlen(s) + 1);
+ strcpy(s1, s);
+ return s1;
+}
diff --git a/pdftops/gmem.h b/pdftops/gmem.h
new file mode 100644
index 000000000..03fab6033
--- /dev/null
+++ b/pdftops/gmem.h
@@ -0,0 +1,53 @@
+/*
+ * gmem.h
+ *
+ * Memory routines with out-of-memory checking.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef GMEM_H
+#define GMEM_H
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Same as malloc, but prints error message and exits if malloc()
+ * returns NULL.
+ */
+extern void *gmalloc(int size);
+
+/*
+ * Same as realloc, but prints error message and exits if realloc()
+ * returns NULL. If <p> is NULL, calls malloc instead of realloc().
+ */
+extern void *grealloc(void *p, int size);
+
+/*
+ * Same as free, but checks for and ignores NULL pointers.
+ */
+extern void gfree(void *p);
+
+#ifdef DEBUG_MEM
+/*
+ * Report on unfreed memory.
+ */
+extern void gMemReport(FILE *f);
+#else
+#define gMemReport(f)
+#endif
+
+/*
+ * Allocate memory and copy a string into it.
+ */
+extern char *copyString(const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/pdftops/gmempp.cxx b/pdftops/gmempp.cxx
new file mode 100644
index 000000000..a70338ca3
--- /dev/null
+++ b/pdftops/gmempp.cxx
@@ -0,0 +1,32 @@
+//========================================================================
+//
+// gmempp.cc
+//
+// Use gmalloc/gfree for C++ new/delete operators.
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <config.h>
+#include "gmem.h"
+
+#ifdef DEBUG_MEM
+
+void *operator new(size_t size) {
+ return gmalloc((int)size);
+}
+
+void *operator new[](size_t size) {
+ return gmalloc((int)size);
+}
+
+void operator delete(void *p) {
+ gfree(p);
+}
+
+void operator delete[](void *p) {
+ gfree(p);
+}
+
+#endif
diff --git a/pdftops/gtypes.h b/pdftops/gtypes.h
new file mode 100644
index 000000000..9f64f57d4
--- /dev/null
+++ b/pdftops/gtypes.h
@@ -0,0 +1,29 @@
+/*
+ * gtypes.h
+ *
+ * Some useful simple types.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef GTYPES_H
+#define GTYPES_H
+
+/*
+ * These have stupid names to avoid conflicts with some (but not all)
+ * C++ compilers which define them.
+ */
+typedef int GBool;
+#define gTrue 1
+#define gFalse 0
+
+/*
+ * These have stupid names to avoid conflicts with <sys/types.h>,
+ * which on various systems defines some random subset of these.
+ */
+typedef unsigned char Guchar;
+typedef unsigned short Gushort;
+typedef unsigned int Guint;
+typedef unsigned long Gulong;
+
+#endif
diff --git a/pdftops/parseargs.c b/pdftops/parseargs.c
new file mode 100644
index 000000000..6d9606015
--- /dev/null
+++ b/pdftops/parseargs.c
@@ -0,0 +1,190 @@
+/*
+ * parseargs.h
+ *
+ * Command line argument parser.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "parseargs.h"
+
+static ArgDesc *findArg(ArgDesc *args, char *arg);
+static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]);
+
+GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) {
+ ArgDesc *arg;
+ int i, j;
+ GBool ok;
+
+ ok = gTrue;
+ i = 1;
+ while (i < *argc) {
+ if (!strcmp(argv[i], "--")) {
+ --*argc;
+ for (j = i; j < *argc; ++j)
+ argv[j] = argv[j+1];
+ break;
+ } else if ((arg = findArg(args, argv[i]))) {
+ if (!grabArg(arg, i, argc, argv))
+ ok = gFalse;
+ } else {
+ ++i;
+ }
+ }
+ return ok;
+}
+
+void printUsage(char *program, char *otherArgs, ArgDesc *args) {
+ ArgDesc *arg;
+ const char *typ;
+ int w, w1;
+
+ w = 0;
+ for (arg = args; arg->arg; ++arg) {
+ if ((w1 = strlen(arg->arg)) > w)
+ w = w1;
+ }
+
+ fprintf(stderr, "Usage: %s [options]", program);
+ if (otherArgs)
+ fprintf(stderr, " %s", otherArgs);
+ fprintf(stderr, "\n");
+
+ for (arg = args; arg->arg; ++arg) {
+ fprintf(stderr, " %s", arg->arg);
+ w1 = 9 + w - strlen(arg->arg);
+ switch (arg->kind) {
+ case argInt:
+ case argIntDummy:
+ typ = " <int>";
+ break;
+ case argFP:
+ case argFPDummy:
+ typ = " <fp>";
+ break;
+ case argString:
+ case argStringDummy:
+ typ = " <string>";
+ break;
+ case argFlag:
+ case argFlagDummy:
+ default:
+ typ = "";
+ break;
+ }
+ fprintf(stderr, "%-*s", w1, typ);
+ if (arg->usage)
+ fprintf(stderr, ": %s", arg->usage);
+ fprintf(stderr, "\n");
+ }
+}
+
+static ArgDesc *findArg(ArgDesc *args, char *arg) {
+ ArgDesc *p;
+
+ for (p = args; p->arg; ++p) {
+ if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
+ return p;
+ }
+ return NULL;
+}
+
+static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) {
+ int n;
+ int j;
+ GBool ok;
+
+ ok = gTrue;
+ n = 0;
+ switch (arg->kind) {
+ case argFlag:
+ *(GBool *)arg->val = gTrue;
+ n = 1;
+ break;
+ case argInt:
+ if (i + 1 < *argc && isInt(argv[i+1])) {
+ *(int *)arg->val = atoi(argv[i+1]);
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ case argFP:
+ if (i + 1 < *argc && isFP(argv[i+1])) {
+ *(double *)arg->val = atof(argv[i+1]);
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ case argString:
+ if (i + 1 < *argc) {
+ strncpy((char *)arg->val, argv[i+1], arg->size - 1);
+ ((char *)arg->val)[arg->size - 1] = '\0';
+ n = 2;
+ } else {
+ ok = gFalse;
+ n = 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Internal error in arg table\n");
+ n = 1;
+ break;
+ }
+ if (n > 0) {
+ *argc -= n;
+ for (j = i; j < *argc; ++j)
+ argv[j] = argv[j+n];
+ }
+ return ok;
+}
+
+GBool isInt(char *s) {
+ if (*s == '-' || *s == '+')
+ ++s;
+ while (isdigit(*s & 255))
+ ++s;
+ if (*s)
+ return gFalse;
+ return gTrue;
+}
+
+GBool isFP(char *s) {
+ int n;
+
+ if (*s == '-' || *s == '+')
+ ++s;
+ n = 0;
+ while (isdigit(*s & 255)) {
+ ++s;
+ ++n;
+ }
+ if (*s == '.')
+ ++s;
+ while (isdigit(*s & 255)) {
+ ++s;
+ ++n;
+ }
+ if (n > 0 && (*s == 'e' || *s == 'E')) {
+ ++s;
+ if (*s == '-' || *s == '+')
+ ++s;
+ n = 0;
+ if (!isdigit(*s & 255))
+ return gFalse;
+ do {
+ ++s;
+ } while (isdigit(*s & 255));
+ }
+ if (*s)
+ return gFalse;
+ return gTrue;
+}
diff --git a/pdftops/parseargs.h b/pdftops/parseargs.h
new file mode 100644
index 000000000..0d163b985
--- /dev/null
+++ b/pdftops/parseargs.h
@@ -0,0 +1,71 @@
+/*
+ * parseargs.h
+ *
+ * Command line argument parser.
+ *
+ * Copyright 1996-2003 Glyph & Cog, LLC
+ */
+
+#ifndef PARSEARGS_H
+#define PARSEARGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "gtypes.h"
+
+/*
+ * Argument kinds.
+ */
+typedef enum {
+ argFlag, /* flag (present / not-present) */
+ /* [val: GBool *] */
+ argInt, /* integer arg */
+ /* [val: int *] */
+ argFP, /* floating point arg */
+ /* [val: double *] */
+ argString, /* string arg */
+ /* [val: char *] */
+ /* dummy entries -- these show up in the usage listing only; */
+ /* useful for X args, for example */
+ argFlagDummy,
+ argIntDummy,
+ argFPDummy,
+ argStringDummy
+} ArgKind;
+
+/*
+ * Argument descriptor.
+ */
+typedef struct {
+ char *arg; /* the command line switch */
+ ArgKind kind; /* kind of arg */
+ void *val; /* place to store value */
+ int size; /* for argString: size of string */
+ char *usage; /* usage string */
+} ArgDesc;
+
+/*
+ * Parse command line. Removes all args which are found in the arg
+ * descriptor list <args>. Stops parsing if "--" is found (and removes
+ * it). Returns gFalse if there was an error.
+ */
+extern GBool parseArgs(ArgDesc *args, int *argc, char *argv[]);
+
+/*
+ * Print usage message, based on arg descriptor list.
+ */
+extern void printUsage(char *program, char *otherArgs, ArgDesc *args);
+
+/*
+ * Check if a string is a valid integer or floating point number.
+ */
+extern GBool isInt(char *s);
+extern GBool isFP(char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/pdftops/pdftops.cxx b/pdftops/pdftops.cxx
new file mode 100644
index 000000000..61a4c9deb
--- /dev/null
+++ b/pdftops/pdftops.cxx
@@ -0,0 +1,342 @@
+//
+// "$Id$"
+//
+// PDF to PostScript filter front-end for the Common UNIX Printing
+// System (CUPS).
+//
+// Copyright 1997-2003 by Easy Software Products.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "LICENSE.txt" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: CUPS Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9600
+// EMail: cups-info@cups.org
+// WWW: http://www.cups.org
+//
+// Contents:
+//
+// main() - Main entry for filter...
+//
+
+//
+// Include necessary headers...
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <cups/string.h>
+#include "parseargs.h"
+#include "GString.h"
+#include "gmem.h"
+#include "Object.h"
+#include "Stream.h"
+#include "Array.h"
+#include "Dict.h"
+#include "XRef.h"
+#include "Catalog.h"
+#include "Page.h"
+#include "PDFDoc.h"
+#include "PSOutputDev.h"
+#include "Params.h"
+#include "Error.h"
+#include "config.h"
+
+#include <cups/cups.h>
+
+
+//
+// 'main()' - Main entry for filter...
+//
+
+int // O - Exit status
+main(int argc, // I - Number of command-line args
+ char *argv[]) // I - Command-line arguments
+{
+ PDFDoc *doc; // Input file
+ GString *fileName; // Input filename
+ GString *psFileName; // Output filename
+ PSLevel level; // PostScript level
+ PSOutputDev *psOut; // Output device
+ int num_options; // Number of options
+ cups_option_t *options; // Options
+ const char *val; // Option value
+ ppd_file_t *ppd; // Current PPD
+ ppd_size_t *size; // Current media size
+ FILE *fp; // Copy file
+ const char *server_root; // Location of config files
+ char tempfile[1024]; // Temporary file
+ char buffer[8192]; // Copy buffer
+ int bytes; // Bytes copied
+ int width, length; // Size in points
+ int left, bottom, right, top;
+ // Imageable area in points
+ int orientation; // Orientation
+ int temp; // Temporary var
+ int duplex; // Duplex the output?
+ int fit; // Fit the pages to the output
+ int printCommands; // Output debug info for commands?
+
+
+ // Make sure status messages are not buffered...
+ setbuf(stderr, NULL);
+
+ // Make sure we have the right number of arguments for CUPS!
+ if (argc < 6 || argc > 7) {
+ fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
+ return (1);
+ }
+
+ // Copy stdin if needed...
+ if (argc == 6) {
+ if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) {
+ perror("ERROR: Unable to copy PDF file");
+ return (1);
+ }
+
+ fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
+ tempfile);
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ fwrite(buffer, 1, bytes, fp);
+ fclose(fp);
+
+ fileName = new GString(tempfile);
+ } else {
+ fileName = new GString(argv[6]);
+ tempfile[0] = '\0';
+ }
+
+ // Default to "Universal" size - min of A4 and Letter...
+ left = 0;
+ bottom = 0;
+ right = 595;
+ top = 792;
+ width = 595;
+ length = 792;
+ level = psLevel2;
+ duplex = 0;
+ fit = 0;
+
+ // Get PPD and initialize options as needed...
+ num_options = cupsParseOptions(argv[5], 0, &options);
+
+ if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
+ {
+ fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD"));
+
+ ppdMarkDefaults(ppd);
+ cupsMarkOptions(ppd, num_options, options);
+
+ if ((size = ppdPageSize(ppd, NULL)) != NULL)
+ {
+ left = (int)size->left;
+ bottom = (int)size->bottom;
+ right = (int)size->right;
+ top = (int)size->top;
+ width = (int)size->width;
+ length = (int)size->length;
+ }
+
+ level = ppd->language_level == 1 ? psLevel1 : psLevel2;
+ }
+
+ // Track the orientation of the print job and update the page
+ // dimensions and margins as needed...
+ orientation = 0;
+
+ if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
+ {
+ if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 &&
+ strcasecmp(val, "false") != 0)
+ orientation = 1;
+ }
+ else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL)
+ {
+ /*
+ * Map IPP orientation values to 0 to 3:
+ *
+ * 3 = 0 degrees = 0
+ * 4 = 90 degrees = 1
+ * 5 = -90 degrees = 3
+ * 6 = 180 degrees = 2
+ */
+
+ orientation = atoi(val) - 3;
+ if (orientation >= 2)
+ orientation ^= 1;
+ }
+
+ switch (orientation & 3)
+ {
+ case 0 : /* Portait */
+ break;
+
+ case 1 : /* Landscape */
+ temp = left;
+ left = bottom;
+ bottom = temp;
+
+ temp = right;
+ right = top;
+ top = temp;
+
+ temp = width;
+ width = length;
+ length = temp;
+ break;
+
+ case 2 : /* Reverse Portrait */
+ temp = width - left;
+ left = width - right;
+ right = temp;
+
+ temp = length - bottom;
+ bottom = length - top;
+ top = temp;
+ break;
+
+ case 3 : /* Reverse Landscape */
+ temp = width - left;
+ left = width - right;
+ right = temp;
+
+ temp = length - bottom;
+ bottom = length - top;
+ top = temp;
+
+ temp = left;
+ left = bottom;
+ bottom = temp;
+
+ temp = right;
+ right = top;
+ top = temp;
+
+ temp = width;
+ width = length;
+ length = temp;
+ break;
+ }
+
+ if ((val = cupsGetOption("debug", num_options, options)) != NULL &&
+ strcasecmp(val, "no") && strcasecmp(val, "off") &&
+ strcasecmp(val, "false"))
+ printCommands = 1;
+ else
+ printCommands = 0;
+
+ if ((val = cupsGetOption("fitplot", num_options, options)) != NULL &&
+ strcasecmp(val, "no") && strcasecmp(val, "off") &&
+ strcasecmp(val, "false"))
+ fit = 1;
+
+ if ((val = cupsGetOption("sides", num_options, options)) != NULL &&
+ strncasecmp(val, "two-", 4) == 0)
+ duplex = 1;
+ else if ((val = cupsGetOption("Duplex", num_options, options)) != NULL &&
+ strncasecmp(val, "Duplex", 6) == 0)
+ duplex = 1;
+ else if ((val = cupsGetOption("JCLDuplex", num_options, options)) != NULL &&
+ strncasecmp(val, "Duplex", 6) == 0)
+ duplex = 1;
+ else if ((val = cupsGetOption("EFDuplex", num_options, options)) != NULL &&
+ strncasecmp(val, "Duplex", 6) == 0)
+ duplex = 1;
+ else if ((val = cupsGetOption("KD03Duplex", num_options, options)) != NULL &&
+ strncasecmp(val, "Duplex", 6) == 0)
+ duplex = 1;
+ else if (ppdIsMarked(ppd, "Duplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "Duplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "JCLDuplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "JCLDuplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "EFDuplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "EFDuplex", "DuplexTumble") ||
+ ppdIsMarked(ppd, "KD03Duplex", "DuplexNoTumble") ||
+ ppdIsMarked(ppd, "KD03Duplex", "DuplexTumble"))
+ duplex = 1;
+
+ cupsFreeOptions(num_options, options);
+
+ if (ppd != NULL)
+ ppdClose(ppd);
+
+ fprintf(stderr, "DEBUG: pdftops - level = %d, width = %d, length = %d\n",
+ level, width, length);
+
+ // read config file
+ if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
+ server_root = CUPS_SERVERROOT;
+
+ snprintf(buffer, sizeof(buffer), "%s/pdftops.conf", server_root);
+
+ globalParams = new GlobalParams(buffer);
+
+ globalParams->setPSPaperWidth(width);
+ globalParams->setPSPaperHeight(length);
+ globalParams->setPSImageableArea(left, bottom, right, top);
+ globalParams->setPSDuplex(duplex);
+ globalParams->setPSFit(fit);
+ globalParams->setPSLevel(level);
+ globalParams->setPSASCIIHex(level == psLevel1);
+ globalParams->setPSEmbedType1(1);
+ globalParams->setPSEmbedTrueType(1);
+ globalParams->setPSEmbedCIDPostScript(1);
+ globalParams->setErrQuiet(0);
+ globalParams->setPrintCommands(printCommands);
+
+ if (printCommands)
+ setbuf(stdout, NULL);
+
+ // open PDF file
+ doc = new PDFDoc(fileName, NULL, NULL);
+
+ // check for print permission
+ if (doc->isOk() && doc->okToPrint())
+ {
+ // CUPS always writes to stdout...
+ psFileName = new GString("-");
+
+ // write PostScript file
+ psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
+ doc->getCatalog(), 1, doc->getNumPages(),
+ psModePS);
+ if (psOut->isOk())
+ doc->displayPages(psOut, 1, doc->getNumPages(), 72, 72, 0, gFalse);
+ delete psOut;
+
+ // clean up
+ delete psFileName;
+ }
+ else
+ {
+ error(-1, "Unable to print this document.");
+ }
+
+ delete doc;
+ delete globalParams;
+
+ // check for memory leaks
+ Object::memCheck(stderr);
+ gMemReport(stderr);
+
+ // Remove temp file if needed...
+ if (tempfile[0])
+ unlink(tempfile);
+
+ return 0;
+}
+
+
+//
+// End of "$Id$".
+//
diff --git a/ppd/Makefile b/ppd/Makefile
new file mode 100644
index 000000000..5e00e814e
--- /dev/null
+++ b/ppd/Makefile
@@ -0,0 +1,63 @@
+#
+# "$Id$"
+#
+# PPD file makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# PPD files...
+#
+
+FILES = deskjet.ppd deskjet2.ppd dymo.ppd epson9.ppd epson24.ppd \
+ laserjet.ppd okidata9.ppd okidat24.ppd stcolor.ppd \
+ stcolor2.ppd stphoto.ppd stphoto2.ppd zebra.ppd
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/model
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/model; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/ppd/deskjet.ppd b/ppd/deskjet.ppd
new file mode 100644
index 000000000..36f03dbd9
--- /dev/null
+++ b/ppd/deskjet.ppd
@@ -0,0 +1,198 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample HP DeskJet driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "DESKJET.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 1
+*ModelName: "HP DeskJet Series"
+*ShortNickName: "HP DeskJet Series"
+*NickName: "HP DeskJet Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Resolution 600dpi *ColorModel CMYK
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "18 36 594 756"
+*ImageableArea Legal/US Legal: "18 36 594 972"
+*ImageableArea Executive/US Executive: "18 36 504 684"
+*ImageableArea Tabloid/US Tabloid: "18 36 774 1188"
+*ImageableArea A3/A3: "18 36 824 1155"
+*ImageableArea A4/A4: "18 36 577 806"
+*ImageableArea A5/A5: "18 36 403 559"
+*ImageableArea B5/JIS B5: "18 36 498 693"
+*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673"
+*ImageableArea Env10/Com-10: "18 36 279 648"
+*ImageableArea EnvC5/EnvC5: "18 36 441 613"
+*ImageableArea EnvDL/EnvDL: "18 36 294 588"
+*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *MediaType/Media Type: PickOne
+*OrderDependency: 10 AnySetup *MediaType
+*DefaultMediaType: Plain
+*MediaType Plain/Plain Paper: "<</MediaType(Plain)/cupsMediaType 0>>setpagedevice"
+*MediaType Bond/Bond Paper: "<</MediaType(Bond)/cupsMediaType 1>>setpagedevice"
+*MediaType Special/Special Paper: "<</MediaType(Special)/cupsMediaType 2>>setpagedevice"
+*MediaType Transparency/Transparency: "<</MediaType(Transparency)/cupsMediaType 3>>setpagedevice"
+*MediaType Glossy/Glossy Paper: "<</MediaType(Glossy)/cupsMediaType 4>>setpagedevice"
+*CloseUI: *MediaType
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Tray
+*InputSlot Tray/Tray: "<</cupsMediaPosition 1>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</cupsMediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</cupsMediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 300dpi
+*Resolution 150dpi/150 DPI: "<</HWResolution[150 150]>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]/cupsColorSpace 3>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/CMYK Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 2>>setpagedevice"
+*ColorModel RGB/CMY Color: "<</cupsColorOrder 1/cupsColorSpace 4/cupsCompression 2>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/deskjet2.ppd b/ppd/deskjet2.ppd
new file mode 100644
index 000000000..919d563eb
--- /dev/null
+++ b/ppd/deskjet2.ppd
@@ -0,0 +1,217 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Second sample HP DeskJet driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "DESKJET2.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 2
+*cupsFlipDuplex: True
+*cupsColorProfile -/-: "1.0 1.5 1.0 -0.25 -0.225 -0.25 1.0 -0.225 -0.25 -0.25 0.9"
+
+*ModelName: "HP New DeskJet Series"
+*ShortNickName: "HP New DeskJet Series"
+*NickName: "HP New DeskJet Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Duplex *Option1 False
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "18 36 594 786"
+*ImageableArea Legal/US Legal: "18 36 594 1002"
+*ImageableArea Executive/US Executive: "18 36 504 714"
+*ImageableArea Tabloid/US Tabloid: "18 36 774 1218"
+*ImageableArea A3/A3: "18 36 824 1185"
+*ImageableArea A4/A4: "18 36 577 836"
+*ImageableArea A5/A5: "18 36 403 589"
+*ImageableArea B5/JIS B5: "18 36 498 723"
+*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 703"
+*ImageableArea Env10/Com-10: "18 36 279 678"
+*ImageableArea EnvC5/EnvC5: "18 36 441 643"
+*ImageableArea EnvDL/EnvDL: "18 36 294 618"
+*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 534"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *MediaType/Media Type: PickOne
+*OrderDependency: 10 AnySetup *MediaType
+*DefaultMediaType: Plain
+*MediaType Plain/Plain Paper: "<</MediaType(Plain)/cupsMediaType 0>>setpagedevice"
+*MediaType Bond/Bond Paper: "<</MediaType(Bond)/cupsMediaType 1>>setpagedevice"
+*MediaType Special/Special Paper: "<</MediaType(Special)/cupsMediaType 2>>setpagedevice"
+*MediaType Transparency/Transparency: "<</MediaType(Transparency)/cupsMediaType 3>>setpagedevice"
+*MediaType Glossy/Glossy Paper: "<</MediaType(Glossy)/cupsMediaType 4>>setpagedevice"
+*CloseUI: *MediaType
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Tray
+*InputSlot Tray/Tray: "<</cupsMediaPosition 1>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</cupsMediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</cupsMediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 300dpi
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*Resolution 600x300dpi/600x300 DPI: "<</HWResolution[600 300]>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK2/CRET Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 2/cupsBitsPerColor 2>>setpagedevice"
+*ColorModel CMYK/CMYK Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 2>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*CloseUI: *ColorModel
+
+*OpenUI *Duplex/Double-Sided Printing: PickOne
+*OrderDependency: 20 PageSetup *Duplex
+*DefaultDuplex: None
+*Duplex None/Off: "<</Duplex false>>setpagedevice"
+*Duplex DuplexNoTumble/Long Edge (Standard): "<</Duplex true/Tumble false>>setpagedevice"
+*Duplex DuplexTumble/Short Edge (Flip): "<</Duplex true/Tumble true>>setpagedevice"
+*CloseUI: *Duplex
+
+*OpenGroup: InstallableOptions
+*OpenUI *Option1/Duplexer: Boolean
+*DefaultOption1: False
+*Option1 True/Installed: ""
+*Option1 False/Not Installed: ""
+*CloseUI: *Option1
+*CloseGroup: InstallableOptions
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/dymo.ppd b/ppd/dymo.ppd
new file mode 100644
index 000000000..418f8a530
--- /dev/null
+++ b/ppd/dymo.ppd
@@ -0,0 +1,155 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample DYMO label printer driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 2001-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "DYMO.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: False
+*cupsFilter: "application/vnd.cups-raster 0 rastertodymo"
+*cupsModelNumber: 0
+*ModelName: "DYMO Label Printer"
+*ShortNickName: "DYMO Label Printer"
+*NickName: "DYMO Label Printer CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "8"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: w81h252
+*PageSize w81h252/Address - 1 1/8 x 3 1/2": "<</PageSize[81 252]/ImagingBBox null>>setpagedevice"
+*PageSize w101h252/Large Address - 1 4/10 x 3 1/2": "<</PageSize[101 252]/ImagingBBox null>>setpagedevice"
+*PageSize w54h144/Return Address - 3/4 x 2": "<</PageSize[54 144]/ImagingBBox null>>setpagedevice"
+*PageSize w167h288/Shipping Address - 2 5/16 x 4": "<</PageSize[167 288]/ImagingBBox null>>setpagedevice"
+*PageSize w162h540/Internet Postage 2-Part - 2 1/4 x 7 1/2": "<</PageSize[162 540]/ImagingBBox null>>setpagedevice"
+*PageSize w162h504/Internet Postage 3-Part - 2 1/4 x 7": "<</PageSize[162 504]/ImagingBBox null>>setpagedevice"
+*PageSize w41h248/File Folder - 9/16 x 3 7/16": "<</PageSize[41 248]/ImagingBBox null>>setpagedevice"
+*PageSize w41h144/Hanging Folder - 9/16 x 2": "<</PageSize[41 144]/ImagingBBox null>>setpagedevice"
+*PageSize w153h198/3.5" Disk - 2 1/8 x 2 3/4": "<</PageSize[153 198]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: w81h252
+*PageRegion w81h252/Address - 1 1/8 x 3 1/2": "<</PageSize[81 252]/ImagingBBox null>>setpagedevice"
+*PageRegion w101h252/Large Address - 1 4/10 x 3 1/2": "<</PageSize[101 252]/ImagingBBox null>>setpagedevice"
+*PageRegion w54h144/Return Address - 3/4 x 2": "<</PageSize[54 144]/ImagingBBox null>>setpagedevice"
+*PageRegion w167h288/Shipping Address - 2 5/16 x 4": "<</PageSize[167 288]/ImagingBBox null>>setpagedevice"
+*PageRegion w162h540/Internet Postage 2-Part - 2 1/4 x 7 1/2": "<</PageSize[162 540]/ImagingBBox null>>setpagedevice"
+*PageRegion w162h504/Internet Postage 3-Part - 2 1/4 x 7": "<</PageSize[162 504]/ImagingBBox null>>setpagedevice"
+*PageRegion w41h248/File Folder - 9/16 x 3 7/16": "<</PageSize[41 248]/ImagingBBox null>>setpagedevice"
+*PageRegion w41h144/Hanging Folder - 9/16 x 2": "<</PageSize[41 144]/ImagingBBox null>>setpagedevice"
+*PageRegion w153h198/3.5" Disk - 2 1/8 x 2 3/4": "<</PageSize[153 198]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: w81h252
+*ImageableArea w81h252/Address - 1 1/8 x 3 1/2": "2 14.9 79 237.1"
+*ImageableArea w101h252/Large Address - 1 4/10 x 3 1/2": "2 14.9 99 237.1"
+*ImageableArea w54h144/Return Address - 3/4 x 2": "2 14.9 52 129.1"
+*ImageableArea w167h288/Shipping Address - 2 5/16 x 4": "2 14.9 165 273.1"
+*ImageableArea w162h540/Internet Postage 2-Part - 2 1/4 x 7 1/2": "2 14.9 160 525.1"
+*ImageableArea w162h504/Internet Postage 3-Part - 2 1/4 x 7": "2 14.9 160 489.1"
+*ImageableArea w41h248/File Folder - 9/16 x 3 7/16": "2 14.9 39 233.1"
+*ImageableArea w41h144/Hanging Folder - 9/16 x 2": "2 14.9 39 129.1"
+*ImageableArea w153h198/3.5" Disk - 2 1/8 x 2 3/4": "2 14.9 151 183.1"
+
+*DefaultPaperDimension: w81h252
+*PaperDimension w81h252/Address - 1 1/8 x 3 1/2": "81 252"
+*PaperDimension w101h252/Large Address - 1 4/10 x 3 1/2": "101 252"
+*PaperDimension w54h144/Return Address - 3/4 x 2": "54 144"
+*PaperDimension w167h288/Shipping Address - 2 5/16 x 4": "167 288"
+*PaperDimension w162h540/Internet Postage 2-Part - 2 1/4 x 7 1/2": "162 540"
+*PaperDimension w162h504/Internet Postage 3-Part - 2 1/4 x 7": "162 504"
+*PaperDimension w41h248/File Folder - 9/16 x 3 7/16": "41 248"
+*PaperDimension w41h144/Hanging Folder - 9/16 x 2": "41 144"
+*PaperDimension w153h198/3.5" Disk - 2 1/8 x 2 3/4": "153 198"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 300dpi
+*Resolution 136dpi/136 DPI: "<</HWResolution[136 136]>>setpagedevice"
+*Resolution 203dpi/203 DPI: "<</HWResolution[203 203]>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *Darkness/Output Darkness: PickOne
+*OrderDependency: 20 AnySetup *Darkness
+*DefaultDarkness: Normal
+*Darkness Light: "<</cupsCompression 0>>setpagedevice"
+*Darkness Medium: "<</cupsCompression 1>>setpagedevice"
+*Darkness Normal: "<</cupsCompression 2>>setpagedevice"
+*Darkness Dark: "<</cupsCompression 3>>setpagedevice"
+*CloseUI: *Darkness
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/epson24.ppd b/ppd/epson24.ppd
new file mode 100644
index 000000000..311c31a01
--- /dev/null
+++ b/ppd/epson24.ppd
@@ -0,0 +1,138 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON 24-Pin driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "EPSON24.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 1
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*ModelName: "EPSON 24-Pin Series"
+*ShortNickName: "EPSON 24-Pin Series"
+*NickName: "EPSON 24-Pin Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: True
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "18.0 18.0 594.0 774.0"
+*ImageableArea Legal: "18.0 18.0 594.0 990.0"
+*ImageableArea A4: "18.0 18.0 577.0 824.0"
+*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+*PaperDimension FanFoldUS: "1071 792"
+
+*MaxMediaWidth: "1080"
+*MaxMediaHeight: "86400"
+*HWMargins: 0 0 0 0
+*CustomPageSize True: "pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice"
+*ParamCustomPageSize Width: 1 points 36 1080
+*ParamCustomPageSize Height: 2 points 36 86400
+*ParamCustomPageSize WidthOffset: 3 points 0 0
+*ParamCustomPageSize HeightOffset: 4 points 0 0
+*ParamCustomPageSize Orientation: 5 int 0 0
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 120dpi
+*Resolution 60dpi/60 DPI: "<</HWResolution[60 60]/cupsRowCount 8>>setpagedevice"
+*Resolution 120dpi/120x60 DPI: "<</HWResolution[120 60]/cupsRowCount 8>>setpagedevice"
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]/cupsRowCount 24>>setpagedevice"
+*Resolution 360x180dpi/360x180 DPI: "<</HWResolution[360 180]/cupsRowCount 24>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]/cupsRowCount 48>>setpagedevice"
+*CloseUI: *Resolution
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/epson9.ppd b/ppd/epson9.ppd
new file mode 100644
index 000000000..0298a2db3
--- /dev/null
+++ b/ppd/epson9.ppd
@@ -0,0 +1,136 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON 9-Pin driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "EPSON9.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 0
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*ModelName: "EPSON 9-Pin Series"
+*ShortNickName: "EPSON 9-Pin Series"
+*NickName: "EPSON 9-Pin Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: True
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "18.0 18.0 594.0 774.0"
+*ImageableArea Legal: "18.0 18.0 594.0 990.0"
+*ImageableArea A4: "18.0 18.0 577.0 824.0"
+*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+*PaperDimension FanFoldUS: "1071 792"
+
+*MaxMediaWidth: "1080"
+*MaxMediaHeight: "86400"
+*HWMargins: 0 0 0 0
+*CustomPageSize True: "pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice"
+*ParamCustomPageSize Width: 1 points 36 1080
+*ParamCustomPageSize Height: 2 points 36 86400
+*ParamCustomPageSize WidthOffset: 3 points 0 0
+*ParamCustomPageSize HeightOffset: 4 points 0 0
+*ParamCustomPageSize Orientation: 5 int 0 0
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 120dpi
+*Resolution 60dpi/60x72 DPI: "<</HWResolution[60 72]/cupsRowCount 8>>setpagedevice"
+*Resolution 120dpi/120x72 DPI: "<</HWResolution[120 72]/cupsRowCount 8>>setpagedevice"
+*Resolution 240dpi/240x72 DPI: "<</HWResolution[240 72]/cupsRowCount 8>>setpagedevice"
+*CloseUI: *Resolution
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/laserjet.ppd b/ppd/laserjet.ppd
new file mode 100644
index 000000000..0ce7f12fd
--- /dev/null
+++ b/ppd/laserjet.ppd
@@ -0,0 +1,200 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample HP LaserJet driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "LASERJET.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: False
+*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 0
+*ModelName: "HP LaserJet Series"
+*ShortNickName: "HP LaserJet Series"
+*NickName: "HP LaserJet Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "8"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Duplex *Option1 False
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "18 36 594 756"
+*ImageableArea Legal/US Legal: "18 36 594 972"
+*ImageableArea Executive/US Executive: "18 36 504 684"
+*ImageableArea Tabloid/US Tabloid: "18 36 774 1188"
+*ImageableArea A3/A3: "18 36 824 1155"
+*ImageableArea A4/A4: "18 36 577 806"
+*ImageableArea A5/A5: "18 36 403 559"
+*ImageableArea B5/JIS B5: "18 36 498 693"
+*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673"
+*ImageableArea Env10/Com-10: "18 36 279 648"
+*ImageableArea EnvC5/EnvC5: "18 36 441 613"
+*ImageableArea EnvDL/EnvDL: "18 36 294 588"
+*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Default
+*InputSlot Default/Default: "<</cupsMediaPosition 0>>setpagedevice"
+*InputSlot Tray1/Tray 1: "<</cupsMediaPosition 8>>setpagedevice"
+*InputSlot Tray2/Tray 2: "<</cupsMediaPosition 1>>setpagedevice"
+*InputSlot Tray3/Tray 3: "<</cupsMediaPosition 4>>setpagedevice"
+*InputSlot Tray4/Tray 4: "<</cupsMediaPosition 5>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</cupsMediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</cupsMediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 300dpi
+*Resolution 150dpi/150 DPI: "<</HWResolution[150 150]/cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]/cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]/cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *Duplex/Double-Sided Printing: PickOne
+*OrderDependency: 20 AnySetup *Duplex
+*DefaultDuplex: None
+*Duplex None/Off: "<</Duplex false>>setpagedevice"
+*Duplex DuplexNoTumble/Long Edge (Standard): "<</Duplex true/Tumble false>>setpagedevice"
+*Duplex DuplexTumble/Short Edge (Flip): "<</Duplex true/Tumble true>>setpagedevice"
+*CloseUI: *Duplex
+
+*OpenGroup: InstallableOptions
+*OpenUI *Option1/Duplexer: Boolean
+*DefaultOption1: False
+*Option1 True/Installed: ""
+*Option1 False/Not Installed: ""
+*CloseUI: *Option1
+*CloseGroup: InstallableOptions
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/okidat24.ppd b/ppd/okidat24.ppd
new file mode 100644
index 000000000..03bd8033b
--- /dev/null
+++ b/ppd/okidat24.ppd
@@ -0,0 +1,128 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample OKIDATA 24-Pin driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "OKIDAT24.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 1
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*ModelName: "OKIDATA 24-Pin Series"
+*ShortNickName: "OKIDATA 24-Pin Series"
+*NickName: "OKIDATA 24-Pin Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "18.0 18.0 594.0 774.0"
+*ImageableArea Legal: "18.0 18.0 594.0 990.0"
+*ImageableArea A4: "18.0 18.0 577.0 824.0"
+*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+*PaperDimension FanFoldUS: "1071 792"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 120dpi
+*Resolution 60dpi/60 DPI: "<</HWResolution[60 60]/cupsRowCount 8>>setpagedevice"
+*Resolution 120dpi/120x60 DPI: "<</HWResolution[120 60]/cupsRowCount 8>>setpagedevice"
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]/cupsRowCount 24>>setpagedevice"
+*Resolution 360x180dpi/360x180 DPI: "<</HWResolution[360 180]/cupsRowCount 24>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]/cupsRowCount 48>>setpagedevice"
+*CloseUI: *Resolution
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/okidata9.ppd b/ppd/okidata9.ppd
new file mode 100644
index 000000000..ef5394af6
--- /dev/null
+++ b/ppd/okidata9.ppd
@@ -0,0 +1,126 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample OKIDATA 9-Pin driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "OKIDATA9.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 0
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*ModelName: "OKIDATA 9-Pin Series"
+*ShortNickName: "OKIDATA 9-Pin Series"
+*NickName: "OKIDATA 9-Pin Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion FanFoldUS: "<</PageSize[1071 792]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "18.0 18.0 594.0 774.0"
+*ImageableArea Legal: "18.0 18.0 594.0 990.0"
+*ImageableArea A4: "18.0 18.0 577.0 824.0"
+*ImageableArea FanFoldUS: "18.0 18.0 1053.0 774.0"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+*PaperDimension FanFoldUS: "1071 792"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 120dpi
+*Resolution 60dpi/60x72 DPI: "<</HWResolution[60 72]/cupsRowCount 8>>setpagedevice"
+*Resolution 120dpi/120x72 DPI: "<</HWResolution[120 72]/cupsRowCount 8>>setpagedevice"
+*Resolution 240dpi/240x72 DPI: "<</HWResolution[240 72]/cupsRowCount 8>>setpagedevice"
+*CloseUI: *Resolution
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/stcolor.ppd b/ppd/stcolor.ppd
new file mode 100644
index 000000000..1e6211921
--- /dev/null
+++ b/ppd/stcolor.ppd
@@ -0,0 +1,132 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON Stylus Color driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "STCOLOR.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 2
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*ModelName: "EPSON Stylus Color Series"
+*ShortNickName: "EPSON Stylus Color Series"
+*NickName: "EPSON Stylus Color Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "8.60 39.60 603.40 766.49"
+*ImageableArea Legal: "8.60 39.60 603.40 982.49"
+*ImageableArea A4: "8.60 39.60 586.40 816.49"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 360dpi
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]>>setpagedevice{0.6666 exp}bind settransfer"
+*Resolution 720dpi/720 DPI: "<</HWResolution[720 720]>>setpagedevice{0.4 exp}bind settransfer"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 1>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 1>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/stcolor2.ppd b/ppd/stcolor2.ppd
new file mode 100644
index 000000000..b33fe48d0
--- /dev/null
+++ b/ppd/stcolor2.ppd
@@ -0,0 +1,132 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON Stylus Color driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "STCOLOR2.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 4
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+*ModelName: "EPSON New Stylus Color Series"
+*ShortNickName: "EPSON New Stylus Color Series"
+*NickName: "EPSON New Stylus Color Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "8.60 39.60 603.40 766.49"
+*ImageableArea Legal: "8.60 39.60 603.40 982.49"
+*ImageableArea A4: "8.60 39.60 586.40 816.49"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 360dpi
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]>>setpagedevice{0.6666 exp}bind settransfer"
+*Resolution 720dpi/720 DPI: "<</HWResolution[720 720]>>setpagedevice{0.4 exp}bind settransfer"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 1>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 1>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/stphoto.ppd b/ppd/stphoto.ppd
new file mode 100644
index 000000000..ca0dd5f53
--- /dev/null
+++ b/ppd/stphoto.ppd
@@ -0,0 +1,132 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON Stylus Photo driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "STPHOTO.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 3
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*ModelName: "EPSON Stylus Photo Series"
+*ShortNickName: "EPSON Stylus Photo Series"
+*NickName: "EPSON Stylus Photo Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "8.60 39.60 603.40 766.49"
+*ImageableArea Legal: "8.60 39.60 603.40 982.49"
+*ImageableArea A4: "8.60 39.60 586.40 816.49"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 360dpi
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]>>setpagedevice{0.6666 exp}bind settransfer"
+*Resolution 720dpi/720 DPI: "<</HWResolution[720 720]>>setpagedevice{0.4 exp}bind settransfer"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/Color: "<</cupsColorOrder 1/cupsColorSpace 9/cupsCompression 1>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 1>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/stphoto2.ppd b/ppd/stphoto2.ppd
new file mode 100644
index 000000000..0f70b4f00
--- /dev/null
+++ b/ppd/stphoto2.ppd
@@ -0,0 +1,132 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample EPSON Stylus Photo driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "STPHOTO2.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsModelNumber: 5
+*cupsFilter: "application/vnd.cups-raster 0 rastertoepson"
+*cupsColorProfile 180dpi/-: "1.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*cupsColorProfile 720dpi/-: "1.0 2.5 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0"
+*ModelName: "EPSON New Stylus Photo Series"
+*ShortNickName: "EPSON New Stylus Photo Series"
+*NickName: "EPSON New Stylus Photo Series CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter: "8.60 39.60 603.40 766.49"
+*ImageableArea Legal: "8.60 39.60 603.40 982.49"
+*ImageableArea A4: "8.60 39.60 586.40 816.49"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+*PaperDimension A4: "595 842"
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 360dpi
+*Resolution 180dpi/180 DPI: "<</HWResolution[180 180]>>setpagedevice"
+*Resolution 360dpi/360 DPI: "<</HWResolution[360 360]>>setpagedevice{0.6666 exp}bind settransfer"
+*Resolution 720dpi/720 DPI: "<</HWResolution[720 720]>>setpagedevice{0.4 exp}bind settransfer"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/Color: "<</cupsColorOrder 1/cupsColorSpace 9/cupsCompression 1>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 1>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/ppd/zebra.ppd b/ppd/zebra.ppd
new file mode 100644
index 000000000..0a9419156
--- /dev/null
+++ b/ppd/zebra.ppd
@@ -0,0 +1,147 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample Zebra label printer driver PPD file for the Common UNIX Printing
+*% System (CUPS).
+*%
+*% Copyright 2001-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "ZEBRA.PPD"
+*Manufacturer: "ESP"
+*Product: "(GNU Ghostscript)"
+*Product: "(ESP Ghostscript)"
+*cupsVersion: 1.1
+*cupsManualCopies: False
+*cupsFilter: "application/vnd.cups-raster 0 rastertodymo"
+*% cupsModelNumber is 16 for EPL line mode, 17 for EPL page mode,
+*% and 18 for ZPL mode.
+*cupsModelNumber: 18
+*ModelName: "Zebra ZPL Label Printer"
+*ShortNickName: "Zebra ZPL Label Printer"
+*NickName: "Zebra ZPL Label Printer CUPS v1.1"
+*PSVersion: "(3010.000) 707"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "8"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: w288h360
+*PageSize w288h360/Label - 4 x 5": "<</PageSize[288 360]/ImagingBBox null>>setpagedevice"
+*PageSize w288h432/Label - 4 x 6": "<</PageSize[288 432]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: w288h360
+*PageRegion w288h360/Label - 4 x 5": "<</PageSize[288 360]/ImagingBBox null>>setpagedevice"
+*PageRegion w288h432/Label - 4 x 6": "<</PageSize[288 432]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: w288h360
+*ImageableArea w288h360/Label - 4 x 5": "0 0 288 360"
+*ImageableArea w288h432/Label - 4 x 5": "0 0 288 432"
+
+*DefaultPaperDimension: w288h360
+*PaperDimension w288h360/Label - 4 x 5": "288 360"
+*PaperDimension w288h432/Label - 4 x 5": "288 432"
+
+*MaxMediaWidth: "288"
+*MaxMediaHeight: "3600"
+*HWMargins: 0 0 0 0
+*CustomPageSize True: "pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice"
+*ParamCustomPageSize Width: 1 points 36 288
+*ParamCustomPageSize Height: 2 points 36 3600
+*ParamCustomPageSize WidthOffset: 3 points 0 0
+*ParamCustomPageSize HeightOffset: 4 points 0 0
+*ParamCustomPageSize Orientation: 5 int 0 0
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 203dpi
+*Resolution 203dpi/203 DPI: "<</HWResolution[203 203]>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *Darkness/Output Darkness: PickOne
+*OrderDependency: 20 AnySetup *Darkness
+*DefaultDarkness: Normal
+*Darkness Light: "<</cupsCompression 0>>setpagedevice"
+*Darkness Medium: "<</cupsCompression 33>>setpagedevice"
+*Darkness Normal: "<</cupsCompression 67>>setpagedevice"
+*Darkness Dark: "<</cupsCompression 100>>setpagedevice"
+*CloseUI: *Darkness
+
+*OpenUI *CutMedia/Cut Labels: Boolean
+*OrderDependency: 10 AnySetup *Cut
+*DefaultCutMedia: True
+*CutMedia False: "<</CutMedia 0>>setpagedevice"
+*CutMedia True: "<</CutMedia 4>>setpagedevice"
+*CloseUI: *CutMedia
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/pstoraster/.cvsignore b/pstoraster/.cvsignore
new file mode 100644
index 000000000..cf5b1a290
--- /dev/null
+++ b/pstoraster/.cvsignore
@@ -0,0 +1,3 @@
+pstoraster
+genarch
+arch.h
diff --git a/pstoraster/README.pstoraster b/pstoraster/README.pstoraster
new file mode 100644
index 000000000..980def219
--- /dev/null
+++ b/pstoraster/README.pstoraster
@@ -0,0 +1,73 @@
+README.pstoraster - 11/14/2003
+------------------------------
+
+INTRODUCTION
+
+ This directory contains the CUPS "driver" for Ghostscript
+ 7.x and 8.x, the pstoraster script that is used to run
+ Ghostscript as a CUPS filter, the pstoraster.convs file that
+ defines the PostScript to raster filter for CUPS drivers, a
+ makefile fragment that adds the CUPS driver, and the wrapper
+ script (pstopxl) and PPD files (pxl*.ppd) to support PCL
+ XL/PCL 6 printers.
+
+ This software is included with both the CUPS and ESP
+ Ghostscript 7.07.1 distributions. While the files will also
+ compile with earlier versions of Ghostscript, there are bugs
+ in older versions of Ghostscript which may cause problems.
+
+ Also, this driver may not be used in any commercial
+ Ghostscript distributions without prior written
+ permission/licensing from Easy Software Products. See the
+ contact information in the file "gdevcups.c" for more
+ information.
+
+
+COMPILING ESP GHOSTSCRIPT WITH THE CUPS DRIVER
+
+ Normally the CUPS driver will be automatically included when
+ you use the configure script supplied with ESP Ghostscript.
+
+ Once you have compiled and installed Ghostscript, restart
+ the cupsd process, either by sending the HUP signal to the
+ process or using the init script supplied with CUPS.
+
+ To use the PCL XL/PCL 6 drivers, make sure that you also
+ configure Ghostscript with the pxlmono and pxlcolor drivers.
+
+
+COMPILING AFPL/GNU GHOSTSCRIPT WITH THE CUPS DRIVER
+
+ Before configuring AFPL or GNU Ghostscript, first copy this
+ directory to the Ghostscript source directory, e.g.:
+
+ cp -r pstoraster /some/path/to/ghostscript-7.07
+
+ Then apply the appropriate patch:
+
+ cd /some/path/to/ghostscript-7.07
+ patch -p1 pstoraster/gs707-lib.patch
+
+ or:
+
+ cd /some/path/to/ghostscript-8.11
+ patch -p1 pstoraster/gs811-lib.patch
+
+ Next, run the configure script to configure the Ghostscript
+ software:
+
+ ./configure [any configure options you want]
+
+ Finally, add the following include line to the end of the
+ makefile:
+
+ include pstoraster/cups.mak
+
+ and add "$(DD)cups.dev" to any of the DEVICE_DEVS lines.
+
+ Once you have compiled and installed Ghostscript, restart
+ the cupsd process, either by sending the HUP signal to the
+ process or using the init script supplied with CUPS.
+
+ To use the PCL XL/PCL 6 drivers, make sure that you also
+ configure Ghostscript with the pxlmono and pxlcolor drivers.
diff --git a/pstoraster/cups.mak b/pstoraster/cups.mak
new file mode 100644
index 000000000..c6113f473
--- /dev/null
+++ b/pstoraster/cups.mak
@@ -0,0 +1,53 @@
+#
+# "$Id: cups.mak 4087 2004-02-25 20:14:54Z mike $"
+#
+# CUPS driver makefile for Ghostscript.
+#
+# Copyright 2001-2004 by Easy Software Products.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+### ----------------- CUPS Ghostscript Driver ---------------------- ###
+
+cups_= $(GLOBJ)gdevcups.$(OBJ)
+
+CUPSSERVER= $(install_prefix)`cups-config --serverbin`
+CUPSCONFIG= $(install_prefix)`cups-config --serverroot`
+CUPSDATA= $(install_prefix)`cups-config --datadir`
+
+$(DD)cups.dev: $(cups_) $(GLD)page.dev
+ $(ADDMOD) $(DD)cups -lib cupsimage -lib cups
+ $(SETPDEV2) $(DD)cups $(cups_)
+
+$(GLOBJ)gdevcups.$(OBJ): pstoraster/gdevcups.c $(PDEVH)
+ $(GLCC) $(GLO_)gdevcups.$(OBJ) $(C_) pstoraster/gdevcups.c
+
+install: install-cups
+
+install-cups:
+ -mkdir -p $(CUPSSERVER)/filter
+ $(INSTALL_PROGRAM) pstoraster/pstoraster $(CUPSSERVER)/filter
+ $(INSTALL_PROGRAM) pstoraster/pstopxl $(CUPSSERVER)/filter
+ -mkdir -p $(CUPSCONFIG)
+ $(INSTALL_DATA) pstoraster/pstoraster.convs $(CUPSCONFIG)
+ -mkdir -p $(CUPSDATA)/model
+ $(INSTALL_DATA) pstoraster/pxlcolor.ppd $(CUPSDATA)/model
+ $(INSTALL_DATA) pstoraster/pxlmono.ppd $(CUPSDATA)/model
+
+
+#
+# End of "$Id: cups.mak 4087 2004-02-25 20:14:54Z mike $".
+#
diff --git a/pstoraster/gdevcups.c b/pstoraster/gdevcups.c
new file mode 100644
index 000000000..8262bd2e0
--- /dev/null
+++ b/pstoraster/gdevcups.c
@@ -0,0 +1,4464 @@
+/*
+ * "$Id$"
+ *
+ * GNU Ghostscript raster output driver for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1993-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3142 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org/
+ *
+ * This code and any derivative of it may be used and distributed
+ * freely under the terms of the GNU General Public License when
+ * used with GNU Ghostscript or its derivatives. Use of the code
+ * (or any derivative of it) with software other than GNU
+ * GhostScript (or its derivatives) is governed by the CUPS license
+ * agreement.
+ *
+ * Contents:
+ *
+ * cups_close() - Close the output file.
+ * cups_get_matrix() - Generate the default page matrix.
+ * cups_get_params() - Get pagedevice parameters.
+ * cups_get_space_params() - Get space parameters from the RIP_CACHE env var.
+ * cups_map_color_rgb() - Map a color index to an RGB color.
+ * cups_map_cielab() - Map CIE Lab transformation...
+ * cups_map_rgb_color() - Map an RGB color to a color index. We map the
+ * RGB color to the output colorspace & bits (we
+ * figure out the format when we output a page).
+ * cups_open() - Open the output file and initialize things.
+ * cups_print_pages() - Send one or more pages to the output file.
+ * cups_put_params() - Set pagedevice parameters.
+ * cups_set_color_info() - Set the color information structure based on
+ * the required output.
+ * cups_print_chunked() - Print a page of chunked pixels.
+ * cups_print_banded() - Print a page of banded pixels.
+ * cups_print_planar() - Print a page of planar pixels.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "std.h" /* to stop stdlib.h redefining types */
+#include "gdevprn.h"
+#include "gsparam.h"
+#include "gsexit.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <cups/raster.h>
+#include <cups/ppd.h>
+#include <math.h>
+
+#undef private
+#define private
+
+
+/*
+ * Check if we are compiling against CUPS 1.2. If so, enable
+ * certain extended attributes and use a different page header
+ * structure and write function...
+ */
+
+#ifdef CUPS_RASTER_SYNCv1
+# define cups_page_header_t cups_page_header2_t
+# define cupsRasterWriteHeader cupsRasterWriteHeader2
+#endif /* CUPS_RASTER_SYNCv1 */
+
+
+/*
+ * Newer versions of Ghostscript don't provide gs_exit() function anymore.
+ * It has been renamed to gs_to_exit()...
+ */
+
+#ifdef dev_t_proc_encode_color
+# define gs_exit gs_to_exit
+#endif /* dev_t_proc_encode_color */
+
+
+/*
+ * CIE XYZ color constants...
+ */
+
+#define D65_X (0.412453 + 0.357580 + 0.180423)
+#define D65_Y (0.212671 + 0.715160 + 0.072169)
+#define D65_Z (0.019334 + 0.119193 + 0.950227)
+
+
+/*
+ * Size of a tile in pixels...
+ */
+
+#define CUPS_TILE_SIZE 256
+
+
+/*
+ * Size of profile LUTs...
+ */
+
+#ifdef dev_t_proc_encode_color
+# define CUPS_MAX_VALUE frac_1
+#else
+# define CUPS_MAX_VALUE gx_max_color_value
+#endif /* dev_t_proc_encode_color */
+
+
+/*
+ * Macros...
+ */
+
+#define x_dpi (pdev->HWResolution[0])
+#define y_dpi (pdev->HWResolution[1])
+#define cups ((gx_device_cups *)pdev)
+
+/*
+ * Macros from <macros.h>; we can't include <macros.h> because it also
+ * defines DEBUG, one of our flags to insert various debugging code.
+ */
+
+#ifndef max
+# define max(a,b) ((a)<(b) ? (b) : (a))
+#endif /* !max */
+
+#ifndef min
+# define min(a,b) ((a)>(b) ? (b) : (a))
+#endif /* !min */
+
+#ifndef abs
+# define abs(x) ((x)>=0 ? (x) : -(x))
+#endif /* !abs */
+
+
+/*
+ * Procedures
+ */
+
+private dev_proc_close_device(cups_close);
+private dev_proc_get_initial_matrix(cups_get_matrix);
+private int cups_get_params(gx_device *, gs_param_list *);
+private dev_proc_open_device(cups_open);
+private int cups_print_pages(gx_device_printer *, FILE *, int);
+private int cups_put_params(gx_device *, gs_param_list *);
+private void cups_set_color_info(gx_device *);
+private dev_proc_sync_output(cups_sync_output);
+private prn_dev_proc_get_space_params(cups_get_space_params);
+
+#ifdef dev_t_proc_encode_color
+private cm_map_proc_gray(cups_map_gray);
+private cm_map_proc_rgb(cups_map_rgb);
+private cm_map_proc_cmyk(cups_map_cmyk);
+private dev_proc_decode_color(cups_decode_color);
+private dev_proc_encode_color(cups_encode_color);
+private dev_proc_get_color_mapping_procs(cups_get_color_mapping_procs);
+
+static const gx_cm_color_map_procs cups_color_mapping_procs =
+{
+ cups_map_gray,
+ cups_map_rgb,
+ cups_map_cmyk
+};
+#else
+private dev_proc_map_cmyk_color(cups_map_cmyk_color);
+private dev_proc_map_color_rgb(cups_map_color_rgb);
+private dev_proc_map_rgb_color(cups_map_rgb_color);
+#endif /* dev_t_proc_encode_color */
+
+
+/*
+ * The device descriptors...
+ */
+
+typedef struct gx_device_cups_s
+{
+ gx_device_common; /* Standard GhostScript device stuff */
+ gx_prn_device_common; /* Standard printer device stuff */
+ int page; /* Page number */
+ cups_raster_t *stream; /* Raster stream */
+ cups_page_header_t header; /* PostScript page device info */
+ int landscape; /* Non-zero if this is landscape */
+} gx_device_cups;
+
+private gx_device_procs cups_procs =
+{
+ cups_open,
+ cups_get_matrix,
+ cups_sync_output,
+ gdev_prn_output_page,
+ cups_close,
+#ifdef dev_t_proc_encode_color
+ NULL, /* map_rgb_color */
+ NULL, /* map_color_rgb */
+#else
+ cups_map_rgb_color,
+ cups_map_color_rgb,
+#endif /* dev_t_proc_encode_color */
+ NULL, /* fill_rectangle */
+ NULL, /* tile_rectangle */
+ NULL, /* copy_mono */
+ NULL, /* copy_color */
+ NULL, /* draw_line */
+ gx_default_get_bits,
+ cups_get_params,
+ cups_put_params,
+#ifdef dev_t_proc_encode_color
+ NULL, /* map_cmyk_color */
+#else
+ cups_map_cmyk_color,
+#endif /* dev_t_proc_encode_color */
+ NULL, /* get_xfont_procs */
+ NULL, /* get_xfont_device */
+ NULL, /* map_rgb_alpha_color */
+ gx_page_device_get_page_device,
+ NULL, /* get_alpha_bits */
+ NULL, /* copy_alpha */
+ NULL, /* get_band */
+ NULL, /* copy_rop */
+ NULL, /* fill_path */
+ NULL, /* stroke_path */
+ NULL, /* fill_mask */
+ NULL, /* fill_trapezoid */
+ NULL, /* fill_parallelogram */
+ NULL, /* fill_triangle */
+ NULL, /* draw_thin_line */
+ NULL, /* begin_image */
+ NULL, /* image_data */
+ NULL, /* end_image */
+ NULL, /* strip_tile_rectangle */
+ NULL /* strip_copy_rop */
+#ifdef dev_t_proc_encode_color
+ ,
+ NULL, /* get_clipping_box */
+ NULL, /* begin_typed_image */
+ NULL, /* get_bits_rectangle */
+ NULL, /* map_color_rgb_alpha */
+ NULL, /* create_compositor */
+ NULL, /* get_hardware_params */
+ NULL, /* text_begin */
+ NULL, /* finish_copydevice */
+ NULL, /* begin_transparency_group */
+ NULL, /* end_transparency_group */
+ NULL, /* begin_transparency_mask */
+ NULL, /* end_transparency_mask */
+ NULL, /* discard_transparency_layer */
+ cups_get_color_mapping_procs,
+ NULL, /* get_color_comp_index */
+ cups_encode_color,
+ cups_decode_color
+#endif /* dev_t_proc_encode_color */
+};
+
+#define prn_device_body_copies(dtype, procs, dname, w10, h10, xdpi, ydpi, lo, to, lm, bm, rm, tm, ncomp, depth, mg, mc, dg, dc, print_pages)\
+ std_device_full_body_type(dtype, &procs, dname, &st_device_printer,\
+ (int)((long)(w10) * (xdpi) / 10),\
+ (int)((long)(h10) * (ydpi) / 10),\
+ xdpi, ydpi,\
+ ncomp, depth, mg, mc, dg, dc,\
+ -(lo) * (xdpi), -(to) * (ydpi),\
+ (lm) * 72.0, (bm) * 72.0,\
+ (rm) * 72.0, (tm) * 72.0\
+ ),\
+ prn_device_body_copies_rest_(print_pages)
+
+gx_device_cups gs_cups_device =
+{
+ prn_device_body_copies(gx_device_cups,/* type */
+ cups_procs, /* procedures */
+ "cups", /* device name */
+ 85, /* initial width */
+ 110, /* initial height */
+ 100, /* initial x resolution */
+ 100, /* initial y resolution */
+ 0, /* initial left offset */
+ 0, /* initial top offset */
+ 0, /* initial left margin */
+ 0, /* initial bottom margin */
+ 0, /* initial right margin */
+ 0, /* initial top margin */
+ 1, /* number of color components */
+ 1, /* number of color bits */
+ 1, /* maximum gray value */
+ 0, /* maximum color value */
+ 2, /* number of gray values */
+ 0, /* number of color values */
+ cups_print_pages),
+ /* print procedure */
+ 0, /* page */
+ NULL, /* stream */
+ { /* header */
+ "", /* MediaClass */
+ "", /* MediaColor */
+ "", /* MediaType */
+ "", /* OutputType */
+ 0, /* AdvanceDistance */
+ CUPS_ADVANCE_NONE, /* AdvanceMedia */
+ CUPS_FALSE, /* Collate */
+ CUPS_CUT_NONE, /* CutMedia */
+ CUPS_FALSE, /* Duplex */
+ { 100, 100 }, /* HWResolution */
+ { 0, 0, 612, 792 }, /* ImagingBoundingBox */
+ CUPS_FALSE, /* InsertSheet */
+ CUPS_JOG_NONE, /* Jog */
+ CUPS_EDGE_TOP, /* LeadingEdge */
+ { 0, 0 }, /* Margins */
+ CUPS_FALSE, /* ManualFeed */
+ 0, /* MediaPosition */
+ 0, /* MediaWeight */
+ CUPS_FALSE, /* MirrorPrint */
+ CUPS_FALSE, /* NegativePrint */
+ 1, /* NumCopies */
+ CUPS_ORIENT_0, /* Orientation */
+ CUPS_FALSE, /* OutputFaceUp */
+ { 612, 792 }, /* PageSize */
+ CUPS_FALSE, /* Separations */
+ CUPS_FALSE, /* TraySwitch */
+ CUPS_FALSE, /* Tumble */
+ 850, /* cupsWidth */
+ 1100, /* cupsHeight */
+ 0, /* cupsMediaType */
+ 1, /* cupsBitsPerColor */
+ 1, /* cupsBitsPerPixel */
+ 107, /* cupsBytesPerLine */
+ CUPS_ORDER_CHUNKED, /* cupsColorOrder */
+ CUPS_CSPACE_K, /* cupsColorSpace */
+ 0, /* cupsCompression */
+ 0, /* cupsRowCount */
+ 0, /* cupsRowFeed */
+ 0 /* cupsRowStep */
+ }
+};
+
+/*
+ * Globals...
+ */
+
+static gx_color_value cupsDecodeLUT[256];
+ /* Output color to RGB value LUT */
+static unsigned char cupsEncodeLUT[gx_max_color_value + 1];
+ /* RGB value to output color LUT */
+
+static ppd_file_t *cupsPPD = 0; /* PPD file for this device */
+static char *cupsProfile = NULL;
+ /* Current simple color profile string */
+static int cupsHaveProfile = 0;
+ /* Has a color profile been defined? */
+static int cupsMatrix[3][3][CUPS_MAX_VALUE + 1];
+ /* Color transform matrix LUT */
+static int cupsDensity[CUPS_MAX_VALUE + 1];
+ /* Density LUT */
+static unsigned char cupsRevLower1[16] =
+ { /* Lower 1-bit reversal table */
+ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+ },
+ cupsRevUpper1[16] =
+ { /* Upper 1-bit reversal table */
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0
+ },
+ cupsRevLower2[16] =
+ { /* Lower 2-bit reversal table */
+ 0x00, 0x04, 0x08, 0x0c, 0x01, 0x05, 0x09, 0x0d,
+ 0x02, 0x06, 0x0a, 0x0e, 0x03, 0x07, 0x0b, 0x0f
+ },
+ cupsRevUpper2[16] =
+ { /* Upper 2-bit reversal table */
+ 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
+ 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0
+ };
+
+
+/*
+ * Local functions...
+ */
+
+static double cups_map_cielab(double, double);
+static void cups_print_chunked(gx_device_printer *, unsigned char *,
+ unsigned char *, int);
+static void cups_print_banded(gx_device_printer *, unsigned char *,
+ unsigned char *, int);
+static void cups_print_planar(gx_device_printer *, unsigned char *,
+ unsigned char *, int);
+
+/*static void cups_set_margins(gx_device *);*/
+
+
+/*
+ * 'cups_close()' - Close the output file.
+ */
+
+private int
+cups_close(gx_device *pdev) /* I - Device info */
+{
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_close(%p)\n", pdev);
+#endif /* DEBUG */
+
+ if (cups->stream != NULL)
+ {
+ cupsRasterClose(cups->stream);
+ cups->stream = NULL;
+ }
+
+#if 0 /* Can't do this here because put_params() might close the device */
+ if (cupsPPD != NULL)
+ {
+ ppdClose(cupsPPD);
+ cupsPPD = NULL;
+ }
+
+ if (cupsProfile != NULL)
+ {
+ free(cupsProfile);
+ cupsProfile = NULL;
+ }
+#endif /* 0 */
+
+ return (gdev_prn_close(pdev));
+}
+
+
+#ifdef dev_t_proc_encode_color
+/*
+ * 'cups_decode_color()' - Decode a color value.
+ */
+
+private int /* O - Status (0 = OK) */
+cups_decode_color(gx_device *pdev, /* I - Device info */
+ gx_color_index ci, /* I - Color index */
+ gx_color_value *cv) /* O - Colors */
+{
+ int i; /* Looping var */
+ int shift; /* Bits to shift */
+ int mask; /* Bits to mask */
+
+
+ if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
+ cups->header.cupsBitsPerColor == 1)
+ {
+ /*
+ * KCMYcm data is represented internally by Ghostscript as CMYK...
+ */
+
+ cv[0] = (ci & 0x20) ? frac_1 : frac_0;
+ cv[1] = (ci & 0x12) ? frac_1 : frac_0;
+ cv[2] = (ci & 0x09) ? frac_1 : frac_0;
+ cv[3] = (ci & 0x04) ? frac_1 : frac_0;
+ }
+ else
+ {
+ shift = cups->header.cupsBitsPerColor;
+ mask = (1 << shift) - 1;
+
+ for (i = cups->color_info.num_components - 1; i > 0; i --, ci >>= shift)
+ cv[i] = cupsDecodeLUT[ci & mask];
+
+ cv[0] = cupsDecodeLUT[ci & mask];
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'cups_encode_color()' - Encode a color value.
+ */
+
+private gx_color_index /* O - Color index */
+cups_encode_color(gx_device *pdev,
+ /* I - Device info */
+ const gx_color_value *cv)
+ /* I - Colors */
+{
+ int i; /* Looping var */
+ gx_color_index ci; /* Color index */
+ int shift; /* Bits to shift */
+
+
+ /*
+ * Encode the color index...
+ */
+
+ shift = cups->header.cupsBitsPerColor;
+
+ for (ci = cupsEncodeLUT[cv[0]], i = 1;
+ i < cups->color_info.num_components;
+ i ++)
+ ci = (ci << shift) | cupsEncodeLUT[cv[i]];
+
+ /*
+ * Handle 6-color output...
+ */
+
+ if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
+ cups->header.cupsBitsPerColor == 1)
+ {
+ /*
+ * Welcome to hackville, where we map CMYK data to the
+ * light inks in draft mode... Map blue to light magenta and
+ * cyan and green to light cyan and yellow...
+ */
+
+ ci <<= 2; /* Leave room for light inks */
+
+ if (ci == 0x18) /* Blue */
+ ci = 0x11; /* == cyan + light magenta */
+ else if (ci == 0x14) /* Green */
+ ci = 0x06; /* == light cyan + yellow */
+ }
+
+ /*
+ * Range check the return value...
+ */
+
+ if (ci == gx_no_color_index)
+ ci --;
+
+ /*
+ * Return the color index...
+ */
+
+ return (ci);
+}
+
+
+/*
+ * 'cups_get_color_mapping_procs()' - Get the list of color mapping procedures.
+ */
+
+private const gx_cm_color_map_procs * /* O - List of device procedures */
+cups_get_color_mapping_procs(const gx_device *pdev)
+ /* I - Device info */
+{
+ return (&cups_color_mapping_procs);
+}
+#endif /* dev_t_proc_encode_color */
+
+
+/*
+ * 'cups_get_matrix()' - Generate the default page matrix.
+ */
+
+private void
+cups_get_matrix(gx_device *pdev, /* I - Device info */
+ gs_matrix *pmat) /* O - Physical transform matrix */
+{
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_get_matrix(%p, %p)\n", pdev, pmat);
+#endif /* DEBUG */
+
+ /*
+ * Set the raster width and height...
+ */
+
+ cups->header.cupsWidth = cups->width;
+ cups->header.cupsHeight = cups->height;
+
+ /*
+ * Set the transform matrix...
+ */
+
+ fprintf(stderr, "DEBUG: cups->header.Duplex = %d\n", cups->header.Duplex);
+ fprintf(stderr, "DEBUG: cups->page = %d\n", cups->page);
+
+ if (cupsPPD)
+ {
+ fprintf(stderr, "DEBUG: cupsPPD = %p\n", cupsPPD);
+ fprintf(stderr, "DEBUG: cupsPPD->flip_duplex = %d\n", cupsPPD->flip_duplex);
+ }
+
+ if (cups->landscape)
+ {
+ /*
+ * Do landscape orientation...
+ */
+
+ if (cups->header.Duplex && !cups->header.Tumble &&
+ cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
+ {
+ pmat->xx = 0.0;
+ pmat->xy = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->yx = -(float)cups->header.HWResolution[1] / 72.0;
+ pmat->yy = 0.0;
+ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0;
+ pmat->ty = (float)cups->header.HWResolution[1] *
+ ((float)cups->header.PageSize[0] - pdev->HWMargins[3]) / 72.0;
+ }
+ else
+ {
+ pmat->xx = 0.0;
+ pmat->xy = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->yx = (float)cups->header.HWResolution[1] / 72.0;
+ pmat->yy = 0.0;
+ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
+ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[1] / 72.0;
+ }
+ }
+ else if (cups->header.Duplex && !cups->header.Tumble &&
+ cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
+ {
+ pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->xy = 0.0;
+ pmat->yx = 0.0;
+ pmat->yy = (float)cups->header.HWResolution[1] / 72.0;
+ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[2] / 72.0;
+ pmat->ty = -(float)cups->header.HWResolution[1] * pdev->HWMargins[3] / 72.0;
+ }
+ else
+ {
+ pmat->xx = (float)cups->header.HWResolution[0] / 72.0;
+ pmat->xy = 0.0;
+ pmat->yx = 0.0;
+ pmat->yy = -(float)cups->header.HWResolution[1] / 72.0;
+ pmat->tx = -(float)cups->header.HWResolution[0] * pdev->HWMargins[0] / 72.0;
+ pmat->ty = (float)cups->header.HWResolution[1] *
+ ((float)cups->header.PageSize[1] - pdev->HWMargins[3]) / 72.0;
+ }
+
+ fprintf(stderr, "DEBUG: width = %d, height = %d\n", cups->width,
+ cups->height);
+ fprintf(stderr, "DEBUG: PageSize = [ %d %d ], HWResolution = [ %d %d ]\n",
+ cups->header.PageSize[0], cups->header.PageSize[1],
+ cups->header.HWResolution[0], cups->header.HWResolution[1]);
+ fprintf(stderr, "DEBUG: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
+ pdev->HWMargins[0], pdev->HWMargins[1], pdev->HWMargins[2],
+ pdev->HWMargins[3]);
+ fprintf(stderr, "DEBUG: matrix = [ %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
+ pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty);
+}
+
+
+/*
+ * 'cups_get_params()' - Get pagedevice parameters.
+ */
+
+private int /* O - Error status */
+cups_get_params(gx_device *pdev, /* I - Device info */
+ gs_param_list *plist) /* I - Parameter list */
+{
+#ifdef CUPS_RASTER_SYNCv1
+ int i; /* Looping var */
+ char name[255]; /* Attribute name */
+#endif /* CUPS_RASTER_SYNCv1 */
+ int code; /* Return code */
+ gs_param_string s; /* Temporary string value */
+ bool b; /* Temporary boolean value */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_get_params(%p, %p)\n", pdev, plist);
+#endif /* DEBUG */
+
+ /*
+ * First process the "standard" page device parameters...
+ */
+
+#ifdef DEBUG
+ fputs("DEBUG2: before gdev_prn_get_params()\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = gdev_prn_get_params(pdev, plist)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: after gdev_prn_get_params()\n", stderr);
+#endif /* DEBUG */
+
+ /*
+ * Then write the CUPS parameters...
+ */
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding MediaClass\n", stderr);
+#endif /* DEBUG */
+
+ param_string_from_string(s, cups->header.MediaClass);
+ if ((code = param_write_string(plist, "MediaClass", &s)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding AdvanceDistance\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "AdvanceDistance",
+ (int *)&(cups->header.AdvanceDistance))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding AdvanceDistance\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "AdvanceMedia",
+ (int *)&(cups->header.AdvanceMedia))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding Collate\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.Collate;
+ if ((code = param_write_bool(plist, "Collate", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding CutMedia\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "CutMedia",
+ (int *)&(cups->header.CutMedia))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding InsertSheet\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.InsertSheet;
+ if ((code = param_write_bool(plist, "InsertSheet", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding Jog\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "Jog",
+ (int *)&(cups->header.Jog))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding LeadingEdge\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "LeadingEdge",
+ (int *)&(cups->header.LeadingEdge))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding ManualFeed\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.ManualFeed;
+ if ((code = param_write_bool(plist, "ManualFeed", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding MediaPosition\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "MediaPosition",
+ (int *)&(cups->header.MediaPosition))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding MirrorPrint\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.MirrorPrint;
+ if ((code = param_write_bool(plist, "MirrorPrint", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding NegativePrint\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.NegativePrint;
+ if ((code = param_write_bool(plist, "NegativePrint", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding OutputFaceUp\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.OutputFaceUp;
+ if ((code = param_write_bool(plist, "OutputFaceUp", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding Separations\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.Separations;
+ if ((code = param_write_bool(plist, "Separations", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding TraySwitch\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.TraySwitch;
+ if ((code = param_write_bool(plist, "TraySwitch", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding Tumble\n", stderr);
+#endif /* DEBUG */
+
+ b = cups->header.Tumble;
+ if ((code = param_write_bool(plist, "Tumble", &b)) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsWidth\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsWidth",
+ (int *)&(cups->header.cupsWidth))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsHeight\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsHeight",
+ (int *)&(cups->header.cupsHeight))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsMediaType\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsMediaType",
+ (int *)&(cups->header.cupsMediaType))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsBitsPerColor\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsBitsPerColor",
+ (int *)&(cups->header.cupsBitsPerColor))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsBitsPerPixel\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsBitsPerPixel",
+ (int *)&(cups->header.cupsBitsPerPixel))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsBytesPerLine\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsBytesPerLine",
+ (int *)&(cups->header.cupsBytesPerLine))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsColorOrder\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsColorOrder",
+ (int *)&(cups->header.cupsColorOrder))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsColorSpace\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsColorSpace",
+ (int *)&(cups->header.cupsColorSpace))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsCompression\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsCompression",
+ (int *)&(cups->header.cupsCompression))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsRowCount\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsRowCount",
+ (int *)&(cups->header.cupsRowCount))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsRowFeed\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsRowFeed",
+ (int *)&(cups->header.cupsRowFeed))) < 0)
+ return (code);
+
+#ifdef DEBUG
+ fputs("DEBUG2: Adding cupsRowStep\n", stderr);
+#endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsRowStep",
+ (int *)&(cups->header.cupsRowStep))) < 0)
+ return (code);
+
+#ifdef CUPS_RASTER_SYNCv1
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsNumColors\n", stderr);
+# endif /* DEBUG */
+
+ if ((code = param_write_int(plist, "cupsNumColors",
+ (int *)&(cups->header.cupsNumColors))) < 0)
+ return (code);
+
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsInteger\n", stderr);
+# endif /* DEBUG */
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsInteger%d", i);
+ if ((code = param_write_int(plist, name,
+ (int *)(cups->header.cupsInteger + i))) < 0)
+ return (code);
+ }
+
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsReal\n", stderr);
+# endif /* DEBUG */
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsReal%d", i);
+ if ((code = param_write_float(plist, name,
+ cups->header.cupsReal + i)) < 0)
+ return (code);
+ }
+
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsString\n", stderr);
+# endif /* DEBUG */
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsReal%d", i);
+ param_string_from_string(s, cups->header.cupsString[i]);
+ if ((code = param_write_string(plist, name, &s)) < 0)
+ return (code);
+ }
+
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsMarkerType\n", stderr);
+# endif /* DEBUG */
+
+ param_string_from_string(s, cups->header.cupsMarkerType);
+ if ((code = param_write_string(plist, "cupsMarkerType", &s)) < 0)
+ return (code);
+
+# ifdef DEBUG
+ fputs("DEBUG2: Adding cupsRenderingIntent\n", stderr);
+# endif /* DEBUG */
+
+ param_string_from_string(s, cups->header.cupsRenderingIntent);
+ if ((code = param_write_string(plist, "cupsRenderingIntent", &s)) < 0)
+ return (code);
+#endif /* CUPS_RASTER_SYNCv1 */
+
+#ifdef DEBUG
+ fputs("DEBUG2: Leaving cups_get_params()\n", stderr);
+#endif /* DEBUG */
+
+ return (0);
+}
+
+
+/*
+ * 'cups_get_space_params()' - Get space parameters from the RIP_CACHE env var.
+ */
+
+void
+cups_get_space_params(const gx_device_printer *pdev,
+ /* I - Printer device */
+ gdev_prn_space_params *space_params)
+ /* O - Space parameters */
+{
+ float cache_size; /* Size of tile cache in bytes */
+ char *cache_env, /* Cache size environment variable */
+ cache_units[255]; /* Cache size units */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_get_space_params(%p, %p)\n", pdev, space_params);
+#endif /* DEBUG */
+
+ if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL)
+ {
+ switch (sscanf(cache_env, "%f%254s", &cache_size, cache_units))
+ {
+ case 0 :
+ cache_size = 8 * 1024 * 1024;
+ break;
+ case 1 :
+ cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
+ break;
+ case 2 :
+ if (tolower(cache_units[0]) == 'g')
+ cache_size *= 1024 * 1024 * 1024;
+ else if (tolower(cache_units[0]) == 'm')
+ cache_size *= 1024 * 1024;
+ else if (tolower(cache_units[0]) == 'k')
+ cache_size *= 1024;
+ else if (tolower(cache_units[0]) == 't')
+ cache_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
+ break;
+ }
+ }
+ else
+ cache_size = 8 * 1024 * 1024;
+
+ fprintf(stderr, "DEBUG: cache_size = %.0f\n", cache_size);
+
+ space_params->MaxBitmap = (int)cache_size;
+ space_params->BufferSpace = (int)cache_size / 10;
+}
+
+
+/*
+ * 'cups_map_cielab()' - Map CIE Lab transformation...
+ */
+
+static double /* O - Adjusted color value */
+cups_map_cielab(double x, /* I - Raw color value */
+ double xn) /* I - Whitepoint color value */
+{
+ double x_xn; /* Fraction of whitepoint */
+
+
+ x_xn = x / xn;
+
+ if (x_xn > 0.008856)
+ return (cbrt(x_xn));
+ else
+ return (7.787 * x_xn + 16.0 / 116.0);
+}
+
+
+#ifdef dev_t_proc_encode_color
+/*
+ * 'cups_map_cmyk()' - Map a CMYK color value to device colors.
+ */
+
+private void
+cups_map_cmyk(gx_device *pdev, /* I - Device info */
+ frac c, /* I - Cyan value */
+ frac m, /* I - Magenta value */
+ frac y, /* I - Yellow value */
+ frac k, /* I - Black value */
+ frac *out) /* O - Device colors */
+{
+ int c0, c1, c2; /* Temporary color values */
+ float rr, rg, rb, /* Real RGB colors */
+ ciex, ciey, ciez, /* CIE XYZ colors */
+ ciey_yn, /* Normalized luminance */
+ ciel, ciea, cieb; /* CIE Lab colors */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_cmyk(%p, %d, %d, %d, %d, %p)\n",
+ pdev, c, m, y, k, out);
+#endif /* DEBUG */
+
+ /*
+ * Convert the CMYK color to the destination colorspace...
+ */
+
+ switch (cups->header.cupsColorSpace)
+ {
+ case CUPS_CSPACE_W :
+ c0 = frac_1 - (c * 31 + m * 61 + y * 8) / 100 - k;
+
+ if (c0 < 0)
+ out[0] = 0;
+ else if (c0 > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c0];
+ break;
+
+ case CUPS_CSPACE_RGBA :
+ out[3] = frac_1;
+
+ case CUPS_CSPACE_RGB :
+ c0 = frac_1 - c - k;
+ c1 = frac_1 - m - k;
+ c2 = frac_1 - y - k;
+
+ if (c0 < 0)
+ out[0] = 0;
+ else if (c0 > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c0];
+
+ if (c1 < 0)
+ out[1] = 0;
+ else if (c1 > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[c1];
+
+ if (c2 < 0)
+ out[2] = 0;
+ else if (c2 > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[c2];
+ break;
+
+ default :
+ case CUPS_CSPACE_K :
+ c0 = (c * 31 + m * 61 + y * 8) / 100 + k;
+
+ if (c0 < 0)
+ out[0] = 0;
+ else if (c0 > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c0];
+ break;
+
+ case CUPS_CSPACE_CMY :
+ c0 = c + k;
+ c1 = m + k;
+ c2 = y + k;
+
+ if (c0 < 0)
+ out[0] = 0;
+ else if (c0 > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c0];
+
+ if (c1 < 0)
+ out[1] = 0;
+ else if (c1 > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[c1];
+
+ if (c2 < 0)
+ out[2] = 0;
+ else if (c2 > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[c2];
+ break;
+
+ case CUPS_CSPACE_YMC :
+ c0 = y + k;
+ c1 = m + k;
+ c2 = c + k;
+
+ if (c0 < 0)
+ out[0] = 0;
+ else if (c0 > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c0];
+
+ if (c1 < 0)
+ out[1] = 0;
+ else if (c1 > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[c1];
+
+ if (c2 < 0)
+ out[2] = 0;
+ else if (c2 > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[c2];
+ break;
+
+ case CUPS_CSPACE_CMYK :
+ if (c < 0)
+ out[0] = 0;
+ else if (c > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[c];
+
+ if (m < 0)
+ out[1] = 0;
+ else if (m > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[m];
+
+ if (y < 0)
+ out[2] = 0;
+ else if (y > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[y];
+
+ if (k < 0)
+ out[3] = 0;
+ else if (k > frac_1)
+ out[3] = (frac)cupsDensity[frac_1];
+ else
+ out[3] = (frac)cupsDensity[k];
+ break;
+
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ if (y < 0)
+ out[0] = 0;
+ else if (y > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[y];
+
+ if (m < 0)
+ out[1] = 0;
+ else if (m > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[m];
+
+ if (c < 0)
+ out[2] = 0;
+ else if (c > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[c];
+
+ if (k < 0)
+ out[3] = 0;
+ else if (k > frac_1)
+ out[3] = (frac)cupsDensity[frac_1];
+ else
+ out[3] = (frac)cupsDensity[k];
+ break;
+
+ case CUPS_CSPACE_KCMYcm :
+ case CUPS_CSPACE_KCMY :
+ if (k < 0)
+ out[0] = 0;
+ else if (k > frac_1)
+ out[0] = (frac)cupsDensity[frac_1];
+ else
+ out[0] = (frac)cupsDensity[k];
+
+ if (c < 0)
+ out[1] = 0;
+ else if (c > frac_1)
+ out[1] = (frac)cupsDensity[frac_1];
+ else
+ out[1] = (frac)cupsDensity[c];
+
+ if (m < 0)
+ out[2] = 0;
+ else if (m > frac_1)
+ out[2] = (frac)cupsDensity[frac_1];
+ else
+ out[2] = (frac)cupsDensity[m];
+
+ if (y < 0)
+ out[3] = 0;
+ else if (y > frac_1)
+ out[3] = (frac)cupsDensity[frac_1];
+ else
+ out[3] = (frac)cupsDensity[y];
+ break;
+
+# ifdef CUPS_RASTER_HAVE_COLORIMETRIC
+ case CUPS_CSPACE_CIEXYZ :
+ case CUPS_CSPACE_CIELab :
+ case CUPS_CSPACE_ICC1 :
+ case CUPS_CSPACE_ICC2 :
+ case CUPS_CSPACE_ICC3 :
+ case CUPS_CSPACE_ICC4 :
+ case CUPS_CSPACE_ICC5 :
+ case CUPS_CSPACE_ICC6 :
+ case CUPS_CSPACE_ICC7 :
+ case CUPS_CSPACE_ICC8 :
+ case CUPS_CSPACE_ICC9 :
+ case CUPS_CSPACE_ICCA :
+ case CUPS_CSPACE_ICCB :
+ case CUPS_CSPACE_ICCC :
+ case CUPS_CSPACE_ICCD :
+ case CUPS_CSPACE_ICCE :
+ case CUPS_CSPACE_ICCF :
+ /*
+ * Convert CMYK to sRGB...
+ */
+
+ c0 = frac_1 - c - k;
+ c1 = frac_1 - m - k;
+ c2 = frac_1 - y - k;
+
+ if (c0 < 0)
+ c0 = 0;
+ else if (c0 > frac_1)
+ c0 = frac_1;
+
+ if (c1 < 0)
+ c1 = 0;
+ else if (c1 > frac_1)
+ c1 = frac_1;
+
+ if (c2 < 0)
+ c2 = 0;
+ else if (c2 > frac_1)
+ c2 = frac_1;
+
+ /*
+ * Convert sRGB to linear RGB...
+ */
+
+ rr = pow((double)c0 / (double)frac_1, 0.58823529412);
+ rg = pow((double)c1 / (double)frac_1, 0.58823529412);
+ rb = pow((double)c2 / (double)frac_1, 0.58823529412);
+
+ /*
+ * Convert to CIE XYZ...
+ */
+
+ ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb;
+ ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb;
+ ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb;
+
+ if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ)
+ {
+ /*
+ * Convert to an integer XYZ color value...
+ */
+
+ if (ciex > 1.0)
+ c0 = frac_1;
+ else if (ciex > 0.0)
+ c0 = (int)(ciex * frac_1);
+ else
+ c0 = 0;
+
+ if (ciey > 1.0)
+ c1 = frac_1;
+ else if (ciey > 0.0)
+ c1 = (int)(ciey * frac_1);
+ else
+ c1 = 0;
+
+ if (ciez > 1.0)
+ c2 = frac_1;
+ else if (ciez > 0.0)
+ c2 = (int)(ciez * frac_1);
+ else
+ c2 = 0;
+ }
+ else
+ {
+ /*
+ * Convert CIE XYZ to Lab...
+ */
+
+ ciey_yn = ciey / D65_Y;
+
+ if (ciey_yn > 0.008856)
+ ciel = 116 * cbrt(ciey_yn) - 16;
+ else
+ ciel = 903.3 * ciey_yn;
+
+ ciea = 500 * (cups_map_cielab(ciex, D65_X) -
+ cups_map_cielab(ciey, D65_Y));
+ cieb = 200 * (cups_map_cielab(ciey, D65_Y) -
+ cups_map_cielab(ciez, D65_Z));
+
+ /*
+ * Scale the L value and bias the a and b values by 128
+ * so that all values are in the range of 0 to 255.
+ */
+
+ ciel *= 2.55;
+ ciea += 128;
+ cieb += 128;
+
+ /*
+ * Convert to frac values...
+ */
+
+ if (ciel < 0.0)
+ c0 = 0;
+ else if (ciel < 255.0)
+ c0 = (int)(ciel * frac_1 / 255.0);
+ else
+ c0 = frac_1;
+
+ if (ciea < 0.0)
+ c1 = 0;
+ else if (ciea < 255.0)
+ c1 = (int)(ciea * frac_1 / 255.0);
+ else
+ c1 = frac_1;
+
+ if (cieb < 0.0)
+ c2 = 0;
+ else if (cieb < 255.0)
+ c2 = (int)(cieb * frac_1 / 255.0);
+ else
+ c2 = frac_1;
+ }
+
+ /*
+ * Put the final color value together...
+ */
+
+ out[0] = c0;
+ out[1] = c1;
+ out[2] = c2;
+ break;
+# endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
+ }
+
+ switch (cups->color_info.num_components)
+ {
+ default :
+ case 1 :
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: \\=== COLOR %d\n", out[0]);
+#endif /* DEBUG */
+ break;
+
+ case 3 :
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: \\=== COLOR %d, %d, %d\n",
+ out[0], out[1], out[2]);
+#endif /* DEBUG */
+ break;
+
+ case 4 :
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: \\=== COLOR %d, %d, %d, %d\n",
+ out[0], out[1], out[2], out[3]);
+#endif /* DEBUG */
+ break;
+ }
+}
+
+
+/*
+ * 'cups_map_gray()' - Map a grayscale value to device colors.
+ */
+
+private void
+cups_map_gray(gx_device *pdev, /* I - Device info */
+ frac g, /* I - Grayscale value */
+ frac *out) /* O - Device colors */
+{
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_gray(%p, %d, %p)\n",
+ pdev, g, out);
+#endif /* DEBUG */
+
+ /*
+ * Just use the CMYK mapper...
+ */
+
+ cups_map_cmyk(pdev, 0, 0, 0, frac_1 - g, out);
+}
+
+
+/*
+ * 'cups_map_rgb()' - Map a RGB color value to device colors.
+ */
+
+private void
+cups_map_rgb(gx_device *pdev,
+ /* I - Device info */
+ const gs_imager_state *pis,/* I - Device state */
+ frac r, /* I - Red value */
+ frac g, /* I - Green value */
+ frac b, /* I - Blue value */
+ frac *out)/* O - Device colors */
+{
+ frac c, m, y, k; /* CMYK values */
+ frac mk; /* Maximum K value */
+ int tc, tm, ty; /* Temporary color values */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_rgb(%p, %p, %d, %d, %d, %p)\n",
+ pdev, pis, r, g, b, out);
+#endif /* DEBUG */
+
+ /*
+ * Compute CMYK values...
+ */
+
+ c = frac_1 - r;
+ m = frac_1 - g;
+ y = frac_1 - b;
+ k = min(c, min(m, y));
+
+ if ((mk = max(c, max(m, y))) > k)
+ k = (int)((float)k * (float)k * (float)k / ((float)mk * (float)mk));
+
+ c -= k;
+ m -= k;
+ y -= k;
+
+ /*
+ * Do color correction as needed...
+ */
+
+ if (cupsHaveProfile)
+ {
+ /*
+ * Color correct CMY...
+ */
+
+ tc = cupsMatrix[0][0][c] +
+ cupsMatrix[0][1][m] +
+ cupsMatrix[0][2][y];
+ tm = cupsMatrix[1][0][c] +
+ cupsMatrix[1][1][m] +
+ cupsMatrix[1][2][y];
+ ty = cupsMatrix[2][0][c] +
+ cupsMatrix[2][1][m] +
+ cupsMatrix[2][2][y];
+
+ if (tc < 0)
+ c = 0;
+ else if (tc > frac_1)
+ c = frac_1;
+ else
+ c = (frac)tc;
+
+ if (tm < 0)
+ m = 0;
+ else if (tm > frac_1)
+ m = frac_1;
+ else
+ m = (frac)tm;
+
+ if (ty < 0)
+ y = 0;
+ else if (ty > frac_1)
+ y = frac_1;
+ else
+ y = (frac)ty;
+ }
+
+ /*
+ * Use the CMYK mapping function to produce the device colors...
+ */
+
+ cups_map_cmyk(pdev, c, m, y, k, out);
+}
+#else
+/*
+ * 'cups_map_cmyk_color()' - Map a CMYK color to a color index.
+ *
+ * This function is only called when a 4 or 6 color colorspace is
+ * selected for output. CMYK colors are *not* corrected but *are*
+ * density adjusted.
+ */
+
+private gx_color_index /* O - Color index */
+cups_map_cmyk_color(gx_device *pdev,
+ /* I - Device info */
+ gx_color_value c, /* I - Cyan value */
+ gx_color_value m, /* I - Magenta value */
+ gx_color_value y, /* I - Yellow value */
+ gx_color_value k) /* I - Black value */
+{
+ gx_color_index i; /* Temporary index */
+ gx_color_value ic, im, iy, ik; /* Integral CMYK values */
+
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_cmyk_color(%p, %d, %d, %d, %d)\n", pdev,
+ c, m, y, k);
+# endif /* DEBUG */
+
+ /*
+ * Setup the color info data as needed...
+ */
+
+ if (pdev->color_info.num_components == 0)
+ cups_set_color_info(pdev);
+
+ /*
+ * Density correct...
+ */
+
+ if (cupsHaveProfile)
+ {
+ c = cupsDensity[c];
+ m = cupsDensity[m];
+ y = cupsDensity[y];
+ k = cupsDensity[k];
+ }
+
+ ic = cupsEncodeLUT[c];
+ im = cupsEncodeLUT[m];
+ iy = cupsEncodeLUT[y];
+ ik = cupsEncodeLUT[k];
+
+ /*
+ * Convert the CMYK color to a color index...
+ */
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
+ break;
+ case 2 :
+ i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
+ break;
+ case 4 :
+ i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
+ break;
+ case 8 :
+ i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
+ break;
+ case 2 :
+ i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
+ break;
+ case 4 :
+ i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
+ break;
+ case 8 :
+ i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_KCMYcm :
+ if (cups->header.cupsBitsPerColor == 1)
+ {
+ if (ik)
+ i = 32;
+ else
+ i = 0;
+
+ if (ic && im)
+ i |= 17;
+ else if (ic && iy)
+ i |= 6;
+ else if (im && iy)
+ i |= 12;
+ else if (ic)
+ i |= 16;
+ else if (im)
+ i |= 8;
+ else if (iy)
+ i |= 4;
+ break;
+ }
+
+ case CUPS_CSPACE_KCMY :
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
+ break;
+ case 2 :
+ i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
+ break;
+ case 4 :
+ i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
+ break;
+ case 8 :
+ i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
+ break;
+ }
+ break;
+ }
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: CMYK (%d,%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n",
+ c, m, y, k, (unsigned)i, ic, im, iy, ik);
+# endif /* DEBUG */
+
+ /*
+ * Make sure we don't get a CMYK color of 255, 255, 255, 255...
+ */
+
+ if (i == gx_no_color_index)
+ i --;
+
+ return (i);
+}
+
+
+/*
+ * 'cups_map_color_rgb()' - Map a color index to an RGB color.
+ */
+
+private int
+cups_map_color_rgb(gx_device *pdev,/* I - Device info */
+ gx_color_index color,/* I - Color index */
+ gx_color_value prgb[3])
+ /* O - RGB values */
+{
+ unsigned char c0, c1, c2, c3; /* Color index components */
+ gx_color_value k, divk; /* Black & divisor */
+
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_color_rgb(%p, %d, %p)\n", pdev,
+ (unsigned)color, prgb);
+# endif /* DEBUG */
+
+ /*
+ * Setup the color info data as needed...
+ */
+
+ if (pdev->color_info.num_components == 0)
+ cups_set_color_info(pdev);
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: COLOR %08x = ", (unsigned)color);
+# endif /* DEBUG */
+
+ /*
+ * Extract the color components from the color index...
+ */
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ c3 = color & 1;
+ color >>= 1;
+ c2 = color & 1;
+ color >>= 1;
+ c1 = color & 1;
+ color >>= 1;
+ c0 = color;
+ break;
+ case 2 :
+ c3 = color & 3;
+ color >>= 2;
+ c2 = color & 3;
+ color >>= 2;
+ c1 = color & 3;
+ color >>= 2;
+ c0 = color;
+ break;
+ case 4 :
+ c3 = color & 15;
+ color >>= 4;
+ c2 = color & 15;
+ color >>= 4;
+ c1 = color & 15;
+ color >>= 4;
+ c0 = color;
+ break;
+ case 8 :
+ c3 = color & 255;
+ color >>= 8;
+ c2 = color & 255;
+ color >>= 8;
+ c1 = color & 255;
+ color >>= 8;
+ c0 = color;
+ break;
+ }
+
+ /*
+ * Convert the color components to RGB...
+ */
+
+ switch (cups->header.cupsColorSpace)
+ {
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ prgb[0] =
+ prgb[1] =
+ prgb[2] = cupsDecodeLUT[c3];
+ break;
+
+ case CUPS_CSPACE_W :
+ prgb[0] =
+ prgb[1] =
+ prgb[2] = cupsDecodeLUT[c3];
+ break;
+
+ case CUPS_CSPACE_RGB :
+ prgb[0] = cupsDecodeLUT[c1];
+ prgb[1] = cupsDecodeLUT[c2];
+ prgb[2] = cupsDecodeLUT[c3];
+ break;
+
+ case CUPS_CSPACE_RGBA :
+ prgb[0] = cupsDecodeLUT[c0];
+ prgb[1] = cupsDecodeLUT[c1];
+ prgb[2] = cupsDecodeLUT[c2];
+ break;
+
+ case CUPS_CSPACE_CMY :
+ prgb[0] = cupsDecodeLUT[c1];
+ prgb[1] = cupsDecodeLUT[c2];
+ prgb[2] = cupsDecodeLUT[c3];
+ break;
+
+ case CUPS_CSPACE_YMC :
+ prgb[0] = cupsDecodeLUT[c3];
+ prgb[1] = cupsDecodeLUT[c2];
+ prgb[2] = cupsDecodeLUT[c1];
+ break;
+
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ k = cupsDecodeLUT[c0];
+ divk = gx_max_color_value - k;
+ if (divk == 0)
+ {
+ prgb[0] = 0;
+ prgb[1] = 0;
+ prgb[2] = 0;
+ }
+ else
+ {
+ prgb[0] = gx_max_color_value + divk -
+ gx_max_color_value * c1 / divk;
+ prgb[1] = gx_max_color_value + divk -
+ gx_max_color_value * c2 / divk;
+ prgb[2] = gx_max_color_value + divk -
+ gx_max_color_value * c3 / divk;
+ }
+ break;
+
+ case CUPS_CSPACE_CMYK :
+ k = cupsDecodeLUT[c3];
+ divk = gx_max_color_value - k;
+ if (divk == 0)
+ {
+ prgb[0] = 0;
+ prgb[1] = 0;
+ prgb[2] = 0;
+ }
+ else
+ {
+ prgb[0] = gx_max_color_value + divk -
+ gx_max_color_value * c0 / divk;
+ prgb[1] = gx_max_color_value + divk -
+ gx_max_color_value * c1 / divk;
+ prgb[2] = gx_max_color_value + divk -
+ gx_max_color_value * c2 / divk;
+ }
+ break;
+
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ k = cupsDecodeLUT[c3];
+ divk = gx_max_color_value - k;
+ if (divk == 0)
+ {
+ prgb[0] = 0;
+ prgb[1] = 0;
+ prgb[2] = 0;
+ }
+ else
+ {
+ prgb[0] = gx_max_color_value + divk -
+ gx_max_color_value * c2 / divk;
+ prgb[1] = gx_max_color_value + divk -
+ gx_max_color_value * c1 / divk;
+ prgb[2] = gx_max_color_value + divk -
+ gx_max_color_value * c0 / divk;
+ }
+ break;
+
+# ifdef CUPS_RASTER_HAVE_COLORIMETRIC
+ case CUPS_CSPACE_CIEXYZ :
+ case CUPS_CSPACE_CIELab :
+ case CUPS_CSPACE_ICC1 :
+ case CUPS_CSPACE_ICC2 :
+ case CUPS_CSPACE_ICC3 :
+ case CUPS_CSPACE_ICC4 :
+ case CUPS_CSPACE_ICC5 :
+ case CUPS_CSPACE_ICC6 :
+ case CUPS_CSPACE_ICC7 :
+ case CUPS_CSPACE_ICC8 :
+ case CUPS_CSPACE_ICC9 :
+ case CUPS_CSPACE_ICCA :
+ case CUPS_CSPACE_ICCB :
+ case CUPS_CSPACE_ICCC :
+ case CUPS_CSPACE_ICCD :
+ case CUPS_CSPACE_ICCE :
+ case CUPS_CSPACE_ICCF :
+ break;
+# endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
+ }
+
+# ifdef DEBUG
+ fprintf(stderr, "%d,%d,%d\n", prgb[0], prgb[1], prgb[2]);
+# endif /* DEBUG */
+
+ return (0);
+}
+
+
+/*
+ * 'cups_map_rgb_color()' - Map an RGB color to a color index. We map the
+ * RGB color to the output colorspace & bits (we
+ * figure out the format when we output a page).
+ */
+
+private gx_color_index /* O - Color index */
+cups_map_rgb_color(gx_device *pdev,/* I - Device info */
+ gx_color_value r, /* I - Red value */
+ gx_color_value g, /* I - Green value */
+ gx_color_value b) /* I - Blue value */
+{
+ gx_color_index i; /* Temporary index */
+ gx_color_value ic, im, iy, ik; /* Integral CMYK values */
+ gx_color_value mk; /* Maximum K value */
+ int tc, tm, ty; /* Temporary color values */
+ float rr, rg, rb, /* Real RGB colors */
+ ciex, ciey, ciez,
+ /* CIE XYZ colors */
+ ciey_yn, /* Normalized luminance */
+ ciel, ciea, cieb;
+ /* CIE Lab colors */
+
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_map_rgb_color(%p, %d, %d, %d)\n", pdev, r, g, b);
+# endif /* DEBUG */
+
+ /*
+ * Setup the color info data as needed...
+ */
+
+ if (pdev->color_info.num_components == 0)
+ cups_set_color_info(pdev);
+
+ /*
+ * Do color correction as needed...
+ */
+
+ if (cupsHaveProfile)
+ {
+ /*
+ * Compute CMYK values...
+ */
+
+ ic = gx_max_color_value - r;
+ im = gx_max_color_value - g;
+ iy = gx_max_color_value - b;
+ ik = min(ic, min(im, iy));
+
+ if ((mk = max(ic, max(im, iy))) > ik)
+ ik = (int)((float)ik * (float)ik * (float)ik / ((float)mk * (float)mk));
+
+ ic -= ik;
+ im -= ik;
+ iy -= ik;
+
+ /*
+ * Color correct CMY...
+ */
+
+ tc = cupsMatrix[0][0][ic] +
+ cupsMatrix[0][1][im] +
+ cupsMatrix[0][2][iy] +
+ ik;
+ tm = cupsMatrix[1][0][ic] +
+ cupsMatrix[1][1][im] +
+ cupsMatrix[1][2][iy] +
+ ik;
+ ty = cupsMatrix[2][0][ic] +
+ cupsMatrix[2][1][im] +
+ cupsMatrix[2][2][iy] +
+ ik;
+
+ /*
+ * Density correct combined CMYK...
+ */
+
+ if (tc < 0)
+ r = gx_max_color_value;
+ else if (tc > gx_max_color_value)
+ r = gx_max_color_value - cupsDensity[gx_max_color_value];
+ else
+ r = gx_max_color_value - cupsDensity[tc];
+
+ if (tm < 0)
+ g = gx_max_color_value;
+ else if (tm > gx_max_color_value)
+ g = gx_max_color_value - cupsDensity[gx_max_color_value];
+ else
+ g = gx_max_color_value - cupsDensity[tm];
+
+ if (ty < 0)
+ b = gx_max_color_value;
+ else if (ty > gx_max_color_value)
+ b = gx_max_color_value - cupsDensity[gx_max_color_value];
+ else
+ b = gx_max_color_value - cupsDensity[ty];
+ }
+
+ /*
+ * Convert the RGB color to a color index...
+ */
+
+ switch (cups->header.cupsColorSpace)
+ {
+ case CUPS_CSPACE_W :
+ i = cupsEncodeLUT[(r * 31 + g * 61 + b * 8) / 100];
+ break;
+
+ case CUPS_CSPACE_RGB :
+ ic = cupsEncodeLUT[r];
+ im = cupsEncodeLUT[g];
+ iy = cupsEncodeLUT[b];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((ic << 1) | im) << 1) | iy;
+ break;
+ case 2 :
+ i = (((ic << 2) | im) << 2) | iy;
+ break;
+ case 4 :
+ i = (((ic << 4) | im) << 4) | iy;
+ break;
+ case 8 :
+ i = (((ic << 8) | im) << 8) | iy;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_RGBA :
+ ic = cupsEncodeLUT[r];
+ im = cupsEncodeLUT[g];
+ iy = cupsEncodeLUT[b];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((ic << 1) | im) << 1) | iy) << 1) | 0x01;
+ break;
+ case 2 :
+ i = (((((ic << 2) | im) << 2) | iy) << 2) | 0x03;
+ break;
+ case 4 :
+ i = (((((ic << 4) | im) << 4) | iy) << 4) | 0x0f;
+ break;
+ case 8 :
+ i = (((((ic << 8) | im) << 8) | iy) << 8) | 0xff;
+ break;
+ }
+ break;
+
+ default :
+ i = cupsEncodeLUT[gx_max_color_value - (r * 31 + g * 61 + b * 8) / 100];
+ break;
+
+ case CUPS_CSPACE_CMY :
+ ic = cupsEncodeLUT[gx_max_color_value - r];
+ im = cupsEncodeLUT[gx_max_color_value - g];
+ iy = cupsEncodeLUT[gx_max_color_value - b];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((ic << 1) | im) << 1) | iy;
+ break;
+ case 2 :
+ i = (((ic << 2) | im) << 2) | iy;
+ break;
+ case 4 :
+ i = (((ic << 4) | im) << 4) | iy;
+ break;
+ case 8 :
+ i = (((ic << 8) | im) << 8) | iy;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_YMC :
+ ic = cupsEncodeLUT[gx_max_color_value - r];
+ im = cupsEncodeLUT[gx_max_color_value - g];
+ iy = cupsEncodeLUT[gx_max_color_value - b];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((iy << 1) | im) << 1) | ic;
+ break;
+ case 2 :
+ i = (((iy << 2) | im) << 2) | ic;
+ break;
+ case 4 :
+ i = (((iy << 4) | im) << 4) | ic;
+ break;
+ case 8 :
+ i = (((iy << 8) | im) << 8) | ic;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_CMYK :
+ ic = gx_max_color_value - r;
+ im = gx_max_color_value - g;
+ iy = gx_max_color_value - b;
+ ik = min(ic, min(im, iy));
+
+ if ((mk = max(ic, max(im, iy))) > ik)
+ ik = (int)((float)ik * (float)ik * (float)ik /
+ ((float)mk * (float)mk));
+
+ ic = cupsEncodeLUT[ic - ik];
+ im = cupsEncodeLUT[im - ik];
+ iy = cupsEncodeLUT[iy - ik];
+ ik = cupsEncodeLUT[ik];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((ic << 1) | im) << 1) | iy) << 1) | ik;
+ break;
+ case 2 :
+ i = (((((ic << 2) | im) << 2) | iy) << 2) | ik;
+ break;
+ case 4 :
+ i = (((((ic << 4) | im) << 4) | iy) << 4) | ik;
+ break;
+ case 8 :
+ i = (((((ic << 8) | im) << 8) | iy) << 8) | ik;
+ break;
+ }
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: CMY (%d,%d,%d) -> CMYK %08x (%d,%d,%d,%d)\n",
+ r, g, b, (unsigned)i, ic, im, iy, ik);
+# endif /* DEBUG */
+ break;
+
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ ic = gx_max_color_value - r;
+ im = gx_max_color_value - g;
+ iy = gx_max_color_value - b;
+ ik = min(ic, min(im, iy));
+
+ if ((mk = max(ic, max(im, iy))) > ik)
+ ik = (int)((float)ik * (float)ik * (float)ik /
+ ((float)mk * (float)mk));
+
+ ic = cupsEncodeLUT[ic - ik];
+ im = cupsEncodeLUT[im - ik];
+ iy = cupsEncodeLUT[iy - ik];
+ ik = cupsEncodeLUT[ik];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((iy << 1) | im) << 1) | ic) << 1) | ik;
+ break;
+ case 2 :
+ i = (((((iy << 2) | im) << 2) | ic) << 2) | ik;
+ break;
+ case 4 :
+ i = (((((iy << 4) | im) << 4) | ic) << 4) | ik;
+ break;
+ case 8 :
+ i = (((((iy << 8) | im) << 8) | ic) << 8) | ik;
+ break;
+ }
+ break;
+
+ case CUPS_CSPACE_KCMYcm :
+ if (cups->header.cupsBitsPerColor == 1)
+ {
+ ic = gx_max_color_value - r;
+ im = gx_max_color_value - g;
+ iy = gx_max_color_value - b;
+ ik = min(ic, min(im, iy));
+
+ if ((mk = max(ic, max(im, iy))) > ik)
+ ik = (int)((float)ik * (float)ik * (float)ik /
+ ((float)mk * (float)mk));
+
+ ic = cupsEncodeLUT[ic - ik];
+ im = cupsEncodeLUT[im - ik];
+ iy = cupsEncodeLUT[iy - ik];
+ ik = cupsEncodeLUT[ik];
+ if (ik)
+ i = 32;
+ else if (ic && im)
+ i = 17;
+ else if (ic && iy)
+ i = 6;
+ else if (im && iy)
+ i = 12;
+ else if (ic)
+ i = 16;
+ else if (im)
+ i = 8;
+ else if (iy)
+ i = 4;
+ else
+ i = 0;
+ break;
+ }
+
+ case CUPS_CSPACE_KCMY :
+ ic = gx_max_color_value - r;
+ im = gx_max_color_value - g;
+ iy = gx_max_color_value - b;
+ ik = min(ic, min(im, iy));
+
+ if ((mk = max(ic, max(im, iy))) > ik)
+ ik = (int)((float)ik * (float)ik * (float)ik /
+ ((float)mk * (float)mk));
+
+ ic = cupsEncodeLUT[ic - ik];
+ im = cupsEncodeLUT[im - ik];
+ iy = cupsEncodeLUT[iy - ik];
+ ik = cupsEncodeLUT[ik];
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((((ik << 1) | ic) << 1) | im) << 1) | iy;
+ break;
+ case 2 :
+ i = (((((ik << 2) | ic) << 2) | im) << 2) | iy;
+ break;
+ case 4 :
+ i = (((((ik << 4) | ic) << 4) | im) << 4) | iy;
+ break;
+ case 8 :
+ i = (((((ik << 8) | ic) << 8) | im) << 8) | iy;
+ break;
+ }
+ break;
+
+# ifdef CUPS_RASTER_HAVE_COLORIMETRIC
+ case CUPS_CSPACE_CIEXYZ :
+ case CUPS_CSPACE_CIELab :
+ case CUPS_CSPACE_ICC1 :
+ case CUPS_CSPACE_ICC2 :
+ case CUPS_CSPACE_ICC3 :
+ case CUPS_CSPACE_ICC4 :
+ case CUPS_CSPACE_ICC5 :
+ case CUPS_CSPACE_ICC6 :
+ case CUPS_CSPACE_ICC7 :
+ case CUPS_CSPACE_ICC8 :
+ case CUPS_CSPACE_ICC9 :
+ case CUPS_CSPACE_ICCA :
+ case CUPS_CSPACE_ICCB :
+ case CUPS_CSPACE_ICCC :
+ case CUPS_CSPACE_ICCD :
+ case CUPS_CSPACE_ICCE :
+ case CUPS_CSPACE_ICCF :
+ /*
+ * Convert sRGB to linear RGB...
+ */
+
+ rr = pow((double)r / (double)gx_max_color_value, 0.58823529412);
+ rg = pow((double)g / (double)gx_max_color_value, 0.58823529412);
+ rb = pow((double)b / (double)gx_max_color_value, 0.58823529412);
+
+ /*
+ * Convert to CIE XYZ...
+ */
+
+ ciex = 0.412453 * rr + 0.357580 * rg + 0.180423 * rb;
+ ciey = 0.212671 * rr + 0.715160 * rg + 0.072169 * rb;
+ ciez = 0.019334 * rr + 0.119193 * rg + 0.950227 * rb;
+
+ if (cups->header.cupsColorSpace == CUPS_CSPACE_CIEXYZ)
+ {
+ /*
+ * Convert to an integer XYZ color value...
+ */
+
+ if (ciex > 1.0)
+ ic = 255;
+ else if (ciex > 0.0)
+ ic = (int)(ciex * 255.0);
+ else
+ ic = 0;
+
+ if (ciey > 1.0)
+ im = 255;
+ else if (ciey > 0.0)
+ im = (int)(ciey * 255.0);
+ else
+ im = 0;
+
+ if (ciez > 1.0)
+ iy = 255;
+ else if (ciez > 0.0)
+ iy = (int)(ciez * 255.0);
+ else
+ iy = 0;
+ }
+ else
+ {
+ /*
+ * Convert CIE XYZ to Lab...
+ */
+
+ ciey_yn = ciey / D65_Y;
+
+ if (ciey_yn > 0.008856)
+ ciel = 116 * cbrt(ciey_yn) - 16;
+ else
+ ciel = 903.3 * ciey_yn;
+
+ ciea = 500 * (cups_map_cielab(ciex, D65_X) -
+ cups_map_cielab(ciey, D65_Y));
+ cieb = 200 * (cups_map_cielab(ciey, D65_Y) -
+ cups_map_cielab(ciez, D65_Z));
+
+ /*
+ * Scale the L value and bias the a and b values by 128
+ * so that all values are in the range of 0 to 255.
+ */
+
+ ciel *= 2.55;
+ ciea += 128;
+ cieb += 128;
+
+ /*
+ * Convert to 8-bit values...
+ */
+
+ if (ciel < 0.0)
+ ic = 0;
+ else if (ciel < 255.0)
+ ic = ciel;
+ else
+ ic = 255;
+
+ if (ciea < 0.0)
+ im = 0;
+ else if (ciea < 255.0)
+ im = ciea;
+ else
+ im = 255;
+
+ if (cieb < 0.0)
+ iy = 0;
+ else if (cieb < 255.0)
+ iy = cieb;
+ else
+ iy = 255;
+ }
+
+ /*
+ * Put the final color value together...
+ */
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ i = (((ic << 1) | im) << 1) | iy;
+ break;
+ case 2 :
+ i = (((ic << 2) | im) << 2) | iy;
+ break;
+ case 4 :
+ i = (((ic << 4) | im) << 4) | iy;
+ break;
+ case 8 :
+ i = (((ic << 8) | im) << 8) | iy;
+ break;
+ }
+ break;
+# endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
+ }
+
+# ifdef DEBUG
+ fprintf(stderr, "DEBUG2: RGB %d,%d,%d = %08x\n", r, g, b, (unsigned)i);
+# endif /* DEBUG */
+
+ return (i);
+}
+#endif /* dev_t_proc_encode_color */
+
+
+/*
+ * 'cups_open()' - Open the output file and initialize things.
+ */
+
+private int /* O - Error status */
+cups_open(gx_device *pdev) /* I - Device info */
+{
+ int code; /* Return status */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_open(%p)\n", pdev);
+#endif /* DEBUG */
+
+ cups->printer_procs.get_space_params = cups_get_space_params;
+
+ if (cups->page == 0)
+ {
+ fputs("INFO: Processing page 1...\n", stderr);
+ cups->page = 1;
+ }
+
+ cups_set_color_info(pdev);
+
+ if ((code = gdev_prn_open(pdev)) != 0)
+ return (code);
+
+ if (cupsPPD == NULL)
+ cupsPPD = ppdOpenFile(getenv("PPD"));
+
+ return (0);
+}
+
+
+/*
+ * 'cups_print_pages()' - Send one or more pages to the output file.
+ */
+
+private int /* O - 0 if everything is OK */
+cups_print_pages(gx_device_printer *pdev,
+ /* I - Device info */
+ FILE *fp, /* I - Output file */
+ int num_copies)
+ /* I - Number of copies */
+{
+ int copy; /* Copy number */
+ int srcbytes; /* Byte width of scanline */
+ unsigned char *src, /* Scanline data */
+ *dst; /* Bitmap data */
+
+
+ (void)fp; /* reference unused file pointer to prevent compiler warning */
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_print_pages(%p, %p, %d)\n", pdev, fp,
+ num_copies);
+#endif /* DEBUG */
+
+ /*
+ * Figure out the number of bytes per line...
+ */
+
+ switch (cups->header.cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerPixel *
+ cups->header.cupsWidth + 7) / 8;
+ break;
+
+ case CUPS_ORDER_BANDED :
+ if (cups->header.cupsColorSpace == CUPS_CSPACE_KCMYcm &&
+ cups->header.cupsBitsPerColor == 1)
+ cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
+ cups->header.cupsWidth + 7) / 8 * 6;
+ else
+ cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
+ cups->header.cupsWidth + 7) / 8 *
+ cups->color_info.num_components;
+ break;
+
+ case CUPS_ORDER_PLANAR :
+ cups->header.cupsBytesPerLine = (cups->header.cupsBitsPerColor *
+ cups->header.cupsWidth + 7) / 8;
+ break;
+ }
+
+ /*
+ * Compute the width of a scanline and allocate input/output buffers...
+ */
+
+ srcbytes = gdev_prn_raster(pdev);
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cupsBitsPerPixel = %d, cupsWidth = %d, cupsBytesPerLine = %d, srcbytes = %d\n",
+ cups->header.cupsBitsPerPixel, cups->header.cupsWidth,
+ cups->header.cupsBytesPerLine, srcbytes);
+#endif /* DEBUG */
+
+ src = (unsigned char *)gs_malloc(srcbytes, 1, "cups_print_pages");
+
+ if (src == NULL) /* can't allocate input buffer */
+ return_error(gs_error_VMerror);
+
+ /*
+ * Need an output buffer, too...
+ */
+
+ dst = (unsigned char *)gs_malloc(cups->header.cupsBytesPerLine, 2,
+ "cups_print_pages");
+
+ if (dst == NULL) /* can't allocate working area */
+ return_error(gs_error_VMerror);
+
+ /*
+ * See if the stream has been initialized yet...
+ */
+
+ if (cups->stream == NULL)
+ {
+ if ((cups->stream = cupsRasterOpen(fileno(cups->file),
+ CUPS_RASTER_WRITE)) == NULL)
+ {
+ perror("ERROR: Unable to open raster stream - ");
+ gs_exit(0);
+ }
+ }
+
+ /*
+ * Output a page of graphics...
+ */
+
+ if (num_copies < 1)
+ num_copies = 1;
+
+ if (cupsPPD != NULL && !cupsPPD->manual_copies)
+ {
+ cups->header.NumCopies = num_copies;
+ num_copies = 1;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cupsWidth = %d, cupsHeight = %d, cupsBytesPerLine = %d\n",
+ cups->header.cupsWidth, cups->header.cupsHeight,
+ cups->header.cupsBytesPerLine);
+#endif /* DEBUG */
+
+ for (copy = num_copies; copy > 0; copy --)
+ {
+ cupsRasterWriteHeader(cups->stream, &(cups->header));
+
+ if (pdev->color_info.num_components == 1)
+ cups_print_chunked(pdev, src, dst, srcbytes);
+ else
+ switch (cups->header.cupsColorOrder)
+ {
+ case CUPS_ORDER_CHUNKED :
+ cups_print_chunked(pdev, src, dst, srcbytes);
+ break;
+ case CUPS_ORDER_BANDED :
+ cups_print_banded(pdev, src, dst, srcbytes);
+ break;
+ case CUPS_ORDER_PLANAR :
+ cups_print_planar(pdev, src, dst, srcbytes);
+ break;
+ }
+ }
+
+ /*
+ * Free temporary storage and return...
+ */
+
+ gs_free((char *)src, srcbytes, 1, "cups_print_pages");
+ gs_free((char *)dst, cups->header.cupsBytesPerLine, 1, "cups_print_pages");
+
+ cups->page ++;
+ fprintf(stderr, "INFO: Processing page %d...\n", cups->page);
+
+ return (0);
+}
+
+
+/*
+ * 'cups_put_params()' - Set pagedevice parameters.
+ */
+
+private int /* O - Error status */
+cups_put_params(gx_device *pdev, /* I - Device info */
+ gs_param_list *plist) /* I - Parameter list */
+{
+ int i; /* Looping var */
+#ifdef CUPS_RASTER_SYNCv1
+ char name[255]; /* Name of attribute */
+#endif /* CUPS_RASTER_SYNCv1 */
+ float margins[4]; /* Physical margins of print */
+ ppd_size_t *size; /* Page size */
+ int code; /* Error code */
+ int intval; /* Integer value */
+ bool boolval; /* Boolean value */
+ float floatval; /* Floating point value */
+ gs_param_string stringval; /* String value */
+ gs_param_float_array arrayval; /* Float array value */
+ int size_set; /* Was the size set? */
+ int color_set; /* Were the color attrs set? */
+ gdev_prn_space_params sp; /* Space parameter data */
+ int width, /* New width of page */
+ height; /* New height of page */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_put_params(%p, %p)\n", pdev, plist);
+#endif /* DEBUG */
+
+ /*
+ * Process other options for CUPS...
+ */
+
+#define stringoption(name, sname) \
+ if ((code = param_read_string(plist, sname, &stringval)) < 0) \
+ { \
+ param_signal_error(plist, sname, code); \
+ return (code); \
+ } \
+ else if (code == 0) \
+ { \
+ strncpy(cups->header.name, (const char *)stringval.data, \
+ stringval.size); \
+ cups->header.name[stringval.size] = '\0'; \
+ }
+
+#define intoption(name, sname, type) \
+ if ((code = param_read_int(plist, sname, &intval)) < 0) \
+ { \
+ param_signal_error(plist, sname, code); \
+ return (code); \
+ } \
+ else if (code == 0) \
+ { \
+ fprintf(stderr, "DEBUG: Setting %s to %d...\n", sname, intval); \
+ cups->header.name = (type)intval; \
+ }
+
+#define floatoption(name, sname) \
+ if ((code = param_read_float(plist, sname, &floatval)) < 0) \
+ { \
+ param_signal_error(plist, sname, code); \
+ return (code); \
+ } \
+ else if (code == 0) \
+ cups->header.name = (unsigned)floatval;
+
+#define booloption(name, sname) \
+ if ((code = param_read_bool(plist, sname, &boolval)) < 0) \
+ { \
+ if ((code = param_read_null(plist, sname)) < 0) \
+ { \
+ param_signal_error(plist, sname, code); \
+ return (code); \
+ } \
+ if (code == 0) \
+ cups->header.name = CUPS_FALSE; \
+ } \
+ else if (code == 0) \
+ cups->header.name = (cups_bool_t)boolval;
+
+#define arrayoption(name, sname, count) \
+ if ((code = param_read_float_array(plist, sname, &arrayval)) < 0) \
+ { \
+ if ((code = param_read_null(plist, sname)) < 0) \
+ { \
+ param_signal_error(plist, sname, code); \
+ return (code); \
+ } \
+ if (code == 0) \
+ for (i = 0; i < count; i ++) \
+ cups->header.name[i] = 0; \
+ } \
+ else if (code == 0) \
+ { \
+ for (i = 0; i < count; i ++) \
+ cups->header.name[i] = (unsigned)arrayval.data[i]; \
+ }
+
+ size_set = param_read_float_array(plist, ".MediaSize", &arrayval) == 0 ||
+ param_read_float_array(plist, "PageSize", &arrayval) == 0;
+ color_set = param_read_int(plist, "cupsColorSpace", &intval) == 0 ||
+ param_read_int(plist, "cupsBitsPerColor", &intval) == 0;
+
+ stringoption(MediaClass, "MediaClass")
+ stringoption(MediaColor, "MediaColor")
+ stringoption(MediaType, "MediaType")
+ stringoption(OutputType, "OutputType")
+ floatoption(AdvanceDistance, "AdvanceDistance")
+ intoption(AdvanceMedia, "AdvanceMedia", cups_adv_t)
+ booloption(Collate, "Collate")
+ intoption(CutMedia, "CutMedia", cups_cut_t)
+ booloption(Duplex, "Duplex")
+ arrayoption(ImagingBoundingBox, "ImagingBoundingBox", 4)
+ booloption(InsertSheet, "InsertSheet")
+ intoption(Jog, "Jog", cups_jog_t)
+ intoption(LeadingEdge, "LeadingEdge", cups_edge_t)
+ arrayoption(Margins, "Margins", 2)
+ booloption(ManualFeed, "ManualFeed")
+ intoption(MediaPosition, "cupsMediaPosition", unsigned) /* Compatibility */
+ intoption(MediaPosition, "MediaPosition", unsigned)
+ floatoption(MediaWeight, "MediaWeight")
+ booloption(MirrorPrint, "MirrorPrint")
+ booloption(NegativePrint, "NegativePrint")
+ intoption(Orientation, "Orientation", cups_orient_t)
+ booloption(OutputFaceUp, "OutputFaceUp")
+ booloption(Separations, "Separations")
+ booloption(TraySwitch, "TraySwitch")
+ booloption(Tumble, "Tumble")
+ intoption(cupsMediaType, "cupsMediaType", unsigned)
+ intoption(cupsBitsPerColor, "cupsBitsPerColor", unsigned)
+ intoption(cupsColorOrder, "cupsColorOrder", cups_order_t)
+ intoption(cupsColorSpace, "cupsColorSpace", cups_cspace_t)
+ intoption(cupsCompression, "cupsCompression", unsigned)
+ intoption(cupsRowCount, "cupsRowCount", unsigned)
+ intoption(cupsRowFeed, "cupsRowFeed", unsigned)
+ intoption(cupsRowStep, "cupsRowStep", unsigned)
+
+#ifdef CUPS_RASTER_SYNCv1
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsInteger%d", i);
+ intoption(cupsInteger[i], name, unsigned)
+ }
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsReal%d", i);
+ floatoption(cupsReal[i], name)
+ }
+
+ for (i = 0; i < 16; i ++)
+ {
+ sprintf(name, "cupsString%d", i);
+ stringoption(cupsString[i], name)
+ }
+
+ stringoption(cupsMarkerType, "cupsMarkerType");
+ stringoption(cupsRenderingIntent, "cupsRenderingIntent");
+#endif /* CUPS_RASTER_SYNCv1 */
+
+ if ((code = param_read_string(plist, "cupsProfile", &stringval)) < 0)
+ {
+ param_signal_error(plist, "cupsProfile", code);
+ return (code);
+ }
+ else if (code == 0)
+ {
+ if (cupsProfile != NULL)
+ free(cupsProfile);
+
+ cupsProfile = strdup(stringval.data);
+ }
+
+ cups_set_color_info(pdev);
+
+ /*
+ * Then process standard page device options...
+ */
+
+ if ((code = gdev_prn_put_params(pdev, plist)) < 0)
+ return (code);
+
+ /*
+ * Update margins/sizes as needed...
+ */
+
+ if (size_set)
+ {
+ /*
+ * Compute the page margins...
+ */
+
+ fprintf(stderr, "DEBUG: Updating PageSize to [%.0f %.0f]...\n",
+ cups->MediaSize[0], cups->MediaSize[1]);
+
+ memset(margins, 0, sizeof(margins));
+
+ cups->landscape = 0;
+
+ if (cupsPPD != NULL)
+ {
+ /*
+ * Find the matching page size...
+ */
+
+ for (i = cupsPPD->num_sizes, size = cupsPPD->sizes;
+ i > 0;
+ i --, size ++)
+ if (fabs(cups->MediaSize[1] - size->length) < 5.0 &&
+ fabs(cups->MediaSize[0] - size->width) < 5.0)
+ break;
+
+ if (i > 0)
+ {
+ /*
+ * Standard size...
+ */
+
+ fprintf(stderr, "DEBUG: size = %s\n", size->name);
+
+ gx_device_set_media_size(pdev, size->width, size->length);
+
+ margins[0] = size->left / 72.0;
+ margins[1] = size->bottom / 72.0;
+ margins[2] = (size->width - size->right) / 72.0;
+ margins[3] = (size->length - size->top) / 72.0;
+ }
+ else
+ {
+ /*
+ * No matching portrait size; look for a matching size in
+ * landscape orientation...
+ */
+
+ for (i = cupsPPD->num_sizes, size = cupsPPD->sizes;
+ i > 0;
+ i --, size ++)
+ if (fabs(cups->MediaSize[0] - size->length) < 5.0 &&
+ fabs(cups->MediaSize[1] - size->width) < 5.0)
+ break;
+
+ if (i > 0)
+ {
+ /*
+ * Standard size in landscape orientation...
+ */
+
+ fprintf(stderr, "DEBUG: landscape size = %s\n", size->name);
+
+ gx_device_set_media_size(pdev, size->length, size->width);
+
+ cups->landscape = 1;
+
+ margins[0] = size->left / 72.0;
+ margins[1] = size->bottom / 72.0;
+ margins[2] = (size->width - size->right) / 72.0;
+ margins[3] = (size->length - size->top) / 72.0;
+ }
+ else
+ {
+ /*
+ * Custom size...
+ */
+
+ fputs("DEBUG: size = Custom\n", stderr);
+
+ for (i = 0; i < 4; i ++)
+ margins[i] = cupsPPD->custom_margins[i] / 72.0;
+ }
+ }
+
+ fprintf(stderr, "DEBUG: margins[] = [ %f %f %f %f ]\n",
+ margins[0], margins[1], margins[2], margins[3]);
+ }
+
+ /*
+ * Set the margins to update the bitmap size...
+ */
+
+ gx_device_set_margins(pdev, margins, false);
+ }
+
+ /*
+ * Set CUPS raster header values...
+ */
+
+ cups->header.HWResolution[0] = pdev->HWResolution[0];
+ cups->header.HWResolution[1] = pdev->HWResolution[1];
+
+ cups->header.Margins[0] = pdev->HWMargins[0];
+ cups->header.Margins[1] = pdev->HWMargins[1];
+
+ cups->header.PageSize[0] = pdev->MediaSize[0];
+ cups->header.PageSize[1] = pdev->MediaSize[1];
+
+ cups->header.ImagingBoundingBox[0] = pdev->HWMargins[0];
+ cups->header.ImagingBoundingBox[1] = pdev->HWMargins[3];
+ cups->header.ImagingBoundingBox[2] = pdev->MediaSize[0] - pdev->HWMargins[2];
+ cups->header.ImagingBoundingBox[3] = pdev->MediaSize[1] - pdev->HWMargins[1];
+
+ /*
+ * Reallocate memory if the size or color depth was changed...
+ */
+
+ if (color_set || size_set)
+ {
+ /*
+ * Make sure the page image is the correct size - current Ghostscript
+ * does not keep track of the margins in the bitmap size...
+ */
+
+ if (cups->landscape)
+ {
+ width = (pdev->MediaSize[1] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
+ pdev->HWResolution[0] / 72.0f + 0.499f;
+ height = (pdev->MediaSize[0] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
+ pdev->HWResolution[1] / 72.0f + 0.499f;
+ }
+ else
+ {
+ width = (pdev->MediaSize[0] - pdev->HWMargins[0] - pdev->HWMargins[2]) *
+ pdev->HWResolution[0] / 72.0f + 0.499f;
+ height = (pdev->MediaSize[1] - pdev->HWMargins[1] - pdev->HWMargins[3]) *
+ pdev->HWResolution[1] / 72.0f + 0.499f;
+ }
+
+ /*
+ * Don't reallocate memory unless the device has been opened...
+ */
+
+ if (pdev->is_open)
+ {
+ /*
+ * Device is open, so reallocate...
+ */
+
+ fprintf(stderr, "DEBUG: Reallocating memory, [%.0f %.0f] = %dx%d pixels...\n",
+ pdev->MediaSize[0], pdev->MediaSize[1], width, height);
+
+ sp = ((gx_device_printer *)pdev)->space_params;
+
+ if ((code = gdev_prn_reallocate_memory(pdev, &sp, width, height)) < 0)
+ return (code);
+ }
+ else
+ {
+ /*
+ * Device isn't yet open, so just save the new width and height...
+ */
+
+ fprintf(stderr, "DEBUG: Setting initial media size, [%.0f %.0f] = %dx%d pixels...\n",
+ pdev->MediaSize[0], pdev->MediaSize[1], width, height);
+
+ pdev->width = width;
+ pdev->height = height;
+ }
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: ppd = %p\n", cupsPPD);
+ fprintf(stderr, "DEBUG2: PageSize = [ %.3f %.3f ]\n",
+ pdev->MediaSize[0], pdev->MediaSize[1]);
+ fprintf(stderr, "DEBUG2: margins = [ %.3f %.3f %.3f %.3f ]\n",
+ margins[0], margins[1], margins[2], margins[3]);
+ fprintf(stderr, "DEBUG2: HWResolution = [ %.3f %.3f ]\n",
+ pdev->HWResolution[0], pdev->HWResolution[1]);
+ fprintf(stderr, "DEBUG2: width = %d, height = %d\n",
+ pdev->width, pdev->height);
+ fprintf(stderr, "DEBUG2: HWMargins = [ %.3f %.3f %.3f %.3f ]\n",
+ pdev->HWMargins[0], pdev->HWMargins[1],
+ pdev->HWMargins[2], pdev->HWMargins[3]);
+#endif /* DEBUG */
+
+ return (0);
+}
+
+
+/*
+ * 'cups_set_color_info()' - Set the color information structure based on
+ * the required output.
+ */
+
+private void
+cups_set_color_info(gx_device *pdev) /* I - Device info */
+{
+ int i, j, k; /* Looping vars */
+ int max_lut; /* Maximum LUT value */
+ float d, g; /* Density and gamma correction */
+ float m[3][3]; /* Color correction matrix */
+ char resolution[41]; /* Resolution string */
+ ppd_profile_t *profile; /* Color profile information */
+
+
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG2: cups_set_color_info(%p)\n", pdev);
+#endif /* DEBUG */
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ case CUPS_CSPACE_W :
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
+ cups->color_info.depth = cups->header.cupsBitsPerPixel;
+ cups->color_info.num_components = 1;
+ break;
+
+ case CUPS_CSPACE_CMY :
+ case CUPS_CSPACE_YMC :
+ case CUPS_CSPACE_RGB :
+ if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
+ cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
+ else if (cups->header.cupsBitsPerColor < 8)
+ cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
+ else
+ cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor;
+
+ if (cups->header.cupsBitsPerColor < 8)
+ cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
+ else
+ cups->color_info.depth = 3 * cups->header.cupsBitsPerColor;
+
+ cups->color_info.num_components = 3;
+ break;
+
+ case CUPS_CSPACE_KCMYcm :
+ if (cups->header.cupsBitsPerColor == 1)
+ {
+ cups->header.cupsBitsPerPixel = 8;
+ cups->color_info.depth = 8;
+ cups->color_info.num_components = 4;
+ break;
+ }
+
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
+ cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
+ else
+ cups->header.cupsBitsPerPixel = 4 * cups->header.cupsBitsPerColor;
+
+ cups->color_info.depth = 4 * cups->header.cupsBitsPerColor;
+ cups->color_info.num_components = 4;
+ break;
+
+#ifdef CUPS_RASTER_HAVE_COLORIMETRIC
+ case CUPS_CSPACE_CIEXYZ :
+ case CUPS_CSPACE_CIELab :
+ case CUPS_CSPACE_ICC1 :
+ case CUPS_CSPACE_ICC2 :
+ case CUPS_CSPACE_ICC3 :
+ case CUPS_CSPACE_ICC4 :
+ case CUPS_CSPACE_ICC5 :
+ case CUPS_CSPACE_ICC6 :
+ case CUPS_CSPACE_ICC7 :
+ case CUPS_CSPACE_ICC8 :
+ case CUPS_CSPACE_ICC9 :
+ case CUPS_CSPACE_ICCA :
+ case CUPS_CSPACE_ICCB :
+ case CUPS_CSPACE_ICCC :
+ case CUPS_CSPACE_ICCD :
+ case CUPS_CSPACE_ICCE :
+ case CUPS_CSPACE_ICCF :
+ /*
+ * Colorimetric color spaces currently are implemented as 24-bit
+ * mapping to XYZ or Lab, which are then converted as needed to
+ * the final representation...
+ *
+ * This code enforces a minimum output depth of 8 bits per
+ * component...
+ */
+
+ if (cups->header.cupsBitsPerColor < 8)
+ cups->header.cupsBitsPerColor = 8;
+
+ if (cups->header.cupsColorOrder != CUPS_ORDER_CHUNKED)
+ cups->header.cupsBitsPerPixel = cups->header.cupsBitsPerColor;
+ else
+ cups->header.cupsBitsPerPixel = 3 * cups->header.cupsBitsPerColor;
+
+ cups->color_info.depth = 24;
+ cups->color_info.num_components = 3;
+ break;
+#endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
+ }
+
+#ifdef dev_t_proc_encode_color
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ cups->color_info.gray_index = GX_CINFO_COMP_NO_INDEX;
+ break;
+
+ case CUPS_CSPACE_W :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ case CUPS_CSPACE_KCMYcm :
+ case CUPS_CSPACE_KCMY :
+ cups->color_info.gray_index = 0;
+ break;
+
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ cups->color_info.gray_index = 3;
+ break;
+ }
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ case CUPS_CSPACE_W :
+ case CUPS_CSPACE_WHITE :
+ case CUPS_CSPACE_RGB :
+# ifdef CUPS_RASTER_HAVE_COLORIMETRIC
+ case CUPS_CSPACE_CIEXYZ :
+ case CUPS_CSPACE_CIELab :
+ case CUPS_CSPACE_ICC1 :
+ case CUPS_CSPACE_ICC2 :
+ case CUPS_CSPACE_ICC3 :
+ case CUPS_CSPACE_ICC4 :
+ case CUPS_CSPACE_ICC5 :
+ case CUPS_CSPACE_ICC6 :
+ case CUPS_CSPACE_ICC7 :
+ case CUPS_CSPACE_ICC8 :
+ case CUPS_CSPACE_ICC9 :
+ case CUPS_CSPACE_ICCA :
+ case CUPS_CSPACE_ICCB :
+ case CUPS_CSPACE_ICCC :
+ case CUPS_CSPACE_ICCD :
+ case CUPS_CSPACE_ICCE :
+ case CUPS_CSPACE_ICCF :
+# endif /* CUPS_RASTER_HAVE_COLORIMETRIC */
+ cups->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
+ break;
+
+ case CUPS_CSPACE_K :
+ case CUPS_CSPACE_GOLD :
+ case CUPS_CSPACE_SILVER :
+ case CUPS_CSPACE_CMY :
+ case CUPS_CSPACE_YMC :
+ case CUPS_CSPACE_KCMYcm :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ cups->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
+ break;
+ }
+
+ cups->color_info.separable_and_linear = GX_CINFO_SEP_LIN_NONE;
+#endif /* dev_t_proc_encode_color */
+
+ if ((i = cups->header.cupsBitsPerColor) > 8)
+ i = 8;
+
+ max_lut = (1 << i) - 1;
+
+ switch (cups->color_info.num_components)
+ {
+ default :
+ case 1 :
+ cups->color_info.max_gray = max_lut;
+ cups->color_info.max_color = 0;
+ cups->color_info.dither_grays = max_lut + 1;
+ cups->color_info.dither_colors = 0;
+ break;
+
+ case 3 :
+ cups->color_info.max_gray = 0;
+ cups->color_info.max_color = max_lut;
+ cups->color_info.dither_grays = 0;
+ cups->color_info.dither_colors = max_lut + 1;
+ break;
+
+ case 4 :
+ cups->color_info.max_gray = max_lut;
+ cups->color_info.max_color = max_lut;
+ cups->color_info.dither_grays = max_lut + 1;
+ cups->color_info.dither_colors = max_lut + 1;
+ break;
+ }
+
+ /*
+ * Enable/disable CMYK color support...
+ */
+
+#ifdef dev_t_proc_encode_color
+ cups->color_info.max_components = cups->color_info.num_components;
+#endif /* dev_t_proc_encode_color */
+
+ /*
+ * Tell Ghostscript to forget any colors it has cached...
+ */
+
+ gx_device_decache_colors(pdev);
+
+ /*
+ * Compute the lookup tables...
+ */
+
+ for (i = 0; i <= gx_max_color_value; i ++)
+ {
+ cupsEncodeLUT[i] = (max_lut * i + gx_max_color_value / 2) /
+ gx_max_color_value;
+
+#ifdef DEBUG
+ if (i == 0 || cupsEncodeLUT[i] != cupsEncodeLUT[i - 1])
+ fprintf(stderr, "DEBUG2: cupsEncodeLUT[%d] = %d\n", i, cupsEncodeLUT[i]);
+#endif /* DEBUG */
+ }
+
+ for (i = 0; i < cups->color_info.dither_grays; i ++)
+ cupsDecodeLUT[i] = gx_max_color_value * i / max_lut;
+
+ fprintf(stderr, "DEBUG: num_components = %d, depth = %d\n",
+ cups->color_info.num_components, cups->color_info.depth);
+ fprintf(stderr, "DEBUG: cupsColorSpace = %d, cupsColorOrder = %d\n",
+ cups->header.cupsColorSpace, cups->header.cupsColorOrder);
+ fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d, cupsBitsPerColor = %d\n",
+ cups->header.cupsBitsPerPixel, cups->header.cupsBitsPerColor);
+ fprintf(stderr, "DEBUG: max_gray = %d, dither_grays = %d\n",
+ cups->color_info.max_gray, cups->color_info.dither_grays);
+ fprintf(stderr, "DEBUG: max_color = %d, dither_colors = %d\n",
+ cups->color_info.max_color, cups->color_info.dither_colors);
+
+ /*
+ * Set the color profile as needed...
+ */
+
+ cupsHaveProfile = 0;
+
+#ifdef dev_t_proc_encode_color
+ if (cupsProfile)
+#else
+ if (cupsProfile && cups->header.cupsBitsPerColor == 8)
+#endif /* dev_t_proc_encode_color */
+ {
+ fprintf(stderr, "DEBUG: Using user-defined profile \"%s\"...\n", cupsProfile);
+
+ if (sscanf(cupsProfile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f", &d, &g,
+ m[0] + 0, m[0] + 1, m[0] + 2,
+ m[1] + 0, m[1] + 1, m[1] + 2,
+ m[2] + 0, m[2] + 1, m[2] + 2) != 11)
+ fputs("DEBUG: User-defined profile does not contain 11 integers!\n", stderr);
+ else
+ {
+ cupsHaveProfile = 1;
+
+ d *= 0.001f;
+ g *= 0.001f;
+ m[0][0] *= 0.001f;
+ m[0][1] *= 0.001f;
+ m[0][2] *= 0.001f;
+ m[1][0] *= 0.001f;
+ m[1][1] *= 0.001f;
+ m[1][2] *= 0.001f;
+ m[2][0] *= 0.001f;
+ m[2][1] *= 0.001f;
+ m[2][2] *= 0.001f;
+ }
+ }
+#ifdef dev_t_proc_encode_color
+ else if (cupsPPD)
+#else
+ else if (cupsPPD && cups->header.cupsBitsPerColor == 8)
+#endif /* dev_t_proc_encode_color */
+ {
+ /*
+ * Find the appropriate color profile...
+ */
+
+ if (pdev->HWResolution[0] != pdev->HWResolution[1])
+ sprintf(resolution, "%.0fx%.0fdpi", pdev->HWResolution[0],
+ pdev->HWResolution[1]);
+ else
+ sprintf(resolution, "%.0fdpi", pdev->HWResolution[0]);
+
+ for (i = 0, profile = cupsPPD->profiles;
+ i < cupsPPD->num_profiles;
+ i ++, profile ++)
+ if ((strcmp(profile->resolution, resolution) == 0 ||
+ profile->resolution[0] == '-') &&
+ (strcmp(profile->media_type, cups->header.MediaType) == 0 ||
+ profile->media_type[0] == '-'))
+ break;
+
+ /*
+ * If we found a color profile, use it!
+ */
+
+ if (i < cupsPPD->num_profiles)
+ {
+ fputs("DEBUG: Using color profile in PPD file!\n", stderr);
+
+ cupsHaveProfile = 1;
+
+ d = profile->density;
+ g = profile->gamma;
+
+ memcpy(m, profile->matrix, sizeof(m));
+ }
+ }
+
+ if (cupsHaveProfile)
+ {
+ for (i = 0; i < 3; i ++)
+ for (j = 0; j < 3; j ++)
+ for (k = 0; k <= CUPS_MAX_VALUE; k ++)
+ {
+ cupsMatrix[i][j][k] = (int)((float)k * m[i][j] + 0.5);
+
+#ifdef DEBUG
+ if ((k & 4095) == 0)
+ fprintf(stderr, "DEBUG2: cupsMatrix[%d][%d][%d] = %d\n",
+ i, j, k, cupsMatrix[i][j][k]);
+#endif /* DEBUG */
+ }
+
+
+ for (k = 0; k <= CUPS_MAX_VALUE; k ++)
+ {
+ cupsDensity[k] = (int)((float)CUPS_MAX_VALUE * d *
+ pow((float)k / (float)CUPS_MAX_VALUE, g) +
+ 0.5);
+
+#ifdef DEBUG
+ if ((k & 4095) == 0)
+ fprintf(stderr, "DEBUG2: cupsDensity[%d] = %d\n", k, cupsDensity[k]);
+#endif /* DEBUG */
+ }
+ }
+ else
+ {
+ for (k = 0; k <= CUPS_MAX_VALUE; k ++)
+ cupsDensity[k] = k;
+ }
+}
+
+
+/*
+ * 'cups_sync_output()' - Keep the user informed of our status...
+ */
+
+private int /* O - Error status */
+cups_sync_output(gx_device *pdev) /* I - Device info */
+{
+ fprintf(stderr, "INFO: Processing page %d...\n", cups->page);
+
+ return (0);
+}
+
+
+/*
+ * 'cups_print_chunked()' - Print a page of chunked pixels.
+ */
+
+static void
+cups_print_chunked(gx_device_printer *pdev,
+ /* I - Printer device */
+ unsigned char *src,
+ /* I - Scanline buffer */
+ unsigned char *dst,
+ /* I - Bitmap buffer */
+ int srcbytes)
+ /* I - Number of bytes in src */
+{
+ int y; /* Looping var */
+ unsigned char *srcptr, /* Pointer to data */
+ *dstptr; /* Pointer to bits */
+ int count; /* Count for loop */
+ int flip; /* Flip scanline? */
+
+
+ if (cups->header.Duplex && !cups->header.Tumble &&
+ cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
+ flip = 1;
+ else
+ flip = 0;
+
+ fprintf(stderr, "DEBUG: cups_print_chunked - flip = %d, height = %d\n",
+ flip, cups->height);
+
+ /*
+ * Loop through the page bitmap and write chunked pixels, reversing as
+ * needed...
+ */
+
+ for (y = 0; y < cups->height; y ++)
+ {
+ /*
+ * Grab the scanline data...
+ */
+
+ if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
+ {
+ fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
+ gs_exit(1);
+ }
+
+ if (flip)
+ {
+ /*
+ * Flip the raster data before writing it...
+ */
+
+ if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+ else
+ {
+ dstptr = dst;
+ count = srcbytes;
+
+ switch (cups->color_info.depth)
+ {
+ case 1 : /* B&W bitmap */
+ for (srcptr += srcbytes - 1;
+ count > 0;
+ count --, srcptr --, dstptr ++)
+ {
+ *dstptr = cupsRevUpper1[*srcptr & 15] |
+ cupsRevLower1[*srcptr >> 4];
+ }
+ break;
+
+ case 2 : /* 2-bit grayscale */
+ for (srcptr += srcbytes - 1;
+ count > 0;
+ count --, srcptr --, dstptr ++)
+ {
+ *dstptr = cupsRevUpper2[*srcptr & 15] |
+ cupsRevLower2[*srcptr >> 4];
+ }
+ break;
+
+ case 4 : /* 4-bit grayscale, or RGB, CMY, or CMYK bitmap */
+ for (srcptr += srcbytes - 1;
+ count > 0;
+ count --, srcptr --, dstptr ++)
+ *dstptr = (*srcptr >> 4) | (*srcptr << 4);
+ break;
+
+ case 8 : /* 8-bit grayscale, or 2-bit RGB, CMY, or CMYK image */
+ for (srcptr += srcbytes - 1;
+ count > 0;
+ count --, srcptr --, dstptr ++)
+ *dstptr = *srcptr;
+ break;
+
+ case 16 : /* 4-bit RGB, CMY or CMYK image */
+ for (srcptr += srcbytes - 2;
+ count > 0;
+ count -= 2, srcptr -= 2, dstptr += 2)
+ {
+ dstptr[0] = srcptr[0];
+ dstptr[1] = srcptr[1];
+ }
+ break;
+
+ case 24 : /* 8-bit RGB or CMY image */
+ for (srcptr += srcbytes - 3;
+ count > 0;
+ count -= 3, srcptr -= 3, dstptr += 3)
+ {
+ dstptr[0] = srcptr[0];
+ dstptr[1] = srcptr[1];
+ dstptr[2] = srcptr[2];
+ }
+ break;
+
+ case 32 : /* 4-bit RGB, CMY or CMYK bitmap */
+ for (srcptr += srcbytes - 4;
+ count > 0;
+ count -= 4, srcptr -= 4, dstptr += 4)
+ {
+ dstptr[0] = srcptr[0];
+ dstptr[1] = srcptr[1];
+ dstptr[2] = srcptr[2];
+ dstptr[3] = srcptr[3];
+ }
+ break;
+ }
+ }
+
+ /*
+ * Write the bitmap data to the raster stream...
+ */
+
+ cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
+ }
+ else
+ {
+ /*
+ * Write the scanline data to the raster stream...
+ */
+
+ cupsRasterWritePixels(cups->stream, srcptr, cups->header.cupsBytesPerLine);
+ }
+ }
+}
+
+
+/*
+ * 'cups_print_banded()' - Print a page of banded pixels.
+ */
+
+static void
+cups_print_banded(gx_device_printer *pdev,
+ /* I - Printer device */
+ unsigned char *src,
+ /* I - Scanline buffer */
+ unsigned char *dst,
+ /* I - Bitmap buffer */
+ int srcbytes)
+ /* I - Number of bytes in src */
+{
+ int x; /* Looping var */
+ int y; /* Looping var */
+ int bandbytes; /* Bytes per band */
+ unsigned char bit; /* Current bit */
+ unsigned char temp; /* Temporary variable */
+ unsigned char *srcptr; /* Pointer to data */
+ unsigned char *cptr, *mptr, *yptr, /* Pointer to components */
+ *kptr, *lcptr, *lmptr; /* ... */
+ int flip; /* Flip scanline? */
+
+
+ if (cups->header.Duplex && !cups->header.Tumble &&
+ cupsPPD && cupsPPD->flip_duplex && !(cups->page & 1))
+ flip = 1;
+ else
+ flip = 0;
+
+ fprintf(stderr, "DEBUG: cups_print_banded - flip = %d, height = %d\n",
+ flip, cups->height);
+
+ /*
+ * Loop through the page bitmap and write banded pixels... We have
+ * to separate each chunked color as needed...
+ */
+
+ bandbytes = (cups->header.cupsWidth * cups->header.cupsBitsPerColor + 7) / 8;
+
+ for (y = 0; y < cups->height; y ++)
+ {
+ /*
+ * Grab the scanline data...
+ */
+
+ if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
+ {
+ fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
+ gs_exit(1);
+ }
+
+ /*
+ * Separate the chunked colors into their components...
+ */
+
+ if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+ else
+ {
+ if (flip)
+ cptr = dst + bandbytes - 1;
+ else
+ cptr = dst;
+
+ mptr = cptr + bandbytes;
+ yptr = mptr + bandbytes;
+ kptr = yptr + bandbytes;
+ lcptr = yptr + bandbytes;
+ lmptr = lcptr + bandbytes;
+
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
+ x > 0;
+ x --, srcptr ++)
+ {
+ if (*srcptr & 0x40)
+ *cptr |= bit;
+ if (*srcptr & 0x20)
+ *mptr |= bit;
+ if (*srcptr & 0x10)
+ *yptr |= bit;
+
+ if (flip)
+ {
+ if (bit < 128)
+ bit <<= 1;
+ else
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ bit = 1;
+ }
+ }
+ else
+ bit >>= 1;
+
+ x --;
+ if (x == 0)
+ break;
+
+ if (*srcptr & 0x4)
+ *cptr |= bit;
+ if (*srcptr & 0x2)
+ *mptr |= bit;
+ if (*srcptr & 0x1)
+ *yptr |= bit;
+
+ if (flip)
+ {
+ if (bit < 128)
+ bit <<= 1;
+ else
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ bit = 1;
+ }
+ }
+ else if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ bit = 128;
+ }
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
+ x > 0;
+ x --, srcptr ++)
+ {
+ if (*srcptr & 0x80)
+ *cptr |= bit;
+ if (*srcptr & 0x40)
+ *mptr |= bit;
+ if (*srcptr & 0x20)
+ *yptr |= bit;
+ if (*srcptr & 0x10)
+ *kptr |= bit;
+
+ if (flip)
+ {
+ if (bit < 128)
+ bit <<= 1;
+ else
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ kptr --;
+ bit = 1;
+ }
+ }
+ else
+ bit >>= 1;
+
+ x --;
+ if (x == 0)
+ break;
+
+ if (*srcptr & 0x8)
+ *cptr |= bit;
+ if (*srcptr & 0x4)
+ *mptr |= bit;
+ if (*srcptr & 0x2)
+ *yptr |= bit;
+ if (*srcptr & 0x1)
+ *kptr |= bit;
+
+ if (flip)
+ {
+ if (bit < 128)
+ bit <<= 1;
+ else
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ kptr --;
+ bit = 1;
+ }
+ }
+ else if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ bit = 128;
+ }
+ }
+ break;
+ case CUPS_CSPACE_KCMYcm :
+ for (x = cups->width, bit = flip ? 1 << (x & 7) : 128;
+ x > 0;
+ x --, srcptr ++)
+ {
+ /*
+ * Note: Because of the way the pointers are setup,
+ * the following code is correct even though
+ * the names don't match...
+ */
+
+ if (*srcptr & 0x20)
+ *cptr |= bit;
+ if (*srcptr & 0x10)
+ *mptr |= bit;
+ if (*srcptr & 0x08)
+ *yptr |= bit;
+ if (*srcptr & 0x04)
+ *kptr |= bit;
+ if (*srcptr & 0x02)
+ *lcptr |= bit;
+ if (*srcptr & 0x01)
+ *lmptr |= bit;
+
+ if (flip)
+ {
+ if (bit < 128)
+ bit <<= 1;
+ else
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ kptr --;
+ lcptr --;
+ lmptr --;
+ bit = 1;
+ }
+ }
+ else if (bit > 1)
+ bit >>= 1;
+ else
+ {
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ lcptr ++;
+ lmptr ++;
+ bit = 128;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 2 :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0;
+ x > 0;
+ x --, srcptr ++)
+ switch (bit)
+ {
+ case 0xc0 :
+ if ((temp = *srcptr & 0x30) != 0)
+ *cptr |= temp << 2;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *mptr |= temp << 4;
+ if ((temp = *srcptr & 0x03) != 0)
+ *yptr |= temp << 6;
+
+ if (flip)
+ {
+ bit = 0x03;
+ cptr --;
+ mptr --;
+ yptr --;
+ }
+ else
+ bit = 0x30;
+ break;
+ case 0x30 :
+ if ((temp = *srcptr & 0x30) != 0)
+ *cptr |= temp;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *mptr |= temp << 2;
+ if ((temp = *srcptr & 0x03) != 0)
+ *yptr |= temp << 4;
+
+ if (flip)
+ bit = 0xc0;
+ else
+ bit = 0x0c;
+ break;
+ case 0x0c :
+ if ((temp = *srcptr & 0x30) != 0)
+ *cptr |= temp >> 2;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *mptr |= temp;
+ if ((temp = *srcptr & 0x03) != 0)
+ *yptr |= temp << 2;
+
+ if (flip)
+ bit = 0x30;
+ else
+ bit = 0x03;
+ break;
+ case 0x03 :
+ if ((temp = *srcptr & 0x30) != 0)
+ *cptr |= temp >> 4;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *mptr |= temp >> 2;
+ if ((temp = *srcptr & 0x03) != 0)
+ *yptr |= temp;
+
+ if (flip)
+ bit = 0x0c;
+ else
+ {
+ bit = 0xc0;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ break;
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ for (x = cups->width, bit = flip ? 3 << (2 * (x & 3)) : 0xc0;
+ x > 0;
+ x --, srcptr ++)
+ switch (bit)
+ {
+ case 0xc0 :
+ if ((temp = *srcptr & 0xc0) != 0)
+ *cptr |= temp;
+ if ((temp = *srcptr & 0x30) != 0)
+ *mptr |= temp << 2;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *yptr |= temp << 4;
+ if ((temp = *srcptr & 0x03) != 0)
+ *kptr |= temp << 6;
+
+ if (flip)
+ {
+ bit = 0x03;
+ cptr --;
+ mptr --;
+ yptr --;
+ kptr --;
+ }
+ else
+ bit = 0x30;
+ break;
+ case 0x30 :
+ if ((temp = *srcptr & 0xc0) != 0)
+ *cptr |= temp >> 2;
+ if ((temp = *srcptr & 0x30) != 0)
+ *mptr |= temp;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *yptr |= temp << 2;
+ if ((temp = *srcptr & 0x03) != 0)
+ *kptr |= temp << 4;
+
+ if (flip)
+ bit = 0xc0;
+ else
+ bit = 0x0c;
+ break;
+ case 0x0c :
+ if ((temp = *srcptr & 0xc0) != 0)
+ *cptr |= temp >> 4;
+ if ((temp = *srcptr & 0x30) != 0)
+ *mptr |= temp >> 2;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *yptr |= temp;
+ if ((temp = *srcptr & 0x03) != 0)
+ *kptr |= temp << 2;
+
+ if (flip)
+ bit = 0x30;
+ else
+ bit = 0x03;
+ break;
+ case 0x03 :
+ if ((temp = *srcptr & 0xc0) != 0)
+ *cptr |= temp >> 6;
+ if ((temp = *srcptr & 0x30) != 0)
+ *mptr |= temp >> 4;
+ if ((temp = *srcptr & 0x0c) != 0)
+ *yptr |= temp >> 2;
+ if ((temp = *srcptr & 0x03) != 0)
+ *kptr |= temp;
+
+ if (flip)
+ bit = 0x0c;
+ else
+ {
+ bit = 0xc0;
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 4 :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f;
+ x > 0;
+ x --, srcptr += 2)
+ switch (bit)
+ {
+ case 0xf0 :
+ if ((temp = srcptr[0] & 0x0f) != 0)
+ *cptr |= temp << 4;
+ if ((temp = srcptr[1] & 0xf0) != 0)
+ *mptr |= temp;
+ if ((temp = srcptr[1] & 0x0f) != 0)
+ *yptr |= temp << 4;
+
+ bit = 0x0f;
+
+ if (flip)
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ }
+ break;
+ case 0x0f :
+ if ((temp = srcptr[0] & 0x0f) != 0)
+ *cptr |= temp;
+ if ((temp = srcptr[1] & 0xf0) != 0)
+ *mptr |= temp >> 4;
+ if ((temp = srcptr[1] & 0x0f) != 0)
+ *yptr |= temp;
+
+ bit = 0xf0;
+
+ if (!flip)
+ {
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ }
+ break;
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ for (x = cups->width, bit = flip && (x & 1) ? 0xf0 : 0x0f;
+ x > 0;
+ x --, srcptr += 2)
+ switch (bit)
+ {
+ case 0xf0 :
+ if ((temp = srcptr[0] & 0xf0) != 0)
+ *cptr |= temp;
+ if ((temp = srcptr[0] & 0x0f) != 0)
+ *mptr |= temp << 4;
+ if ((temp = srcptr[1] & 0xf0) != 0)
+ *yptr |= temp;
+ if ((temp = srcptr[1] & 0x0f) != 0)
+ *kptr |= temp << 4;
+
+ bit = 0x0f;
+
+ if (flip)
+ {
+ cptr --;
+ mptr --;
+ yptr --;
+ kptr --;
+ }
+ break;
+ case 0x0f :
+ if ((temp = srcptr[0] & 0xf0) != 0)
+ *cptr |= temp >> 4;
+ if ((temp = srcptr[0] & 0x0f) != 0)
+ *mptr |= temp;
+ if ((temp = srcptr[1] & 0xf0) != 0)
+ *yptr |= temp >> 4;
+ if ((temp = srcptr[1] & 0x0f) != 0)
+ *kptr |= temp;
+
+ bit = 0xf0;
+
+ if (!flip)
+ {
+ cptr ++;
+ mptr ++;
+ yptr ++;
+ kptr ++;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 8 :
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ if (flip)
+ for (x = cups->width; x > 0; x --)
+ {
+ *cptr-- = *srcptr++;
+ *mptr-- = *srcptr++;
+ *yptr-- = *srcptr++;
+ }
+ else
+ for (x = cups->width; x > 0; x --)
+ {
+ *cptr++ = *srcptr++;
+ *mptr++ = *srcptr++;
+ *yptr++ = *srcptr++;
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ if (flip)
+ for (x = cups->width; x > 0; x --)
+ {
+ *cptr-- = *srcptr++;
+ *mptr-- = *srcptr++;
+ *yptr-- = *srcptr++;
+ *kptr-- = *srcptr++;
+ }
+ else
+ for (x = cups->width; x > 0; x --)
+ {
+ *cptr++ = *srcptr++;
+ *mptr++ = *srcptr++;
+ *yptr++ = *srcptr++;
+ *kptr++ = *srcptr++;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Write the bitmap data to the raster stream...
+ */
+
+ cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
+ }
+}
+
+
+/*
+ * 'cups_print_planar()' - Print a page of planar pixels.
+ */
+
+static void
+cups_print_planar(gx_device_printer *pdev,
+ /* I - Printer device */
+ unsigned char *src,
+ /* I - Scanline buffer */
+ unsigned char *dst,
+ /* I - Bitmap buffer */
+ int srcbytes)
+ /* I - Number of bytes in src */
+{
+ int x; /* Looping var */
+ int y; /* Looping var */
+ int z; /* Looping var */
+ unsigned char srcbit; /* Current source bit */
+ unsigned char dstbit; /* Current destination bit */
+ unsigned char temp; /* Temporary variable */
+ unsigned char *srcptr; /* Pointer to data */
+ unsigned char *dstptr; /* Pointer to bitmap */
+
+
+ /**** NOTE: Currently planar output doesn't support flipped duplex!!! ****/
+
+ /*
+ * Loop through the page bitmap and write planar pixels... We have
+ * to separate each chunked color as needed...
+ */
+
+ for (z = 0; z < pdev->color_info.num_components; z ++)
+ for (y = 0; y < cups->height; y ++)
+ {
+ /*
+ * Grab the scanline data...
+ */
+
+ if (gdev_prn_get_bits((gx_device_printer *)pdev, y, src, &srcptr) < 0)
+ {
+ fprintf(stderr, "ERROR: Unable to get scanline %d!\n", y);
+ gs_exit(1);
+ }
+
+ /*
+ * Pull the individual color planes out of the pixels...
+ */
+
+ if (srcptr[0] == 0 && memcmp(srcptr, srcptr + 1, srcbytes - 1) == 0)
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+ else
+ switch (cups->header.cupsBitsPerColor)
+ {
+ default :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ for (dstptr = dst, x = cups->width, srcbit = 64 >> z,
+ dstbit = 128;
+ x > 0;
+ x --)
+ {
+ if (*srcptr & srcbit)
+ *dstptr |= dstbit;
+
+ if (srcbit >= 16)
+ srcbit >>= 4;
+ else
+ {
+ srcbit = 64 >> z;
+ srcptr ++;
+ }
+
+ if (dstbit > 1)
+ dstbit >>= 1;
+ else
+ {
+ dstbit = 128;
+ dstptr ++;
+ }
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ for (dstptr = dst, x = cups->width, srcbit = 128 >> z,
+ dstbit = 128;
+ x > 0;
+ x --)
+ {
+ if (*srcptr & srcbit)
+ *dstptr |= dstbit;
+
+ if (srcbit >= 16)
+ srcbit >>= 4;
+ else
+ {
+ srcbit = 128 >> z;
+ srcptr ++;
+ }
+
+ if (dstbit > 1)
+ dstbit >>= 1;
+ else
+ {
+ dstbit = 128;
+ dstptr ++;
+ }
+ }
+ break;
+ case CUPS_CSPACE_KCMYcm :
+ for (dstptr = dst, x = cups->width, srcbit = 32 >> z,
+ dstbit = 128;
+ x > 0;
+ x --, srcptr ++)
+ {
+ if (*srcptr & srcbit)
+ *dstptr |= dstbit;
+
+ if (dstbit > 1)
+ dstbit >>= 1;
+ else
+ {
+ dstbit = 128;
+ dstptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 2 :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ for (dstptr = dst, x = cups->width, srcbit = 48 >> (z * 2),
+ dstbit = 0xc0;
+ x > 0;
+ x --, srcptr ++)
+ {
+ if ((temp = *srcptr & srcbit) != 0)
+ {
+ if (srcbit == dstbit)
+ *dstptr |= temp;
+ else
+ {
+ switch (srcbit)
+ {
+ case 0x30 :
+ temp >>= 4;
+ break;
+ case 0x0c :
+ temp >>= 2;
+ break;
+ }
+
+ switch (dstbit)
+ {
+ case 0xc0 :
+ *dstptr |= temp << 6;
+ break;
+ case 0x30 :
+ *dstptr |= temp << 4;
+ break;
+ case 0x0c :
+ *dstptr |= temp << 2;
+ break;
+ case 0x03 :
+ *dstptr |= temp;
+ break;
+ }
+ }
+ }
+
+ if (dstbit > 0x03)
+ dstbit >>= 2;
+ else
+ {
+ dstbit = 0xc0;
+ dstptr ++;
+ }
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ for (dstptr = dst, x = cups->width, srcbit = 192 >> (z * 2),
+ dstbit = 0xc0;
+ x > 0;
+ x --, srcptr ++)
+ {
+ if ((temp = *srcptr & srcbit) != 0)
+ {
+ if (srcbit == dstbit)
+ *dstptr |= temp;
+ else
+ {
+ switch (srcbit)
+ {
+ case 0xc0 :
+ temp >>= 6;
+ break;
+ case 0x30 :
+ temp >>= 4;
+ break;
+ case 0x0c :
+ temp >>= 2;
+ break;
+ }
+
+ switch (dstbit)
+ {
+ case 0xc0 :
+ *dstptr |= temp << 6;
+ break;
+ case 0x30 :
+ *dstptr |= temp << 4;
+ break;
+ case 0x0c :
+ *dstptr |= temp << 2;
+ break;
+ case 0x03 :
+ *dstptr |= temp;
+ break;
+ }
+ }
+ }
+
+ if (dstbit > 0x03)
+ dstbit >>= 2;
+ else
+ {
+ dstbit = 0xc0;
+ dstptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 4 :
+ memset(dst, 0, cups->header.cupsBytesPerLine);
+
+ switch (cups->header.cupsColorSpace)
+ {
+ default :
+ if (z > 0)
+ srcptr ++;
+
+ if (z == 1)
+ srcbit = 0xf0;
+ else
+ srcbit = 0x0f;
+
+ for (dstptr = dst, x = cups->width, dstbit = 0xf0;
+ x > 0;
+ x --, srcptr += 2)
+ {
+ if ((temp = *srcptr & srcbit) != 0)
+ {
+ if (srcbit == dstbit)
+ *dstptr |= temp;
+ else
+ {
+ if (srcbit == 0xf0)
+ temp >>= 4;
+
+ if (dstbit == 0xf0)
+ *dstptr |= temp << 4;
+ else
+ *dstptr |= temp;
+ }
+ }
+
+ if (dstbit == 0xf0)
+ dstbit = 0x0f;
+ else
+ {
+ dstbit = 0xf0;
+ dstptr ++;
+ }
+ }
+ break;
+ case CUPS_CSPACE_GMCK :
+ case CUPS_CSPACE_GMCS :
+ case CUPS_CSPACE_RGBA :
+ case CUPS_CSPACE_CMYK :
+ case CUPS_CSPACE_YMCK :
+ case CUPS_CSPACE_KCMY :
+ case CUPS_CSPACE_KCMYcm :
+ if (z > 1)
+ srcptr ++;
+
+ if (z & 1)
+ srcbit = 0x0f;
+ else
+ srcbit = 0xf0;
+
+ for (dstptr = dst, x = cups->width, dstbit = 0xf0;
+ x > 0;
+ x --, srcptr += 2)
+ {
+ if ((temp = *srcptr & srcbit) != 0)
+ {
+ if (srcbit == dstbit)
+ *dstptr |= temp;
+ else
+ {
+ if (srcbit == 0xf0)
+ temp >>= 4;
+
+ if (dstbit == 0xf0)
+ *dstptr |= temp << 4;
+ else
+ *dstptr |= temp;
+ }
+ }
+
+ if (dstbit == 0xf0)
+ dstbit = 0x0f;
+ else
+ {
+ dstbit = 0xf0;
+ dstptr ++;
+ }
+ }
+ break;
+ }
+ break;
+
+ case 8 :
+ for (srcptr += z, dstptr = dst, x = cups->header.cupsBytesPerLine;
+ x > 0;
+ srcptr += pdev->color_info.num_components, x --)
+ *dstptr++ = *srcptr;
+ break;
+ }
+
+ /*
+ * Write the bitmap data to the raster stream...
+ */
+
+ cupsRasterWritePixels(cups->stream, dst, cups->header.cupsBytesPerLine);
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/pstoraster/gs707-lib.patch b/pstoraster/gs707-lib.patch
new file mode 100644
index 000000000..32b011dd9
--- /dev/null
+++ b/pstoraster/gs707-lib.patch
@@ -0,0 +1,110 @@
+diff -u ghostscript-7.07/lib/gs_init.ps ghostscript-7.07-easysw/lib/gs_init.ps
+--- ghostscript-7.07/lib/gs_init.ps 2003-04-12 10:02:38.000000000 -0400
++++ ghostscript-7.07-easysw/lib/gs_init.ps 2003-11-14 16:38:44.000000000 -0500
+@@ -119,6 +119,7 @@
+ currentdict /NOFONTPATH known /NOFONTPATH exch def
+ currentdict /NOGC known /NOGC exch def
+ currentdict /NOINTERPOLATE .knownget { /INTERPOLATE exch not def } if
++currentdict /NOMEDIAATTRS known /NOMEDIAATTRS exch def
+ currentdict /NOPAGEPROMPT known /NOPAGEPROMPT exch def
+ currentdict /NOPAUSE known /NOPAUSE exch def
+ currentdict /NOPLATFONTS known /NOPLATFONTS exch def
+diff -u ghostscript-7.07/lib/gs_setpd.ps ghostscript-7.07-easysw/lib/gs_setpd.ps
+--- ghostscript-7.07/lib/gs_setpd.ps 2003-04-12 10:02:38.000000000 -0400
++++ ghostscript-7.07-easysw/lib/gs_setpd.ps 2003-11-14 16:38:06.000000000 -0500
+@@ -324,21 +324,42 @@
+ } bind
+ .dicttomark readonly def
+
+-% Define the keys used in input attribute matching.
+-/.inputattrkeys [
+- /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
+- % The following are documented in Adobe's supplement for v2017.
+- /LeadingEdge /MediaClass
+-] readonly def
+-% Define other keys used in media selection.
+-/.inputselectionkeys [
+- /MediaPosition /Orientation
+-] readonly def
+-
+-% Define the keys used in output attribute matching.
+-/.outputattrkeys [
+- /OutputType
+-] readonly def
++% M. Sweet, Easy Software Products:
++%
++% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
++% selection policies for setpagedevice. This is used by CUPS to support
++% the standard Adobe media attributes.
++NOMEDIAATTRS {
++ % Define only PageSize for input attribute matching.
++ /.inputattrkeys [
++ /PageSize
++ ] readonly def
++ % Define no other keys used in media selection.
++ /.inputselectionkeys [
++ /noInputSelectionsKeys
++ ] readonly def
++
++ % Define no keys used in output attribute matching.
++ /.outputattrkeys [
++ /noOutputAttrKeys
++ ] readonly def
++} {
++ % Define the keys used in input attribute matching.
++ /.inputattrkeys [
++ /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
++ % The following are documented in Adobe's supplement for v2017.
++ /LeadingEdge /MediaClass
++ ] readonly def
++ % Define other keys used in media selection.
++ /.inputselectionkeys [
++ /MediaPosition /Orientation
++ ] readonly def
++
++ % Define the keys used in output attribute matching.
++ /.outputattrkeys [
++ /OutputType
++ ] readonly def
++} ifelse
+
+ % Define all the parameters that should always be copied to the merged
+ % dictionary.
+@@ -367,7 +388,13 @@
+ /PageSize false % obsolete alias for .MediaSize
+ /InputAttributes false
+ .inputattrkeys
+- { dup /PageSize eq
++ % M. Sweet, Easy Software Products:
++ %
++ % Treat LeadingEdge like PageSize so that a common Ghostscript driver
++ % doesn't need the NOMEDIAATTRS definition.
++ %
++ % { dup /PageSize eq
++ { dup dup /PageSize eq exch /LeadingEdge eq or
+ { pop }
+ { { 2 index /InputAttributes .knownget { null eq } { true } ifelse } }
+ ifelse
+@@ -442,11 +469,22 @@
+ % They are expected to consume the top 2 operands.
+ % NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize)
+ % the same as 0, i.e., we signal an error.
++%
++% M. Sweet, Easy Software Products:
++%
++% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
++% selection policies for setpagedevice. This is used by CUPS to support
++% the standard Adobe media attributes.
+ 0 { % Set errorinfo and signal a configurationerror.
++ NOMEDIAATTRS {
++ % NOMEDIAATTRS means that the default policy is 7...
++ pop 2 index exch 7 put
++ } {
+ pop dup 4 index exch get 2 array astore
+ $error /errorinfo 3 -1 roll put
+ cleartomark
+ /setpagedevice load /configurationerror signalerror
++ } ifelse
+ } bind
+ 1 { % Roll back the failed request to its previous status.
+ DEBUG { (Rolling back.) = pstack flush } if
diff --git a/pstoraster/gs811-lib.patch b/pstoraster/gs811-lib.patch
new file mode 100644
index 000000000..9cd125305
--- /dev/null
+++ b/pstoraster/gs811-lib.patch
@@ -0,0 +1,110 @@
+diff -u ghostscript-8.11/lib/gs_init.ps ghostscript-8.11-easysw/lib/gs_init.ps
+--- ghostscript-8.11/lib/gs_init.ps 2003-07-30 03:26:55.000000000 -0400
++++ ghostscript-8.11-easysw/lib/gs_init.ps 2003-11-13 13:04:17.000000000 -0500
+@@ -139,6 +139,7 @@
+ currentdict /NOFONTPATH known /NOFONTPATH exch def
+ currentdict /NOGC known /NOGC exch def
+ currentdict /NOINTERPOLATE .knownget { /INTERPOLATE exch not def } if
++currentdict /NOMEDIAATTRS known /NOMEDIAATTRS exch def
+ currentdict /NOOUTERSAVE known /NOOUTERSAVE exch def
+ currentdict /NOPAGEPROMPT known /NOPAGEPROMPT exch def
+ currentdict /NOPAUSE known /NOPAUSE exch def
+diff -u ghostscript-8.11/lib/gs_setpd.ps ghostscript-8.11-easysw/lib/gs_setpd.ps
+--- ghostscript-8.11/lib/gs_setpd.ps 2003-04-12 14:08:18.000000000 -0400
++++ ghostscript-8.11-easysw/lib/gs_setpd.ps 2003-11-14 16:32:55.000000000 -0500
+@@ -344,21 +344,42 @@
+ } bind
+ .dicttomark readonly def
+
+-% Define the keys used in input attribute matching.
+-/.inputattrkeys [
+- /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
+- % The following are documented in Adobe's supplement for v2017.
+- /LeadingEdge /MediaClass
+-] readonly def
+-% Define other keys used in media selection.
+-/.inputselectionkeys [
+- /MediaPosition /Orientation
+-] readonly def
+-
+-% Define the keys used in output attribute matching.
+-/.outputattrkeys [
+- /OutputType
+-] readonly def
++% M. Sweet, Easy Software Products:
++%
++% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
++% selection policies for setpagedevice. This is used by CUPS to support
++% the standard Adobe media attributes.
++NOMEDIAATTRS {
++ % Define only PageSize for input attribute matching.
++ /.inputattrkeys [
++ /PageSize
++ ] readonly def
++ % Define no other keys used in media selection.
++ /.inputselectionkeys [
++ /noInputSelectionsKeys
++ ] readonly def
++
++ % Define no keys used in output attribute matching.
++ /.outputattrkeys [
++ /noOutputAttrKeys
++ ] readonly def
++} {
++ % Define the keys used in input attribute matching.
++ /.inputattrkeys [
++ /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
++ % The following are documented in Adobe's supplement for v2017.
++ /LeadingEdge /MediaClass
++ ] readonly def
++ % Define other keys used in media selection.
++ /.inputselectionkeys [
++ /MediaPosition /Orientation
++ ] readonly def
++
++ % Define the keys used in output attribute matching.
++ /.outputattrkeys [
++ /OutputType
++ ] readonly def
++} ifelse
+
+ % Define all the parameters that should always be copied to the merged
+ % dictionary.
+@@ -387,7 +408,13 @@
+ /PageSize //false % obsolete alias for .MediaSize
+ /InputAttributes //false
+ .inputattrkeys
+- { dup /PageSize eq
++ % M. Sweet, Easy Software Products:
++ %
++ % Treat LeadingEdge like PageSize so that a common Ghostscript driver
++ % doesn't need the NOMEDIAATTRS definition.
++ %
++ % { dup /PageSize eq
++ { dup dup /PageSize eq exch /LeadingEdge eq or
+ { pop }
+ { { 2 index /InputAttributes .knownget { //null eq } { //true } ifelse } }
+ ifelse
+@@ -468,11 +495,22 @@
+ % They are expected to consume the top 2 operands.
+ % NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize)
+ % the same as 0, i.e., we signal an error.
++%
++% M. Sweet, Easy Software Products:
++%
++% Define NOMEDIAATTRS to turn off the default (but unimplementable) media
++% selection policies for setpagedevice. This is used by CUPS to support
++% the standard Adobe media attributes.
+ 0 { % Set errorinfo and signal a configurationerror.
++ NOMEDIAATTRS {
++ % NOMEDIAATTRS means that the default policy is 7...
++ pop 2 index exch 7 put
++ } {
+ pop dup 4 index exch get 2 array astore
+ $error /errorinfo 3 -1 roll put
+ cleartomark
+ /setpagedevice load /configurationerror signalerror
++ } ifelse
+ } bind
+ 1 { % Roll back the failed request to its previous status.
+ SETPDDEBUG { (Rolling back.) = pstack flush } if
diff --git a/pstoraster/pstopxl b/pstoraster/pstopxl
new file mode 100644
index 000000000..227f5f4cd
--- /dev/null
+++ b/pstoraster/pstopxl
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# "$Id: pstopxl 4076 2004-02-24 21:59:13Z mike $"
+#
+# CUPS PCL XL/PCL 6 filter script for Ghostscript.
+#
+# Copyright 2001-2003 by Easy Software Products.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Installation directories...
+prefix=/usr/local
+exec_prefix=${prefix}
+bindir=/usr/lib/cups/filter
+
+# Set the library/font path...
+GS_LIB="${CUPS_FONTPATH:=/usr/share/cups/fonts}"
+export GS_LIB
+
+# Determine the PCL XL/PCL 6 driver to use...
+if test "x$PPD" != x; then
+ colordevice=`grep '^*ColorDevice:' "$PPD" | awk -F: '{print $2}'`
+ case "$colordevice" in
+ *True* | *true*)
+ device="pxlcolor"
+ ;;
+ *)
+ device="pxlmono"
+ ;;
+ esac
+else
+ device="pxlmono"
+fi
+
+# Options we use with Ghostscript...
+gsopts="-dQUIET -dDEBUG -dPARANOIDSAFER -dNOPAUSE -dBATCH"
+gsopts="$gsopts -dNOMEDIAATTRS -sDEVICE=$device -sstdout=%stderr"
+
+# See if we have a filename on the command-line...
+if test -z "$6"; then
+ ifile="-"
+else
+ ifile="$6"
+fi
+
+echo INFO: Starting ESP Ghostscript 7.07.1... 1>&2
+echo DEBUG: Running $bindir/gsrip $gsopts -sOUTPUTFILE="%stdout" "$ifile" 1>&2
+
+# Now run Ghostscript...
+$bindir/gsrip $gsopts -sOUTPUTFILE="%stdout" "$ifile"
+
+#
+# End of "$Id: pstopxl 4076 2004-02-24 21:59:13Z mike $".
+#
diff --git a/pstoraster/pstopxl.in b/pstoraster/pstopxl.in
new file mode 100755
index 000000000..a66b0cab0
--- /dev/null
+++ b/pstoraster/pstopxl.in
@@ -0,0 +1,67 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# CUPS PCL XL/PCL 6 filter script for Ghostscript.
+#
+# Copyright 2001-2004 by Easy Software Products.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Installation directories...
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+
+# Set the library/font path...
+GS_LIB="${CUPS_FONTPATH:=/usr/share/cups/fonts}"
+export GS_LIB
+
+# Determine the PCL XL/PCL 6 driver to use...
+if test "x$PPD" != x; then
+ colordevice=`grep '^*ColorDevice:' "$PPD" | awk -F: '{print $2}'`
+ case "$colordevice" in
+ *True* | *true*)
+ device="pxlcolor"
+ ;;
+ *)
+ device="pxlmono"
+ ;;
+ esac
+else
+ device="pxlmono"
+fi
+
+# Options we use with Ghostscript...
+gsopts="-dQUIET -dDEBUG -dPARANOIDSAFER -dNOPAUSE -dBATCH"
+gsopts="$gsopts -dNOMEDIAATTRS -sDEVICE=$device -sstdout=%stderr"
+
+# See if we have a filename on the command-line...
+if test -z "$6"; then
+ ifile="-"
+else
+ ifile="$6"
+fi
+
+echo INFO: Starting ESP Ghostscript 7.07.1... 1>&2
+echo DEBUG: Running $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" "$ifile" 1>&2
+
+# Now run Ghostscript...
+$bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" "$ifile"
+
+#
+# End of "$Id$".
+#
diff --git a/pstoraster/pstoraster b/pstoraster/pstoraster
new file mode 100755
index 000000000..b6e17cb79
--- /dev/null
+++ b/pstoraster/pstoraster
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# "$Id: pstoraster 3041 2002-12-17 19:00:27Z swdev $"
+#
+# CUPS filter script for Ghostscript.
+#
+# Copyright 2001-2003 by Easy Software Products.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Installation directories...
+prefix=/usr/local
+exec_prefix=${prefix}
+bindir=${exec_prefix}/bin
+
+# Set the library/font path...
+GS_FONTPATH="$CUPS_FONTPATH"
+export GS_FONTPATH
+
+# Options we use with Ghostscript...
+gsopts="-dQUIET -dDEBUG -dPARANOIDSAFER -dNOPAUSE -dBATCH "
+gsopts="$gsopts -dNOMEDIAATTRS -sDEVICE=cups -sstdout=%stderr"
+
+# See if we have a profile=n,n,n,n,n,n,n,n,n,n,n option...
+profile=""
+for option in $5; do
+ case $option in
+ profile=*)
+ profile="-scupsProfile=`echo $option | awk -F= '{print $2}'`"
+ ;;
+ esac
+done
+
+# Now run Ghostscript...
+$bindir/gs $gsopts -sOUTPUTFILE="%stdout" $profile $6
+
+#
+# End of "$Id: pstoraster 3041 2002-12-17 19:00:27Z swdev $".
+#
diff --git a/pstoraster/pstoraster.convs b/pstoraster/pstoraster.convs
new file mode 100644
index 000000000..920520853
--- /dev/null
+++ b/pstoraster/pstoraster.convs
@@ -0,0 +1,29 @@
+#
+# "$Id: pstoraster.convs 4087 2004-02-25 20:14:54Z mike $"
+#
+# MIME converts file for Ghostscript.
+#
+# Copyright 1997-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+application/vnd.cups-postscript application/vnd.cups-raster 100 pstoraster
+
+#
+# End of "$Id: pstoraster.convs 4087 2004-02-25 20:14:54Z mike $".
+#
diff --git a/pstoraster/pstoraster.in b/pstoraster/pstoraster.in
new file mode 100755
index 000000000..dadb30fda
--- /dev/null
+++ b/pstoraster/pstoraster.in
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# CUPS raster filter script for Ghostscript.
+#
+# Copyright 2001-2004 by Easy Software Products.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Installation directories...
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+
+# Set the library/font path...
+GS_LIB="${CUPS_FONTPATH:=/usr/share/cups/fonts}"
+export GS_LIB
+
+# Options we use with Ghostscript...
+gsopts="-dQUIET -dDEBUG -dPARANOIDSAFER -dNOPAUSE -dBATCH"
+gsopts="$gsopts -dNOMEDIAATTRS -sDEVICE=cups -sstdout=%stderr"
+
+# See if we have a profile=n,n,n,n,n,n,n,n,n,n,n option...
+profile=""
+for option in $5; do
+ case $option in
+ profile=*)
+ profile="<</cupsProfile(`echo $option | awk -F= '{print $2}'`)>>setpagedevice"
+ ;;
+ esac
+done
+
+# See if we have a filename on the command-line...
+if test -z "$6"; then
+ ifile="-"
+else
+ ifile="$6"
+fi
+
+echo INFO: Starting ESP Ghostscript 7.07.1... 1>&2
+echo DEBUG: Running $bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c"$profile" "$ifile" 1>&2
+
+# Now run Ghostscript...
+$bindir/@GS@ $gsopts -sOUTPUTFILE="%stdout" -c"$profile" "$ifile"
+
+#
+# End of "$Id$".
+#
diff --git a/pstoraster/pxlcolor.ppd b/pstoraster/pxlcolor.ppd
new file mode 100644
index 000000000..5363caa9e
--- /dev/null
+++ b/pstoraster/pxlcolor.ppd
@@ -0,0 +1,205 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample color PCL XL/PCL 6 driver PPD file for the Common UNIX
+*% Printing System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "PCLCOLOR.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: False
+*cupsFilter: "application/vnd.cups-postscript 0 pstopxl"
+*ModelName: "HP Color LaserJet Series PCL 6"
+*ShortNickName: "HP Color LaserJet Series PCL 6"
+*NickName: "HP Color LaserJet Series PCL 6 CUPS v1.1"
+*PSVersion: "(3010.000) 707"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "8"
+*LandscapeOrientation: Plus90
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Duplex *Option1 False
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "12 12 600 780"
+*ImageableArea Legal/US Legal: "12 12 600 996"
+*ImageableArea Executive/US Executive: "12 12 510 708"
+*ImageableArea Tabloid/US Tabloid: "12 12 780 1212"
+*ImageableArea A3/A3: "12 12 830 1179"
+*ImageableArea A4/A4: "12 12 583 830"
+*ImageableArea A5/A5: "12 12 409 583"
+*ImageableArea B5/JIS B5: "12 12 504 717"
+*ImageableArea EnvISOB5/B5 (ISO): "12 12 469 697"
+*ImageableArea Env10/Com-10: "12 12 285 672"
+*ImageableArea EnvC5/EnvC5: "12 12 447 637"
+*ImageableArea EnvDL/EnvDL: "12 12 300 612"
+*ImageableArea EnvMonarch/Envelope Monarch: "12 12 267 528"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Default
+*InputSlot Default/Default: "<</MediaPosition 0>>setpagedevice"
+*InputSlot Tray1/Tray 1: "<</MediaPosition 8>>setpagedevice"
+*InputSlot Tray2/Tray 2: "<</MediaPosition 1>>setpagedevice"
+*InputSlot Tray3/Tray 3: "<</MediaPosition 4>>setpagedevice"
+*InputSlot Tray4/Tray 4: "<</MediaPosition 5>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</MediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</MediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: RGB
+*ColorModel RGB/Color: "<</BitsPerPixel 24>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</BitsPerPixel 8>>setpagedevice"
+*CloseUI: *ColorModel
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 300dpi
+*Resolution 150dpi/150 DPI: "<</HWResolution[150 150]>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *Duplex/Double-Sided Printing: PickOne
+*OrderDependency: 20 AnySetup *Duplex
+*DefaultDuplex: None
+*Duplex None/Off: "<</Duplex false>>setpagedevice"
+*Duplex DuplexNoTumble/Long Edge (Standard): "<</Duplex true/Tumble false>>setpagedevice"
+*Duplex DuplexTumble/Short Edge (Flip): "<</Duplex true/Tumble true>>setpagedevice"
+*CloseUI: *Duplex
+
+*OpenGroup: InstallableOptions
+*OpenUI *Option1/Duplexer: Boolean
+*DefaultOption1: False
+*Option1 True/Installed: ""
+*Option1 False/Not Installed: ""
+*CloseUI: *Option1
+*CloseGroup: InstallableOptions
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/pstoraster/pxlmono.ppd b/pstoraster/pxlmono.ppd
new file mode 100644
index 000000000..0cd68a3b3
--- /dev/null
+++ b/pstoraster/pxlmono.ppd
@@ -0,0 +1,199 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Sample monochrome PCL XL/PCL 6 driver PPD file for the Common UNIX
+*% Printing System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "PCLMONO.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: False
+*cupsFilter: "application/vnd.cups-postscript 0 pstopxl"
+*ModelName: "HP LaserJet Series PCL 6"
+*ShortNickName: "HP LaserJet Series PCL 6"
+*NickName: "HP LaserJet Series PCL 6 CUPS v1.1"
+*PSVersion: "(3010.000) 707"
+*LanguageLevel: "3"
+*ColorDevice: False
+*DefaultColorSpace: Gray
+*FileSystem: False
+*Throughput: "8"
+*LandscapeOrientation: Plus90
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Duplex *Option1 False
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "12 12 600 780"
+*ImageableArea Legal/US Legal: "12 12 600 996"
+*ImageableArea Executive/US Executive: "12 12 510 708"
+*ImageableArea Tabloid/US Tabloid: "12 12 780 1212"
+*ImageableArea A3/A3: "12 12 830 1179"
+*ImageableArea A4/A4: "12 12 583 830"
+*ImageableArea A5/A5: "12 12 409 583"
+*ImageableArea B5/JIS B5: "12 12 504 717"
+*ImageableArea EnvISOB5/B5 (ISO): "12 12 469 697"
+*ImageableArea Env10/Com-10: "12 12 285 672"
+*ImageableArea EnvC5/EnvC5: "12 12 447 637"
+*ImageableArea EnvDL/EnvDL: "12 12 300 612"
+*ImageableArea EnvMonarch/Envelope Monarch: "12 12 267 528"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Default
+*InputSlot Default/Default: "<</MediaPosition 0>>setpagedevice"
+*InputSlot Tray1/Tray 1: "<</MediaPosition 8>>setpagedevice"
+*InputSlot Tray2/Tray 2: "<</MediaPosition 1>>setpagedevice"
+*InputSlot Tray3/Tray 3: "<</MediaPosition 4>>setpagedevice"
+*InputSlot Tray4/Tray 4: "<</MediaPosition 5>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</MediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</MediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 600dpi
+*Resolution 150dpi/150 DPI: "<</HWResolution[150 150]>>setpagedevice"
+*Resolution 300dpi/300 DPI: "<</HWResolution[300 300]>>setpagedevice"
+*Resolution 600dpi/600 DPI: "<</HWResolution[600 600]>>setpagedevice"
+*Resolution 1200dpi/1200 DPI: "<</HWResolution[1200 1200]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *Duplex/Double-Sided Printing: PickOne
+*OrderDependency: 20 AnySetup *Duplex
+*DefaultDuplex: None
+*Duplex None/Off: "<</Duplex false>>setpagedevice"
+*Duplex DuplexNoTumble/Long Edge (Standard): "<</Duplex true/Tumble false>>setpagedevice"
+*Duplex DuplexTumble/Short Edge (Flip): "<</Duplex true/Tumble true>>setpagedevice"
+*CloseUI: *Duplex
+
+*OpenGroup: InstallableOptions
+*OpenUI *Option1/Duplexer: Boolean
+*DefaultOption1: False
+*Option1 True/Installed: ""
+*Option1 False/Not Installed: ""
+*CloseUI: *Option1
+*CloseGroup: InstallableOptions
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/scheduler/.cvsignore b/scheduler/.cvsignore
new file mode 100644
index 000000000..22f1097b7
--- /dev/null
+++ b/scheduler/.cvsignore
@@ -0,0 +1,5 @@
+cupsd
+cups-polld
+cups-lpd
+testmime
+testspeed
diff --git a/scheduler/Dependencies b/scheduler/Dependencies
new file mode 100644
index 000000000..7f2411c98
--- /dev/null
+++ b/scheduler/Dependencies
@@ -0,0 +1,105 @@
+# DO NOT DELETE
+
+auth.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+auth.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+auth.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+auth.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+auth.o: classes.h job.h conf.h banners.h dirsvc.h network.h ../cups/md5.h
+banners.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+banners.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+banners.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+banners.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+banners.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+cert.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+cert.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+cert.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+cert.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+cert.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+classes.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+classes.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+classes.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+classes.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+classes.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+client.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/md5.h
+client.o: cupsd.h ../cups/string.h ../cups/cups.h ../cups/ipp.h ../cups/ppd.h
+client.o: mime.h ../cups/ipp.h file.h ../cups/http.h ../cups/language.h
+client.o: ../cups/debug.h cert.h client.h auth.h printers.h classes.h job.h
+client.o: conf.h banners.h dirsvc.h network.h
+conf.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+conf.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+conf.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+conf.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+conf.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+devices.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+devices.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+devices.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+devices.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+devices.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+dirsvc.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+dirsvc.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+dirsvc.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+dirsvc.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+dirsvc.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+main.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+main.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+main.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+main.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+main.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+ipp.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+ipp.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+ipp.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+ipp.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+ipp.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+listen.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+listen.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+listen.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+listen.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+listen.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+job.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+job.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+job.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+job.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+job.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+log.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+log.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+log.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+log.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+log.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+network.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+network.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+network.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+network.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+network.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+ppds.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+ppds.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+ppds.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+ppds.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h printers.h
+ppds.o: classes.h job.h conf.h banners.h dirsvc.h network.h
+printers.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+printers.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+printers.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+printers.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+printers.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+quotas.o: cupsd.h ../cups/http-private.h ../config.h ../cups/http.h
+quotas.o: ../cups/md5.h ../cups/string.h ../cups/cups.h ../cups/ipp.h
+quotas.o: ../cups/ppd.h mime.h ../cups/ipp.h file.h ../cups/http.h
+quotas.o: ../cups/language.h ../cups/debug.h cert.h client.h auth.h
+quotas.o: printers.h classes.h job.h conf.h banners.h dirsvc.h network.h
+server.o: ../cups/http-private.h ../config.h ../cups/http.h ../cups/md5.h
+server.o: cupsd.h ../cups/string.h ../cups/cups.h ../cups/ipp.h ../cups/ppd.h
+server.o: mime.h ../cups/ipp.h file.h ../cups/http.h ../cups/language.h
+server.o: ../cups/debug.h cert.h client.h auth.h printers.h classes.h job.h
+server.o: conf.h banners.h dirsvc.h network.h
+file.o: ../cups/string.h ../config.h file.h
+filter.o: ../cups/debug.h ../cups/string.h ../config.h mime.h ../cups/ipp.h
+filter.o: file.h
+mime.o: ../cups/string.h ../config.h mime.h ../cups/ipp.h file.h
+type.o: ../cups/string.h ../config.h mime.h ../cups/ipp.h file.h
+type.o: ../cups/debug.h
+cups-lpd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+cups-lpd.o: ../cups/ppd.h ../cups/string.h ../config.h ../cups/language.h
+cups-polld.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+cups-polld.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
+testmime.o: ../cups/string.h ../config.h mime.h ../cups/ipp.h file.h
+testspeed.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+testspeed.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h
diff --git a/scheduler/Makefile b/scheduler/Makefile
new file mode 100644
index 000000000..daa1ddd41
--- /dev/null
+++ b/scheduler/Makefile
@@ -0,0 +1,144 @@
+#
+# "$Id$"
+#
+# Scheduler Makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+CUPSDOBJS = auth.o banners.o cert.o classes.o client.o conf.o devices.o \
+ dirsvc.o main.o ipp.o listen.o job.o log.o network.o \
+ ppds.o printers.o quotas.o server.o
+MIMEOBJS = file.o filter.o mime.o type.o
+OBJS = $(CUPSDOBJS) $(MIMEOBJS) cups-lpd.o cups-polld.o testmime.o \
+ testspeed.o
+TARGETS = cupsd cups-lpd cups-polld libmime.a testmime testspeed
+
+#
+# Make everything...
+#
+
+all: $(TARGETS)
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS)
+ $(RM) $(TARGETS)
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install the scheduler...
+#
+
+install: all
+ $(INSTALL_DIR) $(SBINDIR)
+ $(INSTALL_BIN) cupsd $(SBINDIR)
+ $(INSTALL_DIR) $(SERVERBIN)/daemon
+ $(INSTALL_BIN) cups-lpd $(SERVERBIN)/daemon
+ $(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
+ $(INSTALL_DIR) -m 711 $(SERVERROOT)/certs
+ $(INSTALL_DIR) $(SERVERROOT)/interfaces
+ $(INSTALL_DIR) $(SERVERROOT)/ppd
+ $(INSTALL_DIR) $(LOGDIR)
+ $(INSTALL_DIR) -m 710 $(REQUESTS)
+ $(INSTALL_DIR) -m 1770 $(REQUESTS)/tmp
+
+
+#
+# Make the scheduler executable, "cupsd".
+#
+
+cupsd: $(CUPSDOBJS) libmime.a ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) libmime.a \
+ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(PAMLIBS) $(LIBS) \
+ $(LIBPAPER) $(LIBMALLOC)
+
+
+#
+# Make the line printer daemon, "cups-lpd".
+#
+
+cups-lpd: cups-lpd.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cups-lpd cups-lpd.o $(LIBS)
+
+
+#
+# Make the polling daemon, "cups-polld".
+#
+
+cups-polld: cups-polld.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cups-polld cups-polld.o $(LIBS)
+
+
+#
+# libmime.a
+#
+
+libmime.a: $(MIMEOBJS)
+ echo Archiving $@...
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $(MIMEOBJS)
+ $(RANLIB) $@
+
+
+#
+# testmime
+#
+
+testmime: testmime.o libmime.a
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ testmime.o libmime.a ../cups/libcups.a $(LIBZ)
+
+
+#
+# Make the test program, "testspeed".
+#
+
+testspeed: testspeed.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o testspeed testspeed.o $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/scheduler/auth.c b/scheduler/auth.c
new file mode 100644
index 000000000..f7c7d5709
--- /dev/null
+++ b/scheduler/auth.c
@@ -0,0 +1,1677 @@
+/*
+ * "$Id$"
+ *
+ * Authorization routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddLocation() - Add a location for authorization.
+ * AddName() - Add a name to a location...
+ * AllowHost() - Add a host name that is allowed to access the
+ * location.
+ * AllowIP() - Add an IP address or network that is allowed to
+ * access the location.
+ * CheckAuth() - Check authorization masks.
+ * CopyLocation() - Make a copy of a location...
+ * DeleteAllLocations() - Free all memory used for location authorization.
+ * DenyHost() - Add a host name that is not allowed to access the
+ * location.
+ * DenyIP() - Add an IP address or network that is not allowed
+ * to access the location.
+ * FindBest() - Find the location entry that best matches the
+ * resource.
+ * FindLocation() - Find the named location.
+ * GetMD5Passwd() - Get an MD5 password.
+ * IsAuthorized() - Check to see if the user is authorized...
+ * add_allow() - Add an allow mask to the location.
+ * add_deny() - Add a deny mask to the location.
+ * cups_crypt() - Encrypt the password using the DES or MD5
+ * algorithms, as needed.
+ * pam_func() - PAM conversation function.
+ * to64() - Base64-encode an integer value...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <pwd.h>
+#include <grp.h>
+#include <cups/md5.h>
+#ifdef HAVE_SHADOW_H
+# include <shadow.h>
+#endif /* HAVE_SHADOW_H */
+#ifdef HAVE_CRYPT_H
+# include <crypt.h>
+#endif /* HAVE_CRYPT_H */
+#if HAVE_LIBPAM
+# ifdef HAVE_PAM_PAM_APPL_H
+# include <pam/pam_appl.h>
+# else
+# include <security/pam_appl.h>
+# endif /* HAVE_PAM_PAM_APPL_H */
+#endif /* HAVE_LIBPAM */
+#ifdef HAVE_USERSEC_H
+# include <usersec.h>
+#endif /* HAVE_USERSEC_H */
+
+
+/*
+ * Local functions...
+ */
+
+static authmask_t *add_allow(location_t *loc);
+static authmask_t *add_deny(location_t *loc);
+#if !HAVE_LIBPAM
+static char *cups_crypt(const char *pw, const char *salt);
+#endif /* !HAVE_LIBPAM */
+#if HAVE_LIBPAM
+static int pam_func(int, const struct pam_message **,
+ struct pam_response **, void *);
+#else
+static void to64(char *s, unsigned long v, int n);
+#endif /* HAVE_LIBPAM */
+
+
+/*
+ * Local globals...
+ */
+
+#if defined(__hpux) && defined(HAVE_LIBPAM)
+static client_t *auth_client; /* Current client being authenticated */
+#endif /* __hpux && HAVE_LIBPAM */
+
+
+/*
+ * 'AddLocation()' - Add a location for authorization.
+ */
+
+location_t * /* O - Pointer to new location record */
+AddLocation(const char *location) /* I - Location path */
+{
+ location_t *temp; /* New location */
+
+
+ /*
+ * Try to allocate memory for the new location.
+ */
+
+ if (NumLocations == 0)
+ temp = malloc(sizeof(location_t));
+ else
+ temp = realloc(Locations, sizeof(location_t) * (NumLocations + 1));
+
+ if (temp == NULL)
+ return (NULL);
+
+ Locations = temp;
+ temp += NumLocations;
+ NumLocations ++;
+
+ /*
+ * Initialize the record and copy the name over...
+ */
+
+ memset(temp, 0, sizeof(location_t));
+ strlcpy(temp->location, location, sizeof(temp->location));
+ temp->length = strlen(temp->location);
+
+ LogMessage(L_DEBUG, "AddLocation: added location \'%s\'", location);
+
+ /*
+ * Return the new record...
+ */
+
+ return (temp);
+}
+
+
+/*
+ * 'AddName()' - Add a name to a location...
+ */
+
+void
+AddName(location_t *loc, /* I - Location to add to */
+ char *name) /* I - Name to add */
+{
+ char **temp; /* Pointer to names array */
+
+
+ if (loc->num_names == 0)
+ temp = malloc(sizeof(char *));
+ else
+ temp = realloc(loc->names, (loc->num_names + 1) * sizeof(char *));
+
+ if (temp == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to add name to location %s: %s", loc->location,
+ strerror(errno));
+ return;
+ }
+
+ loc->names = temp;
+
+ if ((temp[loc->num_names] = strdup(name)) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to duplicate name for location %s: %s",
+ loc->location, strerror(errno));
+ return;
+ }
+
+ loc->num_names ++;
+}
+
+
+/*
+ * 'AllowHost()' - Add a host name that is allowed to access the location.
+ */
+
+void
+AllowHost(location_t *loc, /* I - Location to add to */
+ char *name) /* I - Name of host or domain to add */
+{
+ authmask_t *temp; /* New host/domain mask */
+ char ifname[32], /* Interface name */
+ *ifptr; /* Pointer to end of name */
+
+
+ if ((temp = add_allow(loc)) == NULL)
+ return;
+
+ if (strcasecmp(name, "@LOCAL") == 0)
+ {
+ /*
+ * Allow *interface*...
+ */
+
+ temp->type = AUTH_INTERFACE;
+ temp->mask.name.name = strdup("*");
+ temp->mask.name.length = 1;
+ }
+ else if (strncasecmp(name, "@IF(", 4) == 0)
+ {
+ /*
+ * Allow *interface*...
+ */
+
+ strlcpy(ifname, name + 4, sizeof(ifname));
+
+ ifptr = ifname + strlen(ifname);
+
+ if (ifptr[-1] == ')')
+ {
+ ifptr --;
+ *ifptr = '\0';
+ }
+
+ temp->type = AUTH_INTERFACE;
+ temp->mask.name.name = strdup(ifname);
+ temp->mask.name.length = ifptr - ifname;
+ }
+ else
+ {
+ /*
+ * Allow name...
+ */
+
+ temp->type = AUTH_NAME;
+ temp->mask.name.name = strdup(name);
+ temp->mask.name.length = strlen(name);
+ }
+
+ LogMessage(L_DEBUG, "AllowHost: %s allow %s", loc->location, name);
+}
+
+
+/*
+ * 'AllowIP()' - Add an IP address or network that is allowed to access the
+ * location.
+ */
+
+void
+AllowIP(location_t *loc, /* I - Location to add to */
+ unsigned address, /* I - IP address to add */
+ unsigned netmask) /* I - Netmask of address */
+{
+ authmask_t *temp; /* New host/domain mask */
+
+
+ if ((temp = add_allow(loc)) == NULL)
+ return;
+
+ temp->type = AUTH_IP;
+ temp->mask.ip.address = address;
+ temp->mask.ip.netmask = netmask;
+
+ LogMessage(L_DEBUG, "AllowIP: %s allow %08x/%08x", loc->location,
+ address, netmask);
+}
+
+
+/*
+ * 'CheckAuth()' - Check authorization masks.
+ */
+
+int /* O - 1 if mask matches, 0 otherwise */
+CheckAuth(unsigned ip, /* I - Client address */
+ char *name, /* I - Client hostname */
+ int name_len, /* I - Length of hostname */
+ int num_masks, /* I - Number of masks */
+ authmask_t *masks) /* I - Masks */
+{
+ cups_netif_t *iface; /* Network interface */
+ unsigned netip; /* Network address */
+
+
+ while (num_masks > 0)
+ {
+ switch (masks->type)
+ {
+ case AUTH_INTERFACE :
+ /*
+ * Check for a match with a network interface...
+ */
+
+ netip = htonl(ip);
+
+ if (strcmp(masks->mask.name.name, "*") == 0)
+ {
+ /*
+ * Check against all local interfaces...
+ */
+
+ NetIFUpdate();
+
+ for (iface = NetIFList; iface != NULL; iface = iface->next)
+ {
+ /*
+ * Only check local interfaces...
+ */
+
+ if (!iface->is_local)
+ continue;
+
+ if ((netip & iface->mask.sin_addr.s_addr) ==
+ (iface->address.sin_addr.s_addr &
+ iface->mask.sin_addr.s_addr))
+ return (1);
+ }
+ }
+ else
+ {
+ /*
+ * Check the named interface...
+ */
+
+ if ((iface = NetIFFind(masks->mask.name.name)) != NULL)
+ {
+ if ((netip & iface->mask.sin_addr.s_addr) ==
+ (iface->address.sin_addr.s_addr &
+ iface->mask.sin_addr.s_addr))
+ return (1);
+ }
+ }
+ break;
+
+ case AUTH_NAME :
+ /*
+ * Check for exact name match...
+ */
+
+ if (strcasecmp(name, masks->mask.name.name) == 0)
+ return (1);
+
+ /*
+ * Check for domain match...
+ */
+
+ if (name_len >= masks->mask.name.length &&
+ masks->mask.name.name[0] == '.' &&
+ strcasecmp(name + name_len - masks->mask.name.length,
+ masks->mask.name.name) == 0)
+ return (1);
+ break;
+
+ case AUTH_IP :
+ /*
+ * Check for IP/network address match...
+ */
+
+ if ((ip & masks->mask.ip.netmask) == masks->mask.ip.address)
+ return (1);
+ break;
+ }
+
+ masks ++;
+ num_masks --;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'CopyLocation()' - Make a copy of a location...
+ */
+
+location_t * /* O - New location */
+CopyLocation(location_t **loc) /* IO - Original location */
+{
+ int i; /* Looping var */
+ int locindex; /* Index into Locations array */
+ location_t *temp; /* New location */
+ char location[HTTP_MAX_URI]; /* Location of resource */
+
+
+ /*
+ * Add the new location, updating the original location
+ * pointer as needed...
+ */
+
+ locindex = *loc - Locations;
+
+ /*
+ * Use a local copy of location because AddLocation may cause
+ * this memory to be moved...
+ */
+
+ strlcpy(location, (*loc)->location, sizeof(location));
+
+ if ((temp = AddLocation(location)) == NULL)
+ return (NULL);
+
+ *loc = Locations + locindex;
+
+ /*
+ * Copy the information from the original location to the new one.
+ */
+
+ temp->limit = (*loc)->limit;
+ temp->order_type = (*loc)->order_type;
+ temp->type = (*loc)->type;
+ temp->level = (*loc)->level;
+ temp->satisfy = (*loc)->satisfy;
+ temp->encryption = (*loc)->encryption;
+
+ if ((temp->num_names = (*loc)->num_names) > 0)
+ {
+ /*
+ * Copy the names array...
+ */
+
+ if ((temp->names = calloc(temp->num_names, sizeof(char *))) == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to allocate memory for %d names: %s",
+ temp->num_names, strerror(errno));
+ NumLocations --;
+ return (NULL);
+ }
+
+ for (i = 0; i < temp->num_names; i ++)
+ if ((temp->names[i] = strdup((*loc)->names[i])) == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to copy name \"%s\": %s",
+ (*loc)->names[i], strerror(errno));
+
+ NumLocations --;
+ return (NULL);
+ }
+ }
+
+ if ((temp->num_allow = (*loc)->num_allow) > 0)
+ {
+ /*
+ * Copy allow rules...
+ */
+
+ if ((temp->allow = calloc(temp->num_allow, sizeof(authmask_t))) == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to allocate memory for %d allow rules: %s",
+ temp->num_allow, strerror(errno));
+ NumLocations --;
+ return (NULL);
+ }
+
+ for (i = 0; i < temp->num_allow; i ++)
+ switch (temp->allow[i].type = (*loc)->allow[i].type)
+ {
+ case AUTH_NAME :
+ temp->allow[i].mask.name.length = (*loc)->allow[i].mask.name.length;
+ temp->allow[i].mask.name.name = strdup((*loc)->allow[i].mask.name.name);
+
+ if (temp->allow[i].mask.name.name == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to copy allow name \"%s\": %s",
+ (*loc)->allow[i].mask.name.name, strerror(errno));
+ NumLocations --;
+ return (NULL);
+ }
+ break;
+ case AUTH_IP :
+ memcpy(&(temp->allow[i].mask.ip), &((*loc)->allow[i].mask.ip),
+ sizeof(ipmask_t));
+ break;
+ }
+ }
+
+ if ((temp->num_deny = (*loc)->num_deny) > 0)
+ {
+ /*
+ * Copy deny rules...
+ */
+
+ if ((temp->deny = calloc(temp->num_deny, sizeof(authmask_t))) == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to allocate memory for %d deny rules: %s",
+ temp->num_deny, strerror(errno));
+ NumLocations --;
+ return (NULL);
+ }
+
+ for (i = 0; i < temp->num_deny; i ++)
+ switch (temp->deny[i].type = (*loc)->deny[i].type)
+ {
+ case AUTH_NAME :
+ temp->deny[i].mask.name.length = (*loc)->deny[i].mask.name.length;
+ temp->deny[i].mask.name.name = strdup((*loc)->deny[i].mask.name.name);
+
+ if (temp->deny[i].mask.name.name == NULL)
+ {
+ LogMessage(L_ERROR, "CopyLocation: Unable to copy deny name \"%s\": %s",
+ (*loc)->deny[i].mask.name.name, strerror(errno));
+ NumLocations --;
+ return (NULL);
+ }
+ break;
+ case AUTH_IP :
+ memcpy(&(temp->deny[i].mask.ip), &((*loc)->deny[i].mask.ip),
+ sizeof(ipmask_t));
+ break;
+ }
+ }
+
+ return (temp);
+}
+
+
+/*
+ * 'DeleteAllLocations()' - Free all memory used for location authorization.
+ */
+
+void
+DeleteAllLocations(void)
+{
+ int i, j; /* Looping vars */
+ location_t *loc; /* Current location */
+ authmask_t *mask; /* Current mask */
+
+
+ /*
+ * Free all of the allow/deny records first...
+ */
+
+ for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
+ {
+ for (j = loc->num_names - 1; j >= 0; j --)
+ free(loc->names[j]);
+
+ if (loc->num_names > 0)
+ free(loc->names);
+
+ for (j = loc->num_allow, mask = loc->allow; j > 0; j --, mask ++)
+ if (mask->type == AUTH_NAME || mask->type == AUTH_INTERFACE)
+ free(mask->mask.name.name);
+
+ if (loc->num_allow > 0)
+ free(loc->allow);
+
+ for (j = loc->num_deny, mask = loc->deny; j > 0; j --, mask ++)
+ if (mask->type == AUTH_NAME || mask->type == AUTH_INTERFACE)
+ free(mask->mask.name.name);
+
+ if (loc->num_deny > 0)
+ free(loc->deny);
+ }
+
+ /*
+ * Then free the location array...
+ */
+
+ if (NumLocations > 0)
+ free(Locations);
+
+ Locations = NULL;
+ NumLocations = 0;
+}
+
+
+/*
+ * 'DenyHost()' - Add a host name that is not allowed to access the location.
+ */
+
+void
+DenyHost(location_t *loc, /* I - Location to add to */
+ char *name) /* I - Name of host or domain to add */
+{
+ authmask_t *temp; /* New host/domain mask */
+ char ifname[32], /* Interface name */
+ *ifptr; /* Pointer to end of name */
+
+
+ if ((temp = add_deny(loc)) == NULL)
+ return;
+
+ if (strcasecmp(name, "@LOCAL") == 0)
+ {
+ /*
+ * Deny *interface*...
+ */
+
+ temp->type = AUTH_INTERFACE;
+ temp->mask.name.name = strdup("*");
+ temp->mask.name.length = 1;
+ }
+ else if (strncasecmp(name, "@IF(", 4) == 0)
+ {
+ /*
+ * Deny *interface*...
+ */
+
+ strlcpy(ifname, name + 4, sizeof(ifname));
+
+ ifptr = ifname + strlen(ifname);
+
+ if (ifptr[-1] == ')')
+ {
+ ifptr --;
+ *ifptr = '\0';
+ }
+
+ temp->type = AUTH_INTERFACE;
+ temp->mask.name.name = strdup(ifname);
+ temp->mask.name.length = ifptr - ifname;
+ }
+ else
+ {
+ /*
+ * Deny name...
+ */
+
+ temp->type = AUTH_NAME;
+ temp->mask.name.name = strdup(name);
+ temp->mask.name.length = strlen(name);
+ }
+
+ LogMessage(L_DEBUG, "DenyHost: %s deny %s", loc->location, name);
+}
+
+
+/*
+ * 'DenyIP()' - Add an IP address or network that is not allowed to access
+ * the location.
+ */
+
+void
+DenyIP(location_t *loc, /* I - Location to add to */
+ unsigned address, /* I - IP address to add */
+ unsigned netmask) /* I - Netmask of address */
+{
+ authmask_t *temp; /* New host/domain mask */
+
+
+ if ((temp = add_deny(loc)) == NULL)
+ return;
+
+ temp->type = AUTH_IP;
+ temp->mask.ip.address = address;
+ temp->mask.ip.netmask = netmask;
+
+ LogMessage(L_DEBUG, "DenyIP: %s deny %08x/%08x\n", loc->location,
+ address, netmask);
+}
+
+
+/*
+ * 'FindBest()' - Find the location entry that best matches the resource.
+ */
+
+location_t * /* O - Location that matches */
+FindBest(const char *path, /* I - Resource path */
+ http_state_t state) /* I - HTTP state/request */
+{
+ int i; /* Looping var */
+ char uri[HTTP_MAX_URI],
+ /* URI in request... */
+ *uriptr; /* Pointer into URI */
+ location_t *loc, /* Current location */
+ *best; /* Best match for location so far */
+ int bestlen; /* Length of best match */
+ int limit; /* Limit field */
+ static const int limits[] = /* Map http_status_t to AUTH_LIMIT_xyz */
+ {
+ AUTH_LIMIT_ALL,
+ AUTH_LIMIT_OPTIONS,
+ AUTH_LIMIT_GET,
+ AUTH_LIMIT_GET,
+ AUTH_LIMIT_HEAD,
+ AUTH_LIMIT_POST,
+ AUTH_LIMIT_POST,
+ AUTH_LIMIT_POST,
+ AUTH_LIMIT_PUT,
+ AUTH_LIMIT_PUT,
+ AUTH_LIMIT_DELETE,
+ AUTH_LIMIT_TRACE,
+ AUTH_LIMIT_ALL,
+ AUTH_LIMIT_ALL
+ };
+
+
+ /*
+ * First copy the connection URI to a local string so we have drop
+ * any .ppd extension from the pathname in /printers or /classes
+ * URIs...
+ */
+
+ strlcpy(uri, path, sizeof(uri));
+
+ if (strncmp(uri, "/printers/", 10) == 0 ||
+ strncmp(uri, "/classes/", 9) == 0)
+ {
+ /*
+ * Check if the URI has .ppd on the end...
+ */
+
+ uriptr = uri + strlen(uri) - 4; /* len > 4 if we get here... */
+
+ if (strcmp(uriptr, ".ppd") == 0)
+ *uriptr = '\0';
+ }
+
+ LogMessage(L_DEBUG2, "FindBest: uri = \"%s\"...", uri);
+
+ /*
+ * Loop through the list of locations to find a match...
+ */
+
+ limit = limits[state];
+ best = NULL;
+ bestlen = 0;
+
+ for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
+ {
+ LogMessage(L_DEBUG2, "FindBest: Location %s Limit %x",
+ loc->location, loc->limit);
+
+ if (!strncmp(uri, "/printers/", 10) ||!strncmp(uri, "/classes/", 9))
+ {
+ /*
+ * Use case-insensitive comparison for queue names...
+ */
+
+ if (loc->length > bestlen &&
+ strncasecmp(uri, loc->location, loc->length) == 0 &&
+ loc->location[0] == '/' &&
+ (limit & loc->limit) != 0)
+ {
+ best = loc;
+ bestlen = loc->length;
+ }
+ }
+ else
+ {
+ /*
+ * Use case-sensitive comparison for other URIs...
+ */
+
+ if (loc->length > bestlen &&
+ strncmp(uri, loc->location, loc->length) == 0 &&
+ loc->location[0] == '/' &&
+ (limit & loc->limit) != 0)
+ {
+ best = loc;
+ bestlen = loc->length;
+ }
+ }
+ }
+
+ /*
+ * Return the match, if any...
+ */
+
+ LogMessage(L_DEBUG2, "FindBest: best = \"%s\"",
+ best ? best->location : "NONE");
+
+ return (best);
+}
+
+
+/*
+ * 'FindLocation()' - Find the named location.
+ */
+
+location_t * /* O - Location that matches */
+FindLocation(const char *location) /* I - Connection */
+{
+ int i; /* Looping var */
+
+
+ /*
+ * Loop through the list of locations to find a match...
+ */
+
+ for (i = 0; i < NumLocations; i ++)
+ if (strcasecmp(Locations[i].location, location) == 0)
+ return (Locations + i);
+
+ return (NULL);
+}
+
+
+/*
+ * 'GetMD5Passwd()' - Get an MD5 password.
+ */
+
+char * /* O - MD5 password string */
+GetMD5Passwd(const char *username, /* I - Username */
+ const char *group, /* I - Group */
+ char passwd[33]) /* O - MD5 password string */
+{
+ cups_file_t *fp; /* passwd.md5 file */
+ char filename[1024], /* passwd.md5 filename */
+ line[256], /* Line from file */
+ tempuser[33], /* User from file */
+ tempgroup[33]; /* Group from file */
+
+
+ LogMessage(L_DEBUG2, "GetMD5Passwd(username=\"%s\", group=\"%s\", passwd=%p)",
+ username, group ? group : "(null)", passwd);
+
+ snprintf(filename, sizeof(filename), "%s/passwd.md5", ServerRoot);
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to open %s - %s", filename, strerror(errno));
+ return (NULL);
+ }
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ if (sscanf(line, "%32[^:]:%32[^:]:%32s", tempuser, tempgroup, passwd) != 3)
+ {
+ LogMessage(L_ERROR, "Bad MD5 password line: %s", line);
+ continue;
+ }
+
+ if (strcmp(username, tempuser) == 0 &&
+ (group == NULL || strcmp(group, tempgroup) == 0))
+ {
+ /*
+ * Found the password entry!
+ */
+
+ LogMessage(L_DEBUG2, "Found MD5 user %s, group %s...", username,
+ tempgroup);
+
+ cupsFileClose(fp);
+ return (passwd);
+ }
+ }
+
+ /*
+ * Didn't find a password entry - return NULL!
+ */
+
+ cupsFileClose(fp);
+ return (NULL);
+}
+
+
+/*
+ * 'IsAuthorized()' - Check to see if the user is authorized...
+ */
+
+http_status_t /* O - HTTP_OK if authorized or error code */
+IsAuthorized(client_t *con) /* I - Connection */
+{
+ int i, j, /* Looping vars */
+ auth; /* Authorization status */
+ unsigned address; /* Authorization address */
+ location_t *best; /* Best match for location so far */
+ int hostlen; /* Length of hostname */
+ struct passwd *pw; /* User password data */
+ struct group *grp; /* Group data */
+ char nonce[HTTP_MAX_VALUE],
+ /* Nonce value from client */
+ md5[33], /* MD5 password */
+ basicmd5[33]; /* MD5 of Basic password */
+#if HAVE_LIBPAM
+ pam_handle_t *pamh; /* PAM authentication handle */
+ int pamerr; /* PAM error code */
+ struct pam_conv pamdata; /* PAM conversation data */
+#elif defined(HAVE_USERSEC_H)
+ char *authmsg; /* Authentication message */
+ char *loginmsg; /* Login message */
+ int reenter; /* ??? */
+#else
+ char *pass; /* Encrypted password */
+# ifdef HAVE_SHADOW_H
+ struct spwd *spw; /* Shadow password data */
+# endif /* HAVE_SHADOW_H */
+#endif /* HAVE_LIBPAM */
+ static const char * const states[] = /* HTTP client states... */
+ {
+ "WAITING",
+ "OPTIONS",
+ "GET",
+ "GET",
+ "HEAD",
+ "POST",
+ "POST",
+ "POST",
+ "PUT",
+ "PUT",
+ "DELETE",
+ "TRACE",
+ "CLOSE",
+ "STATUS"
+ };
+
+
+ LogMessage(L_DEBUG2, "IsAuthorized: con->uri = \"%s\"", con->uri);
+
+ /*
+ * Find a matching location; if there is no match then access is
+ * not authorized...
+ */
+
+ if ((best = FindBest(con->uri, con->http.state)) == NULL)
+ return (HTTP_FORBIDDEN);
+
+ /*
+ * Check host/ip-based accesses...
+ */
+
+ address = ntohl(con->http.hostaddr.sin_addr.s_addr);
+ hostlen = strlen(con->http.hostname);
+
+ if (address == 0x7f000001 || strcasecmp(con->http.hostname, "localhost") == 0)
+ {
+ /*
+ * Access from localhost (127.0.0.1) is always allowed...
+ */
+
+ auth = AUTH_ALLOW;
+ }
+ else if (best->num_allow == 0 && best->num_deny == 0)
+ {
+ /*
+ * No allow/deny lines - allow access...
+ */
+
+ auth = AUTH_ALLOW;
+ }
+ else
+ {
+ /*
+ * Do authorization checks on the domain/address...
+ */
+
+ switch (best->order_type)
+ {
+ default :
+ auth = AUTH_DENY; /* anti-compiler-warning-code */
+ break;
+
+ case AUTH_ALLOW : /* Order Deny,Allow */
+ auth = AUTH_ALLOW;
+
+ if (CheckAuth(address, con->http.hostname, hostlen,
+ best->num_deny, best->deny))
+ auth = AUTH_DENY;
+
+ if (CheckAuth(address, con->http.hostname, hostlen,
+ best->num_allow, best->allow))
+ auth = AUTH_ALLOW;
+ break;
+
+ case AUTH_DENY : /* Order Allow,Deny */
+ auth = AUTH_DENY;
+
+ if (CheckAuth(address, con->http.hostname, hostlen,
+ best->num_allow, best->allow))
+ auth = AUTH_ALLOW;
+
+ if (CheckAuth(address, con->http.hostname, hostlen,
+ best->num_deny, best->deny))
+ auth = AUTH_DENY;
+ break;
+ }
+ }
+
+ LogMessage(L_DEBUG2, "IsAuthorized: auth = %d, satisfy=%d...",
+ auth, best->satisfy);
+
+ if (auth == AUTH_DENY && best->satisfy == AUTH_SATISFY_ALL)
+ return (HTTP_FORBIDDEN);
+
+#ifdef HAVE_SSL
+ /*
+ * See if encryption is required...
+ */
+
+ if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: Need upgrade to TLS...");
+ return (HTTP_UPGRADE_REQUIRED);
+ }
+#endif /* HAVE_SSL */
+
+ /*
+ * Now see what access level is required...
+ */
+
+ if (best->level == AUTH_ANON) /* Anonymous access - allow it */
+ return (HTTP_OK);
+
+ LogMessage(L_DEBUG2, "IsAuthorized: username = \"%s\" password = %d chars",
+ con->username, (int)strlen(con->password));
+ DEBUG_printf(("IsAuthorized: username = \"%s\", password = \"%s\"\n",
+ con->username, con->password));
+
+ if (con->username[0] == '\0')
+ {
+ if (best->satisfy == AUTH_SATISFY_ALL || auth == AUTH_DENY)
+ return (HTTP_UNAUTHORIZED); /* Non-anonymous needs user/pass */
+ else
+ return (HTTP_OK); /* unless overridden with Satisfy */
+ }
+
+ /*
+ * Check the user's password...
+ */
+
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"",
+ con->username, address, con->http.hostname);
+
+ pw = NULL;
+
+ if ((address != 0x7f000001 &&
+ strcasecmp(con->http.hostname, "localhost") != 0) ||
+ strncmp(con->http.fields[HTTP_FIELD_AUTHORIZATION], "Local", 5) != 0)
+ {
+ /*
+ * Not doing local certificate-based authentication; check the password...
+ */
+
+ if (!con->password[0])
+ return (HTTP_UNAUTHORIZED);
+
+ /*
+ * See what kind of authentication we are doing...
+ */
+
+ switch (best->type)
+ {
+ case AUTH_BASIC :
+ /*
+ * Get the user info...
+ */
+
+ pw = getpwnam(con->username); /* Get the current password */
+ endpwent(); /* Close the password file */
+
+#if HAVE_LIBPAM
+ /*
+ * Only use PAM to do authentication. This allows MD5 passwords, among
+ * other things...
+ */
+
+ pamdata.conv = pam_func;
+ pamdata.appdata_ptr = con;
+
+# ifdef __hpux
+ /*
+ * Workaround for HP-UX bug in pam_unix; see pam_conv() below for
+ * more info...
+ */
+
+ auth_client = con;
+# endif /* __hpux */
+
+ DEBUG_printf(("IsAuthorized: Setting appdata_ptr = %p\n", con));
+
+ pamerr = pam_start("cups", con->username, &pamdata, &pamh);
+ if (pamerr != PAM_SUCCESS)
+ {
+ LogMessage(L_ERROR, "IsAuthorized: pam_start() returned %d (%s)!\n",
+ pamerr, pam_strerror(pamh, pamerr));
+ pam_end(pamh, 0);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ pamerr = pam_authenticate(pamh, PAM_SILENT);
+ if (pamerr != PAM_SUCCESS)
+ {
+ LogMessage(L_ERROR, "IsAuthorized: pam_authenticate() returned %d (%s)!\n",
+ pamerr, pam_strerror(pamh, pamerr));
+ pam_end(pamh, 0);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ pamerr = pam_acct_mgmt(pamh, PAM_SILENT);
+ if (pamerr != PAM_SUCCESS)
+ {
+ LogMessage(L_ERROR, "IsAuthorized: pam_acct_mgmt() returned %d (%s)!\n",
+ pamerr, pam_strerror(pamh, pamerr));
+ pam_end(pamh, 0);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ pam_end(pamh, PAM_SUCCESS);
+#elif defined(HAVE_USERSEC_H)
+ /*
+ * Use AIX authentication interface...
+ */
+
+ LogMessage(L_DEBUG, "IsAuthorized: AIX authenticate of username \"%s\"",
+ con->username);
+
+ reenter = 1;
+ if (authenticate(con->username, con->password, &reenter, &authmsg) != 0)
+ {
+ LogMessage(L_DEBUG, "IsAuthorized: Unable to authenticate username \"%s\": %s",
+ con->username, strerror(errno));
+ return (HTTP_UNAUTHORIZED);
+ }
+#else
+ /*
+ * Use normal UNIX password file-based authentication...
+ */
+
+ if (pw == NULL) /* No such user... */
+ {
+ LogMessage(L_WARN, "IsAuthorized: Unknown username \"%s\"; access denied.",
+ con->username);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+# ifdef HAVE_SHADOW_H
+ spw = getspnam(con->username);
+ endspent();
+
+ if (spw == NULL && strcmp(pw->pw_passwd, "x") == 0)
+ { /* Don't allow blank passwords! */
+ LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no shadow password; access denied.",
+ con->username);
+ return (HTTP_UNAUTHORIZED); /* No such user or bad shadow file */
+ }
+
+# ifdef DEBUG
+ if (spw != NULL)
+ printf("spw->sp_pwdp = \"%s\"\n", spw->sp_pwdp);
+ else
+ puts("spw = NULL");
+# endif /* DEBUG */
+
+ if (spw != NULL && spw->sp_pwdp[0] == '\0' && pw->pw_passwd[0] == '\0')
+# else
+ if (pw->pw_passwd[0] == '\0')
+# endif /* HAVE_SHADOW_H */
+ { /* Don't allow blank passwords! */
+ LogMessage(L_WARN, "IsAuthorized: Username \"%s\" has no password; access denied.",
+ con->username);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ /*
+ * OK, the password isn't blank, so compare with what came from the client...
+ */
+
+ pass = cups_crypt(con->password, pw->pw_passwd);
+
+ LogMessage(L_DEBUG2, "IsAuthorized: pw_passwd = %s, crypt = %s",
+ pw->pw_passwd, pass);
+
+ if (pass == NULL || strcmp(pw->pw_passwd, pass) != 0)
+ {
+# ifdef HAVE_SHADOW_H
+ if (spw != NULL)
+ {
+ pass = cups_crypt(con->password, spw->sp_pwdp);
+
+ LogMessage(L_DEBUG2, "IsAuthorized: sp_pwdp = %s, crypt = %s",
+ spw->sp_pwdp, pass);
+
+ if (pass == NULL || strcmp(spw->sp_pwdp, pass) != 0)
+ return (HTTP_UNAUTHORIZED);
+ }
+ else
+# endif /* HAVE_SHADOW_H */
+ return (HTTP_UNAUTHORIZED);
+ }
+#endif /* HAVE_LIBPAM */
+ break;
+
+ case AUTH_DIGEST :
+ /*
+ * Do Digest authentication...
+ */
+
+ if (!httpGetSubField(&(con->http), HTTP_FIELD_AUTHORIZATION, "nonce",
+ nonce))
+ {
+ LogMessage(L_ERROR, "IsAuthorized: No nonce value for Digest authentication!");
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ if (strcmp(con->http.hostname, nonce) != 0)
+ {
+ LogMessage(L_ERROR, "IsAuthorized: Nonce value error!");
+ LogMessage(L_ERROR, "IsAuthorized: Expected \"%s\",",
+ con->http.hostname);
+ LogMessage(L_ERROR, "IsAuthorized: Got \"%s\"!", nonce);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ LogMessage(L_DEBUG2, "IsAuthorized: nonce = \"%s\"", nonce);
+
+ if (best->num_names && best->level == AUTH_GROUP)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: num_names = %d", best->num_names);
+
+ for (i = 0; i < best->num_names; i ++)
+ if (GetMD5Passwd(con->username, best->names[i], md5))
+ break;
+
+ if (i >= best->num_names)
+ md5[0] = '\0';
+ }
+ else if (!GetMD5Passwd(con->username, NULL, md5))
+ md5[0] = '\0';
+
+
+ if (!md5[0])
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: No matching user:group for \"%s\" in passwd.md5!",
+ con->username);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ httpMD5Final(nonce, states[con->http.state], con->uri, md5);
+
+ if (strcmp(md5, con->password) != 0)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: MD5s \"%s\" and \"%s\" don't match!",
+ md5, con->password);
+ return (HTTP_UNAUTHORIZED);
+ }
+ break;
+
+ case AUTH_BASICDIGEST :
+ /*
+ * Do Basic authentication with the Digest password file...
+ */
+
+ if (best->num_names && best->level == AUTH_GROUP)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: num_names = %d", best->num_names);
+
+ for (i = 0; i < best->num_names; i ++)
+ if (GetMD5Passwd(con->username, best->names[i], md5))
+ break;
+
+ if (i >= best->num_names)
+ md5[0] = '\0';
+ }
+ else if (!GetMD5Passwd(con->username, NULL, md5))
+ md5[0] = '\0';
+
+ if (!md5[0])
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: No matching user:group for \"%s\" in passwd.md5!",
+ con->username);
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ httpMD5(con->username, "CUPS", con->password, basicmd5);
+
+ if (strcmp(md5, basicmd5) != 0)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: MD5s \"%s\" and \"%s\" don't match!",
+ md5, basicmd5);
+ return (HTTP_UNAUTHORIZED);
+ }
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * Get password entry for certificate-based auth...
+ */
+
+ pw = getpwnam(con->username); /* Get the current password */
+ endpwent(); /* Close the password file */
+ }
+
+ /*
+ * OK, the password is good. See if we need normal user access, or group
+ * access... (root always matches)
+ */
+
+ if (strcmp(con->username, "root") == 0)
+ return (HTTP_OK);
+
+ if (best->level == AUTH_USER)
+ {
+ /*
+ * If there are no names associated with this location, then
+ * any valid user is OK...
+ */
+
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking user membership...");
+
+ if (best->num_names == 0)
+ return (HTTP_OK);
+
+ /*
+ * Otherwise check the user list and return OK if this user is
+ * allowed...
+ */
+
+ for (i = 0; i < best->num_names; i ++)
+ if (strcmp(con->username, best->names[i]) == 0)
+ return (HTTP_OK);
+
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ if (best->type == AUTH_BASIC)
+ {
+ /*
+ * Check to see if this user is in any of the named groups...
+ */
+
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking group membership...");
+
+ for (i = 0; i < best->num_names; i ++)
+ {
+ grp = getgrnam(best->names[i]);
+ endgrent();
+
+ if (grp == NULL) /* No group by that name??? */
+ {
+ LogMessage(L_WARN, "IsAuthorized: group name \"%s\" does not exist!",
+ best->names[i]);
+ return (HTTP_FORBIDDEN);
+ }
+
+ for (j = 0; grp->gr_mem[j] != NULL; j ++)
+ if (strcmp(con->username, grp->gr_mem[j]) == 0)
+ return (HTTP_OK);
+
+ /*
+ * Check to see if the default group ID matches for the user...
+ */
+
+ if (pw != NULL && grp->gr_gid == pw->pw_gid)
+ return (HTTP_OK);
+ }
+
+ /*
+ * The user isn't part of the specified group, so deny access...
+ */
+
+ LogMessage(L_DEBUG2, "IsAuthorized: user not in group!");
+
+ return (HTTP_UNAUTHORIZED);
+ }
+
+ /*
+ * All checks passed...
+ */
+
+ return (HTTP_OK);
+}
+
+
+/*
+ * 'add_allow()' - Add an allow mask to the location.
+ */
+
+static authmask_t * /* O - New mask record */
+add_allow(location_t *loc) /* I - Location to add to */
+{
+ authmask_t *temp; /* New mask record */
+
+
+ /*
+ * Range-check...
+ */
+
+ if (loc == NULL)
+ return (NULL);
+
+ /*
+ * Try to allocate memory for the record...
+ */
+
+ if (loc->num_allow == 0)
+ temp = malloc(sizeof(authmask_t));
+ else
+ temp = realloc(loc->allow, sizeof(authmask_t) * (loc->num_allow + 1));
+
+ if (temp == NULL)
+ return (NULL);
+
+ loc->allow = temp;
+ temp += loc->num_allow;
+ loc->num_allow ++;
+
+ /*
+ * Clear the mask record and return...
+ */
+
+ memset(temp, 0, sizeof(authmask_t));
+ return (temp);
+}
+
+
+/*
+ * 'add_deny()' - Add a deny mask to the location.
+ */
+
+static authmask_t * /* O - New mask record */
+add_deny(location_t *loc) /* I - Location to add to */
+{
+ authmask_t *temp; /* New mask record */
+
+
+ /*
+ * Range-check...
+ */
+
+ if (loc == NULL)
+ return (NULL);
+
+ /*
+ * Try to allocate memory for the record...
+ */
+
+ if (loc->num_deny == 0)
+ temp = malloc(sizeof(authmask_t));
+ else
+ temp = realloc(loc->deny, sizeof(authmask_t) * (loc->num_deny + 1));
+
+ if (temp == NULL)
+ return (NULL);
+
+ loc->deny = temp;
+ temp += loc->num_deny;
+ loc->num_deny ++;
+
+ /*
+ * Clear the mask record and return...
+ */
+
+ memset(temp, 0, sizeof(authmask_t));
+ return (temp);
+}
+
+
+#if !HAVE_LIBPAM
+/*
+ * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms,
+ * as needed.
+ */
+
+static char * /* O - Encrypted password */
+cups_crypt(const char *pw, /* I - Password string */
+ const char *salt) /* I - Salt (key) string */
+{
+ if (strncmp(salt, "$1$", 3) == 0)
+ {
+ /*
+ * Use MD5 passwords without the benefit of PAM; this is for
+ * Slackware Linux, and the algorithm was taken from the
+ * old shadow-19990827/lib/md5crypt.c source code... :(
+ */
+
+ int i; /* Looping var */
+ unsigned long n; /* Output number */
+ int pwlen; /* Length of password string */
+ const char *salt_end; /* End of "salt" data for MD5 */
+ char *ptr; /* Pointer into result string */
+ md5_state_t state; /* Primary MD5 state info */
+ md5_state_t state2; /* Secondary MD5 state info */
+ md5_byte_t digest[16]; /* MD5 digest result */
+ static char result[120]; /* Final password string */
+
+
+ /*
+ * Get the salt data between dollar signs, e.g. $1$saltdata$md5.
+ * Get a maximum of 8 characters of salt data after $1$...
+ */
+
+ for (salt_end = salt + 3; *salt_end && (salt_end - salt) < 11; salt_end ++)
+ if (*salt_end == '$')
+ break;
+
+ /*
+ * Compute the MD5 sum we need...
+ */
+
+ pwlen = strlen(pw);
+
+ md5_init(&state);
+ md5_append(&state, (md5_byte_t *)pw, pwlen);
+ md5_append(&state, (md5_byte_t *)salt, salt_end - salt);
+
+ md5_init(&state2);
+ md5_append(&state2, (md5_byte_t *)pw, pwlen);
+ md5_append(&state2, (md5_byte_t *)salt + 3, salt_end - salt - 3);
+ md5_append(&state2, (md5_byte_t *)pw, pwlen);
+ md5_finish(&state2, digest);
+
+ for (i = pwlen; i > 0; i -= 16)
+ md5_append(&state, digest, i > 16 ? 16 : i);
+
+ for (i = pwlen; i > 0; i >>= 1)
+ md5_append(&state, (md5_byte_t *)((i & 1) ? "" : pw), 1);
+
+ md5_finish(&state, digest);
+
+ for (i = 0; i < 1000; i ++)
+ {
+ md5_init(&state);
+
+ if (i & 1)
+ md5_append(&state, (md5_byte_t *)pw, pwlen);
+ else
+ md5_append(&state, digest, 16);
+
+ if (i % 3)
+ md5_append(&state, (md5_byte_t *)salt + 3, salt_end - salt - 3);
+
+ if (i % 7)
+ md5_append(&state, (md5_byte_t *)pw, pwlen);
+
+ if (i & 1)
+ md5_append(&state, digest, 16);
+ else
+ md5_append(&state, (md5_byte_t *)pw, pwlen);
+
+ md5_finish(&state, digest);
+ }
+
+ /*
+ * Copy the final sum to the result string and return...
+ */
+
+ memcpy(result, salt, salt_end - salt);
+ ptr = result + (salt_end - salt);
+ *ptr++ = '$';
+
+ for (i = 0; i < 5; i ++, ptr += 4)
+ {
+ n = (((digest[i] << 8) | digest[i + 6]) << 8);
+
+ if (i < 4)
+ n |= digest[i + 12];
+ else
+ n |= digest[5];
+
+ to64(ptr, n, 4);
+ }
+
+ to64(ptr, digest[11], 2);
+ ptr += 2;
+ *ptr = '\0';
+
+ return (result);
+ }
+ else
+ {
+ /*
+ * Use the standard crypt() function...
+ */
+
+ return (crypt(pw, salt));
+ }
+}
+#endif /* !HAVE_LIBPAM */
+
+
+#if HAVE_LIBPAM
+/*
+ * 'pam_func()' - PAM conversation function.
+ */
+
+static int /* O - Success or failure */
+pam_func(int num_msg, /* I - Number of messages */
+ const struct pam_message **msg, /* I - Messages */
+ struct pam_response **resp, /* O - Responses */
+ void *appdata_ptr) /* I - Pointer to connection */
+{
+ int i; /* Looping var */
+ struct pam_response *replies; /* Replies */
+ client_t *client; /* Pointer client connection */
+
+
+ /*
+ * Allocate memory for the responses...
+ */
+
+ if ((replies = malloc(sizeof(struct pam_response) * num_msg)) == NULL)
+ return (PAM_CONV_ERR);
+
+ /*
+ * Answer all of the messages...
+ */
+
+ DEBUG_printf(("pam_func: appdata_ptr = %p\n", appdata_ptr));
+
+#ifdef __hpux
+ /*
+ * Apparently some versions of HP-UX 11 have a broken pam_unix security
+ * module. This is a workaround...
+ */
+
+ client = auth_client;
+ (void)appdata_ptr;
+#else
+ client = (client_t *)appdata_ptr;
+#endif /* __hpux */
+
+ for (i = 0; i < num_msg; i ++)
+ {
+ DEBUG_printf(("pam_func: Message = \"%s\"\n", msg[i]->msg));
+
+ switch (msg[i]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_ON, returning \"%s\"...\n",
+ client->username));
+ replies[i].resp_retcode = PAM_SUCCESS;
+ replies[i].resp = strdup(client->username);
+ break;
+
+ case PAM_PROMPT_ECHO_OFF:
+ DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_OFF, returning \"%s\"...\n",
+ client->password));
+ replies[i].resp_retcode = PAM_SUCCESS;
+ replies[i].resp = strdup(client->password);
+ break;
+
+ case PAM_TEXT_INFO:
+ DEBUG_puts("pam_func: PAM_TEXT_INFO...");
+ replies[i].resp_retcode = PAM_SUCCESS;
+ replies[i].resp = NULL;
+ break;
+
+ case PAM_ERROR_MSG:
+ DEBUG_puts("pam_func: PAM_ERROR_MSG...");
+ replies[i].resp_retcode = PAM_SUCCESS;
+ replies[i].resp = NULL;
+ break;
+
+ default:
+ DEBUG_printf(("pam_func: Unknown PAM message %d...\n",
+ msg[i]->msg_style));
+ free(replies);
+ return (PAM_CONV_ERR);
+ }
+ }
+
+ /*
+ * Return the responses back to PAM...
+ */
+
+ *resp = replies;
+
+ return (PAM_SUCCESS);
+}
+#else
+
+
+/*
+ * 'to64()' - Base64-encode an integer value...
+ */
+
+static void
+to64(char *s, /* O - Output string */
+ unsigned long v, /* I - Value to encode */
+ int n) /* I - Number of digits */
+{
+ const char *itoa64 = "./0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+
+
+ for (; n > 0; n --, v >>= 6)
+ *s++ = itoa64[v & 0x3f];
+}
+#endif /* HAVE_LIBPAM */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/auth.h b/scheduler/auth.h
new file mode 100644
index 000000000..a4113cb5f
--- /dev/null
+++ b/scheduler/auth.h
@@ -0,0 +1,139 @@
+/*
+ * "$Id$"
+ *
+ * Authorization definitions for the Common UNIX Printing System (CUPS)
+ * scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * HTTP authorization types and levels...
+ */
+
+#define AUTH_NONE 0 /* No authentication */
+#define AUTH_BASIC 1 /* Basic authentication */
+#define AUTH_DIGEST 2 /* Digest authentication */
+#define AUTH_BASICDIGEST 3 /* Basic authentication w/passwd.md5 */
+
+#define AUTH_ANON 0 /* Anonymous access */
+#define AUTH_USER 1 /* Must have a valid username/password */
+#define AUTH_GROUP 2 /* Must also be in a named group */
+
+#define AUTH_ALLOW 0 /* Allow access */
+#define AUTH_DENY 1 /* Deny access */
+
+#define AUTH_NAME 0 /* Authorize host by name */
+#define AUTH_IP 1 /* Authorize host by IP */
+#define AUTH_INTERFACE 2 /* Authorize host by interface */
+
+#define AUTH_SATISFY_ALL 0 /* Satisfy both address and auth */
+#define AUTH_SATISFY_ANY 1 /* Satisfy either address or auth */
+
+#define AUTH_LIMIT_DELETE 1 /* Limit DELETE requests */
+#define AUTH_LIMIT_GET 2 /* Limit GET requests */
+#define AUTH_LIMIT_HEAD 4 /* Limit HEAD requests */
+#define AUTH_LIMIT_OPTIONS 8 /* Limit OPTIONS requests */
+#define AUTH_LIMIT_POST 16 /* Limit POST requests */
+#define AUTH_LIMIT_PUT 32 /* Limit PUT requests */
+#define AUTH_LIMIT_TRACE 64 /* Limit TRACE requests */
+#define AUTH_LIMIT_ALL 127 /* Limit all requests */
+
+
+/*
+ * HTTP access control structures...
+ */
+
+typedef struct
+{
+ unsigned address, /* IP address */
+ netmask; /* IP netmask */
+} ipmask_t;
+
+typedef struct
+{
+ int length; /* Length of name */
+ char *name; /* Name string */
+} namemask_t;
+
+typedef struct
+{
+ int type; /* Mask type */
+ union
+ {
+ namemask_t name; /* Host/Domain name */
+ ipmask_t ip; /* IP address/network */
+ } mask; /* Mask data */
+} authmask_t;
+
+typedef struct
+{
+ char location[HTTP_MAX_URI]; /* Location of resource */
+ int limit, /* Limit for these types of requests */
+ length, /* Length of location string */
+ order_type, /* Allow or Deny */
+ type, /* Type of authentication */
+ level, /* Access level required */
+ satisfy; /* Satisfy any or all limits? */
+ int num_names; /* Number of names */
+ char **names; /* User or group names */
+ int num_allow; /* Number of Allow lines */
+ authmask_t *allow; /* Allow lines */
+ int num_deny; /* Number of Deny lines */
+ authmask_t *deny; /* Deny lines */
+ http_encryption_t encryption; /* To encrypt or not to encrypt... */
+} location_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int NumLocations VALUE(0);
+ /* Number of authorization locations */
+VAR location_t *Locations VALUE(NULL);
+ /* Authorization locations */
+
+
+/*
+ * Prototypes...
+ */
+
+extern location_t *AddLocation(const char *location);
+extern void AddName(location_t *loc, char *name);
+extern void AllowHost(location_t *loc, char *name);
+extern void AllowIP(location_t *loc, unsigned address,
+ unsigned netmask);
+extern int CheckAuth(unsigned ip, char *name, int namelen,
+ int num_masks, authmask_t *masks);
+extern location_t *CopyLocation(location_t **loc);
+extern void DeleteAllLocations(void);
+extern void DenyHost(location_t *loc, char *name);
+extern void DenyIP(location_t *loc, unsigned address,
+ unsigned netmask);
+extern location_t *FindBest(const char *path, http_state_t state);
+extern location_t *FindLocation(const char *location);
+extern char *GetMD5Passwd(const char *username, const char *group,
+ char passwd[33]);
+extern http_status_t IsAuthorized(client_t *con);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/banners.c b/scheduler/banners.c
new file mode 100644
index 000000000..8c17c037d
--- /dev/null
+++ b/scheduler/banners.c
@@ -0,0 +1,215 @@
+/*
+ * "$Id$"
+ *
+ * Banner routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddBanner() - Add a banner to the array.
+ * FindBanner() - Find a named banner.
+ * LoadBanners() - Load all available banner files...
+ * compare() - Compare two banners.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int compare(const banner_t *b0, const banner_t *b1);
+
+
+/*
+ * 'AddBanner()' - Add a banner to the array.
+ */
+
+void
+AddBanner(const char *name, /* I - Name of banner */
+ const char *filename) /* I - Filename for banner */
+{
+ mime_type_t *filetype; /* Filetype */
+ banner_t *temp; /* New banner data */
+
+
+ /*
+ * See what the filetype is...
+ */
+
+ if ((filetype = mimeFileType(MimeDatabase, filename, NULL)) == NULL)
+ {
+ LogMessage(L_WARN, "AddBanner: Banner \"%s\" is of an unknown file type - skipping!",
+ name);
+ return;
+ }
+
+ /*
+ * Allocate memory...
+ */
+
+ if (NumBanners == 0)
+ temp = malloc(sizeof(banner_t));
+ else
+ temp = realloc(Banners, sizeof(banner_t) * (NumBanners + 1));
+
+ if (temp == NULL)
+ {
+ LogMessage(L_ERROR, "AddBanner: Ran out of memory adding a banner!");
+ return;
+ }
+
+ /*
+ * Copy the new banner data over...
+ */
+
+ Banners = temp;
+ temp += NumBanners;
+ NumBanners ++;
+
+ memset(temp, 0, sizeof(banner_t));
+ strlcpy(temp->name, name, sizeof(temp->name));
+ temp->filetype = filetype;
+}
+
+
+/*
+ * 'FindBanner()' - Find a named banner.
+ */
+
+banner_t * /* O - Pointer to banner or NULL */
+FindBanner(const char *name) /* I - Name of banner */
+{
+ banner_t key; /* Search key */
+
+
+ strlcpy(key.name, name, sizeof(key.name));
+
+ return ((banner_t *)bsearch(&key, Banners, NumBanners, sizeof(banner_t),
+ (int (*)(const void *, const void *))compare));
+}
+
+
+/*
+ * 'LoadBanners()' - Load all available banner files...
+ */
+
+void
+LoadBanners(const char *d) /* I - Directory to search */
+{
+ DIR *dir; /* Directory pointer */
+ DIRENT *dent; /* Directory entry */
+ char filename[1024], /* Name of banner */
+ *ext; /* Pointer to extension */
+ struct stat fileinfo; /* File information */
+
+
+ /*
+ * Free old banner info...
+ */
+
+ if (NumBanners)
+ {
+ free(Banners);
+ NumBanners = 0;
+ }
+
+ /*
+ * Try opening the banner directory...
+ */
+
+ if ((dir = opendir(d)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadBanners: Unable to open banner directory \"%s\": %s",
+ d, strerror(errno));
+ return;
+ }
+
+ /*
+ * Read entries, skipping directories and backup files.
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ /*
+ * Check the file to make sure it isn't a directory or a backup
+ * file of some sort...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", d, dent->d_name);
+
+ if (stat(filename, &fileinfo))
+ {
+ LogMessage(L_WARN, "LoadBanners: Unable to stat \"%s\" banner: %s",
+ dent->d_name, strerror(errno));
+ continue;
+ }
+
+ if (S_ISDIR(fileinfo.st_mode))
+ continue;
+
+ if (dent->d_name[0] == '~')
+ continue;
+
+ if ((ext = strrchr(dent->d_name, '.')) != NULL)
+ if (strcmp(ext, ".bck") == 0 ||
+ strcmp(ext, ".bak") == 0 ||
+ strcmp(ext, ".sav") == 0)
+ continue;
+
+ /*
+ * Must be a valid file; add it!
+ */
+
+ AddBanner(dent->d_name, filename);
+ }
+
+ /*
+ * Close the directory and sort as needed...
+ */
+
+ closedir(dir);
+
+ if (NumBanners > 1)
+ qsort(Banners, NumBanners, sizeof(banner_t),
+ (int (*)(const void *, const void *))compare);
+}
+
+
+/*
+ * 'compare()' - Compare two banners.
+ */
+
+static int /* O - -1 if name0 < name1, etc. */
+compare(const banner_t *b0, /* I - First banner */
+ const banner_t *b1) /* I - Second banner */
+{
+ return (strcasecmp(b0->name, b1->name));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/banners.h b/scheduler/banners.h
new file mode 100644
index 000000000..4d4c97c15
--- /dev/null
+++ b/scheduler/banners.h
@@ -0,0 +1,57 @@
+/*
+ * "$Id$"
+ *
+ * Banner definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Banner information structure...
+ */
+
+typedef struct
+{
+ char name[256]; /* Name of banner */
+ mime_type_t *filetype; /* Filetype for banner */
+} banner_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int NumBanners VALUE(0);
+ /* Number of banner files available */
+VAR banner_t *Banners VALUE(NULL);
+ /* Available banner files */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void AddBanner(const char *name, const char *filename);
+extern banner_t *FindBanner(const char *name);
+extern void LoadBanners(const char *d);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/cert.c b/scheduler/cert.c
new file mode 100644
index 000000000..bdd7d43d0
--- /dev/null
+++ b/scheduler/cert.c
@@ -0,0 +1,297 @@
+/*
+ * "$Id$"
+ *
+ * Authentication certificate routines for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddCert() - Add a certificate.
+ * DeleteCert() - Delete a single certificate.
+ * DeleteAllCerts() - Delete all certificates...
+ * FindCert() - Find a certificate.
+ * InitCerts() - Initialize the certificate "system" and root
+ * certificate.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <grp.h>
+
+
+/*
+ * 'AddCert()' - Add a certificate.
+ */
+
+void
+AddCert(int pid, /* I - Process ID */
+ const char *username) /* I - Username */
+{
+ int i; /* Looping var */
+ cert_t *cert; /* Current certificate */
+ int fd; /* Certificate file */
+ char filename[1024]; /* Certificate filename */
+ struct group *grp; /* System group */
+ static const char hex[] = "0123456789ABCDEF";
+ /* Hex constants... */
+
+
+ LogMessage(L_DEBUG2, "AddCert: adding certificate for pid %d", pid);
+
+ /*
+ * Allocate memory for the certificate...
+ */
+
+ if ((cert = calloc(sizeof(cert_t), 1)) == NULL)
+ return;
+
+ /*
+ * Fill in the certificate information...
+ */
+
+ cert->pid = pid;
+ strlcpy(cert->username, username, sizeof(cert->username));
+
+ for (i = 0; i < 32; i ++)
+ cert->certificate[i] = hex[random() & 15];
+
+ /*
+ * Save the certificate to a file readable only by the User and Group
+ * (or root and SystemGroup for PID == 0)...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, pid);
+ unlink(filename);
+
+ if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
+ {
+ LogMessage(L_ERROR, "AddCert: Unable to create certificate file %s - %s",
+ filename, strerror(errno));
+ free(cert);
+ return;
+ }
+
+ if (pid == 0)
+ {
+ /*
+ * Root certificate...
+ */
+
+ fchmod(fd, 0440);
+
+ if ((grp = getgrnam(SystemGroups[0])) == NULL)
+ fchown(fd, RunUser, 0);
+ else
+ fchown(fd, RunUser, grp->gr_gid);
+
+ endgrent();
+
+ RootCertTime = time(NULL);
+ }
+ else
+ {
+ /*
+ * CGI certificate...
+ */
+
+ fchmod(fd, 0400);
+ fchown(fd, User, Group);
+ }
+
+ DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username,
+ cert->certificate));
+
+ write(fd, cert->certificate, strlen(cert->certificate));
+ close(fd);
+
+ /*
+ * Insert the certificate at the front of the list...
+ */
+
+ cert->next = Certs;
+ Certs = cert;
+}
+
+
+/*
+ * 'DeleteCert()' - Delete a single certificate.
+ */
+
+void
+DeleteCert(int pid) /* I - Process ID */
+{
+ cert_t *cert, /* Current certificate */
+ *prev; /* Previous certificate */
+ char filename[1024]; /* Certificate file */
+
+
+ for (prev = NULL, cert = Certs; cert != NULL; prev = cert, cert = cert->next)
+ if (cert->pid == pid)
+ {
+ /*
+ * Remove this certificate from the list...
+ */
+
+ LogMessage(L_DEBUG2, "DeleteCert: removing certificate for pid %d", pid);
+
+ DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid,
+ cert->username, cert->certificate));
+
+ if (prev == NULL)
+ Certs = cert->next;
+ else
+ prev->next = cert->next;
+
+ free(cert);
+
+ /*
+ * Delete the file and return...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, pid);
+ if (unlink(filename))
+ LogMessage(L_ERROR, "DeleteCert: Unable to remove %s!\n", filename);
+
+ return;
+ }
+}
+
+
+/*
+ * 'DeleteAllCerts()' - Delete all certificates...
+ */
+
+void
+DeleteAllCerts(void)
+{
+ cert_t *cert, /* Current certificate */
+ *next; /* Next certificate */
+ char filename[1024]; /* Certificate file */
+
+
+ /*
+ * Loop through each certificate, deleting them...
+ */
+
+ for (cert = Certs; cert != NULL; cert = next)
+ {
+ /*
+ * Delete the file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/certs/%d", ServerRoot, cert->pid);
+ if (unlink(filename))
+ LogMessage(L_ERROR, "DeleteAllCerts: Unable to remove %s!\n", filename);
+
+ /*
+ * Free memory...
+ */
+
+ next = cert->next;
+ free(cert);
+ }
+
+ Certs = NULL;
+}
+
+
+/*
+ * 'FindCert()' - Find a certificate.
+ */
+
+const char * /* O - Matching username or NULL */
+FindCert(const char *certificate) /* I - Certificate */
+{
+ cert_t *cert; /* Current certificate */
+
+
+ DEBUG_printf(("FindCert(certificate=%s)\n", certificate));
+ for (cert = Certs; cert != NULL; cert = cert->next)
+ if (strcasecmp(certificate, cert->certificate) == 0)
+ {
+ DEBUG_printf((" returning %s...\n", cert->username));
+ return (cert->username);
+ }
+
+ DEBUG_puts(" certificate not found!");
+
+ return (NULL);
+}
+
+
+/*
+ * 'InitCerts()' - Initialize the certificate "system" and root certificate.
+ */
+
+void
+InitCerts(void)
+{
+ cups_file_t *fp; /* /dev/random file */
+ unsigned seed; /* Seed for random number generator */
+ struct timeval tod; /* Time of day */
+
+
+ /*
+ * Initialize the random number generator using the random device or
+ * the current time, as available...
+ */
+
+ if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
+ {
+ /*
+ * Get the time in usecs and use it as the initial seed...
+ */
+
+ gettimeofday(&tod, NULL);
+
+ seed = (unsigned)(tod.tv_sec + tod.tv_usec);
+ }
+ else
+ {
+ /*
+ * Read 4 random characters from the random device and use
+ * them as the seed...
+ */
+
+ seed = cupsFileGetChar(fp);
+ seed = (seed << 8) | cupsFileGetChar(fp);
+ seed = (seed << 8) | cupsFileGetChar(fp);
+ seed = (seed << 8) | cupsFileGetChar(fp);
+
+ cupsFileClose(fp);
+ }
+
+ srandom(seed);
+
+ /*
+ * Create a root certificate and return...
+ */
+
+ AddCert(0, "root");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/cert.h b/scheduler/cert.h
new file mode 100644
index 000000000..4265f1b11
--- /dev/null
+++ b/scheduler/cert.h
@@ -0,0 +1,60 @@
+/*
+ * "$Id$"
+ *
+ * Authentication certificate definitions for the Common UNIX
+ * Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Certificate structure...
+ */
+
+typedef struct cert_str
+{
+ struct cert_str *next; /* Next certificate in list */
+ int pid; /* Process ID (0 for root certificate) */
+ char certificate[33];/* 32 hex characters, or 128 bits */
+ char username[33]; /* Authenticated username */
+} cert_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR cert_t *Certs; /* List of certificates */
+VAR time_t RootCertTime; /* Root certificate update time */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void AddCert(int pid, const char *username);
+extern void DeleteCert(int pid);
+extern void DeleteAllCerts(void);
+extern const char *FindCert(const char *certificate);
+extern void InitCerts(void);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/classes.c b/scheduler/classes.c
new file mode 100644
index 000000000..e329b536c
--- /dev/null
+++ b/scheduler/classes.c
@@ -0,0 +1,725 @@
+/*
+ * "$Id$"
+ *
+ * Printer class routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddClass() - Add a class to the system.
+ * AddPrinterToClass() - Add a printer to a class...
+ * DeletePrinterFromClass() - Delete a printer from a class.
+ * DeletePrinterFromClasses() - Delete a printer from all classes.
+ * DeleteAllClasses() - Remove all classes from the system.
+ * FindAvailablePrinter() - Find an available printer in a class.
+ * FindClass() - Find the named class.
+ * LoadAllClasses() - Load classes from the classes.conf file.
+ * SaveAllClasses() - Save classes to the classes.conf file.
+ * UpdateImplicitClasses() - Update the accepting state of implicit
+ * classes.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * 'AddClass()' - Add a class to the system.
+ */
+
+printer_t * /* O - New class */
+AddClass(const char *name) /* I - Name of class */
+{
+ printer_t *c; /* New class */
+
+
+ /*
+ * Add the printer and set the type to "class"...
+ */
+
+ if ((c = AddPrinter(name)) != NULL)
+ {
+ /*
+ * Change from a printer to a class...
+ */
+
+ c->type = CUPS_PRINTER_CLASS;
+ SetStringf(&c->uri, "ipp://%s:%d/classes/%s", ServerName,
+ ntohs(Listeners[0].address.sin_port), name);
+ }
+
+ return (c);
+}
+
+
+/*
+ * 'AddPrinterToClass()' - Add a printer to a class...
+ */
+
+void
+AddPrinterToClass(printer_t *c, /* I - Class to add to */
+ printer_t *p) /* I - Printer to add */
+{
+ int i; /* Looping var */
+ printer_t **temp; /* Pointer to printer array */
+
+
+ /*
+ * See if this printer is already a member of the class...
+ */
+
+ for (i = 0; i < c->num_printers; i ++)
+ if (c->printers[i] == p)
+ return;
+
+ /*
+ * Allocate memory as needed...
+ */
+
+ if (c->num_printers == 0)
+ temp = malloc(sizeof(printer_t *));
+ else
+ temp = realloc(c->printers, sizeof(printer_t *) * (c->num_printers + 1));
+
+ if (temp == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to add printer %s to class %s!",
+ p->name, c->name);
+ return;
+ }
+
+ /*
+ * Add the printer to the end of the array and update the number of printers.
+ */
+
+ c->printers = temp;
+ temp += c->num_printers;
+ c->num_printers ++;
+
+ *temp = p;
+
+ /*
+ * Update the IPP attributes...
+ */
+
+ SetPrinterAttrs(c);
+}
+
+
+/*
+ * 'DeletePrinterFromClass()' - Delete a printer from a class.
+ */
+
+void
+DeletePrinterFromClass(printer_t *c, /* I - Class to delete from */
+ printer_t *p) /* I - Printer to delete */
+{
+ int i; /* Looping var */
+ cups_ptype_t type; /* Class type */
+
+
+ /*
+ * See if the printer is in the class...
+ */
+
+ for (i = 0; i < c->num_printers; i ++)
+ if (p == c->printers[i])
+ break;
+
+ /*
+ * If it is, remove it from the list...
+ */
+
+ if (i < c->num_printers)
+ {
+ /*
+ * Yes, remove the printer...
+ */
+
+ c->num_printers --;
+ if (i < c->num_printers)
+ memcpy(c->printers + i, c->printers + i + 1,
+ (c->num_printers - i) * sizeof(printer_t *));
+ }
+
+ /*
+ * Recompute the printer type mask as needed...
+ */
+
+ if (c->num_printers > 0)
+ {
+ type = c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT);
+ c->type = ~CUPS_PRINTER_REMOTE;
+
+ for (i = 0; i < c->num_printers; i ++)
+ c->type &= c->printers[i]->type;
+
+ c->type |= type;
+
+ /*
+ * Update the IPP attributes...
+ */
+
+ SetPrinterAttrs(c);
+ }
+}
+
+
+/*
+ * 'DeletePrinterFromClasses()' - Delete a printer from all classes.
+ */
+
+void
+DeletePrinterFromClasses(printer_t *p) /* I - Printer to delete */
+{
+ printer_t *c, /* Pointer to current class */
+ *next; /* Pointer to next class */
+
+
+ /*
+ * Loop through the printer/class list and remove the printer
+ * from each class listed...
+ */
+
+ for (c = Printers; c != NULL; c = next)
+ {
+ next = c->next;
+
+ if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ DeletePrinterFromClass(c, p);
+ }
+
+ /*
+ * Then clean out any empty classes...
+ */
+
+ for (c = Printers; c != NULL; c = next)
+ {
+ next = c->next;
+
+ if ((c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) &&
+ c->num_printers == 0)
+ DeletePrinter(c, 1);
+ }
+}
+
+
+/*
+ * 'DeleteAllClasses()' - Remove all classes from the system.
+ */
+
+void
+DeleteAllClasses(void)
+{
+ printer_t *c, /* Pointer to current printer/class */
+ *next; /* Pointer to next printer in list */
+
+
+ for (c = Printers; c != NULL; c = next)
+ {
+ next = c->next;
+
+ if (c->type & CUPS_PRINTER_CLASS)
+ DeletePrinter(c, 0);
+ }
+}
+
+
+/*
+ * 'FindAvailablePrinter()' - Find an available printer in a class.
+ */
+
+printer_t * /* O - Available printer or NULL */
+FindAvailablePrinter(const char *name) /* I - Class to check */
+{
+ int i; /* Looping var */
+ printer_t *c; /* Printer class */
+
+
+ /*
+ * Find the class...
+ */
+
+ if ((c = FindClass(name)) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to find class \"%s\"!", name);
+ return (NULL);
+ }
+
+ /*
+ * Loop through the printers in the class and return the first idle
+ * printer... We keep track of the last printer that we used so that
+ * a "round robin" type of scheduling is realized (otherwise the first
+ * server might be saturated with print jobs...)
+ *
+ * Thanks to Joel Fredrikson for helping us get this right!
+ */
+
+ for (i = c->last_printer + 1; ; i ++)
+ {
+ if (i >= c->num_printers)
+ i = 0;
+
+ if (c->printers[i]->accepting &&
+ (c->printers[i]->state == IPP_PRINTER_IDLE ||
+ ((c->printers[i]->type & CUPS_PRINTER_REMOTE) && !c->printers[i]->job)))
+ {
+ c->last_printer = i;
+ return (c->printers[i]);
+ }
+
+ if (i == c->last_printer)
+ break;
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'FindClass()' - Find the named class.
+ */
+
+printer_t * /* O - Matching class or NULL */
+FindClass(const char *name) /* I - Name of class */
+{
+ printer_t *c; /* Current class/printer */
+ int diff; /* Difference */
+
+
+ for (c = Printers; c != NULL; c = c->next)
+ if ((diff = strcasecmp(name, c->name)) == 0 &&
+ (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
+ return (c); /* name == c->name */
+ else if (diff < 0) /* name < c->name */
+ return (NULL);
+
+ return (NULL);
+}
+
+
+/*
+ * 'LoadAllClasses()' - Load classes from the classes.conf file.
+ */
+
+void
+LoadAllClasses(void)
+{
+ cups_file_t *fp; /* classes.conf file */
+ int linenum; /* Current line number */
+ int len; /* Length of line */
+ char line[1024], /* Line from file */
+ name[256], /* Parameter name */
+ *nameptr, /* Pointer into name */
+ *value, /* Pointer to value */
+ *valueptr; /* Pointer into value */
+ printer_t *p, /* Current printer class */
+ *temp; /* Temporary pointer to printer */
+
+
+ /*
+ * Open the classes.conf file...
+ */
+
+ snprintf(line, sizeof(line), "%s/classes.conf", ServerRoot);
+ if ((fp = cupsFileOpen(line, "r")) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllClasses: Unable to open %s - %s", line,
+ strerror(errno));
+ return;
+ }
+
+ /*
+ * Read class configurations until we hit EOF...
+ */
+
+ linenum = 0;
+ p = NULL;
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ linenum ++;
+
+ /*
+ * Skip comment lines...
+ */
+
+ if (line[0] == '#')
+ continue;
+
+ /*
+ * Strip trailing whitespace, if any...
+ */
+
+ len = strlen(line);
+
+ while (len > 0 && isspace(line[len - 1] & 255))
+ {
+ len --;
+ line[len] = '\0';
+ }
+
+ /*
+ * Extract the name from the beginning of the line...
+ */
+
+ for (value = line; isspace(*value & 255); value ++);
+
+ for (nameptr = name; *value != '\0' && !isspace(*value & 255) &&
+ nameptr < (name + sizeof(name) - 1);)
+ *nameptr++ = *value++;
+ *nameptr = '\0';
+
+ while (isspace(*value & 255))
+ value ++;
+
+ if (name[0] == '\0')
+ continue;
+
+ /*
+ * Decode the directive...
+ */
+
+ if (strcmp(name, "<Class") == 0 ||
+ strcmp(name, "<DefaultClass") == 0)
+ {
+ /*
+ * <Class name> or <DefaultClass name>
+ */
+
+ if (line[len - 1] == '>' && p == NULL)
+ {
+ line[len - 1] = '\0';
+
+ LogMessage(L_DEBUG, "LoadAllClasses: Loading class %s...", value);
+
+ p = AddClass(value);
+ p->accepting = 1;
+ p->state = IPP_PRINTER_IDLE;
+
+ if (strcmp(name, "<DefaultClass") == 0)
+ DefaultPrinter = p;
+ }
+ else
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of classes.conf.",
+ linenum);
+ return;
+ }
+ }
+ else if (strcmp(name, "</Class>") == 0)
+ {
+ if (p != NULL)
+ {
+ SetPrinterAttrs(p);
+ p = NULL;
+ }
+ else
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of classes.conf.",
+ linenum);
+ return;
+ }
+ }
+ else if (p == NULL)
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of classes.conf.",
+ linenum);
+ return;
+ }
+
+ else if (strcmp(name, "Info") == 0)
+ SetString(&p->info, value);
+ else if (strcmp(name, "Location") == 0)
+ SetString(&p->location, value);
+ else if (strcmp(name, "Printer") == 0)
+ {
+ if ((temp = FindPrinter(value)) == NULL)
+ {
+ LogMessage(L_WARN, "Unknown printer %s on line %d of classes.conf.",
+ value, linenum);
+
+ /*
+ * Add the missing remote printer...
+ */
+
+ if ((temp = AddPrinter(value)) != NULL)
+ {
+ SetString(&temp->make_model, "Remote Printer on unknown");
+
+ temp->state = IPP_PRINTER_STOPPED;
+ temp->type |= CUPS_PRINTER_REMOTE;
+ temp->browse_time = 2147483647;
+
+ SetString(&temp->location, "Location Unknown");
+ SetString(&temp->info, "No Information Available");
+ temp->hostname[0] = '\0';
+
+ SetPrinterAttrs(temp);
+ }
+ }
+
+ if (temp)
+ AddPrinterToClass(p, temp);
+ }
+ else if (strcmp(name, "State") == 0)
+ {
+ /*
+ * Set the initial queue state...
+ */
+
+ if (strcasecmp(value, "idle") == 0)
+ p->state = IPP_PRINTER_IDLE;
+ else if (strcasecmp(value, "stopped") == 0)
+ p->state = IPP_PRINTER_STOPPED;
+ }
+ else if (strcmp(name, "StateMessage") == 0)
+ {
+ /*
+ * Set the initial queue state message...
+ */
+
+ while (isspace(*value & 255))
+ value ++;
+
+ strlcpy(p->state_message, value, sizeof(p->state_message));
+ }
+ else if (strcmp(name, "Accepting") == 0)
+ {
+ /*
+ * Set the initial accepting state...
+ */
+
+ if (strcasecmp(value, "yes") == 0)
+ p->accepting = 1;
+ else
+ p->accepting = 0;
+ }
+ else if (strcmp(name, "JobSheets") == 0)
+ {
+ /*
+ * Set the initial job sheets...
+ */
+
+ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (*valueptr)
+ *valueptr++ = '\0';
+
+ SetString(&p->job_sheets[0], value);
+
+ while (isspace(*valueptr & 255))
+ valueptr ++;
+
+ if (*valueptr)
+ {
+ for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (*valueptr)
+ *valueptr++ = '\0';
+
+ SetString(&p->job_sheets[1], value);
+ }
+ }
+ else if (strcmp(name, "AllowUser") == 0)
+ {
+ p->deny_users = 0;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "DenyUser") == 0)
+ {
+ p->deny_users = 1;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "QuotaPeriod") == 0)
+ p->quota_period = atoi(value);
+ else if (strcmp(name, "PageLimit") == 0)
+ p->page_limit = atoi(value);
+ else if (strcmp(name, "KLimit") == 0)
+ p->k_limit = atoi(value);
+ else
+ {
+ /*
+ * Something else we don't understand...
+ */
+
+ LogMessage(L_ERROR, "Unknown configuration directive %s on line %d of classes.conf.",
+ name, linenum);
+ }
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'SaveAllClasses()' - Save classes to the classes.conf file.
+ */
+
+void
+SaveAllClasses(void)
+{
+ cups_file_t *fp; /* classes.conf file */
+ char temp[1024]; /* Temporary string */
+ char backup[1024]; /* classes.conf.O file */
+ printer_t *pclass; /* Current printer class */
+ int i; /* Looping var */
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
+
+
+ /*
+ * Create the classes.conf file...
+ */
+
+ snprintf(temp, sizeof(temp), "%s/classes.conf", ServerRoot);
+ snprintf(backup, sizeof(backup), "%s/classes.conf.O", ServerRoot);
+
+ if (rename(temp, backup))
+ LogMessage(L_ERROR, "Unable to backup classes.conf - %s", strerror(errno));
+
+ if ((fp = cupsFileOpen(temp, "w")) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to save classes.conf - %s", strerror(errno));
+
+ if (rename(backup, temp))
+ LogMessage(L_ERROR, "Unable to restore classes.conf - %s", strerror(errno));
+ return;
+ }
+ else
+ LogMessage(L_INFO, "Saving classes.conf...");
+
+ /*
+ * Restrict access to the file...
+ */
+
+ fchown(cupsFileNumber(fp), RunUser, Group);
+ fchmod(cupsFileNumber(fp), ConfigFilePerm);
+
+ /*
+ * Write a small header to the file...
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+ strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate);
+
+ cupsFilePuts(fp, "# Class configuration file for " CUPS_SVERSION "\n");
+ cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
+
+ /*
+ * Write each local class known to the system...
+ */
+
+ for (pclass = Printers; pclass != NULL; pclass = pclass->next)
+ {
+ /*
+ * Skip remote destinations and regular printers...
+ */
+
+ if ((pclass->type & CUPS_PRINTER_REMOTE) ||
+ (pclass->type & CUPS_PRINTER_IMPLICIT) ||
+ !(pclass->type & CUPS_PRINTER_CLASS))
+ continue;
+
+ /*
+ * Write printers as needed...
+ */
+
+ if (pclass == DefaultPrinter)
+ cupsFilePrintf(fp, "<DefaultClass %s>\n", pclass->name);
+ else
+ cupsFilePrintf(fp, "<Class %s>\n", pclass->name);
+
+ if (pclass->info)
+ cupsFilePrintf(fp, "Info %s\n", pclass->info);
+
+ if (pclass->location)
+ cupsFilePrintf(fp, "Location %s\n", pclass->location);
+
+ if (pclass->state == IPP_PRINTER_STOPPED)
+ {
+ cupsFilePuts(fp, "State Stopped\n");
+ cupsFilePrintf(fp, "StateMessage %s\n", pclass->state_message);
+ }
+ else
+ cupsFilePuts(fp, "State Idle\n");
+
+ if (pclass->accepting)
+ cupsFilePuts(fp, "Accepting Yes\n");
+ else
+ cupsFilePuts(fp, "Accepting No\n");
+
+ cupsFilePrintf(fp, "JobSheets %s %s\n", pclass->job_sheets[0],
+ pclass->job_sheets[1]);
+
+ for (i = 0; i < pclass->num_printers; i ++)
+ cupsFilePrintf(fp, "Printer %s\n", pclass->printers[i]->name);
+
+ cupsFilePrintf(fp, "QuotaPeriod %d\n", pclass->quota_period);
+ cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit);
+ cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit);
+
+ for (i = 0; i < pclass->num_users; i ++)
+ cupsFilePrintf(fp, "%sUser %s\n", pclass->deny_users ? "Deny" : "Allow",
+ pclass->users[i]);
+
+ cupsFilePuts(fp, "</Class>\n");
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'UpdateImplicitClasses()' - Update the accepting state of implicit classes.
+ */
+
+void
+UpdateImplicitClasses(void)
+{
+ int i; /* Looping var */
+ printer_t *pclass; /* Current class */
+ int accepting; /* printer-is-accepting-jobs value */
+
+
+ for (pclass = Printers; pclass; pclass = pclass->next)
+ if (pclass->type & CUPS_PRINTER_IMPLICIT)
+ {
+ /*
+ * Implicit class, loop through the printers to come up with a
+ * composite state...
+ */
+
+ for (i = 0, accepting = 0; i < pclass->num_printers; i ++)
+ if ((accepting |= pclass->printers[i]->accepting) != 0)
+ break;
+
+ pclass->accepting = accepting;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/classes.h b/scheduler/classes.h
new file mode 100644
index 000000000..62f5031dd
--- /dev/null
+++ b/scheduler/classes.h
@@ -0,0 +1,44 @@
+/*
+ * "$Id$"
+ *
+ * Printer class definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+
+/*
+ * Prototypes...
+ */
+
+extern printer_t *AddClass(const char *name);
+extern void AddPrinterToClass(printer_t *c, printer_t *p);
+extern void DeletePrinterFromClass(printer_t *c, printer_t *p);
+extern void DeletePrinterFromClasses(printer_t *p);
+extern void DeleteAllClasses(void);
+extern printer_t *FindAvailablePrinter(const char *name);
+extern printer_t *FindClass(const char *name);
+extern void LoadAllClasses(void);
+extern void SaveAllClasses(void);
+extern void UpdateImplicitClasses(void);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/client.c b/scheduler/client.c
new file mode 100644
index 000000000..fe2ba0c2f
--- /dev/null
+++ b/scheduler/client.c
@@ -0,0 +1,3467 @@
+/*
+ * "$Id$"
+ *
+ * Client routines for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AcceptClient() - Accept a new client.
+ * CloseAllClients() - Close all remote clients immediately.
+ * CloseClient() - Close a remote client.
+ * EncryptClient() - Enable encryption for the client...
+ * IsCGI() - Is the resource a CGI script/program?
+ * ReadClient() - Read data from a client.
+ * SendCommand() - Send output from a command via HTTP.
+ * SendError() - Send an error message via HTTP.
+ * SendFile() - Send a file via HTTP.
+ * SendHeader() - Send an HTTP request.
+ * UpdateCGI() - Read status messages from CGI scripts and programs.
+ * WriteClient() - Write data to a client as needed.
+ * check_if_modified() - Decode an "If-Modified-Since" line.
+ * decode_auth() - Decode an authorization string.
+ * get_file() - Get a filename and state info.
+ * install_conf_file() - Install a configuration file.
+ * is_path_absolute() - Is a path absolute and free of relative elements.
+ * pipe_command() - Pipe the output of a command to the remote client.
+ * CDSAReadFunc() - Read function for CDSA decryption code.
+ * CDSAWriteFunc() - Write function for CDSA encryption code.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/http-private.h>
+#include "cupsd.h"
+#include <grp.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int check_if_modified(client_t *con,
+ struct stat *filestats);
+static void decode_auth(client_t *con);
+static char *get_file(client_t *con, struct stat *filestats,
+ char *filename, int len);
+static http_status_t install_conf_file(client_t *con);
+static int is_path_absolute(const char *path);
+static int pipe_command(client_t *con, int infile, int *outfile,
+ char *command, char *options);
+
+#ifdef HAVE_CDSASSL
+static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data,
+ size_t *dataLength);
+static OSStatus CDSAWriteFunc(SSLConnectionRef connection,
+ const void *data, size_t *dataLength);
+#endif /* HAVE_CDSASSL */
+
+
+/*
+ * 'AcceptClient()' - Accept a new client.
+ */
+
+void
+AcceptClient(listener_t *lis) /* I - Listener socket */
+{
+ int i; /* Looping var */
+ int count; /* Count of connections on a host */
+ int val; /* Parameter value */
+ client_t *con; /* New client pointer */
+ unsigned address;/* Address of client */
+ struct hostent *host; /* Host entry for address */
+ static time_t last_dos = 0;
+ /* Time of last DoS attack */
+
+
+ LogMessage(L_DEBUG2, "AcceptClient(lis=%p) %d NumClients = %d",
+ lis, lis->fd, NumClients);
+
+ /*
+ * Make sure we don't have a full set of clients already...
+ */
+
+ if (NumClients == MaxClients)
+ return;
+
+ /*
+ * Get a pointer to the next available client...
+ */
+
+ con = Clients + NumClients;
+
+ memset(con, 0, sizeof(client_t));
+ con->http.activity = time(NULL);
+ con->file = -1;
+
+ /*
+ * Accept the client and get the remote address...
+ */
+
+ val = sizeof(struct sockaddr_in);
+
+ if ((con->http.fd = accept(lis->fd, (struct sockaddr *)&(con->http.hostaddr),
+ &val)) < 0)
+ {
+ LogMessage(L_ERROR, "Unable to accept client connection - %s.",
+ strerror(errno));
+ return;
+ }
+
+ con->http.hostaddr.sin_port = lis->address.sin_port;
+
+ /*
+ * Check the number of clients on the same address...
+ */
+
+ for (i = 0, count = 0; i < NumClients; i ++)
+ if (memcmp(&(Clients[i].http.hostaddr), &(con->http.hostaddr),
+ sizeof(con->http.hostaddr)) == 0)
+ {
+ count ++;
+ if (count >= MaxClientsPerHost)
+ break;
+ }
+
+ if (count >= MaxClientsPerHost)
+ {
+ if ((time(NULL) - last_dos) >= 60)
+ {
+ last_dos = time(NULL);
+ LogMessage(L_WARN, "Possible DoS attack - more than %d clients connecting from %s!",
+ MaxClientsPerHost, Clients[i].http.hostname);
+ }
+
+#ifdef WIN32
+ closesocket(con->http.fd);
+#else
+ close(con->http.fd);
+#endif /* WIN32 */
+
+ return;
+ }
+
+ /*
+ * Get the hostname or format the IP address as needed...
+ */
+
+ address = ntohl(con->http.hostaddr.sin_addr.s_addr);
+
+ if (HostNameLookups)
+#ifndef __sgi
+ host = gethostbyaddr((char *)&(con->http.hostaddr.sin_addr),
+ sizeof(struct in_addr), AF_INET);
+#else
+ host = gethostbyaddr(&(con->http.hostaddr.sin_addr),
+ sizeof(struct in_addr), AF_INET);
+#endif /* !__sgi */
+ else
+ host = NULL;
+
+ if (address == 0x7f000001)
+ {
+ /*
+ * Map accesses from the loopback interface to "localhost"...
+ */
+
+ strlcpy(con->http.hostname, "localhost", sizeof(con->http.hostname));
+ }
+ else if (con->http.hostaddr.sin_addr.s_addr == ServerAddr.sin_addr.s_addr)
+ {
+ /*
+ * Map accesses from the same host to the server name.
+ */
+
+ strlcpy(con->http.hostname, ServerName, sizeof(con->http.hostname));
+ }
+ else if (host == NULL)
+ {
+ sprintf(con->http.hostname, "%d.%d.%d.%d", (address >> 24) & 255,
+ (address >> 16) & 255, (address >> 8) & 255, address & 255);
+
+ if (HostNameLookups == 2)
+ {
+ /*
+ * Can't have an unresolved IP address with double-lookups enabled...
+ */
+
+#ifdef WIN32
+ closesocket(con->http.fd);
+#else
+ close(con->http.fd);
+#endif /* WIN32 */
+
+ LogMessage(L_WARN, "Name lookup failed - connection from %s closed!",
+ con->http.hostname);
+ return;
+ }
+ }
+ else
+ strlcpy(con->http.hostname, host->h_name, sizeof(con->http.hostname));
+
+ if (HostNameLookups == 2)
+ {
+ /*
+ * Do double lookups as needed...
+ */
+
+ if ((host = httpGetHostByName(con->http.hostname)) != NULL)
+ {
+ /*
+ * See if the hostname maps to the IP address...
+ */
+
+ if (host->h_length != 4 || host->h_addrtype != AF_INET)
+ {
+ /*
+ * Not an IPv4 address...
+ */
+
+ host = NULL;
+ }
+ else
+ {
+ /*
+ * Compare all of the addresses against this one...
+ */
+
+ for (i = 0; host->h_addr_list[i]; i ++)
+ if (memcmp(&(con->http.hostaddr.sin_addr), host->h_addr_list[i], 4) == 0)
+ break;
+
+ if (!host->h_addr_list[i])
+ host = NULL;
+ }
+ }
+
+ if (host == NULL)
+ {
+ /*
+ * Can't have a hostname that doesn't resolve to the same IP address
+ * with double-lookups enabled...
+ */
+
+#ifdef WIN32
+ closesocket(con->http.fd);
+#else
+ close(con->http.fd);
+#endif /* WIN32 */
+
+ LogMessage(L_WARN, "IP lookup failed - connection from %s closed!",
+ con->http.hostname);
+ return;
+ }
+ }
+
+ LogMessage(L_DEBUG, "AcceptClient: %d from %s:%d.", con->http.fd,
+ con->http.hostname, ntohs(con->http.hostaddr.sin_port));
+
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface... Since we write large buffers
+ * when sending print files and requests, there shouldn't be any
+ * performance penalty for this...
+ */
+
+ val = 1;
+ setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+
+ /*
+ * Close this file on all execs...
+ */
+
+ fcntl(con->http.fd, F_SETFD, fcntl(con->http.fd, F_GETFD) | FD_CLOEXEC);
+
+ /*
+ * Add the socket to the select() input mask.
+ */
+
+ LogMessage(L_DEBUG2, "AcceptClient: Adding fd %d to InputSet...",
+ con->http.fd);
+ FD_SET(con->http.fd, InputSet);
+
+ NumClients ++;
+
+ /*
+ * Temporarily suspend accept()'s until we lose a client...
+ */
+
+ if (NumClients == MaxClients)
+ PauseListening();
+
+#ifdef HAVE_SSL
+ /*
+ * See if we are connecting on a secure port...
+ */
+
+ if (lis->encryption == HTTP_ENCRYPT_ALWAYS)
+ {
+ /*
+ * https connection; go secure...
+ */
+
+ con->http.encryption = HTTP_ENCRYPT_ALWAYS;
+
+ EncryptClient(con);
+ }
+#endif /* HAVE_SSL */
+}
+
+
+/*
+ * 'CloseAllClients()' - Close all remote clients immediately.
+ */
+
+void
+CloseAllClients(void)
+{
+ while (NumClients > 0)
+ CloseClient(Clients);
+}
+
+
+/*
+ * 'CloseClient()' - Close a remote client.
+ */
+
+int /* O - 1 if partial close, 0 if fully closed */
+CloseClient(client_t *con) /* I - Client to close */
+{
+ int partial; /* Do partial close for SSL? */
+#if defined(HAVE_LIBSSL)
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
+ unsigned long error; /* Error code */
+#elif defined(HAVE_GNUTLS)
+ http_tls_t *conn; /* TLS connection information */
+ int error; /* Error code */
+ gnutls_certificate_server_credentials *credentials;
+ /* TLS credentials */
+#endif /* HAVE_GNUTLS */
+
+
+ LogMessage(L_DEBUG, "CloseClient: %d", con->http.fd);
+
+ partial = 0;
+
+#ifdef HAVE_SSL
+ /*
+ * Shutdown encryption as needed...
+ */
+
+ if (con->http.tls)
+ {
+ partial = 1;
+
+# ifdef HAVE_LIBSSL
+ conn = (SSL *)(con->http.tls);
+ context = SSL_get_SSL_CTX(conn);
+
+ switch (SSL_shutdown(conn))
+ {
+ case 1 :
+ LogMessage(L_INFO, "CloseClient: SSL shutdown successful!");
+ break;
+ case -1 :
+ LogMessage(L_ERROR, "CloseClient: Fatal error during SSL shutdown!");
+ default :
+ while ((error = ERR_get_error()) != 0)
+ LogMessage(L_ERROR, "CloseClient: %s", ERR_error_string(error, NULL));
+ break;
+ }
+
+ SSL_CTX_free(context);
+ SSL_free(conn);
+
+# elif defined(HAVE_GNUTLS)
+ conn = (http_tls_t *)(con->http.tls);
+ credentials = (gnutls_certificate_server_credentials *)(conn->credentials);
+
+ error = gnutls_bye(conn->session, GNUTLS_SHUT_WR);
+ switch (error)
+ {
+ case GNUTLS_E_SUCCESS:
+ LogMessage(L_INFO, "CloseClient: SSL shutdown successful!");
+ break;
+ default:
+ LogMessage(L_ERROR, "CloseClient: %s", gnutls_strerror(error));
+ break;
+ }
+
+ gnutls_deinit(conn->session);
+ gnutls_certificate_free_credentials(*credentials);
+ free(credentials);
+ free(conn);
+
+# elif defined(HAVE_CDSASSL)
+ status = SSLClose((SSLContextRef)con->http.tls);
+ SSLDisposeContext((SSLContextRef)con->http.tls);
+# endif /* HAVE_LIBSSL */
+
+ con->http.tls = NULL;
+ }
+#endif /* HAVE_SSL */
+
+ /*
+ * Close the socket and clear the file from the input set for select()...
+ */
+
+ if (con->http.fd > 0)
+ {
+ if (partial)
+ {
+ /*
+ * Only do a partial close so that the encrypted client gets everything.
+ */
+
+ LogMessage(L_DEBUG2, "CloseClient: Removing fd %d from OutputSet...",
+ con->http.fd);
+ shutdown(con->http.fd, 0);
+ FD_CLR(con->http.fd, OutputSet);
+ }
+ else
+ {
+ /*
+ * Shut the socket down fully...
+ */
+
+ LogMessage(L_DEBUG2, "CloseClient: Removing fd %d from InputSet and OutputSet...",
+ con->http.fd);
+ close(con->http.fd);
+ FD_CLR(con->http.fd, InputSet);
+ FD_CLR(con->http.fd, OutputSet);
+ con->http.fd = 0;
+ }
+ }
+
+ if (con->pipe_pid != 0)
+ {
+ /*
+ * Stop any CGI process...
+ */
+
+ LogMessage(L_DEBUG2, "CloseClient: %d Killing process ID %d...",
+ con->http.fd, con->pipe_pid);
+ kill(con->pipe_pid, SIGKILL);
+ }
+
+ if (con->file >= 0)
+ {
+ if (FD_ISSET(con->file, InputSet))
+ {
+ LogMessage(L_DEBUG2, "CloseClient: %d Removing fd %d from InputSet...",
+ con->http.fd, con->file);
+ FD_CLR(con->file, InputSet);
+ }
+
+ LogMessage(L_DEBUG2, "CloseClient: %d Closing data file %d.",
+ con->http.fd, con->file);
+
+ close(con->file);
+ con->file = -1;
+ }
+
+ if (!partial)
+ {
+ /*
+ * Free memory...
+ */
+
+ if (con->http.input_set)
+ free(con->http.input_set);
+
+ httpClearCookie(HTTP(con));
+
+ ClearString(&con->filename);
+ ClearString(&con->command);
+ ClearString(&con->options);
+
+ if (con->request)
+ {
+ ippDelete(con->request);
+ con->request = NULL;
+ }
+
+ if (con->response)
+ {
+ ippDelete(con->response);
+ con->response = NULL;
+ }
+
+ if (con->language)
+ {
+ cupsLangFree(con->language);
+ con->language = NULL;
+ }
+
+ /*
+ * Re-enable new client connections if we are going back under the
+ * limit...
+ */
+
+ if (NumClients == MaxClients)
+ ResumeListening();
+
+ /*
+ * Compact the list of clients as necessary...
+ */
+
+ NumClients --;
+
+ if (con < (Clients + NumClients))
+ memmove(con, con + 1, (Clients + NumClients - con) * sizeof(client_t));
+ }
+
+ return (partial);
+}
+
+
+/*
+ * 'EncryptClient()' - Enable encryption for the client...
+ */
+
+int /* O - 1 on success, 0 on error */
+EncryptClient(client_t *con) /* I - Client to encrypt */
+{
+#if defined HAVE_LIBSSL
+ SSL_CTX *context; /* Context for encryption */
+ SSL *conn; /* Connection for encryption */
+ unsigned long error; /* Error code */
+
+
+ /*
+ * Create the SSL context and accept the connection...
+ */
+
+ context = SSL_CTX_new(SSLv23_server_method());
+
+ SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM);
+ SSL_CTX_use_certificate_file(context, ServerCertificate, SSL_FILETYPE_PEM);
+
+ conn = SSL_new(context);
+
+ SSL_set_fd(conn, con->http.fd);
+ if (SSL_accept(conn) != 1)
+ {
+ LogMessage(L_ERROR, "EncryptClient: Unable to encrypt connection from %s!",
+ con->http.hostname);
+
+ while ((error = ERR_get_error()) != 0)
+ LogMessage(L_ERROR, "EncryptClient: %s", ERR_error_string(error, NULL));
+
+ SSL_CTX_free(context);
+ SSL_free(conn);
+ return (0);
+ }
+
+ LogMessage(L_DEBUG, "EncryptClient: %d Connection from %s now encrypted.",
+ con->http.fd, con->http.hostname);
+
+ con->http.tls = conn;
+ return (1);
+
+#elif defined(HAVE_GNUTLS)
+ http_tls_t *conn; /* TLS session object */
+ int error; /* Error code */
+ gnutls_certificate_server_credentials *credentials;
+ /* TLS credentials */
+
+ /*
+ * Create the SSL object and perform the SSL handshake...
+ */
+
+ conn = (http_tls_t *)malloc(sizeof(gnutls_session));
+
+ if (conn == NULL)
+ return (0);
+
+ credentials = (gnutls_certificate_server_credentials *)
+ malloc(sizeof(gnutls_certificate_server_credentials));
+ if (credentials == NULL)
+ {
+ LogMessage(L_ERROR, "EncryptClient: Unable to encrypt connection from %s!",
+ con->http.hostname);
+ LogMessage(L_ERROR, "EncryptClient: %s", strerror(errno));
+
+ free(conn);
+ return (0);
+ }
+
+ gnutls_certificate_allocate_credentials(credentials);
+ gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
+ ServerKey, GNUTLS_X509_FMT_PEM);
+
+ gnutls_init(&(conn->session), GNUTLS_SERVER);
+ gnutls_set_default_priority(conn->session);
+ gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
+ gnutls_transport_set_ptr(conn->session, con->http.fd);
+
+ error = gnutls_handshake(conn->session);
+
+ if (error != GNUTLS_E_SUCCESS)
+ {
+ LogMessage(L_ERROR, "EncryptClient: Unable to encrypt connection from %s!",
+ con->http.hostname);
+ LogMessage(L_ERROR, "EncryptClient: %s", gnutls_strerror(error));
+
+ gnutls_deinit(conn->session);
+ gnutls_certificate_free_credentials(*credentials);
+ free(conn);
+ free(credentials);
+ return (0);
+ }
+
+ LogMessage(L_DEBUG, "EncryptClient: %d Connection from %s now encrypted.",
+ con->http.fd, con->http.hostname);
+
+ conn->credentials = credentials;
+ con->http.tls = conn;
+ return (1);
+
+#elif defined(HAVE_CDSASSL)
+ OSStatus error; /* Error info */
+ SSLContextRef conn; /* New connection */
+ SSLProtocol tryVersion; /* Protocol version */
+ const char *hostName; /* Local hostname */
+ int allowExpired; /* Allow expired certificates? */
+ int allowAnyRoot; /* Allow any root certificate? */
+ SSLProtocol *negVersion; /* Negotiated protocol version */
+ SSLCipherSuite *negCipher; /* Negotiated cypher */
+ CFArrayRef *peerCerts; /* Certificates */
+
+
+ conn = NULL;
+ error = SSLNewContext(true, &conn);
+ allowExpired = 1;
+ allowAnyRoot = 1;
+
+ if (!error)
+ error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc);
+
+ if (!error)
+ error = SSLSetProtocolVersion(conn, kSSLProtocol3);
+
+ if (!error)
+ error = SSLSetConnection(conn, (SSLConnectionRef)con->http.fd);
+
+ if (!error)
+ {
+ hostName = ServerName; /* MRS: ??? */
+ error = SSLSetPeerDomainName(conn, hostName, strlen(hostName) + 1);
+ }
+
+ /* have to do these options befor setting server certs */
+ if (!error && allowExpired)
+ error = SSLSetAllowsExpiredCerts(conn, true);
+
+ if (!error && allowAnyRoot)
+ error = SSLSetAllowsAnyRoot(conn, true);
+
+ if (!error && ServerCertificatesArray != NULL)
+ error = SSLSetCertificate(conn, ServerCertificatesArray);
+
+ /*
+ * Perform SSL/TLS handshake
+ */
+
+ do
+ {
+ error = SSLHandshake(conn);
+ }
+ while (error == errSSLWouldBlock);
+
+ if (error)
+ {
+ LogMessage(L_ERROR, "EncryptClient: Unable to encrypt connection from %s!",
+ con->http.hostname);
+
+ LogMessage(L_ERROR, "EncryptClient: CDSA error code is %d", error);
+
+ con->http.error = error;
+ con->http.status = HTTP_ERROR;
+
+ if (conn != NULL)
+ SSLDisposeContext(conn);
+
+ return (0);
+ }
+
+ LogMessage(L_DEBUG, "EncryptClient: %d Connection from %s now encrypted.",
+ con->http.fd, con->http.hostname);
+
+ con->http.tls = conn;
+ return (1);
+
+#else
+ return (0);
+#endif /* HAVE_GNUTLS */
+}
+
+
+/*
+ * 'IsCGI()' - Is the resource a CGI script/program?
+ */
+
+int /* O - 1 = CGI, 0 = file */
+IsCGI(client_t *con, /* I - Client connection */
+ const char *filename, /* I - Real filename */
+ struct stat *filestats, /* I - File information */
+ mime_type_t *type) /* I - MIME type */
+{
+ const char *options; /* Options on URL */
+
+
+ LogMessage(L_DEBUG2, "IsCGI(con=%p, filename=\"%s\", filestats=%p, type=%s/%s)\n",
+ con, filename, filestats, type ? type->super : "unknown",
+ type ? type->type : "unknown");
+
+ /*
+ * Get the options, if any...
+ */
+
+ if ((options = strchr(con->uri, '?')) != NULL)
+ options ++;
+
+ /*
+ * Check for known types...
+ */
+
+ if (!type || strcasecmp(type->super, "application"))
+ {
+ LogMessage(L_DEBUG2, "IsCGI: Returning 0...");
+ return (0);
+ }
+
+ if (!strcasecmp(type->type, "x-httpd-cgi") &&
+ (filestats->st_mode & 0111))
+ {
+ /*
+ * "application/x-httpd-cgi" is a CGI script.
+ */
+
+ SetString(&con->command, filename);
+
+ filename = strrchr(filename, '/') + 1; /* Filename always absolute */
+
+ if (options)
+ SetStringf(&con->options, "%s %s", filename, options);
+ else
+ SetStringf(&con->options, "%s", filename);
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 1 with command=\"%s\" and options=\"%s\"",
+ con->command, con->options);
+
+ return (1);
+ }
+#ifdef HAVE_JAVA
+ else if (!strcasecmp(type->type, "x-httpd-java"))
+ {
+ /*
+ * "application/x-httpd-java" is a Java servlet.
+ */
+
+ SetString(&con->command, CUPS_JAVA);
+
+ if (options)
+ SetStringf(&con->options, "java %s %s", filename, options);
+ else
+ SetStringf(&con->options, "java %s", filename);
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 1 with command=\"%s\" and options=\"%s\"",
+ con->command, con->options);
+
+ return (1);
+ }
+#endif /* HAVE_JAVA */
+#ifdef HAVE_PERL
+ else if (!strcasecmp(type->type, "x-httpd-perl"))
+ {
+ /*
+ * "application/x-httpd-perl" is a Perl page.
+ */
+
+ SetString(&con->command, CUPS_PERL);
+
+ if (options)
+ SetStringf(&con->options, "perl %s %s", filename, options);
+ else
+ SetStringf(&con->options, "perl %s", filename);
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 1 with command=\"%s\" and options=\"%s\"",
+ con->command, con->options);
+
+ return (1);
+ }
+#endif /* HAVE_PERL */
+#ifdef HAVE_PHP
+ else if (!strcasecmp(type->type, "x-httpd-php"))
+ {
+ /*
+ * "application/x-httpd-php" is a PHP page.
+ */
+
+ SetString(&con->command, CUPS_PHP);
+
+ if (options)
+ SetStringf(&con->options, "php %s %s", filename, options);
+ else
+ SetStringf(&con->options, "php %s", filename);
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 1 with command=\"%s\" and options=\"%s\"",
+ con->command, con->options);
+
+ return (1);
+ }
+#endif /* HAVE_PHP */
+#ifdef HAVE_PYTHON
+ else if (!strcasecmp(type->type, "x-httpd-python"))
+ {
+ /*
+ * "application/x-httpd-python" is a Python page.
+ */
+
+ SetString(&con->command, CUPS_PYTHON);
+
+ if (options)
+ SetStringf(&con->options, "python %s %s", filename, options);
+ else
+ SetStringf(&con->options, "python %s", filename);
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 1 with command=\"%s\" and options=\"%s\"",
+ con->command, con->options);
+
+ return (1);
+ }
+#endif /* HAVE_PYTHON */
+
+ LogMessage(L_DEBUG2, "IsCGI: Returning 0...");
+
+ return (0);
+}
+
+
+/*
+ * 'ReadClient()' - Read data from a client.
+ */
+
+int /* O - 1 on success, 0 on error */
+ReadClient(client_t *con) /* I - Client to read from */
+{
+ char line[32768], /* Line from client... */
+ operation[64], /* Operation code from socket */
+ version[64], /* HTTP version number string */
+ locale[64], /* Locale */
+ *ptr; /* Pointer into strings */
+ int major, minor; /* HTTP version numbers */
+ http_status_t status; /* Transfer status */
+ ipp_state_t ipp_state; /* State of IPP transfer */
+ int bytes; /* Number of bytes to POST */
+ char *filename; /* Name of file for GET/HEAD */
+ char buf[1024]; /* Buffer for real filename */
+ struct stat filestats; /* File information */
+ mime_type_t *type; /* MIME type of file */
+ printer_t *p; /* Printer */
+ location_t *best; /* Best match for authentication */
+ static unsigned request_id = 0; /* Request ID for temp files */
+
+
+ status = HTTP_CONTINUE;
+
+ LogMessage(L_DEBUG2, "ReadClient: %d, used=%d, file=%d", con->http.fd,
+ con->http.used, con->file);
+
+ if (con->http.error)
+ {
+ LogMessage(L_DEBUG2, "ReadClient: http error seen...");
+ return (CloseClient(con));
+ }
+
+ switch (con->http.state)
+ {
+ case HTTP_WAITING :
+ /*
+ * See if we've received a request line...
+ */
+
+ if (httpGets(line, sizeof(line) - 1, HTTP(con)) == NULL)
+ {
+ LogMessage(L_DEBUG2, "ReadClient: httpGets returned EOF...");
+ return (CloseClient(con));
+ }
+
+ /*
+ * Ignore blank request lines...
+ */
+
+ if (line[0] == '\0')
+ break;
+
+ /*
+ * Clear other state variables...
+ */
+
+ httpClearFields(HTTP(con));
+
+ con->http.activity = time(NULL);
+ con->http.version = HTTP_1_0;
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+ con->http.data_encoding = HTTP_ENCODE_LENGTH;
+ con->http.data_remaining = 0;
+ con->operation = HTTP_WAITING;
+ con->bytes = 0;
+ con->file = -1;
+ con->file_ready = 0;
+ con->pipe_pid = 0;
+ con->username[0] = '\0';
+ con->password[0] = '\0';
+ con->uri[0] = '\0';
+
+ ClearString(&con->command);
+ ClearString(&con->options);
+
+ if (con->language != NULL)
+ {
+ cupsLangFree(con->language);
+ con->language = NULL;
+ }
+
+ /*
+ * Grab the request line...
+ */
+
+ switch (sscanf(line, "%63s%1023s%63s", operation, con->uri, version))
+ {
+ case 1 :
+ LogMessage(L_ERROR, "Bad request line \"%s\" from %s!", line,
+ con->http.hostname);
+ SendError(con, HTTP_BAD_REQUEST);
+ return (CloseClient(con));
+ case 2 :
+ con->http.version = HTTP_0_9;
+ break;
+ case 3 :
+ if (sscanf(version, "HTTP/%d.%d", &major, &minor) != 2)
+ {
+ LogMessage(L_ERROR, "Bad request line \"%s\" from %s!", line,
+ con->http.hostname);
+ SendError(con, HTTP_BAD_REQUEST);
+ return (CloseClient(con));
+ }
+
+ if (major < 2)
+ {
+ con->http.version = (http_version_t)(major * 100 + minor);
+ if (con->http.version == HTTP_1_1 && KeepAlive)
+ con->http.keep_alive = HTTP_KEEPALIVE_ON;
+ else
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+ }
+ else
+ {
+ SendError(con, HTTP_NOT_SUPPORTED);
+ return (CloseClient(con));
+ }
+ break;
+ }
+
+ /*
+ * Handle full URLs in the request line...
+ */
+
+ if (con->uri[0] != '/' && strcmp(con->uri, "*"))
+ {
+ char method[HTTP_MAX_URI], /* Method/scheme */
+ userpass[HTTP_MAX_URI], /* Username:password */
+ hostname[HTTP_MAX_URI], /* Hostname */
+ resource[HTTP_MAX_URI]; /* Resource path */
+ int port; /* Port number */
+
+
+ /*
+ * Separate the URI into its components...
+ */
+
+ httpSeparate(con->uri, method, userpass, hostname, &port, resource);
+
+ /*
+ * Only allow URIs with the servername, localhost, or an IP
+ * address...
+ */
+
+ if (strcasecmp(hostname, ServerName) &&
+ strcasecmp(hostname, "localhost") &&
+ !isdigit(hostname[0]))
+ {
+ /*
+ * Nope, we don't do proxies...
+ */
+
+ LogMessage(L_ERROR, "Bad URI \"%s\" in request!", con->uri);
+ SendError(con, HTTP_METHOD_NOT_ALLOWED);
+ return (CloseClient(con));
+ }
+
+ /*
+ * Copy the resource portion back into the URI; both resource and
+ * con->uri are HTTP_MAX_URI bytes in size...
+ */
+
+ strcpy(con->uri, resource);
+ }
+
+ /*
+ * Process the request...
+ */
+
+ if (strcmp(operation, "GET") == 0)
+ con->http.state = HTTP_GET;
+ else if (strcmp(operation, "PUT") == 0)
+ con->http.state = HTTP_PUT;
+ else if (strcmp(operation, "POST") == 0)
+ con->http.state = HTTP_POST;
+ else if (strcmp(operation, "DELETE") == 0)
+ con->http.state = HTTP_DELETE;
+ else if (strcmp(operation, "TRACE") == 0)
+ con->http.state = HTTP_TRACE;
+ else if (strcmp(operation, "OPTIONS") == 0)
+ con->http.state = HTTP_OPTIONS;
+ else if (strcmp(operation, "HEAD") == 0)
+ con->http.state = HTTP_HEAD;
+ else
+ {
+ LogMessage(L_ERROR, "Bad operation \"%s\"!", operation);
+ SendError(con, HTTP_BAD_REQUEST);
+ return (CloseClient(con));
+ }
+
+ con->start = time(NULL);
+ con->operation = con->http.state;
+
+ LogMessage(L_DEBUG, "ReadClient: %d %s %s HTTP/%d.%d", con->http.fd,
+ operation, con->uri,
+ con->http.version / 100, con->http.version % 100);
+
+ con->http.status = HTTP_OK;
+
+ case HTTP_OPTIONS :
+ case HTTP_DELETE :
+ case HTTP_GET :
+ case HTTP_HEAD :
+ case HTTP_POST :
+ case HTTP_PUT :
+ case HTTP_TRACE :
+ /*
+ * Parse incoming parameters until the status changes...
+ */
+
+ status = httpUpdate(HTTP(con));
+
+ if (status != HTTP_OK && status != HTTP_CONTINUE)
+ {
+ SendError(con, HTTP_BAD_REQUEST);
+ return (CloseClient(con));
+ }
+ break;
+
+ default :
+ break; /* Anti-compiler-warning-code */
+ }
+
+ /*
+ * Handle new transfers...
+ */
+
+ if (status == HTTP_OK)
+ {
+ if (con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE][0])
+ {
+ /*
+ * Figure out the locale from the Accept-Language and Content-Type
+ * fields...
+ */
+
+ if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ',')) != NULL)
+ *ptr = '\0';
+
+ if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ';')) != NULL)
+ *ptr = '\0';
+
+ if ((ptr = strstr(con->http.fields[HTTP_FIELD_CONTENT_TYPE], "charset=")) != NULL)
+ {
+ /*
+ * Combine language and charset, and trim any extra params in the
+ * content-type.
+ */
+
+ snprintf(locale, sizeof(locale), "%s.%s",
+ con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ptr + 8);
+
+ if ((ptr = strchr(locale, ',')) != NULL)
+ *ptr = '\0';
+ }
+ else
+ snprintf(locale, sizeof(locale), "%s.%s",
+ con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], DefaultCharset);
+
+ con->language = cupsLangGet(locale);
+ }
+ else
+ con->language = cupsLangGet(DefaultLocale);
+
+ decode_auth(con);
+
+ if (strncmp(con->http.fields[HTTP_FIELD_CONNECTION], "Keep-Alive", 10) == 0 &&
+ KeepAlive)
+ con->http.keep_alive = HTTP_KEEPALIVE_ON;
+
+ if (con->http.fields[HTTP_FIELD_HOST][0] == '\0' &&
+ con->http.version >= HTTP_1_1)
+ {
+ /*
+ * HTTP/1.1 and higher require the "Host:" field...
+ */
+
+ if (!SendError(con, HTTP_BAD_REQUEST))
+ return (CloseClient(con));
+ }
+ else if (con->operation == HTTP_OPTIONS)
+ {
+ /*
+ * Do OPTIONS command...
+ */
+
+ if ((best = FindBest(con->uri, con->http.state)) != NULL &&
+ best->type != AUTH_NONE)
+ {
+ if (!SendHeader(con, HTTP_UNAUTHORIZED, NULL))
+ return (CloseClient(con));
+ }
+
+ if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
+ con->http.tls == NULL)
+ {
+#ifdef HAVE_SSL
+ /*
+ * Do encryption stuff...
+ */
+
+ if (!SendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
+ return (CloseClient(con));
+
+ httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
+ httpPrintf(HTTP(con), "Content-Length: 0\r\n");
+ httpPrintf(HTTP(con), "\r\n");
+
+ EncryptClient(con);
+#else
+ if (!SendError(con, HTTP_NOT_IMPLEMENTED))
+ return (CloseClient(con));
+#endif /* HAVE_SSL */
+ }
+
+ if (!SendHeader(con, HTTP_OK, NULL))
+ return (CloseClient(con));
+
+ httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n");
+ httpPrintf(HTTP(con), "Content-Length: 0\r\n");
+ httpPrintf(HTTP(con), "\r\n");
+ }
+ else if (!is_path_absolute(con->uri))
+ {
+ /*
+ * Protect against malicious users!
+ */
+
+ if (!SendError(con, HTTP_FORBIDDEN))
+ return (CloseClient(con));
+ }
+ else
+ {
+ if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
+ con->http.tls == NULL)
+ {
+#ifdef HAVE_SSL
+ /*
+ * Do encryption stuff...
+ */
+
+ if (!SendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL))
+ return (CloseClient(con));
+
+ httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
+ httpPrintf(HTTP(con), "Content-Length: 0\r\n");
+ httpPrintf(HTTP(con), "\r\n");
+
+ EncryptClient(con);
+#else
+ if (!SendError(con, HTTP_NOT_IMPLEMENTED))
+ return (CloseClient(con));
+#endif /* HAVE_SSL */
+ }
+
+ if ((status = IsAuthorized(con)) != HTTP_OK)
+ {
+ LogMessage(L_DEBUG2, "ReadClient: Unauthorized request for %s...\n",
+ con->uri);
+ SendError(con, status);
+ return (CloseClient(con));
+ }
+
+ switch (con->http.state)
+ {
+ case HTTP_GET_SEND :
+ if (strncmp(con->uri, "/printers/", 10) == 0 &&
+ strcmp(con->uri + strlen(con->uri) - 4, ".ppd") == 0)
+ {
+ /*
+ * Send PPD file - get the real printer name since printer
+ * names are not case sensitive but filenames can be...
+ */
+
+ con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
+
+ if ((p = FindPrinter(con->uri + 10)) != NULL)
+ snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
+ else
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+
+ break;
+ }
+ }
+
+ if ((strncmp(con->uri, "/admin", 6) == 0 &&
+ strncmp(con->uri, "/admin/conf/", 12) != 0) ||
+ strncmp(con->uri, "/printers", 9) == 0 ||
+ strncmp(con->uri, "/classes", 8) == 0 ||
+ strncmp(con->uri, "/jobs", 5) == 0)
+ {
+ /*
+ * Send CGI output...
+ */
+
+ if (strncmp(con->uri, "/admin", 6) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/admin.cgi", ServerBin);
+
+ if ((ptr = strchr(con->uri + 6, '?')) != NULL)
+ SetStringf(&con->options, "admin%s", ptr);
+ else
+ SetString(&con->options, "admin");
+ }
+ else if (strncmp(con->uri, "/printers", 9) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
+ SetString(&con->options, con->uri + 9);
+ }
+ else if (strncmp(con->uri, "/classes", 8) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin);
+ SetString(&con->options, con->uri + 8);
+ }
+ else
+ {
+ SetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin);
+ SetString(&con->options, con->uri + 5);
+ }
+
+ if (con->options[0] == '/')
+ cups_strcpy(con->options, con->options + 1);
+
+ if (!SendCommand(con, con->command, con->options))
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+ }
+ else
+ LogRequest(con, HTTP_OK);
+
+ if (con->http.version <= HTTP_1_0)
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+ }
+ else if (strncmp(con->uri, "/admin/conf/", 12) == 0 &&
+ (strchr(con->uri + 12, '/') != NULL ||
+ strlen(con->uri) == 12))
+ {
+ /*
+ * GET can only be done to configuration files under
+ * /admin/conf...
+ */
+
+ if (!SendError(con, HTTP_FORBIDDEN))
+ return (CloseClient(con));
+
+ break;
+ }
+ else
+ {
+ /*
+ * Serve a file...
+ */
+
+ if ((filename = get_file(con, &filestats, buf,
+ sizeof(buf))) == NULL)
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+
+ break;
+ }
+
+ type = mimeFileType(MimeDatabase, filename, NULL);
+
+ if (IsCGI(con, filename, &filestats, type))
+ {
+ /*
+ * Note: con->command and con->options were set by
+ * IsCGI()...
+ */
+
+ if (!SendCommand(con, con->command, con->options))
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+ }
+ else
+ LogRequest(con, HTTP_OK);
+
+ if (con->http.version <= HTTP_1_0)
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+ break;
+ }
+
+ if (!check_if_modified(con, &filestats))
+ {
+ if (!SendError(con, HTTP_NOT_MODIFIED))
+ return (CloseClient(con));
+ }
+ else
+ {
+ if (type == NULL)
+ strcpy(line, "text/plain");
+ else
+ snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
+
+ if (!SendFile(con, HTTP_OK, filename, line, &filestats))
+ return (CloseClient(con));
+ }
+ }
+ break;
+
+ case HTTP_POST_RECV :
+ /*
+ * See if the POST request includes a Content-Length field, and if
+ * so check the length against any limits that are set...
+ */
+
+ LogMessage(L_DEBUG2, "POST %s", con->uri);
+ LogMessage(L_DEBUG2, "CONTENT_TYPE = %s", con->http.fields[HTTP_FIELD_CONTENT_TYPE]);
+
+ if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] &&
+ atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) > MaxRequestSize &&
+ MaxRequestSize > 0)
+ {
+ /*
+ * Request too large...
+ */
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+
+ break;
+ }
+ else if (atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) < 0)
+ {
+ /*
+ * Negative content lengths are invalid!
+ */
+
+ if (!SendError(con, HTTP_BAD_REQUEST))
+ return (CloseClient(con));
+
+ break;
+ }
+
+ /*
+ * See what kind of POST request this is; for IPP requests the
+ * content-type field will be "application/ipp"...
+ */
+
+ if (strcmp(con->http.fields[HTTP_FIELD_CONTENT_TYPE], "application/ipp") == 0)
+ con->request = ippNew();
+ else if ((strncmp(con->uri, "/admin", 6) == 0 &&
+ strncmp(con->uri, "/admin/conf/", 12) != 0) ||
+ strncmp(con->uri, "/printers", 9) == 0 ||
+ strncmp(con->uri, "/classes", 8) == 0 ||
+ strncmp(con->uri, "/jobs", 5) == 0)
+ {
+ /*
+ * CGI request...
+ */
+
+ if (strncmp(con->uri, "/admin", 6) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/admin.cgi", ServerBin);
+
+ if ((ptr = strchr(con->uri + 6, '?')) != NULL)
+ SetStringf(&con->options, "admin%s", ptr);
+ else
+ SetString(&con->options, "admin");
+ }
+ else if (strncmp(con->uri, "/printers", 9) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/printers.cgi", ServerBin);
+ SetString(&con->options, con->uri + 9);
+ }
+ else if (strncmp(con->uri, "/classes", 8) == 0)
+ {
+ SetStringf(&con->command, "%s/cgi-bin/classes.cgi", ServerBin);
+ SetString(&con->options, con->uri + 8);
+ }
+ else
+ {
+ SetStringf(&con->command, "%s/cgi-bin/jobs.cgi", ServerBin);
+ SetString(&con->options, con->uri + 5);
+ }
+
+ if (con->options[0] == '/')
+ cups_strcpy(con->options, con->options + 1);
+
+ LogMessage(L_DEBUG2, "ReadClient: %d command=\"%s\", options = \"%s\"",
+ con->http.fd, con->command, con->options);
+
+ if (con->http.version <= HTTP_1_0)
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+ }
+ else
+ {
+ /*
+ * POST to a file...
+ */
+
+ if ((filename = get_file(con, &filestats, buf,
+ sizeof(buf))) == NULL)
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+
+ break;
+ }
+
+ type = mimeFileType(MimeDatabase, filename, NULL);
+
+ if (!IsCGI(con, filename, &filestats, type))
+ {
+ /*
+ * Only POST to CGI's...
+ */
+
+ if (!SendError(con, HTTP_UNAUTHORIZED))
+ return (CloseClient(con));
+ }
+ }
+ break;
+
+ case HTTP_PUT_RECV :
+ /*
+ * Validate the resource name...
+ */
+
+ if (strncmp(con->uri, "/admin/conf/", 12) != 0 ||
+ strchr(con->uri + 12, '/') != NULL ||
+ strlen(con->uri) == 12)
+ {
+ /*
+ * PUT can only be done to configuration files under
+ * /admin/conf...
+ */
+
+ if (!SendError(con, HTTP_FORBIDDEN))
+ return (CloseClient(con));
+
+ break;
+ }
+
+ /*
+ * See if the PUT request includes a Content-Length field, and if
+ * so check the length against any limits that are set...
+ */
+
+ LogMessage(L_DEBUG2, "PUT %s", con->uri);
+ LogMessage(L_DEBUG2, "CONTENT_TYPE = %s", con->http.fields[HTTP_FIELD_CONTENT_TYPE]);
+
+ if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] &&
+ atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) > MaxRequestSize &&
+ MaxRequestSize > 0)
+ {
+ /*
+ * Request too large...
+ */
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+
+ break;
+ }
+ else if (atoi(con->http.fields[HTTP_FIELD_CONTENT_LENGTH]) < 0)
+ {
+ /*
+ * Negative content lengths are invalid!
+ */
+
+ if (!SendError(con, HTTP_BAD_REQUEST))
+ return (CloseClient(con));
+
+ break;
+ }
+
+ /*
+ * Open a temporary file to hold the request...
+ */
+
+ SetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++);
+ con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+
+ LogMessage(L_DEBUG2, "ReadClient: %d REQUEST %s=%d", con->http.fd,
+ con->filename, con->file);
+
+ if (con->file < 0)
+ {
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+
+ fchmod(con->file, 0640);
+ fchown(con->file, RunUser, Group);
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+ break;
+
+ case HTTP_DELETE :
+ case HTTP_TRACE :
+ SendError(con, HTTP_NOT_IMPLEMENTED);
+ return (CloseClient(con));
+
+ case HTTP_HEAD :
+ if (strncmp(con->uri, "/printers/", 10) == 0 &&
+ strcmp(con->uri + strlen(con->uri) - 4, ".ppd") == 0)
+ {
+ /*
+ * Send PPD file - get the real printer name since printer
+ * names are not case sensitive but filenames can be...
+ */
+
+ con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
+
+ if ((p = FindPrinter(con->uri + 10)) != NULL)
+ snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name);
+ else
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+
+ break;
+ }
+ }
+
+ if ((strncmp(con->uri, "/admin/", 7) == 0 &&
+ strncmp(con->uri, "/admin/conf/", 12) != 0) ||
+ strncmp(con->uri, "/printers/", 10) == 0 ||
+ strncmp(con->uri, "/classes/", 9) == 0 ||
+ strncmp(con->uri, "/jobs/", 6) == 0)
+ {
+ /*
+ * CGI output...
+ */
+
+ if (!SendHeader(con, HTTP_OK, "text/html"))
+ return (CloseClient(con));
+
+ if (httpPrintf(HTTP(con), "\r\n") < 0)
+ return (CloseClient(con));
+
+ LogRequest(con, HTTP_OK);
+ }
+ else if (strncmp(con->uri, "/admin/conf/", 12) == 0 &&
+ (strchr(con->uri + 12, '/') != NULL ||
+ strlen(con->uri) == 12))
+ {
+ /*
+ * HEAD can only be done to configuration files under
+ * /admin/conf...
+ */
+
+ if (!SendError(con, HTTP_FORBIDDEN))
+ return (CloseClient(con));
+
+ break;
+ }
+ else if ((filename = get_file(con, &filestats, buf,
+ sizeof(buf))) == NULL)
+ {
+ if (!SendHeader(con, HTTP_NOT_FOUND, "text/html"))
+ return (CloseClient(con));
+
+ LogRequest(con, HTTP_NOT_FOUND);
+ }
+ else if (!check_if_modified(con, &filestats))
+ {
+ if (!SendError(con, HTTP_NOT_MODIFIED))
+ return (CloseClient(con));
+
+ LogRequest(con, HTTP_NOT_MODIFIED);
+ }
+ else
+ {
+ /*
+ * Serve a file...
+ */
+
+ type = mimeFileType(MimeDatabase, filename, NULL);
+ if (type == NULL)
+ strcpy(line, "text/plain");
+ else
+ snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
+
+ if (!SendHeader(con, HTTP_OK, line))
+ return (CloseClient(con));
+
+ if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n",
+ httpGetDateString(filestats.st_mtime)) < 0)
+ return (CloseClient(con));
+
+ if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n",
+ (unsigned long)filestats.st_size) < 0)
+ return (CloseClient(con));
+
+ LogRequest(con, HTTP_OK);
+ }
+
+ if (httpPrintf(HTTP(con), "\r\n") < 0)
+ return (CloseClient(con));
+
+ con->http.state = HTTP_WAITING;
+ break;
+
+ default :
+ break; /* Anti-compiler-warning-code */
+ }
+ }
+ }
+
+ /*
+ * Handle any incoming data...
+ */
+
+ switch (con->http.state)
+ {
+ case HTTP_PUT_RECV :
+ LogMessage(L_DEBUG2, "ReadClient: %d con->data_encoding = %s, con->data_remaining = %d, con->file = %d",
+ con->http.fd,
+ con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "chunked" : "length",
+ con->http.data_remaining, con->file);
+
+ if ((bytes = httpRead(HTTP(con), line, sizeof(line))) < 0)
+ return (CloseClient(con));
+ else if (bytes > 0)
+ {
+ con->bytes += bytes;
+
+ LogMessage(L_DEBUG2, "ReadClient: %d writing %d bytes to %d",
+ con->http.fd, bytes, con->file);
+
+ if (write(con->file, line, bytes) < bytes)
+ {
+ LogMessage(L_ERROR, "ReadClient: Unable to write %d bytes to %s: %s",
+ bytes, con->filename, strerror(errno));
+
+ close(con->file);
+ con->file = -1;
+ unlink(con->filename);
+ ClearString(&con->filename);
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+ }
+
+ if (con->http.state == HTTP_WAITING)
+ {
+ /*
+ * End of file, see how big it is...
+ */
+
+ fstat(con->file, &filestats);
+
+ LogMessage(L_DEBUG2, "ReadClient: %d Closing data file %d, size = %d.",
+ con->http.fd, con->file, (int)filestats.st_size);
+
+ close(con->file);
+ con->file = -1;
+
+ if (filestats.st_size > MaxRequestSize &&
+ MaxRequestSize > 0)
+ {
+ /*
+ * Request is too big; remove it and send an error...
+ */
+
+ LogMessage(L_DEBUG2, "ReadClient: %d Removing temp file %s",
+ con->http.fd, con->filename);
+ unlink(con->filename);
+ ClearString(&con->filename);
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+
+ /*
+ * Install the configuration file...
+ */
+
+ status = install_conf_file(con);
+
+ /*
+ * Return the status to the client...
+ */
+
+ if (!SendError(con, status))
+ return (CloseClient(con));
+ }
+ break;
+
+ case HTTP_POST_RECV :
+ LogMessage(L_DEBUG2, "ReadClient: %d con->data_encoding = %s, con->data_remaining = %d, con->file = %d",
+ con->http.fd,
+ con->http.data_encoding == HTTP_ENCODE_CHUNKED ? "chunked" : "length",
+ con->http.data_remaining, con->file);
+
+ if (con->request != NULL)
+ {
+ /*
+ * Grab any request data from the connection...
+ */
+
+ if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR)
+ {
+ LogMessage(L_ERROR, "ReadClient: %d IPP Read Error!",
+ con->http.fd);
+
+ SendError(con, HTTP_BAD_REQUEST);
+ return (CloseClient(con));
+ }
+ else if (ipp_state != IPP_DATA)
+ break;
+ else
+ con->bytes += ippLength(con->request);
+ }
+
+ if (con->file < 0 && con->http.state != HTTP_POST_SEND)
+ {
+ /*
+ * Create a file as needed for the request data...
+ */
+
+ SetStringf(&con->filename, "%s/%08x", RequestRoot, request_id ++);
+ con->file = open(con->filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
+
+ LogMessage(L_DEBUG2, "ReadClient: %d REQUEST %s=%d", con->http.fd,
+ con->filename, con->file);
+
+ if (con->file < 0)
+ {
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+
+ fchmod(con->file, 0640);
+ fchown(con->file, RunUser, Group);
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+ }
+
+ if (con->http.state != HTTP_POST_SEND)
+ {
+ if ((bytes = httpRead(HTTP(con), line, sizeof(line))) < 0)
+ return (CloseClient(con));
+ else if (bytes > 0)
+ {
+ con->bytes += bytes;
+
+ LogMessage(L_DEBUG2, "ReadClient: %d writing %d bytes to %d",
+ con->http.fd, bytes, con->file);
+
+ if (write(con->file, line, bytes) < bytes)
+ {
+ LogMessage(L_ERROR, "ReadClient: Unable to write %d bytes to %s: %s",
+ bytes, con->filename, strerror(errno));
+
+ close(con->file);
+ con->file = -1;
+ unlink(con->filename);
+ ClearString(&con->filename);
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+ }
+ else if (con->http.state == HTTP_POST_RECV)
+ return (1); /* ??? */
+ else if (con->http.state != HTTP_POST_SEND)
+ return (CloseClient(con));
+ }
+
+ if (con->http.state == HTTP_POST_SEND)
+ {
+ if (con->file >= 0)
+ {
+ fstat(con->file, &filestats);
+
+ LogMessage(L_DEBUG2, "ReadClient: %d Closing data file %d, size = %d.",
+ con->http.fd, con->file, (int)filestats.st_size);
+
+ close(con->file);
+ con->file = -1;
+
+ if (filestats.st_size > MaxRequestSize &&
+ MaxRequestSize > 0)
+ {
+ /*
+ * Request is too big; remove it and send an error...
+ */
+
+ LogMessage(L_DEBUG2, "ReadClient: %d Removing temp file %s",
+ con->http.fd, con->filename);
+ unlink(con->filename);
+ ClearString(&con->filename);
+
+ if (con->request)
+ {
+ /*
+ * Delete any IPP request data...
+ */
+
+ ippDelete(con->request);
+ con->request = NULL;
+ }
+
+ if (!SendError(con, HTTP_REQUEST_TOO_LARGE))
+ return (CloseClient(con));
+ }
+
+ if (con->command)
+ {
+ if (!SendCommand(con, con->command, con->options))
+ {
+ if (!SendError(con, HTTP_NOT_FOUND))
+ return (CloseClient(con));
+ }
+ else
+ LogRequest(con, HTTP_OK);
+ }
+ }
+
+ if (con->request)
+ return (ProcessIPPRequest(con));
+ }
+ break;
+
+ default :
+ break; /* Anti-compiler-warning-code */
+ }
+
+ if (!con->http.keep_alive && con->http.state == HTTP_WAITING)
+ return (CloseClient(con));
+ else
+ return (1);
+}
+
+
+/*
+ * 'SendCommand()' - Send output from a command via HTTP.
+ */
+
+int
+SendCommand(client_t *con,
+ char *command,
+ char *options)
+{
+ int fd;
+
+
+ if (con->filename)
+ fd = open(con->filename, O_RDONLY);
+ else
+ fd = open("/dev/null", O_RDONLY);
+
+ if (fd < 0)
+ {
+ LogMessage(L_ERROR, "SendCommand: %d Unable to open \"%s\" for reading: %s",
+ con->http.fd, con->filename ? con->filename : "/dev/null",
+ strerror(errno));
+ return (0);
+ }
+
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+
+ con->pipe_pid = pipe_command(con, fd, &(con->file), command, options);
+
+ close(fd);
+
+ LogMessage(L_INFO, "Started \"%s\" (pid=%d)", command, con->pipe_pid);
+
+ LogMessage(L_DEBUG, "SendCommand: %d file=%d", con->http.fd, con->file);
+
+ if (con->pipe_pid == 0)
+ return (0);
+
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+
+ LogMessage(L_DEBUG2, "SendCommand: Adding fd %d to InputSet...", con->file);
+ LogMessage(L_DEBUG2, "SendCommand: Adding fd %d to OutputSet...",
+ con->http.fd);
+
+ FD_SET(con->file, InputSet);
+ FD_SET(con->http.fd, OutputSet);
+
+ if (!SendHeader(con, HTTP_OK, NULL))
+ return (0);
+
+ if (con->http.version == HTTP_1_1)
+ {
+ con->http.data_encoding = HTTP_ENCODE_CHUNKED;
+
+ if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n") < 0)
+ return (0);
+ }
+
+ con->file_ready = 0;
+ con->got_fields = 0;
+ con->field_col = 0;
+
+ return (1);
+}
+
+
+/*
+ * 'SendError()' - Send an error message via HTTP.
+ */
+
+int /* O - 1 if successful, 0 otherwise */
+SendError(client_t *con, /* I - Connection */
+ http_status_t code) /* I - Error code */
+{
+ char message[1024]; /* Message for user */
+
+
+ /*
+ * Put the request in the access_log file...
+ */
+
+ LogRequest(con, code);
+
+ LogMessage(L_DEBUG, "SendError: %d code=%d (%s)", con->http.fd, code,
+ httpStatus(code));
+
+ /*
+ * To work around bugs in some proxies, don't use Keep-Alive for some
+ * error messages...
+ */
+
+ if (code >= HTTP_BAD_REQUEST)
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+
+ /*
+ * Send an error message back to the client. If the error code is a
+ * 400 or 500 series, make sure the message contains some text, too!
+ */
+
+ if (!SendHeader(con, code, NULL))
+ return (0);
+
+#ifdef HAVE_SSL
+ if (code == HTTP_UPGRADE_REQUIRED)
+ if (httpPrintf(HTTP(con), "Connection: Upgrade\r\n") < 0)
+ return (0);
+
+ if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n") < 0)
+ return (0);
+#endif /* HAVE_SSL */
+
+ if ((con->http.version >= HTTP_1_1 && !con->http.keep_alive) ||
+ (code >= HTTP_BAD_REQUEST && code != HTTP_UPGRADE_REQUIRED))
+ {
+ if (httpPrintf(HTTP(con), "Connection: close\r\n") < 0)
+ return (0);
+ }
+
+ if (code >= HTTP_BAD_REQUEST)
+ {
+ /*
+ * Send a human-readable error message.
+ */
+
+ snprintf(message, sizeof(message),
+ "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>"
+ "<BODY><H1>%s</H1>%s</BODY></HTML>\n",
+ code, httpStatus(code), httpStatus(code),
+ con->language ? con->language->messages[code] :
+ httpStatus(code));
+
+ if (httpPrintf(HTTP(con), "Content-Type: text/html\r\n") < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "Content-Length: %d\r\n",
+ (int)strlen(message)) < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "\r\n") < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "%s", message) < 0)
+ return (0);
+ }
+ else if (httpPrintf(HTTP(con), "\r\n") < 0)
+ return (0);
+
+ con->http.state = HTTP_WAITING;
+
+ return (1);
+}
+
+
+/*
+ * 'SendFile()' - Send a file via HTTP.
+ */
+
+int
+SendFile(client_t *con,
+ http_status_t code,
+ char *filename,
+ char *type,
+ struct stat *filestats)
+{
+ con->file = open(filename, O_RDONLY);
+
+ LogMessage(L_DEBUG, "SendFile: %d file=%d", con->http.fd, con->file);
+
+ if (con->file < 0)
+ return (0);
+
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+
+ con->pipe_pid = 0;
+
+ if (!SendHeader(con, code, type))
+ return (0);
+
+ if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n", httpGetDateString(filestats->st_mtime)) < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n",
+ (unsigned long)filestats->st_size) < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "\r\n") < 0)
+ return (0);
+
+ LogMessage(L_DEBUG2, "SendFile: Adding fd %d to OutputSet...", con->http.fd);
+
+ FD_SET(con->http.fd, OutputSet);
+
+ return (1);
+}
+
+
+/*
+ * 'SendHeader()' - Send an HTTP request.
+ */
+
+int /* O - 1 on success, 0 on failure */
+SendHeader(client_t *con, /* I - Client to send to */
+ http_status_t code, /* I - HTTP status code */
+ char *type) /* I - MIME type of document */
+{
+ location_t *loc; /* Authentication location */
+
+
+ if (httpPrintf(HTTP(con), "HTTP/%d.%d %d %s\r\n", con->http.version / 100,
+ con->http.version % 100, code, httpStatus(code)) < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "Date: %s\r\n", httpGetDateString(time(NULL))) < 0)
+ return (0);
+ if (ServerHeader)
+ if (httpPrintf(HTTP(con), "Server: %s\r\n", ServerHeader) < 0)
+ return (0);
+ if (con->http.keep_alive && con->http.version >= HTTP_1_0)
+ {
+ if (httpPrintf(HTTP(con), "Connection: Keep-Alive\r\n") < 0)
+ return (0);
+ if (httpPrintf(HTTP(con), "Keep-Alive: timeout=%d\r\n", KeepAliveTimeout) < 0)
+ return (0);
+ }
+ if (code == HTTP_METHOD_NOT_ALLOWED)
+ if (httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST\r\n") < 0)
+ return (0);
+
+ if (code == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * This already succeeded in IsAuthorized...
+ */
+
+ loc = FindBest(con->uri, con->http.state);
+
+ if (loc->type != AUTH_DIGEST)
+ {
+ if (httpPrintf(HTTP(con), "WWW-Authenticate: Basic realm=\"CUPS\"\r\n") < 0)
+ return (0);
+ }
+ else
+ {
+ if (httpPrintf(HTTP(con), "WWW-Authenticate: Digest realm=\"CUPS\", "
+ "nonce=\"%s\"\r\n", con->http.hostname) < 0)
+ return (0);
+ }
+ }
+ if (con->language != NULL)
+ {
+ if (httpPrintf(HTTP(con), "Content-Language: %s\r\n",
+ con->language->language) < 0)
+ return (0);
+
+ if (type != NULL)
+ if (httpPrintf(HTTP(con), "Content-Type: %s; charset=%s\r\n", type,
+ cupsLangEncoding(con->language)) < 0)
+ return (0);
+ }
+ else if (type != NULL)
+ if (httpPrintf(HTTP(con), "Content-Type: %s\r\n", type) < 0)
+ return (0);
+
+ return (1);
+}
+
+
+/*
+ * 'UpdateCGI()' - Read status messages from CGI scripts and programs.
+ */
+
+void
+UpdateCGI(void)
+{
+ int bytes; /* Number of bytes read */
+ char *lineptr, /* Pointer to end of line in buffer */
+ *message; /* Pointer to message text */
+ int loglevel; /* Log level for message */
+ static int bufused = 0; /* Number of bytes used in buffer */
+ static char buffer[1024]; /* Status buffer */
+
+
+ if ((bytes = read(CGIPipes[0], buffer + bufused,
+ sizeof(buffer) - bufused - 1)) > 0)
+ {
+ bufused += bytes;
+ buffer[bufused] = '\0';
+ lineptr = strchr(buffer, '\n');
+ }
+ else if (bytes < 0 && errno == EINTR)
+ return;
+ else
+ {
+ lineptr = buffer + bufused;
+ lineptr[1] = 0;
+ }
+
+ if (bytes == 0 && bufused == 0)
+ lineptr = NULL;
+
+ while (lineptr != NULL)
+ {
+ /*
+ * Terminate each line and process it...
+ */
+
+ *lineptr++ = '\0';
+
+ /*
+ * Figure out the logging level...
+ */
+
+ if (strncmp(buffer, "EMERG:", 6) == 0)
+ {
+ loglevel = L_EMERG;
+ message = buffer + 6;
+ }
+ else if (strncmp(buffer, "ALERT:", 6) == 0)
+ {
+ loglevel = L_ALERT;
+ message = buffer + 6;
+ }
+ else if (strncmp(buffer, "CRIT:", 5) == 0)
+ {
+ loglevel = L_CRIT;
+ message = buffer + 5;
+ }
+ else if (strncmp(buffer, "ERROR:", 6) == 0)
+ {
+ loglevel = L_ERROR;
+ message = buffer + 6;
+ }
+ else if (strncmp(buffer, "WARNING:", 8) == 0)
+ {
+ loglevel = L_WARN;
+ message = buffer + 8;
+ }
+ else if (strncmp(buffer, "NOTICE:", 6) == 0)
+ {
+ loglevel = L_NOTICE;
+ message = buffer + 6;
+ }
+ else if (strncmp(buffer, "INFO:", 5) == 0)
+ {
+ loglevel = L_INFO;
+ message = buffer + 5;
+ }
+ else if (strncmp(buffer, "DEBUG:", 6) == 0)
+ {
+ loglevel = L_DEBUG;
+ message = buffer + 6;
+ }
+ else if (strncmp(buffer, "DEBUG2:", 7) == 0)
+ {
+ loglevel = L_DEBUG2;
+ message = buffer + 7;
+ }
+ else if (strncmp(buffer, "PAGE:", 5) == 0)
+ {
+ loglevel = L_PAGE;
+ message = buffer + 5;
+ }
+ else
+ {
+ loglevel = L_DEBUG;
+ message = buffer;
+ }
+
+ /*
+ * Skip leading whitespace in the message...
+ */
+
+ while (isspace(*message))
+ message ++;
+
+ LogMessage(loglevel, "[CGI] %s", message);
+
+ /*
+ * Copy over the buffer data we've used up...
+ */
+
+ strcpy(buffer, lineptr);
+ bufused -= lineptr - buffer;
+
+ if (bufused < 0)
+ bufused = 0;
+
+ lineptr = strchr(buffer, '\n');
+ }
+
+ if (bytes <= 0)
+ {
+ /*
+ * Fatal error on pipe - should never happen!
+ */
+
+ LogMessage(L_ERROR, "UpdateCGI: error reading from CGI error pipe - %s",
+ strerror(errno));
+ }
+}
+
+
+/*
+ * 'WriteClient()' - Write data to a client as needed.
+ */
+
+int /* O - 1 if success, 0 if fail */
+WriteClient(client_t *con) /* I - Client connection */
+{
+ int bytes; /* Number of bytes written */
+ char buf[HTTP_MAX_BUFFER + 1];/* Data buffer */
+ char *bufptr; /* Pointer into buffer */
+ ipp_state_t ipp_state; /* IPP state value */
+
+
+#ifdef DEBUG
+ LogMessage(L_DEBUG2, "WriteClient(con=%p) %d response=%p, file=%d pipe_pid=%d",
+ con, con->http.fd, con->response, con->file, con->pipe_pid);
+#endif /* DEBUG */
+
+ if (con->http.state != HTTP_GET_SEND &&
+ con->http.state != HTTP_POST_SEND)
+ return (1);
+
+ if (con->response != NULL)
+ {
+ ipp_state = ippWrite(&(con->http), con->response);
+ bytes = ipp_state != IPP_ERROR && ipp_state != IPP_DATA;
+ }
+ else if ((bytes = read(con->file, buf, HTTP_MAX_BUFFER)) > 0)
+ {
+#ifdef DEBUG
+ LogMessage(L_DEBUG2, "WriteClient: Read %d bytes from file %d...",
+ bytes, con->file);
+#endif /* DEBUG */
+
+ if (con->pipe_pid && !con->got_fields)
+ {
+ /*
+ * Inspect the data for Content-Type and other fields.
+ */
+
+ buf[bytes] = '\0';
+
+ for (bufptr = buf; !con->got_fields && *bufptr; bufptr ++)
+ if (*bufptr == '\n')
+ {
+ /*
+ * Send line to client...
+ */
+
+ if (bufptr > buf && bufptr[-1] == '\r')
+ bufptr[-1] = '\0';
+ *bufptr++ = '\0';
+
+ httpPrintf(HTTP(con), "%s\r\n", buf);
+ LogMessage(L_DEBUG2, "WriteClient: %d %s", con->http.fd, buf);
+
+ /*
+ * Update buffer...
+ */
+
+ bytes -= (bufptr - buf);
+ memmove(buf, bufptr, bytes + 1);
+ bufptr = buf - 1;
+
+ /*
+ * See if the line was empty...
+ */
+
+ if (con->field_col == 0)
+ con->got_fields = 1;
+ else
+ con->field_col = 0;
+ }
+ else if (*bufptr != '\r')
+ con->field_col ++;
+
+ if (bytes > 0 && !con->got_fields)
+ {
+ /*
+ * Remaining text needs to go out...
+ */
+
+ httpPrintf(HTTP(con), "%s", buf);
+
+ con->http.activity = time(NULL);
+ return (1);
+ }
+ else if (bytes == 0)
+ {
+ con->http.activity = time(NULL);
+ return (1);
+ }
+ }
+
+ if (httpWrite(HTTP(con), buf, bytes) < 0)
+ {
+ CloseClient(con);
+ return (0);
+ }
+
+ con->bytes += bytes;
+ }
+
+ if (bytes <= 0)
+ {
+ LogRequest(con, HTTP_OK);
+
+ if (con->http.data_encoding == HTTP_ENCODE_CHUNKED)
+ {
+ if (httpPrintf(HTTP(con), "0\r\n\r\n") < 0)
+ {
+ CloseClient(con);
+ return (0);
+ }
+ }
+
+ con->http.state = HTTP_WAITING;
+
+ LogMessage(L_DEBUG2, "WriteClient: Removing fd %d from OutputSet...",
+ con->http.fd);
+
+ FD_CLR(con->http.fd, OutputSet);
+
+ if (con->file >= 0)
+ {
+ if (FD_ISSET(con->file, InputSet))
+ {
+ LogMessage(L_DEBUG2, "WriteClient: Removing fd %d from InputSet...",
+ con->file);
+ FD_CLR(con->file, InputSet);
+ }
+
+ if (con->pipe_pid)
+ kill(con->pipe_pid, SIGTERM);
+
+ LogMessage(L_DEBUG2, "WriteClient: %d Closing data file %d.",
+ con->http.fd, con->file);
+
+ close(con->file);
+ con->file = -1;
+ con->pipe_pid = 0;
+ }
+
+ if (con->filename)
+ {
+ LogMessage(L_DEBUG2, "WriteClient: %d Removing temp file %s",
+ con->http.fd, con->filename);
+ unlink(con->filename);
+ ClearString(&con->filename);
+ }
+
+ if (con->request != NULL)
+ {
+ ippDelete(con->request);
+ con->request = NULL;
+ }
+
+ if (con->response != NULL)
+ {
+ ippDelete(con->response);
+ con->response = NULL;
+ }
+
+ ClearString(&con->command);
+ ClearString(&con->options);
+
+ if (!con->http.keep_alive)
+ {
+ CloseClient(con);
+ return (0);
+ }
+ }
+ else
+ {
+ con->file_ready = 0;
+
+ if (con->pipe_pid && !FD_ISSET(con->file, InputSet))
+ {
+ LogMessage(L_DEBUG2, "WriteClient: Adding fd %d to InputSet...", con->file);
+ FD_SET(con->file, InputSet);
+ }
+ }
+
+ if (bytes >= 1024)
+ LogMessage(L_DEBUG2, "WriteClient: %d %d bytes", con->http.fd, bytes);
+
+ con->http.activity = time(NULL);
+
+ return (1);
+}
+
+
+/*
+ * 'check_if_modified()' - Decode an "If-Modified-Since" line.
+ */
+
+static int /* O - 1 if modified since */
+check_if_modified(client_t *con, /* I - Client connection */
+ struct stat *filestats) /* I - File information */
+{
+ char *ptr; /* Pointer into field */
+ time_t date; /* Time/date value */
+ int size; /* Size/length value */
+
+
+ size = 0;
+ date = 0;
+ ptr = con->http.fields[HTTP_FIELD_IF_MODIFIED_SINCE];
+
+ if (*ptr == '\0')
+ return (1);
+
+ LogMessage(L_DEBUG2, "check_if_modified: %d If-Modified-Since=\"%s\"",
+ con->http.fd, ptr);
+
+ while (*ptr != '\0')
+ {
+ while (isspace(*ptr) || *ptr == ';')
+ ptr ++;
+
+ if (strncasecmp(ptr, "length=", 7) == 0)
+ {
+ ptr += 7;
+ size = atoi(ptr);
+
+ while (isdigit(*ptr))
+ ptr ++;
+ }
+ else if (isalpha(*ptr))
+ {
+ date = httpGetDateTime(ptr);
+ while (*ptr != '\0' && *ptr != ';')
+ ptr ++;
+ }
+ }
+
+ LogMessage(L_DEBUG2, "check_if_modified: %d sizes=%d,%d dates=%d,%d",
+ con->http.fd, size, (int)filestats->st_size, (int)date,
+ (int)filestats->st_mtime);
+
+ return ((size != filestats->st_size && size != 0) ||
+ (date < filestats->st_mtime && date != 0) ||
+ (size == 0 && date == 0));
+}
+
+
+/*
+ * 'decode_auth()' - Decode an authorization string.
+ */
+
+static void
+decode_auth(client_t *con) /* I - Client to decode to */
+{
+ char *s, /* Authorization string */
+ value[1024]; /* Value string */
+ const char *username; /* Certificate username */
+
+
+ /*
+ * Decode the string...
+ */
+
+ s = con->http.fields[HTTP_FIELD_AUTHORIZATION];
+
+ LogMessage(L_DEBUG2, "decode_auth(%p): Authorization string = \"%s\"",
+ con, s);
+
+ if (strncmp(s, "Basic", 5) == 0)
+ {
+ s += 5;
+ while (isspace(*s))
+ s ++;
+
+ httpDecode64(value, s);
+
+ /*
+ * Pull the username and password out...
+ */
+
+ if ((s = strchr(value, ':')) == NULL)
+ {
+ LogMessage(L_DEBUG, "decode_auth: %d no colon in auth string \"%s\"",
+ con->http.fd, value);
+ return;
+ }
+
+ *s++ = '\0';
+
+ strlcpy(con->username, value, sizeof(con->username));
+ strlcpy(con->password, s, sizeof(con->password));
+ }
+ else if (strncmp(s, "Local", 5) == 0)
+ {
+ s += 5;
+ while (isspace(*s))
+ s ++;
+
+ if ((username = FindCert(s)) != NULL)
+ strlcpy(con->username, username, sizeof(con->username));
+ }
+ else if (strncmp(s, "Digest", 5) == 0)
+ {
+ /*
+ * Get the username and password from the Digest attributes...
+ */
+
+ if (httpGetSubField(&(con->http), HTTP_FIELD_AUTHORIZATION, "username",
+ value))
+ strlcpy(con->username, value, sizeof(con->username));
+
+ if (httpGetSubField(&(con->http), HTTP_FIELD_AUTHORIZATION, "response",
+ value))
+ strlcpy(con->password, value, sizeof(con->password));
+ }
+
+ LogMessage(L_DEBUG2, "decode_auth: %d username=\"%s\"",
+ con->http.fd, con->username);
+}
+
+
+/*
+ * 'get_file()' - Get a filename and state info.
+ */
+
+static char * /* O - Real filename */
+get_file(client_t *con, /* I - Client connection */
+ struct stat *filestats, /* O - File information */
+ char *filename, /* IO - Filename buffer */
+ int len) /* I - Buffer length */
+{
+ int status; /* Status of filesystem calls */
+ char *ptr; /* Pointer info filename */
+ int plen; /* Remaining length after pointer */
+
+
+ /*
+ * Need to add DocumentRoot global...
+ */
+
+ if (strncmp(con->uri, "/ppd/", 5) == 0)
+ snprintf(filename, len, "%s%s", ServerRoot, con->uri);
+ else if (strncmp(con->uri, "/admin/conf/", 12) == 0)
+ snprintf(filename, len, "%s%s", ServerRoot, con->uri + 11);
+ else if (con->language != NULL)
+ snprintf(filename, len, "%s/%s%s", DocumentRoot, con->language->language,
+ con->uri);
+ else
+ snprintf(filename, len, "%s%s", DocumentRoot, con->uri);
+
+ if ((ptr = strchr(filename, '?')) != NULL)
+ *ptr = '\0';
+
+ /*
+ * Grab the status for this language; if there isn't a language-specific file
+ * then fallback to the default one...
+ */
+
+ if ((status = stat(filename, filestats)) != 0 && con->language != NULL)
+ {
+ /*
+ * Drop the language prefix and try the current directory...
+ */
+
+ if (strncmp(con->uri, "/ppd/", 5) != 0 &&
+ strncmp(con->uri, "/admin/conf/", 12) != 0)
+ {
+ snprintf(filename, len, "%s%s", DocumentRoot, con->uri);
+
+ if ((ptr = strchr(filename, '?')) != NULL)
+ *ptr = '\0';
+
+ status = stat(filename, filestats);
+ }
+ }
+
+ /*
+ * If we're found a directory, get the index.html file instead...
+ */
+
+ if (!status && S_ISDIR(filestats->st_mode))
+ {
+ if (filename[strlen(filename) - 1] != '/')
+ strlcat(filename, "/", len);
+
+ ptr = filename + strlen(filename);
+ plen = len - (ptr - filename);
+
+ strlcpy(ptr, "index.html", plen);
+ status = stat(filename, filestats);
+
+#ifdef HAVE_JAVA
+ if (status)
+ {
+ strlcpy(ptr, "index.class", plen);
+ status = stat(filename, filestats);
+ }
+#endif /* HAVE_JAVA */
+
+#ifdef HAVE_PERL
+ if (status)
+ {
+ strlcpy(ptr, "index.pl", plen);
+ status = stat(filename, filestats);
+ }
+#endif /* HAVE_PERL */
+
+#ifdef HAVE_PHP
+ if (status)
+ {
+ strlcpy(ptr, "index.php", plen);
+ status = stat(filename, filestats);
+ }
+#endif /* HAVE_PHP */
+
+#ifdef HAVE_PYTHON
+ if (status)
+ {
+ strlcpy(ptr, "index.pyc", plen);
+ status = stat(filename, filestats);
+ }
+
+ if (status)
+ {
+ strlcpy(ptr, "index.py", plen);
+ status = stat(filename, filestats);
+ }
+#endif /* HAVE_PYTHON */
+ }
+
+ LogMessage(L_DEBUG2, "get_file: %d filename=%s size=%d",
+ con->http.fd, filename, status ? -1 : (int)filestats->st_size);
+
+ if (status)
+ return (NULL);
+ else
+ return (filename);
+}
+
+
+/*
+ * 'install_conf_file()' - Install a configuration file.
+ */
+
+static http_status_t /* O - Status */
+install_conf_file(client_t *con) /* I - Connection */
+{
+ cups_file_t *in, /* Input file */
+ *out; /* Output file */
+ char buffer[1024]; /* Copy buffer */
+ int bytes; /* Number of bytes */
+ char conffile[1024], /* Configuration filename */
+ newfile[1024], /* New config filename */
+ oldfile[1024]; /* Old config filename */
+ struct stat confinfo; /* Config file info */
+
+
+ /*
+ * First construct the filenames...
+ */
+
+ snprintf(conffile, sizeof(conffile), "%s%s", ServerRoot, con->uri + 11);
+ snprintf(newfile, sizeof(newfile), "%s%s.N", ServerRoot, con->uri + 11);
+ snprintf(oldfile, sizeof(oldfile), "%s%s.O", ServerRoot, con->uri + 11);
+
+ LogMessage(L_INFO, "Installing config file \"%s\"...", conffile);
+
+ /*
+ * Get the owner, group, and permissions of the configuration file.
+ * If it doesn't exist, assign it to the User and Group in the
+ * cupsd.conf file with mode 0640 permissions.
+ */
+
+ if (stat(conffile, &confinfo))
+ {
+ confinfo.st_uid = User;
+ confinfo.st_gid = Group;
+ confinfo.st_mode = ConfigFilePerm;
+ }
+
+ /*
+ * Open the request file and new config file...
+ */
+
+ if ((in = cupsFileOpen(con->filename, "rb")) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to open request file \"%s\" - %s",
+ con->filename, strerror(errno));
+ return (HTTP_SERVER_ERROR);
+ }
+
+ if ((out = cupsFileOpen(newfile, "wb")) == NULL)
+ {
+ cupsFileClose(in);
+ LogMessage(L_ERROR, "Unable to open config file \"%s\" - %s",
+ newfile, strerror(errno));
+ return (HTTP_SERVER_ERROR);
+ }
+
+ fchmod(cupsFileNumber(out), confinfo.st_mode);
+ fchown(cupsFileNumber(out), confinfo.st_uid, confinfo.st_gid);
+
+ /*
+ * Copy from the request to the new config file...
+ */
+
+ while ((bytes = cupsFileRead(in, buffer, sizeof(buffer))) > 0)
+ if (cupsFileWrite(out, buffer, bytes) < bytes)
+ {
+ LogMessage(L_ERROR, "Unable to copy to config file \"%s\" - %s",
+ newfile, strerror(errno));
+
+ cupsFileClose(in);
+ cupsFileClose(out);
+ unlink(newfile);
+
+ return (HTTP_SERVER_ERROR);
+ }
+
+ /*
+ * Close the files...
+ */
+
+ cupsFileClose(in);
+ if (cupsFileClose(out))
+ {
+ LogMessage(L_ERROR, "Error file closing config file \"%s\" - %s",
+ newfile, strerror(errno));
+
+ unlink(newfile);
+
+ return (HTTP_SERVER_ERROR);
+ }
+
+ /*
+ * Remove the request file...
+ */
+
+ unlink(con->filename);
+ ClearString(&con->filename);
+
+ /*
+ * Unlink the old backup, rename the current config file to the backup
+ * filename, and rename the new config file to the config file name...
+ */
+
+ if (unlink(oldfile))
+ if (errno != ENOENT)
+ {
+ LogMessage(L_ERROR, "Unable to remove backup config file \"%s\" - %s",
+ oldfile, strerror(errno));
+
+ unlink(newfile);
+
+ return (HTTP_SERVER_ERROR);
+ }
+
+ if (rename(conffile, oldfile))
+ if (errno != ENOENT)
+ {
+ LogMessage(L_ERROR, "Unable to rename old config file \"%s\" - %s",
+ conffile, strerror(errno));
+
+ unlink(newfile);
+
+ return (HTTP_SERVER_ERROR);
+ }
+
+ if (rename(newfile, conffile))
+ {
+ LogMessage(L_ERROR, "Unable to rename new config file \"%s\" - %s",
+ newfile, strerror(errno));
+
+ rename(oldfile, conffile);
+ unlink(newfile);
+
+ return (HTTP_SERVER_ERROR);
+ }
+
+ /*
+ * If the cupsd.conf file was updated, set the NeedReload flag...
+ */
+
+ if (strcmp(con->uri, "/admin/conf/cupsd.conf") == 0)
+ NeedReload = RELOAD_CUPSD;
+ else
+ NeedReload = RELOAD_ALL;
+
+ ReloadTime = time(NULL);
+
+ /*
+ * Return that the file was created successfully...
+ */
+
+ return (HTTP_CREATED);
+}
+
+
+/*
+ * 'is_path_absolute()' - Is a path absolute and free of relative elements (i.e. "..").
+ */
+
+static int /* O - 0 if relative, 1 if absolute */
+is_path_absolute(const char *path) /* I - Input path */
+{
+ /*
+ * Check for a leading slash...
+ */
+
+ if (path[0] != '/')
+ return (0);
+
+ /*
+ * Check for "/.." in the path...
+ */
+
+ while ((path = strstr(path, "/..")) != NULL)
+ if (!path[3] || path[3] == '/')
+ return (0);
+
+ /*
+ * If we haven't found any relative paths, return 1 indicating an
+ * absolute path...
+ */
+
+ return (1);
+}
+
+
+/*
+ * 'pipe_command()' - Pipe the output of a command to the remote client.
+ */
+
+static int /* O - Process ID */
+pipe_command(client_t *con, /* I - Client connection */
+ int infile, /* I - Standard input for command */
+ int *outfile, /* O - Standard output for command */
+ char *command, /* I - Command to run */
+ char *options) /* I - Options for command */
+{
+ int i; /* Looping var */
+ int pid; /* Process ID */
+ char *commptr; /* Command string pointer */
+ char *uriptr; /* URI string pointer */
+ int fds[2]; /* Pipe FDs */
+ int argc; /* Number of arguments */
+ int envc; /* Number of environment variables */
+ char argbuf[10240], /* Argument buffer */
+ *argv[100], /* Argument strings */
+ *envp[100]; /* Environment variables */
+ char content_length[1024], /* CONTENT_LENGTH environment variable */
+ content_type[1024], /* CONTENT_TYPE environment variable */
+ cups_datadir[1024], /* CUPS_DATADIR environment variable */
+ cups_serverroot[1024], /* CUPS_SERVERROOT environment variable */
+ http_cookie[1024], /* HTTP_COOKIE environment variable */
+ http_user_agent[1024], /* HTTP_USER_AGENT environment variable */
+ ipp_port[1024], /* IPP_PORT environment variable */
+ lang[1024], /* LANG environment variable */
+ ld_library_path[1024], /* LD_LIBRARY_PATH environment variable */
+ ld_preload[1024], /* LD_PRELOAD environment variable */
+ dyld_library_path[1024],/* DYLD_LIBRARY_PATH environment variable */
+ shlib_path[1024], /* SHLIB_PATH environment variable */
+ nlspath[1024], /* NLSPATH environment variable */
+ *query_string, /* QUERY_STRING env variable */
+ remote_addr[1024], /* REMOTE_ADDR environment variable */
+ remote_host[1024], /* REMOTE_HOST environment variable */
+ remote_user[1024], /* REMOTE_USER environment variable */
+ script_name[1024], /* SCRIPT_NAME environment variable */
+ server_name[1024], /* SERVER_NAME environment variable */
+ server_port[1024], /* SERVER_PORT environment variable */
+ tmpdir[1024], /* TMPDIR environment variable */
+ vg_args[1024], /* VG_ARGS environment variable */
+ ld_assume_kernel[1024]; /* LD_ASSUME_KERNEL environment variable */
+ unsigned address; /* Address of client */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* POSIX signal handler */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+ static const char * const locale_encodings[] =
+ { /* Locale charset names */
+ "ASCII",
+ "ISO8859-1",
+ "ISO8859-2",
+ "ISO8859-3",
+ "ISO8859-4",
+ "ISO8859-5",
+ "ISO8859-6",
+ "ISO8859-7",
+ "ISO8859-8",
+ "ISO8859-9",
+ "ISO8859-10",
+ "UTF-8",
+ "ISO8859-13",
+ "ISO8859-14",
+ "ISO8859-15",
+ "CP874",
+ "CP1250",
+ "CP1251",
+ "CP1252",
+ "CP1253",
+ "CP1254",
+ "CP1255",
+ "CP1256",
+ "CP1257",
+ "CP1258",
+ "KOI8R",
+ "KOI8U"
+ };
+ static const char * const encryptions[] =
+ {
+ "CUPS_ENCRYPTION=IfRequested",
+ "CUPS_ENCRYPTION=Never",
+ "CUPS_ENCRYPTION=Required",
+ "CUPS_ENCRYPTION=Always"
+ };
+
+
+ /*
+ * Parse a copy of the options string, which is of the form:
+ *
+ * name argument+argument+argument
+ * name?argument+argument+argument
+ * name param=value&param=value
+ * name?param=value&param=value
+ *
+ * If the string contains an "=" character after the initial name,
+ * then we treat it as a HTTP GET form request and make a copy of
+ * the remaining string for the environment variable.
+ *
+ * The string is always parsed out as command-line arguments, to
+ * be consistent with Apache...
+ */
+
+ LogMessage(L_DEBUG2, "pipe_command: command=\"%s\", options=\"%s\"",
+ command, options);
+
+ strlcpy(argbuf, options, sizeof(argbuf));
+
+ argv[0] = argbuf;
+ query_string = NULL;
+
+ for (commptr = argbuf, argc = 1; *commptr != '\0' && argc < 99; commptr ++)
+ {
+ /*
+ * Break arguments whenever we see a + or space...
+ */
+
+ if (*commptr == ' ' || *commptr == '+' || (*commptr == '?' && argc == 1))
+ {
+ /*
+ * Terminate the current string and skip trailing whitespace...
+ */
+
+ *commptr++ = '\0';
+
+ while (*commptr == ' ')
+ commptr ++;
+
+ /*
+ * If we don't have a blank string, save it as another argument...
+ */
+
+ if (*commptr)
+ {
+ argv[argc] = commptr;
+ argc ++;
+ }
+ else
+ break;
+
+ /*
+ * If we see an "=" in the remaining string, make a copy of it since
+ * it will be query data...
+ */
+
+ if (argc == 2 && strchr(commptr, '=') && con->operation == HTTP_GET)
+ SetStringf(&query_string, "QUERY_STRING=%s", commptr);
+
+ /*
+ * Don't skip the first non-blank character...
+ */
+
+ commptr --;
+ }
+ else if (*commptr == '%' && isxdigit(commptr[1] & 255) &&
+ isxdigit(commptr[2] & 255))
+ {
+ /*
+ * Convert the %xx notation to the individual character.
+ */
+
+ if (commptr[1] >= '0' && commptr[1] <= '9')
+ *commptr = (commptr[1] - '0') << 4;
+ else
+ *commptr = (tolower(commptr[1]) - 'a' + 10) << 4;
+
+ if (commptr[2] >= '0' && commptr[2] <= '9')
+ *commptr |= commptr[2] - '0';
+ else
+ *commptr |= tolower(commptr[2]) - 'a' + 10;
+
+ cups_strcpy(commptr + 1, commptr + 3);
+
+ /*
+ * Check for a %00 and break if that is the case...
+ */
+
+ if (!*commptr)
+ break;
+ }
+ }
+
+ argv[argc] = NULL;
+
+ if (argv[0][0] == '\0')
+ argv[0] = strrchr(command, '/') + 1;
+
+ /*
+ * Setup the environment variables as needed...
+ */
+
+ address = ntohl(con->http.hostaddr.sin_addr.s_addr);
+
+ if (con->language)
+ snprintf(lang, sizeof(lang), "LANG=%s.%s", con->language->language,
+ locale_encodings[con->language->encoding]);
+ else
+ strcpy(lang, "LANG=C");
+
+ sprintf(ipp_port, "IPP_PORT=%d", LocalPort);
+ sprintf(server_port, "SERVER_PORT=%d", ntohs(con->http.hostaddr.sin_port));
+ if (!strcmp(con->http.hostname, "localhost"))
+ strlcpy(server_name, "SERVER_NAME=localhost", sizeof(server_name));
+ else
+ snprintf(server_name, sizeof(server_name), "SERVER_NAME=%s", ServerName);
+ snprintf(remote_host, sizeof(remote_host), "REMOTE_HOST=%s", con->http.hostname);
+ snprintf(remote_addr, sizeof(remote_addr), "REMOTE_ADDR=%d.%d.%d.%d",
+ (address >> 24) & 255, (address >> 16) & 255,
+ (address >> 8) & 255, address & 255);
+ snprintf(remote_user, sizeof(remote_user), "REMOTE_USER=%s", con->username);
+ snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
+ snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
+ snprintf(cups_serverroot, sizeof(cups_serverroot), "CUPS_SERVERROOT=%s", ServerRoot);
+
+ envc = 0;
+
+ envp[envc ++] = "PATH=/bin:/usr/bin";
+ envp[envc ++] = "SERVER_SOFTWARE=CUPS/1.1";
+ envp[envc ++] = "GATEWAY_INTERFACE=CGI/1.1";
+ if (con->http.version == HTTP_1_1)
+ envp[envc ++] = "SERVER_PROTOCOL=HTTP/1.1";
+ else if (con->http.version == HTTP_1_0)
+ envp[envc ++] = "SERVER_PROTOCOL=HTTP/1.0";
+ else
+ envp[envc ++] = "SERVER_PROTOCOL=HTTP/0.9";
+ envp[envc ++] = "REDIRECT_STATUS=1";
+ envp[envc ++] = "CUPS_SERVER=localhost";
+ envp[envc ++] = ipp_port;
+ envp[envc ++] = server_name;
+ envp[envc ++] = server_port;
+ envp[envc ++] = remote_addr;
+ envp[envc ++] = remote_host;
+ envp[envc ++] = remote_user;
+ envp[envc ++] = lang;
+ envp[envc ++] = TZ;
+ envp[envc ++] = tmpdir;
+ envp[envc ++] = cups_datadir;
+ envp[envc ++] = cups_serverroot;
+
+ if (getenv("VG_ARGS") != NULL)
+ {
+ snprintf(vg_args, sizeof(vg_args), "VG_ARGS=%s", getenv("VG_ARGS"));
+ envp[envc ++] = vg_args;
+ }
+
+ if (getenv("LD_ASSUME_KERNEL") != NULL)
+ {
+ snprintf(ld_assume_kernel, sizeof(ld_assume_kernel), "LD_ASSUME_KERNEL=%s",
+ getenv("LD_ASSUME_KERNEL"));
+ envp[envc ++] = ld_assume_kernel;
+ }
+
+ if (getenv("LD_LIBRARY_PATH") != NULL)
+ {
+ snprintf(ld_library_path, sizeof(ld_library_path), "LD_LIBRARY_PATH=%s",
+ getenv("LD_LIBRARY_PATH"));
+ envp[envc ++] = ld_library_path;
+ }
+
+ if (getenv("LD_PRELOAD") != NULL)
+ {
+ snprintf(ld_preload, sizeof(ld_preload), "LD_PRELOAD=%s",
+ getenv("LD_PRELOAD"));
+ envp[envc ++] = ld_preload;
+ }
+
+ if (getenv("DYLD_LIBRARY_PATH") != NULL)
+ {
+ snprintf(dyld_library_path, sizeof(dyld_library_path), "DYLD_LIBRARY_PATH=%s",
+ getenv("DYLD_LIBRARY_PATH"));
+ envp[envc ++] = dyld_library_path;
+ }
+
+ if (getenv("SHLIB_PATH") != NULL)
+ {
+ snprintf(shlib_path, sizeof(shlib_path), "SHLIB_PATH=%s",
+ getenv("SHLIB_PATH"));
+ envp[envc ++] = shlib_path;
+ }
+
+ if (getenv("NLSPATH") != NULL)
+ {
+ snprintf(nlspath, sizeof(nlspath), "NLSPATH=%s", getenv("NLSPATH"));
+ envp[envc ++] = nlspath;
+ }
+
+ if (con->http.cookie)
+ {
+ snprintf(http_cookie, sizeof(http_cookie), "HTTP_COOKIE=%s",
+ con->http.cookie);
+ envp[envc ++] = http_cookie;
+ }
+
+ if (con->http.fields[HTTP_FIELD_USER_AGENT][0])
+ {
+ snprintf(http_user_agent, sizeof(http_user_agent), "HTTP_USER_AGENT=%s",
+ con->http.fields[HTTP_FIELD_USER_AGENT]);
+ envp[envc ++] = http_user_agent;
+ }
+
+ snprintf(script_name, sizeof(script_name), "SCRIPT_NAME=%s", con->uri);
+ if ((uriptr = strchr(script_name, '?')) != NULL)
+ *uriptr = '\0';
+ envp[envc ++] = script_name;
+
+ if (con->operation == HTTP_GET)
+ {
+ envp[envc ++] = "REQUEST_METHOD=GET";
+
+ if (query_string)
+ {
+ /*
+ * Add GET form variables after ?...
+ */
+
+ envp[envc ++] = query_string;
+ }
+ }
+ else
+ {
+ sprintf(content_length, "CONTENT_LENGTH=%d", con->bytes);
+ snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s",
+ con->http.fields[HTTP_FIELD_CONTENT_TYPE]);
+
+ envp[envc ++] = "REQUEST_METHOD=POST";
+ envp[envc ++] = content_length;
+ envp[envc ++] = content_type;
+ }
+
+ /*
+ * Tell the CGI if we are using encryption...
+ */
+
+ if (con->http.encryption == HTTP_ENCRYPT_ALWAYS)
+ envp[envc ++] = "HTTPS=ON";
+
+ envp[envc ++] = (char *)encryptions[LocalEncryption];
+
+ /*
+ * Terminate the environment array...
+ */
+
+ envp[envc] = NULL;
+
+ if (LogLevel == L_DEBUG2)
+ {
+ for (i = 0; i < argc; i ++)
+ LogMessage(L_DEBUG2, "pipe_command: argv[%d] = \"%s\"", i, argv[i]);
+ for (i = 0; i < envc; i ++)
+ LogMessage(L_DEBUG2, "pipe_command: envp[%d] = \"%s\"", i, envp[i]);
+ }
+
+ /*
+ * Create a pipe for the output...
+ */
+
+ if (cupsdOpenPipe(fds))
+ {
+ ClearString(&query_string);
+
+ LogMessage(L_ERROR, "Unable to create pipes for CGI %s - %s",
+ argv[0], strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Block signals before forking...
+ */
+
+ HoldSignals();
+
+ /*
+ * Then execute the command...
+ */
+
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child comes here... Close stdin if necessary and dup the pipe to stdout.
+ */
+
+ if (!RunUser)
+ {
+ /*
+ * Running as root, so change to a non-priviledged user...
+ */
+
+ if (setgid(Group))
+ exit(errno);
+
+ if (setgroups(1, &Group))
+ exit(errno);
+
+ if (setuid(User))
+ exit(errno);
+ }
+ else
+ {
+ /*
+ * Reset group membership to just the main one we belong to.
+ */
+
+ setgroups(1, &Group);
+ }
+
+ /*
+ * Update stdin/stdout/stderr...
+ */
+
+ if (infile)
+ {
+ close(0);
+ if (dup(infile) < 0)
+ exit(errno);
+ }
+
+ close(1);
+ if (dup(fds[1]) < 0)
+ exit(errno);
+
+ close(2);
+ dup(CGIPipes[1]);
+
+ /*
+ * Change umask to restrict permissions on created files...
+ */
+
+ umask(077);
+
+ /*
+ * Unblock signals before doing the exec...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_DFL);
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+#endif /* HAVE_SIGSET */
+
+ ReleaseSignals();
+
+ /*
+ * Execute the pipe program; if an error occurs, exit with status 1...
+ */
+
+ execve(command, argv, envp);
+ exit(errno);
+ return (0);
+ }
+ else if (pid < 0)
+ {
+ /*
+ * Error - can't fork!
+ */
+
+ LogMessage(L_ERROR, "Unable to fork for CGI %s - %s", argv[0],
+ strerror(errno));
+
+ cupsdClosePipe(fds);
+ pid = 0;
+ }
+ else
+ {
+ /*
+ * Fork successful - return the PID...
+ */
+
+ AddCert(pid, con->username);
+
+ LogMessage(L_DEBUG, "CGI %s started - PID = %d", command, pid);
+
+ *outfile = fds[0];
+ close(fds[1]);
+ }
+
+ ReleaseSignals();
+
+ ClearString(&query_string);
+
+ return (pid);
+}
+
+
+#if defined(HAVE_CDSASSL)
+/*
+ * 'CDSAReadFunc()' - Read function for CDSA decryption code.
+ */
+
+static OSStatus /* O - -1 on error, 0 on success */
+CDSAReadFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
+ void *data, /* I - Data buffer */
+ size_t *dataLength) /* IO - Number of bytes */
+{
+ ssize_t bytes; /* Number of bytes read */
+
+
+ bytes = recv((int)connection, data, *dataLength, 0);
+ if (bytes >= 0)
+ {
+ *dataLength = bytes;
+ return (0);
+ }
+ else
+ return (-1);
+}
+
+
+/*
+ * 'CDSAWriteFunc()' - Write function for CDSA encryption code.
+ */
+
+static OSStatus /* O - -1 on error, 0 on success */
+CDSAWriteFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
+ const void *data, /* I - Data buffer */
+ size_t *dataLength) /* IO - Number of bytes */
+{
+ ssize_t bytes;
+
+
+ bytes = write((int)connection, data, *dataLength);
+ if (bytes >= 0)
+ {
+ *dataLength = bytes;
+ return (0);
+ }
+ else
+ return (-1);
+}
+#endif /* HAVE_CDSASSL */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/client.h b/scheduler/client.h
new file mode 100644
index 000000000..6188122ce
--- /dev/null
+++ b/scheduler/client.h
@@ -0,0 +1,118 @@
+/*
+ * "$Id$"
+ *
+ * Client definitions for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * HTTP client structure...
+ */
+
+typedef struct
+{
+ http_t http; /* HTTP client connection */
+ ipp_t *request, /* IPP request information */
+ *response; /* IPP response information */
+ time_t start; /* Request start time */
+ http_state_t operation; /* Request operation */
+ int bytes; /* Bytes transferred for this request */
+ char username[33], /* Username from Authorization: line */
+ password[33], /* Password from Authorization: line */
+ uri[HTTP_MAX_URI], /* Localized URL/URI for GET/PUT */
+ *filename, /* Filename of output file */
+ *command, /* Command to run */
+ *options; /* Options for command */
+ int file; /* Input/output file */
+ int file_ready; /* Input ready on file/pipe? */
+ int pipe_pid; /* Pipe process ID (or 0 if not a pipe) */
+ int got_fields, /* Non-zero if all fields seen */
+ field_col; /* Column within line */
+ cups_lang_t *language; /* Language to use */
+} client_t;
+
+#define HTTP(con) &((con)->http)
+
+
+/*
+ * HTTP listener structure...
+ */
+
+typedef struct
+{
+ int fd; /* File descriptor for this server */
+ struct sockaddr_in address; /* Bind address of socket */
+ http_encryption_t encryption; /* To encrypt or not to encrypt... */
+} listener_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int ListenBackLog VALUE(SOMAXCONN),
+ /* Max backlog of pending connections */
+ LocalPort VALUE(631);
+ /* Local port to use */
+VAR http_encryption_t LocalEncryption VALUE(HTTP_ENCRYPT_IF_REQUESTED);
+ /* Local port encryption to use */
+VAR int NumListeners VALUE(0);
+ /* Number of listening sockets */
+VAR listener_t *Listeners VALUE(NULL);
+ /* Listening sockets */
+VAR int NumClients VALUE(0);
+ /* Number of HTTP clients */
+VAR client_t *Clients VALUE(NULL);
+ /* HTTP clients */
+VAR struct sockaddr_in ServerAddr; /* Server IP address */
+VAR char *ServerHeader VALUE(NULL);
+ /* Server header in requests */
+VAR int CGIPipes[2] VALUE2(-1,-1);
+ /* Pipes for CGI error/debug output */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void AcceptClient(listener_t *lis);
+extern void CloseAllClients(void);
+extern int CloseClient(client_t *con);
+extern int EncryptClient(client_t *con);
+extern int IsCGI(client_t *con, const char *filename,
+ struct stat *filestats, mime_type_t *type);
+extern void PauseListening(void);
+extern int ProcessIPPRequest(client_t *con);
+extern int ReadClient(client_t *con);
+extern void ResumeListening(void);
+extern int SendCommand(client_t *con, char *command, char *options);
+extern int SendError(client_t *con, http_status_t code);
+extern int SendFile(client_t *con, http_status_t code, char *filename,
+ char *type, struct stat *filestats);
+extern int SendHeader(client_t *con, http_status_t code, char *type);
+extern void ShutdownClient(client_t *con);
+extern void StartListening(void);
+extern void StopListening(void);
+extern void UpdateCGI(void);
+extern int WriteClient(client_t *con);
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/conf.c b/scheduler/conf.c
new file mode 100644
index 000000000..38fca977a
--- /dev/null
+++ b/scheduler/conf.c
@@ -0,0 +1,2232 @@
+/*
+ * "$Id$"
+ *
+ * Configuration routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * ReadConfiguration() - Read the cupsd.conf file.
+ * read_configuration() - Read a configuration file.
+ * read_location() - Read a <Location path> definition.
+ * get_address() - Get an address + port number from a line.
+ * CDSAGetServerCerts() - Convert a keychain name into the CFArrayRef
+ * required by SSLSetCertificate.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <stdarg.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/utsname.h>
+
+#ifdef HAVE_CDSASSL
+# include <Security/SecureTransport.h>
+# include <Security/SecIdentitySearch.h>
+#endif /* HAVE_CDSASSL */
+
+#ifdef HAVE_VSYSLOG
+# include <syslog.h>
+#endif /* HAVE_VSYSLOG */
+
+
+/*
+ * Possibly missing network definitions...
+ */
+
+#ifndef INADDR_NONE
+# define INADDR_NONE 0xffffffff
+#endif /* !INADDR_NONE */
+
+
+/*
+ * Configuration variable structure...
+ */
+
+typedef struct
+{
+ char *name; /* Name of variable */
+ void *ptr; /* Pointer to variable */
+ int type; /* Type (int, string, address) */
+} var_t;
+
+#define VAR_INTEGER 0
+#define VAR_STRING 1
+#define VAR_BOOLEAN 2
+
+
+/*
+ * Local globals...
+ */
+
+static var_t variables[] =
+{
+ { "AccessLog", &AccessLog, VAR_STRING },
+ { "AutoPurgeJobs", &JobAutoPurge, VAR_BOOLEAN },
+ { "BrowseInterval", &BrowseInterval, VAR_INTEGER },
+ { "BrowsePort", &BrowsePort, VAR_INTEGER },
+ { "BrowseShortNames", &BrowseShortNames, VAR_BOOLEAN },
+ { "BrowseTimeout", &BrowseTimeout, VAR_INTEGER },
+ { "Browsing", &Browsing, VAR_BOOLEAN },
+ { "Classification", &Classification, VAR_STRING },
+ { "ClassifyOverride", &ClassifyOverride, VAR_BOOLEAN },
+ { "ConfigFilePerm", &ConfigFilePerm, VAR_INTEGER },
+ { "DataDir", &DataDir, VAR_STRING },
+ { "DefaultCharset", &DefaultCharset, VAR_STRING },
+ { "DefaultLanguage", &DefaultLanguage, VAR_STRING },
+ { "DocumentRoot", &DocumentRoot, VAR_STRING },
+ { "ErrorLog", &ErrorLog, VAR_STRING },
+ { "FaxRetryLimit", &FaxRetryLimit, VAR_INTEGER },
+ { "FaxRetryInterval", &FaxRetryInterval, VAR_INTEGER },
+ { "FileDevice", &FileDevice, VAR_BOOLEAN },
+ { "FilterLimit", &FilterLimit, VAR_INTEGER },
+ { "FilterNice", &FilterNice, VAR_INTEGER },
+ { "FontPath", &FontPath, VAR_STRING },
+ { "HideImplicitMembers", &HideImplicitMembers, VAR_BOOLEAN },
+ { "ImplicitClasses", &ImplicitClasses, VAR_BOOLEAN },
+ { "ImplicitAnyClasses", &ImplicitAnyClasses, VAR_BOOLEAN },
+ { "KeepAliveTimeout", &KeepAliveTimeout, VAR_INTEGER },
+ { "KeepAlive", &KeepAlive, VAR_BOOLEAN },
+ { "LimitRequestBody", &MaxRequestSize, VAR_INTEGER },
+ { "ListenBackLog", &ListenBackLog, VAR_INTEGER },
+ { "LogFilePerm", &LogFilePerm, VAR_INTEGER },
+ { "MaxClients", &MaxClients, VAR_INTEGER },
+ { "MaxClientsPerHost", &MaxClientsPerHost, VAR_INTEGER },
+ { "MaxCopies", &MaxCopies, VAR_INTEGER },
+ { "MaxJobs", &MaxJobs, VAR_INTEGER },
+ { "MaxJobsPerPrinter", &MaxJobsPerPrinter, VAR_INTEGER },
+ { "MaxJobsPerUser", &MaxJobsPerUser, VAR_INTEGER },
+ { "MaxLogSize", &MaxLogSize, VAR_INTEGER },
+ { "MaxPrinterHistory", &MaxPrinterHistory, VAR_INTEGER },
+ { "MaxRequestSize", &MaxRequestSize, VAR_INTEGER },
+ { "PageLog", &PageLog, VAR_STRING },
+ { "PreserveJobFiles", &JobFiles, VAR_BOOLEAN },
+ { "PreserveJobHistory", &JobHistory, VAR_BOOLEAN },
+ { "Printcap", &Printcap, VAR_STRING },
+ { "PrintcapGUI", &PrintcapGUI, VAR_STRING },
+ { "ReloadTimeout", &ReloadTimeout, VAR_INTEGER },
+ { "RemoteRoot", &RemoteRoot, VAR_STRING },
+ { "RequestRoot", &RequestRoot, VAR_STRING },
+ { "RIPCache", &RIPCache, VAR_STRING },
+ { "RunAsUser", &RunAsUser, VAR_BOOLEAN },
+ { "RootCertDuration", &RootCertDuration, VAR_INTEGER },
+ { "ServerAdmin", &ServerAdmin, VAR_STRING },
+ { "ServerBin", &ServerBin, VAR_STRING },
+#ifdef HAVE_SSL
+ { "ServerCertificate", &ServerCertificate, VAR_STRING },
+# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
+ { "ServerKey", &ServerKey, VAR_STRING },
+# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
+#endif /* HAVE_SSL */
+ { "ServerName", &ServerName, VAR_STRING },
+ { "ServerRoot", &ServerRoot, VAR_STRING },
+ { "TempDir", &TempDir, VAR_STRING },
+ { "Timeout", &Timeout, VAR_INTEGER }
+};
+#define NUM_VARS (sizeof(variables) / sizeof(variables[0]))
+
+
+/*
+ * Local functions...
+ */
+
+static int read_configuration(cups_file_t *fp);
+static int read_location(cups_file_t *fp, char *name, int linenum);
+static int get_address(char *value, unsigned defaddress, int defport,
+ struct sockaddr_in *address);
+
+#ifdef HAVE_CDSASSL
+static CFArrayRef CDSAGetServerCerts();
+#endif /* HAVE_CDSASSL */
+
+
+/*
+ * 'ReadConfiguration()' - Read the cupsd.conf file.
+ */
+
+int /* O - 1 on success, 0 otherwise */
+ReadConfiguration(void)
+{
+ int i; /* Looping var */
+ cups_file_t *fp; /* Configuration file */
+ int status; /* Return status */
+ char temp[1024], /* Temporary buffer */
+ *slash; /* Directory separator */
+ char type[MIME_MAX_SUPER + MIME_MAX_TYPE];
+ /* MIME type name */
+ char *language; /* Language string */
+ struct passwd *user; /* Default user */
+ struct group *group; /* Default group */
+ char *old_serverroot, /* Old ServerRoot */
+ *old_requestroot; /* Old RequestRoot */
+
+
+ /*
+ * Shutdown the server...
+ */
+
+ StopServer();
+
+ /*
+ * Save the old root paths...
+ */
+
+ old_serverroot = NULL;
+ SetString(&old_serverroot, ServerRoot);
+ old_requestroot = NULL;
+ SetString(&old_requestroot, RequestRoot);
+
+ /*
+ * Reset the server configuration data...
+ */
+
+ DeleteAllLocations();
+
+ if (NumBrowsers > 0)
+ {
+ free(Browsers);
+
+ NumBrowsers = 0;
+ }
+
+ if (NumPolled > 0)
+ {
+ free(Polled);
+
+ NumPolled = 0;
+ }
+
+ if (NumRelays > 0)
+ {
+ for (i = 0; i < NumRelays; i ++)
+ if (Relays[i].from.type == AUTH_NAME)
+ free(Relays[i].from.mask.name.name);
+
+ free(Relays);
+
+ NumRelays = 0;
+ }
+
+ if (NumListeners > 0)
+ {
+ free(Listeners);
+
+ NumListeners = 0;
+ }
+
+ /*
+ * String options...
+ */
+
+ gethostname(temp, sizeof(temp));
+ SetString(&ServerName, temp);
+ SetStringf(&ServerAdmin, "root@%s", temp);
+ SetString(&ServerBin, CUPS_SERVERBIN);
+ SetString(&RequestRoot, CUPS_REQUESTS);
+ SetString(&DocumentRoot, CUPS_DOCROOT);
+ SetString(&DataDir, CUPS_DATADIR);
+ SetString(&AccessLog, CUPS_LOGDIR "/access_log");
+ SetString(&ErrorLog, CUPS_LOGDIR "/error_log");
+ SetString(&PageLog, CUPS_LOGDIR "/page_log");
+ SetString(&Printcap, "/etc/printcap");
+ SetString(&PrintcapGUI, "/usr/bin/glpoptions");
+ SetString(&FontPath, CUPS_FONTPATH);
+ SetString(&RemoteRoot, "remroot");
+ SetString(&ServerHeader, "CUPS/1.1");
+
+ strlcpy(temp, ConfigurationFile, sizeof(temp));
+ if ((slash = strrchr(temp, '/')) != NULL)
+ *slash = '\0';
+
+ SetString(&ServerRoot, temp);
+
+ ClearString(&Classification);
+ ClassifyOverride = 0;
+
+#ifdef HAVE_SSL
+# ifdef HAVE_CDSASSL
+ SetString(&ServerCertificate, "/var/root/Library/Keychains/CUPS");
+# else
+ SetString(&ServerCertificate, "ssl/server.crt");
+ SetString(&ServerKey, "ssl/server.key");
+# endif /* HAVE_CDSASSL */
+#endif /* HAVE_SSL */
+
+ if ((language = DEFAULT_LANGUAGE) == NULL)
+ language = "en";
+ else if (strcmp(language, "C") == 0 || strcmp(language, "POSIX") == 0)
+ language = "en";
+
+ SetString(&DefaultLanguage, language);
+ SetString(&DefaultCharset, DEFAULT_CHARSET);
+
+ SetString(&RIPCache, "8m");
+
+ if (getenv("TMPDIR") == NULL)
+ SetString(&TempDir, CUPS_REQUESTS "/tmp");
+ else
+ SetString(&TempDir, getenv("TMPDIR"));
+
+ /*
+ * Find the default system group: "sys", "system", or "root"...
+ */
+
+ group = getgrnam(CUPS_DEFAULT_GROUP);
+ endgrent();
+
+ NumSystemGroups = 0;
+
+ if (group != NULL)
+ {
+ SetString(&SystemGroups[0], CUPS_DEFAULT_GROUP);
+ Group = group->gr_gid;
+ }
+ else
+ {
+ group = getgrgid(0);
+ endgrent();
+
+ if (group != NULL)
+ {
+ SetString(&SystemGroups[0], group->gr_name);
+ Group = 0;
+ }
+ else
+ {
+ SetString(&SystemGroups[0], "unknown");
+ Group = 0;
+ }
+ }
+
+ /*
+ * Find the default user...
+ */
+
+ if ((user = getpwnam(CUPS_DEFAULT_USER)) == NULL)
+ User = 1; /* Force to a non-priviledged account */
+ else
+ User = user->pw_uid;
+
+ endpwent();
+
+ /*
+ * Numeric options...
+ */
+
+ ConfigFilePerm = 0640;
+ LogFilePerm = 0644;
+
+ FaxRetryLimit = 5;
+ FaxRetryInterval = 300;
+ FileDevice = FALSE;
+ FilterLevel = 0;
+ FilterLimit = 0;
+ FilterNice = 0;
+ HostNameLookups = FALSE;
+ ImplicitClasses = TRUE;
+ ImplicitAnyClasses = FALSE;
+ HideImplicitMembers = TRUE;
+ KeepAlive = TRUE;
+ KeepAliveTimeout = DEFAULT_KEEPALIVE;
+ ListenBackLog = SOMAXCONN;
+ LogLevel = L_ERROR;
+ MaxClients = 100;
+ MaxClientsPerHost = 0;
+ MaxLogSize = 1024 * 1024;
+ MaxPrinterHistory = 10;
+ MaxRequestSize = 0;
+ ReloadTimeout = 60;
+ RootCertDuration = 300;
+ RunAsUser = FALSE;
+ Timeout = DEFAULT_TIMEOUT;
+
+ BrowseInterval = DEFAULT_INTERVAL;
+ BrowsePort = ippPort();
+ BrowseProtocols = BROWSE_CUPS;
+ BrowseShortNames = TRUE;
+ BrowseTimeout = DEFAULT_TIMEOUT;
+ Browsing = TRUE;
+
+ JobHistory = DEFAULT_HISTORY;
+ JobFiles = DEFAULT_FILES;
+ JobAutoPurge = 0;
+ MaxJobs = 500;
+ MaxJobsPerUser = 0;
+ MaxJobsPerPrinter = 0;
+ MaxCopies = 100;
+
+ /*
+ * Read the configuration file...
+ */
+
+ if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL)
+ return (0);
+
+ status = read_configuration(fp);
+
+ cupsFileClose(fp);
+
+ if (!status)
+ return (0);
+
+ if (RunAsUser)
+ RunUser = User;
+ else
+ RunUser = getuid();
+
+ /*
+ * Use the default system group if none was supplied in cupsd.conf...
+ */
+
+ if (NumSystemGroups == 0)
+ NumSystemGroups ++;
+
+ /*
+ * Get the access control list for browsing...
+ */
+
+ BrowseACL = FindLocation("CUPS_INTERNAL_BROWSE_ACL");
+
+ /*
+ * Open the system log for cupsd if necessary...
+ */
+
+#ifdef HAVE_VSYSLOG
+ if (strcmp(AccessLog, "syslog") == 0 ||
+ strcmp(ErrorLog, "syslog") == 0 ||
+ strcmp(PageLog, "syslog") == 0)
+ openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR);
+#endif /* HAVE_VSYSLOG */
+
+ /*
+ * Log the configuration file that was used...
+ */
+
+ LogMessage(L_INFO, "Loaded configuration file \"%s\"", ConfigurationFile);
+
+ /*
+ * Check that we have at least one listen/port line; if not, report this
+ * as an error and exit!
+ */
+
+ if (NumListeners == 0)
+ {
+ /*
+ * No listeners!
+ */
+
+ LogMessage(L_EMERG, "No valid Listen or Port lines were found in the configuration file!");
+
+ /*
+ * Commit suicide...
+ */
+
+ kill(getpid(), SIGTERM);
+ }
+
+ /*
+ * Set the default locale using the language and charset...
+ */
+
+ SetStringf(&DefaultLocale, "%s.%s", DefaultLanguage, DefaultCharset);
+
+ /*
+ * Update all relative filenames to include the full path from ServerRoot...
+ */
+
+ if (DocumentRoot[0] != '/')
+ SetStringf(&DocumentRoot, "%s/%s", ServerRoot, DocumentRoot);
+
+ if (RequestRoot[0] != '/')
+ SetStringf(&RequestRoot, "%s/%s", ServerRoot, RequestRoot);
+
+ if (ServerBin[0] != '/')
+ SetStringf(&ServerBin, "%s/%s", ServerRoot, ServerBin);
+
+#ifdef HAVE_SSL
+ if (ServerCertificate[0] != '/')
+ SetStringf(&ServerCertificate, "%s/%s", ServerRoot, ServerCertificate);
+
+# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
+ chown(ServerCertificate, RunUser, Group);
+ chmod(ServerCertificate, ConfigFilePerm);
+
+ if (ServerKey[0] != '/')
+ SetStringf(&ServerKey, "%s/%s", ServerRoot, ServerKey);
+
+ chown(ServerKey, RunUser, Group);
+ chmod(ServerKey, ConfigFilePerm);
+# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
+#endif /* HAVE_SSL */
+
+ /*
+ * Make sure that ServerRoot and the config files are owned and
+ * writable by the user and group in the cupsd.conf file...
+ */
+
+ chown(ServerRoot, RunUser, Group);
+ chmod(ServerRoot, 0775);
+
+ snprintf(temp, sizeof(temp), "%s/certs", ServerRoot);
+ chown(temp, RunUser, Group);
+ chmod(temp, 0711);
+
+ snprintf(temp, sizeof(temp), "%s/ppd", ServerRoot);
+ chown(temp, RunUser, Group);
+ chmod(temp, 0755);
+
+ snprintf(temp, sizeof(temp), "%s/ssl", ServerRoot);
+ chown(temp, RunUser, Group);
+ chmod(temp, 0700);
+
+ snprintf(temp, sizeof(temp), "%s/cupsd.conf", ServerRoot);
+ chown(temp, RunUser, Group);
+ chmod(temp, ConfigFilePerm);
+
+ snprintf(temp, sizeof(temp), "%s/classes.conf", ServerRoot);
+ chown(temp, RunUser, Group);
+#ifdef __APPLE__
+ chmod(temp, 0600);
+#else
+ chmod(temp, ConfigFilePerm);
+#endif /* __APPLE__ */
+
+ snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot);
+ chown(temp, RunUser, Group);
+#ifdef __APPLE__
+ chmod(temp, 0600);
+#else
+ chmod(temp, ConfigFilePerm);
+#endif /* __APPLE__ */
+
+ snprintf(temp, sizeof(temp), "%s/passwd.md5", ServerRoot);
+ chown(temp, User, Group);
+ chmod(temp, 0600);
+
+ /*
+ * Make sure the request and temporary directories have the right
+ * permissions...
+ */
+
+ chown(RequestRoot, RunUser, Group);
+ chmod(RequestRoot, 0710);
+
+ if (strncmp(TempDir, RequestRoot, strlen(RequestRoot)) == 0)
+ {
+ /*
+ * Only update ownership and permissions if the CUPS temp directory
+ * is under the spool directory...
+ */
+
+ chown(TempDir, RunUser, Group);
+ chmod(TempDir, 01770);
+ }
+
+ /*
+ * Check the MaxClients setting, and then allocate memory for it...
+ */
+
+ if (MaxClients > (MaxFDs / 3) || MaxClients <= 0)
+ {
+ if (MaxClients > 0)
+ LogMessage(L_INFO, "MaxClients limited to 1/3 of the file descriptor limit (%d)...",
+ MaxFDs);
+
+ MaxClients = MaxFDs / 3;
+ }
+
+ if ((Clients = calloc(sizeof(client_t), MaxClients)) == NULL)
+ {
+ LogMessage(L_ERROR, "ReadConfiguration: Unable to allocate memory for %d clients: %s",
+ MaxClients, strerror(errno));
+ exit(1);
+ }
+ else
+ LogMessage(L_INFO, "Configured for up to %d clients.", MaxClients);
+
+ if (Classification && strcasecmp(Classification, "none") == 0)
+ ClearString(&Classification);
+
+ if (Classification)
+ LogMessage(L_INFO, "Security set to \"%s\"", Classification);
+
+ /*
+ * Update the MaxClientsPerHost value, as needed...
+ */
+
+ if (MaxClientsPerHost <= 0)
+ MaxClientsPerHost = MaxClients;
+
+ if (MaxClientsPerHost > MaxClients)
+ MaxClientsPerHost = MaxClients;
+
+ LogMessage(L_INFO, "Allowing up to %d client connections per host.",
+ MaxClientsPerHost);
+
+ /*
+ * If we are doing a full reload or the server root has changed, flush
+ * the jobs, printers, etc. and start from scratch...
+ */
+
+ if (NeedReload == RELOAD_ALL ||
+ !old_serverroot || !ServerRoot || strcmp(old_serverroot, ServerRoot) ||
+ !old_requestroot || !RequestRoot || strcmp(old_requestroot, RequestRoot))
+ {
+ LogMessage(L_INFO, "Full reload is required.");
+
+ /*
+ * Free all memory...
+ */
+
+ FreeAllJobs();
+ DeleteAllClasses();
+ DeleteAllPrinters();
+
+ DefaultPrinter = NULL;
+
+ if (Devices)
+ {
+ ippDelete(Devices);
+ Devices = NULL;
+ }
+
+ if (PPDs)
+ {
+ ippDelete(PPDs);
+ PPDs = NULL;
+ }
+
+ if (MimeDatabase != NULL)
+ mimeDelete(MimeDatabase);
+
+ if (NumMimeTypes)
+ {
+ for (i = 0; i < NumMimeTypes; i ++)
+ free((void *)MimeTypes[i]);
+
+ free(MimeTypes);
+ }
+
+ /*
+ * Read the MIME type and conversion database...
+ */
+
+ snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
+
+ MimeDatabase = mimeNew();
+ mimeMerge(MimeDatabase, ServerRoot, temp);
+
+ /*
+ * Create a list of MIME types for the document-format-supported
+ * attribute...
+ */
+
+ NumMimeTypes = MimeDatabase->num_types;
+ if (!mimeType(MimeDatabase, "application", "octet-stream"))
+ NumMimeTypes ++;
+
+ MimeTypes = calloc(NumMimeTypes, sizeof(const char *));
+
+ for (i = 0; i < MimeDatabase->num_types; i ++)
+ {
+ snprintf(type, sizeof(type), "%s/%s", MimeDatabase->types[i]->super,
+ MimeDatabase->types[i]->type);
+
+ MimeTypes[i] = strdup(type);
+ }
+
+ if (i < NumMimeTypes)
+ MimeTypes[i] = strdup("application/octet-stream");
+
+ /*
+ * Load banners...
+ */
+
+ snprintf(temp, sizeof(temp), "%s/banners", DataDir);
+ LoadBanners(temp);
+
+ /*
+ * Load printers and classes...
+ */
+
+ LoadAllPrinters();
+ LoadAllClasses();
+
+ CreateCommonData();
+
+ /*
+ * Load devices and PPDs...
+ */
+
+ snprintf(temp, sizeof(temp), "%s/backend", ServerBin);
+ LoadDevices(temp);
+
+ snprintf(temp, sizeof(temp), "%s/model", DataDir);
+ LoadPPDs(temp);
+
+ /*
+ * Load queued jobs...
+ */
+
+ LoadAllJobs();
+
+ LogMessage(L_INFO, "Full reload complete.");
+ }
+ else
+ {
+ CreateCommonData();
+
+ LogMessage(L_INFO, "Partial reload complete.");
+ }
+
+ /*
+ * Reset the reload state...
+ */
+
+ NeedReload = RELOAD_NONE;
+
+ ClearString(&old_serverroot);
+ ClearString(&old_requestroot);
+
+ /*
+ * Startup the server and return...
+ */
+
+ StartServer();
+
+ return (1);
+}
+
+
+/*
+ * 'read_configuration()' - Read a configuration file.
+ */
+
+static int /* O - 1 on success, 0 on failure */
+read_configuration(cups_file_t *fp) /* I - File to read from */
+{
+ int i; /* Looping var */
+ int linenum; /* Current line number */
+ int len; /* Length of line */
+ char line[HTTP_MAX_BUFFER], /* Line from file */
+ name[256], /* Parameter name */
+ *nameptr, /* Pointer into name */
+ *value; /* Pointer to value */
+ int valuelen; /* Length of value */
+ var_t *var; /* Current variable */
+ unsigned address, /* Address value */
+ netmask; /* Netmask value */
+ int ip[4], /* IP address components */
+ ipcount, /* Number of components provided */
+ mask[4]; /* IP netmask components */
+ dirsvc_relay_t *relay; /* Relay data */
+ dirsvc_poll_t *poll; /* Polling data */
+ struct sockaddr_in polladdr; /* Polling address */
+ location_t *location; /* Browse location */
+ cups_file_t *incfile; /* Include file */
+ char incname[1024]; /* Include filename */
+ static unsigned netmasks[4] = /* Standard netmasks... */
+ {
+ 0xff000000,
+ 0xffff0000,
+ 0xffffff00,
+ 0xffffffff
+ };
+
+
+ /*
+ * Loop through each line in the file...
+ */
+
+ linenum = 0;
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ linenum ++;
+
+ /*
+ * Skip comment lines...
+ */
+
+ if (line[0] == '#')
+ continue;
+
+ /*
+ * Strip trailing whitespace, if any...
+ */
+
+ len = strlen(line);
+
+ while (len > 0 && isspace(line[len - 1]))
+ {
+ len --;
+ line[len] = '\0';
+ }
+
+ /*
+ * Extract the name from the beginning of the line...
+ */
+
+ for (value = line; isspace(*value); value ++);
+
+ for (nameptr = name; *value != '\0' && !isspace(*value) &&
+ nameptr < (name + sizeof(name) - 1);)
+ *nameptr++ = *value++;
+ *nameptr = '\0';
+
+ while (isspace(*value))
+ value ++;
+
+ if (name[0] == '\0')
+ continue;
+
+ /*
+ * Decode the directive...
+ */
+
+ if (strcasecmp(name, "Include") == 0)
+ {
+ /*
+ * Include filename
+ */
+
+ if (value[0] == '/')
+ strlcpy(incname, value, sizeof(incname));
+ else
+ snprintf(incname, sizeof(incname), "%s/%s", ServerRoot, value);
+
+ if ((incfile = cupsFileOpen(incname, "rb")) == NULL)
+ LogMessage(L_ERROR, "Unable to include config file \"%s\" - %s",
+ incname, strerror(errno));
+ else
+ {
+ read_configuration(incfile);
+ cupsFileClose(incfile);
+ }
+ }
+ else if (strcasecmp(name, "<Location") == 0)
+ {
+ /*
+ * <Location path>
+ */
+
+ if (line[len - 1] == '>')
+ {
+ line[len - 1] = '\0';
+
+ linenum = read_location(fp, value, linenum);
+ if (linenum == 0)
+ return (0);
+ }
+ else
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d.",
+ linenum);
+ return (0);
+ }
+ }
+ else if (strcasecmp(name, "Port") == 0 ||
+ strcasecmp(name, "Listen") == 0)
+ {
+ /*
+ * Add a listening address to the list...
+ */
+
+ listener_t *temp; /* New listeners array */
+
+
+ if (NumListeners == 0)
+ temp = malloc(sizeof(listener_t));
+ else
+ temp = realloc(Listeners, (NumListeners + 1) * sizeof(listener_t));
+
+ if (!temp)
+ {
+ LogMessage(L_ERROR, "Unable to allocate %s at line %d - %s.",
+ name, linenum, strerror(errno));
+ continue;
+ }
+
+ Listeners = temp;
+ temp += NumListeners;
+
+ memset(temp, 0, sizeof(listener_t));
+
+ if (get_address(value, INADDR_ANY, IPP_PORT, &(temp->address)))
+ {
+ LogMessage(L_INFO, "Listening to %x:%d",
+ (unsigned)ntohl(temp->address.sin_addr.s_addr),
+ ntohs(temp->address.sin_port));
+ NumListeners ++;
+ }
+ else
+ LogMessage(L_ERROR, "Bad %s address %s at line %d.", name,
+ value, linenum);
+ }
+#ifdef HAVE_SSL
+ else if (strcasecmp(name, "SSLPort") == 0 ||
+ strcasecmp(name, "SSLListen") == 0)
+ {
+ /*
+ * Add a listening address to the list...
+ */
+
+ listener_t *temp; /* New listeners array */
+
+
+ if (NumListeners == 0)
+ temp = malloc(sizeof(listener_t));
+ else
+ temp = realloc(Listeners, (NumListeners + 1) * sizeof(listener_t));
+
+ if (!temp)
+ {
+ LogMessage(L_ERROR, "Unable to allocate %s at line %d - %s.",
+ name, linenum, strerror(errno));
+ continue;
+ }
+
+ Listeners = temp;
+ temp += NumListeners;
+
+ if (get_address(value, INADDR_ANY, IPP_PORT, &(temp->address)))
+ {
+ LogMessage(L_INFO, "Listening to %x:%d (SSL)",
+ (unsigned)ntohl(temp->address.sin_addr.s_addr),
+ ntohs(temp->address.sin_port));
+ temp->encryption = HTTP_ENCRYPT_ALWAYS;
+ NumListeners ++;
+ }
+ else
+ LogMessage(L_ERROR, "Bad %s address %s at line %d.", name,
+ value, linenum);
+ }
+#endif /* HAVE_SSL */
+ else if (strcasecmp(name, "BrowseAddress") == 0)
+ {
+ /*
+ * Add a browse address to the list...
+ */
+
+ dirsvc_addr_t *temp; /* New browse address array */
+
+
+ if (NumBrowsers == 0)
+ temp = malloc(sizeof(dirsvc_addr_t));
+ else
+ temp = realloc(Browsers, (NumBrowsers + 1) * sizeof(dirsvc_addr_t));
+
+ if (!temp)
+ {
+ LogMessage(L_ERROR, "Unable to allocate BrowseAddress at line %d - %s.",
+ linenum, strerror(errno));
+ continue;
+ }
+
+ Browsers = temp;
+ temp += NumBrowsers;
+
+ memset(temp, 0, sizeof(dirsvc_addr_t));
+
+ if (strcasecmp(value, "@LOCAL") == 0)
+ {
+ /*
+ * Send browse data to all local interfaces...
+ */
+
+ strcpy(temp->iface, "*");
+ NumBrowsers ++;
+ }
+ else if (strncasecmp(value, "@IF(", 4) == 0)
+ {
+ /*
+ * Send browse data to the named interface...
+ */
+
+ strlcpy(temp->iface, value + 4, sizeof(Browsers[0].iface));
+
+ nameptr = temp->iface + strlen(temp->iface) - 1;
+ if (*nameptr == ')')
+ *nameptr = '\0';
+
+ NumBrowsers ++;
+ }
+ else if (get_address(value, INADDR_NONE, BrowsePort, &(temp->to)))
+ {
+ LogMessage(L_INFO, "Sending browsing info to %x:%d",
+ (unsigned)ntohl(temp->to.sin_addr.s_addr),
+ ntohs(temp->to.sin_port));
+
+ NumBrowsers ++;
+ }
+ else
+ LogMessage(L_ERROR, "Bad BrowseAddress %s at line %d.", value,
+ linenum);
+ }
+ else if (strcasecmp(name, "BrowseOrder") == 0)
+ {
+ /*
+ * "BrowseOrder Deny,Allow" or "BrowseOrder Allow,Deny"...
+ */
+
+ if ((location = FindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
+ location = AddLocation("CUPS_INTERNAL_BROWSE_ACL");
+
+ if (location == NULL)
+ LogMessage(L_ERROR, "Unable to initialize browse access control list!");
+ else if (strncasecmp(value, "deny", 4) == 0)
+ location->order_type = AUTH_ALLOW;
+ else if (strncasecmp(value, "allow", 5) == 0)
+ location->order_type = AUTH_DENY;
+ else
+ LogMessage(L_ERROR, "Unknown BrowseOrder value %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "BrowseProtocols") == 0)
+ {
+ /*
+ * "BrowseProtocol name [... name]"
+ */
+
+ BrowseProtocols = 0;
+
+ for (; *value;)
+ {
+ for (valuelen = 0; value[valuelen]; valuelen ++)
+ if (isspace(value[valuelen]) || value[valuelen] == ',')
+ break;
+
+ if (value[valuelen])
+ {
+ value[valuelen] = '\0';
+ valuelen ++;
+ }
+
+ if (strcasecmp(value, "cups") == 0)
+ BrowseProtocols |= BROWSE_CUPS;
+ else if (strcasecmp(value, "slp") == 0)
+ BrowseProtocols |= BROWSE_SLP;
+ else if (strcasecmp(value, "ldap") == 0)
+ BrowseProtocols |= BROWSE_LDAP;
+ else if (strcasecmp(value, "all") == 0)
+ BrowseProtocols |= BROWSE_ALL;
+ else
+ {
+ LogMessage(L_ERROR, "Unknown browse protocol \"%s\" on line %d.",
+ value, linenum);
+ break;
+ }
+
+ for (value += valuelen; *value; value ++)
+ if (!isspace(*value) || *value != ',')
+ break;
+ }
+ }
+ else if (strcasecmp(name, "BrowseAllow") == 0 ||
+ strcasecmp(name, "BrowseDeny") == 0)
+ {
+ /*
+ * BrowseAllow [From] host/ip...
+ * BrowseDeny [From] host/ip...
+ */
+
+ if ((location = FindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
+ location = AddLocation("CUPS_INTERNAL_BROWSE_ACL");
+
+ if (location == NULL)
+ LogMessage(L_ERROR, "Unable to initialize browse access control list!");
+ else
+ {
+ if (strncasecmp(value, "from ", 5) == 0)
+ {
+ /*
+ * Strip leading "from"...
+ */
+
+ value += 5;
+
+ while (isspace(*value))
+ value ++;
+ }
+
+ /*
+ * Figure out what form the allow/deny address takes:
+ *
+ * All
+ * None
+ * *.domain.com
+ * .domain.com
+ * host.domain.com
+ * nnn.*
+ * nnn.nnn.*
+ * nnn.nnn.nnn.*
+ * nnn.nnn.nnn.nnn
+ * nnn.nnn.nnn.nnn/mm
+ * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+ */
+
+ if (strcasecmp(value, "all") == 0)
+ {
+ /*
+ * All hosts...
+ */
+
+ if (strcasecmp(name, "BrowseAllow") == 0)
+ AllowIP(location, 0, 0);
+ else
+ DenyIP(location, 0, 0);
+ }
+ else if (strcasecmp(value, "none") == 0)
+ {
+ /*
+ * No hosts...
+ */
+
+ if (strcasecmp(name, "BrowseAllow") == 0)
+ AllowIP(location, ~0, 0);
+ else
+ DenyIP(location, ~0, 0);
+ }
+ else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0]))
+ {
+ /*
+ * Host or domain name...
+ */
+
+ if (value[0] == '*')
+ value ++;
+
+ if (strcasecmp(name, "BrowseAllow") == 0)
+ AllowHost(location, value);
+ else
+ DenyHost(location, value);
+ }
+ else
+ {
+ /*
+ * One of many IP address forms...
+ */
+
+ memset(ip, 0, sizeof(ip));
+ ipcount = sscanf(value, "%d.%d.%d.%d", ip + 0, ip + 1, ip + 2, ip + 3);
+ address = (((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3];
+
+ if ((value = strchr(value, '/')) != NULL)
+ {
+ value ++;
+ memset(mask, 0, sizeof(mask));
+ switch (sscanf(value, "%d.%d.%d.%d", mask + 0, mask + 1,
+ mask + 2, mask + 3))
+ {
+ case 1 :
+ netmask = (0xffffffff << (32 - mask[0])) & 0xffffffff;
+ break;
+ case 4 :
+ netmask = (((((mask[0] << 8) | mask[1]) << 8) |
+ mask[2]) << 8) | mask[3];
+ break;
+ default :
+ LogMessage(L_ERROR, "Bad netmask value %s on line %d.",
+ value, linenum);
+ netmask = 0xffffffff;
+ break;
+ }
+ }
+ else
+ netmask = netmasks[ipcount - 1];
+
+ if ((address & ~netmask) != 0)
+ {
+ LogMessage(L_WARN, "Discarding extra bits in %s address %08x for netmask %08x...",
+ name, address, netmask);
+ address &= netmask;
+ }
+
+ if (strcasecmp(name, "BrowseAllow") == 0)
+ AllowIP(location, address, netmask);
+ else
+ DenyIP(location, address, netmask);
+ }
+ }
+ }
+ else if (strcasecmp(name, "BrowseRelay") == 0)
+ {
+ /*
+ * BrowseRelay [from] source [to] destination
+ */
+
+ if (NumRelays == 0)
+ relay = malloc(sizeof(dirsvc_relay_t));
+ else
+ relay = realloc(Relays, (NumRelays + 1) * sizeof(dirsvc_relay_t));
+
+ if (!relay)
+ {
+ LogMessage(L_ERROR, "Unable to allocate BrowseRelay at line %d - %s.",
+ linenum, strerror(errno));
+ continue;
+ }
+
+ Relays = relay;
+ relay += NumRelays;
+
+ memset(relay, 0, sizeof(dirsvc_relay_t));
+
+ if (strncasecmp(value, "from ", 5) == 0)
+ {
+ /*
+ * Strip leading "from"...
+ */
+
+ value += 5;
+
+ while (isspace(*value))
+ value ++;
+ }
+
+ /*
+ * Figure out what form the from address takes:
+ *
+ * *.domain.com
+ * .domain.com
+ * host.domain.com
+ * nnn.*
+ * nnn.nnn.*
+ * nnn.nnn.nnn.*
+ * nnn.nnn.nnn.nnn
+ * nnn.nnn.nnn.nnn/mm
+ * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+ */
+
+ if (value[0] == '*' || value[0] == '.' || !isdigit(value[0]))
+ {
+ /*
+ * Host or domain name...
+ */
+
+ if (value[0] == '*')
+ value ++;
+
+ strlcpy(name, value, sizeof(name));
+ if ((nameptr = strchr(name, ' ')) != NULL)
+ *nameptr = '\0';
+
+ relay->from.type = AUTH_NAME;
+ relay->from.mask.name.name = strdup(name);
+ relay->from.mask.name.length = strlen(name);
+ }
+ else
+ {
+ /*
+ * One of many IP address forms...
+ */
+
+ memset(ip, 0, sizeof(ip));
+ ipcount = sscanf(value, "%d.%d.%d.%d", ip + 0, ip + 1, ip + 2, ip + 3);
+ address = (((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3];
+
+ for (; *value; value ++)
+ if (*value == '/' || isspace(*value))
+ break;
+
+ if (*value == '/')
+ {
+ value ++;
+ memset(mask, 0, sizeof(mask));
+ switch (sscanf(value, "%d.%d.%d.%d", mask + 0, mask + 1,
+ mask + 2, mask + 3))
+ {
+ case 1 :
+ netmask = (0xffffffff << (32 - mask[0])) & 0xffffffff;
+ break;
+ case 4 :
+ netmask = (((((mask[0] << 8) | mask[1]) << 8) |
+ mask[2]) << 8) | mask[3];
+ break;
+ default :
+ LogMessage(L_ERROR, "Bad netmask value %s on line %d.",
+ value, linenum);
+ netmask = 0xffffffff;
+ break;
+ }
+ }
+ else
+ netmask = netmasks[ipcount - 1];
+
+ relay->from.type = AUTH_IP;
+ relay->from.mask.ip.address = address;
+ relay->from.mask.ip.netmask = netmask;
+ }
+
+ /*
+ * Skip value and trailing whitespace...
+ */
+
+ for (; *value; value ++)
+ if (isspace(*value))
+ break;
+
+ while (isspace(*value))
+ value ++;
+
+ if (strncasecmp(value, "to ", 3) == 0)
+ {
+ /*
+ * Strip leading "to"...
+ */
+
+ value += 3;
+
+ while (isspace(*value))
+ value ++;
+ }
+
+ /*
+ * Get "to" address and port...
+ */
+
+ if (get_address(value, INADDR_BROADCAST, BrowsePort, &(relay->to)))
+ {
+ if (relay->from.type == AUTH_NAME)
+ LogMessage(L_INFO, "Relaying from %s to %x:%d",
+ relay->from.mask.name.name,
+ (unsigned)ntohl(relay->to.sin_addr.s_addr),
+ ntohs(relay->to.sin_port));
+ else
+ LogMessage(L_INFO, "Relaying from %x/%x to %x:%d",
+ relay->from.mask.ip.address, relay->from.mask.ip.netmask,
+ (unsigned)ntohl(relay->to.sin_addr.s_addr),
+ ntohs(relay->to.sin_port));
+
+ NumRelays ++;
+ }
+ else
+ {
+ if (relay->from.type == AUTH_NAME)
+ free(relay->from.mask.name.name);
+
+ LogMessage(L_ERROR, "Bad relay address %s at line %d.", value, linenum);
+ }
+ }
+ else if (strcasecmp(name, "BrowsePoll") == 0)
+ {
+ /*
+ * BrowsePoll address[:port]
+ */
+
+ if (NumPolled == 0)
+ poll = malloc(sizeof(dirsvc_poll_t));
+ else
+ poll = realloc(Polled, (NumPolled + 1) * sizeof(dirsvc_poll_t));
+
+ if (!poll)
+ {
+ LogMessage(L_ERROR, "Unable to allocate BrowsePoll at line %d - %s.",
+ linenum, strerror(errno));
+ continue;
+ }
+
+ Polled = poll;
+ poll += NumPolled;
+
+ /*
+ * Get poll address and port...
+ */
+
+ if (get_address(value, INADDR_NONE, ippPort(), &polladdr))
+ {
+ LogMessage(L_INFO, "Polling %x:%d",
+ (unsigned)ntohl(polladdr.sin_addr.s_addr),
+ ntohs(polladdr.sin_port));
+
+ NumPolled ++;
+ memset(poll, 0, sizeof(dirsvc_poll_t));
+
+ address = ntohl(polladdr.sin_addr.s_addr);
+
+ sprintf(poll->hostname, "%d.%d.%d.%d", address >> 24,
+ (address >> 16) & 255, (address >> 8) & 255, address & 255);
+ poll->port = ntohs(polladdr.sin_port);
+ }
+ else
+ LogMessage(L_ERROR, "Bad poll address %s at line %d.", value, linenum);
+ }
+ else if (strcasecmp(name, "User") == 0)
+ {
+ /*
+ * User ID to run as...
+ */
+
+ if (isdigit(value[0]))
+ User = atoi(value);
+ else
+ {
+ struct passwd *p; /* Password information */
+
+ endpwent();
+ p = getpwnam(value);
+
+ if (p != NULL)
+ User = p->pw_uid;
+ else
+ LogMessage(L_WARN, "Unknown username \"%s\"",
+ value);
+ }
+ }
+ else if (strcasecmp(name, "Group") == 0)
+ {
+ /*
+ * Group ID to run as...
+ */
+
+ if (isdigit(value[0]))
+ Group = atoi(value);
+ else
+ {
+ struct group *g; /* Group information */
+
+ endgrent();
+ g = getgrnam(value);
+
+ if (g != NULL)
+ Group = g->gr_gid;
+ else
+ LogMessage(L_WARN, "Unknown groupname \"%s\"",
+ value);
+ }
+ }
+ else if (strcasecmp(name, "SystemGroup") == 0)
+ {
+ /*
+ * System (admin) group(s)...
+ */
+
+ char *valueptr, /* Pointer into value */
+ quote; /* Quote character */
+
+
+ for (i = NumSystemGroups; *value && i < MAX_SYSTEM_GROUPS; i ++)
+ {
+ if (*value == '\'' || *value == '\"')
+ {
+ /*
+ * Scan quoted name...
+ */
+
+ quote = *value++;
+
+ for (valueptr = value; *valueptr; valueptr ++)
+ if (*valueptr == quote)
+ break;
+ }
+ else
+ {
+ /*
+ * Scan space or comma-delimited name...
+ */
+
+ for (valueptr = value; *valueptr; valueptr ++)
+ if (isspace(*valueptr) || *valueptr == ',')
+ break;
+ }
+
+ if (*valueptr)
+ *valueptr++ = '\0';
+
+ SetString(SystemGroups + i, value);
+
+ value = valueptr;
+
+ while (*value == ',' || isspace(*value))
+ value ++;
+ }
+
+ if (i)
+ NumSystemGroups = i;
+ }
+ else if (strcasecmp(name, "HostNameLookups") == 0)
+ {
+ /*
+ * Do hostname lookups?
+ */
+
+ if (strcasecmp(value, "off") == 0)
+ HostNameLookups = 0;
+ else if (strcasecmp(value, "on") == 0)
+ HostNameLookups = 1;
+ else if (strcasecmp(value, "double") == 0)
+ HostNameLookups = 2;
+ else
+ LogMessage(L_WARN, "Unknown HostNameLookups %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "LogLevel") == 0)
+ {
+ /*
+ * Amount of logging to do...
+ */
+
+ if (strcasecmp(value, "debug2") == 0)
+ LogLevel = L_DEBUG2;
+ else if (strcasecmp(value, "debug") == 0)
+ LogLevel = L_DEBUG;
+ else if (strcasecmp(value, "info") == 0)
+ LogLevel = L_INFO;
+ else if (strcasecmp(value, "notice") == 0)
+ LogLevel = L_NOTICE;
+ else if (strcasecmp(value, "warn") == 0)
+ LogLevel = L_WARN;
+ else if (strcasecmp(value, "error") == 0)
+ LogLevel = L_ERROR;
+ else if (strcasecmp(value, "crit") == 0)
+ LogLevel = L_CRIT;
+ else if (strcasecmp(value, "alert") == 0)
+ LogLevel = L_ALERT;
+ else if (strcasecmp(value, "emerg") == 0)
+ LogLevel = L_EMERG;
+ else if (strcasecmp(value, "none") == 0)
+ LogLevel = L_NONE;
+ else
+ LogMessage(L_WARN, "Unknown LogLevel %s on line %d.", value, linenum);
+ }
+ else if (strcasecmp(name, "PrintcapFormat") == 0)
+ {
+ /*
+ * Format of printcap file?
+ */
+
+ if (strcasecmp(value, "bsd") == 0)
+ PrintcapFormat = PRINTCAP_BSD;
+ else if (strcasecmp(value, "solaris") == 0)
+ PrintcapFormat = PRINTCAP_SOLARIS;
+ else
+ LogMessage(L_WARN, "Unknown PrintcapFormat %s on line %d.",
+ value, linenum);
+ }
+ else if (!strcasecmp(name, "ServerTokens"))
+ {
+ /*
+ * Set the string used for the Server header...
+ */
+
+ struct utsname plat; /* Platform info */
+
+
+ uname(&plat);
+
+ if (!strcasecmp(value, "ProductOnly"))
+ SetString(&ServerHeader, "CUPS");
+ else if (!strcasecmp(value, "Major"))
+ SetString(&ServerHeader, "CUPS/1");
+ else if (!strcasecmp(value, "Minor"))
+ SetString(&ServerHeader, "CUPS/1.1");
+ else if (!strcasecmp(value, "Minimal"))
+ SetString(&ServerHeader, CUPS_MINIMAL);
+ else if (!strcasecmp(value, "OS"))
+ SetStringf(&ServerHeader, CUPS_MINIMAL " (%s)", plat.sysname);
+ else if (!strcasecmp(value, "Full"))
+ SetStringf(&ServerHeader, CUPS_MINIMAL " (%s) IPP/1.1", plat.sysname);
+ else if (!strcasecmp(value, "None"))
+ ClearString(&ServerHeader);
+ else
+ LogMessage(L_WARN, "Unknown ServerTokens %s on line %d.", value, linenum);
+ }
+ else
+ {
+ /*
+ * Find a simple variable in the list...
+ */
+
+ for (i = NUM_VARS, var = variables; i > 0; i --, var ++)
+ if (strcasecmp(name, var->name) == 0)
+ break;
+
+ if (i == 0)
+ {
+ /*
+ * Unknown directive! Output an error message and continue...
+ */
+
+ LogMessage(L_ERROR, "Unknown directive %s on line %d.", name,
+ linenum);
+ continue;
+ }
+
+ switch (var->type)
+ {
+ case VAR_INTEGER :
+ {
+ int n; /* Number */
+ char *units; /* Units */
+
+
+ n = strtol(value, &units, 0);
+
+ if (units && *units)
+ {
+ if (tolower(units[0] & 255) == 'g')
+ n *= 1024 * 1024 * 1024;
+ else if (tolower(units[0] & 255) == 'm')
+ n *= 1024 * 1024;
+ else if (tolower(units[0] & 255) == 'k')
+ n *= 1024;
+ else if (tolower(units[0] & 255) == 't')
+ n *= 262144;
+ }
+
+ *((int *)var->ptr) = n;
+ }
+ break;
+
+ case VAR_BOOLEAN :
+ if (strcasecmp(value, "true") == 0 ||
+ strcasecmp(value, "on") == 0 ||
+ strcasecmp(value, "enabled") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ atoi(value) != 0)
+ *((int *)var->ptr) = TRUE;
+ else if (strcasecmp(value, "false") == 0 ||
+ strcasecmp(value, "off") == 0 ||
+ strcasecmp(value, "disabled") == 0 ||
+ strcasecmp(value, "no") == 0 ||
+ strcasecmp(value, "0") == 0)
+ *((int *)var->ptr) = FALSE;
+ else
+ LogMessage(L_ERROR, "Unknown boolean value %s on line %d.",
+ value, linenum);
+ break;
+
+ case VAR_STRING :
+ SetString((char **)var->ptr, value);
+ break;
+ }
+ }
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'read_location()' - Read a <Location path> definition.
+ */
+
+static int /* O - New line number or 0 on error */
+read_location(cups_file_t *fp, /* I - Configuration file */
+ char *location, /* I - Location name/path */
+ int linenum) /* I - Current line number */
+{
+ int i; /* Looping var */
+ location_t *loc, /* New location */
+ *parent; /* Parent location */
+ int len; /* Length of line */
+ char line[HTTP_MAX_BUFFER], /* Line buffer */
+ name[256], /* Configuration directive */
+ *nameptr, /* Pointer into name */
+ *value, /* Value for directive */
+ *valptr; /* Pointer into value */
+ unsigned address, /* Address value */
+ netmask; /* Netmask value */
+ int ip[4], /* IP address components */
+ ipcount, /* Number of components provided */
+ mask[4]; /* IP netmask components */
+ static unsigned netmasks[4] = /* Standard netmasks... */
+ {
+ 0xff000000,
+ 0xffff0000,
+ 0xffffff00,
+ 0xffffffff
+ };
+
+
+ if ((parent = AddLocation(location)) == NULL)
+ return (0);
+
+ parent->limit = AUTH_LIMIT_ALL;
+ loc = parent;
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ linenum ++;
+
+ /*
+ * Skip comment lines...
+ */
+
+ if (line[0] == '#')
+ continue;
+
+ /*
+ * Strip trailing whitespace, if any...
+ */
+
+ len = strlen(line);
+
+ while (len > 0 && isspace(line[len - 1] & 255))
+ {
+ len --;
+ line[len] = '\0';
+ }
+
+ /*
+ * Extract the name from the beginning of the line...
+ */
+
+ for (value = line; isspace(*value & 255); value ++);
+
+ for (nameptr = name; *value != '\0' && !isspace(*value & 255) &&
+ nameptr < (name + sizeof(name) - 1);)
+ *nameptr++ = *value++;
+ *nameptr = '\0';
+
+ while (isspace(*value & 255))
+ value ++;
+
+ if (name[0] == '\0')
+ continue;
+
+ /*
+ * Decode the directive...
+ */
+
+ if (strcasecmp(name, "</Location>") == 0)
+ return (linenum);
+ else if (strcasecmp(name, "<Limit") == 0 ||
+ strcasecmp(name, "<LimitExcept") == 0)
+ {
+ if ((loc = CopyLocation(&parent)) == NULL)
+ return (0);
+
+ loc->limit = 0;
+ while (*value)
+ {
+ for (valptr = value;
+ !isspace(*valptr & 255) && *valptr != '>' && *valptr;
+ valptr ++);
+
+ if (*valptr)
+ *valptr++ = '\0';
+
+ if (strcmp(value, "ALL") == 0)
+ loc->limit = AUTH_LIMIT_ALL;
+ else if (strcmp(value, "GET") == 0)
+ loc->limit |= AUTH_LIMIT_GET;
+ else if (strcmp(value, "HEAD") == 0)
+ loc->limit |= AUTH_LIMIT_HEAD;
+ else if (strcmp(value, "OPTIONS") == 0)
+ loc->limit |= AUTH_LIMIT_OPTIONS;
+ else if (strcmp(value, "POST") == 0)
+ loc->limit |= AUTH_LIMIT_POST;
+ else if (strcmp(value, "PUT") == 0)
+ loc->limit |= AUTH_LIMIT_PUT;
+ else if (strcmp(value, "TRACE") == 0)
+ loc->limit |= AUTH_LIMIT_TRACE;
+ else
+ LogMessage(L_WARN, "Unknown request type %s on line %d!", value,
+ linenum);
+
+ for (value = valptr; isspace(*value & 255) || *value == '>'; value ++);
+ }
+
+ if (strcasecmp(name, "<LimitExcept") == 0)
+ loc->limit = AUTH_LIMIT_ALL ^ loc->limit;
+
+ parent->limit &= ~loc->limit;
+ }
+ else if (strcasecmp(name, "</Limit>") == 0)
+ loc = parent;
+ else if (strcasecmp(name, "Encryption") == 0)
+ {
+ /*
+ * "Encryption xxx" - set required encryption level...
+ */
+
+ if (strcasecmp(value, "never") == 0)
+ loc->encryption = HTTP_ENCRYPT_NEVER;
+ else if (strcasecmp(value, "always") == 0)
+ {
+ LogMessage(L_ERROR, "Encryption value \"%s\" on line %d is invalid in this context. "
+ "Using \"required\" instead.", value, linenum);
+
+ loc->encryption = HTTP_ENCRYPT_REQUIRED;
+ }
+ else if (strcasecmp(value, "required") == 0)
+ loc->encryption = HTTP_ENCRYPT_REQUIRED;
+ else if (strcasecmp(value, "ifrequested") == 0)
+ loc->encryption = HTTP_ENCRYPT_IF_REQUESTED;
+ else
+ LogMessage(L_ERROR, "Unknown Encryption value %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "Order") == 0)
+ {
+ /*
+ * "Order Deny,Allow" or "Order Allow,Deny"...
+ */
+
+ if (strncasecmp(value, "deny", 4) == 0)
+ loc->order_type = AUTH_ALLOW;
+ else if (strncasecmp(value, "allow", 5) == 0)
+ loc->order_type = AUTH_DENY;
+ else
+ LogMessage(L_ERROR, "Unknown Order value %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "Allow") == 0 ||
+ strcasecmp(name, "Deny") == 0)
+ {
+ /*
+ * Allow [From] host/ip...
+ * Deny [From] host/ip...
+ */
+
+ if (strncasecmp(value, "from", 4) == 0)
+ {
+ /*
+ * Strip leading "from"...
+ */
+
+ value += 4;
+
+ while (isspace(*value & 255))
+ value ++;
+ }
+
+ /*
+ * Figure out what form the allow/deny address takes:
+ *
+ * All
+ * None
+ * *.domain.com
+ * .domain.com
+ * host.domain.com
+ * nnn.*
+ * nnn.nnn.*
+ * nnn.nnn.nnn.*
+ * nnn.nnn.nnn.nnn
+ * nnn.nnn.nnn.nnn/mm
+ * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
+ */
+
+ if (strcasecmp(value, "all") == 0)
+ {
+ /*
+ * All hosts...
+ */
+
+ if (strcasecmp(name, "Allow") == 0)
+ AllowIP(loc, 0, 0);
+ else
+ DenyIP(loc, 0, 0);
+ }
+ else if (strcasecmp(value, "none") == 0)
+ {
+ /*
+ * No hosts...
+ */
+
+ if (strcasecmp(name, "Allow") == 0)
+ AllowIP(loc, ~0, 0);
+ else
+ DenyIP(loc, ~0, 0);
+ }
+ else if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
+ {
+ /*
+ * Host or domain name...
+ */
+
+ if (value[0] == '*')
+ value ++;
+
+ if (strcasecmp(name, "Allow") == 0)
+ AllowHost(loc, value);
+ else
+ DenyHost(loc, value);
+ }
+ else
+ {
+ /*
+ * One of many IP address forms...
+ */
+
+ memset(ip, 0, sizeof(ip));
+ ipcount = sscanf(value, "%d.%d.%d.%d", ip + 0, ip + 1, ip + 2, ip + 3);
+ address = (((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3];
+
+ if ((value = strchr(value, '/')) != NULL)
+ {
+ value ++;
+ memset(mask, 0, sizeof(mask));
+ switch (sscanf(value, "%d.%d.%d.%d", mask + 0, mask + 1,
+ mask + 2, mask + 3))
+ {
+ case 1 :
+ netmask = (0xffffffff << (32 - mask[0])) & 0xffffffff;
+ break;
+ case 4 :
+ netmask = (((((mask[0] << 8) | mask[1]) << 8) |
+ mask[2]) << 8) | mask[3];
+ break;
+ default :
+ LogMessage(L_ERROR, "Bad netmask value %s on line %d.",
+ value, linenum);
+ netmask = 0xffffffff;
+ break;
+ }
+ }
+ else
+ netmask = netmasks[ipcount - 1];
+
+ if ((address & ~netmask) != 0)
+ {
+ LogMessage(L_WARN, "Discarding extra bits in %s address %08x for netmask %08x...",
+ name, address, netmask);
+ address &= netmask;
+ }
+
+ if (strcasecmp(name, "Allow") == 0)
+ AllowIP(loc, address, netmask);
+ else
+ DenyIP(loc, address, netmask);
+ }
+ }
+ else if (strcasecmp(name, "AuthType") == 0)
+ {
+ /*
+ * AuthType {none,basic,digest,basicdigest}
+ */
+
+ if (strcasecmp(value, "none") == 0)
+ {
+ loc->type = AUTH_NONE;
+ loc->level = AUTH_ANON;
+ }
+ else if (strcasecmp(value, "basic") == 0)
+ {
+ loc->type = AUTH_BASIC;
+
+ if (loc->level == AUTH_ANON)
+ loc->level = AUTH_USER;
+ }
+ else if (strcasecmp(value, "digest") == 0)
+ {
+ loc->type = AUTH_DIGEST;
+
+ if (loc->level == AUTH_ANON)
+ loc->level = AUTH_USER;
+ }
+ else if (strcasecmp(value, "basicdigest") == 0)
+ {
+ loc->type = AUTH_BASICDIGEST;
+
+ if (loc->level == AUTH_ANON)
+ loc->level = AUTH_USER;
+ }
+ else
+ LogMessage(L_WARN, "Unknown authorization type %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "AuthClass") == 0)
+ {
+ /*
+ * AuthClass anonymous, user, system, group
+ */
+
+ if (strcasecmp(value, "anonymous") == 0)
+ {
+ loc->type = AUTH_NONE;
+ loc->level = AUTH_ANON;
+ }
+ else if (strcasecmp(value, "user") == 0)
+ loc->level = AUTH_USER;
+ else if (strcasecmp(value, "group") == 0)
+ loc->level = AUTH_GROUP;
+ else if (strcasecmp(value, "system") == 0)
+ {
+ loc->level = AUTH_GROUP;
+
+ /*
+ * Use the default system group if none is defined so far...
+ */
+
+ if (NumSystemGroups == 0)
+ NumSystemGroups = 1;
+
+ for (i = 0; i < NumSystemGroups; i ++)
+ AddName(loc, SystemGroups[i]);
+ }
+ else
+ LogMessage(L_WARN, "Unknown authorization class %s on line %d.",
+ value, linenum);
+ }
+ else if (strcasecmp(name, "AuthGroupName") == 0)
+ AddName(loc, value);
+ else if (strcasecmp(name, "Require") == 0)
+ {
+ /*
+ * Apache synonym for AuthClass and AuthGroupName...
+ *
+ * Get initial word:
+ *
+ * Require valid-user
+ * Require group names
+ * Require user names
+ */
+
+ for (valptr = value;
+ !isspace(*valptr & 255) && *valptr != '>' && *valptr;
+ valptr ++);
+
+ if (*valptr)
+ *valptr++ = '\0';
+
+ if (strcasecmp(value, "valid-user") == 0 ||
+ strcasecmp(value, "user") == 0)
+ loc->level = AUTH_USER;
+ else if (strcasecmp(value, "group") == 0)
+ loc->level = AUTH_GROUP;
+ else
+ {
+ LogMessage(L_WARN, "Unknown Require type %s on line %d.",
+ value, linenum);
+ continue;
+ }
+
+ /*
+ * Get the list of names from the line...
+ */
+
+ for (value = valptr; *value;)
+ {
+ for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
+
+ if (*valptr)
+ *valptr++ = '\0';
+
+ AddName(loc, value);
+
+ for (value = valptr; isspace(*value & 255); value ++);
+ }
+ }
+ else if (strcasecmp(name, "Satisfy") == 0)
+ {
+ if (strcasecmp(value, "all") == 0)
+ loc->satisfy = AUTH_SATISFY_ALL;
+ else if (strcasecmp(value, "any") == 0)
+ loc->satisfy = AUTH_SATISFY_ANY;
+ else
+ LogMessage(L_WARN, "Unknown Satisfy value %s on line %d.", value,
+ linenum);
+ }
+ else
+ LogMessage(L_ERROR, "Unknown Location directive %s on line %d.",
+ name, linenum);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'get_address()' - Get an address + port number from a line.
+ */
+
+static int /* O - 1 if address good, 0 if bad */
+get_address(char *value, /* I - Value string */
+ unsigned defaddress, /* I - Default address */
+ int defport, /* I - Default port */
+ struct sockaddr_in *address) /* O - Socket address */
+{
+ char hostname[256], /* Hostname or IP */
+ portname[256]; /* Port number or name */
+ struct hostent *host; /* Host address */
+ struct servent *port; /* Port number */
+
+
+ /*
+ * Initialize the socket address to the defaults...
+ */
+
+ memset(address, 0, sizeof(struct sockaddr_in));
+ address->sin_family = AF_INET;
+ address->sin_addr.s_addr = htonl(defaddress);
+ address->sin_port = htons(defport);
+
+ /*
+ * Try to grab a hostname and port number...
+ */
+
+ switch (sscanf(value, "%255[^:]:%255s", hostname, portname))
+ {
+ case 1 :
+ if (strchr(hostname, '.') == NULL && defaddress == INADDR_ANY)
+ {
+ /*
+ * Hostname is a port number...
+ */
+
+ strlcpy(portname, hostname, sizeof(portname));
+ hostname[0] = '\0';
+ }
+ else
+ portname[0] = '\0';
+ break;
+ case 2 :
+ break;
+ default :
+ LogMessage(L_ERROR, "Unable to decode address \"%s\"!", value);
+ return (0);
+ }
+
+ /*
+ * Decode the hostname and port number as needed...
+ */
+
+ if (hostname[0] && strcmp(hostname, "*"))
+ {
+ if ((host = httpGetHostByName(hostname)) == NULL)
+ {
+ LogMessage(L_ERROR, "httpGetHostByName(\"%s\") failed - %s!", hostname,
+ hstrerror(h_errno));
+ return (0);
+ }
+
+ memcpy(&(address->sin_addr), host->h_addr, host->h_length);
+ address->sin_port = htons(defport);
+ }
+
+ if (portname[0] != '\0')
+ {
+ if (isdigit(portname[0] & 255))
+ address->sin_port = htons(atoi(portname));
+ else
+ {
+ if ((port = getservbyname(portname, NULL)) == NULL)
+ {
+ LogMessage(L_ERROR, "getservbyname(\"%s\") failed - %s!", portname,
+ strerror(errno));
+ return (0);
+ }
+ else
+ address->sin_port = htons(port->s_port);
+ }
+ }
+
+ return (1);
+}
+
+
+#ifdef HAVE_CDSASSL
+/*
+ * 'CDSAGetServerCerts()' - Convert a keychain name into the CFArrayRef
+ * required by SSLSetCertificate.
+ *
+ * For now we assumes that there is exactly one SecIdentity in the
+ * keychain - i.e. there is exactly one matching cert/private key pair.
+ * In the future we will search a keychain for a SecIdentity matching a
+ * specific criteria. We also skip the operation of adding additional
+ * non-signing certs from the keychain to the CFArrayRef.
+ *
+ * To create a self-signed certificate for testing use the certtool.
+ * Executing the following as root will do it:
+ *
+ * certtool c c v k=CUPS
+ */
+
+static CFArrayRef
+CDSAGetServerCerts(void)
+{
+ OSStatus err; /* Error info */
+ SecKeychainRef kcRef; /* Keychain reference */
+ SecIdentitySearchRef srchRef; /* Search reference */
+ SecIdentityRef identity; /* Identity */
+ CFArrayRef ca; /* Certificate array */
+
+
+ kcRef = NULL;
+ srchRef = NULL;
+ identity = NULL;
+ ca = NULL;
+ err = SecKeychainOpen(ServerCertificate, &kcRef);
+
+ if (err)
+ LogMessage(L_ERROR, "Cannot open keychain \"%s\", error %d.",
+ ServerCertificate, err);
+ else
+ {
+ /*
+ * Search for "any" identity matching specified key use;
+ * in this app, we expect there to be exactly one.
+ */
+
+ err = SecIdentitySearchCreate(kcRef, CSSM_KEYUSE_SIGN, &srchRef);
+
+ if (err)
+ LogMessage(L_ERROR,
+ "Cannot find signing key in keychain \"%s\", error %d",
+ ServerCertificate, err);
+ else
+ {
+ err = SecIdentitySearchCopyNext(srchRef, &identity);
+
+ if (err)
+ LogMessage(L_ERROR,
+ "Cannot find signing key in keychain \"%s\", error %d",
+ ServerCertificate, err);
+ else
+ {
+ if (CFGetTypeID(identity) != SecIdentityGetTypeID())
+ LogMessage(L_ERROR, "SecIdentitySearchCopyNext CFTypeID failure!");
+ else
+ {
+ /*
+ * Found one. Place it in a CFArray.
+ * TBD: snag other (non-identity) certs from keychain and add them
+ * to array as well.
+ */
+
+ ca = CFArrayCreate(NULL, (const void **)&identity, 1, NULL);
+
+ if (ca == nil)
+ LogMessage(L_ERROR, "CFArrayCreate error");
+ }
+
+ /*CFRelease(identity);*/
+ }
+
+ /*CFRelease(srchRef);*/
+ }
+
+ /*CFRelease(kcRef);*/
+ }
+
+ return ca;
+}
+#endif /* HAVE_CDSASSL */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/conf.h b/scheduler/conf.h
new file mode 100644
index 000000000..c8ff0a55e
--- /dev/null
+++ b/scheduler/conf.h
@@ -0,0 +1,201 @@
+/*
+ * "$Id$"
+ *
+ * Configuration file definitions for the Common UNIX Printing System (CUPS)
+ * scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+
+/*
+ * Log levels...
+ */
+
+#define L_STATE -2 /* Used internally for state-reasons */
+#define L_PAGE -1 /* Used internally for page logging */
+#define L_NONE 0
+#define L_EMERG 1 /* Emergency issues */
+#define L_ALERT 2 /* Something bad happened that needs attention */
+#define L_CRIT 3 /* Critical error but server continues */
+#define L_ERROR 4 /* Error condition */
+#define L_WARN 5 /* Warning */
+#define L_NOTICE 6 /* Normal condition that needs logging */
+#define L_INFO 7 /* General information */
+#define L_DEBUG 8 /* General debugging */
+#define L_DEBUG2 9 /* Detailed debugging */
+
+
+/*
+ * Printcap formats...
+ */
+
+#define PRINTCAP_BSD 0 /* Berkeley LPD format */
+#define PRINTCAP_SOLARIS 1 /* Solaris lpsched format */
+
+
+/*
+ * Globals...
+ */
+
+VAR char *ConfigurationFile VALUE(NULL),
+ /* Configuration file to use */
+ *ServerName VALUE(NULL),
+ /* FQDN for server */
+ *ServerAdmin VALUE(NULL),
+ /* Administrator's email */
+ *ServerRoot VALUE(NULL),
+ /* Root directory for scheduler */
+ *ServerBin VALUE(NULL),
+ /* Root directory for binaries */
+ *RequestRoot VALUE(NULL),
+ /* Directory for request files */
+ *DocumentRoot VALUE(NULL);
+ /* Root directory for documents */
+VAR int NumSystemGroups VALUE(0);
+ /* Number of system group names */
+VAR char *SystemGroups[MAX_SYSTEM_GROUPS],
+ /* System group names */
+ *AccessLog VALUE(NULL),
+ /* Access log filename */
+ *ErrorLog VALUE(NULL),
+ /* Error log filename */
+ *PageLog VALUE(NULL),
+ /* Page log filename */
+ *DataDir VALUE(NULL),
+ /* Data file directory */
+ *DefaultLanguage VALUE(NULL),
+ /* Default language encoding */
+ *DefaultCharset VALUE(NULL),
+ /* Default charset */
+ *DefaultLocale VALUE(NULL),
+ /* Default locale */
+ *RIPCache VALUE(NULL),
+ /* Amount of memory for RIPs */
+ *TempDir VALUE(NULL),
+ /* Temporary directory */
+ *Printcap VALUE(NULL),
+ /* Printcap file */
+ *PrintcapGUI VALUE(NULL),
+ /* GUI program to use for IRIX */
+ *FontPath VALUE(NULL),
+ /* Font search path */
+ *RemoteRoot VALUE(NULL),
+ /* Remote root user */
+ *Classification VALUE(NULL);
+ /* Classification of system */
+VAR uid_t User VALUE(1);
+ /* User ID for server */
+VAR gid_t Group VALUE(0);
+ /* Group ID for server */
+VAR int ClassifyOverride VALUE(0),
+ /* Allow overrides? */
+ ConfigFilePerm VALUE(0600),
+ /* Permissions for config files */
+ LogFilePerm VALUE(0644),
+ /* Permissions for log files */
+ LogLevel VALUE(L_ERROR),
+ /* Log level */
+ MaxClients VALUE(0),
+ /* Maximum number of clients */
+ MaxClientsPerHost VALUE(0),
+ /* Maximum number of clients per host */
+ MaxCopies VALUE(100),
+ /* Maximum number of copies per job */
+ MaxLogSize VALUE(1024 * 1024),
+ /* Maximum size of log files */
+ MaxPrinterHistory VALUE(10),
+ /* Maximum printer state history */
+ MaxRequestSize VALUE(0),
+ /* Maximum size of IPP requests */
+ HostNameLookups VALUE(FALSE),
+ /* Do we do reverse lookups? */
+ Timeout VALUE(DEFAULT_TIMEOUT),
+ /* Timeout during requests */
+ KeepAlive VALUE(TRUE),
+ /* Support the Keep-Alive option? */
+ KeepAliveTimeout VALUE(DEFAULT_KEEPALIVE),
+ /* Timeout between requests */
+ ImplicitClasses VALUE(TRUE),
+ /* Are classes implicitly created? */
+ ImplicitAnyClasses VALUE(FALSE),
+ /* Create AnyPrinter classes? */
+ HideImplicitMembers VALUE(TRUE),
+ /* Hide implicit class members? */
+ FileDevice VALUE(FALSE),
+ /* Allow file: devices? */
+ FilterLimit VALUE(0),
+ /* Max filter cost at any time */
+ FilterLevel VALUE(0),
+ /* Current filter level */
+ FilterNice VALUE(0),
+ /* Nice value for filters */
+ ReloadTimeout VALUE(0),
+ /* Timeout before reload from SIGHUP */
+ RootCertDuration VALUE(300),
+ /* Root certificate update interval */
+ RunAsUser VALUE(FALSE),
+ /* Run as unpriviledged user? */
+ RunUser, /* User to run as, used for files */
+ PrintcapFormat VALUE(PRINTCAP_BSD);
+ /* Format of printcap file? */
+VAR cups_file_t *AccessFile VALUE(NULL),
+ /* Access log file */
+ *ErrorFile VALUE(NULL),
+ /* Error log file */
+ *PageFile VALUE(NULL);
+ /* Page log file */
+VAR mime_t *MimeDatabase VALUE(NULL);
+ /* MIME type database */
+VAR int NumMimeTypes VALUE(0);
+ /* Number of MIME types */
+VAR const char **MimeTypes VALUE(NULL);
+ /* Array of MIME types */
+
+#ifdef HAVE_SSL
+VAR char *ServerCertificate VALUE(NULL);
+ /* Server certificate file */
+# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS)
+VAR char *ServerKey VALUE(NULL);
+ /* Server key file */
+# else
+VAR CFArrayRef ServerCertificatesArray VALUE(NULL);
+ /* Array containing certificates */
+# endif /* HAVE_LIBSSL || HAVE_GNUTLS */
+#endif /* HAVE_SSL */
+
+
+/*
+ * Prototypes...
+ */
+
+extern char *GetDateTime(time_t t);
+extern int ReadConfiguration(void);
+extern int LogRequest(client_t *con, http_status_t code);
+extern int LogMessage(int level, const char *message, ...)
+#ifdef __GNUC__
+__attribute__ ((__format__ (__printf__, 2, 3)))
+#endif /* __GNUC__ */
+;
+extern int LogPage(job_t *job, const char *page);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c
new file mode 100644
index 000000000..77fb0b9bc
--- /dev/null
+++ b/scheduler/cups-lpd.c
@@ -0,0 +1,1427 @@
+/*
+ * "$Id$"
+ *
+ * Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Process an incoming LPD request...
+ * print_file() - Print a file to a printer or class.
+ * recv_print_job() - Receive a print job from the client.
+ * remove_jobs() - Cancel one or more jobs.
+ * send_state() - Send the queue state.
+ * smart_gets() - Get a line of text, removing the trailing CR
+ * and/or LF.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+
+/*
+ * LPD "mini-daemon" for CUPS. This program must be used in conjunction
+ * with inetd or another similar program that monitors ports and starts
+ * daemons for each client connection. A typical configuration is:
+ *
+ * printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+ *
+ * This daemon implements most of RFC 1179 (the unofficial LPD specification)
+ * except for:
+ *
+ * - This daemon does not check to make sure that the source port is
+ * between 721 and 731, since it isn't necessary for proper
+ * functioning and port-based security is no security at all!
+ *
+ * - The "Print any waiting jobs" command is a no-op.
+ *
+ * The LPD-to-IPP mapping is as defined in RFC 2569. The report formats
+ * currently match the Solaris LPD mini-daemon.
+ */
+
+/*
+ * Prototypes...
+ */
+
+int print_file(const char *name, const char *file,
+ const char *title, const char *docname,
+ const char *user, int num_options,
+ cups_option_t *options);
+int recv_print_job(const char *dest, int num_defaults, cups_option_t *defaults);
+int remove_jobs(const char *dest, const char *agent, const char *list);
+int send_state(const char *dest, const char *list, int longstatus);
+char *smart_gets(char *s, int len, FILE *fp);
+
+
+/*
+ * 'main()' - Process an incoming LPD request...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ int num_defaults; /* Number of default options */
+ cups_option_t *defaults; /* Default options */
+ char line[256], /* Command string */
+ command, /* Command code */
+ *dest, /* Pointer to destination */
+ *list, /* Pointer to list */
+ *agent, /* Pointer to user */
+ status; /* Status for client */
+ int hostlen; /* Size of client address */
+ unsigned hostip; /* (32-bit) IP address */
+ struct sockaddr_in hostaddr; /* Address of client */
+ struct hostent *hostent; /* Host entry of client */
+ char hostname[256]; /* Hostname of client */
+
+
+ /*
+ * Don't buffer the output...
+ */
+
+ setbuf(stdout, NULL);
+
+ /*
+ * Log things using the "cups-lpd" name...
+ */
+
+ openlog("cups-lpd", LOG_PID, LOG_LPR);
+
+ /*
+ * Get the address of the client...
+ */
+
+ hostlen = sizeof(hostaddr);
+
+ if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen))
+ {
+ syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno));
+ strcpy(hostname, "unknown");
+ }
+ else
+ {
+ hostip = ntohl(hostaddr.sin_addr.s_addr);
+ hostent = gethostbyaddr((void *)&(hostaddr.sin_addr), hostlen, AF_INET);
+
+ if (hostent)
+ strlcpy(hostname, hostent->h_name, sizeof(hostname));
+ else
+ {
+ snprintf(hostname, sizeof(hostname), "%d.%d.%d.%d",
+ (hostip >> 24) & 255, (hostip >> 16) & 255,
+ (hostip >> 8) & 255, hostip & 255);
+ }
+
+ syslog(LOG_INFO, "Connection from %s (%d.%d.%d.%d)",
+ hostname, (hostip >> 24) & 255, (hostip >> 16) & 255,
+ (hostip >> 8) & 255, hostip & 255);
+ }
+
+ /*
+ * Scan the command-line for options...
+ */
+
+ num_defaults = 0;
+ defaults = NULL;
+
+ num_defaults = cupsAddOption("job-originating-host-name", hostname,
+ num_defaults, &defaults);
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'o' : /* Option */
+ if (argv[i][2])
+ num_defaults = cupsParseOptions(argv[i] + 2, num_defaults,
+ &defaults);
+ else
+ {
+ i ++;
+ if (i < argc)
+ num_defaults = cupsParseOptions(argv[i], num_defaults, &defaults);
+ else
+ syslog(LOG_WARNING, "Expected option string after -o option!");
+ }
+ break;
+ default :
+ syslog(LOG_WARNING, "Unknown option \"%c\" ignored!", argv[i][1]);
+ break;
+ }
+ }
+ else
+ syslog(LOG_WARNING, "Unknown command-line option \"%s\" ignored!", argv[i]);
+
+ /*
+ * RFC1179 specifies that only 1 daemon command can be received for
+ * every connection.
+ */
+
+ if (smart_gets(line, sizeof(line), stdin) == NULL)
+ {
+ /*
+ * Unable to get command from client! Send an error status and return.
+ */
+
+ syslog(LOG_ERR, "Unable to get command line from client!");
+ putchar(1);
+ return (1);
+ }
+
+ /*
+ * The first byte is the command byte. After that will be the queue name,
+ * resource list, and/or user name.
+ */
+
+ command = line[0];
+ dest = line + 1;
+
+ for (list = dest + 1; *list && !isspace(*list & 255); list ++);
+
+ while (isspace(*list & 255))
+ *list++ = '\0';
+
+ /*
+ * Do the command...
+ */
+
+ switch (command)
+ {
+ default : /* Unknown command */
+ syslog(LOG_ERR, "Unknown LPD command 0x%02X!", command);
+ syslog(LOG_ERR, "Command line = %s", line + 1);
+ putchar(1);
+
+ status = 1;
+ break;
+
+ case 0x01 : /* Print any waiting jobs */
+ syslog(LOG_INFO, "Print waiting jobs (no-op)");
+ putchar(0);
+
+ status = 0;
+ break;
+
+ case 0x02 : /* Receive a printer job */
+ syslog(LOG_INFO, "Receive print job for %s", dest);
+ /* recv_print_job() sends initial status byte */
+
+ status = recv_print_job(dest, num_defaults, defaults);
+ break;
+
+ case 0x03 : /* Send queue state (short) */
+ syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list);
+ /* no status byte for this command */
+
+ status = send_state(dest, list, 0);
+ break;
+
+ case 0x04 : /* Send queue state (long) */
+ syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list);
+ /* no status byte for this command */
+
+ status = send_state(dest, list, 1);
+ break;
+
+ case 0x05 : /* Remove jobs */
+ /*
+ * Grab the agent and skip to the list of users and/or jobs.
+ */
+
+ agent = list;
+
+ for (; *list && !isspace(*list & 255); list ++);
+ while (isspace(*list & 255))
+ *list++ = '\0';
+
+ syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
+
+ status = remove_jobs(dest, agent, list);
+
+ putchar(status);
+ break;
+ }
+
+ syslog(LOG_INFO, "Closing connection");
+ closelog();
+
+ return (status);
+}
+
+
+/*
+ * 'check_printer()' - Check that a printer exists and is accepting jobs.
+ */
+
+int /* O - Job ID */
+check_printer(const char *name) /* I - Printer or class name */
+{
+ http_t *http; /* Connection to server */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP job-id attribute */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ cups_lang_t *language; /* Language to use */
+ int accepting; /* printer-is-accepting-jobs value */
+
+
+ /*
+ * Setup a connection and request data...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
+ strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Build a standard CUPS URI for the printer and fill the standard IPP
+ * attributes...
+ */
+
+ if ((request = ippNew()) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to create request: %s", strerror(errno));
+ httpClose(http);
+ return (0);
+ }
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name);
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requested-attributes",
+ NULL, "printer-is-accepting-jobs");
+
+ /*
+ * Do the request...
+ */
+
+ response = cupsDoRequest(http, request, "/");
+
+ if (response == NULL)
+ {
+ syslog(LOG_ERR, "Unable to check printer status - %s",
+ ippErrorString(cupsLastError()));
+ accepting = 0;
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ syslog(LOG_ERR, "Unable to check printer status - %s",
+ ippErrorString(response->request.status.status_code));
+ accepting = 0;
+ }
+ else if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
+ IPP_TAG_BOOLEAN)) == NULL)
+ {
+ syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in response from server!");
+ accepting = 0;
+ }
+ else
+ accepting = attr->values[0].boolean;
+
+ if (response != NULL)
+ ippDelete(response);
+
+ httpClose(http);
+ cupsLangFree(language);
+
+ return (accepting);
+}
+
+
+/*
+ * 'print_file()' - Print a file to a printer or class.
+ */
+
+int /* O - Job ID */
+print_file(const char *name, /* I - Printer or class name */
+ const char *file, /* I - File to print */
+ const char *title, /* I - Title of job */
+ const char *docname, /* I - Name of job file */
+ const char *user, /* I - Owner of job */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ http_t *http; /* Connection to server */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP job-id attribute */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ cups_lang_t *language; /* Language to use */
+ int jobid; /* New job ID */
+
+
+ /*
+ * Setup a connection and request data...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
+ strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Build a standard CUPS URI for the printer and fill the standard IPP
+ * attributes...
+ */
+
+ if ((request = ippNew()) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to create request: %s", strerror(errno));
+ httpClose(http);
+ return (0);
+ }
+
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name);
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, user);
+
+ if (title)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title);
+ if (docname)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, docname);
+
+ /*
+ * Then add all options on the command-line...
+ */
+
+ cupsEncodeOptions(request, num_options, options);
+
+ /*
+ * Do the request...
+ */
+
+ snprintf(uri, sizeof(uri), "/printers/%s", name);
+
+ response = cupsDoFileRequest(http, request, uri, file);
+
+ if (response == NULL)
+ {
+ syslog(LOG_ERR, "Unable to print file - %s",
+ ippErrorString(cupsLastError()));
+ jobid = 0;
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ syslog(LOG_ERR, "Unable to print file - %s",
+ ippErrorString(response->request.status.status_code));
+ jobid = 0;
+ }
+ else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ syslog(LOG_ERR, "No job-id attribute found in response from server!");
+ jobid = 0;
+ }
+ else
+ {
+ jobid = attr->values[0].integer;
+
+ syslog(LOG_INFO, "Print file - job ID = %d", jobid);
+ }
+
+ if (response != NULL)
+ ippDelete(response);
+
+ httpClose(http);
+ cupsLangFree(language);
+
+ return (jobid);
+}
+
+
+/*
+ * 'recv_print_job()' - Receive a print job from the client.
+ */
+
+int /* O - Command status */
+recv_print_job(const char *dest, /* I - Destination */
+ int num_defaults,
+ /* I - Number of default options */
+ cups_option_t *defaults) /* I - Default options */
+{
+ int i; /* Looping var */
+ int status; /* Command status */
+ int fd; /* Temporary file */
+ FILE *fp; /* File pointer */
+ char filename[1024]; /* Temporary filename */
+ int bytes; /* Bytes received */
+ char line[256], /* Line from file/stdin */
+ command, /* Command from line */
+ *count, /* Number of bytes */
+ *name; /* Name of file */
+ int num_data; /* Number of data files */
+ char control[1024], /* Control filename */
+ data[32][256], /* Data files */
+ temp[32][1024]; /* Temporary files */
+ char user[1024], /* User name */
+ title[1024], /* Job title */
+ docname[1024], /* Document name */
+ queue[256], /* Printer/class queue */
+ *instance; /* Printer/class instance */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests, /* Destinations */
+ *destptr; /* Current destination */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ int banner; /* Print banner? */
+
+
+ status = 0;
+ num_data = 0;
+ fd = -1;
+
+ control[0] = '\0';
+
+ strlcpy(queue, dest, sizeof(queue));
+
+ if ((instance = strrchr(queue, '/')) != NULL)
+ *instance++ = '\0';
+
+ num_dests = cupsGetDests(&dests);
+ if ((destptr = cupsGetDest(queue, instance, num_dests, dests)) == NULL)
+ {
+ /*
+ * If the queue name is blank or "lp" then use the default queue.
+ */
+
+ if (!queue[0] || !strcmp(queue, "lp"))
+ if ((destptr = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
+ strlcpy(queue, destptr->name, sizeof(queue));
+
+ if (destptr == NULL)
+ {
+ if (instance)
+ syslog(LOG_ERR, "Unknown destination %s/%s!", queue, instance);
+ else
+ syslog(LOG_ERR, "Unknown destination %s!", queue);
+
+ cupsFreeDests(num_dests, dests);
+
+ putchar(1);
+
+ return (1);
+ }
+ }
+
+ if (!check_printer(queue))
+ {
+ cupsFreeDests(num_dests, dests);
+
+ putchar(1);
+
+ return (1);
+ }
+
+ putchar(0);
+
+ while (smart_gets(line, sizeof(line), stdin) != NULL)
+ {
+ if (strlen(line) < 2)
+ {
+ status = 1;
+ break;
+ }
+
+ command = line[0];
+ count = line + 1;
+
+ for (name = count + 1; *name && !isspace(*name & 255); name ++);
+ while (isspace(*name & 255))
+ *name++ = '\0';
+
+ switch (command)
+ {
+ default :
+ case 0x01 : /* Abort */
+ status = 1;
+ break;
+
+ case 0x02 : /* Receive control file */
+ if (strlen(name) < 2)
+ {
+ syslog(LOG_ERR, "Bad control file name \"%s\"", name);
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ if (control[0])
+ {
+ /*
+ * Append to the existing control file - the LPD spec is
+ * not entirely clear, but at least the OS/2 LPD code sends
+ * multiple control files per connection...
+ */
+
+ if ((fd = open(control, O_WRONLY)) < 0)
+ {
+ syslog(LOG_ERR,
+ "Unable to append to temporary control file \"%s\" - %s",
+ control, strerror(errno));
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ lseek(fd, 0, SEEK_END);
+ }
+ else
+ {
+ if ((fd = cupsTempFd(control, sizeof(control))) < 0)
+ {
+ syslog(LOG_ERR, "Unable to open temporary control file \"%s\" - %s",
+ control, strerror(errno));
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ strcpy(filename, control);
+ }
+ break;
+
+ case 0x03 : /* Receive data file */
+ if (strlen(name) < 2)
+ {
+ syslog(LOG_ERR, "Bad data file name \"%s\"", name);
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ if (num_data >= (sizeof(data) / sizeof(data[0])))
+ {
+ /*
+ * Too many data files...
+ */
+
+ syslog(LOG_ERR, "Too many data files (%d)", num_data);
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ strlcpy(data[num_data], name, sizeof(data[0]));
+
+ if ((fd = cupsTempFd(temp[num_data], sizeof(temp[0]))) < 0)
+ {
+ syslog(LOG_ERR, "Unable to open temporary data file \"%s\" - %s",
+ temp[num_data], strerror(errno));
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ strcpy(filename, temp[num_data]);
+
+ num_data ++;
+ break;
+ }
+
+ putchar(status);
+
+ if (status)
+ break;
+
+ /*
+ * Copy the data or control file from the client...
+ */
+
+ for (i = atoi(count); i > 0; i -= bytes)
+ {
+ if (i > sizeof(line))
+ bytes = sizeof(line);
+ else
+ bytes = i;
+
+ if ((bytes = fread(line, 1, bytes, stdin)) > 0)
+ bytes = write(fd, line, bytes);
+
+ if (bytes < 1)
+ {
+ syslog(LOG_ERR, "Error while reading file - %s",
+ strerror(errno));
+ status = 1;
+ break;
+ }
+ }
+
+ /*
+ * Read trailing nul...
+ */
+
+ if (!status)
+ {
+ if (fread(line, 1, 1, stdin) < 1)
+ {
+ status = 1;
+ syslog(LOG_ERR, "Error while reading trailing nul - %s",
+ strerror(errno));
+ }
+ else if (line[0])
+ {
+ status = 1;
+ syslog(LOG_ERR, "Trailing character after file is not nul (%02X)!",
+ line[0]);
+ }
+ }
+
+ /*
+ * Close the file and send an acknowledgement...
+ */
+
+ close(fd);
+
+ putchar(status);
+
+ if (status)
+ break;
+ }
+
+ if (!status)
+ {
+ /*
+ * Process the control file and print stuff...
+ */
+
+ if ((fp = fopen(control, "rb")) == NULL)
+ status = 1;
+ else
+ {
+ /*
+ * Grab the job information first...
+ */
+
+ title[0] = '\0';
+ user[0] = '\0';
+ docname[0] = '\0';
+ banner = cupsGetOption("job-sheets", num_defaults, defaults) != NULL;
+
+ while (smart_gets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Process control lines...
+ */
+
+ switch (line[0])
+ {
+ case 'J' : /* Job name */
+ strlcpy(title, line + 1, sizeof(title));
+ break;
+
+ case 'N' : /* Document name */
+ strlcpy(docname, line + 1, sizeof(docname));
+ break;
+
+ case 'P' : /* User identification */
+ strlcpy(user, line + 1, sizeof(user));
+ break;
+
+ case 'L' : /* Print banner page */
+ banner = 1;
+ break;
+ }
+
+ if (status)
+ break;
+ }
+
+ /*
+ * Then print the jobs...
+ */
+
+ rewind(fp);
+
+ while (smart_gets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Process control lines...
+ */
+
+ switch (line[0])
+ {
+ case 'c' : /* Plot CIF file */
+ case 'd' : /* Print DVI file */
+ case 'f' : /* Print formatted file */
+ case 'g' : /* Plot file */
+ case 'l' : /* Print file leaving control characters (raw) */
+ case 'n' : /* Print ditroff output file */
+ case 'o' : /* Print PostScript output file */
+ case 'p' : /* Print file with 'pr' format (prettyprint) */
+ case 'r' : /* File to print with FORTRAN carriage control */
+ case 't' : /* Print troff output file */
+ case 'v' : /* Print raster file */
+ /*
+ * Check that we have a username...
+ */
+
+ if (!user[0])
+ {
+ syslog(LOG_WARNING, "No username specified by client! "
+ "Using \"anonymous\"...");
+ strcpy(user, "anonymous");
+ }
+
+ /*
+ * Copy the default options...
+ */
+
+ num_options = 0;
+ options = NULL;
+
+ for (i = 0; i < num_defaults; i ++)
+ num_options = cupsAddOption(defaults[i].name,
+ defaults[i].value,
+ num_options, &options);
+ for (i = 0; i < destptr->num_options; i ++)
+ num_options = cupsAddOption(destptr->options[i].name,
+ destptr->options[i].value,
+ num_options, &options);
+
+ /*
+ * Add additional options as needed...
+ */
+
+ if (!banner)
+ num_options = cupsAddOption("job-sheets", "none",
+ num_options, &options);
+
+ if (line[0] == 'l')
+ num_options = cupsAddOption("raw", "", num_options, &options);
+
+ if (line[0] == 'p')
+ num_options = cupsAddOption("prettyprint", "", num_options,
+ &options);
+
+ /*
+ * Figure out which file we are printing...
+ */
+
+ for (i = 0; i < num_data; i ++)
+ if (strcmp(data[i], line + 1) == 0)
+ break;
+
+ if (i >= num_data)
+ {
+ status = 1;
+ break;
+ }
+
+ /*
+ * Send the print request...
+ */
+
+ if (print_file(queue, temp[i], title, docname, user, num_options,
+ options) == 0)
+ status = 1;
+ else
+ status = 0;
+
+ cupsFreeOptions(num_options, options);
+ break;
+ }
+
+ if (status)
+ break;
+ }
+
+ fclose(fp);
+ }
+ }
+
+ /*
+ * Clean up all temporary files and return...
+ */
+
+ unlink(control);
+
+ for (i = 0; i < num_data; i ++)
+ unlink(temp[i]);
+
+ cupsFreeDests(num_dests, dests);
+
+ return (status);
+}
+
+
+/*
+ * 'remove_jobs()' - Cancel one or more jobs.
+ */
+
+int /* O - Command status */
+remove_jobs(const char *dest, /* I - Destination */
+ const char *agent, /* I - User agent */
+ const char *list) /* I - List of jobs or users */
+{
+ int id; /* Job ID */
+ http_t *http; /* HTTP server connection */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+
+
+ (void)dest; /* Suppress compiler warnings... */
+
+ /*
+ * Try connecting to the local server...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
+ strerror(errno));
+ return (1);
+ }
+
+ language = cupsLangDefault();
+
+ /*
+ * Loop for each job...
+ */
+
+ while ((id = atoi(list)) > 0)
+ {
+ /*
+ * Skip job ID in list...
+ */
+
+ while (isdigit(*list & 255))
+ list ++;
+ while (isspace(*list & 255))
+ list ++;
+
+ /*
+ * Build an IPP_CANCEL_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * requesting-user-name
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_CANCEL_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ sprintf(uri, "ipp://localhost/jobs/%d", id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, agent);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ cupsLangFree(language);
+ httpClose(http);
+ return (1);
+ }
+ else
+ syslog(LOG_INFO, "Job ID %d cancelled", id);
+
+ ippDelete(response);
+ }
+ else
+ {
+ syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
+ ippErrorString(cupsLastError()));
+ cupsLangFree(language);
+ httpClose(http);
+ return (1);
+ }
+ }
+
+ cupsLangFree(language);
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * 'send_state()' - Send the queue state.
+ */
+
+int /* O - Command status */
+send_state(const char *dest, /* I - Destination */
+ const char *list, /* I - Job or user */
+ int longstatus) /* I - List of jobs or users */
+{
+ int id; /* Job ID from list */
+ http_t *http; /* HTTP server connection */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ ipp_pstate_t state; /* Printer state */
+ const char *jobdest, /* Pointer into job-printer-uri */
+ *jobuser, /* Pointer to job-originating-user-name */
+ *jobname; /* Pointer to job-name */
+ ipp_jstate_t jobstate; /* job-state */
+ int jobid, /* job-id */
+ jobsize, /* job-k-octets */
+ jobcount, /* Number of jobs */
+ jobcopies, /* Number of copies */
+ rank; /* Rank of job */
+ char rankstr[255]; /* Rank string */
+ char namestr[1024]; /* Job name string */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ char queue[256], /* Printer/class queue */
+ *instance; /* Printer/class instance */
+ static const char * const ranks[10] = /* Ranking strings */
+ {
+ "th",
+ "st",
+ "nd",
+ "rd",
+ "th",
+ "th",
+ "th",
+ "th",
+ "th",
+ "th"
+ };
+ static const char * const requested[] =
+ { /* Requested attributes */
+ "job-id",
+ "job-k-octets",
+ "job-state",
+ "job-printer-uri",
+ "job-originating-user-name",
+ "job-name",
+ "copies"
+ };
+
+
+ /*
+ * Remove instance from destination, if any...
+ */
+
+ strlcpy(queue, dest, sizeof(queue));
+
+ if ((instance = strrchr(queue, '/')) != NULL)
+ *instance++ = '\0';
+
+ /*
+ * Try connecting to the local server...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
+ strerror(errno));
+ printf("Unable to connect to server %s: %s", cupsServer(), strerror(errno));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", queue);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-state");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ syslog(LOG_WARNING, "Unable to get printer list: %s\n",
+ ippErrorString(response->request.status.status_code));
+ printf("Unable to get printer list: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
+ state = (ipp_pstate_t)attr->values[0].integer;
+ else
+ state = IPP_PRINTER_STOPPED;
+
+ switch (state)
+ {
+ case IPP_PRINTER_IDLE :
+ printf("%s is ready\n", dest);
+ break;
+ case IPP_PRINTER_PROCESSING :
+ printf("%s is ready and printing\n", dest);
+ break;
+ case IPP_PRINTER_STOPPED :
+ printf("%s is not ready\n", dest);
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ syslog(LOG_WARNING, "Unable to get printer list: %s\n",
+ ippErrorString(cupsLastError()));
+ printf("Unable to get printer list: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ /*
+ * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
+ * the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri or printer-uri
+ */
+
+ id = atoi(list);
+
+ request = ippNew();
+
+ request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", queue);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ if (id)
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", id);
+ else
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, list);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+ }
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(requested) / sizeof(requested[0]),
+ NULL, requested);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ jobcount = 0;
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ printf("get-jobs failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ rank = 1;
+
+ /*
+ * Loop through the job list and display them...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL &&
+ (attr->group_tag != IPP_TAG_JOB || attr->name == NULL))
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ jobid = 0;
+ jobsize = 0;
+ jobstate = IPP_JOB_PENDING;
+ jobname = "untitled";
+ jobuser = NULL;
+ jobdest = NULL;
+ jobcopies = 1;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobid = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobsize = attr->values[0].integer * 1024;
+
+ if (strcmp(attr->name, "job-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ jobstate = (ipp_jstate_t)attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ jobdest ++;
+
+ if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobuser = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "job-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobname = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "copies") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobcopies = attr->values[0].integer;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (jobdest == NULL || jobid == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ if (!longstatus && jobcount == 0)
+ puts("Rank Owner Job File(s) Total Size");
+
+ jobcount ++;
+
+ /*
+ * Display the job...
+ */
+
+ if (jobstate == IPP_JOB_PROCESSING)
+ strcpy(rankstr, "active");
+ else
+ {
+ snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
+ rank ++;
+ }
+
+ if (longstatus)
+ {
+ puts("");
+
+ if (jobcopies > 1)
+ snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
+ jobname);
+ else
+ strlcpy(namestr, jobname, sizeof(namestr));
+
+ printf("%s: %-33.33s [job %d localhost]\n", jobuser, rankstr, jobid);
+ printf(" %-39.39s %d bytes\n", namestr, jobsize);
+ }
+ else
+ printf("%-7s %-7.7s %-7d %-31.31s %d bytes\n", rankstr, jobuser,
+ jobid, jobname, jobsize);
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ printf("get-jobs failed: %s\n", ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ if (jobcount == 0)
+ puts("no entries");
+
+ cupsLangFree(language);
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * 'smart_gets()' - Get a line of text, removing the trailing CR and/or LF.
+ */
+
+char * /* O - Line read or NULL */
+smart_gets(char *s, /* I - Pointer to line buffer */
+ int len, /* I - Size of line buffer */
+ FILE *fp) /* I - File to read from */
+{
+ char *ptr, /* Pointer into line */
+ *end; /* End of line */
+ int ch; /* Character from file */
+
+
+ /*
+ * Read the line; unlike fgets(), we read the entire line but dump
+ * characters that go past the end of the buffer. Also, we accept
+ * CR, LF, or CR LF for the line endings to be "safe", although
+ * RFC 1179 specifically says "just use LF".
+ */
+
+ ptr = s;
+ end = s + len - 1;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == '\n')
+ break;
+ else if (ch == '\r')
+ {
+ /*
+ * See if a LF follows...
+ */
+
+ ch = getc(fp);
+
+ if (ch != '\n')
+ ungetc(ch, fp);
+
+ break;
+ }
+ else if (ptr < end)
+ *ptr++ = ch;
+ }
+
+ *ptr = '\0';
+
+ if (ch == EOF && ptr == s)
+ return (NULL);
+ else
+ return (s);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/cups-polld.c b/scheduler/cups-polld.c
new file mode 100644
index 000000000..a64bbfbfc
--- /dev/null
+++ b/scheduler/cups-polld.c
@@ -0,0 +1,409 @@
+/*
+ * "$Id$"
+ *
+ * Polling daemon for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Open socks and poll until we are killed...
+ * poll_server() - Poll the server for the given set of printers or classes.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/http-private.h>
+#include <cups/cups.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/language.h>
+#include <cups/string.h>
+
+
+/*
+ * Local functions...
+ */
+
+int poll_server(http_t *http, cups_lang_t *language, ipp_op_t op,
+ int sock, int port, int interval, const char *prefix);
+
+
+/*
+ * 'main()' - Open socks and poll until we are killed...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* HTTP connection */
+ cups_lang_t *language; /* Language info */
+ int interval; /* Polling interval */
+ int sock; /* Browser sock */
+ int port; /* Browser port */
+ int val; /* Socket option value */
+ int seconds, /* Seconds left from poll */
+ remain; /* Total remaining time to sleep */
+ char prefix[1024]; /* Prefix for log messages */
+
+
+ /*
+ * Don't buffer log messages...
+ */
+
+ setbuf(stderr, NULL);
+
+ /*
+ * The command-line must contain the following:
+ *
+ * cups-polld server server-port interval port
+ */
+
+ if (argc != 5)
+ {
+ fputs("Usage: cups-polld server server-port interval port\n", stderr);
+ return (1);
+ }
+
+ interval = atoi(argv[3]);
+ port = atoi(argv[4]);
+
+ if (interval < 2)
+ interval = 2;
+
+ snprintf(prefix, sizeof(prefix), "[cups-polld %s:%d]", argv[1], atoi(argv[2]));
+
+ /*
+ * Open a broadcast socket...
+ */
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ fprintf(stderr, "ERROR: %s Unable to open broadcast socket: %s\n", prefix,
+ strerror(errno));
+ return (1);
+ }
+
+ /*
+ * Set the "broadcast" flag...
+ */
+
+ val = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+ {
+ fprintf(stderr, "ERROR: %s Unable to put socket in broadcast mode: %s\n",
+ prefix, strerror(errno));
+
+ close(sock);
+ return (1);
+ }
+
+ /*
+ * Open a connection to the server...
+ */
+
+ while ((http = httpConnectEncrypt(argv[1], atoi(argv[2]),
+ cupsEncryption())) == NULL)
+ {
+ fprintf(stderr, "ERROR: %s Unable to connect to %s on port %s: %s\n",
+ prefix, argv[1], argv[2],
+ h_errno ? hstrerror(h_errno) : strerror(errno));
+ sleep (interval);
+ }
+
+ /*
+ * Loop forever, asking for available printers and classes...
+ */
+
+ language = cupsLangDefault();
+
+ for (;;)
+ {
+ /*
+ * Get the printers, then the classes...
+ */
+
+ remain = interval;
+
+ if ((seconds = poll_server(http, language, CUPS_GET_PRINTERS, sock, port,
+ interval / 2, prefix)) > 0)
+ remain -= seconds;
+
+ if ((seconds = poll_server(http, language, CUPS_GET_CLASSES, sock, port,
+ interval / 2, prefix)) > 0)
+ remain -= seconds;
+
+ /*
+ * Sleep for any remaining time...
+ */
+
+ if (remain > 0)
+ sleep(remain);
+ }
+}
+
+
+/*
+ * 'poll_server()' - Poll the server for the given set of printers or classes.
+ */
+
+int /* O - Number of seconds or -1 on error */
+poll_server(http_t *http, /* I - HTTP connection */
+ cups_lang_t *language, /* I - Language */
+ ipp_op_t op, /* I - Operation code */
+ int sock, /* I - Broadcast sock */
+ int port, /* I - Broadcast port */
+ int interval, /* I - Polling interval */
+ const char *prefix) /* I - Prefix for log messages */
+{
+ int seconds; /* Number of seconds */
+ int count, /* Current number of printers/classes */
+ max_count; /* Maximum printers/classes per second */
+ ipp_t *request, /* Request data */
+ *response; /* Response data */
+ ipp_attribute_t *attr; /* Current attribute */
+ const char *uri, /* printer-uri */
+ *info, /* printer-info */
+ *location, /* printer-location */
+ *make_model; /* printer-make-and-model */
+ cups_ptype_t type; /* printer-type */
+ ipp_pstate_t state; /* printer-state */
+ int accepting; /* printer-is-accepting-jobs */
+ struct sockaddr_in addr; /* Broadcast address */
+ char packet[1540]; /* Data packet */
+ static const char * const attrs[] = /* Requested attributes */
+ {
+ "printer-info",
+ "printer-is-accepting-jobs",
+ "printer-location",
+ "printer-make-and-model",
+ "printer-name",
+ "printer-state",
+ "printer-type",
+ "printer-uri-supported"
+ };
+
+
+ /*
+ * Broadcast to 127.0.0.1 (localhost)
+ */
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_addr.s_addr = htonl(0x7f000001);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ /*
+ * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which requires
+ * only the attributes-charset and attributes-natural-language attributes.
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
+ NULL, attrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "ERROR: %s get-%s failed: %s\n", prefix,
+ op == CUPS_GET_PRINTERS ? "printers" : "classes",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (-1);
+ }
+
+ /*
+ * Figure out how many printers/classes we have...
+ */
+
+ for (attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME),
+ max_count = 0;
+ attr != NULL;
+ attr = ippFindNextAttribute(response, "printer-name", IPP_TAG_NAME),
+ max_count ++);
+
+ fprintf(stderr, "DEBUG: %s found %d %s.\n", prefix, max_count,
+ op == CUPS_GET_PRINTERS ? "printers" : "classes");
+
+ count = 0;
+ seconds = time(NULL);
+ max_count = max_count / interval + 1;
+
+ /*
+ * Loop through the printers or classes returned in the list...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a printer...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this printer...
+ */
+
+ uri = NULL;
+ info = "";
+ location = "";
+ make_model = "";
+ type = CUPS_PRINTER_REMOTE;
+ accepting = 1;
+ state = IPP_PRINTER_IDLE;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-uri-supported") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ uri = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-info") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ info = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 &&
+ attr->value_tag == IPP_TAG_BOOLEAN)
+ accepting = attr->values[0].boolean;
+
+ if (strcmp(attr->name, "printer-location") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ location = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-make-and-model") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ make_model = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ state = (ipp_pstate_t)attr->values[0].integer;
+
+ if (strcmp(attr->name, "printer-type") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ type = (cups_ptype_t)attr->values[0].integer;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (uri == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a local printer or class...
+ */
+
+ if (!(type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ {
+ /*
+ * Send the printer information...
+ */
+
+ type |= CUPS_PRINTER_REMOTE;
+
+ if (!accepting)
+ type |= CUPS_PRINTER_REJECTING;
+
+ snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
+ type, state, uri, location, info, make_model);
+
+ fprintf(stderr, "DEBUG2: %s Sending %s", prefix, packet);
+
+ if (sendto(sock, packet, strlen(packet), 0,
+ (struct sockaddr *)&addr, sizeof(addr)) <= 0)
+ {
+ ippDelete(response);
+ perror("cups-polld");
+ return (-1);
+ }
+
+ /*
+ * Throttle the local broadcasts as needed so that we don't
+ * overwhelm the local server...
+ */
+
+ count ++;
+ if (count >= max_count)
+ {
+ /*
+ * Sleep for a second...
+ */
+
+ count = 0;
+ sleep(1);
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: %s get-%s failed: %s\n", prefix,
+ op == CUPS_GET_PRINTERS ? "printers" : "classes",
+ ippErrorString(cupsLastError()));
+ return (-1);
+ }
+
+ /*
+ * Return the number of seconds we used...
+ */
+
+ return (time(NULL) - seconds);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/cups.pam b/scheduler/cups.pam
new file mode 100644
index 000000000..f38e70184
--- /dev/null
+++ b/scheduler/cups.pam
@@ -0,0 +1,2 @@
+auth required /lib/security/pam_pwdb.so nullok shadow
+account required /lib/security/pam_pwdb.so
diff --git a/scheduler/cupsd.dsp b/scheduler/cupsd.dsp
new file mode 100644
index 000000000..60b2cb927
--- /dev/null
+++ b/scheduler/cupsd.dsp
@@ -0,0 +1,173 @@
+# Microsoft Developer Studio Project File - Name="cupsd" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=cupsd - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "cupsd.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "cupsd.mak" CFG="cupsd - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cupsd - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "cupsd - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "cupsd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "cupsd - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../visualc" /I ".." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "cupsd - Win32 Release"
+# Name "cupsd - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\auth.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\classes.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\conf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dirsvc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\job.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\listen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\printers.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\auth.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\classes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\conf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cupsd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dirsvc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\job.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\printers.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h
new file mode 100644
index 000000000..a3ed9411a
--- /dev/null
+++ b/scheduler/cupsd.h
@@ -0,0 +1,215 @@
+/*
+ * "$Id$"
+ *
+ * Main header file for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+
+/*
+ * Include necessary headers.
+ */
+
+#include <cups/http-private.h>
+#include <cups/string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef WIN32
+# include <direct.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 */
+
+#include <cups/cups.h>
+#include "mime.h"
+#include <cups/http.h>
+#include <cups/ipp.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+
+#if defined(HAVE_CDSASSL)
+# include <CoreFoundation/CoreFoundation.h>
+#endif /* HAVE_CDSASSL */
+
+
+/*
+ * Some OS's don't have hstrerror(), most notably Solaris...
+ */
+
+#ifndef HAVE_HSTRERROR
+# define hstrerror cups_hstrerror
+
+extern const char *cups_hstrerror(int);
+#endif /* !HAVE_HSTRERROR */
+
+
+/*
+ * Common constants.
+ */
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE (!FALSE)
+#endif /* !FALSE */
+
+
+/*
+ * Implementation limits...
+ */
+
+#define MAX_USERPASS 33 /* Maximum size of username/password */
+#define MAX_FILTERS 20 /* Maximum number of filters */
+#define MAX_SYSTEM_GROUPS 32 /* Maximum number of system groups */
+
+
+/*
+ * Defaults...
+ */
+
+#define DEFAULT_HISTORY 1 /* Preserve job history? */
+#define DEFAULT_FILES 0 /* Preserve job files? */
+#define DEFAULT_TIMEOUT 300 /* Timeout during requests/updates */
+#define DEFAULT_KEEPALIVE 60 /* Timeout between requests */
+#define DEFAULT_INTERVAL 30 /* Interval between browse updates */
+#define DEFAULT_LANGUAGE setlocale(LC_ALL,"")
+ /* Default language encoding */
+#define DEFAULT_CHARSET "utf-8" /* Default charset */
+
+
+/*
+ * Global variable macros...
+ */
+
+#ifdef _MAIN_C_
+# define VAR
+# define VALUE(x) =x
+# define VALUE2(x,y) ={x,y}
+#else
+# define VAR extern
+# define VALUE(x)
+# define VALUE2(x,y)
+#endif /* _MAIN_C */
+
+
+/*
+ * Other stuff for the scheduler...
+ */
+
+#include "cert.h"
+#include "client.h"
+#include "auth.h"
+#include "printers.h"
+#include "classes.h"
+#include "job.h"
+#include "conf.h"
+#include "banners.h"
+#include "dirsvc.h"
+#include "network.h"
+
+
+/*
+ * Directory handling functions...
+ */
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+typedef struct dirent DIRENT;
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+typedef struct direct DIRENT;
+# define NAMLEN(dirent) (dirent)->d_namlen
+#endif
+
+
+/*
+ * Reload types...
+ */
+
+#define RELOAD_NONE 0 /* No reload needed */
+#define RELOAD_ALL 1 /* Reload everything */
+#define RELOAD_CUPSD 2 /* Reload only cupsd.conf */
+
+
+/*
+ * Globals...
+ */
+
+VAR int MaxFDs, /* Maximum number of files */
+ SetSize; /* The size of the input/output sets */
+VAR fd_set *InputSet, /* Input files for select() */
+ *OutputSet; /* Output files for select() */
+
+VAR time_t ReloadTime VALUE(0);
+ /* Time of reload request... */
+VAR int NeedReload VALUE(RELOAD_ALL),
+ /* Need to load configuration? */
+ SignalCount VALUE(0);
+ /* Signal handler level */
+
+VAR char *TZ VALUE(NULL);
+ /* Timezone configuration */
+
+VAR ipp_t *Devices VALUE(NULL),
+ /* Available devices */
+ *PPDs VALUE(NULL);
+ /* Available PPDs */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void CatchChildSignals(void);
+extern void ClearString(char **s);
+extern void HoldSignals(void);
+extern void IgnoreChildSignals(void);
+extern void LoadDevices(const char *d);
+extern void LoadPPDs(const char *d);
+extern void ReleaseSignals(void);
+extern void SetString(char **s, const char *v);
+extern void SetStringf(char **s, const char *f, ...);
+extern void StartServer(void);
+extern void StopServer(void);
+extern void cupsdClosePipe(int *fds);
+extern int cupsdOpenPipe(int *fds);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/devices.c b/scheduler/devices.c
new file mode 100644
index 000000000..917e57b62
--- /dev/null
+++ b/scheduler/devices.c
@@ -0,0 +1,484 @@
+/*
+ * "$Id$"
+ *
+ * Device scanning routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * LoadDevices() - Load all available devices.
+ * compare_devs() - Compare PPD file make and model names for sorting.
+ * sigalrm_handler() - Handle alarm signals for backends that get hung
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * Device information structure...
+ */
+
+typedef struct
+{
+ char device_class[128], /* Device class */
+ device_make_and_model[128], /* Make and model, if known */
+ device_info[128], /* Device info/description */
+ device_uri[1024]; /* Device URI */
+} dev_info_t;
+
+
+/*
+ * Local globals...
+ */
+
+static int num_devs, /* Number of devices */
+ alloc_devs; /* Number of allocated entries */
+static dev_info_t *devs; /* Device info */
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_devs(const dev_info_t *p0, const dev_info_t *p1);
+static void sigalrm_handler(int sig);
+
+
+/*
+ * 'LoadDevices()' - Load all available devices.
+ */
+
+void
+LoadDevices(const char *d) /* I - Directory to scan */
+{
+ int i; /* Looping var */
+ int count; /* Number of devices from backend */
+ int compat; /* Compatibility device? */
+ FILE *fp; /* Pipe to device backend */
+ DIR *dir; /* Directory pointer */
+ DIRENT *dent; /* Directory entry */
+ char filename[1024], /* Name of backend */
+ line[2048], /* Line from backend */
+ dclass[64], /* Device class */
+ uri[1024], /* Device URI */
+ info[128], /* Device info */
+ make_model[256];/* Make and model */
+ dev_info_t *dev; /* Current device */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Initialize the device list.
+ */
+
+ Devices = ippNew();
+
+ /*
+ * Try opening the backend directory...
+ */
+
+ if ((dir = opendir(d)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadDevices: Unable to open backend directory \"%s\": %s",
+ d, strerror(errno));
+ return;
+ }
+
+ /*
+ * Setup the devices array...
+ */
+
+ alloc_devs = 0;
+ num_devs = 0;
+ devs = (dev_info_t *)0;
+
+ /*
+ * Ignore child signals...
+ */
+
+ IgnoreChildSignals();
+
+ /*
+ * Loop through all of the device backends...
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ /*
+ * Skip "." and ".."...
+ */
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ /*
+ * Run the backend with no arguments and collect the output...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", d, dent->d_name);
+ if ((fp = popen(filename, "r")) != NULL)
+ {
+ /*
+ * Set an alarm for the first read from the backend; this avoids
+ * problems when a backend is hung getting device information.
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGALRM, sigalrm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGALRM);
+ action.sa_handler = sigalrm_handler;
+ sigaction(SIGALRM, &action, NULL);
+#else
+ signal(SIGALRM, sigalrm_handler);
+#endif /* HAVE_SIGSET */
+
+ alarm(30);
+ count = 0;
+ compat = strcmp(dent->d_name, "smb") == 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Reset the alarm clock...
+ */
+
+ alarm(30);
+
+ /*
+ * Each line is of the form:
+ *
+ * class URI "make model" "name"
+ */
+
+ if (strncasecmp(line, "Usage", 5) == 0)
+ compat = 1;
+ else if (sscanf(line, "%63s%1023s%*[ \t]\"%127[^\"]\"%*[ \t]\"%255[^\"]",
+ dclass, uri, make_model, info) != 4)
+ {
+ /*
+ * Bad format; strip trailing newline and write an error message.
+ */
+
+ if (line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ LogMessage(L_ERROR, "LoadDevices: Bad line from \"%s\": %s",
+ dent->d_name, line);
+ compat = 1;
+ break;
+ }
+ else
+ {
+ /*
+ * Add the device to the array of available devices...
+ */
+
+ if (num_devs >= alloc_devs)
+ {
+ /*
+ * Allocate (more) memory for the devices...
+ */
+
+ if (alloc_devs == 0)
+ dev = malloc(sizeof(dev_info_t) * 16);
+ else
+ dev = realloc(devs, sizeof(dev_info_t) * (alloc_devs + 16));
+
+ if (dev == NULL)
+ {
+ LogMessage(L_ERROR, "LoadDevices: Ran out of memory for %d devices!",
+ alloc_devs + 16);
+ closedir(dir);
+ return;
+ }
+
+ devs = dev;
+ alloc_devs += 16;
+ }
+
+ dev = devs + num_devs;
+ num_devs ++;
+
+ memset(dev, 0, sizeof(dev_info_t));
+ strlcpy(dev->device_class, dclass, sizeof(dev->device_class));
+ strlcpy(dev->device_info, info, sizeof(dev->device_info));
+ strlcpy(dev->device_make_and_model, make_model,
+ sizeof(dev->device_make_and_model));
+ strlcpy(dev->device_uri, uri, sizeof(dev->device_uri));
+
+ LogMessage(L_DEBUG, "LoadDevices: Added device \"%s\"...", uri);
+ count ++;
+ }
+ }
+
+ /*
+ * Turn the alarm clock off and close the pipe to the command...
+ */
+
+ alarm(0);
+
+ pclose(fp);
+
+ /*
+ * Hack for backends that don't support the CUPS 1.1 calling convention:
+ * add a network device with the method == backend name.
+ */
+
+ if (count == 0 && compat)
+ {
+ if (num_devs >= alloc_devs)
+ {
+ /*
+ * Allocate (more) memory for the devices...
+ */
+
+ if (alloc_devs == 0)
+ dev = malloc(sizeof(dev_info_t) * 16);
+ else
+ dev = realloc(devs, sizeof(dev_info_t) * (alloc_devs + 16));
+
+ if (dev == NULL)
+ {
+ LogMessage(L_ERROR, "LoadDevices: Ran out of memory for %d devices!",
+ alloc_devs + 16);
+ closedir(dir);
+ return;
+ }
+
+ devs = dev;
+ alloc_devs += 16;
+ }
+
+ dev = devs + num_devs;
+ num_devs ++;
+
+ memset(dev, 0, sizeof(dev_info_t));
+ strcpy(dev->device_class, "network");
+ snprintf(dev->device_info, sizeof(dev->device_info),
+ "Unknown Network Device (%s)", dent->d_name);
+ strcpy(dev->device_make_and_model, "Unknown");
+ strlcpy(dev->device_uri, dent->d_name, sizeof(dev->device_uri));
+
+ LogMessage(L_DEBUG, "LoadDevices: Compatibility device \"%s\"...",
+ dent->d_name);
+ }
+ }
+ else
+ LogMessage(L_WARN, "LoadDevices: Unable to execute \"%s\" backend: %s",
+ dent->d_name, strerror(errno));
+ }
+
+ closedir(dir);
+
+ /*
+ * Catch child signals...
+ */
+
+ CatchChildSignals();
+
+ /*
+ * Sort the available devices...
+ */
+
+ if (num_devs > 1)
+ qsort(devs, num_devs, sizeof(dev_info_t),
+ (int (*)(const void *, const void *))compare_devs);
+
+ /*
+ * Create the list of devices...
+ */
+
+ for (i = num_devs, dev = devs; i > 0; i --, dev ++)
+ {
+ /*
+ * Add strings to attributes...
+ */
+
+ if (i < num_devs)
+ ippAddSeparator(Devices);
+
+ ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "device-class", NULL, dev->device_class);
+ ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "device-info", NULL, dev->device_info);
+ ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "device-make-and-model", NULL, dev->device_make_and_model);
+ ippAddString(Devices, IPP_TAG_PRINTER, IPP_TAG_URI,
+ "device-uri", NULL, dev->device_uri);
+ }
+
+ /*
+ * Free the devices array...
+ */
+
+ if (alloc_devs)
+ free(devs);
+}
+
+
+/*
+ * 'compare_devs()' - Compare device names for sorting.
+ */
+
+static int /* O - Result of comparison */
+compare_devs(const dev_info_t *d0, /* I - First device */
+ const dev_info_t *d1) /* I - Second device */
+{
+ const char *s, /* First name */
+ *t; /* Second name */
+ int diff, /* Difference between digits */
+ digits; /* Number of digits */
+
+
+ /*
+ * First compare names...
+ */
+
+ s = d0->device_info;
+ t = d1->device_info;
+
+ /*
+ * Loop through both nicknames, returning only when a difference is
+ * seen. Also, compare whole numbers rather than just characters, too!
+ */
+
+ while (*s && *t)
+ {
+ if (isdigit(*s & 255) && isdigit(*t & 255))
+ {
+ /*
+ * Got a number; start by skipping leading 0's...
+ */
+
+ while (*s == '0')
+ s ++;
+ while (*t == '0')
+ t ++;
+
+ /*
+ * Skip equal digits...
+ */
+
+ while (isdigit(*s & 255) && *s == *t)
+ {
+ s ++;
+ t ++;
+ }
+
+ /*
+ * Bounce out if *s and *t aren't both digits...
+ */
+
+ if (isdigit(*s & 255) && !isdigit(*t & 255))
+ return (1);
+ else if (!isdigit(*s & 255) && isdigit(*t & 255))
+ return (-1);
+ else if (!isdigit(*s & 255) || !isdigit(*t & 255))
+ continue;
+
+ if (*s < *t)
+ diff = -1;
+ else
+ diff = 1;
+
+ /*
+ * Figure out how many more digits there are...
+ */
+
+ digits = 0;
+ s ++;
+ t ++;
+
+ while (isdigit(*s & 255))
+ {
+ digits ++;
+ s ++;
+ }
+
+ while (isdigit(*t & 255))
+ {
+ digits --;
+ t ++;
+ }
+
+ /*
+ * Return if the number or value of the digits is different...
+ */
+
+ if (digits < 0)
+ return (-1);
+ else if (digits > 0)
+ return (1);
+ else if (diff)
+ return (diff);
+ }
+ else if (tolower(*s) < tolower(*t))
+ return (-1);
+ else if (tolower(*s) > tolower(*t))
+ return (1);
+ else
+ {
+ s ++;
+ t ++;
+ }
+ }
+
+ /*
+ * Return the results of the final comparison...
+ */
+
+ if (*s)
+ return (1);
+ else if (*t)
+ return (-1);
+ else if ((diff = strcasecmp(d0->device_class, d1->device_class)) != 0)
+ return (diff);
+ else
+ return (strcasecmp(d0->device_uri, d1->device_uri));
+}
+
+
+/*
+ * 'sigalrm_handler()' - Handle alarm signals for backends that get hung
+ * trying to list the available devices...
+ */
+
+static void
+sigalrm_handler(int sig) /* I - Signal number */
+{
+ (void)sig; /* remove compiler warnings... */
+
+ LogMessage(L_WARN, "LoadDevices: Backend did not respond within 30 seconds!");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
new file mode 100644
index 000000000..49f3b8f4f
--- /dev/null
+++ b/scheduler/dirsvc.c
@@ -0,0 +1,1974 @@
+/*
+ * "$Id$"
+ *
+ * Directory services routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * ProcessBrowseData() - Process new browse data.
+ * SendBrowseList() - Send new browsing information as necessary.
+ * SendCUPSBrowse() - Send new browsing information using the CUPS protocol.
+ * StartBrowsing() - Start sending and receiving broadcast information.
+ * StartPolling() - Start polling servers as needed.
+ * StopBrowsing() - Stop sending and receiving broadcast information.
+ * StopPolling() - Stop polling servers as needed.
+ * UpdateCUPSBrowse() - Update the browse lists using the CUPS protocol.
+ * UpdatePolling() - Read status messages from the poll daemons.
+ * RegReportCallback() - Empty SLPRegReport.
+ * SendSLPBrowse() - Register the specified printer with SLP.
+ * SLPDeregPrinter() - SLPDereg() the specified printer
+ * GetSlpAttrVal() - Get an attribute from an SLP registration.
+ * AttrCallback() - SLP attribute callback
+ * SrvUrlCallback() - SLP service url callback
+ * UpdateSLPBrowse() - Get browsing information via SLP.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <grp.h>
+
+
+/*
+ * 'ProcessBrowseData()' - Process new browse data.
+ */
+
+void
+ProcessBrowseData(const char *uri, /* I - URI of printer/class */
+ cups_ptype_t type, /* I - Printer type */
+ ipp_pstate_t state, /* I - Printer state */
+ const char *location,/* I - Printer location */
+ const char *info, /* I - Printer information */
+ const char *make_model) /* I - Printer make and model */
+{
+ int i; /* Looping var */
+ int update; /* Update printer attributes? */
+ char method[HTTP_MAX_URI], /* Method portion of URI */
+ username[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ char name[IPP_MAX_NAME], /* Name of printer */
+ *hptr, /* Pointer into hostname */
+ *sptr; /* Pointer into ServerName */
+ char local_make_model[IPP_MAX_NAME];
+ /* Local make and model */
+ printer_t *p, /* Printer information */
+ *pclass, /* Printer class */
+ *first, /* First printer in class */
+ *next; /* Next printer in list */
+ int offset, /* Offset of name */
+ len; /* Length of name */
+
+
+ /*
+ * Pull the URI apart to see if this is a local or remote printer...
+ */
+
+ httpSeparate(uri, method, username, host, &port, resource);
+
+ /*
+ * Determine if the URI contains any illegal characters in it...
+ */
+
+ if (strncmp(uri, "ipp://", 6) != 0 ||
+ !host[0] ||
+ (strncmp(resource, "/printers/", 10) != 0 &&
+ strncmp(resource, "/classes/", 9) != 0))
+ {
+ LogMessage(L_ERROR, "ProcessBrowseData: Bad printer URI in browse data: %s",
+ uri);
+ return;
+ }
+
+ if (strchr(resource, '?') != NULL ||
+ (strncmp(resource, "/printers/", 10) == 0 &&
+ strchr(resource + 10, '/') != NULL) ||
+ (strncmp(resource, "/classes/", 9) == 0 &&
+ strchr(resource + 9, '/') != NULL))
+ {
+ LogMessage(L_ERROR, "ProcessBrowseData: Bad resource in browse data: %s",
+ resource);
+ return;
+ }
+
+ /*
+ * OK, this isn't a local printer; see if we already have it listed in
+ * the Printers list, and add it if not...
+ */
+
+ type |= CUPS_PRINTER_REMOTE;
+ update = 0;
+ hptr = strchr(host, '.');
+ sptr = strchr(ServerName, '.');
+
+ if (sptr != NULL && hptr != NULL)
+ {
+ /*
+ * Strip the common domain name components...
+ */
+
+ while (hptr != NULL)
+ {
+ if (strcasecmp(hptr, sptr) == 0)
+ {
+ *hptr = '\0';
+ break;
+ }
+ else
+ hptr = strchr(hptr + 1, '.');
+ }
+ }
+
+ if (type & CUPS_PRINTER_CLASS)
+ {
+ /*
+ * Remote destination is a class...
+ */
+
+ if (strncmp(resource, "/classes/", 9) == 0)
+ snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
+ else
+ return;
+
+ if ((p = FindClass(name)) == NULL && BrowseShortNames)
+ {
+ if ((p = FindClass(resource + 9)) != NULL)
+ {
+ if (p->hostname && strcasecmp(p->hostname, host) != 0)
+ {
+ /*
+ * Nope, this isn't the same host; if the hostname isn't the local host,
+ * add it to the other class and then find a class using the full host
+ * name...
+ */
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ {
+ SetStringf(&p->name, "%s@%s", p->name, p->hostname);
+ SetPrinterAttrs(p);
+ SortPrinters();
+ }
+
+ p = NULL;
+ }
+ else if (!p->hostname)
+ {
+ SetString(&p->hostname, host);
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+ update = 1;
+ }
+ }
+ else
+ strlcpy(name, resource + 9, sizeof(name));
+ }
+ else if (p != NULL && !p->hostname)
+ {
+ SetString(&p->hostname, host);
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+ update = 1;
+ }
+
+ if (p == NULL)
+ {
+ /*
+ * Class doesn't exist; add it...
+ */
+
+ p = AddClass(name);
+
+ LogMessage(L_INFO, "Added remote class \"%s\"...", name);
+
+ /*
+ * Force the URI to point to the real server...
+ */
+
+ p->type = type & ~CUPS_PRINTER_REJECTING;
+ p->accepting = 1;
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+ SetString(&p->hostname, host);
+
+ update = 1;
+ }
+ }
+ else
+ {
+ /*
+ * Remote destination is a printer...
+ */
+
+ if (strncmp(resource, "/printers/", 10) == 0)
+ snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
+ else
+ return;
+
+ if ((p = FindPrinter(name)) == NULL && BrowseShortNames)
+ {
+ if ((p = FindPrinter(resource + 10)) != NULL)
+ {
+ if (p->hostname && strcasecmp(p->hostname, host) != 0)
+ {
+ /*
+ * Nope, this isn't the same host; if the hostname isn't the local host,
+ * add it to the other printer and then find a printer using the full host
+ * name...
+ */
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ {
+ SetStringf(&p->name, "%s@%s", p->name, p->hostname);
+ SetPrinterAttrs(p);
+ SortPrinters();
+ }
+
+ p = NULL;
+ }
+ else if (!p->hostname)
+ {
+ SetString(&p->hostname, host);
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+ update = 1;
+ }
+ }
+ else
+ strlcpy(name, resource + 10, sizeof(name));
+ }
+ else if (p != NULL && !p->hostname)
+ {
+ SetString(&p->hostname, host);
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+ update = 1;
+ }
+
+ if (p == NULL)
+ {
+ /*
+ * Printer doesn't exist; add it...
+ */
+
+ p = AddPrinter(name);
+
+ LogMessage(L_INFO, "Added remote printer \"%s\"...", name);
+
+ /*
+ * Force the URI to point to the real server...
+ */
+
+ p->type = type & ~CUPS_PRINTER_REJECTING;
+ p->accepting = 1;
+ SetString(&p->hostname, host);
+ SetString(&p->uri, uri);
+ SetString(&p->device_uri, uri);
+
+ update = 1;
+ }
+ }
+
+ /*
+ * Update the state...
+ */
+
+ p->state = state;
+ p->browse_time = time(NULL);
+
+ if (type & CUPS_PRINTER_REJECTING)
+ {
+ type &= ~CUPS_PRINTER_REJECTING;
+
+ if (p->accepting)
+ {
+ update = 1;
+ p->accepting = 0;
+ }
+ }
+ else if (!p->accepting)
+ {
+ update = 1;
+ p->accepting = 1;
+ }
+
+ if (p->type != type)
+ {
+ p->type = type;
+ update = 1;
+ }
+
+ if (location && (!p->location || strcmp(p->location, location)))
+ {
+ SetString(&p->location, location);
+ update = 1;
+ }
+
+ if (info && (!p->info || strcmp(p->info, info)))
+ {
+ SetString(&p->info, info);
+ update = 1;
+ }
+
+ if (!make_model || !make_model[0])
+ {
+ if (type & CUPS_PRINTER_CLASS)
+ snprintf(local_make_model, sizeof(local_make_model),
+ "Remote Class on %s", host);
+ else
+ snprintf(local_make_model, sizeof(local_make_model),
+ "Remote Printer on %s", host);
+ }
+ else
+ snprintf(local_make_model, sizeof(local_make_model),
+ "%s on %s", make_model, host);
+
+ if (!p->make_model || strcmp(p->make_model, local_make_model))
+ {
+ SetString(&p->make_model, local_make_model);
+ update = 1;
+ }
+
+ if (update)
+ {
+ SetPrinterAttrs(p);
+ UpdateImplicitClasses();
+ }
+
+ /*
+ * See if we have a default printer... If not, make the first printer the
+ * default.
+ */
+
+ if (DefaultPrinter == NULL && Printers != NULL)
+ {
+ DefaultPrinter = Printers;
+
+ WritePrintcap();
+ }
+
+ /*
+ * Do auto-classing if needed...
+ */
+
+ if (ImplicitClasses)
+ {
+ /*
+ * Loop through all available printers and create classes as needed...
+ */
+
+ for (p = Printers, len = 0, offset = 0, first = NULL;
+ p != NULL;
+ p = next)
+ {
+ /*
+ * Get next printer in list...
+ */
+
+ next = p->next;
+
+ /*
+ * Skip implicit classes...
+ */
+
+ if (p->type & CUPS_PRINTER_IMPLICIT)
+ {
+ len = 0;
+ continue;
+ }
+
+ /*
+ * If len == 0, get the length of this printer name up to the "@"
+ * sign (if any).
+ */
+
+ if (len > 0 &&
+ strncasecmp(p->name, name + offset, len) == 0 &&
+ (p->name[len] == '\0' || p->name[len] == '@'))
+ {
+ /*
+ * We have more than one printer with the same name; see if
+ * we have a class, and if this printer is a member...
+ */
+
+ if ((pclass = FindDest(name)) == NULL)
+ {
+ /*
+ * Need to add the class...
+ */
+
+ pclass = AddPrinter(name);
+ pclass->type |= CUPS_PRINTER_IMPLICIT;
+ pclass->accepting = 1;
+ pclass->state = IPP_PRINTER_IDLE;
+
+ SetString(&pclass->location, p->location);
+ SetString(&pclass->info, p->info);
+
+ SetPrinterAttrs(pclass);
+
+ LogMessage(L_INFO, "Added implicit class \"%s\"...", name);
+ }
+
+ if (first != NULL)
+ {
+ for (i = 0; i < pclass->num_printers; i ++)
+ if (pclass->printers[i] == first)
+ break;
+
+ if (i >= pclass->num_printers)
+ AddPrinterToClass(pclass, first);
+
+ first = NULL;
+ }
+
+ for (i = 0; i < pclass->num_printers; i ++)
+ if (pclass->printers[i] == p)
+ break;
+
+ if (i >= pclass->num_printers)
+ AddPrinterToClass(pclass, p);
+ }
+ else
+ {
+ /*
+ * First time around; just get name length and mark it as first
+ * in the list...
+ */
+
+ if ((hptr = strchr(p->name, '@')) != NULL)
+ len = hptr - p->name;
+ else
+ len = strlen(p->name);
+
+ strncpy(name, p->name, len);
+ name[len] = '\0';
+ offset = 0;
+
+ if ((pclass = FindDest(name)) != NULL &&
+ !(pclass->type & CUPS_PRINTER_IMPLICIT))
+ {
+ /*
+ * Can't use same name as a local printer; add "Any" to the
+ * front of the name, unless we have explicitly disabled
+ * the "ImplicitAnyClasses"...
+ */
+
+ if (ImplicitAnyClasses && len < (sizeof(name) - 4))
+ {
+ /*
+ * Add "Any" to the class name...
+ */
+
+ strcpy(name, "Any");
+ strncpy(name + 3, p->name, len);
+ name[len + 3] = '\0';
+ offset = 3;
+ }
+ else
+ {
+ /*
+ * Don't create an implicit class if we have a local printer
+ * with the same name...
+ */
+
+ len = 0;
+ continue;
+ }
+ }
+
+ first = p;
+ }
+ }
+ }
+}
+
+
+/*
+ * 'SendBrowseList()' - Send new browsing information as necessary.
+ */
+
+void
+SendBrowseList(void)
+{
+ int count; /* Number of dests to update */
+ printer_t *p, /* Current printer */
+ *np; /* Next printer */
+ time_t ut, /* Minimum update time */
+ to; /* Timeout time */
+
+
+ if (!Browsing || !BrowseProtocols)
+ return;
+
+ /*
+ * Compute the update and timeout times...
+ */
+
+ ut = time(NULL) - BrowseInterval;
+ to = time(NULL) - BrowseTimeout;
+
+ /*
+ * Figure out how many printers need an update...
+ */
+
+ if (BrowseInterval > 0)
+ {
+ int max_count; /* Maximum number to update */
+
+
+ /*
+ * Throttle the number of printers we'll be updating this time
+ * around based on the number of queues that need updating and
+ * the maximum number of queues to update each second...
+ */
+
+ max_count = 2 * NumPrinters / BrowseInterval + 1;
+
+ for (count = 0, p = Printers; count < max_count && p != NULL; p = p->next)
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+ p->browse_time < ut)
+ count ++;
+
+ /*
+ * Loop through all of the printers and send local updates as needed...
+ */
+
+ for (p = BrowseNext; count > 0; p = p->next)
+ {
+ /*
+ * Check for wraparound...
+ */
+
+ if (!p)
+ p = Printers;
+
+ if (!p)
+ break;
+ else if (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+ continue;
+ else if (p->browse_time < ut)
+ {
+ /*
+ * Need to send an update...
+ */
+
+ count --;
+
+ p->browse_time = time(NULL);
+
+ if (BrowseProtocols & BROWSE_CUPS)
+ SendCUPSBrowse(p);
+
+#ifdef HAVE_LIBSLP
+ if (BrowseProtocols & BROWSE_SLP)
+ SendSLPBrowse(p);
+#endif /* HAVE_LIBSLP */
+ }
+ }
+
+ /*
+ * Save where we left off so that all printers get updated...
+ */
+
+ BrowseNext = p;
+ }
+
+ /*
+ * Loop through all of the printers and send local updates as needed...
+ */
+
+ for (p = Printers; p != NULL; p = np)
+ {
+ /*
+ * Save the next printer pointer...
+ */
+
+ np = p->next;
+
+ /*
+ * If this is a remote queue, see if it needs to be timed out...
+ */
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ {
+ if (p->browse_time < to)
+ {
+ LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...",
+ p->name);
+ DeletePrinter(p, 1);
+ }
+ }
+ }
+}
+
+
+/*
+ * 'SendCUPSBrowse()' - Send new browsing information using the CUPS protocol.
+ */
+
+void
+SendCUPSBrowse(printer_t *p) /* I - Printer to send */
+{
+ int i; /* Looping var */
+ cups_ptype_t type; /* Printer type */
+ dirsvc_addr_t *b; /* Browse address */
+ int bytes; /* Length of packet */
+ char packet[1453]; /* Browse data packet */
+ cups_netif_t *iface; /* Network interface */
+
+
+ /*
+ * Figure out the printer type value...
+ */
+
+ type = p->type | CUPS_PRINTER_REMOTE;
+
+ if (!p->accepting)
+ type |= CUPS_PRINTER_REJECTING;
+
+ /*
+ * Send a packet to each browse address...
+ */
+
+ for (i = NumBrowsers, b = Browsers; i > 0; i --, b ++)
+ if (b->iface[0])
+ {
+ /*
+ * Send the browse packet to one or more interfaces...
+ */
+
+ if (strcmp(b->iface, "*") == 0)
+ {
+ /*
+ * Send to all local interfaces...
+ */
+
+ NetIFUpdate();
+
+ for (iface = NetIFList; iface != NULL; iface = iface->next)
+ {
+ /*
+ * Only send to local interfaces...
+ */
+
+ if (!iface->is_local || !iface->port)
+ continue;
+
+ snprintf(packet, sizeof(packet), "%x %x ipp://%s:%d/%s/%s \"%s\" \"%s\" \"%s\"\n",
+ type, p->state, iface->hostname, iface->port,
+ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
+ p->name, p->location ? p->location : "",
+ p->info ? p->info : "",
+ p->make_model ? p->make_model : "Unknown");
+
+ bytes = strlen(packet);
+
+ LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes to \"%s\") %s", bytes,
+ iface->name, packet);
+
+ iface->broadcast.sin_port = htons(BrowsePort);
+
+ sendto(BrowseSocket, packet, bytes, 0,
+ (struct sockaddr *)&(iface->broadcast),
+ sizeof(struct sockaddr_in));
+ }
+ }
+ else if ((iface = NetIFFind(b->iface)) != NULL)
+ {
+ /*
+ * Send to the named interface...
+ */
+
+ if (!iface->port)
+ continue;
+
+ snprintf(packet, sizeof(packet), "%x %x ipp://%s:%d/%s/%s \"%s\" \"%s\" \"%s\"\n",
+ type, p->state, iface->hostname, iface->port,
+ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
+ p->name, p->location ? p->location : "",
+ p->info ? p->info : "",
+ p->make_model ? p->make_model : "Unknown");
+
+ bytes = strlen(packet);
+
+ LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes to \"%s\") %s", bytes,
+ iface->name, packet);
+
+ iface->broadcast.sin_port = htons(BrowsePort);
+
+ sendto(BrowseSocket, packet, bytes, 0,
+ (struct sockaddr *)&(iface->broadcast),
+ sizeof(struct sockaddr_in));
+ }
+ }
+ else
+ {
+ /*
+ * Send the browse packet to the indicated address using
+ * the default server name...
+ */
+
+ snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
+ type, p->state, p->uri,
+ p->location ? p->location : "",
+ p->info ? p->info : "",
+ p->make_model ? p->make_model : "Unknown");
+
+ bytes = strlen(packet);
+ LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes to %x) %s", bytes,
+ (unsigned)ntohl(b->to.sin_addr.s_addr), packet);
+
+ if (sendto(BrowseSocket, packet, bytes, 0,
+ (struct sockaddr *)&(b->to), sizeof(struct sockaddr_in)) <= 0)
+ {
+ /*
+ * Unable to send browse packet, so remove this address from the
+ * list...
+ */
+
+ LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
+ b - Browsers + 1, strerror(errno));
+
+ if (i > 1)
+ memcpy(b, b + 1, (i - 1) * sizeof(dirsvc_addr_t));
+
+ b --;
+ NumBrowsers --;
+ }
+ }
+}
+
+
+/*
+ * 'StartBrowsing()' - Start sending and receiving broadcast information.
+ */
+
+void
+StartBrowsing(void)
+{
+ int val; /* Socket option value */
+ struct sockaddr_in addr; /* Broadcast address */
+
+
+ if (!Browsing || !BrowseProtocols)
+ return;
+
+ if (BrowseProtocols & BROWSE_CUPS)
+ {
+ /*
+ * Create the broadcast socket...
+ */
+
+ if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
+ strerror(errno));
+ BrowseProtocols &= ~BROWSE_CUPS;
+ return;
+ }
+
+ /*
+ * Set the "broadcast" flag...
+ */
+
+ val = 1;
+ if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+ {
+ LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
+ strerror(errno));
+
+#ifdef WIN32
+ closesocket(BrowseSocket);
+#else
+ close(BrowseSocket);
+#endif /* WIN32 */
+
+ BrowseSocket = -1;
+ BrowseProtocols &= ~BROWSE_CUPS;
+ return;
+ }
+
+ /*
+ * Bind the socket to browse port...
+ */
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(BrowsePort);
+
+ if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
+ {
+ LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
+ strerror(errno));
+
+#ifdef WIN32
+ closesocket(BrowseSocket);
+#else
+ close(BrowseSocket);
+#endif /* WIN32 */
+
+ BrowseSocket = -1;
+ BrowseProtocols &= ~BROWSE_CUPS;
+ return;
+ }
+
+ /*
+ * Close the socket on exec...
+ */
+
+ fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC);
+
+ /*
+ * Finally, add the socket to the input selection set...
+ */
+
+ LogMessage(L_DEBUG2, "StartBrowsing: Adding fd %d to InputSet...",
+ BrowseSocket);
+
+ FD_SET(BrowseSocket, InputSet);
+ }
+ else
+ BrowseSocket = -1;
+
+#ifdef HAVE_LIBSLP
+ if (BrowseProtocols & BROWSE_SLP)
+ {
+ /*
+ * Open SLP handle...
+ */
+
+ if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK)
+ {
+ LogMessage(L_ERROR, "Unable to open an SLP handle; disabling SLP browsing!");
+ BrowseProtocols &= ~BROWSE_SLP;
+ }
+
+ BrowseSLPRefresh = 0;
+ }
+#endif /* HAVE_LIBSLP */
+}
+
+
+/*
+ * 'StartPolling()' - Start polling servers as needed.
+ */
+
+void
+StartPolling(void)
+{
+ int i; /* Looping var */
+ dirsvc_poll_t *poll; /* Current polling server */
+ int pid; /* New process ID */
+ char sport[10]; /* Server port */
+ char bport[10]; /* Browser port */
+ char interval[10]; /* Poll interval */
+ int statusfds[2]; /* Status pipe */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* POSIX signal handler */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ /*
+ * Don't do anything if we aren't polling...
+ */
+
+ if (NumPolled == 0)
+ {
+ PollPipe = -1;
+ return;
+ }
+
+ /*
+ * Setup string arguments for port and interval options.
+ */
+
+ sprintf(bport, "%d", BrowsePort);
+
+ if (BrowseInterval)
+ sprintf(interval, "%d", BrowseInterval);
+ else
+ strcpy(interval, "30");
+
+ /*
+ * Create a pipe that receives the status messages from each
+ * polling daemon...
+ */
+
+ if (cupsdOpenPipe(statusfds))
+ {
+ LogMessage(L_ERROR, "Unable to create polling status pipes - %s.",
+ strerror(errno));
+ PollPipe = -1;
+ return;
+ }
+
+ PollPipe = statusfds[0];
+
+ /*
+ * Run each polling daemon, redirecting stderr to the polling pipe...
+ */
+
+ for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
+ {
+ sprintf(sport, "%d", poll->port);
+
+ /*
+ * Block signals before forking...
+ */
+
+ HoldSignals();
+
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child...
+ */
+
+ if (getuid() == 0)
+ {
+ /*
+ * Running as root, so change to non-priviledged user...
+ */
+
+ if (setgid(Group))
+ exit(errno);
+
+ if (setgroups(1, &Group))
+ exit(errno);
+
+ if (setuid(User))
+ exit(errno);
+ }
+ else
+ {
+ /*
+ * Reset group membership to just the main one we belong to.
+ */
+
+ setgroups(1, &Group);
+ }
+
+ /*
+ * Redirect stdin and stdout to /dev/null, and stderr to the
+ * status pipe. Close all other files.
+ */
+
+ close(0);
+ open("/dev/null", O_RDONLY);
+
+ close(1);
+ open("/dev/null", O_WRONLY);
+
+ close(2);
+ dup(statusfds[1]);
+
+ /*
+ * Unblock signals before doing the exec...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_DFL);
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+#endif /* HAVE_SIGSET */
+
+ ReleaseSignals();
+
+ /*
+ * Execute the polling daemon...
+ */
+
+ execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname,
+ sport, interval, bport, NULL);
+ exit(errno);
+ }
+ else if (pid < 0)
+ {
+ LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s",
+ strerror(errno));
+ poll->pid = 0;
+ break;
+ }
+ else
+ {
+ poll->pid = pid;
+ LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d",
+ poll->hostname, poll->port, pid);
+ }
+
+ ReleaseSignals();
+ }
+
+ close(statusfds[1]);
+
+ /*
+ * Finally, add the pipe to the input selection set...
+ */
+
+ LogMessage(L_DEBUG2, "StartPolling: Adding fd %d to InputSet...",
+ PollPipe);
+
+ FD_SET(PollPipe, InputSet);
+}
+
+
+/*
+ * 'StopBrowsing()' - Stop sending and receiving broadcast information.
+ */
+
+void
+StopBrowsing(void)
+{
+ if (!Browsing || !BrowseProtocols)
+ return;
+
+ if (BrowseProtocols & BROWSE_CUPS)
+ {
+ /*
+ * Close the socket and remove it from the input selection set.
+ */
+
+ if (BrowseSocket >= 0)
+ {
+#ifdef WIN32
+ closesocket(BrowseSocket);
+#else
+ close(BrowseSocket);
+#endif /* WIN32 */
+
+ LogMessage(L_DEBUG2, "StopBrowsing: Removing fd %d from InputSet...",
+ BrowseSocket);
+
+ FD_CLR(BrowseSocket, InputSet);
+ BrowseSocket = -1;
+ }
+ }
+
+#ifdef HAVE_LIBSLP
+ if (BrowseProtocols & BROWSE_SLP)
+ {
+ /*
+ * Close SLP handle...
+ */
+
+ SLPClose(BrowseSLPHandle);
+ }
+#endif /* HAVE_LIBSLP */
+}
+
+
+/*
+ * 'StopPolling()' - Stop polling servers as needed.
+ */
+
+void
+StopPolling(void)
+{
+ int i; /* Looping var */
+ dirsvc_poll_t *poll; /* Current polling server */
+
+
+ if (PollPipe >= 0)
+ {
+ close(PollPipe);
+
+ LogMessage(L_DEBUG2, "StopPolling: removing fd %d from InputSet.",
+ PollPipe);
+ FD_CLR(PollPipe, InputSet);
+
+ PollPipe = -1;
+ }
+
+ for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
+ if (poll->pid)
+ kill(poll->pid, SIGTERM);
+}
+
+
+/*
+ * 'UpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol.
+ */
+
+void
+UpdateCUPSBrowse(void)
+{
+ int i; /* Looping var */
+ int auth; /* Authorization status */
+ int len; /* Length of name string */
+ int bytes; /* Number of bytes left */
+ char packet[1541], /* Broadcast packet */
+ *pptr; /* Pointer into packet */
+ struct sockaddr_in srcaddr; /* Source address */
+ char srcname[1024]; /* Source hostname */
+ unsigned address; /* Source address (host order) */
+ struct hostent *srchost; /* Host entry for source address */
+ unsigned type; /* Printer type */
+ unsigned state; /* Printer state */
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ method[HTTP_MAX_URI], /* Method portion of URI */
+ username[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI], /* Resource portion of URI */
+ info[IPP_MAX_NAME], /* Information string */
+ location[IPP_MAX_NAME], /* Location string */
+ make_model[IPP_MAX_NAME];/* Make and model string */
+ int port; /* Port portion of URI */
+ cups_netif_t *iface; /* Network interface */
+
+
+ /*
+ * Read a packet from the browse socket...
+ */
+
+ len = sizeof(srcaddr);
+ if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0,
+ (struct sockaddr *)&srcaddr, &len)) < 0)
+ {
+ /*
+ * "Connection refused" is returned under Linux if the destination port
+ * or address is unreachable from a previous sendto(); check for the
+ * error here and ignore it for now...
+ */
+
+ if (errno != ECONNREFUSED && errno != EAGAIN)
+ {
+ LogMessage(L_ERROR, "Browse recv failed - %s.", strerror(errno));
+ LogMessage(L_ERROR, "Browsing turned off.");
+
+ StopBrowsing();
+ Browsing = 0;
+ }
+
+ return;
+ }
+
+ packet[bytes] = '\0';
+
+ /*
+ * Figure out where it came from...
+ */
+
+ address = ntohl(srcaddr.sin_addr.s_addr);
+
+ if (HostNameLookups)
+#ifndef __sgi
+ srchost = gethostbyaddr((char *)&(srcaddr.sin_addr), sizeof(struct in_addr),
+ AF_INET);
+#else
+ srchost = gethostbyaddr(&(srcaddr.sin_addr), sizeof(struct in_addr),
+ AF_INET);
+#endif /* !__sgi */
+ else
+ srchost = NULL;
+
+ if (srchost == NULL)
+ sprintf(srcname, "%d.%d.%d.%d", address >> 24, (address >> 16) & 255,
+ (address >> 8) & 255, address & 255);
+ else
+ strlcpy(srcname, srchost->h_name, sizeof(srcname));
+
+ len = strlen(srcname);
+
+ /*
+ * Do ACL stuff...
+ */
+
+ if (BrowseACL && (BrowseACL->num_allow || BrowseACL->num_deny))
+ {
+ if (address == 0x7f000001 || strcasecmp(srcname, "localhost") == 0)
+ {
+ /*
+ * Access from localhost (127.0.0.1) is always allowed...
+ */
+
+ auth = AUTH_ALLOW;
+ }
+ else
+ {
+ /*
+ * Do authorization checks on the domain/address...
+ */
+
+ switch (BrowseACL->order_type)
+ {
+ default :
+ auth = AUTH_DENY; /* anti-compiler-warning-code */
+ break;
+
+ case AUTH_ALLOW : /* Order Deny,Allow */
+ auth = AUTH_ALLOW;
+
+ if (CheckAuth(address, srcname, len,
+ BrowseACL->num_deny, BrowseACL->deny))
+ auth = AUTH_DENY;
+
+ if (CheckAuth(address, srcname, len,
+ BrowseACL->num_allow, BrowseACL->allow))
+ auth = AUTH_ALLOW;
+ break;
+
+ case AUTH_DENY : /* Order Allow,Deny */
+ auth = AUTH_DENY;
+
+ if (CheckAuth(address, srcname, len,
+ BrowseACL->num_allow, BrowseACL->allow))
+ auth = AUTH_ALLOW;
+
+ if (CheckAuth(address, srcname, len,
+ BrowseACL->num_deny, BrowseACL->deny))
+ auth = AUTH_DENY;
+ break;
+ }
+ }
+ }
+ else
+ auth = AUTH_ALLOW;
+
+ if (auth == AUTH_DENY)
+ {
+ LogMessage(L_DEBUG, "UpdateCUPSBrowse: Refused %d bytes from %s", bytes,
+ srcname);
+ return;
+ }
+
+ LogMessage(L_DEBUG2, "UpdateCUPSBrowse: (%d bytes from %s) %s", bytes, srcname,
+ packet);
+
+ /*
+ * Parse packet...
+ */
+
+ if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3)
+ {
+ LogMessage(L_WARN, "UpdateCUPSBrowse: Garbled browse packet - %s",
+ packet);
+ return;
+ }
+
+ strcpy(location, "Location Unknown");
+ strcpy(info, "No Information Available");
+ make_model[0] = '\0';
+
+ if ((pptr = strchr(packet, '\"')) != NULL)
+ {
+ /*
+ * Have extended information; can't use sscanf for it because not all
+ * sscanf's allow empty strings with %[^\"]...
+ */
+
+ for (i = 0, pptr ++;
+ i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ location[i] = *pptr;
+
+ if (i)
+ location[i] = '\0';
+
+ if (*pptr == '\"')
+ pptr ++;
+
+ while (*pptr && isspace(*pptr & 255))
+ pptr ++;
+
+ if (*pptr == '\"')
+ {
+ for (i = 0, pptr ++;
+ i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ info[i] = *pptr;
+
+ if (i)
+ info[i] = '\0';
+
+ if (*pptr == '\"')
+ pptr ++;
+
+ while (*pptr && isspace(*pptr & 255))
+ pptr ++;
+
+ if (*pptr == '\"')
+ {
+ for (i = 0, pptr ++;
+ i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
+ i ++, pptr ++)
+ make_model[i] = *pptr;
+
+ if (i)
+ make_model[i] = '\0';
+ }
+ }
+ }
+
+ DEBUG_puts(packet);
+ DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
+ "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
+ type, state, uri, location, info, make_model));
+
+ /*
+ * Pull the URI apart to see if this is a local or remote printer...
+ */
+
+ httpSeparate(uri, method, username, host, &port, resource);
+
+ DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
+
+ /*
+ * Check for packets from the local server...
+ */
+
+ if (strcasecmp(host, ServerName) == 0)
+ return;
+
+ NetIFUpdate();
+
+ for (iface = NetIFList; iface != NULL; iface = iface->next)
+ if (strcasecmp(host, iface->hostname) == 0)
+ return;
+
+ /*
+ * Do relaying...
+ */
+
+ for (i = 0; i < NumRelays; i ++)
+ if (CheckAuth(address, srcname, len, 1, &(Relays[i].from)))
+ if (sendto(BrowseSocket, packet, bytes, 0,
+ (struct sockaddr *)&(Relays[i].to),
+ sizeof(struct sockaddr_in)) <= 0)
+ {
+ LogMessage(L_ERROR, "UpdateCUPSBrowse: sendto failed for relay %d - %s.",
+ i + 1, strerror(errno));
+ return;
+ }
+
+ /*
+ * Process the browse data...
+ */
+
+ ProcessBrowseData(uri, (cups_ptype_t)type, (ipp_pstate_t)state, location,
+ info, make_model);
+}
+
+
+/*
+ * 'UpdatePolling()' - Read status messages from the poll daemons.
+ */
+
+void
+UpdatePolling(void)
+{
+ int bytes; /* Number of bytes read */
+ char *lineptr; /* Pointer to end of line in buffer */
+ static int bufused = 0; /* Number of bytes used in buffer */
+ static char buffer[1024]; /* Status buffer */
+
+
+ if ((bytes = read(PollPipe, buffer + bufused,
+ sizeof(buffer) - bufused - 1)) > 0)
+ {
+ bufused += bytes;
+ buffer[bufused] = '\0';
+ lineptr = strchr(buffer, '\n');
+ }
+ else if (bytes < 0 && errno == EINTR)
+ return;
+ else
+ {
+ lineptr = buffer + bufused;
+ lineptr[1] = 0;
+ }
+
+ if (bytes == 0 && bufused == 0)
+ lineptr = NULL;
+
+ while (lineptr != NULL)
+ {
+ /*
+ * Terminate each line and process it...
+ */
+
+ *lineptr++ = '\0';
+
+ if (!strncmp(buffer, "ERROR: ", 7))
+ LogMessage(L_ERROR, "%s", buffer + 7);
+ else if (!strncmp(buffer, "DEBUG: ", 7))
+ LogMessage(L_DEBUG, "%s", buffer + 7);
+ else if (!strncmp(buffer, "DEBUG2: ", 8))
+ LogMessage(L_DEBUG2, "%s", buffer + 8);
+ else
+ LogMessage(L_DEBUG, "%s", buffer);
+
+ /*
+ * Copy over the buffer data we've used up...
+ */
+
+ cups_strcpy(buffer, lineptr);
+ bufused -= lineptr - buffer;
+
+ if (bufused < 0)
+ bufused = 0;
+
+ lineptr = strchr(buffer, '\n');
+ }
+
+ if (bytes <= 0)
+ {
+ /*
+ * All polling processes have died; stop polling...
+ */
+
+ LogMessage(L_ERROR, "UpdatePolling: all polling processes have exited!");
+ StopPolling();
+ }
+}
+
+
+/***********************************************************************
+ **** SLP Support Code *************************************************
+ ***********************************************************************/
+
+#ifdef HAVE_LIBSLP
+/*
+ * SLP service name for CUPS...
+ */
+
+# define SLP_CUPS_SRVTYPE "service:printer"
+# define SLP_CUPS_SRVLEN 15
+
+
+/*
+ * Printer service URL structure
+ */
+
+typedef struct _slpsrvurl
+{
+ struct _slpsrvurl *next;
+ char url[HTTP_MAX_URI];
+} slpsrvurl_t;
+
+
+/*
+ * 'RegReportCallback()' - Empty SLPRegReport.
+ */
+
+void
+RegReportCallback(SLPHandle hslp,
+ SLPError errcode,
+ void *cookie)
+{
+ (void)hslp;
+ (void)errcode;
+ (void)cookie;
+
+ return;
+}
+
+
+/*
+ * 'SendSLPBrowse()' - Register the specified printer with SLP.
+ */
+
+void
+SendSLPBrowse(printer_t *p) /* I - Printer to register */
+{
+ char srvurl[HTTP_MAX_URI], /* Printer service URI */
+ attrs[8192], /* Printer attributes */
+ finishings[1024], /* Finishings to support */
+ make_model[IPP_MAX_NAME * 2],
+ /* Make and model, quoted */
+ location[IPP_MAX_NAME * 2],
+ /* Location, quoted */
+ info[IPP_MAX_NAME * 2],
+ /* Info, quoted */
+ *src, /* Pointer to original string */
+ *dst; /* Pointer to destination string */
+ ipp_attribute_t *authentication; /* uri-authentication-supported value */
+ SLPError error; /* SLP error, if any */
+
+
+ LogMessage(L_DEBUG, "SendSLPBrowse(%p = \"%s\")", p, p->name);
+
+ /*
+ * Make the SLP service URL that conforms to the IANA
+ * 'printer:' template.
+ */
+
+ snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
+
+ LogMessage(L_DEBUG2, "Service URL = \"%s\"", srvurl);
+
+ /*
+ * Figure out the finishings string...
+ */
+
+ if (p->type & CUPS_PRINTER_STAPLE)
+ strcpy(finishings, "staple");
+ else
+ finishings[0] = '\0';
+
+ if (p->type & CUPS_PRINTER_BIND)
+ {
+ if (finishings[0])
+ strlcat(finishings, ",bind", sizeof(finishings));
+ else
+ strcpy(finishings, "bind");
+ }
+
+ if (p->type & CUPS_PRINTER_PUNCH)
+ {
+ if (finishings[0])
+ strlcat(finishings, ",punch", sizeof(finishings));
+ else
+ strcpy(finishings, "punch");
+ }
+
+ if (p->type & CUPS_PRINTER_COVER)
+ {
+ if (finishings[0])
+ strlcat(finishings, ",cover", sizeof(finishings));
+ else
+ strcpy(finishings, "cover");
+ }
+
+ if (p->type & CUPS_PRINTER_SORT)
+ {
+ if (finishings[0])
+ strlcat(finishings, ",sort", sizeof(finishings));
+ else
+ strcpy(finishings, "sort");
+ }
+
+ if (!finishings[0])
+ strcpy(finishings, "none");
+
+ /*
+ * Quote any commas in the make and model, location, and info strings...
+ */
+
+ for (src = p->make_model, dst = make_model;
+ src && *src && dst < (make_model + sizeof(make_model) - 2);)
+ {
+ if (*src == ',' || *src == '\\' || *src == ')')
+ *dst++ = '\\';
+
+ *dst++ = *src++;
+ }
+
+ *dst = '\0';
+
+ if (!make_model[0])
+ strcpy(make_model, "Unknown");
+
+ for (src = p->location, dst = location;
+ src && *src && dst < (location + sizeof(location) - 2);)
+ {
+ if (*src == ',' || *src == '\\' || *src == ')')
+ *dst++ = '\\';
+
+ *dst++ = *src++;
+ }
+
+ *dst = '\0';
+
+ if (!location[0])
+ strcpy(location, "Unknown");
+
+ for (src = p->info, dst = info;
+ src && *src && dst < (info + sizeof(info) - 2);)
+ {
+ if (*src == ',' || *src == '\\' || *src == ')')
+ *dst++ = '\\';
+
+ *dst++ = *src++;
+ }
+
+ *dst = '\0';
+
+ if (!info[0])
+ strcpy(info, "Unknown");
+
+ /*
+ * Get the authentication value...
+ */
+
+ authentication = ippFindAttribute(p->attrs, "uri-authentication-supported",
+ IPP_TAG_KEYWORD);
+
+ /*
+ * Make the SLP attribute string list that conforms to
+ * the IANA 'printer:' template.
+ */
+
+ snprintf(attrs, sizeof(attrs),
+ "(printer-uri-supported=%s),"
+ "(uri-authentication-supported=%s>),"
+#ifdef HAVE_SSL
+ "(uri-security-supported=tls>),"
+#else
+ "(uri-security-supported=none>),"
+#endif /* HAVE_SSL */
+ "(printer-name=%s),"
+ "(printer-location=%s),"
+ "(printer-info=%s),"
+ "(printer-more-info=%s),"
+ "(printer-make-and-model=%s),"
+ "(charset-supported=utf-8),"
+ "(natural-language-configured=%s),"
+ "(natural-language-supported=de,en,es,fr,it),"
+ "(color-supported=%s),"
+ "(finishings-supported=%s),"
+ "(sides-supported=one-sided%s),"
+ "(multiple-document-jobs-supported=true)"
+ "(ipp-versions-supported=1.0,1.1)",
+ p->uri, authentication->values[0].string.text, p->name, location,
+ info, p->uri, make_model, DefaultLanguage,
+ p->type & CUPS_PRINTER_COLOR ? "true" : "false",
+ finishings,
+ p->type & CUPS_PRINTER_DUPLEX ?
+ ",two-sided-long-edge,two-sided-short-edge" : "");
+
+ LogMessage(L_DEBUG2, "Attributes = \"%s\"", attrs);
+
+ /*
+ * Register the printer with the SLP server...
+ */
+
+ error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout,
+ SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, RegReportCallback, 0);
+
+ if (error != SLP_OK)
+ LogMessage(L_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name,
+ error);
+}
+
+
+/*
+ * 'SLPDeregPrinter()' - SLPDereg() the specified printer
+ */
+
+void
+SLPDeregPrinter(printer_t *p)
+{
+ char srvurl[HTTP_MAX_URI]; /* Printer service URI */
+
+
+ if((p->type & CUPS_PRINTER_REMOTE) == 0)
+ {
+ /*
+ * Make the SLP service URL that conforms to the IANA
+ * 'printer:' template.
+ */
+
+ snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
+
+ /*
+ * Deregister the printer...
+ */
+
+ SLPDereg(BrowseSLPHandle, srvurl, RegReportCallback, 0);
+ }
+}
+
+
+/*
+ * 'GetSlpAttrVal()' - Get an attribute from an SLP registration.
+ */
+
+int /* O - 0 on success */
+GetSlpAttrVal(const char *attrlist, /* I - Attribute list string */
+ const char *tag, /* I - Name of attribute */
+ char **valbuf) /* O - Value */
+{
+ char *ptr1, /* Pointer into string */
+ *ptr2; /* ... */
+
+
+ ClearString(valbuf);
+
+ if ((ptr1 = strstr(attrlist, tag)) != NULL)
+ {
+ ptr1 += strlen(tag);
+
+ if ((ptr2 = strchr(ptr1,')')) != NULL)
+ {
+ /*
+ * Copy the value...
+ */
+
+ *valbuf = calloc(ptr2 - ptr1 + 1, 1);
+ strncpy(*valbuf, ptr1, ptr2 - ptr1);
+
+ /*
+ * Dequote the value...
+ */
+
+ for (ptr1 = *valbuf; *ptr1; ptr1 ++)
+ if (*ptr1 == '\\' && ptr1[1])
+ cups_strcpy(ptr1, ptr1 + 1);
+
+ return (0);
+ }
+ }
+
+ return (-1);
+}
+
+
+/*
+ * 'AttrCallback()' - SLP attribute callback
+ */
+
+SLPBoolean /* O - SLP_TRUE for success */
+AttrCallback(SLPHandle hslp, /* I - SLP handle */
+ const char *attrlist, /* I - Attribute list */
+ SLPError errcode, /* I - Parsing status for this attr */
+ void *cookie) /* I - Current printer */
+{
+ char *tmp = 0;
+ printer_t *p = (printer_t*)cookie;
+
+
+ /*
+ * Let the compiler know we won't be using these...
+ */
+
+ (void)hslp;
+
+ /*
+ * Bail if there was an error
+ */
+
+ if (errcode != SLP_OK)
+ return (SLP_TRUE);
+
+ /*
+ * Parse the attrlist to obtain things needed to build CUPS browse packet
+ */
+
+ memset(p, 0, sizeof(printer_t));
+
+ p->type = CUPS_PRINTER_REMOTE;
+
+ if (GetSlpAttrVal(attrlist, "(printer-location=", &(p->location)))
+ return (SLP_FALSE);
+ if (GetSlpAttrVal(attrlist, "(printer-info=", &(p->info)))
+ return (SLP_FALSE);
+ if (GetSlpAttrVal(attrlist, "(printer-make-and-model=", &(p->make_model)))
+ return (SLP_FALSE);
+
+ if (GetSlpAttrVal(attrlist, "(color-supported=", &tmp))
+ return (SLP_FALSE);
+ if (strcasecmp(tmp, "true") == 0)
+ p->type |= CUPS_PRINTER_COLOR;
+
+ if (GetSlpAttrVal(attrlist, "(finishings-supported=", &tmp))
+ return (SLP_FALSE);
+ if (strstr(tmp, "staple"))
+ p->type |= CUPS_PRINTER_STAPLE;
+ if (strstr(tmp, "bind"))
+ p->type |= CUPS_PRINTER_BIND;
+ if (strstr(tmp, "punch"))
+ p->type |= CUPS_PRINTER_PUNCH;
+
+ if (GetSlpAttrVal(attrlist, "(sides-supported=", &tmp))
+ return (SLP_FALSE);
+ if (strstr(tmp,"two-sided"))
+ p->type |= CUPS_PRINTER_DUPLEX;
+
+ ClearString(&tmp);
+
+ return (SLP_TRUE);
+}
+
+
+/*
+ * 'SrvUrlCallback()' - SLP service url callback
+ */
+
+SLPBoolean /* O - TRUE = OK, FALSE = error */
+SrvUrlCallback(SLPHandle hslp, /* I - SLP handle */
+ const char *srvurl, /* I - URL of service */
+ unsigned short lifetime, /* I - Life of service */
+ SLPError errcode, /* I - Existing error code */
+ void *cookie) /* I - Pointer to service list */
+{
+ slpsrvurl_t *s, /* New service entry */
+ **head; /* Pointer to head of entry */
+
+
+ /*
+ * Let the compiler know we won't be using these vars...
+ */
+
+ (void)hslp;
+ (void)lifetime;
+
+ /*
+ * Bail if there was an error
+ */
+
+ if (errcode != SLP_OK)
+ return (SLP_TRUE);
+
+ /*
+ * Grab the head of the list...
+ */
+
+ head = (slpsrvurl_t**)cookie;
+
+ /*
+ * Allocate a *temporary* slpsrvurl_t to hold this entry.
+ */
+
+ if ((s = (slpsrvurl_t *)calloc(1, sizeof(slpsrvurl_t))) == NULL)
+ return (SLP_FALSE);
+
+ /*
+ * Copy the SLP service URL...
+ */
+
+ strlcpy(s->url, srvurl, sizeof(s->url));
+
+ /*
+ * Link the SLP service URL into the head of the list
+ */
+
+ if (*head)
+ s->next = *head;
+
+ *head = s;
+
+ return (SLP_TRUE);
+}
+
+
+/*
+ * 'UpdateSLPBrowse()' - Get browsing information via SLP.
+ */
+
+void
+UpdateSLPBrowse(void)
+{
+ slpsrvurl_t *s, /* Temporary list of service URLs */
+ *next; /* Next service in list */
+ printer_t p; /* Printer information */
+ const char *uri; /* Pointer to printer URI */
+ char method[HTTP_MAX_URI], /* Method portion of URI */
+ username[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
+ LogMessage(L_DEBUG, "UpdateSLPBrowse() Start...");
+
+ /*
+ * Reset the refresh time...
+ */
+
+ BrowseSLPRefresh = time(NULL) + BrowseInterval;
+
+ /*
+ * Poll for remote printers using SLP...
+ */
+
+ s = NULL;
+
+ SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
+ SrvUrlCallback, &s);
+
+ /*
+ * Loop through the list of available printers...
+ */
+
+ for (; s; s = next)
+ {
+ /*
+ * Save the "next" pointer...
+ */
+
+ next = s->next;
+
+ /*
+ * Load a printer_t structure with the SLP service attributes...
+ */
+
+ SLPFindAttrs(BrowseSLPHandle, s->url, "", "", AttrCallback, &p);
+
+ /*
+ * Process this printer entry...
+ */
+
+ uri = s->url + SLP_CUPS_SRVLEN + 1;
+
+ if (strncmp(uri, "http://", 7) == 0 ||
+ strncmp(uri, "ipp://", 6) == 0)
+ {
+ /*
+ * Pull the URI apart to see if this is a local or remote printer...
+ */
+
+ httpSeparate(uri, method, username, host, &port, resource);
+
+ if (strcasecmp(host, ServerName) == 0)
+ continue;
+
+ /*
+ * OK, at least an IPP printer, see if it is a CUPS printer or
+ * class...
+ */
+
+ if (strstr(uri, "/printers/") != NULL)
+ ProcessBrowseData(uri, p.type, IPP_PRINTER_IDLE, p.location,
+ p.info, p.make_model);
+ else if (strstr(uri, "/classes/") != NULL)
+ ProcessBrowseData(uri, p.type | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE,
+ p.location, p.info, p.make_model);
+ }
+
+ /*
+ * Free this listing...
+ */
+
+ free(s);
+ }
+
+ LogMessage(L_DEBUG, "UpdateSLPBrowse() End...");
+}
+#endif /* HAVE_LIBSLP */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
new file mode 100644
index 000000000..35c4b6b21
--- /dev/null
+++ b/scheduler/dirsvc.h
@@ -0,0 +1,145 @@
+/*
+ * "$Id$"
+ *
+ * Directory services definitions for the Common UNIX Printing System
+ * (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#ifdef HAVE_LIBSLP
+# include <slp.h>
+#endif /* HAVE_LIBSLP */
+
+
+/*
+ * Browse protocols...
+ */
+
+#define BROWSE_CUPS 1 /* CUPS */
+#define BROWSE_SLP 2 /* SLPv2 */
+#define BROWSE_LDAP 4 /* LDAP (not supported yet) */
+#define BROWSE_ALL 7 /* All protocols */
+
+
+/*
+ * Browse address...
+ */
+
+typedef struct
+{
+ char iface[32]; /* Destination interface */
+ struct sockaddr_in to; /* Destination address */
+} dirsvc_addr_t;
+
+
+/*
+ * Relay structure...
+ */
+
+typedef struct
+{
+ authmask_t from; /* Source address/name mask */
+ struct sockaddr_in to; /* Destination address */
+} dirsvc_relay_t;
+
+
+/*
+ * Polling structure...
+ */
+
+typedef struct
+{
+ char hostname[16]; /* Hostname (actually, IP address) */
+ int port; /* Port number */
+ int pid; /* Current poll server PID */
+} dirsvc_poll_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int Browsing VALUE(TRUE),
+ /* Whether or not browsing is enabled */
+ BrowseProtocols VALUE(BROWSE_ALL),
+ /* Protocols to support */
+ BrowseShortNames VALUE(TRUE),
+ /* Short names for remote printers? */
+ BrowseSocket VALUE(-1),
+ /* Socket for browsing */
+ BrowsePort VALUE(IPP_PORT),
+ /* Port number for broadcasts */
+ BrowseInterval VALUE(DEFAULT_INTERVAL),
+ /* Broadcast interval in seconds */
+ BrowseTimeout VALUE(DEFAULT_TIMEOUT),
+ /* Time out for printers in seconds */
+ NumBrowsers VALUE(0);
+ /* Number of broadcast addresses */
+VAR dirsvc_addr_t *Browsers VALUE(NULL);
+ /* Broadcast addresses */
+VAR location_t *BrowseACL VALUE(NULL);
+ /* Browser access control list */
+VAR printer_t *BrowseNext VALUE(NULL);
+ /* Next class/printer to broadcast */
+VAR int NumRelays VALUE(0);
+ /* Number of broadcast relays */
+VAR dirsvc_relay_t *Relays VALUE(NULL);
+ /* Broadcast relays */
+VAR int NumPolled VALUE(0);
+ /* Number of polled servers */
+VAR dirsvc_poll_t *Polled VALUE(NULL);
+ /* Polled servers */
+VAR int PollPipe VALUE(0);
+ /* Status pipe for pollers */
+
+#ifdef HAVE_LIBSLP
+VAR SLPHandle BrowseSLPHandle VALUE(NULL);
+ /* SLP API handle */
+VAR time_t BrowseSLPRefresh VALUE(0);
+ /* Next SLP refresh time */
+#endif /* HAVE_LIBSLP */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void ProcessBrowseData(const char *uri, cups_ptype_t type,
+ ipp_pstate_t state, const char *location,
+ const char *info, const char *make_model);
+extern void SendBrowseList(void);
+extern void SendCUPSBrowse(printer_t *p);
+extern void SendSLPBrowse(printer_t *p);
+extern void StartBrowsing(void);
+extern void StartPolling(void);
+extern void StopBrowsing(void);
+extern void StopPolling(void);
+extern void UpdateCUPSBrowse(void);
+extern void UpdatePolling(void);
+extern void UpdateSLPBrowse(void);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/file.c b/scheduler/file.c
new file mode 100644
index 000000000..4c8a4b549
--- /dev/null
+++ b/scheduler/file.c
@@ -0,0 +1,997 @@
+/*
+ * "$Id$"
+ *
+ * File functions for the Common UNIX Printing System (CUPS).
+ *
+ * Since stdio files max out at 256 files on many systems, we have to
+ * write similar functions without this limit. At the same time, using
+ * our own file functions allows us to provide transparent support of
+ * gzip'd print files, PPD files, etc.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * cupsFileClose() - Close a CUPS file.
+ * cupsFileFlush() - Flush pending output.
+ * cupsFileGetChar() - Get a single character from a file.
+ * cupsFileGets() - Get a CR and/or LF-terminated line.
+ * cupsFileOpen() - Open a CUPS file.
+ * cupsFilePrintf() - Write a formatted string.
+ * cupsFilePutChar() - Write a character.
+ * cupsFilePuts() - Write a string.
+ * cupsFileRead() - Read from a file.
+ * cupsFileSeek() - Seek in a file.
+ * cupsFileWrite() - Write to a file.
+ * cups_fill() - Fill the input buffer...
+ * cups_read() - Read from a file descriptor.
+ * cups_write() - Write to a file descriptor.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <cups/string.h>
+#include <errno.h>
+
+#ifdef WIN32
+# include <io.h>
+#else
+# include <unistd.h>
+# include <fcntl.h>
+#endif /* WIN32 */
+
+#include "file.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int cups_fill(cups_file_t *fp);
+static int cups_read(int fd, char *buf, int bytes);
+static int cups_write(int fd, const char *buf, int bytes);
+
+
+/*
+ * 'cupsFileClose()' - Close a CUPS file.
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsFileClose(cups_file_t *fp) /* I - CUPS file */
+{
+ int fd; /* File descriptor */
+
+
+ /*
+ * Range check...
+ */
+
+ if (!fp)
+ return (-1);
+
+#ifdef HAVE_LIBZ
+ /*
+ * Free decompression data as needed...
+ */
+
+ if (fp->compressed && fp->mode == 'r')
+ inflateEnd(&fp->stream);
+#endif /* HAVE_LIBZ */
+
+ if (fp->mode == 'w')
+ cupsFileFlush(fp);
+
+ /*
+ * Save the file descriptor we used and free memory...
+ */
+
+ fd = fp->fd;
+
+ free(fp);
+
+ /*
+ * Close the file, returning the close status...
+ */
+
+ return (close(fd));
+}
+
+
+/*
+ * 'cupsFileFlush()' - Flush pending output.
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsFileFlush(cups_file_t *fp) /* I - CUPS file */
+{
+ int bytes; /* Bytes to write */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || fp->mode != 'w')
+ return (-1);
+
+ bytes = fp->ptr - fp->buf;
+
+ if (bytes > 0)
+ {
+ if (cups_write(fp->fd, fp->buf, bytes) < bytes)
+ return (-1);
+
+ fp->ptr = fp->buf;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'cupsFileGetChar()' - Get a single character from a file.
+ */
+
+int /* O - Character or -1 on EOF */
+cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!fp || fp->mode != 'r')
+ return (-1);
+
+ /*
+ * If the input buffer is empty, try to read more data...
+ */
+
+ if (fp->ptr >= fp->end)
+ if (cups_fill(fp) < 0)
+ return (-1);
+
+ /*
+ * Return the next character in the buffer...
+ */
+
+ return (*(fp->ptr)++ & 255);
+}
+
+
+/*
+ * 'cupsFileGets()' - Get a CR and/or LF-terminated line.
+ */
+
+char * /* O - Line read or NULL on eof/error */
+cupsFileGets(cups_file_t *fp, /* I - CUPS file */
+ char *buf, /* O - String buffer */
+ int buflen) /* I - Size of string buffer */
+{
+ int ch; /* Character from file */
+ char *ptr, /* Current position in line buffer */
+ *end; /* End of line buffer */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || fp->mode != 'r' || !buf || buflen < 2)
+ return (NULL);
+
+ /*
+ * Now loop until we have a valid line...
+ */
+
+ for (ptr = buf, end = buf + buflen - 1; ptr < end ;)
+ {
+ if (fp->ptr >= fp->end)
+ if (cups_fill(fp) <= 0)
+ {
+ if (ptr == buf)
+ return (NULL);
+ else
+ break;
+ }
+
+ ch = *(fp->ptr)++;
+
+ if (ch == '\r')
+ {
+ /*
+ * Check for CR LF...
+ */
+
+ if (fp->ptr >= fp->end)
+ if (cups_fill(fp) <= 0)
+ break;
+
+ if (*(fp->ptr) == '\n')
+ fp->ptr ++;
+
+ break;
+ }
+ else if (ch == '\n')
+ {
+ /*
+ * Line feed ends a line...
+ */
+
+ break;
+ }
+ else
+ *ptr++ = ch;
+ }
+
+ *ptr = '\0';
+
+ return (buf);
+}
+
+
+/*
+ * 'cupsFileOpen()' - Open a CUPS file.
+ */
+
+cups_file_t * /* O - CUPS file or NULL */
+cupsFileOpen(const char *filename, /* I - Name of file */
+ const char *mode) /* I - Open mode */
+{
+ cups_file_t *fp; /* New CUPS file */
+ int o; /* Open mode bits */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!filename || !mode || (*mode != 'r' && *mode != 'w' && *mode != 'a'))
+ return (NULL);
+
+ /*
+ * Allocate memory...
+ */
+
+ if ((fp = calloc(1, sizeof(cups_file_t))) == NULL)
+ return (NULL);
+
+ /*
+ * Open the file...
+ */
+
+ switch (*mode)
+ {
+ case 'a' :
+ o = O_RDWR | O_CREAT;
+ fp->mode = 'w';
+ break;
+
+ case 'r' :
+ o = O_RDONLY;
+ fp->mode = 'r';
+ break;
+
+ case 'w' :
+ o = O_WRONLY | O_TRUNC | O_CREAT;
+ fp->mode = 'w';
+ break;
+
+ default : /* Remove bogus compiler warning... */
+ return (NULL);
+ }
+
+ if ((fp->fd = open(filename, o, 0644)) < 0)
+ {
+ /*
+ * Can't open file!
+ */
+
+ free(fp);
+ return (NULL);
+ }
+
+ /*
+ * Don't pass this file to child processes...
+ */
+
+ fcntl(fp->fd, F_SETFD, fcntl(fp->fd, F_GETFD) | FD_CLOEXEC);
+
+ if (*mode == 'a')
+ fp->pos = lseek(fp->fd, 0, SEEK_END);
+ else
+ fp->pos = 0;
+
+ if (*mode != 'r')
+ {
+ fp->ptr = fp->buf;
+ fp->end = fp->buf + sizeof(fp->buf);
+ }
+
+ return (fp);
+}
+
+
+/*
+ * 'cupsFilePrintf()' - Write a formatted string.
+ */
+
+int /* O - Number of bytes written or -1 */
+cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */
+ const char *format, /* I - Printf-style format string */
+ ...) /* I - Additional args as necessary */
+{
+ va_list ap; /* Argument list */
+ int bytes; /* Formatted size */
+ char buf[2048]; /* Formatted text */
+
+
+ if (!fp || !format || fp->mode != 'w')
+ return (-1);
+
+ va_start(ap, format);
+ bytes = vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+
+ if ((fp->ptr + bytes) > fp->end)
+ if (cupsFileFlush(fp))
+ return (-1);
+
+ fp->pos += bytes;
+
+ if (bytes > sizeof(fp->buf))
+ return (cups_write(fp->fd, buf, bytes));
+ else
+ {
+ memcpy(fp->ptr, buf, bytes);
+ fp->ptr += bytes;
+ return (bytes);
+ }
+}
+
+
+/*
+ * 'cupsFilePutChar()' - Write a character.
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsFilePutChar(cups_file_t *fp, /* I - CUPS file */
+ int c) /* I - Character to write */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!fp || fp->mode != 'w')
+ return (-1);
+
+ /*
+ * Buffer it up...
+ */
+
+ if (fp->ptr >= fp->end)
+ if (cupsFileFlush(fp))
+ return (-1);
+
+ *(fp->ptr) ++ = c;
+ fp->pos ++;
+
+ return (0);
+}
+
+
+/*
+ * 'cupsFilePuts()' - Write a string.
+ */
+
+int /* O - Number of bytes written or -1 */
+cupsFilePuts(cups_file_t *fp, /* I - CUPS file */
+ const char *s) /* I - String to write */
+{
+ int bytes; /* Bytes to write */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || !s || fp->mode != 'w')
+ return (-1);
+
+ /*
+ * Write the string...
+ */
+
+ bytes = strlen(s);
+
+ if ((fp->ptr + bytes) > fp->end)
+ if (cupsFileFlush(fp))
+ return (-1);
+
+ fp->pos += bytes;
+
+ if (bytes > sizeof(fp->buf))
+ return (cups_write(fp->fd, s, bytes));
+ else
+ {
+ memcpy(fp->ptr, s, bytes);
+ fp->ptr += bytes;
+ return (bytes);
+ }
+}
+
+
+/*
+ * 'cupsFileRead()' - Read from a file.
+ */
+
+int /* O - Number of bytes read or -1 */
+cupsFileRead(cups_file_t *fp, /* I - CUPS file */
+ char *buf, /* O - Buffer */
+ int bytes) /* I - Number of bytes to read */
+{
+ int total, /* Total bytes read */
+ count; /* Bytes read */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || !buf || bytes < 0 || fp->mode != 'r')
+ return (-1);
+
+ if (bytes == 0)
+ return (0);
+
+ /*
+ * Loop until all bytes are read...
+ */
+
+ total = 0;
+ while (bytes > 0)
+ {
+ if (fp->ptr >= fp->end)
+ if (cups_fill(fp) <= 0)
+ {
+ if (total > 0)
+ return (total);
+ else
+ return (-1);
+ }
+
+ count = fp->end - fp->ptr;
+ if (count > bytes)
+ count = bytes;
+
+ memcpy(buf, fp->ptr, count);
+ fp->ptr += count;
+
+ /*
+ * Update the counts for the last read...
+ */
+
+ bytes -= count;
+ total += count;
+ buf += count;
+ }
+
+ /*
+ * Return the total number of bytes read...
+ */
+
+ return (total);
+}
+
+
+/*
+ * 'cupsFileSeek()' - Seek in a file.
+ */
+
+int /* O - New file position or -1 */
+cupsFileSeek(cups_file_t *fp, /* I - CUPS file */
+ int pos) /* I - Position in file */
+{
+ int bytes; /* Number bytes in buffer */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || pos < 0 || fp->mode != 'r')
+ return (-1);
+
+ /*
+ * Figure out the number of bytes in the current buffer, and then
+ * see if we are outside of it...
+ */
+
+ bytes = fp->end - fp->buf;
+
+ if (pos < fp->pos)
+ {
+ /*
+ * Need to seek backwards...
+ */
+
+#ifdef HAVE_LIBZ
+ if (fp->compressed)
+ {
+ inflateEnd(&fp->stream);
+
+ lseek(fp->fd, 0, SEEK_SET);
+ fp->pos = 0;
+ fp->ptr = NULL;
+ fp->end = NULL;
+ fp->eof = 0;
+
+ while ((bytes = cups_fill(fp)) > 0)
+ if (pos >= fp->pos && pos < (fp->pos + bytes))
+ break;
+
+ if (bytes <= 0)
+ return (-1);
+ }
+ else
+#endif /* HAVE_LIBZ */
+ {
+ lseek(fp->fd, pos, SEEK_SET);
+ fp->pos = pos;
+ fp->ptr = NULL;
+ fp->end = NULL;
+#ifdef HAVE_LIBZ
+ fp->eof = 0;
+#endif /* HAVE_LIBZ */
+ }
+ }
+ else if (pos >= (fp->pos + bytes))
+ {
+ /*
+ * Need to seek forwards...
+ */
+
+#ifdef HAVE_LIBZ
+ if (fp->compressed)
+ {
+ while ((bytes = cups_fill(fp)) > 0)
+ if (pos >= fp->pos && pos < (fp->pos + bytes))
+ break;
+
+ if (bytes <= 0)
+ return (-1);
+ }
+ else
+#endif /* HAVE_LIBZ */
+ {
+ lseek(fp->fd, pos, SEEK_SET);
+ fp->pos = pos;
+ fp->ptr = NULL;
+ fp->end = NULL;
+#ifdef HAVE_LIBZ
+ fp->eof = 0;
+#endif /* HAVE_LIBZ */
+ }
+ }
+ else
+ {
+ /*
+ * Just reposition the current pointer, since we have the right
+ * range...
+ */
+
+ fp->ptr = fp->buf + pos - fp->pos;
+#ifdef HAVE_LIBZ
+ fp->eof = 0;
+#endif /* HAVE_LIBZ */
+ }
+
+ return (pos);
+}
+
+
+/*
+ * 'cupsFileWrite()' - Write to a file.
+ */
+
+int /* O - Number of bytes written */
+cupsFileWrite(cups_file_t *fp, /* I - CUPS file */
+ const char *buf, /* I - Buffer */
+ int bytes) /* I - Number of bytes to write */
+{
+ /*
+ * Range check input...
+ */
+
+ if (!fp || !buf || bytes < 0 || fp->mode != 'w')
+ return (-1);
+
+ if (bytes == 0)
+ return (0);
+
+ /*
+ * Write the buffer...
+ */
+
+ if ((fp->ptr + bytes) > fp->end)
+ if (cupsFileFlush(fp))
+ return (-1);
+
+ fp->pos += bytes;
+
+ if (bytes > sizeof(fp->buf))
+ return (cups_write(fp->fd, buf, bytes));
+ else
+ {
+ memcpy(fp->ptr, buf, bytes);
+ fp->ptr += bytes;
+ return (bytes);
+ }
+}
+
+
+/*
+ * 'cups_fill()' - Fill the input buffer...
+ */
+
+static int /* O - Number of bytes or -1 */
+cups_fill(cups_file_t *fp) /* I - CUPS file */
+{
+ int bytes; /* Number of bytes read */
+#ifdef HAVE_LIBZ
+ const unsigned char *ptr, /* Pointer into buffer */
+ *end; /* End of buffer */
+#endif /* HAVE_LIBZ */
+
+
+ /*
+ * Update the "pos" element as needed...
+ */
+
+ if (fp->ptr)
+ fp->pos += fp->end - fp->buf;
+
+#ifdef HAVE_LIBZ
+ /*
+ * Check to see if we have read any data yet; if not, see if we have a
+ * compressed file...
+ */
+
+ if (!fp->ptr)
+ {
+ /*
+ * Reset the file position in case we are seeking...
+ */
+
+ fp->compressed = 0;
+ fp->pos = 0;
+
+ /*
+ * Read the first bytes in the file to determine if we have a gzip'd
+ * file...
+ */
+
+ if ((bytes = cups_read(fp->fd, (char *)fp->cbuf, sizeof(fp->cbuf))) < 0)
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+
+ if (bytes < 10 || fp->cbuf[0] != 0x1f || fp->cbuf[1] != 0x8b ||
+ fp->cbuf[2] != 8 || (fp->cbuf[3] & 0xe0) != 0)
+ {
+ /*
+ * Not a gzip'd file!
+ */
+
+ memcpy(fp->buf, fp->cbuf, bytes);
+
+ fp->ptr = fp->buf;
+ fp->end = fp->buf + bytes;
+
+ return (bytes);
+ }
+
+ /*
+ * Parse header junk: extra data, original name, and comment...
+ */
+
+ ptr = fp->cbuf + 10;
+ end = fp->cbuf + bytes;
+
+ if (fp->cbuf[3] & 0x04)
+ {
+ /*
+ * Skip extra data...
+ */
+
+ if ((ptr + 2) > end)
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+
+ bytes = ((unsigned char)ptr[1] << 8) | (unsigned char)ptr[0];
+ ptr += 2 + bytes;
+
+ if (ptr > end)
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+ }
+
+ if (fp->cbuf[3] & 0x08)
+ {
+ /*
+ * Skip original name data...
+ */
+
+ while (ptr < end && *ptr)
+ ptr ++;
+
+ if (ptr < end)
+ ptr ++;
+ else
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+ }
+
+ if (fp->cbuf[3] & 0x10)
+ {
+ /*
+ * Skip comment data...
+ */
+
+ while (ptr < end && *ptr)
+ ptr ++;
+
+ if (ptr < end)
+ ptr ++;
+ else
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+ }
+
+ if (fp->cbuf[3] & 0x02)
+ {
+ /*
+ * Skip header CRC data...
+ */
+
+ ptr += 2;
+
+ if (ptr > end)
+ {
+ /*
+ * Can't read from file!
+ */
+
+ return (-1);
+ }
+ }
+
+ /*
+ * Setup the decompressor data...
+ */
+
+ fp->stream.zalloc = (alloc_func)0;
+ fp->stream.zfree = (free_func)0;
+ fp->stream.opaque = (voidpf)0;
+ fp->stream.next_in = (Bytef *)ptr;
+ fp->stream.next_out = NULL;
+ fp->stream.avail_in = end - ptr;
+ fp->stream.avail_out = 0;
+
+ if (inflateInit2(&(fp->stream), -15) != Z_OK)
+ return (-1);
+
+ fp->compressed = 1;
+ }
+
+ if (fp->compressed)
+ {
+ /*
+ * If we have reached end-of-file, return immediately...
+ */
+
+ if (fp->eof)
+ return (-1);
+
+ /*
+ * Fill the decompression buffer as needed...
+ */
+
+ if (fp->stream.avail_in == 0)
+ {
+ if ((bytes = cups_read(fp->fd, (char *)fp->cbuf, sizeof(fp->cbuf))) <= 0)
+ return (-1);
+
+ fp->stream.next_in = fp->cbuf;
+ fp->stream.avail_in = bytes;
+ }
+
+ /*
+ * Decompress data from the buffer...
+ */
+
+ fp->stream.next_out = (Bytef *)fp->buf;
+ fp->stream.avail_out = sizeof(fp->buf);
+
+ if (inflate(&(fp->stream), Z_NO_FLUSH) == Z_STREAM_END)
+ {
+ /*
+ * Mark end-of-file; note: we do not support concatenated gzip files
+ * like gunzip does...
+ */
+
+ fp->eof = 1;
+ }
+
+ bytes = sizeof(fp->buf) - fp->stream.avail_out;
+
+ /*
+ * Return the decompressed data...
+ */
+
+ fp->ptr = fp->buf;
+ fp->end = fp->buf + bytes;
+
+ return (bytes);
+ }
+#endif /* HAVE_LIBZ */
+
+ /*
+ * Read a buffer's full of data...
+ */
+
+ if ((bytes = cups_read(fp->fd, fp->buf, sizeof(fp->buf))) <= 0)
+ {
+ /*
+ * Can't read from file!
+ */
+
+ fp->ptr = fp->buf;
+ fp->end = fp->buf;
+
+ return (-1);
+ }
+
+ /*
+ * Return the bytes we read...
+ */
+
+ fp->ptr = fp->buf;
+ fp->end = fp->buf + bytes;
+
+ return (bytes);
+}
+
+
+/*
+ * 'cups_read()' - Read from a file descriptor.
+ */
+
+int /* O - Number of bytes read or -1 */
+cups_read(int fd, /* I - File descriptor */
+ char *buf, /* I - Buffer */
+ int bytes) /* I - Number bytes */
+{
+ int total; /* Total bytes read */
+
+
+ /*
+ * Loop until we read at least 0 bytes...
+ */
+
+ while ((total = read(fd, buf, bytes)) < 0)
+ {
+ /*
+ * Reads can be interrupted by signals and unavailable resources...
+ */
+
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ else
+ return (-1);
+ }
+
+ /*
+ * Return the total number of bytes read...
+ */
+
+ return (total);
+}
+
+
+/*
+ * 'cups_write()' - Write to a file descriptor.
+ */
+
+int /* O - Number of bytes written or -1 */
+cups_write(int fd, /* I - File descriptor */
+ const char *buf, /* I - Buffer */
+ int bytes) /* I - Number bytes */
+{
+ int total, /* Total bytes written */
+ count; /* Count this time */
+
+
+ /*
+ * Loop until all bytes are written...
+ */
+
+ total = 0;
+ while (bytes > 0)
+ {
+ if ((count = write(fd, buf, bytes)) < 0)
+ {
+ /*
+ * Writes can be interrupted by signals and unavailable resources...
+ */
+
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ else
+ return (-1);
+ }
+
+ /*
+ * Update the counts for the last write call...
+ */
+
+ bytes -= count;
+ total += count;
+ buf += count;
+ }
+
+ /*
+ * Return the total number of bytes written...
+ */
+
+ return (total);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/file.h b/scheduler/file.h
new file mode 100644
index 000000000..27585de35
--- /dev/null
+++ b/scheduler/file.h
@@ -0,0 +1,108 @@
+/*
+ * "$Id$"
+ *
+ * File definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Since stdio files max out at 256 files on many systems, we have to
+ * write similar functions without this limit. At the same time, using
+ * our own file functions allows us to provide transparent support of
+ * gzip'd print files, PPD files, etc.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifndef _CUPS_FILE_H
+# define _CUPS_FILE_H_
+
+/*
+ * Include necessary headers...
+ */
+
+# ifdef HAVE_LIBZ
+# include <zlib.h>
+# endif /* HAVE_LIBZ */
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef _cplusplus
+extern "C" {
+# endif /* _cplusplus */
+
+
+/*
+ * CUPS file definitions...
+ */
+
+# define CUPS_FILE_NONE 0 /* No compression */
+# define CUPS_FILE_GZIP 1 /* GZIP compression */
+
+
+/*
+ * CUPS file structure...
+ */
+
+typedef struct
+{
+ int fd; /* File descriptor */
+ char mode, /* Mode ('r' or 'w') */
+ compressed, /* Compression used? */
+ buf[2048], /* Buffer */
+ *ptr, /* Pointer into buffer */
+ *end; /* End of buffer data */
+ int pos; /* File position for start of buffer */
+
+# ifdef HAVE_LIBZ
+ z_stream stream; /* Decompression stream */
+ int eof; /* End of file? */
+ unsigned char cbuf[1024]; /* Decompression buffer */
+# endif /* HAVE_LIBZ */
+} cups_file_t;
+
+
+/*
+ * Prototypes...
+ */
+
+extern int cupsFileClose(cups_file_t *fp);
+#define cupsFileCompression(fp) (fp)->compressed
+extern int cupsFileFlush(cups_file_t *fp);
+extern int cupsFileGetChar(cups_file_t *fp);
+extern char *cupsFileGets(cups_file_t *fp, char *buf, int buflen);
+#define cupsFileNumber(fp) (fp)->fd
+extern cups_file_t *cupsFileOpen(const char *filename, const char *mode);
+extern int cupsFilePrintf(cups_file_t *fp, const char *format, ...);
+extern int cupsFilePutChar(cups_file_t *fp, int c);
+extern int cupsFilePuts(cups_file_t *fp, const char *s);
+extern int cupsFileRead(cups_file_t *fp, char *buf, int bytes);
+extern int cupsFileSeek(cups_file_t *fp, int pos);
+#define cupsFileTell(fp) (fp)->pos
+extern int cupsFileWrite(cups_file_t *fp, const char *buf, int bytes);
+
+
+# ifdef _cplusplus
+}
+# endif /* _cplusplus */
+#endif /* !_CUPS_FILE_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/filter.c b/scheduler/filter.c
new file mode 100644
index 000000000..73cdf1a29
--- /dev/null
+++ b/scheduler/filter.c
@@ -0,0 +1,326 @@
+/*
+ * "$Id$"
+ *
+ * File type conversion routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * mimeAddFilter() - Add a filter to the current MIME database.
+ * mimeFilter() - Find the fastest way to convert from one type to another.
+ * compare() - Compare two filter types...
+ * lookup() - Lookup a filter...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <cups/debug.h>
+#include <cups/string.h>
+#include "mime.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int compare(mime_filter_t *, mime_filter_t *);
+static mime_filter_t *lookup(mime_t *, mime_type_t *, mime_type_t *);
+
+
+/*
+ * 'mimeAddFilter()' - Add a filter to the current MIME database.
+ */
+
+mime_filter_t * /* O - New filter */
+mimeAddFilter(mime_t *mime, /* I - MIME database */
+ mime_type_t *src, /* I - Source type */
+ mime_type_t *dst, /* I - Destination type */
+ int cost, /* I - Relative time/resource cost */
+ const char *filter) /* I - Filter program to run */
+{
+ mime_filter_t *temp; /* New filter */
+
+
+ /*
+ * Range-check the input...
+ */
+
+ if (mime == NULL || src == NULL || dst == NULL || filter == NULL)
+ return (NULL);
+
+ if (strlen(filter) > (MIME_MAX_FILTER - 1))
+ return (NULL);
+
+ /*
+ * See if we already have an existing filter for the given source and
+ * destination...
+ */
+
+ if ((temp = lookup(mime, src, dst)) != NULL)
+ {
+ /*
+ * Yup, does the existing filter have a higher cost? If so, copy the
+ * filter and cost to the existing filter entry and return it...
+ */
+
+ if (temp->cost > cost)
+ {
+ temp->cost = cost;
+ strlcpy(temp->filter, filter, sizeof(temp->filter));
+ }
+ }
+ else
+ {
+ /*
+ * Nope, add a new one...
+ */
+
+ if (mime->num_filters == 0)
+ temp = malloc(sizeof(mime_filter_t));
+ else
+ temp = realloc(mime->filters, sizeof(mime_filter_t) * (mime->num_filters + 1));
+
+ if (temp == NULL)
+ return (NULL);
+
+ mime->filters = temp;
+ temp += mime->num_filters;
+ mime->num_filters ++;
+
+ /*
+ * Copy the information over and sort if necessary...
+ */
+
+ temp->src = src;
+ temp->dst = dst;
+ temp->cost = cost;
+ strlcpy(temp->filter, filter, sizeof(temp->filter));
+
+ if (mime->num_filters > 1)
+ qsort(mime->filters, mime->num_filters, sizeof(mime_filter_t),
+ (int (*)(const void *, const void *))compare);
+ }
+
+ /*
+ * Return the new/updated filter...
+ */
+
+ return (temp);
+}
+
+
+/*
+ * 'mimeFilter()' - Find the fastest way to convert from one type to another.
+ */
+
+mime_filter_t * /* O - Array of filters to run */
+mimeFilter(mime_t *mime, /* I - MIME database */
+ mime_type_t *src, /* I - Source file type */
+ mime_type_t *dst, /* I - Destination file type */
+ int *num_filters, /* O - Number of filters to run */
+ int max_depth) /* I - Maximum depth of search */
+{
+ int i, j, /* Looping vars */
+ num_temp, /* Number of temporary filters */
+ num_mintemp, /* Number of filters in the minimum */
+ cost, /* Current cost */
+ mincost; /* Current minimum */
+ mime_filter_t *temp, /* Temporary filter */
+ *mintemp, /* Current minimum */
+ *current; /* Current filter */
+
+
+ /*
+ * Range-check the input...
+ */
+
+ DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), num_filters=%p(%d))\n",
+ mime, src, src ? src->super : "?", src ? src->type : "?",
+ dst, dst ? dst->super : "?", dst ? dst->type : "?",
+ num_filters, num_filters ? *num_filters : 0));
+
+ if (mime == NULL || src == NULL || dst == NULL || num_filters == NULL ||
+ max_depth <= 0)
+ return (NULL);
+
+ *num_filters = 0;
+
+ /*
+ * See if there is a filter that can convert the files directly...
+ */
+
+ if ((temp = lookup(mime, src, dst)) != NULL)
+ {
+ /*
+ * Got a direct filter!
+ */
+
+ if ((mintemp = (mime_filter_t *)malloc(sizeof(mime_filter_t))) == NULL)
+ return (NULL);
+
+ memcpy(mintemp, temp, sizeof(mime_filter_t));
+ num_mintemp = 1;
+ mincost = mintemp->cost;
+
+ DEBUG_puts(" Found direct filter:");
+ DEBUG_printf((" %s (cost=%d)\n", mintemp->filter, mincost));
+ }
+ else
+ {
+ /*
+ * No direct filter...
+ */
+
+ mincost = 9999999;
+ mintemp = NULL;
+ num_mintemp = 0;
+ }
+
+ /*
+ * OK, now look for filters from the source type to any other type...
+ */
+
+ for (i = mime->num_filters, current = mime->filters;
+ i > 0;
+ i --, current ++)
+ if (current->src == src)
+ {
+ /*
+ * See if we have any filters that can convert from the destination type
+ * of this filter to the final type...
+ */
+
+ if ((temp = mimeFilter(mime, current->dst, dst, &num_temp,
+ max_depth - 1)) == NULL)
+ continue;
+
+ /*
+ * Found a match; see if this one is less costly than the last (if
+ * any...)
+ */
+
+ for (j = 0, cost = 0; j < num_temp; j ++)
+ cost += temp[j].cost;
+
+ if (cost < mincost)
+ {
+ if (mintemp != NULL)
+ free(mintemp);
+
+ /*
+ * Hey, we got a match! Add the current filter to the beginning of the
+ * filter list...
+ */
+
+ mintemp = (mime_filter_t *)realloc(temp, sizeof(mime_filter_t) *
+ (num_temp + 1));
+
+ if (mintemp == NULL)
+ {
+ *num_filters = 0;
+ return (NULL);
+ }
+
+ memmove(mintemp + 1, mintemp, num_temp * sizeof(mime_filter_t));
+ memcpy(mintemp, current, sizeof(mime_filter_t));
+
+ num_mintemp = num_temp + 1;
+ mincost = cost;
+ }
+ else
+ free(temp);
+ }
+
+ if (mintemp != NULL)
+ {
+ /*
+ * Hey, we got a match!
+ */
+
+ *num_filters = num_mintemp;
+
+#ifdef DEBUG
+ printf(" Returning %d filters:\n", *num_filters);
+ for (i = 0; i < num_mintemp; i ++)
+ printf(" %s\n", mintemp[i].filter);
+#endif /* DEBUG */
+
+ return (mintemp);
+ }
+
+ DEBUG_puts(" Returning zippo...");
+
+ return (NULL);
+}
+
+
+/*
+ * 'compare()' - Compare two filter types...
+ */
+
+static int /* O - Comparison result */
+compare(mime_filter_t *f0, /* I - First filter */
+ mime_filter_t *f1) /* I - Second filter */
+{
+ int i; /* Result of comparison */
+
+
+ if ((i = strcmp(f0->src->super, f1->src->super)) == 0)
+ if ((i = strcmp(f0->src->type, f1->src->type)) == 0)
+ if ((i = strcmp(f0->dst->super, f1->dst->super)) == 0)
+ i = strcmp(f0->dst->type, f1->dst->type);
+
+ return (i);
+}
+
+
+/*
+ * 'lookup()' - Lookup a filter...
+ */
+
+static mime_filter_t * /* O - Filter for src->dst */
+lookup(mime_t *mime, /* I - MIME database */
+ mime_type_t *src, /* I - Source type */
+ mime_type_t *dst) /* I - Destination type */
+{
+ mime_filter_t key; /* Key record for filter search */
+
+
+ if (mime->num_filters == 0)
+ return (NULL);
+
+ key.src = src;
+ key.dst = dst;
+
+ return ((mime_filter_t *)bsearch(&key, mime->filters, mime->num_filters,
+ sizeof(mime_filter_t),
+ (int (*)(const void *, const void *))compare));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
new file mode 100644
index 000000000..d444587dd
--- /dev/null
+++ b/scheduler/ipp.c
@@ -0,0 +1,6877 @@
+/*
+ * "$Id$"
+ *
+ * IPP routines for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * ProcessIPPRequest() - Process an incoming IPP request...
+ * accept_jobs() - Accept print jobs to a printer.
+ * add_class() - Add a class to the system.
+ * add_file() - Add a file to a job.
+ * add_job_state_reasons() - Add the "job-state-reasons" attribute based
+ * upon the job and printer state...
+ * add_printer() - Add a printer to the system.
+ * add_printer_state_reasons() - Add the "printer-state-reasons" attribute
+ * based upon the printer state...
+ * add_queued_job_count() - Add the "queued-job-count" attribute for
+ * cancel_all_jobs() - Cancel all print jobs.
+ * cancel_job() - Cancel a print job.
+ * check_quotas() - Check quotas for a printer and user.
+ * copy_attribute() - Copy a single attribute.
+ * copy_attrs() - Copy attributes from one request to another.
+ * copy_banner() - Copy a banner file to the requests directory
+ * for the specified job.
+ * copy_file() - Copy a PPD file or interface script...
+ * copy_model() - Copy a PPD model file, substituting default
+ * values as needed...
+ * create_job() - Print a file to a printer or class.
+ * delete_printer() - Remove a printer or class from the system.
+ * get_default() - Get the default destination.
+ * get_devices() - Get the list of available devices on the
+ * local system.
+ * get_jobs() - Get a list of jobs for the specified printer.
+ * get_job_attrs() - Get job attributes.
+ * get_ppds() - Get the list of PPD files on the local
+ * system.
+ * get_printer_attrs() - Get printer attributes.
+ * get_printers() - Get a list of printers.
+ * hold_job() - Hold a print job.
+ * move_job() - Move a job to a new destination.
+ * ppd_add_default() - Add a PPD default choice.
+ * ppd_parse_line() - Parse a PPD default line.
+ * print_job() - Print a file to a printer or class.
+ * read_ps_line() - Read a line from a PS file...
+ * read_ps_job_ticket() - Reads a job ticket embedded in a PS file.
+ * reject_jobs() - Reject print jobs to a printer.
+ * release_job() - Release a held print job.
+ * restart_job() - Restart an old print job.
+ * send_document() - Send a file to a printer or class.
+ * send_ipp_error() - Send an error status back to the IPP client.
+ * set_default() - Set the default destination...
+ * set_job_attrs() - Set job attributes.
+ * start_printer() - Start a printer.
+ * stop_printer() - Stop a printer.
+ * validate_job() - Validate printer options and destination.
+ * validate_user() - Validate the user for the request.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef HAVE_LIBPAPER
+# include <paper.h>
+#endif /* HAVE_LIBPAPER */
+
+
+/*
+ * PPD default choice structure...
+ */
+
+typedef struct
+{
+ char option[PPD_MAX_NAME]; /* Main keyword (option name) */
+ char choice[PPD_MAX_NAME]; /* Option keyword (choice name) */
+} ppd_default_t;
+
+
+
+/*
+ * Local functions...
+ */
+
+static void accept_jobs(client_t *con, ipp_attribute_t *uri);
+static void add_class(client_t *con, ipp_attribute_t *uri);
+static int add_file(client_t *con, job_t *job, mime_type_t *filetype,
+ int compression);
+static void add_job_state_reasons(client_t *con, job_t *job);
+static void add_printer(client_t *con, ipp_attribute_t *uri);
+static void add_printer_state_reasons(client_t *con, printer_t *p);
+static void add_queued_job_count(client_t *con, printer_t *p);
+static void cancel_all_jobs(client_t *con, ipp_attribute_t *uri);
+static void cancel_job(client_t *con, ipp_attribute_t *uri);
+static int check_quotas(client_t *con, printer_t *p);
+static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr,
+ int quickcopy);
+static void copy_attrs(ipp_t *to, ipp_t *from, ipp_attribute_t *req,
+ ipp_tag_t group, int quickcopy);
+static int copy_banner(client_t *con, job_t *job, const char *name);
+static int copy_file(const char *from, const char *to);
+static int copy_model(const char *from, const char *to);
+static void create_job(client_t *con, ipp_attribute_t *uri);
+static void delete_printer(client_t *con, ipp_attribute_t *uri);
+static void get_default(client_t *con);
+static void get_devices(client_t *con);
+static void get_jobs(client_t *con, ipp_attribute_t *uri);
+static void get_job_attrs(client_t *con, ipp_attribute_t *uri);
+static void get_ppds(client_t *con);
+static void get_printers(client_t *con, int type);
+static void get_printer_attrs(client_t *con, ipp_attribute_t *uri);
+static void hold_job(client_t *con, ipp_attribute_t *uri);
+static void move_job(client_t *con, ipp_attribute_t *uri);
+static int ppd_add_default(const char *option, const char *choice,
+ int num_defaults, ppd_default_t **defaults);
+static int ppd_parse_line(const char *line, char *option, int olen,
+ char *choice, int clen);
+static void print_job(client_t *con, ipp_attribute_t *uri);
+static void read_ps_job_ticket(client_t *con);
+static void reject_jobs(client_t *con, ipp_attribute_t *uri);
+static void release_job(client_t *con, ipp_attribute_t *uri);
+static void restart_job(client_t *con, ipp_attribute_t *uri);
+static void send_document(client_t *con, ipp_attribute_t *uri);
+static void send_ipp_error(client_t *con, ipp_status_t status);
+static void set_default(client_t *con, ipp_attribute_t *uri);
+static void set_job_attrs(client_t *con, ipp_attribute_t *uri);
+static void start_printer(client_t *con, ipp_attribute_t *uri);
+static void stop_printer(client_t *con, ipp_attribute_t *uri);
+static void validate_job(client_t *con, ipp_attribute_t *uri);
+static int validate_user(client_t *con, const char *owner, char *username,
+ int userlen);
+
+
+/*
+ * 'ProcessIPPRequest()' - Process an incoming IPP request...
+ */
+
+int /* O - 1 on success, 0 on failure */
+ProcessIPPRequest(client_t *con) /* I - Client connection */
+{
+ ipp_tag_t group; /* Current group tag */
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_attribute_t *charset; /* Character set attribute */
+ ipp_attribute_t *language; /* Language attribute */
+ ipp_attribute_t *uri; /* Printer URI attribute */
+ ipp_attribute_t *username; /* requesting-user-name attr */
+
+
+ LogMessage(L_DEBUG2, "ProcessIPPRequest(%p[%d]): operation_id = %04x",
+ con, con->http.fd, con->request->request.op.operation_id);
+
+ /*
+ * First build an empty response message for this request...
+ */
+
+ con->response = ippNew();
+
+ con->response->request.status.version[0] = con->request->request.op.version[0];
+ con->response->request.status.version[1] = con->request->request.op.version[1];
+ con->response->request.status.request_id = con->request->request.op.request_id;
+
+ /*
+ * Then validate the request header and required attributes...
+ */
+
+ if (con->request->request.any.version[0] != 1)
+ {
+ /*
+ * Return an error, since we only support IPP 1.x.
+ */
+
+ LogMessage(L_ERROR, "ProcessIPPRequest: bad request version (%d.%d)!",
+ con->request->request.any.version[0],
+ con->request->request.any.version[1]);
+
+ send_ipp_error(con, IPP_VERSION_NOT_SUPPORTED);
+ }
+ else if (con->request->attrs == NULL)
+ {
+ LogMessage(L_ERROR, "ProcessIPPRequest: no attributes in request!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ }
+ else
+ {
+ /*
+ * Make sure that the attributes are provided in the correct order and
+ * don't repeat groups...
+ */
+
+ for (attr = con->request->attrs, group = attr->group_tag;
+ attr != NULL;
+ attr = attr->next)
+ if (attr->group_tag < group)
+ {
+ /*
+ * Out of order; return an error...
+ */
+
+ LogMessage(L_ERROR, "ProcessIPPRequest: attribute groups are out of order!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ break;
+ }
+ else
+ group = attr->group_tag;
+
+ if (attr == NULL)
+ {
+ /*
+ * Then make sure that the first three attributes are:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri/job-uri
+ */
+
+ attr = con->request->attrs;
+ if (attr != NULL && strcmp(attr->name, "attributes-charset") == 0 &&
+ attr->value_tag == IPP_TAG_CHARSET)
+ charset = attr;
+ else
+ charset = NULL;
+
+ if (attr)
+ attr = attr->next;
+ if (attr != NULL && strcmp(attr->name, "attributes-natural-language") == 0 &&
+ attr->value_tag == IPP_TAG_LANGUAGE)
+ language = attr;
+ else
+ language = NULL;
+
+ if ((attr = ippFindAttribute(con->request, "printer-uri", IPP_TAG_URI)) != NULL)
+ uri = attr;
+ else if ((attr = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI)) != NULL)
+ uri = attr;
+ else
+ uri = NULL;
+
+ if (charset)
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, charset->values[0].string.text);
+ else
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, DefaultCharset);
+
+ if (language)
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language->values[0].string.text);
+ else
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, DefaultLanguage);
+
+ if (charset == NULL || language == NULL ||
+ (uri == NULL &&
+ con->request->request.op.operation_id != CUPS_GET_DEFAULT &&
+ con->request->request.op.operation_id != CUPS_GET_PRINTERS &&
+ con->request->request.op.operation_id != CUPS_GET_CLASSES &&
+ con->request->request.op.operation_id != CUPS_GET_DEVICES &&
+ con->request->request.op.operation_id != CUPS_GET_PPDS))
+ {
+ /*
+ * Return an error, since attributes-charset,
+ * attributes-natural-language, and printer-uri/job-uri are required
+ * for all operations.
+ */
+
+ if (charset == NULL)
+ LogMessage(L_ERROR, "ProcessIPPRequest: missing attributes-charset attribute!");
+
+ if (language == NULL)
+ LogMessage(L_ERROR, "ProcessIPPRequest: missing attributes-natural-language attribute!");
+
+ if (uri == NULL)
+ LogMessage(L_ERROR, "ProcessIPPRequest: missing printer-uri or job-uri attribute!");
+
+ LogMessage(L_DEBUG, "Request attributes follow...");
+
+ for (attr = con->request->attrs; attr != NULL; attr = attr->next)
+ LogMessage(L_DEBUG, "attr \"%s\": group_tag = %x, value_tag = %x",
+ attr->name ? attr->name : "(null)", attr->group_tag,
+ attr->value_tag);
+
+ LogMessage(L_DEBUG, "End of attributes...");
+
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ }
+ else
+ {
+ /*
+ * OK, all the checks pass so far; make sure requesting-user-name is
+ * not "root" from a remote host...
+ */
+
+ if ((username = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME)) != NULL)
+ {
+ /*
+ * Check for root user...
+ */
+
+ if (strcmp(username->values[0].string.text, "root") == 0 &&
+ ntohl(con->http.hostaddr.sin_addr.s_addr) != 0x7f000001 &&
+ strcmp(con->username, "root") != 0)
+ {
+ /*
+ * Remote unauthenticated user masquerading as local root...
+ */
+
+ free(username->values[0].string.text);
+ username->values[0].string.text = strdup(RemoteRoot);
+ }
+ }
+
+ /*
+ * Then try processing the operation...
+ */
+
+ if (uri)
+ LogMessage(L_DEBUG2, "ProcessIPPRequest: URI=\"%s\"",
+ uri->values[0].string.text);
+
+ switch (con->request->request.op.operation_id)
+ {
+ case IPP_PRINT_JOB :
+ print_job(con, uri);
+ break;
+
+ case IPP_VALIDATE_JOB :
+ validate_job(con, uri);
+ break;
+
+ case IPP_CREATE_JOB :
+ create_job(con, uri);
+ break;
+
+ case IPP_SEND_DOCUMENT :
+ send_document(con, uri);
+ break;
+
+ case IPP_CANCEL_JOB :
+ cancel_job(con, uri);
+ break;
+
+ case IPP_GET_JOB_ATTRIBUTES :
+ get_job_attrs(con, uri);
+ break;
+
+ case IPP_GET_JOBS :
+ get_jobs(con, uri);
+ break;
+
+ case IPP_GET_PRINTER_ATTRIBUTES :
+ get_printer_attrs(con, uri);
+ break;
+
+ case IPP_HOLD_JOB :
+ hold_job(con, uri);
+ break;
+
+ case IPP_RELEASE_JOB :
+ release_job(con, uri);
+ break;
+
+ case IPP_RESTART_JOB :
+ restart_job(con, uri);
+ break;
+
+ case IPP_PAUSE_PRINTER :
+ stop_printer(con, uri);
+ break;
+
+ case IPP_RESUME_PRINTER :
+ start_printer(con, uri);
+ break;
+
+ case IPP_PURGE_JOBS :
+ cancel_all_jobs(con, uri);
+ break;
+
+ case IPP_SET_JOB_ATTRIBUTES :
+ set_job_attrs(con, uri);
+ break;
+
+ case CUPS_GET_DEFAULT :
+ get_default(con);
+ break;
+
+ case CUPS_GET_PRINTERS :
+ get_printers(con, 0);
+ break;
+
+ case CUPS_GET_CLASSES :
+ get_printers(con, CUPS_PRINTER_CLASS);
+ break;
+
+ case CUPS_ADD_PRINTER :
+ add_printer(con, uri);
+ break;
+
+ case CUPS_DELETE_PRINTER :
+ delete_printer(con, uri);
+ break;
+
+ case CUPS_ADD_CLASS :
+ add_class(con, uri);
+ break;
+
+ case CUPS_DELETE_CLASS :
+ delete_printer(con, uri);
+ break;
+
+ case CUPS_ACCEPT_JOBS :
+ case IPP_ENABLE_PRINTER :
+ accept_jobs(con, uri);
+ break;
+
+ case CUPS_REJECT_JOBS :
+ case IPP_DISABLE_PRINTER :
+ reject_jobs(con, uri);
+ break;
+
+ case CUPS_SET_DEFAULT :
+ set_default(con, uri);
+ break;
+
+ case CUPS_GET_DEVICES :
+ get_devices(con);
+ break;
+
+ case CUPS_GET_PPDS :
+ get_ppds(con);
+ break;
+
+ case CUPS_MOVE_JOB :
+ move_job(con, uri);
+ break;
+
+ default :
+ send_ipp_error(con, IPP_OPERATION_NOT_SUPPORTED);
+ }
+ }
+ }
+ }
+
+ LogMessage(L_DEBUG, "ProcessIPPRequest: %d status_code=%x",
+ con->http.fd, con->response->request.status.status_code);
+
+ if (SendHeader(con, HTTP_OK, "application/ipp"))
+ {
+#if 0
+ if (con->http.version == HTTP_1_1)
+ {
+ con->http.data_encoding = HTTP_ENCODE_CHUNKED;
+
+ httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n");
+ }
+ else
+#endif /* 0 */
+ {
+ con->http.data_encoding = HTTP_ENCODE_LENGTH;
+ con->http.data_remaining = ippLength(con->response);
+
+ httpPrintf(HTTP(con), "Content-Length: %d\r\n\r\n",
+ con->http.data_remaining);
+ }
+
+ LogMessage(L_DEBUG2, "ProcessIPPRequest: Adding fd %d to OutputSet...",
+ con->http.fd);
+
+ FD_SET(con->http.fd, OutputSet);
+
+ /*
+ * Tell the caller the response header was sent successfully...
+ */
+
+ return (1);
+ }
+ else
+ {
+ /*
+ * Tell the caller the response header could not be sent...
+ */
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'accept_jobs()' - Accept print jobs to a printer.
+ */
+
+static void
+accept_jobs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer or class URI */
+{
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ const char *name; /* Printer name */
+ printer_t *printer; /* Printer data */
+
+
+ LogMessage(L_DEBUG2, "accept_jobs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "accept_jobs: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((name = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "accept_jobs: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Accept jobs sent to the printer...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(name);
+ else
+ printer = FindPrinter(name);
+
+ printer->accepting = 1;
+ printer->state_message[0] = '\0';
+
+ AddPrinterHistory(printer);
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ SaveAllClasses();
+ else
+ SaveAllPrinters();
+
+ LogMessage(L_INFO, "Printer \'%s\' now accepting jobs (\'%s\').", name,
+ con->username);
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'add_class()' - Add a class to the system.
+ */
+
+static void
+add_class(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - URI of class */
+{
+ int i; /* Looping var */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *pclass; /* Class */
+ cups_ptype_t dtype; /* Destination type */
+ const char *dest; /* Printer or class name */
+ ipp_attribute_t *attr; /* Printer attribute */
+ int modify; /* Non-zero if we just modified */
+
+
+ LogMessage(L_DEBUG2, "add_class(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "add_class: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Do we have a valid URI?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/classes/", 9) != 0 || strlen(resource) == 9)
+ {
+ /*
+ * No, return an error...
+ */
+
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * See if the class already exists; if not, create a new class...
+ */
+
+ if ((pclass = FindClass(resource + 9)) == NULL)
+ {
+ /*
+ * Class doesn't exist; see if we have a printer of the same name...
+ */
+
+ if ((pclass = FindPrinter(resource + 9)) != NULL &&
+ !(pclass->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Yes, return an error...
+ */
+
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * No, add the pclass...
+ */
+
+ pclass = AddClass(resource + 9);
+ modify = 0;
+ }
+ else if (pclass->type & CUPS_PRINTER_IMPLICIT)
+ {
+ /*
+ * Rename the implicit class to "AnyClass" or remove it...
+ */
+
+ if (ImplicitAnyClasses)
+ {
+ SetStringf(&pclass->name, "Any%s", resource + 9);
+ SortPrinters();
+ }
+ else
+ DeletePrinter(pclass, 1);
+
+ /*
+ * Add the class as a new local class...
+ */
+
+ pclass = AddClass(resource + 9);
+ modify = 0;
+ }
+ else if (pclass->type & CUPS_PRINTER_REMOTE)
+ {
+ /*
+ * Rename the remote class to "Class"...
+ */
+
+ DeletePrinterFilters(pclass);
+ SetStringf(&pclass->name, "%s@%s", resource + 9, pclass->hostname);
+ SetPrinterAttrs(pclass);
+ SortPrinters();
+
+ /*
+ * Add the class as a new local class...
+ */
+
+ pclass = AddClass(resource + 9);
+ modify = 0;
+ }
+ else
+ modify = 1;
+
+ /*
+ * Look for attributes and copy them over as needed...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL)
+ SetString(&pclass->location, attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT)) != NULL)
+ SetString(&pclass->info, attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) != NULL)
+ {
+ LogMessage(L_INFO, "Setting %s printer-is-accepting-jobs to %d (was %d.)",
+ pclass->name, attr->values[0].boolean, pclass->accepting);
+
+ pclass->accepting = attr->values[0].boolean;
+ AddPrinterHistory(pclass);
+ }
+ if ((attr = ippFindAttribute(con->request, "printer-state", IPP_TAG_ENUM)) != NULL)
+ {
+ if (attr->values[0].integer != IPP_PRINTER_IDLE &&
+ attr->values[0].integer == IPP_PRINTER_STOPPED)
+ {
+ LogMessage(L_ERROR, "Attempt to set %s printer-state to bad value %d!",
+ pclass->name, attr->values[0].integer);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ LogMessage(L_INFO, "Setting %s printer-state to %d (was %d.)", pclass->name,
+ attr->values[0].integer, pclass->state);
+
+ SetPrinterState(pclass, (ipp_pstate_t)(attr->values[0].integer), 0);
+ }
+ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) != NULL)
+ {
+ strlcpy(pclass->state_message, attr->values[0].string.text,
+ sizeof(pclass->state_message));
+ AddPrinterHistory(pclass);
+ }
+ if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL &&
+ !Classification)
+ {
+ SetString(&pclass->job_sheets[0], attr->values[0].string.text);
+ if (attr->num_values > 1)
+ SetString(&pclass->job_sheets[1], attr->values[1].string.text);
+ else
+ SetString(&pclass->job_sheets[1], "none");
+ }
+ if ((attr = ippFindAttribute(con->request, "requesting-user-name-allowed",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ FreePrinterUsers(pclass);
+
+ pclass->deny_users = 0;
+ if (attr->value_tag == IPP_TAG_NAME &&
+ (attr->num_values > 1 ||
+ strcmp(attr->values[0].string.text, "all") != 0))
+ for (i = 0; i < attr->num_values; i ++)
+ AddPrinterUser(pclass, attr->values[i].string.text);
+ }
+ else if ((attr = ippFindAttribute(con->request, "requesting-user-name-denied",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ FreePrinterUsers(pclass);
+
+ pclass->deny_users = 1;
+ if (attr->value_tag == IPP_TAG_NAME &&
+ (attr->num_values > 1 ||
+ strcmp(attr->values[0].string.text, "none") != 0))
+ for (i = 0; i < attr->num_values; i ++)
+ AddPrinterUser(pclass, attr->values[i].string.text);
+ }
+ if ((attr = ippFindAttribute(con->request, "job-quota-period",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_class: Setting job-quota-period to %d...",
+ attr->values[0].integer);
+ FreeQuotas(pclass);
+ pclass->quota_period = attr->values[0].integer;
+ }
+ if ((attr = ippFindAttribute(con->request, "job-k-limit",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_class: Setting job-k-limit to %d...",
+ attr->values[0].integer);
+ FreeQuotas(pclass);
+ pclass->k_limit = attr->values[0].integer;
+ }
+ if ((attr = ippFindAttribute(con->request, "job-page-limit",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_class: Setting job-page-limit to %d...",
+ attr->values[0].integer);
+ FreeQuotas(pclass);
+ pclass->page_limit = attr->values[0].integer;
+ }
+
+ if ((attr = ippFindAttribute(con->request, "member-uris", IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Clear the printer array as needed...
+ */
+
+ if (pclass->num_printers > 0)
+ {
+ free(pclass->printers);
+ pclass->num_printers = 0;
+ }
+
+ /*
+ * Add each printer or class that is listed...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ /*
+ * Search for the printer or class URI...
+ */
+
+ httpSeparate(attr->values[i].string.text, method, username, host,
+ &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "add_class: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Add it to the class...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ {
+ AddPrinterToClass(pclass, FindClass(dest));
+
+ LogMessage(L_DEBUG, "add_class: Added class \"%s\" to class \"%s\"...",
+ dest, pclass->name);
+ }
+ else
+ {
+ AddPrinterToClass(pclass, FindPrinter(dest));
+
+ LogMessage(L_DEBUG, "add_class: Added printer \"%s\" to class \"%s\"...",
+ dest, pclass->name);
+ }
+ }
+ }
+
+ /*
+ * Update the printer class attributes and return...
+ */
+
+ SetPrinterAttrs(pclass);
+ SaveAllClasses();
+ CheckJobs();
+
+ WritePrintcap();
+
+ if (modify)
+ LogMessage(L_INFO, "Class \'%s\' modified by \'%s\'.", pclass->name,
+ con->username);
+ else
+ {
+ AddPrinterHistory(pclass);
+
+ LogMessage(L_INFO, "New class \'%s\' added by \'%s\'.", pclass->name,
+ con->username);
+ }
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'add_file()' - Add a file to a job.
+ */
+
+static int /* O - 0 on success, -1 on error */
+add_file(client_t *con, /* I - Connection to client */
+ job_t *job, /* I - Job to add to */
+ mime_type_t *filetype, /* I - Type of file */
+ int compression) /* I - Compression */
+{
+ mime_type_t **filetypes; /* New filetypes array... */
+ int *compressions; /* New compressions array... */
+
+
+ LogMessage(L_DEBUG2, "add_file(con=%p[%d], job=%d, filetype=%s/%s, compression=%d)\n",
+ con, con->http.fd, job->id, filetype->super, filetype->type,
+ compression);
+
+ /*
+ * Add the file to the job...
+ */
+
+ if (job->num_files == 0)
+ {
+ compressions = (int *)malloc(sizeof(int));
+ filetypes = (mime_type_t **)malloc(sizeof(mime_type_t *));
+ }
+ else
+ {
+ compressions = (int *)realloc(job->compressions,
+ (job->num_files + 1) * sizeof(int));
+ filetypes = (mime_type_t **)realloc(job->filetypes,
+ (job->num_files + 1) *
+ sizeof(mime_type_t *));
+ }
+
+ if (compressions == NULL || filetypes == NULL)
+ {
+ CancelJob(job->id, 1);
+ LogMessage(L_ERROR, "add_file: unable to allocate memory for file types!");
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return (-1);
+ }
+
+ job->compressions = compressions;
+ job->compressions[job->num_files] = compression;
+ job->filetypes = filetypes;
+ job->filetypes[job->num_files] = filetype;
+
+ job->num_files ++;
+
+ return (0);
+}
+
+
+/*
+ * 'add_job_state_reasons()' - Add the "job-state-reasons" attribute based
+ * upon the job and printer state...
+ */
+
+static void
+add_job_state_reasons(client_t *con, /* I - Client connection */
+ job_t *job) /* I - Job info */
+{
+ printer_t *dest; /* Destination printer */
+
+
+ LogMessage(L_DEBUG2, "add_job_state_reasons(%p[%d], %d)\n", con, con->http.fd,
+ job ? job->id : 0);
+
+ switch (job ? job->state->values[0].integer : IPP_JOB_CANCELLED)
+ {
+ case IPP_JOB_PENDING :
+ if (job->dtype & CUPS_PRINTER_CLASS)
+ dest = FindClass(job->dest);
+ else
+ dest = FindPrinter(job->dest);
+
+ if (dest != NULL && dest->state == IPP_PRINTER_STOPPED)
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "printer-stopped");
+ else
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "none");
+ break;
+
+ case IPP_JOB_HELD :
+ if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD) != NULL ||
+ ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME) != NULL)
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-hold-until-specified");
+ else
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-incoming");
+ break;
+
+ case IPP_JOB_PROCESSING :
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-printing");
+ break;
+
+ case IPP_JOB_STOPPED :
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-stopped");
+ break;
+
+ case IPP_JOB_CANCELLED :
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-canceled-by-user");
+ break;
+
+ case IPP_JOB_ABORTED :
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "aborted-by-system");
+ break;
+
+ case IPP_JOB_COMPLETED :
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-state-reasons", NULL, "job-completed-successfully");
+ break;
+ }
+}
+
+
+/*
+ * 'add_printer()' - Add a printer to the system.
+ */
+
+static void
+add_printer(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - URI of printer */
+{
+ int i; /* Looping var */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *printer; /* Printer/class */
+ ipp_attribute_t *attr; /* Printer attribute */
+ cups_file_t *fp; /* Script/PPD file */
+ char line[1024]; /* Line from file... */
+ char srcfile[1024], /* Source Script/PPD file */
+ dstfile[1024]; /* Destination Script/PPD file */
+ int modify; /* Non-zero if we are modifying */
+
+
+ LogMessage(L_DEBUG2, "add_printer(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "add_printer: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Do we have a valid URI?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/printers/", 10) != 0 || strlen(resource) == 10)
+ {
+ /*
+ * No, return an error...
+ */
+
+ LogMessage(L_ERROR, "add_printer: bad printer URI \"%s\"!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * See if the printer already exists; if not, create a new printer...
+ */
+
+ if ((printer = FindPrinter(resource + 10)) == NULL)
+ {
+ /*
+ * Printer doesn't exist; see if we have a class of the same name...
+ */
+
+ if ((printer = FindClass(resource + 10)) != NULL &&
+ !(printer->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Yes, return an error...
+ */
+
+ LogMessage(L_ERROR, "add_printer: \"%s\" already exists as a class!",
+ resource + 10);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * No, add the printer...
+ */
+
+ printer = AddPrinter(resource + 10);
+ modify = 0;
+ }
+ else if (printer->type & CUPS_PRINTER_IMPLICIT)
+ {
+ /*
+ * Rename the implicit printer to "AnyPrinter" or delete it...
+ */
+
+ if (ImplicitAnyClasses)
+ {
+ SetStringf(&printer->name, "Any%s", resource + 10);
+ SortPrinters();
+ }
+ else
+ DeletePrinter(printer, 1);
+
+ /*
+ * Add the printer as a new local printer...
+ */
+
+ printer = AddPrinter(resource + 10);
+ modify = 0;
+ }
+ else if (printer->type & CUPS_PRINTER_REMOTE)
+ {
+ /*
+ * Rename the remote printer to "Printer@server"...
+ */
+
+ DeletePrinterFilters(printer);
+ SetStringf(&printer->name, "%s@%s", resource + 10, printer->hostname);
+ SetPrinterAttrs(printer);
+ SortPrinters();
+
+ /*
+ * Add the printer as a new local printer...
+ */
+
+ printer = AddPrinter(resource + 10);
+ modify = 0;
+ }
+ else
+ modify = 1;
+
+ /*
+ * Look for attributes and copy them over as needed...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL)
+ SetString(&printer->location, attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT)) != NULL)
+ SetString(&printer->info, attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(con->request, "device-uri", IPP_TAG_URI)) != NULL)
+ {
+ ipp_attribute_t *device; /* Current device */
+ int methodlen; /* Length of method string */
+
+
+ /*
+ * Do we have a valid device URI?
+ */
+
+ httpSeparate(attr->values[0].string.text, method, username, host,
+ &port, resource);
+ methodlen = strlen(method);
+
+ if (strcmp(method, "file") == 0)
+ {
+ /*
+ * See if the administrator has enabled file devices...
+ */
+
+ if (!FileDevice && strcmp(resource, "/dev/null"))
+ {
+ /*
+ * File devices are disabled and the URL is not file:/dev/null...
+ */
+
+ LogMessage(L_ERROR, "add_printer: File device URIs have been disabled! "
+ "To enable, see the FileDevice directive in cupsd.conf.");
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * See if the backend is listed as a device...
+ */
+
+ for (device = ippFindAttribute(Devices, "device-uri", IPP_TAG_URI);
+ device != NULL;
+ device = ippFindNextAttribute(Devices, "device-uri", IPP_TAG_URI))
+ if (strncmp(method, device->values[0].string.text, methodlen) == 0 &&
+ (device->values[0].string.text[methodlen] == ':' ||
+ device->values[0].string.text[methodlen] == '\0'))
+ break;
+
+ if (device == NULL)
+ {
+ /*
+ * Could not find device in list!
+ */
+
+ LogMessage(L_ERROR, "add_printer: bad device-uri attribute \'%s\'!",
+ attr->values[0].string.text);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ }
+
+ LogMessage(L_INFO, "Setting %s device-uri to \"%s\" (was \"%s\".)",
+ printer->name,
+ cupsdSanitizeURI(attr->values[0].string.text, line, sizeof(line)),
+ cupsdSanitizeURI(printer->device_uri, resource, sizeof(resource)));
+
+ SetString(&printer->device_uri, attr->values[0].string.text);
+ }
+
+ if ((attr = ippFindAttribute(con->request, "printer-is-accepting-jobs", IPP_TAG_BOOLEAN)) != NULL)
+ {
+ LogMessage(L_INFO, "Setting %s printer-is-accepting-jobs to %d (was %d.)",
+ printer->name, attr->values[0].boolean, printer->accepting);
+
+ printer->accepting = attr->values[0].boolean;
+ AddPrinterHistory(printer);
+ }
+ if ((attr = ippFindAttribute(con->request, "printer-state", IPP_TAG_ENUM)) != NULL)
+ {
+ if (attr->values[0].integer != IPP_PRINTER_IDLE &&
+ attr->values[0].integer == IPP_PRINTER_STOPPED)
+ {
+ LogMessage(L_ERROR, "Attempt to set %s printer-state to bad value %d!",
+ printer->name, attr->values[0].integer);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ LogMessage(L_INFO, "Setting %s printer-state to %d (was %d.)", printer->name,
+ attr->values[0].integer, printer->state);
+
+ SetPrinterState(printer, (ipp_pstate_t)(attr->values[0].integer), 0);
+ }
+ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) != NULL)
+ {
+ strlcpy(printer->state_message, attr->values[0].string.text,
+ sizeof(printer->state_message));
+ AddPrinterHistory(printer);
+ }
+ if ((attr = ippFindAttribute(con->request, "job-sheets-default", IPP_TAG_ZERO)) != NULL &&
+ !Classification)
+ {
+ SetString(&printer->job_sheets[0], attr->values[0].string.text);
+ if (attr->num_values > 1)
+ SetString(&printer->job_sheets[1], attr->values[1].string.text);
+ else
+ SetString(&printer->job_sheets[1], "none");
+ }
+ if ((attr = ippFindAttribute(con->request, "requesting-user-name-allowed",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ FreePrinterUsers(printer);
+
+ printer->deny_users = 0;
+ if (attr->value_tag == IPP_TAG_NAME &&
+ (attr->num_values > 1 ||
+ strcmp(attr->values[0].string.text, "all") != 0))
+ for (i = 0; i < attr->num_values; i ++)
+ AddPrinterUser(printer, attr->values[i].string.text);
+ }
+ else if ((attr = ippFindAttribute(con->request, "requesting-user-name-denied",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ FreePrinterUsers(printer);
+
+ printer->deny_users = 1;
+ if (attr->value_tag == IPP_TAG_NAME &&
+ (attr->num_values > 1 ||
+ strcmp(attr->values[0].string.text, "none") != 0))
+ for (i = 0; i < attr->num_values; i ++)
+ AddPrinterUser(printer, attr->values[i].string.text);
+ }
+ if ((attr = ippFindAttribute(con->request, "job-quota-period",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_printer: Setting job-quota-period to %d...",
+ attr->values[0].integer);
+ FreeQuotas(printer);
+ printer->quota_period = attr->values[0].integer;
+ }
+ if ((attr = ippFindAttribute(con->request, "job-k-limit",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_printer: Setting job-k-limit to %d...",
+ attr->values[0].integer);
+ FreeQuotas(printer);
+ printer->k_limit = attr->values[0].integer;
+ }
+ if ((attr = ippFindAttribute(con->request, "job-page-limit",
+ IPP_TAG_INTEGER)) != NULL)
+ {
+ LogMessage(L_DEBUG, "add_printer: Setting job-page-limit to %d...",
+ attr->values[0].integer);
+ FreeQuotas(printer);
+ printer->page_limit = attr->values[0].integer;
+ }
+
+ /*
+ * See if we have all required attributes...
+ */
+
+ if (!printer->device_uri)
+ SetString(&printer->device_uri, "file:/dev/null");
+
+ /*
+ * See if we have an interface script or PPD file attached to the request...
+ */
+
+ if (con->filename)
+ {
+ strlcpy(srcfile, con->filename, sizeof(srcfile));
+
+ if ((fp = cupsFileOpen(srcfile, "rb")) != NULL)
+ {
+ /*
+ * Yes; get the first line from it...
+ */
+
+ line[0] = '\0';
+ cupsFileGets(fp, line, sizeof(line));
+ cupsFileClose(fp);
+
+ /*
+ * Then see what kind of file it is...
+ */
+
+ snprintf(dstfile, sizeof(dstfile), "%s/interfaces/%s", ServerRoot,
+ printer->name);
+
+ if (strncmp(line, "*PPD-Adobe", 10) == 0)
+ {
+ /*
+ * The new file is a PPD file, so remove any old interface script
+ * that might be lying around...
+ */
+
+ unlink(dstfile);
+ }
+ else
+ {
+ /*
+ * This must be an interface script, so move the file over to the
+ * interfaces directory and make it executable...
+ */
+
+ if (copy_file(srcfile, dstfile))
+ {
+ LogMessage(L_ERROR, "add_printer: Unable to copy interface script from %s to %s - %s!",
+ srcfile, dstfile, strerror(errno));
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ else
+ {
+ LogMessage(L_DEBUG, "add_printer: Copied interface script successfully!");
+ chmod(dstfile, 0755);
+ }
+ }
+
+ snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
+ printer->name);
+
+ if (strncmp(line, "*PPD-Adobe", 10) == 0)
+ {
+ /*
+ * The new file is a PPD file, so move the file over to the
+ * ppd directory and make it readable by all...
+ */
+
+ if (copy_file(srcfile, dstfile))
+ {
+ LogMessage(L_ERROR, "add_printer: Unable to copy PPD file from %s to %s - %s!",
+ srcfile, dstfile, strerror(errno));
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ else
+ {
+ LogMessage(L_DEBUG, "add_printer: Copied PPD file successfully!");
+ chmod(dstfile, 0644);
+ }
+ }
+ else
+ {
+ /*
+ * This must be an interface script, so remove any old PPD file that
+ * may be lying around...
+ */
+
+ unlink(dstfile);
+ }
+ }
+ }
+ else if ((attr = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME)) != NULL)
+ {
+ if (strcmp(attr->values[0].string.text, "raw") == 0)
+ {
+ /*
+ * Raw driver, remove any existing PPD or interface script files.
+ */
+
+ snprintf(dstfile, sizeof(dstfile), "%s/interfaces/%s", ServerRoot,
+ printer->name);
+ unlink(dstfile);
+
+ snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
+ printer->name);
+ unlink(dstfile);
+ }
+ else
+ {
+ /*
+ * PPD model file...
+ */
+
+ snprintf(srcfile, sizeof(srcfile), "%s/model/%s", DataDir,
+ attr->values[0].string.text);
+
+ snprintf(dstfile, sizeof(dstfile), "%s/interfaces/%s", ServerRoot,
+ printer->name);
+ unlink(dstfile);
+
+ snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot,
+ printer->name);
+
+ if (copy_model(srcfile, dstfile))
+ {
+ LogMessage(L_ERROR, "add_printer: Unable to copy PPD file from %s to %s - %s!",
+ srcfile, dstfile, strerror(errno));
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+ else
+ {
+ LogMessage(L_DEBUG, "add_printer: Copied PPD file successfully!");
+ chmod(dstfile, 0644);
+ }
+ }
+ }
+
+ /*
+ * Make this printer the default if there is none...
+ */
+
+ if (DefaultPrinter == NULL)
+ DefaultPrinter = printer;
+
+ /*
+ * Update the printer attributes and return...
+ */
+
+ SetPrinterAttrs(printer);
+ SaveAllPrinters();
+
+ if (printer->job != NULL)
+ {
+ job_t *job;
+
+ /*
+ * Stop the current job and then restart it below...
+ */
+
+ job = (job_t *)printer->job;
+
+ StopJob(job->id, 1);
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ }
+
+ CheckJobs();
+
+ WritePrintcap();
+
+ if (modify)
+ LogMessage(L_INFO, "Printer \'%s\' modified by \'%s\'.", printer->name,
+ con->username);
+ else
+ {
+ AddPrinterHistory(printer);
+
+ LogMessage(L_INFO, "New printer \'%s\' added by \'%s\'.", printer->name,
+ con->username);
+ }
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'add_printer_state_reasons()' - Add the "printer-state-reasons" attribute
+ * based upon the printer state...
+ */
+
+static void
+add_printer_state_reasons(client_t *con, /* I - Client connection */
+ printer_t *p) /* I - Printer info */
+{
+ LogMessage(L_DEBUG2, "add_printer_state_reasons(%p[%d], %p[%s])\n",
+ con, con->http.fd, p, p->name);
+
+ if (p->num_reasons == 0)
+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", NULL,
+ p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
+ else
+ ippAddStrings(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", p->num_reasons, NULL,
+ (const char * const *)p->reasons);
+}
+
+
+/*
+ * 'add_queued_job_count()' - Add the "queued-job-count" attribute for
+ * the specified printer or class.
+ */
+
+static void
+add_queued_job_count(client_t *con, /* I - Client connection */
+ printer_t *p) /* I - Printer or class */
+{
+ int count; /* Number of jobs on destination */
+
+
+ LogMessage(L_DEBUG2, "add_queued_job_count(%p[%d], %p[%s])\n",
+ con, con->http.fd, p, p->name);
+
+ count = GetPrinterJobCount(p->name);
+
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "queued-job-count", count);
+}
+
+
+/*
+ * 'cancel_all_jobs()' - Cancel all print jobs.
+ */
+
+static void
+cancel_all_jobs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job or Printer URI */
+{
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ userpass[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ ipp_attribute_t *attr; /* Attribute in request */
+ const char *username; /* Username */
+ int purge; /* Purge? */
+
+
+ LogMessage(L_DEBUG2, "cancel_all_jobs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "cancel_all_jobs: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") != 0)
+ {
+ LogMessage(L_ERROR, "cancel_all_jobs: bad %s attribute \'%s\'!",
+ uri->name, uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * Get the username (if any) for the jobs we want to cancel (only if
+ * "my-jobs" is specified...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL &&
+ attr->values[0].boolean)
+ {
+ if ((attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME)) != NULL)
+ username = attr->values[0].string.text;
+ else
+ {
+ LogMessage(L_ERROR, "cancel_all_jobs: missing requesting-user-name attribute!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+ }
+ else
+ username = NULL;
+
+ /*
+ * Look for the "purge-jobs" attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "purge-jobs", IPP_TAG_BOOLEAN)) != NULL)
+ purge = attr->values[0].boolean;
+ else
+ purge = 1;
+
+ /*
+ * And if the destination is valid...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, userpass, host, &port,
+ resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI?
+ */
+
+ if (strcmp(resource, "/printers/") != 0)
+ {
+ LogMessage(L_ERROR, "cancel_all_jobs: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Cancel all jobs on all printers...
+ */
+
+ CancelJobs(NULL, username, purge);
+
+ LogMessage(L_INFO, "All jobs were %s by \'%s\'.",
+ purge ? "purged" : "cancelled", con->username);
+ }
+ else
+ {
+ /*
+ * Cancel all of the jobs on the named printer...
+ */
+
+ CancelJobs(dest, username, purge);
+
+ LogMessage(L_INFO, "All jobs on \'%s\' were %s by \'%s\'.", dest,
+ purge ? "purged" : "cancelled", con->username);
+ }
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'cancel_job()' - Cancel a print job.
+ */
+
+static void
+cancel_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job or Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ int jobid; /* Job ID */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ job_t *job; /* Job information */
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ printer_t *printer; /* Printer data */
+
+
+ LogMessage(L_DEBUG2, "cancel_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/jobs/", 5) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "cancel_job: cancel request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "cancel_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ if ((jobid = attr->values[0].integer) == 0)
+ {
+ /*
+ * Find the current job on the specified printer...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "cancel_job: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(dest);
+ else
+ printer = FindPrinter(dest);
+
+ /*
+ * See if the printer is currently printing a job...
+ */
+
+ if (printer->job)
+ jobid = ((job_t *)printer->job)->id;
+ else
+ {
+ /*
+ * No, see if there are any pending jobs...
+ */
+
+ for (job = Jobs; job != NULL; job = job->next)
+ if (job->state->values[0].integer <= IPP_JOB_PROCESSING &&
+ strcasecmp(job->dest, dest) == 0)
+ break;
+
+ if (job != NULL)
+ jobid = job->id;
+ else
+ {
+ LogMessage(L_ERROR, "cancel_job: No active jobs on %s!", dest);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "cancel_job: bad job-uri attribute \'%s\'!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "cancel_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "cancel_job: \"%s\" not authorized to delete job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * See if the job is already completed, cancelled, or aborted; if so,
+ * we can't cancel...
+ */
+
+ if (job->state->values[0].integer >= IPP_JOB_CANCELLED)
+ {
+ LogMessage(L_ERROR, "cancel_job: job id %d is %s - can't cancel!",
+ jobid,
+ job->state->values[0].integer == IPP_JOB_CANCELLED ? "cancelled" :
+ job->state->values[0].integer == IPP_JOB_ABORTED ? "aborted" :
+ "completed");
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * Cancel the job and return...
+ */
+
+ CancelJob(jobid, 0);
+ CheckJobs();
+
+ LogMessage(L_INFO, "Job %d was cancelled by \'%s\'.", jobid, username);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'check_quotas()' - Check quotas for a printer and user.
+ */
+
+static int /* O - 1 if OK, 0 if not */
+check_quotas(client_t *con, /* I - Client connection */
+ printer_t *p) /* I - Printer or class */
+{
+ int i, j; /* Looping vars */
+ ipp_attribute_t *attr; /* Current attribute */
+ char username[33]; /* Username */
+ quota_t *q; /* Quota data */
+ struct passwd *pw; /* User password data */
+ struct group *grp; /* Group data */
+
+
+ LogMessage(L_DEBUG2, "check_quotas(%p[%d], %p[%s])\n",
+ con, con->http.fd, p, p->name);
+
+ /*
+ * Check input...
+ */
+
+ if (con == NULL || p == NULL)
+ return (0);
+
+ /*
+ * Figure out who is printing...
+ */
+
+ attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME);
+
+ if (con->username[0])
+ strlcpy(username, con->username, sizeof(username));
+ else if (attr != NULL)
+ {
+ LogMessage(L_DEBUG, "check_quotas: requesting-user-name = \'%s\'",
+ attr->values[0].string.text);
+
+ strlcpy(username, attr->values[0].string.text, sizeof(username));
+ }
+ else
+ strcpy(username, "anonymous");
+
+ /*
+ * Check global active job limits for printers and users...
+ */
+
+ if (MaxJobsPerPrinter)
+ {
+ /*
+ * Check if there are too many pending jobs on this printer...
+ */
+
+ if (GetPrinterJobCount(p->name) >= MaxJobsPerPrinter)
+ {
+ LogMessage(L_INFO, "Too many jobs for printer \"%s\"...", p->name);
+ return (0);
+ }
+ }
+
+ if (MaxJobsPerUser)
+ {
+ /*
+ * Check if there are too many pending jobs for this user...
+ */
+
+ if (GetUserJobCount(username) >= MaxJobsPerUser)
+ {
+ LogMessage(L_INFO, "Too many jobs for user \"%s\"...", username);
+ return (0);
+ }
+ }
+
+ /*
+ * Check against users...
+ */
+
+ if (p->num_users == 0 && p->k_limit == 0 && p->page_limit == 0)
+ return (1);
+
+ if (p->num_users)
+ {
+ pw = getpwnam(username);
+ endpwent();
+
+ for (i = 0; i < p->num_users; i ++)
+ if (p->users[i][0] == '@')
+ {
+ /*
+ * Check group membership...
+ */
+
+ grp = getgrnam(p->users[i] + 1);
+ endgrent();
+
+ if (grp)
+ {
+ /*
+ * Check primary group...
+ */
+
+ if (pw && grp->gr_gid == pw->pw_gid)
+ break;
+
+ /*
+ * Check usernames in group...
+ */
+
+ for (j = 0; grp->gr_mem[j]; j ++)
+ if (!strcasecmp(username, grp->gr_mem[j]))
+ break;
+
+ if (grp->gr_mem[j])
+ break;
+ }
+ }
+ else if (!strcasecmp(username, p->users[i]))
+ break;
+
+ if ((i < p->num_users) == p->deny_users)
+ {
+ LogMessage(L_INFO, "Denying user \"%s\" access to printer \"%s\"...",
+ username, p->name);
+ return (0);
+ }
+ }
+
+ /*
+ * Check quotas...
+ */
+
+ if (p->k_limit || p->page_limit)
+ {
+ if ((q = UpdateQuota(p, username, 0, 0)) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to allocate quota data for user \"%s\"!",
+ username);
+ return (0);
+ }
+
+ if ((q->k_count >= p->k_limit && p->k_limit) ||
+ (q->page_count >= p->page_limit && p->page_limit))
+ {
+ LogMessage(L_INFO, "User \"%s\" is over the quota limit...",
+ username);
+ return (0);
+ }
+ }
+
+ /*
+ * If we have gotten this far, we're done!
+ */
+
+ return (1);
+}
+
+
+/*
+ * 'copy_attribute()' - Copy a single attribute.
+ */
+
+static ipp_attribute_t * /* O - New attribute */
+copy_attribute(ipp_t *to, /* O - Destination request/response */
+ ipp_attribute_t *attr, /* I - Attribute to copy */
+ int quickcopy)/* I - Do a quick copy? */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *toattr; /* Destination attribute */
+
+
+ LogMessage(L_DEBUG2, "copy_attribute(%p, %p[%s,%x,%x])\n", to, attr,
+ attr->name ? attr->name : "(null)", attr->group_tag,
+ attr->value_tag);
+
+ switch (attr->value_tag & ~IPP_TAG_COPY)
+ {
+ case IPP_TAG_ZERO :
+ toattr = ippAddSeparator(to);
+ break;
+
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag,
+ attr->name, attr->num_values, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ toattr->values[i].integer = attr->values[i].integer;
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ toattr = ippAddBooleans(to, attr->group_tag, attr->name,
+ attr->num_values, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ toattr->values[i].boolean = attr->values[i].boolean;
+ break;
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ toattr = ippAddStrings(to, attr->group_tag,
+ (ipp_tag_t)(attr->value_tag | quickcopy),
+ attr->name, attr->num_values, NULL, NULL);
+
+ if (quickcopy)
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ toattr->values[i].string.text = attr->values[i].string.text;
+ }
+ else
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ toattr->values[i].string.text = strdup(attr->values[i].string.text);
+ }
+ break;
+
+ case IPP_TAG_DATE :
+ toattr = ippAddDate(to, attr->group_tag, attr->name,
+ attr->values[0].date);
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ toattr = ippAddResolutions(to, attr->group_tag, attr->name,
+ attr->num_values, IPP_RES_PER_INCH,
+ NULL, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ toattr->values[i].resolution.xres = attr->values[i].resolution.xres;
+ toattr->values[i].resolution.yres = attr->values[i].resolution.yres;
+ toattr->values[i].resolution.units = attr->values[i].resolution.units;
+ }
+ break;
+
+ case IPP_TAG_RANGE :
+ toattr = ippAddRanges(to, attr->group_tag, attr->name,
+ attr->num_values, NULL, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ toattr->values[i].range.lower = attr->values[i].range.lower;
+ toattr->values[i].range.upper = attr->values[i].range.upper;
+ }
+ break;
+
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ toattr = ippAddStrings(to, attr->group_tag,
+ (ipp_tag_t)(attr->value_tag | quickcopy),
+ attr->name, attr->num_values, NULL, NULL);
+
+ if (quickcopy)
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ toattr->values[i].string.charset = attr->values[i].string.charset;
+ toattr->values[i].string.text = attr->values[i].string.text;
+ }
+ }
+ else
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (!i)
+ toattr->values[i].string.charset =
+ strdup(attr->values[i].string.charset);
+ else
+ toattr->values[i].string.charset =
+ toattr->values[0].string.charset;
+
+ toattr->values[i].string.text = strdup(attr->values[i].string.text);
+ }
+ }
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ toattr = ippAddCollections(to, attr->group_tag, attr->name,
+ attr->num_values, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ toattr->values[i].collection = ippNew();
+ copy_attrs(toattr->values[i].collection, attr->values[i].collection,
+ NULL, IPP_TAG_ZERO, 0);
+ }
+ break;
+
+ default :
+ toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag,
+ attr->name, attr->num_values, NULL);
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ toattr->values[i].unknown.length = attr->values[i].unknown.length;
+
+ if (toattr->values[i].unknown.length > 0)
+ {
+ if ((toattr->values[i].unknown.data = malloc(toattr->values[i].unknown.length)) == NULL)
+ toattr->values[i].unknown.length = 0;
+ else
+ memcpy(toattr->values[i].unknown.data,
+ attr->values[i].unknown.data,
+ toattr->values[i].unknown.length);
+ }
+ }
+ break; /* anti-compiler-warning-code */
+ }
+
+ return (toattr);
+}
+
+
+/*
+ * 'copy_attrs()' - Copy attributes from one request to another.
+ */
+
+static void
+copy_attrs(ipp_t *to, /* I - Destination request */
+ ipp_t *from, /* I - Source request */
+ ipp_attribute_t *req, /* I - Requested attributes */
+ ipp_tag_t group, /* I - Group to copy */
+ int quickcopy) /* I - Do a quick copy? */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *fromattr; /* Source attribute */
+
+
+ LogMessage(L_DEBUG2, "copy_attrs(%p, %p, %p, %x)\n", to, from, req, group);
+
+ if (to == NULL || from == NULL)
+ return;
+
+ if (req != NULL && strcmp(req->values[0].string.text, "all") == 0)
+ req = NULL; /* "all" means no filter... */
+
+ for (fromattr = from->attrs; fromattr != NULL; fromattr = fromattr->next)
+ {
+ /*
+ * Filter attributes as needed...
+ */
+
+ if (group != IPP_TAG_ZERO && fromattr->group_tag != group &&
+ fromattr->group_tag != IPP_TAG_ZERO)
+ continue;
+
+ if (req != NULL && fromattr->name != NULL)
+ {
+ for (i = 0; i < req->num_values; i ++)
+ if (strcmp(fromattr->name, req->values[i].string.text) == 0)
+ break;
+
+ if (i == req->num_values)
+ continue;
+ }
+
+ copy_attribute(to, fromattr, quickcopy);
+ }
+}
+
+
+/*
+ * 'copy_banner()' - Copy a banner file to the requests directory for the
+ * specified job.
+ */
+
+static int /* O - Size of banner file in kbytes */
+copy_banner(client_t *con, /* I - Client connection */
+ job_t *job, /* I - Job information */
+ const char *name) /* I - Name of banner */
+{
+ int i; /* Looping var */
+ int kbytes; /* Size of banner file in kbytes */
+ char filename[1024]; /* Job filename */
+ banner_t *banner; /* Pointer to banner */
+ cups_file_t *in; /* Input file */
+ cups_file_t *out; /* Output file */
+ int ch; /* Character from file */
+ char attrname[255], /* Name of attribute */
+ *s; /* Pointer into name */
+ ipp_attribute_t *attr; /* Attribute */
+
+
+ LogMessage(L_DEBUG2, "copy_banner(%p[%d], %p[%d], %s)",
+ con, con->http.fd, job, job->id, name ? name : "(null)");
+
+ /*
+ * Find the banner; return if not found or "none"...
+ */
+
+ if (name == NULL ||
+ strcmp(name, "none") == 0 ||
+ (banner = FindBanner(name)) == NULL)
+ return (0);
+
+ /*
+ * Open the banner and job files...
+ */
+
+ if (add_file(con, job, banner->filetype, 0))
+ return (0);
+
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id,
+ job->num_files);
+ if ((out = cupsFileOpen(filename, "w")) == NULL)
+ {
+ LogMessage(L_ERROR, "copy_banner: Unable to create banner job file %s - %s",
+ filename, strerror(errno));
+ job->num_files --;
+ return (0);
+ }
+
+ fchmod(cupsFileNumber(out), 0640);
+ fchown(cupsFileNumber(out), RunUser, Group);
+
+ if (con->language)
+ {
+ /*
+ * Try the localized banner file under the subdirectory...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
+ con->language->language, name);
+
+ if (access(filename, 0) && con->language->language[2])
+ {
+ /*
+ * Wasn't able to find "ll_CC" locale file; try the non-national
+ * localization banner directory.
+ */
+
+ attrname[0] = con->language->language[0];
+ attrname[1] = con->language->language[1];
+ attrname[2] = '\0';
+
+ snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir,
+ attrname, name);
+ }
+
+ if (access(filename, 0))
+ {
+ /*
+ * Use the non-localized banner file.
+ */
+
+ snprintf(filename, sizeof(filename), "%s/banners/%s", DataDir, name);
+ }
+ }
+ else
+ {
+ /*
+ * Use the non-localized banner file.
+ */
+
+ snprintf(filename, sizeof(filename), "%s/banners/%s", DataDir, name);
+ }
+
+ if ((in = cupsFileOpen(filename, "r")) == NULL)
+ {
+ cupsFileClose(out);
+ unlink(filename);
+ LogMessage(L_ERROR, "copy_banner: Unable to open banner template file %s - %s",
+ filename, strerror(errno));
+ job->num_files --;
+ return (0);
+ }
+
+ /*
+ * Parse the file to the end...
+ */
+
+ while ((ch = cupsFileGetChar(in)) != EOF)
+ if (ch == '{')
+ {
+ /*
+ * Get an attribute name...
+ */
+
+ for (s = attrname; (ch = cupsFileGetChar(in)) != EOF;)
+ if (!isalpha(ch & 255) && ch != '-' && ch != '?')
+ break;
+ else if (s < (attrname + sizeof(attrname) - 1))
+ *s++ = ch;
+ else
+ break;
+
+ *s = '\0';
+
+ if (ch != '}')
+ {
+ /*
+ * Ignore { followed by stuff that is not an attribute name...
+ */
+
+ cupsFilePrintf(out, "{%s%c", attrname, ch);
+ continue;
+ }
+
+ /*
+ * See if it is defined...
+ */
+
+ if (attrname[0] == '?')
+ s = attrname + 1;
+ else
+ s = attrname;
+
+ if (strcmp(s, "printer-name") == 0)
+ {
+ cupsFilePuts(out, job->dest);
+ continue;
+ }
+ else if ((attr = ippFindAttribute(job->attrs, s, IPP_TAG_ZERO)) == NULL)
+ {
+ /*
+ * See if we have a leading question mark...
+ */
+
+ if (attrname[0] != '?')
+ {
+ /*
+ * Nope, write to file as-is; probably a PostScript procedure...
+ */
+
+ cupsFilePrintf(out, "{%s}", attrname);
+ }
+
+ continue;
+ }
+
+ /*
+ * Output value(s)...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (i)
+ cupsFilePutChar(out, ',');
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ if (strncmp(s, "time-at-", 8) == 0)
+ cupsFilePuts(out, GetDateTime(attr->values[i].integer));
+ else
+ cupsFilePrintf(out, "%d", attr->values[i].integer);
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ cupsFilePrintf(out, "%d", attr->values[i].boolean);
+ break;
+
+ case IPP_TAG_NOVALUE :
+ cupsFilePuts(out, "novalue");
+ break;
+
+ case IPP_TAG_RANGE :
+ cupsFilePrintf(out, "%d-%d", attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ cupsFilePrintf(out, "%dx%d%s", attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ break;
+
+ case IPP_TAG_URI :
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ if (strcasecmp(banner->filetype->type, "postscript") == 0)
+ {
+ /*
+ * Need to quote strings for PS banners...
+ */
+
+ const char *p;
+
+ for (p = attr->values[i].string.text; *p; p ++)
+ {
+ if (*p == '(' || *p == ')' || *p == '\\')
+ {
+ cupsFilePutChar(out, '\\');
+ cupsFilePutChar(out, *p);
+ }
+ else if (*p < 32 || *p > 126)
+ cupsFilePrintf(out, "\\%03o", *p & 255);
+ else
+ cupsFilePutChar(out, *p);
+ }
+ }
+ else
+ cupsFilePuts(out, attr->values[i].string.text);
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+ }
+ }
+ else if (ch == '\\') /* Quoted char */
+ {
+ ch = cupsFileGetChar(in);
+
+ if (ch != '{') /* Only do special handling for \{ */
+ cupsFilePutChar(out, '\\');
+
+ cupsFilePutChar(out, ch);
+ }
+ else
+ cupsFilePutChar(out, ch);
+
+ cupsFileClose(in);
+
+ kbytes = (cupsFileTell(out) + 1023) / 1024;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
+ attr->values[0].integer += kbytes;
+
+ cupsFileClose(out);
+
+ return (kbytes);
+}
+
+
+/*
+ * 'copy_file()' - Copy a PPD file or interface script...
+ */
+
+static int /* O - 0 = success, -1 = error */
+copy_file(const char *from, /* I - Source file */
+ const char *to) /* I - Destination file */
+{
+ cups_file_t *src, /* Source file */
+ *dst; /* Destination file */
+ int bytes; /* Bytes to read/write */
+ char buffer[2048]; /* Copy buffer */
+
+
+ LogMessage(L_DEBUG2, "copy_file(\"%s\", \"%s\")\n", from, to);
+
+ /*
+ * Open the source and destination file for a copy...
+ */
+
+ if ((src = cupsFileOpen(from, "rb")) == NULL)
+ return (-1);
+
+ if ((dst = cupsFileOpen(to, "wb")) == NULL)
+ {
+ cupsFileClose(src);
+ return (-1);
+ }
+
+ /*
+ * Copy the source file to the destination...
+ */
+
+ while ((bytes = cupsFileRead(src, buffer, sizeof(buffer))) > 0)
+ if (cupsFileWrite(dst, buffer, bytes) < bytes)
+ {
+ cupsFileClose(src);
+ cupsFileClose(dst);
+ return (-1);
+ }
+
+ /*
+ * Close both files and return...
+ */
+
+ cupsFileClose(src);
+
+ return (cupsFileClose(dst));
+}
+
+
+/*
+ * 'copy_model()' - Copy a PPD model file, substituting default values
+ * as needed...
+ */
+
+static int /* O - 0 = success, -1 = error */
+copy_model(const char *from, /* I - Source file */
+ const char *to) /* I - Destination file */
+{
+ cups_file_t *src, /* Source file */
+ *dst; /* Destination file */
+ char buffer[2048]; /* Copy buffer */
+ int i; /* Looping var */
+ char option[PPD_MAX_NAME], /* Option name */
+ choice[PPD_MAX_NAME]; /* Choice name */
+ int num_defaults; /* Number of default options */
+ ppd_default_t *defaults; /* Default options */
+ char cups_protocol[PPD_MAX_LINE];
+ /* cupsProtocol attribute */
+#ifdef HAVE_LIBPAPER
+ char *paper_result; /* Paper size name from libpaper */
+ char system_paper[64]; /* Paper size name buffer */
+#endif /* HAVE_LIBPAPER */
+
+
+ LogMessage(L_DEBUG2, "copy_model(\"%s\", \"%s\")\n", from, to);
+
+ /*
+ * Open the destination (if possible) and set the default options...
+ */
+
+ num_defaults = 0;
+ defaults = NULL;
+ cups_protocol[0] = '\0';
+
+ if ((dst = cupsFileOpen(to, "rb")) != NULL)
+ {
+ /*
+ * Read all of the default lines from the old PPD...
+ */
+
+ while (cupsFileGets(dst, buffer, sizeof(buffer)) != NULL)
+ if (!strncmp(buffer, "*Default", 8))
+ {
+ /*
+ * Add the default option...
+ */
+
+ if (!ppd_parse_line(buffer, option, sizeof(option),
+ choice, sizeof(choice)))
+ num_defaults = ppd_add_default(option, choice, num_defaults,
+ &defaults);
+ }
+ else if (!strncmp(buffer, "*cupsProtocol:", 14))
+ strlcpy(cups_protocol, buffer, sizeof(cups_protocol));
+
+ cupsFileClose(dst);
+ }
+#ifdef HAVE_LIBPAPER
+ else if ((paper_result = systempapername()) != NULL)
+ {
+ /*
+ * Set the default media sizes from the systemwide default...
+ */
+
+ strlcpy(system_paper, paper_result, sizeof(system_paper));
+ system_paper[0] = toupper(system_paper[0] & 255);
+
+ num_defaults = ppd_add_default("PageSize", system_paper,
+ num_defaults, &defaults);
+ num_defaults = ppd_add_default("PageRegion", system_paper,
+ num_defaults, &defaults);
+ num_defaults = ppd_add_default("PaperDimension", system_paper,
+ num_defaults, &defaults);
+ num_defaults = ppd_add_default("ImageableArea", system_paper,
+ num_defaults, &defaults);
+ }
+#endif /* HAVE_LIBPAPER */
+ else
+ {
+ /*
+ * Add the default media sizes...
+ *
+ * Note: These values are generally not valid for large-format devices
+ * like plotters, however it is probably safe to say that those
+ * users will configure the media size after initially adding
+ * the device anyways...
+ */
+
+ if (!DefaultLanguage ||
+ !strcasecmp(DefaultLanguage, "C") ||
+ !strcasecmp(DefaultLanguage, "POSIX") ||
+ !strcasecmp(DefaultLanguage, "en") ||
+ !strncasecmp(DefaultLanguage, "en_US", 5) ||
+ !strncasecmp(DefaultLanguage, "en_CA", 5) ||
+ !strncasecmp(DefaultLanguage, "fr_CA", 5))
+ {
+ /*
+ * These are the only locales that will default to "letter" size...
+ */
+
+ num_defaults = ppd_add_default("PageSize", "Letter", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("PageRegion", "Letter", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("PaperDimension", "Letter", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("ImageableArea", "Letter", num_defaults,
+ &defaults);
+ }
+ else
+ {
+ /*
+ * The rest default to "a4" size...
+ */
+
+ num_defaults = ppd_add_default("PageSize", "A4", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("PageRegion", "A4", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("PaperDimension", "A4", num_defaults,
+ &defaults);
+ num_defaults = ppd_add_default("ImageableArea", "A4", num_defaults,
+ &defaults);
+ }
+ }
+
+ /*
+ * Open the source and destination file for a copy...
+ */
+
+ if ((src = cupsFileOpen(from, "rb")) == NULL)
+ {
+ if (num_defaults > 0)
+ free(defaults);
+
+ return (-1);
+ }
+
+ if ((dst = cupsFileOpen(to, "wb")) == NULL)
+ {
+ if (num_defaults > 0)
+ free(defaults);
+
+ cupsFileClose(src);
+ return (-1);
+ }
+
+ /*
+ * Copy the source file to the destination...
+ */
+
+ while (cupsFileGets(src, buffer, sizeof(buffer)) != NULL)
+ {
+ if (!strncmp(buffer, "*Default", 8))
+ {
+ /*
+ * Check for an previous default option choice...
+ */
+
+ if (!ppd_parse_line(buffer, option, sizeof(option),
+ choice, sizeof(choice)))
+ {
+ for (i = 0; i < num_defaults; i ++)
+ if (!strcmp(option, defaults[i].option))
+ {
+ /*
+ * Substitute the previous choice...
+ */
+
+ snprintf(buffer, sizeof(buffer), "*Default%s: %s", option,
+ defaults[i].choice);
+ break;
+ }
+ }
+ }
+
+ cupsFilePrintf(dst, "%s\n", buffer);
+ }
+
+ if (cups_protocol[0])
+ cupsFilePrintf(dst, "%s\n", cups_protocol);
+
+ if (num_defaults > 0)
+ free(defaults);
+
+ /*
+ * Close both files and return...
+ */
+
+ cupsFileClose(src);
+
+ return (cupsFileClose(dst));
+}
+
+
+/*
+ * 'create_job()' - Print a file to a printer or class.
+ */
+
+static void
+create_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ int priority; /* Job priority */
+ char *title; /* Job name/title */
+ job_t *job; /* Current job */
+ char job_uri[HTTP_MAX_URI],
+ /* Job URI */
+ printer_uri[HTTP_MAX_URI],
+ /* Printer URI */
+ method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *printer; /* Printer data */
+ int kbytes; /* Size of print file */
+ int i; /* Looping var */
+ int lowerpagerange; /* Page range bound */
+
+
+ LogMessage(L_DEBUG2, "create_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "create_job: cancel request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "create_job: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the printer is accepting jobs...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ {
+ printer = FindClass(dest);
+ snprintf(printer_uri, sizeof(printer_uri), "http://%s:%d/classes/%s",
+ ServerName, ntohs(con->http.hostaddr.sin_port), dest);
+ }
+ else
+ {
+ printer = FindPrinter(dest);
+
+ snprintf(printer_uri, sizeof(printer_uri), "http://%s:%d/printers/%s",
+ ServerName, ntohs(con->http.hostaddr.sin_port), dest);
+ }
+
+ if (!printer->accepting)
+ {
+ LogMessage(L_INFO, "create_job: destination \'%s\' is not accepting jobs.",
+ dest);
+ send_ipp_error(con, IPP_NOT_ACCEPTING);
+ return;
+ }
+
+ /*
+ * Validate job template attributes; for now just copies and page-ranges...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "copies", IPP_TAG_INTEGER)) != NULL)
+ {
+ if (attr->values[0].integer < 1 || attr->values[0].integer > MaxCopies)
+ {
+ LogMessage(L_INFO, "create_job: bad copies value %d.",
+ attr->values[0].integer);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+ }
+
+ if ((attr = ippFindAttribute(con->request, "page-ranges", IPP_TAG_RANGE)) != NULL)
+ {
+ for (i = 0, lowerpagerange = 1; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].range.lower < lowerpagerange ||
+ attr->values[i].range.lower > attr->values[i].range.upper)
+ {
+ LogMessage(L_ERROR, "create_job: bad page-ranges values %d-%d.",
+ attr->values[i].range.lower, attr->values[i].range.upper);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ lowerpagerange = attr->values[i].range.upper + 1;
+ }
+ }
+
+ /*
+ * Make sure we aren't over our limit...
+ */
+
+ if (NumJobs >= MaxJobs && MaxJobs)
+ CleanJobs();
+
+ if (NumJobs >= MaxJobs && MaxJobs)
+ {
+ LogMessage(L_INFO, "create_job: too many jobs.");
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ if (!check_quotas(con, printer))
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * Set all but the first two attributes to the job attributes group...
+ */
+
+ for (attr = con->request->attrs->next->next; attr; attr = attr->next)
+ attr->group_tag = IPP_TAG_JOB;
+
+ /*
+ * Create the job and set things up...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-priority", IPP_TAG_INTEGER)) != NULL)
+ priority = attr->values[0].integer;
+ else
+ ippAddInteger(con->request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-priority",
+ priority = 50);
+
+ if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL)
+ title = attr->values[0].string.text;
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL,
+ title = "Untitled");
+
+ if ((job = AddJob(priority, printer->name)) == NULL)
+ {
+ LogMessage(L_ERROR, "create_job: unable to add job for destination \'%s\'!",
+ dest);
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+
+ job->dtype = dtype;
+ job->attrs = con->request;
+ con->request = NULL;
+
+ attr = ippFindAttribute(job->attrs, "requesting-user-name", IPP_TAG_NAME);
+
+ if (con->username[0])
+ SetString(&job->username, con->username);
+ else if (attr != NULL)
+ {
+ LogMessage(L_DEBUG, "create_job: requesting-user-name = \'%s\'",
+ attr->values[0].string.text);
+
+ SetString(&job->username, attr->values[0].string.text);
+ }
+ else
+ SetString(&job->username, "anonymous");
+
+ if (attr == NULL)
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name",
+ NULL, job->username);
+ else
+ {
+ attr->group_tag = IPP_TAG_JOB;
+ SetString(&attr->name, "job-originating-user-name");
+ }
+
+ if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ /*
+ * Request contains a job-originating-host-name attribute; validate it...
+ */
+
+ if (attr->value_tag != IPP_TAG_NAME ||
+ attr->num_values != 1 ||
+ strcmp(con->http.hostname, "localhost") != 0)
+ {
+ /*
+ * Can't override the value if we aren't connected via localhost.
+ * Also, we can only have 1 value and it must be a name value.
+ */
+
+ int i; /* Looping var */
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ /*
+ * Free old strings...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ free(attr->values[i].string.text);
+ attr->values[i].string.text = NULL;
+ if (attr->values[i].string.charset)
+ {
+ free(attr->values[i].string.charset);
+ attr->values[i].string.charset = NULL;
+ }
+ }
+
+ default :
+ break;
+ }
+
+ /*
+ * Use the default connection hostname instead...
+ */
+
+ attr->value_tag = IPP_TAG_NAME;
+ attr->num_values = 1;
+ attr->values[0].string.text = strdup(con->http.hostname);
+ }
+
+ attr->group_tag = IPP_TAG_JOB;
+ }
+ else
+ {
+ /*
+ * No job-originating-host-name attribute, so use the hostname from
+ * the connection...
+ */
+
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
+ "job-originating-host-name", NULL, con->http.hostname);
+ }
+
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation",
+ time(NULL));
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "time-at-processing", 0);
+ attr->value_tag = IPP_TAG_NOVALUE;
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "time-at-completed", 0);
+ attr->value_tag = IPP_TAG_NOVALUE;
+
+ /*
+ * Add remaining job attributes...
+ */
+
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
+ job->state = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_ENUM,
+ "job-state", IPP_JOB_STOPPED);
+ job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-media-sheets-completed", 0);
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL,
+ printer_uri);
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL,
+ title);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
+ attr->values[0].integer = 0;
+ else
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-k-octets", 0);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+ if (attr == NULL)
+ attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-hold-until", NULL, "no-hold");
+ if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0 &&
+ !(printer->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Hold job until specified time...
+ */
+
+ SetJobHoldUntil(job->id, attr->values[0].string.text);
+ }
+ else
+ job->hold_until = time(NULL) + 60;
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+
+ if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
+ Classification)
+ {
+ /*
+ * Add job sheets options...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) == NULL)
+ {
+ LogMessage(L_DEBUG, "Adding default job-sheets values \"%s,%s\"...",
+ printer->job_sheets[0], printer->job_sheets[1]);
+
+ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+ 2, NULL, NULL);
+ attr->values[0].string.text = strdup(printer->job_sheets[0]);
+ attr->values[1].string.text = strdup(printer->job_sheets[1]);
+ }
+
+ job->job_sheets = attr;
+
+ /*
+ * Enforce classification level if set...
+ */
+
+ if (Classification)
+ {
+ if (ClassifyOverride)
+ {
+ if (strcmp(attr->values[0].string.text, "none") == 0 &&
+ (attr->num_values == 1 ||
+ strcmp(attr->values[1].string.text, "none") == 0))
+ {
+ /*
+ * Force the leading banner to have the classification on it...
+ */
+
+ SetString(&attr->values[0].string.text, Classification);
+
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,none\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, Classification,
+ job->username);
+ }
+ else if (attr->num_values == 2 &&
+ strcmp(attr->values[0].string.text, attr->values[1].string.text) != 0 &&
+ strcmp(attr->values[0].string.text, "none") != 0 &&
+ strcmp(attr->values[1].string.text, "none") != 0)
+ {
+ /*
+ * Can't put two different security markings on the same document!
+ */
+
+ SetString(&attr->values[1].string.text, attr->values[0].string.text);
+
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ }
+ else if (strcmp(attr->values[0].string.text, Classification) &&
+ strcmp(attr->values[0].string.text, "none") &&
+ (attr->num_values == 1 ||
+ (strcmp(attr->values[1].string.text, Classification) &&
+ strcmp(attr->values[1].string.text, "none"))))
+ {
+ if (attr->num_values == 1)
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ job->username);
+ else
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ }
+ }
+ else if (strcmp(attr->values[0].string.text, Classification) != 0 &&
+ (attr->num_values == 1 ||
+ strcmp(attr->values[1].string.text, Classification) != 0))
+ {
+ /*
+ * Force the banner to have the classification on it...
+ */
+
+ if (attr->num_values == 1 || strcmp(attr->values[0].string.text, "none"))
+ SetString(&attr->values[0].string.text, Classification);
+
+ if (attr->num_values > 1 && strcmp(attr->values[1].string.text, "none"))
+ SetString(&attr->values[1].string.text, Classification);
+
+ if (attr->num_values > 1)
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ else
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, Classification,
+ job->username);
+ }
+ }
+
+ /*
+ * See if we need to add the starting sheet...
+ */
+
+ if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ {
+ LogMessage(L_INFO, "Adding start banner page \"%s\" to job %d.",
+ attr->values[0].string.text, job->id);
+
+ kbytes = copy_banner(con, job, attr->values[0].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+ }
+ else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+ job->sheets = attr;
+
+ /*
+ * Save and log the job...
+ */
+
+ SaveJob(job->id);
+
+ LogMessage(L_INFO, "Job %d created on \'%s\' by \'%s\'.", job->id,
+ job->dest, job->username);
+
+ /*
+ * Fill in the response info...
+ */
+
+ snprintf(job_uri, sizeof(job_uri), "http://%s:%d/jobs/%d", ServerName,
+ ntohs(con->http.hostaddr.sin_port), job->id);
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
+ job->state->values[0].integer);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'delete_printer()' - Remove a printer or class from the system.
+ */
+
+static void
+delete_printer(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - URI of printer or class */
+{
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *printer; /* Printer/class */
+ char filename[1024]; /* Script/PPD filename */
+
+
+ LogMessage(L_DEBUG2, "delete_printer(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "delete_printer: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Do we have a valid URI?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "delete_printer: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Find the printer or class and delete it...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(dest);
+ else
+ printer = FindPrinter(dest);
+
+ /*
+ * Remove old jobs...
+ */
+
+ CancelJobs(dest, NULL, 1);
+
+ /*
+ * Remove any old PPD or script files...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot, dest);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest);
+ unlink(filename);
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ {
+ LogMessage(L_INFO, "Class \'%s\' deleted by \'%s\'.", dest,
+ con->username);
+
+ DeletePrinter(printer, 0);
+ SaveAllClasses();
+ }
+ else
+ {
+ LogMessage(L_INFO, "Printer \'%s\' deleted by \'%s\'.", dest,
+ con->username);
+
+ DeletePrinter(printer, 0);
+ SaveAllPrinters();
+ }
+
+ /*
+ * Return with no errors...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'get_default()' - Get the default destination.
+ */
+
+static void
+get_default(client_t *con) /* I - Client connection */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *requested, /* requested-attributes */
+ *history; /* History collection */
+ int need_history; /* Need to send history collection? */
+
+
+ LogMessage(L_DEBUG2, "get_default(%p[%d])\n", con, con->http.fd);
+
+ if (DefaultPrinter != NULL)
+ {
+ requested = ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD);
+
+ copy_attrs(con->response, DefaultPrinter->attrs, requested, IPP_TAG_ZERO, 0);
+ copy_attrs(con->response, CommonData, requested, IPP_TAG_ZERO, IPP_TAG_COPY);
+
+ need_history = 0;
+
+ if (MaxPrinterHistory > 0 && DefaultPrinter->num_history > 0 && requested)
+ {
+ for (i = 0; i < requested->num_values; i ++)
+ if (!strcmp(requested->values[i].string.text, "all") ||
+ !strcmp(requested->values[i].string.text, "printer-state-history"))
+ {
+ need_history = 1;
+ break;
+ }
+ }
+
+ if (need_history)
+ {
+ history = ippAddCollections(con->response, IPP_TAG_PRINTER,
+ "printer-state-history",
+ DefaultPrinter->num_history, NULL);
+
+ for (i = 0; i < DefaultPrinter->num_history; i ++)
+ copy_attrs(history->values[i].collection = ippNew(),
+ DefaultPrinter->history[i],
+ NULL, IPP_TAG_ZERO, 0);
+ }
+
+ con->response->request.status.status_code = requested ? IPP_OK_SUBST : IPP_OK;
+ }
+ else
+ con->response->request.status.status_code = IPP_NOT_FOUND;
+}
+
+
+/*
+ * 'get_devices()' - Get the list of available devices on the local system.
+ */
+
+static void
+get_devices(client_t *con) /* I - Client connection */
+{
+ LogMessage(L_DEBUG2, "get_devices(%p[%d])\n", con, con->http.fd);
+
+ /*
+ * Copy the device attributes to the response using the requested-attributes
+ * attribute that may be provided by the client.
+ */
+
+ copy_attrs(con->response, Devices,
+ ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD), IPP_TAG_ZERO, IPP_TAG_COPY);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'get_jobs()' - Get a list of jobs for the specified printer.
+ */
+
+static void
+get_jobs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ ipp_attribute_t *attr, /* Current attribute */
+ *requested; /* Requested attributes */
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ cups_ptype_t dmask; /* Destination type mask */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ int completed; /* Completed jobs? */
+ int limit; /* Maximum number of jobs to return */
+ int count; /* Number of jobs that match */
+ job_t *job; /* Current job pointer */
+ char job_uri[HTTP_MAX_URI];
+ /* Job URI... */
+
+
+ LogMessage(L_DEBUG2, "get_jobs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strcmp(resource, "/") == 0 ||
+ (strncmp(resource, "/jobs", 5) == 0 && strlen(resource) <= 6))
+ {
+ dest = NULL;
+ dtype = (cups_ptype_t)0;
+ dmask = (cups_ptype_t)0;
+ }
+ else if (strncmp(resource, "/printers", 9) == 0 && strlen(resource) <= 10)
+ {
+ dest = NULL;
+ dtype = (cups_ptype_t)0;
+ dmask = CUPS_PRINTER_CLASS;
+ }
+ else if (strncmp(resource, "/classes", 8) == 0 && strlen(resource) <= 9)
+ {
+ dest = NULL;
+ dtype = CUPS_PRINTER_CLASS;
+ dmask = CUPS_PRINTER_CLASS;
+ }
+ else if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "get_jobs: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+ else
+ dmask = CUPS_PRINTER_CLASS;
+
+ /*
+ * See if the "which-jobs" attribute have been specified...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "which-jobs", IPP_TAG_KEYWORD)) != NULL &&
+ strcmp(attr->values[0].string.text, "completed") == 0)
+ completed = 1;
+ else
+ completed = 0;
+
+ /*
+ * See if they want to limit the number of jobs reported...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL)
+ limit = attr->values[0].integer;
+ else
+ limit = 1000000;
+
+ /*
+ * See if we only want to see jobs for a specific user...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL &&
+ attr->values[0].boolean)
+ {
+ if (con->username[0])
+ strlcpy(username, con->username, sizeof(username));
+ else if ((attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME)) != NULL)
+ strlcpy(username, attr->values[0].string.text, sizeof(username));
+ else
+ strcpy(username, "anonymous");
+ }
+ else
+ username[0] = '\0';
+
+ requested = ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD);
+
+ /*
+ * OK, build a list of jobs for this printer...
+ */
+
+ for (count = 0, job = Jobs; count < limit && job != NULL; job = job->next)
+ {
+ /*
+ * Filter out jobs that don't match...
+ */
+
+ LogMessage(L_DEBUG2, "get_jobs: job->id = %d", job->id);
+
+ if ((dest != NULL && strcmp(job->dest, dest) != 0) &&
+ (job->printer == NULL || dest == NULL ||
+ strcmp(job->printer->name, dest) != 0))
+ continue;
+ if ((job->dtype & dmask) != dtype &&
+ (job->printer == NULL || (job->printer->type & dmask) != dtype))
+ continue;
+ if (username[0] != '\0' && strcmp(username, job->username) != 0)
+ continue;
+
+ if (completed && job->state->values[0].integer <= IPP_JOB_STOPPED)
+ continue;
+ if (!completed && job->state->values[0].integer > IPP_JOB_STOPPED)
+ continue;
+
+ count ++;
+
+ LogMessage(L_DEBUG2, "get_jobs: count = %d", count);
+
+ /*
+ * Send the requested attributes for each job...
+ */
+
+ snprintf(job_uri, sizeof(job_uri), "http://%s:%d/jobs/%d", ServerName,
+ ntohs(con->http.hostaddr.sin_port), job->id);
+
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-more-info", NULL, job_uri);
+
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-uri", NULL, job_uri);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-printer-up-time", time(NULL));
+
+ /*
+ * Copy the job attributes to the response using the requested-attributes
+ * attribute that may be provided by the client.
+ */
+
+ copy_attrs(con->response, job->attrs, requested, IPP_TAG_JOB, 0);
+
+ add_job_state_reasons(con, job);
+
+ ippAddSeparator(con->response);
+ }
+
+ if (requested != NULL)
+ con->response->request.status.status_code = IPP_OK_SUBST;
+ else
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'get_job_attrs()' - Get job attributes.
+ */
+
+static void
+get_job_attrs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job URI */
+{
+ ipp_attribute_t *attr, /* Current attribute */
+ *requested; /* Requested attributes */
+ int jobid; /* Job ID */
+ job_t *job; /* Current job */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ char job_uri[HTTP_MAX_URI];
+ /* Job URI... */
+
+
+ LogMessage(L_DEBUG2, "get_job_attrs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "get_job_attrs: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "get_job_attrs: bad job-uri attribute \'%s\'!\n",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "get_job_attrs: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Put out the standard attributes...
+ */
+
+ snprintf(job_uri, sizeof(job_uri), "http://%s:%d/jobs/%d",
+ ServerName, ntohs(con->http.hostaddr.sin_port),
+ job->id);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
+
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-more-info", NULL, job_uri);
+
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-uri", NULL, job_uri);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-printer-up-time", time(NULL));
+
+ /*
+ * Copy the job attributes to the response using the requested-attributes
+ * attribute that may be provided by the client.
+ */
+
+ requested = ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD);
+
+ copy_attrs(con->response, job->attrs, requested, IPP_TAG_JOB, 0);
+
+ add_job_state_reasons(con, job);
+
+ if (requested != NULL)
+ con->response->request.status.status_code = IPP_OK_SUBST;
+ else
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'get_ppds()' - Get the list of PPD files on the local system.
+ */
+
+static void
+get_ppds(client_t *con) /* I - Client connection */
+{
+ LogMessage(L_DEBUG2, "get_ppds(%p[%d])\n", con, con->http.fd);
+
+ /*
+ * Copy the PPD attributes to the response using the requested-attributes
+ * attribute that may be provided by the client.
+ */
+
+ copy_attrs(con->response, PPDs,
+ ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD), IPP_TAG_ZERO, IPP_TAG_COPY);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'get_printer_attrs()' - Get printer attributes.
+ */
+
+static void
+get_printer_attrs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *printer; /* Printer/class */
+ time_t curtime; /* Current time */
+ int i; /* Looping var */
+ ipp_attribute_t *requested, /* requested-attributes */
+ *history; /* History collection */
+ int need_history; /* Need to send history collection? */
+
+
+ LogMessage(L_DEBUG2, "get_printer_attrs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "get_printer_attrs: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(dest);
+ else
+ printer = FindPrinter(dest);
+
+ curtime = time(NULL);
+
+ /*
+ * Copy the printer attributes to the response using requested-attributes
+ * and document-format attributes that may be provided by the client.
+ */
+
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ printer->state);
+
+ add_printer_state_reasons(con, printer);
+
+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-state-message", NULL, printer->state_message);
+
+ ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
+ printer->accepting);
+
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-up-time", curtime);
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-state-time", printer->state_time);
+ ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
+ ippTimeToDate(curtime));
+
+ add_queued_job_count(con, printer);
+
+ requested = ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD);
+
+ copy_attrs(con->response, printer->attrs, requested, IPP_TAG_ZERO, 0);
+ copy_attrs(con->response, CommonData, requested, IPP_TAG_ZERO, IPP_TAG_COPY);
+
+ need_history = 0;
+
+ if (MaxPrinterHistory > 0 && printer->num_history > 0 && requested)
+ {
+ for (i = 0; i < requested->num_values; i ++)
+ if (!strcmp(requested->values[i].string.text, "all") ||
+ !strcmp(requested->values[i].string.text, "printer-state-history"))
+ {
+ need_history = 1;
+ break;
+ }
+ }
+
+ if (need_history)
+ {
+ history = ippAddCollections(con->response, IPP_TAG_PRINTER,
+ "printer-state-history",
+ printer->num_history, NULL);
+
+ for (i = 0; i < printer->num_history; i ++)
+ copy_attrs(history->values[i].collection = ippNew(), printer->history[i],
+ NULL, IPP_TAG_ZERO, 0);
+ }
+
+ con->response->request.status.status_code = requested ? IPP_OK_SUBST : IPP_OK;
+}
+
+
+/*
+ * 'get_printers()' - Get a list of printers or classes.
+ */
+
+static void
+get_printers(client_t *con, /* I - Client connection */
+ int type) /* I - 0 or CUPS_PRINTER_CLASS */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *requested, /* requested-attributes */
+ *history, /* History collection */
+ *attr; /* Current attribute */
+ int need_history; /* Need to send history collection? */
+ int limit; /* Maximum number of printers to return */
+ int count; /* Number of printers that match */
+ printer_t *printer; /* Current printer pointer */
+ time_t curtime; /* Current time */
+ int printer_type, /* printer-type attribute */
+ printer_mask; /* printer-type-mask attribute */
+ char *location; /* Location string */
+ char name[IPP_MAX_NAME],
+ /* Printer name */
+ *nameptr; /* Pointer into name */
+ printer_t *iclass; /* Implicit class */
+
+
+ LogMessage(L_DEBUG2, "get_printers(%p[%d], %x)\n", con, con->http.fd, type);
+
+ /*
+ * See if they want to limit the number of printers reported...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL)
+ limit = attr->values[0].integer;
+ else
+ limit = 10000000;
+
+ /*
+ * Support filtering...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "printer-type", IPP_TAG_ENUM)) != NULL)
+ printer_type = attr->values[0].integer;
+ else
+ printer_type = 0;
+
+ if ((attr = ippFindAttribute(con->request, "printer-type-mask", IPP_TAG_ENUM)) != NULL)
+ printer_mask = attr->values[0].integer;
+ else
+ printer_mask = 0;
+
+ if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL)
+ location = attr->values[0].string.text;
+ else
+ location = NULL;
+
+ requested = ippFindAttribute(con->request, "requested-attributes",
+ IPP_TAG_KEYWORD);
+
+ need_history = 0;
+
+ if (MaxPrinterHistory > 0 && requested)
+ {
+ for (i = 0; i < requested->num_values; i ++)
+ if (!strcmp(requested->values[i].string.text, "all") ||
+ !strcmp(requested->values[i].string.text, "printer-state-history"))
+ {
+ need_history = 1;
+ break;
+ }
+ }
+
+ /*
+ * OK, build a list of printers for this printer...
+ */
+
+ curtime = time(NULL);
+
+ for (count = 0, printer = Printers;
+ count < limit && printer != NULL;
+ printer = printer->next)
+ if ((printer->type & CUPS_PRINTER_CLASS) == type &&
+ (printer->type & printer_mask) == printer_type &&
+ (location == NULL || printer->location == NULL ||
+ strcasecmp(printer->location, location) == 0))
+ {
+ /*
+ * If HideImplicitMembers is enabled, see if this printer or class
+ * is a member of an implicit class...
+ */
+
+ if (ImplicitClasses && HideImplicitMembers &&
+ (printer->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Make a copy of the printer name...
+ */
+
+ strlcpy(name, printer->name, sizeof(name));
+
+ if ((nameptr = strchr(name, '@')) != NULL)
+ {
+ /*
+ * Strip trailing @server...
+ */
+
+ *nameptr = '\0';
+
+ /*
+ * Find the core printer, if any...
+ */
+
+ if ((iclass = FindPrinter(name)) != NULL &&
+ (iclass->type & CUPS_PRINTER_IMPLICIT))
+ continue;
+ }
+ }
+
+ /*
+ * Add the group separator as needed...
+ */
+
+ if (count > 0)
+ ippAddSeparator(con->response);
+
+ count ++;
+
+ /*
+ * Send the following attributes for each printer:
+ *
+ * printer-state
+ * printer-state-message
+ * printer-is-accepting-jobs
+ * + all printer attributes
+ */
+
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "printer-state", printer->state);
+
+ add_printer_state_reasons(con, printer);
+
+ ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-state-message", NULL, printer->state_message);
+
+ ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
+ printer->accepting);
+
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-up-time", curtime);
+ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-state-time", printer->state_time);
+ ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
+ ippTimeToDate(curtime));
+
+ add_queued_job_count(con, printer);
+
+ copy_attrs(con->response, printer->attrs, requested, IPP_TAG_ZERO, 0);
+
+ copy_attrs(con->response, CommonData, requested, IPP_TAG_ZERO,
+ IPP_TAG_COPY);
+
+ if (need_history && printer->num_history > 0)
+ {
+ history = ippAddCollections(con->response, IPP_TAG_PRINTER,
+ "printer-state-history",
+ printer->num_history, NULL);
+
+ for (i = 0; i < printer->num_history; i ++)
+ copy_attrs(history->values[i].collection = ippNew(),
+ printer->history[i], NULL, IPP_TAG_ZERO, 0);
+ }
+ }
+
+ con->response->request.status.status_code = requested ? IPP_OK_SUBST : IPP_OK;
+}
+
+
+/*
+ * 'hold_job()' - Hold a print job.
+ */
+
+static void
+hold_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job or Printer URI */
+{
+ ipp_attribute_t *attr, /* Current job-hold-until */
+ *newattr; /* New job-hold-until */
+ int jobid; /* Job ID */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ job_t *job; /* Job information */
+
+
+ LogMessage(L_DEBUG2, "hold_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/jobs/", 5) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "hold_job: hold request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "hold_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "hold_job: bad job-uri attribute \'%s\'!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "hold_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "hold_job: \"%s\" not authorized to hold job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * Hold the job and return...
+ */
+
+ HoldJob(jobid);
+
+ if ((newattr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ newattr = ippFindAttribute(con->request, "job-hold-until", IPP_TAG_NAME);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr != NULL)
+ {
+ /*
+ * Free the old hold value and copy the new one over...
+ */
+
+ free(attr->values[0].string.text);
+
+ if (newattr != NULL)
+ {
+ attr->value_tag = newattr->value_tag;
+ attr->values[0].string.text = strdup(newattr->values[0].string.text);
+ }
+ else
+ {
+ attr->value_tag = IPP_TAG_KEYWORD;
+ attr->values[0].string.text = strdup("indefinite");
+ }
+
+ /*
+ * Hold job until specified time...
+ */
+
+ SetJobHoldUntil(job->id, attr->values[0].string.text);
+ }
+
+ LogMessage(L_INFO, "Job %d was held by \'%s\'.", jobid, username);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'move_job()' - Move a job to a new destination.
+ */
+
+static void
+move_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ int jobid; /* Job ID */
+ job_t *job; /* Current job */
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
+ LogMessage(L_DEBUG2, "move_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "move_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "move_job: bad job-uri attribute \'%s\'!\n",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "move_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job has been completed...
+ */
+
+ if (job->state->values[0].integer > IPP_JOB_STOPPED)
+ {
+ /*
+ * Return a "not-possible" error...
+ */
+
+ LogMessage(L_ERROR, "move_job: job #%d is finished and cannot be altered!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "move_job: \"%s\" not authorized to move job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ if ((attr = ippFindAttribute(con->request, "job-printer-uri", IPP_TAG_URI)) == NULL)
+ {
+ /*
+ * Need job-printer-uri...
+ */
+
+ LogMessage(L_ERROR, "move_job: job-printer-uri attribute missing!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * Move the job to a different printer or class...
+ */
+
+ httpSeparate(attr->values[0].string.text, method, username, host, &port,
+ resource);
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "move_job: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ MoveJob(jobid, dest);
+
+ /*
+ * Start jobs if possible...
+ */
+
+ CheckJobs();
+
+ /*
+ * Return with "everything is OK" status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'ppd_add_default()' - Add a PPD default choice.
+ */
+
+static int /* O - Number of defaults */
+ppd_add_default(const char *option, /* I - Option name */
+ const char *choice, /* I - Choice name */
+ int num_defaults,
+ /* I - Number of defaults */
+ ppd_default_t **defaults)
+ /* IO - Defaults */
+{
+ int i; /* Looping var */
+ ppd_default_t *temp; /* Temporary defaults array */
+
+
+ /*
+ * First check if the option already has a default value; the PPD spec
+ * says that the first one is used...
+ */
+
+ for (i = 0, temp = *defaults; i < num_defaults; i ++)
+ if (!strcmp(option, temp[i].option))
+ return (num_defaults);
+
+ /*
+ * Now add the option...
+ */
+
+ if (num_defaults == 0)
+ temp = malloc(sizeof(ppd_default_t));
+ else
+ temp = realloc(*defaults, (num_defaults + 1) * sizeof(ppd_default_t));
+
+ if (!temp)
+ {
+ LogMessage(L_ERROR, "ppd_add_default: Unable to add default value for \"%s\" - %s",
+ option, strerror(errno));
+ return (num_defaults);
+ }
+
+ *defaults = temp;
+ temp += num_defaults;
+
+ strlcpy(temp->option, option, sizeof(temp->option));
+ strlcpy(temp->choice, choice, sizeof(temp->choice));
+
+ return (num_defaults + 1);
+}
+
+
+/*
+ * 'ppd_parse_line()' - Parse a PPD default line.
+ */
+
+static int /* O - 0 on success, -1 on failure */
+ppd_parse_line(const char *line, /* I - Line */
+ char *option, /* O - Option name */
+ int olen, /* I - Size of option name */
+ char *choice, /* O - Choice name */
+ int clen) /* I - Size of choice name */
+{
+ /*
+ * Verify this is a default option line...
+ */
+
+ if (strncmp(line, "*Default", 8))
+ return (-1);
+
+ /*
+ * Read the option name...
+ */
+
+ for (line += 8, olen --; isalnum(*line & 255); line ++)
+ if (olen > 0)
+ {
+ *option++ = *line;
+ olen --;
+ }
+
+ *option = '\0';
+
+ /*
+ * Skip everything else up to the colon (:)...
+ */
+
+ while (*line && *line != ':')
+ line ++;
+
+ if (!*line)
+ return (-1);
+
+ line ++;
+
+ /*
+ * Now grab the option choice, skipping leading whitespace...
+ */
+
+ while (isspace(*line & 255))
+ line ++;
+
+ for (clen --; isalnum(*line & 255); line ++)
+ if (clen > 0)
+ {
+ *choice++ = *line;
+ clen --;
+ }
+
+ *choice = '\0';
+
+ /*
+ * Return with no errors...
+ */
+
+ return (0);
+}
+
+
+/*
+ * 'print_job()' - Print a file to a printer or class.
+ */
+
+static void
+print_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_attribute_t *format; /* Document-format attribute */
+ const char *dest; /* Destination */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ int priority; /* Job priority */
+ char *title; /* Job name/title */
+ job_t *job; /* Current job */
+ int jobid; /* Job ID number */
+ char job_uri[HTTP_MAX_URI],
+ /* Job URI */
+ printer_uri[HTTP_MAX_URI],
+ /* Printer URI */
+ method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI],
+ /* Resource portion of URI */
+ filename[1024]; /* Job filename */
+ int port; /* Port portion of URI */
+ mime_type_t *filetype; /* Type of file */
+ char super[MIME_MAX_SUPER],
+ /* Supertype of file */
+ type[MIME_MAX_TYPE],
+ /* Subtype of file */
+ mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
+ /* Textual name of mime type */
+ printer_t *printer; /* Printer data */
+ struct stat fileinfo; /* File information */
+ int kbytes; /* Size of file */
+ int i; /* Looping var */
+ int lowerpagerange; /* Page range bound */
+ int compression; /* Document compression */
+
+
+ LogMessage(L_DEBUG2, "print_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "print_job: cancel request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Validate job template attributes; for now just copies and page-ranges...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "copies", IPP_TAG_INTEGER)) != NULL)
+ {
+ if (attr->values[0].integer < 1 || attr->values[0].integer > MaxCopies)
+ {
+ LogMessage(L_INFO, "print_job: bad copies value %d.",
+ attr->values[0].integer);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+ }
+
+ if ((attr = ippFindAttribute(con->request, "page-ranges", IPP_TAG_RANGE)) != NULL)
+ {
+ for (i = 0, lowerpagerange = 1; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].range.lower < lowerpagerange ||
+ attr->values[i].range.lower > attr->values[i].range.upper)
+ {
+ LogMessage(L_ERROR, "print_job: bad page-ranges values %d-%d.",
+ attr->values[i].range.lower, attr->values[i].range.upper);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ lowerpagerange = attr->values[i].range.upper + 1;
+ }
+ }
+
+ /*
+ * OK, see if the client is sending the document compressed - CUPS
+ * only supports "none" and "gzip".
+ */
+
+ compression = CUPS_FILE_NONE;
+
+ if ((attr = ippFindAttribute(con->request, "compression", IPP_TAG_KEYWORD)) != NULL)
+ {
+ if (strcmp(attr->values[0].string.text, "none")
+#ifdef HAVE_LIBZ
+ && strcmp(attr->values[0].string.text, "gzip")
+#endif /* HAVE_LIBZ */
+ )
+ {
+ LogMessage(L_ERROR, "print_job: Unsupported compression \"%s\"!",
+ attr->values[0].string.text);
+ send_ipp_error(con, IPP_ATTRIBUTES);
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
+ "compression", NULL, attr->values[0].string.text);
+ return;
+ }
+
+#ifdef HAVE_LIBZ
+ if (!strcmp(attr->values[0].string.text, "gzip"))
+ compression = CUPS_FILE_GZIP;
+#endif /* HAVE_LIBZ */
+ }
+
+ /*
+ * Do we have a file to print?
+ */
+
+ if (!con->filename)
+ {
+ LogMessage(L_ERROR, "print_job: No file!?!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * Is it a format we support?
+ */
+
+ if ((format = ippFindAttribute(con->request, "document-format", IPP_TAG_MIMETYPE)) != NULL)
+ {
+ /*
+ * Grab format from client...
+ */
+
+ if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super, type) != 2)
+ {
+ LogMessage(L_ERROR, "print_job: could not scan type \'%s\'!",
+ format->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * No document format attribute? Auto-type it!
+ */
+
+ strcpy(super, "application");
+ strcpy(type, "octet-stream");
+ }
+
+ if (strcmp(super, "application") == 0 &&
+ strcmp(type, "octet-stream") == 0)
+ {
+ /*
+ * Auto-type the file...
+ */
+
+ LogMessage(L_DEBUG, "print_job: auto-typing file...");
+
+ filetype = mimeFileType(MimeDatabase, con->filename, &compression);
+
+ if (filetype != NULL)
+ {
+ /*
+ * Replace the document-format attribute value with the auto-typed one.
+ */
+
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
+ filetype->type);
+
+ if (format != NULL)
+ {
+ free(format->values[0].string.text);
+ format->values[0].string.text = strdup(mimetype);
+ }
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
+ }
+ else
+ filetype = mimeType(MimeDatabase, super, type);
+ }
+ else
+ filetype = mimeType(MimeDatabase, super, type);
+
+ if (filetype == NULL)
+ {
+ LogMessage(L_ERROR, "print_job: Unsupported format \'%s/%s\'!",
+ super, type);
+ LogMessage(L_INFO, "Hint: Do you have the raw file printing rules enabled?");
+ send_ipp_error(con, IPP_DOCUMENT_FORMAT);
+
+ if (format)
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format->values[0].string.text);
+
+ return;
+ }
+
+ LogMessage(L_DEBUG, "print_job: request file type is %s/%s.",
+ filetype->super, filetype->type);
+
+ /*
+ * Read any embedded job ticket info from PS files...
+ */
+
+ if (strcasecmp(filetype->super, "application") == 0 &&
+ strcasecmp(filetype->type, "postscript") == 0)
+ read_ps_job_ticket(con);
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "print_job: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the printer is accepting jobs...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ {
+ printer = FindClass(dest);
+ snprintf(printer_uri, sizeof(printer_uri), "http://%s:%d/classes/%s",
+ ServerName, ntohs(con->http.hostaddr.sin_port), dest);
+ }
+ else
+ {
+ printer = FindPrinter(dest);
+
+ snprintf(printer_uri, sizeof(printer_uri), "http://%s:%d/printers/%s",
+ ServerName, ntohs(con->http.hostaddr.sin_port), dest);
+ }
+
+ if (!printer->accepting)
+ {
+ LogMessage(L_INFO, "print_job: destination \'%s\' is not accepting jobs.",
+ dest);
+ send_ipp_error(con, IPP_NOT_ACCEPTING);
+ return;
+ }
+
+ /*
+ * Make sure we aren't over our limit...
+ */
+
+ if (NumJobs >= MaxJobs && MaxJobs)
+ CleanJobs();
+
+ if (NumJobs >= MaxJobs && MaxJobs)
+ {
+ LogMessage(L_INFO, "print_job: too many jobs - %d jobs, max jobs is %d.",
+ NumJobs, MaxJobs);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ if (!check_quotas(con, printer))
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * Set all but the first two attributes to the job attributes group...
+ */
+
+ for (attr = con->request->attrs->next->next; attr; attr = attr->next)
+ attr->group_tag = IPP_TAG_JOB;
+
+ /*
+ * Create the job and set things up...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-priority", IPP_TAG_INTEGER)) != NULL)
+ priority = attr->values[0].integer;
+ else
+ ippAddInteger(con->request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-priority",
+ priority = 50);
+
+ if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL)
+ title = attr->values[0].string.text;
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL,
+ title = "Untitled");
+
+ if ((job = AddJob(priority, printer->name)) == NULL)
+ {
+ LogMessage(L_ERROR, "print_job: unable to add job for destination \'%s\'!",
+ dest);
+ send_ipp_error(con, IPP_INTERNAL_ERROR);
+ return;
+ }
+
+ job->dtype = dtype;
+ job->attrs = con->request;
+ con->request = NULL;
+
+ /*
+ * Copy the rest of the job info...
+ */
+
+ attr = ippFindAttribute(job->attrs, "requesting-user-name", IPP_TAG_NAME);
+
+ if (con->username[0])
+ SetString(&job->username, con->username);
+ else if (attr != NULL)
+ {
+ LogMessage(L_DEBUG, "print_job: requesting-user-name = \'%s\'",
+ attr->values[0].string.text);
+
+ SetString(&job->username, attr->values[0].string.text);
+ }
+ else
+ SetString(&job->username, "anonymous");
+
+ if (attr == NULL)
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name",
+ NULL, job->username);
+ else
+ {
+ attr->group_tag = IPP_TAG_JOB;
+ SetString(&attr->name, "job-originating-user-name");
+ }
+
+ /*
+ * Add remaining job attributes...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ /*
+ * Request contains a job-originating-host-name attribute; validate it...
+ */
+
+ if (attr->value_tag != IPP_TAG_NAME ||
+ attr->num_values != 1 ||
+ strcmp(con->http.hostname, "localhost") != 0)
+ {
+ /*
+ * Can't override the value if we aren't connected via localhost.
+ * Also, we can only have 1 value and it must be a name value.
+ */
+
+ int i; /* Looping var */
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_URI :
+ case IPP_TAG_URISCHEME :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ case IPP_TAG_MIMETYPE :
+ /*
+ * Free old strings...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ free(attr->values[i].string.text);
+ attr->values[i].string.text = NULL;
+ if (attr->values[i].string.charset)
+ {
+ free(attr->values[i].string.charset);
+ attr->values[i].string.charset = NULL;
+ }
+ }
+
+ default :
+ break;
+ }
+
+ /*
+ * Use the default connection hostname instead...
+ */
+
+ attr->value_tag = IPP_TAG_NAME;
+ attr->num_values = 1;
+ attr->values[0].string.text = strdup(con->http.hostname);
+ }
+
+ attr->group_tag = IPP_TAG_JOB;
+ }
+ else
+ {
+ /*
+ * No job-originating-host-name attribute, so use the hostname from
+ * the connection...
+ */
+
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME,
+ "job-originating-host-name", NULL, con->http.hostname);
+ }
+
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
+ job->state = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_ENUM,
+ "job-state", IPP_JOB_PENDING);
+ job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-media-sheets-completed", 0);
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL,
+ printer_uri);
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL,
+ title);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) == NULL)
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-k-octets", 0);
+
+ if (stat(con->filename, &fileinfo))
+ kbytes = 0;
+ else
+ kbytes = (fileinfo.st_size + 1023) / 1024;
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ attr->values[0].integer += kbytes;
+
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation",
+ time(NULL));
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "time-at-processing", 0);
+ attr->value_tag = IPP_TAG_NOVALUE;
+ attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "time-at-completed", 0);
+ attr->value_tag = IPP_TAG_NOVALUE;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+ if (attr == NULL)
+ attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-hold-until", NULL, "no-hold");
+
+ if (attr != NULL && strcmp(attr->values[0].string.text, "no-hold") != 0 &&
+ !(printer->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Hold job until specified time...
+ */
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+ SetJobHoldUntil(job->id, attr->values[0].string.text);
+ }
+
+ if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
+ Classification)
+ {
+ /*
+ * Add job sheets options...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) == NULL)
+ {
+ LogMessage(L_DEBUG, "Adding default job-sheets values \"%s,%s\"...",
+ printer->job_sheets[0], printer->job_sheets[1]);
+
+ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+ 2, NULL, NULL);
+ attr->values[0].string.text = strdup(printer->job_sheets[0]);
+ attr->values[1].string.text = strdup(printer->job_sheets[1]);
+ }
+
+ job->job_sheets = attr;
+
+ /*
+ * Enforce classification level if set...
+ */
+
+ if (Classification)
+ {
+ if (ClassifyOverride)
+ {
+ if (strcmp(attr->values[0].string.text, "none") == 0 &&
+ (attr->num_values == 1 ||
+ strcmp(attr->values[1].string.text, "none") == 0))
+ {
+ /*
+ * Force the leading banner to have the classification on it...
+ */
+
+ SetString(&attr->values[0].string.text, Classification);
+
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,none\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, Classification,
+ job->username);
+ }
+ else if (attr->num_values == 2 &&
+ strcmp(attr->values[0].string.text, attr->values[1].string.text) != 0 &&
+ strcmp(attr->values[0].string.text, "none") != 0 &&
+ strcmp(attr->values[1].string.text, "none") != 0)
+ {
+ /*
+ * Can't put two different security markings on the same document!
+ */
+
+ SetString(&attr->values[1].string.text, attr->values[0].string.text);
+
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ }
+ else if (strcmp(attr->values[0].string.text, Classification) &&
+ strcmp(attr->values[0].string.text, "none") &&
+ (attr->num_values == 1 ||
+ (strcmp(attr->values[1].string.text, Classification) &&
+ strcmp(attr->values[1].string.text, "none"))))
+ {
+ if (attr->num_values == 1)
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ job->username);
+ else
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION OVERRIDDEN "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ }
+ }
+ else if (strcmp(attr->values[0].string.text, Classification) != 0 &&
+ (attr->num_values == 1 ||
+ strcmp(attr->values[1].string.text, Classification) != 0))
+ {
+ /*
+ * Force the banner to have the classification on it...
+ */
+
+ if (attr->num_values == 1 || strcmp(attr->values[0].string.text, "none"))
+ SetString(&attr->values[0].string.text, Classification);
+
+ if (attr->num_values > 1)
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, attr->values[0].string.text,
+ attr->values[1].string.text,
+ job->username);
+ else
+ LogMessage(L_NOTICE, "[Job %d] CLASSIFICATION FORCED "
+ "job-sheets=\"%s\", "
+ "job-originating-user-name=\"%s\"",
+ job->id, Classification,
+ job->username);
+ }
+ }
+
+ /*
+ * Add the starting sheet...
+ */
+
+ if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ {
+ LogMessage(L_INFO, "Adding start banner page \"%s\" to job %d.",
+ attr->values[0].string.text, job->id);
+
+ kbytes = copy_banner(con, job, attr->values[0].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+ }
+ else if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+ job->sheets = attr;
+
+ /*
+ * Add the job file...
+ */
+
+ if (add_file(con, job, filetype, compression))
+ return;
+
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id,
+ job->num_files);
+ rename(con->filename, filename);
+ ClearString(&con->filename);
+
+ /*
+ * See if we need to add the ending sheet...
+ */
+
+ if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+ attr->num_values > 1)
+ {
+ /*
+ * Yes...
+ */
+
+ LogMessage(L_INFO, "Adding end banner page \"%s\" to job %d.",
+ attr->values[1].string.text, job->id);
+
+ kbytes = copy_banner(con, job, attr->values[1].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+
+ /*
+ * Log and save the job...
+ */
+
+ LogMessage(L_INFO, "Job %d queued on \'%s\' by \'%s\'.", job->id,
+ job->dest, job->username);
+ LogMessage(L_DEBUG, "Job %d hold_until = %d", job->id, (int)job->hold_until);
+
+ SaveJob(job->id);
+
+ /*
+ * Start the job if possible... Since CheckJobs() can cancel a job if it
+ * doesn't print, we need to re-find the job afterwards...
+ */
+
+ jobid = job->id;
+
+ CheckJobs();
+
+ job = FindJob(jobid);
+
+ /*
+ * Fill in the response info...
+ */
+
+ snprintf(job_uri, sizeof(job_uri), "http://%s:%d/jobs/%d", ServerName,
+ ntohs(con->http.hostaddr.sin_port), jobid);
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", jobid);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
+ job ? job->state->values[0].integer : IPP_JOB_CANCELLED);
+ add_job_state_reasons(con, job);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'read_ps_job_ticket()' - Reads a job ticket embedded in a PS file.
+ *
+ * This function only gets called when printing a single PostScript
+ * file using the Print-Job operation. It doesn't work for Create-Job +
+ * Send-File, since the job attributes need to be set at job creation
+ * time for banners to work. The embedded PS job ticket stuff is here
+ * only to allow the Windows printer driver for CUPS to pass in JCL
+ * options and IPP attributes which otherwise would be lost.
+ *
+ * The format of a PS job ticket is simple:
+ *
+ * %cupsJobTicket: attr1=value1 attr2=value2 ... attrN=valueN
+ *
+ * %cupsJobTicket: attr1=value1
+ * %cupsJobTicket: attr2=value2
+ * ...
+ * %cupsJobTicket: attrN=valueN
+ *
+ * Job ticket lines must appear immediately after the first line that
+ * specifies PostScript format (%!PS-Adobe-3.0), and CUPS will stop
+ * looking for job ticket info when it finds a line that does not begin
+ * with "%cupsJobTicket:".
+ *
+ * The maximum length of a job ticket line, including the prefix, is
+ * 255 characters to conform with the Adobe DSC.
+ *
+ * Read-only attributes are rejected with a notice to the error log in
+ * case a malicious user tries anything. Since the job ticket is read
+ * prior to attribute validation in print_job(), job ticket attributes
+ * will go through the same validation as IPP attributes...
+ */
+
+static void
+read_ps_job_ticket(client_t *con) /* I - Client connection */
+{
+ cups_file_t *fp; /* File to read from */
+ char line[256]; /* Line data */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ ipp_t *ticket; /* New attributes */
+ ipp_attribute_t *attr, /* Current attribute */
+ *attr2, /* Job attribute */
+ *prev2; /* Previous job attribute */
+
+
+ /*
+ * First open the print file...
+ */
+
+ if ((fp = cupsFileOpen(con->filename, "rb")) == NULL)
+ {
+ LogMessage(L_ERROR, "read_ps_job_ticket: Unable to open PostScript print file - %s",
+ strerror(errno));
+ return;
+ }
+
+ /*
+ * Skip the first line...
+ */
+
+ if (cupsFileGets(fp, line, sizeof(line)) == NULL)
+ {
+ LogMessage(L_ERROR, "read_ps_job_ticket: Unable to read from PostScript print file - %s",
+ strerror(errno));
+ cupsFileClose(fp);
+ return;
+ }
+
+ if (strncmp(line, "%!PS-Adobe-", 11) != 0)
+ {
+ /*
+ * Not a DSC-compliant file, so no job ticket info will be available...
+ */
+
+ cupsFileClose(fp);
+ return;
+ }
+
+ /*
+ * Read job ticket info from the file...
+ */
+
+ num_options = 0;
+ options = NULL;
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ /*
+ * Stop at the first non-ticket line...
+ */
+
+ if (strncmp(line, "%cupsJobTicket:", 15) != 0)
+ break;
+
+ /*
+ * Add the options to the option array...
+ */
+
+ num_options = cupsParseOptions(line + 15, num_options, &options);
+ }
+
+ /*
+ * Done with the file; see if we have any options...
+ */
+
+ cupsFileClose(fp);
+
+ if (num_options == 0)
+ return;
+
+ /*
+ * OK, convert the options to an attribute list, and apply them to
+ * the request...
+ */
+
+ ticket = ippNew();
+ cupsEncodeOptions(ticket, num_options, options);
+
+ /*
+ * See what the user wants to change.
+ */
+
+ for (attr = ticket->attrs; attr != NULL; attr = attr->next)
+ {
+ if (attr->group_tag != IPP_TAG_JOB || !attr->name)
+ continue;
+
+ if (strcmp(attr->name, "job-originating-host-name") == 0 ||
+ strcmp(attr->name, "job-originating-user-name") == 0 ||
+ strcmp(attr->name, "job-media-sheets-completed") == 0 ||
+ strcmp(attr->name, "job-k-octets") == 0 ||
+ strcmp(attr->name, "job-id") == 0 ||
+ strncmp(attr->name, "job-state", 9) == 0 ||
+ strncmp(attr->name, "time-at-", 8) == 0)
+ continue; /* Read-only attrs */
+
+ if ((attr2 = ippFindAttribute(con->request, attr->name, IPP_TAG_ZERO)) != NULL)
+ {
+ /*
+ * Some other value; first free the old value...
+ */
+
+ if (con->request->attrs == attr2)
+ {
+ con->request->attrs = attr2->next;
+ prev2 = NULL;
+ }
+ else
+ {
+ for (prev2 = con->request->attrs; prev2 != NULL; prev2 = prev2->next)
+ if (prev2->next == attr2)
+ {
+ prev2->next = attr2->next;
+ break;
+ }
+ }
+
+ if (con->request->last == attr2)
+ con->request->last = prev2;
+
+ _ipp_free_attr(attr2);
+ }
+
+ /*
+ * Add new option by copying it...
+ */
+
+ copy_attribute(con->request, attr, 0);
+ }
+
+ /*
+ * Then free the attribute list and option array...
+ */
+
+ ippDelete(ticket);
+ cupsFreeOptions(num_options, options);
+}
+
+
+/*
+ * 'reject_jobs()' - Reject print jobs to a printer.
+ */
+
+static void
+reject_jobs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer or class URI */
+{
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ const char *name; /* Printer name */
+ printer_t *printer; /* Printer data */
+ ipp_attribute_t *attr; /* printer-state-message text */
+
+
+ LogMessage(L_DEBUG2, "reject_jobs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "reject_jobs: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((name = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "reject_jobs: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Reject jobs sent to the printer...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(name);
+ else
+ printer = FindPrinter(name);
+
+ printer->accepting = 0;
+
+ if ((attr = ippFindAttribute(con->request, "printer-state-message",
+ IPP_TAG_TEXT)) == NULL)
+ strcpy(printer->state_message, "Rejecting Jobs");
+ else
+ strlcpy(printer->state_message, attr->values[0].string.text,
+ sizeof(printer->state_message));
+
+ AddPrinterHistory(printer);
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ {
+ SaveAllClasses();
+
+ LogMessage(L_INFO, "Class \'%s\' rejecting jobs (\'%s\').", name,
+ con->username);
+ }
+ else
+ {
+ SaveAllPrinters();
+
+ LogMessage(L_INFO, "Printer \'%s\' rejecting jobs (\'%s\').", name,
+ con->username);
+ }
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'release_job()' - Release a held print job.
+ */
+
+static void
+release_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job or Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ int jobid; /* Job ID */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ job_t *job; /* Job information */
+
+
+ LogMessage(L_DEBUG2, "release_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/jobs/", 5) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "release_job: release request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "release_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "release_job: bad job-uri attribute \'%s\'!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "release_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if job is "held"...
+ */
+
+ if (job->state->values[0].integer != IPP_JOB_HELD)
+ {
+ /*
+ * Nope - return a "not possible" error...
+ */
+
+ LogMessage(L_ERROR, "release_job: job #%d is not held!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "release_job: \"%s\" not authorized to release job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * Reset the job-hold-until value to "no-hold"...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr != NULL)
+ {
+ free(attr->values[0].string.text);
+ attr->value_tag = IPP_TAG_KEYWORD;
+ attr->values[0].string.text = strdup("no-hold");
+ }
+
+ /*
+ * Release the job and return...
+ */
+
+ ReleaseJob(jobid);
+
+ LogMessage(L_INFO, "Job %d was released by \'%s\'.", jobid, username);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'restart_job()' - Restart an old print job.
+ */
+
+static void
+restart_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job or Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ int jobid; /* Job ID */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ job_t *job; /* Job information */
+
+
+ LogMessage(L_DEBUG2, "restart_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/jobs/", 5) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "restart_job: restart request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "restart_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "restart_job: bad job-uri attribute \'%s\'!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "restart_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if job is in any of the "completed" states...
+ */
+
+ if (job->state->values[0].integer <= IPP_JOB_PROCESSING)
+ {
+ /*
+ * Nope - return a "not possible" error...
+ */
+
+ LogMessage(L_ERROR, "restart_job: job #%d is not complete!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if we have retained the job files...
+ */
+
+ if (!JobFiles && job->state->values[0].integer > IPP_JOB_STOPPED)
+ {
+ /*
+ * Nope - return a "not possible" error...
+ */
+
+ LogMessage(L_ERROR, "restart_job: job #%d cannot be restarted - no files!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "restart_job: \"%s\" not authorized to restart job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * Restart the job and return...
+ */
+
+ RestartJob(jobid);
+
+ LogMessage(L_INFO, "Job %d was restarted by \'%s\'.", jobid, username);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'send_document()' - Send a file to a printer or class.
+ */
+
+static void
+send_document(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_attribute_t *format; /* Document-format attribute */
+ int jobid; /* Job ID number */
+ job_t *job; /* Current job */
+ char job_uri[HTTP_MAX_URI],
+ /* Job URI */
+ method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ mime_type_t *filetype; /* Type of file */
+ char super[MIME_MAX_SUPER],
+ /* Supertype of file */
+ type[MIME_MAX_TYPE],
+ /* Subtype of file */
+ mimetype[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
+ /* Textual name of mime type */
+ char filename[1024]; /* Job filename */
+ printer_t *printer; /* Current printer */
+ struct stat fileinfo; /* File information */
+ int kbytes; /* Size of file */
+ int compression; /* Type of compression */
+
+
+ LogMessage(L_DEBUG2, "send_document(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/jobs/", 6) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "send_document: print request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "send_document: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "send_document: bad job-uri attribute \'%s\'!",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "send_document: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "send_document: \"%s\" not authorized to send document for job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * OK, see if the client is sending the document compressed - CUPS
+ * only supports "none" and "gzip".
+ */
+
+ compression = CUPS_FILE_NONE;
+
+ if ((attr = ippFindAttribute(con->request, "compression", IPP_TAG_KEYWORD)) != NULL)
+ {
+ if (strcmp(attr->values[0].string.text, "none")
+#ifdef HAVE_LIBZ
+ && strcmp(attr->values[0].string.text, "gzip")
+#endif /* HAVE_LIBZ */
+ )
+ {
+ LogMessage(L_ERROR, "print_job: Unsupported compression \"%s\"!",
+ attr->values[0].string.text);
+ send_ipp_error(con, IPP_ATTRIBUTES);
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
+ "compression", NULL, attr->values[0].string.text);
+ return;
+ }
+
+#ifdef HAVE_LIBZ
+ if (!strcmp(attr->values[0].string.text, "gzip"))
+ compression = CUPS_FILE_GZIP;
+#endif /* HAVE_LIBZ */
+ }
+
+ /*
+ * Do we have a file to print?
+ */
+
+ if (!con->filename)
+ {
+ LogMessage(L_ERROR, "send_document: No file!?!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ /*
+ * Is it a format we support?
+ */
+
+ if ((format = ippFindAttribute(con->request, "document-format", IPP_TAG_MIMETYPE)) != NULL)
+ {
+ /*
+ * Grab format from client...
+ */
+
+ if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super, type) != 2)
+ {
+ LogMessage(L_ERROR, "send_document: could not scan type \'%s\'!",
+ format->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * No document format attribute? Auto-type it!
+ */
+
+ strcpy(super, "application");
+ strcpy(type, "octet-stream");
+ }
+
+ if (strcmp(super, "application") == 0 &&
+ strcmp(type, "octet-stream") == 0)
+ {
+ /*
+ * Auto-type the file...
+ */
+
+ LogMessage(L_DEBUG, "send_document: auto-typing file...");
+
+ filetype = mimeFileType(MimeDatabase, con->filename, &compression);
+
+ if (filetype != NULL)
+ {
+ /*
+ * Replace the document-format attribute value with the auto-typed one.
+ */
+
+ snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super,
+ filetype->type);
+
+ if (format != NULL)
+ {
+ free(format->values[0].string.text);
+ format->values[0].string.text = strdup(mimetype);
+ }
+ else
+ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
+ "document-format", NULL, mimetype);
+ }
+ else
+ filetype = mimeType(MimeDatabase, super, type);
+ }
+ else
+ filetype = mimeType(MimeDatabase, super, type);
+
+ if (filetype == NULL)
+ {
+ LogMessage(L_ERROR, "send_document: Unsupported format \'%s/%s\'!",
+ super, type);
+ LogMessage(L_INFO, "Hint: Do you have the raw file printing rules enabled?");
+ send_ipp_error(con, IPP_DOCUMENT_FORMAT);
+
+ if (format)
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format->values[0].string.text);
+
+ return;
+ }
+
+ LogMessage(L_DEBUG, "send_document: request file type is %s/%s.",
+ filetype->super, filetype->type);
+
+ /*
+ * Add the file to the job...
+ */
+
+ if (add_file(con, job, filetype, compression))
+ return;
+
+ if (job->dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(job->dest);
+ else
+ printer = FindPrinter(job->dest);
+
+ if (stat(con->filename, &fileinfo))
+ kbytes = 0;
+ else
+ kbytes = (fileinfo.st_size + 1023) / 1024;
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL)
+ attr->values[0].integer += kbytes;
+
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id,
+ job->num_files);
+ rename(con->filename, filename);
+
+ ClearString(&con->filename);
+
+ LogMessage(L_INFO, "File of type %s/%s queued in job #%d by \'%s\'.",
+ filetype->super, filetype->type, job->id, job->username);
+
+ /*
+ * Start the job if this is the last document...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "last-document", IPP_TAG_BOOLEAN)) != NULL &&
+ attr->values[0].boolean)
+ {
+ /*
+ * See if we need to add the ending sheet...
+ */
+
+ if (printer != NULL &&
+ !(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+ (attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL &&
+ attr->num_values > 1)
+ {
+ /*
+ * Yes...
+ */
+
+ LogMessage(L_INFO, "Adding end banner page \"%s\" to job %d.",
+ attr->values[1].string.text, job->id);
+
+ kbytes = copy_banner(con, job, attr->values[1].string.text);
+
+ UpdateQuota(printer, job->username, 0, kbytes);
+ }
+
+ if (job->state->values[0].integer == IPP_JOB_STOPPED)
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ else if (job->state->values[0].integer == IPP_JOB_HELD)
+ {
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr == NULL || strcmp(attr->values[0].string.text, "no-hold") == 0)
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ }
+
+ SaveJob(job->id);
+
+ /*
+ * Start the job if possible... Since CheckJobs() can cancel a job if it
+ * doesn't print, we need to re-find the job afterwards...
+ */
+
+ jobid = job->id;
+
+ CheckJobs();
+
+ job = FindJob(jobid);
+ }
+ else
+ {
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr == NULL || strcmp(attr->values[0].string.text, "no-hold") == 0)
+ {
+ job->state->values[0].integer = IPP_JOB_HELD;
+ job->hold_until = time(NULL) + 60;
+ SaveJob(job->id);
+ }
+ }
+
+ /*
+ * Fill in the response info...
+ */
+
+ snprintf(job_uri, sizeof(job_uri), "http://%s:%d/jobs/%d", ServerName,
+ ntohs(con->http.hostaddr.sin_port), jobid);
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL,
+ job_uri);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", jobid);
+
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state",
+ job ? job->state->values[0].integer : IPP_JOB_CANCELLED);
+ add_job_state_reasons(con, job);
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'send_ipp_error()' - Send an error status back to the IPP client.
+ */
+
+static void
+send_ipp_error(client_t *con, /* I - Client connection */
+ ipp_status_t status) /* I - IPP status code */
+{
+ LogMessage(L_DEBUG2, "send_ipp_error(%p[%d], %x)\n", con, con->http.fd,
+ status);
+
+ LogMessage(L_DEBUG, "Sending error: %s", ippErrorString(status));
+
+ con->response->request.status.status_code = status;
+
+ if (ippFindAttribute(con->response, "attributes-charset", IPP_TAG_ZERO) == NULL)
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, DefaultCharset);
+
+ if (ippFindAttribute(con->response, "attributes-natural-language",
+ IPP_TAG_ZERO) == NULL)
+ ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, DefaultLanguage);
+}
+
+
+/*
+ * 'set_default()' - Set the default destination...
+ */
+
+static void
+set_default(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ const char *name; /* Printer name */
+
+
+ LogMessage(L_DEBUG2, "set_default(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "set_default: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((name = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "set_default: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Set it as the default...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ DefaultPrinter = FindClass(name);
+ else
+ DefaultPrinter = FindPrinter(name);
+
+ SaveAllPrinters();
+ SaveAllClasses();
+
+ LogMessage(L_INFO, "Default destination set to \'%s\' by \'%s\'.", name,
+ con->username);
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'set_job_attrs()' - Set job attributes.
+ */
+
+static void
+set_job_attrs(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job URI */
+{
+ ipp_attribute_t *attr, /* Current attribute */
+ *attr2, /* Job attribute */
+ *prev2; /* Previous job attribute */
+ int jobid; /* Job ID */
+ job_t *job; /* Current job */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+
+
+ LogMessage(L_DEBUG2, "set_job_attrs(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Start with "everything is OK" status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (strcmp(uri->name, "printer-uri") == 0)
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "set_job_attrs: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6) != 0)
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "set_job_attrs: bad job-uri attribute \'%s\'!\n",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "set_job_attrs: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job has been completed...
+ */
+
+ if (job->state->values[0].integer > IPP_JOB_STOPPED)
+ {
+ /*
+ * Return a "not-possible" error...
+ */
+
+ LogMessage(L_ERROR, "set_job_attrs: job #%d is finished and cannot be altered!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "set_job_attrs: \"%s\" not authorized to alter job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * See what the user wants to change.
+ */
+
+ for (attr = con->request->attrs; attr != NULL; attr = attr->next)
+ {
+ if (attr->group_tag != IPP_TAG_JOB || !attr->name)
+ continue;
+
+ if (!strcmp(attr->name, "attributes-charset") ||
+ !strcmp(attr->name, "attributes-natural-language") ||
+ !strcmp(attr->name, "document-compression") ||
+ !strcmp(attr->name, "document-format") ||
+ !strcmp(attr->name, "job-detailed-status-messages") ||
+ !strcmp(attr->name, "job-document-access-errors") ||
+ !strcmp(attr->name, "job-id") ||
+ !strcmp(attr->name, "job-k-octets") ||
+ !strcmp(attr->name, "job-originating-host-name") ||
+ !strcmp(attr->name, "job-originating-user-name") ||
+ !strcmp(attr->name, "job-printer-up-time") ||
+ !strcmp(attr->name, "job-printer-uri") ||
+ !strcmp(attr->name, "job-sheets") ||
+ !strcmp(attr->name, "job-state-message") ||
+ !strcmp(attr->name, "job-state-reasons") ||
+ !strcmp(attr->name, "job-uri") ||
+ !strcmp(attr->name, "number-of-documents") ||
+ !strcmp(attr->name, "number-of-intervening-jobs") ||
+ !strcmp(attr->name, "output-device-assigned") ||
+ !strncmp(attr->name, "date-time-at-", 13) ||
+ !strncmp(attr->name, "job-impressions", 15) ||
+ !strncmp(attr->name, "job-k-octets", 12) ||
+ !strncmp(attr->name, "job-media-sheets", 16) ||
+ !strncmp(attr->name, "time-at-", 8))
+ {
+ /*
+ * Read-only attrs!
+ */
+
+ send_ipp_error(con, IPP_ATTRIBUTES_NOT_SETTABLE);
+
+ if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
+ attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
+
+ continue;
+ }
+
+ if (!strcmp(attr->name, "job-priority"))
+ {
+ /*
+ * Change the job priority...
+ */
+
+ if (attr->value_tag != IPP_TAG_INTEGER)
+ {
+ send_ipp_error(con, IPP_REQUEST_VALUE);
+
+ if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
+ attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
+ }
+ else if (job->state->values[0].integer >= IPP_JOB_PROCESSING)
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ else if (con->response->request.status.status_code == IPP_OK)
+ SetJobPriority(jobid, attr->values[0].integer);
+ }
+ else if (!strcmp(attr->name, "job-state"))
+ {
+ /*
+ * Change the job state...
+ */
+
+ if (attr->value_tag != IPP_TAG_ENUM)
+ {
+ send_ipp_error(con, IPP_REQUEST_VALUE);
+
+ if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
+ attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
+ }
+ else
+ {
+ switch (attr->values[0].integer)
+ {
+ case IPP_JOB_PENDING :
+ case IPP_JOB_HELD :
+ if (job->state->values[0].integer > IPP_JOB_HELD)
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ else if (con->response->request.status.status_code == IPP_OK)
+ job->state->values[0].integer = attr->values[0].integer;
+ break;
+
+ case IPP_JOB_PROCESSING :
+ case IPP_JOB_STOPPED :
+ if (job->state->values[0].integer != attr->values[0].integer)
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ break;
+
+ case IPP_JOB_CANCELLED :
+ case IPP_JOB_ABORTED :
+ case IPP_JOB_COMPLETED :
+ if (job->state->values[0].integer > IPP_JOB_PROCESSING)
+ {
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+ else if (con->response->request.status.status_code == IPP_OK)
+ {
+ CancelJob(job->id, 0);
+
+ if (JobHistory)
+ {
+ job->state->values[0].integer = attr->values[0].integer;
+ SaveJob(job->id);
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if (con->response->request.status.status_code != IPP_OK)
+ continue;
+ else if ((attr2 = ippFindAttribute(job->attrs, attr->name, IPP_TAG_ZERO)) != NULL)
+ {
+ /*
+ * Some other value; first free the old value...
+ */
+
+ if (job->attrs->attrs == attr2)
+ {
+ job->attrs->attrs = attr2->next;
+ prev2 = NULL;
+ }
+ else
+ {
+ for (prev2 = job->attrs->attrs; prev2 != NULL; prev2 = prev2->next)
+ if (prev2->next == attr2)
+ {
+ prev2->next = attr2->next;
+ break;
+ }
+ }
+
+ if (job->attrs->last == attr2)
+ job->attrs->last = prev2;
+
+ _ipp_free_attr(attr2);
+
+ /*
+ * Then copy the attribute...
+ */
+
+ copy_attribute(job->attrs, attr, 0);
+
+ /*
+ * See if the job-name or job-hold-until is being changed.
+ */
+
+ if (strcmp(attr->name, "job-hold-until") == 0)
+ {
+ SetJobHoldUntil(job->id, attr->values[0].string.text);
+
+ if (strcmp(attr->values[0].string.text, "no-hold") == 0)
+ ReleaseJob(job->id);
+ else
+ HoldJob(job->id);
+ }
+ }
+ else if (attr->value_tag == IPP_TAG_DELETEATTR)
+ {
+ /*
+ * Delete the attribute...
+ */
+
+ for (attr2 = job->attrs->attrs, prev2 = NULL;
+ attr2 != NULL;
+ prev2 = attr2, attr2 = attr2->next)
+ if (attr2->name && strcmp(attr2->name, attr->name) == 0)
+ break;
+
+ if (attr2)
+ {
+ if (prev2)
+ prev2->next = attr2->next;
+ else
+ job->attrs->attrs = attr2->next;
+
+ if (attr2 == job->attrs->last)
+ job->attrs->last = prev2;
+
+ _ipp_free_attr(attr2);
+ }
+ }
+ else
+ {
+ /*
+ * Add new option by copying it...
+ */
+
+ copy_attribute(job->attrs, attr, 0);
+ }
+ }
+
+ /*
+ * Save the job...
+ */
+
+ SaveJob(job->id);
+
+ /*
+ * Start jobs if possible...
+ */
+
+ CheckJobs();
+}
+
+
+/*
+ * 'start_printer()' - Start a printer.
+ */
+
+static void
+start_printer(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ const char *name; /* Printer name */
+ printer_t *printer; /* Printer data */
+
+
+ LogMessage(L_DEBUG2, "start_printer(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "start_printer: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((name = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "start_printer: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Start the printer...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(name);
+ else
+ printer = FindPrinter(name);
+
+ printer->state_message[0] = '\0';
+
+ StartPrinter(printer, 1);
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ LogMessage(L_INFO, "Class \'%s\' started by \'%s\'.", name,
+ con->username);
+ LogMessage(L_INFO, "Printer \'%s\' started by \'%s\'.", name,
+ con->username);
+
+ CheckJobs();
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'stop_printer()' - Stop a printer.
+ */
+
+static void
+stop_printer(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ const char *name; /* Printer name */
+ printer_t *printer; /* Printer data */
+ ipp_attribute_t *attr; /* printer-state-message attribute */
+
+
+ LogMessage(L_DEBUG2, "stop_printer(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Was this operation called from the correct URI?
+ */
+
+ if (strncmp(con->uri, "/admin/", 7) != 0)
+ {
+ LogMessage(L_ERROR, "stop_printer: admin request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if ((name = ValidateDest(host, resource, &dtype)) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "stop_printer: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Stop the printer...
+ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ printer = FindClass(name);
+ else
+ printer = FindPrinter(name);
+
+ if ((attr = ippFindAttribute(con->request, "printer-state-message",
+ IPP_TAG_TEXT)) == NULL)
+ strcpy(printer->state_message, "Paused");
+ else
+ {
+ strlcpy(printer->state_message, attr->values[0].string.text,
+ sizeof(printer->state_message));
+ }
+
+ StopPrinter(printer, 1);
+
+ if (dtype & CUPS_PRINTER_CLASS)
+ LogMessage(L_INFO, "Class \'%s\' stopped by \'%s\'.", name,
+ con->username);
+ else
+ LogMessage(L_INFO, "Printer \'%s\' stopped by \'%s\'.", name,
+ con->username);
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'validate_job()' - Validate printer options and destination.
+ */
+
+static void
+validate_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Printer URI */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+ ipp_attribute_t *format; /* Document-format attribute */
+ cups_ptype_t dtype; /* Destination type (printer or class) */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ char super[MIME_MAX_SUPER],
+ /* Supertype of file */
+ type[MIME_MAX_TYPE];
+ /* Subtype of file */
+
+
+ LogMessage(L_DEBUG2, "validate_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Verify that the POST operation was done to a valid URI.
+ */
+
+ if (strncmp(con->uri, "/classes/", 9) != 0 &&
+ strncmp(con->uri, "/printers/", 10) != 0)
+ {
+ LogMessage(L_ERROR, "validate_job: request on bad resource \'%s\'!",
+ con->uri);
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * OK, see if the client is sending the document compressed - CUPS
+ * doesn't support compression yet...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "compression", IPP_TAG_KEYWORD)) != NULL &&
+ strcmp(attr->values[0].string.text, "none") == 0)
+ {
+ LogMessage(L_ERROR, "validate_job: Unsupported compression attribute %s!",
+ attr->values[0].string.text);
+ send_ipp_error(con, IPP_ATTRIBUTES);
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD,
+ "compression", NULL, attr->values[0].string.text);
+ return;
+ }
+
+ /*
+ * Is it a format we support?
+ */
+
+ if ((format = ippFindAttribute(con->request, "document-format", IPP_TAG_MIMETYPE)) != NULL)
+ {
+ if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super, type) != 2)
+ {
+ LogMessage(L_ERROR, "validate_job: could not scan type \'%s\'!\n",
+ format->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ if ((strcmp(super, "application") != 0 ||
+ strcmp(type, "octet-stream") != 0) &&
+ mimeType(MimeDatabase, super, type) == NULL)
+ {
+ LogMessage(L_ERROR, "validate_job: Unsupported format \'%s\'!\n",
+ format->values[0].string.text);
+ LogMessage(L_INFO, "Hint: Do you have the raw file printing rules enabled?");
+ send_ipp_error(con, IPP_DOCUMENT_FORMAT);
+ ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format->values[0].string.text);
+ return;
+ }
+ }
+
+ /*
+ * Is the destination valid?
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (ValidateDest(host, resource, &dtype) == NULL)
+ {
+ /*
+ * Bad URI...
+ */
+
+ LogMessage(L_ERROR, "validate_job: resource name \'%s\' no good!", resource);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * Everything was ok, so return OK status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+}
+
+
+/*
+ * 'validate_user()' - Validate the user for the request.
+ */
+
+static int /* O - 1 if permitted, 0 otherwise */
+validate_user(client_t *con, /* I - Client connection */
+ const char *owner, /* I - Owner of job/resource */
+ char *username, /* O - Authenticated username */
+ int userlen) /* I - Length of username */
+{
+ int i, j; /* Looping vars */
+ ipp_attribute_t *attr; /* requesting-user-name attribute */
+ struct passwd *user; /* User info */
+ struct group *group; /* System group info */
+ char junk[33]; /* MD5 password (not used) */
+
+
+ LogMessage(L_DEBUG2, "validate_user(%p[%d], \"%s\", %p, %d)\n",
+ con, con->http.fd, owner, username, userlen);
+
+ /*
+ * Validate input...
+ */
+
+ if (con == NULL || owner == NULL || username == NULL || userlen <= 0)
+ return (0);
+
+ /*
+ * Get the best authenticated username that is available.
+ */
+
+ if (con->username[0])
+ strlcpy(username, con->username, userlen);
+ else if ((attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME)) != NULL)
+ strlcpy(username, attr->values[0].string.text, userlen);
+ else
+ strlcpy(username, "anonymous", userlen);
+
+ /*
+ * Check the username against the owner...
+ */
+
+ if (strcasecmp(username, owner) != 0 && strcasecmp(username, "root") != 0)
+ {
+ /*
+ * Not the owner or root; check to see if the user is a member of the
+ * system group...
+ */
+
+ user = getpwnam(username);
+ endpwent();
+
+ for (i = 0, j = 0, group = NULL; i < NumSystemGroups; i ++)
+ {
+ group = getgrnam(SystemGroups[i]);
+ endgrent();
+
+ if (group != NULL)
+ {
+ for (j = 0; group->gr_mem[j]; j ++)
+ if (strcasecmp(username, group->gr_mem[j]) == 0)
+ break;
+
+ if (group->gr_mem[j])
+ break;
+ }
+ else
+ j = 0;
+ }
+
+ if (user == NULL || group == NULL ||
+ (group->gr_mem[j] == NULL && group->gr_gid != user->pw_gid))
+ {
+ /*
+ * Username not found, group not found, or user is not part of the
+ * system group... Check for a user and group in the MD5 password
+ * file...
+ */
+
+ for (i = 0; i < NumSystemGroups; i ++)
+ if (GetMD5Passwd(username, SystemGroups[i], junk) != NULL)
+ return (1);
+
+ /*
+ * Nope, not an MD5 user, either. Return 0 indicating no-go...
+ */
+
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/job.c b/scheduler/job.c
new file mode 100644
index 000000000..2e069b9cd
--- /dev/null
+++ b/scheduler/job.c
@@ -0,0 +1,2845 @@
+/*
+ * "$Id$"
+ *
+ * Job management routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddJob() - Add a new job to the job queue...
+ * CancelJob() - Cancel the specified print job.
+ * CancelJobs() - Cancel all jobs for the given destination/user...
+ * CheckJobs() - Check the pending jobs and start any if the
+ * destination is available.
+ * CleanJobs() - Clean out old jobs.
+ * FreeAllJobs() - Free all jobs from memory.
+ * FindJob() - Find the specified job.
+ * GetPrinterJobCount() - Get the number of pending, processing,
+ * or held jobs in a printer or class.
+ * GetUserJobCount() - Get the number of pending, processing,
+ * or held jobs for a user.
+ * HoldJob() - Hold the specified job.
+ * LoadAllJobs() - Load all jobs from disk.
+ * LoadJob() - Load a job from disk.
+ * MoveJob() - Move the specified job to a different
+ * destination.
+ * ReleaseJob() - Release the specified job.
+ * RestartJob() - Restart the specified job.
+ * SaveJob() - Save a job to disk.
+ * SetJobHoldUntil() - Set the hold time for a job...
+ * SetJobPriority() - Set the priority of a job, moving it up/down
+ * in the list as needed.
+ * StartJob() - Start a print job.
+ * StopAllJobs() - Stop all print jobs.
+ * StopJob() - Stop a print job.
+ * UpdateJob() - Read a status update from a job's filters.
+ * ipp_length() - Compute the size of the buffer needed to hold
+ * the textual IPP attributes.
+ * start_process() - Start a background process.
+ * set_hold_until() - Set the hold time and update job-hold-until attribute.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <grp.h>
+
+
+/*
+ * Local globals...
+ */
+
+static mime_filter_t gziptoany_filter =
+ {
+ NULL, /* Source type */
+ NULL, /* Destination type */
+ 0, /* Cost */
+ "gziptoany" /* Filter program to run */
+ };
+
+
+/*
+ * Local functions...
+ */
+
+static int ipp_length(ipp_t *ipp);
+static void set_time(job_t *job, const char *name);
+static int start_process(const char *command, char *argv[],
+ char *envp[], int in, int out, int err,
+ int root, int *pid);
+static void set_hold_until(job_t *job, time_t holdtime);
+
+
+/*
+ * 'AddJob()' - Add a new job to the job queue...
+ */
+
+job_t * /* O - New job record */
+AddJob(int priority, /* I - Job priority */
+ const char *dest) /* I - Job destination */
+{
+ job_t *job, /* New job record */
+ *current, /* Current job in queue */
+ *prev; /* Previous job in queue */
+
+
+ job = calloc(sizeof(job_t), 1);
+
+ job->id = NextJobId ++;
+ job->priority = priority;
+ job->pipe = -1;
+ SetString(&job->dest, dest);
+
+ NumJobs ++;
+
+ for (current = Jobs, prev = NULL;
+ current != NULL;
+ prev = current, current = current->next)
+ if (job->priority > current->priority)
+ break;
+
+ job->next = current;
+ if (prev != NULL)
+ prev->next = job;
+ else
+ Jobs = job;
+
+ return (job);
+}
+
+
+/*
+ * 'CancelJob()' - Cancel the specified print job.
+ */
+
+void
+CancelJob(int id, /* I - Job to cancel */
+ int purge) /* I - Purge jobs? */
+{
+ int i; /* Looping var */
+ job_t *current, /* Current job */
+ *prev; /* Previous job in list */
+ char filename[1024]; /* Job filename */
+
+
+ LogMessage(L_DEBUG, "CancelJob: id = %d", id);
+
+ for (current = Jobs, prev = NULL; current != NULL; prev = current, current = current->next)
+ if (current->id == id)
+ {
+ /*
+ * Stop any processes that are working on the current...
+ */
+
+ DEBUG_puts("CancelJob: found job in list.");
+
+ if (current->state->values[0].integer == IPP_JOB_PROCESSING)
+ StopJob(current->id, 0);
+
+ current->state->values[0].integer = IPP_JOB_CANCELLED;
+
+ set_time(current, "time-at-completed");
+
+ /*
+ * Remove the print file for good if we aren't preserving jobs or
+ * files...
+ */
+
+ current->current_file = 0;
+
+ if (!JobHistory || !JobFiles || purge ||
+ (current->dtype & CUPS_PRINTER_REMOTE))
+ for (i = 1; i <= current->num_files; i ++)
+ {
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
+ current->id, i);
+ unlink(filename);
+ }
+
+ if (JobHistory && !purge && !(current->dtype & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Save job state info...
+ */
+
+ SaveJob(current->id);
+ }
+ else
+ {
+ /*
+ * Remove the job info file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot,
+ current->id);
+ unlink(filename);
+
+ /*
+ * Update pointers if we aren't preserving jobs...
+ */
+
+ if (prev == NULL)
+ Jobs = current->next;
+ else
+ prev->next = current->next;
+
+ /*
+ * Free all memory used...
+ */
+
+ if (current->attrs != NULL)
+ ippDelete(current->attrs);
+
+ if (current->num_files > 0)
+ {
+ free(current->compressions);
+ free(current->filetypes);
+ }
+
+ ClearString(&current->username);
+ ClearString(&current->dest);
+
+ free(current);
+
+ NumJobs --;
+ }
+
+ return;
+ }
+}
+
+
+/*
+ * 'CancelJobs()' - Cancel all jobs for the given destination/user...
+ */
+
+void
+CancelJobs(const char *dest, /* I - Destination to cancel */
+ const char *username, /* I - Username or NULL */
+ int purge) /* I - Purge jobs? */
+{
+ job_t *current, /* Current job */
+ *next; /* Next job */
+
+
+ for (current = Jobs; current != NULL;)
+ if ((dest == NULL || !strcmp(current->dest, dest)) &&
+ (username == NULL || !strcmp(current->username, username)))
+ {
+ /*
+ * Cancel all jobs matching this destination/user...
+ */
+
+ next = current->next;
+
+ CancelJob(current->id, purge);
+
+ current = next;
+ }
+ else
+ current = current->next;
+
+ CheckJobs();
+}
+
+
+/*
+ * 'CheckJobs()' - Check the pending jobs and start any if the destination
+ * is available.
+ */
+
+void
+CheckJobs(void)
+{
+ job_t *current, /* Current job in queue */
+ *next; /* Next job in queue */
+ printer_t *printer, /* Printer destination */
+ *pclass; /* Printer class destination */
+
+
+ DEBUG_puts("CheckJobs()");
+
+ for (current = Jobs; current != NULL; current = next)
+ {
+ /*
+ * Save next pointer in case the job is cancelled en-route.
+ */
+
+ next = current->next;
+
+ /*
+ * Start held jobs if they are ready...
+ */
+
+ if (current->state->values[0].integer == IPP_JOB_HELD &&
+ current->hold_until &&
+ current->hold_until < time(NULL))
+ current->state->values[0].integer = IPP_JOB_PENDING;
+
+ /*
+ * Start pending jobs if the destination is available...
+ */
+
+ if (current->state->values[0].integer == IPP_JOB_PENDING && !NeedReload)
+ {
+ if ((pclass = FindClass(current->dest)) != NULL)
+ {
+ /*
+ * If the class is remote, just pass it to the remote server...
+ */
+
+ if (pclass->type & CUPS_PRINTER_REMOTE)
+ printer = pclass;
+ else if (pclass->state != IPP_PRINTER_STOPPED)
+ printer = FindAvailablePrinter(current->dest);
+ else
+ printer = NULL;
+ }
+ else
+ printer = FindPrinter(current->dest);
+
+ if (printer != NULL && (printer->type & CUPS_PRINTER_IMPLICIT))
+ {
+ /*
+ * Handle implicit classes...
+ */
+
+ pclass = printer;
+
+ if (pclass->state != IPP_PRINTER_STOPPED)
+ printer = FindAvailablePrinter(current->dest);
+ else
+ printer = NULL;
+ }
+
+ if (printer == NULL && pclass == NULL)
+ {
+ /*
+ * Whoa, the printer and/or class for this destination went away;
+ * cancel the job...
+ */
+
+ LogMessage(L_WARN, "Printer/class %s has gone away; cancelling job %d!",
+ current->dest, current->id);
+ CancelJob(current->id, 1);
+ }
+ else if (printer != NULL)
+ {
+ /*
+ * See if the printer is available or remote and not printing a job;
+ * if so, start the job...
+ */
+
+ if (printer->state == IPP_PRINTER_IDLE || /* Printer is idle */
+ ((printer->type & CUPS_PRINTER_REMOTE) && /* Printer is remote */
+ !printer->job)) /* and not printing a job */
+ StartJob(current->id, printer);
+ }
+ }
+ }
+}
+
+
+/*
+ * 'CleanJobs()' - Clean out old jobs.
+ */
+
+void
+CleanJobs(void)
+{
+ job_t *job, /* Current job */
+ *next; /* Next job */
+
+
+ if (MaxJobs == 0)
+ return;
+
+ for (job = Jobs; job && NumJobs >= MaxJobs; job = next)
+ {
+ next = job->next;
+
+ if (job->state->values[0].integer >= IPP_JOB_CANCELLED)
+ CancelJob(job->id, 1);
+ }
+}
+
+
+/*
+ * 'FreeAllJobs()' - Free all jobs from memory.
+ */
+
+void
+FreeAllJobs(void)
+{
+ job_t *job, /* Current job */
+ *next; /* Next job */
+
+
+ HoldSignals();
+
+ StopAllJobs();
+
+ for (job = Jobs; job; job = next)
+ {
+ next = job->next;
+
+ ippDelete(job->attrs);
+
+ if (job->num_files > 0)
+ {
+ free(job->compressions);
+ free(job->filetypes);
+ }
+
+ free(job);
+ }
+
+ Jobs = NULL;
+
+ ReleaseSignals();
+}
+
+
+/*
+ * 'FindJob()' - Find the specified job.
+ */
+
+job_t * /* O - Job data */
+FindJob(int id) /* I - Job ID */
+{
+ job_t *current; /* Current job */
+
+
+ for (current = Jobs; current != NULL; current = current->next)
+ if (current->id == id)
+ break;
+
+ return (current);
+}
+
+
+/*
+ * 'GetPrinterJobCount()' - Get the number of pending, processing,
+ * or held jobs in a printer or class.
+ */
+
+int /* O - Job count */
+GetPrinterJobCount(const char *dest) /* I - Printer or class name */
+{
+ int count; /* Job count */
+ job_t *job; /* Current job */
+
+
+ for (job = Jobs, count = 0; job != NULL; job = job->next)
+ if (job->state->values[0].integer <= IPP_JOB_PROCESSING &&
+ strcasecmp(job->dest, dest) == 0)
+ count ++;
+
+ return (count);
+}
+
+
+/*
+ * 'GetUserJobCount()' - Get the number of pending, processing,
+ * or held jobs for a user.
+ */
+
+int /* O - Job count */
+GetUserJobCount(const char *username) /* I - Username */
+{
+ int count; /* Job count */
+ job_t *job; /* Current job */
+
+
+ for (job = Jobs, count = 0; job != NULL; job = job->next)
+ if (job->state->values[0].integer <= IPP_JOB_PROCESSING &&
+ strcmp(job->username, username) == 0)
+ count ++;
+
+ return (count);
+}
+
+
+/*
+ * 'HoldJob()' - Hold the specified job.
+ */
+
+void
+HoldJob(int id) /* I - Job ID */
+{
+ job_t *job; /* Job data */
+
+
+ LogMessage(L_DEBUG, "HoldJob: id = %d", id);
+
+ if ((job = FindJob(id)) == NULL)
+ return;
+
+ if (job->state->values[0].integer == IPP_JOB_PROCESSING)
+ StopJob(id, 0);
+
+ DEBUG_puts("HoldJob: setting state to held...");
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+
+ SaveJob(id);
+
+ CheckJobs();
+}
+
+
+/*
+ * 'LoadAllJobs()' - Load all jobs from disk.
+ */
+
+void
+LoadAllJobs(void)
+{
+ DIR *dir; /* Directory */
+ DIRENT *dent; /* Directory entry */
+ char filename[1024]; /* Full filename of job file */
+ int fd; /* File descriptor */
+ job_t *job, /* New job */
+ *current, /* Current job */
+ *prev; /* Previous job */
+ int jobid, /* Current job ID */
+ fileid; /* Current file ID */
+ ipp_attribute_t *attr; /* Job attribute */
+ char method[HTTP_MAX_URI],
+ /* Method portion of URI */
+ username[HTTP_MAX_URI],
+ /* Username portion of URI */
+ host[HTTP_MAX_URI],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ printer_t *p; /* Printer or class */
+ const char *dest; /* Destination */
+ mime_type_t **filetypes; /* New filetypes array */
+ int *compressions; /* New compressions array */
+
+
+ /*
+ * First open the requests directory...
+ */
+
+ LogMessage(L_DEBUG, "LoadAllJobs: Scanning %s...", RequestRoot);
+
+ NumJobs = 0;
+
+ if ((dir = opendir(RequestRoot)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Unable to open spool directory %s: %s",
+ RequestRoot, strerror(errno));
+ return;
+ }
+
+ /*
+ * Read all the c##### files...
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ if (NAMLEN(dent) >= 6 && dent->d_name[0] == 'c')
+ {
+ /*
+ * Allocate memory for the job...
+ */
+
+ if ((job = calloc(sizeof(job_t), 1)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Ran out of memory for jobs!");
+ closedir(dir);
+ return;
+ }
+
+ if ((job->attrs = ippNew()) == NULL)
+ {
+ free(job);
+ LogMessage(L_ERROR, "LoadAllJobs: Ran out of memory for job attributes!");
+ closedir(dir);
+ return;
+ }
+
+ /*
+ * Assign the job ID...
+ */
+
+ job->id = atoi(dent->d_name + 1);
+ job->pipe = -1;
+
+ LogMessage(L_DEBUG, "LoadAllJobs: Loading attributes for job %d...\n",
+ job->id);
+
+ if (job->id >= NextJobId)
+ NextJobId = job->id + 1;
+
+ /*
+ * Load the job control file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", RequestRoot, dent->d_name);
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Unable to open job control file \"%s\" - %s!",
+ filename, strerror(errno));
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+ else
+ {
+ if (ippReadFile(fd, job->attrs) != IPP_DATA)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Unable to read job control file \"%s\"!",
+ filename);
+ close(fd);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+
+ close(fd);
+ }
+
+ if ((job->state = ippFindAttribute(job->attrs, "job-state", IPP_TAG_ENUM)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Missing or bad job-state attribute in control file \"%s\"!",
+ filename);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+
+ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri", IPP_TAG_URI)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: No job-printer-uri attribute in control file \"%s\"!",
+ filename);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+
+ httpSeparate(attr->values[0].string.text, method, username, host,
+ &port, resource);
+
+ if ((dest = ValidateDest(host, resource, &(job->dtype))) == NULL &&
+ job->state != NULL &&
+ job->state->values[0].integer <= IPP_JOB_PROCESSING)
+ {
+ /*
+ * Job queued on remote printer or class, so add it...
+ */
+
+ if (strncmp(resource, "/classes/", 9) == 0)
+ {
+ p = AddClass(resource + 9);
+ SetString(&p->make_model, "Remote Class on unknown");
+ }
+ else
+ {
+ p = AddPrinter(resource + 10);
+ SetString(&p->make_model, "Remote Printer on unknown");
+ }
+
+ p->state = IPP_PRINTER_STOPPED;
+ p->type |= CUPS_PRINTER_REMOTE;
+ p->browse_time = 2147483647;
+
+ SetString(&p->location, "Location Unknown");
+ SetString(&p->info, "No Information Available");
+ p->hostname[0] = '\0';
+
+ SetPrinterAttrs(p);
+ dest = p->name;
+ }
+
+ if (dest == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Unable to queue job for destination \"%s\"!",
+ attr->values[0].string.text);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+
+ SetString(&job->dest, dest);
+
+ job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed",
+ IPP_TAG_INTEGER);
+ job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-priority", IPP_TAG_INTEGER)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Missing or bad job-priority attribute in control file \"%s\"!",
+ filename);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+ job->priority = attr->values[0].integer;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-originating-user-name", IPP_TAG_NAME)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Missing or bad job-originating-user-name attribute in control file \"%s\"!",
+ filename);
+ ippDelete(job->attrs);
+ free(job);
+ unlink(filename);
+ continue;
+ }
+ SetString(&job->username, attr->values[0].string.text);
+
+ /*
+ * Insert the job into the array, sorting by job priority and ID...
+ */
+
+ for (current = Jobs, prev = NULL;
+ current != NULL;
+ prev = current, current = current->next)
+ if (job->priority > current->priority)
+ break;
+ else if (job->priority == current->priority && job->id < current->id)
+ break;
+
+ job->next = current;
+ if (prev != NULL)
+ prev->next = job;
+ else
+ Jobs = job;
+
+ NumJobs ++;
+
+ /*
+ * Set the job hold-until time and state...
+ */
+
+ if (job->state->values[0].integer == IPP_JOB_HELD)
+ {
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr == NULL)
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ else
+ SetJobHoldUntil(job->id, attr->values[0].string.text);
+ }
+ else if (job->state->values[0].integer == IPP_JOB_PROCESSING)
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ }
+
+ /*
+ * Read all the d##### files...
+ */
+
+ rewinddir(dir);
+
+ while ((dent = readdir(dir)) != NULL)
+ if (NAMLEN(dent) > 7 && dent->d_name[0] == 'd' && strchr(dent->d_name, '-'))
+ {
+ /*
+ * Find the job...
+ */
+
+ jobid = atoi(dent->d_name + 1);
+ fileid = atoi(strchr(dent->d_name, '-') + 1);
+
+ LogMessage(L_DEBUG, "LoadAllJobs: Auto-typing document file %s...",
+ dent->d_name);
+
+ snprintf(filename, sizeof(filename), "%s/%s", RequestRoot, dent->d_name);
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Orphaned print file \"%s\"!",
+ filename);
+ unlink(filename);
+ continue;
+ }
+
+ if (fileid > job->num_files)
+ {
+ if (job->num_files == 0)
+ {
+ compressions = (int *)calloc(fileid, sizeof(int));
+ filetypes = (mime_type_t **)calloc(fileid, sizeof(mime_type_t *));
+ }
+ else
+ {
+ compressions = (int *)realloc(job->compressions,
+ sizeof(int) * fileid);
+ filetypes = (mime_type_t **)realloc(job->filetypes,
+ sizeof(mime_type_t *) * fileid);
+ }
+
+ if (compressions == NULL || filetypes == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllJobs: Ran out of memory for job file types!");
+ continue;
+ }
+
+ job->compressions = compressions;
+ job->filetypes = filetypes;
+ job->num_files = fileid;
+ }
+
+ job->filetypes[fileid - 1] = mimeFileType(MimeDatabase, filename,
+ job->compressions + fileid - 1);
+
+ if (job->filetypes[fileid - 1] == NULL)
+ job->filetypes[fileid - 1] = mimeType(MimeDatabase, "application",
+ "vnd.cups-raw");
+ }
+
+ closedir(dir);
+
+ /*
+ * Clean out old jobs as needed...
+ */
+
+ CleanJobs();
+}
+
+
+/*
+ * 'MoveJob()' - Move the specified job to a different destination.
+ */
+
+void
+MoveJob(int id, /* I - Job ID */
+ const char *dest) /* I - Destination */
+{
+ job_t *current;/* Current job */
+ ipp_attribute_t *attr; /* job-printer-uri attribute */
+ printer_t *p; /* Destination printer or class */
+
+
+ if ((p = FindPrinter(dest)) == NULL)
+ p = FindClass(dest);
+
+ if (p == NULL)
+ return;
+
+ for (current = Jobs; current != NULL; current = current->next)
+ if (current->id == id)
+ {
+ if (current->state->values[0].integer >= IPP_JOB_PROCESSING)
+ break;
+
+ SetString(&current->dest, dest);
+ current->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
+ CUPS_PRINTER_IMPLICIT);
+
+ if ((attr = ippFindAttribute(current->attrs, "job-printer-uri", IPP_TAG_URI)) != NULL)
+ {
+ free(attr->values[0].string.text);
+ attr->values[0].string.text = strdup(p->uri);
+ }
+
+ SaveJob(current->id);
+
+ return;
+ }
+}
+
+
+/*
+ * 'ReleaseJob()' - Release the specified job.
+ */
+
+void
+ReleaseJob(int id) /* I - Job ID */
+{
+ job_t *job; /* Job data */
+
+
+ LogMessage(L_DEBUG, "ReleaseJob: id = %d", id);
+
+ if ((job = FindJob(id)) == NULL)
+ return;
+
+ if (job->state->values[0].integer == IPP_JOB_HELD)
+ {
+ DEBUG_puts("ReleaseJob: setting state to pending...");
+
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ SaveJob(id);
+ CheckJobs();
+ }
+}
+
+
+/*
+ * 'RestartJob()' - Restart the specified job.
+ */
+
+void
+RestartJob(int id) /* I - Job ID */
+{
+ job_t *job; /* Job data */
+
+
+ if ((job = FindJob(id)) == NULL)
+ return;
+
+ if (job->state->values[0].integer == IPP_JOB_STOPPED || JobFiles)
+ {
+ job->tries = 0;
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ SaveJob(id);
+ CheckJobs();
+ }
+}
+
+
+/*
+ * 'SaveJob()' - Save a job to disk.
+ */
+
+void
+SaveJob(int id) /* I - Job ID */
+{
+ job_t *job; /* Pointer to job */
+ char filename[1024]; /* Job control filename */
+ int fd; /* File descriptor */
+
+
+ if ((job = FindJob(id)) == NULL)
+ return;
+
+ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, id);
+
+ if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
+ {
+ LogMessage(L_ERROR, "SaveJob: Unable to create job control file \"%s\" - %s.",
+ filename, strerror(errno));
+ return;
+ }
+
+ fchmod(fd, 0600);
+ fchown(fd, RunUser, Group);
+
+ ippWriteFile(fd, job->attrs);
+
+ LogMessage(L_DEBUG2, "SaveJob: Closing file %d...", fd);
+
+ close(fd);
+}
+
+
+/*
+ * 'SetJobHoldUntil()' - Set the hold time for a job...
+ */
+
+void
+SetJobHoldUntil(int id, /* I - Job ID */
+ const char *when) /* I - When to resume */
+{
+ job_t *job; /* Pointer to job */
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
+ int hour; /* Hold hour */
+ int minute; /* Hold minute */
+ int second; /* Hold second */
+
+
+ LogMessage(L_DEBUG, "SetJobHoldUntil(%d, \"%s\")", id, when);
+
+ if ((job = FindJob(id)) == NULL)
+ return;
+
+ second = 0;
+
+ if (strcmp(when, "indefinite") == 0)
+ {
+ /*
+ * Hold indefinitely...
+ */
+
+ job->hold_until = 0;
+ }
+ else if (strcmp(when, "day-time") == 0)
+ {
+ /*
+ * Hold to 6am the next morning unless local time is < 6pm.
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+
+ if (curdate->tm_hour < 18)
+ job->hold_until = curtime;
+ else
+ job->hold_until = curtime +
+ ((29 - curdate->tm_hour) * 60 + 59 -
+ curdate->tm_min) * 60 + 60 - curdate->tm_sec;
+ }
+ else if (strcmp(when, "evening") == 0 || strcmp(when, "night") == 0)
+ {
+ /*
+ * Hold to 6pm unless local time is > 6pm or < 6am.
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+
+ if (curdate->tm_hour < 6 || curdate->tm_hour >= 18)
+ job->hold_until = curtime;
+ else
+ job->hold_until = curtime +
+ ((17 - curdate->tm_hour) * 60 + 59 -
+ curdate->tm_min) * 60 + 60 - curdate->tm_sec;
+ }
+ else if (strcmp(when, "second-shift") == 0)
+ {
+ /*
+ * Hold to 4pm unless local time is > 4pm.
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+
+ if (curdate->tm_hour >= 16)
+ job->hold_until = curtime;
+ else
+ job->hold_until = curtime +
+ ((15 - curdate->tm_hour) * 60 + 59 -
+ curdate->tm_min) * 60 + 60 - curdate->tm_sec;
+ }
+ else if (strcmp(when, "third-shift") == 0)
+ {
+ /*
+ * Hold to 12am unless local time is < 8am.
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+
+ if (curdate->tm_hour < 8)
+ job->hold_until = curtime;
+ else
+ job->hold_until = curtime +
+ ((23 - curdate->tm_hour) * 60 + 59 -
+ curdate->tm_min) * 60 + 60 - curdate->tm_sec;
+ }
+ else if (strcmp(when, "weekend") == 0)
+ {
+ /*
+ * Hold to weekend unless we are in the weekend.
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+
+ if (curdate->tm_wday == 0 || curdate->tm_wday == 6)
+ job->hold_until = curtime;
+ else
+ job->hold_until = curtime +
+ (((5 - curdate->tm_wday) * 24 +
+ (17 - curdate->tm_hour)) * 60 + 59 -
+ curdate->tm_min) * 60 + 60 - curdate->tm_sec;
+ }
+ else if (sscanf(when, "%d:%d:%d", &hour, &minute, &second) >= 2)
+ {
+ /*
+ * Hold to specified GMT time (HH:MM or HH:MM:SS)...
+ */
+
+ curtime = time(NULL);
+ curdate = gmtime(&curtime);
+
+ job->hold_until = curtime +
+ ((hour - curdate->tm_hour) * 60 + minute -
+ curdate->tm_min) * 60 + second - curdate->tm_sec;
+
+ /*
+ * Hold until next day as needed...
+ */
+
+ if (job->hold_until < curtime)
+ job->hold_until += 24 * 60 * 60 * 60;
+ }
+
+ LogMessage(L_DEBUG, "SetJobHoldUntil: hold_until = %d", (int)job->hold_until);
+}
+
+
+/*
+ * 'SetJobPriority()' - Set the priority of a job, moving it up/down in the
+ * list as needed.
+ */
+
+void
+SetJobPriority(int id, /* I - Job ID */
+ int priority) /* I - New priority (0 to 100) */
+{
+ job_t *job, /* Job to change */
+ *current, /* Current job */
+ *prev; /* Previous job */
+ ipp_attribute_t *attr; /* Job attribute */
+
+
+ /*
+ * Find the job...
+ */
+
+ for (current = Jobs, prev = NULL;
+ current != NULL;
+ prev = current, current = current->next)
+ if (current->id == id)
+ break;
+
+ if (current == NULL)
+ return;
+
+ /*
+ * Set the new priority...
+ */
+
+ job = current;
+ job->priority = priority;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-priority", IPP_TAG_INTEGER)) != NULL)
+ attr->values[0].integer = priority;
+ else
+ ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-priority",
+ priority);
+
+ SaveJob(job->id);
+
+ /*
+ * See if we need to do any sorting...
+ */
+
+ if ((prev == NULL || job->priority < prev->priority) &&
+ (job->next == NULL || job->next->priority < job->priority))
+ return;
+
+ /*
+ * Remove the job from the list, and then insert it where it belongs...
+ */
+
+ if (prev == NULL)
+ Jobs = job->next;
+ else
+ prev->next = job->next;
+
+ for (current = Jobs, prev = NULL;
+ current != NULL;
+ prev = current, current = current->next)
+ if (job->priority > current->priority)
+ break;
+
+ job->next = current;
+ if (prev != NULL)
+ prev->next = job;
+ else
+ Jobs = job;
+}
+
+
+/*
+ * 'StartJob()' - Start a print job.
+ */
+
+void
+StartJob(int id, /* I - Job ID */
+ printer_t *printer) /* I - Printer to print job */
+{
+ job_t *current; /* Current job */
+ int i; /* Looping var */
+ int slot; /* Pipe slot */
+ int num_filters; /* Number of filters for job */
+ mime_filter_t *filters; /* Filters for job */
+ char method[255], /* Method for output */
+ *optptr, /* Pointer to options */
+ *valptr; /* Pointer in value string */
+ ipp_attribute_t *attr; /* Current attribute */
+ int pid; /* Process ID of new filter process */
+ int banner_page; /* 1 if banner page, 0 otherwise */
+ int statusfds[2], /* Pipes used between the filters and scheduler */
+ filterfds[2][2]; /* Pipes used between the filters */
+ int envc; /* Number of environment variables */
+ char *argv[8], /* Filter command-line arguments */
+ filename[1024], /* Job filename */
+ command[1024], /* Full path to filter/backend command */
+ jobid[255], /* Job ID string */
+ title[IPP_MAX_NAME], /* Job title string */
+ copies[255], /* # copies string */
+ *envp[100], /* Environment variables */
+#ifdef __APPLE__
+ processPath[1050], /* CFProcessPath environment variable */
+#endif /* __APPLE__ */
+ path[1024], /* PATH environment variable */
+ ipp_port[1024], /* IPP_PORT environment variable */
+ language[255], /* LANG environment variable */
+ charset[255], /* CHARSET environment variable */
+ classification[1024], /* CLASSIFICATION environment variable */
+ content_type[1024], /* CONTENT_TYPE environment variable */
+ device_uri[1024], /* DEVICE_URI environment variable */
+ sani_uri[1024], /* Sanitized DEVICE_URI env var */
+ ppd[1024], /* PPD environment variable */
+ class_name[255], /* CLASS environment variable */
+ printer_name[255], /* PRINTER environment variable */
+ root[1024], /* CUPS_SERVERROOT environment variable */
+ cache[255], /* RIP_MAX_CACHE environment variable */
+ tmpdir[1024], /* TMPDIR environment variable */
+ ld_library_path[1024], /* LD_LIBRARY_PATH environment variable */
+ ld_preload[1024], /* LD_PRELOAD environment variable */
+ dyld_library_path[1024],/* DYLD_LIBRARY_PATH environment variable */
+ shlib_path[1024], /* SHLIB_PATH environment variable */
+ nlspath[1024], /* NLSPATH environment variable */
+ datadir[1024], /* CUPS_DATADIR environment variable */
+ fontpath[1050], /* CUPS_FONTPATH environment variable */
+ vg_args[1024], /* VG_ARGS environment variable */
+ ld_assume_kernel[1024]; /* LD_ASSUME_KERNEL environment variable */
+ static char *options = NULL; /* Full list of options */
+ static int optlength = 0; /* Length of option buffer */
+
+
+ LogMessage(L_DEBUG, "StartJob(%d, %p)", id, printer);
+
+ for (current = Jobs; current != NULL; current = current->next)
+ if (current->id == id)
+ break;
+
+ if (current == NULL)
+ return;
+
+ LogMessage(L_DEBUG, "StartJob() id = %d, file = %d/%d", id,
+ current->current_file, current->num_files);
+
+ if (current->num_files == 0)
+ {
+ LogMessage(L_ERROR, "Job ID %d has no files! Cancelling it!", id);
+ CancelJob(id, 0);
+ return;
+ }
+
+ /*
+ * Figure out what filters are required to convert from
+ * the source to the destination type...
+ */
+
+ num_filters = 0;
+ current->cost = 0;
+
+ if (printer->raw)
+ {
+ /*
+ * Remote jobs and raw queues go directly to the printer without
+ * filtering...
+ */
+
+ LogMessage(L_DEBUG, "StartJob: Sending job to queue tagged as raw...");
+
+ filters = NULL;
+ }
+ else
+ {
+ /*
+ * Local jobs get filtered...
+ */
+
+ filters = mimeFilter(MimeDatabase, current->filetypes[current->current_file],
+ printer->filetype, &num_filters, MAX_FILTERS - 1);
+
+ if (num_filters == 0)
+ {
+ LogMessage(L_ERROR, "Unable to convert file %d to printable format for job %d!",
+ current->current_file, current->id);
+ LogMessage(L_INFO, "Hint: Do you have ESP Ghostscript installed?");
+
+ if (LogLevel < L_DEBUG)
+ LogMessage(L_INFO, "Hint: Try setting the LogLevel to \"debug\".");
+
+ current->current_file ++;
+
+ if (current->current_file == current->num_files)
+ CancelJob(current->id, 0);
+
+ return;
+ }
+
+ /*
+ * Remove NULL ("-") filters...
+ */
+
+ for (i = 0; i < num_filters;)
+ if (strcmp(filters[i].filter, "-") == 0)
+ {
+ num_filters --;
+ if (i < num_filters)
+ memcpy(filters + i, filters + i + 1,
+ (num_filters - i) * sizeof(mime_filter_t));
+ }
+ else
+ i ++;
+
+ if (num_filters == 0)
+ {
+ free(filters);
+ filters = NULL;
+ }
+ else
+ {
+ /*
+ * Compute filter cost...
+ */
+
+ for (i = 0; i < num_filters; i ++)
+ current->cost += filters[i].cost;
+ }
+ }
+
+ /*
+ * See if the filter cost is too high...
+ */
+
+ if ((FilterLevel + current->cost) > FilterLimit && FilterLevel > 0 &&
+ FilterLimit > 0)
+ {
+ /*
+ * Don't print this job quite yet...
+ */
+
+ if (filters != NULL)
+ free(filters);
+
+ LogMessage(L_INFO, "Holding job %d because filter limit has been reached.",
+ id);
+ LogMessage(L_DEBUG, "StartJob: id = %d, file = %d, "
+ "cost = %d, level = %d, limit = %d",
+ id, current->current_file, current->cost, FilterLevel,
+ FilterLimit);
+ return;
+ }
+
+ FilterLevel += current->cost;
+
+ /*
+ * Add decompression filters, if any...
+ */
+
+ if (current->compressions[current->current_file])
+ {
+ /*
+ * Add gziptoany filter to the front of the list...
+ */
+
+ mime_filter_t *temp_filters;
+
+ if (num_filters == 0)
+ temp_filters = malloc(sizeof(mime_filter_t));
+ else
+ temp_filters = realloc(filters,
+ sizeof(mime_filter_t) * (num_filters + 1));
+
+ if (temp_filters == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to add decompression filter - %s",
+ strerror(errno));
+
+ if (filters != NULL)
+ free(filters);
+
+ current->current_file ++;
+
+ if (current->current_file == current->num_files)
+ CancelJob(current->id, 0);
+
+ return;
+ }
+
+ filters = temp_filters;
+ memmove(filters + 1, filters, num_filters * sizeof(mime_filter_t));
+ *filters = gziptoany_filter;
+ num_filters ++;
+ }
+
+ /*
+ * Update the printer and job state to "processing"...
+ */
+
+ current->state->values[0].integer = IPP_JOB_PROCESSING;
+ current->status = 0;
+ current->printer = printer;
+ printer->job = current;
+ SetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);
+
+ if (current->current_file == 0)
+ set_time(current, "time-at-processing");
+
+ /*
+ * Determine if we are printing a banner page or not...
+ */
+
+ if (current->job_sheets == NULL)
+ {
+ LogMessage(L_DEBUG, "No job-sheets attribute.");
+ if ((current->job_sheets =
+ ippFindAttribute(current->attrs, "job-sheets", IPP_TAG_ZERO)) != NULL)
+ LogMessage(L_DEBUG, "... but someone added one without setting job_sheets!");
+ }
+ else if (current->job_sheets->num_values == 1)
+ LogMessage(L_DEBUG, "job-sheets=%s",
+ current->job_sheets->values[0].string.text);
+ else
+ LogMessage(L_DEBUG, "job-sheets=%s,%s",
+ current->job_sheets->values[0].string.text,
+ current->job_sheets->values[1].string.text);
+
+ if (printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+ banner_page = 0;
+ else if (current->job_sheets == NULL)
+ banner_page = 0;
+ else if (strcasecmp(current->job_sheets->values[0].string.text, "none") != 0 &&
+ current->current_file == 0)
+ banner_page = 1;
+ else if (current->job_sheets->num_values > 1 &&
+ strcasecmp(current->job_sheets->values[1].string.text, "none") != 0 &&
+ current->current_file == (current->num_files - 1))
+ banner_page = 1;
+ else
+ banner_page = 0;
+
+ LogMessage(L_DEBUG, "banner_page = %d", banner_page);
+
+ /*
+ * Building the options string is harder than it needs to be, but
+ * for the moment we need to pass strings for command-line args and
+ * not IPP attribute pointers... :)
+ *
+ * First allocate/reallocate the option buffer as needed...
+ */
+
+ i = ipp_length(current->attrs);
+
+ if (i > optlength)
+ {
+ if (optlength == 0)
+ optptr = malloc(i);
+ else
+ optptr = realloc(options, i);
+
+ if (optptr == NULL)
+ {
+ LogMessage(L_CRIT, "StartJob: Unable to allocate %d bytes for option buffer for job %d!",
+ i, id);
+
+ if (filters != NULL)
+ free(filters);
+
+ FilterLevel -= current->cost;
+
+ CancelJob(id, 0);
+ return;
+ }
+
+ options = optptr;
+ optlength = i;
+ }
+
+ /*
+ * Now loop through the attributes and convert them to the textual
+ * representation used by the filters...
+ */
+
+ optptr = options;
+ *optptr = '\0';
+
+ snprintf(title, sizeof(title), "%s-%d", printer->name, current->id);
+ strcpy(copies, "1");
+
+ for (attr = current->attrs->attrs; attr != NULL; attr = attr->next)
+ {
+ if (strcmp(attr->name, "copies") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ {
+ /*
+ * Don't use the # copies attribute if we are printing the job sheets...
+ */
+
+ if (!banner_page)
+ sprintf(copies, "%d", attr->values[0].integer);
+ }
+ else if (strcmp(attr->name, "job-name") == 0 &&
+ (attr->value_tag == IPP_TAG_NAME ||
+ attr->value_tag == IPP_TAG_NAMELANG))
+ strlcpy(title, attr->values[0].string.text, sizeof(title));
+ else if (attr->group_tag == IPP_TAG_JOB)
+ {
+ /*
+ * Filter out other unwanted attributes...
+ */
+
+ if (attr->value_tag == IPP_TAG_MIMETYPE ||
+ attr->value_tag == IPP_TAG_NAMELANG ||
+ attr->value_tag == IPP_TAG_TEXTLANG ||
+ attr->value_tag == IPP_TAG_URI ||
+ attr->value_tag == IPP_TAG_URISCHEME ||
+ attr->value_tag == IPP_TAG_BEGIN_COLLECTION) /* Not yet supported */
+ continue;
+
+ if (strncmp(attr->name, "time-", 5) == 0)
+ continue;
+
+ if (strncmp(attr->name, "job-", 4) == 0 &&
+ !(printer->type & CUPS_PRINTER_REMOTE))
+ continue;
+
+ if (strncmp(attr->name, "job-", 4) == 0 &&
+ strcmp(attr->name, "job-billing") != 0 &&
+ strcmp(attr->name, "job-sheets") != 0 &&
+ strcmp(attr->name, "job-hold-until") != 0 &&
+ strcmp(attr->name, "job-priority") != 0)
+ continue;
+
+ if ((strcmp(attr->name, "page-label") == 0 ||
+ strcmp(attr->name, "page-border") == 0 ||
+ strncmp(attr->name, "number-up", 9) == 0 ||
+ strcmp(attr->name, "page-set") == 0) &&
+ banner_page)
+ continue;
+
+ /*
+ * Otherwise add them to the list...
+ */
+
+ if (optptr > options)
+ strlcat(optptr, " ", optlength - (optptr - options));
+
+ if (attr->value_tag != IPP_TAG_BOOLEAN)
+ {
+ strlcat(optptr, attr->name, optlength - (optptr - options));
+ strlcat(optptr, "=", optlength - (optptr - options));
+ }
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (i)
+ strlcat(optptr, ",", optlength - (optptr - options));
+
+ optptr += strlen(optptr);
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ snprintf(optptr, optlength - (optptr - options),
+ "%d", attr->values[i].integer);
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ if (!attr->values[i].boolean)
+ strlcat(optptr, "no", optlength - (optptr - options));
+
+ case IPP_TAG_NOVALUE :
+ strlcat(optptr, attr->name,
+ optlength - (optptr - options));
+ break;
+
+ case IPP_TAG_RANGE :
+ if (attr->values[i].range.lower == attr->values[i].range.upper)
+ snprintf(optptr, optlength - (optptr - options) - 1,
+ "%d", attr->values[i].range.lower);
+ else
+ snprintf(optptr, optlength - (optptr - options) - 1,
+ "%d-%d", attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ snprintf(optptr, optlength - (optptr - options) - 1,
+ "%dx%d%s", attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ break;
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ for (valptr = attr->values[i].string.text; *valptr;)
+ {
+ if (strchr(" \t\n\\\'\"", *valptr))
+ *optptr++ = '\\';
+ *optptr++ = *valptr++;
+ }
+
+ *optptr = '\0';
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+ }
+
+ optptr += strlen(optptr);
+ }
+ }
+
+ /*
+ * Build the command-line arguments for the filters. Each filter
+ * has 6 or 7 arguments:
+ *
+ * argv[0] = printer
+ * argv[1] = job ID
+ * argv[2] = username
+ * argv[3] = title
+ * argv[4] = # copies
+ * argv[5] = options
+ * argv[6] = filename (optional; normally stdin)
+ *
+ * This allows legacy printer drivers that use the old System V
+ * printing interface to be used by CUPS.
+ */
+
+ sprintf(jobid, "%d", current->id);
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
+ current->id, current->current_file + 1);
+
+ argv[0] = printer->name;
+ argv[1] = jobid;
+ argv[2] = current->username;
+ argv[3] = title;
+ argv[4] = copies;
+ argv[5] = options;
+ argv[6] = filename;
+ argv[7] = NULL;
+
+ LogMessage(L_DEBUG, "StartJob: argv = \"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"",
+ argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
+
+ /*
+ * Create environment variable strings for the filters...
+ */
+
+ attr = ippFindAttribute(current->attrs, "attributes-natural-language",
+ IPP_TAG_LANGUAGE);
+
+ switch (strlen(attr->values[0].string.text))
+ {
+ default :
+ /*
+ * This is an unknown or badly formatted language code; use
+ * the POSIX locale...
+ */
+
+ strcpy(language, "LANG=C");
+ break;
+
+ case 2 :
+ /*
+ * Just the language code (ll)...
+ */
+
+ snprintf(language, sizeof(language), "LANG=%s",
+ attr->values[0].string.text);
+ break;
+
+ case 5 :
+ /*
+ * Language and country code (ll-cc)...
+ */
+
+ snprintf(language, sizeof(language), "LANG=%c%c_%c%c",
+ attr->values[0].string.text[0],
+ attr->values[0].string.text[1],
+ toupper(attr->values[0].string.text[3] & 255),
+ toupper(attr->values[0].string.text[4] & 255));
+ break;
+ }
+
+ attr = ippFindAttribute(current->attrs, "document-format",
+ IPP_TAG_MIMETYPE);
+ if (attr != NULL &&
+ (optptr = strstr(attr->values[0].string.text, "charset=")) != NULL)
+ snprintf(charset, sizeof(charset), "CHARSET=%s", optptr + 8);
+ else
+ {
+ attr = ippFindAttribute(current->attrs, "attributes-charset",
+ IPP_TAG_CHARSET);
+ snprintf(charset, sizeof(charset), "CHARSET=%s",
+ attr->values[0].string.text);
+ }
+
+ snprintf(path, sizeof(path), "PATH=%s/filter:/bin:/usr/bin", ServerBin);
+ snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
+ current->filetypes[current->current_file]->super,
+ current->filetypes[current->current_file]->type);
+ snprintf(device_uri, sizeof(device_uri), "DEVICE_URI=%s", printer->device_uri);
+ cupsdSanitizeURI(printer->device_uri, sani_uri, sizeof(sani_uri));
+ snprintf(ppd, sizeof(ppd), "PPD=%s/ppd/%s.ppd", ServerRoot, printer->name);
+ snprintf(printer_name, sizeof(printer_name), "PRINTER=%s", printer->name);
+ snprintf(cache, sizeof(cache), "RIP_MAX_CACHE=%s", RIPCache);
+ snprintf(root, sizeof(root), "CUPS_SERVERROOT=%s", ServerRoot);
+ snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
+ snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
+ snprintf(fontpath, sizeof(fontpath), "CUPS_FONTPATH=%s", FontPath);
+ sprintf(ipp_port, "IPP_PORT=%d", LocalPort);
+
+ envc = 0;
+
+ envp[envc ++] = path;
+ envp[envc ++] = "SOFTWARE=CUPS/1.1";
+ envp[envc ++] = "USER=root";
+ envp[envc ++] = charset;
+ envp[envc ++] = language;
+ if (TZ && TZ[0])
+ envp[envc ++] = TZ;
+ envp[envc ++] = ppd;
+ envp[envc ++] = root;
+ envp[envc ++] = cache;
+ envp[envc ++] = tmpdir;
+ envp[envc ++] = content_type;
+ envp[envc ++] = device_uri;
+ envp[envc ++] = printer_name;
+ envp[envc ++] = datadir;
+ envp[envc ++] = fontpath;
+ envp[envc ++] = "CUPS_SERVER=localhost";
+ envp[envc ++] = ipp_port;
+
+ if (getenv("VG_ARGS") != NULL)
+ {
+ snprintf(vg_args, sizeof(vg_args), "VG_ARGS=%s", getenv("VG_ARGS"));
+ envp[envc ++] = vg_args;
+ }
+
+ if (getenv("LD_ASSUME_KERNEL") != NULL)
+ {
+ snprintf(ld_assume_kernel, sizeof(ld_assume_kernel), "LD_ASSUME_KERNEL=%s",
+ getenv("LD_ASSUME_KERNEL"));
+ envp[envc ++] = ld_assume_kernel;
+ }
+
+ if (getenv("LD_LIBRARY_PATH") != NULL)
+ {
+ snprintf(ld_library_path, sizeof(ld_library_path), "LD_LIBRARY_PATH=%s",
+ getenv("LD_LIBRARY_PATH"));
+ envp[envc ++] = ld_library_path;
+ }
+
+ if (getenv("LD_PRELOAD") != NULL)
+ {
+ snprintf(ld_preload, sizeof(ld_preload), "LD_PRELOAD=%s",
+ getenv("LD_PRELOAD"));
+ envp[envc ++] = ld_preload;
+ }
+
+ if (getenv("DYLD_LIBRARY_PATH") != NULL)
+ {
+ snprintf(dyld_library_path, sizeof(dyld_library_path), "DYLD_LIBRARY_PATH=%s",
+ getenv("DYLD_LIBRARY_PATH"));
+ envp[envc ++] = dyld_library_path;
+ }
+
+ if (getenv("SHLIB_PATH") != NULL)
+ {
+ snprintf(shlib_path, sizeof(shlib_path), "SHLIB_PATH=%s",
+ getenv("SHLIB_PATH"));
+ envp[envc ++] = shlib_path;
+ }
+
+ if (getenv("NLSPATH") != NULL)
+ {
+ snprintf(nlspath, sizeof(nlspath), "NLSPATH=%s", getenv("NLSPATH"));
+ envp[envc ++] = nlspath;
+ }
+
+ if (Classification && !banner_page)
+ {
+ if ((attr = ippFindAttribute(current->attrs, "job-sheets",
+ IPP_TAG_NAME)) == NULL)
+ snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+ Classification);
+ else if (attr->num_values > 1 &&
+ strcmp(attr->values[1].string.text, "none") != 0)
+ snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+ attr->values[1].string.text);
+ else
+ snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
+ attr->values[0].string.text);
+
+ envp[envc ++] = classification;
+ }
+
+ if (current->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ {
+ snprintf(class_name, sizeof(class_name), "CLASS=%s", current->dest);
+ envp[envc ++] = class_name;
+ }
+
+#ifdef __APPLE__
+ strlcpy(processPath, "<CFProcessPath>", sizeof(processPath));
+ envp[envc ++] = processPath;
+#endif /* __APPLE__ */
+
+ envp[envc] = NULL;
+
+ for (i = 0; i < envc; i ++)
+ if (strncmp(envp[i], "DEVICE_URI=", 11))
+ LogMessage(L_DEBUG, "StartJob: envp[%d]=\"%s\"", i, envp[i]);
+ else
+ LogMessage(L_DEBUG, "StartJob: envp[%d]=\"DEVICE_URI=%s\"", i, sani_uri);
+
+ current->current_file ++;
+
+ /*
+ * Make sure we have a buffer to read status info into...
+ */
+
+ if (current->buffer == NULL)
+ {
+ LogMessage(L_DEBUG2, "StartJob: Allocating status buffer...");
+
+ if ((current->buffer = malloc(JOB_BUFFER_SIZE)) == NULL)
+ {
+ LogMessage(L_EMERG, "Unable to allocate memory for job status buffer - %s",
+ strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to allocate memory for job status buffer - %s.",
+ strerror(errno));
+
+ if (filters != NULL)
+ free(filters);
+
+ AddPrinterHistory(printer);
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ current->bufused = 0;
+ }
+
+ /*
+ * Now create processes for all of the filters...
+ */
+
+ if (cupsdOpenPipe(statusfds))
+ {
+ LogMessage(L_ERROR, "Unable to create job status pipes - %s.",
+ strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to create status pipes - %s.", strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ LogMessage(L_DEBUG, "StartJob: statusfds = [ %d %d ]",
+ statusfds[0], statusfds[1]);
+
+ current->pipe = statusfds[0];
+ current->status = 0;
+ memset(current->procs, 0, sizeof(current->procs));
+
+ filterfds[1][0] = open("/dev/null", O_RDONLY);
+ filterfds[1][1] = -1;
+
+ if (filterfds[1][0] < 0)
+ {
+ LogMessage(L_ERROR, "Unable to open \"/dev/null\" - %s.", strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to open \"/dev/null\" - %s.", strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ cupsdClosePipe(statusfds);
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ fcntl(filterfds[1][0], F_SETFD, fcntl(filterfds[1][0], F_GETFD) | FD_CLOEXEC);
+
+ LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]", 1, filterfds[1][0],
+ filterfds[1][1]);
+
+ for (i = 0, slot = 0; i < num_filters; i ++)
+ {
+ if (filters[i].filter[0] != '/')
+ snprintf(command, sizeof(command), "%s/filter/%s", ServerBin,
+ filters[i].filter);
+ else
+ strlcpy(command, filters[i].filter, sizeof(command));
+
+#ifdef __APPLE__
+ /*
+ * Setting CFProcessPath lets OS X's Core Foundation code find
+ * the bundle that may be associated with a filter or backend.
+ */
+
+ snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
+ LogMessage(L_DEBUG, "StartJob: %s\n", processPath);
+#endif /* __APPLE__ */
+
+ if (i < (num_filters - 1) ||
+ strncmp(printer->device_uri, "file:", 5) != 0)
+ {
+ if (cupsdOpenPipe(filterfds[slot]))
+ {
+ LogMessage(L_ERROR, "Unable to create job filter pipes - %s.",
+ strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to create filter pipes - %s.", strerror(errno));
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ cupsdClosePipe(statusfds);
+ cupsdClosePipe(filterfds[!slot]);
+ CancelJob(current->id, 0);
+ return;
+ }
+ }
+ else
+ {
+ filterfds[slot][0] = -1;
+ if (strncmp(printer->device_uri, "file:/dev/", 10) == 0)
+ filterfds[slot][1] = open(printer->device_uri + 5,
+ O_WRONLY | O_EXCL);
+ else
+ filterfds[slot][1] = open(printer->device_uri + 5,
+ O_WRONLY | O_CREAT | O_TRUNC, 0600);
+
+ if (filterfds[slot][1] < 0)
+ {
+ LogMessage(L_ERROR, "Unable to open output file \"%s\" - %s.",
+ printer->device_uri, strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to open output file \"%s\" - %s.",
+ printer->device_uri, strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ cupsdClosePipe(statusfds);
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ fcntl(filterfds[slot][1], F_SETFD,
+ fcntl(filterfds[slot][1], F_GETFD) | FD_CLOEXEC);
+ }
+
+ LogMessage(L_DEBUG, "StartJob: filter = \"%s\"", command);
+ LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]",
+ slot, filterfds[slot][0], filterfds[slot][1]);
+
+ pid = start_process(command, argv, envp, filterfds[!slot][0],
+ filterfds[slot][1], statusfds[1], 0,
+ current->procs + i);
+
+ cupsdClosePipe(filterfds[!slot]);
+
+ if (pid == 0)
+ {
+ LogMessage(L_ERROR, "Unable to start filter \"%s\" - %s.",
+ filters[i].filter, strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to start filter \"%s\" - %s.",
+ filters[i].filter, strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ cupsdClosePipe(statusfds);
+ cupsdClosePipe(filterfds[slot]);
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ LogMessage(L_INFO, "Started filter %s (PID %d) for job %d.",
+ command, pid, current->id);
+
+ argv[6] = NULL;
+ slot = !slot;
+ }
+
+ if (filters != NULL)
+ free(filters);
+
+ /*
+ * Finally, pipe the final output into a backend process if needed...
+ */
+
+ if (strncmp(printer->device_uri, "file:", 5) != 0)
+ {
+ sscanf(printer->device_uri, "%254[^:]", method);
+ snprintf(command, sizeof(command), "%s/backend/%s", ServerBin, method);
+
+#ifdef __APPLE__
+ /*
+ * Setting CFProcessPath lets OS X's Core Foundation code find
+ * the bundle that may be associated with a filter or backend.
+ */
+
+ snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
+ LogMessage(L_DEBUG, "StartJob: %s\n", processPath);
+#endif /* __APPLE__ */
+
+ argv[0] = sani_uri;
+
+ filterfds[slot][0] = -1;
+ filterfds[slot][1] = open("/dev/null", O_WRONLY);
+
+ if (filterfds[slot][1] < 0)
+ {
+ LogMessage(L_ERROR, "Unable to open \"/dev/null\" - %s.", strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to open \"/dev/null\" - %s.", strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ CancelJob(current->id, 0);
+ return;
+ }
+
+ fcntl(filterfds[slot][1], F_SETFD,
+ fcntl(filterfds[slot][1], F_GETFD) | FD_CLOEXEC);
+
+ LogMessage(L_DEBUG, "StartJob: backend = \"%s\"", command);
+ LogMessage(L_DEBUG, "StartJob: filterfds[%d] = [ %d %d ]",
+ slot, filterfds[slot][0], filterfds[slot][1]);
+
+ pid = start_process(command, argv, envp, filterfds[!slot][0],
+ filterfds[slot][1], statusfds[1], 1,
+ current->procs + i);
+
+ cupsdClosePipe(filterfds[!slot]);
+
+ if (pid == 0)
+ {
+ LogMessage(L_ERROR, "Unable to start backend \"%s\" - %s.",
+ method, strerror(errno));
+ snprintf(printer->state_message, sizeof(printer->state_message),
+ "Unable to start backend \"%s\" - %s.", method, strerror(errno));
+
+ AddPrinterHistory(printer);
+
+ if (filters != NULL)
+ free(filters);
+
+ cupsdClosePipe(statusfds);
+ cupsdClosePipe(filterfds[slot]);
+ CancelJob(current->id, 0);
+ return;
+ }
+ else
+ {
+ LogMessage(L_INFO, "Started backend %s (PID %d) for job %d.", command, pid,
+ current->id);
+ }
+ }
+ else
+ {
+ filterfds[slot][0] = -1;
+ filterfds[slot][1] = -1;
+
+ cupsdClosePipe(filterfds[!slot]);
+ }
+
+ cupsdClosePipe(filterfds[slot]);
+
+ close(statusfds[1]);
+
+ LogMessage(L_DEBUG2, "StartJob: Adding fd %d to InputSet...", current->pipe);
+
+ FD_SET(current->pipe, InputSet);
+}
+
+
+/*
+ * 'StopAllJobs()' - Stop all print jobs.
+ */
+
+void
+StopAllJobs(void)
+{
+ job_t *current; /* Current job */
+
+
+ DEBUG_puts("StopAllJobs()");
+
+ for (current = Jobs; current != NULL; current = current->next)
+ if (current->state->values[0].integer == IPP_JOB_PROCESSING)
+ {
+ StopJob(current->id, 1);
+ current->state->values[0].integer = IPP_JOB_PENDING;
+ }
+}
+
+
+/*
+ * 'StopJob()' - Stop a print job.
+ */
+
+void
+StopJob(int id, /* I - Job ID */
+ int force) /* I - 1 = Force all filters to stop */
+{
+ int i; /* Looping var */
+ job_t *current; /* Current job */
+
+
+ LogMessage(L_DEBUG, "StopJob: id = %d, force = %d", id, force);
+
+ for (current = Jobs; current != NULL; current = current->next)
+ if (current->id == id)
+ {
+ DEBUG_puts("StopJob: found job in list.");
+
+ if (current->state->values[0].integer == IPP_JOB_PROCESSING)
+ {
+ DEBUG_puts("StopJob: job state is \'processing\'.");
+
+ FilterLevel -= current->cost;
+
+ if (current->status < 0 &&
+ !(current->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) &&
+ !(current->printer->type & CUPS_PRINTER_FAX))
+ SetPrinterState(current->printer, IPP_PRINTER_STOPPED, 1);
+ else if (current->printer->state != IPP_PRINTER_STOPPED)
+ SetPrinterState(current->printer, IPP_PRINTER_IDLE, 0);
+
+ LogMessage(L_DEBUG, "StopJob: printer state is %d", current->printer->state);
+
+ current->state->values[0].integer = IPP_JOB_STOPPED;
+ current->printer->job = NULL;
+ current->printer = NULL;
+
+ current->current_file --;
+
+ for (i = 0; current->procs[i]; i ++)
+ if (current->procs[i] > 0)
+ {
+ kill(current->procs[i], force ? SIGKILL : SIGTERM);
+ current->procs[i] = 0;
+ }
+
+ if (current->pipe >= 0)
+ {
+ /*
+ * Close the pipe and clear the input bit.
+ */
+
+ LogMessage(L_DEBUG2, "StopJob: Removing fd %d from InputSet...",
+ current->pipe);
+
+ close(current->pipe);
+ FD_CLR(current->pipe, InputSet);
+ current->pipe = -1;
+ }
+
+ if (current->buffer)
+ {
+ /*
+ * Free the status buffer...
+ */
+
+ LogMessage(L_DEBUG2, "StopJob: Freeing status buffer...");
+
+ free(current->buffer);
+ current->buffer = NULL;
+ current->bufused = 0;
+ }
+ }
+ return;
+ }
+}
+
+
+/*
+ * 'UpdateJob()' - Read a status update from a job's filters.
+ */
+
+void
+UpdateJob(job_t *job) /* I - Job to check */
+{
+ int i; /* Looping var */
+ int bytes; /* Number of bytes read */
+ int copies; /* Number of copies printed */
+ char *lineptr, /* Pointer to end of line in buffer */
+ *message; /* Pointer to message text */
+ int loglevel; /* Log level for message */
+ int job_history; /* Did CancelJob() keep the job? */
+ cups_ptype_t ptype; /* Printer type (color, small, etc.) */
+
+
+ if ((bytes = read(job->pipe, job->buffer + job->bufused,
+ JOB_BUFFER_SIZE - job->bufused - 1)) > 0)
+ {
+ job->bufused += bytes;
+ job->buffer[job->bufused] = '\0';
+
+ if ((lineptr = strchr(job->buffer, '\n')) == NULL &&
+ job->bufused == (JOB_BUFFER_SIZE - 1))
+ lineptr = job->buffer + job->bufused;
+ }
+ else if (bytes < 0 && errno == EINTR)
+ return;
+ else
+ {
+ lineptr = job->buffer + job->bufused;
+ *lineptr = '\0';
+ }
+
+ if (job->bufused == 0 && bytes == 0)
+ lineptr = NULL;
+
+ while (lineptr != NULL)
+ {
+ /*
+ * Terminate each line and process it...
+ */
+
+ *lineptr++ = '\0';
+
+ /*
+ * Figure out the logging level...
+ */
+
+ if (strncmp(job->buffer, "EMERG:", 6) == 0)
+ {
+ loglevel = L_EMERG;
+ message = job->buffer + 6;
+ }
+ else if (strncmp(job->buffer, "ALERT:", 6) == 0)
+ {
+ loglevel = L_ALERT;
+ message = job->buffer + 6;
+ }
+ else if (strncmp(job->buffer, "CRIT:", 5) == 0)
+ {
+ loglevel = L_CRIT;
+ message = job->buffer + 5;
+ }
+ else if (strncmp(job->buffer, "ERROR:", 6) == 0)
+ {
+ loglevel = L_ERROR;
+ message = job->buffer + 6;
+ }
+ else if (strncmp(job->buffer, "WARNING:", 8) == 0)
+ {
+ loglevel = L_WARN;
+ message = job->buffer + 8;
+ }
+ else if (strncmp(job->buffer, "NOTICE:", 6) == 0)
+ {
+ loglevel = L_NOTICE;
+ message = job->buffer + 6;
+ }
+ else if (strncmp(job->buffer, "INFO:", 5) == 0)
+ {
+ loglevel = L_INFO;
+ message = job->buffer + 5;
+ }
+ else if (strncmp(job->buffer, "DEBUG:", 6) == 0)
+ {
+ loglevel = L_DEBUG;
+ message = job->buffer + 6;
+ }
+ else if (strncmp(job->buffer, "DEBUG2:", 7) == 0)
+ {
+ loglevel = L_DEBUG2;
+ message = job->buffer + 7;
+ }
+ else if (strncmp(job->buffer, "PAGE:", 5) == 0)
+ {
+ loglevel = L_PAGE;
+ message = job->buffer + 5;
+ }
+ else if (strncmp(job->buffer, "STATE:", 6) == 0)
+ {
+ loglevel = L_STATE;
+ message = job->buffer + 6;
+ }
+ else
+ {
+ loglevel = L_DEBUG;
+ message = job->buffer;
+ }
+
+ /*
+ * Skip leading whitespace in the message...
+ */
+
+ while (isspace(*message & 255))
+ message ++;
+
+ /*
+ * Send it to the log file and printer state message as needed...
+ */
+
+ if (loglevel == L_PAGE)
+ {
+ /*
+ * Page message; send the message to the page_log file and update the
+ * job sheet count...
+ */
+
+ if (job->sheets != NULL)
+ {
+ if (!strncasecmp(message, "total ", 6))
+ {
+ /*
+ * Got a total count of pages from a backend or filter...
+ */
+
+ copies = atoi(message + 6);
+ copies -= job->sheets->values[0].integer; /* Just track the delta */
+ }
+ else if (!sscanf(message, "%*d%d", &copies))
+ copies = 1;
+
+ job->sheets->values[0].integer += copies;
+
+ if (job->printer->page_limit)
+ UpdateQuota(job->printer, job->username, copies, 0);
+ }
+
+ LogPage(job, message);
+ }
+ else if (loglevel == L_STATE)
+ SetPrinterReasons(job->printer, message);
+ else
+ {
+ /*
+ * Other status message; send it to the error_log file...
+ */
+
+ if (loglevel != L_INFO || LogLevel == L_DEBUG2)
+ LogMessage(loglevel, "[Job %d] %s", job->id, message);
+
+ if ((loglevel == L_INFO && !job->status) ||
+ loglevel < L_INFO)
+ {
+ strlcpy(job->printer->state_message, message,
+ sizeof(job->printer->state_message));
+
+ AddPrinterHistory(job->printer);
+ }
+ }
+
+ /*
+ * Copy over the buffer data we've used up...
+ */
+
+ cups_strcpy(job->buffer, lineptr);
+ job->bufused -= lineptr - job->buffer;
+
+ if (job->bufused < 0)
+ job->bufused = 0;
+
+ lineptr = strchr(job->buffer, '\n');
+ }
+
+ if (bytes <= 0)
+ {
+ /*
+ * See if all of the filters and the backend have returned their
+ * exit statuses.
+ */
+
+ for (i = 0; job->procs[i]; i ++)
+ if (job->procs[i] > 0)
+ return;
+
+ /*
+ * Handle the end of job stuff...
+ */
+
+ LogMessage(L_DEBUG, "UpdateJob: job %d, file %d is complete.",
+ job->id, job->current_file - 1);
+
+ if (job->pipe >= 0)
+ {
+ /*
+ * Close the pipe and clear the input bit.
+ */
+
+ LogMessage(L_DEBUG2, "UpdateJob: Removing fd %d from InputSet...",
+ job->pipe);
+
+ close(job->pipe);
+ FD_CLR(job->pipe, InputSet);
+ job->pipe = -1;
+ }
+
+ if (job->status < 0)
+ {
+ /*
+ * Backend had errors; stop it...
+ */
+
+ ptype = job->printer->type;
+
+ StopJob(job->id, 0);
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ SaveJob(job->id);
+
+ /*
+ * If the job was queued to a class, try requeuing it... For
+ * faxes, hold the current job for 5 minutes.
+ */
+
+ if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ CheckJobs();
+ else if (ptype & CUPS_PRINTER_FAX)
+ {
+ /*
+ * See how many times we've tried to send the job; if more than
+ * the limit, cancel the job.
+ */
+
+ job->tries ++;
+
+ if (job->tries >= FaxRetryLimit)
+ {
+ /*
+ * Too many tries...
+ */
+
+ LogMessage(L_ERROR, "Canceling fax job %d since it could not be sent after %d tries.",
+ job->id, FaxRetryLimit);
+ CancelJob(job->id, 0);
+ }
+ else
+ {
+ /*
+ * Try again in N seconds...
+ */
+
+ set_hold_until(job, time(NULL) + FaxRetryInterval);
+ }
+
+ CheckJobs();
+ }
+ }
+ else if (job->status > 0)
+ {
+ /*
+ * Filter had errors; cancel it...
+ */
+
+ if (job->current_file < job->num_files)
+ StartJob(job->id, job->printer);
+ else
+ {
+ job_history = JobHistory && !(job->dtype & CUPS_PRINTER_REMOTE);
+
+ CancelJob(job->id, 0);
+
+ if (job_history)
+ {
+ job->state->values[0].integer = IPP_JOB_ABORTED;
+ SaveJob(job->id);
+ }
+
+ CheckJobs();
+ }
+ }
+ else
+ {
+ /*
+ * Job printed successfully; cancel it...
+ */
+
+ if (job->current_file < job->num_files)
+ {
+ FilterLevel -= job->cost;
+ StartJob(job->id, job->printer);
+ }
+ else
+ {
+ job_history = JobHistory && !(job->dtype & CUPS_PRINTER_REMOTE);
+
+ CancelJob(job->id, 0);
+
+ if (job_history)
+ {
+ job->state->values[0].integer = IPP_JOB_COMPLETED;
+ SaveJob(job->id);
+ }
+
+ CheckJobs();
+ }
+ }
+ }
+}
+
+
+/*
+ * 'ipp_length()' - Compute the size of the buffer needed to hold
+ * the textual IPP attributes.
+ */
+
+int /* O - Size of buffer to hold IPP attributes */
+ipp_length(ipp_t *ipp) /* I - IPP request */
+{
+ int bytes; /* Number of bytes */
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* Current attribute */
+
+
+ /*
+ * Loop through all attributes...
+ */
+
+ bytes = 0;
+
+ for (attr = ipp->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip attributes that won't be sent to filters...
+ */
+
+ if (attr->value_tag == IPP_TAG_MIMETYPE ||
+ attr->value_tag == IPP_TAG_NAMELANG ||
+ attr->value_tag == IPP_TAG_TEXTLANG ||
+ attr->value_tag == IPP_TAG_URI ||
+ attr->value_tag == IPP_TAG_URISCHEME)
+ continue;
+
+ if (strncmp(attr->name, "time-", 5) == 0)
+ continue;
+
+ /*
+ * Add space for a leading space and commas between each value.
+ * For the first attribute, the leading space isn't used, so the
+ * extra byte can be used as the nul terminator...
+ */
+
+ bytes ++; /* " " separator */
+ bytes += attr->num_values; /* "," separators */
+
+ /*
+ * Boolean attributes appear as "foo,nofoo,foo,nofoo", while
+ * other attributes appear as "foo=value1,value2,...,valueN".
+ */
+
+ if (attr->value_tag != IPP_TAG_BOOLEAN)
+ bytes += strlen(attr->name);
+ else
+ bytes += attr->num_values * strlen(attr->name);
+
+ /*
+ * Now add the size required for each value in the attribute...
+ */
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ /*
+ * Minimum value of a signed integer is -2147483647, or 11 digits.
+ */
+
+ bytes += attr->num_values * 11;
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ /*
+ * Add two bytes for each false ("no") value...
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ if (!attr->values[i].boolean)
+ bytes += 2;
+ break;
+
+ case IPP_TAG_RANGE :
+ /*
+ * A range is two signed integers separated by a hyphen, or
+ * 23 characters max.
+ */
+
+ bytes += attr->num_values * 23;
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ /*
+ * A resolution is two signed integers separated by an "x" and
+ * suffixed by the units, or 26 characters max.
+ */
+
+ bytes += attr->num_values * 26;
+ break;
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_LANGUAGE :
+ /*
+ * Strings can contain characters that need quoting. We need
+ * at least 2 * len + 2 characters to cover the quotes and
+ * any backslashes in the string.
+ */
+
+ for (i = 0; i < attr->num_values; i ++)
+ bytes += 2 * strlen(attr->values[i].string.text) + 2;
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+ }
+
+ return (bytes);
+}
+
+
+/*
+ * 'set_time()' - Set one of the "time-at-xyz" attributes...
+ */
+
+static void
+set_time(job_t *job, /* I - Job to update */
+ const char *name) /* I - Name of attribute */
+{
+ ipp_attribute_t *attr; /* Time attribute */
+
+
+ if ((attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO)) != NULL)
+ {
+ attr->value_tag = IPP_TAG_INTEGER;
+ attr->values[0].integer = time(NULL);
+ }
+}
+
+
+/*
+ * 'start_process()' - Start a background process.
+ */
+
+static int /* O - Process ID or 0 */
+start_process(const char *command, /* I - Full path to command */
+ char *argv[], /* I - Command-line arguments */
+ char *envp[], /* I - Environment */
+ int infd, /* I - Standard input file descriptor */
+ int outfd, /* I - Standard output file descriptor */
+ int errfd, /* I - Standard error file descriptor */
+ int root, /* I - Run as root? */
+ int *pid) /* O - Process ID */
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* POSIX signal handler */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ LogMessage(L_DEBUG, "start_process(\"%s\", %p, %p, %d, %d, %d)",
+ command, argv, envp, infd, outfd, errfd);
+
+ /*
+ * Block signals before forking...
+ */
+
+ HoldSignals();
+
+ if ((*pid = fork()) == 0)
+ {
+ /*
+ * Child process goes here...
+ *
+ * Update stdin/stdout/stderr as needed...
+ */
+
+ close(0);
+ dup(infd);
+ close(1);
+ dup(outfd);
+ if (errfd > 2)
+ {
+ close(2);
+ dup(errfd);
+ }
+
+ /*
+ * Change the priority of the process based on the FilterNice setting.
+ * (this is not done for backends...)
+ */
+
+ if (!root)
+ nice(FilterNice);
+
+ /*
+ * Change user to something "safe"...
+ */
+
+ if (!root && !RunUser)
+ {
+ /*
+ * Running as root, so change to non-priviledged user...
+ */
+
+ if (setgid(Group))
+ exit(errno);
+
+ if (setgroups(1, &Group))
+ exit(errno);
+
+ if (setuid(User))
+ exit(errno);
+ }
+ else
+ {
+ /*
+ * Reset group membership to just the main one we belong to.
+ */
+
+ setgroups(1, &Group);
+ }
+
+ /*
+ * Change umask to restrict permissions on created files...
+ */
+
+ umask(077);
+
+ /*
+ * Unblock signals before doing the exec...
+ */
+
+#ifdef HAVE_SIGSET
+ sigset(SIGTERM, SIG_DFL);
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_DFL;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+#endif /* HAVE_SIGSET */
+
+ ReleaseSignals();
+
+ /*
+ * Execute the command; if for some reason this doesn't work,
+ * return the error code...
+ */
+
+ execve(command, argv, envp);
+
+ perror(command);
+
+ exit(errno);
+ }
+ else if (*pid < 0)
+ {
+ /*
+ * Error - couldn't fork a new process!
+ */
+
+ LogMessage(L_ERROR, "Unable to fork %s - %s.", command, strerror(errno));
+
+ *pid = 0;
+ }
+
+ ReleaseSignals();
+
+ return (*pid);
+}
+
+
+/*
+ * 'set_hold_until()' - Set the hold time and update job-hold-until attribute...
+ */
+
+static void
+set_hold_until(job_t *job, /* I - Job to update */
+ time_t holdtime) /* I - Hold until time */
+{
+ ipp_attribute_t *attr; /* job-hold-until attribute */
+ struct tm *holddate; /* Hold date */
+ char holdstr[64]; /* Hold time */
+
+
+ /*
+ * Set the hold_until value and hold the job...
+ */
+
+ LogMessage(L_DEBUG, "set_hold_until: hold_until = %d", (int)holdtime);
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+ job->hold_until = holdtime;
+
+ /*
+ * Update the job-hold-until attribute with a string representing GMT
+ * time (HH:MM:SS)...
+ */
+
+ holddate = gmtime(&holdtime);
+ snprintf(holdstr, sizeof(holdstr), "%d:%d:%d", holddate->tm_hour,
+ holddate->tm_min, holddate->tm_sec);
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ /*
+ * Either add the attribute or update the value of the existing one
+ */
+
+ if (attr == NULL)
+ attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-hold-until", NULL, holdstr);
+ else
+ SetString(&attr->values[0].string.text, holdstr);
+
+ SaveJob(job->id);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/job.h b/scheduler/job.h
new file mode 100644
index 000000000..a238450fa
--- /dev/null
+++ b/scheduler/job.h
@@ -0,0 +1,111 @@
+/*
+ * "$Id$"
+ *
+ * Print job definitions for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Constants...
+ */
+
+#define JOB_BUFFER_SIZE 1024 /* Bytes for job status buffer */
+
+
+/*
+ * Job request structure...
+ */
+
+typedef struct job_str
+{
+ struct job_str *next; /* Next job in queue */
+ int id, /* Job ID */
+ priority; /* Job priority */
+ ipp_attribute_t *state; /* Job state */
+ ipp_attribute_t *sheets; /* job-media-sheets-completed */
+ time_t hold_until; /* Hold expiration date/time */
+ char *username; /* Printing user */
+ char *dest; /* Destination printer or class */
+ cups_ptype_t dtype; /* Destination type (class/remote bits) */
+ ipp_attribute_t *job_sheets; /* Job sheets (NULL if none) */
+ int num_files; /* Number of files in job */
+ int current_file; /* Current file in job */
+ mime_type_t **filetypes; /* File types */
+ int *compressions; /* Compression status of each file */
+ ipp_t *attrs; /* Job attributes */
+ int pipe; /* Status pipe for this job */
+ int cost; /* Filtering cost */
+ int procs[MAX_FILTERS + 2]; /* Process IDs, 0 terminated */
+ int status; /* Status code from filters */
+ printer_t *printer; /* Printer this job is assigned to */
+ char *buffer; /* Status buffer */
+ int bufused; /* Amount of buffer in use */
+ int tries; /* Number of tries for this job */
+} job_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int JobHistory VALUE(1); /* Preserve job history? */
+VAR int JobFiles VALUE(0); /* Preserve job files? */
+VAR int MaxJobs VALUE(0), /* Max number of jobs */
+ MaxJobsPerUser VALUE(0), /* Max jobs per user */
+ MaxJobsPerPrinter VALUE(0); /* Max jobs per printer */
+VAR int JobAutoPurge VALUE(0); /* Automatically purge jobs */
+VAR int NumJobs VALUE(0); /* Number of jobs in queue */
+VAR job_t *Jobs VALUE(NULL); /* List of current jobs */
+VAR int NextJobId VALUE(1); /* Next job ID to use */
+VAR int FaxRetryLimit VALUE(5), /* Max number of tries */
+ FaxRetryInterval VALUE(300); /* Seconds between retries */
+
+
+/*
+ * Prototypes...
+ */
+
+extern job_t *AddJob(int priority, const char *dest);
+extern void CancelJob(int id, int purge);
+extern void CancelJobs(const char *dest, const char *username, int purge);
+extern void CheckJobs(void);
+extern void CleanJobs(void);
+extern void DeleteJob(int id);
+extern job_t *FindJob(int id);
+extern void FreeAllJobs(void);
+extern int GetPrinterJobCount(const char *dest);
+extern int GetUserJobCount(const char *username);
+extern void HoldJob(int id);
+extern void LoadAllJobs(void);
+extern void MoveJob(int id, const char *dest);
+extern void ReleaseJob(int id);
+extern void RestartJob(int id);
+extern void SaveJob(int id);
+extern void SetJobHoldUntil(int id, const char *when);
+extern void SetJobPriority(int id, int priority);
+extern void StartJob(int id, printer_t *printer);
+extern void StopAllJobs(void);
+extern void StopJob(int id, int force);
+extern void UpdateJob(job_t *job);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/listen.c b/scheduler/listen.c
new file mode 100644
index 000000000..a4dce1f3d
--- /dev/null
+++ b/scheduler/listen.c
@@ -0,0 +1,258 @@
+/*
+ * "$Id$"
+ *
+ * Server listening routines for the Common UNIX Printing System (CUPS)
+ * scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * PauseListening() - Clear input polling on all listening sockets...
+ * ResumeListening() - Set input polling on all listening sockets...
+ * StartListening() - Create all listening sockets...
+ * StopListening() - Close all listening sockets...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * 'PauseListening()' - Clear input polling on all listening sockets...
+ */
+
+void
+PauseListening(void)
+{
+ int i; /* Looping var */
+ listener_t *lis; /* Current listening socket */
+
+
+ if (NumListeners < 1 || !FD_ISSET(Listeners[0].fd, InputSet))
+ return;
+
+ if (NumClients == MaxClients)
+ LogMessage(L_WARN, "Max clients reached, holding new connections...");
+
+ LogMessage(L_DEBUG, "PauseListening: clearing input bits...");
+
+ for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
+ {
+ LogMessage(L_DEBUG2, "PauseListening: Removing fd %d from InputSet...",
+ lis->fd);
+
+ FD_CLR(lis->fd, InputSet);
+ }
+}
+
+
+/*
+ * 'ResumeListening()' - Set input polling on all listening sockets...
+ */
+
+void
+ResumeListening(void)
+{
+ int i; /* Looping var */
+ listener_t *lis; /* Current listening socket */
+
+
+ if (NumListeners < 1 || FD_ISSET(Listeners[0].fd, InputSet))
+ return;
+
+ if (NumClients >= (MaxClients - 1))
+ LogMessage(L_WARN, "Resuming new connection processing...");
+
+ LogMessage(L_DEBUG, "ResumeListening: setting input bits...");
+
+ for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
+ {
+ LogMessage(L_DEBUG2, "ResumeListening: Adding fd %d to InputSet...",
+ lis->fd);
+
+ FD_SET(lis->fd, InputSet);
+ }
+}
+
+
+/*
+ * 'StartListening()' - Create all listening sockets...
+ */
+
+void
+StartListening(void)
+{
+ int i, /* Looping var */
+ val; /* Parameter value */
+ listener_t *lis; /* Current listening socket */
+ struct hostent *host; /* Host entry for server address */
+
+
+ LogMessage(L_DEBUG, "StartListening: NumListeners=%d", NumListeners);
+
+ /*
+ * Get the server's IP address...
+ */
+
+ memset(&ServerAddr, 0, sizeof(ServerAddr));
+
+ if ((host = httpGetHostByName(ServerName)) != NULL)
+ {
+ /*
+ * Found the server's address!
+ */
+
+ memcpy((char *)&(ServerAddr.sin_addr), host->h_addr, host->h_length);
+ ServerAddr.sin_family = host->h_addrtype;
+ }
+ else
+ {
+ /*
+ * Didn't find it! Use an address of 0...
+ */
+
+ LogMessage(L_ERROR, "StartListening: Unable to find IP address for server name \"%s\" - %s\n",
+ ServerName, hstrerror(h_errno));
+
+ ServerAddr.sin_family = AF_INET;
+ }
+
+ /*
+ * Setup socket listeners...
+ */
+
+ for (i = NumListeners, lis = Listeners, LocalPort = 0; i > 0; i --, lis ++)
+ {
+ LogMessage(L_DEBUG, "StartListening: address=%08x port=%d",
+ (unsigned)ntohl(lis->address.sin_addr.s_addr),
+ ntohs(lis->address.sin_port));
+
+ /*
+ * Save the first port that is bound to the local loopback or
+ * "any" address...
+ */
+
+ if (!LocalPort &&
+ (ntohl(lis->address.sin_addr.s_addr) == 0x7f000001 ||
+ ntohl(lis->address.sin_addr.s_addr) == 0x00000000))
+ {
+ LocalPort = ntohs(lis->address.sin_port);
+ LocalEncryption = lis->encryption;
+ }
+
+ /*
+ * Create a socket for listening...
+ */
+
+ if ((lis->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ {
+ LogMessage(L_ERROR, "StartListening: Unable to open listen socket for address %08x:%d - %s.",
+ (unsigned)ntohl(lis->address.sin_addr.s_addr),
+ ntohs(lis->address.sin_port), strerror(errno));
+ exit(errno);
+ }
+
+ fcntl(lis->fd, F_SETFD, fcntl(lis->fd, F_GETFD) | FD_CLOEXEC);
+
+ /*
+ * Set things up to reuse the local address for this port.
+ */
+
+ val = 1;
+#ifdef __sun
+ setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+#else
+ setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+#endif /* __sun */
+
+ /*
+ * Bind to the port we found...
+ */
+
+ if (bind(lis->fd, (struct sockaddr *)&(lis->address), sizeof(lis->address)) < 0)
+ {
+ LogMessage(L_ERROR, "StartListening: Unable to bind socket for address %08x:%d - %s.",
+ (unsigned)ntohl(lis->address.sin_addr.s_addr),
+ ntohs(lis->address.sin_port), strerror(errno));
+ exit(errno);
+ }
+
+ /*
+ * Listen for new clients.
+ */
+
+ if (listen(lis->fd, ListenBackLog) < 0)
+ {
+ LogMessage(L_ERROR, "StartListening: Unable to listen for clients on address %08x:%d - %s.",
+ (unsigned)ntohl(lis->address.sin_addr.s_addr),
+ ntohs(lis->address.sin_port), strerror(errno));
+ exit(errno);
+ }
+ }
+
+ /*
+ * Make sure that we are listening on localhost!
+ */
+
+ if (!LocalPort)
+ {
+ LogMessage(L_EMERG, "No Listen or Port lines were found to allow access via localhost!");
+
+ /*
+ * Commit suicide...
+ */
+
+ kill(getpid(), SIGTERM);
+ }
+
+ ResumeListening();
+}
+
+
+/*
+ * 'StopListening()' - Close all listening sockets...
+ */
+
+void
+StopListening(void)
+{
+ int i; /* Looping var */
+ listener_t *lis; /* Current listening socket */
+
+
+ LogMessage(L_DEBUG, "StopListening: closing all listen sockets.");
+
+ PauseListening();
+
+ for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
+#ifdef WIN32
+ closesocket(lis->fd);
+#else
+ close(lis->fd);
+#endif /* WIN32 */
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/log.c b/scheduler/log.c
new file mode 100644
index 000000000..65a27df1c
--- /dev/null
+++ b/scheduler/log.c
@@ -0,0 +1,529 @@
+/*
+ * "$Id$"
+ *
+ * Log file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * GetDateTime() - Returns a pointer to a date/time string.
+ * LogMessage() - Log a message to the error log file.
+ * LogPage() - Log a page to the page log file.
+ * LogRequest() - Log an HTTP request in Common Log Format.
+ * check_log_file() - Open/rotate a log file if it needs it.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <stdarg.h>
+
+#ifdef HAVE_VSYSLOG
+# include <syslog.h>
+#endif /* HAVE_VSYSLOG */
+
+
+/*
+ * Local functions...
+ */
+
+static int check_log_file(cups_file_t **, const char *);
+
+
+/*
+ * 'GetDateTime()' - Returns a pointer to a date/time string.
+ */
+
+char * /* O - Date/time string */
+GetDateTime(time_t t) /* I - Time value */
+{
+ struct tm *date; /* Date/time value */
+ static time_t last_time = -1; /* Last time value */
+ static char s[1024]; /* Date/time string */
+ static const char * const months[12] =
+ { /* Months */
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ };
+
+
+ if (t != last_time)
+ {
+ last_time = t;
+
+ /*
+ * Get the date and time from the UNIX time value, and then format it
+ * into a string. Note that we *can't* use the strftime() function since
+ * it is localized and will seriously confuse automatic programs if the
+ * month names are in the wrong language!
+ *
+ * Also, we use the "timezone" variable that contains the current timezone
+ * offset from GMT in seconds so that we are reporting local time in the
+ * log files. If you want GMT, set the TZ environment variable accordingly
+ * before starting the scheduler.
+ *
+ * (*BSD and Darwin store the timezone offset in the tm structure)
+ */
+
+ date = localtime(&t);
+
+ snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
+ date->tm_mday, months[date->tm_mon], 1900 + date->tm_year,
+ date->tm_hour, date->tm_min, date->tm_sec,
+#ifdef HAVE_TM_GMTOFF
+ date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60);
+#else
+ timezone / 3600, (timezone / 60) % 60);
+#endif /* HAVE_TM_GMTOFF */
+ }
+
+ return (s);
+}
+
+
+/*
+ * 'LogMessage()' - Log a message to the error log file.
+ */
+
+int /* O - 1 on success, 0 on error */
+LogMessage(int level, /* I - Log level */
+ const char *message, /* I - printf-style message string */
+ ...) /* I - Additional args as needed */
+{
+ int len; /* Length of message */
+ va_list ap; /* Argument pointer */
+ static const char levels[] = /* Log levels... */
+ {
+ ' ',
+ 'X',
+ 'A',
+ 'C',
+ 'E',
+ 'W',
+ 'N',
+ 'I',
+ 'D',
+ 'd'
+ };
+#ifdef HAVE_VSYSLOG
+ static const int syslevels[] = /* SYSLOG levels... */
+ {
+ 0,
+ LOG_EMERG,
+ LOG_ALERT,
+ LOG_CRIT,
+ LOG_ERR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_INFO,
+ LOG_DEBUG,
+ LOG_DEBUG
+ };
+#endif /* HAVE_VSYSLOG */
+ static int linesize = 0; /* Size of line for output file */
+ static char *line = NULL; /* Line for output file */
+
+
+ /*
+ * See if we want to log this message...
+ */
+
+ if (level > LogLevel)
+ return (1);
+
+#ifdef HAVE_VSYSLOG
+ /*
+ * See if we are logging errors via syslog...
+ */
+
+ if (strcmp(ErrorLog, "syslog") == 0)
+ {
+ va_start(ap, message);
+ vsyslog(syslevels[level], message, ap);
+ va_end(ap);
+
+ return (1);
+ }
+#endif /* HAVE_VSYSLOG */
+
+ /*
+ * Not using syslog; check the log file...
+ */
+
+ if (!check_log_file(&ErrorFile, ErrorLog))
+ return (0);
+
+ /*
+ * Print the log level and date/time...
+ */
+
+ cupsFilePrintf(ErrorFile, "%c %s ", levels[level], GetDateTime(time(NULL)));
+
+ /*
+ * Allocate the line buffer as needed...
+ */
+
+ if (!linesize)
+ {
+ linesize = 8192;
+ line = malloc(linesize);
+
+ if (!line)
+ {
+ cupsFilePrintf(ErrorFile,
+ "ERROR: Unable to allocate memory for line - %s\n",
+ strerror(errno));
+ cupsFileFlush(ErrorFile);
+
+ return (0);
+ }
+ }
+
+ /*
+ * Format the log message...
+ */
+
+ va_start(ap, message);
+ len = vsnprintf(line, linesize, message, ap);
+ va_end(ap);
+
+ /*
+ * Resize the buffer as needed...
+ */
+
+ if (len >= linesize)
+ {
+ len ++;
+
+ if (len < 8192)
+ len = 8192;
+ else if (len > 65536)
+ len = 65536;
+
+ line = realloc(line, len);
+
+ if (line)
+ linesize = len;
+ else
+ {
+ cupsFilePrintf(ErrorFile,
+ "ERROR: Unable to allocate memory for line - %s\n",
+ strerror(errno));
+ cupsFileFlush(ErrorFile);
+
+ return (0);
+ }
+
+ va_start(ap, message);
+ len = vsnprintf(line, linesize, message, ap);
+ va_end(ap);
+ }
+
+ if (len >= linesize)
+ len = linesize - 1;
+
+ /*
+ * Then the log message...
+ */
+
+ cupsFilePuts(ErrorFile, line);
+
+ /*
+ * Then a newline...
+ */
+
+ if (len > 0 && line[len - 1] != '\n')
+ cupsFilePutChar(ErrorFile, '\n');
+
+ /*
+ * Flush the line to the file and return...
+ */
+
+ cupsFileFlush(ErrorFile);
+
+ return (1);
+}
+
+
+/*
+ * 'LogPage()' - Log a page to the page log file.
+ */
+
+int /* O - 1 on success, 0 on error */
+LogPage(job_t *job, /* I - Job being printed */
+ const char *page) /* I - Page being printed */
+{
+ ipp_attribute_t *billing, /* job-billing attribute */
+ *hostname; /* job-originating-host-name attribute */
+
+
+ billing = ippFindAttribute(job->attrs, "job-billing", IPP_TAG_ZERO);
+ hostname = ippFindAttribute(job->attrs, "job-originating-host-name",
+ IPP_TAG_ZERO);
+
+#ifdef HAVE_VSYSLOG
+ /*
+ * See if we are logging pages via syslog...
+ */
+
+ if (strcmp(PageLog, "syslog") == 0)
+ {
+ syslog(LOG_INFO, "PAGE %s %s %d %s %s %s", job->printer->name,
+ job->username ? job->username : "-",
+ job->id, page, billing ? billing->values[0].string.text : "-",
+ hostname->values[0].string.text);
+
+ return (1);
+ }
+#endif /* HAVE_VSYSLOG */
+
+ /*
+ * Not using syslog; check the log file...
+ */
+
+ if (!check_log_file(&PageFile, PageLog))
+ return (0);
+
+ /*
+ * Print a page log entry of the form:
+ *
+ * printer job-id user [DD/MON/YYYY:HH:MM:SS +TTTT] page num-copies \
+ * billing hostname
+ */
+
+ cupsFilePrintf(PageFile, "%s %s %d %s %s %s %s\n", job->printer->name,
+ job->username ? job->username : "-",
+ job->id, GetDateTime(time(NULL)), page,
+ billing ? billing->values[0].string.text : "-",
+ hostname->values[0].string.text);
+ cupsFileFlush(PageFile);
+
+ return (1);
+}
+
+
+/*
+ * 'LogRequest()' - Log an HTTP request in Common Log Format.
+ */
+
+int /* O - 1 on success, 0 on error */
+LogRequest(client_t *con, /* I - Request to log */
+ http_status_t code) /* I - Response code */
+{
+ static const char * const states[] =
+ { /* HTTP client states... */
+ "WAITING",
+ "OPTIONS",
+ "GET",
+ "GET",
+ "HEAD",
+ "POST",
+ "POST",
+ "POST",
+ "PUT",
+ "PUT",
+ "DELETE",
+ "TRACE",
+ "CLOSE",
+ "STATUS"
+ };
+
+
+#ifdef HAVE_VSYSLOG
+ /*
+ * See if we are logging accesses via syslog...
+ */
+
+ if (strcmp(AccessLog, "syslog") == 0)
+ {
+ syslog(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d %d\n",
+ con->http.hostname, con->username[0] != '\0' ? con->username : "-",
+ states[con->operation], con->uri,
+ con->http.version / 100, con->http.version % 100,
+ code, con->bytes);
+
+ return (1);
+ }
+#endif /* HAVE_VSYSLOG */
+
+ /*
+ * Not using syslog; check the log file...
+ */
+
+ if (!check_log_file(&AccessFile, AccessLog))
+ return (0);
+
+ /*
+ * Write a log of the request in "common log format"...
+ */
+
+ cupsFilePrintf(AccessFile, "%s - %s %s \"%s %s HTTP/%d.%d\" %d %d\n",
+ con->http.hostname, con->username[0] != '\0' ? con->username : "-",
+ GetDateTime(con->start), states[con->operation], con->uri,
+ con->http.version / 100, con->http.version % 100,
+ code, con->bytes);
+ cupsFileFlush(AccessFile);
+
+ return (1);
+}
+
+
+/*
+ * 'check_log_file()' - Open/rotate a log file if it needs it.
+ */
+
+static int /* O - 1 if log file open */
+check_log_file(cups_file_t **log, /* IO - Log file */
+ const char *logname) /* I - Log filename */
+{
+ char backname[1024], /* Backup log filename */
+ filename[1024], /* Formatted log filename */
+ *ptr; /* Pointer into filename */
+
+
+ /*
+ * See if we have a log file to check or we are handling a signal...
+ */
+
+ if (log == NULL || logname == NULL || !logname[0] || SignalCount)
+ return (1);
+
+ /*
+ * Format the filename as needed...
+ */
+
+ if (*log == NULL ||
+ (cupsFileTell(*log) > MaxLogSize && MaxLogSize > 0))
+ {
+ /*
+ * Handle format strings...
+ */
+
+ filename[sizeof(filename) - 1] = '\0';
+
+ if (logname[0] != '/')
+ {
+ strlcpy(filename, ServerRoot, sizeof(filename));
+ strlcat(filename, "/", sizeof(filename));
+ }
+ else
+ filename[0] = '\0';
+
+ for (ptr = filename + strlen(filename);
+ *logname && ptr < (filename + sizeof(filename) - 1);
+ logname ++)
+ if (*logname == '%')
+ {
+ /*
+ * Format spec...
+ */
+
+ logname ++;
+ if (*logname == 's')
+ {
+ /*
+ * Insert the server name...
+ */
+
+ strlcpy(ptr, ServerName, sizeof(filename) - (ptr - filename));
+ ptr += strlen(ptr);
+ }
+ else
+ {
+ /*
+ * Otherwise just insert the character...
+ */
+
+ *ptr++ = *logname;
+ }
+ }
+ else
+ *ptr++ = *logname;
+
+ *ptr = '\0';
+ }
+
+ /*
+ * See if the log file is open...
+ */
+
+ if (*log == NULL)
+ {
+ /*
+ * Nope, open the log file...
+ */
+
+ if ((*log = cupsFileOpen(filename, "a")) == NULL)
+ return (0);
+
+ if (strncmp(filename, "/dev/", 5))
+ {
+ fchown(cupsFileNumber(*log), RunUser, Group);
+ fchmod(cupsFileNumber(*log), LogFilePerm);
+ }
+ }
+
+ /*
+ * Do we need to rotate the log?
+ */
+
+ if (cupsFileTell(*log) > MaxLogSize && MaxLogSize > 0)
+ {
+ /*
+ * Rotate log file...
+ */
+
+ cupsFileClose(*log);
+
+ strcpy(backname, filename);
+ strlcat(backname, ".O", sizeof(backname));
+
+ unlink(backname);
+ rename(filename, backname);
+
+ if ((*log = cupsFileOpen(filename, "a")) == NULL)
+ return (0);
+
+ if (strncmp(filename, "/dev/", 5))
+ {
+ fchown(cupsFileNumber(*log), RunUser, Group);
+ fchmod(cupsFileNumber(*log), LogFilePerm);
+ }
+ }
+
+ return (1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/main.c b/scheduler/main.c
new file mode 100644
index 000000000..8c3f9b133
--- /dev/null
+++ b/scheduler/main.c
@@ -0,0 +1,1383 @@
+/*
+ * "$Id$"
+ *
+ * Scheduler main loop for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for the CUPS scheduler.
+ * cupsdClosePipe() - Close a pipe as necessary.
+ * cupsdOpenPipe() - Create a pipe which is closed on exec.
+ * CatchChildSignals() - Catch SIGCHLD signals...
+ * HoldSignals() - Hold child and termination signals.
+ * IgnoreChildSignals() - Ignore SIGCHLD signals...
+ * ReleaseSignals() - Release signals for delivery.
+ * SetString() - Set a string value.
+ * SetStringf() - Set a formatted string value.
+ * parent_handler() - Catch USR1/CHLD signals...
+ * process_children() - Process all dead children...
+ * sigchld_handler() - Handle 'child' signals from old processes.
+ * sighup_handler() - Handle 'hangup' signals to reconfigure the scheduler.
+ * sigterm_handler() - Handle 'terminate' signals that stop the scheduler.
+ * select_timeout() - Calculate the select timeout value.
+ * usage() - Show scheduler usage.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#define _MAIN_C_
+#include "cupsd.h"
+#include <sys/resource.h>
+#include <syslog.h>
+#include <grp.h>
+
+#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
+
+
+/*
+ * Local functions...
+ */
+
+static void parent_handler(int sig);
+static void process_children(void);
+static void sigchld_handler(int sig);
+static void sighup_handler(int sig);
+static void sigterm_handler(int sig);
+static long select_timeout(int fds);
+static void usage(void);
+
+
+/*
+ * Local globals...
+ */
+
+static int parent_signal = 0; /* Set to signal number from child */
+static int holdcount = 0; /* Number of times "hold" was called */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+static sigset_t holdmask; /* Old POSIX signal mask */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+static int dead_children = 0; /* Dead children? */
+static int stop_scheduler = 0; /* Should the scheduler stop? */
+
+
+/*
+ * 'main()' - Main entry for the CUPS scheduler.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ char *opt; /* Option character */
+ int fg; /* Run in the foreground */
+ int fds; /* Number of ready descriptors select returns */
+ fd_set *input, /* Input set for select() */
+ *output; /* Output set for select() */
+ client_t *con; /* Current client */
+ job_t *job, /* Current job */
+ *next; /* Next job */
+ listener_t *lis; /* Current listener */
+ time_t activity; /* Activity timer */
+ time_t browse_time; /* Next browse send time */
+ time_t senddoc_time; /* Send-Document time */
+#ifdef HAVE_MALLINFO
+ time_t mallinfo_time; /* Malloc information time */
+#endif /* HAVE_MALLINFO */
+ struct timeval timeout; /* select() timeout */
+ struct rlimit limit; /* Runtime limit */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#ifdef __sgi
+ cups_file_t *fp; /* Fake lpsched lock file */
+ struct stat statbuf; /* Needed for checking lpsched FIFO */
+#endif /* __sgi */
+
+
+ /*
+ * Check for command-line arguments...
+ */
+
+ fg = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ for (opt = argv[i] + 1; *opt != '\0'; opt ++)
+ switch (*opt)
+ {
+ case 'c' : /* Configuration file */
+ i ++;
+ if (i >= argc)
+ usage();
+
+ if (argv[i][0] == '/')
+ {
+ /*
+ * Absolute directory...
+ */
+
+ SetString(&ConfigurationFile, argv[i]);
+ }
+ else
+ {
+ /*
+ * Relative directory...
+ */
+
+ char current[1024]; /* Current directory */
+
+
+ getcwd(current, sizeof(current));
+ SetStringf(&ConfigurationFile, "%s/%s", current, argv[i]);
+ }
+ break;
+
+ case 'f' : /* Run in foreground... */
+ fg = 1;
+ break;
+
+ case 'F' : /* Run in foreground, but still disconnect from terminal... */
+ fg = -1;
+ break;
+
+ default : /* Unknown option */
+ fprintf(stderr, "cupsd: Unknown option \'%c\' - aborting!\n", *opt);
+ usage();
+ break;
+ }
+ else
+ {
+ fprintf(stderr, "cupsd: Unknown argument \'%s\' - aborting!\n", argv[i]);
+ usage();
+ }
+
+ if (!ConfigurationFile)
+ SetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
+
+ /*
+ * If the user hasn't specified "-f", run in the background...
+ */
+
+ if (!fg)
+ {
+ /*
+ * Setup signal handlers for the parent...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGUSR1, parent_handler);
+ sigset(SIGCHLD, parent_handler);
+
+ sigset(SIGHUP, SIG_IGN);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGUSR1);
+ action.sa_handler = parent_handler;
+ sigaction(SIGUSR1, &action, NULL);
+ sigaction(SIGCHLD, &action, NULL);
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGHUP, &action, NULL);
+#else
+ signal(SIGUSR1, parent_handler);
+ signal(SIGCLD, parent_handler);
+
+ signal(SIGHUP, SIG_IGN);
+#endif /* HAVE_SIGSET */
+
+ if (fork() > 0)
+ {
+ /*
+ * OK, wait for the child to startup and send us SIGUSR1 or to crash
+ * and the OS send us SIGCHLD... We also need to ignore SIGHUP which
+ * might be sent by the init script to restart the scheduler...
+ */
+
+ for (; parent_signal == 0;)
+ sleep(1);
+
+ if (parent_signal == SIGUSR1)
+ return (0);
+
+ if (wait(&i) < 0)
+ {
+ perror("cupsd");
+ return (1);
+ }
+ else if (WIFEXITED(i))
+ {
+ fprintf(stderr, "cupsd: Child exited with status %d!\n", WEXITSTATUS(i));
+ return (2);
+ }
+ else
+ {
+ fprintf(stderr, "cupsd: Child exited on signal %d!\n", WTERMSIG(i));
+ return (3);
+ }
+ }
+ }
+
+ if (fg < 1)
+ {
+ /*
+ * Make sure we aren't tying up any filesystems...
+ */
+
+ chdir("/");
+
+#ifndef DEBUG
+ /*
+ * Disable core dumps...
+ */
+
+ getrlimit(RLIMIT_CORE, &limit);
+ limit.rlim_cur = 0;
+ setrlimit(RLIMIT_CORE, &limit);
+
+ /*
+ * Disconnect from the controlling terminal...
+ */
+
+ close(0);
+ close(1);
+ close(2);
+
+ setsid();
+#endif /* DEBUG */
+ }
+
+ /*
+ * Set the timezone info...
+ */
+
+ if (getenv("TZ") != NULL)
+ SetStringf(&TZ, "TZ=%s", getenv("TZ"));
+ else
+ SetString(&TZ, "");
+
+ tzset();
+
+#ifdef LC_TIME
+ setlocale(LC_TIME, "");
+#endif /* LC_TIME */
+
+ /*
+ * Set the maximum number of files...
+ */
+
+ getrlimit(RLIMIT_NOFILE, &limit);
+
+ if (limit.rlim_max > CUPS_MAX_FDS)
+ MaxFDs = CUPS_MAX_FDS;
+ else
+ MaxFDs = limit.rlim_max;
+
+ limit.rlim_cur = MaxFDs;
+
+ setrlimit(RLIMIT_NOFILE, &limit);
+
+ /*
+ * Allocate memory for the input and output sets...
+ */
+
+ SetSize = (MaxFDs + 31) / 8 + 4;
+ if (SetSize < sizeof(fd_set))
+ SetSize = sizeof(fd_set);
+
+ InputSet = (fd_set *)calloc(1, SetSize);
+ OutputSet = (fd_set *)calloc(1, SetSize);
+ input = (fd_set *)calloc(1, SetSize);
+ output = (fd_set *)calloc(1, SetSize);
+
+ if (InputSet == NULL || OutputSet == NULL || input == NULL || output == NULL)
+ {
+ syslog(LOG_LPR, "Unable to allocate memory for select() sets - exiting!");
+ return (1);
+ }
+
+ /*
+ * Read configuration...
+ */
+
+ if (!ReadConfiguration())
+ {
+ syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
+ ConfigurationFile);
+ return (1);
+ }
+
+ /*
+ * Catch hangup and child signals and ignore broken pipes...
+ */
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ if (RunAsUser)
+ sigset(SIGHUP, sigterm_handler);
+ else
+ sigset(SIGHUP, sighup_handler);
+
+ sigset(SIGPIPE, SIG_IGN);
+ sigset(SIGTERM, sigterm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGHUP);
+
+ if (RunAsUser)
+ action.sa_handler = sigterm_handler;
+ else
+ action.sa_handler = sighup_handler;
+
+ sigaction(SIGHUP, &action, NULL);
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, NULL);
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGCHLD);
+ action.sa_handler = sigterm_handler;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ if (RunAsUser)
+ signal(SIGHUP, sigterm_handler);
+ else
+ signal(SIGHUP, sighup_handler);
+
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGTERM, sigterm_handler);
+#endif /* HAVE_SIGSET */
+
+#ifdef __sgi
+ /*
+ * Try to create a fake lpsched lock file if one is not already there.
+ * Some Adobe applications need it under IRIX in order to enable
+ * printing...
+ */
+
+ if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL)
+ {
+ syslog(LOG_LPR, "Unable to create fake lpsched lock file "
+ "\"/var/spool/lp/SCHEDLOCK\"\' - %s!",
+ strerror(errno));
+ }
+ else
+ {
+ fchmod(cupsFileNumber(fp), 0644);
+ fchown(cupsFileNumber(fp), User, Group);
+
+ cupsFileClose(fp);
+ }
+#endif /* __sgi */
+
+ /*
+ * Initialize authentication certificates...
+ */
+
+ InitCerts();
+
+ /*
+ * If we are running in the background, signal the parent process that
+ * we are up and running...
+ */
+
+ if (!fg)
+ kill(getppid(), SIGUSR1);
+
+ /*
+ * If the administrator has configured the server to run as an unpriviledged
+ * user, change to that user now...
+ */
+
+ if (RunAsUser)
+ {
+ setgid(Group);
+ setgroups(1, &Group);
+ setuid(User);
+ }
+
+ /*
+ * Start any pending print jobs...
+ */
+
+ CheckJobs();
+
+ /*
+ * Loop forever...
+ */
+
+#ifdef HAVE_MALLINFO
+ mallinfo_time = 0;
+#endif /* HAVE_MALLINFO */
+ browse_time = time(NULL);
+ senddoc_time = time(NULL);
+ fds = 1;
+
+ while (!stop_scheduler)
+ {
+#ifdef DEBUG
+ LogMessage(L_DEBUG2, "main: Top of loop, dead_children=%d, NeedReload=%d",
+ dead_children, NeedReload);
+#endif /* DEBUG */
+
+ /*
+ * Check if there are dead children to handle...
+ */
+
+ if (dead_children)
+ process_children();
+
+ /*
+ * Check if we need to load the server configuration file...
+ */
+
+ if (NeedReload)
+ {
+ job_t *job; /* Current job */
+
+
+ /*
+ * Close any idle clients...
+ */
+
+ if (NumClients > 0)
+ {
+ for (i = NumClients, con = Clients; i > 0; i --, con ++)
+ if (con->http.state == HTTP_WAITING)
+ {
+ CloseClient(con);
+ con --;
+ }
+ else
+ con->http.keep_alive = HTTP_KEEPALIVE_OFF;
+
+ PauseListening();
+ }
+
+ /*
+ * Check for any active jobs...
+ */
+
+ for (job = Jobs; job; job = job->next)
+ if (job->state->values[0].integer == IPP_JOB_PROCESSING)
+ break;
+
+ /*
+ * Restart if all clients are closed and all jobs finished, or
+ * if the reload timeout has elapsed...
+ */
+
+ if ((NumClients == 0 && (!job || NeedReload != RELOAD_ALL)) ||
+ (time(NULL) - ReloadTime) >= ReloadTimeout)
+ {
+ if (!ReadConfiguration())
+ {
+ syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!",
+ ConfigurationFile);
+ break;
+ }
+ }
+ }
+
+ /*
+ * Check for available input or ready output. If select() returns
+ * 0 or -1, something bad happened and we should exit immediately.
+ *
+ * Note that we at least have one listening socket open at all
+ * times.
+ */
+
+ memcpy(input, InputSet, SetSize);
+ memcpy(output, OutputSet, SetSize);
+
+ timeout.tv_sec = select_timeout(fds);
+ timeout.tv_usec = 0;
+
+ if ((fds = select(MaxFDs, input, output, NULL, &timeout)) < 0)
+ {
+ char s[16384], /* String buffer */
+ *sptr; /* Pointer into buffer */
+ int slen; /* Length of string buffer */
+
+
+ /*
+ * Got an error from select!
+ */
+
+ if (errno == EINTR) /* Just interrupted by a signal */
+ continue;
+
+ /*
+ * Log all sorts of debug info to help track down the problem.
+ */
+
+ LogMessage(L_EMERG, "select() failed - %s!", strerror(errno));
+
+ strcpy(s, "InputSet =");
+ slen = 10;
+ sptr = s + 10;
+
+ for (i = 0; i < MaxFDs; i ++)
+ if (FD_ISSET(i, InputSet))
+ {
+ snprintf(sptr, sizeof(s) - slen, " %d", i);
+ slen += strlen(sptr);
+ sptr += strlen(sptr);
+ }
+
+ LogMessage(L_EMERG, s);
+
+ strcpy(s, "OutputSet =");
+ slen = 11;
+ sptr = s + 11;
+
+ for (i = 0; i < MaxFDs; i ++)
+ if (FD_ISSET(i, OutputSet))
+ {
+ snprintf(sptr, sizeof(s) - slen, " %d", i);
+ slen += strlen(sptr);
+ sptr += strlen(sptr);
+ }
+
+ LogMessage(L_EMERG, s);
+
+ for (i = 0, con = Clients; i < NumClients; i ++, con ++)
+ LogMessage(L_EMERG, "Clients[%d] = %d, file = %d, state = %d",
+ i, con->http.fd, con->file, con->http.state);
+
+ for (i = 0, lis = Listeners; i < NumListeners; i ++, lis ++)
+ LogMessage(L_EMERG, "Listeners[%d] = %d", i, lis->fd);
+
+ LogMessage(L_EMERG, "BrowseSocket = %d", BrowseSocket);
+
+ for (job = Jobs; job != NULL; job = job->next)
+ LogMessage(L_EMERG, "Jobs[%d] = %d", job->id, job->pipe);
+
+ break;
+ }
+
+ for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
+ if (FD_ISSET(lis->fd, input))
+ AcceptClient(lis);
+
+ for (i = NumClients, con = Clients; i > 0; i --, con ++)
+ {
+ /*
+ * Process the input buffer...
+ */
+
+ if (FD_ISSET(con->http.fd, input) || con->http.used)
+ if (!ReadClient(con))
+ {
+ con --;
+ continue;
+ }
+
+ /*
+ * Write data as needed...
+ */
+
+ if (con->pipe_pid && FD_ISSET(con->file, input))
+ {
+ /*
+ * Keep track of pending input from the file/pipe separately
+ * so that we don't needlessly spin on select() when the web
+ * client is not ready to receive data...
+ */
+
+ con->file_ready = 1;
+
+#ifdef DEBUG
+ LogMessage(L_DEBUG2, "main: Data ready file %d!", con->file);
+#endif /* DEBUG */
+
+ if (!FD_ISSET(con->http.fd, output))
+ {
+ LogMessage(L_DEBUG2, "main: Removing fd %d from InputSet...", con->file);
+ FD_CLR(con->file, InputSet);
+ }
+ }
+
+ if (FD_ISSET(con->http.fd, output) &&
+ (!con->pipe_pid || con->file_ready))
+ if (!WriteClient(con))
+ {
+ con --;
+ continue;
+ }
+
+ /*
+ * Check the activity and close old clients...
+ */
+
+ activity = time(NULL) - Timeout;
+ if (con->http.activity < activity && !con->pipe_pid)
+ {
+ LogMessage(L_DEBUG, "Closing client %d after %d seconds of inactivity...",
+ con->http.fd, Timeout);
+
+ CloseClient(con);
+ con --;
+ continue;
+ }
+ }
+
+ /*
+ * Check for status info from job filters...
+ */
+
+ for (job = Jobs; job != NULL; job = next)
+ {
+ next = job->next;
+
+ if (job->pipe >= 0 && FD_ISSET(job->pipe, input))
+ {
+ /*
+ * Clear the input bit to avoid updating the next job
+ * using the same status pipe file descriptor...
+ */
+
+ FD_CLR(job->pipe, input);
+
+ /*
+ * Read any status messages from the filters...
+ */
+
+ UpdateJob(job);
+ }
+ }
+
+ /*
+ * Update CGI messages as needed...
+ */
+
+ if (CGIPipes[0] >= 0 && FD_ISSET(CGIPipes[0], input))
+ UpdateCGI();
+
+ /*
+ * Update the browse list as needed...
+ */
+
+ if (Browsing && BrowseProtocols)
+ {
+ if (BrowseSocket >= 0 && FD_ISSET(BrowseSocket, input))
+ UpdateCUPSBrowse();
+
+ if (PollPipe >= 0 && FD_ISSET(PollPipe, input))
+ UpdatePolling();
+
+#ifdef HAVE_LIBSLP
+ if ((BrowseProtocols & BROWSE_SLP) && BrowseSLPRefresh <= time(NULL))
+ UpdateSLPBrowse();
+#endif /* HAVE_LIBSLP */
+
+ if (time(NULL) > browse_time)
+ {
+ SendBrowseList();
+ browse_time = time(NULL);
+ }
+ }
+
+ /*
+ * Update any pending multi-file documents...
+ */
+
+ if ((time(NULL) - senddoc_time) >= 10)
+ {
+ CheckJobs();
+ senddoc_time = time(NULL);
+ }
+
+#ifdef HAVE_MALLINFO
+ /*
+ * Log memory usage every minute...
+ */
+
+ if ((time(NULL) - mallinfo_time) >= 60 && LogLevel >= L_DEBUG)
+ {
+ struct mallinfo mem; /* Malloc information */
+
+
+ mem = mallinfo();
+ LogMessage(L_DEBUG, "mallinfo: arena = %d, used = %d, free = %d\n",
+ mem.arena, mem.usmblks + mem.uordblks,
+ mem.fsmblks + mem.fordblks);
+ mallinfo_time = time(NULL);
+ }
+#endif /* HAVE_MALLINFO */
+
+ /*
+ * Update the root certificate once every 5 minutes...
+ */
+
+ if ((time(NULL) - RootCertTime) >= RootCertDuration && RootCertDuration)
+ {
+ /*
+ * Update the root certificate...
+ */
+
+ DeleteCert(0);
+ AddCert(0, "root");
+ }
+ }
+
+ /*
+ * Log a message based on what happened...
+ */
+
+ if (stop_scheduler)
+ LogMessage(L_INFO, "Scheduler shutting down normally.");
+ else
+ LogMessage(L_ERROR, "Scheduler shutting down due to program error.");
+
+ /*
+ * Close all network clients and stop all jobs...
+ */
+
+ StopServer();
+
+ StopAllJobs();
+
+#ifdef __sgi
+ /*
+ * Remove the fake IRIX lpsched lock file, but only if the existing
+ * file is not a FIFO which indicates that the real IRIX lpsched is
+ * running...
+ */
+
+ if (!stat("/var/spool/lp/FIFO", &statbuf))
+ if (!S_ISFIFO(statbuf.st_mode))
+ unlink("/var/spool/lp/SCHEDLOCK");
+#endif /* __sgi */
+
+ /*
+ * Free memory used by FD sets and return...
+ */
+
+ free(InputSet);
+ free(OutputSet);
+ free(input);
+ free(output);
+
+ return (!stop_scheduler);
+}
+
+
+/*
+ * 'cupsdClosePipe()' - Close a pipe as necessary.
+ */
+
+void
+cupsdClosePipe(int *fds) /* I - Pipe file descriptors (2) */
+{
+ /*
+ * Close file descriptors as needed...
+ */
+
+ if (fds[0] >= 0)
+ {
+ close(fds[0]);
+ fds[0] = -1;
+ }
+
+ if (fds[1] >= 0)
+ {
+ close(fds[1]);
+ fds[1] = -1;
+ }
+}
+
+
+/*
+ * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsdOpenPipe(int *fds) /* O - Pipe file descriptors (2) */
+{
+ /*
+ * Create the pipe...
+ */
+
+ if (pipe(fds))
+ return (-1);
+
+ /*
+ * Set the "close on exec" flag on each end of the pipe...
+ */
+
+ if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
+ {
+ close(fds[0]);
+ close(fds[1]);
+ return (-1);
+ }
+
+ if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
+ {
+ close(fds[0]);
+ close(fds[1]);
+ return (-1);
+ }
+
+ /*
+ * Return 0 indicating success...
+ */
+
+ return (0);
+}
+
+
+/*
+ * 'CatchChildSignals()' - Catch SIGCHLD signals...
+ */
+
+void
+CatchChildSignals(void)
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGCHLD, sigchld_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGCHLD);
+ action.sa_handler = sigchld_handler;
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */
+#endif /* HAVE_SIGSET */
+}
+
+
+/*
+ * 'ClearString()' - Clear a string.
+ */
+
+void
+ClearString(char **s) /* O - String value */
+{
+ if (s && *s)
+ {
+ free(*s);
+ *s = NULL;
+ }
+}
+
+
+/*
+ * 'HoldSignals()' - Hold child and termination signals.
+ */
+
+void
+HoldSignals(void)
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ sigset_t newmask; /* New POSIX signal mask */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ holdcount ++;
+ if (holdcount > 1)
+ return;
+
+#ifdef HAVE_SIGSET
+ sighold(SIGTERM);
+ sighold(SIGCHLD);
+#elif defined(HAVE_SIGACTION)
+ sigemptyset(&newmask);
+ sigaddset(&newmask, SIGTERM);
+ sigaddset(&newmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &newmask, &holdmask);
+#endif /* HAVE_SIGSET */
+}
+
+
+/*
+ * 'IgnoreChildSignals()' - Ignore SIGCHLD signals...
+ *
+ * We don't really ignore them, we set the signal handler to SIG_DFL,
+ * since some OS's rely on signals for the wait4() function to work.
+ */
+
+void
+IgnoreChildSignals(void)
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGCHLD, SIG_DFL);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGCHLD);
+ action.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &action, NULL);
+#else
+ signal(SIGCLD, SIG_DFL); /* No, SIGCLD isn't a typo... */
+#endif /* HAVE_SIGSET */
+}
+
+
+/*
+ * 'ReleaseSignals()' - Release signals for delivery.
+ */
+
+void
+ReleaseSignals(void)
+{
+ holdcount --;
+ if (holdcount > 0)
+ return;
+
+#ifdef HAVE_SIGSET
+ sigrelse(SIGTERM);
+ sigrelse(SIGCHLD);
+#elif defined(HAVE_SIGACTION)
+ sigprocmask(SIG_SETMASK, &holdmask, NULL);
+#endif /* HAVE_SIGSET */
+}
+
+
+/*
+ * 'SetString()' - Set a string value.
+ */
+
+void
+SetString(char **s, /* O - New string */
+ const char *v) /* I - String value */
+{
+ if (!s || *s == v)
+ return;
+
+ if (*s)
+ free(*s);
+
+ if (v)
+ *s = strdup(v);
+ else
+ *s = NULL;
+}
+
+
+/*
+ * 'SetStringf()' - Set a formatted string value.
+ */
+
+void
+SetStringf(char **s, /* O - New string */
+ const char *f, /* I - Printf-style format string */
+ ...) /* I - Additional args as needed */
+{
+ char v[1024]; /* Formatting string value */
+ va_list ap; /* Argument pointer */
+ char *olds; /* Old string */
+
+
+ if (!s)
+ return;
+
+ olds = *s;
+
+ if (f)
+ {
+ va_start(ap, f);
+ vsnprintf(v, sizeof(v), f, ap);
+ va_end(ap);
+
+ *s = strdup(v);
+ }
+ else
+ *s = NULL;
+
+ if (olds)
+ free(olds);
+}
+
+
+/*
+ * 'parent_handler()' - Catch USR1/CHLD signals...
+ */
+
+static void
+parent_handler(int sig) /* I - Signal */
+{
+ /*
+ * Store the signal we got from the OS and return...
+ */
+
+ parent_signal = sig;
+}
+
+
+/*
+ * 'process_children()' - Process all dead children...
+ */
+
+static void
+process_children(void)
+{
+ int status; /* Exit status of child */
+ int pid; /* Process ID of child */
+ job_t *job; /* Current job */
+ int i; /* Looping var */
+
+
+ /*
+ * Reset the dead_children flag...
+ */
+
+ dead_children = 0;
+
+ /*
+ * Collect the exit status of some children...
+ */
+
+#ifdef HAVE_WAITPID
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+#elif defined(HAVE_WAIT3)
+ while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
+#else
+ if ((pid = wait(&status)) > 0)
+#endif /* HAVE_WAITPID */
+ {
+ DEBUG_printf(("process_children: pid = %d, status = %d\n", pid, status));
+
+ /*
+ * Ignore SIGTERM errors - that comes when a job is cancelled...
+ */
+
+ if (status == SIGTERM)
+ status = 0;
+
+ if (status)
+ {
+ if (WIFSTOPPED(status))
+ LogMessage(L_ERROR, "PID %d crashed on signal %d!", pid,
+ WSTOPSIG(status));
+ else
+ LogMessage(L_ERROR, "PID %d stopped with status %d!", pid,
+ WEXITSTATUS(status));
+
+ if (LogLevel < L_DEBUG)
+ LogMessage(L_INFO, "Hint: Try setting the LogLevel to \"debug\" to find out more.");
+ }
+ else
+ LogMessage(L_DEBUG2, "PID %d exited with no errors.", pid);
+
+ /*
+ * Delete certificates for CGI processes...
+ */
+
+ if (pid)
+ DeleteCert(pid);
+
+ /*
+ * Lookup the PID in the jobs list...
+ */
+
+ for (job = Jobs; job != NULL; job = job->next)
+ if (job->state != NULL &&
+ job->state->values[0].integer == IPP_JOB_PROCESSING)
+ {
+ for (i = 0; job->procs[i]; i ++)
+ if (job->procs[i] == pid)
+ break;
+
+ if (job->procs[i])
+ {
+ /*
+ * OK, this process has gone away; what's left?
+ */
+
+ job->procs[i] = -pid;
+
+ if (status && job->status >= 0)
+ {
+ /*
+ * An error occurred; save the exit status so we know to stop
+ * the printer or cancel the job when all of the filters finish...
+ *
+ * A negative status indicates that the backend failed and the
+ * printer needs to be stopped.
+ */
+
+ if (!job->procs[i + 1])
+ job->status = -status; /* Backend failed */
+ else
+ job->status = status; /* Filter failed */
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+ * 'sigchld_handler()' - Handle 'child' signals from old processes.
+ */
+
+static void
+sigchld_handler(int sig) /* I - Signal number */
+{
+ (void)sig;
+
+ /*
+ * Flag that we have dead children...
+ */
+
+ dead_children = 1;
+
+ /*
+ * Reset the signal handler as needed...
+ */
+
+#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
+ signal(SIGCLD, sigchld_handler);
+#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
+}
+
+
+/*
+ * 'sighup_handler()' - Handle 'hangup' signals to reconfigure the scheduler.
+ */
+
+static void
+sighup_handler(int sig) /* I - Signal number */
+{
+ (void)sig;
+
+ NeedReload = RELOAD_ALL;
+ ReloadTime = time(NULL);
+
+#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
+ signal(SIGHUP, sighup_handler);
+#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
+}
+
+
+/*
+ * 'sigterm_handler()' - Handle 'terminate' signals that stop the scheduler.
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal */
+{
+ (void)sig; /* remove compiler warnings... */
+
+ /*
+ * Flag that we should stop and return...
+ */
+
+ stop_scheduler = 1;
+}
+
+
+/*
+ * 'select_timeout()' - Calculate the select timeout value.
+ *
+ */
+
+static long /* O - Number of seconds */
+select_timeout(int fds) /* I - Number of ready descriptors select returned */
+{
+ int i; /* Looping var */
+ long timeout; /* Timeout for select */
+ time_t now; /* Current time */
+ client_t *con; /* Client information */
+ printer_t *p; /* Printer information */
+ job_t *job; /* Job information */
+ const char *why; /* Debugging aid */
+
+
+ /*
+ * Check to see if any of the clients have pending data to be
+ * processed; if so, the timeout should be 0...
+ */
+
+ for (i = NumClients, con = Clients; i > 0; i --, con ++)
+ if (con->http.used > 0)
+ return (0);
+
+ /*
+ * If select has been active in the last second (fds != 0) or we have
+ * many resources in use then don't bother trying to optimize the
+ * timeout, just make it 1 second.
+ */
+
+ if (fds || NumClients > 50)
+ return (1);
+
+ /*
+ * Otherwise, check all of the possible events that we need to wake for...
+ */
+
+ now = time(NULL);
+ timeout = now + 86400; /* 86400 == 1 day */
+ why = "do nothing";
+
+ /*
+ * Check the activity and close old clients...
+ */
+
+ for (i = NumClients, con = Clients; i > 0; i --, con ++)
+ if ((con->http.activity + Timeout) < timeout)
+ {
+ timeout = con->http.activity + Timeout;
+ why = "timeout a client connection";
+ }
+
+ /*
+ * Update the browse list as needed...
+ */
+
+ if (Browsing && BrowseProtocols)
+ {
+#ifdef HAVE_LIBSLP
+ if ((BrowseProtocols & BROWSE_SLP) && (BrowseSLPRefresh < timeout))
+ {
+ timeout = BrowseSLPRefresh;
+ why = "update SLP browsing";
+ }
+#endif /* HAVE_LIBSLP */
+
+ if (BrowseProtocols & BROWSE_CUPS)
+ {
+ for (p = Printers; p != NULL; p = p->next)
+ {
+ if (p->type & CUPS_PRINTER_REMOTE)
+ {
+ if ((p->browse_time + BrowseTimeout) < timeout)
+ {
+ timeout = p->browse_time + BrowseTimeout;
+ why = "browse timeout a printer";
+ }
+ }
+ else if (!(p->type & CUPS_PRINTER_IMPLICIT))
+ {
+ if (BrowseInterval && (p->browse_time + BrowseInterval) < timeout)
+ {
+ timeout = p->browse_time + BrowseInterval;
+ why = "send browse update";
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Check for any active jobs...
+ */
+
+ if (timeout > (now + 10))
+ {
+ for (job = Jobs; job != NULL; job = job->next)
+ if (job->state->values[0].integer <= IPP_JOB_PROCESSING)
+ {
+ timeout = now + 10;
+ why = "process active jobs";
+ break;
+ }
+ }
+
+#ifdef HAVE_MALLINFO
+ /*
+ * Log memory usage every minute...
+ */
+
+ if (LogLevel >= L_DEBUG && (mallinfo_time + 60) < timeout)
+ {
+ timeout = mallinfo_time + 60;
+ why = "display memory usage";
+ }
+#endif /* HAVE_MALLINFO */
+
+ /*
+ * Update the root certificate when needed...
+ */
+
+ if (RootCertDuration && (RootCertTime + RootCertDuration) < timeout)
+ {
+ timeout = RootCertTime + RootCertDuration;
+ why = "update root certificate";
+ }
+
+ /*
+ * Adjust from absolute to relative time. If p->browse_time above
+ * was 0 then we can end up with a negative value here, so check.
+ * We add 1 second to the timeout since events occur after the
+ * timeout expires, and limit the timeout to 86400 seconds (1 day)
+ * to avoid select() timeout limits present on some operating
+ * systems...
+ */
+
+ timeout = timeout - now + 1;
+
+ if (timeout < 1)
+ timeout = 1;
+ else if (timeout > 86400)
+ timeout = 86400;
+
+ /*
+ * Log and return the timeout value...
+ */
+
+ LogMessage(L_DEBUG2, "select_timeout: %ld seconds to %s", timeout, why);
+
+ return (timeout);
+}
+
+
+/*
+ * 'usage()' - Show scheduler usage.
+ */
+
+static void
+usage(void)
+{
+ fputs("Usage: cupsd [-c config-file] [-f] [-F]\n", stderr);
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/mime.c b/scheduler/mime.c
new file mode 100644
index 000000000..82025a14d
--- /dev/null
+++ b/scheduler/mime.c
@@ -0,0 +1,587 @@
+/*
+ * "$Id$"
+ *
+ * MIME database file routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * mimeDelete() - Delete (free) a MIME database.
+ * mimeMerge() - Merge a MIME database from disk with the current one.
+ * mimeNew() - Create a new, empty MIME database.
+ * load_types() - Load a xyz.types file...
+ * delete_rules() - Free all memory for the given rule tree.
+ * load_convs() - Load a xyz.convs file...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <cups/string.h>
+#include "mime.h"
+
+#ifdef WIN32
+# include <windows.h>
+#elif HAVE_DIRENT_H
+# include <dirent.h>
+typedef struct dirent DIRENT;
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+typedef struct direct DIRENT;
+# define NAMLEN(dirent) (dirent)->d_namlen
+#endif
+
+
+/*
+ * Local functions...
+ */
+
+static void load_types(mime_t *mime, const char *filename);
+static void load_convs(mime_t *mime, const char *filename,
+ const char *filterpath);
+static void delete_rules(mime_magic_t *rules);
+
+
+/*
+ * 'mimeDelete()' - Delete (free) a MIME database.
+ */
+
+void
+mimeDelete(mime_t *mime) /* I - MIME database */
+{
+ int i; /* Looping var */
+
+
+ if (mime == NULL)
+ return;
+
+ /*
+ * Loop through the file types and delete any rules...
+ */
+
+ for (i = 0; i < mime->num_types; i ++)
+ {
+ delete_rules(mime->types[i]->rules);
+ free(mime->types[i]->type);
+ free(mime->types[i]);
+ }
+
+ /*
+ * Free the types and filters arrays, and then the MIME database structure.
+ */
+
+ free(mime->types);
+ free(mime->filters);
+ free(mime);
+}
+
+
+/*
+ * 'mimeMerge()' - Merge a MIME database from disk with the current one.
+ */
+
+mime_t * /* O - Updated MIME database */
+mimeMerge(mime_t *mime, /* I - MIME database to add to */
+ const char *pathname, /* I - Directory to load */
+ const char *filterpath)/* I - Directory to load */
+{
+#ifdef WIN32
+ HANDLE dir; /* Directory handle */
+ WIN32_FIND_DATA dent; /* Directory entry */
+ char filename[1024], /* Full filename of types/converts file */
+ *pathsep; /* Last character in path */
+
+
+ /*
+ * First open the directory specified by pathname... Return NULL if nothing
+ * was read or if the pathname is NULL...
+ */
+
+ if (pathname == NULL)
+ return (NULL);
+
+ strlcpy(filename, pathname, sizeof(filename));
+
+ pathsep = filename + strlen(filename);
+ if ((pathsep - filename + 9) > sizeof(filename))
+ return (NULL);
+
+ if (pathsep == filename ||
+ (pathsep[-1] != '/' && pathsep[-1] != '\\'))
+ {
+ strcpy(pathsep, "/");
+ pathsep ++;
+ }
+
+ strcpy(pathsep, "*.types");
+
+ if ((dir = FindFirstFile(filename, &dent)) == 0)
+ return (NULL);
+
+ /*
+ * If "mime" is NULL, make a new, blank database...
+ */
+
+ if (mime == NULL)
+ if ((mime = mimeNew()) == NULL)
+ return (NULL);
+
+ /*
+ * Read all the .types files...
+ */
+
+ do
+ {
+ /*
+ * Load a mime.types file...
+ */
+
+ if ((pathsep - filename + strlen(dent.cFileName)) >= sizeof(filename))
+ continue;
+
+ strcpy(pathsep, dent.cFileName);
+ load_types(mime, filename);
+ }
+ while (FindNextFile(dir, &dent));
+
+ FindClose(dir);
+
+ /*
+ * Read all the .convs files...
+ */
+
+ strcpy(pathsep, "*.convs");
+
+ if ((dir = FindFirstFile(filename, &dent)) == 0)
+ return (mime);
+
+ do
+ {
+ /*
+ * Load a mime.convs file...
+ */
+
+ if ((pathsep - filename + strlen(dent.cFileName)) >= sizeof(filename))
+ continue;
+
+ strcpy(pathsep, dent.cFileName);
+ load_convs(mime, filename);
+ }
+ while (FindNextFile(dir, &dent));
+
+ FindClose(dir);
+
+ return (mime);
+#else
+ DIR *dir; /* Directory */
+ DIRENT *dent; /* Directory entry */
+ char filename[1024]; /* Full filename of types/converts file */
+
+
+ /*
+ * First open the directory specified by pathname... Return NULL if nothing
+ * was read or if the pathname is NULL...
+ */
+
+ if (pathname == NULL)
+ return (NULL);
+
+ if ((dir = opendir(pathname)) == NULL)
+ return (NULL);
+
+ /*
+ * If "mime" is NULL, make a new, blank database...
+ */
+
+ if (mime == NULL)
+ if ((mime = mimeNew()) == NULL)
+ return (NULL);
+
+ /*
+ * Read all the .types files...
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (NAMLEN(dent) > 6 &&
+ strcmp(dent->d_name + NAMLEN(dent) - 6, ".types") == 0)
+ {
+ /*
+ * Load a mime.types file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->d_name);
+ load_types(mime, filename);
+ }
+ }
+
+ rewinddir(dir);
+
+ /*
+ * Read all the .convs files...
+ */
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (NAMLEN(dent) > 6 &&
+ strcmp(dent->d_name + NAMLEN(dent) - 6, ".convs") == 0)
+ {
+ /*
+ * Load a mime.convs file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", pathname, dent->d_name);
+ load_convs(mime, filename, filterpath);
+ }
+ }
+
+ closedir(dir);
+
+ return (mime);
+#endif /* WIN32 */
+}
+
+
+/*
+ * 'mimeNew()' - Create a new, empty MIME database.
+ */
+
+mime_t * /* O - MIME database */
+mimeNew(void)
+{
+ return ((mime_t *)calloc(1, sizeof(mime_t)));
+}
+
+
+/*
+ * 'load_types()' - Load a xyz.types file...
+ */
+
+static void
+load_types(mime_t *mime, /* I - MIME database */
+ const char *filename) /* I - Types file to load */
+{
+ cups_file_t *fp; /* Types file */
+ int linelen; /* Length of line */
+ char line[65536], /* Input line from file */
+ *lineptr, /* Current position in line */
+ super[MIME_MAX_SUPER], /* Super-type name */
+ type[MIME_MAX_TYPE], /* Type name */
+ *temp; /* Temporary pointer */
+ mime_type_t *typeptr; /* New MIME type */
+
+
+ /*
+ * First try to open the file...
+ */
+
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ return;
+
+ /*
+ * Then read each line from the file, skipping any comments in the file...
+ */
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ /*
+ * Skip blank lines and lines starting with a #...
+ */
+
+ if (!line[0] || line[0] == '#')
+ continue;
+
+ /*
+ * While the last character in the line is a backslash, continue on to the
+ * next line (and the next, etc.)
+ */
+
+ linelen = strlen(line);
+
+ while (line[linelen - 1] == '\\')
+ {
+ linelen --;
+
+ if (cupsFileGets(fp, line + linelen, sizeof(line) - linelen) == NULL)
+ line[linelen] = '\0';
+ else
+ linelen += strlen(line + linelen);
+ }
+
+ /*
+ * Extract the super-type and type names from the beginning of the line.
+ */
+
+ lineptr = line;
+ temp = super;
+
+ while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
+ (temp - super + 1) < MIME_MAX_SUPER)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ if (*lineptr != '/')
+ continue;
+
+ lineptr ++;
+ temp = type;
+
+ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
+ *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ /*
+ * Add the type and rules to the MIME database...
+ */
+
+ typeptr = mimeAddType(mime, super, type);
+ mimeAddTypeRule(typeptr, lineptr);
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'load_convs()' - Load a xyz.convs file...
+ */
+
+static void
+load_convs(mime_t *mime, /* I - MIME database */
+ const char *filename, /* I - Convs file to load */
+ const char *filterpath) /* I - Directory to load */
+{
+ int i; /* Looping var */
+ cups_file_t *fp; /* Convs file */
+ char line[1024], /* Input line from file */
+ *lineptr, /* Current position in line */
+ super[MIME_MAX_SUPER], /* Super-type name */
+ type[MIME_MAX_TYPE], /* Type name */
+ *temp, /* Temporary pointer */
+ *filter; /* Filter program */
+ mime_type_t **temptype, /* MIME type looping var */
+ *dsttype; /* Destination MIME type */
+ int cost; /* Cost of filter */
+ char filterprog[1024]; /* Full path of filter... */
+
+
+ /*
+ * First try to open the file...
+ */
+
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ return;
+
+ /*
+ * Then read each line from the file, skipping any comments in the file...
+ */
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ /*
+ * Skip blank lines and lines starting with a #...
+ */
+
+ if (!line[0] || line[0] == '#')
+ continue;
+
+ /*
+ * Strip trailing whitespace...
+ */
+
+ for (lineptr = line + strlen(line) - 1;
+ lineptr >= line && isspace(*lineptr & 255);
+ lineptr --)
+ *lineptr = '\0';
+
+ /*
+ * Extract the destination super-type and type names from the middle of
+ * the line.
+ */
+
+ lineptr = line;
+ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0')
+ lineptr ++;
+
+ while (*lineptr == ' ' || *lineptr == '\t')
+ lineptr ++;
+
+ temp = super;
+
+ while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
+ (temp - super + 1) < MIME_MAX_SUPER)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ if (*lineptr != '/')
+ continue;
+
+ lineptr ++;
+ temp = type;
+
+ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
+ *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ if (*lineptr == '\0' || *lineptr == '\n')
+ continue;
+
+ if ((dsttype = mimeType(mime, super, type)) == NULL)
+ continue;
+
+ /*
+ * Then get the cost and filter program...
+ */
+
+ while (*lineptr == ' ' || *lineptr == '\t')
+ lineptr ++;
+
+ if (*lineptr < '0' || *lineptr > '9')
+ continue;
+
+ cost = atoi(lineptr);
+
+ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\0')
+ lineptr ++;
+ while (*lineptr == ' ' || *lineptr == '\t')
+ lineptr ++;
+
+ if (*lineptr == '\0' || *lineptr == '\n')
+ continue;
+
+ filter = lineptr;
+
+#ifndef WIN32
+ if (strcmp(filter, "-") != 0)
+ {
+ /*
+ * Verify that the filter exists and is executable...
+ */
+
+ if (filter[0] == '/')
+ strlcpy(filterprog, filter, sizeof(filterprog));
+ else
+ snprintf(filterprog, sizeof(filterprog), "%s/%s", filterpath, filter);
+
+ if (access(filterprog, X_OK))
+ continue;
+ }
+#endif /* !WIN32 */
+
+ /*
+ * Finally, get the source super-type and type names from the beginning of
+ * the line. We do it here so we can support wildcards...
+ */
+
+ lineptr = line;
+ temp = super;
+
+ while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' &&
+ (temp - super + 1) < MIME_MAX_SUPER)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ if (*lineptr != '/')
+ continue;
+
+ lineptr ++;
+ temp = type;
+
+ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' &&
+ *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE)
+ *temp++ = tolower(*lineptr++ & 255);
+
+ *temp = '\0';
+
+ if (strcmp(super, "*") == 0 && strcmp(type, "*") == 0)
+ {
+ /*
+ * Force * / * to be "application/octet-stream"...
+ */
+
+ strcpy(super, "application");
+ strcpy(type, "octet-stream");
+ }
+
+ /*
+ * Add the filter to the MIME database, supporting wildcards as needed...
+ */
+
+ for (temptype = mime->types, i = 0; i < mime->num_types; i ++, temptype ++)
+ if ((super[0] == '*' || strcmp((*temptype)->super, super) == 0) &&
+ (type[0] == '*' || strcmp((*temptype)->type, type) == 0))
+ mimeAddFilter(mime, *temptype, dsttype, cost, filter);
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'delete_rules()' - Free all memory for the given rule tree.
+ */
+
+static void
+delete_rules(mime_magic_t *rules) /* I - Rules to free */
+{
+ mime_magic_t *next; /* Next rule to free */
+
+
+ /*
+ * Free the rules list, descending recursively to free any child rules.
+ */
+
+ while (rules != NULL)
+ {
+ next = rules->next;
+
+ if (rules->child != NULL)
+ delete_rules(rules->child);
+
+ free(rules);
+ rules = next;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/mime.h b/scheduler/mime.h
new file mode 100644
index 000000000..855094ab8
--- /dev/null
+++ b/scheduler/mime.h
@@ -0,0 +1,147 @@
+/*
+ * "$Id$"
+ *
+ * MIME type/conversion database definitions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifndef _CUPS_MIME_H_
+# define _CUPS_MIME_H_
+
+# include <cups/ipp.h>
+# include "file.h"
+
+
+/*
+ * C++ magic...
+ */
+
+# ifdef _cplusplus
+extern "C" {
+# endif /* _cplusplus */
+
+
+/*
+ * Constants...
+ */
+
+# define MIME_MAX_SUPER 16 /* Maximum size of supertype name */
+# define MIME_MAX_TYPE IPP_MAX_NAME /* Maximum size of type name */
+# define MIME_MAX_FILTER 256 /* Maximum size of filter pathname */
+# define MIME_MAX_BUFFER 8192 /* Maximum size of file buffer */
+
+
+/*
+ * Types/structures...
+ */
+
+typedef enum
+{
+ MIME_MAGIC_NOP, /* No operation */
+ MIME_MAGIC_AND, /* Logical AND of all children */
+ MIME_MAGIC_OR, /* Logical OR of all children */
+ MIME_MAGIC_MATCH, /* Filename match */
+ MIME_MAGIC_ASCII, /* ASCII characters in range */
+ MIME_MAGIC_PRINTABLE, /* Printable characters (32-255) in range */
+ MIME_MAGIC_STRING, /* String matches */
+ MIME_MAGIC_CHAR, /* Character/byte matches */
+ MIME_MAGIC_SHORT, /* Short/16-bit word matches */
+ MIME_MAGIC_INT, /* Integer/32-bit word matches */
+ MIME_MAGIC_LOCALE, /* Current locale matches string */
+ MIME_MAGIC_CONTAINS, /* File contains a string */
+ MIME_MAGIC_ISTRING /* Case-insensitive string matches */
+} mime_op_t;
+
+typedef struct mime_magic_str /**** MIME Magic Data ****/
+{
+ struct mime_magic_str *prev, /* Previous rule */
+ *next, /* Next rule */
+ *parent, /* Parent rules */
+ *child; /* Child rules */
+ short op, /* Operation code (see above) */
+ invert; /* Invert the result */
+ int offset, /* Offset in file */
+ region, /* Region length */
+ length; /* Length of data */
+ union
+ {
+ char matchv[64]; /* Match value */
+ char localev[64]; /* Locale value */
+ char stringv[64]; /* String value */
+ char charv; /* Byte value */
+ short shortv; /* Short value */
+ int intv; /* Integer value */
+ } value;
+} mime_magic_t;
+
+typedef struct /**** MIME Type Data ****/
+{
+ char super[MIME_MAX_SUPER], /* Super-type name ("image", "application", etc.) */
+ *type; /* Type name ("png", "postscript", etc.) */
+ mime_magic_t *rules; /* Rules used to detect this type */
+} mime_type_t;
+
+typedef struct /**** MIME Conversion Filter Data ****/
+{
+ mime_type_t *src, /* Source type */
+ *dst; /* Destination type */
+ int cost; /* Relative cost */
+ char filter[MIME_MAX_FILTER];/* Filter program to use */
+} mime_filter_t;
+
+typedef struct /**** MIME Database ****/
+{
+ int num_types; /* Number of file types */
+ mime_type_t **types; /* File types */
+ int num_filters; /* Number of type conversion filters */
+ mime_filter_t *filters; /* Type conversion filters */
+} mime_t;
+
+
+/*
+ * Functions...
+ */
+
+extern void mimeDelete(mime_t *mime);
+#define mimeLoad(pathname,filterpath) \
+ mimeMerge((mime_t *)0, (pathname), (filterpath))
+extern mime_t *mimeMerge(mime_t *mime, const char *pathname,
+ const char *filterpath);
+extern mime_t *mimeNew(void);
+
+extern mime_type_t *mimeAddType(mime_t *mime, const char *super, const char *type);
+extern int mimeAddTypeRule(mime_type_t *mt, const char *rule);
+extern mime_type_t *mimeFileType(mime_t *mime, const char *pathname,
+ int *compression);
+extern mime_type_t *mimeType(mime_t *mime, const char *super, const char *type);
+
+extern mime_filter_t *mimeAddFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst,
+ int cost, const char *filter);
+extern mime_filter_t *mimeFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst,
+ int *num_filters, int max_depth);
+
+# ifdef _cplusplus
+}
+# endif /* _cplusplus */
+#endif /* !_CUPS_MIME_H_ */
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/network.c b/scheduler/network.c
new file mode 100644
index 000000000..bf6f08ee1
--- /dev/null
+++ b/scheduler/network.c
@@ -0,0 +1,491 @@
+/*
+ * "$Id$"
+ *
+ * Network interface functions for the Common UNIX Printing System
+ * (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Include necessary headers.
+ */
+
+#include "cupsd.h"
+
+#include <net/if.h>
+
+#ifdef HAVE_GETIFADDRS
+/*
+ * Use native getifaddrs() function...
+ */
+# include <ifaddrs.h>
+#else
+/*
+ * Use getifaddrs() emulation...
+ */
+
+# include <sys/ioctl.h>
+# ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+# endif
+
+# ifdef ifa_dstaddr
+# undef ifa_dstaddr
+# endif /* ifa_dstaddr */
+# ifndef ifr_netmask
+# define ifr_netmask ifr_addr
+# endif /* !ifr_netmask */
+
+struct ifaddrs /**** Interface Structure ****/
+{
+ struct ifaddrs *ifa_next; /* Next interface in list */
+ char *ifa_name; /* Name of interface */
+ unsigned int ifa_flags; /* Flags (up, point-to-point, etc.) */
+ struct sockaddr *ifa_addr, /* Network address */
+ *ifa_netmask, /* Address mask */
+ *ifa_dstaddr; /* Broadcast or destination address */
+ void *ifa_data; /* Interface statistics */
+};
+
+int getifaddrs(struct ifaddrs **addrs);
+void freeifaddrs(struct ifaddrs *addrs);
+#endif /* HAVE_GETIFADDRS */
+
+
+/*
+ * 'NetIFFind()' - Find a network interface.
+ */
+
+cups_netif_t * /* O - Network interface data */
+NetIFFind(const char *name) /* I - Name of interface */
+{
+ cups_netif_t *temp; /* Current network interface */
+
+
+ /*
+ * Update the interface list as needed...
+ */
+
+ NetIFUpdate();
+
+ /*
+ * Search for the named interface...
+ */
+
+ for (temp = NetIFList; temp != NULL; temp = temp->next)
+ if (strcasecmp(name, temp->name) == 0)
+ return (temp);
+
+ return (NULL);
+}
+
+
+/*
+ * 'NetIFFree()' - Free the current network interface list.
+ */
+
+void
+NetIFFree(void)
+{
+ cups_netif_t *next; /* Next interface in list */
+
+
+ /*
+ * Loop through the interface list and free all the records...
+ */
+
+ while (NetIFList != NULL)
+ {
+ next = NetIFList->next;
+
+ free(NetIFList);
+
+ NetIFList = next;
+ }
+}
+
+
+/*
+ * 'NetIFUpdate()' - Update the network interface list as needed...
+ */
+
+void
+NetIFUpdate(void)
+{
+ int i; /* Looping var */
+ listener_t *lis; /* Listen address */
+ cups_netif_t *temp; /* Current interface */
+ struct ifaddrs *addrs, /* Interface address list */
+ *addr; /* Current interface address */
+ struct hostent *host; /* Host lookup info */
+
+
+ /*
+ * Update the network interface list no more often than once a
+ * minute...
+ */
+
+ if ((time(NULL) - NetIFTime) < 60)
+ return;
+
+ NetIFTime = time(NULL);
+
+ /*
+ * Free the old interfaces...
+ */
+
+ NetIFFree();
+
+ /*
+ * Grab a new list of interfaces...
+ */
+
+ if (getifaddrs(&addrs) < 0)
+ return;
+
+ for (addr = addrs; addr != NULL; addr = addr->ifa_next)
+ {
+ /*
+ * See if this interface address is IPv4...
+ */
+
+ if (addr->ifa_addr == NULL || addr->ifa_addr->sa_family != AF_INET ||
+ addr->ifa_netmask == NULL || addr->ifa_name == NULL)
+ continue;
+
+ /*
+ * OK, we have an IPv4 address, so create a new list node...
+ */
+
+ if ((temp = calloc(1, sizeof(cups_netif_t))) == NULL)
+ break;
+
+ temp->next = NetIFList;
+ NetIFList = temp;
+
+ /*
+ * Then copy all of the information...
+ */
+
+ strlcpy(temp->name, addr->ifa_name, sizeof(temp->name));
+ memcpy(&(temp->address), addr->ifa_addr, sizeof(temp->address));
+ memcpy(&(temp->mask), addr->ifa_netmask, sizeof(temp->mask));
+
+ if (addr->ifa_dstaddr)
+ memcpy(&(temp->broadcast), addr->ifa_dstaddr, sizeof(temp->broadcast));
+
+ if (!(addr->ifa_flags & IFF_POINTOPOINT) &&
+ ntohl(temp->address.sin_addr.s_addr) != 0x7f000001)
+ temp->is_local = 1;
+
+ /*
+ * Determine which port to use when advertising printers...
+ */
+
+ for (i = NumListeners, lis = Listeners; i > 0; i --, lis ++)
+ if (lis->address.sin_addr.s_addr == 0x00000000 ||
+ (lis->address.sin_addr.s_addr & temp->mask.sin_addr.s_addr) ==
+ temp->address.sin_addr.s_addr)
+ {
+ temp->port = ntohs(lis->address.sin_port);
+ break;
+ }
+
+ /*
+ * Finally, try looking up the hostname for the address as needed...
+ */
+
+ if (HostNameLookups)
+ {
+#ifndef __sgi
+ host = gethostbyaddr((char *)&(temp->address.sin_addr),
+ sizeof(struct in_addr), AF_INET);
+#else
+ host = gethostbyaddr(&(temp->address.sin_addr),
+ sizeof(struct in_addr), AF_INET);
+#endif /* !__sgi */
+ }
+ else
+ host = NULL;
+
+ /*
+ * Map the default server address and localhost to the server name
+ * and localhost, respectively; for all other addresses, use the
+ * dotted notation...
+ */
+
+ if (host != NULL)
+ strlcpy(temp->hostname, host->h_name, sizeof(temp->hostname));
+ else if (ntohl(temp->address.sin_addr.s_addr) == 0x7f000001)
+ strcpy(temp->hostname, "localhost");
+ else if (temp->address.sin_addr.s_addr == ServerAddr.sin_addr.s_addr)
+ strlcpy(temp->hostname, ServerName, sizeof(temp->hostname));
+ else
+ {
+ unsigned ip = ntohl(temp->address.sin_addr.s_addr);
+
+ snprintf(temp->hostname, sizeof(temp->hostname), "%d.%d.%d.%d",
+ (ip >> 24) & 255, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
+ }
+ }
+
+ freeifaddrs(addrs);
+}
+
+
+#ifndef HAVE_GETIFADDRS
+/*
+ * 'getifaddrs()' - Get a list of network interfaces on the system.
+ */
+
+int /* O - 0 on success, -1 on error */
+getifaddrs(struct ifaddrs **addrs) /* O - List of interfaces */
+{
+ int sock; /* Socket */
+ char buffer[65536], /* Buffer for address info */
+ *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+ struct ifconf conf; /* Interface configurations */
+ struct sockaddr addr; /* Address data */
+ struct ifreq *ifp; /* Interface data */
+ int ifpsize; /* Size of interface data */
+ struct ifaddrs *temp; /* Pointer to current interface */
+ struct ifreq request; /* Interface request */
+
+
+ /*
+ * Start with an empty list...
+ */
+
+ if (addrs == NULL)
+ return (-1);
+
+ *addrs = NULL;
+
+ /*
+ * Create a UDP socket to get the interface data...
+ */
+
+ memset (&addr, 0, sizeof(addr));
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return (-1);
+
+ /*
+ * Try to get the list of interfaces...
+ */
+
+ conf.ifc_len = sizeof(buffer);
+ conf.ifc_buf = buffer;
+
+ if (ioctl(sock, SIOCGIFCONF, &conf) < 0)
+ {
+ /*
+ * Couldn't get the list of interfaces...
+ */
+
+ close(sock);
+ return (-1);
+ }
+
+ /*
+ * OK, got the list of interfaces, now lets step through the
+ * buffer to pull them out...
+ */
+
+# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# define sockaddr_len(a) ((a)->sa_len)
+# else
+# define sockaddr_len(a) (sizeof(struct sockaddr))
+# endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+ for (bufptr = buffer, bufend = buffer + conf.ifc_len;
+ bufptr < bufend;
+ bufptr += ifpsize)
+ {
+ /*
+ * Get the current interface information...
+ */
+
+ ifp = (struct ifreq *)bufptr;
+ ifpsize = sizeof(ifp->ifr_name) + sockaddr_len(&(ifp->ifr_addr));
+
+ if (ifpsize < sizeof(struct ifreq))
+ ifpsize = sizeof(struct ifreq);
+
+ memset(&request, 0, sizeof(request));
+ memcpy(request.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name));
+
+ /*
+ * Check the status of the interface...
+ */
+
+ if (ioctl(sock, SIOCGIFFLAGS, &request) < 0)
+ continue;
+
+ /*
+ * Allocate memory for a single interface record...
+ */
+
+ if ((temp = calloc(1, sizeof(struct ifaddrs))) == NULL)
+ {
+ /*
+ * Unable to allocate memory...
+ */
+
+ close(sock);
+ return (-1);
+ }
+
+ /*
+ * Add this record to the front of the list and copy the name, flags,
+ * and network address...
+ */
+
+ temp->ifa_next = *addrs;
+ *addrs = temp;
+ temp->ifa_name = strdup(ifp->ifr_name);
+ temp->ifa_flags = request.ifr_flags;
+ if ((temp->ifa_addr = calloc(1, sockaddr_len(&(ifp->ifr_addr)))) != NULL)
+ memcpy(temp->ifa_addr, &(ifp->ifr_addr), sockaddr_len(&(ifp->ifr_addr)));
+
+ /*
+ * Try to get the netmask for the interface...
+ */
+
+ if (!ioctl(sock, SIOCGIFNETMASK, &request))
+ {
+ /*
+ * Got it, make a copy...
+ */
+
+ if ((temp->ifa_netmask = calloc(1, sizeof(request.ifr_netmask))) != NULL)
+ memcpy(temp->ifa_netmask, &(request.ifr_netmask),
+ sizeof(request.ifr_netmask));
+ }
+
+ /*
+ * Then get the broadcast or point-to-point (destination) address,
+ * if applicable...
+ */
+
+ if (temp->ifa_flags & IFF_BROADCAST)
+ {
+ /*
+ * Have a broadcast address, so get it!
+ */
+
+ if (!ioctl(sock, SIOCGIFBRDADDR, &request))
+ {
+ /*
+ * Got it, make a copy...
+ */
+
+ if ((temp->ifa_dstaddr = calloc(1, sizeof(request.ifr_broadaddr))) != NULL)
+ memcpy(temp->ifa_dstaddr, &(request.ifr_broadaddr),
+ sizeof(request.ifr_broadaddr));
+ }
+ }
+ else if (temp->ifa_flags & IFF_POINTOPOINT)
+ {
+ /*
+ * Point-to-point interface; grab the remote address...
+ */
+
+ if (!ioctl(sock, SIOCGIFDSTADDR, &request))
+ {
+ temp->ifa_dstaddr = malloc(sizeof(request.ifr_dstaddr));
+ memcpy(temp->ifa_dstaddr, &(request.ifr_dstaddr),
+ sizeof(request.ifr_dstaddr));
+ }
+ }
+ }
+
+ /*
+ * OK, we're done with the socket, close it and return 0...
+ */
+
+ close(sock);
+
+ return (0);
+}
+
+
+/*
+ * 'freeifaddrs()' - Free an interface list...
+ */
+
+void
+freeifaddrs(struct ifaddrs *addrs) /* I - Interface list to free */
+{
+ struct ifaddrs *next; /* Next interface in list */
+
+
+ while (addrs != NULL)
+ {
+ /*
+ * Make a copy of the next interface pointer...
+ */
+
+ next = addrs->ifa_next;
+
+ /*
+ * Free data values as needed...
+ */
+
+ if (addrs->ifa_name)
+ {
+ free(addrs->ifa_name);
+ addrs->ifa_name = NULL;
+ }
+
+ if (addrs->ifa_addr)
+ {
+ free(addrs->ifa_addr);
+ addrs->ifa_addr = NULL;
+ }
+
+ if (addrs->ifa_netmask)
+ {
+ free(addrs->ifa_netmask);
+ addrs->ifa_netmask = NULL;
+ }
+
+ if (addrs->ifa_dstaddr)
+ {
+ free(addrs->ifa_dstaddr);
+ addrs->ifa_dstaddr = NULL;
+ }
+
+ /*
+ * Free this node and continue to the next...
+ */
+
+ free(addrs);
+
+ addrs = next;
+ }
+}
+
+#endif /* !HAVE_GETIFADDRS */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/network.h b/scheduler/network.h
new file mode 100644
index 000000000..40126f768
--- /dev/null
+++ b/scheduler/network.h
@@ -0,0 +1,64 @@
+/*
+ * "$Id$"
+ *
+ * Network interface definitions for the Common UNIX Printing System
+ * (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Structures...
+ */
+
+typedef struct cups_netif_str /**** Network interface data ****/
+{
+ struct cups_netif_str *next; /* Next interface in list */
+ char name[32], /* Network interface name */
+ hostname[HTTP_MAX_HOST];
+ /* Hostname associated with interface */
+ int is_local, /* Local (not point-to-point) interface? */
+ port; /* Listen port */
+ struct sockaddr_in address, /* Network address */
+ mask, /* Network mask */
+ broadcast; /* Broadcast address */
+} cups_netif_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR time_t NetIFTime VALUE(0);
+ /* Network interface list time */
+VAR cups_netif_t *NetIFList VALUE(NULL);
+ /* List of network interfaces */
+
+/*
+ * Prototypes...
+ */
+
+extern cups_netif_t *NetIFFind(const char *name);
+extern void NetIFFree(void);
+extern void NetIFUpdate(void);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/ppds.c b/scheduler/ppds.c
new file mode 100644
index 000000000..0c2adff84
--- /dev/null
+++ b/scheduler/ppds.c
@@ -0,0 +1,781 @@
+/*
+ * "$Id$"
+ *
+ * PPD scanning routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * LoadPPDs() - Load PPD files from the specified directory...
+ * buf_read() - Read a buffer of data into memory...
+ * check_ppds() - Check to see if we need to regenerate the PPD file
+ * list...
+ * compare_names() - Compare PPD filenames for sorting.
+ * compare_ppds() - Compare PPD file make and model names for sorting.
+ * load_ppds() - Load PPD files recursively.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+#include <ctype.h>
+
+
+/*
+ * PPD information structures...
+ */
+
+typedef struct
+{
+ char ppd_make[128], /* Manufacturer */
+ ppd_make_and_model[248]; /* Make and model */
+ int ppd_size, /* Size in bytes */
+ ppd_mtime; /* Modification time */
+ char ppd_name[256], /* PPD filename */
+ ppd_natural_language[16]; /* Natural language */
+} ppd_rec_t;
+
+typedef struct
+{
+ int found; /* 1 if PPD is found */
+ ppd_rec_t record; /* ppds.dat record */
+} ppd_info_t;
+
+
+/*
+ * Local globals...
+ */
+
+static int num_ppds, /* Number of PPD files */
+ sorted_ppds, /* Number of sorted PPD files */
+ alloc_ppds; /* Number of allocated entries */
+static ppd_info_t *ppds; /* PPD file info */
+static int changed_ppd; /* Did we change the PPD database? */
+
+
+/*
+ * Local functions...
+ */
+
+static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1);
+static int compare_ppds(const ppd_info_t *p0, const ppd_info_t *p1);
+static void load_ppds(const char *d, const char *p);
+
+
+/*
+ * 'LoadPPDs()' - Load PPD files from the specified directory...
+ */
+
+void
+LoadPPDs(const char *d) /* I - Directory to scan... */
+{
+ int i; /* Looping var */
+ ppd_info_t *ppd; /* Current PPD file */
+ cups_file_t *fp; /* ppds.dat file */
+ struct stat fileinfo; /* ppds.dat information */
+ char filename[1024]; /* ppds.dat filename */
+
+
+ /*
+ * See if we a PPD database file...
+ */
+
+ num_ppds = 0;
+ alloc_ppds = 0;
+ ppds = (ppd_info_t *)0;
+ changed_ppd = 0;
+
+ snprintf(filename, sizeof(filename), "%s/ppds.dat", ServerRoot);
+ if (!stat(filename, &fileinfo) &&
+ (num_ppds = fileinfo.st_size / sizeof(ppd_rec_t)) > 0)
+ {
+ /*
+ * We have a ppds.dat file, so read it!
+ */
+
+ alloc_ppds = num_ppds;
+
+ if ((ppds = malloc(sizeof(ppd_info_t) * num_ppds)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadPPDs: Unable to allocate memory for %d PPD files!",
+ num_ppds);
+ num_ppds = 0;
+ alloc_ppds = 0;
+ }
+ else if ((fp = cupsFileOpen(filename, "rb")) != NULL)
+ {
+ for (i = num_ppds, ppd = ppds; i > 0; i --, ppd ++)
+ {
+ cupsFileRead(fp, (char *)&(ppd->record), sizeof(ppd_rec_t));
+ ppd->found = 0;
+ }
+
+ cupsFileClose(fp);
+
+ LogMessage(L_INFO, "LoadPPDs: Read \"%s\", %d PPDs...", filename,
+ num_ppds);
+
+ /*
+ * Sort the PPDs by name...
+ */
+
+ if (num_ppds > 1)
+ {
+ qsort(ppds, num_ppds, sizeof(ppd_info_t),
+ (int (*)(const void *, const void *))compare_names);
+ }
+ }
+ else
+ {
+ LogMessage(L_ERROR, "LoadPPDs: Unable to read \"%s\" - %s", filename,
+ strerror(errno));
+ num_ppds = 0;
+ }
+ }
+
+ /*
+ * Load all PPDs in the specified directory and below...
+ */
+
+ sorted_ppds = num_ppds;
+
+ load_ppds(d, "");
+
+ /*
+ * Cull PPD files that are no longer present...
+ */
+
+ for (i = num_ppds, ppd = ppds; i > 0; i --, ppd ++)
+ if (!ppd->found)
+ {
+ /*
+ * Remove this PPD file from the list...
+ */
+
+ if (i > 1)
+ memmove(ppd, ppd + 1, (i - 1) * sizeof(ppd_info_t));
+
+ num_ppds --;
+ ppd --;
+ }
+
+ /*
+ * Sort the PPDs by make and model...
+ */
+
+ if (num_ppds > 1)
+ qsort(ppds, num_ppds, sizeof(ppd_info_t),
+ (int (*)(const void *, const void *))compare_ppds);
+
+ /*
+ * Write the new ppds.dat file...
+ */
+
+ if (changed_ppd)
+ {
+ if ((fp = cupsFileOpen(filename, "wb")) != NULL)
+ {
+ for (i = num_ppds, ppd = ppds; i > 0; i --, ppd ++)
+ cupsFileWrite(fp, (char *)&(ppd->record), sizeof(ppd_rec_t));
+
+ cupsFileClose(fp);
+
+ LogMessage(L_INFO, "LoadPPDs: Wrote \"%s\", %d PPDs...", filename,
+ num_ppds);
+ }
+ else
+ LogMessage(L_ERROR, "LoadPPDs: Unable to write \"%s\" - %s", filename,
+ strerror(errno));
+ }
+ else
+ LogMessage(L_INFO, "LoadPPDs: No new or changed PPDs...");
+
+ /*
+ * Create the list of PPDs...
+ */
+
+ PPDs = ippNew();
+
+ /*
+ * First the raw driver...
+ */
+
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "ppd-name", NULL, "raw");
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "ppd-make", NULL, "Raw");
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "ppd-make-and-model", NULL, "Raw Queue");
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "ppd-natural-language", NULL, "en");
+
+ /*
+ * Then the PPD files...
+ */
+
+ for (i = num_ppds, ppd = ppds; i > 0; i --, ppd ++)
+ {
+ ippAddSeparator(PPDs);
+
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "ppd-name", NULL, ppd->record.ppd_name);
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "ppd-make", NULL, ppd->record.ppd_make);
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "ppd-make-and-model", NULL, ppd->record.ppd_make_and_model);
+ ippAddString(PPDs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "ppd-natural-language", NULL, ppd->record.ppd_natural_language);
+ }
+
+ /*
+ * Free the memory used...
+ */
+
+ if (alloc_ppds)
+ {
+ free(ppds);
+ alloc_ppds = 0;
+ }
+}
+
+
+/*
+ * 'compare_names()' - Compare PPD filenames for sorting.
+ */
+
+static int /* O - Result of comparison */
+compare_names(const ppd_info_t *p0, /* I - First PPD file */
+ const ppd_info_t *p1) /* I - Second PPD file */
+{
+ return (strcasecmp(p0->record.ppd_name, p1->record.ppd_name));
+}
+
+
+/*
+ * 'compare_ppds()' - Compare PPD file make and model names for sorting.
+ */
+
+static int /* O - Result of comparison */
+compare_ppds(const ppd_info_t *p0, /* I - First PPD file */
+ const ppd_info_t *p1) /* I - Second PPD file */
+{
+ const char *s, /* First name */
+ *t; /* Second name */
+ int diff, /* Difference between digits */
+ digits; /* Number of digits */
+
+
+ /*
+ * First compare manufacturers...
+ */
+
+ if ((diff = strcasecmp(p0->record.ppd_make, p1->record.ppd_make)) != 0)
+ return (diff);
+
+ /*
+ * Then compare names...
+ */
+
+ s = p0->record.ppd_make_and_model;
+ t = p1->record.ppd_make_and_model;
+
+ /*
+ * Loop through both nicknames, returning only when a difference is
+ * seen. Also, compare whole numbers rather than just characters, too!
+ */
+
+ while (*s && *t)
+ {
+ if (isdigit(*s & 255) && isdigit(*t & 255))
+ {
+ /*
+ * Got a number; start by skipping leading 0's...
+ */
+
+ while (*s == '0')
+ s ++;
+ while (*t == '0')
+ t ++;
+
+ /*
+ * Skip equal digits...
+ */
+
+ while (isdigit(*s & 255) && *s == *t)
+ {
+ s ++;
+ t ++;
+ }
+
+ /*
+ * Bounce out if *s and *t aren't both digits...
+ */
+
+ if (isdigit(*s & 255) && !isdigit(*t & 255))
+ return (1);
+ else if (!isdigit(*s & 255) && isdigit(*t & 255))
+ return (-1);
+ else if (!isdigit(*s & 255) || !isdigit(*t & 255))
+ continue;
+
+ if (*s < *t)
+ diff = -1;
+ else
+ diff = 1;
+
+ /*
+ * Figure out how many more digits there are...
+ */
+
+ digits = 0;
+ s ++;
+ t ++;
+
+ while (isdigit(*s & 255))
+ {
+ digits ++;
+ s ++;
+ }
+
+ while (isdigit(*t & 255))
+ {
+ digits --;
+ t ++;
+ }
+
+ /*
+ * Return if the number or value of the digits is different...
+ */
+
+ if (digits < 0)
+ return (-1);
+ else if (digits > 0)
+ return (1);
+ else if (diff)
+ return (diff);
+ }
+ else if (tolower(*s & 255) < tolower(*t & 255))
+ return (-1);
+ else if (tolower(*s & 255) > tolower(*t & 255))
+ return (1);
+ else
+ {
+ s ++;
+ t ++;
+ }
+ }
+
+ /*
+ * Return the results of the final comparison...
+ */
+
+ if (*s)
+ return (1);
+ else if (*t)
+ return (-1);
+ else
+ return (strcasecmp(p0->record.ppd_natural_language,
+ p1->record.ppd_natural_language));
+}
+
+
+/*
+ * 'load_ppds()' - Load PPD files recursively.
+ */
+
+static void
+load_ppds(const char *d, /* I - Actual directory */
+ const char *p) /* I - Virtual path in name */
+{
+ int i; /* Looping var */
+ cups_file_t *fp; /* Pointer to file */
+ DIR *dir; /* Directory pointer */
+ DIRENT *dent; /* Directory entry */
+ struct stat fileinfo; /* File information */
+ char filename[1024], /* Name of PPD or directory */
+ line[256], /* Line from backend */
+ *ptr, /* Pointer into name */
+ name[128], /* Name of PPD file */
+ language[64], /* PPD language version */
+ country[64], /* Country code */
+ manufacturer[256], /* Manufacturer */
+ make_model[256], /* Make and Model */
+ model_name[256], /* ModelName */
+ nick_name[256]; /* NickName */
+ ppd_info_t *ppd, /* New PPD file */
+ key; /* Search key */
+ int new_ppd; /* Is this a new PPD? */
+ struct /* LanguageVersion translation table */
+ {
+ const char *version, /* LanguageVersion string */
+ *language; /* Language code */
+ } languages[] =
+ {
+ { "chinese", "cn" },
+ { "danish", "da" },
+ { "dutch", "nl" },
+ { "english", "en" },
+ { "finnish", "fi" },
+ { "french", "fr" },
+ { "german", "de" },
+ { "greek", "el" },
+ { "italian", "it" },
+ { "japanese", "jp" },
+ { "norwegian", "no" },
+ { "polish", "pl" },
+ { "portuguese", "pt" },
+ { "russian", "ru" },
+ { "slovak", "sk" },
+ { "spanish", "es" },
+ { "swedish", "sv" },
+ { "turkish", "tr" }
+ };
+
+
+ if ((dir = opendir(d)) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadPPDs: Unable to open PPD directory \"%s\": %s",
+ d, strerror(errno));
+ return;
+ }
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ /*
+ * Skip "." and ".."...
+ */
+
+ if (dent->d_name[0] == '.')
+ continue;
+
+ /*
+ * See if this is a file...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%s", d, dent->d_name);
+
+ if (p[0])
+ snprintf(name, sizeof(name), "%s/%s", p, dent->d_name);
+ else
+ strlcpy(name, dent->d_name, sizeof(name));
+
+ if (stat(filename, &fileinfo))
+ continue;
+
+ if (S_ISDIR(fileinfo.st_mode))
+ {
+ /*
+ * Do subdirectory...
+ */
+
+ load_ppds(filename, name);
+ continue;
+ }
+
+ /*
+ * See if this file has been scanned before...
+ */
+
+ if (sorted_ppds > 0)
+ {
+ strcpy(key.record.ppd_name, name);
+
+ ppd = bsearch(&key, ppds, sorted_ppds, sizeof(ppd_info_t),
+ (int (*)(const void *, const void *))compare_names);
+
+ if (ppd &&
+ ppd->record.ppd_size == fileinfo.st_size &&
+ ppd->record.ppd_mtime == fileinfo.st_mtime)
+ {
+ ppd->found = 1;
+ continue;
+ }
+ }
+ else
+ ppd = NULL;
+
+ /*
+ * No, file is new/changed, so re-scan it...
+ */
+
+ if ((fp = cupsFileOpen(filename, "rb")) == NULL)
+ continue;
+
+ /*
+ * Now see if this is a PPD file...
+ */
+
+ line[0] = '\0';
+ cupsFileGets(fp, line, sizeof(line));
+
+ if (strncmp(line, "*PPD-Adobe:", 11) != 0)
+ {
+ /*
+ * Nope, close the file and continue...
+ */
+
+ cupsFileClose(fp);
+
+ continue;
+ }
+
+ /*
+ * Now read until we get the NickName field...
+ */
+
+ model_name[0] = '\0';
+ nick_name[0] = '\0';
+ manufacturer[0] = '\0';
+ strcpy(language, "en");
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ if (strncmp(line, "*Manufacturer:", 14) == 0)
+ sscanf(line, "%*[^\"]\"%255[^\"]", manufacturer);
+ else if (strncmp(line, "*ModelName:", 11) == 0)
+ sscanf(line, "%*[^\"]\"%127[^\"]", model_name);
+ else if (strncmp(line, "*LanguageVersion:", 17) == 0)
+ sscanf(line, "%*[^:]:%63s", language);
+ else if (strncmp(line, "*NickName:", 10) == 0)
+ sscanf(line, "%*[^\"]\"%255[^\"]", nick_name);
+ else if (strncmp(line, "*OpenUI", 7) == 0)
+ {
+ /*
+ * Stop early if we have a NickName or ModelName attributes
+ * before the first OpenUI...
+ */
+
+ if (model_name[0] || nick_name[0])
+ break;
+ }
+
+ /*
+ * Stop early if we have both the Manufacturer and NickName
+ * attributes...
+ */
+
+ if (manufacturer[0] && nick_name[0])
+ break;
+ }
+
+ /*
+ * Close the file...
+ */
+
+ cupsFileClose(fp);
+
+ /*
+ * See if we got all of the required info...
+ */
+
+ if (nick_name[0])
+ strcpy(make_model, nick_name);
+ else
+ strcpy(make_model, model_name);
+
+ while (isspace(make_model[0] & 255))
+ cups_strcpy(make_model, make_model + 1);
+
+ if (!make_model[0])
+ continue; /* Nope... */
+
+ /*
+ * See if we got a manufacturer...
+ */
+
+ while (isspace(manufacturer[0] & 255))
+ cups_strcpy(manufacturer, manufacturer + 1);
+
+ if (!manufacturer[0] || strcmp(manufacturer, "ESP") == 0)
+ {
+ /*
+ * Nope, copy the first part of the make and model then...
+ */
+
+ strlcpy(manufacturer, make_model, sizeof(manufacturer));
+
+ /*
+ * Truncate at the first space, dash, or slash, or make the
+ * manufacturer "Other"...
+ */
+
+ for (ptr = manufacturer; *ptr; ptr ++)
+ if (*ptr == ' ' || *ptr == '-' || *ptr == '/')
+ break;
+
+ if (*ptr && ptr > manufacturer)
+ *ptr = '\0';
+ else if (strncasecmp(manufacturer, "agfa", 4) == 0)
+ strcpy(manufacturer, "AGFA");
+ else if (strncasecmp(manufacturer, "herk", 4) == 0 ||
+ strncasecmp(manufacturer, "linotype", 8) == 0)
+ strcpy(manufacturer, "LHAG");
+ else
+ strcpy(manufacturer, "Other");
+
+ /*
+ * Hack for various vendors...
+ */
+
+ if (strcasecmp(manufacturer, "XPrint") == 0)
+ strcpy(manufacturer, "Xerox");
+ else if (strcasecmp(manufacturer, "Eastman") == 0)
+ strcpy(manufacturer, "Kodak");
+ else if (strcasecmp(manufacturer, "laserwriter") == 0)
+ strcpy(manufacturer, "Apple");
+ else if (strcasecmp(manufacturer, "colorpoint") == 0)
+ strcpy(manufacturer, "Seiko");
+ else if (strcasecmp(manufacturer, "fiery") == 0)
+ strcpy(manufacturer, "EFI");
+ else if (strcasecmp(manufacturer, "ps") == 0 ||
+ strcasecmp(manufacturer, "colorpass") == 0)
+ strcpy(manufacturer, "Canon");
+ else if (strncasecmp(manufacturer, "primera", 7) == 0)
+ strcpy(manufacturer, "Fargo");
+ else if (strcasecmp(manufacturer, "designjet") == 0)
+ strcpy(manufacturer, "HP");
+ }
+ else if (strncasecmp(manufacturer, "LHAG", 4) == 0 ||
+ strncasecmp(manufacturer, "linotype", 8) == 0)
+ strcpy(manufacturer, "LHAG");
+
+ /*
+ * Fix the language as needed...
+ */
+
+ if ((ptr = strchr(language, '-')) != NULL)
+ *ptr++ = '\0';
+ else if ((ptr = strchr(language, '_')) != NULL)
+ *ptr++ = '\0';
+
+ if (ptr)
+ {
+ /*
+ * Setup the country suffix...
+ */
+
+ country[0] = '_';
+ cups_strcpy(country + 1, ptr);
+ }
+ else
+ {
+ /*
+ * No country suffix...
+ */
+
+ country[0] = '\0';
+ }
+
+ for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
+ if (strcasecmp(languages[i].version, language) == 0)
+ break;
+
+ if (i < (int)(sizeof(languages) / sizeof(languages[0])))
+ {
+ /*
+ * Found a known language...
+ */
+
+ snprintf(language, sizeof(language), "%s%s", languages[i].language,
+ country);
+ }
+ else
+ {
+ /*
+ * Unknown language; use "xx"...
+ */
+
+ strcpy(language, "xx");
+ }
+
+ /*
+ * Add the PPD file...
+ */
+
+ new_ppd = !ppd;
+
+ if (new_ppd)
+ {
+ /*
+ * Allocate memory for the new PPD file...
+ */
+
+ LogMessage(L_DEBUG, "LoadPPDs: Adding ppd \"%s\"...", name);
+
+ if (num_ppds >= alloc_ppds)
+ {
+ /*
+ * Allocate (more) memory for the PPD files...
+ */
+
+ if (alloc_ppds == 0)
+ ppd = malloc(sizeof(ppd_info_t) * 32);
+ else
+ ppd = realloc(ppds, sizeof(ppd_info_t) * (alloc_ppds + 32));
+
+ if (ppd == NULL)
+ {
+ LogMessage(L_ERROR, "load_ppds: Ran out of memory for %d PPD files!",
+ alloc_ppds + 32);
+ closedir(dir);
+ return;
+ }
+
+ ppds = ppd;
+ alloc_ppds += 32;
+ }
+
+ ppd = ppds + num_ppds;
+ num_ppds ++;
+ }
+ else
+ LogMessage(L_DEBUG, "LoadPPDs: Updating ppd \"%s\"...", name);
+
+ /*
+ * Zero the PPD record and copy the info over...
+ */
+
+ memset(ppd, 0, sizeof(ppd_info_t));
+
+ ppd->found = 1;
+ ppd->record.ppd_mtime = fileinfo.st_mtime;
+ ppd->record.ppd_size = fileinfo.st_size;
+
+ strlcpy(ppd->record.ppd_name, name,
+ sizeof(ppd->record.ppd_name));
+ strlcpy(ppd->record.ppd_make, manufacturer,
+ sizeof(ppd->record.ppd_make));
+ strlcpy(ppd->record.ppd_make_and_model, make_model,
+ sizeof(ppd->record.ppd_make_and_model));
+ strlcpy(ppd->record.ppd_natural_language, language,
+ sizeof(ppd->record.ppd_natural_language));
+
+ changed_ppd = 1;
+ }
+
+ closedir(dir);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/printers.c b/scheduler/printers.c
new file mode 100644
index 000000000..b55cadb65
--- /dev/null
+++ b/scheduler/printers.c
@@ -0,0 +1,2495 @@
+/*
+ * "$Id$"
+ *
+ * Printer routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddPrinter() - Add a printer to the system.
+ * AddPrinterFilter() - Add a MIME filter for a printer.
+ * AddPrinterHistory() - Add the current printer state to the history.
+ * AddPrinterUser() - Add a user to the ACL.
+ * DeleteAllPrinters() - Delete all printers from the system.
+ * DeletePrinter() - Delete a printer from the system.
+ * DeletePrinterFilters() - Delete all MIME filters for a printer.
+ * FindPrinter() - Find a printer in the list.
+ * FreePrinterUsers() - Free allow/deny users.
+ * LoadAllPrinters() - Load printers from the printers.conf file.
+ * SaveAllPrinters() - Save all printer definitions to the printers.conf
+ * SetPrinterAttrs() - Set printer attributes based upon the PPD file.
+ * SetPrinterReasons() - Set/update the reasons strings.
+ * SetPrinterState() - Update the current state of a printer.
+ * SortPrinters() - Sort the printer list when a printer name is
+ * changed.
+ * StopPrinter() - Stop a printer from printing any jobs...
+ * ValidateDest() - Validate a printer/class destination.
+ * WritePrintcap() - Write a pseudo-printcap file for older
+ * applications that need it...
+ * cupsdSanitizeURI() - Sanitize a device URI...
+ * write_irix_config() - Update the config files used by the IRIX
+ * desktop tools.
+ * write_irix_state() - Update the status files used by IRIX printing
+ * desktop tools.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * Local functions...
+ */
+
+#ifdef __sgi
+static void write_irix_config(printer_t *p);
+static void write_irix_state(printer_t *p);
+#endif /* __sgi */
+
+
+/*
+ * 'AddPrinter()' - Add a printer to the system.
+ */
+
+printer_t * /* O - New printer */
+AddPrinter(const char *name) /* I - Name of printer */
+{
+ printer_t *p, /* New printer */
+ *current, /* Current printer in list */
+ *prev; /* Previous printer in list */
+
+
+ /*
+ * Range check input...
+ */
+
+ LogMessage(L_DEBUG2, "AddPrinter(\"%s\")", name ? name : "(null)");
+
+ if (name == NULL)
+ return (NULL);
+
+ /*
+ * Create a new printer entity...
+ */
+
+ if ((p = calloc(1, sizeof(printer_t))) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to allocate memory for printer - %s",
+ strerror(errno));
+ return (NULL);
+ }
+
+ SetString(&p->name, name);
+ SetString(&p->info, name);
+ SetString(&p->hostname, ServerName);
+ SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName,
+ NumListeners > 0 ? ntohs(Listeners[0].address.sin_port) : ippPort(),
+ name);
+ SetStringf(&p->device_uri, "file:/dev/null");
+
+ p->state = IPP_PRINTER_STOPPED;
+ p->accepting = 0;
+ p->filetype = mimeAddType(MimeDatabase, "printer", name);
+
+ SetString(&p->job_sheets[0], "none");
+ SetString(&p->job_sheets[1], "none");
+
+ if (MaxPrinterHistory)
+ p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *));
+
+ /*
+ * Insert the printer in the printer list alphabetically...
+ */
+
+ for (prev = NULL, current = Printers;
+ current != NULL;
+ prev = current, current = current->next)
+ if (strcasecmp(p->name, current->name) < 0)
+ break;
+
+ /*
+ * Insert this printer before the current one...
+ */
+
+ if (prev == NULL)
+ Printers = p;
+ else
+ prev->next = p;
+
+ p->next = current;
+
+ /*
+ * Write a new /etc/printcap or /var/spool/lp/pstatus file.
+ */
+
+ WritePrintcap();
+
+ /*
+ * Bump the printer count and return...
+ */
+
+ NumPrinters ++;
+
+ return (p);
+}
+
+
+/*
+ * 'AddPrinterFilter()' - Add a MIME filter for a printer.
+ */
+
+void
+AddPrinterFilter(printer_t *p, /* I - Printer to add to */
+ const char *filter) /* I - Filter to add */
+{
+ int i; /* Looping var */
+ char super[MIME_MAX_SUPER], /* Super-type for filter */
+ type[MIME_MAX_TYPE], /* Type for filter */
+ program[1024]; /* Program/filter name */
+ int cost; /* Cost of filter */
+ mime_type_t **temptype; /* MIME type looping var */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (p == NULL || p->filetype == NULL || filter == NULL)
+ return;
+
+ /*
+ * Parse the filter string; it should be in the following format:
+ *
+ * super/type cost program
+ */
+
+ if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4)
+ {
+ LogMessage(L_ERROR, "AddPrinterFilter: Invalid filter string \"%s\"!",
+ filter);
+ return;
+ }
+
+ /*
+ * Add the filter to the MIME database, supporting wildcards as needed...
+ */
+
+ for (temptype = MimeDatabase->types, i = MimeDatabase->num_types;
+ i > 0;
+ i --, temptype ++)
+ if (((super[0] == '*' && strcasecmp((*temptype)->super, "printer") != 0) ||
+ strcasecmp((*temptype)->super, super) == 0) &&
+ (type[0] == '*' || strcasecmp((*temptype)->type, type) == 0))
+ {
+ LogMessage(L_DEBUG2, "Adding filter %s/%s %s/%s %d %s",
+ (*temptype)->super, (*temptype)->type,
+ p->filetype->super, p->filetype->type,
+ cost, program);
+ mimeAddFilter(MimeDatabase, *temptype, p->filetype, cost, program);
+ }
+}
+
+
+/*
+ * 'AddPrinterHistory()' - Add the current printer state to the history.
+ */
+
+void
+AddPrinterHistory(printer_t *p) /* I - Printer */
+{
+ ipp_t *history; /* History collection */
+
+
+ /*
+ * Stop early if we aren't keeping history data...
+ */
+
+ if (MaxPrinterHistory <= 0)
+ return;
+
+ /*
+ * Retire old history data as needed...
+ */
+
+ p->sequence_number ++;
+
+ if (p->num_history >= MaxPrinterHistory)
+ {
+ p->num_history --;
+ ippDelete(p->history[0]);
+ memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *));
+ }
+
+ /*
+ * Create a collection containing the current printer-state, printer-up-time,
+ * printer-state-message, and printer-state-reasons attributes.
+ */
+
+ history = ippNew();
+ ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ p->state);
+ ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
+ p->accepting);
+ ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message",
+ NULL, p->state_message);
+ if (p->num_reasons == 0)
+ ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", NULL,
+ p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
+ else
+ ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "printer-state-reasons", p->num_reasons, NULL,
+ (const char * const *)p->reasons);
+ ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-state-time", p->state_time);
+ ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "printer-state-sequence-number", p->sequence_number);
+
+ p->history[p->num_history] = history;
+ p->num_history ++;
+}
+
+
+/*
+ * 'AddPrinterUser()' - Add a user to the ACL.
+ */
+
+void
+AddPrinterUser(printer_t *p, /* I - Printer */
+ const char *username) /* I - User */
+{
+ const char **temp; /* Temporary array pointer */
+
+
+ if (!p || !username)
+ return;
+
+ if (p->num_users == 0)
+ temp = malloc(sizeof(char **));
+ else
+ temp = realloc(p->users, sizeof(char **) * (p->num_users + 1));
+
+ if (!temp)
+ return;
+
+ p->users = temp;
+ temp += p->num_users;
+
+ if ((*temp = strdup(username)) != NULL)
+ p->num_users ++;
+}
+
+
+/*
+ * 'CreateCommonData()' - Create the common printer data.
+ */
+
+void
+CreateCommonData(void)
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* Attribute data */
+ static const int nups[] = /* number-up-supported values */
+ { 1, 2, 4, 6, 9, 16 };
+ static const ipp_orient_t orients[4] =/* orientation-requested-supported values */
+ {
+ IPP_PORTRAIT,
+ IPP_LANDSCAPE,
+ IPP_REVERSE_LANDSCAPE,
+ IPP_REVERSE_PORTRAIT
+ };
+ static const char * const holds[] = /* job-hold-until-supported values */
+ {
+ "no-hold",
+ "indefinite",
+ "day-time",
+ "evening",
+ "night",
+ "second-shift",
+ "third-shift",
+ "weekend"
+ };
+ static const char * const versions[] =/* ipp-versions-supported values */
+ {
+ "1.0",
+ "1.1"
+ };
+ static const ipp_op_t ops[] = /* operations-supported values */
+ {
+ IPP_PRINT_JOB,
+ IPP_VALIDATE_JOB,
+ IPP_CREATE_JOB,
+ IPP_SEND_DOCUMENT,
+ IPP_CANCEL_JOB,
+ IPP_GET_JOB_ATTRIBUTES,
+ IPP_GET_JOBS,
+ IPP_GET_PRINTER_ATTRIBUTES,
+ IPP_HOLD_JOB,
+ IPP_RELEASE_JOB,
+ IPP_PAUSE_PRINTER,
+ IPP_RESUME_PRINTER,
+ IPP_PURGE_JOBS,
+ IPP_SET_JOB_ATTRIBUTES,
+ IPP_ENABLE_PRINTER,
+ IPP_DISABLE_PRINTER,
+ CUPS_GET_DEFAULT,
+ CUPS_GET_PRINTERS,
+ CUPS_ADD_PRINTER,
+ CUPS_DELETE_PRINTER,
+ CUPS_GET_CLASSES,
+ CUPS_ADD_CLASS,
+ CUPS_DELETE_CLASS,
+ CUPS_ACCEPT_JOBS,
+ CUPS_REJECT_JOBS,
+ CUPS_GET_DEVICES,
+ CUPS_GET_PPDS,
+ IPP_RESTART_JOB
+ };
+ static const char * const charsets[] =/* charset-supported values */
+ {
+ "us-ascii",
+ "iso-8859-1",
+ "iso-8859-2",
+ "iso-8859-3",
+ "iso-8859-4",
+ "iso-8859-5",
+ "iso-8859-6",
+ "iso-8859-7",
+ "iso-8859-8",
+ "iso-8859-9",
+ "iso-8859-10",
+ "iso-8859-13",
+ "iso-8859-14",
+ "iso-8859-15",
+ "utf-8",
+ "windows-874",
+ "windows-1250",
+ "windows-1251",
+ "windows-1252",
+ "windows-1253",
+ "windows-1254",
+ "windows-1255",
+ "windows-1256",
+ "windows-1257",
+ "windows-1258",
+ "koi8-r",
+ "koi8-u",
+ };
+ static const char * const compressions[] =
+ { /* document-compression-supported values */
+ "none"
+#ifdef HAVE_LIBZ
+ ,"gzip"
+#endif /* HAVE_LIBZ */
+ };
+ static const char * const multiple_document_handling[] =
+ { /* multiple-document-handling-supported values */
+ "separate-documents-uncollated-copies",
+ "separate-documents-collated-copies"
+ };
+
+
+ if (CommonData)
+ ippDelete(CommonData);
+
+ CommonData = ippNew();
+
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "pdl-override-supported", NULL, "not-attempted");
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
+ NULL, versions);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "operations-supported",
+ sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
+ ippAddBoolean(CommonData, IPP_TAG_PRINTER,
+ "multiple-document-jobs-supported", 1);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "multiple-operation-time-out", 60);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "multiple-document-handling-supported",
+ sizeof(multiple_document_handling) /
+ sizeof(multiple_document_handling[0]), NULL,
+ multiple_document_handling);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET,
+ "charset-configured", NULL, DefaultCharset);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET,
+ "charset-supported", sizeof(charsets) / sizeof(charsets[0]),
+ NULL, charsets);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "natural-language-configured", NULL, DefaultLanguage);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
+ "generated-natural-language-supported", NULL, DefaultLanguage);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+ "document-format-default", NULL, "application/octet-stream");
+ ippAddStrings(CommonData, IPP_TAG_PRINTER,
+ (ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
+ "document-format-supported", NumMimeTypes, NULL, MimeTypes);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "compression-supported",
+ sizeof(compressions) / sizeof(compressions[0]),
+ NULL, compressions);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-priority-supported", 100);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-priority-default", 50);
+ ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "copies-default", 1);
+ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "number-up-supported", sizeof(nups) / sizeof(nups[0]), nups);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "number-up-default", 1);
+ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "orientation-requested-supported", 4, (int *)orients);
+ ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "orientation-requested-default", IPP_PORTRAIT);
+ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "job-hold-until-supported", sizeof(holds) / sizeof(holds[0]),
+ NULL, holds);
+ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "job-hold-until-default", NULL, "no-hold");
+
+ if (NumBanners > 0)
+ {
+ /*
+ * Setup the job-sheets-supported and job-sheets-default attributes...
+ */
+
+ if (Classification && !ClassifyOverride)
+ attr = ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-supported", NULL, Classification);
+ else
+ attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-supported", NumBanners + 1, NULL, NULL);
+
+ if (attr == NULL)
+ LogMessage(L_EMERG, "SetPrinterAttrs: Unable to allocate memory for "
+ "job-sheets-supported attribute: %s!",
+ strerror(errno));
+ else if (!Classification || ClassifyOverride)
+ {
+ attr->values[0].string.text = strdup("none");
+
+ for (i = 0; i < NumBanners; i ++)
+ attr->values[i + 1].string.text = strdup(Banners[i].name);
+ }
+ }
+}
+
+
+/*
+ * 'DeleteAllPrinters()' - Delete all printers from the system.
+ */
+
+void
+DeleteAllPrinters(void)
+{
+ printer_t *p, /* Pointer to current printer/class */
+ *next; /* Pointer to next printer in list */
+
+
+ for (p = Printers; p != NULL; p = next)
+ {
+ next = p->next;
+
+ if (!(p->type & CUPS_PRINTER_CLASS))
+ DeletePrinter(p, 0);
+ }
+}
+
+
+/*
+ * 'DeletePrinter()' - Delete a printer from the system.
+ */
+
+void
+DeletePrinter(printer_t *p, /* I - Printer to delete */
+ int update) /* I - Update printers.conf? */
+{
+ int i; /* Looping var */
+ printer_t *current, /* Current printer in list */
+ *prev; /* Previous printer in list */
+#ifdef __sgi
+ char filename[1024]; /* Interface script filename */
+#endif /* __sgi */
+
+
+ DEBUG_printf(("DeletePrinter(%08x): p->name = \"%s\"...\n", p, p->name));
+
+ /*
+ * Range check input...
+ */
+
+ if (p == NULL)
+ return;
+
+ /*
+ * Find the printer in the list...
+ */
+
+ for (prev = NULL, current = Printers;
+ current != NULL;
+ prev = current, current = current->next)
+ if (p == current)
+ break;
+
+ if (current == NULL)
+ {
+ LogMessage(L_ERROR, "Tried to delete a non-existent printer %s!\n",
+ p->name);
+ return;
+ }
+
+ /*
+ * Remove the printer from the list...
+ */
+
+ if (prev == NULL)
+ Printers = p->next;
+ else
+ prev->next = p->next;
+
+ NumPrinters --;
+
+ /*
+ * Stop printing on this printer...
+ */
+
+ StopPrinter(p, update);
+
+ /*
+ * If this printer is the next for browsing, point to the next one...
+ */
+
+ if (p == BrowseNext)
+ BrowseNext = p->next;
+
+ /*
+ * Remove the dummy interface/icon/option files under IRIX...
+ */
+
+#ifdef __sgi
+ snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui",
+ p->name);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
+ unlink(filename);
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
+ unlink(filename);
+#endif /* __sgi */
+
+ /*
+ * If p is the default printer, assign the next one...
+ */
+
+ if (p == DefaultPrinter)
+ {
+ DefaultPrinter = Printers;
+
+ WritePrintcap();
+ }
+
+ /*
+ * Remove this printer from any classes...
+ */
+
+ if (!(p->type & CUPS_PRINTER_IMPLICIT))
+ DeletePrinterFromClasses(p);
+
+ /*
+ * Free all memory used by the printer...
+ */
+
+ if (p->printers != NULL)
+ free(p->printers);
+
+ if (MaxPrinterHistory)
+ {
+ for (i = 0; i < p->num_history; i ++)
+ ippDelete(p->history[i]);
+
+ free(p->history);
+ }
+
+ for (i = 0; i < p->num_reasons; i ++)
+ free(p->reasons[i]);
+
+ ippDelete(p->attrs);
+
+ DeletePrinterFilters(p);
+
+ FreePrinterUsers(p);
+ FreeQuotas(p);
+
+ ClearString(&p->uri);
+ ClearString(&p->hostname);
+ ClearString(&p->name);
+ ClearString(&p->location);
+ ClearString(&p->make_model);
+ ClearString(&p->info);
+ ClearString(&p->job_sheets[0]);
+ ClearString(&p->job_sheets[1]);
+ ClearString(&p->device_uri);
+
+ free(p);
+
+ /*
+ * Write a new /etc/printcap file...
+ */
+
+ WritePrintcap();
+}
+
+
+/*
+ * 'DeletePrinterFilters()' - Delete all MIME filters for a printer.
+ */
+
+void
+DeletePrinterFilters(printer_t *p) /* I - Printer to remove from */
+{
+ int i; /* Looping var */
+ mime_filter_t *filter; /* MIME filter looping var */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (p == NULL)
+ return;
+
+ /*
+ * Remove all filters from the MIME database that have a destination
+ * type == printer...
+ */
+
+ for (filter = MimeDatabase->filters, i = MimeDatabase->num_filters;
+ i > 0;
+ i --, filter ++)
+ if (filter->dst == p->filetype)
+ {
+ /*
+ * Delete the current filter...
+ */
+
+ MimeDatabase->num_filters --;
+
+ if (i > 1)
+ memmove(filter, filter + 1, sizeof(mime_filter_t) * (i - 1));
+
+ filter --;
+ }
+}
+
+
+/*
+ * 'FindDest()' - Find a destination in the list.
+ */
+
+printer_t * /* O - Destination in list */
+FindDest(const char *name) /* I - Name of printer or class to find */
+{
+ printer_t *p; /* Current destination */
+ int diff; /* Difference */
+
+
+ for (p = Printers; p != NULL; p = p->next)
+ if ((diff = strcasecmp(name, p->name)) == 0)/* name == p->name */
+ return (p);
+ else if (diff < 0) /* name < p->name */
+ return (NULL);
+
+ return (NULL);
+}
+
+
+/*
+ * 'FindPrinter()' - Find a printer in the list.
+ */
+
+printer_t * /* O - Printer in list */
+FindPrinter(const char *name) /* I - Name of printer to find */
+{
+ printer_t *p; /* Current printer */
+ int diff; /* Difference */
+
+
+ for (p = Printers; p != NULL; p = p->next)
+ if ((diff = strcasecmp(name, p->name)) == 0 &&
+ !(p->type & CUPS_PRINTER_CLASS)) /* name == p->name */
+ return (p);
+ else if (diff < 0) /* name < p->name */
+ return (NULL);
+
+ return (NULL);
+}
+
+
+/*
+ * 'FreePrinterUsers()' - Free allow/deny users.
+ */
+
+void
+FreePrinterUsers(printer_t *p) /* I - Printer */
+{
+ int i; /* Looping var */
+
+
+ if (!p || !p->num_users)
+ return;
+
+ for (i = 0; i < p->num_users; i ++)
+ free((void *)p->users[i]);
+
+ free(p->users);
+
+ p->num_users = 0;
+ p->users = NULL;
+}
+
+
+/*
+ * 'LoadAllPrinters()' - Load printers from the printers.conf file.
+ */
+
+void
+LoadAllPrinters(void)
+{
+ cups_file_t *fp; /* printers.conf file */
+ int linenum; /* Current line number */
+ int len; /* Length of line */
+ char line[1024], /* Line from file */
+ name[256], /* Parameter name */
+ *nameptr, /* Pointer into name */
+ *value, /* Pointer to value */
+ *valueptr; /* Pointer into value */
+ printer_t *p; /* Current printer */
+
+
+ /*
+ * Open the printers.conf file...
+ */
+
+ snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot);
+ if ((fp = cupsFileOpen(line, "r")) == NULL)
+ {
+ LogMessage(L_ERROR, "LoadAllPrinters: Unable to open %s - %s", line,
+ strerror(errno));
+ return;
+ }
+
+ /*
+ * Read printer configurations until we hit EOF...
+ */
+
+ linenum = 0;
+ p = NULL;
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ linenum ++;
+
+ /*
+ * Skip comment lines...
+ */
+
+ if (line[0] == '#')
+ continue;
+
+ /*
+ * Strip trailing whitespace, if any...
+ */
+
+ len = strlen(line);
+
+ while (len > 0 && isspace(line[len - 1] & 255))
+ {
+ len --;
+ line[len] = '\0';
+ }
+
+ /*
+ * Extract the name from the beginning of the line...
+ */
+
+ for (value = line; isspace(*value & 255); value ++);
+
+ for (nameptr = name; *value != '\0' && !isspace(*value & 255) &&
+ nameptr < (name + sizeof(name) - 1);)
+ *nameptr++ = *value++;
+ *nameptr = '\0';
+
+ while (isspace(*value & 255))
+ value ++;
+
+ if (name[0] == '\0')
+ continue;
+
+ /*
+ * Decode the directive...
+ */
+
+ if (strcmp(name, "<Printer") == 0 ||
+ strcmp(name, "<DefaultPrinter") == 0)
+ {
+ /*
+ * <Printer name> or <DefaultPrinter name>
+ */
+
+ if (line[len - 1] == '>' && p == NULL)
+ {
+ /*
+ * Add the printer and a base file type...
+ */
+
+ line[len - 1] = '\0';
+
+ LogMessage(L_DEBUG, "LoadAllPrinters: Loading printer %s...", value);
+
+ p = AddPrinter(value);
+ p->accepting = 1;
+ p->state = IPP_PRINTER_IDLE;
+
+ /*
+ * Set the default printer as needed...
+ */
+
+ if (strcmp(name, "<DefaultPrinter") == 0)
+ DefaultPrinter = p;
+ }
+ else
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
+ linenum);
+ return;
+ }
+ }
+ else if (strcmp(name, "</Printer>") == 0)
+ {
+ if (p != NULL)
+ {
+ SetPrinterAttrs(p);
+ AddPrinterHistory(p);
+ p = NULL;
+ }
+ else
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
+ linenum);
+ return;
+ }
+ }
+ else if (p == NULL)
+ {
+ LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
+ linenum);
+ return;
+ }
+ else if (strcmp(name, "Info") == 0)
+ SetString(&p->info, value);
+ else if (strcmp(name, "Location") == 0)
+ SetString(&p->location, value);
+ else if (strcmp(name, "DeviceURI") == 0)
+ SetString(&p->device_uri, value);
+ else if (strcmp(name, "State") == 0)
+ {
+ /*
+ * Set the initial queue state...
+ */
+
+ if (strcasecmp(value, "idle") == 0)
+ p->state = IPP_PRINTER_IDLE;
+ else if (strcasecmp(value, "stopped") == 0)
+ p->state = IPP_PRINTER_STOPPED;
+ }
+ else if (strcmp(name, "StateMessage") == 0)
+ {
+ /*
+ * Set the initial queue state message...
+ */
+
+ while (isspace(*value & 255))
+ value ++;
+
+ strlcpy(p->state_message, value, sizeof(p->state_message));
+ }
+ else if (strcmp(name, "Accepting") == 0)
+ {
+ /*
+ * Set the initial accepting state...
+ */
+
+ if (strcasecmp(value, "yes") == 0)
+ p->accepting = 1;
+ else
+ p->accepting = 0;
+ }
+ else if (strcmp(name, "JobSheets") == 0)
+ {
+ /*
+ * Set the initial job sheets...
+ */
+
+ for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (*valueptr)
+ *valueptr++ = '\0';
+
+ SetString(&p->job_sheets[0], value);
+
+ while (isspace(*valueptr & 255))
+ valueptr ++;
+
+ if (*valueptr)
+ {
+ for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+ if (*valueptr)
+ *valueptr++ = '\0';
+
+ SetString(&p->job_sheets[1], value);
+ }
+ }
+ else if (strcmp(name, "AllowUser") == 0)
+ {
+ p->deny_users = 0;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "DenyUser") == 0)
+ {
+ p->deny_users = 1;
+ AddPrinterUser(p, value);
+ }
+ else if (strcmp(name, "QuotaPeriod") == 0)
+ p->quota_period = atoi(value);
+ else if (strcmp(name, "PageLimit") == 0)
+ p->page_limit = atoi(value);
+ else if (strcmp(name, "KLimit") == 0)
+ p->k_limit = atoi(value);
+ else
+ {
+ /*
+ * Something else we don't understand...
+ */
+
+ LogMessage(L_ERROR, "Unknown configuration directive %s on line %d of printers.conf.",
+ name, linenum);
+ }
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'SaveAllPrinters()' - Save all printer definitions to the printers.conf
+ * file.
+ */
+
+void
+SaveAllPrinters(void)
+{
+ int i; /* Looping var */
+ cups_file_t *fp; /* printers.conf file */
+ char temp[1024]; /* Temporary string */
+ char backup[1024]; /* printers.conf.O file */
+ printer_t *printer; /* Current printer class */
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
+
+
+ /*
+ * Create the printers.conf file...
+ */
+
+ snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot);
+ snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot);
+
+ if (rename(temp, backup))
+ LogMessage(L_ERROR, "Unable to backup printers.conf - %s", strerror(errno));
+
+ if ((fp = cupsFileOpen(temp, "w")) == NULL)
+ {
+ LogMessage(L_ERROR, "Unable to save printers.conf - %s", strerror(errno));
+
+ if (rename(backup, temp))
+ LogMessage(L_ERROR, "Unable to restore printers.conf - %s", strerror(errno));
+ return;
+ }
+ else
+ LogMessage(L_INFO, "Saving printers.conf...");
+
+ /*
+ * Restrict access to the file...
+ */
+
+ fchown(cupsFileNumber(fp), getuid(), Group);
+ fchmod(cupsFileNumber(fp), ConfigFilePerm);
+
+ /*
+ * Write a small header to the file...
+ */
+
+ curtime = time(NULL);
+ curdate = localtime(&curtime);
+ strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate);
+
+ cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n");
+ cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
+
+ /*
+ * Write each local printer known to the system...
+ */
+
+ for (printer = Printers; printer != NULL; printer = printer->next)
+ {
+ /*
+ * Skip remote destinations and printer classes...
+ */
+
+ if ((printer->type & CUPS_PRINTER_REMOTE) ||
+ (printer->type & CUPS_PRINTER_CLASS) ||
+ (printer->type & CUPS_PRINTER_IMPLICIT))
+ continue;
+
+ /*
+ * Write printers as needed...
+ */
+
+ if (printer == DefaultPrinter)
+ cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name);
+ else
+ cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
+
+ if (printer->info)
+ cupsFilePrintf(fp, "Info %s\n", printer->info);
+
+ if (printer->location)
+ cupsFilePrintf(fp, "Location %s\n", printer->location);
+
+ if (printer->device_uri)
+ cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
+
+ if (printer->state == IPP_PRINTER_STOPPED)
+ {
+ cupsFilePuts(fp, "State Stopped\n");
+ cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message);
+ }
+ else
+ cupsFilePuts(fp, "State Idle\n");
+
+ if (printer->accepting)
+ cupsFilePuts(fp, "Accepting Yes\n");
+ else
+ cupsFilePuts(fp, "Accepting No\n");
+
+ cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
+ printer->job_sheets[1]);
+
+ cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period);
+ cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit);
+ cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit);
+
+ for (i = 0; i < printer->num_users; i ++)
+ cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
+ printer->users[i]);
+
+ cupsFilePuts(fp, "</Printer>\n");
+
+#ifdef __sgi
+ /*
+ * Make IRIX desktop & printer status happy
+ */
+
+ write_irix_state(printer);
+#endif /* __sgi */
+ }
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'SetPrinterAttrs()' - Set printer attributes based upon the PPD file.
+ */
+
+void
+SetPrinterAttrs(printer_t *p) /* I - Printer to setup */
+{
+ char uri[HTTP_MAX_URI]; /* URI for printer */
+ char resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int i; /* Looping var */
+ char filename[1024]; /* Name of PPD file */
+ int num_media; /* Number of media options */
+ location_t *auth; /* Pointer to authentication element */
+ const char *auth_supported; /* Authentication supported */
+ cups_ptype_t printer_type; /* Printer type data */
+ ppd_file_t *ppd; /* PPD file data */
+ ppd_option_t *input_slot, /* InputSlot options */
+ *media_type, /* MediaType options */
+ *page_size, /* PageSize options */
+ *output_bin, /* OutputBin options */
+ *media_quality; /* EFMediaQualityMode options */
+ ppd_attr_t *ppdattr; /* PPD attribute */
+ ipp_attribute_t *attr; /* Attribute data */
+ ipp_value_t *val; /* Attribute value */
+ int num_finishings;
+ ipp_finish_t finishings[5]; /* finishings-supported values */
+ static const char * const sides[3] = /* sides-supported values */
+ {
+ "one",
+ "two-long-edge",
+ "two-short-edge"
+ };
+
+
+ DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p->name,
+ p->type));
+
+ /*
+ * Make sure that we have the common attributes defined...
+ */
+
+ if (!CommonData)
+ CreateCommonData();
+
+ /*
+ * Clear out old filters and add a filter from application/vnd.cups-raw to
+ * printer/name to handle "raw" printing by users.
+ */
+
+ DeletePrinterFilters(p);
+ AddPrinterFilter(p, "application/vnd.cups-raw 0 -");
+
+ /*
+ * Figure out the authentication that is required for the printer.
+ */
+
+ auth_supported = "requesting-user-name";
+ if (!(p->type & CUPS_PRINTER_REMOTE))
+ {
+ if (p->type & CUPS_PRINTER_CLASS)
+ snprintf(resource, sizeof(resource), "/classes/%s", p->name);
+ else
+ snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+
+ if ((auth = FindBest(resource, HTTP_POST)) != NULL)
+ {
+ if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
+ auth_supported = "basic";
+ else if (auth->type == AUTH_DIGEST)
+ auth_supported = "digest";
+ }
+ }
+
+ /*
+ * Create the required IPP attributes for a printer...
+ */
+
+ if (p->attrs)
+ ippDelete(p->attrs);
+
+ p->attrs = ippNew();
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported",
+ NULL, p->uri);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "uri-authentication-supported", NULL, auth_supported);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "uri-security-supported", NULL, "none");
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL,
+ p->name);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
+ NULL, p->location ? p->location : "");
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
+ NULL, p->info ? p->info : "");
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
+ NULL, p->uri);
+
+ if (p->num_users)
+ {
+ if (p->deny_users)
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-denied", p->num_users, NULL,
+ p->users);
+ else
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-allowed", p->num_users, NULL,
+ p->users);
+ }
+
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-quota-period", p->quota_period);
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-k-limit", p->k_limit);
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "job-page-limit", p->page_limit);
+
+ if (NumBanners > 0 && !(p->type & CUPS_PRINTER_REMOTE))
+ {
+ /*
+ * Setup the job-sheets-default attribute...
+ */
+
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-default", 2, NULL, NULL);
+
+ if (attr != NULL)
+ {
+ attr->values[0].string.text = strdup(Classification ?
+ Classification : p->job_sheets[0]);
+ attr->values[1].string.text = strdup(Classification ?
+ Classification : p->job_sheets[1]);
+ }
+ }
+
+ printer_type = p->type;
+
+ p->raw = 0;
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ {
+ /*
+ * Tell the client this is a remote printer of some type...
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, p->make_model);
+
+ p->raw = 1;
+ }
+ else
+ {
+ /*
+ * Assign additional attributes depending on whether this is a printer
+ * or class...
+ */
+
+ p->type &= ~CUPS_PRINTER_OPTIONS;
+
+ if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ {
+ /*
+ * Add class-specific attributes...
+ */
+
+ if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, p->printers[0]->make_model);
+ else
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, "Local Printer Class");
+
+ if (p->num_printers > 0)
+ {
+ /*
+ * Add a list of member URIs and names...
+ */
+
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
+ "member-uris", p->num_printers, NULL, NULL);
+ p->type |= CUPS_PRINTER_OPTIONS;
+
+ for (i = 0; i < p->num_printers; i ++)
+ {
+ if (attr != NULL)
+ attr->values[i].string.text = strdup(p->printers[i]->uri);
+
+ p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
+ }
+
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "member-names", p->num_printers, NULL, NULL);
+
+ if (attr != NULL)
+ {
+ for (i = 0; i < p->num_printers; i ++)
+ attr->values[i].string.text = strdup(p->printers[i]->name);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Add printer-specific attributes... Start by sanitizing the device
+ * URI so it doesn't have a username or password in it...
+ */
+
+ if (!p->device_uri)
+ strcpy(uri, "file:/dev/null");
+ else if (strstr(p->device_uri, "://") != NULL)
+ {
+ /*
+ * http://..., ipp://..., etc.
+ */
+
+ cupsdSanitizeURI(p->device_uri, uri, sizeof(uri));
+ }
+ else
+ {
+ /*
+ * file:..., serial:..., etc.
+ */
+
+ strlcpy(uri, p->device_uri, sizeof(uri));
+ }
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
+ uri);
+
+ /*
+ * Assign additional attributes from the PPD file (if any)...
+ */
+
+ p->type |= CUPS_PRINTER_BW;
+ finishings[0] = IPP_FINISHINGS_NONE;
+ num_finishings = 1;
+
+ snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
+ p->name);
+
+ if ((ppd = ppdOpenFile(filename)) != NULL)
+ {
+ /*
+ * Add make/model and other various attributes...
+ */
+
+ if (ppd->color_device)
+ p->type |= CUPS_PRINTER_COLOR;
+ if (ppd->variable_sizes)
+ p->type |= CUPS_PRINTER_VARIABLE;
+ if (!ppd->manual_copies)
+ p->type |= CUPS_PRINTER_COPIES;
+ if ((ppdattr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL)
+ if (ppdattr->value && !strcasecmp(ppdattr->value, "true"))
+ p->type |= CUPS_PRINTER_FAX;
+
+ ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported",
+ ppd->color_device);
+ if (ppd->throughput)
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+ "pages-per-minute", ppd->throughput);
+
+ if (ppd->nickname)
+ SetString(&p->make_model, ppd->nickname);
+ else if (ppd->modelname)
+ SetString(&p->make_model, ppd->modelname);
+ else
+ SetString(&p->make_model, "Bad PPD File");
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, p->make_model);
+
+ /*
+ * Add media options from the PPD file...
+ */
+
+ if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL)
+ num_media = input_slot->num_choices;
+ else
+ num_media = 0;
+
+ if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
+ num_media += media_type->num_choices;
+
+ if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL)
+ num_media += page_size->num_choices;
+
+ if ((media_quality = ppdFindOption(ppd, "EFMediaQualityMode")) != NULL)
+ num_media += media_quality->num_choices;
+
+ if (num_media == 0)
+ {
+ LogMessage(L_CRIT, "SetPrinterAttrs: The PPD file for printer %s "
+ "contains no media options and is therefore "
+ "invalid!", p->name);
+ }
+ else
+ {
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "media-supported", num_media, NULL, NULL);
+ if (attr != NULL)
+ {
+ val = attr->values;
+
+ if (input_slot != NULL)
+ for (i = 0; i < input_slot->num_choices; i ++, val ++)
+ val->string.text = strdup(input_slot->choices[i].choice);
+
+ if (media_type != NULL)
+ for (i = 0; i < media_type->num_choices; i ++, val ++)
+ val->string.text = strdup(media_type->choices[i].choice);
+
+ if (media_quality != NULL)
+ for (i = 0; i < media_quality->num_choices; i ++, val ++)
+ val->string.text = strdup(media_quality->choices[i].choice);
+
+ if (page_size != NULL)
+ {
+ for (i = 0; i < page_size->num_choices; i ++, val ++)
+ val->string.text = strdup(page_size->choices[i].choice);
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, page_size->defchoice);
+ }
+ else if (input_slot != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, input_slot->defchoice);
+ else if (media_type != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, media_type->defchoice);
+ else if (media_quality != NULL)
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, media_quality->defchoice);
+ else
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
+ NULL, "none");
+ }
+ }
+
+ /*
+ * Output bin...
+ */
+
+ if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
+ {
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
+ "output-bin-supported", output_bin->num_choices,
+ NULL, NULL);
+
+ if (attr != NULL)
+ {
+ for (i = 0, val = attr->values;
+ i < output_bin->num_choices;
+ i ++, val ++)
+ val->string.text = strdup(output_bin->choices[i].choice);
+ }
+ }
+
+ /*
+ * Duplexing, etc...
+ */
+
+ if (ppdFindOption(ppd, "Duplex") != NULL)
+ {
+ p->type |= CUPS_PRINTER_DUPLEX;
+
+ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported",
+ 3, NULL, sides);
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default",
+ NULL, "one");
+ }
+
+ if (ppdFindOption(ppd, "Collate") != NULL)
+ p->type |= CUPS_PRINTER_COLLATE;
+
+ if (ppdFindOption(ppd, "StapleLocation") != NULL)
+ {
+ p->type |= CUPS_PRINTER_STAPLE;
+ finishings[num_finishings++] = IPP_FINISHINGS_STAPLE;
+ }
+
+ if (ppdFindOption(ppd, "BindEdge") != NULL)
+ {
+ p->type |= CUPS_PRINTER_BIND;
+ finishings[num_finishings++] = IPP_FINISHINGS_BIND;
+ }
+
+ for (i = 0; i < ppd->num_sizes; i ++)
+ if (ppd->sizes[i].length > 1728)
+ p->type |= CUPS_PRINTER_LARGE;
+ else if (ppd->sizes[i].length > 1008)
+ p->type |= CUPS_PRINTER_MEDIUM;
+ else
+ p->type |= CUPS_PRINTER_SMALL;
+
+ /*
+ * Add any filters in the PPD file...
+ */
+
+ DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters));
+ for (i = 0; i < ppd->num_filters; i ++)
+ {
+ DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
+ AddPrinterFilter(p, ppd->filters[i]);
+ }
+
+ if (ppd->num_filters == 0)
+ AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
+
+ ppdClose(ppd);
+
+ printer_type = p->type;
+ }
+ else if (access(filename, 0) == 0)
+ {
+ int pline; /* PPD line number */
+ ppd_status_t pstatus; /* PPD load status */
+
+
+ pstatus = ppdLastError(&pline);
+
+ LogMessage(L_ERROR, "PPD file for %s cannot be loaded!", p->name);
+
+ if (pstatus <= PPD_ALLOC_ERROR)
+ LogMessage(L_ERROR, "%s", strerror(errno));
+ else
+ LogMessage(L_ERROR, "%s on line %d.", ppdErrorString(pstatus),
+ pline);
+
+ LogMessage(L_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.",
+ filename);
+
+ AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
+ }
+ else
+ {
+ /*
+ * If we have an interface script, add a filter entry for it...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
+ p->name);
+ if (access(filename, X_OK) == 0)
+ {
+ /*
+ * Yes, we have a System V style interface script; use it!
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, "Local System V Printer");
+
+ snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
+ ServerRoot, p->name);
+ AddPrinterFilter(p, filename);
+ }
+ else if (p->device_uri &&
+ strncmp(p->device_uri, "ipp://", 6) == 0 &&
+ (strstr(p->device_uri, "/printers/") != NULL ||
+ strstr(p->device_uri, "/classes/") != NULL))
+ {
+ /*
+ * Tell the client this is really a hard-wired remote printer.
+ */
+
+ printer_type |= CUPS_PRINTER_REMOTE;
+
+ /*
+ * Reset the printer-uri-supported attribute to point at the
+ * remote printer...
+ */
+
+ attr = ippFindAttribute(p->attrs, "printer-uri-supported", IPP_TAG_URI);
+ free(attr->values[0].string.text);
+ attr->values[0].string.text = strdup(p->device_uri);
+
+ /*
+ * Then set the make-and-model accordingly...
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, "Remote Printer");
+
+ /*
+ * Print all files directly...
+ */
+
+ p->raw = 1;
+ }
+ else
+ {
+ /*
+ * Otherwise we have neither - treat this as a "dumb" printer
+ * with no PPD file...
+ */
+
+ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+ "printer-make-and-model", NULL, "Local Raw Printer");
+
+ p->raw = 1;
+ }
+ }
+
+ ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "finishings-supported", num_finishings, (int *)finishings);
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
+ "finishings-default", IPP_FINISHINGS_NONE);
+ }
+ }
+
+ /*
+ * Add the CUPS-specific printer-type attribute...
+ */
+
+ ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type",
+ printer_type);
+
+ DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
+ p->type));
+
+#ifdef __sgi
+ /*
+ * Write the IRIX printer config and status files...
+ */
+
+ write_irix_config(p);
+ write_irix_state(p);
+#endif /* __sgi */
+}
+
+
+/*
+ * 'SetPrinterReasons()' - Set/update the reasons strings.
+ */
+
+void
+SetPrinterReasons(printer_t *p, /* I - Printer */
+ const char *s) /* I - Reasons strings */
+{
+ int i; /* Looping var */
+ const char *sptr; /* Pointer into reasons */
+ char reason[255], /* Reason string */
+ *rptr; /* Pointer into reason */
+
+
+ if (s[0] == '-' || s[0] == '+')
+ {
+ /*
+ * Add/remove reasons...
+ */
+
+ sptr = s + 1;
+ }
+ else
+ {
+ /*
+ * Replace reasons...
+ */
+
+ sptr = s;
+
+ for (i = 0; i < p->num_reasons; i ++)
+ free(p->reasons[i]);
+
+ p->num_reasons = 0;
+ }
+
+ /*
+ * Loop through all of the reasons...
+ */
+
+ while (*sptr)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*sptr & 255) || *sptr == ',')
+ sptr ++;
+
+ for (rptr = reason; *sptr && !isspace(*sptr & 255) && *sptr != ','; sptr ++)
+ if (rptr < (reason + sizeof(reason) - 1))
+ *rptr++ = *sptr;
+
+ if (rptr == reason)
+ break;
+
+ *rptr = '\0';
+
+ if (s[0] == '-')
+ {
+ /*
+ * Remove reason...
+ */
+
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcasecmp(reason, p->reasons[i]))
+ {
+ /*
+ * Found a match, so remove it...
+ */
+
+ p->num_reasons --;
+ free(p->reasons[i]);
+
+ if (i < p->num_reasons)
+ memmove(p->reasons + i, p->reasons + i + 1,
+ (p->num_reasons - i) * sizeof(char *));
+
+ i --;
+ }
+ }
+ else if (p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+ {
+ /*
+ * Add reason...
+ */
+
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcasecmp(reason, p->reasons[i]))
+ break;
+
+ if (i >= p->num_reasons)
+ {
+ p->reasons[i] = strdup(reason);
+ p->num_reasons ++;
+ }
+ }
+ }
+}
+
+
+/*
+ * 'SetPrinterState()' - Update the current state of a printer.
+ */
+
+void
+SetPrinterState(printer_t *p, /* I - Printer to change */
+ ipp_pstate_t s, /* I - New state */
+ int update) /* I - Update printers.conf? */
+{
+ ipp_pstate_t old_state; /* Old printer state */
+
+
+ /*
+ * Can't set status of remote printers...
+ */
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ return;
+
+ /*
+ * Set the new state...
+ */
+
+ old_state = p->state;
+ p->state = s;
+
+ if (old_state != s)
+ {
+ /*
+ * Let the browse code know this needs to be updated...
+ */
+
+ BrowseNext = p;
+ p->state_time = time(NULL);
+ p->browse_time = 0;
+
+#ifdef __sgi
+ write_irix_state(p);
+#endif /* __sgi */
+ }
+
+ AddPrinterHistory(p);
+
+ /*
+ * Save the printer configuration if a printer goes from idle or processing
+ * to stopped (or visa-versa)...
+ */
+
+ if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED) &&
+ update)
+ {
+ if (p->type & CUPS_PRINTER_CLASS)
+ SaveAllClasses();
+ else
+ SaveAllPrinters();
+ }
+}
+
+
+/*
+ * 'SortPrinters()' - Sort the printer list when a printer name is changed.
+ */
+
+void
+SortPrinters(void)
+{
+ printer_t *current, /* Current printer */
+ *prev, /* Previous printer */
+ *next; /* Next printer */
+ int did_swap; /* Non-zero if we did a swap */
+
+
+ do
+ {
+ for (did_swap = 0, current = Printers, prev = NULL; current != NULL;)
+ if (current->next == NULL)
+ break;
+ else if (strcasecmp(current->name, current->next->name) > 0)
+ {
+ DEBUG_printf(("Swapping %s and %s...\n", current->name,
+ current->next->name));
+
+ /*
+ * Need to swap these two printers...
+ */
+
+ did_swap = 1;
+
+ if (prev == NULL)
+ Printers = current->next;
+ else
+ prev->next = current->next;
+
+ /*
+ * Yes, we can all get a headache from the next bunch of pointer
+ * swapping...
+ */
+
+ next = current->next;
+ current->next = next->next;
+ next->next = current;
+ prev = next;
+ }
+ else
+ {
+ prev = current;
+ current = current->next;
+ }
+ }
+ while (did_swap);
+}
+
+
+/*
+ * 'StopPrinter()' - Stop a printer from printing any jobs...
+ */
+
+void
+StopPrinter(printer_t *p, /* I - Printer to stop */
+ int update) /* I - Update printers.conf? */
+{
+ job_t *job; /* Active print job */
+
+
+ /*
+ * Set the printer state...
+ */
+
+ SetPrinterState(p, IPP_PRINTER_STOPPED, update);
+
+ /*
+ * See if we have a job printing on this printer...
+ */
+
+ if (p->job)
+ {
+ /*
+ * Get pointer to job...
+ */
+
+ job = (job_t *)p->job;
+
+ /*
+ * Stop it...
+ */
+
+ StopJob(job->id, 0);
+
+ /*
+ * Reset the state to pending...
+ */
+
+ job->state->values[0].integer = IPP_JOB_PENDING;
+
+ SaveJob(job->id);
+ }
+}
+
+
+/*
+ * 'ValidateDest()' - Validate a printer/class destination.
+ */
+
+const char * /* O - Printer or class name */
+ValidateDest(const char *hostname, /* I - Host name */
+ const char *resource, /* I - Resource name */
+ cups_ptype_t *dtype) /* O - Type (printer or class) */
+{
+ printer_t *p; /* Current printer */
+ char localname[1024], /* Localized hostname */
+ *lptr, /* Pointer into localized hostname */
+ *sptr; /* Pointer into server name */
+
+
+ DEBUG_printf(("ValidateDest(\"%s\", \"%s\", %p)\n", hostname, resource, dtype));
+
+ /*
+ * See if the resource is a class or printer...
+ */
+
+ if (strncmp(resource, "/classes/", 9) == 0)
+ {
+ /*
+ * Class...
+ */
+
+ resource += 9;
+ }
+ else if (strncmp(resource, "/printers/", 10) == 0)
+ {
+ /*
+ * Printer...
+ */
+
+ resource += 10;
+ }
+ else
+ {
+ /*
+ * Bad resource name...
+ */
+
+ return (NULL);
+ }
+
+ /*
+ * See if the printer or class name exists...
+ */
+
+ if ((p = FindPrinter(resource)) == NULL)
+ p = FindClass(resource);
+
+ if (p == NULL && strchr(resource, '@') == NULL)
+ return (NULL);
+ else if (p != NULL)
+ {
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
+ return (p->name);
+ }
+
+ /*
+ * Change localhost to the server name...
+ */
+
+ if (strcasecmp(hostname, "localhost") == 0)
+ hostname = ServerName;
+
+ strlcpy(localname, hostname, sizeof(localname));
+
+ if (strcasecmp(hostname, ServerName) != 0)
+ {
+ /*
+ * Localize the hostname...
+ */
+
+ lptr = strchr(localname, '.');
+ sptr = strchr(ServerName, '.');
+
+ if (sptr != NULL && lptr != NULL)
+ {
+ /*
+ * Strip the common domain name components...
+ */
+
+ while (lptr != NULL)
+ {
+ if (strcasecmp(lptr, sptr) == 0)
+ {
+ *lptr = '\0';
+ break;
+ }
+ else
+ lptr = strchr(lptr + 1, '.');
+ }
+ }
+ }
+
+ DEBUG_printf(("localized hostname is \"%s\"...\n", localname));
+
+ /*
+ * Find a matching printer or class...
+ */
+
+ for (p = Printers; p != NULL; p = p->next)
+ if (strcasecmp(p->hostname, localname) == 0 &&
+ strcasecmp(p->name, resource) == 0)
+ {
+ *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_REMOTE);
+ return (p->name);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * 'WritePrintcap()' - Write a pseudo-printcap file for older applications
+ * that need it...
+ */
+
+void
+WritePrintcap(void)
+{
+ cups_file_t *fp; /* printcap file */
+ printer_t *p; /* Current printer */
+
+
+#ifdef __sgi
+ /*
+ * Update the IRIX printer state for the default printer; if
+ * no printers remain, then the default printer file will be
+ * removed...
+ */
+
+ write_irix_state(DefaultPrinter);
+#endif /* __sgi */
+
+ /*
+ * See if we have a printcap file; if not, don't bother writing it.
+ */
+
+ if (!Printcap[0])
+ return;
+
+ /*
+ * Open the printcap file...
+ */
+
+ if ((fp = cupsFileOpen(Printcap, "w")) == NULL)
+ return;
+
+ /*
+ * Put a comment header at the top so that users will know where the
+ * data has come from...
+ */
+
+ cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n");
+ cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n",
+ ServerRoot);
+ cupsFilePuts(fp, "# will be lost.\n");
+
+ /*
+ * Write a new printcap with the current list of printers.
+ */
+
+ switch (PrintcapFormat)
+ {
+ case PRINTCAP_BSD:
+ /*
+ * Each printer is put in the file as:
+ *
+ * Printer1:
+ * Printer2:
+ * Printer3:
+ * ...
+ * PrinterN:
+ */
+
+ if (DefaultPrinter)
+ cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
+ DefaultPrinter->info, ServerName, DefaultPrinter->name);
+
+ for (p = Printers; p != NULL; p = p->next)
+ if (p != DefaultPrinter)
+ cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
+ ServerName, p->name);
+ break;
+
+ case PRINTCAP_SOLARIS:
+ /*
+ * Each printer is put in the file as:
+ *
+ * _all:all=Printer1,Printer2,Printer3,...,PrinterN
+ * _default:use=DefaultPrinter
+ * Printer1:\
+ * :bsdaddr=ServerName,Printer1:\
+ * :description=Description:
+ * Printer2:
+ * :bsdaddr=ServerName,Printer2:\
+ * :description=Description:
+ * Printer3:
+ * :bsdaddr=ServerName,Printer3:\
+ * :description=Description:
+ * ...
+ * PrinterN:
+ * :bsdaddr=ServerName,PrinterN:\
+ * :description=Description:
+ */
+
+ cupsFilePuts(fp, "_all:all=");
+ for (p = Printers; p != NULL; p = p->next)
+ cupsFilePrintf(fp, "%s%c", p->name, p->next ? ',' : '\n');
+
+ if (DefaultPrinter)
+ cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name);
+
+ for (p = Printers; p != NULL; p = p->next)
+ cupsFilePrintf(fp, "%s:\\\n"
+ "\t:bsdaddr=%s,%s:\\\n"
+ "\t:description=%s:\n",
+ p->name, ServerName, p->name, p->info ? p->info : "");
+ break;
+ }
+
+ /*
+ * Close the file...
+ */
+
+ cupsFileClose(fp);
+}
+
+
+/*
+ * 'cupsdSanitizeURI()' - Sanitize a device URI...
+ */
+
+char * /* O - New device URI */
+cupsdSanitizeURI(const char *uri, /* I - Original device URI */
+ char *buffer, /* O - New device URI */
+ int buflen) /* I - Size of new device URI buffer */
+{
+ char *start, /* Start of data after scheme */
+ *slash, /* First slash after scheme:// */
+ *ptr; /* Pointer into user@host:port part */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!uri || !buffer || buflen < 2)
+ return (NULL);
+
+ /*
+ * Copy the device URI to the new buffer...
+ */
+
+ strlcpy(buffer, uri, buflen);
+
+ /*
+ * Find the end of the scheme:// part...
+ */
+
+ if ((ptr = strchr(buffer, ':')) == NULL)
+ return (buffer); /* No scheme: part... */
+
+ for (start = ptr + 1; *start; start ++)
+ if (*start != '/')
+ break;
+
+ /*
+ * Find the next slash (/) in the URI...
+ */
+
+ if ((slash = strchr(start, '/')) == NULL)
+ slash = start + strlen(start); /* No slash, point to the end */
+
+ /*
+ * Check for an @ sign before the slash...
+ */
+
+ if ((ptr = strchr(start, '@')) != NULL && ptr < slash)
+ {
+ /*
+ * Found an @ sign and it is before the resource part, so we have
+ * an authentication string. Copy the remaining URI over the
+ * authentication string...
+ */
+
+ cups_strcpy(start, ptr + 1);
+ }
+
+ /*
+ * Return the new device URI...
+ */
+
+ return (buffer);
+}
+
+
+#ifdef __sgi
+/*
+ * 'write_irix_config()' - Update the config files used by the IRIX
+ * desktop tools.
+ */
+
+static void
+write_irix_config(printer_t *p) /* I - Printer to update */
+{
+ char filename[1024]; /* Interface script filename */
+ cups_file_t *fp; /* Interface script file */
+ ipp_attribute_t *attr; /* Attribute value */
+
+
+ /*
+ * Add dummy interface and GUI scripts to fool SGI's "challenged" printing
+ * tools. First the interface script that tells the tools what kind of
+ * printer we have...
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePuts(fp, "#!/bin/sh\n");
+
+ if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
+ IPP_TAG_TEXT)) != NULL)
+ cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
+ else if (p->type & CUPS_PRINTER_CLASS)
+ cupsFilePuts(fp, "NAME=\"Printer Class\"\n");
+ else
+ cupsFilePuts(fp, "NAME=\"Remote Destination\"\n");
+
+ if (p->type & CUPS_PRINTER_COLOR)
+ cupsFilePuts(fp, "TYPE=ColorPostScript\n");
+ else
+ cupsFilePuts(fp, "TYPE=MonoPostScript\n");
+
+ cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName);
+ cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name);
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0755);
+ chown(filename, User, Group);
+ }
+
+ /*
+ * Then the member file that tells which device file the queue is connected
+ * to... Networked printers use "/dev/null" in this file, so that's what
+ * we use (the actual device URI can confuse some apps...)
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePuts(fp, "/dev/null\n");
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0644);
+ chown(filename, User, Group);
+ }
+
+ /*
+ * The gui_interface file is a script or program that launches a GUI
+ * option panel for the printer, using options specified on the
+ * command-line in the third argument. The option panel must send
+ * any printing options to stdout on a single line when the user
+ * accepts them, or nothing if the user cancels the dialog.
+ *
+ * The default options panel program is /usr/bin/glpoptions, from
+ * the ESP Print Pro software. You can select another using the
+ * PrintcapGUI option.
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePuts(fp, "#!/bin/sh\n");
+ cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0755);
+ chown(filename, User, Group);
+ }
+
+ /*
+ * The POD config file is needed by the printstatus command to show
+ * the printer location and device.
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePrintf(fp, "Printer Class | %s\n",
+ (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript");
+ cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : "");
+ cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : "");
+ cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : "");
+ cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri ? p->device_uri : "");
+ cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name);
+ cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
+ cupsFilePuts(fp, "Status Update Wait | 10 seconds\n");
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0664);
+ chown(filename, User, Group);
+ }
+}
+
+
+/*
+ * 'write_irix_state()' - Update the status files used by IRIX printing
+ * desktop tools.
+ */
+
+static void
+write_irix_state(printer_t *p) /* I - Printer to update */
+{
+ char filename[1024]; /* Interface script filename */
+ cups_file_t *fp; /* Interface script file */
+ int tag; /* Status tag value */
+
+
+ if (p)
+ {
+ /*
+ * The POD status file is needed for the printstatus window to
+ * provide the current status of the printer.
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePrintf(fp, "Operational Status | %s\n",
+ (p->state == IPP_PRINTER_IDLE) ? "Idle" :
+ (p->state == IPP_PRINTER_PROCESSING) ? "Busy" :
+ "Faulted");
+ cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION);
+ cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n",
+ p->device_uri ? p->device_uri : "");
+ cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n",
+ p->accepting ? "Accepting" : "Not accepting");
+ cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0664);
+ chown(filename, User, Group);
+ }
+
+ /*
+ * The activeicons file is needed to provide desktop icons for printers:
+ *
+ * [ quoted from /usr/lib/print/tagit ]
+ *
+ * --- Type of printer tags (base values)
+ *
+ * Dumb=66048 # 0x10200
+ * DumbColor=66080 # 0x10220
+ * Raster=66112 # 0x10240
+ * ColorRaster=66144 # 0x10260
+ * Plotter=66176 # 0x10280
+ * PostScript=66208 # 0x102A0
+ * ColorPostScript=66240 # 0x102C0
+ * MonoPostScript=66272 # 0x102E0
+ *
+ * --- Printer state modifiers for local printers
+ *
+ * Idle=0 # 0x0
+ * Busy=1 # 0x1
+ * Faulted=2 # 0x2
+ * Unknown=3 # 0x3 (Faulted due to unknown reason)
+ *
+ * --- Printer state modifiers for network printers
+ *
+ * NetIdle=8 # 0x8
+ * NetBusy=9 # 0x9
+ * NetFaulted=10 # 0xA
+ * NetUnknown=11 # 0xB (Faulted due to unknown reason)
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
+
+ if (p->type & CUPS_PRINTER_CLASS)
+ unlink(filename);
+ else if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ if (p->type & CUPS_PRINTER_COLOR)
+ tag = 66240;
+ else
+ tag = 66272;
+
+ if (p->type & CUPS_PRINTER_REMOTE)
+ tag |= 8;
+
+ if (p->state == IPP_PRINTER_PROCESSING)
+ tag |= 1;
+
+ else if (p->state == IPP_PRINTER_STOPPED)
+ tag |= 2;
+
+ cupsFilePuts(fp, "#!/bin/sh\n");
+ cupsFilePrintf(fp, "#Tag %d\n", tag);
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0755);
+ chown(filename, User, Group);
+ }
+ }
+
+ /*
+ * The default file is needed by the printers window to show
+ * the default printer.
+ */
+
+ snprintf(filename, sizeof(filename), "/var/spool/lp/default");
+
+ if (DefaultPrinter != NULL)
+ {
+ if ((fp = cupsFileOpen(filename, "w")) != NULL)
+ {
+ cupsFilePrintf(fp, "%s\n", DefaultPrinter->name);
+
+ cupsFileClose(fp);
+
+ chmod(filename, 0644);
+ chown(filename, User, Group);
+ }
+ }
+ else
+ unlink(filename);
+}
+#endif /* __sgi */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/printers.h b/scheduler/printers.h
new file mode 100644
index 000000000..8abe1c1e6
--- /dev/null
+++ b/scheduler/printers.h
@@ -0,0 +1,135 @@
+/*
+ * "$Id$"
+ *
+ * Printer definitions for the Common UNIX Printing System (CUPS) scheduler.
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Quota data...
+ */
+
+typedef struct
+{
+ char username[33]; /* User data */
+ time_t next_update; /* Next update time */
+ int page_count, /* Count of pages */
+ k_count; /* Count of kilobytes */
+} quota_t;
+
+
+/*
+ * Printer/class information structure...
+ */
+
+typedef struct printer_str
+{
+ struct printer_str *next; /* Next printer in list */
+ char *uri, /* Printer URI */
+ *hostname, /* Host printer resides on */
+ *name, /* Printer name */
+ *location, /* Location code */
+ *make_model, /* Make and model */
+ *info; /* Description */
+ int accepting; /* Accepting jobs? */
+ ipp_pstate_t state; /* Printer state */
+ char state_message[1024]; /* Printer state message */
+ int num_reasons; /* Number of printer-state-reasons */
+ char *reasons[16]; /* printer-state-reasons strings */
+ time_t state_time; /* Time at this state */
+ char *job_sheets[2]; /* Banners/job sheets */
+ cups_ptype_t type; /* Printer type (color, small, etc.) */
+ time_t browse_time; /* Last time update was sent/received */
+ char *device_uri; /* Device URI */
+ int raw; /* Raw queue? */
+ mime_type_t *filetype; /* Pseudo-filetype for printer */
+ void *job; /* Current job in queue */
+ ipp_t *attrs; /* Attributes supported by this printer */
+ int num_printers, /* Number of printers in class */
+ last_printer; /* Last printer job was sent to */
+ struct printer_str **printers; /* Printers in class */
+ int quota_period, /* Period for quotas */
+ page_limit, /* Maximum number of pages */
+ k_limit, /* Maximum number of kilobytes */
+ num_quotas; /* Number of quota records */
+ quota_t *quotas; /* Quota records */
+ int deny_users, /* 1 = deny, 0 = allow */
+ num_users; /* Number of allowed/denied users */
+ const char **users; /* Allowed/denied users */
+ int num_history; /* Number of history collections */
+ ipp_t **history; /* History data */
+ int sequence_number; /* Increasing sequence number */
+} printer_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR ipp_t *CommonData VALUE(NULL);
+ /* Common printer object attrs */
+VAR int NumPrinters VALUE(0);
+ /* Number of printers */
+VAR printer_t *Printers VALUE(NULL);
+ /* Printer list */
+VAR printer_t *DefaultPrinter VALUE(NULL);
+ /* Default printer */
+
+
+/*
+ * Prototypes...
+ */
+
+extern printer_t *AddPrinter(const char *name);
+extern void AddPrinterFilter(printer_t *p, const char *filter);
+extern void AddPrinterHistory(printer_t *p);
+extern void AddPrinterUser(printer_t *p, const char *username);
+extern quota_t *AddQuota(printer_t *p, const char *username);
+extern void CreateCommonData(void);
+extern void DeleteAllPrinters(void);
+extern void DeletePrinter(printer_t *p, int update);
+extern void DeletePrinterFilters(printer_t *p);
+extern printer_t *FindDest(const char *name);
+extern printer_t *FindPrinter(const char *name);
+extern quota_t *FindQuota(printer_t *p, const char *username);
+extern void FreePrinterUsers(printer_t *p);
+extern void FreeQuotas(printer_t *p);
+extern void LoadAllPrinters(void);
+extern void SaveAllPrinters(void);
+extern void SetPrinterAttrs(printer_t *p);
+extern void SetPrinterReasons(printer_t *p, const char *s);
+extern void SetPrinterState(printer_t *p, ipp_pstate_t s, int update);
+extern void SortPrinters(void);
+#define StartPrinter(p,u) SetPrinterState((p), IPP_PRINTER_IDLE, (u))
+extern void StopPrinter(printer_t *p, int update);
+extern quota_t *UpdateQuota(printer_t *p, const char *username,
+ int pages, int k);
+extern const char *ValidateDest(const char *hostname,
+ const char *resource,
+ cups_ptype_t *dtype);
+extern void WritePrintcap(void);
+
+extern char *cupsdSanitizeURI(const char *uri, char *buffer,
+ int buflen);
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/quotas.c b/scheduler/quotas.c
new file mode 100644
index 000000000..138a801b7
--- /dev/null
+++ b/scheduler/quotas.c
@@ -0,0 +1,238 @@
+/*
+ * "$Id$"
+ *
+ * Quota routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * AddQuota() - Add a quota record for this printer and user.
+ * FindQuota() - Find a quota record.
+ * FreeQuotas() - Free quotas for a printer.
+ * UpdateQuota() - Update quota data for the specified printer and user.
+ * compare() - Compare two quota records...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cupsd.h"
+
+
+/*
+ * Local functions...
+ */
+
+static int compare(const quota_t *q1, const quota_t *q2);
+
+
+/*
+ * 'AddQuota()' - Add a quota record for this printer and user.
+ */
+
+quota_t * /* O - Quota data */
+AddQuota(printer_t *p, /* I - Printer */
+ const char *username) /* I - User */
+{
+ quota_t *q; /* New quota data */
+
+
+ if (!p || !username)
+ return (NULL);
+
+ if (p->num_quotas == 0)
+ q = malloc(sizeof(quota_t));
+ else
+ q = realloc(p->quotas, sizeof(quota_t) * (p->num_quotas + 1));
+
+ if (!q)
+ return (NULL);
+
+ p->quotas = q;
+ q += p->num_quotas;
+ p->num_quotas ++;
+
+ memset(q, 0, sizeof(quota_t));
+ strlcpy(q->username, username, sizeof(q->username));
+
+ if (p->num_quotas > 1)
+ qsort(p->quotas, p->num_quotas, sizeof(quota_t),
+ (int (*)(const void *, const void *))compare);
+
+ return (FindQuota(p, username));
+}
+
+
+/*
+ * 'FindQuota()' - Find a quota record.
+ */
+
+quota_t * /* O - Quota data */
+FindQuota(printer_t *p, /* I - Printer */
+ const char *username) /* I - User */
+{
+ quota_t *q, /* Quota data pointer */
+ match; /* Search data */
+
+
+ if (!p || !username)
+ return (NULL);
+
+ if (p->num_quotas == 0)
+ q = NULL;
+ else
+ {
+ strlcpy(match.username, username, sizeof(match.username));
+
+ q = bsearch(&match, p->quotas, p->num_quotas, sizeof(quota_t),
+ (int(*)(const void *, const void *))compare);
+ }
+
+ if (q)
+ return (q);
+ else
+ return (AddQuota(p, username));
+}
+
+
+/*
+ * 'FreeQuotas()' - Free quotas for a printer.
+ */
+
+void
+FreeQuotas(printer_t *p) /* I - Printer */
+{
+ if (!p)
+ return;
+
+ if (p->num_quotas)
+ free(p->quotas);
+
+ p->num_quotas = 0;
+ p->quotas = NULL;
+}
+
+
+/*
+ * 'UpdateQuota()' - Update quota data for the specified printer and user.
+ */
+
+quota_t * /* O - Quota data */
+UpdateQuota(printer_t *p, /* I - Printer */
+ const char *username, /* I - User */
+ int pages, /* I - Number of pages */
+ int k) /* I - Number of kilobytes */
+{
+ quota_t *q; /* Quota data */
+ job_t *job, /* Current job */
+ *next; /* Next job */
+ time_t curtime; /* Current time */
+ ipp_attribute_t *attr; /* Job attribute */
+
+
+ if (!p || !username)
+ return (NULL);
+
+ if (!p->k_limit && !p->page_limit)
+ return (NULL);
+
+ if ((q = FindQuota(p, username)) == NULL)
+ return (NULL);
+
+ LogMessage(L_DEBUG, "UpdateQuota: p=%s username=%s pages=%d k=%d",
+ p->name, username, pages, k);
+
+ curtime = time(NULL);
+
+ if (curtime < q->next_update)
+ {
+ q->page_count += pages;
+ q->k_count += k;
+
+ return (q);
+ }
+
+ if (p->quota_period)
+ curtime -= p->quota_period;
+ else
+ curtime = 0;
+
+ q->next_update = 0;
+ q->page_count = 0;
+ q->k_count = 0;
+
+ for (job = Jobs; job; job = next)
+ {
+ next = job->next;
+
+ if (strcasecmp(job->dest, p->name) != 0 ||
+ strcasecmp(job->username, q->username) != 0)
+ continue;
+
+ if ((attr = ippFindAttribute(job->attrs, "time-at-completion",
+ IPP_TAG_INTEGER)) == NULL)
+ if ((attr = ippFindAttribute(job->attrs, "time-at-processing",
+ IPP_TAG_INTEGER)) == NULL)
+ attr = ippFindAttribute(job->attrs, "time-at-creation",
+ IPP_TAG_INTEGER);
+
+ if (attr == NULL)
+ break;
+
+ if (attr->values[0].integer < curtime)
+ {
+ if (JobAutoPurge)
+ CancelJob(job->id, 1);
+
+ continue;
+ }
+
+ if (q->next_update == 0)
+ q->next_update = attr->values[0].integer + p->quota_period;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-media-sheets-completed",
+ IPP_TAG_INTEGER)) != NULL)
+ q->page_count += attr->values[0].integer;
+
+ if ((attr = ippFindAttribute(job->attrs, "job-k-octets",
+ IPP_TAG_INTEGER)) != NULL)
+ q->k_count += attr->values[0].integer;
+ }
+
+ return (q);
+}
+
+
+/*
+ * 'compare()' - Compare two quota records...
+ */
+
+static int /* O - Result of comparison */
+compare(const quota_t *q1, /* I - First quota record */
+ const quota_t *q2) /* I - Second quota record */
+{
+ return (strcasecmp(q1->username, q2->username));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/server.c b/scheduler/server.c
new file mode 100644
index 000000000..1efcaa24d
--- /dev/null
+++ b/scheduler/server.c
@@ -0,0 +1,183 @@
+/*
+ * "$Id$"
+ *
+ * Server start/stop routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * StartServer() - Start the server.
+ * StopServer() - Stop the server.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/http-private.h>
+#include "cupsd.h"
+
+#include <grp.h>
+
+
+/*
+ * 'StartServer()' - Start the server.
+ */
+
+void
+StartServer(void)
+{
+#ifdef HAVE_LIBSSL
+ int i; /* Looping var */
+ struct timeval curtime; /* Current time in microseconds */
+ unsigned char data[1024]; /* Seed data */
+#endif /* HAVE_LIBSSL */
+
+
+#ifdef HAVE_LIBSSL
+ /*
+ * Initialize the encryption libraries...
+ */
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ /*
+ * Using the current time is a dubious random seed, but on some systems
+ * it is the best we can do (on others, this seed isn't even used...)
+ */
+
+ gettimeofday(&curtime, NULL);
+ srand(curtime.tv_sec + curtime.tv_usec);
+
+ for (i = 0; i < sizeof(data); i ++)
+ data[i] = rand(); /* Yes, this is a poor source of random data... */
+
+ RAND_seed(&data, sizeof(data));
+#elif defined(HAVE_GNUTLS)
+ /*
+ * Initialize the encryption libraries...
+ */
+
+ gnutls_global_init();
+#elif defined(HAVE_CDSASSL)
+ ServerCertificatesArray = CDSAGetServerCerts();
+#endif /* HAVE_LIBSSL */
+
+ /*
+ * Startup all the networking stuff...
+ */
+
+ StartListening();
+ StartBrowsing();
+ StartPolling();
+
+ /*
+ * Create a pipe for CGI processes...
+ */
+
+ if (cupsdOpenPipe(CGIPipes))
+ LogMessage(L_ERROR, "StartServer: Unable to create pipes for CGI status!");
+ else
+ {
+ LogMessage(L_DEBUG2, "StartServer: Adding fd %d to InputSet...", CGIPipes[0]);
+ FD_SET(CGIPipes[0], InputSet);
+ }
+}
+
+
+/*
+ * 'StopServer()' - Stop the server.
+ */
+
+void
+StopServer(void)
+{
+ /*
+ * Close all network clients and stop all jobs...
+ */
+
+ CloseAllClients();
+ StopListening();
+ StopPolling();
+ StopBrowsing();
+
+ if (Clients != NULL)
+ {
+ free(Clients);
+ Clients = NULL;
+ }
+
+#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
+ /*
+ * Free all of the certificates...
+ */
+
+ if (ServerCertificatesArray)
+ {
+ CFRelease(ServerCertificatesArray);
+ ServerCertificatesArray = NULL;
+ }
+#endif /* HAVE_SSL && HAVE_CDSASSL */
+
+ /*
+ * Close the pipe for CGI processes...
+ */
+
+ if (CGIPipes[0] >= 0)
+ {
+ LogMessage(L_DEBUG2, "StopServer: Removing fd %d from InputSet...",
+ CGIPipes[0]);
+
+ FD_CLR(CGIPipes[0], InputSet);
+
+ cupsdClosePipe(CGIPipes);
+ }
+
+ /*
+ * Close all log files...
+ */
+
+ if (AccessFile != NULL)
+ {
+ cupsFileClose(AccessFile);
+
+ AccessFile = NULL;
+ }
+
+ if (ErrorFile != NULL)
+ {
+ cupsFileClose(ErrorFile);
+
+ ErrorFile = NULL;
+ }
+
+ if (PageFile != NULL)
+ {
+ cupsFileClose(PageFile);
+
+ PageFile = NULL;
+ }
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/testmime.c b/scheduler/testmime.c
new file mode 100644
index 000000000..25910e0eb
--- /dev/null
+++ b/scheduler/testmime.c
@@ -0,0 +1,247 @@
+/*
+ * "$Id$"
+ *
+ * MIME test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry for the test program.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/string.h>
+#include "mime.h"
+
+
+/*
+ * Local functions...
+ */
+
+static void print_rules(mime_magic_t *rules);
+
+
+/*
+ * 'main()' - Main entry for the test program.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line args */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping vars */
+ const char *filter_path; /* Filter path */
+ char super[MIME_MAX_SUPER], /* Super-type name */
+ type[MIME_MAX_TYPE]; /* Type name */
+ int compression; /* Compression of file */
+ mime_t *mime; /* MIME database */
+ mime_type_t *src, /* Source type */
+ *dst, /* Destination type */
+ **types; /* File type array pointer */
+ mime_filter_t *filters; /* Filters for the file */
+ int num_filters; /* Number of filters for the file */
+
+
+ mime = NULL;
+ src = NULL;
+ dst = NULL;
+ filter_path = "../filter";
+
+ for (i = 1; i < argc; i ++)
+ if (strcmp(argv[i], "-d") == 0)
+ {
+ i ++;
+
+ if (i < argc)
+ mime = mimeLoad(argv[i], filter_path);
+ }
+ else if (strcmp(argv[i], "-f") == 0)
+ {
+ i ++;
+
+ if (i < argc)
+ filter_path = argv[i];
+ }
+ else if (src == NULL)
+ {
+ if (!mime)
+ mime = mimeLoad("../conf", filter_path);
+
+ src = mimeFileType(mime, argv[i], &compression);
+
+ if (src != NULL)
+ printf("%s: %s/%s%s\n", argv[i], src->super, src->type,
+ compression ? " (gzipped)" : "");
+ else
+ {
+ printf("%s: unknown\n", argv[i]);
+ if (mime)
+ mimeDelete(mime);
+ return (1);
+ }
+ }
+ else
+ {
+ sscanf(argv[i], "%15[^/]/%31s", super, type);
+ dst = mimeType(mime, super, type);
+
+ filters = mimeFilter(mime, src, dst, &num_filters, 10);
+
+ if (filters == NULL)
+ {
+ printf("No filters to convert from %s/%s to %s.\n", src->super,
+ src->type, argv[i]);
+ }
+ else
+ {
+ for (j = 0; j < num_filters; j ++)
+ if (j < (num_filters - 1))
+ printf("%s | ", filters[j].filter);
+ else
+ puts(filters[j].filter);
+
+ free(filters);
+ }
+ }
+
+ if (!mime)
+ mime = mimeLoad("../conf", filter_path);
+
+ if (src == NULL)
+ {
+ puts("MIME database types:");
+ for (i = 0, types = mime->types; i < mime->num_types; i ++, types ++)
+ {
+ printf("\t%s/%s:\n", (*types)->super, (*types)->type);
+ print_rules((*types)->rules);
+ puts("");
+ }
+
+ puts("");
+
+ puts("MIME database filters:");
+ for (i = 0, filters = mime->filters; i < mime->num_filters; i ++, filters ++)
+ printf("\t%s/%s to %s/%s: %s (%d)\n",
+ filters->src->super, filters->src->type,
+ filters->dst->super, filters->dst->type,
+ filters->filter, filters->cost);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'print_rules()' - Print the rules for a file type...
+ */
+
+static void
+print_rules(mime_magic_t *rules) /* I - Rules to print */
+{
+ int i; /* Looping var */
+ static char indent[255] = "\t"; /* Indentation for rules */
+
+
+ if (rules == NULL)
+ return;
+
+ while (rules != NULL)
+ {
+ printf("%s[%p] ", indent, rules);
+
+ if (rules->invert)
+ printf("NOT ");
+
+ switch (rules->op)
+ {
+ case MIME_MAGIC_MATCH :
+ printf("match(%s)", rules->value.matchv);
+ break;
+ case MIME_MAGIC_LOCALE :
+ printf("locale(%s)", rules->value.localev);
+ break;
+ case MIME_MAGIC_ASCII :
+ printf("ascii(%d,%d)", rules->offset, rules->length);
+ break;
+ case MIME_MAGIC_PRINTABLE :
+ printf("printable(%d,%d)", rules->offset, rules->length);
+ break;
+ case MIME_MAGIC_STRING :
+ printf("string(%d,", rules->offset);
+ for (i = 0; i < rules->length; i ++)
+ if (rules->value.stringv[i] < ' ' ||
+ rules->value.stringv[i] > 126)
+ printf("<%02X>", rules->value.stringv[i]);
+ else
+ putchar(rules->value.stringv[i]);
+ putchar(')');
+ break;
+ case MIME_MAGIC_CHAR :
+ printf("char(%d,%d)", rules->offset, rules->value.charv);
+ break;
+ case MIME_MAGIC_SHORT :
+ printf("short(%d,%d)", rules->offset, rules->value.shortv);
+ break;
+ case MIME_MAGIC_INT :
+ printf("int(%d,%d)", rules->offset, rules->value.intv);
+ break;
+ case MIME_MAGIC_CONTAINS :
+ printf("contains(%d,%d,", rules->offset, rules->region);
+ for (i = 0; i < rules->length; i ++)
+ if (rules->value.stringv[i] < ' ' ||
+ rules->value.stringv[i] > 126)
+ printf("<%02X>", rules->value.stringv[i]);
+ else
+ putchar(rules->value.stringv[i]);
+ putchar(')');
+ break;
+ default :
+ break;
+ }
+
+ if (rules->child != NULL)
+ {
+ if (rules->op == MIME_MAGIC_OR)
+ puts("OR (");
+ else
+ puts("AND (");
+
+ strcat(indent, "\t");
+ print_rules(rules->child);
+ indent[strlen(indent) - 1] = '\0';
+ printf("%s)\n", indent);
+ }
+ else
+ putchar('\n');
+
+ rules = rules->next;
+ }
+}
+
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/testspeed.c b/scheduler/testspeed.c
new file mode 100644
index 000000000..3daedaaa5
--- /dev/null
+++ b/scheduler/testspeed.c
@@ -0,0 +1,292 @@
+/*
+ * "$Id$"
+ *
+ * Scheduler speed test for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Send multiple IPP requests and report on the average response
+ * time.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <errno.h>
+
+
+/*
+ * Local functions...
+ */
+
+int do_test(const char *server, http_encryption_t encryption,
+ int requests);
+void usage(void);
+
+
+/*
+ * 'main()' - Send multiple IPP requests and report on the average response
+ * time.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ const char *server; /* Server to use */
+ http_encryption_t encryption; /* Encryption to use */
+ int requests; /* Number of requests to send */
+ int children; /* Number of children to fork */
+ int pid; /* Child PID */
+ int status; /* Child status */
+ time_t start, /* Start time */
+ end; /* End time */
+ double elapsed; /* Elapsed time */
+
+
+ /*
+ * Parse command-line options...
+ */
+
+ requests = 100;
+ children = 5;
+ server = cupsServer();
+ encryption = HTTP_ENCRYPT_IF_REQUESTED;
+
+ for (i = 1; i < argc; i ++)
+ if (!strcmp(argv[i], "-c"))
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ children = atoi(argv[i]);
+ }
+ else if (!strcmp(argv[i], "-r"))
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ requests = atoi(argv[i]);
+ }
+ else if (!strcmp(argv[i], "-E"))
+ encryption = HTTP_ENCRYPT_REQUIRED;
+ else if (argv[i][0] == '-')
+ usage();
+ else
+ server = argv[i];
+
+ /*
+ * Then create child processes to act as clients...
+ */
+
+ printf("testspeed: Simulating %d clients with %d requests to %s with %s encryption...\n",
+ children, requests, server,
+ encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no" : "");
+
+ start = time(NULL);
+
+ for (i = 0; i < children; i ++)
+ if ((pid = fork()) == 0)
+ {
+ /*
+ * Child goes here...
+ */
+
+ exit(do_test(server, encryption, requests));
+ }
+ else if (pid < 0)
+ {
+ perror("fork failed");
+ break;
+ }
+ else
+ printf("testspeed(%d): Started...\n", pid);
+
+ /*
+ * Wait for children to finish...
+ */
+
+ for (;;)
+ {
+ pid = wait(&status);
+
+ if (pid < 0 && errno != EINTR)
+ break;
+
+ printf("testspeed(%d): Ended (%d)...\n", pid, status);
+ }
+
+ /*
+ * Compute the total run time...
+ */
+
+ end = time(NULL);
+ elapsed = end - start;
+ i = children * requests;
+
+ printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
+ children, requests, i, elapsed, elapsed / i, i / elapsed);
+
+ /*
+ * Exit with no errors...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'do_test()' - Run a test on a specific host...
+ */
+
+int /* O - Exit status */
+do_test(const char *server, /* I - Server to use */
+ http_encryption_t encryption, /* I - Encryption to use */
+ int requests) /* I - Number of requests to send */
+{
+ int i; /* Looping var */
+ http_t *http; /* Connection to server */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ struct timeval start, /* Start time */
+ end; /* End time */
+ double elapsed; /* Elapsed time */
+ static ipp_op_t ops[4] = /* Operations to test... */
+ {
+ IPP_PRINT_JOB,
+ CUPS_GET_PRINTERS,
+ CUPS_GET_CLASSES,
+ IPP_GET_JOBS
+ };
+
+
+ /*
+ * Connect to the server...
+ */
+
+ http = httpConnectEncrypt(server, ippPort(), encryption);
+
+ if (http == NULL)
+ {
+ perror("testspeed: unable to connect to server");
+ return (1);
+ }
+
+ language = cupsLangDefault();
+
+ /*
+ * Do multiple requests...
+ */
+
+ for (elapsed = 0.0, i = 0; i < requests; i ++)
+ {
+ if ((i % 10) == 0)
+ printf("testspeed(%d): %d%% complete...\n", getpid(), i * 100 / requests);
+
+ /*
+ * Build a request which requires the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ *
+ * In addition, IPP_GET_JOBS needs a printer-uri attribute.
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = ops[i & 3];
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ gettimeofday(&start, NULL);
+
+ switch (request->request.op.operation_id)
+ {
+ case IPP_GET_JOBS :
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ default :
+ response = cupsDoRequest(http, request, "/");
+ break;
+
+ case IPP_PRINT_JOB :
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/test");
+ response = cupsDoFileRequest(http, request, "/printers/test",
+ "../data/testprint.ps");
+ break;
+ }
+
+ gettimeofday(&end, NULL);
+
+ if (response != NULL)
+ ippDelete(response);
+
+ elapsed += (end.tv_sec - start.tv_sec) +
+ 0.000001 * (end.tv_usec - start.tv_usec);
+ }
+
+ cupsLangFree(language);
+ httpClose(http);
+
+ printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
+ getpid(), i, elapsed, elapsed / i, i / elapsed);
+
+ return (0);
+}
+
+
+/*
+ * 'usage()' - Show program usage...
+ */
+
+void
+usage(void)
+{
+ puts("Usage: testspeed [-c children] [-h] [-r requests] [-E] hostname");
+ exit(0);
+}
+
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/type.c b/scheduler/type.c
new file mode 100644
index 000000000..85642a244
--- /dev/null
+++ b/scheduler/type.c
@@ -0,0 +1,1132 @@
+/*
+ * "$Id$"
+ *
+ * MIME typing routines for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * mimeAddType() - Add a MIME type to a database.
+ * mimeAddTypeRule() - Add a detection rule for a file type.
+ * mimeFileType() - Determine the type of a file.
+ * mimeType() - Lookup a file type.
+ * compare() - Compare two MIME super/type names.
+ * checkrules() - Check each rule in a list.
+ * patmatch() - Pattern matching...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <locale.h>
+
+#include <cups/string.h>
+#include "mime.h"
+#include <cups/debug.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int compare(mime_type_t **, mime_type_t **);
+static int checkrules(const char *, cups_file_t *, mime_magic_t *);
+static int patmatch(const char *, const char *);
+
+
+/*
+ * 'mimeAddType()' - Add a MIME type to a database.
+ */
+
+mime_type_t * /* O - New (or existing) MIME type */
+mimeAddType(mime_t *mime, /* I - MIME database */
+ const char *super, /* I - Super-type name */
+ const char *type) /* I - Type name */
+{
+ mime_type_t *temp, /* New MIME type */
+ **types; /* New MIME types array */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (mime == NULL || super == NULL || type == NULL)
+ return (NULL);
+
+ if (strlen(super) > (MIME_MAX_SUPER - 1) ||
+ strlen(type) > (MIME_MAX_TYPE - 1))
+ return (NULL);
+
+ /*
+ * See if the type already exists; if so, return the existing type...
+ */
+
+ if ((temp = mimeType(mime, super, type)) != NULL)
+ return (temp);
+
+ /*
+ * The type doesn't exist; add it...
+ */
+
+ if ((temp = calloc(1, sizeof(mime_type_t))) == NULL)
+ return (NULL);
+
+ if (mime->num_types == 0)
+ types = (mime_type_t **)malloc(sizeof(mime_type_t *));
+ else
+ types = (mime_type_t **)realloc(mime->types, sizeof(mime_type_t *) * (mime->num_types + 1));
+
+ if (types == NULL)
+ {
+ free(temp);
+ return (NULL);
+ }
+
+ mime->types = types;
+ types += mime->num_types;
+ mime->num_types ++;
+
+ *types = temp;
+ strlcpy(temp->super, super, sizeof(temp->super));
+ if ((temp->type = strdup(type)) == NULL)
+ {
+ mime->num_types --;
+ return (NULL);
+ }
+
+ if (mime->num_types > 1)
+ qsort(mime->types, mime->num_types, sizeof(mime_type_t *),
+ (int (*)(const void *, const void *))compare);
+
+ return (temp);
+}
+
+
+/*
+ * 'mimeAddTypeRule()' - Add a detection rule for a file type.
+ */
+
+int /* O - 0 on success, -1 on failure */
+mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */
+ const char *rule) /* I - Rule to add */
+{
+ int num_values, /* Number of values seen */
+ op, /* Operation code */
+ logic, /* Logic for next rule */
+ invert; /* Invert following rule? */
+ char name[255], /* Name in rule string */
+ value[3][255], /* Value in rule string */
+ *ptr, /* Position in name or value */
+ quote; /* Quote character */
+ int length[3]; /* Length of each parameter */
+ mime_magic_t *temp, /* New rule */
+ *current; /* Current rule */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (mt == NULL || rule == NULL)
+ return (-1);
+
+ /*
+ * Find the last rule in the top-level of the rules tree.
+ */
+
+ for (current = mt->rules; current != NULL; current = current->next)
+ if (current->next == NULL)
+ break;
+
+ /*
+ * Parse the rules string. Most rules are either a file extension or a
+ * comparison function:
+ *
+ * extension
+ * function(parameters)
+ */
+
+ logic = MIME_MAGIC_NOP;
+ invert = 0;
+
+ DEBUG_printf(("%s/%s: %s\n", mt->super, mt->type, rule));
+
+ while (*rule != '\0')
+ {
+ while (isspace(*rule & 255))
+ rule ++;
+
+ if (*rule == '(')
+ {
+ DEBUG_puts("new parenthesis group");
+ logic = MIME_MAGIC_NOP;
+ rule ++;
+ }
+ else if (*rule == ')')
+ {
+ DEBUG_puts("close paren...");
+ if (current == NULL || current->parent == NULL)
+ return (-1);
+
+ current = current->parent;
+
+ if (current->parent == NULL)
+ logic = MIME_MAGIC_OR;
+ else
+ logic = current->parent->op;
+
+ rule ++;
+ }
+ else if (*rule == '+' && current != NULL)
+ {
+ if (logic != MIME_MAGIC_AND &&
+ current != NULL && current->prev != NULL && current->prev->prev != NULL)
+ {
+ /*
+ * OK, we have more than 1 rule in the current tree level... Make a
+ * new group tree and move the previous rule to it...
+ */
+
+ if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL)
+ return (-1);
+
+ temp->op = MIME_MAGIC_AND;
+ temp->child = current;
+ temp->parent = current->parent;
+ current->prev->next = temp;
+ temp->prev = current->prev;
+
+ current->prev = NULL;
+ current->parent = temp;
+
+ DEBUG_printf(("creating new AND group %p...\n", temp));
+ }
+ else
+ {
+ DEBUG_printf(("setting group %p op to AND...\n", current->parent));
+ current->parent->op = MIME_MAGIC_AND;
+ }
+
+ logic = MIME_MAGIC_AND;
+ rule ++;
+ }
+ else if (*rule == ',')
+ {
+ if (logic != MIME_MAGIC_OR && current != NULL)
+ {
+ /*
+ * OK, we have two possibilities; either this is the top-level rule or
+ * we have a bunch of AND rules at this level.
+ */
+
+ if (current->parent == NULL)
+ {
+ /*
+ * This is the top-level rule; we have to move *all* of the AND rules
+ * down a level, as AND has precedence over OR.
+ */
+
+ if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL)
+ return (-1);
+
+ DEBUG_printf(("creating new AND group %p inside OR group\n", temp));
+
+ while (current->prev != NULL)
+ {
+ current->parent = temp;
+ current = current->prev;
+ }
+
+ current->parent = temp;
+ temp->op = MIME_MAGIC_AND;
+ temp->child = current;
+
+ mt->rules = current = temp;
+ }
+ else
+ {
+ /*
+ * This isn't the top rule, so go up one level...
+ */
+
+ DEBUG_puts("going up one level");
+ current = current->parent;
+ }
+ }
+
+ logic = MIME_MAGIC_OR;
+ rule ++;
+ }
+ else if (*rule == '!')
+ {
+ DEBUG_puts("NOT");
+ invert = 1;
+ rule ++;
+ }
+ else if (isalnum(*rule & 255))
+ {
+ /*
+ * Read an extension name or a function...
+ */
+
+ for (ptr = name; isalnum(*rule & 255) && (ptr - name) < (sizeof(name) - 1);)
+ *ptr++ = *rule++;
+
+ *ptr = '\0';
+ num_values = 0;
+
+ if (*rule == '(')
+ {
+ /*
+ * Read function parameters...
+ */
+
+ rule ++;
+ for (num_values = 0;
+ num_values < (sizeof(value) / sizeof(value[0]));
+ num_values ++)
+ {
+ ptr = value[num_values];
+
+ while ((ptr - value[num_values]) < (sizeof(value[0]) - 1) &&
+ *rule != '\0' && *rule != ',' && *rule != ')')
+ {
+ if (isspace(*rule & 255))
+ {
+ /*
+ * Ignore whitespace...
+ */
+
+ rule ++;
+ continue;
+ }
+ else if (*rule == '\"' || *rule == '\'')
+ {
+ /*
+ * Copy quoted strings literally...
+ */
+
+ quote = *rule++;
+
+ while (*rule != '\0' && *rule != quote &&
+ (ptr - value[num_values]) < (sizeof(value[0]) - 1))
+ *ptr++ = *rule++;
+
+ if (*rule == quote)
+ rule ++;
+ else
+ return (-1);
+ }
+ else if (*rule == '<')
+ {
+ rule ++;
+
+ while (*rule != '>' && *rule != '\0' &&
+ (ptr - value[num_values]) < (sizeof(value[0]) - 1))
+ {
+ if (isxdigit(rule[0] & 255) && isxdigit(rule[1] & 255))
+ {
+ if (isdigit(*rule))
+ *ptr = (*rule++ - '0') << 4;
+ else
+ *ptr = (tolower(*rule++) - 'a' + 10) << 4;
+
+ if (isdigit(*rule))
+ *ptr++ |= *rule++ - '0';
+ else
+ *ptr++ |= tolower(*rule++) - 'a' + 10;
+ }
+ else
+ return (-1);
+ }
+
+ if (*rule == '>')
+ rule ++;
+ else
+ return (-1);
+ }
+ else
+ *ptr++ = *rule++;
+ }
+
+ *ptr = '\0';
+ length[num_values] = ptr - value[num_values];
+
+ if (*rule != ',')
+ break;
+
+ rule ++;
+ }
+
+ if (*rule != ')')
+ return (-1);
+
+ rule ++;
+
+ /*
+ * Figure out the function...
+ */
+
+ if (strcmp(name, "match") == 0)
+ op = MIME_MAGIC_MATCH;
+ else if (strcmp(name, "ascii") == 0)
+ op = MIME_MAGIC_ASCII;
+ else if (strcmp(name, "printable") == 0)
+ op = MIME_MAGIC_PRINTABLE;
+ else if (strcmp(name, "string") == 0)
+ op = MIME_MAGIC_STRING;
+ else if (strcmp(name, "istring") == 0)
+ op = MIME_MAGIC_ISTRING;
+ else if (strcmp(name, "char") == 0)
+ op = MIME_MAGIC_CHAR;
+ else if (strcmp(name, "short") == 0)
+ op = MIME_MAGIC_SHORT;
+ else if (strcmp(name, "int") == 0)
+ op = MIME_MAGIC_INT;
+ else if (strcmp(name, "locale") == 0)
+ op = MIME_MAGIC_LOCALE;
+ else if (strcmp(name, "contains") == 0)
+ op = MIME_MAGIC_CONTAINS;
+ else
+ return (-1);
+ }
+ else
+ {
+ /*
+ * This is just a filename match on the extension...
+ */
+
+ snprintf(value[0], sizeof(value[0]), "*.%s", name);
+ length[0] = strlen(value[0]);
+ num_values = 1;
+ op = MIME_MAGIC_MATCH;
+ }
+
+ /*
+ * Add a rule for this operation.
+ */
+
+ if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL)
+ return (-1);
+
+ temp->invert = invert;
+ if (current != NULL)
+ {
+ temp->parent = current->parent;
+ current->next = temp;
+ }
+ else
+ mt->rules = temp;
+
+ temp->prev = current;
+
+ if (logic == MIME_MAGIC_NOP)
+ {
+ /*
+ * Add parenthetical grouping...
+ */
+
+ DEBUG_printf(("making new OR group %p for parenthesis...\n", temp));
+
+ temp->op = MIME_MAGIC_OR;
+
+ if ((temp->child = calloc(1, sizeof(mime_magic_t))) == NULL)
+ return (-1);
+
+ temp->child->parent = temp;
+
+ temp = temp->child;
+ logic = MIME_MAGIC_OR;
+ }
+
+ DEBUG_printf(("adding %p: %s, op = %d, logic = %d, invert = %d\n",
+ temp, name, op, logic, invert));
+
+ /*
+ * Fill in data for the rule...
+ */
+
+ current = temp;
+ temp->op = op;
+ invert = 0;
+
+ switch (op)
+ {
+ case MIME_MAGIC_MATCH :
+ if (length[0] > (sizeof(temp->value.matchv) - 1))
+ return (-1);
+ strcpy(temp->value.matchv, value[0]);
+ break;
+ case MIME_MAGIC_ASCII :
+ case MIME_MAGIC_PRINTABLE :
+ temp->offset = strtol(value[0], NULL, 0);
+ temp->length = strtol(value[1], NULL, 0);
+ if (temp->length > MIME_MAX_BUFFER)
+ temp->length = MIME_MAX_BUFFER;
+ break;
+ case MIME_MAGIC_STRING :
+ case MIME_MAGIC_ISTRING :
+ temp->offset = strtol(value[0], NULL, 0);
+ if (length[1] > sizeof(temp->value.stringv))
+ return (-1);
+ temp->length = length[1];
+ memcpy(temp->value.stringv, value[1], length[1]);
+ break;
+ case MIME_MAGIC_CHAR :
+ temp->offset = strtol(value[0], NULL, 0);
+ if (length[1] == 1)
+ temp->value.charv = value[1][0];
+ else
+ temp->value.charv = (char)strtol(value[1], NULL, 0);
+ break;
+ case MIME_MAGIC_SHORT :
+ temp->offset = strtol(value[0], NULL, 0);
+ temp->value.shortv = (short)strtol(value[1], NULL, 0);
+ break;
+ case MIME_MAGIC_INT :
+ temp->offset = strtol(value[0], NULL, 0);
+ temp->value.intv = (int)strtol(value[1], NULL, 0);
+ break;
+ case MIME_MAGIC_LOCALE :
+ if (length[0] > (sizeof(temp->value.localev) - 1))
+ return (-1);
+
+ strcpy(temp->value.localev, value[0]);
+ break;
+ case MIME_MAGIC_CONTAINS :
+ temp->offset = strtol(value[0], NULL, 0);
+ temp->region = strtol(value[1], NULL, 0);
+ if (length[2] > sizeof(temp->value.stringv))
+ return (-1);
+ temp->length = length[2];
+ memcpy(temp->value.stringv, value[2], length[2]);
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'mimeFileType()' - Determine the type of a file.
+ */
+
+mime_type_t * /* O - Type of file */
+mimeFileType(mime_t *mime, /* I - MIME database */
+ const char *pathname, /* I - Name of file to check */
+ int *compression) /* O - Is the file compressed? */
+{
+ int i; /* Looping var */
+ cups_file_t *fp; /* File pointer */
+ mime_type_t **types; /* File types */
+ const char *filename; /* Base filename of file */
+
+
+ /*
+ * Range check input parameters...
+ */
+
+ if (mime == NULL || pathname == NULL)
+ return (NULL);
+
+ /*
+ * Try to open the file...
+ */
+
+ if ((fp = cupsFileOpen(pathname, "r")) == NULL)
+ return (NULL);
+
+ /*
+ * Figure out the filename (without directory portion)...
+ */
+
+ if ((filename = strrchr(pathname, '/')) != NULL)
+ filename ++;
+ else
+ filename = pathname;
+
+ /*
+ * Then check it against all known types...
+ */
+
+ for (i = mime->num_types, types = mime->types; i > 0; i --, types ++)
+ if (checkrules(filename, fp, (*types)->rules))
+ break;
+
+ /*
+ * Finally, close the file and return a match (if any)...
+ */
+
+ if (compression)
+ *compression = cupsFileCompression(fp);
+
+ cupsFileClose(fp);
+
+ if (i > 0)
+ return (*types);
+ else
+ return (NULL);
+}
+
+
+/*
+ * 'mimeType()' - Lookup a file type.
+ */
+
+mime_type_t * /* O - Matching file type definition */
+mimeType(mime_t *mime, /* I - MIME database */
+ const char *super, /* I - Super-type name */
+ const char *type) /* I - Type name */
+{
+ mime_type_t key, /* MIME type search key*/
+ *keyptr, /* Key pointer... */
+ **match; /* Matching pointer */
+
+ /*
+ * Range check input...
+ */
+
+ if (mime == NULL || super == NULL || type == NULL)
+ return (NULL);
+
+ if (strlen(super) > (MIME_MAX_SUPER - 1) ||
+ strlen(type) > (MIME_MAX_TYPE - 1))
+ return (NULL);
+
+ if (mime->num_types == 0)
+ return (NULL);
+
+ /*
+ * Lookup the type in the array...
+ */
+
+ strlcpy(key.super, super, sizeof(key.super));
+ key.type = (char *)type;
+
+ keyptr = &key;
+
+ match = (mime_type_t **)bsearch(&keyptr, mime->types, mime->num_types,
+ sizeof(mime_type_t *),
+ (int (*)(const void *, const void *))compare);
+
+ if (match == NULL)
+ return (NULL);
+ else
+ return (*match);
+}
+
+
+/*
+ * 'compare()' - Compare two MIME super/type names.
+ */
+
+static int /* O - Result of comparison */
+compare(mime_type_t **t0, /* I - First type */
+ mime_type_t **t1) /* I - Second type */
+{
+ int i; /* Result of comparison */
+
+
+ if ((i = strcasecmp((*t0)->super, (*t1)->super)) == 0)
+ i = strcasecmp((*t0)->type, (*t1)->type);
+
+ return (i);
+}
+
+
+/*
+ * 'checkrules()' - Check each rule in a list.
+ */
+
+static int /* O - 1 if match, 0 if no match */
+checkrules(const char *filename, /* I - Filename */
+ cups_file_t *fp, /* I - File to check */
+ mime_magic_t *rules) /* I - Rules to check */
+{
+ int n; /* Looping var */
+ int region; /* Region to look at */
+ int logic, /* Logic to apply */
+ result, /* Result of test */
+ intv; /* Integer value */
+ short shortv; /* Short value */
+ unsigned char buffer[MIME_MAX_BUFFER],/* Input buffer */
+ *bufptr; /* Current buffer position */
+ int bufoffset, /* Offset in file for buffer */
+ buflength; /* Length of data in buffer */
+
+
+ if (rules == NULL)
+ return (0);
+
+ if (rules->parent == NULL)
+ logic = MIME_MAGIC_OR;
+ else
+ logic = rules->parent->op;
+
+ bufoffset = -1;
+ buflength = 0;
+ result = 0;
+
+ while (rules != NULL)
+ {
+ /*
+ * Compute the result of this rule...
+ */
+
+ switch (rules->op)
+ {
+ case MIME_MAGIC_MATCH :
+ result = patmatch(filename, rules->value.matchv);
+ break;
+
+ case MIME_MAGIC_ASCII :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + rules->length) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Test for ASCII printable characters plus standard control chars.
+ */
+
+ if ((rules->offset + rules->length) > (bufoffset + buflength))
+ n = bufoffset + buflength - rules->offset;
+ else
+ n = rules->length;
+
+ bufptr = buffer + rules->offset - bufoffset;
+ while (n > 0)
+ if ((*bufptr >= 32 && *bufptr <= 126) ||
+ (*bufptr >= 8 && *bufptr <= 13) ||
+ *bufptr == 26 || *bufptr == 27)
+ {
+ n --;
+ bufptr ++;
+ }
+ else
+ break;
+
+ result = (n == 0);
+ break;
+
+ case MIME_MAGIC_PRINTABLE :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + rules->length) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Test for 8-bit printable characters plus standard control chars.
+ */
+
+ if ((rules->offset + rules->length) > (bufoffset + buflength))
+ n = bufoffset + buflength - rules->offset;
+ else
+ n = rules->length;
+
+ bufptr = buffer + rules->offset - bufoffset;
+
+ while (n > 0)
+ if (*bufptr >= 128 ||
+ (*bufptr >= 32 && *bufptr <= 126) ||
+ (*bufptr >= 8 && *bufptr <= 13) ||
+ *bufptr == 26 || *bufptr == 27)
+ {
+ n --;
+ bufptr ++;
+ }
+ else
+ break;
+
+ result = (n == 0);
+ break;
+
+ case MIME_MAGIC_STRING :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + rules->length) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the buffer against the string. If the file is too
+ * short then don't compare - it can't match...
+ */
+
+ if ((rules->offset + rules->length) > (bufoffset + buflength))
+ result = 0;
+ else
+ result = (memcmp(buffer + rules->offset - bufoffset,
+ rules->value.stringv, rules->length) == 0);
+ break;
+
+ case MIME_MAGIC_ISTRING :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + rules->length) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the buffer against the string. If the file is too
+ * short then don't compare - it can't match...
+ */
+
+ if ((rules->offset + rules->length) > (bufoffset + buflength))
+ result = 0;
+ else
+ result = (strncasecmp((char *)buffer + rules->offset - bufoffset,
+ rules->value.stringv, rules->length) == 0);
+ break;
+
+ case MIME_MAGIC_CHAR :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset)
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the character values; if the file is too short, it
+ * can't match...
+ */
+
+ if (buflength < 1)
+ result = 0;
+ else
+ result = (buffer[rules->offset - bufoffset] == rules->value.charv);
+ break;
+
+ case MIME_MAGIC_SHORT :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + 2) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the short values; if the file is too short, it
+ * can't match...
+ */
+
+ if (buflength < 2)
+ result = 0;
+ else
+ {
+ bufptr = buffer + rules->offset - bufoffset;
+ shortv = (bufptr[0] << 8) | bufptr[1];
+ result = (shortv == rules->value.shortv);
+ }
+ break;
+
+ case MIME_MAGIC_INT :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + 4) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the int values; if the file is too short, it
+ * can't match...
+ */
+
+ if (buflength < 4)
+ result = 0;
+ else
+ {
+ bufptr = buffer + rules->offset - bufoffset;
+ intv = (((((bufptr[0] << 8) | bufptr[1]) << 8) | bufptr[2]) << 8) |
+ bufptr[3];;
+ result = (intv == rules->value.intv);
+ }
+ break;
+
+ case MIME_MAGIC_LOCALE :
+#if defined(WIN32) || defined(__EMX__) || defined(__APPLE__)
+ result = (strcmp(rules->value.localev, setlocale(LC_ALL, "")) == 0);
+#else
+ result = (strcmp(rules->value.localev, setlocale(LC_MESSAGES, "")) == 0);
+#endif /* __APPLE__ */
+ break;
+
+ case MIME_MAGIC_CONTAINS :
+ /*
+ * Load the buffer if necessary...
+ */
+
+ if (bufoffset < 0 || rules->offset < bufoffset ||
+ (rules->offset + rules->region) > (bufoffset + buflength))
+ {
+ /*
+ * Reload file buffer...
+ */
+
+ cupsFileSeek(fp, rules->offset);
+ buflength = cupsFileRead(fp, (char *)buffer, sizeof(buffer));
+ bufoffset = rules->offset;
+ }
+
+ /*
+ * Compare the buffer against the string. If the file is too
+ * short then don't compare - it can't match...
+ */
+
+ if ((rules->offset + rules->length) > (bufoffset + buflength))
+ result = 0;
+ else
+ {
+ if (buflength > rules->region)
+ region = rules->region - rules->length;
+ else
+ region = buflength - rules->length;
+
+ for (n = 0; n < region; n ++)
+ if ((result = (memcmp(buffer + rules->offset - bufoffset + n,
+ rules->value.stringv, rules->length) == 0)) != 0)
+ break;
+ }
+ break;
+
+ default :
+ if (rules->child != NULL)
+ result = checkrules(filename, fp, rules->child);
+ else
+ result = 0;
+ break;
+ }
+
+ /*
+ * If the logic is inverted, invert the result...
+ */
+
+ if (rules->invert)
+ result = !result;
+
+ /*
+ * OK, now if the current logic is OR and this result is true, the this
+ * rule set is true. If the current logic is AND and this result is false,
+ * the the rule set is false...
+ */
+
+ DEBUG_printf(("result of test %p is %d\n", rules, result));
+
+ if ((result && logic == MIME_MAGIC_OR) ||
+ (!result && logic == MIME_MAGIC_AND))
+ return (result);
+
+ /*
+ * Otherwise the jury is still out on this one, so move to the next rule.
+ */
+
+ rules = rules->next;
+ }
+
+ return (result);
+}
+
+
+/*
+ * 'patmatch()' - Pattern matching...
+ */
+
+static int /* O - 1 if match, 0 if no match */
+patmatch(const char *s, /* I - String to match against */
+ const char *pat) /* I - Pattern to match against */
+{
+ /*
+ * Range check the input...
+ */
+
+ if (s == NULL || pat == NULL)
+ return (0);
+
+ /*
+ * Loop through the pattern and match strings, and stop if we come to a
+ * point where the strings don't match or we find a complete match.
+ */
+
+ while (*s != '\0' && *pat != '\0')
+ {
+ if (*pat == '*')
+ {
+ /*
+ * Wildcard - 0 or more characters...
+ */
+
+ pat ++;
+ if (*pat == '\0')
+ return (1); /* Last pattern char is *, so everything matches now... */
+
+ /*
+ * Test all remaining combinations until we get to the end of the string.
+ */
+
+ while (*s != '\0')
+ {
+ if (patmatch(s, pat))
+ return (1);
+
+ s ++;
+ }
+ }
+ else if (*pat == '?')
+ {
+ /*
+ * Wildcard - 1 character...
+ */
+
+ pat ++;
+ s ++;
+ continue;
+ }
+ else if (*pat == '[')
+ {
+ /*
+ * Match a character from the input set [chars]...
+ */
+
+ pat ++;
+ while (*pat != ']' && *pat != '\0')
+ if (*s == *pat)
+ break;
+ else
+ pat ++;
+
+ if (*pat == ']' || *pat == '\0')
+ return (0);
+
+ while (*pat != ']' && *pat != '\0')
+ pat ++;
+
+ if (*pat == ']')
+ pat ++;
+
+ continue;
+ }
+ else if (*pat == '\\')
+ {
+ /*
+ * Handle quoted characters...
+ */
+
+ pat ++;
+ }
+
+ /*
+ * Stop if the pattern and string don't match...
+ */
+
+ if (*pat++ != *s++)
+ return (0);
+ }
+
+ /*
+ * Done parsing the pattern and string; return 1 if the last character matches
+ * and 0 otherwise...
+ */
+
+ return (*s == *pat);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scripting/java/CUPSPrinter.java b/scripting/java/CUPSPrinter.java
new file mode 100644
index 000000000..a6d7a3075
--- /dev/null
+++ b/scripting/java/CUPSPrinter.java
@@ -0,0 +1,438 @@
+//
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class CUPSPrinter
+{
+ String printer_name;
+ String printer_location;
+ String printer_info;
+ String printer_more_info;
+
+ String[] printer_uri_supported; // Strings
+ String[] uri_authentication_supported; // Strings
+ String[] uri_security_supported; // Strings
+
+ String attributes_charset;
+ String attributes_natural_language;
+
+ int printer_state;
+ String printer_state_reasons;
+
+ boolean printer_is_accepting_jobs;
+
+ long printer_up_time;
+ long printer_current_time;
+
+ int queued_job_count;
+
+ String[] pdl_override_supported;
+ String[] ipp_versions_supported;
+
+ int[] operations_supported; // Integers
+
+ boolean multiple_document_jobs_supported;
+ int multiple_operation_time_out;
+ int[] multiple_document_handling_supported; // Integers
+
+ String charset_configured;
+ String natural_language_configured;
+ String generated_natural_language_supported;
+ String[] charset_supported; // Strings
+
+ String document_format_default;
+ String[] document_format_supported; // Strings
+
+ String[] compression_supported; // Strings
+
+ int job_priority_default;
+ int job_priority_supported;
+
+ int copies_default;
+ int lower_copies_supported;
+ int upper_copies_supported;
+
+ boolean page_ranges_supported;
+
+ int number_up_default;
+ int[] number_up_supported; // integers
+
+
+ int orientation_requested_default;
+ int[] orientation_requested_supported; // Integers
+
+ int job_quota_period;
+ int job_k_limit;
+ int job_page_limit;
+
+ String job_sheets_default; // Should this be a list too?
+ String[] job_sheets_supported; // Strings
+
+ String device_uri;
+
+ boolean color_supported;
+ int pages_per_minute;
+
+ String printer_make_and_model;
+
+ String media_default;
+ String[] media_supported; // Strings
+
+ int finishings_default;
+ int[] finishings_supported; // Integers
+
+ int printer_type;
+
+
+
+ // ---------------------------------------------
+ //
+ // Basic constructor.
+ //
+ public CUPSPrinter()
+ {
+ }
+
+
+
+
+ // ---------------------------------------------
+ //
+ // Move the attributes from an ipp request
+ // into a CUPSPrinter object.
+ //
+ public void updateAttribute( IPPAttribute a )
+ {
+ IPPValue v;
+ int i;
+
+
+ if (a.name.compareTo("printer-name") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_name = v.text;
+ }
+ else if (a.name.compareTo("printer-location") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_location = v.text;
+ }
+ else if (a.name.compareTo("printer-info") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_info = v.text;
+ }
+ else if (a.name.compareTo("printer-more-info") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_more_info = v.text;
+ }
+ else if (a.name.compareTo("printer-uri-supported") == 0)
+ {
+ printer_uri_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ printer_uri_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("uri-authentication-supported") == 0)
+ {
+ uri_authentication_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ uri_authentication_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("uri-security-supported") == 0)
+ {
+ uri_security_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ uri_security_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("attributes-charset") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ attributes_charset = v.text;
+ }
+ else if (a.name.compareTo("attributes-natural-language") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ attributes_natural_language = v.text;
+ }
+ else if (a.name.compareTo("printer-state") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_state = v.integer_value;
+ }
+ else if (a.name.compareTo("printer-state-reasons") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_state_reasons = v.text;
+ }
+ else if (a.name.compareTo("printer-is-accepting-jobs") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_is_accepting_jobs = v.boolean_value;
+ }
+ else if (a.name.compareTo("printer-up-time") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_up_time = v.integer_value;
+ }
+ else if (a.name.compareTo("printer-current-time") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_current_time = v.unix_time; // *** FIX ***
+ }
+ else if (a.name.compareTo("queue-job-count") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ queued_job_count = v.integer_value;
+ }
+ else if (a.name.compareTo("pdl-override-supported") == 0)
+ {
+ pdl_override_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ pdl_override_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("ipp-versions-supported") == 0)
+ {
+ ipp_versions_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ ipp_versions_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("operations-supported") == 0)
+ {
+ operations_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ operations_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("multiple-document-jobs-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ multiple_document_jobs_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("multiple-operation-time-out") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ multiple_operation_time_out = v.integer_value;
+ }
+ else if (a.name.compareTo("multiple-document-handling-supported") == 0)
+ {
+ multiple_document_handling_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ multiple_document_handling_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("charset-configured") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ charset_configured = v.text;
+ }
+ else if (a.name.compareTo("natural-language-configured") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ natural_language_configured = v.text;
+ }
+ else if (a.name.compareTo("generated-natural-language-supported") == 0)
+ {
+ // *** Should this be a list too?
+ v = (IPPValue)a.values.get(0);
+ generated_natural_language_supported = v.text;
+ }
+ else if (a.name.compareTo("charset-supported") == 0)
+ {
+ charset_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ charset_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("document-format-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ document_format_default = v.text;
+ }
+ else if (a.name.compareTo("document-format-supported") == 0)
+ {
+ document_format_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ document_format_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("compression-supported") == 0)
+ {
+ compression_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ compression_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("job-priority-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_priority_default = v.integer_value;
+ }
+ else if (a.name.compareTo("job-priority-supported") == 0)
+ {
+ // *** Should be a list? ***
+ v = (IPPValue)a.values.get(0);
+ job_priority_supported = v.integer_value;
+ }
+ else if (a.name.compareTo("copies-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ copies_default = v.integer_value;
+ }
+ else if (a.name.compareTo("copies-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ lower_copies_supported = v.lower;
+ upper_copies_supported = v.upper;
+ }
+ else if (a.name.compareTo("page-ranges-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ page_ranges_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("number-up-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ number_up_default = v.integer_value;
+ }
+ else if (a.name.compareTo("number-up-supported") == 0)
+ {
+ number_up_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ number_up_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("orientation-requested-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ orientation_requested_default = v.integer_value;
+ }
+ else if (a.name.compareTo("orientation-requested-supported") == 0)
+ {
+ orientation_requested_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ orientation_requested_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("job-quota-period") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_quota_period = v.integer_value;
+ }
+ else if (a.name.compareTo("job-k-limit") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_k_limit = v.integer_value;
+ }
+ else if (a.name.compareTo("job-page-limit") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_page_limit = v.integer_value;
+ }
+ else if (a.name.compareTo("job-sheets-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_sheets_default = v.text;
+ }
+ else if (a.name.compareTo("job-sheets-supported") == 0)
+ {
+ job_sheets_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ job_sheets_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("device-uri") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ device_uri = v.text;
+ }
+ else if (a.name.compareTo("color-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ color_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("pages-per-minute") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ pages_per_minute = v.integer_value;
+ }
+ else if (a.name.compareTo("printer-make-and-model") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_make_and_model = v.text;
+ }
+ else if (a.name.compareTo("media-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ media_default = v.text;
+ }
+ else if (a.name.compareTo("media-supported") == 0)
+ {
+ media_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ media_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("finishings-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ finishings_default = v.integer_value;
+ }
+ else if (a.name.compareTo("finishings-supported") == 0)
+ {
+ finishings_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ finishings_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("printer-type") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_type = v.integer_value;
+ }
+
+ } // End of updateAttribute()
+
+
+
+
+
+} // End of CUPSPrinter class
+
+
diff --git a/scripting/java/README b/scripting/java/README
new file mode 100644
index 000000000..6260cd288
--- /dev/null
+++ b/scripting/java/README
@@ -0,0 +1,9 @@
+README - 04/11/2003
+-------------------
+
+This directory contains the Java API for CUPS, which requires JDK 1.4
+or higher.
+
+The CUPS Java API code and examples are provided under the terms of the
+GNU Library General Public License, just as for the CUPS C API.
+
diff --git a/scripting/java/cups.jar b/scripting/java/cups.jar
new file mode 100644
index 000000000..c348fee30
--- /dev/null
+++ b/scripting/java/cups.jar
Binary files differ
diff --git a/scripting/java/docs/allclasses-frame.html b/scripting/java/docs/allclasses-frame.html
new file mode 100644
index 000000000..9b8e3eb75
--- /dev/null
+++ b/scripting/java/docs/allclasses-frame.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+All Classes
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="All Classes";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B>All Classes</B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="org/cups/Cups.html" TARGET="classFrame">Cups</A>
+<BR>
+<A HREF="org/cups/CupsJob.html" TARGET="classFrame">CupsJob</A>
+<BR>
+<A HREF="org/cups/CupsPrinter.html" TARGET="classFrame">CupsPrinter</A>
+<BR>
+<A HREF="org/cups/IPP.html" TARGET="classFrame">IPP</A>
+<BR>
+<A HREF="org/cups/IPPAttribute.html" TARGET="classFrame">IPPAttribute</A>
+<BR>
+<A HREF="org/cups/IPPDefs.html" TARGET="classFrame">IPPDefs</A>
+<BR>
+<A HREF="org/cups/IPPError.html" TARGET="classFrame">IPPError</A>
+<BR>
+<A HREF="org/cups/IPPHttp.html" TARGET="classFrame">IPPHttp</A>
+<BR>
+<A HREF="org/cups/IPPRequest.html" TARGET="classFrame">IPPRequest</A>
+<BR>
+<A HREF="org/cups/IPPStatus.html" TARGET="classFrame">IPPStatus</A>
+<BR>
+<A HREF="org/cups/IPPURLConnection.html" TARGET="classFrame">IPPURLConnection</A>
+<BR>
+<A HREF="org/cups/IPPValue.html" TARGET="classFrame">IPPValue</A>
+<BR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/deprecated-list.html b/scripting/java/docs/deprecated-list.html
new file mode 100644
index 000000000..53ae1a03a
--- /dev/null
+++ b/scripting/java/docs/deprecated-list.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+Deprecated List
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Deprecated List";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="deprecated-list.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H2>
+<B>Deprecated API</B></H2>
+</CENTER>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="deprecated-list.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/help-doc.html b/scripting/java/docs/help-doc.html
new file mode 100644
index 000000000..fff93ccd0
--- /dev/null
+++ b/scripting/java/docs/help-doc.html
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:31 EDT 2003 -->
+<TITLE>
+API Help
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="API Help";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+How This API Document Is Organized</H1>
+</CENTER>
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.<H3>
+Package</H3>
+<BLOCKQUOTE>
+
+<P>
+Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:<UL>
+<LI>Interfaces (italic)<LI>Classes<LI>Exceptions<LI>Errors</UL>
+</BLOCKQUOTE>
+<H3>
+Class/Interface</H3>
+<BLOCKQUOTE>
+
+<P>
+Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:<UL>
+<LI>Class inheritance diagram<LI>Direct Subclasses<LI>All Known Subinterfaces<LI>All Known Implementing Classes<LI>Class/interface declaration<LI>Class/interface description
+<P>
+<LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
+<P>
+<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
+Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE>
+<H3>
+Tree (Class Hierarchy)</H3>
+<BLOCKQUOTE>
+There is a <A HREF="overview-tree.html">Class Hierarchy</A> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.<UL>
+<LI>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.<LI>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</UL>
+</BLOCKQUOTE>
+<H3>
+Deprecated API</H3>
+<BLOCKQUOTE>
+The <A HREF="deprecated-list.html">Deprecated API</A> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</BLOCKQUOTE>
+<H3>
+Index</H3>
+<BLOCKQUOTE>
+The <A HREF="index-all.html">Index</A> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</BLOCKQUOTE>
+<H3>
+Prev/Next</H3>
+These links take you to the next or previous class, interface, package, or related page.<H3>
+Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+<P>
+<H3>
+Serialized Form</H3>
+Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
+<P>
+<FONT SIZE="-1">
+<EM>
+This help file applies to API documentation generated using the standard doclet.</EM>
+</FONT>
+<BR>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/index-all.html b/scripting/java/docs/index-all.html
new file mode 100644
index 000000000..508bf6f8b
--- /dev/null
+++ b/scripting/java/docs/index-all.html
@@ -0,0 +1,1603 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:29 EDT 2003 -->
+<TITLE>
+Index
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Index";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<A HREF="#_A_">A</A> <A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_F_">F</A> <A HREF="#_G_">G</A> <A HREF="#_H_">H</A> <A HREF="#_I_">I</A> <A HREF="#_J_">J</A> <A HREF="#_L_">L</A> <A HREF="#_M_">M</A> <A HREF="#_N_">N</A> <A HREF="#_O_">O</A> <A HREF="#_P_">P</A> <A HREF="#_Q_">Q</A> <A HREF="#_R_">R</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> <A HREF="#_U_">U</A> <A HREF="#_V_">V</A> <A HREF="#_W_">W</A> <HR>
+<A NAME="_A_"><!-- --></A><H2>
+<B>A</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#ACTIVATE_PRINTER"><B>ACTIVATE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#activity"><B>activity</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#addAttribute(org.cups.IPPAttribute)"><B>addAttribute(IPPAttribute)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Add an attribute to the attibutes list
+ for later parsing.
+<DT><A HREF="org/cups/IPPAttribute.html#addBoolean(boolean)"><B>addBoolean(boolean)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addBooleans(boolean[])"><B>addBooleans(boolean[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addDate(char[])"><B>addDate(char[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addEnum(int)"><B>addEnum(int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addInteger(int)"><B>addInteger(int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addIntegers(int[])"><B>addIntegers(int[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addRange(int, int)"><B>addRange(int, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addRanges(int[], int[])"><B>addRanges(int[], int[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addResolution(byte, int, int)"><B>addResolution(byte, int, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addResolutions(byte, int[], int[])"><B>addResolutions(byte, int[], int[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addSeparator()"><B>addSeparator()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addString(java.lang.String, java.lang.String)"><B>addString(String, String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#addStrings(java.lang.String, java.lang.String[])"><B>addStrings(String, String[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#ATTRIBUTE"><B>ATTRIBUTE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#ATTRIBUTES"><B>ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#ATTRIBUTES_NOT_SETTABLE"><B>ATTRIBUTES_NOT_SETTABLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#attrs"><B>attrs</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#auth_type"><B>auth_type</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_B_"><!-- --></A><H2>
+<B>B</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#BAD_REQUEST"><B>BAD_REQUEST</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#br"><B>br</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_C_"><!-- --></A><H2>
+<B>C</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#CANCEL_CURRENT_JOB"><B>CANCEL_CURRENT_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CANCEL_JOB"><B>CANCEL_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CANCEL_SUBSCRIPTION"><B>CANCEL_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CHARSET"><B>CHARSET</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#checkForResponse()"><B>checkForResponse()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#COMPRESSION_ERROR"><B>COMPRESSION_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#COMPRESSION_NOT_SUPPORTED"><B>COMPRESSION_NOT_SUPPORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CONFLICT"><B>CONFLICT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#conn"><B>conn</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPURLConnection.html#connect()"><B>connect()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPURLConnection.html">IPPURLConnection</A>
+<DD>Not used.
+<DT><A HREF="org/cups/IPPHttp.html#connected"><B>connected</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CREATE_JOB"><B>CREATE_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CREATE_JOB_SUBSCRIPTION"><B>CREATE_JOB_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CREATE_PRINTER_SUBSCRIPTION"><B>CREATE_PRINTER_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/Cups.html"><B>Cups</B></A> - class org.cups.<A HREF="org/cups/Cups.html">Cups</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPDefs.html#CUPS_ACCEPT_JOBS"><B>CUPS_ACCEPT_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_ADD_CLASS"><B>CUPS_ADD_CLASS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_ADD_DEVICE"><B>CUPS_ADD_DEVICE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_ADD_PRINTER"><B>CUPS_ADD_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_DELETE_CLASS"><B>CUPS_DELETE_CLASS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_DELETE_DEVICE"><B>CUPS_DELETE_DEVICE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_DELETE_PRINTER"><B>CUPS_DELETE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_GET_CLASSES"><B>CUPS_GET_CLASSES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_GET_DEFAULT"><B>CUPS_GET_DEFAULT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_GET_DEVICES"><B>CUPS_GET_DEVICES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_GET_PPDS"><B>CUPS_GET_PPDS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_GET_PRINTERS"><B>CUPS_GET_PRINTERS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_MOVE_JOB"><B>CUPS_MOVE_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_REJECT_JOBS"><B>CUPS_REJECT_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#CUPS_SET_DEFAULT"><B>CUPS_SET_DEFAULT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/Cups.html#Cups()"><B>Cups()</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Void constructor.
+<DT><A HREF="org/cups/Cups.html#Cups(java.net.URL)"><B>Cups(URL)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Constructor using a <code>URL</code>.
+<DT><A HREF="org/cups/Cups.html#cupsCancelJob(java.lang.String, int, java.lang.String)"><B>cupsCancelJob(String, int, String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Cancel a job - send a job cancel request to the server.
+<DT><A HREF="org/cups/Cups.html#cupsGetDefault()"><B>cupsGetDefault()</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Get default destination.
+<DT><A HREF="org/cups/Cups.html#cupsGetJobs(boolean, boolean)"><B>cupsGetJobs(boolean, boolean)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Get a list of jobs.
+<DT><A HREF="org/cups/Cups.html#cupsGetPrinterAttributes(java.lang.String)"><B>cupsGetPrinterAttributes(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Get printer attributes
+<DT><A HREF="org/cups/Cups.html#cupsGetPrinters()"><B>cupsGetPrinters()</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Get a list of printers.
+<DT><A HREF="org/cups/Cups.html#cupsGetPrinterStatus(java.lang.String)"><B>cupsGetPrinterStatus(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html"><B>CupsJob</B></A> - class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>.<DD>&nbsp;<DT><A HREF="org/cups/CupsJob.html#CupsJob()"><B>CupsJob()</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>Constructor - set some default values.
+<DT><A HREF="org/cups/CupsPrinter.html"><B>CupsPrinter</B></A> - class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>.<DD>&nbsp;<DT><A HREF="org/cups/CupsPrinter.html#CupsPrinter(org.cups.Cups)"><B>CupsPrinter(Cups)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Constructor.
+<DT><A HREF="org/cups/CupsPrinter.html#CupsPrinter(org.cups.Cups, java.lang.String)"><B>CupsPrinter(Cups, String)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Constructor with name.
+<DT><A HREF="org/cups/Cups.html#cupsPrintFile(java.lang.String, org.cups.IPPAttribute[])"><B>cupsPrintFile(String, IPPAttribute[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Print a file.
+</DL>
+<HR>
+<A NAME="_D_"><!-- --></A><H2>
+<B>D</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#DATA"><B>DATA</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#days"><B>days</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#DEACTIVATE_PRINTER"><B>DEACTIVATE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#DEVICE_ERROR"><B>DEVICE_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#DISABLE_PRINTER"><B>DISABLE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPURLConnection.html#disconnect()"><B>disconnect()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPURLConnection.html">IPPURLConnection</A>
+<DD>Not used.
+<DT><A HREF="org/cups/IPPDefs.html#DOCUMENT_ACCESS_ERROR"><B>DOCUMENT_ACCESS_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#document_format"><B>document_format</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#DOCUMENT_FORMAT"><B>DOCUMENT_FORMAT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#DOCUMENT_FORMAT_ERROR"><B>DOCUMENT_FORMAT_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/Cups.html#doRequest()"><B>doRequest()</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Do a CUPS request to the server.
+<DT><A HREF="org/cups/Cups.html#doRequest(java.io.File)"><B>doRequest(File)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Send a FILE to the CUPS server.
+<DT><A HREF="org/cups/Cups.html#doRequest(java.lang.String)"><B>doRequest(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#dump_response()"><B>dump_response()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html#dump_values()"><B>dump_values()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_E_"><!-- --></A><H2>
+<B>E</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#ENABLE_PRINTER"><B>ENABLE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#error"><B>error</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#ERROR"><B>ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#ERROR_JOB_CANCELLED"><B>ERROR_JOB_CANCELLED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_F_"><!-- --></A><H2>
+<B>F</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BALE"><B>FINISHINGS_BALE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BIND"><B>FINISHINGS_BIND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BIND_BOTTOM"><B>FINISHINGS_BIND_BOTTOM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BIND_LEFT"><B>FINISHINGS_BIND_LEFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BIND_RIGHT"><B>FINISHINGS_BIND_RIGHT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BIND_TOP"><B>FINISHINGS_BIND_TOP</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_BOOKLET_MAKER"><B>FINISHINGS_BOOKLET_MAKER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_COVER"><B>FINISHINGS_COVER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH"><B>FINISHINGS_EDGE_STITCH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_BOTTOM"><B>FINISHINGS_EDGE_STITCH_BOTTOM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_LEFT"><B>FINISHINGS_EDGE_STITCH_LEFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_RIGHT"><B>FINISHINGS_EDGE_STITCH_RIGHT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_TOP"><B>FINISHINGS_EDGE_STITCH_TOP</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_FOLD"><B>FINISHINGS_FOLD</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_JOB_OFFSET"><B>FINISHINGS_JOB_OFFSET</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_NONE"><B>FINISHINGS_NONE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_PUNCH"><B>FINISHINGS_PUNCH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_SADDLE_STITCH"><B>FINISHINGS_SADDLE_STITCH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE"><B>FINISHINGS_STAPLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_BOTTOM_LEFT"><B>FINISHINGS_STAPLE_BOTTOM_LEFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_BOTTOM_RIGHT"><B>FINISHINGS_STAPLE_BOTTOM_RIGHT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_BOTTOM"><B>FINISHINGS_STAPLE_DUAL_BOTTOM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_LEFT"><B>FINISHINGS_STAPLE_DUAL_LEFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_RIGHT"><B>FINISHINGS_STAPLE_DUAL_RIGHT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_TOP"><B>FINISHINGS_STAPLE_DUAL_TOP</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_TOP_LEFT"><B>FINISHINGS_STAPLE_TOP_LEFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_STAPLE_TOP_RIGHT"><B>FINISHINGS_STAPLE_TOP_RIGHT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FINISHINGS_TRIM"><B>FINISHINGS_TRIM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#FORBIDDEN"><B>FORBIDDEN</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_G_"><!-- --></A><H2>
+<B>G</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#GET_JOB_ATTRIBUTES"><B>GET_JOB_ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_JOBS"><B>GET_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_NOTIFICATIONS"><B>GET_NOTIFICATIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_PRINT_SUPPORT_FILES"><B>GET_PRINT_SUPPORT_FILES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_PRINTER_ATTRIBUTES"><B>GET_PRINTER_ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_PRINTER_SUPPORTED_VALUES"><B>GET_PRINTER_SUPPORTED_VALUES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_SUBSCRIPTION_ATTRIBUTES"><B>GET_SUBSCRIPTION_ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#GET_SUBSCRIPTIONS"><B>GET_SUBSCRIPTIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsPrinter.html#getAttributes(org.cups.Cups)"><B>getAttributes(Cups)</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer's attributes.
+<DT><A HREF="org/cups/IPPAttribute.html#getBytes(int, int)"><B>getBytes(int, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsPrinter.html#getCopiesDefault()"><B>getCopiesDefault()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer number of copies default.
+<DT><A HREF="org/cups/IPP.html#getCurrentAttribute()"><B>getCurrentAttribute()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Get the current attribute pointed at by
+ <code>current</code>.
+<DT><A HREF="org/cups/Cups.html#getEncrypt()"><B>getEncrypt()</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Get the value of the <code>encrypt</code> member.
+<DT><A HREF="org/cups/CupsPrinter.html#getJobSheetsDefault()"><B>getJobSheetsDefault()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the default job sheets.
+<DT><A HREF="org/cups/CupsPrinter.html#getJobSheetsSupported()"><B>getJobSheetsSupported()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer job sheets supported.
+<DT><A HREF="org/cups/CupsPrinter.html#getLocation()"><B>getLocation()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer location.
+<DT><A HREF="org/cups/CupsPrinter.html#getLowerCopiesSupported()"><B>getLowerCopiesSupported()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer lower copies supported.
+<DT><A HREF="org/cups/CupsPrinter.html#getMakeAndModel()"><B>getMakeAndModel()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer make and model.
+<DT><A HREF="org/cups/CupsPrinter.html#getOrientationDefault()"><B>getOrientationDefault()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the default orientation.
+<DT><A HREF="org/cups/CupsPrinter.html#getOrientationSupported()"><B>getOrientationSupported()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer orientation supported.
+<DT><A HREF="org/cups/CupsPrinter.html#getPageRangesSupported()"><B>getPageRangesSupported()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get whether the printer supports page ranges.
+<DT><A HREF="org/cups/CupsPrinter.html#getPrinterName()"><B>getPrinterName()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer name.
+<DT><A HREF="org/cups/CupsPrinter.html#getStateReasons()"><B>getStateReasons()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer state reasons.
+<DT><A HREF="org/cups/CupsPrinter.html#getStateText()"><B>getStateText()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer state text.
+<DT><A HREF="org/cups/CupsPrinter.html#getStatus(org.cups.Cups)"><B>getStatus(Cups)</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer's status.
+<DT><A HREF="org/cups/CupsPrinter.html#getUpperCopiesSupported()"><B>getUpperCopiesSupported()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Get the printer upper copies supported.
+<DT><A HREF="org/cups/IPPDefs.html#GONE"><B>GONE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_H_"><!-- --></A><H2>
+<B>H</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#HEADER"><B>HEADER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#HOLD_JOB"><B>HOLD_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#HOLD_NEW_JOBS"><B>HOLD_NEW_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#hostname"><B>hostname</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_0_9"><B>HTTP_0_9</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_1_0"><B>HTTP_1_0</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_1_1"><B>HTTP_1_1</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ACCEPTED"><B>HTTP_ACCEPTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_BASIC"><B>HTTP_AUTH_BASIC</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_MD5"><B>HTTP_AUTH_MD5</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_MD5_INT"><B>HTTP_AUTH_MD5_INT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_MD5_SESS"><B>HTTP_AUTH_MD5_SESS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_MD5_SESS_INT"><B>HTTP_AUTH_MD5_SESS_INT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_AUTH_NONE"><B>HTTP_AUTH_NONE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_BAD_GATEWAY"><B>HTTP_BAD_GATEWAY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_BAD_REQUEST"><B>HTTP_BAD_REQUEST</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_CLOSE"><B>HTTP_CLOSE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_CONFLICT"><B>HTTP_CONFLICT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#http_content_length"><B>http_content_length</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_CONTINUE"><B>HTTP_CONTINUE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_CREATED"><B>HTTP_CREATED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_DELETE"><B>HTTP_DELETE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCODE_CHUNKED"><B>HTTP_ENCODE_CHUNKED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCODE_LENGTH"><B>HTTP_ENCODE_LENGTH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCRYPT_ALWAYS"><B>HTTP_ENCRYPT_ALWAYS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCRYPT_IF_REQUESTED"><B>HTTP_ENCRYPT_IF_REQUESTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCRYPT_NEVER"><B>HTTP_ENCRYPT_NEVER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ENCRYPT_REQUIRED"><B>HTTP_ENCRYPT_REQUIRED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_ERROR"><B>HTTP_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_ACCEPT_LANGUAGE"><B>HTTP_FIELD_ACCEPT_LANGUAGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_ACCEPT_RANGES"><B>HTTP_FIELD_ACCEPT_RANGES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_AUTHORIZATION"><B>HTTP_FIELD_AUTHORIZATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONNECTION"><B>HTTP_FIELD_CONNECTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_ENCODING"><B>HTTP_FIELD_CONTENT_ENCODING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LANGUAGE"><B>HTTP_FIELD_CONTENT_LANGUAGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LENGTH"><B>HTTP_FIELD_CONTENT_LENGTH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LOCATION"><B>HTTP_FIELD_CONTENT_LOCATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_MD5"><B>HTTP_FIELD_CONTENT_MD5</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_RANGE"><B>HTTP_FIELD_CONTENT_RANGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_TYPE"><B>HTTP_FIELD_CONTENT_TYPE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_VERSION"><B>HTTP_FIELD_CONTENT_VERSION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_DATE"><B>HTTP_FIELD_DATE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_HOST"><B>HTTP_FIELD_HOST</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_IF_MODIFIED_SINCE"><B>HTTP_FIELD_IF_MODIFIED_SINCE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_IF_UNMODIFIED_SINCE"><B>HTTP_FIELD_IF_UNMODIFIED_SINCE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_KEEP_ALIVE"><B>HTTP_FIELD_KEEP_ALIVE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_LAST_MODIFIED"><B>HTTP_FIELD_LAST_MODIFIED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_LINK"><B>HTTP_FIELD_LINK</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_LOCATION"><B>HTTP_FIELD_LOCATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_MAX"><B>HTTP_FIELD_MAX</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_RANGE"><B>HTTP_FIELD_RANGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_REFERER"><B>HTTP_FIELD_REFERER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_RETRY_AFTER"><B>HTTP_FIELD_RETRY_AFTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_TRANSFER_ENCODING"><B>HTTP_FIELD_TRANSFER_ENCODING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_UNKNOWN"><B>HTTP_FIELD_UNKNOWN</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_UPGRADE"><B>HTTP_FIELD_UPGRADE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_USER_AGENT"><B>HTTP_FIELD_USER_AGENT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FIELD_WWW_AUTHENTICATE"><B>HTTP_FIELD_WWW_AUTHENTICATE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#http_fields"><B>http_fields</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_FORBIDDEN"><B>HTTP_FORBIDDEN</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_GATEWAY_TIMEOUT"><B>HTTP_GATEWAY_TIMEOUT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_GET"><B>HTTP_GET</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_GET_SEND"><B>HTTP_GET_SEND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_GONE"><B>HTTP_GONE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_HEAD"><B>HTTP_HEAD</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_KEEPALIVE_OFF"><B>HTTP_KEEPALIVE_OFF</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_KEEPALIVE_ON"><B>HTTP_KEEPALIVE_ON</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_LENGTH_REQUIRED"><B>HTTP_LENGTH_REQUIRED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_METHOD_NOT_ALLOWED"><B>HTTP_METHOD_NOT_ALLOWED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_MOVED_PERMANENTLY"><B>HTTP_MOVED_PERMANENTLY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_MOVED_TEMPORARILY"><B>HTTP_MOVED_TEMPORARILY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_MULTIPLE_CHOICES"><B>HTTP_MULTIPLE_CHOICES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NO_CONTENT"><B>HTTP_NO_CONTENT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_ACCEPTABLE"><B>HTTP_NOT_ACCEPTABLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_AUTHORITATIVE"><B>HTTP_NOT_AUTHORITATIVE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_FOUND"><B>HTTP_NOT_FOUND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_IMPLEMENTED"><B>HTTP_NOT_IMPLEMENTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_MODIFIED"><B>HTTP_NOT_MODIFIED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_NOT_SUPPORTED"><B>HTTP_NOT_SUPPORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_OK"><B>HTTP_OK</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_OPTIONS"><B>HTTP_OPTIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PARTIAL_CONTENT"><B>HTTP_PARTIAL_CONTENT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PAYMENT_REQUIRED"><B>HTTP_PAYMENT_REQUIRED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_POST"><B>HTTP_POST</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_POST_RECV"><B>HTTP_POST_RECV</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_POST_SEND"><B>HTTP_POST_SEND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PRECONDITION"><B>HTTP_PRECONDITION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PROXY_AUTHENTICATION"><B>HTTP_PROXY_AUTHENTICATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PUT"><B>HTTP_PUT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_PUT_RECV"><B>HTTP_PUT_RECV</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#http_request"><B>http_request</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_REQUEST_TIMEOUT"><B>HTTP_REQUEST_TIMEOUT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_REQUEST_TOO_LARGE"><B>HTTP_REQUEST_TOO_LARGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_RESET_CONTENT"><B>HTTP_RESET_CONTENT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_SEE_OTHER"><B>HTTP_SEE_OTHER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_SERVER_ERROR"><B>HTTP_SERVER_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_SERVICE_UNAVAILABLE"><B>HTTP_SERVICE_UNAVAILABLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_STATUS"><B>HTTP_STATUS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_SWITCHING_PROTOCOLS"><B>HTTP_SWITCHING_PROTOCOLS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_TRACE"><B>HTTP_TRACE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_UNAUTHORIZED"><B>HTTP_UNAUTHORIZED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_UNSUPPORTED_MEDIATYPE"><B>HTTP_UNSUPPORTED_MEDIATYPE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_UPGRADE_REQUIRED"><B>HTTP_UPGRADE_REQUIRED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_URI_TOO_LONG"><B>HTTP_URI_TOO_LONG</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_USE_PROXY"><B>HTTP_USE_PROXY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#HTTP_WAITING"><B>HTTP_WAITING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Class constants - most not in use yet.
+</DL>
+<HR>
+<A NAME="_I_"><!-- --></A><H2>
+<B>I</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#IDLE"><B>IDLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#IGNORED_ALL_NOTIFICATIONS"><B>IGNORED_ALL_NOTIFICATIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#IGNORED_ALL_SUBSCRIPTIONS"><B>IGNORED_ALL_SUBSCRIPTIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#INTERNAL_ERROR"><B>INTERNAL_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html"><B>IPP</B></A> - class org.cups.<A HREF="org/cups/IPP.html">IPP</A>.<DD>An <code>IPP</code> object is used to hold the various
+ attributes and status of an ipp request..<DT><A HREF="org/cups/IPP.html#IPP()"><B>IPP()</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPAttribute.html"><B>IPPAttribute</B></A> - class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPAttribute.html#IPPAttribute(int, int, java.lang.String)"><B>IPPAttribute(int, int, String)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPValue.html#IPPDateToTime()"><B>IPPDateToTime()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Convert an IPP Date value to Unix Time.
+<DT><A HREF="org/cups/IPPDefs.html"><B>IPPDefs</B></A> - class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>.<DD><code>IPPDefs</code> is a collection of constants for use
+ in the <code>IPP</code> and <code>CUPS</code> classes.<DT><A HREF="org/cups/IPPDefs.html#IPPDefs()"><B>IPPDefs()</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPError.html"><B>IPPError</B></A> - class org.cups.<A HREF="org/cups/IPPError.html">IPPError</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPError.html#IPPError(int)"><B>IPPError(int)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPError.html">IPPError</A>
+<DD>Constructor that sets <code>error_string</code> after creation.
+<DT><A HREF="org/cups/IPP.html#ippFindAttribute(java.lang.String, int)"><B>ippFindAttribute(String, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Find the named attribute of the correct type.
+<DT><A HREF="org/cups/IPP.html#ippFindNextAttribute(java.lang.String, int)"><B>ippFindNextAttribute(String, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Find the named attribute of the correct type.
+<DT><A HREF="org/cups/IPPHttp.html"><B>IPPHttp</B></A> - class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPHttp.html#IPPHttp(java.lang.String)"><B>IPPHttp(String)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Constructor using <code>URL</code>.
+<DT><A HREF="org/cups/IPPHttp.html#IPPHttp(java.lang.String, java.lang.String, java.lang.String, java.lang.String)"><B>IPPHttp(String, String, String, String)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Constructor using <code>URL, user and pass</code>.
+<DT><A HREF="org/cups/IPPRequest.html"><B>IPPRequest</B></A> - class org.cups.<A HREF="org/cups/IPPRequest.html">IPPRequest</A>.<DD>An <code>IPPRequest</code> object is used to hold the
+ status and id's of a request.<DT><A HREF="org/cups/IPPRequest.html#IPPRequest()"><B>IPPRequest()</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPRequest.html">IPPRequest</A>
+<DD>Constructor
+<DT><A HREF="org/cups/IPPRequest.html#IPPRequest(int, short)"><B>IPPRequest(int, short)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPRequest.html">IPPRequest</A>
+<DD>Constructor using request id and operation id.
+<DT><A HREF="org/cups/IPPStatus.html"><B>IPPStatus</B></A> - class org.cups.<A HREF="org/cups/IPPStatus.html">IPPStatus</A>.<DD>Class to convert a status code to text.<DT><A HREF="org/cups/IPPStatus.html#IPPStatus(int)"><B>IPPStatus(int)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPStatus.html">IPPStatus</A>
+<DD>Constructor, access the <code>status_text</code> member
+ after creation.
+<DT><A HREF="org/cups/IPPURLConnection.html"><B>IPPURLConnection</B></A> - class org.cups.<A HREF="org/cups/IPPURLConnection.html">IPPURLConnection</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPURLConnection.html#IPPURLConnection(java.net.URL)"><B>IPPURLConnection(URL)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPURLConnection.html">IPPURLConnection</A>
+<DD>Constructor.
+<DT><A HREF="org/cups/IPPValue.html"><B>IPPValue</B></A> - class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>.<DD>&nbsp;<DT><A HREF="org/cups/IPPValue.html#IPPValue(boolean)"><B>IPPValue(boolean)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Boolean constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(byte)"><B>IPPValue(byte)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Byte constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(byte, int, int)"><B>IPPValue(byte, int, int)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Resolution constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(char[])"><B>IPPValue(char[])</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Date constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(int)"><B>IPPValue(int)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Integer constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(int, boolean)"><B>IPPValue(int, boolean)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Enum constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(int, char[])"><B>IPPValue(int, char[])</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Raw data constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(int, int)"><B>IPPValue(int, int)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Range constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(short)"><B>IPPValue(short)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>Short constructor.
+<DT><A HREF="org/cups/IPPValue.html#IPPValue(java.lang.String, java.lang.String)"><B>IPPValue(String, String)</B></A> -
+Constructor for class org.cups.<A HREF="org/cups/IPPValue.html">IPPValue</A>
+<DD>String constructor.
+<DT><A HREF="org/cups/IPPHttp.html#is"><B>is</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_J_"><!-- --></A><H2>
+<B>J</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#JOB_ABORTED"><B>JOB_ABORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_CANCELLED"><B>JOB_CANCELLED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_COMPLETED"><B>JOB_COMPLETED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_HELD"><B>JOB_HELD</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_hold_until"><B>job_hold_until</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_id"><B>job_id</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_k_octets"><B>job_k_octets</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_media_sheets_completed"><B>job_media_sheets_completed</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_more_info"><B>job_more_info</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_name"><B>job_name</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_originating_host_name"><B>job_originating_host_name</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_originating_user_name"><B>job_originating_user_name</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_PENDING"><B>JOB_PENDING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_printer_up_time"><B>job_printer_up_time</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_printer_uri"><B>job_printer_uri</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_priority"><B>job_priority</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_PROCESSING"><B>JOB_PROCESSING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_sheets"><B>job_sheets</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_state"><B>job_state</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_state_reasons"><B>job_state_reasons</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#JOB_STOPPED"><B>JOB_STOPPED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#job_uri"><B>job_uri</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#jobStatusText()"><B>jobStatusText()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>Convert a job status to a string.
+</DL>
+<HR>
+<A NAME="_L_"><!-- --></A><H2>
+<B>L</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#LANDSCAPE"><B>LANDSCAPE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_M_"><!-- --></A><H2>
+<B>M</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#MAX_NAME"><B>MAX_NAME</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#MAX_VALUES"><B>MAX_VALUES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#method"><B>method</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#months"><B>months</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#MULTIPLE_JOBS_NOT_SUPPORTED"><B>MULTIPLE_JOBS_NOT_SUPPORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_N_"><!-- --></A><H2>
+<B>N</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPHttp.html#nonce"><B>nonce</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#NOT_ACCEPTING"><B>NOT_ACCEPTING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#NOT_AUTHENTICATED"><B>NOT_AUTHENTICATED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#NOT_AUTHORIZED"><B>NOT_AUTHORIZED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#NOT_FOUND"><B>NOT_FOUND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#NOT_POSSIBLE"><B>NOT_POSSIBLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_O_"><!-- --></A><H2>
+<B>O</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#OK"><B>OK</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_BUT_CANCEL_SUBSCRIPTION"><B>OK_BUT_CANCEL_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_CONFLICT"><B>OK_CONFLICT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_IGNORED_NOTIFICATIONS"><B>OK_IGNORED_NOTIFICATIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_IGNORED_SUBSCRIPTIONS"><B>OK_IGNORED_SUBSCRIPTIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_SUBST"><B>OK_SUBST</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OK_TOO_MANY_EVENTS"><B>OK_TOO_MANY_EVENTS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#opaque"><B>opaque</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#OPERATION_NOT_SUPPORTED"><B>OPERATION_NOT_SUPPORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/package-summary.html"><B>org.cups</B></A> - package org.cups<DD>&nbsp;<DT><A HREF="org/cups/IPPHttp.html#os"><B>os</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_P_"><!-- --></A><H2>
+<B>P</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPHttp.html#parseAuthenticate(java.lang.String)"><B>parseAuthenticate(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#passwd"><B>passwd</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#path"><B>path</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PAUSE_PRINTER"><B>PAUSE_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PAUSE_PRINTER_AFTER_CURRENT_JOB"><B>PAUSE_PRINTER_AFTER_CURRENT_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#port"><B>port</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PORT"><B>PORT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PORTRAIT"><B>PORTRAIT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINT_JOB"><B>PRINT_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINT_SUPPORT_FILE_NOT_FOUND"><B>PRINT_SUPPORT_FILE_NOT_FOUND</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINT_URI"><B>PRINT_URI</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINTER_BUSY"><B>PRINTER_BUSY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINTER_IDLE"><B>PRINTER_IDLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINTER_IS_DEACTIVATED"><B>PRINTER_IS_DEACTIVATED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINTER_PROCESSING"><B>PRINTER_PROCESSING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRINTER_STOPPED"><B>PRINTER_STOPPED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PRIVATE"><B>PRIVATE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#processResponse()"><B>processResponse()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Process the HTTP response from the server.
+<DT><A HREF="org/cups/IPPDefs.html#PROMOTE_JOB"><B>PROMOTE_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#PURGE_JOBS"><B>PURGE_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_Q_"><!-- --></A><H2>
+<B>Q</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#QUALITY_DRAFT"><B>QUALITY_DRAFT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#QUALITY_HIGH"><B>QUALITY_HIGH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#QUALITY_NORMAL"><B>QUALITY_NORMAL</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_R_"><!-- --></A><H2>
+<B>R</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPHttp.html#read_buffer"><B>read_buffer</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_charset"><B>read_header_charset</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_content_language"><B>read_header_content_language</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_content_length"><B>read_header_content_length</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_content_type"><B>read_header_content_type</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_date"><B>read_header_date</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header_server"><B>read_header_server</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#read_header()"><B>read_header()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Read the HTTP header from the input stream.
+<DT><A HREF="org/cups/IPPHttp.html#read_line()"><B>read_line()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Read a line from the input stream.
+<DT><A HREF="org/cups/IPPHttp.html#read(int)"><B>read(int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Read up to <code>count</code> bytes from the input stream.
+<DT><A HREF="org/cups/IPPHttp.html#realm"><B>realm</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#reConnect()"><B>reConnect()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Re-establish a dropped connection.
+<DT><A HREF="org/cups/IPPDefs.html#REDIRECTION_OTHER_SITE"><B>REDIRECTION_OTHER_SITE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RELEASE_HELD_NEW_JOBS"><B>RELEASE_HELD_NEW_JOBS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RELEASE_JOB"><B>RELEASE_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RENEW_SUBSCRIPTION"><B>RENEW_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#REPROCESS_JOB"><B>REPROCESS_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#request"><B>request</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#REQUEST_ENTITY"><B>REQUEST_ENTITY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#REQUEST_VALUE"><B>REQUEST_VALUE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RES_PER_CM"><B>RES_PER_CM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RES_PER_INCH"><B>RES_PER_INCH</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#resource"><B>resource</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RESTART_JOB"><B>RESTART_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RESTART_PRINTER"><B>RESTART_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RESUME_JOB"><B>RESUME_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#RESUME_PRINTER"><B>RESUME_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#REVERSE_LANDSCAPE"><B>REVERSE_LANDSCAPE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#REVERSE_PORTRAIT"><B>REVERSE_PORTRAIT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_S_"><!-- --></A><H2>
+<B>S</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#SCHEDULE_JOB_AFTER"><B>SCHEDULE_JOB_AFTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SEND_DOCUMENT"><B>SEND_DOCUMENT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SEND_NOTIFICATIONS"><B>SEND_NOTIFICATIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SEND_URI"><B>SEND_URI</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SERVICE_UNAVAILABLE"><B>SERVICE_UNAVAILABLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SET_JOB_ATTRIBUTES"><B>SET_JOB_ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SET_PRINTER_ATTRIBUTES"><B>SET_PRINTER_ATTRIBUTES</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsPrinter.html#setDefaults()"><B>setDefaults()</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Initialize the members with mostly sane values.
+<DT><A HREF="org/cups/Cups.html#setDest(java.lang.String)"><B>setDest(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>dest</code> member.
+<DT><A HREF="org/cups/Cups.html#setEncrypt(boolean)"><B>setEncrypt(boolean)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>encrypt</code> member.
+<DT><A HREF="org/cups/Cups.html#setInstance(java.lang.String)"><B>setInstance(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>instance</code> member.
+<DT><A HREF="org/cups/IPPRequest.html#setOpStatus(short)"><B>setOpStatus(short)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPRequest.html">IPPRequest</A>
+<DD>Set the operation status of a request.
+<DT><A HREF="org/cups/Cups.html#setPasswd(java.lang.String)"><B>setPasswd(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>passwd</code> member.
+<DT><A HREF="org/cups/IPPHttp.html#setPassword(java.lang.String)"><B>setPassword(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Set the password.
+<DT><A HREF="org/cups/Cups.html#setPath(java.lang.String)"><B>setPath(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>path</code> member.
+<DT><A HREF="org/cups/Cups.html#setPort(int)"><B>setPort(int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>port</code> member.
+<DT><A HREF="org/cups/Cups.html#setProtocol(java.lang.String)"><B>setProtocol(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>protocol</code> member.
+<DT><A HREF="org/cups/IPP.html#setRequestID(short)"><B>setRequestID(short)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Set the <code>IPP</code> request ID.
+<DT><A HREF="org/cups/IPP.html#setRequestOperationID(short)"><B>setRequestOperationID(short)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Set the <code>IPP</code> operation ID.
+<DT><A HREF="org/cups/Cups.html#setServer(java.lang.String)"><B>setServer(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>server</code> member.
+<DT><A HREF="org/cups/IPPRequest.html#setStatus(short)"><B>setStatus(short)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPRequest.html">IPPRequest</A>
+<DD>Set the current status of a request.
+<DT><A HREF="org/cups/IPPHttp.html#setUser(java.lang.String)"><B>setUser(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Set the user name.
+<DT><A HREF="org/cups/Cups.html#setUser(java.lang.String)"><B>setUser(String)</B></A> -
+Method in class org.cups.<A HREF="org/cups/Cups.html">Cups</A>
+<DD>Set the value of the <code>user</code> member.
+<DT><A HREF="org/cups/IPPDefs.html#SHUTDOWN_PRINTER"><B>SHUTDOWN_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#sizeInBytes()"><B>sizeInBytes()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>Get the size in bytes of an <code>IPP</code> request.
+<DT><A HREF="org/cups/IPPAttribute.html#sizeInBytes(int)"><B>sizeInBytes(int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPAttribute.html">IPPAttribute</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#STARTUP_PRINTER"><B>STARTUP_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPP.html#status"><B>status</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPP.html">IPP</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#status"><B>status</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#status_text"><B>status_text</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#SUSPEND_CURRENT_JOB"><B>SUSPEND_CURRENT_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_T_"><!-- --></A><H2>
+<B>T</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#TAG_ADMINDEFINE"><B>TAG_ADMINDEFINE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_BEGIN_COLLECTION"><B>TAG_BEGIN_COLLECTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_BOOLEAN"><B>TAG_BOOLEAN</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_CHARSET"><B>TAG_CHARSET</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_COPY"><B>TAG_COPY</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_DATE"><B>TAG_DATE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_DEFAULT"><B>TAG_DEFAULT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_DELETEATTR"><B>TAG_DELETEATTR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_END"><B>TAG_END</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_END_COLLECTION"><B>TAG_END_COLLECTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_ENUM"><B>TAG_ENUM</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_EVENT_NOTIFICATION"><B>TAG_EVENT_NOTIFICATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_INTEGER"><B>TAG_INTEGER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_JOB"><B>TAG_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_KEYWORD"><B>TAG_KEYWORD</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_LANGUAGE"><B>TAG_LANGUAGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_MASK"><B>TAG_MASK</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_MEMBERNAME"><B>TAG_MEMBERNAME</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_MIMETYPE"><B>TAG_MIMETYPE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_NAME"><B>TAG_NAME</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_NAMELANG"><B>TAG_NAMELANG</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_NOTSETTABLE"><B>TAG_NOTSETTABLE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_NOVALUE"><B>TAG_NOVALUE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_OPERATION"><B>TAG_OPERATION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_PRINTER"><B>TAG_PRINTER</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_RANGE"><B>TAG_RANGE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_RESOLUTION"><B>TAG_RESOLUTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_STRING"><B>TAG_STRING</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_SUBSCRIPTION"><B>TAG_SUBSCRIPTION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_TEXT"><B>TAG_TEXT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_TEXTLANG"><B>TAG_TEXTLANG</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_UNKNOWN"><B>TAG_UNKNOWN</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_UNSUPPORTED_GROUP"><B>TAG_UNSUPPORTED_GROUP</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_UNSUPPORTED_VALUE"><B>TAG_UNSUPPORTED_VALUE</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_URI"><B>TAG_URI</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_URISCHEME"><B>TAG_URISCHEME</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TAG_ZERO"><B>TAG_ZERO</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TEMPORARY_ERROR"><B>TEMPORARY_ERROR</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#time_at_completed"><B>time_at_completed</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#time_at_creation"><B>time_at_creation</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/CupsJob.html#time_at_processing"><B>time_at_processing</B></A> -
+Variable in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TIMEOUT"><B>TIMEOUT</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#TOO_MANY_SUBSCRIPTIONS"><B>TOO_MANY_SUBSCRIPTIONS</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_U_"><!-- --></A><H2>
+<B>U</B></H2>
+<DL>
+<DT><A HREF="org/cups/CupsJob.html#updateAttribute(org.cups.IPPAttribute)"><B>updateAttribute(IPPAttribute)</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsJob.html">CupsJob</A>
+<DD>Process an attribute from a cups.doRequest() call
+ and move the value into a local member.
+<DT><A HREF="org/cups/CupsPrinter.html#updateAttribute(org.cups.IPPAttribute)"><B>updateAttribute(IPPAttribute)</B></A> -
+Method in class org.cups.<A HREF="org/cups/CupsPrinter.html">CupsPrinter</A>
+<DD>Process an attribute from the cups.doRequest() method and move
+ the values into local members.
+<DT><A HREF="org/cups/IPPDefs.html#URI_SCHEME"><B>URI_SCHEME</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#user"><B>user</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPURLConnection.html#usingProxy()"><B>usingProxy()</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPURLConnection.html">IPPURLConnection</A>
+<DD>Determine if using proxy.
+</DL>
+<HR>
+<A NAME="_V_"><!-- --></A><H2>
+<B>V</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPDefs.html#VALIDATE_JOB"><B>VALIDATE_JOB</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#version"><B>version</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#VERSION"><B>VERSION</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPDefs.html#VERSION_NOT_SUPPORTED"><B>VERSION_NOT_SUPPORTED</B></A> -
+Static variable in class org.cups.<A HREF="org/cups/IPPDefs.html">IPPDefs</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_W_"><!-- --></A><H2>
+<B>W</B></H2>
+<DL>
+<DT><A HREF="org/cups/IPPHttp.html#write_content_length"><B>write_content_length</B></A> -
+Variable in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>&nbsp;
+<DT><A HREF="org/cups/IPPHttp.html#write(byte[])"><B>write(byte[])</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Write bytes to the output stream.
+<DT><A HREF="org/cups/IPPHttp.html#write(byte[], int)"><B>write(byte[], int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Write bytes to the output stream.
+<DT><A HREF="org/cups/IPPHttp.html#writeHeader(java.lang.String, int)"><B>writeHeader(String, int)</B></A> -
+Method in class org.cups.<A HREF="org/cups/IPPHttp.html">IPPHttp</A>
+<DD>Write the request header bytes to the server.
+</DL>
+<HR>
+<A HREF="#_A_">A</A> <A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_F_">F</A> <A HREF="#_G_">G</A> <A HREF="#_H_">H</A> <A HREF="#_I_">I</A> <A HREF="#_J_">J</A> <A HREF="#_L_">L</A> <A HREF="#_M_">M</A> <A HREF="#_N_">N</A> <A HREF="#_O_">O</A> <A HREF="#_P_">P</A> <A HREF="#_Q_">Q</A> <A HREF="#_R_">R</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> <A HREF="#_U_">U</A> <A HREF="#_V_">V</A> <A HREF="#_W_">W</A>
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/index.html b/scripting/java/docs/index.html
new file mode 100644
index 000000000..36763451a
--- /dev/null
+++ b/scripting/java/docs/index.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003-->
+<TITLE>
+Generated Documentation (Untitled)
+</TITLE>
+</HEAD>
+<FRAMESET cols="20%,80%">
+<FRAME src="allclasses-frame.html" name="packageFrame">
+<FRAME src="org/cups/package-summary.html" name="classFrame">
+</FRAMESET>
+<NOFRAMES>
+<H2>
+Frame Alert</H2>
+
+<P>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<BR>
+Link to<A HREF="org/cups/package-summary.html">Non-frame version.</A></NOFRAMES>
+</HTML>
diff --git a/scripting/java/docs/org/cups/Cups.html b/scripting/java/docs/org/cups/Cups.html
new file mode 100644
index 000000000..a20e2a1b7
--- /dev/null
+++ b/scripting/java/docs/org/cups/Cups.html
@@ -0,0 +1,692 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+Cups
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.Cups,Cups class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Cups";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="../../org/cups/CupsJob.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="Cups.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class Cups</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.Cups</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>Cups</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#Cups()">Cups</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Void constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#Cups(java.net.URL)">Cups</A></B>(java.net.URL&nbsp;p_url)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor using a <code>URL</code>.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsCancelJob(java.lang.String, int, java.lang.String)">cupsCancelJob</A></B>(java.lang.String&nbsp;printer_name,
+ int&nbsp;p_job_id,
+ java.lang.String&nbsp;p_user_name)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cancel a job - send a job cancel request to the server.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsGetDefault()">cupsGetDefault</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get default destination.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.CupsJob[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsGetJobs(boolean, boolean)">cupsGetJobs</A></B>(boolean&nbsp;showMyJobs,
+ boolean&nbsp;showCompleted)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get a list of jobs.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.List</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsGetPrinterAttributes(java.lang.String)">cupsGetPrinterAttributes</A></B>(java.lang.String&nbsp;printer_name)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get printer attributes</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsGetPrinters()">cupsGetPrinters</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get a list of printers.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.List</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsGetPrinterStatus(java.lang.String)">cupsGetPrinterStatus</A></B>(java.lang.String&nbsp;printer_name)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.CupsJob</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#cupsPrintFile(java.lang.String, org.cups.IPPAttribute[])">cupsPrintFile</A></B>(java.lang.String&nbsp;p_filename,
+ org.cups.IPPAttribute[]&nbsp;p_attrs)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Print a file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#doRequest()">doRequest</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Do a CUPS request to the server.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#doRequest(java.io.File)">doRequest</A></B>(java.io.File&nbsp;file)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Send a FILE to the CUPS server.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#doRequest(java.lang.String)">doRequest</A></B>(java.lang.String&nbsp;from)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#getEncrypt()">getEncrypt</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of the <code>encrypt</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setDest(java.lang.String)">setDest</A></B>(java.lang.String&nbsp;p_dest)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>dest</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setEncrypt(boolean)">setEncrypt</A></B>(boolean&nbsp;p_encrypt)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>encrypt</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setInstance(java.lang.String)">setInstance</A></B>(java.lang.String&nbsp;p_instance)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>instance</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setPasswd(java.lang.String)">setPasswd</A></B>(java.lang.String&nbsp;p_passwd)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>passwd</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setPath(java.lang.String)">setPath</A></B>(java.lang.String&nbsp;p_path)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>path</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setPort(int)">setPort</A></B>(int&nbsp;p_port)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>port</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setProtocol(java.lang.String)">setProtocol</A></B>(java.lang.String&nbsp;p_protocol)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>protocol</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setServer(java.lang.String)">setServer</A></B>(java.lang.String&nbsp;p_server)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>server</code> member.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/Cups.html#setUser(java.lang.String)">setUser</A></B>(java.lang.String&nbsp;p_user)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of the <code>user</code> member.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="Cups()"><!-- --></A><H3>
+Cups</H3>
+<PRE>
+public <B>Cups</B>()</PRE>
+<DL>
+<DD>Void constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="Cups(java.net.URL)"><!-- --></A><H3>
+Cups</H3>
+<PRE>
+public <B>Cups</B>(java.net.URL&nbsp;p_url)</PRE>
+<DL>
+<DD>Constructor using a <code>URL</code>.
+<P>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="setProtocol(java.lang.String)"><!-- --></A><H3>
+setProtocol</H3>
+<PRE>
+public void <B>setProtocol</B>(java.lang.String&nbsp;p_protocol)</PRE>
+<DL>
+<DD>Set the value of the <code>protocol</code> member. Valid values
+ are ipp or http.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setServer(java.lang.String)"><!-- --></A><H3>
+setServer</H3>
+<PRE>
+public void <B>setServer</B>(java.lang.String&nbsp;p_server)</PRE>
+<DL>
+<DD>Set the value of the <code>server</code> member. This is an
+ IP address or a hostname.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setPort(int)"><!-- --></A><H3>
+setPort</H3>
+<PRE>
+public void <B>setPort</B>(int&nbsp;p_port)</PRE>
+<DL>
+<DD>Set the value of the <code>port</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setUser(java.lang.String)"><!-- --></A><H3>
+setUser</H3>
+<PRE>
+public void <B>setUser</B>(java.lang.String&nbsp;p_user)</PRE>
+<DL>
+<DD>Set the value of the <code>user</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setPasswd(java.lang.String)"><!-- --></A><H3>
+setPasswd</H3>
+<PRE>
+public void <B>setPasswd</B>(java.lang.String&nbsp;p_passwd)</PRE>
+<DL>
+<DD>Set the value of the <code>passwd</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDest(java.lang.String)"><!-- --></A><H3>
+setDest</H3>
+<PRE>
+public void <B>setDest</B>(java.lang.String&nbsp;p_dest)</PRE>
+<DL>
+<DD>Set the value of the <code>dest</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setInstance(java.lang.String)"><!-- --></A><H3>
+setInstance</H3>
+<PRE>
+public void <B>setInstance</B>(java.lang.String&nbsp;p_instance)</PRE>
+<DL>
+<DD>Set the value of the <code>instance</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setEncrypt(boolean)"><!-- --></A><H3>
+setEncrypt</H3>
+<PRE>
+public void <B>setEncrypt</B>(boolean&nbsp;p_encrypt)</PRE>
+<DL>
+<DD>Set the value of the <code>encrypt</code> member.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getEncrypt()"><!-- --></A><H3>
+getEncrypt</H3>
+<PRE>
+public boolean <B>getEncrypt</B>()</PRE>
+<DL>
+<DD>Get the value of the <code>encrypt</code> member.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> Encryption on or off.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setPath(java.lang.String)"><!-- --></A><H3>
+setPath</H3>
+<PRE>
+public void <B>setPath</B>(java.lang.String&nbsp;p_path)</PRE>
+<DL>
+<DD>Set the value of the <code>path</code> member. This is the
+ path that will be used in the POST method.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="doRequest(java.lang.String)"><!-- --></A><H3>
+doRequest</H3>
+<PRE>
+public boolean <B>doRequest</B>(java.lang.String&nbsp;from)
+ throws java.io.IOException</PRE>
+<DL>
+<DD><DL>
+
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="doRequest()"><!-- --></A><H3>
+doRequest</H3>
+<PRE>
+public boolean <B>doRequest</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Do a CUPS request to the server.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> True on success, false otherwise
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="doRequest(java.io.File)"><!-- --></A><H3>
+doRequest</H3>
+<PRE>
+public boolean <B>doRequest</B>(java.io.File&nbsp;file)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Send a FILE to the CUPS server.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> True on success, false otherwise
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsGetJobs(boolean, boolean)"><!-- --></A><H3>
+cupsGetJobs</H3>
+<PRE>
+public org.cups.CupsJob[] <B>cupsGetJobs</B>(boolean&nbsp;showMyJobs,
+ boolean&nbsp;showCompleted)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Get a list of jobs.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>CupsJob[]</code> Array of job objects, or null.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsGetPrinters()"><!-- --></A><H3>
+cupsGetPrinters</H3>
+<PRE>
+public java.lang.String[] <B>cupsGetPrinters</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Get a list of printers.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String[]</code> Array of printers, or null.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsGetDefault()"><!-- --></A><H3>
+cupsGetDefault</H3>
+<PRE>
+public java.lang.String <B>cupsGetDefault</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Get default destination.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> Name of default printer, or null.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsGetPrinterAttributes(java.lang.String)"><!-- --></A><H3>
+cupsGetPrinterAttributes</H3>
+<PRE>
+public java.util.List <B>cupsGetPrinterAttributes</B>(java.lang.String&nbsp;printer_name)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Get printer attributes
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>List</code> List of attributes.
+<DD><CODE>java.io.IOException</CODE><DT><B>See Also:</B><DD><code>CupsPrinter</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsPrintFile(java.lang.String, org.cups.IPPAttribute[])"><!-- --></A><H3>
+cupsPrintFile</H3>
+<PRE>
+public org.cups.CupsJob <B>cupsPrintFile</B>(java.lang.String&nbsp;p_filename,
+ org.cups.IPPAttribute[]&nbsp;p_attrs)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Print a file.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>CupsJob</code> Object with job info.
+<DD><CODE>java.io.IOException</CODE><DT><B>See Also:</B><DD><code>CupsJob</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsCancelJob(java.lang.String, int, java.lang.String)"><!-- --></A><H3>
+cupsCancelJob</H3>
+<PRE>
+public int <B>cupsCancelJob</B>(java.lang.String&nbsp;printer_name,
+ int&nbsp;p_job_id,
+ java.lang.String&nbsp;p_user_name)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Cancel a job - send a job cancel request to the server.
+<P>
+<DD><DL>
+
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="cupsGetPrinterStatus(java.lang.String)"><!-- --></A><H3>
+cupsGetPrinterStatus</H3>
+<PRE>
+public java.util.List <B>cupsGetPrinterStatus</B>(java.lang.String&nbsp;printer_name)
+ throws java.io.IOException</PRE>
+<DL>
+<DD><DL>
+
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="../../org/cups/CupsJob.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="Cups.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/CupsJob.html b/scripting/java/docs/org/cups/CupsJob.html
new file mode 100644
index 000000000..56465dff7
--- /dev/null
+++ b/scripting/java/docs/org/cups/CupsJob.html
@@ -0,0 +1,622 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+CupsJob
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.CupsJob,CupsJob class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="CupsJob";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/Cups.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/CupsPrinter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="CupsJob.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class CupsJob</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.CupsJob</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>CupsJob</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#document_format">document_format</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_hold_until">job_hold_until</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_id">job_id</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_k_octets">job_k_octets</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_media_sheets_completed">job_media_sheets_completed</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_more_info">job_more_info</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_name">job_name</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_originating_host_name">job_originating_host_name</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_originating_user_name">job_originating_user_name</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_printer_up_time">job_printer_up_time</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_printer_uri">job_printer_uri</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_priority">job_priority</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_sheets">job_sheets</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_state">job_state</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_state_reasons">job_state_reasons</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#job_uri">job_uri</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#time_at_completed">time_at_completed</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#time_at_creation">time_at_creation</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#time_at_processing">time_at_processing</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#CupsJob()">CupsJob</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor - set some default values.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#jobStatusText()">jobStatusText</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convert a job status to a string.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsJob.html#updateAttribute(org.cups.IPPAttribute)">updateAttribute</A></B>(org.cups.IPPAttribute&nbsp;a)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process an attribute from a cups.doRequest() call
+ and move the value into a local member.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="job_id"><!-- --></A><H3>
+job_id</H3>
+<PRE>
+public int <B>job_id</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_more_info"><!-- --></A><H3>
+job_more_info</H3>
+<PRE>
+public java.lang.String <B>job_more_info</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_uri"><!-- --></A><H3>
+job_uri</H3>
+<PRE>
+public java.lang.String <B>job_uri</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_printer_uri"><!-- --></A><H3>
+job_printer_uri</H3>
+<PRE>
+public java.lang.String <B>job_printer_uri</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_printer_up_time"><!-- --></A><H3>
+job_printer_up_time</H3>
+<PRE>
+public long <B>job_printer_up_time</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_name"><!-- --></A><H3>
+job_name</H3>
+<PRE>
+public java.lang.String <B>job_name</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_originating_user_name"><!-- --></A><H3>
+job_originating_user_name</H3>
+<PRE>
+public java.lang.String <B>job_originating_user_name</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="document_format"><!-- --></A><H3>
+document_format</H3>
+<PRE>
+public java.lang.String <B>document_format</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_originating_host_name"><!-- --></A><H3>
+job_originating_host_name</H3>
+<PRE>
+public java.lang.String <B>job_originating_host_name</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_priority"><!-- --></A><H3>
+job_priority</H3>
+<PRE>
+public int <B>job_priority</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_state"><!-- --></A><H3>
+job_state</H3>
+<PRE>
+public int <B>job_state</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_media_sheets_completed"><!-- --></A><H3>
+job_media_sheets_completed</H3>
+<PRE>
+public int <B>job_media_sheets_completed</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_k_octets"><!-- --></A><H3>
+job_k_octets</H3>
+<PRE>
+public int <B>job_k_octets</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="time_at_creation"><!-- --></A><H3>
+time_at_creation</H3>
+<PRE>
+public long <B>time_at_creation</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="time_at_processing"><!-- --></A><H3>
+time_at_processing</H3>
+<PRE>
+public long <B>time_at_processing</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="time_at_completed"><!-- --></A><H3>
+time_at_completed</H3>
+<PRE>
+public long <B>time_at_completed</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_hold_until"><!-- --></A><H3>
+job_hold_until</H3>
+<PRE>
+public java.lang.String <B>job_hold_until</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_sheets"><!-- --></A><H3>
+job_sheets</H3>
+<PRE>
+public java.lang.String <B>job_sheets</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="job_state_reasons"><!-- --></A><H3>
+job_state_reasons</H3>
+<PRE>
+public java.lang.String <B>job_state_reasons</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="CupsJob()"><!-- --></A><H3>
+CupsJob</H3>
+<PRE>
+public <B>CupsJob</B>()</PRE>
+<DL>
+<DD>Constructor - set some default values.
+<P>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="updateAttribute(org.cups.IPPAttribute)"><!-- --></A><H3>
+updateAttribute</H3>
+<PRE>
+public void <B>updateAttribute</B>(org.cups.IPPAttribute&nbsp;a)</PRE>
+<DL>
+<DD>Process an attribute from a cups.doRequest() call
+ and move the value into a local member.
+<P>
+<DD><DL>
+<DT><B>See Also:</B><DD><code>IPPDefs</code>,
+<code>IPPValues</code>,
+<code>IPPAttributes</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="jobStatusText()"><!-- --></A><H3>
+jobStatusText</H3>
+<PRE>
+public java.lang.String <B>jobStatusText</B>()</PRE>
+<DL>
+<DD>Convert a job status to a string.
+<P>
+<DD><DL>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/Cups.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/CupsPrinter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="CupsJob.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/CupsPrinter.html b/scripting/java/docs/org/cups/CupsPrinter.html
new file mode 100644
index 000000000..ecaf93d04
--- /dev/null
+++ b/scripting/java/docs/org/cups/CupsPrinter.html
@@ -0,0 +1,614 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+CupsPrinter
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.CupsPrinter,CupsPrinter class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="CupsPrinter";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/CupsJob.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPP.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="CupsPrinter.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class CupsPrinter</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.CupsPrinter</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>CupsPrinter</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#CupsPrinter(org.cups.Cups)">CupsPrinter</A></B>(org.cups.Cups&nbsp;c)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#CupsPrinter(org.cups.Cups, java.lang.String)">CupsPrinter</A></B>(org.cups.Cups&nbsp;c,
+ java.lang.String&nbsp;name)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor with name.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getAttributes(org.cups.Cups)">getAttributes</A></B>(org.cups.Cups&nbsp;c)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer's attributes.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getCopiesDefault()">getCopiesDefault</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer number of copies default.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getJobSheetsDefault()">getJobSheetsDefault</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the default job sheets.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getJobSheetsSupported()">getJobSheetsSupported</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer job sheets supported.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getLocation()">getLocation</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer location.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getLowerCopiesSupported()">getLowerCopiesSupported</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer lower copies supported.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getMakeAndModel()">getMakeAndModel</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer make and model.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getOrientationDefault()">getOrientationDefault</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the default orientation.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getOrientationSupported()">getOrientationSupported</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer orientation supported.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getPageRangesSupported()">getPageRangesSupported</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get whether the printer supports page ranges.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getPrinterName()">getPrinterName</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer name.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getStateReasons()">getStateReasons</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer state reasons.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getStateText()">getStateText</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer state text.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getStatus(org.cups.Cups)">getStatus</A></B>(org.cups.Cups&nbsp;c)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer's status.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#getUpperCopiesSupported()">getUpperCopiesSupported</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the printer upper copies supported.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#setDefaults()">setDefaults</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Initialize the members with mostly sane values.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/CupsPrinter.html#updateAttribute(org.cups.IPPAttribute)">updateAttribute</A></B>(org.cups.IPPAttribute&nbsp;a)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process an attribute from the cups.doRequest() method and move
+ the values into local members.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="CupsPrinter(org.cups.Cups)"><!-- --></A><H3>
+CupsPrinter</H3>
+<PRE>
+public <B>CupsPrinter</B>(org.cups.Cups&nbsp;c)</PRE>
+<DL>
+<DD>Constructor. Does not get status or attributes.
+<P>
+<DT><B>See Also:</B><DD><code>Cups</code></DL>
+<HR>
+
+<A NAME="CupsPrinter(org.cups.Cups, java.lang.String)"><!-- --></A><H3>
+CupsPrinter</H3>
+<PRE>
+public <B>CupsPrinter</B>(org.cups.Cups&nbsp;c,
+ java.lang.String&nbsp;name)</PRE>
+<DL>
+<DD>Constructor with name. Get status and attributes.
+<P>
+<DT><B>See Also:</B><DD><code>Cups</code></DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="setDefaults()"><!-- --></A><H3>
+setDefaults</H3>
+<PRE>
+public void <B>setDefaults</B>()</PRE>
+<DL>
+<DD>Initialize the members with mostly sane values.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStatus(org.cups.Cups)"><!-- --></A><H3>
+getStatus</H3>
+<PRE>
+public boolean <B>getStatus</B>(org.cups.Cups&nbsp;c)</PRE>
+<DL>
+<DD>Get the printer's status.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>Boolean</code> True on success.<DT><B>See Also:</B><DD><code>Cups</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getAttributes(org.cups.Cups)"><!-- --></A><H3>
+getAttributes</H3>
+<PRE>
+public boolean <B>getAttributes</B>(org.cups.Cups&nbsp;c)</PRE>
+<DL>
+<DD>Get the printer's attributes.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>Boolean</code> True on success.<DT><B>See Also:</B><DD><code>Cups</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="updateAttribute(org.cups.IPPAttribute)"><!-- --></A><H3>
+updateAttribute</H3>
+<PRE>
+public void <B>updateAttribute</B>(org.cups.IPPAttribute&nbsp;a)</PRE>
+<DL>
+<DD>Process an attribute from the cups.doRequest() method and move
+ the values into local members.
+<P>
+<DD><DL>
+<DT><B>See Also:</B><DD><code>IPPAttributes</code>,
+<code>IPPValues</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getPrinterName()"><!-- --></A><H3>
+getPrinterName</H3>
+<PRE>
+public java.lang.String <B>getPrinterName</B>()</PRE>
+<DL>
+<DD>Get the printer name.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> Printer Name.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStateText()"><!-- --></A><H3>
+getStateText</H3>
+<PRE>
+public java.lang.String <B>getStateText</B>()</PRE>
+<DL>
+<DD>Get the printer state text.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> State text.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStateReasons()"><!-- --></A><H3>
+getStateReasons</H3>
+<PRE>
+public java.lang.String <B>getStateReasons</B>()</PRE>
+<DL>
+<DD>Get the printer state reasons.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> State reason.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getLocation()"><!-- --></A><H3>
+getLocation</H3>
+<PRE>
+public java.lang.String <B>getLocation</B>()</PRE>
+<DL>
+<DD>Get the printer location.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> State location.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMakeAndModel()"><!-- --></A><H3>
+getMakeAndModel</H3>
+<PRE>
+public java.lang.String <B>getMakeAndModel</B>()</PRE>
+<DL>
+<DD>Get the printer make and model.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> Make and model.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getJobSheetsDefault()"><!-- --></A><H3>
+getJobSheetsDefault</H3>
+<PRE>
+public java.lang.String <B>getJobSheetsDefault</B>()</PRE>
+<DL>
+<DD>Get the default job sheets.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> Default job sheets.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getJobSheetsSupported()"><!-- --></A><H3>
+getJobSheetsSupported</H3>
+<PRE>
+public java.lang.String[] <B>getJobSheetsSupported</B>()</PRE>
+<DL>
+<DD>Get the printer job sheets supported.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String[]</code> Array of supported job sheets.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOrientationDefault()"><!-- --></A><H3>
+getOrientationDefault</H3>
+<PRE>
+public int <B>getOrientationDefault</B>()</PRE>
+<DL>
+<DD>Get the default orientation.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Default page orientation.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOrientationSupported()"><!-- --></A><H3>
+getOrientationSupported</H3>
+<PRE>
+public int[] <B>getOrientationSupported</B>()</PRE>
+<DL>
+<DD>Get the printer orientation supported.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int[]</code> Array of supported orientations.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getLowerCopiesSupported()"><!-- --></A><H3>
+getLowerCopiesSupported</H3>
+<PRE>
+public int <B>getLowerCopiesSupported</B>()</PRE>
+<DL>
+<DD>Get the printer lower copies supported.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Lower of the range.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getUpperCopiesSupported()"><!-- --></A><H3>
+getUpperCopiesSupported</H3>
+<PRE>
+public int <B>getUpperCopiesSupported</B>()</PRE>
+<DL>
+<DD>Get the printer upper copies supported.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Upper of the range.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getCopiesDefault()"><!-- --></A><H3>
+getCopiesDefault</H3>
+<PRE>
+public int <B>getCopiesDefault</B>()</PRE>
+<DL>
+<DD>Get the printer number of copies default.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Default number of copies.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getPageRangesSupported()"><!-- --></A><H3>
+getPageRangesSupported</H3>
+<PRE>
+public boolean <B>getPageRangesSupported</B>()</PRE>
+<DL>
+<DD>Get whether the printer supports page ranges.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> True or false.</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/CupsJob.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPP.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="CupsPrinter.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPP.html b/scripting/java/docs/org/cups/IPP.html
new file mode 100644
index 000000000..e790c455b
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPP.html
@@ -0,0 +1,479 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+IPP
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPP,IPP class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPP";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/CupsPrinter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPAttribute.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPP.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPP</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPP</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPP</B><DT>extends java.lang.Object</DL>
+
+<P>
+An <code>IPP</code> object is used to hold the various
+ attributes and status of an ipp request..
+<P>
+
+<P>
+<DL>
+<DT><B>Since:</B></DT>
+ <DD>JDK1.3</DD>
+</DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.List</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#attrs">attrs</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPPRequest</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#request">request</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPPStatus</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#status">status</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#IPP()">IPP</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#addAttribute(org.cups.IPPAttribute)">addAttribute</A></B>(org.cups.IPPAttribute&nbsp;a)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add an attribute to the attibutes list
+ for later parsing.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#dump_response()">dump_response</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPPAttribute</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#getCurrentAttribute()">getCurrentAttribute</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the current attribute pointed at by
+ <code>current</code>.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPPAttribute</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#ippFindAttribute(java.lang.String, int)">ippFindAttribute</A></B>(java.lang.String&nbsp;p_name,
+ int&nbsp;p_type)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Find the named attribute of the correct type.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPPAttribute</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#ippFindNextAttribute(java.lang.String, int)">ippFindNextAttribute</A></B>(java.lang.String&nbsp;p_name,
+ int&nbsp;p_type)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Find the named attribute of the correct type.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#setRequestID(short)">setRequestID</A></B>(short&nbsp;p_id)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the <code>IPP</code> request ID.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#setRequestOperationID(short)">setRequestOperationID</A></B>(short&nbsp;p_operation_id)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the <code>IPP</code> operation ID.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPP.html#sizeInBytes()">sizeInBytes</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the size in bytes of an <code>IPP</code> request.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="request"><!-- --></A><H3>
+request</H3>
+<PRE>
+public org.cups.IPPRequest <B>request</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="status"><!-- --></A><H3>
+status</H3>
+<PRE>
+public org.cups.IPPStatus <B>status</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="attrs"><!-- --></A><H3>
+attrs</H3>
+<PRE>
+public java.util.List <B>attrs</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPP()"><!-- --></A><H3>
+IPP</H3>
+<PRE>
+public <B>IPP</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="addAttribute(org.cups.IPPAttribute)"><!-- --></A><H3>
+addAttribute</H3>
+<PRE>
+public boolean <B>addAttribute</B>(org.cups.IPPAttribute&nbsp;a)</PRE>
+<DL>
+<DD>Add an attribute to the attibutes list
+ for later parsing.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>a</CODE> - <code>IPPAttribute</code> to add.
+<DT><B>Returns:</B><DD><code>true</code> always returns <code>true</code>
+ for now.<DT><B>See Also:</B><DD><A HREF="../../org/cups/IPPAttribute.html"><CODE>IPPAttribute</CODE></A>,
+<A HREF="../../org/cups/IPPValue.html"><CODE>IPPValue</CODE></A></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getCurrentAttribute()"><!-- --></A><H3>
+getCurrentAttribute</H3>
+<PRE>
+public org.cups.IPPAttribute <B>getCurrentAttribute</B>()</PRE>
+<DL>
+<DD>Get the current attribute pointed at by
+ <code>current</code>.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>IPPAttribute</code> Return the current attribute.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="ippFindAttribute(java.lang.String, int)"><!-- --></A><H3>
+ippFindAttribute</H3>
+<PRE>
+public org.cups.IPPAttribute <B>ippFindAttribute</B>(java.lang.String&nbsp;p_name,
+ int&nbsp;p_type)</PRE>
+<DL>
+<DD>Find the named attribute of the correct type. Both must match.
+ This methos searches from the beginning of the attribute list,
+ rather than from the current position.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_name</CODE> - <code>String</code> containing the name.<DD><CODE>p_type</CODE> - <code>int</code> attribute type.
+<DT><B>Returns:</B><DD><code>IPPAttribute</code> Matching attribute if found.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="ippFindNextAttribute(java.lang.String, int)"><!-- --></A><H3>
+ippFindNextAttribute</H3>
+<PRE>
+public org.cups.IPPAttribute <B>ippFindNextAttribute</B>(java.lang.String&nbsp;p_name,
+ int&nbsp;p_type)</PRE>
+<DL>
+<DD>Find the named attribute of the correct type. Both must match.
+ This methos searches from the current position in the attribute list.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_name</CODE> - <code>String</code> containing the name.<DD><CODE>p_type</CODE> - <code>int</code> attribute type.
+<DT><B>Returns:</B><DD><code>IPPAttribute</code> Matching attribute if found.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="sizeInBytes()"><!-- --></A><H3>
+sizeInBytes</H3>
+<PRE>
+public int <B>sizeInBytes</B>()</PRE>
+<DL>
+<DD>Get the size in bytes of an <code>IPP</code> request.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Number of bytes for the request.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setRequestID(short)"><!-- --></A><H3>
+setRequestID</H3>
+<PRE>
+public void <B>setRequestID</B>(short&nbsp;p_id)</PRE>
+<DL>
+<DD>Set the <code>IPP</code> request ID.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_id</CODE> - <code>short</code> request id.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setRequestOperationID(short)"><!-- --></A><H3>
+setRequestOperationID</H3>
+<PRE>
+public void <B>setRequestOperationID</B>(short&nbsp;p_operation_id)</PRE>
+<DL>
+<DD>Set the <code>IPP</code> operation ID.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_operation_id</CODE> - <code>short</code> operation id.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="dump_response()"><!-- --></A><H3>
+dump_response</H3>
+<PRE>
+public void <B>dump_response</B>()</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/CupsPrinter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPAttribute.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPP.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPAttribute.html b/scripting/java/docs/org/cups/IPPAttribute.html
new file mode 100644
index 000000000..fd094076c
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPAttribute.html
@@ -0,0 +1,545 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+IPPAttribute
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPAttribute,IPPAttribute class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPAttribute";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPP.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPDefs.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPAttribute.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPAttribute</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPAttribute</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPAttribute</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#IPPAttribute(int, int, java.lang.String)">IPPAttribute</A></B>(int&nbsp;p_group_tag,
+ int&nbsp;p_value_tag,
+ java.lang.String&nbsp;p_name)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addBoolean(boolean)">addBoolean</A></B>(boolean&nbsp;p_bool)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addBooleans(boolean[])">addBooleans</A></B>(boolean[]&nbsp;p_bools)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addDate(char[])">addDate</A></B>(char[]&nbsp;p_date)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addEnum(int)">addEnum</A></B>(int&nbsp;p_int)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addInteger(int)">addInteger</A></B>(int&nbsp;p_int)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addIntegers(int[])">addIntegers</A></B>(int[]&nbsp;p_ints)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addRange(int, int)">addRange</A></B>(int&nbsp;p_lower,
+ int&nbsp;p_upper)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addRanges(int[], int[])">addRanges</A></B>(int[]&nbsp;p_lower,
+ int[]&nbsp;p_upper)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addResolution(byte, int, int)">addResolution</A></B>(byte&nbsp;p_units,
+ int&nbsp;p_xres,
+ int&nbsp;p_yres)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addResolutions(byte, int[], int[])">addResolutions</A></B>(byte&nbsp;p_units,
+ int[]&nbsp;p_xres,
+ int[]&nbsp;p_yres)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addSeparator()">addSeparator</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addString(java.lang.String, java.lang.String)">addString</A></B>(java.lang.String&nbsp;p_charset,
+ java.lang.String&nbsp;p_text)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#addStrings(java.lang.String, java.lang.String[])">addStrings</A></B>(java.lang.String&nbsp;p_charset,
+ java.lang.String[]&nbsp;p_texts)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#dump_values()">dump_values</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#getBytes(int, int)">getBytes</A></B>(int&nbsp;sz,
+ int&nbsp;last_group)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPAttribute.html#sizeInBytes(int)">sizeInBytes</A></B>(int&nbsp;last_group)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPAttribute(int, int, java.lang.String)"><!-- --></A><H3>
+IPPAttribute</H3>
+<PRE>
+public <B>IPPAttribute</B>(int&nbsp;p_group_tag,
+ int&nbsp;p_value_tag,
+ java.lang.String&nbsp;p_name)</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="addBoolean(boolean)"><!-- --></A><H3>
+addBoolean</H3>
+<PRE>
+public boolean <B>addBoolean</B>(boolean&nbsp;p_bool)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addBooleans(boolean[])"><!-- --></A><H3>
+addBooleans</H3>
+<PRE>
+public boolean <B>addBooleans</B>(boolean[]&nbsp;p_bools)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addEnum(int)"><!-- --></A><H3>
+addEnum</H3>
+<PRE>
+public boolean <B>addEnum</B>(int&nbsp;p_int)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addInteger(int)"><!-- --></A><H3>
+addInteger</H3>
+<PRE>
+public boolean <B>addInteger</B>(int&nbsp;p_int)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addIntegers(int[])"><!-- --></A><H3>
+addIntegers</H3>
+<PRE>
+public boolean <B>addIntegers</B>(int[]&nbsp;p_ints)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addString(java.lang.String, java.lang.String)"><!-- --></A><H3>
+addString</H3>
+<PRE>
+public boolean <B>addString</B>(java.lang.String&nbsp;p_charset,
+ java.lang.String&nbsp;p_text)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addStrings(java.lang.String, java.lang.String[])"><!-- --></A><H3>
+addStrings</H3>
+<PRE>
+public boolean <B>addStrings</B>(java.lang.String&nbsp;p_charset,
+ java.lang.String[]&nbsp;p_texts)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addDate(char[])"><!-- --></A><H3>
+addDate</H3>
+<PRE>
+public boolean <B>addDate</B>(char[]&nbsp;p_date)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addRange(int, int)"><!-- --></A><H3>
+addRange</H3>
+<PRE>
+public boolean <B>addRange</B>(int&nbsp;p_lower,
+ int&nbsp;p_upper)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addRanges(int[], int[])"><!-- --></A><H3>
+addRanges</H3>
+<PRE>
+public boolean <B>addRanges</B>(int[]&nbsp;p_lower,
+ int[]&nbsp;p_upper)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addResolution(byte, int, int)"><!-- --></A><H3>
+addResolution</H3>
+<PRE>
+public boolean <B>addResolution</B>(byte&nbsp;p_units,
+ int&nbsp;p_xres,
+ int&nbsp;p_yres)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addResolutions(byte, int[], int[])"><!-- --></A><H3>
+addResolutions</H3>
+<PRE>
+public boolean <B>addResolutions</B>(byte&nbsp;p_units,
+ int[]&nbsp;p_xres,
+ int[]&nbsp;p_yres)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="addSeparator()"><!-- --></A><H3>
+addSeparator</H3>
+<PRE>
+public boolean <B>addSeparator</B>()</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="sizeInBytes(int)"><!-- --></A><H3>
+sizeInBytes</H3>
+<PRE>
+public int <B>sizeInBytes</B>(int&nbsp;last_group)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getBytes(int, int)"><!-- --></A><H3>
+getBytes</H3>
+<PRE>
+public byte[] <B>getBytes</B>(int&nbsp;sz,
+ int&nbsp;last_group)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="dump_values()"><!-- --></A><H3>
+dump_values</H3>
+<PRE>
+public void <B>dump_values</B>()</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPP.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPDefs.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPAttribute.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPDefs.html b/scripting/java/docs/org/cups/IPPDefs.html
new file mode 100644
index 000000000..432a6ee19
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPDefs.html
@@ -0,0 +1,3756 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+IPPDefs
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPDefs,IPPDefs class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPDefs";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPAttribute.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPError.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPDefs.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPDefs</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPDefs</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPDefs</B><DT>extends java.lang.Object</DL>
+
+<P>
+<code>IPPDefs</code> is a collection of constants for use
+ in the <code>IPP</code> and <code>CUPS</code> classes.
+<P>
+
+<P>
+<DL>
+<DT><B>Since:</B></DT>
+ <DD>JDK1.3</DD>
+</DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ACTIVATE_PRINTER">ACTIVATE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ATTRIBUTE">ATTRIBUTE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ATTRIBUTES">ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ATTRIBUTES_NOT_SETTABLE">ATTRIBUTES_NOT_SETTABLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#BAD_REQUEST">BAD_REQUEST</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CANCEL_CURRENT_JOB">CANCEL_CURRENT_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CANCEL_JOB">CANCEL_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CANCEL_SUBSCRIPTION">CANCEL_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CHARSET">CHARSET</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#COMPRESSION_ERROR">COMPRESSION_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#COMPRESSION_NOT_SUPPORTED">COMPRESSION_NOT_SUPPORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CONFLICT">CONFLICT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CREATE_JOB">CREATE_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CREATE_JOB_SUBSCRIPTION">CREATE_JOB_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CREATE_PRINTER_SUBSCRIPTION">CREATE_PRINTER_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_ACCEPT_JOBS">CUPS_ACCEPT_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_ADD_CLASS">CUPS_ADD_CLASS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_ADD_DEVICE">CUPS_ADD_DEVICE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_ADD_PRINTER">CUPS_ADD_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_DELETE_CLASS">CUPS_DELETE_CLASS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_DELETE_DEVICE">CUPS_DELETE_DEVICE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_DELETE_PRINTER">CUPS_DELETE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_GET_CLASSES">CUPS_GET_CLASSES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_GET_DEFAULT">CUPS_GET_DEFAULT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_GET_DEVICES">CUPS_GET_DEVICES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_GET_PPDS">CUPS_GET_PPDS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_GET_PRINTERS">CUPS_GET_PRINTERS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_MOVE_JOB">CUPS_MOVE_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_REJECT_JOBS">CUPS_REJECT_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#CUPS_SET_DEFAULT">CUPS_SET_DEFAULT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DATA">DATA</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DEACTIVATE_PRINTER">DEACTIVATE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DEVICE_ERROR">DEVICE_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DISABLE_PRINTER">DISABLE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DOCUMENT_ACCESS_ERROR">DOCUMENT_ACCESS_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DOCUMENT_FORMAT">DOCUMENT_FORMAT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#DOCUMENT_FORMAT_ERROR">DOCUMENT_FORMAT_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ENABLE_PRINTER">ENABLE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ERROR">ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#ERROR_JOB_CANCELLED">ERROR_JOB_CANCELLED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BALE">FINISHINGS_BALE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BIND">FINISHINGS_BIND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BIND_BOTTOM">FINISHINGS_BIND_BOTTOM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BIND_LEFT">FINISHINGS_BIND_LEFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BIND_RIGHT">FINISHINGS_BIND_RIGHT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BIND_TOP">FINISHINGS_BIND_TOP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_BOOKLET_MAKER">FINISHINGS_BOOKLET_MAKER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_COVER">FINISHINGS_COVER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH">FINISHINGS_EDGE_STITCH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_BOTTOM">FINISHINGS_EDGE_STITCH_BOTTOM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_LEFT">FINISHINGS_EDGE_STITCH_LEFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_RIGHT">FINISHINGS_EDGE_STITCH_RIGHT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_EDGE_STITCH_TOP">FINISHINGS_EDGE_STITCH_TOP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_FOLD">FINISHINGS_FOLD</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_JOB_OFFSET">FINISHINGS_JOB_OFFSET</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_NONE">FINISHINGS_NONE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_PUNCH">FINISHINGS_PUNCH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_SADDLE_STITCH">FINISHINGS_SADDLE_STITCH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE">FINISHINGS_STAPLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_BOTTOM_LEFT">FINISHINGS_STAPLE_BOTTOM_LEFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_BOTTOM_RIGHT">FINISHINGS_STAPLE_BOTTOM_RIGHT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_BOTTOM">FINISHINGS_STAPLE_DUAL_BOTTOM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_LEFT">FINISHINGS_STAPLE_DUAL_LEFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_RIGHT">FINISHINGS_STAPLE_DUAL_RIGHT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_DUAL_TOP">FINISHINGS_STAPLE_DUAL_TOP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_TOP_LEFT">FINISHINGS_STAPLE_TOP_LEFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_STAPLE_TOP_RIGHT">FINISHINGS_STAPLE_TOP_RIGHT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FINISHINGS_TRIM">FINISHINGS_TRIM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#FORBIDDEN">FORBIDDEN</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_JOB_ATTRIBUTES">GET_JOB_ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_JOBS">GET_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_NOTIFICATIONS">GET_NOTIFICATIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_PRINT_SUPPORT_FILES">GET_PRINT_SUPPORT_FILES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_PRINTER_ATTRIBUTES">GET_PRINTER_ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_PRINTER_SUPPORTED_VALUES">GET_PRINTER_SUPPORTED_VALUES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_SUBSCRIPTION_ATTRIBUTES">GET_SUBSCRIPTION_ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GET_SUBSCRIPTIONS">GET_SUBSCRIPTIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#GONE">GONE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#HEADER">HEADER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#HOLD_JOB">HOLD_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#HOLD_NEW_JOBS">HOLD_NEW_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#IDLE">IDLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#IGNORED_ALL_NOTIFICATIONS">IGNORED_ALL_NOTIFICATIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#IGNORED_ALL_SUBSCRIPTIONS">IGNORED_ALL_SUBSCRIPTIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#INTERNAL_ERROR">INTERNAL_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_ABORTED">JOB_ABORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_CANCELLED">JOB_CANCELLED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_COMPLETED">JOB_COMPLETED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_HELD">JOB_HELD</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_PENDING">JOB_PENDING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_PROCESSING">JOB_PROCESSING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#JOB_STOPPED">JOB_STOPPED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#LANDSCAPE">LANDSCAPE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#MAX_NAME">MAX_NAME</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#MAX_VALUES">MAX_VALUES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#MULTIPLE_JOBS_NOT_SUPPORTED">MULTIPLE_JOBS_NOT_SUPPORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#NOT_ACCEPTING">NOT_ACCEPTING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#NOT_AUTHENTICATED">NOT_AUTHENTICATED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#NOT_AUTHORIZED">NOT_AUTHORIZED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#NOT_FOUND">NOT_FOUND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#NOT_POSSIBLE">NOT_POSSIBLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK">OK</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_BUT_CANCEL_SUBSCRIPTION">OK_BUT_CANCEL_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_CONFLICT">OK_CONFLICT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_IGNORED_NOTIFICATIONS">OK_IGNORED_NOTIFICATIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_IGNORED_SUBSCRIPTIONS">OK_IGNORED_SUBSCRIPTIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_SUBST">OK_SUBST</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OK_TOO_MANY_EVENTS">OK_TOO_MANY_EVENTS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#OPERATION_NOT_SUPPORTED">OPERATION_NOT_SUPPORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PAUSE_PRINTER">PAUSE_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PAUSE_PRINTER_AFTER_CURRENT_JOB">PAUSE_PRINTER_AFTER_CURRENT_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PORT">PORT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PORTRAIT">PORTRAIT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINT_JOB">PRINT_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINT_SUPPORT_FILE_NOT_FOUND">PRINT_SUPPORT_FILE_NOT_FOUND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINT_URI">PRINT_URI</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINTER_BUSY">PRINTER_BUSY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINTER_IDLE">PRINTER_IDLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINTER_IS_DEACTIVATED">PRINTER_IS_DEACTIVATED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINTER_PROCESSING">PRINTER_PROCESSING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRINTER_STOPPED">PRINTER_STOPPED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PRIVATE">PRIVATE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PROMOTE_JOB">PROMOTE_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#PURGE_JOBS">PURGE_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#QUALITY_DRAFT">QUALITY_DRAFT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#QUALITY_HIGH">QUALITY_HIGH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#QUALITY_NORMAL">QUALITY_NORMAL</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REDIRECTION_OTHER_SITE">REDIRECTION_OTHER_SITE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RELEASE_HELD_NEW_JOBS">RELEASE_HELD_NEW_JOBS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RELEASE_JOB">RELEASE_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RENEW_SUBSCRIPTION">RENEW_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REPROCESS_JOB">REPROCESS_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REQUEST_ENTITY">REQUEST_ENTITY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REQUEST_VALUE">REQUEST_VALUE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RES_PER_CM">RES_PER_CM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RES_PER_INCH">RES_PER_INCH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RESTART_JOB">RESTART_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RESTART_PRINTER">RESTART_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RESUME_JOB">RESUME_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#RESUME_PRINTER">RESUME_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REVERSE_LANDSCAPE">REVERSE_LANDSCAPE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#REVERSE_PORTRAIT">REVERSE_PORTRAIT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SCHEDULE_JOB_AFTER">SCHEDULE_JOB_AFTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SEND_DOCUMENT">SEND_DOCUMENT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SEND_NOTIFICATIONS">SEND_NOTIFICATIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SEND_URI">SEND_URI</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SERVICE_UNAVAILABLE">SERVICE_UNAVAILABLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SET_JOB_ATTRIBUTES">SET_JOB_ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SET_PRINTER_ATTRIBUTES">SET_PRINTER_ATTRIBUTES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SHUTDOWN_PRINTER">SHUTDOWN_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#STARTUP_PRINTER">STARTUP_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#SUSPEND_CURRENT_JOB">SUSPEND_CURRENT_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_ADMINDEFINE">TAG_ADMINDEFINE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_BEGIN_COLLECTION">TAG_BEGIN_COLLECTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_BOOLEAN">TAG_BOOLEAN</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_CHARSET">TAG_CHARSET</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_COPY">TAG_COPY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_DATE">TAG_DATE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_DEFAULT">TAG_DEFAULT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_DELETEATTR">TAG_DELETEATTR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_END">TAG_END</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_END_COLLECTION">TAG_END_COLLECTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_ENUM">TAG_ENUM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_EVENT_NOTIFICATION">TAG_EVENT_NOTIFICATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_INTEGER">TAG_INTEGER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_JOB">TAG_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_KEYWORD">TAG_KEYWORD</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_LANGUAGE">TAG_LANGUAGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_MASK">TAG_MASK</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_MEMBERNAME">TAG_MEMBERNAME</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_MIMETYPE">TAG_MIMETYPE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_NAME">TAG_NAME</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_NAMELANG">TAG_NAMELANG</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_NOTSETTABLE">TAG_NOTSETTABLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_NOVALUE">TAG_NOVALUE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_OPERATION">TAG_OPERATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_PRINTER">TAG_PRINTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_RANGE">TAG_RANGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_RESOLUTION">TAG_RESOLUTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_STRING">TAG_STRING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_SUBSCRIPTION">TAG_SUBSCRIPTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_TEXT">TAG_TEXT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_TEXTLANG">TAG_TEXTLANG</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_UNKNOWN">TAG_UNKNOWN</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_UNSUPPORTED_GROUP">TAG_UNSUPPORTED_GROUP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_UNSUPPORTED_VALUE">TAG_UNSUPPORTED_VALUE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_URI">TAG_URI</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_URISCHEME">TAG_URISCHEME</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TAG_ZERO">TAG_ZERO</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TEMPORARY_ERROR">TEMPORARY_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TIMEOUT">TIMEOUT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#TOO_MANY_SUBSCRIPTIONS">TOO_MANY_SUBSCRIPTIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#URI_SCHEME">URI_SCHEME</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#VALIDATE_JOB">VALIDATE_JOB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#VERSION">VERSION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#VERSION_NOT_SUPPORTED">VERSION_NOT_SUPPORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPDefs.html#IPPDefs()">IPPDefs</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="VERSION"><!-- --></A><H3>
+VERSION</H3>
+<PRE>
+public static final byte[] <B>VERSION</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="PORT"><!-- --></A><H3>
+PORT</H3>
+<PRE>
+public static final int <B>PORT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PORT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="MAX_NAME"><!-- --></A><H3>
+MAX_NAME</H3>
+<PRE>
+public static final int <B>MAX_NAME</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.MAX_NAME">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="MAX_VALUES"><!-- --></A><H3>
+MAX_VALUES</H3>
+<PRE>
+public static final int <B>MAX_VALUES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.MAX_VALUES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_ZERO"><!-- --></A><H3>
+TAG_ZERO</H3>
+<PRE>
+public static final int <B>TAG_ZERO</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_ZERO">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_OPERATION"><!-- --></A><H3>
+TAG_OPERATION</H3>
+<PRE>
+public static final int <B>TAG_OPERATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_OPERATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_JOB"><!-- --></A><H3>
+TAG_JOB</H3>
+<PRE>
+public static final int <B>TAG_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_END"><!-- --></A><H3>
+TAG_END</H3>
+<PRE>
+public static final int <B>TAG_END</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_END">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_PRINTER"><!-- --></A><H3>
+TAG_PRINTER</H3>
+<PRE>
+public static final int <B>TAG_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_UNSUPPORTED_GROUP"><!-- --></A><H3>
+TAG_UNSUPPORTED_GROUP</H3>
+<PRE>
+public static final int <B>TAG_UNSUPPORTED_GROUP</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_UNSUPPORTED_GROUP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_SUBSCRIPTION"><!-- --></A><H3>
+TAG_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>TAG_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_EVENT_NOTIFICATION"><!-- --></A><H3>
+TAG_EVENT_NOTIFICATION</H3>
+<PRE>
+public static final int <B>TAG_EVENT_NOTIFICATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_EVENT_NOTIFICATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_UNSUPPORTED_VALUE"><!-- --></A><H3>
+TAG_UNSUPPORTED_VALUE</H3>
+<PRE>
+public static final int <B>TAG_UNSUPPORTED_VALUE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_UNSUPPORTED_VALUE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_DEFAULT"><!-- --></A><H3>
+TAG_DEFAULT</H3>
+<PRE>
+public static final int <B>TAG_DEFAULT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_DEFAULT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_UNKNOWN"><!-- --></A><H3>
+TAG_UNKNOWN</H3>
+<PRE>
+public static final int <B>TAG_UNKNOWN</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_UNKNOWN">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_NOVALUE"><!-- --></A><H3>
+TAG_NOVALUE</H3>
+<PRE>
+public static final int <B>TAG_NOVALUE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_NOVALUE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_NOTSETTABLE"><!-- --></A><H3>
+TAG_NOTSETTABLE</H3>
+<PRE>
+public static final int <B>TAG_NOTSETTABLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_NOTSETTABLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_DELETEATTR"><!-- --></A><H3>
+TAG_DELETEATTR</H3>
+<PRE>
+public static final int <B>TAG_DELETEATTR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_DELETEATTR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_ADMINDEFINE"><!-- --></A><H3>
+TAG_ADMINDEFINE</H3>
+<PRE>
+public static final int <B>TAG_ADMINDEFINE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_ADMINDEFINE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_INTEGER"><!-- --></A><H3>
+TAG_INTEGER</H3>
+<PRE>
+public static final int <B>TAG_INTEGER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_INTEGER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_BOOLEAN"><!-- --></A><H3>
+TAG_BOOLEAN</H3>
+<PRE>
+public static final int <B>TAG_BOOLEAN</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_BOOLEAN">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_ENUM"><!-- --></A><H3>
+TAG_ENUM</H3>
+<PRE>
+public static final int <B>TAG_ENUM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_ENUM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_STRING"><!-- --></A><H3>
+TAG_STRING</H3>
+<PRE>
+public static final int <B>TAG_STRING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_STRING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_DATE"><!-- --></A><H3>
+TAG_DATE</H3>
+<PRE>
+public static final int <B>TAG_DATE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_DATE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_RESOLUTION"><!-- --></A><H3>
+TAG_RESOLUTION</H3>
+<PRE>
+public static final int <B>TAG_RESOLUTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_RESOLUTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_RANGE"><!-- --></A><H3>
+TAG_RANGE</H3>
+<PRE>
+public static final int <B>TAG_RANGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_RANGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_BEGIN_COLLECTION"><!-- --></A><H3>
+TAG_BEGIN_COLLECTION</H3>
+<PRE>
+public static final int <B>TAG_BEGIN_COLLECTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_BEGIN_COLLECTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_TEXTLANG"><!-- --></A><H3>
+TAG_TEXTLANG</H3>
+<PRE>
+public static final int <B>TAG_TEXTLANG</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_TEXTLANG">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_NAMELANG"><!-- --></A><H3>
+TAG_NAMELANG</H3>
+<PRE>
+public static final int <B>TAG_NAMELANG</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_NAMELANG">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_END_COLLECTION"><!-- --></A><H3>
+TAG_END_COLLECTION</H3>
+<PRE>
+public static final int <B>TAG_END_COLLECTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_END_COLLECTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_TEXT"><!-- --></A><H3>
+TAG_TEXT</H3>
+<PRE>
+public static final int <B>TAG_TEXT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_TEXT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_NAME"><!-- --></A><H3>
+TAG_NAME</H3>
+<PRE>
+public static final int <B>TAG_NAME</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_NAME">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_KEYWORD"><!-- --></A><H3>
+TAG_KEYWORD</H3>
+<PRE>
+public static final int <B>TAG_KEYWORD</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_KEYWORD">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_URI"><!-- --></A><H3>
+TAG_URI</H3>
+<PRE>
+public static final int <B>TAG_URI</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_URI">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_URISCHEME"><!-- --></A><H3>
+TAG_URISCHEME</H3>
+<PRE>
+public static final int <B>TAG_URISCHEME</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_URISCHEME">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_CHARSET"><!-- --></A><H3>
+TAG_CHARSET</H3>
+<PRE>
+public static final int <B>TAG_CHARSET</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_CHARSET">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_LANGUAGE"><!-- --></A><H3>
+TAG_LANGUAGE</H3>
+<PRE>
+public static final int <B>TAG_LANGUAGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_LANGUAGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_MIMETYPE"><!-- --></A><H3>
+TAG_MIMETYPE</H3>
+<PRE>
+public static final int <B>TAG_MIMETYPE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_MIMETYPE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_MEMBERNAME"><!-- --></A><H3>
+TAG_MEMBERNAME</H3>
+<PRE>
+public static final int <B>TAG_MEMBERNAME</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_MEMBERNAME">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_MASK"><!-- --></A><H3>
+TAG_MASK</H3>
+<PRE>
+public static final int <B>TAG_MASK</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_MASK">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TAG_COPY"><!-- --></A><H3>
+TAG_COPY</H3>
+<PRE>
+public static final int <B>TAG_COPY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TAG_COPY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RES_PER_INCH"><!-- --></A><H3>
+RES_PER_INCH</H3>
+<PRE>
+public static final int <B>RES_PER_INCH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RES_PER_INCH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RES_PER_CM"><!-- --></A><H3>
+RES_PER_CM</H3>
+<PRE>
+public static final int <B>RES_PER_CM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RES_PER_CM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_NONE"><!-- --></A><H3>
+FINISHINGS_NONE</H3>
+<PRE>
+public static final int <B>FINISHINGS_NONE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_NONE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE"><!-- --></A><H3>
+FINISHINGS_STAPLE</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_PUNCH"><!-- --></A><H3>
+FINISHINGS_PUNCH</H3>
+<PRE>
+public static final int <B>FINISHINGS_PUNCH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_PUNCH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_COVER"><!-- --></A><H3>
+FINISHINGS_COVER</H3>
+<PRE>
+public static final int <B>FINISHINGS_COVER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_COVER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BIND"><!-- --></A><H3>
+FINISHINGS_BIND</H3>
+<PRE>
+public static final int <B>FINISHINGS_BIND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BIND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_SADDLE_STITCH"><!-- --></A><H3>
+FINISHINGS_SADDLE_STITCH</H3>
+<PRE>
+public static final int <B>FINISHINGS_SADDLE_STITCH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_SADDLE_STITCH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_EDGE_STITCH"><!-- --></A><H3>
+FINISHINGS_EDGE_STITCH</H3>
+<PRE>
+public static final int <B>FINISHINGS_EDGE_STITCH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_EDGE_STITCH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_FOLD"><!-- --></A><H3>
+FINISHINGS_FOLD</H3>
+<PRE>
+public static final int <B>FINISHINGS_FOLD</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_FOLD">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_TRIM"><!-- --></A><H3>
+FINISHINGS_TRIM</H3>
+<PRE>
+public static final int <B>FINISHINGS_TRIM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_TRIM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BALE"><!-- --></A><H3>
+FINISHINGS_BALE</H3>
+<PRE>
+public static final int <B>FINISHINGS_BALE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BALE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BOOKLET_MAKER"><!-- --></A><H3>
+FINISHINGS_BOOKLET_MAKER</H3>
+<PRE>
+public static final int <B>FINISHINGS_BOOKLET_MAKER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BOOKLET_MAKER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_JOB_OFFSET"><!-- --></A><H3>
+FINISHINGS_JOB_OFFSET</H3>
+<PRE>
+public static final int <B>FINISHINGS_JOB_OFFSET</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_JOB_OFFSET">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_TOP_LEFT"><!-- --></A><H3>
+FINISHINGS_STAPLE_TOP_LEFT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_TOP_LEFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_TOP_LEFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_BOTTOM_LEFT"><!-- --></A><H3>
+FINISHINGS_STAPLE_BOTTOM_LEFT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_BOTTOM_LEFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_BOTTOM_LEFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_TOP_RIGHT"><!-- --></A><H3>
+FINISHINGS_STAPLE_TOP_RIGHT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_TOP_RIGHT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_TOP_RIGHT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_BOTTOM_RIGHT"><!-- --></A><H3>
+FINISHINGS_STAPLE_BOTTOM_RIGHT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_BOTTOM_RIGHT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_BOTTOM_RIGHT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_EDGE_STITCH_LEFT"><!-- --></A><H3>
+FINISHINGS_EDGE_STITCH_LEFT</H3>
+<PRE>
+public static final int <B>FINISHINGS_EDGE_STITCH_LEFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_EDGE_STITCH_LEFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_EDGE_STITCH_TOP"><!-- --></A><H3>
+FINISHINGS_EDGE_STITCH_TOP</H3>
+<PRE>
+public static final int <B>FINISHINGS_EDGE_STITCH_TOP</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_EDGE_STITCH_TOP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_EDGE_STITCH_RIGHT"><!-- --></A><H3>
+FINISHINGS_EDGE_STITCH_RIGHT</H3>
+<PRE>
+public static final int <B>FINISHINGS_EDGE_STITCH_RIGHT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_EDGE_STITCH_RIGHT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_EDGE_STITCH_BOTTOM"><!-- --></A><H3>
+FINISHINGS_EDGE_STITCH_BOTTOM</H3>
+<PRE>
+public static final int <B>FINISHINGS_EDGE_STITCH_BOTTOM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_EDGE_STITCH_BOTTOM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_DUAL_LEFT"><!-- --></A><H3>
+FINISHINGS_STAPLE_DUAL_LEFT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_DUAL_LEFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_DUAL_LEFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_DUAL_TOP"><!-- --></A><H3>
+FINISHINGS_STAPLE_DUAL_TOP</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_DUAL_TOP</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_DUAL_TOP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_DUAL_RIGHT"><!-- --></A><H3>
+FINISHINGS_STAPLE_DUAL_RIGHT</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_DUAL_RIGHT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_DUAL_RIGHT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_STAPLE_DUAL_BOTTOM"><!-- --></A><H3>
+FINISHINGS_STAPLE_DUAL_BOTTOM</H3>
+<PRE>
+public static final int <B>FINISHINGS_STAPLE_DUAL_BOTTOM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_STAPLE_DUAL_BOTTOM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BIND_LEFT"><!-- --></A><H3>
+FINISHINGS_BIND_LEFT</H3>
+<PRE>
+public static final int <B>FINISHINGS_BIND_LEFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BIND_LEFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BIND_TOP"><!-- --></A><H3>
+FINISHINGS_BIND_TOP</H3>
+<PRE>
+public static final int <B>FINISHINGS_BIND_TOP</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BIND_TOP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BIND_RIGHT"><!-- --></A><H3>
+FINISHINGS_BIND_RIGHT</H3>
+<PRE>
+public static final int <B>FINISHINGS_BIND_RIGHT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BIND_RIGHT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FINISHINGS_BIND_BOTTOM"><!-- --></A><H3>
+FINISHINGS_BIND_BOTTOM</H3>
+<PRE>
+public static final int <B>FINISHINGS_BIND_BOTTOM</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FINISHINGS_BIND_BOTTOM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PORTRAIT"><!-- --></A><H3>
+PORTRAIT</H3>
+<PRE>
+public static final int <B>PORTRAIT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PORTRAIT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="LANDSCAPE"><!-- --></A><H3>
+LANDSCAPE</H3>
+<PRE>
+public static final int <B>LANDSCAPE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.LANDSCAPE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REVERSE_LANDSCAPE"><!-- --></A><H3>
+REVERSE_LANDSCAPE</H3>
+<PRE>
+public static final int <B>REVERSE_LANDSCAPE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REVERSE_LANDSCAPE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REVERSE_PORTRAIT"><!-- --></A><H3>
+REVERSE_PORTRAIT</H3>
+<PRE>
+public static final int <B>REVERSE_PORTRAIT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REVERSE_PORTRAIT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="QUALITY_DRAFT"><!-- --></A><H3>
+QUALITY_DRAFT</H3>
+<PRE>
+public static final int <B>QUALITY_DRAFT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.QUALITY_DRAFT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="QUALITY_NORMAL"><!-- --></A><H3>
+QUALITY_NORMAL</H3>
+<PRE>
+public static final int <B>QUALITY_NORMAL</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.QUALITY_NORMAL">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="QUALITY_HIGH"><!-- --></A><H3>
+QUALITY_HIGH</H3>
+<PRE>
+public static final int <B>QUALITY_HIGH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.QUALITY_HIGH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_PENDING"><!-- --></A><H3>
+JOB_PENDING</H3>
+<PRE>
+public static final int <B>JOB_PENDING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_PENDING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_HELD"><!-- --></A><H3>
+JOB_HELD</H3>
+<PRE>
+public static final int <B>JOB_HELD</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_HELD">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_PROCESSING"><!-- --></A><H3>
+JOB_PROCESSING</H3>
+<PRE>
+public static final int <B>JOB_PROCESSING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_PROCESSING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_STOPPED"><!-- --></A><H3>
+JOB_STOPPED</H3>
+<PRE>
+public static final int <B>JOB_STOPPED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_STOPPED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_CANCELLED"><!-- --></A><H3>
+JOB_CANCELLED</H3>
+<PRE>
+public static final int <B>JOB_CANCELLED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_CANCELLED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_ABORTED"><!-- --></A><H3>
+JOB_ABORTED</H3>
+<PRE>
+public static final int <B>JOB_ABORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_ABORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="JOB_COMPLETED"><!-- --></A><H3>
+JOB_COMPLETED</H3>
+<PRE>
+public static final int <B>JOB_COMPLETED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.JOB_COMPLETED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINTER_IDLE"><!-- --></A><H3>
+PRINTER_IDLE</H3>
+<PRE>
+public static final int <B>PRINTER_IDLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINTER_IDLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINTER_PROCESSING"><!-- --></A><H3>
+PRINTER_PROCESSING</H3>
+<PRE>
+public static final int <B>PRINTER_PROCESSING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINTER_PROCESSING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINTER_STOPPED"><!-- --></A><H3>
+PRINTER_STOPPED</H3>
+<PRE>
+public static final int <B>PRINTER_STOPPED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINTER_STOPPED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ERROR"><!-- --></A><H3>
+ERROR</H3>
+<PRE>
+public static final int <B>ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="IDLE"><!-- --></A><H3>
+IDLE</H3>
+<PRE>
+public static final int <B>IDLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.IDLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HEADER"><!-- --></A><H3>
+HEADER</H3>
+<PRE>
+public static final int <B>HEADER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.HEADER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ATTRIBUTE"><!-- --></A><H3>
+ATTRIBUTE</H3>
+<PRE>
+public static final int <B>ATTRIBUTE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ATTRIBUTE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DATA"><!-- --></A><H3>
+DATA</H3>
+<PRE>
+public static final int <B>DATA</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DATA">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINT_JOB"><!-- --></A><H3>
+PRINT_JOB</H3>
+<PRE>
+public static final int <B>PRINT_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINT_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINT_URI"><!-- --></A><H3>
+PRINT_URI</H3>
+<PRE>
+public static final int <B>PRINT_URI</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINT_URI">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="VALIDATE_JOB"><!-- --></A><H3>
+VALIDATE_JOB</H3>
+<PRE>
+public static final int <B>VALIDATE_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.VALIDATE_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CREATE_JOB"><!-- --></A><H3>
+CREATE_JOB</H3>
+<PRE>
+public static final int <B>CREATE_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CREATE_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SEND_DOCUMENT"><!-- --></A><H3>
+SEND_DOCUMENT</H3>
+<PRE>
+public static final int <B>SEND_DOCUMENT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SEND_DOCUMENT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SEND_URI"><!-- --></A><H3>
+SEND_URI</H3>
+<PRE>
+public static final int <B>SEND_URI</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SEND_URI">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CANCEL_JOB"><!-- --></A><H3>
+CANCEL_JOB</H3>
+<PRE>
+public static final int <B>CANCEL_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CANCEL_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_JOB_ATTRIBUTES"><!-- --></A><H3>
+GET_JOB_ATTRIBUTES</H3>
+<PRE>
+public static final int <B>GET_JOB_ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_JOB_ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_JOBS"><!-- --></A><H3>
+GET_JOBS</H3>
+<PRE>
+public static final int <B>GET_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_PRINTER_ATTRIBUTES"><!-- --></A><H3>
+GET_PRINTER_ATTRIBUTES</H3>
+<PRE>
+public static final int <B>GET_PRINTER_ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_PRINTER_ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HOLD_JOB"><!-- --></A><H3>
+HOLD_JOB</H3>
+<PRE>
+public static final int <B>HOLD_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.HOLD_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RELEASE_JOB"><!-- --></A><H3>
+RELEASE_JOB</H3>
+<PRE>
+public static final int <B>RELEASE_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RELEASE_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RESTART_JOB"><!-- --></A><H3>
+RESTART_JOB</H3>
+<PRE>
+public static final int <B>RESTART_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RESTART_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PAUSE_PRINTER"><!-- --></A><H3>
+PAUSE_PRINTER</H3>
+<PRE>
+public static final int <B>PAUSE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PAUSE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RESUME_PRINTER"><!-- --></A><H3>
+RESUME_PRINTER</H3>
+<PRE>
+public static final int <B>RESUME_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RESUME_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PURGE_JOBS"><!-- --></A><H3>
+PURGE_JOBS</H3>
+<PRE>
+public static final int <B>PURGE_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PURGE_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SET_PRINTER_ATTRIBUTES"><!-- --></A><H3>
+SET_PRINTER_ATTRIBUTES</H3>
+<PRE>
+public static final int <B>SET_PRINTER_ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SET_PRINTER_ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SET_JOB_ATTRIBUTES"><!-- --></A><H3>
+SET_JOB_ATTRIBUTES</H3>
+<PRE>
+public static final int <B>SET_JOB_ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SET_JOB_ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_PRINTER_SUPPORTED_VALUES"><!-- --></A><H3>
+GET_PRINTER_SUPPORTED_VALUES</H3>
+<PRE>
+public static final int <B>GET_PRINTER_SUPPORTED_VALUES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_PRINTER_SUPPORTED_VALUES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CREATE_PRINTER_SUBSCRIPTION"><!-- --></A><H3>
+CREATE_PRINTER_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>CREATE_PRINTER_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CREATE_PRINTER_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CREATE_JOB_SUBSCRIPTION"><!-- --></A><H3>
+CREATE_JOB_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>CREATE_JOB_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CREATE_JOB_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_SUBSCRIPTION_ATTRIBUTES"><!-- --></A><H3>
+GET_SUBSCRIPTION_ATTRIBUTES</H3>
+<PRE>
+public static final int <B>GET_SUBSCRIPTION_ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_SUBSCRIPTION_ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_SUBSCRIPTIONS"><!-- --></A><H3>
+GET_SUBSCRIPTIONS</H3>
+<PRE>
+public static final int <B>GET_SUBSCRIPTIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_SUBSCRIPTIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RENEW_SUBSCRIPTION"><!-- --></A><H3>
+RENEW_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>RENEW_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RENEW_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CANCEL_SUBSCRIPTION"><!-- --></A><H3>
+CANCEL_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>CANCEL_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CANCEL_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_NOTIFICATIONS"><!-- --></A><H3>
+GET_NOTIFICATIONS</H3>
+<PRE>
+public static final int <B>GET_NOTIFICATIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_NOTIFICATIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SEND_NOTIFICATIONS"><!-- --></A><H3>
+SEND_NOTIFICATIONS</H3>
+<PRE>
+public static final int <B>SEND_NOTIFICATIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SEND_NOTIFICATIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GET_PRINT_SUPPORT_FILES"><!-- --></A><H3>
+GET_PRINT_SUPPORT_FILES</H3>
+<PRE>
+public static final int <B>GET_PRINT_SUPPORT_FILES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GET_PRINT_SUPPORT_FILES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ENABLE_PRINTER"><!-- --></A><H3>
+ENABLE_PRINTER</H3>
+<PRE>
+public static final int <B>ENABLE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ENABLE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DISABLE_PRINTER"><!-- --></A><H3>
+DISABLE_PRINTER</H3>
+<PRE>
+public static final int <B>DISABLE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DISABLE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PAUSE_PRINTER_AFTER_CURRENT_JOB"><!-- --></A><H3>
+PAUSE_PRINTER_AFTER_CURRENT_JOB</H3>
+<PRE>
+public static final int <B>PAUSE_PRINTER_AFTER_CURRENT_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PAUSE_PRINTER_AFTER_CURRENT_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HOLD_NEW_JOBS"><!-- --></A><H3>
+HOLD_NEW_JOBS</H3>
+<PRE>
+public static final int <B>HOLD_NEW_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.HOLD_NEW_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RELEASE_HELD_NEW_JOBS"><!-- --></A><H3>
+RELEASE_HELD_NEW_JOBS</H3>
+<PRE>
+public static final int <B>RELEASE_HELD_NEW_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RELEASE_HELD_NEW_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DEACTIVATE_PRINTER"><!-- --></A><H3>
+DEACTIVATE_PRINTER</H3>
+<PRE>
+public static final int <B>DEACTIVATE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DEACTIVATE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ACTIVATE_PRINTER"><!-- --></A><H3>
+ACTIVATE_PRINTER</H3>
+<PRE>
+public static final int <B>ACTIVATE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ACTIVATE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RESTART_PRINTER"><!-- --></A><H3>
+RESTART_PRINTER</H3>
+<PRE>
+public static final int <B>RESTART_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RESTART_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SHUTDOWN_PRINTER"><!-- --></A><H3>
+SHUTDOWN_PRINTER</H3>
+<PRE>
+public static final int <B>SHUTDOWN_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SHUTDOWN_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="STARTUP_PRINTER"><!-- --></A><H3>
+STARTUP_PRINTER</H3>
+<PRE>
+public static final int <B>STARTUP_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.STARTUP_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REPROCESS_JOB"><!-- --></A><H3>
+REPROCESS_JOB</H3>
+<PRE>
+public static final int <B>REPROCESS_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REPROCESS_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CANCEL_CURRENT_JOB"><!-- --></A><H3>
+CANCEL_CURRENT_JOB</H3>
+<PRE>
+public static final int <B>CANCEL_CURRENT_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CANCEL_CURRENT_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SUSPEND_CURRENT_JOB"><!-- --></A><H3>
+SUSPEND_CURRENT_JOB</H3>
+<PRE>
+public static final int <B>SUSPEND_CURRENT_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SUSPEND_CURRENT_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="RESUME_JOB"><!-- --></A><H3>
+RESUME_JOB</H3>
+<PRE>
+public static final int <B>RESUME_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.RESUME_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PROMOTE_JOB"><!-- --></A><H3>
+PROMOTE_JOB</H3>
+<PRE>
+public static final int <B>PROMOTE_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PROMOTE_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SCHEDULE_JOB_AFTER"><!-- --></A><H3>
+SCHEDULE_JOB_AFTER</H3>
+<PRE>
+public static final int <B>SCHEDULE_JOB_AFTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SCHEDULE_JOB_AFTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRIVATE"><!-- --></A><H3>
+PRIVATE</H3>
+<PRE>
+public static final int <B>PRIVATE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRIVATE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_GET_DEFAULT"><!-- --></A><H3>
+CUPS_GET_DEFAULT</H3>
+<PRE>
+public static final int <B>CUPS_GET_DEFAULT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_GET_DEFAULT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_GET_PRINTERS"><!-- --></A><H3>
+CUPS_GET_PRINTERS</H3>
+<PRE>
+public static final int <B>CUPS_GET_PRINTERS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_GET_PRINTERS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_ADD_PRINTER"><!-- --></A><H3>
+CUPS_ADD_PRINTER</H3>
+<PRE>
+public static final int <B>CUPS_ADD_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_ADD_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_DELETE_PRINTER"><!-- --></A><H3>
+CUPS_DELETE_PRINTER</H3>
+<PRE>
+public static final int <B>CUPS_DELETE_PRINTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_DELETE_PRINTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_GET_CLASSES"><!-- --></A><H3>
+CUPS_GET_CLASSES</H3>
+<PRE>
+public static final int <B>CUPS_GET_CLASSES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_GET_CLASSES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_ADD_CLASS"><!-- --></A><H3>
+CUPS_ADD_CLASS</H3>
+<PRE>
+public static final int <B>CUPS_ADD_CLASS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_ADD_CLASS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_DELETE_CLASS"><!-- --></A><H3>
+CUPS_DELETE_CLASS</H3>
+<PRE>
+public static final int <B>CUPS_DELETE_CLASS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_DELETE_CLASS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_ACCEPT_JOBS"><!-- --></A><H3>
+CUPS_ACCEPT_JOBS</H3>
+<PRE>
+public static final int <B>CUPS_ACCEPT_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_ACCEPT_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_REJECT_JOBS"><!-- --></A><H3>
+CUPS_REJECT_JOBS</H3>
+<PRE>
+public static final int <B>CUPS_REJECT_JOBS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_REJECT_JOBS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_SET_DEFAULT"><!-- --></A><H3>
+CUPS_SET_DEFAULT</H3>
+<PRE>
+public static final int <B>CUPS_SET_DEFAULT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_SET_DEFAULT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_GET_DEVICES"><!-- --></A><H3>
+CUPS_GET_DEVICES</H3>
+<PRE>
+public static final int <B>CUPS_GET_DEVICES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_GET_DEVICES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_GET_PPDS"><!-- --></A><H3>
+CUPS_GET_PPDS</H3>
+<PRE>
+public static final int <B>CUPS_GET_PPDS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_GET_PPDS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_MOVE_JOB"><!-- --></A><H3>
+CUPS_MOVE_JOB</H3>
+<PRE>
+public static final int <B>CUPS_MOVE_JOB</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_MOVE_JOB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_ADD_DEVICE"><!-- --></A><H3>
+CUPS_ADD_DEVICE</H3>
+<PRE>
+public static final int <B>CUPS_ADD_DEVICE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_ADD_DEVICE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CUPS_DELETE_DEVICE"><!-- --></A><H3>
+CUPS_DELETE_DEVICE</H3>
+<PRE>
+public static final int <B>CUPS_DELETE_DEVICE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CUPS_DELETE_DEVICE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK"><!-- --></A><H3>
+OK</H3>
+<PRE>
+public static final int <B>OK</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_SUBST"><!-- --></A><H3>
+OK_SUBST</H3>
+<PRE>
+public static final int <B>OK_SUBST</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_SUBST">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_CONFLICT"><!-- --></A><H3>
+OK_CONFLICT</H3>
+<PRE>
+public static final int <B>OK_CONFLICT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_CONFLICT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_IGNORED_SUBSCRIPTIONS"><!-- --></A><H3>
+OK_IGNORED_SUBSCRIPTIONS</H3>
+<PRE>
+public static final int <B>OK_IGNORED_SUBSCRIPTIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_IGNORED_SUBSCRIPTIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_IGNORED_NOTIFICATIONS"><!-- --></A><H3>
+OK_IGNORED_NOTIFICATIONS</H3>
+<PRE>
+public static final int <B>OK_IGNORED_NOTIFICATIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_IGNORED_NOTIFICATIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_TOO_MANY_EVENTS"><!-- --></A><H3>
+OK_TOO_MANY_EVENTS</H3>
+<PRE>
+public static final int <B>OK_TOO_MANY_EVENTS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_TOO_MANY_EVENTS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OK_BUT_CANCEL_SUBSCRIPTION"><!-- --></A><H3>
+OK_BUT_CANCEL_SUBSCRIPTION</H3>
+<PRE>
+public static final int <B>OK_BUT_CANCEL_SUBSCRIPTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OK_BUT_CANCEL_SUBSCRIPTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REDIRECTION_OTHER_SITE"><!-- --></A><H3>
+REDIRECTION_OTHER_SITE</H3>
+<PRE>
+public static final int <B>REDIRECTION_OTHER_SITE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REDIRECTION_OTHER_SITE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="BAD_REQUEST"><!-- --></A><H3>
+BAD_REQUEST</H3>
+<PRE>
+public static final int <B>BAD_REQUEST</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.BAD_REQUEST">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FORBIDDEN"><!-- --></A><H3>
+FORBIDDEN</H3>
+<PRE>
+public static final int <B>FORBIDDEN</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.FORBIDDEN">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NOT_AUTHENTICATED"><!-- --></A><H3>
+NOT_AUTHENTICATED</H3>
+<PRE>
+public static final int <B>NOT_AUTHENTICATED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.NOT_AUTHENTICATED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NOT_AUTHORIZED"><!-- --></A><H3>
+NOT_AUTHORIZED</H3>
+<PRE>
+public static final int <B>NOT_AUTHORIZED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.NOT_AUTHORIZED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NOT_POSSIBLE"><!-- --></A><H3>
+NOT_POSSIBLE</H3>
+<PRE>
+public static final int <B>NOT_POSSIBLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.NOT_POSSIBLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TIMEOUT"><!-- --></A><H3>
+TIMEOUT</H3>
+<PRE>
+public static final int <B>TIMEOUT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TIMEOUT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NOT_FOUND"><!-- --></A><H3>
+NOT_FOUND</H3>
+<PRE>
+public static final int <B>NOT_FOUND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.NOT_FOUND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="GONE"><!-- --></A><H3>
+GONE</H3>
+<PRE>
+public static final int <B>GONE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.GONE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REQUEST_ENTITY"><!-- --></A><H3>
+REQUEST_ENTITY</H3>
+<PRE>
+public static final int <B>REQUEST_ENTITY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REQUEST_ENTITY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="REQUEST_VALUE"><!-- --></A><H3>
+REQUEST_VALUE</H3>
+<PRE>
+public static final int <B>REQUEST_VALUE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.REQUEST_VALUE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DOCUMENT_FORMAT"><!-- --></A><H3>
+DOCUMENT_FORMAT</H3>
+<PRE>
+public static final int <B>DOCUMENT_FORMAT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DOCUMENT_FORMAT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ATTRIBUTES"><!-- --></A><H3>
+ATTRIBUTES</H3>
+<PRE>
+public static final int <B>ATTRIBUTES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ATTRIBUTES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="URI_SCHEME"><!-- --></A><H3>
+URI_SCHEME</H3>
+<PRE>
+public static final int <B>URI_SCHEME</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.URI_SCHEME">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CHARSET"><!-- --></A><H3>
+CHARSET</H3>
+<PRE>
+public static final int <B>CHARSET</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CHARSET">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="CONFLICT"><!-- --></A><H3>
+CONFLICT</H3>
+<PRE>
+public static final int <B>CONFLICT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.CONFLICT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="COMPRESSION_NOT_SUPPORTED"><!-- --></A><H3>
+COMPRESSION_NOT_SUPPORTED</H3>
+<PRE>
+public static final int <B>COMPRESSION_NOT_SUPPORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.COMPRESSION_NOT_SUPPORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="COMPRESSION_ERROR"><!-- --></A><H3>
+COMPRESSION_ERROR</H3>
+<PRE>
+public static final int <B>COMPRESSION_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.COMPRESSION_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DOCUMENT_FORMAT_ERROR"><!-- --></A><H3>
+DOCUMENT_FORMAT_ERROR</H3>
+<PRE>
+public static final int <B>DOCUMENT_FORMAT_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DOCUMENT_FORMAT_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DOCUMENT_ACCESS_ERROR"><!-- --></A><H3>
+DOCUMENT_ACCESS_ERROR</H3>
+<PRE>
+public static final int <B>DOCUMENT_ACCESS_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DOCUMENT_ACCESS_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ATTRIBUTES_NOT_SETTABLE"><!-- --></A><H3>
+ATTRIBUTES_NOT_SETTABLE</H3>
+<PRE>
+public static final int <B>ATTRIBUTES_NOT_SETTABLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ATTRIBUTES_NOT_SETTABLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="IGNORED_ALL_SUBSCRIPTIONS"><!-- --></A><H3>
+IGNORED_ALL_SUBSCRIPTIONS</H3>
+<PRE>
+public static final int <B>IGNORED_ALL_SUBSCRIPTIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.IGNORED_ALL_SUBSCRIPTIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TOO_MANY_SUBSCRIPTIONS"><!-- --></A><H3>
+TOO_MANY_SUBSCRIPTIONS</H3>
+<PRE>
+public static final int <B>TOO_MANY_SUBSCRIPTIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TOO_MANY_SUBSCRIPTIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="IGNORED_ALL_NOTIFICATIONS"><!-- --></A><H3>
+IGNORED_ALL_NOTIFICATIONS</H3>
+<PRE>
+public static final int <B>IGNORED_ALL_NOTIFICATIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.IGNORED_ALL_NOTIFICATIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINT_SUPPORT_FILE_NOT_FOUND"><!-- --></A><H3>
+PRINT_SUPPORT_FILE_NOT_FOUND</H3>
+<PRE>
+public static final int <B>PRINT_SUPPORT_FILE_NOT_FOUND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINT_SUPPORT_FILE_NOT_FOUND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="INTERNAL_ERROR"><!-- --></A><H3>
+INTERNAL_ERROR</H3>
+<PRE>
+public static final int <B>INTERNAL_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.INTERNAL_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OPERATION_NOT_SUPPORTED"><!-- --></A><H3>
+OPERATION_NOT_SUPPORTED</H3>
+<PRE>
+public static final int <B>OPERATION_NOT_SUPPORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.OPERATION_NOT_SUPPORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SERVICE_UNAVAILABLE"><!-- --></A><H3>
+SERVICE_UNAVAILABLE</H3>
+<PRE>
+public static final int <B>SERVICE_UNAVAILABLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.SERVICE_UNAVAILABLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="VERSION_NOT_SUPPORTED"><!-- --></A><H3>
+VERSION_NOT_SUPPORTED</H3>
+<PRE>
+public static final int <B>VERSION_NOT_SUPPORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.VERSION_NOT_SUPPORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="DEVICE_ERROR"><!-- --></A><H3>
+DEVICE_ERROR</H3>
+<PRE>
+public static final int <B>DEVICE_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.DEVICE_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="TEMPORARY_ERROR"><!-- --></A><H3>
+TEMPORARY_ERROR</H3>
+<PRE>
+public static final int <B>TEMPORARY_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.TEMPORARY_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NOT_ACCEPTING"><!-- --></A><H3>
+NOT_ACCEPTING</H3>
+<PRE>
+public static final int <B>NOT_ACCEPTING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.NOT_ACCEPTING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINTER_BUSY"><!-- --></A><H3>
+PRINTER_BUSY</H3>
+<PRE>
+public static final int <B>PRINTER_BUSY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINTER_BUSY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="ERROR_JOB_CANCELLED"><!-- --></A><H3>
+ERROR_JOB_CANCELLED</H3>
+<PRE>
+public static final int <B>ERROR_JOB_CANCELLED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.ERROR_JOB_CANCELLED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="MULTIPLE_JOBS_NOT_SUPPORTED"><!-- --></A><H3>
+MULTIPLE_JOBS_NOT_SUPPORTED</H3>
+<PRE>
+public static final int <B>MULTIPLE_JOBS_NOT_SUPPORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.MULTIPLE_JOBS_NOT_SUPPORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PRINTER_IS_DEACTIVATED"><!-- --></A><H3>
+PRINTER_IS_DEACTIVATED</H3>
+<PRE>
+public static final int <B>PRINTER_IS_DEACTIVATED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPDefs.PRINTER_IS_DEACTIVATED">Constant Field Values</A></DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPDefs()"><!-- --></A><H3>
+IPPDefs</H3>
+<PRE>
+public <B>IPPDefs</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPAttribute.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPError.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPDefs.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPError.html b/scripting/java/docs/org/cups/IPPError.html
new file mode 100644
index 000000000..4baf7b321
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPError.html
@@ -0,0 +1,208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+IPPError
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPError,IPPError class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPError";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPDefs.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPHttp.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPError.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPError</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPError</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPError</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPError.html#IPPError(int)">IPPError</A></B>(int&nbsp;p_error)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor that sets <code>error_string</code> after creation.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPError(int)"><!-- --></A><H3>
+IPPError</H3>
+<PRE>
+public <B>IPPError</B>(int&nbsp;p_error)</PRE>
+<DL>
+<DD>Constructor that sets <code>error_string</code> after creation.
+<P>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPDefs.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPHttp.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPError.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPHttp.html b/scripting/java/docs/org/cups/IPPHttp.html
new file mode 100644
index 000000000..1cf4b5463
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPHttp.html
@@ -0,0 +1,2931 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+IPPHttp
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPHttp,IPPHttp class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPHttp";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPError.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPRequest.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPHttp.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPHttp</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPHttp</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPHttp</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#activity">activity</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#auth_type">auth_type</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.io.BufferedReader</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#br">br</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.net.Socket</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#conn">conn</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#connected">connected</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#days">days</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#error">error</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#hostname">hostname</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_0_9">HTTP_0_9</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_1_0">HTTP_1_0</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_1_1">HTTP_1_1</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ACCEPTED">HTTP_ACCEPTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_BASIC">HTTP_AUTH_BASIC</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_MD5">HTTP_AUTH_MD5</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_MD5_INT">HTTP_AUTH_MD5_INT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_MD5_SESS">HTTP_AUTH_MD5_SESS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_MD5_SESS_INT">HTTP_AUTH_MD5_SESS_INT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_AUTH_NONE">HTTP_AUTH_NONE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_BAD_GATEWAY">HTTP_BAD_GATEWAY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_BAD_REQUEST">HTTP_BAD_REQUEST</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_CLOSE">HTTP_CLOSE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_CONFLICT">HTTP_CONFLICT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#http_content_length">http_content_length</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_CONTINUE">HTTP_CONTINUE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_CREATED">HTTP_CREATED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_DELETE">HTTP_DELETE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCODE_CHUNKED">HTTP_ENCODE_CHUNKED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCODE_LENGTH">HTTP_ENCODE_LENGTH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCRYPT_ALWAYS">HTTP_ENCRYPT_ALWAYS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCRYPT_IF_REQUESTED">HTTP_ENCRYPT_IF_REQUESTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCRYPT_NEVER">HTTP_ENCRYPT_NEVER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ENCRYPT_REQUIRED">HTTP_ENCRYPT_REQUIRED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_ERROR">HTTP_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_ACCEPT_LANGUAGE">HTTP_FIELD_ACCEPT_LANGUAGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_ACCEPT_RANGES">HTTP_FIELD_ACCEPT_RANGES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_AUTHORIZATION">HTTP_FIELD_AUTHORIZATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONNECTION">HTTP_FIELD_CONNECTION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_ENCODING">HTTP_FIELD_CONTENT_ENCODING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LANGUAGE">HTTP_FIELD_CONTENT_LANGUAGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LENGTH">HTTP_FIELD_CONTENT_LENGTH</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_LOCATION">HTTP_FIELD_CONTENT_LOCATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_MD5">HTTP_FIELD_CONTENT_MD5</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_RANGE">HTTP_FIELD_CONTENT_RANGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_TYPE">HTTP_FIELD_CONTENT_TYPE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_CONTENT_VERSION">HTTP_FIELD_CONTENT_VERSION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_DATE">HTTP_FIELD_DATE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_HOST">HTTP_FIELD_HOST</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_IF_MODIFIED_SINCE">HTTP_FIELD_IF_MODIFIED_SINCE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_IF_UNMODIFIED_SINCE">HTTP_FIELD_IF_UNMODIFIED_SINCE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_KEEP_ALIVE">HTTP_FIELD_KEEP_ALIVE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_LAST_MODIFIED">HTTP_FIELD_LAST_MODIFIED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_LINK">HTTP_FIELD_LINK</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_LOCATION">HTTP_FIELD_LOCATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_MAX">HTTP_FIELD_MAX</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_RANGE">HTTP_FIELD_RANGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_REFERER">HTTP_FIELD_REFERER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_RETRY_AFTER">HTTP_FIELD_RETRY_AFTER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_TRANSFER_ENCODING">HTTP_FIELD_TRANSFER_ENCODING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_UNKNOWN">HTTP_FIELD_UNKNOWN</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_UPGRADE">HTTP_FIELD_UPGRADE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_USER_AGENT">HTTP_FIELD_USER_AGENT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FIELD_WWW_AUTHENTICATE">HTTP_FIELD_WWW_AUTHENTICATE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#http_fields">http_fields</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_FORBIDDEN">HTTP_FORBIDDEN</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_GATEWAY_TIMEOUT">HTTP_GATEWAY_TIMEOUT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_GET">HTTP_GET</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_GET_SEND">HTTP_GET_SEND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_GONE">HTTP_GONE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_HEAD">HTTP_HEAD</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_KEEPALIVE_OFF">HTTP_KEEPALIVE_OFF</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_KEEPALIVE_ON">HTTP_KEEPALIVE_ON</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_LENGTH_REQUIRED">HTTP_LENGTH_REQUIRED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_METHOD_NOT_ALLOWED">HTTP_METHOD_NOT_ALLOWED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_MOVED_PERMANENTLY">HTTP_MOVED_PERMANENTLY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_MOVED_TEMPORARILY">HTTP_MOVED_TEMPORARILY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_MULTIPLE_CHOICES">HTTP_MULTIPLE_CHOICES</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NO_CONTENT">HTTP_NO_CONTENT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_ACCEPTABLE">HTTP_NOT_ACCEPTABLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_AUTHORITATIVE">HTTP_NOT_AUTHORITATIVE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_FOUND">HTTP_NOT_FOUND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_IMPLEMENTED">HTTP_NOT_IMPLEMENTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_MODIFIED">HTTP_NOT_MODIFIED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_NOT_SUPPORTED">HTTP_NOT_SUPPORTED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_OK">HTTP_OK</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_OPTIONS">HTTP_OPTIONS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PARTIAL_CONTENT">HTTP_PARTIAL_CONTENT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PAYMENT_REQUIRED">HTTP_PAYMENT_REQUIRED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_POST">HTTP_POST</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_POST_RECV">HTTP_POST_RECV</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_POST_SEND">HTTP_POST_SEND</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PRECONDITION">HTTP_PRECONDITION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PROXY_AUTHENTICATION">HTTP_PROXY_AUTHENTICATION</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PUT">HTTP_PUT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_PUT_RECV">HTTP_PUT_RECV</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#http_request">http_request</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_REQUEST_TIMEOUT">HTTP_REQUEST_TIMEOUT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_REQUEST_TOO_LARGE">HTTP_REQUEST_TOO_LARGE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_RESET_CONTENT">HTTP_RESET_CONTENT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_SEE_OTHER">HTTP_SEE_OTHER</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_SERVER_ERROR">HTTP_SERVER_ERROR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_SERVICE_UNAVAILABLE">HTTP_SERVICE_UNAVAILABLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_STATUS">HTTP_STATUS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_SWITCHING_PROTOCOLS">HTTP_SWITCHING_PROTOCOLS</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_TRACE">HTTP_TRACE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_UNAUTHORIZED">HTTP_UNAUTHORIZED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_UNSUPPORTED_MEDIATYPE">HTTP_UNSUPPORTED_MEDIATYPE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_UPGRADE_REQUIRED">HTTP_UPGRADE_REQUIRED</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_URI_TOO_LONG">HTTP_URI_TOO_LONG</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_USE_PROXY">HTTP_USE_PROXY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#HTTP_WAITING">HTTP_WAITING</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class constants - most not in use yet.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.io.BufferedInputStream</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#is">is</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#method">method</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#months">months</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#nonce">nonce</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#opaque">opaque</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.io.BufferedOutputStream</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#os">os</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#passwd">passwd</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#path">path</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#port">port</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;char[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_buffer">read_buffer</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_charset">read_header_charset</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_content_language">read_header_content_language</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_content_length">read_header_content_length</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_content_type">read_header_content_type</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_date">read_header_date</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header_server">read_header_server</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#realm">realm</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#resource">resource</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#status">status</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#status_text">status_text</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#user">user</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#version">version</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#write_content_length">write_content_length</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#IPPHttp(java.lang.String)">IPPHttp</A></B>(java.lang.String&nbsp;request_url)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor using <code>URL</code>.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#IPPHttp(java.lang.String, java.lang.String, java.lang.String, java.lang.String)">IPPHttp</A></B>(java.lang.String&nbsp;request_url,
+ java.lang.String&nbsp;p_auth_type,
+ java.lang.String&nbsp;p_user,
+ java.lang.String&nbsp;p_passwd)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor using <code>URL, user and pass</code>.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#checkForResponse()">checkForResponse</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#parseAuthenticate(java.lang.String)">parseAuthenticate</A></B>(java.lang.String&nbsp;p_auth)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;org.cups.IPP</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#processResponse()">processResponse</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Process the HTTP response from the server.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_header()">read_header</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read the HTTP header from the input stream.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read_line()">read_line</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read a line from the input stream.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;char[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#read(int)">read</A></B>(int&nbsp;count)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Read up to <code>count</code> bytes from the input stream.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#reConnect()">reConnect</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Re-establish a dropped connection.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#setPassword(java.lang.String)">setPassword</A></B>(java.lang.String&nbsp;p_passwd)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the password.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#setUser(java.lang.String)">setUser</A></B>(java.lang.String&nbsp;p_user)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the user name.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#write(byte[])">write</A></B>(byte[]&nbsp;bytes)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Write bytes to the output stream.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#write(byte[], int)">write</A></B>(byte[]&nbsp;bytes,
+ int&nbsp;length)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Write bytes to the output stream.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPHttp.html#writeHeader(java.lang.String, int)">writeHeader</A></B>(java.lang.String&nbsp;request,
+ int&nbsp;content_length)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Write the request header bytes to the server.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="HTTP_WAITING"><!-- --></A><H3>
+HTTP_WAITING</H3>
+<PRE>
+public static final int <B>HTTP_WAITING</B></PRE>
+<DL>
+<DD>Class constants - most not in use yet.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_WAITING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_OPTIONS"><!-- --></A><H3>
+HTTP_OPTIONS</H3>
+<PRE>
+public static final int <B>HTTP_OPTIONS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_OPTIONS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_GET"><!-- --></A><H3>
+HTTP_GET</H3>
+<PRE>
+public static final int <B>HTTP_GET</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_GET">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_GET_SEND"><!-- --></A><H3>
+HTTP_GET_SEND</H3>
+<PRE>
+public static final int <B>HTTP_GET_SEND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_GET_SEND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_HEAD"><!-- --></A><H3>
+HTTP_HEAD</H3>
+<PRE>
+public static final int <B>HTTP_HEAD</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_HEAD">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_POST"><!-- --></A><H3>
+HTTP_POST</H3>
+<PRE>
+public static final int <B>HTTP_POST</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_POST">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_POST_RECV"><!-- --></A><H3>
+HTTP_POST_RECV</H3>
+<PRE>
+public static final int <B>HTTP_POST_RECV</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_POST_RECV">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_POST_SEND"><!-- --></A><H3>
+HTTP_POST_SEND</H3>
+<PRE>
+public static final int <B>HTTP_POST_SEND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_POST_SEND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PUT"><!-- --></A><H3>
+HTTP_PUT</H3>
+<PRE>
+public static final int <B>HTTP_PUT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PUT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PUT_RECV"><!-- --></A><H3>
+HTTP_PUT_RECV</H3>
+<PRE>
+public static final int <B>HTTP_PUT_RECV</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PUT_RECV">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_DELETE"><!-- --></A><H3>
+HTTP_DELETE</H3>
+<PRE>
+public static final int <B>HTTP_DELETE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_DELETE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_TRACE"><!-- --></A><H3>
+HTTP_TRACE</H3>
+<PRE>
+public static final int <B>HTTP_TRACE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_TRACE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_CLOSE"><!-- --></A><H3>
+HTTP_CLOSE</H3>
+<PRE>
+public static final int <B>HTTP_CLOSE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_CLOSE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_STATUS"><!-- --></A><H3>
+HTTP_STATUS</H3>
+<PRE>
+public static final int <B>HTTP_STATUS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_STATUS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_0_9"><!-- --></A><H3>
+HTTP_0_9</H3>
+<PRE>
+public static final int <B>HTTP_0_9</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_0_9">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_1_0"><!-- --></A><H3>
+HTTP_1_0</H3>
+<PRE>
+public static final int <B>HTTP_1_0</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_1_0">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_1_1"><!-- --></A><H3>
+HTTP_1_1</H3>
+<PRE>
+public static final int <B>HTTP_1_1</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_1_1">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_KEEPALIVE_OFF"><!-- --></A><H3>
+HTTP_KEEPALIVE_OFF</H3>
+<PRE>
+public static final int <B>HTTP_KEEPALIVE_OFF</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_KEEPALIVE_OFF">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_KEEPALIVE_ON"><!-- --></A><H3>
+HTTP_KEEPALIVE_ON</H3>
+<PRE>
+public static final int <B>HTTP_KEEPALIVE_ON</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_KEEPALIVE_ON">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCODE_LENGTH"><!-- --></A><H3>
+HTTP_ENCODE_LENGTH</H3>
+<PRE>
+public static final int <B>HTTP_ENCODE_LENGTH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCODE_LENGTH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCODE_CHUNKED"><!-- --></A><H3>
+HTTP_ENCODE_CHUNKED</H3>
+<PRE>
+public static final int <B>HTTP_ENCODE_CHUNKED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCODE_CHUNKED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCRYPT_IF_REQUESTED"><!-- --></A><H3>
+HTTP_ENCRYPT_IF_REQUESTED</H3>
+<PRE>
+public static final int <B>HTTP_ENCRYPT_IF_REQUESTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCRYPT_IF_REQUESTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCRYPT_NEVER"><!-- --></A><H3>
+HTTP_ENCRYPT_NEVER</H3>
+<PRE>
+public static final int <B>HTTP_ENCRYPT_NEVER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCRYPT_NEVER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCRYPT_REQUIRED"><!-- --></A><H3>
+HTTP_ENCRYPT_REQUIRED</H3>
+<PRE>
+public static final int <B>HTTP_ENCRYPT_REQUIRED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCRYPT_REQUIRED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ENCRYPT_ALWAYS"><!-- --></A><H3>
+HTTP_ENCRYPT_ALWAYS</H3>
+<PRE>
+public static final int <B>HTTP_ENCRYPT_ALWAYS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ENCRYPT_ALWAYS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_NONE"><!-- --></A><H3>
+HTTP_AUTH_NONE</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_NONE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_NONE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_BASIC"><!-- --></A><H3>
+HTTP_AUTH_BASIC</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_BASIC</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_BASIC">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_MD5"><!-- --></A><H3>
+HTTP_AUTH_MD5</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_MD5</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_MD5">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_MD5_SESS"><!-- --></A><H3>
+HTTP_AUTH_MD5_SESS</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_MD5_SESS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_MD5_SESS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_MD5_INT"><!-- --></A><H3>
+HTTP_AUTH_MD5_INT</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_MD5_INT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_MD5_INT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_AUTH_MD5_SESS_INT"><!-- --></A><H3>
+HTTP_AUTH_MD5_SESS_INT</H3>
+<PRE>
+public static final int <B>HTTP_AUTH_MD5_SESS_INT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_AUTH_MD5_SESS_INT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ERROR"><!-- --></A><H3>
+HTTP_ERROR</H3>
+<PRE>
+public static final int <B>HTTP_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_CONTINUE"><!-- --></A><H3>
+HTTP_CONTINUE</H3>
+<PRE>
+public static final int <B>HTTP_CONTINUE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_CONTINUE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_SWITCHING_PROTOCOLS"><!-- --></A><H3>
+HTTP_SWITCHING_PROTOCOLS</H3>
+<PRE>
+public static final int <B>HTTP_SWITCHING_PROTOCOLS</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_SWITCHING_PROTOCOLS">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_OK"><!-- --></A><H3>
+HTTP_OK</H3>
+<PRE>
+public static final int <B>HTTP_OK</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_OK">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_CREATED"><!-- --></A><H3>
+HTTP_CREATED</H3>
+<PRE>
+public static final int <B>HTTP_CREATED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_CREATED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_ACCEPTED"><!-- --></A><H3>
+HTTP_ACCEPTED</H3>
+<PRE>
+public static final int <B>HTTP_ACCEPTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_ACCEPTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_AUTHORITATIVE"><!-- --></A><H3>
+HTTP_NOT_AUTHORITATIVE</H3>
+<PRE>
+public static final int <B>HTTP_NOT_AUTHORITATIVE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_AUTHORITATIVE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NO_CONTENT"><!-- --></A><H3>
+HTTP_NO_CONTENT</H3>
+<PRE>
+public static final int <B>HTTP_NO_CONTENT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NO_CONTENT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_RESET_CONTENT"><!-- --></A><H3>
+HTTP_RESET_CONTENT</H3>
+<PRE>
+public static final int <B>HTTP_RESET_CONTENT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_RESET_CONTENT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PARTIAL_CONTENT"><!-- --></A><H3>
+HTTP_PARTIAL_CONTENT</H3>
+<PRE>
+public static final int <B>HTTP_PARTIAL_CONTENT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PARTIAL_CONTENT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_MULTIPLE_CHOICES"><!-- --></A><H3>
+HTTP_MULTIPLE_CHOICES</H3>
+<PRE>
+public static final int <B>HTTP_MULTIPLE_CHOICES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_MULTIPLE_CHOICES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_MOVED_PERMANENTLY"><!-- --></A><H3>
+HTTP_MOVED_PERMANENTLY</H3>
+<PRE>
+public static final int <B>HTTP_MOVED_PERMANENTLY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_MOVED_PERMANENTLY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_MOVED_TEMPORARILY"><!-- --></A><H3>
+HTTP_MOVED_TEMPORARILY</H3>
+<PRE>
+public static final int <B>HTTP_MOVED_TEMPORARILY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_MOVED_TEMPORARILY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_SEE_OTHER"><!-- --></A><H3>
+HTTP_SEE_OTHER</H3>
+<PRE>
+public static final int <B>HTTP_SEE_OTHER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_SEE_OTHER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_MODIFIED"><!-- --></A><H3>
+HTTP_NOT_MODIFIED</H3>
+<PRE>
+public static final int <B>HTTP_NOT_MODIFIED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_MODIFIED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_USE_PROXY"><!-- --></A><H3>
+HTTP_USE_PROXY</H3>
+<PRE>
+public static final int <B>HTTP_USE_PROXY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_USE_PROXY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_BAD_REQUEST"><!-- --></A><H3>
+HTTP_BAD_REQUEST</H3>
+<PRE>
+public static final int <B>HTTP_BAD_REQUEST</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_BAD_REQUEST">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_UNAUTHORIZED"><!-- --></A><H3>
+HTTP_UNAUTHORIZED</H3>
+<PRE>
+public static final int <B>HTTP_UNAUTHORIZED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_UNAUTHORIZED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PAYMENT_REQUIRED"><!-- --></A><H3>
+HTTP_PAYMENT_REQUIRED</H3>
+<PRE>
+public static final int <B>HTTP_PAYMENT_REQUIRED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PAYMENT_REQUIRED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FORBIDDEN"><!-- --></A><H3>
+HTTP_FORBIDDEN</H3>
+<PRE>
+public static final int <B>HTTP_FORBIDDEN</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FORBIDDEN">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_FOUND"><!-- --></A><H3>
+HTTP_NOT_FOUND</H3>
+<PRE>
+public static final int <B>HTTP_NOT_FOUND</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_FOUND">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_METHOD_NOT_ALLOWED"><!-- --></A><H3>
+HTTP_METHOD_NOT_ALLOWED</H3>
+<PRE>
+public static final int <B>HTTP_METHOD_NOT_ALLOWED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_METHOD_NOT_ALLOWED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_ACCEPTABLE"><!-- --></A><H3>
+HTTP_NOT_ACCEPTABLE</H3>
+<PRE>
+public static final int <B>HTTP_NOT_ACCEPTABLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_ACCEPTABLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PROXY_AUTHENTICATION"><!-- --></A><H3>
+HTTP_PROXY_AUTHENTICATION</H3>
+<PRE>
+public static final int <B>HTTP_PROXY_AUTHENTICATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PROXY_AUTHENTICATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_REQUEST_TIMEOUT"><!-- --></A><H3>
+HTTP_REQUEST_TIMEOUT</H3>
+<PRE>
+public static final int <B>HTTP_REQUEST_TIMEOUT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_REQUEST_TIMEOUT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_CONFLICT"><!-- --></A><H3>
+HTTP_CONFLICT</H3>
+<PRE>
+public static final int <B>HTTP_CONFLICT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_CONFLICT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_GONE"><!-- --></A><H3>
+HTTP_GONE</H3>
+<PRE>
+public static final int <B>HTTP_GONE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_GONE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_LENGTH_REQUIRED"><!-- --></A><H3>
+HTTP_LENGTH_REQUIRED</H3>
+<PRE>
+public static final int <B>HTTP_LENGTH_REQUIRED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_LENGTH_REQUIRED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_PRECONDITION"><!-- --></A><H3>
+HTTP_PRECONDITION</H3>
+<PRE>
+public static final int <B>HTTP_PRECONDITION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_PRECONDITION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_REQUEST_TOO_LARGE"><!-- --></A><H3>
+HTTP_REQUEST_TOO_LARGE</H3>
+<PRE>
+public static final int <B>HTTP_REQUEST_TOO_LARGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_REQUEST_TOO_LARGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_URI_TOO_LONG"><!-- --></A><H3>
+HTTP_URI_TOO_LONG</H3>
+<PRE>
+public static final int <B>HTTP_URI_TOO_LONG</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_URI_TOO_LONG">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_UNSUPPORTED_MEDIATYPE"><!-- --></A><H3>
+HTTP_UNSUPPORTED_MEDIATYPE</H3>
+<PRE>
+public static final int <B>HTTP_UNSUPPORTED_MEDIATYPE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_UNSUPPORTED_MEDIATYPE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_UPGRADE_REQUIRED"><!-- --></A><H3>
+HTTP_UPGRADE_REQUIRED</H3>
+<PRE>
+public static final int <B>HTTP_UPGRADE_REQUIRED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_UPGRADE_REQUIRED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_SERVER_ERROR"><!-- --></A><H3>
+HTTP_SERVER_ERROR</H3>
+<PRE>
+public static final int <B>HTTP_SERVER_ERROR</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_SERVER_ERROR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_IMPLEMENTED"><!-- --></A><H3>
+HTTP_NOT_IMPLEMENTED</H3>
+<PRE>
+public static final int <B>HTTP_NOT_IMPLEMENTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_IMPLEMENTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_BAD_GATEWAY"><!-- --></A><H3>
+HTTP_BAD_GATEWAY</H3>
+<PRE>
+public static final int <B>HTTP_BAD_GATEWAY</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_BAD_GATEWAY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_SERVICE_UNAVAILABLE"><!-- --></A><H3>
+HTTP_SERVICE_UNAVAILABLE</H3>
+<PRE>
+public static final int <B>HTTP_SERVICE_UNAVAILABLE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_SERVICE_UNAVAILABLE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_GATEWAY_TIMEOUT"><!-- --></A><H3>
+HTTP_GATEWAY_TIMEOUT</H3>
+<PRE>
+public static final int <B>HTTP_GATEWAY_TIMEOUT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_GATEWAY_TIMEOUT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_NOT_SUPPORTED"><!-- --></A><H3>
+HTTP_NOT_SUPPORTED</H3>
+<PRE>
+public static final int <B>HTTP_NOT_SUPPORTED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_NOT_SUPPORTED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_UNKNOWN"><!-- --></A><H3>
+HTTP_FIELD_UNKNOWN</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_UNKNOWN</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_UNKNOWN">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_ACCEPT_LANGUAGE"><!-- --></A><H3>
+HTTP_FIELD_ACCEPT_LANGUAGE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_ACCEPT_LANGUAGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_ACCEPT_LANGUAGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_ACCEPT_RANGES"><!-- --></A><H3>
+HTTP_FIELD_ACCEPT_RANGES</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_ACCEPT_RANGES</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_ACCEPT_RANGES">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_AUTHORIZATION"><!-- --></A><H3>
+HTTP_FIELD_AUTHORIZATION</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_AUTHORIZATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_AUTHORIZATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONNECTION"><!-- --></A><H3>
+HTTP_FIELD_CONNECTION</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONNECTION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONNECTION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_ENCODING"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_ENCODING</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_ENCODING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_ENCODING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_LANGUAGE"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_LANGUAGE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_LANGUAGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_LANGUAGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_LENGTH"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_LENGTH</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_LENGTH</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_LENGTH">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_LOCATION"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_LOCATION</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_LOCATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_LOCATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_MD5"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_MD5</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_MD5</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_MD5">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_RANGE"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_RANGE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_RANGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_RANGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_TYPE"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_TYPE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_TYPE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_TYPE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_CONTENT_VERSION"><!-- --></A><H3>
+HTTP_FIELD_CONTENT_VERSION</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_CONTENT_VERSION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_CONTENT_VERSION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_DATE"><!-- --></A><H3>
+HTTP_FIELD_DATE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_DATE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_DATE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_HOST"><!-- --></A><H3>
+HTTP_FIELD_HOST</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_HOST</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_HOST">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_IF_MODIFIED_SINCE"><!-- --></A><H3>
+HTTP_FIELD_IF_MODIFIED_SINCE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_IF_MODIFIED_SINCE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_IF_MODIFIED_SINCE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_IF_UNMODIFIED_SINCE"><!-- --></A><H3>
+HTTP_FIELD_IF_UNMODIFIED_SINCE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_IF_UNMODIFIED_SINCE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_IF_UNMODIFIED_SINCE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_KEEP_ALIVE"><!-- --></A><H3>
+HTTP_FIELD_KEEP_ALIVE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_KEEP_ALIVE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_KEEP_ALIVE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_LAST_MODIFIED"><!-- --></A><H3>
+HTTP_FIELD_LAST_MODIFIED</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_LAST_MODIFIED</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_LAST_MODIFIED">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_LINK"><!-- --></A><H3>
+HTTP_FIELD_LINK</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_LINK</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_LINK">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_LOCATION"><!-- --></A><H3>
+HTTP_FIELD_LOCATION</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_LOCATION</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_LOCATION">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_RANGE"><!-- --></A><H3>
+HTTP_FIELD_RANGE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_RANGE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_RANGE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_REFERER"><!-- --></A><H3>
+HTTP_FIELD_REFERER</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_REFERER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_REFERER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_RETRY_AFTER"><!-- --></A><H3>
+HTTP_FIELD_RETRY_AFTER</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_RETRY_AFTER</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_RETRY_AFTER">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_TRANSFER_ENCODING"><!-- --></A><H3>
+HTTP_FIELD_TRANSFER_ENCODING</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_TRANSFER_ENCODING</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_TRANSFER_ENCODING">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_UPGRADE"><!-- --></A><H3>
+HTTP_FIELD_UPGRADE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_UPGRADE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_UPGRADE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_USER_AGENT"><!-- --></A><H3>
+HTTP_FIELD_USER_AGENT</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_USER_AGENT</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_USER_AGENT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_WWW_AUTHENTICATE"><!-- --></A><H3>
+HTTP_FIELD_WWW_AUTHENTICATE</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_WWW_AUTHENTICATE</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_WWW_AUTHENTICATE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="HTTP_FIELD_MAX"><!-- --></A><H3>
+HTTP_FIELD_MAX</H3>
+<PRE>
+public static final int <B>HTTP_FIELD_MAX</B></PRE>
+<DL>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../constant-values.html#org.cups.IPPHttp.HTTP_FIELD_MAX">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="http_fields"><!-- --></A><H3>
+http_fields</H3>
+<PRE>
+public static final java.lang.String[] <B>http_fields</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="days"><!-- --></A><H3>
+days</H3>
+<PRE>
+public static final java.lang.String[] <B>days</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="months"><!-- --></A><H3>
+months</H3>
+<PRE>
+public static final java.lang.String[] <B>months</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="conn"><!-- --></A><H3>
+conn</H3>
+<PRE>
+public java.net.Socket <B>conn</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="connected"><!-- --></A><H3>
+connected</H3>
+<PRE>
+public boolean <B>connected</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="is"><!-- --></A><H3>
+is</H3>
+<PRE>
+public java.io.BufferedInputStream <B>is</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="br"><!-- --></A><H3>
+br</H3>
+<PRE>
+public java.io.BufferedReader <B>br</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="os"><!-- --></A><H3>
+os</H3>
+<PRE>
+public java.io.BufferedOutputStream <B>os</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="write_content_length"><!-- --></A><H3>
+write_content_length</H3>
+<PRE>
+public int <B>write_content_length</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_date"><!-- --></A><H3>
+read_header_date</H3>
+<PRE>
+public java.lang.String <B>read_header_date</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_server"><!-- --></A><H3>
+read_header_server</H3>
+<PRE>
+public java.lang.String <B>read_header_server</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_charset"><!-- --></A><H3>
+read_header_charset</H3>
+<PRE>
+public java.lang.String <B>read_header_charset</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_content_language"><!-- --></A><H3>
+read_header_content_language</H3>
+<PRE>
+public java.lang.String <B>read_header_content_language</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_content_type"><!-- --></A><H3>
+read_header_content_type</H3>
+<PRE>
+public java.lang.String <B>read_header_content_type</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_header_content_length"><!-- --></A><H3>
+read_header_content_length</H3>
+<PRE>
+public int <B>read_header_content_length</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="read_buffer"><!-- --></A><H3>
+read_buffer</H3>
+<PRE>
+public char[] <B>read_buffer</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="status"><!-- --></A><H3>
+status</H3>
+<PRE>
+public int <B>status</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="status_text"><!-- --></A><H3>
+status_text</H3>
+<PRE>
+public java.lang.String <B>status_text</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="version"><!-- --></A><H3>
+version</H3>
+<PRE>
+public java.lang.String <B>version</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="error"><!-- --></A><H3>
+error</H3>
+<PRE>
+public int <B>error</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="activity"><!-- --></A><H3>
+activity</H3>
+<PRE>
+public int <B>activity</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="hostname"><!-- --></A><H3>
+hostname</H3>
+<PRE>
+public java.lang.String <B>hostname</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="port"><!-- --></A><H3>
+port</H3>
+<PRE>
+public int <B>port</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="path"><!-- --></A><H3>
+path</H3>
+<PRE>
+public java.lang.String <B>path</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="user"><!-- --></A><H3>
+user</H3>
+<PRE>
+public java.lang.String <B>user</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="passwd"><!-- --></A><H3>
+passwd</H3>
+<PRE>
+public java.lang.String <B>passwd</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="auth_type"><!-- --></A><H3>
+auth_type</H3>
+<PRE>
+public java.lang.String <B>auth_type</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="realm"><!-- --></A><H3>
+realm</H3>
+<PRE>
+public java.lang.String <B>realm</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="opaque"><!-- --></A><H3>
+opaque</H3>
+<PRE>
+public java.lang.String <B>opaque</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="nonce"><!-- --></A><H3>
+nonce</H3>
+<PRE>
+public java.lang.String <B>nonce</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="resource"><!-- --></A><H3>
+resource</H3>
+<PRE>
+public java.lang.String <B>resource</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="method"><!-- --></A><H3>
+method</H3>
+<PRE>
+public java.lang.String <B>method</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="http_request"><!-- --></A><H3>
+http_request</H3>
+<PRE>
+public java.lang.String <B>http_request</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="http_content_length"><!-- --></A><H3>
+http_content_length</H3>
+<PRE>
+public int <B>http_content_length</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPHttp(java.lang.String)"><!-- --></A><H3>
+IPPHttp</H3>
+<PRE>
+public <B>IPPHttp</B>(java.lang.String&nbsp;request_url)
+ throws java.io.IOException,
+ java.net.UnknownHostException</PRE>
+<DL>
+<DD>Constructor using <code>URL</code>.
+<P>
+<DT><B>Parameters:</B><DD><CODE>request_url</CODE> - <code>URL</code> of server to connect to.</DL>
+<HR>
+
+<A NAME="IPPHttp(java.lang.String, java.lang.String, java.lang.String, java.lang.String)"><!-- --></A><H3>
+IPPHttp</H3>
+<PRE>
+public <B>IPPHttp</B>(java.lang.String&nbsp;request_url,
+ java.lang.String&nbsp;p_auth_type,
+ java.lang.String&nbsp;p_user,
+ java.lang.String&nbsp;p_passwd)
+ throws java.io.IOException,
+ java.net.UnknownHostException</PRE>
+<DL>
+<DD>Constructor using <code>URL, user and pass</code>.
+<P>
+<DT><B>Parameters:</B><DD><CODE>request_url</CODE> - <code>URL</code> of server to connect to.<DD><CODE>p_auth_type</CODE> - <code>String</code> basic or digest.<DD><CODE>p_user</CODE> - <code>String</code> User name.<DD><CODE>p_passwd</CODE> - <code>String</code> password.</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="reConnect()"><!-- --></A><H3>
+reConnect</H3>
+<PRE>
+public boolean <B>reConnect</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Re-establish a dropped connection.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> True if connected.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setUser(java.lang.String)"><!-- --></A><H3>
+setUser</H3>
+<PRE>
+public void <B>setUser</B>(java.lang.String&nbsp;p_user)</PRE>
+<DL>
+<DD>Set the user name.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_user</CODE> - <code>String</code> - user name.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setPassword(java.lang.String)"><!-- --></A><H3>
+setPassword</H3>
+<PRE>
+public void <B>setPassword</B>(java.lang.String&nbsp;p_passwd)</PRE>
+<DL>
+<DD>Set the password.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>p_passwd</CODE> - <code>String</code> - password.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="writeHeader(java.lang.String, int)"><!-- --></A><H3>
+writeHeader</H3>
+<PRE>
+public int <B>writeHeader</B>(java.lang.String&nbsp;request,
+ int&nbsp;content_length)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Write the request header bytes to the server.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>request</CODE> - <code>String</code> - the request.<DD><CODE>content_length</CODE> - <code>int</code> - size of the total request.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="checkForResponse()"><!-- --></A><H3>
+checkForResponse</H3>
+<PRE>
+public int <B>checkForResponse</B>()</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="write(byte[])"><!-- --></A><H3>
+write</H3>
+<PRE>
+public void <B>write</B>(byte[]&nbsp;bytes)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Write bytes to the output stream.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>bytes</CODE> - Array of bytes to write to the stream.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="write(byte[], int)"><!-- --></A><H3>
+write</H3>
+<PRE>
+public void <B>write</B>(byte[]&nbsp;bytes,
+ int&nbsp;length)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Write bytes to the output stream.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>bytes</CODE> - Array of bytes to write to the stream.<DD><CODE>length</CODE> - Number of bytes to write to the stream.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="read_header()"><!-- --></A><H3>
+read_header</H3>
+<PRE>
+public int <B>read_header</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Read the HTTP header from the input stream.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>int</code> Content length of response.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="read_line()"><!-- --></A><H3>
+read_line</H3>
+<PRE>
+public java.lang.String <B>read_line</B>()
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Read a line from the input stream.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>String</code> Line read.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="read(int)"><!-- --></A><H3>
+read</H3>
+<PRE>
+public char[] <B>read</B>(int&nbsp;count)
+ throws java.io.IOException</PRE>
+<DL>
+<DD>Read up to <code>count</code> bytes from the input stream.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>char[]</code> Character array of data read.
+<DD><CODE>java.io.IOException</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="processResponse()"><!-- --></A><H3>
+processResponse</H3>
+<PRE>
+public org.cups.IPP <B>processResponse</B>()</PRE>
+<DL>
+<DD>Process the HTTP response from the server.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>IPP</code> IPP object containing response data.<DT><B>See Also:</B><DD><code>IPP</code>,
+<code>IPPRequest</code>,
+<code>IPPAttribute</code>,
+<code>IPPValue</code>,
+<code>IPPDefs</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="parseAuthenticate(java.lang.String)"><!-- --></A><H3>
+parseAuthenticate</H3>
+<PRE>
+public void <B>parseAuthenticate</B>(java.lang.String&nbsp;p_auth)</PRE>
+<DL>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPError.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPRequest.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPHttp.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPRequest.html b/scripting/java/docs/org/cups/IPPRequest.html
new file mode 100644
index 000000000..9ed2d6090
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPRequest.html
@@ -0,0 +1,290 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:31 EDT 2003 -->
+<TITLE>
+IPPRequest
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPRequest,IPPRequest class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPRequest";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPHttp.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPStatus.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPRequest.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPRequest</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPRequest</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPRequest</B><DT>extends java.lang.Object</DL>
+
+<P>
+An <code>IPPRequest</code> object is used to hold the
+ status and id's of a request.
+<P>
+
+<P>
+<DL>
+<DT><B>Since:</B></DT>
+ <DD>JDK1.3</DD>
+</DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPRequest.html#IPPRequest()">IPPRequest</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPRequest.html#IPPRequest(int, short)">IPPRequest</A></B>(int&nbsp;p_request_id,
+ short&nbsp;p_operation_id)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor using request id and operation id.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPRequest.html#setOpStatus(short)">setOpStatus</A></B>(short&nbsp;p_status_code)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the operation status of a request.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPRequest.html#setStatus(short)">setStatus</A></B>(short&nbsp;p_status_code)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the current status of a request.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPRequest()"><!-- --></A><H3>
+IPPRequest</H3>
+<PRE>
+public <B>IPPRequest</B>()</PRE>
+<DL>
+<DD>Constructor
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPRequest(int, short)"><!-- --></A><H3>
+IPPRequest</H3>
+<PRE>
+public <B>IPPRequest</B>(int&nbsp;p_request_id,
+ short&nbsp;p_operation_id)</PRE>
+<DL>
+<DD>Constructor using request id and operation id.
+<P>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="setStatus(short)"><!-- --></A><H3>
+setStatus</H3>
+<PRE>
+public void <B>setStatus</B>(short&nbsp;p_status_code)</PRE>
+<DL>
+<DD>Set the current status of a request.
+<P>
+<DD><DL>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setOpStatus(short)"><!-- --></A><H3>
+setOpStatus</H3>
+<PRE>
+public void <B>setOpStatus</B>(short&nbsp;p_status_code)</PRE>
+<DL>
+<DD>Set the operation status of a request.
+<P>
+<DD><DL>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPHttp.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPStatus.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPRequest.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPStatus.html b/scripting/java/docs/org/cups/IPPStatus.html
new file mode 100644
index 000000000..9f65ba85f
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPStatus.html
@@ -0,0 +1,218 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:31 EDT 2003 -->
+<TITLE>
+IPPStatus
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPStatus,IPPStatus class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPStatus";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPRequest.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPURLConnection.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPStatus.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPStatus</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPStatus</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPStatus</B><DT>extends java.lang.Object</DL>
+
+<P>
+Class to convert a status code to text.
+<P>
+
+<P>
+<DL>
+<DT><B>Since:</B></DT>
+ <DD>JDK1.3</DD>
+</DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPStatus.html#IPPStatus(int)">IPPStatus</A></B>(int&nbsp;p_status)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor, access the <code>status_text</code> member
+ after creation.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPStatus(int)"><!-- --></A><H3>
+IPPStatus</H3>
+<PRE>
+public <B>IPPStatus</B>(int&nbsp;p_status)</PRE>
+<DL>
+<DD>Constructor, access the <code>status_text</code> member
+ after creation.
+<P>
+<DT><B>See Also:</B><DD><code>IPPDefs</code></DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPRequest.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPURLConnection.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPStatus.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.lang.Object">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPURLConnection.html b/scripting/java/docs/org/cups/IPPURLConnection.html
new file mode 100644
index 000000000..164e2c3dc
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPURLConnection.html
@@ -0,0 +1,315 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:31 EDT 2003 -->
+<TITLE>
+IPPURLConnection
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPURLConnection,IPPURLConnection class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPURLConnection";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPStatus.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPValue.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPURLConnection.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_java.net.URLConnection">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPURLConnection</H2>
+<PRE>
+java.lang.Object
+ |
+ +--java.net.URLConnection
+ |
+ +--<B>org.cups.IPPURLConnection</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPURLConnection</B><DT>extends java.net.URLConnection</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_java.net.URLConnection"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Fields inherited from class java.net.URLConnection</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>allowUserInteraction, connected, doInput, doOutput, ifModifiedSince, url, useCaches</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPURLConnection.html#IPPURLConnection(java.net.URL)">IPPURLConnection</A></B>(java.net.URL&nbsp;url)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Constructor.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPURLConnection.html#connect()">connect</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Not used.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPURLConnection.html#disconnect()">disconnect</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Not used.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPURLConnection.html#usingProxy()">usingProxy</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Determine if using proxy.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.net.URLConnection"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.net.URLConnection</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>addRequestProperty, getAllowUserInteraction, getContent, getContent, getContentEncoding, getContentLength, getContentType, getDate, getDefaultAllowUserInteraction, getDefaultRequestProperty, getDefaultUseCaches, getDoInput, getDoOutput, getExpiration, getFileNameMap, getHeaderField, getHeaderField, getHeaderFieldDate, getHeaderFieldInt, getHeaderFieldKey, getHeaderFields, getIfModifiedSince, getInputStream, getLastModified, getOutputStream, getPermission, getRequestProperties, getRequestProperty, getURL, getUseCaches, guessContentTypeFromName, guessContentTypeFromStream, setAllowUserInteraction, setContentHandlerFactory, setDefaultAllowUserInteraction, setDefaultRequestProperty, setDefaultUseCaches, setDoInput, setDoOutput, setFileNameMap, setIfModifiedSince, setRequestProperty, setUseCaches, toString</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPURLConnection(java.net.URL)"><!-- --></A><H3>
+IPPURLConnection</H3>
+<PRE>
+public <B>IPPURLConnection</B>(java.net.URL&nbsp;url)</PRE>
+<DL>
+<DD>Constructor.
+<P>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="usingProxy()"><!-- --></A><H3>
+usingProxy</H3>
+<PRE>
+public boolean <B>usingProxy</B>()</PRE>
+<DL>
+<DD>Determine if using proxy.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>boolean</code> Always <code>false</code> for now.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="connect()"><!-- --></A><H3>
+connect</H3>
+<PRE>
+public void <B>connect</B>()</PRE>
+<DL>
+<DD>Not used.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>connect</CODE> in class <CODE>java.net.URLConnection</CODE></DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="disconnect()"><!-- --></A><H3>
+disconnect</H3>
+<PRE>
+public void <B>disconnect</B>()</PRE>
+<DL>
+<DD>Not used.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPStatus.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../org/cups/IPPValue.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPURLConnection.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_java.net.URLConnection">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/org/cups/IPPValue.html b/scripting/java/docs/org/cups/IPPValue.html
new file mode 100644
index 000000000..ae174d4c2
--- /dev/null
+++ b/scripting/java/docs/org/cups/IPPValue.html
@@ -0,0 +1,400 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:31 EDT 2003 -->
+<TITLE>
+IPPValue
+</TITLE>
+<META NAME="keywords" CONTENT="org.cups.IPPValue,IPPValue class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IPPValue";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPURLConnection.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPValue.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.cups</FONT>
+<BR>
+Class IPPValue</H2>
+<PRE>
+java.lang.Object
+ |
+ +--<B>org.cups.IPPValue</B>
+</PRE>
+<HR>
+<DL>
+<DT>public class <B>IPPValue</B><DT>extends java.lang.Object</DL>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(boolean)">IPPValue</A></B>(boolean&nbsp;p_boolean)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(byte)">IPPValue</A></B>(byte&nbsp;p_byte)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Byte constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(byte, int, int)">IPPValue</A></B>(byte&nbsp;p_units,
+ int&nbsp;p_xres,
+ int&nbsp;p_yres)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Resolution constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(char[])">IPPValue</A></B>(char[]&nbsp;p_date)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(int)">IPPValue</A></B>(int&nbsp;p_int)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(int, boolean)">IPPValue</A></B>(int&nbsp;p_int,
+ boolean&nbsp;anything)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Enum constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(int, char[])">IPPValue</A></B>(int&nbsp;p_length,
+ char[]&nbsp;p_data)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Raw data constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(int, int)">IPPValue</A></B>(int&nbsp;p_lower,
+ int&nbsp;p_upper)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Range constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(short)">IPPValue</A></B>(short&nbsp;p_short)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Short constructor.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPValue(java.lang.String, java.lang.String)">IPPValue</A></B>(java.lang.String&nbsp;p_charset,
+ java.lang.String&nbsp;p_text)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String constructor.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../org/cups/IPPValue.html#IPPDateToTime()">IPPDateToTime</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Convert an IPP Date value to Unix Time.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPValue(byte)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(byte&nbsp;p_byte)</PRE>
+<DL>
+<DD>Byte constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(short)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(short&nbsp;p_short)</PRE>
+<DL>
+<DD>Short constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(int)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(int&nbsp;p_int)</PRE>
+<DL>
+<DD>Integer constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(int, boolean)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(int&nbsp;p_int,
+ boolean&nbsp;anything)</PRE>
+<DL>
+<DD>Enum constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(boolean)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(boolean&nbsp;p_boolean)</PRE>
+<DL>
+<DD>Boolean constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(char[])"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(char[]&nbsp;p_date)</PRE>
+<DL>
+<DD>Date constructor. Also set the <code>unix_time</code> member.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(java.lang.String, java.lang.String)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(java.lang.String&nbsp;p_charset,
+ java.lang.String&nbsp;p_text)</PRE>
+<DL>
+<DD>String constructor. Set the <code>string</code> and
+ <code>charset</code> values.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(int, int)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(int&nbsp;p_lower,
+ int&nbsp;p_upper)</PRE>
+<DL>
+<DD>Range constructor. Automatically swap as needed.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(byte, int, int)"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(byte&nbsp;p_units,
+ int&nbsp;p_xres,
+ int&nbsp;p_yres)</PRE>
+<DL>
+<DD>Resolution constructor.
+<P>
+</DL>
+<HR>
+
+<A NAME="IPPValue(int, char[])"><!-- --></A><H3>
+IPPValue</H3>
+<PRE>
+public <B>IPPValue</B>(int&nbsp;p_length,
+ char[]&nbsp;p_data)</PRE>
+<DL>
+<DD>Raw data constructor.
+<P>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IPPDateToTime()"><!-- --></A><H3>
+IPPDateToTime</H3>
+<PRE>
+public long <B>IPPDateToTime</B>()</PRE>
+<DL>
+<DD>Convert an IPP Date value to Unix Time.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD><code>long</code> Unix time in seconds.<DT><B>See Also:</B><DD><code>IPPCalender</code></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../org/cups/IPPURLConnection.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="../../index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="IPPValue.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="../../allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/overview-tree.html b/scripting/java/docs/overview-tree.html
new file mode 100644
index 000000000..b1d1a053a
--- /dev/null
+++ b/scripting/java/docs/overview-tree.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:29 EDT 2003 -->
+<TITLE>
+Class Hierarchy
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Class Hierarchy";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="overview-tree.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H2>
+Hierarchy For All Packages</H2>
+</CENTER>
+<DL>
+<DT><B>Package Hierarchies:</B><DD><A HREF="org/cups/package-tree.html">org.cups</A></DL>
+<HR>
+<H2>
+Class Hierarchy
+</H2>
+<UL>
+<LI TYPE="circle">class java.lang.Object<UL>
+<LI TYPE="circle">class org.cups.<A HREF="org/cups/Cups.html"><B>Cups</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/CupsJob.html"><B>CupsJob</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/CupsPrinter.html"><B>CupsPrinter</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPP.html"><B>IPP</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPAttribute.html"><B>IPPAttribute</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPDefs.html"><B>IPPDefs</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPError.html"><B>IPPError</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPHttp.html"><B>IPPHttp</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPRequest.html"><B>IPPRequest</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPStatus.html"><B>IPPStatus</B></A><LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPValue.html"><B>IPPValue</B></A><LI TYPE="circle">class java.net.URLConnection<UL>
+<LI TYPE="circle">class org.cups.<A HREF="org/cups/IPPURLConnection.html"><B>IPPURLConnection</B></A></UL>
+</UL>
+</UL>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="overview-tree.html" TARGET="_top"><B>NO FRAMES</B></A> &nbsp;
+&nbsp;
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/package-list b/scripting/java/docs/package-list
new file mode 100644
index 000000000..ea630cc10
--- /dev/null
+++ b/scripting/java/docs/package-list
@@ -0,0 +1 @@
+org.cups
diff --git a/scripting/java/docs/packages.html b/scripting/java/docs/packages.html
new file mode 100644
index 000000000..18cf2b4e2
--- /dev/null
+++ b/scripting/java/docs/packages.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 11 14:20:30 EDT 2003 -->
+<TITLE>
+
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<BODY BGCOLOR="white">
+
+<BR>
+
+<BR>
+
+<BR>
+<CENTER>
+The front page has been relocated.Please see:
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Frame version</A>
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="org/cups/package-summary.html">Non-frame version.</A></CENTER>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/serialized-form.html b/scripting/java/docs/serialized-form.html
new file mode 100644
index 000000000..ed30f6fe6
--- /dev/null
+++ b/scripting/java/docs/serialized-form.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Tue Feb 11 14:29:07 PST 2003 -->
+<TITLE>
+Serialized Form
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<BODY BGCOLOR="white">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="com/easysw/cups/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="serialized-form.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+Serialized Form</H1>
+</CENTER>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="com/easysw/cups/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A> &nbsp;
+&nbsp;<A HREF="serialized-form.html" TARGET="_top"><B>NO FRAMES</B></A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/scripting/java/docs/stylesheet.css b/scripting/java/docs/stylesheet.css
new file mode 100644
index 000000000..b62ecb51b
--- /dev/null
+++ b/scripting/java/docs/stylesheet.css
@@ -0,0 +1,29 @@
+/* Javadoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF }
+
+/* Table colors */
+.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
+.TableSubHeadingColor { background: #EEEEFF } /* Light mauve */
+.TableRowColor { background: #FFFFFF } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+.FrameHeadingFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+.FrameItemFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+
+/* Example of smaller, sans-serif font in frames */
+/* .FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */
+
+/* Navigation bar fonts and colors */
+.NavBarCell1 { background-color:#EEEEFF;}/* Light mauve */
+.NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */
+.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}
+
+.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+
diff --git a/scripting/java/example/GLP.java b/scripting/java/example/GLP.java
new file mode 100644
index 000000000..421c9180b
--- /dev/null
+++ b/scripting/java/example/GLP.java
@@ -0,0 +1,59 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLP implements ActionListener
+{
+ private JTabbedPane mainPanel = null;
+
+ // Constructor
+ public GLP()
+ {
+ GLPvars.init();
+
+ GLPvars.mainGLPPanel = new JTabbedPane();
+ GLPvars.tabs = new GLPtabs();
+ GLPvars.mainGLPPanel = GLPvars.tabs.getPanel();
+ }
+
+ // Implementation of ActionListener interface.
+ public void actionPerformed(ActionEvent event)
+ {
+ // if ("comboBoxChanged".equals(event.getActionCommand()))
+ // {
+ // update the icon to display the new phase
+ // phaseIconLabel.setIcon(images[phaseChoices.getSelectedIndex()]);
+ // }
+ }
+
+ // main method
+ public static void main(String[] args)
+ {
+ // create a new instance of CupsApplet
+ GLP app = new GLP();
+
+ // Create a frame and container for the panels.
+ JFrame glpFrame = new JFrame("Java GLP");
+
+ // Set the look and feel.
+ try {
+ UIManager.setLookAndFeel(
+ UIManager.getCrossPlatformLookAndFeelClassName());
+ } catch(Exception e) {}
+
+ glpFrame.setContentPane(GLPvars.mainGLPPanel);
+
+ // Exit when the window is closed.
+ glpFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ glpFrame.setSize(600,400);
+
+ // Show the converter.
+ // glpFrame.pack();
+ glpFrame.setVisible(true);
+ }
+}
diff --git a/scripting/java/example/GLPcolors.java b/scripting/java/example/GLPcolors.java
new file mode 100644
index 000000000..008945c2b
--- /dev/null
+++ b/scripting/java/example/GLPcolors.java
@@ -0,0 +1,22 @@
+
+import java.awt.*;
+import javax.swing.*;
+import org.cups.*;
+
+public class GLPcolors
+{
+
+ public static Color backgroundColor = new Color(0xff,0xff,0xff);
+ public static Color errorlightColor = new Color(0xcf,0x66,0x66);
+ public static Color highlightColor = new Color(0x99,0x99,0x66);
+ public static Color foregroundColor = new Color(0,0,0);
+
+ public static Color labelBackgroundColor = new Color( 0x66, 0xcf, 0x66 );
+
+ public static Color tabBackgroundColor = new Color(0x22,0x22,0x8f);
+ public static Color tabForegroundColor = new Color(0xff,0xff,0xff);
+
+ public static Color buttonForegroundColor = new Color(0xff,0xff,0xff);
+ public static Color buttonBackgroundColor = new Color(0x22,0x22,0x8f);
+
+}
diff --git a/scripting/java/example/GLPdetail.java b/scripting/java/example/GLPdetail.java
new file mode 100644
index 000000000..bec6e1259
--- /dev/null
+++ b/scripting/java/example/GLPdetail.java
@@ -0,0 +1,279 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPdetail implements ActionListener
+{
+ private JPanel mainPanel = null;
+ private JPanel controlPanel = null;
+ private JPanel detailPanel = null;
+ private JScrollPane jobPanel = null;
+ private BoxLayout mainLayout = null;
+
+ private JLabel tmp = null;
+
+ private JButton completedButton = null;
+ private JButton myJobsButton = null;
+ private JButton printFileButton = null;
+
+ private String completedText = "Show Completed";
+ private String myJobsText = "Show My Jobs";
+ private String printFileText = "Print a file";
+
+ private GLPprinterDetail detail = null;
+ private GLPjobList joblist = null;
+ private CupsPrinter printer = null;
+ private Cups cups = null;
+
+
+ public GLPdetail()
+ {
+ URL u;
+
+ mainPanel = new JPanel();
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+
+ // Create the buttons panel
+ controlPanel = new JPanel();
+ controlPanel.setLayout(new GridLayout(1,3,2,2));
+ controlPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ controlPanel.setBackground(GLPcolors.backgroundColor);
+ completedButton = new JButton(completedText);
+ myJobsButton = new JButton(myJobsText);
+ printFileButton = new JButton(printFileText);
+
+ completedButton.setActionCommand(completedText);
+ completedButton.addActionListener(this);
+
+ myJobsButton.setActionCommand(myJobsText);
+ myJobsButton.addActionListener(this);
+
+ printFileButton.setActionCommand(printFileText);
+ printFileButton.addActionListener(this);
+
+ completedButton.setBackground(GLPcolors.buttonBackgroundColor);
+ completedButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ myJobsButton.setBackground(GLPcolors.buttonBackgroundColor);
+ myJobsButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ printFileButton.setBackground(GLPcolors.buttonBackgroundColor);
+ printFileButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ controlPanel.add(completedButton);
+ controlPanel.add(myJobsButton);
+ controlPanel.add(printFileButton);
+
+ // -----------------------------------------------------------
+ //
+ // Now get the printer objects
+ //
+ if (GLPvars.selectedPrinterName != null)
+ {
+ try
+ {
+ u = new URL("http://" + GLPvars.getServerName() +
+ ":631/printers/" + GLPvars.selectedPrinterName );
+ cups = new Cups(u);
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+ printer = new CupsPrinter( cups, GLPvars.selectedPrinterName );
+
+ detail = new GLPprinterDetail( printer );
+ joblist = new GLPjobList(printer);
+
+ detailPanel = detail.getPanel();
+ jobPanel = joblist.getPanel();
+
+ mainLayout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
+ mainPanel.setLayout(mainLayout);
+ mainPanel.add(detailPanel);
+ mainPanel.add(controlPanel);
+ mainPanel.add(jobPanel);
+ }
+ catch (IOException e)
+ {
+ tmp = new JLabel("Error loading printer: " + GLPvars.selectedPrinterName);
+ mainPanel.add(tmp);
+ return;
+ }
+ }
+ else
+ {
+ tmp = new JLabel("No printer selected.");
+ mainPanel.add(tmp);
+ }
+
+
+ } //
+
+
+
+ public void topDetail()
+ {
+ URL u;
+
+ mainPanel = new JPanel();
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+
+ // Create the buttons panel
+ controlPanel = new JPanel();
+ controlPanel.setLayout(new GridLayout(1,3,2,2));
+ controlPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ controlPanel.setBackground(GLPcolors.backgroundColor);
+ completedButton = new JButton();
+ myJobsButton = new JButton();
+ printFileButton = new JButton(printFileText);
+
+ if (GLPvars.showCompletedJobs)
+ {
+ completedButton.setText("Show Active");
+ completedButton.setActionCommand("Show Active");
+ }
+ else
+ {
+ completedButton.setText("Show Completed");
+ completedButton.setActionCommand("Show Completed");
+ }
+ completedButton.addActionListener(this);
+
+ if (GLPvars.showMyJobs)
+ {
+ myJobsButton.setText("Show All Users");
+ myJobsButton.setActionCommand("Show All Users");
+ }
+ else
+ {
+ myJobsButton.setText("Show My Jobs");
+ myJobsButton.setActionCommand("Show My Jobs");
+ }
+ myJobsButton.addActionListener(this);
+
+ printFileButton.setActionCommand(printFileText);
+ printFileButton.addActionListener(this);
+
+ completedButton.setBackground(GLPcolors.buttonBackgroundColor);
+ completedButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ myJobsButton.setBackground(GLPcolors.buttonBackgroundColor);
+ myJobsButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ printFileButton.setBackground(GLPcolors.buttonBackgroundColor);
+ printFileButton.setForeground(GLPcolors.buttonForegroundColor);
+
+ controlPanel.add(completedButton);
+ controlPanel.add(myJobsButton);
+ controlPanel.add(printFileButton);
+
+ // -----------------------------------------------------------
+ //
+ // Now get the printer objects
+ //
+ if (GLPvars.selectedPrinterName != null)
+ {
+ try
+ {
+ //
+ // Create connection
+ //
+ u = new URL("http://" + GLPvars.getServerName() +
+ ":631/printers/" + GLPvars.selectedPrinterName );
+ cups = new Cups(u);
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+ //
+ //
+
+ printer = new CupsPrinter( cups, GLPvars.selectedPrinterName );
+ detail = new GLPprinterDetail( printer );
+ joblist = new GLPjobList(printer);
+
+ detailPanel = detail.getPanel();
+
+ jobPanel = joblist.getPanel();
+
+ mainLayout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
+ mainPanel.setLayout(mainLayout);
+ mainPanel.add(detailPanel);
+ mainPanel.add(controlPanel);
+ mainPanel.add(jobPanel);
+ }
+ catch (IOException e)
+ {
+ tmp = new JLabel("IOException while loading printer: " +
+ GLPvars.selectedPrinterName);
+ mainPanel.add(tmp);
+ return;
+ }
+ }
+ else
+ {
+ tmp = new JLabel("No printer selected.");
+ mainPanel.add(tmp);
+ }
+ }
+
+ public JPanel getPanel()
+ {
+ return(mainPanel);
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ // String source = e.getActionCommand();
+ Object source = e.getSource();
+ if (source == completedButton)
+ {
+ if (GLPvars.showCompletedJobs)
+ {
+ GLPvars.showCompletedJobs = !GLPvars.showCompletedJobs;
+ completedButton.setText("Show Active");
+ completedButton.setActionCommand("Show Active");
+ GLPvars.tabs.updateDetailPanel();
+ GLPvars.tabs.tabPanel.setSelectedIndex(2);
+ }
+ else
+ {
+ completedButton.setText("Show Completed");
+ completedButton.setActionCommand("Show Completed");
+ GLPvars.showCompletedJobs = !GLPvars.showCompletedJobs;
+ GLPvars.tabs.updateDetailPanel();
+ GLPvars.tabs.tabPanel.setSelectedIndex(2);
+ }
+ }
+ else if (source == myJobsButton)
+ {
+ if (GLPvars.showMyJobs)
+ {
+ GLPvars.showMyJobs = !GLPvars.showMyJobs;
+ myJobsButton.setText("Show All Users");
+ myJobsButton.setActionCommand("Show All Users");
+ GLPvars.tabs.updateDetailPanel();
+ GLPvars.tabs.tabPanel.setSelectedIndex(2);
+ }
+ else
+ {
+ GLPvars.showMyJobs = !GLPvars.showMyJobs;
+ myJobsButton.setText("Show My Jobs");
+ myJobsButton.setActionCommand("Show My Jobs");
+ GLPvars.tabs.updateDetailPanel();
+ GLPvars.tabs.tabPanel.setSelectedIndex(2);
+ }
+ }
+ else if (source == printFileButton)
+ {
+ if (printer != null)
+ {
+ GLPvars.tabs.updateOptionsPanel(printer);
+ GLPvars.tabs.tabPanel.setSelectedIndex(3);
+ }
+ }
+ }
+
+}
+
diff --git a/scripting/java/example/GLPjobList.java b/scripting/java/example/GLPjobList.java
new file mode 100644
index 000000000..ab149f3b4
--- /dev/null
+++ b/scripting/java/example/GLPjobList.java
@@ -0,0 +1,150 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import org.cups.*;
+
+public class GLPjobList implements ActionListener
+{
+ Cups cups = null;
+ GridLayout mainLayout = null;
+ JPanel errorPanel = null;
+ JScrollPane jobPane = null;
+
+ public GLPjobList(CupsPrinter cp)
+ {
+ load(cp);
+ }
+
+ // Constructor
+ public void load(CupsPrinter cp)
+ {
+ URL u;
+ CupsJob[] jobs;
+ int num_jobs = 0;
+
+ try
+ {
+ u = new URL("http://" + GLPvars.cupsServerName + ":631/printers/" +
+ cp.getPrinterName());
+ cups = new Cups(u);
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+
+ jobs = cups.cupsGetJobs(GLPvars.showMyJobs,
+ GLPvars.showCompletedJobs );
+ }
+ catch (IOException e)
+ {
+ GLPjobTableModel tm = new GLPjobTableModel(1,1);
+ tm.setValueAt("Error getting job list(IOException)",0,0);
+ JTable table = new JTable(tm);
+ jobPane = new JScrollPane(table);
+ jobPane.setBackground(GLPcolors.backgroundColor);
+ return;
+ }
+
+ if (jobs == null)
+ {
+ String job_user = "";
+ String job_type = "";
+ if (GLPvars.showCompletedJobs)
+ job_type = "No completed jobs";
+ else
+ job_type = "No active jobs";
+ if (GLPvars.showMyJobs)
+ job_user = " for " + GLPvars.cupsUser;
+
+ GLPjobTableModel tm = new GLPjobTableModel(1,1);
+ tm.setValueAt(job_type + job_user + ".",0,0);
+ JTable table = new JTable(tm);
+ jobPane = new JScrollPane(table);
+ jobPane.setBackground(GLPcolors.backgroundColor);
+ return;
+ }
+
+ num_jobs = jobs.length;
+ int jobcount = 0;
+ for (int i=0; i < num_jobs; i++)
+ {
+ if (jobs[i].job_id < 0)
+ continue;
+ jobcount++;
+ }
+
+ if (jobcount < 1)
+ {
+ GLPjobTableModel tm = new GLPjobTableModel(1,1);
+ String comp_str = "active";
+ if (GLPvars.showCompletedJobs)
+ comp_str = "completed";
+
+ tm.setValueAt("No " + comp_str + " jobs on " +
+ cp.getPrinterName(),0,0);
+ JTable table = new JTable(tm);
+ jobPane = new JScrollPane(table);
+ jobPane.setBackground(GLPcolors.backgroundColor);
+ return;
+ }
+
+ GLPjobTableModel tm = new GLPjobTableModel(jobcount,6);
+ tm.setColumnName(0,"ID");
+ tm.setColumnName(1,"Name");
+ tm.setColumnName(2,"User");
+ tm.setColumnName(3,"Create Time");
+ tm.setColumnName(4,"Size");
+ tm.setColumnName(5,"Status");
+
+ String szString;
+ Date date = new Date();
+ int currjob = 0;
+ for (int i=0; i < num_jobs; i++)
+ {
+ //
+ // Bug in cupsGetJobs?
+ //
+ if (jobs[i].job_id < 0)
+ continue;
+
+ tm.setValueAt( new Integer( jobs[i].job_id), currjob, 0 );
+ tm.setValueAt( (Object)jobs[i].job_name, currjob, 1 );
+ tm.setValueAt( (Object)jobs[i].job_originating_user_name,currjob,2);
+
+ date.setTime(jobs[i].time_at_creation * 1000);
+ tm.setValueAt( date.toString(), currjob, 3 );
+
+ if (jobs[i].job_k_octets < 1000)
+ szString = Integer.toString(jobs[i].job_k_octets) + "k";
+ else
+ szString = Double.toString((float)jobs[i].job_k_octets / 1000.0) + "mb";
+ tm.setValueAt( szString, currjob, 4 );
+ tm.setValueAt( jobs[i].jobStatusText(), currjob, 5 );
+ currjob++;
+ }
+
+ JTable table = new JTable( tm );
+
+ jobPane = new JScrollPane(table);
+ jobPane.setBackground(GLPcolors.backgroundColor);
+ jobPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ jobPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ // if (e.getActionCommand().equals(maskFieldString))
+ // {
+ // }
+ }
+
+
+ public JScrollPane getPanel()
+ {
+ return(jobPane);
+ }
+
+}
diff --git a/scripting/java/example/GLPjobTableModel.java b/scripting/java/example/GLPjobTableModel.java
new file mode 100644
index 000000000..6f5827bcb
--- /dev/null
+++ b/scripting/java/example/GLPjobTableModel.java
@@ -0,0 +1,104 @@
+
+import javax.swing.table.*;
+import javax.swing.event.TableModelListener;
+import javax.swing.event.TableModelEvent;
+import org.cups.*;
+
+public class GLPjobTableModel extends AbstractTableModel
+ implements TableModelListener
+{
+ protected TableModel model;
+ private final Object[][] rowData;
+ private final String[] colNames;
+ private int rowCount = 0;
+ private int colCount = 0;
+
+ public GLPjobTableModel( int num_rows, int num_cols )
+ {
+ rowData = new Object[num_rows][num_cols];
+ colNames = new String[num_cols];
+ rowCount = num_rows;
+ colCount = num_cols;
+ }
+
+ public TableModel getModel()
+ {
+ return model;
+ }
+
+ public void setModel(TableModel model)
+ {
+ this.model = model;
+ model.addTableModelListener(this);
+ }
+
+ // By default, implement TableModel by forwarding all messages
+ // to the model.
+
+ public Object getValueAt(int aRow, int aColumn)
+ {
+ if (rowCount >= aRow && colCount >= aColumn)
+ return (rowData[aRow][aColumn]);
+ else
+ return(null);
+ }
+
+ public void setValueAt(Object aValue, int aRow, int aColumn)
+ {
+ if (rowCount >= aRow && colCount >= aColumn)
+ rowData[aRow][aColumn] = aValue;
+ }
+
+ public int getRowCount()
+ {
+ return (rowCount);
+ }
+
+ public int getColumnCount()
+ {
+ return (colCount);
+ }
+
+ public void setColumnName(int aColumn, String aName)
+ {
+ if (colCount >= aColumn)
+ {
+ colNames[aColumn] = aName;
+ }
+ }
+
+ public String getColumnName(int aColumn)
+ {
+ if (colCount >= aColumn)
+ return (colNames[aColumn]);
+ else
+ return("");
+ }
+
+ public Class getColumnClass(int aColumn)
+ {
+ if (colCount >= aColumn)
+ {
+ if (rowData[0][aColumn] != null)
+ return (rowData[0][aColumn].getClass());
+ else
+ return( null );
+ }
+ else return(null);
+ }
+
+ public boolean isCellEditable(int row, int column)
+ {
+ return(false);
+ }
+
+
+//
+// Implementation of the TableModelListener interface,
+//
+ // By default forward all events to all the listeners.
+ public void tableChanged(TableModelEvent e)
+ {
+ fireTableChanged(e);
+ }
+}
diff --git a/scripting/java/example/GLPoptions.java b/scripting/java/example/GLPoptions.java
new file mode 100644
index 000000000..81057d09d
--- /dev/null
+++ b/scripting/java/example/GLPoptions.java
@@ -0,0 +1,662 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPoptions implements ActionListener
+{
+ Cups cups = null;
+ CupsJob job = null;
+ CupsPrinter printer = null;
+
+ String fileName = "";
+
+ JPanel mainPanel;
+ JTextField fileTextField;
+ JButton printButton;
+ GridBagLayout mainLayout;
+ GridBagConstraints mainConst;
+
+ //
+ // Print options;
+ //
+ String[] jobSheetsNames;
+ String[] orientationNames;
+ int[] orientationValues;
+ String[] qualityNames;
+ int[] qualityValues;
+
+ String jobSheetsOption = "";
+ int orientationOption = -1;
+ int qualityOption = -1;
+
+ int pageLowerOption = 0;
+ int pageUpperOption = 0;
+ boolean pagePrintAll = true;
+
+ int numCopiesOption = 1;
+ int numLowerCopiesOption = -1;
+ int numUpperCopiesOption = -1;
+
+ int selectedJobSheets = 0;
+ int selectedOrientation = 0;
+ int selectedQuality = 0;
+
+ JComboBox orientationBox;
+ JComboBox jobSheetsBox;
+ JTextField numCopiesField;
+ JCheckBox printAllCheckBox;
+ JTextField pageLowerField;
+ JTextField pageUpperField;
+ MyTextListener textListener = new MyTextListener();
+
+
+ // Constructor
+ public GLPoptions()
+ {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+ JLabel label = new JLabel("No printer selected");
+ label.setForeground(GLPcolors.foregroundColor);
+ mainPanel.add(label,BorderLayout.CENTER);
+ }
+
+ // Constructor
+ public GLPoptions(CupsPrinter cp)
+ {
+ printer = cp;
+ if (printer != null)
+ {
+ load(printer);
+ }
+ else
+ {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+ JLabel label = new JLabel("No printer selected");
+ label.setForeground(GLPcolors.foregroundColor);
+ mainPanel.add(label,BorderLayout.CENTER);
+ }
+ }
+
+
+ private void load( CupsPrinter cp )
+ {
+
+ fillOptionValues();
+
+ // Create the main panel to contain the two sub panels.
+ mainPanel = new JPanel();
+ mainLayout = new GridBagLayout();
+ mainConst = new GridBagConstraints();
+
+ mainPanel.setLayout(mainLayout);
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+
+ String tmp_s = "Printing to " + printer.getPrinterName() +
+ " on " + GLPvars.cupsServerName;
+ JLabel printerNameText = new JLabel(tmp_s);
+ printerNameText.setForeground(GLPcolors.foregroundColor);
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 0;
+ mainConst.fill = GridBagConstraints.NONE;
+ mainConst.weightx = 0.0;
+ mainConst.weighty = 0.0;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( printerNameText, mainConst );
+ mainPanel.add(printerNameText);
+
+ JPanel filePanel = buildFilePanel();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 1;
+ mainConst.fill = GridBagConstraints.HORIZONTAL;
+ mainConst.weightx = 1.0;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( filePanel, mainConst );
+ mainPanel.add(filePanel);
+
+ JPanel orientationPanel = buildOrientationComboBox();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 2;
+ mainConst.fill = GridBagConstraints.NONE;
+ mainConst.weightx = 0.8;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( orientationPanel, mainConst );
+ mainPanel.add(orientationPanel);
+
+ JPanel jobSheetsPanel = buildJobSheetsComboBox();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 3;
+ mainConst.fill = GridBagConstraints.NONE;
+ mainConst.weightx = 0.8;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( jobSheetsPanel, mainConst );
+ mainPanel.add(jobSheetsPanel);
+
+ JPanel numCopiesPanel = buildNumCopiesPanel();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 4;
+ mainConst.fill = GridBagConstraints.HORIZONTAL;
+ mainConst.weightx = 1.0;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( numCopiesPanel, mainConst );
+ mainPanel.add(numCopiesPanel);
+
+ JPanel pageRangePanel = buildPageRangePanel();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 5;
+ mainConst.fill = GridBagConstraints.HORIZONTAL;
+ mainConst.weightx = 1.0;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( pageRangePanel, mainConst );
+ mainPanel.add(pageRangePanel);
+
+ JPanel buttonPanel = buildButtonPanel();
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = 6;
+ mainConst.fill = GridBagConstraints.NONE;
+ mainConst.weightx = 1.0;
+ mainConst.weighty = 0.1;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( buttonPanel, mainConst );
+ mainPanel.add(buttonPanel);
+
+ }
+
+
+ // --------------------------------------------------------------
+ //
+ // Filename / Browse panel
+ //
+ public JPanel buildFilePanel()
+ {
+ JPanel localPanel = new JPanel();
+ final JFileChooser fc = new JFileChooser();
+
+ localPanel.setBackground(GLPcolors.backgroundColor);
+ localPanel.setLayout(new BorderLayout());
+
+ //Create a regular text field.
+ fileTextField = new JTextField(50);
+ fileTextField.addActionListener(this);
+
+ //Create some labels for the fields.
+ JLabel fileFieldLabel = new JLabel(" File to print: ");
+ fileFieldLabel.setForeground(GLPcolors.foregroundColor);
+ // fileFieldLabel.setLabelFor(fileTextField);
+
+ localPanel.add( fileFieldLabel, BorderLayout.WEST );
+ localPanel.add( fileTextField, BorderLayout.CENTER );
+
+ //Create the open button
+ JButton openButton = new JButton("Browse ..." );
+ openButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ int returnVal = fc.showOpenDialog(mainPanel);
+ if (returnVal == JFileChooser.APPROVE_OPTION)
+ {
+ File file = fc.getSelectedFile();
+ // fileTextField.setText(file.getPath() + file.getName());
+ fileTextField.setText(file.getPath());
+ fileName = file.getPath();
+ }
+ }
+ });
+ openButton.setBackground(GLPcolors.buttonBackgroundColor);
+ openButton.setForeground(GLPcolors.buttonForegroundColor);
+ localPanel.add(openButton, BorderLayout.EAST );
+ return(localPanel);
+ }
+
+
+
+ public JPanel buildOrientationComboBox()
+ {
+ JPanel localPanel = new JPanel();
+ localPanel.setLayout(new BorderLayout());
+ localPanel.setBackground(GLPcolors.backgroundColor);
+
+ JLabel localLabel = new JLabel("Page Orientation: ");
+ localLabel.setBackground(GLPcolors.backgroundColor);
+ localLabel.setForeground(GLPcolors.foregroundColor);
+
+ orientationBox = new JComboBox(orientationNames);
+ if (selectedOrientation > 0)
+ orientationBox.setSelectedIndex(selectedOrientation);
+ orientationBox.addActionListener(this);
+ orientationBox.setBackground(GLPcolors.backgroundColor);
+
+ localPanel.add(localLabel,BorderLayout.WEST);
+ localPanel.add(orientationBox,BorderLayout.CENTER);
+
+ return(localPanel);
+ }
+
+
+ public JPanel buildJobSheetsComboBox()
+ {
+ JPanel localPanel = new JPanel();
+ localPanel.setLayout(new BorderLayout());
+ localPanel.setBackground(GLPcolors.backgroundColor);
+
+ JLabel localLabel = new JLabel("Job Sheets: ");
+ localLabel.setBackground(GLPcolors.backgroundColor);
+ localLabel.setForeground(GLPcolors.foregroundColor);
+
+ jobSheetsBox = new JComboBox(jobSheetsNames);
+ if (selectedJobSheets > 0)
+ jobSheetsBox.setSelectedIndex(selectedJobSheets);
+ jobSheetsBox.addActionListener(this);
+ jobSheetsBox.setBackground(GLPcolors.backgroundColor);
+
+ localPanel.add(localLabel,BorderLayout.WEST);
+ localPanel.add(jobSheetsBox,BorderLayout.CENTER);
+
+ return(localPanel);
+ }
+
+ public JPanel buildNumCopiesPanel()
+ {
+ JPanel localPanel = new JPanel();
+ localPanel.setLayout(new FlowLayout());
+ localPanel.setBackground(GLPcolors.backgroundColor);
+
+ JLabel localLabel = new JLabel("Number of copies: ");
+ localLabel.setBackground(GLPcolors.backgroundColor);
+ localLabel.setForeground(GLPcolors.foregroundColor);
+
+ numCopiesField = new JTextField(3);
+ if (numCopiesOption > 0)
+ numCopiesField.setText(new Integer(numCopiesOption).toString());
+ numCopiesField.addActionListener(this);
+ numCopiesField.addFocusListener(textListener);
+ numCopiesField.setBackground(GLPcolors.backgroundColor);
+
+ localPanel.add(localLabel);
+ localPanel.add(numCopiesField);
+
+ return(localPanel);
+ }
+
+
+ public JPanel buildPageRangePanel()
+ {
+ JPanel localPanel = new JPanel();
+ localPanel.setLayout(new FlowLayout());
+ localPanel.setBackground(GLPcolors.backgroundColor);
+
+ printAllCheckBox = new JCheckBox("Print all", pagePrintAll );
+ printAllCheckBox.setBackground(GLPcolors.backgroundColor);
+ printAllCheckBox.setForeground(GLPcolors.foregroundColor);
+ printAllCheckBox.addActionListener(this);
+
+ JLabel localLabel = new JLabel("-or- pages: ");
+ localLabel.setBackground(GLPcolors.backgroundColor);
+ localLabel.setForeground(GLPcolors.foregroundColor);
+
+ JLabel localLabel2 = new JLabel(" to ");
+ localLabel2.setBackground(GLPcolors.backgroundColor);
+ localLabel2.setForeground(GLPcolors.foregroundColor);
+
+ pageLowerField = new JTextField(4);
+ pageUpperField = new JTextField(4);
+
+ pageLowerField.addActionListener(this);
+ pageUpperField.addActionListener(this);
+ pageLowerField.addFocusListener(textListener);
+ pageUpperField.addFocusListener(textListener);
+
+ pageLowerField.setBackground(GLPcolors.backgroundColor);
+ pageUpperField.setBackground(GLPcolors.backgroundColor);
+ pageLowerField.setEnabled(false);
+ pageUpperField.setEnabled(false);
+
+ localPanel.add(printAllCheckBox);
+ localPanel.add(localLabel);
+ localPanel.add(pageLowerField);
+ localPanel.add(localLabel2);
+ localPanel.add(pageUpperField);
+
+ return(localPanel);
+ }
+
+
+
+
+ public JPanel buildTextPanel()
+ {
+ JPanel localPanel = new JPanel();
+ return(localPanel);
+ }
+
+ public JPanel buildButtonPanel()
+ {
+ JPanel localPanel = new JPanel();
+ localPanel.setLayout(new BorderLayout());
+ printButton = new JButton(" Print ");
+ printButton.setBackground(GLPcolors.buttonBackgroundColor);
+ printButton.setForeground(GLPcolors.buttonForegroundColor);
+ printButton.addActionListener( this );
+ localPanel.add(printButton, BorderLayout.WEST );
+ return(localPanel);
+ }
+
+
+
+ public void updateOptions(CupsPrinter cp)
+ {
+ printer = cp;
+ if (printer != null)
+ {
+ load(printer);
+ }
+ else
+ {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+ JLabel label = new JLabel("No printer selected");
+ label.setForeground(GLPcolors.foregroundColor);
+ mainPanel.add(label,BorderLayout.CENTER);
+ }
+ }
+
+ public JPanel getPanel()
+ {
+ return(mainPanel);
+ }
+
+
+
+
+ public CupsJob printFile( String filename )
+ {
+ Cups cups;
+ CupsJob job;
+ URL u;
+ IPPAttribute attrs[];
+
+ attrs = buildPrintAttributes();
+
+ // for (int i=0; i < attrs.length; i++)
+ // attrs[i].dump_values();
+
+ try
+ {
+ u = new URL("http://" + GLPvars.getServerName() +
+ ":631/printers/" + printer.getPrinterName() );
+ cups = new Cups(u);
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+
+ job = cups.cupsPrintFile(filename,attrs);
+ return(job);
+ }
+ catch (IOException e)
+ {
+ return(null);
+ }
+ }
+
+
+
+
+ private void fillOptionValues()
+ {
+ IPPAttribute a;
+ int i, n;
+
+ //
+ // Job sheets ....
+ //
+ jobSheetsNames = printer.getJobSheetsSupported();
+ if (printer.getJobSheetsDefault() != "none")
+ {
+ for (i=0; i < jobSheetsNames.length; i++)
+ if (jobSheetsNames[i] == printer.getJobSheetsDefault())
+ selectedJobSheets = i;
+ }
+
+ //
+ // Orientation ....
+ //
+ orientationNames = new String[printer.getOrientationSupported().length];
+ orientationValues = printer.getOrientationSupported();
+ for (i=0; i < printer.getOrientationSupported().length; i++)
+ {
+ if (orientationValues[i] == printer.getOrientationDefault())
+ selectedOrientation = i;
+ switch( orientationValues[i] )
+ {
+ case IPPDefs.PORTRAIT:
+ orientationNames[i] = "Portrait";
+ break;
+ case IPPDefs.LANDSCAPE:
+ orientationNames[i] = "Landscape";
+ break;
+ case IPPDefs.REVERSE_LANDSCAPE:
+ orientationNames[i] = "Reverse Landscape";
+ break;
+ case IPPDefs.REVERSE_PORTRAIT:
+ orientationNames[i] = "Reverse Portrait";
+ break;
+ }
+ }
+
+ if (printer.getLowerCopiesSupported() ==
+ printer.getUpperCopiesSupported())
+ {
+ numCopiesOption = printer.getCopiesDefault();
+ }
+ else
+ {
+ numCopiesOption = printer.getLowerCopiesSupported();
+ numLowerCopiesOption = printer.getLowerCopiesSupported();
+ numUpperCopiesOption = printer.getUpperCopiesSupported();
+ }
+ }
+
+
+ private IPPAttribute[] buildPrintAttributes()
+ {
+ IPPAttribute a;
+ IPPAttribute[] attrs;
+ int num_attrs = 0;
+
+ if (orientationOption >= 0)
+ num_attrs++;
+ if (jobSheetsOption.length() > 0)
+ num_attrs++;
+ if (numCopiesOption > 1)
+ num_attrs++;
+ if ((pageLowerOption > 0) && (pageUpperOption > 0) && (!pagePrintAll))
+ num_attrs++;
+
+ if (num_attrs > 0)
+ attrs = new IPPAttribute[num_attrs];
+ else
+ return(null);
+
+ int i = 0;
+ if (jobSheetsOption.length() > 0)
+ {
+ attrs[i] = new IPPAttribute( IPPDefs.TAG_JOB,
+ IPPDefs.TAG_NAME,
+ "job-sheets" );
+ attrs[i].addString( "", jobSheetsOption );
+ i++;
+ }
+ if (orientationOption >= IPPDefs.PORTRAIT)
+ {
+ attrs[i] = new IPPAttribute( IPPDefs.TAG_JOB,
+ IPPDefs.TAG_ENUM,
+ "orientation-requested" );
+ attrs[i].addEnum( orientationOption );
+ i++;
+ }
+ if (numCopiesOption > 1)
+ {
+ attrs[i] = new IPPAttribute( IPPDefs.TAG_JOB,
+ IPPDefs.TAG_INTEGER,
+ "copies" );
+ attrs[i].addInteger( numCopiesOption );
+ i++;
+ }
+ if ((pageLowerOption > 0) && (pageUpperOption > 0) && (!pagePrintAll))
+ {
+ attrs[i] = new IPPAttribute( IPPDefs.TAG_JOB,
+ IPPDefs.TAG_RANGE,
+ "page-ranges" );
+ attrs[i].addRange( pageLowerOption, pageUpperOption );
+ i++;
+ }
+ return(attrs);
+ }
+
+
+
+ // Implementation of ActionListener interface.
+ public void actionPerformed(ActionEvent e)
+ {
+ Object source = e.getSource();
+
+ //
+ // Name typed in
+ //
+ if (source == printAllCheckBox)
+ {
+ JCheckBox cb = (JCheckBox)source;
+ pagePrintAll = cb.isSelected();
+ pageLowerField.setEnabled(!pagePrintAll);
+ pageUpperField.setEnabled(!pagePrintAll);
+ }
+ else if (source == pageLowerField)
+ {
+ String s = pageLowerField.getText();
+ if (s.length() > 1)
+ {
+ pageLowerOption = new Integer(s).intValue();
+ // if (pageLowerOption > 0)
+ // printAllCheckBox.setChecked(false);
+ }
+ }
+ else if (source == pageUpperField)
+ {
+ String s = pageUpperField.getText();
+ if (s.length() > 1)
+ {
+ pageUpperOption = new Integer(s).intValue();
+ // if (pageUpperOption > 0)
+ // printAllCheckBox.setChecked(false);
+ }
+ }
+ else if (source == orientationBox)
+ {
+ JComboBox cb = (JComboBox)source;
+ selectedOrientation = cb.getSelectedIndex();
+ orientationOption = orientationValues[selectedOrientation];
+ }
+ else if (source == jobSheetsBox)
+ {
+ JComboBox cb = (JComboBox)source;
+ selectedJobSheets = cb.getSelectedIndex();
+ jobSheetsOption = jobSheetsNames[selectedJobSheets];
+ }
+ else if (source == numCopiesField)
+ {
+ String s = numCopiesField.getText();
+ if (s.length() >= 1)
+ {
+ numCopiesOption = new Integer(s).intValue();
+ }
+ }
+ else if (source == fileTextField)
+ {
+ String s = fileTextField.getText();
+ if (s.length() > 1)
+ {
+ fileName = s;
+ }
+ }
+ else if (source == printButton)
+ {
+ if (fileName.length() > 1)
+ {
+ job = printFile( fileName );
+ if (job != null)
+ {
+ fileName = "";
+ fileTextField.setText("");
+ JOptionPane.showMessageDialog(mainPanel,
+ "Job " + printer.getPrinterName() + "-" +
+ new Integer(job.job_id).toString() +
+ " queued.");
+ }
+ }
+ }
+ }
+
+
+
+
+
+ public class MyTextListener implements FocusListener
+ {
+
+ public void focusGained(FocusEvent e)
+ {
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ JTextField txtField = (JTextField)e.getSource();
+ if (txtField == numCopiesField)
+ {
+ String s = numCopiesField.getText();
+ if (s.length() >= 1)
+ {
+ numCopiesOption = new Integer(s).intValue();
+ }
+ }
+ else if (txtField == pageLowerField)
+ {
+ String s = pageLowerField.getText();
+ if (s.length() >= 1)
+ {
+ pageLowerOption = new Integer(s).intValue();
+ }
+ }
+ else if (txtField == pageUpperField)
+ {
+ String s = pageUpperField.getText();
+ if (s.length() >= 1)
+ {
+ pageUpperOption = new Integer(s).intValue();
+ }
+ }
+ }
+ }
+
+}
diff --git a/scripting/java/example/GLPprinterDetail.java b/scripting/java/example/GLPprinterDetail.java
new file mode 100644
index 000000000..3ffc1571d
--- /dev/null
+++ b/scripting/java/example/GLPprinterDetail.java
@@ -0,0 +1,244 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPprinterDetail
+{
+
+ private CupsPrinter printer = null;
+ private JScrollPane scrollPane = null;
+ private JPanel mainPanel = null;
+
+
+ // Constructor
+ public GLPprinterDetail( CupsPrinter cp )
+ {
+ printer = cp;
+ load();
+ }
+
+ public void load()
+ {
+ mainPanel = new JPanel();
+ mainPanel = printerInfoPanel( printer );
+ }
+
+
+
+ // -----------------------------------------------------------
+ //
+ // Build an info panel for an individual printer.
+ //
+ private JPanel printerInfoPanel( CupsPrinter cp )
+ {
+ JPanel printerPanel = new JPanel();
+ BoxLayout printerBox;
+
+ JPanel leftHeader = new JPanel();
+ JPanel rightHeader = new JPanel();
+
+ JPanel leftPane = new JPanel();
+ JPanel rightPane = new JPanel();
+
+ GridBagLayout leftLayout = new GridBagLayout();
+ GridBagLayout rightLayout = new GridBagLayout();
+
+ GridBagConstraints leftConst = new GridBagConstraints();
+ GridBagConstraints rightConst = new GridBagConstraints();
+
+
+ JLabel printerIconLabel = null;
+ JLabel printerInfoLabel = null;
+ JLabel printerNameLabel = null;
+ JLabel printerMakeLabel = null;
+
+ JTable printerStatusTable = null;
+
+ printerBox = new BoxLayout(printerPanel, BoxLayout.X_AXIS);
+ printerPanel.setLayout(printerBox);
+ printerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ printerPanel.setBackground(GLPcolors.backgroundColor);
+
+ // Add border around the panel.
+
+
+ // ------------------------------------------------------------
+ // Left pane
+ // ------------------------------------------------------------
+ leftPane.setLayout(leftLayout);
+ leftPane.setBackground(GLPcolors.backgroundColor);
+
+ leftHeader.setLayout(new BorderLayout());
+ leftHeader.setBackground(GLPcolors.highlightColor);
+ leftHeader.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+
+ printerNameLabel = new JLabel(cp.getPrinterName());
+ printerNameLabel.setForeground(Color.black);
+ leftHeader.add( printerNameLabel, BorderLayout.WEST);
+ leftConst.gridwidth = GridBagConstraints.RELATIVE;
+ leftConst.gridx = 0;
+ leftConst.gridy = 0;
+ leftConst.fill = GridBagConstraints.HORIZONTAL;
+ leftConst.weightx = 0.0;
+ leftConst.weighty = 0.0;
+ leftConst.ipady = 4;
+ leftLayout.setConstraints( leftHeader, leftConst );
+ leftPane.add(leftHeader);
+
+ String imageName = "./images/printer-" +
+ cp.getStateText() + ".gif";
+ JButton printerButton;
+ try
+ {
+ URL iconURL = ClassLoader.getSystemResource(imageName);
+ ImageIcon icon = new ImageIcon(iconURL);
+ printerButton = new JButton( "<html><center><b>" +
+ cp.getPrinterName() +
+ "</b></center></html>",
+ icon );
+ }
+ catch (NullPointerException e)
+ {
+ printerButton = new JButton( "<html><center><b>" +
+ cp.getPrinterName() +
+ "</b></center></html>");
+ }
+ printerButton.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+ printerButton.setBackground(GLPcolors.backgroundColor);
+ printerButton.setActionCommand( cp.getPrinterName() );
+ // printerButton.addActionListener(this);
+ printerButton.setToolTipText("Click to go to " + cp.getPrinterName() +
+ "'s extended informtion page.");
+
+ leftConst.gridwidth = GridBagConstraints.REMAINDER;
+ leftConst.gridx = 0;
+ leftConst.gridy = 1;
+ leftConst.fill = GridBagConstraints.BOTH;
+ leftConst.weightx = 1.0;
+ leftConst.weighty = 1.0;
+ leftConst.ipady = 4;
+ leftLayout.setConstraints( printerButton, leftConst );
+ leftPane.add(printerButton);
+
+
+ // ------------------------------------------------------------
+ // Right pane
+ // ------------------------------------------------------------
+ rightPane.setLayout(rightLayout);
+ rightPane.setBackground(GLPcolors.backgroundColor);
+
+ rightHeader.setLayout(new BorderLayout());
+ rightHeader.setBackground(GLPcolors.highlightColor);
+ rightHeader.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+
+ printerMakeLabel = new JLabel(cp.getMakeAndModel());
+ printerMakeLabel.setForeground(Color.black);
+ rightHeader.add( printerMakeLabel, BorderLayout.WEST);
+
+ rightConst.gridwidth = GridBagConstraints.RELATIVE;
+ rightConst.gridx = 0;
+ rightConst.gridy = 0;
+ rightConst.fill = GridBagConstraints.HORIZONTAL;
+ rightConst.weightx = 0.0;
+ rightConst.weighty = 0.0;
+ rightConst.ipady = 4;
+ rightLayout.setConstraints( rightHeader, rightConst );
+ rightPane.add(rightHeader);
+
+
+ Font labelFont = new Font("Serif",Font.BOLD, 12 );
+ // Font textFont = new Font("Serif", Font.NORMAL, 12 );
+ Font messageFont = new Font("Serif", Font.ITALIC, 12 );
+
+ JLabel pdServerLabel = new JLabel("Server");
+ JLabel pdNameLabel = new JLabel("Name");
+ JLabel pdLocationLabel = new JLabel("Location");
+ JLabel pdStatusLabel = new JLabel("Status");
+ JLabel pdMessageLabel = new JLabel("Message");
+
+ JLabel pdServerText = new JLabel(GLPvars.cupsServerName);
+ JLabel pdNameText = new JLabel(cp.getPrinterName());
+ JLabel pdLocationText = new JLabel(cp.getLocation());
+ JLabel pdStatusText = new JLabel(cp.getStateText());
+ JLabel pdMessageText = new JLabel(cp.getStateReasons());
+
+ pdServerLabel.setFont(labelFont);
+ pdNameLabel.setFont(labelFont);
+ pdLocationLabel.setFont(labelFont);
+ pdStatusLabel.setFont(labelFont);
+ pdMessageLabel.setFont(labelFont);
+ pdMessageText.setFont(messageFont);
+
+ pdServerLabel.setForeground(Color.black);
+ pdNameLabel.setForeground(Color.black);
+ pdLocationLabel.setForeground(Color.black);
+ pdStatusLabel.setForeground(Color.black);
+ pdMessageLabel.setForeground(Color.black);
+
+
+ JPanel tablePane;
+ if ((cp.getStateReasons().length() > 0) &&
+ (!cp.getStateReasons().equals("none")))
+ {
+ tablePane = new JPanel(new GridLayout(5,2,2,2));
+ tablePane.add(pdServerLabel);
+ tablePane.add(pdServerText);
+
+ tablePane.add(pdNameLabel);
+ tablePane.add(pdNameText);
+
+ tablePane.add(pdLocationLabel);
+ tablePane.add(pdLocationText);
+
+ tablePane.add(pdStatusLabel);
+ tablePane.add(pdStatusText);
+
+ tablePane.add(pdMessageLabel);
+ tablePane.add(pdMessageText);
+ }
+ else
+ {
+ tablePane = new JPanel(new GridLayout(4,2,2,2));
+ tablePane.add(pdServerLabel);
+ tablePane.add(pdServerText);
+
+ tablePane.add(pdNameLabel);
+ tablePane.add(pdNameText);
+
+ tablePane.add(pdLocationLabel);
+ tablePane.add(pdLocationText);
+
+ tablePane.add(pdStatusLabel);
+ tablePane.add(pdStatusText);
+
+ }
+ tablePane.setBackground(GLPcolors.backgroundColor);
+
+ // printerStatusTable.setShowGrid(false);
+ rightConst.gridwidth = GridBagConstraints.REMAINDER;
+ rightConst.gridx = 0;
+ rightConst.gridy = 1;
+ rightConst.fill = GridBagConstraints.BOTH;
+ rightConst.weightx = 1.0;
+ rightConst.weighty = 1.0;
+ rightConst.ipady = 4;
+ rightLayout.setConstraints( tablePane, rightConst );
+ rightPane.add(tablePane);
+
+ printerPanel.add(leftPane);
+ printerPanel.add(rightPane);
+
+ return(printerPanel);
+ }
+
+
+ public JPanel getPanel()
+ {
+ return(mainPanel);
+ }
+}
diff --git a/scripting/java/example/GLPprinters.java b/scripting/java/example/GLPprinters.java
new file mode 100644
index 000000000..56dc8c110
--- /dev/null
+++ b/scripting/java/example/GLPprinters.java
@@ -0,0 +1,509 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPprinters implements ActionListener
+{
+
+ private Cups cups = null;
+ public String cupsServerName = "";
+
+ private JScrollPane scrollPane = null;
+ private JPanel mainPanel = null;
+ private JPanel serverPanel = null;
+ private JPanel maskPanel = null;
+
+ private GridBagLayout mainLayout = null;
+ private GridBagConstraints mainConst = null;
+ private GridBagLayout maskLayout = null;
+ private GridBagConstraints maskConst = null;
+
+ private JLabel serverLabel = null;
+
+ JTextField nameTextField = null;
+ protected static final String maskFieldString = "Printer Name:";
+ protected static final String maskButtonString = "Apply";
+
+ private String currentMask = "";
+
+
+ // Constructor
+ public GLPprinters()
+ {
+ cupsServerName = GLPvars.getServerName();
+ load();
+ }
+
+ public void load()
+ {
+ String[] printer_names;
+ String default_printer;
+ int num_printers = 0;
+ int y = 0, i = 0;
+ URL u;
+ CupsPrinter cp;
+
+
+ // -----------------------------------------------------------
+ //
+ // First get a list of printer names.
+ //
+ try
+ {
+ u = new URL("http://" + GLPvars.getServerName() + ":631/");
+ cups = new Cups(u);
+
+ // If authorization is required ....
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+
+ printer_names = cups.cupsGetPrinters();
+ if (printer_names != null)
+ num_printers = printer_names.length;
+ else
+ num_printers = 0;
+ }
+ catch (IOException e)
+ {
+ mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+ JLabel errorLabel = new JLabel("Error loading printers from " +
+ GLPvars.getServerName());
+ errorLabel.setForeground(Color.red);
+ mainPanel.add( errorLabel, BorderLayout.CENTER );
+ scrollPane = new JScrollPane(mainPanel);
+ return;
+ }
+
+ // -----------------------------------------------------------
+ //
+ // Now get the printer objects
+ //
+ CupsPrinter[] printers = new CupsPrinter[num_printers];
+ for (i=0; i < num_printers; i++)
+ {
+ try
+ {
+ u = new URL("http://" + GLPvars.getServerName() +
+ ":631/printers/" + printer_names[i] );
+ cups = new Cups(u);
+
+ // If authorization is required ....
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+
+ printers[i] = new CupsPrinter( cups, printer_names[i] );
+ }
+ catch (IOException e)
+ {
+ // System.out.println("GLPprinters: IOException");
+ // return(null);
+ }
+ }
+
+
+ //
+ // Keep track in case it changes.
+ //
+ cupsServerName = GLPvars.getServerName();
+
+ if (printer_names != null)
+ num_printers = printer_names.length;
+ else
+ num_printers = 0;
+
+ // default_printer = c.cupsGetDefault();
+
+ // Create the main panel to contain the two sub panels.
+ mainPanel = new JPanel();
+ mainLayout = new GridBagLayout();
+ mainConst = new GridBagConstraints();
+
+ mainPanel.setLayout(mainLayout);
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ mainPanel.setBackground(GLPcolors.backgroundColor);
+
+ // --------------------------------------------------------------
+ //
+ // Add the server name label
+ //
+ serverPanel = new JPanel();
+ serverPanel.setLayout( new BorderLayout());
+ serverPanel.setBackground(GLPcolors.backgroundColor);
+ serverLabel = new JLabel("Printers on " + GLPvars.getServerName());
+ serverLabel.setForeground(GLPcolors.foregroundColor);
+ serverPanel.add(serverLabel, BorderLayout.NORTH );
+
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = y++;
+ mainConst.fill = GridBagConstraints.BOTH;
+ mainConst.weightx = 0.0;
+ mainConst.weighty = 0.0;
+ mainConst.ipadx = 4;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( serverPanel, mainConst );
+ mainPanel.add(serverPanel);
+
+ // --------------------------------------------------------------
+ //
+ // Add the printer masking panel
+ //
+ maskPanel = new JPanel();
+ maskLayout = new GridBagLayout();
+ maskConst = new GridBagConstraints();
+
+ maskPanel.setLayout(maskLayout);
+ maskPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ maskPanel.setBackground(GLPcolors.backgroundColor);
+
+ JPanel localMaskPanel = buildMaskPanel();
+ maskConst.gridwidth = GridBagConstraints.RELATIVE;
+ maskConst.gridx = 0;
+ maskConst.gridy = 0;
+ maskConst.fill = GridBagConstraints.NONE;
+ maskConst.weightx = 0.0;
+ maskConst.weighty = 0.0;
+ maskConst.ipadx = 4;
+ maskConst.ipady = 4;
+ maskLayout.setConstraints( localMaskPanel, maskConst );
+ maskPanel.add(localMaskPanel);
+
+ //
+ // Add the masking panel to the main panel.
+ //
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = y++;
+ mainConst.fill = GridBagConstraints.BOTH;
+ mainConst.weightx = 0.0;
+ mainConst.weighty = 0.0;
+ mainConst.ipadx = 4;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( maskPanel, mainConst );
+ mainPanel.add(maskPanel);
+
+
+
+ // --------------------------------------------------------------
+ //
+ // Add the printers
+ //
+ double weight = 1.0 / (double)printers.length;
+ for (i=0; i < printers.length; i++)
+ {
+ JPanel subPanel = printerInfoPanel( printers[i] );
+ mainConst.gridwidth = GridBagConstraints.RELATIVE;
+ mainConst.gridx = 0;
+ mainConst.gridy = y++;
+ mainConst.fill = GridBagConstraints.BOTH;
+ mainConst.weightx = 1.0;
+ mainConst.weighty = weight;
+ mainConst.ipady = 4;
+ mainLayout.setConstraints( subPanel, mainConst );
+ mainPanel.add(subPanel);
+ }
+
+ // ------------------------------------------------
+ //
+ // Put the whole thing into a scroll pane.
+ //
+ scrollPane = new JScrollPane(mainPanel);
+ }
+
+
+
+ // -----------------------------------------------------------
+ //
+ // Build an info panel for an individual printer.
+ //
+ private JPanel printerInfoPanel( CupsPrinter cp )
+ {
+ JPanel printerPanel = new JPanel();
+ BoxLayout printerBox;
+
+ JPanel leftHeader = new JPanel();
+ JPanel rightHeader = new JPanel();
+
+ JPanel leftPane = new JPanel();
+ JPanel rightPane = new JPanel();
+
+ GridBagLayout leftLayout = new GridBagLayout();
+ GridBagLayout rightLayout = new GridBagLayout();
+
+ GridBagConstraints leftConst = new GridBagConstraints();
+ GridBagConstraints rightConst = new GridBagConstraints();
+
+
+ JLabel printerIconLabel = null;
+ JLabel printerInfoLabel = null;
+ JLabel printerNameLabel = null;
+ JLabel printerMakeLabel = null;
+
+ JTable printerStatusTable = null;
+
+ printerBox = new BoxLayout(printerPanel, BoxLayout.X_AXIS);
+ printerPanel.setLayout(printerBox);
+ printerPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ printerPanel.setBackground(GLPcolors.backgroundColor);
+
+ // Add border around the panel.
+
+
+ // ------------------------------------------------------------
+ // Left pane
+ // ------------------------------------------------------------
+ leftPane.setLayout(leftLayout);
+ leftPane.setBackground(GLPcolors.backgroundColor);
+
+ leftHeader.setLayout(new BorderLayout());
+ leftHeader.setBackground(GLPcolors.highlightColor);
+ leftHeader.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+
+ printerNameLabel = new JLabel(cp.getPrinterName());
+ printerNameLabel.setForeground(Color.black);
+ leftHeader.add( printerNameLabel, BorderLayout.WEST);
+ leftConst.gridwidth = GridBagConstraints.RELATIVE;
+ leftConst.gridx = 0;
+ leftConst.gridy = 0;
+ leftConst.fill = GridBagConstraints.HORIZONTAL;
+ leftConst.weightx = 0.0;
+ leftConst.weighty = 0.0;
+ leftConst.ipady = 4;
+ leftLayout.setConstraints( leftHeader, leftConst );
+ leftPane.add(leftHeader);
+
+ String imageName = "./images/printer-" + cp.getStateText() + ".gif";
+ URL iconURL = ClassLoader.getSystemResource(imageName);
+ ImageIcon icon = new ImageIcon(iconURL);
+ JButton printerButton = new JButton( "<html><center><b>" +
+ cp.getPrinterName() +
+ "</b></center></html>",
+ icon );
+ printerButton.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+ printerButton.setBackground(GLPcolors.backgroundColor);
+ printerButton.setActionCommand( cp.getPrinterName() );
+ printerButton.addActionListener(this);
+ printerButton.setToolTipText("Click to go to " + cp.getPrinterName() +
+ "'s extended informtion page.");
+
+ leftConst.gridwidth = GridBagConstraints.REMAINDER;
+ leftConst.gridx = 0;
+ leftConst.gridy = 1;
+ leftConst.fill = GridBagConstraints.BOTH;
+ leftConst.weightx = 1.0;
+ leftConst.weighty = 1.0;
+ leftConst.ipady = 4;
+ leftLayout.setConstraints( printerButton, leftConst );
+ leftPane.add(printerButton);
+
+
+ // ------------------------------------------------------------
+ // Right pane
+ // ------------------------------------------------------------
+ rightPane.setLayout(rightLayout);
+ rightPane.setBackground(GLPcolors.backgroundColor);
+
+ rightHeader.setLayout(new BorderLayout());
+ rightHeader.setBackground(GLPcolors.highlightColor);
+ rightHeader.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+
+ printerMakeLabel = new JLabel(cp.getMakeAndModel());
+ printerMakeLabel.setForeground(Color.black);
+ rightHeader.add( printerMakeLabel, BorderLayout.WEST);
+
+ rightConst.gridwidth = GridBagConstraints.RELATIVE;
+ rightConst.gridx = 0;
+ rightConst.gridy = 0;
+ rightConst.fill = GridBagConstraints.HORIZONTAL;
+ rightConst.weightx = 0.0;
+ rightConst.weighty = 0.0;
+ rightConst.ipady = 4;
+ rightLayout.setConstraints( rightHeader, rightConst );
+ rightPane.add(rightHeader);
+
+
+ Font labelFont = new Font("Serif",Font.BOLD, 12 );
+ // Font textFont = new Font("Serif", Font.NORMAL, 12 );
+ Font messageFont = new Font("Serif", Font.ITALIC, 12 );
+
+ JLabel pdNameLabel = new JLabel("Name");
+ JLabel pdLocationLabel = new JLabel("Location");
+ JLabel pdStatusLabel = new JLabel("Status");
+ JLabel pdMessageLabel = new JLabel("Message");
+
+ JLabel pdNameText = new JLabel(cp.getPrinterName());
+ JLabel pdLocationText = new JLabel(cp.getLocation());
+ JLabel pdStatusText = new JLabel(cp.getStateText());
+ JLabel pdMessageText = new JLabel(cp.getStateReasons());
+
+ pdNameLabel.setFont(labelFont);
+ pdLocationLabel.setFont(labelFont);
+ pdStatusLabel.setFont(labelFont);
+ pdMessageLabel.setFont(labelFont);
+ pdMessageText.setFont(messageFont);
+
+ pdNameLabel.setForeground(Color.black);
+ pdLocationLabel.setForeground(Color.black);
+ pdStatusLabel.setForeground(Color.black);
+ pdMessageLabel.setForeground(Color.black);
+
+ JPanel tablePane;
+ if ((cp.getStateReasons().length() > 0) &&
+ (!cp.getStateReasons().equals("none")))
+ {
+ tablePane = new JPanel(new GridLayout(4,2,2,2));
+ tablePane.add(pdNameLabel);
+ tablePane.add(pdNameText);
+
+ tablePane.add(pdLocationLabel);
+ tablePane.add(pdLocationText);
+
+ tablePane.add(pdStatusLabel);
+ tablePane.add(pdStatusText);
+
+ tablePane.add(pdMessageLabel);
+ tablePane.add(pdMessageText);
+ }
+ else
+ {
+ tablePane = new JPanel(new GridLayout(3,2,2,2));
+ tablePane.add(pdNameLabel);
+ tablePane.add(pdNameText);
+
+ tablePane.add(pdLocationLabel);
+ tablePane.add(pdLocationText);
+
+ tablePane.add(pdStatusLabel);
+ tablePane.add(pdStatusText);
+
+ }
+ tablePane.setBackground(GLPcolors.backgroundColor);
+
+ // printerStatusTable.setShowGrid(false);
+ rightConst.gridwidth = GridBagConstraints.REMAINDER;
+ rightConst.gridx = 0;
+ rightConst.gridy = 1;
+ rightConst.fill = GridBagConstraints.BOTH;
+ rightConst.weightx = 1.0;
+ rightConst.weighty = 1.0;
+ rightConst.ipady = 4;
+ rightLayout.setConstraints( tablePane, rightConst );
+ rightPane.add(tablePane);
+
+ printerPanel.add(leftPane);
+ printerPanel.add(rightPane);
+
+ return(printerPanel);
+ }
+
+
+
+
+
+ public JPanel buildMaskPanel()
+ {
+
+ // Create the main panel to contain the two sub panels.
+ JPanel namePanel = new JPanel();
+ GridBagLayout nameLayout = new GridBagLayout();
+ GridBagConstraints nameConst = new GridBagConstraints();
+
+ namePanel.setLayout(nameLayout);
+ namePanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ namePanel.setBackground(GLPcolors.backgroundColor);
+
+
+ //Create a regular text field.
+ nameTextField = new JTextField(16);
+ nameTextField.setActionCommand(maskFieldString);
+ nameTextField.addActionListener(this);
+ nameTextField.setText("");
+
+ //Create some labels for the fields.
+ JLabel nameFieldLabel = new JLabel(maskFieldString);
+ nameFieldLabel.setForeground(GLPcolors.foregroundColor);
+ nameFieldLabel.setLabelFor(nameTextField);
+
+ // Text
+ nameConst.gridwidth = GridBagConstraints.RELATIVE;
+ nameConst.gridx = 0;
+ nameConst.gridy = 0;
+ nameConst.fill = GridBagConstraints.HORIZONTAL;
+ nameConst.weightx = 0.0;
+ nameConst.weighty = 0.0;
+ nameConst.ipadx = 4;
+ nameConst.ipady = 4;
+ nameLayout.setConstraints( nameFieldLabel, nameConst );
+ namePanel.add(nameFieldLabel);
+
+ nameConst.gridwidth = GridBagConstraints.RELATIVE;
+ nameConst.gridx = 1;
+ nameConst.gridy = 0;
+ nameConst.fill = GridBagConstraints.HORIZONTAL;
+ nameConst.weightx = 0.0;
+ nameConst.weighty = 0.0;
+ nameConst.ipadx = 4;
+ nameConst.ipady = 4;
+ nameLayout.setConstraints( nameTextField, nameConst );
+ namePanel.add(nameTextField);
+
+ JButton applyButton = new JButton(maskButtonString);
+ applyButton.setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createRaisedBevelBorder(),
+ BorderFactory.createEmptyBorder(2,2,2,2)));
+ applyButton.setActionCommand(maskButtonString);
+ applyButton.addActionListener(this);
+ nameConst.gridx = 2;
+ nameConst.gridy = 0;
+ nameConst.fill = GridBagConstraints.NONE;
+ nameLayout.setConstraints( applyButton, nameConst );
+ nameConst.weightx = 0.0;
+ nameConst.weighty = 0.0;
+ nameConst.ipadx = 4;
+ nameConst.ipady = 4;
+ namePanel.add(applyButton);
+
+ return(namePanel);
+ }
+
+
+ public void actionPerformed(ActionEvent e)
+ {
+ if (e.getActionCommand().equals(maskFieldString))
+ {
+ String s = nameTextField.getText();
+ if (s.length() > 1)
+ {
+ currentMask = s;
+ }
+ }
+ else if (e.getActionCommand().equals(maskButtonString))
+ {
+ String s = nameTextField.getText();
+ if (s.length() > 1)
+ {
+ currentMask = s;
+ }
+ }
+ else
+ {
+ GLPvars.selectedPrinterName = e.getActionCommand();
+ GLPvars.tabs.updateDetailPanel();
+ GLPvars.tabs.tabPanel.setSelectedIndex(2);
+ }
+ }
+
+
+ public JScrollPane getPanel()
+ {
+ return(scrollPane);
+ }
+}
diff --git a/scripting/java/example/GLPsearch.java b/scripting/java/example/GLPsearch.java
new file mode 100644
index 000000000..7c8845dd6
--- /dev/null
+++ b/scripting/java/example/GLPsearch.java
@@ -0,0 +1,121 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPsearch extends Thread
+{
+ String localHostName = null;
+ String localHostIP = null;
+ String localSubNet = null;
+ InetAddress localHostAddress = null;
+
+ private int current_octet = 1;
+ private int count = 0;
+ private int thread_num = 0;
+ private boolean is_done = false;
+ private boolean is_completed = false;
+
+
+ // Constructor
+ public GLPsearch( int t_num )
+ {
+ thread_num = t_num;
+ try
+ {
+ localHostAddress = InetAddress.getLocalHost();
+ }
+ catch (UnknownHostException e)
+ {
+ }
+ localHostName = localHostAddress.getHostName();
+ // localHostIP = localHostAddress.getHostAddress();
+ localHostIP = "192.168.1.100";
+ int i = localHostIP.lastIndexOf(".");
+ localSubNet = localHostIP.substring(0,i);
+ }
+
+
+
+ // Constructor
+ public GLPsearch(int t_num, String subnet)
+ {
+ thread_num = t_num;
+ try
+ {
+ localHostAddress = InetAddress.getLocalHost();
+ }
+ catch (UnknownHostException e)
+ {
+ }
+ localHostName = localHostAddress.getHostName();
+ localHostIP = localHostAddress.getHostAddress();
+ localSubNet = subnet;
+ }
+
+
+ public void run()
+ {
+ Cups cups = null;
+ String host = "";
+ String test = "";
+ InetAddress lookupAddress;
+ URL u = null;
+
+ is_done = false;
+ for (int x = thread_num+1; x < 255 && !is_done; x += 8 )
+ {
+ count++;
+ current_octet = x;
+ host = localSubNet + "." + x;
+ try
+ {
+ u = new URL("http://" + host + ":631/printers");
+ cups = new Cups(u);
+ cups.setUser(GLPvars.cupsUser);
+ cups.setPasswd(GLPvars.cupsPasswd);
+
+ test = cups.cupsGetDefault();
+ if ((test != null) && (test.length() > 0))
+ {
+ lookupAddress = InetAddress.getByName(host);
+ GLPvars.addToServerList(lookupAddress.getHostName());
+ }
+ else
+ {
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ if (!is_done)
+ is_completed = true;
+ is_done = true;
+ }
+
+ public void interrupt()
+ {
+ is_done = true;
+ }
+
+ public boolean completed()
+ {
+ return(is_completed);
+ }
+
+ public boolean done()
+ {
+ return(is_done);
+ }
+
+ public int getValue()
+ {
+ return(count);
+ }
+
+}
diff --git a/scripting/java/example/GLPsearchProgressPanel.java b/scripting/java/example/GLPsearchProgressPanel.java
new file mode 100644
index 000000000..898942d5e
--- /dev/null
+++ b/scripting/java/example/GLPsearchProgressPanel.java
@@ -0,0 +1,195 @@
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.JScrollPane;
+import javax.swing.JPanel;
+import javax.swing.JFrame;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import org.cups.*;
+
+public class GLPsearchProgressPanel
+{
+ private JProgressBar progressBar;
+ private Timer timer;
+ private JButton searchButton;
+ private JLabel progressLabel;
+ private GLPsearch tasks[];
+ private JPanel panel = null;
+
+ public GLPsearchProgressPanel()
+ {
+ //Create the demo's UI.
+ searchButton = new JButton("Search");
+ searchButton.setActionCommand("Search");
+ searchButton.addActionListener(new ButtonListener());
+
+ progressLabel = new JLabel("Search your local subnet for CUPS servers");
+ progressLabel.setBackground(GLPcolors.backgroundColor);
+ progressLabel.setForeground(GLPcolors.foregroundColor);
+
+ progressBar = new JProgressBar(0, 254);
+ progressBar.setValue(0);
+ progressBar.setBorderPainted(true);
+ progressBar.setOrientation(JProgressBar.HORIZONTAL);
+ progressBar.setBackground(GLPcolors.backgroundColor);
+ progressBar.setForeground( Color.blue );
+ progressBar.setStringPainted(true);
+
+ panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setBackground(GLPcolors.backgroundColor);
+
+ panel.add(progressLabel,BorderLayout.NORTH);
+ panel.add(progressBar, BorderLayout.CENTER);
+ panel.add(searchButton, BorderLayout.EAST);
+
+ //Create a timer.
+ timer = new Timer(300, new ActionListener()
+ {
+
+ public void actionPerformed(ActionEvent evt)
+ {
+ int n = 0;
+ for (int i=0; i < 8; i++)
+ {
+ if (tasks[i] != null)
+ n += tasks[i].getValue();
+ }
+ progressBar.setValue(n);
+
+
+ //
+ // See if all the threads completed yet.
+ //
+ int d = 0;
+ for (int j=0; j < 8; j++ )
+ {
+ if (tasks[j] != null)
+ {
+ if (tasks[j].done())
+ {
+ d++;
+ }
+ }
+ else d++; // Thread removed ???
+ }
+
+ if (d >= 8)
+ {
+ timer.stop();
+ progressBar.setValue(progressBar.getMinimum());
+ searchButton.setActionCommand("Search");
+ searchButton.setText("Search");
+ progressLabel.setText("Search local subnet for CUPS servers");
+
+ String[] servers = GLPvars.getServerList();
+ if ((servers != null) && (servers.length > 0))
+ {
+ GLPvars.searchTM = new GLPjobTableModel(servers.length,1);
+ GLPvars.searchTM.setColumnName(0,"Search Results");
+ for (int i=0; i < servers.length; i++)
+ GLPvars.searchTM.setValueAt(servers[i],i,0);
+ GLPvars.searchTable = new JTable(GLPvars.searchTM);
+
+
+ GLPvars.searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ ListSelectionModel rowSM = GLPvars.searchTable.getSelectionModel();
+ rowSM.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ //Ignore extra messages.
+ if (e.getValueIsAdjusting()) return;
+
+ ListSelectionModel lsm =
+ (ListSelectionModel)e.getSource();
+ if (lsm.isSelectionEmpty())
+ {
+ //no rows are selected
+ }
+ else
+ {
+ int selectedRow = lsm.getMinSelectionIndex();
+ String newServer = (String)GLPvars.searchTM.getValueAt(selectedRow,0);
+ GLPvars.setServerName(newServer);
+ GLPvars.tabs.updateServerPanel(GLPvars.cupsServerName);
+ }
+ }
+ });
+ GLPvars.tabs.updateServerPanel(GLPvars.cupsServerName);
+ }
+ // DEBUG
+
+ } // threads complete?
+
+
+
+ }
+ });
+ }
+
+
+
+
+ /**
+ * The actionPerformed method in this class
+ * is called when the user presses the start button.
+ */
+ class ButtonListener implements ActionListener
+ {
+
+ public void actionPerformed(ActionEvent evt)
+ {
+
+ if (evt.getActionCommand().equals("Search"))
+ {
+ progressLabel.setText("Searching .....");
+ //
+ // Create the search threads ....
+ //
+ tasks = new GLPsearch[8];
+ for (int i=0; i < 8; i++)
+ tasks[i] = new GLPsearch(i+1);
+
+ searchButton.setActionCommand("Stop");
+ searchButton.setText("Stop");
+ for (int i=0; i < 8; i++)
+ {
+ if (tasks[i] != null)
+ {
+ tasks[i].start();
+ }
+ }
+ timer.start();
+ }
+ else if (evt.getActionCommand().equals("Stop"))
+ {
+ progressLabel.setText("Search local subnet for CUPS servers");
+
+ for (int i=0; i < 8; i++)
+ {
+ if (tasks[i] != null)
+ {
+ tasks[i].interrupt();
+ }
+ // tasks[i] = null;
+ }
+
+ searchButton.setActionCommand("Search");
+ searchButton.setText("Search");
+
+ } // Stop event
+
+ } // actionPerformed
+ } // end of class
+
+ public JPanel getPanel()
+ {
+ return(panel);
+ }
+
+
+}
diff --git a/scripting/java/example/GLPserver.java b/scripting/java/example/GLPserver.java
new file mode 100644
index 000000000..c819a9b39
--- /dev/null
+++ b/scripting/java/example/GLPserver.java
@@ -0,0 +1,192 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPserver implements ActionListener
+{
+
+ private JPanel serverPanel = null;
+ private JPanel searchPanel = null;
+
+ private GLPjobTableModel tm = null;
+ private JTable table = null;
+
+ protected JLabel currentLabel;
+ protected JLabel currentLabelValue;
+ protected JLabel actionLabel;
+ protected JTextField serverTextField;
+
+ protected static final String serverFieldString = "New Server Name:";
+ protected static final String applyButtonString = "Apply Changes";
+
+
+ // Constructor
+ public GLPserver()
+ {
+ GLPvars.searchTM = new GLPjobTableModel(1,1);
+ GLPvars.searchTM.setColumnName( 0, "Search Results" );
+ GLPvars.searchTM.setValueAt("No search results",0,0);
+ GLPvars.searchTable = new JTable(GLPvars.searchTM);
+
+ load();
+ }
+
+ public void load()
+ {
+ GridBagLayout serverLayout;
+ GridBagConstraints serverConst;
+
+ // Create the main panel to contain the two sub panels.
+ serverPanel = new JPanel();
+ serverLayout = new GridBagLayout();
+ serverConst = new GridBagConstraints();
+
+ serverPanel.setLayout(serverLayout);
+ serverPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ serverPanel.setBackground(GLPcolors.backgroundColor);
+
+
+ //Create a regular text field.
+ serverTextField = new JTextField(32);
+ serverTextField.setActionCommand(serverFieldString);
+ serverTextField.addActionListener(this);
+
+ //Create some labels for the fields.
+ JLabel serverFieldLabel = new JLabel(serverFieldString);
+ serverFieldLabel.setForeground(GLPcolors.foregroundColor);
+ serverFieldLabel.setLabelFor(serverTextField);
+
+ currentLabel = new JLabel("Current Server Name: ");
+ currentLabel.setForeground(GLPcolors.foregroundColor);
+ currentLabelValue = new JLabel(GLPvars.getServerName());
+
+ serverConst.gridwidth = GridBagConstraints.RELATIVE;
+ serverConst.gridx = 0;
+ serverConst.gridy = 0;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 0.4;
+ serverConst.weighty = 0.0;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( currentLabel, serverConst );
+ serverPanel.add(currentLabel);
+
+ serverConst.gridwidth = GridBagConstraints.RELATIVE;
+ serverConst.gridx = 1;
+ serverConst.gridy = 0;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 0.4;
+ serverConst.weighty = 0.0;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( currentLabelValue, serverConst );
+ serverPanel.add(currentLabelValue);
+
+ // Text
+ serverConst.gridwidth = GridBagConstraints.RELATIVE;
+ serverConst.gridx = 0;
+ serverConst.gridy = 1;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 0.4;
+ serverConst.weighty = 0.0;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( serverFieldLabel, serverConst );
+ serverPanel.add(serverFieldLabel);
+
+ serverConst.gridwidth = GridBagConstraints.RELATIVE;
+ serverConst.gridx = 1;
+ serverConst.gridy = 1;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 0.4;
+ serverConst.weighty = 0.0;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( serverTextField, serverConst );
+ serverPanel.add(serverTextField);
+
+ JButton applyButton = new JButton(applyButtonString);
+ applyButton.setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createRaisedBevelBorder(),
+ BorderFactory.createEmptyBorder(5,5,5,5)));
+ applyButton.setActionCommand(applyButtonString);
+ applyButton.addActionListener(this);
+ serverConst.gridx = 1;
+ serverConst.gridy = 2;
+ serverConst.fill = GridBagConstraints.NONE;
+ serverLayout.setConstraints( applyButton, serverConst );
+ serverConst.weightx = 0.4;
+ serverConst.weighty = 0.0;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverPanel.add(applyButton);
+
+ GLPsearchProgressPanel progress = new GLPsearchProgressPanel();
+ searchPanel = progress.getPanel();
+ serverConst.gridx = 1;
+ serverConst.gridy = 3;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 0.6;
+ serverConst.weighty = 0.3;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( searchPanel, serverConst );
+ serverPanel.add(searchPanel);
+
+ serverConst.gridx = 1;
+ serverConst.gridy = 4;
+ serverConst.fill = GridBagConstraints.HORIZONTAL;
+ serverConst.weightx = 1.0;
+ serverConst.weighty = 0.5;
+ serverConst.ipadx = 4;
+ serverConst.ipady = 4;
+ serverLayout.setConstraints( GLPvars.searchTable, serverConst );
+ serverPanel.add(GLPvars.searchTable);
+
+ }
+
+
+ public void actionPerformed(ActionEvent e)
+ {
+ if (e.getActionCommand().equals(serverFieldString))
+ {
+ String s = serverTextField.getText();
+ if (s.length() > 1)
+ {
+ GLPvars.setServerName(s);
+ serverTextField.setText("");
+ currentLabelValue.setText(GLPvars.getServerName());
+ }
+ }
+ else if (e.getActionCommand().equals(applyButtonString))
+ {
+ String s = serverTextField.getText();
+ if (s.length() > 1)
+ {
+ GLPvars.setServerName(s);
+ serverTextField.setText("");
+ currentLabelValue.setText(GLPvars.getServerName());
+ }
+ }
+ }
+
+ public void updateServer( String server )
+ {
+ GLPvars.setServerName(server);
+ load();
+ serverTextField.setText("");
+ currentLabelValue.setText(GLPvars.getServerName());
+ }
+
+
+ public JPanel getPanel()
+ {
+ return(serverPanel);
+ }
+
+}
diff --git a/scripting/java/example/GLPtabs.java b/scripting/java/example/GLPtabs.java
new file mode 100644
index 000000000..d4f5e7d49
--- /dev/null
+++ b/scripting/java/example/GLPtabs.java
@@ -0,0 +1,117 @@
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.net.URL;
+import java.net.*;
+import java.io.*;
+import org.cups.*;
+
+public class GLPtabs extends JPanel
+{
+ JTabbedPane tabPanel = null;
+
+ //
+ // Panels for the various tabs.
+ //
+ JPanel serverPanel = null;
+ JScrollPane printersPanel = null;
+ JPanel detailPanel = null;
+ JPanel optionsPanel = null;
+
+ GLPserver server = null;
+ GLPprinters printers = null;
+ GLPdetail detail = null;
+ GLPoptions options = null;
+
+
+
+ // Constructor
+ public GLPtabs()
+ {
+ tabPanel = new JTabbedPane();
+ tabPanel.setBackground(Color.white);
+
+ serverPanel = new JPanel();
+ server = new GLPserver();
+ serverPanel = server.getPanel();
+ tabPanel.add("Server", serverPanel);
+ tabPanel.setBackgroundAt(0,GLPcolors.tabBackgroundColor);
+ tabPanel.setForegroundAt(0,GLPcolors.tabForegroundColor);
+
+ printersPanel = new JScrollPane();
+ printers = new GLPprinters();
+ printersPanel = printers.getPanel();
+ tabPanel.add( "Printers", printersPanel );
+ tabPanel.setBackgroundAt(1,GLPcolors.tabBackgroundColor);
+ tabPanel.setForegroundAt(1,GLPcolors.tabForegroundColor);
+
+
+ detail = new GLPdetail();
+ detailPanel = detail.getPanel();
+ tabPanel.add( "Destination", detailPanel );
+ tabPanel.setBackgroundAt(2,GLPcolors.tabBackgroundColor);
+ tabPanel.setForegroundAt(2,GLPcolors.tabForegroundColor);
+
+ options = new GLPoptions();
+ optionsPanel = new JPanel();
+ optionsPanel.setBackground(GLPcolors.backgroundColor);
+ tabPanel.add( "Options", optionsPanel );
+ tabPanel.setBackgroundAt(3,GLPcolors.tabBackgroundColor);
+ tabPanel.setForegroundAt(3,GLPcolors.tabForegroundColor);
+
+ tabPanel.setSelectedIndex(0);
+
+ tabPanel.addChangeListener(new ChangeListener()
+ {
+ public void stateChanged( ChangeEvent e )
+ {
+ Object source = e.getSource();
+ if (!printers.cupsServerName.equals(GLPvars.getServerName()))
+ {
+ printers.load();
+ printersPanel = printers.getPanel();
+ tabPanel.setComponentAt(1,printersPanel);
+ }
+ }
+ });
+
+ JPanel jobsPanel = new JPanel();
+ JPanel filePanel = new JPanel();
+ }
+
+
+
+ public void updateServerPanel(String s)
+ {
+ server.updateServer(s);
+ serverPanel = server.getPanel();
+ tabPanel.setComponentAt(0,serverPanel);
+ }
+
+ public void updateDetailPanel()
+ {
+ detail.topDetail();
+ detailPanel = detail.getPanel();
+ tabPanel.setComponentAt(2,detailPanel);
+ }
+
+ public void updateOptionsPanel(CupsPrinter cp)
+ {
+ options.updateOptions(cp);
+ optionsPanel = options.getPanel();
+ tabPanel.setComponentAt(3,optionsPanel);
+ }
+
+ public boolean updatePrintersTab()
+ {
+ return(true);
+ }
+
+ public JTabbedPane getPanel()
+ {
+ return(tabPanel);
+ }
+
+}
diff --git a/scripting/java/example/GLPvars.java b/scripting/java/example/GLPvars.java
new file mode 100644
index 000000000..12576a0d1
--- /dev/null
+++ b/scripting/java/example/GLPvars.java
@@ -0,0 +1,93 @@
+
+import java.util.*;
+import javax.swing.*;
+import org.cups.*;
+
+public class GLPvars
+{
+ // Current selected server name or address.
+ public static String cupsServerName = null;
+
+ // Current selected printer name.
+ public static String selectedPrinterName = null;
+
+ // Current user name and password.
+ public static String cupsUser = "root";
+ public static String cupsPasswd = "Frak998";
+
+ // So we can access the tabs from other classes.
+ public static JTabbedPane mainGLPPanel = null;
+ public static GLPtabs tabs = null;
+
+ // List of servers found using search.
+ protected static List serverList = null;
+
+ // So we can update the search results from the search classes.
+ public static GLPjobTableModel searchTM = null;
+ public static JTable searchTable = null;
+
+ // What kind of jobs to list.
+ public static boolean showMyJobs = false;
+ public static boolean showCompletedJobs = false;
+
+ // Constructor
+ public GLPvars()
+ {
+ cupsServerName = "localhost";
+ serverList = new ArrayList();
+ }
+
+ public static void init()
+ {
+ cupsServerName = "localhost";
+ serverList = new ArrayList();
+ }
+
+
+ public static String getServerName()
+ {
+ return(cupsServerName);
+ }
+
+ public static void setServerName( String name )
+ {
+ cupsServerName = name;
+ }
+
+
+ //
+ // Reset the server list.
+ //
+ public static void clearServerList()
+ {
+ serverList = null;
+ }
+
+
+ //
+ // Add a cups server to the server list.
+ //
+ public static void addToServerList( String serverName )
+ {
+ if (serverList != null)
+ serverList.add(serverName);
+ }
+
+ //
+ // Get the full server list (if any).
+ //
+ public static String[] getServerList()
+ {
+ if (serverList != null)
+ {
+ String[] servers = new String[serverList.size()];
+ for (int i=0; i < serverList.size(); i++)
+ servers[i] = (String)serverList.get(i);
+ return(servers);
+ }
+ return(null);
+ }
+
+
+
+}
diff --git a/scripting/java/example/class.list b/scripting/java/example/class.list
new file mode 100644
index 000000000..27c251458
--- /dev/null
+++ b/scripting/java/example/class.list
@@ -0,0 +1,13 @@
+GLPcolors.java
+GLPdetail.java
+GLP.java
+GLPjobList.java
+GLPjobTableModel.java
+GLPoptions.java
+GLPprinterDetail.java
+GLPprinters.java
+GLPsearch.java
+GLPsearchProgressPanel.java
+GLPserver.java
+GLPtabs.java
+GLPvars.java
diff --git a/scripting/java/example/images/left.gif b/scripting/java/example/images/left.gif
new file mode 100644
index 000000000..fd7b04104
--- /dev/null
+++ b/scripting/java/example/images/left.gif
Binary files differ
diff --git a/scripting/java/example/images/print-test-page.gif b/scripting/java/example/images/print-test-page.gif
new file mode 100644
index 000000000..8268a1d14
--- /dev/null
+++ b/scripting/java/example/images/print-test-page.gif
Binary files differ
diff --git a/scripting/java/example/images/printer-idle.gif b/scripting/java/example/images/printer-idle.gif
new file mode 100644
index 000000000..68d990c62
--- /dev/null
+++ b/scripting/java/example/images/printer-idle.gif
Binary files differ
diff --git a/scripting/java/example/images/printer-stopped.gif b/scripting/java/example/images/printer-stopped.gif
new file mode 100644
index 000000000..76f45649b
--- /dev/null
+++ b/scripting/java/example/images/printer-stopped.gif
Binary files differ
diff --git a/scripting/java/example/images/restart-job.gif b/scripting/java/example/images/restart-job.gif
new file mode 100644
index 000000000..8dc072759
--- /dev/null
+++ b/scripting/java/example/images/restart-job.gif
Binary files differ
diff --git a/scripting/java/example/images/show-active.gif b/scripting/java/example/images/show-active.gif
new file mode 100644
index 000000000..0c1ef7d6c
--- /dev/null
+++ b/scripting/java/example/images/show-active.gif
Binary files differ
diff --git a/scripting/java/example/images/show-completed.gif b/scripting/java/example/images/show-completed.gif
new file mode 100644
index 000000000..760319152
--- /dev/null
+++ b/scripting/java/example/images/show-completed.gif
Binary files differ
diff --git a/scripting/java/src/org/cups/Cups.java b/scripting/java/src/org/cups/Cups.java
new file mode 100644
index 000000000..3c29faa6e
--- /dev/null
+++ b/scripting/java/src/org/cups/Cups.java
@@ -0,0 +1,1413 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>Cups</code> object is used for connecting to servers,
+ * reading and writing data, and performing common CUPS operations.
+ *
+ * @author TDB
+ * @version 1.0.1
+ * @since JDK1.3
+ */
+
+import java.io.*;
+import java.util.*;
+import java.net.*;
+
+public class Cups
+{
+
+ static final int REQ_STATE_CREATE_HTTP = 0;
+ static final int REQ_STATE_WRITE_HTTP_HEADER = 1;
+ static final int REQ_STATE_WRITE_IPP_HEADER = 2;
+ static final int REQ_STATE_WRITE_IPP_ATTRS = 3;
+ static final int REQ_STATE_FINISH_IPP_ATTRS = 4;
+ static final int REQ_STATE_READ_RESPONSE = 5;
+ static final int REQ_STATE_DONE = 6;
+ static final String[] req_state_names =
+ { "Create HTTP",
+ "Write Http Header",
+ "Write IPP Header",
+ "Write IPP Attrs",
+ "Finish IPP Attrs",
+ "Read Response",
+ "Done"
+ };
+
+
+ static final int FILEREQ_STATE_CREATE_HTTP = 0;
+ static final int FILEREQ_STATE_WRITE_HTTP_HEADER = 1;
+ static final int FILEREQ_STATE_WRITE_IPP_HEADER = 2;
+ static final int FILEREQ_STATE_WRITE_IPP_ATTRS = 3;
+ static final int FILEREQ_STATE_FINISH_IPP_ATTRS = 4;
+ static final int FILEREQ_STATE_WRITE_FILE_DATA = 5;
+ static final int FILEREQ_STATE_READ_RESPONSE = 6;
+ static final int FILEREQ_STATE_DONE = 7;
+ static final String[] filereq_state_names =
+ { "Create HTTP",
+ "Write Http Header",
+ "Write IPP Header",
+ "Write IPP Attrs",
+ "Finish IPP Attrs",
+ "Write File Data",
+ "Read Response",
+ "Done"
+ };
+
+
+ IPP ipp; // IPP Request
+ IPPHttp http; // Connection to server
+
+
+ String protocol; // Protocol name
+ String address; // address/name of server
+ int port; // Port #
+ String path; // Path ....
+ String dest; // Name of destination printer
+ String instance; // Instance of printer
+
+ //
+ // encrypt, user, and passwd are not fully implemented!
+ //
+ boolean encrypt; // Open encrypted connection.
+ String user; // User to login as.
+ String passwd; // Password if needed.
+
+ String site; // URL of site.
+
+ int last_error; // Last error #
+ String error_text; // Text for error
+
+ /**
+ * Void constructor.
+ */
+ public Cups()
+ {
+ http = null;
+ ipp = null;
+
+ protocol = "http";
+ address = "localhost";
+ port = 631;
+ path = "/";
+ site = "http://localhost:631/";
+ dest = "";
+ instance = "";
+ user = "";
+ passwd = "";
+ encrypt = false;
+ }
+
+ /**
+ * Constructor using a <code>URL</code>.
+ *
+ * @param <code>p_url</code> A <code>URL</code> object.
+ */
+ public Cups( URL p_url )
+ {
+ http = null;
+ ipp = null;
+
+ protocol = p_url.getProtocol() + "://";
+ address = p_url.getHost();
+ port = p_url.getPort();
+ path = p_url.getPath();
+
+ site = protocol + address;
+ if (port > 0)
+ site = site + ":" + port;
+
+ if (path.length() > 0)
+ site = site + path;
+
+ dest = "";
+ instance = "";
+ user = "";
+ passwd = "";
+ encrypt = false;
+ }
+
+
+ /**
+ * Set the value of the <code>protocol</code> member. Valid values
+ * are ipp or http.
+ *
+ * @param <code>p_protocol</code> String with protocol.
+ */
+ public void setProtocol( String p_protocol )
+ {
+ protocol = p_protocol;
+ site = protocol + "://" + address + ":" + port + path;
+ }
+
+ /**
+ * Set the value of the <code>server</code> member. This is an
+ * IP address or a hostname.
+ *
+ * @param <code>p_server</code> IP address or hostname.
+ */
+ public void setServer( String p_server )
+ {
+ address = p_server;
+ site = protocol + "://" + address + ":" + port + path;
+ }
+
+
+ /**
+ * Set the value of the <code>port</code> member.
+ *
+ * @param <code>p_port</code> Port number.
+ */
+ public void setPort( int p_port )
+ {
+ port = p_port;
+ site = protocol + "://" + address + ":" + port + path;
+ }
+
+
+ /**
+ * Set the value of the <code>user</code> member.
+ *
+ * @param <code>p_user</code> User name.
+ */
+ public void setUser( String p_user )
+ {
+ user = p_user;
+ }
+
+
+ /**
+ * Set the value of the <code>passwd</code> member.
+ *
+ * @param <code>p_passwd</code> Password.
+ */
+ public void setPasswd( String p_passwd )
+ {
+ passwd = p_passwd;
+ }
+
+
+ /**
+ * Set the value of the <code>dest</code> member.
+ *
+ * @param <code>p_dest</code> Destination.
+ */
+ public void setDest( String p_dest )
+ {
+ dest = p_dest;
+ }
+
+
+ /**
+ * Set the value of the <code>instance</code> member.
+ *
+ * @param <code>p_instance</code> Instance.
+ */
+ public void setInstance( String p_instance)
+ {
+ instance = p_instance;
+ }
+
+
+ /**
+ * Set the value of the <code>encrypt</code> member.
+ *
+ * @param <code>p_enrypt</code> Yes or no.
+ */
+ public void setEncrypt( boolean p_encrypt )
+ {
+ encrypt = p_encrypt;
+ }
+
+
+ /**
+ * Get the value of the <code>encrypt</code> member.
+ *
+ * @return <code>boolean</code> Encryption on or off.
+ */
+ public boolean getEncrypt()
+ {
+ return(encrypt);
+ }
+
+
+ /**
+ * Set the value of the <code>path</code> member. This is the
+ * path that will be used in the POST method.
+ *
+ * @param <code>p_path</code> Path on server.
+ */
+ public void setPath( String p_path )
+ {
+ path = p_path;
+ site = protocol + "://" + address + ":" + port + path;
+ }
+
+
+
+ public boolean doRequest(String from) throws IOException
+ {
+ // System.out.println("doRequest From: " + from );
+ return(doRequest());
+ }
+
+
+
+ /**
+ * Do a CUPS request to the server.
+ *
+ * @param <code>p_dest</code> Destination name.
+ * @return <code>boolean</code> True on success, false otherwise
+ * @throw <code>IOException</code>
+ */
+ public boolean doRequest() throws IOException
+ {
+ IPPAttribute attr;
+ int state = REQ_STATE_CREATE_HTTP;
+ int errors = 0;
+
+ while (true)
+ {
+ switch( state )
+ {
+
+ case REQ_STATE_CREATE_HTTP:
+ String url_str = site + dest;
+
+ try
+ {
+ if (user.length() > 0 && passwd.length() > 0)
+ http = new IPPHttp(url_str, "", user, passwd );
+ else
+ http = new IPPHttp(url_str);
+ state++;
+ }
+ catch (IOException e)
+ {
+ throw(e);
+ }
+ break;
+
+
+
+ case REQ_STATE_WRITE_HTTP_HEADER:
+ //
+ // Send the HTTP header.
+ //
+ switch( http.writeHeader( http.path, ipp.sizeInBytes() ))
+ {
+ case IPPHttp.HTTP_FORBIDDEN:
+ case IPPHttp.HTTP_NOT_FOUND:
+ case IPPHttp.HTTP_BAD_REQUEST:
+ case IPPHttp.HTTP_METHOD_NOT_ALLOWED:
+ case IPPHttp.HTTP_PAYMENT_REQUIRED:
+ case IPPHttp.HTTP_UPGRADE_REQUIRED:
+ case IPPHttp.HTTP_ERROR:
+ case IPPHttp.HTTP_UNAUTHORIZED:
+ errors++;
+ if (errors < 5)
+ {
+ if (!http.reConnect())
+ {
+ System.out.println("Could not reConnect(0)!");
+ return(false);
+ }
+ }
+ else
+ {
+ return(false);
+ }
+ break;
+
+ default: state++;
+ }
+ break;
+
+
+
+ case REQ_STATE_WRITE_IPP_HEADER:
+ //
+ // Send the request header.
+ //
+ byte[] header = new byte[8];
+ header[0] = (byte)1;
+ header[1] = (byte)1;
+ header[2] = (byte)((ipp.request.operation_id & 0xff00) >> 8);
+ header[3] = (byte)(ipp.request.operation_id & 0xff);
+ header[4] = (byte)((ipp.request.request_id & 0xff000000) >> 24);
+ header[5] = (byte)((ipp.request.request_id & 0xff0000) >> 16);
+ header[6] = (byte)((ipp.request.request_id & 0xff00) >> 8);
+ header[7] = (byte)(ipp.request.request_id & 0xff);
+ http.write( header );
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ if (http.reConnect())
+ state = REQ_STATE_WRITE_HTTP_HEADER;
+ else
+ {
+ System.out.println("Could not reConnect(1)\n");
+ return(false);
+ }
+ }
+ else
+ {
+ return(false);
+ }
+ }
+ else state++;
+ break;
+
+
+ case REQ_STATE_WRITE_IPP_ATTRS:
+ //
+ // Send the attributes list.
+ //
+ byte[] bytes;
+ int sz;
+ int last_group = -1;
+ boolean auth_error = false;
+ for (int i=0; i < ipp.attrs.size() && !auth_error; i++)
+ {
+ attr = (IPPAttribute)ipp.attrs.get(i);
+ sz = attr.sizeInBytes(last_group);
+ bytes = attr.getBytes(sz,last_group);
+ last_group = attr.group_tag;
+ http.write(bytes);
+
+ //
+ // Check for server response between each attribute.
+ //
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ if (!http.reConnect())
+ {
+ System.out.println("Could not reConnect(2)");
+ return(false);
+ }
+ state = REQ_STATE_WRITE_HTTP_HEADER;
+ auth_error = true;
+ }
+ else
+ {
+ return(false);
+ }
+ }
+
+ }
+ if (!auth_error)
+ state++;
+ break;
+
+
+
+ case REQ_STATE_FINISH_IPP_ATTRS:
+ //
+ // Send the end of attributes tag.
+ //
+ byte[] footer = new byte[1];
+ footer[0] = (byte)IPPDefs.TAG_END;
+ http.write( footer );
+
+ //
+ // Keep checking .....
+ //
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ if (!http.reConnect())
+ {
+ System.out.println("Could not reConnect(3)");
+ return(false);
+ }
+ state = REQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ {
+ return(false);
+ }
+ }
+ else state++;
+ break;
+
+
+
+ case REQ_STATE_READ_RESPONSE:
+ //
+ // Now read back response
+ //
+ int read_length;
+ read_length = http.read_header();
+ switch( http.status )
+ {
+ case IPPHttp.HTTP_OK:
+ break;
+
+ case IPPHttp.HTTP_UNAUTHORIZED:
+ http.reConnect();
+ state = REQ_STATE_WRITE_HTTP_HEADER;
+ errors = 0;
+ break;
+
+ default:
+ errors++;
+ if (errors < 5)
+ {
+ if (!http.reConnect())
+ {
+ System.out.println("Could not reConnect(4)");
+ return(false);
+ }
+ state = REQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ {
+ System.out.println("Too many errors: " + errors );
+ return(false);
+ }
+ break;
+ }
+
+ if ((read_length > 0) && (state == REQ_STATE_READ_RESPONSE))
+ {
+ http.read_buffer = http.read(read_length);
+ ipp = http.processResponse();
+ state++;
+ }
+ break;
+
+ case REQ_STATE_DONE:
+ //
+ // success.
+ //
+ http.conn.close();
+ http = null;
+ return(true);
+ }
+ }
+
+ } // End of doRequest
+
+
+
+ /**
+ * Send a FILE to the CUPS server.
+ *
+ * @param <code>file</code> File to send.
+ * @return <code>boolean</code> True on success, false otherwise
+ * @throw <code>IOException</code>
+ */
+ public boolean doRequest(File file) throws IOException
+ {
+ IPPAttribute attr;
+ int state = FILEREQ_STATE_CREATE_HTTP;
+ int errors = 0;
+ FileInputStream fis = null;
+
+ while (true)
+ {
+ switch( state )
+ {
+
+ case FILEREQ_STATE_CREATE_HTTP:
+ String url_str = site + dest;
+ try
+ {
+ if (user.length() > 0 && passwd.length() > 0)
+ http = new IPPHttp(url_str, "", user, passwd );
+ else
+ http = new IPPHttp(url_str);
+ state++;
+ }
+ catch (IOException e)
+ {
+ throw(e);
+ }
+ break;
+
+
+
+ case FILEREQ_STATE_WRITE_HTTP_HEADER:
+
+ if (fis != null)
+ {
+ fis.close();
+ }
+
+ //
+ // Open an input stream to the file.
+ //
+ try
+ {
+ fis = new FileInputStream(file);
+ }
+ catch (IOException e)
+ {
+ last_error = -1;
+ error_text = "Error opening file input stream.";
+ throw(e);
+ }
+
+ //
+ // Send the HTTP header.
+ //
+ int ippSz = ipp.sizeInBytes() + (int)file.length();
+ switch( http.writeHeader( http.path, ippSz ))
+ {
+ case IPPHttp.HTTP_FORBIDDEN:
+ case IPPHttp.HTTP_NOT_FOUND:
+ case IPPHttp.HTTP_BAD_REQUEST:
+ case IPPHttp.HTTP_METHOD_NOT_ALLOWED:
+ case IPPHttp.HTTP_PAYMENT_REQUIRED:
+ case IPPHttp.HTTP_UPGRADE_REQUIRED:
+ case IPPHttp.HTTP_ERROR:
+ case IPPHttp.HTTP_UNAUTHORIZED:
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ }
+ else
+ return(false);
+ break;
+
+ default: state++;
+ }
+ break;
+
+
+
+ case FILEREQ_STATE_WRITE_IPP_HEADER:
+ //
+ // Send the request header.
+ //
+ byte[] header = new byte[8];
+ header[0] = (byte)1;
+ header[1] = (byte)1;
+ header[2] = (byte)((ipp.request.operation_id & 0xff00) >> 8);
+ header[3] = (byte)(ipp.request.operation_id & 0xff);
+ header[4] = (byte)((ipp.request.request_id & 0xff000000) >> 24);
+ header[5] = (byte)((ipp.request.request_id & 0xff0000) >> 16);
+ header[6] = (byte)((ipp.request.request_id & 0xff00) >> 8);
+ header[7] = (byte)(ipp.request.request_id & 0xff);
+ http.write( header );
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ return(false);
+ }
+ else state++;
+ break;
+
+
+ case FILEREQ_STATE_WRITE_IPP_ATTRS:
+ //
+ // Send the attributes list.
+ //
+ byte[] bytes;
+ int sz;
+ int last_group = -1;
+ boolean auth_error = false;
+ for (int i=0; i < ipp.attrs.size() && !auth_error; i++)
+ {
+ attr = (IPPAttribute)ipp.attrs.get(i);
+ sz = attr.sizeInBytes(last_group);
+ bytes = attr.getBytes(sz,last_group);
+ last_group = attr.group_tag;
+ http.write(bytes);
+
+ //
+ // Check for server response between each attribute.
+ //
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ auth_error = true;
+ }
+ else
+ return(false);
+ }
+
+ }
+ if (!auth_error)
+ state++;
+ break;
+
+
+
+ case FILEREQ_STATE_FINISH_IPP_ATTRS:
+ //
+ // Send the end of attributes tag.
+ //
+ byte[] footer = new byte[1];
+ footer[0] = (byte)IPPDefs.TAG_END;
+ http.write( footer );
+
+ //
+ // Keep checking .....
+ //
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ return(false);
+ }
+ else state++;
+ break;
+
+
+
+ case FILEREQ_STATE_WRITE_FILE_DATA:
+ //
+ // Send the file data - this could be improved on ALOT.
+ //
+ int count;
+ byte[] b = new byte[1024];
+ while ((state == FILEREQ_STATE_WRITE_FILE_DATA) &&
+ ((count = fis.read(b)) != -1))
+ {
+ //
+ // Keep checking .....
+ //
+ if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
+ {
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ {
+ return(false);
+ }
+ }
+ else
+ {
+ if (count > 0)
+ http.write( b, count );
+ }
+
+ } // while
+
+ if (state == FILEREQ_STATE_WRITE_FILE_DATA)
+ {
+ fis.close();
+ fis = null;
+ state++;
+ }
+ break;
+
+
+
+ case FILEREQ_STATE_READ_RESPONSE:
+ //
+ // Now read back response
+ //
+ int read_length;
+ read_length = http.read_header();
+ switch( http.status )
+ {
+ case IPPHttp.HTTP_OK:
+ break;
+
+ case IPPHttp.HTTP_UNAUTHORIZED:
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ errors = 0;
+ break;
+
+ default:
+ errors++;
+ if (errors < 5)
+ {
+ http.reConnect();
+ state = FILEREQ_STATE_WRITE_HTTP_HEADER;
+ }
+ else
+ {
+ return(false);
+ }
+ break;
+ }
+
+ if ((read_length > 0) && (state == FILEREQ_STATE_READ_RESPONSE))
+ {
+ http.read_buffer = http.read(read_length);
+ ipp = http.processResponse();
+ state++;
+ }
+ break;
+
+ case FILEREQ_STATE_DONE:
+ //
+ // success.
+ //
+ http.conn.close();
+ http = null;
+ return(true);
+ }
+ }
+
+ } // End of doRequest(file)
+
+
+
+
+
+
+
+ /**
+ * Get a list of jobs.
+ *
+ * @param <code>showMyJobs</code> Show only jobs for user.
+ * @param <code>showCompleted</code> Show completed OR active jobs.
+ *
+ * @return <code>CupsJob[]</code> Array of job objects, or null.
+ * @throw <code>IOException</code>
+ */
+ public CupsJob[] cupsGetJobs( boolean showMyJobs, boolean showCompleted )
+ throws IOException
+ {
+
+ IPPAttribute a;
+
+ String req_attrs[] = /* Requested attributes */
+ {
+ "job-id",
+ "job-priority",
+ "job-k-octets",
+ "job-state",
+ "time-at-completed",
+ "time-at-creation",
+ "time-at-processing",
+ "job-printer-uri",
+ "document-format",
+ "job-name",
+ "job-originating-user-name"
+ };
+
+
+ ipp = new IPP();
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.GET_JOBS );
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+
+ //
+ // Add the printer uri
+ //
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
+ "printer-uri" );
+
+ if (site != null)
+ a.addString( "", site );
+ else
+ a.addString( "", "ipp://localhost/jobs" ); // Default ...
+ // a.dump_values();
+ ipp.addAttribute(a);
+
+
+ //
+ // Add the requesting user name
+ // **FIX** This should be fixed to use the user member.
+ //
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
+ "requesting-user-name" );
+ a.addString( "", "root" );
+ ipp.addAttribute(a);
+
+ //
+ // Show only my jobs?
+ //
+ if (showMyJobs)
+ {
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_BOOLEAN,
+ "my-jobs" );
+ a.addBoolean( true );
+ ipp.addAttribute(a);
+ }
+
+ //
+ // Show completed jobs?
+ //
+ if (showCompleted)
+ {
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_KEYWORD,
+ "which-jobs" );
+ a.addString( "", "completed" );
+ ipp.addAttribute(a);
+ }
+
+ //
+ // Get ALL attributes - to get only listed ones,
+ // uncomment this and fill in req_attrs.
+ //
+ // a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_KEYWORD,
+ // "requested-attributes" );
+ // a.addStrings( "", req_attrs );
+ // ipp.addAttribute(a);
+
+ //
+ // Do the request and process the response.
+ //
+ if (doRequest("cupsGetJobs"))
+ {
+
+
+ //
+ // First we have to figure out how many jobs there are
+ // so we can create the array.
+ //
+
+ //
+ // Skip past leading attributes
+ //
+ int i = 0;
+ int group_tag = -1;
+ while ((i < ipp.attrs.size()) && (group_tag != IPPDefs.TAG_JOB))
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ group_tag = a.group_tag;
+ if (group_tag != IPPDefs.TAG_JOB)
+ i++;
+ }
+
+ int num_jobs = 0;
+ group_tag = IPPDefs.TAG_JOB;
+ while ((i < ipp.attrs.size()) && (group_tag == IPPDefs.TAG_JOB))
+ {
+ a = (IPPAttribute)ipp.attrs.get(i++);
+ if ((a != null) && (a.name.compareTo("job-id") == 0))
+ num_jobs++;
+ // a.dump_values();
+ }
+
+ if (num_jobs < 1)
+ return(null);
+
+
+ //
+ // Now create the array of the proper size.
+ //
+ int n = 0;
+ CupsJob[] jobs = new CupsJob[num_jobs];
+ for (n=0; n < num_jobs; n++)
+ {
+ jobs[n] = new CupsJob();
+ }
+
+
+
+
+ //
+ // Skip past leading attributes
+ //
+ group_tag = -1;
+ i = 0;
+ while ((i < ipp.attrs.size()) && (group_tag != IPPDefs.TAG_JOB))
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ group_tag = a.group_tag;
+ if (group_tag != IPPDefs.TAG_JOB)
+ i++;
+ }
+
+ //
+ // Now we actually fill the array with the job data.
+ //
+ n = 0;
+ for (;i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+
+ if (a.group_tag == IPPDefs.TAG_ZERO)
+ {
+ n++;
+ continue;
+ }
+ else
+ {
+ try
+ {
+ jobs[n].updateAttribute( a );
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ return(jobs);
+ }
+ }
+ }
+ return( jobs );
+ }
+ return(null);
+
+ } // End of cupsGetJobs
+
+
+
+ /**
+ * Get a list of printers.
+ *
+ * @return <code>String[]</code> Array of printers, or null.
+ * @throw <code>IOException</code>
+ */
+ public String[] cupsGetPrinters()
+ throws IOException
+ {
+
+ IPPAttribute a;
+
+ ipp = new IPP();
+
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.CUPS_GET_PRINTERS );
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+
+ if (doRequest("cupsGetPrinters"))
+ {
+ int num_printers = 0;
+ for (int i=0; i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ if ((a.name.compareTo("printer-name") == 0) &&
+ (a.value_tag == IPPDefs.TAG_NAME))
+ {
+ num_printers++;
+ }
+ }
+ if (num_printers < 1)
+ return(null);
+
+ String[] printers = new String[num_printers];
+ IPPValue val;
+ int n = 0;
+ for (int i=0; i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ if (a.group_tag < 2)
+ continue;
+
+ if ((a.name.compareTo("printer-name") == 0) &&
+ (a.value_tag == IPPDefs.TAG_NAME))
+ {
+ val = (IPPValue)a.values.get(0);
+ if (val != null)
+ {
+ printers[n] = val.text;
+ n++;
+ }
+ }
+ }
+ return( printers );
+
+ } // if doRequest ...
+
+ return(null);
+
+ } // End of cupsGetPrinters
+
+
+
+
+ /**
+ * Get default destination.
+ *
+ * @return <code>String</code> Name of default printer, or null.
+ * @throw <code>IOException</code>
+ */
+ public String cupsGetDefault()
+ throws IOException
+ {
+
+ IPPAttribute a;
+
+
+ ipp = new IPP();
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.CUPS_GET_DEFAULT);
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+
+ if (doRequest("cupsGetDefault"))
+ {
+ if ((ipp == null) || (ipp.attrs == null))
+ return(null);
+
+ int num_printers = 0;
+ for (int i=0; i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ if ((a.name.compareTo("printer-name") == 0) &&
+ (a.value_tag == IPPDefs.TAG_NAME))
+ {
+ IPPValue val = (IPPValue)a.values.get(0);
+ if (val != null)
+ {
+ return( val.text );
+ }
+ }
+ }
+ } // if doRequest ...
+
+ return(null);
+
+ } // End of cupsGetDefault
+
+
+
+
+
+
+ /**
+ * Get printer attributes
+ *
+ * @param <code>printer_name</code> Name of printer to get info for.
+ * @return <code>List</code> List of attributes.
+ * @throw <code>IOException</code>
+ *
+ * @see <code>CupsPrinter</code>
+ */
+ public List cupsGetPrinterAttributes( String printer_name )
+ throws IOException
+ {
+
+ IPPAttribute a;
+
+ ipp = new IPP();
+
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.GET_PRINTER_ATTRIBUTES );
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
+ "printer-uri" );
+ a.addString( "", site + "/printers/" + printer_name );
+ ipp.addAttribute(a);
+
+ if (doRequest("cupsGetPrinterAttributes"))
+ {
+ return(ipp.attrs);
+ }
+
+ return(null);
+
+ } // End of cupsGetPrinterAttributes
+
+
+
+
+ /**
+ * Print a file.
+ *
+ * @param <code>p_filename</code> Path of file to print.
+ * @param <code>p_attrs[]</code> Array of print job attributes.
+ *
+ * @return <code>CupsJob</code> Object with job info.
+ *
+ * @throw <code>IOException</code>
+ *
+ * @see <code>CupsJob</code>
+ */
+ public CupsJob cupsPrintFile( String p_filename,
+ IPPAttribute p_attrs[] )
+ throws IOException
+ {
+
+ CupsJob job;
+ IPPAttribute a;
+ File file;
+
+
+ file = new File(p_filename);
+ if (!file.exists())
+ {
+ last_error = -1;
+ error_text = "File does not exist.";
+ return(null);
+ }
+
+ if (!file.canRead())
+ {
+ last_error = -1;
+ error_text = "File cannot be read.";
+ return(null);
+ }
+
+
+ ipp = new IPP();
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.PRINT_JOB );
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
+ "printer-uri" );
+ a.addString( "", site + dest );
+ ipp.addAttribute(a);
+
+ // ------------
+ // **FIX** Fix this later.
+/*
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
+ "requesting-user-name" );
+ // a.addString( "", p_username );
+ a.addString( "", "root");
+ ipp.addAttribute(a);
+*/
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
+ "job-name" );
+ a.addString( "", file.getName() );
+ ipp.addAttribute(a);
+
+ if (p_attrs != null)
+ {
+ for (int i=0; i < p_attrs.length; i++)
+ {
+ a = p_attrs[i];
+ ipp.addAttribute(a);
+ }
+ }
+
+ if (doRequest(file))
+ {
+ job = new CupsJob();
+ for (int i=0; i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ job.updateAttribute(a);
+ }
+ return(job);
+
+ } // if doRequest ...
+
+ return(null);
+
+ } // End of cupsPrintFile
+
+
+
+
+
+ /**
+ * Cancel a job - send a job cancel request to the server.
+ *
+ * @param <code>printer_name</code> Destination.
+ * @param <code>p_job_id</code> ID of job.
+ * @param <code>p_user_name</code> Requesting user name.
+ *
+ * @throw <code>IOException</code>
+ */
+ public int cupsCancelJob( String printer_name,
+ int p_job_id,
+ String p_user_name )
+ throws IOException
+ {
+
+ IPPAttribute a;
+
+ ipp = new IPP();
+
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest( 1, (short)IPPDefs.CANCEL_JOB );
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
+ "printer-uri" );
+ a.addString( "", site + dest );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_INTEGER,
+ "job-id" );
+ a.addInteger( p_job_id );
+ ipp.addAttribute(a);
+
+ // ------------
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
+ "requesting-user-name" );
+ a.addString( "", p_user_name );
+ ipp.addAttribute(a);
+
+ if (doRequest("cupsCancelJob"))
+ {
+ for (int i=0; i < ipp.attrs.size(); i++)
+ {
+ a = (IPPAttribute)ipp.attrs.get(i);
+ a.dump_values();
+ }
+ return(0);
+
+ } // if doRequest ...
+
+ return(0);
+
+ } // End of cupsCancelJob
+
+
+
+
+ public List cupsGetPrinterStatus(String printer_name)
+ throws IOException
+ {
+ IPPAttribute a;
+ String p_uri;
+
+ ipp = new IPP();
+
+ //
+ // Fill in the required attributes
+ //
+ ipp.request = new IPPRequest(1,(short)IPPDefs.GET_PRINTER_ATTRIBUTES);
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
+ "attributes-charset" );
+ a.addString( "", "iso-8859-1" );
+ ipp.addAttribute(a);
+
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
+ "attributes-natural-language" );
+ a.addString( "", "en" );
+ ipp.addAttribute(a);
+
+ a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
+ "printer-uri" );
+ p_uri = "ipp://" + address + ":" +
+ port + "/printers/" + printer_name;
+ a.addString( "", p_uri );
+ ipp.addAttribute(a);
+
+ if (doRequest("cupsGetPrinterStatus"))
+ {
+ return(ipp.attrs);
+ }
+ return(null);
+ }
+
+
+
+
+
+} // End of Cups class
+
diff --git a/scripting/java/src/org/cups/CupsJob.java b/scripting/java/src/org/cups/CupsJob.java
new file mode 100644
index 000000000..c38560ba6
--- /dev/null
+++ b/scripting/java/src/org/cups/CupsJob.java
@@ -0,0 +1,216 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+
+/**
+ * A <code>CupsJob</code> object holds job data, and has methods to
+ * process cups job list responses into a usable form.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+//
+import java.io.*;
+import java.net.*;
+
+public class CupsJob
+{
+ public int job_id;
+ public String job_more_info;
+ public String job_uri;
+ public String job_printer_uri;
+ public long job_printer_up_time;
+ public String job_name;
+ public String job_originating_user_name;
+ public String document_format;
+ public String job_originating_host_name;
+ public int job_priority;
+ public int job_state;
+ public int job_media_sheets_completed;
+ public int job_k_octets;
+ public long time_at_creation;
+ public long time_at_processing;
+ public long time_at_completed;
+ public String job_hold_until;
+ public String job_sheets;
+ public String job_state_reasons;
+
+
+ /**
+ * Constructor - set some default values.
+ */
+ public CupsJob()
+ {
+ job_id = -1;
+ job_more_info = "";
+ job_uri = "";
+ job_printer_uri = "";
+ job_printer_up_time = 0;
+ job_name = "";
+ job_originating_user_name = "";
+ document_format = "";
+ job_originating_host_name = "";
+ job_priority = -1;
+ job_state = 0;
+ job_media_sheets_completed = 0;
+ job_k_octets = 0;
+ time_at_creation = 0;
+ time_at_processing = 0;
+ time_at_completed = 0;
+ job_hold_until = "";
+ job_sheets = "";
+ job_state_reasons = "";
+ }
+
+
+
+
+ /**
+ * Process an attribute from a cups.doRequest() call
+ * and move the value into a local member.
+ *
+ * @see <code>IPPDefs</code>
+ * @see <code>IPPValues</code>
+ * @see <code>IPPAttributes</code>
+ */
+ public void updateAttribute( IPPAttribute a )
+ {
+ IPPValue val;
+
+ //
+ // Kick out if no values are present.
+ //
+ if (a.values.size() < 1)
+ return;
+
+ val = (IPPValue)a.values.get(0);
+ if (a.name.compareTo("job-more-info") == 0)
+ {
+ job_more_info = val.text;
+ }
+ else if (a.name.compareTo("job-uri") == 0)
+ {
+ job_uri = val.text;
+ }
+ else if (a.name.compareTo("job-printer-up-time") == 0)
+ {
+ job_printer_up_time = val.integer_value;
+ }
+ else if (a.name.compareTo("job-originating-user-name") == 0)
+ {
+ job_originating_user_name = val.text;
+ }
+ else if (a.name.compareTo("document-format") == 0)
+ {
+ document_format = val.text;
+ }
+ else if (a.name.compareTo("job-priority") == 0)
+ {
+ job_priority = val.integer_value;
+ }
+ else if (a.name.compareTo("job-originating-host-name") == 0)
+ {
+ job_originating_host_name = val.text;
+ }
+ else if (a.name.compareTo("job-id") == 0)
+ {
+ job_id = val.integer_value;
+ }
+ else if (a.name.compareTo("job-state") == 0)
+ {
+ job_state = val.integer_value;
+ }
+ else if (a.name.compareTo("job-media-sheets-completed") == 0)
+ {
+ job_media_sheets_completed = val.integer_value;
+ }
+ else if (a.name.compareTo("job-printer-uri") == 0)
+ {
+ job_printer_uri = val.text;
+ }
+ else if (a.name.compareTo("job-name") == 0)
+ {
+ job_name = val.text;
+ }
+ else if (a.name.compareTo("job-k-octets") == 0)
+ {
+ job_k_octets = val.integer_value;
+ }
+ else if (a.name.compareTo("time-at-creation") == 0)
+ {
+ time_at_creation = val.integer_value;
+ }
+ else if (a.name.compareTo("time-at-processing") == 0)
+ {
+ time_at_processing = val.integer_value;
+ }
+ else if (a.name.compareTo("time-at-completed") == 0)
+ {
+ time_at_completed = val.integer_value;
+ }
+ else if (a.name.compareTo("job-hold-until") == 0)
+ {
+ job_hold_until = val.text;
+ }
+ else if (a.name.compareTo("job-sheets") == 0)
+ {
+ job_sheets = val.text;
+ }
+ else if (a.name.compareTo("job-state-reasons") == 0)
+ {
+ job_state_reasons = val.text;
+ }
+ }
+
+
+ /**
+ * Convert a job status to a string.
+ *
+ * @see <code>IPPDefs</code>
+ */
+ public String jobStatusText()
+ {
+ switch( job_state )
+ {
+ case 3: return("Pending");
+ case 4: return("Held");
+ case 5: return("Processing");
+ case 6: return("Stopped");
+ case 7: return("Cancelled");
+ case 8: return("Aborted");
+ case 9: return("Completed");
+ }
+ return("Unknown");
+ }
+
+
+}
+
+// eof ....
diff --git a/scripting/java/src/org/cups/CupsPrinter.java b/scripting/java/src/org/cups/CupsPrinter.java
new file mode 100644
index 000000000..0e8c4dbeb
--- /dev/null
+++ b/scripting/java/src/org/cups/CupsPrinter.java
@@ -0,0 +1,837 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * A <code>CupsPrinter</code> holds printer attribute / status information,
+ * and has methods to process CUPS server responses.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+public class CupsPrinter
+{
+
+ //
+ // Printer attributes / status members.
+ //
+ String printer_name;
+
+ String printer_location;
+ String printer_info;
+ String printer_more_info;
+
+ String[] printer_uri_supported; // Strings
+ String[] uri_authentication_supported; // Strings
+ String[] uri_security_supported; // Strings
+
+ String attributes_charset;
+ String attributes_natural_language;
+
+ int printer_state;
+ String printer_state_text;
+ String printer_state_reasons;
+
+ boolean printer_is_accepting_jobs;
+
+ long printer_up_time;
+ long printer_current_time;
+
+ int queued_job_count;
+
+ String[] pdl_override_supported;
+ String[] ipp_versions_supported;
+
+ int[] operations_supported; // Integers
+
+ boolean multiple_document_jobs_supported;
+ int multiple_operation_time_out;
+ int[] multiple_document_handling_supported; // Integers
+
+ String charset_configured;
+ String natural_language_configured;
+ String generated_natural_language_supported;
+ String[] charset_supported; // Strings
+
+ String document_format_default;
+ String[] document_format_supported; // Strings
+
+ String[] compression_supported; // Strings
+
+ int job_priority_default;
+ int job_priority_supported;
+
+ int copies_default;
+ int lower_copies_supported;
+ int upper_copies_supported;
+
+ boolean page_ranges_supported;
+
+ int number_up_default;
+ int[] number_up_supported; // integers
+
+
+ int orientation_requested_default;
+ int[] orientation_requested_supported; // Integers
+
+ int job_quota_period;
+ int job_k_limit;
+ int job_page_limit;
+
+ String job_sheets_default; // Should this be a list too?
+ String[] job_sheets_supported; // Strings
+
+ String device_uri;
+
+ boolean color_supported;
+ int pages_per_minute;
+
+ String printer_make_and_model;
+
+ String media_default;
+ String[] media_supported; // Strings
+
+ int finishings_default;
+ int[] finishings_supported; // Integers
+
+ int printer_type;
+
+
+
+ /**
+ * Constructor. Does not get status or attributes.
+ *
+ * @param <code>c</code> Cups object.
+ *
+ * @see <code>Cups</code>
+ */
+ public CupsPrinter(Cups c)
+ {
+ setDefaults();
+ }
+
+ /**
+ * Constructor with name. Get status and attributes.
+ *
+ * @param <code>c</code> Cups object.
+ * @param <code>name</code> Name of printer.
+ *
+ * @see <code>Cups</code>
+ */
+ public CupsPrinter(Cups c, String name)
+ {
+ setDefaults();
+ printer_name = name;
+
+ //
+ //
+ getStatus(c);
+ getAttributes(c);
+ }
+
+
+
+ /**
+ * Initialize the members with mostly sane values.
+ *
+ */
+ public void setDefaults()
+ {
+ printer_name = "";
+ printer_location = "";
+ printer_info = "";
+ printer_more_info = "";
+ printer_uri_supported = null;
+ uri_authentication_supported = null;
+ uri_security_supported = null;
+ attributes_charset = "us-ascii";
+ attributes_natural_language = "en";
+ printer_state = -1;
+ printer_state_text = "";
+ printer_state_reasons = "";
+ printer_is_accepting_jobs = false;
+ printer_up_time = 0;
+ printer_current_time = 0;
+ queued_job_count = 0;
+ pdl_override_supported = null;
+ ipp_versions_supported = null;
+ operations_supported = null;
+ multiple_document_jobs_supported = false;
+ multiple_operation_time_out = 0;
+ multiple_document_handling_supported = null;
+ charset_configured = "";
+ natural_language_configured = "";
+ generated_natural_language_supported = "";
+ charset_supported = null;
+ document_format_default = "";
+ document_format_supported = null;
+ compression_supported = null;
+ job_priority_default = -1;
+ job_priority_supported = -1;
+ copies_default = 1;
+ lower_copies_supported = 1;
+ upper_copies_supported = 1;
+ page_ranges_supported = false;
+ number_up_default = 0;
+ number_up_supported = null;
+ orientation_requested_default = 0;
+ orientation_requested_supported = null;
+ job_quota_period = 0;
+ job_k_limit = 0;
+ job_page_limit = 0;
+ job_sheets_default = "none,none";
+ job_sheets_supported = null;
+ device_uri = "";
+ color_supported = false;
+ pages_per_minute = 0;
+ printer_make_and_model = "";
+ media_default = "";
+ media_supported = null;
+ finishings_default = 0;
+ finishings_supported = null;
+ printer_type = 0;
+ }
+
+
+ /**
+ * Get the printer's status.
+ *
+ * @param <code>c</code> Cups object.
+ *
+ * @return <code>Boolean</code> True on success.
+ *
+ * @see <code>Cups</code>
+ */
+ public boolean getStatus(Cups c)
+ {
+ List attrs;
+ IPPAttribute a;
+ String p_uri;
+
+ try
+ {
+ attrs = c.cupsGetPrinterStatus(printer_name);
+ for (int i=0; i < attrs.size(); i++)
+ {
+ a = (IPPAttribute)attrs.get(i);
+ updateAttribute(a);
+ }
+ return(true);
+ }
+ catch (IOException e)
+ {
+ return(false);
+ }
+ }
+
+
+
+ /**
+ * Get the printer's attributes.
+ *
+ * @param <code>c</code> Cups object.
+ *
+ * @return <code>Boolean</code> True on success.
+ *
+ * @see <code>Cups</code>
+ */
+ public boolean getAttributes(Cups c)
+ {
+ List attrs;
+ IPPAttribute a;
+ String p_uri;
+
+ try
+ {
+ attrs = c.cupsGetPrinterAttributes(printer_name);
+ for (int i=0; i < attrs.size(); i++)
+ {
+ a = (IPPAttribute)attrs.get(i);
+ updateAttribute(a);
+ }
+ return(true);
+ }
+ catch (IOException e)
+ {
+ return(false);
+ }
+ }
+
+
+
+
+ /**
+ * Process an attribute from the cups.doRequest() method and move
+ * the values into local members.
+ *
+ * @param <code>a</code> IPPAttribute.
+ *
+ * @see <code>IPPAttributes</code>
+ * @see <code>IPPValues</code>
+ */
+ public void updateAttribute( IPPAttribute a )
+ {
+ IPPValue v;
+ int i;
+
+ // a.dump_values();
+
+ if (a.name.compareTo("printer-name") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_name = v.text;
+ }
+ else if (a.name.compareTo("printer-location") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_location = v.text;
+ }
+ else if (a.name.compareTo("printer-info") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_info = v.text;
+ }
+ else if (a.name.compareTo("printer-more-info") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_more_info = v.text;
+ }
+ else if (a.name.compareTo("printer-uri-supported") == 0)
+ {
+ printer_uri_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ printer_uri_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("uri-authentication-supported") == 0)
+ {
+ uri_authentication_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ uri_authentication_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("uri-security-supported") == 0)
+ {
+ uri_security_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ uri_security_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("attributes-charset") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ attributes_charset = v.text;
+ }
+ else if (a.name.compareTo("attributes-natural-language") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ attributes_natural_language = v.text;
+ }
+ else if (a.name.compareTo("printer-state") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_state = v.integer_value;
+ switch( printer_state )
+ {
+ case 3: printer_state_text = "idle";
+ break;
+ case 4: printer_state_text = "processing";
+ break;
+ case 5: printer_state_text = "stopped";
+ break;
+ }
+ }
+ else if (a.name.compareTo("printer-state-reasons") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_state_reasons = v.text;
+ }
+ else if (a.name.compareTo("printer-is-accepting-jobs") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_is_accepting_jobs = v.boolean_value;
+ }
+ else if (a.name.compareTo("printer-up-time") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_up_time = v.integer_value;
+ }
+ else if (a.name.compareTo("printer-current-time") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_current_time = v.unix_time; // *** FIX ***
+ }
+ else if (a.name.compareTo("queue-job-count") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ queued_job_count = v.integer_value;
+ }
+ else if (a.name.compareTo("pdl-override-supported") == 0)
+ {
+ pdl_override_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ pdl_override_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("ipp-versions-supported") == 0)
+ {
+ ipp_versions_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ ipp_versions_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("operations-supported") == 0)
+ {
+ operations_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ operations_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("multiple-document-jobs-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ multiple_document_jobs_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("multiple-operation-time-out") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ multiple_operation_time_out = v.integer_value;
+ }
+ else if (a.name.compareTo("multiple-document-handling-supported") == 0)
+ {
+ multiple_document_handling_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ multiple_document_handling_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("charset-configured") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ charset_configured = v.text;
+ }
+ else if (a.name.compareTo("natural-language-configured") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ natural_language_configured = v.text;
+ }
+ else if (a.name.compareTo("generated-natural-language-supported") == 0)
+ {
+ // *** Should this be a list too?
+ v = (IPPValue)a.values.get(0);
+ generated_natural_language_supported = v.text;
+ }
+ else if (a.name.compareTo("charset-supported") == 0)
+ {
+ charset_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ charset_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("document-format-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ document_format_default = v.text;
+ }
+ else if (a.name.compareTo("document-format-supported") == 0)
+ {
+ document_format_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ document_format_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("compression-supported") == 0)
+ {
+ compression_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ compression_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("job-priority-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_priority_default = v.integer_value;
+ }
+ else if (a.name.compareTo("job-priority-supported") == 0)
+ {
+ // *** Should be a list? ***
+ v = (IPPValue)a.values.get(0);
+ job_priority_supported = v.integer_value;
+ }
+ else if (a.name.compareTo("copies-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ copies_default = v.integer_value;
+ }
+ else if (a.name.compareTo("copies-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ lower_copies_supported = v.lower;
+ upper_copies_supported = v.upper;
+ }
+ else if (a.name.compareTo("page-ranges-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ page_ranges_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("number-up-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ number_up_default = v.integer_value;
+ }
+ else if (a.name.compareTo("number-up-supported") == 0)
+ {
+ number_up_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ number_up_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("orientation-requested-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ orientation_requested_default = v.integer_value;
+ }
+ else if (a.name.compareTo("orientation-requested-supported") == 0)
+ {
+ orientation_requested_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ orientation_requested_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("job-quota-period") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_quota_period = v.integer_value;
+ }
+ else if (a.name.compareTo("job-k-limit") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_k_limit = v.integer_value;
+ }
+ else if (a.name.compareTo("job-page-limit") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_page_limit = v.integer_value;
+ }
+ else if (a.name.compareTo("job-sheets-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ job_sheets_default = v.text;
+ }
+ else if (a.name.compareTo("job-sheets-supported") == 0)
+ {
+ job_sheets_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ job_sheets_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("device-uri") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ device_uri = v.text;
+ }
+ else if (a.name.compareTo("color-supported") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ color_supported = v.boolean_value;
+ }
+ else if (a.name.compareTo("pages-per-minute") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ pages_per_minute = v.integer_value;
+ }
+ else if (a.name.compareTo("printer-make-and-model") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_make_and_model = v.text;
+ }
+ else if (a.name.compareTo("media-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ media_default = v.text;
+ }
+ else if (a.name.compareTo("media-supported") == 0)
+ {
+ media_supported = new String[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ media_supported[i] = v.text;
+ }
+ }
+ else if (a.name.compareTo("finishings-default") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ finishings_default = v.integer_value;
+ }
+ else if (a.name.compareTo("finishings-supported") == 0)
+ {
+ finishings_supported = new int[a.values.size()];
+ for (i=0; i < a.values.size(); i++)
+ {
+ v = (IPPValue)a.values.get(i);
+ finishings_supported[i] = v.integer_value;
+ }
+ }
+ else if (a.name.compareTo("printer-type") == 0)
+ {
+ v = (IPPValue)a.values.get(0);
+ printer_type = v.integer_value;
+ }
+
+ } // End of updateAttribute()
+
+
+ /**
+ * Get the printer name.
+ *
+ * @return <code>String</code> Printer Name.
+ */
+ public String getPrinterName()
+ {
+ return(printer_name);
+ }
+
+ /**
+ * Get the printer state text.
+ *
+ * @return <code>String</code> State text.
+ */
+ public String getStateText()
+ {
+ return(printer_state_text);
+ }
+
+ /**
+ * Get the printer state reasons.
+ *
+ * @return <code>String</code> State reason.
+ */
+ public String getStateReasons()
+ {
+ return(printer_state_reasons);
+ }
+
+ /**
+ * Get the printer location.
+ *
+ * @return <code>String</code> State location.
+ */
+ public String getLocation()
+ {
+ return(printer_location);
+ }
+
+ /**
+ * Get the printer make and model.
+ *
+ * @return <code>String</code> Make and model.
+ */
+ public String getMakeAndModel()
+ {
+ return(printer_make_and_model);
+ }
+
+
+
+ /**
+ * Get the default job sheets.
+ *
+ * @return <code>String</code> Default job sheets.
+ */
+ public String getJobSheetsDefault()
+ {
+ return(job_sheets_default);
+ }
+
+ /**
+ * Get the printer job sheets supported.
+ *
+ * @return <code>String[]</code> Array of supported job sheets.
+ */
+ public String[] getJobSheetsSupported()
+ {
+ return(job_sheets_supported);
+ }
+
+
+ /**
+ * Get the default orientation.
+ *
+ * @return <code>int</code> Default page orientation.
+ */
+ public int getOrientationDefault()
+ {
+ return(orientation_requested_default);
+ }
+
+ /**
+ * Get the printer orientation supported.
+ *
+ * @return <code>int[]</code> Array of supported orientations.
+ */
+ public int[] getOrientationSupported()
+ {
+ return(orientation_requested_supported);
+ }
+
+
+ /**
+ * Get the printer lower copies supported.
+ *
+ * @return <code>int</code> Lower of the range.
+ */
+ public int getLowerCopiesSupported()
+ {
+ return(lower_copies_supported);
+ }
+
+
+ /**
+ * Get the printer upper copies supported.
+ *
+ * @return <code>int</code> Upper of the range.
+ */
+ public int getUpperCopiesSupported()
+ {
+ return(upper_copies_supported);
+ }
+
+
+ /**
+ * Get the printer number of copies default.
+ *
+ * @return <code>int</code> Default number of copies.
+ */
+ public int getCopiesDefault()
+ {
+ return(copies_default);
+ }
+
+
+ /**
+ * Get whether the printer supports page ranges.
+ *
+ * @return <code>boolean</code> True or false.
+ */
+ public boolean getPageRangesSupported()
+ {
+ return(page_ranges_supported);
+ }
+
+
+
+ /**
+ * Debug method.
+ */
+ void dump()
+ {
+ int i;
+
+ System.out.println("Printer Name: " + printer_name );
+ System.out.println("Location: " + printer_location );
+ System.out.println("Printer Info: " + printer_info );
+ System.out.println("More Info: " + printer_more_info );
+
+ if (printer_uri_supported != null)
+ {
+ System.out.println("Printer URI's Supported: ");
+ for (i=0; i < printer_uri_supported.length; i++)
+ {
+ System.out.println(" " + printer_uri_supported[i] );
+ }
+ }
+
+ if (uri_authentication_supported != null)
+ {
+ System.out.println("URI Authentication Supported: ");
+ for (i=0; i < uri_authentication_supported.length; i++)
+ {
+ System.out.println(" " + uri_authentication_supported[i] );
+ }
+ }
+
+ if (uri_security_supported != null)
+ {
+ System.out.println("URI Security Supported: ");
+ for (i=0; i < uri_security_supported.length; i++)
+ {
+ System.out.println(" " + uri_security_supported[i] );
+ }
+ }
+
+ System.out.println("Attributes Charset: " + attributes_charset );
+ System.out.println("Attributes Natural Language: " + attributes_natural_language );
+
+ System.out.println("Printer State: " + printer_state );
+ System.out.println("Printer State Text: " + printer_state_text );
+ System.out.println("Printer State Reasons: " + printer_state_reasons );
+
+ if (printer_is_accepting_jobs)
+ System.out.println("Accepting Jobs: Yes");
+ else
+ System.out.println("Accepting Jobs: No");
+
+
+}
+
+
+
+} // End of CupsPrinter class
+
+
diff --git a/scripting/java/src/org/cups/IPP.java b/scripting/java/src/org/cups/IPP.java
new file mode 100644
index 000000000..650687d1a
--- /dev/null
+++ b/scripting/java/src/org/cups/IPP.java
@@ -0,0 +1,251 @@
+package org.cups;
+
+/**
+ * @version 0.00 06-NOV-2001
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+import java.util.*;
+
+/**
+ * An <code>IPP</code> object is used to hold the various
+ * attributes and status of an ipp request..
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+public class IPP
+{
+ public IPPRequest request; // The request header
+ public IPPStatus status; // Status of request
+ public List attrs; // Attributes list.
+
+ short state; // Current IPP state (of request???)
+ int current; // Index into attributes array.
+ int last; // Index into attributes array.
+ short current_tag;
+
+
+ // ------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ public IPP()
+ {
+ state = IPPDefs.IDLE;
+ attrs = new LinkedList();
+ current = -1;
+ last = -1;
+ current_tag = IPPDefs.TAG_ZERO;
+ }
+
+
+
+ /**
+ * Add an attribute to the attibutes list
+ * for later parsing.
+ *
+ * @param a <code>IPPAttribute</code> to add.
+ * @return <code>true</code> always returns <code>true</code>
+ * for now.
+ *
+ * @see IPPAttribute
+ * @see IPPValue
+ */
+ public boolean addAttribute( IPPAttribute a )
+ {
+ attrs.add(a);
+ return(true);
+ }
+
+ /**
+ * Get the current attribute pointed at by
+ * <code>current</code>.
+ *
+ * @return <code>IPPAttribute</code> Return the current attribute.
+ * @return <code>null</code> Return <code>null</code>
+ * if <code>current</code> is 0.
+ */
+ public IPPAttribute getCurrentAttribute()
+ {
+ if (current >= 0)
+ return( (IPPAttribute)attrs.get(current) );
+ else
+ return( null );
+ }
+
+ // public void setCurrentAttribute( IPPAttribute p_attr )
+ // {
+ // if (current >= 0)
+ // return( (IPPAttribute)attrs.get(current) );
+ // }
+
+
+ /**
+ *
+ * Find the named attribute of the correct type. Both must match.
+ * This methos searches from the beginning of the attribute list,
+ * rather than from the current position.
+ *
+ * @param p_name <code>String</code> containing the name.
+ * @param p_type <code>int</code> attribute type.
+ *
+ * @return <code>IPPAttribute</code> Matching attribute if found.
+ * @return <code>null</code> <code>null</code> if not found.
+ */
+ public IPPAttribute ippFindAttribute( String p_name, int p_type )
+ {
+ if (p_name.length() < 1)
+ return(null);
+ current = -1;
+ return(ippFindNextAttribute(p_name, p_type));
+ }
+
+
+
+
+ /**
+ *
+ * Find the named attribute of the correct type. Both must match.
+ * This methos searches from the current position in the attribute list.
+ *
+ * @param p_name <code>String</code> containing the name.
+ * @param p_type <code>int</code> attribute type.
+ *
+ * @return <code>IPPAttribute</code> Matching attribute if found.
+ * @return <code>null</code> <code>null</code> if not found.
+ */
+ public IPPAttribute ippFindNextAttribute( String p_name, int p_type )
+ {
+ int value_tag;
+
+ if (p_name.length() < 1)
+ return(null);
+
+ if ((current >= 0) && (current < (attrs.size() - 1)))
+ current++;
+ else
+ current = 0;
+
+ for (int i = current; i < attrs.size(); i++)
+ {
+ IPPAttribute tmp = (IPPAttribute)attrs.get(i);
+ value_tag = (tmp.value_tag & IPPDefs.TAG_MASK);
+ if ((tmp.name.length() > 0) && (tmp.name == p_name) &&
+ (value_tag == p_type || p_type == IPPDefs.TAG_ZERO ||
+ (value_tag == IPPDefs.TAG_TEXTLANG && p_type == IPPDefs.TAG_TEXT) ||
+ (value_tag == IPPDefs.TAG_NAMELANG && p_type == IPPDefs.TAG_NAME)))
+ {
+ current = i;
+ return(tmp);
+ }
+ }
+ return(null);
+ }
+
+
+ /**
+ * Get the size in bytes of an <code>IPP</code> request.
+ *
+ * @return <code>int</code> Number of bytes for the request.
+ */
+ public int sizeInBytes()
+ {
+ IPPAttribute a;
+ int bytes = 8;
+ int last_group = IPPDefs.TAG_ZERO;
+
+ for (int i=0; i < attrs.size(); i++)
+ {
+ a = (IPPAttribute)attrs.get(i);
+ bytes += a.sizeInBytes(last_group);
+ last_group = a.group_tag;
+ }
+ bytes++; // one for the end tag.
+
+ return(bytes);
+
+ } // End of IPP.sizeInBytes()
+
+
+
+
+
+ int ippBytes()
+ {
+ int i = 0;
+ return(0);
+ }
+
+
+
+ /**
+ * Set the <code>IPP</code> request ID.
+ *
+ * @param p_id <code>short</code> request id.
+ */
+ public void setRequestID( short p_id )
+ {
+ request.request_id = p_id;
+ }
+
+ /**
+ * Set the <code>IPP</code> operation ID.
+ *
+ * @param p_operation_id <code>short</code> operation id.
+ */
+ public void setRequestOperationID( short p_operation_id )
+ {
+ request.operation_id = p_operation_id;
+ }
+
+
+ //
+ // Dump a list - for debugging.
+ //
+ public void dump_response()
+ {
+ IPPAttribute a;
+ int last_group = IPPDefs.TAG_ZERO;
+
+ for (int i=0; i < attrs.size(); i++)
+ {
+ a = (IPPAttribute)attrs.get(i);
+ a.dump_values();
+ last_group = a.group_tag;
+ }
+ return;
+
+ } // End of IPP.dump_response()
+
+
+} // End of IPP class
+
+
+
+
+//
+// End of IPP.java
+//
diff --git a/scripting/java/src/org/cups/IPPAttribute.java b/scripting/java/src/org/cups/IPPAttribute.java
new file mode 100644
index 000000000..9d53fe183
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPAttribute.java
@@ -0,0 +1,593 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+/**
+ * An <code>IPPAttribute</code> object hold attributes for communicating
+ * messages to / from the CUPS server.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+import java.util.*;
+
+public class IPPAttribute
+{
+ int group_tag;
+ int value_tag;
+ String name;
+ List values;
+
+
+
+ public IPPAttribute( int p_group_tag, int p_value_tag,
+ String p_name )
+ {
+ group_tag = p_group_tag;
+ value_tag = p_value_tag;
+ name = p_name;
+ values = new ArrayList();
+
+ } // End of IPPAttribute constructor.
+
+
+ //
+ // Add a boolean value to the objects values list.
+ //
+ public boolean addBoolean( boolean p_bool )
+ {
+ IPPValue val = new IPPValue( p_bool );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add a set of boolean values to the objects values list.
+ //
+ public boolean addBooleans( boolean p_bools[] )
+ {
+ if (p_bools.length < 1)
+ return(false);
+
+ for (int i=0; i < p_bools.length; i++ )
+ {
+ IPPValue val = new IPPValue( p_bools[i] );
+ values.add(val);
+ }
+ return(true);
+ }
+
+
+ //
+ // Add an enum value to the objects values list.
+ //
+ public boolean addEnum( int p_int )
+ {
+ IPPValue val = new IPPValue( p_int, true );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add an integer value to the objects values list.
+ //
+ public boolean addInteger( int p_int )
+ {
+ IPPValue val = new IPPValue( p_int );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add a set of integer values to the objects values list.
+ //
+ public boolean addIntegers( int p_ints[] )
+ {
+ if (p_ints.length < 1)
+ return(false);
+
+ for (int i=0; i < p_ints.length; i++ )
+ {
+ IPPValue val = new IPPValue( p_ints[i] );
+ values.add(val);
+ }
+ return(true);
+ }
+
+
+ //
+ // Add a string value to the objects values list.
+ //
+ public boolean addString( String p_charset, String p_text )
+ {
+ String l_value;
+ String final_value;
+
+ //
+ // Force the value to English for POSIX locale.
+ //
+ if ((value_tag == IPPDefs.TAG_LANGUAGE) && (p_text == "C"))
+ {
+ l_value = "en";
+ }
+ else
+ {
+ l_value = p_text;
+ }
+
+
+ //
+ // Convert language values to lowercase and _ to - as needed.
+ //
+ if ((value_tag == IPPDefs.TAG_LANGUAGE) ||
+ (value_tag == IPPDefs.TAG_CHARSET))
+ {
+ StringBuffer temp = new StringBuffer(l_value.length());
+ char c;
+ for (int i = 0; i < l_value.length(); i++)
+ {
+ c = l_value.charAt(i);
+ if (c == '_')
+ c = '-';
+ else if (Character.isUpperCase(c))
+ c = Character.toLowerCase(c);
+ temp.append(c);
+ }
+ final_value = temp.toString();
+ }
+ else
+ {
+ final_value = l_value;
+ }
+ IPPValue val = new IPPValue( p_charset, final_value );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add a set of strings to the objects values list.
+ //
+ public boolean addStrings( String p_charset, String p_texts[] )
+ {
+ if (p_texts.length < 1)
+ return(false);
+
+ //
+ // Just call the singular string method to save on coding.
+ //
+ for (int i=0; i < p_texts.length; i++ )
+ {
+ addString( p_charset, p_texts[i] );
+ }
+ return(true);
+ }
+
+ //
+ // Add an ipp date value to the objects values list.
+ //
+ public boolean addDate( char p_date[] )
+ {
+ IPPValue val = new IPPValue( p_date );
+ values.add(val);
+ return(true);
+ }
+
+ //
+ // Add a range value to the objects values list.
+ //
+ public boolean addRange( int p_lower, int p_upper )
+ {
+ IPPValue val = new IPPValue( p_lower, p_upper );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add a set of range values to the objects values list.
+ //
+ public boolean addRanges( int p_lower[], int p_upper[] )
+ {
+ //
+ // Avoid index out of bounds errors.
+ //
+ if (p_lower.length != p_upper.length)
+ return(false);
+
+ for (int i=0; i < p_lower.length; i++ )
+ addRange( p_lower[i], p_upper[i] );
+ return(true);
+ }
+
+
+ //
+ // Add a resolution value to the objects values list.
+ //
+ public boolean addResolution( byte p_units, int p_xres, int p_yres )
+ {
+ IPPValue val = new IPPValue( p_units, p_xres, p_yres );
+ values.add(val);
+ return(true);
+ }
+
+
+ //
+ // Add a set of resolution values to the objects values list.
+ //
+ public boolean addResolutions( byte p_units, int p_xres[], int p_yres[] )
+ {
+ if (p_xres.length != p_yres.length)
+ return(false);
+
+ for (int i=0; i < p_xres.length; i++)
+ addResolution( p_units, p_xres[i], p_yres[i] );
+ return(true);
+ }
+
+
+ //
+ // Set the attribute as a separator.
+ //
+ public boolean addSeparator()
+ {
+ value_tag = IPPDefs.TAG_ZERO;
+ group_tag = IPPDefs.TAG_ZERO;
+ return(true);
+ }
+
+
+
+ //
+ // Calculate the size in bytes for an IPP requests attributes.
+ //
+ public int sizeInBytes(int last_group)
+ {
+ IPPValue val;
+ int bytes = 0; // Start with one for the group tag.
+
+ //
+ // Add 1 if first time, or group tag changes.
+ //
+ if (last_group != group_tag)
+ bytes ++;
+
+ bytes ++; // Add 1 for the value tag.
+ bytes += 2; // Add 2 for the name length field.
+ bytes += name.length(); // Add the length of the name.
+
+ for (int i=0; i < values.size(); i++ )
+ {
+ val = (IPPValue)values.get(i);
+
+ if (i > 0)
+ {
+ // If an array of values, add 1 for another value tag, plus
+ // 2 for zero length name.
+ //
+ bytes += 3;
+ }
+
+ switch (value_tag)
+ {
+ case IPPDefs.TAG_INTEGER :
+ case IPPDefs.TAG_ENUM :
+ bytes += 2;
+ bytes += 4;
+ break;
+
+ case IPPDefs.TAG_BOOLEAN :
+ bytes += 2;
+ bytes ++;
+ break;
+
+ case IPPDefs.TAG_TEXT:
+ case IPPDefs.TAG_NAME:
+ case IPPDefs.TAG_KEYWORD:
+ case IPPDefs.TAG_STRING:
+ case IPPDefs.TAG_URI:
+ case IPPDefs.TAG_URISCHEME:
+ case IPPDefs.TAG_CHARSET:
+ case IPPDefs.TAG_LANGUAGE:
+ case IPPDefs.TAG_MIMETYPE:
+ bytes += 2;
+ bytes += val.text.length();
+ break;
+
+ case IPPDefs.TAG_DATE :
+ bytes += 2;
+ bytes += 11;
+ break;
+
+ case IPPDefs.TAG_RESOLUTION :
+ bytes += 2;
+ bytes += 9;
+ break;
+
+ case IPPDefs.TAG_RANGE :
+ bytes += 2;
+ bytes += 8;
+ break;
+
+ case IPPDefs.TAG_TEXTLANG :
+ case IPPDefs.TAG_NAMELANG :
+ bytes += 6; // 2 overall len, 2 charset len, 2 text len
+ bytes += val.charset.length() +
+ val.text.length();
+ break;
+
+ default :
+ bytes += 2;
+ if (val.data != null)
+ bytes += val.data.length;
+ break;
+ }
+ }
+
+ // bytes++; // 1 byte for end of values tag.
+
+ return(bytes);
+
+ } // End of IPPAttribute.sizeInBytes()
+
+
+ //
+ // Get the characters of an attribute
+ //
+ public byte[] getBytes( int sz, int last_group )
+ {
+ IPPValue val;
+
+ int i,j, n;
+ int bi = 0; // Start with one for the group tag.
+ byte[] bytes = new byte[sz];
+
+ if (group_tag != last_group)
+ {
+ bytes[bi++] = (byte)group_tag;
+ last_group = group_tag;
+ }
+ bytes[bi++] = (byte)value_tag;
+
+ bytes[bi++] = (byte)((name.length() & 0xff00) >> 8);
+ bytes[bi++] = (byte)(name.length() & 0xff);
+ for (j=0; j < name.length(); j++)
+ bytes[bi++] = (byte)name.charAt(j);
+
+ for (i=0; i < values.size(); i++ )
+ {
+ if (i > 0)
+ {
+ bytes[bi++] = (byte)value_tag;
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)0;
+ }
+
+ val = (IPPValue)values.get(i);
+ switch (value_tag)
+ {
+ case IPPDefs.TAG_INTEGER :
+ case IPPDefs.TAG_ENUM :
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)4;
+ bytes[bi++] = (byte)((val.integer_value & 0xff000000) >> 24);
+ bytes[bi++] = (byte)((val.integer_value & 0xff0000) >> 16);
+ bytes[bi++] = (byte)((val.integer_value & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.integer_value & 0xff);
+ break;
+
+ case IPPDefs.TAG_BOOLEAN :
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)1;
+ if (val.boolean_value)
+ bytes[bi++] = (byte)1;
+ else
+ bytes[bi++] = (byte)0;
+ break;
+
+ case IPPDefs.TAG_TEXT :
+ case IPPDefs.TAG_NAME :
+ case IPPDefs.TAG_KEYWORD :
+ case IPPDefs.TAG_STRING :
+ case IPPDefs.TAG_URI :
+ case IPPDefs.TAG_URISCHEME :
+ case IPPDefs.TAG_CHARSET :
+ case IPPDefs.TAG_LANGUAGE :
+ case IPPDefs.TAG_MIMETYPE :
+ bytes[bi++] = (byte)((val.text.length() & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.text.length() & 0xff);
+ for (j=0; j < val.text.length(); j++)
+ {
+ bytes[bi++] = (byte)val.text.charAt(j);
+ }
+ break;
+
+ case IPPDefs.TAG_DATE:
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)11;
+ for (j=0; j < 11; j++)
+ bytes[bi++] = (byte)val.date_value[j];
+ break;
+
+ case IPPDefs.TAG_RESOLUTION :
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)9;
+ bytes[bi++] = (byte)((val.xres & 0xff000000) >> 24);
+ bytes[bi++] = (byte)((val.xres & 0xff0000) >> 16);
+ bytes[bi++] = (byte)((val.xres & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.xres & 0xff);
+ bytes[bi++] = (byte)((val.yres & 0xff000000) >> 24);
+ bytes[bi++] = (byte)((val.yres & 0xff0000) >> 16);
+ bytes[bi++] = (byte)((val.yres & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.yres & 0xff);
+ bytes[bi++] = (byte)val.units;
+ break;
+
+ case IPPDefs.TAG_RANGE :
+ bytes[bi++] = (byte)0;
+ bytes[bi++] = (byte)8;
+ bytes[bi++] = (byte)((val.lower & 0xff000000) >> 24);
+ bytes[bi++] = (byte)((val.lower & 0xff0000) >> 16);
+ bytes[bi++] = (byte)((val.lower & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.lower & 0xff);
+ bytes[bi++] = (byte)((val.upper & 0xff000000) >> 24);
+ bytes[bi++] = (byte)((val.upper & 0xff0000) >> 16);
+ bytes[bi++] = (byte)((val.upper & 0xff00) >> 8);
+ bytes[bi++] = (byte)(val.upper & 0xff);
+ break;
+
+ case IPPDefs.TAG_TEXTLANG :
+ case IPPDefs.TAG_NAMELANG :
+ n = val.charset.length() +
+ val.text.length() + 4;
+ bytes[bi++] = (byte)((n & 0xff00) >> 8);
+ bytes[bi++] = (byte)(n & 0xff);
+
+ n = val.charset.length();
+ bytes[bi++] = (byte)((n & 0xff00) >> 8);
+ bytes[bi++] = (byte)(n & 0xff);
+ for (j=0; j < val.charset.length(); j++)
+ bytes[bi++] = (byte)val.charset.charAt(j);
+
+ n = val.text.length();
+ bytes[bi++] = (byte)((n & 0xff00) >> 8);
+ bytes[bi++] = (byte)(n & 0xff);
+ for (j=0; j < (byte)val.text.length(); j++)
+ bytes[bi++] = (byte)val.text.charAt(j);
+
+ break;
+
+ default :
+ if (val.data != null)
+ {
+ n = val.data.length;
+ bytes[bi++] = (byte)((n & 0xff00) >> 8);
+ bytes[bi++] = (byte)(n & 0xff);
+ for (j=0; j < val.data.length; j++)
+ bytes[bi++] = (byte)val.data[j];
+ }
+ break;
+ }
+ }
+
+ return(bytes);
+
+ } // End of IPPAttribute.getBytes()
+
+
+
+
+ //
+ //
+ //
+ public void dump_values()
+ {
+ IPPValue val;
+
+ if ((values == null) || (values.size() < 1))
+ {
+ System.out.println( " ---- Separator ---- \n");
+ return;
+ }
+
+ for (int i=0; i < values.size(); i++ )
+ {
+ val = (IPPValue)values.get(i);
+
+ System.out.println("ATTR GTAG: " + group_tag );
+ System.out.println("ATTR VTAG: " + value_tag );
+ System.out.println("ATTR NAME: " + name );
+
+ // switch (value_tag & ~IPPDefs.TAG_COPY)
+ switch (value_tag)
+ {
+ case IPPDefs.TAG_INTEGER :
+ case IPPDefs.TAG_ENUM :
+ System.out.println( " INTEGER: " + val.integer_value );
+ break;
+
+ case IPPDefs.TAG_BOOLEAN :
+ System.out.println( " BOOLEAN: " + val.boolean_value );
+ break;
+
+ case IPPDefs.TAG_TEXT :
+ case IPPDefs.TAG_NAME :
+ case IPPDefs.TAG_KEYWORD :
+ case IPPDefs.TAG_STRING :
+ case IPPDefs.TAG_URI :
+ case IPPDefs.TAG_URISCHEME :
+ case IPPDefs.TAG_CHARSET :
+ case IPPDefs.TAG_LANGUAGE :
+ case IPPDefs.TAG_MIMETYPE :
+ System.out.println( " CHARSET: " + val.charset +
+ " TEXT: " + val.text );
+ break;
+
+ case IPPDefs.TAG_DATE :
+ System.out.println( " DATE: " + val.unix_time );
+ break;
+
+ case IPPDefs.TAG_RESOLUTION :
+ System.out.println( " UNITS: " + val.units +
+ " XRES: " + val.xres +
+ " YRES: " + val.yres );
+ break;
+
+ case IPPDefs.TAG_RANGE :
+ System.out.println( " LOWER: " + val.lower +
+ " UPPER: " + val.upper );
+ break;
+
+ case IPPDefs.TAG_TEXTLANG :
+ case IPPDefs.TAG_NAMELANG :
+ System.out.println( " CHARSET: " + val.charset +
+ " TEXT: " + val.text );
+ break;
+
+ case IPPDefs.TAG_ZERO:
+ System.out.println( " ---- Separator ---- \n");
+ break;
+
+ default :
+ break;
+ }
+ }
+ return;
+
+ }
+
+
+
+
+} // End of IPPAttribute class
+
+
+
+
diff --git a/scripting/java/src/org/cups/IPPBase64Encoder.java b/scripting/java/src/org/cups/IPPBase64Encoder.java
new file mode 100644
index 000000000..f1e5b33e8
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPBase64Encoder.java
@@ -0,0 +1,46 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * The <code>IPPBase64Encoder</code> overrides part of the sun encoder.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+
+class IPPBase64Encoder extends sun.misc.BASE64Encoder
+{
+ protected void encodeLineSuffix(java.io.OutputStream out)
+ throws java.io.IOException
+ {
+ // do nothing.
+ }
+}
+
diff --git a/scripting/java/src/org/cups/IPPCalendar.java b/scripting/java/src/org/cups/IPPCalendar.java
new file mode 100644
index 000000000..610c9d67c
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPCalendar.java
@@ -0,0 +1,62 @@
+package org.cups;
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPPCalendar</code> object is used for date/time conversion.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+import java.util.*;
+
+class IPPCalendar extends GregorianCalendar
+{
+ /**
+ * Get the time in milliseconds from the <code>GregorianCalendar</code>
+ * class.
+ *
+ * @return <code>long</code> Time in milliseconds of a date.
+ */
+ public long getTimeInMillis()
+ {
+ return(super.getTimeInMillis());
+ }
+
+ /**
+ * Get the unix time in seconds from the <code>GregorianCalendar</code>
+ * class.
+ *
+ * @return <code>int</code> Unix Time in seconds of a date.
+ */
+ public int getUnixTime()
+ {
+ return( (int)(getTimeInMillis() / 1000) );
+ }
+
+} // end of class
diff --git a/scripting/java/src/org/cups/IPPDefs.java b/scripting/java/src/org/cups/IPPDefs.java
new file mode 100644
index 000000000..027fd127a
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPDefs.java
@@ -0,0 +1,310 @@
+
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * <code>IPPDefs</code> is a collection of constants for use
+ * in the <code>IPP</code> and <code>CUPS</code> classes.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+public class IPPDefs
+{
+
+ /*
+ * IPP version string...
+ */
+ public static final byte VERSION[] = { 1, 0 };
+
+
+ /*
+ * IPP registered port number... This is the default value - applications
+ * should use the ippPort() function so that you can customize things in
+ * /etc/services if needed!
+ */
+ public static final int PORT = 631;
+
+
+ /*
+ * Common limits...
+ */
+ public static final int MAX_NAME = 256;
+ public static final int MAX_VALUES = 10; /* Now just an allocation
+ increment */
+
+
+ /*
+ * Format tags for attribute formats...
+ */
+ public static final int TAG_ZERO = 0x00;
+ public static final int TAG_OPERATION = 0x01;
+ public static final int TAG_JOB = 0x02;
+ public static final int TAG_END = 0x03;
+ public static final int TAG_PRINTER = 0x04;
+ public static final int TAG_UNSUPPORTED_GROUP = 0x05;
+ public static final int TAG_SUBSCRIPTION = 0x06;
+ public static final int TAG_EVENT_NOTIFICATION = 0x07;
+ public static final int TAG_UNSUPPORTED_VALUE = 0x10;
+ public static final int TAG_DEFAULT = 0x11;
+ public static final int TAG_UNKNOWN = 0x12;
+ public static final int TAG_NOVALUE = 0x13;
+ public static final int TAG_NOTSETTABLE = 0x15;
+ public static final int TAG_DELETEATTR = 0x16;
+ public static final int TAG_ADMINDEFINE = 0x17;
+ public static final int TAG_INTEGER = 0x21;
+ public static final int TAG_BOOLEAN = 0x22;
+ public static final int TAG_ENUM = 0x23;
+ public static final int TAG_STRING = 0x30;
+ public static final int TAG_DATE = 0x31;
+ public static final int TAG_RESOLUTION = 0x32;
+ public static final int TAG_RANGE = 0x33;
+ public static final int TAG_BEGIN_COLLECTION = 0x34;
+ public static final int TAG_TEXTLANG = 0x35;
+ public static final int TAG_NAMELANG = 0x36;
+ public static final int TAG_END_COLLECTION = 0x37;
+ public static final int TAG_TEXT = 0x41;
+ public static final int TAG_NAME = 0x42;
+ public static final int TAG_KEYWORD = 0x44;
+ public static final int TAG_URI = 0x45;
+ public static final int TAG_URISCHEME = 0x46;
+ public static final int TAG_CHARSET = 0x47;
+ public static final int TAG_LANGUAGE = 0x48;
+ public static final int TAG_MIMETYPE = 0x49;
+ public static final int TAG_MEMBERNAME = 0x4A;
+ public static final int TAG_MASK = 0x7FFFFFFF;
+ public static final int TAG_COPY = 0x80000001;
+
+
+ /*
+ * Resolution units...
+ */
+ public static final int RES_PER_INCH = 0x03;
+ public static final int RES_PER_CM = 0x04;
+
+
+ /*
+ * Finishings...
+ */
+ public static final int FINISHINGS_NONE = 0x03;
+ public static final int FINISHINGS_STAPLE = 0x04;
+ public static final int FINISHINGS_PUNCH = 0x05;
+ public static final int FINISHINGS_COVER = 0x06;
+ public static final int FINISHINGS_BIND = 0x07;
+ public static final int FINISHINGS_SADDLE_STITCH = 0x08;
+ public static final int FINISHINGS_EDGE_STITCH = 0x09;
+ public static final int FINISHINGS_FOLD = 0x0A;
+ public static final int FINISHINGS_TRIM = 0x0B;
+ public static final int FINISHINGS_BALE = 0x0C;
+ public static final int FINISHINGS_BOOKLET_MAKER = 0x0D;
+ public static final int FINISHINGS_JOB_OFFSET = 0x0E;
+ public static final int FINISHINGS_STAPLE_TOP_LEFT = 0x14;
+ public static final int FINISHINGS_STAPLE_BOTTOM_LEFT = 0x15;
+ public static final int FINISHINGS_STAPLE_TOP_RIGHT = 0x16;
+ public static final int FINISHINGS_STAPLE_BOTTOM_RIGHT = 0x17;
+ public static final int FINISHINGS_EDGE_STITCH_LEFT = 0x18;
+ public static final int FINISHINGS_EDGE_STITCH_TOP = 0x19;
+ public static final int FINISHINGS_EDGE_STITCH_RIGHT = 0x1A;
+ public static final int FINISHINGS_EDGE_STITCH_BOTTOM = 0x1B;
+ public static final int FINISHINGS_STAPLE_DUAL_LEFT = 0x1C;
+ public static final int FINISHINGS_STAPLE_DUAL_TOP = 0x1D;
+ public static final int FINISHINGS_STAPLE_DUAL_RIGHT = 0x1E;
+ public static final int FINISHINGS_STAPLE_DUAL_BOTTOM = 0x1F;
+ public static final int FINISHINGS_BIND_LEFT = 0x32;
+ public static final int FINISHINGS_BIND_TOP = 0x33;
+ public static final int FINISHINGS_BIND_RIGHT = 0x34;
+ public static final int FINISHINGS_BIND_BOTTOM = 0x35;
+
+
+ /*
+ * Orientation...
+ */
+ public static final int PORTRAIT = 0x03;
+ public static final int LANDSCAPE = 0x04;
+ public static final int REVERSE_LANDSCAPE = 0x05;
+ public static final int REVERSE_PORTRAIT = 0x06;
+
+
+ /*
+ * Qualities...
+ */
+ public static final int QUALITY_DRAFT = 0x03;
+ public static final int QUALITY_NORMAL = 0x04;
+ public static final int QUALITY_HIGH = 0x05;
+
+
+ /*
+ * Job States....
+ */
+ public static final int JOB_PENDING = 0x03;
+ public static final int JOB_HELD = 0x04;
+ public static final int JOB_PROCESSING = 0x05;
+ public static final int JOB_STOPPED = 0x06;
+ public static final int JOB_CANCELLED = 0x07;
+ public static final int JOB_ABORTED = 0x08;
+ public static final int JOB_COMPLETED = 0x09;
+
+
+ /*
+ * Printer States....
+ */
+ public static final int PRINTER_IDLE = 0x03;
+ public static final int PRINTER_PROCESSING = 0x04;
+ public static final int PRINTER_STOPPED = 0x05;
+
+
+ /*
+ * IPP states...
+ */
+ public static final int ERROR = 0xFFFFFFFF;
+ public static final int IDLE = 0x00;
+ public static final int HEADER = 0x01;
+ public static final int ATTRIBUTE = 0x02;
+ public static final int DATA = 0x03;
+
+
+ /*
+ * IPP operations...
+ */
+ public static final int PRINT_JOB = 0x02;
+ public static final int PRINT_URI = 0x03;
+ public static final int VALIDATE_JOB = 0x04;
+ public static final int CREATE_JOB = 0x05;
+ public static final int SEND_DOCUMENT = 0x06;
+ public static final int SEND_URI = 0x07;
+ public static final int CANCEL_JOB = 0x08;
+ public static final int GET_JOB_ATTRIBUTES = 0x09;
+ public static final int GET_JOBS = 0x0A;
+ public static final int GET_PRINTER_ATTRIBUTES = 0x0B;
+ public static final int HOLD_JOB = 0x0C;
+ public static final int RELEASE_JOB = 0x0D;
+ public static final int RESTART_JOB = 0x0E;
+ public static final int PAUSE_PRINTER = 0x10;
+ public static final int RESUME_PRINTER = 0x11;
+ public static final int PURGE_JOBS = 0x12;
+ public static final int SET_PRINTER_ATTRIBUTES = 0x13;
+ public static final int SET_JOB_ATTRIBUTES = 0x14;
+ public static final int GET_PRINTER_SUPPORTED_VALUES = 0x15;
+ public static final int CREATE_PRINTER_SUBSCRIPTION = 0x16;
+ public static final int CREATE_JOB_SUBSCRIPTION = 0x17;
+ public static final int GET_SUBSCRIPTION_ATTRIBUTES = 0x18;
+ public static final int GET_SUBSCRIPTIONS = 0x19;
+ public static final int RENEW_SUBSCRIPTION = 0x1A;
+ public static final int CANCEL_SUBSCRIPTION = 0x1B;
+ public static final int GET_NOTIFICATIONS = 0x1C;
+ public static final int SEND_NOTIFICATIONS = 0x1D;
+ public static final int GET_PRINT_SUPPORT_FILES = 0x21;
+ public static final int ENABLE_PRINTER = 0x22;
+ public static final int DISABLE_PRINTER = 0x23;
+ public static final int PAUSE_PRINTER_AFTER_CURRENT_JOB = 0x24;
+ public static final int HOLD_NEW_JOBS = 0x25;
+ public static final int RELEASE_HELD_NEW_JOBS = 0x26;
+ public static final int DEACTIVATE_PRINTER = 0x27;
+ public static final int ACTIVATE_PRINTER = 0x28;
+ public static final int RESTART_PRINTER = 0x29;
+ public static final int SHUTDOWN_PRINTER = 0x2A;
+ public static final int STARTUP_PRINTER = 0x2B;
+ public static final int REPROCESS_JOB = 0x2C;
+ public static final int CANCEL_CURRENT_JOB = 0x2D;
+ public static final int SUSPEND_CURRENT_JOB = 0x2E;
+ public static final int RESUME_JOB = 0x2F;
+ public static final int PROMOTE_JOB = 0x30;
+ public static final int SCHEDULE_JOB_AFTER = 0x31;
+ public static final int PRIVATE = 0x4000;
+ public static final int CUPS_GET_DEFAULT = 0x4001;
+ public static final int CUPS_GET_PRINTERS = 0x4002;
+ public static final int CUPS_ADD_PRINTER = 0x4003;
+ public static final int CUPS_DELETE_PRINTER = 0x4004;
+ public static final int CUPS_GET_CLASSES = 0x4005;
+ public static final int CUPS_ADD_CLASS = 0x4006;
+ public static final int CUPS_DELETE_CLASS = 0x4007;
+ public static final int CUPS_ACCEPT_JOBS = 0x4008;
+ public static final int CUPS_REJECT_JOBS = 0x4009;
+ public static final int CUPS_SET_DEFAULT = 0x400A;
+ public static final int CUPS_GET_DEVICES = 0x400B;
+ public static final int CUPS_GET_PPDS = 0x400C;
+ public static final int CUPS_MOVE_JOB = 0x400D;
+ public static final int CUPS_ADD_DEVICE = 0x400E;
+ public static final int CUPS_DELETE_DEVICE = 0x400F;
+
+
+
+ /*
+ * IPP status codes...
+ */
+ public static final int OK = 0x00;
+ public static final int OK_SUBST = 0x01;
+ public static final int OK_CONFLICT = 0x02;
+ public static final int OK_IGNORED_SUBSCRIPTIONS = 0x03;
+ public static final int OK_IGNORED_NOTIFICATIONS = 0x04;
+ public static final int OK_TOO_MANY_EVENTS = 0x05;
+ public static final int OK_BUT_CANCEL_SUBSCRIPTION = 0x06;
+ public static final int REDIRECTION_OTHER_SITE = 0x300;
+ public static final int BAD_REQUEST = 0x400;
+ public static final int FORBIDDEN = 0x401;
+ public static final int NOT_AUTHENTICATED = 0x402;
+ public static final int NOT_AUTHORIZED = 0x403;
+ public static final int NOT_POSSIBLE = 0x404;
+ public static final int TIMEOUT = 0x405;
+ public static final int NOT_FOUND = 0x406;
+ public static final int GONE = 0x407;
+ public static final int REQUEST_ENTITY = 0x408;
+ public static final int REQUEST_VALUE = 0x409;
+ public static final int DOCUMENT_FORMAT = 0x40A;
+ public static final int ATTRIBUTES = 0x40B;
+ public static final int URI_SCHEME = 0x40C;
+ public static final int CHARSET = 0x40D;
+ public static final int CONFLICT = 0x40E;
+ public static final int COMPRESSION_NOT_SUPPORTED = 0x40F;
+ public static final int COMPRESSION_ERROR = 0x410;
+ public static final int DOCUMENT_FORMAT_ERROR = 0x411;
+ public static final int DOCUMENT_ACCESS_ERROR = 0x412;
+ public static final int ATTRIBUTES_NOT_SETTABLE = 0x413;
+ public static final int IGNORED_ALL_SUBSCRIPTIONS = 0x414;
+ public static final int TOO_MANY_SUBSCRIPTIONS = 0x415;
+ public static final int IGNORED_ALL_NOTIFICATIONS = 0x416;
+ public static final int PRINT_SUPPORT_FILE_NOT_FOUND = 0x417;
+ public static final int INTERNAL_ERROR = 0x500;
+ public static final int OPERATION_NOT_SUPPORTED = 0x501;
+ public static final int SERVICE_UNAVAILABLE = 0x502;
+ public static final int VERSION_NOT_SUPPORTED = 0x503;
+ public static final int DEVICE_ERROR = 0x504;
+ public static final int TEMPORARY_ERROR = 0x505;
+ public static final int NOT_ACCEPTING = 0x506;
+ public static final int PRINTER_BUSY = 0x507;
+ public static final int ERROR_JOB_CANCELLED = 0x508;
+ public static final int MULTIPLE_JOBS_NOT_SUPPORTED = 0x509;
+ public static final int PRINTER_IS_DEACTIVATED = 0x50A;
+
+}
+
+
diff --git a/scripting/java/src/org/cups/IPPError.java b/scripting/java/src/org/cups/IPPError.java
new file mode 100644
index 000000000..46be6ef0c
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPError.java
@@ -0,0 +1,159 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPPError</code> object is used for error conversion.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+import java.util.*;
+import java.io.*;
+
+
+public class IPPError
+{
+ private int error_number;
+ private String error_string;
+
+
+ /**
+ * Constructor that sets <code>error_string</code> after creation.
+ *
+ * @param <code>error_number</code> Error number to convert.
+ * @see <code>IPPDefs</code>
+ */
+ public IPPError(int p_error)
+ {
+ error_number = p_error;
+ error_string = ippErrorString( error_number );
+ }
+
+
+ /**
+ * Get the string associated with an error number.
+ *
+ * @param <code>error</code> Error number to convert.
+ * @see <code>IPPDefs</code>
+ */
+ private String ippErrorString( int error )
+ {
+ String unknown;
+ String status_oks[] = // "OK" status codes
+ {
+ "successful-ok",
+ "successful-ok-ignored-or-substituted-attributes",
+ "successful-ok-conflicting-attributes",
+ "successful-ok-ignored-subscriptions",
+ "successful-ok-ignored-notifications",
+ "successful-ok-too-many-events",
+ "successful-ok-but-cancel-subscription"
+ };
+
+ String status_400s[] = // Client errors
+ {
+ "client-error-bad-request",
+ "client-error-forbidden",
+ "client-error-not-authenticated",
+ "client-error-not-authorized",
+ "client-error-not-possible",
+ "client-error-timeout",
+ "client-error-not-found",
+ "client-error-gone",
+ "client-error-request-entity-too-large",
+ "client-error-request-value-too-long",
+ "client-error-document-format-not-supported",
+ "client-error-attributes-or-values-not-supported",
+ "client-error-uri-scheme-not-supported",
+ "client-error-charset-not-supported",
+ "client-error-conflicting-attributes",
+ "client-error-compression-not-supported",
+ "client-error-compression-error",
+ "client-error-document-format-error",
+ "client-error-document-access-error",
+ "client-error-attributes-not-settable",
+ "client-error-ignored-all-subscriptions",
+ "client-error-too-many-subscriptions",
+ "client-error-ignored-all-notifications",
+ "client-error-print-support-file-not-found"
+ };
+
+ String status_500s[] = // Server errors
+ {
+ "server-error-internal-error",
+ "server-error-operation-not-supported",
+ "server-error-service-unavailable",
+ "server-error-version-not-supported",
+ "server-error-device-error",
+ "server-error-temporary-error",
+ "server-error-not-accepting-jobs",
+ "server-error-busy",
+ "server-error-job-canceled",
+ "server-error-multiple-document-jobs-not-supported",
+ "server-error-printer-is-deactivated"
+ };
+
+
+ //
+ // See if the error code is a known value...
+ //
+ if ((error >= IPPDefs.OK) && (error <= IPPDefs.OK_BUT_CANCEL_SUBSCRIPTION))
+ {
+ return (status_oks[error]);
+ }
+ else if (error == IPPDefs.REDIRECTION_OTHER_SITE)
+ {
+ return ("redirection-other-site");
+ }
+ else if ((error >= IPPDefs.BAD_REQUEST) &&
+ (error <= IPPDefs.PRINT_SUPPORT_FILE_NOT_FOUND))
+ {
+ return (status_400s[error - IPPDefs.BAD_REQUEST]);
+ }
+ else if ((error >= IPPDefs.INTERNAL_ERROR) &&
+ (error <= IPPDefs.PRINTER_IS_DEACTIVATED))
+ {
+ return (status_500s[error - IPPDefs.INTERNAL_ERROR]);
+ }
+
+ //
+ // No, build an "unknown-xxxx" error string...
+ //
+
+ unknown = "unknown" + error;
+
+ return (unknown);
+ }
+
+
+} // End of IPPError class
+
+
+
diff --git a/scripting/java/src/org/cups/IPPHttp.java b/scripting/java/src/org/cups/IPPHttp.java
new file mode 100644
index 000000000..378052174
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPHttp.java
@@ -0,0 +1,1353 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPPHttp</code> object is used for reading/writing to the cups
+ * server, and processing responses.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+import java.io.*;
+import java.util.*;
+import java.net.*;
+import java.security.*;
+
+public class IPPHttp
+{
+
+ /**
+ * Class constants - most not in use yet.
+ */
+ public static final int HTTP_WAITING = 0x00;
+ public static final int HTTP_OPTIONS = 0x01;
+ public static final int HTTP_GET = 0x02;
+ public static final int HTTP_GET_SEND = 0x03;
+ public static final int HTTP_HEAD = 0x04;
+ public static final int HTTP_POST = 0x05;
+ public static final int HTTP_POST_RECV = 0x06;
+ public static final int HTTP_POST_SEND = 0x07;
+ public static final int HTTP_PUT = 0x08;
+ public static final int HTTP_PUT_RECV = 0x09;
+ public static final int HTTP_DELETE = 0x0A;
+ public static final int HTTP_TRACE = 0x0B;
+ public static final int HTTP_CLOSE = 0x0C;
+ public static final int HTTP_STATUS = 0x0D;
+
+ public static final int HTTP_0_9 = 0x09;
+ public static final int HTTP_1_0 = 0x64;
+ public static final int HTTP_1_1 = 0x65;
+
+ public static final int HTTP_KEEPALIVE_OFF = 0x00;
+ public static final int HTTP_KEEPALIVE_ON = 0x01;
+
+ public static final int HTTP_ENCODE_LENGTH = 0x00;
+ public static final int HTTP_ENCODE_CHUNKED = 0x01;
+
+ public static final int HTTP_ENCRYPT_IF_REQUESTED = 0x00;
+ public static final int HTTP_ENCRYPT_NEVER = 0x01;
+ public static final int HTTP_ENCRYPT_REQUIRED = 0x02;
+ public static final int HTTP_ENCRYPT_ALWAYS = 0x03;
+
+ public static final int HTTP_AUTH_NONE = 0x00;
+ public static final int HTTP_AUTH_BASIC = 0x01;
+ public static final int HTTP_AUTH_MD5 = 0x02;
+ public static final int HTTP_AUTH_MD5_SESS = 0x03;
+ public static final int HTTP_AUTH_MD5_INT = 0x04;
+ public static final int HTTP_AUTH_MD5_SESS_INT = 0x05;
+
+ public static final int HTTP_ERROR = 0xFFFFFFFF;
+ public static final int HTTP_CONTINUE = 0x64;
+ public static final int HTTP_SWITCHING_PROTOCOLS = 0x65;
+ public static final int HTTP_OK = 0xC8;
+ public static final int HTTP_CREATED = 0xC9;
+ public static final int HTTP_ACCEPTED = 0xCA;
+ public static final int HTTP_NOT_AUTHORITATIVE = 0xCB;
+ public static final int HTTP_NO_CONTENT = 0xCC;
+ public static final int HTTP_RESET_CONTENT = 0xCD;
+ public static final int HTTP_PARTIAL_CONTENT = 0xCE;
+ public static final int HTTP_MULTIPLE_CHOICES = 0x12C;
+ public static final int HTTP_MOVED_PERMANENTLY = 0x12D;
+ public static final int HTTP_MOVED_TEMPORARILY = 0x12E;
+ public static final int HTTP_SEE_OTHER = 0x12F;
+ public static final int HTTP_NOT_MODIFIED = 0x130;
+ public static final int HTTP_USE_PROXY = 0x131;
+ public static final int HTTP_BAD_REQUEST = 0x190;
+ public static final int HTTP_UNAUTHORIZED = 0x191;
+ public static final int HTTP_PAYMENT_REQUIRED = 0x192;
+ public static final int HTTP_FORBIDDEN = 0x193;
+ public static final int HTTP_NOT_FOUND = 0x194;
+ public static final int HTTP_METHOD_NOT_ALLOWED = 0x195;
+ public static final int HTTP_NOT_ACCEPTABLE = 0x196;
+ public static final int HTTP_PROXY_AUTHENTICATION = 0x197;
+ public static final int HTTP_REQUEST_TIMEOUT = 0x198;
+ public static final int HTTP_CONFLICT = 0x199;
+ public static final int HTTP_GONE = 0x19A;
+ public static final int HTTP_LENGTH_REQUIRED = 0x19B;
+ public static final int HTTP_PRECONDITION = 0x19C;
+ public static final int HTTP_REQUEST_TOO_LARGE = 0x19D;
+ public static final int HTTP_URI_TOO_LONG = 0x19E;
+ public static final int HTTP_UNSUPPORTED_MEDIATYPE = 0x19F;
+ public static final int HTTP_UPGRADE_REQUIRED = 0x1AA;
+ public static final int HTTP_SERVER_ERROR = 0x1F4;
+ public static final int HTTP_NOT_IMPLEMENTED = 0x1F5;
+ public static final int HTTP_BAD_GATEWAY = 0x1F6;
+ public static final int HTTP_SERVICE_UNAVAILABLE = 0x1F7;
+ public static final int HTTP_GATEWAY_TIMEOUT = 0x1F8;
+
+ public static final int HTTP_NOT_SUPPORTED = 0x1F9;
+
+ public static final int HTTP_FIELD_UNKNOWN = 0xFFFFFFFF;
+ public static final int HTTP_FIELD_ACCEPT_LANGUAGE = 0x00;
+ public static final int HTTP_FIELD_ACCEPT_RANGES = 0x01;
+ public static final int HTTP_FIELD_AUTHORIZATION = 0x02;
+ public static final int HTTP_FIELD_CONNECTION = 0x03;
+ public static final int HTTP_FIELD_CONTENT_ENCODING = 0x04;
+ public static final int HTTP_FIELD_CONTENT_LANGUAGE = 0x05;
+ public static final int HTTP_FIELD_CONTENT_LENGTH = 0x06;
+ public static final int HTTP_FIELD_CONTENT_LOCATION = 0x07;
+ public static final int HTTP_FIELD_CONTENT_MD5 = 0x08;
+ public static final int HTTP_FIELD_CONTENT_RANGE = 0x09;
+ public static final int HTTP_FIELD_CONTENT_TYPE = 0x0A;
+ public static final int HTTP_FIELD_CONTENT_VERSION = 0x0B;
+ public static final int HTTP_FIELD_DATE = 0x0C;
+ public static final int HTTP_FIELD_HOST = 0x0D;
+ public static final int HTTP_FIELD_IF_MODIFIED_SINCE = 0x0E;
+ public static final int HTTP_FIELD_IF_UNMODIFIED_SINCE = 0x0F;
+ public static final int HTTP_FIELD_KEEP_ALIVE = 0x10;
+ public static final int HTTP_FIELD_LAST_MODIFIED = 0x11;
+ public static final int HTTP_FIELD_LINK = 0x12;
+ public static final int HTTP_FIELD_LOCATION = 0x13;
+ public static final int HTTP_FIELD_RANGE = 0x14;
+ public static final int HTTP_FIELD_REFERER = 0x15;
+ public static final int HTTP_FIELD_RETRY_AFTER = 0x16;
+ public static final int HTTP_FIELD_TRANSFER_ENCODING = 0x17;
+ public static final int HTTP_FIELD_UPGRADE = 0x18;
+ public static final int HTTP_FIELD_USER_AGENT = 0x19;
+ public static final int HTTP_FIELD_WWW_AUTHENTICATE = 0x1A;
+ public static final int HTTP_FIELD_MAX = 0x1B;
+
+ public static final String http_fields[] =
+ {
+ "Accept-Language",
+ "Accept-Ranges",
+ "Authorization",
+ "Connection",
+ "Content-Encoding",
+ "Content-Language",
+ "Content-Length",
+ "Content-Location",
+ "Content-MD5",
+ "Content-Range",
+ "Content-Type",
+ "Content-Version",
+ "Date",
+ "Host",
+ "If-Modified-Since",
+ "If-Unmodified-since",
+ "Keep-Alive",
+ "Last-Modified",
+ "Link",
+ "Location",
+ "Range",
+ "Referer",
+ "Retry-After",
+ "Transfer-Encoding",
+ "Upgrade",
+ "User-Agent",
+ "WWW-Authenticate"
+ };
+ public static final String days[] =
+ {
+ "Sun",
+ "Mon",
+ "Tue",
+ "Wed",
+ "Thu",
+ "Fri",
+ "Sat"
+ };
+ public static final String months[] =
+ {
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec"
+ };
+
+
+
+ //
+ // Private class members.
+ //
+ private URL url; // URL of connection.
+
+ public Socket conn; // Connection socket.
+ public boolean connected; // True when connected.
+
+ public BufferedInputStream is; // Input stream.
+ public BufferedReader br;
+ public BufferedOutputStream os; // Output stream.
+
+ private boolean encrypted;
+
+ public int write_content_length;
+ private char write_buffer[];
+ private int write_buffer_head;
+ private int write_buffer_tail;
+
+ public String read_header_date;
+ public String read_header_server;
+ public String read_header_charset;
+ public String read_header_content_language;
+ public String read_header_content_type;
+ public int read_header_content_length;
+
+ public char read_buffer[];
+ private int read_buffer_head;
+ private int read_buffer_tail;
+
+ public int status;
+ public String status_text;
+ public String version;
+ public int error;
+ public int activity;
+
+ public String hostname; // Hostname from URL
+ public int port; // Port from URL.
+ public String path; // Path from URL.
+ public String user; // User name
+ public String passwd; // Password
+
+ public String auth_type; // none, basic, digest
+ public String realm; // For digest auth
+ public String opaque; // For digest auth
+ public String nonce; // For digest auth
+ public String resource; // For digest auth
+ public String method; // For digest auth
+
+ public String http_request;
+ public int http_content_length;
+
+
+
+ /**
+ * Constructor using <code>URL</code>.
+ *
+ * @param request_url <code>URL</code> of server to connect to.
+ * @throw IOException
+ * @throw UnknownHostException
+ */
+ public IPPHttp( String request_url )
+ throws IOException, UnknownHostException
+ {
+
+ encrypted = false;
+ status = 0;
+ status_text = "";
+ version = "1.0";
+ connected = false;
+ user = "";
+ passwd = "";
+
+ auth_type = "";
+ realm = "";
+ nonce = "";
+ resource = "";
+ method = "";
+
+ try
+ {
+ //
+ // Create the URL and split it up.
+ //
+ url = new URL(request_url);
+ hostname = url.getHost();
+ port = url.getPort();
+ path = url.getPath();
+
+
+ //
+ // Open the socket and set the options.
+ //
+ conn = new Socket(hostname, port);
+ conn.setSoTimeout(200);
+
+ //
+ // Create the input and output streams.
+ //
+ is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
+ os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
+ connected = true;
+ }
+ catch(UnknownHostException unknownhostexception)
+ {
+ throw unknownhostexception;
+ }
+ catch(IOException ioexception)
+ {
+ throw ioexception;
+ }
+ }
+
+
+
+ /**
+ * Constructor using <code>URL, user and pass</code>.
+ *
+ * @param request_url <code>URL</code> of server to connect to.
+ * @param p_auth_type <code>String</code> basic or digest.
+ * @param p_user <code>String</code> User name.
+ * @param p_passwd <code>String</code> password.
+ * @throw IOException
+ * @throw UnknownHostException
+ */
+ public IPPHttp( String request_url, String p_auth_type,
+ String p_user, String p_passwd )
+ throws IOException, UnknownHostException
+ {
+ encrypted = false;
+ status = 0;
+ status_text = "";
+ version = "1.0";
+ connected = false;
+
+ user = p_user;
+ passwd = p_passwd;
+ auth_type = p_auth_type;
+
+ realm = "";
+ nonce = "";
+ resource = "";
+ method = "";
+
+ try
+ {
+ //
+ // Create the URL and split it up.
+ //
+ url = new URL(request_url);
+ hostname = url.getHost();
+ port = url.getPort();
+ path = url.getPath();
+
+ //
+ // Open the socket and set the options.
+ //
+ conn = new Socket(hostname, port);
+ conn.setSoTimeout(200);
+
+ //
+ // Create the input and output streams.
+ //
+ is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
+ os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
+ connected = true;
+ }
+ catch(UnknownHostException unknownhostexception)
+ {
+ throw unknownhostexception;
+ }
+ catch(IOException ioexception)
+ {
+ throw ioexception;
+ }
+ }
+
+
+
+
+ /**
+ * Re-establish a dropped connection.
+ *
+ * @return <code>boolean</code> True if connected.
+ *
+ * @throw IOException
+ */
+ public boolean reConnect() throws IOException
+ {
+ connected = false;
+ status = 0;
+ status_text = "";
+ try
+ {
+ //
+ // Open the socket and set the options.
+ //
+ conn = new Socket(hostname, port);
+ conn.setSoTimeout(200);
+
+ //
+ // Create the input and output streams.
+ //
+ is = new BufferedInputStream(new DataInputStream(conn.getInputStream()));
+ os = new BufferedOutputStream(new DataOutputStream(conn.getOutputStream()));
+ connected = true;
+ return(connected);
+
+ }
+ catch (IOException ioexception)
+ {
+ connected = false;
+ throw(ioexception);
+ }
+ }
+
+
+
+ /**
+ * Set the user name.
+ *
+ * @param p_user <code>String</code> - user name.
+ */
+ public void setUser(String p_user )
+ {
+ user = p_user;
+ }
+
+
+ /**
+ * Set the password.
+ *
+ * @param p_passwd <code>String</code> - password.
+ */
+ public void setPassword(String p_passwd )
+ {
+ passwd = p_passwd;
+ }
+
+
+
+
+ /**
+ * Write the request header bytes to the server.
+ *
+ * @param request <code>String</code> - the request.
+ * @param content_length <code>int</code> - size of the total request.
+ * @throw IOException
+ */
+ public int writeHeader(String request, int content_length )
+ throws IOException
+ {
+
+ http_request = request;
+ http_content_length = content_length;
+
+ try
+ {
+ String s1 = "POST " + request + " HTTP/1.0\r\n";
+ os.write(s1.getBytes(), 0, s1.length());
+
+ s1 = "Content-type: application/ipp\r\n";
+ os.write(s1.getBytes(), 0, s1.length());
+
+
+ //
+ // Do basic style authorization if needed.
+ //
+ if (auth_type.compareTo("basic") == 0)
+ {
+ s1 = user + ":" + passwd;
+ IPPBase64Encoder encoder = new IPPBase64Encoder();
+ String auth_string = encoder.encode(s1.getBytes());
+ s1 = "Authorization: Basic " + auth_string + "\r\n";
+ os.write(s1.getBytes(), 0, s1.length());
+ }
+ else if (auth_type.compareTo("digest") == 0)
+ {
+ try
+ {
+ IPPMD5 md5 = IPPMD5.getInstance();
+ String auth_string = md5.MD5Digest(user, passwd, realm,
+ "POST", path, nonce );
+ s1 = "Authorization: Digest " + "username=\"" + user + "\", " +
+ "realm=\"" + realm + "\", " +
+ "nonce=\"" + nonce + "\", " +
+ "response=\"" + auth_string + "\"\r\n";
+
+ os.write(s1.getBytes(), 0, s1.length());
+ }
+ catch(NoSuchAlgorithmException e)
+ {
+ System.out.println("No such algorithm: MD5.");
+ }
+ }
+
+ s1 = "Content-length: " + content_length + "\r\n\r\n";
+ os.write(s1.getBytes(), 0, s1.length());
+ os.flush();
+ }
+ catch(IOException ioexception)
+ {
+ error = HTTP_ERROR;
+ throw ioexception;
+ }
+
+
+ try
+ {
+ int local_status = 0;
+
+ //
+ // Check for any response.
+ //
+ if (is.available() > 0)
+ {
+ StringBuffer http_version = new StringBuffer(32);
+ StringBuffer http_status = new StringBuffer(32);
+ StringBuffer http_text = new StringBuffer(256);
+
+ String read_buffer;
+ status = 0;
+ is.mark(8192);
+ while (is.available() > 0)
+ {
+ read_buffer = read_line();
+
+ if (read_buffer.startsWith("HTTP/"))
+ {
+ int i,n;
+ String s2 = read_buffer.substring(5);
+
+
+ for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
+ {
+ http_version.append(s2.charAt(i));
+ }
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (;(i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_status.append(s2.charAt(i));
+ }
+
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_text.append(s2.charAt(i));
+ }
+ local_status = Integer.parseInt(http_status.toString(), 10);
+ }
+ }
+ is.reset();
+ }
+
+ //
+ // See if we need to reconnect and send authorization.
+ //
+ switch( local_status )
+ {
+ //
+ // Not authorized.
+ //
+ case HTTP_UNAUTHORIZED: read_header();
+ return( local_status );
+ }
+ }
+ catch(IOException ioexception)
+ {
+ error = HTTP_ERROR;
+ throw ioexception;
+ }
+ return(0);
+ }
+
+
+
+
+
+
+ public int checkForResponse()
+ {
+ //
+ // Check for any response.
+ //
+ try
+ {
+ if (is.available() > 0)
+ {
+ StringBuffer http_version = new StringBuffer(32);
+ StringBuffer http_status = new StringBuffer(32);
+ StringBuffer http_text = new StringBuffer(256);
+ int local_status = 0;
+ String read_buffer;
+
+ status = 0;
+ is.mark(8192);
+ while (is.available() > 0)
+ {
+ read_buffer = read_line();
+ if (read_buffer.startsWith("HTTP/"))
+ {
+ int i,n;
+ String s2 = read_buffer.substring(5);
+ for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
+ {
+ http_version.append(s2.charAt(i));
+ }
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (;(i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_status.append(s2.charAt(i));
+ }
+
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_text.append(s2.charAt(i));
+ }
+ local_status = Integer.parseInt(http_status.toString(), 10);
+ status = local_status;
+ }
+ }
+ is.reset();
+
+ //
+ // See if we need to reconnect and send authorization.
+ //
+ switch( local_status )
+ {
+ //
+ // Not authorized.
+ //
+ case HTTP_UNAUTHORIZED: read_header();
+ return( local_status );
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ return(HTTP_ERROR);
+ }
+ return(0);
+ }
+
+
+ /**
+ * Write bytes to the output stream.
+ *
+ * @param bytes Array of bytes to write to the stream.
+ * @throw IOException
+ */
+ public void write(byte bytes[])
+ throws IOException
+ {
+ try
+ {
+ os.write(bytes, 0, bytes.length);
+ os.flush();
+ }
+ catch(IOException ioexception)
+ {
+ error = HTTP_ERROR;
+ throw ioexception;
+ }
+ }
+
+
+ /**
+ * Write bytes to the output stream.
+ *
+ * @param bytes Array of bytes to write to the stream.
+ * @param length Number of bytes to write to the stream.
+ * @throw IOException
+ */
+ public void write(byte bytes[], int length )
+ throws IOException
+ {
+ try
+ {
+ os.write(bytes, 0, length);
+ os.flush();
+ }
+ catch(IOException ioexception)
+ {
+ error = HTTP_ERROR;
+ throw ioexception;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ /**
+ * Read the HTTP header from the input stream.
+ *
+ * @return <code>int</code> Content length of response.
+ * @return 0 Return zero on error.
+ * @throw IOException
+ */
+ public int read_header()
+ throws IOException
+ {
+ boolean done = false;
+ read_header_content_length = 0;
+
+ String read_buffer;
+ while (!done)
+ {
+ read_buffer = read_line();
+ if (read_buffer.startsWith("HTTP/"))
+ {
+ int i,n;
+ String s2 = read_buffer.substring(5);
+
+ StringBuffer http_version = new StringBuffer(32);
+ StringBuffer http_status = new StringBuffer(32);
+ StringBuffer http_text = new StringBuffer(256);
+
+ for (i=0;(i < s2.length() && s2.charAt(i) != ' '); i++)
+ {
+ http_version.append(s2.charAt(i));
+ }
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (;(i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_status.append(s2.charAt(i));
+ }
+
+ while (i < s2.length() && s2.charAt(i) == ' ')
+ i++;
+ for (n=0;(n < 256 && i < s2.length() && s2.charAt(i) != '\n' &&
+ s2.charAt(i) != '\r' && s2.charAt(i) != ' '); i++)
+ {
+ http_text.append(s2.charAt(i));
+ }
+ version = http_version.toString();
+ status = Integer.parseInt(http_status.toString(), 10);
+ status_text = http_text.toString();
+ }
+ else if (read_buffer.startsWith("WWW-Authenticate: Basic"))
+ {
+ String s2=read_buffer.substring("WWW-Authenticate: Basic".length());
+ auth_type = "basic";
+ }
+ else if (read_buffer.startsWith("WWW-Authenticate: Digest"))
+ {
+ String s2=read_buffer.substring("WWW-Authenticate: Digest".length());
+ auth_type = "digest";
+ parseAuthenticate(s2);
+ }
+ else if (read_buffer.startsWith("Content-Length:"))
+ {
+ String s2 = read_buffer.substring(15);
+ read_header_content_length = Integer.parseInt(s2.trim(), 10);
+ }
+ else if (read_buffer.startsWith("Content-Language:"))
+ {
+ String s3 = read_buffer.substring(17);
+ read_header_content_language = s3.trim();
+ }
+ else if (read_buffer.startsWith("Server:"))
+ {
+ String s4 = read_buffer.substring(7);
+ read_header_server = s4.trim();
+ }
+ else if (read_buffer.startsWith("Date:"))
+ {
+ String s5 = read_buffer.substring(5);
+ read_header_date = s5.trim();
+ }
+ else if (read_buffer.length() == 0)
+ {
+ done = true;
+ return( read_header_content_length );
+ }
+ }
+ return( 0 );
+ }
+
+
+
+ /**
+ * Read a line from the input stream.
+ *
+ * @return <code>String</code> Line read.
+ * @throw <code>IOException</code>
+ */
+ public String read_line()
+ throws IOException
+ {
+ StringBuffer sb = new StringBuffer();
+ int c = 0;
+
+ try
+ {
+ while ((c != -1) && (c != 10))
+ {
+ c = is.read();
+ switch( c )
+ {
+ case -1:
+ case 10:
+ case 13:
+ break;
+
+ default: sb.append((char)c);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ throw(e);
+ }
+ return(sb.toString());
+ }
+
+
+
+
+
+ /**
+ * Read up to <code>count</code> bytes from the input stream.
+ *
+ * @param <code>count</code> Number of bytes to read.
+ * @return <code>char[]</code> Character array of data read.
+ * @throw <code>IOException</code>
+ */
+ public char[] read(int count)
+ throws IOException
+ {
+ char ac[] = new char[count];
+ int j = 0;
+ try
+ {
+ for (int k = is.read(); k != -1 && j < count; k = is.read())
+ {
+ ac[j++] = (char)k;
+ }
+ }
+ catch(IOException ioexception)
+ {
+ throw ioexception;
+ }
+ return(ac);
+ }
+
+
+ /**
+ * Process the HTTP response from the server.
+ *
+ * @return <code>IPP</code> IPP object containing response data.
+ * @see <code>IPP</code>
+ * @see <code>IPPRequest</code>
+ * @see <code>IPPAttribute</code>
+ * @see <code>IPPValue</code>
+ * @see <code>IPPDefs</code>
+ */
+ public IPP processResponse()
+ {
+ IPP ipp;
+ IPPAttribute attr; // temp attribute
+ IPPValue val; // temp value
+
+ short vtag; // Current value tag
+ short gtag; // Current group tag
+
+ char[] buffer;
+
+ ipp = new IPP();
+ ipp.request = new IPPRequest();
+
+ int read_buffer_bytes = read_buffer.length;
+ int read_buffer_remaining = read_buffer_bytes;
+ int bufferidx = 0;
+ int n;
+
+
+ ipp.current = -1; // current attritue??
+ ipp.last = -1; // last attr?
+ attr = null;
+ buffer = read_buffer;
+ gtag = -1;
+ vtag = -1;
+
+
+ // ---------------------------------------------------------------
+ // State machine to process response.
+ //
+ ipp.state = IPPDefs.IDLE;
+ while ((ipp.state != IPPDefs.TAG_END) &&
+ (read_buffer_remaining > 0))
+ {
+ switch (ipp.state)
+ {
+ case IPPDefs.IDLE :
+ ipp.state++; /* Avoid common problem... */
+
+ //
+ // Get the request header...
+ //
+ case IPPDefs.HEADER :
+ if (read_buffer_remaining < 8)
+ {
+ return (null);
+ }
+
+ //
+ // Verify the major version number...
+ //
+ if (buffer[0] != (char)1)
+ {
+ return (null);
+ }
+
+ //
+ // Then copy the request header over...
+ //
+ ipp.request.version[0] = buffer[bufferidx++];
+ ipp.request.version[1] = buffer[bufferidx++];
+ ipp.request.op_status = (short)((short)buffer[bufferidx] << 8) |
+ (short)buffer[bufferidx+1];
+ bufferidx += 2;
+
+ //
+ // Get the text version of the request status ....
+ //
+ ipp.status = new IPPStatus(ipp.request.op_status);
+
+ ipp.request.request_id = (int)((int)buffer[bufferidx] << 24) |
+ ((int)buffer[bufferidx+1] << 16) |
+ ((int)buffer[bufferidx+2] << 8) |
+ ((int)buffer[bufferidx+3]);
+ bufferidx += 4;
+ read_buffer_remaining -= 8;
+
+ ipp.state = IPPDefs.ATTRIBUTE;
+ ipp.current = -1;
+ ipp.current_tag = IPPDefs.TAG_ZERO;
+ break;
+
+ case IPPDefs.ATTRIBUTE :
+ while (read_buffer_remaining > 0)
+ {
+ //
+ // Read the value tag first.
+ //
+ vtag = (short)buffer[bufferidx++];
+ read_buffer_remaining--;
+ if (vtag == IPPDefs.TAG_END)
+ {
+ //
+ // No more attributes left...
+ //
+ ipp.state = IPPDefs.DATA;
+ if (attr != null)
+ {
+ ipp.addAttribute(attr);
+ attr = null;
+ }
+ break;
+ }
+ else if (vtag < IPPDefs.TAG_UNSUPPORTED_VALUE)
+ {
+ if (attr != null)
+ {
+ ipp.addAttribute(attr);
+ }
+
+ //
+ // Group tag... Set the current group and continue...
+ //
+ gtag = vtag;
+
+ // If still the same group ....
+ if (ipp.current_tag == gtag)
+ {
+ //
+ // Add a separator
+ //
+ attr = new IPPAttribute(IPPDefs.TAG_ZERO,IPPDefs.TAG_ZERO,"");
+ ipp.addAttribute(attr);
+ attr = null;
+ }
+
+
+ ipp.current_tag = gtag;
+ ipp.current = -1;
+ continue;
+ }
+
+ //
+ // Get the name...
+ //
+ n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
+ bufferidx += 2;
+ read_buffer_remaining -= 2;
+
+ if (n == 0)
+ {
+ //
+ // Parse Error, can't add additional values to null attr
+ //
+ if (attr == null)
+ return (null);
+
+ //
+ // More values for current attribute...
+ //
+
+ //
+ // Make sure we aren't adding a new value of a different
+ // type...
+ //
+
+ if (attr.value_tag == IPPDefs.TAG_STRING ||
+ (attr.value_tag >= IPPDefs.TAG_TEXTLANG &&
+ attr.value_tag <= IPPDefs.TAG_MIMETYPE))
+ {
+ //
+ // String values can sometimes come across in different
+ // forms; accept sets of differing values...
+ //
+ if (vtag != IPPDefs.TAG_STRING &&
+ (vtag < IPPDefs.TAG_TEXTLANG || vtag > IPPDefs.TAG_MIMETYPE))
+ return (null);
+ }
+ else if (attr.value_tag != vtag)
+ return (null);
+ }
+ else
+ {
+ if (attr != null)
+ {
+ ipp.addAttribute(attr);
+ attr = null;
+ }
+
+ //
+ // New Attribute
+ //
+ StringBuffer s = new StringBuffer();
+ for (int i=0; i < n; i++)
+ {
+ s.append((char)buffer[bufferidx++]);
+ read_buffer_remaining--;
+ }
+ attr = new IPPAttribute( gtag, vtag, s.toString() );
+ }
+ n = ((short)buffer[bufferidx] << 8) | (short)buffer[bufferidx+1];
+ bufferidx += 2;
+ read_buffer_remaining -= 2;
+
+ switch (vtag)
+ {
+ case IPPDefs.TAG_INTEGER :
+ case IPPDefs.TAG_ENUM :
+ n = (int)(((int)buffer[bufferidx] << 24) |
+ ((int)buffer[bufferidx+1] << 16) |
+ ((int)buffer[bufferidx+2] << 8) |
+ ((int)buffer[bufferidx+3]));
+ bufferidx += 4;
+ read_buffer_remaining -= 4;
+ attr.addInteger( n );
+ break;
+
+ case IPPDefs.TAG_BOOLEAN :
+ if ((byte)buffer[bufferidx++] > 0)
+ attr.addBoolean(true);
+ else
+ attr.addBoolean(false);
+ read_buffer_remaining --;
+ break;
+
+ case IPPDefs.TAG_TEXT :
+ case IPPDefs.TAG_NAME :
+ case IPPDefs.TAG_KEYWORD :
+ case IPPDefs.TAG_STRING :
+ case IPPDefs.TAG_URI :
+ case IPPDefs.TAG_URISCHEME :
+ case IPPDefs.TAG_CHARSET :
+ case IPPDefs.TAG_LANGUAGE :
+ case IPPDefs.TAG_MIMETYPE :
+ StringBuffer s = new StringBuffer();
+ for (int i=0; i < n; i++ )
+ {
+ s.append( (char)buffer[bufferidx++] );
+ read_buffer_remaining --;
+ }
+ attr.addString( "", s.toString() );
+ break;
+
+
+ case IPPDefs.TAG_DATE :
+ char db[] = new char[11];
+ for (int i=0; i < 11; i++ )
+ {
+ db[i] = (char)buffer[bufferidx++];
+ read_buffer_remaining --;
+ }
+ attr.addDate( db );
+ break;
+
+
+ case IPPDefs.TAG_RESOLUTION :
+ if (read_buffer_remaining < 9)
+ return( null );
+
+ int x, y;
+ byte u;
+ x = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
+ (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
+ (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
+ (((int)buffer[bufferidx+3] & 0x000000ff));
+ bufferidx += 4;
+ read_buffer_remaining -= 4;
+
+ y = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
+ (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
+ (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
+ (((int)buffer[bufferidx+3] & 0x000000ff));
+ bufferidx += 4;
+ read_buffer_remaining -= 4;
+
+ u = (byte)buffer[bufferidx++];
+ read_buffer_remaining--;
+ attr.addResolution( u, x, y );
+ break;
+
+ case IPPDefs.TAG_RANGE :
+ if (read_buffer_remaining < 8)
+ return (null);
+
+ int lower, upper;
+ lower = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
+ (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
+ (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
+ (((int)buffer[bufferidx+3] & 0x000000ff));
+ bufferidx += 4;
+ read_buffer_remaining -= 4;
+
+ upper = (int)(((int)buffer[bufferidx] & 0xff000000) << 24) |
+ (((int)buffer[bufferidx+1] & 0x00ff0000) << 16) |
+ (((int)buffer[bufferidx+2] & 0x0000ff00) << 8) |
+ (((int)buffer[bufferidx+3] & 0x000000ff));
+ bufferidx += 4;
+ read_buffer_remaining -= 4;
+
+ attr.addRange( (short)lower, (short)upper );
+ break;
+
+ case IPPDefs.TAG_TEXTLANG :
+ case IPPDefs.TAG_NAMELANG :
+ //
+ // text-with-language and name-with-language are composite
+ // values:
+ //
+ // charset-length
+ // charset
+ // text-length
+ // text
+ //
+
+ n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
+ bufferidx += 2;
+
+ StringBuffer cs = new StringBuffer();
+ for (int i=0; i < n; i++ )
+ {
+ cs.append( (char)buffer[bufferidx++] );
+ read_buffer_remaining --;
+ }
+
+ n = ((int)buffer[bufferidx] << 8) | (int)buffer[bufferidx+1];
+ bufferidx += 2;
+
+ StringBuffer tx = new StringBuffer();
+ for (int i=0; i < n; i++ )
+ {
+ tx.append( (char)buffer[bufferidx++] );
+ read_buffer_remaining --;
+ }
+
+ attr.addString( cs.toString(), tx.toString() );
+ break;
+
+
+ default : /* Other unsupported values */
+ if (n > 0)
+ {
+ bufferidx += n;
+ read_buffer_remaining -= n;
+ }
+ break;
+ }
+ } // End of while
+
+ if (attr != null)
+ {
+ ipp.addAttribute(attr);
+ attr = null;
+ }
+ break;
+
+ case IPPDefs.DATA :
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+ }
+ return (ipp);
+}
+
+
+
+//
+// Parse a WWW-Authenticate: Digest request
+//
+public void parseAuthenticate( String p_auth )
+{
+ String tmp;
+ StringBuffer val;
+ int i,n;
+
+ tmp = p_auth;
+ while (tmp.length() > 0)
+ {
+ i = 0;
+ while (tmp.length() > 0 && (tmp.charAt(i) == ' ' || tmp.charAt(i) == '"'))
+ tmp = tmp.substring(1);
+ i = 0;
+
+ if (tmp.startsWith("realm="))
+ {
+ i = "realm=".length();
+ tmp = tmp.substring(i);
+ i = 0;
+ while ((i < tmp.length()) &&
+ (tmp.charAt(i) == ' ' ||
+ tmp.charAt(i) == '"' ||
+ tmp.charAt(i) == '='))
+ {
+ i++;
+ }
+ val = new StringBuffer(1024);
+ while (i < tmp.length() && tmp.charAt(i) != '"')
+ val.append(tmp.charAt(i++));
+ realm = val.toString();
+ tmp = tmp.substring(i);
+ }
+ else if (tmp.startsWith("nonce="))
+ {
+ i = "nonce=".length();
+ tmp = tmp.substring(i);
+ i = 0;
+ while ((i < tmp.length()) &&
+ (tmp.charAt(i) == ' ' ||
+ tmp.charAt(i) == '"' ||
+ tmp.charAt(i) == '='))
+ {
+ i++;
+ }
+ val = new StringBuffer(1024);
+ while (i < tmp.length() && tmp.charAt(i) != '"')
+ val.append(tmp.charAt(i++));
+ nonce = val.toString();
+ tmp = tmp.substring(i);
+ }
+ else if (tmp.startsWith("opaque="))
+ {
+ i = "opaque=".length();
+ tmp = tmp.substring(i);
+ i = 0;
+ while ((i < tmp.length()) &&
+ (tmp.charAt(i) == ' ' ||
+ tmp.charAt(i) == '"' ||
+ tmp.charAt(i) == '='))
+ {
+ i++;
+ }
+ val = new StringBuffer(1024);
+ while (i < tmp.length() && tmp.charAt(i) != '"')
+ val.append(tmp.charAt(i++));
+ opaque = val.toString();
+ tmp = tmp.substring(i);
+ }
+ else
+ {
+ StringBuffer name = new StringBuffer(256);
+ while ((i < tmp.length()) &&
+ (tmp.charAt(i) != ' ' ||
+ tmp.charAt(i) != '"' ||
+ tmp.charAt(i) != '='))
+ {
+ name.append(tmp.charAt(i++));
+ }
+
+ i = name.toString().length();
+ tmp = tmp.substring(i);
+ i = 0;
+ while ((i < tmp.length()) &&
+ (tmp.charAt(i) == ' ' ||
+ tmp.charAt(i) == '"' ||
+ tmp.charAt(i) == '='))
+ {
+ i++;
+ }
+ val = new StringBuffer(1024);
+ while (i < tmp.length() && tmp.charAt(i) != '"')
+ val.append(tmp.charAt(i++));
+ //junk = val.toString();
+ tmp = tmp.substring(i);
+ }
+ }
+}
+
+
+
+
+
+} // End of IPPHttp class
+
+
diff --git a/scripting/java/src/org/cups/IPPMD5.java b/scripting/java/src/org/cups/IPPMD5.java
new file mode 100644
index 000000000..99fc160e8
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPMD5.java
@@ -0,0 +1,134 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * Digest MD5 password routines.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+import java.security.*;
+
+public class IPPMD5
+{
+ public MessageDigest md = null;
+ static private IPPMD5 md5 = null;
+ private static final char[] hexChars = {'0','1','2','3','4','5','6','7',
+ '8','9','a','b','c','d','e','f'};
+
+ /**
+ * Constructor is private so you must use the getInstance method
+ */
+ private IPPMD5() throws NoSuchAlgorithmException
+ {
+ md = MessageDigest.getInstance("MD5");
+ }
+
+
+ /**
+ * This returns the singleton instance
+ */
+ public static IPPMD5 getInstance() throws NoSuchAlgorithmException
+ {
+
+ if (md5 == null)
+ {
+ md5 = new IPPMD5();
+ }
+ return (md5);
+ }
+
+
+ public String hashData(byte[] dataToHash)
+ {
+ return(hexStringFromBytes((calculateHash(dataToHash))));
+ }
+
+
+ private byte[] calculateHash(byte[] dataToHash)
+ {
+ md.update(dataToHash, 0, dataToHash.length);
+ return(md.digest());
+ }
+
+
+ public String hexStringFromBytes(byte[] b)
+ {
+ String hex = "";
+ int msb;
+ int lsb = 0;
+ int i;
+
+ // MSB maps to idx 0
+ for (i = 0; i < b.length; i++)
+ {
+ msb = ((int)b[i] & 0x000000FF) / 16;
+ lsb = ((int)b[i] & 0x000000FF) % 16;
+ // System.out.println("I: " + i + " B: " + b[i] + " MSB: " +
+ // msb + " LSB: " + lsb );
+ hex = hex + hexChars[msb] + hexChars[lsb];
+ }
+ return(hex);
+ }
+
+
+
+
+
+ public String MD5Digest( String user, String passwd, String realm,
+ String method, String resource, String nonce )
+ {
+ String tmp;
+ String A1, A2;
+ String auth_string = "";
+
+ try
+ {
+ tmp = user + ":" + realm + ":" + passwd;
+ md = MessageDigest.getInstance("MD5");
+ A1 = hexStringFromBytes(md.digest(tmp.getBytes()));
+
+ tmp = method + ":" + resource;
+ md = MessageDigest.getInstance("MD5");
+ A2 = hexStringFromBytes(md.digest(tmp.getBytes()));
+
+ tmp = A1 + ":" + nonce + ":" + A2;
+ md = MessageDigest.getInstance("MD5");
+ auth_string = hexStringFromBytes(md.digest(tmp.getBytes()));
+ return(auth_string);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ }
+ return("");
+
+ }
+
+
+}
diff --git a/scripting/java/src/org/cups/IPPRequest.java b/scripting/java/src/org/cups/IPPRequest.java
new file mode 100644
index 000000000..1cc264ef4
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPRequest.java
@@ -0,0 +1,97 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPPRequest</code> object is used to hold the
+ * status and id's of a request.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+public class IPPRequest
+{
+ char[] version; // Proto version number
+ int request_id; // Unique ID
+
+ int op_status;
+ short operation_id;
+ short status_code;
+
+ /**
+ * Constructor
+ */
+ public IPPRequest()
+ {
+ version = new char[2];
+ }
+
+ /**
+ * Constructor using request id and operation id.
+ *
+ * @param <code>p_request_id</code> ID of request.
+ * @param <code>p_operation_id</code> Operation ID for request.
+ *
+ * @see <code>IPPDefs</code>
+ */
+ public IPPRequest( int p_request_id, short p_operation_id )
+ {
+ version = new char[2];
+ version[0] = (char)1;
+ version[1] = (char)1;
+ request_id = p_request_id;
+ operation_id = p_operation_id;
+ }
+
+ /**
+ * Set the current status of a request.
+ *
+ * @param <code>p_status_code</code> Status code.
+ * @see <code>IPPDefs</code>
+ */
+ public void setStatus( short p_status_code )
+ {
+ status_code = p_status_code;
+ }
+
+ /**
+ * Set the operation status of a request.
+ *
+ * @param <code>p_status_code</code> Operation status code.
+ * @see <code>IPPDefs</code>
+ */
+ public void setOpStatus( short p_status_code )
+ {
+ op_status = p_status_code;
+ }
+
+} // End of IPPRequest class
+
+
+
+
diff --git a/scripting/java/src/org/cups/IPPStatus.java b/scripting/java/src/org/cups/IPPStatus.java
new file mode 100644
index 000000000..8a90623b0
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPStatus.java
@@ -0,0 +1,195 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * Class to convert a status code to text.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+public class IPPStatus
+{
+ int status;
+ String status_text;
+
+ /**
+ * Constructor, access the <code>status_text</code> member
+ * after creation.
+ *
+ * @param <code>p_status</code> Status code to convert.
+ * @see <code>IPPDefs</code>
+ */
+ public IPPStatus( int p_status )
+ {
+ status = p_status;
+ switch( status )
+ {
+ case IPPDefs.OK:
+ status_text = "OK";
+ break;
+ case IPPDefs.OK_SUBST:
+ status_text = "OK, substituted";
+ break;
+ case IPPDefs.OK_CONFLICT:
+ status_text = "OK, conflict";
+ break;
+ case IPPDefs.OK_IGNORED_SUBSCRIPTIONS:
+ status_text = "OK, ignored subscriptions";
+ break;
+ case IPPDefs.OK_IGNORED_NOTIFICATIONS:
+ status_text = "OK, ignored notifications";
+ break;
+ case IPPDefs.OK_TOO_MANY_EVENTS:
+ status_text = "OK, too many events";
+ break;
+ case IPPDefs.OK_BUT_CANCEL_SUBSCRIPTION:
+ status_text = "OK, but cancel subscription";
+ break;
+ case IPPDefs.REDIRECTION_OTHER_SITE:
+ status_text = "Redirected to other site";
+ break;
+ case IPPDefs.BAD_REQUEST:
+ status_text = "Bad request";
+ break;
+ case IPPDefs.FORBIDDEN:
+ status_text = "Forbidden";
+ break;
+ case IPPDefs.NOT_AUTHENTICATED:
+ status_text = "Not authenticated";
+ break;
+ case IPPDefs.NOT_AUTHORIZED:
+ status_text = "Not authorized";
+ break;
+ case IPPDefs.NOT_POSSIBLE:
+ status_text = "Not possible";
+ break;
+ case IPPDefs.TIMEOUT:
+ status_text = "Timeout";
+ break;
+ case IPPDefs.NOT_FOUND:
+ status_text = "Not found";
+ break;
+ case IPPDefs.GONE:
+ status_text = "Gone";
+ break;
+ case IPPDefs.REQUEST_ENTITY:
+ status_text = "Request entity";
+ break;
+ case IPPDefs.REQUEST_VALUE:
+ status_text = "Request value";
+ break;
+ case IPPDefs.DOCUMENT_FORMAT:
+ status_text = "Document format";
+ break;
+ case IPPDefs.ATTRIBUTES:
+ status_text = "Attributes";
+ break;
+ case IPPDefs.URI_SCHEME:
+ status_text = "URI scheme";
+ break;
+ case IPPDefs.CHARSET:
+ status_text = "Charset";
+ break;
+ case IPPDefs.CONFLICT:
+ status_text = "Conflict";
+ break;
+ case IPPDefs.COMPRESSION_NOT_SUPPORTED:
+ status_text = "Compression not supported";
+ break;
+ case IPPDefs.COMPRESSION_ERROR:
+ status_text = "Compression error";
+ break;
+ case IPPDefs.DOCUMENT_FORMAT_ERROR:
+ status_text = "Document format error";
+ break;
+ case IPPDefs.DOCUMENT_ACCESS_ERROR:
+ status_text = "Document access error";
+ break;
+ case IPPDefs.ATTRIBUTES_NOT_SETTABLE:
+ status_text = "Attributes not settable";
+ break;
+ case IPPDefs.IGNORED_ALL_SUBSCRIPTIONS:
+ status_text = "Ignored all subscriptions";
+ break;
+ case IPPDefs.TOO_MANY_SUBSCRIPTIONS:
+ status_text = "Too many subscriptions";
+ break;
+ case IPPDefs.IGNORED_ALL_NOTIFICATIONS:
+ status_text = "Ingored all notifications";
+ break;
+ case IPPDefs.PRINT_SUPPORT_FILE_NOT_FOUND:
+ status_text = "Support file not found";
+ break;
+ case IPPDefs.INTERNAL_ERROR:
+ status_text = "Internal error";
+ break;
+ case IPPDefs.OPERATION_NOT_SUPPORTED:
+ status_text = "Operation not supported";
+ break;
+ case IPPDefs.SERVICE_UNAVAILABLE:
+ status_text = "Service unavailable";
+ break;
+ case IPPDefs.VERSION_NOT_SUPPORTED:
+ status_text = "Version not supported";
+ break;
+ case IPPDefs.DEVICE_ERROR:
+ status_text = "Device error";
+ break;
+ case IPPDefs.TEMPORARY_ERROR:
+ status_text = "Temporary error";
+ break;
+ case IPPDefs.NOT_ACCEPTING:
+ status_text = "Not accepting";
+ break;
+ case IPPDefs.PRINTER_BUSY:
+ status_text = "Printer busy";
+ break;
+ case IPPDefs.ERROR_JOB_CANCELLED:
+ status_text = "Error, job cancelled";
+ break;
+ case IPPDefs.MULTIPLE_JOBS_NOT_SUPPORTED:
+ status_text = "Multiple jobs not supported";
+ break;
+ case IPPDefs.PRINTER_IS_DEACTIVATED:
+ status_text = "Printer is de-activated";
+ break;
+ default:
+ status_text = "Unknown error";
+ }
+ }
+
+
+
+
+
+} // End of IPPStatus class
+
+
+
diff --git a/scripting/java/src/org/cups/IPPURLConnection.java b/scripting/java/src/org/cups/IPPURLConnection.java
new file mode 100644
index 000000000..d2d6611c9
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPURLConnection.java
@@ -0,0 +1,78 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * Implementation of the URLConnection interface.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+public class IPPURLConnection extends URLConnection
+{
+
+ /**
+ * Constructor.
+ */
+ public IPPURLConnection( URL url )
+ {
+ super(url);
+ }
+
+ /**
+ * Determine if using proxy.
+ *
+ * @return <code>boolean</code> Always <code>false</code> for now.
+ */
+ public boolean usingProxy()
+ {
+ return(false);
+ }
+
+ /**
+ * Not used.
+ */
+ public void connect()
+ {
+ return;
+ }
+
+ /**
+ * Not used.
+ */
+ public void disconnect()
+ {
+ return;
+ }
+
+} // end of class
diff --git a/scripting/java/src/org/cups/IPPValue.java b/scripting/java/src/org/cups/IPPValue.java
new file mode 100644
index 000000000..d2aa0eb5d
--- /dev/null
+++ b/scripting/java/src/org/cups/IPPValue.java
@@ -0,0 +1,264 @@
+package org.cups;
+
+/**
+ * @version 1.00 06-NOV-2003
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPPValue</code> object is used to hold the
+ * different kinds of values in a generic object.
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
+import java.util.*;
+
+public class IPPValue
+{
+
+ int value_type; // Type of value for this object.
+
+ int integer_value; // Integer value
+ boolean boolean_value; // Boolean value
+
+
+ char date_value[]; // Date/time value
+ long unix_time; // Unix time ....
+
+ //
+ // Resolution Type
+ //
+ int xres;
+ int yres;
+ byte units;
+
+ //
+ // Range Type
+ //
+ int lower;
+ int upper;
+
+ //
+ // String Type
+ //
+ String charset;
+ String text;
+
+ //
+ // Unknown Type
+ //
+ int length;
+ char data[];
+
+
+ /**
+ * Byte constructor.
+ *
+ * @param <code>p_byte</code> Byte value.
+ */
+ public IPPValue( byte p_byte )
+ {
+ value_type = IPPDefs.TAG_INTEGER;
+ integer_value = (int)p_byte;
+ }
+
+ /**
+ * Short constructor.
+ *
+ * @param <code>p_short</code> Short value.
+ */
+ public IPPValue( short p_short )
+ {
+ value_type = IPPDefs.TAG_INTEGER;
+ integer_value = (int)p_short;
+ }
+
+ /**
+ * Integer constructor.
+ *
+ * @param <code>p_int</code> Integer value.
+ */
+ public IPPValue( int p_int )
+ {
+ value_type = IPPDefs.TAG_INTEGER;
+ integer_value = p_int;
+ }
+
+ /**
+ * Enum constructor.
+ *
+ * @param <code>p_int</code> Integer value - force to IPP enum.
+ */
+ public IPPValue( int p_int, boolean anything )
+ {
+ value_type = IPPDefs.TAG_ENUM;
+ integer_value = p_int;
+ }
+
+ /**
+ * Boolean constructor.
+ *
+ * @param <code>p_boolean</code> Boolean value.
+ */
+ public IPPValue( boolean p_boolean )
+ {
+ value_type = IPPDefs.TAG_BOOLEAN;
+ boolean_value = p_boolean;
+ }
+
+
+ /**
+ * Date constructor. Also set the <code>unix_time</code> member.
+ *
+ * @param <code>p_date[]</code> Character array with date value.
+ */
+ public IPPValue( char p_date[] )
+ {
+ value_type = IPPDefs.TAG_DATE;
+ date_value = p_date;
+ unix_time = IPPDateToTime();
+ }
+
+
+
+ /**
+ * String constructor. Set the <code>string</code> and
+ * <code>charset</code> values.
+ *
+ * @param <code>p_charset</code> Charset for string.
+ * @param <code>p_text</code> Text for string.
+ */
+ public IPPValue( String p_charset, String p_text )
+ {
+ value_type = IPPDefs.TAG_STRING;
+ charset = p_charset;
+ text = p_text;
+ }
+
+
+ /**
+ * Range constructor. Automatically swap as needed.
+ *
+ * @param <code>p_lower</code> Integer lower value.
+ * @param <code>p_upper</code> Integer upper value.
+ */
+ public IPPValue( int p_lower, int p_upper )
+ {
+ value_type = IPPDefs.TAG_RANGE;
+ if (p_lower < p_upper)
+ {
+ lower = p_lower;
+ upper = p_upper;
+ }
+ else
+ {
+ lower = p_upper;
+ upper = p_lower;
+ }
+ }
+
+
+ /**
+ * Resolution constructor.
+ *
+ * @param <code>p_units</code> Unit of measure.
+ * @param <code>p_xres</code> X resolution.
+ * @param <code>p_yres</code> Y resolution.
+ */
+ public IPPValue( byte p_units, int p_xres, int p_yres )
+ {
+ value_type = IPPDefs.TAG_RESOLUTION;
+ units = p_units;
+ xres = p_xres;
+ yres = p_yres;
+ }
+
+
+ /**
+ * Raw data constructor.
+ *
+ * @param <code>p_length</code> Size of array.
+ * @param <code>p_data[]</code> Data.
+ */
+ public IPPValue( int p_length, char p_data[] )
+ {
+ value_type = IPPDefs.TAG_UNKNOWN;
+ length = p_length;
+ data = p_data;
+ }
+
+
+
+ /**
+ * Convert an IPP Date value to Unix Time.
+ *
+ * @return <code>long</code> Unix time in seconds.
+ * @see <code>IPPCalender</code>
+ */
+ public long IPPDateToTime()
+ {
+
+ //
+ // Compute the offset from GMT in milliseconds.
+ //
+ int raw_offset = (((int)date_value[9] * 3600) + ((int)date_value[10] * 60)) * 1000;
+ if (date_value[8] == '-')
+ raw_offset = 0 - raw_offset;
+
+ //
+ // Get the timezone for that offset.
+ //
+ TimeZone tz = new SimpleTimeZone(raw_offset,"GMT");
+
+ //
+ // Create a subclassed gregorian calendar (sub classed so we have
+ // access to the getTimeInMillis() method).
+ //
+ IPPCalendar cl = new IPPCalendar();
+
+ int year = ((((int)date_value[0]) << 8) | (((int)date_value[1]) - 1900));
+ int month = ((int)date_value[2]) - 1;
+ int day = (int)date_value[3];
+ int hour = (int)date_value[4];
+ int minute = (int)date_value[5];
+ int second = (int)date_value[6];
+
+ //
+ // Now set the calendar to the matching time.
+ //
+ cl.setTimeZone( tz );
+ cl.set( year, month, day, hour, minute, second );
+
+ //
+ // And finally get the unix time.
+ //
+ long the_time = cl.getTimeInMillis();
+ the_time /= 1000;
+
+ return(the_time);
+ }
+
+} // End of class
diff --git a/scripting/java/src/org/cups/Makefile b/scripting/java/src/org/cups/Makefile
new file mode 100644
index 000000000..9fe32f9f2
--- /dev/null
+++ b/scripting/java/src/org/cups/Makefile
@@ -0,0 +1,92 @@
+#
+# "$Id$"
+#
+# Java Makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2003 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+#
+# Default build rules and suffixes...
+#
+
+.SUFFIXES: .class .jar .java
+.SILENT:
+
+.java.class:
+ echo Compiling $@...
+ javac -d ../.. -classpath ../.. $<
+
+
+#
+# List of classes...
+#
+
+CLASSES = \
+ IPPBase64Encoder.class \
+ IPPDefs.class \
+ IPPError.class \
+ IPPStatus.class \
+ IPPCalendar.class \
+ IPPValue.class \
+ IPPAttribute.class \
+ IPPRequest.class \
+ IPPURLConnection.class \
+ IPP.class \
+ IPPHttp.class \
+ CupsJob.class \
+ Cups.class \
+ CupsPrinter.class
+
+
+#
+# Make everything...
+#
+
+all: ../../../cups.jar
+
+
+#
+# Clean everything...
+#
+
+clean:
+ rm -f $(CLASSES)
+
+
+#
+# Make documentation using javadoc...
+#
+
+docs:
+ javadoc -d ../../../docs -classpath ../.. -verbose $(CLASSES:.class=.java)
+
+
+#
+# Make CUPS class archive...
+#
+
+../../../cups.jar: $(CLASSES)
+ rm -f ../../../cups.jar
+ jar cvf ../../../cups.jar $(CLASSES)
+
+
+#
+# End of "$Id$".
+#
diff --git a/scripting/java/src/org/cups/cups.nfo b/scripting/java/src/org/cups/cups.nfo
new file mode 100644
index 000000000..900db5150
--- /dev/null
+++ b/scripting/java/src/org/cups/cups.nfo
@@ -0,0 +1,34 @@
+/**
+ * @version 1.00 06-NOV-2002
+ * @author Easy Software Products
+ *
+ * Internet Printing Protocol definitions for the Common UNIX Printing
+ * System (CUPS).
+ *
+ * Copyright 1997-2002 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/**
+ * An <code>IPP</code> object is used to hold the various
+ * attributes and status of an ipp request..
+ *
+ * @author TDB
+ * @version 1.0
+ * @since JDK1.3
+ */
diff --git a/scripting/perl/CUPS.pm b/scripting/perl/CUPS.pm
new file mode 100644
index 000000000..5f2ed5f14
--- /dev/null
+++ b/scripting/perl/CUPS.pm
@@ -0,0 +1,144 @@
+package CUPS;
+
+use 5.006;
+use strict;
+use warnings;
+use Carp;
+
+require Exporter;
+require DynaLoader;
+use AutoLoader;
+
+our @ISA = qw(Exporter DynaLoader);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+# This allows declaration use CUPS ':all';
+# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
+# will save memory.
+our %EXPORT_TAGS = ( 'all' => [ qw(
+ CUPS_DATE_ANY
+ CUPS_VERSION
+ HTTP_MAX_BUFFER
+ HTTP_MAX_HOST
+ HTTP_MAX_URI
+ HTTP_MAX_VALUE
+ IPP_MAX_NAME
+ IPP_MAX_VALUES
+ IPP_PORT
+ PPD_MAX_LINE
+ PPD_MAX_NAME
+ PPD_MAX_TEXT
+ PPD_VERSION
+) ] );
+
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+
+our @EXPORT = qw(
+ CUPS_DATE_ANY
+ CUPS_VERSION
+ HTTP_MAX_BUFFER
+ HTTP_MAX_HOST
+ HTTP_MAX_URI
+ HTTP_MAX_VALUE
+ IPP_MAX_NAME
+ IPP_MAX_VALUES
+ IPP_PORT
+ PPD_MAX_LINE
+ PPD_MAX_NAME
+ PPD_MAX_TEXT
+ PPD_VERSION
+);
+our $VERSION = '1.2';
+
+sub AUTOLOAD {
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname;
+ our $AUTOLOAD;
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ croak "& not defined" if $constname eq 'constant';
+ my $val = constant($constname, @_ ? $_[0] : 0);
+ if ($! != 0) {
+ if ($! =~ /Invalid/ || $!{EINVAL}) {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else {
+ croak "Your vendor has not defined CUPS macro $constname";
+ }
+ }
+ {
+ no strict 'refs';
+ # Fixed between 5.005_53 and 5.005_61
+ if ($] >= 5.00561) {
+ *$AUTOLOAD = sub () { $val };
+ }
+ else {
+ *$AUTOLOAD = sub { $val };
+ }
+ }
+ goto &$AUTOLOAD;
+}
+
+bootstrap CUPS $VERSION;
+
+# Preloaded methods go here.
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+# Below is stub documentation for your module. You better edit it!
+
+=head1 NAME
+
+CUPS - Perl extension for blah blah blah
+
+=head1 SYNOPSIS
+
+ use CUPS;
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Stub documentation for CUPS, created by h2xs. It looks like the
+author of the extension was negligent enough to leave the stub
+unedited.
+
+Blah blah blah.
+
+=head2 EXPORT
+
+None by default.
+
+=head2 Exportable constants
+
+ CUPS_DATE_ANY
+ CUPS_VERSION
+ HTTP_MAX_BUFFER
+ HTTP_MAX_HOST
+ HTTP_MAX_URI
+ HTTP_MAX_VALUE
+ IPP_MAX_NAME
+ IPP_MAX_VALUES
+ IPP_PORT
+ PPD_MAX_LINE
+ PPD_MAX_NAME
+ PPD_MAX_TEXT
+ PPD_VERSION
+
+
+=head1 AUTHOR
+
+A. U. Thor, E<lt>a.u.thor@a.galaxy.far.far.awayE<gt>
+
+=head1 SEE ALSO
+
+L<perl>.
+
+=cut
diff --git a/scripting/perl/CUPS.xs b/scripting/perl/CUPS.xs
new file mode 100644
index 000000000..efaf6dc7a
--- /dev/null
+++ b/scripting/perl/CUPS.xs
@@ -0,0 +1,270 @@
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include <cups/cups.h>
+#include <cups/http.h>
+#include <cups/ipp.h>
+#include <cups/language.h>
+#include <cups/ppd.h>
+
+static int
+not_here(char *s)
+{
+ croak("%s not implemented on this architecture", s);
+ return -1;
+}
+
+static double
+constant_PPD_M(char *name, int len, int arg)
+{
+ if (5 + 3 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[5 + 3]) {
+ case 'L':
+ if (strEQ(name + 5, "AX_LINE")) { /* PPD_M removed */
+#ifdef PPD_MAX_LINE
+ return PPD_MAX_LINE;
+#else
+ goto not_there;
+#endif
+ }
+ case 'N':
+ if (strEQ(name + 5, "AX_NAME")) { /* PPD_M removed */
+#ifdef PPD_MAX_NAME
+ return PPD_MAX_NAME;
+#else
+ goto not_there;
+#endif
+ }
+ case 'T':
+ if (strEQ(name + 5, "AX_TEXT")) { /* PPD_M removed */
+#ifdef PPD_MAX_TEXT
+ return PPD_MAX_TEXT;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_P(char *name, int len, int arg)
+{
+ if (1 + 3 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[1 + 3]) {
+ case 'M':
+ if (!strnEQ(name + 1,"PD_", 3))
+ break;
+ return constant_PPD_M(name, len, arg);
+ case 'V':
+ if (strEQ(name + 1, "PD_VERSION")) { /* P removed */
+#ifdef PPD_VERSION
+ return PPD_VERSION;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_H(char *name, int len, int arg)
+{
+ if (1 + 8 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[1 + 8]) {
+ case 'B':
+ if (strEQ(name + 1, "TTP_MAX_BUFFER")) { /* H removed */
+#ifdef HTTP_MAX_BUFFER
+ return HTTP_MAX_BUFFER;
+#else
+ goto not_there;
+#endif
+ }
+ case 'H':
+ if (strEQ(name + 1, "TTP_MAX_HOST")) { /* H removed */
+#ifdef HTTP_MAX_HOST
+ return HTTP_MAX_HOST;
+#else
+ goto not_there;
+#endif
+ }
+ case 'U':
+ if (strEQ(name + 1, "TTP_MAX_URI")) { /* H removed */
+#ifdef HTTP_MAX_URI
+ return HTTP_MAX_URI;
+#else
+ goto not_there;
+#endif
+ }
+ case 'V':
+ if (strEQ(name + 1, "TTP_MAX_VALUE")) { /* H removed */
+#ifdef HTTP_MAX_VALUE
+ return HTTP_MAX_VALUE;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_IPP_M(char *name, int len, int arg)
+{
+ if (5 + 3 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[5 + 3]) {
+ case 'N':
+ if (strEQ(name + 5, "AX_NAME")) { /* IPP_M removed */
+#ifdef IPP_MAX_NAME
+ return IPP_MAX_NAME;
+#else
+ goto not_there;
+#endif
+ }
+ case 'V':
+ if (strEQ(name + 5, "AX_VALUES")) { /* IPP_M removed */
+#ifdef IPP_MAX_VALUES
+ return IPP_MAX_VALUES;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_I(char *name, int len, int arg)
+{
+ if (1 + 3 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[1 + 3]) {
+ case 'M':
+ if (!strnEQ(name + 1,"PP_", 3))
+ break;
+ return constant_IPP_M(name, len, arg);
+ case 'P':
+ if (strEQ(name + 1, "PP_PORT")) { /* I removed */
+#ifdef IPP_PORT
+ return IPP_PORT;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant_C(char *name, int len, int arg)
+{
+ if (1 + 4 >= len ) {
+ errno = EINVAL;
+ return 0;
+ }
+ switch (name[1 + 4]) {
+ case 'D':
+ if (strEQ(name + 1, "UPS_DATE_ANY")) { /* C removed */
+#ifdef CUPS_DATE_ANY
+ return CUPS_DATE_ANY;
+#else
+ goto not_there;
+#endif
+ }
+ case 'V':
+ if (strEQ(name + 1, "UPS_VERSION")) { /* C removed */
+#ifdef CUPS_VERSION
+ return CUPS_VERSION;
+#else
+ goto not_there;
+#endif
+ }
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+static double
+constant(char *name, int len, int arg)
+{
+ errno = 0;
+ switch (name[0 + 0]) {
+ case 'C':
+ return constant_C(name, len, arg);
+ case 'H':
+ return constant_H(name, len, arg);
+ case 'I':
+ return constant_I(name, len, arg);
+ case 'P':
+ return constant_P(name, len, arg);
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
+
+
+MODULE = CUPS PACKAGE = CUPS
+
+
+double
+constant(sv,arg)
+ PREINIT:
+ STRLEN len;
+ INPUT:
+ SV * sv
+ char * s = SvPV(sv, len);
+ int arg
+ CODE:
+ RETVAL = constant(s,len,arg);
+ OUTPUT:
+ RETVAL
+
diff --git a/scripting/perl/Makefile.PL b/scripting/perl/Makefile.PL
new file mode 100644
index 000000000..f5e4bdd27
--- /dev/null
+++ b/scripting/perl/Makefile.PL
@@ -0,0 +1,17 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'CUPS',
+ 'VERSION_FROM' => 'CUPS.pm', # finds $VERSION
+ 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'CUPS.pm', # retrieve abstract from module
+ AUTHOR => 'A. U. Thor <a.u.thor@a.galaxy.far.far.away>') : ()),
+ 'LIBS' => ['-lcups '], # e.g., '-lm'
+ 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
+ # Insert -I. if you add *.h files later:
+ 'INC' => '', # e.g., '-I/usr/include/other'
+ # Un-comment this if you add C files to link with later:
+ # 'OBJECT' => '$(O_FILES)', # link all the C files too
+);
diff --git a/scripting/perl/README b/scripting/perl/README
new file mode 100644
index 000000000..6b762ab92
--- /dev/null
+++ b/scripting/perl/README
@@ -0,0 +1,46 @@
+README - 04/11/2003
+-------------------
+
+The README is used to introduce the module and provide
+instructions on how to install the module, any machine
+dependencies it may have (for example C compilers and installed
+libraries) and any other information that should be provided
+before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts
+the README file from a module distribution so that people
+browsing the archive can use it get an idea of the modules uses.
+It is usually a good idea to provide version information here so
+that people can decide whether fixes for the module are worth
+downloading.
+
+
+INSTALLATION
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+ CUPS 1.1.19 or higher
+
+
+COPYRIGHT AND LICENCE
+
+CUPS is Copyright 1993-2003 by Easy Software Products. CUPS,
+the CUPS logo, and the Common UNIX Printing System are the
+trademark property of Easy Software Products.
+
+CUPS is provided under the terms of the GNU General Public
+License and GNU Library General Public License. This program is
+distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the "LICENSE.html",
+"LICENSE.txt", or "cups.license" files for more information.
diff --git a/scripting/perl/test.pl b/scripting/perl/test.pl
new file mode 100644
index 000000000..acf31916b
--- /dev/null
+++ b/scripting/perl/test.pl
@@ -0,0 +1,17 @@
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+#########################
+
+# change 'tests => 1' to 'tests => last_test_to_print';
+
+use Test;
+BEGIN { plan tests => 1 };
+use CUPS;
+ok(1); # If we made it this far, we're ok.
+
+#########################
+
+# Insert your test code below, the Test module is use()ed here so read
+# its man page ( perldoc Test ) for help writing this test script.
+
diff --git a/scripting/php/Dependencies b/scripting/php/Dependencies
new file mode 100644
index 000000000..c5e45a09c
--- /dev/null
+++ b/scripting/php/Dependencies
@@ -0,0 +1,6 @@
+# DO NOT DELETE
+
+phpcups.o: php_phpcups.h ../../cups/cups.h ../../cups/ipp.h ../../cups/http.h
+phpcups.o: ../../cups/md5.h ../../cups/ppd.h ../../cups/ipp.h
+phpcups.o: ../../cups/language.h ../../cups/string.h ../../config.h
+phpcups.o: ../../cups/debug.h
diff --git a/scripting/php/Example/phpcups.inc.php4 b/scripting/php/Example/phpcups.inc.php4
new file mode 100644
index 000000000..dfb11fb09
--- /dev/null
+++ b/scripting/php/Example/phpcups.inc.php4
@@ -0,0 +1,310 @@
+<?php
+/*
+ * PHP module for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * Basic CupsPrinter class. Will be extended in next release.
+ *
+ */
+if (!$INCLUDED_PHPCUPS_INC)
+{
+ $INCLUDED_PHPCUPS_INC = True;
+
+
+ class CupsPrinter
+ {
+ var $printer_name;
+ var $printer_server;
+ var $printer_instance;
+ var $is_default;
+ var $printer_options;
+ var $printer_state;
+ var $printer_state_message;
+ var $accepting_jobs;
+ var $queued_job_count;
+ var $description;
+ var $location;
+ var $printer_info;
+ var $printer_more_info;
+ var $make_and_model;
+ var $printer_uri;
+ var $device_uri;
+ var $job_quota_period;
+ var $job_k_limit;
+ var $job_page_limit;
+ var $color_supported;
+ var $pages_per_minute;
+ var $finishings_supported; // Array
+ var $finishings_default;
+ var $printer_type;
+ var $operations_supported; // Array
+ var $multiple_document_jobs_supported;
+ var $multiple_operation_time_out;
+ var $job_priority_supported_lower;
+ var $job_priority_supported_upper;
+ var $job_priority_default;
+ var $copies_supported_lower;
+ var $copies_supported_upper;
+ var $copies_default;
+ var $page_range_supported;
+ var $number_up_supported; // Array
+ var $number_up_default;
+ var $orientation_requested_supported; // Array
+ var $orientation_requested_default;
+ var $media_supported; // Array
+ var $media_default;
+
+ function CupsPrinter()
+ {
+ $this->printer_name = "";
+ $this->printer_destination = "";
+ $this->is_default = 0;
+ $this->options = Array();
+ $this->printer_state = -1;
+ $this->printer_state_message = "";
+ $this->accepting_jobs = FALSE;
+ $this->queued_job_count = 0;
+ $this->description = "";
+ $this->location = "";
+ $this->printer_info = "";
+ $this->printer_more_info = "";
+ $this->make_and_model = "";
+ $this->printer_uri_supported = Array();
+ $this->device_uri = "";
+ $this->job_quota_period = 0;
+ $this->job_k_limit = 0;
+ $this->job_page_limit = 0;
+ $this->color_supported = FALSE;
+ $this->pages_per_minute = 0;
+ $this->finishings_supported = Array();
+ $this->finishings_default = 0;
+ $this->printer_type = 0;
+ $this->operations_supported = Array();
+ $this->multiple_document_jobs_supported = FALSE;
+ $this->multiple_operation_time_out = 0;
+ $this->job_priority_supported_lower = 0;
+ $this->job_priority_supported_upper = 100;
+ $this->job_priority_default = 50;
+ $this->copies_supported_lower = 1;
+ $this->copies_supported_upper = 1;
+ $this->copies_default = 1;
+ $this->page_range_supported = FALSE;
+ $this->number_up_supported = Array();
+ $this->number_up_default = 0;
+ $this->orientation_requested_supported = Array();
+ $this->orientation_requested_default = 3;
+ $this->media_supported = Array();
+ $this->media_default = "";
+
+ } // End of constructor
+
+
+ //
+ // Get the attributes
+ //
+ function getAttributes()
+ {
+ $o_arr = cups_get_dest_options($this->printer_server,
+ $this->printer_name,
+ $this->printer_instance);
+ $this->printer_options = $o_arr;
+
+ $attrs = cups_get_printer_attributes( "localhost", $this->printer_name );
+ while ($obj = current($attrs))
+ {
+ next($attrs);
+
+ if ($obj->name == "printer-state")
+ {
+ $this->printer_state = $obj->value;
+ }
+ else if ($obj->name == "printer-state-message")
+ {
+ $this->printer_state_message = $obj->value;
+ }
+ else if ($obj->name == "printer-location")
+ {
+ $this->location = $obj->value;
+ }
+ else if ($obj->name == "printer-make-and-model")
+ {
+ $this->description = $obj->value;
+ }
+ else if ($obj->name == "printer-uri-supported")
+ {
+ $this->printer_uri_supported[$obj->value] = $obj->value;
+ }
+ else if ($obj->name == "device-uri")
+ {
+ $this->device_uri = $obj->value;
+ }
+ else if ($obj->name == "queued-job-count")
+ {
+ $this->queued_job_count = $obj->value;
+ }
+ else if ($obj->name == "printer-is-accepting-jobs")
+ {
+ $this->accepting_jobs = $obj->value ? TRUE : FALSE;
+ }
+ else if ($obj->name == "color-supported")
+ {
+ $this->color_supported = $obj->value ? TRUE : FALSE;
+ }
+ else if ($obj->name == "pages-per-minute")
+ {
+ $this->pages_per_minute = $obj->value;
+ }
+ else if ($obj->name == "operations-supported")
+ {
+ $this->operations_supported["O$obj->value"] = $obj->value;
+ }
+ else if ($obj->name == "orientation-requested-supported")
+ {
+ $this->orientation_requested_supported["O$obj->value"] = $obj->value;
+ }
+ else if ($obj->name == "orientation-requested-default")
+ {
+ $this->orientation_requested_default = $obj->value;
+ }
+ else if ($obj->name == "finishings-supported")
+ {
+ $this->finishings_supported["F$obj->value"] = $obj->value;
+ }
+ else if ($obj->name == "finishings-default")
+ {
+ $this->finishings_default = $obj->value;
+ }
+ else if ($obj->name == "number-up-supported")
+ {
+ $this->number_up_supported["N$obj->value"] = $obj->value;
+ }
+ else if ($obj->name == "number-up-default")
+ {
+ $this->number_up_default = $obj->value;
+ }
+ else if ($obj->name == "printer-type")
+ {
+ $this->printer_type = $obj->value;
+ }
+ else if ($obj->name == "multiple-document-jobs-suppoted")
+ {
+ $this->multiple_document_jobs_supported = $obj->value ? TRUE : FALSE;
+ }
+ else if ($obj->name == "multiple-operation-time-out")
+ {
+ $this->multiple_operation_time_out = $obj->value;
+ }
+ else if ($obj->name == "job-priority-supported")
+ {
+ $this->job_priority_supported_upper = $obj->value;
+ }
+ else if ($obj->name == "job-priority-default")
+ {
+ $this->job_priority_default = $obj->value;
+ }
+ else if ($obj->name == "copies-supported")
+ {
+ $tmpa = explode("-",$obj->value);
+ if (count($tmpa) > 1)
+ {
+ $this->copies_supported_lower = $tmpa[0];
+ $this->copies_supported_upper = $tmpa[1];
+ }
+ else if (count($tmpa) == 1)
+ {
+ $this->copies_supported_lower = $tmpa[0];
+ $this->copies_supported_upper = $tmpa[0];
+ }
+ }
+ else if ($obj->name == "copies-default")
+ {
+ $this->copies_supported_default = $obj->value;
+ }
+ else if ($obj->name == "page-ranges-supported")
+ {
+ $this->page_ranges_supported = $obj->value ? TRUE : FALSE;
+ }
+ else if ($obj->name == "media-default")
+ {
+ $this->media_default = $obj->value;
+ }
+ else if ($obj->name == "media-supported")
+ {
+ $this->media_supported[$obj->value] = $obj->value;
+ }
+
+ } // while
+
+ } // End of getAttributes
+
+
+ } // End of CupsPrinter class
+
+
+
+
+ //
+ // Get the printer / destination list.
+ //
+ function phpcups_getDestList()
+ {
+ $return_value = Array();
+
+ //
+ // Get the destination objects array.
+ //
+ $p_arr = cups_get_dest_list();
+
+ if (!IS_ARRAY($p_arr))
+ {
+ return(NULL);
+ }
+
+ reset($p_arr);
+
+ while ($p_obj = current($p_arr))
+ {
+ next($p_arr);
+
+ //
+ // Get the options for the current destination.
+ //
+ $o_arr = cups_get_dest_options("localhost",$p_obj->name,$p_obj->instance);
+
+ $p = new CupsPrinter();
+ $p->printer_name = $p_obj->name;
+ $p->printer_instance = $p_obj->instance;
+ $p->is_default = $p_obj->is_default;
+ $p->printer_options = $o_arr;
+ $p->getAttributes();
+
+ $return_value[$p->printer_name] = $p;
+ }
+ return($return_value);
+
+ } // End of phpcups_getDestList()
+
+
+
+
+} // if included.
+?>
diff --git a/scripting/php/Makefile b/scripting/php/Makefile
new file mode 100644
index 000000000..2d997406f
--- /dev/null
+++ b/scripting/php/Makefile
@@ -0,0 +1,101 @@
+#
+# "$Id$"
+#
+# PHP Makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2003 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+
+#
+# Where to install the PHP module...
+#
+
+PHPDIR = `php-config --extension-dir`
+OPTIONS = `php-config --includes` -I../.. -DCOMPILE_DL_PHPCUPS
+
+
+#
+# Object files...
+#
+
+OBJS = phpcups.o
+
+
+#
+# Targets in this directory...
+#
+
+TARGETS = phpcups.so
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Remove object and target files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS)
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I../.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install object and target files...
+#
+
+install: all
+ echo Installing $(TARGETS) in $(PHPDIR)
+ $(INSTALL_DIR) $(PHPDIR)
+ cp $(TARGETS) $(PHPDIR)
+
+
+#
+# phpcups.so
+#
+
+phpcups.so: $(OBJS) ../../Makedefs
+ echo Linking $@...
+ $(DSO) $(DSOFLAGS) -o $@ $(OBJS) -L../../cups -lcups
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/scripting/php/README b/scripting/php/README
new file mode 100644
index 000000000..0cb23f1d5
--- /dev/null
+++ b/scripting/php/README
@@ -0,0 +1,21 @@
+README - 04/08/2003
+-------------------
+
+This directory contains a dynamically loadable CUPS extension
+module for PHP 4. To compile it type:
+
+ make
+
+To install it, type:
+
+ make install
+
+Questions should be reported to the CUPS newsgroups/mailing
+lists at:
+
+ http://www.cups.org/newsgroups.php
+
+Bug reports and enhancement requests can be submitted via the
+form at:
+
+ http://www.cups.org/str.php
diff --git a/scripting/php/config.m4 b/scripting/php/config.m4
new file mode 100644
index 000000000..562e9e27b
--- /dev/null
+++ b/scripting/php/config.m4
@@ -0,0 +1,60 @@
+dnl $Id: config.m4 3867 2003-08-14 22:29:23Z ted $
+dnl config.m4 for extension phpcups
+
+dnl Comments in this file start with the string 'dnl'.
+dnl Remove where necessary. This file will not work
+dnl without editing.
+
+dnl If your extension references something external, use with:
+
+PHP_ARG_WITH(phpcups, for phpcups support,
+dnl Make sure that the comment is aligned:
+[ --with-phpcups Include phpcups support])
+
+dnl Otherwise use enable:
+
+dnl PHP_ARG_ENABLE(phpcups, whether to enable phpcups support,
+dnl Make sure that the comment is aligned:
+dnl [ --enable-phpcups Enable phpcups support])
+
+if test "$PHP_PHPCUPS" != "no"; then
+ dnl Write more examples of tests here...
+
+ dnl # --with-phpcups -> check with-path
+ dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
+ dnl SEARCH_FOR="/include/phpcups.h" # you most likely want to change this
+ dnl if test -r $PHP_PHPCUPS/; then # path given as parameter
+ dnl PHPCUPS_DIR=$PHP_PHPCUPS
+ dnl else # search default path list
+ dnl AC_MSG_CHECKING(for phpcups files in default path)
+ dnl for i in $SEARCH_PATH ; do
+ dnl if test -r $i/$SEARCH_FOR; then
+ dnl PHPCUPS_DIR=$i
+ dnl AC_MSG_RESULT(found in $i)
+ dnl fi
+ dnl done
+ dnl fi
+ dnl
+ dnl if test -z "$PHPCUPS_DIR"; then
+ dnl AC_MSG_RESULT(not found)
+ dnl AC_MSG_ERROR(Please reinstall the phpcups distribution)
+ dnl fi
+
+ dnl # --with-phpcups -> add include path
+ PHP_ADD_INCLUDE(/var/httpd2/web2/cups)
+ PHP_ADD_INCLUDE(/var/httpd2/web2/cups/cups)
+
+ dnl # --with-phpcups -> chech for lib and symbol presence
+ dnl LIBNAME=phpcups # you may want to change this
+ dnl LIBSYMBOL=phpcups # you most likely want to change this
+ dnl old_LIBS=$LIBS
+ dnl LIBS="$LIBS -L$PHPCUPS_DIR/lib -lm -ldl"
+ dnl AC_CHECK_LIB($LIBNAME, $LIBSYMBOL, [AC_DEFINE(HAVE_PHPCUPSLIB,1,[ ])],
+ dnl [AC_MSG_ERROR(wrong phpcups lib version or lib not found)])
+ dnl LIBS=$old_LIBS
+ dnl
+ dnl PHP_SUBST(PHPCUPS_SHARED_LIBADD)
+ PHP_ADD_LIBRARY_WITH_PATH("cups", "/var/httpd2/web2/cups/cups", PHPCUPS_SHARED_LIBADD)
+
+ PHP_EXTENSION(phpcups, $ext_shared)
+fi
diff --git a/scripting/php/php_phpcups.h b/scripting/php/php_phpcups.h
new file mode 100644
index 000000000..ad9771b4d
--- /dev/null
+++ b/scripting/php/php_phpcups.h
@@ -0,0 +1,87 @@
+/*
+ * "$Id$"
+ *
+ * PHP module include file for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifndef PHP_PHPCUPS_H
+# define PHP_PHPCUPS_H
+
+extern zend_module_entry phpcups_module_entry;
+# define phpext_phpcups_ptr &phpcups_module_entry
+
+# ifdef PHP_WIN32
+# define PHP_PHPCUPS_API __declspec(dllexport)
+# else
+# define PHP_PHPCUPS_API
+# endif
+
+# ifdef ZTS
+# include "TSRM.h"
+# endif
+
+PHP_MINIT_FUNCTION(phpcups);
+PHP_MSHUTDOWN_FUNCTION(phpcups);
+PHP_RINIT_FUNCTION(phpcups);
+PHP_RSHUTDOWN_FUNCTION(phpcups);
+PHP_MINFO_FUNCTION(phpcups);
+
+PHP_FUNCTION(confirm_phpcups_compiled);
+PHP_FUNCTION(cups_get_dest_options);
+PHP_FUNCTION(cups_get_dest_list);
+PHP_FUNCTION(cups_get_jobs);
+PHP_FUNCTION(cups_cancel_job);
+PHP_FUNCTION(cups_print_file);
+PHP_FUNCTION(cups_last_error);
+PHP_FUNCTION(cups_get_printer_attributes);
+
+/*
+ Declare any global variables you may need between the BEGIN
+ and END macros here:
+
+ZEND_BEGIN_MODULE_GLOBALS(phpcups)
+ int global_value;
+ char *global_string;
+ZEND_END_MODULE_GLOBALS(phpcups)
+*/
+
+/* In every utility function you add that needs to use variables
+ in php_phpcups_globals, call TSRM_FETCH(); after declaring other
+ variables used by that function, or better yet, pass in TSRMG_CC
+ after the last function argument and declare your utility function
+ with TSRMG_DC after the last declared argument. Always refer to
+ the globals in your function as PHPCUPS_G(variable). You are
+ encouraged to rename these macros something shorter, see
+ examples in any other php module directory.
+*/
+
+# ifdef ZTS
+# define PHPCUPS_G(v) TSRMG(phpcups_globals_id, zend_phpcups_globals *, v)
+# else
+# define PHPCUPS_G(v) (phpcups_globals.v)
+# endif
+
+#endif /* !PHP_PHPCUPS_H */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scripting/php/phpcups.c b/scripting/php/phpcups.c
new file mode 100644
index 000000000..67b175d32
--- /dev/null
+++ b/scripting/php/phpcups.c
@@ -0,0 +1,1357 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: |
+ | |
+ +----------------------------------------------------------------------+
+ */
+
+/*
+ * "$Id$"
+ *
+ * Printing utilities for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2002 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "php_phpcups.h"
+
+/*
+ * Include necessary headers...
+ */
+
+#include "config.h"
+#include "cups.h"
+#include "ipp.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+static int le_result, le_link, le_plink;
+
+
+
+
+/*
+ * Local globals...
+ */
+
+static http_t *cups_server = NULL; /* Current server connection */
+static ipp_status_t last_error = IPP_OK; /* Last IPP error */
+static char authstring[HTTP_MAX_VALUE] = "";
+ /* Authorization string */
+static char pwdstring[33] = ""; /* Last password string */
+
+
+
+
+
+/*
+ * *********************************************************************
+ */
+
+
+
+
+/* If you declare any globals in php_phpcups.h uncomment this:
+ZEND_DECLARE_MODULE_GLOBALS(phpcups)
+*/
+
+/* True global resources - no need for thread safety here */
+static int le_phpcups;
+
+/*
+ * Every user visible function must have an entry in phpcups_functions[].
+ */
+function_entry phpcups_functions[] = {
+ PHP_FE(confirm_phpcups_compiled,NULL)
+ PHP_FE(cups_get_dest_list, NULL)
+ PHP_FE(cups_get_dest_options, NULL)
+ PHP_FE(cups_get_jobs, NULL)
+ PHP_FE(cups_cancel_job, NULL)
+ PHP_FE(cups_last_error, NULL)
+ PHP_FE(cups_print_file, NULL)
+ PHP_FE(cups_get_printer_attributes, NULL)
+ {NULL, NULL, NULL}
+};
+
+
+
+
+zend_module_entry phpcups_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "phpcups",
+ phpcups_functions,
+ PHP_MINIT(phpcups),
+ PHP_MSHUTDOWN(phpcups),
+ PHP_RINIT(phpcups), /* Replace with NULL if there's nothing to do at request start */
+ PHP_RSHUTDOWN(phpcups), /* Replace with NULL if there's nothing to do at request end */
+ PHP_MINFO(phpcups),
+ "0.1", /* Replace with version number for your extension */
+ STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_PHPCUPS
+ZEND_GET_MODULE(phpcups)
+#endif
+
+
+
+
+/* Remove comments and fill if you need to have entries in php.ini
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("phpcups.value", "42", PHP_INI_ALL, OnUpdateInt, global_value, zend_phpcups_globals, phpcups_globals)
+ STD_PHP_INI_ENTRY("phpcups.string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_phpcups_globals, phpcups_globals)
+PHP_INI_END()
+*/
+
+
+
+
+/* Uncomment this function if you have INI entries
+static void php_phpcups_init_globals(zend_phpcups_globals *phpcups_globals)
+{
+ phpcups_globals->value = 0;
+ phpcups_globals->string = NULL;
+}
+*/
+
+
+
+
+PHP_MINIT_FUNCTION(phpcups)
+{
+ /* If you have INI entries, uncomment these lines
+ ZEND_INIT_MODULE_GLOBALS(phpcups, php_phpcups_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
+ */
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(phpcups)
+{
+ /* uncomment this line if you have INI entries
+ UNREGISTER_INI_ENTRIES();
+ */
+ return SUCCESS;
+}
+
+/* Remove if there's nothing to do at request start */
+PHP_RINIT_FUNCTION(phpcups)
+{
+ return SUCCESS;
+}
+
+/* Remove if there's nothing to do at request end */
+PHP_RSHUTDOWN_FUNCTION(phpcups)
+{
+ return SUCCESS;
+}
+
+
+
+PHP_MINFO_FUNCTION(phpcups)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "phpcups support", "enabled");
+ php_info_print_table_end();
+
+ /* Remove comments if you have entries in php.ini
+ DISPLAY_INI_ENTRIES();
+ */
+}
+
+
+
+
+
+
+
+/* Remove the following function when you have succesfully modified config.m4
+ so that your module can be compiled into PHP, it exists only for testing
+ purposes. */
+
+/* Every user-visible function in PHP should document itself in the source */
+PHP_FUNCTION(confirm_phpcups_compiled)
+{
+ char *arg = NULL;
+ int arg_len, len;
+ char string[256];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
+ return;
+ }
+
+ len = sprintf(string, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "phpcups", arg);
+ RETURN_STRINGL(string, len, 1);
+}
+/* The previous line is meant for vim and emacs, so it can correctly fold and
+ unfold functions in source code. See the corresponding marks just before
+ function definition, where the functions purpose is also documented. Please
+ follow this convention for the convenience of others editing your code.
+*/
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * Function: cups_get_dest_options
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: d_name - String - Name of destination.
+ * d_instance - String - Name of instance on destination.
+ *
+ * Returns: Array of option "objects", with each object
+ * containing the members:
+ *
+ * name - String - Option name
+ * value - String - Option value
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_get_dest_options)
+{
+ char *arg = NULL;
+ int arg_len, len;
+
+ zval *new_object;
+
+ zval **d_server,
+ **d_name,
+ **d_instance;
+
+ char c_server[256],
+ c_name[256],
+ c_instance[256];
+
+ char l_server[256],
+ l_name[256],
+ l_instance[256];
+
+ cups_dest_t *dests, *dptr;
+ int num_dests;
+ int i, j;
+
+ array_init(return_value);
+
+ if ((ZEND_NUM_ARGS() != 3) ||
+ (zend_get_parameters_ex(3,&d_server,&d_name,&d_instance) != SUCCESS))
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex( d_server );
+ convert_to_string_ex( d_name );
+ convert_to_string_ex( d_instance );
+
+ /*
+ * Find the dest/instance we want options for.
+ */
+ bzero( c_server, 256 );
+ bzero( c_name, 256 );
+ bzero( c_instance, 256 );
+
+ if ( (char *)(*d_server)->value.str.val != NULL )
+ strcpy( c_server,(char *)(*d_server)->value.str.val );
+ if ( (char *)(*d_name)->value.str.val != NULL )
+ strcpy( c_name,(char *)(*d_name)->value.str.val );
+ if ( (char *)(*d_instance)->value.str.val != NULL )
+ strcpy( c_instance,(char *)(*d_instance)->value.str.val );
+
+
+ if (strlen(c_server))
+ cupsSetServer(c_server);
+
+ num_dests = cupsGetDests(&dests);
+ for (i=0, j = -1; (i < num_dests) && (j < 0); i++)
+ {
+ dptr = &dests[i];
+
+ if (dptr->name == NULL)
+ strcpy( l_name, "" );
+ else
+ strcpy( l_name, dptr->name );
+
+ if (dptr->instance == NULL)
+ strcpy( l_instance, "" );
+ else
+ strcpy( l_instance, dptr->instance );
+
+ if ((!strcmp( l_name, c_name )) &&
+ (!strcmp( l_instance, c_instance )))
+ {
+
+ for (j=0; j < dptr->num_options; j++ )
+ {
+ if ((dptr->options[j].name != NULL) &&
+ (dptr->options[j].value != NULL))
+ {
+ MAKE_STD_ZVAL(new_object);
+ if (object_init(new_object) == SUCCESS)
+ {
+ add_property_string(new_object,"name",dptr->options[j].name, 1 );
+ add_property_string(new_object,"value",dptr->options[j].value,1);
+ add_next_index_zval( return_value, new_object );
+ }
+ }
+ }
+ }
+ }
+ cupsFreeDests(num_dests,dests);
+}
+
+
+
+
+/*
+ * Function: cups_get_dest_list
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: cups server (optional)
+ *
+ * Returns: Array of destination "objects", with each object
+ * containing the members:
+ *
+ * name - String - Name of destination.
+ * instance - String - Name of instance on destination.
+ * is_default - Long - 1 if default printer.
+ * num_options - Long - Number of options for destination.
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_get_dest_list)
+{
+ char *arg = NULL;
+ int arg_len, len;
+
+ zval **z_server;
+ zval *new_object;
+
+ char c_server[256];
+
+ char string[2560];
+ char temp[256];
+
+ cups_dest_t *dests, *dptr;
+ int num_dests;
+ int i;
+
+ /*
+ * Initialize the return array.
+ */
+ array_init(return_value);
+
+ switch (ZEND_NUM_ARGS())
+ {
+ /*
+ * Change servers if passed.
+ */
+ case 1: if (zend_get_parameters_ex(1,&z_server) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex( z_server );
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ {
+ strcpy( c_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer( c_server );
+ }
+ break;
+ }
+
+
+ /*
+ * First get the destination list from the cups server.
+ */
+ num_dests = cupsGetDests(&dests);
+
+ /*
+ * Loop through the list, create and fill in the objects, and
+ * add them to the array.
+ */
+ string[0] = '\0';
+ for (i=0; i < num_dests; i++)
+ {
+ dptr = &dests[i];
+
+ MAKE_STD_ZVAL(new_object);
+ if (object_init(new_object) == SUCCESS)
+ {
+ if (strlen(c_server))
+ add_property_string( new_object, "server", c_server, 1 );
+ else
+ add_property_string( new_object, "server", "", 1 );
+
+ if (dptr->name != NULL)
+ add_property_string( new_object, "name", dptr->name, 1 );
+ else
+ add_property_string( new_object, "name", "", 1 );
+
+ if (dptr->instance != NULL)
+ add_property_string( new_object, "instance", dptr->instance, 1 );
+ else
+ add_property_string( new_object, "instance", "", 1 );
+
+ add_property_long( new_object, "is_default", dptr->is_default );
+ add_property_long( new_object, "num_options", dptr->num_options );
+ add_next_index_zval( return_value, new_object );
+ }
+ }
+
+ /*
+ * free the list .....
+ */
+ cupsFreeDests(num_dests,dests);
+}
+
+
+
+/*
+ * Function: cups_get_jobs
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: server - String - Name or IP of cups server. Blank
+ * for localhost.
+ *
+ * name - String - Name of destination to query.
+ *
+ * user - String - Username to get job list for.
+ * * Optional, default all users
+ *
+ * my_jobs - Long - Show only my jobs
+ * * Optional, default FALSE
+ *
+ * completed - Long - Show completed jobs
+ * * Optional, default FALSE
+ *
+ * Returns: Array of print job "objects", with each object
+ * containing the members:
+ *
+ * id - Long - Job id
+ * dest - String - Name of destination.
+ * title - String - Title of document.
+ * user - String - User who submitted job.
+ * format - String - Document format (MIME type)
+ * state - Long - Current state of the job.
+ * size - Long - Size in bytes of the job.
+ * priority - Long - Job priority.
+ * completed_time - Long - Time job completed (UNIX time).
+ * creation_time - Long - Time job created (UNIX time).
+ * processing_time- Long - Processing time in seconds?
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION( cups_get_jobs )
+{
+ char *arg = NULL;
+
+ int arg_len,
+ len;
+
+ zval *new_object;
+
+ zval **z_server,
+ **z_name,
+ **z_user,
+ **z_myjobs,
+ **z_completed;
+
+ char p_server[256],
+ p_name[256],
+ p_user[256];
+
+ int p_myjobs,
+ p_completed;
+
+ cups_job_t *jobs,
+ *jptr;
+
+ int num_jobs;
+ int i;
+
+ bzero( p_server, 256 );
+ bzero( p_name, 256 );
+ bzero( p_user, 256 );
+ p_myjobs = 0;
+ p_completed = 0;
+
+ /*
+ * Initialize return value.
+ */
+ array_init(return_value);
+
+ /*
+ * Parse params.
+ */
+ switch(ZEND_NUM_ARGS())
+ {
+ /*
+ * server, destination only provided.
+ */
+ case 2:
+ if (zend_get_parameters_ex( 2, &z_server,&z_name ) == SUCCESS)
+ {
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ convert_to_string_ex( z_name );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ }
+ break;
+
+ /*
+ * server, destination and user
+ */
+ case 3:
+ if (zend_get_parameters_ex( 3, &z_server, &z_name,
+ &z_user ) == SUCCESS)
+ {
+ convert_to_string_ex( z_name );
+ convert_to_string_ex( z_user );
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ if ( (char *)(*z_user)->value.str.val != NULL )
+ strcpy( p_user,(char *)(*z_user)->value.str.val );
+ }
+ break;
+
+ /*
+ * server, destination, user, and myjobs
+ */
+ case 4:
+ if (zend_get_parameters_ex( 4, &z_server, &z_name, &z_user,
+ &z_myjobs ) == SUCCESS)
+ {
+ convert_to_string_ex( z_name );
+ convert_to_string_ex( z_user );
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ if ( (char *)(*z_user)->value.str.val != NULL )
+ strcpy( p_user,(char *)(*z_user)->value.str.val );
+
+ convert_to_string_ex( z_myjobs );
+ p_myjobs = strtoul((char *)(*z_myjobs)->value.str.val,NULL,10);
+ }
+ break;
+
+ /*
+ * server, destination, user, myjobs, and completed
+ */
+ case 5:
+ if (zend_get_parameters_ex( 5, &z_server, &z_name, &z_user,
+ &z_myjobs, &z_completed ) == SUCCESS)
+ {
+ convert_to_string_ex( z_name );
+ convert_to_string_ex( z_user );
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ if ( (char *)(*z_user)->value.str.val != NULL )
+ strcpy( p_user,(char *)(*z_user)->value.str.val );
+
+ convert_to_string_ex( z_myjobs );
+ p_myjobs = strtoul((char *)(*z_myjobs)->value.str.val,NULL,10);
+
+ convert_to_string_ex( z_completed);
+ p_completed = strtoul((char *)(*z_completed)->value.str.val,NULL,10);
+ }
+ break;
+ }
+
+ /*
+ * Set the cups server if given.
+ */
+ if (strlen(p_server))
+ cupsSetServer(p_server);
+
+ /*
+ * Set the cups user if given, otherwise get all jobs.
+ */
+ if (strlen(p_user))
+ cupsSetUser(p_user);
+ else
+ cupsSetUser("root");
+
+ /*
+ * Get the jobs list from the CUPS server.
+ */
+ num_jobs = cupsGetJobs(&jobs,p_name,p_myjobs,p_completed);
+
+ /*
+ * Build the array of objects to return.
+ */
+ for (i=0; i < num_jobs; i++)
+ {
+ jptr = &jobs[i];
+
+ MAKE_STD_ZVAL(new_object);
+ if (object_init(new_object) == SUCCESS)
+ {
+ add_property_long(new_object,"id",jptr->id );
+ add_property_string(new_object,"dest",jptr->dest, 1 );
+ add_property_string(new_object,"title",jptr->title, 1 );
+ add_property_string(new_object,"user",jptr->user, 1 );
+ add_property_string(new_object,"format",jptr->format, 1 );
+ add_property_long(new_object,"state",jptr->state );
+ add_property_long(new_object,"size",jptr->size );
+ add_property_long(new_object,"priority",jptr->priority );
+ add_property_long(new_object,"completed_time",jptr->completed_time);
+ add_property_long(new_object,"creation_time",jptr->creation_time);
+ add_property_long(new_object,"processing_time",jptr->processing_time);
+ add_next_index_zval( return_value, new_object );
+ }
+ else
+ {
+ printf("\nError creating new object\n");
+ }
+ }
+ cupsFreeJobs(num_jobs,jobs);
+}
+
+
+
+
+/*
+ * Function: cups_last_error
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: none.
+ *
+ * Returns: error number - Long
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_last_error)
+{
+ static char error[1024];
+
+ zval **z_server;
+ char c_server[256];
+
+ bzero( c_server, 256 );
+
+ switch (ZEND_NUM_ARGS())
+ {
+ /*
+ * Change servers if passed.
+ */
+ case 1: if (zend_get_parameters_ex(1,&z_server) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex( z_server );
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ {
+ strcpy( c_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer( c_server );
+ }
+ break;
+ }
+ sprintf( error,"%d", cupsLastError());
+
+ RETURN_STRINGL(error, strlen(error)+1, 1);
+}
+
+
+
+
+
+
+/*
+ * Function: cups_cancel_job
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: server - String - Name or IP of cups server.
+ * name - String - Name of destination.
+ * job - Long - Job ID to cancel.
+ *
+ * Returns: error number - Long?????????
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_cancel_job)
+{
+ zval **z_server, **z_name, **z_job;
+
+ char p_server[256], p_name[256];
+ int p_job;
+
+ int ret_val = -1;
+
+ /*
+ * Get parameters .....
+ */
+ if ((ZEND_NUM_ARGS() != 3) ||
+ (zend_get_parameters_ex( 3, &z_server, &z_name, &z_job ) != SUCCESS))
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ {
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer(p_server);
+ }
+
+ convert_to_string_ex( z_name );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+
+ convert_to_string_ex( z_job );
+ p_job = strtoul((char *)(*z_job)->value.str.val,NULL,10);
+
+ if (strlen(p_server))
+ cupsSetServer(p_server);
+ cupsSetUser("root");
+
+ /*
+ * Errrr .... Cancel the job ......
+ */
+ ret_val = cupsCancelJob(p_name,p_job);
+
+ RETURN_LONG(ret_val);
+}
+
+
+
+cups_option_t *_phpcups_parse_options( cups_option_t *options,
+ int *num_options, char *param )
+{
+ char name[1024], value[1024];
+
+ sscanf(param,"%1023[^=]=%1023s", name, value );
+
+ if (strlen(name) && strlen(value))
+ {
+ if (options == NULL)
+ {
+ options = (cups_option_t *)emalloc(sizeof(cups_option_t));
+ options->name = (char *)emalloc(strlen(name)+1);
+ options->value = (char *)emalloc(strlen(value)+1);
+ strcpy( options->name, name );
+ strcpy( options->value, value );
+ *num_options++;
+ }
+ else
+ {
+ options = (cups_option_t *)erealloc(options,
+ (*num_options+1) * sizeof(cups_option_t));
+ options[*num_options].name = (char *)emalloc(strlen(name)+1);
+ options[*num_options].value = (char *)emalloc(strlen(value)+1);
+ strcpy( options[*num_options].name, name );
+ strcpy( options[*num_options].value, value );
+ *num_options++;
+ }
+ }
+ return(options);
+}
+
+
+/*
+ * Function: cups_print_file
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: printer - String - Name of destination.
+ * filename - String - Name of file to print (full path).
+ * title - String - Title of document.
+ *
+ * Returns: Job ID - Long
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_print_file)
+{
+ zval **z_server, **z_printer, **z_filename, **z_title,
+ **z_options, **keydata;
+
+ HashTable *param_ht;
+
+ char p_server[256];
+ char p_printer[256];
+ char p_filename[256];
+ char p_title[256];
+
+ char temp[4096];
+ cups_option_t *options = NULL;
+
+ int count, current;
+ int ret_val = -1;
+
+ bzero( p_server, 256 );
+ bzero( p_printer, 256 );
+ bzero( p_filename, 256 );
+ bzero( p_title, 256 );
+ bzero( temp, 4096);
+ current = 0;
+
+ int zend_num_args = ZEND_NUM_ARGS();
+ switch (zend_num_args)
+ {
+ /*
+ * Server / Destination / filename only.
+ */
+ case 3:
+ if (zend_get_parameters_ex( 3, &z_server, &z_printer,
+ &z_filename) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ {
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer(p_server);
+ }
+ convert_to_string_ex( z_printer);
+ if ( (char *)(*z_printer)->value.str.val != NULL )
+ strcpy( p_printer,(char *)(*z_printer)->value.str.val );
+ convert_to_string_ex( z_filename );
+ if ( (char *)(*z_filename)->value.str.val != NULL )
+ strcpy( p_filename,(char *)(*z_filename)->value.str.val );
+ strcpy( p_title,"untitled");
+ break;
+
+ /*
+ * Server, destination, filename and title.
+ */
+ case 4:
+ if (zend_get_parameters_ex( 4, &z_server,
+ &z_printer,
+ &z_filename,
+ &z_title) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ {
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer(p_server);
+ }
+
+ convert_to_string_ex( z_printer);
+ if ( (char *)(*z_printer)->value.str.val != NULL )
+ strcpy( p_printer,(char *)(*z_printer)->value.str.val );
+
+ convert_to_string_ex( z_filename );
+ if ( (char *)(*z_filename)->value.str.val != NULL )
+ strcpy( p_filename,(char *)(*z_filename)->value.str.val );
+
+ convert_to_string_ex( z_title );
+ if ( (char *)(*z_title)->value.str.val != NULL )
+ strcpy( p_title,(char *)(*z_title)->value.str.val );
+
+ _zz_internal_log( "cups_print_file", p_server );
+ _zz_internal_log( "cups_print_file", p_printer );
+ _zz_internal_log( "cups_print_file", p_filename );
+ _zz_internal_log( "cups_print_file", p_title );
+ break;
+
+ /*
+ * Server, destination, filename and title plus printer options.
+ */
+ case 5:
+ if (zend_get_parameters_ex( 5, &z_server,
+ &z_printer,
+ &z_filename,
+ &z_title,
+ &z_options) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex( z_server);
+ if ( (char *)(*z_server)->value.str.val != NULL )
+ {
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ cupsSetServer(p_server);
+ }
+ convert_to_string_ex( z_printer);
+ if ( (char *)(*z_printer)->value.str.val != NULL )
+ strcpy( p_printer,(char *)(*z_printer)->value.str.val );
+ convert_to_string_ex( z_filename );
+ if ( (char *)(*z_filename)->value.str.val != NULL )
+ strcpy( p_filename,(char *)(*z_filename)->value.str.val );
+ convert_to_string_ex( z_title );
+ if ( (char *)(*z_title)->value.str.val != NULL )
+ strcpy( p_title,(char *)(*z_title)->value.str.val );
+
+ _zz_internal_log( "cups_print_file(server)", p_server );
+ _zz_internal_log( "cups_print_file(printer)", p_printer );
+ _zz_internal_log( "cups_print_file(filename)", p_filename );
+ _zz_internal_log( "cups_print_file(title)", p_title );
+
+ /*
+ * Convert options array.
+ */
+ convert_to_array_ex( z_options );
+ param_ht = Z_ARRVAL_PP( z_options );
+ count = zend_hash_num_elements( param_ht );
+ options = emalloc(sizeof(zval **) * count);
+
+ current = 0;
+ zend_hash_internal_pointer_reset(param_ht);
+ for (current=0; current < count; current++)
+ {
+ zend_hash_get_current_data(param_ht,(void **)&keydata);
+ switch(Z_TYPE_PP(keydata))
+ {
+ case IS_STRING:
+ convert_to_string_ex(keydata);
+ strcpy(temp,(char *)(*keydata)->value.str.val );
+ _zz_internal_log( "cups_print_file(option)", temp );
+ options = _phpcups_parse_options( options, &current,
+ temp );
+ break;
+ }
+ zend_hash_move_forward(param_ht);
+ }
+ break;
+
+ default: WRONG_PARAM_COUNT;
+ }
+
+ if (current > 0)
+ {
+
+ bzero(temp,4096);
+ sprintf(temp,"(2) - P: %s F: %s T: %s C: %d", p_printer, p_filename,
+ p_title, current );
+ _zz_internal_log( "cups_print_file", temp );
+ ret_val = cupsPrintFile( p_printer,p_filename,p_title,current,options);
+ for (current=0; current < count; current++)
+ {
+ efree( options[current].name );
+ efree( options[current].value );
+ }
+ efree(options);
+ }
+ else
+ {
+ _zz_internal_log( "cups_print_file", "going to print");
+ ret_val = cupsPrintFile( p_printer,p_filename,p_title,0,NULL );
+ }
+
+ RETURN_LONG(ret_val);
+}
+
+
+int _phpcups_get_printer_status(char *server, int port, char *name );
+
+typedef struct printer_attrs_type
+{
+ char *name;
+ char *value;
+} printer_attrs_t;
+
+
+
+int num_attrs = 0;
+printer_attrs_t *printer_attrs = NULL;
+
+void free_attrs_list(void);
+void _phpcups_free_attrs_list(void);
+
+/*
+ * Function: cups_get_printer_attributes
+ *
+ * Date: 8 April 2002 - TDB
+ *
+ * Parameters: name - String - Name of destination.
+ *
+ * Returns: state - String
+ *
+ * Comments:
+ *
+ */
+PHP_FUNCTION(cups_get_printer_attributes)
+{
+ zval **z_server, **z_port, **z_name;
+
+ zval *new_object;
+
+ char p_server[256], p_name[256];
+ int p_port = 631;
+
+ int i, count;
+
+
+ /*
+ * Initialize return value.
+ */
+ array_init(return_value);
+
+ /*
+ * Get parameters .....
+ */
+ switch(ZEND_NUM_ARGS())
+ {
+ //
+ // Destination name only, assume localhost
+ //
+ case 1:
+ if (zend_get_parameters_ex( 1, &z_name ) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ strcpy( p_server,"localhost" );
+ convert_to_string_ex( z_name );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ break;
+
+ //
+ // Server and estination name only, assume port 631
+ //
+ case 2:
+ if (zend_get_parameters_ex( 2, &z_server, &z_name ) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex( z_server);
+ if ((char *)(*z_server)->value.str.val != NULL)
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ convert_to_string_ex( z_name );
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ break;
+
+ //
+ // Server, destination name and port.
+ //
+ case 3:
+ if(zend_get_parameters_ex(3,&z_server,&z_port,&z_name) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex(z_server);
+ if ((char *)(*z_server)->value.str.val != NULL)
+ strcpy( p_server,(char *)(*z_server)->value.str.val );
+ convert_to_string_ex(z_name);
+ if ( (char *)(*z_name)->value.str.val != NULL )
+ strcpy( p_name,(char *)(*z_name)->value.str.val );
+ convert_to_string_ex(z_port);
+ if ( (char *)(*z_port)->value.str.val != NULL )
+ p_port = atoi( (char *)(*z_name)->value.str.val );
+ break;
+
+ default: WRONG_PARAM_COUNT;
+ }
+
+ printer_attrs = NULL;
+ count = _phpcups_get_printer_status( p_server, p_port, p_name );
+
+ /*
+ * Create an array of objects containing name / value pairs.
+ */
+ for (i=0; i < count; i++)
+ {
+ if ((printer_attrs[i].name != NULL) && (printer_attrs[i].value != NULL))
+ {
+ MAKE_STD_ZVAL(new_object);
+ if (object_init(new_object) == SUCCESS)
+ {
+ add_property_string(new_object,"name",printer_attrs[i].name, 1 );
+ add_property_string(new_object,"value",printer_attrs[i].value, 1 );
+ add_next_index_zval( return_value, new_object );
+ }
+ }
+ }
+ _phpcups_free_attrs_list();
+}
+
+
+
+
+void _phpcups_free_attrs_list(void)
+{
+ int i;
+
+ if (num_attrs < 1)
+ return;
+
+ for ( i=0; i < num_attrs; i++ )
+ {
+ if (printer_attrs[i].name != NULL)
+ efree(printer_attrs[i].name);
+ if (printer_attrs[i].value != NULL)
+ efree(printer_attrs[i].value );
+ }
+ efree(printer_attrs);
+ num_attrs = 0;
+}
+
+
+
+
+
+
+
+int _phpcups_update_attrs_list( char *name, char *value )
+{
+ if (num_attrs < 1)
+ {
+ printer_attrs = (printer_attrs_t *)emalloc(sizeof(printer_attrs_t));
+ printer_attrs->name = (char *)emalloc(strlen(name)+1);
+ printer_attrs->value = (char *)emalloc(strlen(value)+1);
+ strcpy( printer_attrs->name, name );
+ strcpy( printer_attrs->value, value );
+ num_attrs = 1;
+ }
+ else
+ {
+ printer_attrs = (printer_attrs_t *)erealloc(printer_attrs,
+ (num_attrs + 1) * sizeof(printer_attrs_t));
+
+ printer_attrs[num_attrs].name = (char *)emalloc(strlen(name)+1);
+ printer_attrs[num_attrs].value = (char *)emalloc(strlen(value)+1);
+ strcpy( printer_attrs[num_attrs].name, name );
+ strcpy( printer_attrs[num_attrs].value, value );
+ num_attrs++;
+ }
+ return(num_attrs);
+}
+
+
+
+int _phpcups_get_printer_status( char *server, int port, char *name )
+{
+ http_encryption_t encrypt = HTTP_ENCRYPT_IF_REQUESTED;
+
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+
+ char printer_uri[1024];
+ char temp[1024];
+ static char *req_attrs[] = {"printer-state", "printer-state-reason" };
+ int i;
+ FILE *fp;
+
+ if (name == NULL)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (0);
+ }
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if ((cups_server = httpConnectEncrypt(server, port, encrypt)) == NULL)
+ {
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ sprintf(printer_uri, "ipp://localhost/printers/%-s", name );
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri );
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ num_attrs = 0;
+ printer_attrs = NULL;
+
+ if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+
+ if (attr->num_values < 1)
+ continue;
+
+ if (attr->name != NULL &&
+ strcasecmp(attr->name, "printer-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ {
+ strcpy( temp, "unknown" );
+ switch( attr->values[0].integer )
+ {
+ case 3: strcpy( temp, "idle" );
+ break;
+ case 4: strcpy( temp, "processing" );
+ break;
+ case 5: strcpy( temp, "stopped" );
+ break;
+ default: continue;
+ }
+ _phpcups_update_attrs_list( attr->name, temp );
+ }
+ else if (attr->name != NULL &&
+ (attr->value_tag == IPP_TAG_TEXT ||
+ attr->value_tag == IPP_TAG_URI ||
+ attr->value_tag == IPP_TAG_KEYWORD ||
+ attr->value_tag == IPP_TAG_STRING))
+ {
+ for (i=0; i < attr->num_values; i++)
+ _phpcups_update_attrs_list(attr->name, attr->values[i].string.text );
+ }
+ else if (attr->name != NULL &&
+ (attr->value_tag == IPP_TAG_ENUM ||
+ attr->value_tag == IPP_TAG_BOOLEAN ||
+ attr->value_tag == IPP_TAG_INTEGER))
+ {
+ for (i=0; i < attr->num_values; i++)
+ {
+ sprintf(temp,"%-d", attr->values[i].integer );
+ _phpcups_update_attrs_list(attr->name, temp );
+ }
+ }
+ else if (attr->name != NULL &&
+ attr->value_tag == IPP_TAG_RESOLUTION)
+ {
+ for (i=0; i < attr->num_values; i++)
+ {
+ sprintf(temp,"%-dx%-dx%-d",
+ attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units );
+ _phpcups_update_attrs_list(attr->name, temp );
+ }
+ }
+ else if (attr->name != NULL &&
+ attr->value_tag == IPP_TAG_RANGE)
+ {
+ for (i=0; i < attr->num_values; i++)
+ {
+ sprintf(temp,"%d-%d",
+ attr->values[i].range.lower,
+ attr->values[i].range.upper );
+ _phpcups_update_attrs_list(attr->name, temp );
+ }
+ }
+ }
+ ippDelete(response);
+ }
+ else
+ {
+ last_error = IPP_BAD_REQUEST;
+ return(0);
+ }
+ return (num_attrs);
+}
+
+
+void _zz_internal_log( char *func, char *line )
+{
+ FILE *fp;
+
+ if ((fp = fopen("/var/log/cups/project.log","a")) == NULL)
+ return;
+
+ fprintf(fp,"phpcups: %s - %s\n", func, line );
+ fflush(fp);
+ fclose(fp);
+}
+
+
+
+/*
+ * End of "$Id$".
+ */
+
+
+/*
+ */
diff --git a/scripting/php/phpcups.php b/scripting/php/phpcups.php
new file mode 100644
index 000000000..01ce6a8fc
--- /dev/null
+++ b/scripting/php/phpcups.php
@@ -0,0 +1,53 @@
+<?
+//
+// "$Id: phpcups.php 3603 2003-04-11 18:42:52Z mike $"
+//
+// PHP test script for the Common UNIX Printing System (CUPS).
+//
+// Copyright 1997-2003 by Easy Software Products, all rights reserved.
+//
+// These coded instructions, statements, and computer programs are the
+// property of Easy Software Products and are protected by Federal
+// copyright law. Distribution and use rights are outlined in the file
+// "LICENSE.txt" which should have been included with this file. If this
+// file is missing or damaged please contact Easy Software Products
+// at:
+//
+// Attn: CUPS Licensing Information
+// Easy Software Products
+// 44141 Airport View Drive, Suite 204
+// Hollywood, Maryland 20636-3111 USA
+//
+// Voice: (301) 373-9603
+// EMail: cups-info@cups.org
+// WWW: http://www.cups.org
+//
+
+// Make sure the module is loaded...
+if(!extension_loaded('phpcups')) {
+ dl('phpcups.so');
+}
+
+// Get the list of functions in the module...
+$module = 'phpcups';
+$functions = get_extension_funcs($module);
+
+echo "Functions available in the $module extension:<br>\n";
+
+foreach($functions as $func) {
+ echo $func."<br>\n";
+}
+echo "<br>\n";
+
+$function = 'confirm_' . $module . '_compiled';
+if (extension_loaded($module)) {
+ $str = $function($module);
+} else {
+ $str = "Module $module is not compiled into PHP";
+}
+echo "$str\n";
+
+//
+// End of "$Id: phpcups.php 3603 2003-04-11 18:42:52Z mike $".
+//
+?>
diff --git a/standards/pwg5100.1.pdf b/standards/pwg5100.1.pdf
new file mode 100644
index 000000000..80260170f
--- /dev/null
+++ b/standards/pwg5100.1.pdf
Binary files differ
diff --git a/standards/pwg5100.2.pdf b/standards/pwg5100.2.pdf
new file mode 100644
index 000000000..6b0ad3abc
--- /dev/null
+++ b/standards/pwg5100.2.pdf
Binary files differ
diff --git a/standards/pwg5100.3.pdf b/standards/pwg5100.3.pdf
new file mode 100644
index 000000000..0ac46446f
--- /dev/null
+++ b/standards/pwg5100.3.pdf
Binary files differ
diff --git a/standards/pwg5100.4.pdf b/standards/pwg5100.4.pdf
new file mode 100644
index 000000000..3d6c0305f
--- /dev/null
+++ b/standards/pwg5100.4.pdf
Binary files differ
diff --git a/standards/rfc1179.txt b/standards/rfc1179.txt
new file mode 100644
index 000000000..ef59411f7
--- /dev/null
+++ b/standards/rfc1179.txt
@@ -0,0 +1,787 @@
+
+
+
+
+
+
+Network Printing Working Group L. McLaughlin III, Editor
+Request for Comments: 1179 The Wollongong Group
+ August 1990
+
+
+ Line Printer Daemon Protocol
+
+Status of this Memo
+
+ This RFC describes an existing print server protocol widely used on
+ the Internet for communicating between line printer daemons (both
+ clients and servers). This memo is for informational purposes only,
+ and does not specify an Internet standard. Please refer to the
+ current edition of the "IAB Official Protocol Standards" for the
+ standardization state and status of this protocol. Distribution of
+ this memo is unlimited.
+
+1. Introduction
+
+ The Berkeley versions of the Unix(tm) operating system provide line
+ printer spooling with a collection of programs: lpr (assign to
+ queue), lpq (display the queue), lprm (remove from queue), and lpc
+ (control the queue). These programs interact with an autonomous
+ process called the line printer daemon. This RFC describes the
+ protocols with which a line printer daemon client may control
+ printing.
+
+ This memo is based almost entirely on the work of Robert Knight at
+ Princeton University. I gratefully acknowledge his efforts in
+ deciphering the UNIX lpr protocol and producing earlier versions of
+ this document.
+
+2. Model of Printing Environment
+
+ A group of hosts request services from a line printer daemon process
+ running on a host. The services provided by the process are related
+ to printing jobs. A printing job produces output from one file.
+ Each job will have a unique job number which is between 0 and 999,
+ inclusive. The jobs are requested by users which have names. These
+ user names may not start with a digit.
+
+3. Specification of the Protocol
+
+ The specification includes file formats for the control and data
+ files as well as messages used by the protocol.
+
+
+
+
+
+
+McLaughlin [Page 1]
+
+RFC 1179 LPR August 1990
+
+
+3.1 Message formats
+
+ LPR is a a TCP-based protocol. The port on which a line printer
+ daemon listens is 515. The source port must be in the range 721 to
+ 731, inclusive. A line printer daemon responds to commands send to
+ its port. All commands begin with a single octet code, which is a
+ binary number which represents the requested function. The code is
+ immediately followed by the ASCII name of the printer queue name on
+ which the function is to be performed. If there are other operands
+ to the command, they are separated from the printer queue name with
+ white space (ASCII space, horizontal tab, vertical tab, and form
+ feed). The end of the command is indicated with an ASCII line feed
+ character.
+
+4. Diagram Conventions
+
+ The diagrams in the rest of this RFC use these conventions. These
+ diagrams show the format of an octet stream sent to the server. The
+ outermost box represents this stream. Each box within the outermost
+ one shows one portion of the stream. If the contents of the box is
+ two decimal digits, this indicates that the binary 8 bit value is to
+ be used. If the contents is two uppercase letters, this indicates
+ that the corresponding ASCII control character is to be used. An
+ exception to this is that the character SP can be interpreted as
+ white space. (See the preceding section for a definition.) If the
+ contents is a single letter, the ASCII code for this letter must be
+ sent. Otherwise, the contents are intended to be mnemonic of the
+ contents of the field which is a sequence of octets.
+
+5. Daemon commands
+
+ The verbs in the command names should be interpreted as statements
+ made to the daemon. Thus, the command "Print any waiting jobs" is an
+ imperative to the line printer daemon to which it is sent. A new
+ connection must be made for each command to be given to the daemon.
+
+5.1 01 - Print any waiting jobs
+
+ +----+-------+----+
+ | 01 | Queue | LF |
+ +----+-------+----+
+ Command code - 1
+ Operand - Printer queue name
+
+ This command starts the printing process if it not already running.
+
+
+
+
+
+
+McLaughlin [Page 2]
+
+RFC 1179 LPR August 1990
+
+
+5.2 02 - Receive a printer job
+
+ +----+-------+----+
+ | 02 | Queue | LF |
+ +----+-------+----+
+ Command code - 2
+ Operand - Printer queue name
+
+ Receiving a job is controlled by a second level of commands. The
+ daemon is given commands by sending them over the same connection.
+ The commands are described in the next section (6).
+
+ After this command is sent, the client must read an acknowledgement
+ octet from the daemon. A positive acknowledgement is an octet of
+ zero bits. A negative acknowledgement is an octet of any other
+ pattern.
+
+5.3 03 - Send queue state (short)
+
+ +----+-------+----+------+----+
+ | 03 | Queue | SP | List | LF |
+ +----+-------+----+------+----+
+ Command code - 3
+ Operand 1 - Printer queue name
+ Other operands - User names or job numbers
+
+ If the user names or job numbers or both are supplied then only those
+ jobs for those users or with those numbers will be sent.
+
+ The response is an ASCII stream which describes the printer queue.
+ The stream continues until the connection closes. Ends of lines are
+ indicated with ASCII LF control characters. The lines may also
+ contain ASCII HT control characters.
+
+5.4 04 - Send queue state (long)
+
+ +----+-------+----+------+----+
+ | 04 | Queue | SP | List | LF |
+ +----+-------+----+------+----+
+ Command code - 4
+ Operand 1 - Printer queue name
+ Other operands - User names or job numbers
+
+ If the user names or job numbers or both are supplied then only those
+ jobs for those users or with those numbers will be sent.
+
+ The response is an ASCII stream which describes the printer queue.
+ The stream continues until the connection closes. Ends of lines are
+
+
+
+McLaughlin [Page 3]
+
+RFC 1179 LPR August 1990
+
+
+ indicated with ASCII LF control characters. The lines may also
+ contain ASCII HT control characters.
+
+5.5 05 - Remove jobs
+
+ +----+-------+----+-------+----+------+----+
+ | 05 | Queue | SP | Agent | SP | List | LF |
+ +----+-------+----+-------+----+------+----+
+ Command code - 5
+ Operand 1 - Printer queue name
+ Operand 2 - User name making request (the agent)
+ Other operands - User names or job numbers
+
+ This command deletes the print jobs from the specified queue which
+ are listed as the other operands. If only the agent is given, the
+ command is to delete the currently active job. Unless the agent is
+ "root", it is not possible to delete a job which is not owned by the
+ user. This is also the case for specifying user names instead of
+ numbers. That is, agent "root" can delete jobs by user name but no
+ other agents can.
+
+6. Receive job subcommands
+
+ These commands are processed when the line printer daemon has
+ been given the receive job command. The daemon will continue to
+ process commands until the connection is closed.
+
+ After a subcommand is sent, the client must wait for an
+ acknowledgement from the daemon. A positive acknowledgement is an
+ octet of zero bits. A negative acknowledgement is an octet of any
+ other pattern.
+
+ LPR clients SHOULD be able to sent the receive data file and receive
+ control file subcommands in either order. LPR servers MUST be able
+ to receive the control file subcommand first and SHOULD be able to
+ receive the data file subcommand first.
+
+6.1 01 - Abort job
+
+ Command code - 1
+ +----+----+
+ | 01 | LF |
+ +----+----+
+
+ No operands should be supplied. This subcommand will remove any
+ files which have been created during this "Receive job" command.
+
+
+
+
+
+McLaughlin [Page 4]
+
+RFC 1179 LPR August 1990
+
+
+6.2 02 - Receive control file
+
+ +----+-------+----+------+----+
+ | 02 | Count | SP | Name | LF |
+ +----+-------+----+------+----+
+ Command code - 2
+ Operand 1 - Number of bytes in control file
+ Operand 2 - Name of control file
+
+ The control file must be an ASCII stream with the ends of lines
+ indicated by ASCII LF. The total number of bytes in the stream is
+ sent as the first operand. The name of the control file is sent as
+ the second. It should start with ASCII "cfA", followed by a three
+ digit job number, followed by the host name which has constructed the
+ control file. Acknowledgement processing must occur as usual after
+ the command is sent.
+
+ The next "Operand 1" octets over the same TCP connection are the
+ intended contents of the control file. Once all of the contents have
+ been delivered, an octet of zero bits is sent as an indication that
+ the file being sent is complete. A second level of acknowledgement
+ processing must occur at this point.
+
+6.3 03 - Receive data file
+
+ +----+-------+----+------+----+
+ | 03 | Count | SP | Name | LF |
+ +----+-------+----+------+----+
+ Command code - 3
+ Operand 1 - Number of bytes in data file
+ Operand 2 - Name of data file
+
+ The data file may contain any 8 bit values at all. The total number
+ of bytes in the stream may be sent as the first operand, otherwise
+ the field should be cleared to 0. The name of the data file should
+ start with ASCII "dfA". This should be followed by a three digit job
+ number. The job number should be followed by the host name which has
+ constructed the data file. Interpretation of the contents of the
+ data file is determined by the contents of the corresponding control
+ file. If a data file length has been specified, the next "Operand 1"
+ octets over the same TCP connection are the intended contents of the
+ data file. In this case, once all of the contents have been
+ delivered, an octet of zero bits is sent as an indication that the
+ file being sent is complete. A second level of acknowledgement
+ processing must occur at this point.
+
+
+
+
+
+
+McLaughlin [Page 5]
+
+RFC 1179 LPR August 1990
+
+
+7. Control file lines
+
+ This section discusses the format of the lines in the control file
+ which is sent to the line printer daemon.
+
+ Each line of the control file consists of a single, printable ASCII
+ character which represents a function to be performed when the file
+ is printed. Interpretation of these command characters are case-
+ sensitive. The rest of the line after the command character is the
+ command's operand. No leading white space is permitted after the
+ command character. The line ends with an ASCII new line.
+
+ Those commands which have a lower case letter as a command code are
+ used to specify an actual printing request. The commands which use
+ upper case are used to describe parametric values or background
+ conditions.
+
+ Some commands must be included in every control file. These are 'H'
+ (responsible host) and 'P' (responsible user). Additionally, there
+ must be at least one lower case command to produce any output.
+
+7.1 C - Class for banner page
+
+ +---+-------+----+
+ | C | Class | LF |
+ +---+-------+----+
+ Command code - 'C'
+ Operand - Name of class for banner pages
+
+ This command sets the class name to be printed on the banner page.
+ The name must be 31 or fewer octets. The name can be omitted. If it
+ is, the name of the host on which the file is printed will be used.
+ The class is conventionally used to display the host from which the
+ printing job originated. It will be ignored unless the print banner
+ command ('L') is also used.
+
+7.2 H - Host name
+
+ +---+------+----+
+ | H | Host | LF |
+ +---+------+----+
+ Command code - 'H'
+ Operand - Name of host
+
+ This command specifies the name of the host which is to be treated as
+ the source of the print job. The command must be included in the
+ control file. The name of the host must be 31 or fewer octets.
+
+
+
+
+McLaughlin [Page 6]
+
+RFC 1179 LPR August 1990
+
+
+7.3 I - Indent Printing
+
+ +---+-------+----+
+ | I | count | LF |
+ +---+-------+----+
+ Command code - 'I'
+ Operand - Indenting count
+
+ This command specifies that, for files which are printed with the
+ 'f', of columns given. (It is ignored for other output generating
+ commands.) The identing count operand must be all decimal digits.
+
+7.4 J - Job name for banner page
+
+ +---+----------+----+
+ | J | Job name | LF |
+ +---+----------+----+
+ Command code - 'J'
+ Operand - Job name
+
+ This command sets the job name to be printed on the banner page. The
+ name of the job must be 99 or fewer octets. It can be omitted. The
+ job name is conventionally used to display the name of the file or
+ files which were "printed". It will be ignored unless the print
+ banner command ('L') is also used.
+
+7.5 L - Print banner page
+
+ +---+------+----+
+ | L | User | LF |
+ +---+------+----+
+ Command code - 'L'
+ Operand - Name of user for burst pages
+
+ This command causes the banner page to be printed. The user name can
+ be omitted. The class name for banner page and job name for banner
+ page commands must precede this command in the control file to be
+ effective.
+
+7.6 M - Mail When Printed
+
+ +---+------+----+
+ | M | user | LF |
+ +---+------+----+
+ Command code - 'M'
+ Operand - User name
+
+ This entry causes mail to be sent to the user given as the operand at
+
+
+
+McLaughlin [Page 7]
+
+RFC 1179 LPR August 1990
+
+
+ the host specified by the 'H' entry when the printing operation ends
+ (successfully or unsuccessfully).
+
+7.7 N - Name of source file
+
+ +---+------+----+
+ | N | Name | LF |
+ +---+------+----+
+ Command code - 'N'
+ Operand - File name
+
+ This command specifies the name of the file from which the data file
+ was constructed. It is returned on a query and used in printing with
+ the 'p' command when no title has been given. It must be 131 or
+ fewer octets.
+
+7.8 P - User identification
+
+ +---+------+----+
+ | P | Name | LF |
+ +---+------+----+
+ Command code - 'P'
+ Operand - User id
+
+ This command specifies the user identification of the entity
+ requesting the printing job. This command must be included in the
+ control file. The user identification must be 31 or fewer octets.
+
+7.9 S - Symbolic link data
+
+ +---+--------+----+-------+----+
+ | S | device | SP | inode | LF |
+ +---+--------+----+-------+----+
+ Command code - 'S'
+ Operand 1 - Device number
+ Operand 2 - Inode number
+
+ This command is used to record symbolic link data on a Unix system so
+ that changing a file's directory entry after a file is printed will
+ not print the new file. It is ignored if the data file is not
+ symbolically linked.
+
+
+
+
+
+
+
+
+
+
+McLaughlin [Page 8]
+
+RFC 1179 LPR August 1990
+
+
+7.10 T - Title for pr
+
+ +---+-------+----+
+ | T | title | LF |
+ +---+-------+----+
+ Command code - 'T'
+ Operand - Title text
+
+ This command provides a title for a file which is to be printed with
+ either the 'p' command. (It is ignored by all of the other printing
+ commands.) The title must be 79 or fewer octets.
+
+7.11 U - Unlink data file
+
+ +---+------+----+
+ | U | file | LF |
+ +---+------+----+
+ Command code - 'U'
+ Operand - File to unlink
+
+ This command indicates that the specified file is no longer needed.
+ This should only be used for data files.
+
+7.12 W - Width of output
+
+ +---+-------+----+
+ | W | width | LF |
+ +---+-------+----+
+ Command code - 'W'
+ Operand - Width count
+
+ This command limits the output to the specified number of columns for
+ the 'f', 'l', and 'p' commands. (It is ignored for other output
+ generating commands.) The width count operand must be all decimal
+ digits. It may be silently reduced to some lower value. The default
+ value for the width is 132.
+
+7.13 1 - troff R font
+
+ +---+------+----+
+ | 1 | file | LF |
+ +---+------+----+
+ Command code - '1'
+ Operand - File name
+
+ This command specifies the file name for the troff R font. [1] This
+ is the font which is printed using Times Roman by default.
+
+
+
+
+McLaughlin [Page 9]
+
+RFC 1179 LPR August 1990
+
+
+7.14 2 - troff I font
+
+ +---+------+----+
+ | 2 | file | LF |
+ +---+------+----+
+ Command code - '2'
+ Operand - File name
+
+ This command specifies the file name for the troff I font. [1] This
+ is the font which is printed using Times Italic by default.
+
+7.15 3 - troff B font
+
+ +---+------+----+
+ | 3 | file | LF |
+ +---+------+----+
+ Command code - '3'
+ Operand - File name
+
+ This command specifies the file name for the troff B font. [1] This
+ is the font which is printed using Times Bold by default.
+
+7.16 4 - troff S font
+
+ +---+------+----+
+ | 4 | file | LF |
+ +---+------+----+
+ Command code - '4'
+ Operand - File name
+
+ This command specifies the file name for the troff S font. [1] This
+ is the font which is printed using Special Mathematical Font by
+ default.
+
+7.17 c - Plot CIF file
+
+ +---+------+----+
+ | c | file | LF |
+ +---+------+----+
+ Command code - 'c'
+ Operand - File to plot
+
+ This command causes the data file to be plotted, treating the data as
+ CIF (CalTech Intermediate Form) graphics language. [2]
+
+
+
+
+
+
+
+McLaughlin [Page 10]
+
+RFC 1179 LPR August 1990
+
+
+7.18 d - Print DVI file
+
+ +---+------+----+
+ | d | file | LF |
+ +---+------+----+
+ Command code - 'd'
+ Operand - File to print
+
+ This command causes the data file to be printed, treating the data as
+ DVI (TeX output). [3]
+
+7.19 f - Print formatted file
+
+ +---+------+----+
+ | f | file | LF |
+ +---+------+----+
+ Command code - 'f'
+ Operand - File to print
+
+ This command cause the data file to be printed as a plain text file,
+ providing page breaks as necessary. Any ASCII control characters
+ which are not in the following list are discarded: HT, CR, FF, LF,
+ and BS.
+
+7.20 g - Plot file
+
+ +---+------+----+
+ | g | file | LF |
+ +---+------+----+
+ Command code - 'g'
+ Operand - File to plot
+
+ This command causes the data file to be plotted, treating the data as
+ output from the Berkeley Unix plot library. [1]
+
+7.21 k - Reserved for use by Kerberized LPR clients and servers.
+
+7.22 l - Print file leaving control characters
+
+ +---+------+----+
+ | l | file | LF |
+ +---+------+----+
+ Command code - 'l' (lower case L)
+ Operand - File to print
+
+ This command causes the specified data file to printed without
+ filtering the control characters (as is done with the 'f' command).
+
+
+
+
+McLaughlin [Page 11]
+
+RFC 1179 LPR August 1990
+
+
+7.23 n - Print ditroff output file
+
+ +---+------+----+
+ | n | file | LF |
+ +---+------+----+
+ Command code - 'n'
+ Operand - File to print
+
+ This command prints the data file to be printed, treating the data as
+ ditroff output. [4]
+
+7.24 o - Print Postscript output file
+
+ +---+------+----+
+ | o | file | LF |
+ +---+------+----+
+ Command code - 'o'
+ Operand - File to print
+
+ This command prints the data file to be printed, treating the data as
+ standard Postscript input.
+
+7.25 p - Print file with 'pr' format
+
+ +---+------+----+
+ | p | file | LF |
+ +---+------+----+
+ Command code - 'p'
+ Operand - File to print
+
+ This command causes the data file to be printed with a heading, page
+ numbers, and pagination. The heading should include the date and
+ time that printing was started, the title, and a page number
+ identifier followed by the page number. The title is the name of
+ file as specified by the 'N' command, unless the 'T' command (title)
+ has been given. After a page of text has been printed, a new page is
+ started with a new page number. (There is no way to specify the
+ length of the page.)
+
+7.26 r - File to print with FORTRAN carriage control
+
+ +---+------+----+
+ | r | file | LF |
+ +---+------+----+
+ Command code - 'r'
+ Operand - File to print
+
+ This command causes the data file to be printed, interpreting the
+
+
+
+McLaughlin [Page 12]
+
+RFC 1179 LPR August 1990
+
+
+ first column of each line as FORTRAN carriage control. The FORTRAN
+ standard limits this to blank, "1", "0", and "+" carriage controls.
+ Most FORTRAN programmers also expect "-" (triple space) to work as
+ well.
+
+7.27 t - Print troff output file
+
+ +---+------+----+
+ | t | file | LF |
+ +---+------+----+
+ Command code - 't'
+ Operand - File to print
+
+ This command prints the data file as Graphic Systems C/A/T
+ phototypesetter input. [5] This is the standard output of the Unix
+ "troff" command.
+
+7.28 v - Print raster file
+
+ +---+------+----+
+ | v | file | LF |
+ +---+------+----+
+ Command code - 'v'
+ Operand - File to print
+
+ This command prints a Sun raster format file. [6]
+
+7.29 z - Reserved for future use with the Palladium print system.
+
+REFERENCES and BIBLIOGRAPHY
+
+ [1] Computer Science Research Group, "UNIX Programmer's Reference
+ Manual", USENIX, 1986.
+
+ [2] Hon and Sequin, "A Guide to LSI Implementation", XEROX PARC,
+ 1980.
+
+ [3] Knuth, D., "TeX The Program".
+
+ [4] Kernighan, B., "A Typesetter-independent TROFF".
+
+ [5] "Model C/A/T Phototypesetter", Graphic Systems, Inc. Hudson, N.H.
+
+ [6] Sun Microsystems, "Pixrect Reference Manual", Sun Microsystems,
+ Mountain View, CA, 1988.
+
+
+
+
+
+
+McLaughlin [Page 13]
+
+RFC 1179 LPR August 1990
+
+
+Security Considerations
+
+ Security issues are not discussed in this memo.
+
+Author's Address
+
+ Leo J. McLaughlin III
+ The Wollongong Group
+ 1129 San Antonio Road
+ Palo Alto, CA 94303
+
+ Phone: 415-962-7100
+
+ EMail: ljm@twg.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+McLaughlin [Page 14]
+ \ No newline at end of file
diff --git a/standards/rfc1321.txt b/standards/rfc1321.txt
new file mode 100644
index 000000000..68af27d2b
--- /dev/null
+++ b/standards/rfc1321.txt
@@ -0,0 +1,1179 @@
+
+
+
+
+
+
+Network Working Group R. Rivest
+Request for Comments: 1321 MIT Laboratory for Computer Science
+ and RSA Data Security, Inc.
+ April 1992
+
+
+ The MD5 Message-Digest Algorithm
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Acknowlegements
+
+ We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
+ David Chaum, and Noam Nisan for numerous helpful comments and
+ suggestions.
+
+Table of Contents
+
+ 1. Executive Summary 1
+ 2. Terminology and Notation 2
+ 3. MD5 Algorithm Description 3
+ 4. Summary 6
+ 5. Differences Between MD4 and MD5 6
+ References 7
+ APPENDIX A - Reference Implementation 7
+ Security Considerations 21
+ Author's Address 21
+
+1. Executive Summary
+
+ This document describes the MD5 message-digest algorithm. The
+ algorithm takes as input a message of arbitrary length and produces
+ as output a 128-bit "fingerprint" or "message digest" of the input.
+ It is conjectured that it is computationally infeasible to produce
+ two messages having the same message digest, or to produce any
+ message having a given prespecified target message digest. The MD5
+ algorithm is intended for digital signature applications, where a
+ large file must be "compressed" in a secure manner before being
+ encrypted with a private (secret) key under a public-key cryptosystem
+ such as RSA.
+
+
+
+
+
+
+
+Rivest [Page 1]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ The MD5 algorithm is designed to be quite fast on 32-bit machines. In
+ addition, the MD5 algorithm does not require any large substitution
+ tables; the algorithm can be coded quite compactly.
+
+ The MD5 algorithm is an extension of the MD4 message-digest algorithm
+ 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
+ design. MD5 was designed because it was felt that MD4 was perhaps
+ being adopted for use more quickly than justified by the existing
+ critical review; because MD4 was designed to be exceptionally fast,
+ it is "at the edge" in terms of risking successful cryptanalytic
+ attack. MD5 backs off a bit, giving up a little in speed for a much
+ greater likelihood of ultimate security. It incorporates some
+ suggestions made by various reviewers, and contains additional
+ optimizations. The MD5 algorithm is being placed in the public domain
+ for review and possible adoption as a standard.
+
+ For OSI-based applications, MD5's object identifier is
+
+ md5 OBJECT IDENTIFIER ::=
+ iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
+
+ In the X.509 type AlgorithmIdentifier [3], the parameters for MD5
+ should have type NULL.
+
+2. Terminology and Notation
+
+ In this document a "word" is a 32-bit quantity and a "byte" is an
+ eight-bit quantity. A sequence of bits can be interpreted in a
+ natural manner as a sequence of bytes, where each consecutive group
+ of eight bits is interpreted as a byte with the high-order (most
+ significant) bit of each byte listed first. Similarly, a sequence of
+ bytes can be interpreted as a sequence of 32-bit words, where each
+ consecutive group of four bytes is interpreted as a word with the
+ low-order (least significant) byte given first.
+
+ Let x_i denote "x sub i". If the subscript is an expression, we
+ surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+ superscripts (exponentiation), so that x^i denotes x to the i-th
+ power.
+
+ Let the symbol "+" denote addition of words (i.e., modulo-2^32
+ addition). Let X <<< s denote the 32-bit value obtained by circularly
+ shifting (rotating) X left by s bit positions. Let not(X) denote the
+ bit-wise complement of X, and let X v Y denote the bit-wise OR of X
+ and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
+ denote the bit-wise AND of X and Y.
+
+
+
+
+
+Rivest [Page 2]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+3. MD5 Algorithm Description
+
+ We begin by supposing that we have a b-bit message as input, and that
+ we wish to find its message digest. Here b is an arbitrary
+ nonnegative integer; b may be zero, it need not be a multiple of
+ eight, and it may be arbitrarily large. We imagine the bits of the
+ message written down as follows:
+
+ m_0 m_1 ... m_{b-1}
+
+ The following five steps are performed to compute the message digest
+ of the message.
+
+3.1 Step 1. Append Padding Bits
+
+ The message is "padded" (extended) so that its length (in bits) is
+ congruent to 448, modulo 512. That is, the message is extended so
+ that it is just 64 bits shy of being a multiple of 512 bits long.
+ Padding is always performed, even if the length of the message is
+ already congruent to 448, modulo 512.
+
+ Padding is performed as follows: a single "1" bit is appended to the
+ message, and then "0" bits are appended so that the length in bits of
+ the padded message becomes congruent to 448, modulo 512. In all, at
+ least one bit and at most 512 bits are appended.
+
+3.2 Step 2. Append Length
+
+ A 64-bit representation of b (the length of the message before the
+ padding bits were added) is appended to the result of the previous
+ step. In the unlikely event that b is greater than 2^64, then only
+ the low-order 64 bits of b are used. (These bits are appended as two
+ 32-bit words and appended low-order word first in accordance with the
+ previous conventions.)
+
+ At this point the resulting message (after padding with bits and with
+ b) has a length that is an exact multiple of 512 bits. Equivalently,
+ this message has a length that is an exact multiple of 16 (32-bit)
+ words. Let M[0 ... N-1] denote the words of the resulting message,
+ where N is a multiple of 16.
+
+3.3 Step 3. Initialize MD Buffer
+
+ A four-word buffer (A,B,C,D) is used to compute the message digest.
+ Here each of A, B, C, D is a 32-bit register. These registers are
+ initialized to the following values in hexadecimal, low-order bytes
+ first):
+
+
+
+
+Rivest [Page 3]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ word A: 01 23 45 67
+ word B: 89 ab cd ef
+ word C: fe dc ba 98
+ word D: 76 54 32 10
+
+3.4 Step 4. Process Message in 16-Word Blocks
+
+ We first define four auxiliary functions that each take as input
+ three 32-bit words and produce as output one 32-bit word.
+
+ F(X,Y,Z) = XY v not(X) Z
+ G(X,Y,Z) = XZ v Y not(Z)
+ H(X,Y,Z) = X xor Y xor Z
+ I(X,Y,Z) = Y xor (X v not(Z))
+
+ In each bit position F acts as a conditional: if X then Y else Z.
+ The function F could have been defined using + instead of v since XY
+ and not(X)Z will never have 1's in the same bit position.) It is
+ interesting to note that if the bits of X, Y, and Z are independent
+ and unbiased, the each bit of F(X,Y,Z) will be independent and
+ unbiased.
+
+ The functions G, H, and I are similar to the function F, in that they
+ act in "bitwise parallel" to produce their output from the bits of X,
+ Y, and Z, in such a manner that if the corresponding bits of X, Y,
+ and Z are independent and unbiased, then each bit of G(X,Y,Z),
+ H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
+ the function H is the bit-wise "xor" or "parity" function of its
+ inputs.
+
+ This step uses a 64-element table T[1 ... 64] constructed from the
+ sine function. Let T[i] denote the i-th element of the table, which
+ is equal to the integer part of 4294967296 times abs(sin(i)), where i
+ is in radians. The elements of the table are given in the appendix.
+
+ Do the following:
+
+ /* Process each 16-word block. */
+ For i = 0 to N/16-1 do
+
+ /* Copy block i into X. */
+ For j = 0 to 15 do
+ Set X[j] to M[i*16+j].
+ end /* of loop on j */
+
+ /* Save A as AA, B as BB, C as CC, and D as DD. */
+ AA = A
+ BB = B
+
+
+
+Rivest [Page 4]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ CC = C
+ DD = D
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
+ [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
+ [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
+ [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
+ [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
+ [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
+ [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
+ [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
+ [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
+ [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Do the following 16 operations. */
+ [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
+ [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
+ [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
+ [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ A = A + AA
+ B = B + BB
+ C = C + CC
+ D = D + DD
+
+ end /* of loop on i */
+
+
+
+Rivest [Page 5]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+3.5 Step 5. Output
+
+ The message digest produced as output is A, B, C, D. That is, we
+ begin with the low-order byte of A, and end with the high-order byte
+ of D.
+
+ This completes the description of MD5. A reference implementation in
+ C is given in the appendix.
+
+4. Summary
+
+ The MD5 message-digest algorithm is simple to implement, and provides
+ a "fingerprint" or message digest of a message of arbitrary length.
+ It is conjectured that the difficulty of coming up with two messages
+ having the same message digest is on the order of 2^64 operations,
+ and that the difficulty of coming up with any message having a given
+ message digest is on the order of 2^128 operations. The MD5 algorithm
+ has been carefully scrutinized for weaknesses. It is, however, a
+ relatively new algorithm and further security analysis is of course
+ justified, as is the case with any new proposal of this sort.
+
+5. Differences Between MD4 and MD5
+
+ The following are the differences between MD4 and MD5:
+
+ 1. A fourth round has been added.
+
+ 2. Each step now has a unique additive constant.
+
+ 3. The function g in round 2 was changed from (XY v XZ v YZ) to
+ (XZ v Y not(Z)) to make g less symmetric.
+
+ 4. Each step now adds in the result of the previous step. This
+ promotes a faster "avalanche effect".
+
+ 5. The order in which input words are accessed in rounds 2 and
+ 3 is changed, to make these patterns less like each other.
+
+ 6. The shift amounts in each round have been approximately
+ optimized, to yield a faster "avalanche effect." The shifts in
+ different rounds are distinct.
+
+
+
+
+
+
+
+
+
+
+Rivest [Page 6]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+References
+
+ [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and
+ RSA Data Security, Inc., April 1992.
+
+ [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
+ and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
+ Proceedings, pages 303-311, Springer-Verlag, 1991.
+
+ [3] CCITT Recommendation X.509 (1988), "The Directory -
+ Authentication Framework."
+
+APPENDIX A - Reference Implementation
+
+ This appendix contains the following files taken from RSAREF: A
+ Cryptographic Toolkit for Privacy-Enhanced Mail:
+
+ global.h -- global header file
+
+ md5.h -- header file for MD5
+
+ md5c.c -- source code for MD5
+
+ For more information on RSAREF, send email to <rsaref@rsa.com>.
+
+ The appendix also includes the following file:
+
+ mddriver.c -- test driver for MD2, MD4 and MD5
+
+ The driver compiles for MD5 by default but can compile for MD2 or MD4
+ if the symbol MD is defined on the C compiler command line as 2 or 4.
+
+ The implementation is portable and should work on many different
+ plaforms. However, it is not difficult to optimize the implementation
+ on particular platforms, an exercise left to the reader. For example,
+ on "little-endian" platforms where the lowest-addressed byte in a 32-
+ bit word is the least significant and there are no alignment
+ restrictions, the call to Decode in MD5Transform can be replaced with
+ a typecast.
+
+A.1 global.h
+
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+ function argument prototyping.
+The following makes PROTOTYPES default to 0 if it has not already
+
+
+
+Rivest [Page 7]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 0
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+ returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+A.2 md5.h
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+
+
+
+Rivest [Page 8]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+ ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+
+A.3 md5c.c
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include "global.h"
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+
+
+
+Rivest [Page 9]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+ ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+ ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+
+
+
+Rivest [Page 10]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context; /* context */
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+*/
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context; /* context */
+unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+
+
+
+Rivest [Page 11]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+*/
+ if (inputLen >= partLen) {
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD5_CTX *context; /* context */
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+*/
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+
+
+
+Rivest [Page 12]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+
+
+
+Rivest [Page 13]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+
+
+
+Rivest [Page 14]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+*/
+ MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+
+
+
+Rivest [Page 15]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
+
+A.4 mddriver.c
+
+/* MDDRIVER.C - test driver for MD2, MD4 and MD5
+ */
+
+/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+rights reserved.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* The following makes MD default to MD5 if it has not already been
+ defined with C compiler flags.
+ */
+#ifndef MD
+#define MD MD5
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include "global.h"
+#if MD == 2
+#include "md2.h"
+#endif
+#if MD == 4
+
+
+
+Rivest [Page 16]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+#include "md4.h"
+#endif
+#if MD == 5
+#include "md5.h"
+#endif
+
+/* Length of test block, number of test blocks.
+ */
+#define TEST_BLOCK_LEN 1000
+#define TEST_BLOCK_COUNT 1000
+
+static void MDString PROTO_LIST ((char *));
+static void MDTimeTrial PROTO_LIST ((void));
+static void MDTestSuite PROTO_LIST ((void));
+static void MDFile PROTO_LIST ((char *));
+static void MDFilter PROTO_LIST ((void));
+static void MDPrint PROTO_LIST ((unsigned char [16]));
+
+#if MD == 2
+#define MD_CTX MD2_CTX
+#define MDInit MD2Init
+#define MDUpdate MD2Update
+#define MDFinal MD2Final
+#endif
+#if MD == 4
+#define MD_CTX MD4_CTX
+#define MDInit MD4Init
+#define MDUpdate MD4Update
+#define MDFinal MD4Final
+#endif
+#if MD == 5
+#define MD_CTX MD5_CTX
+#define MDInit MD5Init
+#define MDUpdate MD5Update
+#define MDFinal MD5Final
+#endif
+
+/* Main driver.
+
+Arguments (may be any combination):
+ -sstring - digests string
+ -t - runs time trial
+ -x - runs test script
+ filename - digests file
+ (none) - digests standard input
+ */
+int main (argc, argv)
+int argc;
+
+
+
+Rivest [Page 17]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+char *argv[];
+{
+ int i;
+
+ if (argc > 1)
+ for (i = 1; i < argc; i++)
+ if (argv[i][0] == '-' && argv[i][1] == 's')
+ MDString (argv[i] + 2);
+ else if (strcmp (argv[i], "-t") == 0)
+ MDTimeTrial ();
+ else if (strcmp (argv[i], "-x") == 0)
+ MDTestSuite ();
+ else
+ MDFile (argv[i]);
+ else
+ MDFilter ();
+
+ return (0);
+}
+
+/* Digests a string and prints the result.
+ */
+static void MDString (string)
+char *string;
+{
+ MD_CTX context;
+ unsigned char digest[16];
+ unsigned int len = strlen (string);
+
+ MDInit (&context);
+ MDUpdate (&context, string, len);
+ MDFinal (digest, &context);
+
+ printf ("MD%d (\"%s\") = ", MD, string);
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
+ blocks.
+ */
+static void MDTimeTrial ()
+{
+ MD_CTX context;
+ time_t endTime, startTime;
+ unsigned char block[TEST_BLOCK_LEN], digest[16];
+ unsigned int i;
+
+
+
+
+Rivest [Page 18]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ printf
+ ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
+ TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
+
+ /* Initialize block */
+ for (i = 0; i < TEST_BLOCK_LEN; i++)
+ block[i] = (unsigned char)(i & 0xff);
+
+ /* Start timer */
+ time (&startTime);
+
+ /* Digest blocks */
+ MDInit (&context);
+ for (i = 0; i < TEST_BLOCK_COUNT; i++)
+ MDUpdate (&context, block, TEST_BLOCK_LEN);
+ MDFinal (digest, &context);
+
+ /* Stop timer */
+ time (&endTime);
+
+ printf (" done\n");
+ printf ("Digest = ");
+ MDPrint (digest);
+ printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
+ printf
+ ("Speed = %ld bytes/second\n",
+ (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
+}
+
+/* Digests a reference suite of strings and prints the results.
+ */
+static void MDTestSuite ()
+{
+ printf ("MD%d test suite:\n", MD);
+
+ MDString ("");
+ MDString ("a");
+ MDString ("abc");
+ MDString ("message digest");
+ MDString ("abcdefghijklmnopqrstuvwxyz");
+ MDString
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString
+ ("1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+}
+
+/* Digests a file and prints the result.
+
+
+
+Rivest [Page 19]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ */
+static void MDFile (filename)
+char *filename;
+{
+ FILE *file;
+ MD_CTX context;
+ int len;
+ unsigned char buffer[1024], digest[16];
+
+ if ((file = fopen (filename, "rb")) == NULL)
+ printf ("%s can't be opened\n", filename);
+
+ else {
+ MDInit (&context);
+ while (len = fread (buffer, 1, 1024, file))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ fclose (file);
+
+ printf ("MD%d (%s) = ", MD, filename);
+ MDPrint (digest);
+ printf ("\n");
+ }
+}
+
+/* Digests the standard input and prints the result.
+ */
+static void MDFilter ()
+{
+ MD_CTX context;
+ int len;
+ unsigned char buffer[16], digest[16];
+
+ MDInit (&context);
+ while (len = fread (buffer, 1, 16, stdin))
+ MDUpdate (&context, buffer, len);
+ MDFinal (digest, &context);
+
+ MDPrint (digest);
+ printf ("\n");
+}
+
+/* Prints a message digest in hexadecimal.
+ */
+static void MDPrint (digest)
+unsigned char digest[16];
+{
+
+
+
+Rivest [Page 20]
+
+RFC 1321 MD5 Message-Digest Algorithm April 1992
+
+
+ unsigned int i;
+
+ for (i = 0; i < 16; i++)
+ printf ("%02x", digest[i]);
+}
+
+A.5 Test suite
+
+ The MD5 test suite (driver option "-x") should print the following
+ results:
+
+MD5 test suite:
+MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
+MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
+MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
+MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
+MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
+MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
+d174ab98d277d9f5a5611c2c9f419d9f
+MD5 ("123456789012345678901234567890123456789012345678901234567890123456
+78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
+
+Security Considerations
+
+ The level of security discussed in this memo is considered to be
+ sufficient for implementing very high security hybrid digital-
+ signature schemes based on MD5 and a public-key cryptosystem.
+
+Author's Address
+
+ Ronald L. Rivest
+ Massachusetts Institute of Technology
+ Laboratory for Computer Science
+ NE43-324
+ 545 Technology Square
+ Cambridge, MA 02139-1986
+
+ Phone: (617) 253-5880
+ EMail: rivest@theory.lcs.mit.edu
+
+
+
+
+
+
+
+
+
+
+
+
+Rivest [Page 21]
+ \ No newline at end of file
diff --git a/standards/rfc2246.txt b/standards/rfc2246.txt
new file mode 100644
index 000000000..2e838cf5d
--- /dev/null
+++ b/standards/rfc2246.txt
@@ -0,0 +1,4483 @@
+
+
+
+
+
+
+Network Working Group T. Dierks
+Request for Comments: 2246 Certicom
+Category: Standards Track C. Allen
+ Certicom
+ January 1999
+
+
+ The TLS Protocol
+ Version 1.0
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ This document specifies Version 1.0 of the Transport Layer Security
+ (TLS) protocol. The TLS protocol provides communications privacy over
+ the Internet. The protocol allows client/server applications to
+ communicate in a way that is designed to prevent eavesdropping,
+ tampering, or message forgery.
+
+Table of Contents
+
+ 1. Introduction 3
+ 2. Goals 4
+ 3. Goals of this document 5
+ 4. Presentation language 5
+ 4.1. Basic block size 6
+ 4.2. Miscellaneous 6
+ 4.3. Vectors 6
+ 4.4. Numbers 7
+ 4.5. Enumerateds 7
+ 4.6. Constructed types 8
+ 4.6.1. Variants 9
+ 4.7. Cryptographic attributes 10
+ 4.8. Constants 11
+ 5. HMAC and the pseudorandom function 11
+ 6. The TLS Record Protocol 13
+ 6.1. Connection states 14
+
+
+
+Dierks & Allen Standards Track [Page 1]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ 6.2. Record layer 16
+ 6.2.1. Fragmentation 16
+ 6.2.2. Record compression and decompression 17
+ 6.2.3. Record payload protection 18
+ 6.2.3.1. Null or standard stream cipher 19
+ 6.2.3.2. CBC block cipher 19
+ 6.3. Key calculation 21
+ 6.3.1. Export key generation example 22
+ 7. The TLS Handshake Protocol 23
+ 7.1. Change cipher spec protocol 24
+ 7.2. Alert protocol 24
+ 7.2.1. Closure alerts 25
+ 7.2.2. Error alerts 26
+ 7.3. Handshake Protocol overview 29
+ 7.4. Handshake protocol 32
+ 7.4.1. Hello messages 33
+ 7.4.1.1. Hello request 33
+ 7.4.1.2. Client hello 34
+ 7.4.1.3. Server hello 36
+ 7.4.2. Server certificate 37
+ 7.4.3. Server key exchange message 39
+ 7.4.4. Certificate request 41
+ 7.4.5. Server hello done 42
+ 7.4.6. Client certificate 43
+ 7.4.7. Client key exchange message 43
+ 7.4.7.1. RSA encrypted premaster secret message 44
+ 7.4.7.2. Client Diffie-Hellman public value 45
+ 7.4.8. Certificate verify 45
+ 7.4.9. Finished 46
+ 8. Cryptographic computations 47
+ 8.1. Computing the master secret 47
+ 8.1.1. RSA 48
+ 8.1.2. Diffie-Hellman 48
+ 9. Mandatory Cipher Suites 48
+ 10. Application data protocol 48
+ A. Protocol constant values 49
+ A.1. Record layer 49
+ A.2. Change cipher specs message 50
+ A.3. Alert messages 50
+ A.4. Handshake protocol 51
+ A.4.1. Hello messages 51
+ A.4.2. Server authentication and key exchange messages 52
+ A.4.3. Client authentication and key exchange messages 53
+ A.4.4. Handshake finalization message 54
+ A.5. The CipherSuite 54
+ A.6. The Security Parameters 56
+ B. Glossary 57
+ C. CipherSuite definitions 61
+
+
+
+Dierks & Allen Standards Track [Page 2]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ D. Implementation Notes 64
+ D.1. Temporary RSA keys 64
+ D.2. Random Number Generation and Seeding 64
+ D.3. Certificates and authentication 65
+ D.4. CipherSuites 65
+ E. Backward Compatibility With SSL 66
+ E.1. Version 2 client hello 67
+ E.2. Avoiding man-in-the-middle version rollback 68
+ F. Security analysis 69
+ F.1. Handshake protocol 69
+ F.1.1. Authentication and key exchange 69
+ F.1.1.1. Anonymous key exchange 69
+ F.1.1.2. RSA key exchange and authentication 70
+ F.1.1.3. Diffie-Hellman key exchange with authentication 71
+ F.1.2. Version rollback attacks 71
+ F.1.3. Detecting attacks against the handshake protocol 72
+ F.1.4. Resuming sessions 72
+ F.1.5. MD5 and SHA 72
+ F.2. Protecting application data 72
+ F.3. Final notes 73
+ G. Patent Statement 74
+ Security Considerations 75
+ References 75
+ Credits 77
+ Comments 78
+ Full Copyright Statement 80
+
+1. Introduction
+
+ The primary goal of the TLS Protocol is to provide privacy and data
+ integrity between two communicating applications. The protocol is
+ composed of two layers: the TLS Record Protocol and the TLS Handshake
+ Protocol. At the lowest level, layered on top of some reliable
+ transport protocol (e.g., TCP[TCP]), is the TLS Record Protocol. The
+ TLS Record Protocol provides connection security that has two basic
+ properties:
+
+ - The connection is private. Symmetric cryptography is used for
+ data encryption (e.g., DES [DES], RC4 [RC4], etc.) The keys for
+ this symmetric encryption are generated uniquely for each
+ connection and are based on a secret negotiated by another
+ protocol (such as the TLS Handshake Protocol). The Record
+ Protocol can also be used without encryption.
+
+ - The connection is reliable. Message transport includes a message
+ integrity check using a keyed MAC. Secure hash functions (e.g.,
+ SHA, MD5, etc.) are used for MAC computations. The Record
+ Protocol can operate without a MAC, but is generally only used in
+
+
+
+Dierks & Allen Standards Track [Page 3]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ this mode while another protocol is using the Record Protocol as
+ a transport for negotiating security parameters.
+
+ The TLS Record Protocol is used for encapsulation of various higher
+ level protocols. One such encapsulated protocol, the TLS Handshake
+ Protocol, allows the server and client to authenticate each other and
+ to negotiate an encryption algorithm and cryptographic keys before
+ the application protocol transmits or receives its first byte of
+ data. The TLS Handshake Protocol provides connection security that
+ has three basic properties:
+
+ - The peer's identity can be authenticated using asymmetric, or
+ public key, cryptography (e.g., RSA [RSA], DSS [DSS], etc.). This
+ authentication can be made optional, but is generally required
+ for at least one of the peers.
+
+ - The negotiation of a shared secret is secure: the negotiated
+ secret is unavailable to eavesdroppers, and for any authenticated
+ connection the secret cannot be obtained, even by an attacker who
+ can place himself in the middle of the connection.
+
+ - The negotiation is reliable: no attacker can modify the
+ negotiation communication without being detected by the parties
+ to the communication.
+
+ One advantage of TLS is that it is application protocol independent.
+ Higher level protocols can layer on top of the TLS Protocol
+ transparently. The TLS standard, however, does not specify how
+ protocols add security with TLS; the decisions on how to initiate TLS
+ handshaking and how to interpret the authentication certificates
+ exchanged are left up to the judgment of the designers and
+ implementors of protocols which run on top of TLS.
+
+2. Goals
+
+ The goals of TLS Protocol, in order of their priority, are:
+
+ 1. Cryptographic security: TLS should be used to establish a secure
+ connection between two parties.
+
+ 2. Interoperability: Independent programmers should be able to
+ develop applications utilizing TLS that will then be able to
+ successfully exchange cryptographic parameters without knowledge
+ of one another's code.
+
+ 3. Extensibility: TLS seeks to provide a framework into which new
+ public key and bulk encryption methods can be incorporated as
+ necessary. This will also accomplish two sub-goals: to prevent
+
+
+
+Dierks & Allen Standards Track [Page 4]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ the need to create a new protocol (and risking the introduction
+ of possible new weaknesses) and to avoid the need to implement an
+ entire new security library.
+
+ 4. Relative efficiency: Cryptographic operations tend to be highly
+ CPU intensive, particularly public key operations. For this
+ reason, the TLS protocol has incorporated an optional session
+ caching scheme to reduce the number of connections that need to
+ be established from scratch. Additionally, care has been taken to
+ reduce network activity.
+
+3. Goals of this document
+
+ This document and the TLS protocol itself are based on the SSL 3.0
+ Protocol Specification as published by Netscape. The differences
+ between this protocol and SSL 3.0 are not dramatic, but they are
+ significant enough that TLS 1.0 and SSL 3.0 do not interoperate
+ (although TLS 1.0 does incorporate a mechanism by which a TLS
+ implementation can back down to SSL 3.0). This document is intended
+ primarily for readers who will be implementing the protocol and those
+ doing cryptographic analysis of it. The specification has been
+ written with this in mind, and it is intended to reflect the needs of
+ those two groups. For that reason, many of the algorithm-dependent
+ data structures and rules are included in the body of the text (as
+ opposed to in an appendix), providing easier access to them.
+
+ This document is not intended to supply any details of service
+ definition nor interface definition, although it does cover select
+ areas of policy as they are required for the maintenance of solid
+ security.
+
+4. Presentation language
+
+ This document deals with the formatting of data in an external
+ representation. The following very basic and somewhat casually
+ defined presentation syntax will be used. The syntax draws from
+ several sources in its structure. Although it resembles the
+ programming language "C" in its syntax and XDR [XDR] in both its
+ syntax and intent, it would be risky to draw too many parallels. The
+ purpose of this presentation language is to document TLS only, not to
+ have general application beyond that particular goal.
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 5]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+4.1. Basic block size
+
+ The representation of all data items is explicitly specified. The
+ basic data block size is one byte (i.e. 8 bits). Multiple byte data
+ items are concatenations of bytes, from left to right, from top to
+ bottom. From the bytestream a multi-byte item (a numeric in the
+ example) is formed (using C notation) by:
+
+ value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
+ ... | byte[n-1];
+
+ This byte ordering for multi-byte values is the commonplace network
+ byte order or big endian format.
+
+4.2. Miscellaneous
+
+ Comments begin with "/*" and end with "*/".
+
+ Optional components are denoted by enclosing them in "[[ ]]" double
+ brackets.
+
+ Single byte entities containing uninterpreted data are of type
+ opaque.
+
+4.3. Vectors
+
+ A vector (single dimensioned array) is a stream of homogeneous data
+ elements. The size of the vector may be specified at documentation
+ time or left unspecified until runtime. In either case the length
+ declares the number of bytes, not the number of elements, in the
+ vector. The syntax for specifying a new type T' that is a fixed
+ length vector of type T is
+
+ T T'[n];
+
+ Here T' occupies n bytes in the data stream, where n is a multiple of
+ the size of T. The length of the vector is not included in the
+ encoded stream.
+
+ In the following example, Datum is defined to be three consecutive
+ bytes that the protocol does not interpret, while Data is three
+ consecutive Datum, consuming a total of nine bytes.
+
+ opaque Datum[3]; /* three uninterpreted bytes */
+ Datum Data[9]; /* 3 consecutive 3 byte vectors */
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 6]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Variable length vectors are defined by specifying a subrange of legal
+ lengths, inclusively, using the notation <floor..ceiling>. When
+ encoded, the actual length precedes the vector's contents in the byte
+ stream. The length will be in the form of a number consuming as many
+ bytes as required to hold the vector's specified maximum (ceiling)
+ length. A variable length vector with an actual length field of zero
+ is referred to as an empty vector.
+
+ T T'<floor..ceiling>;
+
+ In the following example, mandatory is a vector that must contain
+ between 300 and 400 bytes of type opaque. It can never be empty. The
+ actual length field consumes two bytes, a uint16, sufficient to
+ represent the value 400 (see Section 4.4). On the other hand, longer
+ can represent up to 800 bytes of data, or 400 uint16 elements, and it
+ may be empty. Its encoding will include a two byte actual length
+ field prepended to the vector. The length of an encoded vector must
+ be an even multiple of the length of a single element (for example, a
+ 17 byte vector of uint16 would be illegal).
+
+ opaque mandatory<300..400>;
+ /* length field is 2 bytes, cannot be empty */
+ uint16 longer<0..800>;
+ /* zero to 400 16-bit unsigned integers */
+
+4.4. Numbers
+
+ The basic numeric data type is an unsigned byte (uint8). All larger
+ numeric data types are formed from fixed length series of bytes
+ concatenated as described in Section 4.1 and are also unsigned. The
+ following numeric types are predefined.
+
+ uint8 uint16[2];
+ uint8 uint24[3];
+ uint8 uint32[4];
+ uint8 uint64[8];
+
+ All values, here and elsewhere in the specification, are stored in
+ "network" or "big-endian" order; the uint32 represented by the hex
+ bytes 01 02 03 04 is equivalent to the decimal value 16909060.
+
+4.5. Enumerateds
+
+ An additional sparse data type is available called enum. A field of
+ type enum can only assume the values declared in the definition.
+ Each definition is a different type. Only enumerateds of the same
+ type may be assigned or compared. Every element of an enumerated must
+
+
+
+
+Dierks & Allen Standards Track [Page 7]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ be assigned a value, as demonstrated in the following example. Since
+ the elements of the enumerated are not ordered, they can be assigned
+ any unique value, in any order.
+
+ enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;
+
+ Enumerateds occupy as much space in the byte stream as would its
+ maximal defined ordinal value. The following definition would cause
+ one byte to be used to carry fields of type Color.
+
+ enum { red(3), blue(5), white(7) } Color;
+
+ One may optionally specify a value without its associated tag to
+ force the width definition without defining a superfluous element.
+ In the following example, Taste will consume two bytes in the data
+ stream but can only assume the values 1, 2 or 4.
+
+ enum { sweet(1), sour(2), bitter(4), (32000) } Taste;
+
+ The names of the elements of an enumeration are scoped within the
+ defined type. In the first example, a fully qualified reference to
+ the second element of the enumeration would be Color.blue. Such
+ qualification is not required if the target of the assignment is well
+ specified.
+
+ Color color = Color.blue; /* overspecified, legal */
+ Color color = blue; /* correct, type implicit */
+
+ For enumerateds that are never converted to external representation,
+ the numerical information may be omitted.
+
+ enum { low, medium, high } Amount;
+
+4.6. Constructed types
+
+ Structure types may be constructed from primitive types for
+ convenience. Each specification declares a new, unique type. The
+ syntax for definition is much like that of C.
+
+ struct {
+ T1 f1;
+ T2 f2;
+ ...
+ Tn fn;
+ } [[T]];
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 8]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ The fields within a structure may be qualified using the type's name
+ using a syntax much like that available for enumerateds. For example,
+ T.f2 refers to the second field of the previous declaration.
+ Structure definitions may be embedded.
+
+4.6.1. Variants
+
+ Defined structures may have variants based on some knowledge that is
+ available within the environment. The selector must be an enumerated
+ type that defines the possible variants the structure defines. There
+ must be a case arm for every element of the enumeration declared in
+ the select. The body of the variant structure may be given a label
+ for reference. The mechanism by which the variant is selected at
+ runtime is not prescribed by the presentation language.
+
+ struct {
+ T1 f1;
+ T2 f2;
+ ....
+ Tn fn;
+ select (E) {
+ case e1: Te1;
+ case e2: Te2;
+ ....
+ case en: Ten;
+ } [[fv]];
+ } [[Tv]];
+
+ For example:
+
+ enum { apple, orange } VariantTag;
+ struct {
+ uint16 number;
+ opaque string<0..10>; /* variable length */
+ } V1;
+ struct {
+ uint32 number;
+ opaque string[10]; /* fixed length */
+ } V2;
+ struct {
+ select (VariantTag) { /* value of selector is implicit */
+ case apple: V1; /* VariantBody, tag = apple */
+ case orange: V2; /* VariantBody, tag = orange */
+ } variant_body; /* optional label on variant */
+ } VariantRecord;
+
+ Variant structures may be qualified (narrowed) by specifying a value
+ for the selector prior to the type. For example, a
+
+
+
+Dierks & Allen Standards Track [Page 9]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ orange VariantRecord
+
+ is a narrowed type of a VariantRecord containing a variant_body of
+ type V2.
+
+4.7. Cryptographic attributes
+
+ The four cryptographic operations digital signing, stream cipher
+ encryption, block cipher encryption, and public key encryption are
+ designated digitally-signed, stream-ciphered, block-ciphered, and
+ public-key-encrypted, respectively. A field's cryptographic
+ processing is specified by prepending an appropriate key word
+ designation before the field's type specification. Cryptographic keys
+ are implied by the current session state (see Section 6.1).
+
+ In digital signing, one-way hash functions are used as input for a
+ signing algorithm. A digitally-signed element is encoded as an opaque
+ vector <0..2^16-1>, where the length is specified by the signing
+ algorithm and key.
+
+ In RSA signing, a 36-byte structure of two hashes (one SHA and one
+ MD5) is signed (encrypted with the private key). It is encoded with
+ PKCS #1 block type 0 or type 1 as described in [PKCS1].
+
+ In DSS, the 20 bytes of the SHA hash are run directly through the
+ Digital Signing Algorithm with no additional hashing. This produces
+ two values, r and s. The DSS signature is an opaque vector, as above,
+ the contents of which are the DER encoding of:
+
+ Dss-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+ }
+
+ In stream cipher encryption, the plaintext is exclusive-ORed with an
+ identical amount of output generated from a cryptographically-secure
+ keyed pseudorandom number generator.
+
+ In block cipher encryption, every block of plaintext encrypts to a
+ block of ciphertext. All block cipher encryption is done in CBC
+ (Cipher Block Chaining) mode, and all items which are block-ciphered
+ will be an exact multiple of the cipher block length.
+
+ In public key encryption, a public key algorithm is used to encrypt
+ data in such a way that it can be decrypted only with the matching
+ private key. A public-key-encrypted element is encoded as an opaque
+ vector <0..2^16-1>, where the length is specified by the signing
+ algorithm and key.
+
+
+
+Dierks & Allen Standards Track [Page 10]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ An RSA encrypted value is encoded with PKCS #1 block type 2 as
+ described in [PKCS1].
+
+ In the following example:
+
+ stream-ciphered struct {
+ uint8 field1;
+ uint8 field2;
+ digitally-signed opaque hash[20];
+ } UserType;
+
+ The contents of hash are used as input for the signing algorithm,
+ then the entire structure is encrypted with a stream cipher. The
+ length of this structure, in bytes would be equal to 2 bytes for
+ field1 and field2, plus two bytes for the length of the signature,
+ plus the length of the output of the signing algorithm. This is known
+ due to the fact that the algorithm and key used for the signing are
+ known prior to encoding or decoding this structure.
+
+4.8. Constants
+
+ Typed constants can be defined for purposes of specification by
+ declaring a symbol of the desired type and assigning values to it.
+ Under-specified types (opaque, variable length vectors, and
+ structures that contain opaque) cannot be assigned values. No fields
+ of a multi-element structure or vector may be elided.
+
+ For example,
+
+ struct {
+ uint8 f1;
+ uint8 f2;
+ } Example1;
+
+ Example1 ex1 = {1, 4}; /* assigns f1 = 1, f2 = 4 */
+
+5. HMAC and the pseudorandom function
+
+ A number of operations in the TLS record and handshake layer required
+ a keyed MAC; this is a secure digest of some data protected by a
+ secret. Forging the MAC is infeasible without knowledge of the MAC
+ secret. The construction we use for this operation is known as HMAC,
+ described in [HMAC].
+
+ HMAC can be used with a variety of different hash algorithms. TLS
+ uses it in the handshake with two different algorithms: MD5 and SHA-
+ 1, denoting these as HMAC_MD5(secret, data) and HMAC_SHA(secret,
+
+
+
+
+Dierks & Allen Standards Track [Page 11]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ data). Additional hash algorithms can be defined by cipher suites and
+ used to protect record data, but MD5 and SHA-1 are hard coded into
+ the description of the handshaking for this version of the protocol.
+
+ In addition, a construction is required to do expansion of secrets
+ into blocks of data for the purposes of key generation or validation.
+ This pseudo-random function (PRF) takes as input a secret, a seed,
+ and an identifying label and produces an output of arbitrary length.
+
+ In order to make the PRF as secure as possible, it uses two hash
+ algorithms in a way which should guarantee its security if either
+ algorithm remains secure.
+
+ First, we define a data expansion function, P_hash(secret, data)
+ which uses a single hash function to expand a secret and seed into an
+ arbitrary quantity of output:
+
+ P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
+ HMAC_hash(secret, A(2) + seed) +
+ HMAC_hash(secret, A(3) + seed) + ...
+
+ Where + indicates concatenation.
+
+ A() is defined as:
+ A(0) = seed
+ A(i) = HMAC_hash(secret, A(i-1))
+
+ P_hash can be iterated as many times as is necessary to produce the
+ required quantity of data. For example, if P_SHA-1 was being used to
+ create 64 bytes of data, it would have to be iterated 4 times
+ (through A(4)), creating 80 bytes of output data; the last 16 bytes
+ of the final iteration would then be discarded, leaving 64 bytes of
+ output data.
+
+ TLS's PRF is created by splitting the secret into two halves and
+ using one half to generate data with P_MD5 and the other half to
+ generate data with P_SHA-1, then exclusive-or'ing the outputs of
+ these two expansion functions together.
+
+ S1 and S2 are the two halves of the secret and each is the same
+ length. S1 is taken from the first half of the secret, S2 from the
+ second half. Their length is created by rounding up the length of the
+ overall secret divided by two; thus, if the original secret is an odd
+ number of bytes long, the last byte of S1 will be the same as the
+ first byte of S2.
+
+ L_S = length in bytes of secret;
+ L_S1 = L_S2 = ceil(L_S / 2);
+
+
+
+Dierks & Allen Standards Track [Page 12]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ The secret is partitioned into two halves (with the possibility of
+ one shared byte) as described above, S1 taking the first L_S1 bytes
+ and S2 the last L_S2 bytes.
+
+ The PRF is then defined as the result of mixing the two pseudorandom
+ streams by exclusive-or'ing them together.
+
+ PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
+ P_SHA-1(S2, label + seed);
+
+ The label is an ASCII string. It should be included in the exact form
+ it is given without a length byte or trailing null character. For
+ example, the label "slithy toves" would be processed by hashing the
+ following bytes:
+
+ 73 6C 69 74 68 79 20 74 6F 76 65 73
+
+ Note that because MD5 produces 16 byte outputs and SHA-1 produces 20
+ byte outputs, the boundaries of their internal iterations will not be
+ aligned; to generate a 80 byte output will involve P_MD5 being
+ iterated through A(5), while P_SHA-1 will only iterate through A(4).
+
+6. The TLS Record Protocol
+
+ The TLS Record Protocol is a layered protocol. At each layer,
+ messages may include fields for length, description, and content.
+ The Record Protocol takes messages to be transmitted, fragments the
+ data into manageable blocks, optionally compresses the data, applies
+ a MAC, encrypts, and transmits the result. Received data is
+ decrypted, verified, decompressed, and reassembled, then delivered to
+ higher level clients.
+
+ Four record protocol clients are described in this document: the
+ handshake protocol, the alert protocol, the change cipher spec
+ protocol, and the application data protocol. In order to allow
+ extension of the TLS protocol, additional record types can be
+ supported by the record protocol. Any new record types should
+ allocate type values immediately beyond the ContentType values for
+ the four record types described here (see Appendix A.2). If a TLS
+ implementation receives a record type it does not understand, it
+ should just ignore it. Any protocol designed for use over TLS must be
+ carefully designed to deal with all possible attacks against it.
+ Note that because the type and length of a record are not protected
+ by encryption, care should be take to minimize the value of traffic
+ analysis of these values.
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 13]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+6.1. Connection states
+
+ A TLS connection state is the operating environment of the TLS Record
+ Protocol. It specifies a compression algorithm, encryption algorithm,
+ and MAC algorithm. In addition, the parameters for these algorithms
+ are known: the MAC secret and the bulk encryption keys and IVs for
+ the connection in both the read and the write directions. Logically,
+ there are always four connection states outstanding: the current read
+ and write states, and the pending read and write states. All records
+ are processed under the current read and write states. The security
+ parameters for the pending states can be set by the TLS Handshake
+ Protocol, and the Handshake Protocol can selectively make either of
+ the pending states current, in which case the appropriate current
+ state is disposed of and replaced with the pending state; the pending
+ state is then reinitialized to an empty state. It is illegal to make
+ a state which has not been initialized with security parameters a
+ current state. The initial current state always specifies that no
+ encryption, compression, or MAC will be used.
+
+ The security parameters for a TLS Connection read and write state are
+ set by providing the following values:
+
+ connection end
+ Whether this entity is considered the "client" or the "server" in
+ this connection.
+
+ bulk encryption algorithm
+ An algorithm to be used for bulk encryption. This specification
+ includes the key size of this algorithm, how much of that key is
+ secret, whether it is a block or stream cipher, the block size of
+ the cipher (if appropriate), and whether it is considered an
+ "export" cipher.
+
+ MAC algorithm
+ An algorithm to be used for message authentication. This
+ specification includes the size of the hash which is returned by
+ the MAC algorithm.
+
+ compression algorithm
+ An algorithm to be used for data compression. This specification
+ must include all information the algorithm requires to do
+ compression.
+
+ master secret
+ A 48 byte secret shared between the two peers in the connection.
+
+ client random
+ A 32 byte value provided by the client.
+
+
+
+Dierks & Allen Standards Track [Page 14]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ server random
+ A 32 byte value provided by the server.
+
+ These parameters are defined in the presentation language as:
+
+ enum { server, client } ConnectionEnd;
+
+ enum { null, rc4, rc2, des, 3des, des40 } BulkCipherAlgorithm;
+
+ enum { stream, block } CipherType;
+
+ enum { true, false } IsExportable;
+
+ enum { null, md5, sha } MACAlgorithm;
+
+ enum { null(0), (255) } CompressionMethod;
+
+ /* The algorithms specified in CompressionMethod,
+ BulkCipherAlgorithm, and MACAlgorithm may be added to. */
+
+ struct {
+ ConnectionEnd entity;
+ BulkCipherAlgorithm bulk_cipher_algorithm;
+ CipherType cipher_type;
+ uint8 key_size;
+ uint8 key_material_length;
+ IsExportable is_exportable;
+ MACAlgorithm mac_algorithm;
+ uint8 hash_size;
+ CompressionMethod compression_algorithm;
+ opaque master_secret[48];
+ opaque client_random[32];
+ opaque server_random[32];
+ } SecurityParameters;
+
+ The record layer will use the security parameters to generate the
+ following six items:
+
+ client write MAC secret
+ server write MAC secret
+ client write key
+ server write key
+ client write IV (for block ciphers only)
+ server write IV (for block ciphers only)
+
+ The client write parameters are used by the server when receiving and
+ processing records and vice-versa. The algorithm used for generating
+ these items from the security parameters is described in section 6.3.
+
+
+
+Dierks & Allen Standards Track [Page 15]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Once the security parameters have been set and the keys have been
+ generated, the connection states can be instantiated by making them
+ the current states. These current states must be updated for each
+ record processed. Each connection state includes the following
+ elements:
+
+ compression state
+ The current state of the compression algorithm.
+
+ cipher state
+ The current state of the encryption algorithm. This will consist
+ of the scheduled key for that connection. In addition, for block
+ ciphers running in CBC mode (the only mode specified for TLS),
+ this will initially contain the IV for that connection state and
+ be updated to contain the ciphertext of the last block encrypted
+ or decrypted as records are processed. For stream ciphers, this
+ will contain whatever the necessary state information is to allow
+ the stream to continue to encrypt or decrypt data.
+
+ MAC secret
+ The MAC secret for this connection as generated above.
+
+ sequence number
+ Each connection state contains a sequence number, which is
+ maintained separately for read and write states. The sequence
+ number must be set to zero whenever a connection state is made
+ the active state. Sequence numbers are of type uint64 and may not
+ exceed 2^64-1. A sequence number is incremented after each
+ record: specifically, the first record which is transmitted under
+ a particular connection state should use sequence number 0.
+
+6.2. Record layer
+
+ The TLS Record Layer receives uninterpreted data from higher layers
+ in non-empty blocks of arbitrary size.
+
+6.2.1. Fragmentation
+
+ The record layer fragments information blocks into TLSPlaintext
+ records carrying data in chunks of 2^14 bytes or less. Client message
+ boundaries are not preserved in the record layer (i.e., multiple
+ client messages of the same ContentType may be coalesced into a
+ single TLSPlaintext record, or a single message may be fragmented
+ across several records).
+
+ struct {
+ uint8 major, minor;
+ } ProtocolVersion;
+
+
+
+Dierks & Allen Standards Track [Page 16]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ enum {
+ change_cipher_spec(20), alert(21), handshake(22),
+ application_data(23), (255)
+ } ContentType;
+
+ struct {
+ ContentType type;
+ ProtocolVersion version;
+ uint16 length;
+ opaque fragment[TLSPlaintext.length];
+ } TLSPlaintext;
+
+ type
+ The higher level protocol used to process the enclosed fragment.
+
+ version
+ The version of the protocol being employed. This document
+ describes TLS Version 1.0, which uses the version { 3, 1 }. The
+ version value 3.1 is historical: TLS version 1.0 is a minor
+ modification to the SSL 3.0 protocol, which bears the version
+ value 3.0. (See Appendix A.1).
+
+ length
+ The length (in bytes) of the following TLSPlaintext.fragment.
+ The length should not exceed 2^14.
+
+ fragment
+ The application data. This data is transparent and treated as an
+ independent block to be dealt with by the higher level protocol
+ specified by the type field.
+
+ Note: Data of different TLS Record layer content types may be
+ interleaved. Application data is generally of lower precedence
+ for transmission than other content types.
+
+6.2.2. Record compression and decompression
+
+ All records are compressed using the compression algorithm defined in
+ the current session state. There is always an active compression
+ algorithm; however, initially it is defined as
+ CompressionMethod.null. The compression algorithm translates a
+ TLSPlaintext structure into a TLSCompressed structure. Compression
+ functions are initialized with default state information whenever a
+ connection state is made active.
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 17]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Compression must be lossless and may not increase the content length
+ by more than 1024 bytes. If the decompression function encounters a
+ TLSCompressed.fragment that would decompress to a length in excess of
+ 2^14 bytes, it should report a fatal decompression failure error.
+
+ struct {
+ ContentType type; /* same as TLSPlaintext.type */
+ ProtocolVersion version;/* same as TLSPlaintext.version */
+ uint16 length;
+ opaque fragment[TLSCompressed.length];
+ } TLSCompressed;
+
+ length
+ The length (in bytes) of the following TLSCompressed.fragment.
+ The length should not exceed 2^14 + 1024.
+
+ fragment
+ The compressed form of TLSPlaintext.fragment.
+
+ Note: A CompressionMethod.null operation is an identity operation; no
+ fields are altered.
+
+ Implementation note:
+ Decompression functions are responsible for ensuring that
+ messages cannot cause internal buffer overflows.
+
+6.2.3. Record payload protection
+
+ The encryption and MAC functions translate a TLSCompressed structure
+ into a TLSCiphertext. The decryption functions reverse the process.
+ The MAC of the record also includes a sequence number so that
+ missing, extra or repeated messages are detectable.
+
+ struct {
+ ContentType type;
+ ProtocolVersion version;
+ uint16 length;
+ select (CipherSpec.cipher_type) {
+ case stream: GenericStreamCipher;
+ case block: GenericBlockCipher;
+ } fragment;
+ } TLSCiphertext;
+
+ type
+ The type field is identical to TLSCompressed.type.
+
+ version
+ The version field is identical to TLSCompressed.version.
+
+
+
+Dierks & Allen Standards Track [Page 18]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ length
+ The length (in bytes) of the following TLSCiphertext.fragment.
+ The length may not exceed 2^14 + 2048.
+
+ fragment
+ The encrypted form of TLSCompressed.fragment, with the MAC.
+
+6.2.3.1. Null or standard stream cipher
+
+ Stream ciphers (including BulkCipherAlgorithm.null - see Appendix
+ A.6) convert TLSCompressed.fragment structures to and from stream
+ TLSCiphertext.fragment structures.
+
+ stream-ciphered struct {
+ opaque content[TLSCompressed.length];
+ opaque MAC[CipherSpec.hash_size];
+ } GenericStreamCipher;
+
+ The MAC is generated as:
+
+ HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
+ TLSCompressed.version + TLSCompressed.length +
+ TLSCompressed.fragment));
+
+ where "+" denotes concatenation.
+
+ seq_num
+ The sequence number for this record.
+
+ hash
+ The hashing algorithm specified by
+ SecurityParameters.mac_algorithm.
+
+ Note that the MAC is computed before encryption. The stream cipher
+ encrypts the entire block, including the MAC. For stream ciphers that
+ do not use a synchronization vector (such as RC4), the stream cipher
+ state from the end of one record is simply used on the subsequent
+ packet. If the CipherSuite is TLS_NULL_WITH_NULL_NULL, encryption
+ consists of the identity operation (i.e., the data is not encrypted
+ and the MAC size is zero implying that no MAC is used).
+ TLSCiphertext.length is TLSCompressed.length plus
+ CipherSpec.hash_size.
+
+6.2.3.2. CBC block cipher
+
+ For block ciphers (such as RC2 or DES), the encryption and MAC
+ functions convert TLSCompressed.fragment structures to and from block
+ TLSCiphertext.fragment structures.
+
+
+
+Dierks & Allen Standards Track [Page 19]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ block-ciphered struct {
+ opaque content[TLSCompressed.length];
+ opaque MAC[CipherSpec.hash_size];
+ uint8 padding[GenericBlockCipher.padding_length];
+ uint8 padding_length;
+ } GenericBlockCipher;
+
+ The MAC is generated as described in Section 6.2.3.1.
+
+ padding
+ Padding that is added to force the length of the plaintext to be
+ an integral multiple of the block cipher's block length. The
+ padding may be any length up to 255 bytes long, as long as it
+ results in the TLSCiphertext.length being an integral multiple of
+ the block length. Lengths longer than necessary might be
+ desirable to frustrate attacks on a protocol based on analysis of
+ the lengths of exchanged messages. Each uint8 in the padding data
+ vector must be filled with the padding length value.
+
+ padding_length
+ The padding length should be such that the total size of the
+ GenericBlockCipher structure is a multiple of the cipher's block
+ length. Legal values range from zero to 255, inclusive. This
+ length specifies the length of the padding field exclusive of the
+ padding_length field itself.
+
+ The encrypted data length (TLSCiphertext.length) is one more than the
+ sum of TLSCompressed.length, CipherSpec.hash_size, and
+ padding_length.
+
+ Example: If the block length is 8 bytes, the content length
+ (TLSCompressed.length) is 61 bytes, and the MAC length is 20
+ bytes, the length before padding is 82 bytes. Thus, the
+ padding length modulo 8 must be equal to 6 in order to make
+ the total length an even multiple of 8 bytes (the block
+ length). The padding length can be 6, 14, 22, and so on,
+ through 254. If the padding length were the minimum necessary,
+ 6, the padding would be 6 bytes, each containing the value 6.
+ Thus, the last 8 octets of the GenericBlockCipher before block
+ encryption would be xx 06 06 06 06 06 06 06, where xx is the
+ last octet of the MAC.
+
+ Note: With block ciphers in CBC mode (Cipher Block Chaining) the
+ initialization vector (IV) for the first record is generated with
+ the other keys and secrets when the security parameters are set.
+ The IV for subsequent records is the last ciphertext block from
+ the previous record.
+
+
+
+
+Dierks & Allen Standards Track [Page 20]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+6.3. Key calculation
+
+ The Record Protocol requires an algorithm to generate keys, IVs, and
+ MAC secrets from the security parameters provided by the handshake
+ protocol.
+
+ The master secret is hashed into a sequence of secure bytes, which
+ are assigned to the MAC secrets, keys, and non-export IVs required by
+ the current connection state (see Appendix A.6). CipherSpecs require
+ a client write MAC secret, a server write MAC secret, a client write
+ key, a server write key, a client write IV, and a server write IV,
+ which are generated from the master secret in that order. Unused
+ values are empty.
+
+ When generating keys and MAC secrets, the master secret is used as an
+ entropy source, and the random values provide unencrypted salt
+ material and IVs for exportable ciphers.
+
+ To generate the key material, compute
+
+ key_block = PRF(SecurityParameters.master_secret,
+ "key expansion",
+ SecurityParameters.server_random +
+ SecurityParameters.client_random);
+
+ until enough output has been generated. Then the key_block is
+ partitioned as follows:
+
+ client_write_MAC_secret[SecurityParameters.hash_size]
+ server_write_MAC_secret[SecurityParameters.hash_size]
+ client_write_key[SecurityParameters.key_material_length]
+ server_write_key[SecurityParameters.key_material_length]
+ client_write_IV[SecurityParameters.IV_size]
+ server_write_IV[SecurityParameters.IV_size]
+
+ The client_write_IV and server_write_IV are only generated for non-
+ export block ciphers. For exportable block ciphers, the
+ initialization vectors are generated later, as described below. Any
+ extra key_block material is discarded.
+
+ Implementation note:
+ The cipher spec which is defined in this document which requires
+ the most material is 3DES_EDE_CBC_SHA: it requires 2 x 24 byte
+ keys, 2 x 20 byte MAC secrets, and 2 x 8 byte IVs, for a total of
+ 104 bytes of key material.
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 21]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Exportable encryption algorithms (for which CipherSpec.is_exportable
+ is true) require additional processing as follows to derive their
+ final write keys:
+
+ final_client_write_key =
+ PRF(SecurityParameters.client_write_key,
+ "client write key",
+ SecurityParameters.client_random +
+ SecurityParameters.server_random);
+ final_server_write_key =
+ PRF(SecurityParameters.server_write_key,
+ "server write key",
+ SecurityParameters.client_random +
+ SecurityParameters.server_random);
+
+ Exportable encryption algorithms derive their IVs solely from the
+ random values from the hello messages:
+
+ iv_block = PRF("", "IV block", SecurityParameters.client_random +
+ SecurityParameters.server_random);
+
+ The iv_block is partitioned into two initialization vectors as the
+ key_block was above:
+
+ client_write_IV[SecurityParameters.IV_size]
+ server_write_IV[SecurityParameters.IV_size]
+
+ Note that the PRF is used without a secret in this case: this just
+ means that the secret has a length of zero bytes and contributes
+ nothing to the hashing in the PRF.
+
+6.3.1. Export key generation example
+
+ TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 requires five random bytes for
+ each of the two encryption keys and 16 bytes for each of the MAC
+ keys, for a total of 42 bytes of key material. The PRF output is
+ stored in the key_block. The key_block is partitioned, and the write
+ keys are salted because this is an exportable encryption algorithm.
+
+ key_block = PRF(master_secret,
+ "key expansion",
+ server_random +
+ client_random)[0..41]
+ client_write_MAC_secret = key_block[0..15]
+ server_write_MAC_secret = key_block[16..31]
+ client_write_key = key_block[32..36]
+ server_write_key = key_block[37..41]
+
+
+
+
+Dierks & Allen Standards Track [Page 22]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ final_client_write_key = PRF(client_write_key,
+ "client write key",
+ client_random +
+ server_random)[0..15]
+ final_server_write_key = PRF(server_write_key,
+ "server write key",
+ client_random +
+ server_random)[0..15]
+
+ iv_block = PRF("", "IV block", client_random +
+ server_random)[0..15]
+ client_write_IV = iv_block[0..7]
+ server_write_IV = iv_block[8..15]
+
+7. The TLS Handshake Protocol
+
+ The TLS Handshake Protocol consists of a suite of three sub-protocols
+ which are used to allow peers to agree upon security parameters for
+ the record layer, authenticate themselves, instantiate negotiated
+ security parameters, and report error conditions to each other.
+
+ The Handshake Protocol is responsible for negotiating a session,
+ which consists of the following items:
+
+ session identifier
+ An arbitrary byte sequence chosen by the server to identify an
+ active or resumable session state.
+
+ peer certificate
+ X509v3 [X509] certificate of the peer. This element of the state
+ may be null.
+
+ compression method
+ The algorithm used to compress data prior to encryption.
+
+ cipher spec
+ Specifies the bulk data encryption algorithm (such as null, DES,
+ etc.) and a MAC algorithm (such as MD5 or SHA). It also defines
+ cryptographic attributes such as the hash_size. (See Appendix A.6
+ for formal definition)
+
+ master secret
+ 48-byte secret shared between the client and server.
+
+ is resumable
+ A flag indicating whether the session can be used to initiate new
+ connections.
+
+
+
+
+Dierks & Allen Standards Track [Page 23]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ These items are then used to create security parameters for use by
+ the Record Layer when protecting application data. Many connections
+ can be instantiated using the same session through the resumption
+ feature of the TLS Handshake Protocol.
+
+7.1. Change cipher spec protocol
+
+ The change cipher spec protocol exists to signal transitions in
+ ciphering strategies. The protocol consists of a single message,
+ which is encrypted and compressed under the current (not the pending)
+ connection state. The message consists of a single byte of value 1.
+
+ struct {
+ enum { change_cipher_spec(1), (255) } type;
+ } ChangeCipherSpec;
+
+ The change cipher spec message is sent by both the client and server
+ to notify the receiving party that subsequent records will be
+ protected under the newly negotiated CipherSpec and keys. Reception
+ of this message causes the receiver to instruct the Record Layer to
+ immediately copy the read pending state into the read current state.
+ Immediately after sending this message, the sender should instruct
+ the record layer to make the write pending state the write active
+ state. (See section 6.1.) The change cipher spec message is sent
+ during the handshake after the security parameters have been agreed
+ upon, but before the verifying finished message is sent (see section
+ 7.4.9).
+
+7.2. Alert protocol
+
+ One of the content types supported by the TLS Record layer is the
+ alert type. Alert messages convey the severity of the message and a
+ description of the alert. Alert messages with a level of fatal result
+ in the immediate termination of the connection. In this case, other
+ connections corresponding to the session may continue, but the
+ session identifier must be invalidated, preventing the failed session
+ from being used to establish new connections. Like other messages,
+ alert messages are encrypted and compressed, as specified by the
+ current connection state.
+
+ enum { warning(1), fatal(2), (255) } AlertLevel;
+
+ enum {
+ close_notify(0),
+ unexpected_message(10),
+ bad_record_mac(20),
+ decryption_failed(21),
+ record_overflow(22),
+
+
+
+Dierks & Allen Standards Track [Page 24]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ decompression_failure(30),
+ handshake_failure(40),
+ bad_certificate(42),
+ unsupported_certificate(43),
+ certificate_revoked(44),
+ certificate_expired(45),
+ certificate_unknown(46),
+ illegal_parameter(47),
+ unknown_ca(48),
+ access_denied(49),
+ decode_error(50),
+ decrypt_error(51),
+ export_restriction(60),
+ protocol_version(70),
+ insufficient_security(71),
+ internal_error(80),
+ user_canceled(90),
+ no_renegotiation(100),
+ (255)
+ } AlertDescription;
+
+ struct {
+ AlertLevel level;
+ AlertDescription description;
+ } Alert;
+
+7.2.1. Closure alerts
+
+ The client and the server must share knowledge that the connection is
+ ending in order to avoid a truncation attack. Either party may
+ initiate the exchange of closing messages.
+
+ close_notify
+ This message notifies the recipient that the sender will not send
+ any more messages on this connection. The session becomes
+ unresumable if any connection is terminated without proper
+ close_notify messages with level equal to warning.
+
+ Either party may initiate a close by sending a close_notify alert.
+ Any data received after a closure alert is ignored.
+
+ Each party is required to send a close_notify alert before closing
+ the write side of the connection. It is required that the other party
+ respond with a close_notify alert of its own and close down the
+ connection immediately, discarding any pending writes. It is not
+ required for the initiator of the close to wait for the responding
+ close_notify alert before closing the read side of the connection.
+
+
+
+
+Dierks & Allen Standards Track [Page 25]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ If the application protocol using TLS provides that any data may be
+ carried over the underlying transport after the TLS connection is
+ closed, the TLS implementation must receive the responding
+ close_notify alert before indicating to the application layer that
+ the TLS connection has ended. If the application protocol will not
+ transfer any additional data, but will only close the underlying
+ transport connection, then the implementation may choose to close the
+ transport without waiting for the responding close_notify. No part of
+ this standard should be taken to dictate the manner in which a usage
+ profile for TLS manages its data transport, including when
+ connections are opened or closed.
+
+ NB: It is assumed that closing a connection reliably delivers
+ pending data before destroying the transport.
+
+7.2.2. Error alerts
+
+ Error handling in the TLS Handshake protocol is very simple. When an
+ error is detected, the detecting party sends a message to the other
+ party. Upon transmission or receipt of an fatal alert message, both
+ parties immediately close the connection. Servers and clients are
+ required to forget any session-identifiers, keys, and secrets
+ associated with a failed connection. The following error alerts are
+ defined:
+
+ unexpected_message
+ An inappropriate message was received. This alert is always fatal
+ and should never be observed in communication between proper
+ implementations.
+
+ bad_record_mac
+ This alert is returned if a record is received with an incorrect
+ MAC. This message is always fatal.
+
+ decryption_failed
+ A TLSCiphertext decrypted in an invalid way: either it wasn`t an
+ even multiple of the block length or its padding values, when
+ checked, weren`t correct. This message is always fatal.
+
+ record_overflow
+ A TLSCiphertext record was received which had a length more than
+ 2^14+2048 bytes, or a record decrypted to a TLSCompressed record
+ with more than 2^14+1024 bytes. This message is always fatal.
+
+ decompression_failure
+ The decompression function received improper input (e.g. data
+ that would expand to excessive length). This message is always
+ fatal.
+
+
+
+Dierks & Allen Standards Track [Page 26]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ handshake_failure
+ Reception of a handshake_failure alert message indicates that the
+ sender was unable to negotiate an acceptable set of security
+ parameters given the options available. This is a fatal error.
+
+ bad_certificate
+ A certificate was corrupt, contained signatures that did not
+ verify correctly, etc.
+
+ unsupported_certificate
+ A certificate was of an unsupported type.
+
+ certificate_revoked
+ A certificate was revoked by its signer.
+
+ certificate_expired
+ A certificate has expired or is not currently valid.
+
+ certificate_unknown
+ Some other (unspecified) issue arose in processing the
+ certificate, rendering it unacceptable.
+
+ illegal_parameter
+ A field in the handshake was out of range or inconsistent with
+ other fields. This is always fatal.
+
+ unknown_ca
+ A valid certificate chain or partial chain was received, but the
+ certificate was not accepted because the CA certificate could not
+ be located or couldn`t be matched with a known, trusted CA. This
+ message is always fatal.
+
+ access_denied
+ A valid certificate was received, but when access control was
+ applied, the sender decided not to proceed with negotiation.
+ This message is always fatal.
+
+ decode_error
+ A message could not be decoded because some field was out of the
+ specified range or the length of the message was incorrect. This
+ message is always fatal.
+
+ decrypt_error
+ A handshake cryptographic operation failed, including being
+ unable to correctly verify a signature, decrypt a key exchange,
+ or validate a finished message.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 27]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ export_restriction
+ A negotiation not in compliance with export restrictions was
+ detected; for example, attempting to transfer a 1024 bit
+ ephemeral RSA key for the RSA_EXPORT handshake method. This
+ message is always fatal.
+
+ protocol_version
+ The protocol version the client has attempted to negotiate is
+ recognized, but not supported. (For example, old protocol
+ versions might be avoided for security reasons). This message is
+ always fatal.
+
+ insufficient_security
+ Returned instead of handshake_failure when a negotiation has
+ failed specifically because the server requires ciphers more
+ secure than those supported by the client. This message is always
+ fatal.
+
+ internal_error
+ An internal error unrelated to the peer or the correctness of the
+ protocol makes it impossible to continue (such as a memory
+ allocation failure). This message is always fatal.
+
+ user_canceled
+ This handshake is being canceled for some reason unrelated to a
+ protocol failure. If the user cancels an operation after the
+ handshake is complete, just closing the connection by sending a
+ close_notify is more appropriate. This alert should be followed
+ by a close_notify. This message is generally a warning.
+
+ no_renegotiation
+ Sent by the client in response to a hello request or by the
+ server in response to a client hello after initial handshaking.
+ Either of these would normally lead to renegotiation; when that
+ is not appropriate, the recipient should respond with this alert;
+ at that point, the original requester can decide whether to
+ proceed with the connection. One case where this would be
+ appropriate would be where a server has spawned a process to
+ satisfy a request; the process might receive security parameters
+ (key length, authentication, etc.) at startup and it might be
+ difficult to communicate changes to these parameters after that
+ point. This message is always a warning.
+
+ For all errors where an alert level is not explicitly specified, the
+ sending party may determine at its discretion whether this is a fatal
+ error or not; if an alert with a level of warning is received, the
+
+
+
+
+
+Dierks & Allen Standards Track [Page 28]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ receiving party may decide at its discretion whether to treat this as
+ a fatal error or not. However, all messages which are transmitted
+ with a level of fatal must be treated as fatal messages.
+
+7.3. Handshake Protocol overview
+
+ The cryptographic parameters of the session state are produced by the
+ TLS Handshake Protocol, which operates on top of the TLS Record
+ Layer. When a TLS client and server first start communicating, they
+ agree on a protocol version, select cryptographic algorithms,
+ optionally authenticate each other, and use public-key encryption
+ techniques to generate shared secrets.
+
+ The TLS Handshake Protocol involves the following steps:
+
+ - Exchange hello messages to agree on algorithms, exchange random
+ values, and check for session resumption.
+
+ - Exchange the necessary cryptographic parameters to allow the
+ client and server to agree on a premaster secret.
+
+ - Exchange certificates and cryptographic information to allow the
+ client and server to authenticate themselves.
+
+ - Generate a master secret from the premaster secret and exchanged
+ random values.
+
+ - Provide security parameters to the record layer.
+
+ - Allow the client and server to verify that their peer has
+ calculated the same security parameters and that the handshake
+ occurred without tampering by an attacker.
+
+ Note that higher layers should not be overly reliant on TLS always
+ negotiating the strongest possible connection between two peers:
+ there are a number of ways a man in the middle attacker can attempt
+ to make two entities drop down to the least secure method they
+ support. The protocol has been designed to minimize this risk, but
+ there are still attacks available: for example, an attacker could
+ block access to the port a secure service runs on, or attempt to get
+ the peers to negotiate an unauthenticated connection. The fundamental
+ rule is that higher levels must be cognizant of what their security
+ requirements are and never transmit information over a channel less
+ secure than what they require. The TLS protocol is secure, in that
+ any cipher suite offers its promised level of security: if you
+ negotiate 3DES with a 1024 bit RSA key exchange with a host whose
+ certificate you have verified, you can expect to be that secure.
+
+
+
+
+Dierks & Allen Standards Track [Page 29]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ However, you should never send data over a link encrypted with 40 bit
+ security unless you feel that data is worth no more than the effort
+ required to break that encryption.
+
+ These goals are achieved by the handshake protocol, which can be
+ summarized as follows: The client sends a client hello message to
+ which the server must respond with a server hello message, or else a
+ fatal error will occur and the connection will fail. The client hello
+ and server hello are used to establish security enhancement
+ capabilities between client and server. The client hello and server
+ hello establish the following attributes: Protocol Version, Session
+ ID, Cipher Suite, and Compression Method. Additionally, two random
+ values are generated and exchanged: ClientHello.random and
+ ServerHello.random.
+
+ The actual key exchange uses up to four messages: the server
+ certificate, the server key exchange, the client certificate, and the
+ client key exchange. New key exchange methods can be created by
+ specifying a format for these messages and defining the use of the
+ messages to allow the client and server to agree upon a shared
+ secret. This secret should be quite long; currently defined key
+ exchange methods exchange secrets which range from 48 to 128 bytes in
+ length.
+
+ Following the hello messages, the server will send its certificate,
+ if it is to be authenticated. Additionally, a server key exchange
+ message may be sent, if it is required (e.g. if their server has no
+ certificate, or if its certificate is for signing only). If the
+ server is authenticated, it may request a certificate from the
+ client, if that is appropriate to the cipher suite selected. Now the
+ server will send the server hello done message, indicating that the
+ hello-message phase of the handshake is complete. The server will
+ then wait for a client response. If the server has sent a certificate
+ request message, the client must send the certificate message. The
+ client key exchange message is now sent, and the content of that
+ message will depend on the public key algorithm selected between the
+ client hello and the server hello. If the client has sent a
+ certificate with signing ability, a digitally-signed certificate
+ verify message is sent to explicitly verify the certificate.
+
+ At this point, a change cipher spec message is sent by the client,
+ and the client copies the pending Cipher Spec into the current Cipher
+ Spec. The client then immediately sends the finished message under
+ the new algorithms, keys, and secrets. In response, the server will
+ send its own change cipher spec message, transfer the pending to the
+ current Cipher Spec, and send its finished message under the new
+
+
+
+
+
+Dierks & Allen Standards Track [Page 30]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Cipher Spec. At this point, the handshake is complete and the client
+ and server may begin to exchange application layer data. (See flow
+ chart below.)
+
+ Client Server
+
+ ClientHello -------->
+ ServerHello
+ Certificate*
+ ServerKeyExchange*
+ CertificateRequest*
+ <-------- ServerHelloDone
+ Certificate*
+ ClientKeyExchange
+ CertificateVerify*
+ [ChangeCipherSpec]
+ Finished -------->
+ [ChangeCipherSpec]
+ <-------- Finished
+ Application Data <-------> Application Data
+
+ Fig. 1 - Message flow for a full handshake
+
+ * Indicates optional or situation-dependent messages that are not
+ always sent.
+
+ Note: To help avoid pipeline stalls, ChangeCipherSpec is an
+ independent TLS Protocol content type, and is not actually a TLS
+ handshake message.
+
+ When the client and server decide to resume a previous session or
+ duplicate an existing session (instead of negotiating new security
+ parameters) the message flow is as follows:
+
+ The client sends a ClientHello using the Session ID of the session to
+ be resumed. The server then checks its session cache for a match. If
+ a match is found, and the server is willing to re-establish the
+ connection under the specified session state, it will send a
+ ServerHello with the same Session ID value. At this point, both
+ client and server must send change cipher spec messages and proceed
+ directly to finished messages. Once the re-establishment is complete,
+ the client and server may begin to exchange application layer data.
+ (See flow chart below.) If a Session ID match is not found, the
+ server generates a new session ID and the TLS client and server
+ perform a full handshake.
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 31]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Client Server
+
+ ClientHello -------->
+ ServerHello
+ [ChangeCipherSpec]
+ <-------- Finished
+ [ChangeCipherSpec]
+ Finished -------->
+ Application Data <-------> Application Data
+
+ Fig. 2 - Message flow for an abbreviated handshake
+
+ The contents and significance of each message will be presented in
+ detail in the following sections.
+
+7.4. Handshake protocol
+
+ The TLS Handshake Protocol is one of the defined higher level clients
+ of the TLS Record Protocol. This protocol is used to negotiate the
+ secure attributes of a session. Handshake messages are supplied to
+ the TLS Record Layer, where they are encapsulated within one or more
+ TLSPlaintext structures, which are processed and transmitted as
+ specified by the current active session state.
+
+ enum {
+ hello_request(0), client_hello(1), server_hello(2),
+ certificate(11), server_key_exchange (12),
+ certificate_request(13), server_hello_done(14),
+ certificate_verify(15), client_key_exchange(16),
+ finished(20), (255)
+ } HandshakeType;
+
+ struct {
+ HandshakeType msg_type; /* handshake type */
+ uint24 length; /* bytes in message */
+ select (HandshakeType) {
+ case hello_request: HelloRequest;
+ case client_hello: ClientHello;
+ case server_hello: ServerHello;
+ case certificate: Certificate;
+ case server_key_exchange: ServerKeyExchange;
+ case certificate_request: CertificateRequest;
+ case server_hello_done: ServerHelloDone;
+ case certificate_verify: CertificateVerify;
+ case client_key_exchange: ClientKeyExchange;
+ case finished: Finished;
+ } body;
+ } Handshake;
+
+
+
+Dierks & Allen Standards Track [Page 32]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ The handshake protocol messages are presented below in the order they
+ must be sent; sending handshake messages in an unexpected order
+ results in a fatal error. Unneeded handshake messages can be omitted,
+ however. Note one exception to the ordering: the Certificate message
+ is used twice in the handshake (from server to client, then from
+ client to server), but described only in its first position. The one
+ message which is not bound by these ordering rules in the Hello
+ Request message, which can be sent at any time, but which should be
+ ignored by the client if it arrives in the middle of a handshake.
+
+7.4.1. Hello messages
+
+ The hello phase messages are used to exchange security enhancement
+ capabilities between the client and server. When a new session
+ begins, the Record Layer's connection state encryption, hash, and
+ compression algorithms are initialized to null. The current
+ connection state is used for renegotiation messages.
+
+7.4.1.1. Hello request
+
+ When this message will be sent:
+ The hello request message may be sent by the server at any time.
+
+ Meaning of this message:
+ Hello request is a simple notification that the client should
+ begin the negotiation process anew by sending a client hello
+ message when convenient. This message will be ignored by the
+ client if the client is currently negotiating a session. This
+ message may be ignored by the client if it does not wish to
+ renegotiate a session, or the client may, if it wishes, respond
+ with a no_renegotiation alert. Since handshake messages are
+ intended to have transmission precedence over application data,
+ it is expected that the negotiation will begin before no more
+ than a few records are received from the client. If the server
+ sends a hello request but does not receive a client hello in
+ response, it may close the connection with a fatal alert.
+
+ After sending a hello request, servers should not repeat the request
+ until the subsequent handshake negotiation is complete.
+
+ Structure of this message:
+ struct { } HelloRequest;
+
+ Note: This message should never be included in the message hashes which
+ are maintained throughout the handshake and used in the finished
+ messages and the certificate verify message.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 33]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+7.4.1.2. Client hello
+
+ When this message will be sent:
+ When a client first connects to a server it is required to send
+ the client hello as its first message. The client can also send a
+ client hello in response to a hello request or on its own
+ initiative in order to renegotiate the security parameters in an
+ existing connection.
+
+ Structure of this message:
+ The client hello message includes a random structure, which is
+ used later in the protocol.
+
+ struct {
+ uint32 gmt_unix_time;
+ opaque random_bytes[28];
+ } Random;
+
+ gmt_unix_time
+ The current time and date in standard UNIX 32-bit format (seconds
+ since the midnight starting Jan 1, 1970, GMT) according to the
+ sender's internal clock. Clocks are not required to be set
+ correctly by the basic TLS Protocol; higher level or application
+ protocols may define additional requirements.
+
+ random_bytes
+ 28 bytes generated by a secure random number generator.
+
+ The client hello message includes a variable length session
+ identifier. If not empty, the value identifies a session between the
+ same client and server whose security parameters the client wishes to
+ reuse. The session identifier may be from an earlier connection, this
+ connection, or another currently active connection. The second option
+ is useful if the client only wishes to update the random structures
+ and derived values of a connection, while the third option makes it
+ possible to establish several independent secure connections without
+ repeating the full handshake protocol. These independent connections
+ may occur sequentially or simultaneously; a SessionID becomes valid
+ when the handshake negotiating it completes with the exchange of
+ Finished messages and persists until removed due to aging or because
+ a fatal error was encountered on a connection associated with the
+ session. The actual contents of the SessionID are defined by the
+ server.
+
+ opaque SessionID<0..32>;
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 34]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Warning:
+ Because the SessionID is transmitted without encryption or
+ immediate MAC protection, servers must not place confidential
+ information in session identifiers or let the contents of fake
+ session identifiers cause any breach of security. (Note that the
+ content of the handshake as a whole, including the SessionID, is
+ protected by the Finished messages exchanged at the end of the
+ handshake.)
+
+ The CipherSuite list, passed from the client to the server in the
+ client hello message, contains the combinations of cryptographic
+ algorithms supported by the client in order of the client's
+ preference (favorite choice first). Each CipherSuite defines a key
+ exchange algorithm, a bulk encryption algorithm (including secret key
+ length) and a MAC algorithm. The server will select a cipher suite
+ or, if no acceptable choices are presented, return a handshake
+ failure alert and close the connection.
+
+ uint8 CipherSuite[2]; /* Cryptographic suite selector */
+
+ The client hello includes a list of compression algorithms supported
+ by the client, ordered according to the client's preference.
+
+ enum { null(0), (255) } CompressionMethod;
+
+ struct {
+ ProtocolVersion client_version;
+ Random random;
+ SessionID session_id;
+ CipherSuite cipher_suites<2..2^16-1>;
+ CompressionMethod compression_methods<1..2^8-1>;
+ } ClientHello;
+
+ client_version
+ The version of the TLS protocol by which the client wishes to
+ communicate during this session. This should be the latest
+ (highest valued) version supported by the client. For this
+ version of the specification, the version will be 3.1 (See
+ Appendix E for details about backward compatibility).
+
+ random
+ A client-generated random structure.
+
+ session_id
+ The ID of a session the client wishes to use for this connection.
+ This field should be empty if no session_id is available or the
+ client wishes to generate new security parameters.
+
+
+
+
+Dierks & Allen Standards Track [Page 35]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ cipher_suites
+ This is a list of the cryptographic options supported by the
+ client, with the client's first preference first. If the
+ session_id field is not empty (implying a session resumption
+ request) this vector must include at least the cipher_suite from
+ that session. Values are defined in Appendix A.5.
+
+ compression_methods
+ This is a list of the compression methods supported by the
+ client, sorted by client preference. If the session_id field is
+ not empty (implying a session resumption request) it must include
+ the compression_method from that session. This vector must
+ contain, and all implementations must support,
+ CompressionMethod.null. Thus, a client and server will always be
+ able to agree on a compression method.
+
+ After sending the client hello message, the client waits for a server
+ hello message. Any other handshake message returned by the server
+ except for a hello request is treated as a fatal error.
+
+ Forward compatibility note:
+ In the interests of forward compatibility, it is permitted for a
+ client hello message to include extra data after the compression
+ methods. This data must be included in the handshake hashes, but
+ must otherwise be ignored. This is the only handshake message for
+ which this is legal; for all other messages, the amount of data
+ in the message must match the description of the message
+ precisely.
+
+7.4.1.3. Server hello
+
+ When this message will be sent:
+ The server will send this message in response to a client hello
+ message when it was able to find an acceptable set of algorithms.
+ If it cannot find such a match, it will respond with a handshake
+ failure alert.
+
+ Structure of this message:
+ struct {
+ ProtocolVersion server_version;
+ Random random;
+ SessionID session_id;
+ CipherSuite cipher_suite;
+ CompressionMethod compression_method;
+ } ServerHello;
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 36]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ server_version
+ This field will contain the lower of that suggested by the client
+ in the client hello and the highest supported by the server. For
+ this version of the specification, the version is 3.1 (See
+ Appendix E for details about backward compatibility).
+
+ random
+ This structure is generated by the server and must be different
+ from (and independent of) ClientHello.random.
+
+ session_id
+ This is the identity of the session corresponding to this
+ connection. If the ClientHello.session_id was non-empty, the
+ server will look in its session cache for a match. If a match is
+ found and the server is willing to establish the new connection
+ using the specified session state, the server will respond with
+ the same value as was supplied by the client. This indicates a
+ resumed session and dictates that the parties must proceed
+ directly to the finished messages. Otherwise this field will
+ contain a different value identifying the new session. The server
+ may return an empty session_id to indicate that the session will
+ not be cached and therefore cannot be resumed. If a session is
+ resumed, it must be resumed using the same cipher suite it was
+ originally negotiated with.
+
+ cipher_suite
+ The single cipher suite selected by the server from the list in
+ ClientHello.cipher_suites. For resumed sessions this field is the
+ value from the state of the session being resumed.
+
+ compression_method
+ The single compression algorithm selected by the server from the
+ list in ClientHello.compression_methods. For resumed sessions
+ this field is the value from the resumed session state.
+
+7.4.2. Server certificate
+
+ When this message will be sent:
+ The server must send a certificate whenever the agreed-upon key
+ exchange method is not an anonymous one. This message will always
+ immediately follow the server hello message.
+
+ Meaning of this message:
+ The certificate type must be appropriate for the selected cipher
+ suite's key exchange algorithm, and is generally an X.509v3
+ certificate. It must contain a key which matches the key exchange
+ method, as follows. Unless otherwise specified, the signing
+
+
+
+
+Dierks & Allen Standards Track [Page 37]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ algorithm for the certificate must be the same as the algorithm
+ for the certificate key. Unless otherwise specified, the public
+ key may be of any length.
+
+ Key Exchange Algorithm Certificate Key Type
+
+ RSA RSA public key; the certificate must
+ allow the key to be used for encryption.
+
+ RSA_EXPORT RSA public key of length greater than
+ 512 bits which can be used for signing,
+ or a key of 512 bits or shorter which
+ can be used for either encryption or
+ signing.
+
+ DHE_DSS DSS public key.
+
+ DHE_DSS_EXPORT DSS public key.
+
+ DHE_RSA RSA public key which can be used for
+ signing.
+
+ DHE_RSA_EXPORT RSA public key which can be used for
+ signing.
+
+ DH_DSS Diffie-Hellman key. The algorithm used
+ to sign the certificate should be DSS.
+
+ DH_RSA Diffie-Hellman key. The algorithm used
+ to sign the certificate should be RSA.
+
+ All certificate profiles, key and cryptographic formats are defined
+ by the IETF PKIX working group [PKIX]. When a key usage extension is
+ present, the digitalSignature bit must be set for the key to be
+ eligible for signing, as described above, and the keyEncipherment bit
+ must be present to allow encryption, as described above. The
+ keyAgreement bit must be set on Diffie-Hellman certificates.
+
+ As CipherSuites which specify new key exchange methods are specified
+ for the TLS Protocol, they will imply certificate format and the
+ required encoded keying information.
+
+ Structure of this message:
+ opaque ASN.1Cert<1..2^24-1>;
+
+ struct {
+ ASN.1Cert certificate_list<0..2^24-1>;
+ } Certificate;
+
+
+
+Dierks & Allen Standards Track [Page 38]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ certificate_list
+ This is a sequence (chain) of X.509v3 certificates. The sender's
+ certificate must come first in the list. Each following
+ certificate must directly certify the one preceding it. Because
+ certificate validation requires that root keys be distributed
+ independently, the self-signed certificate which specifies the
+ root certificate authority may optionally be omitted from the
+ chain, under the assumption that the remote end must already
+ possess it in order to validate it in any case.
+
+ The same message type and structure will be used for the client's
+ response to a certificate request message. Note that a client may
+ send no certificates if it does not have an appropriate certificate
+ to send in response to the server's authentication request.
+
+ Note: PKCS #7 [PKCS7] is not used as the format for the certificate
+ vector because PKCS #6 [PKCS6] extended certificates are not
+ used. Also PKCS #7 defines a SET rather than a SEQUENCE, making
+ the task of parsing the list more difficult.
+
+7.4.3. Server key exchange message
+
+ When this message will be sent:
+ This message will be sent immediately after the server
+ certificate message (or the server hello message, if this is an
+ anonymous negotiation).
+
+ The server key exchange message is sent by the server only when
+ the server certificate message (if sent) does not contain enough
+ data to allow the client to exchange a premaster secret. This is
+ true for the following key exchange methods:
+
+ RSA_EXPORT (if the public key in the server certificate is
+ longer than 512 bits)
+ DHE_DSS
+ DHE_DSS_EXPORT
+ DHE_RSA
+ DHE_RSA_EXPORT
+ DH_anon
+
+ It is not legal to send the server key exchange message for the
+ following key exchange methods:
+
+ RSA
+ RSA_EXPORT (when the public key in the server certificate is
+ less than or equal to 512 bits in length)
+ DH_DSS
+ DH_RSA
+
+
+
+Dierks & Allen Standards Track [Page 39]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Meaning of this message:
+ This message conveys cryptographic information to allow the
+ client to communicate the premaster secret: either an RSA public
+ key to encrypt the premaster secret with, or a Diffie-Hellman
+ public key with which the client can complete a key exchange
+ (with the result being the premaster secret.)
+
+ As additional CipherSuites are defined for TLS which include new key
+ exchange algorithms, the server key exchange message will be sent if
+ and only if the certificate type associated with the key exchange
+ algorithm does not provide enough information for the client to
+ exchange a premaster secret.
+
+ Note: According to current US export law, RSA moduli larger than 512
+ bits may not be used for key exchange in software exported from
+ the US. With this message, the larger RSA keys encoded in
+ certificates may be used to sign temporary shorter RSA keys for
+ the RSA_EXPORT key exchange method.
+
+ Structure of this message:
+ enum { rsa, diffie_hellman } KeyExchangeAlgorithm;
+
+ struct {
+ opaque rsa_modulus<1..2^16-1>;
+ opaque rsa_exponent<1..2^16-1>;
+ } ServerRSAParams;
+
+ rsa_modulus
+ The modulus of the server's temporary RSA key.
+
+ rsa_exponent
+ The public exponent of the server's temporary RSA key.
+
+ struct {
+ opaque dh_p<1..2^16-1>;
+ opaque dh_g<1..2^16-1>;
+ opaque dh_Ys<1..2^16-1>;
+ } ServerDHParams; /* Ephemeral DH parameters */
+
+ dh_p
+ The prime modulus used for the Diffie-Hellman operation.
+
+ dh_g
+ The generator used for the Diffie-Hellman operation.
+
+ dh_Ys
+ The server's Diffie-Hellman public value (g^X mod p).
+
+
+
+
+Dierks & Allen Standards Track [Page 40]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ case diffie_hellman:
+ ServerDHParams params;
+ Signature signed_params;
+ case rsa:
+ ServerRSAParams params;
+ Signature signed_params;
+ };
+ } ServerKeyExchange;
+
+ params
+ The server's key exchange parameters.
+
+ signed_params
+ For non-anonymous key exchanges, a hash of the corresponding
+ params value, with the signature appropriate to that hash
+ applied.
+
+ md5_hash
+ MD5(ClientHello.random + ServerHello.random + ServerParams);
+
+ sha_hash
+ SHA(ClientHello.random + ServerHello.random + ServerParams);
+
+ enum { anonymous, rsa, dsa } SignatureAlgorithm;
+
+ select (SignatureAlgorithm)
+ { case anonymous: struct { };
+ case rsa:
+ digitally-signed struct {
+ opaque md5_hash[16];
+ opaque sha_hash[20];
+ };
+ case dsa:
+ digitally-signed struct {
+ opaque sha_hash[20];
+ };
+ } Signature;
+
+7.4.4. Certificate request
+
+ When this message will be sent:
+ A non-anonymous server can optionally request a certificate from
+ the client, if appropriate for the selected cipher suite. This
+ message, if sent, will immediately follow the Server Key Exchange
+ message (if it is sent; otherwise, the Server Certificate
+ message).
+
+
+
+Dierks & Allen Standards Track [Page 41]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Structure of this message:
+ enum {
+ rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
+ (255)
+ } ClientCertificateType;
+
+ opaque DistinguishedName<1..2^16-1>;
+
+ struct {
+ ClientCertificateType certificate_types<1..2^8-1>;
+ DistinguishedName certificate_authorities<3..2^16-1>;
+ } CertificateRequest;
+
+ certificate_types
+ This field is a list of the types of certificates requested,
+ sorted in order of the server's preference.
+
+ certificate_authorities
+ A list of the distinguished names of acceptable certificate
+ authorities. These distinguished names may specify a desired
+ distinguished name for a root CA or for a subordinate CA;
+ thus, this message can be used both to describe known roots
+ and a desired authorization space.
+
+ Note: DistinguishedName is derived from [X509].
+
+ Note: It is a fatal handshake_failure alert for an anonymous server to
+ request client identification.
+
+7.4.5. Server hello done
+
+ When this message will be sent:
+ The server hello done message is sent by the server to indicate
+ the end of the server hello and associated messages. After
+ sending this message the server will wait for a client response.
+
+ Meaning of this message:
+ This message means that the server is done sending messages to
+ support the key exchange, and the client can proceed with its
+ phase of the key exchange.
+
+ Upon receipt of the server hello done message the client should
+ verify that the server provided a valid certificate if required
+ and check that the server hello parameters are acceptable.
+
+ Structure of this message:
+ struct { } ServerHelloDone;
+
+
+
+
+Dierks & Allen Standards Track [Page 42]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+7.4.6. Client certificate
+
+ When this message will be sent:
+ This is the first message the client can send after receiving a
+ server hello done message. This message is only sent if the
+ server requests a certificate. If no suitable certificate is
+ available, the client should send a certificate message
+ containing no certificates. If client authentication is required
+ by the server for the handshake to continue, it may respond with
+ a fatal handshake failure alert. Client certificates are sent
+ using the Certificate structure defined in Section 7.4.2.
+
+ Note: When using a static Diffie-Hellman based key exchange method
+ (DH_DSS or DH_RSA), if client authentication is requested, the
+ Diffie-Hellman group and generator encoded in the client's
+ certificate must match the server specified Diffie-Hellman
+ parameters if the client's parameters are to be used for the key
+ exchange.
+
+7.4.7. Client key exchange message
+
+ When this message will be sent:
+ This message is always sent by the client. It will immediately
+ follow the client certificate message, if it is sent. Otherwise
+ it will be the first message sent by the client after it receives
+ the server hello done message.
+
+ Meaning of this message:
+ With this message, the premaster secret is set, either though
+ direct transmission of the RSA-encrypted secret, or by the
+ transmission of Diffie-Hellman parameters which will allow each
+ side to agree upon the same premaster secret. When the key
+ exchange method is DH_RSA or DH_DSS, client certification has
+ been requested, and the client was able to respond with a
+ certificate which contained a Diffie-Hellman public key whose
+ parameters (group and generator) matched those specified by the
+ server in its certificate, this message will not contain any
+ data.
+
+ Structure of this message:
+ The choice of messages depends on which key exchange method has
+ been selected. See Section 7.4.3 for the KeyExchangeAlgorithm
+ definition.
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ case rsa: EncryptedPreMasterSecret;
+ case diffie_hellman: ClientDiffieHellmanPublic;
+
+
+
+Dierks & Allen Standards Track [Page 43]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ } exchange_keys;
+ } ClientKeyExchange;
+
+7.4.7.1. RSA encrypted premaster secret message
+
+ Meaning of this message:
+ If RSA is being used for key agreement and authentication, the
+ client generates a 48-byte premaster secret, encrypts it using
+ the public key from the server's certificate or the temporary RSA
+ key provided in a server key exchange message, and sends the
+ result in an encrypted premaster secret message. This structure
+ is a variant of the client key exchange message, not a message in
+ itself.
+
+ Structure of this message:
+ struct {
+ ProtocolVersion client_version;
+ opaque random[46];
+ } PreMasterSecret;
+
+ client_version
+ The latest (newest) version supported by the client. This is
+ used to detect version roll-back attacks. Upon receiving the
+ premaster secret, the server should check that this value
+ matches the value transmitted by the client in the client
+ hello message.
+
+ random
+ 46 securely-generated random bytes.
+
+ struct {
+ public-key-encrypted PreMasterSecret pre_master_secret;
+ } EncryptedPreMasterSecret;
+
+ Note: An attack discovered by Daniel Bleichenbacher [BLEI] can be used
+ to attack a TLS server which is using PKCS#1 encoded RSA. The
+ attack takes advantage of the fact that by failing in different
+ ways, a TLS server can be coerced into revealing whether a
+ particular message, when decrypted, is properly PKCS#1 formatted
+ or not.
+
+ The best way to avoid vulnerability to this attack is to treat
+ incorrectly formatted messages in a manner indistinguishable from
+ correctly formatted RSA blocks. Thus, when it receives an
+ incorrectly formatted RSA block, a server should generate a
+ random 48-byte value and proceed using it as the premaster
+ secret. Thus, the server will act identically whether the
+ received RSA block is correctly encoded or not.
+
+
+
+Dierks & Allen Standards Track [Page 44]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ pre_master_secret
+ This random value is generated by the client and is used to
+ generate the master secret, as specified in Section 8.1.
+
+7.4.7.2. Client Diffie-Hellman public value
+
+ Meaning of this message:
+ This structure conveys the client's Diffie-Hellman public value
+ (Yc) if it was not already included in the client's certificate.
+ The encoding used for Yc is determined by the enumerated
+ PublicValueEncoding. This structure is a variant of the client
+ key exchange message, not a message in itself.
+
+ Structure of this message:
+ enum { implicit, explicit } PublicValueEncoding;
+
+ implicit
+ If the client certificate already contains a suitable
+ Diffie-Hellman key, then Yc is implicit and does not need to
+ be sent again. In this case, the Client Key Exchange message
+ will be sent, but will be empty.
+
+ explicit
+ Yc needs to be sent.
+
+ struct {
+ select (PublicValueEncoding) {
+ case implicit: struct { };
+ case explicit: opaque dh_Yc<1..2^16-1>;
+ } dh_public;
+ } ClientDiffieHellmanPublic;
+
+ dh_Yc
+ The client's Diffie-Hellman public value (Yc).
+
+7.4.8. Certificate verify
+
+ When this message will be sent:
+ This message is used to provide explicit verification of a client
+ certificate. This message is only sent following a client
+ certificate that has signing capability (i.e. all certificates
+ except those containing fixed Diffie-Hellman parameters). When
+ sent, it will immediately follow the client key exchange message.
+
+ Structure of this message:
+ struct {
+ Signature signature;
+ } CertificateVerify;
+
+
+
+Dierks & Allen Standards Track [Page 45]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ The Signature type is defined in 7.4.3.
+
+ CertificateVerify.signature.md5_hash
+ MD5(handshake_messages);
+
+ Certificate.signature.sha_hash
+ SHA(handshake_messages);
+
+ Here handshake_messages refers to all handshake messages sent or
+ received starting at client hello up to but not including this
+ message, including the type and length fields of the handshake
+ messages. This is the concatenation of all the Handshake structures
+ as defined in 7.4 exchanged thus far.
+
+7.4.9. Finished
+
+ When this message will be sent:
+ A finished message is always sent immediately after a change
+ cipher spec message to verify that the key exchange and
+ authentication processes were successful. It is essential that a
+ change cipher spec message be received between the other
+ handshake messages and the Finished message.
+
+ Meaning of this message:
+ The finished message is the first protected with the just-
+ negotiated algorithms, keys, and secrets. Recipients of finished
+ messages must verify that the contents are correct. Once a side
+ has sent its Finished message and received and validated the
+ Finished message from its peer, it may begin to send and receive
+ application data over the connection.
+
+ struct {
+ opaque verify_data[12];
+ } Finished;
+
+ verify_data
+ PRF(master_secret, finished_label, MD5(handshake_messages) +
+ SHA-1(handshake_messages)) [0..11];
+
+ finished_label
+ For Finished messages sent by the client, the string "client
+ finished". For Finished messages sent by the server, the
+ string "server finished".
+
+ handshake_messages
+ All of the data from all handshake messages up to but not
+ including this message. This is only data visible at the
+ handshake layer and does not include record layer headers.
+
+
+
+Dierks & Allen Standards Track [Page 46]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ This is the concatenation of all the Handshake structures as
+ defined in 7.4 exchanged thus far.
+
+ It is a fatal error if a finished message is not preceded by a change
+ cipher spec message at the appropriate point in the handshake.
+
+ The hash contained in finished messages sent by the server
+ incorporate Sender.server; those sent by the client incorporate
+ Sender.client. The value handshake_messages includes all handshake
+ messages starting at client hello up to, but not including, this
+ finished message. This may be different from handshake_messages in
+ Section 7.4.8 because it would include the certificate verify message
+ (if sent). Also, the handshake_messages for the finished message sent
+ by the client will be different from that for the finished message
+ sent by the server, because the one which is sent second will include
+ the prior one.
+
+ Note: Change cipher spec messages, alerts and any other record types
+ are not handshake messages and are not included in the hash
+ computations. Also, Hello Request messages are omitted from
+ handshake hashes.
+
+8. Cryptographic computations
+
+ In order to begin connection protection, the TLS Record Protocol
+ requires specification of a suite of algorithms, a master secret, and
+ the client and server random values. The authentication, encryption,
+ and MAC algorithms are determined by the cipher_suite selected by the
+ server and revealed in the server hello message. The compression
+ algorithm is negotiated in the hello messages, and the random values
+ are exchanged in the hello messages. All that remains is to calculate
+ the master secret.
+
+8.1. Computing the master secret
+
+ For all key exchange methods, the same algorithm is used to convert
+ the pre_master_secret into the master_secret. The pre_master_secret
+ should be deleted from memory once the master_secret has been
+ computed.
+
+ master_secret = PRF(pre_master_secret, "master secret",
+ ClientHello.random + ServerHello.random)
+ [0..47];
+
+ The master secret is always exactly 48 bytes in length. The length of
+ the premaster secret will vary depending on key exchange method.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 47]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+8.1.1. RSA
+
+ When RSA is used for server authentication and key exchange, a 48-
+ byte pre_master_secret is generated by the client, encrypted under
+ the server's public key, and sent to the server. The server uses its
+ private key to decrypt the pre_master_secret. Both parties then
+ convert the pre_master_secret into the master_secret, as specified
+ above.
+
+ RSA digital signatures are performed using PKCS #1 [PKCS1] block type
+ 1. RSA public key encryption is performed using PKCS #1 block type 2.
+
+8.1.2. Diffie-Hellman
+
+ A conventional Diffie-Hellman computation is performed. The
+ negotiated key (Z) is used as the pre_master_secret, and is converted
+ into the master_secret, as specified above.
+
+ Note: Diffie-Hellman parameters are specified by the server, and may
+ be either ephemeral or contained within the server's certificate.
+
+9. Mandatory Cipher Suites
+
+ In the absence of an application profile standard specifying
+ otherwise, a TLS compliant application MUST implement the cipher
+ suite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.
+
+10. Application data protocol
+
+ Application data messages are carried by the Record Layer and are
+ fragmented, compressed and encrypted based on the current connection
+ state. The messages are treated as transparent data to the record
+ layer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 48]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+A. Protocol constant values
+
+ This section describes protocol types and constants.
+
+A.1. Record layer
+
+ struct {
+ uint8 major, minor;
+ } ProtocolVersion;
+
+ ProtocolVersion version = { 3, 1 }; /* TLS v1.0 */
+
+ enum {
+ change_cipher_spec(20), alert(21), handshake(22),
+ application_data(23), (255)
+ } ContentType;
+
+ struct {
+ ContentType type;
+ ProtocolVersion version;
+ uint16 length;
+ opaque fragment[TLSPlaintext.length];
+ } TLSPlaintext;
+
+ struct {
+ ContentType type;
+ ProtocolVersion version;
+ uint16 length;
+ opaque fragment[TLSCompressed.length];
+ } TLSCompressed;
+
+ struct {
+ ContentType type;
+ ProtocolVersion version;
+ uint16 length;
+ select (CipherSpec.cipher_type) {
+ case stream: GenericStreamCipher;
+ case block: GenericBlockCipher;
+ } fragment;
+ } TLSCiphertext;
+
+ stream-ciphered struct {
+ opaque content[TLSCompressed.length];
+ opaque MAC[CipherSpec.hash_size];
+ } GenericStreamCipher;
+
+ block-ciphered struct {
+ opaque content[TLSCompressed.length];
+
+
+
+Dierks & Allen Standards Track [Page 49]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ opaque MAC[CipherSpec.hash_size];
+ uint8 padding[GenericBlockCipher.padding_length];
+ uint8 padding_length;
+ } GenericBlockCipher;
+
+A.2. Change cipher specs message
+
+ struct {
+ enum { change_cipher_spec(1), (255) } type;
+ } ChangeCipherSpec;
+
+A.3. Alert messages
+
+ enum { warning(1), fatal(2), (255) } AlertLevel;
+
+ enum {
+ close_notify(0),
+ unexpected_message(10),
+ bad_record_mac(20),
+ decryption_failed(21),
+ record_overflow(22),
+ decompression_failure(30),
+ handshake_failure(40),
+ bad_certificate(42),
+ unsupported_certificate(43),
+ certificate_revoked(44),
+ certificate_expired(45),
+ certificate_unknown(46),
+ illegal_parameter(47),
+ unknown_ca(48),
+ access_denied(49),
+ decode_error(50),
+ decrypt_error(51),
+ export_restriction(60),
+ protocol_version(70),
+ insufficient_security(71),
+ internal_error(80),
+ user_canceled(90),
+ no_renegotiation(100),
+ (255)
+ } AlertDescription;
+
+ struct {
+ AlertLevel level;
+ AlertDescription description;
+ } Alert;
+
+
+
+
+
+Dierks & Allen Standards Track [Page 50]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+A.4. Handshake protocol
+
+ enum {
+ hello_request(0), client_hello(1), server_hello(2),
+ certificate(11), server_key_exchange (12),
+ certificate_request(13), server_hello_done(14),
+ certificate_verify(15), client_key_exchange(16),
+ finished(20), (255)
+ } HandshakeType;
+
+ struct {
+ HandshakeType msg_type;
+ uint24 length;
+ select (HandshakeType) {
+ case hello_request: HelloRequest;
+ case client_hello: ClientHello;
+ case server_hello: ServerHello;
+ case certificate: Certificate;
+ case server_key_exchange: ServerKeyExchange;
+ case certificate_request: CertificateRequest;
+ case server_hello_done: ServerHelloDone;
+ case certificate_verify: CertificateVerify;
+ case client_key_exchange: ClientKeyExchange;
+ case finished: Finished;
+ } body;
+ } Handshake;
+
+A.4.1. Hello messages
+
+ struct { } HelloRequest;
+
+ struct {
+ uint32 gmt_unix_time;
+ opaque random_bytes[28];
+ } Random;
+
+ opaque SessionID<0..32>;
+
+ uint8 CipherSuite[2];
+
+ enum { null(0), (255) } CompressionMethod;
+
+ struct {
+ ProtocolVersion client_version;
+ Random random;
+ SessionID session_id;
+ CipherSuite cipher_suites<2..2^16-1>;
+ CompressionMethod compression_methods<1..2^8-1>;
+
+
+
+Dierks & Allen Standards Track [Page 51]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ } ClientHello;
+
+ struct {
+ ProtocolVersion server_version;
+ Random random;
+ SessionID session_id;
+ CipherSuite cipher_suite;
+ CompressionMethod compression_method;
+ } ServerHello;
+
+A.4.2. Server authentication and key exchange messages
+
+ opaque ASN.1Cert<2^24-1>;
+
+ struct {
+ ASN.1Cert certificate_list<1..2^24-1>;
+ } Certificate;
+
+ enum { rsa, diffie_hellman } KeyExchangeAlgorithm;
+
+ struct {
+ opaque RSA_modulus<1..2^16-1>;
+ opaque RSA_exponent<1..2^16-1>;
+ } ServerRSAParams;
+
+ struct {
+ opaque DH_p<1..2^16-1>;
+ opaque DH_g<1..2^16-1>;
+ opaque DH_Ys<1..2^16-1>;
+ } ServerDHParams;
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ case diffie_hellman:
+ ServerDHParams params;
+ Signature signed_params;
+ case rsa:
+ ServerRSAParams params;
+ Signature signed_params;
+ };
+ } ServerKeyExchange;
+
+ enum { anonymous, rsa, dsa } SignatureAlgorithm;
+
+ select (SignatureAlgorithm)
+ { case anonymous: struct { };
+ case rsa:
+ digitally-signed struct {
+
+
+
+Dierks & Allen Standards Track [Page 52]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ opaque md5_hash[16];
+ opaque sha_hash[20];
+ };
+ case dsa:
+ digitally-signed struct {
+ opaque sha_hash[20];
+ };
+ } Signature;
+
+ enum {
+ rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
+ (255)
+ } ClientCertificateType;
+
+ opaque DistinguishedName<1..2^16-1>;
+
+ struct {
+ ClientCertificateType certificate_types<1..2^8-1>;
+ DistinguishedName certificate_authorities<3..2^16-1>;
+ } CertificateRequest;
+
+ struct { } ServerHelloDone;
+
+A.4.3. Client authentication and key exchange messages
+
+ struct {
+ select (KeyExchangeAlgorithm) {
+ case rsa: EncryptedPreMasterSecret;
+ case diffie_hellman: DiffieHellmanClientPublicValue;
+ } exchange_keys;
+ } ClientKeyExchange;
+
+ struct {
+ ProtocolVersion client_version;
+ opaque random[46];
+
+ } PreMasterSecret;
+
+ struct {
+ public-key-encrypted PreMasterSecret pre_master_secret;
+ } EncryptedPreMasterSecret;
+
+ enum { implicit, explicit } PublicValueEncoding;
+
+ struct {
+ select (PublicValueEncoding) {
+ case implicit: struct {};
+ case explicit: opaque DH_Yc<1..2^16-1>;
+
+
+
+Dierks & Allen Standards Track [Page 53]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ } dh_public;
+ } ClientDiffieHellmanPublic;
+
+ struct {
+ Signature signature;
+ } CertificateVerify;
+
+A.4.4. Handshake finalization message
+
+ struct {
+ opaque verify_data[12];
+ } Finished;
+
+A.5. The CipherSuite
+
+ The following values define the CipherSuite codes used in the client
+ hello and server hello messages.
+
+ A CipherSuite defines a cipher specification supported in TLS Version
+ 1.0.
+
+ TLS_NULL_WITH_NULL_NULL is specified and is the initial state of a
+ TLS connection during the first handshake on that channel, but must
+ not be negotiated, as it provides no more protection than an
+ unsecured connection.
+
+ CipherSuite TLS_NULL_WITH_NULL_NULL = { 0x00,0x00 };
+
+ The following CipherSuite definitions require that the server provide
+ an RSA certificate that can be used for key exchange. The server may
+ request either an RSA or a DSS signature-capable certificate in the
+ certificate request message.
+
+ CipherSuite TLS_RSA_WITH_NULL_MD5 = { 0x00,0x01 };
+ CipherSuite TLS_RSA_WITH_NULL_SHA = { 0x00,0x02 };
+ CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x03 };
+ CipherSuite TLS_RSA_WITH_RC4_128_MD5 = { 0x00,0x04 };
+ CipherSuite TLS_RSA_WITH_RC4_128_SHA = { 0x00,0x05 };
+ CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00,0x06 };
+ CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = { 0x00,0x07 };
+ CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x08 };
+ CipherSuite TLS_RSA_WITH_DES_CBC_SHA = { 0x00,0x09 };
+ CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0A };
+
+ The following CipherSuite definitions are used for server-
+ authenticated (and optionally client-authenticated) Diffie-Hellman.
+ DH denotes cipher suites in which the server's certificate contains
+ the Diffie-Hellman parameters signed by the certificate authority
+
+
+
+Dierks & Allen Standards Track [Page 54]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ (CA). DHE denotes ephemeral Diffie-Hellman, where the Diffie-Hellman
+ parameters are signed by a DSS or RSA certificate, which has been
+ signed by the CA. The signing algorithm used is specified after the
+ DH or DHE parameter. The server can request an RSA or DSS signature-
+ capable certificate from the client for client authentication or it
+ may request a Diffie-Hellman certificate. Any Diffie-Hellman
+ certificate provided by the client must use the parameters (group and
+ generator) described by the server.
+
+ CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0B };
+ CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = { 0x00,0x0C };
+ CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x0D };
+ CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x0E };
+ CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = { 0x00,0x0F };
+ CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x10 };
+ CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x11 };
+ CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA = { 0x00,0x12 };
+ CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00,0x13 };
+ CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x14 };
+ CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA = { 0x00,0x15 };
+ CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00,0x16 };
+
+ The following cipher suites are used for completely anonymous
+ Diffie-Hellman communications in which neither party is
+ authenticated. Note that this mode is vulnerable to man-in-the-middle
+ attacks and is therefore deprecated.
+
+ CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x17 };
+ CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 = { 0x00,0x18 };
+ CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = { 0x00,0x19 };
+ CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA = { 0x00,0x1A };
+ CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = { 0x00,0x1B };
+
+ Note: All cipher suites whose first byte is 0xFF are considered
+ private and can be used for defining local/experimental
+ algorithms. Interoperability of such types is a local matter.
+
+ Note: Additional cipher suites can be registered by publishing an RFC
+ which specifies the cipher suites, including the necessary TLS
+ protocol information, including message encoding, premaster
+ secret derivation, symmetric encryption and MAC calculation and
+ appropriate reference information for the algorithms involved.
+ The RFC editor's office may, at its discretion, choose to publish
+ specifications for cipher suites which are not completely
+ described (e.g., for classified algorithms) if it finds the
+ specification to be of technical interest and completely
+ specified.
+
+
+
+
+Dierks & Allen Standards Track [Page 55]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are
+ reserved to avoid collision with Fortezza-based cipher suites in
+ SSL 3.
+
+A.6. The Security Parameters
+
+ These security parameters are determined by the TLS Handshake
+ Protocol and provided as parameters to the TLS Record Layer in order
+ to initialize a connection state. SecurityParameters includes:
+
+ enum { null(0), (255) } CompressionMethod;
+
+ enum { server, client } ConnectionEnd;
+
+ enum { null, rc4, rc2, des, 3des, des40, idea }
+ BulkCipherAlgorithm;
+
+ enum { stream, block } CipherType;
+
+ enum { true, false } IsExportable;
+
+ enum { null, md5, sha } MACAlgorithm;
+
+ /* The algorithms specified in CompressionMethod,
+ BulkCipherAlgorithm, and MACAlgorithm may be added to. */
+
+ struct {
+ ConnectionEnd entity;
+ BulkCipherAlgorithm bulk_cipher_algorithm;
+ CipherType cipher_type;
+ uint8 key_size;
+ uint8 key_material_length;
+ IsExportable is_exportable;
+ MACAlgorithm mac_algorithm;
+ uint8 hash_size;
+ CompressionMethod compression_algorithm;
+ opaque master_secret[48];
+ opaque client_random[32];
+ opaque server_random[32];
+ } SecurityParameters;
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 56]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+B. Glossary
+
+ application protocol
+ An application protocol is a protocol that normally layers
+ directly on top of the transport layer (e.g., TCP/IP). Examples
+ include HTTP, TELNET, FTP, and SMTP.
+
+ asymmetric cipher
+ See public key cryptography.
+
+ authentication
+ Authentication is the ability of one entity to determine the
+ identity of another entity.
+
+ block cipher
+ A block cipher is an algorithm that operates on plaintext in
+ groups of bits, called blocks. 64 bits is a common block size.
+
+ bulk cipher
+ A symmetric encryption algorithm used to encrypt large quantities
+ of data.
+
+ cipher block chaining (CBC)
+ CBC is a mode in which every plaintext block encrypted with a
+ block cipher is first exclusive-ORed with the previous ciphertext
+ block (or, in the case of the first block, with the
+ initialization vector). For decryption, every block is first
+ decrypted, then exclusive-ORed with the previous ciphertext block
+ (or IV).
+
+ certificate
+ As part of the X.509 protocol (a.k.a. ISO Authentication
+ framework), certificates are assigned by a trusted Certificate
+ Authority and provide a strong binding between a party's identity
+ or some other attributes and its public key.
+
+ client
+ The application entity that initiates a TLS connection to a
+ server. This may or may not imply that the client initiated the
+ underlying transport connection. The primary operational
+ difference between the server and client is that the server is
+ generally authenticated, while the client is only optionally
+ authenticated.
+
+ client write key
+ The key used to encrypt data written by the client.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 57]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ client write MAC secret
+ The secret data used to authenticate data written by the client.
+
+ connection
+ A connection is a transport (in the OSI layering model
+ definition) that provides a suitable type of service. For TLS,
+ such connections are peer to peer relationships. The connections
+ are transient. Every connection is associated with one session.
+
+ Data Encryption Standard
+ DES is a very widely used symmetric encryption algorithm. DES is
+ a block cipher with a 56 bit key and an 8 byte block size. Note
+ that in TLS, for key generation purposes, DES is treated as
+ having an 8 byte key length (64 bits), but it still only provides
+ 56 bits of protection. (The low bit of each key byte is presumed
+ to be set to produce odd parity in that key byte.) DES can also
+ be operated in a mode where three independent keys and three
+ encryptions are used for each block of data; this uses 168 bits
+ of key (24 bytes in the TLS key generation method) and provides
+ the equivalent of 112 bits of security. [DES], [3DES]
+
+ Digital Signature Standard (DSS)
+ A standard for digital signing, including the Digital Signing
+ Algorithm, approved by the National Institute of Standards and
+ Technology, defined in NIST FIPS PUB 186, "Digital Signature
+ Standard," published May, 1994 by the U.S. Dept. of Commerce.
+ [DSS]
+
+ digital signatures
+ Digital signatures utilize public key cryptography and one-way
+ hash functions to produce a signature of the data that can be
+ authenticated, and is difficult to forge or repudiate.
+
+ handshake
+ An initial negotiation between client and server that establishes
+ the parameters of their transactions.
+
+ Initialization Vector (IV)
+ When a block cipher is used in CBC mode, the initialization
+ vector is exclusive-ORed with the first plaintext block prior to
+ encryption.
+
+ IDEA
+ A 64-bit block cipher designed by Xuejia Lai and James Massey.
+ [IDEA]
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 58]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Message Authentication Code (MAC)
+ A Message Authentication Code is a one-way hash computed from a
+ message and some secret data. It is difficult to forge without
+ knowing the secret data. Its purpose is to detect if the message
+ has been altered.
+
+ master secret
+ Secure secret data used for generating encryption keys, MAC
+ secrets, and IVs.
+
+ MD5
+ MD5 is a secure hashing function that converts an arbitrarily
+ long data stream into a digest of fixed size (16 bytes). [MD5]
+
+ public key cryptography
+ A class of cryptographic techniques employing two-key ciphers.
+ Messages encrypted with the public key can only be decrypted with
+ the associated private key. Conversely, messages signed with the
+ private key can be verified with the public key.
+
+ one-way hash function
+ A one-way transformation that converts an arbitrary amount of
+ data into a fixed-length hash. It is computationally hard to
+ reverse the transformation or to find collisions. MD5 and SHA are
+ examples of one-way hash functions.
+
+ RC2
+ A block cipher developed by Ron Rivest at RSA Data Security, Inc.
+ [RSADSI] described in [RC2].
+
+ RC4
+ A stream cipher licensed by RSA Data Security [RSADSI]. A
+ compatible cipher is described in [RC4].
+
+ RSA
+ A very widely used public-key algorithm that can be used for
+ either encryption or digital signing. [RSA]
+
+ salt
+ Non-secret random data used to make export encryption keys resist
+ precomputation attacks.
+
+ server
+ The server is the application entity that responds to requests
+ for connections from clients. See also under client.
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 59]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ session
+ A TLS session is an association between a client and a server.
+ Sessions are created by the handshake protocol. Sessions define a
+ set of cryptographic security parameters, which can be shared
+ among multiple connections. Sessions are used to avoid the
+ expensive negotiation of new security parameters for each
+ connection.
+
+ session identifier
+ A session identifier is a value generated by a server that
+ identifies a particular session.
+
+ server write key
+ The key used to encrypt data written by the server.
+
+ server write MAC secret
+ The secret data used to authenticate data written by the server.
+
+ SHA
+ The Secure Hash Algorithm is defined in FIPS PUB 180-1. It
+ produces a 20-byte output. Note that all references to SHA
+ actually use the modified SHA-1 algorithm. [SHA]
+
+ SSL
+ Netscape's Secure Socket Layer protocol [SSL3]. TLS is based on
+ SSL Version 3.0
+
+ stream cipher
+ An encryption algorithm that converts a key into a
+ cryptographically-strong keystream, which is then exclusive-ORed
+ with the plaintext.
+
+ symmetric cipher
+ See bulk cipher.
+
+ Transport Layer Security (TLS)
+ This protocol; also, the Transport Layer Security working group
+ of the Internet Engineering Task Force (IETF). See "Comments" at
+ the end of this document.
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 60]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+C. CipherSuite definitions
+
+CipherSuite Is Key Cipher Hash
+ Exportable Exchange
+
+TLS_NULL_WITH_NULL_NULL * NULL NULL NULL
+TLS_RSA_WITH_NULL_MD5 * RSA NULL MD5
+TLS_RSA_WITH_NULL_SHA * RSA NULL SHA
+TLS_RSA_EXPORT_WITH_RC4_40_MD5 * RSA_EXPORT RC4_40 MD5
+TLS_RSA_WITH_RC4_128_MD5 RSA RC4_128 MD5
+TLS_RSA_WITH_RC4_128_SHA RSA RC4_128 SHA
+TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 * RSA_EXPORT RC2_CBC_40 MD5
+TLS_RSA_WITH_IDEA_CBC_SHA RSA IDEA_CBC SHA
+TLS_RSA_EXPORT_WITH_DES40_CBC_SHA * RSA_EXPORT DES40_CBC SHA
+TLS_RSA_WITH_DES_CBC_SHA RSA DES_CBC SHA
+TLS_RSA_WITH_3DES_EDE_CBC_SHA RSA 3DES_EDE_CBC SHA
+TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA * DH_DSS_EXPORT DES40_CBC SHA
+TLS_DH_DSS_WITH_DES_CBC_SHA DH_DSS DES_CBC SHA
+TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA DH_DSS 3DES_EDE_CBC SHA
+TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA * DH_RSA_EXPORT DES40_CBC SHA
+TLS_DH_RSA_WITH_DES_CBC_SHA DH_RSA DES_CBC SHA
+TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA DH_RSA 3DES_EDE_CBC SHA
+TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA * DHE_DSS_EXPORT DES40_CBC SHA
+TLS_DHE_DSS_WITH_DES_CBC_SHA DHE_DSS DES_CBC SHA
+TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA DHE_DSS 3DES_EDE_CBC SHA
+TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA * DHE_RSA_EXPORT DES40_CBC SHA
+TLS_DHE_RSA_WITH_DES_CBC_SHA DHE_RSA DES_CBC SHA
+TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA DHE_RSA 3DES_EDE_CBC SHA
+TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 * DH_anon_EXPORT RC4_40 MD5
+TLS_DH_anon_WITH_RC4_128_MD5 DH_anon RC4_128 MD5
+TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA DH_anon DES40_CBC SHA
+TLS_DH_anon_WITH_DES_CBC_SHA DH_anon DES_CBC SHA
+TLS_DH_anon_WITH_3DES_EDE_CBC_SHA DH_anon 3DES_EDE_CBC SHA
+
+
+ * Indicates IsExportable is True
+
+ Key
+ Exchange
+ Algorithm Description Key size limit
+
+ DHE_DSS Ephemeral DH with DSS signatures None
+ DHE_DSS_EXPORT Ephemeral DH with DSS signatures DH = 512 bits
+ DHE_RSA Ephemeral DH with RSA signatures None
+ DHE_RSA_EXPORT Ephemeral DH with RSA signatures DH = 512 bits,
+ RSA = none
+ DH_anon Anonymous DH, no signatures None
+ DH_anon_EXPORT Anonymous DH, no signatures DH = 512 bits
+
+
+
+Dierks & Allen Standards Track [Page 61]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ DH_DSS DH with DSS-based certificates None
+ DH_DSS_EXPORT DH with DSS-based certificates DH = 512 bits
+ DH_RSA DH with RSA-based certificates None
+ DH_RSA_EXPORT DH with RSA-based certificates DH = 512 bits,
+ RSA = none
+ NULL No key exchange N/A
+ RSA RSA key exchange None
+ RSA_EXPORT RSA key exchange RSA = 512 bits
+
+ Key size limit
+ The key size limit gives the size of the largest public key that
+ can be legally used for encryption in cipher suites that are
+ exportable.
+
+ Key Expanded Effective IV Block
+ Cipher Type Material Key Material Key Bits Size Size
+
+ NULL * Stream 0 0 0 0 N/A
+ IDEA_CBC Block 16 16 128 8 8
+ RC2_CBC_40 * Block 5 16 40 8 8
+ RC4_40 * Stream 5 16 40 0 N/A
+ RC4_128 Stream 16 16 128 0 N/A
+ DES40_CBC * Block 5 8 40 8 8
+ DES_CBC Block 8 8 56 8 8
+ 3DES_EDE_CBC Block 24 24 168 8 8
+
+ * Indicates IsExportable is true.
+
+ Type
+ Indicates whether this is a stream cipher or a block cipher
+ running in CBC mode.
+
+ Key Material
+ The number of bytes from the key_block that are used for
+ generating the write keys.
+
+ Expanded Key Material
+ The number of bytes actually fed into the encryption algorithm
+
+ Effective Key Bits
+ How much entropy material is in the key material being fed into
+ the encryption routines.
+
+ IV Size
+ How much data needs to be generated for the initialization
+ vector. Zero for stream ciphers; equal to the block size for
+ block ciphers.
+
+
+
+
+Dierks & Allen Standards Track [Page 62]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Block Size
+ The amount of data a block cipher enciphers in one chunk; a
+ block cipher running in CBC mode can only encrypt an even
+ multiple of its block size.
+
+ Hash Hash Padding
+ function Size Size
+ NULL 0 0
+ MD5 16 48
+ SHA 20 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 63]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+D. Implementation Notes
+
+ The TLS protocol cannot prevent many common security mistakes. This
+ section provides several recommendations to assist implementors.
+
+D.1. Temporary RSA keys
+
+ US Export restrictions limit RSA keys used for encryption to 512
+ bits, but do not place any limit on lengths of RSA keys used for
+ signing operations. Certificates often need to be larger than 512
+ bits, since 512-bit RSA keys are not secure enough for high-value
+ transactions or for applications requiring long-term security. Some
+ certificates are also designated signing-only, in which case they
+ cannot be used for key exchange.
+
+ When the public key in the certificate cannot be used for encryption,
+ the server signs a temporary RSA key, which is then exchanged. In
+ exportable applications, the temporary RSA key should be the maximum
+ allowable length (i.e., 512 bits). Because 512-bit RSA keys are
+ relatively insecure, they should be changed often. For typical
+ electronic commerce applications, it is suggested that keys be
+ changed daily or every 500 transactions, and more often if possible.
+ Note that while it is acceptable to use the same temporary key for
+ multiple transactions, it must be signed each time it is used.
+
+ RSA key generation is a time-consuming process. In many cases, a
+ low-priority process can be assigned the task of key generation.
+
+ Whenever a new key is completed, the existing temporary key can be
+ replaced with the new one.
+
+D.2. Random Number Generation and Seeding
+
+ TLS requires a cryptographically-secure pseudorandom number generator
+ (PRNG). Care must be taken in designing and seeding PRNGs. PRNGs
+ based on secure hash operations, most notably MD5 and/or SHA, are
+ acceptable, but cannot provide more security than the size of the
+ random number generator state. (For example, MD5-based PRNGs usually
+ provide 128 bits of state.)
+
+ To estimate the amount of seed material being produced, add the
+ number of bits of unpredictable information in each seed byte. For
+ example, keystroke timing values taken from a PC compatible's 18.2 Hz
+ timer provide 1 or 2 secure bits each, even though the total size of
+ the counter value is 16 bits or more. To seed a 128-bit PRNG, one
+ would thus require approximately 100 such timer values.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 64]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Warning: The seeding functions in RSAREF and versions of BSAFE prior to
+ 3.0 are order-independent. For example, if 1000 seed bits are
+ supplied, one at a time, in 1000 separate calls to the seed
+ function, the PRNG will end up in a state which depends only
+ on the number of 0 or 1 seed bits in the seed data (i.e.,
+ there are 1001 possible final states). Applications using
+ BSAFE or RSAREF must take extra care to ensure proper seeding.
+ This may be accomplished by accumulating seed bits into a
+ buffer and processing them all at once or by processing an
+ incrementing counter with every seed bit; either method will
+ reintroduce order dependence into the seeding process.
+
+D.3. Certificates and authentication
+
+ Implementations are responsible for verifying the integrity of
+ certificates and should generally support certificate revocation
+ messages. Certificates should always be verified to ensure proper
+ signing by a trusted Certificate Authority (CA). The selection and
+ addition of trusted CAs should be done very carefully. Users should
+ be able to view information about the certificate and root CA.
+
+D.4. CipherSuites
+
+ TLS supports a range of key sizes and security levels, including some
+ which provide no or minimal security. A proper implementation will
+ probably not support many cipher suites. For example, 40-bit
+ encryption is easily broken, so implementations requiring strong
+ security should not allow 40-bit keys. Similarly, anonymous Diffie-
+ Hellman is strongly discouraged because it cannot prevent man-in-
+ the-middle attacks. Applications should also enforce minimum and
+ maximum key sizes. For example, certificate chains containing 512-bit
+ RSA keys or signatures are not appropriate for high-security
+ applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 65]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+E. Backward Compatibility With SSL
+
+ For historical reasons and in order to avoid a profligate consumption
+ of reserved port numbers, application protocols which are secured by
+ TLS 1.0, SSL 3.0, and SSL 2.0 all frequently share the same
+ connection port: for example, the https protocol (HTTP secured by SSL
+ or TLS) uses port 443 regardless of which security protocol it is
+ using. Thus, some mechanism must be determined to distinguish and
+ negotiate among the various protocols.
+
+ TLS version 1.0 and SSL 3.0 are very similar; thus, supporting both
+ is easy. TLS clients who wish to negotiate with SSL 3.0 servers
+ should send client hello messages using the SSL 3.0 record format and
+ client hello structure, sending {3, 1} for the version field to note
+ that they support TLS 1.0. If the server supports only SSL 3.0, it
+ will respond with an SSL 3.0 server hello; if it supports TLS, with a
+ TLS server hello. The negotiation then proceeds as appropriate for
+ the negotiated protocol.
+
+ Similarly, a TLS server which wishes to interoperate with SSL 3.0
+ clients should accept SSL 3.0 client hello messages and respond with
+ an SSL 3.0 server hello if an SSL 3.0 client hello is received which
+ has a version field of {3, 0}, denoting that this client does not
+ support TLS.
+
+ Whenever a client already knows the highest protocol known to a
+ server (for example, when resuming a session), it should initiate the
+ connection in that native protocol.
+
+ TLS 1.0 clients that support SSL Version 2.0 servers must send SSL
+ Version 2.0 client hello messages [SSL2]. TLS servers should accept
+ either client hello format if they wish to support SSL 2.0 clients on
+ the same connection port. The only deviations from the Version 2.0
+ specification are the ability to specify a version with a value of
+ three and the support for more ciphering types in the CipherSpec.
+
+ Warning: The ability to send Version 2.0 client hello messages will be
+ phased out with all due haste. Implementors should make every
+ effort to move forward as quickly as possible. Version 3.0
+ provides better mechanisms for moving to newer versions.
+
+ The following cipher specifications are carryovers from SSL Version
+ 2.0. These are assumed to use RSA for key exchange and
+ authentication.
+
+ V2CipherSpec TLS_RC4_128_WITH_MD5 = { 0x01,0x00,0x80 };
+ V2CipherSpec TLS_RC4_128_EXPORT40_WITH_MD5 = { 0x02,0x00,0x80 };
+ V2CipherSpec TLS_RC2_CBC_128_CBC_WITH_MD5 = { 0x03,0x00,0x80 };
+
+
+
+Dierks & Allen Standards Track [Page 66]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ V2CipherSpec TLS_RC2_CBC_128_CBC_EXPORT40_WITH_MD5
+ = { 0x04,0x00,0x80 };
+ V2CipherSpec TLS_IDEA_128_CBC_WITH_MD5 = { 0x05,0x00,0x80 };
+ V2CipherSpec TLS_DES_64_CBC_WITH_MD5 = { 0x06,0x00,0x40 };
+ V2CipherSpec TLS_DES_192_EDE3_CBC_WITH_MD5 = { 0x07,0x00,0xC0 };
+
+ Cipher specifications native to TLS can be included in Version 2.0
+ client hello messages using the syntax below. Any V2CipherSpec
+ element with its first byte equal to zero will be ignored by Version
+ 2.0 servers. Clients sending any of the above V2CipherSpecs should
+ also include the TLS equivalent (see Appendix A.5):
+
+ V2CipherSpec (see TLS name) = { 0x00, CipherSuite };
+
+E.1. Version 2 client hello
+
+ The Version 2.0 client hello message is presented below using this
+ document's presentation model. The true definition is still assumed
+ to be the SSL Version 2.0 specification.
+
+ uint8 V2CipherSpec[3];
+
+ struct {
+ uint8 msg_type;
+ Version version;
+ uint16 cipher_spec_length;
+ uint16 session_id_length;
+ uint16 challenge_length;
+ V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
+ opaque session_id[V2ClientHello.session_id_length];
+ Random challenge;
+ } V2ClientHello;
+
+ msg_type
+ This field, in conjunction with the version field, identifies a
+ version 2 client hello message. The value should be one (1).
+
+ version
+ The highest version of the protocol supported by the client
+ (equals ProtocolVersion.version, see Appendix A.1).
+
+ cipher_spec_length
+ This field is the total length of the field cipher_specs. It
+ cannot be zero and must be a multiple of the V2CipherSpec length
+ (3).
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 67]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ session_id_length
+ This field must have a value of either zero or 16. If zero, the
+ client is creating a new session. If 16, the session_id field
+ will contain the 16 bytes of session identification.
+
+ challenge_length
+ The length in bytes of the client's challenge to the server to
+ authenticate itself. This value must be 32.
+
+ cipher_specs
+ This is a list of all CipherSpecs the client is willing and able
+ to use. There must be at least one CipherSpec acceptable to the
+ server.
+
+ session_id
+ If this field's length is not zero, it will contain the
+ identification for a session that the client wishes to resume.
+
+ challenge
+ The client challenge to the server for the server to identify
+ itself is a (nearly) arbitrary length random. The TLS server will
+ right justify the challenge data to become the ClientHello.random
+ data (padded with leading zeroes, if necessary), as specified in
+ this protocol specification. If the length of the challenge is
+ greater than 32 bytes, only the last 32 bytes are used. It is
+ legitimate (but not necessary) for a V3 server to reject a V2
+ ClientHello that has fewer than 16 bytes of challenge data.
+
+ Note: Requests to resume a TLS session should use a TLS client hello.
+
+E.2. Avoiding man-in-the-middle version rollback
+
+ When TLS clients fall back to Version 2.0 compatibility mode, they
+ should use special PKCS #1 block formatting. This is done so that TLS
+ servers will reject Version 2.0 sessions with TLS-capable clients.
+
+ When TLS clients are in Version 2.0 compatibility mode, they set the
+ right-hand (least-significant) 8 random bytes of the PKCS padding
+ (not including the terminal null of the padding) for the RSA
+ encryption of the ENCRYPTED-KEY-DATA field of the CLIENT-MASTER-KEY
+ to 0x03 (the other padding bytes are random). After decrypting the
+ ENCRYPTED-KEY-DATA field, servers that support TLS should issue an
+ error if these eight padding bytes are 0x03. Version 2.0 servers
+ receiving blocks padded in this manner will proceed normally.
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 68]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+F. Security analysis
+
+ The TLS protocol is designed to establish a secure connection between
+ a client and a server communicating over an insecure channel. This
+ document makes several traditional assumptions, including that
+ attackers have substantial computational resources and cannot obtain
+ secret information from sources outside the protocol. Attackers are
+ assumed to have the ability to capture, modify, delete, replay, and
+ otherwise tamper with messages sent over the communication channel.
+ This appendix outlines how TLS has been designed to resist a variety
+ of attacks.
+
+F.1. Handshake protocol
+
+ The handshake protocol is responsible for selecting a CipherSpec and
+ generating a Master Secret, which together comprise the primary
+ cryptographic parameters associated with a secure session. The
+ handshake protocol can also optionally authenticate parties who have
+ certificates signed by a trusted certificate authority.
+
+F.1.1. Authentication and key exchange
+
+ TLS supports three authentication modes: authentication of both
+ parties, server authentication with an unauthenticated client, and
+ total anonymity. Whenever the server is authenticated, the channel is
+ secure against man-in-the-middle attacks, but completely anonymous
+ sessions are inherently vulnerable to such attacks. Anonymous
+ servers cannot authenticate clients. If the server is authenticated,
+ its certificate message must provide a valid certificate chain
+ leading to an acceptable certificate authority. Similarly,
+ authenticated clients must supply an acceptable certificate to the
+ server. Each party is responsible for verifying that the other's
+ certificate is valid and has not expired or been revoked.
+
+ The general goal of the key exchange process is to create a
+ pre_master_secret known to the communicating parties and not to
+ attackers. The pre_master_secret will be used to generate the
+ master_secret (see Section 8.1). The master_secret is required to
+ generate the certificate verify and finished messages, encryption
+ keys, and MAC secrets (see Sections 7.4.8, 7.4.9 and 6.3). By sending
+ a correct finished message, parties thus prove that they know the
+ correct pre_master_secret.
+
+F.1.1.1. Anonymous key exchange
+
+ Completely anonymous sessions can be established using RSA or
+ Diffie-Hellman for key exchange. With anonymous RSA, the client
+ encrypts a pre_master_secret with the server's uncertified public key
+
+
+
+Dierks & Allen Standards Track [Page 69]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ extracted from the server key exchange message. The result is sent in
+ a client key exchange message. Since eavesdroppers do not know the
+ server's private key, it will be infeasible for them to decode the
+ pre_master_secret. (Note that no anonymous RSA Cipher Suites are
+ defined in this document).
+
+ With Diffie-Hellman, the server's public parameters are contained in
+ the server key exchange message and the client's are sent in the
+ client key exchange message. Eavesdroppers who do not know the
+ private values should not be able to find the Diffie-Hellman result
+ (i.e. the pre_master_secret).
+
+ Warning: Completely anonymous connections only provide protection
+ against passive eavesdropping. Unless an independent tamper-
+ proof channel is used to verify that the finished messages
+ were not replaced by an attacker, server authentication is
+ required in environments where active man-in-the-middle
+ attacks are a concern.
+
+F.1.1.2. RSA key exchange and authentication
+
+ With RSA, key exchange and server authentication are combined. The
+ public key may be either contained in the server's certificate or may
+ be a temporary RSA key sent in a server key exchange message. When
+ temporary RSA keys are used, they are signed by the server's RSA or
+ DSS certificate. The signature includes the current
+ ClientHello.random, so old signatures and temporary keys cannot be
+ replayed. Servers may use a single temporary RSA key for multiple
+ negotiation sessions.
+
+ Note: The temporary RSA key option is useful if servers need large
+ certificates but must comply with government-imposed size limits
+ on keys used for key exchange.
+
+ After verifying the server's certificate, the client encrypts a
+ pre_master_secret with the server's public key. By successfully
+ decoding the pre_master_secret and producing a correct finished
+ message, the server demonstrates that it knows the private key
+ corresponding to the server certificate.
+
+ When RSA is used for key exchange, clients are authenticated using
+ the certificate verify message (see Section 7.4.8). The client signs
+ a value derived from the master_secret and all preceding handshake
+ messages. These handshake messages include the server certificate,
+ which binds the signature to the server, and ServerHello.random,
+ which binds the signature to the current handshake process.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 70]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+F.1.1.3. Diffie-Hellman key exchange with authentication
+
+ When Diffie-Hellman key exchange is used, the server can either
+ supply a certificate containing fixed Diffie-Hellman parameters or
+ can use the server key exchange message to send a set of temporary
+ Diffie-Hellman parameters signed with a DSS or RSA certificate.
+ Temporary parameters are hashed with the hello.random values before
+ signing to ensure that attackers do not replay old parameters. In
+ either case, the client can verify the certificate or signature to
+ ensure that the parameters belong to the server.
+
+ If the client has a certificate containing fixed Diffie-Hellman
+ parameters, its certificate contains the information required to
+ complete the key exchange. Note that in this case the client and
+ server will generate the same Diffie-Hellman result (i.e.,
+ pre_master_secret) every time they communicate. To prevent the
+ pre_master_secret from staying in memory any longer than necessary,
+ it should be converted into the master_secret as soon as possible.
+ Client Diffie-Hellman parameters must be compatible with those
+ supplied by the server for the key exchange to work.
+
+ If the client has a standard DSS or RSA certificate or is
+ unauthenticated, it sends a set of temporary parameters to the server
+ in the client key exchange message, then optionally uses a
+ certificate verify message to authenticate itself.
+
+F.1.2. Version rollback attacks
+
+ Because TLS includes substantial improvements over SSL Version 2.0,
+ attackers may try to make TLS-capable clients and servers fall back
+ to Version 2.0. This attack can occur if (and only if) two TLS-
+ capable parties use an SSL 2.0 handshake.
+
+ Although the solution using non-random PKCS #1 block type 2 message
+ padding is inelegant, it provides a reasonably secure way for Version
+ 3.0 servers to detect the attack. This solution is not secure against
+ attackers who can brute force the key and substitute a new
+ ENCRYPTED-KEY-DATA message containing the same key (but with normal
+ padding) before the application specified wait threshold has expired.
+ Parties concerned about attacks of this scale should not be using
+ 40-bit encryption keys anyway. Altering the padding of the least-
+ significant 8 bytes of the PKCS padding does not impact security for
+ the size of the signed hashes and RSA key lengths used in the
+ protocol, since this is essentially equivalent to increasing the
+ input block size by 8 bytes.
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 71]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+F.1.3. Detecting attacks against the handshake protocol
+
+ An attacker might try to influence the handshake exchange to make the
+ parties select different encryption algorithms than they would
+ normally choose. Because many implementations will support 40-bit
+ exportable encryption and some may even support null encryption or
+ MAC algorithms, this attack is of particular concern.
+
+ For this attack, an attacker must actively change one or more
+ handshake messages. If this occurs, the client and server will
+ compute different values for the handshake message hashes. As a
+ result, the parties will not accept each others' finished messages.
+ Without the master_secret, the attacker cannot repair the finished
+ messages, so the attack will be discovered.
+
+F.1.4. Resuming sessions
+
+ When a connection is established by resuming a session, new
+ ClientHello.random and ServerHello.random values are hashed with the
+ session's master_secret. Provided that the master_secret has not been
+ compromised and that the secure hash operations used to produce the
+ encryption keys and MAC secrets are secure, the connection should be
+ secure and effectively independent from previous connections.
+ Attackers cannot use known encryption keys or MAC secrets to
+ compromise the master_secret without breaking the secure hash
+ operations (which use both SHA and MD5).
+
+ Sessions cannot be resumed unless both the client and server agree.
+ If either party suspects that the session may have been compromised,
+ or that certificates may have expired or been revoked, it should
+ force a full handshake. An upper limit of 24 hours is suggested for
+ session ID lifetimes, since an attacker who obtains a master_secret
+ may be able to impersonate the compromised party until the
+ corresponding session ID is retired. Applications that may be run in
+ relatively insecure environments should not write session IDs to
+ stable storage.
+
+F.1.5. MD5 and SHA
+
+ TLS uses hash functions very conservatively. Where possible, both MD5
+ and SHA are used in tandem to ensure that non-catastrophic flaws in
+ one algorithm will not break the overall protocol.
+
+F.2. Protecting application data
+
+ The master_secret is hashed with the ClientHello.random and
+ ServerHello.random to produce unique data encryption keys and MAC
+ secrets for each connection.
+
+
+
+Dierks & Allen Standards Track [Page 72]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Outgoing data is protected with a MAC before transmission. To prevent
+ message replay or modification attacks, the MAC is computed from the
+ MAC secret, the sequence number, the message length, the message
+ contents, and two fixed character strings. The message type field is
+ necessary to ensure that messages intended for one TLS Record Layer
+ client are not redirected to another. The sequence number ensures
+ that attempts to delete or reorder messages will be detected. Since
+ sequence numbers are 64-bits long, they should never overflow.
+ Messages from one party cannot be inserted into the other's output,
+ since they use independent MAC secrets. Similarly, the server-write
+ and client-write keys are independent so stream cipher keys are used
+ only once.
+
+ If an attacker does break an encryption key, all messages encrypted
+ with it can be read. Similarly, compromise of a MAC key can make
+ message modification attacks possible. Because MACs are also
+ encrypted, message-alteration attacks generally require breaking the
+ encryption algorithm as well as the MAC.
+
+ Note: MAC secrets may be larger than encryption keys, so messages can
+ remain tamper resistant even if encryption keys are broken.
+
+F.3. Final notes
+
+ For TLS to be able to provide a secure connection, both the client
+ and server systems, keys, and applications must be secure. In
+ addition, the implementation must be free of security errors.
+
+ The system is only as strong as the weakest key exchange and
+ authentication algorithm supported, and only trustworthy
+ cryptographic functions should be used. Short public keys, 40-bit
+ bulk encryption keys, and anonymous servers should be used with great
+ caution. Implementations and users must be careful when deciding
+ which certificates and certificate authorities are acceptable; a
+ dishonest certificate authority can do tremendous damage.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 73]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+G. Patent Statement
+
+ Some of the cryptographic algorithms proposed for use in this
+ protocol have patent claims on them. In addition Netscape
+ Communications Corporation has a patent claim on the Secure Sockets
+ Layer (SSL) work that this standard is based on. The Internet
+ Standards Process as defined in RFC 2026 requests that a statement be
+ obtained from a Patent holder indicating that a license will be made
+ available to applicants under reasonable terms and conditions.
+
+ The Massachusetts Institute of Technology has granted RSA Data
+ Security, Inc., exclusive sub-licensing rights to the following
+ patent issued in the United States:
+
+ Cryptographic Communications System and Method ("RSA"), No.
+ 4,405,829
+
+ Netscape Communications Corporation has been issued the following
+ patent in the United States:
+
+ Secure Socket Layer Application Program Apparatus And Method
+ ("SSL"), No. 5,657,390
+
+ Netscape Communications has issued the following statement:
+
+ Intellectual Property Rights
+
+ Secure Sockets Layer
+
+ The United States Patent and Trademark Office ("the PTO")
+ recently issued U.S. Patent No. 5,657,390 ("the SSL Patent") to
+ Netscape for inventions described as Secure Sockets Layers
+ ("SSL"). The IETF is currently considering adopting SSL as a
+ transport protocol with security features. Netscape encourages
+ the royalty-free adoption and use of the SSL protocol upon the
+ following terms and conditions:
+
+ * If you already have a valid SSL Ref license today which
+ includes source code from Netscape, an additional patent
+ license under the SSL patent is not required.
+
+ * If you don't have an SSL Ref license, you may have a royalty
+ free license to build implementations covered by the SSL
+ Patent Claims or the IETF TLS specification provided that you
+ do not to assert any patent rights against Netscape or other
+ companies for the implementation of SSL or the IETF TLS
+ recommendation.
+
+
+
+
+Dierks & Allen Standards Track [Page 74]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ What are "Patent Claims":
+
+ Patent claims are claims in an issued foreign or domestic patent
+ that:
+
+ 1) must be infringed in order to implement methods or build
+ products according to the IETF TLS specification; or
+
+ 2) patent claims which require the elements of the SSL patent
+ claims and/or their equivalents to be infringed.
+
+ The Internet Society, Internet Architecture Board, Internet
+ Engineering Steering Group and the Corporation for National Research
+ Initiatives take no position on the validity or scope of the patents
+ and patent applications, nor on the appropriateness of the terms of
+ the assurance. The Internet Society and other groups mentioned above
+ have not made any determination as to any other intellectual property
+ rights which may apply to the practice of this standard. Any further
+ consideration of these matters is the user's own responsibility.
+
+Security Considerations
+
+ Security issues are discussed throughout this memo.
+
+References
+
+ [3DES] W. Tuchman, "Hellman Presents No Shortcut Solutions To DES,"
+ IEEE Spectrum, v. 16, n. 7, July 1979, pp40-41.
+
+ [BLEI] Bleichenbacher D., "Chosen Ciphertext Attacks against
+ Protocols Based on RSA Encryption Standard PKCS #1" in
+ Advances in Cryptology -- CRYPTO'98, LNCS vol. 1462, pages:
+ 1--12, 1998.
+
+ [DES] ANSI X3.106, "American National Standard for Information
+ Systems-Data Link Encryption," American National Standards
+ Institute, 1983.
+
+ [DH1] W. Diffie and M. E. Hellman, "New Directions in
+ Cryptography," IEEE Transactions on Information Theory, V.
+ IT-22, n. 6, Jun 1977, pp. 74-84.
+
+ [DSS] NIST FIPS PUB 186, "Digital Signature Standard," National
+ Institute of Standards and Technology, U.S. Department of
+ Commerce, May 18, 1994.
+
+ [FTP] Postel J., and J. Reynolds, "File Transfer Protocol", STD 9,
+ RFC 959, October 1985.
+
+
+
+Dierks & Allen Standards Track [Page 75]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ [HTTP] Berners-Lee, T., Fielding, R., and H. Frystyk, "Hypertext
+ Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
+
+ [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
+ Hashing for Message Authentication," RFC 2104, February
+ 1997.
+
+ [IDEA] X. Lai, "On the Design and Security of Block Ciphers," ETH
+ Series in Information Processing, v. 1, Konstanz: Hartung-
+ Gorre Verlag, 1992.
+
+ [MD2] Kaliski, B., "The MD2 Message Digest Algorithm", RFC 1319,
+ April 1992.
+
+ [MD5] Rivest, R., "The MD5 Message Digest Algorithm", RFC 1321,
+ April 1992.
+
+ [PKCS1] RSA Laboratories, "PKCS #1: RSA Encryption Standard,"
+ version 1.5, November 1993.
+
+ [PKCS6] RSA Laboratories, "PKCS #6: RSA Extended Certificate Syntax
+ Standard," version 1.5, November 1993.
+
+ [PKCS7] RSA Laboratories, "PKCS #7: RSA Cryptographic Message Syntax
+ Standard," version 1.5, November 1993.
+
+ [PKIX] Housley, R., Ford, W., Polk, W. and D. Solo, "Internet
+ Public Key Infrastructure: Part I: X.509 Certificate and CRL
+ Profile", RFC 2459, January 1999.
+
+ [RC2] Rivest, R., "A Description of the RC2(r) Encryption
+ Algorithm", RFC 2268, January 1998.
+
+ [RC4] Thayer, R. and K. Kaukonen, A Stream Cipher Encryption
+ Algorithm, Work in Progress.
+
+ [RSA] R. Rivest, A. Shamir, and L. M. Adleman, "A Method for
+ Obtaining Digital Signatures and Public-Key Cryptosystems,"
+ Communications of the ACM, v. 21, n. 2, Feb 1978, pp. 120-
+ 126.
+
+ [RSADSI] Contact RSA Data Security, Inc., Tel: 415-595-8782
+
+ [SCH] B. Schneier. Applied Cryptography: Protocols, Algorithms,
+ and Source Code in C, Published by John Wiley & Sons, Inc.
+ 1994.
+
+
+
+
+
+Dierks & Allen Standards Track [Page 76]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ [SHA] NIST FIPS PUB 180-1, "Secure Hash Standard," National
+ Institute of Standards and Technology, U.S. Department of
+ Commerce, Work in Progress, May 31, 1994.
+
+ [SSL2] Hickman, Kipp, "The SSL Protocol", Netscape Communications
+ Corp., Feb 9, 1995.
+
+ [SSL3] A. Frier, P. Karlton, and P. Kocher, "The SSL 3.0 Protocol",
+ Netscape Communications Corp., Nov 18, 1996.
+
+ [TCP] Postel, J., "Transmission Control Protocol," STD 7, RFC 793,
+ September 1981.
+
+ [TEL] Postel J., and J. Reynolds, "Telnet Protocol
+ Specifications", STD 8, RFC 854, May 1993.
+
+ [TEL] Postel J., and J. Reynolds, "Telnet Option Specifications",
+ STD 8, RFC 855, May 1993.
+
+ [X509] CCITT. Recommendation X.509: "The Directory - Authentication
+ Framework". 1988.
+
+ [XDR] R. Srinivansan, Sun Microsystems, RFC-1832: XDR: External
+ Data Representation Standard, August 1995.
+
+Credits
+
+ Win Treese
+ Open Market
+
+ EMail: treese@openmarket.com
+
+
+ Editors
+
+ Christopher Allen Tim Dierks
+ Certicom Certicom
+
+ EMail: callen@certicom.com EMail: tdierks@certicom.com
+
+
+ Authors' Addresses
+
+ Tim Dierks Philip L. Karlton
+ Certicom Netscape Communications
+
+ EMail: tdierks@certicom.com
+
+
+
+
+Dierks & Allen Standards Track [Page 77]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Alan O. Freier Paul C. Kocher
+ Netscape Communications Independent Consultant
+
+ EMail: freier@netscape.com EMail: pck@netcom.com
+
+
+ Other contributors
+
+ Martin Abadi Robert Relyea
+ Digital Equipment Corporation Netscape Communications
+
+ EMail: ma@pa.dec.com EMail: relyea@netscape.com
+
+ Ran Canetti Jim Roskind
+ IBM Watson Research Center Netscape Communications
+
+ EMail: canetti@watson.ibm.com EMail: jar@netscape.com
+
+
+ Taher Elgamal Micheal J. Sabin, Ph. D.
+ Securify Consulting Engineer
+
+ EMail: elgamal@securify.com EMail: msabin@netcom.com
+
+
+ Anil R. Gangolli Dan Simon
+ Structured Arts Computing Corp. Microsoft
+
+ EMail: gangolli@structuredarts.com EMail: dansimon@microsoft.com
+
+
+ Kipp E.B. Hickman Tom Weinstein
+ Netscape Communications Netscape Communications
+
+ EMail: kipp@netscape.com EMail: tomw@netscape.com
+
+
+ Hugo Krawczyk
+ IBM Watson Research Center
+
+ EMail: hugo@watson.ibm.com
+
+Comments
+
+ The discussion list for the IETF TLS working group is located at the
+ e-mail address <ietf-tls@lists.consensus.com>. Information on the
+ group and information on how to subscribe to the list is at
+ <http://lists.consensus.com/>.
+
+
+
+Dierks & Allen Standards Track [Page 78]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+ Archives of the list can be found at:
+ <http://www.imc.org/ietf-tls/mail-archive/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 79]
+
+RFC 2246 The TLS Protocol Version 1.0 January 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Dierks & Allen Standards Track [Page 80]
+
diff --git a/standards/rfc2396.txt b/standards/rfc2396.txt
new file mode 100644
index 000000000..5bd52110a
--- /dev/null
+++ b/standards/rfc2396.txt
@@ -0,0 +1,2243 @@
+
+
+
+
+
+
+Network Working Group T. Berners-Lee
+Request for Comments: 2396 MIT/LCS
+Updates: 1808, 1738 R. Fielding
+Category: Standards Track U.C. Irvine
+ L. Masinter
+ Xerox Corporation
+ August 1998
+
+
+ Uniform Resource Identifiers (URI): Generic Syntax
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+IESG Note
+
+ This paper describes a "superset" of operations that can be applied
+ to URI. It consists of both a grammar and a description of basic
+ functionality for URI. To understand what is a valid URI, both the
+ grammar and the associated description have to be studied. Some of
+ the functionality described is not applicable to all URI schemes, and
+ some operations are only possible when certain media types are
+ retrieved using the URI, regardless of the scheme used.
+
+Abstract
+
+ A Uniform Resource Identifier (URI) is a compact string of characters
+ for identifying an abstract or physical resource. This document
+ defines the generic syntax of URI, including both absolute and
+ relative forms, and guidelines for their use; it revises and replaces
+ the generic definitions in RFC 1738 and RFC 1808.
+
+ This document defines a grammar that is a superset of all valid URI,
+ such that an implementation can parse the common components of a URI
+ reference without knowing the scheme-specific requirements of every
+ possible identifier type. This document does not define a generative
+ grammar for URI; that task will be performed by the individual
+ specifications of each URI scheme.
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 1]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+1. Introduction
+
+ Uniform Resource Identifiers (URI) provide a simple and extensible
+ means for identifying a resource. This specification of URI syntax
+ and semantics is derived from concepts introduced by the World Wide
+ Web global information initiative, whose use of such objects dates
+ from 1990 and is described in "Universal Resource Identifiers in WWW"
+ [RFC1630]. The specification of URI is designed to meet the
+ recommendations laid out in "Functional Recommendations for Internet
+ Resource Locators" [RFC1736] and "Functional Requirements for Uniform
+ Resource Names" [RFC1737].
+
+ This document updates and merges "Uniform Resource Locators"
+ [RFC1738] and "Relative Uniform Resource Locators" [RFC1808] in order
+ to define a single, generic syntax for all URI. It excludes those
+ portions of RFC 1738 that defined the specific syntax of individual
+ URL schemes; those portions will be updated as separate documents, as
+ will the process for registration of new URI schemes. This document
+ does not discuss the issues and recommendation for dealing with
+ characters outside of the US-ASCII character set [ASCII]; those
+ recommendations are discussed in a separate document.
+
+ All significant changes from the prior RFCs are noted in Appendix G.
+
+1.1 Overview of URI
+
+ URI are characterized by the following definitions:
+
+ Uniform
+ Uniformity provides several benefits: it allows different types
+ of resource identifiers to be used in the same context, even
+ when the mechanisms used to access those resources may differ;
+ it allows uniform semantic interpretation of common syntactic
+ conventions across different types of resource identifiers; it
+ allows introduction of new types of resource identifiers
+ without interfering with the way that existing identifiers are
+ used; and, it allows the identifiers to be reused in many
+ different contexts, thus permitting new applications or
+ protocols to leverage a pre-existing, large, and widely-used
+ set of resource identifiers.
+
+ Resource
+ A resource can be anything that has identity. Familiar
+ examples include an electronic document, an image, a service
+ (e.g., "today's weather report for Los Angeles"), and a
+ collection of other resources. Not all resources are network
+ "retrievable"; e.g., human beings, corporations, and bound
+ books in a library can also be considered resources.
+
+
+
+Berners-Lee, et. al. Standards Track [Page 2]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ The resource is the conceptual mapping to an entity or set of
+ entities, not necessarily the entity which corresponds to that
+ mapping at any particular instance in time. Thus, a resource
+ can remain constant even when its content---the entities to
+ which it currently corresponds---changes over time, provided
+ that the conceptual mapping is not changed in the process.
+
+ Identifier
+ An identifier is an object that can act as a reference to
+ something that has identity. In the case of URI, the object is
+ a sequence of characters with a restricted syntax.
+
+ Having identified a resource, a system may perform a variety of
+ operations on the resource, as might be characterized by such words
+ as `access', `update', `replace', or `find attributes'.
+
+1.2. URI, URL, and URN
+
+ A URI can be further classified as a locator, a name, or both. The
+ term "Uniform Resource Locator" (URL) refers to the subset of URI
+ that identify resources via a representation of their primary access
+ mechanism (e.g., their network "location"), rather than identifying
+ the resource by name or by some other attribute(s) of that resource.
+ The term "Uniform Resource Name" (URN) refers to the subset of URI
+ that are required to remain globally unique and persistent even when
+ the resource ceases to exist or becomes unavailable.
+
+ The URI scheme (Section 3.1) defines the namespace of the URI, and
+ thus may further restrict the syntax and semantics of identifiers
+ using that scheme. This specification defines those elements of the
+ URI syntax that are either required of all URI schemes or are common
+ to many URI schemes. It thus defines the syntax and semantics that
+ are needed to implement a scheme-independent parsing mechanism for
+ URI references, such that the scheme-dependent handling of a URI can
+ be postponed until the scheme-dependent semantics are needed. We use
+ the term URL below when describing syntax or semantics that only
+ apply to locators.
+
+ Although many URL schemes are named after protocols, this does not
+ imply that the only way to access the URL's resource is via the named
+ protocol. Gateways, proxies, caches, and name resolution services
+ might be used to access some resources, independent of the protocol
+ of their origin, and the resolution of some URL may require the use
+ of more than one protocol (e.g., both DNS and HTTP are typically used
+ to access an "http" URL's resource when it can't be found in a local
+ cache).
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 3]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ A URN differs from a URL in that it's primary purpose is persistent
+ labeling of a resource with an identifier. That identifier is drawn
+ from one of a set of defined namespaces, each of which has its own
+ set name structure and assignment procedures. The "urn" scheme has
+ been reserved to establish the requirements for a standardized URN
+ namespace, as defined in "URN Syntax" [RFC2141] and its related
+ specifications.
+
+ Most of the examples in this specification demonstrate URL, since
+ they allow the most varied use of the syntax and often have a
+ hierarchical namespace. A parser of the URI syntax is capable of
+ parsing both URL and URN references as a generic URI; once the scheme
+ is determined, the scheme-specific parsing can be performed on the
+ generic URI components. In other words, the URI syntax is a superset
+ of the syntax of all URI schemes.
+
+1.3. Example URI
+
+ The following examples illustrate URI that are in common use.
+
+ ftp://ftp.is.co.za/rfc/rfc1808.txt
+ -- ftp scheme for File Transfer Protocol services
+
+ gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles
+ -- gopher scheme for Gopher and Gopher+ Protocol services
+
+ http://www.math.uio.no/faq/compression-faq/part1.html
+ -- http scheme for Hypertext Transfer Protocol services
+
+ mailto:mduerst@ifi.unizh.ch
+ -- mailto scheme for electronic mail addresses
+
+ news:comp.infosystems.www.servers.unix
+ -- news scheme for USENET news groups and articles
+
+ telnet://melvyl.ucop.edu/
+ -- telnet scheme for interactive services via the TELNET Protocol
+
+1.4. Hierarchical URI and Relative Forms
+
+ An absolute identifier refers to a resource independent of the
+ context in which the identifier is used. In contrast, a relative
+ identifier refers to a resource by describing the difference within a
+ hierarchical namespace between the current context and an absolute
+ identifier of the resource.
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 4]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ Some URI schemes support a hierarchical naming system, where the
+ hierarchy of the name is denoted by a "/" delimiter separating the
+ components in the scheme. This document defines a scheme-independent
+ `relative' form of URI reference that can be used in conjunction with
+ a `base' URI (of a hierarchical scheme) to produce another URI. The
+ syntax of hierarchical URI is described in Section 3; the relative
+ URI calculation is described in Section 5.
+
+1.5. URI Transcribability
+
+ The URI syntax was designed with global transcribability as one of
+ its main concerns. A URI is a sequence of characters from a very
+ limited set, i.e. the letters of the basic Latin alphabet, digits,
+ and a few special characters. A URI may be represented in a variety
+ of ways: e.g., ink on paper, pixels on a screen, or a sequence of
+ octets in a coded character set. The interpretation of a URI depends
+ only on the characters used and not how those characters are
+ represented in a network protocol.
+
+ The goal of transcribability can be described by a simple scenario.
+ Imagine two colleagues, Sam and Kim, sitting in a pub at an
+ international conference and exchanging research ideas. Sam asks Kim
+ for a location to get more information, so Kim writes the URI for the
+ research site on a napkin. Upon returning home, Sam takes out the
+ napkin and types the URI into a computer, which then retrieves the
+ information to which Kim referred.
+
+ There are several design concerns revealed by the scenario:
+
+ o A URI is a sequence of characters, which is not always
+ represented as a sequence of octets.
+
+ o A URI may be transcribed from a non-network source, and thus
+ should consist of characters that are most likely to be able to
+ be typed into a computer, within the constraints imposed by
+ keyboards (and related input devices) across languages and
+ locales.
+
+ o A URI often needs to be remembered by people, and it is easier
+ for people to remember a URI when it consists of meaningful
+ components.
+
+ These design concerns are not always in alignment. For example, it
+ is often the case that the most meaningful name for a URI component
+ would require characters that cannot be typed into some systems. The
+ ability to transcribe the resource identifier from one medium to
+ another was considered more important than having its URI consist of
+ the most meaningful of components. In local and regional contexts
+
+
+
+Berners-Lee, et. al. Standards Track [Page 5]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ and with improving technology, users might benefit from being able to
+ use a wider range of characters; such use is not defined in this
+ document.
+
+1.6. Syntax Notation and Common Elements
+
+ This document uses two conventions to describe and define the syntax
+ for URI. The first, called the layout form, is a general description
+ of the order of components and component separators, as in
+
+ <first>/<second>;<third>?<fourth>
+
+ The component names are enclosed in angle-brackets and any characters
+ outside angle-brackets are literal separators. Whitespace should be
+ ignored. These descriptions are used informally and do not define
+ the syntax requirements.
+
+ The second convention is a BNF-like grammar, used to define the
+ formal URI syntax. The grammar is that of [RFC822], except that "|"
+ is used to designate alternatives. Briefly, rules are separated from
+ definitions by an equal "=", indentation is used to continue a rule
+ definition over more than one line, literals are quoted with "",
+ parentheses "(" and ")" are used to group elements, optional elements
+ are enclosed in "[" and "]" brackets, and elements may be preceded
+ with <n>* to designate n or more repetitions of the following
+ element; n defaults to 0.
+
+ Unlike many specifications that use a BNF-like grammar to define the
+ bytes (octets) allowed by a protocol, the URI grammar is defined in
+ terms of characters. Each literal in the grammar corresponds to the
+ character it represents, rather than to the octet encoding of that
+ character in any particular coded character set. How a URI is
+ represented in terms of bits and bytes on the wire is dependent upon
+ the character encoding of the protocol used to transport it, or the
+ charset of the document which contains it.
+
+ The following definitions are common to many elements:
+
+ alpha = lowalpha | upalpha
+
+ lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+ "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+ "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
+
+ upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
+ "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
+ "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 6]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+ "8" | "9"
+
+ alphanum = alpha | digit
+
+ The complete URI syntax is collected in Appendix A.
+
+2. URI Characters and Escape Sequences
+
+ URI consist of a restricted set of characters, primarily chosen to
+ aid transcribability and usability both in computer systems and in
+ non-computer communications. Characters used conventionally as
+ delimiters around URI were excluded. The restricted set of
+ characters consists of digits, letters, and a few graphic symbols
+ were chosen from those common to most of the character encodings and
+ input facilities available to Internet users.
+
+ uric = reserved | unreserved | escaped
+
+ Within a URI, characters are either used as delimiters, or to
+ represent strings of data (octets) within the delimited portions.
+ Octets are either represented directly by a character (using the US-
+ ASCII character for that octet [ASCII]) or by an escape encoding.
+ This representation is elaborated below.
+
+2.1 URI and non-ASCII characters
+
+ The relationship between URI and characters has been a source of
+ confusion for characters that are not part of US-ASCII. To describe
+ the relationship, it is useful to distinguish between a "character"
+ (as a distinguishable semantic entity) and an "octet" (an 8-bit
+ byte). There are two mappings, one from URI characters to octets, and
+ a second from octets to original characters:
+
+ URI character sequence->octet sequence->original character sequence
+
+ A URI is represented as a sequence of characters, not as a sequence
+ of octets. That is because URI might be "transported" by means that
+ are not through a computer network, e.g., printed on paper, read over
+ the radio, etc.
+
+ A URI scheme may define a mapping from URI characters to octets;
+ whether this is done depends on the scheme. Commonly, within a
+ delimited component of a URI, a sequence of characters may be used to
+ represent a sequence of octets. For example, the character "a"
+ represents the octet 97 (decimal), while the character sequence "%",
+ "0", "a" represents the octet 10 (decimal).
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 7]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ There is a second translation for some resources: the sequence of
+ octets defined by a component of the URI is subsequently used to
+ represent a sequence of characters. A 'charset' defines this mapping.
+ There are many charsets in use in Internet protocols. For example,
+ UTF-8 [UTF-8] defines a mapping from sequences of octets to sequences
+ of characters in the repertoire of ISO 10646.
+
+ In the simplest case, the original character sequence contains only
+ characters that are defined in US-ASCII, and the two levels of
+ mapping are simple and easily invertible: each 'original character'
+ is represented as the octet for the US-ASCII code for it, which is,
+ in turn, represented as either the US-ASCII character, or else the
+ "%" escape sequence for that octet.
+
+ For original character sequences that contain non-ASCII characters,
+ however, the situation is more difficult. Internet protocols that
+ transmit octet sequences intended to represent character sequences
+ are expected to provide some way of identifying the charset used, if
+ there might be more than one [RFC2277]. However, there is currently
+ no provision within the generic URI syntax to accomplish this
+ identification. An individual URI scheme may require a single
+ charset, define a default charset, or provide a way to indicate the
+ charset used.
+
+ It is expected that a systematic treatment of character encoding
+ within URI will be developed as a future modification of this
+ specification.
+
+2.2. Reserved Characters
+
+ Many URI include components consisting of or delimited by, certain
+ special characters. These characters are called "reserved", since
+ their usage within the URI component is limited to their reserved
+ purpose. If the data for a URI component would conflict with the
+ reserved purpose, then the conflicting data must be escaped before
+ forming the URI.
+
+ reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+ "$" | ","
+
+ The "reserved" syntax class above refers to those characters that are
+ allowed within a URI, but which may not be allowed within a
+ particular component of the generic URI syntax; they are used as
+ delimiters of the components described in Section 3.
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 8]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ Characters in the "reserved" set are not reserved in all contexts.
+ The set of characters actually reserved within any given URI
+ component is defined by that component. In general, a character is
+ reserved if the semantics of the URI changes if the character is
+ replaced with its escaped US-ASCII encoding.
+
+2.3. Unreserved Characters
+
+ Data characters that are allowed in a URI but do not have a reserved
+ purpose are called unreserved. These include upper and lower case
+ letters, decimal digits, and a limited set of punctuation marks and
+ symbols.
+
+ unreserved = alphanum | mark
+
+ mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+
+ Unreserved characters can be escaped without changing the semantics
+ of the URI, but this should not be done unless the URI is being used
+ in a context that does not allow the unescaped character to appear.
+
+2.4. Escape Sequences
+
+ Data must be escaped if it does not have a representation using an
+ unreserved character; this includes data that does not correspond to
+ a printable character of the US-ASCII coded character set, or that
+ corresponds to any US-ASCII character that is disallowed, as
+ explained below.
+
+2.4.1. Escaped Encoding
+
+ An escaped octet is encoded as a character triplet, consisting of the
+ percent character "%" followed by the two hexadecimal digits
+ representing the octet code. For example, "%20" is the escaped
+ encoding for the US-ASCII space character.
+
+ escaped = "%" hex hex
+ hex = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+ "a" | "b" | "c" | "d" | "e" | "f"
+
+2.4.2. When to Escape and Unescape
+
+ A URI is always in an "escaped" form, since escaping or unescaping a
+ completed URI might change its semantics. Normally, the only time
+ escape encodings can safely be made is when the URI is being created
+ from its component parts; each component may have its own set of
+ characters that are reserved, so only the mechanism responsible for
+ generating or interpreting that component can determine whether or
+
+
+
+Berners-Lee, et. al. Standards Track [Page 9]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ not escaping a character will change its semantics. Likewise, a URI
+ must be separated into its components before the escaped characters
+ within those components can be safely decoded.
+
+ In some cases, data that could be represented by an unreserved
+ character may appear escaped; for example, some of the unreserved
+ "mark" characters are automatically escaped by some systems. If the
+ given URI scheme defines a canonicalization algorithm, then
+ unreserved characters may be unescaped according to that algorithm.
+ For example, "%7e" is sometimes used instead of "~" in an http URL
+ path, but the two are equivalent for an http URL.
+
+ Because the percent "%" character always has the reserved purpose of
+ being the escape indicator, it must be escaped as "%25" in order to
+ be used as data within a URI. Implementers should be careful not to
+ escape or unescape the same string more than once, since unescaping
+ an already unescaped string might lead to misinterpreting a percent
+ data character as another escaped character, or vice versa in the
+ case of escaping an already escaped string.
+
+2.4.3. Excluded US-ASCII Characters
+
+ Although they are disallowed within the URI syntax, we include here a
+ description of those US-ASCII characters that have been excluded and
+ the reasons for their exclusion.
+
+ The control characters in the US-ASCII coded character set are not
+ used within a URI, both because they are non-printable and because
+ they are likely to be misinterpreted by some control mechanisms.
+
+ control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
+
+ The space character is excluded because significant spaces may
+ disappear and insignificant spaces may be introduced when URI are
+ transcribed or typeset or subjected to the treatment of word-
+ processing programs. Whitespace is also used to delimit URI in many
+ contexts.
+
+ space = <US-ASCII coded character 20 hexadecimal>
+
+ The angle-bracket "<" and ">" and double-quote (") characters are
+ excluded because they are often used as the delimiters around URI in
+ text documents and protocol fields. The character "#" is excluded
+ because it is used to delimit a URI from a fragment identifier in URI
+ references (Section 4). The percent character "%" is excluded because
+ it is used for the encoding of escaped characters.
+
+ delims = "<" | ">" | "#" | "%" | <">
+
+
+
+Berners-Lee, et. al. Standards Track [Page 10]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ Other characters are excluded because gateways and other transport
+ agents are known to sometimes modify such characters, or they are
+ used as delimiters.
+
+ unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
+
+ Data corresponding to excluded characters must be escaped in order to
+ be properly represented within a URI.
+
+3. URI Syntactic Components
+
+ The URI syntax is dependent upon the scheme. In general, absolute
+ URI are written as follows:
+
+ <scheme>:<scheme-specific-part>
+
+ An absolute URI contains the name of the scheme being used (<scheme>)
+ followed by a colon (":") and then a string (the <scheme-specific-
+ part>) whose interpretation depends on the scheme.
+
+ The URI syntax does not require that the scheme-specific-part have
+ any general structure or set of semantics which is common among all
+ URI. However, a subset of URI do share a common syntax for
+ representing hierarchical relationships within the namespace. This
+ "generic URI" syntax consists of a sequence of four main components:
+
+ <scheme>://<authority><path>?<query>
+
+ each of which, except <scheme>, may be absent from a particular URI.
+ For example, some URI schemes do not allow an <authority> component,
+ and others do not use a <query> component.
+
+ absoluteURI = scheme ":" ( hier_part | opaque_part )
+
+ URI that are hierarchical in nature use the slash "/" character for
+ separating hierarchical components. For some file systems, a "/"
+ character (used to denote the hierarchical structure of a URI) is the
+ delimiter used to construct a file name hierarchy, and thus the URI
+ path will look similar to a file pathname. This does NOT imply that
+ the resource is a file or that the URI maps to an actual filesystem
+ pathname.
+
+ hier_part = ( net_path | abs_path ) [ "?" query ]
+
+ net_path = "//" authority [ abs_path ]
+
+ abs_path = "/" path_segments
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 11]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ URI that do not make use of the slash "/" character for separating
+ hierarchical components are considered opaque by the generic URI
+ parser.
+
+ opaque_part = uric_no_slash *uric
+
+ uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+ "&" | "=" | "+" | "$" | ","
+
+ We use the term <path> to refer to both the <abs_path> and
+ <opaque_part> constructs, since they are mutually exclusive for any
+ given URI and can be parsed as a single component.
+
+3.1. Scheme Component
+
+ Just as there are many different methods of access to resources,
+ there are a variety of schemes for identifying such resources. The
+ URI syntax consists of a sequence of components separated by reserved
+ characters, with the first component defining the semantics for the
+ remainder of the URI string.
+
+ Scheme names consist of a sequence of characters beginning with a
+ lower case letter and followed by any combination of lower case
+ letters, digits, plus ("+"), period ("."), or hyphen ("-"). For
+ resiliency, programs interpreting URI should treat upper case letters
+ as equivalent to lower case in scheme names (e.g., allow "HTTP" as
+ well as "http").
+
+ scheme = alpha *( alpha | digit | "+" | "-" | "." )
+
+ Relative URI references are distinguished from absolute URI in that
+ they do not begin with a scheme name. Instead, the scheme is
+ inherited from the base URI, as described in Section 5.2.
+
+3.2. Authority Component
+
+ Many URI schemes include a top hierarchical element for a naming
+ authority, such that the namespace defined by the remainder of the
+ URI is governed by that authority. This authority component is
+ typically defined by an Internet-based server or a scheme-specific
+ registry of naming authorities.
+
+ authority = server | reg_name
+
+ The authority component is preceded by a double slash "//" and is
+ terminated by the next slash "/", question-mark "?", or by the end of
+ the URI. Within the authority component, the characters ";", ":",
+ "@", "?", and "/" are reserved.
+
+
+
+Berners-Lee, et. al. Standards Track [Page 12]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ An authority component is not required for a URI scheme to make use
+ of relative references. A base URI without an authority component
+ implies that any relative reference will also be without an authority
+ component.
+
+3.2.1. Registry-based Naming Authority
+
+ The structure of a registry-based naming authority is specific to the
+ URI scheme, but constrained to the allowed characters for an
+ authority component.
+
+ reg_name = 1*( unreserved | escaped | "$" | "," |
+ ";" | ":" | "@" | "&" | "=" | "+" )
+
+3.2.2. Server-based Naming Authority
+
+ URL schemes that involve the direct use of an IP-based protocol to a
+ specified server on the Internet use a common syntax for the server
+ component of the URI's scheme-specific data:
+
+ <userinfo>@<host>:<port>
+
+ where <userinfo> may consist of a user name and, optionally, scheme-
+ specific information about how to gain authorization to access the
+ server. The parts "<userinfo>@" and ":<port>" may be omitted.
+
+ server = [ [ userinfo "@" ] hostport ]
+
+ The user information, if present, is followed by a commercial at-sign
+ "@".
+
+ userinfo = *( unreserved | escaped |
+ ";" | ":" | "&" | "=" | "+" | "$" | "," )
+
+ Some URL schemes use the format "user:password" in the userinfo
+ field. This practice is NOT RECOMMENDED, because the passing of
+ authentication information in clear text (such as URI) has proven to
+ be a security risk in almost every case where it has been used.
+
+ The host is a domain name of a network host, or its IPv4 address as a
+ set of four decimal digit groups separated by ".". Literal IPv6
+ addresses are not supported.
+
+ hostport = host [ ":" port ]
+ host = hostname | IPv4address
+ hostname = *( domainlabel "." ) toplabel [ "." ]
+ domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+
+
+
+Berners-Lee, et. al. Standards Track [Page 13]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
+ port = *digit
+
+ Hostnames take the form described in Section 3 of [RFC1034] and
+ Section 2.1 of [RFC1123]: a sequence of domain labels separated by
+ ".", each domain label starting and ending with an alphanumeric
+ character and possibly also containing "-" characters. The rightmost
+ domain label of a fully qualified domain name will never start with a
+ digit, thus syntactically distinguishing domain names from IPv4
+ addresses, and may be followed by a single "." if it is necessary to
+ distinguish between the complete domain name and any local domain.
+ To actually be "Uniform" as a resource locator, a URL hostname should
+ be a fully qualified domain name. In practice, however, the host
+ component may be a local domain literal.
+
+ Note: A suitable representation for including a literal IPv6
+ address as the host part of a URL is desired, but has not yet been
+ determined or implemented in practice.
+
+ The port is the network port number for the server. Most schemes
+ designate protocols that have a default port number. Another port
+ number may optionally be supplied, in decimal, separated from the
+ host by a colon. If the port is omitted, the default port number is
+ assumed.
+
+3.3. Path Component
+
+ The path component contains data, specific to the authority (or the
+ scheme if there is no authority component), identifying the resource
+ within the scope of that scheme and authority.
+
+ path = [ abs_path | opaque_part ]
+
+ path_segments = segment *( "/" segment )
+ segment = *pchar *( ";" param )
+ param = *pchar
+
+ pchar = unreserved | escaped |
+ ":" | "@" | "&" | "=" | "+" | "$" | ","
+
+ The path may consist of a sequence of path segments separated by a
+ single slash "/" character. Within a path segment, the characters
+ "/", ";", "=", and "?" are reserved. Each path segment may include a
+ sequence of parameters, indicated by the semicolon ";" character.
+ The parameters are not significant to the parsing of relative
+ references.
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 14]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+3.4. Query Component
+
+ The query component is a string of information to be interpreted by
+ the resource.
+
+ query = *uric
+
+ Within a query component, the characters ";", "/", "?", ":", "@",
+ "&", "=", "+", ",", and "$" are reserved.
+
+4. URI References
+
+ The term "URI-reference" is used here to denote the common usage of a
+ resource identifier. A URI reference may be absolute or relative,
+ and may have additional information attached in the form of a
+ fragment identifier. However, "the URI" that results from such a
+ reference includes only the absolute URI after the fragment
+ identifier (if any) is removed and after any relative URI is resolved
+ to its absolute form. Although it is possible to limit the
+ discussion of URI syntax and semantics to that of the absolute
+ result, most usage of URI is within general URI references, and it is
+ impossible to obtain the URI from such a reference without also
+ parsing the fragment and resolving the relative form.
+
+ URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+
+ The syntax for relative URI is a shortened form of that for absolute
+ URI, where some prefix of the URI is missing and certain path
+ components ("." and "..") have a special meaning when, and only when,
+ interpreting a relative path. The relative URI syntax is defined in
+ Section 5.
+
+4.1. Fragment Identifier
+
+ When a URI reference is used to perform a retrieval action on the
+ identified resource, the optional fragment identifier, separated from
+ the URI by a crosshatch ("#") character, consists of additional
+ reference information to be interpreted by the user agent after the
+ retrieval action has been successfully completed. As such, it is not
+ part of a URI, but is often used in conjunction with a URI.
+
+ fragment = *uric
+
+ The semantics of a fragment identifier is a property of the data
+ resulting from a retrieval action, regardless of the type of URI used
+ in the reference. Therefore, the format and interpretation of
+ fragment identifiers is dependent on the media type [RFC2046] of the
+ retrieval result. The character restrictions described in Section 2
+
+
+
+Berners-Lee, et. al. Standards Track [Page 15]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ for URI also apply to the fragment in a URI-reference. Individual
+ media types may define additional restrictions or structure within
+ the fragment for specifying different types of "partial views" that
+ can be identified within that media type.
+
+ A fragment identifier is only meaningful when a URI reference is
+ intended for retrieval and the result of that retrieval is a document
+ for which the identified fragment is consistently defined.
+
+4.2. Same-document References
+
+ A URI reference that does not contain a URI is a reference to the
+ current document. In other words, an empty URI reference within a
+ document is interpreted as a reference to the start of that document,
+ and a reference containing only a fragment identifier is a reference
+ to the identified fragment of that document. Traversal of such a
+ reference should not result in an additional retrieval action.
+ However, if the URI reference occurs in a context that is always
+ intended to result in a new request, as in the case of HTML's FORM
+ element, then an empty URI reference represents the base URI of the
+ current document and should be replaced by that URI when transformed
+ into a request.
+
+4.3. Parsing a URI Reference
+
+ A URI reference is typically parsed according to the four main
+ components and fragment identifier in order to determine what
+ components are present and whether the reference is relative or
+ absolute. The individual components are then parsed for their
+ subparts and, if not opaque, to verify their validity.
+
+ Although the BNF defines what is allowed in each component, it is
+ ambiguous in terms of differentiating between an authority component
+ and a path component that begins with two slash characters. The
+ greedy algorithm is used for disambiguation: the left-most matching
+ rule soaks up as much of the URI reference string as it is capable of
+ matching. In other words, the authority component wins.
+
+ Readers familiar with regular expressions should see Appendix B for a
+ concrete parsing example and test oracle.
+
+5. Relative URI References
+
+ It is often the case that a group or "tree" of documents has been
+ constructed to serve a common purpose; the vast majority of URI in
+ these documents point to resources within the tree rather than
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 16]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ outside of it. Similarly, documents located at a particular site are
+ much more likely to refer to other resources at that site than to
+ resources at remote sites.
+
+ Relative addressing of URI allows document trees to be partially
+ independent of their location and access scheme. For instance, it is
+ possible for a single set of hypertext documents to be simultaneously
+ accessible and traversable via each of the "file", "http", and "ftp"
+ schemes if the documents refer to each other using relative URI.
+ Furthermore, such document trees can be moved, as a whole, without
+ changing any of the relative references. Experience within the WWW
+ has demonstrated that the ability to perform relative referencing is
+ necessary for the long-term usability of embedded URI.
+
+ The syntax for relative URI takes advantage of the <hier_part> syntax
+ of <absoluteURI> (Section 3) in order to express a reference that is
+ relative to the namespace of another hierarchical URI.
+
+ relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+
+ A relative reference beginning with two slash characters is termed a
+ network-path reference, as defined by <net_path> in Section 3. Such
+ references are rarely used.
+
+ A relative reference beginning with a single slash character is
+ termed an absolute-path reference, as defined by <abs_path> in
+ Section 3.
+
+ A relative reference that does not begin with a scheme name or a
+ slash character is termed a relative-path reference.
+
+ rel_path = rel_segment [ abs_path ]
+
+ rel_segment = 1*( unreserved | escaped |
+ ";" | "@" | "&" | "=" | "+" | "$" | "," )
+
+ Within a relative-path reference, the complete path segments "." and
+ ".." have special meanings: "the current hierarchy level" and "the
+ level above this hierarchy level", respectively. Although this is
+ very similar to their use within Unix-based filesystems to indicate
+ directory levels, these path components are only considered special
+ when resolving a relative-path reference to its absolute form
+ (Section 5.2).
+
+ Authors should be aware that a path segment which contains a colon
+ character cannot be used as the first segment of a relative URI path
+ (e.g., "this:that"), because it would be mistaken for a scheme name.
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 17]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ It is therefore necessary to precede such segments with other
+ segments (e.g., "./this:that") in order for them to be referenced as
+ a relative path.
+
+ It is not necessary for all URI within a given scheme to be
+ restricted to the <hier_part> syntax, since the hierarchical
+ properties of that syntax are only necessary when relative URI are
+ used within a particular document. Documents can only make use of
+ relative URI when their base URI fits within the <hier_part> syntax.
+ It is assumed that any document which contains a relative reference
+ will also have a base URI that obeys the syntax. In other words,
+ relative URI cannot be used within a document that has an unsuitable
+ base URI.
+
+ Some URI schemes do not allow a hierarchical syntax matching the
+ <hier_part> syntax, and thus cannot use relative references.
+
+5.1. Establishing a Base URI
+
+ The term "relative URI" implies that there exists some absolute "base
+ URI" against which the relative reference is applied. Indeed, the
+ base URI is necessary to define the semantics of any relative URI
+ reference; without it, a relative reference is meaningless. In order
+ for relative URI to be usable within a document, the base URI of that
+ document must be known to the parser.
+
+ The base URI of a document can be established in one of four ways,
+ listed below in order of precedence. The order of precedence can be
+ thought of in terms of layers, where the innermost defined base URI
+ has the highest precedence. This can be visualized graphically as:
+
+ .----------------------------------------------------------.
+ | .----------------------------------------------------. |
+ | | .----------------------------------------------. | |
+ | | | .----------------------------------------. | | |
+ | | | | .----------------------------------. | | | |
+ | | | | | <relative_reference> | | | | |
+ | | | | `----------------------------------' | | | |
+ | | | | (5.1.1) Base URI embedded in the | | | |
+ | | | | document's content | | | |
+ | | | `----------------------------------------' | | |
+ | | | (5.1.2) Base URI of the encapsulating entity | | |
+ | | | (message, document, or none). | | |
+ | | `----------------------------------------------' | |
+ | | (5.1.3) URI used to retrieve the entity | |
+ | `----------------------------------------------------' |
+ | (5.1.4) Default Base URI is application-dependent |
+ `----------------------------------------------------------'
+
+
+
+Berners-Lee, et. al. Standards Track [Page 18]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+5.1.1. Base URI within Document Content
+
+ Within certain document media types, the base URI of the document can
+ be embedded within the content itself such that it can be readily
+ obtained by a parser. This can be useful for descriptive documents,
+ such as tables of content, which may be transmitted to others through
+ protocols other than their usual retrieval context (e.g., E-Mail or
+ USENET news).
+
+ It is beyond the scope of this document to specify how, for each
+ media type, the base URI can be embedded. It is assumed that user
+ agents manipulating such media types will be able to obtain the
+ appropriate syntax from that media type's specification. An example
+ of how the base URI can be embedded in the Hypertext Markup Language
+ (HTML) [RFC1866] is provided in Appendix D.
+
+ A mechanism for embedding the base URI within MIME container types
+ (e.g., the message and multipart types) is defined by MHTML
+ [RFC2110]. Protocols that do not use the MIME message header syntax,
+ but which do allow some form of tagged metainformation to be included
+ within messages, may define their own syntax for defining the base
+ URI as part of a message.
+
+5.1.2. Base URI from the Encapsulating Entity
+
+ If no base URI is embedded, the base URI of a document is defined by
+ the document's retrieval context. For a document that is enclosed
+ within another entity (such as a message or another document), the
+ retrieval context is that entity; thus, the default base URI of the
+ document is the base URI of the entity in which the document is
+ encapsulated.
+
+5.1.3. Base URI from the Retrieval URI
+
+ If no base URI is embedded and the document is not encapsulated
+ within some other entity (e.g., the top level of a composite entity),
+ then, if a URI was used to retrieve the base document, that URI shall
+ be considered the base URI. Note that if the retrieval was the
+ result of a redirected request, the last URI used (i.e., that which
+ resulted in the actual retrieval of the document) is the base URI.
+
+5.1.4. Default Base URI
+
+ If none of the conditions described in Sections 5.1.1--5.1.3 apply,
+ then the base URI is defined by the context of the application.
+ Since this definition is necessarily application-dependent, failing
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 19]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ to define the base URI using one of the other methods may result in
+ the same content being interpreted differently by different types of
+ application.
+
+ It is the responsibility of the distributor(s) of a document
+ containing relative URI to ensure that the base URI for that document
+ can be established. It must be emphasized that relative URI cannot
+ be used reliably in situations where the document's base URI is not
+ well-defined.
+
+5.2. Resolving Relative References to Absolute Form
+
+ This section describes an example algorithm for resolving URI
+ references that might be relative to a given base URI.
+
+ The base URI is established according to the rules of Section 5.1 and
+ parsed into the four main components as described in Section 3. Note
+ that only the scheme component is required to be present in the base
+ URI; the other components may be empty or undefined. A component is
+ undefined if its preceding separator does not appear in the URI
+ reference; the path component is never undefined, though it may be
+ empty. The base URI's query component is not used by the resolution
+ algorithm and may be discarded.
+
+ For each URI reference, the following steps are performed in order:
+
+ 1) The URI reference is parsed into the potential four components and
+ fragment identifier, as described in Section 4.3.
+
+ 2) If the path component is empty and the scheme, authority, and
+ query components are undefined, then it is a reference to the
+ current document and we are done. Otherwise, the reference URI's
+ query and fragment components are defined as found (or not found)
+ within the URI reference and not inherited from the base URI.
+
+ 3) If the scheme component is defined, indicating that the reference
+ starts with a scheme name, then the reference is interpreted as an
+ absolute URI and we are done. Otherwise, the reference URI's
+ scheme is inherited from the base URI's scheme component.
+
+ Due to a loophole in prior specifications [RFC1630], some parsers
+ allow the scheme name to be present in a relative URI if it is the
+ same as the base URI scheme. Unfortunately, this can conflict
+ with the correct parsing of non-hierarchical URI. For backwards
+ compatibility, an implementation may work around such references
+ by removing the scheme if it matches that of the base URI and the
+ scheme is known to always use the <hier_part> syntax. The parser
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 20]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ can then continue with the steps below for the remainder of the
+ reference components. Validating parsers should mark such a
+ misformed relative reference as an error.
+
+ 4) If the authority component is defined, then the reference is a
+ network-path and we skip to step 7. Otherwise, the reference
+ URI's authority is inherited from the base URI's authority
+ component, which will also be undefined if the URI scheme does not
+ use an authority component.
+
+ 5) If the path component begins with a slash character ("/"), then
+ the reference is an absolute-path and we skip to step 7.
+
+ 6) If this step is reached, then we are resolving a relative-path
+ reference. The relative path needs to be merged with the base
+ URI's path. Although there are many ways to do this, we will
+ describe a simple method using a separate string buffer.
+
+ a) All but the last segment of the base URI's path component is
+ copied to the buffer. In other words, any characters after the
+ last (right-most) slash character, if any, are excluded.
+
+ b) The reference's path component is appended to the buffer
+ string.
+
+ c) All occurrences of "./", where "." is a complete path segment,
+ are removed from the buffer string.
+
+ d) If the buffer string ends with "." as a complete path segment,
+ that "." is removed.
+
+ e) All occurrences of "<segment>/../", where <segment> is a
+ complete path segment not equal to "..", are removed from the
+ buffer string. Removal of these path segments is performed
+ iteratively, removing the leftmost matching pattern on each
+ iteration, until no matching pattern remains.
+
+ f) If the buffer string ends with "<segment>/..", where <segment>
+ is a complete path segment not equal to "..", that
+ "<segment>/.." is removed.
+
+ g) If the resulting buffer string still begins with one or more
+ complete path segments of "..", then the reference is
+ considered to be in error. Implementations may handle this
+ error by retaining these components in the resolved path (i.e.,
+ treating them as part of the final URI), by removing them from
+ the resolved path (i.e., discarding relative levels above the
+ root), or by avoiding traversal of the reference.
+
+
+
+Berners-Lee, et. al. Standards Track [Page 21]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ h) The remaining buffer string is the reference URI's new path
+ component.
+
+ 7) The resulting URI components, including any inherited from the
+ base URI, are recombined to give the absolute form of the URI
+ reference. Using pseudocode, this would be
+
+ result = ""
+
+ if scheme is defined then
+ append scheme to result
+ append ":" to result
+
+ if authority is defined then
+ append "//" to result
+ append authority to result
+
+ append path to result
+
+ if query is defined then
+ append "?" to result
+ append query to result
+
+ if fragment is defined then
+ append "#" to result
+ append fragment to result
+
+ return result
+
+ Note that we must be careful to preserve the distinction between a
+ component that is undefined, meaning that its separator was not
+ present in the reference, and a component that is empty, meaning
+ that the separator was present and was immediately followed by the
+ next component separator or the end of the reference.
+
+ The above algorithm is intended to provide an example by which the
+ output of implementations can be tested -- implementation of the
+ algorithm itself is not required. For example, some systems may find
+ it more efficient to implement step 6 as a pair of segment stacks
+ being merged, rather than as a series of string pattern replacements.
+
+ Note: Some WWW client applications will fail to separate the
+ reference's query component from its path component before merging
+ the base and reference paths in step 6 above. This may result in
+ a loss of information if the query component contains the strings
+ "/../" or "/./".
+
+ Resolution examples are provided in Appendix C.
+
+
+
+Berners-Lee, et. al. Standards Track [Page 22]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+6. URI Normalization and Equivalence
+
+ In many cases, different URI strings may actually identify the
+ identical resource. For example, the host names used in URL are
+ actually case insensitive, and the URL <http://www.XEROX.com> is
+ equivalent to <http://www.xerox.com>. In general, the rules for
+ equivalence and definition of a normal form, if any, are scheme
+ dependent. When a scheme uses elements of the common syntax, it will
+ also use the common syntax equivalence rules, namely that the scheme
+ and hostname are case insensitive and a URL with an explicit ":port",
+ where the port is the default for the scheme, is equivalent to one
+ where the port is elided.
+
+7. Security Considerations
+
+ A URI does not in itself pose a security threat. Users should beware
+ that there is no general guarantee that a URL, which at one time
+ located a given resource, will continue to do so. Nor is there any
+ guarantee that a URL will not locate a different resource at some
+ later point in time, due to the lack of any constraint on how a given
+ authority apportions its namespace. Such a guarantee can only be
+ obtained from the person(s) controlling that namespace and the
+ resource in question. A specific URI scheme may include additional
+ semantics, such as name persistence, if those semantics are required
+ of all naming authorities for that scheme.
+
+ It is sometimes possible to construct a URL such that an attempt to
+ perform a seemingly harmless, idempotent operation, such as the
+ retrieval of an entity associated with the resource, will in fact
+ cause a possibly damaging remote operation to occur. The unsafe URL
+ is typically constructed by specifying a port number other than that
+ reserved for the network protocol in question. The client
+ unwittingly contacts a site that is in fact running a different
+ protocol. The content of the URL contains instructions that, when
+ interpreted according to this other protocol, cause an unexpected
+ operation. An example has been the use of a gopher URL to cause an
+ unintended or impersonating message to be sent via a SMTP server.
+
+ Caution should be used when using any URL that specifies a port
+ number other than the default for the protocol, especially when it is
+ a number within the reserved space.
+
+ Care should be taken when a URL contains escaped delimiters for a
+ given protocol (for example, CR and LF characters for telnet
+ protocols) that these are not unescaped before transmission. This
+ might violate the protocol, but avoids the potential for such
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 23]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ characters to be used to simulate an extra operation or parameter in
+ that protocol, which might lead to an unexpected and possibly harmful
+ remote operation to be performed.
+
+ It is clearly unwise to use a URL that contains a password which is
+ intended to be secret. In particular, the use of a password within
+ the 'userinfo' component of a URL is strongly disrecommended except
+ in those rare cases where the 'password' parameter is intended to be
+ public.
+
+8. Acknowledgements
+
+ This document was derived from RFC 1738 [RFC1738] and RFC 1808
+ [RFC1808]; the acknowledgements in those specifications still apply.
+ In addition, contributions by Gisle Aas, Martin Beet, Martin Duerst,
+ Jim Gettys, Martijn Koster, Dave Kristol, Daniel LaLiberte, Foteos
+ Macrides, James Marshall, Ryan Moats, Keith Moore, and Lauren Wood
+ are gratefully acknowledged.
+
+9. References
+
+ [RFC2277] Alvestrand, H., "IETF Policy on Character Sets and
+ Languages", BCP 18, RFC 2277, January 1998.
+
+ [RFC1630] Berners-Lee, T., "Universal Resource Identifiers in WWW: A
+ Unifying Syntax for the Expression of Names and Addresses
+ of Objects on the Network as used in the World-Wide Web",
+ RFC 1630, June 1994.
+
+ [RFC1738] Berners-Lee, T., Masinter, L., and M. McCahill, Editors,
+ "Uniform Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1866] Berners-Lee T., and D. Connolly, "HyperText Markup Language
+ Specification -- 2.0", RFC 1866, November 1995.
+
+ [RFC1123] Braden, R., Editor, "Requirements for Internet Hosts --
+ Application and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages", STD 11, RFC 822, August 1982.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators", RFC
+ 1808, June 1995.
+
+ [RFC2046] Freed, N., and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 24]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ [RFC1736] Kunze, J., "Functional Recommendations for Internet
+ Resource Locators", RFC 1736, February 1995.
+
+ [RFC2141] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC2110] Palme, J., and A. Hopmann, "MIME E-mail Encapsulation of
+ Aggregate Documents, such as HTML (MHTML)", RFC 2110, March
+ 1997.
+
+ [RFC1737] Sollins, K., and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", RFC 1737, December 1994.
+
+ [ASCII] US-ASCII. "Coded Character Set -- 7-bit American Standard
+ Code for Information Interchange", ANSI X3.4-1986.
+
+ [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO 10646",
+ RFC 2279, January 1998.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 25]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+10. Authors' Addresses
+
+ Tim Berners-Lee
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science, NE43-356
+ 545 Technology Square
+ Cambridge, MA 02139
+
+ Fax: +1(617)258-8682
+ EMail: timbl@w3.org
+
+
+ Roy T. Fielding
+ Department of Information and Computer Science
+ University of California, Irvine
+ Irvine, CA 92697-3425
+
+ Fax: +1(949)824-1715
+ EMail: fielding@ics.uci.edu
+
+
+ Larry Masinter
+ Xerox PARC
+ 3333 Coyote Hill Road
+ Palo Alto, CA 94034
+
+ Fax: +1(415)812-4333
+ EMail: masinter@parc.xerox.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 26]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+A. Collected BNF for URI
+
+ URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+ absoluteURI = scheme ":" ( hier_part | opaque_part )
+ relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+
+ hier_part = ( net_path | abs_path ) [ "?" query ]
+ opaque_part = uric_no_slash *uric
+
+ uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
+ "&" | "=" | "+" | "$" | ","
+
+ net_path = "//" authority [ abs_path ]
+ abs_path = "/" path_segments
+ rel_path = rel_segment [ abs_path ]
+
+ rel_segment = 1*( unreserved | escaped |
+ ";" | "@" | "&" | "=" | "+" | "$" | "," )
+
+ scheme = alpha *( alpha | digit | "+" | "-" | "." )
+
+ authority = server | reg_name
+
+ reg_name = 1*( unreserved | escaped | "$" | "," |
+ ";" | ":" | "@" | "&" | "=" | "+" )
+
+ server = [ [ userinfo "@" ] hostport ]
+ userinfo = *( unreserved | escaped |
+ ";" | ":" | "&" | "=" | "+" | "$" | "," )
+
+ hostport = host [ ":" port ]
+ host = hostname | IPv4address
+ hostname = *( domainlabel "." ) toplabel [ "." ]
+ domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
+ port = *digit
+
+ path = [ abs_path | opaque_part ]
+ path_segments = segment *( "/" segment )
+ segment = *pchar *( ";" param )
+ param = *pchar
+ pchar = unreserved | escaped |
+ ":" | "@" | "&" | "=" | "+" | "$" | ","
+
+ query = *uric
+
+ fragment = *uric
+
+
+
+Berners-Lee, et. al. Standards Track [Page 27]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ uric = reserved | unreserved | escaped
+ reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+ "$" | ","
+ unreserved = alphanum | mark
+ mark = "-" | "_" | "." | "!" | "~" | "*" | "'" |
+ "(" | ")"
+
+ escaped = "%" hex hex
+ hex = digit | "A" | "B" | "C" | "D" | "E" | "F" |
+ "a" | "b" | "c" | "d" | "e" | "f"
+
+ alphanum = alpha | digit
+ alpha = lowalpha | upalpha
+
+ lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
+ "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
+ "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
+ upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
+ "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
+ "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
+ digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
+ "8" | "9"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 28]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+B. Parsing a URI Reference with a Regular Expression
+
+ As described in Section 4.3, the generic URI syntax is not sufficient
+ to disambiguate the components of some forms of URI. Since the
+ "greedy algorithm" described in that section is identical to the
+ disambiguation method used by POSIX regular expressions, it is
+ natural and commonplace to use a regular expression for parsing the
+ potential four components and fragment identifier of a URI reference.
+
+ The following line is the regular expression for breaking-down a URI
+ reference into its components.
+
+ ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+ 12 3 4 5 6 7 8 9
+
+ The numbers in the second line above are only to assist readability;
+ they indicate the reference points for each subexpression (i.e., each
+ paired parenthesis). We refer to the value matched for subexpression
+ <n> as $<n>. For example, matching the above expression to
+
+ http://www.ics.uci.edu/pub/ietf/uri/#Related
+
+ results in the following subexpression matches:
+
+ $1 = http:
+ $2 = http
+ $3 = //www.ics.uci.edu
+ $4 = www.ics.uci.edu
+ $5 = /pub/ietf/uri/
+ $6 = <undefined>
+ $7 = <undefined>
+ $8 = #Related
+ $9 = Related
+
+ where <undefined> indicates that the component is not present, as is
+ the case for the query component in the above example. Therefore, we
+ can determine the value of the four components and fragment as
+
+ scheme = $2
+ authority = $4
+ path = $5
+ query = $7
+ fragment = $9
+
+ and, going in the opposite direction, we can recreate a URI reference
+ from its components using the algorithm in step 7 of Section 5.2.
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 29]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+C. Examples of Resolving Relative URI References
+
+ Within an object with a well-defined base URI of
+
+ http://a/b/c/d;p?q
+
+ the relative URI would be resolved as follows:
+
+C.1. Normal Examples
+
+ g:h = g:h
+ g = http://a/b/c/g
+ ./g = http://a/b/c/g
+ g/ = http://a/b/c/g/
+ /g = http://a/g
+ //g = http://g
+ ?y = http://a/b/c/?y
+ g?y = http://a/b/c/g?y
+ #s = (current document)#s
+ g#s = http://a/b/c/g#s
+ g?y#s = http://a/b/c/g?y#s
+ ;x = http://a/b/c/;x
+ g;x = http://a/b/c/g;x
+ g;x?y#s = http://a/b/c/g;x?y#s
+ . = http://a/b/c/
+ ./ = http://a/b/c/
+ .. = http://a/b/
+ ../ = http://a/b/
+ ../g = http://a/b/g
+ ../.. = http://a/
+ ../../ = http://a/
+ ../../g = http://a/g
+
+C.2. Abnormal Examples
+
+ Although the following abnormal examples are unlikely to occur in
+ normal practice, all URI parsers should be capable of resolving them
+ consistently. Each example uses the same base as above.
+
+ An empty reference refers to the start of the current document.
+
+ <> = (current document)
+
+ Parsers must be careful in handling the case where there are more
+ relative path ".." segments than there are hierarchical levels in the
+ base URI's path. Note that the ".." syntax cannot be used to change
+ the authority component of a URI.
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 30]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ ../../../g = http://a/../g
+ ../../../../g = http://a/../../g
+
+ In practice, some implementations strip leading relative symbolic
+ elements (".", "..") after applying a relative URI calculation, based
+ on the theory that compensating for obvious author errors is better
+ than allowing the request to fail. Thus, the above two references
+ will be interpreted as "http://a/g" by some implementations.
+
+ Similarly, parsers must avoid treating "." and ".." as special when
+ they are not complete components of a relative path.
+
+ /./g = http://a/./g
+ /../g = http://a/../g
+ g. = http://a/b/c/g.
+ .g = http://a/b/c/.g
+ g.. = http://a/b/c/g..
+ ..g = http://a/b/c/..g
+
+ Less likely are cases where the relative URI uses unnecessary or
+ nonsensical forms of the "." and ".." complete path segments.
+
+ ./../g = http://a/b/g
+ ./g/. = http://a/b/c/g/
+ g/./h = http://a/b/c/g/h
+ g/../h = http://a/b/c/h
+ g;x=1/./y = http://a/b/c/g;x=1/y
+ g;x=1/../y = http://a/b/c/y
+
+ All client applications remove the query component from the base URI
+ before resolving relative URI. However, some applications fail to
+ separate the reference's query and/or fragment components from a
+ relative path before merging it with the base path. This error is
+ rarely noticed, since typical usage of a fragment never includes the
+ hierarchy ("/") character, and the query component is not normally
+ used within relative references.
+
+ g?y/./x = http://a/b/c/g?y/./x
+ g?y/../x = http://a/b/c/g?y/../x
+ g#s/./x = http://a/b/c/g#s/./x
+ g#s/../x = http://a/b/c/g#s/../x
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 31]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ Some parsers allow the scheme name to be present in a relative URI if
+ it is the same as the base URI scheme. This is considered to be a
+ loophole in prior specifications of partial URI [RFC1630]. Its use
+ should be avoided.
+
+ http:g = http:g ; for validating parsers
+ | http://a/b/c/g ; for backwards compatibility
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 32]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+D. Embedding the Base URI in HTML documents
+
+ It is useful to consider an example of how the base URI of a document
+ can be embedded within the document's content. In this appendix, we
+ describe how documents written in the Hypertext Markup Language
+ (HTML) [RFC1866] can include an embedded base URI. This appendix
+ does not form a part of the URI specification and should not be
+ considered as anything more than a descriptive example.
+
+ HTML defines a special element "BASE" which, when present in the
+ "HEAD" portion of a document, signals that the parser should use the
+ BASE element's "HREF" attribute as the base URI for resolving any
+ relative URI. The "HREF" attribute must be an absolute URI. Note
+ that, in HTML, element and attribute names are case-insensitive. For
+ example:
+
+ <!doctype html public "-//IETF//DTD HTML//EN">
+ <HTML><HEAD>
+ <TITLE>An example HTML document</TITLE>
+ <BASE href="http://www.ics.uci.edu/Test/a/b/c">
+ </HEAD><BODY>
+ ... <A href="../x">a hypertext anchor</A> ...
+ </BODY></HTML>
+
+ A parser reading the example document should interpret the given
+ relative URI "../x" as representing the absolute URI
+
+ <http://www.ics.uci.edu/Test/a/x>
+
+ regardless of the context in which the example document was obtained.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 33]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+E. Recommendations for Delimiting URI in Context
+
+ URI are often transmitted through formats that do not provide a clear
+ context for their interpretation. For example, there are many
+ occasions when URI are included in plain text; examples include text
+ sent in electronic mail, USENET news messages, and, most importantly,
+ printed on paper. In such cases, it is important to be able to
+ delimit the URI from the rest of the text, and in particular from
+ punctuation marks that might be mistaken for part of the URI.
+
+ In practice, URI are delimited in a variety of ways, but usually
+ within double-quotes "http://test.com/", angle brackets
+ <http://test.com/>, or just using whitespace
+
+ http://test.com/
+
+ These wrappers do not form part of the URI.
+
+ In the case where a fragment identifier is associated with a URI
+ reference, the fragment would be placed within the brackets as well
+ (separated from the URI with a "#" character).
+
+ In some cases, extra whitespace (spaces, linebreaks, tabs, etc.) may
+ need to be added to break long URI across lines. The whitespace
+ should be ignored when extracting the URI.
+
+ No whitespace should be introduced after a hyphen ("-") character.
+ Because some typesetters and printers may (erroneously) introduce a
+ hyphen at the end of line when breaking a line, the interpreter of a
+ URI containing a line break immediately after a hyphen should ignore
+ all unescaped whitespace around the line break, and should be aware
+ that the hyphen may or may not actually be part of the URI.
+
+ Using <> angle brackets around each URI is especially recommended as
+ a delimiting style for URI that contain whitespace.
+
+ The prefix "URL:" (with or without a trailing space) was recommended
+ as a way to used to help distinguish a URL from other bracketed
+ designators, although this is not common in practice.
+
+ For robustness, software that accepts user-typed URI should attempt
+ to recognize and strip both delimiters and embedded whitespace.
+
+ For example, the text:
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 34]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ Yes, Jim, I found it under "http://www.w3.org/Addressing/",
+ but you can probably pick it up from <ftp://ds.internic.
+ net/rfc/>. Note the warning in <http://www.ics.uci.edu/pub/
+ ietf/uri/historical.html#WARNING>.
+
+ contains the URI references
+
+ http://www.w3.org/Addressing/
+ ftp://ds.internic.net/rfc/
+ http://www.ics.uci.edu/pub/ietf/uri/historical.html#WARNING
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 35]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+F. Abbreviated URLs
+
+ The URL syntax was designed for unambiguous reference to network
+ resources and extensibility via the URL scheme. However, as URL
+ identification and usage have become commonplace, traditional media
+ (television, radio, newspapers, billboards, etc.) have increasingly
+ used abbreviated URL references. That is, a reference consisting of
+ only the authority and path portions of the identified resource, such
+ as
+
+ www.w3.org/Addressing/
+
+ or simply the DNS hostname on its own. Such references are primarily
+ intended for human interpretation rather than machine, with the
+ assumption that context-based heuristics are sufficient to complete
+ the URL (e.g., most hostnames beginning with "www" are likely to have
+ a URL prefix of "http://"). Although there is no standard set of
+ heuristics for disambiguating abbreviated URL references, many client
+ implementations allow them to be entered by the user and
+ heuristically resolved. It should be noted that such heuristics may
+ change over time, particularly when new URL schemes are introduced.
+
+ Since an abbreviated URL has the same syntax as a relative URL path,
+ abbreviated URL references cannot be used in contexts where relative
+ URLs are expected. This limits the use of abbreviated URLs to places
+ where there is no defined base URL, such as dialog boxes and off-line
+ advertisements.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 36]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+G. Summary of Non-editorial Changes
+
+G.1. Additions
+
+ Section 4 (URI References) was added to stem the confusion regarding
+ "what is a URI" and how to describe fragment identifiers given that
+ they are not part of the URI, but are part of the URI syntax and
+ parsing concerns. In addition, it provides a reference definition
+ for use by other IETF specifications (HTML, HTTP, etc.) that have
+ previously attempted to redefine the URI syntax in order to account
+ for the presence of fragment identifiers in URI references.
+
+ Section 2.4 was rewritten to clarify a number of misinterpretations
+ and to leave room for fully internationalized URI.
+
+ Appendix F on abbreviated URLs was added to describe the shortened
+ references often seen on television and magazine advertisements and
+ explain why they are not used in other contexts.
+
+G.2. Modifications from both RFC 1738 and RFC 1808
+
+ Changed to URI syntax instead of just URL.
+
+ Confusion regarding the terms "character encoding", the URI
+ "character set", and the escaping of characters with %<hex><hex>
+ equivalents has (hopefully) been reduced. Many of the BNF rule names
+ regarding the character sets have been changed to more accurately
+ describe their purpose and to encompass all "characters" rather than
+ just US-ASCII octets. Unless otherwise noted here, these
+ modifications do not affect the URI syntax.
+
+ Both RFC 1738 and RFC 1808 refer to the "reserved" set of characters
+ as if URI-interpreting software were limited to a single set of
+ characters with a reserved purpose (i.e., as meaning something other
+ than the data to which the characters correspond), and that this set
+ was fixed by the URI scheme. However, this has not been true in
+ practice; any character that is interpreted differently when it is
+ escaped is, in effect, reserved. Furthermore, the interpreting
+ engine on a HTTP server is often dependent on the resource, not just
+ the URI scheme. The description of reserved characters has been
+ changed accordingly.
+
+ The plus "+", dollar "$", and comma "," characters have been added to
+ those in the "reserved" set, since they are treated as reserved
+ within the query component.
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 37]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ The tilde "~" character was added to those in the "unreserved" set,
+ since it is extensively used on the Internet in spite of the
+ difficulty to transcribe it with some keyboards.
+
+ The syntax for URI scheme has been changed to require that all
+ schemes begin with an alpha character.
+
+ The "user:password" form in the previous BNF was changed to a
+ "userinfo" token, and the possibility that it might be
+ "user:password" made scheme specific. In particular, the use of
+ passwords in the clear is not even suggested by the syntax.
+
+ The question-mark "?" character was removed from the set of allowed
+ characters for the userinfo in the authority component, since testing
+ showed that many applications treat it as reserved for separating the
+ query component from the rest of the URI.
+
+ The semicolon ";" character was added to those stated as being
+ reserved within the authority component, since several new schemes
+ are using it as a separator within userinfo to indicate the type of
+ user authentication.
+
+ RFC 1738 specified that the path was separated from the authority
+ portion of a URI by a slash. RFC 1808 followed suit, but with a
+ fudge of carrying around the separator as a "prefix" in order to
+ describe the parsing algorithm. RFC 1630 never had this problem,
+ since it considered the slash to be part of the path. In writing
+ this specification, it was found to be impossible to accurately
+ describe and retain the difference between the two URI
+ <foo:/bar> and <foo:bar>
+ without either considering the slash to be part of the path (as
+ corresponds to actual practice) or creating a separate component just
+ to hold that slash. We chose the former.
+
+G.3. Modifications from RFC 1738
+
+ The definition of specific URL schemes and their scheme-specific
+ syntax and semantics has been moved to separate documents.
+
+ The URL host was defined as a fully-qualified domain name. However,
+ many URLs are used without fully-qualified domain names (in contexts
+ for which the full qualification is not necessary), without any host
+ (as in some file URLs), or with a host of "localhost".
+
+ The URL port is now *digit instead of 1*digit, since systems are
+ expected to handle the case where the ":" separator between host and
+ port is supplied without a port.
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 38]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+ The recommendations for delimiting URI in context (Appendix E) have
+ been adjusted to reflect current practice.
+
+G.4. Modifications from RFC 1808
+
+ RFC 1808 (Section 4) defined an empty URL reference (a reference
+ containing nothing aside from the fragment identifier) as being a
+ reference to the base URL. Unfortunately, that definition could be
+ interpreted, upon selection of such a reference, as a new retrieval
+ action on that resource. Since the normal intent of such references
+ is for the user agent to change its view of the current document to
+ the beginning of the specified fragment within that document, not to
+ make an additional request of the resource, a description of how to
+ correctly interpret an empty reference has been added in Section 4.
+
+ The description of the mythical Base header field has been replaced
+ with a reference to the Content-Location header field defined by
+ MHTML [RFC2110].
+
+ RFC 1808 described various schemes as either having or not having the
+ properties of the generic URI syntax. However, the only requirement
+ is that the particular document containing the relative references
+ have a base URI that abides by the generic URI syntax, regardless of
+ the URI scheme, so the associated description has been updated to
+ reflect that.
+
+ The BNF term <net_loc> has been replaced with <authority>, since the
+ latter more accurately describes its use and purpose. Likewise, the
+ authority is no longer restricted to the IP server syntax.
+
+ Extensive testing of current client applications demonstrated that
+ the majority of deployed systems do not use the ";" character to
+ indicate trailing parameter information, and that the presence of a
+ semicolon in a path segment does not affect the relative parsing of
+ that segment. Therefore, parameters have been removed as a separate
+ component and may now appear in any path segment. Their influence
+ has been removed from the algorithm for resolving a relative URI
+ reference. The resolution examples in Appendix C have been modified
+ to reflect this change.
+
+ Implementations are now allowed to work around misformed relative
+ references that are prefixed by the same scheme as the base URI, but
+ only for schemes known to use the <hier_part> syntax.
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 39]
+
+RFC 2396 URI Generic Syntax August 1998
+
+
+H. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Berners-Lee, et. al. Standards Track [Page 40]
+
diff --git a/standards/rfc2487.txt b/standards/rfc2487.txt
new file mode 100644
index 000000000..fb1305f00
--- /dev/null
+++ b/standards/rfc2487.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group P. Hoffman
+Request for Comments: 2487 Internet Mail Consortium
+Category: Standards Track January 1999
+
+
+ SMTP Service Extension for Secure SMTP over TLS
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Abstract
+
+ This document describes an extension to the SMTP service that allows
+ an SMTP server and client to use transport-layer security to provide
+ private, authenticated communication over the Internet. This gives
+ SMTP agents the ability to protect some or all of their
+ communications from eavesdroppers and attackers.
+
+2. Introduction
+
+ SMTP [RFC-821] servers and clients normally communicate in the clear
+ over the Internet. In many cases, this communication goes through one
+ or more router that is not controlled or trusted by either entity.
+ Such an untrusted router might allow a third party to monitor or
+ alter the communications between the server and client.
+
+ Further, there is often a desire for two SMTP agents to be able to
+ authenticate each others' identities. For example, a secure SMTP
+ server might only allow communications from other SMTP agents it
+ knows, or it might act differently for messages received from an
+ agent it knows than from one it doesn't know.
+
+ TLS [TLS], more commonly known as SSL, is a popular mechanism for
+ enhancing TCP communications with privacy and authentication. TLS is
+ in wide use with the HTTP protocol, and is also being used for adding
+ security to many other common protocols that run over TCP.
+
+
+
+
+
+
+Hoffman Standards Track [Page 1]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+2.1 Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC-2119].
+
+3. STARTTLS Extension
+
+ The STARTTLS extension to SMTP is laid out as follows:
+
+ (1) the name of the SMTP service defined here is STARTTLS;
+
+ (2) the EHLO keyword value associated with the extension is STARTTLS;
+
+ (3) the STARTTLS keyword has no parameters;
+
+ (4) a new SMTP verb, "STARTTLS", is defined;
+
+ (5) no additional parameters are added to any SMTP command.
+
+4. The STARTTLS Keyword
+
+ The STARTTLS keyword is used to tell the SMTP client that the SMTP
+ server allows use of TLS. It takes no parameters.
+
+5. The STARTTLS Command
+
+ The format for the STARTTLS command is:
+
+ STARTTLS
+
+ with no parameters.
+
+ After the client gives the STARTTLS command, the server responds with
+ one of the following reply codes:
+
+ 220 Ready to start TLS
+ 501 Syntax error (no parameters allowed)
+ 454 TLS not available due to temporary reason
+
+ A publicly-referenced SMTP server MUST NOT require use of the
+ STARTTLS extension in order to deliver mail locally. This rule
+ prevents the STARTTLS extension from damaging the interoperability of
+ the Internet's SMTP infrastructure. A publicly-referenced SMTP server
+ is an SMTP server which runs on port 25 of an Internet host listed in
+ the MX record (or A record if an MX record is not present) for the
+ domain name on the right hand side of an Internet mail address.
+
+
+
+
+Hoffman Standards Track [Page 2]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+ Any SMTP server may refuse to accept messages for relay based on
+ authentication supplied during the TLS negotiation. An SMTP server
+ that is not publicly referenced may refuse to accept any messages for
+ relay or local delivery based on authentication supplied during the
+ TLS negotiation.
+
+ A SMTP server that is not publicly referenced may choose to require
+ that the client perform a TLS negotiation before accepting any
+ commands. In this case, the server SHOULD return the reply code:
+
+ 530 Must issue a STARTTLS command first
+
+ to every command other than NOOP, EHLO, STARTTLS, or QUIT. If the
+ client and server are using the ENHANCEDSTATUSCODES ESMTP extension
+ [RFC-2034], the status code to be returned SHOULD be 5.7.0.
+
+ After receiving a 220 response to a STARTTLS command, the client
+ SHOULD start the TLS negotiation before giving any other SMTP
+ commands.
+
+ If the SMTP client is using pipelining as defined in RFC 1854, the
+ STARTTLS command must be the last command in a group.
+
+5.1 Processing After the STARTTLS Command
+
+ After the TLS handshake has been completed, both parties MUST
+ immediately decide whether or not to continue based on the
+ authentication and privacy achieved. The SMTP client and server may
+ decide to move ahead even if the TLS negotiation ended with no
+ authentication and/or no privacy because most SMTP services are
+ performed with no authentication and no privacy, but some SMTP
+ clients or servers may want to continue only if a particular level of
+ authentication and/or privacy was achieved.
+
+ If the SMTP client decides that the level of authentication or
+ privacy is not high enough for it to continue, it SHOULD issue an
+ SMTP QUIT command immediately after the TLS negotiation is complete.
+ If the SMTP server decides that the level of authentication or
+ privacy is not high enough for it to continue, it SHOULD reply to
+ every SMTP command from the client (other than a QUIT command) with
+ the 554 reply code (with a possible text string such as "Command
+ refused due to lack of security").
+
+ The decision of whether or not to believe the authenticity of the
+ other party in a TLS negotiation is a local matter. However, some
+ general rules for the decisions are:
+
+
+
+
+
+Hoffman Standards Track [Page 3]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+ - A SMTP client would probably only want to authenticate an SMTP
+ server whose server certificate has a domain name that is the
+ domain name that the client thought it was connecting to.
+ - A publicly-referenced SMTP server would probably want to accept
+ any certificate from an SMTP client, and would possibly want to
+ put distinguishing information about the certificate in the
+ Received header of messages that were relayed or submitted from
+ the client.
+
+5.2 Result of the STARTTLS Command
+
+ Upon completion of the TLS handshake, the SMTP protocol is reset to
+ the initial state (the state in SMTP after a server issues a 220
+ service ready greeting). The server MUST discard any knowledge
+ obtained from the client, such as the argument to the EHLO command,
+ which was not obtained from the TLS negotiation itself. The client
+ MUST discard any knowledge obtained from the server, such as the list
+ of SMTP service extensions, which was not obtained from the TLS
+ negotiation itself. The client SHOULD send an EHLO command as the
+ first command after a successful TLS negotiation.
+
+ The list of SMTP service extensions returned in response to an EHLO
+ command received after the TLS handshake MAY be different than the
+ list returned before the TLS handshake. For example, an SMTP server
+ might not want to advertise support for a particular SASL mechanism
+ [SASL] unless a client has sent an appropriate client certificate
+ during a TLS handshake.
+
+ Both the client and the server MUST know if there is a TLS session
+ active. A client MUST NOT attempt to start a TLS session if a TLS
+ session is already active. A server MUST NOT return the TLS extension
+ in response to an EHLO command received after a TLS handshake has
+ completed.
+
+6. Usage Example
+
+ The following dialog illustrates how a client and server can start a
+ TLS session:
+
+ S: <waits for connection on TCP port 25>
+ C: <opens connection>
+ S: 220 mail.imc.org SMTP service ready
+ C: EHLO mail.ietf.org
+ S: 250-mail.imc.org offers a warm hug of welcome
+ S: 250 STARTTLS
+ C: STARTTLS
+ S: 220 Go ahead
+ C: <starts TLS negotiation>
+
+
+
+Hoffman Standards Track [Page 4]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+ C & S: <negotiate a TLS session>
+ C & S: <check result of negotiation>
+ C: <continues by sending an SMTP command>
+ . . .
+
+7. Security Considerations
+
+ It should be noted that SMTP is not an end-to-end mechanism. Thus, if
+ an SMTP client/server pair decide to add TLS privacy, they are not
+ securing the transport from the originating mail user agent to the
+ recipient. Further, because delivery of a single piece of mail may
+ go between more than two SMTP servers, adding TLS privacy to one pair
+ of servers does not mean that the entire SMTP chain has been made
+ private. Further, just because an SMTP server can authenticate an
+ SMTP client, it does not mean that the mail from the SMTP client was
+ authenticated by the SMTP client when the client received it.
+
+ Both the STMP client and server must check the result of the TLS
+ negotiation to see whether acceptable authentication or privacy was
+ achieved. Ignoring this step completely invalidates using TLS for
+ security. The decision about whether acceptable authentication or
+ privacy was achieved is made locally, is implementation-dependant,
+ and is beyond the scope of this document.
+
+ The SMTP client and server should note carefully the result of the
+ TLS negotiation. If the negotiation results in no privacy, or if it
+ results in privacy using algorithms or key lengths that are deemed
+ not strong enough, or if the authentication is not good enough for
+ either party, the client may choose to end the SMTP session with an
+ immediate QUIT command, or the server may choose to not accept any
+ more SMTP commands.
+
+ A server announcing in an EHLO response that it uses a particular TLS
+ protocol should not pose any security issues, since any use of TLS
+ will be at least as secure as no use of TLS.
+
+ A man-in-the-middle attack can be launched by deleting the "250
+ STARTTLS" response from the server. This would cause the client not
+ to try to start a TLS session. An SMTP client can protect against
+ this attack by recording the fact that a particular SMTP server
+ offers TLS during one session and generating an alarm if it does not
+ appear in the EHLO response for a later session. The lack of TLS
+ during a session SHOULD NOT result in the bouncing of email, although
+ it could result in delayed processing.
+
+
+
+
+
+
+
+Hoffman Standards Track [Page 5]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+ Before the TLS handshake has begun, any protocol interactions are
+ performed in the clear and may be modified by an active attacker. For
+ this reason, clients and servers MUST discard any knowledge obtained
+ prior to the start of the TLS handshake upon completion of the TLS
+ handshake.
+
+ The STARTTLS extension is not suitable for authenticating the author
+ of an email message unless every hop in the delivery chain, including
+ the submission to the first SMTP server, is authenticated. Another
+ proposal [SMTP-AUTH] can be used to authenticate delivery and MIME
+ security multiparts [MIME-SEC] can be used to authenticate the author
+ of an email message. In addition, the [SMTP-AUTH] proposal offers
+ simpler and more flexible options to authenticate an SMTP client and
+ the SASL EXTERNAL mechanism [SASL] MAY be used in conjunction with
+ the STARTTLS command to provide an authorization identity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman Standards Track [Page 6]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+A. References
+
+ [RFC-821] Postel, J., "Simple Mail Transfer Protocol", RFC 821,
+ August 1982.
+
+ [RFC-1869] Klensin, J., Freed, N, Rose, M, Stefferud, E. and D.
+ Crocker, "SMTP Service Extensions", STD 10, RFC 1869,
+ November 1995.
+
+ [RFC-2034] Freed, N., "SMTP Service Extension for Returning Enhanced
+ Error Codes", RFC 2034, October 1996.
+
+ [RFC-2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [SASL] Myers, J., "Simple Authentication and Security Layer
+ (SASL)", RFC 2222, October 1997.
+
+ [SMTP-AUTH] "SMTP Service Extension for Authentication", Work in
+ Progress.
+
+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
+ RFC 2246, January 1999.
+
+B. Author's Address
+
+ Paul Hoffman
+ Internet Mail Consortium
+ 127 Segre Place
+ Santa Cruz, CA 95060
+
+ Phone: (831) 426-9827
+ EMail: phoffman@imc.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman Standards Track [Page 7]
+
+RFC 2487 SMTP Service Extension January 1999
+
+
+C. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman Standards Track [Page 8]
+
diff --git a/standards/rfc2565.txt b/standards/rfc2565.txt
new file mode 100644
index 000000000..56511d478
--- /dev/null
+++ b/standards/rfc2565.txt
@@ -0,0 +1,2075 @@
+
+
+
+
+
+
+Network Working Group R. Herriot, Ed.
+Request for Comments: 2565 Xerox Corporation
+Category: Experimental S. Butler
+ Hewlett-Packard
+ P. Moore
+ Microsoft
+ R. Turner
+ Sharp Labs
+ April 1999
+
+
+ Internet Printing Protocol/1.0: Encoding and Transport
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note
+
+ This document defines an Experimental protocol for the Internet
+ community. The IESG expects that a revised version of this protocol
+ will be published as Proposed Standard protocol. The Proposed
+ Standard, when published, is expected to change from the protocol
+ defined in this memo. In particular, it is expected that the
+ standards-track version of the protocol will incorporate strong
+ authentication and privacy features, and that an "ipp:" URL type will
+ be defined which supports those security measures. Other changes to
+ the protocol are also possible. Implementors are warned that future
+ versions of this protocol may not interoperate with the version of
+ IPP defined in this document, or if they do interoperate, that some
+ protocol features may not be available.
+
+ The IESG encourages experimentation with this protocol, especially in
+ combination with Transport Layer Security (TLS) [RFC 2246], to help
+ determine how TLS may effectively be used as a security layer for
+ IPP.
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 1]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document defines the
+ rules for encoding IPP operations and IPP attributes into a new
+ Internet mime media type called "application/ipp". This document
+ also defines the rules for transporting over HTTP a message body
+ whose Content-Type is "application/ipp".
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics [RFC2566]
+ Internet Printing Protocol/1.0: Encoding and Transport (this
+ document)
+ Internet Printing Protocol/1.0: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The document, "Design Goals for an Internet Printing Protocol", takes
+ a broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0. Operator and administrator requirements are
+ out of scope for version 1.0.
+
+ The document, "Rationale for the Structure and Model and Protocol for
+ the Internet Printing Protocol", describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specifications, and gives background and rationale for the
+ IETF working group's major decisions.
+
+ The document, "Internet Printing Protocol/1.0: Model and Semantics",
+ describes a simplified model with abstract objects, their attributes,
+ and their operations that are independent of encoding and transport.
+ It introduces a Printer and a Job object. The Job object optionally
+ supports multiple documents per Job. It also addresses security,
+ internationalization, and directory issues.
+
+ This document "Internet Printing Protocol/1.0: Implementer's Guide",
+ gives advice to implementers of IPP clients and IPP objects.
+
+
+
+
+
+Herriot, et al. Experimental [Page 2]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ The document "Mapping between LPD and IPP Protocols" gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+Table of Contents
+
+ 1. Introduction.....................................................4
+ 2. Conformance Terminology..........................................4
+ 3. Encoding of the Operation Layer.................................4
+ 3.1 Picture of the Encoding.....................................5
+ 3.2 Syntax of Encoding..........................................7
+ 3.3 Version-number..............................................9
+ 3.4 Operation-id................................................9
+ 3.5 Status-code.................................................9
+ 3.6 Request-id..................................................9
+ 3.7 Tags.......................................................10
+ 3.7.1 Delimiter Tags.........................................10
+ 3.7.2 Value Tags.............................................11
+ 3.8 Name-Length................................................13
+ 3.9 (Attribute) Name...........................................13
+ 3.10 Value Length...............................................16
+ 3.11 (Attribute) Value..........................................16
+ 3.12 Data.......................................................18
+ 4. Encoding of Transport Layer.....................................18
+ 5. Security Considerations.........................................19
+ 5.1 Using IPP with SSL3........................................19
+ 6. References......................................................20
+ 7. Authors' Addresses..............................................22
+ 8. Other Participants:.............................................24
+ 9. Appendix A: Protocol Examples...................................25
+ 9.1 Print-Job Request..........................................25
+ 9.2 Print-Job Response (successful)............................26
+ 9.3 Print-Job Response (failure)...............................27
+ 9.4 Print-Job Response (success with attributes ignored).......28
+ 9.5 Print-URI Request..........................................30
+ 9.6 Create-Job Request.........................................31
+ 9.7 Get-Jobs Request...........................................31
+ 9.8 Get-Jobs Response..........................................32
+ 10. Appendix C: Registration of MIME Media Type Information for
+ "application/ipp"..............................................35
+ 11. Full Copyright Statement.......................................37
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 3]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+1. Introduction
+
+ This document contains the rules for encoding IPP operations and
+ describes two layers: the transport layer and the operation layer.
+
+ The transport layer consists of an HTTP/1.1 request or response. RFC
+ 2068 [RFC2068] describes HTTP/1.1. This document specifies the HTTP
+ headers that an IPP implementation supports.
+
+ The operation layer consists of a message body in an HTTP request or
+ response. The document "Internet Printing Protocol/1.0: Model and
+ Semantics" [RFC2566] defines the semantics of such a message body and
+ the supported values. This document specifies the encoding of an IPP
+ operation. The aforementioned document [RFC2566] is henceforth
+ referred to as the "IPP model document"
+
+2. Conformance Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+ interpreted as described in RFC 2119 [RFC2119].
+
+3. Encoding of the Operation Layer
+
+ The operation layer MUST contain a single operation request or
+ operation response. Each request or response consists of a sequence
+ of values and attribute groups. Attribute groups consist of a
+ sequence of attributes each of which is a name and value. Names and
+ values are ultimately sequences of octets
+
+ The encoding consists of octets as the most primitive type. There are
+ several types built from octets, but three important types are
+ integers, character strings and octet strings, on which most other
+ data types are built. Every character string in this encoding MUST be
+ a sequence of characters where the characters are associated with
+ some charset and some natural language. A character string MUST be in
+ "reading order" with the first character in the value (according to
+ reading order) being the first character in the encoding. A character
+ string whose associated charset is US-ASCII whose associated natural
+ language is US English is henceforth called a US-ASCII-STRING. A
+ character string whose associated charset and natural language are
+ specified in a request or response as described in the model document
+ is henceforth called a LOCALIZED-STRING. An octet string MUST be in
+ "IPP model document order" with the first octet in the value
+ (according to the IPP model document order) being the first octet in
+ the encoding Every integer in this encoding MUST be encoded as a
+ signed integer using two's-complement binary encoding with big-endian
+ format (also known as "network order" and "most significant byte
+
+
+
+Herriot, et al. Experimental [Page 4]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ first"). The number of octets for an integer MUST be 1, 2 or 4,
+ depending on usage in the protocol. Such one-octet integers,
+ henceforth called SIGNED-BYTE, are used for the version-number and
+ tag fields. Such two-byte integers, henceforth called SIGNED-SHORT
+ are used for the operation-id, status-code and length fields. Four
+ byte integers, henceforth called SIGNED-INTEGER, are used for values
+ fields and the sequence number.
+
+ The following two sections present the operation layer in two ways
+
+ - informally through pictures and description
+ - formally through Augmented Backus-Naur Form (ABNF), as specified
+ by RFC 2234 [RFC2234]
+
+3.1 Picture of the Encoding
+
+ The encoding for an operation request or response consists of:
+
+ -----------------------------------------------
+ | version-number | 2 bytes - required
+ -----------------------------------------------
+ | operation-id (request) |
+ | or | 2 bytes - required
+ | status-code (response) |
+ -----------------------------------------------
+ | request-id | 4 bytes - required
+ -----------------------------------------------------------
+ | xxx-attributes-tag | 1 byte |
+ ----------------------------------------------- |-0 or more
+ | xxx-attribute-sequence | n bytes |
+ -----------------------------------------------------------
+ | end-of-attributes-tag | 1 byte - required
+ -----------------------------------------------
+ | data | q bytes - optional
+ -----------------------------------------------
+
+ The xxx-attributes-tag and xxx-attribute-sequence represents four
+ different values of "xxx", namely, operation, job, printer and
+ unsupported. The xxx-attributes-tag and an xxx-attribute-sequence
+ represent attribute groups in the model document. The xxx-
+ attributes-tag identifies the attribute group and the xxx-attribute-
+ sequence contains the attributes.
+
+ The expected sequence of xxx-attributes-tag and xxx-attribute-
+ sequence is specified in the IPP model document for each operation
+ request and operation response.
+
+
+
+
+
+Herriot, et al. Experimental [Page 5]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ A request or response SHOULD contain each xxx-attributes-tag defined
+ for that request or response even if there are no attributes except
+ for the unsupported-attributes-tag which SHOULD be present only if
+ the unsupported-attribute-sequence is non-empty. A receiver of a
+ request MUST be able to process as equivalent empty attribute groups:
+
+ a) an xxx-attributes-tag with an empty xxx-attribute-sequence,
+ b) an expected but missing xxx-attributes-tag.
+
+ The data is omitted from some operations, but the end-of-attributes-
+ tag is present even when the data is omitted. Note, the xxx-
+ attributes-tags and end-of-attributes-tag are called 'delimiter-
+ tags'. Note: the xxx-attribute-sequence, shown above may consist of 0
+ bytes, according to the rule below.
+
+ An xxx-attributes-sequence consists of zero or more compound-
+ attributes.
+
+ -----------------------------------------------
+ | compound-attribute | s bytes - 0 or more
+ -----------------------------------------------
+
+ A compound-attribute consists of an attribute with a single value
+ followed by zero or more additional values.
+
+ Note: a 'compound-attribute' represents a single attribute in the
+ model document. The 'additional value' syntax is for attributes with
+ 2 or more values.
+
+ Each attribute consists of:
+
+ -----------------------------------------------
+ | value-tag | 1 byte
+ -----------------------------------------------
+ | name-length (value is u) | 2 bytes
+ -----------------------------------------------
+ | name | u bytes
+ -----------------------------------------------
+ | value-length (value is v) | 2 bytes
+ -----------------------------------------------
+ | value | v bytes
+ -----------------------------------------------
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 6]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ An additional value consists of:
+
+ -----------------------------------------------------------
+ | value-tag | 1 byte |
+ ----------------------------------------------- |
+ | name-length (value is 0x0000) | 2 bytes |
+ ----------------------------------------------- |-0 or more
+ | value-length (value is w) | 2 bytes |
+ ----------------------------------------------- |
+ | value | w bytes |
+ -----------------------------------------------------------
+
+ Note: an additional value is like an attribute whose name-length is 0.
+
+ From the standpoint of a parsing loop, the encoding consists of:
+
+ -----------------------------------------------
+ | version-number | 2 bytes - required
+ -----------------------------------------------
+ | operation-id (request) |
+ | or | 2 bytes - required
+ | status-code (response) |
+ -----------------------------------------------
+ | request-id | 4 bytes - required
+ -----------------------------------------------------------
+ | tag (delimiter-tag or value-tag) | 1 byte |
+ ----------------------------------------------- |-0 or more
+ | empty or rest of attribute | x bytes |
+ -----------------------------------------------------------
+ | end-of-attributes-tag | 2 bytes - required
+ -----------------------------------------------
+ | data | y bytes - optional
+ -----------------------------------------------
+
+ The value of the tag determines whether the bytes following the
+ tag are:
+
+ - attributes
+ - data
+ - the remainder of a single attribute where the tag specifies the
+ type of the value.
+
+3.2 Syntax of Encoding
+
+ The syntax below is ABNF [RFC2234] except 'strings of literals' MUST
+ be case sensitive. For example 'a' means lower case 'a' and not
+ upper case 'A'. In addition, SIGNED-BYTE and SIGNED-SHORT fields
+ are represented as '%x' values which show their range of values.
+
+
+
+Herriot, et al. Experimental [Page 7]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ ipp-message = ipp-request / ipp-response
+ ipp-request = version-number operation-id request-id
+ *(xxx-attributes-tag xxx-attribute-sequence)
+ end-of-attributes-tag data
+ ipp-response = version-number status-code request-id
+ *(xxx-attributes-tag xxx-attribute-sequence)
+ end-of-attributes-tag data
+ xxx-attribute-sequence = *compound-attribute
+
+ xxx-attributes-tag = operation-attributes-tag / job-attributes-tag /
+ printer-attributes-tag / unsupported-attributes-tag
+
+ version-number = major-version-number minor-version-number
+ major-version-number = SIGNED-BYTE ; initially %d1
+ minor-version-number = SIGNED-BYTE ; initially %d0
+
+ operation-id = SIGNED-SHORT ; mapping from model defined below
+ status-code = SIGNED-SHORT ; mapping from model defined below
+ request-id = SIGNED-INTEGER ; whose value is > 0
+
+ compound-attribute = attribute *additional-values
+ attribute = value-tag name-length name value-length value
+ additional-values = value-tag zero-name-length value-length value
+
+ name-length = SIGNED-SHORT ; number of octets of 'name'
+ name = LALPHA *( LALPHA / DIGIT / "-" / "_" / "." )
+ value-length = SIGNED-SHORT ; number of octets of 'value'
+ value = OCTET-STRING
+
+ data = OCTET-STRING
+
+ zero-name-length = %x00.00 ; name-length of 0
+ operation-attributes-tag = %x01 ; tag of 1
+ job-attributes-tag = %x02 ; tag of 2
+ printer-attributes-tag = %x04 ; tag of 4
+ unsupported-attributes-tag = %x05 ; tag of 5
+ end-of-attributes-tag = %x03 ; tag of 3
+ value-tag = %x10-FF
+
+ SIGNED-BYTE = BYTE
+ SIGNED-SHORT = 2BYTE
+ SIGNED-INTEGER = 4BYTE
+ DIGIT = %x30-39 ; "0" to "9"
+ LALPHA = %x61-7A ; "a" to "z"
+ BYTE = %x00-FF
+ OCTET-STRING = *BYTE
+
+
+
+
+
+Herriot, et al. Experimental [Page 8]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ The syntax allows an xxx-attributes-tag to be present when the xxx-
+ attribute-sequence that follows is empty. The syntax is defined this
+ way to allow for the response of Get-Jobs where no attributes are
+ returned for some job-objects. Although it is RECOMMENDED that the
+ sender not send an xxx-attributes-tag if there are no attributes
+ (except in the Get-Jobs response just mentioned), the receiver MUST
+ be able to decode such syntax.
+
+3.3 Version-number
+
+ The version-number MUST consist of a major and minor version-number,
+ each of which MUST be represented by a SIGNED-BYTE. The protocol
+ described in this document MUST have a major version-number of 1
+ (0x01) and a minor version-number of 0 (0x00). The ABNF for these
+ two bytes MUST be %x01.00.
+
+3.4 Operation-id
+
+ Operation-ids are defined as enums in the model document. An
+ operation-ids enum value MUST be encoded as a SIGNED-SHORT.
+
+ Note: the values 0x4000 to 0xFFFF are reserved for private
+ extensions.
+
+3.5 Status-code
+
+ Status-codes are defined as enums in the model document. A status-
+ code enum value MUST be encoded as a SIGNED-SHORT.
+
+ The status-code is an operation attribute in the model document. In
+ the protocol, the status-code is in a special position, outside of
+ the operation attributes.
+
+ If an IPP status-code is returned, then the HTTP Status-Code MUST be
+ 200 (successful-ok). With any other HTTP Status-Code value, the HTTP
+ response MUST NOT contain an IPP message-body, and thus no IPP
+ status-code is returned.
+
+3.6 Request-id
+
+ The request-id allows a client to match a response with a request.
+ This mechanism is unnecessary in HTTP, but may be useful when
+ application/ipp entity bodies are used in another context.
+
+ The request-id in a response MUST be the value of the request-id
+ received in the corresponding request. A client can set the
+ request-id in each request to a unique value or a constant value,
+ such as 1, depending on what the client does with the request-id
+
+
+
+Herriot, et al. Experimental [Page 9]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ returned in the response. The value of the request-id MUST be greater
+ than zero.
+
+3.7 Tags
+
+ There are two kinds of tags:
+
+ - delimiter tags: delimit major sections of the protocol, namely
+ attributes and data
+ - value tags: specify the type of each attribute value
+
+3.7.1 Delimiter Tags
+
+ The following table specifies the values for the delimiter tags:
+
+ Tag Value (Hex) Delimiter
+
+ 0x00 reserved
+ 0x01 operation-attributes-tag
+ 0x02 job-attributes-tag
+ 0x03 end-of-attributes-tag
+ 0x04 printer-attributes-tag
+ 0x05 unsupported-attributes-tag
+ 0x06-0x0e reserved for future delimiters
+ 0x0F reserved for future chunking-end-of-attributes-
+ tag
+
+ When an xxx-attributes-tag occurs in the protocol, it MUST mean that
+ zero or more following attributes up to the next delimiter tag are
+ attributes belonging to group xxx as defined in the model document,
+ where xxx is operation, job, printer, unsupported.
+
+ Doing substitution for xxx in the above paragraph, this means the
+ following. When an operation-attributes-tag occurs in the protocol,
+ it MUST mean that the zero or more following attributes up to the
+ next delimiter tag are operation attributes as defined in the model
+ document. When an job-attributes-tag occurs in the protocol, it MUST
+ mean that the zero or more following attributes up to the next
+ delimiter tag are job attributes or job template attributes as
+ defined in the model document. When a printer-attributes-tag occurs
+ in the protocol, it MUST mean that the zero or more following
+ attributes up to the next delimiter tag are printer attributes as
+ defined in the model document. When an unsupported-attributes-tag
+ occurs in the protocol, it MUST mean that the zero or more following
+ attributes up to the next delimiter tag are unsupported attributes as
+ defined in the model document.
+
+
+
+
+
+Herriot, et al. Experimental [Page 10]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ The operation-attributes-tag and end-of-attributes-tag MUST each
+ occur exactly once in an operation. The operation-attributes-tag MUST
+ be the first tag delimiter, and the end-of-attributes-tag MUST be the
+ last tag delimiter. If the operation has a document-content group,
+ the document data in that group MUST follow the end-of-attributes-
+ tag.
+
+ Each of the other three xxx-attributes-tags defined above is
+ OPTIONAL in an operation and each MUST occur at most once in an
+ operation, except for job-attributes-tag in a Get-Jobs response which
+ may occur zero or more times.
+
+ The order and presence of delimiter tags for each operation request
+ and each operation response MUST be that defined in the model
+ document. For further details, see section 3.9 "(Attribute) Name" and
+ section 9 "Appendix A: Protocol Examples".
+
+ A Printer MUST treat the reserved delimiter tags differently from
+ reserved value tags so that the Printer knows that there is an entire
+ attribute group that it doesn't understand as opposed to a single
+ value that it doesn't understand.
+
+3.7.2 Value Tags
+
+ The remaining tables show values for the value-tag, which is the
+ first octet of an attribute. The value-tag specifies the type of the
+ value of the attribute. The following table specifies the "out-of-
+ band" values for the value-tag.
+
+ Tag Value (Hex) Meaning
+
+ 0x10 unsupported
+ 0x11 reserved for future 'default'
+ 0x12 unknown
+ 0x13 no-value
+
+ Tag Value (Hex) Meaning
+
+ 0x14-0x1F reserved for future "out-of-band" values.
+
+ The "unsupported" value MUST be used in the attribute-sequence of an
+ error response for those attributes which the printer does not
+ support. The "default" value is reserved for future use of setting
+ value back to their default value. The "unknown" value is used for
+ the value of a supported attribute when its value is temporarily
+ unknown. The "no-value" value is used for a supported attribute to
+ which
+
+
+
+
+Herriot, et al. Experimental [Page 11]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ no value has been assigned, e.g. "job-k-octets-supported" has no
+ value if an implementation supports this attribute, but an
+ administrator has not configured the printer to have a limit.
+
+ The following table specifies the integer values for the value-tag:
+
+ Tag Value (Hex) Meaning
+
+ 0x20 reserved
+ 0x21 integer
+ 0x22 boolean
+ 0x23 enum
+ 0x24-0x2F reserved for future integer types
+
+ NOTE: 0x20 is reserved for "generic integer" if it should ever be
+ needed.
+
+ The following table specifies the octetString values for the value-
+ tag:
+
+ Tag Value (Hex) Meaning
+
+ 0x30 octetString with an unspecified format
+ 0x31 dateTime
+ 0x32 resolution
+ 0x33 rangeOfInteger
+ 0x34 reserved for collection (in the future)
+ 0x35 textWithLanguage
+ 0x36 nameWithLanguage
+ 0x37-0x3F reserved for future octetString types
+
+ The following table specifies the character-string values for the
+ value-tag:
+
+ Tag Value (Hex) Meaning
+
+ 0x40 reserved
+ 0x41 textWithoutLanguage
+ 0x42 nameWithoutLanguage
+ 0x43 reserved
+ 0x44 keyword
+ 0x45 uri
+ 0x46 uriScheme
+ 0x47 charset
+ 0x48 naturalLanguage
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 12]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Tag Value (Hex) Meaning
+
+ 0x49 mimeMediaType
+ 0x4A-0x5F reserved for future character string types
+
+ NOTE: 0x40 is reserved for "generic character-string" if it should
+ ever be needed.
+
+ NOTE: an attribute value always has a type, which is explicitly
+ specified by its tag; one such tag value is "nameWithoutLanguage".
+ An attribute's name has an implicit type, which is keyword.
+
+ The values 0x60-0xFF are reserved for future types. There are no
+ values allocated for private extensions. A new type MUST be
+ registered via the type 2 registration process [RFC2566].
+
+ The tag 0x7F is reserved for extending types beyond the 255 values
+ available with a single byte. A tag value of 0x7F MUST signify that
+ the first 4 bytes of the value field are interpreted as the tag
+ value. Note, this future extension doesn't affect parsers that are
+ unaware of this special tag. The tag is like any other unknown tag,
+ and the value length specifies the length of a value which contains a
+ value that the parser treats atomically. All these 4 byte tag values
+ are currently unallocated except that the values 0x40000000-
+ 0x7FFFFFFF are reserved for experimental use.
+
+3.8 Name-Length
+
+ The name-length field MUST consist of a SIGNED-SHORT. This field MUST
+ specify the number of octets in the name field which follows the
+ name-length field, excluding the two bytes of the name-length field.
+
+ If a name-length field has a value of zero, the following name field
+ MUST be empty, and the following value MUST be treated as an
+ additional value for the preceding attribute. Within an attribute-
+ sequence, if two attributes have the same name, the first occurrence
+ MUST be ignored. The zero-length name is the only mechanism for
+ multi-valued attributes.
+
+3.9 (Attribute) Name
+
+ Some operation elements are called parameters in the model document
+ [RFC2566]. They MUST be encoded in a special position and they MUST
+ NOT appear as an operation attributes. These parameters are:
+
+ - "version-number": The parameter named "version-number" in the
+ IPP model document MUST become the "version-number" field in the
+ operation layer request or response.
+
+
+
+Herriot, et al. Experimental [Page 13]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ - "operation-id": The parameter named "operation-id" in the IPP
+ model document MUST become the "operation-id" field in the
+ operation layer request.
+ - "status-code": The parameter named "status-code" in the IPP
+ model document MUST become the "status-code" field in the
+ operation layer response.
+ - "request-id": The parameter named "request-id" in the IPP model
+ document MUST become the "request-id" field in the operation
+ layer request or response.
+
+ All Printer and Job objects are identified by a Uniform Resource
+ Identifier (URI) [RFC2396] so that they can be persistently and
+ unambiguously referenced. The notion of a URI is a useful concept,
+ however, until the notion of URI is more stable (i.e., defined more
+ completely and deployed more widely), it is expected that the URIs
+ used for IPP objects will actually be URLs [RFC1738] [RFC1808].
+ Since every URL is a specialized form of a URI, even though the more
+ generic term URI is used throughout the rest of this document, its
+ usage is intended to cover the more specific notion of URL as well.
+
+ Some operation elements are encoded twice, once as the request-URI on
+ the HTTP Request-Line and a second time as a REQUIRED operation
+ attribute in the application/ipp entity. These attributes are the
+ target URI for the operation:
+
+ - "printer-uri": When the target is a printer and the transport is
+ HTTP or HTTPS (for SSL3 [ssl]), the target printer-uri defined
+ in each operation in the IPP model document MUST be an operation
+ attribute called "printer-uri" and it MUST also be specified
+ outside of the operation layer as the request-URI on the
+ Request-Line at the HTTP level.
+ - "job-uri": When the target is a job and the transport is HTTP or
+ HTTPS (for SSL3), the target job-uri of each operation in the
+ IPP model document MUST be an operation attribute called "job-
+ uri" and it MUST also be specified outside of the operation
+ layer as the request-URI on the Request-Line at the HTTP level.
+
+ Note: The target URI is included twice in an operation referencing
+ the same IPP object, but the two URIs NEED NOT be literally
+ identical. One can be a relative URI and the other can be an absolute
+ URI. HTTP/1.1 allows clients to generate and send a relative URI
+ rather than an absolute URI. A relative URI identifies a resource
+ with the scope of the HTTP server, but does not include scheme, host
+ or port. The following statements characterize how URLs should be
+ used in the mapping of IPP onto HTTP/1.1:
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 14]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ 1. Although potentially redundant, a client MUST supply the target
+ of the operation both as an operation attribute and as a URI at
+ the HTTP layer. The rationale for this decision is to maintain
+ a consistent set of rules for mapping application/ipp to
+ possibly many communication layers, even where URLs are not
+ used as the addressing mechanism in the transport layer.
+ 2. Even though these two URLs might not be literally identical
+ (one being relative and the other being absolute), they MUST
+ both reference the same IPP object.
+ 3. The URI in the HTTP layer is either relative or absolute and is
+ used by the HTTP server to route the HTTP request to the
+ correct resource relative to that HTTP server. The HTTP server
+ need not be aware of the URI within the operation request.
+ 4. Once the HTTP server resource begins to process the HTTP
+ request, it might get the reference to the appropriate IPP
+ Printer object from either the HTTP URI (using to the context
+ of the HTTP server for relative URLs) or from the URI within
+ the operation request; the choice is up to the implementation.
+ 5. HTTP URIs can be relative or absolute, but the target URI in
+ the operation MUST be an absolute URI.
+
+ The model document arranges the remaining attributes into groups for
+ each operation request and response. Each such group MUST be
+ represented in the protocol by an xxx-attribute-sequence preceded by
+ the appropriate xxx-attributes-tag (See the table below and section 9
+ "Appendix A: Protocol Examples"). In addition, the order of these
+ xxx-attributes-tags and xxx-attribute-sequences in the protocol MUST
+ be the same as in the model document, but the order of attributes
+ within each xxx-attribute-sequence MUST be unspecified. The table
+ below maps the model document group name to xxx-attributes-sequence:
+
+ Model Document Group xxx-attributes-sequence
+
+ Operation Attributes operations-attributes-sequence
+ Job Template Attributes job-attributes-sequence
+ Job Object Attributes job-attributes-sequence
+ Unsupported Attributes unsupported-attributes-sequence
+ Requested Attributes job-attributes-sequence
+ Get-Job-Attributes)
+ Requested Attributes printer-attributes-sequence
+ Get-Printer-Attributes)
+ Document Content in a special position as described
+ above
+
+ If an operation contains attributes from more than one job object
+ (e.g. Get-Jobs response), the attributes from each job object MUST
+ be in a separate job-attribute-sequence, such that the attributes
+
+
+
+
+Herriot, et al. Experimental [Page 15]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ from the ith job object are in the ith job-attribute-sequence. See
+ Section 9 "Appendix A: Protocol Examples" for table showing the
+ application of the rules above.
+
+3.10 Value Length
+
+ Each attribute value MUST be preceded by a SIGNED-SHORT, which MUST
+ specify the number of octets in the value which follows this length,
+ exclusive of the two bytes specifying the length.
+
+ For any of the types represented by binary signed integers, the
+ sender MUST encode the value in exactly four octets.
+
+ For any of the types represented by character-strings, the sender
+ MUST encode the value with all the characters of the string and
+ without any padding characters.
+
+ If a value-tag contains an "out-of-band" value, such as
+ "unsupported", the value-length MUST be 0 and the value empty. The
+ value has no meaning when the value-tag has an "out-of-band" value.
+ If a client receives a response with a nonzero value-length in this
+ case, it MUST ignore the value field. If a printer receives a request
+ with a nonzero value-length in this case, it MUST reject the request.
+
+3.11 (Attribute) Value
+
+ The syntax types and most of the details of their representation are
+ defined in the IPP model document. The table below augments the
+ information in the model document, and defines the syntax types from
+ the model document in terms of the 5 basic types defined in section 3
+ "Encoding of the Operation Layer". The 5 types are US-ASCII-STRING,
+ LOCALIZED-STRING, SIGNED-INTEGER, SIGNED-SHORT, SIGNED-BYTE, and
+ OCTET-STRING.
+
+Syntax of Attribute Encoding
+Value
+
+textWithoutLanguage, LOCALIZED-STRING.
+nameWithoutLanguage
+
+textWithLanguage OCTET_STRING consisting of 4 fields:
+ a) a SIGNED-SHORT which is the number of octets
+ in the following field
+ b) a value of type natural-language,
+ c) a SIGNED-SHORT which is the number of octets
+ in the following field,
+ d) a value of type textWithoutLanguage.
+
+
+
+
+Herriot, et al. Experimental [Page 16]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ The length of a textWithLanguage value MUST be 4
+ + the value of field a + the value of field c.
+
+nameWithLanguage OCTET_STRING consisting of 4 fields:
+ a) a SIGNED-SHORT which is the number of octets
+ in the following field
+ b) a value of type natural-language,
+ c) a SIGNED-SHORT which is the number of octets
+ in the following field
+ d) a value of type nameWithoutLanguage.
+
+ The length of a nameWithLanguage value MUST be 4
+ + the value of field a + the value of field c.
+
+charset, US-ASCII-STRING.
+naturalLanguage,
+mimeMediaType,
+keyword, uri, and
+uriScheme
+
+boolean SIGNED-BYTE where 0x00 is 'false' and 0x01 is
+ 'true'.
+
+Syntax of Attribute Encoding
+Value
+
+
+integer and enum a SIGNED-INTEGER.
+
+dateTime OCTET-STRING consisting of eleven octets whose
+ contents are defined by "DateAndTime" in RFC
+ 2579 [RFC2579].
+
+resolution OCTET_STRING consisting of nine octets of 2
+ SIGNED-INTEGERs followed by a SIGNED-BYTE. The
+ first SIGNED-INTEGER contains the value of cross
+ feed direction resolution. The second SIGNED-
+ INTEGER contains the value of feed direction
+ resolution. The SIGNED-BYTE contains the units
+ value.
+
+rangeOfInteger Eight octets consisting of 2 SIGNED-INTEGERs.
+ The first SIGNED-INTEGER contains the lower
+ bound and the second SIGNED-INTEGER contains the
+ upper bound.
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 17]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+1setOf X Encoding according to the rules for an attribute
+ with more than 1 value. Each value X is encoded
+ according to the rules for encoding its type.
+
+octetString OCTET-STRING
+
+ The type of the value in the model document determines the encoding
+ in the value and the value of the value-tag.
+
+3.12 Data
+
+ The data part MUST include any data required by the operation
+
+4. Encoding of Transport Layer
+
+ HTTP/1.1 [RFC2068] is the transport layer for this protocol.
+
+ The operation layer has been designed with the assumption that the
+ transport layer contains the following information:
+
+ - the URI of the target job or printer operation
+ - the total length of the data in the operation layer, either as a
+ single length or as a sequence of chunks each with a length.
+
+ It is REQUIRED that a printer implementation support HTTP over the
+ IANA assigned Well Known Port 631 (the IPP default port), though a
+ printer implementation may support HTTP over some other port as well.
+ In addition, a printer may have to support another port for privacy
+ (See Section 5 "Security Considerations").
+
+ Note: even though port 631 is the IPP default, port 80 remains the
+ default for an HTTP URI. Thus a URI for a printer using port 631
+ MUST contain an explicit port, e.g. "http://forest:631/pinetree". An
+ HTTP URI for IPP with no explicit port implicitly reference port 80,
+ which is consistent with the rules for HTTP/1.1. Each HTTP operation
+ MUST use the POST method where the request-URI is the object target
+ of the operation, and where the "Content-Type" of the message-body in
+ each request and response MUST be "application/ipp". The message-body
+ MUST contain the operation layer and MUST have the syntax described
+ in section 3.2 "Syntax of Encoding". A client implementation MUST
+ adhere to the rules for a client described for HTTP1.1 [RFC2068]. A
+ printer (server) implementation MUST adhere the rules for an origin
+ server described for HTTP1.1 [RFC2068].
+
+ An IPP server sends a response for each request that it receives. If
+ an IPP server detects an error, it MAY send a response before it has
+ read the entire request. If the HTTP layer of the IPP server
+ completes processing the HTTP headers successfully, it MAY send an
+
+
+
+Herriot, et al. Experimental [Page 18]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ intermediate response, such as "100 Continue", with no IPP data
+ before sending the IPP response. A client MUST expect such a variety
+ of responses from an IPP server. For further information on HTTP/1.1,
+ consult the HTTP documents [RFC2068].
+
+5. Security Considerations
+
+ The IPP Model document defines an IPP implementation with "privacy"
+ as one that implements Secure Socket Layer Version 3 (SSL3). Note:
+ SSL3 is not an IETF standards track specification. SSL3 meets the
+ requirements for IPP security with regards to features such as mutual
+ authentication and privacy (via encryption). The IPP Model document
+ also outlines IPP-specific security considerations and should be the
+ primary reference for security implications with regards to the IPP
+ protocol itself.
+
+ The IPP Model document defines an IPP implementation with
+ "authentication" as one that implements the standard way for
+ transporting IPP messages within HTTP 1.1. These include the security
+ considerations outlined in the HTTP 1.1 standard document [RFC2068]
+ and Digest Access Authentication extension [RFC2069].
+
+ The current HTTP infrastructure supports HTTP over TCP port 80. IPP
+ server implementations MUST offer IPP services using HTTP over the
+ IANA assigned Well Known Port 631 (the IPP default port). IPP server
+ implementations may support other ports, in addition to this port.
+
+ See further discussion of IPP security concepts in the model document
+ [RFC2566].
+
+5.1 Using IPP with SSL3
+
+ An assumption is that the URI for a secure IPP Printer object has
+ been found by means outside the IPP printing protocol, via a
+ directory service, web site or other means.
+
+ IPP provides a transparent connection to SSL by calling the
+ corresponding URL (a https URI connects by default to port 443).
+ However, the following functions can be provided to ease the
+ integration of IPP with SSL during implementation:
+
+ connect (URI), returns a status
+
+ "connect" makes an https call and returns the immediate status
+ of the connection as returned by SSL to the user. The status
+ values are explained in section 5.4.2 of the SSL document
+ [ssl].
+
+
+
+
+Herriot, et al. Experimental [Page 19]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ A session-id may also be retained to later resume a session.
+ The SSL handshake protocol may also require the cipher
+ specifications supported by the client, key length of the
+ ciphers, compression methods, certificates, etc. These should
+ be sent to the server and hence should be available to the IPP
+ client (although as part of administration features).
+
+ disconnect (session)
+
+ to disconnect a particular session.
+
+ The session-id available from the "connect" could be used.
+
+ resume (session)
+
+ to reconnect using a previous session-id.
+
+ The availability of this information as administration features are
+ left for implementers, and need not be specified at this time.
+
+6. References
+
+ [RFC2278] Freed, N. and J. Postel, "IANA Charset Registration
+ Procedures", BCP 19, RFC 2278, January 1998.
+
+ [dpa] ISO/IEC 10175 Document Printing Application (DPA), June
+ 1996.
+
+ [iana] IANA Registry of Coded Character Sets:
+ ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets.
+
+ [ipp-iig] Hastings, Tom, et al., "Internet Printing Protocol/1.0:
+ Implementer's Guide", Work in Progress.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P., Tuner, R., "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 20]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages", STD 11, RFC 822, August 1982.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC1179] McLaughlin, L. III, (editor), "Line Printer Daemon
+ Protocol" RFC 1179, August 1990.
+
+ [RFC2223] Postel, J. and J. Reynolds, "Instructions to RFC Authors",
+ RFC 2223, October 1997.
+
+ [RFC1738] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S. and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1766] Alvestrand, H., " Tags for the Identification of
+ Languages", RFC 1766, March 1995.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators", RFC
+ 1808, June 1995.
+
+ [RFC2579] McCloghrie, K., Perkins, D. and J. Schoenwaelder, "Textual
+ Conventions for SMIv2", STD 58, RFC 2579, April 1999.
+
+ [RFC2046] Freed, N. and N. Borenstein, Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+ [RFC2048] Freed, N., Klensin J. and J. Postel. Multipurpose Internet
+ Mail Extension (MIME) Part Four: Registration Procedures",
+ BCP 13, RFC 2048, November 1996.
+
+ [RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
+ 2068, January 1997.
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 21]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ [RFC2069] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to
+ HTTP: Digest Access Authentication", RFC 2069, January
+ 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2184] Freed, N. and K. Moore, "MIME Parameter Value and Encoded
+ Word Extensions: Character Sets, Languages, and
+ Continuations", RFC 2184, August 1997.
+
+ [RFC2234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234. November 1997.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+7. Authors' Addresses
+
+ Robert Herriot (Editor)
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: rherriot@pahv.xerox.com
+
+
+ Sylvan Butler
+ Hewlett-Packard
+ 11311 Chinden Blvd.
+ Boise, ID 83714
+
+ Phone: 208-396-6000
+ Fax: 208-396-3457
+ EMail: sbutler@boi.hp.com
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 22]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Paul Moore
+ Microsoft
+ One Microsoft Way
+ Redmond, WA 98053
+
+ Phone: 425-936-0908
+ Fax: 425-93MS-FAX
+ EMail: paulmo@microsoft.com
+
+
+ Randy Turner
+ Sharp Laboratories
+ 5750 NW Pacific Rim Blvd
+ Camas, WA 98607
+
+ Phone: 360-817-8456
+ Fax: 360-817-8436
+ EMail: rturner@sharplabs.com
+
+
+ IPP Mailing List: ipp@pwg.org
+ IPP Mailing List Subscription: ipp-request@pwg.org
+ IPP Web Page: http://www.pwg.org/ipp/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 23]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+8. Other Participants:
+
+ Chuck Adams - Tektronix Harry Lewis - IBM
+ Ron Bergman - Dataproducts Tony Liao - Vivid Image
+ Keith Carter - IBM David Manchala - Xerox
+ Angelo Caruso - Xerox Carl-Uno Manros - Xerox
+ Jeff Copeland - QMS Jay Martin - Underscore
+ Roger deBry - IBM Larry Masinter - Xerox
+ Lee Farrell - Canon Ira McDonald - High North Inc.
+ Sue Gleeson - Digital Bob Pentecost - Hewlett-Packard
+ Charles Gordon - Osicom Patrick Powell - Astart
+ Technologies
+ Brian Grimshaw - Apple Jeff Rackowitz - Intermec
+ Jerry Hadsell - IBM Xavier Riley - Xerox
+ Richard Hart - Digital Gary Roberts - Ricoh
+ Tom Hastings - Xerox Stuart Rowley - Kyocera
+ Stephen Holmstead Richard Schneider - Epson
+ Zhi-Hong Huang - Zenographics Shigern Ueda - Canon
+ Scott Isaacson - Novell Bob Von Andel - Allegro Software
+ Rich Lomicka - Digital William Wagner - Digital Products
+ David Kellerman - Northlake Jasper Wong - Xionics
+ Software
+ Robert Kline - TrueSpectra Don Wright - Lexmark
+ Dave Kuntz - Hewlett-Packard Rick Yardumian - Xerox
+ Takami Kurono - Brother Lloyd Young - Lexmark
+ Rich Landau - Digital Peter Zehler - Xerox
+ Greg LeClair - Epson Frank Zhao - Panasonic
+ Steve Zilles - Adobe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 24]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+9. Appendix A: Protocol Examples
+
+9.1 Print-Job Request
+
+ The following is an example of a Print-Job request with job-name,
+ copies, and sides specified. The "ipp-attribute-fidelity" attribute
+ is set to 'true' so that the print request will fail if the "copies"
+ or the "sides" attribute are not supported or their values are not
+ supported.
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x0002 Print-Job operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x001A value-length
+ http://forest: printer pinetree value
+ 631/pinetree
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0006 value-length
+ foobar foobar value
+ 0x22 boolean type value-tag
+ 0x16 name-length
+ ipp-attribute- ipp-attribute-fidelity name
+ fidelity
+ 0x01 value-length
+ 0x01 true value
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer type value-tag
+
+
+
+Herriot, et al. Experimental [Page 25]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x44 keyword type value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0013 value-length
+ two-sided- two-sided-long-edge value
+ long-edge
+ 0x03 end-of-attributes end-of-attributes-tag
+ %!PS... <PostScript> data
+
+9.2 Print-Job Response (successful)
+
+ Here is an example of a successful Print-Job response to the previous
+ Print-Job request. The printer supported the "copies" and "sides"
+ attributes and their supplied values. The status code returned is '
+ successful-ok'.
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x0000 successful-ok status-code
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural- name
+ natural-language language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x000D value-length
+ successful-ok successful-ok value
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer value-tag
+ 0x0006 name-length
+
+
+
+
+
+Herriot, et al. Experimental [Page 26]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x45 uri type value-tag
+ 0x0007 name-length
+ job-uri job-uri name
+ 0x001E value-length
+ http://forest:63 job 123 on pinetree value
+ 1/pinetree/123
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0009 name-length
+ job-state job-state name
+ 0x0004 value-length
+ 0x0003 pending value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+9.3 Print-Job Response (failure)
+
+ Here is an example of an unsuccessful Print-Job response to the
+ previous Print-Job request. It fails because, in this case, the
+ printer does not support the "sides" attribute and because the value
+ '20' for the "copies" attribute is not supported. Therefore, no job
+ is created, and neither a "job-id" nor a "job-uri" operation
+ attribute is returned. The error code returned is 'client-error-
+ attributes-or-values-not-supported' (0x040B).
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x040B client-error-attributes-or- status-code
+ values-not-supported
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attribute tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+
+
+
+
+Herriot, et al. Experimental [Page 27]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status- status-message name
+ message
+ 0x002F value-length
+ client-error- client-error-attributes-or- value
+ attributes- values-not-supported
+ or-values-
+ not-supported
+ 0x05 start unsupported-attributes unsupported-attributes tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x10 unsupported (type) value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0000 value-length
+ 0x03 end-of-attributes end-of-attributes-tag
+
+9.4 Print-Job Response (success with attributes ignored)
+
+ Here is an example of a successful Print-Job response to a Print-Job
+ request like the previous Print-Job request, except that the value of
+ 'ipp-attribute-fidelity' is false. The print request succeeds, even
+ though, in this case, the printer supports neither the "sides"
+ attribute nor the value '20' for the "copies" attribute. Therefore, a
+ job is created, and both a "job-id" and a "job-uri" operation
+ attribute are returned. The unsupported attributes are also returned
+ in an Unsupported Attributes Group. The error code returned is '
+ successful-ok-ignored-or-substituted-attributes' (0x0001).
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x0001 successful-ok-ignored-or- status-code
+ substituted-attributes
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+
+
+
+Herriot, et al. Experimental [Page 28]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural- name
+ natural-language language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x002F value-length
+ successful-ok- successful-ok-ignored-or- value
+ ignored-or- substituted-attributes
+ substituted-
+ attributes
+ 0x05 start unsupported- unsupported-attributes
+ attributes tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x10 unsupported (type) value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0000 value-length
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x45 uri type value-tag
+ 0x0007 name-length
+ job-uri job-uri name
+ 0x001E value-length
+ http://forest:63 job 123 on pinetree value
+ 1/pinetree/123
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0009 name-length
+ job-state job-state name
+ 0x0004 value-length
+ 0x0003 pending value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+
+
+
+
+Herriot, et al. Experimental [Page 29]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+9.5 Print-URI Request
+
+ The following is an example of Print-URI request with copies and
+ job-name parameters:
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+
+ Octets Symbolic Value Protocol field
+ 0x0003 Print-URI operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x001A value-length
+ http://forest printer pinetree value
+ :631/pinetree
+ 0x45 uri type value-tag
+ 0x000C name-length
+ document-uri document-uri name
+ 0x11 value-length
+ ftp://foo.com ftp://foo.com/foo value
+ /foo
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0006 value-length
+ foobar foobar value
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+
+
+
+Herriot, et al. Experimental [Page 30]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ 0x00000001 1 value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+9.6 Create-Job Request
+
+ The following is an example of Create-Job request with no parameters
+ and no attributes:
+
+ Octets Symbolic Value Protocol field
+ 0x0100 1.0 version-number
+ 0x0005 Create-Job operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+
+ Octets Symbolic Value Protocol field
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x001A value-length
+ http://forest: printer pinetree value
+ 631/pinetree
+ 0x03 end-of-attributes end-of-attributes-tag
+
+9.7 Get-Jobs Request
+
+ The following is an example of Get-Jobs request with parameters but
+ no attributes:
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x000A Get-Jobs operation-id
+ 0x00000123 0x123 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+
+
+
+Herriot, et al. Experimental [Page 31]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x001A value-length
+ http://forest:6 printer pinetree value
+ 31/pinetree
+ 0x21 integer type value-tag
+ 0x0005 name-length
+ limit limit name
+ 0x0004 value-length
+ 0x00000032 50 value
+ 0x44 keyword type value-tag
+ 0x0014 name-length
+ requested- requested-attributes name
+ attributes
+ 0x0006 value-length
+ job-id job-id value
+ 0x44 keyword type value-tag
+ 0x0000 additional value name-length
+ 0x0008 value-length
+ job-name job-name value
+ 0x44 keyword type value-tag
+ 0x0000 additional value name-length
+ 0x000F value-length
+ document-format document-format value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+9.8 Get-Jobs Response
+
+ The following is an of Get-Jobs response from previous request with 3
+ jobs. The Printer returns no information about the second job
+ (because of security reasons):
+
+
+
+
+
+Herriot, et al. Experimental [Page 32]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ 0x0100 1.0 version-number
+ 0x0000 successful-ok status-code
+ 0x00000123 0x123 request-id (echoed
+ back)
+ 0x01 start operation-attributes operation-attribute-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x000A value-length
+ ISO-8859-1 ISO-8859-1 value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x000D value-length
+ successful-ok successful-ok value
+ 0x02 start job-attributes (1st job-attributes-tag
+ object)
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x36 nameWithLanguage value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x000C value-length
+ 0x0005 sub-value-length
+ fr-ca fr-CA value
+ 0x0003 sub-value-length
+ fou fou name
+ 0x02 start job-attributes (2nd job-attributes-tag
+ object)
+ 0x02 start job-attributes (3rd job-attributes-tag
+ object)
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+
+
+
+Herriot, et al. Experimental [Page 33]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Octets Symbolic Value Protocol field
+
+ 148 148 value
+ 0x36 nameWithLanguage value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0012 value-length
+ 0x0005 sub-value-length
+ de-CH de-CH value
+ 0x0009 sub-value-length
+ isch guet isch guet name
+ 0x03 end-of-attributes end-of-attributes-tag
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 34]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+10. Appendix C: Registration of MIME Media Type Information for
+ "application/ipp"
+
+ This appendix contains the information that IANA requires for
+ registering a MIME media type. The information following this
+ paragraph will be forwarded to IANA to register application/ipp whose
+ contents are defined in Section 3 "Encoding of the Operation Layer"
+ in this document:
+
+ MIME type name: application
+
+ MIME subtype name: ipp
+
+ A Content-Type of "application/ipp" indicates an Internet Printing
+ Protocol message body (request or response). Currently there is one
+ version: IPP/1.0, whose syntax is described in Section 3 "Encoding of
+ the Operation Layer" of [RFC2565], and whose semantics are described
+ in [RFC2566].
+
+ Required parameters: none
+
+ Optional parameters: none
+
+ Encoding considerations:
+
+ IPP/1.0 protocol requests/responses MAY contain long lines and ALWAYS
+ contain binary data (for example attribute value lengths).
+
+ Security considerations:
+
+ IPP/1.0 protocol requests/responses do not introduce any security
+ risks not already inherent in the underlying transport protocols.
+ Protocol mixed-version interworking rules in [RFC2566] as well as
+ protocol encoding rules in [RFC2565] are complete and unambiguous.
+
+ Interoperability considerations:
+
+ IPP/1.0 requests (generated by clients) and responses (generated by
+ servers) MUST comply with all conformance requirements imposed by the
+ normative specifications [RFC2566] and [RFC2565]. Protocol encoding
+ rules specified in [RFC2565] are comprehensive, so that
+ interoperability between conforming implementations is guaranteed
+ (although support for specific optional features is not ensured).
+ Both the "charset" and "natural-language" of all IPP/1.0 attribute
+ values which are a LOCALIZED-STRING are explicit within IPP protocol
+ requests/responses (without recourse to any external information in
+ HTTP, SMTP, or other message transport headers).
+
+
+
+
+Herriot, et al. Experimental [Page 35]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+ Published specification:
+
+ [RFC2566] Isaacson, S., deBry, R., Hastings, T., Herriot, R. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics" RFC 2566, April 1999.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P., Tuner, R., "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ Applications which use this media type:
+
+ Internet Printing Protocol (IPP) print clients and print servers,
+ communicating using HTTP/1.1 (see [RFC2565]), SMTP/ESMTP, FTP, or
+ other transport protocol. Messages of type "application/ipp" are
+ self-contained and transport-independent, including "charset" and
+ "natural-language" context for any LOCALIZED-STRING value.
+
+ Person & email address to contact for further information:
+
+ Scott A. Isaacson
+ Novell, Inc.
+ 122 E 1700 S
+ Provo, UT 84606
+
+ Phone: 801-861-7366
+ Fax: 801-861-4025
+ Email: sisaacson@novell.com
+
+ or
+
+ Robert Herriot (Editor)
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: rherriot@pahv.xerox.com
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 36]
+
+RFC 2565 IPP/1.0: Encoding and Transport April 1999
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 37]
+
diff --git a/standards/rfc2566.txt b/standards/rfc2566.txt
new file mode 100644
index 000000000..f373d6a0f
--- /dev/null
+++ b/standards/rfc2566.txt
@@ -0,0 +1,9691 @@
+
+
+
+
+
+
+Network Working Group R. deBry
+Request for Comments: 2566 Utah Valley State College
+Category: Experimental T. Hastings
+ Xerox Corporation
+ R. Herriot
+ Xerox Corporation
+ S. Isaacson
+ Novell, Inc.
+ P. Powell
+ Astart Technologies
+ April 1999
+
+
+ Internet Printing Protocol/1.0: Model and Semantics
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note
+
+ This document defines an Experimental protocol for the Internet
+ community. The IESG expects that a revised version of this protocol
+ will be published as Proposed Standard protocol. The Proposed
+ Standard, when published, is expected to change from the protocol
+ defined in this memo. In particular, it is expected that the
+ standards-track version of the protocol will incorporate strong
+ authentication and privacy features, and that an "ipp:" URL type will
+ be defined which supports those security measures. Other changes to
+ the protocol are also possible. Implementors are warned that future
+ versions of this protocol may not interoperate with the version of
+ IPP defined in this document, or if they do interoperate, that some
+ protocol features may not be available.
+
+ The IESG encourages experimentation with this protocol, especially in
+ combination with Transport Layer Security (TLS) [RFC 2246], to help
+ determine how TLS may effectively be used as a security layer for
+ IPP.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 1]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document describes a
+ simplified model consisting of abstract objects, their attributes,
+ and their operations that is independent of encoding and transport.
+ The model consists of a Printer and a Job object. A Job optionally
+ supports multiple documents. IPP 1.0 semantics allow end-users and
+ operators to query printer capabilities, submit print jobs, inquire
+ about the status of print jobs and printers, and cancel print jobs.
+ This document also addresses security, internationalization, and
+ directory issues.
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics (this document)
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Internet Printing Protocol/1.0: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0. Operator and administrator requirements
+ are out of scope for version 1.0.
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specifications, and gives background and rationale for the
+ IETF working group's major decisions.
+
+ The "Internet Printing Protocol/1.0: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1. It defines the encoding rules
+ for a new Internet media type called "application/ipp".
+
+ The "Internet Printing Protocol/1.0: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.0 and some of
+
+
+
+deBry, et al. Experimental [Page 2]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+Table of Contents
+
+1. Introduction 8
+ 1.1 Simplified Printing Model 9
+2. IPP Objects 11
+ 2.1 Printer Object 12
+ 2.2 Job Object 14
+ 2.3 Object Relationships 14
+ 2.4 Object Identity 15
+3. IPP Operations 18
+ 3.1 Common Semantics 19
+ 3.1.1 Required Parameters 19
+ 3.1.2 Operation IDs and Request IDs 20
+ 3.1.3 Attributes 20
+ 3.1.4 Character Set and Natural Language Operation Attributes 22
+ 3.1.4.1 Request Operation Attributes 22
+ 3.1.4.2 Response Operation Attributes 26
+ 3.1.5 Operation Targets 28
+ 3.1.6 Operation Status Codes and Messages 29
+ 3.1.7 Versions 30
+ 3.1.8 Job Creation Operations 32
+ 3.2 Printer Operations 34
+ 3.2.1 Print-Job Operation 34
+ 3.2.1.1 Print-Job Request 34
+ 3.2.1.2 Print-Job Response 38
+ 3.2.2 Print-URI Operation 41
+ 3.2.3 Validate-Job Operation 42
+ 3.2.4 Create-Job Operation 42
+ 3.2.5 Get-Printer-Attributes Operation 43
+ 3.2.5.1 Get-Printer-Attributes Request 44
+ 3.2.5.2 Get-Printer-Attributes Response 46
+ 3.2.6 Get-Jobs Operation 47
+ 3.2.6.1 Get-Jobs Request 47
+ 3.2.6.2 Get-Jobs Response 49
+ 3.3 Job Operations 50
+ 3.3.1 Send-Document Operation 50
+ 3.3.1.1 Send-Document Request 51
+ 3.3.1.2 Send-Document Response 53
+ 3.3.2 Send-URI Operation 54
+
+
+
+deBry, et al. Experimental [Page 3]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 3.3.3 Cancel-Job Operation 54
+ 3.3.3.1 Cancel-Job Request 54
+ 3.3.3.2 Cancel-Job Response 55
+ 3.3.4 Get-Job-Attributes Operation 56
+ 3.3.4.1 Get-Job-Attributes Request 57
+ 3.3.4.2 Get-Job-Attributes Response 57
+4. Object Attributes 58
+ 4.1 Attribute Syntaxes 59
+ 4.1.1 'text' 60
+ 4.1.1.1 'textWithoutLanguage' 61
+ 4.1.1.2 'textWithLanguage' 61
+ 4.1.2 'name' 62
+ 4.1.2.1 'nameWithoutLanguage' 62
+ 4.1.2.2 'nameWithLanguage' 63
+ 4.1.2.3 Matching 'name' attribute values 63
+ 4.1.3 'keyword' 64
+ 4.1.4 'enum' 65
+ 4.1.5 'uri' 65
+ 4.1.6 'uriScheme' 65
+ 4.1.7 'charset' 66
+ 4.1.8 'naturalLanguage' 67
+ 4.1.9 'mimeMediaType' 67
+ 4.1.10 'octetString' 69
+ 4.1.11 'boolean' 69
+ 4.1.12 'integer' 69
+ 4.1.13 'rangeOfInteger' 69
+ 4.1.14 'dateTime' 69
+ 4.1.15 'resolution' 69
+ 4.1.16 '1setOf X' 70
+ 4.2 Job Template Attributes 70
+ 4.2.1 job-priority (integer(1:100)) 74
+ 4.2.2 job-hold-until (type3 keyword | name (MAX)) 75
+ 4.2.3 job-sheets (type3 keyword | name(MAX)) 75
+ 4.2.4 multiple-document-handling (type2 keyword) 76
+ 4.2.5 copies (integer(1:MAX)) 77
+ 4.2.6 finishings (1setOf type2 enum) 78
+ 4.2.7 page-ranges (1setOf rangeOfInteger (1:MAX)) 79
+ 4.2.8 sides (type2 keyword) 80
+ 4.2.9 number-up (integer(1:MAX)) 80
+ 4.2.10 orientation-requested (type2 enum) 81
+ 4.2.11 media (type3 keyword | name(MAX)) 82
+ 4.2.12 printer-resolution (resolution) 83
+ 4.2.13 print-quality (type2 enum) 83
+ 4.3 Job Description Attributes 84
+ 4.3.1 job-uri (uri) 85
+ 4.3.2 job-id (integer(1:MAX)) 85
+ 4.3.3 job-printer-uri (uri) 86
+ 4.3.4 job-more-info (uri) 86
+
+
+
+deBry, et al. Experimental [Page 4]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 4.3.5 job-name (name(MAX)) 86
+ 4.3.6 job-originating-user-name (name(MAX)) 86
+ 4.3.7 job-state (type1 enum) 87
+ 4.3.8 job-state-reasons (1setOf type2 keyword) 90
+ 4.3.9 job-state-message (text(MAX)) 92
+ 4.3.10 number-of-documents (integer(0:MAX)) 93
+ 4.3.11 output-device-assigned (name(127)) 93
+ 4.3.12 time-at-creation (integer(0:MAX)) 93
+ 4.3.13 time-at-processing (integer(0:MAX)) 93
+ 4.3.14 time-at-completed (integer(0:MAX)) 94
+ 4.3.15 number-of-intervening-jobs (integer(0:MAX)) 94
+ 4.3.16 job-message-from-operator (text(127)) 94
+ 4.3.17 job-k-octets (integer(0:MAX)) 94
+ 4.3.18 job-impressions (integer(0:MAX)) 95
+ 4.3.19 job-media-sheets (integer(0:MAX)) 95
+ 4.3.20 job-k-octets-processed (integer(0:MAX)) 96
+ 4.3.21 job-impressions-completed (integer(0:MAX)) 96
+ 4.3.22 job-media-sheets-completed (integer(0:MAX)) 96
+ 4.3.23 attributes-charset (charset) 97
+ 4.3.24 attributes-natural-language (naturalLanguage) 97
+ 4.4 Printer Description Attributes 97
+ 4.4.1 printer-uri-supported (1setOf uri) 99
+ 4.4.2 uri-security-supported (1setOf type2 keyword) 100
+ 4.4.3 printer-name (name(127)) 101
+ 4.4.4 printer-location (text(127)) 101
+ 4.4.5 printer-info (text(127)) 101
+ 4.4.6 printer-more-info (uri) 101
+ 4.4.7 printer-driver-installer (uri) 102
+ 4.4.8 printer-make-and-model (text(127)) 102
+ 4.4.9 printer-more-info-manufacturer (uri) 102
+ 4.4.10 printer-state (type1 enum) 102
+ 4.4.11 printer-state-reasons (1setOf type2 keyword) 103
+ 4.4.12 printer-state-message (text(MAX)) 106
+ 4.4.13 operations-supported (1setOf type2 enum) 106
+ 4.4.14 charset-configured (charset) 107
+ 4.4.15 charset-supported (1setOf charset) 107
+ 4.4.16 natural-language-configured (naturalLanguage) 107
+ 4.4.17 generated-natural-language-supported(1setOf naturalLanguage108
+ 4.4.18 document-format-default (mimeMediaType) 108
+ 4.4.19 document-format-supported (1setOf mimeMediaType) 108
+ 4.4.20 printer-is-accepting-jobs (boolean) 109
+ 4.4.21 queued-job-count (integer(0:MAX)) 109
+ 4.4.22 printer-message-from-operator (text(127)) 109
+ 4.4.23 color-supported (boolean) 109
+ 4.4.24 reference-uri-schemes-supported (1setOf uriScheme) 109
+ 4.4.25 pdl-override-supported (type2 keyword) 110
+ 4.4.26 printer-up-time (integer(1:MAX)) 110
+ 4.4.27 printer-current-time (dateTime) 111
+
+
+
+deBry, et al. Experimental [Page 5]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 4.4.28 multiple-operation-time-out (integer(1:MAX)) 111
+ 4.4.29 compression-supported (1setOf type3 keyword) 111
+ 4.4.30 job-k-octets-supported (rangeOfInteger(0:MAX)) 112
+ 4.4.31 job-impressions-supported (rangeOfInteger(0:MAX)) 112
+ 4.4.32 job-media-sheets-supported (rangeOfInteger(0:MAX)) 112
+5. Conformance 112
+ 5.1 Client Conformance Requirements 112
+ 5.2 IPP Object Conformance Requirements 113
+ 5.2.1 Objects 113
+ 5.2.2 Operations 113
+ 5.2.3 IPP Object Attributes 114
+ 5.2.4 Extensions 114
+ 5.2.5 Attribute Syntaxes 115
+ 5.3 Charset and Natural Language Requirements 115
+ 5.4 Security Conformance Requirements 115
+6. IANA Considerations (registered and private extensions) 116
+ 6.1 Typed 'keyword' and 'enum' Extensions 116
+ 6.2 Attribute Extensibility 119
+ 6.3 Attribute Syntax Extensibility 119
+ 6.4 Operation Extensibility 120
+ 6.5 Attribute Groups 120
+ 6.6 Status Code Extensibility 120
+ 6.7 Registration of MIME types/sub-types for document-formats 121
+ 6.8 Registration of charsets for use in 'charset' attribute values121
+7. Internationalization Considerations 121
+8. Security Considerations 125
+ 8.1 Security Scenarios 126
+ 8.1.1 Client and Server in the Same Security Domain 126
+ 8.1.2 Client and Server in Different Security Domains 126
+ 8.1.3 Print by Reference 127
+ 8.2 URIs for SSL3 and non-SSL3 Access 127
+ 8.3 The "requesting-user-name" (name(MAX)) Operation Attribute 127
+ 8.4 Restricted Queries 129
+ 8.5 Queries on jobs submitted using non-IPP protocols 129
+ 8.6 IPP Security Application Profile for SSL3 130
+9. References 131
+10. Authors' Addresses 134
+11. Formats for IPP Registration Proposals 136
+ 11.1 Type2 keyword attribute values registration 136
+ 11.2 Type3 keyword attribute values registration 137
+ 11.3 Type2 enum attribute values registration 137
+ 11.4 Type3 enum attribute values registration 137
+ 11.5 Attribute registration 138
+ 11.6 Attribute Syntax registration 138
+ 11.7 Operation registration 139
+ 11.8 Attribute Group registration 139
+ 11.9 Status code registration 139
+12.APPENDIX A: Terminology 141
+
+
+
+deBry, et al. Experimental [Page 6]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 12.1 Conformance Terminology 141
+ 12.1.1 NEED NOT 141
+ 12.2 Model Terminology 141
+ 12.2.1 Keyword 141
+ 12.2.2 Attributes 141
+ 12.2.2.1 Attribute Name 141
+ 12.2.2.2 Attribute Group Name 142
+ 12.2.2.3 Attribute Value 142
+ 12.2.2.4 Attribute Syntax 142
+ 12.2.3 Supports 142
+ 12.2.4 print-stream page 144
+ 12.2.5 impression 144
+13.APPENDIX B: Status Codes and Suggested Status Code Messages 145
+ 13.1 Status Codes 146
+ 13.1.1 Informational 146
+ 13.1.2 Successful Status Codes 146
+ 13.1.2.1 successful-ok (0x0000) 146
+ 13.1.2.2 successful-ok-ignored-or-substituted-attributes (0x0001) 146
+ 13.1.2.3 successful-ok-conflicting-attributes (0x0002) 147
+ 13.1.3 Redirection Status Codes 147
+ 13.1.4 Client Error Status Codes 147
+ 13.1.4.1 client-error-bad-request (0x0400) 147
+ 13.1.4.2 client-error-forbidden (0x0401) 147
+ 13.1.4.3 client-error-not-authenticated (0x0402) 148
+ 13.1.4.4 client-error-not-authorized (0x0403) 148
+ 13.1.4.5 client-error-not-possible (0x0404) 148
+ 13.1.4.6 client-error-timeout (0x0405) 148
+ 13.1.4.7 client-error-not-found (0x0406) 149
+ 13.1.4.8 client-error-gone (0x0407) 149
+ 13.1.4.9 client-error-request-entity-too-large (0x0408) 149
+ 13.1.4.10client-error-request-value-too-long (0x0409) 150
+ 13.1.4.11client-error-document-format-not-supported (0x040A) 150
+ 13.1.4.12client-error-attributes-or-values-not-supported (0x040B) 150
+ 13.1.4.13client-error-uri-scheme-not-supported (0x040C) 151
+ 13.1.4.14client-error-charset-not-supported (0x040D) 151
+ 13.1.4.15client-error-conflicting-attributes (0x040E) 151
+ 13.1.5 Server Error Status Codes 151
+ 13.1.5.1 server-error-internal-error (0x0500) 151
+ 13.1.5.2 server-error-operation-not-supported (0x0501) 152
+ 13.1.5.3 server-error-service-unavailable (0x0502) 152
+ 13.1.5.4 server-error-version-not-supported (0x0503) 152
+ 13.1.5.5 server-error-device-error (0x0504) 152
+ 13.1.5.6 server-error-temporary-error (0x0505) 153
+ 13.1.5.7 server-error-not-accepting-jobs (0x0506) 153
+ 13.1.5.8 server-error-busy (0x0507) 153
+ 13.1.5.9 server-error-job-canceled (0x0508) 153
+ 13.2 Status Codes for IPP Operations 153
+14.APPENDIX C: "media" keyword values 155
+
+
+
+deBry, et al. Experimental [Page 7]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+15.APPENDIX D: Processing IPP Attributes 160
+ 15.1 Fidelity 160
+ 15.2 Page Description Language (PDL) Override 161
+ 15.3 Using Job Template Attributes During Document Processing. 163
+16.APPENDIX E: Generic Directory Schema 166
+17.APPENDIX F: Change History for the Model and Semantics document 168
+18.FULL COPYRIGHT STATEMENT 173
+
+1. Introduction
+
+ The Internet Printing Protocol (IPP) is an application level protocol
+ that can be used for distributed printing using Internet tools and
+ technologies. IPP version 1.0 (IPP/1.0) focuses only on end user
+ functionality. This document is just one of a suite of documents
+ that fully define IPP. The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics (this document)
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Internet Printing Protocol/1.0: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ Anyone reading these documents for the first time is strongly
+ encouraged to read the IPP documents in the above order.
+
+ This document is laid out as follows:
+
+ - The rest of Section 1 is an introduction to the IPP simplified
+ model for distributed printing.
+ - Section 2 introduces the object types covered in the model with
+ their basic behaviors, attributes, and interactions.
+ - Section 3 defines the operations included in IPP/1.0. IPP
+ operations are synchronous, therefore, for each operation, there
+ is a both request and a response.
+ - Section 4 defines the attributes (and their syntaxes) that are
+ used in the model.
+ - Sections 5 - 6 summarizes the implementation conformance
+ requirements for objects that support the protocol and IANA
+ considerations, respectively.
+ - Sections 7 - 11 cover the Internationalization and Security
+ considerations as well as References, Author contact information,
+ and Formats for Registration Proposals.
+ - Sections 12 - 14 are appendices that cover Terminology, Status
+ Codes and Messages, and "media" keyword values.
+
+
+
+
+
+deBry, et al. Experimental [Page 8]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: This document uses terms such as "attributes",
+ "keywords", and "support". These terms have special
+ meaning and are defined in the model terminology section
+ 12.2. Capitalized terms, such as MUST, MUST NOT, REQUIRED,
+ SHOULD, SHOULD NOT, MAY, NEED NOT, and OPTIONAL, have
+ special meaning relating to conformance. These terms are
+ defined in section 12.1 on conformance terminology, most of
+ which is taken from RFC 2119 [RFC2119].
+
+ - Section 15 is an appendix that helps to clarify the effects of
+ interactions between related attributes and their values.
+ - Section 16 is an appendix that enumerates the subset of Printer
+ attributes that form a generic directory schema. These
+ attributes are useful when registering a Printer so that a
+ client can find the Printer not just by name, but by filtered
+ searches as well.
+ - Section 17 is an appendix that provides a Change History
+ summarizing the clarification and changes that might affect an
+ implementation since the June 30, 1998 draft.
+
+1.1 Simplified Printing Model
+
+ In order to achieve its goal of realizing a workable printing
+ protocol for the Internet, the Internet Printing Protocol (IPP) is
+ based on a simplified printing model that abstracts the many
+ components of real world printing solutions. The Internet is a
+ distributed computing environment where requesters of print services
+ (clients, applications, printer drivers, etc.) cooperate and interact
+ with print service providers. This model and semantics document
+ describes a simple, abstract model for IPP even though the underlying
+ configurations may be complex "n-tier" client/server systems. An
+ important simplifying step in the IPP model is to expose only the key
+ objects and interfaces required for printing. The model described in
+ this model document does not include features, interfaces, and
+ relationships that are beyond the scope of the first version of IPP
+ (IPP/1.0). IPP/1.0 incorporates many of the relevant ideas and
+ lessons learned from other specification and development efforts
+ [HTPP] [ISO10175] [LDPA] [P1387.4] [PSIS] [RFC1179] [SWP]. IPP is
+ heavily influenced by the printing model introduced in the Document
+ Printing Application (DPA) [ISO10175] standard. Although DPA
+ specifies both end user and administrative features, IPP version 1.0
+ (IPP/1.0) focuses only on end user functionality.
+
+ The IPP/1.0 model encapsulates the important components of
+ distributed printing into two object types:
+
+ - Printer (Section 2.1)
+ - Job (Section 2.2)
+
+
+
+deBry, et al. Experimental [Page 9]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Each object type has an associated set of operations (see section 3)
+ and attributes (see section 4).
+
+ It is important, however, to understand that in real system
+ implementations (which lie underneath the abstracted IPP/1.0 model),
+ there are other components of a print service which are not
+ explicitly defined in the IPP/1.0 model. The following figure
+ illustrates where IPP/1.0 fits with respect to these other
+ components.
+
+ +--------------+
+ | Application |
+ o +. . . . . . . |
+ \|/ | Spooler |
+ / \ +. . . . . . . | +---------+
+ End-User | Print Driver |---| File |
+ +-----------+ +-----+ +------+-------+ +----+----+
+ | Browser | | GUI | | |
+ +-----+-----+ +--+--+ | |
+ | | | |
+ | +---+------------+---+ |
+ N D S | | IPP Client |------------+
+ O I E | +---------+----------+
+ T R C | |
+ I E U |
+ F C R -------------- Transport ------------------
+ I T I
+ C O T | --+
+ A R Y +--------+--------+ |
+ T Y | IPP Server | |
+ I +--------+--------+ |
+ O | |
+ N +-----------------+ | IPP Printer
+ | Print Service | |
+ +-----------------+ |
+ | --+
+ +-----------------+
+ | Output Device(s)|
+ +-----------------+
+
+ An IPP Printer object encapsulates the functions normally associated
+ with physical output devices along with the spooling, scheduling and
+ multiple device management functions often associated with a print
+ server. Printer objects are optionally registered as entries in a
+ directory where end users find and select them based on some sort of
+ filtered and context based searching mechanism (see section 16). The
+ directory is used to store relatively static information about the
+ Printer, allowing end users to search for and find Printers that
+
+
+
+deBry, et al. Experimental [Page 10]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ match their search criteria, for example: name, context, printer
+ capabilities, etc. The more dynamic information, such as state,
+ currently loaded and ready media, number of jobs at the Printer,
+ errors, warnings, and so forth, is directly associated with the
+ Printer object itself rather than with the entry in the directory
+ which only represents the Printer object.
+
+ IPP clients implement the IPP protocol on the client side and give
+ end users (or programs running on behalf of end users) the ability to
+ query Printer objects and submit and manage print jobs. An IPP
+ server is just that part of the Printer object that implements the
+ server-side protocol. The rest of the Printer object implements (or
+ gateways into) the application semantics of the print service itself.
+ The Printer objects may be embedded in an output device or may be
+ implemented on a host on the network that communicates with an output
+ device.
+
+ When a job is submitted to the Printer object and the Printer object
+ validates the attributes in the submission request, the Printer
+ object creates a new Job object. The end user then interacts with
+ this new Job object to query its status and monitor the progress of
+ the job. End users may also cancel the print job by using the Job
+ object's Cancel-Job operation. The notification service is out of
+ scope for IPP/1.0, but using such a notification service, the end
+ user is able to register for and receive Printer specific and Job
+ specific events. An end user can query the status of Printer objects
+ and can follow the progress of Job objects by polling using the Get-
+ Printer-Attributes, Get-Jobs, and Get-Job-Attributes operations.
+
+2. IPP Objects
+
+ The IPP/1.0 model introduces objects of type Printer and Job. Each
+ type of object models relevant aspects of a real-world entity such as
+ a real printer or real print job. Each object type is defined as a
+ set of possible attributes that may be supported by instances of that
+ object type. For each object (instance), the actual set of supported
+ attributes and values describe a specific implementation. The
+ object's attributes and values describe its state, capabilities,
+ realizable features, job processing functions, and default behaviors
+ and characteristics. For example, the Printer object type is defined
+ as a set of attributes that each Printer object potentially supports.
+ In the same manner, the Job object type is defined as a set of
+ attributes that are potentially supported by each Job object.
+
+ Each attribute included in the set of attributes defining an object
+ type is labeled as:
+
+
+
+
+
+deBry, et al. Experimental [Page 11]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ - "REQUIRED": each object MUST support the attribute.
+ - "OPTIONAL": each object MAY support the attribute.
+
+ There is no such similar labeling of attribute values. However, if
+ an implementation supports an attribute, it MUST support at least one
+ of the possible values for that attribute.
+
+2.1 Printer Object
+
+ The major component of the IPP/1.0 model is the Printer object. A
+ Printer object implements the server-side of the IPP/1.0 protocol.
+ Using the protocol, end users may query the attributes of the Printer
+ object and submit print jobs to the Printer object. The actual
+ implementation components behind the Printer abstraction may take on
+ different forms and different configurations. However, the model
+ abstraction allows the details of the configuration of real
+ components to remain opaque to the end user. Section 3 describes
+ each of the Printer operations in detail.
+
+ The capabilities and state of a Printer object are described by its
+ attributes. Printer attributes are divided into two groups:
+
+ - "job-template" attributes: These attributes describe supported
+ job processing capabilities and defaults for the Printer object.
+ (See section 4.2)
+ - "printer-description" attributes: These attributes describe the
+ Printer object's identification, state, location, references to
+ other sources of information about the Printer object, etc. (see
+ section 4.4)
+
+ Since a Printer object is an abstraction of a generic document output
+ device and print service provider, a Printer object could be used to
+ represent any real or virtual device with semantics consistent with
+ the Printer object, such as a fax device, an imager, or even a CD
+ writer.
+
+ Some examples of configurations supporting a Printer object include:
+
+ 1) An output device with no spooling capabilities
+ 2) An output device with a built-in spooler
+ 3) A print server supporting IPP with one or more associated output
+ devices
+ 3a) The associated output devices may or may not be capable of
+ spooling jobs
+ 3b) The associated output devices may or may not support IPP
+
+
+
+
+
+
+deBry, et al. Experimental [Page 12]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ The following figures show some examples of how Printer objects can
+ be realized on top of various distributed printing configurations.
+ The embedded case below represents configurations 1 and 2. The hosted
+ and fan-out figures below represent configurations 3a and 3b.
+
+ Legend:
+
+ ##### indicates a Printer object which is
+ either embedded in an output device or is
+ hosted in a server. The Printer object
+ might or might not be capable of queuing/spooling.
+
+ any indicates any network protocol or direct
+ connect, including IPP
+
+
+ embedded printer:
+ output device
+ +---------------+
+ O +--------+ | ########### |
+ /|\ | client |------------IPP------------># Printer # |
+ / \ +--------+ | # Object # |
+ | ########### |
+ +---------------+
+
+
+ hosted printer:
+ +---------------+
+ O +--------+ ########### | |
+ /|\ | client |--IPP--># Printer #-any->| output device |
+ / \ +--------+ # Object # | |
+ ########### +---------------+
+
+
+
+ +---------------+
+ fan out: | |
+ +-->| output device |
+ any/ | |
+ O +--------+ ########### / +---------------+
+ /|\ | client |-IPP-># Printer #--*
+ / \ +--------+ # Object # \ +---------------+
+ ########### any\ | |
+ +-->| output device |
+ | |
+ +---------------+
+
+
+
+
+
+deBry, et al. Experimental [Page 13]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+2.2 Job Object
+
+ A Job object is used to model a print job. A Job object contains
+ documents. The information required to create a Job object is sent
+ in a create request from the end user via an IPP Client to the
+ Printer object. The Printer object validates the create request, and
+ if the Printer object accepts the request, the Printer object creates
+ the new Job object. Section 3 describes each of the Job operations
+ in detail.
+
+ The characteristics and state of a Job object are described by its
+ attributes. Job attributes are grouped into two groups as follows:
+
+ - "job-template" attributes: These attributes can be supplied by
+ the client or end user and include job processing instructions
+ which are intended to override any Printer object defaults and/or
+ instructions embedded within the document data. (See section 4.2)
+ - "job-description" attributes: These attributes describe the Job
+ object's identification, state, size, etc. The client supplies
+ some of these attributes, and the Printer object generates others.
+ (See section 4.3)
+
+ An implementation MUST support at least one document per Job object.
+ An implementation MAY support multiple documents per Job object. A
+ document is either:
+
+ - a stream of document data in a format supported by the Printer
+ object (typically a Page Description Language - PDL), or
+ - a reference to such a stream of document data
+
+ In IPP/1.0, a document is not modeled as an IPP object, therefore it
+ has no object identifier or associated attributes. All job
+ processing instructions are modeled as Job object attributes. These
+ attributes are called Job Template attributes and they apply equally
+ to all documents within a Job object.
+
+2.3 Object Relationships
+
+ IPP objects have relationships that are maintained persistently along
+ with the persistent storage of the object attributes.
+
+ A Printer object can represent either one or more physical output
+ devices or a logical device which "processes" jobs but never actually
+ uses a physical output device to put marks on paper. Examples of
+ logical devices include a Web page publisher or a gateway into an
+ online document archive or repository. A Printer object contains
+ zero or more Job objects.
+
+
+
+
+deBry, et al. Experimental [Page 14]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ A Job object is contained by exactly one Printer object, however the
+ identical document data associated with a Job object could be sent to
+ either the same or a different Printer object. In this case, a
+ second Job object would be created which would be almost identical to
+ the first Job object, however it would have new (different) Job
+ object identifiers (see section 2.4).
+
+ A Job object is either empty (before any documents have been added)
+ or contains one or more documents. If the contained document is a
+ stream of document data, that stream can be contained in only one
+ document. However, there can be identical copies of the stream in
+ other documents in the same or different Job objects. If the
+ contained document is just a reference to a stream of document data,
+ other documents (in the same or different Job object(s)) may contain
+ the same reference.
+
+2.4 Object Identity
+
+ All Printer and Job objects are identified by a Uniform Resource
+ Identifier (URI) [RFC2396] so that they can be persistently and
+ unambiguously referenced. The notion of a URI is a useful concept,
+ however, until the notion of URI is more stable (i.e., defined more
+ completely and deployed more widely), it is expected that the URIs
+ used for IPP objects will actually be URLs [RFC2396]. Since every
+ URL is a specialized form of a URI, even though the more generic term
+ URI is used throughout the rest of this document, its usage is
+ intended to cover the more specific notion of URL as well.
+
+ An administrator configures Printer objects to either support or not
+ support authentication and/or message privacy using SSL3 [SSL] (the
+ mechanism for security configuration is outside the scope of
+ IPP/1.0). In some situations, both types of connections (both
+ authenticated and unauthenticated) can be established using a single
+ communication channel that has some sort of negotiation mechanism.
+ In other situations, multiple communication channels are used, one
+ for each type of security configuration. Section 8 provides a full
+ description of all security considerations and configurations.
+
+ If a Printer object supports more than one communication channel,
+ some or all of those channels might support and/or require different
+ security mechanisms. In such cases, an administrator could expose
+ the simultaneous support for these multiple communication channels as
+ multiple URIs for a single Printer object where each URI represents
+ one of the communication channels to the Printer object. To support
+ this flexibility, the IPP Printer object type defines a multi-valued
+ identification attribute called the "printer-uri-supported"
+ attribute. It MUST contain at least one URI. It MAY contain more
+ than one URI. That is, every Printer object will have at least one
+
+
+
+deBry, et al. Experimental [Page 15]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ URI that identifies at least one communication channel to the Printer
+ object, but it may have more than one URI where each URI identifies a
+ different communication channel to the Printer object. The
+ "printer-uri-supported" attribute has a companion attribute, the
+ "uri-security-supported" attribute, that has the same cardinality as
+ "printer-uri-supported". The purpose of the "uri-security-supported"
+ attribute is to indicate the security mechanisms (if any) used for
+ each URI listed in "printer-uri-supported". These two attributes are
+ fully described in sections 4.4.1 and 4.4.2.
+
+ When a job is submitted to the Printer object via a create request,
+ the client supplies only a single Printer object URI. The client
+ supplied Printer object URI MUST be one of the values in the
+ "printer-uri-supported" Printer attribute.
+
+ Note: IPP/1.0 does not specify how the client obtains the client
+ supplied URI, but it is RECOMMENDED that a Printer object be
+ registered as an entry in a directory service. End-users and
+ programs can then interrogate the directory searching for Printers.
+ Section 16 defines a generic schema for Printer object entries in the
+ directory service and describes how the entry acts as a bridge to the
+ actual IPP Printer object. The entry in the directory that
+ represents the IPP Printer object includes the possibly many URIs for
+ that Printer object as values in one its attributes.
+
+ When a client submits a create request to the Printer object, the
+ Printer object validates the request and creates a new Job object.
+ The Printer object assigns the new Job object a URI which is stored
+ in the "job-uri" Job attribute. This URI is then used by clients as
+ the target for subsequent Job operations. The Printer object
+ generates a Job URI based on its configured security policy and the
+ URI used by the client in the create request.
+
+ For example, consider a Printer object that supports both a
+ communication channel secured by the use of SSL3 (using HTTP over
+ SSL3 with an "https" schemed URI) and another open communication
+ channel that is not secured with SSL3 (using a simple "http" schemed
+ URI). If a client were to submit a job using the secure URI, the
+ Printer object would assign the new Job object a secure URI as well.
+ If a client were to submit a job using the open-channel URI, the
+ Printer would assign the new Job object an open-channel URI.
+
+ In addition, the Printer object also populates the Job object's
+ "job-printer-uri" attribute. This is a reference back to the Printer
+ object that created the Job object. If a client only has access to a
+ Job object's "job-uri" identifier, the client can query the Job's
+ "job-printer-uri" attribute in order to determine which Printer
+ object created the Job object. If the Printer object supports more
+
+
+
+deBry, et al. Experimental [Page 16]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ than one URI, the Printer object picks the one URI supplied by the
+ client when creating the job to build the value for and to populate
+ the Job's "job-printer-uri" attribute.
+
+ Allowing Job objects to have URIs allows for flexibility and
+ scalability. For example, in some implementations, the Printer
+ object might create Jobs that are processed in the same local
+ environment as the Printer object itself. In this case, the Job URI
+ might just be a composition of the Printer's URI and some unique
+ component for the Job object, such as the unique 32-bit positive
+ integer mentioned later in this paragraph. In other implementations,
+ the Printer object might be a central clearing-house for validating
+ all Job object creation requests, but the Job object itself might be
+ created in some environment that is remote from the Printer object.
+ In this case, the Job object's URI may have no physical-location
+ relationship at all to the Printer object's URI. Again, the fact
+ that Job objects have URIs allows for flexibility and scalability,
+ however, many existing printing systems have local models or
+ interface constraints that force print jobs to be identified using
+ only a 32-bit positive integer rather than an independent URI. This
+ numeric Job ID is only unique within the context of the Printer
+ object to which the create request was originally submitted.
+ Therefore, in order to allow both types of client access to IPP Job
+ objects (either by Job URI or by numeric Job ID), when the Printer
+ object successfully processes a create request and creates a new Job
+ object, the Printer object MUST generate both a Job URI and a Job ID.
+ The Job ID (stored in the "job-id" attribute) only has meaning in the
+ context of the Printer object to which the create request was
+ originally submitted. This requirement to support both Job URIs and
+ Job IDs allows all types of clients to access Printer objects and Job
+ objects no matter the local constraints imposed on the client
+ implementation.
+
+ In addition to identifiers, Printer objects and Job objects have
+ names ("printer-name" and "job-name"). An object name NEED NOT be
+ unique across all instances of all objects. A Printer object's name
+ is chosen and set by an administrator through some mechanism outside
+ the scope of IPP/1.0. A Job object's name is optionally chosen and
+ supplied by the IPP client submitting the job. If the client does
+ not supply a Job object name, the Printer object generates a name for
+ the new Job object. In all cases, the name only has local meaning.
+
+ To summarize:
+
+ - Each Printer object is identified with one or more URIs. The
+ Printer's "printer-uri-supported" attribute contains the URI(s).
+
+
+
+
+
+deBry, et al. Experimental [Page 17]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ - The Printer object's "uri-security-supported" attribute
+ identifies the communication channel security protocols that may
+ or may not have been configured for the various Printer object
+ URIs (e.g., 'ssl3' or 'none').
+ - Each Job object is identified with a Job URI. The Job's "job-uri"
+ attribute contains the URI.
+ - Each Job object is also identified with Job ID which is a 32-bit,
+ positive integer. The Job's "job-id" attribute contains the Job
+ ID. The Job ID is only unique within the context of the Printer
+ object which created the Job object.
+ - Each Job object has a "job-printer-uri" attribute which contains
+ the URI of the Printer object that was used to create the Job
+ object. This attribute is used to determine the Printer object
+ that created a Job object when given only the URI for the Job
+ object. This linkage is necessary to determine the languages,
+ charsets, and operations which are supported on that Job (the
+ basis for such support comes from the creating Printer object).
+ - Each Printer object has a name (which is not necessarily unique).
+ The administrator chooses and sets this name through some
+ mechanism outside the scope of IPP/1.0 itself. The Printer
+ object's "printer-name" attribute contains the name.
+ - Each Job object has a name (which is not necessarily unique). The
+ client optionally supplies this name in the create request. If
+ the client does not supply this name, the Printer object generates
+ a name for the Job object. The Job object's "job-name" attribute
+ contains the name.
+
+3. IPP Operations
+
+ IPP objects support operations. An operation consists of a request
+ and a response. When a client communicates with an IPP object, the
+ client issues an operation request to the URI for that object.
+ Operation requests and responses have parameters that identify the
+ operation. Operations also have attributes that affect the run-time
+ characteristics of the operation (the intended target, localization
+ information, etc.). These operation-specific attributes are called
+ operation attributes (as compared to object attributes such as
+ Printer object attributes or Job object attributes). Each request
+ carries along with it any operation attributes, object attributes,
+ and/or document data required to perform the operation. Each request
+ requires a response from the object. Each response indicates success
+ or failure of the operation with a status code as a response
+ parameter. The response contains any operation attributes, object
+ attributes, and/or status messages generated during the execution of
+ the operation request.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 18]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ This section describes the semantics of the IPP operations, both
+ requests and responses, in terms of the parameters, attributes, and
+ other data associated with each operation.
+
+ The IPP/1.0 Printer operations are:
+
+ Print-Job (section 3.2.1)
+ Print-URI (section 3.2.2)
+ Validate-Job (section 3.2.3)
+ Create-Job (section 3.2.4)
+ Get-Printer-Attributes (section 3.2.5)
+ Get-Jobs (section 3.2.6)
+
+ The Job operations are:
+
+ Send-Document (section 3.3.1)
+ Send-URI (section 3.3.2)
+ Cancel-Job (section 3.3.3)
+ Get-Job-Attributes (section 3.3.4)
+
+ The Send-Document and Send-URI Job operations are used to add a new
+ document to an existing multi-document Job object created using the
+ Create-Job operation.
+
+3.1 Common Semantics
+
+ All IPP operations require some common parameters and operation
+ attributes. These common elements and their semantic characteristics
+ are defined and described in more detail in the following sections.
+
+3.1.1 Required Parameters
+
+ Every operation request contains the following REQUIRED parameters:
+
+ - a "version-number",
+ - an "operation-id",
+ - a "request-id", and
+ - the attributes that are REQUIRED for that type of request.
+
+ Every operation response contains the following REQUIRED parameters:
+
+ - a "version-number",
+ - a "status-code",
+ - the "request-id" that was supplied in the corresponding request,
+ and
+ - the attributes that are REQUIRED for that type of response.
+
+
+
+
+
+deBry, et al. Experimental [Page 19]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ The encoding and transport document [RFC2565] defines special rules
+ for the encoding of these parameters. All other operation elements
+ are represented using the more generic encoding rules for attributes
+ and groups of attributes.
+
+3.1.2 Operation IDs and Request IDs
+
+ Each IPP operation request includes an identifying "operation-id"
+ value. Valid values are defined in the "operations-supported"
+ Printer attribute section (see section 4.4.13). The client specifies
+ which operation is being requested by supplying the correct
+ "operation-id" value.
+
+ In addition, every invocation of an operation is identified by a
+ "request-id" value. For each request, the client chooses the
+ "request-id" which MUST be an integer (possibly unique depending on
+ client requirements) in the range from 1 to 2**31 - 1 (inclusive).
+ This "request-id" allows clients to manage multiple outstanding
+ requests. The receiving IPP object copies all 32-bits of the client-
+ supplied "request-id" attribute into the response so that the client
+ can match the response with the correct outstanding request, even if
+ the "request-id" is out of range. If the request is terminated
+ before the complete "request-id" is received, the IPP object rejects
+ the request and returns a response with a "request-id" of 0.
+
+ Note: In some cases, the transport protocol underneath IPP might be a
+ connection oriented protocol that would make it impossible for a
+ client to receive responses in any order other than the order in
+ which the corresponding requests were sent. In such cases, the
+ "request-id" attribute would not be essential for correct protocol
+ operation. However, in other mappings, the operation responses can
+ come back in any order. In these cases, the "request-id" would be
+ essential.
+
+3.1.3 Attributes
+
+ Operation requests and responses are both composed of groups of
+ attributes and/or document data. The attributes groups are:
+
+ - Operation Attributes: These attributes are passed in the
+ operation and affect the IPP object's behavior while processing
+ the operation request and may affect other attributes or groups
+ of attributes. Some operation attributes describe the document
+ data associated with the print job and are associated with new
+ Job objects, however most operation attributes do not persist
+ beyond the life of the operation. The description of each
+ operation attribute includes conformance statements indicating
+ which operation attributes are REQUIRED and which are OPTIONAL
+
+
+
+deBry, et al. Experimental [Page 20]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ for an IPP object to support and which attributes a client MUST
+ supply in a request and an IPP object MUST supply in a response.
+ - Job Template Attributes: These attributes affect the processing
+ of a job. A client OPTIONALLY supplies Job Template Attributes
+ in a create request, and the receiving object MUST be prepared to
+ receive all supported attributes. The Job object can later be
+ queried to find out what Job Template attributes were originally
+ requested in the create request, and such attributes are returned
+ in the response as Job Object Attributes. The Printer object can
+ be queried about its Job Template attributes to find out what
+ type of job processing capabilities are supported and/or what the
+ default job processing behaviors are, though such attributes are
+ returned in the response as Printer Object Attributes. The
+ "ipp-attribute-fidelity" operation attribute affects processing
+ of all client-supplied Job Template attributes (see section 15
+ for a full description of "ipp-attribute-fidelity" and its
+ relationship to other attributes).
+ - Job Object Attributes: These attributes are returned in response
+ to a query operation directed at a Job object.
+ - Printer Object Attributes: These attributes are returned in
+ response to a query operation directed at a Printer object.
+ - Unsupported Attributes: In a create request, the client supplies
+ a set of Operation and Job Template attributes. If any of these
+ attributes or their values is unsupported by the Printer object,
+ the Printer object returns the set of unsupported attributes in
+ the response. Section 15 gives a full description of how Job
+ Template attributes supplied by the client in a create request
+ are processed by the Printer object and how unsupported
+ attributes are returned to the client. Because of extensibility,
+ any IPP object might receive a request that contains new or
+ unknown attributes or values for which it has no support. In such
+ cases, the IPP object processes what it can and returns the
+ unsupported attributes in the response.
+
+ Later in this section, each operation is formally defined by
+ identifying the allowed and expected groups of attributes for each
+ request and response. The model identifies a specific order for each
+ group in each request or response, but the attributes within each
+ group may be in any order, unless specified otherwise.
+
+ Each attribute specification includes the attribute's name followed
+ by the name of its attribute syntax(es) in parenthesizes. In
+ addition, each 'integer' attribute is followed by the allowed range
+ in parentheses, (m:n), for values of that attribute. Each 'text' or
+ 'name' attribute is followed by the maximum size in octets in
+ parentheses, (size), for values of that attribute. For more details
+ on attribute syntax notation, see the descriptions of these
+ attributes syntaxes in section 4.1.
+
+
+
+deBry, et al. Experimental [Page 21]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: Document data included in the operation is not strictly an
+ attribute, but it is treated as a special attribute group for
+ ordering purposes. The only operations that support supplying the
+ document data within an operation request are Print-Job and Send-
+ Document. There are no operation responses that include document
+ data.
+
+ Note: Some operations are REQUIRED for IPP objects to support; the
+ others are OPTIONAL (see section 5.2.2). Therefore, before using an
+ OPTIONAL operation, a client SHOULD first use the REQUIRED Get-
+ Printer-Attributes operation to query the Printer's "operations-
+ supported" attribute in order to determine which OPTIONAL Printer and
+ Job operations are actually supported. The client SHOULD NOT use an
+ OPTIONAL operation that is not supported. When an IPP object
+ receives a request to perform an operation it does not support, it
+ returns the 'server-error-operation-not-supported' status code (see
+ section 13.1.5.2). An IPP object is non-conformant if it does not
+ support a REQUIRED operation.
+
+3.1.4 Character Set and Natural Language Operation Attributes
+
+ Some Job and Printer attributes have values that are text strings and
+ names intended for human understanding rather than machine
+ understanding (see the 'text' and 'name' attribute syntax
+ descriptions in section 4.1). The following sections describe two
+ special Operation Attributes called "attributes-charset" and
+ "attributes-natural-language". These attributes are always part of
+ the Operation Attributes group. For most attribute groups, the order
+ of the attributes within the group is not important. However, for
+ these two attributes within the Operation Attributes group, the order
+ is critical. The "attributes-charset" attribute MUST be the first
+ attribute in the group and the "attributes-natural-language"
+ attribute MUST be the second attribute in the group. In other words,
+ these attributes MUST be supplied in every IPP request and response,
+ they MUST come first in the group, and MUST come in the specified
+ order. For job creation operations, the IPP Printer implementation
+ saves these two attributes with the new Job object as Job Description
+ attributes. For the sake of brevity in this document, these
+ operation attribute descriptions are not repeated with every
+ operation request and response, but have a reference back to this
+ section instead.
+
+3.1.4.1 Request Operation Attributes
+
+ The client MUST supply and the Printer object MUST support the
+ following REQUIRED operation attributes in every IPP/1.0 operation
+ request:
+
+
+
+
+deBry, et al. Experimental [Page 22]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "attributes-charset" (charset):
+ This operation attribute identifies the charset (coded character
+ set and encoding method) used by any 'text' and 'name'
+ attributes that the client is supplying in this request. It
+ also identifies the charset that the Printer object MUST use (if
+ supported) for all 'text' and 'name' attributes and status
+ messages that the Printer object returns in the response to this
+ request. See Sections 4.1.1 and 4.1.2 for the specification of
+ the 'text' and 'name' attribute syntaxes.
+
+ All clients and IPP objects MUST support the 'utf-8' charset
+ [RFC2279] and MAY support additional charsets provided that they
+ are registered with IANA [IANA-CS]. If the Printer object does
+ not support the client supplied charset value, the Printer
+ object MUST reject the request, set the "attributes-charset" to
+ 'utf-8' in the response, and return the 'client-error-charset-
+ not-supported' status code and any 'text' or 'name' attributes
+ using the 'utf-8' charset. The Printer object MUST indicate the
+ charset(s) supported as the values of the "charset-supported"
+ Printer attribute (see Section 4.4.15), so that the client can
+ query to determine which charset(s) are supported.
+
+ Note to client implementers: Since IPP objects are only required
+ to support the 'utf-8' charset, in order to maximize
+ interoperability with multiple IPP object implementations, a
+ client may want to supply 'utf-8' in the "attributes-charset"
+ operation attribute, even though the client is only passing and
+ able to present a simpler charset, such as US-ASCII or ISO-
+ 8859-1. Then the client will have to filter out (or charset
+ convert) those characters that are returned in the response that
+ it cannot present to its user. On the other hand, if both the
+ client and the IPP objects also support a charset in common
+ besides utf-8, the client may want to use that charset in order
+ to avoid charset conversion or data loss.
+
+ See the 'charset' attribute syntax description in Section 4.1.7
+ for the syntax and semantic interpretation of the values of this
+ attribute and for example values.
+
+ "attributes-natural-language" (naturalLanguage):
+ This operation attribute identifies the natural language used by
+ any 'text' and 'name' attributes that the client is supplying in
+ this request. This attribute also identifies the natural
+ language that the Printer object SHOULD use for all 'text' and '
+ name' attributes and status messages that the Printer object
+ returns in the response to this request.
+
+
+
+
+
+deBry, et al. Experimental [Page 23]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ There are no REQUIRED natural languages required for the Printer
+ object to support. However, the Printer object's "generated-
+ natural-language-supported" attribute identifies the natural
+ languages supported by the Printer object and any contained Job
+ objects for all text strings generated by the IPP object. A
+ client MAY query this attribute to determine which natural
+ language(s) are supported for generated messages.
+
+ For any of the attributes for which the Printer object generates
+ text, i.e., for the "job-state-message", "printer-state-
+ message", and status messages (see Section 3.1.6), the Printer
+ object MUST be able to generate these text strings in any of its
+ supported natural languages. If the client requests a natural
+ language that is not supported, the Printer object MUST return
+ these generated messages in the Printer's configured natural
+ language as specified by the Printer's "natural-language-
+ configured" attribute" (see Section 4.4.16).
+
+ For other 'text' and 'name' attributes supplied by the client,
+ authentication system, operator, system administrator, or
+ manufacturer (i.e., for "job-originating-user-name", "printer-
+ name" (name), "printer-location" (text), "printer-info" (text),
+ and "printer-make-and-model" (text)), the Printer object is only
+ required to support the configured natural language of the
+ Printer identified by the Printer object's "natural-language-
+ configured" attribute, though support of additional natural
+ languages for these attributes is permitted.
+
+ For any 'text' or 'name' attribute in the request that is in a
+ different natural language than the value supplied in the
+ "attributes-natural-language" operation attribute, the client
+ MUST use the Natural Language Override mechanism (see sections
+ 4.1.1.2 and 4.1.2.2) for each such attribute value supplied.
+ The client MAY use the Natural Language Override mechanism
+ redundantly, i.e., use it even when the value is in the same
+ natural language as the value supplied in the "attributes-
+ natural-language" operation attribute of the request.
+
+ The IPP object MUST accept any natural language and any Natural
+ Language Override, whether the IPP object supports that natural
+ language or not (and independent of the value of the "ipp-
+ attribute-fidelity" Operation attribute). That is the IPP
+ object accepts all client supplied values no matter what the
+ values are in the Printer object's "generated-natural-language-
+ supported" attribute. That attribute, "generated-natural-
+ language-supported", only applies to generated messages,
+
+
+
+
+
+deBry, et al. Experimental [Page 24]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ not client supplied messages. The IPP object MUST remember that
+ natural language for all client-supplied attributes, and when
+ returning those attributes in response to a query, the IPP
+ object MUST indicate that natural language.
+
+ Each value whose attribute syntax type is 'text' or 'name' (see
+ sections 4.1.1 and 4.1.2) has an Associated Natural-Language.
+ This document does not specify how this association is stored in
+ a Printer or Job object. When such a value is encoded in a
+ request or response, the natural language is either implicit or
+ explicit:
+
+ - In the implicit case, the value contains only the
+ text/name value, and the language is specified by the
+ "attributes-natural-language" operation attribute in the
+ request or response (see sections 4.1.1.1
+ textWithoutLanguage and 4.1.2.1 nameWithoutLanguage).
+
+ - In the explicit case (also known as the Natural-Language
+ Override case), the value contains both the language and
+ the text/name value (see sections 4.1.1.2
+ textWithLanguage and 4.1.2.2 nameWithLanguage).
+
+ For example, the "job-name" attribute MAY be supplied by the
+ client in a create request. The text value for this attribute
+ will be in the natural language identified by the "attribute-
+ natural-language" attribute, or if different, as identified by
+ the Natural Language Override mechanism. If supplied, the IPP
+ object will use the value of the "job-name" attribute to
+ populate the Job object's "job-name" attribute. Whenever any
+ client queries the Job object's "job-name" attribute, the IPP
+ object returns the attribute as stored and uses the Natural
+ Language Override mechanism to specify the natural language, if
+ it is different from that reported in the "attributes-natural-
+ language" operation attribute of the response. The IPP object
+ MAY use the Natural Language Override mechanism redundantly,
+ i.e., use it even when the value is in the same natural language
+ as the value supplied in the "attributes-natural-language"
+ operation attribute of the response.
+
+ An IPP object MUST NOT reject a request based on a supplied
+ natural language in an "attributes-natural-language" Operation
+ attribute or in any attribute that uses the Natural Language
+ Override.
+
+ See the 'naturalLanguage' attribute syntax description in
+ section 4.1.8 for the syntax and semantic interpretation of the
+ values of this attribute and for example values.
+
+
+
+deBry, et al. Experimental [Page 25]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Clients SHOULD NOT supply 'text' or 'name' attributes that use an
+ illegal combination of natural language and charset. For example,
+ suppose a Printer object supports charsets 'utf-8', 'iso-8859-1', and
+ 'iso-8859-7'. Suppose also, that it supports natural languages 'en'
+ (English), 'fr' (French), and 'el' (Greek). Although the Printer
+ object supports the charset 'iso-8859-1' and natural language 'el',
+ it probably does not support the combination of Greek text strings
+ using the 'iso-8859-1' charset. The Printer object handles this
+ apparent incompatibility differently depending on the context in
+ which it occurs:
+
+ - In a create request: If the client supplies a text or name
+ attribute (for example, the "job-name" operation attribute) that
+ uses an apparently incompatible combination, it is a client
+ choice that does not affect the Printer object or its correct
+ operation. Therefore, the Printer object simply accepts the
+ client supplied value, stores it with the Job object, and
+ responds back with the same combination whenever the client (or
+ any client) queries for that attribute.
+ - In a query-type operation, like Get-Printer-Attributes: If the
+ client requests an apparently incompatible combination, the
+ Printer object responds (as described in section 3.1.4.2) using
+ the Printer's configured natural language rather than the natural
+ language requested by the client.
+
+ In either case, the Printer object does not reject the request
+ because of the apparent incompatibility. The potential incompatible
+ combination of charset and natural language can occur either at the
+ global operation level or at the Natural Language Override
+ attribute-by-attribute level. In addition, since the response always
+ includes explicit charset and natural language information, there is
+ never any question or ambiguity in how the client interprets the
+ response.
+
+3.1.4.2 Response Operation Attributes
+
+ The Printer object MUST supply and the client MUST support the
+ following REQUIRED operation attributes in every IPP/1.0 operation
+ response:
+
+ "attributes-charset" (charset):
+ This operation attribute identifies the charset used by any '
+ text' and 'name' attributes that the Printer object is returning
+ in this response. The value in this response MUST be the same
+ value as the "attributes-charset" operation attribute supplied
+ by the client in the request. If this is not possible
+
+
+
+
+
+deBry, et al. Experimental [Page 26]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ (i.e., the charset requested is not supported), the request
+ would have been rejected. See "attributes-charset" described in
+ Section 3.1.4.1 above.
+
+ If the Printer object supports more than just the 'utf-8'
+ charset, the Printer object MUST be able to code convert between
+ each of the charsets supported on a highest fidelity possible
+ basis in order to return the 'text' and 'name' attributes in the
+ charset requested by the client. However, some information loss
+ MAY occur during the charset conversion depending on the
+ charsets involved. For example, the Printer object may convert
+ from a UTF-8 'a' to a US-ASCII 'a' (with no loss of
+ information), from an ISO Latin 1 CAPITAL LETTER A WITH ACUTE
+ ACCENT to US-ASCII 'A' (losing the accent), or from a UTF-8
+ Japanese Kanji character to some ISO Latin 1 error character
+ indication such as '?', decimal code equivalent, or to the
+ absence of a character, depending on implementation.
+
+ Note: Whether an implementation that supports more than one
+ charset stores the data in the charset supplied by the client or
+ code converts to one of the other supported charsets, depends on
+ implementation. The strategy should try to minimize loss of
+ information during code conversion. On each response, such an
+ implementation converts from its internal charset to that
+ requested.
+
+ "attributes-natural-language" (naturalLanguage):
+ This operation attribute identifies the natural language used by
+ any 'text' and 'name' attributes that the IPP object is
+ returning in this response. Unlike the "attributes-charset"
+ operation attribute, the IPP object NEED NOT return the same
+ value as that supplied by the client in the request. The IPP
+ object MAY return the natural language of the Job object or the
+ Printer's configured natural language as identified by the
+ Printer object's "natural-language-configured" attribute, rather
+ than the natural language supplied by the client. For any '
+ text' or 'name' attribute or status message in the response that
+ is in a different natural language than the value returned in
+ the "attributes-natural-language" operation attribute, the IPP
+ object MUST use the Natural Language Override mechanism (see
+ sections 4.1.1.2 and 4.1.2.2) on each attribute value returned.
+ The IPP object MAY use the Natural Language Override mechanism
+ redundantly, i.e., use it even when the value is in the same
+ natural language as the value supplied in the "attributes-
+ natural-language" operation attribute of the response.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 27]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+3.1.5 Operation Targets
+
+ All IPP operations are directed at IPP objects. For Printer
+ operations, the operation is always directed at a Printer object
+ using one of its URIs (i.e., one of the values in the Printer
+ object's "printer-uri-supported" attribute). Even if the Printer
+ object supports more than one URI, the client supplies only one URI
+ as the target of the operation. The client identifies the target
+ object by supplying the correct URI in the "printer-uri (uri)"
+ operation attribute.
+
+ For Job operations, the operation is directed at either:
+
+ - The Job object itself using the Job object's URI. In this case,
+ the client identifies the target object by supplying the correct
+ URI in the "job-uri (uri)" operation attribute.
+ - The Printer object that created the Job object using both the
+ Printer objects URI and the Job object's Job ID. Since the
+ Printer object that created the Job object generated the Job ID,
+ it MUST be able to correctly associate the client supplied Job ID
+ with the correct Job object. The client supplies the Printer
+ object's URI in the "printer-uri (uri)" operation attribute and
+ the Job object's Job ID in the "job-id (integer(1:MAX))"
+ operation attribute.
+
+ If the operation is directed at the Job object directly using the Job
+ object's URI, the client MUST NOT include the redundant "job-id"
+ operation attribute.
+
+ The operation target attributes are REQUIRED operation attributes
+ that MUST be included in every operation request. Like the charset
+ and natural language attributes (see section 3.1.4), the operation
+ target attributes are specially ordered operation attributes. In all
+ cases, the operation target attributes immediately follow the
+ "attributes-charset" and "attributes-natural-language" attributes
+ within the operation attribute group, however the specific ordering
+ rules are:
+
+ - In the case where there is only one operation target attribute
+ (i.e., either only the "printer-uri" attribute or only the "job-
+ uri" attribute), that attribute MUST be the third attribute in
+ the operation attributes group.
+ - In the case where Job operations use two operation target
+ attributes (i.e., the "printer-uri" and "job-id" attributes), the
+ "printer-uri" attribute MUST be the third attribute and the
+ "job-id" attribute MUST be the fourth attribute.
+
+
+
+
+
+deBry, et al. Experimental [Page 28]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ In all cases, the target URIs contained within the body of IPP
+ operation requests and responses must be in absolute format rather
+ than relative format (a relative URL identifies a resource with the
+ scope of the HTTP server, but does not include scheme, host or port).
+
+ The following rules apply to the use of port numbers in URIs that
+ identify IPP objects:
+
+ 1. If the URI scheme allows the port number to be explicitly
+ included in the URI string, and a port number is specified
+ within the URI, then that port number MUST be used by the client
+ to contact the IPP object.
+
+ 2. If the URI scheme allows the port number to be explicitly
+ included in the URI string, and a port number is not specified
+ within the URI, then default port number implied by that URI
+ scheme MUST be used by the client to contact the IPP object.
+
+ 3. If the URI scheme does not allow an explicit port number to be
+ specified within the URI, then the default port number implied
+ by that URI MUST be used by the client to contact the IPP
+ object.
+
+ Note: The IPP encoding and transport document [RFC2565] shows a
+ mapping of IPP onto HTTP/1.1 and defines a new default port number
+ for using IPP over HTTP/1.1.
+
+3.1.6 Operation Status Codes and Messages
+
+ Every operation response includes a REQUIRED "status-code" parameter
+ and an OPTIONAL "status-message" operation attribute. The "status-
+ code" provides information on the processing of a request. A
+ "status-message" attribute provides a short textual description of
+ the status of the operation. The status code is intended for use by
+ automata, and the status message is intended for the human end user.
+ If a response does include a "status-message" attribute, an IPP
+ client NEED NOT examine or display the message, however it SHOULD do
+ so in some implementation specific manner.
+
+ The "status-code" value is a numeric value that has semantic meaning.
+ The "status-code" syntax is similar to a "type2 enum" (see section
+ 4.1 on "Attribute Syntaxes") except that values can range only from
+ 0x0000 to 0x7FFF. Section 13 describes the status codes, assigns the
+ numeric values, and suggests a corresponding status message for each
+ status code. The "status-message" attribute's syntax is "text(255)".
+ A client implementation of IPP SHOULD convert status code values into
+ any localized message that has semantic meaning to the end user.
+
+
+
+
+deBry, et al. Experimental [Page 29]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ If the Printer object supports the "status-message" operation
+ attribute, the Printer object MUST be able to generate this message
+ in any of the natural languages identified by the Printer object's
+ "generated-natural-language-supported" attribute (see the
+ "attributes-natural-language" operation attribute specified in
+ section 3.1.4.1). As described in section 3.1.4.1 for any returned '
+ text' attribute, if there is a choice for generating this message,
+ the Printer object uses the natural language indicated by the value
+ of the "attributes-natural-language" in the client request if
+ supported, otherwise the Printer object uses the value in the Printer
+ object's own "natural-language-configured" attribute. If the Printer
+ object supports the "status-message" operation attribute, it SHOULD
+ use the REQUIRED 'utf-8' charset to return a status message for the
+ following error status codes (see section 13): 'client-error-bad-
+ request', 'client-error-charset-not-supported', 'server-error-
+ internal-error', 'server-error-operation-not-supported', and '
+ server-error-version-not-supported'. In this case, it MUST set the
+ value of the "attributes-charset" operation attribute to 'utf-8' in
+ the error response.
+
+3.1.7 Versions
+
+ Each operation request and response carries with it a "version-
+ number" parameter. Each value of the "version-number" is in the form
+ "X.Y" where X is the major version number and Y is the minor version
+ number. By including a version number in the client request, it
+ allows the client to identify which version of IPP it is interested
+ in using. If the IPP object does not support that version, the
+ object responds with a status code of 'server-error-version-not-
+ supported' along with the closest version number that is supported
+ (see section 13.1.5.4).
+
+ There is no version negotiation per se. However, if after receiving
+ a 'server-error-version-not-supported' status code from an IPP
+ object, there is nothing that prevents a client from trying again
+ with a different version number. In order to conform to IPP/1.0, an
+ implementation MUST support at least version '1.0'.
+
+ There is only one notion of "version number" that covers both IPP
+ Model and IPP Protocol changes. Thus the version number MUST change
+ when introducing a new version of the Model and Semantics document
+ [RFC2566] or a new version of the Encoding and Transport document
+ [RFC2565].
+
+ Changes to the major version number indicate structural or syntactic
+ changes that make it impossible for older version of IPP clients and
+ Printer objects to correctly parse and process the new or changed
+ attributes, operations and responses. If the major version number
+
+
+
+deBry, et al. Experimental [Page 30]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ changes, the minor version numbers is set to zero. As an example,
+ adding the "ipp-attribute-fidelity" attribute (if it had not been
+ part of version '1.0'), would have required a change to the major
+ version number. Items that might affect the changing of the major
+ version number include any changes to the Model and Semantics
+ document [RFC2566] or the Encoding and Transport [RFC2565] itself,
+ such as:
+
+ - reordering of ordered attributes or attribute sets
+ - changes to the syntax of existing attributes
+ - changing Operation or Job Template attributes from OPTIONAL to
+ REQUIRED and vice versa
+ - adding REQUIRED (for an IPP object to support) operation
+ attributes
+ - adding REQUIRED (for an IPP object to support) operation
+ attribute groups
+ - adding values to existing operation attributes
+ - adding REQUIRED operations
+
+ Changes to the minor version number indicate the addition of new
+ features, attributes and attribute values that may not be understood
+ by all IPP objects, but which can be ignored if not understood.
+ Items that might affect the changing of the minor version number
+ include any changes to the model objects and attributes but not the
+ encoding and transport rules [RFC2565] (except adding attribute
+ syntaxes). Examples of such changes are:
+
+ - grouping all extensions not included in a previous version into
+ a new version
+ - adding new attribute values
+ - adding new object attributes
+ - adding OPTIONAL (for an IPP object to support) operation
+ attributes (i.e., those attributes that an IPP object can ignore
+ without confusing clients)
+ - adding OPTIONAL (for an IPP object to support) operation
+ attribute groups (i.e., those attributes that an IPP object can
+ ignore without confusing clients)
+ - adding new attribute syntaxes
+ - adding OPTIONAL operations
+ - changing Job Description attributes or Printer Description
+ attributes from OPTIONAL to REQUIRED or vice versa.
+
+ The encoding of the "operation-id", the "version-number", the
+ "status-code", and the "request-id" MUST NOT change over any version
+ number (either major or minor). This rule guarantees that all future
+ versions will be backwards compatible with all previous versions (at
+ least for checking the "operation-id", the "version-number", and the
+ "request-id"). In addition, any protocol elements (attributes, error
+
+
+
+deBry, et al. Experimental [Page 31]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ codes, tags, etc.) that are not carried forward from one version to
+ the next are deprecated so that they can never be reused with new
+ semantics.
+
+ Implementations that support a certain major version NEED NOT support
+ ALL previous versions. As each new major version is defined (through
+ the release of a new specification), that major version will specify
+ which previous major versions MUST be supported in compliant
+ implementations.
+
+3.1.8 Job Creation Operations
+
+ In order to "submit a print job" and create a new Job object, a
+ client issues a create request. A create request is any one of
+ following three operation requests:
+
+ - The Print-Job Request: A client that wants to submit a print job
+ with only a single document uses the Print-Job operation. The
+ operation allows for the client to "push" the document data to
+ the Printer object by including the document data in the request
+ itself.
+
+ - The Print-URI Request: A client that wants to submit a print job
+ with only a single document (where the Printer object "pulls" the
+ document data instead of the client "pushing" the data to the
+ Printer object) uses the Print-URI operation. In this case, the
+ client includes in the request only a URI reference to the
+ document data (not the document data itself).
+
+ - The Create-Job Request: A client that wants to submit a print job
+ with multiple documents uses the Create-Job operation. This
+ operation is followed by an arbitrary number of Send-Document
+ and/or Send-URI operations (each creating another document for
+ the newly create Job object). The Send-Document operation
+ includes the document data in the request (the client "pushes"
+ the document data to the printer), and the Send-URI operation
+ includes only a URI reference to the document data in the request
+ (the Printer "pulls" the document data from the referenced
+ location). The last Send-Document or Send-URI request for a
+ given Job object includes a "last-document" operation attribute
+ set to 'true' indicating that this is the last request.
+
+ Throughout this model specification, the term "create request" is
+ used to refer to any of these three operation requests.
+
+ A Create-Job operation followed by only one Send-Document operation
+ is semantically equivalent to a Print-Job operation, however, for
+ performance reasons, the client SHOULD use the Print-Job operation
+
+
+
+deBry, et al. Experimental [Page 32]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ for all single document jobs. Also, Print-Job is a REQUIRED
+ operation (all implementations MUST support it) whereas Create-Job is
+ an OPTIONAL operation, hence some implementations might not support
+ it.
+
+ Job submission time is the point in time when a client issues a
+ create request. The initial state of every Job object is the '
+ pending' or 'pending-held' state. Later, the Printer object begins
+ processing the print job. At this point in time, the Job object's
+ state moves to 'processing'. This is known as job processing time.
+ There are validation checks that must be done at job submission time
+ and others that must be performed at job processing time.
+
+ At job submission time and at the time a Validate-Job operation is
+ received, the Printer MUST do the following:
+
+ 1. Process the client supplied attributes and either accept or
+ reject the request
+ 2. Validate the syntax of and support for the scheme of any client
+ supplied URI
+
+ At job submission time the Printer object MUST validate whether or
+ not the supplied attributes, attribute syntaxes, and values are
+ supported by matching them with the Printer object's corresponding
+ "xxx-supported" attributes. See section 3.2.1.2 for details. [ipp-
+ iig] presents suggested steps for an IPP object to either accept or
+ reject any request and additional steps for processing create
+ requests.
+
+ At job submission time the Printer object NEED NOT perform the
+ validation checks reserved for job processing time such as:
+
+ 1. Validating the document data
+ 2. Validating the actual contents of any client supplied URI
+ (resolve the reference and follow the link to the document data)
+
+ At job submission time, these additional job processing time
+ validation checks are essentially useless, since they require
+ actually parsing and interpreting the document data, are not
+ guaranteed to be 100% accurate, and MUST be done, yet again, at job
+ processing time. Also, in the case of a URI, checking for
+ availability at job submission time does not guarantee availability
+ at job processing time. In addition, at job processing time, the
+ Printer object might discover any of the following conditions that
+ were not detectable at job submission time:
+
+ - runtime errors in the document data,
+ - nested document data that is in an unsupported format,
+
+
+
+deBry, et al. Experimental [Page 33]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ - the URI reference is no longer valid (i.e., the server hosting
+ the document might be down), or
+ - any other job processing error
+
+ At job processing time, since the Printer object has already
+ responded with a successful status code in the response to the create
+ request, if the Printer object detects an error, the Printer object
+ is unable to inform the end user of the error with an operation
+ status code. In this case, the Printer, depending on the error, can
+ set the "job-state", "job-state-reasons", or "job-state-message"
+ attributes to the appropriate value(s) so that later queries can
+ report the correct job status.
+
+ Note: Asynchronous notification of events is outside the scope of
+ IPP/1.0.
+
+3.2 Printer Operations
+
+ All Printer operations are directed at Printer objects. A client
+ MUST always supply the "printer-uri" operation attribute in order to
+ identify the correct target of the operation.
+
+3.2.1 Print-Job Operation
+
+ This REQUIRED operation allows a client to submit a print job with
+ only one document and supply the document data (rather than just a
+ reference to the data). See Section 15 for the suggested steps for
+ processing create operations and their Operation and Job Template
+ attributes.
+
+3.2.1.1 Print-Job Request
+
+ The following groups of attributes are supplied as part of the
+ Print-Job Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1. The Printer object
+ MUST copy these values to the corresponding Job Description
+ attributes described in sections 4.3.23 and 4.3.24.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+
+
+
+
+deBry, et al. Experimental [Page 34]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "job-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied Job name. If this attribute is supplied by the client,
+ its value is used for the "job-name" attribute of the newly
+ created Job object. The client MAY automatically include any
+ information that will help the end-user distinguish amongst
+ his/her jobs, such as the name of the application program along
+ with information from the document, such as the document name,
+ document subject, or source file name. If this attribute is not
+ supplied by the client, the Printer generates a name to use in
+ the "job-name" attribute of the newly created Job object (see
+ Section 4.3.5).
+
+ "ipp-attribute-fidelity" (boolean):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. The value 'true' indicates
+ that total fidelity to client supplied Job Template attributes
+ and values is required, else the Printer object MUST reject the
+ Print-Job request. The value 'false' indicates that a
+ reasonable attempt to print the Job object is acceptable and the
+ Printer object MUST accept the Print-job request. If not
+ supplied, the Printer object assumes the value is 'false'. All
+ Printer objects MUST support both types of job processing. See
+ section 15 for a full description of "ipp-attribute-fidelity"
+ and its relationship to other attributes, especially the Printer
+ object's "pdl-override-supported" attribute.
+
+ "document-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied document name. The document name MAY be different than
+ the Job name. Typically, the client software automatically
+ supplies the document name on behalf of the end user by using a
+ file name or an application generated name. If this attribute
+ is supplied, its value can be used in a manner defined by each
+ implementation. Examples include: printed along with the Job
+ (job start sheet, page adornments, etc.), used by accounting or
+ resource tracking management tools, or even stored along with
+ the document as a document level attribute. IPP/1.0 does not
+ support the concept of document level attributes.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 35]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "document-format" (mimeMediaType) :
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. The value of this attribute
+ identifies the format of the supplied document data. If the
+ client does not supply this attribute, the Printer object
+ assumes that the document data is in the format defined by the
+ Printer object's "document-format-default" attribute. If the
+ client supplies this attribute, but the value is not supported
+ by the Printer object, i.e., the value is not one of the values
+ of the Printer object's "document-format-supported" attribute,
+ the Printer object MUST reject the request and return the '
+ client-error-document-format-not-supported' status code.
+
+ "document-natural-language" (naturalLanguage):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. This attribute
+ specifies the natural language of the document for those
+ document-formats that require a specification of the natural
+ language in order to image the document unambiguously. There are
+ no particular values required for the Printer object to support.
+
+ "compression" (type3 keyword)
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "compression-
+ supported" attribute (see section 4.4.29). The client supplied
+ "compression" operation attribute identifies the compression
+ algorithm used on the document data. If the client omits this
+ attribute, the Printer object MUST assume that the data is not
+ compressed. If the client supplies the attribute and the
+ Printer object supports the attribute, the Printer object uses
+ the corresponding decompression algorithm on the document data.
+ If the client supplies this attribute, but the value is not
+ supported by the Printer object, i.e., the value is not one of
+ the values of the Printer object's "compression-supported"
+ attribute, the Printer object MUST copy the attribute and its
+ value to the Unsupported Attributes response group, reject the
+ request, and return the 'client-error-attributes-or-values-not-
+ supported' status code.
+
+ "job-k-octets" (integer(0:MAX))
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-k-
+ octets-supported" attribute (see section 4.4.30). The client
+ supplied "job-k-octets" operation attribute identifies the total
+ size of the document(s) in K octets being submitted (see section
+ 4.3.17 for the complete semantics). If the client supplies the
+
+
+
+
+
+deBry, et al. Experimental [Page 36]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ attribute and the Printer object supports the attribute, the
+ value of the attribute is used to populate the Job object's
+ "job-k-octets" Job Description attribute.
+
+ Note: For this attribute and the following two attributes
+ ("job-impressions", and "job-media-sheets"), if the client
+ supplies the attribute, but the Printer object does not support
+ the attribute, the Printer object ignores the client-supplied
+ value. If the client supplies the attribute and the Printer
+ supports the attribute, and the value is within the range of the
+ corresponding Printer object's "xxx-supported" attribute, the
+ Printer object MUST use the value to populate the Job object's
+ "xxx" attribute. If the client supplies the attribute and the
+ Printer supports the attribute, but the value is outside the
+ range of the corresponding Printer object's "xxx-supported"
+ attribute, the Printer object MUST copy the attribute and its
+ value to the Unsupported Attributes response group, reject the
+ request, and return the 'client-error-attributes-or-values-not-
+ supported' status code. If the client does not supply the
+ attribute, the Printer object MAY choose to populate the
+ corresponding Job object attribute depending on whether the
+ Printer object supports the attribute and is able to calculate
+ or discern the correct value.
+
+ "job-impressions" (integer(0:MAX))
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-
+ impressions-supported" attribute (see section 4.4.31). The
+ client supplied "job-impressions" operation attribute identifies
+ the total size in number of impressions of the document(s) being
+ submitted (see section 4.3.18 for the complete semantics).
+
+ See note under "job-k-octets".
+
+ "job-media-sheets" (integer(0:MAX))
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-media-
+ sheets-supported" attribute (see section 4.4.32). The client
+ supplied "job-media-sheets" operation attribute identifies the
+ total number of media sheets to be produced for this job (see
+ section 4.3.19 for the complete semantics).
+
+ See note under "job-k-octets".
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 37]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Group 2: Job Template Attributes
+
+ The client OPTIONALLY supplies a set of Job Template attributes
+ as defined in section 4.2. If the client is not supplying any
+ Job Template attributes in the request, the client SHOULD omit
+ Group 2 rather than sending an empty group. However, a Printer
+ object MUST be able to accept an empty group.
+
+ Group 3: Document Content
+
+ The client MUST supply the document data to be processed.
+
+ Note: In addition to the MANDATORY parameters required for every
+ operation request, the simplest Print-Job Request consists of just
+ the "attributes-charset" and "attributes-natural-language" operation
+ attributes; the "printer-uri" target operation attribute; the
+ Document Content and nothing else. In this simple case, the Printer
+ object:
+
+ - creates a new Job object (the Job object contains a single
+ document),
+ - stores a generated Job name in the "job-name" attribute in the
+ natural language and charset requested (see Section 3.1.4.1) (if
+ those are supported, otherwise using the Printer object's default
+ natural language and charset), and
+ - at job processing time, uses its corresponding default value
+ attributes for the supported Job Template attributes that were
+ not supplied by the client as IPP attribute or embedded
+ instructions in the document data.
+
+3.2.1.2 Print-Job Response
+
+ The Printer object MUST return to the client the following sets
+ of attributes as part of the Print-Job Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in sections 14 and
+ 3.1.6. If the client supplies unsupported or conflicting Job
+ Template attributes or values, the Printer object MUST reject or
+ accept the Print-Job request depending on the whether the client
+ supplied a 'true' or 'false' value for the "ipp-attribute-
+ fidelity" operation attribute. See the Implementer's Guide
+ [ipp-iig] for a complete description of the suggested steps for
+ processing a create request.
+
+
+
+deBry, et al. Experimental [Page 38]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation and Job Template attributes supplied
+ by the client (in the request) that are not supported by the
+ Printer object or that conflict with one another (see the
+ Implementer's Guide [ipp-iig]). If the Printer object is not
+ returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Unsupported attributes fall into three categories:
+
+ 1. The Printer object does not support the supplied attribute
+ (no matter what the attribute syntax or value).
+ 2. The Printer object does support the attribute, but does not
+ support some or all of the particular attribute syntaxes or
+ values supplied by the client (i.e., the Printer object does
+ not have those attribute syntaxes or values in its
+ corresponding "xxx-supported" attribute).
+ 3. The Printer object does support the attributes and values
+ supplied, but the particular values are in conflict with one
+ another, because they violate a constraint, such as not being
+ able to staple transparencies.
+
+ In the case of an unsupported attribute name, the Printer object
+ returns the client-supplied attribute with a substituted "out-
+ of-band" value of 'unsupported' indicating no support for the
+ attribute itself (see the beginning of section 4.1).
+
+ In the case of a supported attribute with one or more
+ unsupported attribute syntaxes or values, the Printer object
+ simply returns the client-supplied attribute with the
+ unsupported attribute syntaxes or values as supplied by the
+ client. This indicates support for the attribute, but no
+ support for that particular attribute syntax or value. If the
+ client supplies a multi-valued attribute with more than one
+ value and the Printer object supports the attribute but only
+ supports a subset of the client-supplied attribute syntaxes or
+ values, the Printer object MUST return only those attribute
+ syntaxes or values that are unsupported.
+
+ In the case of two (or more) supported attribute values that are
+ in conflict with one another (although each is supported
+ independently, the values conflict when requested together
+
+
+
+deBry, et al. Experimental [Page 39]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ within the same job), the Printer object MUST return all the
+ values that it ignores or substitutes to resolve the conflict,
+ but not any of the values that it is still using. The choice
+ for exactly how to resolve the conflict is implementation
+ dependent. See The Implementer's Guide [ipp-iig] for an
+ example.
+
+ In these three cases, the value of the "ipp-attribute-fidelity"
+ supplied by the client does not affect what the Printer object
+ returns. The value of "ipp-attribute-fidelity" only affects
+ whether the Print-Job operation is accepted or rejected. If the
+ job is accepted, the client may query the job using the Get-
+ Job-Attributes operation requesting the unsupported attributes
+ that were returned in the create response to see which
+ attributes were ignored (not stored on the Job object) and which
+ attributes were stored with other (substituted) values.
+
+ Group 3: Job Object Attributes
+
+ "job-uri" (uri):
+ The Printer object MUST return the Job object's URI by returning
+ the contents of the REQUIRED "job-uri" Job object attribute.
+ The client uses the Job object's URI when directing operations
+ at the Job object. The Printer object always uses its
+ configured security policy when creating the new URI. However,
+ if the Printer object supports more than one URI, the Printer
+ object also uses information about which URI was used in the
+ Print-Job Request to generated the new URI so that the new URI
+ references the correct access channel. In other words, if the
+ Print-Job Request comes in over a secure channel, the Printer
+ object MUST generate a Job URI that uses the secure channel as
+ well.
+
+ "job-id" (integer(1:MAX)):
+ The Printer object MUST return the Job object's Job ID by
+ returning the REQUIRED "job-id" Job object attribute. The
+ client uses this "job-id" attribute in conjunction with the
+ "printer-uri" attribute used in the Print-Job Request when
+ directing Job operations at the Printer object.
+
+ "job-state":
+ The Printer object MUST return the Job object's REQUIRED "job-
+ state" attribute. The value of this attribute (along with the
+ value of the next attribute "job-state-reasons") is taken from a
+ "snapshot" of the new Job object at some meaningful point in
+ time (implementation defined) between when the Printer object
+ receives the Print-Job Request and when the Printer object
+ returns the response.
+
+
+
+deBry, et al. Experimental [Page 40]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "job-state-reasons":
+ The Printer object OPTIONALLY returns the Job object's OPTIONAL
+ "job-state-reasons" attribute. If the Printer object supports
+ this attribute then it MUST be returned in the response. If
+ this attribute is not returned in the response, the client can
+ assume that the "job-state-reasons" attribute is not supported
+ and will not be returned in a subsequent Job object query.
+
+ "job-state-message":
+ The Printer object OPTIONALLY returns the Job object's OPTIONAL
+ "job-state-message" attribute. If the Printer object supports
+ this attribute then it MUST be returned in the response. If
+ this attribute is not returned in the response, the client can
+ assume that the "job-state-message" attribute is not supported
+ and will not be returned in a subsequent Job object query.
+
+ "number-of-intervening-jobs":
+ The Printer object OPTIONALLY returns the Job object's OPTIONAL
+ "number-of-intervening-jobs" attribute. If the Printer object
+ supports this attribute then it MUST be returned in the
+ response. If this attribute is not returned in the response,
+ the client can assume that the "number-of-intervening-jobs"
+ attribute is not supported and will not be returned in a
+ subsequent Job object query.
+
+ Note: Since any printer state information which affects a job's
+ state is reflected in the "job-state" and "job-state-reasons"
+ attributes, it is sufficient to return only these attributes and
+ no specific printer status attributes.
+
+ Note: In addition to the MANDATORY parameters required for every
+ operation response, the simplest response consists of the just the
+ "attributes-charset" and "attributes-natural-language" operation
+ attributes and the "job-uri", "job-id", and "job-state" Job Object
+ Attributes. In this simplest case, the status code is "successful-
+ ok" and there is no "status-message" operation attribute.
+
+3.2.2 Print-URI Operation
+
+ This OPTIONAL operation is identical to the Print-Job operation
+ (section 3.2.1) except that a client supplies a URI reference to the
+ document data using the "document-uri" (uri) operation attribute (in
+ Group 1) rather than including the document data itself. Before
+ returning the response, the Printer MUST validate that the Printer
+ supports the retrieval method (e.g., http, ftp, etc.) implied by the
+ URI, and MUST check for valid URI syntax. If the client-supplied URI
+ scheme is not supported, i.e. the value is not in the Printer
+ object's "referenced-uri-scheme-supported" attribute, the Printer
+
+
+
+deBry, et al. Experimental [Page 41]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ object MUST reject the request and return the 'client-error-uri-
+ scheme-not-supported' status code. See The Implementer's Guide
+ [ipp-iig] for suggested additional checks. The Printer NEED NOT
+ follow the reference and validate the contents of the reference.
+
+ If the Printer object supports this operation, it MUST support the
+ "reference-uri-schemes-supported" Printer attribute (see section
+ 4.4.24).
+
+ It is up to the IPP object to interpret the URI and subsequently
+ "pull" the document from the source referenced by the URI string.
+
+3.2.3 Validate-Job Operation
+
+ This REQUIRED operation is similar to the Print-Job operation
+ (section 3.2.1) except that a client supplies no document data and
+ the Printer allocates no resources (i.e., it does not create a new
+ Job object). This operation is used only to verify capabilities of a
+ printer object against whatever attributes are supplied by the client
+ in the Validate-Job request. By using the Validate-Job operation a
+ client can validate that an identical Print-Job operation (with the
+ document data) would be accepted. The Validate-Job operation also
+ performs the same security negotiation as the Print-Job operation
+ (see section 8), so that a client can check that the client and
+ Printer object security requirements can be met before performing a
+ Print-Job operation.
+
+ Note: The Validate-Job operation does not accept a "document-uri"
+ attribute in order to allow a client to check that the same Print-URI
+ operation will be accepted, since the client doesn't send the data
+ with the Print-URI operation. The client SHOULD just issue the
+ Print-URI request.
+
+ The Printer object returns the same status codes, Operation
+ Attributes (Group 1) and Unsupported Attributes (Group 2) as the
+ Print-Job operation. However, no Job Object Attributes (Group 3) are
+ returned, since no Job object is created.
+
+3.2.4 Create-Job Operation
+
+ This OPTIONAL operation is similar to the Print-Job operation
+ (section 3.2.1) except that in the Create-Job request, a client does
+ not supply document data or any reference to document data. Also,
+ the client does not supply any of the "document-name", "document-
+ format", "compression", or "document-natural-language" operation
+ attributes. This operation is followed by one or more Send-Document
+ or Send-URI operations. In each of those operation requests, the
+
+
+
+
+deBry, et al. Experimental [Page 42]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ client OPTIONALLY supplies the "document-name", "document-format",
+ and "document-natural-language" attributes for each document in the
+ multi-document Job object.
+
+ If a Printer object supports the Create-Job operation, it MUST also
+ support the Send-Document operation and also MAY support the Send-URI
+ operation.
+
+ If the Printer object supports this operation, it MUST support the
+ "multiple-operation-time-out" Printer attribute (see section 4.4.28).
+
+
+3.2.5 Get-Printer-Attributes Operation
+
+ This REQUIRED operation allows a client to request the values of the
+ attributes of a Printer object. In the request, the client supplies
+ the set of Printer attribute names and/or attribute group names in
+ which the requester is interested. In the response, the Printer
+ object returns a corresponding attribute set with the appropriate
+ attribute values filled in.
+
+ For Printer objects, the possible names of attribute groups are:
+
+ - 'job-template': all of the Job Template attributes that apply to
+ a Printer object (the last two columns of the table in Section
+ 4.2).
+ - 'printer-description': the attributes specified in Section 4.4.
+ - 'all': the special group 'all' that includes all supported
+ attributes.
+
+ Since a client MAY request specific attributes or named groups, there
+ is a potential that there is some overlap. For example, if a client
+ requests, 'printer-name' and 'all', the client is actually requesting
+ the "printer-name" attribute twice: once by naming it explicitly, and
+ once by inclusion in the 'all' group. In such cases, the Printer
+ object NEED NOT return each attribute only once in the response even
+ if it is requested multiple times. The client SHOULD NOT request the
+ same attribute in multiple ways.
+
+ It is NOT REQUIRED that a Printer object support all attributes
+ belonging to a group (since some attributes are OPTIONAL). However,
+ it is REQUIRED that each Printer object support all group names.
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 43]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+3.2.5.1 Get-Printer-Attributes Request
+
+ The following sets of attributes are part of the Get-Printer-
+ Attributes Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ attributes-charset" and "attributes-natural-language" butes as
+ described in section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "requested-attributes" (1setOf keyword) :
+ The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is
+ interested. The Printer object MUST support this attribute. If
+ the client omits this attribute, the Printer MUST respond as if
+ this attribute had been supplied with a value of 'all'.
+
+ "document-format" (mimeMediaType) :
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. This attribute is useful
+ for a Printer object to determine the set of supported attribute
+ values that relate to the requested document format. The
+ Printer object MUST return the attributes and values that it
+ uses to validate a job on a create or Validate-Job operation in
+ which this document format is supplied. The Printer object
+ SHOULD return only (1) those attributes that are supported for
+ the specified format and (2) the attribute values that are
+ supported for the specified document format. By specifying the
+ document format, the client can get the Printer object to
+ eliminate the attributes and values that are not supported for a
+ specific document format. For example, a Printer object might
+ have multiple interpreters to support both '
+ application/postscript' (for PostScript) and 'text/plain' (for
+ text) documents. However, for only one of those interpreters
+ might the Printer object be able to support "number-up" with
+ values of '1', '2', and '4'. For the other interpreter it might
+ be able to only support "number-up" with a value of '1'. Thus a
+
+
+
+
+
+deBry, et al. Experimental [Page 44]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ client can use the Get-Printer-Attributes operation to obtain
+ the attributes and values that will be used to accept/reject a
+ create job operation.
+
+ If the Printer object does not distinguish between different
+ sets of supported values for each different document format when
+ validating jobs in the create and Validate-Job operations, it
+ MUST NOT distinguish between different document formats in the
+ Get-Printer-Attributes operation. If the Printer object does
+ distinguish between different sets of supported values for each
+ different document format specified by the client, this
+ specialization applies only to the following Printer object
+ attributes:
+
+ - Printer attributes that are Job Template attributes ("xxx-
+ default" "xxx-supported", and "xxx-ready" in the Table in
+ Section 4.2),
+ - "pdl-override-supported",
+ - "compression-supported",
+ - "job-k-octets-supported",
+ - "job-impressions-supported,
+ - "job-media-sheets-supported"
+ - "printer-driver-installer",
+ - "color-supported", and
+ - "reference-uri-schemes-supported"
+
+ The values of all other Printer object attributes (including
+ "document-format-supported") remain invariant with respect to
+ the client supplied document format (except for new Printer
+ description attribute as registered according to section 6.2).
+
+ If the client omits this "document-format" operation attribute,
+ the Printer object MUST respond as if the attribute had been
+ supplied with the value of the Printer object's "document-
+ format-default" attribute. It is recommended that the client
+ always supply a value for "document-format", since the Printer
+ object's "document-format-default" may be 'application/octet-
+ stream', in which case the returned attributes and values are
+ for the union of the document formats that the Printer can
+ automatically sense. For more details, see the description of
+ the 'mimeMediaType' attribute syntax in section 4.1.9.
+
+ If the client supplies a value for the "document-format"
+ Operation attribute that is not supported by the Printer, i.e.,
+ is not among the values of the Printer object's "document-
+ format-supported" attribute, the Printer object MUST reject the
+ operation and return the 'client-error-document-format-not-
+ supported' status code.
+
+
+
+deBry, et al. Experimental [Page 45]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+3.2.5.2 Get-Printer-Attributes Response
+
+ The Printer object returns the following sets of attributes as part
+ of the Get-Printer-Attributes Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in section 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation attributes supplied by the client (in
+ the request) that are not supported by the Printer object or
+ that conflict with one another (see sections 3.2.1.2 and 16).
+ The response NEED NOT contain the "requested-attributes"
+ operation attribute with any supplied values (attribute
+ keywords) that were requested by the client but are not
+ supported by the IPP object. If the Printer object is not
+ returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Group 3: Printer Object Attributes
+
+ This is the set of requested attributes and their current
+ values. The Printer object ignores (does not respond with) any
+ requested attribute which is not supported. The Printer object
+ MAY respond with a subset of the supported attributes and
+ values, depending on the security policy in force. However, the
+ Printer object MUST respond with the 'unknown' value for any
+ supported attribute (including all REQUIRED attributes) for
+ which the Printer object does not know the value. Also the
+ Printer object MUST respond with the 'no-value' for any
+ supported attribute (including all REQUIRED attributes) for
+ which the system administrator has not configured a value. See
+ the description of the "out-of-band" values in the beginning of
+ Section 4.1.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 46]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+3.2.6 Get-Jobs Operation
+
+ This REQUIRED operation allows a client to retrieve the list of Job
+ objects belonging to the target Printer object. The client may also
+ supply a list of Job attribute names and/or attribute group names. A
+ group of Job object attributes will be returned for each Job object
+ that is returned.
+
+ This operation is similar to the Get-Job-Attributes operation, except
+ that this Get-Jobs operation returns attributes from possibly more
+ than one object (see the description of Job attribute group names in
+ section 3.3.4).
+
+3.2.6.1 Get-Jobs Request
+
+ The client submits the Get-Jobs request to a Printer object.
+
+ The following groups of attributes are part of the Get-Jobs Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "limit" (integer(1:MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It is an integer value that
+ indicates a limit to the number of Job objects returned. The
+ limit is a "stateless limit" in that if the value supplied by
+ the client is 'N', then only the first 'N' jobs are returned in
+ the Get-Jobs Response. There is no mechanism to allow for the
+ next 'M' jobs after the first 'N' jobs. If the client does not
+ supply this attribute, the Printer object responds with all
+ applicable jobs.
+
+ "requested-attributes" (1setOf keyword):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It is a set of Job
+ attribute names and/or attribute groups names in whose values
+
+
+
+deBry, et al. Experimental [Page 47]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ the requester is interested. This set of attributes is returned
+ for each Job object that is returned. The allowed attribute
+ group names are the same as those defined in the Get-Job-
+ Attributes operation in section 3.3.4. If the client does not
+ supply this attribute, the Printer MUST respond as if the client
+ had supplied this attribute with two values: 'job-uri' and '
+ job-id'.
+
+ "which-jobs" (type2 keyword):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It indicates which Job
+ objects MUST be returned by the Printer object. The values for
+ this attribute are:
+
+ 'completed': This includes any Job object whose state is
+ 'completed', 'canceled', or 'aborted'.
+ 'not-completed': This includes any Job object whose state is '
+ pending', 'processing', 'processing-stopped', or 'pending-
+ held'.
+
+ A Printer object MUST support both values. However, if the
+ mentation does not keep jobs in the 'completed', 'canceled', '
+ aborted' states, then it returns no jobs when the 'completed'
+ value is supplied.
+
+ If a client supplies some other value, the Printer object MUST
+ copy the attribute and the unsupported value to the Unsupported
+ Attributes response group, reject the request, and return the '
+ client-error-attributes-or-values-not-supported' status code.
+
+ If the client does not supply this attribute, the Printer object
+ MUST respond as if the client had supplied the attribute with a
+ value of 'not-completed'.
+
+ "my-jobs" (boolean):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It indicates whether all
+ jobs or just the jobs submitted by the requesting user of this
+ request MUST be returned by the Printer object. If the client
+ does not supply this attribute, the Printer object MUST respond
+ as if the client had supplied the attribute with a value of '
+ false', i.e., all jobs. The means for authenticating the
+ requesting user and matching the jobs is described in section 8.
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 48]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+3.2.6.2 Get-Jobs Response
+
+ The Printer object returns all of the Job objects that match the
+ criteria as defined by the attribute values supplied by the client in
+ the request. It is possible that no Job objects are returned since
+ there may literally be no Job objects at the Printer, or there may be
+ no Job objects that match the criteria supplied by the client. If
+ the client requests any Job attributes at all, there is a set of Job
+ Object Attributes returned for each Job object.
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in sections 14 and
+ 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation attributes supplied by the client (in
+ the request) that are not supported by the Printer object or
+ that conflict with one another (see sections 3.2.1.2 and the
+ Implementer's Guide [ipp-iig]). The response NEED NOT contain
+ the "requested-attributes" operation attribute with any supplied
+ values (attribute keywords) that were requested by the client
+ but are not supported by the IPP object. If the Printer object
+ is not returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Groups 3 to N: Job Object Attributes
+
+ The Printer object responds with one set of Job Object
+ Attributes for each returned Job object. The Printer object
+ ignores (does not respond with) any requested attribute or value
+ which is not supported or which is restricted by the security
+ policy in force, including whether the requesting user is the
+ user that submitted the job (job originating user) or not (see
+ section 8). However, the Printer object MUST respond with the '
+ unknown' value for any supported attribute (including all
+ REQUIRED attributes) for which the Printer object does not know
+
+
+
+
+
+deBry, et al. Experimental [Page 49]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ the value, unless it would violate the security policy. See the
+ description of the "out-of-band" values in the beginning of
+ Section 4.1.
+
+ Jobs are returned in the following order:
+
+ - If the client requests all 'completed' Jobs (Jobs in the '
+ completed', 'aborted', or 'canceled' states), then the Jobs
+ are returned newest to oldest (with respect to actual
+ completion time)
+ - If the client requests all 'not-completed' Jobs (Jobs in the
+ 'pending', 'processing', 'pending-held', and 'processing-
+ stopped' states), then Jobs are returned in relative
+ chronological order of expected time to complete (based on
+ whatever scheduling algorithm is configured for the Printer
+ object).
+
+3.3 Job Operations
+
+ All Job operations are directed at Job objects. A client MUST always
+ supply some means of identifying the Job object in order to identify
+ the correct target of the operation. That job identification MAY
+ either be a single Job URI or a combination of a Printer URI with a
+ Job ID. The IPP object implementation MUST support both forms of
+ identification for every job.
+
+3.3.1 Send-Document Operation
+
+ This OPTIONAL operation allows a client to create a multi-document
+ Job object that is initially "empty" (contains no documents). In the
+ Create-Job response, the Printer object returns the Job object's URI
+ (the "job-uri" attribute) and the Job object's 32-bit identifier (the
+ "job-id" attribute). For each new document that the client desires
+ to add, the client uses a Send-Document operation. Each Send-
+ Document Request contains the entire stream of document data for one
+ document.
+
+ Since the Create-Job and the send operations (Send-Document or Send-
+ URI operations) that follow could occur over an arbitrarily long
+ period of time for a particular job, a client MUST send another send
+ operation within an IPP Printer defined minimum time interval after
+ the receipt of the previous request for the job. If a Printer object
+ supports multiple document jobs, the Printer object MUST support the
+ "multiple-operation-time-out" attribute (see section 4.4.28). This
+ attribute indicates the minimum number of seconds the Printer object
+ will wait for the next send operation before taking some recovery
+ action.
+
+
+
+
+deBry, et al. Experimental [Page 50]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ An IPP object MUST recover from an errant client that does not supply
+ a send operation, sometime after the minimum time interval specified
+ by the Printer object's "multiple-operation-time-out" attribute.
+ Such recovery MAY include any of the following or other recovery
+ actions:
+
+ 1. Assume that the Job is an invalid job, start the process of
+ changing the job state to 'aborted', add the 'aborted-by-system'
+ value to the job's "job-state-reasons" attribute (see section
+ 4.3.8), if supported, and clean up all resources associated with
+ the Job. In this case, if another send operation is finally
+ received, the Printer responds with an "client-error-not-
+ possible" or "client-error-not-found" depending on whether or
+ not the Job object is still around when the send operation
+ finally arrives.
+ 2. Assume that the last send operation received was in fact the
+ last document (as if the "last-document" flag had been set to '
+ true'), close the Job object, and proceed to process it (i.e.,
+ move the Job's state to 'pending').
+ 3. Assume that the last send operation received was in fact the
+ last document, close the Job, but move it to the 'pending-held'
+ and add the 'submission-interrupted' value to the job's "job-
+ state-reasons" attribute (see section 4.3.8), if supported.
+ This action allows the user or an operator to determine whether
+ to continue processing the Job by moving it back to the '
+ pending' state or to cancel the job.
+
+ Each implementation is free to decide the "best" action to take
+ depending on local policy, whether any documents have been added,
+ whether the implementation spools jobs or not, and/or any other piece
+ of information available to it. If the choice is to abort the Job
+ object, it is possible that the Job object may already have been
+ processed to the point that some media sheet pages have been printed.
+
+3.3.1.1 Send-Document Request
+
+ The following attribute sets are part of the Send-Document Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 51]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX))or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ "requesting-user-name" (name(MAX)) attribute SHOULD be supplied
+ by the client as described in section 8.3.
+
+ "document-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied document name. The document name MAY be different than
+ the Job name. It might be helpful, but NEED NOT be unique
+ across multiple documents in the same Job. Typically, the
+ client software automatically supplies the document name on
+ behalf of the end user by using a file name or an application
+ generated name. See the description of the "document-name"
+ operation attribute in the Print-Job Request (section 3.2.1.1)
+ for more information about this attribute
+
+ "document-format" (mimeMediaType):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. The value of this attribute
+ identifies the format of the supplied document data. If the
+ client does not supply this attribute, the Printer object
+ assumes that the document data is in the format defined by the
+ Printer object's "document-format-default" attribute. If the
+ client supplies this attribute, but the value is not supported
+ by the Printer object, i.e., the value is not one of the values
+ of the Printer object's "document-format-supported" attribute,
+ the Printer object MUST reject the request and return the '
+ client-error-document-format-not-supported' status code.
+
+ "document-natural-language" (naturalLanguage):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. This attribute
+ specifies the natural language of the document for those
+ document-formats that require a specification of the natural
+ language in order to image the document unambiguously. There
+ are no particular values required for the Printer object to
+ support.
+
+ "compression" (type3 keyword)
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "compression-
+ supported" attribute (see section 4.4.29). The client supplied
+
+
+
+deBry, et al. Experimental [Page 52]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "compression" operation attribute identifies the compression
+ algorithm used on the document data. If the client omits this
+ attribute, the Printer object MUST assume that the data is not
+ compressed. If the client supplies the attribute and the
+ Printer object supports the attribute, the Printer object MUST
+ use the corresponding decompression algorithm on the document
+ data. If the client supplies this attribute, but the value is
+ not supported by the Printer object, i.e., the value is not one
+ of the values of the Printer object's "compression-supported"
+ attribute, the Printer object MUST copy the attribute and its
+ value to the Unsupported Attributes response group, reject the
+ request, and return the 'client-error-attributes-or-values-not-
+ supported' status code.
+
+ "last-document" (boolean):
+ The client MUST supply this attribute. The Printer object MUST
+ support this attribute. It is a boolean flag that is set to '
+ true' if this is the last document for the Job, 'false'
+ otherwise.
+
+ Group 2: Document Content
+
+ The client MUST supply the document data if the "last-document"
+ flag is set to 'false'. However, since a client might not know
+ that the previous document sent with a Send-Document (or Send-
+ URI) operation was the last document (i.e., the "last-document"
+ attribute was set to 'false'), it is legal to send a Send-
+ Document request with no document data where the "last-document"
+ flag is set to 'true'. Such a request MUST NOT increment the
+ value of the Job object's "number-of-documents" attribute, since
+ no real document was added to the job.
+
+3.3.1.2 Send-Document Response
+
+ The following sets of attributes are part of the Send-Document
+ Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in sections 14 and
+ 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+
+
+deBry, et al. Experimental [Page 53]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation attributes supplied by the client (in
+ the request) that are not supported by the Printer object or
+ that conflict with one another (see sections 3.2.1.2 and the
+ Implementer's Guide [ipp-iig]). If the Printer object is not
+ returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Group 3: Job Object Attributes
+
+ This is the same set of attributes as described in the Print-Job
+ response (see section 3.2.1.2).
+
+3.3.2 Send-URI Operation
+
+ This OPTIONAL operation is identical to the Send-Document operation
+ (see section 3.3.1) except that a client MUST supply a URI reference
+ ("document-uri" operation attribute) rather than the document data
+ itself. If a Printer object supports this operation, clients can use
+ both Send-URI or Send-Document operations to add new documents to an
+ existing multi-document Job object. However, if a client needs to
+ indicate that the previous Send-URI or Send-Document was the last
+ document, the client MUST use the Send-Document operation with no
+ document data and the "last-document" flag set to 'true' (rather than
+ using a Send-URI operation with no "document-uri" operation
+ attribute).
+
+ If a Printer object supports this operation, it MUST also support the
+ Print-URI operation (see section 3.2.2).
+
+ The Printer object MUST validate the syntax and URI scheme of the
+ supplied URI before returning a response, just as in the Print-URI
+ operation.
+
+3.3.3 Cancel-Job Operation
+
+ This REQUIRED operation allows a client to cancel a Print Job from
+ the time the job is created up to the time it is completed, canceled,
+ or aborted. Since a Job might already be printing by the time a
+ Cancel-Job is received, some media sheet pages might be printed
+ before the job is actually terminated.
+
+3.3.3.1 Cancel-Job Request
+
+ The following groups of attributes are part of the Cancel-Job
+ Request:
+
+
+
+deBry, et al. Experimental [Page 54]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX))or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "message" (text(127)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. It is a message to
+ the operator. This "message" attribute is not the same as the
+ "job-message-from-operator" attribute. That attribute is used
+ to report a message from the operator to the end user that
+ queries that attribute. This "message" operation attribute is
+ used to send a message from the client to the operator along
+ with the operation request. It is an implementation decision of
+ how or where to display this message to the operator (if at
+ all).
+
+3.3.3.2 Cancel-Job Response
+
+ The following sets of attributes are part of the Cancel-Job Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in sections 14 and
+ 3.1.6.
+
+ If the job is already in the 'completed', 'aborted', or '
+ canceled' state, or the 'process-to-stop-point' value is set in
+ the Job's "job-state-reasons" attribute, the Printer object MUST
+ reject the request and return the 'client-error-not-possible'
+ error status code.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 55]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation attributes supplied by the client (in
+ the request) that are not supported by the Printer object or
+ that conflict with one another (see section 3.2.1.2 and the
+ Implementer's Guide [ipp-iig]). If the Printer object is not
+ returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Once a successful response has been sent, the implementation
+ guarantees that the Job will eventually end up in the 'canceled'
+ state. Between the time of the Cancel-Job operation is accepted and
+ when the job enters the 'canceled' job-state (see section 4.3.7), the
+ "job-state-reasons" attribute SHOULD contain the 'processing-to-
+ stop-point' value which indicates to later queries that although the
+ Job might still be 'processing', it will eventually end up in the '
+ canceled' state, not the 'completed' state.
+
+3.3.4 Get-Job-Attributes Operation
+
+ This REQUIRED operation allows a client to request the values of
+ attributes of a Job object and it is almost identical to the Get-
+ Printer-Attributes operation (see section 3.2.5). The only
+ differences are that the operation is directed at a Job object rather
+ than a Printer object, there is no "document-format" operation
+ attribute used when querying a Job object, and the returned attribute
+ group is a set of Job object attributes rather than a set of Printer
+ object attributes.
+
+ For Jobs, the possible names of attribute groups are:
+
+ - 'job-template': all of the Job Template attributes that apply to a
+ Job object (the first column of the table in Section 4.2).
+ - 'job-description': all of the Job Description attributes specified
+ in Section 4.3.
+ - 'all': the special group 'all' that includes all supported
+ attributes.
+
+ Since a client MAY request specific attributes or named groups, there
+ is a potential that there is some overlap. For example, if a client
+ requests, 'job-name' and 'job-description', the client is actually
+ requesting the "job-name" attribute once by naming it explicitly, and
+ once by inclusion in the 'job-description' group. In such cases, the
+
+
+
+deBry, et al. Experimental [Page 56]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Printer object NEED NOT return the attribute only once in the
+ response even if it is requested multiple times. The client SHOULD
+ NOT request the same attribute in multiple ways.
+
+ It is NOT REQUIRED that a Job object support all attributes belonging
+ to a group (since some attributes are OPTIONAL). However it is
+ REQUIRED that each Job object support all group names.
+
+3.3.4.1 Get-Job-Attributes Request
+
+ The following groups of attributes are part of the Get-Job-Attributes
+ Request when the request is directed at a Job object:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX)) or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "requested-attributes" (1setOf keyword) :
+ The client OPTIONALLY supplies this attribute. The IPP object
+ MUST support this attribute. It is a set of attribute names
+ and/or attribute group names in whose values the requester is
+ interested. If the client omits this attribute, the IPP object
+ MUST respond as if this attribute had been supplied with a value
+ of 'all'.
+
+3.3.4.2 Get-Job-Attributes Response
+
+ The Printer object returns the following sets of attributes as part
+ of the Get-Job-Attributes Response:
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 57]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text) operation attribute as described in sections 14 and
+ 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2. The "attributes-
+ natural-language" MAY be the natural language of the Job object,
+ rather than the one requested.
+
+ Group 2: Unsupported Attributes
+
+ This is a set of Operation attributes supplied by the client (in
+ the request) that are not supported by the Printer object or
+ that conflict with one another (see sections 3.2.1.2 and the
+ Implementer's Guide [ipp-iig]). The response NEED NOT contain
+ the "requested-attributes" operation attribute with any supplied
+ values (attribute keywords) that were requested by the client
+ but are not supported by the IPP object. If the Printer object
+ is not returning any Unsupported Attributes in the response, the
+ Printer object SHOULD omit Group 2 rather than sending an empty
+ group. However, a client MUST be able to accept an empty group.
+
+ Group 3: Job Object Attributes
+
+ This is the set of requested attributes and their current
+ values. The IPP object ignores (does not respond with) any
+ requested attribute or value which is not supported or which is
+ restricted by the security policy in force, including whether
+ the requesting user is the user that submitted the job (job
+ originating user) or not (see section 8). However, the IPP
+ object MUST respond with the 'unknown' value for any supported
+ attribute (including all RED butes) for which the IPP object
+ does not know the value, s it would violate the security policy.
+ See the description e "out-of-band" values in the beginning of
+ Section 4.1.
+
+4. Object Attributes
+
+ This section describes the attributes with their corresponding
+ attribute syntaxes and values that are part of the IPP model. The
+ sections below show the objects and their associated attributes which
+ are included within the scope of this protocol. Many of these
+ attributes are derived from other relevant specifications:
+
+
+
+deBry, et al. Experimental [Page 58]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ - Document Printing Application (DPA) [ISO10175]
+ - RFC 1759 Printer MIB [RFC1759]
+
+ Each attribute is uniquely identified in this document using a
+ "keyword" (see section 12.2.1) which is the name of the attribute.
+ The keyword is included in the section header describing that
+ attribute.
+
+ Note: Not only are keywords used to identify attributes, but one of
+ the attribute syntaxes described below is "keyword" so that some
+ attributes have keyword values. Therefore, these attributes are
+ defined as having an attribute syntax that is a set of keywords.
+
+4.1 Attribute Syntaxes
+
+ This section defines the basic attribute syntax types that all clients
+ and IPP objects MUST be able to accept in responses and accept in
+ requests, respectively. Each attribute description in sections 3 and
+ 4 includes the name of attribute syntax(es) in the heading (in
+ parentheses). A conforming implementation of an attribute MUST
+ include the semantics of the attribute syntax(es) so identified.
+ Section 6.3 describes how the protocol can be extended with new
+ attribute syntaxes.
+
+ The attribute syntaxes are specified in the following sub-sections,
+ where the sub-section heading is the keyword name of the attribute
+ syntax inside the single quotes. In operation requests and responses
+ each attribute value MUST be represented as one of the attribute
+ syntaxes specified in the sub-section heading for the attribute. In
+ addition, the value of an attribute in a response (but not in a
+ request) MAY be one of the "out-of-band" values. Standard
+ "out-of-band" values are:
+
+ 'unknown': The attribute is supported by the IPP object, but the
+ value is unknown to the IPP object for some reason.
+ 'unsupported': The attribute is unsupported by the IPP object. This
+ value MUST be returned only as the value of an attribute in the
+ Unsupported Attributes Group.
+ 'no-value': The attribute is supported by the Printer object, but
+ the system administrator has not yet configured a value.
+
+ The Encoding and Transport specification [RFC2565] defines mechanisms
+ for passing "out-of-band" values. All attributes in a request MUST
+ have one or more values as defined in Sections 4.2 to 4.4. Thus
+ clients MUST NOT supply attributes with "out-of-band" values. All
+ attribute in a response MUST have one or more values as defined in
+ Sections 4.2 to 4.4 or a single "out-of-band" value.
+
+
+
+
+deBry, et al. Experimental [Page 59]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Most attributes are defined to have a single attribute syntax.
+ However, a few attributes (e.g., "job-sheet", "media", "job-hold-
+ until") are defined to have several attribute syntaxes, depending on
+ the value. These multiple attribute syntaxes are separated by the
+ "|" character in the sub-section heading to indicate the choice.
+ Since each value MUST be tagged as to its attribute syntax in the
+
+ protocol, a single-valued attribute instance may have any one of its
+ attribute syntaxes and a multi-valued attribute instance may have a
+ mixture of its defined attribute syntaxes.
+
+4.1.1 'text'
+
+ A text attribute is an attribute whose value is a sequence of zero or
+ more characters encoded in a maximum of 1023 ('MAX') octets. MAX is
+ the maximum length for each value of any text attribute. However, if
+ an attribute will always contain values whose maximum length is much
+ less than MAX, the definition of that attribute will include a
+ qualifier that defines the maximum length for values of that
+ attribute. For example: the "printer-location" attribute is
+ specified as "printer-location (text(127))". In this case, text
+ values for "printer-location" MUST NOT exceed 127 octets; if supplied
+ with a longer text string via some external interface (other than the
+ protocol), implementations are free to truncate to this shorter
+ length limitation.
+
+ In this specification, all text attributes are defined using the '
+ text' syntax. However, 'text' is used only for brevity; the formal
+ interpretation of 'text' is: 'textWithoutLanguage |
+ textWithLanguage'. That is, for any attribute defined in this
+ specification using the 'text' attribute syntax, all IPP objects and
+ clients MUST support both the 'textWithoutLanguage' and '
+ textWithLanguage' attribute syntaxes. However, in actual usage and
+ protocol execution, objects and clients accept and return only one of
+ the two syntax per attribute. The syntax 'text' never appears "on-
+ the-wire".
+
+ Both 'textWithoutLanguage' and 'textWithLanguage' are needed to
+ support the real world needs of interoperability between sites and
+ systems that use different natural languages as the basis for human
+ communication. Generally, one natural language applies to all text
+ attributes in a given request or response. The language is indicated
+ by the "attributes-natural-language" operation attribute defined in
+ section 3.1.4 or "attributes-natural-language" job attribute defined
+ in section 4.3.24, and there is no need to identify the natural
+ language for each text string on a value-by-value basis. In these
+ cases, the attribute syntax 'textWithoutLanguage' is used for text
+ attributes. In other cases, the client needs to supply or the
+
+
+
+deBry, et al. Experimental [Page 60]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Printer object needs to return a text value in a natural language
+ that is different from the rest of the text values in the request or
+ response. In these cases, the client or Printer object uses the
+ attribute syntax 'textWithLanguage' for text attributes (this is the
+ Natural Language Override mechanism described in section 3.1.4).
+
+ The 'textWithoutLanguage' and 'textWithLanguage' attribute syntaxes
+ are described in more detail in the following sections.
+
+4.1.1.1 'textWithoutLanguage'
+
+ The 'textWithoutLanguage' syntax indicates a value that is sequence
+ of zero or more characters. Text strings are encoded using the rules
+ of some charset. The Printer object MUST support the UTF-8 charset
+ [RFC2279] and MAY support additional charsets to represent 'text'
+ values, provided that the charsets are registered with IANA [IANA-
+ CS]. See Section 4.1.7 for the specification of the 'charset'
+ attribute syntax, including restricted semantics and examples of
+ charsets.
+
+4.1.1.2 'textWithLanguage'
+
+ The 'textWithLanguage' attribute syntax is a compound attribute
+ syntax consisting of two parts: a 'textWithoutLanguage' part plus an
+ additional 'naturalLanguage' (see section 4.1.8) part that overrides
+ the natural language in force. The 'naturalLanguage' part explicitly
+ identifies the natural language that applies to the text part of that
+ value and that value alone. For any give text attribute, the '
+ textWithoutLanguage' part is limited to the maximum length defined
+ for that attribute, but the 'naturalLanguage' part is always limited
+ to 63 octets. Using the 'textWithLanguage' attribute syntax rather
+ than the normal 'textWithoutLanguage' syntax is the so-called Natural
+ Language Override mechanism and MUST be supported by all IPP objects
+ and clients.
+
+ If the attribute is multi-valued (1setOf text), then the '
+ textWithLanguage' attribute syntax MUST be used to explicitly specify
+ each attribute value whose natural language needs to be overridden.
+ Other values in a multi-valued 'text' attribute in a request or a
+ response revert to the natural language of the operation attribute.
+
+ In a create request, the Printer object MUST accept and store with
+ the Job object any natural language in the "attributes-natural-
+ language" operation attribute, whether the Printer object supports
+ that natural language or not. Furthermore, the Printer object MUST
+ accept and store any 'textWithLanguage' attribute value, whether the
+
+
+
+
+
+deBry, et al. Experimental [Page 61]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Printer object supports that natural language or not. These
+ requirements are independent of the value of the "ipp-attribute-
+ fidelity" operation attribute that the client MAY supply.
+
+ Example: If the client supplies the "attributes-natural-language"
+ operation attribute with the value: 'en' indicating English, but the
+ value of the "job-name" attribute is in French, the client MUST use
+ the 'textWithLanguage' attribute syntax with the following two
+ values:
+
+ 'fr': Natural Language Override indicating French
+ 'Rapport Mensuel': the job name in French
+
+ See the Encoding and Transport document [RFC2565] for a detailed
+ example of the 'textWithLanguage' attribute syntax.
+
+4.1.2 'name'
+
+ This syntax type is used for user-friendly strings, such as a Printer
+ name, that, for humans, are more meaningful than identifiers. Names
+ are never translated from one natural language to another. The '
+ name' attribute syntax is essentially the same as 'text', including
+ the REQUIRED support of UTF-8 except that the sequence of characters
+ is limited so that its encoded form MUST NOT exceed 255 (MAX) octets.
+
+ Also like 'text', 'name' is really an abbreviated notation for either
+ 'nameWithoutLanguage' or 'nameWithLanguage'. That is, all IPP
+ objects and clients MUST support both the 'nameWithoutLanguage' and '
+ nameWithLanguage' attribute syntaxes. However, in actual usage and
+ protocol execution, objects and clients accept and return only one of
+ the two syntax per attribute. The syntax 'name' never appears "on-
+ the-wire".
+
+ Note: Only the 'text' and 'name' attribute syntaxes permit the
+ Natural Language Override mechanism.
+
+ Some attributes are defined as 'type3 keyword | name'. These
+ attributes support values that are either type3 keywords or names.
+ This dual-syntax mechanism enables a site administrator to extend
+ these attributes to legally include values that are locally defined
+ by the site administrator. Such names are not registered with IANA.
+
+4.1.2.1 'nameWithoutLanguage'
+
+ The 'nameWithoutLanguage' syntax indicates a value that is sequence
+ of zero or more characters so that its encoded form does not exceed
+ MAX octets.
+
+
+
+
+deBry, et al. Experimental [Page 62]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.1.2.2 'nameWithLanguage'
+
+ The 'nameWithLanguage' attribute syntax is a compound attribute
+ syntax consisting of two parts: a 'nameWithoutLanguage' part plus an
+ additional 'naturalLanguage' (see section 4.1.8) part that overrides
+ the natural language in force. The 'naturalLanguage' part explicitly
+ identifies the natural language that applies to that name value and
+ that name value alone.
+
+ The 'nameWithLanguage' attribute syntax behaves the same as the '
+ textWithLanguage' syntax. If a name is in a language that is
+ different than the rest of the object or operation, then this '
+ nameWithLanguage' syntax is used rather than the generic '
+ nameWithoutLanguage' syntax.
+
+ Example: If the client supplies the "attributes-natural-language"
+ operation attribute with the value: 'en' indicating English, but the
+ "printer-name" attribute is in German, the client MUST use the '
+ nameWithLanguage' attribute syntax as follows:
+
+ 'de': Natural Language Override indicating German
+ 'Farbdrucker': the Printer name in German
+
+4.1.2.3 Matching 'name' attribute values
+
+ For purposes of matching two 'name' attribute values for equality,
+ such as in job validation (where a client-supplied value for
+ attribute "xxx" is checked to see if the value is among the values of
+ the Printer object's corresponding "xxx-supported" attribute), the
+ following match rules apply:
+
+ 1. 'keyword' values never match 'name' values.
+
+ 2. 'name' (nameWithoutLanguage and nameWithLanguage) values
+ match if (1) the name parts match and (2) the Associated
+ Natural-Language parts (see section 3.1.4.1) match. The
+ matching rules are:
+
+ a. the name parts match if the two names are identical
+ character by character, except it is RECOMMENDED that case
+ be ignored. For example: 'Ajax-letter-head-white' MUST
+ match 'Ajax-letter-head-white' and SHOULD match 'ajax-
+ letter-head-white' and 'AJAX-LETTER-HEAD-WHITE'.
+
+ b. the Associated Natural-Language parts match if the
+ shorter of the two meets the syntactic requirements of RFC
+ 1766 [RFC1766] and matches byte for byte with the longer.
+ For example, 'en' matches 'en', 'en-us' and 'en-gb', but
+
+
+
+deBry, et al. Experimental [Page 63]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ matches neither 'fr' nor 'e'.
+
+4.1.3 'keyword'
+
+ The 'keyword' attribute syntax is a sequence of characters, length: 1
+ to 255, containing only the US-ASCII [ASCII] encoded values for
+ lowercase letters ("a" - "z"), digits ("0" - "9"), hyphen ("-"), dot
+ ("."), and underscore ("_"). The first character MUST be a lowercase
+ letter. Furthermore, keywords MUST be in U.S. English.
+
+ This syntax type is used for enumerating semantic identifiers of
+ entities in the abstract protocol, i.e., entities identified in this
+ document. Keywords are used as attribute names or values of
+ attributes. Unlike 'text' and 'name' attribute values, 'keyword'
+ values MUST NOT use the Natural Language Override mechanism, since
+ they MUST always be US-ASCII and U.S. English.
+
+ Keywords are for use in the protocol. A user interface will likely
+ provide a mapping between protocol keywords and displayable user-
+ friendly words and phrases which are localized to the natural
+ language of the user. While the keywords specified in this document
+ MAY be displayed to users whose natural language is U.S. English,
+ they MAY be mapped to other U.S. English words for U.S. English
+ users, since the user interface is outside the scope of this
+ document.
+
+ In the definition for each attribute of this syntax type, the full
+ set of defined keyword values for that attribute are listed.
+
+ When a keyword is used to represent an attribute (its name), it MUST
+ be unique within the full scope of all IPP objects and attributes.
+ When a keyword is used to represent a value of an attribute, it MUST
+ be unique just within the scope of that attribute. That is, the same
+ keyword MUST NOT be used for two different values within the same
+ attribute to mean two different semantic ideas. However, the same
+ keyword MAY be used across two or more attributes, representing
+ different semantic ideas for each attribute. Section 6.1 describes
+ how the protocol can be extended with new keyword values. Examples
+ of attribute name keywords:
+
+ "job-name"
+ "attributes-charset"
+
+ Note: This document uses "type1", "type2", and "type3" prefixes to
+ the "keyword" basic syntax to indicate different levels of review for
+ extensions (see section 6.1).
+
+
+
+
+
+deBry, et al. Experimental [Page 64]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.1.4 'enum'
+
+ The 'enum' attribute syntax is an enumerated integer value that is in
+ the range from 1 to 2**31 - 1 (MAX). Each value has an associated '
+ keyword' name. In the definition for each attribute of this syntax
+ type, the full set of possible values for that attribute are listed.
+ This syntax type is used for attributes for which there are enum
+ values assigned by other standards, such as SNMP MIBs. A number of
+ attribute enum values in this specification are also used for
+ corresponding attributes in other standards [RFC1759]. This syntax
+ type is not used for attributes to which the system administrator may
+ assign values. Section 6.1 describes how the protocol can be
+ extended with new enum values.
+
+ Enum values are for use in the protocol. A user interface will
+ provide a mapping between protocol enum values and displayable user-
+ friendly words and phrases which are localized to the natural
+ language of the user. While the enum symbols specified in this
+ document MAY be displayed to users whose natural language is U.S.
+ English, they MAY be mapped to other U.S. English words for U.S.
+ English users, since the user interface is outside the scope of this
+ document.
+
+ Note: SNMP MIBs use '2' for 'unknown' which corresponds to the IPP
+ "out-of-band" value 'unknown'. See the description of the "out-of-
+ band" values at the beginning of Section 4.1. Therefore, attributes
+ of type 'enum' start at '3'.
+
+ Note: This document uses "type1", "type2", and "type3" prefixes to
+ the "enum" basic syntax to indicate different levels of review for
+ extensions (see section 6.1).
+
+4.1.5 'uri'
+
+ The 'uri' attribute syntax is any valid Uniform Resource Identifier
+ or URI [RFC2396]. Most often, URIs are simply Uniform Resource
+ Locators or URLs. The maximum length of URIs used as values of IPP
+ attributes is 1023 octets. Although most other IPP attribute syntax
+ types allow for only lower-cased values, this attribute syntax type
+ conforms to the case-sensitive and case-insensitive rules specified
+ in [RFC2396].
+
+4.1.6 'uriScheme'
+
+ The 'uriScheme' attribute syntax is a sequence of characters
+ representing a URI scheme according to RFC 2396 [RFC2396]. Though
+ RFC 2396 requires that the values be case-insensitive, IPP requires
+
+
+
+
+deBry, et al. Experimental [Page 65]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ all lower case values in IPP attributes to simplify comparing by IPP
+ clients and Printer objects. Standard values for this syntax type
+ are the following keywords:
+
+ 'http': for HTTP schemed URIs (e.g., "http:...")
+ 'https': for use with HTTPS schemed URIs (e.g., "https:...")
+ (not on IETF standards track)
+ 'ftp': for FTP schemed URIs (e.g., "ftp:...")
+ 'mailto': for SMTP schemed URIs (e.g., "mailto:...")
+ 'file': for file schemed URIs (e.g., "file:...")
+
+ A Printer object MAY support any URI 'scheme' that has been
+ registered with IANA [IANA-MT]. The maximum length of URI 'scheme'
+ values used to represent IPP attribute values is 63 octets.
+
+4.1.7 'charset'
+
+ The 'charset' attribute syntax is a standard identifier for a
+ charset. A charset is a coded character set and encoding scheme.
+ Charsets are used for labeling certain document contents and 'text'
+ and 'name' attribute values. The syntax and semantics of this
+ attribute syntax are specified in RFC 2046 [RFC2046] and contained in
+ the IANA character-set Registry [IANA-CS] according to the IANA
+ procedures [RFC2278]. Though RFC 2046 requires that the values be
+ case-insensitive US-ASCII, IPP requires all lower case values in IPP
+ attributes to simplify comparing by IPP clients and Printer objects.
+ When a character-set in the IANA registry has more than one name
+ (alias), the name labeled as "(preferred MIME name)", if present,
+ MUST be used.
+
+ The maximum length of 'charset' values used to represent IPP
+ attribute values is 63 octets.
+
+ Some examples are:
+
+ 'utf-8': ISO 10646 Universal Multiple-Octet Coded Character Set
+ (UCS) represented as the UTF-8 [RFC2279] transfer encoding
+ scheme in which US-ASCII is a subset charset.
+ 'us-ascii': 7-bit American Standard Code for Information
+ Interchange (ASCII), ANSI X3.4-1986 [ASCII]. That standard
+ defines US-ASCII, but RFC 2045 [RFC2045] eliminates most of the
+ control characters from conformant usage in MIME and IPP.
+ 'iso-8859-1': 8-bit One-Byte Coded Character Set, Latin Alphabet
+ Nr 1 [ISO8859-1]. That standard defines a coded character set
+ that is used by Latin languages in the Western Hemisphere and
+ Western Europe. US-ASCII is a subset charset.
+
+
+
+
+
+deBry, et al. Experimental [Page 66]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'iso-10646-ucs-2': ISO 10646 Universal Multiple-Octet Coded
+ Character Set (UCS) represented as two octets (UCS-2), with the
+ high order octet of each pair coming first (so-called Big Endian
+ integer).
+
+ Some attribute descriptions MAY place additional requirements on
+ charset values that may be used, such as REQUIRED values that MUST be
+ supported or additional restrictions, such as requiring that the
+ charset have US-ASCII as a subset charset.
+
+4.1.8 'naturalLanguage'
+
+ The 'naturalLanguage' attribute syntax is a standard identifier for a
+ natural language and optionally a country. The values for this
+ syntax type are defined by RFC 1766 [RFC1766]. Though RFC 1766
+ requires that the values be case-insensitive US-ASCII, IPP requires
+ all lower case to simplify comparing by IPP clients and Printer
+ objects. Examples include:
+
+ 'en': for English
+ 'en-us': for US English
+ 'fr': for French
+ 'de': for German
+
+ The maximum length of 'naturalLanguage' values used to represent IPP
+ attribute values is 63 octets.
+
+4.1.9 'mimeMediaType'
+
+ The 'mimeMediaType' attribute syntax is the Internet Media Type
+ (sometimes called MIME type) as defined by RFC 2046 [RFC2046] and
+ registered according to the procedures of RFC 2048 [RFC2048] for
+ identifying a document format. The value MAY include a charset
+ parameter, depending on the specification of the Media Type in the
+ IANA Registry [IANA-MT]. Although most other IPP syntax types allow
+ for only lower-cased values, this syntax type allows for mixed-case
+ values which are case-insensitive.
+
+ Examples are:
+
+ 'text/html': An HTML document
+ 'text/plain': A plain text document in US-ASCII (RFC 2046 indicates
+ that in the absence of the charset parameter MUST mean US-ASCII
+ rather than simply unspecified) [RFC2046].
+ 'text/plain; charset=US-ASCII': A plain text document in US-ASCII
+ [52, 56].
+ 'text/plain; charset=ISO-8859-1': A plain text document in ISO
+ 8859-1 (Latin 1) [ISO8859-1].
+
+
+
+deBry, et al. Experimental [Page 67]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'text/plain; charset=utf-8': A plain text document in ISO 10646
+ represented as UTF-8 [RFC2279]
+ 'text/plain, charset=iso-10646-ucs-2': A plain text document in
+ ISO 10646 represented in two octets (UCS-2) [ISO10646-1]
+ 'application/postscript': A PostScript document [RFC2046]
+ 'application/vnd.hp-PCL': A PCL document [IANA-MT] (charset escape
+ sequence embedded in the document data)
+ 'application/octet-stream': Auto-sense - see below
+
+ One special type is 'application/octet-stream'. If the Printer
+ object supports this value, the Printer object MUST be capable of
+ auto-sensing the format of the document data. If the Printer
+ object's default value attribute "document-format-default" is set to
+ 'application/octet-stream', the Printer object not only supports
+ auto-sensing of the document format, but will depend on the result of
+ applying its auto-sensing when the client does not supply the
+ "document-format" attribute. If the client supplies a document
+ format value, the Printer MUST rely on the supplied attribute, rather
+ than trust its auto-sensing algorithm. To summarize:
+
+ 1. If the client does not supply a document format value, the
+ Printer MUST rely on its default value setting (which may be '
+ application/octet-stream' indicating an auto-sensing mechanism).
+ 2. If the client supplies a value other than 'application/octet-
+ stream', the client is supplying valid information about the
+ format of the document data and the Printer object MUST trust
+ the client supplied value more than the outcome of applying an
+ automatic format detection mechanism. For example, the client
+ may be requesting the printing of a PostScript file as a '
+ text/plain' document. The Printer object MUST print a text
+ representation of the PostScript commands rather than interpret
+ the stream of PostScript commands and print the result.
+ 3. If the client supplies a value of 'application/octet-stream',
+ the client is indicating that the Printer object MUST use its
+ auto-sensing mechanism on the client supplied document data
+ whether auto-sensing is the Printer object's default or not.
+
+ Note: Since the auto-sensing algorithm is probabilistic, if the
+ client requests both auto-sensing ("document-format" set to '
+ application/octet-stream') and true fidelity ("ipp-attribute-
+ fidelity" set to 'true'), the Printer object might not be able to
+ guarantee exactly what the end user intended (the auto-sensing
+ algorithm might mistake one document format for another ), but it is
+ able to guarantee that its auto-sensing mechanism be used.
+
+ The maximum length of a 'mimeMediaType' value to represent IPP
+ attribute values is 255 octets.
+
+
+
+
+deBry, et al. Experimental [Page 68]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.1.10 'octetString'
+
+ The 'octetString' attribute syntax is a sequence of octets encoded in
+ a maximum of 1023 octets which is indicated in sub-section headers
+ using the notation: octetString(MAX). This syntax type is used for
+ opaque data.
+
+4.1.11 'boolean'
+
+ The 'boolean' attribute syntax has only two values: 'true' and '
+ false'.
+
+4.1.12 'integer'
+
+ The 'integer' attribute syntax is an integer value that is in the
+ range from -2**31 (MIN) to 2**31 - 1 (MAX). Each individual
+ attribute may specify the range constraint explicitly in sub-section
+ headers if the range is different from the full range of possible
+ integer values. For example: job-priority (integer(1:100)) for the
+ "job-priority" attribute. However, the enforcement of that
+ additional constraint is up to the IPP objects, not the protocol.
+
+4.1.13 'rangeOfInteger'
+
+ The 'rangeOfInteger' attribute syntax is an ordered pair of integers
+ that defines an inclusive range of integer values. The first integer
+ specifies the lower bound and the second specifies the upper bound.
+ If a range constraint is specified in the header description for an
+ attribute in this document whose attribute syntax is 'rangeOfInteger'
+ (i.e., 'X:Y' indicating X as a minimum value and Y as a maximum
+ value), then the constraint applies to both integers.
+
+4.1.14 'dateTime'
+
+ The 'dateTime' attribute syntax is a standard, fixed length, 11 octet
+ representation of the "DateAndTime" syntax as defined in RFC 2579
+ [RFC2579]. RFC 2579 also identifies an 8 octet representation of a
+ "DateAndTime" value, but IPP objects MUST use the 11 octet
+ representation. A user interface will provide a mapping between
+ protocol dateTime values and displayable user-friendly words or
+ presentation values and phrases which are localized to the natural
+ language and date format of the user.
+
+4.1.15 'resolution'
+
+ The 'resolution' attribute syntax specifies a two-dimensional
+ resolution in the indicated units. It consists of 3 values: a cross
+ feed direction resolution (positive integer value), a feed direction
+
+
+
+deBry, et al. Experimental [Page 69]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ resolution (positive integer value), and a units value. The
+ semantics of these three components are taken from the Printer MIB
+ [RFC1759] suggested values. That is, the cross feed direction
+ component resolution component is the same as the
+ prtMarkerAddressabilityXFeedDir object in the Printer MIB, the feed
+ direction component resolution component is the same as the
+ prtMarkerAddressabilityFeedDir in the Printer MIB, and the units
+ component is the same as the prtMarkerAddressabilityUnit object in
+ the Printer MIB (namely, '3' indicates dots per inch and '4'
+ indicates dots per centimeter). All three values MUST be present
+ even if the first two values are the same. Example: '300', '600', '
+ 3' indicates a 300 dpi cross-feed direction resolution, a 600 dpi
+ feed direction resolution, since a '3' indicates dots per inch (dpi).
+
+4.1.16 '1setOf X'
+
+ The '1setOf X' attribute syntax is 1 or more values of attribute
+ syntax type X. This syntax type is used for multi-valued attributes.
+ The syntax type is called '1setOf' rather than just 'setOf' as a
+ reminder that the set of values MUST NOT be empty (i.e., a set of
+ size 0). Sets are normally unordered. However each attribute
+ description of this type may specify that the values MUST be in a
+ certain order for that attribute.
+
+4.2 Job Template Attributes
+
+ Job Template attributes describe job processing behavior. Support
+ for Job Template attributes by a Printer object is OPTIONAL (see
+ section 13.2.3 for a description of support for OPTIONAL attributes).
+ Also, clients OPTIONALLY supply Job Template attributes in create
+ requests.
+
+ Job Template attributes conform to the following rules. For each Job
+ Template attribute called "xxx":
+
+ 1. If the Printer object supports "xxx" then it MUST support both a
+ "xxx-default" attribute (unless there is a "No" in the table
+ below) and a "xxx-supported" attribute. If the Printer object
+ doesn't support "xxx", then it MUST support neither an "xxx-
+ default" attribute nor an "xxx-supported" attribute, and it MUST
+ treat an attribute "xxx" supplied by a client as unsupported.
+ An attribute "xxx" may be supported for some document formats
+ and not supported for other document formats. For example, it
+ is expected that a Printer object would only support
+ "orientation-requested" for some document formats (such as '
+ text/plain' or 'text/html') but not others (such as '
+ application/postscript').
+
+
+
+
+deBry, et al. Experimental [Page 70]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 2. "xxx" is OPTIONALLY supplied by the client in a create request.
+ If "xxx" is supplied, the client is indicating a desired job
+ processing behavior for this Job. When "xxx" is not supplied,
+ the client is indicating that the Printer object apply its
+ default job processing behavior at job processing time if the
+ document content does not contain an embedded instruction
+ indicating an xxx-related behavior.
+
+ Note: Since an administrator MAY change the default value
+ attribute after a Job object has been submitted but before it
+ has been processed, the default value used by the Printer object
+ at job processing time may be different that the default value
+ in effect at job submission time.
+
+ 3. The "xxx-supported" attribute is a Printer object attribute that
+ describes which job processing behaviors are supported by that
+ Printer object. A client can query the Printer object to find
+ out what xxx-related behaviors are supported by inspecting the
+ returned values of the "xxx-supported" attribute.
+
+ Note: The "xxx" in each "xxx-supported" attribute name is
+ singular, even though an "xxx-supported" attribute usually has
+ more than one value, such as "job-sheet-supported", unless the
+ "xxx" Job Template attribute is plural, such as "finishings" or
+ "sides". In such cases the "xxx-supported" attribute names are:
+ "finishings-supported" and "sides-supported".
+
+ 4. The "xxx-default" default value attribute describes what will be
+ done at job processing time when no other job processing
+ information is supplied by the client (either explicitly as an
+ IPP attribute in the create request or implicitly as an embedded
+ instruction within the document data).
+
+ If an application wishes to present an end user with a list of
+ supported values from which to choose, the application SHOULD query
+ the Printer object for its supported value attributes. The
+ application SHOULD also query the default value attributes. If the
+ application then limits selectable values to only those value that
+ are supported, the application can guarantee that the values supplied
+ by the client in the create request all fall within the set of
+ supported values at the Printer. When querying the Printer, the
+ client MAY enumerate each attribute by name in the Get-Printer-
+ Attributes Request, or the client MAY just name the "job-template"
+ group in order to get the complete set of supported attributes (both
+ supported and default attributes).
+
+
+
+
+
+
+deBry, et al. Experimental [Page 71]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ The "finishings" attribute is an example of a Job Template attribute.
+ It can take on a set of values such as 'staple', 'punch', and/or '
+ cover'. A client can query the Printer object for the "finishings-
+ supported" attribute and the "finishings-default" attribute. The
+ supported attribute contains a set of supported values. The default
+ value attribute contains the finishing value(s) that will be used for
+ a new Job if the client does not supply a "finishings" attribute in
+ the create request and the document data does not contain any
+ corresponding finishing instructions. If the client does supply the
+ "finishings" attribute in the create request, the IPP object
+ validates the value or values to make sure that they are a subset of
+ the supported values identified in the Printer object's "finishings-
+ supported" attribute. See section 3.2.1.2.
+
+ The table below summarizes the names and relationships for all Job
+ Template attributes. The first column of the table (labeled "Job
+ Attribute") shows the name and syntax for each Job Template attribute
+ in the Job object. These are the attributes that can optionally be
+ supplied by the client in a create request. The last two columns
+ (labeled "Printer: Default Value Attribute" and "Printer: Supported
+ Values Attribute") shows the name and syntax for each Job Template
+ attribute in the Printer object (the default value attribute and the
+ supported values attribute). A "No" in the table means the Printer
+ MUST NOT support the attribute (that is, the attribute is simply not
+ applicable). For brevity in the table, the 'text' and 'name' entries
+ do not show the maximum length for each attribute.
+
+ +===================+======================+======================+
+ | Job Attribute |Printer: Default Value| Printer: Supported |
+ | | Attribute | Values Attribute |
+ +===================+======================+======================+
+ | job-priority | job-priority-default |job-priority-supported|
+ | (integer 1:100) | (integer 1:100) |(integer 1:100) |
+ +-------------------+----------------------+----------------------+
+ | job-hold-until | job-hold-until- |job-hold-until- |
+ | (type3 keyword | | default | supported |
+ | name) | (type3 keyword | |(1setOf |
+ | | name) | type3 keyword | name)|
+ +-------------------+----------------------+----------------------+
+ | job-sheets | job-sheets-default |job-sheets-supported |
+ | (type3 keyword | | (type3 keyword | |(1setOf |
+ | name) | name) | type3 keyword | name)|
+ +-------------------+----------------------+----------------------+
+ |multiple-document- |multiple-document- |multiple-document- |
+ | handling | handling-default |handling-supported |
+ | (type2 keyword) | (type2 keyword) |(1setOf type2 keyword)|
+ +-------------------+----------------------+----------------------+
+
+
+
+
+deBry, et al. Experimental [Page 72]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ +===================+======================+======================+
+ | Job Attribute |Printer: Default Value| Printer: Supported |
+ | | Attribute | Values Attribute |
+ +===================+======================+======================+
+ | copies | copies-default | copies-supported |
+ | (integer (1:MAX)) | (integer (1:MAX)) | (rangeOfInteger |
+ | | | (1:MAX)) |
+ +-------------------+----------------------+----------------------+
+ | finishings | finishings-default | finishings-supported |
+ |(1setOf type2 enum)|(1setOf type2 enum) |(1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+ | page-ranges | No | page-ranges- |
+ | (1setOf | | supported (boolean) |
+ | rangeOfInteger | | |
+ | (1:MAX)) | | |
+ +-------------------+----------------------+----------------------+
+ | sides | sides-default | sides-supported |
+ | (type2 keyword) | (type2 keyword) |(1setOf type2 keyword)|
+ +-------------------+----------------------+----------------------+
+ | number-up | number-up-default | number-up-supported |
+ | (integer (1:MAX)) | (integer (1:MAX)) |(1setOf integer |
+ | | | (1:MAX) | |
+ | | | rangeOfInteger |
+ | | | (1:MAX)) |
+ +-------------------+----------------------+----------------------+
+ | orientation- |orientation-requested-|orientation-requested-|
+ | requested | default | supported |
+ | (type2 enum) | (type2 enum) | (1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+ | media | media-default | media-supported |
+ | (type3 keyword | | (type3 keyword | |(1setOf |
+ | name) | name) | type3 keyword | name)|
+ | | | |
+ | | | media-ready |
+ | | |(1setOf |
+ | | | type3 keyword | name)|
+ +-------------------+----------------------+----------------------+
+ | printer-resolution| printer-resolution- | printer-resolution- |
+ | (resolution) | default | supported |
+ | | (resolution) |(1setOf resolution) |
+ +-------------------+----------------------+----------------------+
+ | print-quality | print-quality-default| print-quality- |
+ | (type2 enum) | (type2 enum) | supported |
+ | | |(1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 73]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.2.1 job-priority (integer(1:100))
+
+ This attribute specifies a priority for scheduling the Job. A higher
+ value specifies a higher priority. The value 1 indicates the lowest
+ possible priority. The value 100 indicates the highest possible
+ priority. Among those jobs that are ready to print, a Printer MUST
+ print all jobs with a priority value of n before printing those with
+ a priority value of n-1 for all n.
+
+ If the Printer object supports this attribute, it MUST always support
+ the full range from 1 to 100. No administrative restrictions are
+ permitted. This way an end-user can always make full use of the
+ entire range with any Printer object. If privileged jobs are
+ implemented outside IPP/1.0, they MUST have priorities higher than
+ 100, rather than restricting the range available to end-users.
+
+ If the client does not supply this attribute and this attribute is
+ supported by the Printer object, the Printer object MUST use the
+ value of the Printer object's "job-priority-default" at job
+ submission time (unlike most Job Template attributes that are used if
+ necessary at job processing time).
+
+ The syntax for the "job-priority-supported" is also integer(1:100).
+ This single integer value indicates the number of priority levels
+ supported. The Printer object MUST take the value supplied by the
+ client and map it to the closest integer in a sequence of n integers
+ values that are evenly distributed over the range from 1 to 100 using
+ the formula:
+
+ roundToNearestInt((100x+50)/n)
+
+ where n is the value of "job-priority-supported" and x ranges from 0
+ through n-1.
+
+ For example, if n=1 the sequence of values is 50; if n=2, the
+ sequence of values is: 25 and 75; if n = 3, the sequence of values
+ is: 17, 50 and 83; if n = 10, the sequence of values is: 5, 15, 25,
+ 35, 45, 55, 65, 75, 85, and 95; if n = 100, the sequence of values
+ is: 1, 2, 3, . 100.
+
+ If the value of the Printer object's "job-priority-supported" is 10
+ and the client supplies values in the range 1 to 10, the Printer
+ object maps them to 5, in the range 11 to 20, the Printer object maps
+ them to 15, etc.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 74]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.2.2 job-hold-until (type3 keyword | name (MAX))
+
+ This attribute specifies the named time period during which the Job
+ MUST become a candidate for printing.
+
+ Standard keyword values for named time periods are:
+
+ 'no-hold': immediately, if there are not other reasons to hold the
+ job
+ 'day-time': during the day
+ 'evening': evening
+ 'night': night
+ 'weekend': weekend
+ 'second-shift': second-shift (after close of business)
+ 'third-shift': third-shift (after midnight)
+
+ An administrator MUST associate allowable print times with a named
+ time period (by means outside IPP/1.0). An administrator is
+ encouraged to pick names that suggest the type of time period. An
+ administrator MAY define additional values using the 'name' or '
+ keyword' attribute syntax, depending on implementation.
+
+ If the value of this attribute specifies a time period that is in the
+ future, the Printer MUST add the 'job-hold-until-specified' value to
+ the job's "job-state-reasons" attribute, move the job to the '
+ pending-held' state, and MUST NOT schedule the job for printing until
+ the specified time-period arrives. When the specified time period
+ arrives, the Printer MUST remove the 'job-hold-until-specified' value
+ from the job's "job-state-reason" attribute and, if there are no
+ other job state reasons that keep the job in the 'pending-held'
+ state, the Printer MUST consider the job as a candidate for
+ processing by moving the job to the 'pending' state.
+
+ If this job attribute value is the named value 'no-hold', or the
+ specified time period has already started, the job MUST be a
+ candidate for processing immediately.
+
+ If the client does not supply this attribute and this attribute is
+ supported by the Printer object, the Printer object MUST use the
+ value of the Printer object's "job-hold-until-default" at job
+ submission time (unlike most Job Template attributes that are used if
+ necessary at job processing time).
+
+4.2.3 job-sheets (type3 keyword | name(MAX))
+
+ This attribute determines which job start/end sheet(s), if any, MUST
+ be printed with a job.
+
+
+
+
+deBry, et al. Experimental [Page 75]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Standard keyword values are:
+
+ 'none': no job sheet is printed
+ 'standard': one or more site specific standard job sheets are
+ printed, e.g. a single start sheet or both start and end sheet
+ is printed
+
+ An administrator MAY define additional values using the 'name' or '
+ keyword' attribute syntax, depending on implementation.
+
+ Note: The effect of this attribute on jobs with multiple documents
+ MAY be affected by the "multiple-document-handling" job attribute
+ (section 4.2.4), depending on the job sheet semantics.
+
+4.2.4 multiple-document-handling (type2 keyword)
+
+ This attribute is relevant only if a job consists of two or more
+ documents. The attribute controls finishing operations and the
+ placement of one or more print-stream pages into impressions and onto
+ media sheets. When the value of the "copies" attribute exceeds 1, it
+ also controls the order in which the copies that result from
+ processing the documents are produced. For the purposes of this
+ explanations, if "a" represents an instance of document data, then
+ the result of processing the data in document "a" is a sequence of
+ media sheets represented by "a(*)".
+
+ Standard keyword values are:
+
+ 'single-document': If a Job object has multiple documents, say, the
+ document data is called a and b, then the result of processing
+ all the document data (a and then b) MUST be treated as a single
+ sequence of media sheets for finishing operations; that is,
+ finishing would be performed on the concatenation of the
+ sequences a(*),b(*). The Printer object MUST NOT force the data
+ in each document instance to be formatted onto a new print-
+ stream page, nor to start a new impression on a new media sheet.
+ If more than one copy is made, the ordering of the sets of media
+ sheets resulting from processing the document data MUST be a(*),
+ b(*), a(*), b(*), ..., and the Printer object MUST force each
+ copy (a(*),b(*)) to start on a new media sheet.
+ 'separate-documents-uncollated-copies': If a Job object has
+ multiple documents, say, the document data is called a and b,
+ then the result of processing the data in each document instance
+ MUST be treated as a single sequence of media sheets for
+ finishing operations; that is, the sets a(*) and b(*) would each
+ be finished separately. The Printer object MUST force each copy
+ of the result of processing the data in a single document to
+ start on a new media sheet. If more than one copy is made, the
+
+
+
+deBry, et al. Experimental [Page 76]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ ordering of the sets of media sheets resulting from processing
+ the document data MUST be a(*), a(*), ..., b(*), b(*) ... .
+ 'separate-documents-collated-copies': If a Job object has multiple
+ documents, say, the document data is called a and b, then the
+ result of processing the data in each document instance MUST be
+ treated as a single sequence of media sheets for finishing
+ operations; that is, the sets a(*) and b(*) would each be
+ finished separately. The Printer object MUST force each copy of
+ the result of processing the data in a single document to start
+ on a new media sheet. If more than one copy is made, the
+ ordering of the sets of media sheets resulting from processing
+ the document data MUST be a(*), b(*), a(*), b(*), ... .
+ 'single-document-new-sheet': Same as 'single-document', except
+ that the Printer object MUST ensure that the first impression of
+ each document instance in the job is placed on a new media
+ sheet. This value allows multiple documents to be stapled
+ together with a single staple where each document starts on a
+ new sheet.
+
+ The 'single-document' value is the same as 'separate-documents-
+ collated-copies' with respect to ordering of print-stream pages, but
+ not media sheet generation, since 'single-document' will put the
+ first page of the next document on the back side of a sheet if an odd
+ number of pages have been produced so far for the job, while '
+ separate-documents-collated-copies' always forces the next document
+ or document copy on to a new sheet. In addition, if the "finishings"
+ attribute specifies 'staple', then with 'single-document', documents
+ a and b are stapled together as a single document with no regard to
+ new sheets, with 'single-document-new-sheet', documents a and b are
+ stapled together as a single document, but document b starts on a new
+ sheet, but with 'separate-documents-uncollated-copies' and '
+ separate-documents-collated-copies', documents a and b are stapled
+ separately.
+
+ Note: None of these values provide means to produce uncollated sheets
+ within a document, i.e., where multiple copies of sheet n are
+ produced before sheet n+1 of the same document.
+
+ The relationship of this attribute and the other attributes that
+ control document processing is described in section 15.3.
+
+4.2.5 copies (integer(1:MAX))
+
+ This attribute specifies the number of copies to be printed.
+
+ On many devices the supported number of collated copies will be
+ limited by the number of physical output bins on the device, and may
+ be different from the number of uncollated copies which can be
+
+
+
+deBry, et al. Experimental [Page 77]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ supported.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.6 finishings (1setOf type2 enum)
+
+ This attribute identifies the finishing operations that the Printer
+ uses for each copy of each printed document in the Job. For Jobs with
+ multiple documents, the "multiple-document-handling" attribute
+ determines what constitutes a "copy" for purposes of finishing.
+
+ Standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'none': Perform no finishing
+ '4' 'staple': Bind the document(s) with one or more staples.
+ The exact number and placement of the staples is
+ site-defined.
+ '5' 'punch': This value indicates that holes are required in
+ the finished document. The exact number and placement
+ of the holes is site-defined The punch specification
+ MAY be satisfied (in a site- and implementation-
+ specific manner) either by drilling/punching, or by
+ substituting pre-drilled media.
+ '6' 'cover': This value is specified when it is desired to
+ select a non-printed (or pre-printed) cover for the
+ document. This does not supplant the specification of
+ a printed cover (on cover stock medium) by the
+ document itself.
+ '7' 'bind': This value indicates that a binding is to be
+ applied to the document; the type and placement of the
+ binding is site-defined."
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+ If the client supplies a value of 'none' along with any other
+ combination of values, it is the same as if only that other
+ combination of values had been supplied (that is the 'none' value has
+ no effect).
+
+
+
+deBry, et al. Experimental [Page 78]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.2.7 page-ranges (1setOf rangeOfInteger (1:MAX))
+
+ This attribute identifies the range(s) of print-stream pages that the
+ Printer object uses for each copy of each document which are to be
+ printed. Nothing is printed for any pages identified that do not
+ exist in the document(s). Ranges MUST be in ascending order, for
+ example: 1-3, 5-7, 15-19 and MUST NOT overlap, so that a non-spooling
+ Printer object can process the job in a single pass. If the ranges
+ are not ascending or are overlapping, the IPP object MUST reject the
+ request and return the 'client-error-bad-request' status code. The
+ attribute is associated with print-stream pages not application-
+ numbered pages (for example, the page numbers found in the headers
+ and or footers for certain word processing applications).
+
+ For Jobs with multiple documents, the "multiple-document-handling"
+ attribute determines what constitutes a "copy" for purposes of the
+ specified page range(s). When "multiple-document-handling" is '
+ single-document', the Printer object MUST apply each supplied page
+ range once to the concatenation of the print-stream pages. For
+ example, if there are 8 documents of 10 pages each, the page-range '
+ 41:60' prints the pages in the 5th and 6th documents as a single
+ document and none of the pages of the other documents are printed.
+ When "multiple-document-handling" is 'separate-documents-uncollated-
+ copies' or 'separate-documents-collated-copies', the Printer object
+ MUST apply each supplied page range repeatedly to each document copy.
+ For the same job, the page-range '1:3, 10:10' would print the first 3
+ pages and the 10th page of each of the 8 documents in the Job, as 8
+ separate documents.
+
+ In most cases, the exact pages to be printed will be generated by a
+ device driver and this attribute would not be required. However,
+ when printing an archived document which has already been formatted,
+ the end user may elect to print just a subset of the pages contained
+ in the document. In this case, if page-range = n.m is specified, the
+ first page to be printed will be page n. All subsequent pages of the
+ document will be printed through and including page m.
+
+ "page-ranges-supported" is a boolean value indicating whether or not
+ the printer is capable of supporting the printing of page ranges.
+ This capability may differ from one PDL to another. There is no
+ "page-ranges-default" attribute. If the "page-ranges" attribute is
+ not supplied by the client, all pages of the document will be
+ printed.
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 79]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.8 sides (type2 keyword)
+
+ This attribute specifies how print-stream pages are to be imposed
+ upon the sides of an instance of a selected medium, i.e., an
+ impression.
+
+ The standard keyword values are:
+
+ 'one-sided': imposes each consecutive print-stream page upon the
+ same side of consecutive media sheets.
+ 'two-sided-long-edge': imposes each consecutive pair of print-
+ stream pages upon front and back sides of consecutive media
+ sheets, such that the orientation of each pair of print-stream
+ pages on the medium would be correct for the reader as if for
+ binding on the long edge. This imposition is sometimes called '
+ duplex' or 'head-to-head'.
+ 'two-sided-short-edge': imposes each consecutive pair of print-
+ stream pages upon front and back sides of consecutive media
+ sheets, such that the orientation of each pair of print-stream
+ pages on the medium would be correct for the reader as if for
+ binding on the short edge. This imposition is sometimes called
+ 'tumble' or 'head-to-toe'.
+
+ 'two-sided-long-edge', 'two-sided-short-edge', 'tumble', and 'duplex'
+ all work the same for portrait or landscape. However 'head-to-toe'
+ is 'tumble' in portrait but 'duplex' in landscape. 'head-to-head'
+ also switches between 'duplex' and 'tumble' when using portrait and
+ landscape modes.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.9 number-up (integer(1:MAX))
+
+ This attribute specifies the number of print-stream pages to impose
+ upon a single side of an instance of a selected medium. For example,
+ if the value is:
+
+
+
+
+
+deBry, et al. Experimental [Page 80]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Value Description
+
+ '1' the Printer MUST place one print-stream page on a single
+ side of an instance of the selected medium (MAY add
+ some sort of translation, scaling, or rotation).
+ '2' the Printer MUST place two print-stream pages on a single
+ side of an instance of the selected medium (MAY add
+ some sort of translation, scaling, or rotation).
+ '4' the Printer MUST place four print-stream pages on a single
+ side of an instance of the selected medium (MAY add
+ some sort of translation, scaling, or rotation).
+
+ This attribute primarily controls the translation, scaling and
+ rotation of print-stream pages.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.10 orientation-requested (type2 enum)
+
+ This attribute indicates the desired orientation for printed print-
+ stream pages; it does not describe the orientation of the client-
+ supplied print-stream pages.
+
+ For some document formats (such as 'application/postscript'), the
+ desired orientation of the print-stream pages is specified within the
+ document data. This information is generated by a device driver
+ prior to the submission of the print job. Other document formats
+ (such as 'text/plain') do not include the notion of desired
+ orientation within the document data. In the latter case it is
+ possible for the Printer object to bind the desired orientation to
+ the document data after it has been submitted. It is expected that a
+ Printer object would only support "orientations-requested" for some
+ document formats (e.g., 'text/plain' or 'text/html') but not others
+ (e.g., 'application/postscript'). This is no different than any
+ other Job Template attribute since section 4.2, item 1, points out
+ that a Printer object may support or not support any Job Template
+ attribute based on the document format supplied by the client.
+ However, a special mention is made here since it is very likely that
+ a Printer object will support "orientation-requested" for only a
+ subset of the supported document formats.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 81]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'portrait': The content will be imaged across the short
+ edge of the medium.
+ '4' 'landscape': The content will be imaged across the long
+ edge of the medium. Landscape is defined to be a
+ rotation of the print-stream page to be imaged by +90
+ degrees with respect to the medium (i.e. anti-
+ clockwise) from the portrait orientation. Note: The
+ +90 direction was chosen because simple finishing on
+ the long edge is the same edge whether portrait or
+ landscape
+ '5' 'reverse-landscape': The content will be imaged across the
+ long edge of the medium. Reverse-landscape is defined
+ to be a rotation of the print-stream page to be imaged
+ by - 90 degrees with respect to the medium (i.e.
+ clockwise) from the portrait orientation. Note: The '
+ reverse-landscape' value was added because some
+ applications rotate landscape -90 degrees from
+ portrait, rather than +90 degrees.
+ '6' 'reverse-portrait': The content will be imaged across the
+ short edge of the medium. Reverse-portrait is defined
+ to be a rotation of the print-stream page to be imaged
+ by 180 degrees with respect to the medium from the
+ portrait orientation. Note: The 'reverse-portrait'
+ value was added for use with the "finishings"
+ attribute in cases where the opposite edge is desired
+ for finishing a portrait document on simple finishing
+ devices that have only one finishing position. Thus a
+ 'text'/plain' portrait document can be stapled "on the
+ right" by a simple finishing device as is common use
+ with some middle eastern languages such as Hebrew.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.11 media (type3 keyword | name(MAX))
+
+ This attribute identifies the medium that the Printer uses for all
+ impressions of the Job.
+
+ The values for "media" include medium-names, medium-sizes, input-
+ trays and electronic forms so that one attribute specifies the media.
+
+
+
+deBry, et al. Experimental [Page 82]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ If a Printer object supports a medium name as a value of this
+ attribute, such a medium name implicitly selects an input-tray that
+ contains the specified medium. If a Printer object supports a medium
+ size as a value of this attribute, such a medium size implicitly
+ selects a medium name that in turn implicitly selects an input-tray
+ that contains the medium with the specified size. If a Printer
+ object supports an input-tray as the value of this attribute, such an
+ input-tray implicitly selects the medium that is in that input-tray
+ at the time the job prints. This case includes manual-feed input-
+ trays. If a Printer object supports an electronic form as the value
+ of this attribute, such an electronic form implicitly selects a
+ medium-name that in turn implicitly selects an input-tray that
+ contains the medium specified by the electronic form. The electronic
+ form also implicitly selects an image that the Printer MUST merge
+ with the document data as its prints each page.
+
+ Standard keyword values are (taken from ISO DPA and the Printer MIB)
+ and are listed in section 14. An administrator MAY define additional
+ values using the 'name' or 'keyword' attribute syntax, depending on
+ implementation.
+
+ There is also an additional Printer attribute named "media-ready"
+ which differs from "media-supported" in that legal values only
+ include the subset of "media-supported" values that are physically
+ loaded and ready for printing with no operator intervention required.
+ If an IPP object supports "media-supported", it NEED NOT support
+ "media-ready".
+
+ The relationship of this attribute and the other attributes that
+ control document processing is described in section 15.3.
+
+4.2.12 printer-resolution (resolution)
+
+ This attribute identifies the resolution that Printer uses for the
+ Job.
+
+4.2.13 print-quality (type2 enum)
+
+ This attribute specifies the print quality that the Printer uses for
+ the Job.
+
+ The standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'draft': lowest quality available on the printer
+ '4' 'normal': normal or intermediate quality on the printer
+ '5' 'high': highest quality available on the printer
+
+
+
+deBry, et al. Experimental [Page 83]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.3 Job Description Attributes
+
+ The attributes in this section form the attribute group called "job-
+ description". The following table summarizes these attributes. The
+ third column indicates whether the attribute is a REQUIRED attribute
+ that MUST be supported by Printer objects. If it is not indicated as
+ REQUIRED, then it is OPTIONAL. The maximum size in octets for 'text'
+ and 'name' attributes is indicated in parenthesizes.
+
+ +----------------------------+----------------------+----------------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+----------------------+----------------+
+ | job-uri | uri | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-id | integer(1:MAX) | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-printer-uri | uri | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-more-info | uri | |
+ +----------------------------+----------------------+----------------+
+ | job-name | name (MAX) | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-originating-user-name | name (MAX) | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-state | type1 enum | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | job-state-reasons | 1setOf type2 keyword | |
+ +----------------------------+----------------------+----------------+
+ | job-state-message | text (MAX) | |
+ +----------------------------+----------------------+----------------+
+ | number-of-documents | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | output-device-assigned | name (127) | |
+ +----------------------------+----------------------+----------------+
+ | time-at-creation | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | time-at-processing | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | time-at-completed | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | number-of-intervening-jobs | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-message-from-operator | text (127) | |
+ +----------------------------+----------------------+----------------+
+ | job-k-octets | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-impressions | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+
+
+
+deBry, et al. Experimental [Page 84]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ +----------------------------+----------------------+----------------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+----------------------+----------------+
+ | job-media-sheets | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-k-octets-processed | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-impressions-completed | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-media-sheets-completed | integer (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | attributes-charset | charset | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | attributes-natural-language| naturalLanguage | REQUIRED |
+ +----------------------------+----------------------+----------------+
+
+
+4.3.1 job-uri (uri)
+
+ This REQUIRED attribute contains the URI for the job. The Printer
+ object, on receipt of a new job, generates a URI which identifies the
+ new Job. The Printer object returns the value of the "job-uri"
+ attribute as part of the response to a create request. The precise
+ format of a Job URI is implementation dependent. If the Printer
+ object supports more than one URI and there is some relationship
+ between the newly formed Job URI and the Printer object's URI, the
+ Printer object uses the Printer URI supplied by the client in the
+ create request. For example, if the create request comes in over a
+ secure channel, the new Job URI MUST use the same secure channel.
+ This can be guaranteed because the Printer object is responsible for
+ generating the Job URI and the Printer object is aware of its
+ security configuration and policy as well as the Printer URI used in
+ the create request.
+
+ For a description of this attribute and its relationship to "job-id"
+ and "job-printer-uri" attribute, see the discussion in section 2.4 on
+ "Object Identity".
+
+4.3.2 job-id (integer(1:MAX))
+
+ This REQUIRED attribute contains the ID of the job. The Printer, on
+ receipt of a new job, generates an ID which identifies the new Job on
+ that Printer. The Printer returns the value of the "job-id"
+ attribute as part of the response to a create request. The 0 value
+ is not included to allow for compatibility with SNMP index values
+ which also cannot be 0.
+
+
+
+
+
+deBry, et al. Experimental [Page 85]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ For a description of this attribute and its relationship to "job-uri"
+ and "job-printer-uri" attribute, see the discussion in section 2.4 on
+ "Object Identity".
+
+4.3.3 job-printer-uri (uri)
+
+ This REQUIRED attribute identifies the Printer object that created
+ this Job object. When a Printer object creates a Job object, it
+ populates this attribute with the Printer object URI that was used in
+ the create request. This attribute permits a client to identify the
+ Printer object that created this Job object when only the Job
+ object's URI is available to the client. The client queries the
+ creating Printer object to determine which languages, charsets,
+ operations, are supported for this Job.
+
+ For a description of this attribute and its relationship to "job-uri"
+ and "job-id" attribute, see the discussion in section 2.4 on "Object
+ Identity".
+
+4.3.4 job-more-info (uri)
+
+ Similar to "printer-more-info", this attribute contains the URI
+ referencing some resource with more information about this Job
+ object, perhaps an HTML page containing information about the Job.
+
+4.3.5 job-name (name(MAX))
+
+ This REQUIRED attribute is the name of the job. It is a name that is
+ more user friendly than the "job-uri" attribute value. It does not
+ need to be unique between Jobs. The Job's "job-name" attribute is
+ set to the value supplied by the client in the "job-name" operation
+ attribute in the create request (see Section 3.2.1.1). If, however,
+ the "job-name" operation attribute is not supplied by the client in
+ the create request, the Printer object, on creation of the Job, MUST
+ generate a name. The printer SHOULD generate the value of the Job's
+ "job-name" attribute from the first of the following sources that
+ produces a value: 1) the "document-name" operation attribute of the
+ first (or only) document, 2) the "document-URI" attribute of the
+ first (or only) document, or 3) any other piece of Job specific
+ and/or Document Content information.
+
+4.3.6 job-originating-user-name (name(MAX))
+
+ This REQUIRED attribute contains the name of the end user that
+ submitted the print job. The Printer object sets this attribute to
+ the most authenticated printable name that it can obtain from the
+ authentication service over which the IPP operation was received.
+
+
+
+
+deBry, et al. Experimental [Page 86]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Only if such is not available, does the Printer object use the value
+ supplied by the client in the "requesting-user-name" operation
+ attribute of the create operation (see Section 8).
+
+ Note: The Printer object needs to keep an internal originating user
+ id of some form, typically as a credential of a principal, with the
+ Job object. Since such an internal attribute is implementation-
+ dependent and not of interest to clients, it is not specified as a
+ Job Description attribute. This originating user id is used for
+ authorization checks (if any) on all subsequent operation.
+
+4.3.7 job-state (type1 enum)
+
+ This REQUIRED attribute identifies the current state of the job.
+ Even though the IPP protocol defines eight values for job states,
+ implementations only need to support those states which are
+ appropriate for the particular implementation. In other words, a
+ Printer supports only those job states implemented by the output
+ device and available to the Printer object implementation.
+
+ Standard enum values are:
+
+ Values Symbolic Name and Description
+
+ '3' 'pending': The job is a candidate to start processing, but
+ is not yet processing.
+
+ '4' 'pending-held': The job is not a candidate for processing
+ for any number of reasons but will return to the '
+ pending' state as soon as the reasons are no longer
+ present. The job's "job-state-reason" attribute MUST
+ indicate why the job is no longer a candidate for
+ processing.
+
+ '5' 'processing': One or more of:
+
+ 1. the job is using, or is attempting to use, one or
+ more purely software processes that are analyzing,
+ creating, or interpreting a PDL, etc.,
+ 2. the job is using, or is attempting to use, one or
+ more hardware devices that are interpreting a PDL,
+ making marks on a medium, and/or performing finishing,
+ such as stapling, etc.,
+ 3. the Printer object has made the job ready for
+ printing, but the output device is not yet printing
+ it, either because the job hasn't reached the output
+
+
+
+
+
+deBry, et al. Experimental [Page 87]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ device or because the job is queued in the output
+ device or some other spooler, awaiting the output
+ device to print it.
+
+ When the job is in the 'processing' state, the entire
+ job state includes the detailed status represented in
+ the printer's "printer-state", "printer-state-
+ reasons", and "printer-state-message" attributes.
+
+ Implementations MAY, though they NEED NOT, include
+ additional values in the job's "job-state-reasons"
+ attribute to indicate the progress of the job, such as
+ adding the 'job-printing' value to indicate when the
+ output device is actually making marks on paper and/or
+ the 'processing-to-stop-point' value to indicate that
+ the IPP object is in the process of canceling or
+ aborting the job. Most implementations won't bother
+ with this nuance.
+
+ '6' 'processing-stopped': The job has stopped while processing
+ for any number of reasons and will return to the '
+ processing' state as soon as the reasons are no longer
+ present.
+
+ The job's "job-state-reason" attribute MAY indicate
+ why the job has stopped processing. For example, if
+ the output device is stopped, the 'printer-stopped'
+ value MAY be included in the job's "job-state-reasons"
+ attribute.
+
+ Note: When an output device is stopped, the device
+ usually indicates its condition in human readable form
+ locally at the device. A client can obtain more
+ complete device status remotely by querying the
+ Printer object's "printer-state", "printer-state-
+ reasons" and "printer-state-message" attributes.
+
+ '7' 'canceled': The job has been canceled by a Cancel-Job
+ operation and the Printer object has completed
+ canceling the job and all job status attributes have
+ reached their final values for the job. While the
+ Printer object is canceling the job, the job remains
+ in its current state, but the job's "job-state-
+ reasons" attribute SHOULD contain the 'processing-to-
+ stop-point' value and one of the 'canceled-by-user', '
+ canceled-by-operator', or 'canceled-at-device' value.
+
+
+
+
+
+deBry, et al. Experimental [Page 88]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ When the job moves to the 'canceled' state, the '
+ processing-to-stop-point' value, if present, MUST be
+ removed, but the 'canceled-by-xxx', if present, MUST
+ remain.
+
+ '8' 'aborted': The job has been aborted by the system, usually
+ while the job was in the 'processing' or 'processing-
+ stopped' state and the Printer has completed aborting
+ the job and all job status attributes have reached
+ their final values for the job. While the Printer
+ object is aborting the job, the job remains in its
+ current state, but the job's "job-state-reasons"
+ attribute SHOULD contain the 'processing-to-stop-
+ point' and 'aborted-by-system' values. When the job
+ moves to the 'aborted' state, the 'processing-to-
+ stop-point' value, if present, MUST be removed, but
+ the 'aborted-by-system' value, if present, MUST
+ remain.
+
+ '9' 'completed': The job has completed successfully or with
+ warnings or errors after processing and all of the job
+ media sheets have been successfully stacked in the
+ appropriate output bin(s) and all job status
+ attributes have reached their final values for the
+ job. The job's "job-state-reasons" attribute SHOULD
+ contain one of: 'completed-successfully', '
+ completed-with-warnings', or 'completed-with-errors'
+ values.
+
+ The final value for this attribute MUST be one of: 'completed', '
+ canceled', or 'aborted' before the Printer removes the job
+ altogether. The length of time that jobs remain in the 'canceled', '
+ aborted', and 'completed' states depends on implementation.
+
+ The following figure shows the normal job state transitions.
+
+ +----> canceled
+ /
+ +----> pending --------> processing ---------+------> completed
+ | ^ ^ \
+ --->+ | | +----> aborted
+ | v v /
+ +----> pending-held processing-stopped ---+
+
+ Normally a job progresses from left to right. Other state
+ transitions are unlikely, but are not forbidden. Not shown are the
+ transitions to the 'canceled' state from the 'pending', 'pending-
+ held', and 'processing-stopped' states.
+
+
+
+deBry, et al. Experimental [Page 89]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Jobs reach one of the three terminal states: 'completed', 'canceled',
+ or 'aborted', after the jobs have completed all activity, including
+ stacking output media, after the jobs have completed all activity,
+ and all job status attributes have reached their final values for the
+ job.
+
+ Note: As with all other IPP attributes, if the implementation can not
+ determine the correct value for this attribute, it SHOULD respond
+ with the out-of-band value 'unknown' (see section 4.1) rather than
+ try to guess at some possibly incorrect value and give the end user
+ the wrong impression about the state of the Job object. For example,
+ if the implementation is just a gateway into some printing system
+ that does not provide detailed status about the print job, the IPP
+ Job object's state might literally be 'unknown'.
+
+4.3.8 job-state-reasons (1setOf type2 keyword)
+
+ This attribute provides additional information about the job's
+ current state, i.e., information that augments the value of the job's
+ "job-state" attribute.
+
+ Implementation of these values is OPTIONAL, i.e., a Printer NEED NOT
+ implement them, even if (1) the output device supports the
+ functionality represented by the reason and (2) is available to the
+ Printer object implementation. These values MAY be used with any job
+ state or states for which the reason makes sense. Furthermore, when
+ implemented, the Printer MUST return these values when the reason
+ applies and MUST NOT return them when the reason no longer applies
+ whether the value of the Job's "job-state" attribute changed or not.
+ When the Job does not have any reasons for being in its current
+ state, the value of the Job's "job-state-reasons" attribute MUST be '
+ none'.
+
+ Note: While values cannot be added to the 'job-state' attribute
+ without impacting deployed clients that take actions upon receiving
+ "job-state" values, it is the intent that additional "job-state-
+ reasons" values can be defined and registered without impacting such
+ deployed clients. In other words, the "job-state-reasons" attribute
+ is intended to be extensible.
+
+ The following standard keyword values are defined. For ease of
+ understanding, the values are presented in the order in which the
+ reasons are likely to occur (if implemented), starting with the '
+ job-incoming' value:
+
+ 'none': There are no reasons for the job's current state.
+ 'job-incoming': The Create-Job operation has been accepted by the
+ Printer, but the Printer is expecting additional Send-Document
+
+
+
+deBry, et al. Experimental [Page 90]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ and/or Send-URI operations and/or is accessing/accepting
+ document data.
+ 'submission-interrupted': The job was not completely submitted for
+ some unforeseen reason, such as: (1) the Printer has crashed
+ before the job was closed by the client, (2) the Printer or the
+ document transfer method has crashed in some non-recoverable way
+ before the document data was entirely transferred to the
+ Printer, (3) the client crashed or failed to close the job
+ before the time-out period. See section 4.4.28.
+ 'job-outgoing': The Printer is transmitting the job to the output
+ device.
+ 'job-hold-until-specified': The value of the job's "job-hold-
+ until" attribute was specified with a time period that is still
+ in the future. The job MUST NOT be a candidate for processing
+ until this reason is removed and there are no other reasons to
+ hold the job.
+ 'resources-are-not-ready': At least one of the resources needed by
+ the job, such as media, fonts, resource objects, etc., is not
+ ready on any of the physical printer's for which the job is a
+ candidate. This condition MAY be detected when the job is
+ accepted, or subsequently while the job is pending or
+ processing, depending on implementation. The job may remain in
+ its current state or be moved to the 'pending-held' state,
+ depending on implementation and/or job scheduling policy.
+ 'printer-stopped-partly': The value of the Printer's "printer-
+ state-reasons" attribute contains the value 'stopped-partly'.
+ 'printer-stopped': The value of the Printer's "printer-state"
+ attribute is 'stopped'.
+ 'job-interpreting': Job is in the 'processing' state, but more
+ specifically, the Printer is interpreting the document data.
+ 'job-queued': Job is in the 'processing' state, but more
+ specifically, the Printer has queued the document data.
+ 'job-transforming': Job is in the 'processing' state, but more
+ specifically, the Printer is interpreting document data and
+ producing another electronic representation.
+ 'job-printing': The output device is marking media. This value is
+ useful for Printers which spend a great deal of time processing
+ (1) when no marking is happening and then want to show that
+ marking is now happening or (2) when the job is in the process
+ of being canceled or aborted while the job remains in the '
+ processing' state, but the marking has not yet stopped so that
+ impression or sheet counts are still increasing for the job.
+ 'job-canceled-by-user': The job was canceled by the owner of the
+ job using the Cancel-Job request, i.e., by a user whose
+ authenticated identity is the same as the value of the
+ originating user that created the Job object, or by some other
+ authorized end-user, such as a member of the job owner's
+ security group.
+
+
+
+deBry, et al. Experimental [Page 91]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'job-canceled-by-operator': The job was canceled by the operator
+ using the Cancel-Job request, i.e., by a user who has been
+ authenticated as having operator privileges (whether local or
+ remote). If the security policy is to allow anyone to cancel
+ anyone's job, then this value may be used when the job is
+ canceled by other than the owner of the job. For such a
+ security policy, in effect, everyone is an operator as far as
+ canceling jobs with IPP is concerned.
+ 'job-canceled-at-device': The job was canceled by an unidentified
+ local user, i.e., a user at a console at the device.
+ 'aborted-by-system': The job (1) is in the process of being
+ aborted, (2) has been aborted by the system and placed in the '
+ aborted' state, or (3) has been aborted by the system and placed
+ in the 'pending-held' state, so that a user or operator can
+ manually try the job again.
+ 'processing-to-stop-point': The requester has issued a Cancel-Job
+ operation or the Printer object has aborted the job, but is
+ still performing some actions on the job until a specified stop
+ point occurs or job termination/cleanup is completed.
+
+ This reason is recommended to be used in conjunction with the '
+ processing' job state to indicate that the Printer object is
+ still performing some actions on the job while the job remains
+ in the 'processing' state. After all the job's job description
+ attributes have stopped incrementing, the Printer object moves
+ the job from the 'processing' state to the 'canceled' or '
+ aborted' job states.
+
+ 'service-off-line': The Printer is off-line and accepting no jobs.
+ All 'pending' jobs are put into the 'pending-held' state. This
+ situation could be true if the service's or document transform's
+ input is impaired or broken.
+ 'job-completed-successfully': The job completed successfully.
+ 'job-completed-with-warnings': The job completed with warnings.
+ 'job-completed-with-errors': The job completed with errors (and
+ possibly warnings too).
+
+4.3.9 job-state-message (text(MAX))
+
+ This attribute specifies information about the "job-state" and "job-
+ state-reasons" attributes in human readable text. If the Printer
+ object supports this attribute, the Printer object MUST be able to
+ generate this message in any of the natural languages identified by
+ the Printer's "generated-natural-language-supported" attribute (see
+ the "attributes-natural-language" operation attribute specified in
+ Section 3.1.4.1).
+
+
+
+
+
+deBry, et al. Experimental [Page 92]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: the value SHOULD NOT contain additional information not
+ contained in the values of the "job-state" and "job-states-reasons"
+ attributes, such as interpreter error information. Otherwise,
+ application programs might attempt to parse the (localized text).
+ For such additional information such as interpreter errors for
+ application program consumption, a new attribute with keyword values,
+ needs to be developed and registered.
+
+4.3.10 number-of-documents (integer(0:MAX))
+
+ This attribute indicates the number of documents in the job, i.e.,
+ the number of Send-Document, Send-URI, Print-Job, or Print-URI
+ operations that the Printer has accepted for this job, regardless of
+ whether the document data has reached the Printer object or not.
+
+ Implementations supporting the OPTIONAL Create-Job/Send-
+ Document/Send-URI operations SHOULD support this attribute so that
+ clients can query the number of documents in each job.
+
+4.3.11 output-device-assigned (name(127))
+
+ This attribute identifies the output device to which the Printer
+ object has assigned this job. If an output device implements an
+ embedded Printer object, the Printer object NEED NOT set this
+ attribute. If a print server implements a Printer object, the value
+ MAY be empty (zero-length string) or not returned until the Printer
+ object assigns an output device to the job. This attribute is
+ particularly useful when a single Printer object support multiple
+ devices (so called "fan-out").
+
+4.3.12 time-at-creation (integer(0:MAX))
+
+ This attribute indicates the point in time at which the Job object
+ was created. In order to populate this attribute, the Printer object
+ uses the value in its "printer-up-time" attribute at the time the Job
+ object is created.
+
+4.3.13 time-at-processing (integer(0:MAX))
+
+ This attribute indicates the point in time at which the Job object
+ began processing. In order to populate this attribute, the Printer
+ object uses the value in its "printer-up-time" attribute at the time
+ the Job object is moved into the 'processing' state for the first
+ time.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 93]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.3.14 time-at-completed (integer(0:MAX))
+
+ This attribute indicates the point in time at which the Job object
+ completed (or was cancelled or aborted). In order to populate this
+ attribute, the Printer object uses the value in its "printer-up-time"
+ attribute at the time the Job object is moved into the 'completed' or
+ 'canceled' or 'aborted' state.
+
+4.3.15 number-of-intervening-jobs (integer(0:MAX))
+
+ This attribute indicates the number of jobs that are "ahead" of this
+ job in the relative chronological order of expected time to complete
+ (i.e., the current scheduled order). For efficiency, it is only
+ necessary to calculate this value when an operation is performed that
+ requests this attribute.
+
+4.3.16 job-message-from-operator (text(127))
+
+ This attribute provides a message from an operator, system
+ administrator or "intelligent" process to indicate to the end user
+ the reasons for modification or other management action taken on a
+ job.
+
+4.3.17 job-k-octets (integer(0:MAX))
+
+ This attribute specifies the total size of the document(s) in K
+ octets, i.e., in units of 1024 octets requested to be processed in
+ the job. The value MUST be rounded up, so that a job between 1 and
+ 1024 octets MUST be indicated as being 1, 1025 to 2048 MUST be 2,
+ etc.
+
+ This value MUST NOT include the multiplicative factors contributed by
+ the number of copies specified by the "copies" attribute, independent
+ of whether the device can process multiple copies without making
+ multiple passes over the job or document data and independent of
+ whether the output is collated or not. Thus the value is independent
+ of the implementation and indicates the size of the document(s)
+ measured in K octets independent of the number of copies.
+
+ This value MUST also not include the multiplicative factor due to a
+ copies instruction embedded in the document data. If the document
+ data actually includes replications of the document data, this value
+ will include such replication. In other words, this value is always
+ the size of the source document data, rather than a measure of the
+ hardcopy output to be produced.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 94]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: This attribute and the following two attributes ("job-
+ impressions" and "job-media-sheets") are not intended to be counters;
+ they are intended to be useful routing and scheduling information if
+ known. For these three attributes, the Printer object may try to
+ compute the value if it is not supplied in the create request. Even
+ if the client does supply a value for these three attributes in the
+ create request, the Printer object MAY choose to change the value if
+ the Printer object is able to compute a value which is more accurate
+ than the client supplied value. The Printer object may be able to
+ determine the correct value for these three attributes either right
+ at job submission time or at any later point in time.
+
+4.3.18 job-impressions (integer(0:MAX))
+
+ This attribute specifies the total size in number of impressions of
+ the document(s) being submitted (see the definition of impression in
+ section 13.2.5).
+
+ As with "job-k-octets", this value MUST NOT include the
+ multiplicative factors contributed by the number of copies specified
+ by the "copies" attribute, independent of whether the device can
+ process multiple copies without making multiple passes over the job
+ or document data and independent of whether the output is collated or
+ not. Thus the value is independent of the implementation and
+ reflects the size of the document(s) measured in impressions
+ independent of the number of copies.
+
+ As with "job-k-octets", this value MUST also not include the
+ multiplicative factor due to a copies instruction embedded in the
+ document data. If the document data actually includes replications
+ of the document data, this value will include such replication. In
+ other words, this value is always the number of impressions in the
+ source document data, rather than a measure of the number of
+ impressions to be produced by the job.
+
+ See the Note in the "job-k-octets" attribute that also applies to
+ this attribute.
+
+4.3.19 job-media-sheets (integer(0:MAX))
+
+ This attribute specifies the total number of media sheets to be
+ produced for this job.
+
+ Unlike the "job-k-octets" and the "job-impressions" attributes, this
+ value MUST include the multiplicative factors contributed by the
+ number of copies specified by the "copies" attribute and a 'number of
+ copies' instruction embedded in the document data, if any. This
+ difference allows the system administrator to control the lower and
+
+
+
+deBry, et al. Experimental [Page 95]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ upper bounds of both (1) the size of the document(s) with "job-k-
+ octets-supported" and "job-impressions-supported" and (2) the size of
+ the job with "job-media-sheets-supported".
+
+ See the Note in the "job-k-octets" attribute that also applies to
+ this attribute.
+
+4.3.20 job-k-octets-processed (integer(0:MAX))
+
+ This attribute specifies the total number of octets processed in K
+ octets, i.e., in units of 1024 octets so far. The value MUST be
+ rounded up, so that a job between 1 and 1024 octets inclusive MUST be
+ indicated as being 1, 1025 to 2048 inclusive MUST be 2, etc.
+
+ For implementations where multiple copies are produced by the
+ interpreter with only a single pass over the data, the final value
+ MUST be equal to the value of the "job-k-octets" attribute. For
+ implementations where multiple copies are produced by the interpreter
+ by processing the data for each copy, the final value MUST be a
+ multiple of the value of the "job-k-octets" attribute.
+
+ Note: This attribute and the following two attributes ("job-
+ impressions-completed" and "job-sheets-completed") are intended to be
+ counters. That is, the value for a job that has not started
+ processing MUST be 0. When the job's "job-state" is 'processing' or
+ 'processing-stopped', this value is intended to contain the amount of
+ the job that has been processed to the time at which the attributes
+ are requested.
+
+4.3.21 job-impressions-completed (integer(0:MAX))
+
+ This job attribute specifies the number of impressions completed for
+ the job so far. For printing devices, the impressions completed
+ includes interpreting, marking, and stacking the output.
+
+ See the note in "job-k-octets-processed" which also applies to this
+ attribute.
+
+4.3.22 job-media-sheets-completed (integer(0:MAX))
+
+ This job attribute specifies the media-sheets completed marking and
+ stacking for the entire job so far whether those sheets have been
+ processed on one side or on both.
+
+ See the note in "job-k-octets-processed" which also applies to this
+ attribute.
+
+
+
+
+
+deBry, et al. Experimental [Page 96]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.3.23 attributes-charset (charset)
+
+ This REQUIRED attribute is populated using the value in the client
+ supplied "attributes-charset" attribute in the create request. It
+ identifies the charset (coded character set and encoding method) used
+ by any Job attributes with attribute syntax 'text' and 'name' that
+ were supplied by the client in the create request. See Section 3.1.4
+ for a complete description of the "attributes-charset" operation
+ attribute.
+
+ This attribute does not indicate the charset in which the 'text' and
+ 'name' values are stored internally in the Job object. The internal
+ charset is implementation-defined. The IPP object MUST convert from
+ whatever the internal charset is to that being requested in an
+ operation as specified in Section 3.1.4.
+
+4.3.24 attributes-natural-language (naturalLanguage)
+
+ This REQUIRED attribute is populated using the value in the client
+ supplied "attributes-natural-language" attribute in the create
+ request. It identifies the natural language used for any Job
+ attributes with attribute syntax 'text' and 'name' that were supplied
+ by the client in the create request. See Section 3.1.4 for a
+ complete description of the "attributes-natural-language" operation
+ attribute. See Sections 4.1.1.2 and 4.1.2.2 for how a Natural
+ Language Override may be supplied explicitly for each 'text' and '
+ name' attribute value that differs from the value identified by the
+ "attributes-natural-language" attribute.
+
+4.4 Printer Description Attributes
+
+ These attributes form the attribute group called "printer-
+ description". The following table summarizes these attributes, their
+ syntax, and whether or not they are REQUIRED for a Printer object to
+ support. If they are not indicated as REQUIRED, they are OPTIONAL.
+ The maximum size in octets for 'text' and 'name' attributes is
+ indicated in parenthesizes.
+
+ Note: How these attributes are set by an Administrator is outside the
+ scope of this specification.
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 97]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ +----------------------------+----------------------+----------------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+----------------------+----------------+
+ | printer-uri-supported | 1setOf uri | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | uri-security-supported | 1setOf type2 keyword | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | printer-name | name (127) | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | printer-location | text (127) | |
+ +----------------------------+----------------------+----------------+
+ | printer-info | text (127) | |
+ +----------------------------+----------------------+----------------+
+ | printer-more-info | uri | |
+ +----------------------------+----------------------+----------------+
+ | printer-driver-installer | uri | |
+ +----------------------------+----------------------+----------------+
+ | printer-make-and-model | text (127) | |
+ +----------------------------+----------------------+----------------+
+ | printer-more-info- | uri | |
+ | manufacturer | | |
+ +----------------------------+----------------------+----------------+
+ | printer-state | type1 enum | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | printer-state-reasons | 1setOf type2 keyword | |
+ +----------------------------+----------------------+----------------+
+ | printer-state-message | text (MAX) | |
+ +----------------------------+----------------------+----------------+
+ | operations-supported | 1setOf type2 enum | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | charset-configured | charset | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | charset-supported | 1setOf charset | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | natural-language-configured| naturalLanguage | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | generated-natural-language-| 1setOf | REQUIRED |
+ | supported | naturalLanguage | |
+ +----------------------------+----------------------+----------------+
+ | document-format-default | mimeMediaType | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | document-format- | 1setOf | REQUIRED |
+ | supported | mimeMediaType | |
+ +----------------------------+----------------------+----------------+
+ | printer-is-accepting-jobs | boolean | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | queued-job-count | integer (0:MAX) | RECOMMENDED |
+ +----------------------------+----------------------+----------------+
+
+
+
+deBry, et al. Experimental [Page 98]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ +----------------------------+----------------------+----------------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+----------------------+----------------+
+ | printer-message-from- | text (127) | |
+ | operator | | |
+ +----------------------------+----------------------+----------------+
+ | color-supported | boolean | |
+ +----------------------------+----------------------+----------------+
+ | reference-uri-schemes- | 1setOf uriScheme | |
+ | supported | | |
+ +----------------------------+----------------------+----------------+
+ | pdl-override-supported | type2 keyword | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | printer-up-time | integer (1:MAX) | REQUIRED |
+ +----------------------------+----------------------+----------------+
+ | printer-current-time | dateTime | |
+ +----------------------------+----------------------+----------------+
+ | multiple-operation-time-out| integer (1:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | compression-supported | 1setOf type3 keyword | |
+ +----------------------------+----------------------+----------------+
+ | job-k-octets-supported | rangeOfInteger | |
+ | | (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-impressions-supported | rangeOfInteger | |
+ | | (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+ | job-media-sheets-supported | rangeOfInteger | |
+ | | (0:MAX) | |
+ +----------------------------+----------------------+----------------+
+
+4.4.1 printer-uri-supported (1setOf uri)
+
+ This REQUIRED Printer attribute contains at least one URI for the
+ Printer object. It OPTIONALLY contains more than one URI for the
+ Printer object. An administrator determines a Printer object's
+ URI(s) and configures this attribute to contain those URIs by some
+ means outside the scope of IPP/1.0. The precise format of this URI
+ is implementation dependent and depends on the protocol. See the
+ next section for a description "uri-security-supported" which is the
+ REQUIRED companion attribute to this "printer-uri-supported"
+ attribute. See section 2.4 on Printer object identity and section
+ 8.2 on security and URIs for more information.
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 99]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.4.2 uri-security-supported (1setOf type2 keyword)
+
+ This REQUIRED Printer attribute MUST have the same cardinality
+ (contain the same number of values) as the "printer-uri-supported"
+ attribute. This attribute identifies the security mechanisms used
+ for each URI listed in the "printer-uri-supported" attribute. The "i
+ th" value in "uri-security-supported" corresponds to the "i th" value
+ in "printer-uri-supported" and it describes the security mechanisms
+ used for accessing the Printer object via that URI. The following
+ standard values are defined:
+
+ 'none': There are no secure communication channel protocols in use
+ for the given URI.
+
+ 'ssl3': SSL3 [SSL] is the secure communications channel protocol in
+ use for the given URI.
+
+ Consider the following example. For a single Printer object, an
+ administrator configures the "printer-uri-supported" and "uri-
+ security-supported" attributes as follows:
+
+ "printer-uri-supported": 'http://acme.com/open-use-printer', '
+ http://acme.com/restricted-use-printer', '
+ http://acme.com/private-printer'
+ "uri-security-supported": 'none', 'none', 'ssl3'
+
+ In this case, one Printer object has three URIs.
+
+ - For the first URI, 'http://acme.com/open-use-printer', the value
+ 'none' in "uri-security-supported" indicates that there is no
+ secure channel protocol configured to run under HTTP. The name
+ implies that there is no Basic or Digest authentication being
+ used, but it is up to the client to determine that while using
+ HTTP underneath the IPP application protocol.
+ - For the second URI, 'http://acme.com/restricted-use-printer', the
+ value 'none' in "uri-security-supported" indicates that there is
+ no secure channel protocol configured to run under HTTP. In
+ this case, although the name does imply that there is some sort
+ of Basic or Digest authentication being used within HTTP, it is
+ up to the client to determine that while using HTTP and by
+ processing any '401 Unauthorized' HTTP error messages.
+ - For the third URI, 'http://acme.com/private-printer', the value '
+ ssl3' in "uri-security-supported" indicates that SSL3 is being
+ used to secure the channel. The client SHOULD be prepared to
+ use SSL3 framing to negotiate an acceptable ciphersuite to use
+ while communicating with the Printer object. In this case, the
+ name implies the use of a secure communications channel, but the
+ fact is made explicit by the presence of the 'ssl3' value in
+
+
+
+deBry, et al. Experimental [Page 100]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "uri-security-supported". The client does not need to resort to
+ understanding which security it must use by following naming
+ conventions or by parsing the URI to determine which security
+ mechanisms are implied.
+
+ It is expected that many IPP Printer objects will be configured to
+ support only one channel (either configured to use SSL3 access or
+ not), and will therefore only ever have one URI listed in the
+ "printer-uri-supported" attribute. No matter the configuration of
+ the Printer object (whether it has only one URI or more than one
+ URI), a client MUST supply only one URI in the target "printer-uri"
+ operation attribute.
+
+4.4.3 printer-name (name(127))
+
+ This REQUIRED Printer attribute contains the name of the Printer
+ object. It is a name that is more end-user friendly than a URI. An
+ administrator determines a printer's name and sets this attribute to
+ that name. This name may be the last part of the printer's URI or it
+ may be unrelated. In non-US-English locales, a name may contain
+ characters that are not allowed in a URI.
+
+4.4.4 printer-location (text(127))
+
+ This Printer attribute identifies the location of the device. This
+ could include things like: "in Room 123A, second floor of building
+ XYZ".
+
+4.4.5 printer-info (text(127))
+
+ This Printer attribute identifies the descriptive information about
+ this Printer object. This could include things like: "This printer
+ can be used for printing color transparencies for HR presentations",
+ or "Out of courtesy for others, please print only small (1-5 page)
+ jobs at this printer", or even "This printer is going away on July 1,
+ 1997, please find a new printer".
+
+4.4.6 printer-more-info (uri)
+
+ This Printer attribute contains a URI used to obtain more information
+ about this specific Printer object. For example, this could be an
+ HTTP type URI referencing an HTML page accessible to a Web Browser.
+ The information obtained from this URI is intended for end user
+ consumption. Features outside the scope of IPP can be accessed from
+ this URI. The information is intended to be specific to this printer
+ instance and site specific services (e.g. job pricing, services
+ offered, end user assistance). The device manufacturer may initially
+ populate this attribute.
+
+
+
+deBry, et al. Experimental [Page 101]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+4.4.7 printer-driver-installer (uri)
+
+ This Printer attribute contains a URI to use to locate the driver
+ installer for this Printer object. This attribute is intended for
+ consumption by automata. The mechanics of print driver installation
+ is outside the scope of IPP. The device manufacturer may initially
+ populate this attribute.
+
+4.4.8 printer-make-and-model (text(127))
+
+ This Printer attribute identifies the make and model of the device.
+ The device manufacturer may initially populate this attribute.
+
+4.4.9 printer-more-info-manufacturer (uri)
+
+ This Printer attribute contains a URI used to obtain more information
+ about this type of device. The information obtained from this URI is
+ intended for end user consumption. Features outside the scope of IPP
+ can be accessed from this URI (e.g., latest firmware, upgrades, print
+ drivers, optional features available, details on color support). The
+ information is intended to be germane to this printer without regard
+ to site specific modifications or services. The device manufacturer
+ may initially populate this attribute.
+
+4.4.10 printer-state (type1 enum)
+
+ This REQUIRED Printer attribute identifies the current state of the
+ device. The "printer-state reasons" attribute augments the
+ "printer-state" attribute to give more detailed information about the
+ Printer in the given printer state.
+
+ A Printer object need only update this attribute before responding to
+ an operation which requests the attribute; the Printer object NEED
+ NOT update this attribute continually, since asynchronous event
+ notification is not part of IPP/1.0. A Printer NEED NOT implement
+ all values if they are not applicable to a given implementation.
+
+ The following standard enum values are defined:
+
+ Value Symbolic Name and Description
+
+ '3' 'idle': If a Printer receives a job (whose required
+ resources are ready) while in this state, such a job
+ MUST transit into the 'processing' state immediately.
+ If the "printer-state-reasons" attribute contains any
+ reasons, they MUST be reasons that would not prevent a
+ job from transiting into the 'processing' state
+ immediately, e.g., 'toner-low'. Note: if a Printer
+
+
+
+deBry, et al. Experimental [Page 102]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ controls more than one output device, the above
+ definition implies that a Printer is 'idle' if at
+ least one output device is idle.
+
+ '4' 'processing': If a Printer receives a job (whose required
+ resources are ready) while in this state, such a job
+ MUST transit into the 'pending' state immediately.
+ Such a job MUST transit into the 'processing' state
+ only after jobs ahead of it complete. If the
+ "printer-state-reasons" attribute contains any
+ reasons, they MUST be reasons that do not prevent the
+ current job from printing, e.g. 'toner-low'. Note:
+ if a Printer controls more than one output device, the
+ above definition implies that a Printer is '
+ processing' if at least one output device is
+ processing, and none is idle.
+
+ '5' 'stopped': If a Printer receives a job (whose required
+ resources are ready) while in this state, such a job
+ MUST transit into the 'pending' state immediately.
+ Such a job MUST transit into the 'processing' state
+ only after some human fixes the problem that stopped
+ the printer and after jobs ahead of it complete
+ processing. If supported, the "printer-state-reasons"
+ attribute MUST contain at least one reason, e.g. '
+ media-jam', which prevents it from either processing
+ the current job or transitioning a 'pending' job to
+ the 'processing' state.
+
+ Note: if a Printer controls more than one output
+ device, the above definition implies that a Printer is
+ 'stopped' only if all output devices are stopped.
+ Also, it is tempting to define 'stopped' as when a
+ sufficient number of output devices are stopped and
+ leave it to an implementation to define the sufficient
+ number. But such a rule complicates the definition of
+ 'stopped' and 'processing'. For example, with this
+ alternate definition of 'stopped', a job can move from
+ 'pending' to 'processing' without human intervention,
+ even though the Printer is stopped.
+
+4.4.11 printer-state-reasons (1setOf type2 keyword)
+
+ This Printer attribute supplies additional detail about the device's
+ state.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 103]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Each keyword value MAY have a suffix to indicate its level of
+ severity. The three levels are: report (least severe), warning, and
+ error (most severe).
+
+ - '-report': This suffix indicates that the reason is a "report".
+ An implementation may choose to omit some or all reports. Some
+ reports specify finer granularity about the printer state;
+ others serve as a precursor to a warning. A report MUST contain
+ nothing that could affect the printed output.
+ - '-warning': This suffix indicates that the reason is a "warning".
+ An implementation may choose to omit some or all warnings.
+ Warnings serve as a precursor to an error. A warning MUST
+ contain nothing that prevents a job from completing, though in
+ some cases the output may be of lower quality.
+ - '-error': This suffix indicates that the reason is an "error".
+ An implementation MUST include all errors. If this attribute
+ contains one or more errors, printer MUST be in the stopped
+ state.
+
+ If the implementation does not add any one of the three suffixes, all
+ parties MUST assume that the reason is an "error".
+
+ If a Printer object controls more than one output device, each value
+ of this attribute MAY apply to one or more of the output devices. An
+ error on one output device that does not stop the Printer object as a
+ whole MAY appear as a warning in the Printer's "printer-state-reasons
+ attribute". If the "printer-state" for such a Printer has a value of
+ 'stopped', then there MUST be an error reason among the values in the
+ "printer-state-reasons" attribute.
+
+ The following standard keyword values are defined:
+
+ 'other': The device has detected an error other than one listed in
+ this document.
+ 'none': There are not reasons. This state reason is semantically
+ equivalent to "printer-state-reasons" without any value.
+ 'media-needed': A tray has run out of media.
+ 'media-jam': The device has a media jam.
+ 'paused': Someone has paused the Printer object. In this state, a
+ Printer MUST NOT produce printed output, but it MUST perform
+ other operations requested by a client. If a Printer had been
+ printing a job when the Printer was paused, the Printer MUST
+ resume printing that job when the Printer is no longer paused
+ and leave no evidence in the printed output of such a pause.
+ 'shutdown': Someone has removed a Printer object from service, and
+ the device may be powered down or physically removed. In this
+ state, a Printer object MUST NOT produce printed output, and
+ unless the Printer object is realized by a print server that is
+
+
+
+deBry, et al. Experimental [Page 104]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ still active, the Printer object MUST perform no other
+ operations requested by a client, including returning this
+ value. If a Printer object had been printing a job when it was
+ shutdown, the Printer NEED NOT resume printing that job when the
+ Printer is no longer shutdown. If the Printer resumes printing
+ such a job, it may leave evidence in the printed output of such
+ a shutdown, e.g. the part printed before the shutdown may be
+ printed a second time after the shutdown.
+ 'connecting-to-device': The Printer object has scheduled a job on
+ the output device and is in the process of connecting to a
+ shared network output device (and might not be able to actually
+ start printing the job for an arbitrarily long time depending on
+ the usage of the output device by other servers on the network).
+ 'timed-out': The server was able to connect to the output device
+ (or is always connected), but was unable to get a response from
+ the output device.
+ 'stopping': The Printer object is in the process of stopping the
+ device and will be stopped in a while. When the device is
+ stopped, the Printer object will change the Printer object's
+ state to 'stopped'. The 'stopping-warning' reason is never an
+ error, even for a Printer with a single output device. When an
+ output-device ceases accepting jobs, the Printer will have this
+ reason while the output device completes printing.
+ 'stopped-partly': When a Printer object controls more than one
+ output device, this reason indicates that one or more output
+ devices are stopped. If the reason is a report, fewer than half
+ of the output devices are stopped. If the reason is a warning,
+ fewer than all of the output devices are stopped.
+ 'toner-low': The device is low on toner.
+ 'toner-empty': The device is out of toner.
+ 'spool-area-full': The limit of persistent storage allocated for
+ spooling has been reached.
+ 'cover-open': One or more covers on the device are open.
+ 'interlock-open': One or more interlock devices on the printer are
+ unlocked.
+ 'door-open': One or more doors on the device are open.
+ 'input-tray-missing': One or more input trays are not in the
+ device.
+ 'media-low': At least one input tray is low on media.
+ 'media-empty': At least one input tray is empty.
+ 'output-tray-missing': One or more output trays are not in the
+ device
+ 'output-area-almost-full': One or more output area is almost full
+ (e.g. tray, stacker, collator).
+ 'output-area-full': One or more output area is full. (e.g. tray,
+ stacker, collator)
+ 'marker-supply-low': The device is low on at least one marker
+ supply. (e.g. toner, ink, ribbon)
+
+
+
+deBry, et al. Experimental [Page 105]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'marker-supply-empty: The device is out of at least one marker
+ supply. (e.g. toner, ink, ribbon)
+ 'marker-waste-almost-full': The device marker supply waste
+ receptacle is almost full.
+ 'marker-waste-full': The device marker supply waste receptacle is
+ full.
+ 'fuser-over-temp': The fuser temperature is above normal.
+ 'fuser-under-temp': The fuser temperature is below normal.
+ 'opc-near-eol': The optical photo conductor is near end of life.
+ 'opc-life-over': The optical photo conductor is no longer
+ functioning.
+ 'developer-low': The device is low on developer.
+ 'developer-empty: The device is out of developer.
+ 'interpreter-resource-unavailable': An interpreter resource is
+ unavailable (i.e. font, form)
+
+4.4.12 printer-state-message (text(MAX))
+
+ This Printer attribute specifies the additional information about the
+ printer state and printer state reasons in human readable text. If
+ the Printer object supports this attribute, the Printer object MUST
+ be able to generate this message in any of the natural languages
+ identified by the Printer's "generated-natural-language-supported"
+ attribute (see the "attributes-natural-language" operation attribute
+ specified in Section 3.1.4.1).
+
+4.4.13 operations-supported (1setOf type2 enum)
+
+ This REQUIRED Printer attribute specifies the set of supported
+ operations for this Printer object and contained Job objects. All
+ 32-bit enum values for this attribute MUST NOT exceed 0x8FFF, since
+ these values are passed in two octets in each Protocol request
+ [RFC2565].
+
+ The following standard enum and "operation-id" (see section 3.1.2)
+ values are defined:
+
+ Value Operation Name
+ ----------------- -------------------------------------
+
+ 0x0000 reserved, not used
+ 0x0001 reserved, not used
+ 0x0002 Print-Job
+ 0x0003 Print-URI
+ 0x0004 Validate-Job
+ 0x0005 Create-Job
+ 0x0006 Send-Document
+ 0x0007 Send-URI
+
+
+
+deBry, et al. Experimental [Page 106]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 0x0008 Cancel-Job
+ 0x0009 Get-Job-Attributes
+ 0x000A Get-Jobs
+ 0x000B Get-Printer-Attributes
+ 0x000C-0x3FFF reserved for future operations
+ 0x4000-0x8FFF reserved for private extensions
+
+ This allows for certain vendors to implement private extensions that
+ are guaranteed to not conflict with future registered extensions.
+ However, there is no guarantee that two or more private extensions
+ will not conflict.
+
+4.4.14 charset-configured (charset)
+
+ This REQUIRED Printer attribute identifies the charset that the
+ Printer object has been configured to represent 'text' and 'name'
+ Printer attributes that are set by the operator, system
+ administrator, or manufacturer, i.e., for "printer-name" (name),
+ "printer-location" (text), "printer-info" (text), and "printer-make-
+ and-model" (text). Therefore, the value of the Printer object's
+ "charset-configured" attribute MUST also be among the values of the
+ Printer object's "charset-supported" attribute.
+
+4.4.15 charset-supported (1setOf charset)
+
+ This REQUIRED Printer attribute identifies the set of charsets that
+ the Printer and contained Job objects support in attributes with
+ attribute syntax 'text' and 'name'. At least the value 'utf-8' MUST
+ be present, since IPP objects MUST support the UTF-8 [RFC2279]
+ charset. If a Printer object supports a charset, it means that for
+ all attributes of syntax 'text' and 'name' the IPP object MUST (1)
+ accept the charset in requests and return the charset in responses as
+ needed.
+
+ If more charsets than UTF-8 are supported, the IPP object MUST
+ perform charset conversion between the charsets as described in
+ Section 3.2.1.2.
+
+4.4.16 natural-language-configured (naturalLanguage)
+
+ This REQUIRED Printer attribute identifies the natural language that
+ the Printer object has been configured to represent 'text' and 'name'
+ Printer attributes that are set by the operator, system
+ administrator, or manufacturer, i.e., for "printer-name" (name),
+ "printer-location" (text), "printer-info" (text), and "printer-make-
+ and-model" (text). When returning these Printer attributes, the
+ Printer object MAY return them in the configured natural language
+ specified by this attribute, instead of the natural language
+
+
+
+deBry, et al. Experimental [Page 107]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ requested by the client in the "attributes-natural-language"
+ operation attribute. See Section 3.1.4.1 for the specification of
+ the OPTIONAL multiple natural language support. Therefore, the value
+ of the Printer object's "natural-language-configured" attribute MUST
+ also be among the values of the Printer object's "generated-natural-
+ language-supported" attribute.
+
+4.4.17 generated-natural-language-supported (1setOf naturalLanguage)
+
+ This REQUIRED Printer attribute identifies the natural language(s)
+ that the Printer object and contained Job objects support in
+ attributes with attribute syntax 'text' and 'name'. The natural
+ language(s) supported depends on implementation and/or configuration.
+ Unlike charsets, IPP objects MUST accept requests with any natural
+ language or any Natural Language Override whether the natural
+ language is supported or not.
+
+ If a Printer object supports a natural language, it means that for
+ any of the attributes for which the Printer or Job object generates
+ messages, i.e., for the "job-state-message" and "printer-state-
+ message" attributes and Operation Messages (see Section 3.1.5) in
+ operation responses, the Printer and Job objects MUST be able to
+ generate messages in any of the Printer's supported natural
+ languages. See section 3.1.4 for the specification of 'text' and '
+ name' attributes in operation requests and responses.
+
+ Note: A Printer object that supports multiple natural languages,
+ often has separate catalogs of messages, one for each natural
+ language supported.
+
+4.4.18 document-format-default (mimeMediaType)
+
+ This REQUIRED Printer attribute identifies the document format that
+ the Printer object has been configured to assume if the client does
+ not supply a "document-format" operation attribute in any of the
+ operation requests that supply document data. The standard values
+ for this attribute are Internet Media types (sometimes called MIME
+ types). For further details see the description of the '
+ mimeMediaType' attribute syntax in Section 4.1.9.
+
+4.4.19 document-format-supported (1setOf mimeMediaType)
+
+ This REQUIRED Printer attribute identifies the set of document
+ formats that the Printer object and contained Job objects can
+ support. For further details see the description of the '
+ mimeMediaType' attribute syntax in Section 4.1.9.
+
+4.4.20 printer-is-accepting-jobs (boolean)
+
+
+
+deBry, et al. Experimental [Page 108]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ This REQUIRED Printer attribute indicates whether the printer is
+ currently able to accept jobs, i.e., is accepting Print-Job, Print-
+ URI, and Create-Job requests. If the value is 'true', the printer is
+ accepting jobs. If the value is 'false', the Printer object is
+ currently rejecting any jobs submitted to it. In this case, the
+ Printer object returns the 'server-error-not-accepting-jobs' status
+ code.
+
+ Note: This value is independent of the "printer-state" and "printer-
+ state-reasons" attributes because its value does not affect the
+ current job; rather it affects future jobs. This attribute may cause
+ the Printer to reject jobs when the "printer-state" is 'idle' or it
+ may cause the Printer object to accepts jobs when the "printer-state"
+ is 'stopped'.
+
+4.4.21 queued-job-count (integer(0:MAX))
+
+ This RECOMMENDED Printer attribute contains a count of the number of
+ jobs that are either 'pending', 'processing', 'pending-held', or '
+ processing-stopped' and is set by the Printer object.
+
+4.4.22 printer-message-from-operator (text(127))
+
+ This Printer attribute provides a message from an operator, system
+ administrator or "intelligent" process to indicate to the end user
+ information or status of the printer, such as why it is unavailable
+ or when it is expected to be available.
+
+4.4.23 color-supported (boolean)
+
+ This Printer attribute identifies whether the device is capable of
+ any type of color printing at all, including highlight color. All
+ document instructions having to do with color are embedded within the
+ document PDL (none are external IPP attributes in IPP/1.0).
+
+ Note: end-users are able to determine the nature and details of the
+ color support by querying the "printer-more-info-manufacturer"
+ Printer attribute.
+
+4.4.24 reference-uri-schemes-supported (1setOf uriScheme)
+
+ This Printer attribute specifies which URI schemes are supported for
+ use in the "document-uri" operation attribute of the Print-URI or
+ Send-URI operation. If a Printer object supports these optional
+ operations, it MUST support the "reference-uri-schemes-supported"
+ Printer attribute with at least the following schemed URI value:
+
+ 'ftp': The Printer object will use an FTP 'get' operation as
+
+
+
+deBry, et al. Experimental [Page 109]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ defined in RFC 2228 [RFC2228] using FTP URLs as defined by
+ [RFC2396] and[RFC2316].
+
+ The Printer object MAY OPTIONALLY support other URI schemes (see
+ section 4.1.6).
+
+4.4.25 pdl-override-supported (type2 keyword)
+
+ This REQUIRED Printer attribute expresses the ability for a
+ particular Printer implementation to either attempt to override
+ document data instructions with IPP attributes or not.
+
+ This attribute takes on the following values:
+
+ - 'attempted': This value indicates that the Printer object
+ attempts to make the IPP attribute values take precedence over
+ embedded instructions in the document data, however there is no
+ guarantee.
+
+ - 'not-attempted': This value indicates that the Printer object
+ makes no attempt to make the IPP attribute values take precedence
+ over embedded instructions in the document data.
+
+ Section 15 contains a full description of how this attribute
+ interacts with and affects other IPP attributes, especially the
+ "ipp-attribute-fidelity" attribute.
+
+4.4.26 printer-up-time (integer(1:MAX))
+
+ This REQUIRED Printer attribute indicates the amount of time (in
+ seconds) that this instance of this Printer implementation has been
+ up and running. This value is used to populate the Job attributes
+ "time-at-creation", "time-at-processing", and "time-at-completed".
+ These time values are all measured in seconds and all have meaning
+ only relative to this attribute, "printer-up-time". The value is a
+ monotonically increasing value starting from 1 when the Printer
+ object is started-up (initialized, booted, etc.).
+
+ If the Printer object goes down at some value 'n', and comes back up,
+ the implementation MAY:
+
+ 1. Know how long it has been down, and resume at some value greater
+ than 'n', or
+ 2. Restart from 1.
+
+ In the first case, the Printer SHOULD not tweak any existing related
+ Job attributes ("time-at-creation", "time-at-processing", and "time-
+ at-completed"). In the second case, the Printer object SHOULD reset
+
+
+
+deBry, et al. Experimental [Page 110]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ those attributes to 0. If a client queries a time-related Job
+ attribute and finds the value to be 0, the client MUST assume that
+ the Job was submitted in some life other than the Printer's current
+ life.
+
+4.4.27 printer-current-time (dateTime)
+
+ This Printer attribute indicates the current absolute wall-clock
+ time. If an implementation supports this attribute, then a client
+ could calculate the absolute wall-clock time each Job's "time-at-
+ creation", "time-at-processing", and "time-at-completed" attributes
+ by using both "printer-up-time" and this attribute, "printer-
+ current-time". If an implementation does not support this attribute,
+ a client can only calculate the relative time of certain events based
+ on the REQUIRED "printer-up-time" attribute.
+
+4.4.28 multiple-operation-time-out (integer(1:MAX))
+
+ This Printer attributes identifies the minimum time (in seconds) that
+ the Printer object waits for additional Send-Document or Send-URI
+ operations to follow a still-open multi-document Job object before
+ taking any recovery actions, such as the ones indicated in section
+ 3.3.1.
+
+ It is RECOMMENDED that vendors supply a value for this attribute that
+ is between 60 and 240 seconds. An implementation MAY allow a system
+ administrator to set this attribute. If so, the system administrator
+ MAY be able to set values outside this range.
+
+4.4.29 compression-supported (1setOf type3 keyword)
+
+ This Printer attribute identifies the set of supported compression
+ algorithms for document data. Compression only applies to the
+ document data; compression does not apply to the encoding of the IPP
+ operation itself. The supported values are used to validate the
+ client supplied "compression" operation attributes in Print-Job,
+ Send-Document, and Send-URI requests.
+
+ Standard values are :
+
+ 'none': no compression is used.
+ 'deflate': ZIP public domain inflate/deflate) compression
+ technology
+ 'gzip' GNU zip compression technology described in RFC 1952
+ [RFC1952].
+ 'compress': UNIX compression technology
+
+4.4.30 job-k-octets-supported (rangeOfInteger(0:MAX))
+
+
+
+deBry, et al. Experimental [Page 111]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ This Printer attribute specifies the upper and lower bounds of total
+ sizes of jobs in K octets, i.e., in units of 1024 octets. The
+ supported values are used to validate the client supplied "job-k-
+ octets" operation attributes in create requests. The corresponding
+ job description attribute "job-k-octets" is defined in section
+ 4.3.17.
+
+ 4.4.31 job-impressions-supported (rangeOfInteger(0:MAX))
+
+ This Printer attribute specifies the upper and lower bounds for the
+ number of impressions per job. The supported values are used to
+ validate the client supplied "job-impressions" operation attributes
+ in create requests. The corresponding job description attribute
+ "job-impressions" is defined in section 4.3.18.
+
+4.4.32 job-media-sheets-supported (rangeOfInteger(0:MAX))
+
+ This Printer attribute specifies the upper and lower bounds for the
+ number of media sheets per job. The supported values are used to
+ validate the client supplied "job-media-sheets" operation attributes
+ in create requests. The corresponding Job attribute "job-media-
+ sheets" is defined in section 4.3.19.
+
+5. Conformance
+
+ This section describes conformance issues and requirements. This
+ document introduces model entities such as objects, operations,
+ attributes, attribute syntaxes, and attribute values. These
+ conformance sections describe the conformance requirements which
+ apply to these model entities.
+
+5.1 Client Conformance Requirements
+
+ A conforming client MUST support all REQUIRED operations as defined
+ in this document. For each attribute included in an operation
+ request, a conforming client MUST supply a value whose type and value
+ syntax conforms to the requirements of the Model document as
+ specified in Sections 3 and 4. A conforming client MAY supply any
+ registered extensions and/or private extensions in an operation
+ request, as long as they meet the requirements in Section 6.
+
+ Otherwise, there are no conformance requirements placed on the user
+ interfaces provided by IPP clients or their applications. For
+ example, one application might not allow an end user to submit
+ multiple documents per job, while another does. One application
+ might first query a Printer object in order to supply a graphical
+ user interface (GUI) dialogue box with supported and default values
+ whereas a different implementation might not.
+
+
+
+deBry, et al. Experimental [Page 112]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ When sending a request, an IPP client NEED NOT supply any attributes
+ that are indicated as OPTIONALLY supplied by the client.
+
+ A client MUST be able to accept any of the attribute syntaxes defined
+ in Section 4.1, including their full range, that may be returned to
+ it in a response from a Printer object. In particular for each
+ attribute that the client supports whose attribute syntax is 'text',
+ the client MUST accept and process both the 'textWithoutLanguage' and
+ 'textWithLanguage' forms. Similarly, for each attribute that the
+ client supports whose attribute syntax is 'name', the client MUST
+ accept and process both the 'nameWithoutLanguage' and '
+ nameWithLanguage' forms. For presentation purposes, truncation of
+ long attribute values is not recommended. A recommended approach
+ would be for the client implementation to allow the user to scroll
+ through long attribute values.
+
+ A query response may contain attribute groups, attributes, and values
+ that the client does not expect. Therefore, a client implementation
+ MUST gracefully handle such responses and not refuse to inter-operate
+ with a conforming Printer that is returning extended registered or
+ private attributes and/or attribute values that conform to Section 6.
+ Clients may choose to ignore any parameters, attributes, or values
+ that they do not understand.
+
+5.2 IPP Object Conformance Requirements
+
+ This section specifies the conformance requirements for conforming
+ implementations with respect to objects, operations, and attributes.
+
+5.2.1 Objects
+
+ Conforming implementations MUST implement all of the model objects as
+ defined in this specification in the indicated sections:
+
+ Section 2.1 - Printer Object
+ Section 2.2 - Job Object
+
+5.2.2 Operations
+
+ Conforming IPP object implementations MUST implement all of the
+ REQUIRED model operations, including REQUIRED responses, as defined
+ in this specification in the indicated sections:
+
+ For a Printer object:
+ Print-Job (section 3.2.1) REQUIRED
+ Print-URI (section 3.2.2) OPTIONAL
+ Validate-Job (section 3.2.3) REQUIRED
+ Create-Job (section 3.2.4) OPTIONAL
+
+
+
+deBry, et al. Experimental [Page 113]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Get-Printer-Attributes (section 3.2.5) REQUIRED
+ Get-Jobs (section 3.2.6) REQUIRED
+
+ For a Job object:
+ Send-Document (section 3.3.1) OPTIONAL
+ Send-URI (section 3.3.2) OPTIONAL
+ Cancel-Job (section 3.3.3) REQUIRED
+ Get-Job-Attributes (section 3.3.4) REQUIRED
+
+ Conforming IPP objects MUST support all REQUIRED operation attributes
+ and all values of such attributes if so indicated in the description.
+ Conforming IPP objects MUST ignore all unsupported or unknown
+ operation attributes or operation attribute groups received in a
+ request, but MUST reject a request that contains a supported
+ operation attribute that contains an unsupported value.
+
+ The following section on object attributes specifies the support
+ required for object attributes.
+
+5.2.3 IPP Object Attributes
+
+ Conforming IPP objects MUST support all of the REQUIRED object
+ attributes, as defined in this specification in the indicated
+ sections.
+
+ If an object supports an attribute, it MUST support only those values
+ specified in this document or through the extension mechanism
+ described in section 5.2.4. It MAY support any non-empty subset of
+ these values. That is, it MUST support at least one of the specified
+ values and at most all of them.
+
+5.2.4 Extensions
+
+ A conforming IPP object MAY support registered extensions and private
+ extensions, as long as they meet the requirements specified in
+ Section 6.
+
+ For each attribute included in an operation response, a conforming
+ IPP object MUST return a value whose type and value syntax conforms
+ to the requirement of the Model document as specified in Sections 3
+ and 4.
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 114]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+5.2.5 Attribute Syntaxes
+
+ An IPP object MUST be able to accept any of the attribute syntaxes
+ defined in Section 4.1, including their full range, in any operation
+ in which a client may supply attributes or the system administrator
+ may configure attributes (by means outside the scope of IPP/1.0). In
+ particular for each attribute that the IPP object supports whose
+ attribute syntax is 'text', the IPP object MUST accept and process
+ both the 'textWithoutLanguage' and 'textWithLanguage' forms.
+ Similarly, for each attribute that the IPP object supports whose
+ attribute syntax is 'name', the IPP object MUST accept and process
+ both the 'nameWithoutLanguage' and 'nameWithLanguage' forms.
+ Furthermore, an IPP object MUST return attributes to the client in
+ operation responses that conform to the syntax specified in Section
+ 4.1, including their full range if supplied previously by a client.
+
+5.3 Charset and Natural Language Requirements
+
+ All clients and IPP objects MUST support the 'utf-8' charset as
+ defined in section 4.1.7.
+
+ IPP objects MUST be able to accept any client request which correctly
+ uses the "attributes-natural-language" operation attribute or the
+ Natural Language Override mechanism on any individual attribute
+ whether or not the natural language is supported by the IPP object.
+ If an IPP object supports a natural language, then it MUST be able to
+ translate (perhaps by table lookup) all generated 'text' or 'name'
+ attribute values into one of the supported languages (see section
+ 3.1.4). That is, the IPP object that supports a natural language
+ NEED NOT be a general purpose translator of any arbitrary 'text' or '
+ name' value supplied by the client into that natural language.
+ However, the object MUST be able to translate (automatically
+ generate) any of its own attribute values and messages into that
+ natural language.
+
+5.4 Security Conformance Requirements
+
+ Conforming IPP Printer objects MAY support Secure Socket Layer
+ Version 3 (SSL3) [SSL] access, support access without SSL3 or support
+ both means of access.
+
+ Conforming IPP clients SHOULD support SSL3 access and non-SSL3
+ access. Note: This client requirement to support both means that
+ conforming IPP clients will be able to inter-operate with any IPP
+ Printer object.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 115]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ For a detailed discussion of security considerations and the IPP
+ application security profile required for SSL3 support, see section
+ 8.
+
+6. IANA Considerations (registered and private extensions)
+
+ This section describes how IPP can be extended to allow the following
+ registered and private extensions to IPP:
+
+ 1. keyword attribute values
+ 2. enum attribute values
+ 3. attributes
+ 4. attribute syntaxes
+ 5. operations
+ 6. attribute groups
+ 7. status codes
+
+ Extensions registered for use with IPP/1.0 are OPTIONAL for client
+ and IPP object conformance to the IPP/1.0 Model specification.
+
+ These extension procedures are aligned with the guidelines as set
+ forth by the IESG [RFC2434]. Section 11 describes how to propose new
+ registrations for consideration. IANA will reject registration
+ proposals that leave out required information or do not follow the
+ appropriate format described in Section 11. IPP/1.0 may also be
+ extended by an appropriate RFC that specifies any of the above
+ extensions.
+
+6.1 Typed 'keyword' and 'enum' Extensions
+
+ IPP allows for 'keyword' and 'enum' extensions (see sections 4.1.2.3
+ and 4.1.4). This document uses prefixes to the 'keyword' and 'enum'
+ basic attribute syntax type in order to communicate extra information
+ to the reader through its name. This extra information is not
+ represented in the protocol because it is unimportant to a client or
+ Printer object. The list below describes the prefixes and their
+ meaning.
+
+ "type1": The IPP specification must be revised to add a new
+ keyword or a new enum. No private keywords or enums are
+ allowed.
+
+ "type2": Implementers can, at any time, add new keyword or enum
+ values by proposing the complete specification to IANA:
+
+ iana@iana.org
+
+
+
+
+
+deBry, et al. Experimental [Page 116]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ IANA will forward the registration proposal to the IPP
+ Designated Expert who will review the proposal with a mailing
+ list that the Designated Expert keeps for this purpose.
+ Initially, that list will be the mailing list used by the IPP
+ WG:
+
+ ipp@pwg.org
+
+ even after the IPP WG is disbanded as permitted by [RFC2434].
+ The IPP Designated Expert is appointed by the IESG Area Director
+ responsible for IPP, according to [RFC2434].
+
+ When a type2 keyword or enum is approved, the IPP Designated
+ Expert becomes the point of contact for any future maintenance
+ that might be required for that registration.
+
+ "type3": Implementers can, at any time, add new keyword and enum
+ values by submitting the complete specification to IANA as for
+ type2 who will forward the proposal to the IPP Designated
+ Expert. While no additional technical review is required, the
+ IPP Designated Expert may, at his/her discretion, forward the
+ proposal to the same mailing list as for type2 registrations for
+ advice and comment.
+
+ When a type3 keyword or enum is approved by the IPP Designated
+ Expert, the original proposer becomes the point of contact for
+ any future maintenance that might be required for that
+ registration.
+
+ For type2 and type3 keywords, the proposer includes the name of the
+ keyword in the registration proposal and the name is part of the
+ technical review.
+
+ After type2 and type3 enums specifications are approved, the IPP
+ Designated Expert in consultation with IANA assigns the next
+ available enum number for each enum value.
+
+ IANA will publish approved type2 and type3 keyword and enum
+ attributes value registration specifications in:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-values/xxx/yyy.txt
+
+ where xxx is the attribute name that specifies the initial values and
+ yyy.txt is a descriptive file name that contains one or more enums or
+ keywords approved at the same time. For example, if several
+ additional enums for stapling are approved for use with the
+
+
+
+
+
+deBry, et al. Experimental [Page 117]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "finishings" attribute (and "finishings-default" and "finishings-
+ supported" attributes), IANA will publish the additional values in
+ the file:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-
+ values/finishings/stapling.txt
+
+ Note: Some attributes are defined to be: 'type3 keywords' | 'name'
+ which allows for attribute values to be extended by a site
+ administrator with administrator defined names. Such names are not
+ registered with IANA.
+
+ By definition, each of the three types above assert some sort of
+ registry or review process in order for extensions to be considered
+ valid. Each higher numbered level (1, 2, 3) tends to be decreasingly
+ less stringent than the previous level. Therefore, any typeN value
+ MAY be registered using a process for some typeM where M is less than
+ N, however such registration is NOT REQUIRED. For example, a type3
+ value MAY be registered in a type 1 manner (by being included in a
+ future version of an IPP specification), however, it is NOT REQUIRED.
+
+ This specification defines keyword and enum values for all of the
+ above types, including type3 keywords.
+
+ For private (unregistered) keyword extensions, implementers SHOULD
+ use keywords with a suitable distinguishing prefix, such as "xxx-"
+ where xxx is the (lowercase) fully qualified company name registered
+ with IANA for use in domain names [RFC1035]. For example, if the
+ company XYZ Corp. had obtained the domain name "XYZ.com", then a
+ private keyword 'abc' would be: 'xyz.com-abc'.
+
+ Note: RFC 1035 [RFC1035] indicates that while upper and lower case
+ letters are allowed in domain names, no significance is attached to
+ the case. That is, two names with the same spelling but different
+ case are to be treated as if identical. Also, the labels in a domain
+ name must follow the rules for ARPANET host names: They must start
+ with a letter, end with a letter or digit, and have as interior
+ characters only letters, digits, and hyphen. Labels must be 63
+ characters or less. Labels are separated by the "." character.
+
+ For private (unregistered) enum extension, implementers MUST use
+ values in the reserved integer range which is 2**30 to 2**31-1.
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 118]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+6.2 Attribute Extensibility
+
+ Attribute names are type2 keywords. Therefore, new attributes may be
+ registered and have the same status as attributes in this document by
+ following the type2 extension rules. For private (unregistered)
+ attribute extensions, implementers SHOULD use keywords with a
+ suitable distinguishing prefix as described in Section 6.1.
+
+ IANA will publish approved attribute registration specifications as
+ separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attributes/xxx-yyy.txt
+
+ where "xxx-yyy" is the new attribute name.
+
+ If a new Printer object attribute is defined and its values can be
+ affected by a specific document format, its specification needs to
+ contain the following sentence:
+
+ "The value of this attribute returned in a Get-Printer-Attributes
+ response MAY depend on the "document-format" attribute supplied
+ (see Section 3.2.5.1)."
+
+ If the specification does not, then its value in the Get-Printer-
+ Attributes response MUST NOT depend on the "document-format" supplied
+ in the request. When a new Job Template attribute is registered, the
+ value of the Printer attributes MAY vary with "document-format"
+ supplied in the request without the specification having to indicate
+ so.
+
+6.3 Attribute Syntax Extensibility
+
+ Attribute syntaxes are like type2 enums. Therefore, new attribute
+ syntaxes may be registered and have the same status as attribute
+ syntaxes in this document by following the type2 extension rules
+ described in Section 6.1. The value codes that identify each of the
+ attribute syntaxes are assigned in the Encoding and Transport
+ specification [RFC2565], including a designated range for private,
+ experimental use.
+
+ For attribute syntaxes, the IPP Designated Expert in consultation
+ with IANA assigns the next attribute syntax code in the appropriate
+ range as specified in [RFC2565]. IANA will publish approved
+ attribute syntax registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-syntaxes/xxx-yyy.txt
+
+ where 'xxx-yyy' is the new attribute syntax name.
+
+
+
+deBry, et al. Experimental [Page 119]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+6.4 Operation Extensibility
+
+ Operations may also be registered following the type2 procedures
+ described in Section 6.1, though major new operations will usually be
+ done by a new standards track RFC that augments this document. For
+ private (unregistered) operation extensions, implementers MUST use
+ the range for the "operation-id" in requests specified in Section
+ 4.4.13 "operations-supported" Printer attribute.
+
+ For operations, the IPP Designated Expert in consultation with IANA
+ assigns the next operation-id code as specified in Section 4.4.13.
+ IANA will publish approved operation registration specifications as
+ separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/operations/Xxx-Yyy.txt
+
+ where "Xxx-Yyy" is the new operation name.
+
+6.5 Attribute Groups
+
+ Attribute groups passed in requests and responses may be registered
+ following the type2 procedures described in Section 6.1. The tags
+ that identify each of the attribute groups are assigned in [RFC2565].
+
+ For attribute groups, the IPP Designated Expert in consultation with
+ IANA assigns the next attribute group tag code in the appropriate
+ range as specified in [RFC2565]. IANA will publish approved
+ attribute group registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-group-tags/xxx-yyy-
+ tag.txt
+
+ where 'xxx-yyy-tag' is the new attribute group tag name.
+
+6.6 Status Code Extensibility
+
+ Operation status codes may also be registered following the type2
+ procedures described in Section 6.1. The values for status codes are
+ allocated in ranges as specified in Section 13 for each status code
+ class:
+
+ "informational" - Request received, continuing process
+ "successful" - The action was successfully received, understood,
+ and accepted
+ "redirection" - Further action must be taken in order to complete
+ the request
+ "client-error" - The request contains bad syntax or cannot be
+ fulfilled
+
+
+
+deBry, et al. Experimental [Page 120]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "server-error" - The IPP object failed to fulfill an apparently
+ valid request
+
+ For private (unregistered) operation status code extensions,
+ implementers MUST use the top of each range as specified in Section
+ 13.
+
+ For operation status codes, the IPP Designated Expert in consultation
+ with IANA assigns the next status code in the appropriate class range
+ as specified in Section 13. IANA will publish approved status code
+ registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/status-codes/xxx-yyy.txt
+
+ where "xxx-yyy" is the new operation status code keyword.
+
+6.7 Registration of MIME types/sub-types for document-formats
+
+ The "document-format" attribute's syntax is 'mimeMediaType'. This
+ means that valid values are Internet Media Types (see Section 4.1.9).
+ RFC 2045 [RFC2045] defines the syntax for valid Internet media types.
+ IANA is the registry for all Internet media types.
+
+6.8 Registration of charsets for use in 'charset' attribute values
+
+ The "attributes-charset" attribute's syntax is 'charset'. This means
+ that valid values are charsets names. When a charset in the IANA
+ registry has more than one name (alias), the name labeled as
+ "(preferred MIME name)", if present, MUST be used (see Section
+ 4.1.7). IANA is the registry for charsets following the procedures
+ of [RFC2278].
+
+7. Internationalization Considerations
+
+ Some of the attributes have values that are text strings and names
+ which are intended for human understanding rather than machine
+ understanding (see the 'text' and 'name' attribute syntaxes in
+ Sections 4.1.1 and 4.1.2).
+
+ In each operation request, the client
+
+ - identifies the charset and natural language of the request which
+ affects each supplied 'text' and 'name' attribute value, and
+ - requests the charset and natural language for attributes returned
+ by the IPP object in operation responses (as described in Section
+ 3.1.4.1).
+
+
+
+
+
+deBry, et al. Experimental [Page 121]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ In addition, the client MAY separately and individually identify the
+ Natural Language Override of a supplied 'text' or 'name' attribute
+ using the 'textWithLanguage' and 'nameWithLanguage' technique
+ described section 4.1.1.2 and 4.1.2.2 respectively.
+
+ All IPP objects MUST support the UTF-8 [RFC2279] charset in all '
+ text' and 'name' attributes supported. If an IPP object supports
+ more than the UTF-8 charset, the object MUST convert between them in
+ order to return the requested charset to the client according to
+ Section 3.1.4.2. If an IPP object supports more than one natural
+ language, the object SHOULD return 'text' and 'name' values in the
+ natural language requested where those values are generated by the
+ Printer (see Section 3.1.4.1).
+
+ For Printers that support multiple charsets and/or multiple natural
+ languages in 'text' and 'name' attributes, different jobs may have
+ been submitted in differing charsets and/or natural languages. All
+ responses MUST be returned in the charset requested by the client.
+ However, the Get-Jobs operation uses the 'textWithLanguage' and '
+ nameWithLanguage' mechanism to identify the differing natural
+ languages with each job attribute returned.
+
+ The Printer object also has configured charset and natural language
+ attributes. The client can query the Printer object to determine
+ the list of charsets and natural languages supported by the Printer
+ object and what the Printer object's configured values are. See the
+ "charset-configured", "charset-supported", "natural-language-
+ configured", and "generated-natural-language-supported" Printer
+ description attributes for more details.
+
+ The "charset-supported" attributed identifies the supported charsets.
+ If a charset is supported, the IPP object MUST be capable of
+ converting to and from that charset into any other supported charset.
+ In many cases, an IPP object will support only one charset and it
+ MUST be the UTF-8 charset.
+
+ The "charset-configured" attribute identifies the one supported
+ charset which is the native charset given the current configuration
+ of the IPP object (administrator defined).
+
+ The "generated-natural-language-supported" attribute identifies the
+ set of supported natural languages for generated messages; it is not
+ related to the set of natural languages that must be accepted for
+ client supplied 'text' and 'name' attributes. For client supplied '
+ text' and 'name' attributes, an IPP object MUST accept ALL supplied
+ natural languages. Just because a Printer object is currently
+
+
+
+
+
+deBry, et al. Experimental [Page 122]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ configured to support 'en-us' natural language does not mean that the
+ Printer object should reject a job if the client supplies a job name
+ that is in 'fr-ca'.
+
+ The "natural-language-configured" attribute identifies the one
+ supported natural language for generated messages which is the native
+ natural language given the current configuration of the IPP object
+ (administrator defined).
+
+ Attributes of type 'text' and 'name' are populated from different
+ sources. These attributes can be categorized into following groups
+ (depending on the source of the attribute):
+
+ 1. Some attributes are supplied by the client (e.g., the client
+ supplied "job-name", "document-name", and "requesting-user-name"
+ operation attributes along with the corresponding Job object's
+ "job-name" and "job-originating-user-name" attributes). The IPP
+ object MUST accept these attributes in any natural language no
+ matter what the set of supported languages for generated
+ messages
+ 2. Some attributes are supplied by the system administrator (e.g.,
+ the Printer object's "printer-name" and "printer-location"
+ attributes). These too can be in any natural language. If the
+ natural language for these attributes is different than what a
+ client requests, then they must be reported using the Natural
+ Language Override mechanism.
+ 3. Some attributes are supplied by the device manufacturer (e.g.,
+ the Printer object's "printer-make-and-model" attribute). These
+ too can be in any natural language. If the natural language for
+ these attributes is different than what a client requests, then
+ they must be reported using the Natural Language Override
+ mechanism.
+ 4. Some attributes are supplied by the operator (e.g., the Job
+ object's "job-message-from-operator" attribute). These too can
+ be in any natural language. If the natural language for these
+ attributes is different than what a client requests, then they
+ must be reported using the Natural Language Override mechanism.
+ 5. Some attributes are generated by the IPP object (e.g., the Job
+ object's "job-state-message" attribute, the Printer object's
+ "printer-state-message" attribute, and the "status-message"
+ operation attribute). These attributes can only be in one of
+ the "generated-natural-language-supported" natural languages.
+ If a client requests some natural language for these attributes
+ other than one of the supported values, the IPP object SHOULD
+ respond using the value of the "natural-language-configured"
+ attribute (using the Natural Language Override mechanism if
+ needed).
+
+
+
+
+deBry, et al. Experimental [Page 123]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ The 'text' and 'name' attributes specified in this version of this
+ document (additional ones will be registered according to the
+ procedures in Section 6) are:
+
+ Attributes Source
+ -------------------------- ----------
+ Operation Attributes
+ job-name (name) client
+ document-name (name) client
+ requesting-user-name (name) client
+ status-message Job or Printer object
+
+ Job Template Attributes:
+ job-hold-until) client matches administrator-configured
+ (keyword | name
+ job-hold-until-default client matches administrator-configured
+ (keyword | name)
+ job-hold-until-supported client matches administrator-configured
+ (keyword | name)
+ job-sheets client matches administrator-configured
+ (keyword | name)
+ job-sheets-default client matches administrator-configured
+ (keyword | name)
+ job-sheets-supported client matches administrator-configured
+ (keyword | name)
+ media client matches administrator-configured
+ (keyword | name)
+ media-default client matches administrator-configured
+ (keyword | name)
+ media-supported client matches administrator-configured
+ (keyword | name)
+ media-ready client matches administrator-configured
+ (keyword | name)
+
+ Job Description Attributes:
+ job-name (name) client or Printer object
+ job-originating-user-name (name) Printer object
+ job-state-message (text) Job or Printer object
+ output-device-assigned (name(127)) administrator
+ job-message-from-operator (text(127)) operator
+
+ Printer Description Attributes:
+ printer-name (name(127)) administrator
+ printer-location (text(127)) administrator
+ printer-info (text(127)) administrator
+ printer-make-and-model (text(127)) administrator or manufacturer
+ printer-state-message (text) Printer object
+ printer-message-from-operator (text(127)) operator
+
+
+
+deBry, et al. Experimental [Page 124]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+8. Security Considerations
+
+ Some IPP objects MAY be deployed over protocol stacks that support
+ Secure Socket Layer Version 3 (SSL3) [SSL]. Note: SSL3 is not an
+ IETF standards track specification. Other IPP objects MAY be
+ deployed over protocol stacks that do not support SSL3. Some IPP
+ objects MAY be deployed over both types of protocol stacks. Those
+ IPP objects that support SSL3, are capable of supporting mutual
+ authentication as well as privacy of messages via multiple encryption
+ schemes. An important point about security related information for
+ SSL3 access to an IPP object, is that the security-related parameters
+ (authentication, encryption keys, etc.) are "out-of-band" to the
+ actual IPP protocol.
+
+ An IPP object that does not support SSL3 MAY elect to support a
+ transport layer that provides other security mechanisms. For
+ example, in a mapping of IPP over HTTP/1.1 [RFC2565], if the IPP
+ object does not support SSL3, HTTP still allows for client
+ authentication using Digest Access Authentication (DAA) [RFC2069].
+
+ It is difficult to anticipate the security risks that might exist in
+ any given IPP environment. For example, if IPP is used within a given
+ corporation over a private network, the risks of exposing document
+ data may be low enough that the corporation will choose not to use
+ encryption on that data. However, if the connection between the
+ client and the IPP object is over a public network, the client may
+ wish to protect the content of the information during transmission
+ through the network with encryption.
+
+ Furthermore, the value of the information being printed may vary from
+ one IPP environment to the next. Printing payroll checks, for
+ example, would have a different value than printing public
+ information from a file. There is also the possibly of denial-of-
+ service attacks, but denial-of-service attacks against printing
+ resources are not well understood and there is no published
+ precedents regarding this scenario.
+
+ Once the authenticated identity of the requester has been supplied to
+ the IPP object, the object uses that identity to enforce any
+ authorization policy that might be in place. For example, one site's
+ policy might be that only the job owner is allowed to cancel a job.
+ The details and mechanisms to set up a particular access control
+ policy are not part of IPP/1.0, and must be established via some
+ other type of administrative or access control framework. However,
+ there are operation status codes that allow an IPP server to return
+ information back to a client about any potential access control
+ violations for an IPP object.
+
+
+
+
+deBry, et al. Experimental [Page 125]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ During a create operation, the client's identity is recorded in the
+ Job object in an implementation-defined attribute. This information
+ can be used to verify a client's identity for subsequent operations
+ on that Job object in order to enforce any access control policy that
+ might be in effect. See section 8.3 below for more details.
+
+ Since the security levels or the specific threats that any given IPP
+ system administrator may be concerned with cannot be anticipated, IPP
+ MUST be capable of operating with different security mechanisms and
+ security policies as required by the individual installation.
+ Security policies might vary from very strong, to very weak, to none
+ at all, and corresponding security mechanisms will be required. SSL3
+ supports the type of negotiated levels of security required by most,
+ if not all, potential IPP environments. IPP environments that require
+ no security can elect to deploy IPP objects that do not utilize the
+ optional SSL3 security mechanisms.
+
+8.1 Security Scenarios
+
+ The following sections describe specific security attacks for IPP
+ environments. Where examples are provided they should be considered
+ illustrative of the environment and not an exhaustive set. Not all of
+ these environments will necessarily be addressed in initial
+ implementations of IPP.
+
+8.1.1 Client and Server in the Same Security Domain
+
+ This environment is typical of internal networks where traditional
+ office workers print the output of personal productivity applications
+ on shared work-group printers, or where batch applications print
+ their output on large production printers. Although the identity of
+ the user may be trusted in this environment, a user might want to
+ protect the content of a document against such attacks as
+ eavesdropping, replaying or tampering.
+
+8.1.2 Client and Server in Different Security Domains
+
+ Examples of this environment include printing a document created by
+ the client on a publicly available printer, such as at a commercial
+ print shop; or printing a document remotely on a business associate's
+ printer. This latter operation is functionally equivalent to sending
+ the document to the business associate as a facsimile. Printing
+ sensitive information on a Printer in a different security domain
+ requires strong security measures. In this environment authentication
+ of the printer is required as well as protection against unauthorized
+ use of print resources. Since the document crosses security domains,
+
+
+
+
+
+deBry, et al. Experimental [Page 126]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ protection against eavesdropping and document tampering are also
+ required. It will also be important in this environment to protect
+ Printers against "spamming" and malicious document content.
+
+8.1.3 Print by Reference
+
+ When the document is not stored on the client, printing can be done
+ by reference. That is, the print request can contain a reference, or
+ pointer, to the document instead of the actual document itself.
+ Standard methods currently do not exist for remote entities to
+ "assume" the credentials of a client for forwarding requests to a 3rd
+ party. It is anticipated that Print-By-Reference will be used to
+ access "public" documents and that sophisticated methods for
+ authenticating "proxies" will not be specified for version 1 of IPP.
+
+8.2 URIs for SSL3 and non-SSL3 Access
+
+ As described earlier, an IPP object can support SSL3 access, non-SSL3
+ access, or both. The "printer-uri-supported" attribute contains the
+ Printer object's URI(s). Its companion attribute, "uri-security-
+ supported", identifies the security mechanism used for each URI
+ listed in the "printer-uri-supported" attribute. For each Printer
+ operation request, a client MUST supply only one URI in the
+ "printer-uri" operation attribute. In other words, even though the
+ Printer supports more than one URI, the client only interacts with
+ the Printer object using one if its URIs. This duality is not needed
+ for Job objects, since the Printer objects is the factory for Job
+ objects, and the Printer object will generate the correct URI for new
+ Job objects depending on the Printer object's security configuration.
+
+8.3 The "requesting-user-name" (name(MAX)) Operation Attribute
+
+ Each operation MUST specify the user who is performing the operation
+ in both of the following two ways:
+
+ 1) via the REQUIRED "requesting-user-name" operation attribute that
+ a client SHOULD supply in all operations. The client MUST obtain
+ the value for this attribute from an environmental or network
+ login name for the user, rather than allowing the user to supply
+ any value. If the client does not supply a value for
+ "requesting-user-name", the printer MUST assume that the client
+ is supplying some anonymous name, such as "anonymous".
+ 2) via an authentication mechanism of the underlying transport
+ which may be configured to give no authentication information.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 127]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ There are six cases to consider:
+
+ a) the authentication mechanism gives no information, and the
+ client doesn't specify "requesting-user-name".
+ b) the authentication mechanism gives no information, but the
+ client specifies "requesting-user-name".
+ c) the authentication mechanism specifies a user which has no human
+ readable representation, and the client doesn't specify
+ "requesting-user-name".
+ d) the authentication mechanism specifies a user which has no human
+ readable representation, but the client specifies "requesting-
+ user-name".
+ e) the authentication mechanism specifies a user which has a human
+ readable representation. The Printer object ignores the
+ "requesting-user-name".
+ f) the authentication mechanism specifies a user who is trusted and
+ whose name means that the value of the "requesting-user-name",
+ which MUST be present, is treated as the authenticated name.
+
+ Note: Case "f" is intended for a tightly coupled gateway and server
+ to work together so that the "user" name is able to be that of the
+ gateway client and not that of the gateway. Because most, if not
+ all, system vendors will initially implement IPP via a gateway into
+ their existing print system, this mechanism is necessary unless the
+ authentication mechanism allows a gateway (client) to act on behalf
+ of some other client.
+
+ The user-name has two forms:
+
+ - one that is human readable: it is held in the REQUIRED "job-
+ originating-user-name" Job Description attribute which is set
+ during the job creation operations. It is used for presentation
+ only, such as returning in queries or printing on start sheets
+ - one for authorization: it is held in an undefined (by IPP) Job
+ object attribute which is set by the job creation operation. It
+ is used to authorize other operations, such as Send-Document,
+ Send-URI, Cancel-Job, to determine the user when the "my-jobs"
+ attribute is specified with Get-Jobs, and to limit what
+ attributes and values to return with Get-Job-Attributes and Get-
+ Jobs.
+
+ The human readable user name:
+
+ - is the value of the "requesting-user-name" for cases b, d and f.
+ - comes from the authentication mechanism for case e
+ - is some anonymous name, such as "anonymous" for cases a and c.
+
+ The user name used for authorization:
+
+
+
+deBry, et al. Experimental [Page 128]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ - is the value of the "requesting-user-name" for cases b and f.
+ - comes from the authentication mechanism for cases c, d and e
+ - is some anonymous name, such as "anonymous" for case a.
+
+ The essence of these rules for resolving conflicting sources of
+ user-names is that a printer implementation is free to pick either
+ source as long as it achieves consistent results. That is, if a user
+ uses the same path for a series of requests, the requests MUST appear
+ to come from the same user from the standpoint of both the human-
+ readable user name and the user name for authorization. This rule
+ MUST continue to apply even if a request could be authenticated by
+ two or more mechanisms. It doesn't matter which of several
+ authentication mechanisms a Printer uses as long as it achieves
+ consistent results. If a client uses more than one authentication
+ mechanism, it is recommended that an administrator make all
+ credentials resolve to the same user and user-name as much as
+ possible.
+
+8.4 Restricted Queries
+
+ In many IPP operations, a client supplies a list of attributes to be
+ returned in the response. For security reasons, an IPP object may be
+ configured not to return all attributes (or all values) that a client
+ requests. The job attributes returned MAY depend on whether the
+ requesting user is the same as the user that submitted the job. The
+ IPP object MAY even return none of the requested attributes. In such
+ cases, the status returned is the same as if the object had returned
+ all requested attributes. The client cannot tell by such a response
+ whether the requested attribute was present or absent on the object.
+
+8.5 Queries on jobs submitted using non-IPP protocols
+
+ If the device that an IPP Printer is representing is able to accept
+ jobs using other job submission protocols in addition to IPP, it is
+ RECOMMENDED that such an implementation at least allow such "foreign"
+ jobs to be queried using Get-Jobs returning "job-id" and "job-uri" as
+ 'unknown'. Such an implementation NEED NOT support all of the same
+ IPP job attributes as for IPP jobs. The IPP object returns the '
+ unknown' out-of-band value for any requested attribute of a foreign
+ job that is supported for IPP jobs, but not for foreign jobs.
+
+ It is further RECOMMENDED, that the IPP Printer generate "job-id" and
+ "job-uri" values for such "foreign jobs", if possible, so that they
+ may be targets of other IPP operations, such as Get-Job-Attributes
+ and Cancel-Job. Such an implementation also needs to deal with the
+ problem of authentication of such foreign jobs. One approach would
+ be to treat all such foreign jobs as belonging to users other than
+ the user of the IPP client. Another approach would be for the
+
+
+
+deBry, et al. Experimental [Page 129]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ foreign job to belong to 'anonymous'. Only if the IPP client has
+ been authenticated as an operator or administrator of the IPP Printer
+ object, could the foreign jobs be queried by an IPP request.
+ Alternatively, if the security policy is to allow users to query
+ other users' jobs, then the foreign jobs would also be visible to an
+ end-user IPP client using Get-Jobs and Get-Job-Attributes.
+
+8.6 IPP Security Application Profile for SSL3
+
+ The IPP application profile for SSL3 follows the "Secure Socket
+ Layer" requirement as documented in the SSL3 specification [SSL].
+ For interoperability, the SSL3 cipher suites are:
+
+ SSL_RSA_WITH_RC4_128_MD5
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ SSL_RSA_WITH_DES_CBC_SHA
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+ SSL_RSA_WITH_NULL_MD5
+
+ Client implementations MUST NOT assume any other cipher suites are
+ supported by an IPP Printer object.
+
+ If a conforming IPP object supports SSL3, it MUST implement and
+ support the cipher suites listed above and MAY support additional
+ cipher suites.
+
+ A conforming IPP client SHOULD support SSL3 including the cipher
+ suites listed above. A conforming IPP client MAY support additional
+ cipher suites.
+
+ It is possible that due to certain government export restrictions
+ some non-compliant versions of this extension could be deployed.
+ Implementations wishing to inter-operate with such non-compliant
+ versions MAY offer the SSL_RSA_EXPORT_WITH_RC4_40_MD5 and
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 mechanisms. However, since 40 bit
+ ciphers are known to be vulnerable to attack by current technology,
+ any client which actives a 40 bit cipher MUST NOT indicate to the
+ user that the connection is completely secure from eavesdropping.
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 130]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+9. References
+
+ [ASCII] Coded Character Set - 7-bit American Standard Code for
+ Information Interchange (ASCII), ANSI X3.4-1986. This
+ standard is the specification of the US-ASCII charset.
+
+ [HTPP] J. Barnett, K. Carter, R. DeBry, "Initial Draft -
+ Hypertext Printing Protocol - HTPP/1.0", October 1996.
+ ftp://ftp.pwg.org/pub/pwg/ipp/historic/htpp/
+ overview.ps.gz
+
+ [IANA-CS] IANA Registry of Coded Character Sets:
+ ftp://ftp.isi.edu/in-notes/iana/assignments/character-
+ sets
+
+ [IANA-MT] IANA Registry of Media Types: ftp://ftp.isi.edu/in-
+ notes/iana/assignments/media-types/
+
+ [ipp-iig] Hastings, T. and C. Manros, "Internet Printing
+ Protocol/1.0: Implementer's Guide", Work in Progress.
+
+ [ISO10646-1] ISO/IEC 10646-1:1993, "Information technology --
+ Universal Multiple-Octet Coded Character Set (UCS) -
+ Part 1: Architecture and Basic Multilingual Plane,
+ JTC1/SC2."
+
+ [ISO8859-1] ISO/IEC 8859-1:1987, "Information technology -- 8-bit
+ One-Byte Coded Character Set - Part 1: Latin Alphabet Nr
+ 1", 1987, JTC1/SC2.
+
+ [ISO10175] ISO/IEC 10175 Document Printing Application (DPA), June
+ 1996.
+
+ [LDPA] T. Hastings, S. Isaacson, M. MacKay, C. Manros, D. Taylor, P.
+ Zehler, "LDPA - Lightweight Document Printing
+ Application", October 1996,
+ ftp://ftp.pwg.org/pub/pwg/ipp/historic/ldpa/ldpa8.pdf.gz
+
+ [P1387.4] Kirk, M. (Editor), POSIX System Administration - Part 4:
+ Printing Interfaces, POSIX 1387.4 D8, 1994.
+
+ [PSIS] Herriot, R. (editor), X/Open A Printing System
+ Interoperability Specification (PSIS), August 1995.
+
+ [PWG] Printer Working Group, http://www.pwg.org.
+
+ [RFC1035] Mockapetris, P., "DOMAIN NAMES - IMPLEMENTATION AND
+ SPECIFICATION", STD 13, RFC 1035, November 1987.
+
+
+
+deBry, et al. Experimental [Page 131]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S. and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1766] Alvestrand, H., "Tags for the Identification of
+ Languages", RFC 1766, March 1995.
+
+ [RFC1179] McLaughlin, L. (Editor), "Line Printer Daemon Protocol",
+ RFC 1179, August 1990.
+
+ [RFC1952] Deutsch, P., "GZIP file format specification version
+ 4.3", RFC 1952, May 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, " Multipurpose Internet
+ Mail Extensions (MIME) Part One: Format of Internet
+ Message Bodies", RFC 2045, November 1996.
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+ [RFC2048] Freed, N., Klensin, J. and J. Postel, "Multipurpose
+ Internet Mail Extension (MIME) Part Four: Registration
+ Procedures", RFC 2048, November 1996.
+
+ [RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. AND T.
+ Berners-Lee, "Hypertext Transfer Protocol - HTTP/1.1",
+ RFC 2068, January 1997.
+
+ [RFC2069] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to
+ HTTP: Digest Access Authentication", RFC 2069, January
+ 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2228] Horowitz, M. and S. Lunt, "FTP Security Extensions", RFC
+ 2228, October 1997.
+
+ [RFC2277] Alvestrand, H., "IETF Policy on Character Sets and
+ Languages" RFC 2277, January 1998.
+
+ [RFC2278] Freed, N. and J. Postel: "IANA Charset Registration
+ Procedures", BCP 19, RFC 2278, January 1998.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+deBry, et al. Experimental [Page 132]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ [RFC2316] Bellovin, S., "Report of the IAB Security Architecture
+ Workshop", RFC 2316, April 1998.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner
+ "Internet Printing Protocol/1.0: Encoding and
+ Transport", RFC 2565, April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2579] McCloghrie, K., Perkins, D. and J. Schoenwaelder,
+ "Textual Conventions for SMIv2", STD 58, RFC 2579, April
+ 1999.
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version
+ 3.02), November 1996.
+
+ [SWP] P. Moore, B. Jahromi, S. Butler, "Simple Web Printing
+ SWP/1.0", May 7, 1997,
+ ftp://ftp.pwg.org/pub/pwg/ipp/new_PRO/swp9705.pdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 133]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+10. Authors' Addresses
+
+ Scott A. Isaacson (Editor)
+ Novell, Inc.
+ 122 E 1700 S
+ Provo, UT 84606
+
+ Phone: 801-861-7366
+ Fax: 801-861-2517
+ EMail: sisaacson@novell.com
+
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St.
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Robert Herriot
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: robert.herriot@pahv.xerox.com
+
+
+ Roger deBry
+ Utah Valley State College
+ Orem, UT 84058
+
+ Phone: (801) 222-8000
+ EMail: debryro@uvsc.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 134]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Patrick Powell
+ Astart Technologies
+ 9475 Chesapeake Dr., Suite D
+ San Diego, CA 95123
+
+ Phone: (619) 874-6543
+ Fax: (619) 279-8424
+ EMail: papowell@astart.com
+
+ IPP Mailing List: ipp@pwg.org
+ IPP Mailing List Subscription: ipp-request@pwg.org
+ IPP Web Page: http://www.pwg.org/ipp/
+
+ Implementers of this specification are encouraged to join IPP Mailing
+ List in order to participate in any discussions of clarification
+ issues and review of registration proposals for additional attributes
+ and values.
+
+ Other Participants:
+
+ Chuck Adams - Tektronix
+ Jeff Barnett - IBM
+ Ron Bergman - Dataproducts Corp.
+ Sylvan Butler - HP
+ Keith Carter - IBM Corporation
+ Jeff Copeland - QMS
+ Andy Davidson - Tektronix
+ Mabry Dozier - QMS
+ Lee Farrell - Canon Information Systems
+ Steve Gebert - IBM
+ Babek Jahromi - Microsoft
+ David Kellerman - Northlake Software
+ Rick Landau - Digital
+ Greg LeClair - Epson
+ Harry Lewis - IBM
+ Pete Loya - HP
+ Ray Lutz - Cognisys
+ Mike MacKay - Novell, Inc.
+ Daniel Manchala - Xerox
+ Carl-Uno Manros - Xerox
+ Jay Martin - Underscore
+ Larry Masinter - Xerox
+ Stan McConnell - Xerox
+ Ira McDonald - High North Inc.
+ Paul Moore - Microsoft
+ Tetsuya Morita - Ricoh
+ Yuichi Niwa - Ricoh
+ Pat Nogay - IBM
+
+
+
+deBry, et al. Experimental [Page 135]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Ron Norton - Printronics
+ Bob Pentecost - HP
+ Rob Rhoads - Intel
+ Xavier Riley - Xerox
+ David Roach - Unisys
+ Stuart Rowley - Kyocera
+ Hiroyuki Sato - Canon
+ Bob Setterbo - Adobe
+ Devon Taylor - Novell, Inc.
+ Mike Timperman - Lexmark
+ Randy Turner - Sharp
+ Atsushi Yuki - Kyocera
+ Rick Yardumian - Xerox
+ Lloyd Young - Lexmark
+ Bill Wagner - DPI
+ Jim Walker - DAZEL
+ Chris Wellens - Interworking Labs
+ Rob Whittle - Novell, Inc.
+ Don Wright - Lexmark
+ Peter Zehler - Xerox
+ Steve Zilles - Adobe
+
+11. Formats for IPP Registration Proposals
+
+ In order to propose an IPP extension for registration, the proposer
+ must submit an application to IANA by email to "iana@iana.org" or by
+ filling out the appropriate form on the IANA web pages
+ (http://www.iana.org). This section specifies the required
+ information and the formats for proposing registrations of extensions
+ to IPP as provided in Section 6 for:
+
+ 1. type2 'keyword' attribute values
+ 2. type3 'keyword' attribute values
+ 3. type2 'enum' attribute values
+ 4. type3 'enum' attribute values
+ 5. attributes
+ 6. attribute syntaxes
+ 7. operations
+ 8. status codes
+
+11.1 Type2 keyword attribute values registration
+
+ Type of registration: type2 keyword attribute value
+ Name of attribute to which this keyword specification is to be added:
+ Proposed keyword name of this keyword value:
+ Specification of this keyword value (follow the style of IPP Model
+ Section 4.1.2.3):
+ Name of proposer:
+
+
+
+deBry, et al. Experimental [Page 136]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type2 keywords, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.2 Type3 keyword attribute values registration
+
+ Type of registration: type3 keyword attribute value
+ Name of attribute to which this keyword specification is to be added:
+ Proposed keyword name of this keyword value:
+ Specification of this keyword value (follow the style of IPP Model
+ Section 4.1.2.3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type3 keywords, the proposer will be the point of contact
+ for the approved registration specification, if any maintenance of
+ the registration specification is needed.
+
+11.3 Type2 enum attribute values registration
+
+ Type of registration: type2 enum attribute value
+ Name of attribute to which this enum specification is to be added:
+ Keyword symbolic name of this enum value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Specification of this enum value (follow the style of IPP Model
+ Section 4.1.4):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type2 enums, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.4 Type3 enum attribute values registration
+
+ Type of registration: type3 enum attribute value
+ Name of attribute to which this enum specification is to be added:
+ Keyword symbolic name of this enum value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Specification of this enum value (follow the style of IPP Model
+ Section 4.1.4):
+
+
+
+deBry, et al. Experimental [Page 137]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type3 enums, the proposer will be the point of contact for
+ the approved registration specification, if any maintenance of the
+ registration specification is needed.
+
+11.5 Attribute registration
+
+ Type of registration: attribute
+ Proposed keyword name of this attribute:
+ Types of attribute (Operation, Job Template, Job Description,
+ Printer Description):
+ Operations to be used with if the attribute is an operation
+ attribute:
+ Object (Job, Printer, etc. if bound to an object):
+ Attribute syntax(es) (include 1setOf and range as in Section 4.2):
+ If attribute syntax is 'keyword' or 'enum', is it type2 or type3:
+ If this is a Printer attribute, MAY the value returned depend on
+ "document-format" (See Section 6.2):
+ If this is a Job Template attribute, how does its specification
+ depend on the value of the "multiple-document-handling" attribute:
+ Specification of this attribute (follow the style of IPP Model
+ Section 4.2):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For attributes, the IPP Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.6 Attribute Syntax registration
+
+ Type of registration: attribute syntax
+ Proposed name of this attribute syntax:
+ Type of attribute syntax (integer, octetString, character-string,
+ see [RFC2565]):
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Specification of this attribute (follow the style of IPP Model
+ Section 4.1):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+
+
+
+
+deBry, et al. Experimental [Page 138]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Note: For attribute syntaxes, the IPP Designated Expert will be the
+ point of contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.7 Operation registration
+
+ Type of registration: operation
+ Proposed name of this operation:
+ Numeric operation-id value (to be assigned by the IPP Designated
+ Expert in consultation with IANA):
+ Object Target (Job, Printer, etc. that operation is upon):
+ Specification of this attribute (follow the style of IPP Model
+ Section 3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For operations, the IPP Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.8 Attribute Group registration
+
+ Type of registration: attribute group
+ Proposed name of this attribute group:
+ Numeric tag according to [RFC2565] (to be assigned by the IPP
+ Designated Expert in consultation with IANA):
+ Operation requests and group number for each operation in which the
+ attribute group occurs:
+ Operation responses and group number for each operation in which the
+ attribute group occurs:
+ Specification of this attribute group (follow the style of IPP Model
+ Section 3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For attribute groups, the IPP Designated Expert will be the
+ point of contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.9 Status code registration
+
+ Type of registration: status code
+ Keyword symbolic name of this status code value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Operations that this status code may be used with:
+
+
+
+deBry, et al. Experimental [Page 139]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ Specification of this status code (follow the style of IPP Model
+ Section 14 APPENDIX B: Status Codes and Suggested Status Code
+ Messages):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For status codes, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 140]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+12. APPENDIX A: Terminology
+
+ This specification uses the terminology defined in this section.
+
+12.1 Conformance Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+ interpreted as described in RFC 2119 [RFC2119].
+
+12.1.1 NEED NOT
+
+ This term is not included in RFC 2119. The verb "NEED NOT" indicates
+ an action that the subject of the sentence does not have to implement
+ in order to claim conformance to the standard. The verb "NEED NOT"
+ is used instead of "MAY NOT" since "MAY NOT" sounds like a
+ prohibition.
+
+12.2 Model Terminology
+
+12.2.1 Keyword
+
+ Keywords are used within this document as identifiers of semantic
+ entities within the abstract model (see section 4.1.2.3). Attribute
+ names, some attribute values, attribute syntaxes, and attribute group
+ names are represented as keywords.
+
+12.2.2 Attributes
+
+ An attribute is an item of information that is associated with an
+ instance of an IPP object. An attribute consists of an attribute
+ name and one or more attribute values. Each attribute has a specific
+ attribute syntax. All object attributes are defined in section 4 and
+ all operation attributes are defined in section 3.
+
+ Job Template Attributes are described in section 4.2. The client
+ optionally supplies Job Template attributes in a create request
+ (operation requests that create Job objects). The Printer object has
+ associated attributes which define supported and default values for
+ the Printer.
+
+12.2.2.1 Attribute Name
+
+ Each attribute is uniquely identified in this document by its
+ attribute name. An attribute name is a keyword. The keyword
+ attribute name is given in the section header describing that
+
+
+
+
+
+deBry, et al. Experimental [Page 141]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ attribute. In running text in this document, attribute names are
+ indicated inside double quotation marks (") where the quotation marks
+ are not part of the keyword itself.
+
+12.2.2.2 Attribute Group Name
+
+ Related attributes are grouped into named groups. The name of the
+ group is a keyword. The group name may be used in place of naming
+ all the attributes in the group explicitly. Attribute groups are
+ defined in section 3.
+
+12.2.2.3 Attribute Value
+
+ Each attribute has one or more values. Attribute values are
+ represented in the syntax type specified for that attribute. In
+ running text in this document, attribute values are indicated inside
+ single quotation marks ('), whether their attribute syntax is
+ keyword, integer, text, etc. where the quotation marks are not part
+ of the value itself.
+
+12.2.2.4 Attribute Syntax
+
+ Each attribute is defined using an explicit syntax type. In this
+ document, each syntax type is defined as a keyword with specific
+ meaning. The Encoding and Transport document [RFC2565] indicates the
+ actual "on-the-wire" encoding rules for each syntax type. Attribute
+ syntax types are defined in section 4.1.
+
+12.2.3 Supports
+
+ By definition, a Printer object supports an attribute only if that
+ Printer object responds with the corresponding attribute populated
+ with some value(s) in a response to a query for that attribute. A
+ Printer object supports an attribute value if the value is one of the
+ Printer object's "supported values" attributes. The device behind a
+ Printer object may exhibit a behavior that corresponds to some IPP
+ attribute, but if the Printer object, when queried for that
+ attribute, doesn't respond with the attribute, then as far as IPP is
+ concerned, that implementation does not support that feature. If the
+ Printer object's "xxx-supported" attribute is not populated with a
+ particular value (even if that value is a legal value for that
+ attribute), then that Printer object does not support that particular
+ value.
+
+ A conforming implementation MUST support all REQUIRED attributes.
+ However, even for REQUIRED attributes, conformance to IPP does not
+ mandate that all implementations support all possible values
+ representing all possible job processing behaviors and features. For
+
+
+
+deBry, et al. Experimental [Page 142]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ example, if a given instance of a Printer supports only certain
+ document formats, then that Printer responds with the "document-
+ format-supported" attribute populated with a set of values, possibly
+ only one, taken from the entire set of possible values defined for
+ that attribute. This limited set of values represents the Printer's
+ set of supported document formats. Supporting an attribute and some
+ set of values for that attribute enables IPP end users to be aware of
+ and make use of those features associated with that attribute and
+ those values. If an implementation chooses to not support an
+ attribute or some specific value, then IPP end users would have no
+ ability to make use of that feature within the context of IPP itself.
+ However, due to existing practice and legacy systems which are not
+ IPP aware, there might be some other mechanism outside the scope of
+ IPP to control or request the "unsupported" feature (such as embedded
+ instructions within the document data itself).
+
+ For example, consider the "finishings-supported" attribute.
+
+ 1) If a Printer object is not physically capable of stapling, the
+ "finishings-supported" attribute MUST NOT be populated with the
+ value of 'staple'.
+ 2) A Printer object is physically capable of stapling, however an
+ implementation chooses not to support stapling in the IPP
+ "finishings" attribute. In this case, 'staple' MUST NOT be a
+ value in the "finishings-supported" Printer object attribute.
+ Without support for the value 'staple', an IPP end user would
+ have no means within the protocol itself to request that a Job
+ be stapled. However, an existing document data formatter might
+ be able to request that the document be stapled directly with an
+ embedded instruction within the document data. In this case,
+ the IPP implementation does not "support" stapling, however the
+ end user is still able to have some control over the stapling of
+ the completed job.
+ 3) A Printer object is physically capable of stapling, and an
+ implementation chooses to support stapling in the IPP
+ "finishings" attribute. In this case, 'staple' MUST be a value
+ in the "finishings-supported" Printer object attribute. Doing
+ so, would enable end users to be aware of and make use of the
+ stapling feature using IPP attributes.
+
+ Even though support for Job Template attributes by a Printer object
+ is OPTIONAL, it is RECOMMENDED that if the device behind a Printer
+ object is capable of realizing any feature or function that
+ corresponds to an IPP attribute and some associated value, then that
+ implementation SHOULD support that IPP attribute and value.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 143]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ The set of values in any of the supported value attributes is set
+ (populated) by some administrative process or automatic sensing
+ mechanism that is outside the scope of IPP. For administrative
+ policy and control reasons, an administrator may choose to make only
+ a subset of possible values visible to the end user. In this case,
+ the real output device behind the IPP Printer abstraction may be
+ capable of a certain feature, however an administrator is specifying
+ that access to that feature not be exposed to the end user through
+ the IPP protocol. Also, since a Printer object may represent a
+ logical print device (not just a physical device) the actual process
+ for supporting a value is undefined and left up to the
+ implementation. However, if a Printer object supports a value, some
+ manual human action may be needed to realize the semantic action
+ associated with the value, but no end user action is required.
+
+ For example, if one of the values in the "finishings-supported"
+ attribute is 'staple', the actual process might be an automatic
+ staple action by a physical device controlled by some command sent to
+ the device. Or, the actual process of stapling might be a manual
+ action by an operator at an operator attended Printer object.
+
+ For another example of how supported attributes function, consider a
+ system administrator who desires to control all print jobs so that no
+ job sheets are printed in order to conserve paper. To force no job
+ sheets, the system administrator sets the only supported value for
+ the "job-sheets-supported" attribute to 'none'. In this case, if a
+ client requests anything except 'none', the create request is
+ rejected or the "job-sheets" value is ignored (depending on the value
+ of "ipp-attribute-fidelity"). To force the use of job start/end
+ sheets on all jobs, the administrator does not include the value '
+ none' in the "job-sheets-supported" attribute. In this case, if a
+ client requests 'none', the create request is rejected or the "job-
+ sheets" value is ignored (again depending on the value of "ipp-
+ attribute-fidelity").
+
+12.2.4 print-stream page
+
+ A "print-stream page" is a page according to the definition of pages
+ in the language used to express the document data.
+
+12.2.5 impression
+
+ An "impression" is the image (possibly many print-stream pages in
+ different configurations) imposed onto a single media page.
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 144]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+13. APPENDIX B: Status Codes and Suggested Status Code Messages
+
+ This section defines status code enum keywords and values that are
+ used to provide semantic information on the results of an operation
+ request. Each operation response MUST include a status code. The
+ response MAY also contain a status message that provides a short
+ textual description of the status. The status code is intended for
+ use by automata, and the status message is intended for the human end
+ user. Since the status message is an OPTIONAL component of the
+ operation response, an IPP application (i.e., a browser, GUI, print
+ driver or gateway) is NOT REQUIRED to examine or display the status
+ message, since it MAY not be returned to the application.
+
+ The prefix of the status keyword defines the class of response as
+ follows:
+
+ "informational" - Request received, continuing process
+ "successful" - The action was successfully received, understood,
+ and accepted
+ "redirection" - Further action must be taken in order to complete
+ the request
+ "client-error" - The request contains bad syntax or cannot be
+ fulfilled
+ "server-error" - The IPP object failed to fulfill an apparently
+ valid request
+
+ As with type2 enums, IPP status codes are extensible. IPP clients
+ are NOT REQUIRED to understand the meaning of all registered status
+ codes, though such understanding is obviously desirable. However,
+ IPP clients MUST understand the class of any status code, as
+ indicated by the prefix, and treat any unrecognized response as being
+ equivalent to the first status code of that class, with the exception
+ that an unrecognized response MUST NOT be cached. For example, if an
+ unrecognized status code of "client-error-xxx-yyy" is received by the
+ client, it can safely assume that there was something wrong with its
+ request and treat the response as if it had received a "client-
+ error-bad-request" status code. In such cases, IPP applications
+ SHOULD present the OPTIONAL message (if present) to the end user
+ since the message is likely to contain human readable information
+ which will help to explain the unusual status. The name of the enum
+ is the suggested status message for US English.
+
+ The status code values range from 0x0000 to 0x7FFF. The value ranges
+ for each status code class are as follows:
+
+ "successful" - 0x0000 to 0x00FF
+ "informational" - 0x0100 to 0x01FF
+ "redirection" - 0x0200 to 0x02FF
+
+
+
+deBry, et al. Experimental [Page 145]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ "client-error" - 0x0400 to 0x04FF
+ "server-error" - 0x0500 to 0x05FF
+
+ The top half (128 values) of each range (0x0n40 to 0x0nFF, for n = 0
+ to 5) is reserved for private use within each status code class.
+ Values 0x0600 to 0x7FFF are reserved for future assignment and MUST
+ NOT be used.
+
+13.1 Status Codes
+
+ Each status code is described below. Section 13.1.5.9 contains a
+ table that indicates which status codes apply to which operations.
+ The Implementer's Guide [ipp-iig] describe the suggested steps for
+ processing IPP attributes for all operations, including returning
+ status codes.
+
+13.1.1 Informational
+
+ This class of status code indicates a provisional response and is to
+ be used for informational purposes only.
+
+ There are no status codes defined in IPP/1.0 for this class of status
+ code.
+
+13.1.2 Successful Status Codes
+
+ This class of status code indicates that the client's request was
+ successfully received, understood, and accepted.
+
+13.1.2.1 successful-ok (0x0000)
+
+ The request has succeeded and no request attributes were substituted
+ or ignored. In the case of a response to a create request, the '
+ successful-ok' status code indicates that the request was
+ successfully received and validated, and that the Job object has been
+ created; it does not indicate that the job has been processed. The
+ transition of the Job object into the 'completed' state is the only
+ indicator that the job has been printed.
+
+13.1.2.2 successful-ok-ignored-or-substituted-attributes (0x0001)
+
+ The request has succeeded, but some supplied (1) attributes were
+ ignored or (2) unsupported values were substituted with supported
+ values or were ignored in order to perform the operation without
+ rejecting it. Unsupported attributes, attribute syntaxes, or values
+ MUST be returned in the Unsupported Attributes group of the response
+ for all operations. There is an exception to this rule for the query
+ operations: Get-Printer-Attributes, Get-Jobs, and Get-Job-Attributes
+
+
+
+deBry, et al. Experimental [Page 146]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ for the "requested-attributes" operation attribute only. When the
+ supplied values of the "requested-attributes" operation attribute are
+ requesting attributes that are not supported, the IPP object MAY, but
+ is NOT REQUIRED to, return the "requested-attributes" attribute in
+ the Unsupported Attribute response group (with the unsupported values
+ only). See section 3.2.1.2.
+
+13.1.2.3 successful-ok-conflicting-attributes (0x0002)
+
+ The request has succeeded, but some supplied attribute values
+ conflicted with the values of other supplied attributes. These
+ conflicting values were either (1) substituted with (supported)
+ values or (2) the attributes were removed in order to process the job
+ without rejecting it. Attributes or values which conflict with other
+ attributes and have been substituted or ignored MUST be returned in
+ the Unsupported Attributes group of the response for all operations
+ as supplied by the client. See section 3.2.1.2.
+
+13.1.3 Redirection Status Codes
+
+ This class of status code indicates that further action needs to be
+ taken to fulfill the request.
+
+ There are no status codes defined in IPP/1.0 for this class of status
+ code.
+
+13.1.4 Client Error Status Codes
+
+ This class of status code is intended for cases in which the client
+ seems to have erred. The IPP object SHOULD return a message
+ containing an explanation of the error situation and whether it is a
+ temporary or permanent condition.
+
+13.1.4.1 client-error-bad-request (0x0400)
+
+ The request could not be understood by the IPP object due to
+ malformed syntax (such as the value of a fixed length attribute whose
+ length does not match the prescribed length for that attribute - see
+ the Implementer's Guide [ipp-iig] ). The IPP application SHOULD NOT
+ repeat the request without modifications.
+
+13.1.4.2 client-error-forbidden (0x0401)
+
+ The IPP object understood the request, but is refusing to fulfill it.
+ Additional authentication information or authorization credentials
+ will not help and the request SHOULD NOT be repeated. This status
+
+
+
+
+
+deBry, et al. Experimental [Page 147]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ code is commonly used when the IPP object does not wish to reveal
+ exactly why the request has been refused or when no other response is
+ applicable.
+
+13.1.4.3 client-error-not-authenticated (0x0402)
+
+ The request requires user authentication. The IPP client may repeat
+ the request with suitable authentication information. If the request
+ already included authentication information, then this status code
+ indicates that authorization has been refused for those credentials.
+ If this response contains the same challenge as the prior response,
+ and the user agent has already attempted authentication at least
+ once, then the response message may contain relevant diagnostic
+ information. This status codes reveals more information than
+ "client-error-forbidden".
+
+13.1.4.4 client-error-not-authorized (0x0403)
+
+ The requester is not authorized to perform the request. Additional
+ authentication information or authorization credentials will not help
+ and the request SHOULD NOT be repeated. This status code is used
+ when the IPP object wishes to reveal that the authentication
+ information is understandable, however, the requester is explicitly
+ not authorized to perform the request. This status codes reveals
+ more information than "client-error-forbidden" and "client-error-
+ not-authenticated".
+
+13.1.4.5 client-error-not-possible (0x0404)
+
+ This status code is used when the request is for something that can
+ not happen. For example, there might be a request to cancel a job
+ that has already been canceled or aborted by the system. The IPP
+ client SHOULD NOT repeat the request.
+
+13.1.4.6 client-error-timeout (0x0405)
+
+ The client did not produce a request within the time that the IPP
+ object was prepared to wait. For example, a client issued a Create-
+ Job operation and then, after a long period of time, issued a Send-
+ Document operation and this error status code was returned in
+ response to the Send-Document request (see section 3.3.1). The IPP
+ object might have been forced to clean up resources that had been
+ held for the waiting additional Documents. The IPP object was forced
+ to close the Job since the client took too long. The client SHOULD
+ NOT repeat the request without modifications.
+
+
+
+
+
+
+deBry, et al. Experimental [Page 148]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+13.1.4.7 client-error-not-found (0x0406)
+
+ The IPP object has not found anything matching the request URI. No
+ indication is given of whether the condition is temporary or
+ permanent. For example, a client with an old reference to a Job (a
+ URI) tries to cancel the Job, however in the mean time the Job might
+ have been completed and all record of it at the Printer has been
+ deleted. This status code, 'client-error-not-found' is returned
+ indicating that the referenced Job can not be found. This error
+ status code is also used when a client supplies a URI as a reference
+ to the document data in either a Print-URI or Send-URI operation, but
+ the document can not be found.
+
+ In practice, an IPP application should avoid a not found situation by
+ first querying and presenting a list of valid Printer URIs and Job
+ URIs to the end-user.
+
+13.1.4.8 client-error-gone (0x0407)
+
+ The requested object is no longer available and no forwarding address
+ is known. This condition should be considered permanent. Clients
+ with link editing capabilities should delete references to the
+ request URI after user approval. If the IPP object does not know or
+ has no facility to determine, whether or not the condition is
+ permanent, the status code "client-error-not-found" should be used
+ instead.
+
+ This response is primarily intended to assist the task of maintenance
+ by notifying the recipient that the resource is intentionally
+ unavailable and that the IPP object administrator desires that remote
+ links to that resource be removed. It is not necessary to mark all
+ permanently unavailable resources as "gone" or to keep the mark for
+ any length of time -- that is left to the discretion of the IPP
+ object administrator.
+
+13.1.4.9 client-error-request-entity-too-large (0x0408)
+
+ The IPP object is refusing to process a request because the request
+ entity is larger than the IPP object is willing or able to process.
+ An IPP Printer returns this status code when it limits the size of
+ print jobs and it receives a print job that exceeds that limit or
+ when the attributes are so many that their encoding causes the
+ request entity to exceed IPP object capacity.
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 149]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+13.1.4.10 client-error-request-value-too-long (0x0409)
+
+ The IPP object is refusing to service the request because one or more
+ of the client-supplied attributes has a variable length value that is
+ longer than the maximum length specified for that attribute. The IPP
+ object might not have sufficient resources (memory, buffers, etc.) to
+ process (even temporarily), interpret, and/or ignore a value larger
+ than the maximum length. Another use of this error code is when the
+ IPP object supports the processing of a large value that is less than
+ the maximum length, but during the processing of the request as a
+ whole, the object may pass the value onto some other system component
+ which is not able to accept the large value. For more details, see
+ the Implementer's Guide [ipp-iig] .
+
+ Note: For attribute values that are URIs, this rare condition is
+ only likely to occur when a client has improperly submitted a request
+ with long query information (e.g. an IPP application allows an end-
+ user to enter an invalid URI), when the client has descended into a
+ URI "black hole" of redirection (e.g., a redirected URI prefix that
+ points to a suffix of itself), or when the IPP object is under attack
+ by a client attempting to exploit security holes present in some IPP
+ objects using fixed-length buffers for reading or manipulating the
+ Request-URI.
+
+13.1.4.11 client-error-document-format-not-supported (0x040A)
+
+ The IPP object is refusing to service the request because the
+ document data is in a format, as specified in the "document-format"
+ operation attribute, that is not supported by the Printer object.
+ This error is returned independent of the client-supplied "ipp-
+ attribute-fidelity". The Printer object MUST return this status
+ code, even if there are other attributes that are not supported as
+ well, since this error is a bigger problem than with Job Template
+ attributes.
+
+13.1.4.12 client-error-attributes-or-values-not-supported (0x040B)
+
+ In a create request, if the Printer object does not support one or
+ more attributes, attribute syntaxes, or attribute values supplied in
+ the request and the client supplied the "ipp-attributes-fidelity"
+ operation attribute with the 'true' value, the Printer object MUST
+ return this status code. For example, if the request indicates '
+ iso-a4' media, but that media type is not supported by the Printer
+ object. Or, if the client supplies an optional attribute and the
+ attribute itself is not even supported by the Printer. If the "ipp-
+ attribute-fidelity" attribute is 'false', the Printer MUST ignore or
+ substitute values for unsupported attributes and values rather than
+ reject the request and return this status code.
+
+
+
+deBry, et al. Experimental [Page 150]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ For any operation where a client requests attributes (such as a Get-
+ Jobs, Get-Printer-Attributes, or Get-Job-Attributes operation), if
+ the IPP object does not support one or more of the requested
+ attributes, the IPP object simply ignores the unsupported requested
+ attributes and processes the request as if they had not been
+ supplied, rather than returning this status code. In this case, the
+ IPP object MUST return the 'successful-ok-ignored-or-substituted-
+ attributes' status code and MAY return the unsupported attributes as
+ values of the "requested-attributes" in the Unsupported Attributes
+ Group (see section 13.1.2.2).
+
+13.1.4.13 client-error-uri-scheme-not-supported (0x040C)
+
+ The type of the client supplied URI in a Print-URI or a Send-URI
+ operation is not supported.
+
+13.1.4.14 client-error-charset-not-supported (0x040D)
+
+ For any operation, if the IPP Printer does not support the charset
+ supplied by the client in the "attributes-charset" operation
+ attribute, the Printer MUST reject the operation and return this
+ status and any 'text' or 'name' attributes using the 'utf-8' charset
+ (see Section 3.1.4.1).
+
+13.1.4.15 client-error-conflicting-attributes (0x040E)
+
+ The request is rejected because some attribute values conflicted with
+ the values of other attributes which this specification does not
+ permit to be substituted or ignored.
+
+13.1.5 Server Error Status Codes
+
+ This class of status codes indicates cases in which the IPP object is
+ aware that it has erred or is incapable of performing the request.
+ The IPP object SHOULD include a message containing an explanation of
+ the error situation, and whether it is a temporary or permanent
+ condition.
+
+13.1.5.1 server-error-internal-error (0x0500)
+
+ The IPP object encountered an unexpected condition that prevented it
+ from fulfilling the request. This error status code differs from
+ "server-error-temporary-error" in that it implies a more permanent
+ type of internal error. It also differs from "server-error-device-
+ error" in that it implies an unexpected condition (unlike a paper-jam
+ or out-of-toner problem which is undesirable but expected). This
+ error status code indicates that probably some knowledgeable human
+ intervention is required.
+
+
+
+deBry, et al. Experimental [Page 151]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+13.1.5.2 server-error-operation-not-supported (0x0501)
+
+ The IPP object does not support the functionality required to fulfill
+ the request. This is the appropriate response when the IPP object
+ does not recognize an operation or is not capable of supporting it.
+
+13.1.5.3 server-error-service-unavailable (0x0502)
+
+ The IPP object is currently unable to handle the request due to a
+ temporary overloading or maintenance of the IPP object. The
+ implication is that this is a temporary condition which will be
+ alleviated after some delay. If known, the length of the delay may be
+ indicated in the message. If no delay is given, the IPP application
+ should handle the response as it would for a "server-error-
+ temporary-error" response. If the condition is more permanent, the
+ error status codes "client-error-gone" or "client-error-not-found"
+ could be used.
+
+13.1.5.4 server-error-version-not-supported (0x0503)
+
+ The IPP object does not support, or refuses to support, the IPP
+ protocol version that was used in the request message. The IPP
+ object is indicating that it is unable or unwilling to complete the
+ request using the same version as supplied in the request other than
+ with this error message. The response should contain a Message
+ describing why that version is not supported and what other versions
+ are supported by that IPP object.
+
+ A conforming IPP/1.0 client MUST specify the valid version ('1.0') on
+ each request. A conforming IPP/1.0 object MUST NOT return this
+ status code to a conforming IPP/1.0 client. An IPP object MUST
+ return this status code to a non-conforming IPP client. The response
+ MUST identify in the "version-number" operation attribute the closest
+ version number that the IPP object does support.
+
+13.1.5.5 server-error-device-error (0x0504)
+
+ A printer error, such as a paper jam, occurs while the IPP object
+ processes a Print or Send operation. The response contains the true
+ Job Status (the values of the "job-state" and "job-state-reasons"
+ attributes). Additional information can be returned in the optional
+ "job-state-message" attribute value or in the OPTIONAL status message
+ that describes the error in more detail. This error status code is
+ only returned in situations where the Printer is unable to accept the
+ create request because of such a device error. For example, if the
+ Printer is unable to spool, and can only accept one job at a time,
+ the reason it might reject a create request is that the printer
+ currently has a paper jam. In many cases however, where the Printer
+
+
+
+deBry, et al. Experimental [Page 152]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ object can accept the request even though the Printer has some error
+ condition, the 'successful-ok' status code will be returned. In such
+ a case, the client would look at the returned Job Object Attributes
+ or later query the Printer to determine its state and state reasons.
+
+13.1.5.6 server-error-temporary-error (0x0505)
+
+ A temporary error such as a buffer full write error, a memory
+ overflow (i.e. the document data exceeds the memory of the Printer),
+ or a disk full condition, occurs while the IPP Printer processes an
+ operation. The client MAY try the unmodified request again at some
+ later point in time with an expectation that the temporary internal
+ error condition may have been cleared. Alternatively, as an
+ implementation option, a Printer object MAY delay the response until
+ the temporary condition is cleared so that no error is returned.
+
+13.1.5.7 server-error-not-accepting-jobs (0x0506)
+
+ A temporary error indicating that the Printer is not currently
+ accepting jobs, because the administrator has set the value of the
+ Printer's "printer-is-not-accepting-jobs" attribute to 'false' (by
+ means outside of IPP/1.0).
+
+13.1.5.8 server-error-busy (0x0507)
+
+ A temporary error indicating that the Printer is too busy processing
+ jobs and/or other requests. The client SHOULD try the unmodified
+ request again at some later point in time with an expectation that
+ the temporary busy condition will have been cleared.
+
+13.1.5.9 server-error-job-canceled (0x0508)
+
+ An error indicating that the job has been canceled by an operator or
+ the system while the client was transmitting the data to the IPP
+ Printer. If a job-id and job-uri had been created, then they are
+ returned in the Print-Job, Send-Document, or Send-URI response as
+ usual; otherwise, no job-id and job-uri are returned in the response.
+
+13.2 Status Codes for IPP Operations
+
+ PJ = Print-Job, PU = Print-URI, CJ = Create-Job, SD = Send-Document
+ SU = Send-URI, V = Validate-Job, GA = Get-Job-Attributes and
+ Get-Printer-Attributes, GJ = Get-Jobs, C = Cancel-Job
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 153]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ IPP Operations
+ IPP Status Keyword PJ PU CJ SD SU V GA GJ C
+ ------------------ -- -- -- -- -- - -- -- -
+ successful-ok x x x x x x x x x
+ successful-ok-ignored-or-substituted- x x x x x x x x x
+ attributes
+ successful-ok-conflicting-attributes x x x x x x x x x
+ client-error-bad-request x x x x x x x x x
+ client-error-forbidden x x x x x x x x x
+ client-error-not-authenticated x x x x x x x x x
+ client-error-not-authorized x x x x x x x x x
+ client-error-not-possible x x x x x x x x x
+ client-error-timeout x x
+ client-error-not-found x x x x x x x x x
+ client-error-gone x x x x x x x x x
+ client-error-request-entity-too-large x x x x x x x x x
+ client-error-request-value-too-long x x x x x x x x x
+ client-error-document-format-not- x x x x x x
+ supported
+ client-error-attributes-or-values-not- x x x x x x x x x
+ supported
+ client-error-uri-scheme-not-supported x x
+ client-error-charset-not-supported x x x x x x x x x
+ client-error-conflicting-attributes x x x x x x x x x
+ server-error-internal-error x x x x x x x x x
+ server-error-operation-not-supported x x x x
+ server-error-service-unavailable x x x x x x x x x
+ server-error-version-not-supported x x x x x x x x x
+ server-error-device-error x x x x x
+ server-error-temporary-error x x x x x
+ server-error-not-accepting-jobs x x x x
+ server-error-busy x x x x x x x x x
+ server-error-job-canceled x x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 154]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+14. APPENDIX C: "media" keyword values
+
+ Standard keyword values are taken from several sources.
+
+ Standard values are defined (taken from DPA[ISO10175] and the Printer
+ MIB[RFC1759]):
+
+ 'default': The default medium for the output device
+ 'iso-a4-white': Specifies the ISO A4 white medium
+ 'iso-a4-colored': Specifies the ISO A4 colored medium
+ 'iso-a4-transparent' Specifies the ISO A4 transparent medium
+ 'iso-a3-white': Specifies the ISO A3 white medium
+ 'iso-a3-colored': Specifies the ISO A3 colored medium
+ 'iso-a5-white': Specifies the ISO A5 white medium
+ 'iso-a5-colored': Specifies the ISO A5 colored medium
+ 'iso-b4-white': Specifies the ISO B4 white medium
+ 'iso-b4-colored': Specifies the ISO B4 colored medium
+ 'iso-b5-white': Specifies the ISO B5 white medium
+ 'iso-b5-colored': Specifies the ISO B5 colored medium
+ 'jis-b4-white': Specifies the JIS B4 white medium
+ 'jis-b4-colored': Specifies the JIS B4 colored medium
+ 'jis-b5-white': Specifies the JIS B5 white medium
+ 'jis-b5-colored': Specifies the JIS B5 colored medium
+
+ The following standard values are defined for North American media:
+
+ 'na-letter-white': Specifies the North American letter white medium
+ 'na-letter-colored': Specifies the North American letter colored
+ medium
+ 'na-letter-transparent': Specifies the North American letter
+ transparent medium
+ 'na-legal-white': Specifies the North American legal white medium
+ 'na-legal-colored': Specifies the North American legal colored
+ medium
+
+ The following standard values are defined for envelopes:
+
+ 'iso-b4-envelope': Specifies the ISO B4 envelope medium
+ 'iso-b5-envelope': Specifies the ISO B5 envelope medium
+ 'iso-c3-envelope': Specifies the ISO C3 envelope medium
+ 'iso-c4-envelope': Specifies the ISO C4 envelope medium
+ 'iso-c5-envelope': Specifies the ISO C5 envelope medium
+ 'iso-c6-envelope': Specifies the ISO C6 envelope medium
+ 'iso-designated-long-envelope': Specifies the ISO Designated Long
+ envelope medium
+ 'na-10x13-envelope': Specifies the North American 10x13 envelope
+ medium
+
+
+
+
+deBry, et al. Experimental [Page 155]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'na-9x12-envelope': Specifies the North American 9x12 envelope
+ medium
+ 'monarch-envelope': Specifies the Monarch envelope
+ 'na-number-10-envelope': Specifies the North American number 10
+ business envelope medium
+ 'na-7x9-envelope': Specifies the North American 7x9 inch envelope
+ 'na-9x11-envelope': Specifies the North American 9x11 inch envelope
+ 'na-10x14-envelope': Specifies the North American 10x14 inch
+ envelope
+ 'na-number-9-envelope': Specifies the North American number 9
+ business envelope
+ 'na-6x9-envelope': Specifies the North American 6x9 inch envelope
+ 'na-10x15-envelope': Specifies the North American 10x15 inch
+ envelope
+
+ The following standard values are defined for the less commonly used
+ media (white-only):
+
+ 'executive-white': Specifies the white executive medium
+ 'folio-white': Specifies the folio white medium
+ 'invoice-white': Specifies the white invoice medium
+ 'ledger-white': Specifies the white ledger medium
+ 'quarto-white': Specified the white quarto medium
+ 'iso-a0-white': Specifies the ISO A0 white medium
+ 'iso-a1-white': Specifies the ISO A1 white medium
+ 'iso-a2-white': Specifies the ISO A2 white medium
+ 'iso-a6-white': Specifies the ISO A6 white medium
+ 'iso-a7-white': Specifies the ISO A7 white medium
+ 'iso-a8-white': Specifies the ISO A8 white medium
+ 'iso-a9-white': Specifies the ISO A9 white medium
+ 'iso-10-white': Specifies the ISO A10 white medium
+ 'iso-b0-white': Specifies the ISO B0 white medium
+ 'iso-b1-white': Specifies the ISO B1 white medium
+ 'iso-b2-white': Specifies the ISO B2 white medium
+ 'iso-b3-white': Specifies the ISO B3 white medium
+ 'iso-b6-white': Specifies the ISO B6 white medium
+ 'iso-b7-white': Specifies the ISO B7 white medium
+ 'iso-b8-white': Specifies the ISO B8 white medium
+ 'iso-b9-white': Specifies the ISO B9 white medium
+ 'iso-b10-white': Specifies the ISO B10 white medium
+ 'jis-b0-white': Specifies the JIS B0 white medium
+ 'jis-b1-white': Specifies the JIS B1 white medium
+ 'jis-b2-white': Specifies the JIS B2 white medium
+ 'jis-b3-white': Specifies the JIS B3 white medium
+ 'jis-b6-white': Specifies the JIS B6 white medium
+ 'jis-b7-white': Specifies the JIS B7 white medium
+
+
+
+
+
+deBry, et al. Experimental [Page 156]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'jis-b8-white': Specifies the JIS B8 white medium
+ 'jis-b9-white': Specifies the JIS B9 white medium
+ 'jis-b10-white': Specifies the JIS B10 white medium
+
+
+ The following standard values are defined for engineering media:
+
+ 'a': Specifies the engineering A size medium
+ 'b': Specifies the engineering B size medium
+ 'c': Specifies the engineering C size medium
+ 'd': Specifies the engineering D size medium
+ 'e': Specifies the engineering E size medium
+
+
+ The following standard values are defined for input-trays (from ISO
+ DPA and the Printer MIB):
+
+ 'top': The top input tray in the printer.
+ 'middle': The middle input tray in the printer.
+ 'bottom': The bottom input tray in the printer.
+ 'envelope': The envelope input tray in the printer.
+ 'manual': The manual feed input tray in the printer.
+ 'large-capacity': The large capacity input tray in the printer.
+ 'main': The main input tray
+ 'side': The side input tray
+
+
+ The following standard values are defined for media sizes (from ISO
+ DPA):
+
+ 'iso-a0': Specifies the ISO A0 size: 841 mm by 1189 mm as defined
+ in ISO 216
+ 'iso-a1': Specifies the ISO A1 size: 594 mm by 841 mm as defined in
+ ISO 216
+ 'iso-a2': Specifies the ISO A2 size: 420 mm by 594 mm as defined in
+ ISO 216
+ 'iso-a3': Specifies the ISO A3 size: 297 mm by 420 mm as defined in
+ ISO 216
+ 'iso-a4': Specifies the ISO A4 size: 210 mm by 297 mm as defined in
+ ISO 216
+ 'iso-a5': Specifies the ISO A5 size: 148 mm by 210 mm as defined in
+ ISO 216
+ 'iso-a6': Specifies the ISO A6 size: 105 mm by 148 mm as defined in
+ ISO 216
+ 'iso-a7': Specifies the ISO A7 size: 74 mm by 105 mm as defined in
+ ISO 216
+ 'iso-a8': Specifies the ISO A8 size: 52 mm by 74 mm as defined in
+ ISO 216
+
+
+
+deBry, et al. Experimental [Page 157]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'iso-a9': Specifies the ISO A9 size: 37 mm by 52 mm as defined in
+ ISO 216
+ 'iso-a10': Specifies the ISO A10 size: 26 mm by 37 mm as defined in
+ ISO 216
+ 'iso-b0': Specifies the ISO B0 size: 1000 mm by 1414 mm as defined
+ in ISO 216
+ 'iso-b1': Specifies the ISO B1 size: 707 mm by 1000 mm as defined
+ in ISO 216
+ 'iso-b2': Specifies the ISO B2 size: 500 mm by 707 mm as defined in
+ ISO 216
+ 'iso-b3': Specifies the ISO B3 size: 353 mm by 500 mm as defined in
+ ISO 216
+ 'iso-b4': Specifies the ISO B4 size: 250 mm by 353 mm as defined in
+ ISO 216
+ 'iso-b5': Specifies the ISO B5 size: 176 mm by 250 mm as defined in
+ ISO 216
+ 'iso-b6': Specifies the ISO B6 size: 125 mm by 176 mm as defined in
+ ISO 216
+ 'iso-b7': Specifies the ISO B7 size: 88 mm by 125 mm as defined in
+ ISO 216
+ 'iso-b8': Specifies the ISO B8 size: 62 mm by 88 mm as defined in
+ ISO 216
+ 'iso-b9': Specifies the ISO B9 size: 44 mm by 62 mm as defined in
+ ISO 216
+ 'iso-b10': Specifies the ISO B10 size: 31 mm by 44 mm as defined in
+ ISO 216
+ 'na-letter': Specifies the North American letter size: 8.5 inches by
+ 11 inches
+ 'na-legal': Specifies the North American legal size: 8.5 inches by
+ 14 inches
+ 'executive': Specifies the executive size (7.25 X 10.5 in)
+ 'folio': Specifies the folio size (8.5 X 13 in)
+ 'invoice': Specifies the invoice size (5.5 X 8.5 in)
+ 'ledger': Specifies the ledger size (11 X 17 in)
+ 'quarto': Specifies the quarto size (8.5 X 10.83 in)
+ 'iso-c3': Specifies the ISO C3 size: 324 mm by 458 mm as defined in
+ ISO 269
+ 'iso-c4': Specifies the ISO C4 size: 229 mm by 324 mm as defined in
+ ISO 269
+ 'iso-c5': Specifies the ISO C5 size: 162 mm by 229 mm as defined in
+ ISO 269
+ 'iso-c6': Specifies the ISO C6 size: 114 mm by 162 mm as defined in
+ ISO 269
+ 'iso-designated-long': Specifies the ISO Designated Long size: 110
+ mm by 220 mm as defined in ISO 269
+ 'na-10x13-envelope': Specifies the North American 10x13 size: 10
+ inches by 13 inches
+
+
+
+
+deBry, et al. Experimental [Page 158]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 'na-9x12-envelope': Specifies the North American 9x12 size: 9
+ inches by 12 inches
+ 'na-number-10-envelope': Specifies the North American number 10
+ business envelope size: 4.125 inches by 9.5 inches
+ 'na-7x9-envelope': Specifies the North American 7x9 inch envelope
+ size
+ 'na-9x11-envelope': Specifies the North American 9x11 inch envelope
+ size
+ 'na-10x14-envelope': Specifies the North American 10x14 inch
+ envelope size
+ 'na-number-9-envelope': Specifies the North American number 9
+ business envelope size
+ 'na-6x9-envelope': Specifies the North American 6x9 envelope size
+ 'na-10x15-envelope': Specifies the North American 10x15 envelope
+ size
+ 'monarch-envelope': Specifies the Monarch envelope size (3.87 x 7.5
+ in)
+ 'jis-b0': Specifies the JIS B0 size: 1030mm x 1456mm
+ 'jis-b1': Specifies the JIS B1 size: 728mm x 1030mm
+ 'jis-b2': Specifies the JIS B2 size: 515mm x 728mm
+ 'jis-b3': Specifies the JIS B3 size: 364mm x 515mm
+ 'jis-b4': Specifies the JIS B4 size: 257mm x 364mm
+ 'jis-b5': Specifies the JIS B5 size: 182mm x 257mm
+ 'jis-b6': Specifies the JIS B6 size: 128mm x 182mm
+ 'jis-b7': Specifies the JIS B7 size: 91mm x 128mm
+ 'jis-b8': Specifies the JIS B8 size: 64mm x 91mm
+ 'jis-b9': Specifies the JIS B9 size: 45mm x 64mm
+ 'jis-b10': Specifies the JIS B10 size: 32mm x 45mm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 159]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+15. APPENDIX D: Processing IPP Attributes
+
+ When submitting a print job to a Printer object, the IPP model allows
+ a client to supply operation and Job Template attributes along with
+ the document data. These Job Template attributes in the create
+ request affect the rendering, production and finishing of the
+ documents in the job. Similar types of instructions may also be
+ contained in the document to be printed, that is, embedded within the
+ print data itself. In addition, the Printer has a set of attributes
+ that describe what rendering and finishing options which are
+ supported by that Printer. This model, which allows for flexibility
+ and power, also introduces the potential that at job submission time,
+ these client-supplied attributes may conflict with either:
+
+ - what the implementation is capable of realizing (i.e., what the
+ Printer supports), as well as
+ - the instructions embedded within the print data itself.
+
+ The following sections describe how these two types of conflicts are
+ handled in the IPP model.
+
+15.1 Fidelity
+
+ If there is a conflict between what the client requests and what a
+ Printer object supports, the client may request one of two possible
+ conflict handling mechanisms:
+
+ 1) either reject the job since the job can not be processed exactly
+ as specified, or
+ 2) allow the Printer to make any changes necessary to proceed with
+ processing the Job the best it can.
+
+ In the first case the client is indicating to the Printer object:
+ "Print the job exactly as specified with no exceptions, and if that
+ can't be done, don't even bother printing the job at all." In the
+ second case, the client is indicating to the Printer object: "It is
+ more important to make sure the job is printed rather than be
+ processed exactly as specified; just make sure the job is printed
+ even if client supplied attributes need to be changed or ignored."
+
+ The IPP model accounts for this situation by introducing an "ipp-
+ attribute-fidelity" attribute.
+
+ In a create request, "ipp-attribute-fidelity" is a boolean operation
+ attribute that is OPTIONALLY supplied by the client. The value '
+ true' indicates that total fidelity to client supplied Job Template
+ attributes and values is required. The client is requesting that the
+ Job be printed exactly as specified, and if that is not possible then
+
+
+
+deBry, et al. Experimental [Page 160]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ the job MUST be rejected rather than processed incorrectly. The
+ value 'false' indicates that a reasonable attempt to print the Job is
+ acceptable. If a Printer does not support some of the client
+ supplied Job Template attributes or values, the Printer MUST ignore
+ them or substitute any supported value for unsupported values,
+ respectively. The Printer may choose to substitute the default value
+ associated with that attribute, or use some other supported value
+ that is similar to the unsupported requested value. For example, if
+ a client supplies a "media" value of 'na-letter', the Printer may
+ choose to substitute 'iso-a4' rather than a default value of '
+ envelope'. If the client does not supply the "ipp-attribute-fidelity"
+ attribute, the Printer assumes a value of 'false'.
+
+ Each Printer implementation MUST support both types of "fidelity"
+ printing (that is whether the client supplies a value of 'true' or '
+ false'):
+
+ - If the client supplies 'false' or does not supply the attribute,
+ the Printer object MUST always accept the request by ignoring
+ unsupported Job Template attributes and by substituting
+ unsupported values of supported Job Template attributes with
+ supported values.
+ - If the client supplies 'true', the Printer object MUST reject the
+ request if the client supplies unsupported Job Template
+ attributes.
+
+ Since a client can always query a Printer to find out exactly what is
+ and is not supported, "ipp-attribute-fidelity" set to 'false' is
+ useful when:
+
+ 1) The End-User uses a command line interface to request attributes
+ that might not be supported.
+ 2) In a GUI context, if the End User expects the job might be moved
+ to another printer and prefers a sub-optimal result to nothing
+ at all.
+ 3) The End User just wants something reasonable in lieu of nothing
+ at all.
+
+15.2 Page Description Language (PDL) Override
+
+ If there is a conflict between the value of an IPP Job Template
+ attribute and a corresponding instruction in the document data, the
+ value of the IPP attribute SHOULD take precedence over the document
+ instruction. Consider the case where a previously formatted file of
+ document data is sent to an IPP Printer. In this case, if the client
+ supplies any attributes at job submission time, the client desires
+ that those attributes override the embedded instructions. Consider
+ the case were a previously formatted document has embedded in it
+
+
+
+deBry, et al. Experimental [Page 161]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ commands to load 'iso-a4' media. However, the document is passed to
+ an end user that only has access to a printer with 'na-letter' media
+ loaded. That end user most likely wants to submit that document to
+ an IPP Printer with the "media" Job Template attribute set to 'na-
+ letter'. The job submission attribute should take precedence over
+ the embedded PDL instruction. However, until companies that supply
+ document data interpreters allow a way for external IPP attributes to
+ take precedence over embedded job production instructions, a Printer
+ might not be able to support the semantics that IPP attributes
+ override the embedded instructions.
+
+ The IPP model accounts for this situation by introducing a "pdl-
+ override-supported" attribute that describes the Printer objects
+ capabilities to override instructions embedded in the PDL data
+ stream. The value of the "pdl-override-supported" attribute is
+ configured by means outside IPP/1.0.
+
+ This REQUIRED Printer attribute takes on the following values:
+
+ - 'attempted': This value indicates that the Printer object
+ attempts to make the IPP attribute values take precedence over
+ embedded instructions in the document data, however there is no
+ guarantee.
+ - 'not-attempted': This value indicates that the Printer object
+ makes no attempt to make the IPP attribute values take precedence
+ over embedded instructions in the document data.
+
+ At job processing time, an implementation that supports the value of
+ 'attempted' might do one of several different actions:
+
+ 1) Generate an output device specific command sequence to realize
+ the feature represented by the IPP attribute value.
+ 2) Parse the document data itself and replace the conflicting
+ embedded instruction with a new embedded instruction that
+ matches the intent of the IPP attribute value.
+ 3) Indicate to the Printer that external supplied attributes take
+ precedence over embedded instructions and then pass the external
+ IPP attribute values to the document data interpreter.
+ 4) Anything else that allows for the semantics that IPP attributes
+ override embedded document data instructions.
+
+ Since 'attempted' does not offer any type of guarantee, even though a
+ given Printer object might not do a very "good" job of attempting to
+ ensure that IPP attributes take a higher precedence over instructions
+ embedded in the document data, it would still be a conforming
+ implementation.
+
+
+
+
+
+deBry, et al. Experimental [Page 162]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ At job processing time, an implementation that supports the value of
+ 'not-attempted' might do one of the following actions:
+
+ 1) Simply pre-pend the document data with the PDL instruction that
+ corresponds to the client-supplied PDL attribute, such that if
+ the document data also has the same PDL instruction, it will
+ override what the Printer object pre-pended. In other words,
+ this implementation is using the same implementation semantics
+ for the client-supplied IPP attributes as for the Printer object
+ defaults.
+ 2) Parse the document data and replace the conflicting embedded
+ instruction with a new embedded instruction that approximates,
+ but does not match, the semantic intent of the IPP attribute
+ value.
+
+ Note: The "ipp-attribute-fidelity" attribute applies to the
+ Printer's ability to either accept or reject other unsupported Job
+ Template attributes. In other words, if "ipp-attribute-fidelity" is
+ set to 'true', a Job is accepted if and only if the client supplied
+ Job Template attributes and values are supported by the Printer.
+ Whether these attributes actually affect the processing of the Job
+ when the document data contains embedded instructions depends on the
+ ability of the Printer to override the instructions embedded in the
+ document data with the semantics of the IPP attributes. If the
+ document data attributes can be overridden ("pdl-override-supported"
+ set to 'attempted'), the Printer makes an attempt to use the IPP
+ attributes when processing the Job. If the document data attributes
+ can not be overridden ("pdl-override-supported" set to 'not-
+ attempted'), the Printer makes no attempt to override the embedded
+ document data instructions with the IPP attributes when processing
+ the Job, and hence, the IPP attributes may fail to affect the Job
+ processing and output when the corresponding instruction is embedded
+ in the document data.
+
+15.3 Using Job Template Attributes During Document Processing.
+
+ The Printer object uses some of the Job object's Job Template
+ attributes during the processing of the document data associated with
+ that job. These include, but are not limited to, "orientation",
+ "number-up", "sides", "media", and "copies". The processing of each
+ document in a Job Object MUST follow the steps below. These steps are
+ intended only to identify when and how attributes are to be used in
+ processing document data and any alternative steps that accomplishes
+ the same effect can be used to implement this specification.
+
+ 1. Using the client supplied "document-format" attribute or some
+ form of document format detection algorithm (if the value of
+ "document- format" is not specific enough), determine whether or
+
+
+
+deBry, et al. Experimental [Page 163]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ not the document data has already been formatted for printing.
+ If the document data has been formatted, then go to step 2.
+ Otherwise, the document data MUST be formatted. The formatting
+ detection algorithm is implementation defined and is not
+ specified by this specification. The formatting of the document
+ data uses the "orientation-requested" attribute to determine how
+ the formatted print data should be placed on a print-stream
+ page, see section 4.2.10 for the details.
+
+ 2. The document data is in the form of a print-stream in a known
+ media type. The "page-ranges" attribute is used to select, as
+ specified in section 4.2.7, a sub-sequence of the pages in the
+ print-stream that are to be processed and images.
+
+ 3. The input to this step is a sequence of print-stream pages. This
+ step is controlled by the "number-up" attribute. If the value of
+ "number-up" is N, then during the processing of the print-stream
+ pages, each N print-stream pages are positioned, as specified in
+ section 4.2.9, to create a single impression. If a given
+ document does not have N more print-stream pages, then the
+ completion of the impression is controlled by the "multiple-
+ document-handling" attribute as described in section 4.2.4; when
+ the value of this attribute is 'single-document' or 'single-
+ document-new-sheet', the print-stream pages of document data
+ from subsequent documents is used to complete the impression.
+
+ The size(scaling), position(translation) and rotation of the
+ print-stream pages on the impression is implementation defined.
+ Note that during this process the print-stream pages may be
+ rendered to a form suitable for placing on the impression; this
+ rendering is controlled by the values of the "printer-
+ resolution" and "print- quality" attributes as described in
+ sections 4.2.12 and 4.2.13. In the case N=1, the impression is
+ nearly the same as the print-stream page; the differences would
+ only be in the size, position and rotation of the print-stream
+ page and/or any decoration, such as a frame to the page, that is
+ added by the implementation.
+
+ 4. The collection of impressions is placed, in sequence, onto sides
+ of the media sheets. This placement is controlled by the "sides"
+ attribute and the orientation of the print-stream page, as
+ described in section 4.2.8. The orientation of the print-stream
+ pages affects the orientation of the impression; for example, if
+ "number-up" equals 2, then, typically, two portrait print-stream
+ pages become one landscape impression. Note that the placement
+ of impressions onto media sheets is also controlled by the
+ "multiple-document-handling" attribute as described in section
+ 4.2.4.
+
+
+
+deBry, et al. Experimental [Page 164]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 5. The "copies" and "multiple-document-handling" attributes are
+ used to determine how many copies of each media instance are
+ created and in what order. See sections 4.2.5 and 4.2.4 for the
+ details.
+
+ 6. When the correct number of copies are created, the media
+ instances are finished according to the values of the
+ "finishings" attribute as described in 4.2.6. Note that
+ sometimes finishing operations may require manual intervention
+ to perform the finishing operations on the copies, especially
+ uncollated copies. This specification allows any or all of the
+ processing steps to be performed automatically or manually at
+ the discretion of the Printer object.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 165]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+16. APPENDIX E: Generic Directory Schema
+
+ This section defines a generic schema for an entry in a directory
+ service. A directory service is a means by which service users can
+ locate service providers. In IPP environments, this means that IPP
+ Printers can be registered (either automatically or with the help of
+ an administrator) as entries of type printer in the directory using
+ an implementation specific mechanism such as entry attributes, entry
+ type fields, specific branches, etc. IPP clients can search or
+ browse for entries of type printer. Clients use the directory
+ service to find entries based on naming, organizational contexts, or
+ filtered searches on attribute values of entries. For example, a
+ client can find all printers in the "Local Department" context.
+ Authentication and authorization are also often part of a directory
+ service so that an administrator can place limits on end users so
+ that they are only allowed to find entries to which they have certain
+ access rights. IPP itself does not require any specific directory
+ service protocol or provider.
+
+ Note: Some directory implementations allow for the notion of
+ "aliasing". That is, one directory entry object can appear as
+ multiple directory entry object with different names for each object.
+ In each case, each alias refers to the same directory entry object
+ which refers to a single IPP Printer object.
+
+ The generic schema is a subset of IPP Printer Job Template and
+ Printer Description attributes (sections 4.2 and 4.4). These
+ attributes are identified as either RECOMMENDED or OPTIONAL for the
+ directory entry itself. This conformance labeling is NOT the same
+ conformance labeling applied to the attributes of IPP Printers
+ objects. The conformance labeling in this Appendix is intended to
+ apply to directory templates and to IPP Printer implementations that
+ subscribe by adding one or more entries to a directory. RECOMMENDED
+ attributes SHOULD be associated with each directory entry. OPTIONAL
+ attributes MAY be associated with the directory entry (if known or
+ supported). In addition, all directory entry attributes SHOULD
+ reflect the current attribute values for the corresponding Printer
+ object.
+
+ The names of attributes in directory schema and entries SHOULD be the
+ same as the IPP Printer attribute names as shown.
+
+ In order to bridge between the directory service and the IPP Printer
+ object, one of the RECOMMENDED directory entry attributes is the
+ Printer object's "printer-uri-supported" attribute. The IPP client
+ queries the "printer-uri-supported" attribute in the directory entry
+
+
+
+
+
+deBry, et al. Experimental [Page 166]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ and then addresses the IPP Printer object using one of its URIs. The
+ "uri-security-supported" attribute identifies the protocol (if any)
+ used to secure a channel.
+
+ The following attributes define the generic schema for directory
+ entries of type PRINTER:
+
+ printer-uri-supported RECOMMENDED Section 4.4.1
+ uri-security-supported RECOMMENDED Section 4.4.2
+ printer-name RECOMMENDED Section 4.4.3
+ printer-location RECOMMENDED Section 4.4.4
+ printer-info OPTIONAL Section 4.4.5
+ printer-more-info OPTIONAL Section 4.4.6
+ printer-make-and-model RECOMMENDED Section 4.4.8
+ charset-supported OPTIONAL Section 4.4.15
+ generated-natural-language-
+ supported OPTIONAL Section 4.4.17
+ document-format-supported RECOMMENDED Section 4.4.19
+ color-supported RECOMMENDED Section 4.4.23
+ finishings-supported OPTIONAL Section 4.2.6
+ number-up-supported OPTIONAL Section 4.2.7
+ sides-supported RECOMMENDED Section 4.2.8
+ media-supported RECOMMENDED Section 4.2.11
+ printer-resolution-supported OPTIONAL Section 4.2.12
+ print-quality-supported OPTIONAL Section 4.2.13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 167]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+17. APPENDIX F: Change History for the IPP Model and Semantics document
+
+ The following substantive changes and major clarifications have been
+ made to this document from the June 30, 1998 version based on the
+ interoperability testing that took place September 23-25 1998 and
+ subsequent mailing list and meeting discussions. They are listed in
+ the order of occurrence in the document. These changes are the ones
+ that might affect implementations. Clarifications that are unlikely
+ to affect implementations are not listed. The issue numbers refer to
+ the IPP Issues List which is available in the following directory:
+
+ ftp://ftp.pwg.org/pub/pwg/ipp/approved-clarifications/
+
+ Section Description
+
+ global Replaced TLS references with SSL3 references as agreed with
+ our Area Director on 11/12/1998.
+
+ global Removed the indications that some of these IPP documents
+ are informational, since the intent is now to publish all
+ IPP/1.0 documents as informational as agreed with our Area
+ Director on 11/12/1998.
+
+ 3.1.2, Clarify that the IPP object SHOULD NOT validate the
+ 16.3.3 range of the request-id being 1 to 2**31-1, but accepts
+ [now ipp- and returns any value. Clients MUST still keep in the
+ iig] range 1 to 2**31 though. If the request is terminated
+ before the complete "request-id" is received, the IPP
+ object rejects the request and returns a response with a
+ "request-id" of 0 (Issue 1.36).
+
+ 3.1.4.1, Clarified that when a client submits a request in a
+ 13.1.4.14 charset that is not supported, the IPP object SHOULD
+ return any 'text' or 'name' attributes in the 'utf-8'
+ charset, if it returns any, since clients and IPP
+ objects MUST support 'utf-8'. (Issue 1.19)
+
+ 3.1.4.1 Clarified Section 3.1.4.1 Request Operation Attributes
+ that a client MAY use the attribute level natural
+ language override (text/nameWithLanguage) redundantly in
+ a request. (Issue 1.46)
+
+ 3.1.4.2 Clarified Section 3.1.4.2 Response Operation Attributes
+ that an IPP object MAY use the attribute level natural
+ language override (text/nameWithLanguage) redundantly in
+ a response. (Issue 1.46)
+
+
+
+
+
+deBry, et al. Experimental [Page 168]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 3.1.6 Clarified section 3.1.6: If the Printer object supports
+ the "status-message" operation attribute, it NEED NOT
+ return a status message for the following error status
+ codes: 'client-error-bad-request', 'client-error-
+ charset-not-supported', 'server-error-internal-error',
+ 'server-error-operation-not-supported', and 'server-
+ error-version-not-supported'.
+
+ 3.2.1.1 Clarified that if a client is not supplying any Job
+ Template attributes in a request, the client SHOULD omit
+ Group 2 rather than sending an empty group. However, a
+ Printer object MUST be able to accept an empty group.
+ This makes [RFC2566] agree with [RFC2565]. (Issue 1.16)
+
+ 3.2.1.2, Clarified that if an IPP object is not returning any
+ 3.2.5.2, Unsupported Attributes in a response, the IPP object
+ 3.2.6.2, SHOULD omit Group 2 rather than sending an empty group.
+ 3.3.1.2, However, a client MUST be able to accept an empty group.
+ 3.3.3.2, This makes [RFC2566] agree with [RFC2565]. (Issue 1.17)
+ 3.3.4.2
+
+ 3.2.1.2, Clarified that an IPP object MUST treat an unsupported
+ 13.1.2.2, attribute syntax supplied in a request in the same way
+ 13.1.4.12 as an unsupported value. The IPP object MUST return the
+ attribute, the attribute syntax, and the value in the
+ Unsupported Attributes group. (Issue 1.26)
+
+ 3.2.5.2, Clarified for Get-Printer-Attributes, Get-Jobs, and Get-
+ 3.2.6.2, Job-Attributes that an IPP object MUST return
+ 3.3.4.2, 'successful-ok-ignored-or-substituted-attributes' (0x1),
+
+ 13.1.2.1, rather than 'successful-ok' (0x0), when a client
+ 13.1.2.2, supplies unsupported attributes as values of the
+ 13.1.4.12 'requested-attributes' operation attribute. (Issue
+ 1.24)
+ Also clarified that the response NEED NOT contain the
+ "requested-attributes" operation attribute with any
+ supplied values (attribute keywords) that were requested
+ by the client but are not supported by the IPP object.
+ (Issue 1.18)
+
+ 3.2.6.2 Deleted the job-level natural language override (NLO)
+ 4.1.1.2 from Section 3.2.6.2 Get-Jobs Response so that all
+ 4.3.24 operation responses are the same with respect to NLO.
+ (Issue 1.47)
+
+
+
+
+
+
+deBry, et al. Experimental [Page 169]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 3.3.1 Clarified that an IPP Printer that supports the Create-
+ Job operation MUST handle the situation when a client
+ does not supply Send-Document or Send-URI operations
+ within a one- to four-minute time period. Also
+ clarified that a client MUST send documents in a multi-
+ document job without undue or unbounded delay. (Issue
+ 1.28)
+
+ 3.3.3 Clarified that the IPP object MUST reject a Cancel-Job
+ request if the job is in 'completed', 'canceled', or
+ 'aborted' job states. (Issue 1.12)
+
+ 4.1.2.3 Added this new sub-section: it specifies that
+ nameWithoutLanguage plus the implicit natural language
+ matches nameWithLanguage, if the values and natural
+ languages are the same. Also added that keyword never
+ matches nameWithLanguage or nameWithoutLanguage.
+ Clarified that if both have countries, that the
+ countries SHOULD match as well. If either do not, then
+ the country field SHOULD be ignored. (Issues 1.33 and
+ 1.34)
+
+ 4.1.5 Clarified regarding the case-insensitivity of URLs to
+ refer only to the RFCs that define them. (Issue 1.10)
+
+ 4.1.11 Clarified that 'boolean' is not a full-sized integer.
+ (Issue 1.38)
+
+ 4.1.15 Clarified that 'resolution' is not three full-sized
+ integers. (Issue 1.20)
+
+ 4.2.* Clarified that standard values are keywords or enums,
+ not names. (Issue 1.49).
+
+ 4.2.4 Added the 'single-document-new-sheet' value to Section
+ 4.2.4 multiple-document-handling. (Issue 1.54)
+
+ 4.4.18, Clarified that the "document-format-default" and
+ 4.4.19 "document-format-supported" Printer Description
+ attributes are REQUIRED to agree with the table. (Issue
+ 1.4)
+
+ 4.4.21 Changed "queued-job-count" from OPTIONAL to RECOMMENDED.
+ (Issue 1.14)
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 170]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 4.4.28 Clarified that the implementation supplied value for the
+ "multiple-operation-time-out" attribute SHOULD be
+ between 30 and 240 seconds, though the implementation
+ MAY allow the administrator to set values, and MAY allow
+ values outside this range. (Issue 1.28)
+
+ 5.1, Clarified Client Conformance that if a client supports
+ 5.2.5 an attribute of 'text' attribute syntax, that it MUST
+ support both the textWithoutLanguage and the
+ textWithLanguage forms. Same for 'name' attribute
+ syntax. Same for an IPP object (Issue 1.48)
+
+ 6.5, Added new section to allow Attribute Groups to be
+ 12.8 registered as extensions for being passed in operation
+ requests and responses. (Issue 1.25)
+
+ 7. Updated the table of text and name attributes to agree
+ with Section 4.2.
+
+ 8.5 Added a new section RECOMMENDING that the Get-Jobs
+ SHOULD return non-IPP jobs whether or not assigning them
+ a job-id and job-uri. Also RECOMMENDED generating, if
+ possible, job-id and job-uri and supporting other IPP
+ operations on foreign jobs as an implementer option.
+ (Issue 1.32)
+
+ 9. Updated document references.
+
+ 13.1.4.14 Clarified 'client-error-charset-not-supported' that
+ 'utf-8' must be used for any 'text' or 'name' attributes
+ returned in the error response (Issue 1.19).
+
+ 13.1.5.9 Added a new error code 'server-error-job-canceled'
+ (0x0508) to be returned if a job is canceled by another
+ client or aborted by the IPP object while the first
+ client is still sending the document data. (Issue 1.29)
+
+ 15.3, Moved these sections recommending operation processing
+ 15.4 steps to the new Implementer's Guide (informational).
+ There indicated that all of the error checks are not
+ required, so an IPP object MAY be forgiving and accept
+ non-conforming requests. However, a conforming client
+ MUST supply requests that would pass all of the error
+ checks indicated. (Issue 1.21)
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 171]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+ 16 Changed directory schema attributes from REQUIRED to
+ RECOMMENDED. Changed some of the OPTIONAL to
+ RECOMMENDED to agree with the SLP template. Changed the
+ "charset-supported" and "natural-language-supported"
+ from REQUIRED to OPTIONAL. Recommended that the names
+ be the same in a directory entry as the IPP attribute
+ names. (Issue 1.53)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 172]
+
+RFC 2566 IPP/1.0: Model and Semantics April 1999
+
+
+18. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et al. Experimental [Page 173]
+
diff --git a/standards/rfc2567.txt b/standards/rfc2567.txt
new file mode 100644
index 000000000..d5ef440be
--- /dev/null
+++ b/standards/rfc2567.txt
@@ -0,0 +1,2411 @@
+
+
+
+
+
+
+Network Working Group F.D. Wright
+Request for Comments: 2567 Lexmark International
+Category: Experimental April 1999
+
+
+ Design Goals for an Internet Printing Protocol
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note
+
+ This document defines an Experimental protocol for the Internet
+ community. The IESG expects that a revised version of this protocol
+ will be published as Proposed Standard protocol. The Proposed
+ Standard, when published, is expected to change from the protocol
+ defined in this memo. In particular, it is expected that the
+ standards-track version of the protocol will incorporate strong
+ authentication and privacy features, and that an "ipp:" URL type will
+ be defined which supports those security measures. Other changes to
+ the protocol are also possible. Implementers are warned that future
+ versions of this protocol may not interoperate with the version of
+ IPP defined in this document, or if they do interoperate, that some
+ protocol features may not be available.
+
+ The IESG encourages experimentation with this protocol, especially in
+ combination with Transport Layer Security (TLS) [RFC2246], to help
+ determine how TLS may effectively be used as a security layer for
+ IPP.
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document takes a broad
+ look at distributed printing functionality, and it enumerates real-
+ life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+
+
+
+Wright Experimental [Page 1]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ administrators. The design goals document calls out a subset of end
+ user requirements that are satisfied in IPP/1.0. Operator and
+ administrator requirements are out of scope for version 1.0.
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol (this document)
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics [RFC2568]
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Internet Printing Protocol/1.0: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specifications, and gives background and rationale for the
+ IETF working group's major decisions.
+
+ The "Internet Printing Protocol/1.0: Model and Semantics" document
+ describes a simplified model consisting of abstract objects, their
+ attributes, and their operations that is independent of encoding and
+ transport. The model consists of a Printer and a Job object. The
+ Job optionally supports multiple documents. IPP 1.0 semantics allow
+ end-users and operators to query printer capabilities, submit print
+ jobs, inquire about the status of print jobs and printers, and cancel
+ print jobs. This document also addresses security,
+ internationalization, and directory issues.
+
+ The "Internet Printing Protocol/1.0: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1. It defines the encoding rules
+ for a new Internet media type called "application/ipp".
+
+ The "Internet Printing Protocol/1.0: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.0 and some of
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+
+
+
+
+Wright Experimental [Page 2]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+TABLE OF CONTENTS
+
+ 1. INTRODUCTION.....................................................4
+ 2. TERMINOLOGY......................................................4
+ 3. DESIGN GOALS.....................................................6
+ 3.1. End-user.......................................................6
+ 3.1.1. Finding or locating a printer................................6
+ 3.1.2. Create an instance of the printer............................7
+ 3.1.3. Viewing the status and capabilities of a printer.............7
+ 3.1.4. Submitting a print job.......................................8
+ 3.1.5. Viewing the status of a submitted print job..................9
+ 3.1.6. Canceling a Print Job........................................9
+ 3.2. Operator (NOT REQUIRED FOR V1.0)...............................9
+ 3.2.1. Alerting.....................................................9
+ 3.2.2. Changing Print and Job Status...............................10
+ 3.3. Administrator (NOT REQUIRED FOR v1.0).........................10
+ 4. OBJECTIVES OF THE PROTOCOL......................................10
+ 4.1. SECURITY CONSIDERATIONS.......................................11
+ 4.2. Interaction with LPD (RFC1179)................................12
+ 4.3. Extensibility.................................................12
+ 4.4. Firewalls.....................................................13
+ 4.5. Internationalization..........................................13
+ 5. IPP SCENARIOS...................................................13
+ 5.1. Printer Discovery.............................................14
+ 5.2. Driver Installation...........................................15
+ 5.3. Submitting a Print Job........................................15
+ 5.4. Getting Status/Capabilities...................................16
+ 5.5. Asynchronous Notification.....................................17
+ 5.6. Job Canceling.................................................17
+ 6. Security Considerations.........................................18
+ 7. REFERENCES......................................................18
+ 8. ACKNOWLEDGMENTS.................................................19
+ 9. AUTHOR'S ADDRESS................................................19
+ 10. APPENDIX - DETAILED SCENARIOS..................................20
+ 10.1. Printer discovery within an enterprise.......................20
+ 10.2. Printer discovery across enterprises.........................21
+ 10.3. Printer discovery on the Internet -logical operations........21
+ 10.4. Printer discovery on the Internet - authentication...........22
+ 10.5. Driver Download..............................................23
+ 10.6. Submitting a print job as a file.............................24
+ 10.7. Submitting a print job with two documents....................24
+ 10.8. Submitting a print job as a file, printing fails.............25
+ 10.9. Submitting a print job with authentication, PRIVACY and
+ payment......................................................26
+ 10.10. Submitting a print job with decryption error................27
+ 10.11. Submitting a print job with authentication..................28
+ 10.12. Submitting a print job generated dynamically................29
+ 10.13. Submitting a print job with a Printer jam - CANCELED........29
+
+
+
+Wright Experimental [Page 3]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ 10.14. Submitting a print job with a Printer jam - recovered.......30
+ 10.15. Submitting a print job with server pull.....................31
+ 10.16. Submitting a print job with referenced resources............32
+ 10.17. Getting Capabilities........................................33
+ 10.17.1. Submission Attributes.....................................33
+ 10.17.2. Printer Capabilities......................................33
+ 10.18. Getting Status..............................................34
+ 10.18.1. Printer State/Status......................................34
+ 10.18.2. Job Status................................................34
+ 10.18.3. Status of All My Jobs.....................................34
+ 10.19. Asynchronous Notification...................................35
+ 10.19.1. Job Completion............................................35
+ 10.19.2. Job Complete with Data....................................35
+ 10.19.3. Print Job Fails...........................................35
+ 10.20. Cancel a job................................................36
+ 10.21. End to end Scenario - within an enterprise..................36
+ 10.22. End to end Scenario - across enterprises....................37
+ 10.23. End to End Scenario - on the internet.......................40
+ 11. Full Copyright Statement.......................................43
+
+1. INTRODUCTION
+
+ The IPP protocol is heavily influenced by the printing model
+ introduced in the Document Printing Application (DPA) [ISO10175]
+ standard. Although DPA specifies both end user and administrative
+ features, IPP version 1.0 (IPP/1.0) focuses only on end user
+ functionality.
+
+2. TERMINOLOGY
+
+ Internet Printing for the purposes of this document is the
+ application of Internet tools, programs, servers and networks to
+ allow end-users to print to a remote printer using, after initial
+ setup or configuration, the same methods, operations and paradigms as
+ would be used for a locally attached or a local area network attached
+ printer. This could include the use of HTTP servers and browsers and
+ other applications for providing static, dynamic and interactive
+ printer locating services, user installation, selection,
+ configuration, print job submission, printer capability inquiry and
+ status inquiry of remote printers and jobs.
+
+ For the purposes of this document, a WEB Browser is software
+ available from a number of sources including but not limited to the
+ following: Microsoft Internet Explorer, NCSA Mosaic, Netscape
+ Navigator, Sun Hot Java!. The major task of these products is to use
+ the Hypertext Transport Protocol (HTTP) to retrieve, interpret and
+ display Hypertext Markup Language (HTML). These products are often a
+ part of a complete Internet Printing system because they are often
+
+
+
+Wright Experimental [Page 4]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ used as a means of obtaining the status of or more information about
+ the printing system; however, they may not be present in all
+ implementations.
+
+ Throughout this document, 'printer' shall be interpreted to include
+ any device which is capable of marking on a piece of media using any
+ available technology. These design goals do not include support for
+ multi-tiered printing solutions involving servers (single or
+ multiple) logically in front of the actual printing device yet all
+ such configurations shall be supported but shall appear to the end-
+ user as only a single device.
+
+ Throughout this document 'driver' refers to the code installed in
+ some client operating system to generate the print data stream for
+ the intended printer. Some computing environments may not include a
+ separate printer driver. Rather, the generation of the proper print
+ data stream is accomplished in an application on that computer. How
+ such a computer environment or application is updated to support a
+ new printer now made available using IPP is outside the scope of IPP.
+ The actual details for installing a printer driver are operating
+ system dependent and are also outside the scope of IPP. See also
+ section 4.1 (SECURITY CONSIDERATIONS) for security implications of
+ driver download and installation.
+
+ The IPP protocol will support the following physical configurations:
+
+ - An IPP client talking to an IPP Printer object imbedded in a
+ single, physical output device.
+ - An IPP Client talking to a server containing one or more IPP
+ Printer objects. Each Printer object is associated with exactly one
+ physical output device supported by the server. The protocol
+ between the server and the output devices is undefined.
+ - An IPP Client talking to an IPP Printer object in a server. The
+ Printer object is associated with one or more physical output
+ devices, but the client only sees the Printer object, which is an
+ abstraction and represents all of the associated physical output
+ devices. The protocol between the server and the physical output
+ devices is undefined.
+
+ Throughout this document, certain design goals will be identified as
+ not being a part of version 1.0 (or V1.0) of the protocol or as being
+ satisfied by means outside of IPP. IPP is assumed to be one part, an
+ enabler, of a complete Internet Printing solution. For example
+ printer instance creation is not performed by but is enabled by the
+ protocol. Globally, none of the operator or administrators wants and
+ needs are included in the design goals for version 1.0. Some of the
+ end-user wants and needs may also be excluded from version 1.0 and
+ will be so noted in the description of them. Subsequent versions of
+
+
+
+Wright Experimental [Page 5]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ the protocol (e.g. V2.0) may include support for these initially
+ excluded wants and needs.
+
+3. DESIGN GOALS
+
+ The next three sections identify the design goals for an Internet
+ printing protocol from three roles assumed by humans: end-user,
+ operator, and administrator. The goals defined here are only those
+ that need to be addressed by an Internet printing protocol. Other
+ wants and needs, such as that the operator needs physical access to
+ the printer (e.g. to be able to load paper or clear jams) are not
+ covered by this document. Section 5 contains scenarios which provide
+ more detailed examples of the entire process including discovery,
+ status, printing and end-of-job reporting.
+
+3.1. END-USER
+
+ An end-user of a printer accepting jobs through the Internet is one
+ of the roles in which humans act. The end-user is the person that
+ will submit a job to be printed on the printer.
+
+ The wants and needs of the end-user are broken down into six
+ categories: finding/locating a printer, creating a local instance of
+ a printer, viewing printer status, viewing printer capabilities,
+ submitting a print job, viewing print job status, altering the
+ attributes of a print job.
+
+3.1.1. Finding or locating a printer.
+
+ End-users want to be able to find and locate printers to which they
+ are authorized to print. They want to be able to perform this
+ function using a standard WEB browser or other application. Multiple
+ criteria can be applied to find the printers needed. These criteria
+ include but are not limited to:
+
+ - by name (Printer 1, Joes-color-printer, etc.)
+ - by geographic location (bldg 1, Kentucky, etc.)
+ - by capability or attribute (color, duplex, legal paper, etc.)
+
+ Additionally, while it is outside of scope of IPP, end-users want to
+ be able to limit the scope of their searching to:
+
+ - inside a functional sub-domain
+ - include only a particular domain (lexmark.com)
+ - exclude specified domains
+
+
+
+
+
+
+Wright Experimental [Page 6]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ While an Internet printing protocol may not of itself include this
+ function, IPP must define and enable a directory schema which will
+ provide the necessary information for a directory service
+ implementation to consistently represent printers by their IPP
+ attributes.
+
+3.1.2. Create an instance of the printer.
+
+ After finding the desired printer, an end-user needs to be able to
+ create a local instance of that printer within the end-user operating
+ system or desktop. This local instance will vary depending upon the
+ printing paradigm of the operating system. For example, some UNIX
+ users will only want a queue or a reference to a remote printer
+ created on their machine while other UNIX users and Windows NT users
+ will want the queue and also the necessary icons and registry entries
+ to be created and initialized. Where required, drivers may need to
+ be downloaded from some repository and installed on the computer.
+ All necessary decompressing, unpacking, and other installation
+ actions should occur without end-user interaction or intervention
+ excepting initial approval by the end-user. Once the local instance
+ of the printer has been installed, it shall appear to the end-user of
+ the operating system and to the applications running there as any
+ other printer (local, local area network connected, or network
+ operating system connected) on the end-user desktop or environment.
+ IPP's role in this goal is simply to enable the creation of the
+ printer instance providing information such as where to locate a
+ printer driver for this printer, as an attribute of an IPP Printer.
+
+3.1.3. Viewing the status and capabilities of a printer.
+
+ Before using a selected printer or, in fact at any time, the end-user
+ needs the ability to verify the characteristics and status of both
+ printers and jobs queued for that printer. When checking the
+ characteristics of a printer, the end-user typically wants to be able
+ to determine the capability of the device, e.g.:
+
+ - supported media, commonly paper, by size and type
+ - paper handling capability, e.g. duplex, collating, finishing
+ - color capability
+
+ When checking the status of the printer and its print jobs, the end-
+ user typically wants to be able to determine:
+
+ - is the printer on-line?
+ - what are the defaults to be used for printing?
+ - how many jobs are queued for the printer?
+ - how are job priorities assigned? (outside the scope of IPP)
+
+
+
+
+Wright Experimental [Page 7]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+3.1.4. Submitting a print job.
+
+ Once the desired printer has been located and installed, the end-user
+ wants to print to that printer from normal applications using
+ standard methods. These normal applications include such programs as
+ word processors, spreadsheets, data-base applications, WEB browsers,
+ production printing applications, etc. Additionally, the end-user
+ may want to print a file already existing on the end-user's computer
+ -- "simple push". In addition to printing from an application and
+ simple push, the end-user needs to have the ability to submit a print
+ job by reference. Printing by reference is defined to mean as
+ submitting a job by providing a reference to an existing document.
+ The reference, a URI, will be resolved before the actual print
+ process occurs. Submitting a job by reference relieves the user from
+ downloading the document from the remote server and then sending it
+ via IPP to the printer. This saves both time and network bandwidth.
+
+ Some means shall be provided to determine if the format of a job
+ matches the capability of the printer. This can be done by one of
+ the following (all of which are outside of scope of the IPP
+ protocol):
+
+ - the end-user selects the correct printer driver
+ - the printer automatically selects the proper interpreter
+ - the end-user uses some other manual procedure.
+
+ A standard action shall be defined should the job's requirements not
+ match the capabilities of the printer.
+
+ Because the end-user does not want to know the details of the
+ underlying printing process, the protocol must support job-to-printer
+ capability matching (all implementations are not necessarily required
+ to implement this function.) This matching capability requires
+ knowing both the printer's capabilities and attributes and those
+ capabilities and attributes required by the job. Actions taken when
+ a print job requires capabilities or attributes that are not
+ available on the printer vary and can include but are not limited to:
+
+ - rejecting the print job
+ - redirecting the print job to another printer (Not in V1.0)
+ - printing the job, accepting differences in the appearance
+
+ Print jobs will also be submitted by background or batch applications
+ without human intervention.
+
+ End-users need the ability to set certain print job parameters at the
+ time the job is submitted. These parameters include but are not
+ limited to:
+
+
+
+Wright Experimental [Page 8]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - number of copies
+ - single or two sided printing
+ - finishing
+ - job priority
+
+3.1.5. Viewing the status of a submitted print job.
+
+ After a job has been submitted to a printer, the end-user needs a way
+ to view the status of that job (i.e. job waiting, job printing, job
+ done) and to determine where the job is in the print queue.
+
+ In addition to the need to inquire about the status of a print job,
+ automatic notification of the completion of that job is also
+ required.
+
+ Notification means are not defined by the protocol but the protocol
+ must provide a means of enabling and disabling the notification.
+
+3.1.6. Canceling a Print Job
+
+ While a job is waiting to be printed or has been started but not yet
+ completed, the original creator/submitter of the print job (i.e. the
+ end-user) shall be able to cancel the job entirely (job is waiting)
+ or the remaining portion of it (job is printing.) Altering the print
+ job itself is not a V1.0 design goal.
+
+3.2. OPERATOR (NOT REQUIRED FOR V1.0)
+
+ An operator of a printer accepting jobs through the Internet is one
+ of the roles in which humans act. The operator has the
+ responsibility of monitoring the status of the printer as well as
+ managing and controlling the jobs at the device. These
+ responsibilities include but are not limited to the replenishing of
+ supplies (ink, toner, paper, etc.), the clearing of minor errors
+ (paper jams, etc.) and the re-prioritization of end-user jobs.
+ Operator wants and needs will not be addressed by V1.0 of the
+ protocol.
+
+ The wants and needs of the operator include all those of the end-user
+ but may include additional privileges. For example, an operator may
+ be able to view all print jobs on a printer while the end-user might
+ only be able to see his own jobs.
+
+3.2.1. Alerting.
+
+ One of the required operator functions is having the ability to
+ discover or to be alerted to changes in the status of a printer
+ particularly those changes that cause a printer to stop printing and
+
+
+
+Wright Experimental [Page 9]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ to be able to correct those problems. As such, an Internet printing
+ protocol shall be able to alert a designated operator or operators to
+ these conditions such as 'out of paper', 'out of ink', etc.
+ Additionally. the operator shall be able to, asynchronous to other
+ printer activity, inquire as to a printer's or a job's status.
+
+3.2.2. Changing Print and Job Status.
+
+ Another of the required operator functions is the ability to affect
+ changes to printer and job status remotely. For example, the
+ operator will need to be able to re-prioritize or cancel any print
+ jobs on a printer to which the operator has authority.
+
+3.3. ADMINISTRATOR (NOT REQUIRED FOR V1.0)
+
+ An administrator of a printer accepting jobs through the Internet is
+ one of the roles in which humans act. The administrator has the
+ responsibility of creating the printer instances and controlling the
+ authorization of other end-users and operators. Administrator wants
+ and needs will not be addressed by V1.0 of the protocol.
+
+ The wants and needs of the administrator include all those of the
+ end-user and, in some environments, some or all of those of the
+ operator. Minimally, the administrator must also have the tools,
+ programs, utilities and supporting protocols available to be able to:
+
+ - create an instance of a printer
+ - create, edit and maintain the list of authorized end-users
+ - create, edit and maintain the list of authorized operators
+ - create, edit and maintain the list of authorized
+ administrators
+ - create, customize, change or otherwise alter the manner in
+ which the status capabilities and other information about printers
+ and jobs are presented
+ - create, customize, or change other printer or job features
+ - administrate billing or other charge-back mechanisms
+ - create sets of defaults
+ - create sets of capabilities
+
+ The administrator must have the capability to perform all the above
+ tasks locally or remotely to the printer.
+
+4. OBJECTIVES OF THE PROTOCOL
+
+ The protocol to be defined by an Internet printing working group will
+ address the wants and needs of the end-user (V1.0). It will not, at
+ least initially, address the operator or administrator wants and
+ needs (V2.0).
+
+
+
+Wright Experimental [Page 10]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ The protocol defined shall be independent of the operating system of
+ both the client and the server. Generally, any platform capable of
+ supporting a WEB Browser should be capable of being a client.
+ Generally, any platform providing a WEB/HTTP server and printing
+ services should be capable of being a server. Usage of the WEB
+ Browser and Server is not required for IPP; the operating system,
+ operating system extensions or other applications may provide IPP
+ functionality directly.
+
+ In many environments such as Windows 95, Windows NT and OS/2, the
+ print data is created and transmitted to the printer on the fly
+ rather than being created, spooled and then transmitted to the
+ printer (a typical UNIX method.) The Internet Printing Protocol must
+ properly handle either methodology and make this transparent to the
+ end-user.
+
+4.1. SECURITY CONSIDERATIONS
+
+ It is required that the Internet Printing Protocol be able to operate
+ within a secure environment. Wherever reasonable, IPP ought to make
+ use of existing security protocols and services. IPP will not invent
+ new security features when the design goals described in this
+ document can be met by existing protocols and services. Examples of
+ such services include Secure Socket Layer Version 3 (SSL3) [SSL] and
+ HTTP Digest Access Authentication [RFC2069]. Note: SSL3 is not on
+ the IETF standards track.
+
+ Since we cannot anticipate the security levels or the specific
+ threats that any given IPP print administrator may be concerned with,
+ IPP must be capable of operating with different security mechanisms
+ and policies as required by the individual installation. The initial
+ security needs of IPP are derived from two primary considerations.
+ First, the printing environments described in this document take into
+ account that the client, the Printer, and the document to be printed
+ may each exist in different security domains. When objects are in
+ different security domains the design goals for authentication and
+ message protection may be much stronger than when they are all in the
+ same domain.
+
+ Secondly, the sensitivity and value of the content being printed will
+ vary from one instance of a print job to another. For example, a
+ publicly available document does not need the same level of
+ protection as a payroll document does. Message protection design
+ goals include data origin authentication, privacy, integrity, and
+ non-repudiation.
+
+
+
+
+
+
+Wright Experimental [Page 11]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ In many environments (e.g. Windows, OS/2) a printer driver may be
+ needed to create the proper datastream for printer. This document
+ discusses downloading such a new driver from a variety of sources.
+ Downloading and installing any software, including drivers) on a
+ computer exposes that computer to a number of security risks
+ including but not limited to:
+
+ - defective software
+ - malicious software (e.g. Trojan horses)
+ - inappropriate software (i.e. software doing something
+ deemed unreasonable by the user.)
+
+ As such, proper security considerations and actions need to be taken
+ by the user and/or a system administrator to prevent the compromising
+ of the computer. Administrators should configure downloading
+ mechanism for printer drivers in such a way as to be able to verify
+ the source of driver software and encrypt or otherwise protect that
+ software during download.
+
+ Examples including security considerations can be found in sections 5
+ (IPP SCENARIOS) and 10 (APPENDIX - DETAILED SCENARIOS) later in this
+ document.
+
+4.2. INTERACTION WITH LPD (RFC1179)
+
+ Many versions of UNIX and in fact other operating systems provide a
+ means of printing as described in [RFC1179] (Line Printer Daemon
+ Protocol.) This document describes the file formats for the control
+ and data files as well as the messages used by the protocol. Because
+ of the simplistic approach taken by this protocol, many manufacturers
+ have include proprietary enhancements and extensions to 'lpd.'
+ Because of this divergence and due to other design goals described in
+ this document, there is no requirement for backward compatibility or
+ interoperability with 'lpd'. However, a mapping of LPD functionality
+ and IPP functionality shall be provided so as to enable a gateway
+ between LPD and IPP.
+
+4.3. EXTENSIBILITY
+
+ The Internet Printing Protocol shall be extensible by several means
+ that facilitate interoperability and prevent implementation
+ collisions:
+
+ - by providing a process whereby implementers can submit proposals
+ for registration of new attributes and new enumerated values for
+ existing attributes.
+
+
+
+
+
+Wright Experimental [Page 12]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ * that require review and approval. The Internet Assigned
+ Number Authority (IANA) will be the repository for such
+ accepted registration proposals after review.
+
+ * that do not require review and approval. IANA will be the
+ repository for such registrations.
+
+ - by providing syntax in the protocol so that implementers may add
+ private (i.e. unregistered) attributes and enumerated attribute
+ values.
+
+ - by providing versioning and negotiation so as to enable future
+ implementations of IPP to interoperate with implementations of
+ version 1.0 of IPP.
+
+4.4. FIREWALLS
+
+ As stated in section 3 Design Goals, Internet printing shall, by
+ definition, support printing from one enterprise to another. As
+ such, the Internet printing protocol must be capable of passing
+ through firewalls and/or proxy servers (where enabled by the firewall
+ administrator) preferably without modification to the existing
+ firewall technology.
+
+4.5. INTERNATIONALIZATION
+
+ Users of Internet printing will come from all over the world. As
+ such, where appropriate, internationalization and localization will
+ be enabled for the protocol.
+
+5. IPP SCENARIOS
+
+ Each of the scenarios in this section describes a specific IPP
+ operation, such as submitting a print job. Section 10 contains
+ several detailed flows for each scenario to provide additional
+ detail. The examples should not be considered exhaustive, but
+ illustrative of the functions and features required in the protocol.
+ Flows are intended to be protocol neutral. It is not assumed that all
+ of the functions and features described in these scenarios will
+ necessarily be supported directly by IPP or in version 1.0 of IPP.
+
+ See the IPP Model and Semantics document for details on
+ configurations of clients, servers and firewalls.
+
+
+
+
+
+
+
+
+Wright Experimental [Page 13]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+5.1. PRINTER DISCOVERY
+
+ Client Directory Service
+ Service
+
+ +----------------------------------------------------------- >
+ give me information on printers with these characteristics
+
+
+ < -----------------------------------------------------------+
+ Information on Printers matching these characteristics
+
+ The objective of printer discovery is to locate printers that meet
+ the client's wants and needs. The Directory Service should provide
+ enough information for the client to make an initial choice. The
+ client may have to connect to each individual Printer offered to get
+ more detail. Not all information available from the Directory
+ Service is obtained using IPP; some information may be
+ administratively provided.
+
+ The actual protocol used between client and Directory or Name Service
+ is considered outside the scope of IPP. Printer Discover is included
+ in the scenarios to provide design goals for the directory schema for
+ IPP Printers and to further define Printer attributes.
+
+ Characteristics that might be considered when locating a Printer
+ include:
+
+ - capabilities of the Printer, e.g. PDLs supported
+ - physical location, e.g. in building 010
+ - driver required and location
+ - cost per page to print (outside the scope of IPP)
+ - whether or not printer is access controlled
+ - whether or not usage requires client authentication
+ - whether or not Printer can be authenticated
+ - whether or not payment is required for printing (outside the scope
+ of IPP)
+ - maximum job size (spool size) (outside the scope of IPP)
+ - whether or not Printer support compression (outside the scope of
+ IPP)
+ - whether or not Printer supports encryption
+ - administrative limits on this Printer
+ - maximum number of copies per job
+ - maximum number of pages per job
+
+
+
+
+
+
+
+Wright Experimental [Page 14]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Responses could additionally include:
+
+ - how to get more information
+ - web page
+ - telephone number
+ - help desk
+
+5.2. DRIVER INSTALLATION
+
+ Client Printer
+
+ +----------------------------------------------------------- >
+ Where can I find a driver & software to install it?
+
+
+ < -----------------------------------------------------------+
+ URIs for drivers and install software
+
+ Driver here refers to the code installed in some client operating
+ system to generate the print data stream for the intended printer.
+ The actual details for installing a printer driver are operating
+ system dependent and are also outside the scope of IPP. However, an
+ IPP printer or a directory service advertising an IPP Printer should
+ be capable of telling a client what drivers are available and/or
+ required, where they can be found, and provide pointers to
+ installation instructions, installation code or initialization
+ strings required to install the driver. See section 4.1 (SECURITY
+ CONSIDERATIONS) for security implications of driver download and
+ installation.
+
+5.3. SUBMITTING A PRINT JOB
+
+ Client IPP Printer
+
+ +----------------------------------------------------------- >
+ Here is a Print Job
+ - Job attributes
+ - Print data
+
+
+ < -----------------------------------------------------------+
+ Response
+
+ The protocol must support these sources of client data:
+
+ - Print data is a file submitted with the job
+ - Print data is generated on the fly by an application
+ - Print data is a file referenced by a URI
+
+
+
+Wright Experimental [Page 15]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ The protocol must handle overrun conditions in the printer and must
+ support overlapped printing and downloading of the file in devices
+ that are unable to spool files before printing them.
+
+ Every print request will have a response. Responses will indicate
+ success or failure of the request and provide information on failures
+ when they occur. Responses would include things like:
+
+ - Got the print job and queued it
+ - Got the print job and am printing it
+ - Got the print job, started to print it, but printing failed
+ - why it failed (e.g. unrecoverable PostScript error)
+ - state of the printer
+ - how much printed
+ - Got the print job but couldn't print it
+ - why it can't be printed
+ - state of the printer
+ - Got the print job but don't know what to do with it
+ - Didn't get a complete print job (e.g. communication failure)
+
+5.4. GETTING STATUS/CAPABILITIES
+
+ Client IPP Printer
+
+ +----------------------------------------------------------- >
+ Get status and/or capabilities of Printer
+
+
+ < -----------------------------------------------------------+
+ Status/Capabilities
+
+ Clients will need to get information about
+
+ - Static capabilities of the device
+ - Dynamic state of the Printer (e.g. out of paper)
+ - State of a specific job owned by this client
+ - State of all jobs owned by this client
+ - queued
+ - printing
+ - completed
+
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 16]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - Job submission attributes supported/required
+ - scheduling attributes (e.g. priority)
+ - production attributes (e.g. number of copies)
+
+5.5. ASYNCHRONOUS NOTIFICATION
+
+ Client IPP Printer
+
+ +----------------------------------------------------------- >
+ Use the following method to notify me of Printer events
+
+ .
+ .
+ .
+ < -----------------------------------------------------------+
+ Asynchronous notification of Printer event
+
+ Clients must be able to request asynchronous notification for Printer
+ events such as
+
+ - job completion
+ - a fatal error that requires the job to be resubmitted
+ - a condition that severely impacts a queued job for this client
+ e.g. printer is out of paper
+
+ Note: end-user notification is a V1.0 design goal while operator
+ notification is for V2.0.
+
+5.6. JOB CANCELING
+
+ Client IPP Printer
+
+ +----------------------------------------------------------- >
+ Cancel the named job as indicated
+
+
+ < -----------------------------------------------------------+
+ Response (did it or not)
+
+ Similarly clients must be able to make changes to jobs which have
+ been submitted and are queued for printing. Changing of job
+ attributes should also be supported. Job modifications, holding and
+ releasing of jobs are not included in the design goals for IPP v1.0.
+
+
+
+
+
+
+
+
+Wright Experimental [Page 17]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+6. SECURITY CONSIDERATIONS
+
+ The security considerations for IPP are described in Section 4.1
+ above.
+
+7. REFERENCES
+
+ [ipp-iig] Hastings, T. and C. Manros, "Internet Printing
+ Protocol/1.0: Implementer's Guide", Work in Progress.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2568, April 1999.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [ISO10175] ISO/IEC 10175, Document Printing Application, June 1996.
+
+ [RFC1179] McLaughlin, L., "Line Printer Daemon Protocol" RFC 1179,
+ August 1990.
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version
+ 3.02), November 1996.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 18]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+8. ACKNOWLEDGMENTS
+
+ This document draws heavily from preliminary work done by others
+ especially in the Printer Working Group (PWG). The author gratefully
+ acknowledges the specific contributions of:
+
+ Scott Isaacson Roger deBry
+ Novell Utah Valley State College
+ sisaacson@novell.com debryro@uvsc.edu
+
+ Carl-Uno Manros Robert Herriot
+ Xerox Sun
+ manros@cp10.es.xerox.com Robert.Herrior@pahv.xerox.xom
+
+ Tom Hastings Peter Zehler
+ Xerox Xerox
+ hastings@cp10.es.xerox.com Peter.Zehler@usa.xerox.com
+
+9. AUTHOR'S ADDRESS
+
+ F.D. (Don) Wright
+ Lexmark International
+ C14/035-3
+ 740 New Circle Rd
+ Lexington, KY 40550
+
+ Phone: 606-232-4808
+ Fax: 606-232-6740
+ EMail: don@lexmark.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 19]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10. APPENDIX - DETAILED SCENARIOS
+
+ The following are more detailed scenarios illustrating how the
+ Internet Printing Protocol is expected to be used as a part of a
+ complete Internet Printing system. Some parts of the scenarios
+ include concepts, functions and information that may be outside of
+ the scope of version 1.0 of IPP (e.g. cost per page, payments means
+ available, etc.) The information contained herein is meant to be
+ generic. There may not be an exact wording or terminology match
+ between these scenarios and the implementation documents.
+
+10.1. PRINTER DISCOVERY WITHIN AN ENTERPRISE
+
+ A user wants to find a color Postscript printer in his/her enterprise
+ which will print transparencies. The client, directory service, and
+ printer are all behind the same corporate firewall. Because color
+ foils are expensive, printers of this type are access controlled and
+ require an account to be established so that printing can be billed
+ back to the using department. Note the request to find a printer
+ usable by Dept. J15. Drivers for all supported printers are
+ available from the server they are associated with. A help desk is
+ provided for end user support. The printer is unattended.
+
+ Client Directory Service
+
+ +---------------------------------------------------------- >
+ Find a printer with these characteristics
+ - prints color, prints transparencies
+ - prints Postscript
+ - is in building 003
+ - accessible by the client
+
+ < ----------------------------------------------------------+
+ Printer "Color-A"
+ - prints color, prints transparencies
+ - prints Postscript
+ - in room H-6, building 003
+ - driver ABC-Postscript-V1.3 required, here is URI
+ - cost is $.45 per page for color transparencies
+ - limit is 10 pages per job
+ - authentication required to use printer
+ - printer is unattended
+ - help desk at x5001
+
+ Printer "Color-B"
+ - prints color, prints transparencies
+ - prints Postscript
+ - in room J-10, building 003
+
+
+
+Wright Experimental [Page 20]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - driver XYZ-Postscript-V2.4 required, here is URI
+ - cost is $1.25 page for color transparencies
+ - limit is 5 pages per job
+ - authentication is required to use printer
+ - printer is unattended
+ - help desk at x5001
+
+10.2. PRINTER DISCOVERY ACROSS ENTERPRISES
+
+ A user in Company A wants to find a public printer in a business
+ partner's enterprise (Company B) on which to print a purchase order.
+ The client is behind one corporate firewall and the directory service
+ and the printer are behind a different corporate firewall. Drivers
+ for all supported printers are available from the server they are
+ associated with. A web page is provided for end user support for
+ public printers.
+
+ Client Company B Directory Service
+
+ +---------------------------------------------------------- >
+ Find a printer with these characteristics
+ - prints black and white
+ - is in El Segundo, building A
+ - is a public printer
+
+ < ----------------------------------------------------------+
+ Printer "Public-A"
+ - prints black and white
+ - prints Postscript
+ - in El Segundo, room H-6, building A
+ - driver ABC-Postscript-V1.3 required, here is URI
+ - printer is public
+ - help available at http://xerox/elSegundo/publicPrinters
+
+ Printer "Public-B"
+ - prints black and white
+ - prints PCL/5e
+ - is in El Segundo, room J-10, building A
+ - driver XYZ-PCL-V2.4 required, here is URI
+ - printer is public
+ - help available at http://xerox/elSegundo/publicPrinters
+
+10.3. PRINTER DISCOVERY ON THE INTERNET -LOGICAL OPERATIONS
+
+ A student wants to print a paper on a printer at his neighborhood
+ Ink-o's print shop. The report was written using Microsoft Word. The
+ student is interested in the cost of printing since his budget is
+ limited. Note the use of logical operators to find this information.
+
+
+
+Wright Experimental [Page 21]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Client Ink-o's Directory Service
+
+ +---------------------------------------------------------- >
+ Find a Printer with these characteristics
+ - prints color or black and white
+ - costs less than $.50 per page
+ - tell me about resolution and marking technology
+
+ < ----------------------------------------------------------+
+ Printer "Color-A"
+ - prints color
+ - 600 dpi laser printer
+ - prints Postscript
+ - driver ABC-Postscript-V1.3 required, here is URI
+ - cost is $.50 per page for color
+ - payment required prior to submitting print job
+ - here is URI for more information on Ink-o's
+
+ Printer "Mono-B"
+ - prints black and white
+ - 300 dpi inkjet printer
+ - prints Postscript
+ - driver XYZ-Postscript-V2.4 required, here is URI
+ - cost is $0.35 page for black and white
+ - payment required prior to submitting print job
+ - here is URI for more information on Ink-o's
+
+10.4. PRINTER DISCOVERY ON THE INTERNET - AUTHENTICATION
+
+ An executive in her hotel room is finishing an important presentation
+ on her laptop computer. She connects to a local print shop through
+ the web to get a copy of her charts printed for tomorrow's
+ presentation. She must find a print shop that is convenient to her
+ hotel and can print color transparencies. She wants to be sure that
+ the printer can be authenticated and can accept encrypted data.
+
+ Client SirZippy Directory Service
+
+ +---------------------------------------------------------- >
+ Find a Printer with these characteristics
+ - prints color transparencies
+ - is in Boulder, Colorado
+ - Printer can be authenticated
+ - Printer supports encryption
+
+
+
+
+
+
+
+Wright Experimental [Page 22]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Tell me when you are open for business
+
+ < ----------------------------------------------------------+
+ Printer "Color-A"
+ - prints color transparencies
+ - prints Postscript
+ - driver ABC-Postscript-V1.3 required, here is URI
+ - payment required prior to submitting print job
+ - Printer can be authenticated
+ - Data can be encrypted
+ - Located at 1670 Pearl Street, Boulder, CO
+ - This Branch is open 24 hours a day
+
+
+ Printer "Color-B"
+ - prints color transparencies
+ - prints Postscript
+ - driver ABC-Postscript-V1.3 required, here is URI
+ - payment required prior to submitting print job
+ - Printer can be authenticated
+ - Data can be encrypted
+ - Located at 1220 Arapahoe, Boulder, CO
+ - This Branch is open from 9:00 am to 6:30 pm
+
+10.5. DRIVER DOWNLOAD
+
+ An end user in an enterprise wants to print a lengthy report on a
+ newly installed high speed PostScript printer. Since she will likely
+ use this printer often, she would like to download a driver and
+ install it on her workstation. She is running Windows 95. Note:
+ Driver download is not a V1.0 design goal.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Tell me where to find print drivers for you
+
+
+
+ < ----------------------------------------------------------+
+ Driver install file is at
+ http://www.ibm.com/drivers/NP12a/Win95
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 23]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10.6. SUBMITTING A PRINT JOB AS A FILE
+
+ An end-user wants to submit a print job. The print file already
+ exists on his workstation. The client and printer are behind the same
+ corporate firewall. The printer is available to anyone behind the
+ firewall and no authorization or authentication is required. The data
+ is pushed to the printer. The printer is capable of spooling the
+ output. No errors occur.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print job accepted and spooled
+ - job id = #12345
+ - current state of print job = spooled
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+
+10.7. SUBMITTING A PRINT JOB WITH TWO DOCUMENTS
+
+ An end-user wants to submit a print job. The print file already
+ exists on his workstation. The client and printer are behind the same
+ corporate firewall. The printer is available to anyone behind the
+ firewall and no authorization or authentication is required. The data
+ is pushed to the printer. The job consists of two separate documents.
+ The printer is capable of spooling the output. No errors occur.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+
+ < ----------------------------------------------------------+
+
+
+
+Wright Experimental [Page 24]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Print job accepted and spooled
+ - job id = #12345
+ - submission time = 02/12/97, 15:35
+ +---------------------------------------------------------- >
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ - OK
+
+ +---------------------------------------------------------- >
+ - here is the document to print, it is the last document.
+
+ < ----------------------------------------------------------+
+ - OK
+
+10.8. SUBMITTING A PRINT JOB AS A FILE, PRINTING FAILS
+
+ An end-user wants to submit a print job. The print file already
+ exists on his workstation. The client and printer are behind the same
+ corporate firewall. The printer is available to anyone behind the
+ firewall and no authorization or authentication is required. The data
+ is pushed to the printer. The printer is not capable of spooling the
+ output so it begins printing while still receiving the file. An error
+ occurs and the printer cannot complete printing (in this case the
+ user requires A4 paper and that paper size is not available on the
+ printer.)
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print job accepted
+
+ - printing failed
+ - current state of print job = canceled (A4 not available)
+ - submission time = 02/12/97, 15:35
+ - printer state = ready
+
+
+
+
+
+Wright Experimental [Page 25]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10.9. SUBMITTING A PRINT JOB WITH AUTHENTICATION, PRIVACY AND PAYMENT
+
+ A traveling executive needs to print a set of transparencies for an
+ important business meeting. The charts are in Lotus Freelance format
+ on his notebook computer. He has located a SirZippy print shop near
+ his hotel that will print color transparencies. Because the
+ information on the charts is sensitive, he wants to be sure that his
+ data is sent to the Printer in an encrypted format. He also wants to
+ authenticate the Printer. The Printer also authenticates the user.
+ Payment occurs across the Internet.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+
+ Mutual authentication and exchange of secret keys
+
+ +---------------------------------------------------------- >
+ Here is a print job (encrypted)
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - tell me where to pick up output
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print job accepted and spooled (encrypted)
+ - job id = #12345
+ - current state of print job = spooled
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+ - payment required to proceed with job
+ - pick up at 230 East Main after 3:30 pm today
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Payment transaction
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 26]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10.10. SUBMITTING A PRINT JOB WITH DECRYPTION ERROR
+
+ A traveling executive needs to print a set of transparencies for an
+ important business meeting. The charts are in Lotus Freelance format
+ on his notebook computer. He has located a SirZippy print shop near
+ his hotel that will print color transparencies. Because the
+ information on the charts is sensitive, he wants to be sure that his
+ data is sent to the printer in an encrypted format. He also wants to
+ authenticate the printer. The printer also authenticates the user.
+ Payment occurs across the Internet. An error occurs during
+ decryption.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Mutual authentication and exchange of secret keys
+
+
+ +---------------------------------------------------------- >
+ Here is a print job (encrypted)
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - tell me where to pick up output
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print job accepted and spooled (encrypted)
+ - job id = #12345
+ - current state of print job = spooled
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+ - payment required to proceed with job
+ - pick up at 230 East Main after 3:30 pm today
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Payment transaction
+ .
+ .
+ .
+ < ----------------------------------------------------------+
+ Asynchronous response (email in this case)
+ - decryption failed on job #12345
+
+
+
+Wright Experimental [Page 27]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - no pages printed
+ - current state of job = aborted
+
+10.11. SUBMITTING A PRINT JOB WITH AUTHENTICATION
+
+ An end-user wants to submit a print job. The print file already
+ exists on his workstation. The client and printer are behind the same
+ corporate firewall. The printer is available to anyone behind the
+ firewall but authentication and authorization is required.
+ Authorization takes place using the authenticated end-user's name.
+ The data is pushed to the printer. The printer is capable of spooling
+ the output.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Authentication
+
+ Note: An authentication failure would end the transaction at
+ this point.
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - tell me where to pick up output
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print job accepted and spooled
+ - job id = #12345
+ - current state of print job = spooled
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+
+
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 28]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10.12. SUBMITTING A PRINT JOB GENERATED DYNAMICALLY
+
+ An end-user wants to submit a print job. The print data is generated
+ dynamically and is being transmitted by a printer driver on the
+ client workstation as available. The client and printer are behind
+ the same corporate firewall. The printer is available to anyone
+ behind the firewall and no authentication and authorization is
+ required. The data is pushed to the printer. The printer is capable
+ of spooling the output. No error occurs.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - document is in Postscript format
+ - here is the print job
+
+
+ < ----------------------------------------------------------+
+ Print data accepted and spooling started
+ - job id = #12345
+ - current job state = spooled
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+
+10.13. SUBMITTING A PRINT JOB WITH A PRINTER JAM - CANCELED
+
+ An end-user wants to submit a print job. The print data is generated
+ dynamically and is being transmitted by a printer driver on the
+ client workstation as available. The client and printer are behind
+ the same corporate firewall. The printer is available to anyone
+ behind the firewall and no authentication and authorization is
+ required. The data is pushed to the printer. The printer is not
+ capable of spooling the output. The printer jams notifies the user
+ and the user chooses to cancel the job.
+
+ Client IPP Printer
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+
+
+
+Wright Experimental [Page 29]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - return status of the printer in response
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ Print data accepted and printing started
+ - job id = #12345
+
+ +---------------------------------------------------------- >
+ - What is the status of print job #12345?
+
+ < --------------------------------------------------------- +
+ - Job #12345 accepted but printer jammed, cannot continue
+
+ +---------------------------------------------------------- >
+ - Cancel job #12345
+
+ * Printer flushes remaining data
+ < ----------------------------------------------------------+
+ Print job terminated
+ - current job state = canceled
+ - submission time = 02/12/97, 15:35
+ - printer state = jammed
+
+10.14. SUBMITTING A PRINT JOB WITH A PRINTER JAM - RECOVERED
+
+ An end-user wants to submit a print job. The print data is generated
+ dynamically and is being transmitted by a printer driver on the
+ client workstation as available. The client and printer are behind
+ the same corporate firewall. The printer is available to anyone
+ behind the firewall and no authentication and authorization is
+ required. The data is pushed to the printer. The printer is not
+ capable of spooling the output. The printer jams, notifies the user
+ and the user clears the jam and elects to continue.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - document is in Postscript format
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+
+
+
+Wright Experimental [Page 30]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Print data accepted and printing started
+ - job id = #12345
+
+ < --------------------------------------------------------- +
+ - Notification: printer jammed, cannot continue
+
+ * Jam is clear by human intervention, printing continues
+
+ +---------------------------------------------------------- >
+ Here is the last part of the document to print
+
+ < ----------------------------------------------------------+
+ Print job received
+ - current job state = printing
+ - submission time = 02/12/97, 15:35
+ - printer state = printing
+
+10.15. SUBMITTING A PRINT JOB WITH SERVER PULL
+
+ An end-user wants to submit a print job. The print data is in a file
+ and is publicly available. It is pulled by the printer. The client
+ and printer are behind the same corporate firewall. The printer is
+ available to anyone behind the firewall and no authentication and
+ authorization is required. The printer is capable of spooling the
+ output. Printing may start before the entire job has been pulled.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+ - here is a reference to the data to be printed
+
+ < ----------------------------------------------------------+
+ Print data accepted and printing started
+ - job id = #12345
+ - current state of job = spooled
+ - submission time = 02/12/97, 13:15
+ - printer state = printing
+
+ .
+ .
+ < ----------------------------------------------------------+
+
+
+
+Wright Experimental [Page 31]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Get the file to be printed
+
+ +---------------------------------------------------------- >
+ Here it is
+
+ Note: Failure to find the file, would end the transaction
+ with an error at this point and an asynchronous
+ notification would be send to the Client.
+
+ < ----------------------------------------------------------+
+ Data received
+
+10.16. SUBMITTING A PRINT JOB WITH REFERENCED RESOURCES
+
+ An end-user wants to submit a print job. Part of the print data is
+ on a file on the user's workstation. It is pushed by the client, but
+ the print job requires some resource not included in the print file.
+ The client and printer are behind the same corporate firewall. The
+ printer is available to anyone behind the firewall and no
+ authentication and authorization is required. The printer is capable
+ of spooling the output. No errors occur.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job name = MyJob
+ - notify me by email when done printing
+ - print on iso-a4-white paper
+ - print on both sides of the paper
+ - return status of the printer in response
+
+ < ----------------------------------------------------------+
+ Print job accepted and spooled
+ - job id = #12345
+ - submission time = 02/12/97, 15:35
+
+ +---------------------------------------------------------- >
+ - here is the document to print
+
+ < ----------------------------------------------------------+
+ - OK
+
+ +---------------------------------------------------------- >
+ - here is the URI to print, it is the last document.
+
+ < ----------------------------------------------------------+
+ - OK
+
+
+
+Wright Experimental [Page 32]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ < ----------------------------------------------------------+
+ Get the external resource
+
+ +---------------------------------------------------------- >
+ Here it is
+
+10.17. GETTING CAPABILITIES
+
+10.17.1. Submission Attributes
+
+ An end-user wants to get the production and scheduling attributes
+ that are supported or required when submitting jobs to this printer.
+ The client will use these attributes when forming the subsequent
+ print request.
+
+ Client IPP Printer
+ +---------------------------------------------------------- >
+ I'm going to submit a Postscript job
+ give me your job submission attributes
+
+ < ----------------------------------------------------------+
+ Postscript production attributes for this Printer are:
+ - medium-select = us-letter-white, us-legal-white
+ - default is us-letter-white
+ - copies = 1,2,3,4,5
+ - default is 1
+ - print-quality = draft, normal, high
+ - default is draft
+ - sides = 1-sided, 2-sided-long-edge
+ - default is 2-sided-long-edge
+ - Job scheduling attributes for this Printer are:
+ - job-priority = 1,2,3
+ - default = 3
+
+10.17.2. Printer Capabilities
+
+ An end-user wants to determine the resolution, marking technology,
+ and PDLs supported by the printer.
+
+ Client IPP Printer
+ +---------------------------------------------------------- >
+ Please tell me the
+ - resolution of the printer
+ - the marking technology of the printer
+ - PDLs supported
+ < ----------------------------------------------------------+
+ Printer resolution = 600 dpi
+ Marking Technology = laser
+
+
+
+Wright Experimental [Page 33]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ PDLs supported = Postscript level 2, PCL/6
+
+10.18. GETTING STATUS
+
+10.18.1. Printer State/Status
+
+ An end-user wants to determine the state or status of the printer.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ What is the state of the printer?
+
+ < ----------------------------------------------------------+
+ Printer state = out-of-paper
+
+10.18.2. Job Status
+
+ An end user wants to get the status of a job he has submitted.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Please tell me the status of job #12345
+
+ < ----------------------------------------------------------+
+ Job #12345 is queued
+ it is number 3 in the queue
+ printer state = printing
+
+10.18.3. Status of All My Jobs
+
+ An end user wants to get a list of all of the jobs he has submitted
+ to this Printer.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ Please tell me the status of my jobs
+
+ < ----------------------------------------------------------+
+ Job #00012 is complete
+ Printed at 12:35 on 01/23/97
+
+ Job #09876 is printing
+
+ Job #12345 is queued
+ it is number 3 in the queue
+
+
+
+Wright Experimental [Page 34]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Job #34567 is queued
+ it is number 7 in the queue
+
+10.19. ASYNCHRONOUS NOTIFICATION
+
+10.19.1. Job Completion
+
+ An end-user wants to get notification of events that affect his print
+ jobs. Print job completes without error.
+
+ Client IPP Printer
+
+ < ----------------------------------------------------------+
+ Print job #123 completed
+
+10.19.2. Job Complete with Data
+
+ An end-user wants to get notification of events that affect his print
+ jobs. Print job completes, users asked for all end of job
+ information.
+
+ Client IPP Printer
+
+ < ----------------------------------------------------------+
+ Print job #123 completed
+ - total pages printed = 15
+ - number of copies printed = 3
+ - total cost to print = $7.45
+ - pick up copies in room H-6, building 005
+
+10.19.3. Print Job Fails
+
+ An end-user wants to get notification of events that affect his print
+ jobs. Print job fails. Printer is unattended.
+
+ Client IPP Printer
+
+ < ----------------------------------------------------------+
+ Print job #123 failed
+ - total pages printed = 15
+ - number of pages submitted = 25
+ - printer-state = jammed
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 35]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+10.20. CANCEL A JOB
+
+ The end-user submits a print job and later decides to cancel it.
+
+ Client IPP Printer
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Authentication.
+
+
+ +---------------------------------------------------------- >
+ Cancel job #1234
+
+ < ----------------------------------------------------------+
+ Job #1234 Canceled
+
+
+10.21. END TO END SCENARIO - WITHIN AN ENTERPRISE
+
+ An office worker prints on shared departmental printers. All printers
+ in the office are public, that is, no authentication or authorization
+ is required. Printers are protected from external access by a
+ firewall. No billing or accounting is required. Most printing is done
+ from desktop applications. A help desk is provided for printing
+ problems. Standard operating systems and applications are used.
+ Drivers are available, but are installed manually by support
+ personnel. This scenario assumes that drivers have been installed and
+ that drivers are not IPP aware, that is, they cannot communicate
+ across an IPP connection to obtain status and capabilities. IPP
+ printers appear in application pull-down menus. Printer
+ configuration data is hard wired into the driver.
+
+ End-user selects print from the application pull down menu. An IPP
+ printer is selected from the list of Printers offered
+
+ The driver puts up a dialogue with hard-wired set of options for this
+ printer. The end-user makes choices and submits job.
+
+ Client IPP Printer
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job-name = memo-to-boss
+ - notify me by email when job is complete
+ - print on us-letter-white paper
+ - print 1 copy
+ - print at normal quality
+ - print on 1 side
+
+
+
+Wright Experimental [Page 36]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - give me the state of the printer in response
+
+ The driver generates the print data and passes it to the IPP driver a
+ piece at a time as it is generated.
+
+ +---------------------------------------------------------- >
+ Here is the print data
+
+
+ < ----------------------------------------------------------+
+ Print data received, file is spooled
+ - printer state = printing
+ - time submitted = 2/12/97, 15:35
+ - current job state = spooled
+
+ Client adds this job to list of current jobs. List of jobs and state
+ of each is available on a pull-down menu on the client.
+
+ End-user selects job #1234 from list and clicks on it to see its
+ status.
+
+ +---------------------------------------------------------- >
+ Give me the state of job #1234
+ and the state of the Printer
+
+ < ----------------------------------------------------------+
+ Job #1234 state = spooled
+ - it is number 3 in the queue
+ - printer state = printing
+
+ The job completes without error
+
+ < ----------------------------------------------------------+
+ Job #1234 completed
+ 12 of 12 pages printed
+
+10.22. END TO END SCENARIO - ACROSS ENTERPRISES
+
+ An office worker in Company A needs to print an office document on a
+ "public" printer at Company B, a business partner. Both companies
+ have corporate firewalls so the print request must flow out of A's
+ firewall and into B's firewall. The office worker can look at public
+ printers in Company B's directory service. The document is generated
+ by a desktop application. Since the printer is "public" no
+ authentication or authorization is required. A driver is downloaded.
+ The driver is IPP aware, that is, it can communicate dynamically
+ through the IPP protocol layer to obtain information about the
+ printer.
+
+
+
+Wright Experimental [Page 37]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Client Company B's Directory Service
+
+ End user connects to B's Directory service
+
+ +---------------------------------------------------------- >
+ Find a Printer with these characteristics
+ - public (no authorization or authentication required)
+ - is in Lexington, building 004
+ - prints black and white
+
+ < ----------------------------------------------------------+
+ Printer "Public-A"
+ - http://www.lexmark.com/pubprinter/a
+
+ Printer "Public-B"
+ - http://www.lexmark.com/pubprinter/b
+
+ End user selects Public-A
+
+ Client Public-A
+
+ +---------------------------------------------------------- >
+ Where can I find a driver for you?
+
+ < ----------------------------------------------------------+
+ Drivers at http://www.lexmark.com/pubprinters/a/os245
+
+ End user gets driver and installs it on his PC.
+
+ End-user selects print from the application pull down menu. "Public-
+ A" is selected from the list of Printers offered
+
+ +---------------------------------------------------------- >
+ I'm going to submit a print job
+ give me your job submission attributes
+
+ < ----------------------------------------------------------+
+
+ Production attributes for this Printer are:
+ - medium-select = us-letter-white, us-legal-white
+ - default is us-letter-white
+ - copies = 1,2,3,4,5
+ - default is 1
+ - print-quality = draft, normal, high
+ - default is draft
+ - sides = 1-sided, 2-sided-long-edge
+ - default is 2-sided-long-edge
+
+
+
+
+Wright Experimental [Page 38]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Job scheduling attributes for this Printer are:
+ - job-priority = 1,2,3
+ default = 3
+
+ Driver puts up dialogue with available options and fills in the
+ defaults.
+
+ End-user makes choices and submits job
+
+ +---------------------------------------------------------- >
+ Here is a print job
+ - job-name = memo-to-Don-Wright
+ - notify me by email when job is complete
+ - print on us-letter-white paper
+ - print 1 copy
+ - print at normal quality
+ - print on 1 side
+ - give me the state of the printer in response
+
+
+ The driver generates the print data and passes it to the IPP driver a
+ piece at a time.
+
+ +---------------------------------------------------------- >
+ Here is the print data
+
+ < ----------------------------------------------------------+
+ Print data received, and spooling started
+ print job id = #1234
+
+ Print data received, file is spooled
+
+ - printer state = printing
+ - time submitted = 2/12/97, 15:35
+ - current job state = spooled
+
+ Client adds this job to list of current jobs. List of jobs and state
+ of each is available on a pull-down menu on the client.
+
+ End-user selects job #1234 from list and clicks on it to see its
+ status.
+
+ +---------------------------------------------------------- >
+ Give me the state of job #1234
+ and the state of the Printer
+
+ < ----------------------------------------------------------+
+ Job #1234 state = spooled
+
+
+
+Wright Experimental [Page 39]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ - it is number 3 in the queue
+ - printer state = printing
+
+ * The job completes without error
+ < ----------------------------------------------------------+
+ Job #1234 completed
+ 12 of 12 pages printed
+
+10.23. END TO END SCENARIO - ON THE INTERNET
+
+ An executive in her hotel room is finishing an important presentation
+ on her laptop computer. She connects to a local print shop through
+ the web to get a copy of her charts printed for tomorrow's
+ presentation. She must find a print shop that is convenient and can
+ print color transparencies. She must download and temporarily install
+ a driver in order to generate the PDL required by the print shop.
+ Mutual authentication is required by the print shop and payment must
+ be made in advance. The job is encrypted on the wire to prevent
+ eavesdropping.
+
+ End-user completes presentation. She goes to the web and connects to
+ the SirZippy home page.
+
+ Client SirZippy Directory Service
+ +---------------------------------------------------------- >
+
+ Find me a printer with these characteristics
+ - Near Market Street in San Jose
+ - Prints color transparencies
+ - drivers can be downloaded
+ - supports privacy (encryption)
+ -
+
+ Available Printers matching these characteristics are looked up in the
+ Directory Service
+
+ < ----------------------------------------------------------+
+
+ Printer "Color-A"
+ - located at 123 First Street in San Jose
+ - URI is http://www.SirZippy.com/FirstStreet/Color-A
+ - prints color transparencies
+ - 600 dpi laser
+ - driver ABC-Postscript-V1.3 available at this URI
+ - cost = $.75 per page
+ - authentication required to use printer
+ - payment required prior to printing
+
+
+
+
+Wright Experimental [Page 40]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Printer "Color-B"
+ - located at 67 San Carlos Street, San Jose
+ - URI is http://www.SirZippy.com/SanCarlos/Color-B
+ - prints color transparencies
+ - 1200 dpi laser
+ - driver XYZ-PostScript-V4.3 available at this URI
+ - cost = $1.25 per page
+ - authentication required to use printer
+ - payment required prior to printing
+ - more information at this URI
+
+ The user decides to use the first printer because it is closer. She
+ connects to the URI given to get a driver.
+
+ Client Driver URI
+
+ +---------------------------------------------------------- >
+ I need a driver for "Color-A"
+
+
+ < ----------------------------------------------------------+
+ Driver installer is at http://www.xerox.com/prtdrvrs
+
+ Driver is installed
+
+ User connects to
+ "Color-A"
+
+ Client IPP Printer "Color-A"
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Mutual authentication and exchange of secret keys
+
+ +---------------------------------------------------------- >
+ I'm going to submit a print job
+ give me your job submission attributes
+
+ < ----------------------------------------------------------+
+ Production attributes for this Printer are:
+ - medium-select = us-letter-white, us-legal-white
+ - default is us-letter-white
+ - copies = 1,2,3,4,5
+ - default is 1
+ - print-quality = draft, normal, high
+ - default is draft
+ - sides = 1-sided, 2-sided-long-edge
+ - default is 2-sided-long-edge
+
+
+
+Wright Experimental [Page 41]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+ Job scheduling attributes for this Printer are:
+ - job-priority = 1,2,3
+ default = 3
+
+ Driver puts up dialogue with available options and fills in the
+ defaults.
+
+ End-user makes choices and submits job
+
+ +---------------------------------------------------------- >
+ Here is a print job
+
+ - job-name = presentation
+ - notify me by email when job is complete
+ - print on us-letter-transparency
+ - print 1 copy
+ - print at high quality
+ - print by 9:00 am tomorrow morning
+ - give me the state of the printer in response
+
+ The driver generates the print data and passes it to the IPP driver a
+ piece at a time.
+
+ +---------------------------------------------------------- >
+ Here is the print data
+
+ < ---------------------------------------------------------+
+ Print data received, and spooling started
+ print job id = #1234
+
+ Print data received, file is spooled
+ - printer state = printing
+ - time submitted = 2/12/97, 15:35
+ - current job state = held, waiting for payment
+
+ +---------------------------------------------------------- >
+ < ----------------------------------------------------------+
+ Payment transaction
+
+ < ----------------------------------------------------------+
+ Job is scheduled to print, pick up after 9:00am tomorrow
+ Thank you for using SirZippy
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 42]
+
+RFC 2567 Internet Printing Design Goals April 1999
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wright Experimental [Page 43]
+
diff --git a/standards/rfc2568.txt b/standards/rfc2568.txt
new file mode 100644
index 000000000..2d3ae4905
--- /dev/null
+++ b/standards/rfc2568.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group S. Zilles
+Request for Comments: 2568 Adobe Systems Inc.
+Category: Experimental April 1999
+
+
+ Rationale for the Structure of the Model and Protocol
+ for the Internet Printing Protocol
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note
+
+ This document defines an Experimental protocol for the Internet
+ community. The IESG expects that a revised version of this protocol
+ will be published as Proposed Standard protocol. The Proposed
+ Standard, when published, is expected to change from the protocol
+ defined in this memo. In particular, it is expected that the
+ standards-track version of the protocol will incorporate strong
+ authentication and privacy features, and that an "ipp:" URL type will
+ be defined which supports those security measures. Other changes to
+ the protocol are also possible. Implementors are warned that future
+ versions of this protocol may not interoperate with the version of
+ IPP defined in this document, or if they do interoperate, that some
+ protocol features may not be available.
+
+ The IESG encourages experimentation with this protocol, especially in
+ combination with Transport Layer Security (TLS) [RFC2246], to help
+ determine how TLS may effectively be used as a security layer for
+ IPP.
+
+ABSTRACT
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document describes IPP
+ from a high level view, defines a roadmap for the various documents
+ that form the suite of IPP specifications, and gives background and
+ rationale for the IETF working group's major decisions.
+
+
+
+Zilles Experimental [Page 1]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol (this document)
+ Internet Printing Protocol/1.0: Model and Semantics [RFC2566]
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Internet Printing Protocol/1.0: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. The Design Goals document calls out a subset of end
+ user requirements that are satisfied in IPP/1.0. Operator and
+ administrator requirements are out of scope for version 1.0.
+
+ The "Internet Printing Protocol/1.0: Model and Semantics" document
+ describes a simplified model consisting of abstract objects, their
+ attributes, and their operations that is independent of encoding and
+ transport. The model consists of a Printer and a Job object. The
+ Job optionally supports multiple documents. This document also
+ addresses security, internationalization, and directory issues.
+
+ The "Internet Printing Protocol/1.0: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1. It defines the encoding rules
+ for a new Internet media type called "application/ipp".
+
+ The "Internet Printing Protocol/1.0: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.0 and some of
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+1. ARCHITECTURAL OVERVIEW
+
+ The Internet Printing Protocol (IPP) is an application level protocol
+ that can be used for distributed printing on the Internet. This
+ protocol defines interactions between a client and a server. The
+
+
+
+Zilles Experimental [Page 2]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ protocol allows a client to inquire about capabilities of a printer,
+ to submit print jobs and to inquire about and cancel print jobs. The
+ server for these requests is the Printer; the Printer is an
+ abstraction of a generic document output device and/or a print
+ service provider. Thus, the Printer could be a real printing device,
+ such as a computer printer or fax output device, or it could be a
+ service that interfaced with output devices.
+
+ The protocol is heavily influenced by the printing model introduced
+ in the Document Printing Application (DPA) [ISO10175] standard.
+ Although DPA specifies both end user and administrative features, IPP
+ version 1.0 (IPP/1.0) focuses only on end user functionality.
+
+ The architecture for IPP defines (in the Model and Semantics document
+ [RFC2566]) an abstract Model for the data which is used to control
+ the printing process and to provide information about the process and
+ the capabilities of the Printer. This abstract Model is hierarchical
+ in nature and reflects the structure of the Printer and the Jobs that
+ may be being processed by the Printer.
+
+ The Internet provides a channel between the client and the
+ server/Printer. Use of this channel requires flattening and
+ sequencing the hierarchical Model data. Therefore, the IPP also
+ defines (in the Encoding and Transport document [RFC2565]) an
+ encoding of the data in the model for transfer between the client and
+ server. This transfer of data may be either a request or the
+ response to a request.
+
+ Finally, the IPP defines (in the Encoding and Transport document
+ [RFC2565]) a protocol for transferring the encoded request and
+ response data between the client and the server/Printer.
+
+ An example of a typical interaction would be a request from the
+ client to create a print job. The client would assemble the Model
+ data to be associated with that job, such as the name of the job, the
+ media to use, the number of pages to place on each media instance,
+ etc. This data would then be encoded according to the Protocol and
+ would be transmitted according to the Protocol. The server/Printer
+ would receive the encoded Model data, decode it into a form
+ understood by the server/Printer and, based on that data, do one of
+ two things: (1) accept the job or (2) reject the job. In either case,
+ the server must construct a response in terms of the Model data,
+ encode that response according to the Protocol and transmit that
+ encoded Model data as the response to the request using the Protocol.
+
+ Another part of the IPP architecture is the Directory Schema
+ described in the model document. The role of a Directory Schema is to
+ provide a standard set of attributes which might be used to query a
+
+
+
+Zilles Experimental [Page 3]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ directory service for the URI of a Printer that is likely to meet the
+ needs of the client. The IPP architecture also addresses security
+ issues such as control of access to server/Printers and secure
+ transmissions of requests, response and the data to be printed.
+
+2. THE PRINTER
+
+ Because the (abstract) server/Printer encompasses a wide range of
+ implementations, it is necessary to make some assumptions about a
+ minimal implementation. The most likely minimal implementation is one
+ that is embedded in an output device running a specialized real time
+ operating system and with limited processing, memory and storage
+ capabilities. This printer will be connected to the Internet and will
+ have at least a TCP/IP capability with (likely) SNMP [RFC1905,
+ RFC1906] support for the Internet connection. In addition, it is
+ likely the the Printer will be an HTML/HTTP server to allow direct
+ user access to information about the printer.
+
+3. RATIONALE FOR THE MODEL
+
+ The Model [RFC2566] is defined independently of any encoding of the
+ Model data both to support the likely uses of IPP and to be robust
+ with respect to the possibility of alternate encoding.
+
+ It is expected that a client or server/Printer would represent the
+ Model data in some data structure within the applications/servers
+ that support IPP. Therefore, the Model was designed to make that
+ representation straightforward. Typically a parser or formatter would
+ be used to convert from or to the encoded data format. Once in an
+ internal form suitable to a product, the data can be manipulated by
+ the product. For example, the data sent with a Print Job can be used
+ to control the processing of that Print Job.
+
+ The semantics of IPP are attached to the (abstract) Model.
+ Therefore, the application/server is not dependent on the encoding of
+ the Model data, and it is possible to consider alternative mechanisms
+ and formats by which the data could be transmitted from a client to a
+ server; for example, a server could have a direct, client-less GUI
+ interface that might be used to accept some kinds of Print Jobs. This
+ independence would also allow a different encoding and/or
+ transmission mechanism to be used if the ones adopted here were shown
+ to be overly limiting in the future. Such a change could be migrated
+ into new products as an alternate protocol stack/parser for the Model
+ data.
+
+
+
+
+
+
+
+Zilles Experimental [Page 4]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ Having an abstract Model also allows the Model data to be aligned
+ with the (abstract) model used in the Printer [RFC1759], Job and Host
+ Resources MIBs. This provides consistency in interpretation of the
+ data obtained independently of how the data is accessed, whether via
+ IPP or via SNMP [RFC1905, RFC1906] and the Printer/Job MIBs.
+
+ There is one aspect of the Model that deserves some extra
+ explanation. There are two ways for identifying a Job object: (a)
+ with a Job URI and (b) using a combination of the Printer URI and a
+ Job ID (a 32 bit positive integer). Allowing Job objects to have URIs
+ allows for flexibility and scalability. For example a job could be
+ moved from a printer with a large backlog to one with a smaller load
+ and the job identification, the Job object URI, need not change.
+ However, many existing printing systems have local models or
+ interface constraints that force Job objects to be identified using
+ only a 32-bit positive integer rather than a URI. This numeric Job
+ ID is only unique within the context of the Printer object to which
+ the create request was originally submitted. In order to allow both
+ types of client access to Jobs (either by Job URI or by numeric Job
+ ID), when the Printer object successfully processes a create request
+ and creates a new Job, the Printer object generates both a Job URI
+ and a Job ID for the new Job object. This requirement allows all
+ clients to access Printer objects and Job objects independent of any
+ local constraints imposed on the client implementation.
+
+4. RATIONALE FOR THE PROTOCOL
+
+ There are two parts to the Protocol: (1) the encoding of the Model
+ data and (2) the mechanism for transmitting the model data between
+ client and server.
+
+4.1 The Encoding
+
+ To make it simpler to develop embedded printers, a very simple binary
+ encoding has been chosen. This encoding is adequate to represent the
+ kinds of data that occur within the Model. It has a simple structure
+ consisting of sequences of attributes. Each attribute has a name,
+ prefixed by a name length, and a value. The names are strings
+ constrained to characters from a subset of ASCII. The values are
+ either scalars or a sequence of scalars. Each scalar value has a
+ length specification and a value tag which indicates the type of the
+ value. The value type has two parts: a major class part, such as
+ integer or string, and a minor class part which distinguishes the
+ usage of the major class, such as dateTime string. Tagging of the
+ values with type information allows for introducing new value types
+ at some future time.
+
+
+
+
+
+Zilles Experimental [Page 5]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ A fully encoded request/response has a version number, an operation
+ (for a request) or a status and optionally a status message (for a
+ response), associated parameters and attributes which are encoded
+ Model data and, optionally (for a request), print data following the
+ Model data.
+
+4.2 The Transmission Mechanism
+
+ The chosen mechanism for transmitting the encoded Model data is HTTP
+ 1.1 Post (and associated response). No modifications to HTTP 1.1 are
+ proposed or required. The sole role of the Transmission Mechanism is
+ to provide a transfer of encoded Model data from/to the client
+ to/from the server. This could be done using any data delivery
+ mechanism. The key reasons why HTTP 1.1 Post is used are given below.
+ The most important of these is the first. With perhaps this
+ exception, these reasons could be satisfied by other mechanisms.
+ There is no claim that this list uniquely determines a choice of
+ mechanism.
+
+ 1. HTTP 1.0 is already widely deployed and, based on the recent
+ evidence, HTTP 1.1 is being widely deployed as the manufacturers
+ release new products. The performance benefits of HTTP 1.1 have
+ been shown and manufactures are reacting positively.
+
+ Wide deployment has meant that many of the problems of making a
+ protocol work in a wide range of environments from local net to
+ Intranet to Internet have been solved and will stay solved with
+ HTTP 1.1 deployment.
+
+ 2. HTTP 1.1 solves most of the problems that might have required a
+ new protocol to be developed. HTTP 1.1 allows persistent
+ connections that make a multi-message protocol be more efficient;
+ for example it is practical to have separate Create-Job and Send-
+ Document messages. Chunking allows the transmission of large print
+ files without having to pre-scan the file to determine the file
+ length. The accept headers allow the client's protocol and
+ localization desires to be transmitted with the IPP operations and
+ data. If the Model were to provide for the redirection of Job
+ requests, such as Cancel-Job, when a Job is moved, the HTTP
+ redirect response allows a client to be informed when a Job he is
+ interested in is moved to another server/Printer for any reason.
+
+ 3. Most network Printers will be implementing HTTP servers for
+ reasons other than IPP. These network attached Printers want to
+ provide information on how to use the printer, its current state,
+ HELP information, etc. in HTML. This requires having an HTTP
+ server which would be available to do IPP functions as well.
+
+
+
+
+Zilles Experimental [Page 6]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ 4. Most of the complexity of HTTP 1.1 is concerned with the
+ implementation of HTTP proxies and not the implementation of HTTP
+ clients and/or servers. Work is proceeding in the HTTP Working
+ Group to help identify what must be done by a server. As the
+ Encoding and Transport document shows, that is not very much.
+
+ 5. HTTP implementations provide support for handling URLs that
+ would have to be provided if a new protocol were defined.
+
+ 6. An HTTP based solution fits well with the Internet security
+ mechanisms that are currently deployed or being deployed. HTTP
+ will run over SSL3. The digest access authentication mechanism of
+ HTTP 1.1 provides an adequate level of access control. These
+ solutions are deployed and in practical use; a new solution would
+ require extensive use to have the same degree of confidence in its
+ security. Note: SSL3 is not on the IETF standards track.
+
+ 7. HTTP provides an extensibility model that a new protocol would
+ have to develop independently. In particular, the headers,
+ intent-types (via Internet Media Types) and error codes have wide
+ acceptance and a useful set of definitions and methods for
+ extension.
+
+ 8. Although not strictly a reason why IPP should use HTTP as the
+ transmission protocol, it is extremely helpful that there are many
+ prototyping tools that work with HTTP and that CGI scripts can be
+ used to test and debug parts of the protocol.
+
+ 9. Finally, the POST method was chosen to carry the print data
+ because its usage for data transmission has been established, it
+ works and the results are available via CGI scripts or servlets.
+ Creating a new method would have better identified the intended
+ use of the POSTed data, but a new method would be more difficult
+ to deploy. Assigning a new default port for IPP provided the
+ necessary identification with minimal impact to installed
+ infrastructure, so was chosen instead.
+
+5. RATIONALE FOR THE DIRECTORY SCHEMA
+
+ Successful use of IPP depends on the client finding a suitable IPP
+ enabled Printer to which to send a IPP requests, such as print a
+ job. This task is simplified if there is a Directory Service which
+ can be queried for a suitable Printer. The purpose of the
+ Directory Schema is to have a standard description of Printer
+ attributes that can be associated the URI for the printer. These
+ attributes are a subset of the Model attributes and can be encoded
+ in the appropriate query syntax for the Directory Service being
+ used by the client.
+
+
+
+Zilles Experimental [Page 7]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+6. SECURITY CONSIDERATIONS - RATIONALE FOR SECURITY
+
+ Security is an area of active work on the Internet. Complete
+ solutions to a wide range of security concerns are not yet
+ available. Therefore, in the design of IPP, the focus has been on
+ identifying a set of security protocols/features that are
+ implemented (or currently implementable) and solve real problems
+ with distributed printing. The two areas that seem appropriate to
+ support are: (1) authorization to use a Printer and (2) secure
+ interaction with a printer. The chosen mechanisms are the digest
+ authentication mechanism of HTTP 1.1 and SSL3 [SSL] secure
+ communication mechanism.
+
+7. REFERENCES
+
+ [ipp-iig] Hastings, T. and C. Manros, "Internet Printing
+ Protocol/1.0:Implementer's Guide", Work in Progress.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2566] deBry, R., Isaacson, S., Hastings, T., Herriot, R. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [ISO10175] ISO/IEC 10175 "Document Printing Application (DPA)", June
+ 1996.
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S. and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1905] Case, J., McCloghrie, K., Rose, M. and S. Waldbusser,
+ "Protocol Operations for Version 2 of the Simple Network
+ Management Protocol (SNMPv2)", RFC 1905, January 1996.
+
+ [RFC1906] Case, J., McCloghrie, K., Rose, M. and S. Waldbusser,
+ "Transport Mappings for Version 2 of the Simple Network
+ Management Protocol (SNMPv2)", RFC 1906, January 1996.
+
+
+
+
+
+Zilles Experimental [Page 8]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version
+ 3.02), November 1996.
+
+8. AUTHOR'S ADDRESS
+
+ Stephen Zilles
+ Adobe Systems Incorporated
+ 345 Park Avenue
+ MailStop W14
+ San Jose, CA 95110-2704
+
+ Phone: +1 408 536-4766
+ Fax: +1 408 537-4042
+ EMail: szilles@adobe.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zilles Experimental [Page 9]
+
+RFC 2568 Rationale for IPP April 1999
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Zilles Experimental [Page 10]
+
diff --git a/standards/rfc2569.txt b/standards/rfc2569.txt
new file mode 100644
index 000000000..767857c34
--- /dev/null
+++ b/standards/rfc2569.txt
@@ -0,0 +1,1571 @@
+
+
+
+
+
+
+Network Working Group R. Herriot
+Request For Comments: 2569 Xerox Corporation
+Category: Experimental N. Jacobs
+ Sun Microsystems, Inc.
+ T. Hastings
+ Xerox Corporation
+ J. Martin
+ Underscore, Inc.
+ April 1999
+
+
+ Mapping between LPD and IPP Protocols
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note
+
+ This document defines an Experimental protocol for the Internet
+ community. The IESG expects that a revised version of this protocol
+ will be published as Proposed Standard protocol. The Proposed
+ Standard, when published, is expected to change from the protocol
+ defined in this memo. In particular, it is expected that the
+ standards-track version of the protocol will incorporate strong
+ authentication and privacy features, and that an "ipp:" URL type will
+ be defined which supports those security measures. Other changes to
+ the protocol are also possible. Implementors are warned that future
+ versions of this protocol may not interoperate with the version of
+ IPP defined in this document, or if they do interoperate, that some
+ protocol features may not be available.
+
+ The IESG encourages experimentation with this protocol, especially in
+ combination with Transport Layer Security (TLS) [RFC 2246], to help
+ determine how TLS may effectively be used as a security layer for
+ IPP.
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 1]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon). This document describes the mapping between (1) the commands
+ and operands of the 'Line Printer Daemon (LPD) Protocol' specified in
+ RFC 1179 and (2) the operations, operation attributes and job
+ template attributes of the Internet Printing Protocol/1.0 (IPP). One
+ of the purposes of this document is to compare the functionality of
+ the two protocols. Another purpose is to facilitate implementation
+ of gateways between LPD and IPP.
+
+ WARNING: RFC 1179 was not on the IETF standards track. While RFC
+ 1179 was intended to record existing practice, it fell short in some
+ areas. However, this specification maps between (1) the actual
+ current practice of RFC 1179 and (2) IPP. This document does not
+ attempt to map the numerous divergent extensions to the LPD protocol
+ that have been made by many implementers.
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics [RFC2566]
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Internet Printing Protocol/1.0: Implementors Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols (this document)
+
+ The document, "Design Goals for an Internet Printing Protocol", takes
+ a broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0. Operator and administrator requirements are
+ out of scope for version 1.0.
+
+ The document, "Rationale for the Structure and Model and Protocol for
+ the Internet Printing Protocol", describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specifications, and gives background and rationale for the
+ IETF working group's major decisions.
+
+
+
+
+
+Herriot, et al. Experimental [Page 2]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ The document, "Internet Printing Protocol/1.0: Model and Semantics",
+ describes a simplified model with abstract objects, their attributes,
+ and their operations. It introduces a Printer and a Job object. The
+ Job object supports multiple documents per Job. It also addresses
+ security, internationalization, and directory issues.
+
+ The document, "Internet Printing Protocol/1.0: Encoding and
+ Transport", is a formal mapping of the abstract operations and
+ attributes defined in the model document onto HTTP/1.1. It defines
+ the encoding rules for a new Internet media type called '
+ application/ipp'.
+
+ This document "Internet Printing Protocol/1.0: Implementer's Guide",
+ gives advice to implementers of IPP clients and IPP objects.
+
+TABLE OF CONTENTS
+
+ 1. Introduction.....................................................4
+ 2. Terminology......................................................5
+ 3. Mapping from LPD Commands to IPP Operations......................5
+ 3.1 Print any waiting jobs..........................................6
+ 3.2 Receive a printer job...........................................6
+ 3.2.1 Abort job.....................................................7
+ 3.2.2 Receive control file..........................................7
+ 3.2.3 Receive data file.............................................8
+ 3.3 Send queue state (short)........................................8
+ 3.4 Send queue state (long)........................................10
+ 3.5 Remove jobs....................................................12
+ 4. Mapping of LPD Control File Lines to IPP Operation and Job
+ Template Attributes.............................................13
+ 4.1 Required Job Functions.........................................13
+ 4.2 Optional Job Functions.........................................14
+ 4.3 Required Document Functions....................................14
+ 4.4 Recommended Document Functions.................................16
+ 5. Mapping from IPP operations to LPD commands.....................16
+ 5.1 Print-Job......................................................16
+ 5.2 Print-URI......................................................18
+ 5.3 Validate-Job...................................................18
+ 5.4 Create-Job.....................................................18
+ 5.5 Send-Document..................................................18
+ 5.6 Send-URI.......................................................18
+ 5.7 Cancel-Job.....................................................18
+ 5.8 Get-Printer-Attributes.........................................19
+ 5.9 Get-Job-Attributes.............................................19
+ 5.10 Get-Jobs......................................................20
+ 6. Mapping of IPP Attributes to LPD Control File Lines.............20
+ 6.1 Required Job Functions.........................................21
+ 6.2 Optional Job Functions.........................................21
+
+
+
+Herriot, et al. Experimental [Page 3]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ 6.3 Required Document Functions....................................22
+ 7. Security Considerations.........................................23
+ 8. References......................................................23
+ 9. Authors' Addresses..............................................24
+ 10.Appendix A: ABNF Syntax for response of Send-queue-state (short)25
+ 11.Appendix B: ABNF Syntax for response of Send-queue-state (long) 26
+ 12.Appendix C: Unsupported LPD functions...........................27
+ 13.Full Copyright Statement........................................28
+
+1. Introduction
+
+ The reader of this specification is expected to be familiar with the
+ IPP Model and Semantics specification [RFC2566], the IPP Encoding and
+ Transport [RF2565], and the Line Printer Daemon (LPD) protocol
+ specification [RFC1179] as described in RFC 1179.
+
+ RFC 1179 was written in 1990 in an attempt to document existing LPD
+ protocol implementations. Since then, a number of undocumented
+ extensions have been made by vendors to support functionality
+ specific to their printing solutions. All of these extensions
+ consist of additional control file commands. This document does not
+ address any of these vendor extensions. Rather it addresses existing
+ practice within the context of the features described by RFC 1179.
+ Deviations of existing practice from RFC 1179 are so indicated.
+
+ Other LPD control file commands in RFC 1179 are obsolete. They are
+ intended to work on "text" only formats and are inappropriate for
+ many contemporary document formats that completely specify each page.
+ This document does not address the support of these obsolete
+ features.
+
+ In the area of document formats, also known as page description
+ languages (PDL), RFC 1179 defines a fixed set with no capability for
+ extension. Consequently, some new PDL's are not supported, and some
+ of those that are supported are sufficiently unimportant now that
+ they have not been registered for use with the Printer MIB [RFC1759]
+ and IPP [RFC2566] [RFC2565], though they could be registered if
+ desired. See the Printer MIB specification [RFC1759] and/or the IPP
+ Model specification [RFC2566] for instructions for registration of
+ document-formats with IANA. IANA lists the registered document-
+ formats as "printer languages".
+
+ This document addresses the protocol mapping for both directions:
+ mapping of the LPD protocol to the IPP protocol and mapping of the
+ IPP protocol to the LPD protocol. The former is called the "LPD-to-
+ IPP mapper" and the latter is called the "IPP-to-LPD mapper".
+
+
+
+
+
+Herriot, et al. Experimental [Page 4]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ This document is an informational document that is not on the
+ standards track. It is intended to help implementers of gateways
+ between IPP and LPD. It also provides an example, which gives
+ additional insight into IPP.
+
+2. Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+ RFC 1179 uses the word "command" in two contexts: for over-the-wire
+ operations and for command file functions. This document SHALL use
+ the word "command" for the former and the phrase "functions" for the
+ latter. The syntax of the LPD commands is given using ABNF
+ [RFC2234].
+
+ The following tokens are used in order to make the syntax more
+ readable:
+
+ LF stands for %x0A (linefeed)
+ SP stands for %x20. (space)
+ DIGIT stands for %x30-39 ("0" to "9")
+
+3. Mapping from LPD Commands to IPP Operations
+
+ This section describes the mapping from LPD commands to IPP
+ operations. Each of the following sub-sections appear as sub-
+ sections of section 5 of RFC 1179.
+
+ The following table summarizes the IPP operation that the mapper uses
+ when it receives an LPD command. Each section below gives more
+ detail:
+
+ LPD command IPP operation
+
+
+ print-any-waiting-jobs ignore
+ receive-a-printer-job Print-Job or Create-Job/Send-Document
+ send queue state Get-Printer-Attributes and Get-Jobs
+ (short or long)
+ remove-jobs Cancel-Job
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 5]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+3.1 Print any waiting jobs
+
+ Command syntax:
+
+ print-waiting-jobs = %x01 printer-name LF
+
+ This command causes the LPD daemon check its queue and print any
+ waiting jobs. An IPP printer handles waiting jobs without such a
+ nudge.
+
+ If the mapper receives this LPD command, it SHALL ignore it and send
+ no IPP operation.
+
+3.2 Receive a printer job
+
+ Command syntax:
+
+ receive-job = %x02 printer-name LF
+
+ The control file and data files mentioned in the following paragraphs
+ are received via LPD sub-commands that follow this command. Their
+ mapping to IPP commands and attributes is described later in this
+ section.
+
+ The mapper maps the 'Receive a printer job' command to either:
+
+ - the Print-Job operation which includes a single data file or
+ - the Create-Job operation followed by one Send-Document operation
+ for each data file.
+
+ If the IPP printer supports both Create-Job and Send-Document, and if
+ a job consists of:
+
+ - a single data file, the mapper SHOULD use the Print-Job
+ operation, but MAY use the Create-Job and Send-Document
+ operations.
+ - more than one data file, the mapper SHALL use Create-Job
+ followed by one Send-Document for each received LPD data file.
+
+ If the IPP printer does not support both Create-Job and Send-
+ Document, and if a job consists of:
+
+ - a single data file, the mapper SHALL use the PrintJob
+ operation.
+ - more than one data file, the mapper SHALL submit each received
+ LPD data file as a separate Print-Job operation (thereby
+ converting a single LPD job into multiple IPP jobs).
+
+
+
+
+Herriot, et al. Experimental [Page 6]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ If the mapper uses Create-Job and Send-Document, it MUST send the
+ Create-Job operation before it sends any Send-Document operations
+ whether the LPD control file, which supplies attributes for Create-
+ Job, arrives before or after all LPD data files.
+
+ NOTE: This specification does not specify how the mapper maps: the
+ LPD Printer-name operand to the IPP "printer-uri" operation
+ attribute.
+
+ The following three sub-sections gives further details about the
+ mapping from LPD receive-a-printer-job sub-commands. Each of the
+ following subsections appear as sub-sections of section 6 of RFC
+ 1179.
+
+3.2.1 Abort job
+
+ Sub-command syntax:
+
+ abort-job = %x1 LF
+
+ This sub-command of receive-a-printer-job is intended to abort any
+ job transfer in process.
+
+ If the mapper receives this sub-command, it SHALL cancel the job that
+ it is in the process of transmitting.
+
+ If the mapper is in the process of sending a Print-Job or Create-Job
+ operation, it terminates the job either by closing the connection, or
+ performing the Cancel-Job operation with the job-uri that it received
+ from the Print-Job or Create-Job operation.
+
+ NOTE: This sub-command is implied if at any time the connection
+ between the LPD client and server is terminated before an entire
+ print job has been transferred via an LPD Receive-a-printer-job
+ request.
+
+3.2.2 Receive control file
+
+ Sub-command syntax:
+
+ receive-control-file = %x2 number-of-bytes SP name-of-control-file LF
+ number-of-bytes = 1*DIGIT
+ name-of-control-file = "cfA" job-number client-host-name
+ ; e.g. "cfA123woden"
+ job-number = 3DIGIT
+ client-host-name = <a host name>
+
+
+
+
+
+Herriot, et al. Experimental [Page 7]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ This sub-command is roughly equivalent to the IPP Create-Job
+ operation.
+
+ The mapper SHALL use the contents of the received LPD control file to
+ create IPP operation attribute and job template attribute values to
+ transmit with the Print-Job or Create-Job operation.
+
+3.2.3 Receive data file
+
+Sub-command syntax: %x3 number-of-bytes-in-data-file Name-of-data-file
+
+ receive-data-file = %x03 number-of-bytes SP name-of-data-file LF
+ number-of-bytes = 1*DIGIT
+ name-of-data-file = "df" letter job-number client-host-name
+ ; e.g. "dfA123woden for the first file
+ letter = %x41-5A / %x61-7A ; "A" to "Z", "a" to "z"
+ ; first file is "A",
+ ; second "B", and 52nd file is "z"
+ job-number = 3DIGIT
+ client-host-name = <a host name>
+
+ This sub-command is roughly equivalent to the IPP Send-Document
+ operation.
+
+ The mapper SHALL use the contents of the received LPD data file as
+ the data to transmit with the IPP Print-Job or Send-Document
+ operation.
+
+ Although RFC 1179 alludes to a method for passing an unspecified
+ length data file by using an octet-count of zero, no implementations
+ support this feature. The mapper SHALL reject a job that has a value
+ of 0 in the number-of-bytes field.
+
+3.3 Send queue state (short)
+
+ Command syntax:
+
+send-queue-short = %x03 printer-name *(SP(user-name / job-number)) LF
+
+ The mapper's response to this command includes information about the
+ printer and its jobs. RFC 1179 specifies neither the information nor
+ the format of its response. This document requires the mapper to
+ follow existing practice as specified in this document.
+
+ The mapper SHALL produce a response in the following format which
+ consists of a printer-status line optionally followed by a heading
+ line, and a list of jobs. This format is defined by examples below.
+ Appendix A contains the ABNF syntax.
+
+
+
+Herriot, et al. Experimental [Page 8]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ For an printer with no jobs, the response starts in column 1 and is:
+
+ no entries
+
+ For a printer with jobs, an example of the response is:
+
+ killtree is ready and printing
+ Rank Owner Job Files Total Size
+ active fred 123 stuff 1204 bytes
+ 1st smith 124 resume, foo 34576 bytes
+ 2nd fred 125 more 99 bytes
+ 3rd mary 126 mydoc 378 bytes
+ 4th jones 127 statistics.ps 4567 bytes
+ 5th fred 128 data.txt 9 bytes
+
+ The column numbers of above headings and job entries are:
+
+ | | | | |
+ 01 08 19 35 63
+
+ The mapper SHALL produce each field above from the following IPP
+ attribute:
+
+ LPD field IPP attribute special conversion details
+
+ printer- printer-state and For a printer-state of idle or
+ status printer-state-reasons processing, the mapper SHALL use
+ the formats above. For stopped,
+ the mapper SHALL use printer-
+ state-reasons to produce an
+ unspecified format for the error.
+ rank number-of- the mapper SHALL the format above
+ intervening-jobs
+ owner job-originating-user- unspecified conversion; job-
+ name originating-user-name may be the
+ mapper's user-name
+ job job-id the mapper shall use the job-id
+ files document-name the mapper shall create a comma
+ separated list of the document-
+ names and then truncate this list
+ to the first 24 characters
+ total- job-k- the mapper shall multiple the
+ size octets*copies*1024 value of job-k-octets by 1024 and
+ by the value of the "copies"
+ attribute.
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 9]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ A mapper SHOULD use the job attribute number-of-intervening-jobs
+ rather than the job's position in a list of jobs to determine 'rank'
+ because a Printer may omit jobs that it wants to keep secret. If a
+ printer doesn't support the job attribute number-of-intervening-jobs,
+ a mapper MAY use the job's position.
+
+ Note: a Printer may set the value of job-originating-user-name to the
+ authenticated user or to the value of "requesting-user-name",
+ depending on the implementation and configuration. For a gateway, the
+ authenticated user is the user-id of the gateway, but the
+ "requesting-user-name" may contain the name of the user who is the
+ gateway's client.
+
+ In order to obtain the information specified above, The LPD-to-IPP
+ mapper SHALL use the Get-Printer-Attributes operation to get
+ printer-status and SHOULD use the Get-Jobs operation to get
+ information about all of the jobs. If the LPD command contains job-
+ numbers or user-names, the mapper MAY handle the filtering of the
+ response. If the LPD command contains job-numbers but no user-names,
+ the mapper MAY use Get-Job-Attributes on each converted job-number
+ rather than Get-Jobs. If the LPD command contains a single user-name
+ but no job-numbers, the mapper MAY use Get-Jobs with the my-jobs
+ option if the server supports this option and if the server allows
+ the client to be a proxy for the LPD user.
+
+ NOTE: This specification does not define how the mapper maps the LPD
+ Printer-name operand to the IPP "printer-uri" operation attribute.
+
+3.4 Send queue state (long)
+
+ Command syntax:
+
+ send-queue-long = %x04 printer-name *(SP(user-name / job-number)) LF
+
+ The mapper's response to this command includes information about the
+ printer and its jobs. RFC 1179 specifies neither the information nor
+ the format of its response. This document requires the mapper to
+ follow existing practice as specified in this document.
+
+ The mapper SHALL produce a response in the following format which
+ consists of a printer-status line optionally followed a list of jobs,
+ where each job consists of a blank line, a description line, and one
+ line for each file. The description line contains the user-name,
+ rank, job-number and host. This format is defined by examples below.
+ Appendix B contain the ABNF syntax.
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 10]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ For an printer with no jobs the response is:
+
+ no entries
+
+ For a printer with jobs, an example of the response is:
+
+ killtree is ready and printing
+
+ fred: active [job 123 tiger]
+ 2 copies of stuff 602 bytes
+
+ smith: 1st [job 124 snail]
+ 2 copies of resume 7088 bytes
+ 2 copies of foo 10200 bytes
+
+ fred: 2nd [job 125 tiger]
+ more 99 bytes
+
+ The column numbers of above headings and job entries are:
+
+ | | |
+ 01 09 41
+
+ Although the format of the long form is different from the format of
+ the short form, their fields are identical except for a) the copies
+ and host fields which are only in the long form, and b) the "size"
+ field contains the single copy size of each file. Thus the sum of
+ the file sizes in the "size" field times the value of the "copies"
+ field produces the value for the "Total Size" field in the short
+ form. For fields other than the host and copies fields, see the
+ preceding section. For the host field see the table below.
+
+ LPD field IPP attribute special conversion details
+
+ host unspecified conversion; job-
+ originating-host may be the
+ mapper's host
+ copies copies the mapper shall assume the
+ value of copies precedes the
+ string "copies of "; otherwise,
+ the value of copies is 1.
+
+ NOTE: This specification does not define how the mapper maps the LPD
+ Printer-name operand to the IPP printer-uri operation attribute.
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 11]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+3.5 Remove jobs
+
+ Command syntax:
+
+ remove-jobs = %x05 printer-name SP agent
+ *(SP(user-name / job-number)) LF
+
+ The agent operand is the user-name of the user initiating the
+ remove-jobs command. The special user-name 'root' indicates a
+ privileged user who can remove jobs whose user-name differs from the
+ agent.
+
+ The mapper SHALL issue one Cancel-Job operation for each job
+ referenced by the remove-jobs command. Each job-number in the
+ remove-jobs command references a single job. Each user-name in the
+ remove-jobs command implicitly references all jobs owned by the
+ specified user. The active job is implicitly referenced when the
+ remove-jobs command contains neither job-numbers nor user-names. The
+ mapper MAY use Get-Jobs to determine the job-uri of implicitly
+ referenced jobs.
+
+ The mapper SHALL not use the agent name of 'root' when end-users
+ cancel their own jobs. Violation of this rule creates a potential
+ security violation, and it may cause the printer to issue a
+ notification that misleads a user into thinking that some other
+ person canceled the job.
+
+ If the agent of a remove-jobs command for a job J is the same as the
+ user name specified with the 'P' function in the control file for job
+ J, then the mapper SHALL ensure that the initiator of the Cancel-Job
+ command for job J is the same as job-originating-user for job J.
+
+ Note: This requirement means that a mapper must be consistent in who
+ the receiver perceives as the initiator of IPP operations. The mapper
+ either acts as itself or acts on behalf of another user. The latter
+ is preferable if it is possible. This consistency is necessary
+ between Print-Job/Create-Job and Cancel-Job in order for Cancel-Job
+ to work, but it is also desirable for other operations. For example,
+ Get-Jobs may give more information about job submitted by the
+ initiator of this operation.
+
+ NOTE: This specification does not define how the mapper maps: (1) the
+ LPD printer-name to the IPP "printer-uri" or (2) the LPD job-number
+ to the IPP "job-uri".
+
+ NOTE: This specification does not specify how the mapper maps the LPD
+ user-name to the IPP job-originating-user because the mapper may use
+ its own user-name with jobs.
+
+
+
+Herriot, et al. Experimental [Page 12]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+4. Mapping of LPD Control File Lines to IPP Operation and Job Template
+ Attributes
+
+ This section describes the mapping from LPD control file lines
+ (called 'functions') to IPP operation attributes and job template
+ attributes. The mapper receives the control file lines via the LPD
+ receive-control-file sub-command. Each of the LPD functions appear
+ as sub-sections of section 7 of RFC 1179.
+
+ In LPD control file lines, the text operands have a maximum length of
+ 31 or 99 while IPP operation attribute and job template attribute
+ values have a maximum of 255 or 1023 octets, depending on the
+ attribute syntax. Therefore, no data is lost.
+
+ The mapper converts each supported LPD function to its corresponding
+ IPP operation or job template attribute as defined by tables in the
+ subsections that follow. These subsections group functions according
+ to whether they are:
+
+ - required with a job,
+ - optional with a job
+ - required with each document.
+
+ In the tables below, each LPD value is given a name, such as 'h'. If
+ an IPP value uses the LPD value, then the IPP value column contains
+ the LPD name, such as 'h' to denote this. Otherwise, the IPP value
+ column specifies the literal value.
+
+4.1 Required Job Functions
+
+ The following LPD functions MUST be in a received LPD job. The mapper
+ SHALL receive each of the following LPD functions and SHALL include
+ the information as a operation or job template attribute with each
+ IPP job. The functions SHOULD be in the order 'H', 'P' and they
+ SHOULD be the first two functions in the control file, but they MAY
+ be anywhere in the control file and in any order:
+
+ LPD function IPP
+ name value description name value
+
+ H h Originating Host h (in security layer)
+ P u User identification requesting- u (and in security
+ user-name layer)
+ none ipp- 'true'
+ attribute-
+ fidelity
+
+
+
+
+
+Herriot, et al. Experimental [Page 13]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ A mapper MAY send its own host rather than the client's host, and a
+ mapper MAY send its own user-name as user identification rather than
+ the client user. But in any case, the values sent SHALL be compatible
+ with the Cancel-Job operation. The IPP operation MAY have no way to
+ specify an originating host-name.
+
+ The mapper SHALL include ipp-attribute-fidelity = true so that it
+ doesn't have to determine which attributes a printer supports.
+
+4.2 Optional Job Functions
+
+ The following LPD functions MAY be present in a received job. These
+ functions SHOULD follow the required job functions and precede the
+ document functions, but they MAY be anywhere in the control file.
+
+ If the mapper receives such an LPD function, the mapper SHALL include
+ the corresponding IPP attribute with the value converted as specified
+ in the table below. If the mapper does not receive such an LPD
+ attribute, the mapper SHALL NOT include the corresponding IPP
+ attribute, except the 'L' LPD function whose absence has a special
+ meaning as noted in the table.
+
+ LPD function IPP
+ name value description name value
+
+ J j Job name for job-name j
+ banner page
+ L l Print banner page job-sheets 'standard' if 'L' is
+ present
+ 'none' if 'L' is present
+ M m Mail When Printed IPP has no notification
+ mechanism. To support
+ this LPD feature, the
+ gateway must poll using
+ the Get-Job-Attributes
+ operation.
+
+4.3 Required Document Functions
+
+ The mapper SHALL receive one set of the required document functions
+ with each copy of a document, and SHALL include the converted
+ information as operation or job template attributes with each IPP
+ document.
+
+ If the control file contains required and recommended document
+ functions, the required functions SHOULD precede the recommended ones
+ and if the job contains multiple documents, all the functions for
+
+
+
+
+Herriot, et al. Experimental [Page 14]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ each document are grouped together as shown in the example of section
+ 6.3 "Required Document Functions". However, the document functions
+ MAY be in any order.
+
+ LPD function IPP
+ name value description name value
+
+ f fff Print formatted document-format 'application/octet-
+ file stream'
+ l fff Print file leaving document-format 'application/octet-
+ control characters stream'
+ o fff Print Postscript document-format 'application/PostScri
+ output file pt'
+ copies see note
+
+ Note: In practice, the 'f' LPD function is often overloaded. It is
+ often used with any format of document data including PostScript and
+ PCL data.
+
+ Note: In practice, the 'l' LPD function is often used as a rough
+ equivalent to the 'f' function.
+
+ Note: When RFC 1179 was written, no implementation supported the 'o'
+ function; instead 'f' was used for PostScript. Windows NT now sends '
+ o' function for a PostScript file.
+
+ Note: the value 'fff' of the 'f', 'l' and 'o' functions is the name
+ of the data file as transferred, e.g. "dfA123woden".
+
+ If the mapper receives any other lower case letter, the mapper SHALL
+ reject the job because the document contains a format that the mapper
+ does not support.
+
+ The mapper determines the number of copies by counting the number of
+ occurrences of each 'fff' file with one of the lower-case functions
+ above. For example, if 'f dfA123woden' occurs 4 times, then copies
+ has a value of 4. Although the LPD protocol allows the value of
+ copies to be different for each document, the commands and the
+ receiving print systems don't support this.
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 15]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+4.4 Recommended Document Functions
+
+ The mapper SHOULD receive one set of the recommended document
+ functions with each document, and SHOULD include the converted
+ information as an operation or job template attribute with each IPP
+ document. The functions SHOULD be received in the order 'U' and 'N',
+ but they MAY arrive in any order.
+
+ LPD function IPP
+ name value description name value
+
+ U fff ignored
+ N n Name of source file document-name n
+
+ Note: the value 'fff' of the 'U' function is the name of the data
+ file as transferred, e.g. "dfA123woden".
+
+5. Mapping from IPP operations to LPD commands
+
+ If the IPP-to-LPD mapper receives an IPP operation, the following
+ table summarizes the LPD command that it uses. Each section below
+ gives the detail. Each of the following sub-sections appear as sub-
+ sections of section 3 in the document "Internet Printing
+ Protocol/1.0: Model and Semantics" [RFC2566].
+
+ IPP operation LPD command
+
+ Print-Job or Print-URI or receive-a-printer-job
+ Create-Job/Send-Document/Send-URI and then print-any-waiting-jobs
+ Validate-Job implemented by the mapper
+ Cancel-Job remove-jobs
+ Get-Printer-Attributes, Get-Job- send queue state (short or long)
+ Attributes or Get-Jobs
+
+5.1 Print-Job
+
+ The mapper SHALL send the following commands in the order listed
+ below:
+
+ - receive-a-printer-job command
+ - both receive-control-file sub-command and receive-data-file
+ sub-command (unspecified order, see Note below)
+ - print-any-waiting-jobs command, except that if the mapper is
+ sending a sequence of receive a printer-job commands, it MAY
+ omit sending print-any-waiting-jobs after any receive a
+ printer-job command that is neither the first nor last command
+ in this sequence
+
+
+
+
+Herriot, et al. Experimental [Page 16]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ Note: it is recommended that the order of the receive-control-file
+ subcommand and the receive-data-file sub-command be configurable
+ because either order fails for some print systems. Some print systems
+ assume that the control file follows all data files and start
+ printing immediately on receipt of the control file. When such a
+ print system tries to print a data file that has not arrived, it
+ produces an error. Other print systems assume that the control file
+ arrives before the data files and start printing when the first data
+ file arrives. Such a system ignores the control information, such as
+ banner page or copies.
+
+ NOTE: This specification does not define the mapping between the IPP
+ printer-uri and the LPD printer-name.
+
+ The mapper SHALL send the IPP operation attributes and job template
+ attributes received from the operation to the LPD printer by using
+ the LPD receive-control-file sub-command. The mapper SHALL create the
+ LPD job-number for use in the control file name, but the receiving
+ printer MAY, in some circumstances, assign a different job-number to
+ the job. The mapper SHALL create the IPP job-id and IPP job-uri
+ returned in the Print-Job response.
+
+ NOTE: This specification does not specify how the mapper determines
+ the LPD job-number, the IPP job-id or the IPP job-uri of a job that
+ it creates nor does it specify the relationship between the IPP job-
+ uri, IPP the job-id and the LPD job-number, both of which the mapper
+ creates. However, it is likely that the mapper will use the same
+ integer value for both the LPD job-number and the IPP job-id, and
+ that the IPP Job-uri is the printer's URI with the job-id
+ concatenated on the end.
+
+ The mapper SHALL send data received in the IPP operation to the LPD
+ printer by using the LPD receive-data-file sub-command. The mapper
+ SHALL specify the exact number of bytes being transmitted in the
+ number-of-bytes field of the receive-data-file sub-command. It SHALL
+ NOT use a value of 0 in this field.
+
+ If the mapper, while it is transmitting a receive-a-printer-job
+ command or sub-command, either detects that its IPP connection has
+ closed or receives a Cancel-Job operation, the mapper SHALL terminate
+ the LPD job either with the abort sub-command or the remove-jobs
+ command.
+
+ This document does not address error code conversion.
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 17]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+5.2 Print-URI
+
+ The mapper SHALL handle this operation in the same way as a Print-Job
+ operation except that it SHALL obtain data referenced by the
+ "document-uri" operation attribute and SHALL then treat that data as
+ if it had been received via a Print-Job operation.
+
+5.3 Validate-Job
+
+ The mapper SHALL perform this operation directly. Because LPD
+ supports very few attributes, this operation doesn't have much to
+ check.
+
+5.4 Create-Job
+
+ The mapper SHALL handle this operation like Print-Job, except:
+
+ - the mapper SHALL send the control file after it has received the
+ last Send-Document or Send-URI operation because the control
+ file contains all the document-name and document-format values
+ specified in the Send-Document and Send-URI operations.
+ - the mapper SHALL perform one receive-data-file sub-command for
+ each Send-Document or Send-URI operation received and in the
+ same order received.
+ - the mapper SHALL send the control file either before all data
+ files or after all data files. (See the note in the section on
+ Print-Job about the dilemma of sending the control file either
+ before or after the data files.
+
+5.5 Send-Document
+
+ The mapper performs a receive-data-file sub-command on the received
+ data. See the preceding section 5.4 "Create-Job" for the details.
+
+5.6 Send-URI
+
+ The mapper SHALL obtain the data referenced by the "document-uri"
+ operation attribute, and SHALL then treat that data as if it had been
+ received via a Send-Document operation. See the preceding section 5.5
+ "Send-Document" for the details.
+
+5.7 Cancel-Job
+
+ The mapper SHALL perform a remove-jobs command with the following
+ operation attributes:
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 18]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ - the printer is the one to which the job was submitted, that is
+ the IPP printer-uri is mapped to an LPD printer-name by the same
+ mechanism as for all commands
+ - the agent is the authenticated user-name of the IPP client
+ - the job-number is the job-id returned by the Print-Job command,
+ that is, the LPD job-number has the same value as the IPP job-id
+ for likely implementations
+
+5.8 Get-Printer-Attributes
+
+ LPD severely limits the set of attributes that the mapper is able to
+ return in its response for this operation. The mapper SHALL support,
+ at most, the following printer attributes:
+
+ - printer-state
+ - printer-state-reasons
+
+ The mapper uses either the long or short form of the "send queue
+ state" command.
+
+ The mapper SHALL assume that the LPD response that it receives has
+ the format and information specified in section 3.3 "Send queue state
+ (short)" and section 3.4 "Send queue state (long)". The mapper SHALL
+ determine the value of each requested attribute by using the inverse
+ of the mapping specified in the two aforementioned sections.
+
+ Note: the mapper can determine the response from the printer-status
+ line without examining the rest of the LPD response.
+
+5.9 Get-Job-Attributes
+
+ LPD severely limits the set of attributes that the mapper is able to
+ return in its response for this operation. The mapper SHALL support,
+ at most, the following job attributes:
+
+ - number-of-intervening-jobs
+ - job-originating-user-name
+ - job-id
+ - document-name
+ - job-k-octets
+ - copies
+
+ The mapper uses either the long or short form of the "send queue
+ state" command. If it receives a request for the "job-k-octets" or
+ "copies" and supports the attribute it SHALL use the long form;
+ otherwise, it SHALL use the short form.
+
+
+
+
+
+Herriot, et al. Experimental [Page 19]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ Note: the value of job-k-octets is the value in the short form
+ divided by the number of "copies" which is on the long form only. Its
+ value can also be determined by adding the "size" field values for
+ each document in the job in the long form.
+
+ The mapper SHALL assume that the LPD response that it receives has
+ the format and information specified in section 3.3 "Send queue state
+ (short)" and section 3.4 "Send queue state (long)". The mapper SHALL
+ determine the value of each requested attribute by using the inverse
+ of the mapping specified in the two aforementioned sections.
+
+ Note: when the mapper uses the LPD short form, it can determine the
+ response from the single LPD line that pertains to the job specified
+ by the Get-Job-Attributes operation.
+
+ Note: the mapper can use its correspondence between the IPP job-id,
+ job-uri and the LPD job-number.
+
+5.10 Get-Jobs
+
+ The mapper SHALL perform this operation in the same way as Get-Job-
+ Attributes except that the mapper converts all the LPD job-lines, and
+ the IPP response contains one job object for each job-line in the LPD
+ response.
+
+6. Mapping of IPP Attributes to LPD Control File Lines
+
+ This section describes the mapping from IPP operation attributes and
+ job template attributes to LPD control file lines (called '
+ functions'). The mapper receives the IPP operation attributes and job
+ template atributes via the IPP operation. Each of the IPP operation
+ attributes and job template attributes appear as sub-sections of
+ section 3 and 4.2 in the IPP model document [RFC2566].
+
+ In the context of LPD control file lines, the text operands have a
+ maximum length of 31 or 99 while IPP operation attributes and job
+ template attributes have a maximum of 255 or 1023 octets, depending
+ on the attribute syntax. Therefore, there may be some data loss if
+ the IPP operation attribute and job template attribute values exceed
+ the maximum length of the LPD equivalent operands.
+
+ The mapper converts each supported IPP operation attribute and job
+ template attribute to its corresponding LPD function as defined by
+ tables in the subsections that follow. These subsections group
+ functions according to whether they are:
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 20]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ - required with a job,
+ - optional with a job
+ - required with each document.
+
+ In the tables below, each IPP value is given a name, such as 'h'. If
+ an LPD value uses the IPP value, then the LPD value column contains
+ the IPP name, such as 'h' to denote this. Otherwise, the LPD value
+ column specifies the literal value.
+
+6.1 Required Job Functions
+
+ The mapper SHALL include the following LPD functions with each job,
+ and they SHALL have the specified value. They SHALL be the first
+ functions in the control file and they SHALL be in the order "H" and
+ then "P".
+
+ IPP LPD function
+ name value name value description
+
+ (perhaps in security h H gateway host Originating Host
+ layer)
+ requesting-user-name u P u User identification
+ and in the security
+ layer
+
+ A mapper SHALL sends its own host rather than the client's host,
+ because some LPD systems require that it be the same as the host from
+ which the remove-jobs command comes. A mapper MAY send its own user
+ name as user identification rather than the client user. But in any
+ case, the values sent SHALL be compatible with the LPD remove-jobs
+ operation.
+
+6.2 Optional Job Functions
+
+ The mapper MAY include the following LPD functions with each job.
+ They SHALL have the specified value if they are sent. These
+ functions, if present, SHALL follow the require job functions, and
+ they SHALL precede the required document functions.
+
+ IPP attribute LPD function
+ name value name value description
+
+ job-name j J j Job name for banner
+ page
+ job-sheets 'standard' L u Print banner page
+ job-sheets 'none' omit 'L' function
+
+
+
+
+
+Herriot, et al. Experimental [Page 21]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ Note: 'L' has special meaning when it is omitted. If 'J' is omitted,
+ some undefined behavior occurs with respect to the banner page.
+
+6.3 Required Document Functions
+
+ The mapper SHALL include one set of the following LPD functions with
+ each document, and they SHALL have the specified values. For each
+ document, the order of the functions SHALL be 'f', 'U' and then 'N',
+ where 'f' is replicated once for each copy.
+
+ IPP attribute LPD function
+
+ name value name value description
+
+ document- 'application/octet- f fff Print formatted file
+ format stream' or
+ 'application/PostScript'
+ copies c replicate 'f' 'c'
+ times
+ none U fff Unlink data file
+ document- n N n Name of source file
+ name
+
+ Note: the value 'fff' of the 'f' and 'U' functions is the name of the
+ data file as transferred, e.g. "dfA123woden".
+
+ Note: the mapper SHALL not send the 'o' function
+
+ ISSUE: should we register DVI, troff or ditroff?
+
+ If the mapper receives no "ipp-attribute-fidelitybest-effort" or it
+ has a value of false, then the mapper SHALL reject the job if it
+ specifies attributes or attribute values that are not among those
+ supported in the above tables.
+
+ Below is an example of the minimal control file for a job with three
+ copies of two files 'foo' and 'bar':
+
+ H tiger
+ P jones
+ f dfA123woden
+ f dfA123woden
+ f dfA123woden
+ U dfA123woden
+ N foo
+ f dfB123woden
+ f dfB123woden
+ f dfB123woden
+
+
+
+Herriot, et al. Experimental [Page 22]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+ U dfB123woden
+ N bar
+
+7. Security Considerations
+
+ There are no security issues beyond those covered in the IPP Encoding
+ and Transport document [RFC2565], the IPP model document [RFC2566]
+ and the LPD document [RFC1179].
+
+8. References
+
+ [ipp-iig] Hasting, T., et al., "Internet Printing Protocol/1.0:
+ Implementer's Guide", Work in Progress.
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S., and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1179] McLaughlin, L., "Line Printer Daemon Protocol", RFC 1179,
+ August 1990.
+
+ [RFC2119] Bradner, S. "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2234] D. Crocker et al., "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S., and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 23]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+9. Authors' Addresses
+
+ Robert Herriot (Editor)
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: rherriot@pahv.xerox.com
+
+
+ Norm Jacobs
+ Sun Microsystems Inc.
+ 1430 Owl Ridge Rd.
+ Colorado Springs, CO 80919
+
+ Phone: 719-532-9927
+ Fax: 719-535-0956
+ EMail: Norm.Jacobs@Central.sun.com
+
+
+ Thomas N. Hastings
+ Xerox Corporation
+ 701 S. Aviation Blvd., ESAE-231
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Jay Martin
+ Underscore, Inc.
+ 41-C Sagamore Park Road
+ Hudson, NH 03051-4915
+
+ Phone: 603-889-7000
+ Fax: 603-889-2699
+ EMail: jkm@underscore.com
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 24]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+10. Appendix A: ABNF Syntax for response of Send-queue-state (short)
+
+ The syntax in ABNF for the response to the LPD command 'send-queue-
+ state (long)' is:
+
+ status-response = empty-queue / nonempty-queue
+ empty-queue = "no-entries" LF
+ nonempty-queue = printer-status LF heading LF *(job LF)
+ printer-status = OK-status / error-status
+ OK-status = printer-name SP "ready and printing" LF
+ error-status = < implementation dependent status information >
+ heading = "Rank" 3SP "Owner" 6SP "Job" 13SP "Files"
+ 23SP "Total Size" LF
+ ; the column headings and their values below begin
+ at the columns
+ ; 1, 8, 19, 35 and 63
+ job = rank *SP owner *SP job *SP files *SP total-size "bytes"
+ ; jobs are in order of oldest to newest
+ rank = "active" / "1st" / "2nd" / "3rd" / integer "th"
+ ; job that is printing is "active"
+ ; other values show position in the queue
+ owner = <user name of person who submitted the job>
+ job = 1*3DIGIT ; job-number
+ files = <file name> *( "," <file name>) ; truncated to 24 characters
+ total-size = 1*DIGIT ; combined size in bytes of all documents
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 25]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+11. Appendix B: ABNF Syntax for response of Send-queue-state (long)
+
+ The syntax in ABNF for the response to the LPD command 'send-queue-
+ state (long)' is:
+
+ status-response = empty-queue / nonempty-queue
+ empty-queue = "no-entries" LF
+ nonempty-queue = printer-status LF *job
+ printer-status = OK-status / error-status
+ OK-status = printer-name SP "ready and printing" LF
+ error-status = < implementation dependent status information >
+ job = LF line-1 LF line-2 LF
+ line-1 = owner ":" SP rank 1*SP "[job" job SP host "]"
+ line-2 = file-name 1*SP document-size "bytes"
+ ; jobs are in order of oldest to newest
+ rank = "active" / "1st" / "2nd" / "3rd" / integer "th"
+ ; job that is printing is "active"
+ ; other values show position in the queue
+ owner = <user name of person who submitted the job>
+ job = 1*3DIGIT
+ file-name = [ 1*DIGIT "copies of" SP ] <file name>
+ ; truncated to 24 characters
+ document-size = 1*DIGIT ;size of single copy of the document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 26]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+12. Appendix C: Unsupported LPD functions
+
+ The follow LPD functions have no IPP equivalent. The LPD-to-IPP
+ mapper ignores them and the IPP-to-LPD mapper does not send them.
+
+ LPD command
+ name description
+
+ C Class for banner page
+ I Indent Printing
+ H Host of client
+ M Mail when printed
+ S Symbolic link data
+ T Title for pr
+ W Width of output
+ 1 troff R font
+ 2 troff I font
+ 3 troff B font
+ 4 troff S font
+
+ The follow LPD functions specify document-formats which have no IPP
+ equivalent, unless someone registers them. The LPD-to-IPP mapper
+ rejects jobs that request such a document format, and the IPP-to-LPD
+ mapper does not send them.
+
+ LPD command
+ name description
+
+ c Plot CIF file
+ d Print DVI file
+ g Plot file
+ k reserved for Kerberized clients and servers
+ n Print ditroff output file
+ p Print file with 'pr' format
+ r File to print with FORTRAN carriage control
+ t Print troff output file
+ v Print raster file
+ z reserved for future use with the Palladium
+ print system
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 27]
+
+RFC 2569 Mapping between LPD and IPP Protocols April 1999
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Experimental [Page 28]
+
diff --git a/standards/rfc2595.txt b/standards/rfc2595.txt
new file mode 100644
index 000000000..66897cd6c
--- /dev/null
+++ b/standards/rfc2595.txt
@@ -0,0 +1,843 @@
+
+
+
+
+
+
+Network Working Group C. Newman
+Request for Comments: 2595 Innosoft
+Category: Standards Track June 1999
+
+
+ Using TLS with IMAP, POP3 and ACAP
+
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Motivation
+
+ The TLS protocol (formerly known as SSL) provides a way to secure an
+ application protocol from tampering and eavesdropping. The option of
+ using such security is desirable for IMAP, POP and ACAP due to common
+ connection eavesdropping and hijacking attacks [AUTH]. Although
+ advanced SASL authentication mechanisms can provide a lightweight
+ version of this service, TLS is complimentary to simple
+ authentication-only SASL mechanisms or deployed clear-text password
+ login commands.
+
+ Many sites have a high investment in authentication infrastructure
+ (e.g., a large database of a one-way-function applied to user
+ passwords), so a privacy layer which is not tightly bound to user
+ authentication can protect against network eavesdropping attacks
+ without requiring a new authentication infrastructure and/or forcing
+ all users to change their password. Recognizing that such sites will
+ desire simple password authentication in combination with TLS
+ encryption, this specification defines the PLAIN SASL mechanism for
+ use with protocols which lack a simple password authentication
+ command such as ACAP and SMTP. (Note there is a separate RFC for the
+ STARTTLS command in SMTP [SMTPTLS].)
+
+ There is a strong desire in the IETF to eliminate the transmission of
+ clear-text passwords over unencrypted channels. While SASL can be
+ used for this purpose, TLS provides an additional tool with different
+ deployability characteristics. A server supporting both TLS with
+
+
+
+
+Newman Standards Track [Page 1]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ simple passwords and a challenge/response SASL mechanism is likely to
+ interoperate with a wide variety of clients without resorting to
+ unencrypted clear-text passwords.
+
+ The STARTTLS command rectifies a number of the problems with using a
+ separate port for a "secure" protocol variant. Some of these are
+ mentioned in section 7.
+
+1.1. Conventions Used in this Document
+
+ The key words "REQUIRED", "MUST", "MUST NOT", "SHOULD", "SHOULD NOT",
+ "MAY", and "OPTIONAL" in this document are to be interpreted as
+ described in "Key words for use in RFCs to Indicate Requirement
+ Levels" [KEYWORDS].
+
+ Terms related to authentication are defined in "On Internet
+ Authentication" [AUTH].
+
+ Formal syntax is defined using ABNF [ABNF].
+
+ In examples, "C:" and "S:" indicate lines sent by the client and
+ server respectively.
+
+2. Basic Interoperability and Security Requirements
+
+ The following requirements apply to all implementations of the
+ STARTTLS extension for IMAP, POP3 and ACAP.
+
+2.1. Cipher Suite Requirements
+
+ Implementation of the TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [TLS] cipher
+ suite is REQUIRED. This is important as it assures that any two
+ compliant implementations can be configured to interoperate.
+
+ All other cipher suites are OPTIONAL.
+
+2.2. Privacy Operational Mode Security Requirements
+
+ Both clients and servers SHOULD have a privacy operational mode which
+ refuses authentication unless successful activation of an encryption
+ layer (such as that provided by TLS) occurs prior to or at the time
+ of authentication and which will terminate the connection if that
+ encryption layer is deactivated. Implementations are encouraged to
+ have flexability with respect to the minimal encryption strength or
+ cipher suites permitted. A minimalist approach to this
+ recommendation would be an operational mode where the
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA cipher suite is mandatory prior to
+ permitting authentication.
+
+
+
+Newman Standards Track [Page 2]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ Clients MAY have an operational mode which uses encryption only when
+ it is advertised by the server, but authentication continues
+ regardless. For backwards compatibility, servers SHOULD have an
+ operational mode where only the authentication mechanisms required by
+ the relevant base protocol specification are needed to successfully
+ authenticate.
+
+2.3. Clear-Text Password Requirements
+
+ Clients and servers which implement STARTTLS MUST be configurable to
+ refuse all clear-text login commands or mechanisms (including both
+ standards-track and nonstandard mechanisms) unless an encryption
+ layer of adequate strength is active. Servers which allow
+ unencrypted clear-text logins SHOULD be configurable to refuse
+ clear-text logins both for the entire server, and on a per-user
+ basis.
+
+2.4. Server Identity Check
+
+ During the TLS negotiation, the client MUST check its understanding
+ of the server hostname against the server's identity as presented in
+ the server Certificate message, in order to prevent man-in-the-middle
+ attacks. Matching is performed according to these rules:
+
+ - The client MUST use the server hostname it used to open the
+ connection as the value to compare against the server name as
+ expressed in the server certificate. The client MUST NOT use any
+ form of the server hostname derived from an insecure remote source
+ (e.g., insecure DNS lookup). CNAME canonicalization is not done.
+
+ - If a subjectAltName extension of type dNSName is present in the
+ certificate, it SHOULD be used as the source of the server's
+ identity.
+
+ - Matching is case-insensitive.
+
+ - A "*" wildcard character MAY be used as the left-most name
+ component in the certificate. For example, *.example.com would
+ match a.example.com, foo.example.com, etc. but would not match
+ example.com.
+
+ - If the certificate contains multiple names (e.g. more than one
+ dNSName field), then a match with any one of the fields is
+ considered acceptable.
+
+ If the match fails, the client SHOULD either ask for explicit user
+ confirmation, or terminate the connection and indicate the server's
+ identity is suspect.
+
+
+
+Newman Standards Track [Page 3]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+2.5. TLS Security Policy Check
+
+ Both the client and server MUST check the result of the STARTTLS
+ command and subsequent TLS negotiation to see whether acceptable
+ authentication or privacy was achieved. Ignoring this step
+ completely invalidates using TLS for security. The decision about
+ whether acceptable authentication or privacy was achieved is made
+ locally, is implementation-dependent, and is beyond the scope of this
+ document.
+
+3. IMAP STARTTLS extension
+
+ When the TLS extension is present in IMAP, "STARTTLS" is listed as a
+ capability in response to the CAPABILITY command. This extension
+ adds a single command, "STARTTLS" to the IMAP protocol which is used
+ to begin a TLS negotiation.
+
+3.1. STARTTLS Command
+
+ Arguments: none
+
+ Responses: no specific responses for this command
+
+ Result: OK - begin TLS negotiation
+ BAD - command unknown or arguments invalid
+
+ A TLS negotiation begins immediately after the CRLF at the end of
+ the tagged OK response from the server. Once a client issues a
+ STARTTLS command, it MUST NOT issue further commands until a
+ server response is seen and the TLS negotiation is complete.
+
+ The STARTTLS command is only valid in non-authenticated state.
+ The server remains in non-authenticated state, even if client
+ credentials are supplied during the TLS negotiation. The SASL
+ [SASL] EXTERNAL mechanism MAY be used to authenticate once TLS
+ client credentials are successfully exchanged, but servers
+ supporting the STARTTLS command are not required to support the
+ EXTERNAL mechanism.
+
+ Once TLS has been started, the client MUST discard cached
+ information about server capabilities and SHOULD re-issue the
+ CAPABILITY command. This is necessary to protect against
+ man-in-the-middle attacks which alter the capabilities list prior
+ to STARTTLS. The server MAY advertise different capabilities
+ after STARTTLS.
+
+ The formal syntax for IMAP is amended as follows:
+
+
+
+
+Newman Standards Track [Page 4]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ command_any =/ "STARTTLS"
+
+ Example: C: a001 CAPABILITY
+ S: * CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED
+ S: a001 OK CAPABILITY completed
+ C: a002 STARTTLS
+ S: a002 OK Begin TLS negotiation now
+ <TLS negotiation, further commands are under TLS layer>
+ C: a003 CAPABILITY
+ S: * CAPABILITY IMAP4rev1 AUTH=EXTERNAL
+ S: a003 OK CAPABILITY completed
+ C: a004 LOGIN joe password
+ S: a004 OK LOGIN completed
+
+3.2. IMAP LOGINDISABLED capability
+
+ The current IMAP protocol specification (RFC 2060) requires the
+ implementation of the LOGIN command which uses clear-text passwords.
+ Many sites may choose to disable this command unless encryption is
+ active for security reasons. An IMAP server MAY advertise that the
+ LOGIN command is disabled by including the LOGINDISABLED capability
+ in the capability response. Such a server will respond with a tagged
+ "NO" response to any attempt to use the LOGIN command.
+
+ An IMAP server which implements STARTTLS MUST implement support for
+ the LOGINDISABLED capability on unencrypted connections.
+
+ An IMAP client which complies with this specification MUST NOT issue
+ the LOGIN command if this capability is present.
+
+ This capability is useful to prevent clients compliant with this
+ specification from sending an unencrypted password in an environment
+ subject to passive attacks. It has no impact on an environment
+ subject to active attacks as a man-in-the-middle attacker can remove
+ this capability. Therefore this does not relieve clients of the need
+ to follow the privacy mode recommendation in section 2.2.
+
+ Servers advertising this capability will fail to interoperate with
+ many existing compliant IMAP clients and will be unable to prevent
+ those clients from disclosing the user's password.
+
+4. POP3 STARTTLS extension
+
+ The POP3 STARTTLS extension adds the STLS command to POP3 servers.
+ If this is implemented, the POP3 extension mechanism [POP3EXT] MUST
+ also be implemented to avoid the need for client probing of multiple
+ commands. The capability name "STLS" indicates this command is
+ present and permitted in the current state.
+
+
+
+Newman Standards Track [Page 5]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ STLS
+
+ Arguments: none
+
+ Restrictions:
+ Only permitted in AUTHORIZATION state.
+
+ Discussion:
+ A TLS negotiation begins immediately after the CRLF at the
+ end of the +OK response from the server. A -ERR response
+ MAY result if a security layer is already active. Once a
+ client issues a STLS command, it MUST NOT issue further
+ commands until a server response is seen and the TLS
+ negotiation is complete.
+
+ The STLS command is only permitted in AUTHORIZATION state
+ and the server remains in AUTHORIZATION state, even if
+ client credentials are supplied during the TLS negotiation.
+ The AUTH command [POP-AUTH] with the EXTERNAL mechanism
+ [SASL] MAY be used to authenticate once TLS client
+ credentials are successfully exchanged, but servers
+ supporting the STLS command are not required to support the
+ EXTERNAL mechanism.
+
+ Once TLS has been started, the client MUST discard cached
+ information about server capabilities and SHOULD re-issue
+ the CAPA command. This is necessary to protect against
+ man-in-the-middle attacks which alter the capabilities list
+ prior to STLS. The server MAY advertise different
+ capabilities after STLS.
+
+ Possible Responses:
+ +OK -ERR
+
+ Examples:
+ C: STLS
+ S: +OK Begin TLS negotiation
+ <TLS negotiation, further commands are under TLS layer>
+ ...
+ C: STLS
+ S: -ERR Command not permitted when TLS active
+
+
+
+
+
+
+
+
+
+
+Newman Standards Track [Page 6]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+5. ACAP STARTTLS extension
+
+ When the TLS extension is present in ACAP, "STARTTLS" is listed as a
+ capability in the ACAP greeting. No arguments to this capability are
+ defined at this time. This extension adds a single command,
+ "STARTTLS" to the ACAP protocol which is used to begin a TLS
+ negotiation.
+
+5.1. STARTTLS Command
+
+ Arguments: none
+
+ Responses: no specific responses for this command
+
+ Result: OK - begin TLS negotiation
+ BAD - command unknown or arguments invalid
+
+ A TLS negotiation begins immediately after the CRLF at the end of
+ the tagged OK response from the server. Once a client issues a
+ STARTTLS command, it MUST NOT issue further commands until a
+ server response is seen and the TLS negotiation is complete.
+
+ The STARTTLS command is only valid in non-authenticated state.
+ The server remains in non-authenticated state, even if client
+ credentials are supplied during the TLS negotiation. The SASL
+ [SASL] EXTERNAL mechanism MAY be used to authenticate once TLS
+ client credentials are successfully exchanged, but servers
+ supporting the STARTTLS command are not required to support the
+ EXTERNAL mechanism.
+
+ After the TLS layer is established, the server MUST re-issue an
+ untagged ACAP greeting. This is necessary to protect against
+ man-in-the-middle attacks which alter the capabilities list prior
+ to STARTTLS. The client MUST discard cached capability
+ information and replace it with the information from the new ACAP
+ greeting. The server MAY advertise different capabilities after
+ STARTTLS.
+
+ The formal syntax for ACAP is amended as follows:
+
+ command_any =/ "STARTTLS"
+
+ Example: S: * ACAP (SASL "CRAM-MD5") (STARTTLS)
+ C: a002 STARTTLS
+ S: a002 OK "Begin TLS negotiation now"
+ <TLS negotiation, further commands are under TLS layer>
+ S: * ACAP (SASL "CRAM-MD5" "PLAIN" "EXTERNAL")
+
+
+
+
+Newman Standards Track [Page 7]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+6. PLAIN SASL mechanism
+
+ Clear-text passwords are simple, interoperate with almost all
+ existing operating system authentication databases, and are useful
+ for a smooth transition to a more secure password-based
+ authentication mechanism. The drawback is that they are unacceptable
+ for use over an unencrypted network connection.
+
+ This defines the "PLAIN" SASL mechanism for use with ACAP and other
+ protocols with no clear-text login command. The PLAIN SASL mechanism
+ MUST NOT be advertised or used unless a strong encryption layer (such
+ as the provided by TLS) is active or backwards compatibility dictates
+ otherwise.
+
+ The mechanism consists of a single message from the client to the
+ server. The client sends the authorization identity (identity to
+ login as), followed by a US-ASCII NUL character, followed by the
+ authentication identity (identity whose password will be used),
+ followed by a US-ASCII NUL character, followed by the clear-text
+ password. The client may leave the authorization identity empty to
+ indicate that it is the same as the authentication identity.
+
+ The server will verify the authentication identity and password with
+ the system authentication database and verify that the authentication
+ credentials permit the client to login as the authorization identity.
+ If both steps succeed, the user is logged in.
+
+ The server MAY also use the password to initialize any new
+ authentication database, such as one suitable for CRAM-MD5
+ [CRAM-MD5].
+
+ Non-US-ASCII characters are permitted as long as they are represented
+ in UTF-8 [UTF-8]. Use of non-visible characters or characters which
+ a user may be unable to enter on some keyboards is discouraged.
+
+ The formal grammar for the client message using Augmented BNF [ABNF]
+ follows.
+
+ message = [authorize-id] NUL authenticate-id NUL password
+ authenticate-id = 1*UTF8-SAFE ; MUST accept up to 255 octets
+ authorize-id = 1*UTF8-SAFE ; MUST accept up to 255 octets
+ password = 1*UTF8-SAFE ; MUST accept up to 255 octets
+ NUL = %x00
+ UTF8-SAFE = %x01-09 / %x0B-0C / %x0E-7F / UTF8-2 /
+ UTF8-3 / UTF8-4 / UTF8-5 / UTF8-6
+ UTF8-1 = %x80-BF
+ UTF8-2 = %xC0-DF UTF8-1
+ UTF8-3 = %xE0-EF 2UTF8-1
+
+
+
+Newman Standards Track [Page 8]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ UTF8-4 = %xF0-F7 3UTF8-1
+ UTF8-5 = %xF8-FB 4UTF8-1
+ UTF8-6 = %xFC-FD 5UTF8-1
+
+ Here is an example of how this might be used to initialize a CRAM-MD5
+ authentication database for ACAP:
+
+ Example: S: * ACAP (SASL "CRAM-MD5") (STARTTLS)
+ C: a001 AUTHENTICATE "CRAM-MD5"
+ S: + "<1896.697170952@postoffice.reston.mci.net>"
+ C: "tim b913a602c7eda7a495b4e6e7334d3890"
+ S: a001 NO (TRANSITION-NEEDED)
+ "Please change your password, or use TLS to login"
+ C: a002 STARTTLS
+ S: a002 OK "Begin TLS negotiation now"
+ <TLS negotiation, further commands are under TLS layer>
+ S: * ACAP (SASL "CRAM-MD5" "PLAIN" "EXTERNAL")
+ C: a003 AUTHENTICATE "PLAIN" {21+}
+ C: <NUL>tim<NUL>tanstaaftanstaaf
+ S: a003 OK CRAM-MD5 password initialized
+
+ Note: In this example, <NUL> represents a single ASCII NUL octet.
+
+7. imaps and pop3s ports
+
+ Separate "imaps" and "pop3s" ports were registered for use with SSL.
+ Use of these ports is discouraged in favor of the STARTTLS or STLS
+ commands.
+
+ A number of problems have been observed with separate ports for
+ "secure" variants of protocols. This is an attempt to enumerate some
+ of those problems.
+
+ - Separate ports lead to a separate URL scheme which intrudes into
+ the user interface in inappropriate ways. For example, many web
+ pages use language like "click here if your browser supports SSL."
+ This is a decision the browser is often more capable of making than
+ the user.
+
+ - Separate ports imply a model of either "secure" or "not secure."
+ This can be misleading in a number of ways. First, the "secure"
+ port may not in fact be acceptably secure as an export-crippled
+ cipher suite might be in use. This can mislead users into a false
+ sense of security. Second, the normal port might in fact be
+ secured by using a SASL mechanism which includes a security layer.
+ Thus the separate port distinction makes the complex topic of
+ security policy even more confusing. One common result of this
+ confusion is that firewall administrators are often misled into
+
+
+
+Newman Standards Track [Page 9]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ permitting the "secure" port and blocking the standard port. This
+ could be a poor choice given the common use of SSL with a 40-bit
+ key encryption layer and plain-text password authentication is less
+ secure than strong SASL mechanisms such as GSSAPI with Kerberos 5.
+
+ - Use of separate ports for SSL has caused clients to implement only
+ two security policies: use SSL or don't use SSL. The desirable
+ security policy "use TLS when available" would be cumbersome with
+ the separate port model, but is simple with STARTTLS.
+
+ - Port numbers are a limited resource. While they are not yet in
+ short supply, it is unwise to set a precedent that could double (or
+ worse) the speed of their consumption.
+
+
+8. IANA Considerations
+
+ This constitutes registration of the "STARTTLS" and "LOGINDISABLED"
+ IMAP capabilities as required by section 7.2.1 of RFC 2060 [IMAP].
+
+ The registration for the POP3 "STLS" capability follows:
+
+ CAPA tag: STLS
+ Arguments: none
+ Added commands: STLS
+ Standard commands affected: May enable USER/PASS as a side-effect.
+ CAPA command SHOULD be re-issued after successful completion.
+ Announced states/Valid states: AUTHORIZATION state only.
+ Specification reference: this memo
+
+ The registration for the ACAP "STARTTLS" capability follows:
+
+ Capability name: STARTTLS
+ Capability keyword: STARTTLS
+ Capability arguments: none
+ Published Specification(s): this memo
+ Person and email address for further information:
+ see author's address section below
+
+ The registration for the PLAIN SASL mechanism follows:
+
+ SASL mechanism name: PLAIN
+ Security Considerations: See section 9 of this memo
+ Published specification: this memo
+ Person & email address to contact for further information:
+ see author's address section below
+ Intended usage: COMMON
+ Author/Change controller: see author's address section below
+
+
+
+Newman Standards Track [Page 10]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+9. Security Considerations
+
+ TLS only provides protection for data sent over a network connection.
+ Messages transferred over IMAP or POP3 are still available to server
+ administrators and usually subject to eavesdropping, tampering and
+ forgery when transmitted through SMTP or NNTP. TLS is no substitute
+ for an end-to-end message security mechanism using MIME security
+ multiparts [MIME-SEC].
+
+ A man-in-the-middle attacker can remove STARTTLS from the capability
+ list or generate a failure response to the STARTTLS command. In
+ order to detect such an attack, clients SHOULD warn the user when
+ session privacy is not active and/or be configurable to refuse to
+ proceed without an acceptable level of security.
+
+ A man-in-the-middle attacker can always cause a down-negotiation to
+ the weakest authentication mechanism or cipher suite available. For
+ this reason, implementations SHOULD be configurable to refuse weak
+ mechanisms or cipher suites.
+
+ Any protocol interactions prior to the TLS handshake are performed in
+ the clear and can be modified by a man-in-the-middle attacker. For
+ this reason, clients MUST discard cached information about server
+ capabilities advertised prior to the start of the TLS handshake.
+
+ Clients are encouraged to clearly indicate when the level of
+ encryption active is known to be vulnerable to attack using modern
+ hardware (such as encryption keys with 56 bits of entropy or less).
+
+ The LOGINDISABLED IMAP capability (discussed in section 3.2) only
+ reduces the potential for passive attacks, it provides no protection
+ against active attacks. The responsibility remains with the client
+ to avoid sending a password over a vulnerable channel.
+
+ The PLAIN mechanism relies on the TLS encryption layer for security.
+ When used without TLS, it is vulnerable to a common network
+ eavesdropping attack. Therefore PLAIN MUST NOT be advertised or used
+ unless a suitable TLS encryption layer is active or backwards
+ compatibility dictates otherwise.
+
+ When the PLAIN mechanism is used, the server gains the ability to
+ impersonate the user to all services with the same password
+ regardless of any encryption provided by TLS or other network privacy
+ mechanisms. While many other authentication mechanisms have similar
+ weaknesses, stronger SASL mechanisms such as Kerberos address this
+ issue. Clients are encouraged to have an operational mode where all
+ mechanisms which are likely to reveal the user's password to the
+ server are disabled.
+
+
+
+Newman Standards Track [Page 11]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ The security considerations for TLS apply to STARTTLS and the
+ security considerations for SASL apply to the PLAIN mechanism.
+ Additional security requirements are discussed in section 2.
+
+10. References
+
+ [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [ACAP] Newman, C. and J. Myers, "ACAP -- Application
+ Configuration Access Protocol", RFC 2244, November 1997.
+
+ [AUTH] Haller, N. and R. Atkinson, "On Internet Authentication",
+ RFC 1704, October 1994.
+
+ [CRAM-MD5] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP
+ AUTHorize Extension for Simple Challenge/Response", RFC
+ 2195, September 1997.
+
+ [IMAP] Crispin, M., "Internet Message Access Protocol - Version
+ 4rev1", RFC 2060, December 1996.
+
+ [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [MIME-SEC] Galvin, J., Murphy, S., Crocker, S. and N. Freed,
+ "Security Multiparts for MIME: Multipart/Signed and
+ Multipart/Encrypted", RFC 1847, October 1995.
+
+ [POP3] Myers, J. and M. Rose, "Post Office Protocol - Version 3",
+ STD 53, RFC 1939, May 1996.
+
+ [POP3EXT] Gellens, R., Newman, C. and L. Lundblade, "POP3 Extension
+ Mechanism", RFC 2449, November 1998.
+
+ [POP-AUTH] Myers, J., "POP3 AUTHentication command", RFC 1734,
+ December 1994.
+
+ [SASL] Myers, J., "Simple Authentication and Security Layer
+ (SASL)", RFC 2222, October 1997.
+
+ [SMTPTLS] Hoffman, P., "SMTP Service Extension for Secure SMTP over
+ TLS", RFC 2487, January 1999.
+
+ [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
+ RFC 2246, January 1999.
+
+
+
+
+
+Newman Standards Track [Page 12]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+11. Author's Address
+
+ Chris Newman
+ Innosoft International, Inc.
+ 1050 Lakes Drive
+ West Covina, CA 91790 USA
+
+ EMail: chris.newman@innosoft.com
+
+
+A. Appendix -- Compliance Checklist
+
+ An implementation is not compliant if it fails to satisfy one or more
+ of the MUST requirements for the protocols it implements. An
+ implementation that satisfies all the MUST and all the SHOULD
+ requirements for its protocols is said to be "unconditionally
+ compliant"; one that satisfies all the MUST requirements but not all
+ the SHOULD requirements for its protocols is said to be
+ "conditionally compliant".
+
+ Rules Section
+ ----- -------
+ Mandatory-to-implement Cipher Suite 2.1
+ SHOULD have mode where encryption required 2.2
+ server SHOULD have mode where TLS not required 2.2
+ MUST be configurable to refuse all clear-text login
+ commands or mechanisms 2.3
+ server SHOULD be configurable to refuse clear-text
+ login commands on entire server and on per-user basis 2.3
+ client MUST check server identity 2.4
+ client MUST use hostname used to open connection 2.4
+ client MUST NOT use hostname from insecure remote lookup 2.4
+ client SHOULD support subjectAltName of dNSName type 2.4
+ client SHOULD ask for confirmation or terminate on fail 2.4
+ MUST check result of STARTTLS for acceptable privacy 2.5
+ client MUST NOT issue commands after STARTTLS
+ until server response and negotiation done 3.1,4,5.1
+ client MUST discard cached information 3.1,4,5.1,9
+ client SHOULD re-issue CAPABILITY/CAPA command 3.1,4
+ IMAP server with STARTTLS MUST implement LOGINDISABLED 3.2
+ IMAP client MUST NOT issue LOGIN if LOGINDISABLED 3.2
+ POP server MUST implement POP3 extensions 4
+ ACAP server MUST re-issue ACAP greeting 5.1
+
+
+
+
+Newman Standards Track [Page 13]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+ client SHOULD warn when session privacy not active and/or
+ refuse to proceed without acceptable security level 9
+ SHOULD be configurable to refuse weak mechanisms or
+ cipher suites 9
+
+ The PLAIN mechanism is an optional part of this specification.
+ However if it is implemented the following rules apply:
+
+ Rules Section
+ ----- -------
+ MUST NOT use PLAIN unless strong encryption active
+ or backwards compatibility dictates otherwise 6,9
+ MUST use UTF-8 encoding for characters in PLAIN 6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Newman Standards Track [Page 14]
+
+RFC 2595 Using TLS with IMAP, POP3 and ACAP June 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Newman Standards Track [Page 15]
+
diff --git a/standards/rfc2616.txt b/standards/rfc2616.txt
new file mode 100644
index 000000000..45d7d08b8
--- /dev/null
+++ b/standards/rfc2616.txt
@@ -0,0 +1,9859 @@
+
+
+
+
+
+
+Network Working Group R. Fielding
+Request for Comments: 2616 UC Irvine
+Obsoletes: 2068 J. Gettys
+Category: Standards Track Compaq/W3C
+ J. Mogul
+ Compaq
+ H. Frystyk
+ W3C/MIT
+ L. Masinter
+ Xerox
+ P. Leach
+ Microsoft
+ T. Berners-Lee
+ W3C/MIT
+ June 1999
+
+
+ Hypertext Transfer Protocol -- HTTP/1.1
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. It is a generic, stateless, protocol which can be used for
+ many tasks beyond its use for hypertext, such as name servers and
+ distributed object management systems, through extension of its
+ request methods, error codes and headers [47]. A feature of HTTP is
+ the typing and negotiation of data representation, allowing systems
+ to be built independently of the data being transferred.
+
+ HTTP has been in use by the World-Wide Web global information
+ initiative since 1990. This specification defines the protocol
+ referred to as "HTTP/1.1", and is an update to RFC 2068 [33].
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 1]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+Table of Contents
+
+ 1 Introduction ...................................................7
+ 1.1 Purpose......................................................7
+ 1.2 Requirements .................................................8
+ 1.3 Terminology ..................................................8
+ 1.4 Overall Operation ...........................................12
+ 2 Notational Conventions and Generic Grammar ....................14
+ 2.1 Augmented BNF ...............................................14
+ 2.2 Basic Rules .................................................15
+ 3 Protocol Parameters ...........................................17
+ 3.1 HTTP Version ................................................17
+ 3.2 Uniform Resource Identifiers ................................18
+ 3.2.1 General Syntax ...........................................19
+ 3.2.2 http URL .................................................19
+ 3.2.3 URI Comparison ...........................................20
+ 3.3 Date/Time Formats ...........................................20
+ 3.3.1 Full Date ................................................20
+ 3.3.2 Delta Seconds ............................................21
+ 3.4 Character Sets ..............................................21
+ 3.4.1 Missing Charset ..........................................22
+ 3.5 Content Codings .............................................23
+ 3.6 Transfer Codings ............................................24
+ 3.6.1 Chunked Transfer Coding ..................................25
+ 3.7 Media Types .................................................26
+ 3.7.1 Canonicalization and Text Defaults .......................27
+ 3.7.2 Multipart Types ..........................................27
+ 3.8 Product Tokens ..............................................28
+ 3.9 Quality Values ..............................................29
+ 3.10 Language Tags ...............................................29
+ 3.11 Entity Tags .................................................30
+ 3.12 Range Units .................................................30
+ 4 HTTP Message ..................................................31
+ 4.1 Message Types ...............................................31
+ 4.2 Message Headers .............................................31
+ 4.3 Message Body ................................................32
+ 4.4 Message Length ..............................................33
+ 4.5 General Header Fields .......................................34
+ 5 Request .......................................................35
+ 5.1 Request-Line ................................................35
+ 5.1.1 Method ...................................................36
+ 5.1.2 Request-URI ..............................................36
+ 5.2 The Resource Identified by a Request ........................38
+ 5.3 Request Header Fields .......................................38
+ 6 Response ......................................................39
+ 6.1 Status-Line .................................................39
+ 6.1.1 Status Code and Reason Phrase ............................39
+ 6.2 Response Header Fields ......................................41
+
+
+
+Fielding, et al. Standards Track [Page 2]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 7 Entity ........................................................42
+ 7.1 Entity Header Fields ........................................42
+ 7.2 Entity Body .................................................43
+ 7.2.1 Type .....................................................43
+ 7.2.2 Entity Length ............................................43
+ 8 Connections ...................................................44
+ 8.1 Persistent Connections ......................................44
+ 8.1.1 Purpose ..................................................44
+ 8.1.2 Overall Operation ........................................45
+ 8.1.3 Proxy Servers ............................................46
+ 8.1.4 Practical Considerations .................................46
+ 8.2 Message Transmission Requirements ...........................47
+ 8.2.1 Persistent Connections and Flow Control ..................47
+ 8.2.2 Monitoring Connections for Error Status Messages .........48
+ 8.2.3 Use of the 100 (Continue) Status .........................48
+ 8.2.4 Client Behavior if Server Prematurely Closes Connection ..50
+ 9 Method Definitions ............................................51
+ 9.1 Safe and Idempotent Methods .................................51
+ 9.1.1 Safe Methods .............................................51
+ 9.1.2 Idempotent Methods .......................................51
+ 9.2 OPTIONS .....................................................52
+ 9.3 GET .........................................................53
+ 9.4 HEAD ........................................................54
+ 9.5 POST ........................................................54
+ 9.6 PUT .........................................................55
+ 9.7 DELETE ......................................................56
+ 9.8 TRACE .......................................................56
+ 9.9 CONNECT .....................................................57
+ 10 Status Code Definitions ......................................57
+ 10.1 Informational 1xx ...........................................57
+ 10.1.1 100 Continue .............................................58
+ 10.1.2 101 Switching Protocols ..................................58
+ 10.2 Successful 2xx ..............................................58
+ 10.2.1 200 OK ...................................................58
+ 10.2.2 201 Created ..............................................59
+ 10.2.3 202 Accepted .............................................59
+ 10.2.4 203 Non-Authoritative Information ........................59
+ 10.2.5 204 No Content ...........................................60
+ 10.2.6 205 Reset Content ........................................60
+ 10.2.7 206 Partial Content ......................................60
+ 10.3 Redirection 3xx .............................................61
+ 10.3.1 300 Multiple Choices .....................................61
+ 10.3.2 301 Moved Permanently ....................................62
+ 10.3.3 302 Found ................................................62
+ 10.3.4 303 See Other ............................................63
+ 10.3.5 304 Not Modified .........................................63
+ 10.3.6 305 Use Proxy ............................................64
+ 10.3.7 306 (Unused) .............................................64
+
+
+
+Fielding, et al. Standards Track [Page 3]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 10.3.8 307 Temporary Redirect ...................................65
+ 10.4 Client Error 4xx ............................................65
+ 10.4.1 400 Bad Request .........................................65
+ 10.4.2 401 Unauthorized ........................................66
+ 10.4.3 402 Payment Required ....................................66
+ 10.4.4 403 Forbidden ...........................................66
+ 10.4.5 404 Not Found ...........................................66
+ 10.4.6 405 Method Not Allowed ..................................66
+ 10.4.7 406 Not Acceptable ......................................67
+ 10.4.8 407 Proxy Authentication Required .......................67
+ 10.4.9 408 Request Timeout .....................................67
+ 10.4.10 409 Conflict ............................................67
+ 10.4.11 410 Gone ................................................68
+ 10.4.12 411 Length Required .....................................68
+ 10.4.13 412 Precondition Failed .................................68
+ 10.4.14 413 Request Entity Too Large ............................69
+ 10.4.15 414 Request-URI Too Long ................................69
+ 10.4.16 415 Unsupported Media Type ..............................69
+ 10.4.17 416 Requested Range Not Satisfiable .....................69
+ 10.4.18 417 Expectation Failed ..................................70
+ 10.5 Server Error 5xx ............................................70
+ 10.5.1 500 Internal Server Error ................................70
+ 10.5.2 501 Not Implemented ......................................70
+ 10.5.3 502 Bad Gateway ..........................................70
+ 10.5.4 503 Service Unavailable ..................................70
+ 10.5.5 504 Gateway Timeout ......................................71
+ 10.5.6 505 HTTP Version Not Supported ...........................71
+ 11 Access Authentication ........................................71
+ 12 Content Negotiation ..........................................71
+ 12.1 Server-driven Negotiation ...................................72
+ 12.2 Agent-driven Negotiation ....................................73
+ 12.3 Transparent Negotiation .....................................74
+ 13 Caching in HTTP ..............................................74
+ 13.1.1 Cache Correctness ........................................75
+ 13.1.2 Warnings .................................................76
+ 13.1.3 Cache-control Mechanisms .................................77
+ 13.1.4 Explicit User Agent Warnings .............................78
+ 13.1.5 Exceptions to the Rules and Warnings .....................78
+ 13.1.6 Client-controlled Behavior ...............................79
+ 13.2 Expiration Model ............................................79
+ 13.2.1 Server-Specified Expiration ..............................79
+ 13.2.2 Heuristic Expiration .....................................80
+ 13.2.3 Age Calculations .........................................80
+ 13.2.4 Expiration Calculations ..................................83
+ 13.2.5 Disambiguating Expiration Values .........................84
+ 13.2.6 Disambiguating Multiple Responses ........................84
+ 13.3 Validation Model ............................................85
+ 13.3.1 Last-Modified Dates ......................................86
+
+
+
+Fielding, et al. Standards Track [Page 4]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 13.3.2 Entity Tag Cache Validators ..............................86
+ 13.3.3 Weak and Strong Validators ...............................86
+ 13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates.89
+ 13.3.5 Non-validating Conditionals ..............................90
+ 13.4 Response Cacheability .......................................91
+ 13.5 Constructing Responses From Caches ..........................92
+ 13.5.1 End-to-end and Hop-by-hop Headers ........................92
+ 13.5.2 Non-modifiable Headers ...................................92
+ 13.5.3 Combining Headers ........................................94
+ 13.5.4 Combining Byte Ranges ....................................95
+ 13.6 Caching Negotiated Responses ................................95
+ 13.7 Shared and Non-Shared Caches ................................96
+ 13.8 Errors or Incomplete Response Cache Behavior ................97
+ 13.9 Side Effects of GET and HEAD ................................97
+ 13.10 Invalidation After Updates or Deletions ...................97
+ 13.11 Write-Through Mandatory ...................................98
+ 13.12 Cache Replacement .........................................99
+ 13.13 History Lists .............................................99
+ 14 Header Field Definitions ....................................100
+ 14.1 Accept .....................................................100
+ 14.2 Accept-Charset .............................................102
+ 14.3 Accept-Encoding ............................................102
+ 14.4 Accept-Language ............................................104
+ 14.5 Accept-Ranges ..............................................105
+ 14.6 Age ........................................................106
+ 14.7 Allow ......................................................106
+ 14.8 Authorization ..............................................107
+ 14.9 Cache-Control ..............................................108
+ 14.9.1 What is Cacheable .......................................109
+ 14.9.2 What May be Stored by Caches ............................110
+ 14.9.3 Modifications of the Basic Expiration Mechanism .........111
+ 14.9.4 Cache Revalidation and Reload Controls ..................113
+ 14.9.5 No-Transform Directive ..................................115
+ 14.9.6 Cache Control Extensions ................................116
+ 14.10 Connection ...............................................117
+ 14.11 Content-Encoding .........................................118
+ 14.12 Content-Language .........................................118
+ 14.13 Content-Length ...........................................119
+ 14.14 Content-Location .........................................120
+ 14.15 Content-MD5 ..............................................121
+ 14.16 Content-Range ............................................122
+ 14.17 Content-Type .............................................124
+ 14.18 Date .....................................................124
+ 14.18.1 Clockless Origin Server Operation ......................125
+ 14.19 ETag .....................................................126
+ 14.20 Expect ...................................................126
+ 14.21 Expires ..................................................127
+ 14.22 From .....................................................128
+
+
+
+Fielding, et al. Standards Track [Page 5]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 14.23 Host .....................................................128
+ 14.24 If-Match .................................................129
+ 14.25 If-Modified-Since ........................................130
+ 14.26 If-None-Match ............................................132
+ 14.27 If-Range .................................................133
+ 14.28 If-Unmodified-Since ......................................134
+ 14.29 Last-Modified ............................................134
+ 14.30 Location .................................................135
+ 14.31 Max-Forwards .............................................136
+ 14.32 Pragma ...................................................136
+ 14.33 Proxy-Authenticate .......................................137
+ 14.34 Proxy-Authorization ......................................137
+ 14.35 Range ....................................................138
+ 14.35.1 Byte Ranges ...........................................138
+ 14.35.2 Range Retrieval Requests ..............................139
+ 14.36 Referer ..................................................140
+ 14.37 Retry-After ..............................................141
+ 14.38 Server ...................................................141
+ 14.39 TE .......................................................142
+ 14.40 Trailer ..................................................143
+ 14.41 Transfer-Encoding..........................................143
+ 14.42 Upgrade ..................................................144
+ 14.43 User-Agent ...............................................145
+ 14.44 Vary .....................................................145
+ 14.45 Via ......................................................146
+ 14.46 Warning ..................................................148
+ 14.47 WWW-Authenticate .........................................150
+ 15 Security Considerations .......................................150
+ 15.1 Personal Information....................................151
+ 15.1.1 Abuse of Server Log Information .........................151
+ 15.1.2 Transfer of Sensitive Information .......................151
+ 15.1.3 Encoding Sensitive Information in URI's .................152
+ 15.1.4 Privacy Issues Connected to Accept Headers ..............152
+ 15.2 Attacks Based On File and Path Names .......................153
+ 15.3 DNS Spoofing ...............................................154
+ 15.4 Location Headers and Spoofing ..............................154
+ 15.5 Content-Disposition Issues .................................154
+ 15.6 Authentication Credentials and Idle Clients ................155
+ 15.7 Proxies and Caching ........................................155
+ 15.7.1 Denial of Service Attacks on Proxies....................156
+ 16 Acknowledgments .............................................156
+ 17 References ..................................................158
+ 18 Authors' Addresses ..........................................162
+ 19 Appendices ..................................................164
+ 19.1 Internet Media Type message/http and application/http ......164
+ 19.2 Internet Media Type multipart/byteranges ...................165
+ 19.3 Tolerant Applications ......................................166
+ 19.4 Differences Between HTTP Entities and RFC 2045 Entities ....167
+
+
+
+Fielding, et al. Standards Track [Page 6]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 19.4.1 MIME-Version ............................................167
+ 19.4.2 Conversion to Canonical Form ............................167
+ 19.4.3 Conversion of Date Formats ..............................168
+ 19.4.4 Introduction of Content-Encoding ........................168
+ 19.4.5 No Content-Transfer-Encoding ............................168
+ 19.4.6 Introduction of Transfer-Encoding .......................169
+ 19.4.7 MHTML and Line Length Limitations .......................169
+ 19.5 Additional Features ........................................169
+ 19.5.1 Content-Disposition .....................................170
+ 19.6 Compatibility with Previous Versions .......................170
+ 19.6.1 Changes from HTTP/1.0 ...................................171
+ 19.6.2 Compatibility with HTTP/1.0 Persistent Connections ......172
+ 19.6.3 Changes from RFC 2068 ...................................172
+ 20 Index .......................................................175
+ 21 Full Copyright Statement ....................................176
+
+1 Introduction
+
+1.1 Purpose
+
+ The Hypertext Transfer Protocol (HTTP) is an application-level
+ protocol for distributed, collaborative, hypermedia information
+ systems. HTTP has been in use by the World-Wide Web global
+ information initiative since 1990. The first version of HTTP,
+ referred to as HTTP/0.9, was a simple protocol for raw data transfer
+ across the Internet. HTTP/1.0, as defined by RFC 1945 [6], improved
+ the protocol by allowing messages to be in the format of MIME-like
+ messages, containing metainformation about the data transferred and
+ modifiers on the request/response semantics. However, HTTP/1.0 does
+ not sufficiently take into consideration the effects of hierarchical
+ proxies, caching, the need for persistent connections, or virtual
+ hosts. In addition, the proliferation of incompletely-implemented
+ applications calling themselves "HTTP/1.0" has necessitated a
+ protocol version change in order for two communicating applications
+ to determine each other's true capabilities.
+
+ This specification defines the protocol referred to as "HTTP/1.1".
+ This protocol includes more stringent requirements than HTTP/1.0 in
+ order to ensure reliable implementation of its features.
+
+ Practical information systems require more functionality than simple
+ retrieval, including search, front-end update, and annotation. HTTP
+ allows an open-ended set of methods and headers that indicate the
+ purpose of a request [47]. It builds on the discipline of reference
+ provided by the Uniform Resource Identifier (URI) [3], as a location
+ (URL) [4] or name (URN) [20], for indicating the resource to which a
+
+
+
+
+
+Fielding, et al. Standards Track [Page 7]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ method is to be applied. Messages are passed in a format similar to
+ that used by Internet mail [9] as defined by the Multipurpose
+ Internet Mail Extensions (MIME) [7].
+
+ HTTP is also used as a generic protocol for communication between
+ user agents and proxies/gateways to other Internet systems, including
+ those supported by the SMTP [16], NNTP [13], FTP [18], Gopher [2],
+ and WAIS [10] protocols. In this way, HTTP allows basic hypermedia
+ access to resources available from diverse applications.
+
+1.2 Requirements
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [34].
+
+ An implementation is not compliant if it fails to satisfy one or more
+ of the MUST or REQUIRED level requirements for the protocols it
+ implements. An implementation that satisfies all the MUST or REQUIRED
+ level and all the SHOULD level requirements for its protocols is said
+ to be "unconditionally compliant"; one that satisfies all the MUST
+ level requirements but not all the SHOULD level requirements for its
+ protocols is said to be "conditionally compliant."
+
+1.3 Terminology
+
+ This specification uses a number of terms to refer to the roles
+ played by participants in, and objects of, the HTTP communication.
+
+ connection
+ A transport layer virtual circuit established between two programs
+ for the purpose of communication.
+
+ message
+ The basic unit of HTTP communication, consisting of a structured
+ sequence of octets matching the syntax defined in section 4 and
+ transmitted via the connection.
+
+ request
+ An HTTP request message, as defined in section 5.
+
+ response
+ An HTTP response message, as defined in section 6.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 8]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ resource
+ A network data object or service that can be identified by a URI,
+ as defined in section 3.2. Resources may be available in multiple
+ representations (e.g. multiple languages, data formats, size, and
+ resolutions) or vary in other ways.
+
+ entity
+ The information transferred as the payload of a request or
+ response. An entity consists of metainformation in the form of
+ entity-header fields and content in the form of an entity-body, as
+ described in section 7.
+
+ representation
+ An entity included with a response that is subject to content
+ negotiation, as described in section 12. There may exist multiple
+ representations associated with a particular response status.
+
+ content negotiation
+ The mechanism for selecting the appropriate representation when
+ servicing a request, as described in section 12. The
+ representation of entities in any response can be negotiated
+ (including error responses).
+
+ variant
+ A resource may have one, or more than one, representation(s)
+ associated with it at any given instant. Each of these
+ representations is termed a `varriant'. Use of the term `variant'
+ does not necessarily imply that the resource is subject to content
+ negotiation.
+
+ client
+ A program that establishes connections for the purpose of sending
+ requests.
+
+ user agent
+ The client which initiates a request. These are often browsers,
+ editors, spiders (web-traversing robots), or other end user tools.
+
+ server
+ An application program that accepts connections in order to
+ service requests by sending back responses. Any given program may
+ be capable of being both a client and a server; our use of these
+ terms refers only to the role being performed by the program for a
+ particular connection, rather than to the program's capabilities
+ in general. Likewise, any server may act as an origin server,
+ proxy, gateway, or tunnel, switching behavior based on the nature
+ of each request.
+
+
+
+
+Fielding, et al. Standards Track [Page 9]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ origin server
+ The server on which a given resource resides or is to be created.
+
+ proxy
+ An intermediary program which acts as both a server and a client
+ for the purpose of making requests on behalf of other clients.
+ Requests are serviced internally or by passing them on, with
+ possible translation, to other servers. A proxy MUST implement
+ both the client and server requirements of this specification. A
+ "transparent proxy" is a proxy that does not modify the request or
+ response beyond what is required for proxy authentication and
+ identification. A "non-transparent proxy" is a proxy that modifies
+ the request or response in order to provide some added service to
+ the user agent, such as group annotation services, media type
+ transformation, protocol reduction, or anonymity filtering. Except
+ where either transparent or non-transparent behavior is explicitly
+ stated, the HTTP proxy requirements apply to both types of
+ proxies.
+
+ gateway
+ A server which acts as an intermediary for some other server.
+ Unlike a proxy, a gateway receives requests as if it were the
+ origin server for the requested resource; the requesting client
+ may not be aware that it is communicating with a gateway.
+
+ tunnel
+ An intermediary program which is acting as a blind relay between
+ two connections. Once active, a tunnel is not considered a party
+ to the HTTP communication, though the tunnel may have been
+ initiated by an HTTP request. The tunnel ceases to exist when both
+ ends of the relayed connections are closed.
+
+ cache
+ A program's local store of response messages and the subsystem
+ that controls its message storage, retrieval, and deletion. A
+ cache stores cacheable responses in order to reduce the response
+ time and network bandwidth consumption on future, equivalent
+ requests. Any client or server may include a cache, though a cache
+ cannot be used by a server that is acting as a tunnel.
+
+ cacheable
+ A response is cacheable if a cache is allowed to store a copy of
+ the response message for use in answering subsequent requests. The
+ rules for determining the cacheability of HTTP responses are
+ defined in section 13. Even if a resource is cacheable, there may
+ be additional constraints on whether a cache can use the cached
+ copy for a particular request.
+
+
+
+
+Fielding, et al. Standards Track [Page 10]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ first-hand
+ A response is first-hand if it comes directly and without
+ unnecessary delay from the origin server, perhaps via one or more
+ proxies. A response is also first-hand if its validity has just
+ been checked directly with the origin server.
+
+ explicit expiration time
+ The time at which the origin server intends that an entity should
+ no longer be returned by a cache without further validation.
+
+ heuristic expiration time
+ An expiration time assigned by a cache when no explicit expiration
+ time is available.
+
+ age
+ The age of a response is the time since it was sent by, or
+ successfully validated with, the origin server.
+
+ freshness lifetime
+ The length of time between the generation of a response and its
+ expiration time.
+
+ fresh
+ A response is fresh if its age has not yet exceeded its freshness
+ lifetime.
+
+ stale
+ A response is stale if its age has passed its freshness lifetime.
+
+ semantically transparent
+ A cache behaves in a "semantically transparent" manner, with
+ respect to a particular response, when its use affects neither the
+ requesting client nor the origin server, except to improve
+ performance. When a cache is semantically transparent, the client
+ receives exactly the same response (except for hop-by-hop headers)
+ that it would have received had its request been handled directly
+ by the origin server.
+
+ validator
+ A protocol element (e.g., an entity tag or a Last-Modified time)
+ that is used to find out whether a cache entry is an equivalent
+ copy of an entity.
+
+ upstream/downstream
+ Upstream and downstream describe the flow of a message: all
+ messages flow from upstream to downstream.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 11]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ inbound/outbound
+ Inbound and outbound refer to the request and response paths for
+ messages: "inbound" means "traveling toward the origin server",
+ and "outbound" means "traveling toward the user agent"
+
+1.4 Overall Operation
+
+ The HTTP protocol is a request/response protocol. A client sends a
+ request to the server in the form of a request method, URI, and
+ protocol version, followed by a MIME-like message containing request
+ modifiers, client information, and possible body content over a
+ connection with a server. The server responds with a status line,
+ including the message's protocol version and a success or error code,
+ followed by a MIME-like message containing server information, entity
+ metainformation, and possible entity-body content. The relationship
+ between HTTP and MIME is described in appendix 19.4.
+
+ Most HTTP communication is initiated by a user agent and consists of
+ a request to be applied to a resource on some origin server. In the
+ simplest case, this may be accomplished via a single connection (v)
+ between the user agent (UA) and the origin server (O).
+
+ request chain ------------------------>
+ UA -------------------v------------------- O
+ <----------------------- response chain
+
+ A more complicated situation occurs when one or more intermediaries
+ are present in the request/response chain. There are three common
+ forms of intermediary: proxy, gateway, and tunnel. A proxy is a
+ forwarding agent, receiving requests for a URI in its absolute form,
+ rewriting all or part of the message, and forwarding the reformatted
+ request toward the server identified by the URI. A gateway is a
+ receiving agent, acting as a layer above some other server(s) and, if
+ necessary, translating the requests to the underlying server's
+ protocol. A tunnel acts as a relay point between two connections
+ without changing the messages; tunnels are used when the
+ communication needs to pass through an intermediary (such as a
+ firewall) even when the intermediary cannot understand the contents
+ of the messages.
+
+ request chain -------------------------------------->
+ UA -----v----- A -----v----- B -----v----- C -----v----- O
+ <------------------------------------- response chain
+
+ The figure above shows three intermediaries (A, B, and C) between the
+ user agent and origin server. A request or response message that
+ travels the whole chain will pass through four separate connections.
+ This distinction is important because some HTTP communication options
+
+
+
+Fielding, et al. Standards Track [Page 12]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ may apply only to the connection with the nearest, non-tunnel
+ neighbor, only to the end-points of the chain, or to all connections
+ along the chain. Although the diagram is linear, each participant may
+ be engaged in multiple, simultaneous communications. For example, B
+ may be receiving requests from many clients other than A, and/or
+ forwarding requests to servers other than C, at the same time that it
+ is handling A's request.
+
+ Any party to the communication which is not acting as a tunnel may
+ employ an internal cache for handling requests. The effect of a cache
+ is that the request/response chain is shortened if one of the
+ participants along the chain has a cached response applicable to that
+ request. The following illustrates the resulting chain if B has a
+ cached copy of an earlier response from O (via C) for a request which
+ has not been cached by UA or A.
+
+ request chain ---------->
+ UA -----v----- A -----v----- B - - - - - - C - - - - - - O
+ <--------- response chain
+
+ Not all responses are usefully cacheable, and some requests may
+ contain modifiers which place special requirements on cache behavior.
+ HTTP requirements for cache behavior and cacheable responses are
+ defined in section 13.
+
+ In fact, there are a wide variety of architectures and configurations
+ of caches and proxies currently being experimented with or deployed
+ across the World Wide Web. These systems include national hierarchies
+ of proxy caches to save transoceanic bandwidth, systems that
+ broadcast or multicast cache entries, organizations that distribute
+ subsets of cached data via CD-ROM, and so on. HTTP systems are used
+ in corporate intranets over high-bandwidth links, and for access via
+ PDAs with low-power radio links and intermittent connectivity. The
+ goal of HTTP/1.1 is to support the wide diversity of configurations
+ already deployed while introducing protocol constructs that meet the
+ needs of those who build web applications that require high
+ reliability and, failing that, at least reliable indications of
+ failure.
+
+ HTTP communication usually takes place over TCP/IP connections. The
+ default port is TCP 80 [19], but other ports can be used. This does
+ not preclude HTTP from being implemented on top of any other protocol
+ on the Internet, or on other networks. HTTP only presumes a reliable
+ transport; any protocol that provides such guarantees can be used;
+ the mapping of the HTTP/1.1 request and response structures onto the
+ transport data units of the protocol in question is outside the scope
+ of this specification.
+
+
+
+
+Fielding, et al. Standards Track [Page 13]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ In HTTP/1.0, most implementations used a new connection for each
+ request/response exchange. In HTTP/1.1, a connection may be used for
+ one or more request/response exchanges, although connections may be
+ closed for a variety of reasons (see section 8.1).
+
+2 Notational Conventions and Generic Grammar
+
+2.1 Augmented BNF
+
+ All of the mechanisms specified in this document are described in
+ both prose and an augmented Backus-Naur Form (BNF) similar to that
+ used by RFC 822 [9]. Implementors will need to be familiar with the
+ notation in order to understand this specification. The augmented BNF
+ includes the following constructs:
+
+ name = definition
+ The name of a rule is simply the name itself (without any
+ enclosing "<" and ">") and is separated from its definition by the
+ equal "=" character. White space is only significant in that
+ indentation of continuation lines is used to indicate a rule
+ definition that spans more than one line. Certain basic rules are
+ in uppercase, such as SP, LWS, HT, CRLF, DIGIT, ALPHA, etc. Angle
+ brackets are used within definitions whenever their presence will
+ facilitate discerning the use of rule names.
+
+ "literal"
+ Quotation marks surround literal text. Unless stated otherwise,
+ the text is case-insensitive.
+
+ rule1 | rule2
+ Elements separated by a bar ("|") are alternatives, e.g., "yes |
+ no" will accept yes or no.
+
+ (rule1 rule2)
+ Elements enclosed in parentheses are treated as a single element.
+ Thus, "(elem (foo | bar) elem)" allows the token sequences "elem
+ foo elem" and "elem bar elem".
+
+ *rule
+ The character "*" preceding an element indicates repetition. The
+ full form is "<n>*<m>element" indicating at least <n> and at most
+ <m> occurrences of element. Default values are 0 and infinity so
+ that "*(element)" allows any number, including zero; "1*element"
+ requires at least one; and "1*2element" allows one or two.
+
+ [rule]
+ Square brackets enclose optional elements; "[foo bar]" is
+ equivalent to "*1(foo bar)".
+
+
+
+Fielding, et al. Standards Track [Page 14]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ N rule
+ Specific repetition: "<n>(element)" is equivalent to
+ "<n>*<n>(element)"; that is, exactly <n> occurrences of (element).
+ Thus 2DIGIT is a 2-digit number, and 3ALPHA is a string of three
+ alphabetic characters.
+
+ #rule
+ A construct "#" is defined, similar to "*", for defining lists of
+ elements. The full form is "<n>#<m>element" indicating at least
+ <n> and at most <m> elements, each separated by one or more commas
+ (",") and OPTIONAL linear white space (LWS). This makes the usual
+ form of lists very easy; a rule such as
+ ( *LWS element *( *LWS "," *LWS element ))
+ can be shown as
+ 1#element
+ Wherever this construct is used, null elements are allowed, but do
+ not contribute to the count of elements present. That is,
+ "(element), , (element) " is permitted, but counts as only two
+ elements. Therefore, where at least one element is required, at
+ least one non-null element MUST be present. Default values are 0
+ and infinity so that "#element" allows any number, including zero;
+ "1#element" requires at least one; and "1#2element" allows one or
+ two.
+
+ ; comment
+ A semi-colon, set off some distance to the right of rule text,
+ starts a comment that continues to the end of line. This is a
+ simple way of including useful notes in parallel with the
+ specifications.
+
+ implied *LWS
+ The grammar described by this specification is word-based. Except
+ where noted otherwise, linear white space (LWS) can be included
+ between any two adjacent words (token or quoted-string), and
+ between adjacent words and separators, without changing the
+ interpretation of a field. At least one delimiter (LWS and/or
+
+ separators) MUST exist between any two tokens (for the definition
+ of "token" below), since they would otherwise be interpreted as a
+ single token.
+
+2.2 Basic Rules
+
+ The following rules are used throughout this specification to
+ describe basic parsing constructs. The US-ASCII coded character set
+ is defined by ANSI X3.4-1986 [21].
+
+
+
+
+
+Fielding, et al. Standards Track [Page 15]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ OCTET = <any 8-bit sequence of data>
+ CHAR = <any US-ASCII character (octets 0 - 127)>
+ UPALPHA = <any US-ASCII uppercase letter "A".."Z">
+ LOALPHA = <any US-ASCII lowercase letter "a".."z">
+ ALPHA = UPALPHA | LOALPHA
+ DIGIT = <any US-ASCII digit "0".."9">
+ CTL = <any US-ASCII control character
+ (octets 0 - 31) and DEL (127)>
+ CR = <US-ASCII CR, carriage return (13)>
+ LF = <US-ASCII LF, linefeed (10)>
+ SP = <US-ASCII SP, space (32)>
+ HT = <US-ASCII HT, horizontal-tab (9)>
+ <"> = <US-ASCII double-quote mark (34)>
+
+ HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
+ protocol elements except the entity-body (see appendix 19.3 for
+ tolerant applications). The end-of-line marker within an entity-body
+ is defined by its associated media type, as described in section 3.7.
+
+ CRLF = CR LF
+
+ HTTP/1.1 header field values can be folded onto multiple lines if the
+ continuation line begins with a space or horizontal tab. All linear
+ white space, including folding, has the same semantics as SP. A
+ recipient MAY replace any linear white space with a single SP before
+ interpreting the field value or forwarding the message downstream.
+
+ LWS = [CRLF] 1*( SP | HT )
+
+ The TEXT rule is only used for descriptive field contents and values
+ that are not intended to be interpreted by the message parser. Words
+ of *TEXT MAY contain characters from character sets other than ISO-
+ 8859-1 [22] only when encoded according to the rules of RFC 2047
+ [14].
+
+ TEXT = <any OCTET except CTLs,
+ but including LWS>
+
+ A CRLF is allowed in the definition of TEXT only as part of a header
+ field continuation. It is expected that the folding LWS will be
+ replaced with a single SP before interpretation of the TEXT value.
+
+ Hexadecimal numeric characters are used in several protocol elements.
+
+ HEX = "A" | "B" | "C" | "D" | "E" | "F"
+ | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
+
+
+
+
+
+Fielding, et al. Standards Track [Page 16]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Many HTTP/1.1 header field values consist of words separated by LWS
+ or special characters. These special characters MUST be in a quoted
+ string to be used within a parameter value (as defined in section
+ 3.6).
+
+ token = 1*<any CHAR except CTLs or separators>
+ separators = "(" | ")" | "<" | ">" | "@"
+ | "," | ";" | ":" | "\" | <">
+ | "/" | "[" | "]" | "?" | "="
+ | "{" | "}" | SP | HT
+
+ Comments can be included in some HTTP header fields by surrounding
+ the comment text with parentheses. Comments are only allowed in
+ fields containing "comment" as part of their field value definition.
+ In all other fields, parentheses are considered part of the field
+ value.
+
+ comment = "(" *( ctext | quoted-pair | comment ) ")"
+ ctext = <any TEXT excluding "(" and ")">
+
+ A string of text is parsed as a single word if it is quoted using
+ double-quote marks.
+
+ quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
+ qdtext = <any TEXT except <">>
+
+ The backslash character ("\") MAY be used as a single-character
+ quoting mechanism only within quoted-string and comment constructs.
+
+ quoted-pair = "\" CHAR
+
+3 Protocol Parameters
+
+3.1 HTTP Version
+
+ HTTP uses a "<major>.<minor>" numbering scheme to indicate versions
+ of the protocol. The protocol versioning policy is intended to allow
+ the sender to indicate the format of a message and its capacity for
+ understanding further HTTP communication, rather than the features
+ obtained via that communication. No change is made to the version
+ number for the addition of message components which do not affect
+ communication behavior or which only add to extensible field values.
+ The <minor> number is incremented when the changes made to the
+ protocol add features which do not change the general message parsing
+ algorithm, but which may add to the message semantics and imply
+ additional capabilities of the sender. The <major> number is
+ incremented when the format of a message within the protocol is
+ changed. See RFC 2145 [36] for a fuller explanation.
+
+
+
+Fielding, et al. Standards Track [Page 17]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The version of an HTTP message is indicated by an HTTP-Version field
+ in the first line of the message.
+
+ HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+
+ Note that the major and minor numbers MUST be treated as separate
+ integers and that each MAY be incremented higher than a single digit.
+ Thus, HTTP/2.4 is a lower version than HTTP/2.13, which in turn is
+ lower than HTTP/12.3. Leading zeros MUST be ignored by recipients and
+ MUST NOT be sent.
+
+ An application that sends a request or response message that includes
+ HTTP-Version of "HTTP/1.1" MUST be at least conditionally compliant
+ with this specification. Applications that are at least conditionally
+ compliant with this specification SHOULD use an HTTP-Version of
+ "HTTP/1.1" in their messages, and MUST do so for any message that is
+ not compatible with HTTP/1.0. For more details on when to send
+ specific HTTP-Version values, see RFC 2145 [36].
+
+ The HTTP version of an application is the highest HTTP version for
+ which the application is at least conditionally compliant.
+
+ Proxy and gateway applications need to be careful when forwarding
+ messages in protocol versions different from that of the application.
+ Since the protocol version indicates the protocol capability of the
+ sender, a proxy/gateway MUST NOT send a message with a version
+ indicator which is greater than its actual version. If a higher
+ version request is received, the proxy/gateway MUST either downgrade
+ the request version, or respond with an error, or switch to tunnel
+ behavior.
+
+ Due to interoperability problems with HTTP/1.0 proxies discovered
+ since the publication of RFC 2068[33], caching proxies MUST, gateways
+ MAY, and tunnels MUST NOT upgrade the request to the highest version
+ they support. The proxy/gateway's response to that request MUST be in
+ the same major version as the request.
+
+ Note: Converting between versions of HTTP may involve modification
+ of header fields required or forbidden by the versions involved.
+
+3.2 Uniform Resource Identifiers
+
+ URIs have been known by many names: WWW addresses, Universal Document
+ Identifiers, Universal Resource Identifiers [3], and finally the
+ combination of Uniform Resource Locators (URL) [4] and Names (URN)
+ [20]. As far as HTTP is concerned, Uniform Resource Identifiers are
+ simply formatted strings which identify--via name, location, or any
+ other characteristic--a resource.
+
+
+
+Fielding, et al. Standards Track [Page 18]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+3.2.1 General Syntax
+
+ URIs in HTTP can be represented in absolute form or relative to some
+ known base URI [11], depending upon the context of their use. The two
+ forms are differentiated by the fact that absolute URIs always begin
+ with a scheme name followed by a colon. For definitive information on
+ URL syntax and semantics, see "Uniform Resource Identifiers (URI):
+ Generic Syntax and Semantics," RFC 2396 [42] (which replaces RFCs
+ 1738 [4] and RFC 1808 [11]). This specification adopts the
+ definitions of "URI-reference", "absoluteURI", "relativeURI", "port",
+ "host","abs_path", "rel_path", and "authority" from that
+ specification.
+
+ The HTTP protocol does not place any a priori limit on the length of
+ a URI. Servers MUST be able to handle the URI of any resource they
+ serve, and SHOULD be able to handle URIs of unbounded length if they
+ provide GET-based forms that could generate such URIs. A server
+ SHOULD return 414 (Request-URI Too Long) status if a URI is longer
+ than the server can handle (see section 10.4.15).
+
+ Note: Servers ought to be cautious about depending on URI lengths
+ above 255 bytes, because some older client or proxy
+ implementations might not properly support these lengths.
+
+3.2.2 http URL
+
+ The "http" scheme is used to locate network resources via the HTTP
+ protocol. This section defines the scheme-specific syntax and
+ semantics for http URLs.
+
+ http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+
+ If the port is empty or not given, port 80 is assumed. The semantics
+ are that the identified resource is located at the server listening
+ for TCP connections on that port of that host, and the Request-URI
+ for the resource is abs_path (section 5.1.2). The use of IP addresses
+ in URLs SHOULD be avoided whenever possible (see RFC 1900 [24]). If
+ the abs_path is not present in the URL, it MUST be given as "/" when
+ used as a Request-URI for a resource (section 5.1.2). If a proxy
+ receives a host name which is not a fully qualified domain name, it
+ MAY add its domain to the host name it received. If a proxy receives
+ a fully qualified domain name, the proxy MUST NOT change the host
+ name.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 19]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+3.2.3 URI Comparison
+
+ When comparing two URIs to decide if they match or not, a client
+ SHOULD use a case-sensitive octet-by-octet comparison of the entire
+ URIs, with these exceptions:
+
+ - A port that is empty or not given is equivalent to the default
+ port for that URI-reference;
+
+ - Comparisons of host names MUST be case-insensitive;
+
+ - Comparisons of scheme names MUST be case-insensitive;
+
+ - An empty abs_path is equivalent to an abs_path of "/".
+
+ Characters other than those in the "reserved" and "unsafe" sets (see
+ RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding.
+
+ For example, the following three URIs are equivalent:
+
+ http://abc.com:80/~smith/home.html
+ http://ABC.com/%7Esmith/home.html
+ http://ABC.com:/%7esmith/home.html
+
+3.3 Date/Time Formats
+
+3.3.1 Full Date
+
+ HTTP applications have historically allowed three different formats
+ for the representation of date/time stamps:
+
+ Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+
+ The first format is preferred as an Internet standard and represents
+ a fixed-length subset of that defined by RFC 1123 [8] (an update to
+ RFC 822 [9]). The second format is in common use, but is based on the
+ obsolete RFC 850 [12] date format and lacks a four-digit year.
+ HTTP/1.1 clients and servers that parse the date value MUST accept
+ all three formats (for compatibility with HTTP/1.0), though they MUST
+ only generate the RFC 1123 format for representing HTTP-date values
+ in header fields. See section 19.3 for further information.
+
+ Note: Recipients of date values are encouraged to be robust in
+ accepting date values that may have been sent by non-HTTP
+ applications, as is sometimes the case when retrieving or posting
+ messages via proxies/gateways to SMTP or NNTP.
+
+
+
+Fielding, et al. Standards Track [Page 20]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ All HTTP date/time stamps MUST be represented in Greenwich Mean Time
+ (GMT), without exception. For the purposes of HTTP, GMT is exactly
+ equal to UTC (Coordinated Universal Time). This is indicated in the
+ first two formats by the inclusion of "GMT" as the three-letter
+ abbreviation for time zone, and MUST be assumed when reading the
+ asctime format. HTTP-date is case sensitive and MUST NOT include
+ additional LWS beyond that specifically included as SP in the
+ grammar.
+
+ HTTP-date = rfc1123-date | rfc850-date | asctime-date
+ rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+ rfc850-date = weekday "," SP date2 SP time SP "GMT"
+ asctime-date = wkday SP date3 SP time SP 4DIGIT
+ date1 = 2DIGIT SP month SP 4DIGIT
+ ; day month year (e.g., 02 Jun 1982)
+ date2 = 2DIGIT "-" month "-" 2DIGIT
+ ; day-month-year (e.g., 02-Jun-82)
+ date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ ; month day (e.g., Jun 2)
+ time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ ; 00:00:00 - 23:59:59
+ wkday = "Mon" | "Tue" | "Wed"
+ | "Thu" | "Fri" | "Sat" | "Sun"
+ weekday = "Monday" | "Tuesday" | "Wednesday"
+ | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ month = "Jan" | "Feb" | "Mar" | "Apr"
+ | "May" | "Jun" | "Jul" | "Aug"
+ | "Sep" | "Oct" | "Nov" | "Dec"
+
+ Note: HTTP requirements for the date/time stamp format apply only
+ to their usage within the protocol stream. Clients and servers are
+ not required to use these formats for user presentation, request
+ logging, etc.
+
+3.3.2 Delta Seconds
+
+ Some HTTP header fields allow a time value to be specified as an
+ integer number of seconds, represented in decimal, after the time
+ that the message was received.
+
+ delta-seconds = 1*DIGIT
+
+3.4 Character Sets
+
+ HTTP uses the same definition of the term "character set" as that
+ described for MIME:
+
+
+
+
+
+Fielding, et al. Standards Track [Page 21]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The term "character set" is used in this document to refer to a
+ method used with one or more tables to convert a sequence of octets
+ into a sequence of characters. Note that unconditional conversion in
+ the other direction is not required, in that not all characters may
+ be available in a given character set and a character set may provide
+ more than one sequence of octets to represent a particular character.
+ This definition is intended to allow various kinds of character
+ encoding, from simple single-table mappings such as US-ASCII to
+ complex table switching methods such as those that use ISO-2022's
+ techniques. However, the definition associated with a MIME character
+ set name MUST fully specify the mapping to be performed from octets
+ to characters. In particular, use of external profiling information
+ to determine the exact mapping is not permitted.
+
+ Note: This use of the term "character set" is more commonly
+ referred to as a "character encoding." However, since HTTP and
+ MIME share the same registry, it is important that the terminology
+ also be shared.
+
+ HTTP character sets are identified by case-insensitive tokens. The
+ complete set of tokens is defined by the IANA Character Set registry
+ [19].
+
+ charset = token
+
+ Although HTTP allows an arbitrary token to be used as a charset
+ value, any token that has a predefined value within the IANA
+ Character Set registry [19] MUST represent the character set defined
+ by that registry. Applications SHOULD limit their use of character
+ sets to those defined by the IANA registry.
+
+ Implementors should be aware of IETF character set requirements [38]
+ [41].
+
+3.4.1 Missing Charset
+
+ Some HTTP/1.0 software has interpreted a Content-Type header without
+ charset parameter incorrectly to mean "recipient should guess."
+ Senders wishing to defeat this behavior MAY include a charset
+ parameter even when the charset is ISO-8859-1 and SHOULD do so when
+ it is known that it will not confuse the recipient.
+
+ Unfortunately, some older HTTP/1.0 clients did not deal properly with
+ an explicit charset parameter. HTTP/1.1 recipients MUST respect the
+ charset label provided by the sender; and those user agents that have
+ a provision to "guess" a charset MUST use the charset from the
+
+
+
+
+
+Fielding, et al. Standards Track [Page 22]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ content-type field if they support that charset, rather than the
+ recipient's preference, when initially displaying a document. See
+ section 3.7.1.
+
+3.5 Content Codings
+
+ Content coding values indicate an encoding transformation that has
+ been or can be applied to an entity. Content codings are primarily
+ used to allow a document to be compressed or otherwise usefully
+ transformed without losing the identity of its underlying media type
+ and without loss of information. Frequently, the entity is stored in
+ coded form, transmitted directly, and only decoded by the recipient.
+
+ content-coding = token
+
+ All content-coding values are case-insensitive. HTTP/1.1 uses
+ content-coding values in the Accept-Encoding (section 14.3) and
+ Content-Encoding (section 14.11) header fields. Although the value
+ describes the content-coding, what is more important is that it
+ indicates what decoding mechanism will be required to remove the
+ encoding.
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ content-coding value tokens. Initially, the registry contains the
+ following tokens:
+
+ gzip An encoding format produced by the file compression program
+ "gzip" (GNU zip) as described in RFC 1952 [25]. This format is a
+ Lempel-Ziv coding (LZ77) with a 32 bit CRC.
+
+ compress
+ The encoding format produced by the common UNIX file compression
+ program "compress". This format is an adaptive Lempel-Ziv-Welch
+ coding (LZW).
+
+ Use of program names for the identification of encoding formats
+ is not desirable and is discouraged for future encodings. Their
+ use here is representative of historical practice, not good
+ design. For compatibility with previous implementations of HTTP,
+ applications SHOULD consider "x-gzip" and "x-compress" to be
+ equivalent to "gzip" and "compress" respectively.
+
+ deflate
+ The "zlib" format defined in RFC 1950 [31] in combination with
+ the "deflate" compression mechanism described in RFC 1951 [29].
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 23]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ identity
+ The default (identity) encoding; the use of no transformation
+ whatsoever. This content-coding is used only in the Accept-
+ Encoding header, and SHOULD NOT be used in the Content-Encoding
+ header.
+
+ New content-coding value tokens SHOULD be registered; to allow
+ interoperability between clients and servers, specifications of the
+ content coding algorithms needed to implement a new value SHOULD be
+ publicly available and adequate for independent implementation, and
+ conform to the purpose of content coding defined in this section.
+
+3.6 Transfer Codings
+
+ Transfer-coding values are used to indicate an encoding
+ transformation that has been, can be, or may need to be applied to an
+ entity-body in order to ensure "safe transport" through the network.
+ This differs from a content coding in that the transfer-coding is a
+ property of the message, not of the original entity.
+
+ transfer-coding = "chunked" | transfer-extension
+ transfer-extension = token *( ";" parameter )
+
+ Parameters are in the form of attribute/value pairs.
+
+ parameter = attribute "=" value
+ attribute = token
+ value = token | quoted-string
+
+ All transfer-coding values are case-insensitive. HTTP/1.1 uses
+ transfer-coding values in the TE header field (section 14.39) and in
+ the Transfer-Encoding header field (section 14.41).
+
+ Whenever a transfer-coding is applied to a message-body, the set of
+ transfer-codings MUST include "chunked", unless the message is
+ terminated by closing the connection. When the "chunked" transfer-
+ coding is used, it MUST be the last transfer-coding applied to the
+ message-body. The "chunked" transfer-coding MUST NOT be applied more
+ than once to a message-body. These rules allow the recipient to
+ determine the transfer-length of the message (section 4.4).
+
+ Transfer-codings are analogous to the Content-Transfer-Encoding
+ values of MIME [7], which were designed to enable safe transport of
+ binary data over a 7-bit transport service. However, safe transport
+ has a different focus for an 8bit-clean transfer protocol. In HTTP,
+ the only unsafe characteristic of message-bodies is the difficulty in
+ determining the exact body length (section 7.2.2), or the desire to
+ encrypt data over a shared transport.
+
+
+
+Fielding, et al. Standards Track [Page 24]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The Internet Assigned Numbers Authority (IANA) acts as a registry for
+ transfer-coding value tokens. Initially, the registry contains the
+ following tokens: "chunked" (section 3.6.1), "identity" (section
+ 3.6.2), "gzip" (section 3.5), "compress" (section 3.5), and "deflate"
+ (section 3.5).
+
+ New transfer-coding value tokens SHOULD be registered in the same way
+ as new content-coding value tokens (section 3.5).
+
+ A server which receives an entity-body with a transfer-coding it does
+ not understand SHOULD return 501 (Unimplemented), and close the
+ connection. A server MUST NOT send transfer-codings to an HTTP/1.0
+ client.
+
+3.6.1 Chunked Transfer Coding
+
+ The chunked encoding modifies the body of a message in order to
+ transfer it as a series of chunks, each with its own size indicator,
+ followed by an OPTIONAL trailer containing entity-header fields. This
+ allows dynamically produced content to be transferred along with the
+ information necessary for the recipient to verify that it has
+ received the full message.
+
+ Chunked-Body = *chunk
+ last-chunk
+ trailer
+ CRLF
+
+ chunk = chunk-size [ chunk-extension ] CRLF
+ chunk-data CRLF
+ chunk-size = 1*HEX
+ last-chunk = 1*("0") [ chunk-extension ] CRLF
+
+ chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
+ chunk-ext-name = token
+ chunk-ext-val = token | quoted-string
+ chunk-data = chunk-size(OCTET)
+ trailer = *(entity-header CRLF)
+
+ The chunk-size field is a string of hex digits indicating the size of
+ the chunk. The chunked encoding is ended by any chunk whose size is
+ zero, followed by the trailer, which is terminated by an empty line.
+
+ The trailer allows the sender to include additional HTTP header
+ fields at the end of the message. The Trailer header field can be
+ used to indicate which header fields are included in a trailer (see
+ section 14.40).
+
+
+
+
+Fielding, et al. Standards Track [Page 25]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ A server using chunked transfer-coding in a response MUST NOT use the
+ trailer for any header fields unless at least one of the following is
+ true:
+
+ a)the request included a TE header field that indicates "trailers" is
+ acceptable in the transfer-coding of the response, as described in
+ section 14.39; or,
+
+ b)the server is the origin server for the response, the trailer
+ fields consist entirely of optional metadata, and the recipient
+ could use the message (in a manner acceptable to the origin server)
+ without receiving this metadata. In other words, the origin server
+ is willing to accept the possibility that the trailer fields might
+ be silently discarded along the path to the client.
+
+ This requirement prevents an interoperability failure when the
+ message is being received by an HTTP/1.1 (or later) proxy and
+ forwarded to an HTTP/1.0 recipient. It avoids a situation where
+ compliance with the protocol would have necessitated a possibly
+ infinite buffer on the proxy.
+
+ An example process for decoding a Chunked-Body is presented in
+ appendix 19.4.6.
+
+ All HTTP/1.1 applications MUST be able to receive and decode the
+ "chunked" transfer-coding, and MUST ignore chunk-extension extensions
+ they do not understand.
+
+3.7 Media Types
+
+ HTTP uses Internet Media Types [17] in the Content-Type (section
+ 14.17) and Accept (section 14.1) header fields in order to provide
+ open and extensible data typing and type negotiation.
+
+ media-type = type "/" subtype *( ";" parameter )
+ type = token
+ subtype = token
+
+ Parameters MAY follow the type/subtype in the form of attribute/value
+ pairs (as defined in section 3.6).
+
+ The type, subtype, and parameter attribute names are case-
+ insensitive. Parameter values might or might not be case-sensitive,
+ depending on the semantics of the parameter name. Linear white space
+ (LWS) MUST NOT be used between the type and subtype, nor between an
+ attribute and its value. The presence or absence of a parameter might
+ be significant to the processing of a media-type, depending on its
+ definition within the media type registry.
+
+
+
+Fielding, et al. Standards Track [Page 26]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Note that some older HTTP applications do not recognize media type
+ parameters. When sending data to older HTTP applications,
+ implementations SHOULD only use media type parameters when they are
+ required by that type/subtype definition.
+
+ Media-type values are registered with the Internet Assigned Number
+ Authority (IANA [19]). The media type registration process is
+ outlined in RFC 1590 [17]. Use of non-registered media types is
+ discouraged.
+
+3.7.1 Canonicalization and Text Defaults
+
+ Internet media types are registered with a canonical form. An
+ entity-body transferred via HTTP messages MUST be represented in the
+ appropriate canonical form prior to its transmission except for
+ "text" types, as defined in the next paragraph.
+
+ When in canonical form, media subtypes of the "text" type use CRLF as
+ the text line break. HTTP relaxes this requirement and allows the
+ transport of text media with plain CR or LF alone representing a line
+ break when it is done consistently for an entire entity-body. HTTP
+ applications MUST accept CRLF, bare CR, and bare LF as being
+ representative of a line break in text media received via HTTP. In
+ addition, if the text is represented in a character set that does not
+ use octets 13 and 10 for CR and LF respectively, as is the case for
+ some multi-byte character sets, HTTP allows the use of whatever octet
+ sequences are defined by that character set to represent the
+ equivalent of CR and LF for line breaks. This flexibility regarding
+ line breaks applies only to text media in the entity-body; a bare CR
+ or LF MUST NOT be substituted for CRLF within any of the HTTP control
+ structures (such as header fields and multipart boundaries).
+
+ If an entity-body is encoded with a content-coding, the underlying
+ data MUST be in a form defined above prior to being encoded.
+
+ The "charset" parameter is used with some media types to define the
+ character set (section 3.4) of the data. When no explicit charset
+ parameter is provided by the sender, media subtypes of the "text"
+ type are defined to have a default charset value of "ISO-8859-1" when
+ received via HTTP. Data in character sets other than "ISO-8859-1" or
+ its subsets MUST be labeled with an appropriate charset value. See
+ section 3.4.1 for compatibility problems.
+
+3.7.2 Multipart Types
+
+ MIME provides for a number of "multipart" types -- encapsulations of
+ one or more entities within a single message-body. All multipart
+ types share a common syntax, as defined in section 5.1.1 of RFC 2046
+
+
+
+Fielding, et al. Standards Track [Page 27]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ [40], and MUST include a boundary parameter as part of the media type
+ value. The message body is itself a protocol element and MUST
+ therefore use only CRLF to represent line breaks between body-parts.
+ Unlike in RFC 2046, the epilogue of any multipart message MUST be
+ empty; HTTP applications MUST NOT transmit the epilogue (even if the
+ original multipart contains an epilogue). These restrictions exist in
+ order to preserve the self-delimiting nature of a multipart message-
+ body, wherein the "end" of the message-body is indicated by the
+ ending multipart boundary.
+
+ In general, HTTP treats a multipart message-body no differently than
+ any other media type: strictly as payload. The one exception is the
+ "multipart/byteranges" type (appendix 19.2) when it appears in a 206
+ (Partial Content) response, which will be interpreted by some HTTP
+ caching mechanisms as described in sections 13.5.4 and 14.16. In all
+ other cases, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ The MIME header fields within each body-part of a multipart message-
+ body do not have any significance to HTTP beyond that defined by
+ their MIME semantics.
+
+ In general, an HTTP user agent SHOULD follow the same or similar
+ behavior as a MIME user agent would upon receipt of a multipart type.
+ If an application receives an unrecognized multipart subtype, the
+ application MUST treat it as being equivalent to "multipart/mixed".
+
+ Note: The "multipart/form-data" type has been specifically defined
+ for carrying form data suitable for processing via the POST
+ request method, as described in RFC 1867 [15].
+
+3.8 Product Tokens
+
+ Product tokens are used to allow communicating applications to
+ identify themselves by software name and version. Most fields using
+ product tokens also allow sub-products which form a significant part
+ of the application to be listed, separated by white space. By
+ convention, the products are listed in order of their significance
+ for identifying the application.
+
+ product = token ["/" product-version]
+ product-version = token
+
+ Examples:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+ Server: Apache/0.8.4
+
+
+
+
+
+Fielding, et al. Standards Track [Page 28]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Product tokens SHOULD be short and to the point. They MUST NOT be
+ used for advertising or other non-essential information. Although any
+ token character MAY appear in a product-version, this token SHOULD
+ only be used for a version identifier (i.e., successive versions of
+ the same product SHOULD only differ in the product-version portion of
+ the product value).
+
+3.9 Quality Values
+
+ HTTP content negotiation (section 12) uses short "floating point"
+ numbers to indicate the relative importance ("weight") of various
+ negotiable parameters. A weight is normalized to a real number in
+ the range 0 through 1, where 0 is the minimum and 1 the maximum
+ value. If a parameter has a quality value of 0, then content with
+ this parameter is `not acceptable' for the client. HTTP/1.1
+ applications MUST NOT generate more than three digits after the
+ decimal point. User configuration of these values SHOULD also be
+ limited in this fashion.
+
+ qvalue = ( "0" [ "." 0*3DIGIT ] )
+ | ( "1" [ "." 0*3("0") ] )
+
+ "Quality values" is a misnomer, since these values merely represent
+ relative degradation in desired quality.
+
+3.10 Language Tags
+
+ A language tag identifies a natural language spoken, written, or
+ otherwise conveyed by human beings for communication of information
+ to other human beings. Computer languages are explicitly excluded.
+ HTTP uses language tags within the Accept-Language and Content-
+ Language fields.
+
+ The syntax and registry of HTTP language tags is the same as that
+ defined by RFC 1766 [1]. In summary, a language tag is composed of 1
+ or more parts: A primary language tag and a possibly empty series of
+ subtags:
+
+ language-tag = primary-tag *( "-" subtag )
+ primary-tag = 1*8ALPHA
+ subtag = 1*8ALPHA
+
+ White space is not allowed within the tag and all tags are case-
+ insensitive. The name space of language tags is administered by the
+ IANA. Example tags include:
+
+ en, en-US, en-cockney, i-cherokee, x-pig-latin
+
+
+
+
+Fielding, et al. Standards Track [Page 29]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ where any two-letter primary-tag is an ISO-639 language abbreviation
+ and any two-letter initial subtag is an ISO-3166 country code. (The
+ last three tags above are not registered tags; all but the last are
+ examples of tags which could be registered in future.)
+
+3.11 Entity Tags
+
+ Entity tags are used for comparing two or more entities from the same
+ requested resource. HTTP/1.1 uses entity tags in the ETag (section
+ 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and
+ If-Range (section 14.27) header fields. The definition of how they
+ are used and compared as cache validators is in section 13.3.3. An
+ entity tag consists of an opaque quoted string, possibly prefixed by
+ a weakness indicator.
+
+ entity-tag = [ weak ] opaque-tag
+ weak = "W/"
+ opaque-tag = quoted-string
+
+ A "strong entity tag" MAY be shared by two entities of a resource
+ only if they are equivalent by octet equality.
+
+ A "weak entity tag," indicated by the "W/" prefix, MAY be shared by
+ two entities of a resource only if the entities are equivalent and
+ could be substituted for each other with no significant change in
+ semantics. A weak entity tag can only be used for weak comparison.
+
+ An entity tag MUST be unique across all versions of all entities
+ associated with a particular resource. A given entity tag value MAY
+ be used for entities obtained by requests on different URIs. The use
+ of the same entity tag value in conjunction with entities obtained by
+ requests on different URIs does not imply the equivalence of those
+ entities.
+
+3.12 Range Units
+
+ HTTP/1.1 allows a client to request that only part (a range of) the
+ response entity be included within the response. HTTP/1.1 uses range
+ units in the Range (section 14.35) and Content-Range (section 14.16)
+ header fields. An entity can be broken down into subranges according
+ to various structural units.
+
+ range-unit = bytes-unit | other-range-unit
+ bytes-unit = "bytes"
+ other-range-unit = token
+
+ The only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1
+ implementations MAY ignore ranges specified using other units.
+
+
+
+Fielding, et al. Standards Track [Page 30]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ HTTP/1.1 has been designed to allow implementations of applications
+ that do not depend on knowledge of ranges.
+
+4 HTTP Message
+
+4.1 Message Types
+
+ HTTP messages consist of requests from client to server and responses
+ from server to client.
+
+ HTTP-message = Request | Response ; HTTP/1.1 messages
+
+ Request (section 5) and Response (section 6) messages use the generic
+ message format of RFC 822 [9] for transferring entities (the payload
+ of the message). Both types of message consist of a start-line, zero
+ or more header fields (also known as "headers"), an empty line (i.e.,
+ a line with nothing preceding the CRLF) indicating the end of the
+ header fields, and possibly a message-body.
+
+ generic-message = start-line
+ *(message-header CRLF)
+ CRLF
+ [ message-body ]
+ start-line = Request-Line | Status-Line
+
+ In the interest of robustness, servers SHOULD ignore any empty
+ line(s) received where a Request-Line is expected. In other words, if
+ the server is reading the protocol stream at the beginning of a
+ message and receives a CRLF first, it should ignore the CRLF.
+
+ Certain buggy HTTP/1.0 client implementations generate extra CRLF's
+ after a POST request. To restate what is explicitly forbidden by the
+ BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an
+ extra CRLF.
+
+4.2 Message Headers
+
+ HTTP header fields, which include general-header (section 4.5),
+ request-header (section 5.3), response-header (section 6.2), and
+ entity-header (section 7.1) fields, follow the same generic format as
+ that given in Section 3.1 of RFC 822 [9]. Each header field consists
+ of a name followed by a colon (":") and the field value. Field names
+ are case-insensitive. The field value MAY be preceded by any amount
+ of LWS, though a single SP is preferred. Header fields can be
+ extended over multiple lines by preceding each extra line with at
+ least one SP or HT. Applications ought to follow "common form", where
+ one is known or indicated, when generating HTTP constructs, since
+ there might exist some implementations that fail to accept anything
+
+
+
+Fielding, et al. Standards Track [Page 31]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ beyond the common forms.
+
+ message-header = field-name ":" [ field-value ]
+ field-name = token
+ field-value = *( field-content | LWS )
+ field-content = <the OCTETs making up the field-value
+ and consisting of either *TEXT or combinations
+ of token, separators, and quoted-string>
+
+ The field-content does not include any leading or trailing LWS:
+ linear white space occurring before the first non-whitespace
+ character of the field-value or after the last non-whitespace
+ character of the field-value. Such leading or trailing LWS MAY be
+ removed without changing the semantics of the field value. Any LWS
+ that occurs between field-content MAY be replaced with a single SP
+ before interpreting the field value or forwarding the message
+ downstream.
+
+ The order in which header fields with differing field names are
+ received is not significant. However, it is "good practice" to send
+ general-header fields first, followed by request-header or response-
+ header fields, and ending with the entity-header fields.
+
+ Multiple message-header fields with the same field-name MAY be
+ present in a message if and only if the entire field-value for that
+ header field is defined as a comma-separated list [i.e., #(values)].
+ It MUST be possible to combine the multiple header fields into one
+ "field-name: field-value" pair, without changing the semantics of the
+ message, by appending each subsequent field-value to the first, each
+ separated by a comma. The order in which header fields with the same
+ field-name are received is therefore significant to the
+ interpretation of the combined field value, and thus a proxy MUST NOT
+ change the order of these field values when a message is forwarded.
+
+4.3 Message Body
+
+ The message-body (if any) of an HTTP message is used to carry the
+ entity-body associated with the request or response. The message-body
+ differs from the entity-body only when a transfer-coding has been
+ applied, as indicated by the Transfer-Encoding header field (section
+ 14.41).
+
+ message-body = entity-body
+ | <entity-body encoded as per Transfer-Encoding>
+
+ Transfer-Encoding MUST be used to indicate any transfer-codings
+ applied by an application to ensure safe and proper transfer of the
+ message. Transfer-Encoding is a property of the message, not of the
+
+
+
+Fielding, et al. Standards Track [Page 32]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ entity, and thus MAY be added or removed by any application along the
+ request/response chain. (However, section 3.6 places restrictions on
+ when certain transfer-codings may be used.)
+
+ The rules for when a message-body is allowed in a message differ for
+ requests and responses.
+
+ The presence of a message-body in a request is signaled by the
+ inclusion of a Content-Length or Transfer-Encoding header field in
+ the request's message-headers. A message-body MUST NOT be included in
+ a request if the specification of the request method (section 5.1.1)
+ does not allow sending an entity-body in requests. A server SHOULD
+ read and forward a message-body on any request; if the request method
+ does not include defined semantics for an entity-body, then the
+ message-body SHOULD be ignored when handling the request.
+
+ For response messages, whether or not a message-body is included with
+ a message is dependent on both the request method and the response
+ status code (section 6.1.1). All responses to the HEAD request method
+ MUST NOT include a message-body, even though the presence of entity-
+ header fields might lead one to believe they do. All 1xx
+ (informational), 204 (no content), and 304 (not modified) responses
+ MUST NOT include a message-body. All other responses do include a
+ message-body, although it MAY be of zero length.
+
+4.4 Message Length
+
+ The transfer-length of a message is the length of the message-body as
+ it appears in the message; that is, after any transfer-codings have
+ been applied. When a message-body is included with a message, the
+ transfer-length of that body is determined by one of the following
+ (in order of precedence):
+
+ 1.Any response message which "MUST NOT" include a message-body (such
+ as the 1xx, 204, and 304 responses and any response to a HEAD
+ request) is always terminated by the first empty line after the
+ header fields, regardless of the entity-header fields present in
+ the message.
+
+ 2.If a Transfer-Encoding header field (section 14.41) is present and
+ has any value other than "identity", then the transfer-length is
+ defined by use of the "chunked" transfer-coding (section 3.6),
+ unless the message is terminated by closing the connection.
+
+ 3.If a Content-Length header field (section 14.13) is present, its
+ decimal value in OCTETs represents both the entity-length and the
+ transfer-length. The Content-Length header field MUST NOT be sent
+ if these two lengths are different (i.e., if a Transfer-Encoding
+
+
+
+Fielding, et al. Standards Track [Page 33]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ header field is present). If a message is received with both a
+ Transfer-Encoding header field and a Content-Length header field,
+ the latter MUST be ignored.
+
+ 4.If the message uses the media type "multipart/byteranges", and the
+ ransfer-length is not otherwise specified, then this self-
+ elimiting media type defines the transfer-length. This media type
+ UST NOT be used unless the sender knows that the recipient can arse
+ it; the presence in a request of a Range header with ultiple byte-
+ range specifiers from a 1.1 client implies that the lient can parse
+ multipart/byteranges responses.
+
+ A range header might be forwarded by a 1.0 proxy that does not
+ understand multipart/byteranges; in this case the server MUST
+ delimit the message using methods defined in items 1,3 or 5 of
+ this section.
+
+ 5.By the server closing the connection. (Closing the connection
+ cannot be used to indicate the end of a request body, since that
+ would leave no possibility for the server to send back a response.)
+
+ For compatibility with HTTP/1.0 applications, HTTP/1.1 requests
+ containing a message-body MUST include a valid Content-Length header
+ field unless the server is known to be HTTP/1.1 compliant. If a
+ request contains a message-body and a Content-Length is not given,
+ the server SHOULD respond with 400 (bad request) if it cannot
+ determine the length of the message, or with 411 (length required) if
+ it wishes to insist on receiving a valid Content-Length.
+
+ All HTTP/1.1 applications that receive entities MUST accept the
+ "chunked" transfer-coding (section 3.6), thus allowing this mechanism
+ to be used for messages when the message length cannot be determined
+ in advance.
+
+ Messages MUST NOT include both a Content-Length header field and a
+ non-identity transfer-coding. If the message does include a non-
+ identity transfer-coding, the Content-Length MUST be ignored.
+
+ When a Content-Length is given in a message where a message-body is
+ allowed, its field value MUST exactly match the number of OCTETs in
+ the message-body. HTTP/1.1 user agents MUST notify the user when an
+ invalid length is received and detected.
+
+4.5 General Header Fields
+
+ There are a few header fields which have general applicability for
+ both request and response messages, but which do not apply to the
+ entity being transferred. These header fields apply only to the
+
+
+
+Fielding, et al. Standards Track [Page 34]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ message being transmitted.
+
+ general-header = Cache-Control ; Section 14.9
+ | Connection ; Section 14.10
+ | Date ; Section 14.18
+ | Pragma ; Section 14.32
+ | Trailer ; Section 14.40
+ | Transfer-Encoding ; Section 14.41
+ | Upgrade ; Section 14.42
+ | Via ; Section 14.45
+ | Warning ; Section 14.46
+
+ General-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields may be given the semantics of general
+ header fields if all parties in the communication recognize them to
+ be general-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+5 Request
+
+ A request message from a client to a server includes, within the
+ first line of that message, the method to be applied to the resource,
+ the identifier of the resource, and the protocol version in use.
+
+ Request = Request-Line ; Section 5.1
+ *(( general-header ; Section 4.5
+ | request-header ; Section 5.3
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 4.3
+
+5.1 Request-Line
+
+ The Request-Line begins with a method token, followed by the
+ Request-URI and the protocol version, and ending with CRLF. The
+ elements are separated by SP characters. No CR or LF is allowed
+ except in the final CRLF sequence.
+
+ Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 35]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+5.1.1 Method
+
+ The Method token indicates the method to be performed on the
+ resource identified by the Request-URI. The method is case-sensitive.
+
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+
+ The list of methods allowed by a resource can be specified in an
+ Allow header field (section 14.7). The return code of the response
+ always notifies the client whether a method is currently allowed on a
+ resource, since the set of allowed methods can change dynamically. An
+ origin server SHOULD return the status code 405 (Method Not Allowed)
+ if the method is known by the origin server but not allowed for the
+ requested resource, and 501 (Not Implemented) if the method is
+ unrecognized or not implemented by the origin server. The methods GET
+ and HEAD MUST be supported by all general-purpose servers. All other
+ methods are OPTIONAL; however, if the above methods are implemented,
+ they MUST be implemented with the same semantics as those specified
+ in section 9.
+
+5.1.2 Request-URI
+
+ The Request-URI is a Uniform Resource Identifier (section 3.2) and
+ identifies the resource upon which to apply the request.
+
+ Request-URI = "*" | absoluteURI | abs_path | authority
+
+ The four options for Request-URI are dependent on the nature of the
+ request. The asterisk "*" means that the request does not apply to a
+ particular resource, but to the server itself, and is only allowed
+ when the method used does not necessarily apply to a resource. One
+ example would be
+
+ OPTIONS * HTTP/1.1
+
+ The absoluteURI form is REQUIRED when the request is being made to a
+ proxy. The proxy is requested to forward the request or service it
+ from a valid cache, and return the response. Note that the proxy MAY
+ forward the request on to another proxy or directly to the server
+
+
+
+Fielding, et al. Standards Track [Page 36]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ specified by the absoluteURI. In order to avoid request loops, a
+ proxy MUST be able to recognize all of its server names, including
+ any aliases, local variations, and the numeric IP address. An example
+ Request-Line would be:
+
+ GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
+
+ To allow for transition to absoluteURIs in all requests in future
+ versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI
+ form in requests, even though HTTP/1.1 clients will only generate
+ them in requests to proxies.
+
+ The authority form is only used by the CONNECT method (section 9.9).
+
+ The most common form of Request-URI is that used to identify a
+ resource on an origin server or gateway. In this case the absolute
+ path of the URI MUST be transmitted (see section 3.2.1, abs_path) as
+ the Request-URI, and the network location of the URI (authority) MUST
+ be transmitted in a Host header field. For example, a client wishing
+ to retrieve the resource above directly from the origin server would
+ create a TCP connection to port 80 of the host "www.w3.org" and send
+ the lines:
+
+ GET /pub/WWW/TheProject.html HTTP/1.1
+ Host: www.w3.org
+
+ followed by the remainder of the Request. Note that the absolute path
+ cannot be empty; if none is present in the original URI, it MUST be
+ given as "/" (the server root).
+
+ The Request-URI is transmitted in the format specified in section
+ 3.2.1. If the Request-URI is encoded using the "% HEX HEX" encoding
+ [42], the origin server MUST decode the Request-URI in order to
+ properly interpret the request. Servers SHOULD respond to invalid
+ Request-URIs with an appropriate status code.
+
+ A transparent proxy MUST NOT rewrite the "abs_path" part of the
+ received Request-URI when forwarding it to the next inbound server,
+ except as noted above to replace a null abs_path with "/".
+
+ Note: The "no rewrite" rule prevents the proxy from changing the
+ meaning of the request when the origin server is improperly using
+ a non-reserved URI character for a reserved purpose. Implementors
+ should be aware that some pre-HTTP/1.1 proxies have been known to
+ rewrite the Request-URI.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 37]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+5.2 The Resource Identified by a Request
+
+ The exact resource identified by an Internet request is determined by
+ examining both the Request-URI and the Host header field.
+
+ An origin server that does not allow resources to differ by the
+ requested host MAY ignore the Host header field value when
+ determining the resource identified by an HTTP/1.1 request. (But see
+ section 19.6.1.1 for other requirements on Host support in HTTP/1.1.)
+
+ An origin server that does differentiate resources based on the host
+ requested (sometimes referred to as virtual hosts or vanity host
+ names) MUST use the following rules for determining the requested
+ resource on an HTTP/1.1 request:
+
+ 1. If Request-URI is an absoluteURI, the host is part of the
+ Request-URI. Any Host header field value in the request MUST be
+ ignored.
+
+ 2. If the Request-URI is not an absoluteURI, and the request includes
+ a Host header field, the host is determined by the Host header
+ field value.
+
+ 3. If the host as determined by rule 1 or 2 is not a valid host on
+ the server, the response MUST be a 400 (Bad Request) error message.
+
+ Recipients of an HTTP/1.0 request that lacks a Host header field MAY
+ attempt to use heuristics (e.g., examination of the URI path for
+ something unique to a particular host) in order to determine what
+ exact resource is being requested.
+
+5.3 Request Header Fields
+
+ The request-header fields allow the client to pass additional
+ information about the request, and about the client itself, to the
+ server. These fields act as request modifiers, with semantics
+ equivalent to the parameters on a programming language method
+ invocation.
+
+ request-header = Accept ; Section 14.1
+ | Accept-Charset ; Section 14.2
+ | Accept-Encoding ; Section 14.3
+ | Accept-Language ; Section 14.4
+ | Authorization ; Section 14.8
+ | Expect ; Section 14.20
+ | From ; Section 14.22
+ | Host ; Section 14.23
+ | If-Match ; Section 14.24
+
+
+
+Fielding, et al. Standards Track [Page 38]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ | If-Modified-Since ; Section 14.25
+ | If-None-Match ; Section 14.26
+ | If-Range ; Section 14.27
+ | If-Unmodified-Since ; Section 14.28
+ | Max-Forwards ; Section 14.31
+ | Proxy-Authorization ; Section 14.34
+ | Range ; Section 14.35
+ | Referer ; Section 14.36
+ | TE ; Section 14.39
+ | User-Agent ; Section 14.43
+
+ Request-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of request-
+ header fields if all parties in the communication recognize them to
+ be request-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+6 Response
+
+ After receiving and interpreting a request message, a server responds
+ with an HTTP response message.
+
+ Response = Status-Line ; Section 6.1
+ *(( general-header ; Section 4.5
+ | response-header ; Section 6.2
+ | entity-header ) CRLF) ; Section 7.1
+ CRLF
+ [ message-body ] ; Section 7.2
+
+6.1 Status-Line
+
+ The first line of a Response message is the Status-Line, consisting
+ of the protocol version followed by a numeric status code and its
+ associated textual phrase, with each element separated by SP
+ characters. No CR or LF is allowed except in the final CRLF sequence.
+
+ Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+
+6.1.1 Status Code and Reason Phrase
+
+ The Status-Code element is a 3-digit integer result code of the
+ attempt to understand and satisfy the request. These codes are fully
+ defined in section 10. The Reason-Phrase is intended to give a short
+ textual description of the Status-Code. The Status-Code is intended
+ for use by automata and the Reason-Phrase is intended for the human
+ user. The client is not required to examine or display the Reason-
+ Phrase.
+
+
+
+Fielding, et al. Standards Track [Page 39]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The first digit of the Status-Code defines the class of response. The
+ last two digits do not have any categorization role. There are 5
+ values for the first digit:
+
+ - 1xx: Informational - Request received, continuing process
+
+ - 2xx: Success - The action was successfully received,
+ understood, and accepted
+
+ - 3xx: Redirection - Further action must be taken in order to
+ complete the request
+
+ - 4xx: Client Error - The request contains bad syntax or cannot
+ be fulfilled
+
+ - 5xx: Server Error - The server failed to fulfill an apparently
+ valid request
+
+ The individual values of the numeric status codes defined for
+ HTTP/1.1, and an example set of corresponding Reason-Phrase's, are
+ presented below. The reason phrases listed here are only
+ recommendations -- they MAY be replaced by local equivalents without
+ affecting the protocol.
+
+ Status-Code =
+ "100" ; Section 10.1.1: Continue
+ | "101" ; Section 10.1.2: Switching Protocols
+ | "200" ; Section 10.2.1: OK
+ | "201" ; Section 10.2.2: Created
+ | "202" ; Section 10.2.3: Accepted
+ | "203" ; Section 10.2.4: Non-Authoritative Information
+ | "204" ; Section 10.2.5: No Content
+ | "205" ; Section 10.2.6: Reset Content
+ | "206" ; Section 10.2.7: Partial Content
+ | "300" ; Section 10.3.1: Multiple Choices
+ | "301" ; Section 10.3.2: Moved Permanently
+ | "302" ; Section 10.3.3: Found
+ | "303" ; Section 10.3.4: See Other
+ | "304" ; Section 10.3.5: Not Modified
+ | "305" ; Section 10.3.6: Use Proxy
+ | "307" ; Section 10.3.8: Temporary Redirect
+ | "400" ; Section 10.4.1: Bad Request
+ | "401" ; Section 10.4.2: Unauthorized
+ | "402" ; Section 10.4.3: Payment Required
+ | "403" ; Section 10.4.4: Forbidden
+ | "404" ; Section 10.4.5: Not Found
+ | "405" ; Section 10.4.6: Method Not Allowed
+ | "406" ; Section 10.4.7: Not Acceptable
+
+
+
+Fielding, et al. Standards Track [Page 40]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ | "407" ; Section 10.4.8: Proxy Authentication Required
+ | "408" ; Section 10.4.9: Request Time-out
+ | "409" ; Section 10.4.10: Conflict
+ | "410" ; Section 10.4.11: Gone
+ | "411" ; Section 10.4.12: Length Required
+ | "412" ; Section 10.4.13: Precondition Failed
+ | "413" ; Section 10.4.14: Request Entity Too Large
+ | "414" ; Section 10.4.15: Request-URI Too Large
+ | "415" ; Section 10.4.16: Unsupported Media Type
+ | "416" ; Section 10.4.17: Requested range not satisfiable
+ | "417" ; Section 10.4.18: Expectation Failed
+ | "500" ; Section 10.5.1: Internal Server Error
+ | "501" ; Section 10.5.2: Not Implemented
+ | "502" ; Section 10.5.3: Bad Gateway
+ | "503" ; Section 10.5.4: Service Unavailable
+ | "504" ; Section 10.5.5: Gateway Time-out
+ | "505" ; Section 10.5.6: HTTP Version not supported
+ | extension-code
+
+ extension-code = 3DIGIT
+ Reason-Phrase = *<TEXT, excluding CR, LF>
+
+ HTTP status codes are extensible. HTTP applications are not required
+ to understand the meaning of all registered status codes, though such
+ understanding is obviously desirable. However, applications MUST
+ understand the class of any status code, as indicated by the first
+ digit, and treat any unrecognized response as being equivalent to the
+ x00 status code of that class, with the exception that an
+ unrecognized response MUST NOT be cached. For example, if an
+ unrecognized status code of 431 is received by the client, it can
+ safely assume that there was something wrong with its request and
+ treat the response as if it had received a 400 status code. In such
+ cases, user agents SHOULD present to the user the entity returned
+ with the response, since that entity is likely to include human-
+ readable information which will explain the unusual status.
+
+6.2 Response Header Fields
+
+ The response-header fields allow the server to pass additional
+ information about the response which cannot be placed in the Status-
+ Line. These header fields give information about the server and about
+ further access to the resource identified by the Request-URI.
+
+ response-header = Accept-Ranges ; Section 14.5
+ | Age ; Section 14.6
+ | ETag ; Section 14.19
+ | Location ; Section 14.30
+ | Proxy-Authenticate ; Section 14.33
+
+
+
+Fielding, et al. Standards Track [Page 41]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ | Retry-After ; Section 14.37
+ | Server ; Section 14.38
+ | Vary ; Section 14.44
+ | WWW-Authenticate ; Section 14.47
+
+ Response-header field names can be extended reliably only in
+ combination with a change in the protocol version. However, new or
+ experimental header fields MAY be given the semantics of response-
+ header fields if all parties in the communication recognize them to
+ be response-header fields. Unrecognized header fields are treated as
+ entity-header fields.
+
+7 Entity
+
+ Request and Response messages MAY transfer an entity if not otherwise
+ restricted by the request method or response status code. An entity
+ consists of entity-header fields and an entity-body, although some
+ responses will only include the entity-headers.
+
+ In this section, both sender and recipient refer to either the client
+ or the server, depending on who sends and who receives the entity.
+
+7.1 Entity Header Fields
+
+ Entity-header fields define metainformation about the entity-body or,
+ if no body is present, about the resource identified by the request.
+ Some of this metainformation is OPTIONAL; some might be REQUIRED by
+ portions of this specification.
+
+ entity-header = Allow ; Section 14.7
+ | Content-Encoding ; Section 14.11
+ | Content-Language ; Section 14.12
+ | Content-Length ; Section 14.13
+ | Content-Location ; Section 14.14
+ | Content-MD5 ; Section 14.15
+ | Content-Range ; Section 14.16
+ | Content-Type ; Section 14.17
+ | Expires ; Section 14.21
+ | Last-Modified ; Section 14.29
+ | extension-header
+
+ extension-header = message-header
+
+ The extension-header mechanism allows additional entity-header fields
+ to be defined without changing the protocol, but these fields cannot
+ be assumed to be recognizable by the recipient. Unrecognized header
+ fields SHOULD be ignored by the recipient and MUST be forwarded by
+ transparent proxies.
+
+
+
+Fielding, et al. Standards Track [Page 42]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+7.2 Entity Body
+
+ The entity-body (if any) sent with an HTTP request or response is in
+ a format and encoding defined by the entity-header fields.
+
+ entity-body = *OCTET
+
+ An entity-body is only present in a message when a message-body is
+ present, as described in section 4.3. The entity-body is obtained
+ from the message-body by decoding any Transfer-Encoding that might
+ have been applied to ensure safe and proper transfer of the message.
+
+7.2.1 Type
+
+ When an entity-body is included with a message, the data type of that
+ body is determined via the header fields Content-Type and Content-
+ Encoding. These define a two-layer, ordered encoding model:
+
+ entity-body := Content-Encoding( Content-Type( data ) )
+
+ Content-Type specifies the media type of the underlying data.
+ Content-Encoding may be used to indicate any additional content
+ codings applied to the data, usually for the purpose of data
+ compression, that are a property of the requested resource. There is
+ no default encoding.
+
+ Any HTTP/1.1 message containing an entity-body SHOULD include a
+ Content-Type header field defining the media type of that body. If
+ and only if the media type is not given by a Content-Type field, the
+ recipient MAY attempt to guess the media type via inspection of its
+ content and/or the name extension(s) of the URI used to identify the
+ resource. If the media type remains unknown, the recipient SHOULD
+ treat it as type "application/octet-stream".
+
+7.2.2 Entity Length
+
+ The entity-length of a message is the length of the message-body
+ before any transfer-codings have been applied. Section 4.4 defines
+ how the transfer-length of a message-body is determined.
+
+
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 43]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+8 Connections
+
+8.1 Persistent Connections
+
+8.1.1 Purpose
+
+ Prior to persistent connections, a separate TCP connection was
+ established to fetch each URL, increasing the load on HTTP servers
+ and causing congestion on the Internet. The use of inline images and
+ other associated data often require a client to make multiple
+ requests of the same server in a short amount of time. Analysis of
+ these performance problems and results from a prototype
+ implementation are available [26] [30]. Implementation experience and
+ measurements of actual HTTP/1.1 (RFC 2068) implementations show good
+ results [39]. Alternatives have also been explored, for example,
+ T/TCP [27].
+
+ Persistent HTTP connections have a number of advantages:
+
+ - By opening and closing fewer TCP connections, CPU time is saved
+ in routers and hosts (clients, servers, proxies, gateways,
+ tunnels, or caches), and memory used for TCP protocol control
+ blocks can be saved in hosts.
+
+ - HTTP requests and responses can be pipelined on a connection.
+ Pipelining allows a client to make multiple requests without
+ waiting for each response, allowing a single TCP connection to
+ be used much more efficiently, with much lower elapsed time.
+
+ - Network congestion is reduced by reducing the number of packets
+ caused by TCP opens, and by allowing TCP sufficient time to
+ determine the congestion state of the network.
+
+ - Latency on subsequent requests is reduced since there is no time
+ spent in TCP's connection opening handshake.
+
+ - HTTP can evolve more gracefully, since errors can be reported
+ without the penalty of closing the TCP connection. Clients using
+ future versions of HTTP might optimistically try a new feature,
+ but if communicating with an older server, retry with old
+ semantics after an error is reported.
+
+ HTTP implementations SHOULD implement persistent connections.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 44]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+8.1.2 Overall Operation
+
+ A significant difference between HTTP/1.1 and earlier versions of
+ HTTP is that persistent connections are the default behavior of any
+ HTTP connection. That is, unless otherwise indicated, the client
+ SHOULD assume that the server will maintain a persistent connection,
+ even after error responses from the server.
+
+ Persistent connections provide a mechanism by which a client and a
+ server can signal the close of a TCP connection. This signaling takes
+ place using the Connection header field (section 14.10). Once a close
+ has been signaled, the client MUST NOT send any more requests on that
+ connection.
+
+8.1.2.1 Negotiation
+
+ An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
+ maintain a persistent connection unless a Connection header including
+ the connection-token "close" was sent in the request. If the server
+ chooses to close the connection immediately after sending the
+ response, it SHOULD send a Connection header including the
+ connection-token close.
+
+ An HTTP/1.1 client MAY expect a connection to remain open, but would
+ decide to keep it open based on whether the response from a server
+ contains a Connection header with the connection-token close. In case
+ the client does not want to maintain a connection for more than that
+ request, it SHOULD send a Connection header including the
+ connection-token close.
+
+ If either the client or the server sends the close token in the
+ Connection header, that request becomes the last one for the
+ connection.
+
+ Clients and servers SHOULD NOT assume that a persistent connection is
+ maintained for HTTP versions less than 1.1 unless it is explicitly
+ signaled. See section 19.6.2 for more information on backward
+ compatibility with HTTP/1.0 clients.
+
+ In order to remain persistent, all messages on the connection MUST
+ have a self-defined message length (i.e., one not defined by closure
+ of the connection), as described in section 4.4.
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 45]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+8.1.2.2 Pipelining
+
+ A client that supports persistent connections MAY "pipeline" its
+ requests (i.e., send multiple requests without waiting for each
+ response). A server MUST send its responses to those requests in the
+ same order that the requests were received.
+
+ Clients which assume persistent connections and pipeline immediately
+ after connection establishment SHOULD be prepared to retry their
+ connection if the first pipelined attempt fails. If a client does
+ such a retry, it MUST NOT pipeline before it knows the connection is
+ persistent. Clients MUST also be prepared to resend their requests if
+ the server closes the connection before sending all of the
+ corresponding responses.
+
+ Clients SHOULD NOT pipeline requests using non-idempotent methods or
+ non-idempotent sequences of methods (see section 9.1.2). Otherwise, a
+ premature termination of the transport connection could lead to
+ indeterminate results. A client wishing to send a non-idempotent
+ request SHOULD wait to send that request until it has received the
+ response status for the previous request.
+
+8.1.3 Proxy Servers
+
+ It is especially important that proxies correctly implement the
+ properties of the Connection header field as specified in section
+ 14.10.
+
+ The proxy server MUST signal persistent connections separately with
+ its clients and the origin servers (or other proxy servers) that it
+ connects to. Each persistent connection applies to only one transport
+ link.
+
+ A proxy server MUST NOT establish a HTTP/1.1 persistent connection
+ with an HTTP/1.0 client (but see RFC 2068 [33] for information and
+ discussion of the problems with the Keep-Alive header implemented by
+ many HTTP/1.0 clients).
+
+8.1.4 Practical Considerations
+
+ Servers will usually have some time-out value beyond which they will
+ no longer maintain an inactive connection. Proxy servers might make
+ this a higher value since it is likely that the client will be making
+ more connections through the same server. The use of persistent
+ connections places no requirements on the length (or existence) of
+ this time-out for either the client or the server.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 46]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ When a client or server wishes to time-out it SHOULD issue a graceful
+ close on the transport connection. Clients and servers SHOULD both
+ constantly watch for the other side of the transport close, and
+ respond to it as appropriate. If a client or server does not detect
+ the other side's close promptly it could cause unnecessary resource
+ drain on the network.
+
+ A client, server, or proxy MAY close the transport connection at any
+ time. For example, a client might have started to send a new request
+ at the same time that the server has decided to close the "idle"
+ connection. From the server's point of view, the connection is being
+ closed while it was idle, but from the client's point of view, a
+ request is in progress.
+
+ This means that clients, servers, and proxies MUST be able to recover
+ from asynchronous close events. Client software SHOULD reopen the
+ transport connection and retransmit the aborted sequence of requests
+ without user interaction so long as the request sequence is
+ idempotent (see section 9.1.2). Non-idempotent methods or sequences
+ MUST NOT be automatically retried, although user agents MAY offer a
+ human operator the choice of retrying the request(s). Confirmation by
+ user-agent software with semantic understanding of the application
+ MAY substitute for user confirmation. The automatic retry SHOULD NOT
+ be repeated if the second sequence of requests fails.
+
+ Servers SHOULD always respond to at least one request per connection,
+ if at all possible. Servers SHOULD NOT close a connection in the
+ middle of transmitting a response, unless a network or client failure
+ is suspected.
+
+ Clients that use persistent connections SHOULD limit the number of
+ simultaneous connections that they maintain to a given server. A
+ single-user client SHOULD NOT maintain more than 2 connections with
+ any server or proxy. A proxy SHOULD use up to 2*N connections to
+ another server or proxy, where N is the number of simultaneously
+ active users. These guidelines are intended to improve HTTP response
+ times and avoid congestion.
+
+8.2 Message Transmission Requirements
+
+8.2.1 Persistent Connections and Flow Control
+
+ HTTP/1.1 servers SHOULD maintain persistent connections and use TCP's
+ flow control mechanisms to resolve temporary overloads, rather than
+ terminating connections with the expectation that clients will retry.
+ The latter technique can exacerbate network congestion.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 47]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+8.2.2 Monitoring Connections for Error Status Messages
+
+ An HTTP/1.1 (or later) client sending a message-body SHOULD monitor
+ the network connection for an error status while it is transmitting
+ the request. If the client sees an error status, it SHOULD
+ immediately cease transmitting the body. If the body is being sent
+ using a "chunked" encoding (section 3.6), a zero length chunk and
+ empty trailer MAY be used to prematurely mark the end of the message.
+ If the body was preceded by a Content-Length header, the client MUST
+ close the connection.
+
+8.2.3 Use of the 100 (Continue) Status
+
+ The purpose of the 100 (Continue) status (see section 10.1.1) is to
+ allow a client that is sending a request message with a request body
+ to determine if the origin server is willing to accept the request
+ (based on the request headers) before the client sends the request
+ body. In some cases, it might either be inappropriate or highly
+ inefficient for the client to send the body if the server will reject
+ the message without looking at the body.
+
+ Requirements for HTTP/1.1 clients:
+
+ - If a client will wait for a 100 (Continue) response before
+ sending the request body, it MUST send an Expect request-header
+ field (section 14.20) with the "100-continue" expectation.
+
+ - A client MUST NOT send an Expect request-header field (section
+ 14.20) with the "100-continue" expectation if it does not intend
+ to send a request body.
+
+ Because of the presence of older implementations, the protocol allows
+ ambiguous situations in which a client may send "Expect: 100-
+ continue" without receiving either a 417 (Expectation Failed) status
+ or a 100 (Continue) status. Therefore, when a client sends this
+ header field to an origin server (possibly via a proxy) from which it
+ has never seen a 100 (Continue) status, the client SHOULD NOT wait
+ for an indefinite period before sending the request body.
+
+ Requirements for HTTP/1.1 origin servers:
+
+ - Upon receiving a request which includes an Expect request-header
+ field with the "100-continue" expectation, an origin server MUST
+ either respond with 100 (Continue) status and continue to read
+ from the input stream, or respond with a final status code. The
+ origin server MUST NOT wait for the request body before sending
+ the 100 (Continue) response. If it responds with a final status
+ code, it MAY close the transport connection or it MAY continue
+
+
+
+Fielding, et al. Standards Track [Page 48]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ to read and discard the rest of the request. It MUST NOT
+ perform the requested method if it returns a final status code.
+
+ - An origin server SHOULD NOT send a 100 (Continue) response if
+ the request message does not include an Expect request-header
+ field with the "100-continue" expectation, and MUST NOT send a
+ 100 (Continue) response if such a request comes from an HTTP/1.0
+ (or earlier) client. There is an exception to this rule: for
+ compatibility with RFC 2068, a server MAY send a 100 (Continue)
+ status in response to an HTTP/1.1 PUT or POST request that does
+ not include an Expect request-header field with the "100-
+ continue" expectation. This exception, the purpose of which is
+ to minimize any client processing delays associated with an
+ undeclared wait for 100 (Continue) status, applies only to
+ HTTP/1.1 requests, and not to requests with any other HTTP-
+ version value.
+
+ - An origin server MAY omit a 100 (Continue) response if it has
+ already received some or all of the request body for the
+ corresponding request.
+
+ - An origin server that sends a 100 (Continue) response MUST
+ ultimately send a final status code, once the request body is
+ received and processed, unless it terminates the transport
+ connection prematurely.
+
+ - If an origin server receives a request that does not include an
+ Expect request-header field with the "100-continue" expectation,
+ the request includes a request body, and the server responds
+ with a final status code before reading the entire request body
+ from the transport connection, then the server SHOULD NOT close
+ the transport connection until it has read the entire request,
+ or until the client closes the connection. Otherwise, the client
+ might not reliably receive the response message. However, this
+ requirement is not be construed as preventing a server from
+ defending itself against denial-of-service attacks, or from
+ badly broken client implementations.
+
+ Requirements for HTTP/1.1 proxies:
+
+ - If a proxy receives a request that includes an Expect request-
+ header field with the "100-continue" expectation, and the proxy
+ either knows that the next-hop server complies with HTTP/1.1 or
+ higher, or does not know the HTTP version of the next-hop
+ server, it MUST forward the request, including the Expect header
+ field.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 49]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - If the proxy knows that the version of the next-hop server is
+ HTTP/1.0 or lower, it MUST NOT forward the request, and it MUST
+ respond with a 417 (Expectation Failed) status.
+
+ - Proxies SHOULD maintain a cache recording the HTTP version
+ numbers received from recently-referenced next-hop servers.
+
+ - A proxy MUST NOT forward a 100 (Continue) response if the
+ request message was received from an HTTP/1.0 (or earlier)
+ client and did not include an Expect request-header field with
+ the "100-continue" expectation. This requirement overrides the
+ general rule for forwarding of 1xx responses (see section 10.1).
+
+8.2.4 Client Behavior if Server Prematurely Closes Connection
+
+ If an HTTP/1.1 client sends a request which includes a request body,
+ but which does not include an Expect request-header field with the
+ "100-continue" expectation, and if the client is not directly
+ connected to an HTTP/1.1 origin server, and if the client sees the
+ connection close before receiving any status from the server, the
+ client SHOULD retry the request. If the client does retry this
+ request, it MAY use the following "binary exponential backoff"
+ algorithm to be assured of obtaining a reliable response:
+
+ 1. Initiate a new connection to the server
+
+ 2. Transmit the request-headers
+
+ 3. Initialize a variable R to the estimated round-trip time to the
+ server (e.g., based on the time it took to establish the
+ connection), or to a constant value of 5 seconds if the round-
+ trip time is not available.
+
+ 4. Compute T = R * (2**N), where N is the number of previous
+ retries of this request.
+
+ 5. Wait either for an error response from the server, or for T
+ seconds (whichever comes first)
+
+ 6. If no error response is received, after T seconds transmit the
+ body of the request.
+
+ 7. If client sees that the connection is closed prematurely,
+ repeat from step 1 until the request is accepted, an error
+ response is received, or the user becomes impatient and
+ terminates the retry process.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 50]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If at any point an error status is received, the client
+
+ - SHOULD NOT continue and
+
+ - SHOULD close the connection if it has not completed sending the
+ request message.
+
+9 Method Definitions
+
+ The set of common methods for HTTP/1.1 is defined below. Although
+ this set can be expanded, additional methods cannot be assumed to
+ share the same semantics for separately extended clients and servers.
+
+ The Host request-header field (section 14.23) MUST accompany all
+ HTTP/1.1 requests.
+
+9.1 Safe and Idempotent Methods
+
+9.1.1 Safe Methods
+
+ Implementors should be aware that the software represents the user in
+ their interactions over the Internet, and should be careful to allow
+ the user to be aware of any actions they might take which may have an
+ unexpected significance to themselves or others.
+
+ In particular, the convention has been established that the GET and
+ HEAD methods SHOULD NOT have the significance of taking an action
+ other than retrieval. These methods ought to be considered "safe".
+ This allows user agents to represent other methods, such as POST, PUT
+ and DELETE, in a special way, so that the user is made aware of the
+ fact that a possibly unsafe action is being requested.
+
+ Naturally, it is not possible to ensure that the server does not
+ generate side-effects as a result of performing a GET request; in
+ fact, some dynamic resources consider that a feature. The important
+ distinction here is that the user did not request the side-effects,
+ so therefore cannot be held accountable for them.
+
+9.1.2 Idempotent Methods
+
+ Methods can also have the property of "idempotence" in that (aside
+ from error or expiration issues) the side-effects of N > 0 identical
+ requests is the same as for a single request. The methods GET, HEAD,
+ PUT and DELETE share this property. Also, the methods OPTIONS and
+ TRACE SHOULD NOT have side effects, and so are inherently idempotent.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 51]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ However, it is possible that a sequence of several requests is non-
+ idempotent, even if all of the methods executed in that sequence are
+ idempotent. (A sequence is idempotent if a single execution of the
+ entire sequence always yields a result that is not changed by a
+ reexecution of all, or part, of that sequence.) For example, a
+ sequence is non-idempotent if its result depends on a value that is
+ later modified in the same sequence.
+
+ A sequence that never has side effects is idempotent, by definition
+ (provided that no concurrent operations are being executed on the
+ same set of resources).
+
+9.2 OPTIONS
+
+ The OPTIONS method represents a request for information about the
+ communication options available on the request/response chain
+ identified by the Request-URI. This method allows the client to
+ determine the options and/or requirements associated with a resource,
+ or the capabilities of a server, without implying a resource action
+ or initiating a resource retrieval.
+
+ Responses to this method are not cacheable.
+
+ If the OPTIONS request includes an entity-body (as indicated by the
+ presence of Content-Length or Transfer-Encoding), then the media type
+ MUST be indicated by a Content-Type field. Although this
+ specification does not define any use for such a body, future
+ extensions to HTTP might use the OPTIONS body to make more detailed
+ queries on the server. A server that does not support such an
+ extension MAY discard the request body.
+
+ If the Request-URI is an asterisk ("*"), the OPTIONS request is
+ intended to apply to the server in general rather than to a specific
+ resource. Since a server's communication options typically depend on
+ the resource, the "*" request is only useful as a "ping" or "no-op"
+ type of method; it does nothing beyond allowing the client to test
+ the capabilities of the server. For example, this can be used to test
+ a proxy for HTTP/1.1 compliance (or lack thereof).
+
+ If the Request-URI is not an asterisk, the OPTIONS request applies
+ only to the options that are available when communicating with that
+ resource.
+
+ A 200 response SHOULD include any header fields that indicate
+ optional features implemented by the server and applicable to that
+ resource (e.g., Allow), possibly including extensions not defined by
+ this specification. The response body, if any, SHOULD also include
+ information about the communication options. The format for such a
+
+
+
+Fielding, et al. Standards Track [Page 52]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ body is not defined by this specification, but might be defined by
+ future extensions to HTTP. Content negotiation MAY be used to select
+ the appropriate response format. If no response body is included, the
+ response MUST include a Content-Length field with a field-value of
+ "0".
+
+ The Max-Forwards request-header field MAY be used to target a
+ specific proxy in the request chain. When a proxy receives an OPTIONS
+ request on an absoluteURI for which request forwarding is permitted,
+ the proxy MUST check for a Max-Forwards field. If the Max-Forwards
+ field-value is zero ("0"), the proxy MUST NOT forward the message;
+ instead, the proxy SHOULD respond with its own communication options.
+ If the Max-Forwards field-value is an integer greater than zero, the
+ proxy MUST decrement the field-value when it forwards the request. If
+ no Max-Forwards field is present in the request, then the forwarded
+ request MUST NOT include a Max-Forwards field.
+
+9.3 GET
+
+ The GET method means retrieve whatever information (in the form of an
+ entity) is identified by the Request-URI. If the Request-URI refers
+ to a data-producing process, it is the produced data which shall be
+ returned as the entity in the response and not the source text of the
+ process, unless that text happens to be the output of the process.
+
+ The semantics of the GET method change to a "conditional GET" if the
+ request message includes an If-Modified-Since, If-Unmodified-Since,
+ If-Match, If-None-Match, or If-Range header field. A conditional GET
+ method requests that the entity be transferred only under the
+ circumstances described by the conditional header field(s). The
+ conditional GET method is intended to reduce unnecessary network
+ usage by allowing cached entities to be refreshed without requiring
+ multiple requests or transferring data already held by the client.
+
+ The semantics of the GET method change to a "partial GET" if the
+ request message includes a Range header field. A partial GET requests
+ that only part of the entity be transferred, as described in section
+ 14.35. The partial GET method is intended to reduce unnecessary
+ network usage by allowing partially-retrieved entities to be
+ completed without transferring data already held by the client.
+
+ The response to a GET request is cacheable if and only if it meets
+ the requirements for HTTP caching described in section 13.
+
+ See section 15.1.3 for security considerations when used for forms.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 53]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+9.4 HEAD
+
+ The HEAD method is identical to GET except that the server MUST NOT
+ return a message-body in the response. The metainformation contained
+ in the HTTP headers in response to a HEAD request SHOULD be identical
+ to the information sent in response to a GET request. This method can
+ be used for obtaining metainformation about the entity implied by the
+ request without transferring the entity-body itself. This method is
+ often used for testing hypertext links for validity, accessibility,
+ and recent modification.
+
+ The response to a HEAD request MAY be cacheable in the sense that the
+ information contained in the response MAY be used to update a
+ previously cached entity from that resource. If the new field values
+ indicate that the cached entity differs from the current entity (as
+ would be indicated by a change in Content-Length, Content-MD5, ETag
+ or Last-Modified), then the cache MUST treat the cache entry as
+ stale.
+
+9.5 POST
+
+ The POST method is used to request that the origin server accept the
+ entity enclosed in the request as a new subordinate of the resource
+ identified by the Request-URI in the Request-Line. POST is designed
+ to allow a uniform method to cover the following functions:
+
+ - Annotation of existing resources;
+
+ - Posting a message to a bulletin board, newsgroup, mailing list,
+ or similar group of articles;
+
+ - Providing a block of data, such as the result of submitting a
+ form, to a data-handling process;
+
+ - Extending a database through an append operation.
+
+ The actual function performed by the POST method is determined by the
+ server and is usually dependent on the Request-URI. The posted entity
+ is subordinate to that URI in the same way that a file is subordinate
+ to a directory containing it, a news article is subordinate to a
+ newsgroup to which it is posted, or a record is subordinate to a
+ database.
+
+ The action performed by the POST method might not result in a
+ resource that can be identified by a URI. In this case, either 200
+ (OK) or 204 (No Content) is the appropriate response status,
+ depending on whether or not the response includes an entity that
+ describes the result.
+
+
+
+Fielding, et al. Standards Track [Page 54]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If a resource has been created on the origin server, the response
+ SHOULD be 201 (Created) and contain an entity which describes the
+ status of the request and refers to the new resource, and a Location
+ header (see section 14.30).
+
+ Responses to this method are not cacheable, unless the response
+ includes appropriate Cache-Control or Expires header fields. However,
+ the 303 (See Other) response can be used to direct the user agent to
+ retrieve a cacheable resource.
+
+ POST requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ See section 15.1.3 for security considerations.
+
+9.6 PUT
+
+ The PUT method requests that the enclosed entity be stored under the
+ supplied Request-URI. If the Request-URI refers to an already
+ existing resource, the enclosed entity SHOULD be considered as a
+ modified version of the one residing on the origin server. If the
+ Request-URI does not point to an existing resource, and that URI is
+ capable of being defined as a new resource by the requesting user
+ agent, the origin server can create the resource with that URI. If a
+ new resource is created, the origin server MUST inform the user agent
+ via the 201 (Created) response. If an existing resource is modified,
+ either the 200 (OK) or 204 (No Content) response codes SHOULD be sent
+ to indicate successful completion of the request. If the resource
+ could not be created or modified with the Request-URI, an appropriate
+ error response SHOULD be given that reflects the nature of the
+ problem. The recipient of the entity MUST NOT ignore any Content-*
+ (e.g. Content-Range) headers that it does not understand or implement
+ and MUST return a 501 (Not Implemented) response in such cases.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+ The fundamental difference between the POST and PUT requests is
+ reflected in the different meaning of the Request-URI. The URI in a
+ POST request identifies the resource that will handle the enclosed
+ entity. That resource might be a data-accepting process, a gateway to
+ some other protocol, or a separate entity that accepts annotations.
+ In contrast, the URI in a PUT request identifies the entity enclosed
+ with the request -- the user agent knows what URI is intended and the
+ server MUST NOT attempt to apply the request to some other resource.
+ If the server desires that the request be applied to a different URI,
+
+
+
+
+Fielding, et al. Standards Track [Page 55]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ it MUST send a 301 (Moved Permanently) response; the user agent MAY
+ then make its own decision regarding whether or not to redirect the
+ request.
+
+ A single resource MAY be identified by many different URIs. For
+ example, an article might have a URI for identifying "the current
+ version" which is separate from the URI identifying each particular
+ version. In this case, a PUT request on a general URI might result in
+ several other URIs being defined by the origin server.
+
+ HTTP/1.1 does not define how a PUT method affects the state of an
+ origin server.
+
+ PUT requests MUST obey the message transmission requirements set out
+ in section 8.2.
+
+ Unless otherwise specified for a particular entity-header, the
+ entity-headers in the PUT request SHOULD be applied to the resource
+ created or modified by the PUT.
+
+9.7 DELETE
+
+ The DELETE method requests that the origin server delete the resource
+ identified by the Request-URI. This method MAY be overridden by human
+ intervention (or other means) on the origin server. The client cannot
+ be guaranteed that the operation has been carried out, even if the
+ status code returned from the origin server indicates that the action
+ has been completed successfully. However, the server SHOULD NOT
+ indicate success unless, at the time the response is given, it
+ intends to delete the resource or move it to an inaccessible
+ location.
+
+ A successful response SHOULD be 200 (OK) if the response includes an
+ entity describing the status, 202 (Accepted) if the action has not
+ yet been enacted, or 204 (No Content) if the action has been enacted
+ but the response does not include an entity.
+
+ If the request passes through a cache and the Request-URI identifies
+ one or more currently cached entities, those entries SHOULD be
+ treated as stale. Responses to this method are not cacheable.
+
+9.8 TRACE
+
+ The TRACE method is used to invoke a remote, application-layer loop-
+ back of the request message. The final recipient of the request
+ SHOULD reflect the message received back to the client as the
+ entity-body of a 200 (OK) response. The final recipient is either the
+
+
+
+
+Fielding, et al. Standards Track [Page 56]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ origin server or the first proxy or gateway to receive a Max-Forwards
+ value of zero (0) in the request (see section 14.31). A TRACE request
+ MUST NOT include an entity.
+
+ TRACE allows the client to see what is being received at the other
+ end of the request chain and use that data for testing or diagnostic
+ information. The value of the Via header field (section 14.45) is of
+ particular interest, since it acts as a trace of the request chain.
+ Use of the Max-Forwards header field allows the client to limit the
+ length of the request chain, which is useful for testing a chain of
+ proxies forwarding messages in an infinite loop.
+
+ If the request is valid, the response SHOULD contain the entire
+ request message in the entity-body, with a Content-Type of
+ "message/http". Responses to this method MUST NOT be cached.
+
+9.9 CONNECT
+
+ This specification reserves the method name CONNECT for use with a
+ proxy that can dynamically switch to being a tunnel (e.g. SSL
+ tunneling [44]).
+
+10 Status Code Definitions
+
+ Each Status-Code is described below, including a description of which
+ method(s) it can follow and any metainformation required in the
+ response.
+
+10.1 Informational 1xx
+
+ This class of status code indicates a provisional response,
+ consisting only of the Status-Line and optional headers, and is
+ terminated by an empty line. There are no required headers for this
+ class of status code. Since HTTP/1.0 did not define any 1xx status
+ codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client
+ except under experimental conditions.
+
+ A client MUST be prepared to accept one or more 1xx status responses
+ prior to a regular response, even if the client does not expect a 100
+ (Continue) status message. Unexpected 1xx status responses MAY be
+ ignored by a user agent.
+
+ Proxies MUST forward 1xx responses, unless the connection between the
+ proxy and its client has been closed, or unless the proxy itself
+ requested the generation of the 1xx response. (For example, if a
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 57]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ proxy adds a "Expect: 100-continue" field when it forwards a request,
+ then it need not forward the corresponding 100 (Continue)
+ response(s).)
+
+10.1.1 100 Continue
+
+ The client SHOULD continue with its request. This interim response is
+ used to inform the client that the initial part of the request has
+ been received and has not yet been rejected by the server. The client
+ SHOULD continue by sending the remainder of the request or, if the
+ request has already been completed, ignore this response. The server
+ MUST send a final response after the request has been completed. See
+ section 8.2.3 for detailed discussion of the use and handling of this
+ status code.
+
+10.1.2 101 Switching Protocols
+
+ The server understands and is willing to comply with the client's
+ request, via the Upgrade message header field (section 14.42), for a
+ change in the application protocol being used on this connection. The
+ server will switch protocols to those defined by the response's
+ Upgrade header field immediately after the empty line which
+ terminates the 101 response.
+
+ The protocol SHOULD be switched only when it is advantageous to do
+ so. For example, switching to a newer version of HTTP is advantageous
+ over older versions, and switching to a real-time, synchronous
+ protocol might be advantageous when delivering resources that use
+ such features.
+
+10.2 Successful 2xx
+
+ This class of status code indicates that the client's request was
+ successfully received, understood, and accepted.
+
+10.2.1 200 OK
+
+ The request has succeeded. The information returned with the response
+ is dependent on the method used in the request, for example:
+
+ GET an entity corresponding to the requested resource is sent in
+ the response;
+
+ HEAD the entity-header fields corresponding to the requested
+ resource are sent in the response without any message-body;
+
+ POST an entity describing or containing the result of the action;
+
+
+
+
+Fielding, et al. Standards Track [Page 58]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ TRACE an entity containing the request message as received by the
+ end server.
+
+10.2.2 201 Created
+
+ The request has been fulfilled and resulted in a new resource being
+ created. The newly created resource can be referenced by the URI(s)
+ returned in the entity of the response, with the most specific URI
+ for the resource given by a Location header field. The response
+ SHOULD include an entity containing a list of resource
+ characteristics and location(s) from which the user or user agent can
+ choose the one most appropriate. The entity format is specified by
+ the media type given in the Content-Type header field. The origin
+ server MUST create the resource before returning the 201 status code.
+ If the action cannot be carried out immediately, the server SHOULD
+ respond with 202 (Accepted) response instead.
+
+ A 201 response MAY contain an ETag response header field indicating
+ the current value of the entity tag for the requested variant just
+ created, see section 14.19.
+
+10.2.3 202 Accepted
+
+ The request has been accepted for processing, but the processing has
+ not been completed. The request might or might not eventually be
+ acted upon, as it might be disallowed when processing actually takes
+ place. There is no facility for re-sending a status code from an
+ asynchronous operation such as this.
+
+ The 202 response is intentionally non-committal. Its purpose is to
+ allow a server to accept a request for some other process (perhaps a
+ batch-oriented process that is only run once per day) without
+ requiring that the user agent's connection to the server persist
+ until the process is completed. The entity returned with this
+ response SHOULD include an indication of the request's current status
+ and either a pointer to a status monitor or some estimate of when the
+ user can expect the request to be fulfilled.
+
+10.2.4 203 Non-Authoritative Information
+
+ The returned metainformation in the entity-header is not the
+ definitive set as available from the origin server, but is gathered
+ from a local or a third-party copy. The set presented MAY be a subset
+ or superset of the original version. For example, including local
+ annotation information about the resource might result in a superset
+ of the metainformation known by the origin server. Use of this
+ response code is not required and is only appropriate when the
+ response would otherwise be 200 (OK).
+
+
+
+Fielding, et al. Standards Track [Page 59]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.2.5 204 No Content
+
+ The server has fulfilled the request but does not need to return an
+ entity-body, and might want to return updated metainformation. The
+ response MAY include new or updated metainformation in the form of
+ entity-headers, which if present SHOULD be associated with the
+ requested variant.
+
+ If the client is a user agent, it SHOULD NOT change its document view
+ from that which caused the request to be sent. This response is
+ primarily intended to allow input for actions to take place without
+ causing a change to the user agent's active document view, although
+ any new or updated metainformation SHOULD be applied to the document
+ currently in the user agent's active view.
+
+ The 204 response MUST NOT include a message-body, and thus is always
+ terminated by the first empty line after the header fields.
+
+10.2.6 205 Reset Content
+
+ The server has fulfilled the request and the user agent SHOULD reset
+ the document view which caused the request to be sent. This response
+ is primarily intended to allow input for actions to take place via
+ user input, followed by a clearing of the form in which the input is
+ given so that the user can easily initiate another input action. The
+ response MUST NOT include an entity.
+
+10.2.7 206 Partial Content
+
+ The server has fulfilled the partial GET request for the resource.
+ The request MUST have included a Range header field (section 14.35)
+ indicating the desired range, and MAY have included an If-Range
+ header field (section 14.27) to make the request conditional.
+
+ The response MUST include the following header fields:
+
+ - Either a Content-Range header field (section 14.16) indicating
+ the range included with this response, or a multipart/byteranges
+ Content-Type including Content-Range fields for each part. If a
+ Content-Length header field is present in the response, its
+ value MUST match the actual number of OCTETs transmitted in the
+ message-body.
+
+ - Date
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+
+
+
+Fielding, et al. Standards Track [Page 60]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the 206 response is the result of an If-Range request that used a
+ strong cache validator (see section 13.3.3), the response SHOULD NOT
+ include other entity-headers. If the response is the result of an
+ If-Range request that used a weak validator, the response MUST NOT
+ include other entity-headers; this prevents inconsistencies between
+ cached entity-bodies and updated headers. Otherwise, the response
+ MUST include all of the entity-headers that would have been returned
+ with a 200 (OK) response to the same request.
+
+ A cache MUST NOT combine a 206 response with other previously cached
+ content if the ETag or Last-Modified headers do not match exactly,
+ see 13.5.4.
+
+ A cache that does not support the Range and Content-Range headers
+ MUST NOT cache 206 (Partial) responses.
+
+10.3 Redirection 3xx
+
+ This class of status code indicates that further action needs to be
+ taken by the user agent in order to fulfill the request. The action
+ required MAY be carried out by the user agent without interaction
+ with the user if and only if the method used in the second request is
+ GET or HEAD. A client SHOULD detect infinite redirection loops, since
+ such loops generate network traffic for each redirection.
+
+ Note: previous versions of this specification recommended a
+ maximum of five redirections. Content developers should be aware
+ that there might be clients that implement such a fixed
+ limitation.
+
+10.3.1 300 Multiple Choices
+
+ The requested resource corresponds to any one of a set of
+ representations, each with its own specific location, and agent-
+ driven negotiation information (section 12) is being provided so that
+ the user (or user agent) can select a preferred representation and
+ redirect its request to that location.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of resource characteristics and location(s) from
+ which the user or user agent can choose the one most appropriate. The
+ entity format is specified by the media type given in the Content-
+ Type header field. Depending upon the format and the capabilities of
+
+
+
+
+Fielding, et al. Standards Track [Page 61]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ the user agent, selection of the most appropriate choice MAY be
+ performed automatically. However, this specification does not define
+ any standard for such automatic selection.
+
+ If the server has a preferred choice of representation, it SHOULD
+ include the specific URI for that representation in the Location
+ field; user agents MAY use the Location field value for automatic
+ redirection. This response is cacheable unless indicated otherwise.
+
+10.3.2 301 Moved Permanently
+
+ The requested resource has been assigned a new permanent URI and any
+ future references to this resource SHOULD use one of the returned
+ URIs. Clients with link editing capabilities ought to automatically
+ re-link references to the Request-URI to one or more of the new
+ references returned by the server, where possible. This response is
+ cacheable unless indicated otherwise.
+
+ The new permanent URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ If the 301 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: When automatically redirecting a POST request after
+ receiving a 301 status code, some existing HTTP/1.0 user agents
+ will erroneously change it into a GET request.
+
+10.3.3 302 Found
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection might be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 62]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If the 302 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+ Note: RFC 1945 and RFC 2068 specify that the client is not allowed
+ to change the method on the redirected request. However, most
+ existing user agent implementations treat 302 as if it were a 303
+ response, performing a GET on the Location field-value regardless
+ of the original request method. The status codes 303 and 307 have
+ been added for servers that wish to make unambiguously clear which
+ kind of reaction is expected of the client.
+
+10.3.4 303 See Other
+
+ The response to the request can be found under a different URI and
+ SHOULD be retrieved using a GET method on that resource. This method
+ exists primarily to allow the output of a POST-activated script to
+ redirect the user agent to a selected resource. The new URI is not a
+ substitute reference for the originally requested resource. The 303
+ response MUST NOT be cached, but the response to the second
+ (redirected) request might be cacheable.
+
+ The different URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s).
+
+ Note: Many pre-HTTP/1.1 user agents do not understand the 303
+ status. When interoperability with such clients is a concern, the
+ 302 status code may be used instead, since most user agents react
+ to a 302 response as described here for 303.
+
+10.3.5 304 Not Modified
+
+ If the client has performed a conditional GET request and access is
+ allowed, but the document has not been modified, the server SHOULD
+ respond with this status code. The 304 response MUST NOT contain a
+ message-body, and thus is always terminated by the first empty line
+ after the header fields.
+
+ The response MUST include the following header fields:
+
+ - Date, unless its omission is required by section 14.18.1
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 63]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If a clockless origin server obeys these rules, and proxies and
+ clients add their own Date to any response received without one (as
+ already specified by [RFC 2068], section 14.19), caches will operate
+ correctly.
+
+ - ETag and/or Content-Location, if the header would have been sent
+ in a 200 response to the same request
+
+ - Expires, Cache-Control, and/or Vary, if the field-value might
+ differ from that sent in any previous response for the same
+ variant
+
+ If the conditional GET used a strong cache validator (see section
+ 13.3.3), the response SHOULD NOT include other entity-headers.
+ Otherwise (i.e., the conditional GET used a weak validator), the
+ response MUST NOT include other entity-headers; this prevents
+ inconsistencies between cached entity-bodies and updated headers.
+
+ If a 304 response indicates an entity not currently cached, then the
+ cache MUST disregard the response and repeat the request without the
+ conditional.
+
+ If a cache uses a received 304 response to update a cache entry, the
+ cache MUST update the entry to reflect any new field values given in
+ the response.
+
+10.3.6 305 Use Proxy
+
+ The requested resource MUST be accessed through the proxy given by
+ the Location field. The Location field gives the URI of the proxy.
+ The recipient is expected to repeat this single request via the
+ proxy. 305 responses MUST only be generated by origin servers.
+
+ Note: RFC 2068 was not clear that 305 was intended to redirect a
+ single request, and to be generated by origin servers only. Not
+ observing these limitations has significant security consequences.
+
+10.3.7 306 (Unused)
+
+ The 306 status code was used in a previous version of the
+ specification, is no longer used, and the code is reserved.
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 64]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.3.8 307 Temporary Redirect
+
+ The requested resource resides temporarily under a different URI.
+ Since the redirection MAY be altered on occasion, the client SHOULD
+ continue to use the Request-URI for future requests. This response
+ is only cacheable if indicated by a Cache-Control or Expires header
+ field.
+
+ The temporary URI SHOULD be given by the Location field in the
+ response. Unless the request method was HEAD, the entity of the
+ response SHOULD contain a short hypertext note with a hyperlink to
+ the new URI(s) , since many pre-HTTP/1.1 user agents do not
+ understand the 307 status. Therefore, the note SHOULD contain the
+ information necessary for a user to repeat the original request on
+ the new URI.
+
+ If the 307 status code is received in response to a request other
+ than GET or HEAD, the user agent MUST NOT automatically redirect the
+ request unless it can be confirmed by the user, since this might
+ change the conditions under which the request was issued.
+
+10.4 Client Error 4xx
+
+ The 4xx class of status code is intended for cases in which the
+ client seems to have erred. Except when responding to a HEAD request,
+ the server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. These status codes are applicable to any request method.
+ User agents SHOULD display any included entity to the user.
+
+ If the client is sending data, a server implementation using TCP
+ SHOULD be careful to ensure that the client acknowledges receipt of
+ the packet(s) containing the response, before the server closes the
+ input connection. If the client continues sending data to the server
+ after the close, the server's TCP stack will send a reset packet to
+ the client, which may erase the client's unacknowledged input buffers
+ before they can be read and interpreted by the HTTP application.
+
+10.4.1 400 Bad Request
+
+ The request could not be understood by the server due to malformed
+ syntax. The client SHOULD NOT repeat the request without
+ modifications.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 65]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.4.2 401 Unauthorized
+
+ The request requires user authentication. The response MUST include a
+ WWW-Authenticate header field (section 14.47) containing a challenge
+ applicable to the requested resource. The client MAY repeat the
+ request with a suitable Authorization header field (section 14.8). If
+ the request already included Authorization credentials, then the 401
+ response indicates that authorization has been refused for those
+ credentials. If the 401 response contains the same challenge as the
+ prior response, and the user agent has already attempted
+ authentication at least once, then the user SHOULD be presented the
+ entity that was given in the response, since that entity might
+ include relevant diagnostic information. HTTP access authentication
+ is explained in "HTTP Authentication: Basic and Digest Access
+ Authentication" [43].
+
+10.4.3 402 Payment Required
+
+ This code is reserved for future use.
+
+10.4.4 403 Forbidden
+
+ The server understood the request, but is refusing to fulfill it.
+ Authorization will not help and the request SHOULD NOT be repeated.
+ If the request method was not HEAD and the server wishes to make
+ public why the request has not been fulfilled, it SHOULD describe the
+ reason for the refusal in the entity. If the server does not wish to
+ make this information available to the client, the status code 404
+ (Not Found) can be used instead.
+
+10.4.5 404 Not Found
+
+ The server has not found anything matching the Request-URI. No
+ indication is given of whether the condition is temporary or
+ permanent. The 410 (Gone) status code SHOULD be used if the server
+ knows, through some internally configurable mechanism, that an old
+ resource is permanently unavailable and has no forwarding address.
+ This status code is commonly used when the server does not wish to
+ reveal exactly why the request has been refused, or when no other
+ response is applicable.
+
+10.4.6 405 Method Not Allowed
+
+ The method specified in the Request-Line is not allowed for the
+ resource identified by the Request-URI. The response MUST include an
+ Allow header containing a list of valid methods for the requested
+ resource.
+
+
+
+
+Fielding, et al. Standards Track [Page 66]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.4.7 406 Not Acceptable
+
+ The resource identified by the request is only capable of generating
+ response entities which have content characteristics not acceptable
+ according to the accept headers sent in the request.
+
+ Unless it was a HEAD request, the response SHOULD include an entity
+ containing a list of available entity characteristics and location(s)
+ from which the user or user agent can choose the one most
+ appropriate. The entity format is specified by the media type given
+ in the Content-Type header field. Depending upon the format and the
+ capabilities of the user agent, selection of the most appropriate
+ choice MAY be performed automatically. However, this specification
+ does not define any standard for such automatic selection.
+
+ Note: HTTP/1.1 servers are allowed to return responses which are
+ not acceptable according to the accept headers sent in the
+ request. In some cases, this may even be preferable to sending a
+ 406 response. User agents are encouraged to inspect the headers of
+ an incoming response to determine if it is acceptable.
+
+ If the response could be unacceptable, a user agent SHOULD
+ temporarily stop receipt of more data and query the user for a
+ decision on further actions.
+
+10.4.8 407 Proxy Authentication Required
+
+ This code is similar to 401 (Unauthorized), but indicates that the
+ client must first authenticate itself with the proxy. The proxy MUST
+ return a Proxy-Authenticate header field (section 14.33) containing a
+ challenge applicable to the proxy for the requested resource. The
+ client MAY repeat the request with a suitable Proxy-Authorization
+ header field (section 14.34). HTTP access authentication is explained
+ in "HTTP Authentication: Basic and Digest Access Authentication"
+ [43].
+
+10.4.9 408 Request Timeout
+
+ The client did not produce a request within the time that the server
+ was prepared to wait. The client MAY repeat the request without
+ modifications at any later time.
+
+10.4.10 409 Conflict
+
+ The request could not be completed due to a conflict with the current
+ state of the resource. This code is only allowed in situations where
+ it is expected that the user might be able to resolve the conflict
+ and resubmit the request. The response body SHOULD include enough
+
+
+
+Fielding, et al. Standards Track [Page 67]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ information for the user to recognize the source of the conflict.
+ Ideally, the response entity would include enough information for the
+ user or user agent to fix the problem; however, that might not be
+ possible and is not required.
+
+ Conflicts are most likely to occur in response to a PUT request. For
+ example, if versioning were being used and the entity being PUT
+ included changes to a resource which conflict with those made by an
+ earlier (third-party) request, the server might use the 409 response
+ to indicate that it can't complete the request. In this case, the
+ response entity would likely contain a list of the differences
+ between the two versions in a format defined by the response
+ Content-Type.
+
+10.4.11 410 Gone
+
+ The requested resource is no longer available at the server and no
+ forwarding address is known. This condition is expected to be
+ considered permanent. Clients with link editing capabilities SHOULD
+ delete references to the Request-URI after user approval. If the
+ server does not know, or has no facility to determine, whether or not
+ the condition is permanent, the status code 404 (Not Found) SHOULD be
+ used instead. This response is cacheable unless indicated otherwise.
+
+ The 410 response is primarily intended to assist the task of web
+ maintenance by notifying the recipient that the resource is
+ intentionally unavailable and that the server owners desire that
+ remote links to that resource be removed. Such an event is common for
+ limited-time, promotional services and for resources belonging to
+ individuals no longer working at the server's site. It is not
+ necessary to mark all permanently unavailable resources as "gone" or
+ to keep the mark for any length of time -- that is left to the
+ discretion of the server owner.
+
+10.4.12 411 Length Required
+
+ The server refuses to accept the request without a defined Content-
+ Length. The client MAY repeat the request if it adds a valid
+ Content-Length header field containing the length of the message-body
+ in the request message.
+
+10.4.13 412 Precondition Failed
+
+ The precondition given in one or more of the request-header fields
+ evaluated to false when it was tested on the server. This response
+ code allows the client to place preconditions on the current resource
+ metainformation (header field data) and thus prevent the requested
+ method from being applied to a resource other than the one intended.
+
+
+
+Fielding, et al. Standards Track [Page 68]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.4.14 413 Request Entity Too Large
+
+ The server is refusing to process a request because the request
+ entity is larger than the server is willing or able to process. The
+ server MAY close the connection to prevent the client from continuing
+ the request.
+
+ If the condition is temporary, the server SHOULD include a Retry-
+ After header field to indicate that it is temporary and after what
+ time the client MAY try again.
+
+10.4.15 414 Request-URI Too Long
+
+ The server is refusing to service the request because the Request-URI
+ is longer than the server is willing to interpret. This rare
+ condition is only likely to occur when a client has improperly
+ converted a POST request to a GET request with long query
+ information, when the client has descended into a URI "black hole" of
+ redirection (e.g., a redirected URI prefix that points to a suffix of
+ itself), or when the server is under attack by a client attempting to
+ exploit security holes present in some servers using fixed-length
+ buffers for reading or manipulating the Request-URI.
+
+10.4.16 415 Unsupported Media Type
+
+ The server is refusing to service the request because the entity of
+ the request is in a format not supported by the requested resource
+ for the requested method.
+
+10.4.17 416 Requested Range Not Satisfiable
+
+ A server SHOULD return a response with this status code if a request
+ included a Range request-header field (section 14.35), and none of
+ the range-specifier values in this field overlap the current extent
+ of the selected resource, and the request did not include an If-Range
+ request-header field. (For byte-ranges, this means that the first-
+ byte-pos of all of the byte-range-spec values were greater than the
+ current length of the selected resource.)
+
+ When this status code is returned for a byte-range request, the
+ response SHOULD include a Content-Range entity-header field
+ specifying the current length of the selected resource (see section
+ 14.16). This response MUST NOT use the multipart/byteranges content-
+ type.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 69]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.4.18 417 Expectation Failed
+
+ The expectation given in an Expect request-header field (see section
+ 14.20) could not be met by this server, or, if the server is a proxy,
+ the server has unambiguous evidence that the request could not be met
+ by the next-hop server.
+
+10.5 Server Error 5xx
+
+ Response status codes beginning with the digit "5" indicate cases in
+ which the server is aware that it has erred or is incapable of
+ performing the request. Except when responding to a HEAD request, the
+ server SHOULD include an entity containing an explanation of the
+ error situation, and whether it is a temporary or permanent
+ condition. User agents SHOULD display any included entity to the
+ user. These response codes are applicable to any request method.
+
+10.5.1 500 Internal Server Error
+
+ The server encountered an unexpected condition which prevented it
+ from fulfilling the request.
+
+10.5.2 501 Not Implemented
+
+ The server does not support the functionality required to fulfill the
+ request. This is the appropriate response when the server does not
+ recognize the request method and is not capable of supporting it for
+ any resource.
+
+10.5.3 502 Bad Gateway
+
+ The server, while acting as a gateway or proxy, received an invalid
+ response from the upstream server it accessed in attempting to
+ fulfill the request.
+
+10.5.4 503 Service Unavailable
+
+ The server is currently unable to handle the request due to a
+ temporary overloading or maintenance of the server. The implication
+ is that this is a temporary condition which will be alleviated after
+ some delay. If known, the length of the delay MAY be indicated in a
+ Retry-After header. If no Retry-After is given, the client SHOULD
+ handle the response as it would for a 500 response.
+
+ Note: The existence of the 503 status code does not imply that a
+ server must use it when becoming overloaded. Some servers may wish
+ to simply refuse the connection.
+
+
+
+
+Fielding, et al. Standards Track [Page 70]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+10.5.5 504 Gateway Timeout
+
+ The server, while acting as a gateway or proxy, did not receive a
+ timely response from the upstream server specified by the URI (e.g.
+ HTTP, FTP, LDAP) or some other auxiliary server (e.g. DNS) it needed
+ to access in attempting to complete the request.
+
+ Note: Note to implementors: some deployed proxies are known to
+ return 400 or 500 when DNS lookups time out.
+
+10.5.6 505 HTTP Version Not Supported
+
+ The server does not support, or refuses to support, the HTTP protocol
+ version that was used in the request message. The server is
+ indicating that it is unable or unwilling to complete the request
+ using the same major version as the client, as described in section
+ 3.1, other than with this error message. The response SHOULD contain
+ an entity describing why that version is not supported and what other
+ protocols are supported by that server.
+
+11 Access Authentication
+
+ HTTP provides several OPTIONAL challenge-response authentication
+ mechanisms which can be used by a server to challenge a client
+ request and by a client to provide authentication information. The
+ general framework for access authentication, and the specification of
+ "basic" and "digest" authentication, are specified in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. This
+ specification adopts the definitions of "challenge" and "credentials"
+ from that specification.
+
+12 Content Negotiation
+
+ Most HTTP responses include an entity which contains information for
+ interpretation by a human user. Naturally, it is desirable to supply
+ the user with the "best available" entity corresponding to the
+ request. Unfortunately for servers and caches, not all users have the
+ same preferences for what is "best," and not all user agents are
+ equally capable of rendering all entity types. For that reason, HTTP
+ has provisions for several mechanisms for "content negotiation" --
+ the process of selecting the best representation for a given response
+ when there are multiple representations available.
+
+ Note: This is not called "format negotiation" because the
+ alternate representations may be of the same media type, but use
+ different capabilities of that type, be in different languages,
+ etc.
+
+
+
+
+Fielding, et al. Standards Track [Page 71]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Any response containing an entity-body MAY be subject to negotiation,
+ including error responses.
+
+ There are two kinds of content negotiation which are possible in
+ HTTP: server-driven and agent-driven negotiation. These two kinds of
+ negotiation are orthogonal and thus may be used separately or in
+ combination. One method of combination, referred to as transparent
+ negotiation, occurs when a cache uses the agent-driven negotiation
+ information provided by the origin server in order to provide
+ server-driven negotiation for subsequent requests.
+
+12.1 Server-driven Negotiation
+
+ If the selection of the best representation for a response is made by
+ an algorithm located at the server, it is called server-driven
+ negotiation. Selection is based on the available representations of
+ the response (the dimensions over which it can vary; e.g. language,
+ content-coding, etc.) and the contents of particular header fields in
+ the request message or on other information pertaining to the request
+ (such as the network address of the client).
+
+ Server-driven negotiation is advantageous when the algorithm for
+ selecting from among the available representations is difficult to
+ describe to the user agent, or when the server desires to send its
+ "best guess" to the client along with the first response (hoping to
+ avoid the round-trip delay of a subsequent request if the "best
+ guess" is good enough for the user). In order to improve the server's
+ guess, the user agent MAY include request header fields (Accept,
+ Accept-Language, Accept-Encoding, etc.) which describe its
+ preferences for such a response.
+
+ Server-driven negotiation has disadvantages:
+
+ 1. It is impossible for the server to accurately determine what
+ might be "best" for any given user, since that would require
+ complete knowledge of both the capabilities of the user agent
+ and the intended use for the response (e.g., does the user want
+ to view it on screen or print it on paper?).
+
+ 2. Having the user agent describe its capabilities in every
+ request can be both very inefficient (given that only a small
+ percentage of responses have multiple representations) and a
+ potential violation of the user's privacy.
+
+ 3. It complicates the implementation of an origin server and the
+ algorithms for generating responses to a request.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 72]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 4. It may limit a public cache's ability to use the same response
+ for multiple user's requests.
+
+ HTTP/1.1 includes the following request-header fields for enabling
+ server-driven negotiation through description of user agent
+ capabilities and user preferences: Accept (section 14.1), Accept-
+ Charset (section 14.2), Accept-Encoding (section 14.3), Accept-
+ Language (section 14.4), and User-Agent (section 14.43). However, an
+ origin server is not limited to these dimensions and MAY vary the
+ response based on any aspect of the request, including information
+ outside the request-header fields or within extension header fields
+ not defined by this specification.
+
+ The Vary header field can be used to express the parameters the
+ server uses to select a representation that is subject to server-
+ driven negotiation. See section 13.6 for use of the Vary header field
+ by caches and section 14.44 for use of the Vary header field by
+ servers.
+
+12.2 Agent-driven Negotiation
+
+ With agent-driven negotiation, selection of the best representation
+ for a response is performed by the user agent after receiving an
+ initial response from the origin server. Selection is based on a list
+ of the available representations of the response included within the
+ header fields or entity-body of the initial response, with each
+ representation identified by its own URI. Selection from among the
+ representations may be performed automatically (if the user agent is
+ capable of doing so) or manually by the user selecting from a
+ generated (possibly hypertext) menu.
+
+ Agent-driven negotiation is advantageous when the response would vary
+ over commonly-used dimensions (such as type, language, or encoding),
+ when the origin server is unable to determine a user agent's
+ capabilities from examining the request, and generally when public
+ caches are used to distribute server load and reduce network usage.
+
+ Agent-driven negotiation suffers from the disadvantage of needing a
+ second request to obtain the best alternate representation. This
+ second request is only efficient when caching is used. In addition,
+ this specification does not define any mechanism for supporting
+ automatic selection, though it also does not prevent any such
+ mechanism from being developed as an extension and used within
+ HTTP/1.1.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 73]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ HTTP/1.1 defines the 300 (Multiple Choices) and 406 (Not Acceptable)
+ status codes for enabling agent-driven negotiation when the server is
+ unwilling or unable to provide a varying response using server-driven
+ negotiation.
+
+12.3 Transparent Negotiation
+
+ Transparent negotiation is a combination of both server-driven and
+ agent-driven negotiation. When a cache is supplied with a form of the
+ list of available representations of the response (as in agent-driven
+ negotiation) and the dimensions of variance are completely understood
+ by the cache, then the cache becomes capable of performing server-
+ driven negotiation on behalf of the origin server for subsequent
+ requests on that resource.
+
+ Transparent negotiation has the advantage of distributing the
+ negotiation work that would otherwise be required of the origin
+ server and also removing the second request delay of agent-driven
+ negotiation when the cache is able to correctly guess the right
+ response.
+
+ This specification does not define any mechanism for transparent
+ negotiation, though it also does not prevent any such mechanism from
+ being developed as an extension that could be used within HTTP/1.1.
+
+13 Caching in HTTP
+
+ HTTP is typically used for distributed information systems, where
+ performance can be improved by the use of response caches. The
+ HTTP/1.1 protocol includes a number of elements intended to make
+ caching work as well as possible. Because these elements are
+ inextricable from other aspects of the protocol, and because they
+ interact with each other, it is useful to describe the basic caching
+ design of HTTP separately from the detailed descriptions of methods,
+ headers, response codes, etc.
+
+ Caching would be useless if it did not significantly improve
+ performance. The goal of caching in HTTP/1.1 is to eliminate the need
+ to send requests in many cases, and to eliminate the need to send
+ full responses in many other cases. The former reduces the number of
+ network round-trips required for many operations; we use an
+ "expiration" mechanism for this purpose (see section 13.2). The
+ latter reduces network bandwidth requirements; we use a "validation"
+ mechanism for this purpose (see section 13.3).
+
+ Requirements for performance, availability, and disconnected
+ operation require us to be able to relax the goal of semantic
+ transparency. The HTTP/1.1 protocol allows origin servers, caches,
+
+
+
+Fielding, et al. Standards Track [Page 74]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ and clients to explicitly reduce transparency when necessary.
+ However, because non-transparent operation may confuse non-expert
+ users, and might be incompatible with certain server applications
+ (such as those for ordering merchandise), the protocol requires that
+ transparency be relaxed
+
+ - only by an explicit protocol-level request when relaxed by
+ client or origin server
+
+ - only with an explicit warning to the end user when relaxed by
+ cache or client
+
+ Therefore, the HTTP/1.1 protocol provides these important elements:
+
+ 1. Protocol features that provide full semantic transparency when
+ this is required by all parties.
+
+ 2. Protocol features that allow an origin server or user agent to
+ explicitly request and control non-transparent operation.
+
+ 3. Protocol features that allow a cache to attach warnings to
+ responses that do not preserve the requested approximation of
+ semantic transparency.
+
+ A basic principle is that it must be possible for the clients to
+ detect any potential relaxation of semantic transparency.
+
+ Note: The server, cache, or client implementor might be faced with
+ design decisions not explicitly discussed in this specification.
+ If a decision might affect semantic transparency, the implementor
+ ought to err on the side of maintaining transparency unless a
+ careful and complete analysis shows significant benefits in
+ breaking transparency.
+
+13.1.1 Cache Correctness
+
+ A correct cache MUST respond to a request with the most up-to-date
+ response held by the cache that is appropriate to the request (see
+ sections 13.2.5, 13.2.6, and 13.12) which meets one of the following
+ conditions:
+
+ 1. It has been checked for equivalence with what the origin server
+ would have returned by revalidating the response with the
+ origin server (section 13.3);
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 75]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 2. It is "fresh enough" (see section 13.2). In the default case,
+ this means it meets the least restrictive freshness requirement
+ of the client, origin server, and cache (see section 14.9); if
+ the origin server so specifies, it is the freshness requirement
+ of the origin server alone.
+
+ If a stored response is not "fresh enough" by the most
+ restrictive freshness requirement of both the client and the
+ origin server, in carefully considered circumstances the cache
+ MAY still return the response with the appropriate Warning
+ header (see section 13.1.5 and 14.46), unless such a response
+ is prohibited (e.g., by a "no-store" cache-directive, or by a
+ "no-cache" cache-request-directive; see section 14.9).
+
+ 3. It is an appropriate 304 (Not Modified), 305 (Proxy Redirect),
+ or error (4xx or 5xx) response message.
+
+ If the cache can not communicate with the origin server, then a
+ correct cache SHOULD respond as above if the response can be
+ correctly served from the cache; if not it MUST return an error or
+ warning indicating that there was a communication failure.
+
+ If a cache receives a response (either an entire response, or a 304
+ (Not Modified) response) that it would normally forward to the
+ requesting client, and the received response is no longer fresh, the
+ cache SHOULD forward it to the requesting client without adding a new
+ Warning (but without removing any existing Warning headers). A cache
+ SHOULD NOT attempt to revalidate a response simply because that
+ response became stale in transit; this might lead to an infinite
+ loop. A user agent that receives a stale response without a Warning
+ MAY display a warning indication to the user.
+
+13.1.2 Warnings
+
+ Whenever a cache returns a response that is neither first-hand nor
+ "fresh enough" (in the sense of condition 2 in section 13.1.1), it
+ MUST attach a warning to that effect, using a Warning general-header.
+ The Warning header and the currently defined warnings are described
+ in section 14.46. The warning allows clients to take appropriate
+ action.
+
+ Warnings MAY be used for other purposes, both cache-related and
+ otherwise. The use of a warning, rather than an error status code,
+ distinguish these responses from true failures.
+
+ Warnings are assigned three digit warn-codes. The first digit
+ indicates whether the Warning MUST or MUST NOT be deleted from a
+ stored cache entry after a successful revalidation:
+
+
+
+Fielding, et al. Standards Track [Page 76]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 1xx Warnings that describe the freshness or revalidation status of
+ the response, and so MUST be deleted after a successful
+ revalidation. 1XX warn-codes MAY be generated by a cache only when
+ validating a cached entry. It MUST NOT be generated by clients.
+
+ 2xx Warnings that describe some aspect of the entity body or entity
+ headers that is not rectified by a revalidation (for example, a
+ lossy compression of the entity bodies) and which MUST NOT be
+ deleted after a successful revalidation.
+
+ See section 14.46 for the definitions of the codes themselves.
+
+ HTTP/1.0 caches will cache all Warnings in responses, without
+ deleting the ones in the first category. Warnings in responses that
+ are passed to HTTP/1.0 caches carry an extra warning-date field,
+ which prevents a future HTTP/1.1 recipient from believing an
+ erroneously cached Warning.
+
+ Warnings also carry a warning text. The text MAY be in any
+ appropriate natural language (perhaps based on the client's Accept
+ headers), and include an OPTIONAL indication of what character set is
+ used.
+
+ Multiple warnings MAY be attached to a response (either by the origin
+ server or by a cache), including multiple warnings with the same code
+ number. For example, a server might provide the same warning with
+ texts in both English and Basque.
+
+ When multiple warnings are attached to a response, it might not be
+ practical or reasonable to display all of them to the user. This
+ version of HTTP does not specify strict priority rules for deciding
+ which warnings to display and in what order, but does suggest some
+ heuristics.
+
+13.1.3 Cache-control Mechanisms
+
+ The basic cache mechanisms in HTTP/1.1 (server-specified expiration
+ times and validators) are implicit directives to caches. In some
+ cases, a server or client might need to provide explicit directives
+ to the HTTP caches. We use the Cache-Control header for this purpose.
+
+ The Cache-Control header allows a client or server to transmit a
+ variety of directives in either requests or responses. These
+ directives typically override the default caching algorithms. As a
+ general rule, if there is any apparent conflict between header
+ values, the most restrictive interpretation is applied (that is, the
+ one that is most likely to preserve semantic transparency). However,
+
+
+
+
+Fielding, et al. Standards Track [Page 77]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ in some cases, cache-control directives are explicitly specified as
+ weakening the approximation of semantic transparency (for example,
+ "max-stale" or "public").
+
+ The cache-control directives are described in detail in section 14.9.
+
+13.1.4 Explicit User Agent Warnings
+
+ Many user agents make it possible for users to override the basic
+ caching mechanisms. For example, the user agent might allow the user
+ to specify that cached entities (even explicitly stale ones) are
+ never validated. Or the user agent might habitually add "Cache-
+ Control: max-stale=3600" to every request. The user agent SHOULD NOT
+ default to either non-transparent behavior, or behavior that results
+ in abnormally ineffective caching, but MAY be explicitly configured
+ to do so by an explicit action of the user.
+
+ If the user has overridden the basic caching mechanisms, the user
+ agent SHOULD explicitly indicate to the user whenever this results in
+ the display of information that might not meet the server's
+ transparency requirements (in particular, if the displayed entity is
+ known to be stale). Since the protocol normally allows the user agent
+ to determine if responses are stale or not, this indication need only
+ be displayed when this actually happens. The indication need not be a
+ dialog box; it could be an icon (for example, a picture of a rotting
+ fish) or some other indicator.
+
+ If the user has overridden the caching mechanisms in a way that would
+ abnormally reduce the effectiveness of caches, the user agent SHOULD
+ continually indicate this state to the user (for example, by a
+ display of a picture of currency in flames) so that the user does not
+ inadvertently consume excess resources or suffer from excessive
+ latency.
+
+13.1.5 Exceptions to the Rules and Warnings
+
+ In some cases, the operator of a cache MAY choose to configure it to
+ return stale responses even when not requested by clients. This
+ decision ought not be made lightly, but may be necessary for reasons
+ of availability or performance, especially when the cache is poorly
+ connected to the origin server. Whenever a cache returns a stale
+ response, it MUST mark it as such (using a Warning header) enabling
+ the client software to alert the user that there might be a potential
+ problem.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 78]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ It also allows the user agent to take steps to obtain a first-hand or
+ fresh response. For this reason, a cache SHOULD NOT return a stale
+ response if the client explicitly requests a first-hand or fresh one,
+ unless it is impossible to comply for technical or policy reasons.
+
+13.1.6 Client-controlled Behavior
+
+ While the origin server (and to a lesser extent, intermediate caches,
+ by their contribution to the age of a response) are the primary
+ source of expiration information, in some cases the client might need
+ to control a cache's decision about whether to return a cached
+ response without validating it. Clients do this using several
+ directives of the Cache-Control header.
+
+ A client's request MAY specify the maximum age it is willing to
+ accept of an unvalidated response; specifying a value of zero forces
+ the cache(s) to revalidate all responses. A client MAY also specify
+ the minimum time remaining before a response expires. Both of these
+ options increase constraints on the behavior of caches, and so cannot
+ further relax the cache's approximation of semantic transparency.
+
+ A client MAY also specify that it will accept stale responses, up to
+ some maximum amount of staleness. This loosens the constraints on the
+ caches, and so might violate the origin server's specified
+ constraints on semantic transparency, but might be necessary to
+ support disconnected operation, or high availability in the face of
+ poor connectivity.
+
+13.2 Expiration Model
+
+13.2.1 Server-Specified Expiration
+
+ HTTP caching works best when caches can entirely avoid making
+ requests to the origin server. The primary mechanism for avoiding
+ requests is for an origin server to provide an explicit expiration
+ time in the future, indicating that a response MAY be used to satisfy
+ subsequent requests. In other words, a cache can return a fresh
+ response without first contacting the server.
+
+ Our expectation is that servers will assign future explicit
+ expiration times to responses in the belief that the entity is not
+ likely to change, in a semantically significant way, before the
+ expiration time is reached. This normally preserves semantic
+ transparency, as long as the server's expiration times are carefully
+ chosen.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 79]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The expiration mechanism applies only to responses taken from a cache
+ and not to first-hand responses forwarded immediately to the
+ requesting client.
+
+ If an origin server wishes to force a semantically transparent cache
+ to validate every request, it MAY assign an explicit expiration time
+ in the past. This means that the response is always stale, and so the
+ cache SHOULD validate it before using it for subsequent requests. See
+ section 14.9.4 for a more restrictive way to force revalidation.
+
+ If an origin server wishes to force any HTTP/1.1 cache, no matter how
+ it is configured, to validate every request, it SHOULD use the "must-
+ revalidate" cache-control directive (see section 14.9).
+
+ Servers specify explicit expiration times using either the Expires
+ header, or the max-age directive of the Cache-Control header.
+
+ An expiration time cannot be used to force a user agent to refresh
+ its display or reload a resource; its semantics apply only to caching
+ mechanisms, and such mechanisms need only check a resource's
+ expiration status when a new request for that resource is initiated.
+ See section 13.13 for an explanation of the difference between caches
+ and history mechanisms.
+
+13.2.2 Heuristic Expiration
+
+ Since origin servers do not always provide explicit expiration times,
+ HTTP caches typically assign heuristic expiration times, employing
+ algorithms that use other header values (such as the Last-Modified
+ time) to estimate a plausible expiration time. The HTTP/1.1
+ specification does not provide specific algorithms, but does impose
+ worst-case constraints on their results. Since heuristic expiration
+ times might compromise semantic transparency, they ought to used
+ cautiously, and we encourage origin servers to provide explicit
+ expiration times as much as possible.
+
+13.2.3 Age Calculations
+
+ In order to know if a cached entry is fresh, a cache needs to know if
+ its age exceeds its freshness lifetime. We discuss how to calculate
+ the latter in section 13.2.4; this section describes how to calculate
+ the age of a response or cache entry.
+
+ In this discussion, we use the term "now" to mean "the current value
+ of the clock at the host performing the calculation." Hosts that use
+ HTTP, but especially hosts running origin servers and caches, SHOULD
+ use NTP [28] or some similar protocol to synchronize their clocks to
+ a globally accurate time standard.
+
+
+
+Fielding, et al. Standards Track [Page 80]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ HTTP/1.1 requires origin servers to send a Date header, if possible,
+ with every response, giving the time at which the response was
+ generated (see section 14.18). We use the term "date_value" to denote
+ the value of the Date header, in a form appropriate for arithmetic
+ operations.
+
+ HTTP/1.1 uses the Age response-header to convey the estimated age of
+ the response message when obtained from a cache. The Age field value
+ is the cache's estimate of the amount of time since the response was
+ generated or revalidated by the origin server.
+
+ In essence, the Age value is the sum of the time that the response
+ has been resident in each of the caches along the path from the
+ origin server, plus the amount of time it has been in transit along
+ network paths.
+
+ We use the term "age_value" to denote the value of the Age header, in
+ a form appropriate for arithmetic operations.
+
+ A response's age can be calculated in two entirely independent ways:
+
+ 1. now minus date_value, if the local clock is reasonably well
+ synchronized to the origin server's clock. If the result is
+ negative, the result is replaced by zero.
+
+ 2. age_value, if all of the caches along the response path
+ implement HTTP/1.1.
+
+ Given that we have two independent ways to compute the age of a
+ response when it is received, we can combine these as
+
+ corrected_received_age = max(now - date_value, age_value)
+
+ and as long as we have either nearly synchronized clocks or all-
+ HTTP/1.1 paths, one gets a reliable (conservative) result.
+
+ Because of network-imposed delays, some significant interval might
+ pass between the time that a server generates a response and the time
+ it is received at the next outbound cache or client. If uncorrected,
+ this delay could result in improperly low ages.
+
+ Because the request that resulted in the returned Age value must have
+ been initiated prior to that Age value's generation, we can correct
+ for delays imposed by the network by recording the time at which the
+ request was initiated. Then, when an Age value is received, it MUST
+ be interpreted relative to the time the request was initiated, not
+
+
+
+
+
+Fielding, et al. Standards Track [Page 81]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ the time that the response was received. This algorithm results in
+ conservative behavior no matter how much delay is experienced. So, we
+ compute:
+
+ corrected_initial_age = corrected_received_age
+ + (now - request_time)
+
+ where "request_time" is the time (according to the local clock) when
+ the request that elicited this response was sent.
+
+ Summary of age calculation algorithm, when a cache receives a
+ response:
+
+ /*
+ * age_value
+ * is the value of Age: header received by the cache with
+ * this response.
+ * date_value
+ * is the value of the origin server's Date: header
+ * request_time
+ * is the (local) time when the cache made the request
+ * that resulted in this cached response
+ * response_time
+ * is the (local) time when the cache received the
+ * response
+ * now
+ * is the current (local) time
+ */
+
+ apparent_age = max(0, response_time - date_value);
+ corrected_received_age = max(apparent_age, age_value);
+ response_delay = response_time - request_time;
+ corrected_initial_age = corrected_received_age + response_delay;
+ resident_time = now - response_time;
+ current_age = corrected_initial_age + resident_time;
+
+ The current_age of a cache entry is calculated by adding the amount
+ of time (in seconds) since the cache entry was last validated by the
+ origin server to the corrected_initial_age. When a response is
+ generated from a cache entry, the cache MUST include a single Age
+ header field in the response with a value equal to the cache entry's
+ current_age.
+
+ The presence of an Age header field in a response implies that a
+ response is not first-hand. However, the converse is not true, since
+ the lack of an Age header field in a response does not imply that the
+
+
+
+
+
+Fielding, et al. Standards Track [Page 82]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ response is first-hand unless all caches along the request path are
+ compliant with HTTP/1.1 (i.e., older HTTP caches did not implement
+ the Age header field).
+
+13.2.4 Expiration Calculations
+
+ In order to decide whether a response is fresh or stale, we need to
+ compare its freshness lifetime to its age. The age is calculated as
+ described in section 13.2.3; this section describes how to calculate
+ the freshness lifetime, and to determine if a response has expired.
+ In the discussion below, the values can be represented in any form
+ appropriate for arithmetic operations.
+
+ We use the term "expires_value" to denote the value of the Expires
+ header. We use the term "max_age_value" to denote an appropriate
+ value of the number of seconds carried by the "max-age" directive of
+ the Cache-Control header in a response (see section 14.9.3).
+
+ The max-age directive takes priority over Expires, so if max-age is
+ present in a response, the calculation is simply:
+
+ freshness_lifetime = max_age_value
+
+ Otherwise, if Expires is present in the response, the calculation is:
+
+ freshness_lifetime = expires_value - date_value
+
+ Note that neither of these calculations is vulnerable to clock skew,
+ since all of the information comes from the origin server.
+
+ If none of Expires, Cache-Control: max-age, or Cache-Control: s-
+ maxage (see section 14.9.3) appears in the response, and the response
+ does not include other restrictions on caching, the cache MAY compute
+ a freshness lifetime using a heuristic. The cache MUST attach Warning
+ 113 to any response whose age is more than 24 hours if such warning
+ has not already been added.
+
+ Also, if the response does have a Last-Modified time, the heuristic
+ expiration value SHOULD be no more than some fraction of the interval
+ since that time. A typical setting of this fraction might be 10%.
+
+ The calculation to determine if a response has expired is quite
+ simple:
+
+ response_is_fresh = (freshness_lifetime > current_age)
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 83]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.2.5 Disambiguating Expiration Values
+
+ Because expiration values are assigned optimistically, it is possible
+ for two caches to contain fresh values for the same resource that are
+ different.
+
+ If a client performing a retrieval receives a non-first-hand response
+ for a request that was already fresh in its own cache, and the Date
+ header in its existing cache entry is newer than the Date on the new
+ response, then the client MAY ignore the response. If so, it MAY
+ retry the request with a "Cache-Control: max-age=0" directive (see
+ section 14.9), to force a check with the origin server.
+
+ If a cache has two fresh responses for the same representation with
+ different validators, it MUST use the one with the more recent Date
+ header. This situation might arise because the cache is pooling
+ responses from other caches, or because a client has asked for a
+ reload or a revalidation of an apparently fresh cache entry.
+
+13.2.6 Disambiguating Multiple Responses
+
+ Because a client might be receiving responses via multiple paths, so
+ that some responses flow through one set of caches and other
+ responses flow through a different set of caches, a client might
+ receive responses in an order different from that in which the origin
+ server sent them. We would like the client to use the most recently
+ generated response, even if older responses are still apparently
+ fresh.
+
+ Neither the entity tag nor the expiration value can impose an
+ ordering on responses, since it is possible that a later response
+ intentionally carries an earlier expiration time. The Date values are
+ ordered to a granularity of one second.
+
+ When a client tries to revalidate a cache entry, and the response it
+ receives contains a Date header that appears to be older than the one
+ for the existing entry, then the client SHOULD repeat the request
+ unconditionally, and include
+
+ Cache-Control: max-age=0
+
+ to force any intermediate caches to validate their copies directly
+ with the origin server, or
+
+ Cache-Control: no-cache
+
+ to force any intermediate caches to obtain a new copy from the origin
+ server.
+
+
+
+Fielding, et al. Standards Track [Page 84]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If the Date values are equal, then the client MAY use either response
+ (or MAY, if it is being extremely prudent, request a new response).
+ Servers MUST NOT depend on clients being able to choose
+ deterministically between responses generated during the same second,
+ if their expiration times overlap.
+
+13.3 Validation Model
+
+ When a cache has a stale entry that it would like to use as a
+ response to a client's request, it first has to check with the origin
+ server (or possibly an intermediate cache with a fresh response) to
+ see if its cached entry is still usable. We call this "validating"
+ the cache entry. Since we do not want to have to pay the overhead of
+ retransmitting the full response if the cached entry is good, and we
+ do not want to pay the overhead of an extra round trip if the cached
+ entry is invalid, the HTTP/1.1 protocol supports the use of
+ conditional methods.
+
+ The key protocol features for supporting conditional methods are
+ those concerned with "cache validators." When an origin server
+ generates a full response, it attaches some sort of validator to it,
+ which is kept with the cache entry. When a client (user agent or
+ proxy cache) makes a conditional request for a resource for which it
+ has a cache entry, it includes the associated validator in the
+ request.
+
+ The server then checks that validator against the current validator
+ for the entity, and, if they match (see section 13.3.3), it responds
+ with a special status code (usually, 304 (Not Modified)) and no
+ entity-body. Otherwise, it returns a full response (including
+ entity-body). Thus, we avoid transmitting the full response if the
+ validator matches, and we avoid an extra round trip if it does not
+ match.
+
+ In HTTP/1.1, a conditional request looks exactly the same as a normal
+ request for the same resource, except that it carries a special
+ header (which includes the validator) that implicitly turns the
+ method (usually, GET) into a conditional.
+
+ The protocol includes both positive and negative senses of cache-
+ validating conditions. That is, it is possible to request either that
+ a method be performed if and only if a validator matches or if and
+ only if no validators match.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 85]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Note: a response that lacks a validator may still be cached, and
+ served from cache until it expires, unless this is explicitly
+ prohibited by a cache-control directive. However, a cache cannot
+ do a conditional retrieval if it does not have a validator for the
+ entity, which means it will not be refreshable after it expires.
+
+13.3.1 Last-Modified Dates
+
+ The Last-Modified entity-header field value is often used as a cache
+ validator. In simple terms, a cache entry is considered to be valid
+ if the entity has not been modified since the Last-Modified value.
+
+13.3.2 Entity Tag Cache Validators
+
+ The ETag response-header field value, an entity tag, provides for an
+ "opaque" cache validator. This might allow more reliable validation
+ in situations where it is inconvenient to store modification dates,
+ where the one-second resolution of HTTP date values is not
+ sufficient, or where the origin server wishes to avoid certain
+ paradoxes that might arise from the use of modification dates.
+
+ Entity Tags are described in section 3.11. The headers used with
+ entity tags are described in sections 14.19, 14.24, 14.26 and 14.44.
+
+13.3.3 Weak and Strong Validators
+
+ Since both origin servers and caches will compare two validators to
+ decide if they represent the same or different entities, one normally
+ would expect that if the entity (the entity-body or any entity-
+ headers) changes in any way, then the associated validator would
+ change as well. If this is true, then we call this validator a
+ "strong validator."
+
+ However, there might be cases when a server prefers to change the
+ validator only on semantically significant changes, and not when
+ insignificant aspects of the entity change. A validator that does not
+ always change when the resource changes is a "weak validator."
+
+ Entity tags are normally "strong validators," but the protocol
+ provides a mechanism to tag an entity tag as "weak." One can think of
+ a strong validator as one that changes whenever the bits of an entity
+ changes, while a weak value changes whenever the meaning of an entity
+ changes. Alternatively, one can think of a strong validator as part
+ of an identifier for a specific entity, while a weak validator is
+ part of an identifier for a set of semantically equivalent entities.
+
+ Note: One example of a strong validator is an integer that is
+ incremented in stable storage every time an entity is changed.
+
+
+
+Fielding, et al. Standards Track [Page 86]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ An entity's modification time, if represented with one-second
+ resolution, could be a weak validator, since it is possible that
+ the resource might be modified twice during a single second.
+
+ Support for weak validators is optional. However, weak validators
+ allow for more efficient caching of equivalent objects; for
+ example, a hit counter on a site is probably good enough if it is
+ updated every few days or weeks, and any value during that period
+ is likely "good enough" to be equivalent.
+
+ A "use" of a validator is either when a client generates a request
+ and includes the validator in a validating header field, or when a
+ server compares two validators.
+
+ Strong validators are usable in any context. Weak validators are only
+ usable in contexts that do not depend on exact equality of an entity.
+ For example, either kind is usable for a conditional GET of a full
+ entity. However, only a strong validator is usable for a sub-range
+ retrieval, since otherwise the client might end up with an internally
+ inconsistent entity.
+
+ Clients MAY issue simple (non-subrange) GET requests with either weak
+ validators or strong validators. Clients MUST NOT use weak validators
+ in other forms of request.
+
+ The only function that the HTTP/1.1 protocol defines on validators is
+ comparison. There are two validator comparison functions, depending
+ on whether the comparison context allows the use of weak validators
+ or not:
+
+ - The strong comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, and both MUST
+ NOT be weak.
+
+ - The weak comparison function: in order to be considered equal,
+ both validators MUST be identical in every way, but either or
+ both of them MAY be tagged as "weak" without affecting the
+ result.
+
+ An entity tag is strong unless it is explicitly tagged as weak.
+ Section 3.11 gives the syntax for entity tags.
+
+ A Last-Modified time, when used as a validator in a request, is
+ implicitly weak unless it is possible to deduce that it is strong,
+ using the following rules:
+
+ - The validator is being compared by an origin server to the
+ actual current validator for the entity and,
+
+
+
+Fielding, et al. Standards Track [Page 87]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - That origin server reliably knows that the associated entity did
+ not change twice during the second covered by the presented
+ validator.
+
+ or
+
+ - The validator is about to be used by a client in an If-
+ Modified-Since or If-Unmodified-Since header, because the client
+ has a cache entry for the associated entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ or
+
+ - The validator is being compared by an intermediate cache to the
+ validator stored in its cache entry for the entity, and
+
+ - That cache entry includes a Date value, which gives the time
+ when the origin server sent the original response, and
+
+ - The presented Last-Modified time is at least 60 seconds before
+ the Date value.
+
+ This method relies on the fact that if two different responses were
+ sent by the origin server during the same second, but both had the
+ same Last-Modified time, then at least one of those responses would
+ have a Date value equal to its Last-Modified time. The arbitrary 60-
+ second limit guards against the possibility that the Date and Last-
+ Modified values are generated from different clocks, or at somewhat
+ different times during the preparation of the response. An
+ implementation MAY use a value larger than 60 seconds, if it is
+ believed that 60 seconds is too short.
+
+ If a client wishes to perform a sub-range retrieval on a value for
+ which it has only a Last-Modified time and no opaque validator, it
+ MAY do this only if the Last-Modified time is strong in the sense
+ described here.
+
+ A cache or origin server receiving a conditional request, other than
+ a full-body GET request, MUST use the strong comparison function to
+ evaluate the condition.
+
+ These rules allow HTTP/1.1 caches and clients to safely perform sub-
+ range retrievals on values that have been obtained from HTTP/1.0
+
+
+
+Fielding, et al. Standards Track [Page 88]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ servers.
+
+13.3.4 Rules for When to Use Entity Tags and Last-Modified Dates
+
+ We adopt a set of rules and recommendations for origin servers,
+ clients, and caches regarding when various validator types ought to
+ be used, and for what purposes.
+
+ HTTP/1.1 origin servers:
+
+ - SHOULD send an entity tag validator unless it is not feasible to
+ generate one.
+
+ - MAY send a weak entity tag instead of a strong entity tag, if
+ performance considerations support the use of weak entity tags,
+ or if it is unfeasible to send a strong entity tag.
+
+ - SHOULD send a Last-Modified value if it is feasible to send one,
+ unless the risk of a breakdown in semantic transparency that
+ could result from using this date in an If-Modified-Since header
+ would lead to serious problems.
+
+ In other words, the preferred behavior for an HTTP/1.1 origin server
+ is to send both a strong entity tag and a Last-Modified value.
+
+ In order to be legal, a strong entity tag MUST change whenever the
+ associated entity value changes in any way. A weak entity tag SHOULD
+ change whenever the associated entity changes in a semantically
+ significant way.
+
+ Note: in order to provide semantically transparent caching, an
+ origin server must avoid reusing a specific strong entity tag
+ value for two different entities, or reusing a specific weak
+ entity tag value for two semantically different entities. Cache
+ entries might persist for arbitrarily long periods, regardless of
+ expiration times, so it might be inappropriate to expect that a
+ cache will never again attempt to validate an entry using a
+ validator that it obtained at some point in the past.
+
+ HTTP/1.1 clients:
+
+ - If an entity tag has been provided by the origin server, MUST
+ use that entity tag in any cache-conditional request (using If-
+ Match or If-None-Match).
+
+ - If only a Last-Modified value has been provided by the origin
+ server, SHOULD use that value in non-subrange cache-conditional
+ requests (using If-Modified-Since).
+
+
+
+Fielding, et al. Standards Track [Page 89]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - If only a Last-Modified value has been provided by an HTTP/1.0
+ origin server, MAY use that value in subrange cache-conditional
+ requests (using If-Unmodified-Since:). The user agent SHOULD
+ provide a way to disable this, in case of difficulty.
+
+ - If both an entity tag and a Last-Modified value have been
+ provided by the origin server, SHOULD use both validators in
+ cache-conditional requests. This allows both HTTP/1.0 and
+ HTTP/1.1 caches to respond appropriately.
+
+ An HTTP/1.1 origin server, upon receiving a conditional request that
+ includes both a Last-Modified date (e.g., in an If-Modified-Since or
+ If-Unmodified-Since header field) and one or more entity tags (e.g.,
+ in an If-Match, If-None-Match, or If-Range header field) as cache
+ validators, MUST NOT return a response status of 304 (Not Modified)
+ unless doing so is consistent with all of the conditional header
+ fields in the request.
+
+ An HTTP/1.1 caching proxy, upon receiving a conditional request that
+ includes both a Last-Modified date and one or more entity tags as
+ cache validators, MUST NOT return a locally cached response to the
+ client unless that cached response is consistent with all of the
+ conditional header fields in the request.
+
+ Note: The general principle behind these rules is that HTTP/1.1
+ servers and clients should transmit as much non-redundant
+ information as is available in their responses and requests.
+ HTTP/1.1 systems receiving this information will make the most
+ conservative assumptions about the validators they receive.
+
+ HTTP/1.0 clients and caches will ignore entity tags. Generally,
+ last-modified values received or used by these systems will
+ support transparent and efficient caching, and so HTTP/1.1 origin
+ servers should provide Last-Modified values. In those rare cases
+ where the use of a Last-Modified value as a validator by an
+ HTTP/1.0 system could result in a serious problem, then HTTP/1.1
+ origin servers should not provide one.
+
+13.3.5 Non-validating Conditionals
+
+ The principle behind entity tags is that only the service author
+ knows the semantics of a resource well enough to select an
+ appropriate cache validation mechanism, and the specification of any
+ validator comparison function more complex than byte-equality would
+ open up a can of worms. Thus, comparisons of any other headers
+ (except Last-Modified, for compatibility with HTTP/1.0) are never
+ used for purposes of validating a cache entry.
+
+
+
+
+Fielding, et al. Standards Track [Page 90]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.4 Response Cacheability
+
+ Unless specifically constrained by a cache-control (section 14.9)
+ directive, a caching system MAY always store a successful response
+ (see section 13.8) as a cache entry, MAY return it without validation
+ if it is fresh, and MAY return it after successful validation. If
+ there is neither a cache validator nor an explicit expiration time
+ associated with a response, we do not expect it to be cached, but
+ certain caches MAY violate this expectation (for example, when little
+ or no network connectivity is available). A client can usually detect
+ that such a response was taken from a cache by comparing the Date
+ header to the current time.
+
+ Note: some HTTP/1.0 caches are known to violate this expectation
+ without providing any Warning.
+
+ However, in some cases it might be inappropriate for a cache to
+ retain an entity, or to return it in response to a subsequent
+ request. This might be because absolute semantic transparency is
+ deemed necessary by the service author, or because of security or
+ privacy considerations. Certain cache-control directives are
+ therefore provided so that the server can indicate that certain
+ resource entities, or portions thereof, are not to be cached
+ regardless of other considerations.
+
+ Note that section 14.8 normally prevents a shared cache from saving
+ and returning a response to a previous request if that request
+ included an Authorization header.
+
+ A response received with a status code of 200, 203, 206, 300, 301 or
+ 410 MAY be stored by a cache and used in reply to a subsequent
+ request, subject to the expiration mechanism, unless a cache-control
+ directive prohibits caching. However, a cache that does not support
+ the Range and Content-Range headers MUST NOT cache 206 (Partial
+ Content) responses.
+
+ A response received with any other status code (e.g. status codes 302
+ and 307) MUST NOT be returned in a reply to a subsequent request
+ unless there are cache-control directives or another header(s) that
+ explicitly allow it. For example, these include the following: an
+ Expires header (section 14.21); a "max-age", "s-maxage", "must-
+ revalidate", "proxy-revalidate", "public" or "private" cache-control
+ directive (section 14.9).
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 91]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.5 Constructing Responses From Caches
+
+ The purpose of an HTTP cache is to store information received in
+ response to requests for use in responding to future requests. In
+ many cases, a cache simply returns the appropriate parts of a
+ response to the requester. However, if the cache holds a cache entry
+ based on a previous response, it might have to combine parts of a new
+ response with what is held in the cache entry.
+
+13.5.1 End-to-end and Hop-by-hop Headers
+
+ For the purpose of defining the behavior of caches and non-caching
+ proxies, we divide HTTP headers into two categories:
+
+ - End-to-end headers, which are transmitted to the ultimate
+ recipient of a request or response. End-to-end headers in
+ responses MUST be stored as part of a cache entry and MUST be
+ transmitted in any response formed from a cache entry.
+
+ - Hop-by-hop headers, which are meaningful only for a single
+ transport-level connection, and are not stored by caches or
+ forwarded by proxies.
+
+ The following HTTP/1.1 headers are hop-by-hop headers:
+
+ - Connection
+ - Keep-Alive
+ - Proxy-Authenticate
+ - Proxy-Authorization
+ - TE
+ - Trailers
+ - Transfer-Encoding
+ - Upgrade
+
+ All other headers defined by HTTP/1.1 are end-to-end headers.
+
+ Other hop-by-hop headers MUST be listed in a Connection header,
+ (section 14.10) to be introduced into HTTP/1.1 (or later).
+
+13.5.2 Non-modifiable Headers
+
+ Some features of the HTTP/1.1 protocol, such as Digest
+ Authentication, depend on the value of certain end-to-end headers. A
+ transparent proxy SHOULD NOT modify an end-to-end header unless the
+ definition of that header requires or specifically allows that.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 92]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ request or response, and it MUST NOT add any of these fields if not
+ already present:
+
+ - Content-Location
+
+ - Content-MD5
+
+ - ETag
+
+ - Last-Modified
+
+ A transparent proxy MUST NOT modify any of the following fields in a
+ response:
+
+ - Expires
+
+ but it MAY add any of these fields if not already present. If an
+ Expires header is added, it MUST be given a field-value identical to
+ that of the Date header in that response.
+
+ A proxy MUST NOT modify or add any of the following fields in a
+ message that contains the no-transform cache-control directive, or in
+ any request:
+
+ - Content-Encoding
+
+ - Content-Range
+
+ - Content-Type
+
+ A non-transparent proxy MAY modify or add these fields to a message
+ that does not include no-transform, but if it does so, it MUST add a
+ Warning 214 (Transformation applied) if one does not already appear
+ in the message (see section 14.46).
+
+ Warning: unnecessary modification of end-to-end headers might
+ cause authentication failures if stronger authentication
+ mechanisms are introduced in later versions of HTTP. Such
+ authentication mechanisms MAY rely on the values of header fields
+ not listed here.
+
+ The Content-Length field of a request or response is added or deleted
+ according to the rules in section 4.4. A transparent proxy MUST
+ preserve the entity-length (section 7.2.2) of the entity-body,
+ although it MAY change the transfer-length (section 4.4).
+
+
+
+
+
+Fielding, et al. Standards Track [Page 93]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.5.3 Combining Headers
+
+ When a cache makes a validating request to a server, and the server
+ provides a 304 (Not Modified) response or a 206 (Partial Content)
+ response, the cache then constructs a response to send to the
+ requesting client.
+
+ If the status code is 304 (Not Modified), the cache uses the entity-
+ body stored in the cache entry as the entity-body of this outgoing
+ response. If the status code is 206 (Partial Content) and the ETag or
+ Last-Modified headers match exactly, the cache MAY combine the
+ contents stored in the cache entry with the new contents received in
+ the response and use the result as the entity-body of this outgoing
+ response, (see 13.5.4).
+
+ The end-to-end headers stored in the cache entry are used for the
+ constructed response, except that
+
+ - any stored Warning headers with warn-code 1xx (see section
+ 14.46) MUST be deleted from the cache entry and the forwarded
+ response.
+
+ - any stored Warning headers with warn-code 2xx MUST be retained
+ in the cache entry and the forwarded response.
+
+ - any end-to-end headers provided in the 304 or 206 response MUST
+ replace the corresponding headers from the cache entry.
+
+ Unless the cache decides to remove the cache entry, it MUST also
+ replace the end-to-end headers stored with the cache entry with
+ corresponding headers received in the incoming response, except for
+ Warning headers as described immediately above. If a header field-
+ name in the incoming response matches more than one header in the
+ cache entry, all such old headers MUST be replaced.
+
+ In other words, the set of end-to-end headers received in the
+ incoming response overrides all corresponding end-to-end headers
+ stored with the cache entry (except for stored Warning headers with
+ warn-code 1xx, which are deleted even if not overridden).
+
+ Note: this rule allows an origin server to use a 304 (Not
+ Modified) or a 206 (Partial Content) response to update any header
+ associated with a previous response for the same entity or sub-
+ ranges thereof, although it might not always be meaningful or
+ correct to do so. This rule does not allow an origin server to use
+ a 304 (Not Modified) or a 206 (Partial Content) response to
+ entirely delete a header that it had provided with a previous
+ response.
+
+
+
+Fielding, et al. Standards Track [Page 94]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.5.4 Combining Byte Ranges
+
+ A response might transfer only a subrange of the bytes of an entity-
+ body, either because the request included one or more Range
+ specifications, or because a connection was broken prematurely. After
+ several such transfers, a cache might have received several ranges of
+ the same entity-body.
+
+ If a cache has a stored non-empty set of subranges for an entity, and
+ an incoming response transfers another subrange, the cache MAY
+ combine the new subrange with the existing set if both the following
+ conditions are met:
+
+ - Both the incoming response and the cache entry have a cache
+ validator.
+
+ - The two cache validators match using the strong comparison
+ function (see section 13.3.3).
+
+ If either requirement is not met, the cache MUST use only the most
+ recent partial response (based on the Date values transmitted with
+ every response, and using the incoming response if these values are
+ equal or missing), and MUST discard the other partial information.
+
+13.6 Caching Negotiated Responses
+
+ Use of server-driven content negotiation (section 12.1), as indicated
+ by the presence of a Vary header field in a response, alters the
+ conditions and procedure by which a cache can use the response for
+ subsequent requests. See section 14.44 for use of the Vary header
+ field by servers.
+
+ A server SHOULD use the Vary header field to inform a cache of what
+ request-header fields were used to select among multiple
+ representations of a cacheable response subject to server-driven
+ negotiation. The set of header fields named by the Vary field value
+ is known as the "selecting" request-headers.
+
+ When the cache receives a subsequent request whose Request-URI
+ specifies one or more cache entries including a Vary header field,
+ the cache MUST NOT use such a cache entry to construct a response to
+ the new request unless all of the selecting request-headers present
+ in the new request match the corresponding stored request-headers in
+ the original request.
+
+ The selecting request-headers from two requests are defined to match
+ if and only if the selecting request-headers in the first request can
+ be transformed to the selecting request-headers in the second request
+
+
+
+Fielding, et al. Standards Track [Page 95]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ by adding or removing linear white space (LWS) at places where this
+ is allowed by the corresponding BNF, and/or combining multiple
+ message-header fields with the same field name following the rules
+ about message headers in section 4.2.
+
+ A Vary header field-value of "*" always fails to match and subsequent
+ requests on that resource can only be properly interpreted by the
+ origin server.
+
+ If the selecting request header fields for the cached entry do not
+ match the selecting request header fields of the new request, then
+ the cache MUST NOT use a cached entry to satisfy the request unless
+ it first relays the new request to the origin server in a conditional
+ request and the server responds with 304 (Not Modified), including an
+ entity tag or Content-Location that indicates the entity to be used.
+
+ If an entity tag was assigned to a cached representation, the
+ forwarded request SHOULD be conditional and include the entity tags
+ in an If-None-Match header field from all its cache entries for the
+ resource. This conveys to the server the set of entities currently
+ held by the cache, so that if any one of these entities matches the
+ requested entity, the server can use the ETag header field in its 304
+ (Not Modified) response to tell the cache which entry is appropriate.
+ If the entity-tag of the new response matches that of an existing
+ entry, the new response SHOULD be used to update the header fields of
+ the existing entry, and the result MUST be returned to the client.
+
+ If any of the existing cache entries contains only partial content
+ for the associated entity, its entity-tag SHOULD NOT be included in
+ the If-None-Match header field unless the request is for a range that
+ would be fully satisfied by that entry.
+
+ If a cache receives a successful response whose Content-Location
+ field matches that of an existing cache entry for the same Request-
+ ]URI, whose entity-tag differs from that of the existing entry, and
+ whose Date is more recent than that of the existing entry, the
+ existing entry SHOULD NOT be returned in response to future requests
+ and SHOULD be deleted from the cache.
+
+13.7 Shared and Non-Shared Caches
+
+ For reasons of security and privacy, it is necessary to make a
+ distinction between "shared" and "non-shared" caches. A non-shared
+ cache is one that is accessible only to a single user. Accessibility
+ in this case SHOULD be enforced by appropriate security mechanisms.
+ All other caches are considered to be "shared." Other sections of
+
+
+
+
+
+Fielding, et al. Standards Track [Page 96]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ this specification place certain constraints on the operation of
+ shared caches in order to prevent loss of privacy or failure of
+ access controls.
+
+13.8 Errors or Incomplete Response Cache Behavior
+
+ A cache that receives an incomplete response (for example, with fewer
+ bytes of data than specified in a Content-Length header) MAY store
+ the response. However, the cache MUST treat this as a partial
+ response. Partial responses MAY be combined as described in section
+ 13.5.4; the result might be a full response or might still be
+ partial. A cache MUST NOT return a partial response to a client
+ without explicitly marking it as such, using the 206 (Partial
+ Content) status code. A cache MUST NOT return a partial response
+ using a status code of 200 (OK).
+
+ If a cache receives a 5xx response while attempting to revalidate an
+ entry, it MAY either forward this response to the requesting client,
+ or act as if the server failed to respond. In the latter case, it MAY
+ return a previously received response unless the cached entry
+ includes the "must-revalidate" cache-control directive (see section
+ 14.9).
+
+13.9 Side Effects of GET and HEAD
+
+ Unless the origin server explicitly prohibits the caching of their
+ responses, the application of GET and HEAD methods to any resources
+ SHOULD NOT have side effects that would lead to erroneous behavior if
+ these responses are taken from a cache. They MAY still have side
+ effects, but a cache is not required to consider such side effects in
+ its caching decisions. Caches are always expected to observe an
+ origin server's explicit restrictions on caching.
+
+ We note one exception to this rule: since some applications have
+ traditionally used GETs and HEADs with query URLs (those containing a
+ "?" in the rel_path part) to perform operations with significant side
+ effects, caches MUST NOT treat responses to such URIs as fresh unless
+ the server provides an explicit expiration time. This specifically
+ means that responses from HTTP/1.0 servers for such URIs SHOULD NOT
+ be taken from a cache. See section 9.1.1 for related information.
+
+13.10 Invalidation After Updates or Deletions
+
+ The effect of certain methods performed on a resource at the origin
+ server might cause one or more existing cache entries to become non-
+ transparently invalid. That is, although they might continue to be
+ "fresh," they do not accurately reflect what the origin server would
+ return for a new request on that resource.
+
+
+
+Fielding, et al. Standards Track [Page 97]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ There is no way for the HTTP protocol to guarantee that all such
+ cache entries are marked invalid. For example, the request that
+ caused the change at the origin server might not have gone through
+ the proxy where a cache entry is stored. However, several rules help
+ reduce the likelihood of erroneous behavior.
+
+ In this section, the phrase "invalidate an entity" means that the
+ cache will either remove all instances of that entity from its
+ storage, or will mark these as "invalid" and in need of a mandatory
+ revalidation before they can be returned in response to a subsequent
+ request.
+
+ Some HTTP methods MUST cause a cache to invalidate an entity. This is
+ either the entity referred to by the Request-URI, or by the Location
+ or Content-Location headers (if present). These methods are:
+
+ - PUT
+
+ - DELETE
+
+ - POST
+
+ In order to prevent denial of service attacks, an invalidation based
+ on the URI in a Location or Content-Location header MUST only be
+ performed if the host part is the same as in the Request-URI.
+
+ A cache that passes through requests for methods it does not
+ understand SHOULD invalidate any entities referred to by the
+ Request-URI.
+
+13.11 Write-Through Mandatory
+
+ All methods that might be expected to cause modifications to the
+ origin server's resources MUST be written through to the origin
+ server. This currently includes all methods except for GET and HEAD.
+ A cache MUST NOT reply to such a request from a client before having
+ transmitted the request to the inbound server, and having received a
+ corresponding response from the inbound server. This does not prevent
+ a proxy cache from sending a 100 (Continue) response before the
+ inbound server has sent its final reply.
+
+ The alternative (known as "write-back" or "copy-back" caching) is not
+ allowed in HTTP/1.1, due to the difficulty of providing consistent
+ updates and the problems arising from server, cache, or network
+ failure prior to write-back.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 98]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+13.12 Cache Replacement
+
+ If a new cacheable (see sections 14.9.2, 13.2.5, 13.2.6 and 13.8)
+ response is received from a resource while any existing responses for
+ the same resource are cached, the cache SHOULD use the new response
+ to reply to the current request. It MAY insert it into cache storage
+ and MAY, if it meets all other requirements, use it to respond to any
+ future requests that would previously have caused the old response to
+ be returned. If it inserts the new response into cache storage the
+ rules in section 13.5.3 apply.
+
+ Note: a new response that has an older Date header value than
+ existing cached responses is not cacheable.
+
+13.13 History Lists
+
+ User agents often have history mechanisms, such as "Back" buttons and
+ history lists, which can be used to redisplay an entity retrieved
+ earlier in a session.
+
+ History mechanisms and caches are different. In particular history
+ mechanisms SHOULD NOT try to show a semantically transparent view of
+ the current state of a resource. Rather, a history mechanism is meant
+ to show exactly what the user saw at the time when the resource was
+ retrieved.
+
+ By default, an expiration time does not apply to history mechanisms.
+ If the entity is still in storage, a history mechanism SHOULD display
+ it even if the entity has expired, unless the user has specifically
+ configured the agent to refresh expired history documents.
+
+ This is not to be construed to prohibit the history mechanism from
+ telling the user that a view might be stale.
+
+ Note: if history list mechanisms unnecessarily prevent users from
+ viewing stale resources, this will tend to force service authors
+ to avoid using HTTP expiration controls and cache controls when
+ they would otherwise like to. Service authors may consider it
+ important that users not be presented with error messages or
+ warning messages when they use navigation controls (such as BACK)
+ to view previously fetched resources. Even though sometimes such
+ resources ought not to cached, or ought to expire quickly, user
+ interface considerations may force service authors to resort to
+ other means of preventing caching (e.g. "once-only" URLs) in order
+ not to suffer the effects of improperly functioning history
+ mechanisms.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 99]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14 Header Field Definitions
+
+ This section defines the syntax and semantics of all standard
+ HTTP/1.1 header fields. For entity-header fields, both sender and
+ recipient refer to either the client or the server, depending on who
+ sends and who receives the entity.
+
+14.1 Accept
+
+ The Accept request-header field can be used to specify certain media
+ types which are acceptable for the response. Accept headers can be
+ used to indicate that the request is specifically limited to a small
+ set of desired types, as in the case of a request for an in-line
+ image.
+
+ Accept = "Accept" ":"
+ #( media-range [ accept-params ] )
+
+ media-range = ( "*/*"
+ | ( type "/" "*" )
+ | ( type "/" subtype )
+ ) *( ";" parameter )
+ accept-params = ";" "q" "=" qvalue *( accept-extension )
+ accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+
+ The asterisk "*" character is used to group media types into ranges,
+ with "*/*" indicating all media types and "type/*" indicating all
+ subtypes of that type. The media-range MAY include media type
+ parameters that are applicable to that range.
+
+ Each media-range MAY be followed by one or more accept-params,
+ beginning with the "q" parameter for indicating a relative quality
+ factor. The first "q" parameter (if any) separates the media-range
+ parameter(s) from the accept-params. Quality factors allow the user
+ or user agent to indicate the relative degree of preference for that
+ media-range, using the qvalue scale from 0 to 1 (section 3.9). The
+ default value is q=1.
+
+ Note: Use of the "q" parameter name to separate media type
+ parameters from Accept extension parameters is due to historical
+ practice. Although this prevents any media type parameter named
+ "q" from being used with a media range, such an event is believed
+ to be unlikely given the lack of any "q" parameters in the IANA
+ media type registry and the rare usage of any media type
+ parameters in Accept. Future media types are discouraged from
+ registering any parameter named "q".
+
+
+
+
+
+Fielding, et al. Standards Track [Page 100]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The example
+
+ Accept: audio/*; q=0.2, audio/basic
+
+ SHOULD be interpreted as "I prefer audio/basic, but send me any audio
+ type if it is the best available after an 80% mark-down in quality."
+
+ If no Accept header field is present, then it is assumed that the
+ client accepts all media types. If an Accept header field is present,
+ and if the server cannot send a response which is acceptable
+ according to the combined Accept field value, then the server SHOULD
+ send a 406 (not acceptable) response.
+
+ A more elaborate example is
+
+ Accept: text/plain; q=0.5, text/html,
+ text/x-dvi; q=0.8, text/x-c
+
+ Verbally, this would be interpreted as "text/html and text/x-c are
+ the preferred media types, but if they do not exist, then send the
+ text/x-dvi entity, and if that does not exist, send the text/plain
+ entity."
+
+ Media ranges can be overridden by more specific media ranges or
+ specific media types. If more than one media range applies to a given
+ type, the most specific reference has precedence. For example,
+
+ Accept: text/*, text/html, text/html;level=1, */*
+
+ have the following precedence:
+
+ 1) text/html;level=1
+ 2) text/html
+ 3) text/*
+ 4) */*
+
+ The media type quality factor associated with a given type is
+ determined by finding the media range with the highest precedence
+ which matches that type. For example,
+
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+
+ would cause the following values to be associated:
+
+ text/html;level=1 = 1
+ text/html = 0.7
+ text/plain = 0.3
+
+
+
+Fielding, et al. Standards Track [Page 101]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ image/jpeg = 0.5
+ text/html;level=2 = 0.4
+ text/html;level=3 = 0.7
+
+ Note: A user agent might be provided with a default set of quality
+ values for certain media ranges. However, unless the user agent is
+ a closed system which cannot interact with other rendering agents,
+ this default set ought to be configurable by the user.
+
+14.2 Accept-Charset
+
+ The Accept-Charset request-header field can be used to indicate what
+ character sets are acceptable for the response. This field allows
+ clients capable of understanding more comprehensive or special-
+ purpose character sets to signal that capability to a server which is
+ capable of representing documents in those character sets.
+
+ Accept-Charset = "Accept-Charset" ":"
+ 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
+
+
+ Character set values are described in section 3.4. Each charset MAY
+ be given an associated quality value which represents the user's
+ preference for that charset. The default value is q=1. An example is
+
+ Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
+
+ The special value "*", if present in the Accept-Charset field,
+ matches every character set (including ISO-8859-1) which is not
+ mentioned elsewhere in the Accept-Charset field. If no "*" is present
+ in an Accept-Charset field, then all character sets not explicitly
+ mentioned get a quality value of 0, except for ISO-8859-1, which gets
+ a quality value of 1 if not explicitly mentioned.
+
+ If no Accept-Charset header is present, the default is that any
+ character set is acceptable. If an Accept-Charset header is present,
+ and if the server cannot send a response which is acceptable
+ according to the Accept-Charset header, then the server SHOULD send
+ an error response with the 406 (not acceptable) status code, though
+ the sending of an unacceptable response is also allowed.
+
+14.3 Accept-Encoding
+
+ The Accept-Encoding request-header field is similar to Accept, but
+ restricts the content-codings (section 3.5) that are acceptable in
+ the response.
+
+ Accept-Encoding = "Accept-Encoding" ":"
+
+
+
+Fielding, et al. Standards Track [Page 102]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 1#( codings [ ";" "q" "=" qvalue ] )
+ codings = ( content-coding | "*" )
+
+ Examples of its use are:
+
+ Accept-Encoding: compress, gzip
+ Accept-Encoding:
+ Accept-Encoding: *
+ Accept-Encoding: compress;q=0.5, gzip;q=1.0
+ Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
+
+ A server tests whether a content-coding is acceptable, according to
+ an Accept-Encoding field, using these rules:
+
+ 1. If the content-coding is one of the content-codings listed in
+ the Accept-Encoding field, then it is acceptable, unless it is
+ accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+ 2. The special "*" symbol in an Accept-Encoding field matches any
+ available content-coding not explicitly listed in the header
+ field.
+
+ 3. If multiple content-codings are acceptable, then the acceptable
+ content-coding with the highest non-zero qvalue is preferred.
+
+ 4. The "identity" content-coding is always acceptable, unless
+ specifically refused because the Accept-Encoding field includes
+ "identity;q=0", or because the field includes "*;q=0" and does
+ not explicitly include the "identity" content-coding. If the
+ Accept-Encoding field-value is empty, then only the "identity"
+ encoding is acceptable.
+
+ If an Accept-Encoding field is present in a request, and if the
+ server cannot send a response which is acceptable according to the
+ Accept-Encoding header, then the server SHOULD send an error response
+ with the 406 (Not Acceptable) status code.
+
+ If no Accept-Encoding field is present in a request, the server MAY
+ assume that the client will accept any content coding. In this case,
+ if "identity" is one of the available content-codings, then the
+ server SHOULD use the "identity" content-coding, unless it has
+ additional information that a different content-coding is meaningful
+ to the client.
+
+ Note: If the request does not include an Accept-Encoding field,
+ and if the "identity" content-coding is unavailable, then
+ content-codings commonly understood by HTTP/1.0 clients (i.e.,
+
+
+
+Fielding, et al. Standards Track [Page 103]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ "gzip" and "compress") are preferred; some older clients
+ improperly display messages sent with other content-codings. The
+ server might also make this decision based on information about
+ the particular user-agent or client.
+
+ Note: Most HTTP/1.0 applications do not recognize or obey qvalues
+ associated with content-codings. This means that qvalues will not
+ work and are not permitted with x-gzip or x-compress.
+
+14.4 Accept-Language
+
+ The Accept-Language request-header field is similar to Accept, but
+ restricts the set of natural languages that are preferred as a
+ response to the request. Language tags are defined in section 3.10.
+
+ Accept-Language = "Accept-Language" ":"
+ 1#( language-range [ ";" "q" "=" qvalue ] )
+ language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+
+ Each language-range MAY be given an associated quality value which
+ represents an estimate of the user's preference for the languages
+ specified by that range. The quality value defaults to "q=1". For
+ example,
+
+ Accept-Language: da, en-gb;q=0.8, en;q=0.7
+
+ would mean: "I prefer Danish, but will accept British English and
+ other types of English." A language-range matches a language-tag if
+ it exactly equals the tag, or if it exactly equals a prefix of the
+ tag such that the first tag character following the prefix is "-".
+ The special range "*", if present in the Accept-Language field,
+ matches every tag not matched by any other range present in the
+ Accept-Language field.
+
+ Note: This use of a prefix matching rule does not imply that
+ language tags are assigned to languages in such a way that it is
+ always true that if a user understands a language with a certain
+ tag, then this user will also understand all languages with tags
+ for which this tag is a prefix. The prefix rule simply allows the
+ use of prefix tags if this is the case.
+
+ The language quality factor assigned to a language-tag by the
+ Accept-Language field is the quality value of the longest language-
+ range in the field that matches the language-tag. If no language-
+ range in the field matches the tag, the language quality factor
+ assigned is 0. If no Accept-Language header is present in the
+ request, the server
+
+
+
+
+Fielding, et al. Standards Track [Page 104]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ SHOULD assume that all languages are equally acceptable. If an
+ Accept-Language header is present, then all languages which are
+ assigned a quality factor greater than 0 are acceptable.
+
+ It might be contrary to the privacy expectations of the user to send
+ an Accept-Language header with the complete linguistic preferences of
+ the user in every request. For a discussion of this issue, see
+ section 15.1.4.
+
+ As intelligibility is highly dependent on the individual user, it is
+ recommended that client applications make the choice of linguistic
+ preference available to the user. If the choice is not made
+ available, then the Accept-Language header field MUST NOT be given in
+ the request.
+
+ Note: When making the choice of linguistic preference available to
+ the user, we remind implementors of the fact that users are not
+ familiar with the details of language matching as described above,
+ and should provide appropriate guidance. As an example, users
+ might assume that on selecting "en-gb", they will be served any
+ kind of English document if British English is not available. A
+ user agent might suggest in such a case to add "en" to get the
+ best matching behavior.
+
+14.5 Accept-Ranges
+
+ The Accept-Ranges response-header field allows the server to
+ indicate its acceptance of range requests for a resource:
+
+ Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
+ acceptable-ranges = 1#range-unit | "none"
+
+ Origin servers that accept byte-range requests MAY send
+
+ Accept-Ranges: bytes
+
+ but are not required to do so. Clients MAY generate byte-range
+ requests without having received this header for the resource
+ involved. Range units are defined in section 3.12.
+
+ Servers that do not accept any kind of range request for a
+ resource MAY send
+
+ Accept-Ranges: none
+
+ to advise the client not to attempt a range request.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 105]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.6 Age
+
+ The Age response-header field conveys the sender's estimate of the
+ amount of time since the response (or its revalidation) was
+ generated at the origin server. A cached response is "fresh" if
+ its age does not exceed its freshness lifetime. Age values are
+ calculated as specified in section 13.2.3.
+
+ Age = "Age" ":" age-value
+ age-value = delta-seconds
+
+ Age values are non-negative decimal integers, representing time in
+ seconds.
+
+ If a cache receives a value larger than the largest positive
+ integer it can represent, or if any of its age calculations
+ overflows, it MUST transmit an Age header with a value of
+ 2147483648 (2^31). An HTTP/1.1 server that includes a cache MUST
+ include an Age header field in every response generated from its
+ own cache. Caches SHOULD use an arithmetic type of at least 31
+ bits of range.
+
+14.7 Allow
+
+ The Allow entity-header field lists the set of methods supported
+ by the resource identified by the Request-URI. The purpose of this
+ field is strictly to inform the recipient of valid methods
+ associated with the resource. An Allow header field MUST be
+ present in a 405 (Method Not Allowed) response.
+
+ Allow = "Allow" ":" #Method
+
+ Example of use:
+
+ Allow: GET, HEAD, PUT
+
+ This field cannot prevent a client from trying other methods.
+ However, the indications given by the Allow header field value
+ SHOULD be followed. The actual set of allowed methods is defined
+ by the origin server at the time of each request.
+
+ The Allow header field MAY be provided with a PUT request to
+ recommend the methods to be supported by the new or modified
+ resource. The server is not required to support these methods and
+ SHOULD include an Allow header in the response giving the actual
+ supported methods.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 106]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ A proxy MUST NOT modify the Allow header field even if it does not
+ understand all the methods specified, since the user agent might
+ have other means of communicating with the origin server.
+
+14.8 Authorization
+
+ A user agent that wishes to authenticate itself with a server--
+ usually, but not necessarily, after receiving a 401 response--does
+ so by including an Authorization request-header field with the
+ request. The Authorization field value consists of credentials
+ containing the authentication information of the user agent for
+ the realm of the resource being requested.
+
+ Authorization = "Authorization" ":" credentials
+
+ HTTP access authentication is described in "HTTP Authentication:
+ Basic and Digest Access Authentication" [43]. If a request is
+ authenticated and a realm specified, the same credentials SHOULD
+ be valid for all other requests within this realm (assuming that
+ the authentication scheme itself does not require otherwise, such
+ as credentials that vary according to a challenge value or using
+ synchronized clocks).
+
+ When a shared cache (see section 13.7) receives a request
+ containing an Authorization field, it MUST NOT return the
+ corresponding response as a reply to any other request, unless one
+ of the following specific exceptions holds:
+
+ 1. If the response includes the "s-maxage" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But (if the specified maximum age has
+ passed) a proxy cache MUST first revalidate it with the origin
+ server, using the request-headers from the new request to allow
+ the origin server to authenticate the new request. (This is the
+ defined behavior for s-maxage.) If the response includes "s-
+ maxage=0", the proxy MUST always revalidate it before re-using
+ it.
+
+ 2. If the response includes the "must-revalidate" cache-control
+ directive, the cache MAY use that response in replying to a
+ subsequent request. But if the response is stale, all caches
+ MUST first revalidate it with the origin server, using the
+ request-headers from the new request to allow the origin server
+ to authenticate the new request.
+
+ 3. If the response includes the "public" cache-control directive,
+ it MAY be returned in reply to any subsequent request.
+
+
+
+
+Fielding, et al. Standards Track [Page 107]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.9 Cache-Control
+
+ The Cache-Control general-header field is used to specify directives
+ that MUST be obeyed by all caching mechanisms along the
+ request/response chain. The directives specify behavior intended to
+ prevent caches from adversely interfering with the request or
+ response. These directives typically override the default caching
+ algorithms. Cache directives are unidirectional in that the presence
+ of a directive in a request does not imply that the same directive is
+ to be given in the response.
+
+ Note that HTTP/1.0 caches might not implement Cache-Control and
+ might only implement Pragma: no-cache (see section 14.32).
+
+ Cache directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a cache-
+ directive for a specific cache.
+
+ Cache-Control = "Cache-Control" ":" 1#cache-directive
+
+ cache-directive = cache-request-directive
+ | cache-response-directive
+
+ cache-request-directive =
+ "no-cache" ; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
+ | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
+ | "min-fresh" "=" delta-seconds ; Section 14.9.3
+ | "no-transform" ; Section 14.9.5
+ | "only-if-cached" ; Section 14.9.4
+ | cache-extension ; Section 14.9.6
+
+ cache-response-directive =
+ "public" ; Section 14.9.1
+ | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
+ | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
+ | "no-store" ; Section 14.9.2
+ | "no-transform" ; Section 14.9.5
+ | "must-revalidate" ; Section 14.9.4
+ | "proxy-revalidate" ; Section 14.9.4
+ | "max-age" "=" delta-seconds ; Section 14.9.3
+ | "s-maxage" "=" delta-seconds ; Section 14.9.3
+ | cache-extension ; Section 14.9.6
+
+ cache-extension = token [ "=" ( token | quoted-string ) ]
+
+
+
+Fielding, et al. Standards Track [Page 108]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ When a directive appears without any 1#field-name parameter, the
+ directive applies to the entire request or response. When such a
+ directive appears with a 1#field-name parameter, it applies only to
+ the named field or fields, and not to the rest of the request or
+ response. This mechanism supports extensibility; implementations of
+ future versions of the HTTP protocol might apply these directives to
+ header fields not defined in HTTP/1.1.
+
+ The cache-control directives can be broken down into these general
+ categories:
+
+ - Restrictions on what are cacheable; these may only be imposed by
+ the origin server.
+
+ - Restrictions on what may be stored by a cache; these may be
+ imposed by either the origin server or the user agent.
+
+ - Modifications of the basic expiration mechanism; these may be
+ imposed by either the origin server or the user agent.
+
+ - Controls over cache revalidation and reload; these may only be
+ imposed by a user agent.
+
+ - Control over transformation of entities.
+
+ - Extensions to the caching system.
+
+14.9.1 What is Cacheable
+
+ By default, a response is cacheable if the requirements of the
+ request method, request header fields, and the response status
+ indicate that it is cacheable. Section 13.4 summarizes these defaults
+ for cacheability. The following Cache-Control response directives
+ allow an origin server to override the default cacheability of a
+ response:
+
+ public
+ Indicates that the response MAY be cached by any cache, even if it
+ would normally be non-cacheable or cacheable only within a non-
+ shared cache. (See also Authorization, section 14.8, for
+ additional details.)
+
+ private
+ Indicates that all or part of the response message is intended for
+ a single user and MUST NOT be cached by a shared cache. This
+ allows an origin server to state that the specified parts of the
+
+
+
+
+
+Fielding, et al. Standards Track [Page 109]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ response are intended for only one user and are not a valid
+ response for requests by other users. A private (non-shared) cache
+ MAY cache the response.
+
+ Note: This usage of the word private only controls where the
+ response may be cached, and cannot ensure the privacy of the
+ message content.
+
+ no-cache
+ If the no-cache directive does not specify a field-name, then a
+ cache MUST NOT use the response to satisfy a subsequent request
+ without successful revalidation with the origin server. This
+ allows an origin server to prevent caching even by caches that
+ have been configured to return stale responses to client requests.
+
+ If the no-cache directive does specify one or more field-names,
+ then a cache MAY use the response to satisfy a subsequent request,
+ subject to any other restrictions on caching. However, the
+ specified field-name(s) MUST NOT be sent in the response to a
+ subsequent request without successful revalidation with the origin
+ server. This allows an origin server to prevent the re-use of
+ certain header fields in a response, while still allowing caching
+ of the rest of the response.
+
+ Note: Most HTTP/1.0 caches will not recognize or obey this
+ directive.
+
+14.9.2 What May be Stored by Caches
+
+ no-store
+ The purpose of the no-store directive is to prevent the
+ inadvertent release or retention of sensitive information (for
+ example, on backup tapes). The no-store directive applies to the
+ entire message, and MAY be sent either in a response or in a
+ request. If sent in a request, a cache MUST NOT store any part of
+ either this request or any response to it. If sent in a response,
+ a cache MUST NOT store any part of either this response or the
+ request that elicited it. This directive applies to both non-
+ shared and shared caches. "MUST NOT store" in this context means
+ that the cache MUST NOT intentionally store the information in
+ non-volatile storage, and MUST make a best-effort attempt to
+ remove the information from volatile storage as promptly as
+ possible after forwarding it.
+
+ Even when this directive is associated with a response, users
+ might explicitly store such a response outside of the caching
+ system (e.g., with a "Save As" dialog). History buffers MAY store
+ such responses as part of their normal operation.
+
+
+
+Fielding, et al. Standards Track [Page 110]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The purpose of this directive is to meet the stated requirements
+ of certain users and service authors who are concerned about
+ accidental releases of information via unanticipated accesses to
+ cache data structures. While the use of this directive might
+ improve privacy in some cases, we caution that it is NOT in any
+ way a reliable or sufficient mechanism for ensuring privacy. In
+ particular, malicious or compromised caches might not recognize or
+ obey this directive, and communications networks might be
+ vulnerable to eavesdropping.
+
+14.9.3 Modifications of the Basic Expiration Mechanism
+
+ The expiration time of an entity MAY be specified by the origin
+ server using the Expires header (see section 14.21). Alternatively,
+ it MAY be specified using the max-age directive in a response. When
+ the max-age cache-control directive is present in a cached response,
+ the response is stale if its current age is greater than the age
+ value given (in seconds) at the time of a new request for that
+ resource. The max-age directive on a response implies that the
+ response is cacheable (i.e., "public") unless some other, more
+ restrictive cache directive is also present.
+
+ If a response includes both an Expires header and a max-age
+ directive, the max-age directive overrides the Expires header, even
+ if the Expires header is more restrictive. This rule allows an origin
+ server to provide, for a given response, a longer expiration time to
+ an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
+ useful if certain HTTP/1.0 caches improperly calculate ages or
+ expiration times, perhaps due to desynchronized clocks.
+
+ Many HTTP/1.0 cache implementations will treat an Expires value that
+ is less than or equal to the response Date value as being equivalent
+ to the Cache-Control response directive "no-cache". If an HTTP/1.1
+ cache receives such a response, and the response does not include a
+ Cache-Control header field, it SHOULD consider the response to be
+ non-cacheable in order to retain compatibility with HTTP/1.0 servers.
+
+ Note: An origin server might wish to use a relatively new HTTP
+ cache control feature, such as the "private" directive, on a
+ network including older caches that do not understand that
+ feature. The origin server will need to combine the new feature
+ with an Expires field whose value is less than or equal to the
+ Date value. This will prevent older caches from improperly
+ caching the response.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 111]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ s-maxage
+ If a response includes an s-maxage directive, then for a shared
+ cache (but not for a private cache), the maximum age specified by
+ this directive overrides the maximum age specified by either the
+ max-age directive or the Expires header. The s-maxage directive
+ also implies the semantics of the proxy-revalidate directive (see
+ section 14.9.4), i.e., that the shared cache must not use the
+ entry after it becomes stale to respond to a subsequent request
+ without first revalidating it with the origin server. The s-
+ maxage directive is always ignored by a private cache.
+
+ Note that most older caches, not compliant with this specification,
+ do not implement any cache-control directives. An origin server
+ wishing to use a cache-control directive that restricts, but does not
+ prevent, caching by an HTTP/1.1-compliant cache MAY exploit the
+ requirement that the max-age directive overrides the Expires header,
+ and the fact that pre-HTTP/1.1-compliant caches do not observe the
+ max-age directive.
+
+ Other directives allow a user agent to modify the basic expiration
+ mechanism. These directives MAY be specified on a request:
+
+ max-age
+ Indicates that the client is willing to accept a response whose
+ age is no greater than the specified time in seconds. Unless max-
+ stale directive is also included, the client is not willing to
+ accept a stale response.
+
+ min-fresh
+ Indicates that the client is willing to accept a response whose
+ freshness lifetime is no less than its current age plus the
+ specified time in seconds. That is, the client wants a response
+ that will still be fresh for at least the specified number of
+ seconds.
+
+ max-stale
+ Indicates that the client is willing to accept a response that has
+ exceeded its expiration time. If max-stale is assigned a value,
+ then the client is willing to accept a response that has exceeded
+ its expiration time by no more than the specified number of
+ seconds. If no value is assigned to max-stale, then the client is
+ willing to accept a stale response of any age.
+
+ If a cache returns a stale response, either because of a max-stale
+ directive on a request, or because the cache is configured to
+ override the expiration time of a response, the cache MUST attach a
+ Warning header to the stale response, using Warning 110 (Response is
+ stale).
+
+
+
+Fielding, et al. Standards Track [Page 112]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ A cache MAY be configured to return stale responses without
+ validation, but only if this does not conflict with any "MUST"-level
+ requirements concerning cache validation (e.g., a "must-revalidate"
+ cache-control directive).
+
+ If both the new request and the cached entry include "max-age"
+ directives, then the lesser of the two values is used for determining
+ the freshness of the cached entry for that request.
+
+14.9.4 Cache Revalidation and Reload Controls
+
+ Sometimes a user agent might want or need to insist that a cache
+ revalidate its cache entry with the origin server (and not just with
+ the next cache along the path to the origin server), or to reload its
+ cache entry from the origin server. End-to-end revalidation might be
+ necessary if either the cache or the origin server has overestimated
+ the expiration time of the cached response. End-to-end reload may be
+ necessary if the cache entry has become corrupted for some reason.
+
+ End-to-end revalidation may be requested either when the client does
+ not have its own local cached copy, in which case we call it
+ "unspecified end-to-end revalidation", or when the client does have a
+ local cached copy, in which case we call it "specific end-to-end
+ revalidation."
+
+ The client can specify these three kinds of action using Cache-
+ Control request directives:
+
+ End-to-end reload
+ The request includes a "no-cache" cache-control directive or, for
+ compatibility with HTTP/1.0 clients, "Pragma: no-cache". Field
+ names MUST NOT be included with the no-cache directive in a
+ request. The server MUST NOT use a cached copy when responding to
+ such a request.
+
+ Specific end-to-end revalidation
+ The request includes a "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request includes a cache-validating conditional with
+ the client's current validator.
+
+ Unspecified end-to-end revalidation
+ The request includes "max-age=0" cache-control directive, which
+ forces each cache along the path to the origin server to
+ revalidate its own entry, if any, with the next cache or server.
+ The initial request does not include a cache-validating
+
+
+
+
+Fielding, et al. Standards Track [Page 113]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ conditional; the first cache along the path (if any) that holds a
+ cache entry for this resource includes a cache-validating
+ conditional with its current validator.
+
+ max-age
+ When an intermediate cache is forced, by means of a max-age=0
+ directive, to revalidate its own cache entry, and the client has
+ supplied its own validator in the request, the supplied validator
+ might differ from the validator currently stored with the cache
+ entry. In this case, the cache MAY use either validator in making
+ its own request without affecting semantic transparency.
+
+ However, the choice of validator might affect performance. The
+ best approach is for the intermediate cache to use its own
+ validator when making its request. If the server replies with 304
+ (Not Modified), then the cache can return its now validated copy
+ to the client with a 200 (OK) response. If the server replies with
+ a new entity and cache validator, however, the intermediate cache
+ can compare the returned validator with the one provided in the
+ client's request, using the strong comparison function. If the
+ client's validator is equal to the origin server's, then the
+ intermediate cache simply returns 304 (Not Modified). Otherwise,
+ it returns the new entity with a 200 (OK) response.
+
+ If a request includes the no-cache directive, it SHOULD NOT
+ include min-fresh, max-stale, or max-age.
+
+ only-if-cached
+ In some cases, such as times of extremely poor network
+ connectivity, a client may want a cache to return only those
+ responses that it currently has stored, and not to reload or
+ revalidate with the origin server. To do this, the client may
+ include the only-if-cached directive in a request. If it receives
+ this directive, a cache SHOULD either respond using a cached entry
+ that is consistent with the other constraints of the request, or
+ respond with a 504 (Gateway Timeout) status. However, if a group
+ of caches is being operated as a unified system with good internal
+ connectivity, such a request MAY be forwarded within that group of
+ caches.
+
+ must-revalidate
+ Because a cache MAY be configured to ignore a server's specified
+ expiration time, and because a client request MAY include a max-
+ stale directive (which has a similar effect), the protocol also
+ includes a mechanism for the origin server to require revalidation
+ of a cache entry on any subsequent use. When the must-revalidate
+ directive is present in a response received by a cache, that cache
+ MUST NOT use the entry after it becomes stale to respond to a
+
+
+
+Fielding, et al. Standards Track [Page 114]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ subsequent request without first revalidating it with the origin
+ server. (I.e., the cache MUST do an end-to-end revalidation every
+ time, if, based solely on the origin server's Expires or max-age
+ value, the cached response is stale.)
+
+ The must-revalidate directive is necessary to support reliable
+ operation for certain protocol features. In all circumstances an
+ HTTP/1.1 cache MUST obey the must-revalidate directive; in
+ particular, if the cache cannot reach the origin server for any
+ reason, it MUST generate a 504 (Gateway Timeout) response.
+
+ Servers SHOULD send the must-revalidate directive if and only if
+ failure to revalidate a request on the entity could result in
+ incorrect operation, such as a silently unexecuted financial
+ transaction. Recipients MUST NOT take any automated action that
+ violates this directive, and MUST NOT automatically provide an
+ unvalidated copy of the entity if revalidation fails.
+
+ Although this is not recommended, user agents operating under
+ severe connectivity constraints MAY violate this directive but, if
+ so, MUST explicitly warn the user that an unvalidated response has
+ been provided. The warning MUST be provided on each unvalidated
+ access, and SHOULD require explicit user confirmation.
+
+ proxy-revalidate
+ The proxy-revalidate directive has the same meaning as the must-
+ revalidate directive, except that it does not apply to non-shared
+ user agent caches. It can be used on a response to an
+ authenticated request to permit the user's cache to store and
+ later return the response without needing to revalidate it (since
+ it has already been authenticated once by that user), while still
+ requiring proxies that service many users to revalidate each time
+ (in order to make sure that each user has been authenticated).
+ Note that such authenticated responses also need the public cache
+ control directive in order to allow them to be cached at all.
+
+14.9.5 No-Transform Directive
+
+ no-transform
+ Implementors of intermediate caches (proxies) have found it useful
+ to convert the media type of certain entity bodies. A non-
+ transparent proxy might, for example, convert between image
+ formats in order to save cache space or to reduce the amount of
+ traffic on a slow link.
+
+ Serious operational problems occur, however, when these
+ transformations are applied to entity bodies intended for certain
+ kinds of applications. For example, applications for medical
+
+
+
+Fielding, et al. Standards Track [Page 115]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ imaging, scientific data analysis and those using end-to-end
+ authentication, all depend on receiving an entity body that is bit
+ for bit identical to the original entity-body.
+
+ Therefore, if a message includes the no-transform directive, an
+ intermediate cache or proxy MUST NOT change those headers that are
+ listed in section 13.5.2 as being subject to the no-transform
+ directive. This implies that the cache or proxy MUST NOT change
+ any aspect of the entity-body that is specified by these headers,
+ including the value of the entity-body itself.
+
+14.9.6 Cache Control Extensions
+
+ The Cache-Control header field can be extended through the use of one
+ or more cache-extension tokens, each with an optional assigned value.
+ Informational extensions (those which do not require a change in
+ cache behavior) MAY be added without changing the semantics of other
+ directives. Behavioral extensions are designed to work by acting as
+ modifiers to the existing base of cache directives. Both the new
+ directive and the standard directive are supplied, such that
+ applications which do not understand the new directive will default
+ to the behavior specified by the standard directive, and those that
+ understand the new directive will recognize it as modifying the
+ requirements associated with the standard directive. In this way,
+ extensions to the cache-control directives can be made without
+ requiring changes to the base protocol.
+
+ This extension mechanism depends on an HTTP cache obeying all of the
+ cache-control directives defined for its native HTTP-version, obeying
+ certain extensions, and ignoring all directives that it does not
+ understand.
+
+ For example, consider a hypothetical new response directive called
+ community which acts as a modifier to the private directive. We
+ define this new directive to mean that, in addition to any non-shared
+ cache, any cache which is shared only by members of the community
+ named within its value may cache the response. An origin server
+ wishing to allow the UCI community to use an otherwise private
+ response in their shared cache(s) could do so by including
+
+ Cache-Control: private, community="UCI"
+
+ A cache seeing this header field will act correctly even if the cache
+ does not understand the community cache-extension, since it will also
+ see and understand the private directive and thus default to the safe
+ behavior.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 116]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Unrecognized cache-directives MUST be ignored; it is assumed that any
+ cache-directive likely to be unrecognized by an HTTP/1.1 cache will
+ be combined with standard directives (or the response's default
+ cacheability) such that the cache behavior will remain minimally
+ correct even if the cache does not understand the extension(s).
+
+14.10 Connection
+
+ The Connection general-header field allows the sender to specify
+ options that are desired for that particular connection and MUST NOT
+ be communicated by proxies over further connections.
+
+ The Connection header has the following grammar:
+
+ Connection = "Connection" ":" 1#(connection-token)
+ connection-token = token
+
+ HTTP/1.1 proxies MUST parse the Connection header field before a
+ message is forwarded and, for each connection-token in this field,
+ remove any header field(s) from the message with the same name as the
+ connection-token. Connection options are signaled by the presence of
+ a connection-token in the Connection header field, not by any
+ corresponding additional header field(s), since the additional header
+ field may not be sent if there are no parameters associated with that
+ connection option.
+
+ Message headers listed in the Connection header MUST NOT include
+ end-to-end headers, such as Cache-Control.
+
+ HTTP/1.1 defines the "close" connection option for the sender to
+ signal that the connection will be closed after completion of the
+ response. For example,
+
+ Connection: close
+
+ in either the request or the response header fields indicates that
+ the connection SHOULD NOT be considered `persistent' (section 8.1)
+ after the current request/response is complete.
+
+ HTTP/1.1 applications that do not support persistent connections MUST
+ include the "close" connection option in every message.
+
+ A system receiving an HTTP/1.0 (or lower-version) message that
+ includes a Connection header MUST, for each connection-token in this
+ field, remove and ignore any header field(s) from the message with
+ the same name as the connection-token. This protects against mistaken
+ forwarding of such header fields by pre-HTTP/1.1 proxies. See section
+ 19.6.2.
+
+
+
+Fielding, et al. Standards Track [Page 117]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.11 Content-Encoding
+
+ The Content-Encoding entity-header field is used as a modifier to the
+ media-type. When present, its value indicates what additional content
+ codings have been applied to the entity-body, and thus what decoding
+ mechanisms must be applied in order to obtain the media-type
+ referenced by the Content-Type header field. Content-Encoding is
+ primarily used to allow a document to be compressed without losing
+ the identity of its underlying media type.
+
+ Content-Encoding = "Content-Encoding" ":" 1#content-coding
+
+ Content codings are defined in section 3.5. An example of its use is
+
+ Content-Encoding: gzip
+
+ The content-coding is a characteristic of the entity identified by
+ the Request-URI. Typically, the entity-body is stored with this
+ encoding and is only decoded before rendering or analogous usage.
+ However, a non-transparent proxy MAY modify the content-coding if the
+ new coding is known to be acceptable to the recipient, unless the
+ "no-transform" cache-control directive is present in the message.
+
+ If the content-coding of an entity is not "identity", then the
+ response MUST include a Content-Encoding entity-header (section
+ 14.11) that lists the non-identity content-coding(s) used.
+
+ If the content-coding of an entity in a request message is not
+ acceptable to the origin server, the server SHOULD respond with a
+ status code of 415 (Unsupported Media Type).
+
+ If multiple encodings have been applied to an entity, the content
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+14.12 Content-Language
+
+ The Content-Language entity-header field describes the natural
+ language(s) of the intended audience for the enclosed entity. Note
+ that this might not be equivalent to all the languages used within
+ the entity-body.
+
+ Content-Language = "Content-Language" ":" 1#language-tag
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 118]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Language tags are defined in section 3.10. The primary purpose of
+ Content-Language is to allow a user to identify and differentiate
+ entities according to the user's own preferred language. Thus, if the
+ body content is intended only for a Danish-literate audience, the
+ appropriate field is
+
+ Content-Language: da
+
+ If no Content-Language is specified, the default is that the content
+ is intended for all language audiences. This might mean that the
+ sender does not consider it to be specific to any natural language,
+ or that the sender does not know for which language it is intended.
+
+ Multiple languages MAY be listed for content that is intended for
+ multiple audiences. For example, a rendition of the "Treaty of
+ Waitangi," presented simultaneously in the original Maori and English
+ versions, would call for
+
+ Content-Language: mi, en
+
+ However, just because multiple languages are present within an entity
+ does not mean that it is intended for multiple linguistic audiences.
+ An example would be a beginner's language primer, such as "A First
+ Lesson in Latin," which is clearly intended to be used by an
+ English-literate audience. In this case, the Content-Language would
+ properly only include "en".
+
+ Content-Language MAY be applied to any media type -- it is not
+ limited to textual documents.
+
+14.13 Content-Length
+
+ The Content-Length entity-header field indicates the size of the
+ entity-body, in decimal number of OCTETs, sent to the recipient or,
+ in the case of the HEAD method, the size of the entity-body that
+ would have been sent had the request been a GET.
+
+ Content-Length = "Content-Length" ":" 1*DIGIT
+
+ An example is
+
+ Content-Length: 3495
+
+ Applications SHOULD use this field to indicate the transfer-length of
+ the message-body, unless this is prohibited by the rules in section
+ 4.4.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 119]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Any Content-Length greater than or equal to zero is a valid value.
+ Section 4.4 describes how to determine the length of a message-body
+ if a Content-Length is not given.
+
+ Note that the meaning of this field is significantly different from
+ the corresponding definition in MIME, where it is an optional field
+ used within the "message/external-body" content-type. In HTTP, it
+ SHOULD be sent whenever the message's length can be determined prior
+ to being transferred, unless this is prohibited by the rules in
+ section 4.4.
+
+14.14 Content-Location
+
+ The Content-Location entity-header field MAY be used to supply the
+ resource location for the entity enclosed in the message when that
+ entity is accessible from a location separate from the requested
+ resource's URI. A server SHOULD provide a Content-Location for the
+ variant corresponding to the response entity; especially in the case
+ where a resource has multiple entities associated with it, and those
+ entities actually have separate locations by which they might be
+ individually accessed, the server SHOULD provide a Content-Location
+ for the particular variant which is returned.
+
+ Content-Location = "Content-Location" ":"
+ ( absoluteURI | relativeURI )
+
+ The value of Content-Location also defines the base URI for the
+ entity.
+
+ The Content-Location value is not a replacement for the original
+ requested URI; it is only a statement of the location of the resource
+ corresponding to this particular entity at the time of the request.
+ Future requests MAY specify the Content-Location URI as the request-
+ URI if the desire is to identify the source of that particular
+ entity.
+
+ A cache cannot assume that an entity with a Content-Location
+ different from the URI used to retrieve it can be used to respond to
+ later requests on that Content-Location URI. However, the Content-
+ Location can be used to differentiate between multiple entities
+ retrieved from a single requested resource, as described in section
+ 13.6.
+
+ If the Content-Location is a relative URI, the relative URI is
+ interpreted relative to the Request-URI.
+
+ The meaning of the Content-Location header in PUT or POST requests is
+ undefined; servers are free to ignore it in those cases.
+
+
+
+Fielding, et al. Standards Track [Page 120]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.15 Content-MD5
+
+ The Content-MD5 entity-header field, as defined in RFC 1864 [23], is
+ an MD5 digest of the entity-body for the purpose of providing an
+ end-to-end message integrity check (MIC) of the entity-body. (Note: a
+ MIC is good for detecting accidental modification of the entity-body
+ in transit, but is not proof against malicious attacks.)
+
+ Content-MD5 = "Content-MD5" ":" md5-digest
+ md5-digest = <base64 of 128 bit MD5 digest as per RFC 1864>
+
+ The Content-MD5 header field MAY be generated by an origin server or
+ client to function as an integrity check of the entity-body. Only
+ origin servers or clients MAY generate the Content-MD5 header field;
+ proxies and gateways MUST NOT generate it, as this would defeat its
+ value as an end-to-end integrity check. Any recipient of the entity-
+ body, including gateways and proxies, MAY check that the digest value
+ in this header field matches that of the entity-body as received.
+
+ The MD5 digest is computed based on the content of the entity-body,
+ including any content-coding that has been applied, but not including
+ any transfer-encoding applied to the message-body. If the message is
+ received with a transfer-encoding, that encoding MUST be removed
+ prior to checking the Content-MD5 value against the received entity.
+
+ This has the result that the digest is computed on the octets of the
+ entity-body exactly as, and in the order that, they would be sent if
+ no transfer-encoding were being applied.
+
+ HTTP extends RFC 1864 to permit the digest to be computed for MIME
+ composite media-types (e.g., multipart/* and message/rfc822), but
+ this does not change how the digest is computed as defined in the
+ preceding paragraph.
+
+ There are several consequences of this. The entity-body for composite
+ types MAY contain many body-parts, each with its own MIME and HTTP
+ headers (including Content-MD5, Content-Transfer-Encoding, and
+ Content-Encoding headers). If a body-part has a Content-Transfer-
+ Encoding or Content-Encoding header, it is assumed that the content
+ of the body-part has had the encoding applied, and the body-part is
+ included in the Content-MD5 digest as is -- i.e., after the
+ application. The Transfer-Encoding header field is not allowed within
+ body-parts.
+
+ Conversion of all line breaks to CRLF MUST NOT be done before
+ computing or checking the digest: the line break convention used in
+ the text actually transmitted MUST be left unaltered when computing
+ the digest.
+
+
+
+Fielding, et al. Standards Track [Page 121]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Note: while the definition of Content-MD5 is exactly the same for
+ HTTP as in RFC 1864 for MIME entity-bodies, there are several ways
+ in which the application of Content-MD5 to HTTP entity-bodies
+ differs from its application to MIME entity-bodies. One is that
+ HTTP, unlike MIME, does not use Content-Transfer-Encoding, and
+ does use Transfer-Encoding and Content-Encoding. Another is that
+ HTTP more frequently uses binary content types than MIME, so it is
+ worth noting that, in such cases, the byte order used to compute
+ the digest is the transmission byte order defined for the type.
+ Lastly, HTTP allows transmission of text types with any of several
+ line break conventions and not just the canonical form using CRLF.
+
+14.16 Content-Range
+
+ The Content-Range entity-header is sent with a partial entity-body to
+ specify where in the full entity-body the partial body should be
+ applied. Range units are defined in section 3.12.
+
+ Content-Range = "Content-Range" ":" content-range-spec
+
+ content-range-spec = byte-content-range-spec
+ byte-content-range-spec = bytes-unit SP
+ byte-range-resp-spec "/"
+ ( instance-length | "*" )
+
+ byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
+ | "*"
+ instance-length = 1*DIGIT
+
+ The header SHOULD indicate the total length of the full entity-body,
+ unless this length is unknown or difficult to determine. The asterisk
+ "*" character means that the instance-length is unknown at the time
+ when the response was generated.
+
+ Unlike byte-ranges-specifier values (see section 14.35.1), a byte-
+ range-resp-spec MUST only specify one range, and MUST contain
+ absolute byte positions for both the first and last byte of the
+ range.
+
+ A byte-content-range-spec with a byte-range-resp-spec whose last-
+ byte-pos value is less than its first-byte-pos value, or whose
+ instance-length value is less than or equal to its last-byte-pos
+ value, is invalid. The recipient of an invalid byte-content-range-
+ spec MUST ignore it and any content transferred along with it.
+
+ A server sending a response with status code 416 (Requested range not
+ satisfiable) SHOULD include a Content-Range field with a byte-range-
+ resp-spec of "*". The instance-length specifies the current length of
+
+
+
+Fielding, et al. Standards Track [Page 122]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ the selected resource. A response with status code 206 (Partial
+ Content) MUST NOT include a Content-Range field with a byte-range-
+ resp-spec of "*".
+
+ Examples of byte-content-range-spec values, assuming that the entity
+ contains a total of 1234 bytes:
+
+ . The first 500 bytes:
+ bytes 0-499/1234
+
+ . The second 500 bytes:
+ bytes 500-999/1234
+
+ . All except for the first 500 bytes:
+ bytes 500-1233/1234
+
+ . The last 500 bytes:
+ bytes 734-1233/1234
+
+ When an HTTP message includes the content of a single range (for
+ example, a response to a request for a single range, or to a request
+ for a set of ranges that overlap without any holes), this content is
+ transmitted with a Content-Range header, and a Content-Length header
+ showing the number of bytes actually transferred. For example,
+
+ HTTP/1.1 206 Partial content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-Range: bytes 21010-47021/47022
+ Content-Length: 26012
+ Content-Type: image/gif
+
+ When an HTTP message includes the content of multiple ranges (for
+ example, a response to a request for multiple non-overlapping
+ ranges), these are transmitted as a multipart message. The multipart
+ media type used for this purpose is "multipart/byteranges" as defined
+ in appendix 19.2. See appendix 19.6.3 for a compatibility issue.
+
+ A response to a request for a single range MUST NOT be sent using the
+ multipart/byteranges media type. A response to a request for
+ multiple ranges, whose result is a single range, MAY be sent as a
+ multipart/byteranges media type with one part. A client that cannot
+ decode a multipart/byteranges message MUST NOT ask for multiple
+ byte-ranges in a single request.
+
+ When a client requests multiple byte-ranges in one request, the
+ server SHOULD return them in the order that they appeared in the
+ request.
+
+
+
+Fielding, et al. Standards Track [Page 123]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If the server ignores a byte-range-spec because it is syntactically
+ invalid, the server SHOULD treat the request as if the invalid Range
+ header field did not exist. (Normally, this means return a 200
+ response containing the full entity).
+
+ If the server receives a request (other than one including an If-
+ Range request-header field) with an unsatisfiable Range request-
+ header field (that is, all of whose byte-range-spec values have a
+ first-byte-pos value greater than the current length of the selected
+ resource), it SHOULD return a response code of 416 (Requested range
+ not satisfiable) (section 10.4.17).
+
+ Note: clients cannot depend on servers to send a 416 (Requested
+ range not satisfiable) response instead of a 200 (OK) response for
+ an unsatisfiable Range request-header, since not all servers
+ implement this request-header.
+
+14.17 Content-Type
+
+ The Content-Type entity-header field indicates the media type of the
+ entity-body sent to the recipient or, in the case of the HEAD method,
+ the media type that would have been sent had the request been a GET.
+
+ Content-Type = "Content-Type" ":" media-type
+
+ Media types are defined in section 3.7. An example of the field is
+
+ Content-Type: text/html; charset=ISO-8859-4
+
+ Further discussion of methods for identifying the media type of an
+ entity is provided in section 7.2.1.
+
+14.18 Date
+
+ The Date general-header field represents the date and time at which
+ the message was originated, having the same semantics as orig-date in
+ RFC 822. The field value is an HTTP-date, as described in section
+ 3.3.1; it MUST be sent in RFC 1123 [8]-date format.
+
+ Date = "Date" ":" HTTP-date
+
+ An example is
+
+ Date: Tue, 15 Nov 1994 08:12:31 GMT
+
+ Origin servers MUST include a Date header field in all responses,
+ except in these cases:
+
+
+
+
+Fielding, et al. Standards Track [Page 124]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 1. If the response status code is 100 (Continue) or 101 (Switching
+ Protocols), the response MAY include a Date header field, at
+ the server's option.
+
+ 2. If the response status code conveys a server error, e.g. 500
+ (Internal Server Error) or 503 (Service Unavailable), and it is
+ inconvenient or impossible to generate a valid Date.
+
+ 3. If the server does not have a clock that can provide a
+ reasonable approximation of the current time, its responses
+ MUST NOT include a Date header field. In this case, the rules
+ in section 14.18.1 MUST be followed.
+
+ A received message that does not have a Date header field MUST be
+ assigned one by the recipient if the message will be cached by that
+ recipient or gatewayed via a protocol which requires a Date. An HTTP
+ implementation without a clock MUST NOT cache responses without
+ revalidating them on every use. An HTTP cache, especially a shared
+ cache, SHOULD use a mechanism, such as NTP [28], to synchronize its
+ clock with a reliable external standard.
+
+ Clients SHOULD only send a Date header field in messages that include
+ an entity-body, as in the case of the PUT and POST requests, and even
+ then it is optional. A client without a clock MUST NOT send a Date
+ header field in a request.
+
+ The HTTP-date sent in a Date header SHOULD NOT represent a date and
+ time subsequent to the generation of the message. It SHOULD represent
+ the best available approximation of the date and time of message
+ generation, unless the implementation has no means of generating a
+ reasonably accurate date and time. In theory, the date ought to
+ represent the moment just before the entity is generated. In
+ practice, the date can be generated at any time during the message
+ origination without affecting its semantic value.
+
+14.18.1 Clockless Origin Server Operation
+
+ Some origin server implementations might not have a clock available.
+ An origin server without a clock MUST NOT assign Expires or Last-
+ Modified values to a response, unless these values were associated
+ with the resource by a system or user with a reliable clock. It MAY
+ assign an Expires value that is known, at or before server
+ configuration time, to be in the past (this allows "pre-expiration"
+ of responses without storing separate Expires values for each
+ resource).
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 125]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.19 ETag
+
+ The ETag response-header field provides the current value of the
+ entity tag for the requested variant. The headers used with entity
+ tags are described in sections 14.24, 14.26 and 14.44. The entity tag
+ MAY be used for comparison with other entities from the same resource
+ (see section 13.3.3).
+
+ ETag = "ETag" ":" entity-tag
+
+ Examples:
+
+ ETag: "xyzzy"
+ ETag: W/"xyzzy"
+ ETag: ""
+
+14.20 Expect
+
+ The Expect request-header field is used to indicate that particular
+ server behaviors are required by the client.
+
+ Expect = "Expect" ":" 1#expectation
+
+ expectation = "100-continue" | expectation-extension
+ expectation-extension = token [ "=" ( token | quoted-string )
+ *expect-params ]
+ expect-params = ";" token [ "=" ( token | quoted-string ) ]
+
+
+ A server that does not understand or is unable to comply with any of
+ the expectation values in the Expect field of a request MUST respond
+ with appropriate error status. The server MUST respond with a 417
+ (Expectation Failed) status if any of the expectations cannot be met
+ or, if there are other problems with the request, some other 4xx
+ status.
+
+ This header field is defined with extensible syntax to allow for
+ future extensions. If a server receives a request containing an
+ Expect field that includes an expectation-extension that it does not
+ support, it MUST respond with a 417 (Expectation Failed) status.
+
+ Comparison of expectation values is case-insensitive for unquoted
+ tokens (including the 100-continue token), and is case-sensitive for
+ quoted-string expectation-extensions.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 126]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The Expect mechanism is hop-by-hop: that is, an HTTP/1.1 proxy MUST
+ return a 417 (Expectation Failed) status if it receives a request
+ with an expectation that it cannot meet. However, the Expect
+ request-header itself is end-to-end; it MUST be forwarded if the
+ request is forwarded.
+
+ Many older HTTP/1.0 and HTTP/1.1 applications do not understand the
+ Expect header.
+
+ See section 8.2.3 for the use of the 100 (continue) status.
+
+14.21 Expires
+
+ The Expires entity-header field gives the date/time after which the
+ response is considered stale. A stale cache entry may not normally be
+ returned by a cache (either a proxy cache or a user agent cache)
+ unless it is first validated with the origin server (or with an
+ intermediate cache that has a fresh copy of the entity). See section
+ 13.2 for further discussion of the expiration model.
+
+ The presence of an Expires field does not imply that the original
+ resource will change or cease to exist at, before, or after that
+ time.
+
+ The format is an absolute date and time as defined by HTTP-date in
+ section 3.3.1; it MUST be in RFC 1123 date format:
+
+ Expires = "Expires" ":" HTTP-date
+
+ An example of its use is
+
+ Expires: Thu, 01 Dec 1994 16:00:00 GMT
+
+ Note: if a response includes a Cache-Control field with the max-
+ age directive (see section 14.9.3), that directive overrides the
+ Expires field.
+
+ HTTP/1.1 clients and caches MUST treat other invalid date formats,
+ especially including the value "0", as in the past (i.e., "already
+ expired").
+
+ To mark a response as "already expired," an origin server sends an
+ Expires date that is equal to the Date header value. (See the rules
+ for expiration calculations in section 13.2.4.)
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 127]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ To mark a response as "never expires," an origin server sends an
+ Expires date approximately one year from the time the response is
+ sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one
+ year in the future.
+
+ The presence of an Expires header field with a date value of some
+ time in the future on a response that otherwise would by default be
+ non-cacheable indicates that the response is cacheable, unless
+ indicated otherwise by a Cache-Control header field (section 14.9).
+
+14.22 From
+
+ The From request-header field, if given, SHOULD contain an Internet
+ e-mail address for the human user who controls the requesting user
+ agent. The address SHOULD be machine-usable, as defined by "mailbox"
+ in RFC 822 [9] as updated by RFC 1123 [8]:
+
+ From = "From" ":" mailbox
+
+ An example is:
+
+ From: webmaster@w3.org
+
+ This header field MAY be used for logging purposes and as a means for
+ identifying the source of invalid or unwanted requests. It SHOULD NOT
+ be used as an insecure form of access protection. The interpretation
+ of this field is that the request is being performed on behalf of the
+ person given, who accepts responsibility for the method performed. In
+ particular, robot agents SHOULD include this header so that the
+ person responsible for running the robot can be contacted if problems
+ occur on the receiving end.
+
+ The Internet e-mail address in this field MAY be separate from the
+ Internet host which issued the request. For example, when a request
+ is passed through a proxy the original issuer's address SHOULD be
+ used.
+
+ The client SHOULD NOT send the From header field without the user's
+ approval, as it might conflict with the user's privacy interests or
+ their site's security policy. It is strongly recommended that the
+ user be able to disable, enable, and modify the value of this field
+ at any time prior to a request.
+
+14.23 Host
+
+ The Host request-header field specifies the Internet host and port
+ number of the resource being requested, as obtained from the original
+ URI given by the user or referring resource (generally an HTTP URL,
+
+
+
+Fielding, et al. Standards Track [Page 128]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ as described in section 3.2.2). The Host field value MUST represent
+ the naming authority of the origin server or gateway given by the
+ original URL. This allows the origin server or gateway to
+ differentiate between internally-ambiguous URLs, such as the root "/"
+ URL of a server for multiple host names on a single IP address.
+
+ Host = "Host" ":" host [ ":" port ] ; Section 3.2.2
+
+ A "host" without any trailing port information implies the default
+ port for the service requested (e.g., "80" for an HTTP URL). For
+ example, a request on the origin server for
+ <http://www.w3.org/pub/WWW/> would properly include:
+
+ GET /pub/WWW/ HTTP/1.1
+ Host: www.w3.org
+
+ A client MUST include a Host header field in all HTTP/1.1 request
+ messages . If the requested URI does not include an Internet host
+ name for the service being requested, then the Host header field MUST
+ be given with an empty value. An HTTP/1.1 proxy MUST ensure that any
+ request message it forwards does contain an appropriate Host header
+ field that identifies the service being requested by the proxy. All
+ Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request)
+ status code to any HTTP/1.1 request message which lacks a Host header
+ field.
+
+ See sections 5.2 and 19.6.1.1 for other requirements relating to
+ Host.
+
+14.24 If-Match
+
+ The If-Match request-header field is used with a method to make it
+ conditional. A client that has one or more entities previously
+ obtained from the resource can verify that one of those entities is
+ current by including a list of their associated entity tags in the
+ If-Match header field. Entity tags are defined in section 3.11. The
+ purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead. It is also
+ used, on updating requests, to prevent inadvertent modification of
+ the wrong version of a resource. As a special case, the value "*"
+ matches any current entity of the resource.
+
+ If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-Match header) on that resource, or if "*" is given
+
+
+
+
+Fielding, et al. Standards Track [Page 129]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ and any current entity exists for that resource, then the server MAY
+ perform the requested method as if the If-Match header field did not
+ exist.
+
+ A server MUST use the strong comparison function (see section 13.3.3)
+ to compare the entity tags in If-Match.
+
+ If none of the entity tags match, or if "*" is given and no current
+ entity exists, the server MUST NOT perform the requested method, and
+ MUST return a 412 (Precondition Failed) response. This behavior is
+ most useful when the client wants to prevent an updating method, such
+ as PUT, from modifying a resource that has changed since the client
+ last retrieved it.
+
+ If the request would, without the If-Match header field, result in
+ anything other than a 2xx or 412 status, then the If-Match header
+ MUST be ignored.
+
+ The meaning of "If-Match: *" is that the method SHOULD be performed
+ if the representation selected by the origin server (or by a cache,
+ possibly using the Vary mechanism, see section 14.44) exists, and
+ MUST NOT be performed if the representation does not exist.
+
+ A request intended to update a resource (e.g., a PUT) MAY include an
+ If-Match header field to signal that the request method MUST NOT be
+ applied if the entity corresponding to the If-Match value (a single
+ entity tag) is no longer a representation of that resource. This
+ allows the user to indicate that they do not wish the request to be
+ successful if the resource has been changed without their knowledge.
+ Examples:
+
+ If-Match: "xyzzy"
+ If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-Match: *
+
+ The result of a request having both an If-Match header field and
+ either an If-None-Match or an If-Modified-Since header fields is
+ undefined by this specification.
+
+14.25 If-Modified-Since
+
+ The If-Modified-Since request-header field is used with a method to
+ make it conditional: if the requested variant has not been modified
+ since the time specified in this field, an entity will not be
+ returned from the server; instead, a 304 (not modified) response will
+ be returned without any message-body.
+
+ If-Modified-Since = "If-Modified-Since" ":" HTTP-date
+
+
+
+Fielding, et al. Standards Track [Page 130]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ An example of the field is:
+
+ If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ A GET method with an If-Modified-Since header and no Range header
+ requests that the identified entity be transferred only if it has
+ been modified since the date given by the If-Modified-Since header.
+ The algorithm for determining this includes the following cases:
+
+ a) If the request would normally result in anything other than a
+ 200 (OK) status, or if the passed If-Modified-Since date is
+ invalid, the response is exactly the same as for a normal GET.
+ A date which is later than the server's current time is
+ invalid.
+
+ b) If the variant has been modified since the If-Modified-Since
+ date, the response is exactly the same as for a normal GET.
+
+ c) If the variant has not been modified since a valid If-
+ Modified-Since date, the server SHOULD return a 304 (Not
+ Modified) response.
+
+ The purpose of this feature is to allow efficient updates of cached
+ information with a minimum amount of transaction overhead.
+
+ Note: The Range request-header field modifies the meaning of If-
+ Modified-Since; see section 14.35 for full details.
+
+ Note: If-Modified-Since times are interpreted by the server, whose
+ clock might not be synchronized with the client.
+
+ Note: When handling an If-Modified-Since header field, some
+ servers will use an exact date comparison function, rather than a
+ less-than function, for deciding whether to send a 304 (Not
+ Modified) response. To get best results when sending an If-
+ Modified-Since header field for cache validation, clients are
+ advised to use the exact date string received in a previous Last-
+ Modified header field whenever possible.
+
+ Note: If a client uses an arbitrary date in the If-Modified-Since
+ header instead of a date taken from the Last-Modified header for
+ the same request, the client should be aware of the fact that this
+ date is interpreted in the server's understanding of time. The
+ client should consider unsynchronized clocks and rounding problems
+ due to the different encodings of time between the client and
+ server. This includes the possibility of race conditions if the
+ document has changed between the time it was first requested and
+ the If-Modified-Since date of a subsequent request, and the
+
+
+
+Fielding, et al. Standards Track [Page 131]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ possibility of clock-skew-related problems if the If-Modified-
+ Since date is derived from the client's clock without correction
+ to the server's clock. Corrections for different time bases
+ between client and server are at best approximate due to network
+ latency.
+
+ The result of a request having both an If-Modified-Since header field
+ and either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.26 If-None-Match
+
+ The If-None-Match request-header field is used with a method to make
+ it conditional. A client that has one or more entities previously
+ obtained from the resource can verify that none of those entities is
+ current by including a list of their associated entity tags in the
+ If-None-Match header field. The purpose of this feature is to allow
+ efficient updates of cached information with a minimum amount of
+ transaction overhead. It is also used to prevent a method (e.g. PUT)
+ from inadvertently modifying an existing resource when the client
+ believes that the resource does not exist.
+
+ As a special case, the value "*" matches any current entity of the
+ resource.
+
+ If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )
+
+ If any of the entity tags match the entity tag of the entity that
+ would have been returned in the response to a similar GET request
+ (without the If-None-Match header) on that resource, or if "*" is
+ given and any current entity exists for that resource, then the
+ server MUST NOT perform the requested method, unless required to do
+ so because the resource's modification date fails to match that
+ supplied in an If-Modified-Since header field in the request.
+ Instead, if the request method was GET or HEAD, the server SHOULD
+ respond with a 304 (Not Modified) response, including the cache-
+ related header fields (particularly ETag) of one of the entities that
+ matched. For all other request methods, the server MUST respond with
+ a status of 412 (Precondition Failed).
+
+ See section 13.3.3 for rules on how to determine if two entities tags
+ match. The weak comparison function can only be used with GET or HEAD
+ requests.
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 132]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If none of the entity tags match, then the server MAY perform the
+ requested method as if the If-None-Match header field did not exist,
+ but MUST also ignore any If-Modified-Since header field(s) in the
+ request. That is, if no entity tags match, then the server MUST NOT
+ return a 304 (Not Modified) response.
+
+ If the request would, without the If-None-Match header field, result
+ in anything other than a 2xx or 304 status, then the If-None-Match
+ header MUST be ignored. (See section 13.3.4 for a discussion of
+ server behavior when both If-Modified-Since and If-None-Match appear
+ in the same request.)
+
+ The meaning of "If-None-Match: *" is that the method MUST NOT be
+ performed if the representation selected by the origin server (or by
+ a cache, possibly using the Vary mechanism, see section 14.44)
+ exists, and SHOULD be performed if the representation does not exist.
+ This feature is intended to be useful in preventing races between PUT
+ operations.
+
+ Examples:
+
+ If-None-Match: "xyzzy"
+ If-None-Match: W/"xyzzy"
+ If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
+ If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
+ If-None-Match: *
+
+ The result of a request having both an If-None-Match header field and
+ either an If-Match or an If-Unmodified-Since header fields is
+ undefined by this specification.
+
+14.27 If-Range
+
+ If a client has a partial copy of an entity in its cache, and wishes
+ to have an up-to-date copy of the entire entity in its cache, it
+ could use the Range request-header with a conditional GET (using
+ either or both of If-Unmodified-Since and If-Match.) However, if the
+ condition fails because the entity has been modified, the client
+ would then have to make a second request to obtain the entire current
+ entity-body.
+
+ The If-Range header allows a client to "short-circuit" the second
+ request. Informally, its meaning is `if the entity is unchanged, send
+ me the part(s) that I am missing; otherwise, send me the entire new
+ entity'.
+
+ If-Range = "If-Range" ":" ( entity-tag | HTTP-date )
+
+
+
+
+Fielding, et al. Standards Track [Page 133]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If the client has no entity tag for an entity, but does have a Last-
+ Modified date, it MAY use that date in an If-Range header. (The
+ server can distinguish between a valid HTTP-date and any form of
+ entity-tag by examining no more than two characters.) The If-Range
+ header SHOULD only be used together with a Range header, and MUST be
+ ignored if the request does not include a Range header, or if the
+ server does not support the sub-range operation.
+
+ If the entity tag given in the If-Range header matches the current
+ entity tag for the entity, then the server SHOULD provide the
+ specified sub-range of the entity using a 206 (Partial content)
+ response. If the entity tag does not match, then the server SHOULD
+ return the entire entity using a 200 (OK) response.
+
+14.28 If-Unmodified-Since
+
+ The If-Unmodified-Since request-header field is used with a method to
+ make it conditional. If the requested resource has not been modified
+ since the time specified in this field, the server SHOULD perform the
+ requested operation as if the If-Unmodified-Since header were not
+ present.
+
+ If the requested variant has been modified since the specified time,
+ the server MUST NOT perform the requested operation, and MUST return
+ a 412 (Precondition Failed).
+
+ If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date
+
+ An example of the field is:
+
+ If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
+
+ If the request normally (i.e., without the If-Unmodified-Since
+ header) would result in anything other than a 2xx or 412 status, the
+ If-Unmodified-Since header SHOULD be ignored.
+
+ If the specified date is invalid, the header is ignored.
+
+ The result of a request having both an If-Unmodified-Since header
+ field and either an If-None-Match or an If-Modified-Since header
+ fields is undefined by this specification.
+
+14.29 Last-Modified
+
+ The Last-Modified entity-header field indicates the date and time at
+ which the origin server believes the variant was last modified.
+
+ Last-Modified = "Last-Modified" ":" HTTP-date
+
+
+
+Fielding, et al. Standards Track [Page 134]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ An example of its use is
+
+ Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
+
+ The exact meaning of this header field depends on the implementation
+ of the origin server and the nature of the original resource. For
+ files, it may be just the file system last-modified time. For
+ entities with dynamically included parts, it may be the most recent
+ of the set of last-modify times for its component parts. For database
+ gateways, it may be the last-update time stamp of the record. For
+ virtual objects, it may be the last time the internal state changed.
+
+ An origin server MUST NOT send a Last-Modified date which is later
+ than the server's time of message origination. In such cases, where
+ the resource's last modification would indicate some time in the
+ future, the server MUST replace that date with the message
+ origination date.
+
+ An origin server SHOULD obtain the Last-Modified value of the entity
+ as close as possible to the time that it generates the Date value of
+ its response. This allows a recipient to make an accurate assessment
+ of the entity's modification time, especially if the entity changes
+ near the time that the response is generated.
+
+ HTTP/1.1 servers SHOULD send Last-Modified whenever feasible.
+
+14.30 Location
+
+ The Location response-header field is used to redirect the recipient
+ to a location other than the Request-URI for completion of the
+ request or identification of a new resource. For 201 (Created)
+ responses, the Location is that of the new resource which was created
+ by the request. For 3xx responses, the location SHOULD indicate the
+ server's preferred URI for automatic redirection to the resource. The
+ field value consists of a single absolute URI.
+
+ Location = "Location" ":" absoluteURI
+
+ An example is:
+
+ Location: http://www.w3.org/pub/WWW/People.html
+
+ Note: The Content-Location header field (section 14.14) differs
+ from Location in that the Content-Location identifies the original
+ location of the entity enclosed in the request. It is therefore
+ possible for a response to contain header fields for both Location
+ and Content-Location. Also see section 13.10 for cache
+ requirements of some methods.
+
+
+
+Fielding, et al. Standards Track [Page 135]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.31 Max-Forwards
+
+ The Max-Forwards request-header field provides a mechanism with the
+ TRACE (section 9.8) and OPTIONS (section 9.2) methods to limit the
+ number of proxies or gateways that can forward the request to the
+ next inbound server. This can be useful when the client is attempting
+ to trace a request chain which appears to be failing or looping in
+ mid-chain.
+
+ Max-Forwards = "Max-Forwards" ":" 1*DIGIT
+
+ The Max-Forwards value is a decimal integer indicating the remaining
+ number of times this request message may be forwarded.
+
+ Each proxy or gateway recipient of a TRACE or OPTIONS request
+ containing a Max-Forwards header field MUST check and update its
+ value prior to forwarding the request. If the received value is zero
+ (0), the recipient MUST NOT forward the request; instead, it MUST
+ respond as the final recipient. If the received Max-Forwards value is
+ greater than zero, then the forwarded message MUST contain an updated
+ Max-Forwards field with a value decremented by one (1).
+
+ The Max-Forwards header field MAY be ignored for all other methods
+ defined by this specification and for any extension methods for which
+ it is not explicitly referred to as part of that method definition.
+
+14.32 Pragma
+
+ The Pragma general-header field is used to include implementation-
+ specific directives that might apply to any recipient along the
+ request/response chain. All pragma directives specify optional
+ behavior from the viewpoint of the protocol; however, some systems
+ MAY require that behavior be consistent with the directives.
+
+ Pragma = "Pragma" ":" 1#pragma-directive
+ pragma-directive = "no-cache" | extension-pragma
+ extension-pragma = token [ "=" ( token | quoted-string ) ]
+
+ When the no-cache directive is present in a request message, an
+ application SHOULD forward the request toward the origin server even
+ if it has a cached copy of what is being requested. This pragma
+ directive has the same semantics as the no-cache cache-directive (see
+ section 14.9) and is defined here for backward compatibility with
+ HTTP/1.0. Clients SHOULD include both header fields when a no-cache
+ request is sent to a server not known to be HTTP/1.1 compliant.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 136]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Pragma directives MUST be passed through by a proxy or gateway
+ application, regardless of their significance to that application,
+ since the directives might be applicable to all recipients along the
+ request/response chain. It is not possible to specify a pragma for a
+ specific recipient; however, any pragma directive not relevant to a
+ recipient SHOULD be ignored by that recipient.
+
+ HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client had
+ sent "Cache-Control: no-cache". No new Pragma directives will be
+ defined in HTTP.
+
+ Note: because the meaning of "Pragma: no-cache as a response
+ header field is not actually specified, it does not provide a
+ reliable replacement for "Cache-Control: no-cache" in a response
+
+14.33 Proxy-Authenticate
+
+ The Proxy-Authenticate response-header field MUST be included as part
+ of a 407 (Proxy Authentication Required) response. The field value
+ consists of a challenge that indicates the authentication scheme and
+ parameters applicable to the proxy for this Request-URI.
+
+ Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. Unlike
+ WWW-Authenticate, the Proxy-Authenticate header field applies only to
+ the current connection and SHOULD NOT be passed on to downstream
+ clients. However, an intermediate proxy might need to obtain its own
+ credentials by requesting them from the downstream client, which in
+ some circumstances will appear as if the proxy is forwarding the
+ Proxy-Authenticate header field.
+
+14.34 Proxy-Authorization
+
+ The Proxy-Authorization request-header field allows the client to
+ identify itself (or its user) to a proxy which requires
+ authentication. The Proxy-Authorization field value consists of
+ credentials containing the authentication information of the user
+ agent for the proxy and/or realm of the resource being requested.
+
+ Proxy-Authorization = "Proxy-Authorization" ":" credentials
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43] . Unlike
+ Authorization, the Proxy-Authorization header field applies only to
+ the next outbound proxy that demanded authentication using the Proxy-
+ Authenticate field. When multiple proxies are used in a chain, the
+
+
+
+Fielding, et al. Standards Track [Page 137]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Proxy-Authorization header field is consumed by the first outbound
+ proxy that was expecting to receive credentials. A proxy MAY relay
+ the credentials from the client request to the next proxy if that is
+ the mechanism by which the proxies cooperatively authenticate a given
+ request.
+
+14.35 Range
+
+14.35.1 Byte Ranges
+
+ Since all HTTP entities are represented in HTTP messages as sequences
+ of bytes, the concept of a byte range is meaningful for any HTTP
+ entity. (However, not all clients and servers need to support byte-
+ range operations.)
+
+ Byte range specifications in HTTP apply to the sequence of bytes in
+ the entity-body (not necessarily the same as the message-body).
+
+ A byte range operation MAY specify a single range of bytes, or a set
+ of ranges within a single entity.
+
+ ranges-specifier = byte-ranges-specifier
+ byte-ranges-specifier = bytes-unit "=" byte-range-set
+ byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
+ byte-range-spec = first-byte-pos "-" [last-byte-pos]
+ first-byte-pos = 1*DIGIT
+ last-byte-pos = 1*DIGIT
+
+ The first-byte-pos value in a byte-range-spec gives the byte-offset
+ of the first byte in a range. The last-byte-pos value gives the
+ byte-offset of the last byte in the range; that is, the byte
+ positions specified are inclusive. Byte offsets start at zero.
+
+ If the last-byte-pos value is present, it MUST be greater than or
+ equal to the first-byte-pos in that byte-range-spec, or the byte-
+ range-spec is syntactically invalid. The recipient of a byte-range-
+ set that includes one or more syntactically invalid byte-range-spec
+ values MUST ignore the header field that includes that byte-range-
+ set.
+
+ If the last-byte-pos value is absent, or if the value is greater than
+ or equal to the current length of the entity-body, last-byte-pos is
+ taken to be equal to one less than the current length of the entity-
+ body in bytes.
+
+ By its choice of last-byte-pos, a client can limit the number of
+ bytes retrieved without knowing the size of the entity.
+
+
+
+
+Fielding, et al. Standards Track [Page 138]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ suffix-byte-range-spec = "-" suffix-length
+ suffix-length = 1*DIGIT
+
+ A suffix-byte-range-spec is used to specify the suffix of the
+ entity-body, of a length given by the suffix-length value. (That is,
+ this form specifies the last N bytes of an entity-body.) If the
+ entity is shorter than the specified suffix-length, the entire
+ entity-body is used.
+
+ If a syntactically valid byte-range-set includes at least one byte-
+ range-spec whose first-byte-pos is less than the current length of
+ the entity-body, or at least one suffix-byte-range-spec with a non-
+ zero suffix-length, then the byte-range-set is satisfiable.
+ Otherwise, the byte-range-set is unsatisfiable. If the byte-range-set
+ is unsatisfiable, the server SHOULD return a response with a status
+ of 416 (Requested range not satisfiable). Otherwise, the server
+ SHOULD return a response with a status of 206 (Partial Content)
+ containing the satisfiable ranges of the entity-body.
+
+ Examples of byte-ranges-specifier values (assuming an entity-body of
+ length 10000):
+
+ - The first 500 bytes (byte offsets 0-499, inclusive): bytes=0-
+ 499
+
+ - The second 500 bytes (byte offsets 500-999, inclusive):
+ bytes=500-999
+
+ - The final 500 bytes (byte offsets 9500-9999, inclusive):
+ bytes=-500
+
+ - Or bytes=9500-
+
+ - The first and last bytes only (bytes 0 and 9999): bytes=0-0,-1
+
+ - Several legal but not canonical specifications of the second 500
+ bytes (byte offsets 500-999, inclusive):
+ bytes=500-600,601-999
+ bytes=500-700,601-999
+
+14.35.2 Range Retrieval Requests
+
+ HTTP retrieval requests using conditional or unconditional GET
+ methods MAY request one or more sub-ranges of the entity, instead of
+ the entire entity, using the Range request header, which applies to
+ the entity returned as the result of the request:
+
+ Range = "Range" ":" ranges-specifier
+
+
+
+Fielding, et al. Standards Track [Page 139]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ A server MAY ignore the Range header. However, HTTP/1.1 origin
+ servers and intermediate caches ought to support byte ranges when
+ possible, since Range supports efficient recovery from partially
+ failed transfers, and supports efficient partial retrieval of large
+ entities.
+
+ If the server supports the Range header and the specified range or
+ ranges are appropriate for the entity:
+
+ - The presence of a Range header in an unconditional GET modifies
+ what is returned if the GET is otherwise successful. In other
+ words, the response carries a status code of 206 (Partial
+ Content) instead of 200 (OK).
+
+ - The presence of a Range header in a conditional GET (a request
+ using one or both of If-Modified-Since and If-None-Match, or
+ one or both of If-Unmodified-Since and If-Match) modifies what
+ is returned if the GET is otherwise successful and the
+ condition is true. It does not affect the 304 (Not Modified)
+ response returned if the conditional is false.
+
+ In some cases, it might be more appropriate to use the If-Range
+ header (see section 14.27) in addition to the Range header.
+
+ If a proxy that supports ranges receives a Range request, forwards
+ the request to an inbound server, and receives an entire entity in
+ reply, it SHOULD only return the requested range to its client. It
+ SHOULD store the entire received response in its cache if that is
+ consistent with its cache allocation policies.
+
+14.36 Referer
+
+ The Referer[sic] request-header field allows the client to specify,
+ for the server's benefit, the address (URI) of the resource from
+ which the Request-URI was obtained (the "referrer", although the
+ header field is misspelled.) The Referer request-header allows a
+ server to generate lists of back-links to resources for interest,
+ logging, optimized caching, etc. It also allows obsolete or mistyped
+ links to be traced for maintenance. The Referer field MUST NOT be
+ sent if the Request-URI was obtained from a source that does not have
+ its own URI, such as input from the user keyboard.
+
+ Referer = "Referer" ":" ( absoluteURI | relativeURI )
+
+ Example:
+
+ Referer: http://www.w3.org/hypertext/DataSources/Overview.html
+
+
+
+
+Fielding, et al. Standards Track [Page 140]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If the field value is a relative URI, it SHOULD be interpreted
+ relative to the Request-URI. The URI MUST NOT include a fragment. See
+ section 15.1.3 for security considerations.
+
+14.37 Retry-After
+
+ The Retry-After response-header field can be used with a 503 (Service
+ Unavailable) response to indicate how long the service is expected to
+ be unavailable to the requesting client. This field MAY also be used
+ with any 3xx (Redirection) response to indicate the minimum time the
+ user-agent is asked wait before issuing the redirected request. The
+ value of this field can be either an HTTP-date or an integer number
+ of seconds (in decimal) after the time of the response.
+
+ Retry-After = "Retry-After" ":" ( HTTP-date | delta-seconds )
+
+ Two examples of its use are
+
+ Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+ Retry-After: 120
+
+ In the latter example, the delay is 2 minutes.
+
+14.38 Server
+
+ The Server response-header field contains information about the
+ software used by the origin server to handle the request. The field
+ can contain multiple product tokens (section 3.8) and comments
+ identifying the server and any significant subproducts. The product
+ tokens are listed in order of their significance for identifying the
+ application.
+
+ Server = "Server" ":" 1*( product | comment )
+
+ Example:
+
+ Server: CERN/3.0 libwww/2.17
+
+ If the response is being forwarded through a proxy, the proxy
+ application MUST NOT modify the Server response-header. Instead, it
+ SHOULD include a Via field (as described in section 14.45).
+
+ Note: Revealing the specific software version of the server might
+ allow the server machine to become more vulnerable to attacks
+ against software that is known to contain security holes. Server
+ implementors are encouraged to make this field a configurable
+ option.
+
+
+
+
+Fielding, et al. Standards Track [Page 141]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+14.39 TE
+
+ The TE request-header field indicates what extension transfer-codings
+ it is willing to accept in the response and whether or not it is
+ willing to accept trailer fields in a chunked transfer-coding. Its
+ value may consist of the keyword "trailers" and/or a comma-separated
+ list of extension transfer-coding names with optional accept
+ parameters (as described in section 3.6).
+
+ TE = "TE" ":" #( t-codings )
+ t-codings = "trailers" | ( transfer-extension [ accept-params ] )
+
+ The presence of the keyword "trailers" indicates that the client is
+ willing to accept trailer fields in a chunked transfer-coding, as
+ defined in section 3.6.1. This keyword is reserved for use with
+ transfer-coding values even though it does not itself represent a
+ transfer-coding.
+
+ Examples of its use are:
+
+ TE: deflate
+ TE:
+ TE: trailers, deflate;q=0.5
+
+ The TE header field only applies to the immediate connection.
+ Therefore, the keyword MUST be supplied within a Connection header
+ field (section 14.10) whenever TE is present in an HTTP/1.1 message.
+
+ A server tests whether a transfer-coding is acceptable, according to
+ a TE field, using these rules:
+
+ 1. The "chunked" transfer-coding is always acceptable. If the
+ keyword "trailers" is listed, the client indicates that it is
+ willing to accept trailer fields in the chunked response on
+ behalf of itself and any downstream clients. The implication is
+ that, if given, the client is stating that either all
+ downstream clients are willing to accept trailer fields in the
+ forwarded response, or that it will attempt to buffer the
+ response on behalf of downstream recipients.
+
+ Note: HTTP/1.1 does not define any means to limit the size of a
+ chunked response such that a client can be assured of buffering
+ the entire response.
+
+ 2. If the transfer-coding being tested is one of the transfer-
+ codings listed in the TE field, then it is acceptable unless it
+ is accompanied by a qvalue of 0. (As defined in section 3.9, a
+ qvalue of 0 means "not acceptable.")
+
+
+
+Fielding, et al. Standards Track [Page 142]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 3. If multiple transfer-codings are acceptable, then the
+ acceptable transfer-coding with the highest non-zero qvalue is
+ preferred. The "chunked" transfer-coding always has a qvalue
+ of 1.
+
+ If the TE field-value is empty or if no TE field is present, the only
+ transfer-coding is "chunked". A message with no transfer-coding is
+ always acceptable.
+
+14.40 Trailer
+
+ The Trailer general field value indicates that the given set of
+ header fields is present in the trailer of a message encoded with
+ chunked transfer-coding.
+
+ Trailer = "Trailer" ":" 1#field-name
+
+ An HTTP/1.1 message SHOULD include a Trailer header field in a
+ message using chunked transfer-coding with a non-empty trailer. Doing
+ so allows the recipient to know which header fields to expect in the
+ trailer.
+
+ If no Trailer header field is present, the trailer SHOULD NOT include
+ any header fields. See section 3.6.1 for restrictions on the use of
+ trailer fields in a "chunked" transfer-coding.
+
+ Message header fields listed in the Trailer header field MUST NOT
+ include the following header fields:
+
+ . Transfer-Encoding
+
+ . Content-Length
+
+ . Trailer
+
+14.41 Transfer-Encoding
+
+ The Transfer-Encoding general-header field indicates what (if any)
+ type of transformation has been applied to the message body in order
+ to safely transfer it between the sender and the recipient. This
+ differs from the content-coding in that the transfer-coding is a
+ property of the message, not of the entity.
+
+ Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
+
+ Transfer-codings are defined in section 3.6. An example is:
+
+ Transfer-Encoding: chunked
+
+
+
+Fielding, et al. Standards Track [Page 143]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ If multiple encodings have been applied to an entity, the transfer-
+ codings MUST be listed in the order in which they were applied.
+ Additional information about the encoding parameters MAY be provided
+ by other entity-header fields not defined by this specification.
+
+ Many older HTTP/1.0 applications do not understand the Transfer-
+ Encoding header.
+
+14.42 Upgrade
+
+ The Upgrade general-header allows the client to specify what
+ additional communication protocols it supports and would like to use
+ if the server finds it appropriate to switch protocols. The server
+ MUST use the Upgrade header field within a 101 (Switching Protocols)
+ response to indicate which protocol(s) are being switched.
+
+ Upgrade = "Upgrade" ":" 1#product
+
+ For example,
+
+ Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
+
+ The Upgrade header field is intended to provide a simple mechanism
+ for transition from HTTP/1.1 to some other, incompatible protocol. It
+ does so by allowing the client to advertise its desire to use another
+ protocol, such as a later version of HTTP with a higher major version
+ number, even though the current request has been made using HTTP/1.1.
+ This eases the difficult transition between incompatible protocols by
+ allowing the client to initiate a request in the more commonly
+ supported protocol while indicating to the server that it would like
+ to use a "better" protocol if available (where "better" is determined
+ by the server, possibly according to the nature of the method and/or
+ resource being requested).
+
+ The Upgrade header field only applies to switching application-layer
+ protocols upon the existing transport-layer connection. Upgrade
+ cannot be used to insist on a protocol change; its acceptance and use
+ by the server is optional. The capabilities and nature of the
+ application-layer communication after the protocol change is entirely
+ dependent upon the new protocol chosen, although the first action
+ after changing the protocol MUST be a response to the initial HTTP
+ request containing the Upgrade header field.
+
+ The Upgrade header field only applies to the immediate connection.
+ Therefore, the upgrade keyword MUST be supplied within a Connection
+ header field (section 14.10) whenever Upgrade is present in an
+ HTTP/1.1 message.
+
+
+
+
+Fielding, et al. Standards Track [Page 144]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The Upgrade header field cannot be used to indicate a switch to a
+ protocol on a different connection. For that purpose, it is more
+ appropriate to use a 301, 302, 303, or 305 redirection response.
+
+ This specification only defines the protocol name "HTTP" for use by
+ the family of Hypertext Transfer Protocols, as defined by the HTTP
+ version rules of section 3.1 and future updates to this
+ specification. Any token can be used as a protocol name; however, it
+ will only be useful if both the client and server associate the name
+ with the same protocol.
+
+14.43 User-Agent
+
+ The User-Agent request-header field contains information about the
+ user agent originating the request. This is for statistical purposes,
+ the tracing of protocol violations, and automated recognition of user
+ agents for the sake of tailoring responses to avoid particular user
+ agent limitations. User agents SHOULD include this field with
+ requests. The field can contain multiple product tokens (section 3.8)
+ and comments identifying the agent and any subproducts which form a
+ significant part of the user agent. By convention, the product tokens
+ are listed in order of their significance for identifying the
+ application.
+
+ User-Agent = "User-Agent" ":" 1*( product | comment )
+
+ Example:
+
+ User-Agent: CERN-LineMode/2.15 libwww/2.17b3
+
+14.44 Vary
+
+ The Vary field value indicates the set of request-header fields that
+ fully determines, while the response is fresh, whether a cache is
+ permitted to use the response to reply to a subsequent request
+ without revalidation. For uncacheable or stale responses, the Vary
+ field value advises the user agent about the criteria that were used
+ to select the representation. A Vary field value of "*" implies that
+ a cache cannot determine from the request headers of a subsequent
+ request whether this response is the appropriate representation. See
+ section 13.6 for use of the Vary header field by caches.
+
+ Vary = "Vary" ":" ( "*" | 1#field-name )
+
+ An HTTP/1.1 server SHOULD include a Vary header field with any
+ cacheable response that is subject to server-driven negotiation.
+ Doing so allows a cache to properly interpret future requests on that
+ resource and informs the user agent about the presence of negotiation
+
+
+
+Fielding, et al. Standards Track [Page 145]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ on that resource. A server MAY include a Vary header field with a
+ non-cacheable response that is subject to server-driven negotiation,
+ since this might provide the user agent with useful information about
+ the dimensions over which the response varies at the time of the
+ response.
+
+ A Vary field value consisting of a list of field-names signals that
+ the representation selected for the response is based on a selection
+ algorithm which considers ONLY the listed request-header field values
+ in selecting the most appropriate representation. A cache MAY assume
+ that the same selection will be made for future requests with the
+ same values for the listed field names, for the duration of time for
+ which the response is fresh.
+
+ The field-names given are not limited to the set of standard
+ request-header fields defined by this specification. Field names are
+ case-insensitive.
+
+ A Vary field value of "*" signals that unspecified parameters not
+ limited to the request-headers (e.g., the network address of the
+ client), play a role in the selection of the response representation.
+ The "*" value MUST NOT be generated by a proxy server; it may only be
+ generated by an origin server.
+
+14.45 Via
+
+ The Via general-header field MUST be used by gateways and proxies to
+ indicate the intermediate protocols and recipients between the user
+ agent and the server on requests, and between the origin server and
+ the client on responses. It is analogous to the "Received" field of
+ RFC 822 [9] and is intended to be used for tracking message forwards,
+ avoiding request loops, and identifying the protocol capabilities of
+ all senders along the request/response chain.
+
+ Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
+ received-protocol = [ protocol-name "/" ] protocol-version
+ protocol-name = token
+ protocol-version = token
+ received-by = ( host [ ":" port ] ) | pseudonym
+ pseudonym = token
+
+ The received-protocol indicates the protocol version of the message
+ received by the server or client along each segment of the
+ request/response chain. The received-protocol version is appended to
+ the Via field value when the message is forwarded so that information
+ about the protocol capabilities of upstream applications remains
+ visible to all recipients.
+
+
+
+
+Fielding, et al. Standards Track [Page 146]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The protocol-name is optional if and only if it would be "HTTP". The
+ received-by field is normally the host and optional port number of a
+ recipient server or client that subsequently forwarded the message.
+ However, if the real host is considered to be sensitive information,
+ it MAY be replaced by a pseudonym. If the port is not given, it MAY
+ be assumed to be the default port of the received-protocol.
+
+ Multiple Via field values represents each proxy or gateway that has
+ forwarded the message. Each recipient MUST append its information
+ such that the end result is ordered according to the sequence of
+ forwarding applications.
+
+ Comments MAY be used in the Via header field to identify the software
+ of the recipient proxy or gateway, analogous to the User-Agent and
+ Server header fields. However, all comments in the Via field are
+ optional and MAY be removed by any recipient prior to forwarding the
+ message.
+
+ For example, a request message could be sent from an HTTP/1.0 user
+ agent to an internal proxy code-named "fred", which uses HTTP/1.1 to
+ forward the request to a public proxy at nowhere.com, which completes
+ the request by forwarding it to the origin server at www.ics.uci.edu.
+ The request received by www.ics.uci.edu would then have the following
+ Via header field:
+
+ Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
+
+ Proxies and gateways used as a portal through a network firewall
+ SHOULD NOT, by default, forward the names and ports of hosts within
+ the firewall region. This information SHOULD only be propagated if
+ explicitly enabled. If not enabled, the received-by host of any host
+ behind the firewall SHOULD be replaced by an appropriate pseudonym
+ for that host.
+
+ For organizations that have strong privacy requirements for hiding
+ internal structures, a proxy MAY combine an ordered subsequence of
+ Via header field entries with identical received-protocol values into
+ a single such entry. For example,
+
+ Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy
+
+ could be collapsed to
+
+ Via: 1.0 ricky, 1.1 mertz, 1.0 lucy
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 147]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Applications SHOULD NOT combine multiple entries unless they are all
+ under the same organizational control and the hosts have already been
+ replaced by pseudonyms. Applications MUST NOT combine entries which
+ have different received-protocol values.
+
+14.46 Warning
+
+ The Warning general-header field is used to carry additional
+ information about the status or transformation of a message which
+ might not be reflected in the message. This information is typically
+ used to warn about a possible lack of semantic transparency from
+ caching operations or transformations applied to the entity body of
+ the message.
+
+ Warning headers are sent with responses using:
+
+ Warning = "Warning" ":" 1#warning-value
+
+ warning-value = warn-code SP warn-agent SP warn-text
+ [SP warn-date]
+
+ warn-code = 3DIGIT
+ warn-agent = ( host [ ":" port ] ) | pseudonym
+ ; the name or pseudonym of the server adding
+ ; the Warning header, for use in debugging
+ warn-text = quoted-string
+ warn-date = <"> HTTP-date <">
+
+ A response MAY carry more than one Warning header.
+
+ The warn-text SHOULD be in a natural language and character set that
+ is most likely to be intelligible to the human user receiving the
+ response. This decision MAY be based on any available knowledge, such
+ as the location of the cache or user, the Accept-Language field in a
+ request, the Content-Language field in a response, etc. The default
+ language is English and the default character set is ISO-8859-1.
+
+ If a character set other than ISO-8859-1 is used, it MUST be encoded
+ in the warn-text using the method described in RFC 2047 [14].
+
+ Warning headers can in general be applied to any message, however
+ some specific warn-codes are specific to caches and can only be
+ applied to response messages. New Warning headers SHOULD be added
+ after any existing Warning headers. A cache MUST NOT delete any
+ Warning header that it received with a message. However, if a cache
+ successfully validates a cache entry, it SHOULD remove any Warning
+ headers previously attached to that entry except as specified for
+
+
+
+
+Fielding, et al. Standards Track [Page 148]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ specific Warning codes. It MUST then add any Warning headers received
+ in the validating response. In other words, Warning headers are those
+ that would be attached to the most recent relevant response.
+
+ When multiple Warning headers are attached to a response, the user
+ agent ought to inform the user of as many of them as possible, in the
+ order that they appear in the response. If it is not possible to
+ inform the user of all of the warnings, the user agent SHOULD follow
+ these heuristics:
+
+ - Warnings that appear early in the response take priority over
+ those appearing later in the response.
+
+ - Warnings in the user's preferred character set take priority
+ over warnings in other character sets but with identical warn-
+ codes and warn-agents.
+
+ Systems that generate multiple Warning headers SHOULD order them with
+ this user agent behavior in mind.
+
+ Requirements for the behavior of caches with respect to Warnings are
+ stated in section 13.1.2.
+
+ This is a list of the currently-defined warn-codes, each with a
+ recommended warn-text in English, and a description of its meaning.
+
+ 110 Response is stale
+ MUST be included whenever the returned response is stale.
+
+ 111 Revalidation failed
+ MUST be included if a cache returns a stale response because an
+ attempt to revalidate the response failed, due to an inability to
+ reach the server.
+
+ 112 Disconnected operation
+ SHOULD be included if the cache is intentionally disconnected from
+ the rest of the network for a period of time.
+
+ 113 Heuristic expiration
+ MUST be included if the cache heuristically chose a freshness
+ lifetime greater than 24 hours and the response's age is greater
+ than 24 hours.
+
+ 199 Miscellaneous warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action, besides presenting the warning to
+ the user.
+
+
+
+Fielding, et al. Standards Track [Page 149]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 214 Transformation applied
+ MUST be added by an intermediate cache or proxy if it applies any
+ transformation changing the content-coding (as specified in the
+ Content-Encoding header) or media-type (as specified in the
+ Content-Type header) of the response, or the entity-body of the
+ response, unless this Warning code already appears in the response.
+
+ 299 Miscellaneous persistent warning
+ The warning text MAY include arbitrary information to be presented
+ to a human user, or logged. A system receiving this warning MUST
+ NOT take any automated action.
+
+ If an implementation sends a message with one or more Warning headers
+ whose version is HTTP/1.0 or lower, then the sender MUST include in
+ each warning-value a warn-date that matches the date in the response.
+
+ If an implementation receives a message with a warning-value that
+ includes a warn-date, and that warn-date is different from the Date
+ value in the response, then that warning-value MUST be deleted from
+ the message before storing, forwarding, or using it. (This prevents
+ bad consequences of naive caching of Warning header fields.) If all
+ of the warning-values are deleted for this reason, the Warning header
+ MUST be deleted as well.
+
+14.47 WWW-Authenticate
+
+ The WWW-Authenticate response-header field MUST be included in 401
+ (Unauthorized) response messages. The field value consists of at
+ least one challenge that indicates the authentication scheme(s) and
+ parameters applicable to the Request-URI.
+
+ WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge
+
+ The HTTP access authentication process is described in "HTTP
+ Authentication: Basic and Digest Access Authentication" [43]. User
+ agents are advised to take special care in parsing the WWW-
+ Authenticate field value as it might contain more than one challenge,
+ or if more than one WWW-Authenticate header field is provided, the
+ contents of a challenge itself can contain a comma-separated list of
+ authentication parameters.
+
+15 Security Considerations
+
+ This section is meant to inform application developers, information
+ providers, and users of the security limitations in HTTP/1.1 as
+ described by this document. The discussion does not include
+ definitive solutions to the problems revealed, though it does make
+ some suggestions for reducing security risks.
+
+
+
+Fielding, et al. Standards Track [Page 150]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+15.1 Personal Information
+
+ HTTP clients are often privy to large amounts of personal information
+ (e.g. the user's name, location, mail address, passwords, encryption
+ keys, etc.), and SHOULD be very careful to prevent unintentional
+ leakage of this information via the HTTP protocol to other sources.
+ We very strongly recommend that a convenient interface be provided
+ for the user to control dissemination of such information, and that
+ designers and implementors be particularly careful in this area.
+ History shows that errors in this area often create serious security
+ and/or privacy problems and generate highly adverse publicity for the
+ implementor's company.
+
+15.1.1 Abuse of Server Log Information
+
+ A server is in the position to save personal data about a user's
+ requests which might identify their reading patterns or subjects of
+ interest. This information is clearly confidential in nature and its
+ handling can be constrained by law in certain countries. People using
+ the HTTP protocol to provide data are responsible for ensuring that
+ such material is not distributed without the permission of any
+ individuals that are identifiable by the published results.
+
+15.1.2 Transfer of Sensitive Information
+
+ Like any generic data transfer protocol, HTTP cannot regulate the
+ content of the data that is transferred, nor is there any a priori
+ method of determining the sensitivity of any particular piece of
+ information within the context of any given request. Therefore,
+ applications SHOULD supply as much control over this information as
+ possible to the provider of that information. Four header fields are
+ worth special mention in this context: Server, Via, Referer and From.
+
+ Revealing the specific software version of the server might allow the
+ server machine to become more vulnerable to attacks against software
+ that is known to contain security holes. Implementors SHOULD make the
+ Server header field a configurable option.
+
+ Proxies which serve as a portal through a network firewall SHOULD
+ take special precautions regarding the transfer of header information
+ that identifies the hosts behind the firewall. In particular, they
+ SHOULD remove, or replace with sanitized versions, any Via fields
+ generated behind the firewall.
+
+ The Referer header allows reading patterns to be studied and reverse
+ links drawn. Although it can be very useful, its power can be abused
+ if user details are not separated from the information contained in
+
+
+
+
+Fielding, et al. Standards Track [Page 151]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ the Referer. Even when the personal information has been removed, the
+ Referer header might indicate a private document's URI whose
+ publication would be inappropriate.
+
+ The information sent in the From field might conflict with the user's
+ privacy interests or their site's security policy, and hence it
+ SHOULD NOT be transmitted without the user being able to disable,
+ enable, and modify the contents of the field. The user MUST be able
+ to set the contents of this field within a user preference or
+ application defaults configuration.
+
+ We suggest, though do not require, that a convenient toggle interface
+ be provided for the user to enable or disable the sending of From and
+ Referer information.
+
+ The User-Agent (section 14.43) or Server (section 14.38) header
+ fields can sometimes be used to determine that a specific client or
+ server have a particular security hole which might be exploited.
+ Unfortunately, this same information is often used for other valuable
+ purposes for which HTTP currently has no better mechanism.
+
+15.1.3 Encoding Sensitive Information in URI's
+
+ Because the source of a link might be private information or might
+ reveal an otherwise private information source, it is strongly
+ recommended that the user be able to select whether or not the
+ Referer field is sent. For example, a browser client could have a
+ toggle switch for browsing openly/anonymously, which would
+ respectively enable/disable the sending of Referer and From
+ information.
+
+ Clients SHOULD NOT include a Referer header field in a (non-secure)
+ HTTP request if the referring page was transferred with a secure
+ protocol.
+
+ Authors of services which use the HTTP protocol SHOULD NOT use GET
+ based forms for the submission of sensitive data, because this will
+ cause this data to be encoded in the Request-URI. Many existing
+ servers, proxies, and user agents will log the request URI in some
+ place where it might be visible to third parties. Servers can use
+ POST-based form submission instead
+
+15.1.4 Privacy Issues Connected to Accept Headers
+
+ Accept request-headers can reveal information about the user to all
+ servers which are accessed. The Accept-Language header in particular
+ can reveal information the user would consider to be of a private
+ nature, because the understanding of particular languages is often
+
+
+
+Fielding, et al. Standards Track [Page 152]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ strongly correlated to the membership of a particular ethnic group.
+ User agents which offer the option to configure the contents of an
+ Accept-Language header to be sent in every request are strongly
+ encouraged to let the configuration process include a message which
+ makes the user aware of the loss of privacy involved.
+
+ An approach that limits the loss of privacy would be for a user agent
+ to omit the sending of Accept-Language headers by default, and to ask
+ the user whether or not to start sending Accept-Language headers to a
+ server if it detects, by looking for any Vary response-header fields
+ generated by the server, that such sending could improve the quality
+ of service.
+
+ Elaborate user-customized accept header fields sent in every request,
+ in particular if these include quality values, can be used by servers
+ as relatively reliable and long-lived user identifiers. Such user
+ identifiers would allow content providers to do click-trail tracking,
+ and would allow collaborating content providers to match cross-server
+ click-trails or form submissions of individual users. Note that for
+ many users not behind a proxy, the network address of the host
+ running the user agent will also serve as a long-lived user
+ identifier. In environments where proxies are used to enhance
+ privacy, user agents ought to be conservative in offering accept
+ header configuration options to end users. As an extreme privacy
+ measure, proxies could filter the accept headers in relayed requests.
+ General purpose user agents which provide a high degree of header
+ configurability SHOULD warn users about the loss of privacy which can
+ be involved.
+
+15.2 Attacks Based On File and Path Names
+
+ Implementations of HTTP origin servers SHOULD be careful to restrict
+ the documents returned by HTTP requests to be only those that were
+ intended by the server administrators. If an HTTP server translates
+ HTTP URIs directly into file system calls, the server MUST take
+ special care not to serve files that were not intended to be
+ delivered to HTTP clients. For example, UNIX, Microsoft Windows, and
+ other operating systems use ".." as a path component to indicate a
+ directory level above the current one. On such a system, an HTTP
+ server MUST disallow any such construct in the Request-URI if it
+ would otherwise allow access to a resource outside those intended to
+ be accessible via the HTTP server. Similarly, files intended for
+ reference only internally to the server (such as access control
+ files, configuration files, and script code) MUST be protected from
+ inappropriate retrieval, since they might contain sensitive
+ information. Experience has shown that minor bugs in such HTTP server
+ implementations have turned into security risks.
+
+
+
+
+Fielding, et al. Standards Track [Page 153]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+15.3 DNS Spoofing
+
+ Clients using HTTP rely heavily on the Domain Name Service, and are
+ thus generally prone to security attacks based on the deliberate
+ mis-association of IP addresses and DNS names. Clients need to be
+ cautious in assuming the continuing validity of an IP number/DNS name
+ association.
+
+ In particular, HTTP clients SHOULD rely on their name resolver for
+ confirmation of an IP number/DNS name association, rather than
+ caching the result of previous host name lookups. Many platforms
+ already can cache host name lookups locally when appropriate, and
+ they SHOULD be configured to do so. It is proper for these lookups to
+ be cached, however, only when the TTL (Time To Live) information
+ reported by the name server makes it likely that the cached
+ information will remain useful.
+
+ If HTTP clients cache the results of host name lookups in order to
+ achieve a performance improvement, they MUST observe the TTL
+ information reported by DNS.
+
+ If HTTP clients do not observe this rule, they could be spoofed when
+ a previously-accessed server's IP address changes. As network
+ renumbering is expected to become increasingly common [24], the
+ possibility of this form of attack will grow. Observing this
+ requirement thus reduces this potential security vulnerability.
+
+ This requirement also improves the load-balancing behavior of clients
+ for replicated servers using the same DNS name and reduces the
+ likelihood of a user's experiencing failure in accessing sites which
+ use that strategy.
+
+15.4 Location Headers and Spoofing
+
+ If a single server supports multiple organizations that do not trust
+ one another, then it MUST check the values of Location and Content-
+ Location headers in responses that are generated under control of
+ said organizations to make sure that they do not attempt to
+ invalidate resources over which they have no authority.
+
+15.5 Content-Disposition Issues
+
+ RFC 1806 [35], from which the often implemented Content-Disposition
+ (see section 19.5.1) header in HTTP is derived, has a number of very
+ serious security considerations. Content-Disposition is not part of
+ the HTTP standard, but since it is widely implemented, we are
+ documenting its use and risks for implementors. See RFC 2183 [49]
+ (which updates RFC 1806) for details.
+
+
+
+Fielding, et al. Standards Track [Page 154]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+15.6 Authentication Credentials and Idle Clients
+
+ Existing HTTP clients and user agents typically retain authentication
+ information indefinitely. HTTP/1.1. does not provide a method for a
+ server to direct clients to discard these cached credentials. This is
+ a significant defect that requires further extensions to HTTP.
+ Circumstances under which credential caching can interfere with the
+ application's security model include but are not limited to:
+
+ - Clients which have been idle for an extended period following
+ which the server might wish to cause the client to reprompt the
+ user for credentials.
+
+ - Applications which include a session termination indication
+ (such as a `logout' or `commit' button on a page) after which
+ the server side of the application `knows' that there is no
+ further reason for the client to retain the credentials.
+
+ This is currently under separate study. There are a number of work-
+ arounds to parts of this problem, and we encourage the use of
+ password protection in screen savers, idle time-outs, and other
+ methods which mitigate the security problems inherent in this
+ problem. In particular, user agents which cache credentials are
+ encouraged to provide a readily accessible mechanism for discarding
+ cached credentials under user control.
+
+15.7 Proxies and Caching
+
+ By their very nature, HTTP proxies are men-in-the-middle, and
+ represent an opportunity for man-in-the-middle attacks. Compromise of
+ the systems on which the proxies run can result in serious security
+ and privacy problems. Proxies have access to security-related
+ information, personal information about individual users and
+ organizations, and proprietary information belonging to users and
+ content providers. A compromised proxy, or a proxy implemented or
+ configured without regard to security and privacy considerations,
+ might be used in the commission of a wide range of potential attacks.
+
+ Proxy operators should protect the systems on which proxies run as
+ they would protect any system that contains or transports sensitive
+ information. In particular, log information gathered at proxies often
+ contains highly sensitive personal information, and/or information
+ about organizations. Log information should be carefully guarded, and
+ appropriate guidelines for use developed and followed. (Section
+ 15.1.1).
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 155]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Caching proxies provide additional potential vulnerabilities, since
+ the contents of the cache represent an attractive target for
+ malicious exploitation. Because cache contents persist after an HTTP
+ request is complete, an attack on the cache can reveal information
+ long after a user believes that the information has been removed from
+ the network. Therefore, cache contents should be protected as
+ sensitive information.
+
+ Proxy implementors should consider the privacy and security
+ implications of their design and coding decisions, and of the
+ configuration options they provide to proxy operators (especially the
+ default configuration).
+
+ Users of a proxy need to be aware that they are no trustworthier than
+ the people who run the proxy; HTTP itself cannot solve this problem.
+
+ The judicious use of cryptography, when appropriate, may suffice to
+ protect against a broad range of security and privacy attacks. Such
+ cryptography is beyond the scope of the HTTP/1.1 specification.
+
+15.7.1 Denial of Service Attacks on Proxies
+
+ They exist. They are hard to defend against. Research continues.
+ Beware.
+
+16 Acknowledgments
+
+ This specification makes heavy use of the augmented BNF and generic
+ constructs defined by David H. Crocker for RFC 822 [9]. Similarly, it
+ reuses many of the definitions provided by Nathaniel Borenstein and
+ Ned Freed for MIME [7]. We hope that their inclusion in this
+ specification will help reduce past confusion over the relationship
+ between HTTP and Internet mail message formats.
+
+ The HTTP protocol has evolved considerably over the years. It has
+ benefited from a large and active developer community--the many
+ people who have participated on the www-talk mailing list--and it is
+ that community which has been most responsible for the success of
+ HTTP and of the World-Wide Web in general. Marc Andreessen, Robert
+ Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois
+ Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob
+ McCool, Lou Montulli, Dave Raggett, Tony Sanders, and Marc
+ VanHeyningen deserve special recognition for their efforts in
+ defining early aspects of the protocol.
+
+ This document has benefited greatly from the comments of all those
+ participating in the HTTP-WG. In addition to those already mentioned,
+ the following individuals have contributed to this specification:
+
+
+
+Fielding, et al. Standards Track [Page 156]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Gary Adams Ross Patterson
+ Harald Tveit Alvestrand Albert Lunde
+ Keith Ball John C. Mallery
+ Brian Behlendorf Jean-Philippe Martin-Flatin
+ Paul Burchard Mitra
+ Maurizio Codogno David Morris
+ Mike Cowlishaw Gavin Nicol
+ Roman Czyborra Bill Perry
+ Michael A. Dolan Jeffrey Perry
+ David J. Fiander Scott Powers
+ Alan Freier Owen Rees
+ Marc Hedlund Luigi Rizzo
+ Greg Herlihy David Robinson
+ Koen Holtman Marc Salomon
+ Alex Hopmann Rich Salz
+ Bob Jernigan Allan M. Schiffman
+ Shel Kaphan Jim Seidman
+ Rohit Khare Chuck Shotton
+ John Klensin Eric W. Sink
+ Martijn Koster Simon E. Spero
+ Alexei Kosut Richard N. Taylor
+ David M. Kristol Robert S. Thau
+ Daniel LaLiberte Bill (BearHeart) Weinman
+ Ben Laurie Francois Yergeau
+ Paul J. Leach Mary Ellen Zurko
+ Daniel DuBois Josh Cohen
+
+
+ Much of the content and presentation of the caching design is due to
+ suggestions and comments from individuals including: Shel Kaphan,
+ Paul Leach, Koen Holtman, David Morris, and Larry Masinter.
+
+ Most of the specification of ranges is based on work originally done
+ by Ari Luotonen and John Franks, with additional input from Steve
+ Zilles.
+
+ Thanks to the "cave men" of Palo Alto. You know who you are.
+
+ Jim Gettys (the current editor of this document) wishes particularly
+ to thank Roy Fielding, the previous editor of this document, along
+ with John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen
+ Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, and
+ Larry Masinter for their help. And thanks go particularly to Jeff
+ Mogul and Scott Lawrence for performing the "MUST/MAY/SHOULD" audit.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 157]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ The Apache Group, Anselm Baird-Smith, author of Jigsaw, and Henrik
+ Frystyk implemented RFC 2068 early, and we wish to thank them for the
+ discovery of many of the problems that this document attempts to
+ rectify.
+
+17 References
+
+ [1] Alvestrand, H., "Tags for the Identification of Languages", RFC
+ 1766, March 1995.
+
+ [2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey,
+ D. and B. Alberti, "The Internet Gopher Protocol (a distributed
+ document search and retrieval protocol)", RFC 1436, March 1993.
+
+ [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", RFC
+ 1630, June 1994.
+
+ [4] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform Resource
+ Locators (URL)", RFC 1738, December 1994.
+
+ [5] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language -
+ 2.0", RFC 1866, November 1995.
+
+ [6] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext Transfer
+ Protocol -- HTTP/1.0", RFC 1945, May 1996.
+
+ [7] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ RFC 2045, November 1996.
+
+ [8] Braden, R., "Requirements for Internet Hosts -- Communication
+ Layers", STD 3, RFC 1123, October 1989.
+
+ [9] Crocker, D., "Standard for The Format of ARPA Internet Text
+ Messages", STD 11, RFC 822, August 1982.
+
+ [10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R.,
+ Sui, J., and M. Grinbaum, "WAIS Interface Protocol Prototype
+ Functional Specification," (v1.5), Thinking Machines
+ Corporation, April 1990.
+
+ [11] Fielding, R., "Relative Uniform Resource Locators", RFC 1808,
+ June 1995.
+
+ [12] Horton, M. and R. Adams, "Standard for Interchange of USENET
+ Messages", RFC 1036, December 1987.
+
+
+
+
+
+Fielding, et al. Standards Track [Page 158]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ [13] Kantor, B. and P. Lapsley, "Network News Transfer Protocol", RFC
+ 977, February 1986.
+
+ [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
+ Three: Message Header Extensions for Non-ASCII Text", RFC 2047,
+ November 1996.
+
+ [15] Nebel, E. and L. Masinter, "Form-based File Upload in HTML", RFC
+ 1867, November 1995.
+
+ [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821,
+ August 1982.
+
+ [17] Postel, J., "Media Type Registration Procedure", RFC 1590,
+ November 1996.
+
+ [18] Postel, J. and J. Reynolds, "File Transfer Protocol", STD 9, RFC
+ 959, October 1985.
+
+ [19] Reynolds, J. and J. Postel, "Assigned Numbers", STD 2, RFC 1700,
+ October 1994.
+
+ [20] Sollins, K. and L. Masinter, "Functional Requirements for
+ Uniform Resource Names", RFC 1737, December 1994.
+
+ [21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for
+ Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.
+
+ [22] ISO-8859. International Standard -- Information Processing --
+ 8-bit Single-Byte Coded Graphic Character Sets --
+ Part 1: Latin alphabet No. 1, ISO-8859-1:1987.
+ Part 2: Latin alphabet No. 2, ISO-8859-2, 1987.
+ Part 3: Latin alphabet No. 3, ISO-8859-3, 1988.
+ Part 4: Latin alphabet No. 4, ISO-8859-4, 1988.
+ Part 5: Latin/Cyrillic alphabet, ISO-8859-5, 1988.
+ Part 6: Latin/Arabic alphabet, ISO-8859-6, 1987.
+ Part 7: Latin/Greek alphabet, ISO-8859-7, 1987.
+ Part 8: Latin/Hebrew alphabet, ISO-8859-8, 1988.
+ Part 9: Latin alphabet No. 5, ISO-8859-9, 1990.
+
+ [23] Meyers, J. and M. Rose, "The Content-MD5 Header Field", RFC
+ 1864, October 1995.
+
+ [24] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC
+ 1900, February 1996.
+
+ [25] Deutsch, P., "GZIP file format specification version 4.3", RFC
+ 1952, May 1996.
+
+
+
+Fielding, et al. Standards Track [Page 159]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ [26] Venkata N. Padmanabhan, and Jeffrey C. Mogul. "Improving HTTP
+ Latency", Computer Networks and ISDN Systems, v. 28, pp. 25-35,
+ Dec. 1995. Slightly revised version of paper in Proc. 2nd
+ International WWW Conference '94: Mosaic and the Web, Oct. 1994,
+ which is available at
+ http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/HTTPLat
+ ency.html.
+
+ [27] Joe Touch, John Heidemann, and Katia Obraczka. "Analysis of HTTP
+ Performance", <URL: http://www.isi.edu/touch/pubs/http-perf96/>,
+ ISI Research Report ISI/RR-98-463, (original report dated Aug.
+ 1996), USC/Information Sciences Institute, August 1998.
+
+ [28] Mills, D., "Network Time Protocol (Version 3) Specification,
+ Implementation and Analysis", RFC 1305, March 1992.
+
+ [29] Deutsch, P., "DEFLATE Compressed Data Format Specification
+ version 1.3", RFC 1951, May 1996.
+
+ [30] S. Spero, "Analysis of HTTP Performance Problems,"
+ http://sunsite.unc.edu/mdma-release/http-prob.html.
+
+ [31] Deutsch, P. and J. Gailly, "ZLIB Compressed Data Format
+ Specification version 3.3", RFC 1950, May 1996.
+
+ [32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP:
+ Digest Access Authentication", RFC 2069, January 1997.
+
+ [33] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
+ 2068, January 1997.
+
+ [34] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [35] Troost, R. and Dorner, S., "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition
+ Header", RFC 1806, June 1995.
+
+ [36] Mogul, J., Fielding, R., Gettys, J. and H. Frystyk, "Use and
+ Interpretation of HTTP Version Numbers", RFC 2145, May 1997.
+ [jg639]
+
+ [37] Palme, J., "Common Internet Message Headers", RFC 2076, February
+ 1997. [jg640]
+
+
+
+
+
+Fielding, et al. Standards Track [Page 160]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ [38] Yergeau, F., "UTF-8, a transformation format of Unicode and
+ ISO-10646", RFC 2279, January 1998. [jg641]
+
+ [39] Nielsen, H.F., Gettys, J., Baird-Smith, A., Prud'hommeaux, E.,
+ Lie, H., and C. Lilley. "Network Performance Effects of
+ HTTP/1.1, CSS1, and PNG," Proceedings of ACM SIGCOMM '97, Cannes
+ France, September 1997.[jg642]
+
+ [40] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046, November
+ 1996. [jg643]
+
+ [41] Alvestrand, H., "IETF Policy on Character Sets and Languages",
+ BCP 18, RFC 2277, January 1998. [jg644]
+
+ [42] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource
+ Identifiers (URI): Generic Syntax and Semantics", RFC 2396,
+ August 1998. [jg645]
+
+ [43] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
+ Leach, P., Luotonen, A., Sink, E. and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access Authentication", RFC
+ 2617, June 1999. [jg646]
+
+ [44] Luotonen, A., "Tunneling TCP based protocols through Web proxy
+ servers," Work in Progress. [jg647]
+
+ [45] Palme, J. and A. Hopmann, "MIME E-mail Encapsulation of
+ Aggregate Documents, such as HTML (MHTML)", RFC 2110, March
+ 1997.
+
+ [46] Bradner, S., "The Internet Standards Process -- Revision 3", BCP
+ 9, RFC 2026, October 1996.
+
+ [47] Masinter, L., "Hyper Text Coffee Pot Control Protocol
+ (HTCPCP/1.0)", RFC 2324, 1 April 1998.
+
+ [48] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Five: Conformance Criteria and Examples",
+ RFC 2049, November 1996.
+
+ [49] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation
+ Information in Internet Messages: The Content-Disposition Header
+ Field", RFC 2183, August 1997.
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 161]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+18 Authors' Addresses
+
+ Roy T. Fielding
+ Information and Computer Science
+ University of California, Irvine
+ Irvine, CA 92697-3425, USA
+
+ Fax: +1 (949) 824-1715
+ EMail: fielding@ics.uci.edu
+
+
+ James Gettys
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: jg@w3.org
+
+
+ Jeffrey C. Mogul
+ Western Research Laboratory
+ Compaq Computer Corporation
+ 250 University Avenue
+ Palo Alto, California, 94305, USA
+
+ EMail: mogul@wrl.dec.com
+
+
+ Henrik Frystyk Nielsen
+ World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: frystyk@w3.org
+
+
+ Larry Masinter
+ Xerox Corporation
+ 3333 Coyote Hill Road
+ Palo Alto, CA 94034, USA
+
+ EMail: masinter@parc.xerox.com
+
+
+
+
+
+Fielding, et al. Standards Track [Page 162]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Paul J. Leach
+ Microsoft Corporation
+ 1 Microsoft Way
+ Redmond, WA 98052, USA
+
+ EMail: paulle@microsoft.com
+
+
+ Tim Berners-Lee
+ Director, World Wide Web Consortium
+ MIT Laboratory for Computer Science
+ 545 Technology Square
+ Cambridge, MA 02139, USA
+
+ Fax: +1 (617) 258 8682
+ EMail: timbl@w3.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 163]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+19 Appendices
+
+19.1 Internet Media Type message/http and application/http
+
+ In addition to defining the HTTP/1.1 protocol, this document serves
+ as the specification for the Internet media type "message/http" and
+ "application/http". The message/http type can be used to enclose a
+ single HTTP request or response message, provided that it obeys the
+ MIME restrictions for all "message" types regarding line length and
+ encodings. The application/http type can be used to enclose a
+ pipeline of one or more HTTP request or response messages (not
+ intermixed). The following is to be registered with IANA [17].
+
+ Media Type name: message
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed message
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+ Media Type name: application
+ Media subtype name: http
+ Required parameters: none
+ Optional parameters: version, msgtype
+ version: The HTTP-Version number of the enclosed messages
+ (e.g., "1.1"). If not present, the version can be
+ determined from the first line of the body.
+ msgtype: The message type -- "request" or "response". If not
+ present, the type can be determined from the first
+ line of the body.
+ Encoding considerations: HTTP messages enclosed by this type
+ are in "binary" format; use of an appropriate
+ Content-Transfer-Encoding is required when
+ transmitted via E-mail.
+ Security considerations: none
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 164]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+19.2 Internet Media Type multipart/byteranges
+
+ When an HTTP 206 (Partial Content) response message includes the
+ content of multiple ranges (a response to a request for multiple
+ non-overlapping ranges), these are transmitted as a multipart
+ message-body. The media type for this purpose is called
+ "multipart/byteranges".
+
+ The multipart/byteranges media type includes two or more parts, each
+ with its own Content-Type and Content-Range fields. The required
+ boundary parameter specifies the boundary string used to separate
+ each body-part.
+
+ Media Type name: multipart
+ Media subtype name: byteranges
+ Required parameters: boundary
+ Optional parameters: none
+ Encoding considerations: only "7bit", "8bit", or "binary" are
+ permitted
+ Security considerations: none
+
+
+ For example:
+
+ HTTP/1.1 206 Partial Content
+ Date: Wed, 15 Nov 1995 06:25:24 GMT
+ Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
+ Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
+
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 500-999/8000
+
+ ...the first range...
+ --THIS_STRING_SEPARATES
+ Content-type: application/pdf
+ Content-range: bytes 7000-7999/8000
+
+ ...the second range
+ --THIS_STRING_SEPARATES--
+
+ Notes:
+
+ 1) Additional CRLFs may precede the first boundary string in the
+ entity.
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 165]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ 2) Although RFC 2046 [40] permits the boundary string to be
+ quoted, some existing implementations handle a quoted boundary
+ string incorrectly.
+
+ 3) A number of browsers and servers were coded to an early draft
+ of the byteranges specification to use a media type of
+ multipart/x-byteranges, which is almost, but not quite
+ compatible with the version documented in HTTP/1.1.
+
+19.3 Tolerant Applications
+
+ Although this document specifies the requirements for the generation
+ of HTTP/1.1 messages, not all applications will be correct in their
+ implementation. We therefore recommend that operational applications
+ be tolerant of deviations whenever those deviations can be
+ interpreted unambiguously.
+
+ Clients SHOULD be tolerant in parsing the Status-Line and servers
+ tolerant when parsing the Request-Line. In particular, they SHOULD
+ accept any amount of SP or HT characters between fields, even though
+ only a single SP is required.
+
+ The line terminator for message-header fields is the sequence CRLF.
+ However, we recommend that applications, when parsing such headers,
+ recognize a single LF as a line terminator and ignore the leading CR.
+
+ The character set of an entity-body SHOULD be labeled as the lowest
+ common denominator of the character codes used within that body, with
+ the exception that not labeling the entity is preferred over labeling
+ the entity with the labels US-ASCII or ISO-8859-1. See section 3.7.1
+ and 3.4.1.
+
+ Additional rules for requirements on parsing and encoding of dates
+ and other potential problems with date encodings include:
+
+ - HTTP/1.1 clients and caches SHOULD assume that an RFC-850 date
+ which appears to be more than 50 years in the future is in fact
+ in the past (this helps solve the "year 2000" problem).
+
+ - An HTTP/1.1 implementation MAY internally represent a parsed
+ Expires date as earlier than the proper value, but MUST NOT
+ internally represent a parsed Expires date as later than the
+ proper value.
+
+ - All expiration-related calculations MUST be done in GMT. The
+ local time zone MUST NOT influence the calculation or comparison
+ of an age or expiration time.
+
+
+
+
+Fielding, et al. Standards Track [Page 166]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - If an HTTP header incorrectly carries a date value with a time
+ zone other than GMT, it MUST be converted into GMT using the
+ most conservative possible conversion.
+
+19.4 Differences Between HTTP Entities and RFC 2045 Entities
+
+ HTTP/1.1 uses many of the constructs defined for Internet Mail (RFC
+ 822 [9]) and the Multipurpose Internet Mail Extensions (MIME [7]) to
+ allow entities to be transmitted in an open variety of
+ representations and with extensible mechanisms. However, RFC 2045
+ discusses mail, and HTTP has a few features that are different from
+ those described in RFC 2045. These differences were carefully chosen
+ to optimize performance over binary connections, to allow greater
+ freedom in the use of new media types, to make date comparisons
+ easier, and to acknowledge the practice of some early HTTP servers
+ and clients.
+
+ This appendix describes specific areas where HTTP differs from RFC
+ 2045. Proxies and gateways to strict MIME environments SHOULD be
+ aware of these differences and provide the appropriate conversions
+ where necessary. Proxies and gateways from MIME environments to HTTP
+ also need to be aware of the differences because some conversions
+ might be required.
+
+19.4.1 MIME-Version
+
+ HTTP is not a MIME-compliant protocol. However, HTTP/1.1 messages MAY
+ include a single MIME-Version general-header field to indicate what
+ version of the MIME protocol was used to construct the message. Use
+ of the MIME-Version header field indicates that the message is in
+ full compliance with the MIME protocol (as defined in RFC 2045[7]).
+ Proxies/gateways are responsible for ensuring full compliance (where
+ possible) when exporting HTTP messages to strict MIME environments.
+
+ MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
+
+ MIME version "1.0" is the default for use in HTTP/1.1. However,
+ HTTP/1.1 message parsing and semantics are defined by this document
+ and not the MIME specification.
+
+19.4.2 Conversion to Canonical Form
+
+ RFC 2045 [7] requires that an Internet mail entity be converted to
+ canonical form prior to being transferred, as described in section 4
+ of RFC 2049 [48]. Section 3.7.1 of this document describes the forms
+ allowed for subtypes of the "text" media type when transmitted over
+ HTTP. RFC 2046 requires that content with a type of "text" represent
+ line breaks as CRLF and forbids the use of CR or LF outside of line
+
+
+
+Fielding, et al. Standards Track [Page 167]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ break sequences. HTTP allows CRLF, bare CR, and bare LF to indicate a
+ line break within text content when a message is transmitted over
+ HTTP.
+
+ Where it is possible, a proxy or gateway from HTTP to a strict MIME
+ environment SHOULD translate all line breaks within the text media
+ types described in section 3.7.1 of this document to the RFC 2049
+ canonical form of CRLF. Note, however, that this might be complicated
+ by the presence of a Content-Encoding and by the fact that HTTP
+ allows the use of some character sets which do not use octets 13 and
+ 10 to represent CR and LF, as is the case for some multi-byte
+ character sets.
+
+ Implementors should note that conversion will break any cryptographic
+ checksums applied to the original content unless the original content
+ is already in canonical form. Therefore, the canonical form is
+ recommended for any content that uses such checksums in HTTP.
+
+19.4.3 Conversion of Date Formats
+
+ HTTP/1.1 uses a restricted set of date formats (section 3.3.1) to
+ simplify the process of date comparison. Proxies and gateways from
+ other protocols SHOULD ensure that any Date header field present in a
+ message conforms to one of the HTTP/1.1 formats and rewrite the date
+ if necessary.
+
+19.4.4 Introduction of Content-Encoding
+
+ RFC 2045 does not include any concept equivalent to HTTP/1.1's
+ Content-Encoding header field. Since this acts as a modifier on the
+ media type, proxies and gateways from HTTP to MIME-compliant
+ protocols MUST either change the value of the Content-Type header
+ field or decode the entity-body before forwarding the message. (Some
+ experimental applications of Content-Type for Internet mail have used
+ a media-type parameter of ";conversions=<content-coding>" to perform
+ a function equivalent to Content-Encoding. However, this parameter is
+ not part of RFC 2045.)
+
+19.4.5 No Content-Transfer-Encoding
+
+ HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC
+ 2045. Proxies and gateways from MIME-compliant protocols to HTTP MUST
+ remove any non-identity CTE ("quoted-printable" or "base64") encoding
+ prior to delivering the response message to an HTTP client.
+
+ Proxies and gateways from HTTP to MIME-compliant protocols are
+ responsible for ensuring that the message is in the correct format
+ and encoding for safe transport on that protocol, where "safe
+
+
+
+Fielding, et al. Standards Track [Page 168]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ transport" is defined by the limitations of the protocol being used.
+ Such a proxy or gateway SHOULD label the data with an appropriate
+ Content-Transfer-Encoding if doing so will improve the likelihood of
+ safe transport over the destination protocol.
+
+19.4.6 Introduction of Transfer-Encoding
+
+ HTTP/1.1 introduces the Transfer-Encoding header field (section
+ 14.41). Proxies/gateways MUST remove any transfer-coding prior to
+ forwarding a message via a MIME-compliant protocol.
+
+ A process for decoding the "chunked" transfer-coding (section 3.6)
+ can be represented in pseudo-code as:
+
+ length := 0
+ read chunk-size, chunk-extension (if any) and CRLF
+ while (chunk-size > 0) {
+ read chunk-data and CRLF
+ append chunk-data to entity-body
+ length := length + chunk-size
+ read chunk-size and CRLF
+ }
+ read entity-header
+ while (entity-header not empty) {
+ append entity-header to existing header fields
+ read entity-header
+ }
+ Content-Length := length
+ Remove "chunked" from Transfer-Encoding
+
+19.4.7 MHTML and Line Length Limitations
+
+ HTTP implementations which share code with MHTML [45] implementations
+ need to be aware of MIME line length limitations. Since HTTP does not
+ have this limitation, HTTP does not fold long lines. MHTML messages
+ being transported by HTTP follow all conventions of MHTML, including
+ line length limitations and folding, canonicalization, etc., since
+ HTTP transports all message-bodies as payload (see section 3.7.2) and
+ does not interpret the content or any MIME header lines that might be
+ contained therein.
+
+19.5 Additional Features
+
+ RFC 1945 and RFC 2068 document protocol elements used by some
+ existing HTTP implementations, but not consistently and correctly
+ across most HTTP/1.1 applications. Implementors are advised to be
+ aware of these features, but cannot rely upon their presence in, or
+ interoperability with, other HTTP/1.1 applications. Some of these
+
+
+
+Fielding, et al. Standards Track [Page 169]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ describe proposed experimental features, and some describe features
+ that experimental deployment found lacking that are now addressed in
+ the base HTTP/1.1 specification.
+
+ A number of other headers, such as Content-Disposition and Title,
+ from SMTP and MIME are also often implemented (see RFC 2076 [37]).
+
+19.5.1 Content-Disposition
+
+ The Content-Disposition response-header field has been proposed as a
+ means for the origin server to suggest a default filename if the user
+ requests that the content is saved to a file. This usage is derived
+ from the definition of Content-Disposition in RFC 1806 [35].
+
+ content-disposition = "Content-Disposition" ":"
+ disposition-type *( ";" disposition-parm )
+ disposition-type = "attachment" | disp-extension-token
+ disposition-parm = filename-parm | disp-extension-parm
+ filename-parm = "filename" "=" quoted-string
+ disp-extension-token = token
+ disp-extension-parm = token "=" ( token | quoted-string )
+
+ An example is
+
+ Content-Disposition: attachment; filename="fname.ext"
+
+ The receiving user agent SHOULD NOT respect any directory path
+ information present in the filename-parm parameter, which is the only
+ parameter believed to apply to HTTP implementations at this time. The
+ filename SHOULD be treated as a terminal component only.
+
+ If this header is used in a response with the application/octet-
+ stream content-type, the implied suggestion is that the user agent
+ should not display the response, but directly enter a `save response
+ as...' dialog.
+
+ See section 15.5 for Content-Disposition security issues.
+
+19.6 Compatibility with Previous Versions
+
+ It is beyond the scope of a protocol specification to mandate
+ compliance with previous versions. HTTP/1.1 was deliberately
+ designed, however, to make supporting previous versions easy. It is
+ worth noting that, at the time of composing this specification
+ (1996), we would expect commercial HTTP/1.1 servers to:
+
+ - recognize the format of the Request-Line for HTTP/0.9, 1.0, and
+ 1.1 requests;
+
+
+
+Fielding, et al. Standards Track [Page 170]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ - understand any valid request in the format of HTTP/0.9, 1.0, or
+ 1.1;
+
+ - respond appropriately with a message in the same major version
+ used by the client.
+
+ And we would expect HTTP/1.1 clients to:
+
+ - recognize the format of the Status-Line for HTTP/1.0 and 1.1
+ responses;
+
+ - understand any valid response in the format of HTTP/0.9, 1.0, or
+ 1.1.
+
+ For most implementations of HTTP/1.0, each connection is established
+ by the client prior to the request and closed by the server after
+ sending the response. Some implementations implement the Keep-Alive
+ version of persistent connections described in section 19.7.1 of RFC
+ 2068 [33].
+
+19.6.1 Changes from HTTP/1.0
+
+ This section summarizes major differences between versions HTTP/1.0
+ and HTTP/1.1.
+
+19.6.1.1 Changes to Simplify Multi-homed Web Servers and Conserve IP
+ Addresses
+
+ The requirements that clients and servers support the Host request-
+ header, report an error if the Host request-header (section 14.23) is
+ missing from an HTTP/1.1 request, and accept absolute URIs (section
+ 5.1.2) are among the most important changes defined by this
+ specification.
+
+ Older HTTP/1.0 clients assumed a one-to-one relationship of IP
+ addresses and servers; there was no other established mechanism for
+ distinguishing the intended server of a request than the IP address
+ to which that request was directed. The changes outlined above will
+ allow the Internet, once older HTTP clients are no longer common, to
+ support multiple Web sites from a single IP address, greatly
+ simplifying large operational Web servers, where allocation of many
+ IP addresses to a single host has created serious problems. The
+ Internet will also be able to recover the IP addresses that have been
+ allocated for the sole purpose of allowing special-purpose domain
+ names to be used in root-level HTTP URLs. Given the rate of growth of
+ the Web, and the number of servers already deployed, it is extremely
+
+
+
+
+
+Fielding, et al. Standards Track [Page 171]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ important that all implementations of HTTP (including updates to
+ existing HTTP/1.0 applications) correctly implement these
+ requirements:
+
+ - Both clients and servers MUST support the Host request-header.
+
+ - A client that sends an HTTP/1.1 request MUST send a Host header.
+
+ - Servers MUST report a 400 (Bad Request) error if an HTTP/1.1
+ request does not include a Host request-header.
+
+ - Servers MUST accept absolute URIs.
+
+19.6.2 Compatibility with HTTP/1.0 Persistent Connections
+
+ Some clients and servers might wish to be compatible with some
+ previous implementations of persistent connections in HTTP/1.0
+ clients and servers. Persistent connections in HTTP/1.0 are
+ explicitly negotiated as they are not the default behavior. HTTP/1.0
+ experimental implementations of persistent connections are faulty,
+ and the new facilities in HTTP/1.1 are designed to rectify these
+ problems. The problem was that some existing 1.0 clients may be
+ sending Keep-Alive to a proxy server that doesn't understand
+ Connection, which would then erroneously forward it to the next
+ inbound server, which would establish the Keep-Alive connection and
+ result in a hung HTTP/1.0 proxy waiting for the close on the
+ response. The result is that HTTP/1.0 clients must be prevented from
+ using Keep-Alive when talking to proxies.
+
+ However, talking to proxies is the most important use of persistent
+ connections, so that prohibition is clearly unacceptable. Therefore,
+ we need some other mechanism for indicating a persistent connection
+ is desired, which is safe to use even when talking to an old proxy
+ that ignores Connection. Persistent connections are the default for
+ HTTP/1.1 messages; we introduce a new keyword (Connection: close) for
+ declaring non-persistence. See section 14.10.
+
+ The original HTTP/1.0 form of persistent connections (the Connection:
+ Keep-Alive and Keep-Alive header) is documented in RFC 2068. [33]
+
+19.6.3 Changes from RFC 2068
+
+ This specification has been carefully audited to correct and
+ disambiguate key word usage; RFC 2068 had many problems in respect to
+ the conventions laid out in RFC 2119 [34].
+
+ Clarified which error code should be used for inbound server failures
+ (e.g. DNS failures). (Section 10.5.5).
+
+
+
+Fielding, et al. Standards Track [Page 172]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ CREATE had a race that required an Etag be sent when a resource is
+ first created. (Section 10.2.2).
+
+ Content-Base was deleted from the specification: it was not
+ implemented widely, and there is no simple, safe way to introduce it
+ without a robust extension mechanism. In addition, it is used in a
+ similar, but not identical fashion in MHTML [45].
+
+ Transfer-coding and message lengths all interact in ways that
+ required fixing exactly when chunked encoding is used (to allow for
+ transfer encoding that may not be self delimiting); it was important
+ to straighten out exactly how message lengths are computed. (Sections
+ 3.6, 4.4, 7.2.2, 13.5.2, 14.13, 14.16)
+
+ A content-coding of "identity" was introduced, to solve problems
+ discovered in caching. (section 3.5)
+
+ Quality Values of zero should indicate that "I don't want something"
+ to allow clients to refuse a representation. (Section 3.9)
+
+ The use and interpretation of HTTP version numbers has been clarified
+ by RFC 2145. Require proxies to upgrade requests to highest protocol
+ version they support to deal with problems discovered in HTTP/1.0
+ implementations (Section 3.1)
+
+ Charset wildcarding is introduced to avoid explosion of character set
+ names in accept headers. (Section 14.2)
+
+ A case was missed in the Cache-Control model of HTTP/1.1; s-maxage
+ was introduced to add this missing case. (Sections 13.4, 14.8, 14.9,
+ 14.9.3)
+
+ The Cache-Control: max-age directive was not properly defined for
+ responses. (Section 14.9.3)
+
+ There are situations where a server (especially a proxy) does not
+ know the full length of a response but is capable of serving a
+ byterange request. We therefore need a mechanism to allow byteranges
+ with a content-range not indicating the full length of the message.
+ (Section 14.16)
+
+ Range request responses would become very verbose if all meta-data
+ were always returned; by allowing the server to only send needed
+ headers in a 206 response, this problem can be avoided. (Section
+ 10.2.7, 13.5.3, and 14.27)
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 173]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Fix problem with unsatisfiable range requests; there are two cases:
+ syntactic problems, and range doesn't exist in the document. The 416
+ status code was needed to resolve this ambiguity needed to indicate
+ an error for a byte range request that falls outside of the actual
+ contents of a document. (Section 10.4.17, 14.16)
+
+ Rewrite of message transmission requirements to make it much harder
+ for implementors to get it wrong, as the consequences of errors here
+ can have significant impact on the Internet, and to deal with the
+ following problems:
+
+ 1. Changing "HTTP/1.1 or later" to "HTTP/1.1", in contexts where
+ this was incorrectly placing a requirement on the behavior of
+ an implementation of a future version of HTTP/1.x
+
+ 2. Made it clear that user-agents should retry requests, not
+ "clients" in general.
+
+ 3. Converted requirements for clients to ignore unexpected 100
+ (Continue) responses, and for proxies to forward 100 responses,
+ into a general requirement for 1xx responses.
+
+ 4. Modified some TCP-specific language, to make it clearer that
+ non-TCP transports are possible for HTTP.
+
+ 5. Require that the origin server MUST NOT wait for the request
+ body before it sends a required 100 (Continue) response.
+
+ 6. Allow, rather than require, a server to omit 100 (Continue) if
+ it has already seen some of the request body.
+
+ 7. Allow servers to defend against denial-of-service attacks and
+ broken clients.
+
+ This change adds the Expect header and 417 status code. The message
+ transmission requirements fixes are in sections 8.2, 10.4.18,
+ 8.1.2.2, 13.11, and 14.20.
+
+ Proxies should be able to add Content-Length when appropriate.
+ (Section 13.5.2)
+
+ Clean up confusion between 403 and 404 responses. (Section 10.4.4,
+ 10.4.5, and 10.4.11)
+
+ Warnings could be cached incorrectly, or not updated appropriately.
+ (Section 13.1.2, 13.2.4, 13.5.2, 13.5.3, 14.9.3, and 14.46) Warning
+ also needed to be a general header, as PUT or other methods may have
+ need for it in requests.
+
+
+
+Fielding, et al. Standards Track [Page 174]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+ Transfer-coding had significant problems, particularly with
+ interactions with chunked encoding. The solution is that transfer-
+ codings become as full fledged as content-codings. This involves
+ adding an IANA registry for transfer-codings (separate from content
+ codings), a new header field (TE) and enabling trailer headers in the
+ future. Transfer encoding is a major performance benefit, so it was
+ worth fixing [39]. TE also solves another, obscure, downward
+ interoperability problem that could have occurred due to interactions
+ between authentication trailers, chunked encoding and HTTP/1.0
+ clients.(Section 3.6, 3.6.1, and 14.39)
+
+ The PATCH, LINK, UNLINK methods were defined but not commonly
+ implemented in previous versions of this specification. See RFC 2068
+ [33].
+
+ The Alternates, Content-Version, Derived-From, Link, URI, Public and
+ Content-Base header fields were defined in previous versions of this
+ specification, but not commonly implemented. See RFC 2068 [33].
+
+20 Index
+
+ Please see the PostScript version of this RFC for the INDEX.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 175]
+
+RFC 2616 HTTP/1.1 June 1999
+
+
+21. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fielding, et al. Standards Track [Page 176]
+
diff --git a/standards/rfc2617.txt b/standards/rfc2617.txt
new file mode 100644
index 000000000..771aa924a
--- /dev/null
+++ b/standards/rfc2617.txt
@@ -0,0 +1,1907 @@
+
+
+
+
+
+
+Network Working Group J. Franks
+Request for Comments: 2617 Northwestern University
+Obsoletes: 2069 P. Hallam-Baker
+Category: Standards Track Verisign, Inc.
+ J. Hostetler
+ AbiSource, Inc.
+ S. Lawrence
+ Agranat Systems, Inc.
+ P. Leach
+ Microsoft Corporation
+ A. Luotonen
+ Netscape Communications Corporation
+ L. Stewart
+ Open Market, Inc.
+ June 1999
+
+
+ HTTP Authentication: Basic and Digest Access Authentication
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ "HTTP/1.0", includes the specification for a Basic Access
+ Authentication scheme. This scheme is not considered to be a secure
+ method of user authentication (unless used in conjunction with some
+ external secure system such as SSL [5]), as the user name and
+ password are passed over the network as cleartext.
+
+ This document also provides the specification for HTTP's
+ authentication framework, the original Basic authentication scheme
+ and a scheme based on cryptographic hashes, referred to as "Digest
+ Access Authentication". It is therefore also intended to serve as a
+ replacement for RFC 2069 [6]. Some optional elements specified by
+ RFC 2069 have been removed from this specification due to problems
+ found since its publication; other new elements have been added for
+ compatibility, those new elements have been made optional, but are
+ strongly recommended.
+
+
+
+Franks, et al. Standards Track [Page 1]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ Like Basic, Digest access authentication verifies that both parties
+ to a communication know a shared secret (a password); unlike Basic,
+ this verification can be done without sending the password in the
+ clear, which is Basic's biggest weakness. As with most other
+ authentication protocols, the greatest sources of risks are usually
+ found not in the core protocol itself but in policies and procedures
+ surrounding its use.
+
+Table of Contents
+
+ 1 Access Authentication................................ 3
+ 1.1 Reliance on the HTTP/1.1 Specification............ 3
+ 1.2 Access Authentication Framework................... 3
+ 2 Basic Authentication Scheme.......................... 5
+ 3 Digest Access Authentication Scheme.................. 6
+ 3.1 Introduction...................................... 6
+ 3.1.1 Purpose......................................... 6
+ 3.1.2 Overall Operation............................... 6
+ 3.1.3 Representation of digest values................. 7
+ 3.1.4 Limitations..................................... 7
+ 3.2 Specification of Digest Headers................... 7
+ 3.2.1 The WWW-Authenticate Response Header............ 8
+ 3.2.2 The Authorization Request Header................ 11
+ 3.2.3 The Authentication-Info Header.................. 15
+ 3.3 Digest Operation.................................. 17
+ 3.4 Security Protocol Negotiation..................... 18
+ 3.5 Example........................................... 18
+ 3.6 Proxy-Authentication and Proxy-Authorization...... 19
+ 4 Security Considerations.............................. 19
+ 4.1 Authentication of Clients using Basic
+ Authentication.................................... 19
+ 4.2 Authentication of Clients using Digest
+ Authentication.................................... 20
+ 4.3 Limited Use Nonce Values.......................... 21
+ 4.4 Comparison of Digest with Basic Authentication.... 22
+ 4.5 Replay Attacks.................................... 22
+ 4.6 Weakness Created by Multiple Authentication
+ Schemes........................................... 23
+ 4.7 Online dictionary attacks......................... 23
+ 4.8 Man in the Middle................................. 24
+ 4.9 Chosen plaintext attacks.......................... 24
+ 4.10 Precomputed dictionary attacks.................... 25
+ 4.11 Batch brute force attacks......................... 25
+ 4.12 Spoofing by Counterfeit Servers................... 25
+ 4.13 Storing passwords................................. 26
+ 4.14 Summary........................................... 26
+ 5 Sample implementation................................ 27
+ 6 Acknowledgments...................................... 31
+
+
+
+Franks, et al. Standards Track [Page 2]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ 7 References........................................... 31
+ 8 Authors' Addresses................................... 32
+ 9 Full Copyright Statement............................. 34
+
+1 Access Authentication
+
+1.1 Reliance on the HTTP/1.1 Specification
+
+ This specification is a companion to the HTTP/1.1 specification [2].
+ It uses the augmented BNF section 2.1 of that document, and relies on
+ both the non-terminals defined in that document and other aspects of
+ the HTTP/1.1 specification.
+
+1.2 Access Authentication Framework
+
+ HTTP provides a simple challenge-response authentication mechanism
+ that MAY be used by a server to challenge a client request and by a
+ client to provide authentication information. It uses an extensible,
+ case-insensitive token to identify the authentication scheme,
+ followed by a comma-separated list of attribute-value pairs which
+ carry the parameters necessary for achieving authentication via that
+ scheme.
+
+ auth-scheme = token
+ auth-param = token "=" ( token | quoted-string )
+
+ The 401 (Unauthorized) response message is used by an origin server
+ to challenge the authorization of a user agent. This response MUST
+ include a WWW-Authenticate header field containing at least one
+ challenge applicable to the requested resource. The 407 (Proxy
+ Authentication Required) response message is used by a proxy to
+ challenge the authorization of a client and MUST include a Proxy-
+ Authenticate header field containing at least one challenge
+ applicable to the proxy for the requested resource.
+
+ challenge = auth-scheme 1*SP 1#auth-param
+
+ Note: User agents will need to take special care in parsing the WWW-
+ Authenticate or Proxy-Authenticate header field value if it contains
+ more than one challenge, or if more than one WWW-Authenticate header
+ field is provided, since the contents of a challenge may itself
+ contain a comma-separated list of authentication parameters.
+
+ The authentication parameter realm is defined for all authentication
+ schemes:
+
+ realm = "realm" "=" realm-value
+ realm-value = quoted-string
+
+
+
+Franks, et al. Standards Track [Page 3]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ The realm directive (case-insensitive) is required for all
+ authentication schemes that issue a challenge. The realm value
+ (case-sensitive), in combination with the canonical root URL (the
+ absoluteURI for the server whose abs_path is empty; see section 5.1.2
+ of [2]) of the server being accessed, defines the protection space.
+ These realms allow the protected resources on a server to be
+ partitioned into a set of protection spaces, each with its own
+ authentication scheme and/or authorization database. The realm value
+ is a string, generally assigned by the origin server, which may have
+ additional semantics specific to the authentication scheme. Note that
+ there may be multiple challenges with the same auth-scheme but
+ different realms.
+
+ A user agent that wishes to authenticate itself with an origin
+ server--usually, but not necessarily, after receiving a 401
+ (Unauthorized)--MAY do so by including an Authorization header field
+ with the request. A client that wishes to authenticate itself with a
+ proxy--usually, but not necessarily, after receiving a 407 (Proxy
+ Authentication Required)--MAY do so by including a Proxy-
+ Authorization header field with the request. Both the Authorization
+ field value and the Proxy-Authorization field value consist of
+ credentials containing the authentication information of the client
+ for the realm of the resource being requested. The user agent MUST
+ choose to use one of the challenges with the strongest auth-scheme it
+ understands and request credentials from the user based upon that
+ challenge.
+
+ credentials = auth-scheme #auth-param
+
+ Note that many browsers will only recognize Basic and will require
+ that it be the first auth-scheme presented. Servers should only
+ include Basic if it is minimally acceptable.
+
+ The protection space determines the domain over which credentials can
+ be automatically applied. If a prior request has been authorized, the
+ same credentials MAY be reused for all other requests within that
+ protection space for a period of time determined by the
+ authentication scheme, parameters, and/or user preference. Unless
+ otherwise defined by the authentication scheme, a single protection
+ space cannot extend outside the scope of its server.
+
+ If the origin server does not wish to accept the credentials sent
+ with a request, it SHOULD return a 401 (Unauthorized) response. The
+ response MUST include a WWW-Authenticate header field containing at
+ least one (possibly new) challenge applicable to the requested
+ resource. If a proxy does not accept the credentials sent with a
+ request, it SHOULD return a 407 (Proxy Authentication Required). The
+ response MUST include a Proxy-Authenticate header field containing a
+
+
+
+Franks, et al. Standards Track [Page 4]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ (possibly new) challenge applicable to the proxy for the requested
+ resource.
+
+ The HTTP protocol does not restrict applications to this simple
+ challenge-response mechanism for access authentication. Additional
+ mechanisms MAY be used, such as encryption at the transport level or
+ via message encapsulation, and with additional header fields
+ specifying authentication information. However, these additional
+ mechanisms are not defined by this specification.
+
+ Proxies MUST be completely transparent regarding user agent
+ authentication by origin servers. That is, they must forward the
+ WWW-Authenticate and Authorization headers untouched, and follow the
+ rules found in section 14.8 of [2]. Both the Proxy-Authenticate and
+ the Proxy-Authorization header fields are hop-by-hop headers (see
+ section 13.5.1 of [2]).
+
+2 Basic Authentication Scheme
+
+ The "basic" authentication scheme is based on the model that the
+ client must authenticate itself with a user-ID and a password for
+ each realm. The realm value should be considered an opaque string
+ which can only be compared for equality with other realms on that
+ server. The server will service the request only if it can validate
+ the user-ID and password for the protection space of the Request-URI.
+ There are no optional authentication parameters.
+
+ For Basic, the framework above is utilized as follows:
+
+ challenge = "Basic" realm
+ credentials = "Basic" basic-credentials
+
+ Upon receipt of an unauthorized request for a URI within the
+ protection space, the origin server MAY respond with a challenge like
+ the following:
+
+ WWW-Authenticate: Basic realm="WallyWorld"
+
+ where "WallyWorld" is the string assigned by the server to identify
+ the protection space of the Request-URI. A proxy may respond with the
+ same challenge using the Proxy-Authenticate header field.
+
+ To receive authorization, the client sends the userid and password,
+ separated by a single colon (":") character, within a base64 [7]
+ encoded string in the credentials.
+
+ basic-credentials = base64-user-pass
+ base64-user-pass = <base64 [4] encoding of user-pass,
+
+
+
+Franks, et al. Standards Track [Page 5]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ except not limited to 76 char/line>
+ user-pass = userid ":" password
+ userid = *<TEXT excluding ":">
+ password = *TEXT
+
+ Userids might be case sensitive.
+
+ If the user agent wishes to send the userid "Aladdin" and password
+ "open sesame", it would use the following header field:
+
+ Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+
+ A client SHOULD assume that all paths at or deeper than the depth of
+ the last symbolic element in the path field of the Request-URI also
+ are within the protection space specified by the Basic realm value of
+ the current challenge. A client MAY preemptively send the
+ corresponding Authorization header with requests for resources in
+ that space without receipt of another challenge from the server.
+ Similarly, when a client sends a request to a proxy, it may reuse a
+ userid and password in the Proxy-Authorization header field without
+ receiving another challenge from the proxy server. See section 4 for
+ security considerations associated with Basic authentication.
+
+3 Digest Access Authentication Scheme
+
+3.1 Introduction
+
+3.1.1 Purpose
+
+ The protocol referred to as "HTTP/1.0" includes the specification for
+ a Basic Access Authentication scheme[1]. That scheme is not
+ considered to be a secure method of user authentication, as the user
+ name and password are passed over the network in an unencrypted form.
+ This section provides the specification for a scheme that does not
+ send the password in cleartext, referred to as "Digest Access
+ Authentication".
+
+ The Digest Access Authentication scheme is not intended to be a
+ complete answer to the need for security in the World Wide Web. This
+ scheme provides no encryption of message content. The intent is
+ simply to create an access authentication method that avoids the most
+ serious flaws of Basic authentication.
+
+3.1.2 Overall Operation
+
+ Like Basic Access Authentication, the Digest scheme is based on a
+ simple challenge-response paradigm. The Digest scheme challenges
+ using a nonce value. A valid response contains a checksum (by
+
+
+
+Franks, et al. Standards Track [Page 6]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ default, the MD5 checksum) of the username, the password, the given
+ nonce value, the HTTP method, and the requested URI. In this way, the
+ password is never sent in the clear. Just as with the Basic scheme,
+ the username and password must be prearranged in some fashion not
+ addressed by this document.
+
+3.1.3 Representation of digest values
+
+ An optional header allows the server to specify the algorithm used to
+ create the checksum or digest. By default the MD5 algorithm is used
+ and that is the only algorithm described in this document.
+
+ For the purposes of this document, an MD5 digest of 128 bits is
+ represented as 32 ASCII printable characters. The bits in the 128 bit
+ digest are converted from most significant to least significant bit,
+ four bits at a time to their ASCII presentation as follows. Each four
+ bits is represented by its familiar hexadecimal notation from the
+ characters 0123456789abcdef. That is, binary 0000 gets represented by
+ the character '0', 0001, by '1', and so on up to the representation
+ of 1111 as 'f'.
+
+3.1.4 Limitations
+
+ The Digest authentication scheme described in this document suffers
+ from many known limitations. It is intended as a replacement for
+ Basic authentication and nothing more. It is a password-based system
+ and (on the server side) suffers from all the same problems of any
+ password system. In particular, no provision is made in this protocol
+ for the initial secure arrangement between user and server to
+ establish the user's password.
+
+ Users and implementors should be aware that this protocol is not as
+ secure as Kerberos, and not as secure as any client-side private-key
+ scheme. Nevertheless it is better than nothing, better than what is
+ commonly used with telnet and ftp, and better than Basic
+ authentication.
+
+3.2 Specification of Digest Headers
+
+ The Digest Access Authentication scheme is conceptually similar to
+ the Basic scheme. The formats of the modified WWW-Authenticate header
+ line and the Authorization header line are specified below. In
+ addition, a new header, Authentication-Info, is specified.
+
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 7]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+3.2.1 The WWW-Authenticate Response Header
+
+ If a server receives a request for an access-protected object, and an
+ acceptable Authorization header is not sent, the server responds with
+ a "401 Unauthorized" status code, and a WWW-Authenticate header as
+ per the framework defined above, which for the digest scheme is
+ utilized as follows:
+
+ challenge = "Digest" digest-challenge
+
+ digest-challenge = 1#( realm | [ domain ] | nonce |
+ [ opaque ] |[ stale ] | [ algorithm ] |
+ [ qop-options ] | [auth-param] )
+
+
+ domain = "domain" "=" <"> URI ( 1*SP URI ) <">
+ URI = absoluteURI | abs_path
+ nonce = "nonce" "=" nonce-value
+ nonce-value = quoted-string
+ opaque = "opaque" "=" quoted-string
+ stale = "stale" "=" ( "true" | "false" )
+ algorithm = "algorithm" "=" ( "MD5" | "MD5-sess" |
+ token )
+ qop-options = "qop" "=" <"> 1#qop-value <">
+ qop-value = "auth" | "auth-int" | token
+
+ The meanings of the values of the directives used above are as
+ follows:
+
+ realm
+ A string to be displayed to users so they know which username and
+ password to use. This string should contain at least the name of
+ the host performing the authentication and might additionally
+ indicate the collection of users who might have access. An example
+ might be "registered_users@gotham.news.com".
+
+ domain
+ A quoted, space-separated list of URIs, as specified in RFC XURI
+ [7], that define the protection space. If a URI is an abs_path, it
+ is relative to the canonical root URL (see section 1.2 above) of
+ the server being accessed. An absoluteURI in this list may refer to
+ a different server than the one being accessed. The client can use
+ this list to determine the set of URIs for which the same
+ authentication information may be sent: any URI that has a URI in
+ this list as a prefix (after both have been made absolute) may be
+ assumed to be in the same protection space. If this directive is
+ omitted or its value is empty, the client should assume that the
+ protection space consists of all URIs on the responding server.
+
+
+
+Franks, et al. Standards Track [Page 8]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ This directive is not meaningful in Proxy-Authenticate headers, for
+ which the protection space is always the entire proxy; if present
+ it should be ignored.
+
+ nonce
+ A server-specified data string which should be uniquely generated
+ each time a 401 response is made. It is recommended that this
+ string be base64 or hexadecimal data. Specifically, since the
+ string is passed in the header lines as a quoted string, the
+ double-quote character is not allowed.
+
+ The contents of the nonce are implementation dependent. The quality
+ of the implementation depends on a good choice. A nonce might, for
+ example, be constructed as the base 64 encoding of
+
+ time-stamp H(time-stamp ":" ETag ":" private-key)
+
+ where time-stamp is a server-generated time or other non-repeating
+ value, ETag is the value of the HTTP ETag header associated with
+ the requested entity, and private-key is data known only to the
+ server. With a nonce of this form a server would recalculate the
+ hash portion after receiving the client authentication header and
+ reject the request if it did not match the nonce from that header
+ or if the time-stamp value is not recent enough. In this way the
+ server can limit the time of the nonce's validity. The inclusion of
+ the ETag prevents a replay request for an updated version of the
+ resource. (Note: including the IP address of the client in the
+ nonce would appear to offer the server the ability to limit the
+ reuse of the nonce to the same client that originally got it.
+ However, that would break proxy farms, where requests from a single
+ user often go through different proxies in the farm. Also, IP
+ address spoofing is not that hard.)
+
+ An implementation might choose not to accept a previously used
+ nonce or a previously used digest, in order to protect against a
+ replay attack. Or, an implementation might choose to use one-time
+ nonces or digests for POST or PUT requests and a time-stamp for GET
+ requests. For more details on the issues involved see section 4.
+ of this document.
+
+ The nonce is opaque to the client.
+
+ opaque
+ A string of data, specified by the server, which should be returned
+ by the client unchanged in the Authorization header of subsequent
+ requests with URIs in the same protection space. It is recommended
+ that this string be base64 or hexadecimal data.
+
+
+
+
+Franks, et al. Standards Track [Page 9]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ stale
+ A flag, indicating that the previous request from the client was
+ rejected because the nonce value was stale. If stale is TRUE
+ (case-insensitive), the client may wish to simply retry the request
+ with a new encrypted response, without reprompting the user for a
+ new username and password. The server should only set stale to TRUE
+ if it receives a request for which the nonce is invalid but with a
+ valid digest for that nonce (indicating that the client knows the
+ correct username/password). If stale is FALSE, or anything other
+ than TRUE, or the stale directive is not present, the username
+ and/or password are invalid, and new values must be obtained.
+
+ algorithm
+ A string indicating a pair of algorithms used to produce the digest
+ and a checksum. If this is not present it is assumed to be "MD5".
+ If the algorithm is not understood, the challenge should be ignored
+ (and a different one used, if there is more than one).
+
+ In this document the string obtained by applying the digest
+ algorithm to the data "data" with secret "secret" will be denoted
+ by KD(secret, data), and the string obtained by applying the
+ checksum algorithm to the data "data" will be denoted H(data). The
+ notation unq(X) means the value of the quoted-string X without the
+ surrounding quotes.
+
+ For the "MD5" and "MD5-sess" algorithms
+
+ H(data) = MD5(data)
+
+ and
+
+ KD(secret, data) = H(concat(secret, ":", data))
+
+ i.e., the digest is the MD5 of the secret concatenated with a colon
+ concatenated with the data. The "MD5-sess" algorithm is intended to
+ allow efficient 3rd party authentication servers; for the
+ difference in usage, see the description in section 3.2.2.2.
+
+ qop-options
+ This directive is optional, but is made so only for backward
+ compatibility with RFC 2069 [6]; it SHOULD be used by all
+ implementations compliant with this version of the Digest scheme.
+ If present, it is a quoted string of one or more tokens indicating
+ the "quality of protection" values supported by the server. The
+ value "auth" indicates authentication; the value "auth-int"
+ indicates authentication with integrity protection; see the
+
+
+
+
+
+Franks, et al. Standards Track [Page 10]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ descriptions below for calculating the response directive value for
+ the application of this choice. Unrecognized options MUST be
+ ignored.
+
+ auth-param
+ This directive allows for future extensions. Any unrecognized
+ directive MUST be ignored.
+
+3.2.2 The Authorization Request Header
+
+ The client is expected to retry the request, passing an Authorization
+ header line, which is defined according to the framework above,
+ utilized as follows.
+
+ credentials = "Digest" digest-response
+ digest-response = 1#( username | realm | nonce | digest-uri
+ | response | [ algorithm ] | [cnonce] |
+ [opaque] | [message-qop] |
+ [nonce-count] | [auth-param] )
+
+ username = "username" "=" username-value
+ username-value = quoted-string
+ digest-uri = "uri" "=" digest-uri-value
+ digest-uri-value = request-uri ; As specified by HTTP/1.1
+ message-qop = "qop" "=" qop-value
+ cnonce = "cnonce" "=" cnonce-value
+ cnonce-value = nonce-value
+ nonce-count = "nc" "=" nc-value
+ nc-value = 8LHEX
+ response = "response" "=" request-digest
+ request-digest = <"> 32LHEX <">
+ LHEX = "0" | "1" | "2" | "3" |
+ "4" | "5" | "6" | "7" |
+ "8" | "9" | "a" | "b" |
+ "c" | "d" | "e" | "f"
+
+ The values of the opaque and algorithm fields must be those supplied
+ in the WWW-Authenticate response header for the entity being
+ requested.
+
+ response
+ A string of 32 hex digits computed as defined below, which proves
+ that the user knows a password
+
+ username
+ The user's name in the specified realm.
+
+
+
+
+
+Franks, et al. Standards Track [Page 11]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ digest-uri
+ The URI from Request-URI of the Request-Line; duplicated here
+ because proxies are allowed to change the Request-Line in transit.
+
+ qop
+ Indicates what "quality of protection" the client has applied to
+ the message. If present, its value MUST be one of the alternatives
+ the server indicated it supports in the WWW-Authenticate header.
+ These values affect the computation of the request-digest. Note
+ that this is a single token, not a quoted list of alternatives as
+ in WWW- Authenticate. This directive is optional in order to
+ preserve backward compatibility with a minimal implementation of
+ RFC 2069 [6], but SHOULD be used if the server indicated that qop
+ is supported by providing a qop directive in the WWW-Authenticate
+ header field.
+
+ cnonce
+ This MUST be specified if a qop directive is sent (see above), and
+ MUST NOT be specified if the server did not send a qop directive in
+ the WWW-Authenticate header field. The cnonce-value is an opaque
+ quoted string value provided by the client and used by both client
+ and server to avoid chosen plaintext attacks, to provide mutual
+ authentication, and to provide some message integrity protection.
+ See the descriptions below of the calculation of the response-
+ digest and request-digest values.
+
+ nonce-count
+ This MUST be specified if a qop directive is sent (see above), and
+ MUST NOT be specified if the server did not send a qop directive in
+ the WWW-Authenticate header field. The nc-value is the hexadecimal
+ count of the number of requests (including the current request)
+ that the client has sent with the nonce value in this request. For
+ example, in the first request sent in response to a given nonce
+ value, the client sends "nc=00000001". The purpose of this
+ directive is to allow the server to detect request replays by
+ maintaining its own copy of this count - if the same nc-value is
+ seen twice, then the request is a replay. See the description
+ below of the construction of the request-digest value.
+
+ auth-param
+ This directive allows for future extensions. Any unrecognized
+ directive MUST be ignored.
+
+ If a directive or its value is improper, or required directives are
+ missing, the proper response is 400 Bad Request. If the request-
+ digest is invalid, then a login failure should be logged, since
+ repeated login failures from a single client may indicate an attacker
+ attempting to guess passwords.
+
+
+
+Franks, et al. Standards Track [Page 12]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ The definition of request-digest above indicates the encoding for its
+ value. The following definitions show how the value is computed.
+
+3.2.2.1 Request-Digest
+
+ If the "qop" value is "auth" or "auth-int":
+
+ request-digest = <"> < KD ( H(A1), unq(nonce-value)
+ ":" nc-value
+ ":" unq(cnonce-value)
+ ":" unq(qop-value)
+ ":" H(A2)
+ ) <">
+
+ If the "qop" directive is not present (this construction is for
+ compatibility with RFC 2069):
+
+ request-digest =
+ <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) >
+ <">
+
+ See below for the definitions for A1 and A2.
+
+3.2.2.2 A1
+
+ If the "algorithm" directive's value is "MD5" or is unspecified, then
+ A1 is:
+
+ A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+
+ where
+
+ passwd = < user's password >
+
+ If the "algorithm" directive's value is "MD5-sess", then A1 is
+ calculated only once - on the first request by the client following
+ receipt of a WWW-Authenticate challenge from the server. It uses the
+ server nonce from that challenge, and the first client nonce value to
+ construct A1 as follows:
+
+ A1 = H( unq(username-value) ":" unq(realm-value)
+ ":" passwd )
+ ":" unq(nonce-value) ":" unq(cnonce-value)
+
+ This creates a 'session key' for the authentication of subsequent
+ requests and responses which is different for each "authentication
+ session", thus limiting the amount of material hashed with any one
+ key. (Note: see further discussion of the authentication session in
+
+
+
+Franks, et al. Standards Track [Page 13]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ section 3.3.) Because the server need only use the hash of the user
+ credentials in order to create the A1 value, this construction could
+ be used in conjunction with a third party authentication service so
+ that the web server would not need the actual password value. The
+ specification of such a protocol is beyond the scope of this
+ specification.
+
+3.2.2.3 A2
+
+ If the "qop" directive's value is "auth" or is unspecified, then A2
+ is:
+
+ A2 = Method ":" digest-uri-value
+
+ If the "qop" value is "auth-int", then A2 is:
+
+ A2 = Method ":" digest-uri-value ":" H(entity-body)
+
+3.2.2.4 Directive values and quoted-string
+
+ Note that the value of many of the directives, such as "username-
+ value", are defined as a "quoted-string". However, the "unq" notation
+ indicates that surrounding quotation marks are removed in forming the
+ string A1. Thus if the Authorization header includes the fields
+
+ username="Mufasa", realm=myhost@testrealm.com
+
+ and the user Mufasa has password "Circle Of Life" then H(A1) would be
+ H(Mufasa:myhost@testrealm.com:Circle Of Life) with no quotation marks
+ in the digested string.
+
+ No white space is allowed in any of the strings to which the digest
+ function H() is applied unless that white space exists in the quoted
+ strings or entity body whose contents make up the string to be
+ digested. For example, the string A1 illustrated above must be
+
+ Mufasa:myhost@testrealm.com:Circle Of Life
+
+ with no white space on either side of the colons, but with the white
+ space between the words used in the password value. Likewise, the
+ other strings digested by H() must not have white space on either
+ side of the colons which delimit their fields unless that white space
+ was in the quoted strings or entity body being digested.
+
+ Also note that if integrity protection is applied (qop=auth-int), the
+ H(entity-body) is the hash of the entity body, not the message body -
+ it is computed before any transfer encoding is applied by the sender
+
+
+
+
+Franks, et al. Standards Track [Page 14]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ and after it has been removed by the recipient. Note that this
+ includes multipart boundaries and embedded headers in each part of
+ any multipart content-type.
+
+3.2.2.5 Various considerations
+
+ The "Method" value is the HTTP request method as specified in section
+ 5.1.1 of [2]. The "request-uri" value is the Request-URI from the
+ request line as specified in section 5.1.2 of [2]. This may be "*",
+ an "absoluteURL" or an "abs_path" as specified in section 5.1.2 of
+ [2], but it MUST agree with the Request-URI. In particular, it MUST
+ be an "absoluteURL" if the Request-URI is an "absoluteURL". The
+ "cnonce-value" is an optional client-chosen value whose purpose is
+ to foil chosen plaintext attacks.
+
+ The authenticating server must assure that the resource designated by
+ the "uri" directive is the same as the resource specified in the
+ Request-Line; if they are not, the server SHOULD return a 400 Bad
+ Request error. (Since this may be a symptom of an attack, server
+ implementers may want to consider logging such errors.) The purpose
+ of duplicating information from the request URL in this field is to
+ deal with the possibility that an intermediate proxy may alter the
+ client's Request-Line. This altered (but presumably semantically
+ equivalent) request would not result in the same digest as that
+ calculated by the client.
+
+ Implementers should be aware of how authenticated transactions
+ interact with shared caches. The HTTP/1.1 protocol specifies that
+ when a shared cache (see section 13.7 of [2]) has received a request
+ containing an Authorization header and a response from relaying that
+ request, it MUST NOT return that response as a reply to any other
+ request, unless one of two Cache-Control (see section 14.9 of [2])
+ directives was present in the response. If the original response
+ included the "must-revalidate" Cache-Control directive, the cache MAY
+ use the entity of that response in replying to a subsequent request,
+ but MUST first revalidate it with the origin server, using the
+ request headers from the new request to allow the origin server to
+ authenticate the new request. Alternatively, if the original response
+ included the "public" Cache-Control directive, the response entity
+ MAY be returned in reply to any subsequent request.
+
+3.2.3 The Authentication-Info Header
+
+ The Authentication-Info header is used by the server to communicate
+ some information regarding the successful authentication in the
+ response.
+
+
+
+
+
+Franks, et al. Standards Track [Page 15]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ AuthenticationInfo = "Authentication-Info" ":" auth-info
+ auth-info = 1#(nextnonce | [ message-qop ]
+ | [ response-auth ] | [ cnonce ]
+ | [nonce-count] )
+ nextnonce = "nextnonce" "=" nonce-value
+ response-auth = "rspauth" "=" response-digest
+ response-digest = <"> *LHEX <">
+
+ The value of the nextnonce directive is the nonce the server wishes
+ the client to use for a future authentication response. The server
+ may send the Authentication-Info header with a nextnonce field as a
+ means of implementing one-time or otherwise changing nonces. If the
+ nextnonce field is present the client SHOULD use it when constructing
+ the Authorization header for its next request. Failure of the client
+ to do so may result in a request to re-authenticate from the server
+ with the "stale=TRUE".
+
+ Server implementations should carefully consider the performance
+ implications of the use of this mechanism; pipelined requests will
+ not be possible if every response includes a nextnonce directive
+ that must be used on the next request received by the server.
+ Consideration should be given to the performance vs. security
+ tradeoffs of allowing an old nonce value to be used for a limited
+ time to permit request pipelining. Use of the nonce-count can
+ retain most of the security advantages of a new server nonce
+ without the deleterious affects on pipelining.
+
+ message-qop
+ Indicates the "quality of protection" options applied to the
+ response by the server. The value "auth" indicates authentication;
+ the value "auth-int" indicates authentication with integrity
+ protection. The server SHOULD use the same value for the message-
+ qop directive in the response as was sent by the client in the
+ corresponding request.
+
+ The optional response digest in the "response-auth" directive
+ supports mutual authentication -- the server proves that it knows the
+ user's secret, and with qop=auth-int also provides limited integrity
+ protection of the response. The "response-digest" value is calculated
+ as for the "request-digest" in the Authorization header, except that
+ if "qop=auth" or is not specified in the Authorization header for the
+ request, A2 is
+
+ A2 = ":" digest-uri-value
+
+ and if "qop=auth-int", then A2 is
+
+ A2 = ":" digest-uri-value ":" H(entity-body)
+
+
+
+Franks, et al. Standards Track [Page 16]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ where "digest-uri-value" is the value of the "uri" directive on the
+ Authorization header in the request. The "cnonce-value" and "nc-
+ value" MUST be the ones for the client request to which this message
+ is the response. The "response-auth", "cnonce", and "nonce-count"
+ directives MUST BE present if "qop=auth" or "qop=auth-int" is
+ specified.
+
+ The Authentication-Info header is allowed in the trailer of an HTTP
+ message transferred via chunked transfer-coding.
+
+3.3 Digest Operation
+
+ Upon receiving the Authorization header, the server may check its
+ validity by looking up the password that corresponds to the submitted
+ username. Then, the server must perform the same digest operation
+ (e.g., MD5) performed by the client, and compare the result to the
+ given request-digest value.
+
+ Note that the HTTP server does not actually need to know the user's
+ cleartext password. As long as H(A1) is available to the server, the
+ validity of an Authorization header may be verified.
+
+ The client response to a WWW-Authenticate challenge for a protection
+ space starts an authentication session with that protection space.
+ The authentication session lasts until the client receives another
+ WWW-Authenticate challenge from any server in the protection space. A
+ client should remember the username, password, nonce, nonce count and
+ opaque values associated with an authentication session to use to
+ construct the Authorization header in future requests within that
+ protection space. The Authorization header may be included
+ preemptively; doing so improves server efficiency and avoids extra
+ round trips for authentication challenges. The server may choose to
+ accept the old Authorization header information, even though the
+ nonce value included might not be fresh. Alternatively, the server
+ may return a 401 response with a new nonce value, causing the client
+ to retry the request; by specifying stale=TRUE with this response,
+ the server tells the client to retry with the new nonce, but without
+ prompting for a new username and password.
+
+ Because the client is required to return the value of the opaque
+ directive given to it by the server for the duration of a session,
+ the opaque data may be used to transport authentication session state
+ information. (Note that any such use can also be accomplished more
+ easily and safely by including the state in the nonce.) For example,
+ a server could be responsible for authenticating content that
+ actually sits on another server. It would achieve this by having the
+ first 401 response include a domain directive whose value includes a
+ URI on the second server, and an opaque directive whose value
+
+
+
+Franks, et al. Standards Track [Page 17]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ contains the state information. The client will retry the request, at
+ which time the server might respond with a 301/302 redirection,
+ pointing to the URI on the second server. The client will follow the
+ redirection, and pass an Authorization header , including the
+ <opaque> data.
+
+ As with the basic scheme, proxies must be completely transparent in
+ the Digest access authentication scheme. That is, they must forward
+ the WWW-Authenticate, Authentication-Info and Authorization headers
+ untouched. If a proxy wants to authenticate a client before a request
+ is forwarded to the server, it can be done using the Proxy-
+ Authenticate and Proxy-Authorization headers described in section 3.6
+ below.
+
+3.4 Security Protocol Negotiation
+
+ It is useful for a server to be able to know which security schemes a
+ client is capable of handling.
+
+ It is possible that a server may want to require Digest as its
+ authentication method, even if the server does not know that the
+ client supports it. A client is encouraged to fail gracefully if the
+ server specifies only authentication schemes it cannot handle.
+
+3.5 Example
+
+ The following example assumes that an access-protected document is
+ being requested from the server via a GET request. The URI of the
+ document is "http://www.nowhere.org/dir/index.html". Both client and
+ server know that the username for this document is "Mufasa", and the
+ password is "Circle Of Life" (with one space between each of the
+ three words).
+
+ The first time the client requests the document, no Authorization
+ header is sent, so the server responds with:
+
+ HTTP/1.1 401 Unauthorized
+ WWW-Authenticate: Digest
+ realm="testrealm@host.com",
+ qop="auth,auth-int",
+ nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
+ opaque="5ccc069c403ebaf9f0171e9517f40e41"
+
+ The client may prompt the user for the username and password, after
+ which it will respond with a new request, including the following
+ Authorization header:
+
+
+
+
+
+Franks, et al. Standards Track [Page 18]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ Authorization: Digest username="Mufasa",
+ realm="testrealm@host.com",
+ nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
+ uri="/dir/index.html",
+ qop=auth,
+ nc=00000001,
+ cnonce="0a4f113b",
+ response="6629fae49393a05397450978507c4ef1",
+ opaque="5ccc069c403ebaf9f0171e9517f40e41"
+
+3.6 Proxy-Authentication and Proxy-Authorization
+
+ The digest authentication scheme may also be used for authenticating
+ users to proxies, proxies to proxies, or proxies to origin servers by
+ use of the Proxy-Authenticate and Proxy-Authorization headers. These
+ headers are instances of the Proxy-Authenticate and Proxy-
+ Authorization headers specified in sections 10.33 and 10.34 of the
+ HTTP/1.1 specification [2] and their behavior is subject to
+ restrictions described there. The transactions for proxy
+ authentication are very similar to those already described. Upon
+ receiving a request which requires authentication, the proxy/server
+ must issue the "407 Proxy Authentication Required" response with a
+ "Proxy-Authenticate" header. The digest-challenge used in the
+ Proxy-Authenticate header is the same as that for the WWW-
+ Authenticate header as defined above in section 3.2.1.
+
+ The client/proxy must then re-issue the request with a Proxy-
+ Authorization header, with directives as specified for the
+ Authorization header in section 3.2.2 above.
+
+ On subsequent responses, the server sends Proxy-Authentication-Info
+ with directives the same as those for the Authentication-Info header
+ field.
+
+ Note that in principle a client could be asked to authenticate itself
+ to both a proxy and an end-server, but never in the same response.
+
+4 Security Considerations
+
+4.1 Authentication of Clients using Basic Authentication
+
+ The Basic authentication scheme is not a secure method of user
+ authentication, nor does it in any way protect the entity, which is
+ transmitted in cleartext across the physical network used as the
+ carrier. HTTP does not prevent additional authentication schemes and
+ encryption mechanisms from being employed to increase security or the
+ addition of enhancements (such as schemes to use one-time passwords)
+ to Basic authentication.
+
+
+
+Franks, et al. Standards Track [Page 19]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ The most serious flaw in Basic authentication is that it results in
+ the essentially cleartext transmission of the user's password over
+ the physical network. It is this problem which Digest Authentication
+ attempts to address.
+
+ Because Basic authentication involves the cleartext transmission of
+ passwords it SHOULD NOT be used (without enhancements) to protect
+ sensitive or valuable information.
+
+ A common use of Basic authentication is for identification purposes
+ -- requiring the user to provide a user name and password as a means
+ of identification, for example, for purposes of gathering accurate
+ usage statistics on a server. When used in this way it is tempting to
+ think that there is no danger in its use if illicit access to the
+ protected documents is not a major concern. This is only correct if
+ the server issues both user name and password to the users and in
+ particular does not allow the user to choose his or her own password.
+ The danger arises because naive users frequently reuse a single
+ password to avoid the task of maintaining multiple passwords.
+
+ If a server permits users to select their own passwords, then the
+ threat is not only unauthorized access to documents on the server but
+ also unauthorized access to any other resources on other systems that
+ the user protects with the same password. Furthermore, in the
+ server's password database, many of the passwords may also be users'
+ passwords for other sites. The owner or administrator of such a
+ system could therefore expose all users of the system to the risk of
+ unauthorized access to all those sites if this information is not
+ maintained in a secure fashion.
+
+ Basic Authentication is also vulnerable to spoofing by counterfeit
+ servers. If a user can be led to believe that he is connecting to a
+ host containing information protected by Basic authentication when,
+ in fact, he is connecting to a hostile server or gateway, then the
+ attacker can request a password, store it for later use, and feign an
+ error. This type of attack is not possible with Digest
+ Authentication. Server implementers SHOULD guard against the
+ possibility of this sort of counterfeiting by gateways or CGI
+ scripts. In particular it is very dangerous for a server to simply
+ turn over a connection to a gateway. That gateway can then use the
+ persistent connection mechanism to engage in multiple transactions
+ with the client while impersonating the original server in a way that
+ is not detectable by the client.
+
+4.2 Authentication of Clients using Digest Authentication
+
+ Digest Authentication does not provide a strong authentication
+ mechanism, when compared to public key based mechanisms, for example.
+
+
+
+Franks, et al. Standards Track [Page 20]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ However, it is significantly stronger than (e.g.) CRAM-MD5, which has
+ been proposed for use with LDAP [10], POP and IMAP (see RFC 2195
+ [9]). It is intended to replace the much weaker and even more
+ dangerous Basic mechanism.
+
+ Digest Authentication offers no confidentiality protection beyond
+ protecting the actual password. All of the rest of the request and
+ response are available to an eavesdropper.
+
+ Digest Authentication offers only limited integrity protection for
+ the messages in either direction. If qop=auth-int mechanism is used,
+ those parts of the message used in the calculation of the WWW-
+ Authenticate and Authorization header field response directive values
+ (see section 3.2 above) are protected. Most header fields and their
+ values could be modified as a part of a man-in-the-middle attack.
+
+ Many needs for secure HTTP transactions cannot be met by Digest
+ Authentication. For those needs TLS or SHTTP are more appropriate
+ protocols. In particular Digest authentication cannot be used for any
+ transaction requiring confidentiality protection. Nevertheless many
+ functions remain for which Digest authentication is both useful and
+ appropriate. Any service in present use that uses Basic should be
+ switched to Digest as soon as practical.
+
+4.3 Limited Use Nonce Values
+
+ The Digest scheme uses a server-specified nonce to seed the
+ generation of the request-digest value (as specified in section
+ 3.2.2.1 above). As shown in the example nonce in section 3.2.1, the
+ server is free to construct the nonce such that it may only be used
+ from a particular client, for a particular resource, for a limited
+ period of time or number of uses, or any other restrictions. Doing
+ so strengthens the protection provided against, for example, replay
+ attacks (see 4.5). However, it should be noted that the method
+ chosen for generating and checking the nonce also has performance and
+ resource implications. For example, a server may choose to allow
+ each nonce value to be used only once by maintaining a record of
+ whether or not each recently issued nonce has been returned and
+ sending a next-nonce directive in the Authentication-Info header
+ field of every response. This protects against even an immediate
+ replay attack, but has a high cost checking nonce values, and perhaps
+ more important will cause authentication failures for any pipelined
+ requests (presumably returning a stale nonce indication). Similarly,
+ incorporating a request-specific element such as the Etag value for a
+ resource limits the use of the nonce to that version of the resource
+ and also defeats pipelining. Thus it may be useful to do so for
+ methods with side effects but have unacceptable performance for those
+ that do not.
+
+
+
+Franks, et al. Standards Track [Page 21]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+4.4 Comparison of Digest with Basic Authentication
+
+ Both Digest and Basic Authentication are very much on the weak end of
+ the security strength spectrum. But a comparison between the two
+ points out the utility, even necessity, of replacing Basic by Digest.
+
+ The greatest threat to the type of transactions for which these
+ protocols are used is network snooping. This kind of transaction
+ might involve, for example, online access to a database whose use is
+ restricted to paying subscribers. With Basic authentication an
+ eavesdropper can obtain the password of the user. This not only
+ permits him to access anything in the database, but, often worse,
+ will permit access to anything else the user protects with the same
+ password.
+
+ By contrast, with Digest Authentication the eavesdropper only gets
+ access to the transaction in question and not to the user's password.
+ The information gained by the eavesdropper would permit a replay
+ attack, but only with a request for the same document, and even that
+ may be limited by the server's choice of nonce.
+
+4.5 Replay Attacks
+
+ A replay attack against Digest authentication would usually be
+ pointless for a simple GET request since an eavesdropper would
+ already have seen the only document he could obtain with a replay.
+ This is because the URI of the requested document is digested in the
+ client request and the server will only deliver that document. By
+ contrast under Basic Authentication once the eavesdropper has the
+ user's password, any document protected by that password is open to
+ him.
+
+ Thus, for some purposes, it is necessary to protect against replay
+ attacks. A good Digest implementation can do this in various ways.
+ The server created "nonce" value is implementation dependent, but if
+ it contains a digest of the client IP, a time-stamp, the resource
+ ETag, and a private server key (as recommended above) then a replay
+ attack is not simple. An attacker must convince the server that the
+ request is coming from a false IP address and must cause the server
+ to deliver the document to an IP address different from the address
+ to which it believes it is sending the document. An attack can only
+ succeed in the period before the time-stamp expires. Digesting the
+ client IP and time-stamp in the nonce permits an implementation which
+ does not maintain state between transactions.
+
+ For applications where no possibility of replay attack can be
+ tolerated the server can use one-time nonce values which will not be
+ honored for a second use. This requires the overhead of the server
+
+
+
+Franks, et al. Standards Track [Page 22]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ remembering which nonce values have been used until the nonce time-
+ stamp (and hence the digest built with it) has expired, but it
+ effectively protects against replay attacks.
+
+ An implementation must give special attention to the possibility of
+ replay attacks with POST and PUT requests. Unless the server employs
+ one-time or otherwise limited-use nonces and/or insists on the use of
+ the integrity protection of qop=auth-int, an attacker could replay
+ valid credentials from a successful request with counterfeit form
+ data or other message body. Even with the use of integrity protection
+ most metadata in header fields is not protected. Proper nonce
+ generation and checking provides some protection against replay of
+ previously used valid credentials, but see 4.8.
+
+4.6 Weakness Created by Multiple Authentication Schemes
+
+ An HTTP/1.1 server may return multiple challenges with a 401
+ (Authenticate) response, and each challenge may use a different
+ auth-scheme. A user agent MUST choose to use the strongest auth-
+ scheme it understands and request credentials from the user based
+ upon that challenge.
+
+ Note that many browsers will only recognize Basic and will require
+ that it be the first auth-scheme presented. Servers should only
+ include Basic if it is minimally acceptable.
+
+ When the server offers choices of authentication schemes using the
+ WWW-Authenticate header, the strength of the resulting authentication
+ is only as good as that of the of the weakest of the authentication
+ schemes. See section 4.8 below for discussion of particular attack
+ scenarios that exploit multiple authentication schemes.
+
+4.7 Online dictionary attacks
+
+ If the attacker can eavesdrop, then it can test any overheard
+ nonce/response pairs against a list of common words. Such a list is
+ usually much smaller than the total number of possible passwords. The
+ cost of computing the response for each password on the list is paid
+ once for each challenge.
+
+ The server can mitigate this attack by not allowing users to select
+ passwords that are in a dictionary.
+
+
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 23]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+4.8 Man in the Middle
+
+ Both Basic and Digest authentication are vulnerable to "man in the
+ middle" (MITM) attacks, for example, from a hostile or compromised
+ proxy. Clearly, this would present all the problems of eavesdropping.
+ But it also offers some additional opportunities to the attacker.
+
+ A possible man-in-the-middle attack would be to add a weak
+ authentication scheme to the set of choices, hoping that the client
+ will use one that exposes the user's credentials (e.g. password). For
+ this reason, the client should always use the strongest scheme that
+ it understands from the choices offered.
+
+ An even better MITM attack would be to remove all offered choices,
+ replacing them with a challenge that requests only Basic
+ authentication, then uses the cleartext credentials from the Basic
+ authentication to authenticate to the origin server using the
+ stronger scheme it requested. A particularly insidious way to mount
+ such a MITM attack would be to offer a "free" proxy caching service
+ to gullible users.
+
+ User agents should consider measures such as presenting a visual
+ indication at the time of the credentials request of what
+ authentication scheme is to be used, or remembering the strongest
+ authentication scheme ever requested by a server and produce a
+ warning message before using a weaker one. It might also be a good
+ idea for the user agent to be configured to demand Digest
+ authentication in general, or from specific sites.
+
+ Or, a hostile proxy might spoof the client into making a request the
+ attacker wanted rather than one the client wanted. Of course, this is
+ still much harder than a comparable attack against Basic
+ Authentication.
+
+4.9 Chosen plaintext attacks
+
+ With Digest authentication, a MITM or a malicious server can
+ arbitrarily choose the nonce that the client will use to compute the
+ response. This is called a "chosen plaintext" attack. The ability to
+ choose the nonce is known to make cryptanalysis much easier [8].
+
+ However, no way to analyze the MD5 one-way function used by Digest
+ using chosen plaintext is currently known.
+
+ The countermeasure against this attack is for clients to be
+ configured to require the use of the optional "cnonce" directive;
+ this allows the client to vary the input to the hash in a way not
+ chosen by the attacker.
+
+
+
+Franks, et al. Standards Track [Page 24]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+4.10 Precomputed dictionary attacks
+
+ With Digest authentication, if the attacker can execute a chosen
+ plaintext attack, the attacker can precompute the response for many
+ common words to a nonce of its choice, and store a dictionary of
+ (response, password) pairs. Such precomputation can often be done in
+ parallel on many machines. It can then use the chosen plaintext
+ attack to acquire a response corresponding to that challenge, and
+ just look up the password in the dictionary. Even if most passwords
+ are not in the dictionary, some might be. Since the attacker gets to
+ pick the challenge, the cost of computing the response for each
+ password on the list can be amortized over finding many passwords. A
+ dictionary with 100 million password/response pairs would take about
+ 3.2 gigabytes of disk storage.
+
+ The countermeasure against this attack is to for clients to be
+ configured to require the use of the optional "cnonce" directive.
+
+4.11 Batch brute force attacks
+
+ With Digest authentication, a MITM can execute a chosen plaintext
+ attack, and can gather responses from many users to the same nonce.
+ It can then find all the passwords within any subset of password
+ space that would generate one of the nonce/response pairs in a single
+ pass over that space. It also reduces the time to find the first
+ password by a factor equal to the number of nonce/response pairs
+ gathered. This search of the password space can often be done in
+ parallel on many machines, and even a single machine can search large
+ subsets of the password space very quickly -- reports exist of
+ searching all passwords with six or fewer letters in a few hours.
+
+ The countermeasure against this attack is to for clients to be
+ configured to require the use of the optional "cnonce" directive.
+
+4.12 Spoofing by Counterfeit Servers
+
+ Basic Authentication is vulnerable to spoofing by counterfeit
+ servers. If a user can be led to believe that she is connecting to a
+ host containing information protected by a password she knows, when
+ in fact she is connecting to a hostile server, then the hostile
+ server can request a password, store it away for later use, and feign
+ an error. This type of attack is more difficult with Digest
+ Authentication -- but the client must know to demand that Digest
+ authentication be used, perhaps using some of the techniques
+ described above to counter "man-in-the-middle" attacks. Again, the
+ user can be helped in detecting this attack by a visual indication of
+ the authentication mechanism in use with appropriate guidance in
+ interpreting the implications of each scheme.
+
+
+
+Franks, et al. Standards Track [Page 25]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+4.13 Storing passwords
+
+ Digest authentication requires that the authenticating agent (usually
+ the server) store some data derived from the user's name and password
+ in a "password file" associated with a given realm. Normally this
+ might contain pairs consisting of username and H(A1), where H(A1) is
+ the digested value of the username, realm, and password as described
+ above.
+
+ The security implications of this are that if this password file is
+ compromised, then an attacker gains immediate access to documents on
+ the server using this realm. Unlike, say a standard UNIX password
+ file, this information need not be decrypted in order to access
+ documents in the server realm associated with this file. On the other
+ hand, decryption, or more likely a brute force attack, would be
+ necessary to obtain the user's password. This is the reason that the
+ realm is part of the digested data stored in the password file. It
+ means that if one Digest authentication password file is compromised,
+ it does not automatically compromise others with the same username
+ and password (though it does expose them to brute force attack).
+
+ There are two important security consequences of this. First the
+ password file must be protected as if it contained unencrypted
+ passwords, because for the purpose of accessing documents in its
+ realm, it effectively does.
+
+ A second consequence of this is that the realm string should be
+ unique among all realms which any single user is likely to use. In
+ particular a realm string should include the name of the host doing
+ the authentication. The inability of the client to authenticate the
+ server is a weakness of Digest Authentication.
+
+4.14 Summary
+
+ By modern cryptographic standards Digest Authentication is weak. But
+ for a large range of purposes it is valuable as a replacement for
+ Basic Authentication. It remedies some, but not all, weaknesses of
+ Basic Authentication. Its strength may vary depending on the
+ implementation. In particular the structure of the nonce (which is
+ dependent on the server implementation) may affect the ease of
+ mounting a replay attack. A range of server options is appropriate
+ since, for example, some implementations may be willing to accept the
+ server overhead of one-time nonces or digests to eliminate the
+ possibility of replay. Others may satisfied with a nonce like the one
+ recommended above restricted to a single IP address and a single ETag
+ or with a limited lifetime.
+
+
+
+
+
+Franks, et al. Standards Track [Page 26]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ The bottom line is that *any* compliant implementation will be
+ relatively weak by cryptographic standards, but *any* compliant
+ implementation will be far superior to Basic Authentication.
+
+5 Sample implementation
+
+ The following code implements the calculations of H(A1), H(A2),
+ request-digest and response-digest, and a test program which computes
+ the values used in the example of section 3.5. It uses the MD5
+ implementation from RFC 1321.
+
+ File "digcalc.h":
+
+#define HASHLEN 16
+typedef char HASH[HASHLEN];
+#define HASHHEXLEN 32
+typedef char HASHHEX[HASHHEXLEN+1];
+#define IN
+#define OUT
+
+/* calculate H(A1) as per HTTP Digest spec */
+void DigestCalcHA1(
+ IN char * pszAlg,
+ IN char * pszUserName,
+ IN char * pszRealm,
+ IN char * pszPassword,
+ IN char * pszNonce,
+ IN char * pszCNonce,
+ OUT HASHHEX SessionKey
+ );
+
+/* calculate request-digest/response-digest as per HTTP Digest spec */
+void DigestCalcResponse(
+ IN HASHHEX HA1, /* H(A1) */
+ IN char * pszNonce, /* nonce from server */
+ IN char * pszNonceCount, /* 8 hex digits */
+ IN char * pszCNonce, /* client nonce */
+ IN char * pszQop, /* qop-value: "", "auth", "auth-int" */
+ IN char * pszMethod, /* method from the request */
+ IN char * pszDigestUri, /* requested URL */
+ IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
+ OUT HASHHEX Response /* request-digest or response-digest */
+ );
+
+File "digcalc.c":
+
+#include <global.h>
+#include <md5.h>
+
+
+
+Franks, et al. Standards Track [Page 27]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+#include <string.h>
+#include "digcalc.h"
+
+void CvtHex(
+ IN HASH Bin,
+ OUT HASHHEX Hex
+ )
+{
+ unsigned short i;
+ unsigned char j;
+
+ for (i = 0; i < HASHLEN; i++) {
+ j = (Bin[i] >> 4) & 0xf;
+ if (j <= 9)
+ Hex[i*2] = (j + '0');
+ else
+ Hex[i*2] = (j + 'a' - 10);
+ j = Bin[i] & 0xf;
+ if (j <= 9)
+ Hex[i*2+1] = (j + '0');
+ else
+ Hex[i*2+1] = (j + 'a' - 10);
+ };
+ Hex[HASHHEXLEN] = '\0';
+};
+
+/* calculate H(A1) as per spec */
+void DigestCalcHA1(
+ IN char * pszAlg,
+ IN char * pszUserName,
+ IN char * pszRealm,
+ IN char * pszPassword,
+ IN char * pszNonce,
+ IN char * pszCNonce,
+ OUT HASHHEX SessionKey
+ )
+{
+ MD5_CTX Md5Ctx;
+ HASH HA1;
+
+ MD5Init(&Md5Ctx);
+ MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword));
+ MD5Final(HA1, &Md5Ctx);
+ if (stricmp(pszAlg, "md5-sess") == 0) {
+
+
+
+Franks, et al. Standards Track [Page 28]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ MD5Init(&Md5Ctx);
+ MD5Update(&Md5Ctx, HA1, HASHLEN);
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
+ MD5Final(HA1, &Md5Ctx);
+ };
+ CvtHex(HA1, SessionKey);
+};
+
+/* calculate request-digest/response-digest as per HTTP Digest spec */
+void DigestCalcResponse(
+ IN HASHHEX HA1, /* H(A1) */
+ IN char * pszNonce, /* nonce from server */
+ IN char * pszNonceCount, /* 8 hex digits */
+ IN char * pszCNonce, /* client nonce */
+ IN char * pszQop, /* qop-value: "", "auth", "auth-int" */
+ IN char * pszMethod, /* method from the request */
+ IN char * pszDigestUri, /* requested URL */
+ IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
+ OUT HASHHEX Response /* request-digest or response-digest */
+ )
+{
+ MD5_CTX Md5Ctx;
+ HASH HA2;
+ HASH RespHash;
+ HASHHEX HA2Hex;
+
+ // calculate H(A2)
+ MD5Init(&Md5Ctx);
+ MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri));
+ if (stricmp(pszQop, "auth-int") == 0) {
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, HEntity, HASHHEXLEN);
+ };
+ MD5Final(HA2, &Md5Ctx);
+ CvtHex(HA2, HA2Hex);
+
+ // calculate response
+ MD5Init(&Md5Ctx);
+ MD5Update(&Md5Ctx, HA1, HASHHEXLEN);
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce));
+ MD5Update(&Md5Ctx, ":", 1);
+ if (*pszQop) {
+
+
+
+Franks, et al. Standards Track [Page 29]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce));
+ MD5Update(&Md5Ctx, ":", 1);
+ MD5Update(&Md5Ctx, pszQop, strlen(pszQop));
+ MD5Update(&Md5Ctx, ":", 1);
+ };
+ MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN);
+ MD5Final(RespHash, &Md5Ctx);
+ CvtHex(RespHash, Response);
+};
+
+File "digtest.c":
+
+
+#include <stdio.h>
+#include "digcalc.h"
+
+void main(int argc, char ** argv) {
+
+ char * pszNonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093";
+ char * pszCNonce = "0a4f113b";
+ char * pszUser = "Mufasa";
+ char * pszRealm = "testrealm@host.com";
+ char * pszPass = "Circle Of Life";
+ char * pszAlg = "md5";
+ char szNonceCount[9] = "00000001";
+ char * pszMethod = "GET";
+ char * pszQop = "auth";
+ char * pszURI = "/dir/index.html";
+ HASHHEX HA1;
+ HASHHEX HA2 = "";
+ HASHHEX Response;
+
+ DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce,
+pszCNonce, HA1);
+ DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop,
+ pszMethod, pszURI, HA2, Response);
+ printf("Response = %s\n", Response);
+};
+
+
+
+
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 30]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+6 Acknowledgments
+
+ Eric W. Sink, of AbiSource, Inc., was one of the original authors
+ before the specification underwent substantial revision.
+
+ In addition to the authors, valuable discussion instrumental in
+ creating this document has come from Peter J. Churchyard, Ned Freed,
+ and David M. Kristol.
+
+ Jim Gettys and Larry Masinter edited this document for update.
+
+7 References
+
+ [1] Berners-Lee, T., Fielding, R. and H. Frystyk, "Hypertext
+ Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.
+
+ [2] Fielding, R., Gettys, J., Mogul, J., Frysyk, H., Masinter, L.,
+ Leach, P. and T. Berners-Lee, "Hypertext Transfer Protocol --
+ HTTP/1.1", RFC 2616, June 1999.
+
+ [3] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April
+ 1992.
+
+ [4] Freed, N. and N. Borenstein. "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ RFC 2045, November 1996.
+
+ [5] Dierks, T. and C. Allen "The TLS Protocol, Version 1.0", RFC
+ 2246, January 1999.
+
+ [6] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+ Luotonen, A., Sink, E. and L. Stewart, "An Extension to HTTP :
+ Digest Access Authentication", RFC 2069, January 1997.
+
+ [7] Berners Lee, T, Fielding, R. and L. Masinter, "Uniform Resource
+ Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
+
+ [8] Kaliski, B.,Robshaw, M., "Message Authentication with MD5",
+ CryptoBytes, Sping 1995, RSA Inc,
+ (http://www.rsa.com/rsalabs/pubs/cryptobytes/spring95/md5.htm)
+
+ [9] Klensin, J., Catoe, R. and P. Krumviede, "IMAP/POP AUTHorize
+ Extension for Simple Challenge/Response", RFC 2195, September
+ 1997.
+
+ [10] Morgan, B., Alvestrand, H., Hodges, J., Wahl, M.,
+ "Authentication Methods for LDAP", Work in Progress.
+
+
+
+
+Franks, et al. Standards Track [Page 31]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+8 Authors' Addresses
+
+ John Franks
+ Professor of Mathematics
+ Department of Mathematics
+ Northwestern University
+ Evanston, IL 60208-2730, USA
+
+ EMail: john@math.nwu.edu
+
+
+ Phillip M. Hallam-Baker
+ Principal Consultant
+ Verisign Inc.
+ 301 Edgewater Place
+ Suite 210
+ Wakefield MA 01880, USA
+
+ EMail: pbaker@verisign.com
+
+
+ Jeffery L. Hostetler
+ Software Craftsman
+ AbiSource, Inc.
+ 6 Dunlap Court
+ Savoy, IL 61874
+
+ EMail: jeff@AbiSource.com
+
+
+ Scott D. Lawrence
+ Agranat Systems, Inc.
+ 5 Clocktower Place, Suite 400
+ Maynard, MA 01754, USA
+
+ EMail: lawrence@agranat.com
+
+
+ Paul J. Leach
+ Microsoft Corporation
+ 1 Microsoft Way
+ Redmond, WA 98052, USA
+
+ EMail: paulle@microsoft.com
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 32]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+ Ari Luotonen
+ Member of Technical Staff
+ Netscape Communications Corporation
+ 501 East Middlefield Road
+ Mountain View, CA 94043, USA
+
+
+ Lawrence C. Stewart
+ Open Market, Inc.
+ 215 First Street
+ Cambridge, MA 02142, USA
+
+ EMail: stewart@OpenMarket.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 33]
+
+RFC 2617 HTTP Authentication June 1999
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Franks, et al. Standards Track [Page 34]
+
diff --git a/standards/rfc2639.txt b/standards/rfc2639.txt
new file mode 100644
index 000000000..e3ab71684
--- /dev/null
+++ b/standards/rfc2639.txt
@@ -0,0 +1,3587 @@
+
+
+
+
+
+
+Network Working Group T. Hastings
+Request for Comments: 2639 C. Manros
+Category: Informational Xerox Corporation
+ July 1999
+
+
+ Internet Printing Protocol/1.0: Implementer's Guide
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document contains
+ information that supplements the IPP Model and Semantics [RFC2566]
+ and the IPP Transport and Encoding [RFC2565] documents. It is
+ intended to help implementers understand IPP/1.0 and some of the
+ considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.0: Model and Semantics [RFC2566]
+ Internet Printing Protocol/1.0: Encoding and Transport [RFC2565]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The document, "Design Goals for an Internet Printing Protocol", takes
+ a broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+
+
+
+
+
+Hastings & Manros Informational [Page 1]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ administrators. The design goals document calls out a subset of end
+ user requirements that are satisfied in IPP/1.0. Operator and
+ administrator requirements are out of scope for version 1.0.
+
+ The document, "Rationale for the Structure and Model and Protocol for
+ the Internet Printing Protocol", describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specifications, and gives background and rationale for the
+ IETF working group's major decisions.
+
+ The document, "Internet Printing Protocol/1.0: Model and Semantics",
+ describes a simplified model with abstract objects, their attributes,
+ and their operations. The model introduces a Printer and a Job. The
+ Job supports multiple documents per Job. The model document also
+ addresses how security, internationalization, and directory issues
+ are addressed.
+
+ The document, "Internet Printing Protocol/1.0: Encoding and
+ Transport", is a formal mapping of the abstract operations and
+ attributes defined in the model document onto HTTP/1.1. It also
+ defines the encoding rules for a new Internet media type called
+ "application/ipp".
+
+ The document, "Mapping between LPD and IPP Protocols", gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+Table of Contents
+
+ 1 Introduction......................................................4
+ 1.1 Conformance language............................................4
+ 1.2 Other terminology...............................................5
+ 2 Model and Semantics...............................................5
+ 2.1 Summary of Operation Attributes.................................5
+ 2.2 Suggested Operation Processing Steps for IPP Objects ..........10
+ 2.2.1 Suggested Operation Processing Steps for all Operations..11
+ 2.2.1.1 Validate version number...............................11
+ 2.2.1.2 Validate operation identifier.........................11
+ 2.2.1.3 Validate the request identifier.......................11
+ 2.2.1.4 Validate attribute group and attribute presence and
+ order.................................................12
+ 2.2.1.5 Validate the values of the REQUIRED Operation
+ attributes............................................19
+ 2.2.1.6 Validate the values of the OPTIONAL Operation
+ attributes............................................23
+ 2.2.2 Suggested Additional Processing Steps for Operations that
+ Create/Validate Jobs and Add Documents.....................26
+ 2.2.2.1 Default "ipp-attribute-fidelity" if not supplied......26
+
+
+
+Hastings & Manros Informational [Page 2]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ 2.2.2.2 Check that the Printer object is accepting jobs.......26
+ 2.2.2.3 Validate the values of the Job Template attributes....26
+ 2.2.3 Algorithm for job validation...............................27
+ 2.2.3.1 Check for conflicting Job Template attributes values..33
+ 2.2.3.2 Decide whether to REJECT the request..................33
+ 2.2.3.3 For the Validate-Job operation, RETURN one of the
+ success status codes..................................34
+ 2.2.3.4 Create the Job object with attributes to support......34
+ 2.2.3.5 Return one of the success status codes................36
+ 2.2.3.6 Accept appended Document Content......................36
+ 2.2.3.7 Scheduling and Starting to Process the Job............36
+ 2.2.3.8 Completing the Job....................................37
+ 2.2.3.9 Destroying the Job after completion...................37
+ 2.2.3.10 Interaction with "ipp-attribute-fidelity".............37
+ 2.3 Status codes returned by operation ............................37
+ 2.3.1 Printer Operations.........................................38
+ 2.3.1.1 Print-Job.............................................38
+ 2.3.1.2 Print-URI.............................................40
+ 2.3.1.3 Validate-Job..........................................40
+ 2.3.1.4 Create-Job............................................41
+ 2.3.1.5 Get-Printer-Attributes................................41
+ 2.3.1.6 Get-Jobs..............................................42
+ 2.3.2 Job Operations.............................................43
+ 2.3.2.1 Send-Document.........................................43
+ 2.3.2.2 Send-URI..............................................44
+ 2.3.2.3 Cancel-Job............................................44
+ 2.3.2.4 Get-Job-Attributes....................................45
+ 2.4 Validate-Job...................................................46
+ 2.5 Case Sensitivity in URIs ......................................46
+ 2.6 Character Sets, natural languages, and internationalization....46
+ 2.6.1 Character set code conversion support .....................46
+ 2.6.2 What charset to return when an unsupported charset is
+ requested?.................................................48
+ 2.6.3 Natural Language Override (NLO) ...........................48
+ 2.7 The "queued-job-count" Printer Description attribute...........50
+ 2.7.1 Why is "queued-job-count" RECOMMENDED?.....................50
+ 2.7.2 Is "queued-job-count" a good measure of how busy a printer
+ is?........................................................50
+ 2.8 Sending empty attribute groups ................................50
+ 2.9 Returning unsupported attributes in Get-Xxxx responses ........51
+ 2.10 Returning job-state in Print-Job response ....................51
+ 2.11 Flow controlling the data portion of a Print-Job request .....52
+ 2.12 Multi-valued attributes ......................................53
+ 2.13 Querying jobs with IPP that were submitted using other job
+ submission protocols .........................................53
+ 2.14 The 'none' value for empty sets ..............................54
+ 2.15 Get-Jobs, my-jobs='true', and 'requesting-user-name'?.........54
+
+
+
+
+Hastings & Manros Informational [Page 3]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ 2.16 The "multiple-document-handling" Job Template attribute and
+ support of multiple document jobs.............................54
+ 3 Encoding and Transport...........................................55
+ 3.1 General Headers................................................56
+ 3.2 Request Headers...............................................57
+ 3.3 Response Headers...............................................58
+ 3.4 Entity Headers................................................59
+ 3.5 Optional support for HTTP/1.0..................................60
+ 3.6 HTTP/1.1 Chunking..............................................60
+ 3.6.1 Disabling IPP Server Response Chunking.....................60
+ 3.6.2 Warning About the Support of Chunked Requests..............60
+ 4 References.......................................................61
+ 4.1 Authors' Addresses.............................................62
+ 5 Security Considerations..........................................62
+ 6 Notices..........................................................62
+ Full Copyright Statement............................................65
+
+1 Introduction
+
+ This document contains information that supplements the IPP Model and
+ Semantics [RFC2566] and the IPP Transport and Encoding [RFC2565]
+ documents. As such this information is not part of the formal
+ specifications. Instead information is presented to help implementers
+ understand the specification, including some of the motivation for
+ decisions taken by the committee in developing the specification.
+ Some of the implementation considerations are intended to help
+ implementers design their client and/or IPP object implementations.
+ If there are any contradictions between this document and [RFC2566] or
+ [RFC2565], those documents take precedence over this document.
+
+1.1 Conformance language
+
+ Usually, this document does not contain the terminology MUST, MUST
+ NOT, MAY, NEED NOT, SHOULD, SHOULD NOT, REQUIRED, and OPTIONAL.
+ However, when those terms do appear in this document, their intent is
+ to repeat what the [RFC2566] and [RFC2565] documents require and
+ allow, rather than specifying additional conformance requirements.
+ These terms are defined in section 13 on conformance terminology in
+ [RFC2566], most of which is taken from RFC 2119 [RFC2119].
+
+ Implementers should read section 13 in [RFC2566] in order to
+ understand these capitalized words. The words MUST, MUST NOT, and
+ REQUIRED indicate what implementations are required to support in a
+ client or IPP object in order to be conformant to [RFC2566] and
+ [RFC2565]. MAY, NEED NOT, and OPTIONAL indicate was is merely allowed
+ as an implementer option. The verbs SHOULD and SHOULD NOT indicate
+ suggested behavior, but which is not required or disallowed,
+ respectively, in order to conform to the specification.
+
+
+
+Hastings & Manros Informational [Page 4]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+1.2 Other terminology
+
+ The term "sender" refers to the client that sends a request or an IPP
+ object that returns a response. The term "receiver" refers to the IPP
+ object that receives a request and to a client that receives a
+ response.
+
+2 Model and Semantics
+
+ This section discusses various aspects of IPP/1.0 Model and Semantics
+ [RFC2566].
+
+2.1 Summary of Operation Attributes
+
+ Legend for the following table:
+
+ R indicates a REQUIRED operation or attribute for an
+ implementation to support
+
+ O indicates an OPTIONAL operation or attribute for an
+ implementation to support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 5]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Table 1. Summary of operation attributes for Printer operations
+
+ Printer Operations
+
+ Requests Responses
+
+ Operation Print- Pri Crea Get- Get- All
+ Attributes Job, nt- te- Printer- Jobs Opera-
+ Validate URI Job Attribut tions
+ -Job (O) (O) es
+
+ Operation parameters--REQUIRED to be supplied by the sender
+
+ operation-id R R R R R
+
+ status-code R
+
+ request-id R R R R R R
+
+ version-number R R R R R R
+
+ Operation attributes-REQUIRED to be supplied by the sender
+
+ attributes-charset R R R R R R
+
+ attributes- R R R R R R
+ natural-language
+
+ document-uri R
+
+ job-id*
+
+ job-uri*
+
+ last-document
+
+ printer-uri R R R R R
+
+ Operation attributes-RECOMMENDED to be supplied by the sender
+
+ job-name R R R
+
+ requesting-user- R R R R R
+ name
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 6]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Printer Operations
+
+ Requests Responses
+
+ Operation Print- Pri Crea Get- Get- All
+ Attributes Job, nt- te- Printer Jobs Opera-
+ Vali- URI Job Attri- tions
+ date-Job (O) (O) butes
+
+ Operation attributes-OPTIONAL to be supplied by the sender
+
+ status-message O
+
+ compression O O
+
+ document-format R R O
+
+ document-name O O
+
+ document-natural- O O
+ language
+
+ ipp-attribute- R R R
+ fidelity
+
+ job-impressions O O O
+
+ job-k-octets O O O
+
+ job-media-sheets O O O
+
+ limit R
+
+ message
+
+ my-jobs R
+
+ requested- R R
+ attributes
+
+ which-jobs R
+
+ * "job-id" is REQUIRED only if used together with
+ "printer-uri" to identify the target job; otherwise, "job-
+ uri" is REQUIRED.
+
+
+
+
+
+
+Hastings & Manros Informational [Page 7]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Table 2. Summary of operation attributes for Job operations
+
+
+ Requests Responses
+
+ Operation Send- Send- Cancel Get- All
+ Attributes Document URI -Job Job- Opera-
+ (O) (O) Attri- tions
+ butes
+
+ Operation parameters--REQUIRED to be supplied by the sender
+
+ operation-id R R R R
+
+ status-code R
+
+ request-id R R R R R
+
+ version-number R R R R R
+
+ Operation attributes-REQUIRED to be supplied by the sender
+
+ attributes- R R R R R
+ charset
+
+ attributes- R R R R R
+ natural-language
+
+ document-uri R
+
+ job-id* R R R R
+
+ job-uri* R R R R
+
+ last-document R R
+
+ printer-uri R R R R
+
+ Operation attributes-RECOMMENDED to be supplied by the
+ sender
+
+ job-name
+
+ requesting-user- R R R R
+ name
+
+
+
+
+
+
+Hastings & Manros Informational [Page 8]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Job Operations
+
+ Requests Responses
+
+ Operation Attributes Send- Send- Cance Get- All
+ Document URI l-Job Job- Opera-
+ (O) (O) Attri- tions
+ butes
+
+ Operation attributes.OPTIONAL to be supplied by the sender
+
+ status-message O
+
+ compression O O
+
+ document-format R R
+
+ document-name O O
+
+ document-natural- O O
+ language
+
+ ipp-attribute-
+ fidelity
+
+ job-impressions
+
+ job-k-octets
+
+ job-media-sheets
+
+ limit
+
+ message O
+
+ my-jobs
+
+ requested-attributes R
+
+ which-jobs
+
+ * "job-id" is REQUIRED only if used together with "printer-
+ uri" to identify the target job; otherwise, "job-uri" is
+ REQUIRED.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 9]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.2 Suggested Operation Processing Steps for IPP Objects
+
+ This section suggests the steps and error checks that an IPP object
+ MAY perform when processing requests and returning responses. An IPP
+ object MAY perform some or all of the error checks. However, some
+ implementations MAY choose to be more forgiving than the error checks
+ shown here, in order to be able to accept requests from non-
+ conforming clients. Not performing all of these error checks is a
+ so-called "forgiving" implementation. On the other hand, clients
+ that successfully submit requests to IPP objects that do perform all
+ the error checks will be more likely to be able to interoperate with
+ other IPP object implementations. Thus an implementer of an IPP
+ object needs to decide whether to be a "forgiving" or a "strict"
+ implementation. Therefore, the error status codes returned may
+ differ between implementations. Consequentially, client SHOULD NOT
+ expect exactly the error code processing described in this section.
+
+ When an IPP object receives a request, the IPP object either accepts
+ or rejects the request. In order to determine whether or not to
+ accept or reject the request, the IPP object SHOULD execute the
+ following steps. The order of the steps may be rearranged and/or
+ combined, including making one or multiple passes over the request.
+
+ A client MUST supply requests that would pass all of the error checks
+ indicated here in order to be a conforming client. Therefore, a
+ client SHOULD supply requests that are conforming, in order to avoid
+ being rejected by some IPP object implementations and/or risking
+ different semantics by different implementations of forgiving
+ implementations. For example, a forgiving implementation that
+ accepts multiple occurrences of the same attribute, rather than
+ rejecting the request might use the first occurrences, while another
+ might use the last occurrence. Thus such a non-conforming client
+ would get different results from the two forgiving implementations.
+
+ In the following, processing continues step by step until a "RETURNS
+ the xxx status code ." statement is encountered. Error returns are
+ indicated by the verb: "REJECTS". Since clients have difficulty
+ getting the status code before sending all of the document data in a
+ Print-Job request, clients SHOULD use the Validate-Job operation
+ before sending large documents to be printed, in order to validate
+ whether the IPP Printer will accept the job or not.
+
+ It is assumed that security authentication and authorization has
+ already taken place at a lower layer.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 10]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.2.1 Suggested Operation Processing Steps for all Operations
+
+ This section is intended to apply to all operations. The next
+ section contains the additional steps for the Print-Job, Validate-
+ Job, Print-URI, Create-Job, Send-Document, and Send-URI operations
+ that create jobs, adds documents, and validates jobs.
+
+2.2.1.1 Validate version number
+
+ Every request and every response contains the "version-number"
+ attribute. The value of this attribute is the major and minor
+ version number of the syntax and semantics that the client and IPP
+ object is using, respectively. The "version-number" attribute
+ remains in a fixed position across all future versions so that all
+ clients and IPP object that support future versions can determine
+ which version is being used. The IPP object checks to see if the
+ major version number supplied in the request is supported. If not,
+ the Printer object REJECTS the request and RETURNS the 'server-
+ error-version-not-supported' status code in the response. The IPP
+ object returns in the "version-number" response attribute the major
+ and minor version for the error response. Thus the client can learn
+ at least one major and minor version that the IPP object supports.
+ The IPP object is encouraged to return the closest version number to
+ the one supplied by the client.
+
+ The checking of the minor version number is implementation dependent,
+ however if the client supplied minor version is explicitly supported,
+ the IPP object MUST respond using that identical minor version
+ number. If the requested minor version is not supported (the
+ requested minor version is either higher or lower) than a supported
+ minor version, the IPP object SHOULD return the closest supported
+ minor version.
+
+2.2.1.2 Validate operation identifier
+
+ The Printer object checks to see if the "operation-id" attribute
+ supplied by the client is supported as indicated in the Printer
+ object's "operations-supported" attribute. If not, the Printer
+ REJECTS the request and returns the 'server-error-operation-not-
+ supported' status code in the response.
+
+2.2.1.3 Validate the request identifier
+
+ The Printer object SHOULD NOT check to see if the "request-id"
+ attribute supplied by the client is in range: between 1 and 2**31 - 1
+ (inclusive), but copies all 32 bits.
+
+
+
+
+
+Hastings & Manros Informational [Page 11]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Note: The "version-number", "operation-id", and the "request-id"
+ parameters are in fixed octet positions in the IPP/1.0 encoding. The
+ "version-number" parameter will be the same fixed octet position in
+ all versions of the protocol. These fields are validated before
+ proceeding with the rest of the validation.
+
+2.2.1.4 Validate attribute group and attribute presence and order
+
+ The order of the following validation steps depends on
+ implementation.
+
+2.2.1.4.1 Validate the presence and order of attribute groups
+
+ Client requests and IPP object responses contain attribute groups
+ that Section 3 requires to be present and in a specified order. An
+ IPP object verifies that the attribute groups are present and in the
+ correct order in requests supplied by clients (attribute groups
+ without an * in the following tables).
+
+ If an IPP object receives a request with (1) required attribute
+ groups missing, or (2) the attributes groups are out of order, or (3)
+ the groups are repeated, the IPP object REJECTS the request and
+ RETURNS the 'client-error-bad-request' status code. For example, it
+ is an error for the Job Template Attributes group to occur before the
+ Operation Attributes group, for the Operation Attributes group to be
+ omitted, or for an attribute group to occur more than once, except in
+ the Get-Jobs response.
+
+ Since this kind of attribute group error is most likely to be an
+ error detected by a client developer rather than by a customer, the
+ IPP object NEED NOT return an indication of which attribute group was
+ in error in either the Unsupported Attributes group or the Status
+ Message. Also, the IPP object NEED NOT find all attribute group
+ errors before returning this error.
+
+2.2.1.4.2 Ignore unknown attribute groups in the expected position
+
+ Future attribute groups may be added to the specification at the end
+ of requests just before the Document Content and at the end of
+ response, except for the Get-Jobs response, where it maybe there or
+ before the first job attributes returned. If an IPP object receives
+ an unknown attribute group in these positions, it ignores the entire
+ group, rather than returning an error, since that group may be a new
+ group in a later minor version of the protocol that can be ignored.
+ (If the new attribute group cannot be ignored without confusing the
+ client, the major version number would have been increased in the
+
+
+
+
+
+Hastings & Manros Informational [Page 12]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ protocol document and in the request). If the unknown group occurs
+ in a different position, the IPP object REJECTS the request and
+ RETURNS the 'client-error-bad-request' status code.
+
+ Clients also ignore unknown attribute groups returned in a response.
+
+ Note: By validating that requests are in the proper form, IPP
+ objects force clients to use the proper form which, in turn,
+ increases the chances that customers will be able to use such clients
+ from multiple vendors with IPP objects from other vendors.
+
+2.2.1.4.3 Validate the presence of a single occurrence of required
+ Operation attributes
+
+ Client requests and IPP object responses contain Operation attributes
+ that [RFC2566] Section 3 requires to be present. Attributes within a
+ group may be in any order, except for the ordering of target,
+ charset, and natural languages attributes. These attributes MUST be
+ first, and MUST be supplied in the following order: charset, natural
+ language, and then target. An IPP object verifies that the attributes
+ that Section 4 requires to be supplied by the client have been
+ supplied in the request (attributes without an * in the following
+ tables). An asterisk (*) indicates groups and Operation attributes
+ that the client may omit in a request or an IPP object may omit in a
+ response.
+
+ If an IPP object receives a request with required attributes missing
+ or repeated from a group or in the wrong position, the behavior of
+ the IPP object is IMPLEMENTATION DEPENDENT. Some of the possible
+ implementations are:
+
+ 1.REJECTS the request and RETURNS the 'client-error-bad-request'
+ status code
+
+ 2.accepts the request and uses the first occurrence of the
+ attribute no matter where it is
+
+ 3.accepts the request and uses the last occurrence of the
+ attribute no matter where it is
+
+ 4.accept the request and assume some default value for the missing
+ attribute
+
+ Therefore, client MUST send conforming requests, if they want to
+ receive the same behavior from all IPP object implementations. For
+ example, it is an error for the "attributes-charset" or "attributes-
+ natural-language" attribute to be omitted in any operation request,
+ or for an Operation attribute to be supplied in a Job Template group
+
+
+
+Hastings & Manros Informational [Page 13]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ or a Job Template attribute to be supplied in an Operation Attribute
+ group in a create request. It is also an error to supply the
+ "attributes-charset" attribute twice.
+
+ Since these kinds of attribute errors are most likely to be detected
+ by a client developer rather than by a customer, the IPP object NEED
+ NOT return an indication of which attribute was in error in either
+ the Unsupported Attributes group or the Status Message. Also, the
+ IPP object NEED NOT find all attribute errors before returning this
+ error.
+
+ The following tables list all the attributes for all the operations
+ by attribute group in each request and each response. The order of
+ the groups is the order that the client supplies the groups as
+ specified in [RFC2566] Section 3. The order of the attributes within
+ a group is arbitrary, except as noted for some of the special
+ operation attributes (charset, natural language, and target). The
+ tables below use the following notation:
+
+ R indicates a REQUIRED attribute that an IPP object MUST support
+ O indicates an OPTIONAL attribute that an IPP object NEED NOT
+ support
+ * indicates that a client MAY omit the attribute in a request
+ and that an IPP object MAY omit the attribute in a
+ response. The absence of an * means that a client MUST
+ supply the attribute in a request and an IPP object MUST
+ supply the attribute in a response.
+
+ Operation Requests
+
+ The tables below show the attributes in their proper attribute groups
+ for operation requests:
+
+ Note: All operation requests contain "version-number", "operation-
+ id", and "request-id" parameters.
+
+ Print-Job Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+ requesting-user-name (R*)
+ job-name (R*)
+ ipp-attribute-fidelity (R*)
+ document-name (R*)
+ document-format (R*)
+ document-natural-language (O*)
+ compression (O*)
+
+
+
+Hastings & Manros Informational [Page 14]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ job-k-octets (O*)
+ job-impressions (O*)
+ job-media-sheets (O*)
+ Group 2: Job Template Attributes (R*)
+ <Job Template attributes> (O*)
+ (see [RFC2566] Section 4.2)
+ Group 3: Document Content (R)
+ <document content>
+
+ Validate-Job Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+ requesting-user-name (R*)
+ job-name (R*)
+ ipp-attribute-fidelity (R*)
+ document-name (R*)
+ document-format (R*)
+ document-natural-language (O*)
+ compression (O*)
+ job-k-octets (O*)
+ job-impressions (O*)
+ job-media-sheets (O*)
+ Group 2: Job Template Attributes (R*)
+ <Job Template attributes> (O*)
+ (see [RFC2566] Section 4.2)
+
+ Create-Job Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+ requesting-user-name (R*)
+ job-name (R*)
+ ipp-attribute-fidelity (R*)
+ job-k-octets (O*)
+ job-impressions (O*)
+ job-media-sheets (O*)
+ Group 2: Job Template Attributes (R*)
+ <Job Template attributes> (O*) (see
+ (see [RFC2566] Section 4.2)
+
+ Print-URI Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+
+
+
+Hastings & Manros Informational [Page 15]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ document-uri (R)
+ requesting-user-name (R*)
+ job-name (R*)
+ ipp-attribute-fidelity (R*)
+ document-name (R*)
+ document-format (R*)
+ document-natural-language (O*)
+ compression (O*)
+ job-k-octets (O*)
+ job-impressions (O*)
+ job-media-sheets (O*)
+ Group 2: Job Template Attributes (R*)
+ <Job Template attributes> (O*) (see
+ (see [RFC2566] Section 4.2)
+
+ Send-Document Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ (printer-uri & job-id) | job-uri (R)
+ last-document (R)
+ requesting-user-name (R*)
+ document-name (R*)
+ document-format (R*)
+ document-natural-language (O*)
+ compression (O*)
+ Group 2: Document Content (R*)
+ <document content>
+
+ Send-URI Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ (printer-uri & job-id) | job-uri (R)
+ last-document (R)
+ document-uri (R)
+ requesting-user-name (R*)
+ document-name (R*)
+ document-format (R*)
+ document-natural-language (O*)
+ compression (O*)
+
+
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 16]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Cancel-Job Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ (printer-uri & job-id) | job-uri (R)
+ requesting-user-name (R*)
+ message (O*)
+
+ Get-Printer-Attributes Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+ requesting-user-name (R*)
+ requested-attributes (R*)
+ document-format (R*)
+
+ Get-Job-Attributes Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ (printer-uri & job-id) | job-uri (R)
+ requesting-user-name (R*)
+ requested-attributes (R*)
+
+ Get-Jobs Request:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ printer-uri (R)
+ requesting-user-name (R*)
+ limit (R*)
+ requested-attributes (R*)
+ which-jobs (R*)
+ my-jobs (R*)
+
+
+ Operation Responses
+
+ The tables below show the response attributes in their proper
+ attribute groups for responses.
+
+ Note: All operation responses contain "version-number", "status-
+ code", and "request-id" parameters.
+
+ Print-Job Response:
+ Print-URI Response:
+ Create-Job Response:
+
+
+
+Hastings & Manros Informational [Page 17]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Send-Document Response:
+ Send-URI Response:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ status-message (O*)
+ Group 2: Unsupported Attributes (R*) (see Note 3)
+ <unsupported attributes> (R*)
+ Group 3: Job Object Attributes(R*) (see Note 2)
+ job-uri (R)
+ job-id (R)
+ job-state (R)
+ job-state-reasons (O*)
+ job-state-message (O*)
+ number-of-intervening-jobs (O*)
+
+ Validate-Job Response:
+ Cancel-Job Response:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ status-message (O*)
+ Group 2: Unsupported Attributes (R*) (see Note 3)
+ <unsupported attributes> (R*)
+
+ Note 2 - the Job Object Attributes and Printer Object Attributes are
+ returned only if the IPP object returns one of the success status
+ codes.
+
+ Note 3 - the Unsupported Attributes Group is present only if the
+ client included some Operation and/or Job Template attributes or
+ values that the Printer doesn't support whether a success or an error
+ return.
+
+ Get-Printer-Attributes Response:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ status-message (O*)
+ Group 2: Unsupported Attributes (R*) (see Note 4)
+ <unsupported attributes> (R*)
+ Group 3: Printer Object Attributes(R*) (see Note 2)
+ <requested attributes> (R*)
+
+ Note 4 - the Unsupported Attributes Group is present only if the
+ client included some Operation attributes that the Printer doesn't
+ support whether a success or an error return.
+
+
+
+
+Hastings & Manros Informational [Page 18]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Get-Job-Attributes Response:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ status-message (O*)
+ Group 2: Unsupported Attributes (R*) (see Note 4)
+ <unsupported attributes> (R*)
+ Group 3: Job Object Attributes(R*) (see Note 2)
+ <requested attributes> (R*)
+
+ Get-Jobs Response:
+ Group 1: Operation Attributes (R)
+ attributes-charset (R)
+ attributes-natural-language (R)
+ status-message (O*)
+ Group 2: Unsupported Attributes (R*) (see Note 4)
+ <unsupported attributes> (R*)
+ Group 3: Job Object Attributes(R*) (see Note 2, 5)
+ <requested attributes> (R*)
+
+ Note 5: for the Get-Jobs operation the response contains a separate
+ Job Object Attributes group 3 to N containing requested-attributes
+ for each job object in the response.
+
+2.2.1.5 Validate the values of the REQUIRED Operation attributes
+
+ An IPP object validates the values supplied by the client of the
+ REQUIRED Operation attribute that the IPP object MUST support. The
+ next section specifies the validation of the values of the OPTIONAL
+ Operation attributes that IPP objects MAY support.
+
+ The IPP object performs the following syntactic validation checks of
+ each Operation attribute value:
+
+ a)that the length of each Operation attribute value is correct for
+ the attribute syntax tag supplied by the client according to
+ [RFC2566] Section 4.1,
+
+ b)that the attribute syntax tag is correct for that Operation
+ attribute according to [RFC2566] Section 3,
+
+ c)that the value is in the range specified for that Operation
+ attribute according to [RFC2566] Section 3,
+
+ d)that multiple values are supplied by the client only for
+ operation attributes that are multi-valued, i.e., that are
+ 1setOf X according to [RFC2566] Section 3.
+
+
+
+
+Hastings & Manros Informational [Page 19]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ If any of these checks fail, the IPP object REJECTS the request and
+ RETURNS the 'client-error-bad-request' or the 'client-error-request-
+ value-too-long' status code. Since such an error is most likely to
+ be an error detected by a client developer, rather than by an end-
+ user, the IPP object NEED NOT return an indication of which attribute
+ had the error in either the Unsupported Attributes Group or the
+
+ Status Message. The description for each of these syntactic checks
+ is explicitly expressed in the first IF statement in the following
+ table.
+
+ In addition, the IPP object checks each Operation attribute value
+ against some Printer object attribute or some hard-coded value if
+ there is no "xxx-supported" Printer object attribute defined. If its
+ value is not among those supported or is not in the range supported,
+ then the IPP object REJECTS the request and RETURNS the error status
+ code indicated in the table by the second IF statement. If the value
+ of the Printer object's "xxx-supported" attribute is 'no-value'
+ (because the system administrator hasn't configured a value), the
+ check always fails.
+
+ attributes-charset (charset)
+
+ IF NOT a single non-empty 'charset' value, REJECT/RETURN 'client-
+ error-bad-request'.
+
+ IF the value length is greater than 63 octets, REJECT/RETURN '
+ client-error-request-value-too-long'.
+ IF NOT in the Printer object's "charset-supported" attribute,
+ REJECT/RETURN "client-error-charset-not-supported".
+
+
+ attributes-natural-language(naturalLanguage)
+
+ IF NOT a single non-empty 'naturalLanguage' value, REJECT/RETURN
+ 'client-error-bad-request'.
+ IF the value length is greater than 63 octets, REJECT/RETURN '
+ client-error-request-value-too-long'.
+ ACCEPT the request even if not a member of the set in the Printer
+ object's "generated-natural-language-supported" attribute. If
+ the supplied value is not a member of the Printer object's
+ "generated-natural-language-supported" attribute, use the
+ Printer object's "natural-language-configured" value.
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 20]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ requesting-user-name
+
+ IF NOT a single 'name' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF the IPP object can obtain a better authenticated name, use it
+ instead.
+
+
+ job-name(name)
+
+ IF NOT a single 'name' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT supplied by the client, the Printer object creates a name
+ from the document-name or document-uri.
+
+
+ document-name (name)
+
+ IF NOT a single 'name' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+
+
+ ipp-attribute-fidelity (boolean)
+
+ IF NEITHER a single 'true' NOR a single 'false' 'boolean' value,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF the value length is NOT equal to 1 octet, REJECT/RETURN '
+ client-error-request-value-too-long'
+ IF NOT supplied by the client, the IPP object assumes the value
+ 'false'.
+
+
+ document-format (mimeMediaType)
+
+ IF NOT a single non-empty 'mimeMediaType' value, REJECT/RETURN
+ 'client-error-bad-request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT in the Printer object's "document-format-supported"
+ attribute, REJECT/RETURN 'client-error-document-format-not-
+ supported'
+
+
+
+
+Hastings & Manros Informational [Page 21]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ IF NOT supplied by the client, the IPP object assumes the value of
+ the Printer object's "document-format-default" attribute.
+
+
+ document-uri (uri)
+
+ IF NOT a single non-empty 'uri' value, REJECT/RETURN 'client-
+ error-bad-request'.
+ IF the value length is greater than 1023 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF the URI syntax is not valid, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF scheme is NOT in the Printer object's "reference-uri-schemes-
+ supported" attribute, REJECT/RETURN 'client-error-uri-scheme-
+ not-supported'.
+ The Printer object MAY check to see if the document exists and is
+ accessible. If the document is not found or is not accessible,
+ REJECT/RETURN 'client-error-not found'.
+
+
+ last-document (boolean)
+
+ IF NEITHER a single 'true' NOR a single 'false' 'boolean' value,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF the value length is NOT equal to 1 octet, REJECT/RETURN '
+ client-error-request-value-too-long'
+
+
+ job-id (integer(1:MAX))
+
+ IF NOT an single 'integer' value equal to 4 octets AND in the
+ range 1 to MAX, REJECT/RETURN 'client-error-bad-request'.
+
+ IF NOT a job-id of an existing Job object, REJECT/RETURN 'client-
+ error-not-found' or 'client-error-gone' status code, if keep
+ track of recently deleted jobs.
+
+
+ requested-attributes (1setOf keyword)
+
+ IF NOT one or more 'keyword' values, REJECT/RETURN 'client-error-
+ bad-request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ Ignore unsupported values which are the keyword names of
+ unsupported attributes. Don't bother to copy such requested
+ (unsupported) attributes to the Unsupported Attribute response
+ group since the response will not return them.
+
+
+
+Hastings & Manros Informational [Page 22]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ which-jobs (type2 keyword)
+
+ IF NOT a single 'keyword' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NEITHER 'completed' NOR 'not-completed', copy the attribute and
+ the unsupported value to the Unsupported Attributes response
+ group and REJECT/RETURN 'client-error-attributes-or-values-
+ not-supported'.
+ Note: a Printer still supports the 'completed' value even if it
+ keeps no completed/canceled/aborted jobs: by returning no jobs
+ when so queried.
+ IF NOT supplied by the client, the IPP object assumes the 'not-
+ completed' value.
+
+
+ my-jobs (boolean)
+
+ IF NEITHER a single 'true' NOR a single 'false' 'boolean' value,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF the value length is NOT equal to 1 octet, REJECT/RETURN '
+ client-error-request-value-too-long'
+ IF NOT supplied by the client, the IPP object assumes the 'false'
+ value.
+
+
+ limit (integer(1:MAX))
+
+ IF NOT a single 'integer' value equal to 4 octets AND in the range
+ 1 to MAX, REJECT/RETURN 'client-error-bad-request'.
+ IF NOT supplied by the client, the IPP object returns all jobs, no
+ matter how many.
+
+2.2.1.6 Validate the values of the OPTIONAL Operation attributes
+
+ OPTIONAL Operation attributes are those that an IPP object MAY or MAY
+ NOT support. An IPP object validates the values of the OPTIONAL
+ attributes supplied by the client. The IPP object performs the same
+ syntactic validation checks for each OPTIONAL attribute value as in
+ Section 2.2.1.5. As in Section 2.2.1.5, if any fail, the IPP object
+ REJECTS the request and RETURNS the 'client-error-bad-request' or the
+ 'client-error-request-value-too-long' status code.
+
+ In addition, the IPP object checks each Operation attribute value
+ against some Printer attribute or some hard-coded value if there is
+ no "xxx-supported" Printer attribute defined. If its value is not
+ among those supported or is not in the range supported, then the IPP
+
+
+
+Hastings & Manros Informational [Page 23]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ object REJECTS the request and RETURNS the error status code
+ indicated in the table. If the value of the Printer object's "xxx-
+ supported" attribute is 'no-value' (because the system administrator
+ hasn't configured a value), the check always fails.
+
+ If the IPP object doesn't recognize/support an attribute, the IPP
+ object treats the attribute as an unknown or unsupported attribute
+ (see the last row in the table below).
+
+ document-natural-language (naturalLanguage)
+
+ IF NOT a single non-empty 'naturalLanguage' value, REJECT/RETURN '
+ client-error-bad-request'.
+ IF the value length is greater than 63 octets, REJECT/RETURN '
+ client-error-request-value-too-long'.
+ IF NOT a value that the Printer object supports in document
+ formats, (no corresponding "xxx-supported" Printer attribute),
+ REJECT/RETURN 'client-error-natural-language-not-supported'.
+
+
+ compression (type3 keyword)
+
+ IF NOT a single 'keyword' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN '
+ client-error-request-value-too-long'.
+ IF NOT in the Printer object's "compression-supported" attribute,
+ copy the attribute and the unsupported value to the Unsupported
+ Attributes response group and REJECT/RETURN 'client-error-
+ attributes-or-values-not-supported'.
+
+
+ job-k-octets (integer(0:MAX))
+
+ IF NOT a single 'integer' value equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the range of the Printer object's "job-k-octets-
+ supported" attribute, copy the attribute and the unsupported
+ value to the Unsupported Attributes response group and
+ REJECT/RETURN 'client-error-attributes-or-values-not-
+ supported'.
+
+
+ job-impressions (integer(0:MAX))
+
+ IF NOT a single 'integer' value equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+
+
+
+
+Hastings & Manros Informational [Page 24]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ IF NOT in the range of the Printer object's "job-impressions-
+ supported" attribute, copy the attribute and the unsupported
+ value to the Unsupported Attributes response group and
+ REJECT/RETURN 'client-error-attributes-or-values-not-
+ supported'.
+
+
+ job-media-sheets (integer(0:MAX))
+
+ IF NOT a single 'integer' value equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the range of the Printer object's "job-media-sheets-
+ supported" attribute, copy the attribute and the unsupported
+ value to the Unsupported Attributes response group and
+ REJECT/RETURN 'client-error-attributes-or-values-not-
+ supported'.
+
+
+ message (text(127))
+
+ IF NOT a single 'text' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 127 octets,
+ REJECT/RETURN 'client-error-request-value-too-long'.
+
+
+ unknown or unsupported attribute
+
+ IF the attribute syntax supplied by the client is supported but
+ the length is not legal for that attribute syntax,
+ REJECT/RETURN 'client-error-request-value-too-long'.
+ ELSE copy the attribute and value to the Unsupported Attributes
+ response group and change the attribute value to the "out-of-
+ band" 'unsupported' value, but otherwise ignore the attribute.
+
+ Note: Future Operation attributes may be added to the protocol
+ specification that may occur anywhere in the specified group.
+ When the operation is otherwise successful, the IPP object returns
+ the 'successful-ok-ignored-or-substituted-attributes' status code.
+ Ignoring unsupported Operation attributes in all operations is
+ analogous to the handling of unsupported Job Template attributes
+ in the create and Validate-Job operations when the client supplies
+ the "ipp-attribute-fidelity" Operation attribute with the 'false'
+ value. This last rule is so that we can add OPTIONAL Operation
+ attributes to future versions of IPP so that older clients can
+ inter-work with new IPP objects and newer clients can inter-work
+ with older IPP objects. (If the new attribute cannot be ignored
+ without performing unexpectedly, the major version number would
+
+
+
+Hastings & Manros Informational [Page 25]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ have been increased in the protocol document and in the request).
+ This rule for Operation attributes is independent of the value of
+ the "ipp-attribute-fidelity" attribute. For example, if an IPP
+ object doesn't support the OPTIONAL "job-k-octets" attribute', the
+ IPP object treats "job-k-octets" as an unknown attribute and only
+ checks the length for the 'integer' attribute syntax supplied by
+ the client. If it is not four octets, the IPP object REJECTS the
+ request and RETURNS the 'client-error-bad-request' status code,
+ else the IPP object copies the attribute to the Unsupported
+ Attribute response group, setting the value to the "out-of-band" '
+ unsupported' value, but otherwise ignores the attribute.
+
+2.2.2 Suggested Additional Processing Steps for Operations that
+ Create/Validate Jobs and Add Documents
+
+ This section in combination with the previous section recommends the
+ processing steps for the Print-Job, Validate-Job, Print-URI, Create-
+ Job, Send-Document, and Send-URI operations that IPP objects SHOULD
+ use. These are the operations that create jobs, validate a Print-Job
+ request, and add documents to a job.
+
+2.2.2.1 Default "ipp-attribute-fidelity" if not supplied
+
+ The Printer object checks to see if the client supplied an "ipp-
+ attribute-fidelity" Operation attribute. If the attribute is not
+ supplied by the client, the IPP object assumes that the value is
+ 'false'.
+
+2.2.2.2 Check that the Printer object is accepting jobs
+
+ If the value of the Printer object's "printer-is-accepting-jobs" is
+ 'false', the Printer object REJECTS the request and RETURNS the
+ 'server-error-not-accepting-jobs' status code.
+
+2.2.2.3 Validate the values of the Job Template attributes
+
+ An IPP object validates the values of all Job Template attribute
+ supplied by the client. The IPP object performs the analogous
+ syntactic validation checks of each Job Template attribute value that
+ it performs for Operation attributes (see Section 2.2.1.5.):
+
+ a)that the length of each value is correct for the attribute
+ syntax tag supplied by the client according to [RFC2566] Section
+ 4.1.
+
+ b)that the attribute syntax tag is correct for that attribute
+ according to [RFC2566] Sections 4.2 to 4.4.
+
+
+
+
+Hastings & Manros Informational [Page 26]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ c)that multiple values are supplied only for multi-valued
+ attributes, i.e., that are 1setOf X according to [RFC2566]
+ Sections 4.2 to 4.4.
+
+ As in Section 2.2.1.5, if any of these syntactic checks fail, the IPP
+ object REJECTS the request and RETURNS the 'client-error-bad-request'
+ or 'client-error-request-value-too-long' status code as appropriate,
+ independent of the value of the "ipp-attribute-fidelity". Since such
+ an error is most likely to be an error detected by a client
+ developer, rather than by an end-user, the IPP object NEED NOT return
+ an indication of which attribute had the error in either the
+ Unsupported Attributes Group or the Status Message. The description
+ for each of these syntactic checks is explicitly expressed in the
+ first IF statement in the following table.
+
+ Each Job Template attribute MUST occur no more than once. If an IPP
+ Printer receives a create request with multiple occurrences of a Job
+ Template attribute, it MAY:
+
+ 1.reject the operation and return the 'client-error-bad syntax'
+ error status code
+
+ 2.accept the operation and use the first occurrence of the
+ attribute
+
+ 3.accept the operation and use the last occurrence of the
+ attribute
+
+ depending on implementation. Therefore, clients MUST NOT supply
+ multiple occurrences of the same Job Template attribute in the Job
+ Attributes group in the request.
+
+2.2.3 Algorithm for job validation
+
+ The process of validating a Job-Template attribute "xxx" against a
+ Printer attribute "xxx-supported" can use the following validation
+ algorithm (see section 3.2.1.2 in [RFC2566]).
+
+ To validate the value U of Job-Template attribute "xxx" against the
+ value V of Printer "xxx-supported", perform the following algorithm:
+
+ 1.If U is multi-valued, validate each value X of U by performing
+ the algorithm in Table 3 with each value X. Each validation is
+ separate from the standpoint of returning unsupported values.
+
+ Example: If U is "finishings" that the client supplies with
+ 'staple', 'bind' values, then X takes on the successive values:
+ 'staple', then 'bind'
+
+
+
+Hastings & Manros Informational [Page 27]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ 2.If V is multi-valued, validate X against each Z of V by
+ performing the algorithm in Table 3 with each value Z. If a
+ value Z validates, the validation for the attribute value X
+ succeeds. If it fails, the algorithm is applied to the next
+ value Z of V. If there are no more values Z of V, validation
+ fails.
+
+ Example: If V is "sides-supported" with values: 'one-sided',
+ 'two-sided-long', and 'two-sided-short', then Z takes on the
+ successive values: 'one-sided', 'two-sided-long', and
+ 'two-sided-short'. If the client supplies "sides" with 'two-
+ sided-long', the first comparison fails ('one-sided' is not
+ equal to 'two-sided-long'), the second comparison succeeds
+ ('two-sided-long' is equal to 'two-sided-long"), and the third
+ comparison ('two-sided-short' with 'two-sided-long') is not even
+ performed.
+
+ 3.If both U and V are single-valued, let X be U and Z be V and use
+ the validation rules in Table 3.
+
+ Table 3 - Rules for validating single values X against Z
+
+ attribute attribute validated if:
+ syntax of X syntax of Z
+
+ integer rangeOfInteger X is within the range of
+ Z
+
+ uri uriScheme the uri scheme in X is
+ equal to Z
+
+ any boolean the value of Z is TRUE
+
+ any any X and Z are of the same
+ type and are equal.
+
+ If the value of the Printer object's "xxx-supported" attribute is '
+ no-value' (because the system administrator hasn't configured a
+ value), the check always fails. If the check fails, the IPP object
+ copies the attribute to the Unsupported Attributes response group
+ with its unsupported value. If the attribute contains more than one
+ value, each value is checked and each unsupported value is separately
+ copied, while supported values are not copied. If an IPP object
+ doesn't recognize/support a Job Template attribute, i.e., there is no
+ corresponding Printer object "xxx-supported" attribute, the IPP
+ object treats the attribute as an unknown or unsupported attribute
+ (see the last row in the table below).
+
+
+
+
+Hastings & Manros Informational [Page 28]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ If some Job Template attributes are supported for some document
+ formats and not for others or the values are different for different
+ document formats, the IPP object SHOULD take that into account in
+ this validation using the value of the "document-format" supplied by
+ the client (or defaulted to the value of the Printer's "document-
+ format-default" attribute, if not supplied by the client). For
+ example, if "number-up" is supported for the 'text/plain' document
+ format, but not for the 'application/postscript' document format, the
+ check SHOULD (though it NEED NOT) depend on the value of the
+ "document-format" operation attribute. See "document-format" in
+ [RFC2566] section 3.2.1.1 and 3.2.5.1.
+
+ Note: whether the request is accepted or rejected is determined by
+ the value of the "ipp-attribute-fidelity" attribute in a subsequent
+ step, so that all Job Template attribute supplied are examined and
+ all unsupported attributes and/or values are copied to the
+ Unsupported Attributes response group.
+
+ job-priority (integer(1:100))
+
+ IF NOT a single 'integer' value with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT supplied by the client, use the value of the Printer
+ object's "job-priority-default" attribute at job submission
+ time.
+ IF NOT in the range 1 to 100, inclusive, copy the attribute and
+ the unsupported value to the Unsupported Attributes response
+ group.
+ Map the value to the nearest supported value in the range 1:100 as
+ specified by the number of discrete values indicated by the
+ value of the Printer's "job-priority-supported" attribute. See
+ the formula in [RFC2566] Section 4.2.1.
+
+ job-hold-until (type3 keyword | name)
+
+ IF NOT a single 'keyword' or 'name' value, REJECT/RETURN 'client-
+ error-bad-request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT supplied by the client, use the value of the Printer
+ object's "job-hold-until" attribute at job submission time.
+ IF NOT in the Printer object's "job-hold-until-supported"
+ attribute, copy the attribute and the unsupported value to the
+ Unsupported Attributes response group.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 29]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ job-sheets (type3 keyword | name)
+
+ IF NOT a single 'keyword' or 'name' value, REJECT/RETURN 'client-
+ error-bad-request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT in the Printer object's "job-sheets-supported" attribute,
+ copy the attribute and the unsupported value to the Unsupported
+ Attributes response group.
+
+ multiple-document-handling (type2 keyword)
+
+ IF NOT a single 'keyword' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT in the Printer object's "multiple-document-handling-
+ supported" attribute, copy the attribute and the unsupported
+ value to the Unsupported Attributes response group.
+
+ copies (integer(1:MAX))
+
+ IF NOT a single 'integer' value with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in range of the Printer object's "copies-supported"
+ attribute copy the attribute and the unsupported value to the
+ Unsupported
+ Attributes response group.
+
+ finishings (1setOf type2 enum)
+
+ IF NOT an 'enum' value(s) each with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the Printer object's "finishings-supported" attribute,
+ copy the attribute and the unsupported value(s), but not any
+ supported values, to the Unsupported Attributes response group.
+
+ page-ranges (1setOf rangeOfInteger(1:MAX))
+
+ IF NOT a 'rangeOfInteger' value(s) each with a length equal to 8
+ octets, REJECT/RETURN 'client-error-bad-request'.
+ IF first value is greater than second value in any range, the
+ ranges are not in ascending order, or ranges overlap,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF the value of the Printer object's "page-ranges-supported"
+ attribute is 'false', copy the attribute to the Unsupported
+ Attributes response group and set the value to the "out-of-
+ band" 'unsupported' value.
+
+
+
+Hastings & Manros Informational [Page 30]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ sides (type2 keyword)
+
+ IF NOT a single 'keyword' value, REJECT/RETURN 'client-error-bad-
+ request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT in the Printer object's "sides-supported" attribute, copy
+ the attribute and the unsupported value to the Unsupported
+ Attributes response group.
+
+ number-up (integer(1:MAX))
+
+ IF NOT a single 'integer' value with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT a value or in the range of one of the values of the Printer
+ object's "number-up-supported" attribute, copy the attribute
+ and value to the Unsupported Attribute response group.
+
+ orientation-requested (type2 enum)
+
+ IF NOT a single 'enum' value with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the Printer object's "orientation-requested-supported"
+ attribute, copy the attribute and the unsupported value to the
+ Unsupported Attributes response group.
+
+ media (type3 keyword | name)
+
+ IF NOT a single 'keyword' or 'name' value, REJECT/RETURN 'client-
+ error-bad-request'.
+ IF the value length is greater than 255 octets, REJECT/RETURN
+ 'client-error-request-value-too-long'.
+ IF NOT in the Printer object's "media-supported" attribute, copy
+ the attribute and the unsupported value to the Unsupported
+ Attributes response group.
+
+ printer-resolution (resolution)
+
+ IF NOT a single 'resolution' value with a length equal to 9
+ octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the Printer object's "printer-resolution-supported"
+ attribute, copy the attribute and the unsupported value to the
+ Unsupported Attributes response group.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 31]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ print-quality (type2 enum)
+
+ IF NOT a single 'enum' value with a length equal to 4 octets,
+ REJECT/RETURN 'client-error-bad-request'.
+ IF NOT in the Printer object's "print-quality-supported"
+ attribute, copy the attribute and the unsupported value to the
+ Unsupported Attributes response group.
+
+ unknown or unsupported attribute (i.e., there is no corresponding
+ Printer object "xxx-supported" attribute)
+
+ IF the attribute syntax supplied by the client is supported but
+ the length is not legal for that attribute syntax,
+ REJECT/RETURN 'client-error-bad-request' if the length of the
+ attribute syntax is fixed or 'client-error-request-value-too-
+ long' if the length of the attribute syntax is variable.
+ ELSE copy the attribute and value to the Unsupported Attributes
+ response group and change the attribute value to the "out-of-
+ band" 'unsupported' value. Any remaining Job Template
+ Attributes are either unknown or unsupported Job Template
+ attributes and are validated algorithmically according to their
+ attribute syntax for proper length (see below).
+
+ If the attribute syntax is supported AND the length check
+ fails, the IPP object REJECTS the request and RETURNS the '
+ client-error-bad-request' if the length of the attribute syntax
+ is fixed or the 'client-error-request-value-too-long' status
+ code if the length of the attribute syntax is variable.
+ Otherwise, the IPP object copies the unsupported Job Template
+ attribute to the Unsupported Attributes response group and
+ changes the attribute value to the "out-of-band" 'unsupported'
+ value. The following table shows the length checks for all
+ attribute syntaxes. In the following table: "<=" means less
+ than or equal, "=" means equal to:
+
+ Name Octet length check for read-write attributes
+ ----------- --------------------------------------------
+ 'textWithLanguage <= 1023 AND 'naturalLanguage' <= 63
+ 'textWithoutLanguage' <= 1023
+ 'nameWithLanguage' <= 255 AND 'naturalLanguage' <= 63
+ 'nameWithoutLanguage' <= 255
+ 'keyword' <= 255
+ 'enum' = 4
+ 'uri' <= 1023
+ 'uriScheme' <= 63
+ 'charset' <= 63
+ 'naturalLanguage' <= 63
+ 'mimeMediaType' <= 255
+
+
+
+Hastings & Manros Informational [Page 32]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ 'octetString' <= 1023
+ 'boolean' = 1
+ 'integer' = 4
+ 'rangeOfInteger' = 8
+ 'dateTime' = 11
+ 'resolution' = 9
+ '1setOf X'
+
+2.2.3.1 Check for conflicting Job Template attributes values
+
+ Once all the Operation and Job Template attributes have been checked
+ individually, the Printer object SHOULD check for any conflicting
+ values among all the supported values supplied by the client. For
+ example, a Printer object might be able to staple and to print on
+ transparencies, however due to physical stapling constraints, the
+ Printer object might not be able to staple transparencies. The IPP
+ object copies the supported attributes and their conflicting
+ attribute values to the Unsupported Attributes response group. The
+ Printer object only copies over those attributes that the Printer
+ object either ignores or substitutes in order to resolve the
+ conflict, and it returns the original values which were supplied by
+ the client. For example suppose the client supplies "finishings"
+ equals 'staple' and "media" equals 'transparency', but the Printer
+ object does not support stapling transparencies. If the Printer
+ chooses to ignore the stapling request in order to resolve the
+ conflict, the Printer objects returns "finishings" equal to 'staple'
+ in the Unsupported Attributes response group. If any attributes are
+ multi-valued, only the conflicting values of the attributes are
+ copied.
+
+ Note: The decisions made to resolve the conflict (if there is a
+ choice) is implementation dependent.
+
+2.2.3.2 Decide whether to REJECT the request
+
+ If there were any unsupported Job Template attributes or
+ unsupported/conflicting Job Template attribute values and the client
+ supplied the "ipp-attribute-fidelity" attribute with the 'true'
+ value, the Printer object REJECTS the request and return the status
+ code:
+
+ (1) 'client-error-conflicting-attributes' status code, if there
+ were any conflicts between attributes supplied by the client.
+ (2) 'client-error-attributes-or-values-not-supported' status code,
+ otherwise.
+
+
+
+
+
+
+Hastings & Manros Informational [Page 33]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Note: Unsupported Operation attributes or values that are returned
+ do not affect the status returned in this step. If the unsupported
+ Operation attribute was a serious error, the above already rejected
+ the request in a previous step. If control gets to this step with
+ unsupported Operation attributes being returned, they are not serious
+ errors.
+
+2.2.3.3 For the Validate-Job operation, RETURN one of the success
+ status codes
+
+ If the requested operation is the Validate-Job operation, the Printer
+ object returns:
+
+ (1) the "successful-ok" status code, if there are no unsupported
+ or conflicting Job Template attributes or values.
+ (2) the "successful-ok-conflicting-attributes, if there are any
+ conflicting Job Template attribute or values.
+ (3) the "successful-ok-ignored-or-substituted-attributes, if there
+ are only unsupported Job Template attributes or values.
+
+ Note: Unsupported Operation attributes or values that are returned
+ do not affect the status returned in this step. If the unsupported
+ Operation attribute was a serious error, the above already rejected
+ the request in a previous step. If control gets to this step with
+ unsupported Operation attributes being returned, they are not serious
+ errors.
+
+2.2.3.4 Create the Job object with attributes to support
+
+ If "ipp-attribute-fidelity" is set to 'false' (or it was not supplied
+ by the client), the Printer object:
+
+ (1) creates a Job object, assigns a unique value to the job's
+ "job-uri" and "job-id" attributes, and initializes all of the
+ job's other supported Job Description attributes.
+ (2) removes all unsupported attributes from the Job object.
+ (3) for each unsupported value, removes either the unsupported
+ value or substitutes the unsupported attribute value with some
+ supported value. If an attribute has no values after removing
+ unsupported values from it, the attribute is removed from the
+ Job object (so that the normal default behavior at job
+ processing time will take place for that attribute).
+ (4) for each conflicting value, removes either the conflicting
+ value or substitutes the conflicting attribute value with some
+ other supported value. If an attribute has no values after
+ removing conflicting values from it, the attribute is removed
+ from the Job object (so that the normal default behavior at
+ job processing time will take place for that attribute).
+
+
+
+Hastings & Manros Informational [Page 34]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ If there were no attributes or values flagged as unsupported, or the
+ value of 'ipp-attribute-fidelity" was 'false', the Printer object is
+ able to accept the create request and create a new Job object. If
+ the "ipp-attribute-fidelity" attribute is set to 'true', the Job
+ Template attributes that populate the new Job object are necessarily
+ all the Job Template attributes supplied in the create request. If
+ the "ipp-attribute-fidelity" attribute is set to 'false', the Job
+ Template attributes that populate the new Job object are all the
+ client supplied Job Template attributes that are supported or that
+ have value substitution. Thus, some of the requested Job Template
+ attributes may not appear in the Job object because the Printer
+ object did not support those attributes. The attributes that
+ populate the Job object are persistently stored with the Job object
+ for that Job. A Get-Job-Attributes operation on that Job object will
+ return only those attributes that are persistently stored with the
+ Job object.
+
+ Note: All Job Template attributes that are persistently stored with
+ the Job object are intended to be "override values"; that is, they
+ that take precedence over whatever other embedded instructions might
+ be in the document data itself. However, it is not possible for all
+ Printer objects to realize the semantics of "override". End users
+ may query the Printer's "pdl-override-supported" attribute to
+ determine if the Printer either attempts or does not attempt to
+ override document data instructions with IPP attributes.
+
+ There are some cases, where a Printer supports a Job Template
+ attribute and has an associated default value set for that attribute.
+ In the case where a client does not supply the corresponding
+ attribute, the Printer does not use its default values to populate
+ Job attributes when creating the new Job object; only Job Template
+ attributes actually in the create request are used to populate the
+ Job object. The Printer's default values are only used later at Job
+ processing time if no other IPP attribute or instruction embedded in
+ the document data is present.
+
+ Note: If the default values associated with Job Template attributes
+ that the client did not supply were to be used to populate the Job
+ object, then these values would become "override values" rather than
+ defaults. If the Printer supports the 'attempted' value of the
+ "pdl-override-supported" attribute, then these override values could
+ replace values specified within the document data. This is not the
+ intent of the default value mechanism. A default value for an
+ attribute is used only if the create request did not specify that
+ attribute (or it was ignored when allowed by "ipp-attribute-fidelity"
+ being 'false') and no value was provided within the content of the
+ document data.
+
+
+
+
+Hastings & Manros Informational [Page 35]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ If the client does not supply a value for some Job Template
+ attribute, and the Printer does not support that attribute, as far as
+ IPP is concerned, the result of processing that Job (with respect to
+ the missing attribute) is undefined.
+
+2.2.3.5 Return one of the success status codes
+
+ Once the Job object has been created, the Printer object accepts the
+ request and returns to the client:
+
+ (1) the 'successful-ok' status code, if there are no unsupported
+ or conflicting Job Template attributes or values.
+ (2) the 'successful-ok-conflicting-attributes' status code, if
+ there are any conflicting Job Template attribute or values.
+ (3) the 'successful-ok-ignored-or-substituted-attributes' status
+ code, if there are only unsupported Job Template attributes or
+ values.
+
+ Note: Unsupported Operation attributes or values that are returned
+ do not affect the status returned in this step. If the unsupported
+ Operation attribute was a serious error, the above already rejected
+ the request in a previous step. If control gets to this step with
+ unsupported Operation attributes being returned, they are not serious
+ errors.
+
+ The Printer object also returns Job status attributes that indicate
+ the initial state of the Job ('pending', 'pending-held', '
+ processing', etc.), etc. See Print-Job Response, [RFC2566] section
+ 3.2.1.2.
+
+2.2.3.6 Accept appended Document Content
+
+ The Printer object accepts the appended Document Content data and
+ either starts it printing, or spools it for later processing.
+
+2.2.3.7 Scheduling and Starting to Process the Job
+
+ The Printer object uses its own configuration and implementation
+ specific algorithms for scheduling the Job in the correct processing
+ order. Once the Printer object begins processing the Job, the
+ Printer changes the Job's state to 'processing'. If the Printer
+ object supports PDL override (the "pdl-override-supported" attribute
+ set to 'attempted'), the implementation does its best to see that IPP
+ attributes take precedence over embedded instructions in the document
+ data.
+
+
+
+
+
+
+Hastings & Manros Informational [Page 36]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.2.3.8 Completing the Job
+
+ The Printer object continues to process the Job until it can move the
+ Job into the 'completed' state. If an Cancel-Job operation is
+ received, the implementation eventually moves the Job into the '
+ canceled' state. If the system encounters errors during processing
+ that do not allow it to progress the Job into a completed state, the
+ implementation halts all processing, cleans up any resources, and
+ moves the Job into the 'aborted' state.
+
+2.2.3.9 Destroying the Job after completion
+
+ Once the Job moves to the 'completed', 'aborted', or 'canceled'
+ state, it is an implementation decision as to when to destroy the Job
+ object and release all associated resources. Once the Job has been
+ destroyed, the Printer would return either the "client-error-not-
+ found" or "client-error-gone" status codes for operations directed at
+ that Job.
+
+ Note: the Printer object SHOULD NOT re-use a "job-uri" or "job-id"
+ value for a sufficiently long time after a job has been destroyed, so
+ that stale references kept by clients are less likely to access the
+ wrong (newer) job.
+
+2.2.3.10 Interaction with "ipp-attribute-fidelity"
+
+ Some Printer object implementations may support "ipp-attribute-
+ fidelity" set to 'true' and "pdl-override-supported" set to '
+ attempted' and yet still not be able to realize exactly what the
+ client specifies in the create request. This is due to legacy
+ decisions and assumptions that have been made about the role of job
+ instructions embedded within the document data and external job
+ instructions that accompany the document data and how to handle
+ conflicts between such instructions. The inability to be 100%
+ precise about how a given implementation will behave is also
+ compounded by the fact that the two special attributes, "ipp-
+ attribute-fidelity" and "pdl-override-supported", apply to the whole
+ job rather than specific values for each attribute. For example, some
+ implementations may be able to override almost all Job Template
+ attributes except for "number-up".
+
+2.3 Status codes returned by operation
+
+ This section lists all status codes once in the first operation
+ (Print-Job). Then it lists the status codes that are different or
+ specialized for subsequent operations under each operation.
+
+
+
+
+
+Hastings & Manros Informational [Page 37]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.3.1 Printer Operations
+
+2.3.1.1 Print-Job
+
+ The Printer object MUST return one of the following "status-code"
+ values for the indicated reason. Whether all of the document data
+ has been accepted or not before returning the success or error
+ response depends on implementation. See Section 14 for a more
+ complete description of each status code.
+
+ For the following success status codes, the Job object has been
+ created and the "job-id", and "job-uri" assigned and returned in the
+ response:
+
+ successful-ok: no request attributes were substituted or ignored.
+ successful-ok-ignored-or-substituted-attributes: some supplied
+ (1) attributes were ignored or (2) unsupported attribute
+ syntaxes or values were substituted with supported values or
+ were ignored. Unsupported attributes, attribute syntaxes, or
+ values MUST be returned in the Unsupported Attributes group of
+ the response.
+ successful-ok-conflicting-attributes: some supplied attribute
+ values conflicted with the values of other supplied attributes
+ and were either substituted or ignored. Attributes or values
+ which conflict with other attributes and have been substituted
+ or ignored MUST be returned in the Unsupported Attributes group
+ of the response as supplied by the client.
+
+ [RFC2566] section 3.1.6 Operation Status Codes and Messages states:
+
+ If the Printer object supports the "status-message" operation
+ attribute, it SHOULD use the REQUIRED 'utf-8' charset to return
+ a status message for the following error status codes (see
+ section 14): 'client-error-bad-request', 'client-error-
+ charset-not-supported', 'server-error-internal-error', '
+ server-error-operation-not-supported', and 'server-error-
+ version-not-supported'. In this case, it MUST set the value of
+ the "attributes-charset" operation attribute to 'utf-8' in the
+ error response.
+
+ For the following error status codes, no job is created and no "job-
+ id" or "job-uri" is returned:
+
+ client-error-bad-request: The request syntax does not conform to
+ the specification.
+
+
+
+
+
+
+Hastings & Manros Informational [Page 38]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ client-error-forbidden: The request is being refused for
+ authorization or authentication reasons. The implementation
+ security policy is to not reveal whether the failure is one of
+ authentication or authorization.
+ client-error-not-authenticated: Either the request requires
+ authentication information to be supplied or the authentication
+ information is not sufficient for authorization.
+ client-error-not-authorized: The requester is not authorized to
+ perform the request on the target object.
+ client-error-not-possible: The request cannot be carried out
+ because of the state of the system. See also 'server-error-
+ not-accepting-jobs' status code which MUST take precedence if
+ the Printer object's "printer-accepting-jobs" attribute is '
+ false'.
+ client-error-timeout: not applicable.
+ client-error-not-found: the target object does not exist.
+ client-error-gone: the target object no longer exists and no
+ forwarding address is known.
+ client-error-request-entity-too-large: the size of the request
+ and/or print data exceeds the capacity of the IPP Printer to
+ process it.
+ client-error-request-value-too-long: the size of request variable
+ length attribute values, such as 'text' and 'name' attribute
+ syntaxes, exceed the maximum length specified in [RFC2566] for
+ the attribute and MUST be returned in the Unsupported
+ Attributes Group.
+ client-error-document-format-not-supported: the document format
+ supplied is not supported. The "document-format" attribute
+ with the unsupported value MUST be returned in the Unsupported
+ Attributes Group. This error SHOULD take precedence over any
+ other 'xxx-not-supported' error, except 'client-error-charset-
+ not-supported'.
+ client-error-attributes-or-values-not-supported: one or more
+ supplied attributes, attribute syntaxes, or values are not
+ supported and the client supplied the "ipp-attributes-fidelity"
+ operation attribute with a 'true' value. They MUST be returned
+ in the Unsupported Attributes Group as explained below.
+ client-error-uri-scheme-not-supported: not applicable.
+ client-error-charset-not-supported: the charset supplied in the
+ "attributes-charset" operation attribute is not supported. The
+ Printer's "configured-charset" MUST be returned in the response
+ as the value of the "attributes-charset" operation attribute
+ and used for any 'text' and 'name' attributes returned in the
+ error response. This error SHOULD take precedence over any
+ other error, unless the request syntax is so bad that the
+ client's supplied "attributes-charset" cannot be determined.
+
+
+
+
+
+Hastings & Manros Informational [Page 39]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ client-error-conflicting-attributes: one or more supplied
+ attribute va attribute values conflicted with each other and
+ the client supplied the "ipp-attributes-fidelity" operation
+ attribute with a 'true' value. They MUST be returned in the
+ Unsupported Attributes Group as explained below.
+ server-error-internal-error: an unexpected condition prevents the
+ request from being fulfilled.
+ server-error-operation-not-supported: not applicable (since
+ Print-Job is REQUIRED).
+ server-error-service-unavailable: the service is temporarily
+ overloaded.
+ server-error-version-not-supported: the version in the request is
+ not supported. The "closest" version number supported MUST be
+ returned in the response.
+ server-error-device-error: a device error occurred while
+ receiving or spooling the request or document data or the IPP
+ Printer object can only accept one job at a time.
+ server-error-temporary-error: a temporary error such as a buffer
+ full write error, a memory overflow, or a disk full condition
+ occurred while receiving the request and/or the document data.
+ server-error-not-accepting-jobs: the Printer object's "printer-
+ is-not-accepting-jobs" attribute is 'false'.
+ server-error-busy: the Printer is too busy processing jobs to
+ accept another job at this time.
+ server-error-job-canceled: the job has been canceled by an
+ operator or the system while the client was transmitting the
+ document data.
+
+2.3.1.2 Print-URI
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to Print-URI with the following
+ specializations and differences. See Section 14 for a more complete
+ description of each status code.
+
+ server-error-uri-scheme-not-supported: the URI scheme supplied in
+ the "document-uri" operation attribute is not supported and is
+ returned in the Unsupported Attributes group.
+
+2.3.1.3 Validate-Job
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to Validate-Job. See Section 14
+ for a more complete description of each status code.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 40]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.3.1.4 Create-Job
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to Create-Job with the following
+ specializations and differences. See Section 14 for a more complete
+ description of each status code.
+
+ server-error-operation-not-supported: the Create-Job operation is
+ not supported.
+
+2.3.1.5 Get-Printer-Attributes
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to the Get-Printer-Attributes
+ operation with the following specializations and differences. See
+ Section 14 for a more complete description of each status code.
+
+ For the following success status codes, the requested attributes are
+ returned in Group 3 in the response:
+
+ successful-ok: no request attributes were substituted or ignored
+ (same as Print-Job) and no requested attributes were
+ unsupported.
+ successful-ok-ignored-or-substituted-attributes: same as Print-
+ Job, except the "requested-attributes" operation attribute MAY,
+ but NEED NOT, be returned with the unsupported values.
+ successful-ok-conflicting-attributes: same as Print-Job.
+
+ For the error status codes, Group 3 is returned containing no
+ attributes or is not returned at all:
+
+ client-error-not-possible: Same as Print-Job, in addition the
+ Printer object is not accepting any requests.
+ client-error-request-entity-too-large: same as Print-job, except
+ that no print data is involved.
+ client-error-attributes-or-values-not-supported: not applicable,
+ since unsupported operation attributes MUST be ignored and '
+ successful-ok-ignored-or-substituted-attributes' returned.
+ client-error-conflicting-attributes: same as Print-Job, except
+ that "ipp-attribute-fidelity" is not involved.
+ server-error-operation-not-supported: not applicable (since Get-
+ Printer-Attributes is REQUIRED).
+ server-error-device-error: same as Print-Job, except that no
+ document data is involved.
+ server-error-temporary-error: same as Print-Job, except that no
+ document data is involved.
+ server-error-not-accepting-jobs: not applicable.
+
+
+
+
+Hastings & Manros Informational [Page 41]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ server-error-busy: same as Print-Job, except the IPP object is
+ too busy to accept even query requests.
+ server-error-job-canceled: not applicable.
+
+2.3.1.6 Get-Jobs
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to the Get-Jobs operation with the
+ following specializations and differences. See Section 14 for a
+ more complete description of each status code.
+
+ For the following success status codes, the requested attributes are
+ returned in Group 3 in the response:
+
+ successful-ok: no request attributes were substituted or ignored
+ (same as Print-Job) and no requested attributes were
+ unsupported.
+ successful-ok-ignored-or-substituted-attributes: same as Print-
+ Job, except the "requested-attributes" operation attribute MAY,
+ but NEED NOT, be returned with the unsupported values.
+ successful-ok-conflicting-attributes: same as Print-Job.
+
+ For any error status codes, Group 3 is returned containing no
+ attributes or is not returned at all. The following brief error
+ status code descriptions contain unique information for use with
+ Get-Jobs operation. See section 14 for the other error status codes
+ that apply uniformly to all operations:
+
+ client-error-not-possible: Same as Print-Job, in addition the
+ Printer object is not accepting any requests.
+ client-error-request-entity-too-large: same as Print-job, except
+ that no print data is involved.
+ client-error-document-format-not-supported: not applicable.
+ client-error-attributes-or-values-not-supported: not applicable,
+ since unsupported operation attributes MUST be ignored and '
+ successful-ok-ignored-or-substituted-attributes' returned.
+ client-error-conflicting-attributes: same as Print-Job, except
+ that "ipp-attribute-fidelity" is not involved.
+ server-error-operation-not-supported: not applicable (since Get-
+ Jobs is REQUIRED).
+ server-error-device-error: same as Print-Job, except that no
+ document data is involved.
+ server-error-temporary-error: same as Print-Job, except that no
+ document data is involved.
+ server-error-not-accepting-jobs: not applicable.
+ server-error-job-canceled: not applicable.
+
+
+
+
+
+Hastings & Manros Informational [Page 42]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.3.2 Job Operations
+
+2.3.2.1 Send-Document
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to the Get-Printer-Attributes
+ operation with the following specializations and differences. See
+ Section 14 for a more complete description of each status code.
+
+ For the following success status codes, the document has been added
+ to the specified Job object and the job's "number-of-documents"
+ attribute has been incremented:
+
+ successful-ok: no request attributes were substituted or ignored
+ (same as Print-Job).
+ successful-ok-ignored-or-substituted-attributes: same as Print-
+ Job.
+ successful-ok-conflicting-attributes: same as Print-Job.
+
+ For the error status codes, no document has been added to the Job
+ object and the job's "number-of-documents" attribute has not been
+ incremented:
+
+ client-error-not-possible: Same as Print-Job, except that the
+ Printer's "printer-is-accepting-jobs" attribute is not
+ involved, so that the client is able to finish submitting a
+ multi-document job after this attribute has been set to 'true'.
+ Another condition is that the state of the job precludes Send-
+ Document, i.e., the job has already been closed out by the
+ client. However, if the IPP Printer closed out the job due to
+ timeout, the 'client-error-timeout' error status SHOULD be
+ returned instead.
+ client-error-timeout: This request was sent after the Printer
+ closed the job, because it has not received a Send-Document or
+ Send-URI operation within the Printer's "multiple-operation-
+ time-out" period.
+ client-error-request-entity-too-large: same as Print-Job.
+ client-error-conflicting-attributes: same as Print-Job, except
+ that "ipp-attributes-fidelity" operation attribute is not
+ involved.
+ server-error-operation-not-supported: the Send-Document request
+ is not supported.
+ server-error-not-accepting-jobs: not applicable.
+ server-error-job-canceled: the job has been canceled by an
+ operator or the system while the client was transmitting the
+ data.
+
+
+
+
+
+Hastings & Manros Informational [Page 43]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.3.2.2 Send-URI
+
+ All of the Print-Job status code descriptions in Section 3.2.1.2
+ Print-Job Response with the specializations described for Send-
+ Document are applicable to Send-URI. See Section 14 for a more
+ complete description of each status code.
+
+ server-error-uri-scheme-not-supported: the URI scheme supplied in
+ the "document-uri" operation attribute is not supported and the
+ "document-uri" attribute MUST be returned in the Unsupported
+ Attributes group.
+
+2.3.2.3 Cancel-Job
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to Cancel-Job with the following
+ specializations and differences. See Section 14 for a more complete
+ description of each status code.
+
+ For the following success status codes, the Job object is being
+ canceled or has been canceled:
+
+ successful-ok: no request attributes were substituted or ignored
+ (same as Print-Job).
+ successful-ok-ignored-or-substituted-attributes: same as Print-
+ Job.
+ successful-ok-conflicting-attributes: same as Print-Job.
+
+ For any of the error status codes, the Job object has not been
+ canceled or was previously canceled.
+
+ client-error-not-possible: The request cannot be carried out
+ because of the state of the Job object ('completed', '
+ canceled', or 'aborted') or the state of the system.
+ client-error-not-found: the target Printer and/or Job object does
+ not exist.
+ client-error-gone: the target Printer and/or Job object no longer
+ exists and no forwarding address is known.
+ client-error-request-entity-too-large: same as Print-Job, except
+ no document data is involved.
+ client-error-document-format-not-supported: not applicable.
+ client-error-attributes-or-values-not-supported: not applicable,
+ since unsupported operation attributes and values MUST be
+ ignored.
+ client-error-conflicting-attributes: same as Print-Job, except
+ that the Printer's "printer-is-accepting-jobs" attribute is not
+ involved.
+
+
+
+
+Hastings & Manros Informational [Page 44]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ server-error-operation-not-supported: not applicable (Cancel-Job
+ is REQUIRED).
+ server-error-device-error: same as Print-Job, except no document
+ data is involved.
+ server-error-temporary-error: same as Print-Job, except no
+ document data is involved.
+ server-error-not-accepting-jobs: not applicable.
+ server-error-job-canceled: not applicable.
+
+2.3.2.4 Get-Job-Attributes
+
+ All of the Print-Job status codes described in Section 3.2.1.2
+ Print-Job Response are applicable to Get-Job-Attributes with the
+ following specializations and differences. See Section 14 for a more
+ complete description of each status code.
+
+ For the following success status codes, the requested attributes are
+ returned in Group 3 in the response:
+
+ successful-ok: no request attributes were substituted or ignored
+ (same as Print-Job) and no requested attributes were
+ unsupported.
+ successful-ok-ignored-or-substituted-attributes: same as Print-
+ Job, except the "requested-attributes" operation attribute MAY,
+ but NEED NOT, be returned with the unsupported values.
+ successful-ok-conflicting-attributes: same as Print-Job.
+
+ For the error status codes, Group 3 is returned containing no
+ attributes or is not returned at all.
+
+ client-error-not-possible: Same as Print-Job, in addition the
+ Printer object is not accepting any requests.
+ client-error-document-format-not-supported: not applicable.
+ client-error-attributes-or-values-not-supported: not applicable.
+ client-error-uri-scheme-not-supported: not applicable.
+ client-error-conflicting-attributes: not applicable
+ server-error-operation-not-supported: not applicable (since Get-
+ Job-Attributes is REQUIRED).
+ server-error-device-error: same as Print-Job, except no document
+ data is involved.
+ server-error-temporary-error: sane as Print-Job, except no
+ document data is involved.
+ server-error-not-accepting-jobs: not applicable. server-error-
+ job-canceled: not applicable.
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 45]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.4 Validate-Job
+
+ The Validate-Job operation has been designed so that its
+ implementation may be a part of the Print-Job operation. Therefore,
+ requiring Validate-Job is not a burden on implementers. Also it is
+ useful for client's to be able to count on its presence in all
+ conformance implementations, so that the client can determine before
+ sending a long document, whether the job will be accepted by the IPP
+ Printer or not.
+
+2.5 Case Sensitivity in URIs
+
+ IPP client and server implementations must be aware of the diverse
+ uppercase/lowercase nature of URIs. RFC 2396 defines URL schemes and
+ Host names as case insensitive but reminds us that the rest of the
+ URL may well demonstrate case sensitivity. When creating URL's for
+ fields where the choice is completely arbitrary, it is probably best
+ to select lower case. However, this cannot be guaranteed and
+ implementations MUST NOT rely on any fields being case-sensitive or
+ case-insensitive in the URL beyond the URL scheme and host name
+ fields.
+
+ The reason that the IPP specification does not make any restrictions
+ on URIs, is so that implementations of IPP may use off-the-shelf
+ components that conform to the standards that define URIs, such as
+ RFC 2396 and the HTTP/1.1 specifications [RFC2068]. See these
+ specifications for rules of matching, comparison, and case-
+ sensitivity.
+
+ It is also recommended that System Administrators and implementations
+ avoid creating URLs for different printers that differ only in their
+ case. For example, don't have Printer1 and printer1 as two different
+ IPP Printers.
+
+ The HTTP/1.1 specification [RFC2068] contains more details on
+ comparing URLs.
+
+2.6 Character Sets, natural languages, and internationalization
+
+ This section discusses character set support, natural language
+ support and internationalization.
+
+2.6.1 Character set code conversion support
+
+ IPP clients and IPP objects are REQUIRED to support UTF-8. They MAY
+ support additional charsets. It is RECOMMENDED that an IPP object
+ also support US-ASCII, since many clients support US-ASCII, and
+ indicate that UTF-8 and US-ASCII are supported by populating the
+
+
+
+Hastings & Manros Informational [Page 46]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Printer's "charset-supported" with 'utf-8' and 'us-ascii' values. An
+ IPP object is required to code covert with as little loss as possible
+ between the charsets that it supports, as indicated in the Printer's
+ "charsets-supported" attribute.
+
+ How should the server handle the situation where the "attributes-
+ charset" of the response itself is "us-ascii", but one or more
+ attributes in that response is in the "utf-8" format?
+
+ Example: Consider a case where a client sends a Print-Job request
+ with "utf-8" as the value of "attributes-charset" and with the "job-
+ name" attribute supplied. Later another client submits a Get-Job-
+ Attribute or Get-Jobs request. This second request contains the
+ "attributes-charset" with value "us-ascii" and "requested-attributes"
+ attribute with exactly one value "job-name".
+
+ According to the RFC2566 document (section 3.1.4.2), the value of the
+ "attributes-charset" for the response of the second request must be
+ "us-ascii" since that is the charset specified in the request. The
+ "job-name" value, however, is in "utf-8" format. Should the request
+ be rejected even though both "utf-8" and "us-ascii" charsets are
+ supported by the server? or should the "job-name" value be converted
+ to "us-ascii" and return "successful-ok-conflicting-attributes"
+ (0x0002) as the status code?
+
+ Answer: An IPP object that supports both utf-8 (REQUIRED) and us-
+ ascii, the second paragraph of section 3.1.4.2 applies so that the
+ IPP object MUST accept the request, perform code set conversion
+ between these two charsets with "the highest fidelity possible" and
+ return 'successful-ok', rather than a warning 'successful-ok-
+ conflicting-attributes, or an error. The printer will do the best it
+ can to convert between each of the character sets that it supports--
+ even if that means providing a string of question marks because none
+ of the characters are representable in US ASCII. If it can't perform
+ such conversion, it MUST NOT advertise us-ascii as a value of its
+ "attributes-charset-supported" and MUST reject any request that
+ requests 'us-ascii'.
+
+ One IPP object implementation strategy is to convert all request text
+ and name values to a Unicode internal representation. This is 16-bit
+ and virtually universal. Then convert to the specified operation
+ attributes-charset on output.
+
+ Also it would be smarter for a client to ask for 'utf-8', rather than
+ 'us-ascii' and throw away characters that it doesn't understand,
+ rather than depending on the code conversion of the IPP object.
+
+
+
+
+
+Hastings & Manros Informational [Page 47]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.6.2 What charset to return when an unsupported charset is requested?
+
+ Section 3.1.4.1 Request Operation attributes was clarified in
+ November 1998 as follows:
+
+ All clients and IPP objects MUST support the 'utf-8' charset
+ [RFC2044] and MAY support additional charsets provided that they
+ are registered with IANA [IANA-CS]. If the Printer object does
+ not support the client supplied charset value, the Printer object
+ MUST reject the request, set the "attributes-charset" to 'utf-8'
+ in the response, and return the 'client-error-charset-not-
+ supported' status code and any 'text' or 'name' attributes using
+ the 'utf-8' charset.
+
+ Since the client and IPP object MUST support UTF-8, returning any
+ text or name attributes in UTF-8 when the client requests a charset
+ that is not supported should allow the client to display the text or
+ name.
+
+ Since such an error is a client error, rather than a user error, the
+ client should check the status code first so that it can avoid
+ displaying any other returned 'text' and 'name' attributes that are
+ not in the charset requested.
+
+ Furthermore, [RFC2566] section 14.1.4.14 client-error-charset-not-
+ supported (0x040D) was clarified in November 1998 as follows:
+
+ For any operation, if the IPP Printer does not support the charset
+ supplied by the client in the "attributes-charset" operation
+ attribute, the Printer MUST reject the operation and return this
+ status and any 'text' or 'name' attributes using the 'utf-8'
+ charset (see Section 3.1.4.1).
+
+2.6.3 Natural Language Override (NLO)
+
+ The 'text' and 'name' attributes each have two forms. One has an
+ implicit natural language, and the other has an explicit natural
+ language. The 'textWithoutLanguage' and 'textWithoutLanguage' are
+ the two 'text' forms. The 'nameWithoutLanguage" and '
+ nameWithLanguage are the two 'name' forms. If a receiver (IPP object
+ or IPP client) supports an attribute with attribute syntax 'text', it
+ MUST support both forms in a request and a response. A sender (IPP
+ client or IPP object) MAY send either form for any such attribute.
+ When a sender sends a WithoutLanguage form, the implicit natural
+ language is specified in the "attributes-natural-language" operation
+ attribute which all senders MUST include in every request and
+ response.
+
+
+
+
+Hastings & Manros Informational [Page 48]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ When a sender sends a WithLanguage form, it MAY be different from the
+ implicit natural language supplied by the sender or it MAY be the
+ same. The receiver MUST treat either form equivalently.
+
+ There is an implementation decision for senders, whether to always
+ send the WithLanguage forms or use the WithoutLanguage form when the
+ attribute's natural language is the same as the request or response.
+ The former approach makes the sender implementation simpler. The
+ latter approach is more efficient on the wire and allows inter-
+ working with non-conforming receivers that fail to support the
+ WithLanguage forms. As each approach have advantages, the choice is
+ completely up to the implementer of the sender.
+
+ Furthermore, when a client receives a 'text' or 'name' job attribute
+ that it had previously supplied, that client MUST NOT expect to see
+ the attribute in the same form, i.e., in the same WithoutLanguage or
+ WithLanguage form as the client supplied when it created the job.
+ The IPP object is free to transform the attribute from the
+ WithLanguage form to the WithoutLanguage form and vice versa, as long
+ as the natural language is preserved. However, in order to meet this
+ latter requirement, it is usually simpler for the IPP object
+ implementation to store the natural language explicitly with the
+ attribute value, i.e., to store using an internal representation that
+ resembles the WithLanguage form.
+
+ The IPP Printer MUST copy the natural language of a job, i.e., the
+ value of the "attributes-natural-language" operation attribute
+ supplied by the client in the create operation, to the Job object as
+ a Job Description attribute, so that a client is able to query it.
+ In returning a Get-Job-Attributes response, the IPP object MAY return
+ one of three natural language values in the response's "attributes-
+ natural-language" operation attribute: (1) that requested by the
+ requester, (2) the natural language of the job, or (3) the configured
+ natural language of the IPP Printer, if the requested language is not
+ supported by the IPP Printer.
+
+ This "attributes-natural-language" Job Description attribute is
+ useful for an IPP object implementation that prints start sheets in
+ the language of the user who submitted the job. This same Job
+ Description attribute is useful to a multi-lingual operator who has
+ to communicate with different job submitters in different natural
+ languages. This same Job Description attribute is expected to be
+ used in the future to generate notification messages in the natural
+ language of the job submitter.
+
+ Early drafts of [RFC2566] contained a job-level natural language
+ override (NLO) for the Get-Jobs response. A job-level (NLO) is an
+ (unrequested) Job Attribute which then specified the implicit natural
+
+
+
+Hastings & Manros Informational [Page 49]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ language for any other WithoutLanguage job attributes returned in the
+ response for that job. Interoperability testing of early
+ implementations showed that no one was implementing the job-level NLO
+ in Get-Job responses. So the job-level NLO was eliminated from the
+ Get- Jobs response. This simplification makes all requests and
+ responses consistent in that the implicit natural language for any
+ WithoutLanguage 'text' or 'name' form is always supplied in the
+ request's or response's "attributes-natural-language" operation
+ attribute.
+
+2.7 The "queued-job-count" Printer Description attribute
+
+2.7.1 Why is "queued-job-count" RECOMMENDED?
+
+ The reason that "queued-job-count" is RECOMMENDED, is that some
+ clients look at that attribute alone when summarizing the status of a
+ list of printers, instead of doing a Get-Jobs to determine the number
+ of jobs in the queue. Implementations that fail to support the
+ "queued-job-count" will cause that client to display 0 jobs when
+ there are actually queued jobs.
+
+ We would have made it a REQUIRED Printer attribute, but some
+ implementations had already been completed before the issue was
+ raised, so making it a SHOULD was a compromise.
+
+2.7.2 Is "queued-job-count" a good measure of how busy a printer is?
+
+ The "queued-job-count" is not a good measure of how busy the printer
+ is when there are held jobs. A future registration could be to add a
+ "held-job-count" (or an "active-job-count") Printer Description
+ attribute if experience shows that such an attribute (combination) is
+ needed to quickly indicate how busy a printer really is.
+
+2.8 Sending empty attribute groups
+
+ The [RFC2566] and [RFC2565] specifications RECOMMEND that a sender
+ not send an empty attribute group in a request or a response.
+ However, they REQUIRE a receiver to accept an empty attribute group
+ as equivalent to the omission of that group. So a client SHOULD omit
+ the Job Template Attributes group entirely in a create operation that
+ is not supplying any Job Template attributes. Similarly, an IPP
+ object SHOULD omit an empty Unsupported Attributes group if there are
+ no unsupported attributes to be returned in a response.
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 50]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ The [RFC2565] specification REQUIRES a receiver to be able to receive
+ either an empty attribute group or an omitted attribute group and
+ treat them equivalently. The term "receiver" means an IPP object for
+ a request and a client for a response. The term "sender' means a
+ client for a request and an IPP object for a response.
+
+ There is an exception to the rule for Get-Jobs when there are no
+ attributes to be returned. [RFC2565] contains the following
+ paragraph:
+
+ The syntax allows an xxx-attributes-tag to be present when the
+ xxx-attribute-sequence that follows is empty. The syntax is
+ defined this way to allow for the response of Get-Jobs where no
+ attributes are returned for some job-objects. Although it is
+ RECOMMENDED that the sender not send an xxx-attributes-tag if
+ there are no attributes (except in the Get-Jobs response just
+ mentioned), the receiver MUST be able to decode such syntax.
+
+2.9 Returning unsupported attributes in Get-Xxxx responses
+
+ In the Get-Printer-Attributes, Get-Jobs, or Get-Job-Attributes
+ responses, the client cannot depend on getting unsupported attributes
+ returned in the Unsupported Attributes group that the client
+ requested, but are not supported by the IPP object. However, such
+ unsupported requested attributes will not be returned in the Job
+ Attributes or Printer Attributes group (since they are unsupported).
+ Furthermore, the IPP object is REQUIRED to return the 'successful-
+ ok-ignored-or-substituted-attributes' status code, so that the client
+ knows that not all that was requested has been returned.
+
+2.10 Returning job-state in Print-Job response
+
+ An IPP client submits a small job via Print-Job. By the time the IPP
+ printer/print server is putting together a response to the operation,
+ the job has finished printing and been removed as an object from the
+ print system. What should the job-state be in the response?
+
+ The Model suggests that the Printer return a response before it even
+ accepts the document content. The Job Object Attributes are returned
+ only if the IPP object returns one of the success status codes. Then
+ the job-state would always be "pending" or "pending-held".
+
+ This issue comes up for the implementation of an IPP Printer object
+ as a server that forwards jobs to devices that do not provide job
+ status back to the server. If the server is reasonably certain that
+ the job completed successfully, then it should return the job-state
+ as 'completed'. Also the server can keep the job in its "job
+ history" long after the job is no longer in the device. Then a user
+
+
+
+Hastings & Manros Informational [Page 51]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ could query the server and see that the job was in the 'completed'
+ state and completed as specified by the job's "time-at-completed"
+ time which would be the same as the server submitted the job to the
+ device.
+
+ An alternative is for the server to respond to the client before or
+ while sending the job to the device, instead of waiting until the
+ server has finished sending the job to the device. In this case, the
+ server can return the job's state as 'pending' with the 'job-
+ outgoing' value in the job's "job-state-reasons" attribute.
+
+ If the server doesn't know for sure whether the job completed
+ successfully (or at all), it could return the (out-of-band) 'unknown'
+ value.
+
+ On the other hand, if the server is able to query the device and/or
+ setup some sort of event notification that the device initiates when
+ the job makes state transitions, then the server can return the
+ current job state in the Print-Job response and in subsequent queries
+ because the server knows what the job state is in the device (or can
+ query the device).
+
+ All of these alternatives depend on implementation of the server and
+ the device.
+
+2.11 Flow controlling the data portion of a Print-Job request
+
+ A paused printer (or one that is stopped due to paper out or jam or
+ spool space full or buffer space full, may flow control the data of a
+ Print-Job operation (at the TCP/IP layer), so that the client is not
+ able to send all the document data. Consequently, the Printer will
+ not return a response until the condition is changed.
+
+ The Printer should not return a Print-Job response with an error code
+ in any of these conditions, since either the printer will be resumed
+ and/or the condition will be freed either by human intervention or as
+ jobs print.
+
+ In writing test scripts to test IPP Printers, the script must also be
+ written not to expect a response, if the printer has been paused,
+ until the printer is resumed, in order to work with all possible
+ implementations.
+
+2.12 Multi-valued attributes
+
+ What is the attribute syntax for a multi-valued attribute? Since
+ some attributes support values in more than one data type, such as
+ "media", "job-hold-until", and "job-sheets", IPP semantics associate
+
+
+
+Hastings & Manros Informational [Page 52]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ the attribute syntax with each value, not with the attribute as a
+ whole. The protocol associates the attribute syntax tag with each
+ value. Don't be fooled, just because the attribute syntax tag comes
+ before the attribute keyword. All attribute values after the first
+ have a zero length attribute keyword as the indication of a
+ subsequent value of the same attribute.
+
+2.13 Querying jobs with IPP that were submitted using other job
+ submission protocols
+
+ The following clarification was added to [RFC2566] section 8.5:
+
+ 8.5 Queries on jobs submitted using non-IPP protocols
+
+ If the device that an IPP Printer is representing is able to
+ accept jobs using other job submission protocols in addition to
+ IPP, it is RECOMMEND that such an implementation at least allow
+ such "foreign" jobs to be queried using Get-Jobs returning "job-
+ id" and "job-uri" as 'unknown'. Such an implementation NEED NOT
+ support all of the same IPP job attributes as for IPP jobs. The
+ IPP object returns the 'unknown' out-of-band value for any
+ requested attribute of a foreign job that is supported for IPP
+ jobs, but not for foreign jobs.
+
+ It is further RECOMMENDED, that the IPP Printer generate "job-id"
+ and "job-uri" values for such "foreign jobs", if possible, so that
+ they may be targets of other IPP operations, such as Get-Job-
+ Attributes and Cancel-Job. Such an implementation also needs to
+ deal with the problem of authentication of such foreign jobs. One
+ approach would be to treat all such foreign jobs as belonging to
+ users other than the user of the IPP client. Another approach
+ would be for the foreign job to belong to 'anonymous'. Only if
+ the IPP client has been authenticated as an operator or
+ administrator of the IPP Printer object, could the foreign jobs be
+ queried by an IPP request. Alternatively, if the security policy
+ is to allow users to query other users' jobs, then the foreign
+ jobs would also be visible to an end-user IPP client using Get-
+ Jobs and Get-Job-Attributes.
+
+ Thus IPP MAY be implemented as a "universal" protocol that provides
+ access to jobs submitted with any job submission protocol. As IPP
+ becomes widely implemented, providing a more universal access makes
+ sense.
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 53]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+2.14 The 'none' value for empty sets
+
+ [RFC2566] states that the 'none' value should be used as the value of
+ a 1SetOf when the set is empty. In most cases, sets that are
+ potentially empty contain keywords so the keyword 'none' is used, but
+ for the 3 finishings attributes, the values are enums and thus the
+ empty set is represented by the enum 3. Currently there are no other
+ attributes with 1SetOf values which can be empty and can contain
+ values that are not keywords. This exception requires special code
+ and is a potential place for bugs. It would have been better if we
+ had chosen an out-of-band value, either "no-value" or some new value,
+ such as 'none'. Since we didn't, implementations have to deal with
+ the different representations of 'none', depending on the attribute
+ syntax.
+
+2.15 Get-Jobs, my-jobs='true', and 'requesting-user-name'?
+
+ In [RFC2566] section 3.2.6.1 'Get-Jobs Request', if the attribute '
+ my-jobs' is present and set to TRUE, MUST the 'requesting-user-name'
+ attribute be there to, and if it's not present what should the IPP
+ printer do?
+
+ [RFC2566] Section 8.3 describes the various cases of "requesting-
+ user-name" being present or not for any operation. If the client
+ does not supply a value for "requesting-user-name", the printer MUST
+ assume that the client is supplying some anonymous name, such as
+ "anonymous".
+
+2.16 The "multiple-document-handling" Job Template attribute and support
+ of multiple document jobs
+
+ ISSUE: IPP/1.0 is silent on which of the four effects an
+ implementation would perform if it supports Create-Job, but does not
+ support "multiple-document-handling".
+
+ A fix to IPP/1.0 would be to require implementing all four values of
+ "multiple-document-handling" if Create-Job is supported at all. Or
+ at least 'single-document-new-sheet' and 'separate-documents-
+ uncollated-copies'. In any case, an implementation that supports
+ Create-Job SHOULD also support "multiple-document-handling". Support
+ for all four values is RECOMMENDED, but at least the 'single-
+ document-new-sheet' and 'separate-documents-uncollated-copies'
+ values, along with the "multiple-document-handling-default"
+ indicating the default behavior and "multiple-document-handling-
+ supported" values. If an implementation spools the data, it should
+ also support the 'separate-documents-collated-copies' value as well.
+
+
+
+
+
+Hastings & Manros Informational [Page 54]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+3 Encoding and Transport
+
+ This section discusses various aspects of IPP/1.0 Encoding and
+ Transport [RFC2565].
+
+ A server is not required to send a response until after it has
+ received the client.s entire request. Hence, a client must not
+ expect a response until after it has sent the entire request.
+ However, we recommend that the server return a response as soon as
+ possible if an error is detected while the client is still sending
+ the data, rather than waiting until all of the data is received.
+ Therefore, we also recommend that a client listen for an error
+ response that an IPP server MAY send before it receives all the data.
+ In this case a client, if chunking the data, can send a premature
+ zero-length chunk to end the request before sending all the data (and
+ so the client can keep the connection open for other requests, rather
+ than closing it). If the request is blocked for some reason, a client
+ MAY determine the reason by opening another connection to query the
+ server using Get-Printer-Attributes.
+
+ In the following sections, there are a tables of all HTTP headers
+ which describe their use in an IPP client or server. The following
+ is an explanation of each column in these tables.
+
+ - the .header. column contains the name of a header.
+ - the .request/client. column indicates whether a client sends the
+ header.
+ - the .request/ server. column indicates whether a server supports
+ the header when received.
+ - the .response/ server. column indicates whether a server sends
+ the header.
+ - the .response /client. column indicates whether a client
+ supports the header when received.
+ - the .values and conditions. column specifies the allowed header
+ values and the conditions for the header to be present in a
+ request/response.
+
+ The table for .request headers. does not have columns for responses,
+ and the table for .response headers. does not have columns for
+ requests.
+
+ The following is an explanation of the values in the .request/client.
+ and .response/ server. columns.
+
+ - must: the client or server MUST send the header,
+ - must-if: the client or server MUST send the header when the
+ condition described in the .values and conditions. column is
+ met,
+
+
+
+Hastings & Manros Informational [Page 55]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ - may: the client or server MAY send the header
+ - not: the client or server SHOULD NOT send the header. It is not
+ relevant to an IPP implementation.
+
+ The following is an explanation of the values in the
+ .response/client. and .request/ server. columns.
+
+ - must: the client or server MUST support the header,
+ - may: the client or server MAY support the header
+ - not: the client or server SHOULD NOT support the header. It is
+ not relevant to an IPP implementation.
+
+3.1 General Headers
+
+
+ The following is a table for the general headers.
+
+
+ General- Request Response Values and Conditions
+ Header
+
+ Client Server Server Client
+
+ Cache- must not must not .no-cache. only
+ Control
+
+ Connection must-if must must- must .close. only. Both
+ if client and server
+ SHOULD keep a
+ connection for the
+ duration of a sequence
+ of operations. The
+ client and server MUST
+ include this header
+ for the last operation
+ in such a sequence.
+
+ Date may may must may per RFC 1123 [RFC1123]
+ from RFC 2068
+ [RFC2068]
+
+ Pragma must not must not .no-cache. only
+
+ Transfer- must-if must must- must .chunked. only .
+ Encoding if Header MUST be present
+ if Content-Length is
+ absent.
+
+
+
+
+Hastings & Manros Informational [Page 56]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Upgrade not not not not
+
+ Via not not not not
+
+3.2 Request Headers
+
+
+ The following is a table for the request headers.
+
+
+ Request-Header Client Server Request Values and Conditions
+
+ Accept may must .application/ipp. only. This
+ value is the default if the
+
+ Request-Header Client Server Request Values and Conditions
+
+ client omits it
+
+ Accept-Charset not not Charset information is within
+ the application/ipp entity
+
+ Accept-Encoding may must empty and per RFC 2068 [RFC2068]
+ and IANA registry for content-
+ codings
+
+ Accept-Language not not language information is within
+ the application/ipp entity
+
+ Authorization must-if must per RFC 2068. A client MUST send
+ this header when it receives a
+ 401 .Unauthorized. response and
+ does not receive a .Proxy-
+ Authenticate. header.
+
+ From not not per RFC 2068. Because RFC
+ recommends sending this header
+ only with the user.s approval, it
+ is not very useful
+
+ Host must must per RFC 2068
+
+ If-Match not not
+
+ If-Modified- not not
+ Since
+
+ If-None-Match not not
+
+
+
+Hastings & Manros Informational [Page 57]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ If-Range not not
+
+ If-Unmodified- not not
+ Since
+
+ Max-Forwards not not
+
+ Proxy- must-if not per RFC 2068. A client MUST send
+ Authorization this header when it receives a
+ 401 .Unauthorized. response and a
+ .Proxy-Authenticate. header.
+
+ Range not not
+
+ Referer not not
+
+ User-Agent not not
+
+
+3.3 Response Headers
+
+
+ The following is a table for the request headers.
+
+
+ Response- Server Client Response Values and Conditions
+ Header
+
+ Accept-Ranges not not
+
+ Age not not
+
+ Location must-if may per RFC 2068. When URI needs
+ redirection.
+
+ Proxy- not must per RFC 2068
+ Authenticate
+
+ Public may may per RFC 2068
+
+ Retry-After may may per RFC 2068
+
+ Server not not
+
+ Vary not not
+
+ Warning may may per RFC 2068
+
+
+
+
+Hastings & Manros Informational [Page 58]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ WWW- must-if must per RFC 2068. When a server needs to
+ Authenticate authenticate a client.
+
+3.4 Entity Headers
+
+
+ The following is a table for the entity headers.
+
+
+ Entity-Header Request Response Values and Conditions
+
+ Client Server Server Client
+
+ Allow not not not not
+
+ Content-Base not not not not
+
+ Content- may must must must per RFC 2068 and IANA
+ Encoding registry for content
+ codings.
+
+ Content- not not not not Application/ipp
+ Language handles language
+
+ Content- must-if must must-if must the length of the
+ Length message-body per RFC
+ 2068. Header MUST be
+ present if Transfer-
+
+ Entity-Header Request Response Values and Conditions
+
+ Client Server Server Client
+
+ Encoding is absent.
+
+ Content- not not not not
+ Location
+
+ Content-MD5 may may may may per RFC 2068
+
+ Content-Range not not not not
+
+ Content-Type must must must must .application/ipp.
+ only
+
+ ETag not not not not
+
+ Expires not not not not
+
+
+
+Hastings & Manros Informational [Page 59]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Last-Modified not not not not
+
+
+3.5 Optional support for HTTP/1.0
+
+ IPP implementations consist of an HTTP layer and an IPP layer. In
+ the following discussion, the term "client" refers to the HTTP client
+ layer and the term "server" refers to the HTTP server layer. The
+ Encoding and Transport document [RFC2565] requires that HTTP 1.1 MUST
+ be supported by all clients and all servers. However, a client
+ and/or a server implementation may choose to also support HTTP 1.0.
+
+ - This option means that a server may choose to communicate with a
+ (non-conforming) client that only supports HTTP 1.0. In such cases
+ the server should not use any HTTP 1.1 specific parameters or
+ features and should respond using HTTP version number 1.0.
+
+ - This option also means that a client may choose to communicate with
+ a (non-conforming) server that only supports HTTP 1.0. In such
+ cases, if the server responds with an HTTP .unsupported version
+ number. to an HTTP 1.1 request, the client should retry using HTTP
+ version number 1.0.
+
+3.6 HTTP/1.1 Chunking
+
+3.6.1 Disabling IPP Server Response Chunking
+
+ Clients MUST anticipate that the HTTP/1.1 server may chunk responses
+ and MUST accept them in responses. However, a (non-conforming) HTTP
+ client that is unable to accept chunked responses may attempt to
+ request an HTTP 1.1 server not to use chunking in its response to an
+ operation by using the following HTTP header:
+
+ TE: identity
+
+ This mechanism should not be used by a server to disable a client
+ from chunking a request, since chunking of document data is an
+ important feature for clients to send long documents.
+
+3.6.2 Warning About the Support of Chunked Requests
+
+ This section describes some problems with the use of chunked requests
+ and HTTP/1.1 servers.
+
+ The HTTP/1.1 standard [HTTP] requires that conforming servers support
+ chunked requests for any method. However, in spite of this
+ requirement, some HTTP/1.1 implementations support chunked responses
+ in the GET method, but do not support chunked POST method requests.
+
+
+
+Hastings & Manros Informational [Page 60]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ Some HTTP/1.1 implementations that support CGI scripts [CGI] and/or
+ servlets [Servlet] require that the client supply a Content-Length.
+ These implementations might reject a chunked POST method and return a
+ 411 status code (Length Required), might attempt to buffer the
+ request and run out of room returning a 413 status code (Request
+ Entity Too Large), or might successfully accept the chunked request.
+
+ Because of this lack of conformance of HTTP servers to the HTTP/1.1
+ standard, the IPP standard [RFC2565] REQUIRES that a conforming IPP
+ Printer object implementation support chunked requests and that
+ conforming clients accept chunked responses. Therefore, IPP object
+ implementers are warned to seek HTTP server implementations that
+ support chunked POST requests in order to conform to the IPP standard
+ and/or use implementation techniques that support chunked POST
+ requests.
+
+4 References
+
+ [CGI] Coar, K. and D. Robinson, "The WWW Common Gateway Interface
+ Version 1.1 (CGI/1.1)", Work in Progress.
+
+ [HTTP] Fielding, R., Gettys,J., Mogul, J., Frystyk,, H., Masinter,
+ L., Leach, P. and T. Berners-Lee, "Hypertext Transfer
+ Protocol -- HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC1123] Braden, S., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+
+
+
+
+Hastings & Manros Informational [Page 61]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ [RFC2026] Bradner, S., "The Internet Standards Process -- Revision
+ 3", BCP 9, RFC 2026, October 1996.
+
+ [RFC2068] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC
+ 2068, January 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [Servlet] Servlet Specification Version 2.1
+ (http://java.sun.com/products/servlet/2.1/index.html).
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version 3.02),
+ November 1996.
+
+4.1 Authors' Addresses
+
+ Thomas N. Hastings
+ Xerox Corporation
+ 701 Aviation Blvd.
+ El Segundo, CA 90245
+
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Carl-Uno Manros
+ Xerox Corporation
+ 701 Aviation Blvd.
+ El Segundo, CA 90245
+
+ EMail: manros@cp10.es.xerox.com
+
+5 Security Considerations
+
+ Security issues are discussed in sections 2.2, 2.3.1, and 8.5.
+
+6 Notices
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+
+
+
+Hastings & Manros Informational [Page 62]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11 [BCP-11].
+ Copies of claims of rights made available for publication and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 63]
+
+RFC 2639 IPP/1.0: Implementer's Guide July 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings & Manros Informational [Page 64]
+
diff --git a/standards/rfc2712.txt b/standards/rfc2712.txt
new file mode 100644
index 000000000..4888e2e2d
--- /dev/null
+++ b/standards/rfc2712.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group A. Medvinsky
+Request for Comments: 2712 Excite
+Category: Standards Track M. Hur
+ CyberSafe Corporation
+ October 1999
+
+
+ Addition of Kerberos Cipher Suites to Transport Layer Security (TLS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+IESG Note:
+
+ The 40-bit ciphersuites defined in this memo are included only for
+ the purpose of documenting the fact that those ciphersuite codes have
+ already been assigned. 40-bit ciphersuites were designed to comply
+ with US-centric, and now obsolete, export restrictions. They were
+ never secure, and nowadays are inadequate even for casual
+ applications. Implementation and use of the 40-bit ciphersuites
+ defined in this document, and elsewhere, is strongly discouraged.
+
+1. Abstract
+
+ This document proposes the addition of new cipher suites to the TLS
+ protocol [1] to support Kerberos-based authentication. Kerberos
+ credentials are used to achieve mutual authentication and to
+ establish a master secret which is subsequently used to secure
+ client-server communication.
+
+2. Introduction
+
+ Flexibility is one of the main strengths of the TLS protocol.
+ Clients and servers can negotiate cipher suites to meet specific
+ security and administrative policies. However, to date,
+ authentication in TLS is limited only to public key solutions. As a
+ result, TLS does not fully support organizations with heterogeneous
+ security deployments that include authentication systems based on
+ symmetric cryptography. Kerberos, originally developed at MIT, is
+
+
+
+Medvinsky & Hur Standards Track [Page 1]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+ based on an open standard [2] and is the most widely deployed
+ symmetric key authentication system. This document proposes a new
+ option for negotiating Kerberos authentication within the TLS
+ framework. This achieves mutual authentication and the establishment
+ of a master secret using Kerberos credentials. The proposed changes
+ are minimal and, in fact, no different from adding a new public key
+ algorithm to the TLS framework.
+
+3. Kerberos Authentication Option In TLS
+
+ This section describes the addition of the Kerberos authentication
+ option to the TLS protocol. Throughout this document, we refer to
+ the basic SSL handshake shown in Figure 1. For a review of the TLS
+ handshake see [1].
+
+ CLIENT SERVER
+ ------ ------
+ ClientHello
+ -------------------------------->
+ ServerHello
+ Certificate *
+ ServerKeyExchange*
+ CertificateRequest*
+ ServerHelloDone
+ <-------------------------------
+ Certificate*
+ ClientKeyExchange
+ CertificateVerify*
+ change cipher spec
+ Finished
+ | -------------------------------->
+ | change cipher spec
+ | Finished
+ | |
+ | |
+ Application Data <------------------------------->Application Data
+
+ FIGURE 1: The TLS protocol. All messages followed by a star are
+ optional. Note: This figure was taken from an IETF document
+ [1].
+
+ The TLS security context is negotiated in the client and server hello
+ messages. For example: TLS_RSA_WITH_RC4_MD5 means the initial
+ authentication will be done using the RSA public key algorithm, RC4
+ will be used for the session key, and MACs will be based on the MD5
+ algorithm. Thus, to facilitate the Kerberos authentication option,
+ we must start by defining new cipher suites including (but not
+ limited to):
+
+
+
+Medvinsky & Hur Standards Track [Page 2]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+ CipherSuite TLS_KRB5_WITH_DES_CBC_SHA = { 0x00,0x1E };
+ CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_SHA = { 0x00,0x1F };
+ CipherSuite TLS_KRB5_WITH_RC4_128_SHA = { 0x00,0x20 };
+ CipherSuite TLS_KRB5_WITH_IDEA_CBC_SHA = { 0x00,0x21 };
+ CipherSuite TLS_KRB5_WITH_DES_CBC_MD5 = { 0x00,0x22 };
+ CipherSuite TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = { 0x00,0x23 };
+ CipherSuite TLS_KRB5_WITH_RC4_128_MD5 = { 0x00,0x24 };
+ CipherSuite TLS_KRB5_WITH_IDEA_CBC_MD5 = { 0x00,0x25 };
+
+ CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = { 0x00,0x26 };
+ CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = { 0x00,0x27 };
+ CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_SHA = { 0x00,0x28 };
+ CipherSuite TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = { 0x00,0x29 };
+ CipherSuite TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00,0x2A };
+ CipherSuite TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = { 0x00,0x2B };
+
+ To establish a Kerberos-based security context, one or more of the
+ above cipher suites must be specified in the client hello message.
+ If the TLS server supports the Kerberos authentication option, the
+ server hello message, sent to the client, will confirm the Kerberos
+ cipher suite selected by the server. The server's certificate, the
+ client
+
+ CertificateRequest, and the ServerKeyExchange shown in Figure 1 will
+ be omitted since authentication and the establishment of a master
+ secret will be done using the client's Kerberos credentials for the
+ TLS server. The client's certificate will be omitted for the same
+ reason. Note that these messages are specified as optional in the
+ TLS protocol; therefore, omitting them is permissible.
+
+ The Kerberos option must be added to the ClientKeyExchange message as
+ shown in Figure 2.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Medvinsky & Hur Standards Track [Page 3]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+ struct
+ {
+ select (KeyExchangeAlgorithm)
+ {
+ case krb5: KerberosWrapper; /* new addition */
+ case rsa: EncryptedPreMasterSecret;
+ case diffie_hellman: ClientDiffieHellmanPublic;
+ } Exchange_keys;
+
+ } ClientKeyExchange;
+
+ struct
+ {
+ opaque Ticket;
+ opaque authenticator; /* optional */
+ opaque EncryptedPreMasterSecret; /* encrypted with the session key
+ which is sealed in the ticket */
+ } KerberosWrapper; /* new addition */
+
+ FIGURE 2: The Kerberos option in the ClientKeyExchange.
+
+ To use the Kerberos authentication option, the TLS client must obtain
+ a service ticket for the TLS server. In TLS, the ClientKeyExchange
+ message is used to pass a random 48-byte pre-master secret to the
+ server.
+
+ The client and server then use the pre-master secret to independently
+ derive the master secret, which in turn is used for generating
+ session keys and for MAC computations. Thus, if the Kerberos option
+ is selected, the pre-master secret structure is the same as that used
+ in the RSA case; it is encrypted under the Kerberos session key and
+ sent to the TLS server along with the Kerberos credentials (see
+ Figure 2). The ticket and authenticator are encoded per RFC 1510
+ (ASN.1 encoding). Once the ClientKeyExchange message is received,
+ the server's secret key is used to unwrap the credentials and extract
+ the pre-master secret.
+
+ Note that a Kerberos authenticator is not required, since the master
+ secret derived by the client and server is seeded with a random value
+ passed in the server hello message, thus foiling replay attacks.
+ However, the authenticator may still prove useful for passing
+ authorization information and is thus allotted an optional field (see
+ Figure 2).
+
+ Lastly, the client and server exchange the finished messages to
+ complete the handshake. At this point we have achieved the
+ following:
+
+
+
+
+Medvinsky & Hur Standards Track [Page 4]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+ 1) A master secret, used to protect all subsequent communication, is
+ securely established.
+
+ 2) Mutual client-server authentication is achieved, since the TLS
+ server proves knowledge of the master secret in the finished
+ message.
+
+ Note that the Kerberos option fits in seamlessly, without adding any
+ new messages.
+
+4. Naming Conventions:
+
+ To obtain an appropriate service ticket, the TLS client must
+ determine the principal name of the TLS server. The Kerberos service
+ naming convention is used for this purpose, as follows:
+
+ host/MachineName@Realm
+ where:
+ - The literal, "host", follows the Kerberos convention when not
+ concerned about the protection domain on a particular machine.
+ - "MachineName" is the particular instance of the service.
+ - The Kerberos "Realm" is the domain name of the machine.
+
+5. Summary
+
+ The proposed Kerberos authentication option is added in exactly the
+ same manner as a new public key algorithm would be added to TLS.
+ Furthermore, it establishes the master secret in exactly the same
+ manner.
+
+6. Security Considerations
+
+ Kerberos ciphersuites are subject to the same security considerations
+ as the TLS protocol. In addition, just as a public key
+ implementation must take care to protect the private key (for example
+ the PIN for a smartcard), a Kerberos implementation must take care to
+ protect the long lived secret that is shared between the principal
+ and the KDC. In particular, a weak password may be subject to a
+ dictionary attack. In order to strengthen the initial authentication
+ to a KDC, an implementor may choose to utilize secondary
+ authentication via a token card, or one may utilize initial
+ authentication to the KDC based on public key cryptography (commonly
+ known as PKINIT - a product of the Common Authentication Technology
+ working group of the IETF).
+
+
+
+
+
+
+
+Medvinsky & Hur Standards Track [Page 5]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+7. Acknowledgements
+
+ We would like to thank Clifford Neuman for his invaluable comments on
+ earlier versions of this document.
+
+8. References
+
+ [1] Dierks, T. and C. Allen, "The TLS Protocol, Version 1.0", RFC
+ 2246, January 1999.
+
+ [2] Kohl J. and C. Neuman, "The Kerberos Network Authentication
+ Service (V5)", RFC 1510, September 1993.
+
+9. Authors' Addresses
+
+ Ari Medvinsky
+ Excite
+ 555 Broadway
+ Redwood City, CA 94063
+
+ Phone: +1 650 569 2119
+ EMail: amedvins@excitecorp.com
+ http://www.excite.com
+
+
+ Matthew Hur
+ CyberSafe Corporation
+ 1605 NW Sammamish Road
+ Issaquah WA 98027-5378
+
+ Phone: +1 425 391 6000
+ EMail: matt.hur@cybersafe.com
+ http://www.cybersafe.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Medvinsky & Hur Standards Track [Page 6]
+
+RFC 2712 Addition of Kerberos Cipher Suites to TLS October 1999
+
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Medvinsky & Hur Standards Track [Page 7]
+
diff --git a/standards/rfc2817.txt b/standards/rfc2817.txt
new file mode 100644
index 000000000..d7b7e703b
--- /dev/null
+++ b/standards/rfc2817.txt
@@ -0,0 +1,731 @@
+
+
+
+
+
+
+Network Working Group R. Khare
+Request for Comments: 2817 4K Associates / UC Irvine
+Updates: 2616 S. Lawrence
+Category: Standards Track Agranat Systems, Inc.
+ May 2000
+
+
+ Upgrading to TLS Within HTTP/1.1
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This memo explains how to use the Upgrade mechanism in HTTP/1.1 to
+ initiate Transport Layer Security (TLS) over an existing TCP
+ connection. This allows unsecured and secured HTTP traffic to share
+ the same well known port (in this case, http: at 80 rather than
+ https: at 443). It also enables "virtual hosting", so a single HTTP +
+ TLS server can disambiguate traffic intended for several hostnames at
+ a single IP address.
+
+ Since HTTP/1.1 [1] defines Upgrade as a hop-by-hop mechanism, this
+ memo also documents the HTTP CONNECT method for establishing end-to-
+ end tunnels across HTTP proxies. Finally, this memo establishes new
+ IANA registries for public HTTP status codes, as well as public or
+ private Upgrade product tokens.
+
+ This memo does NOT affect the current definition of the 'https' URI
+ scheme, which already defines a separate namespace
+ (http://example.org/ and https://example.org/ are not equivalent).
+
+
+
+
+
+
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 1]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+Table of Contents
+
+ 1. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.1 Requirements Terminology . . . . . . . . . . . . . . . . . . . 4
+ 3. Client Requested Upgrade to HTTP over TLS . . . . . . . . . . 4
+ 3.1 Optional Upgrade . . . . . . . . . . . . . . . . . . . . . . . 4
+ 3.2 Mandatory Upgrade . . . . . . . . . . . . . . . . . . . . . . 4
+ 3.3 Server Acceptance of Upgrade Request . . . . . . . . . . . . . 4
+ 4. Server Requested Upgrade to HTTP over TLS . . . . . . . . . . 5
+ 4.1 Optional Advertisement . . . . . . . . . . . . . . . . . . . . 5
+ 4.2 Mandatory Advertisement . . . . . . . . . . . . . . . . . . . 5
+ 5. Upgrade across Proxies . . . . . . . . . . . . . . . . . . . . 6
+ 5.1 Implications of Hop By Hop Upgrade . . . . . . . . . . . . . . 6
+ 5.2 Requesting a Tunnel with CONNECT . . . . . . . . . . . . . . . 6
+ 5.3 Establishing a Tunnel with CONNECT . . . . . . . . . . . . . . 7
+ 6. Rationale for the use of a 4xx (client error) Status Code . . 7
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8
+ 7.1 HTTP Status Code Registry . . . . . . . . . . . . . . . . . . 8
+ 7.2 HTTP Upgrade Token Registry . . . . . . . . . . . . . . . . . 8
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 9
+ 8.1 Implications for the https: URI Scheme . . . . . . . . . . . . 10
+ 8.2 Security Considerations for CONNECT . . . . . . . . . . . . . 10
+ References . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 11
+ A. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 12
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . 13
+
+1. Motivation
+
+ The historical practice of deploying HTTP over SSL3 [3] has
+ distinguished the combination from HTTP alone by a unique URI scheme
+ and the TCP port number. The scheme 'http' meant the HTTP protocol
+ alone on port 80, while 'https' meant the HTTP protocol over SSL on
+ port 443. Parallel well-known port numbers have similarly been
+ requested -- and in some cases, granted -- to distinguish between
+ secured and unsecured use of other application protocols (e.g.
+ snews, ftps). This approach effectively halves the number of
+ available well known ports.
+
+ At the Washington DC IETF meeting in December 1997, the Applications
+ Area Directors and the IESG reaffirmed that the practice of issuing
+ parallel "secure" port numbers should be deprecated. The HTTP/1.1
+ Upgrade mechanism can apply Transport Layer Security [6] to an open
+ HTTP connection.
+
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 2]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ In the nearly two years since, there has been broad acceptance of the
+ concept behind this proposal, but little interest in implementing
+ alternatives to port 443 for generic Web browsing. In fact, nothing
+ in this memo affects the current interpretation of https: URIs.
+ However, new application protocols built atop HTTP, such as the
+ Internet Printing Protocol [7], call for just such a mechanism in
+ order to move ahead in the IETF standards process.
+
+ The Upgrade mechanism also solves the "virtual hosting" problem.
+ Rather than allocating multiple IP addresses to a single host, an
+ HTTP/1.1 server will use the Host: header to disambiguate the
+ intended web service. As HTTP/1.1 usage has grown more prevalent,
+ more ISPs are offering name-based virtual hosting, thus delaying IP
+ address space exhaustion.
+
+ TLS (and SSL) have been hobbled by the same limitation as earlier
+ versions of HTTP: the initial handshake does not specify the intended
+ hostname, relying exclusively on the IP address. Using a cleartext
+ HTTP/1.1 Upgrade: preamble to the TLS handshake -- choosing the
+ certificates based on the initial Host: header -- will allow ISPs to
+ provide secure name-based virtual hosting as well.
+
+2. Introduction
+
+ TLS, a.k.a., SSL (Secure Sockets Layer), establishes a private end-
+ to-end connection, optionally including strong mutual authentication,
+ using a variety of cryptosystems. Initially, a handshake phase uses
+ three subprotocols to set up a record layer, authenticate endpoints,
+ set parameters, as well as report errors. Then, there is an ongoing
+ layered record protocol that handles encryption, compression, and
+ reassembly for the remainder of the connection. The latter is
+ intended to be completely transparent. For example, there is no
+ dependency between TLS's record markers and or certificates and
+ HTTP/1.1's chunked encoding or authentication.
+
+ Either the client or server can use the HTTP/1.1 [1] Upgrade
+ mechanism (Section 14.42) to indicate that a TLS-secured connection
+ is desired or necessary. This memo defines the "TLS/1.0" Upgrade
+ token, and a new HTTP Status Code, "426 Upgrade Required".
+
+ Section 3 and Section 4 describe the operation of a directly
+ connected client and server. Intermediate proxies must establish an
+ end-to-end tunnel before applying those operations, as explained in
+ Section 5.
+
+
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 3]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+2.1 Requirements Terminology
+
+ Keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT" and
+ "MAY" that appear in this document are to be interpreted as described
+ in RFC 2119 [11].
+
+3. Client Requested Upgrade to HTTP over TLS
+
+ When the client sends an HTTP/1.1 request with an Upgrade header
+ field containing the token "TLS/1.0", it is requesting the server to
+ complete the current HTTP/1.1 request after switching to TLS/1.0.
+
+3.1 Optional Upgrade
+
+ A client MAY offer to switch to secured operation during any clear
+ HTTP request when an unsecured response would be acceptable:
+
+ GET http://example.bank.com/acct_stat.html?749394889300 HTTP/1.1
+ Host: example.bank.com
+ Upgrade: TLS/1.0
+ Connection: Upgrade
+
+ In this case, the server MAY respond to the clear HTTP operation
+ normally, OR switch to secured operation (as detailed in the next
+ section).
+
+ Note that HTTP/1.1 [1] specifies "the upgrade keyword MUST be
+ supplied within a Connection header field (section 14.10) whenever
+ Upgrade is present in an HTTP/1.1 message".
+
+3.2 Mandatory Upgrade
+
+ If an unsecured response would be unacceptable, a client MUST send an
+ OPTIONS request first to complete the switch to TLS/1.0 (if
+ possible).
+
+ OPTIONS * HTTP/1.1
+ Host: example.bank.com
+ Upgrade: TLS/1.0
+ Connection: Upgrade
+
+3.3 Server Acceptance of Upgrade Request
+
+ As specified in HTTP/1.1 [1], if the server is prepared to initiate
+ the TLS handshake, it MUST send the intermediate "101 Switching
+ Protocol" and MUST include an Upgrade response header specifying the
+ tokens of the protocol stack it is switching to:
+
+
+
+
+Khare & Lawrence Standards Track [Page 4]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ HTTP/1.1 101 Switching Protocols
+ Upgrade: TLS/1.0, HTTP/1.1
+ Connection: Upgrade
+
+ Note that the protocol tokens listed in the Upgrade header of a 101
+ Switching Protocols response specify an ordered 'bottom-up' stack.
+
+ As specified in HTTP/1.1 [1], Section 10.1.2: "The server will
+ switch protocols to those defined by the response's Upgrade header
+ field immediately after the empty line which terminates the 101
+ response".
+
+ Once the TLS handshake completes successfully, the server MUST
+ continue with the response to the original request. Any TLS handshake
+ failure MUST lead to disconnection, per the TLS error alert
+ specification.
+
+4. Server Requested Upgrade to HTTP over TLS
+
+ The Upgrade response header field advertises possible protocol
+ upgrades a server MAY accept. In conjunction with the "426 Upgrade
+ Required" status code, a server can advertise the exact protocol
+ upgrade(s) that a client MUST accept to complete the request.
+
+4.1 Optional Advertisement
+
+ As specified in HTTP/1.1 [1], the server MAY include an Upgrade
+ header in any response other than 101 or 426 to indicate a
+ willingness to switch to any (combination) of the protocols listed.
+
+4.2 Mandatory Advertisement
+
+ A server MAY indicate that a client request can not be completed
+ without TLS using the "426 Upgrade Required" status code, which MUST
+ include an an Upgrade header field specifying the token of the
+ required TLS version.
+
+ HTTP/1.1 426 Upgrade Required
+ Upgrade: TLS/1.0, HTTP/1.1
+ Connection: Upgrade
+
+ The server SHOULD include a message body in the 426 response which
+ indicates in human readable form the reason for the error and
+ describes any alternative courses which may be available to the user.
+
+ Note that even if a client is willing to use TLS, it must use the
+ operations in Section 3 to proceed; the TLS handshake cannot begin
+ immediately after the 426 response.
+
+
+
+Khare & Lawrence Standards Track [Page 5]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+5. Upgrade across Proxies
+
+ As a hop-by-hop header, Upgrade is negotiated between each pair of
+ HTTP counterparties. If a User Agent sends a request with an Upgrade
+ header to a proxy, it is requesting a change to the protocol between
+ itself and the proxy, not an end-to-end change.
+
+ Since TLS, in particular, requires end-to-end connectivity to provide
+ authentication and prevent man-in-the-middle attacks, this memo
+ specifies the CONNECT method to establish a tunnel across proxies.
+
+ Once a tunnel is established, any of the operations in Section 3 can
+ be used to establish a TLS connection.
+
+5.1 Implications of Hop By Hop Upgrade
+
+ If an origin server receives an Upgrade header from a proxy and
+ responds with a 101 Switching Protocols response, it is changing the
+ protocol only on the connection between the proxy and itself.
+ Similarly, a proxy might return a 101 response to its client to
+ change the protocol on that connection independently of the protocols
+ it is using to communicate toward the origin server.
+
+ These scenarios also complicate diagnosis of a 426 response. Since
+ Upgrade is a hop-by-hop header, a proxy that does not recognize 426
+ might remove the accompanying Upgrade header and prevent the client
+ from determining the required protocol switch. If a client receives
+ a 426 status without an accompanying Upgrade header, it will need to
+ request an end to end tunnel connection as described in Section 5.2
+ and repeat the request in order to obtain the required upgrade
+ information.
+
+ This hop-by-hop definition of Upgrade was a deliberate choice. It
+ allows for incremental deployment on either side of proxies, and for
+ optimized protocols between cascaded proxies without the knowledge of
+ the parties that are not a part of the change.
+
+5.2 Requesting a Tunnel with CONNECT
+
+ A CONNECT method requests that a proxy establish a tunnel connection
+ on its behalf. The Request-URI portion of the Request-Line is always
+ an 'authority' as defined by URI Generic Syntax [2], which is to say
+ the host name and port number destination of the requested connection
+ separated by a colon:
+
+ CONNECT server.example.com:80 HTTP/1.1
+ Host: server.example.com:80
+
+
+
+
+Khare & Lawrence Standards Track [Page 6]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ Other HTTP mechanisms can be used normally with the CONNECT method --
+ except end-to-end protocol Upgrade requests, of course, since the
+ tunnel must be established first.
+
+ For example, proxy authentication might be used to establish the
+ authority to create a tunnel:
+
+ CONNECT server.example.com:80 HTTP/1.1
+ Host: server.example.com:80
+ Proxy-Authorization: basic aGVsbG86d29ybGQ=
+
+ Like any other pipelined HTTP/1.1 request, data to be tunneled may be
+ sent immediately after the blank line. The usual caveats also apply:
+ data may be discarded if the eventual response is negative, and the
+ connection may be reset with no response if more than one TCP segment
+ is outstanding.
+
+5.3 Establishing a Tunnel with CONNECT
+
+ Any successful (2xx) response to a CONNECT request indicates that the
+ proxy has established a connection to the requested host and port,
+ and has switched to tunneling the current connection to that server
+ connection.
+
+ It may be the case that the proxy itself can only reach the requested
+ origin server through another proxy. In this case, the first proxy
+ SHOULD make a CONNECT request of that next proxy, requesting a tunnel
+ to the authority. A proxy MUST NOT respond with any 2xx status code
+ unless it has either a direct or tunnel connection established to the
+ authority.
+
+ An origin server which receives a CONNECT request for itself MAY
+ respond with a 2xx status code to indicate that a connection is
+ established.
+
+ If at any point either one of the peers gets disconnected, any
+ outstanding data that came from that peer will be passed to the other
+ one, and after that also the other connection will be terminated by
+ the proxy. If there is outstanding data to that peer undelivered,
+ that data will be discarded.
+
+6. Rationale for the use of a 4xx (client error) Status Code
+
+ Reliable, interoperable negotiation of Upgrade features requires an
+ unambiguous failure signal. The 426 Upgrade Required status code
+ allows a server to definitively state the precise protocol extensions
+ a given resource must be served with.
+
+
+
+
+Khare & Lawrence Standards Track [Page 7]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ It might at first appear that the response should have been some form
+ of redirection (a 3xx code), by analogy to an old-style redirection
+ to an https: URI. User agents that do not understand Upgrade:
+ preclude this.
+
+ Suppose that a 3xx code had been assigned for "Upgrade Required"; a
+ user agent that did not recognize it would treat it as 300. It would
+ then properly look for a "Location" header in the response and
+ attempt to repeat the request at the URL in that header field. Since
+ it did not know to Upgrade to incorporate the TLS layer, it would at
+ best fail again at the new URL.
+
+7. IANA Considerations
+
+ IANA shall create registries for two name spaces, as described in BCP
+ 26 [10]:
+
+ o HTTP Status Codes
+ o HTTP Upgrade Tokens
+
+7.1 HTTP Status Code Registry
+
+ The HTTP Status Code Registry defines the name space for the Status-
+ Code token in the Status line of an HTTP response. The initial
+ values for this name space are those specified by:
+
+ 1. Draft Standard for HTTP/1.1 [1]
+ 2. Web Distributed Authoring and Versioning [4] [defines 420-424]
+ 3. WebDAV Advanced Collections [5] (Work in Progress) [defines 425]
+ 4. Section 6 [defines 426]
+
+ Values to be added to this name space SHOULD be subject to review in
+ the form of a standards track document within the IETF Applications
+ Area. Any such document SHOULD be traceable through statuses of
+ either 'Obsoletes' or 'Updates' to the Draft Standard for
+ HTTP/1.1 [1].
+
+7.2 HTTP Upgrade Token Registry
+
+ The HTTP Upgrade Token Registry defines the name space for product
+ tokens used to identify protocols in the Upgrade HTTP header field.
+ Each registered token should be associated with one or a set of
+ specifications, and with contact information.
+
+ The Draft Standard for HTTP/1.1 [1] specifies that these tokens obey
+ the production for 'product':
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 8]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ product = token ["/" product-version]
+ product-version = token
+
+ Registrations should be allowed on a First Come First Served basis as
+ described in BCP 26 [10]. These specifications need not be IETF
+ documents or be subject to IESG review, but should obey the following
+ rules:
+
+ 1. A token, once registered, stays registered forever.
+ 2. The registration MUST name a responsible party for the
+ registration.
+ 3. The registration MUST name a point of contact.
+ 4. The registration MAY name the documentation required for the
+ token.
+ 5. The responsible party MAY change the registration at any time.
+ The IANA will keep a record of all such changes, and make them
+ available upon request.
+ 6. The responsible party for the first registration of a "product"
+ token MUST approve later registrations of a "version" token
+ together with that "product" token before they can be registered.
+ 7. If absolutely required, the IESG MAY reassign the responsibility
+ for a token. This will normally only be used in the case when a
+ responsible party cannot be contacted.
+
+ This specification defines the protocol token "TLS/1.0" as the
+ identifier for the protocol specified by The TLS Protocol [6].
+
+ It is NOT required that specifications for upgrade tokens be made
+ publicly available, but the contact information for the registration
+ SHOULD be.
+
+8. Security Considerations
+
+ The potential for a man-in-the-middle attack (deleting the Upgrade
+ header) remains the same as current, mixed http/https practice:
+
+ o Removing the Upgrade header is similar to rewriting web pages to
+ change https:// links to http:// links.
+ o The risk is only present if the server is willing to vend such
+ information over both a secure and an insecure channel in the
+ first place.
+ o If the client knows for a fact that a server is TLS-compliant, it
+ can insist on it by only sending an Upgrade request with a no-op
+ method like OPTIONS.
+ o Finally, as the https: specification warns, "users should
+ carefully examine the certificate presented by the server to
+ determine if it meets their expectations".
+
+
+
+
+Khare & Lawrence Standards Track [Page 9]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ Furthermore, for clients that do not explicitly try to invoke TLS,
+ servers can use the Upgrade header in any response other than 101 or
+ 426 to advertise TLS compliance. Since TLS compliance should be
+ considered a feature of the server and not the resource at hand, it
+ should be sufficient to send it once, and let clients cache that
+ fact.
+
+8.1 Implications for the https: URI Scheme
+
+ While nothing in this memo affects the definition of the 'https' URI
+ scheme, widespread adoption of this mechanism for HyperText content
+ could use 'http' to identify both secure and non-secure resources.
+
+ The choice of what security characteristics are required on the
+ connection is left to the client and server. This allows either
+ party to use any information available in making this determination.
+ For example, user agents may rely on user preference settings or
+ information about the security of the network such as 'TLS required
+ on all POST operations not on my local net', or servers may apply
+ resource access rules such as 'the FORM on this page must be served
+ and submitted using TLS'.
+
+8.2 Security Considerations for CONNECT
+
+ A generic TCP tunnel is fraught with security risks. First, such
+ authorization should be limited to a small number of known ports.
+ The Upgrade: mechanism defined here only requires onward tunneling at
+ port 80. Second, since tunneled data is opaque to the proxy, there
+ are additional risks to tunneling to other well-known or reserved
+ ports. A putative HTTP client CONNECTing to port 25 could relay spam
+ via SMTP, for example.
+
+References
+
+ [1] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L.,
+ Leach, P. and T. Berners-Lee, "Hypertext Transfer Protocol --
+ HTTP/1.1", RFC 2616, June 1999.
+
+ [2] Berners-Lee, T., Fielding, R. and L. Masinter, "URI Generic
+ Syntax", RFC 2396, August 1998.
+
+ [3] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
+
+ [4] Goland, Y., Whitehead, E., Faizi, A., Carter, S. and D. Jensen,
+ "Web Distributed Authoring and Versioning", RFC 2518, February
+ 1999.
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 10]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+ [5] Slein, J., Whitehead, E.J., et al., "WebDAV Advanced Collections
+ Protocol", Work In Progress.
+
+ [6] Dierks, T. and C. Allen, "The TLS Protocol", RFC 2246, January
+ 1999.
+
+ [7] Herriot, R., Butler, S., Moore, P. and R. Turner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565, April
+ 1999.
+
+ [8] Luotonen, A., "Tunneling TCP based protocols through Web proxy
+ servers", Work In Progress. (Also available in: Luotonen, Ari.
+ Web Proxy Servers, Prentice-Hall, 1997 ISBN:0136806120.)
+
+ [9] Rose, M., "Writing I-Ds and RFCs using XML", RFC 2629, June
+ 1999.
+
+ [10] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
+
+ [11] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+Authors' Addresses
+
+ Rohit Khare
+ 4K Associates / UC Irvine
+ 3207 Palo Verde
+ Irvine, CA 92612
+ US
+
+ Phone: +1 626 806 7574
+ EMail: rohit@4K-associates.com
+ URI: http://www.4K-associates.com/
+
+
+ Scott Lawrence
+ Agranat Systems, Inc.
+ 5 Clocktower Place
+ Suite 400
+ Maynard, MA 01754
+ US
+
+ Phone: +1 978 461 0888
+ EMail: lawrence@agranat.com
+ URI: http://www.agranat.com/
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 11]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+Appendix A. Acknowledgments
+
+ The CONNECT method was originally described in a Work in Progress
+ titled, "Tunneling TCP based protocols through Web proxy servers",
+ [8] by Ari Luotonen of Netscape Communications Corporation. It was
+ widely implemented by HTTP proxies, but was never made a part of any
+ IETF Standards Track document. The method name CONNECT was reserved,
+ but not defined in [1].
+
+ The definition provided here is derived directly from that earlier
+ memo, with some editorial changes and conformance to the stylistic
+ conventions since established in other HTTP specifications.
+
+ Additional Thanks to:
+
+ o Paul Hoffman for his work on the STARTTLS command extension for
+ ESMTP.
+ o Roy Fielding for assistance with the rationale behind Upgrade:
+ and its interaction with OPTIONS.
+ o Eric Rescorla for his work on standardizing the existing https:
+ practice to compare with.
+ o Marshall Rose, for the xml2rfc document type description and tools
+ [9].
+ o Jim Whitehead, for sorting out the current range of available HTTP
+ status codes.
+ o Henrik Frystyk Nielsen, whose work on the Mandatory extension
+ mechanism pointed out a hop-by-hop Upgrade still requires
+ tunneling.
+ o Harald Alvestrand for improvements to the token registration
+ rules.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 12]
+
+RFC 2817 HTTP Upgrade to TLS May 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Khare & Lawrence Standards Track [Page 13]
+
diff --git a/standards/rfc2818.txt b/standards/rfc2818.txt
new file mode 100644
index 000000000..219a1c427
--- /dev/null
+++ b/standards/rfc2818.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group E. Rescorla
+Request for Comments: 2818 RTFM, Inc.
+Category: Informational May 2000
+
+
+ HTTP Over TLS
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This memo describes how to use TLS to secure HTTP connections over
+ the Internet. Current practice is to layer HTTP over SSL (the
+ predecessor to TLS), distinguishing secured traffic from insecure
+ traffic by the use of a different server port. This document
+ documents that practice using TLS. A companion document describes a
+ method for using HTTP/TLS over the same port as normal HTTP
+ [RFC2817].
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . 2
+ 1.1. Requirements Terminology . . . . . . . . . . . . . . . 2
+ 2. HTTP Over TLS . . . . . . . . . . . . . . . . . . . . . . 2
+ 2.1. Connection Initiation . . . . . . . . . . . . . . . . . 2
+ 2.2. Connection Closure . . . . . . . . . . . . . . . . . . 2
+ 2.2.1. Client Behavior . . . . . . . . . . . . . . . . . . . 3
+ 2.2.2. Server Behavior . . . . . . . . . . . . . . . . . . . 3
+ 2.3. Port Number . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.4. URI Format . . . . . . . . . . . . . . . . . . . . . . 4
+ 3. Endpoint Identification . . . . . . . . . . . . . . . . . 4
+ 3.1. Server Identity . . . . . . . . . . . . . . . . . . . . 4
+ 3.2. Client Identity . . . . . . . . . . . . . . . . . . . . 5
+ References . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ Security Considerations . . . . . . . . . . . . . . . . . . 6
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . 6
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . 7
+
+
+
+
+
+
+Rescorla Informational [Page 1]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+1. Introduction
+
+ HTTP [RFC2616] was originally used in the clear on the Internet.
+ However, increased use of HTTP for sensitive applications has
+ required security measures. SSL, and its successor TLS [RFC2246] were
+ designed to provide channel-oriented security. This document
+ describes how to use HTTP over TLS.
+
+1.1. Requirements Terminology
+
+ Keywords "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT" and
+ "MAY" that appear in this document are to be interpreted as described
+ in [RFC2119].
+
+2. HTTP Over TLS
+
+ Conceptually, HTTP/TLS is very simple. Simply use HTTP over TLS
+ precisely as you would use HTTP over TCP.
+
+2.1. Connection Initiation
+
+ The agent acting as the HTTP client should also act as the TLS
+ client. It should initiate a connection to the server on the
+ appropriate port and then send the TLS ClientHello to begin the TLS
+ handshake. When the TLS handshake has finished. The client may then
+ initiate the first HTTP request. All HTTP data MUST be sent as TLS
+ "application data". Normal HTTP behavior, including retained
+ connections should be followed.
+
+2.2. Connection Closure
+
+ TLS provides a facility for secure connection closure. When a valid
+ closure alert is received, an implementation can be assured that no
+ further data will be received on that connection. TLS
+ implementations MUST initiate an exchange of closure alerts before
+ closing a connection. A TLS implementation MAY, after sending a
+ closure alert, close the connection without waiting for the peer to
+ send its closure alert, generating an "incomplete close". Note that
+ an implementation which does this MAY choose to reuse the session.
+ This SHOULD only be done when the application knows (typically
+ through detecting HTTP message boundaries) that it has received all
+ the message data that it cares about.
+
+ As specified in [RFC2246], any implementation which receives a
+ connection close without first receiving a valid closure alert (a
+ "premature close") MUST NOT reuse that session. Note that a
+ premature close does not call into question the security of the data
+ already received, but simply indicates that subsequent data might
+
+
+
+Rescorla Informational [Page 2]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+ have been truncated. Because TLS is oblivious to HTTP
+ request/response boundaries, it is necessary to examine the HTTP data
+ itself (specifically the Content-Length header) to determine whether
+ the truncation occurred inside a message or between messages.
+
+2.2.1. Client Behavior
+
+ Because HTTP uses connection closure to signal end of server data,
+ client implementations MUST treat any premature closes as errors and
+ the data received as potentially truncated. While in some cases the
+ HTTP protocol allows the client to find out whether truncation took
+ place so that, if it received the complete reply, it may tolerate
+ such errors following the principle to "[be] strict when sending and
+ tolerant when receiving" [RFC1958], often truncation does not show in
+ the HTTP protocol data; two cases in particular deserve special note:
+
+ A HTTP response without a Content-Length header. Since data length
+ in this situation is signalled by connection close a premature
+ close generated by the server cannot be distinguished from a
+ spurious close generated by an attacker.
+
+ A HTTP response with a valid Content-Length header closed before
+ all data has been read. Because TLS does not provide document
+ oriented protection, it is impossible to determine whether the
+ server has miscomputed the Content-Length or an attacker has
+ truncated the connection.
+
+ There is one exception to the above rule. When encountering a
+ premature close, a client SHOULD treat as completed all requests for
+ which it has received as much data as specified in the Content-Length
+ header.
+
+ A client detecting an incomplete close SHOULD recover gracefully. It
+ MAY resume a TLS session closed in this fashion.
+
+ Clients MUST send a closure alert before closing the connection.
+ Clients which are unprepared to receive any more data MAY choose not
+ to wait for the server's closure alert and simply close the
+ connection, thus generating an incomplete close on the server side.
+
+2.2.2. Server Behavior
+
+ RFC 2616 permits an HTTP client to close the connection at any time,
+ and requires servers to recover gracefully. In particular, servers
+ SHOULD be prepared to receive an incomplete close from the client,
+ since the client can often determine when the end of server data is.
+ Servers SHOULD be willing to resume TLS sessions closed in this
+ fashion.
+
+
+
+Rescorla Informational [Page 3]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+ Implementation note: In HTTP implementations which do not use
+ persistent connections, the server ordinarily expects to be able to
+ signal end of data by closing the connection. When Content-Length is
+ used, however, the client may have already sent the closure alert and
+ dropped the connection.
+
+ Servers MUST attempt to initiate an exchange of closure alerts with
+ the client before closing the connection. Servers MAY close the
+ connection after sending the closure alert, thus generating an
+ incomplete close on the client side.
+
+2.3. Port Number
+
+ The first data that an HTTP server expects to receive from the client
+ is the Request-Line production. The first data that a TLS server (and
+ hence an HTTP/TLS server) expects to receive is the ClientHello.
+ Consequently, common practice has been to run HTTP/TLS over a
+ separate port in order to distinguish which protocol is being used.
+ When HTTP/TLS is being run over a TCP/IP connection, the default port
+ is 443. This does not preclude HTTP/TLS from being run over another
+ transport. TLS only presumes a reliable connection-oriented data
+ stream.
+
+2.4. URI Format
+
+ HTTP/TLS is differentiated from HTTP URIs by using the 'https'
+ protocol identifier in place of the 'http' protocol identifier. An
+ example URI specifying HTTP/TLS is:
+
+ https://www.example.com/~smith/home.html
+
+3. Endpoint Identification
+
+3.1. Server Identity
+
+ In general, HTTP/TLS requests are generated by dereferencing a URI.
+ As a consequence, the hostname for the server is known to the client.
+ If the hostname is available, the client MUST check it against the
+ server's identity as presented in the server's Certificate message,
+ in order to prevent man-in-the-middle attacks.
+
+ If the client has external information as to the expected identity of
+ the server, the hostname check MAY be omitted. (For instance, a
+ client may be connecting to a machine whose address and hostname are
+ dynamic but the client knows the certificate that the server will
+ present.) In such cases, it is important to narrow the scope of
+ acceptable certificates as much as possible in order to prevent man
+
+
+
+
+Rescorla Informational [Page 4]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+ in the middle attacks. In special cases, it may be appropriate for
+ the client to simply ignore the server's identity, but it must be
+ understood that this leaves the connection open to active attack.
+
+ If a subjectAltName extension of type dNSName is present, that MUST
+ be used as the identity. Otherwise, the (most specific) Common Name
+ field in the Subject field of the certificate MUST be used. Although
+ the use of the Common Name is existing practice, it is deprecated and
+ Certification Authorities are encouraged to use the dNSName instead.
+
+ Matching is performed using the matching rules specified by
+ [RFC2459]. If more than one identity of a given type is present in
+ the certificate (e.g., more than one dNSName name, a match in any one
+ of the set is considered acceptable.) Names may contain the wildcard
+ character * which is considered to match any single domain name
+ component or component fragment. E.g., *.a.com matches foo.a.com but
+ not bar.foo.a.com. f*.com matches foo.com but not bar.com.
+
+ In some cases, the URI is specified as an IP address rather than a
+ hostname. In this case, the iPAddress subjectAltName must be present
+ in the certificate and must exactly match the IP in the URI.
+
+ If the hostname does not match the identity in the certificate, user
+ oriented clients MUST either notify the user (clients MAY give the
+ user the opportunity to continue with the connection in any case) or
+ terminate the connection with a bad certificate error. Automated
+ clients MUST log the error to an appropriate audit log (if available)
+ and SHOULD terminate the connection (with a bad certificate error).
+ Automated clients MAY provide a configuration setting that disables
+ this check, but MUST provide a setting which enables it.
+
+ Note that in many cases the URI itself comes from an untrusted
+ source. The above-described check provides no protection against
+ attacks where this source is compromised. For example, if the URI was
+ obtained by clicking on an HTML page which was itself obtained
+ without using HTTP/TLS, a man in the middle could have replaced the
+ URI. In order to prevent this form of attack, users should carefully
+ examine the certificate presented by the server to determine if it
+ meets their expectations.
+
+3.2. Client Identity
+
+ Typically, the server has no external knowledge of what the client's
+ identity ought to be and so checks (other than that the client has a
+ certificate chain rooted in an appropriate CA) are not possible. If a
+ server has such knowledge (typically from some source external to
+ HTTP or TLS) it SHOULD check the identity as described above.
+
+
+
+
+Rescorla Informational [Page 5]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+References
+
+ [RFC2459] Housley, R., Ford, W., Polk, W. and D. Solo, "Internet
+ Public Key Infrastructure: Part I: X.509 Certificate and
+ CRL Profile", RFC 2459, January 1999.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter,
+ L., Leach, P. and T. Berners-Lee, "Hypertext Transfer
+ Protocol, HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC2119] Bradner, S., "Key Words for use in RFCs to indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol", RFC 2246,
+ January 1999.
+
+ [RFC2817] Khare, R. and S. Lawrence, "Upgrading to TLS Within
+ HTTP/1.1", RFC 2817, May 2000.
+
+Security Considerations
+
+ This entire document is about security.
+
+Author's Address
+
+ Eric Rescorla
+ RTFM, Inc.
+ 30 Newell Road, #16
+ East Palo Alto, CA 94303
+
+ Phone: (650) 328-8631
+ EMail: ekr@rtfm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rescorla Informational [Page 6]
+
+RFC 2818 HTTP Over TLS May 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rescorla Informational [Page 7]
+
diff --git a/standards/rfc2821.txt b/standards/rfc2821.txt
new file mode 100644
index 000000000..0eac91188
--- /dev/null
+++ b/standards/rfc2821.txt
@@ -0,0 +1,4427 @@
+
+
+
+
+
+
+Network Working Group J. Klensin, Editor
+Request for Comments: 2821 AT&T Laboratories
+Obsoletes: 821, 974, 1869 April 2001
+Updates: 1123
+Category: Standards Track
+
+
+ Simple Mail Transfer Protocol
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document is a self-contained specification of the basic protocol
+ for the Internet electronic mail transport. It consolidates, updates
+ and clarifies, but doesn't add new or change existing functionality
+ of the following:
+
+ - the original SMTP (Simple Mail Transfer Protocol) specification of
+ RFC 821 [30],
+
+ - domain name system requirements and implications for mail
+ transport from RFC 1035 [22] and RFC 974 [27],
+
+ - the clarifications and applicability statements in RFC 1123 [2],
+ and
+
+ - material drawn from the SMTP Extension mechanisms [19].
+
+ It obsoletes RFC 821, RFC 974, and updates RFC 1123 (replaces the
+ mail transport materials of RFC 1123). However, RFC 821 specifies
+ some features that were not in significant use in the Internet by the
+ mid-1990s and (in appendices) some additional transport models.
+ Those sections are omitted here in the interest of clarity and
+ brevity; readers needing them should refer to RFC 821.
+
+
+
+
+
+
+Klensin Standards Track [Page 1]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ It also includes some additional material from RFC 1123 that required
+ amplification. This material has been identified in multiple ways,
+ mostly by tracking flaming on various lists and newsgroups and
+ problems of unusual readings or interpretations that have appeared as
+ the SMTP extensions have been deployed. Where this specification
+ moves beyond consolidation and actually differs from earlier
+ documents, it supersedes them technically as well as textually.
+
+ Although SMTP was designed as a mail transport and delivery protocol,
+ this specification also contains information that is important to its
+ use as a 'mail submission' protocol, as recommended for POP [3, 26]
+ and IMAP [6]. Additional submission issues are discussed in RFC 2476
+ [15].
+
+ Section 2.3 provides definitions of terms specific to this document.
+ Except when the historical terminology is necessary for clarity, this
+ document uses the current 'client' and 'server' terminology to
+ identify the sending and receiving SMTP processes, respectively.
+
+ A companion document [32] discusses message headers, message bodies
+ and formats and structures for them, and their relationship.
+
+Table of Contents
+
+ 1. Introduction .................................................. 4
+ 2. The SMTP Model ................................................ 5
+ 2.1 Basic Structure .............................................. 5
+ 2.2 The Extension Model .......................................... 7
+ 2.2.1 Background ................................................. 7
+ 2.2.2 Definition and Registration of Extensions .................. 8
+ 2.3 Terminology .................................................. 9
+ 2.3.1 Mail Objects ............................................... 10
+ 2.3.2 Senders and Receivers ...................................... 10
+ 2.3.3 Mail Agents and Message Stores ............................. 10
+ 2.3.4 Host ....................................................... 11
+ 2.3.5 Domain ..................................................... 11
+ 2.3.6 Buffer and State Table ..................................... 11
+ 2.3.7 Lines ...................................................... 12
+ 2.3.8 Originator, Delivery, Relay, and Gateway Systems ........... 12
+ 2.3.9 Message Content and Mail Data .............................. 13
+ 2.3.10 Mailbox and Address ....................................... 13
+ 2.3.11 Reply ..................................................... 13
+ 2.4 General Syntax Principles and Transaction Model .............. 13
+ 3. The SMTP Procedures: An Overview .............................. 15
+ 3.1 Session Initiation ........................................... 15
+ 3.2 Client Initiation ............................................ 16
+ 3.3 Mail Transactions ............................................ 16
+ 3.4 Forwarding for Address Correction or Updating ................ 19
+
+
+
+Klensin Standards Track [Page 2]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ 3.5 Commands for Debugging Addresses ............................. 20
+ 3.5.1 Overview ................................................... 20
+ 3.5.2 VRFY Normal Response ....................................... 22
+ 3.5.3 Meaning of VRFY or EXPN Success Response ................... 22
+ 3.5.4 Semantics and Applications of EXPN ......................... 23
+ 3.6 Domains ...................................................... 23
+ 3.7 Relaying ..................................................... 24
+ 3.8 Mail Gatewaying .............................................. 25
+ 3.8.1 Header Fields in Gatewaying ................................ 26
+ 3.8.2 Received Lines in Gatewaying ............................... 26
+ 3.8.3 Addresses in Gatewaying .................................... 26
+ 3.8.4 Other Header Fields in Gatewaying .......................... 27
+ 3.8.5 Envelopes in Gatewaying .................................... 27
+ 3.9 Terminating Sessions and Connections ......................... 27
+ 3.10 Mailing Lists and Aliases ................................... 28
+ 3.10.1 Alias ..................................................... 28
+ 3.10.2 List ...................................................... 28
+ 4. The SMTP Specifications ....................................... 29
+ 4.1 SMTP Commands ................................................ 29
+ 4.1.1 Command Semantics and Syntax ............................... 29
+ 4.1.1.1 Extended HELLO (EHLO) or HELLO (HELO) ................... 29
+ 4.1.1.2 MAIL (MAIL) .............................................. 31
+ 4.1.1.3 RECIPIENT (RCPT) ......................................... 31
+ 4.1.1.4 DATA (DATA) .............................................. 33
+ 4.1.1.5 RESET (RSET) ............................................. 34
+ 4.1.1.6 VERIFY (VRFY) ............................................ 35
+ 4.1.1.7 EXPAND (EXPN) ............................................ 35
+ 4.1.1.8 HELP (HELP) .............................................. 35
+ 4.1.1.9 NOOP (NOOP) .............................................. 35
+ 4.1.1.10 QUIT (QUIT) ............................................. 36
+ 4.1.2 Command Argument Syntax .................................... 36
+ 4.1.3 Address Literals ........................................... 38
+ 4.1.4 Order of Commands .......................................... 39
+ 4.1.5 Private-use Commands ....................................... 40
+ 4.2 SMTP Replies ................................................ 40
+ 4.2.1 Reply Code Severities and Theory ........................... 42
+ 4.2.2 Reply Codes by Function Groups ............................. 44
+ 4.2.3 Reply Codes in Numeric Order .............................. 45
+ 4.2.4 Reply Code 502 ............................................. 46
+ 4.2.5 Reply Codes After DATA and the Subsequent <CRLF>.<CRLF> .... 46
+ 4.3 Sequencing of Commands and Replies ........................... 47
+ 4.3.1 Sequencing Overview ........................................ 47
+ 4.3.2 Command-Reply Sequences .................................... 48
+ 4.4 Trace Information ............................................ 49
+ 4.5 Additional Implementation Issues ............................. 53
+ 4.5.1 Minimum Implementation ..................................... 53
+ 4.5.2 Transparency ............................................... 53
+ 4.5.3 Sizes and Timeouts ......................................... 54
+
+
+
+Klensin Standards Track [Page 3]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ 4.5.3.1 Size limits and minimums ................................. 54
+ 4.5.3.2 Timeouts ................................................. 56
+ 4.5.4 Retry Strategies ........................................... 57
+ 4.5.4.1 Sending Strategy ......................................... 58
+ 4.5.4.2 Receiving Strategy ....................................... 59
+ 4.5.5 Messages with a null reverse-path .......................... 59
+ 5. Address Resolution and Mail Handling .......................... 60
+ 6. Problem Detection and Handling ................................ 62
+ 6.1 Reliable Delivery and Replies by Email ....................... 62
+ 6.2 Loop Detection ............................................... 63
+ 6.3 Compensating for Irregularities .............................. 63
+ 7. Security Considerations ....................................... 64
+ 7.1 Mail Security and Spoofing ................................... 64
+ 7.2 "Blind" Copies ............................................... 65
+ 7.3 VRFY, EXPN, and Security ..................................... 65
+ 7.4 Information Disclosure in Announcements ...................... 66
+ 7.5 Information Disclosure in Trace Fields ....................... 66
+ 7.6 Information Disclosure in Message Forwarding ................. 67
+ 7.7 Scope of Operation of SMTP Servers ........................... 67
+ 8. IANA Considerations ........................................... 67
+ 9. References .................................................... 68
+ 10. Editor's Address ............................................. 70
+ 11. Acknowledgments .............................................. 70
+ Appendices ....................................................... 71
+ A. TCP Transport Service ......................................... 71
+ B. Generating SMTP Commands from RFC 822 Headers ................. 71
+ C. Source Routes ................................................. 72
+ D. Scenarios ..................................................... 73
+ E. Other Gateway Issues .......................................... 76
+ F. Deprecated Features of RFC 821 ................................ 76
+ Full Copyright Statement ......................................... 79
+
+1. Introduction
+
+ The objective of the Simple Mail Transfer Protocol (SMTP) is to
+ transfer mail reliably and efficiently.
+
+ SMTP is independent of the particular transmission subsystem and
+ requires only a reliable ordered data stream channel. While this
+ document specifically discusses transport over TCP, other transports
+ are possible. Appendices to RFC 821 describe some of them.
+
+ An important feature of SMTP is its capability to transport mail
+ across networks, usually referred to as "SMTP mail relaying" (see
+ section 3.8). A network consists of the mutually-TCP-accessible
+ hosts on the public Internet, the mutually-TCP-accessible hosts on a
+ firewall-isolated TCP/IP Intranet, or hosts in some other LAN or WAN
+ environment utilizing a non-TCP transport-level protocol. Using
+
+
+
+Klensin Standards Track [Page 4]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ SMTP, a process can transfer mail to another process on the same
+ network or to some other network via a relay or gateway process
+ accessible to both networks.
+
+ In this way, a mail message may pass through a number of intermediate
+ relay or gateway hosts on its path from sender to ultimate recipient.
+ The Mail eXchanger mechanisms of the domain name system [22, 27] (and
+ section 5 of this document) are used to identify the appropriate
+ next-hop destination for a message being transported.
+
+2. The SMTP Model
+
+2.1 Basic Structure
+
+ The SMTP design can be pictured as:
+
+ +----------+ +----------+
+ +------+ | | | |
+ | User |<-->| | SMTP | |
+ +------+ | Client- |Commands/Replies| Server- |
+ +------+ | SMTP |<-------------->| SMTP | +------+
+ | File |<-->| | and Mail | |<-->| File |
+ |System| | | | | |System|
+ +------+ +----------+ +----------+ +------+
+ SMTP client SMTP server
+
+ When an SMTP client has a message to transmit, it establishes a two-
+ way transmission channel to an SMTP server. The responsibility of an
+ SMTP client is to transfer mail messages to one or more SMTP servers,
+ or report its failure to do so.
+
+ The means by which a mail message is presented to an SMTP client, and
+ how that client determines the domain name(s) to which mail messages
+ are to be transferred is a local matter, and is not addressed by this
+ document. In some cases, the domain name(s) transferred to, or
+ determined by, an SMTP client will identify the final destination(s)
+ of the mail message. In other cases, common with SMTP clients
+ associated with implementations of the POP [3, 26] or IMAP [6]
+ protocols, or when the SMTP client is inside an isolated transport
+ service environment, the domain name determined will identify an
+ intermediate destination through which all mail messages are to be
+ relayed. SMTP clients that transfer all traffic, regardless of the
+ target domain names associated with the individual messages, or that
+ do not maintain queues for retrying message transmissions that
+ initially cannot be completed, may otherwise conform to this
+ specification but are not considered fully-capable. Fully-capable
+ SMTP implementations, including the relays used by these less capable
+
+
+
+
+Klensin Standards Track [Page 5]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ ones, and their destinations, are expected to support all of the
+ queuing, retrying, and alternate address functions discussed in this
+ specification.
+
+ The means by which an SMTP client, once it has determined a target
+ domain name, determines the identity of an SMTP server to which a
+ copy of a message is to be transferred, and then performs that
+ transfer, is covered by this document. To effect a mail transfer to
+ an SMTP server, an SMTP client establishes a two-way transmission
+ channel to that SMTP server. An SMTP client determines the address
+ of an appropriate host running an SMTP server by resolving a
+ destination domain name to either an intermediate Mail eXchanger host
+ or a final target host.
+
+ An SMTP server may be either the ultimate destination or an
+ intermediate "relay" (that is, it may assume the role of an SMTP
+ client after receiving the message) or "gateway" (that is, it may
+ transport the message further using some protocol other than SMTP).
+ SMTP commands are generated by the SMTP client and sent to the SMTP
+ server. SMTP replies are sent from the SMTP server to the SMTP
+ client in response to the commands.
+
+ In other words, message transfer can occur in a single connection
+ between the original SMTP-sender and the final SMTP-recipient, or can
+ occur in a series of hops through intermediary systems. In either
+ case, a formal handoff of responsibility for the message occurs: the
+ protocol requires that a server accept responsibility for either
+ delivering a message or properly reporting the failure to do so.
+
+ Once the transmission channel is established and initial handshaking
+ completed, the SMTP client normally initiates a mail transaction.
+ Such a transaction consists of a series of commands to specify the
+ originator and destination of the mail and transmission of the
+ message content (including any headers or other structure) itself.
+ When the same message is sent to multiple recipients, this protocol
+ encourages the transmission of only one copy of the data for all
+ recipients at the same destination (or intermediate relay) host.
+
+ The server responds to each command with a reply; replies may
+ indicate that the command was accepted, that additional commands are
+ expected, or that a temporary or permanent error condition exists.
+ Commands specifying the sender or recipients may include server-
+ permitted SMTP service extension requests as discussed in section
+ 2.2. The dialog is purposely lock-step, one-at-a-time, although this
+ can be modified by mutually-agreed extension requests such as command
+ pipelining [13].
+
+
+
+
+
+Klensin Standards Track [Page 6]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ Once a given mail message has been transmitted, the client may either
+ request that the connection be shut down or may initiate other mail
+ transactions. In addition, an SMTP client may use a connection to an
+ SMTP server for ancillary services such as verification of email
+ addresses or retrieval of mailing list subscriber addresses.
+
+ As suggested above, this protocol provides mechanisms for the
+ transmission of mail. This transmission normally occurs directly
+ from the sending user's host to the receiving user's host when the
+ two hosts are connected to the same transport service. When they are
+ not connected to the same transport service, transmission occurs via
+ one or more relay SMTP servers. An intermediate host that acts as
+ either an SMTP relay or as a gateway into some other transmission
+ environment is usually selected through the use of the domain name
+ service (DNS) Mail eXchanger mechanism.
+
+ Usually, intermediate hosts are determined via the DNS MX record, not
+ by explicit "source" routing (see section 5 and appendices C and
+ F.2).
+
+2.2 The Extension Model
+
+2.2.1 Background
+
+ In an effort that started in 1990, approximately a decade after RFC
+ 821 was completed, the protocol was modified with a "service
+ extensions" model that permits the client and server to agree to
+ utilize shared functionality beyond the original SMTP requirements.
+ The SMTP extension mechanism defines a means whereby an extended SMTP
+ client and server may recognize each other, and the server can inform
+ the client as to the service extensions that it supports.
+
+ Contemporary SMTP implementations MUST support the basic extension
+ mechanisms. For instance, servers MUST support the EHLO command even
+ if they do not implement any specific extensions and clients SHOULD
+ preferentially utilize EHLO rather than HELO. (However, for
+ compatibility with older conforming implementations, SMTP clients and
+ servers MUST support the original HELO mechanisms as a fallback.)
+ Unless the different characteristics of HELO must be identified for
+ interoperability purposes, this document discusses only EHLO.
+
+ SMTP is widely deployed and high-quality implementations have proven
+ to be very robust. However, the Internet community now considers
+ some services to be important that were not anticipated when the
+ protocol was first designed. If support for those services is to be
+ added, it must be done in a way that permits older implementations to
+ continue working acceptably. The extension framework consists of:
+
+
+
+
+Klensin Standards Track [Page 7]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ - The SMTP command EHLO, superseding the earlier HELO,
+
+ - a registry of SMTP service extensions,
+
+ - additional parameters to the SMTP MAIL and RCPT commands, and
+
+ - optional replacements for commands defined in this protocol, such
+ as for DATA in non-ASCII transmissions [33].
+
+ SMTP's strength comes primarily from its simplicity. Experience with
+ many protocols has shown that protocols with few options tend towards
+ ubiquity, whereas protocols with many options tend towards obscurity.
+
+ Each and every extension, regardless of its benefits, must be
+ carefully scrutinized with respect to its implementation, deployment,
+ and interoperability costs. In many cases, the cost of extending the
+ SMTP service will likely outweigh the benefit.
+
+2.2.2 Definition and Registration of Extensions
+
+ The IANA maintains a registry of SMTP service extensions. A
+ corresponding EHLO keyword value is associated with each extension.
+ Each service extension registered with the IANA must be defined in a
+ formal standards-track or IESG-approved experimental protocol
+ document. The definition must include:
+
+ - the textual name of the SMTP service extension;
+
+ - the EHLO keyword value associated with the extension;
+
+ - the syntax and possible values of parameters associated with the
+ EHLO keyword value;
+
+ - any additional SMTP verbs associated with the extension
+ (additional verbs will usually be, but are not required to be, the
+ same as the EHLO keyword value);
+
+ - any new parameters the extension associates with the MAIL or RCPT
+ verbs;
+
+ - a description of how support for the extension affects the
+ behavior of a server and client SMTP; and,
+
+ - the increment by which the extension is increasing the maximum
+ length of the commands MAIL and/or RCPT, over that specified in
+ this standard.
+
+
+
+
+
+Klensin Standards Track [Page 8]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ In addition, any EHLO keyword value starting with an upper or lower
+ case "X" refers to a local SMTP service extension used exclusively
+ through bilateral agreement. Keywords beginning with "X" MUST NOT be
+ used in a registered service extension. Conversely, keyword values
+ presented in the EHLO response that do not begin with "X" MUST
+ correspond to a standard, standards-track, or IESG-approved
+ experimental SMTP service extension registered with IANA. A
+ conforming server MUST NOT offer non-"X"-prefixed keyword values that
+ are not described in a registered extension.
+
+ Additional verbs and parameter names are bound by the same rules as
+ EHLO keywords; specifically, verbs beginning with "X" are local
+ extensions that may not be registered or standardized. Conversely,
+ verbs not beginning with "X" must always be registered.
+
+2.3 Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described below.
+
+ 1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that
+ the definition is an absolute requirement of the specification.
+
+ 2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the
+ definition is an absolute prohibition of the specification.
+
+ 3. SHOULD This word, or the adjective "RECOMMENDED", mean that
+ there may exist valid reasons in particular circumstances to
+ ignore a particular item, but the full implications must be
+ understood and carefully weighed before choosing a different
+ course.
+
+ 4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean
+ that there may exist valid reasons in particular circumstances
+ when the particular behavior is acceptable or even useful, but the
+ full implications should be understood and the case carefully
+ weighed before implementing any behavior described with this
+ label.
+
+ 5. MAY This word, or the adjective "OPTIONAL", mean that an item is
+ truly optional. One vendor may choose to include the item because
+ a particular marketplace requires it or because the vendor feels
+ that it enhances the product while another vendor may omit the
+ same item. An implementation which does not include a particular
+ option MUST be prepared to interoperate with another
+ implementation which does include the option, though perhaps with
+ reduced functionality. In the same vein an implementation which
+
+
+
+Klensin Standards Track [Page 9]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ does include a particular option MUST be prepared to interoperate
+ with another implementation which does not include the option
+ (except, of course, for the feature the option provides.)
+
+2.3.1 Mail Objects
+
+ SMTP transports a mail object. A mail object contains an envelope
+ and content.
+
+ The SMTP envelope is sent as a series of SMTP protocol units
+ (described in section 3). It consists of an originator address (to
+ which error reports should be directed); one or more recipient
+ addresses; and optional protocol extension material. Historically,
+ variations on the recipient address specification command (RCPT TO)
+ could be used to specify alternate delivery modes, such as immediate
+ display; those variations have now been deprecated (see appendix F,
+ section F.6).
+
+ The SMTP content is sent in the SMTP DATA protocol unit and has two
+ parts: the headers and the body. If the content conforms to other
+ contemporary standards, the headers form a collection of field/value
+ pairs structured as in the message format specification [32]; the
+ body, if structured, is defined according to MIME [12]. The content
+ is textual in nature, expressed using the US-ASCII repertoire [1].
+ Although SMTP extensions (such as "8BITMIME" [20]) may relax this
+ restriction for the content body, the content headers are always
+ encoded using the US-ASCII repertoire. A MIME extension [23] defines
+ an algorithm for representing header values outside the US-ASCII
+ repertoire, while still encoding them using the US-ASCII repertoire.
+
+2.3.2 Senders and Receivers
+
+ In RFC 821, the two hosts participating in an SMTP transaction were
+ described as the "SMTP-sender" and "SMTP-receiver". This document
+ has been changed to reflect current industry terminology and hence
+ refers to them as the "SMTP client" (or sometimes just "the client")
+ and "SMTP server" (or just "the server"), respectively. Since a
+ given host may act both as server and client in a relay situation,
+ "receiver" and "sender" terminology is still used where needed for
+ clarity.
+
+2.3.3 Mail Agents and Message Stores
+
+ Additional mail system terminology became common after RFC 821 was
+ published and, where convenient, is used in this specification. In
+ particular, SMTP servers and clients provide a mail transport service
+ and therefore act as "Mail Transfer Agents" (MTAs). "Mail User
+ Agents" (MUAs or UAs) are normally thought of as the sources and
+
+
+
+Klensin Standards Track [Page 10]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ targets of mail. At the source, an MUA might collect mail to be
+ transmitted from a user and hand it off to an MTA; the final
+ ("delivery") MTA would be thought of as handing the mail off to an
+ MUA (or at least transferring responsibility to it, e.g., by
+ depositing the message in a "message store"). However, while these
+ terms are used with at least the appearance of great precision in
+ other environments, the implied boundaries between MUAs and MTAs
+ often do not accurately match common, and conforming, practices with
+ Internet mail. Hence, the reader should be cautious about inferring
+ the strong relationships and responsibilities that might be implied
+ if these terms were used elsewhere.
+
+2.3.4 Host
+
+ For the purposes of this specification, a host is a computer system
+ attached to the Internet (or, in some cases, to a private TCP/IP
+ network) and supporting the SMTP protocol. Hosts are known by names
+ (see "domain"); identifying them by numerical address is discouraged.
+
+2.3.5 Domain
+
+ A domain (or domain name) consists of one or more dot-separated
+ components. These components ("labels" in DNS terminology [22]) are
+ restricted for SMTP purposes to consist of a sequence of letters,
+ digits, and hyphens drawn from the ASCII character set [1]. Domain
+ names are used as names of hosts and of other entities in the domain
+ name hierarchy. For example, a domain may refer to an alias (label
+ of a CNAME RR) or the label of Mail eXchanger records to be used to
+ deliver mail instead of representing a host name. See [22] and
+ section 5 of this specification.
+
+ The domain name, as described in this document and in [22], is the
+ entire, fully-qualified name (often referred to as an "FQDN"). A
+ domain name that is not in FQDN form is no more than a local alias.
+ Local aliases MUST NOT appear in any SMTP transaction.
+
+2.3.6 Buffer and State Table
+
+ SMTP sessions are stateful, with both parties carefully maintaining a
+ common view of the current state. In this document we model this
+ state by a virtual "buffer" and a "state table" on the server which
+ may be used by the client to, for example, "clear the buffer" or
+ "reset the state table," causing the information in the buffer to be
+ discarded and the state to be returned to some previous state.
+
+
+
+
+
+
+
+Klensin Standards Track [Page 11]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+2.3.7 Lines
+
+ SMTP commands and, unless altered by a service extension, message
+ data, are transmitted in "lines". Lines consist of zero or more data
+ characters terminated by the sequence ASCII character "CR" (hex value
+ 0D) followed immediately by ASCII character "LF" (hex value 0A).
+ This termination sequence is denoted as <CRLF> in this document.
+ Conforming implementations MUST NOT recognize or generate any other
+ character or character sequence as a line terminator. Limits MAY be
+ imposed on line lengths by servers (see section 4.5.3).
+
+ In addition, the appearance of "bare" "CR" or "LF" characters in text
+ (i.e., either without the other) has a long history of causing
+ problems in mail implementations and applications that use the mail
+ system as a tool. SMTP client implementations MUST NOT transmit
+ these characters except when they are intended as line terminators
+ and then MUST, as indicated above, transmit them only as a <CRLF>
+ sequence.
+
+2.3.8 Originator, Delivery, Relay, and Gateway Systems
+
+ This specification makes a distinction among four types of SMTP
+ systems, based on the role those systems play in transmitting
+ electronic mail. An "originating" system (sometimes called an SMTP
+ originator) introduces mail into the Internet or, more generally,
+ into a transport service environment. A "delivery" SMTP system is
+ one that receives mail from a transport service environment and
+ passes it to a mail user agent or deposits it in a message store
+ which a mail user agent is expected to subsequently access. A
+ "relay" SMTP system (usually referred to just as a "relay") receives
+ mail from an SMTP client and transmits it, without modification to
+ the message data other than adding trace information, to another SMTP
+ server for further relaying or for delivery.
+
+ A "gateway" SMTP system (usually referred to just as a "gateway")
+ receives mail from a client system in one transport environment and
+ transmits it to a server system in another transport environment.
+ Differences in protocols or message semantics between the transport
+ environments on either side of a gateway may require that the gateway
+ system perform transformations to the message that are not permitted
+ to SMTP relay systems. For the purposes of this specification,
+ firewalls that rewrite addresses should be considered as gateways,
+ even if SMTP is used on both sides of them (see [11]).
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 12]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+2.3.9 Message Content and Mail Data
+
+ The terms "message content" and "mail data" are used interchangeably
+ in this document to describe the material transmitted after the DATA
+ command is accepted and before the end of data indication is
+ transmitted. Message content includes message headers and the
+ possibly-structured message body. The MIME specification [12]
+ provides the standard mechanisms for structured message bodies.
+
+2.3.10 Mailbox and Address
+
+ As used in this specification, an "address" is a character string
+ that identifies a user to whom mail will be sent or a location into
+ which mail will be deposited. The term "mailbox" refers to that
+ depository. The two terms are typically used interchangeably unless
+ the distinction between the location in which mail is placed (the
+ mailbox) and a reference to it (the address) is important. An
+ address normally consists of user and domain specifications. The
+ standard mailbox naming convention is defined to be "local-
+ part@domain": contemporary usage permits a much broader set of
+ applications than simple "user names". Consequently, and due to a
+ long history of problems when intermediate hosts have attempted to
+ optimize transport by modifying them, the local-part MUST be
+ interpreted and assigned semantics only by the host specified in the
+ domain part of the address.
+
+2.3.11 Reply
+
+ An SMTP reply is an acknowledgment (positive or negative) sent from
+ receiver to sender via the transmission channel in response to a
+ command. The general form of a reply is a numeric completion code
+ (indicating failure or success) usually followed by a text string.
+ The codes are for use by programs and the text is usually intended
+ for human users. Recent work [34] has specified further structuring
+ of the reply strings, including the use of supplemental and more
+ specific completion codes.
+
+2.4 General Syntax Principles and Transaction Model
+
+ SMTP commands and replies have a rigid syntax. All commands begin
+ with a command verb. All Replies begin with a three digit numeric
+ code. In some commands and replies, arguments MUST follow the verb
+ or reply code. Some commands do not accept arguments (after the
+ verb), and some reply codes are followed, sometimes optionally, by
+ free form text. In both cases, where text appears, it is separated
+ from the verb or reply code by a space character. Complete
+ definitions of commands and replies appear in section 4.
+
+
+
+
+Klensin Standards Track [Page 13]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ Verbs and argument values (e.g., "TO:" or "to:" in the RCPT command
+ and extension name keywords) are not case sensitive, with the sole
+ exception in this specification of a mailbox local-part (SMTP
+ Extensions may explicitly specify case-sensitive elements). That is,
+ a command verb, an argument value other than a mailbox local-part,
+ and free form text MAY be encoded in upper case, lower case, or any
+ mixture of upper and lower case with no impact on its meaning. This
+ is NOT true of a mailbox local-part. The local-part of a mailbox
+ MUST BE treated as case sensitive. Therefore, SMTP implementations
+ MUST take care to preserve the case of mailbox local-parts. Mailbox
+ domains are not case sensitive. In particular, for some hosts the
+ user "smith" is different from the user "Smith". However, exploiting
+ the case sensitivity of mailbox local-parts impedes interoperability
+ and is discouraged.
+
+ A few SMTP servers, in violation of this specification (and RFC 821)
+ require that command verbs be encoded by clients in upper case.
+ Implementations MAY wish to employ this encoding to accommodate those
+ servers.
+
+ The argument field consists of a variable length character string
+ ending with the end of the line, i.e., with the character sequence
+ <CRLF>. The receiver will take no action until this sequence is
+ received.
+
+ The syntax for each command is shown with the discussion of that
+ command. Common elements and parameters are shown in section 4.1.2.
+
+ Commands and replies are composed of characters from the ASCII
+ character set [1]. When the transport service provides an 8-bit byte
+ (octet) transmission channel, each 7-bit character is transmitted
+ right justified in an octet with the high order bit cleared to zero.
+ More specifically, the unextended SMTP service provides seven bit
+ transport only. An originating SMTP client which has not
+ successfully negotiated an appropriate extension with a particular
+ server MUST NOT transmit messages with information in the high-order
+ bit of octets. If such messages are transmitted in violation of this
+ rule, receiving SMTP servers MAY clear the high-order bit or reject
+ the message as invalid. In general, a relay SMTP SHOULD assume that
+ the message content it has received is valid and, assuming that the
+ envelope permits doing so, relay it without inspecting that content.
+ Of course, if the content is mislabeled and the data path cannot
+ accept the actual content, this may result in ultimate delivery of a
+ severely garbled message to the recipient. Delivery SMTP systems MAY
+ reject ("bounce") such messages rather than deliver them. No sending
+ SMTP system is permitted to send envelope commands in any character
+
+
+
+
+
+Klensin Standards Track [Page 14]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ set other than US-ASCII; receiving systems SHOULD reject such
+ commands, normally using "500 syntax error - invalid character"
+ replies.
+
+ Eight-bit message content transmission MAY be requested of the server
+ by a client using extended SMTP facilities, notably the "8BITMIME"
+ extension [20]. 8BITMIME SHOULD be supported by SMTP servers.
+ However, it MUST not be construed as authorization to transmit
+ unrestricted eight bit material. 8BITMIME MUST NOT be requested by
+ senders for material with the high bit on that is not in MIME format
+ with an appropriate content-transfer encoding; servers MAY reject
+ such messages.
+
+ The metalinguistic notation used in this document corresponds to the
+ "Augmented BNF" used in other Internet mail system documents. The
+ reader who is not familiar with that syntax should consult the ABNF
+ specification [8]. Metalanguage terms used in running text are
+ surrounded by pointed brackets (e.g., <CRLF>) for clarity.
+
+3. The SMTP Procedures: An Overview
+
+ This section contains descriptions of the procedures used in SMTP:
+ session initiation, the mail transaction, forwarding mail, verifying
+ mailbox names and expanding mailing lists, and the opening and
+ closing exchanges. Comments on relaying, a note on mail domains, and
+ a discussion of changing roles are included at the end of this
+ section. Several complete scenarios are presented in appendix D.
+
+3.1 Session Initiation
+
+ An SMTP session is initiated when a client opens a connection to a
+ server and the server responds with an opening message.
+
+ SMTP server implementations MAY include identification of their
+ software and version information in the connection greeting reply
+ after the 220 code, a practice that permits more efficient isolation
+ and repair of any problems. Implementations MAY make provision for
+ SMTP servers to disable the software and version announcement where
+ it causes security concerns. While some systems also identify their
+ contact point for mail problems, this is not a substitute for
+ maintaining the required "postmaster" address (see section 4.5.1).
+
+ The SMTP protocol allows a server to formally reject a transaction
+ while still allowing the initial connection as follows: a 554
+ response MAY be given in the initial connection opening message
+ instead of the 220. A server taking this approach MUST still wait
+ for the client to send a QUIT (see section 4.1.1.10) before closing
+ the connection and SHOULD respond to any intervening commands with
+
+
+
+Klensin Standards Track [Page 15]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ "503 bad sequence of commands". Since an attempt to make an SMTP
+ connection to such a system is probably in error, a server returning
+ a 554 response on connection opening SHOULD provide enough
+ information in the reply text to facilitate debugging of the sending
+ system.
+
+3.2 Client Initiation
+
+ Once the server has sent the welcoming message and the client has
+ received it, the client normally sends the EHLO command to the
+ server, indicating the client's identity. In addition to opening the
+ session, use of EHLO indicates that the client is able to process
+ service extensions and requests that the server provide a list of the
+ extensions it supports. Older SMTP systems which are unable to
+ support service extensions and contemporary clients which do not
+ require service extensions in the mail session being initiated, MAY
+ use HELO instead of EHLO. Servers MUST NOT return the extended
+ EHLO-style response to a HELO command. For a particular connection
+ attempt, if the server returns a "command not recognized" response to
+ EHLO, the client SHOULD be able to fall back and send HELO.
+
+ In the EHLO command the host sending the command identifies itself;
+ the command may be interpreted as saying "Hello, I am <domain>" (and,
+ in the case of EHLO, "and I support service extension requests").
+
+3.3 Mail Transactions
+
+ There are three steps to SMTP mail transactions. The transaction
+ starts with a MAIL command which gives the sender identification.
+ (In general, the MAIL command may be sent only when no mail
+ transaction is in progress; see section 4.1.4.) A series of one or
+ more RCPT commands follows giving the receiver information. Then a
+ DATA command initiates transfer of the mail data and is terminated by
+ the "end of mail" data indicator, which also confirms the
+ transaction.
+
+ The first step in the procedure is the MAIL command.
+
+ MAIL FROM:<reverse-path> [SP <mail-parameters> ] <CRLF>
+
+ This command tells the SMTP-receiver that a new mail transaction is
+ starting and to reset all its state tables and buffers, including any
+ recipients or mail data. The <reverse-path> portion of the first or
+ only argument contains the source mailbox (between "<" and ">"
+ brackets), which can be used to report errors (see section 4.2 for a
+ discussion of error reporting). If accepted, the SMTP server returns
+ a 250 OK reply. If the mailbox specification is not acceptable for
+ some reason, the server MUST return a reply indicating whether the
+
+
+
+Klensin Standards Track [Page 16]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ failure is permanent (i.e., will occur again if the client tries to
+ send the same address again) or temporary (i.e., the address might be
+ accepted if the client tries again later). Despite the apparent
+ scope of this requirement, there are circumstances in which the
+ acceptability of the reverse-path may not be determined until one or
+ more forward-paths (in RCPT commands) can be examined. In those
+ cases, the server MAY reasonably accept the reverse-path (with a 250
+ reply) and then report problems after the forward-paths are received
+ and examined. Normally, failures produce 550 or 553 replies.
+
+ Historically, the <reverse-path> can contain more than just a
+ mailbox, however, contemporary systems SHOULD NOT use source routing
+ (see appendix C).
+
+ The optional <mail-parameters> are associated with negotiated SMTP
+ service extensions (see section 2.2).
+
+ The second step in the procedure is the RCPT command.
+
+ RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF>
+
+ The first or only argument to this command includes a forward-path
+ (normally a mailbox and domain, always surrounded by "<" and ">"
+ brackets) identifying one recipient. If accepted, the SMTP server
+ returns a 250 OK reply and stores the forward-path. If the recipient
+ is known not to be a deliverable address, the SMTP server returns a
+ 550 reply, typically with a string such as "no such user - " and the
+ mailbox name (other circumstances and reply codes are possible).
+ This step of the procedure can be repeated any number of times.
+
+ The <forward-path> can contain more than just a mailbox.
+ Historically, the <forward-path> can be a source routing list of
+ hosts and the destination mailbox, however, contemporary SMTP clients
+ SHOULD NOT utilize source routes (see appendix C). Servers MUST be
+ prepared to encounter a list of source routes in the forward path,
+ but SHOULD ignore the routes or MAY decline to support the relaying
+ they imply. Similarly, servers MAY decline to accept mail that is
+ destined for other hosts or systems. These restrictions make a
+ server useless as a relay for clients that do not support full SMTP
+ functionality. Consequently, restricted-capability clients MUST NOT
+ assume that any SMTP server on the Internet can be used as their mail
+ processing (relaying) site. If a RCPT command appears without a
+ previous MAIL command, the server MUST return a 503 "Bad sequence of
+ commands" response. The optional <rcpt-parameters> are associated
+ with negotiated SMTP service extensions (see section 2.2).
+
+ The third step in the procedure is the DATA command (or some
+ alternative specified in a service extension).
+
+
+
+Klensin Standards Track [Page 17]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ DATA <CRLF>
+
+ If accepted, the SMTP server returns a 354 Intermediate reply and
+ considers all succeeding lines up to but not including the end of
+ mail data indicator to be the message text. When the end of text is
+ successfully received and stored the SMTP-receiver sends a 250 OK
+ reply.
+
+ Since the mail data is sent on the transmission channel, the end of
+ mail data must be indicated so that the command and reply dialog can
+ be resumed. SMTP indicates the end of the mail data by sending a
+ line containing only a "." (period or full stop). A transparency
+ procedure is used to prevent this from interfering with the user's
+ text (see section 4.5.2).
+
+ The end of mail data indicator also confirms the mail transaction and
+ tells the SMTP server to now process the stored recipients and mail
+ data. If accepted, the SMTP server returns a 250 OK reply. The DATA
+ command can fail at only two points in the protocol exchange:
+
+ - If there was no MAIL, or no RCPT, command, or all such commands
+ were rejected, the server MAY return a "command out of sequence"
+ (503) or "no valid recipients" (554) reply in response to the DATA
+ command. If one of those replies (or any other 5yz reply) is
+ received, the client MUST NOT send the message data; more
+ generally, message data MUST NOT be sent unless a 354 reply is
+ received.
+
+ - If the verb is initially accepted and the 354 reply issued, the
+ DATA command should fail only if the mail transaction was
+ incomplete (for example, no recipients), or if resources were
+ unavailable (including, of course, the server unexpectedly
+ becoming unavailable), or if the server determines that the
+ message should be rejected for policy or other reasons.
+
+ However, in practice, some servers do not perform recipient
+ verification until after the message text is received. These servers
+ SHOULD treat a failure for one or more recipients as a "subsequent
+ failure" and return a mail message as discussed in section 6. Using
+ a "550 mailbox not found" (or equivalent) reply code after the data
+ are accepted makes it difficult or impossible for the client to
+ determine which recipients failed.
+
+ When RFC 822 format [7, 32] is being used, the mail data include the
+ memo header items such as Date, Subject, To, Cc, From. Server SMTP
+ systems SHOULD NOT reject messages based on perceived defects in the
+ RFC 822 or MIME [12] message header or message body. In particular,
+
+
+
+
+Klensin Standards Track [Page 18]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ they MUST NOT reject messages in which the numbers of Resent-fields
+ do not match or Resent-to appears without Resent-from and/or Resent-
+ date.
+
+ Mail transaction commands MUST be used in the order discussed above.
+
+3.4 Forwarding for Address Correction or Updating
+
+ Forwarding support is most often required to consolidate and simplify
+ addresses within, or relative to, some enterprise and less frequently
+ to establish addresses to link a person's prior address with current
+ one. Silent forwarding of messages (without server notification to
+ the sender), for security or non-disclosure purposes, is common in
+ the contemporary Internet.
+
+ In both the enterprise and the "new address" cases, information
+ hiding (and sometimes security) considerations argue against exposure
+ of the "final" address through the SMTP protocol as a side-effect of
+ the forwarding activity. This may be especially important when the
+ final address may not even be reachable by the sender. Consequently,
+ the "forwarding" mechanisms described in section 3.2 of RFC 821, and
+ especially the 251 (corrected destination) and 551 reply codes from
+ RCPT must be evaluated carefully by implementers and, when they are
+ available, by those configuring systems.
+
+ In particular:
+
+ * Servers MAY forward messages when they are aware of an address
+ change. When they do so, they MAY either provide address-updating
+ information with a 251 code, or may forward "silently" and return
+ a 250 code. But, if a 251 code is used, they MUST NOT assume that
+ the client will actually update address information or even return
+ that information to the user.
+
+ Alternately,
+
+ * Servers MAY reject or bounce messages when they are not
+ deliverable when addressed. When they do so, they MAY either
+ provide address-updating information with a 551 code, or may
+ reject the message as undeliverable with a 550 code and no
+ address-specific information. But, if a 551 code is used, they
+ MUST NOT assume that the client will actually update address
+ information or even return that information to the user.
+
+ SMTP server implementations that support the 251 and/or 551 reply
+ codes are strongly encouraged to provide configuration mechanisms so
+ that sites which conclude that they would undesirably disclose
+ information can disable or restrict their use.
+
+
+
+Klensin Standards Track [Page 19]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+3.5 Commands for Debugging Addresses
+
+3.5.1 Overview
+
+ SMTP provides commands to verify a user name or obtain the content of
+ a mailing list. This is done with the VRFY and EXPN commands, which
+ have character string arguments. Implementations SHOULD support VRFY
+ and EXPN (however, see section 3.5.2 and 7.3).
+
+ For the VRFY command, the string is a user name or a user name and
+ domain (see below). If a normal (i.e., 250) response is returned,
+ the response MAY include the full name of the user and MUST include
+ the mailbox of the user. It MUST be in either of the following
+ forms:
+
+ User Name <local-part@domain>
+ local-part@domain
+
+ When a name that is the argument to VRFY could identify more than one
+ mailbox, the server MAY either note the ambiguity or identify the
+ alternatives. In other words, any of the following are legitimate
+ response to VRFY:
+
+ 553 User ambiguous
+
+ or
+
+ 553- Ambiguous; Possibilities are
+ 553-Joe Smith <jsmith@foo.com>
+ 553-Harry Smith <hsmith@foo.com>
+ 553 Melvin Smith <dweep@foo.com>
+
+ or
+
+ 553-Ambiguous; Possibilities
+ 553- <jsmith@foo.com>
+ 553- <hsmith@foo.com>
+ 553 <dweep@foo.com>
+
+ Under normal circumstances, a client receiving a 553 reply would be
+ expected to expose the result to the user. Use of exactly the forms
+ given, and the "user ambiguous" or "ambiguous" keywords, possibly
+ supplemented by extended reply codes such as those described in [34],
+ will facilitate automated translation into other languages as needed.
+ Of course, a client that was highly automated or that was operating
+ in another language than English, might choose to try to translate
+ the response, to return some other indication to the user than the
+
+
+
+
+Klensin Standards Track [Page 20]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ literal text of the reply, or to take some automated action such as
+ consulting a directory service for additional information before
+ reporting to the user.
+
+ For the EXPN command, the string identifies a mailing list, and the
+ successful (i.e., 250) multiline response MAY include the full name
+ of the users and MUST give the mailboxes on the mailing list.
+
+ In some hosts the distinction between a mailing list and an alias for
+ a single mailbox is a bit fuzzy, since a common data structure may
+ hold both types of entries, and it is possible to have mailing lists
+ containing only one mailbox. If a request is made to apply VRFY to a
+ mailing list, a positive response MAY be given if a message so
+ addressed would be delivered to everyone on the list, otherwise an
+ error SHOULD be reported (e.g., "550 That is a mailing list, not a
+ user" or "252 Unable to verify members of mailing list"). If a
+ request is made to expand a user name, the server MAY return a
+ positive response consisting of a list containing one name, or an
+ error MAY be reported (e.g., "550 That is a user name, not a mailing
+ list").
+
+ In the case of a successful multiline reply (normal for EXPN) exactly
+ one mailbox is to be specified on each line of the reply. The case
+ of an ambiguous request is discussed above.
+
+ "User name" is a fuzzy term and has been used deliberately. An
+ implementation of the VRFY or EXPN commands MUST include at least
+ recognition of local mailboxes as "user names". However, since
+ current Internet practice often results in a single host handling
+ mail for multiple domains, hosts, especially hosts that provide this
+ functionality, SHOULD accept the "local-part@domain" form as a "user
+ name"; hosts MAY also choose to recognize other strings as "user
+ names".
+
+ The case of expanding a mailbox list requires a multiline reply, such
+ as:
+
+ C: EXPN Example-People
+ S: 250-Jon Postel <Postel@isi.edu>
+ S: 250-Fred Fonebone <Fonebone@physics.foo-u.edu>
+ S: 250 Sam Q. Smith <SQSmith@specific.generic.com>
+
+ or
+
+ C: EXPN Executive-Washroom-List
+ S: 550 Access Denied to You.
+
+
+
+
+
+Klensin Standards Track [Page 21]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ The character string arguments of the VRFY and EXPN commands cannot
+ be further restricted due to the variety of implementations of the
+ user name and mailbox list concepts. On some systems it may be
+ appropriate for the argument of the EXPN command to be a file name
+ for a file containing a mailing list, but again there are a variety
+ of file naming conventions in the Internet. Similarly, historical
+ variations in what is returned by these commands are such that the
+ response SHOULD be interpreted very carefully, if at all, and SHOULD
+ generally only be used for diagnostic purposes.
+
+3.5.2 VRFY Normal Response
+
+ When normal (2yz or 551) responses are returned from a VRFY or EXPN
+ request, the reply normally includes the mailbox name, i.e.,
+ "<local-part@domain>", where "domain" is a fully qualified domain
+ name, MUST appear in the syntax. In circumstances exceptional enough
+ to justify violating the intent of this specification, free-form text
+ MAY be returned. In order to facilitate parsing by both computers
+ and people, addresses SHOULD appear in pointed brackets. When
+ addresses, rather than free-form debugging information, are returned,
+ EXPN and VRFY MUST return only valid domain addresses that are usable
+ in SMTP RCPT commands. Consequently, if an address implies delivery
+ to a program or other system, the mailbox name used to reach that
+ target MUST be given. Paths (explicit source routes) MUST NOT be
+ returned by VRFY or EXPN.
+
+ Server implementations SHOULD support both VRFY and EXPN. For
+ security reasons, implementations MAY provide local installations a
+ way to disable either or both of these commands through configuration
+ options or the equivalent. When these commands are supported, they
+ are not required to work across relays when relaying is supported.
+ Since they were both optional in RFC 821, they MUST be listed as
+ service extensions in an EHLO response, if they are supported.
+
+3.5.3 Meaning of VRFY or EXPN Success Response
+
+ A server MUST NOT return a 250 code in response to a VRFY or EXPN
+ command unless it has actually verified the address. In particular,
+ a server MUST NOT return 250 if all it has done is to verify that the
+ syntax given is valid. In that case, 502 (Command not implemented)
+ or 500 (Syntax error, command unrecognized) SHOULD be returned. As
+ stated elsewhere, implementation (in the sense of actually validating
+ addresses and returning information) of VRFY and EXPN are strongly
+ recommended. Hence, implementations that return 500 or 502 for VRFY
+ are not in full compliance with this specification.
+
+
+
+
+
+
+Klensin Standards Track [Page 22]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ There may be circumstances where an address appears to be valid but
+ cannot reasonably be verified in real time, particularly when a
+ server is acting as a mail exchanger for another server or domain.
+ "Apparent validity" in this case would normally involve at least
+ syntax checking and might involve verification that any domains
+ specified were ones to which the host expected to be able to relay
+ mail. In these situations, reply code 252 SHOULD be returned. These
+ cases parallel the discussion of RCPT verification discussed in
+ section 2.1. Similarly, the discussion in section 3.4 applies to the
+ use of reply codes 251 and 551 with VRFY (and EXPN) to indicate
+ addresses that are recognized but that would be forwarded or bounced
+ were mail received for them. Implementations generally SHOULD be
+ more aggressive about address verification in the case of VRFY than
+ in the case of RCPT, even if it takes a little longer to do so.
+
+3.5.4 Semantics and Applications of EXPN
+
+ EXPN is often very useful in debugging and understanding problems
+ with mailing lists and multiple-target-address aliases. Some systems
+ have attempted to use source expansion of mailing lists as a means of
+ eliminating duplicates. The propagation of aliasing systems with
+ mail on the Internet, for hosts (typically with MX and CNAME DNS
+ records), for mailboxes (various types of local host aliases), and in
+ various proxying arrangements, has made it nearly impossible for
+ these strategies to work consistently, and mail systems SHOULD NOT
+ attempt them.
+
+3.6 Domains
+
+ Only resolvable, fully-qualified, domain names (FQDNs) are permitted
+ when domain names are used in SMTP. In other words, names that can
+ be resolved to MX RRs or A RRs (as discussed in section 5) are
+ permitted, as are CNAME RRs whose targets can be resolved, in turn,
+ to MX or A RRs. Local nicknames or unqualified names MUST NOT be
+ used. There are two exceptions to the rule requiring FQDNs:
+
+ - The domain name given in the EHLO command MUST BE either a primary
+ host name (a domain name that resolves to an A RR) or, if the host
+ has no name, an address literal as described in section 4.1.1.1.
+
+ - The reserved mailbox name "postmaster" may be used in a RCPT
+ command without domain qualification (see section 4.1.1.3) and
+ MUST be accepted if so used.
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 23]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+3.7 Relaying
+
+ In general, the availability of Mail eXchanger records in the domain
+ name system [22, 27] makes the use of explicit source routes in the
+ Internet mail system unnecessary. Many historical problems with
+ their interpretation have made their use undesirable. SMTP clients
+ SHOULD NOT generate explicit source routes except under unusual
+ circumstances. SMTP servers MAY decline to act as mail relays or to
+ accept addresses that specify source routes. When route information
+ is encountered, SMTP servers are also permitted to ignore the route
+ information and simply send to the final destination specified as the
+ last element in the route and SHOULD do so. There has been an
+ invalid practice of using names that do not appear in the DNS as
+ destination names, with the senders counting on the intermediate
+ hosts specified in source routing to resolve any problems. If source
+ routes are stripped, this practice will cause failures. This is one
+ of several reasons why SMTP clients MUST NOT generate invalid source
+ routes or depend on serial resolution of names.
+
+ When source routes are not used, the process described in RFC 821 for
+ constructing a reverse-path from the forward-path is not applicable
+ and the reverse-path at the time of delivery will simply be the
+ address that appeared in the MAIL command.
+
+ A relay SMTP server is usually the target of a DNS MX record that
+ designates it, rather than the final delivery system. The relay
+ server may accept or reject the task of relaying the mail in the same
+ way it accepts or rejects mail for a local user. If it accepts the
+ task, it then becomes an SMTP client, establishes a transmission
+ channel to the next SMTP server specified in the DNS (according to
+ the rules in section 5), and sends it the mail. If it declines to
+ relay mail to a particular address for policy reasons, a 550 response
+ SHOULD be returned.
+
+ Many mail-sending clients exist, especially in conjunction with
+ facilities that receive mail via POP3 or IMAP, that have limited
+ capability to support some of the requirements of this specification,
+ such as the ability to queue messages for subsequent delivery
+ attempts. For these clients, it is common practice to make private
+ arrangements to send all messages to a single server for processing
+ and subsequent distribution. SMTP, as specified here, is not ideally
+ suited for this role, and work is underway on standardized mail
+ submission protocols that might eventually supercede the current
+ practices. In any event, because these arrangements are private and
+ fall outside the scope of this specification, they are not described
+ here.
+
+
+
+
+
+Klensin Standards Track [Page 24]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ It is important to note that MX records can point to SMTP servers
+ which act as gateways into other environments, not just SMTP relays
+ and final delivery systems; see sections 3.8 and 5.
+
+ If an SMTP server has accepted the task of relaying the mail and
+ later finds that the destination is incorrect or that the mail cannot
+ be delivered for some other reason, then it MUST construct an
+ "undeliverable mail" notification message and send it to the
+ originator of the undeliverable mail (as indicated by the reverse-
+ path). Formats specified for non-delivery reports by other standards
+ (see, for example, [24, 25]) SHOULD be used if possible.
+
+ This notification message must be from the SMTP server at the relay
+ host or the host that first determines that delivery cannot be
+ accomplished. Of course, SMTP servers MUST NOT send notification
+ messages about problems transporting notification messages. One way
+ to prevent loops in error reporting is to specify a null reverse-path
+ in the MAIL command of a notification message. When such a message
+ is transmitted the reverse-path MUST be set to null (see section
+ 4.5.5 for additional discussion). A MAIL command with a null
+ reverse-path appears as follows:
+
+ MAIL FROM:<>
+
+ As discussed in section 2.4.1, a relay SMTP has no need to inspect or
+ act upon the headers or body of the message data and MUST NOT do so
+ except to add its own "Received:" header (section 4.4) and,
+ optionally, to attempt to detect looping in the mail system (see
+ section 6.2).
+
+3.8 Mail Gatewaying
+
+ While the relay function discussed above operates within the Internet
+ SMTP transport service environment, MX records or various forms of
+ explicit routing may require that an intermediate SMTP server perform
+ a translation function between one transport service and another. As
+ discussed in section 2.3.8, when such a system is at the boundary
+ between two transport service environments, we refer to it as a
+ "gateway" or "gateway SMTP".
+
+ Gatewaying mail between different mail environments, such as
+ different mail formats and protocols, is complex and does not easily
+ yield to standardization. However, some general requirements may be
+ given for a gateway between the Internet and another mail
+ environment.
+
+
+
+
+
+
+Klensin Standards Track [Page 25]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+3.8.1 Header Fields in Gatewaying
+
+ Header fields MAY be rewritten when necessary as messages are
+ gatewayed across mail environment boundaries. This may involve
+ inspecting the message body or interpreting the local-part of the
+ destination address in spite of the prohibitions in section 2.4.1.
+
+ Other mail systems gatewayed to the Internet often use a subset of
+ RFC 822 headers or provide similar functionality with a different
+ syntax, but some of these mail systems do not have an equivalent to
+ the SMTP envelope. Therefore, when a message leaves the Internet
+ environment, it may be necessary to fold the SMTP envelope
+ information into the message header. A possible solution would be to
+ create new header fields to carry the envelope information (e.g.,
+ "X-SMTP-MAIL:" and "X-SMTP-RCPT:"); however, this would require
+ changes in mail programs in foreign environments and might risk
+ disclosure of private information (see section 7.2).
+
+3.8.2 Received Lines in Gatewaying
+
+ When forwarding a message into or out of the Internet environment, a
+ gateway MUST prepend a Received: line, but it MUST NOT alter in any
+ way a Received: line that is already in the header.
+
+ "Received:" fields of messages originating from other environments
+ may not conform exactly to this specification. However, the most
+ important use of Received: lines is for debugging mail faults, and
+ this debugging can be severely hampered by well-meaning gateways that
+ try to "fix" a Received: line. As another consequence of trace
+ fields arising in non-SMTP environments, receiving systems MUST NOT
+ reject mail based on the format of a trace field and SHOULD be
+ extremely robust in the light of unexpected information or formats in
+ those fields.
+
+ The gateway SHOULD indicate the environment and protocol in the "via"
+ clauses of Received field(s) that it supplies.
+
+3.8.3 Addresses in Gatewaying
+
+ From the Internet side, the gateway SHOULD accept all valid address
+ formats in SMTP commands and in RFC 822 headers, and all valid RFC
+ 822 messages. Addresses and headers generated by gateways MUST
+ conform to applicable Internet standards (including this one and RFC
+ 822). Gateways are, of course, subject to the same rules for
+ handling source routes as those described for other SMTP systems in
+ section 3.3.
+
+
+
+
+
+Klensin Standards Track [Page 26]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+3.8.4 Other Header Fields in Gatewaying
+
+ The gateway MUST ensure that all header fields of a message that it
+ forwards into the Internet mail environment meet the requirements for
+ Internet mail. In particular, all addresses in "From:", "To:",
+ "Cc:", etc., fields MUST be transformed (if necessary) to satisfy RFC
+ 822 syntax, MUST reference only fully-qualified domain names, and
+ MUST be effective and useful for sending replies. The translation
+ algorithm used to convert mail from the Internet protocols to another
+ environment's protocol SHOULD ensure that error messages from the
+ foreign mail environment are delivered to the return path from the
+ SMTP envelope, not to the sender listed in the "From:" field (or
+ other fields) of the RFC 822 message.
+
+3.8.5 Envelopes in Gatewaying
+
+ Similarly, when forwarding a message from another environment into
+ the Internet, the gateway SHOULD set the envelope return path in
+ accordance with an error message return address, if supplied by the
+ foreign environment. If the foreign environment has no equivalent
+ concept, the gateway must select and use a best approximation, with
+ the message originator's address as the default of last resort.
+
+3.9 Terminating Sessions and Connections
+
+ An SMTP connection is terminated when the client sends a QUIT
+ command. The server responds with a positive reply code, after which
+ it closes the connection.
+
+ An SMTP server MUST NOT intentionally close the connection except:
+
+ - After receiving a QUIT command and responding with a 221 reply.
+
+ - After detecting the need to shut down the SMTP service and
+ returning a 421 response code. This response code can be issued
+ after the server receives any command or, if necessary,
+ asynchronously from command receipt (on the assumption that the
+ client will receive it after the next command is issued).
+
+ In particular, a server that closes connections in response to
+ commands that are not understood is in violation of this
+ specification. Servers are expected to be tolerant of unknown
+ commands, issuing a 500 reply and awaiting further instructions from
+ the client.
+
+
+
+
+
+
+
+Klensin Standards Track [Page 27]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ An SMTP server which is forcibly shut down via external means SHOULD
+ attempt to send a line containing a 421 response code to the SMTP
+ client before exiting. The SMTP client will normally read the 421
+ response code after sending its next command.
+
+ SMTP clients that experience a connection close, reset, or other
+ communications failure due to circumstances not under their control
+ (in violation of the intent of this specification but sometimes
+ unavoidable) SHOULD, to maintain the robustness of the mail system,
+ treat the mail transaction as if a 451 response had been received and
+ act accordingly.
+
+3.10 Mailing Lists and Aliases
+
+ An SMTP-capable host SHOULD support both the alias and the list
+ models of address expansion for multiple delivery. When a message is
+ delivered or forwarded to each address of an expanded list form, the
+ return address in the envelope ("MAIL FROM:") MUST be changed to be
+ the address of a person or other entity who administers the list.
+ However, in this case, the message header [32] MUST be left
+ unchanged; in particular, the "From" field of the message header is
+ unaffected.
+
+ An important mail facility is a mechanism for multi-destination
+ delivery of a single message, by transforming (or "expanding" or
+ "exploding") a pseudo-mailbox address into a list of destination
+ mailbox addresses. When a message is sent to such a pseudo-mailbox
+ (sometimes called an "exploder"), copies are forwarded or
+ redistributed to each mailbox in the expanded list. Servers SHOULD
+ simply utilize the addresses on the list; application of heuristics
+ or other matching rules to eliminate some addresses, such as that of
+ the originator, is strongly discouraged. We classify such a pseudo-
+ mailbox as an "alias" or a "list", depending upon the expansion
+ rules.
+
+3.10.1 Alias
+
+ To expand an alias, the recipient mailer simply replaces the pseudo-
+ mailbox address in the envelope with each of the expanded addresses
+ in turn; the rest of the envelope and the message body are left
+ unchanged. The message is then delivered or forwarded to each
+ expanded address.
+
+3.10.2 List
+
+ A mailing list may be said to operate by "redistribution" rather than
+ by "forwarding". To expand a list, the recipient mailer replaces the
+ pseudo-mailbox address in the envelope with all of the expanded
+
+
+
+Klensin Standards Track [Page 28]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ addresses. The return address in the envelope is changed so that all
+ error messages generated by the final deliveries will be returned to
+ a list administrator, not to the message originator, who generally
+ has no control over the contents of the list and will typically find
+ error messages annoying.
+
+4. The SMTP Specifications
+
+4.1 SMTP Commands
+
+4.1.1 Command Semantics and Syntax
+
+ The SMTP commands define the mail transfer or the mail system
+ function requested by the user. SMTP commands are character strings
+ terminated by <CRLF>. The commands themselves are alphabetic
+ characters terminated by <SP> if parameters follow and <CRLF>
+ otherwise. (In the interest of improved interoperability, SMTP
+ receivers are encouraged to tolerate trailing white space before the
+ terminating <CRLF>.) The syntax of the local part of a mailbox must
+ conform to receiver site conventions and the syntax specified in
+ section 4.1.2. The SMTP commands are discussed below. The SMTP
+ replies are discussed in section 4.2.
+
+ A mail transaction involves several data objects which are
+ communicated as arguments to different commands. The reverse-path is
+ the argument of the MAIL command, the forward-path is the argument of
+ the RCPT command, and the mail data is the argument of the DATA
+ command. These arguments or data objects must be transmitted and
+ held pending the confirmation communicated by the end of mail data
+ indication which finalizes the transaction. The model for this is
+ that distinct buffers are provided to hold the types of data objects,
+ that is, there is a reverse-path buffer, a forward-path buffer, and a
+ mail data buffer. Specific commands cause information to be appended
+ to a specific buffer, or cause one or more buffers to be cleared.
+
+ Several commands (RSET, DATA, QUIT) are specified as not permitting
+ parameters. In the absence of specific extensions offered by the
+ server and accepted by the client, clients MUST NOT send such
+ parameters and servers SHOULD reject commands containing them as
+ having invalid syntax.
+
+4.1.1.1 Extended HELLO (EHLO) or HELLO (HELO)
+
+ These commands are used to identify the SMTP client to the SMTP
+ server. The argument field contains the fully-qualified domain name
+ of the SMTP client if one is available. In situations in which the
+ SMTP client system does not have a meaningful domain name (e.g., when
+ its address is dynamically allocated and no reverse mapping record is
+
+
+
+Klensin Standards Track [Page 29]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ available), the client SHOULD send an address literal (see section
+ 4.1.3), optionally followed by information that will help to identify
+ the client system. y The SMTP server identifies itself to the SMTP
+ client in the connection greeting reply and in the response to this
+ command.
+
+ A client SMTP SHOULD start an SMTP session by issuing the EHLO
+ command. If the SMTP server supports the SMTP service extensions it
+ will give a successful response, a failure response, or an error
+ response. If the SMTP server, in violation of this specification,
+ does not support any SMTP service extensions it will generate an
+ error response. Older client SMTP systems MAY, as discussed above,
+ use HELO (as specified in RFC 821) instead of EHLO, and servers MUST
+ support the HELO command and reply properly to it. In any event, a
+ client MUST issue HELO or EHLO before starting a mail transaction.
+
+ These commands, and a "250 OK" reply to one of them, confirm that
+ both the SMTP client and the SMTP server are in the initial state,
+ that is, there is no transaction in progress and all state tables and
+ buffers are cleared.
+
+ Syntax:
+
+ ehlo = "EHLO" SP Domain CRLF
+ helo = "HELO" SP Domain CRLF
+
+ Normally, the response to EHLO will be a multiline reply. Each line
+ of the response contains a keyword and, optionally, one or more
+ parameters. Following the normal syntax for multiline replies, these
+ keyworks follow the code (250) and a hyphen for all but the last
+ line, and the code and a space for the last line. The syntax for a
+ positive response, using the ABNF notation and terminal symbols of
+ [8], is:
+
+ ehlo-ok-rsp = ( "250" domain [ SP ehlo-greet ] CRLF )
+ / ( "250-" domain [ SP ehlo-greet ] CRLF
+ *( "250-" ehlo-line CRLF )
+ "250" SP ehlo-line CRLF )
+
+ ehlo-greet = 1*(%d0-9 / %d11-12 / %d14-127)
+ ; string of any characters other than CR or LF
+
+ ehlo-line = ehlo-keyword *( SP ehlo-param )
+
+ ehlo-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-")
+ ; additional syntax of ehlo-params depends on
+ ; ehlo-keyword
+
+
+
+
+Klensin Standards Track [Page 30]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ ehlo-param = 1*(%d33-127)
+ ; any CHAR excluding <SP> and all
+ ; control characters (US-ASCII 0-31 inclusive)
+
+ Although EHLO keywords may be specified in upper, lower, or mixed
+ case, they MUST always be recognized and processed in a case-
+ insensitive manner. This is simply an extension of practices
+ specified in RFC 821 and section 2.4.1.
+
+4.1.1.2 MAIL (MAIL)
+
+ This command is used to initiate a mail transaction in which the mail
+ data is delivered to an SMTP server which may, in turn, deliver it to
+ one or more mailboxes or pass it on to another system (possibly using
+ SMTP). The argument field contains a reverse-path and may contain
+ optional parameters. In general, the MAIL command may be sent only
+ when no mail transaction is in progress, see section 4.1.4.
+
+ The reverse-path consists of the sender mailbox. Historically, that
+ mailbox might optionally have been preceded by a list of hosts, but
+ that behavior is now deprecated (see appendix C). In some types of
+ reporting messages for which a reply is likely to cause a mail loop
+ (for example, mail delivery and nondelivery notifications), the
+ reverse-path may be null (see section 3.7).
+
+ This command clears the reverse-path buffer, the forward-path buffer,
+ and the mail data buffer; and inserts the reverse-path information
+ from this command into the reverse-path buffer.
+
+ If service extensions were negotiated, the MAIL command may also
+ carry parameters associated with a particular service extension.
+
+ Syntax:
+
+ "MAIL FROM:" ("<>" / Reverse-Path)
+ [SP Mail-parameters] CRLF
+
+4.1.1.3 RECIPIENT (RCPT)
+
+ This command is used to identify an individual recipient of the mail
+ data; multiple recipients are specified by multiple use of this
+ command. The argument field contains a forward-path and may contain
+ optional parameters.
+
+ The forward-path normally consists of the required destination
+ mailbox. Sending systems SHOULD not generate the optional list of
+ hosts known as a source route. Receiving systems MUST recognize
+
+
+
+
+Klensin Standards Track [Page 31]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ source route syntax but SHOULD strip off the source route
+ specification and utilize the domain name associated with the mailbox
+ as if the source route had not been provided.
+
+ Similarly, relay hosts SHOULD strip or ignore source routes, and
+ names MUST NOT be copied into the reverse-path. When mail reaches
+ its ultimate destination (the forward-path contains only a
+ destination mailbox), the SMTP server inserts it into the destination
+ mailbox in accordance with its host mail conventions.
+
+ For example, mail received at relay host xyz.com with envelope
+ commands
+
+ MAIL FROM:<userx@y.foo.org>
+ RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org>
+
+ will normally be sent directly on to host d.bar.org with envelope
+ commands
+
+ MAIL FROM:<userx@y.foo.org>
+ RCPT TO:<userc@d.bar.org>
+
+ As provided in appendix C, xyz.com MAY also choose to relay the
+ message to hosta.int, using the envelope commands
+
+ MAIL FROM:<userx@y.foo.org>
+ RCPT TO:<@hosta.int,@jkl.org:userc@d.bar.org>
+
+ or to jkl.org, using the envelope commands
+
+ MAIL FROM:<userx@y.foo.org>
+ RCPT TO:<@jkl.org:userc@d.bar.org>
+
+ Of course, since hosts are not required to relay mail at all, xyz.com
+ may also reject the message entirely when the RCPT command is
+ received, using a 550 code (since this is a "policy reason").
+
+ If service extensions were negotiated, the RCPT command may also
+ carry parameters associated with a particular service extension
+ offered by the server. The client MUST NOT transmit parameters other
+ than those associated with a service extension offered by the server
+ in its EHLO response.
+
+Syntax:
+ "RCPT TO:" ("<Postmaster@" domain ">" / "<Postmaster>" / Forward-Path)
+ [SP Rcpt-parameters] CRLF
+
+
+
+
+
+Klensin Standards Track [Page 32]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+4.1.1.4 DATA (DATA)
+
+ The receiver normally sends a 354 response to DATA, and then treats
+ the lines (strings ending in <CRLF> sequences, as described in
+ section 2.3.7) following the command as mail data from the sender.
+ This command causes the mail data to be appended to the mail data
+ buffer. The mail data may contain any of the 128 ASCII character
+ codes, although experience has indicated that use of control
+ characters other than SP, HT, CR, and LF may cause problems and
+ SHOULD be avoided when possible.
+
+ The mail data is terminated by a line containing only a period, that
+ is, the character sequence "<CRLF>.<CRLF>" (see section 4.5.2). This
+ is the end of mail data indication. Note that the first <CRLF> of
+ this terminating sequence is also the <CRLF> that ends the final line
+ of the data (message text) or, if there was no data, ends the DATA
+ command itself. An extra <CRLF> MUST NOT be added, as that would
+ cause an empty line to be added to the message. The only exception
+ to this rule would arise if the message body were passed to the
+ originating SMTP-sender with a final "line" that did not end in
+ <CRLF>; in that case, the originating SMTP system MUST either reject
+ the message as invalid or add <CRLF> in order to have the receiving
+ SMTP server recognize the "end of data" condition.
+
+ The custom of accepting lines ending only in <LF>, as a concession to
+ non-conforming behavior on the part of some UNIX systems, has proven
+ to cause more interoperability problems than it solves, and SMTP
+ server systems MUST NOT do this, even in the name of improved
+ robustness. In particular, the sequence "<LF>.<LF>" (bare line
+ feeds, without carriage returns) MUST NOT be treated as equivalent to
+ <CRLF>.<CRLF> as the end of mail data indication.
+
+ Receipt of the end of mail data indication requires the server to
+ process the stored mail transaction information. This processing
+ consumes the information in the reverse-path buffer, the forward-path
+ buffer, and the mail data buffer, and on the completion of this
+ command these buffers are cleared. If the processing is successful,
+ the receiver MUST send an OK reply. If the processing fails the
+ receiver MUST send a failure reply. The SMTP model does not allow
+ for partial failures at this point: either the message is accepted by
+ the server for delivery and a positive response is returned or it is
+ not accepted and a failure reply is returned. In sending a positive
+ completion reply to the end of data indication, the receiver takes
+ full responsibility for the message (see section 6.1). Errors that
+ are diagnosed subsequently MUST be reported in a mail message, as
+ discussed in section 4.4.
+
+
+
+
+
+Klensin Standards Track [Page 33]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ When the SMTP server accepts a message either for relaying or for
+ final delivery, it inserts a trace record (also referred to
+ interchangeably as a "time stamp line" or "Received" line) at the top
+ of the mail data. This trace record indicates the identity of the
+ host that sent the message, the identity of the host that received
+ the message (and is inserting this time stamp), and the date and time
+ the message was received. Relayed messages will have multiple time
+ stamp lines. Details for formation of these lines, including their
+ syntax, is specified in section 4.4.
+
+ Additional discussion about the operation of the DATA command appears
+ in section 3.3.
+
+ Syntax:
+ "DATA" CRLF
+
+4.1.1.5 RESET (RSET)
+
+ This command specifies that the current mail transaction will be
+ aborted. Any stored sender, recipients, and mail data MUST be
+ discarded, and all buffers and state tables cleared. The receiver
+ MUST send a "250 OK" reply to a RSET command with no arguments. A
+ reset command may be issued by the client at any time. It is
+ effectively equivalent to a NOOP (i.e., if has no effect) if issued
+ immediately after EHLO, before EHLO is issued in the session, after
+ an end-of-data indicator has been sent and acknowledged, or
+ immediately before a QUIT. An SMTP server MUST NOT close the
+ connection as the result of receiving a RSET; that action is reserved
+ for QUIT (see section 4.1.1.10).
+
+ Since EHLO implies some additional processing and response by the
+ server, RSET will normally be more efficient than reissuing that
+ command, even though the formal semantics are the same.
+
+ There are circumstances, contrary to the intent of this
+ specification, in which an SMTP server may receive an indication that
+ the underlying TCP connection has been closed or reset. To preserve
+ the robustness of the mail system, SMTP servers SHOULD be prepared
+ for this condition and SHOULD treat it as if a QUIT had been received
+ before the connection disappeared.
+
+ Syntax:
+ "RSET" CRLF
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 34]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+4.1.1.6 VERIFY (VRFY)
+
+ This command asks the receiver to confirm that the argument
+ identifies a user or mailbox. If it is a user name, information is
+ returned as specified in section 3.5.
+
+ This command has no effect on the reverse-path buffer, the forward-
+ path buffer, or the mail data buffer.
+
+ Syntax:
+ "VRFY" SP String CRLF
+
+4.1.1.7 EXPAND (EXPN)
+
+ This command asks the receiver to confirm that the argument
+ identifies a mailing list, and if so, to return the membership of
+ that list. If the command is successful, a reply is returned
+ containing information as described in section 3.5. This reply will
+ have multiple lines except in the trivial case of a one-member list.
+
+ This command has no effect on the reverse-path buffer, the forward-
+ path buffer, or the mail data buffer and may be issued at any time.
+
+ Syntax:
+ "EXPN" SP String CRLF
+
+4.1.1.8 HELP (HELP)
+
+ This command causes the server to send helpful information to the
+ client. The command MAY take an argument (e.g., any command name)
+ and return more specific information as a response.
+
+ This command has no effect on the reverse-path buffer, the forward-
+ path buffer, or the mail data buffer and may be issued at any time.
+
+ SMTP servers SHOULD support HELP without arguments and MAY support it
+ with arguments.
+
+ Syntax:
+ "HELP" [ SP String ] CRLF
+
+4.1.1.9 NOOP (NOOP)
+
+ This command does not affect any parameters or previously entered
+ commands. It specifies no action other than that the receiver send
+ an OK reply.
+
+
+
+
+
+Klensin Standards Track [Page 35]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ This command has no effect on the reverse-path buffer, the forward-
+ path buffer, or the mail data buffer and may be issued at any time.
+ If a parameter string is specified, servers SHOULD ignore it.
+
+ Syntax:
+ "NOOP" [ SP String ] CRLF
+
+4.1.1.10 QUIT (QUIT)
+
+ This command specifies that the receiver MUST send an OK reply, and
+ then close the transmission channel.
+
+ The receiver MUST NOT intentionally close the transmission channel
+ until it receives and replies to a QUIT command (even if there was an
+ error). The sender MUST NOT intentionally close the transmission
+ channel until it sends a QUIT command and SHOULD wait until it
+ receives the reply (even if there was an error response to a previous
+ command). If the connection is closed prematurely due to violations
+ of the above or system or network failure, the server MUST cancel any
+ pending transaction, but not undo any previously completed
+ transaction, and generally MUST act as if the command or transaction
+ in progress had received a temporary error (i.e., a 4yz response).
+
+ The QUIT command may be issued at any time.
+
+ Syntax:
+ "QUIT" CRLF
+
+4.1.2 Command Argument Syntax
+
+ The syntax of the argument fields of the above commands (using the
+ syntax specified in [8] where applicable) is given below. Some of
+ the productions given below are used only in conjunction with source
+ routes as described in appendix C. Terminals not defined in this
+ document, such as ALPHA, DIGIT, SP, CR, LF, CRLF, are as defined in
+ the "core" syntax [8 (section 6)] or in the message format syntax
+ [32].
+
+ Reverse-path = Path
+ Forward-path = Path
+ Path = "<" [ A-d-l ":" ] Mailbox ">"
+ A-d-l = At-domain *( "," A-d-l )
+ ; Note that this form, the so-called "source route",
+ ; MUST BE accepted, SHOULD NOT be generated, and SHOULD be
+ ; ignored.
+ At-domain = "@" domain
+ Mail-parameters = esmtp-param *(SP esmtp-param)
+ Rcpt-parameters = esmtp-param *(SP esmtp-param)
+
+
+
+Klensin Standards Track [Page 36]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ esmtp-param = esmtp-keyword ["=" esmtp-value]
+ esmtp-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-")
+ esmtp-value = 1*(%d33-60 / %d62-127)
+ ; any CHAR excluding "=", SP, and control characters
+ Keyword = Ldh-str
+ Argument = Atom
+ Domain = (sub-domain 1*("." sub-domain)) / address-literal
+ sub-domain = Let-dig [Ldh-str]
+
+ address-literal = "[" IPv4-address-literal /
+ IPv6-address-literal /
+ General-address-literal "]"
+ ; See section 4.1.3
+
+ Mailbox = Local-part "@" Domain
+
+ Local-part = Dot-string / Quoted-string
+ ; MAY be case-sensitive
+
+ Dot-string = Atom *("." Atom)
+
+ Atom = 1*atext
+
+ Quoted-string = DQUOTE *qcontent DQUOTE
+
+ String = Atom / Quoted-string
+
+ While the above definition for Local-part is relatively permissive,
+ for maximum interoperability, a host that expects to receive mail
+ SHOULD avoid defining mailboxes where the Local-part requires (or
+ uses) the Quoted-string form or where the Local-part is case-
+ sensitive. For any purposes that require generating or comparing
+ Local-parts (e.g., to specific mailbox names), all quoted forms MUST
+ be treated as equivalent and the sending system SHOULD transmit the
+ form that uses the minimum quoting possible.
+
+ Systems MUST NOT define mailboxes in such a way as to require the use
+ in SMTP of non-ASCII characters (octets with the high order bit set
+ to one) or ASCII "control characters" (decimal value 0-31 and 127).
+ These characters MUST NOT be used in MAIL or RCPT commands or other
+ commands that require mailbox names.
+
+ Note that the backslash, "\", is a quote character, which is used to
+ indicate that the next character is to be used literally (instead of
+ its normal interpretation). For example, "Joe\,Smith" indicates a
+ single nine character user field with the comma being the fourth
+ character of the field.
+
+
+
+
+Klensin Standards Track [Page 37]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ To promote interoperability and consistent with long-standing
+ guidance about conservative use of the DNS in naming and applications
+ (e.g., see section 2.3.1 of the base DNS document, RFC1035 [22]),
+ characters outside the set of alphas, digits, and hyphen MUST NOT
+ appear in domain name labels for SMTP clients or servers. In
+ particular, the underscore character is not permitted. SMTP servers
+ that receive a command in which invalid character codes have been
+ employed, and for which there are no other reasons for rejection,
+ MUST reject that command with a 501 response.
+
+4.1.3 Address Literals
+
+ Sometimes a host is not known to the domain name system and
+ communication (and, in particular, communication to report and repair
+ the error) is blocked. To bypass this barrier a special literal form
+ of the address is allowed as an alternative to a domain name. For
+ IPv4 addresses, this form uses four small decimal integers separated
+ by dots and enclosed by brackets such as [123.255.37.2], which
+ indicates an (IPv4) Internet Address in sequence-of-octets form. For
+ IPv6 and other forms of addressing that might eventually be
+ standardized, the form consists of a standardized "tag" that
+ identifies the address syntax, a colon, and the address itself, in a
+ format specified as part of the IPv6 standards [17].
+
+ Specifically:
+
+ IPv4-address-literal = Snum 3("." Snum)
+ IPv6-address-literal = "IPv6:" IPv6-addr
+ General-address-literal = Standardized-tag ":" 1*dcontent
+ Standardized-tag = Ldh-str
+ ; MUST be specified in a standards-track RFC
+ ; and registered with IANA
+
+ Snum = 1*3DIGIT ; representing a decimal integer
+ ; value in the range 0 through 255
+ Let-dig = ALPHA / DIGIT
+ Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
+
+ IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp
+ IPv6-hex = 1*4HEXDIG
+ IPv6-full = IPv6-hex 7(":" IPv6-hex)
+ IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" [IPv6-hex *5(":"
+ IPv6-hex)]
+ ; The "::" represents at least 2 16-bit groups of zeros
+ ; No more than 6 groups in addition to the "::" may be
+ ; present
+ IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal
+ IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::"
+
+
+
+Klensin Standards Track [Page 38]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ [IPv6-hex *3(":" IPv6-hex) ":"] IPv4-address-literal
+ ; The "::" represents at least 2 16-bit groups of zeros
+ ; No more than 4 groups in addition to the "::" and
+ ; IPv4-address-literal may be present
+
+4.1.4 Order of Commands
+
+ There are restrictions on the order in which these commands may be
+ used.
+
+ A session that will contain mail transactions MUST first be
+ initialized by the use of the EHLO command. An SMTP server SHOULD
+ accept commands for non-mail transactions (e.g., VRFY or EXPN)
+ without this initialization.
+
+ An EHLO command MAY be issued by a client later in the session. If
+ it is issued after the session begins, the SMTP server MUST clear all
+ buffers and reset the state exactly as if a RSET command had been
+ issued. In other words, the sequence of RSET followed immediately by
+ EHLO is redundant, but not harmful other than in the performance cost
+ of executing unnecessary commands.
+
+ If the EHLO command is not acceptable to the SMTP server, 501, 500,
+ or 502 failure replies MUST be returned as appropriate. The SMTP
+ server MUST stay in the same state after transmitting these replies
+ that it was in before the EHLO was received.
+
+ The SMTP client MUST, if possible, ensure that the domain parameter
+ to the EHLO command is a valid principal host name (not a CNAME or MX
+ name) for its host. If this is not possible (e.g., when the client's
+ address is dynamically assigned and the client does not have an
+ obvious name), an address literal SHOULD be substituted for the
+ domain name and supplemental information provided that will assist in
+ identifying the client.
+
+ An SMTP server MAY verify that the domain name parameter in the EHLO
+ command actually corresponds to the IP address of the client.
+ However, the server MUST NOT refuse to accept a message for this
+ reason if the verification fails: the information about verification
+ failure is for logging and tracing only.
+
+ The NOOP, HELP, EXPN, VRFY, and RSET commands can be used at any time
+ during a session, or without previously initializing a session. SMTP
+ servers SHOULD process these normally (that is, not return a 503
+ code) even if no EHLO command has yet been received; clients SHOULD
+ open a session with EHLO before sending these commands.
+
+
+
+
+
+Klensin Standards Track [Page 39]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ If these rules are followed, the example in RFC 821 that shows "550
+ access denied to you" in response to an EXPN command is incorrect
+ unless an EHLO command precedes the EXPN or the denial of access is
+ based on the client's IP address or other authentication or
+ authorization-determining mechanisms.
+
+ The MAIL command (or the obsolete SEND, SOML, or SAML commands)
+ begins a mail transaction. Once started, a mail transaction consists
+ of a transaction beginning command, one or more RCPT commands, and a
+ DATA command, in that order. A mail transaction may be aborted by
+ the RSET (or a new EHLO) command. There may be zero or more
+ transactions in a session. MAIL (or SEND, SOML, or SAML) MUST NOT be
+ sent if a mail transaction is already open, i.e., it should be sent
+ only if no mail transaction had been started in the session, or it
+ the previous one successfully concluded with a successful DATA
+ command, or if the previous one was aborted with a RSET.
+
+ If the transaction beginning command argument is not acceptable, a
+ 501 failure reply MUST be returned and the SMTP server MUST stay in
+ the same state. If the commands in a transaction are out of order to
+ the degree that they cannot be processed by the server, a 503 failure
+ reply MUST be returned and the SMTP server MUST stay in the same
+ state.
+
+ The last command in a session MUST be the QUIT command. The QUIT
+ command cannot be used at any other time in a session, but SHOULD be
+ used by the client SMTP to request connection closure, even when no
+ session opening command was sent and accepted.
+
+4.1.5 Private-use Commands
+
+ As specified in section 2.2.2, commands starting in "X" may be used
+ by bilateral agreement between the client (sending) and server
+ (receiving) SMTP agents. An SMTP server that does not recognize such
+ a command is expected to reply with "500 Command not recognized". An
+ extended SMTP server MAY list the feature names associated with these
+ private commands in the response to the EHLO command.
+
+ Commands sent or accepted by SMTP systems that do not start with "X"
+ MUST conform to the requirements of section 2.2.2.
+
+4.2 SMTP Replies
+
+ Replies to SMTP commands serve to ensure the synchronization of
+ requests and actions in the process of mail transfer and to guarantee
+ that the SMTP client always knows the state of the SMTP server.
+ Every command MUST generate exactly one reply.
+
+
+
+
+Klensin Standards Track [Page 40]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ The details of the command-reply sequence are described in section
+ 4.3.
+
+ An SMTP reply consists of a three digit number (transmitted as three
+ numeric characters) followed by some text unless specified otherwise
+ in this document. The number is for use by automata to determine
+ what state to enter next; the text is for the human user. The three
+ digits contain enough encoded information that the SMTP client need
+ not examine the text and may either discard it or pass it on to the
+ user, as appropriate. Exceptions are as noted elsewhere in this
+ document. In particular, the 220, 221, 251, 421, and 551 reply codes
+ are associated with message text that must be parsed and interpreted
+ by machines. In the general case, the text may be receiver dependent
+ and context dependent, so there are likely to be varying texts for
+ each reply code. A discussion of the theory of reply codes is given
+ in section 4.2.1. Formally, a reply is defined to be the sequence: a
+ three-digit code, <SP>, one line of text, and <CRLF>, or a multiline
+ reply (as defined in section 4.2.1). Since, in violation of this
+ specification, the text is sometimes not sent, clients which do not
+ receive it SHOULD be prepared to process the code alone (with or
+ without a trailing space character). Only the EHLO, EXPN, and HELP
+ commands are expected to result in multiline replies in normal
+ circumstances, however, multiline replies are allowed for any
+ command.
+
+ In ABNF, server responses are:
+
+ Greeting = "220 " Domain [ SP text ] CRLF
+ Reply-line = Reply-code [ SP text ] CRLF
+
+ where "Greeting" appears only in the 220 response that announces that
+ the server is opening its part of the connection.
+
+ An SMTP server SHOULD send only the reply codes listed in this
+ document. An SMTP server SHOULD use the text shown in the examples
+ whenever appropriate.
+
+ An SMTP client MUST determine its actions only by the reply code, not
+ by the text (except for the "change of address" 251 and 551 and, if
+ necessary, 220, 221, and 421 replies); in the general case, any text,
+ including no text at all (although senders SHOULD NOT send bare
+ codes), MUST be acceptable. The space (blank) following the reply
+ code is considered part of the text. Whenever possible, a receiver-
+ SMTP SHOULD test the first digit (severity indication) of the reply
+ code.
+
+
+
+
+
+
+Klensin Standards Track [Page 41]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ The list of codes that appears below MUST NOT be construed as
+ permanent. While the addition of new codes should be a rare and
+ significant activity, with supplemental information in the textual
+ part of the response being preferred, new codes may be added as the
+ result of new Standards or Standards-track specifications.
+ Consequently, a sender-SMTP MUST be prepared to handle codes not
+ specified in this document and MUST do so by interpreting the first
+ digit only.
+
+4.2.1 Reply Code Severities and Theory
+
+ The three digits of the reply each have a special significance. The
+ first digit denotes whether the response is good, bad or incomplete.
+ An unsophisticated SMTP client, or one that receives an unexpected
+ code, will be able to determine its next action (proceed as planned,
+ redo, retrench, etc.) by examining this first digit. An SMTP client
+ that wants to know approximately what kind of error occurred (e.g.,
+ mail system error, command syntax error) may examine the second
+ digit. The third digit and any supplemental information that may be
+ present is reserved for the finest gradation of information.
+
+ There are five values for the first digit of the reply code:
+
+ 1yz Positive Preliminary reply
+ The command has been accepted, but the requested action is being
+ held in abeyance, pending confirmation of the information in this
+ reply. The SMTP client should send another command specifying
+ whether to continue or abort the action. Note: unextended SMTP
+ does not have any commands that allow this type of reply, and so
+ does not have continue or abort commands.
+
+ 2yz Positive Completion reply
+ The requested action has been successfully completed. A new
+ request may be initiated.
+
+ 3yz Positive Intermediate reply
+ The command has been accepted, but the requested action is being
+ held in abeyance, pending receipt of further information. The
+ SMTP client should send another command specifying this
+ information. This reply is used in command sequence groups (i.e.,
+ in DATA).
+
+ 4yz Transient Negative Completion reply
+ The command was not accepted, and the requested action did not
+ occur. However, the error condition is temporary and the action
+ may be requested again. The sender should return to the beginning
+ of the command sequence (if any). It is difficult to assign a
+ meaning to "transient" when two different sites (receiver- and
+
+
+
+Klensin Standards Track [Page 42]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ sender-SMTP agents) must agree on the interpretation. Each reply
+ in this category might have a different time value, but the SMTP
+ client is encouraged to try again. A rule of thumb to determine
+ whether a reply fits into the 4yz or the 5yz category (see below)
+ is that replies are 4yz if they can be successful if repeated
+ without any change in command form or in properties of the sender
+ or receiver (that is, the command is repeated identically and the
+ receiver does not put up a new implementation.)
+
+ 5yz Permanent Negative Completion reply
+ The command was not accepted and the requested action did not
+ occur. The SMTP client is discouraged from repeating the exact
+ request (in the same sequence). Even some "permanent" error
+ conditions can be corrected, so the human user may want to direct
+ the SMTP client to reinitiate the command sequence by direct
+ action at some point in the future (e.g., after the spelling has
+ been changed, or the user has altered the account status).
+
+ The second digit encodes responses in specific categories:
+
+ x0z Syntax: These replies refer to syntax errors, syntactically
+ correct commands that do not fit any functional category, and
+ unimplemented or superfluous commands.
+
+ x1z Information: These are replies to requests for information,
+ such as status or help.
+
+ x2z Connections: These are replies referring to the transmission
+ channel.
+
+ x3z Unspecified.
+
+ x4z Unspecified.
+
+ x5z Mail system: These replies indicate the status of the receiver
+ mail system vis-a-vis the requested transfer or other mail system
+ action.
+
+ The third digit gives a finer gradation of meaning in each category
+ specified by the second digit. The list of replies illustrates this.
+ Each reply text is recommended rather than mandatory, and may even
+ change according to the command with which it is associated. On the
+ other hand, the reply codes must strictly follow the specifications
+ in this section. Receiver implementations should not invent new
+ codes for slightly different situations from the ones described here,
+ but rather adapt codes already defined.
+
+
+
+
+
+Klensin Standards Track [Page 43]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ For example, a command such as NOOP, whose successful execution does
+ not offer the SMTP client any new information, will return a 250
+ reply. The reply is 502 when the command requests an unimplemented
+ non-site-specific action. A refinement of that is the 504 reply for
+ a command that is implemented, but that requests an unimplemented
+ parameter.
+
+ The reply text may be longer than a single line; in these cases the
+ complete text must be marked so the SMTP client knows when it can
+ stop reading the reply. This requires a special format to indicate a
+ multiple line reply.
+
+ The format for multiline replies requires that every line, except the
+ last, begin with the reply code, followed immediately by a hyphen,
+ "-" (also known as minus), followed by text. The last line will
+ begin with the reply code, followed immediately by <SP>, optionally
+ some text, and <CRLF>. As noted above, servers SHOULD send the <SP>
+ if subsequent text is not sent, but clients MUST be prepared for it
+ to be omitted.
+
+ For example:
+
+ 123-First line
+ 123-Second line
+ 123-234 text beginning with numbers
+ 123 The last line
+
+ In many cases the SMTP client then simply needs to search for a line
+ beginning with the reply code followed by <SP> or <CRLF> and ignore
+ all preceding lines. In a few cases, there is important data for the
+ client in the reply "text". The client will be able to identify
+ these cases from the current context.
+
+4.2.2 Reply Codes by Function Groups
+
+ 500 Syntax error, command unrecognized
+ (This may include errors such as command line too long)
+ 501 Syntax error in parameters or arguments
+ 502 Command not implemented (see section 4.2.4)
+ 503 Bad sequence of commands
+ 504 Command parameter not implemented
+
+ 211 System status, or system help reply
+ 214 Help message
+ (Information on how to use the receiver or the meaning of a
+ particular non-standard command; this reply is useful only
+ to the human user)
+
+
+
+
+Klensin Standards Track [Page 44]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ 220 <domain> Service ready
+ 221 <domain> Service closing transmission channel
+ 421 <domain> Service not available, closing transmission channel
+ (This may be a reply to any command if the service knows it
+ must shut down)
+
+ 250 Requested mail action okay, completed
+ 251 User not local; will forward to <forward-path>
+ (See section 3.4)
+ 252 Cannot VRFY user, but will accept message and attempt
+ delivery
+ (See section 3.5.3)
+ 450 Requested mail action not taken: mailbox unavailable
+ (e.g., mailbox busy)
+ 550 Requested action not taken: mailbox unavailable
+ (e.g., mailbox not found, no access, or command rejected
+ for policy reasons)
+ 451 Requested action aborted: error in processing
+ 551 User not local; please try <forward-path>
+ (See section 3.4)
+ 452 Requested action not taken: insufficient system storage
+ 552 Requested mail action aborted: exceeded storage allocation
+ 553 Requested action not taken: mailbox name not allowed
+ (e.g., mailbox syntax incorrect)
+ 354 Start mail input; end with <CRLF>.<CRLF>
+ 554 Transaction failed (Or, in the case of a connection-opening
+ response, "No SMTP service here")
+
+4.2.3 Reply Codes in Numeric Order
+
+ 211 System status, or system help reply
+ 214 Help message
+ (Information on how to use the receiver or the meaning of a
+ particular non-standard command; this reply is useful only
+ to the human user)
+ 220 <domain> Service ready
+ 221 <domain> Service closing transmission channel
+ 250 Requested mail action okay, completed
+ 251 User not local; will forward to <forward-path>
+ (See section 3.4)
+ 252 Cannot VRFY user, but will accept message and attempt
+ delivery
+ (See section 3.5.3)
+
+ 354 Start mail input; end with <CRLF>.<CRLF>
+
+
+
+
+
+
+Klensin Standards Track [Page 45]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ 421 <domain> Service not available, closing transmission channel
+ (This may be a reply to any command if the service knows it
+ must shut down)
+ 450 Requested mail action not taken: mailbox unavailable
+ (e.g., mailbox busy)
+ 451 Requested action aborted: local error in processing
+ 452 Requested action not taken: insufficient system storage
+ 500 Syntax error, command unrecognized
+ (This may include errors such as command line too long)
+ 501 Syntax error in parameters or arguments
+ 502 Command not implemented (see section 4.2.4)
+ 503 Bad sequence of commands
+ 504 Command parameter not implemented
+ 550 Requested action not taken: mailbox unavailable
+ (e.g., mailbox not found, no access, or command rejected
+ for policy reasons)
+ 551 User not local; please try <forward-path>
+ (See section 3.4)
+ 552 Requested mail action aborted: exceeded storage allocation
+ 553 Requested action not taken: mailbox name not allowed
+ (e.g., mailbox syntax incorrect)
+ 554 Transaction failed (Or, in the case of a connection-opening
+ response, "No SMTP service here")
+
+4.2.4 Reply Code 502
+
+ Questions have been raised as to when reply code 502 (Command not
+ implemented) SHOULD be returned in preference to other codes. 502
+ SHOULD be used when the command is actually recognized by the SMTP
+ server, but not implemented. If the command is not recognized, code
+ 500 SHOULD be returned. Extended SMTP systems MUST NOT list
+ capabilities in response to EHLO for which they will return 502 (or
+ 500) replies.
+
+4.2.5 Reply Codes After DATA and the Subsequent <CRLF>.<CRLF>
+
+ When an SMTP server returns a positive completion status (2yz code)
+ after the DATA command is completed with <CRLF>.<CRLF>, it accepts
+ responsibility for:
+
+ - delivering the message (if the recipient mailbox exists), or
+
+ - if attempts to deliver the message fail due to transient
+ conditions, retrying delivery some reasonable number of times at
+ intervals as specified in section 4.5.4.
+
+
+
+
+
+
+Klensin Standards Track [Page 46]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ - if attempts to deliver the message fail due to permanent
+ conditions, or if repeated attempts to deliver the message fail
+ due to transient conditions, returning appropriate notification to
+ the sender of the original message (using the address in the SMTP
+ MAIL command).
+
+ When an SMTP server returns a permanent error status (5yz) code after
+ the DATA command is completed with <CRLF>.<CRLF>, it MUST NOT make
+ any subsequent attempt to deliver that message. The SMTP client
+ retains responsibility for delivery of that message and may either
+ return it to the user or requeue it for a subsequent attempt (see
+ section 4.5.4.1).
+
+ The user who originated the message SHOULD be able to interpret the
+ return of a transient failure status (by mail message or otherwise)
+ as a non-delivery indication, just as a permanent failure would be
+ interpreted. I.e., if the client SMTP successfully handles these
+ conditions, the user will not receive such a reply.
+
+ When an SMTP server returns a permanent error status (5yz) code after
+ the DATA command is completely with <CRLF>.<CRLF>, it MUST NOT make
+ any subsequent attempt to deliver the message. As with temporary
+ error status codes, the SMTP client retains responsibility for the
+ message, but SHOULD not again attempt delivery to the same server
+ without user review and intervention of the message.
+
+4.3 Sequencing of Commands and Replies
+
+4.3.1 Sequencing Overview
+
+ The communication between the sender and receiver is an alternating
+ dialogue, controlled by the sender. As such, the sender issues a
+ command and the receiver responds with a reply. Unless other
+ arrangements are negotiated through service extensions, the sender
+ MUST wait for this response before sending further commands.
+
+ One important reply is the connection greeting. Normally, a receiver
+ will send a 220 "Service ready" reply when the connection is
+ completed. The sender SHOULD wait for this greeting message before
+ sending any commands.
+
+ Note: all the greeting-type replies have the official name (the
+ fully-qualified primary domain name) of the server host as the first
+ word following the reply code. Sometimes the host will have no
+ meaningful name. See 4.1.3 for a discussion of alternatives in these
+ situations.
+
+
+
+
+
+Klensin Standards Track [Page 47]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ For example,
+
+ 220 ISIF.USC.EDU Service ready
+ or
+ 220 mail.foo.com SuperSMTP v 6.1.2 Service ready
+ or
+ 220 [10.0.0.1] Clueless host service ready
+
+ The table below lists alternative success and failure replies for
+ each command. These SHOULD be strictly adhered to: a receiver may
+ substitute text in the replies, but the meaning and action implied by
+ the code numbers and by the specific command reply sequence cannot be
+ altered.
+
+4.3.2 Command-Reply Sequences
+
+ Each command is listed with its usual possible replies. The prefixes
+ used before the possible replies are "I" for intermediate, "S" for
+ success, and "E" for error. Since some servers may generate other
+ replies under special circumstances, and to allow for future
+ extension, SMTP clients SHOULD, when possible, interpret only the
+ first digit of the reply and MUST be prepared to deal with
+ unrecognized reply codes by interpreting the first digit only.
+ Unless extended using the mechanisms described in section 2.2, SMTP
+ servers MUST NOT transmit reply codes to an SMTP client that are
+ other than three digits or that do not start in a digit between 2 and
+ 5 inclusive.
+
+ These sequencing rules and, in principle, the codes themselves, can
+ be extended or modified by SMTP extensions offered by the server and
+ accepted (requested) by the client.
+
+ In addition to the codes listed below, any SMTP command can return
+ any of the following codes if the corresponding unusual circumstances
+ are encountered:
+
+ 500 For the "command line too long" case or if the command name was
+ not recognized. Note that producing a "command not recognized"
+ error in response to the required subset of these commands is a
+ violation of this specification.
+
+ 501 Syntax error in command or arguments. In order to provide for
+ future extensions, commands that are specified in this document as
+ not accepting arguments (DATA, RSET, QUIT) SHOULD return a 501
+ message if arguments are supplied in the absence of EHLO-
+ advertised extensions.
+
+ 421 Service shutting down and closing transmission channel
+
+
+
+Klensin Standards Track [Page 48]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ Specific sequences are:
+
+ CONNECTION ESTABLISHMENT
+ S: 220
+ E: 554
+ EHLO or HELO
+ S: 250
+ E: 504, 550
+ MAIL
+ S: 250
+ E: 552, 451, 452, 550, 553, 503
+ RCPT
+ S: 250, 251 (but see section 3.4 for discussion of 251 and 551)
+ E: 550, 551, 552, 553, 450, 451, 452, 503, 550
+ DATA
+ I: 354 -> data -> S: 250
+ E: 552, 554, 451, 452
+ E: 451, 554, 503
+ RSET
+ S: 250
+ VRFY
+ S: 250, 251, 252
+ E: 550, 551, 553, 502, 504
+ EXPN
+ S: 250, 252
+ E: 550, 500, 502, 504
+ HELP
+ S: 211, 214
+ E: 502, 504
+ NOOP
+ S: 250
+ QUIT
+ S: 221
+
+4.4 Trace Information
+
+ When an SMTP server receives a message for delivery or further
+ processing, it MUST insert trace ("time stamp" or "Received")
+ information at the beginning of the message content, as discussed in
+ section 4.1.1.4.
+
+ This line MUST be structured as follows:
+
+ - The FROM field, which MUST be supplied in an SMTP environment,
+ SHOULD contain both (1) the name of the source host as presented
+ in the EHLO command and (2) an address literal containing the IP
+ address of the source, determined from the TCP connection.
+
+
+
+
+Klensin Standards Track [Page 49]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ - The ID field MAY contain an "@" as suggested in RFC 822, but this
+ is not required.
+
+ - The FOR field MAY contain a list of <path> entries when multiple
+ RCPT commands have been given. This may raise some security
+ issues and is usually not desirable; see section 7.2.
+
+ An Internet mail program MUST NOT change a Received: line that was
+ previously added to the message header. SMTP servers MUST prepend
+ Received lines to messages; they MUST NOT change the order of
+ existing lines or insert Received lines in any other location.
+
+ As the Internet grows, comparability of Received fields is important
+ for detecting problems, especially slow relays. SMTP servers that
+ create Received fields SHOULD use explicit offsets in the dates
+ (e.g., -0800), rather than time zone names of any type. Local time
+ (with an offset) is preferred to UT when feasible. This formulation
+ allows slightly more information about local circumstances to be
+ specified. If UT is needed, the receiver need merely do some simple
+ arithmetic to convert the values. Use of UT loses information about
+ the time zone-location of the server. If it is desired to supply a
+ time zone name, it SHOULD be included in a comment.
+
+ When the delivery SMTP server makes the "final delivery" of a
+ message, it inserts a return-path line at the beginning of the mail
+ data. This use of return-path is required; mail systems MUST support
+ it. The return-path line preserves the information in the <reverse-
+ path> from the MAIL command. Here, final delivery means the message
+ has left the SMTP environment. Normally, this would mean it had been
+ delivered to the destination user or an associated mail drop, but in
+ some cases it may be further processed and transmitted by another
+ mail system.
+
+ It is possible for the mailbox in the return path to be different
+ from the actual sender's mailbox, for example, if error responses are
+ to be delivered to a special error handling mailbox rather than to
+ the message sender. When mailing lists are involved, this
+ arrangement is common and useful as a means of directing errors to
+ the list maintainer rather than the message originator.
+
+ The text above implies that the final mail data will begin with a
+ return path line, followed by one or more time stamp lines. These
+ lines will be followed by the mail data headers and body [32].
+
+ It is sometimes difficult for an SMTP server to determine whether or
+ not it is making final delivery since forwarding or other operations
+ may occur after the message is accepted for delivery. Consequently,
+
+
+
+
+Klensin Standards Track [Page 50]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ any further (forwarding, gateway, or relay) systems MAY remove the
+ return path and rebuild the MAIL command as needed to ensure that
+ exactly one such line appears in a delivered message.
+
+ A message-originating SMTP system SHOULD NOT send a message that
+ already contains a Return-path header. SMTP servers performing a
+ relay function MUST NOT inspect the message data, and especially not
+ to the extent needed to determine if Return-path headers are present.
+ SMTP servers making final delivery MAY remove Return-path headers
+ before adding their own.
+
+ The primary purpose of the Return-path is to designate the address to
+ which messages indicating non-delivery or other mail system failures
+ are to be sent. For this to be unambiguous, exactly one return path
+ SHOULD be present when the message is delivered. Systems using RFC
+ 822 syntax with non-SMTP transports SHOULD designate an unambiguous
+ address, associated with the transport envelope, to which error
+ reports (e.g., non-delivery messages) should be sent.
+
+ Historical note: Text in RFC 822 that appears to contradict the use
+ of the Return-path header (or the envelope reverse path address from
+ the MAIL command) as the destination for error messages is not
+ applicable on the Internet. The reverse path address (as copied into
+ the Return-path) MUST be used as the target of any mail containing
+ delivery error messages.
+
+ In particular:
+
+ - a gateway from SMTP->elsewhere SHOULD insert a return-path header,
+ unless it is known that the "elsewhere" transport also uses
+ Internet domain addresses and maintains the envelope sender
+ address separately.
+
+ - a gateway from elsewhere->SMTP SHOULD delete any return-path
+ header present in the message, and either copy that information to
+ the SMTP envelope or combine it with information present in the
+ envelope of the other transport system to construct the reverse
+ path argument to the MAIL command in the SMTP envelope.
+
+ The server must give special treatment to cases in which the
+ processing following the end of mail data indication is only
+ partially successful. This could happen if, after accepting several
+ recipients and the mail data, the SMTP server finds that the mail
+ data could be successfully delivered to some, but not all, of the
+ recipients. In such cases, the response to the DATA command MUST be
+ an OK reply. However, the SMTP server MUST compose and send an
+ "undeliverable mail" notification message to the originator of the
+ message.
+
+
+
+Klensin Standards Track [Page 51]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ A single notification listing all of the failed recipients or
+ separate notification messages MUST be sent for each failed
+ recipient. For economy of processing by the sender, the former is
+ preferred when possible. All undeliverable mail notification
+ messages are sent using the MAIL command (even if they result from
+ processing the obsolete SEND, SOML, or SAML commands) and use a null
+ return path as discussed in section 3.7.
+
+ The time stamp line and the return path line are formally defined as
+ follows:
+
+Return-path-line = "Return-Path:" FWS Reverse-path <CRLF>
+
+Time-stamp-line = "Received:" FWS Stamp <CRLF>
+
+Stamp = From-domain By-domain Opt-info ";" FWS date-time
+
+ ; where "date-time" is as defined in [32]
+ ; but the "obs-" forms, especially two-digit
+ ; years, are prohibited in SMTP and MUST NOT be used.
+
+From-domain = "FROM" FWS Extended-Domain CFWS
+
+By-domain = "BY" FWS Extended-Domain CFWS
+
+Extended-Domain = Domain /
+ ( Domain FWS "(" TCP-info ")" ) /
+ ( Address-literal FWS "(" TCP-info ")" )
+
+TCP-info = Address-literal / ( Domain FWS Address-literal )
+ ; Information derived by server from TCP connection
+ ; not client EHLO.
+
+Opt-info = [Via] [With] [ID] [For]
+
+Via = "VIA" FWS Link CFWS
+
+With = "WITH" FWS Protocol CFWS
+
+ID = "ID" FWS String / msg-id CFWS
+
+For = "FOR" FWS 1*( Path / Mailbox ) CFWS
+
+Link = "TCP" / Addtl-Link
+Addtl-Link = Atom
+ ; Additional standard names for links are registered with the
+ ; Internet Assigned Numbers Authority (IANA). "Via" is
+ ; primarily of value with non-Internet transports. SMTP
+
+
+
+Klensin Standards Track [Page 52]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ ; servers SHOULD NOT use unregistered names.
+Protocol = "ESMTP" / "SMTP" / Attdl-Protocol
+Attdl-Protocol = Atom
+ ; Additional standard names for protocols are registered with the
+ ; Internet Assigned Numbers Authority (IANA). SMTP servers
+ ; SHOULD NOT use unregistered names.
+
+4.5 Additional Implementation Issues
+
+4.5.1 Minimum Implementation
+
+ In order to make SMTP workable, the following minimum implementation
+ is required for all receivers. The following commands MUST be
+ supported to conform to this specification:
+
+ EHLO
+ HELO
+ MAIL
+ RCPT
+ DATA
+ RSET
+ NOOP
+ QUIT
+ VRFY
+
+ Any system that includes an SMTP server supporting mail relaying or
+ delivery MUST support the reserved mailbox "postmaster" as a case-
+ insensitive local name. This postmaster address is not strictly
+ necessary if the server always returns 554 on connection opening (as
+ described in section 3.1). The requirement to accept mail for
+ postmaster implies that RCPT commands which specify a mailbox for
+ postmaster at any of the domains for which the SMTP server provides
+ mail service, as well as the special case of "RCPT TO:<Postmaster>"
+ (with no domain specification), MUST be supported.
+
+ SMTP systems are expected to make every reasonable effort to accept
+ mail directed to Postmaster from any other system on the Internet.
+ In extreme cases --such as to contain a denial of service attack or
+ other breach of security-- an SMTP server may block mail directed to
+ Postmaster. However, such arrangements SHOULD be narrowly tailored
+ so as to avoid blocking messages which are not part of such attacks.
+
+4.5.2 Transparency
+
+ Without some provision for data transparency, the character sequence
+ "<CRLF>.<CRLF>" ends the mail text and cannot be sent by the user.
+ In general, users are not aware of such "forbidden" sequences. To
+
+
+
+
+Klensin Standards Track [Page 53]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ allow all user composed text to be transmitted transparently, the
+ following procedures are used:
+
+ - Before sending a line of mail text, the SMTP client checks the
+ first character of the line. If it is a period, one additional
+ period is inserted at the beginning of the line.
+
+ - When a line of mail text is received by the SMTP server, it checks
+ the line. If the line is composed of a single period, it is
+ treated as the end of mail indicator. If the first character is a
+ period and there are other characters on the line, the first
+ character is deleted.
+
+ The mail data may contain any of the 128 ASCII characters. All
+ characters are to be delivered to the recipient's mailbox, including
+ spaces, vertical and horizontal tabs, and other control characters.
+ If the transmission channel provides an 8-bit byte (octet) data
+ stream, the 7-bit ASCII codes are transmitted right justified in the
+ octets, with the high order bits cleared to zero. See 3.7 for
+ special treatment of these conditions in SMTP systems serving a relay
+ function.
+
+ In some systems it may be necessary to transform the data as it is
+ received and stored. This may be necessary for hosts that use a
+ different character set than ASCII as their local character set, that
+ store data in records rather than strings, or which use special
+ character sequences as delimiters inside mailboxes. If such
+ transformations are necessary, they MUST be reversible, especially if
+ they are applied to mail being relayed.
+
+4.5.3 Sizes and Timeouts
+
+4.5.3.1 Size limits and minimums
+
+ There are several objects that have required minimum/maximum sizes.
+ Every implementation MUST be able to receive objects of at least
+ these sizes. Objects larger than these sizes SHOULD be avoided when
+ possible. However, some Internet mail constructs such as encoded
+ X.400 addresses [16] will often require larger objects: clients MAY
+ attempt to transmit these, but MUST be prepared for a server to
+ reject them if they cannot be handled by it. To the maximum extent
+ possible, implementation techniques which impose no limits on the
+ length of these objects should be used.
+
+ local-part
+ The maximum total length of a user name or other local-part is 64
+ characters.
+
+
+
+
+Klensin Standards Track [Page 54]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ domain
+ The maximum total length of a domain name or number is 255
+ characters.
+
+ path
+ The maximum total length of a reverse-path or forward-path is 256
+ characters (including the punctuation and element separators).
+
+ command line
+ The maximum total length of a command line including the command
+ word and the <CRLF> is 512 characters. SMTP extensions may be
+ used to increase this limit.
+
+ reply line
+ The maximum total length of a reply line including the reply code
+ and the <CRLF> is 512 characters. More information may be
+ conveyed through multiple-line replies.
+
+ text line
+ The maximum total length of a text line including the <CRLF> is
+ 1000 characters (not counting the leading dot duplicated for
+ transparency). This number may be increased by the use of SMTP
+ Service Extensions.
+
+ message content
+ The maximum total length of a message content (including any
+ message headers as well as the message body) MUST BE at least 64K
+ octets. Since the introduction of Internet standards for
+ multimedia mail [12], message lengths on the Internet have grown
+ dramatically, and message size restrictions should be avoided if
+ at all possible. SMTP server systems that must impose
+ restrictions SHOULD implement the "SIZE" service extension [18],
+ and SMTP client systems that will send large messages SHOULD
+ utilize it when possible.
+
+ recipients buffer
+ The minimum total number of recipients that must be buffered is
+ 100 recipients. Rejection of messages (for excessive recipients)
+ with fewer than 100 RCPT commands is a violation of this
+ specification. The general principle that relaying SMTP servers
+ MUST NOT, and delivery SMTP servers SHOULD NOT, perform validation
+ tests on message headers suggests that rejecting a message based
+ on the total number of recipients shown in header fields is to be
+ discouraged. A server which imposes a limit on the number of
+ recipients MUST behave in an orderly fashion, such as to reject
+ additional addresses over its limit rather than silently
+ discarding addresses previously accepted. A client that needs to
+
+
+
+
+Klensin Standards Track [Page 55]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ deliver a message containing over 100 RCPT commands SHOULD be
+ prepared to transmit in 100-recipient "chunks" if the server
+ declines to accept more than 100 recipients in a single message.
+
+ Errors due to exceeding these limits may be reported by using the
+ reply codes. Some examples of reply codes are:
+
+ 500 Line too long.
+ or
+ 501 Path too long
+ or
+ 452 Too many recipients (see below)
+ or
+ 552 Too much mail data.
+
+ RFC 821 [30] incorrectly listed the error where an SMTP server
+ exhausts its implementation limit on the number of RCPT commands
+ ("too many recipients") as having reply code 552. The correct reply
+ code for this condition is 452. Clients SHOULD treat a 552 code in
+ this case as a temporary, rather than permanent, failure so the logic
+ below works.
+
+ When a conforming SMTP server encounters this condition, it has at
+ least 100 successful RCPT commands in its recipients buffer. If the
+ server is able to accept the message, then at least these 100
+ addresses will be removed from the SMTP client's queue. When the
+ client attempts retransmission of those addresses which received 452
+ responses, at least 100 of these will be able to fit in the SMTP
+ server's recipients buffer. Each retransmission attempt which is
+ able to deliver anything will be able to dispose of at least 100 of
+ these recipients.
+
+ If an SMTP server has an implementation limit on the number of RCPT
+ commands and this limit is exhausted, it MUST use a response code of
+ 452 (but the client SHOULD also be prepared for a 552, as noted
+ above). If the server has a configured site-policy limitation on the
+ number of RCPT commands, it MAY instead use a 5XX response code.
+ This would be most appropriate if the policy limitation was intended
+ to apply if the total recipient count for a particular message body
+ were enforced even if that message body was sent in multiple mail
+ transactions.
+
+4.5.3.2 Timeouts
+
+ An SMTP client MUST provide a timeout mechanism. It MUST use per-
+ command timeouts rather than somehow trying to time the entire mail
+ transaction. Timeouts SHOULD be easily reconfigurable, preferably
+ without recompiling the SMTP code. To implement this, a timer is set
+
+
+
+Klensin Standards Track [Page 56]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ for each SMTP command and for each buffer of the data transfer. The
+ latter means that the overall timeout is inherently proportional to
+ the size of the message.
+
+ Based on extensive experience with busy mail-relay hosts, the minimum
+ per-command timeout values SHOULD be as follows:
+
+ Initial 220 Message: 5 minutes
+ An SMTP client process needs to distinguish between a failed TCP
+ connection and a delay in receiving the initial 220 greeting
+ message. Many SMTP servers accept a TCP connection but delay
+ delivery of the 220 message until their system load permits more
+ mail to be processed.
+
+ MAIL Command: 5 minutes
+
+ RCPT Command: 5 minutes
+ A longer timeout is required if processing of mailing lists and
+ aliases is not deferred until after the message was accepted.
+
+ DATA Initiation: 2 minutes
+ This is while awaiting the "354 Start Input" reply to a DATA
+ command.
+
+ Data Block: 3 minutes
+ This is while awaiting the completion of each TCP SEND call
+ transmitting a chunk of data.
+
+ DATA Termination: 10 minutes.
+ This is while awaiting the "250 OK" reply. When the receiver gets
+ the final period terminating the message data, it typically
+ performs processing to deliver the message to a user mailbox. A
+ spurious timeout at this point would be very wasteful and would
+ typically result in delivery of multiple copies of the message,
+ since it has been successfully sent and the server has accepted
+ responsibility for delivery. See section 6.1 for additional
+ discussion.
+
+ An SMTP server SHOULD have a timeout of at least 5 minutes while it
+ is awaiting the next command from the sender.
+
+4.5.4 Retry Strategies
+
+ The common structure of a host SMTP implementation includes user
+ mailboxes, one or more areas for queuing messages in transit, and one
+ or more daemon processes for sending and receiving mail. The exact
+ structure will vary depending on the needs of the users on the host
+
+
+
+
+Klensin Standards Track [Page 57]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ and the number and size of mailing lists supported by the host. We
+ describe several optimizations that have proved helpful, particularly
+ for mailers supporting high traffic levels.
+
+ Any queuing strategy MUST include timeouts on all activities on a
+ per-command basis. A queuing strategy MUST NOT send error messages
+ in response to error messages under any circumstances.
+
+4.5.4.1 Sending Strategy
+
+ The general model for an SMTP client is one or more processes that
+ periodically attempt to transmit outgoing mail. In a typical system,
+ the program that composes a message has some method for requesting
+ immediate attention for a new piece of outgoing mail, while mail that
+ cannot be transmitted immediately MUST be queued and periodically
+ retried by the sender. A mail queue entry will include not only the
+ message itself but also the envelope information.
+
+ The sender MUST delay retrying a particular destination after one
+ attempt has failed. In general, the retry interval SHOULD be at
+ least 30 minutes; however, more sophisticated and variable strategies
+ will be beneficial when the SMTP client can determine the reason for
+ non-delivery.
+
+ Retries continue until the message is transmitted or the sender gives
+ up; the give-up time generally needs to be at least 4-5 days. The
+ parameters to the retry algorithm MUST be configurable.
+
+ A client SHOULD keep a list of hosts it cannot reach and
+ corresponding connection timeouts, rather than just retrying queued
+ mail items.
+
+ Experience suggests that failures are typically transient (the target
+ system or its connection has crashed), favoring a policy of two
+ connection attempts in the first hour the message is in the queue,
+ and then backing off to one every two or three hours.
+
+ The SMTP client can shorten the queuing delay in cooperation with the
+ SMTP server. For example, if mail is received from a particular
+ address, it is likely that mail queued for that host can now be sent.
+ Application of this principle may, in many cases, eliminate the
+ requirement for an explicit "send queues now" function such as ETRN
+ [9].
+
+ The strategy may be further modified as a result of multiple
+ addresses per host (see below) to optimize delivery time vs. resource
+ usage.
+
+
+
+
+Klensin Standards Track [Page 58]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ An SMTP client may have a large queue of messages for each
+ unavailable destination host. If all of these messages were retried
+ in every retry cycle, there would be excessive Internet overhead and
+ the sending system would be blocked for a long period. Note that an
+ SMTP client can generally determine that a delivery attempt has
+ failed only after a timeout of several minutes and even a one-minute
+ timeout per connection will result in a very large delay if retries
+ are repeated for dozens, or even hundreds, of queued messages to the
+ same host.
+
+ At the same time, SMTP clients SHOULD use great care in caching
+ negative responses from servers. In an extreme case, if EHLO is
+ issued multiple times during the same SMTP connection, different
+ answers may be returned by the server. More significantly, 5yz
+ responses to the MAIL command MUST NOT be cached.
+
+ When a mail message is to be delivered to multiple recipients, and
+ the SMTP server to which a copy of the message is to be sent is the
+ same for multiple recipients, then only one copy of the message
+ SHOULD be transmitted. That is, the SMTP client SHOULD use the
+ command sequence: MAIL, RCPT, RCPT,... RCPT, DATA instead of the
+ sequence: MAIL, RCPT, DATA, ..., MAIL, RCPT, DATA. However, if there
+ are very many addresses, a limit on the number of RCPT commands per
+ MAIL command MAY be imposed. Implementation of this efficiency
+ feature is strongly encouraged.
+
+ Similarly, to achieve timely delivery, the SMTP client MAY support
+ multiple concurrent outgoing mail transactions. However, some limit
+ may be appropriate to protect the host from devoting all its
+ resources to mail.
+
+4.5.4.2 Receiving Strategy
+
+ The SMTP server SHOULD attempt to keep a pending listen on the SMTP
+ port at all times. This requires the support of multiple incoming
+ TCP connections for SMTP. Some limit MAY be imposed but servers that
+ cannot handle more than one SMTP transaction at a time are not in
+ conformance with the intent of this specification.
+
+ As discussed above, when the SMTP server receives mail from a
+ particular host address, it could activate its own SMTP queuing
+ mechanisms to retry any mail pending for that host address.
+
+4.5.5 Messages with a null reverse-path
+
+ There are several types of notification messages which are required
+ by existing and proposed standards to be sent with a null reverse
+ path, namely non-delivery notifications as discussed in section 3.7,
+
+
+
+Klensin Standards Track [Page 59]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ other kinds of Delivery Status Notifications (DSNs) [24], and also
+ Message Disposition Notifications (MDNs) [10]. All of these kinds of
+ messages are notifications about a previous message, and they are
+ sent to the reverse-path of the previous mail message. (If the
+ delivery of such a notification message fails, that usually indicates
+ a problem with the mail system of the host to which the notification
+ message is addressed. For this reason, at some hosts the MTA is set
+ up to forward such failed notification messages to someone who is
+ able to fix problems with the mail system, e.g., via the postmaster
+ alias.)
+
+ All other types of messages (i.e., any message which is not required
+ by a standards-track RFC to have a null reverse-path) SHOULD be sent
+ with with a valid, non-null reverse-path.
+
+ Implementors of automated email processors should be careful to make
+ sure that the various kinds of messages with null reverse-path are
+ handled correctly, in particular such systems SHOULD NOT reply to
+ messages with null reverse-path.
+
+5. Address Resolution and Mail Handling
+
+ Once an SMTP client lexically identifies a domain to which mail will
+ be delivered for processing (as described in sections 3.6 and 3.7), a
+ DNS lookup MUST be performed to resolve the domain name [22]. The
+ names are expected to be fully-qualified domain names (FQDNs):
+ mechanisms for inferring FQDNs from partial names or local aliases
+ are outside of this specification and, due to a history of problems,
+ are generally discouraged. The lookup first attempts to locate an MX
+ record associated with the name. If a CNAME record is found instead,
+ the resulting name is processed as if it were the initial name. If
+ no MX records are found, but an A RR is found, the A RR is treated as
+ if it was associated with an implicit MX RR, with a preference of 0,
+ pointing to that host. If one or more MX RRs are found for a given
+ name, SMTP systems MUST NOT utilize any A RRs associated with that
+ name unless they are located using the MX RRs; the "implicit MX" rule
+ above applies only if there are no MX records present. If MX records
+ are present, but none of them are usable, this situation MUST be
+ reported as an error.
+
+ When the lookup succeeds, the mapping can result in a list of
+ alternative delivery addresses rather than a single address, because
+ of multiple MX records, multihoming, or both. To provide reliable
+ mail transmission, the SMTP client MUST be able to try (and retry)
+ each of the relevant addresses in this list in order, until a
+ delivery attempt succeeds. However, there MAY also be a configurable
+ limit on the number of alternate addresses that can be tried. In any
+ case, the SMTP client SHOULD try at least two addresses.
+
+
+
+Klensin Standards Track [Page 60]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ Two types of information is used to rank the host addresses: multiple
+ MX records, and multihomed hosts.
+
+ Multiple MX records contain a preference indication that MUST be used
+ in sorting (see below). Lower numbers are more preferred than higher
+ ones. If there are multiple destinations with the same preference
+ and there is no clear reason to favor one (e.g., by recognition of an
+ easily-reached address), then the sender-SMTP MUST randomize them to
+ spread the load across multiple mail exchangers for a specific
+ organization.
+
+ The destination host (perhaps taken from the preferred MX record) may
+ be multihomed, in which case the domain name resolver will return a
+ list of alternative IP addresses. It is the responsibility of the
+ domain name resolver interface to have ordered this list by
+ decreasing preference if necessary, and SMTP MUST try them in the
+ order presented.
+
+ Although the capability to try multiple alternative addresses is
+ required, specific installations may want to limit or disable the use
+ of alternative addresses. The question of whether a sender should
+ attempt retries using the different addresses of a multihomed host
+ has been controversial. The main argument for using the multiple
+ addresses is that it maximizes the probability of timely delivery,
+ and indeed sometimes the probability of any delivery; the counter-
+ argument is that it may result in unnecessary resource use. Note
+ that resource use is also strongly determined by the sending strategy
+ discussed in section 4.5.4.1.
+
+ If an SMTP server receives a message with a destination for which it
+ is a designated Mail eXchanger, it MAY relay the message (potentially
+ after having rewritten the MAIL FROM and/or RCPT TO addresses), make
+ final delivery of the message, or hand it off using some mechanism
+ outside the SMTP-provided transport environment. Of course, neither
+ of the latter require that the list of MX records be examined
+ further.
+
+ If it determines that it should relay the message without rewriting
+ the address, it MUST sort the MX records to determine candidates for
+ delivery. The records are first ordered by preference, with the
+ lowest-numbered records being most preferred. The relay host MUST
+ then inspect the list for any of the names or addresses by which it
+ might be known in mail transactions. If a matching record is found,
+ all records at that preference level and higher-numbered ones MUST be
+ discarded from consideration. If there are no records left at that
+ point, it is an error condition, and the message MUST be returned as
+ undeliverable. If records do remain, they SHOULD be tried, best
+ preference first, as described above.
+
+
+
+Klensin Standards Track [Page 61]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+6. Problem Detection and Handling
+
+6.1 Reliable Delivery and Replies by Email
+
+ When the receiver-SMTP accepts a piece of mail (by sending a "250 OK"
+ message in response to DATA), it is accepting responsibility for
+ delivering or relaying the message. It must take this responsibility
+ seriously. It MUST NOT lose the message for frivolous reasons, such
+ as because the host later crashes or because of a predictable
+ resource shortage.
+
+ If there is a delivery failure after acceptance of a message, the
+ receiver-SMTP MUST formulate and mail a notification message. This
+ notification MUST be sent using a null ("<>") reverse path in the
+ envelope. The recipient of this notification MUST be the address
+ from the envelope return path (or the Return-Path: line). However,
+ if this address is null ("<>"), the receiver-SMTP MUST NOT send a
+ notification. Obviously, nothing in this section can or should
+ prohibit local decisions (i.e., as part of the same system
+ environment as the receiver-SMTP) to log or otherwise transmit
+ information about null address events locally if that is desired. If
+ the address is an explicit source route, it MUST be stripped down to
+ its final hop.
+
+ For example, suppose that an error notification must be sent for a
+ message that arrived with:
+
+ MAIL FROM:<@a,@b:user@d>
+
+ The notification message MUST be sent using:
+
+ RCPT TO:<user@d>
+
+ Some delivery failures after the message is accepted by SMTP will be
+ unavoidable. For example, it may be impossible for the receiving
+ SMTP server to validate all the delivery addresses in RCPT command(s)
+ due to a "soft" domain system error, because the target is a mailing
+ list (see earlier discussion of RCPT), or because the server is
+ acting as a relay and has no immediate access to the delivering
+ system.
+
+ To avoid receiving duplicate messages as the result of timeouts, a
+ receiver-SMTP MUST seek to minimize the time required to respond to
+ the final <CRLF>.<CRLF> end of data indicator. See RFC 1047 [28] for
+ a discussion of this problem.
+
+
+
+
+
+
+Klensin Standards Track [Page 62]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+6.2 Loop Detection
+
+ Simple counting of the number of "Received:" headers in a message has
+ proven to be an effective, although rarely optimal, method of
+ detecting loops in mail systems. SMTP servers using this technique
+ SHOULD use a large rejection threshold, normally at least 100
+ Received entries. Whatever mechanisms are used, servers MUST contain
+ provisions for detecting and stopping trivial loops.
+
+6.3 Compensating for Irregularities
+
+ Unfortunately, variations, creative interpretations, and outright
+ violations of Internet mail protocols do occur; some would suggest
+ that they occur quite frequently. The debate as to whether a well-
+ behaved SMTP receiver or relay should reject a malformed message,
+ attempt to pass it on unchanged, or attempt to repair it to increase
+ the odds of successful delivery (or subsequent reply) began almost
+ with the dawn of structured network mail and shows no signs of
+ abating. Advocates of rejection claim that attempted repairs are
+ rarely completely adequate and that rejection of bad messages is the
+ only way to get the offending software repaired. Advocates of
+ "repair" or "deliver no matter what" argue that users prefer that
+ mail go through it if at all possible and that there are significant
+ market pressures in that direction. In practice, these market
+ pressures may be more important to particular vendors than strict
+ conformance to the standards, regardless of the preference of the
+ actual developers.
+
+ The problems associated with ill-formed messages were exacerbated by
+ the introduction of the split-UA mail reading protocols [3, 26, 5,
+ 21]. These protocols have encouraged the use of SMTP as a posting
+ protocol, and SMTP servers as relay systems for these client hosts
+ (which are often only intermittently connected to the Internet).
+ Historically, many of those client machines lacked some of the
+ mechanisms and information assumed by SMTP (and indeed, by the mail
+ format protocol [7]). Some could not keep adequate track of time;
+ others had no concept of time zones; still others could not identify
+ their own names or addresses; and, of course, none could satisfy the
+ assumptions that underlay RFC 822's conception of authenticated
+ addresses.
+
+ In response to these weak SMTP clients, many SMTP systems now
+ complete messages that are delivered to them in incomplete or
+ incorrect form. This strategy is generally considered appropriate
+ when the server can identify or authenticate the client, and there
+ are prior agreements between them. By contrast, there is at best
+ great concern about fixes applied by a relay or delivery SMTP server
+ that has little or no knowledge of the user or client machine.
+
+
+
+Klensin Standards Track [Page 63]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ The following changes to a message being processed MAY be applied
+ when necessary by an originating SMTP server, or one used as the
+ target of SMTP as an initial posting protocol:
+
+ - Addition of a message-id field when none appears
+
+ - Addition of a date, time or time zone when none appears
+
+ - Correction of addresses to proper FQDN format
+
+ The less information the server has about the client, the less likely
+ these changes are to be correct and the more caution and conservatism
+ should be applied when considering whether or not to perform fixes
+ and how. These changes MUST NOT be applied by an SMTP server that
+ provides an intermediate relay function.
+
+ In all cases, properly-operating clients supplying correct
+ information are preferred to corrections by the SMTP server. In all
+ cases, documentation of actions performed by the servers (in trace
+ fields and/or header comments) is strongly encouraged.
+
+7. Security Considerations
+
+7.1 Mail Security and Spoofing
+
+ SMTP mail is inherently insecure in that it is feasible for even
+ fairly casual users to negotiate directly with receiving and relaying
+ SMTP servers and create messages that will trick a naive recipient
+ into believing that they came from somewhere else. Constructing such
+ a message so that the "spoofed" behavior cannot be detected by an
+ expert is somewhat more difficult, but not sufficiently so as to be a
+ deterrent to someone who is determined and knowledgeable.
+ Consequently, as knowledge of Internet mail increases, so does the
+ knowledge that SMTP mail inherently cannot be authenticated, or
+ integrity checks provided, at the transport level. Real mail
+ security lies only in end-to-end methods involving the message
+ bodies, such as those which use digital signatures (see [14] and,
+ e.g., PGP [4] or S/MIME [31]).
+
+ Various protocol extensions and configuration options that provide
+ authentication at the transport level (e.g., from an SMTP client to
+ an SMTP server) improve somewhat on the traditional situation
+ described above. However, unless they are accompanied by careful
+ handoffs of responsibility in a carefully-designed trust environment,
+ they remain inherently weaker than end-to-end mechanisms which use
+ digitally signed messages rather than depending on the integrity of
+ the transport system.
+
+
+
+
+Klensin Standards Track [Page 64]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ Efforts to make it more difficult for users to set envelope return
+ path and header "From" fields to point to valid addresses other than
+ their own are largely misguided: they frustrate legitimate
+ applications in which mail is sent by one user on behalf of another
+ or in which error (or normal) replies should be directed to a special
+ address. (Systems that provide convenient ways for users to alter
+ these fields on a per-message basis should attempt to establish a
+ primary and permanent mailbox address for the user so that Sender
+ fields within the message data can be generated sensibly.)
+
+ This specification does not further address the authentication issues
+ associated with SMTP other than to advocate that useful functionality
+ not be disabled in the hope of providing some small margin of
+ protection against an ignorant user who is trying to fake mail.
+
+7.2 "Blind" Copies
+
+ Addresses that do not appear in the message headers may appear in the
+ RCPT commands to an SMTP server for a number of reasons. The two
+ most common involve the use of a mailing address as a "list exploder"
+ (a single address that resolves into multiple addresses) and the
+ appearance of "blind copies". Especially when more than one RCPT
+ command is present, and in order to avoid defeating some of the
+ purpose of these mechanisms, SMTP clients and servers SHOULD NOT copy
+ the full set of RCPT command arguments into the headers, either as
+ part of trace headers or as informational or private-extension
+ headers. Since this rule is often violated in practice, and cannot
+ be enforced, sending SMTP systems that are aware of "bcc" use MAY
+ find it helpful to send each blind copy as a separate message
+ transaction containing only a single RCPT command.
+
+ There is no inherent relationship between either "reverse" (from
+ MAIL, SAML, etc., commands) or "forward" (RCPT) addresses in the SMTP
+ transaction ("envelope") and the addresses in the headers. Receiving
+ systems SHOULD NOT attempt to deduce such relationships and use them
+ to alter the headers of the message for delivery. The popular
+ "Apparently-to" header is a violation of this principle as well as a
+ common source of unintended information disclosure and SHOULD NOT be
+ used.
+
+7.3 VRFY, EXPN, and Security
+
+ As discussed in section 3.5, individual sites may want to disable
+ either or both of VRFY or EXPN for security reasons. As a corollary
+ to the above, implementations that permit this MUST NOT appear to
+ have verified addresses that are not, in fact, verified. If a site
+
+
+
+
+
+Klensin Standards Track [Page 65]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ disables these commands for security reasons, the SMTP server MUST
+ return a 252 response, rather than a code that could be confused with
+ successful or unsuccessful verification.
+
+ Returning a 250 reply code with the address listed in the VRFY
+ command after having checked it only for syntax violates this rule.
+ Of course, an implementation that "supports" VRFY by always returning
+ 550 whether or not the address is valid is equally not in
+ conformance.
+
+ Within the last few years, the contents of mailing lists have become
+ popular as an address information source for so-called "spammers."
+ The use of EXPN to "harvest" addresses has increased as list
+ administrators have installed protections against inappropriate uses
+ of the lists themselves. Implementations SHOULD still provide
+ support for EXPN, but sites SHOULD carefully evaluate the tradeoffs.
+ As authentication mechanisms are introduced into SMTP, some sites may
+ choose to make EXPN available only to authenticated requestors.
+
+7.4 Information Disclosure in Announcements
+
+ There has been an ongoing debate about the tradeoffs between the
+ debugging advantages of announcing server type and version (and,
+ sometimes, even server domain name) in the greeting response or in
+ response to the HELP command and the disadvantages of exposing
+ information that might be useful in a potential hostile attack. The
+ utility of the debugging information is beyond doubt. Those who
+ argue for making it available point out that it is far better to
+ actually secure an SMTP server rather than hope that trying to
+ conceal known vulnerabilities by hiding the server's precise identity
+ will provide more protection. Sites are encouraged to evaluate the
+ tradeoff with that issue in mind; implementations are strongly
+ encouraged to minimally provide for making type and version
+ information available in some way to other network hosts.
+
+7.5 Information Disclosure in Trace Fields
+
+ In some circumstances, such as when mail originates from within a LAN
+ whose hosts are not directly on the public Internet, trace
+ ("Received") fields produced in conformance with this specification
+ may disclose host names and similar information that would not
+ normally be available. This ordinarily does not pose a problem, but
+ sites with special concerns about name disclosure should be aware of
+ it. Also, the optional FOR clause should be supplied with caution or
+ not at all when multiple recipients are involved lest it
+ inadvertently disclose the identities of "blind copy" recipients to
+ others.
+
+
+
+
+Klensin Standards Track [Page 66]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+7.6 Information Disclosure in Message Forwarding
+
+ As discussed in section 3.4, use of the 251 or 551 reply codes to
+ identify the replacement address associated with a mailbox may
+ inadvertently disclose sensitive information. Sites that are
+ concerned about those issues should ensure that they select and
+ configure servers appropriately.
+
+7.7 Scope of Operation of SMTP Servers
+
+ It is a well-established principle that an SMTP server may refuse to
+ accept mail for any operational or technical reason that makes sense
+ to the site providing the server. However, cooperation among sites
+ and installations makes the Internet possible. If sites take
+ excessive advantage of the right to reject traffic, the ubiquity of
+ email availability (one of the strengths of the Internet) will be
+ threatened; considerable care should be taken and balance maintained
+ if a site decides to be selective about the traffic it will accept
+ and process.
+
+ In recent years, use of the relay function through arbitrary sites
+ has been used as part of hostile efforts to hide the actual origins
+ of mail. Some sites have decided to limit the use of the relay
+ function to known or identifiable sources, and implementations SHOULD
+ provide the capability to perform this type of filtering. When mail
+ is rejected for these or other policy reasons, a 550 code SHOULD be
+ used in response to EHLO, MAIL, or RCPT as appropriate.
+
+8. IANA Considerations
+
+ IANA will maintain three registries in support of this specification.
+ The first consists of SMTP service extensions with the associated
+ keywords, and, as needed, parameters and verbs. As specified in
+ section 2.2.2, no entry may be made in this registry that starts in
+ an "X". Entries may be made only for service extensions (and
+ associated keywords, parameters, or verbs) that are defined in
+ standards-track or experimental RFCs specifically approved by the
+ IESG for this purpose.
+
+ The second registry consists of "tags" that identify forms of domain
+ literals other than those for IPv4 addresses (specified in RFC 821
+ and in this document) and IPv6 addresses (specified in this
+ document). Additional literal types require standardization before
+ being used; none are anticipated at this time.
+
+ The third, established by RFC 821 and renewed by this specification,
+ is a registry of link and protocol identifiers to be used with the
+ "via" and "with" subclauses of the time stamp ("Received: header")
+
+
+
+Klensin Standards Track [Page 67]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ described in section 4.4. Link and protocol identifiers in addition
+ to those specified in this document may be registered only by
+ standardization or by way of an RFC-documented, IESG-approved,
+ Experimental protocol extension.
+
+9. References
+
+ [1] American National Standards Institute (formerly United States of
+ America Standards Institute), X3.4, 1968, "USA Code for
+ Information Interchange". ANSI X3.4-1968 has been replaced by
+ newer versions with slight modifications, but the 1968 version
+ remains definitive for the Internet.
+
+ [2] Braden, R., "Requirements for Internet hosts - application and
+ support", STD 3, RFC 1123, October 1989.
+
+ [3] Butler, M., Chase, D., Goldberger, J., Postel, J. and J.
+ Reynolds, "Post Office Protocol - version 2", RFC 937, February
+ 1985.
+
+ [4] Callas, J., Donnerhacke, L., Finney, H. and R. Thayer, "OpenPGP
+ Message Format", RFC 2440, November 1998.
+
+ [5] Crispin, M., "Interactive Mail Access Protocol - Version 2", RFC
+ 1176, August 1990.
+
+ [6] Crispin, M., "Internet Message Access Protocol - Version 4", RFC
+ 2060, December 1996.
+
+ [7] Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages", RFC 822, August 1982.
+
+ [8] Crocker, D. and P. Overell, Eds., "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [9] De Winter, J., "SMTP Service Extension for Remote Message Queue
+ Starting", RFC 1985, August 1996.
+
+ [10] Fajman, R., "An Extensible Message Format for Message
+ Disposition Notifications", RFC 2298, March 1998.
+
+ [11] Freed, N, "Behavior of and Requirements for Internet Firewalls",
+ RFC 2979, October 2000.
+
+ [12] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ RFC 2045, December 1996.
+
+
+
+
+Klensin Standards Track [Page 68]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ [13] Freed, N., "SMTP Service Extension for Command Pipelining", RFC
+ 2920, September 2000.
+
+ [14] Galvin, J., Murphy, S., Crocker, S. and N. Freed, "Security
+ Multiparts for MIME: Multipart/Signed and Multipart/Encrypted",
+ RFC 1847, October 1995.
+
+ [15] Gellens, R. and J. Klensin, "Message Submission", RFC 2476,
+ December 1998.
+
+ [16] Kille, S., "Mapping between X.400 and RFC822/MIME", RFC 2156,
+ January 1998.
+
+ [17] Hinden, R and S. Deering, Eds. "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [18] Klensin, J., Freed, N. and K. Moore, "SMTP Service Extension for
+ Message Size Declaration", STD 10, RFC 1870, November 1995.
+
+ [19] Klensin, J., Freed, N., Rose, M., Stefferud, E. and D. Crocker,
+ "SMTP Service Extensions", STD 10, RFC 1869, November 1995.
+
+ [20] Klensin, J., Freed, N., Rose, M., Stefferud, E. and D. Crocker,
+ "SMTP Service Extension for 8bit-MIMEtransport", RFC 1652, July
+ 1994.
+
+ [21] Lambert, M., "PCMAIL: A distributed mail system for personal
+ computers", RFC 1056, July 1988.
+
+ [22] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [23] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
+ Three: Message Header Extensions for Non-ASCII Text", RFC 2047,
+ December 1996.
+
+ [24] Moore, K., "SMTP Service Extension for Delivery Status
+ Notifications", RFC 1891, January 1996.
+
+ [25] Moore, K., and G. Vaudreuil, "An Extensible Message Format for
+ Delivery Status Notifications", RFC 1894, January 1996.
+
+ [26] Myers, J. and M. Rose, "Post Office Protocol - Version 3", STD
+ 53, RFC 1939, May 1996.
+
+
+
+
+Klensin Standards Track [Page 69]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ [27] Partridge, C., "Mail routing and the domain system", RFC 974,
+ January 1986.
+
+ [28] Partridge, C., "Duplicate messages and SMTP", RFC 1047, February
+ 1988.
+
+ [29] Postel, J., ed., "Transmission Control Protocol - DARPA Internet
+ Program Protocol Specification", STD 7, RFC 793, September 1981.
+
+ [30] Postel, J., "Simple Mail Transfer Protocol", RFC 821, August
+ 1982.
+
+ [31] Ramsdell, B., Ed., "S/MIME Version 3 Message Specification", RFC
+ 2633, June 1999.
+
+ [32] Resnick, P., Ed., "Internet Message Format", RFC 2822, April
+ 2001.
+
+ [33] Vaudreuil, G., "SMTP Service Extensions for Transmission of
+ Large and Binary MIME Messages", RFC 1830, August 1995.
+
+ [34] Vaudreuil, G., "Enhanced Mail System Status Codes", RFC 1893,
+ January 1996.
+
+10. Editor's Address
+
+ John C. Klensin
+ AT&T Laboratories
+ 99 Bedford St
+ Boston, MA 02111 USA
+
+ Phone: 617-574-3076
+ EMail: klensin@research.att.com
+
+11. Acknowledgments
+
+ Many people worked long and hard on the many iterations of this
+ document. There was wide-ranging debate in the IETF DRUMS Working
+ Group, both on its mailing list and in face to face discussions,
+ about many technical issues and the role of a revised standard for
+ Internet mail transport, and many contributors helped form the
+ wording in this specification. The hundreds of participants in the
+ many discussions since RFC 821 was produced are too numerous to
+ mention, but they all helped this document become what it is.
+
+
+
+
+
+
+
+Klensin Standards Track [Page 70]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+APPENDICES
+
+A. TCP Transport Service
+
+ The TCP connection supports the transmission of 8-bit bytes. The
+ SMTP data is 7-bit ASCII characters. Each character is transmitted
+ as an 8-bit byte with the high-order bit cleared to zero. Service
+ extensions may modify this rule to permit transmission of full 8-bit
+ data bytes as part of the message body, but not in SMTP commands or
+ responses.
+
+B. Generating SMTP Commands from RFC 822 Headers
+
+ Some systems use RFC 822 headers (only) in a mail submission
+ protocol, or otherwise generate SMTP commands from RFC 822 headers
+ when such a message is handed to an MTA from a UA. While the MTA-UA
+ protocol is a private matter, not covered by any Internet Standard,
+ there are problems with this approach. For example, there have been
+ repeated problems with proper handling of "bcc" copies and
+ redistribution lists when information that conceptually belongs to a
+ mail envelopes is not separated early in processing from header
+ information (and kept separate).
+
+ It is recommended that the UA provide its initial ("submission
+ client") MTA with an envelope separate from the message itself.
+ However, if the envelope is not supplied, SMTP commands SHOULD be
+ generated as follows:
+
+ 1. Each recipient address from a TO, CC, or BCC header field SHOULD
+ be copied to a RCPT command (generating multiple message copies if
+ that is required for queuing or delivery). This includes any
+ addresses listed in a RFC 822 "group". Any BCC fields SHOULD then
+ be removed from the headers. Once this process is completed, the
+ remaining headers SHOULD be checked to verify that at least one
+ To:, Cc:, or Bcc: header remains. If none do, then a bcc: header
+ with no additional information SHOULD be inserted as specified in
+ [32].
+
+ 2. The return address in the MAIL command SHOULD, if possible, be
+ derived from the system's identity for the submitting (local)
+ user, and the "From:" header field otherwise. If there is a
+ system identity available, it SHOULD also be copied to the Sender
+ header field if it is different from the address in the From
+ header field. (Any Sender field that was already there SHOULD be
+ removed.) Systems may provide a way for submitters to override
+ the envelope return address, but may want to restrict its use to
+ privileged users. This will not prevent mail forgery, but may
+ lessen its incidence; see section 7.1.
+
+
+
+Klensin Standards Track [Page 71]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ When an MTA is being used in this way, it bears responsibility for
+ ensuring that the message being transmitted is valid. The mechanisms
+ for checking that validity, and for handling (or returning) messages
+ that are not valid at the time of arrival, are part of the MUA-MTA
+ interface and not covered by this specification.
+
+ A submission protocol based on Standard RFC 822 information alone
+ MUST NOT be used to gateway a message from a foreign (non-SMTP) mail
+ system into an SMTP environment. Additional information to construct
+ an envelope must come from some source in the other environment,
+ whether supplemental headers or the foreign system's envelope.
+
+ Attempts to gateway messages using only their header "to" and "cc"
+ fields have repeatedly caused mail loops and other behavior adverse
+ to the proper functioning of the Internet mail environment. These
+ problems have been especially common when the message originates from
+ an Internet mailing list and is distributed into the foreign
+ environment using envelope information. When these messages are then
+ processed by a header-only remailer, loops back to the Internet
+ environment (and the mailing list) are almost inevitable.
+
+C. Source Routes
+
+ Historically, the <reverse-path> was a reverse source routing list of
+ hosts and a source mailbox. The first host in the <reverse-path>
+ SHOULD be the host sending the MAIL command. Similarly, the
+ <forward-path> may be a source routing lists of hosts and a
+ destination mailbox. However, in general, the <forward-path> SHOULD
+ contain only a mailbox and domain name, relying on the domain name
+ system to supply routing information if required. The use of source
+ routes is deprecated; while servers MUST be prepared to receive and
+ handle them as discussed in section 3.3 and F.2, clients SHOULD NOT
+ transmit them and this section was included only to provide context.
+
+ For relay purposes, the forward-path may be a source route of the
+ form "@ONE,@TWO:JOE@THREE", where ONE, TWO, and THREE MUST BE fully-
+ qualified domain names. This form is used to emphasize the
+ distinction between an address and a route. The mailbox is an
+ absolute address, and the route is information about how to get
+ there. The two concepts should not be confused.
+
+ If source routes are used, RFC 821 and the text below should be
+ consulted for the mechanisms for constructing and updating the
+ forward- and reverse-paths.
+
+
+
+
+
+
+
+Klensin Standards Track [Page 72]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ The SMTP server transforms the command arguments by moving its own
+ identifier (its domain name or that of any domain for which it is
+ acting as a mail exchanger), if it appears, from the forward-path to
+ the beginning of the reverse-path.
+
+ Notice that the forward-path and reverse-path appear in the SMTP
+ commands and replies, but not necessarily in the message. That is,
+ there is no need for these paths and especially this syntax to appear
+ in the "To:" , "From:", "CC:", etc. fields of the message header.
+ Conversely, SMTP servers MUST NOT derive final message delivery
+ information from message header fields.
+
+ When the list of hosts is present, it is a "reverse" source route and
+ indicates that the mail was relayed through each host on the list
+ (the first host in the list was the most recent relay). This list is
+ used as a source route to return non-delivery notices to the sender.
+ As each relay host adds itself to the beginning of the list, it MUST
+ use its name as known in the transport environment to which it is
+ relaying the mail rather than that of the transport environment from
+ which the mail came (if they are different).
+
+D. Scenarios
+
+ This section presents complete scenarios of several types of SMTP
+ sessions. In the examples, "C:" indicates what is said by the SMTP
+ client, and "S:" indicates what is said by the SMTP server.
+
+D.1 A Typical SMTP Transaction Scenario
+
+ This SMTP example shows mail sent by Smith at host bar.com, to Jones,
+ Green, and Brown at host foo.com. Here we assume that host bar.com
+ contacts host foo.com directly. The mail is accepted for Jones and
+ Brown. Green does not have a mailbox at host foo.com.
+
+ S: 220 foo.com Simple Mail Transfer Service Ready
+ C: EHLO bar.com
+ S: 250-foo.com greets bar.com
+ S: 250-8BITMIME
+ S: 250-SIZE
+ S: 250-DSN
+ S: 250 HELP
+ C: MAIL FROM:<Smith@bar.com>
+ S: 250 OK
+ C: RCPT TO:<Jones@foo.com>
+ S: 250 OK
+ C: RCPT TO:<Green@foo.com>
+ S: 550 No such user here
+ C: RCPT TO:<Brown@foo.com>
+
+
+
+Klensin Standards Track [Page 73]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ S: 250 OK
+ C: DATA
+ S: 354 Start mail input; end with <CRLF>.<CRLF>
+ C: Blah blah blah...
+ C: ...etc. etc. etc.
+ C: .
+ S: 250 OK
+ C: QUIT
+ S: 221 foo.com Service closing transmission channel
+
+D.2 Aborted SMTP Transaction Scenario
+
+ S: 220 foo.com Simple Mail Transfer Service Ready
+ C: EHLO bar.com
+ S: 250-foo.com greets bar.com
+ S: 250-8BITMIME
+ S: 250-SIZE
+ S: 250-DSN
+ S: 250 HELP
+ C: MAIL FROM:<Smith@bar.com>
+ S: 250 OK
+ C: RCPT TO:<Jones@foo.com>
+ S: 250 OK
+ C: RCPT TO:<Green@foo.com>
+ S: 550 No such user here
+ C: RSET
+ S: 250 OK
+ C: QUIT
+ S: 221 foo.com Service closing transmission channel
+
+D.3 Relayed Mail Scenario
+
+ Step 1 -- Source Host to Relay Host
+
+ S: 220 foo.com Simple Mail Transfer Service Ready
+ C: EHLO bar.com
+ S: 250-foo.com greets bar.com
+ S: 250-8BITMIME
+ S: 250-SIZE
+ S: 250-DSN
+ S: 250 HELP
+ C: MAIL FROM:<JQP@bar.com>
+ S: 250 OK
+ C: RCPT TO:<@foo.com:Jones@XYZ.COM>
+ S: 250 OK
+ C: DATA
+ S: 354 Start mail input; end with <CRLF>.<CRLF>
+ C: Date: Thu, 21 May 1998 05:33:29 -0700
+
+
+
+Klensin Standards Track [Page 74]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ C: From: John Q. Public <JQP@bar.com>
+ C: Subject: The Next Meeting of the Board
+ C: To: Jones@xyz.com
+ C:
+ C: Bill:
+ C: The next meeting of the board of directors will be
+ C: on Tuesday.
+ C: John.
+ C: .
+ S: 250 OK
+ C: QUIT
+ S: 221 foo.com Service closing transmission channel
+
+ Step 2 -- Relay Host to Destination Host
+
+ S: 220 xyz.com Simple Mail Transfer Service Ready
+ C: EHLO foo.com
+ S: 250 xyz.com is on the air
+ C: MAIL FROM:<@foo.com:JQP@bar.com>
+ S: 250 OK
+ C: RCPT TO:<Jones@XYZ.COM>
+ S: 250 OK
+ C: DATA
+ S: 354 Start mail input; end with <CRLF>.<CRLF>
+ C: Received: from bar.com by foo.com ; Thu, 21 May 1998
+ C: 05:33:29 -0700
+ C: Date: Thu, 21 May 1998 05:33:22 -0700
+ C: From: John Q. Public <JQP@bar.com>
+ C: Subject: The Next Meeting of the Board
+ C: To: Jones@xyz.com
+ C:
+ C: Bill:
+ C: The next meeting of the board of directors will be
+ C: on Tuesday.
+ C: John.
+ C: .
+ S: 250 OK
+ C: QUIT
+ S: 221 foo.com Service closing transmission channel
+
+D.4 Verifying and Sending Scenario
+
+ S: 220 foo.com Simple Mail Transfer Service Ready
+ C: EHLO bar.com
+ S: 250-foo.com greets bar.com
+ S: 250-8BITMIME
+ S: 250-SIZE
+ S: 250-DSN
+
+
+
+Klensin Standards Track [Page 75]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+ S: 250-VRFY
+ S: 250 HELP
+ C: VRFY Crispin
+ S: 250 Mark Crispin <Admin.MRC@foo.com>
+ C: SEND FROM:<EAK@bar.com>
+ S: 250 OK
+ C: RCPT TO:<Admin.MRC@foo.com>
+ S: 250 OK
+ C: DATA
+ S: 354 Start mail input; end with <CRLF>.<CRLF>
+ C: Blah blah blah...
+ C: ...etc. etc. etc.
+ C: .
+ S: 250 OK
+ C: QUIT
+ S: 221 foo.com Service closing transmission channel
+
+E. Other Gateway Issues
+
+ In general, gateways between the Internet and other mail systems
+ SHOULD attempt to preserve any layering semantics across the
+ boundaries between the two mail systems involved. Gateway-
+ translation approaches that attempt to take shortcuts by mapping,
+ (such as envelope information from one system to the message headers
+ or body of another) have generally proven to be inadequate in
+ important ways. Systems translating between environments that do not
+ support both envelopes and headers and Internet mail must be written
+ with the understanding that some information loss is almost
+ inevitable.
+
+F. Deprecated Features of RFC 821
+
+ A few features of RFC 821 have proven to be problematic and SHOULD
+ NOT be used in Internet mail.
+
+F.1 TURN
+
+ This command, described in RFC 821, raises important security issues
+ since, in the absence of strong authentication of the host requesting
+ that the client and server switch roles, it can easily be used to
+ divert mail from its correct destination. Its use is deprecated;
+ SMTP systems SHOULD NOT use it unless the server can authenticate the
+ client.
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 76]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+F.2 Source Routing
+
+ RFC 821 utilized the concept of explicit source routing to get mail
+ from one host to another via a series of relays. The requirement to
+ utilize source routes in regular mail traffic was eliminated by the
+ introduction of the domain name system "MX" record and the last
+ significant justification for them was eliminated by the
+ introduction, in RFC 1123, of a clear requirement that addresses
+ following an "@" must all be fully-qualified domain names.
+ Consequently, the only remaining justifications for the use of source
+ routes are support for very old SMTP clients or MUAs and in mail
+ system debugging. They can, however, still be useful in the latter
+ circumstance and for routing mail around serious, but temporary,
+ problems such as problems with the relevant DNS records.
+
+ SMTP servers MUST continue to accept source route syntax as specified
+ in the main body of this document and in RFC 1123. They MAY, if
+ necessary, ignore the routes and utilize only the target domain in
+ the address. If they do utilize the source route, the message MUST
+ be sent to the first domain shown in the address. In particular, a
+ server MUST NOT guess at shortcuts within the source route.
+
+ Clients SHOULD NOT utilize explicit source routing except under
+ unusual circumstances, such as debugging or potentially relaying
+ around firewall or mail system configuration errors.
+
+F.3 HELO
+
+ As discussed in sections 3.1 and 4.1.1, EHLO is strongly preferred to
+ HELO when the server will accept the former. Servers must continue
+ to accept and process HELO in order to support older clients.
+
+F.4 #-literals
+
+ RFC 821 provided for specifying an Internet address as a decimal
+ integer host number prefixed by a pound sign, "#". In practice, that
+ form has been obsolete since the introduction of TCP/IP. It is
+ deprecated and MUST NOT be used.
+
+F.5 Dates and Years
+
+ When dates are inserted into messages by SMTP clients or servers
+ (e.g., in trace fields), four-digit years MUST BE used. Two-digit
+ years are deprecated; three-digit years were never permitted in the
+ Internet mail system.
+
+
+
+
+
+
+Klensin Standards Track [Page 77]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+F.6 Sending versus Mailing
+
+ In addition to specifying a mechanism for delivering messages to
+ user's mailboxes, RFC 821 provided additional, optional, commands to
+ deliver messages directly to the user's terminal screen. These
+ commands (SEND, SAML, SOML) were rarely implemented, and changes in
+ workstation technology and the introduction of other protocols may
+ have rendered them obsolete even where they are implemented.
+
+ Clients SHOULD NOT provide SEND, SAML, or SOML as services. Servers
+ MAY implement them. If they are implemented by servers, the
+ implementation model specified in RFC 821 MUST be used and the
+ command names MUST be published in the response to the EHLO command.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 78]
+
+RFC 2821 Simple Mail Transfer Protocol April 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Standards Track [Page 79]
+
diff --git a/standards/rfc2822.txt b/standards/rfc2822.txt
new file mode 100644
index 000000000..9f698f77d
--- /dev/null
+++ b/standards/rfc2822.txt
@@ -0,0 +1,2859 @@
+
+
+
+
+
+
+Network Working Group P. Resnick, Editor
+Request for Comments: 2822 QUALCOMM Incorporated
+Obsoletes: 822 April 2001
+Category: Standards Track
+
+
+ Internet Message Format
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This standard specifies a syntax for text messages that are sent
+ between computer users, within the framework of "electronic mail"
+ messages. This standard supersedes the one specified in Request For
+ Comments (RFC) 822, "Standard for the Format of ARPA Internet Text
+ Messages", updating it to reflect current practice and incorporating
+ incremental changes that were specified in other RFCs.
+
+Table of Contents
+
+ 1. Introduction ............................................... 3
+ 1.1. Scope .................................................... 3
+ 1.2. Notational conventions ................................... 4
+ 1.2.1. Requirements notation .................................. 4
+ 1.2.2. Syntactic notation ..................................... 4
+ 1.3. Structure of this document ............................... 4
+ 2. Lexical Analysis of Messages ............................... 5
+ 2.1. General Description ...................................... 5
+ 2.1.1. Line Length Limits ..................................... 6
+ 2.2. Header Fields ............................................ 7
+ 2.2.1. Unstructured Header Field Bodies ....................... 7
+ 2.2.2. Structured Header Field Bodies ......................... 7
+ 2.2.3. Long Header Fields ..................................... 7
+ 2.3. Body ..................................................... 8
+ 3. Syntax ..................................................... 9
+ 3.1. Introduction ............................................. 9
+ 3.2. Lexical Tokens ........................................... 9
+
+
+
+Resnick Standards Track [Page 1]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ 3.2.1. Primitive Tokens ....................................... 9
+ 3.2.2. Quoted characters ......................................10
+ 3.2.3. Folding white space and comments .......................11
+ 3.2.4. Atom ...................................................12
+ 3.2.5. Quoted strings .........................................13
+ 3.2.6. Miscellaneous tokens ...................................13
+ 3.3. Date and Time Specification ..............................14
+ 3.4. Address Specification ....................................15
+ 3.4.1. Addr-spec specification ................................16
+ 3.5 Overall message syntax ....................................17
+ 3.6. Field definitions ........................................18
+ 3.6.1. The origination date field .............................20
+ 3.6.2. Originator fields ......................................21
+ 3.6.3. Destination address fields .............................22
+ 3.6.4. Identification fields ..................................23
+ 3.6.5. Informational fields ...................................26
+ 3.6.6. Resent fields ..........................................26
+ 3.6.7. Trace fields ...........................................28
+ 3.6.8. Optional fields ........................................29
+ 4. Obsolete Syntax ............................................29
+ 4.1. Miscellaneous obsolete tokens ............................30
+ 4.2. Obsolete folding white space .............................31
+ 4.3. Obsolete Date and Time ...................................31
+ 4.4. Obsolete Addressing ......................................33
+ 4.5. Obsolete header fields ...................................33
+ 4.5.1. Obsolete origination date field ........................34
+ 4.5.2. Obsolete originator fields .............................34
+ 4.5.3. Obsolete destination address fields ....................34
+ 4.5.4. Obsolete identification fields .........................35
+ 4.5.5. Obsolete informational fields ..........................35
+ 4.5.6. Obsolete resent fields .................................35
+ 4.5.7. Obsolete trace fields ..................................36
+ 4.5.8. Obsolete optional fields ...............................36
+ 5. Security Considerations ....................................36
+ 6. Bibliography ...............................................37
+ 7. Editor's Address ...........................................38
+ 8. Acknowledgements ...........................................39
+ Appendix A. Example messages ..................................41
+ A.1. Addressing examples ......................................41
+ A.1.1. A message from one person to another with simple
+ addressing .............................................41
+ A.1.2. Different types of mailboxes ...........................42
+ A.1.3. Group addresses ........................................43
+ A.2. Reply messages ...........................................43
+ A.3. Resent messages ..........................................44
+ A.4. Messages with trace fields ...............................46
+ A.5. White space, comments, and other oddities ................47
+ A.6. Obsoleted forms ..........................................47
+
+
+
+Resnick Standards Track [Page 2]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ A.6.1. Obsolete addressing ....................................48
+ A.6.2. Obsolete dates .........................................48
+ A.6.3. Obsolete white space and comments ......................48
+ Appendix B. Differences from earlier standards ................49
+ Appendix C. Notices ...........................................50
+ Full Copyright Statement ......................................51
+
+1. Introduction
+
+1.1. Scope
+
+ This standard specifies a syntax for text messages that are sent
+ between computer users, within the framework of "electronic mail"
+ messages. This standard supersedes the one specified in Request For
+ Comments (RFC) 822, "Standard for the Format of ARPA Internet Text
+ Messages" [RFC822], updating it to reflect current practice and
+ incorporating incremental changes that were specified in other RFCs
+ [STD3].
+
+ This standard specifies a syntax only for text messages. In
+ particular, it makes no provision for the transmission of images,
+ audio, or other sorts of structured data in electronic mail messages.
+ There are several extensions published, such as the MIME document
+ series [RFC2045, RFC2046, RFC2049], which describe mechanisms for the
+ transmission of such data through electronic mail, either by
+ extending the syntax provided here or by structuring such messages to
+ conform to this syntax. Those mechanisms are outside of the scope of
+ this standard.
+
+ In the context of electronic mail, messages are viewed as having an
+ envelope and contents. The envelope contains whatever information is
+ needed to accomplish transmission and delivery. (See [RFC2821] for a
+ discussion of the envelope.) The contents comprise the object to be
+ delivered to the recipient. This standard applies only to the format
+ and some of the semantics of message contents. It contains no
+ specification of the information in the envelope.
+
+ However, some message systems may use information from the contents
+ to create the envelope. It is intended that this standard facilitate
+ the acquisition of such information by programs.
+
+ This specification is intended as a definition of what message
+ content format is to be passed between systems. Though some message
+ systems locally store messages in this format (which eliminates the
+ need for translation between formats) and others use formats that
+ differ from the one specified in this standard, local storage is
+ outside of the scope of this standard.
+
+
+
+
+Resnick Standards Track [Page 3]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Note: This standard is not intended to dictate the internal formats
+ used by sites, the specific message system features that they are
+ expected to support, or any of the characteristics of user interface
+ programs that create or read messages. In addition, this standard
+ does not specify an encoding of the characters for either transport
+ or storage; that is, it does not specify the number of bits used or
+ how those bits are specifically transferred over the wire or stored
+ on disk.
+
+1.2. Notational conventions
+
+1.2.1. Requirements notation
+
+ This document occasionally uses terms that appear in capital letters.
+ When the terms "MUST", "SHOULD", "RECOMMENDED", "MUST NOT", "SHOULD
+ NOT", and "MAY" appear capitalized, they are being used to indicate
+ particular requirements of this specification. A discussion of the
+ meanings of these terms appears in [RFC2119].
+
+1.2.2. Syntactic notation
+
+ This standard uses the Augmented Backus-Naur Form (ABNF) notation
+ specified in [RFC2234] for the formal definitions of the syntax of
+ messages. Characters will be specified either by a decimal value
+ (e.g., the value %d65 for uppercase A and %d97 for lowercase A) or by
+ a case-insensitive literal value enclosed in quotation marks (e.g.,
+ "A" for either uppercase or lowercase A). See [RFC2234] for the full
+ description of the notation.
+
+1.3. Structure of this document
+
+ This document is divided into several sections.
+
+ This section, section 1, is a short introduction to the document.
+
+ Section 2 lays out the general description of a message and its
+ constituent parts. This is an overview to help the reader understand
+ some of the general principles used in the later portions of this
+ document. Any examples in this section MUST NOT be taken as
+ specification of the formal syntax of any part of a message.
+
+ Section 3 specifies formal ABNF rules for the structure of each part
+ of a message (the syntax) and describes the relationship between
+ those parts and their meaning in the context of a message (the
+ semantics). That is, it describes the actual rules for the structure
+ of each part of a message (the syntax) as well as a description of
+ the parts and instructions on how they ought to be interpreted (the
+ semantics). This includes analysis of the syntax and semantics of
+
+
+
+Resnick Standards Track [Page 4]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ subparts of messages that have specific structure. The syntax
+ included in section 3 represents messages as they MUST be created.
+ There are also notes in section 3 to indicate if any of the options
+ specified in the syntax SHOULD be used over any of the others.
+
+ Both sections 2 and 3 describe messages that are legal to generate
+ for purposes of this standard.
+
+ Section 4 of this document specifies an "obsolete" syntax. There are
+ references in section 3 to these obsolete syntactic elements. The
+ rules of the obsolete syntax are elements that have appeared in
+ earlier revisions of this standard or have previously been widely
+ used in Internet messages. As such, these elements MUST be
+ interpreted by parsers of messages in order to be conformant to this
+ standard. However, since items in this syntax have been determined
+ to be non-interoperable or to cause significant problems for
+ recipients of messages, they MUST NOT be generated by creators of
+ conformant messages.
+
+ Section 5 details security considerations to take into account when
+ implementing this standard.
+
+ Section 6 is a bibliography of references in this document.
+
+ Section 7 contains the editor's address.
+
+ Section 8 contains acknowledgements.
+
+ Appendix A lists examples of different sorts of messages. These
+ examples are not exhaustive of the types of messages that appear on
+ the Internet, but give a broad overview of certain syntactic forms.
+
+ Appendix B lists the differences between this standard and earlier
+ standards for Internet messages.
+
+ Appendix C has copyright and intellectual property notices.
+
+2. Lexical Analysis of Messages
+
+2.1. General Description
+
+ At the most basic level, a message is a series of characters. A
+ message that is conformant with this standard is comprised of
+ characters with values in the range 1 through 127 and interpreted as
+ US-ASCII characters [ASCII]. For brevity, this document sometimes
+ refers to this range of characters as simply "US-ASCII characters".
+
+
+
+
+
+Resnick Standards Track [Page 5]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Note: This standard specifies that messages are made up of characters
+ in the US-ASCII range of 1 through 127. There are other documents,
+ specifically the MIME document series [RFC2045, RFC2046, RFC2047,
+ RFC2048, RFC2049], that extend this standard to allow for values
+ outside of that range. Discussion of those mechanisms is not within
+ the scope of this standard.
+
+ Messages are divided into lines of characters. A line is a series of
+ characters that is delimited with the two characters carriage-return
+ and line-feed; that is, the carriage return (CR) character (ASCII
+ value 13) followed immediately by the line feed (LF) character (ASCII
+ value 10). (The carriage-return/line-feed pair is usually written in
+ this document as "CRLF".)
+
+ A message consists of header fields (collectively called "the header
+ of the message") followed, optionally, by a body. The header is a
+ sequence of lines of characters with special syntax as defined in
+ this standard. The body is simply a sequence of characters that
+ follows the header and is separated from the header by an empty line
+ (i.e., a line with nothing preceding the CRLF).
+
+2.1.1. Line Length Limits
+
+ There are two limits that this standard places on the number of
+ characters in a line. Each line of characters MUST be no more than
+ 998 characters, and SHOULD be no more than 78 characters, excluding
+ the CRLF.
+
+ The 998 character limit is due to limitations in many implementations
+ which send, receive, or store Internet Message Format messages that
+ simply cannot handle more than 998 characters on a line. Receiving
+ implementations would do well to handle an arbitrarily large number
+ of characters in a line for robustness sake. However, there are so
+ many implementations which (in compliance with the transport
+ requirements of [RFC2821]) do not accept messages containing more
+ than 1000 character including the CR and LF per line, it is important
+ for implementations not to create such messages.
+
+ The more conservative 78 character recommendation is to accommodate
+ the many implementations of user interfaces that display these
+ messages which may truncate, or disastrously wrap, the display of
+ more than 78 characters per line, in spite of the fact that such
+ implementations are non-conformant to the intent of this
+ specification (and that of [RFC2821] if they actually cause
+ information to be lost). Again, even though this limitation is put on
+ messages, it is encumbant upon implementations which display messages
+
+
+
+
+
+Resnick Standards Track [Page 6]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ to handle an arbitrarily large number of characters in a line
+ (certainly at least up to the 998 character limit) for the sake of
+ robustness.
+
+2.2. Header Fields
+
+ Header fields are lines composed of a field name, followed by a colon
+ (":"), followed by a field body, and terminated by CRLF. A field
+ name MUST be composed of printable US-ASCII characters (i.e.,
+ characters that have values between 33 and 126, inclusive), except
+ colon. A field body may be composed of any US-ASCII characters,
+ except for CR and LF. However, a field body may contain CRLF when
+ used in header "folding" and "unfolding" as described in section
+ 2.2.3. All field bodies MUST conform to the syntax described in
+ sections 3 and 4 of this standard.
+
+2.2.1. Unstructured Header Field Bodies
+
+ Some field bodies in this standard are defined simply as
+ "unstructured" (which is specified below as any US-ASCII characters,
+ except for CR and LF) with no further restrictions. These are
+ referred to as unstructured field bodies. Semantically, unstructured
+ field bodies are simply to be treated as a single line of characters
+ with no further processing (except for header "folding" and
+ "unfolding" as described in section 2.2.3).
+
+2.2.2. Structured Header Field Bodies
+
+ Some field bodies in this standard have specific syntactical
+ structure more restrictive than the unstructured field bodies
+ described above. These are referred to as "structured" field bodies.
+ Structured field bodies are sequences of specific lexical tokens as
+ described in sections 3 and 4 of this standard. Many of these tokens
+ are allowed (according to their syntax) to be introduced or end with
+ comments (as described in section 3.2.3) as well as the space (SP,
+ ASCII value 32) and horizontal tab (HTAB, ASCII value 9) characters
+ (together known as the white space characters, WSP), and those WSP
+ characters are subject to header "folding" and "unfolding" as
+ described in section 2.2.3. Semantic analysis of structured field
+ bodies is given along with their syntax.
+
+2.2.3. Long Header Fields
+
+ Each header field is logically a single line of characters comprising
+ the field name, the colon, and the field body. For convenience
+ however, and to deal with the 998/78 character limitations per line,
+ the field body portion of a header field can be split into a multiple
+ line representation; this is called "folding". The general rule is
+
+
+
+Resnick Standards Track [Page 7]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ that wherever this standard allows for folding white space (not
+ simply WSP characters), a CRLF may be inserted before any WSP. For
+ example, the header field:
+
+ Subject: This is a test
+
+ can be represented as:
+
+ Subject: This
+ is a test
+
+ Note: Though structured field bodies are defined in such a way that
+ folding can take place between many of the lexical tokens (and even
+ within some of the lexical tokens), folding SHOULD be limited to
+ placing the CRLF at higher-level syntactic breaks. For instance, if
+ a field body is defined as comma-separated values, it is recommended
+ that folding occur after the comma separating the structured items in
+ preference to other places where the field could be folded, even if
+ it is allowed elsewhere.
+
+ The process of moving from this folded multiple-line representation
+ of a header field to its single line representation is called
+ "unfolding". Unfolding is accomplished by simply removing any CRLF
+ that is immediately followed by WSP. Each header field should be
+ treated in its unfolded form for further syntactic and semantic
+ evaluation.
+
+2.3. Body
+
+ The body of a message is simply lines of US-ASCII characters. The
+ only two limitations on the body are as follows:
+
+ - CR and LF MUST only occur together as CRLF; they MUST NOT appear
+ independently in the body.
+
+ - Lines of characters in the body MUST be limited to 998 characters,
+ and SHOULD be limited to 78 characters, excluding the CRLF.
+
+ Note: As was stated earlier, there are other standards documents,
+ specifically the MIME documents [RFC2045, RFC2046, RFC2048, RFC2049]
+ that extend this standard to allow for different sorts of message
+ bodies. Again, these mechanisms are beyond the scope of this
+ document.
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 8]
+
+RFC 2822 Internet Message Format April 2001
+
+
+3. Syntax
+
+3.1. Introduction
+
+ The syntax as given in this section defines the legal syntax of
+ Internet messages. Messages that are conformant to this standard
+ MUST conform to the syntax in this section. If there are options in
+ this section where one option SHOULD be generated, that is indicated
+ either in the prose or in a comment next to the syntax.
+
+ For the defined expressions, a short description of the syntax and
+ use is given, followed by the syntax in ABNF, followed by a semantic
+ analysis. Primitive tokens that are used but otherwise unspecified
+ come from [RFC2234].
+
+ In some of the definitions, there will be nonterminals whose names
+ start with "obs-". These "obs-" elements refer to tokens defined in
+ the obsolete syntax in section 4. In all cases, these productions
+ are to be ignored for the purposes of generating legal Internet
+ messages and MUST NOT be used as part of such a message. However,
+ when interpreting messages, these tokens MUST be honored as part of
+ the legal syntax. In this sense, section 3 defines a grammar for
+ generation of messages, with "obs-" elements that are to be ignored,
+ while section 4 adds grammar for interpretation of messages.
+
+3.2. Lexical Tokens
+
+ The following rules are used to define an underlying lexical
+ analyzer, which feeds tokens to the higher-level parsers. This
+ section defines the tokens used in structured header field bodies.
+
+ Note: Readers of this standard need to pay special attention to how
+ these lexical tokens are used in both the lower-level and
+ higher-level syntax later in the document. Particularly, the white
+ space tokens and the comment tokens defined in section 3.2.3 get used
+ in the lower-level tokens defined here, and those lower-level tokens
+ are in turn used as parts of the higher-level tokens defined later.
+ Therefore, the white space and comments may be allowed in the
+ higher-level tokens even though they may not explicitly appear in a
+ particular definition.
+
+3.2.1. Primitive Tokens
+
+ The following are primitive tokens referred to elsewhere in this
+ standard, but not otherwise defined in [RFC2234]. Some of them will
+ not appear anywhere else in the syntax, but they are convenient to
+ refer to in other parts of this document.
+
+
+
+
+Resnick Standards Track [Page 9]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Note: The "specials" below are just such an example. Though the
+ specials token does not appear anywhere else in this standard, it is
+ useful for implementers who use tools that lexically analyze
+ messages. Each of the characters in specials can be used to indicate
+ a tokenization point in lexical analysis.
+
+NO-WS-CTL = %d1-8 / ; US-ASCII control characters
+ %d11 / ; that do not include the
+ %d12 / ; carriage return, line feed,
+ %d14-31 / ; and white space characters
+ %d127
+
+text = %d1-9 / ; Characters excluding CR and LF
+ %d11 /
+ %d12 /
+ %d14-127 /
+ obs-text
+
+specials = "(" / ")" / ; Special characters used in
+ "<" / ">" / ; other parts of the syntax
+ "[" / "]" /
+ ":" / ";" /
+ "@" / "\" /
+ "," / "." /
+ DQUOTE
+
+ No special semantics are attached to these tokens. They are simply
+ single characters.
+
+3.2.2. Quoted characters
+
+ Some characters are reserved for special interpretation, such as
+ delimiting lexical tokens. To permit use of these characters as
+ uninterpreted data, a quoting mechanism is provided.
+
+quoted-pair = ("\" text) / obs-qp
+
+ Where any quoted-pair appears, it is to be interpreted as the text
+ character alone. That is to say, the "\" character that appears as
+ part of a quoted-pair is semantically "invisible".
+
+ Note: The "\" character may appear in a message where it is not part
+ of a quoted-pair. A "\" character that does not appear in a
+ quoted-pair is not semantically invisible. The only places in this
+ standard where quoted-pair currently appears are ccontent, qcontent,
+ dcontent, no-fold-quote, and no-fold-literal.
+
+
+
+
+
+Resnick Standards Track [Page 10]
+
+RFC 2822 Internet Message Format April 2001
+
+
+3.2.3. Folding white space and comments
+
+ White space characters, including white space used in folding
+ (described in section 2.2.3), may appear between many elements in
+ header field bodies. Also, strings of characters that are treated as
+ comments may be included in structured field bodies as characters
+ enclosed in parentheses. The following defines the folding white
+ space (FWS) and comment constructs.
+
+ Strings of characters enclosed in parentheses are considered comments
+ so long as they do not appear within a "quoted-string", as defined in
+ section 3.2.5. Comments may nest.
+
+ There are several places in this standard where comments and FWS may
+ be freely inserted. To accommodate that syntax, an additional token
+ for "CFWS" is defined for places where comments and/or FWS can occur.
+ However, where CFWS occurs in this standard, it MUST NOT be inserted
+ in such a way that any line of a folded header field is made up
+ entirely of WSP characters and nothing else.
+
+FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
+ obs-FWS
+
+ctext = NO-WS-CTL / ; Non white space controls
+
+ %d33-39 / ; The rest of the US-ASCII
+ %d42-91 / ; characters not including "(",
+ %d93-126 ; ")", or "\"
+
+ccontent = ctext / quoted-pair / comment
+
+comment = "(" *([FWS] ccontent) [FWS] ")"
+
+CFWS = *([FWS] comment) (([FWS] comment) / FWS)
+
+ Throughout this standard, where FWS (the folding white space token)
+ appears, it indicates a place where header folding, as discussed in
+ section 2.2.3, may take place. Wherever header folding appears in a
+ message (that is, a header field body containing a CRLF followed by
+ any WSP), header unfolding (removal of the CRLF) is performed before
+ any further lexical analysis is performed on that header field
+ according to this standard. That is to say, any CRLF that appears in
+ FWS is semantically "invisible."
+
+ A comment is normally used in a structured field body to provide some
+ human readable informational text. Since a comment is allowed to
+ contain FWS, folding is permitted within the comment. Also note that
+ since quoted-pair is allowed in a comment, the parentheses and
+
+
+
+Resnick Standards Track [Page 11]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ backslash characters may appear in a comment so long as they appear
+ as a quoted-pair. Semantically, the enclosing parentheses are not
+ part of the comment; the comment is what is contained between the two
+ parentheses. As stated earlier, the "\" in any quoted-pair and the
+ CRLF in any FWS that appears within the comment are semantically
+ "invisible" and therefore not part of the comment either.
+
+ Runs of FWS, comment or CFWS that occur between lexical tokens in a
+ structured field header are semantically interpreted as a single
+ space character.
+
+3.2.4. Atom
+
+ Several productions in structured header field bodies are simply
+ strings of certain basic characters. Such productions are called
+ atoms.
+
+ Some of the structured header field bodies also allow the period
+ character (".", ASCII value 46) within runs of atext. An additional
+ "dot-atom" token is defined for those purposes.
+
+atext = ALPHA / DIGIT / ; Any character except controls,
+ "!" / "#" / ; SP, and specials.
+ "$" / "%" / ; Used for atoms
+ "&" / "'" /
+ "*" / "+" /
+ "-" / "/" /
+ "=" / "?" /
+ "^" / "_" /
+ "`" / "{" /
+ "|" / "}" /
+ "~"
+
+atom = [CFWS] 1*atext [CFWS]
+
+dot-atom = [CFWS] dot-atom-text [CFWS]
+
+dot-atom-text = 1*atext *("." 1*atext)
+
+ Both atom and dot-atom are interpreted as a single unit, comprised of
+ the string of characters that make it up. Semantically, the optional
+ comments and FWS surrounding the rest of the characters are not part
+ of the atom; the atom is only the run of atext characters in an atom,
+ or the atext and "." characters in a dot-atom.
+
+
+
+
+
+
+
+Resnick Standards Track [Page 12]
+
+RFC 2822 Internet Message Format April 2001
+
+
+3.2.5. Quoted strings
+
+ Strings of characters that include characters other than those
+ allowed in atoms may be represented in a quoted string format, where
+ the characters are surrounded by quote (DQUOTE, ASCII value 34)
+ characters.
+
+qtext = NO-WS-CTL / ; Non white space controls
+
+ %d33 / ; The rest of the US-ASCII
+ %d35-91 / ; characters not including "\"
+ %d93-126 ; or the quote character
+
+qcontent = qtext / quoted-pair
+
+quoted-string = [CFWS]
+ DQUOTE *([FWS] qcontent) [FWS] DQUOTE
+ [CFWS]
+
+ A quoted-string is treated as a unit. That is, quoted-string is
+ identical to atom, semantically. Since a quoted-string is allowed to
+ contain FWS, folding is permitted. Also note that since quoted-pair
+ is allowed in a quoted-string, the quote and backslash characters may
+ appear in a quoted-string so long as they appear as a quoted-pair.
+
+ Semantically, neither the optional CFWS outside of the quote
+ characters nor the quote characters themselves are part of the
+ quoted-string; the quoted-string is what is contained between the two
+ quote characters. As stated earlier, the "\" in any quoted-pair and
+ the CRLF in any FWS/CFWS that appears within the quoted-string are
+ semantically "invisible" and therefore not part of the quoted-string
+ either.
+
+3.2.6. Miscellaneous tokens
+
+ Three additional tokens are defined, word and phrase for combinations
+ of atoms and/or quoted-strings, and unstructured for use in
+ unstructured header fields and in some places within structured
+ header fields.
+
+word = atom / quoted-string
+
+phrase = 1*word / obs-phrase
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 13]
+
+RFC 2822 Internet Message Format April 2001
+
+
+utext = NO-WS-CTL / ; Non white space controls
+ %d33-126 / ; The rest of US-ASCII
+ obs-utext
+
+unstructured = *([FWS] utext) [FWS]
+
+3.3. Date and Time Specification
+
+ Date and time occur in several header fields. This section specifies
+ the syntax for a full date and time specification. Though folding
+ white space is permitted throughout the date-time specification, it
+ is RECOMMENDED that a single space be used in each place that FWS
+ appears (whether it is required or optional); some older
+ implementations may not interpret other occurrences of folding white
+ space correctly.
+
+date-time = [ day-of-week "," ] date FWS time [CFWS]
+
+day-of-week = ([FWS] day-name) / obs-day-of-week
+
+day-name = "Mon" / "Tue" / "Wed" / "Thu" /
+ "Fri" / "Sat" / "Sun"
+
+date = day month year
+
+year = 4*DIGIT / obs-year
+
+month = (FWS month-name FWS) / obs-month
+
+month-name = "Jan" / "Feb" / "Mar" / "Apr" /
+ "May" / "Jun" / "Jul" / "Aug" /
+ "Sep" / "Oct" / "Nov" / "Dec"
+
+day = ([FWS] 1*2DIGIT) / obs-day
+
+time = time-of-day FWS zone
+
+time-of-day = hour ":" minute [ ":" second ]
+
+hour = 2DIGIT / obs-hour
+
+minute = 2DIGIT / obs-minute
+
+second = 2DIGIT / obs-second
+
+zone = (( "+" / "-" ) 4DIGIT) / obs-zone
+
+
+
+
+
+Resnick Standards Track [Page 14]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ The day is the numeric day of the month. The year is any numeric
+ year 1900 or later.
+
+ The time-of-day specifies the number of hours, minutes, and
+ optionally seconds since midnight of the date indicated.
+
+ The date and time-of-day SHOULD express local time.
+
+ The zone specifies the offset from Coordinated Universal Time (UTC,
+ formerly referred to as "Greenwich Mean Time") that the date and
+ time-of-day represent. The "+" or "-" indicates whether the
+ time-of-day is ahead of (i.e., east of) or behind (i.e., west of)
+ Universal Time. The first two digits indicate the number of hours
+ difference from Universal Time, and the last two digits indicate the
+ number of minutes difference from Universal Time. (Hence, +hhmm
+ means +(hh * 60 + mm) minutes, and -hhmm means -(hh * 60 + mm)
+ minutes). The form "+0000" SHOULD be used to indicate a time zone at
+ Universal Time. Though "-0000" also indicates Universal Time, it is
+ used to indicate that the time was generated on a system that may be
+ in a local time zone other than Universal Time and therefore
+ indicates that the date-time contains no information about the local
+ time zone.
+
+ A date-time specification MUST be semantically valid. That is, the
+ day-of-the-week (if included) MUST be the day implied by the date,
+ the numeric day-of-month MUST be between 1 and the number of days
+ allowed for the specified month (in the specified year), the
+ time-of-day MUST be in the range 00:00:00 through 23:59:60 (the
+ number of seconds allowing for a leap second; see [STD12]), and the
+ zone MUST be within the range -9959 through +9959.
+
+3.4. Address Specification
+
+ Addresses occur in several message header fields to indicate senders
+ and recipients of messages. An address may either be an individual
+ mailbox, or a group of mailboxes.
+
+address = mailbox / group
+
+mailbox = name-addr / addr-spec
+
+name-addr = [display-name] angle-addr
+
+angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
+
+group = display-name ":" [mailbox-list / CFWS] ";"
+ [CFWS]
+
+
+
+
+Resnick Standards Track [Page 15]
+
+RFC 2822 Internet Message Format April 2001
+
+
+display-name = phrase
+
+mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list
+
+address-list = (address *("," address)) / obs-addr-list
+
+ A mailbox receives mail. It is a conceptual entity which does not
+ necessarily pertain to file storage. For example, some sites may
+ choose to print mail on a printer and deliver the output to the
+ addressee's desk. Normally, a mailbox is comprised of two parts: (1)
+ an optional display name that indicates the name of the recipient
+ (which could be a person or a system) that could be displayed to the
+ user of a mail application, and (2) an addr-spec address enclosed in
+ angle brackets ("<" and ">"). There is also an alternate simple form
+ of a mailbox where the addr-spec address appears alone, without the
+ recipient's name or the angle brackets. The Internet addr-spec
+ address is described in section 3.4.1.
+
+ Note: Some legacy implementations used the simple form where the
+ addr-spec appears without the angle brackets, but included the name
+ of the recipient in parentheses as a comment following the addr-spec.
+ Since the meaning of the information in a comment is unspecified,
+ implementations SHOULD use the full name-addr form of the mailbox,
+ instead of the legacy form, to specify the display name associated
+ with a mailbox. Also, because some legacy implementations interpret
+ the comment, comments generally SHOULD NOT be used in address fields
+ to avoid confusing such implementations.
+
+ When it is desirable to treat several mailboxes as a single unit
+ (i.e., in a distribution list), the group construct can be used. The
+ group construct allows the sender to indicate a named group of
+ recipients. This is done by giving a display name for the group,
+ followed by a colon, followed by a comma separated list of any number
+ of mailboxes (including zero and one), and ending with a semicolon.
+ Because the list of mailboxes can be empty, using the group construct
+ is also a simple way to communicate to recipients that the message
+ was sent to one or more named sets of recipients, without actually
+ providing the individual mailbox address for each of those
+ recipients.
+
+3.4.1. Addr-spec specification
+
+ An addr-spec is a specific Internet identifier that contains a
+ locally interpreted string followed by the at-sign character ("@",
+ ASCII value 64) followed by an Internet domain. The locally
+ interpreted string is either a quoted-string or a dot-atom. If the
+ string can be represented as a dot-atom (that is, it contains no
+ characters other than atext characters or "." surrounded by atext
+
+
+
+Resnick Standards Track [Page 16]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ characters), then the dot-atom form SHOULD be used and the
+ quoted-string form SHOULD NOT be used. Comments and folding white
+ space SHOULD NOT be used around the "@" in the addr-spec.
+
+addr-spec = local-part "@" domain
+
+local-part = dot-atom / quoted-string / obs-local-part
+
+domain = dot-atom / domain-literal / obs-domain
+
+domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
+
+dcontent = dtext / quoted-pair
+
+dtext = NO-WS-CTL / ; Non white space controls
+
+ %d33-90 / ; The rest of the US-ASCII
+ %d94-126 ; characters not including "[",
+ ; "]", or "\"
+
+ The domain portion identifies the point to which the mail is
+ delivered. In the dot-atom form, this is interpreted as an Internet
+ domain name (either a host name or a mail exchanger name) as
+ described in [STD3, STD13, STD14]. In the domain-literal form, the
+ domain is interpreted as the literal Internet address of the
+ particular host. In both cases, how addressing is used and how
+ messages are transported to a particular host is covered in the mail
+ transport document [RFC2821]. These mechanisms are outside of the
+ scope of this document.
+
+ The local-part portion is a domain dependent string. In addresses,
+ it is simply interpreted on the particular host as a name of a
+ particular mailbox.
+
+3.5 Overall message syntax
+
+ A message consists of header fields, optionally followed by a message
+ body. Lines in a message MUST be a maximum of 998 characters
+ excluding the CRLF, but it is RECOMMENDED that lines be limited to 78
+ characters excluding the CRLF. (See section 2.1.1 for explanation.)
+ In a message body, though all of the characters listed in the text
+ rule MAY be used, the use of US-ASCII control characters (values 1
+ through 8, 11, 12, and 14 through 31) is discouraged since their
+ interpretation by receivers for display is not guaranteed.
+
+
+
+
+
+
+
+Resnick Standards Track [Page 17]
+
+RFC 2822 Internet Message Format April 2001
+
+
+message = (fields / obs-fields)
+ [CRLF body]
+
+body = *(*998text CRLF) *998text
+
+ The header fields carry most of the semantic information and are
+ defined in section 3.6. The body is simply a series of lines of text
+ which are uninterpreted for the purposes of this standard.
+
+3.6. Field definitions
+
+ The header fields of a message are defined here. All header fields
+ have the same general syntactic structure: A field name, followed by
+ a colon, followed by the field body. The specific syntax for each
+ header field is defined in the subsequent sections.
+
+ Note: In the ABNF syntax for each field in subsequent sections, each
+ field name is followed by the required colon. However, for brevity
+ sometimes the colon is not referred to in the textual description of
+ the syntax. It is, nonetheless, required.
+
+ It is important to note that the header fields are not guaranteed to
+ be in a particular order. They may appear in any order, and they
+ have been known to be reordered occasionally when transported over
+ the Internet. However, for the purposes of this standard, header
+ fields SHOULD NOT be reordered when a message is transported or
+ transformed. More importantly, the trace header fields and resent
+ header fields MUST NOT be reordered, and SHOULD be kept in blocks
+ prepended to the message. See sections 3.6.6 and 3.6.7 for more
+ information.
+
+ The only required header fields are the origination date field and
+ the originator address field(s). All other header fields are
+ syntactically optional. More information is contained in the table
+ following this definition.
+
+fields = *(trace
+ *(resent-date /
+ resent-from /
+ resent-sender /
+ resent-to /
+ resent-cc /
+ resent-bcc /
+ resent-msg-id))
+ *(orig-date /
+ from /
+ sender /
+ reply-to /
+
+
+
+Resnick Standards Track [Page 18]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ to /
+ cc /
+ bcc /
+ message-id /
+ in-reply-to /
+ references /
+ subject /
+ comments /
+ keywords /
+ optional-field)
+
+ The following table indicates limits on the number of times each
+ field may occur in a message header as well as any special
+ limitations on the use of those fields. An asterisk next to a value
+ in the minimum or maximum column indicates that a special restriction
+ appears in the Notes column.
+
+Field Min number Max number Notes
+
+trace 0 unlimited Block prepended - see
+ 3.6.7
+
+resent-date 0* unlimited* One per block, required
+ if other resent fields
+ present - see 3.6.6
+
+resent-from 0 unlimited* One per block - see
+ 3.6.6
+
+resent-sender 0* unlimited* One per block, MUST
+ occur with multi-address
+ resent-from - see 3.6.6
+
+resent-to 0 unlimited* One per block - see
+ 3.6.6
+
+resent-cc 0 unlimited* One per block - see
+ 3.6.6
+
+resent-bcc 0 unlimited* One per block - see
+ 3.6.6
+
+resent-msg-id 0 unlimited* One per block - see
+ 3.6.6
+
+orig-date 1 1
+
+from 1 1 See sender and 3.6.2
+
+
+
+Resnick Standards Track [Page 19]
+
+RFC 2822 Internet Message Format April 2001
+
+
+sender 0* 1 MUST occur with multi-
+ address from - see 3.6.2
+
+reply-to 0 1
+
+to 0 1
+
+cc 0 1
+
+bcc 0 1
+
+message-id 0* 1 SHOULD be present - see
+ 3.6.4
+
+in-reply-to 0* 1 SHOULD occur in some
+ replies - see 3.6.4
+
+references 0* 1 SHOULD occur in some
+ replies - see 3.6.4
+
+subject 0 1
+
+comments 0 unlimited
+
+keywords 0 unlimited
+
+optional-field 0 unlimited
+
+ The exact interpretation of each field is described in subsequent
+ sections.
+
+3.6.1. The origination date field
+
+ The origination date field consists of the field name "Date" followed
+ by a date-time specification.
+
+orig-date = "Date:" date-time CRLF
+
+ The origination date specifies the date and time at which the creator
+ of the message indicated that the message was complete and ready to
+ enter the mail delivery system. For instance, this might be the time
+ that a user pushes the "send" or "submit" button in an application
+ program. In any case, it is specifically not intended to convey the
+ time that the message is actually transported, but rather the time at
+ which the human or other creator of the message has put the message
+ into its final form, ready for transport. (For example, a portable
+ computer user who is not connected to a network might queue a message
+
+
+
+
+Resnick Standards Track [Page 20]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ for delivery. The origination date is intended to contain the date
+ and time that the user queued the message, not the time when the user
+ connected to the network to send the message.)
+
+3.6.2. Originator fields
+
+ The originator fields of a message consist of the from field, the
+ sender field (when applicable), and optionally the reply-to field.
+ The from field consists of the field name "From" and a
+ comma-separated list of one or more mailbox specifications. If the
+ from field contains more than one mailbox specification in the
+ mailbox-list, then the sender field, containing the field name
+ "Sender" and a single mailbox specification, MUST appear in the
+ message. In either case, an optional reply-to field MAY also be
+ included, which contains the field name "Reply-To" and a
+ comma-separated list of one or more addresses.
+
+from = "From:" mailbox-list CRLF
+
+sender = "Sender:" mailbox CRLF
+
+reply-to = "Reply-To:" address-list CRLF
+
+ The originator fields indicate the mailbox(es) of the source of the
+ message. The "From:" field specifies the author(s) of the message,
+ that is, the mailbox(es) of the person(s) or system(s) responsible
+ for the writing of the message. The "Sender:" field specifies the
+ mailbox of the agent responsible for the actual transmission of the
+ message. For example, if a secretary were to send a message for
+ another person, the mailbox of the secretary would appear in the
+ "Sender:" field and the mailbox of the actual author would appear in
+ the "From:" field. If the originator of the message can be indicated
+ by a single mailbox and the author and transmitter are identical, the
+ "Sender:" field SHOULD NOT be used. Otherwise, both fields SHOULD
+ appear.
+
+ The originator fields also provide the information required when
+ replying to a message. When the "Reply-To:" field is present, it
+ indicates the mailbox(es) to which the author of the message suggests
+ that replies be sent. In the absence of the "Reply-To:" field,
+ replies SHOULD by default be sent to the mailbox(es) specified in the
+ "From:" field unless otherwise specified by the person composing the
+ reply.
+
+ In all cases, the "From:" field SHOULD NOT contain any mailbox that
+ does not belong to the author(s) of the message. See also section
+ 3.6.3 for more information on forming the destination addresses for a
+ reply.
+
+
+
+Resnick Standards Track [Page 21]
+
+RFC 2822 Internet Message Format April 2001
+
+
+3.6.3. Destination address fields
+
+ The destination fields of a message consist of three possible fields,
+ each of the same form: The field name, which is either "To", "Cc", or
+ "Bcc", followed by a comma-separated list of one or more addresses
+ (either mailbox or group syntax).
+
+to = "To:" address-list CRLF
+
+cc = "Cc:" address-list CRLF
+
+bcc = "Bcc:" (address-list / [CFWS]) CRLF
+
+ The destination fields specify the recipients of the message. Each
+ destination field may have one or more addresses, and each of the
+ addresses indicate the intended recipients of the message. The only
+ difference between the three fields is how each is used.
+
+ The "To:" field contains the address(es) of the primary recipient(s)
+ of the message.
+
+ The "Cc:" field (where the "Cc" means "Carbon Copy" in the sense of
+ making a copy on a typewriter using carbon paper) contains the
+ addresses of others who are to receive the message, though the
+ content of the message may not be directed at them.
+
+ The "Bcc:" field (where the "Bcc" means "Blind Carbon Copy") contains
+ addresses of recipients of the message whose addresses are not to be
+ revealed to other recipients of the message. There are three ways in
+ which the "Bcc:" field is used. In the first case, when a message
+ containing a "Bcc:" field is prepared to be sent, the "Bcc:" line is
+ removed even though all of the recipients (including those specified
+ in the "Bcc:" field) are sent a copy of the message. In the second
+ case, recipients specified in the "To:" and "Cc:" lines each are sent
+ a copy of the message with the "Bcc:" line removed as above, but the
+ recipients on the "Bcc:" line get a separate copy of the message
+ containing a "Bcc:" line. (When there are multiple recipient
+ addresses in the "Bcc:" field, some implementations actually send a
+ separate copy of the message to each recipient with a "Bcc:"
+ containing only the address of that particular recipient.) Finally,
+ since a "Bcc:" field may contain no addresses, a "Bcc:" field can be
+ sent without any addresses indicating to the recipients that blind
+ copies were sent to someone. Which method to use with "Bcc:" fields
+ is implementation dependent, but refer to the "Security
+ Considerations" section of this document for a discussion of each.
+
+
+
+
+
+
+Resnick Standards Track [Page 22]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ When a message is a reply to another message, the mailboxes of the
+ authors of the original message (the mailboxes in the "From:" field)
+ or mailboxes specified in the "Reply-To:" field (if it exists) MAY
+ appear in the "To:" field of the reply since these would normally be
+ the primary recipients of the reply. If a reply is sent to a message
+ that has destination fields, it is often desirable to send a copy of
+ the reply to all of the recipients of the message, in addition to the
+ author. When such a reply is formed, addresses in the "To:" and
+ "Cc:" fields of the original message MAY appear in the "Cc:" field of
+ the reply, since these are normally secondary recipients of the
+ reply. If a "Bcc:" field is present in the original message,
+ addresses in that field MAY appear in the "Bcc:" field of the reply,
+ but SHOULD NOT appear in the "To:" or "Cc:" fields.
+
+ Note: Some mail applications have automatic reply commands that
+ include the destination addresses of the original message in the
+ destination addresses of the reply. How those reply commands behave
+ is implementation dependent and is beyond the scope of this document.
+ In particular, whether or not to include the original destination
+ addresses when the original message had a "Reply-To:" field is not
+ addressed here.
+
+3.6.4. Identification fields
+
+ Though optional, every message SHOULD have a "Message-ID:" field.
+ Furthermore, reply messages SHOULD have "In-Reply-To:" and
+ "References:" fields as appropriate, as described below.
+
+ The "Message-ID:" field contains a single unique message identifier.
+ The "References:" and "In-Reply-To:" field each contain one or more
+ unique message identifiers, optionally separated by CFWS.
+
+ The message identifier (msg-id) is similar in syntax to an angle-addr
+ construct without the internal CFWS.
+
+message-id = "Message-ID:" msg-id CRLF
+
+in-reply-to = "In-Reply-To:" 1*msg-id CRLF
+
+references = "References:" 1*msg-id CRLF
+
+msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
+
+id-left = dot-atom-text / no-fold-quote / obs-id-left
+
+id-right = dot-atom-text / no-fold-literal / obs-id-right
+
+no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
+
+
+
+Resnick Standards Track [Page 23]
+
+RFC 2822 Internet Message Format April 2001
+
+
+no-fold-literal = "[" *(dtext / quoted-pair) "]"
+
+ The "Message-ID:" field provides a unique message identifier that
+ refers to a particular version of a particular message. The
+ uniqueness of the message identifier is guaranteed by the host that
+ generates it (see below). This message identifier is intended to be
+ machine readable and not necessarily meaningful to humans. A message
+ identifier pertains to exactly one instantiation of a particular
+ message; subsequent revisions to the message each receive new message
+ identifiers.
+
+ Note: There are many instances when messages are "changed", but those
+ changes do not constitute a new instantiation of that message, and
+ therefore the message would not get a new message identifier. For
+ example, when messages are introduced into the transport system, they
+ are often prepended with additional header fields such as trace
+ fields (described in section 3.6.7) and resent fields (described in
+ section 3.6.6). The addition of such header fields does not change
+ the identity of the message and therefore the original "Message-ID:"
+ field is retained. In all cases, it is the meaning that the sender
+ of the message wishes to convey (i.e., whether this is the same
+ message or a different message) that determines whether or not the
+ "Message-ID:" field changes, not any particular syntactic difference
+ that appears (or does not appear) in the message.
+
+ The "In-Reply-To:" and "References:" fields are used when creating a
+ reply to a message. They hold the message identifier of the original
+ message and the message identifiers of other messages (for example,
+ in the case of a reply to a message which was itself a reply). The
+ "In-Reply-To:" field may be used to identify the message (or
+ messages) to which the new message is a reply, while the
+ "References:" field may be used to identify a "thread" of
+ conversation.
+
+ When creating a reply to a message, the "In-Reply-To:" and
+ "References:" fields of the resultant message are constructed as
+ follows:
+
+ The "In-Reply-To:" field will contain the contents of the "Message-
+ ID:" field of the message to which this one is a reply (the "parent
+ message"). If there is more than one parent message, then the "In-
+ Reply-To:" field will contain the contents of all of the parents'
+ "Message-ID:" fields. If there is no "Message-ID:" field in any of
+ the parent messages, then the new message will have no "In-Reply-To:"
+ field.
+
+
+
+
+
+
+Resnick Standards Track [Page 24]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ The "References:" field will contain the contents of the parent's
+ "References:" field (if any) followed by the contents of the parent's
+ "Message-ID:" field (if any). If the parent message does not contain
+ a "References:" field but does have an "In-Reply-To:" field
+ containing a single message identifier, then the "References:" field
+ will contain the contents of the parent's "In-Reply-To:" field
+ followed by the contents of the parent's "Message-ID:" field (if
+ any). If the parent has none of the "References:", "In-Reply-To:",
+ or "Message-ID:" fields, then the new message will have no
+ "References:" field.
+
+ Note: Some implementations parse the "References:" field to display
+ the "thread of the discussion". These implementations assume that
+ each new message is a reply to a single parent and hence that they
+ can walk backwards through the "References:" field to find the parent
+ of each message listed there. Therefore, trying to form a
+ "References:" field for a reply that has multiple parents is
+ discouraged and how to do so is not defined in this document.
+
+ The message identifier (msg-id) itself MUST be a globally unique
+ identifier for a message. The generator of the message identifier
+ MUST guarantee that the msg-id is unique. There are several
+ algorithms that can be used to accomplish this. Since the msg-id has
+ a similar syntax to angle-addr (identical except that comments and
+ folding white space are not allowed), a good method is to put the
+ domain name (or a domain literal IP address) of the host on which the
+ message identifier was created on the right hand side of the "@", and
+ put a combination of the current absolute date and time along with
+ some other currently unique (perhaps sequential) identifier available
+ on the system (for example, a process id number) on the left hand
+ side. Using a date on the left hand side and a domain name or domain
+ literal on the right hand side makes it possible to guarantee
+ uniqueness since no two hosts use the same domain name or IP address
+ at the same time. Though other algorithms will work, it is
+ RECOMMENDED that the right hand side contain some domain identifier
+ (either of the host itself or otherwise) such that the generator of
+ the message identifier can guarantee the uniqueness of the left hand
+ side within the scope of that domain.
+
+ Semantically, the angle bracket characters are not part of the
+ msg-id; the msg-id is what is contained between the two angle bracket
+ characters.
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 25]
+
+RFC 2822 Internet Message Format April 2001
+
+
+3.6.5. Informational fields
+
+ The informational fields are all optional. The "Keywords:" field
+ contains a comma-separated list of one or more words or
+ quoted-strings. The "Subject:" and "Comments:" fields are
+ unstructured fields as defined in section 2.2.1, and therefore may
+ contain text or folding white space.
+
+subject = "Subject:" unstructured CRLF
+
+comments = "Comments:" unstructured CRLF
+
+keywords = "Keywords:" phrase *("," phrase) CRLF
+
+ These three fields are intended to have only human-readable content
+ with information about the message. The "Subject:" field is the most
+ common and contains a short string identifying the topic of the
+ message. When used in a reply, the field body MAY start with the
+ string "Re: " (from the Latin "res", in the matter of) followed by
+ the contents of the "Subject:" field body of the original message.
+ If this is done, only one instance of the literal string "Re: " ought
+ to be used since use of other strings or more than one instance can
+ lead to undesirable consequences. The "Comments:" field contains any
+ additional comments on the text of the body of the message. The
+ "Keywords:" field contains a comma-separated list of important words
+ and phrases that might be useful for the recipient.
+
+3.6.6. Resent fields
+
+ Resent fields SHOULD be added to any message that is reintroduced by
+ a user into the transport system. A separate set of resent fields
+ SHOULD be added each time this is done. All of the resent fields
+ corresponding to a particular resending of the message SHOULD be
+ together. Each new set of resent fields is prepended to the message;
+ that is, the most recent set of resent fields appear earlier in the
+ message. No other fields in the message are changed when resent
+ fields are added.
+
+ Each of the resent fields corresponds to a particular field elsewhere
+ in the syntax. For instance, the "Resent-Date:" field corresponds to
+ the "Date:" field and the "Resent-To:" field corresponds to the "To:"
+ field. In each case, the syntax for the field body is identical to
+ the syntax given previously for the corresponding field.
+
+ When resent fields are used, the "Resent-From:" and "Resent-Date:"
+ fields MUST be sent. The "Resent-Message-ID:" field SHOULD be sent.
+ "Resent-Sender:" SHOULD NOT be used if "Resent-Sender:" would be
+ identical to "Resent-From:".
+
+
+
+Resnick Standards Track [Page 26]
+
+RFC 2822 Internet Message Format April 2001
+
+
+resent-date = "Resent-Date:" date-time CRLF
+
+resent-from = "Resent-From:" mailbox-list CRLF
+
+resent-sender = "Resent-Sender:" mailbox CRLF
+
+resent-to = "Resent-To:" address-list CRLF
+
+resent-cc = "Resent-Cc:" address-list CRLF
+
+resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF
+
+resent-msg-id = "Resent-Message-ID:" msg-id CRLF
+
+ Resent fields are used to identify a message as having been
+ reintroduced into the transport system by a user. The purpose of
+ using resent fields is to have the message appear to the final
+ recipient as if it were sent directly by the original sender, with
+ all of the original fields remaining the same. Each set of resent
+ fields correspond to a particular resending event. That is, if a
+ message is resent multiple times, each set of resent fields gives
+ identifying information for each individual time. Resent fields are
+ strictly informational. They MUST NOT be used in the normal
+ processing of replies or other such automatic actions on messages.
+
+ Note: Reintroducing a message into the transport system and using
+ resent fields is a different operation from "forwarding".
+ "Forwarding" has two meanings: One sense of forwarding is that a mail
+ reading program can be told by a user to forward a copy of a message
+ to another person, making the forwarded message the body of the new
+ message. A forwarded message in this sense does not appear to have
+ come from the original sender, but is an entirely new message from
+ the forwarder of the message. On the other hand, forwarding is also
+ used to mean when a mail transport program gets a message and
+ forwards it on to a different destination for final delivery. Resent
+ header fields are not intended for use with either type of
+ forwarding.
+
+ The resent originator fields indicate the mailbox of the person(s) or
+ system(s) that resent the message. As with the regular originator
+ fields, there are two forms: a simple "Resent-From:" form which
+ contains the mailbox of the individual doing the resending, and the
+ more complex form, when one individual (identified in the
+ "Resent-Sender:" field) resends a message on behalf of one or more
+ others (identified in the "Resent-From:" field).
+
+ Note: When replying to a resent message, replies behave just as they
+ would with any other message, using the original "From:",
+
+
+
+Resnick Standards Track [Page 27]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ "Reply-To:", "Message-ID:", and other fields. The resent fields are
+ only informational and MUST NOT be used in the normal processing of
+ replies.
+
+ The "Resent-Date:" indicates the date and time at which the resent
+ message is dispatched by the resender of the message. Like the
+ "Date:" field, it is not the date and time that the message was
+ actually transported.
+
+ The "Resent-To:", "Resent-Cc:", and "Resent-Bcc:" fields function
+ identically to the "To:", "Cc:", and "Bcc:" fields respectively,
+ except that they indicate the recipients of the resent message, not
+ the recipients of the original message.
+
+ The "Resent-Message-ID:" field provides a unique identifier for the
+ resent message.
+
+3.6.7. Trace fields
+
+ The trace fields are a group of header fields consisting of an
+ optional "Return-Path:" field, and one or more "Received:" fields.
+ The "Return-Path:" header field contains a pair of angle brackets
+ that enclose an optional addr-spec. The "Received:" field contains a
+ (possibly empty) list of name/value pairs followed by a semicolon and
+ a date-time specification. The first item of the name/value pair is
+ defined by item-name, and the second item is either an addr-spec, an
+ atom, a domain, or a msg-id. Further restrictions may be applied to
+ the syntax of the trace fields by standards that provide for their
+ use, such as [RFC2821].
+
+trace = [return]
+ 1*received
+
+return = "Return-Path:" path CRLF
+
+path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) /
+ obs-path
+
+received = "Received:" name-val-list ";" date-time CRLF
+
+name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)]
+
+name-val-pair = item-name CFWS item-value
+
+item-name = ALPHA *(["-"] (ALPHA / DIGIT))
+
+item-value = 1*angle-addr / addr-spec /
+ atom / domain / msg-id
+
+
+
+Resnick Standards Track [Page 28]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ A full discussion of the Internet mail use of trace fields is
+ contained in [RFC2821]. For the purposes of this standard, the trace
+ fields are strictly informational, and any formal interpretation of
+ them is outside of the scope of this document.
+
+3.6.8. Optional fields
+
+ Fields may appear in messages that are otherwise unspecified in this
+ standard. They MUST conform to the syntax of an optional-field.
+ This is a field name, made up of the printable US-ASCII characters
+ except SP and colon, followed by a colon, followed by any text which
+ conforms to unstructured.
+
+ The field names of any optional-field MUST NOT be identical to any
+ field name specified elsewhere in this standard.
+
+optional-field = field-name ":" unstructured CRLF
+
+field-name = 1*ftext
+
+ftext = %d33-57 / ; Any character except
+ %d59-126 ; controls, SP, and
+ ; ":".
+
+ For the purposes of this standard, any optional field is
+ uninterpreted.
+
+4. Obsolete Syntax
+
+ Earlier versions of this standard allowed for different (usually more
+ liberal) syntax than is allowed in this version. Also, there have
+ been syntactic elements used in messages on the Internet whose
+ interpretation have never been documented. Though some of these
+ syntactic forms MUST NOT be generated according to the grammar in
+ section 3, they MUST be accepted and parsed by a conformant receiver.
+ This section documents many of these syntactic elements. Taking the
+ grammar in section 3 and adding the definitions presented in this
+ section will result in the grammar to use for interpretation of
+ messages.
+
+ Note: This section identifies syntactic forms that any implementation
+ MUST reasonably interpret. However, there are certainly Internet
+ messages which do not conform to even the additional syntax given in
+ this section. The fact that a particular form does not appear in any
+ section of this document is not justification for computer programs
+ to crash or for malformed data to be irretrievably lost by any
+ implementation. To repeat an example, though this document requires
+ lines in messages to be no longer than 998 characters, silently
+
+
+
+Resnick Standards Track [Page 29]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ discarding the 999th and subsequent characters in a line without
+ warning would still be bad behavior for an implementation. It is up
+ to the implementation to deal with messages robustly.
+
+ One important difference between the obsolete (interpreting) and the
+ current (generating) syntax is that in structured header field bodies
+ (i.e., between the colon and the CRLF of any structured header
+ field), white space characters, including folding white space, and
+ comments can be freely inserted between any syntactic tokens. This
+ allows many complex forms that have proven difficult for some
+ implementations to parse.
+
+ Another key difference between the obsolete and the current syntax is
+ that the rule in section 3.2.3 regarding lines composed entirely of
+ white space in comments and folding white space does not apply. See
+ the discussion of folding white space in section 4.2 below.
+
+ Finally, certain characters that were formerly allowed in messages
+ appear in this section. The NUL character (ASCII value 0) was once
+ allowed, but is no longer for compatibility reasons. CR and LF were
+ allowed to appear in messages other than as CRLF; this use is also
+ shown here.
+
+ Other differences in syntax and semantics are noted in the following
+ sections.
+
+4.1. Miscellaneous obsolete tokens
+
+ These syntactic elements are used elsewhere in the obsolete syntax or
+ in the main syntax. The obs-char and obs-qp elements each add ASCII
+ value 0. Bare CR and bare LF are added to obs-text and obs-utext.
+ The period character is added to obs-phrase. The obs-phrase-list
+ provides for "empty" elements in a comma-separated list of phrases.
+
+ Note: The "period" (or "full stop") character (".") in obs-phrase is
+ not a form that was allowed in earlier versions of this or any other
+ standard. Period (nor any other character from specials) was not
+ allowed in phrase because it introduced a parsing difficulty
+ distinguishing between phrases and portions of an addr-spec (see
+ section 4.4). It appears here because the period character is
+ currently used in many messages in the display-name portion of
+ addresses, especially for initials in names, and therefore must be
+ interpreted properly. In the future, period may appear in the
+ regular syntax of phrase.
+
+obs-qp = "\" (%d0-127)
+
+obs-text = *LF *CR *(obs-char *LF *CR)
+
+
+
+Resnick Standards Track [Page 30]
+
+RFC 2822 Internet Message Format April 2001
+
+
+obs-char = %d0-9 / %d11 / ; %d0-127 except CR and
+ %d12 / %d14-127 ; LF
+
+obs-utext = obs-text
+
+obs-phrase = word *(word / "." / CFWS)
+
+obs-phrase-list = phrase / 1*([phrase] [CFWS] "," [CFWS]) [phrase]
+
+ Bare CR and bare LF appear in messages with two different meanings.
+ In many cases, bare CR or bare LF are used improperly instead of CRLF
+ to indicate line separators. In other cases, bare CR and bare LF are
+ used simply as ASCII control characters with their traditional ASCII
+ meanings.
+
+4.2. Obsolete folding white space
+
+ In the obsolete syntax, any amount of folding white space MAY be
+ inserted where the obs-FWS rule is allowed. This creates the
+ possibility of having two consecutive "folds" in a line, and
+ therefore the possibility that a line which makes up a folded header
+ field could be composed entirely of white space.
+
+ obs-FWS = 1*WSP *(CRLF 1*WSP)
+
+4.3. Obsolete Date and Time
+
+ The syntax for the obsolete date format allows a 2 digit year in the
+ date field and allows for a list of alphabetic time zone
+ specifications that were used in earlier versions of this standard.
+ It also permits comments and folding white space between many of the
+ tokens.
+
+obs-day-of-week = [CFWS] day-name [CFWS]
+
+obs-year = [CFWS] 2*DIGIT [CFWS]
+
+obs-month = CFWS month-name CFWS
+
+obs-day = [CFWS] 1*2DIGIT [CFWS]
+
+obs-hour = [CFWS] 2DIGIT [CFWS]
+
+obs-minute = [CFWS] 2DIGIT [CFWS]
+
+obs-second = [CFWS] 2DIGIT [CFWS]
+
+obs-zone = "UT" / "GMT" / ; Universal Time
+
+
+
+Resnick Standards Track [Page 31]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ ; North American UT
+ ; offsets
+ "EST" / "EDT" / ; Eastern: - 5/ - 4
+ "CST" / "CDT" / ; Central: - 6/ - 5
+ "MST" / "MDT" / ; Mountain: - 7/ - 6
+ "PST" / "PDT" / ; Pacific: - 8/ - 7
+
+ %d65-73 / ; Military zones - "A"
+ %d75-90 / ; through "I" and "K"
+ %d97-105 / ; through "Z", both
+ %d107-122 ; upper and lower case
+
+ Where a two or three digit year occurs in a date, the year is to be
+ interpreted as follows: If a two digit year is encountered whose
+ value is between 00 and 49, the year is interpreted by adding 2000,
+ ending up with a value between 2000 and 2049. If a two digit year is
+ encountered with a value between 50 and 99, or any three digit year
+ is encountered, the year is interpreted by adding 1900.
+
+ In the obsolete time zone, "UT" and "GMT" are indications of
+ "Universal Time" and "Greenwich Mean Time" respectively and are both
+ semantically identical to "+0000".
+
+ The remaining three character zones are the US time zones. The first
+ letter, "E", "C", "M", or "P" stands for "Eastern", "Central",
+ "Mountain" and "Pacific". The second letter is either "S" for
+ "Standard" time, or "D" for "Daylight" (or summer) time. Their
+ interpretations are as follows:
+
+ EDT is semantically equivalent to -0400
+ EST is semantically equivalent to -0500
+ CDT is semantically equivalent to -0500
+ CST is semantically equivalent to -0600
+ MDT is semantically equivalent to -0600
+ MST is semantically equivalent to -0700
+ PDT is semantically equivalent to -0700
+ PST is semantically equivalent to -0800
+
+ The 1 character military time zones were defined in a non-standard
+ way in [RFC822] and are therefore unpredictable in their meaning.
+ The original definitions of the military zones "A" through "I" are
+ equivalent to "+0100" through "+0900" respectively; "K", "L", and "M"
+ are equivalent to "+1000", "+1100", and "+1200" respectively; "N"
+ through "Y" are equivalent to "-0100" through "-1200" respectively;
+ and "Z" is equivalent to "+0000". However, because of the error in
+ [RFC822], they SHOULD all be considered equivalent to "-0000" unless
+ there is out-of-band information confirming their meaning.
+
+
+
+
+Resnick Standards Track [Page 32]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Other multi-character (usually between 3 and 5) alphabetic time zones
+ have been used in Internet messages. Any such time zone whose
+ meaning is not known SHOULD be considered equivalent to "-0000"
+ unless there is out-of-band information confirming their meaning.
+
+4.4. Obsolete Addressing
+
+ There are three primary differences in addressing. First, mailbox
+ addresses were allowed to have a route portion before the addr-spec
+ when enclosed in "<" and ">". The route is simply a comma-separated
+ list of domain names, each preceded by "@", and the list terminated
+ by a colon. Second, CFWS were allowed between the period-separated
+ elements of local-part and domain (i.e., dot-atom was not used). In
+ addition, local-part is allowed to contain quoted-string in addition
+ to just atom. Finally, mailbox-list and address-list were allowed to
+ have "null" members. That is, there could be two or more commas in
+ such a list with nothing in between them.
+
+obs-angle-addr = [CFWS] "<" [obs-route] addr-spec ">" [CFWS]
+
+obs-route = [CFWS] obs-domain-list ":" [CFWS]
+
+obs-domain-list = "@" domain *(*(CFWS / "," ) [CFWS] "@" domain)
+
+obs-local-part = word *("." word)
+
+obs-domain = atom *("." atom)
+
+obs-mbox-list = 1*([mailbox] [CFWS] "," [CFWS]) [mailbox]
+
+obs-addr-list = 1*([address] [CFWS] "," [CFWS]) [address]
+
+ When interpreting addresses, the route portion SHOULD be ignored.
+
+4.5. Obsolete header fields
+
+ Syntactically, the primary difference in the obsolete field syntax is
+ that it allows multiple occurrences of any of the fields and they may
+ occur in any order. Also, any amount of white space is allowed
+ before the ":" at the end of the field name.
+
+obs-fields = *(obs-return /
+ obs-received /
+ obs-orig-date /
+ obs-from /
+ obs-sender /
+ obs-reply-to /
+ obs-to /
+
+
+
+Resnick Standards Track [Page 33]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ obs-cc /
+ obs-bcc /
+ obs-message-id /
+ obs-in-reply-to /
+ obs-references /
+ obs-subject /
+ obs-comments /
+ obs-keywords /
+ obs-resent-date /
+ obs-resent-from /
+ obs-resent-send /
+ obs-resent-rply /
+ obs-resent-to /
+ obs-resent-cc /
+ obs-resent-bcc /
+ obs-resent-mid /
+ obs-optional)
+
+ Except for destination address fields (described in section 4.5.3),
+ the interpretation of multiple occurrences of fields is unspecified.
+ Also, the interpretation of trace fields and resent fields which do
+ not occur in blocks prepended to the message is unspecified as well.
+ Unless otherwise noted in the following sections, interpretation of
+ other fields is identical to the interpretation of their non-obsolete
+ counterparts in section 3.
+
+4.5.1. Obsolete origination date field
+
+obs-orig-date = "Date" *WSP ":" date-time CRLF
+
+4.5.2. Obsolete originator fields
+
+obs-from = "From" *WSP ":" mailbox-list CRLF
+
+obs-sender = "Sender" *WSP ":" mailbox CRLF
+
+obs-reply-to = "Reply-To" *WSP ":" mailbox-list CRLF
+
+4.5.3. Obsolete destination address fields
+
+obs-to = "To" *WSP ":" address-list CRLF
+
+obs-cc = "Cc" *WSP ":" address-list CRLF
+
+obs-bcc = "Bcc" *WSP ":" (address-list / [CFWS]) CRLF
+
+
+
+
+
+
+Resnick Standards Track [Page 34]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ When multiple occurrences of destination address fields occur in a
+ message, they SHOULD be treated as if the address-list in the first
+ occurrence of the field is combined with the address lists of the
+ subsequent occurrences by adding a comma and concatenating.
+
+4.5.4. Obsolete identification fields
+
+ The obsolete "In-Reply-To:" and "References:" fields differ from the
+ current syntax in that they allow phrase (words or quoted strings) to
+ appear. The obsolete forms of the left and right sides of msg-id
+ allow interspersed CFWS, making them syntactically identical to
+ local-part and domain respectively.
+
+obs-message-id = "Message-ID" *WSP ":" msg-id CRLF
+
+obs-in-reply-to = "In-Reply-To" *WSP ":" *(phrase / msg-id) CRLF
+
+obs-references = "References" *WSP ":" *(phrase / msg-id) CRLF
+
+obs-id-left = local-part
+
+obs-id-right = domain
+
+ For purposes of interpretation, the phrases in the "In-Reply-To:" and
+ "References:" fields are ignored.
+
+ Semantically, none of the optional CFWS surrounding the local-part
+ and the domain are part of the obs-id-left and obs-id-right
+ respectively.
+
+4.5.5. Obsolete informational fields
+
+obs-subject = "Subject" *WSP ":" unstructured CRLF
+
+obs-comments = "Comments" *WSP ":" unstructured CRLF
+
+obs-keywords = "Keywords" *WSP ":" obs-phrase-list CRLF
+
+4.5.6. Obsolete resent fields
+
+ The obsolete syntax adds a "Resent-Reply-To:" field, which consists
+ of the field name, the optional comments and folding white space, the
+ colon, and a comma separated list of addresses.
+
+obs-resent-from = "Resent-From" *WSP ":" mailbox-list CRLF
+
+obs-resent-send = "Resent-Sender" *WSP ":" mailbox CRLF
+
+
+
+
+Resnick Standards Track [Page 35]
+
+RFC 2822 Internet Message Format April 2001
+
+
+obs-resent-date = "Resent-Date" *WSP ":" date-time CRLF
+
+obs-resent-to = "Resent-To" *WSP ":" address-list CRLF
+
+obs-resent-cc = "Resent-Cc" *WSP ":" address-list CRLF
+
+obs-resent-bcc = "Resent-Bcc" *WSP ":"
+ (address-list / [CFWS]) CRLF
+
+obs-resent-mid = "Resent-Message-ID" *WSP ":" msg-id CRLF
+
+obs-resent-rply = "Resent-Reply-To" *WSP ":" address-list CRLF
+
+ As with other resent fields, the "Resent-Reply-To:" field is to be
+ treated as trace information only.
+
+4.5.7. Obsolete trace fields
+
+ The obs-return and obs-received are again given here as template
+ definitions, just as return and received are in section 3. Their
+ full syntax is given in [RFC2821].
+
+obs-return = "Return-Path" *WSP ":" path CRLF
+
+obs-received = "Received" *WSP ":" name-val-list CRLF
+
+obs-path = obs-angle-addr
+
+4.5.8. Obsolete optional fields
+
+obs-optional = field-name *WSP ":" unstructured CRLF
+
+5. Security Considerations
+
+ Care needs to be taken when displaying messages on a terminal or
+ terminal emulator. Powerful terminals may act on escape sequences
+ and other combinations of ASCII control characters with a variety of
+ consequences. They can remap the keyboard or permit other
+ modifications to the terminal which could lead to denial of service
+ or even damaged data. They can trigger (sometimes programmable)
+ answerback messages which can allow a message to cause commands to be
+ issued on the recipient's behalf. They can also effect the operation
+ of terminal attached devices such as printers. Message viewers may
+ wish to strip potentially dangerous terminal escape sequences from
+ the message prior to display. However, other escape sequences appear
+ in messages for useful purposes (cf. [RFC2045, RFC2046, RFC2047,
+ RFC2048, RFC2049, ISO2022]) and therefore should not be stripped
+ indiscriminately.
+
+
+
+Resnick Standards Track [Page 36]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Transmission of non-text objects in messages raises additional
+ security issues. These issues are discussed in [RFC2045, RFC2046,
+ RFC2047, RFC2048, RFC2049].
+
+ Many implementations use the "Bcc:" (blind carbon copy) field
+ described in section 3.6.3 to facilitate sending messages to
+ recipients without revealing the addresses of one or more of the
+ addressees to the other recipients. Mishandling this use of "Bcc:"
+ has implications for confidential information that might be revealed,
+ which could eventually lead to security problems through knowledge of
+ even the existence of a particular mail address. For example, if
+ using the first method described in section 3.6.3, where the "Bcc:"
+ line is removed from the message, blind recipients have no explicit
+ indication that they have been sent a blind copy, except insofar as
+ their address does not appear in the message header. Because of
+ this, one of the blind addressees could potentially send a reply to
+ all of the shown recipients and accidentally reveal that the message
+ went to the blind recipient. When the second method from section
+ 3.6.3 is used, the blind recipient's address appears in the "Bcc:"
+ field of a separate copy of the message. If the "Bcc:" field sent
+ contains all of the blind addressees, all of the "Bcc:" recipients
+ will be seen by each "Bcc:" recipient. Even if a separate message is
+ sent to each "Bcc:" recipient with only the individual's address,
+ implementations still need to be careful to process replies to the
+ message as per section 3.6.3 so as not to accidentally reveal the
+ blind recipient to other recipients.
+
+6. Bibliography
+
+ [ASCII] American National Standards Institute (ANSI), Coded
+ Character Set - 7-Bit American National Standard Code for
+ Information Interchange, ANSI X3.4, 1986.
+
+ [ISO2022] International Organization for Standardization (ISO),
+ Information processing - ISO 7-bit and 8-bit coded
+ character sets - Code extension techniques, Third edition
+ - 1986-05-01, ISO 2022, 1986.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA Internet
+ Text Messages", RFC 822, August 1982.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+
+
+Resnick Standards Track [Page 37]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ [RFC2047] Moore, K., "Multipurpose Internet Mail Extensions (MIME)
+ Part Three: Message Header Extensions for Non-ASCII Text",
+ RFC 2047, November 1996.
+
+ [RFC2048] Freed, N., Klensin, J. and J. Postel, "Multipurpose
+ Internet Mail Extensions (MIME) Part Four: Format of
+ Internet Message Bodies", RFC 2048, November 1996.
+
+ [RFC2049] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Five: Conformance Criteria and
+ Examples", RFC 2049, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2234] Crocker, D., Editor, and P. Overell, "Augmented BNF for
+ Syntax Specifications: ABNF", RFC 2234, November 1997.
+
+ [RFC2821] Klensin, J., Editor, "Simple Mail Transfer Protocol", RFC
+ 2821, March 2001.
+
+ [STD3] Braden, R., "Host Requirements", STD 3, RFC 1122 and RFC
+ 1123, October 1989.
+
+ [STD12] Mills, D., "Network Time Protocol", STD 12, RFC 1119,
+ September 1989.
+
+ [STD13] Mockapetris, P., "Domain Name System", STD 13, RFC 1034
+ and RFC 1035, November 1987.
+
+ [STD14] Partridge, C., "Mail Routing and the Domain System", STD
+ 14, RFC 974, January 1986.
+
+7. Editor's Address
+
+ Peter W. Resnick
+ QUALCOMM Incorporated
+ 5775 Morehouse Drive
+ San Diego, CA 92121-1714
+ USA
+
+ Phone: +1 858 651 4478
+ Fax: +1 858 651 1102
+ EMail: presnick@qualcomm.com
+
+
+
+
+
+
+
+Resnick Standards Track [Page 38]
+
+RFC 2822 Internet Message Format April 2001
+
+
+8. Acknowledgements
+
+ Many people contributed to this document. They included folks who
+ participated in the Detailed Revision and Update of Messaging
+ Standards (DRUMS) Working Group of the Internet Engineering Task
+ Force (IETF), the chair of DRUMS, the Area Directors of the IETF, and
+ people who simply sent their comments in via e-mail. The editor is
+ deeply indebted to them all and thanks them sincerely. The below
+ list includes everyone who sent e-mail concerning this document.
+ Hopefully, everyone who contributed is named here:
+
+ Matti Aarnio Barry Finkel Larry Masinter
+ Tanaka Akira Erik Forsberg Denis McKeon
+ Russ Allbery Chuck Foster William P McQuillan
+ Eric Allman Paul Fox Alexey Melnikov
+ Harald Tveit Alvestrand Klaus M. Frank Perry E. Metzger
+ Ran Atkinson Ned Freed Steven Miller
+ Jos Backus Jochen Friedrich Keith Moore
+ Bruce Balden Randall C. Gellens John Gardiner Myers
+ Dave Barr Sukvinder Singh Gill Chris Newman
+ Alan Barrett Tim Goodwin John W. Noerenberg
+ John Beck Philip Guenther Eric Norman
+ J. Robert von Behren Tony Hansen Mike O'Dell
+ Jos den Bekker John Hawkinson Larry Osterman
+ D. J. Bernstein Philip Hazel Paul Overell
+ James Berriman Kai Henningsen Jacob Palme
+ Norbert Bollow Robert Herriot Michael A. Patton
+ Raj Bose Paul Hethmon Uzi Paz
+ Antony Bowesman Jim Hill Michael A. Quinlan
+ Scott Bradner Paul E. Hoffman Eric S. Raymond
+ Randy Bush Steve Hole Sam Roberts
+ Tom Byrer Kari Hurtta Hugh Sasse
+ Bruce Campbell Marco S. Hyman Bart Schaefer
+ Larry Campbell Ofer Inbar Tom Scola
+ W. J. Carpenter Olle Jarnefors Wolfgang Segmuller
+ Michael Chapman Kevin Johnson Nick Shelness
+ Richard Clayton Sudish Joseph John Stanley
+ Maurizio Codogno Maynard Kang Einar Stefferud
+ Jim Conklin Prabhat Keni Jeff Stephenson
+ R. Kelley Cook John C. Klensin Bernard Stern
+ Steve Coya Graham Klyne Peter Sylvester
+ Mark Crispin Brad Knowles Mark Symons
+ Dave Crocker Shuhei Kobayashi Eric Thomas
+ Matt Curtin Peter Koch Lee Thompson
+ Michael D'Errico Dan Kohn Karel De Vriendt
+ Cyrus Daboo Christian Kuhtz Matthew Wall
+ Jutta Degener Anand Kumria Rolf Weber
+ Mark Delany Steen Larsen Brent B. Welch
+
+
+
+Resnick Standards Track [Page 39]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Steve Dorner Eliot Lear Dan Wing
+ Harold A. Driscoll Barry Leiba Jack De Winter
+ Michael Elkins Jay Levitt Gregory J. Woodhouse
+ Robert Elz Lars-Johan Liman Greg A. Woods
+ Johnny Eriksson Charles Lindsey Kazu Yamamoto
+ Erik E. Fair Pete Loshin Alain Zahm
+ Roger Fajman Simon Lyall Jamie Zawinski
+ Patrik Faltstrom Bill Manning Timothy S. Zurcher
+ Claus Andre Farber John Martin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 40]
+
+RFC 2822 Internet Message Format April 2001
+
+
+Appendix A. Example messages
+
+ This section presents a selection of messages. These are intended to
+ assist in the implementation of this standard, but should not be
+ taken as normative; that is to say, although the examples in this
+ section were carefully reviewed, if there happens to be a conflict
+ between these examples and the syntax described in sections 3 and 4
+ of this document, the syntax in those sections is to be taken as
+ correct.
+
+ Messages are delimited in this section between lines of "----". The
+ "----" lines are not part of the message itself.
+
+A.1. Addressing examples
+
+ The following are examples of messages that might be sent between two
+ individuals.
+
+A.1.1. A message from one person to another with simple addressing
+
+ This could be called a canonical message. It has a single author,
+ John Doe, a single recipient, Mary Smith, a subject, the date, a
+ message identifier, and a textual message in the body.
+
+----
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 41]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ If John's secretary Michael actually sent the message, though John
+ was the author and replies to this message should go back to him, the
+ sender field would be used:
+
+----
+From: John Doe <jdoe@machine.example>
+Sender: Michael Jones <mjones@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+A.1.2. Different types of mailboxes
+
+ This message includes multiple addresses in the destination fields
+ and also uses several different forms of addresses.
+
+----
+From: "Joe Q. Public" <john.q.public@example.com>
+To: Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>
+Cc: <boss@nil.test>, "Giant; \"Big\" Box" <sysservices@example.net>
+Date: Tue, 1 Jul 2003 10:52:37 +0200
+Message-ID: <5678.21-Nov-1997@example.com>
+
+Hi everyone.
+----
+
+ Note that the display names for Joe Q. Public and Giant; "Big" Box
+ needed to be enclosed in double-quotes because the former contains
+ the period and the latter contains both semicolon and double-quote
+ characters (the double-quote characters appearing as quoted-pair
+ construct). Conversely, the display name for Who? could appear
+ without them because the question mark is legal in an atom. Notice
+ also that jdoe@example.org and boss@nil.test have no display names
+ associated with them at all, and jdoe@example.org uses the simpler
+ address form without the angle brackets.
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 42]
+
+RFC 2822 Internet Message Format April 2001
+
+
+A.1.3. Group addresses
+
+----
+From: Pete <pete@silly.example>
+To: A Group:Chris Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;
+Cc: Undisclosed recipients:;
+Date: Thu, 13 Feb 1969 23:32:54 -0330
+Message-ID: <testabcd.1234@silly.example>
+
+Testing.
+----
+
+ In this message, the "To:" field has a single group recipient named A
+ Group which contains 3 addresses, and a "Cc:" field with an empty
+ group recipient named Undisclosed recipients.
+
+A.2. Reply messages
+
+ The following is a series of three messages that make up a
+ conversation thread between John and Mary. John firsts sends a
+ message to Mary, Mary then replies to John's message, and then John
+ replies to Mary's reply message.
+
+ Note especially the "Message-ID:", "References:", and "In-Reply-To:"
+ fields in each message.
+
+----
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 43]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ When sending replies, the Subject field is often retained, though
+ prepended with "Re: " as described in section 3.6.5.
+
+----
+From: Mary Smith <mary@example.net>
+To: John Doe <jdoe@machine.example>
+Reply-To: "Mary Smith: Personal Account" <smith@home.example>
+Subject: Re: Saying Hello
+Date: Fri, 21 Nov 1997 10:01:10 -0600
+Message-ID: <3456@example.net>
+In-Reply-To: <1234@local.machine.example>
+References: <1234@local.machine.example>
+
+This is a reply to your hello.
+----
+
+ Note the "Reply-To:" field in the above message. When John replies
+ to Mary's message above, the reply should go to the address in the
+ "Reply-To:" field instead of the address in the "From:" field.
+
+----
+To: "Mary Smith: Personal Account" <smith@home.example>
+From: John Doe <jdoe@machine.example>
+Subject: Re: Saying Hello
+Date: Fri, 21 Nov 1997 11:00:00 -0600
+Message-ID: <abcd.1234@local.machine.tld>
+In-Reply-To: <3456@example.net>
+References: <1234@local.machine.example> <3456@example.net>
+
+This is a reply to your reply.
+----
+
+A.3. Resent messages
+
+ Start with the message that has been used as an example several
+ times:
+
+----
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+
+
+
+Resnick Standards Track [Page 44]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ Say that Mary, upon receiving this message, wishes to send a copy of
+ the message to Jane such that (a) the message would appear to have
+ come straight from John; (b) if Jane replies to the message, the
+ reply should go back to John; and (c) all of the original
+ information, like the date the message was originally sent to Mary,
+ the message identifier, and the original addressee, is preserved. In
+ this case, resent fields are prepended to the message:
+
+----
+Resent-From: Mary Smith <mary@example.net>
+Resent-To: Jane Brown <j-brown@other.example>
+Resent-Date: Mon, 24 Nov 1997 14:22:01 -0800
+Resent-Message-ID: <78910@example.net>
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+ If Jane, in turn, wished to resend this message to another person,
+ she would prepend her own set of resent header fields to the above
+ and send that.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 45]
+
+RFC 2822 Internet Message Format April 2001
+
+
+A.4. Messages with trace fields
+
+ As messages are sent through the transport system as described in
+ [RFC2821], trace fields are prepended to the message. The following
+ is an example of what those trace fields might look like. Note that
+ there is some folding white space in the first one since these lines
+ can be long.
+
+----
+Received: from x.y.test
+ by example.net
+ via TCP
+ with ESMTP
+ id ABC12345
+ for <mary@example.net>; 21 Nov 1997 10:05:43 -0600
+Received: from machine.example by x.y.test; 21 Nov 1997 10:01:22 -0600
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: Fri, 21 Nov 1997 09:55:06 -0600
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 46]
+
+RFC 2822 Internet Message Format April 2001
+
+
+A.5. White space, comments, and other oddities
+
+ White space, including folding white space, and comments can be
+ inserted between many of the tokens of fields. Taking the example
+ from A.1.3, white space and comments can be inserted into all of the
+ fields.
+
+----
+From: Pete(A wonderful \) chap) <pete(his account)@silly.test(his host)>
+To:A Group(Some people)
+ :Chris Jones <c@(Chris's host.)public.example>,
+ joe@example.org,
+ John <jdoe@one.test> (my dear friend); (the end of the group)
+Cc:(Empty list)(start)Undisclosed recipients :(nobody(that I know)) ;
+Date: Thu,
+ 13
+ Feb
+ 1969
+ 23:32
+ -0330 (Newfoundland Time)
+Message-ID: <testabcd.1234@silly.test>
+
+Testing.
+----
+
+ The above example is aesthetically displeasing, but perfectly legal.
+ Note particularly (1) the comments in the "From:" field (including
+ one that has a ")" character appearing as part of a quoted-pair); (2)
+ the white space absent after the ":" in the "To:" field as well as
+ the comment and folding white space after the group name, the special
+ character (".") in the comment in Chris Jones's address, and the
+ folding white space before and after "joe@example.org,"; (3) the
+ multiple and nested comments in the "Cc:" field as well as the
+ comment immediately following the ":" after "Cc"; (4) the folding
+ white space (but no comments except at the end) and the missing
+ seconds in the time of the date field; and (5) the white space before
+ (but not within) the identifier in the "Message-ID:" field.
+
+A.6. Obsoleted forms
+
+ The following are examples of obsolete (that is, the "MUST NOT
+ generate") syntactic elements described in section 4 of this
+ document.
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 47]
+
+RFC 2822 Internet Message Format April 2001
+
+
+A.6.1. Obsolete addressing
+
+ Note in the below example the lack of quotes around Joe Q. Public,
+ the route that appears in the address for Mary Smith, the two commas
+ that appear in the "To:" field, and the spaces that appear around the
+ "." in the jdoe address.
+
+----
+From: Joe Q. Public <john.q.public@example.com>
+To: Mary Smith <@machine.tld:mary@example.net>, , jdoe@test . example
+Date: Tue, 1 Jul 2003 10:52:37 +0200
+Message-ID: <5678.21-Nov-1997@example.com>
+
+Hi everyone.
+----
+
+A.6.2. Obsolete dates
+
+ The following message uses an obsolete date format, including a non-
+ numeric time zone and a two digit year. Note that although the
+ day-of-week is missing, that is not specific to the obsolete syntax;
+ it is optional in the current syntax as well.
+
+----
+From: John Doe <jdoe@machine.example>
+To: Mary Smith <mary@example.net>
+Subject: Saying Hello
+Date: 21 Nov 97 09:55:06 GMT
+Message-ID: <1234@local.machine.example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+A.6.3. Obsolete white space and comments
+
+ White space and comments can appear between many more elements than
+ in the current syntax. Also, folding lines that are made up entirely
+ of white space are legal.
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 48]
+
+RFC 2822 Internet Message Format April 2001
+
+
+----
+From : John Doe <jdoe@machine(comment). example>
+To : Mary Smith
+__
+ <mary@example.net>
+Subject : Saying Hello
+Date : Fri, 21 Nov 1997 09(comment): 55 : 06 -0600
+Message-ID : <1234 @ local(blah) .machine .example>
+
+This is a message just to say hello.
+So, "Hello".
+----
+
+ Note especially the second line of the "To:" field. It starts with
+ two space characters. (Note that "__" represent blank spaces.)
+ Therefore, it is considered part of the folding as described in
+ section 4.2. Also, the comments and white space throughout
+ addresses, dates, and message identifiers are all part of the
+ obsolete syntax.
+
+Appendix B. Differences from earlier standards
+
+ This appendix contains a list of changes that have been made in the
+ Internet Message Format from earlier standards, specifically [RFC822]
+ and [STD3]. Items marked with an asterisk (*) below are items which
+ appear in section 4 of this document and therefore can no longer be
+ generated.
+
+ 1. Period allowed in obsolete form of phrase.
+ 2. ABNF moved out of document to [RFC2234].
+ 3. Four or more digits allowed for year.
+ 4. Header field ordering (and lack thereof) made explicit.
+ 5. Encrypted header field removed.
+ 6. Received syntax loosened to allow any token/value pair.
+ 7. Specifically allow and give meaning to "-0000" time zone.
+ 8. Folding white space is not allowed between every token.
+ 9. Requirement for destinations removed.
+ 10. Forwarding and resending redefined.
+ 11. Extension header fields no longer specifically called out.
+ 12. ASCII 0 (null) removed.*
+ 13. Folding continuation lines cannot contain only white space.*
+ 14. Free insertion of comments not allowed in date.*
+ 15. Non-numeric time zones not allowed.*
+ 16. Two digit years not allowed.*
+ 17. Three digit years interpreted, but not allowed for generation.
+ 18. Routes in addresses not allowed.*
+ 19. CFWS within local-parts and domains not allowed.*
+ 20. Empty members of address lists not allowed.*
+
+
+
+Resnick Standards Track [Page 49]
+
+RFC 2822 Internet Message Format April 2001
+
+
+ 21. Folding white space between field name and colon not allowed.*
+ 22. Comments between field name and colon not allowed.
+ 23. Tightened syntax of in-reply-to and references.*
+ 24. CFWS within msg-id not allowed.*
+ 25. Tightened semantics of resent fields as informational only.
+ 26. Resent-Reply-To not allowed.*
+ 27. No multiple occurrences of fields (except resent and received).*
+ 28. Free CR and LF not allowed.*
+ 29. Routes in return path not allowed.*
+ 30. Line length limits specified.
+ 31. Bcc more clearly specified.
+
+Appendix C. Notices
+
+ Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 50]
+
+RFC 2822 Internet Message Format April 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Resnick Standards Track [Page 51]
+
diff --git a/standards/rfc2910.txt b/standards/rfc2910.txt
new file mode 100644
index 000000000..e13631c2a
--- /dev/null
+++ b/standards/rfc2910.txt
@@ -0,0 +1,2579 @@
+
+
+
+
+
+
+Network Working Group R. Herriot, Editor
+Request for Comments: 2910 Xerox Corporation
+Obsoletes: 2565 S. Butler
+Category: Standards Track Hewlett-Packard
+ P. Moore
+ Peerless Systems Networking
+ R. Turner
+ 2wire.com
+ J. Wenn
+ Xerox Corporation
+ September 2000
+
+
+ Internet Printing Protocol/1.1: Encoding and Transport
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document defines the
+ rules for encoding IPP operations and IPP attributes into a new
+ Internet mime media type called "application/ipp". This document
+ also defines the rules for transporting over Hypertext Transfer
+ Protocol (HTTP) a message body whose Content-Type is
+ "application/ipp". This document defines a new scheme named 'ipp' for
+ identifying IPP printers and jobs.
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 1]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics [RFC2911]
+ Internet Printing Protocol/1.1: Encoding and Transport (this
+ document)
+ Internet Printing Protocol/1.1: Implementer's Guide [ipp-iig]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The document, "Design Goals for an Internet Printing Protocol", takes
+ a broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.1. A few OPTIONAL operator operations have
+ been added to IPP/1.1.
+
+ The document, "Rationale for the Structure and Model and Protocol for
+ the Internet Printing Protocol", describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specification documents, and gives background and rationale
+ for the IETF working group's major decisions.
+
+ The document, "Internet Printing Protocol/1.1: Model and Semantics",
+ describes a simplified model with abstract objects, their attributes,
+ and their operations that are independent of encoding and transport.
+ It introduces a Printer and a Job object. The Job object optionally
+ supports multiple documents per Job. It also addresses security,
+ internationalization, and directory issues.
+
+ The document "Internet Printing Protocol/1.1: Implementer's Guide",
+ gives advice to implementers of IPP clients and IPP objects.
+
+ The document "Mapping between LPD and IPP Protocols", gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 2]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+Table of Contents
+
+ 1. Introduction ...................................................4
+ 2. Conformance Terminology ........................................4
+ 3. Encoding of the Operation Layer ...............................4
+ 3.1 Picture of the Encoding ...................................6
+ 3.1.1 Request and Response...................................6
+ 3.1.2 Attribute Group........................................6
+ 3.1.3 Attribute..............................................7
+ 3.1.4 Picture of the Encoding of an Attribute-with-one-value.7
+ 3.1.5 Additional-value.......................................8
+ 3.1.6 Alternative Picture of the Encoding of a Request Or a
+ Response...............................................9
+ 3.2 Syntax of Encoding ........................................9
+ 3.3 Attribute-group ..........................................11
+ 3.4 Required Parameters ......................................12
+ 3.4.1 Version-number........................................12
+ 3.4.2 Operation-id..........................................12
+ 3.4.3 Status-code...........................................12
+ 3.4.4 Request-id............................................13
+ 3.5 Tags .....................................................13
+ 3.5.1 Delimiter Tags........................................13
+ 3.5.2 Value Tags............................................14
+ 3.6 Name-Length ..............................................16
+ 3.7 (Attribute) Name .........................................16
+ 3.8 Value Length .............................................16
+ 3.9 (Attribute) Value ........................................17
+ 3.10 Data .....................................................18
+ 4. Encoding of Transport Layer ...................................18
+ 4.1 Printer-uri and job-uri ..................................19
+ 5. IPP URL Scheme ................................................20
+ 6. IANA Considerations ...........................................22
+ 7. Internationalization Considerations ...........................23
+ 8. Security Considerations .......................................23
+ 8.1 Security Conformance Requirements ........................23
+ 8.1.1 Digest Authentication.................................23
+ 8.1.2 Transport Layer Security (TLS)........................24
+ 8.2 Using IPP with TLS .......................................25
+ 9. Interoperability with IPP/1.0 Implementations .................25
+ 9.1 The "version-number" Parameter ...........................25
+ 9.2 Security and URL Schemes .................................26
+ 10. References ...................................................27
+ 11. Authors' Addresses ...........................................29
+ 12. Other Participants: ..........................................31
+ 13. Appendix A: Protocol Examples ................................33
+ 13.1 Print-Job Request ........................................33
+ 13.2 Print-Job Response (successful) ..........................34
+ 13.3 Print-Job Response (failure) .............................35
+
+
+
+Herriot, et al. Standards Track [Page 3]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ 13.4 Print-Job Response (success with attributes ignored) .....36
+ 13.5 Print-URI Request ........................................38
+ 13.6 Create-Job Request .......................................39
+ 13.7 Get-Jobs Request .........................................40
+ 13.8 Get-Jobs Response ........................................41
+ 14. Appendix B: Registration of MIME Media Type Information for
+ "application/ipp".............................................42
+ 15. Appendix C: Changes from IPP/1.0 .............................44
+ 16. Full Copyright Statement .....................................45
+
+1. Introduction
+
+ This document contains the rules for encoding IPP operations and
+ describes two layers: the transport layer and the operation layer.
+
+ The transport layer consists of an HTTP/1.1 request or response. RFC
+ 2616 [RFC2616] describes HTTP/1.1. This document specifies the HTTP
+ headers that an IPP implementation supports.
+
+ The operation layer consists of a message body in an HTTP request or
+ response. The document "Internet Printing Protocol/1.1: Model and
+ Semantics" [RFC2911] defines the semantics of such a message body and
+ the supported values. This document specifies the encoding of an IPP
+ operation. The aforementioned document [RFC2911] is henceforth
+ referred to as the "IPP model document" or simply "model document".
+
+ Note: the version number of IPP (1.1) and HTTP (1.1) are not linked.
+ They both just happen to be 1.1.
+
+2. Conformance Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+ interpreted as described in RFC 2119 [RFC2119].
+
+3. Encoding of the Operation Layer
+
+ The operation layer is the message body part of the HTTP request or
+ response and it MUST contain a single IPP operation request or IPP
+ operation response. Each request or response consists of a sequence
+ of values and attribute groups. Attribute groups consist of a
+ sequence of attributes each of which is a name and value. Names and
+ values are ultimately sequences of octets.
+
+ The encoding consists of octets as the most primitive type. There are
+ several types built from octets, but three important types are
+ integers, character strings and octet strings, on which most other
+ data types are built. Every character string in this encoding MUST be
+
+
+
+Herriot, et al. Standards Track [Page 4]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ a sequence of characters where the characters are associated with
+ some charset and some natural language. A character string MUST be in
+ "reading order" with the first character in the value (according to
+ reading order) being the first character in the encoding. A character
+ string whose associated charset is US-ASCII whose associated natural
+ language is US English is henceforth called a US-ASCII-STRING. A
+ character string whose associated charset and natural language are
+ specified in a request or response as described in the model document
+ is henceforth called a LOCALIZED-STRING. An octet string MUST be in
+ "IPP model document order" with the first octet in the value
+ (according to the IPP model document order) being the first octet in
+ the encoding. Every integer in this encoding MUST be encoded as a
+ signed integer using two's-complement binary encoding with big-endian
+ format (also known as "network order" and "most significant byte
+ first"). The number of octets for an integer MUST be 1, 2 or 4,
+ depending on usage in the protocol. Such one-octet integers,
+ henceforth called SIGNED-BYTE, are used for the version-number and
+ tag fields. Such two-byte integers, henceforth called SIGNED-SHORT
+ are used for the operation-id, status-code and length fields. Four
+ byte integers, henceforth called SIGNED-INTEGER, are used for value
+ fields and the request-id.
+
+ The following two sections present the encoding of the operation
+ layer in two ways:
+
+ - informally through pictures and description
+ - formally through Augmented Backus-Naur Form (ABNF), as
+ specified by RFC 2234 [RFC2234]
+
+ An operation request or response MUST use the encoding described in
+ these two sections.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 5]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+3.1 Picture of the Encoding
+
+3.1.1 Request and Response
+
+ An operation request or response is encoded as follows:
+
+ -----------------------------------------------
+ | version-number | 2 bytes - required
+ -----------------------------------------------
+ | operation-id (request) |
+ | or | 2 bytes - required
+ | status-code (response) |
+ -----------------------------------------------
+ | request-id | 4 bytes - required
+ -----------------------------------------------
+ | attribute-group | n bytes - 0 or more
+ -----------------------------------------------
+ | end-of-attributes-tag | 1 byte - required
+ -----------------------------------------------
+ | data | q bytes - optional
+ -----------------------------------------------
+
+ The first three fields in the above diagram contain the value of
+ attributes described in section 3.1.1 of the Model document.
+
+ The fourth field is the "attribute-group" field, and it occurs 0 or
+ more times. Each "attribute-group" field represents a single group of
+ attributes, such as an Operation Attributes group or a Job Attributes
+ group (see the Model document). The IPP model document specifies the
+ required attribute groups and their order for each operation request
+ and response.
+
+ The "end-of-attributes-tag" field is always present, even when the
+ "data" is not present. The Model document specifies for each
+ operation request and response whether the "data" field is present or
+ absent.
+
+3.1.2 Attribute Group
+
+ Each "attribute-group" field is encoded as follows:
+
+ -----------------------------------------------
+ | begin-attribute-group-tag | 1 byte
+ ----------------------------------------------------------
+ | attribute | p bytes |- 0 or more
+ ----------------------------------------------------------
+
+
+
+
+
+Herriot, et al. Standards Track [Page 6]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The "begin-attribute-group-tag" field marks the beginning of an
+ "attribute-group" field and its value identifies the type of
+ attribute group, e.g. Operations Attributes group versus a Job
+ Attributes group. The "begin-attribute-group-tag" field also marks
+ the end of the previous attribute group except for the "begin-
+ attribute-group-tag" field in the first "attribute-group" field of a
+ request or response. The "begin-attribute-group-tag" field acts as
+ an "attribute-group" terminator because an "attribute-group" field
+ cannot nest inside another "attribute-group" field.
+
+ An "attribute-group" field contains zero or more "attribute" fields.
+
+ Note, the values of the "begin-attribute-group-tag" field and the
+ "end-of-attributes-tag" field are called "delimiter-tags".
+
+3.1.3 Attribute
+
+ An "attribute" field is encoded as follows:
+
+ -----------------------------------------------
+ | attribute-with-one-value | q bytes
+ ----------------------------------------------------------
+ | additional-value | r bytes |- 0 or more
+ ----------------------------------------------------------
+
+ When an attribute is single valued (e.g. "copies" with value of 10)
+ or multi-valued with one value (e.g. "sides-supported" with just the
+ value 'one-sided') it is encoded with just an "attribute-with-one-
+ value" field. When an attribute is multi-valued with n values (e.g.
+ "sides-supported" with the values 'one-sided' and 'two-sided-long-
+ edge'), it is encoded with an "attribute-with-one-value" field
+ followed by n-1 "additional-value" fields.
+
+3.1.4 Picture of the Encoding of an Attribute-with-one-value
+
+ Each "attribute-with-one-value" field is encoded as follows:
+
+ -----------------------------------------------
+ | value-tag | 1 byte
+ -----------------------------------------------
+ | name-length (value is u) | 2 bytes
+ -----------------------------------------------
+ | name | u bytes
+ -----------------------------------------------
+ | value-length (value is v) | 2 bytes
+ -----------------------------------------------
+ | value | v bytes
+ -----------------------------------------------
+
+
+
+Herriot, et al. Standards Track [Page 7]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ An "attribute-with-one-value" field is encoded with five subfields:
+
+ The "value-tag" field specifies the attribute syntax, e.g. 0x44
+ for the attribute syntax 'keyword'.
+
+ The "name-length" field specifies the length of the "name" field
+ in bytes, e.g. u in the above diagram or 15 for the name "sides-
+ supported".
+
+ The "name" field contains the textual name of the attribute, e.g.
+ "sides-supported".
+
+ The "value-length" field specifies the length of the "value" field
+ in bytes, e.g. v in the above diagram or 9 for the (keyword) value
+ 'one-sided'.
+
+ The "value" field contains the value of the attribute, e.g. the
+ textual value 'one-sided'.
+
+3.1.5 Additional-value
+
+ Each "additional-value" field is encoded as follows:
+
+ -----------------------------------------------
+ | value-tag | 1 byte
+ -----------------------------------------------
+ | name-length (value is 0x0000) | 2 bytes
+ -----------------------------------------------
+ | value-length (value is w) | 2 bytes
+ -----------------------------------------------
+ | value | w bytes
+ -----------------------------------------------
+
+ An "additional-value" is encoded with four subfields:
+
+ The "value-tag" field specifies the attribute syntax, e.g. 0x44
+ for the attribute syntax 'keyword'.
+
+ The "name-length" field has the value of 0 in order to signify
+ that it is an "additional-value". The value of the "name-length"
+ field distinguishes an "additional-value" field ("name-length" is
+ 0) from an "attribute-with-one-value" field ("name-length" is not
+ 0).
+
+ The "value-length" field specifies the length of the "value" field
+ in bytes, e.g. w in the above diagram or 19 for the (keyword)
+ value 'two-sided-long-edge'.
+
+
+
+
+Herriot, et al. Standards Track [Page 8]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The "value" field contains the value of the attribute, e.g. the
+ textual value 'two-sided-long-edge'.
+
+3.1.6 Alternative Picture of the Encoding of a Request Or a Response
+
+ From the standpoint of a parser that performs an action based on a
+ "tag" value, the encoding consists of:
+
+ -----------------------------------------------
+ | version-number | 2 bytes - required
+ -----------------------------------------------
+ | operation-id (request) |
+ | or | 2 bytes - required
+ | status-code (response) |
+ -----------------------------------------------
+ | request-id | 4 bytes - required
+ -----------------------------------------------------------
+ | tag (delimiter-tag or value-tag) | 1 byte |
+ ----------------------------------------------- |-0 or more
+ | empty or rest of attribute | x bytes |
+ -----------------------------------------------------------
+ | end-of-attributes-tag | 1 byte - required
+ -----------------------------------------------
+ | data | y bytes - optional
+ -----------------------------------------------
+
+ The following show what fields the parser would expect after each
+ type of "tag":
+
+ - "begin-attribute-group-tag": expect zero or more "attribute"
+ fields
+ - "value-tag": expect the remainder of an "attribute-with-one-
+ value" or an "additional-value".
+ - "end-of-attributes-tag": expect that "attribute" fields are
+ complete and there is optional "data"
+
+3.2 Syntax of Encoding
+
+ The syntax below is ABNF [RFC2234] except 'strings of literals' MUST
+ be case sensitive. For example 'a' means lower case 'a' and not
+ upper case 'A'. In addition, SIGNED-BYTE and SIGNED-SHORT fields
+ are represented as '%x' values which show their range of values.
+
+ ipp-message = ipp-request / ipp-response
+ ipp-request = version-number operation-id request-id
+ *attribute-group end-of-attributes-tag data
+ ipp-response = version-number status-code request-id
+ *attribute-group end-of-attributes-tag data
+
+
+
+Herriot, et al. Standards Track [Page 9]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ attribute-group = begin-attribute-group-tag *attribute
+
+ version-number = major-version-number minor-version-number
+ major-version-number = SIGNED-BYTE
+ minor-version-number = SIGNED-BYTE
+
+ operation-id = SIGNED-SHORT ; mapping from model defined below
+ status-code = SIGNED-SHORT ; mapping from model defined below
+ request-id = SIGNED-INTEGER ; whose value is > 0
+
+ attribute = attribute-with-one-value *additional-value
+
+ attribute-with-one-value = value-tag name-length name
+ value-length value
+ additional-value = value-tag zero-name-length value-length value
+
+ name-length = SIGNED-SHORT ; number of octets of 'name'
+ name = LALPHA *( LALPHA / DIGIT / "-" / "_" / "." )
+ value-length = SIGNED-SHORT ; number of octets of 'value'
+ value = OCTET-STRING
+
+ data = OCTET-STRING
+
+ zero-name-length = %x00.00 ; name-length of 0
+ value-tag = %x10-FF ;see section 3.7.2
+ begin-attribute-group-tag = %x00-02 / %04-0F ; see section 3.7.1
+ end-of-attributes-tag = %x03 ; tag of 3
+ ; see section 3.7.1
+ SIGNED-BYTE = BYTE
+ SIGNED-SHORT = 2BYTE
+ SIGNED-INTEGER = 4BYTE
+ DIGIT = %x30-39 ; "0" to "9"
+ LALPHA = %x61-7A ; "a" to "z"
+ BYTE = %x00-FF
+ OCTET-STRING = *BYTE
+
+ The syntax below defines additional terms that are referenced in this
+ document. This syntax provides an alternate grouping of the delimiter
+ tags.
+
+ delimiter-tag = begin-attribute-group-tag / ; see section 3.7.1
+ end-of-attributes-tag
+ delimiter-tag = %x00-0F ; see section 3.7.1
+
+ begin-attribute-group-tag = %x00 / operation-attributes-tag /
+ job-attributes-tag / printer-attributes-tag /
+ unsupported-attributes-tag / %x06-0F
+ operation-attributes-tag = %x01 ; tag of 1
+
+
+
+Herriot, et al. Standards Track [Page 10]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ job-attributes-tag = %x02 ; tag of 2
+ printer-attributes-tag = %x04 ; tag of 4
+ unsupported-attributes-tag = %x05 ; tag of 5
+
+3.3 Attribute-group
+
+ Each "attribute-group" field MUST be encoded with the "begin-
+ attribute-group-tag" field followed by zero or more "attribute" sub-
+ fields.
+
+ The table below maps the model document group name to value of the
+ "begin-attribute-group-tag" field:
+
+ Model Document Group "begin-attribute-group-tag" field
+ values
+
+ Operation Attributes "operations-attributes-tag"
+ Job Template Attributes "job-attributes-tag"
+ Job Object Attributes "job-attributes-tag"
+ Unsupported Attributes "unsupported-attributes-tag"
+ Requested Attributes "job-attributes-tag"
+ (Get-Job-Attributes)
+ Requested Attributes "printer-attributes-tag"
+ (Get-Printer-Attributes)
+ Document Content in a special position as
+ described above
+
+ For each operation request and response, the model document
+ prescribes the required and optional attribute groups, along with
+ their order. Within each attribute group, the model document
+ prescribes the required and optional attributes, along with their
+ order.
+
+ When the Model document requires an attribute group in a request or
+ response and the attribute group contains zero attributes, a request
+ or response SHOULD encode the attribute group with the "begin-
+ attribute-group-tag" field followed by zero "attribute" fields. For
+ example, if the client requests a single unsupported attribute with
+ the Get-Printer-Attributes operation, the Printer MUST return no
+ "attribute" fields, and it SHOULD return a "begin-attribute-group-
+ tag" field for the Printer Attributes Group. The Unsupported
+ Attributes group is not such an example. According to the model
+ document, the Unsupported Attributes Group SHOULD be present only if
+ the unsupported attributes group contains at least one attribute.
+
+ A receiver of a request MUST be able to process the following as
+ equivalent empty attribute groups:
+
+
+
+
+Herriot, et al. Standards Track [Page 11]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ a) A "begin-attribute-group-tag" field with zero following
+ "attribute" fields.
+
+ b) An expected but missing "begin-attribute-group-tag" field.
+
+ When the Model document requires a sequence of an unknown number of
+ attribute groups, each of the same type, the encoding MUST contain
+ one "begin-attribute-group-tag" field for each attribute group even
+ when an "attribute-group" field contains zero "attribute" sub-fields.
+ For example, for the Get-Jobs operation may return zero attributes
+ for some jobs and not others. The "begin-attribute-group-tag" field
+ followed by zero "attribute" fields tells the recipient that there is
+ a job in queue for which no information is available except that it
+ is in the queue.
+
+3.4 Required Parameters
+
+ Some operation elements are called parameters in the model document
+ [RFC2911]. They MUST be encoded in a special position and they MUST
+ NOT appear as operation attributes. These parameters are described
+ in the subsections below.
+
+3.4.1 Version-number
+
+ The "version-number" field MUST consist of a major and minor
+ version-number, each of which MUST be represented by a SIGNED-BYTE.
+ The major version-number MUST be the first byte of the encoding and
+ the minor version-number MUST be the second byte of the encoding. The
+ protocol described in this document MUST have a major version-number
+ of 1 (0x01) and a minor version-number of 1 (0x01). The ABNF for
+ these two bytes MUST be %x01.01.
+
+3.4.2 Operation-id
+
+ The "operation-id" field MUST contain an operation-id value defined
+ in the model document. The value MUST be encoded as a SIGNED-SHORT
+ and it MUST be in the third and fourth bytes of the encoding of an
+ operation request.
+
+3.4.3 Status-code
+
+ The "status-code" field MUST contain a status-code value defined in
+ the model document. The value MUST be encoded as a SIGNED-SHORT and
+ it MUST be in the third and fourth bytes of the encoding of an
+ operation response.
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 12]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The status-code is an operation attribute in the model document. In
+ the protocol, the status-code is in a special position, outside of
+ the operation attributes.
+
+ If an IPP status-code is returned, then the HTTP Status-Code MUST be
+ 200 (successful-ok). With any other HTTP Status-Code value, the HTTP
+ response MUST NOT contain an IPP message-body, and thus no IPP
+ status-code is returned.
+
+3.4.4 Request-id
+
+ The "request-id" field MUST contain a request-id value as defined in
+ the model document. The value MUST be encoded as a SIGNED-INTEGER and
+ it MUST be in the fifth through eighth bytes of the encoding.
+
+3.5 Tags
+
+ There are two kinds of tags:
+
+ - delimiter tags: delimit major sections of the protocol, namely
+ attributes and data
+ - value tags: specify the type of each attribute value
+
+3.5.1 Delimiter Tags
+
+ The following table specifies the values for the delimiter tags:
+
+ Tag Value (Hex) Meaning
+
+ 0x00 reserved for definition in a future IETF
+ standards track document
+ 0x01 "operation-attributes-tag"
+ 0x02 "job-attributes-tag"
+ 0x03 "end-of-attributes-tag"
+ 0x04 "printer-attributes-tag"
+ 0x05 "unsupported-attributes-tag"
+ 0x06-0x0f reserved for future delimiters in IETF
+ standards track documents
+
+ When a "begin-attribute-group-tag" field occurs in the protocol, it
+ means that zero or more following attributes up to the next delimiter
+ tag MUST be attributes belonging to the attribute group specified by
+ the value of the "begin-attribute-group-tag". For example, if the
+ value of "begin-attribute-group-tag" is 0x01, the following
+ attributes MUST be members of the Operations Attributes group.
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 13]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The "end-of-attributes-tag" (value 0x03) MUST occur exactly once in
+ an operation. It MUST be the last "delimiter-tag". If the operation
+ has a document-content group, the document data in that group MUST
+ follow the "end-of-attributes-tag".
+
+ The order and presence of "attribute-group" fields (whose beginning
+ is marked by the "begin-attribute-group-tag" subfield) for each
+ operation request and each operation response MUST be that defined in
+ the model document. For further details, see section 3.7 "(Attribute)
+ Name" and 13 "Appendix A: Protocol Examples".
+
+ A Printer MUST treat a "delimiter-tag" (values from 0x00 through
+ 0x0F) differently from a "value-tag" (values from 0x10 through 0xFF)
+ so that the Printer knows that there is an entire attribute group
+ that it doesn't understand as opposed to a single value that it
+ doesn't understand.
+
+3.5.2 Value Tags
+
+ The remaining tables show values for the "value-tag" field, which is
+ the first octet of an attribute. The "value-tag" field specifies the
+ type of the value of the attribute.
+
+ The following table specifies the "out-of-band" values for the
+ "value-tag" field.
+
+ Tag Value (Hex) Meaning
+
+ 0x10 unsupported
+ 0x11 reserved for 'default' for definition in a future
+ IETF standards track document
+ 0x12 unknown
+ 0x13 no-value
+ 0x14-0x1F reserved for "out-of-band" values in future IETF
+ standards track documents.
+
+ The following table specifies the integer values for the "value-tag"
+ field:
+
+ Tag Value (Hex) Meaning
+
+ 0x20 reserved for definition in a future IETF
+ standards track document
+ 0x21 integer
+ 0x22 boolean
+ 0x23 enum
+ 0x24-0x2F reserved for integer types for definition in
+ future IETF standards track documents
+
+
+
+Herriot, et al. Standards Track [Page 14]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ NOTE: 0x20 is reserved for "generic integer" if it should ever be
+ needed.
+
+ The following table specifies the octetString values for the "value-
+ tag" field:
+
+ Tag Value (Hex) Meaning
+
+ 0x30 octetString with an unspecified format
+ 0x31 dateTime
+ 0x32 resolution
+ 0x33 rangeOfInteger
+ 0x34 reserved for definition in a future IETF
+ standards track document
+ 0x35 textWithLanguage
+ 0x36 nameWithLanguage
+ 0x37-0x3F reserved for octetString type definitions in
+ future IETF standards track documents
+
+ The following table specifies the character-string values for the
+ "value-tag" field:
+
+ Tag Value (Hex) Meaning
+
+ 0x40 reserved for definition in a future IETF
+ standards track document
+ 0x41 textWithoutLanguage
+ 0x42 nameWithoutLanguage
+ 0x43 reserved for definition in a future IETF
+ standards track document
+ 0x44 keyword
+ 0x45 uri
+ 0x46 uriScheme
+ 0x47 charset
+ 0x48 naturalLanguage
+ 0x49 mimeMediaType
+ 0x4A-0x5F reserved for character string type definitions
+ in future IETF standards track documents
+
+ NOTE: 0x40 is reserved for "generic character-string" if it should
+ ever be needed.
+
+ NOTE: an attribute value always has a type, which is explicitly
+ specified by its tag; one such tag value is "nameWithoutLanguage".
+ An attribute's name has an implicit type, which is keyword.
+
+ The values 0x60-0xFF are reserved for future type definitions in IETF
+ standards track documents.
+
+
+
+Herriot, et al. Standards Track [Page 15]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The tag 0x7F is reserved for extending types beyond the 255 values
+ available with a single byte. A tag value of 0x7F MUST signify that
+ the first 4 bytes of the value field are interpreted as the tag
+ value. Note this future extension doesn't affect parsers that are
+ unaware of this special tag. The tag is like any other unknown tag,
+ and the value length specifies the length of a value, which contains
+ a value that the parser treats atomically. Values from 0x00 to
+ 0x37777777 are reserved for definition in future IETF standard track
+ documents. The values 0x40000000 to 0x7FFFFFFF are reserved for
+ vendor extensions.
+
+3.6 Name-Length
+
+ The "name-length" field MUST consist of a SIGNED-SHORT. This field
+ MUST specify the number of octets in the immediately following "name"
+ field. The value of this field excludes the two bytes of the "name-
+ length" field. For example, if the "name" field contains "sides", the
+ value of this field is 5.
+
+ If a "name-length" field has a value of zero, the following "name"
+ field MUST be empty, and the following value MUST be treated as an
+ additional value for the attribute encoded in the nearest preceding
+ "attribute-with-one-value" field. Within an attribute group, if two
+ or more attributes have the same name, the attribute group is mal-
+ formed (see [RFC2911] section 3.1.3). The zero-length name is the
+ only mechanism for multi-valued attributes.
+
+3.7 (Attribute) Name
+
+ The "name" field MUST contain the name of an attribute. The model
+ document [RFC2911] specifies such names.
+
+3.8 Value Length
+
+ The "value-length" field MUST consist of a SIGNED-SHORT. This field
+ MUST specify the number of octets in the immediately following
+ "value" field. The value of this field excludes the two bytes of the
+ "value-length" field. For example, if the "value" field contains the
+ keyword (text) value 'one-sided', the value of this field is 9.
+
+ For any of the types represented by binary signed integers, the
+ sender MUST encode the value in exactly four octets.
+
+ For any of the types represented by character-strings, the sender
+ MUST encode the value with all the characters of the string and
+ without any padding characters.
+
+
+
+
+
+Herriot, et al. Standards Track [Page 16]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ For "out-of-band" "value-tag" fields defined in this document, such
+ as "unsupported", the "value-length" MUST be 0 and the "value" empty;
+ the "value" has no meaning when the "value-tag" has one of these
+ "out-of-band" values. For future "out-of-band" "value-tag" fields,
+ the same rule holds unless the definition explicitly states that the
+ "value-length" MAY be non-zero and the "value" non-empty.
+
+3.9 (Attribute) Value
+
+ The syntax types (specified by the "value-tag" field) and most of the
+ details of the representation of attribute values are defined in the
+ IPP model document. The table below augments the information in the
+ model document, and defines the syntax types from the model document
+ in terms of the 5 basic types defined in section 3, "Encoding of the
+ Operation Layer". The 5 types are US-ASCII-STRING, LOCALIZED-STRING,
+ SIGNED-INTEGER, SIGNED-SHORT, SIGNED-BYTE, and OCTET-STRING.
+
+ Syntax of Attribute Encoding
+ Value
+
+ textWithoutLanguage, LOCALIZED-STRING.
+ nameWithoutLanguage
+
+ textWithLanguage OCTET-STRING consisting of 4 fields:
+ a. a SIGNED-SHORT which is the number of
+ octets in the following field
+ b. a value of type natural-language,
+ c. a SIGNED-SHORT which is the number of
+ octets in the following field,
+ d. a value of type textWithoutLanguage.
+ The length of a textWithLanguage value MUST be
+ 4 + the value of field a + the value of field c.
+
+ nameWithLanguage OCTET-STRING consisting of 4 fields:
+ a. a SIGNED-SHORT which is the number of
+ octets in the following field
+ b. a value of type natural-language,
+ c. a SIGNED-SHORT which is the number of
+ octets in the following field
+ d. a value of type nameWithoutLanguage.
+ The length of a nameWithLanguage value MUST be
+ 4 + the value of field a + the value of field c.
+
+ charset, US-ASCII-STRING.
+ naturalLanguage,
+ mimeMediaType,
+ keyword, uri, and
+ uriScheme
+
+
+
+Herriot, et al. Standards Track [Page 17]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Syntax of Attribute Encoding
+ Value
+
+ boolean SIGNED-BYTE where 0x00 is 'false' and 0x01 is
+ 'true'.
+
+ integer and enum a SIGNED-INTEGER.
+
+ dateTime OCTET-STRING consisting of eleven octets whose
+ contents are defined by "DateAndTime" in RFC
+ 1903 [RFC1903].
+
+ resolution OCTET-STRING consisting of nine octets of 2
+ SIGNED-INTEGERs followed by a SIGNED-BYTE. The
+ first SIGNED-INTEGER contains the value of
+ cross feed direction resolution. The second
+ SIGNED-INTEGER contains the value of feed
+ direction resolution. The SIGNED-BYTE contains
+ the units
+
+ rangeOfInteger Eight octets consisting of 2 SIGNED-INTEGERs.
+ The first SIGNED-INTEGER contains the lower
+ bound and the second SIGNED-INTEGER contains
+ the upper bound.
+
+ 1setOf X Encoding according to the rules for an
+ attribute with more than 1 value. Each value
+ X is encoded according to the rules for
+ encoding its type.
+
+ octetString OCTET-STRING
+
+
+ The attribute syntax type of the value determines its encoding and
+ the value of its "value-tag".
+
+3.10 Data
+
+ The "data" field MUST include any data required by the operation
+
+4. Encoding of Transport Layer
+
+ HTTP/1.1 [RFC2616] is the transport layer for this protocol.
+
+ The operation layer has been designed with the assumption that the
+ transport layer contains the following information:
+
+
+
+
+
+Herriot, et al. Standards Track [Page 18]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ - the URI of the target job or printer operation
+ - the total length of the data in the operation layer, either as
+ a single length or as a sequence of chunks each with a length.
+
+ It is REQUIRED that a printer implementation support HTTP over the
+ IANA assigned Well Known Port 631 (the IPP default port), though a
+ printer implementation may support HTTP over some other port as well.
+
+ Each HTTP operation MUST use the POST method where the request-URI is
+ the object target of the operation, and where the "Content-Type" of
+ the message-body in each request and response MUST be
+ "application/ipp". The message-body MUST contain the operation layer
+ and MUST have the syntax described in section 3.2 "Syntax of
+ Encoding". A client implementation MUST adhere to the rules for a
+ client described for HTTP1.1 [RFC2616]. A printer (server)
+ implementation MUST adhere the rules for an origin server described
+ for HTTP1.1 [RFC2616].
+
+ An IPP server sends a response for each request that it receives. If
+ an IPP server detects an error, it MAY send a response before it has
+ read the entire request. If the HTTP layer of the IPP server
+ completes processing the HTTP headers successfully, it MAY send an
+ intermediate response, such as "100 Continue", with no IPP data
+ before sending the IPP response. A client MUST expect such a variety
+ of responses from an IPP server. For further information on HTTP/1.1,
+ consult the HTTP documents [RFC2616].
+
+ An HTTP server MUST support chunking for IPP requests, and an IPP
+ client MUST support chunking for IPP responses according to HTTP/1.1
+ [RFC2616]. Note: this rule causes a conflict with non-compliant
+ implementations of HTTP/1.1 that don't support chunking for POST
+ methods, and this rule may cause a conflict with non-compliant
+ implementations of HTTP/1.1 that don't support chunking for CGI
+ scripts.
+
+4.1 Printer-uri and job-uri
+
+ All Printer and Job objects are identified by a Uniform Resource
+ Identifier (URI) [RFC2396] so that they can be persistently and
+ unambiguously referenced. Since every URL is a specialized form of a
+ URI, even though the more generic term URI is used throughout the
+ rest of this document, its usage is intended to cover the more
+ specific notion of URL as well.
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 19]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Some operation elements are encoded twice, once as the request-URI on
+ the HTTP Request-Line and a second time as a REQUIRED operation
+ attribute in the application/ipp entity. These attributes are the
+ target URI for the operation and are called printer-uri and job-uri.
+ Note: The target URI is included twice in an operation referencing
+ the same IPP object, but the two URIs NEED NOT be literally
+ identical. One can be a relative URI and the other can be an absolute
+ URI. HTTP/1.1 allows clients to generate and send a relative URI
+ rather than an absolute URI. A relative URI identifies a resource
+ with the scope of the HTTP server, but does not include scheme, host
+ or port. The following statements characterize how URLs should be
+ used in the mapping of IPP onto HTTP/1.1:
+
+ 1. Although potentially redundant, a client MUST supply the target
+ of the operation both as an operation attribute and as a URI at
+ the HTTP layer. The rationale for this decision is to maintain
+ a consistent set of rules for mapping application/ipp to
+ possibly many communication layers, even where URLs are not
+ used as the addressing mechanism in the transport layer.
+ 2. Even though these two URLs might not be literally identical
+ (one being relative and the other being absolute), they MUST
+ both reference the same IPP object. However, a Printer NEED NOT
+ verify that the two URLs reference the same IPP object, and
+ NEED NOT take any action if it determines the two URLs to be
+ different.
+ 3. The URI in the HTTP layer is either relative or absolute and is
+ used by the HTTP server to route the HTTP request to the
+ correct resource relative to that HTTP server. The HTTP server
+ need not be aware of the URI within the operation request.
+ 4. Once the HTTP server resource begins to process the HTTP
+ request, it might get the reference to the appropriate IPP
+ Printer object from either the HTTP URI (using to the context
+ of the HTTP server for relative URLs) or from the URI within
+ the operation request; the choice is up to the implementation.
+ 5. HTTP URIs can be relative or absolute, but the target URI in
+ the operation MUST be an absolute URI.
+
+5. IPP URL Scheme
+
+ The IPP/1.1 document defines a new scheme 'ipp' as the value of a URL
+ that identifies either an IPP printer object or an IPP job object.
+ The IPP attributes using the 'ipp' scheme are specified below.
+ Because the HTTP layer does not support the 'ipp' scheme, a client
+ MUST map 'ipp' URLs to 'http' URLs, and then follows the HTTP
+ [RFC2616][RFC2617] rules for constructing a Request-Line and HTTP
+ headers. The mapping is simple because the 'ipp' scheme implies all
+ of the same protocol semantics as that of the 'http' scheme
+
+
+
+
+Herriot, et al. Standards Track [Page 20]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ [RFC2616], except that it represents a print service and the implicit
+ (default) port number that clients use to connect to a server is port
+ 631.
+
+ In the remainder of this section the term 'ipp-URL' means a URL whose
+ scheme is 'ipp' and whose implicit (default) port is 631. The term
+ 'http-URL' means a URL whose scheme is 'http', and the term 'https-
+ URL' means a URL whose scheme is 'https',
+
+ A client and an IPP object (i.e. the server) MUST support the ipp-URL
+ value in the following IPP attributes.
+ job attributes:
+ job-uri
+ job-printer-uri
+ printer attributes:
+ printer-uri-supported
+ operation attributes:
+ job-uri
+ printer-uri
+ Each of the above attributes identifies a printer or job object. The
+ ipp-URL is intended as the value of the attributes in this list, and
+ for no other attributes. All of these attributes have a syntax type
+ of 'uri', but there are attributes with a syntax type of 'uri' that
+ do not use the 'ipp' scheme, e.g. 'job-more-info'.
+
+ If a printer registers its URL with a directory service, the printer
+ MUST register an ipp-URL.
+
+ User interfaces are beyond the scope of this document. But if
+ software exposes the ipp-URL values of any of the above five
+ attributes to a human user, it is REQUIRED that the human see the
+ ipp-URL as is.
+
+ When a client sends a request, it MUST convert a target ipp-URL to a
+ target http-URL for the HTTP layer according to the following rules:
+
+ 1. change the 'ipp' scheme to 'http'
+ 2. add an explicit port 631 if the URL does not contain an
+ explicit port. Note: port 631 is the IANA assigned Well Known
+ Port for the 'ipp' scheme.
+
+ The client MUST use the target http-URL in both the HTTP Request-
+ Line and HTTP headers, as specified by HTTP [RFC2616] [RFC2617] .
+ However, the client MUST use the target ipp-URL for the value of the
+ "printer-uri" or "job-uri" operation attribute within the
+ application/ipp body of the request. The server MUST use the ipp-URL
+
+
+
+
+
+Herriot, et al. Standards Track [Page 21]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ for the value of the "printer-uri", "job-uri" or "printer-uri-
+ supported" attributes within the application/ipp body of the
+ response.
+
+ For example, when an IPP client sends a request directly (i.e. no
+ proxy) to an ipp-URL "ipp://myhost.com/myprinter/myqueue", it opens a
+ TCP connection to port 631 (the ipp implicit port) on the host
+ "myhost.com" and sends the following data:
+
+ POST /myprinter/myqueue HTTP/1.1
+ Host: myhost.com:631
+ Content-type: application/ipp
+ Transfer-Encoding: chunked
+ ...
+ "printer-uri" "ipp://myhost.com/myprinter/myqueue"
+ (encoded in application/ipp message body)
+ ...
+
+ As another example, when an IPP client sends the same request as
+ above via a proxy "myproxy.com", it opens a TCP connection to the
+ proxy port 8080 on the proxy host "myproxy.com" and sends the
+ following data:
+
+ POST http://myhost.com:631/myprinter/myqueue HTTP/1.1
+ Host: myhost.com:631
+ Content-type: application/ipp
+ Transfer-Encoding: chunked
+ ...
+ "printer-uri" "ipp://myhost.com/myprinter/myqueue"
+ (encoded in application/ipp message body)
+ ...
+
+ The proxy then connects to the IPP origin server with headers that
+ are the same as the "no-proxy" example above.
+
+6. IANA Considerations
+
+ This section describes the procedures for allocating encoding for the
+ following IETF standards track extensions and vendor extensions to
+ the IPP/1.1 Encoding and Transport document:
+
+ 1. attribute syntaxes - see [RFC2911] section 6.3
+ 2. attribute groups - see [RFC2911] section 6.5
+ 3. out-of-band attribute values - see [RFC2911] section 6.7
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 22]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ These extensions follow the "type2" registration procedures defined
+ in [RFC2911] section 6. Extensions registered for use with IPP/1.1
+ are OPTIONAL for client and IPP object conformance to the IPP/1.1
+ Encoding and Transport document.
+
+ These extension procedures are aligned with the guidelines as set
+ forth by the IESG [IANA-CON]. The [RFC2911] Section 11 describes how
+ to propose new registrations for consideration. IANA will reject
+ registration proposals that leave out required information or do not
+ follow the appropriate format described in [RFC2911] Section 11. The
+ IPP/1.1 Encoding and Transport document may also be extended by an
+ appropriate RFC that specifies any of the above extensions.
+
+7. Internationalization Considerations
+
+ See the section on "Internationalization Considerations" in the
+ document "Internet Printing Protocol/1.1: Model and Semantics"
+ [RFC2911] for information on internationalization. This document adds
+ no additional issues.
+
+8. Security Considerations
+
+ The IPP Model and Semantics document [RFC2911] discusses high level
+ security requirements (Client Authentication, Server Authentication
+ and Operation Privacy). Client Authentication is the mechanism by
+ which the client proves its identity to the server in a secure
+ manner. Server Authentication is the mechanism by which the server
+ proves its identity to the client in a secure manner. Operation
+ Privacy is defined as a mechanism for protecting operations from
+ eavesdropping.
+
+8.1 Security Conformance Requirements
+
+ This section defines the security requirements for IPP clients and
+ IPP objects.
+
+8.1.1 Digest Authentication
+
+ IPP clients MUST support:
+
+ Digest Authentication [RFC2617].
+
+ MD5 and MD5-sess MUST be implemented and supported.
+
+ The Message Integrity feature NEED NOT be used.
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 23]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ IPP Printers SHOULD support:
+
+ Digest Authentication [RFC2617].
+
+ MD5 and MD5-sess MUST be implemented and supported.
+
+ The Message Integrity feature NEED NOT be used.
+
+ The reasons that IPP Printers SHOULD (rather than MUST) support
+ Digest Authentication are:
+
+ 1. While Client Authentication is important, there is a certain class
+ of printer devices where it does not make sense. Specifically, a
+ low-end device with limited ROM space and low paper throughput may
+ not need Client Authentication. This class of device typically
+ requires firmware designers to make trade-offs between protocols
+ and functionality to arrive at the lowest-cost solution possible.
+ Factored into the designer's decisions is not just the size of the
+ code, but also the testing, maintenance, usefulness, and time-to-
+ market impact for each feature delivered to the customer. Forcing
+ such low-end devices to provide security in order to claim IPP/1.1
+ conformance would not make business sense and could potentially
+ stall the adoption of the standard.
+
+ 2. Print devices that have high-volume throughput and have available
+ ROM space have a compelling argument to provide support for Client
+ Authentication that safeguards the device from unauthorized
+ access. These devices are prone to a high loss of consumables and
+ paper if unauthorized access should occur.
+
+8.1.2 Transport Layer Security (TLS)
+
+ IPP Printers SHOULD support Transport Layer Security (TLS) [RFC2246]
+ for Server Authentication and Operation Privacy. IPP Printers MAY
+ also support TLS for Client Authentication. If an IPP Printer
+ supports TLS, it MUST support the TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+ cipher suite as mandated by RFC 2246 [RFC2246]. All other cipher
+ suites are OPTIONAL. An IPP Printer MAY support Basic Authentication
+ (described in HTTP/1.1 [RFC2617]) for Client Authentication if the
+ channel is secure. TLS with the above mandated cipher suite can
+ provide such a secure channel.
+
+ If a IPP client supports TLS, it MUST support the
+ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA cipher suite as mandated by RFC
+ 2246 [RFC2246]. All other cipher suites are OPTIONAL.
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 24]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ The IPP Model and Semantics document defines two printer attributes
+ ("uri-authentication-supported" and "uri-security-supported") that
+ the client can use to discover the security policy of a printer. That
+ document also outlines IPP-specific security considerations and
+ should be the primary reference for security implications with regard
+ to the IPP protocol itself. For backward compatibility with IPP
+ version 1.0, IPP clients and printers may also support SSL3 [ssl].
+ This is in addition to the security required in this document.
+
+8.2 Using IPP with TLS
+
+ IPP/1.1 uses the "Upgrading to TLS Within HTTP/1.1" mechanism
+ [RFC2817]. An initial IPP request never uses TLS. The client
+ requests a secure TLS connection by using the HTTP "Upgrade" header,
+ while the server agrees in the HTTP response. The switch to TLS
+ occurs either because the server grants the client's request to
+ upgrade to TLS, or a server asks to switch to TLS in its response.
+ Secure communication begins with a server's response to switch to
+ TLS.
+
+9. Interoperability with IPP/1.0 Implementations
+
+ It is beyond the scope of this specification to mandate conformance
+ with previous versions. IPP/1.1 was deliberately designed, however,
+ to make supporting previous versions easy. It is worth noting that,
+ at the time of composing this specification (1999), we would expect
+ IPP/1.1 Printer implementations to:
+
+ understand any valid request in the format of IPP/1.0, or 1.1;
+
+ respond appropriately with a response containing the same
+ "version-number" parameter value used by the client in the
+ request.
+
+ And we would expect IPP/1.1 clients to:
+
+ understand any valid response in the format of IPP/1.0, or 1.1.
+
+9.1 The "version-number" Parameter
+
+ The following are rules regarding the "version-number" parameter (see
+ section 3.3):
+
+ 1. Clients MUST send requests containing a "version-number"
+ parameter with a '1.1' value and SHOULD try supplying alternate
+ version numbers if they receive a 'server-error-version-not-
+ supported' error return in a response.
+
+
+
+
+Herriot, et al. Standards Track [Page 25]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ 2. IPP objects MUST accept requests containing a "version-number"
+ parameter with a '1.1' value (or reject the request for reasons
+ other than 'server-error-version-not-supported').
+
+ 3. It is recommended that IPP objects accept any request with the
+ major version '1' (or reject the request for reasons other than
+ 'server-error-version-not-supported'). See [RFC2911]
+ "versions" sub-section.
+
+ 4. In any case, security MUST NOT be compromised when a client
+ supplies a lower "version-number" parameter in a request. For
+ example, if an IPP/1.1 conforming Printer object accepts
+ version '1.0' requests and is configured to enforce Digest
+ Authentication, it MUST do the same for a version '1.0'
+ request.
+
+9.2 Security and URL Schemes
+
+ The following are rules regarding security, the "version-number"
+ parameter, and the URL scheme supplied in target attributes and
+ responses:
+
+ 1. When a client supplies a request, the "printer-uri" or "job-
+ uri" target operation attribute MUST have the same scheme as
+ that indicated in one of the values of the "printer-uri-
+ supported" Printer attribute.
+
+ 2. When the server returns the "job-printer-uri" or "job-uri" Job
+ Description attributes, it SHOULD return the same scheme
+ ('ipp', 'https', 'http', etc.) that the client supplied in the
+ "printer-uri" or "job-uri" target operation attributes in the
+ Get-Job-Attributes or Get-Jobs request, rather than the scheme
+ used when the job was created. However, when a client requests
+ job attributes using the Get-Job-Attributes or Get-Jobs
+ operations, the jobs and job attributes that the server returns
+ depends on: (1) the security in effect when the job was
+ created, (2) the security in effect in the query request, and
+ (3) the security policy in force.
+
+ 3. It is recommended that if a server registers a non-secure ipp-
+ URL with a directory service (see [RFC2911] "Generic Directory
+ Schema" Appendix), then it also register an http-URL for
+ interoperability with IPP/1.0 clients (see section 9).
+
+ 4. In any case, security MUST NOT be compromised when a client
+ supplies an 'http' or other non-secure URL scheme in the target
+ "printer-uri" and "job-uri" operation attributes in a request.
+
+
+
+
+Herriot, et al. Standards Track [Page 26]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+10. References
+
+ [dpa] ISO/IEC 10175 Document Printing Application (DPA), June
+ 1996.
+
+ [iana] IANA Registry of Coded Character Sets:
+ ftp://ftp.isi.edu/in-notes/iana/assignments/character-
+ sets.
+
+ [IANA-CON] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [ipp-iig] Hastings, Tom, et al., "Internet Printing Protocol/1.1:
+ Implementer's Guide", Work in Progress.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA Internet
+ Text Messages", STD 11, RFC 822, August 1982.
+
+ [RFC1123] Braden, S., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October, 1989.
+
+ [RFC1179] McLaughlin, L. III, (editor), "Line Printer Daemon
+ Protocol", RFC 1179, August 1990.
+
+ [RFC2223] Postel, J. and J. Reynolds, "Instructions to RFC Authors",
+ RFC 2223, October 1997.
+
+ [RFC1738] Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform
+ Resource Locators (URL)", RFC 1738, December 1994.
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S. and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1766] Alvestrand, H., "Tags for the Identification of
+ Languages", RFC 1766, March 1995.
+
+ [RFC1808] Fielding, R., "Relative Uniform Resource Locators", RFC
+ 1808, June 1995.
+
+ [RFC1903] Case, J., McCloghrie, K., Rose, M. and S. Waldbusser,
+ "Textual Conventions for Version 2 of the Simple Network
+ Management Protocol (SNMPv2)", RFC 1903, January 1996.
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part Two: Media Types", RFC 2046,
+ November 1996.
+
+
+
+
+Herriot, et al. Standards Track [Page 27]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ [RFC2048] Freed, N., Klensin, J. and J. Postel, "Multipurpose
+ Internet Mail Extension (MIME) Part Four: Registration
+ Procedures", BCP 13, RFC 2048, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2184] Freed, N. and K. Moore, "MIME Parameter Value and Encoded
+ Word Extensions: Character Sets, Languages, and
+ Continuations", RFC 2184, August 1997.
+
+ [RFC2234] Crocker, D. and P. Overall, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol", RFC 2246.
+ January 1999.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Turner,
+ "Internet Printing Protocol/1.0: Encoding and Transport",
+ RFC 2565, April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
+ Masinter, L., Leach, P. and T. Berners-Lee, "Hypertext
+ Transfer Protocol - HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
+ Leach, P., Luotonen, A. and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access Authentication",
+ RFC 2617, June 1999.
+
+
+
+Herriot, et al. Standards Track [Page 28]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ [RFC2817] Khare, R. and S. Lawrence, "Upgrading to TLS Within
+ HTTP/1.1", RFC 2817, May 2000.
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P., Turner, R. and J.
+ Wenn, "Internet Printing Protocol/1.1: Encoding and
+ Transport", RFC 2910, September 2000.
+
+ [RFC2911] Hastings, T., Herriot, R., deBry, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.1: Model and
+ Semantics", RFC 2911, September 2000.
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version
+ 3.02), November 1996.
+
+11. Authors' Addresses
+
+ Robert Herriot, Editor
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: robert.herriot@pahv.xerox.com
+
+
+ Sylvan Butler
+ Hewlett-Packard
+ 11311 Chinden Blvd.
+ Boise, ID 83714
+
+ Phone: 208-396-6000
+ Fax: 208-396-3457
+ EMail: sbutler@boi.hp.com
+
+
+ Paul Moore
+ Peerless Systems Networking
+ 10900 NE 8th St #900
+ Bellevue, WA 98004
+
+ Phone: 425-462-5852
+ EMail: pmoore@peerless.com
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 29]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Randy Turner
+ 2Wire, Inc.
+ 694 Tasman Dr.
+ Milpitas, CA 95035
+
+ Phone: 408-546-1273
+
+
+ John Wenn
+ Xerox Corporation
+ 737 Hawaii St
+ El Segundo, CA 90245
+
+ Phone: 310-333-5764
+ Fax: 310-333-5514
+ EMail: jwenn@cp10.es.xerox.com
+
+
+ IPP Web Page: http://www.pwg.org/ipp/
+ IPP Mailing List: ipp@pwg.org
+
+ To subscribe to the ipp mailing list, send the following email:
+ 1) send it to majordomo@pwg.org
+ 2) leave the subject line blank
+ 3) put the following two lines in the message body:
+ subscribe ipp
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 30]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+12. Other Participants:
+
+ Chuck Adams - Tektronix Shivaun Albright - HP
+ Stefan Andersson - Axis Jeff Barnett - IBM
+ Ron Bergman - Hitachi Koki Imaging Dennis Carney - IBM
+ Systems
+ Keith Carter - IBM Angelo Caruso - Xerox
+ Rajesh Chawla - TR Computing Nancy Chen - Okidata
+ Solutions
+ Josh Cohen - Microsoft Jeff Copeland - QMS
+ Andy Davidson - Tektronix Roger deBry - IBM
+ Maulik Desai - Auco Mabry Dozier - QMS
+ Lee Farrell - Canon Information Satoshi Fujitami - Ricoh
+ Systems
+ Steve Gebert - IBM Sue Gleeson - Digital
+ Charles Gordon - Osicom Brian Grimshaw - Apple
+ Jerry Hadsell - IBM Richard Hart - Digital
+ Tom Hastings - Xerox Henrik Holst - I-data
+ Stephen Holmstead Zhi-Hong Huang - Zenographics
+ Scott Isaacson - Novell Babek Jahromi - Microsoft
+ Swen Johnson - Xerox David Kellerman - Northlake
+ Software
+ Robert Kline - TrueSpectra Charles Kong - Panasonic
+ Carl Kugler - IBM Dave Kuntz - Hewlett-Packard
+ Takami Kurono - Brother Rick Landau - Digital
+ Scott Lawrence - Agranot Systems Greg LeClair - Epson
+ Dwight Lewis - Lexmark Harry Lewis - IBM
+ Tony Liao - Vivid Image Roy Lomicka - Digital
+ Pete Loya - HP Ray Lutz - Cognisys
+ Mike MacKay - Novell, Inc. David Manchala - Xerox
+ Carl-Uno Manros - Xerox Jay Martin - Underscore
+ Stan McConnell - Xerox Larry Masinter - Xerox
+ Sandra Matts - Hewlett Packard Peter Michalek - Shinesoft
+ Ira McDonald - High North Inc. Mike Moldovan - G3 Nova
+ Tetsuya Morita - Ricoh Yuichi Niwa - Ricoh
+ Pat Nogay - IBM Ron Norton - Printronics
+ Hugo Parra, Novell Bob Pentecost - Hewlett-Packard
+ Patrick Powell - Astart Jeff Rackowitz - Intermec
+ Technologies
+ Eric Random - Peerless Rob Rhoads - Intel
+ Xavier Riley - Xerox Gary Roberts - Ricoh
+ David Roach - Unisys Stuart Rowley - Kyocera
+ Yuji Sasaki - Japan Computer Richard Schneider - Epson
+ Industry
+ Kris Schoff - HP Katsuaki Sekiguchi - Canon
+ Information Systems
+
+
+
+
+
+Herriot, et al. Standards Track [Page 31]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Bob Setterbo - Adobe Gail Songer - Peerless
+ Hideki Tanaka - Cannon Information Devon Taylor - Novell, Inc.
+ Systems
+ Mike Timperman - Lexmark Atsushi Uchino - Epson
+ Shigeru Ueda - Canon Bob Von Andel - Allegro Software
+ William Wagner - NetSilicon/DPI Jim Walker - DAZEL
+ Chris Wellens - Interworking Labs Trevor Wells - Hewlett Packard
+ Craig Whittle - Sharp Labs Rob Whittle - Novell, Inc.
+ Jasper Wong - Xionics Don Wright - Lexmark
+ Michael Wu - Heidelberg Digital Rick Yardumian - Xerox
+ Michael Yeung - Canon Information Lloyd Young - Lexmark
+ Systems
+ Atsushi Yuki - Kyocera Peter Zehler - Xerox
+ William Zhang - Canon Information Frank Zhao - Panasonic
+ Systems
+ Steve Zilles - Adobe Rob Zirnstein - Canon Information
+ Systems
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 32]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+13. Appendix A: Protocol Examples
+
+13.1 Print-Job Request
+
+ The following is an example of a Print-Job request with job-name,
+ copies, and sides specified. The "ipp-attribute-fidelity" attribute
+ is set to 'true' so that the print request will fail if the "copies"
+ or the "sides" attribute are not supported or their values are not
+ supported.
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0002 Print-Job operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- name
+ natural- attributes-natural-language
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x0015 value-length
+ ipp://forest/ printer pinetree value
+ pinetree
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0006 value-length
+ foobar foobar value
+ 0x22 boolean type value-tag
+ 0x0016 name-length
+ ipp-attribute- ipp-attribute-fidelity name
+ fidelity
+ 0x0001 value-length
+ 0x01 true value
+
+
+
+
+
+Herriot, et al. Standards Track [Page 33]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x44 keyword type value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0013 value-length
+ two-sided- two-sided-long-edge value
+ long-edge
+ 0x03 end-of-attributes end-of-attributes-tag
+ %!PS... <PostScript> data
+
+13.2 Print-Job Response (successful)
+
+ Here is an example of a successful Print-Job response to the previous
+ Print-Job request. The printer supported the "copies" and "sides"
+ attributes and their supplied values. The status code returned is
+ 'successful-ok'.
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0000 successful-ok status-code
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural- name
+ natural-language language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x000D value-length
+
+
+
+
+
+Herriot, et al. Standards Track [Page 34]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ successful-ok successful-ok value
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x45 uri type value-tag
+ 0x0007 name-length
+ job-uri job-uri name
+ 0x0019 value-length
+ ipp://forest/ job 123 on pinetree value
+ pinetree/123
+ 0x23 enum type value-tag
+ 0x0009 name-length
+ job-state job-state name
+ 0x0004 value-length
+ 0x0003 pending value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.3 Print-Job Response (failure)
+
+ Here is an example of an unsuccessful Print-Job response to the
+ previous Print-Job request. It fails because, in this case, the
+ printer does not support the "sides" attribute and because the value
+ '20' for the "copies" attribute is not supported. Therefore, no job
+ is created, and neither a "job-id" nor a "job-uri" operation
+ attribute is returned. The error code returned is 'client-error-
+ attributes-or-values-not-supported' (0x040B).
+
+ 0x0101 1.1 version-number
+ 0x040B client-error-attributes-or- status-code
+ values-not-supported
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 35]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status- status-message name
+ message
+ 0x002F value-length
+ client-error- value
+ attributes- values-not-supported
+ or-values- client-error-attributes-or-
+ not-supported
+ 0x05 start unsupported-attributes unsupported-attributes tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x10 unsupported (type) value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0000 value-length
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.4 Print-Job Response (success with attributes ignored)
+
+ Here is an example of a successful Print-Job response to a Print-Job
+ request like the previous Print-Job request, except that the value of
+ 'ipp-attribute-fidelity' is false. The print request succeeds, even
+ though, in this case, the printer supports neither the "sides"
+ attribute nor the value '20' for the "copies" attribute. Therefore, a
+ job is created, and both a "job-id" and a "job-uri" operation
+ attribute are returned. The unsupported attributes are also returned
+ in an Unsupported Attributes Group. The error code returned is
+ 'successful-ok-ignored-or-substituted-attributes' (0x0001).
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0001 successful-ok-ignored-or- status-code
+
+
+
+
+
+Herriot, et al. Standards Track [Page 36]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ substituted-attributes
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural- name
+ natural-language language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x002F value-length
+ successful-ok- successful-ok-ignored-or- value
+ ignored-or- substituted-attributes
+ substituted-
+ attributes
+ 0x05 start unsupported- unsupported-attributes
+ attributes tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000014 20 value
+ 0x10 unsupported (type) value-tag
+ 0x0005 name-length
+ sides sides name
+ 0x0000 value-length
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x45 uri type value-tag
+ 0x0007 name-length
+ job-uri job-uri name
+ 0x0019 value-length
+ ipp://forest/ job 123 on pinetree value
+ pinetree/123
+
+
+
+Herriot, et al. Standards Track [Page 37]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ 0x23 enum type value-tag
+ 0x0009 name-length
+ job-state job-state name
+ 0x0004 value-length
+ 0x0003 pending value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.5 Print-URI Request
+
+ The following is an example of Print-URI request with copies and
+ job-name parameters:
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0003 Print-URI operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x0015 value-length
+ ipp://forest/ printer pinetree value
+ pinetree
+ 0x45 uri type value-tag
+ 0x000C name-length
+ document-uri document-uri name
+ 0x0011 value-length
+ ftp://foo.com ftp://foo.com/foo value
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 38]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ /foo
+ 0x42 nameWithoutLanguage type value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0006 value-length
+ foobar foobar value
+ 0x02 start job-attributes job-attributes-tag
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ copies copies name
+ 0x0004 value-length
+ 0x00000001 1 value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.6 Create-Job Request
+
+ The following is an example of Create-Job request with no parameters
+ and no attributes:
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0005 Create-Job operation-id
+ 0x00000001 1 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x0015 value-length
+ ipp://forest/ printer pinetree value
+ pinetree
+
+
+
+
+
+Herriot, et al. Standards Track [Page 39]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ inetree
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.7 Get-Jobs Request
+
+ The following is an example of Get-Jobs request with parameters but
+ no attributes:
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x000A Get-Jobs operation-id
+ 0x00000123 0x123 request-id
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x0008 value-length
+ us-ascii US-ASCII value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x45 uri type value-tag
+ 0x000B name-length
+ printer-uri printer-uri name
+ 0x0015 value-length
+ ipp://forest/ printer pinetree value
+ pinetree
+ 0x21 integer type value-tag
+ 0x0005 name-length
+ limit limit name
+ 0x0004 value-length
+ 0x00000032 50 value
+ 0x44 keyword type value-tag
+ 0x0014 name-length
+ requested- requested-attributes name
+ attributes
+ 0x0006 value-length
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 40]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ job-id job-id value
+ 0x44 keyword type value-tag
+ 0x0000 additional value name-length
+ 0x0008 value-length
+ job-name job-name value
+ 0x44 keyword type value-tag
+ 0x0000 additional value name-length
+ 0x000F value-length
+ document-format document-format value
+ 0x03 end-of-attributes end-of-attributes-tag
+
+13.8 Get-Jobs Response
+
+ The following is an of Get-Jobs response from previous request with 3
+ jobs. The Printer returns no information about the second job
+ (because of security reasons):
+
+ Octets Symbolic Value Protocol field
+
+ 0x0101 1.1 version-number
+ 0x0000 successful-ok status-code
+ 0x00000123 0x123 request-id (echoed
+ back)
+ 0x01 start operation-attributes operation-attributes-tag
+ 0x47 charset type value-tag
+ 0x0012 name-length
+ attributes- attributes-charset name
+ charset
+ 0x000A value-length
+ ISO-8859-1 ISO-8859-1 value
+ 0x48 natural-language type value-tag
+ 0x001B name-length
+ attributes- attributes-natural-language name
+ natural-
+ language
+ 0x0005 value-length
+ en-us en-US value
+ 0x41 textWithoutLanguage type value-tag
+ 0x000E name-length
+ status-message status-message name
+ 0x000D value-length
+ successful-ok successful-ok value
+ 0x02 start job-attributes (1st job-attributes-tag
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 41]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Octets Symbolic Value Protocol field
+
+ object)
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 147 147 value
+ 0x36 nameWithLanguage value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x000C value-length
+ 0x0005 sub-value-length
+ fr-ca fr-CA value
+ 0x0003 sub-value-length
+ fou fou name
+ 0x02 start job-attributes (2nd job-attributes-tag
+ object)
+ 0x02 start job-attributes (3rd job-attributes-tag
+ object)
+ 0x21 integer type value-tag
+ 0x0006 name-length
+ job-id job-id name
+ 0x0004 value-length
+ 148 149 value
+ 0x36 nameWithLanguage value-tag
+ 0x0008 name-length
+ job-name job-name name
+ 0x0012 value-length
+ 0x0005 sub-value-length
+ de-CH de-CH value
+ 0x0009 sub-value-length
+ isch guet isch guet name
+ 0x03 end-of-attributes end-of-attributes-tag
+
+14. Appendix B: Registration of MIME Media Type Information for
+ "application/ipp"
+
+ This appendix contains the information that IANA requires for
+ registering a MIME media type. The information following this
+ paragraph will be forwarded to IANA to register application/ipp whose
+ contents are defined in Section 3 "Encoding of the Operation Layer"
+ in this document:
+
+ MIME type name: application
+
+ MIME subtype name: ipp
+
+
+
+
+Herriot, et al. Standards Track [Page 42]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ A Content-Type of "application/ipp" indicates an Internet Printing
+ Protocol message body (request or response). Currently there is one
+ version: IPP/1.1, whose syntax is described in Section 3 "Encoding of
+ the Operation Layer" of [RFC2910], and whose semantics are described
+ in [RFC2911].
+
+ Required parameters: none
+
+ Optional parameters: none
+
+ Encoding considerations:
+
+ IPP/1.1 protocol requests/responses MAY contain long lines and ALWAYS
+ contain binary data (for example attribute value lengths).
+
+ Security considerations:
+
+ IPP/1.1 protocol requests/responses do not introduce any security
+ risks not already inherent in the underlying transport protocols.
+ Protocol mixed-version interworking rules in [RFC2911] as well as
+ protocol encoding rules in [RFC2910] are complete and unambiguous.
+
+ Interoperability considerations:
+
+ IPP/1.1 requests (generated by clients) and responses (generated by
+ servers) MUST comply with all conformance requirements imposed by the
+ normative specifications [RFC2911] and [RFC2910]. Protocol encoding
+ rules specified in [RFC2910] are comprehensive, so that
+ interoperability between conforming implementations is guaranteed
+ (although support for specific optional features is not ensured).
+ Both the "charset" and "natural-language" of all IPP/1.1 attribute
+ values which are a LOCALIZED-STRING are explicit within IPP protocol
+ requests/responses (without recourse to any external information in
+ HTTP, SMTP, or other message transport headers).
+
+ Published specifications:
+
+ [RFC2911] Hastings, T., Herriot, R., deBry, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.1: Model and
+ Semantics", RFC 2911, September 2000.
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P., Turner, R. and J.
+ Wenn, "Internet Printing Protocol/1.1: Encoding and
+ Transport", RFC 2910, September 2000.
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 43]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ Applications which use this media type:
+
+ Internet Printing Protocol (IPP) print clients and print servers,
+ communicating using HTTP/1.1 (see [RFC2910]), SMTP/ESMTP, FTP, or
+ other transport protocol. Messages of type "application/ipp" are
+ self-contained and transport-independent, including "charset" and
+ "natural-language" context for any LOCALIZED-STRING value.
+
+ Person & email address to contact for further information:
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St. ESAE-231
+ El Segundo, CA
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+ or
+
+ Robert Herriot
+ Xerox Corporation
+ 3400 Hillview Ave., Bldg #1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: robert.herriot@pahv.xerox.com
+
+ Intended usage:
+
+ COMMON
+
+15. Appendix C: Changes from IPP/1.0
+
+ IPP/1.1 is identical to IPP/1.0 [RFC2565] with the follow changes:
+
+ 1. Attributes values that identify a printer or job object use a new
+ 'ipp' scheme. The 'http' and 'https' schemes are supported only
+ for backward compatibility. See section 5.
+
+ 2. Clients MUST support of Digest Authentication, IPP Printers SHOULD
+ support Digest Authentication. See Section 8.1.1
+
+ 3. TLS is recommended for channel security. In addition, SSL3 may be
+ supported for backward compatibility. See Section 8.1.2
+
+
+
+
+Herriot, et al. Standards Track [Page 44]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+ 4. It is recommended that IPP/1.1 objects accept any request with
+ major version number '1'. See section 9.1.
+
+ 5. IPP objects SHOULD return the URL scheme requested for "job-
+ printer-uri" and "job-uri" Job Attributes, rather than the URL
+ scheme used to create the job. See section 9.2.
+
+ 6. The IANA and Internationalization sections have been added. The
+ terms "private use" and "experimental" have been changed to
+ "vendor extension". The reserved allocations for attribute group
+ tags, attribute syntax tags, and out-of-band attribute values have
+ been clarified as to which are reserved to future IETF standards
+ track documents and which are reserved to vendor extension. Both
+ kinds of extensions use the type2 registration procedures as
+ defined in [RFC2911].
+
+ 7. Clarified that future "out-of-band" value definitions may use the
+ value field if additional information is needed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 45]
+
+RFC 2910 IPP/1.1: Encoding and Transport September 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Herriot, et al. Standards Track [Page 46]
+
diff --git a/standards/rfc2911.txt b/standards/rfc2911.txt
new file mode 100644
index 000000000..29c85a426
--- /dev/null
+++ b/standards/rfc2911.txt
@@ -0,0 +1,12547 @@
+
+
+
+
+
+
+Network Working Group T. Hastings, Editor
+Request for Comments: 2911 R. Herriot
+Obsoletes: 2566 Xerox Corporation
+Category: Standards Track R. deBry
+ Utah Valley State College
+ S. Isaacson
+ Novell, Inc.
+ P. Powell
+ Astart Technologies
+ September 2000
+
+
+ Internet Printing Protocol/1.1: Model and Semantics
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document is one of a set of documents, which together describe
+ all aspects of a new Internet Printing Protocol (IPP). IPP is an
+ application level protocol that can be used for distributed printing
+ using Internet tools and technologies. This document describes a
+ simplified model consisting of abstract objects, their attributes,
+ and their operations that is independent of encoding and transport.
+ The model consists of a Printer and a Job object. A Job optionally
+ supports multiple documents. IPP 1.1 semantics allow end-users and
+ operators to query printer capabilities, submit print jobs, inquire
+ about the status of print jobs and printers, cancel, hold, release,
+ and restart print jobs. IPP 1.1 semantics allow operators to pause,
+ resume, and purge (jobs from) Printer objects. This document also
+ addresses security, internationalization, and directory issues.
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 1]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics (this document)
+ Internet Printing Protocol/1.1: Encoding and Transport [RFC2910]
+ Internet Printing Protocol/1.1: Implementer's Guide [IPP-IIG]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0. A few OPTIONAL operator operations have
+ been added to IPP/1.1.
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specification documents, and gives background and rationale
+ for the IETF working group's major decisions.
+
+ The "Internet Printing Protocol/1.1: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1 [RFC2616]. It defines the
+ encoding rules for a new Internet MIME media type called
+ "application/ipp". This document also defines the rules for
+ transporting over HTTP a message body whose Content-Type is
+ "application/ipp". This document defines a new scheme named 'ipp'
+ for identifying IPP printers and jobs.
+
+ The "Internet Printing Protocol/1.1: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.1 and some of
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 2]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+Table of Contents
+
+ 1. Introduction 9
+ 1.1 Simplified Printing Model 10
+ 2. IPP Objects 12
+ 2.1 Printer Object 13
+ 2.2 Job Object 15
+ 2.3 Object Relationships 16
+ 2.4 Object Identity 17
+ 3. IPP Operations 20
+ 3.1 Common Semantics 21
+ 3.1.1 Required Parameters 21
+ 3.1.2 Operation IDs and Request IDs 22
+ 3.1.3 Attributes 22
+ 3.1.4 Character Set and Natural Language Operation Attribute 24
+ 3.1.4.1 Request Operation Attributes 25
+ 3.1.4.2 Response Operation Attributes 29
+ 3.1.5 Operation Targets 30
+ 3.1.6 Operation Response Status Codes and Status Messages 32
+ 3.1.6.1 "status-code" (type2 enum) 32
+ 3.1.6.2 "status-message" (text(255)) 33
+ 3.1.6.3 "detailed-status-message" (text(MAX)) 33
+ 3.1.6.4 "document-access-error" (text(MAX)) 34
+ 3.1.7 Unsupported Attributes 34
+ 3.1.8 Versions 36
+ 3.1.9 Job Creation Operations 38
+ 3.2 Printer Operations 41
+ 3.2.1 Print-Job Operation 41
+ 3.2.1.1 Print-Job Request 41
+ 3.2.1.2 Print-Job Response 46
+ 3.2.2 Print-URI Operation 48
+ 3.2.3 Validate-Job Operation 49
+ 3.2.4 Create-Job Operation 49
+ 3.2.5 Get-Printer-Attributes Operation 50
+ 3.2.5.1 Get-Printer-Attributes Request 51
+ 3.2.5.2 Get-Printer-Attributes Response 53
+ 3.2.6 Get-Jobs Operation 54
+ 3.2.6.1 Get-Jobs Request 54
+ 3.2.6.2 Get-Jobs Response 56
+ 3.2.7 Pause-Printer Operation 57
+ 3.2.7.1 Pause-Printer Request 59
+ 3.2.7.2 Pause-Printer Response 60
+ 3.2.8 Resume-Printer Operation 60
+ 3.2.9 Purge-Jobs Operation 61
+ 3.3 Job Operations 62
+ 3.3.1 Send-Document Operation 62
+ 3.3.1.1 Send-Document Request 64
+ 3.3.1.2 Send-Document Response 65
+
+
+
+Hastings, et al. Standards Track [Page 3]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 3.3.2 Send-URI Operation 66
+ 3.3.3 Cancel-Job Operation 66
+ 3.3.3.1 Cancel-Job Request 67
+ 3.3.3.2 Cancel-Job Response 68
+ 3.3.4 Get-Job-Attributes Operation 69
+ 3.3.4.1 Get-Job-Attributes Request 69
+ 3.3.4.2 Get-Job-Attributes Response 70
+ 3.3.5 Hold-Job Operation 71
+ 3.3.5.1 Hold-Job Request 72
+ 3.3.5.2 Hold-Job Response 73
+ 3.3.6 Release-Job Operation 74
+ 3.3.7 Restart-Job Operation 75
+ 3.3.7.1 Restart-Job Request 76
+ 3.3.7.2 Restart-Job Response 78
+ 4. Object Attributes 78
+ 4.1 Attribute Syntaxes 78
+ 4.1.1 'text' 79
+ 4.1.1.1 'textWithoutLanguage' 80
+ 4.1.1.2 'textWithLanguage' 80
+ 4.1.2 'name' 81
+ 4.1.2.1 'nameWithoutLanguage' 82
+ 4.1.2.2 'nameWithLanguage' 82
+ 4.1.2.3 Matching 'name' attribute values 83
+ 4.1.3 'keyword' 84
+ 4.1.4 'enum' 85
+ 4.1.5 'uri' 85
+ 4.1.6 'uriScheme' 86
+ 4.1.7 'charset' 86
+ 4.1.8 'naturalLanguage' 87
+ 4.1.9 'mimeMediaType' 87
+ 4.1.9.1 Application/octet-stream -- Auto-Sensing 88
+ the document format
+ 4.1.10 'octetString' 89
+ 4.1.11 'boolean' 89
+ 4.1.12 'integer' 89
+ 4.1.13 'rangeOfInteger' 90
+ 4.1.14 'dateTime' 90
+ 4.1.15 'resolution' 90
+ 4.1.16 '1setOf X' 90
+ 4.2 Job Template Attributes 91
+ 4.2.1 job-priority (integer(1:100)) 94
+ 4.2.2 job-hold-until (type3 keyword | name (MAX)) 95
+ 4.2.3 job-sheets (type3 keyword | name(MAX)) 96
+ 4.2.4 multiple-document-handling (type2 keyword) 96
+ 4.2.5 copies (integer(1:MAX)) 98
+ 4.2.6 finishings (1setOf type2 enum) 98
+ 4.2.7 page-ranges (1setOf rangeOfInteger (1:MAX)) 101
+ 4.2.8 sides (type2 keyword) 102
+
+
+
+Hastings, et al. Standards Track [Page 4]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 4.2.9 number-up (integer(1:MAX)) 102
+ 4.2.10 orientation-requested (type2 enum) 103
+ 4.2.11 media (type3 keyword | name(MAX)) 104
+ 4.2.12 printer-resolution (resolution) 105
+ 4.2.13 print-quality (type2 enum) 105
+ 4.3 Job Description Attributes 106
+ 4.3.1 job-uri (uri) 107
+ 4.3.2 job-id (integer(1:MAX)) 108
+ 4.3.3 job-printer-uri (uri) 108
+ 4.3.4 job-more-info (uri) 108
+ 4.3.5 job-name (name(MAX)) 108
+ 4.3.6 job-originating-user-name (name(MAX)) 109
+ 4.3.7 job-state (type1 enum) 109
+ 4.3.7.1 Forwarding Servers 112
+ 4.3.7.2 Partitioning of Job States 112
+ 4.3.8 job-state-reasons (1setOf type2 keyword) 113
+ 4.3.9 job-state-message (text(MAX)) 118
+ 4.3.10 job-detailed-status-messages (1setOf text(MAX)) 118
+ 4.3.11 job-document-access-errors (1setOf text(MAX)) 118
+ 4.3.12 number-of-documents (integer(0:MAX)) 119
+ 4.3.13 output-device-assigned (name(127)) 119
+ 4.3.14 Event Time Job Description Attributes 119
+ 4.3.14.1 time-at-creation (integer(MIN:MAX)) 120
+ 4.3.14.2 time-at-processing (integer(MIN:MAX)) 120
+ 4.3.14.3 time-at-completed (integer(MIN:MAX)) 120
+ 4.3.14.4 job-printer-up-time (integer(1:MAX)) 120
+ 4.3.14.5 date-time-at-creation (dateTime) 121
+ 4.3.14.6 date-time-at-processing (dateTime) 121
+ 4.3.14.7 date-time-at-completed (dateTime) 121
+ 4.3.15 number-of-intervening-jobs (integer(0:MAX)) 121
+ 4.3.16 job-message-from-operator (text(127)) 121
+ 4.3.17 Job Size Attributes 121
+ 4.3.17.1 job-k-octets (integer(0:MAX)) 122
+ 4.3.17.2 job-impressions (integer(0:MAX)) 122
+ 4.3.17.3 job-media-sheets (integer(0:MAX)) 123
+ 4.3.18 Job Progress Attributes 123
+ 4.3.18.1 job-k-octets-processed (integer(0:MAX)) 123
+ 4.3.18.2 job-impressions-completed (integer(0:MAX)) 123
+ 4.3.18.3 job-media-sheets-completed (integer(0:MAX)) 124
+ 4.3.19 attributes-charset (charset) 124
+ 4.3.20 attributes-natural-language (naturalLanguage) 124
+ 4.4 Printer Description Attributes 124
+ 4.4.1 printer-uri-supported (1setOf uri) 126
+ 4.4.2 uri-authentication-supported (1setOf type2 keyword) 127
+ 4.4.3 uri-security-supported (1setOf type2 keyword) 128
+ 4.4.4 printer-name (name(127)) 129
+ 4.4.5 printer-location (text(127)) 129
+ 4.4.6 printer-info (text(127)) 130
+
+
+
+Hastings, et al. Standards Track [Page 5]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 4.4.7 printer-more-info (uri) 130
+ 4.4.8 printer-driver-installer (uri) 130
+ 4.4.9 printer-make-and-model (text(127)) 130
+ 4.4.10 printer-more-info-manufacturer (uri) 130
+ 4.4.11 printer-state (type1 enum) 131
+ 4.4.12 printer-state-reasons (1setOf type2 keyword) 131
+ 4.4.13 printer-state-message (text(MAX)) 134
+ 4.4.14 ipp-versions-supported (1setOf type2 keyword) 134
+ 4.4.15 operations-supported (1setOf type2 enum) 135
+ 4.4.16 multiple-document-jobs-supported (boolean) 136
+ 4.4.17 charset-configured (charset) 136
+ 4.4.18 charset-supported (1setOf charset) 137
+ 4.4.19 natural-language-configured (naturalLanguage) 137
+ 4.4.20 generated-natural-language-supported
+ (1setOf naturalLanguage) 137
+ 4.4.21 document-format-default (mimeMediaType) 138
+ 4.4.22 document-format-supported (1setOf mimeMediaType) 138
+ 4.4.23 printer-is-accepting-jobs (boolean) 138
+ 4.4.24 queued-job-count (integer(0:MAX)) 138
+ 4.4.25 printer-message-from-operator (text(127)) 139
+ 4.4.26 color-supported (boolean) 139
+ 4.4.27 reference-uri-schemes-supported (1setOf uriScheme) 139
+ 4.4.28 pdl-override-supported (type2 keyword) 139
+ 4.4.29 printer-up-time (integer(1:MAX)) 140
+ 4.4.30 printer-current-time (dateTime) 140
+ 4.4.31 multiple-operation-time-out (integer(1:MAX)) 141
+ 4.4.32 compression-supported (1setOf type3 keyword) 141
+ 4.4.33 job-k-octets-supported (rangeOfInteger(0:MAX)) 142
+ 4.4.34 job-impressions-supported (rangeOfInteger(0:MAX)) 142
+ 4.4.35 job-media-sheets-supported (rangeOfInteger(0:MAX)) 142
+ 4.4.36 pages-per-minute (integer(0:MAX)) 142
+ 4.4.37 pages-per-minute-color (integer(0:MAX)) 142
+ 5. Conformance 143
+ 5.1 Client Conformance Requirements 143
+ 5.2 IPP Object Conformance Requirements 145
+ 5.2.1 Objects 145
+ 5.2.2 Operations 145
+ 5.2.3 IPP Object Attributes 146
+ 5.2.4 Versions 146
+ 5.2.5 Extensions 147
+ 5.2.6 Attribute Syntaxes 147
+ 5.2.7 Security 148
+ 5.3 Charset and Natural Language Requirements 148
+ 6. IANA Considerations 148
+ 6.1 Typed 'keyword' and 'enum' Extensions 149
+ 6.2 Attribute Extensibility 151
+ 6.3 Attribute Syntax Extensibility 152
+ 6.4 Operation Extensibility 152
+
+
+
+Hastings, et al. Standards Track [Page 6]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 6.5 Attribute Group Extensibility 153
+ 6.6 Status Code Extensibility 153
+ 6.7 Out-of-band Attribute Value Extensibility 154
+ 6.8 Registration of MIME types/sub-types for document-formats 154
+ 6.9 Registration of charsets for use in 'charset'
+ attribute values 154
+ 7. Internationalization Considerations 154
+ 8. Security Considerations 158
+ 8.1 Security Scenarios 159
+ 8.1.1 Client and Server in the Same Security Domain 159
+ 8.1.2 Client and Server in Different Security Domains 159
+ 8.1.3 Print by Reference 160
+ 8.2 URIs in Operation, Job, and Printer attributes 160
+ 8.3 URIs for each authentication mechanisms 160
+ 8.4 Restricted Queries 161
+ 8.5 Operations performed by operators and system
+ administrators 161
+ 8.6 Queries on jobs submitted using non-IPP protocols 162
+ 9. References 162
+ 10. Authors' Addresses 166
+ 11. Formats for IPP Registration Proposals 168
+ 11.1 Type2 keyword attribute values registration 169
+ 11.2 Type3 keyword attribute values registration 169
+ 11.3 Type2 enum attribute values registration 169
+ 11.4 Type3 enum attribute values registration 170
+ 11.5 Attribute registration 170
+ 11.6 Attribute Syntax registration 171
+ 11.7 Operation registration 171
+ 11.8 Attribute Group registration 171
+ 11.9 Status code registration 172
+ 11.10 Out-of-band Attribute Value registration 172
+ 12. APPENDIX A: Terminology 173
+ 12.1 Conformance Terminology 173
+ 12.1.1 NEED NOT 173
+ 12.2 Model Terminology 173
+ 12.2.1 Keyword 173
+ 12.2.2 Attributes 173
+ 12.2.2.1 Attribute Name 173
+ 12.2.2.2 Attribute Group Name 174
+ 12.2.2.3 Attribute Value 174
+ 12.2.2.4 Attribute Syntax 174
+ 12.2.3 Supports 174
+ 12.2.4 print-stream page 176
+ 12.2.5 impression 177
+ 13. APPENDIX B: Status Codes and Suggested Status Code Messages 177
+ 13.1 Status Codes 178
+ 13.1.1 Informational 178
+ 13.1.2 Successful Status Codes 178
+
+
+
+Hastings, et al. Standards Track [Page 7]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 13.1.2.1 successful-ok (0x0000) 178
+ 13.1.2.2 successful-ok-ignored-or-substituted-attributes
+ (0x0001) 179
+ 13.1.2.3 successful-ok-conflicting-attributes (0x0002) 179
+ 13.1.3 Redirection Status Codes 179
+ 13.1.4 Client Error Status Codes 179
+ 13.1.4.1 client-error-bad-request (0x0400) 180
+ 13.1.4.2 client-error-forbidden (0x0401) 180
+ 13.1.4.3 client-error-not-authenticated (0x0402) 180
+ 13.1.4.4 client-error-not-authorized (0x0403) 180
+ 13.1.4.5 client-error-not-possible (0x0404) 180
+ 13.1.4.6 client-error-timeout (0x0405) 181
+ 13.1.4.7 client-error-not-found (0x0406) 181
+ 13.1.4.8 client-error-gone (0x0407) 181
+ 13.1.4.9 client-error-request-entity-too-large (0x0408) 182
+ 13.1.4.10 client-error-request-value-too-long (0x0409) 182
+ 13.1.4.11 client-error-document-format-not-supported (0x040A) 182
+ 13.1.4.12 client-error-attributes-or-values-not-supported
+ (0x040B) 183
+ 13.1.4.13 client-error-uri-scheme-not-supported (0x040C) 183
+ 13.1.4.14 client-error-charset-not-supported (0x040D) 183
+ 13.1.4.15 client-error-conflicting-attributes (0x040E) 183
+ 13.1.4.16 client-error-compression-not-supported (0x040F) 184
+ 13.1.4.17 client-error-compression-error (0x0410) 184
+ 13.1.4.18 client-error-document-format-error (0x0411) 184
+ 13.1.4.19 client-error-document-access-error (0x0412) 184
+ 13.1.5 Server Error Status Codes 185
+ 13.1.5.1 server-error-internal-error (0x0500) 185
+ 13.1.5.2 server-error-operation-not-supported (0x0501) 185
+ 13.1.5.3 server-error-service-unavailable (0x0502) 185
+ 13.1.5.4 server-error-version-not-supported (0x0503) 185
+ 13.1.5.5 server-error-device-error (0x0504) 186
+ 13.1.5.6 server-error-temporary-error (0x0505) 186
+ 13.1.5.7 server-error-not-accepting-jobs (0x0506) 187
+ 13.1.5.8 server-error-busy (0x0507) 187
+ 13.1.5.9 server-error-job-canceled (0x0508) 187
+ 13.1.5.10 server-error-multiple-document-jobs-not-supported
+ (0x0509) 187
+ 13.2 Status Codes for IPP Operations 187
+ 14. APPENDIX C: "media" keyword values 190
+ 15. APPENDIX D: Processing IPP Attributes 208
+ 15.1 Fidelity 209
+ 15.2 Page Description Language (PDL) Override 210
+ 15.3 Using Job Template Attributes During Document Processing 212
+ 16. APPENDIX E: Generic Directory Schema 214
+ 17. APPENDIX F: Differences between the IPP/1.0 and IPP/1.1
+ "Model and Semantics" Documents 215
+ 18. Full Copyright Statement 224
+
+
+
+Hastings, et al. Standards Track [Page 8]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+1. Introduction
+
+ The Internet Printing Protocol (IPP) is an application level protocol
+ that can be used for distributed printing using Internet tools and
+ technologies. IPP version 1.1 (IPP/1.1) focuses primarily on end
+ user functionality with a few administrative operations included.
+ This document is just one of a suite of documents that fully define
+ IPP. The full set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the Internet
+ Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics (this document)
+ Internet Printing Protocol/1.1: Encoding and Transport [RFC2910]
+ Internet Printing Protocol/1.1: Implementer's Guide [IPP-IIG]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ Anyone reading these documents for the first time is strongly
+ encouraged to read the IPP documents in the above order.
+
+ This document is laid out as follows:
+
+ - The rest of Section 1 is an introduction to the IPP simplified
+ model for distributed printing.
+ - Section 2 introduces the object types covered in the model with
+ their basic behaviors, attributes, and interactions.
+ - Section 3 defines the operations included in IPP/1.1. IPP
+ operations are synchronous, therefore, for each operation, there is
+ a both request and a response.
+ - Section 4 defines the attributes (and their syntaxes) that are used
+ in the model.
+ - Sections 5 - 6 summarizes the implementation conformance
+ requirements for objects that support the protocol and IANA
+ considerations, respectively.
+ - Sections 7 - 11 cover the Internationalization and Security
+ considerations as well as References, Author contact information,
+ and Formats for Registration Proposals.
+ - Sections 12 - 14 are appendices that cover Terminology, Status
+ Codes and Messages, and "media" keyword values.
+
+ Note: This document uses terms such as "attributes", "keywords",
+ and "support". These terms have special meaning and are defined
+ in the model terminology section 12.2. Capitalized terms, such
+ as MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, MAY, NEED NOT,
+ and OPTIONAL, have special meaning relating to conformance.
+ These terms are defined in section 12.1 on conformance
+ terminology, most of which is taken from RFC 2119 [RFC2119].
+
+
+
+
+Hastings, et al. Standards Track [Page 9]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - Section 15 is an appendix that helps to clarify the effects of
+ interactions between related attributes and their values.
+ - Section 16 is an appendix that enumerates the subset of Printer
+ attributes that form a generic directory schema. These attributes
+ are useful when registering a Printer so that a client can find the
+ Printer not just by name, but by filtered searches as well.
+ - Section 17 is an appendix summarizing the additions and changes
+ from the IPP/1.0 "Model and Semantics" document [RFC2566] to make
+ this IPP/1.1 document.
+ - Section 18 is the full copyright notice.
+
+1.1 Simplified Printing Model
+
+ In order to achieve its goal of realizing a workable printing
+ protocol for the Internet, the Internet Printing Protocol (IPP) is
+ based on a simplified printing model that abstracts the many
+ components of real world printing solutions. The Internet is a
+ distributed computing environment where requesters of print services
+ (clients, applications, printer drivers, etc.) cooperate and interact
+ with print service providers. This model and semantics document
+ describes a simple, abstract model for IPP even though the underlying
+ configurations may be complex "n-tier" client/server systems. An
+ important simplifying step in the IPP model is to expose only the key
+ objects and interfaces required for printing. The model described in
+ this model document does not include features, interfaces, and
+ relationships that are beyond the scope of the first version of IPP
+ (IPP/1.1). IPP/1.1 incorporates many of the relevant ideas and
+ lessons learned from other specification and development efforts
+ [HTPP] [ISO10175] [LDPA] [P1387.4] [PSIS] [RFC1179] [SWP]. IPP is
+ heavily influenced by the printing model introduced in the Document
+ Printing Application (DPA) [ISO10175] standard. Although DPA
+ specifies both end user and administrative features, IPP version 1.1
+ (IPP/1.1) focuses primarily on end user functionality with a few
+ additional OPTIONAL operator operations.
+
+ The IPP/1.1 model encapsulates the important components of
+ distributed printing into two object types:
+
+ - Printer (Section 2.1)
+ - Job (Section 2.2)
+
+ Each object type has an associated set of operations (see section 3)
+ and attributes (see section 4).
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 10]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ It is important, however, to understand that in real system
+ implementations (which lie underneath the abstracted IPP/1.1 model),
+ there are other components of a print service which are not
+ explicitly defined in the IPP/1.1 model. The following figure
+ illustrates where IPP/1.1 fits with respect to these other
+ components.
+
+ +--------------+
+ | Application |
+ o +. . . . . . . |
+ \|/ | Spooler |
+ / \ +. . . . . . . | +---------+
+ End-User | Print Driver |---| File |
+ +-----------+ +-----+ +------+-------+ +----+----+
+ | Browser | | GUI | | |
+ +-----+-----+ +--+--+ | |
+ | | | |
+ | +---+------------+---+ |
+ N D S | | IPP Client |------------+
+ O I E | +---------+----------+
+ T R C | |
+ I E U |
+ F C R -------------- Transport ------------------
+ I T I
+ C O T | --+
+ A R Y +--------+--------+ |
+ T Y | IPP Server | |
+ I +--------+--------+ |
+ O | |
+ N +-----------------+ | IPP Printer
+ | Print Service | |
+ +-----------------+ |
+ | --+
+ +-----------------+
+ | Output Device(s)|
+ +-----------------+
+
+ An IPP Printer object encapsulates the functions normally associated
+ with physical output devices along with the spooling, scheduling and
+ multiple device management functions often associated with a print
+ server. Printer objects are optionally registered as entries in a
+ directory where end users find and select them based on some sort of
+ filtered and context based searching mechanism (see section 16). The
+ directory is used to store relatively static information about the
+ Printer, allowing end users to search for and find Printers that
+ match their search criteria, for example: name, context, printer
+ capabilities, etc. The more dynamic information, such as state,
+ currently loaded and ready media, number of jobs at the Printer,
+
+
+
+Hastings, et al. Standards Track [Page 11]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ errors, warnings, and so forth, is directly associated with the
+ Printer object itself rather than with the entry in the directory
+ which only represents the Printer object.
+
+ IPP clients implement the IPP protocol on the client side and give
+ end users (or programs running on behalf of end users) the ability to
+ query Printer objects and submit and manage print jobs. An IPP
+ server is just that part of the Printer object that implements the
+ server-side protocol. The rest of the Printer object implements (or
+ gateways into) the application semantics of the print service itself.
+ The Printer objects may be embedded in an output device or may be
+ implemented on a host on the network that communicates with an output
+ device.
+
+ When a job is submitted to the Printer object and the Printer object
+ validates the attributes in the submission request, the Printer
+ object creates a new Job object. The end user then interacts with
+ this new Job object to query its status and monitor the progress of
+ the job. An end user can also cancel their print jobs by using the
+ Job object's Cancel-Job operation. An end-user can also hold,
+ release, and restart their print jobs using the Job object's OPTIONAL
+ Hold-Job, Release-Job, and Restart-Job operations, if implemented.
+
+ A privileged operator or administrator of a Printer object can
+ cancel, hold, release, and restart any user's job using the REQUIRED
+ Cancel-Job and the OPTIONAL Hold-Job, Release-Job, and Restart-Job
+ operations. In additional privileged operator or administrator of a
+ Printer object can pause, resume, or purge (jobs from) a Printer
+ object using the OPTIONAL Pause-Printer, Resume-Printer, and Purge-
+ Jobs operations, if implemented.
+
+ The notification service is out of scope for this IPP/1.1 document,
+ but using such a notification service, the end user is able to
+ register for and receive Printer specific and Job specific events.
+ An end user can query the status of Printer objects and can follow
+ the progress of Job objects by polling using the Get-Printer-
+ Attributes, Get-Jobs, and Get-Job-Attributes operations.
+
+2. IPP Objects
+
+ The IPP/1.1 model introduces objects of type Printer and Job. Each
+ type of object models relevant aspects of a real-world entity such as
+ a real printer or real print job. Each object type is defined as a
+ set of possible attributes that may be supported by instances of that
+ object type. For each object (instance), the actual set of supported
+ attributes and values describe a specific implementation. The
+ object's attributes and values describe its state, capabilities,
+ realizable features, job processing functions, and default behaviors
+
+
+
+Hastings, et al. Standards Track [Page 12]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ and characteristics. For example, the Printer object type is defined
+ as a set of attributes that each Printer object potentially supports.
+ In the same manner, the Job object type is defined as a set of
+ attributes that are potentially supported by each Job object.
+
+ Each attribute included in the set of attributes defining an object
+ type is labeled as:
+
+ - "REQUIRED": each object MUST support the attribute.
+ - "RECOMMENDED": each object SHOULD support the attribute.
+ - "OPTIONAL": each object MAY support the attribute.
+
+ Some definitions of attribute values indicate that an object MUST or
+ SHOULD support the value; otherwise, support of the value is
+ OPTIONAL.
+
+ However, if an implementation supports an attribute, it MUST support
+ at least one of the possible values for that attribute.
+
+2.1 Printer Object
+
+ The major component of the IPP/1.1 model is the Printer object. A
+ Printer object implements the server-side of the IPP/1.1 protocol.
+ Using the protocol, end users may query the attributes of the Printer
+ object and submit print jobs to the Printer object. The actual
+ implementation components behind the Printer abstraction may take on
+ different forms and different configurations. However, the model
+ abstraction allows the details of the configuration of real
+ components to remain opaque to the end user. Section 3 describes
+ each of the Printer operations in detail.
+
+ The capabilities and state of a Printer object are described by its
+ attributes. Printer attributes are divided into two groups:
+
+ - "job-template" attributes: These attributes describe supported job
+ processing capabilities and defaults for the Printer object. (See
+ section 4.2)
+ - "printer-description" attributes: These attributes describe the
+ Printer object's identification, state, location, references to
+ other sources of information about the Printer object, etc. (see
+ section 4.4)
+
+ Since a Printer object is an abstraction of a generic document output
+ device and print service provider, a Printer object could be used to
+ represent any real or virtual device with semantics consistent with
+ the Printer object, such as a fax device, an imager, or even a CD
+ writer.
+
+
+
+
+Hastings, et al. Standards Track [Page 13]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Some examples of configurations supporting a Printer object include:
+
+ 1) An output device with no spooling capabilities
+ 2) An output device with a built-in spooler
+ 3) A print server supporting IPP with one or more associated
+ output devices
+ 3a) The associated output devices may or may not be capable of
+ spooling jobs
+ 3b) The associated output devices may or may not support IPP
+
+ The following figures show some examples of how Printer objects can
+ be realized on top of various distributed printing configurations.
+ The embedded case below represents configurations 1 and 2. The hosted
+ and fan-out figures below represent configurations 3a and 3b.
+
+ In this document the term "client" refers to a software entity that
+ sends IPP operation requests to an IPP Printer object and accepts IPP
+ operation responses. A client MAY be:
+
+ 1. contained within software controlled by an end user, e.g.
+ activated by the "Print" menu item in an application or
+
+ 2. the print server component that sends IPP requests to either an
+ output device or another "downstream" print server.
+
+ The term "IPP Printer" is a network entity that accepts IPP operation
+ requests and returns IPP operation responses. As such, an IPP object
+ MAY be:
+
+ 1. an (embedded) device component that accepts IPP requests and
+ controls the device or
+
+ 2. a component of a print server that accepts IPP requests (where
+ the print server controls one or more networked devices using
+ IPP or other protocols).
+
+ Legend:
+
+ ##### indicates a Printer object which is
+ either embedded in an output device or is
+ hosted in a server. The Printer object
+ might or might not be capable of queuing/spooling.
+
+ any indicates any network protocol or direct
+ connect, including IPP
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 14]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ embedded printer:
+ output device
+ +---------------+
+ O +--------+ | ########### |
+ /|\ | client |------------IPP------------># Printer # |
+ / \ +--------+ | # Object # |
+ | ########### |
+ +---------------+
+
+ hosted printer:
+ +---------------+
+ O +--------+ ########### | |
+ /|\ | client |--IPP--># Printer #-any->| output device |
+ / \ +--------+ # Object # | |
+ ########### +---------------+
+
+
+ +---------------+
+ fan out: | |
+ +-->| output device |
+ any/ | |
+ O +--------+ ########### / +---------------+
+ /|\ | client |-IPP-># Printer #--*
+ / \ +--------+ # Object # \ +---------------+
+ ########### any\ | |
+ +-->| output device |
+ | |
+ +---------------+
+
+2.2 Job Object
+
+ A Job object is used to model a print job. A Job object contains
+ documents. The information required to create a Job object is sent
+ in a create request from the end user via an IPP Client to the
+ Printer object. The Printer object validates the create request, and
+ if the Printer object accepts the request, the Printer object creates
+ the new Job object. Section 3 describes each of the Job operations
+ in detail.
+
+ The characteristics and state of a Job object are described by its
+ attributes. Job attributes are grouped into two groups as follows:
+
+ - "job-template" attributes: These attributes can be supplied by
+ the client or end user and include job processing instructions
+ which are intended to override any Printer object defaults
+ and/or instructions embedded within the document data. (See
+ section 4.2)
+
+
+
+
+Hastings, et al. Standards Track [Page 15]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - "job-description" attributes: These attributes describe the Job
+ object's identification, state, size, etc. The client supplies
+ some of these attributes, and the Printer object generates
+ others. (See section 4.3)
+
+ An implementation MUST support at least one document per Job object.
+ An implementation MAY support multiple documents per Job object. A
+ document is either:
+
+ - a stream of document data in a format supported by the Printer
+ object (typically a Page Description Language - PDL), or
+ - a reference to such a stream of document data
+
+ In IPP/1.1, a document is not modeled as an IPP object, therefore it
+ has no object identifier or associated attributes. All job
+ processing instructions are modeled as Job object attributes. These
+ attributes are called Job Template attributes and they apply equally
+ to all documents within a Job object.
+
+2.3 Object Relationships
+
+ IPP objects have relationships that are maintained persistently along
+ with the persistent storage of the object attributes.
+
+ A Printer object can represent either one or more physical output
+ devices or a logical device which "processes" jobs but never actually
+ uses a physical output device to put marks on paper. Examples of
+ logical devices include a Web page publisher or a gateway into an
+ online document archive or repository. A Printer object contains
+ zero or more Job objects.
+
+ A Job object is contained by exactly one Printer object, however the
+ identical document data associated with a Job object could be sent to
+ either the same or a different Printer object. In this case, a
+ second Job object would be created which would be almost identical to
+ the first Job object, however it would have new (different) Job
+ object identifiers (see section 2.4).
+
+ A Job object is either empty (before any documents have been added)
+ or contains one or more documents. If the contained document is a
+ stream of document data, that stream can be contained in only one
+ document. However, there can be identical copies of the stream in
+ other documents in the same or different Job objects. If the
+ contained document is just a reference to a stream of document data,
+ other documents (in the same or different Job object(s)) may contain
+ the same reference.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 16]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+2.4 Object Identity
+
+ All Printer and Job objects are identified by a Uniform Resource
+ Identifier (URI) [RFC2396] so that they can be persistently and
+ unambiguously referenced. Since every URL is a specialized form of a
+ URI, even though the more generic term URI is used throughout the
+ rest of this document, its usage is intended to cover the more
+ specific notion of URL as well.
+
+ An administrator configures Printer objects to either support or not
+ support authentication and/or message privacy using Transport Layer
+ Security (TLS) [RFC2246] (the mechanism for security configuration is
+ outside the scope of this IPP/1.1 document). In some situations,
+ both types of connections (both authenticated and unauthenticated)
+ can be established using a single communication channel that has some
+ sort of negotiation mechanism. In other situations, multiple
+ communication channels are used, one for each type of security
+ configuration. Section 8 provides a full description of all security
+ considerations and configurations.
+
+ If a Printer object supports more than one communication channel,
+ some or all of those channels might support and/or require different
+ security mechanisms. In such cases, an administrator could expose
+ the simultaneous support for these multiple communication channels as
+ multiple URIs for a single Printer object where each URI represents
+ one of the communication channels to the Printer object. To support
+ this flexibility, the IPP Printer object type defines a multi-valued
+ identification attribute called the "printer-uri-supported"
+ attribute. It MUST contain at least one URI. It MAY contain more
+ than one URI. That is, every Printer object will have at least one
+ URI that identifies at least one communication channel to the Printer
+ object, but it may have more than one URI where each URI identifies a
+ different communication channel to the Printer object. The
+ "printer-uri-supported" attribute has two companion attributes, the
+ "uri-security-supported" attribute and the "uri-authentication-
+ supported". Both have the same cardinality as "printer-uri-
+ supported". The purpose of the "uri-security-supported" attribute is
+ to indicate the security mechanisms (if any) used for each URI listed
+ in "printer-uri-supported". The purpose of the "uri-authentication-
+ supported" attribute is to indicate the authentication mechanisms (if
+ any) used for each URI listed in "printer-uri-supported". These
+ three attributes are fully described in sections 4.4.1, 4.4.2, and
+ 4.4.3.
+
+ When a job is submitted to the Printer object via a create request,
+ the client supplies only a single Printer object URI. The client
+ supplied Printer object URI MUST be one of the values in the
+ "printer-uri-supported" Printer attribute.
+
+
+
+Hastings, et al. Standards Track [Page 17]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ IPP/1.1 does not specify how the client obtains the client supplied
+ URI, but it is RECOMMENDED that a Printer object be registered as an
+ entry in a directory service. End-users and programs can then
+ interrogate the directory searching for Printers. Section 16 defines
+ a generic schema for Printer object entries in the directory service
+ and describes how the entry acts as a bridge to the actual IPP
+ Printer object. The entry in the directory that represents the IPP
+ Printer object includes the possibly many URIs for that Printer
+ object as values in one its attributes.
+
+ When a client submits a create request to the Printer object, the
+ Printer object validates the request and creates a new Job object.
+ The Printer object assigns the new Job object a URI which is stored
+ in the "job-uri" Job attribute. This URI is then used by clients as
+ the target for subsequent Job operations. The Printer object
+ generates a Job URI based on its configured security policy and the
+ URI used by the client in the create request.
+
+ For example, consider a Printer object that supports both a
+ communication channel secured by the use of SSL3 (using HTTP over
+ SSL3 with an "https" schemed URI) and another open communication
+ channel that is not secured with SSL3 (using a simple "http" schemed
+ URI). If a client were to submit a job using the secure URI, the
+ Printer object would assign the new Job object a secure URI as well.
+ If a client were to submit a job using the open-channel URI, the
+ Printer would assign the new Job object an open-channel URI.
+
+ In addition, the Printer object also populates the Job object's
+ "job-printer-uri" attribute. This is a reference back to the Printer
+ object that created the Job object. If a client only has access to a
+ Job object's "job-uri" identifier, the client can query the Job's
+ "job-printer-uri" attribute in order to determine which Printer
+ object created the Job object. If the Printer object supports more
+ than one URI, the Printer object picks the one URI supplied by the
+ client when creating the job to build the value for and to populate
+ the Job's "job-printer-uri" attribute.
+
+ Allowing Job objects to have URIs allows for flexibility and
+ scalability. For example, in some implementations, the Printer
+ object might create Jobs that are processed in the same local
+ environment as the Printer object itself. In this case, the Job URI
+ might just be a composition of the Printer's URI and some unique
+ component for the Job object, such as the unique 32-bit positive
+ integer mentioned later in this paragraph. In other implementations,
+ the Printer object might be a central clearing-house for validating
+ all Job object creation requests, but the Job object itself might be
+ created in some environment that is remote from the Printer object.
+ In this case, the Job object's URI may have no physical-location
+
+
+
+Hastings, et al. Standards Track [Page 18]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ relationship at all to the Printer object's URI. Again, the fact
+ that Job objects have URIs allows for flexibility and scalability,
+ however, many existing printing systems have local models or
+ interface constraints that force print jobs to be identified using
+ only a 32-bit positive integer rather than an independent URI. This
+ numeric Job ID is only unique within the context of the Printer
+ object to which the create request was originally submitted.
+ Therefore, in order to allow both types of client access to IPP Job
+ objects (either by Job URI or by numeric Job ID), when the Printer
+ object successfully processes a create request and creates a new Job
+ object, the Printer object MUST generate both a Job URI and a Job ID.
+ The Job ID (stored in the "job-id" attribute) only has meaning in the
+ context of the Printer object to which the create request was
+ originally submitted. This requirement to support both Job URIs and
+ Job IDs allows all types of clients to access Printer objects and Job
+ objects no matter the local constraints imposed on the client
+ implementation.
+
+ In addition to identifiers, Printer objects and Job objects have
+ names ("printer-name" and "job-name"). An object name NEED NOT be
+ unique across all instances of all objects. A Printer object's name
+ is chosen and set by an administrator through some mechanism outside
+ the scope of this IPP/1.1 document. A Job object's name is
+ optionally chosen and supplied by the IPP client submitting the job.
+ If the client does not supply a Job object name, the Printer object
+ generates a name for the new Job object. In all cases, the name only
+ has local meaning.
+
+ To summarize:
+
+ - Each Printer object is identified with one or more URIs. The
+ Printer's "printer-uri-supported" attribute contains the URI(s).
+ - The Printer object's "uri-security-supported" attribute
+ identifies the communication channel security protocols that may
+ or may not have been configured for the various Printer object
+ URIs (e.g., 'tls' or 'none').
+ - The Printer object's "uri-authentication-supported" attribute
+ identifies the authentication mechanisms that may or may not
+ have been configured for the various Printer object URIs (e.g.,
+ 'digest' or 'none').
+ - Each Job object is identified with a Job URI. The Job's "job-
+ uri" attribute contains the URI.
+ - Each Job object is also identified with Job ID which is a 32-
+ bit, positive integer. The Job's "job-id" attribute contains
+ the Job ID. The Job ID is only unique within the context of the
+ Printer object which created the Job object.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 19]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - Each Job object has a "job-printer-uri" attribute which contains
+ the URI of the Printer object that was used to create the Job
+ object. This attribute is used to determine the Printer object
+ that created a Job object when given only the URI for the Job
+ object. This linkage is necessary to determine the languages,
+ charsets, and operations which are supported on that Job (the
+ basis for such support comes from the creating Printer object).
+ - Each Printer object has a name (which is not necessarily
+ unique). The administrator chooses and sets this name through
+ some mechanism outside the scope of this IPP/1.1 document. The
+ Printer object's "printer-name" attribute contains the name.
+ - Each Job object has a name (which is not necessarily unique).
+ The client optionally supplies this name in the create request.
+ If the client does not supply this name, the Printer object
+ generates a name for the Job object. The Job object's "job-name"
+ attribute contains the name.
+
+3. IPP Operations
+
+ IPP objects support operations. An operation consists of a request
+ and a response. When a client communicates with an IPP object, the
+ client issues an operation request to the URI for that object.
+ Operation requests and responses have parameters that identify the
+ operation. Operations also have attributes that affect the run-time
+ characteristics of the operation (the intended target, localization
+ information, etc.). These operation-specific attributes are called
+ operation attributes (as compared to object attributes such as
+ Printer object attributes or Job object attributes). Each request
+ carries along with it any operation attributes, object attributes,
+ and/or document data required to perform the operation. Each request
+ requires a response from the object. Each response indicates success
+ or failure of the operation with a status code as a response
+ parameter. The response contains any operation attributes, object
+ attributes, and/or status messages generated during the execution of
+ the operation request.
+
+ This section describes the semantics of the IPP operations, both
+ requests and responses, in terms of the parameters, attributes, and
+ other data associated with each operation.
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 20]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The IPP/1.1 Printer operations are:
+
+ Print-Job (section 3.2.1)
+ Print-URI (section 3.2.2)
+ Validate-Job (section 3.2.3)
+ Create-Job (section 3.2.4)
+ Get-Printer-Attributes (section 3.2.5)
+ Get-Jobs (section 3.2.6)
+ Pause-Printer (section 3.3.5)
+ Resume-Printer (section 3.3.6)
+ Purge-Jobs (section 3.3.7)
+
+ The Job operations are:
+
+ Send-Document (section 3.3.1)
+ Send-URI (section 3.3.2)
+ Cancel-Job (section 3.3.3)
+ Get-Job-Attributes (section 3.3.4)
+ Hold-Job (section 3.3.5)
+ Release-Job (section 3.3.6)
+ Restart-Job (section 3.3.7)
+
+ The Send-Document and Send-URI Job operations are used to add a new
+ document to an existing multi-document Job object created using the
+ Create-Job operation.
+
+3.1 Common Semantics
+
+ All IPP operations require some common parameters and operation
+ attributes. These common elements and their semantic characteristics
+ are defined and described in more detail in the following sections.
+
+3.1.1 Required Parameters
+
+ Every operation request contains the following REQUIRED parameters:
+
+ - a "version-number",
+ - an "operation-id",
+ - a "request-id", and
+ - the attributes that are REQUIRED for that type of request.
+
+ Every operation response contains the following REQUIRED parameters:
+
+ - a "version-number",
+ - a "status-code",
+ - the "request-id" that was supplied in the corresponding request,
+ and
+ - the attributes that are REQUIRED for that type of response.
+
+
+
+Hastings, et al. Standards Track [Page 21]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The "Encoding and Transport" document [RFC2910] defines special rules
+ for the encoding of these parameters. All other operation elements
+ are represented using the more generic encoding rules for attributes
+ and groups of attributes.
+
+3.1.2 Operation IDs and Request IDs
+
+ Each IPP operation request includes an identifying "operation-id"
+ value. Valid values are defined in the "operations-supported"
+ Printer attribute section (see section 4.4.15). The client specifies
+ which operation is being requested by supplying the correct
+ "operation-id" value.
+
+ In addition, every invocation of an operation is identified by a
+ "request-id" value. For each request, the client chooses the
+ "request-id" which MUST be an integer (possibly unique depending on
+ client requirements) in the range from 1 to 2**31 - 1 (inclusive).
+ This "request-id" allows clients to manage multiple outstanding
+ requests. The receiving IPP object copies all 32-bits of the client-
+ supplied "request-id" attribute into the response so that the client
+ can match the response with the correct outstanding request, even if
+ the "request-id" is out of range. If the request is terminated
+ before the complete "request-id" is received, the IPP object rejects
+ the request and returns a response with a "request-id" of 0.
+
+ Note: In some cases, the transport protocol underneath IPP might be a
+ connection oriented protocol that would make it impossible for a
+ client to receive responses in any order other than the order in
+ which the corresponding requests were sent. In such cases, the
+ "request-id" attribute would not be essential for correct protocol
+ operation. However, in other mappings, the operation responses can
+ come back in any order. In these cases, the "request-id" would be
+ essential.
+
+3.1.3 Attributes
+
+ Operation requests and responses are both composed of groups of
+ attributes and/or document data. The attributes groups are:
+
+ - Operation Attributes: These attributes are passed in the
+ operation and affect the IPP object's behavior while processing
+ the operation request and may affect other attributes or groups
+ of attributes. Some operation attributes describe the document
+ data associated with the print job and are associated with new
+ Job objects, however most operation attributes do not persist
+ beyond the life of the operation. The description of each
+ operation attribute includes conformance statements indicating
+ which operation attributes are REQUIRED and which are OPTIONAL
+
+
+
+Hastings, et al. Standards Track [Page 22]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ for an IPP object to support and which attributes a client MUST
+ supply in a request and an IPP object MUST supply in a response.
+ - Job Template Attributes: These attributes affect the processing
+ of a job. A client OPTIONALLY supplies Job Template Attributes
+ in a create request, and the receiving object MUST be prepared
+ to receive all supported attributes. The Job object can later
+ be queried to find out what Job Template attributes were
+ originally requested in the create request, and such attributes
+ are returned in the response as Job Object Attributes. The
+ Printer object can be queried about its Job Template attributes
+ to find out what type of job processing capabilities are
+ supported and/or what the default job processing behaviors are,
+ though such attributes are returned in the response as Printer
+ Object Attributes. The "ipp-attribute-fidelity" operation
+ attribute affects processing of all client-supplied Job Template
+ attributes (see sections 3.2.1.2 and 15 for a full description
+ of "ipp-attribute-fidelity" and its relationship to other
+ attributes).
+ - Job Object Attributes: These attributes are returned in response
+ to a query operation directed at a Job object.
+ - Printer Object Attributes: These attributes are returned in
+ response to a query operation directed at a Printer object.
+ - Unsupported Attributes: In a create request, the client supplies
+ a set of Operation and Job Template attributes. If any of these
+ attributes or their values is unsupported by the Printer object,
+ the Printer object returns the set of unsupported attributes in
+ the response. Sections 3.1.7, 3.2.1.2, and 15 give a full
+ description of how Job Template attributes supplied by the
+ client in a create request are processed by the Printer object
+ and how unsupported attributes are returned to the client.
+ Because of extensibility, any IPP object might receive a request
+ that contains new or unknown attributes or values for which it
+ has no support. In such cases, the IPP object processes what it
+ can and returns the unsupported attributes in the response. The
+ Unsupported Attribute group is defined for all operation
+ responses for returning unsupported attributes that the client
+ supplied in the request.
+
+ Later in this section, each operation is formally defined by
+ identifying the allowed and expected groups of attributes for each
+ request and response. The model identifies a specific order for each
+ group in each request or response, but the attributes within each
+ group may be in any order, unless specified otherwise.
+
+ The attributes within a group MUST be unique; if an attribute with
+ the same name occurs more than once, the group is mal-formed.
+ Clients MUST NOT submit such malformed requests and Printers MUST NOT
+ return such malformed responses. If such a malformed request is
+
+
+
+Hastings, et al. Standards Track [Page 23]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ submitted to a Printer, the Printer MUST either (1) reject the
+ request with the 'client-error-bad-request' status code (see section
+ 13.1.4.1) or (2) process the request normally after selecting only
+ one of the attribute instances, depending on implementation. Which
+ attribute is selected when there are duplicate attributes depends on
+ implementation. The IPP Printer MUST NOT use the values from more
+ than one such duplicate attribute instance.
+
+ Each attribute definition includes the attribute's name followed by
+ the name of its attribute syntax(es) in parenthesizes. In addition,
+ each 'integer' attribute is followed by the allowed range in
+ parentheses, (m:n), for values of that attribute. Each 'text' or
+ 'name' attribute is followed by the maximum size in octets in
+ parentheses, (size), for values of that attribute. For more details
+ on attribute syntax notation, see the descriptions of these
+ attributes syntaxes in section 4.1.
+
+ Note: Document data included in the operation is not strictly an
+ attribute, but it is treated as a special attribute group for
+ ordering purposes. The only operations that support supplying the
+ document data within an operation request are Print-Job and Send-
+ Document. There are no operation responses that include document
+ data.
+
+ Some operations are REQUIRED for IPP objects to support; the others
+ are OPTIONAL (see section 5.2.2). Therefore, before using an
+ OPTIONAL operation, a client SHOULD first use the REQUIRED Get-
+ Printer-Attributes operation to query the Printer's "operations-
+ supported" attribute in order to determine which OPTIONAL Printer and
+ Job operations are actually supported. The client SHOULD NOT use an
+ OPTIONAL operation that is not supported. When an IPP object
+ receives a request to perform an operation it does not support, it
+ returns the 'server-error-operation-not-supported' status code (see
+ section 13.1.5.2). An IPP object is non-conformant if it does not
+ support a REQUIRED operation.
+
+3.1.4 Character Set and Natural Language Operation Attributes
+
+ Some Job and Printer attributes have values that are text strings and
+ names intended for human understanding rather than machine
+ understanding (see the 'text' and 'name' attribute syntax
+ descriptions in section 4.1). The following sections describe two
+ special Operation Attributes called "attributes-charset" and
+ "attributes-natural-language". These attributes are always part of
+ the Operation Attributes group. For most attribute groups, the order
+ of the attributes within the group is not important. However, for
+ these two attributes within the Operation Attributes group, the order
+ is critical. The "attributes-charset" attribute MUST be the first
+
+
+
+Hastings, et al. Standards Track [Page 24]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ attribute in the group and the "attributes-natural-language"
+ attribute MUST be the second attribute in the group. In other words,
+ these attributes MUST be supplied in every IPP request and response,
+ they MUST come first in the group, and MUST come in the specified
+ order. For job creation operations, the IPP Printer implementation
+ saves these two attributes with the new Job object as Job Description
+ attributes. For the sake of brevity in this document, these
+ operation attribute descriptions are not repeated with every
+ operation request and response, but have a reference back to this
+ section instead.
+
+3.1.4.1 Request Operation Attributes
+
+ The client MUST supply and the Printer object MUST support the
+ following REQUIRED operation attributes in every IPP/1.1 operation
+ request:
+
+ "attributes-charset" (charset):
+ This operation attribute identifies the charset (coded
+ character set and encoding method) used by any 'text' and
+ 'name' attributes that the client is supplying in this request.
+ It also identifies the charset that the Printer object MUST use
+ (if supported) for all 'text' and 'name' attributes and status
+ messages that the Printer object returns in the response to
+ this request. See Sections 4.1.1 and 4.1.2 for the definition
+ of the 'text' and 'name' attribute syntaxes.
+
+ All clients and IPP objects MUST support the 'utf-8' charset
+ [RFC2279] and MAY support additional charsets provided that
+ they are registered with IANA [IANA-CS]. If the Printer object
+ does not support the client supplied charset value, the Printer
+ object MUST reject the request, set the "attributes-charset" to
+ 'utf-8' in the response, and return the 'client-error-charset-
+ not-supported' status code and any 'text' or 'name' attributes
+ using the 'utf-8' charset. The Printer NEED NOT return any
+ attributes in the Unsupported Attributes Group (See sections
+ 3.1.7 and 3.2.1.2). The Printer object MUST indicate the
+ charset(s) supported as the values of the "charset-supported"
+ Printer attribute (see Section 4.4.18), so that the client can
+ query to determine which charset(s) are supported.
+
+ Note to client implementers: Since IPP objects are only
+ required to support the 'utf-8' charset, in order to maximize
+ interoperability with multiple IPP object implementations, a
+ client may want to supply 'utf-8' in the "attributes-charset"
+ operation attribute, even though the client is only passing and
+ able to present a simpler charset, such as US-ASCII [ASCII] or
+ ISO-8859-1 [ISO8859-1]. Then the client will have to filter
+
+
+
+Hastings, et al. Standards Track [Page 25]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ out (or charset convert) those characters that are returned in
+ the response that it cannot present to its user. On the other
+ hand, if both the client and the IPP objects also support a
+ charset in common besides utf-8, the client may want to use
+ that charset in order to avoid charset conversion or data loss.
+
+ See the 'charset' attribute syntax description in Section 4.1.7
+ for the syntax and semantic interpretation of the values of
+ this attribute and for example values.
+
+ "attributes-natural-language" (naturalLanguage):
+ This operation attribute identifies the natural language used
+ by any 'text' and 'name' attributes that the client is
+ supplying in this request. This attribute also identifies the
+ natural language that the Printer object SHOULD use for all
+ 'text' and 'name' attributes and status messages that the
+ Printer object returns in the response to this request. See
+ the 'naturalLanguage' attribute syntax description in section
+ 4.1.8 for the syntax and semantic interpretation of the values
+ of this attribute and for example values.
+
+ There are no REQUIRED natural languages required for the
+ Printer object to support. However, the Printer object's
+ "generated-natural-language-supported" attribute identifies the
+ natural languages supported by the Printer object and any
+ contained Job objects for all text strings generated by the IPP
+ object. A client MAY query this attribute to determine which
+ natural language(s) are supported for generated messages.
+
+ For any of the attributes for which the Printer object
+ generates text, i.e., for the "job-state-message", "printer-
+ state-message", and status messages (see Section 3.1.6), the
+ Printer object MUST be able to generate these text strings in
+ any of its supported natural languages. If the client requests
+ a natural language that is not supported, the Printer object
+ MUST return these generated messages in the Printer's
+ configured natural language as specified by the Printer's
+ "natural-language-configured" attribute" (see Section 4.4.19).
+
+ For other 'text' and 'name' attributes supplied by the client,
+ authentication system, operator, system administrator, or
+ manufacturer (i.e., for "job-originating-user-name", "printer-
+ name" (name), "printer-location" (text), "printer-info" (text),
+ and "printer-make-and-model" (text)), the Printer object is
+ only required to support the configured natural language of the
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 26]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Printer identified by the Printer object's "natural-language-
+ configured" attribute, though support of additional natural
+ languages for these attributes is permitted.
+
+ For any 'text' or 'name' attribute in the request that is in a
+ different natural language than the value supplied in the
+ "attributes-natural-language" operation attribute, the client
+ MUST use the Natural Language Override mechanism (see sections
+ 4.1.1.2 and 4.1.2.2) for each such attribute value supplied.
+ The client MAY use the Natural Language Override mechanism
+ redundantly, i.e., use it even when the value is in the same
+ natural language as the value supplied in the "attributes-
+ natural-language" operation attribute of the request.
+
+ The IPP object MUST accept any natural language and any Natural
+ Language Override, whether the IPP object supports that natural
+ language or not (and independent of the value of the "ipp-
+ attribute-fidelity" Operation attribute). That is the IPP
+ object accepts all client supplied values no matter what the
+ values are in the Printer object's "generated-natural-
+ language-supported" attribute. That attribute, "generated-
+ natural-language-supported", only applies to generated
+ messages, not client supplied messages. The IPP object MUST
+ remember that natural language for all client-supplied
+ attributes, and when returning those attributes in response to
+ a query, the IPP object MUST indicate that natural language.
+
+ Each value whose attribute syntax type is 'text' or 'name' (see
+ sections 4.1.1 and 4.1.2) has an Associated Natural-Language.
+ This document does not specify how this association is stored
+ in a Printer or Job object. When such a value is encoded in a
+ request or response, the natural language is either implicit or
+ explicit:
+
+ - In the implicit case, the value contains only the text/name
+ value, and the language is specified by the "attributes-
+ natural-language" operation attribute in the request or
+ response (see sections 4.1.1.1 textWithoutLanguage and
+ 4.1.2.1 nameWithoutLanguage).
+
+ - In the explicit case (also known as the Natural-Language
+ Override case), the value contains both the language and the
+ text/name value (see sections 4.1.1.2 textWithLanguage and
+ 4.1.2.2 nameWithLanguage).
+
+ For example, the "job-name" attribute MAY be supplied by the
+ client in a create request. The text value for this attribute
+ will be in the natural language identified by the "attribute-
+
+
+
+Hastings, et al. Standards Track [Page 27]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ natural-language" attribute, or if different, as identified by
+ the Natural Language Override mechanism. If supplied, the IPP
+ object will use the value of the "job-name" attribute to
+ populate the Job object's "job-name" attribute. Whenever any
+ client queries the Job object's "job-name" attribute, the IPP
+ object returns the attribute as stored and uses the Natural
+ Language Override mechanism to specify the natural language, if
+ it is different from that reported in the "attributes-natural-
+ language" operation attribute of the response. The IPP object
+ MAY use the Natural Language Override mechanism redundantly,
+ i.e., use it even when the value is in the same natural
+ language as the value supplied in the "attributes-natural-
+ language" operation attribute of the response.
+
+ An IPP object MUST NOT reject a request based on a supplied
+ natural language in an "attributes-natural-language" Operation
+ attribute or in any attribute that uses the Natural Language
+ Override.
+
+ Clients SHOULD NOT supply 'text' or 'name' attributes that use an
+ illegal combination of natural language and charset. For example,
+ suppose a Printer object supports charsets 'utf-8', 'iso-8859-1', and
+ 'iso-8859-7'. Suppose also, that it supports natural languages 'en'
+ (English), 'fr' (French), and 'el' (Greek). Although the Printer
+ object supports the charset 'iso-8859-1' and natural language 'el',
+ it probably does not support the combination of Greek text strings
+ using the 'iso-8859-1' charset. The Printer object handles this
+ apparent incompatibility differently depending on the context in
+ which it occurs:
+
+ - In a create request: If the client supplies a text or name
+ attribute (for example, the "job-name" operation attribute) that
+ uses an apparently incompatible combination, it is a client
+ choice that does not affect the Printer object or its correct
+ operation. Therefore, the Printer object simply accepts the
+ client supplied value, stores it with the Job object, and
+ responds back with the same combination whenever the client (or
+ any client) queries for that attribute.
+ - In a query-type operation, like Get-Printer-Attributes: If the
+ client requests an apparently incompatible combination, the
+ Printer object responds (as described in section 3.1.4.2) using
+ the Printer's configured natural language rather than the
+ natural language requested by the client.
+
+ In either case, the Printer object does not reject the request
+ because of the apparent incompatibility. The potential incompatible
+ combination of charset and natural language can occur either at the
+ global operation level or at the Natural Language Override
+
+
+
+Hastings, et al. Standards Track [Page 28]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ attribute-by-attribute level. In addition, since the response always
+ includes explicit charset and natural language information, there is
+ never any question or ambiguity in how the client interprets the
+ response.
+
+3.1.4.2 Response Operation Attributes
+
+ The Printer object MUST supply and the client MUST support the
+ following REQUIRED operation attributes in every IPP/1.1 operation
+ response:
+
+ "attributes-charset" (charset):
+ This operation attribute identifies the charset used by any
+ 'text' and 'name' attributes that the Printer object is
+ returning in this response. The value in this response MUST be
+ the same value as the "attributes-charset" operation attribute
+ supplied by the client in the request. If this is not possible
+ (i.e., the charset requested is not supported), the request
+ would have been rejected. See "attributes-charset" described
+ in Section 3.1.4.1 above.
+
+ If the Printer object supports more than just the 'utf-8'
+ charset, the Printer object MUST be able to code convert
+ between each of the charsets supported on a highest fidelity
+ possible basis in order to return the 'text' and 'name'
+ attributes in the charset requested by the client. However,
+ some information loss MAY occur during the charset conversion
+ depending on the charsets involved. For example, the Printer
+ object may convert from a UTF-8 'a' to a US-ASCII 'a' (with no
+ loss of information), from an ISO Latin 1 CAPITAL LETTER A WITH
+ ACUTE ACCENT to US-ASCII 'A' (losing the accent), or from a
+ UTF-8 Japanese Kanji character to some ISO Latin 1 error
+ character indication such as '?', decimal code equivalent, or
+ to the absence of a character, depending on implementation.
+
+ Whether an implementation that supports more than one charset
+ stores the data in the charset supplied by the client or code
+ converts to one of the other supported charsets, depends on
+ implementation. The strategy should try to minimize loss of
+ information during code conversion. On each response, such an
+ implementation converts from its internal charset to that
+ requested.
+
+ "attributes-natural-language" (naturalLanguage):
+ This operation attribute identifies the natural language used
+ by any 'text' and 'name' attributes that the IPP object is
+ returning in this response. Unlike the "attributes-charset"
+ operation attribute, the IPP object NEED NOT return the same
+
+
+
+Hastings, et al. Standards Track [Page 29]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ value as that supplied by the client in the request. The IPP
+ object MAY return the natural language of the Job object or the
+ Printer's configured natural language as identified by the
+ Printer object's "natural-language-configured" attribute,
+ rather than the natural language supplied by the client. For
+ any 'text' or 'name' attribute or status message in the
+ response that is in a different natural language than the value
+ returned in the "attributes-natural-language" operation
+ attribute, the IPP object MUST use the Natural Language
+ Override mechanism (see sections 4.1.1.2 and 4.1.2.2) on each
+ attribute value returned. The IPP object MAY use the Natural
+ Language Override mechanism redundantly, i.e., use it even when
+ the value is in the same natural language as the value supplied
+ in the "attributes-natural-language" operation attribute of the
+ response.
+
+3.1.5 Operation Targets
+
+ All IPP operations are directed at IPP objects. For Printer
+ operations, the operation is always directed at a Printer object
+ using one of its URIs (i.e., one of the values in the Printer
+ object's "printer-uri-supported" attribute). Even if the Printer
+ object supports more than one URI, the client supplies only one URI
+ as the target of the operation. The client identifies the target
+ object by supplying the correct URI in the "printer-uri (uri)"
+ operation attribute.
+
+ For Job operations, the operation is directed at either:
+
+ - The Job object itself using the Job object's URI. In this case,
+ the client identifies the target object by supplying the correct
+ URI in the "job-uri (uri)" operation attribute.
+ - The Printer object that created the Job object using both the
+ Printer objects URI and the Job object's Job ID. Since the
+ Printer object that created the Job object generated the Job ID,
+ it MUST be able to correctly associate the client supplied Job
+ ID with the correct Job object. The client supplies the Printer
+ object's URI in the "printer-uri (uri)" operation attribute and
+ the Job object's Job ID in the "job-id (integer(1:MAX))"
+ operation attribute.
+
+ If the operation is directed at the Job object directly using the Job
+ object's URI, the client MUST NOT include the redundant "job-id"
+ operation attribute.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 30]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The operation target attributes are REQUIRED operation attributes
+ that MUST be included in every operation request. Like the charset
+ and natural language attributes (see section 3.1.4), the operation
+ target attributes are specially ordered operation attributes. In all
+ cases, the operation target attributes immediately follow the
+ "attributes-charset" and "attributes-natural-language" attributes
+ within the operation attribute group, however the specific ordering
+ rules are:
+
+ - In the case where there is only one operation target attribute
+ (i.e., either only the "printer-uri" attribute or only the
+ "job-uri" attribute), that attribute MUST be the third attribute
+ in the operation attributes group.
+ - In the case where Job operations use two operation target
+ attributes (i.e., the "printer-uri" and "job-id" attributes),
+ the "printer-uri" attribute MUST be the third attribute and the
+ "job-id" attribute MUST be the fourth attribute.
+
+ In all cases, the target URIs contained within the body of IPP
+ operation requests and responses must be in absolute format rather
+ than relative format (a relative URL identifies a resource with the
+ scope of the HTTP server, but does not include scheme, host or port).
+
+ The following rules apply to the use of port numbers in URIs that
+ identify IPP objects:
+
+ 1. If the URI scheme allows the port number to be explicitly
+ included in the URI string, and a port number is specified
+ within the URI, then that port number MUST be used by the
+ client to contact the IPP object.
+
+ 2. If the URI scheme allows the port number to be explicitly
+ included in the URI string, and a port number is not specified
+ within the URI, then default port number implied by that URI
+ scheme MUST be used by the client to contact the IPP object.
+
+ 3. If the URI scheme does not allow an explicit port number to be
+ specified within the URI, then the default port number implied
+ by that URI MUST be used by the client to contact the IPP
+ object.
+
+ Note: The IPP "Encoding and Transport document [RFC2910] shows a
+ mapping of IPP onto HTTP/1.1 [RFC2616] and defines a new default port
+ number for using IPP over HTTP/1.1.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 31]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.1.6 Operation Response Status Codes and Status Messages
+
+ Every operation response includes a REQUIRED "status-code" parameter
+ and an OPTIONAL "status-message" operation attribute, and an OPTIONAL
+ "detailed-status-message" operation attribute. The Print-URI and
+ Send-URI response MAY include an OPTIONAL "document-access-error"
+ operation attribute.
+
+3.1.6.1 "status-code" (type2 enum)
+
+ The REQUIRED "status-code" parameter provides information on the
+ processing of a request.
+
+ The status code is intended for use by automata. A client
+ implementation of IPP SHOULD convert status code values into any
+ localized message that has semantic meaning to the end user.
+
+ The "status-code" value is a numeric value that has semantic meaning.
+ The "status-code" syntax is similar to a "type2 enum" (see section
+ 4.1 on "Attribute Syntaxes") except that values can range only from
+ 0x0000 to 0x7FFF. Section 13 describes the status codes, assigns the
+ numeric values, and suggests a corresponding status message for each
+ status code for use by the client when the user's natural language is
+ English.
+
+ If the Printer performs an operation with no errors and it encounters
+ no problems, it MUST return the status code 'successful-ok' in the
+ response. See section 13.
+
+ If the client supplies unsupported values for the following
+ parameters or Operation attributes, the Printer object MUST reject
+ the operation, NEED NOT return the unsupported attribute value in the
+ Unsupported Attributes group, and MUST return the indicated status
+ code:
+
+ Parameter/Attribute Status code
+
+ version-number server-error-version-not-supported
+ operation-id server-error-operation-not-supported
+ attributes-charset client-error-charset-not-supported
+ compression client-error-compression-not-supported
+ document-format client-error-document-format-not-supported
+ document-uri client-error-uri-scheme-not-supported,
+ client-error-document-access-error
+
+ If the client supplies unsupported values for other attributes, or
+ unsupported attributes, the Printer returns the status code defined
+ in section 3.1.7 on Unsupported Attributes.
+
+
+
+Hastings, et al. Standards Track [Page 32]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.1.6.2 "status-message" (text(255))
+
+ The OPTIONAL "status-message" operation attribute provides a short
+ textual description of the status of the operation. The "status-
+ message" attribute's syntax is "text(255)", so the maximum length is
+ 255 octets (see section 4.1.1). The status message is intended for
+ the human end user. If a response does include a "status-message"
+ attribute, an IPP client NEED NOT examine or display the messages,
+ however it SHOULD do so in some implementation specific manner. The
+ "status-message" is especially useful for a later version of a
+ Printer object to return as supplemental information for the human
+ user to accompany a status code that an earlier version of a client
+ might not understand.
+
+ If the Printer object supports the "status-message" operation
+ attribute, the Printer object MUST be able to generate this message
+ in any of the natural languages identified by the Printer object's
+ "generated-natural-language-supported" attribute (see the
+ "attributes-natural-language" operation attribute specified in
+ section 3.1.4.1. Section 13 suggests the text for the status message
+ returned by the Printer for use with the English natural language.
+
+ As described in section 3.1.4.1 for any returned 'text' attribute, if
+ there is a choice for generating this message, the Printer object
+ uses the natural language indicated by the value of the "attributes-
+ natural-language" in the client request if supported, otherwise the
+ Printer object uses the value in the Printer object's own "natural-
+ language-configured" attribute.
+
+ If the Printer object supports the "status-message" operation
+ attribute, it SHOULD use the REQUIRED 'utf-8' charset to return a
+ status message for the following error status codes (see section 13):
+ 'client-error-bad-request', 'client-error-charset-not-supported',
+ 'server-error-internal-error', 'server-error-operation-not-
+ supported', and 'server-error-version-not-supported'. In this case,
+ it MUST set the value of the "attributes-charset" operation attribute
+ to 'utf-8' in the error response.
+
+3.1.6.3 "detailed-status-message" (text(MAX))
+
+ The OPTIONAL "detailed-status-message" operation attribute provides
+ additional more detailed technical and implementation-specific
+ information about the operation. The "detailed-status-message"
+ attribute's syntax is "text(MAX)", so the maximum length is 1023
+ octets (see section 4.1.1). If the Printer objects supports the
+ "detailed-status-message" operation attribute, the Printer NEED NOT
+ localize the message, since it is intended for use by the system
+ administrator or other experienced technical persons. Localization
+
+
+
+Hastings, et al. Standards Track [Page 33]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ might obscure the technical meaning of such messages. Clients MUST
+ NOT attempt to parse the value of this attribute. See the
+ "document-access-error" operation attribute (section 3.1.6.4) for
+ additional errors that a program can process.
+
+3.1.6.4 "document-access-error" (text(MAX))
+
+ This OPTIONAL operation attribute provides additional information
+ about any document access errors encountered by the Printer before it
+ returned a response to the Print-URI (section 3.2.2) or Send-URI
+ (section 3.3.1) operation. For errors in the protocol identified by
+ the URI scheme in the "document-uri" operation attribute, such as
+ 'http:' or 'ftp:', the error code is returned in parentheses,
+ followed by the URI. For example:
+
+ (404) http://ftp.pwg.org/pub/pwg/ipp/new_MOD/ipp-model-v11.pdf
+
+ Most Internet protocols use decimal error codes (unlike IPP), so the
+ ASCII error code representation is in decimal.
+
+3.1.7 Unsupported Attributes
+
+ The Unsupported Attributes group contains attributes that are not
+ supported by the operation. This group is primarily for the job
+ creation operations, but all operations can return this group.
+
+ A Printer object MUST include an Unsupported Attributes group in a
+ response if the status code is one of the following: 'successful-
+ ok-ignored-or-substituted-attributes', 'successful-ok-conflicting-
+ attributes', 'client-error-attributes-or-values-not-supported' or
+ 'client-error-conflicting-attributes'.
+
+ If the status code is one of the four specified in the preceding
+ paragraph, the Unsupported Attributes group MUST contain all of those
+ attributes and only those attributes that are:
+
+ a. an Operation or Job Template attribute supplied in the request,
+ and
+
+ b. unsupported by the printer. See below for details on the three
+ categories "unsupported" attributes.
+
+ If the status code is one of those in the table in section 3.1.6.1,
+ the Unsupported Attributes group NEED NOT contain the unsupported
+ parameter or attribute indicated in that table.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 34]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If the Printer object is not returning any Unsupported Attributes in
+ the response, the Printer object SHOULD omit Group 2 rather than
+ sending an empty group. However, a client MUST be able to accept an
+ empty group.
+
+ Unsupported attributes fall into three categories:
+
+ 1. The Printer object does not support the supplied attribute (no
+ matter what the attribute syntax or value).
+
+ 2. The Printer object does support the attribute, but does not
+ support some or all of the particular attribute syntaxes or
+ values supplied by the client (i.e., the Printer object does
+ not have those attribute syntaxes or values in its
+ corresponding "xxx-supported" attribute).
+
+ 3. The Printer object does support the attributes and values
+ supplied, but the particular values are in conflict with one
+ another, because they violate a constraint, such as not being
+ able to staple transparencies.
+
+ In the case of an unsupported attribute name, the Printer object
+ returns the client-supplied attribute with a substituted value of
+ 'unsupported'. This value's syntax type is "out-of-band" and its
+ encoding is defined by special rules for "out-of-band" values in the
+ "Encoding and Transport" document [RFC2910]. Its value indicates no
+ support for the attribute itself (see the beginning of section 4.1).
+
+ In the case of a supported attribute with one or more unsupported
+ attribute syntaxes or values, the Printer object simply returns the
+ client-supplied attribute with the unsupported attribute syntaxes or
+ values as supplied by the client. This indicates support for the
+ attribute, but no support for that particular attribute syntax or
+ value. If the client supplies a multi-valued attribute with more
+ than one value and the Printer object supports the attribute but only
+ supports a subset of the client-supplied attribute syntaxes or
+ values, the Printer object
+
+ MUST return only those attribute syntaxes or values that are
+ unsupported.
+
+ In the case of two (or more) supported attribute values that are in
+ conflict with one another (although each is supported independently,
+ the values conflict when requested together within the same job), the
+ Printer object MUST return all the values that it ignores or
+ substitutes to resolve the conflict, but not any of the values that
+
+
+
+
+
+Hastings, et al. Standards Track [Page 35]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ it is still using. The choice for exactly how to resolve the
+ conflict is implementation dependent. See sections 3.2.1.2 and 15.
+ See The Implementer's Guide [IPP-IIG] for an example.
+
+3.1.8 Versions
+
+ Each operation request and response carries with it a "version-
+ number" parameter. Each value of the "version-number" is in the form
+ "X.Y" where X is the major version number and Y is the minor version
+ number. By including a version number in the client request, it
+ allows the client to identify which version of IPP it is interested
+ in using, i.e., the version whose conformance requirements the client
+ may be depending upon the Printer to meet.
+
+ If the IPP object does not support that major version number supplied
+ by the client, i.e., the major version field of the "version-number"
+ parameter does not match any of the values of the Printer's "ipp-
+ versions-supported" (see section 4.4.14), the object MUST respond
+ with a status code of 'server-error-version-not-supported' along with
+ the closest version number that is supported (see section 13.1.5.4).
+ If the major version number is supported, but the minor version
+ number is not, the IPP object SHOULD accept and attempt to perform
+ the request (or reject the request if the operation is not
+ supported), else it rejects the request and returns the 'server-
+ error-version-not-supported' status code. In all cases, the IPP
+ object MUST return the "version-number" that it supports that is
+ closest to the version number supplied by the client in the request.
+
+ There is no version negotiation per se. However, if after receiving
+ a 'server-error-version-not-supported' status code from an IPP
+ object, a client SHOULD try again with a different version number. A
+ client MAY also determine the versions supported either from a
+ directory that conforms to Appendix E (see section 16) or by querying
+ the Printer object's "ipp-versions-supported" attribute (see section
+ 4.4.14) to determine which versions are supported.
+
+ An IPP object implementation MUST support version '1.1', i.e., meet
+ the conformance requirements for IPP/1.1 as specified in this
+ document and [RFC2910]. It is recommended that IPP object
+ implementations accept any request with the major version '1' (or
+ reject the request if the operation is not supported).
+
+ There is only one notion of "version number" that covers both IPP
+ Model and IPP Protocol changes. Thus the version number MUST change
+ when introducing a new version of the Model and Semantics document
+ (this document) or a new version of the "Encoding and Transport"
+ document [RFC2910].
+
+
+
+
+Hastings, et al. Standards Track [Page 36]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Changes to the major version number of the Model and Semantics
+ document indicate structural or syntactic changes that make it
+ impossible for older version of IPP clients and Printer objects to
+ correctly parse and correctly process the new or changed attributes,
+ operations and responses. If the major version number changes, the
+ minor version numbers is set to zero. As an example, adding the
+ REQUIRED "ipp-attribute-fidelity" attribute to version '1.1' (if it
+ had not been part of version '1.0'), would have required a change to
+ the major version number, since an IPP/1.0 Printer would not have
+ processed a request with the correct semantics that contained the
+ "ipp-attribute-fidelity" attribute that it did not know about. Items
+ that might affect the changing of the major version number include
+ any changes to the Model and Semantics document (this document) or
+ the "Encoding and Transport" document [RFC2910] itself, such as:
+
+ - reordering of ordered attributes or attribute sets
+ - changes to the syntax of existing attributes
+ - adding REQUIRED (for an IPP object to support) operation
+ attribute groups
+ - adding values to existing REQUIRED operation attributes
+ - adding REQUIRED operations
+
+ Changes to the minor version number indicate the addition of new
+ features, attributes and attribute values that may not be understood
+ by all IPP objects, but which can be ignored if not understood.
+ Items that might affect the changing of the minor version number
+ include any changes to the model objects and attributes but not the
+ encoding and transport rules [RFC2910] (except adding attribute
+ syntaxes). Examples of such changes are:
+
+ - grouping all extensions not included in a previous version into
+ a new version
+ - adding new attribute values
+ - adding new object attributes
+ - adding OPTIONAL (for an IPP object to support) operation
+ attributes (i.e., those attributes that an IPP object can ignore
+ without confusing clients)
+ - adding OPTIONAL (for an IPP object to support) operation
+ attribute groups (i.e., those attributes that an IPP object can
+ ignore without confusing clients)
+ - adding new attribute syntaxes
+ - adding OPTIONAL operations
+ - changing Job Description attributes or Printer Description
+ attributes from OPTIONAL to REQUIRED or vice versa.
+ - adding OPTIONAL attribute syntaxes to an existing attribute.
+
+ The encoding of the "version-number" MUST NOT change over any version
+ number (either major or minor). This rule guarantees that all future
+
+
+
+Hastings, et al. Standards Track [Page 37]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ versions will be backwards compatible with all previous versions (at
+ least for checking the "version-number"). In addition, any protocol
+ elements (attributes, error codes, tags, etc.) that are not carried
+ forward from one version to the next are deprecated so that they can
+ never be reused with new semantics.
+
+ Implementations that support a certain version NEED NOT support ALL
+ previous versions. As each new version is defined (through the
+ release of a new IPP specification document), that version will
+ specify which previous versions MUST and which versions SHOULD be
+ supported in compliant implementations.
+
+3.1.9 Job Creation Operations
+
+ In order to "submit a print job" and create a new Job object, a
+ client issues a create request. A create request is any one of
+ following three operation requests:
+
+ - The Print-Job Request: A client that wants to submit a print job
+ with only a single document uses the Print-Job operation. The
+ operation allows for the client to "push" the document data to
+ the Printer object by including the document data in the request
+ itself.
+
+ - The Print-URI Request: A client that wants to submit a print job
+ with only a single document (where the Printer object "pulls"
+ the document data instead of the client "pushing" the data to
+ the Printer object) uses the Print-URI operation. In this
+ case, the client includes in the request only a URI reference to
+ the document data (not the document data itself).
+
+ - The Create-Job Request: A client that wants to submit a print
+ job with multiple documents uses the Create-Job operation. This
+ operation is followed by an arbitrary number (one or more) of
+ Send-Document and/or Send-URI operations (each creating another
+ document for the newly create Job object). The Send-Document
+ operation includes the document data in the request (the client
+ "pushes" the document data to the printer), and the Send-URI
+ operation includes only a URI reference to the document data in
+ the request (the Printer "pulls" the document data from the
+ referenced location). The last Send-Document or Send-URI
+ request for a given Job object includes a "last-document"
+ operation attribute set to 'true' indicating that this is the
+ last request.
+
+ Throughout this model document, the term "create request" is used to
+ refer to any of these three operation requests.
+
+
+
+
+Hastings, et al. Standards Track [Page 38]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ A Create-Job operation followed by only one Send-Document operation
+ is semantically equivalent to a Print-Job operation, however, for
+ performance reasons, the client SHOULD use the Print-Job operation
+ for all single document jobs. Also, Print-Job is a REQUIRED
+ operation (all implementations MUST support it) whereas Create-Job is
+ an OPTIONAL operation, hence some implementations might not support
+ it.
+
+ Job submission time is the point in time when a client issues a
+ create request. The initial state of every Job object is the
+ 'pending', 'pending-held', or 'processing' state (see section 4.3.7).
+ When the Printer object begins processing the print job, the Job
+ object's state moves to 'processing'. This is known as job
+ processing time. There are validation checks that must be done at
+ job submission time and others that must be performed at job
+ processing time.
+
+ At job submission time and at the time a Validate-Job operation is
+ received, the Printer MUST do the following:
+
+ 1. Process the client supplied attributes and either accept or
+ reject the request
+ 2. Validate the syntax of and support for the scheme of any client
+ supplied URI
+
+ At job submission time the Printer object MUST validate whether or
+ not the supplied attributes, attribute syntaxes, and values are
+ supported by matching them with the Printer object's corresponding
+ "xxx-supported" attributes. See section 3.1.7 for details. [IPP-
+ IIG] presents suggested steps for an IPP object to either accept or
+ reject any request and additional steps for processing create
+ requests.
+
+ At job submission time the Printer object NEED NOT perform the
+ validation checks reserved for job processing time such as:
+
+ 1. Validating the document data
+ 2. Validating the actual contents of any client supplied URI
+ (resolve the reference and follow the link to the document
+ data)
+
+ At job submission time, these additional job processing time
+ validation checks are essentially useless, since they require
+ actually parsing and interpreting the document data, are not
+ guaranteed to be 100% accurate, and MUST be done, yet again, at job
+ processing time. Also, in the case of a URI, checking for
+ availability at job submission time does not guarantee availability
+
+
+
+
+Hastings, et al. Standards Track [Page 39]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ at job processing time. In addition, at job processing time, the
+ Printer object might discover any of the following conditions that
+ were not detectable at job submission time:
+
+ - runtime errors in the document data,
+ - nested document data that is in an unsupported format,
+ - the URI reference is no longer valid (i.e., the server hosting
+ the document might be down), or
+ - any other job processing error
+
+ At job submission time, a Printer object, especially a non-spooling
+ Printer, MAY accept jobs that it does not have enough space for. In
+ such a situation, a Printer object MAY stop reading data from a
+ client for an indefinite period of time. A client MUST be prepared
+ for a write operation to block for an indefinite period of time (see
+ section 5.1 on client conformance).
+
+ When a Printer object has too little space for starting a new job, it
+ MAY reject a new create request. In this case, a Printer object MUST
+ return a response (in reply to the rejected request) with a status-
+ code of 'server-error-busy' (see section 14.1.5.8) and it MAY close
+ the connection before receiving all bytes of the operation. A
+ Printer SHOULD indicate that it is temporarily unable to accept jobs
+ by setting the 'spool-space-full' value in its "printer-state-
+ reasons" attribute and removing the value when it can accept another
+ job (see section 4.4.12).
+
+ When receiving a 'server-error-busy' status-code in an operation
+ response, a client MUST be prepared for the Printer object to close
+ the connection before the client has sent all of the data (especially
+ for the Print-Job operation). A client MUST be prepared to keep
+ submitting a create request until the IPP Printer object accepts the
+ create request.
+
+ At job processing time, since the Printer object has already
+ responded with a successful status code in the response to the create
+ request, if the Printer object detects an error, the Printer object
+ is unable to inform the end user of the error with an operation
+ status code. In this case, the Printer, depending on the error, can
+ set the job object's "job-state", "job-state-reasons", or "job-
+ state-message" attributes to the appropriate value(s) so that later
+ queries can report the correct job status.
+
+ Note: Asynchronous notification of events is outside the scope of
+ this IPP/1.1 document.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 40]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.2 Printer Operations
+
+ All Printer operations are directed at Printer objects. A client
+ MUST always supply the "printer-uri" operation attribute in order to
+ identify the correct target of the operation.
+
+3.2.1 Print-Job Operation
+
+ This REQUIRED operation allows a client to submit a print job with
+ only one document and supply the document data (rather than just a
+ reference to the data). See Section 15 for the suggested steps for
+ processing create operations and their Operation and Job Template
+ attributes.
+
+3.2.1.1 Print-Job Request
+
+ The following groups of attributes are supplied as part of the
+ Print-Job Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1. The Printer object
+ MUST copy these values to the corresponding Job Description
+ attributes described in sections 4.3.19 and 4.3.20.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "job-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied Job name. If this attribute is supplied by the
+ client, its value is used for the "job-name" attribute of the
+ newly created Job object. The client MAY automatically include
+ any information that will help the end-user distinguish amongst
+ his/her jobs, such as the name of the application program along
+ with information from the document, such as the document name,
+ document subject, or source file name. If this attribute is
+ not supplied by the client, the Printer generates a name to use
+ in the "job-name" attribute of the newly created Job object
+ (see Section 4.3.5).
+
+
+
+Hastings, et al. Standards Track [Page 41]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "ipp-attribute-fidelity" (boolean):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. The value 'true' indicates
+ that total fidelity to client supplied Job Template attributes
+ and values is required, else the Printer object MUST reject the
+ Print-Job request. The value 'false' indicates that a
+ reasonable attempt to print the Job object is acceptable and
+ the Printer object MUST accept the Print-Job request. If not
+ supplied, the Printer object assumes the value is 'false'. All
+ Printer objects MUST support both types of job processing. See
+ section 15 for a full description of "ipp-attribute-fidelity"
+ and its relationship to other attributes, especially the
+ Printer object's "pdl-override-supported" attribute.
+
+ "document-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied document name. The document name MAY be different
+ than the Job name. Typically, the client software
+ automatically supplies the document name on behalf of the end
+ user by using a file name or an application generated name. If
+ this attribute is supplied, its value can be used in a manner
+ defined by each implementation. Examples include: printed
+ along with the Job (job start sheet, page adornments, etc.),
+ used by accounting or resource tracking management tools, or
+ even stored along with the document as a document level
+ attribute. IPP/1.1 does not support the concept of document
+ level attributes.
+
+ "compression" (type3 keyword):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute and the "compression-
+ supported" attribute (see section 4.4.32). The client supplied
+ "compression" operation attribute identifies the compression
+ algorithm used on the document data. The following cases exist:
+
+ a) If the client omits this attribute, the Printer object MUST
+ assume that the data is not compressed (i.e. the Printer
+ follows the rules below as if the client supplied the
+ "compression" attribute with a value of 'none').
+ b) If the client supplies this attribute, but the value is not
+ supported by the Printer object, i.e., the value is not one
+ of the values of the Printer object's "compression-
+ supported" attribute, the Printer object MUST reject the
+ request, and return the 'client-error-compression-not-
+ supported' status code. See section 3.1.7 for returning
+ unsupported attributes and values.
+
+
+
+
+Hastings, et al. Standards Track [Page 42]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ c) If the client supplies the attribute and the Printer object
+ supports the attribute value, the Printer object uses the
+ corresponding decompression algorithm on the document data.
+ d) If the decompression algorithm fails before the Printer
+ returns an operation response, the Printer object MUST
+ reject the request and return the 'client-error-
+ compression-error' status code.
+ e) If the decompression algorithm fails after the Printer
+ returns an operation response, the Printer object MUST abort
+ the job and add the 'compression-error' value to the job's
+ "job-state-reasons" attribute.
+ f) If the decompression algorithm succeeds, the document data
+ MUST then have the format specified by the job's "document-
+ format" attribute, if supplied (see "document-format"
+ operation attribute definition below).
+
+ "document-format" (mimeMediaType):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. The value of this
+ attribute identifies the format of the supplied document data.
+ The following cases exist:
+
+ a) If the client does not supply this attribute, the Printer
+ object assumes that the document data is in the format
+ defined by the Printer object's "document-format-default"
+ attribute. (i.e. the Printer follows the rules below as if
+ the client supplied the "document-format" attribute with a
+ value equal to the printer's default value).
+ b) If the client supplies this attribute, but the value is not
+ supported by the Printer object, i.e., the value is not one
+ of the values of the Printer object's "document-format-
+ supported" attribute, the Printer object MUST reject the
+ request and return the 'client-error-document-format-not-
+ supported' status code.
+ c) If the client supplies this attribute and its value is
+ 'application/octet-stream' (i.e. to be auto-sensed, see
+ Section 4.1.9.1), and the format is not one of the
+ document-formats that the Printer can auto-sense, and this
+ check occurs before the Printer returns an operation
+ response, then the Printer MUST reject the request and
+ return the 'client-error-document-format-not-supported'
+ status code.
+ d) If the client supplies this attribute, and the value is
+ supported by the Printer object, the Printer is capable of
+ interpreting the document data.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 43]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ e) If interpreting of the document data fails before the
+ Printer returns an operation response, the Printer object
+ MUST reject the request and return the 'client-error-
+ document-format-error' status code.
+ f) If interpreting of the document data fails after the Printer
+ returns an operation response, the Printer object MUST abort
+ the job and add the 'document-format-error' value to the
+ job's "job-state-reasons" attribute.
+
+ "document-natural-language" (naturalLanguage):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. This attribute
+ specifies the natural language of the document for those
+ document-formats that require a specification of the natural
+ language in order to image the document unambiguously. There
+ are no particular values required for the Printer object to
+ support.
+
+ "job-k-octets" (integer(0:MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-k-
+ octets-supported" attribute (see section 4.4.33). The client
+ supplied "job-k-octets" operation attribute identifies the
+ total size of the document(s) in K octets being submitted (see
+ section 4.3.17.1 for the complete semantics). If the client
+ supplies the attribute and the Printer object supports the
+ attribute, the value of the attribute is used to populate the
+ Job object's "job-k-octets" Job Description attribute.
+
+ For this attribute and the following two attributes ("job-
+ impressions", and "job-media-sheets"), if the client supplies
+ the attribute, but the Printer object does not support the
+ attribute, the Printer object ignores the client-supplied
+ value. If the client supplies the attribute and the Printer
+ supports the attribute, and the value is within the range of
+ the corresponding Printer object's "xxx-supported" attribute,
+ the Printer object MUST use the value to populate the Job
+ object's "xxx" attribute. If the client supplies the attribute
+ and the Printer supports the attribute, but the value is
+ outside the range of the corresponding Printer object's "xxx-
+ supported" attribute, the Printer object MUST copy the
+ attribute and its value to the Unsupported Attributes response
+ group, reject the request, and return the 'client-error-
+ attributes-or-values-not-supported' status code. If the client
+ does not supply the attribute, the Printer object MAY choose to
+ populate the corresponding Job object attribute depending on
+ whether the Printer object supports the attribute and is able
+ to calculate or discern the correct value.
+
+
+
+Hastings, et al. Standards Track [Page 44]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "job-impressions" (integer(0:MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-
+ impressions-supported" attribute (see section 4.4.34). The
+ client supplied "job-impressions" operation attribute
+ identifies the total size in number of impressions of the
+ document(s) being submitted (see section 4.3.17.2 for the
+ complete semantics).
+
+ See last paragraph under "job-k-octets".
+
+ "job-media-sheets" (integer(0:MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute and the "job-media-
+ sheets-supported" attribute (see section 4.4.35). The client
+ supplied "job-media-sheets" operation attribute identifies the
+ total number of media sheets to be produced for this job (see
+ section 4.3.17.3 for the complete semantics).
+
+ See last paragraph under "job-k-octets".
+
+ Group 2: Job Template Attributes
+
+ The client OPTIONALLY supplies a set of Job Template attributes as
+ defined in section 4.2. If the client is not supplying any Job
+ Template attributes in the request, the client SHOULD omit Group 2
+ rather than sending an empty group. However, a Printer object
+ MUST be able to accept an empty group.
+
+ Group 3: Document Content
+
+ The client MUST supply the document data to be processed.
+
+ In addition to the MANDATORY parameters required for every
+ operation request, the simplest Print-Job Request consists of just
+ the "attributes-charset" and "attributes-natural-language"
+ operation attributes; the "printer-uri" target operation
+ attribute; the Document Content and nothing else. In this simple
+ case, the Printer object:
+
+ - creates a new Job object (the Job object contains a single
+ document),
+ - stores a generated Job name in the "job-name" attribute in the
+ natural language and charset requested (see Section 3.1.4.1) (if
+ those are supported, otherwise using the Printer object's
+ default natural language and charset), and
+
+
+
+
+
+Hastings, et al. Standards Track [Page 45]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - at job processing time, uses its corresponding default value
+ attributes for the supported Job Template attributes that were
+ not supplied by the client as IPP attribute or embedded
+ instructions in the document data.
+
+3.2.1.2 Print-Job Response
+
+ The Printer object MUST return to the client the following sets of
+ attributes as part of the Print-Job Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6. If
+ the client supplies unsupported or conflicting Job Template
+ attributes or values, the Printer object MUST reject or accept
+ the Print-Job request depending on the whether the client
+ supplied a 'true' or 'false' value for the "ipp-attribute-
+ fidelity" operation attribute. See the Implementer's Guide
+ [IPP-IIG] for a complete description of the suggested steps for
+ processing a create request.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+ The value of the "ipp-attribute-fidelity" supplied by the client
+ does not affect what attributes the Printer object returns in this
+ group. The value of "ipp-attribute-fidelity" only affects whether
+ the Print-Job operation is accepted or rejected. If the job is
+ accepted, the client may query the job using the Get-Job-
+ Attributes operation requesting the unsupported attributes that
+ were returned in the create response to see which attributes were
+ ignored (not stored on the Job object) and which attributes were
+ stored with other (substituted) values.
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 46]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Group 3: Job Object Attributes
+
+ "job-uri" (uri):
+ The Printer object MUST return the Job object's URI by
+ returning the contents of the REQUIRED "job-uri" Job object
+ attribute. The client uses the Job object's URI when directing
+ operations at the Job object. The Printer object always uses
+ its configured security policy when creating the new URI.
+ However, if the Printer object supports more than one URI, the
+ Printer object also uses information about which URI was used
+ in the Print-Job Request to generated the new URI so that the
+ new URI references the correct access channel. In other words,
+ if the Print-Job Request comes in over a secure channel, the
+ Printer object MUST generate a Job URI that uses the secure
+ channel as well.
+
+ "job-id" (integer(1:MAX)):
+ The Printer object MUST return the Job object's Job ID by
+ returning the REQUIRED "job-id" Job object attribute. The
+ client uses this "job-id" attribute in conjunction with the
+ "printer-uri" attribute used in the Print-Job Request when
+ directing Job operations at the Printer object.
+
+ "job-state" (type1 enum):
+ The Printer object MUST return the Job object's REQUIRED "job-
+ state" attribute. The value of this attribute (along with the
+ value of the next attribute: "job-state-reasons") is taken
+ from a "snapshot" of the new Job object at some meaningful
+ point in time (implementation defined) between when the Printer
+ object receives the Print-Job Request and when the Printer
+ object returns the response.
+
+ "job-state-reasons" (1setOf type2 keyword):
+ The Printer object MUST return the Job object's REQUIRED "job-
+ state-reasons" attribute.
+
+ "job-state-message" (text(MAX)):
+ The Printer object OPTIONALLY returns the Job object's OPTIONAL
+ "job-state-message" attribute. If the Printer object supports
+ this attribute then it MUST be returned in the response. If
+ this attribute is not returned in the response, the client can
+ assume that the "job-state-message" attribute is not supported
+ and will not be returned in a subsequent Job object query.
+
+ "number-of-intervening-jobs" (integer(0:MAX)):
+ The Printer object OPTIONALLY returns the Job object's OPTIONAL
+ "number-of-intervening-jobs" attribute. If the Printer object
+ supports this attribute then it MUST be returned in the
+
+
+
+Hastings, et al. Standards Track [Page 47]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ response. If this attribute is not returned in the response,
+ the client can assume that the "number-of-intervening-jobs"
+ attribute is not supported and will not be returned in a
+ subsequent Job object query.
+
+ Note: Since any printer state information which affects a job's
+ state is reflected in the "job-state" and "job-state-reasons"
+ attributes, it is sufficient to return only these attributes
+ and no specific printer status attributes.
+
+ Note: In addition to the MANDATORY parameters required for every
+ operation response, the simplest response consists of the just the
+ "attributes-charset" and "attributes-natural-language" operation
+ attributes and the "job-uri", "job-id", and "job-state" Job Object
+ Attributes. In this simplest case, the status code is 'successful-
+ ok' and there is no "status-message" or "detailed-status-message"
+ operation attribute.
+
+3.2.2 Print-URI Operation
+
+ This OPTIONAL operation is identical to the Print-Job operation
+ (section 3.2.1) except that a client supplies a URI reference to the
+ document data using the "document-uri" (uri) operation attribute (in
+ Group 1) rather than including the document data itself. Before
+ returning the response, the Printer MUST validate that the Printer
+ supports the retrieval method (e.g., http, ftp, etc.) implied by the
+ URI, and MUST check for valid URI syntax. If the client-supplied URI
+ scheme is not supported, i.e. the value is not in the Printer
+ object's "referenced-uri-scheme-supported" attribute, the Printer
+ object MUST reject the request and return the 'client-error-uri-
+ scheme-not-supported' status code.
+
+ The IPP Printer MAY validate the accessibility of the document as
+ part of the operation or subsequently. If the Printer determines an
+ accessibility problem before returning an operation response, it
+ rejects the request and returns the 'client-error-document-access-
+ error' status code. The Printer MAY also return a specific document
+ access error code using the "document-access-error" operation
+ attribute (see section 3.1.6.4).
+
+ If the Printer determines this document accessibility problem after
+ accepting the request and returning an operation response with one of
+ the successful status codes, the Printer adds the 'document-access-
+ error' value to the job's "job-state-reasons" attribute and MAY
+ populate the job's "job-document-access-errors" Job Description
+ attribute (see section 4.3.11). See The Implementer's Guide [IPP-
+ IIG] for suggested additional checks.
+
+
+
+
+Hastings, et al. Standards Track [Page 48]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If the Printer object supports this operation, it MUST support the
+ "reference-uri-schemes-supported" Printer attribute (see section
+ 4.4.27).
+
+ It is up to the IPP object to interpret the URI and subsequently
+ "pull" the document from the source referenced by the URI string.
+
+3.2.3 Validate-Job Operation
+
+ This REQUIRED operation is similar to the Print-Job operation
+ (section 3.2.1) except that a client supplies no document data and
+ the Printer allocates no resources (i.e., it does not create a new
+ Job object). This operation is used only to verify capabilities of a
+ printer object against whatever attributes are supplied by the client
+ in the Validate-Job request. By using the Validate-Job operation a
+ client can validate that an identical Print-Job operation (with the
+ document data) would be accepted. The Validate-Job operation also
+ performs the same security negotiation as the Print-Job operation
+ (see section 8), so that a client can check that the client and
+ Printer object security requirements can be met before performing a
+ Print-Job operation.
+
+ The Validate-Job operation does not accept a "document-uri" attribute
+ in order to allow a client to check that the same Print-URI operation
+ will be accepted, since the client doesn't send the data with the
+ Print-URI operation. The client SHOULD just issue the Print-URI
+ request.
+
+ The Printer object returns the same status codes, Operation
+ Attributes (Group 1) and Unsupported Attributes (Group 2) as the
+ Print-Job operation. However, no Job Object Attributes (Group 3) are
+ returned, since no Job object is created.
+
+3.2.4 Create-Job Operation
+
+ This OPTIONAL operation is similar to the Print-Job operation
+ (section 3.2.1) except that in the Create-Job request, a client does
+ not supply document data or any reference to document data. Also,
+ the client does not supply any of the "document-name", "document-
+ format", "compression", or "document-natural-language" operation
+ attributes. This operation is followed by one or more Send-Document
+ or Send-URI operations. In each of those operation requests, the
+ client OPTIONALLY supplies the "document-name", "document-format",
+ and "document-natural-language" attributes for each document in the
+ multi-document Job object.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 49]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If a Printer object supports the Create-Job operation, it MUST also
+ support the Send-Document operation and also MAY support the Send-URI
+ operation.
+
+ If the Printer object supports this operation, it MUST support the
+ "multiple-operation-time-out" Printer attribute (see section 4.4.31).
+
+ If the Printer object supports this operation, then it MUST support
+ the "multiple-document-jobs-supported" Printer Description attribute
+ (see section 4.4.16) and indicate whether or not it supports
+ multiple-document jobs.
+
+ If the Printer object supports this operation and supports multiple
+ documents in a job, then it MUST support the "multiple-document-
+ handling" Job Template job attribute with at least one value (see
+ section 4.2.4) and the associated "multiple-document-handling-
+ default" and "multiple-document-handling-supported" Job Template
+ Printer attributes (see section 4.2).
+
+ After the Create-Job operation has completed, the value of the "job-
+ state" attribute is similar to the "job-state" after a Print-Job,
+ even though no document-data has arrived. A Printer MAY set the
+ 'job-data-insufficient' value of the job's "job-state-reason"
+ attribute to indicate that processing cannot begin until sufficient
+ data has arrived and set the "job-state" to either 'pending' or
+ 'pending-held'. A non-spooling printer that doesn't implement the
+ 'pending' job state may even set the "job-state" to 'processing',
+ even though there is not yet any data to process. See sections 4.3.7
+ and 4.3.8.
+
+3.2.5 Get-Printer-Attributes Operation
+
+ This REQUIRED operation allows a client to request the values of the
+ attributes of a Printer object. In the request, the client supplies
+ the set of Printer attribute names and/or attribute group names in
+ which the requester is interested. In the response, the Printer
+ object returns a corresponding attribute set with the appropriate
+ attribute values filled in.
+
+ For Printer objects, the possible names of attribute groups are:
+
+ - 'job-template': the subset of the Job Template attributes that
+ apply to a Printer object (the last two columns of the table in
+ Section 4.2) that the implementation supports for Printer
+ objects.
+ - 'printer-description': the subset of the attributes specified in
+ Section 4.4 that the implementation supports for Printer
+ objects.
+
+
+
+Hastings, et al. Standards Track [Page 50]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - 'all': the special group 'all' that includes all attributes that
+ the implementation supports for Printer objects.
+
+ Since a client MAY request specific attributes or named groups, there
+ is a potential that there is some overlap. For example, if a client
+ requests, 'printer-name' and 'all', the client is actually requesting
+ the "printer-name" attribute twice: once by naming it explicitly, and
+ once by inclusion in the 'all' group. In such cases, the Printer
+ object NEED NOT return each attribute only once in the response even
+ if it is requested multiple times. The client SHOULD NOT request the
+ same attribute in multiple ways.
+
+ It is NOT REQUIRED that a Printer object support all attributes
+ belonging to a group (since some attributes are OPTIONAL). However,
+ it is REQUIRED that each Printer object support all group names.
+
+3.2.5.1 Get-Printer-Attributes Request
+
+ The following sets of attributes are part of the Get-Printer-
+ Attributes Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "requested-attributes" (1setOf keyword):
+ The client OPTIONALLY supplies a set of attribute names and/or
+ attribute group names in whose values the requester is
+ interested. The Printer object MUST support this attribute.
+ If the client omits this attribute, the Printer MUST respond as
+ if this attribute had been supplied with a value of 'all'.
+
+ "document-format" (mimeMediaType):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. This attribute is useful
+ for a Printer object to determine the set of supported
+ attribute values that relate to the requested document format.
+ The Printer object MUST return the attributes and values that
+
+
+
+Hastings, et al. Standards Track [Page 51]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ it uses to validate a job on a create or Validate-Job operation
+ in which this document format is supplied. The Printer object
+ SHOULD return only (1) those attributes that are supported for
+ the specified format and (2) the attribute values that are
+ supported for the specified document format. By specifying the
+ document format, the client can get the Printer object to
+ eliminate the attributes and values that are not supported for
+ a specific document format. For example, a Printer object
+ might have multiple interpreters to support both
+ 'application/postscript' (for PostScript) and 'text/plain' (for
+ text) documents. However, for only one of those interpreters
+ might the Printer object be able to support "number-up" with
+ values of '1', '2', and '4'. For the other interpreter it
+ might be able to only support "number-up" with a value of '1'.
+ Thus a client can use the Get-Printer-Attributes operation to
+ obtain the attributes and values that will be used to
+ accept/reject a create job operation.
+
+ If the Printer object does not distinguish between different
+ sets of supported values for each different document format
+ when validating jobs in the create and Validate-Job operations,
+ it MUST NOT distinguish between different document formats in
+ the Get-Printer-Attributes operation. If the Printer object
+ does distinguish between different sets of supported values for
+ each different document format specified by the client, this
+ specialization applies only to the following Printer object
+ attributes:
+
+ - Printer attributes that are Job Template attributes ("xxx-
+ default" "xxx-supported", and "xxx-ready" in the Table in
+ Section 4.2),
+ - "pdl-override-supported",
+ - "compression-supported",
+ - "job-k-octets-supported",
+ - "job-impressions-supported",
+ - "job-media-sheets-supported",
+ - "printer-driver-installer",
+ - "color-supported", and
+ - "reference-uri-schemes-supported"
+
+ The values of all other Printer object attributes (including
+ "document-format-supported") remain invariant with respect to the
+ client supplied document format (except for new Printer
+ description attribute as registered according to section 6.2).
+
+ If the client omits this "document-format" operation attribute,
+ the Printer object MUST respond as if the attribute had been
+ supplied with the value of the Printer object's "document-format-
+
+
+
+Hastings, et al. Standards Track [Page 52]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ default" attribute. It is RECOMMENDED that the client always
+ supply a value for "document-format", since the Printer object's
+ "document-format-default" may be 'application/octet-stream', in
+ which case the returned attributes and values are for the union of
+ the document formats that the Printer can automatically sense.
+ For more details, see the description of the 'mimeMediaType'
+ attribute syntax in section 4.1.9.
+
+ If the client supplies a value for the "document-format" Operation
+ attribute that is not supported by the Printer, i.e., is not among
+ the values of the Printer object's "document-format-supported"
+ attribute, the Printer object MUST reject the operation and return
+ the 'client-error-document-format-not-supported' status code.
+
+3.2.5.2 Get-Printer-Attributes Response
+
+ The Printer object returns the following sets of attributes as part
+ of the Get-Printer-Attributes Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+ The response NEED NOT contain the "requested-attributes" operation
+ attribute with any supplied values (attribute keywords) that were
+ requested by the client but are not supported by the IPP object.
+ If the Printer object does return unsupported attributes
+ referenced in the "requested-attributes" operation attribute and
+ that attribute included group names, such as 'all', the
+ unsupported attributes MUST NOT include attributes described in
+ the standard but not supported by the implementation.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 53]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Group 3: Printer Object Attributes
+
+ This is the set of requested attributes and their current values.
+ The Printer object ignores (does not respond with) any requested
+ attribute which is not supported. The Printer object MAY respond
+ with a subset of the supported attributes and values, depending on
+ the security policy in force. However, the Printer object MUST
+ respond with the 'unknown' value for any supported attribute
+ (including all REQUIRED attributes) for which the Printer object
+ does not know the value. Also the Printer object MUST respond
+ with the 'no-value' for any supported attribute (including all
+ REQUIRED attributes) for which the system administrator has not
+ configured a value. See the description of the "out-of-band"
+ values in the beginning of Section 4.1.
+
+3.2.6 Get-Jobs Operation
+
+ This REQUIRED operation allows a client to retrieve the list of Job
+ objects belonging to the target Printer object. The client may also
+ supply a list of Job attribute names and/or attribute group names. A
+ group of Job object attributes will be returned for each Job object
+ that is returned.
+
+ This operation is similar to the Get-Job-Attributes operation, except
+ that this Get-Jobs operation returns attributes from possibly more
+ than one object.
+
+3.2.6.1 Get-Jobs Request
+
+ The client submits the Get-Jobs request to a Printer object.
+
+ The following groups of attributes are part of the Get-Jobs Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 54]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "limit" (integer(1:MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It is an integer value that
+ determines the maximum number of jobs that a client will
+ receive from the Printer even if "which-jobs" or "my-jobs"
+ constrain which jobs are returned. The limit is a "stateless
+ limit" in that if the value supplied by the client is 'N', then
+ only the first 'N' jobs are returned in the Get-Jobs Response.
+ There is no mechanism to allow for the next 'M' jobs after the
+ first 'N' jobs. If the client does not supply this attribute,
+ the Printer object responds with all applicable jobs.
+
+ "requested-attributes" (1setOf type2 keyword):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It is a set of Job
+ attribute names and/or attribute groups names in whose values
+ the requester is interested. This set of attributes is
+ returned for each Job object that is returned. The allowed
+ attribute group names are the same as those defined in the
+ Get-Job-Attributes operation in section 3.3.4. If the client
+ does not supply this attribute, the Printer MUST respond as if
+ the client had supplied this attribute with two values: 'job-
+ uri' and 'job-id'.
+
+ "which-jobs" (type2 keyword):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It indicates which Job
+ objects MUST be returned by the Printer object. The values for
+ this attribute are:
+
+ 'completed': This includes any Job object whose state is
+ 'completed', 'canceled', or 'aborted'.
+ 'not-completed': This includes any Job object whose state is
+ 'pending', 'processing', 'processing-stopped', or 'pending-
+ held'.
+
+ A Printer object MUST support both values. However, if the
+ implementation does not keep jobs in the 'completed',
+ 'canceled', and 'aborted' states, then it returns no jobs when
+ the 'completed' value is supplied.
+
+ If a client supplies some other value, the Printer object MUST
+ copy the attribute and the unsupported value to the Unsupported
+ Attributes response group, reject the request, and return the
+ 'client-error-attributes-or-values-not-supported' status code.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 55]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If the client does not supply this attribute, the Printer
+ object MUST respond as if the client had supplied the attribute
+ with a value of 'not-completed'.
+
+ "my-jobs" (boolean):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It indicates whether jobs
+ from all users or just the jobs submitted by the requesting
+ user of this request MUST be considered as candidate jobs to be
+ returned by the Printer object. If the client does not supply
+ this attribute, the Printer object MUST respond as if the
+ client had supplied the attribute with a value of 'false',
+ i.e., jobs from all users. The means for authenticating the
+ requesting user and matching the jobs is described in section
+ 8.
+
+3.2.6.2 Get-Jobs Response
+
+ The Printer object returns all of the Job objects up to the number
+ specified by the "limit" attribute that match the criteria as defined
+ by the attribute values supplied by the client in the request. It is
+ possible that no Job objects are returned since there may literally
+ be no Job objects at the Printer, or there may be no Job objects that
+ match the criteria supplied by the client. If the client requests
+ any Job attributes at all, there is a set of Job Object Attributes
+ returned for each Job object.
+
+ It is not an error for the Printer to return 0 jobs. If the response
+ returns 0 jobs because there are no jobs matching the criteria, and
+ the request would have returned 1 or more jobs with a status code of
+ 'successful-ok' if there had been jobs matching the criteria, then
+ the status code for 0 jobs MUST be 'successful-ok'.
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 56]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+ The response NEED NOT contain the "requested-attributes" operation
+ attribute with any supplied values (attribute keywords) that were
+ requested by the client but are not supported by the IPP object.
+ If the Printer object does return unsupported attributes
+ referenced in the "requested-attributes" operation attribute and
+ that attribute included group names, such as 'all', the
+ unsupported attributes MUST NOT include attributes described in
+ the standard but not supported by the implementation.
+
+ Groups 3 to N: Job Object Attributes
+
+ The Printer object responds with one set of Job Object Attributes
+ for each returned Job object. The Printer object ignores (does
+ not respond with) any requested attribute or value which is not
+ supported or which is restricted by the security policy in force,
+ including whether the requesting user is the user that submitted
+ the job (job originating user) or not (see section 8). However,
+ the Printer object MUST respond with the 'unknown' value for any
+ supported attribute (including all REQUIRED attributes) for which
+ the Printer object does not know the value, unless it would
+ violate the security policy. See the description of the "out-of-
+ band" values in the beginning of Section 4.1.
+
+ Jobs are returned in the following order:
+
+ - If the client requests all 'completed' Jobs (Jobs in the
+ 'completed', 'aborted', or 'canceled' states), then the Jobs are
+ returned newest to oldest (with respect to actual completion
+ time)
+ - If the client requests all 'not-completed' Jobs (Jobs in the
+ 'pending', 'processing', 'pending-held', and 'processing-
+ stopped' states), then Jobs are returned in relative
+ chronological order of expected time to complete (based on
+ whatever scheduling algorithm is configured for the Printer
+ object).
+
+3.2.7 Pause-Printer Operation
+
+ This OPTIONAL operation allows a client to stop the Printer object
+ from scheduling jobs on all its devices. Depending on
+ implementation, the Pause-Printer operation MAY also stop the Printer
+ from processing the current job or jobs. Any job that is currently
+ being printed is either stopped as soon as the implementation permits
+
+
+
+
+Hastings, et al. Standards Track [Page 57]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ or is completed, depending on implementation. The Printer object
+ MUST still accept create operations to create new jobs, but MUST
+ prevent any jobs from entering the 'processing' state.
+
+ If the Pause-Printer operation is supported, then the Resume-Printer
+ operation MUST be supported, and vice-versa.
+
+ The IPP Printer stops the current job(s) on its device(s) that were
+ in the 'processing' or 'processing-stopped' states as soon as the
+ implementation permits. If the implementation will take appreciable
+ time to stop, the IPP Printer adds the 'moving-to-paused' value to
+ the Printer object's "printer-state-reasons" attribute (see section
+ 4.4.12). When the device(s) have all stopped, the IPP Printer
+ transitions the Printer object to the 'stopped' state, removes the
+ 'moving-to-paused' value, if present, and adds the 'paused' value to
+ the Printer object's "printer-state-reasons" attribute.
+
+ When the current job(s) complete that were in the 'processing' state,
+ the IPP Printer transitions them to the 'completed' state. When the
+ current job(s) stop in mid processing that were in the 'processing'
+ state, the IPP Printer transitions them to the 'processing-stopped'
+ state and adds the 'printer-stopped' value to the job's "job-state-
+ reasons" attribute.
+
+ For any jobs that are 'pending' or 'pending-held', the 'printer-
+ stopped' value of the jobs' "job-state-reasons" attribute also
+ applies. However, the IPP Printer NEED NOT update those jobs' "job-
+ state-reasons" attributes and only need return the 'printer-stopped'
+ value when those jobs are queried (so-called "lazy evaluation").
+
+ Whether the Pause-Printer operation affects jobs that were submitted
+ to the device from other sources than the IPP Printer object in the
+ same way that the Pause-Printer operation affects jobs that were
+ submitted to the IPP Printer object using IPP, depends on
+ implementation, i.e., on whether the IPP protocol is being used as a
+ universal management protocol or just to manage IPP jobs,
+ respectively.
+
+ The IPP Printer MUST accept the request in any state and transition
+ the Printer to the indicated new "printer-state" before returning as
+ follows:
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 58]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Current New "printer IPP Printer's response status
+ "printer- "printer- -state- code and action:
+ state" state" reasons"
+
+ 'idle' 'stopped' 'paused' 'successful-ok'
+ 'processing' 'processing' 'moving- OPTION 1: 'successful-ok';
+ to- Later, when all output has
+ paused' stopped, the "printer-state"
+ becomes 'stopped', and the
+ 'paused' value replaces the
+ 'moving-to-paused' value in the
+ "printer-state-reasons"
+ attribute
+ 'processing' 'stopped' 'paused' OPTION 2: 'successful-ok';
+ all device output stopped
+ immediately
+ 'stopped' 'stopped' 'paused' 'successful-ok'
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must be an operator or administrator of the Printer
+ object (see Sections 1 and 8.5). Otherwise, the IPP Printer MUST
+ reject the operation and return: 'client-error-forbidden', 'client-
+ error-not-authenticated', or 'client-error-not-authorized' as
+ appropriate.
+
+3.2.7.1 Pause-Printer Request
+
+ The following groups of attributes are part of the Pause-Printer
+ Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute which is the target
+ for this operation as described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 59]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.2.7.2 Pause-Printer Response
+
+ The following groups of attributes are part of the Pause-Printer
+ Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+3.2.8 Resume-Printer Operation
+
+ This operation allows a client to resume the Printer object
+ scheduling jobs on all its devices. The Printer object MUST remove
+ the 'paused' and 'moving-to-paused' values from the Printer object's
+ "printer-state-reasons" attribute, if present. If there are no other
+ reasons to keep a device paused (such as media-jam), the IPP Printer
+ is free to transition itself to the 'processing' or 'idle' states,
+ depending on whether there are jobs to be processed or not,
+ respectively, and the device(s) resume processing jobs.
+
+ If the Pause-Printer operation is supported, then the Resume-Printer
+ operation MUST be supported, and vice-versa.
+
+ The IPP Printer removes the 'printer-stopped' value from any job's
+ "job-state-reasons" attributes contained in that Printer.
+
+ The IPP Printer MUST accept the request in any state, transition the
+ Printer object to the indicated new state as follows:
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 60]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Current New "printer- IPP Printer's response status code and
+ "printer- state" action:
+ state"
+
+ 'idle' 'idle' 'successful-ok'
+ 'processing' 'processing' 'successful-ok'
+
+ 'stopped' 'processing' 'successful-ok';
+ when there are jobs to be processed
+ 'stopped' 'idle' 'successful-ok';
+ when there are no jobs to be processed.
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must be an operator or administrator of the Printer
+ object (see Sections 1 and 8.5). Otherwise, the IPP Printer MUST
+ reject the operation and return: 'client-error-forbidden', 'client-
+ error-not-authenticated', or 'client-error-not-authorized' as
+ appropriate.
+
+ The Resume-Printer Request and Resume-Printer Response have the same
+ attribute groups and attributes as the Pause-Printer operation (see
+ sections 3.2.7.1 and 3.2.7.2).
+
+3.2.9 Purge-Jobs Operation
+
+ This OPTIONAL operation allows a client to remove all jobs from an
+ IPP Printer object, regardless of their job states, including jobs in
+ the Printer object's Job History (see Section 4.3.7.2). After a
+ Purge-Jobs operation has been performed, a Printer object MUST return
+ no jobs in subsequent Get-Job-Attributes and Get-Jobs responses
+ (until new jobs are submitted).
+
+ Whether the Purge-Jobs (and Get-Jobs) operation affects jobs that
+ were submitted to the device from other sources than the IPP Printer
+ object in the same way that the Purge-Jobs operation affects jobs
+ that were submitted to the IPP Printer object using IPP, depends on
+ implementation, i.e., on whether the IPP protocol is being used as a
+ universal management protocol or just to manage IPP jobs,
+ respectively.
+
+ Note: if an operator wants to cancel all jobs without clearing out
+ the Job History, the operator uses the Cancel-Job operation on each
+ job instead of using the Purge-Jobs operation.
+
+ The Printer object MUST accept this operation in any state and
+ transition the Printer object to the 'idle' state.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 61]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must be an operator or administrator of the Printer
+ object (see Sections 1 and 8.5). Otherwise, the IPP object MUST
+ reject the operation and return: client-error-forbidden, client-
+ error-not-authenticated, and client-error-not-authorized as
+ appropriate.
+
+ The Purge-Jobs Request and Purge-Jobs Response have the same
+ attribute groups and attributes as the Pause-Printer operation (see
+ sections 3.2.7.1 and 3.2.7.2).
+
+3.3 Job Operations
+
+ All Job operations are directed at Job objects. A client MUST always
+ supply some means of identifying the Job object in order to identify
+ the correct target of the operation. That job identification MAY
+ either be a single Job URI or a combination of a Printer URI with a
+ Job ID. The IPP object implementation MUST support both forms of
+ identification for every job.
+
+3.3.1 Send-Document Operation
+
+ This OPTIONAL operation allows a client to create a multi-document
+ Job object that is initially "empty" (contains no documents). In the
+ Create-Job response, the Printer object returns the Job object's URI
+ (the "job-uri" attribute) and the Job object's 32-bit identifier (the
+ "job-id" attribute). For each new document that the client desires
+ to add, the client uses a Send-Document operation. Each Send-
+ Document Request contains the entire stream of document data for one
+ document.
+
+ If the Printer supports this operation but does not support multiple
+ documents per job, the Printer MUST reject subsequent Send-Document
+ operations supplied with data and return the 'server-error-multiple-
+ document-jobs-not-supported'. However, the Printer MUST accept the
+ first document with a 'true' or 'false' value for the "last-document"
+ operation attribute (see below), so that clients MAY always submit
+ one document jobs with a 'false' value for "last-document" in the
+ first Send-Document and a 'true' for "last-document" in the second
+ Send-Document (with no data).
+
+ Since the Create-Job and the send operations (Send-Document or Send-
+ URI operations) that follow could occur over an arbitrarily long
+ period of time for a particular job, a client MUST send another send
+ operation within an IPP Printer defined minimum time interval after
+ the receipt of the previous request for the job. If a Printer object
+ supports the Create-Job and Send-Document operations, the Printer
+ object MUST support the "multiple-operation-time-out" attribute (see
+
+
+
+Hastings, et al. Standards Track [Page 62]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ section 4.4.31). This attribute indicates the minimum number of
+ seconds the Printer object will wait for the next send operation
+ before taking some recovery action.
+
+ An IPP object MUST recover from an errant client that does not supply
+ a send operation, sometime after the minimum time interval specified
+ by the Printer object's "multiple-operation-time-out" attribute.
+ Such recovery MAY include any of the following or other recovery
+ actions:
+
+ 1. Assume that the Job is an invalid job, start the process of
+ changing the job state to 'aborted', add the 'aborted-by-
+ system' value to the job's "job-state-reasons" attribute (see
+ section 4.3.8), and clean up all resources associated with the
+ Job. In this case, if another send operation is finally
+ received, the Printer responds with an "client-error-not-
+ possible" or "client-error-not-found" depending on whether or
+ not the Job object is still around when the send operation
+ finally arrives.
+ 2. Assume that the last send operation received was in fact the
+ last document (as if the "last-document" flag had been set to
+ 'true'), close the Job object, and proceed to process it (i.e.,
+ move the Job's state to 'pending').
+ 3. Assume that the last send operation received was in fact the
+ last document, close the Job, but move it to the 'pending-held'
+ and add the 'submission-interrupted' value to the job's "job-
+ state-reasons" attribute (see section 4.3.8). This action
+ allows the user or an operator to determine whether to continue
+ processing the Job by moving it back to the 'pending' state
+ using the Release-Job operation (see section 3.3.6) or to
+ cancel the job using the Cancel-Job operation (see section
+ 3.3.3).
+
+ Each implementation is free to decide the "best" action to take
+ depending on local policy, whether any documents have been added,
+ whether the implementation spools jobs or not, and/or any other
+ piece of information available to it. If the choice is to abort the
+ Job object, it is possible that the Job object may already have been
+ processed to the point that some media sheet pages have been printed.
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must either be the job owner (as determined in the
+ Create-Job operation) or an operator or administrator of the Printer
+ object (see Sections 1 and 8.5). Otherwise, the IPP object MUST
+ reject the operation and return: 'client-error-forbidden', 'client-
+ error-not-authenticated', or 'client-error-not-authorized' as
+ appropriate.
+
+
+
+
+Hastings, et al. Standards Track [Page 63]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.3.1.1 Send-Document Request
+
+ The following attribute sets are part of the Send-Document Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX))or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "document-name" (name(MAX)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. It contains the client
+ supplied document name. The document name MAY be different than
+ the Job name. It might be helpful, but NEED NOT be unique
+ across multiple documents in the same Job. Typically, the
+ client software automatically supplies the document name on
+ behalf of the end user by using a file name or an application
+ generated name. See the description of the "document-name"
+ operation attribute in the Print-Job Request (section 3.2.1.1)
+ for more information about this attribute.
+
+ "compression" (type3 keyword):
+ See the description of "compression" for the Print-Job operation
+ in Section 3.2.1.1.
+
+ "document-format" (mimeMediaType):
+ See the description of "document-format" for the Print-Job
+ operation in Section 3.2.1.1.
+
+ "document-natural-language" (naturalLanguage):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. This attribute
+ specifies the natural language of the document for those
+ document-formats that require a specification of the natural
+ language in order to image the document unambiguously. There
+ are no particular values required for the Printer object to
+ support.
+
+
+
+Hastings, et al. Standards Track [Page 64]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "last-document" (boolean):
+ The client MUST supply this attribute. The Printer object MUST
+ support this attribute. It is a boolean flag that is set to
+ 'true' if this is the last document for the Job, 'false'
+ otherwise.
+
+ Group 2: Document Content
+
+ The client MUST supply the document data if the "last-document"
+ flag is set to 'false'. However, since a client might not know
+ that the previous document sent with a Send-Document (or Send-URI)
+ operation was the last document (i.e., the "last-document"
+ attribute was set to 'false'), it is legal to send a Send-Document
+ request with no document data where the "last-document" flag is
+ set to 'true'. Such a request MUST NOT increment the value of the
+ Job object's "number-of-documents" attribute, since no real
+ document was added to the job. It is not an error for a client to
+ submit a job with no actual document data, i.e., only a single
+ Create-Job and Send-Document request with a "last-document"
+ operation attribute set to 'true' with no document data.
+
+3.3.1.2 Send-Document Response
+
+ The following sets of attributes are part of the Send-Document
+ Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+ Group 3: Job Object Attributes
+
+ This is the same set of attributes as described in the Print-Job
+ response (see section 3.2.1.2).
+
+
+
+
+
+Hastings, et al. Standards Track [Page 65]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.3.2 Send-URI Operation
+
+ This OPTIONAL operation is identical to the Send-Document operation
+ (see section 3.3.1) except that a client MUST supply a URI reference
+ ("document-uri" operation attribute) rather than the document data
+ itself. If a Printer object supports this operation, clients can use
+ both Send-URI or Send-Document operations to add new documents to an
+ existing multi-document Job object. However, if a client needs to
+ indicate that the previous Send-URI or Send-Document was the last
+ document, the client MUST use the Send-Document operation with no
+ document data and the "last-document" flag set to 'true' (rather than
+ using a Send-URI operation with no "document-uri" operation
+ attribute).
+
+ If a Printer object supports this operation, it MUST also support the
+ Print-URI operation (see section 3.2.2).
+
+ The Printer object MUST validate the syntax and URI scheme of the
+ supplied URI before returning a response, just as in the Print-URI
+ operation. The IPP Printer MAY validate the accessibility of the
+ document as part of the operation or subsequently (see section
+ 3.2.2).
+
+3.3.3 Cancel-Job Operation
+
+ This REQUIRED operation allows a client to cancel a Print Job from
+ the time the job is created up to the time it is completed, canceled,
+ or aborted. Since a Job might already be printing by the time a
+ Cancel-Job is received, some media sheet pages might be printed
+ before the job is actually terminated.
+
+ The IPP object MUST accept or reject the request based on the job's
+ current state and transition the job to the indicated new state as
+ follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 66]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Current "job- New "job- IPP object's response status
+ state" state" code and action:
+
+ 'pending' 'canceled' 'successful-ok'
+ 'pending-held' 'canceled' 'successful-ok'
+ 'processing' 'canceled' 'successful-ok'
+ 'processing' 'processing' 'successful-ok' See Rule 1
+ 'processing' 'processing' 'client-error-not-possible'
+ See Rule 2
+ 'processing- 'canceled' 'successful-ok'
+ stopped'
+ 'processing- 'processing- 'successful-ok' See Rule 1
+ stopped' stopped'
+ 'processing- 'processing- 'client-error-not-possible'
+ stopped' stopped' See Rule 2
+ 'completed' 'completed' 'client-error-not-possible'
+ 'canceled' 'canceled' 'client-error-not-possible'
+ 'aborted' 'aborted' 'client-error-not-possible'
+
+ Rule 1: If the implementation requires some measurable time to
+ cancel the job in the 'processing' or 'processing-stopped' job
+ states, the IPP object MUST add the 'processing-to-stop-point' value
+ to the job's "job-state-reasons" attribute and then transition the
+ job to the 'canceled' state when the processing ceases (see section
+ 4.3.8).
+
+ Rule 2: If the Job object already has the 'processing-to-stop-point'
+ value in its "job-state-reasons" attribute, then the Printer object
+ MUST reject a Cancel-Job operation.
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must either be the job owner or an operator or
+ administrator of the Printer object (see Sections 1 and 8.5).
+ Otherwise, the IPP object MUST reject the operation and return:
+ 'client-error-forbidden', 'client-error-not-authenticated', or
+ 'client-error-not-authorized' as appropriate.
+
+3.3.3.1 Cancel-Job Request
+
+ The following groups of attributes are part of the Cancel-Job
+ Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+
+
+
+Hastings, et al. Standards Track [Page 67]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX))or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "message" (text(127)):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object OPTIONALLY supports this attribute. It is a message to
+ the operator. This "message" attribute is not the same as the
+ "job-message-from-operator" attribute. That attribute is used
+ to report a message from the operator to the end user that
+ queries that attribute. This "message" operation attribute is
+ used to send a message from the client to the operator along
+ with the operation request. It is an implementation decision
+ of how or where to display this message to the operator (if at
+ all).
+
+3.3.3.2 Cancel-Job Response
+
+ The following sets of attributes are part of the Cancel-Job Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+ Once a successful response has been sent, the implementation
+ guarantees that the Job will eventually end up in the 'canceled'
+ state. Between the time of the Cancel-Job operation is accepted and
+ when the job enters the 'canceled' job-state (see section 4.3.7), the
+ "job-state-reasons" attribute SHOULD contain the 'processing-to-
+ stop-point'
+
+
+
+Hastings, et al. Standards Track [Page 68]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ value which indicates to later queries that although the Job might
+ still be 'processing', it will eventually end up in the
+ 'canceled' state, not the 'completed' state.
+
+3.3.4 Get-Job-Attributes Operation
+
+ This REQUIRED operation allows a client to request the values of
+ attributes of a Job object and it is almost identical to the Get-
+ Printer-Attributes operation (see section 3.2.5). The only
+ differences are that the operation is directed at a Job object rather
+ than a Printer object, there is no "document-format" operation
+ attribute used when querying a Job object, and the returned attribute
+ group is a set of Job object attributes rather than a set of Printer
+ object attributes.
+
+ For Jobs, the possible names of attribute groups are:
+
+ - 'job-template': the subset of the Job Template attributes that
+ apply to a Job object (the first column of the table in Section
+ 4.2) that the implementation supports for Job objects.
+ - 'job-description': the subset of the Job Description attributes
+ specified in Section 4.3 that the implementation supports for
+ Job objects.
+ - 'all': the special group 'all' that includes all attributes that
+ the implementation supports for Job objects.
+
+ Since a client MAY request specific attributes or named groups, there
+ is a potential that there is some overlap. For example, if a client
+ requests, 'job-name' and 'job-description', the client is actually
+ requesting the "job-name" attribute once by naming it explicitly, and
+ once by inclusion in the 'job-description' group. In such cases, the
+ Printer object NEED NOT return the attribute only once in the
+ response even if it is requested multiple times. The client SHOULD
+ NOT request the same attribute in multiple ways.
+
+ It is NOT REQUIRED that a Job object support all attributes belonging
+ to a group (since some attributes are OPTIONAL). However it is
+ REQUIRED that each Job object support all these group names.
+
+3.3.4.1 Get-Job-Attributes Request
+
+ The following groups of attributes are part of the Get-Job-Attributes
+ Request when the request is directed at a Job object:
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 69]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.1.
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX)) or (2) the "job-uri" (uri) operation
+ attribute(s) which define the target for this operation as
+ described in section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client as described in section 8.3.
+
+ "requested-attributes" (1setOf keyword):
+ The client OPTIONALLY supplies this attribute. The IPP object
+ MUST support this attribute. It is a set of attribute names
+ and/or attribute group names in whose values the requester is
+ interested. If the client omits this attribute, the IPP object
+ MUST respond as if this attribute had been supplied with a value
+ of 'all'.
+
+3.3.4.2 Get-Job-Attributes Response
+
+ The Printer object returns the following sets of attributes as part
+ of the Get-Job-Attributes Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in sections 13 and 3.1.6.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in section 3.1.4.2. The "attributes-
+ natural-language" MAY be the natural language of the Job
+ object, rather than the one requested.
+
+ Group 2: Unsupported Attributes
+
+ See section 3.1.7 for details on returning Unsupported Attributes.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 70]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The response NEED NOT contain the "requested-attributes" operation
+ attribute with any supplied values (attribute keywords) that were
+ requested by the client but are not supported by the IPP object.
+ If the Printer object does return unsupported attributes
+ referenced in the "requested-attributes" operation attribute and
+ that attribute included group names, such as 'all', the
+ unsupported attributes MUST NOT include attributes described in
+ the standard but not supported by the implementation.
+
+ Group 3: Job Object Attributes
+
+ This is the set of requested attributes and their current values.
+ The IPP object ignores (does not respond with) any requested
+ attribute or value which is not supported or which is restricted
+ by the security policy in force, including whether the requesting
+ user is the user that submitted the job (job originating user) or
+ not (see section 8). However, the IPP object MUST respond with
+ the 'unknown' value for any supported attribute (including all
+ REQUIRED attributes) for which the IPP object does not know the
+ value, unless it would violate the security policy. See the
+ description of the "out-of-band" values in the beginning of
+ Section 4.1.
+
+3.3.5 Hold-Job Operation
+
+ This OPTIONAL operation allows a client to hold a pending job in the
+ queue so that it is not eligible for scheduling. If the Hold-Job
+ operation is supported, then the Release-Job operation MUST be
+ supported, and vice-versa. The OPTIONAL "job-hold-until" operation
+ attribute allows a client to specify whether to hold the job
+ indefinitely or until a specified time period, if supported.
+
+ The IPP object MUST accept or reject the request based on the job's
+ current state and transition the job to the indicated new state as
+ follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 71]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Current "job- New "job-state" IPP object's response status
+ state" code and action:
+
+ 'pending' 'pending-held' 'successful-ok' See Rule 1
+ 'pending' 'pending' 'successful-ok' See Rule 2
+ 'pending-held' 'pending-held' 'successful-ok' See Rule 1
+ 'pending-held' 'pending' 'successful-ok' See Rule 2
+ 'processing' 'processing' 'client-error-not-possible'
+ 'processing- 'processing- 'client-error-not-possible'
+ stopped' stopped'
+ 'completed' 'completed' 'client-error-not-possible'
+ 'canceled' 'canceled' 'client-error-not-possible'
+ 'aborted' 'aborted' 'client-error-not-possible'
+
+ Rule 1: If the implementation supports multiple reasons for a job to
+ be in the 'pending-held' state, the IPP object MUST add the 'job-
+ hold-until-specified' value to the job's "job-state-reasons"
+ attribute.
+
+ Rule 2: If the IPP object supports the "job-hold-until" operation
+ attribute, but the specified time period has already started (or is
+ the 'no-hold' value) and there are no other reasons to hold the job,
+ the IPP object MUST make the job be a candidate for processing
+ immediately (see Section 4.2.2) by putting the job in the 'pending'
+ state.
+
+ Note: In order to keep the Hold-Job operation simple, such a request
+ is rejected when the job is in the 'processing' or 'processing-
+ stopped' states. If an operation is needed to hold jobs while in
+ these states, it will be added as an additional operation, rather
+ than overloading the Hold-Job operation. Then it is clear to clients
+ by querying the Printer object's "operations-supported" (see Section
+ 4.4.15) and the Job object's "job-state" (see Section 4.3.7)
+ attributes which operations are possible.
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must either be the job owner or an operator or
+ administrator of the Printer object (see Sections 1 and 8.5).
+ Otherwise, the IPP object MUST reject the operation and return:
+ 'client-error-forbidden', 'client-error-not-authenticated', or
+ 'client-error-not-authorized' as appropriate.
+
+3.3.5.1 Hold-Job Request
+
+ The groups and operation attributes are the same as for a Cancel-Job
+ request (see section 3.3.3.1), with the addition of the following
+ Group 1 Operation attribute:
+
+
+
+
+Hastings, et al. Standards Track [Page 72]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "job-hold-until" (type3 keyword | name(MAX)):
+ The client OPTIONALLY supplies this Operation attribute. The
+ IPP object MUST support this operation attribute in a Hold-Job
+ request, if it supports the "job-hold-until" Job template
+ attribute in create operations. See section 4.2.2. The IPP
+ object SHOULD support the "job-hold-until" Job Template
+ attribute for use in job create operations with at least the
+ 'indefinite' value, if it supports the Hold-Job operation.
+ Otherwise, a client cannot create a job and hold it immediately
+ (without picking some supported time period in the future).
+
+ If supplied and supported as specified in the Printer's "job-
+ hold-until-supported" attribute, the IPP object copies the
+ supplied operation attribute to the Job object, replacing the
+ job's previous "job-hold-until" attribute, if present, and
+ makes the job a candidate for scheduling during the supplied
+ named time period.
+
+ If supplied, but either the "job-hold-until" Operation
+ attribute itself or the value supplied is not supported, the
+ IPP object accepts the request, returns the unsupported
+ attribute or value in the Unsupported Attributes Group
+ according to section 3.1.7, returns the 'successful-ok-
+ ignored-or-substituted-attributes, and holds the job
+ indefinitely until a client performs a subsequent Release-Job
+ operation.
+
+ If the client (1) supplies a value that specifies a time period
+ that has already started or the 'no-hold' value (meaning don't
+ hold the job) and (2) the IPP object supports the "job-hold-
+ until" operation attribute and there are no other reasons to
+ hold the job, the IPP object MUST accept the operation and make
+ the job be a candidate for processing immediately (see Section
+ 4.2.2).
+
+ If the client does not supply a "job-hold-until" Operation
+ attribute in the request, the IPP object MUST populate the job
+ object with a "job-hold-until" attribute with the 'indefinite'
+ value (if IPP object supports the "job-hold-until" attribute)
+ and hold the job indefinitely, until a client performs a
+ Release-Job operation.
+
+3.3.5.2 Hold-Job Response
+
+ The groups and attributes are the same as for a Cancel-Job response
+ (see section 3.3.3.2).
+
+
+
+
+
+Hastings, et al. Standards Track [Page 73]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.3.6 Release-Job Operation
+
+ This OPTIONAL operation allows a client to release a previously held
+ job so that it is again eligible for scheduling. If the Hold-Job
+ operation is supported, then the Release-Job operation MUST be
+ supported, and vice-versa.
+
+ This operation removes the "job-hold-until" job attribute, if
+ present, from the job object that had been supplied in the create or
+ most recent Hold-Job or Restart-Job operation and removes its effect
+ on the job. The IPP object MUST remove the 'job-hold-until-
+ specified' value from the job's "job-state-reasons" attribute, if
+ present. See section 4.3.8.
+
+ The IPP object MUST accept or reject the request based on the job's
+ current state and transition the job to the indicated new state as
+ follows:
+
+ Current "job- New "job-state" IPP object's response status
+ state" code and action:
+
+ 'pending' 'pending' 'successful-ok'
+ No effect on the job.
+ 'pending-held' 'pending-held' 'successful-ok' See Rule 1
+ 'pending-held' 'pending' 'successful-ok'
+ 'processing' 'processing' 'successful-ok'
+ No effect on the job.
+ 'processing- 'processing- 'successful-ok'
+ stopped' stopped' No effect on the job.
+ 'completed' 'completed' 'client-error-not-possible'
+ 'canceled' 'canceled' 'client-error-not-possible'
+ 'aborted' 'aborted' 'client-error-not-possible'
+
+ Rule 1: If there are other reasons to keep the job in the 'pending-
+ held' state, such as 'resources-are-not-ready', the job remains in
+ the 'pending-held' state. Thus the 'pending-held' state is not just
+ for jobs that have the 'job-hold-until' applied to them, but are for
+ any reason to keep the job from being a candidate for scheduling and
+ processing, such as 'resources-are-not-ready'. See the "job-hold-
+ until" attribute (section 4.2.2).
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must either be the job owner or an operator or
+ administrator of the Printer object (see Sections 1 and 8.5).
+ Otherwise, the IPP object MUST reject the operation and return:
+ 'client-error-forbidden', 'client-error-not-authenticated', or
+ 'client-error-not-authorized' as appropriate.
+
+
+
+
+Hastings, et al. Standards Track [Page 74]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The Release-Job Request and Release-Job Response have the same
+ attribute groups and attributes as the Cancel-Job operation (see
+ section 3.3.3.1 and 3.3.3.2).
+
+3.3.7 Restart-Job Operation
+
+ This OPTIONAL operation allows a client to restart a job that is
+ retained in the queue after processing has completed (see section
+ 4.3.7.2).
+
+ The job is moved to the 'pending' or 'pending-held' job state and
+ restarts at the beginning on the same IPP Printer object with the
+ same attribute values. If any of the documents in the job were
+ passed by reference (Print-URI or Send-URI), the Printer MUST re-
+ fetch the data, since the semantics of Restart-Job are to repeat all
+ Job processing. The Job Description attributes that accumulate job
+ progress, such as "job-impressions-completed", "job-media-sheets-
+ completed", and "job-k-octets-processed", MUST be reset to 0 so that
+ they give an accurate record of the job from its restart point. The
+ job object MUST continue to use the same "job-uri" and "job-id"
+ attribute values.
+
+ Note: If in the future an operation is needed that does not reset
+ the job progress attributes, then a new operation will be defined
+ which makes a copy of the job, assigns a new "job-uri" and "job-id"
+ to the copy and resets the job progress attributes in the new copy
+ only.
+
+ The IPP object MUST accept or reject the request based on the job's
+ current state, transition the job to the indicated new state as
+ follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 75]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Current "job- New "job-state" IPP object's response status
+ state" code and action:
+
+ 'pending' 'pending' 'client-error-not-possible'
+ 'pending-held' 'pending-held' 'client-error-not-possible'
+ 'processing' 'processing' 'client-error-not-possible'
+ 'processing- 'processing- 'client-error-not-possible'
+ stopped' stopped'
+ 'completed' 'pending' or 'successful-ok' - job is started
+ 'pending-held' over.
+ 'completed' 'completed' 'client-error-not-possible' -
+ see Rule 1
+ 'canceled' 'pending' or 'successful-ok' - job is started
+ 'pending-held' over.
+ 'canceled' 'canceled' 'client-error-not-possible' -
+ see Rule 1
+ 'aborted' 'pending' or 'successful-ok' - job is started
+ 'pending-held' over.
+ 'aborted' 'aborted' 'client-error-not-possible' -
+ see Rule 1
+
+ Rule 1: If the Job Retention Period has expired for the job in this
+ state, then the IPP object rejects the operation. See section
+ 4.3.7.2.
+
+ Note: In order to prevent a user from inadvertently restarting a job
+ in the middle, the Restart-Job request is rejected when the job is in
+ the 'processing' or 'processing-stopped' states. If in the future an
+ operation is needed to hold or restart jobs while in these states, it
+ will be added as an additional operation, rather than overloading the
+ Restart-Job operation, so that it is clear that the user intended
+ that the current job not be completed.
+
+ Access Rights: The authenticated user (see section 8.3) performing
+ this operation must either be the job owner or an operator or
+ administrator of the Printer object (see Sections 1 and 8.5).
+ Otherwise, the IPP object MUST reject the operation and return:
+ 'client-error-forbidden', 'client-error-not-authenticated', or
+ 'client-error-not-authorized' as appropriate.
+
+3.3.7.1 Restart-Job Request
+
+ The groups and attributes are the same as for a Cancel-Job request
+ (see section 3.3.3.1), with the addition of the following Group 1
+ Operation attribute:
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 76]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ "job-hold-until" (type3 keyword | name(MAX)):
+ The client OPTIONALLY supplies this attribute. The IPP object
+ MUST support this Operation attribute in a Restart-Job request,
+ if it supports the "job-hold-until" Job Template attribute in
+ create operations. See section 4.2.2. Otherwise, the IPP
+ object NEED NOT support the "job-hold-until" Operation
+ attribute in a Restart-Job request.
+
+ If supplied and supported as specified in the Printer's "job-
+ hold-until-supported" attribute, the IPP object copies the
+ supplied Operation attribute to the Job object, replacing the
+ job's previous "job-hold-until" attribute, if present, and
+ makes the job a candidate for scheduling during the supplied
+ named time period. See section 4.2.2.
+
+ If supplied, but the value is not supported, the IPP object
+ accepts the request, returns the unsupported attribute or value
+ in the Unsupported Attributes Group according to section 3.1.7,
+ returns the 'successful-ok-ignored-or-substituted-attributes'
+ status code, and holds the job indefinitely until a client
+ performs a subsequent Release-Job operation.
+
+ If supplied, but the "job-hold-until" Operation attribute
+ itself is not supported, the IPP object accepts the request,
+ returns the unsupported attribute with the out-of-band
+ 'unsupported' value in the Unsupported Attributes Group
+ according to section 3.1.7, returns the 'successful-ok-
+ ignored-or-substituted-attributes' status code, and restarts
+ the job, i.e., ignores the "job-hold-until" attribute.
+
+ If the client (1) supplies a value that specifies a time period
+ that has already started or the 'no-hold' value (meaning don't
+ hold the job) and (2) the IPP object supports the "job-hold-
+ until" operation attribute and there are no other reasons to
+ hold the job, the IPP object makes the job a candidate for
+ processing immediately (see Section 4.2.2).
+
+ If the client does not supply a "job-hold-until" operation
+ attribute in the request, the IPP object removes the "job-
+ hold-until" attribute, if present, from the job. If there are
+ no other reasons to hold the job, the Restart-Job operation
+ makes the job a candidate for processing immediately (see
+ Section 4.2.2).
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 77]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+3.3.7.2 Restart-Job Response
+
+ The groups and attributes are the same as for a Cancel-Job response
+ (see section 3.3.3.2).
+
+ Note: In the future an OPTIONAL Modify-Job or Set-Job-Attributes
+ operation may be specified that allows the client to modify other
+ attributes before releasing the restarted job.
+
+4. Object Attributes
+
+ This section describes the attributes with their corresponding
+ attribute syntaxes and values that are part of the IPP model. The
+ sections below show the objects and their associated attributes which
+ are included within the scope of this protocol. Many of these
+ attributes are derived from other relevant documents:
+
+ - Document Printing Application (DPA) [ISO10175]
+ - RFC 1759 Printer MIB [RFC1759]
+
+ Each attribute is uniquely identified in this document using a
+ "keyword" (see section 12.2.1) which is the name of the attribute.
+ The keyword is included in the section header describing that
+ attribute.
+
+ Note: Not only are keywords used to identify attributes, but one of
+ the attribute syntaxes described below is "keyword" so that some
+ attributes have keyword values. Therefore, these attributes are
+ defined as having an attribute syntax that is a set of keywords.
+
+4.1 Attribute Syntaxes
+
+ This section defines the basic attribute syntax types that all
+ clients and IPP objects MUST be able to accept in responses and
+ accept in requests, respectively. Each attribute description in
+ sections 3 and 4 includes the name of attribute syntax(es) in the
+ heading (in parentheses). A conforming implementation of an
+ attribute MUST include the semantics of the attribute syntax(es) so
+ identified. Section 6.3 describes how the protocol can be extended
+ with new attribute syntaxes.
+
+ The attribute syntaxes are specified in the following sub-sections,
+ where the sub-section heading is the keyword name of the attribute
+ syntax inside the single quotes. In operation requests and responses
+ each attribute value MUST be represented as one of the attribute
+ syntaxes specified in the sub-section heading for the attribute. In
+ addition, the value of an attribute in a response (but not in a
+
+
+
+
+Hastings, et al. Standards Track [Page 78]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ request) MAY be one of the "out-of-band" values whose special
+ encoding rules are defined in the "Encoding and Transport" document
+ [RFC2910]. Standard "out-of-band" values are:
+
+ 'unknown': The attribute is supported by the IPP object, but the
+ value is unknown to the IPP object for some reason.
+ 'unsupported': The attribute is unsupported by the IPP object.
+ This value MUST be returned only as the value of an attribute
+ in the Unsupported Attributes Group.
+ 'no-value': The attribute is supported by the Printer object, but
+ the administrator has not yet configured a value.
+
+ All attributes in a request MUST have one or more values as defined
+ in Sections 4.2 to 4.4. Thus clients MUST NOT supply attributes with
+ "out-of-band" values for operations defined in this document. All
+ attributes in a response MUST have one or more values as defined in
+ Sections 4.2 to 4.4 or a single "out-of-band" value.
+
+ Most attributes are defined to have a single attribute syntax.
+ However, a few attributes (e.g., "job-sheet", "media", "job-hold-
+ until") are defined to have several attribute syntaxes, depending on
+ the value. These multiple attribute syntaxes are separated by the
+ "|" character in the sub-section heading to indicate the choice.
+ Since each value MUST be tagged as to its attribute syntax in the
+ protocol, a single-valued attribute instance may have any one of its
+ attribute syntaxes and a multi-valued attribute instance may have a
+ mixture of its defined attribute syntaxes.
+
+4.1.1 'text'
+
+ A text attribute is an attribute whose value is a sequence of zero or
+ more characters encoded in a maximum of 1023 ('MAX') octets. MAX is
+ the maximum length for each value of any text attribute. However, if
+ an attribute will always contain values whose maximum length is much
+ less than MAX, the definition of that attribute will include a
+ qualifier that defines the maximum length for values of that
+ attribute. For example: the "printer-location" attribute is
+ specified as "printer-location (text(127))". In this case, text
+ values for "printer-location" MUST NOT exceed 127 octets; if supplied
+ with a longer text string via some external interface (other than the
+ protocol), implementations are free to truncate to this shorter
+ length limitation.
+
+ In this document, all text attributes are defined using the 'text'
+ syntax. However, 'text' is used only for brevity; the formal
+ interpretation of 'text' is: 'textWithoutLanguage |
+ textWithLanguage'. That is, for any attribute defined in this
+ document using the 'text' attribute syntax, all IPP objects and
+
+
+
+Hastings, et al. Standards Track [Page 79]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ clients MUST support both the 'textWithoutLanguage' and
+ 'textWithLanguage' attribute syntaxes. However, in actual usage and
+ protocol execution, objects and clients accept and return only one of
+ the two syntax per attribute. The syntax 'text' never appears "on-
+ the-wire".
+
+ Both 'textWithoutLanguage' and 'textWithLanguage' are needed to
+ support the real world needs of interoperability between sites and
+ systems that use different natural languages as the basis for human
+ communication. Generally, one natural language applies to all text
+ attributes in a given request or response. The language is indicated
+ by the "attributes-natural-language" operation attribute defined in
+ section 3.1.4 or "attributes-natural-language" job attribute defined
+ in section 4.3.20, and there is no need to identify the natural
+ language for each text string on a value-by-value basis. In these
+ cases, the attribute syntax 'textWithoutLanguage' is used for text
+ attributes. In other cases, the client needs to supply or the
+ Printer object needs to return a text value in a natural language
+ that is different from the rest of the text values in the request or
+ response. In these cases, the client or Printer object uses the
+ attribute syntax 'textWithLanguage' for text attributes (this is the
+ Natural Language Override mechanism described in section 3.1.4).
+
+ The 'textWithoutLanguage' and 'textWithLanguage' attribute syntaxes
+ are described in more detail in the following sections.
+
+4.1.1.1 'textWithoutLanguage'
+
+ The 'textWithoutLanguage' syntax indicates a value that is sequence
+ of zero or more characters encoded in a maximum of 1023 (MAX) octets.
+ Text strings are encoded using the rules of some charset. The
+ Printer object MUST support the UTF-8 charset [RFC2279] and MAY
+ support additional charsets to represent 'text' values, provided that
+ the charsets are registered with IANA [IANA-CS]. See Section 4.1.7
+ for the definition of the 'charset' attribute syntax, including
+ restricted semantics and examples of charsets.
+
+4.1.1.2 'textWithLanguage'
+
+ The 'textWithLanguage' attribute syntax is a compound attribute
+ syntax consisting of two parts: a 'textWithoutLanguage' part encoded
+ in a maximum of 1023 (MAX) octets plus an additional
+ 'naturalLanguage' (see section 4.1.8) part that overrides the natural
+ language in force. The 'naturalLanguage' part explicitly identifies
+ the natural language that applies to the text part of that value and
+ that value alone. For any give text attribute, the
+ 'textWithoutLanguage' part is limited to the maximum length defined
+ for that 'text' attribute, and the 'naturalLanguage' part is always
+
+
+
+Hastings, et al. Standards Track [Page 80]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ limited to 63 (additional) octets. Using the 'textWithLanguage'
+ attribute syntax rather than the normal 'textWithoutLanguage' syntax
+ is the so-called Natural Language Override mechanism and MUST be
+ supported by all IPP objects and clients.
+
+ If the attribute is multi-valued (1setOf text), then the
+ 'textWithLanguage' attribute syntax MUST be used to explicitly
+ specify each attribute value whose natural language needs to be
+ overridden. Other values in a multi-valued 'text' attribute in a
+ request or a response revert to the natural language of the operation
+ attribute.
+
+ In a create request, the Printer object MUST accept and store with
+ the Job object any natural language in the "attributes-natural-
+ language" operation attribute, whether the Printer object supports
+ that natural language or not. Furthermore, the Printer object MUST
+ accept and store any 'textWithLanguage' attribute value, whether the
+ Printer object supports that natural language or not. These
+ requirements are independent of the value of the "ipp-attribute-
+ fidelity" operation attribute that the client MAY supply.
+
+ Example: If the client supplies the "attributes-natural-language"
+ operation attribute with the value: 'en' indicating English, but the
+ value of the "job-name" attribute is in French, the client MUST use
+ the 'textWithLanguage' attribute syntax with the following two
+ values:
+
+ 'fr': Natural Language Override indicating French
+ 'Rapport Mensuel': the job name in French
+
+ See the "Encoding and Transport" document [RFC2910] section 3.9 for
+ the encoding of the two parts and Appendix A for a detailed example
+ of the 'textWithLanguage' attribute syntax.
+
+4.1.2 'name'
+
+ This syntax type is used for user-friendly strings, such as a Printer
+ name, that, for humans, are more meaningful than identifiers. Names
+ are never translated from one natural language to another. The
+ 'name' attribute syntax is essentially the same as 'text', including
+ the REQUIRED support of UTF-8 except that the sequence of characters
+ is limited so that its encoded form MUST NOT exceed 255 (MAX) octets.
+
+ Also like 'text', 'name' is really an abbreviated notation for either
+ 'nameWithoutLanguage' or 'nameWithLanguage'. That is, all IPP
+ objects and clients MUST support both the 'nameWithoutLanguage' and
+ 'nameWithLanguage' attribute syntaxes. However, in actual usage and
+
+
+
+
+Hastings, et al. Standards Track [Page 81]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ protocol execution, objects and clients accept and return only one of
+ the two syntax per attribute. The syntax 'name' never appears "on-
+ the-wire".
+
+ Only the 'text' and 'name' attribute syntaxes permit the Natural
+ Language Override mechanism.
+
+ Some attributes are defined as 'type3 keyword | name'. These
+ attributes support values that are either type3 keywords or names.
+ This dual-syntax mechanism enables a site administrator to extend
+ these attributes to legally include values that are locally defined
+ by the site administrator. Such names are not registered with IANA.
+
+4.1.2.1 'nameWithoutLanguage'
+
+ The 'nameWithoutLanguage' syntax indicates a value that is sequence
+ of zero or more characters encoded in a maximum of 255 (MAX) octets.
+
+4.1.2.2 'nameWithLanguage'
+
+ The 'nameWithLanguage' attribute syntax is a compound attribute
+ syntax consisting of two parts: a 'nameWithoutLanguage' part encoded
+ in a maximum of 1023 (MAX) octets plus an additional
+ 'naturalLanguage' (see section 4.1.8) part that overrides the natural
+ language in force. The 'naturalLanguage' part explicitly identifies
+ the natural language that applies to that name value and that name
+ value alone. For any give text attribute, the 'textWithoutLanguage'
+ part is limited to the maximum length defined for that 'text'
+ attribute, and the 'naturalLanguage' part is always limited to 63
+ (additional) octets. Using the 'textWithLanguage' attribute syntax
+ rather than the normal 'textWithoutLanguage' syntax is the so-called
+ Natural Language Override mechanism and MUST be supported by all IPP
+ objects and clients.
+
+ The 'nameWithLanguage' attribute syntax behaves the same as the
+ 'textWithLanguage' syntax. Using the 'textWithLanguage' attribute
+ syntax rather than the normal 'textWithoutLanguage' syntax is the
+ so-called Natural Language Override mechanism and MUST be supported
+ by all IPP objects and clients. If a name is in a language that is
+ different than the rest of the object or operation, then this
+ 'nameWithLanguage' syntax is used rather than the generic
+ 'nameWithoutLanguage' syntax.
+
+ If the attribute is multi-valued (1setOf text), then the
+ 'nameWithLanguage' attribute syntax MUST be used to explicitly
+ specify each attribute value whose natural language needs to be
+ overridden.
+
+
+
+
+Hastings, et al. Standards Track [Page 82]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Other values in a multi-valued 'name' attribute in a request or a
+ response revert to the natural language of the operation attribute.
+
+ In a create request, the Printer object MUST accept and store with
+ the Job object any natural language in the "attributes-natural-
+ language" operation attribute, whether the Printer object supports
+ that natural language or not. Furthermore, the Printer object MUST
+ accept and store any 'nameWithLanguage' attribute value, whether the
+ Printer object supports that natural language or not. These
+ requirements are independent of the value of the "ipp-attribute-
+ fidelity" operation attribute that the client MAY supply.
+
+ Example: If the client supplies the "attributes-natural-language"
+ operation attribute with the value: 'en' indicating English, but the
+ "printer-name" attribute is in German, the client MUST use the
+ 'nameWithLanguage' attribute syntax as follows:
+
+ 'de': Natural Language Override indicating German
+ 'Farbdrucker': the Printer name in German
+
+ See the "Encoding and Transport" document [RFC2910] section 3.9 for
+ the encoding of the two parts and Appendix A for a detailed example
+ of the 'nameWithLanguage' attribute syntax.
+
+4.1.2.3 Matching 'name' attribute values
+
+ For purposes of matching two 'name' attribute values for equality,
+ such as in job validation (where a client-supplied value for
+ attribute "xxx" is checked to see if the value is among the values of
+ the Printer object's corresponding "xxx-supported" attribute), the
+ following match rules apply:
+
+ 1. 'keyword' values never match 'name' values.
+
+ 2. 'name' (nameWithoutLanguage and nameWithLanguage) values match
+ if (1) the name parts match and (2) the Associated Natural-
+ Language parts (see section 3.1.4.1) match. The matching rules
+ are:
+
+ a. the name parts match if the two names are identical
+ character by character, except it is RECOMMENDED that case
+ be ignored. For example: 'Ajax-letter-head-white' MUST
+ match 'Ajax-letter-head-white' and SHOULD match 'ajax-
+ letter-head-white' and 'AJAX-LETTER-HEAD-WHITE'.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 83]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ b. the Associated Natural-Language parts match if the shorter
+ of the two meets the syntactic requirements of RFC 1766
+ [RFC1766] and matches byte for byte with the longer. For
+ example, 'en' matches 'en', 'en-us' and 'en-gb', but matches
+ neither 'fr' nor 'e'.
+
+4.1.3 'keyword'
+
+ The 'keyword' attribute syntax is a sequence of characters, length: 1
+ to 255, containing only the US-ASCII [ASCII] encoded values for
+ lowercase letters ("a" - "z"), digits ("0" - "9"), hyphen ("-"), dot
+ ("."), and underscore ("_"). The first character MUST be a lowercase
+ letter. Furthermore, keywords MUST be in U.S. English.
+
+ This syntax type is used for enumerating semantic identifiers of
+ entities in the abstract protocol, i.e., entities identified in this
+ document. Keywords are used as attribute names or values of
+ attributes. Unlike 'text' and 'name' attribute values, 'keyword'
+ values MUST NOT use the Natural Language Override mechanism, since
+ they MUST always be US-ASCII and U.S. English.
+
+ Keywords are for use in the protocol. A user interface will likely
+ provide a mapping between protocol keywords and displayable user-
+ friendly words and phrases which are localized to the natural
+ language of the user. While the keywords specified in this document
+ MAY be displayed to users whose natural language is U.S. English,
+ they MAY be mapped to other U.S. English words for U.S. English
+ users, since the user interface is outside the scope of this
+ document.
+
+ In the definition for each attribute of this syntax type, the full
+ set of defined keyword values for that attribute are listed.
+
+ When a keyword is used to represent an attribute (its name), it MUST
+ be unique within the full scope of all IPP objects and attributes.
+ When a keyword is used to represent a value of an attribute, it MUST
+ be unique just within the scope of that attribute. That is, the same
+ keyword MUST NOT be used for two different values within the same
+ attribute to mean two different semantic ideas. However, the same
+ keyword MAY be used across two or more attributes, representing
+ different semantic ideas for each attribute. Section 6.1 describes
+ how the protocol can be extended with new keyword values. Examples
+ of attribute name keywords:
+
+ "job-name"
+ "attributes-charset"
+
+
+
+
+
+Hastings, et al. Standards Track [Page 84]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Note: This document uses "type1", "type2", and "type3" prefixes to
+ the "keyword" basic syntax to indicate different levels of review for
+ extensions (see section 6.1).
+
+4.1.4 'enum'
+
+ The 'enum' attribute syntax is an enumerated integer value that is in
+ the range from 1 to 2**31 - 1 (MAX). Each value has an associated
+ 'keyword' name. In the definition for each attribute of this syntax
+ type, the full set of possible values for that attribute are listed.
+ This syntax type is used for attributes for which there are enum
+ values assigned by other standards, such as SNMP MIBs. A number of
+ attribute enum values in this document are also used for
+ corresponding attributes in other standards [RFC1759]. This syntax
+ type is not used for attributes to which the administrator may assign
+ values. Section 6.1 describes how the protocol can be extended with
+ new enum values.
+
+ Enum values are for use in the protocol. A user interface will
+ provide a mapping between protocol enum values and displayable user-
+ friendly words and phrases which are localized to the natural
+ language of the user. While the enum symbols specified in this
+ document MAY be displayed to users whose natural language is U.S.
+ English, they MAY be mapped to other U.S. English words for U.S.
+ English users, since the user interface is outside the scope of this
+ document.
+
+ Note: SNMP MIBs use '2' for 'unknown' which corresponds to the IPP
+ "out-of-band" value 'unknown'. See the description of the "out-of-
+ band" values at the beginning of Section 4.1. Therefore, attributes
+ of type 'enum' start at '3'.
+
+ Note: This document uses "type1", "type2", and "type3" prefixes to
+ the "enum" basic syntax to indicate different levels of review for
+ extensions (see section 6.1).
+
+4.1.5 'uri'
+
+ The 'uri' attribute syntax is any valid Uniform Resource Identifier
+ or URI [RFC2396]. Most often, URIs are simply Uniform Resource
+ Locators or URLs. The maximum length of URIs used as values of IPP
+ attributes is 1023 octets. Although most other IPP attribute syntax
+ types allow for only lower-cased values, this attribute syntax type
+ conforms to the case-sensitive and case-insensitive rules specified
+ in [RFC2396]. See also [IPP-IIG] for a discussion of case in URIs.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 85]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.1.6 'uriScheme'
+
+ The 'uriScheme' attribute syntax is a sequence of characters
+ representing a URI scheme according to RFC 2396 [RFC2396]. Though
+ RFC 2396 requires that the values be case-insensitive, IPP requires
+ all lower case values in IPP attributes to simplify comparing by IPP
+ clients and Printer objects.
+
+ Standard values for this syntax type are the following keywords:
+
+ 'ipp': for IPP schemed URIs (e.g., "ipp:...")
+ 'http': for HTTP schemed URIs (e.g., "http:...")
+ 'https': for use with HTTPS schemed URIs (e.g., "https:...") (not
+ on IETF standards track)
+ 'ftp': for FTP schemed URIs (e.g., "ftp:...")
+ 'mailto': for SMTP schemed URIs (e.g., "mailto:...")
+ 'file': for file schemed URIs (e.g., "file:...")
+
+ A Printer object MAY support any URI 'scheme' that has been
+ registered with IANA [IANA-MT]. The maximum length of URI 'scheme'
+ values used to represent IPP attribute values is 63 octets.
+
+4.1.7 'charset'
+
+ The 'charset' attribute syntax is a standard identifier for a
+ charset. A charset is a coded character set and encoding scheme.
+ Charsets are used for labeling certain document contents and 'text'
+ and 'name' attribute values. The syntax and semantics of this
+ attribute syntax are specified in RFC 2046 [RFC2046] and contained in
+ the IANA character-set Registry [IANA-CS] according to the IANA
+ procedures [RFC2278]. Though RFC 2046 requires that the values be
+ case-insensitive US-ASCII [ASCII], IPP requires all lower case values
+ in IPP attributes to simplify comparing by IPP clients and Printer
+ objects. When a character-set in the IANA registry has more than one
+ name (alias), the name labeled as "(preferred MIME name)", if
+ present, MUST be used.
+
+ The maximum length of 'charset' values used to represent IPP
+ attribute values is 63 octets.
+
+ Some examples are:
+
+ 'utf-8': ISO 10646 Universal Multiple-Octet Coded Character Set
+ (UCS) represented as the UTF-8 [RFC2279] transfer encoding
+ scheme in which US-ASCII is a subset charset.
+ 'us-ascii': 7-bit American Standard Code for Information
+ Interchange (ASCII), ANSI X3.4-1986 [ASCII]. That standard
+
+
+
+
+Hastings, et al. Standards Track [Page 86]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ defines US-ASCII, but RFC 2045 [RFC2045] eliminates most of the
+ control characters from conformant usage in MIME and IPP.
+ 'iso-8859-1': 8-bit One-Byte Coded Character Set, Latin Alphabet
+ Nr 1 [ISO8859-1]. That standard defines a coded character set
+ that is used by Latin languages in the Western Hemisphere and
+ Western Europe. US-ASCII is a subset charset.
+
+ Some attribute descriptions MAY place additional requirements on
+ charset values that may be used, such as REQUIRED values that MUST be
+ supported or additional restrictions, such as requiring that the
+ charset have US- ASCII as a subset charset.
+
+4.1.8 'naturalLanguage'
+
+ The 'naturalLanguage' attribute syntax is a standard identifier for a
+ natural language and optionally a country. The values for this
+ syntax type are defined by RFC 1766 [RFC1766]. Though RFC 1766
+ requires that the values be case-insensitive US-ASCII [ASCII], IPP
+ requires all lower case to simplify comparing by IPP clients and
+ Printer objects. Examples include:
+
+ 'en': for English
+ 'en-us': for US English
+ 'fr': for French
+ 'de': for German
+
+ The maximum length of 'naturalLanguage' values used to represent IPP
+ attribute values is 63 octets.
+
+4.1.9 'mimeMediaType'
+
+ The 'mimeMediaType' attribute syntax is the Internet Media Type
+ (sometimes called MIME type) as defined by RFC 2046 [RFC2046] and
+ registered according to the procedures of RFC 2048 [RFC2048] for
+ identifying a document format. The value MAY include a charset, or
+ other, parameter, depending on the specification of the Media Type in
+ the IANA Registry [IANA-MT]. Although most other IPP syntax types
+ allow for only lower-cased values, this syntax type allows for
+ mixed-case values which are case-insensitive.
+
+ Examples are:
+ 'text/html': An HTML document
+ 'text/plain': A plain text document in US-ASCII (RFC 2046
+ indicates that in the absence of the charset parameter MUST
+ mean US-ASCII rather than simply unspecified) [RFC2046].
+ 'text/plain; charset=US-ASCII': A plain text document in US-ASCII
+ [52, 56].
+
+
+
+
+Hastings, et al. Standards Track [Page 87]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'text/plain; charset=ISO-8859-1': A plain text document in ISO
+ 8859-1 (Latin 1) [ISO8859-1].
+ 'text/plain; charset=utf-8': A plain text document in ISO 10646
+ represented as UTF-8 [RFC2279]
+ 'application/postscript': A PostScript document [RFC2046]
+ 'application/vnd.hp-PCL': A PCL document [IANA-MT] (charset
+ escape sequence embedded in the document data)
+ 'application/pdf': Portable Document Format - see IANA MIME Media
+ Type registry
+ 'application/octet-stream': Auto-sense - see section 4.1.9.1
+
+ The maximum length of a 'mimeMediaType' value to represent IPP
+ attribute values is 255 octets.
+
+4.1.9.1 Application/octet-stream -- Auto-Sensing the document format
+
+ One special type is 'application/octet-stream'. If the Printer
+ object supports this value, the Printer object MUST be capable of
+ auto-sensing the format of the document data using an
+ implementation-dependent method that examines some number of octets
+ of the document data, either as part of the create operation and/or
+ at document processing time. During auto-sensing, a Printer may
+ determine that the document-data has a format that the Printer
+ doesn't recognize. If the Printer determines this problem before
+ returning an operation response, it rejects the request and returns
+ the 'client-error-document-format-not-supported' status code. If the
+ Printer determines this problem after accepting the request and
+ returning an operation response with one of the successful status
+ codes, the Printer adds the 'unsupported-document-format' value to
+ the job's "job-state-reasons" attribute.
+
+ If the Printer object's default value attribute "document-format-
+ default" is set to 'application/octet-stream', the Printer object not
+ only supports auto-sensing of the document format, but will depend on
+ the result of applying its auto-sensing when the client does not
+ supply the "document-format" attribute. If the client supplies a
+ document format value, the Printer MUST rely on the supplied
+ attribute, rather than trust its auto-sensing algorithm. To
+ summarize:
+
+ 1. If the client does not supply a document format value, the
+ Printer MUST rely on its default value setting (which may be
+ 'application/octet-stream' indicating an auto-sensing
+ mechanism).
+ 2. If the client supplies a value other than 'application/octet-
+ stream', the client is supplying valid information about the
+ format of the document data and the Printer object MUST trust
+ the client supplied value more than the outcome of applying an
+
+
+
+Hastings, et al. Standards Track [Page 88]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ automatic format detection mechanism. For example, the client
+ may be requesting the printing of a PostScript file as a
+ 'text/plain' document. The Printer object MUST print a text
+ representation of the PostScript commands rather than interpret
+ the stream of PostScript commands and print the result.
+ 3. If the client supplies a value of 'application/octet-stream',
+ the client is indicating that the Printer object MUST use its
+ auto-sensing mechanism on the client supplied document data
+ whether auto-sensing is the Printer object's default or not.
+
+ Note: Since the auto-sensing algorithm is probabilistic, if the
+ client requests both auto-sensing ("document-format" set to
+ 'application/octet-stream') and true fidelity ("ipp-attribute-
+ fidelity" set to 'true'), the Printer object might not be able to
+ guarantee exactly what the end user intended (the auto-sensing
+ algorithm might mistake one document format for another), but it is
+ able to guarantee that its auto-sensing mechanism be used.
+
+ When a Printer performs auto-sensing of a document in a submitted
+ job, it is RECOMMENDED that the Printer indicate to the user that
+ such auto-sensing has occurred and which document-format was auto-
+ sensed by printing that information on the job's job-start-sheet.
+
+4.1.10 'octetString'
+
+ The 'octetString' attribute syntax is a sequence of octets encoded in
+ a maximum of 1023 octets which is indicated in sub-section headers
+ using the notation: octetString(MAX). This syntax type is used for
+ opaque data.
+
+4.1.11 'boolean'
+
+ The 'boolean' attribute syntax has only two values: 'true' and
+ 'false'.
+
+4.1.12 'integer'
+
+ The 'integer' attribute syntax is an integer value that is in the
+ range from -2**31 (MIN) to 2**31 - 1 (MAX). Each individual
+ attribute may specify the range constraint explicitly in sub-section
+ headers if the range is different from the full range of possible
+ integer values. For example: job-priority (integer(1:100)) for the
+ "job-priority" attribute. However, the enforcement of that
+ additional constraint is up to the IPP objects, not the protocol.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 89]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.1.13 'rangeOfInteger'
+
+ The 'rangeOfInteger' attribute syntax is an ordered pair of integers
+ that defines an inclusive range of integer values. The first integer
+ specifies the lower bound and the second specifies the upper bound.
+ If a range constraint is specified in the header description for an
+ attribute in this document whose attribute syntax is 'rangeOfInteger'
+ (i.e., 'X:Y' indicating X as a minimum value and Y as a maximum
+ value), then the constraint applies to both integers.
+
+4.1.14 'dateTime'
+
+ The 'dateTime' attribute syntax is a standard, fixed length, 11 octet
+ representation of the "DateAndTime" syntax as defined in RFC 2579
+ [RFC2579]. RFC 2579 also identifies an 8 octet representation of a
+ "DateAndTime" value, but IPP objects MUST use the 11 octet
+ representation. A user interface will provide a mapping between
+ protocol dateTime values and displayable user-friendly words or
+ presentation values and phrases which are localized to the natural
+ language and date format of the user, including time zone.
+
+4.1.15 'resolution'
+
+ The 'resolution' attribute syntax specifies a two-dimensional
+ resolution in the indicated units. It consists of 3 values: a cross
+ feed direction resolution (positive integer value), a feed direction
+ resolution (positive integer value), and a units value. The
+ semantics of these three components are taken from the Printer MIB
+ [RFC1759] suggested values. That is, the cross feed direction
+ component resolution component is the same as the
+ prtMarkerAddressabilityXFeedDir object in the Printer MIB, the feed
+ direction component resolution component is the same as the
+ prtMarkerAddressabilityFeedDir in the Printer MIB, and the units
+ component is the same as the prtMarkerAddressabilityUnit object in
+ the Printer MIB (namely, '3' indicates dots per inch and '4'
+ indicates dots per centimeter). All three values MUST be present
+ even if the first two values are the same. Example: '300', '600',
+ '3' indicates a 300 dpi cross-feed direction resolution, a 600 dpi
+ feed direction resolution, since a '3' indicates dots per inch (dpi).
+
+4.1.16 '1setOf X'
+
+ The '1setOf X' attribute syntax is 1 or more values of attribute
+ syntax type X. This syntax type is used for multi-valued attributes.
+ The syntax type is called '1setOf' rather than just 'setOf' as a
+ reminder that the set of values MUST NOT be empty (i.e., a set of
+
+
+
+
+
+Hastings, et al. Standards Track [Page 90]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ size 0). Sets are normally unordered. However each attribute
+ description of this type may specify that the values MUST be in a
+ certain order for that attribute.
+
+4.2 Job Template Attributes
+
+ Job Template attributes describe job processing behavior. Support
+ for Job Template attributes by a Printer object is OPTIONAL (see
+ section 12.2.3 for a description of support for OPTIONAL attributes).
+ Also, clients OPTIONALLY supply Job Template attributes in create
+ requests.
+
+ Job Template attributes conform to the following rules. For each Job
+ Template attribute called "xxx":
+
+ 1. If the Printer object supports "xxx" then it MUST support both
+ a "xxx-default" attribute (unless there is a "No" in the table
+ below) and a "xxx-supported" attribute. If the Printer object
+ doesn't support "xxx", then it MUST support neither an "xxx-
+ default" attribute nor an "xxx-supported" attribute, and it
+ MUST treat an attribute "xxx" supplied by a client as
+ unsupported. An attribute "xxx" may be supported for some
+ document formats and not supported for other document formats.
+ For example, it is expected that a Printer object would only
+ support "orientation-requested" for some document formats (such
+ as 'text/plain' or 'text/html') but not others (such as
+ 'application/postscript').
+
+ 2. "xxx" is OPTIONALLY supplied by the client in a create request.
+ If "xxx" is supplied, the client is indicating a desired job
+ processing behavior for this Job. When "xxx" is not supplied,
+ the client is indicating that the Printer object apply its
+ default job processing behavior at job processing time if the
+ document content does not contain an embedded instruction
+ indicating an xxx-related behavior.
+
+ Since an administrator MAY change the default value attribute
+ after a Job object has been submitted but before it has been
+ processed, the default value used by the Printer object at job
+ processing time may be different that the default value in
+ effect at job submission time.
+
+ 3. The "xxx-supported" attribute is a Printer object attribute
+ that describes which job processing behaviors are supported by
+ that Printer object. A client can query the Printer object to
+ find out what xxx-related behaviors are supported by inspecting
+ the returned values of the "xxx-supported" attribute.
+
+
+
+
+Hastings, et al. Standards Track [Page 91]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Note: The "xxx" in each "xxx-supported" attribute name is
+ singular, even though an "xxx-supported" attribute usually has
+ more than one value, such as "job-sheet-supported", unless the
+ "xxx" Job Template attribute is plural, such as "finishings" or
+ "sides". In such cases the "xxx-supported" attribute names
+ are: "finishings- supported" and "sides-supported".
+
+ 4. The "xxx-default" default value attribute describes what will
+ be done at job processing time when no other job processing
+ information is supplied by the client (either explicitly as an
+ IPP attribute in the create request or implicitly as an
+ embedded instruction within the document data).
+
+ If an application wishes to present an end user with a list of
+ supported values from which to choose, the application SHOULD query
+ the Printer object for its supported value attributes. The
+ application SHOULD also query the default value attributes. If the
+ application then limits selectable values to only those value that
+ are supported, the application can guarantee that the values supplied
+ by the client in the create request all fall within the set of
+ supported values at the Printer. When querying the Printer, the
+ client MAY enumerate each attribute by name in the Get-Printer-
+ Attributes Request, or the client MAY just name the "job-template"
+ group in order to get the complete set of supported attributes (both
+ supported and default attributes).
+
+ The "finishings" attribute is an example of a Job Template attribute.
+ It can take on a set of values such as 'staple', 'punch', and/or
+ 'cover'. A client can query the Printer object for the "finishings-
+ supported" attribute and the "finishings-default" attribute. The
+ supported attribute contains a set of supported values. The default
+ value attribute contains the finishing value(s) that will be used for
+ a new Job if the client does not supply a "finishings" attribute in
+ the create request and the document data does not contain any
+ corresponding finishing instructions. If the client does supply the
+ "finishings" attribute in the create request, the IPP object
+ validates the value or values to make sure that they are a subset of
+ the supported values identified in the Printer object's "finishings-
+ supported" attribute. See section 3.1.7.
+
+ The table below summarizes the names and relationships for all Job
+ Template attributes. The first column of the table (labeled "Job
+ Attribute") shows the name and syntax for each Job Template attribute
+ in the Job object. These are the attributes that can optionally be
+ supplied by the client in a create request. The last two columns
+ (labeled "Printer: Default Value Attribute" and "Printer: Supported
+ Values Attribute") show the name and syntax for each Job Template
+ attribute in the Printer object (the default value attribute and the
+
+
+
+Hastings, et al. Standards Track [Page 92]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ supported values attribute). A "No" in the table means the Printer
+ MUST NOT support the attribute (that is, the attribute is simply not
+ applicable). For brevity in the table, the 'text' and 'name' entries
+ do not show the maximum length for each attribute.
+
+ +===================+======================+======================+
+ | Job Attribute |Printer: Default Value| Printer: Supported |
+ | | Attribute | Values Attribute |
+ +===================+======================+======================+
+ | job-priority | job-priority-default |job-priority-supported|
+ | (integer 1:100) | (integer 1:100) |(integer 1:100) |
+ +-------------------+----------------------+----------------------+
+ | job-hold-until | job-hold-until- |job-hold-until- |
+ | (type3 keyword | | default | supported |
+ | name) | (type3 keyword | |(1setOf ( |
+ | | name) |type3 keyword | name))|
+ +-------------------+----------------------+----------------------+
+ | job-sheets | job-sheets-default |job-sheets-supported |
+ | (type3 keyword | | (type3 keyword | |(1setOf ( |
+ | name) | name) |type3 keyword | name))|
+ +-------------------+----------------------+----------------------+
+ |multiple-document- |multiple-document- |multiple-document- |
+ | handling | handling-default |handling-supported |
+ | (type2 keyword) | (type2 keyword) |(1setOf type2 keyword)|
+ +-------------------+----------------------+----------------------+
+ | copies | copies-default | copies-supported |
+ | (integer (1:MAX)) | (integer (1:MAX)) | (rangeOfInteger |
+ | | | (1:MAX)) |
+ +-------------------+----------------------+----------------------+
+ | finishings | finishings-default | finishings-supported |
+ |(1setOf type2 enum)|(1setOf type2 enum) |(1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+ | page-ranges | No | page-ranges- |
+ | (1setOf | | supported (boolean) |
+ | rangeOfInteger | | |
+ | (1:MAX)) | | |
+ +-------------------+----------------------+----------------------+
+ | sides | sides-default | sides-supported |
+ | (type2 keyword) | (type2 keyword) |(1setOf type2 keyword)|
+ +-------------------+----------------------+----------------------+
+ | number-up | number-up-default | number-up-supported |
+ | (integer (1:MAX)) | (integer (1:MAX)) |(1setOf (integer |
+ | | | (1:MAX) | |
+ | | | rangeOfInteger |
+ | | | (1:MAX))) |
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 93]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ +-------------------+----------------------+----------------------+
+ | orientation- |orientation-requested-|orientation-requested-|
+ | requested | default | supported |
+ | (type2 enum) | (type2 enum) | (1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+ | media | media-default | media-supported |
+ | (type3 keyword | | (type3 keyword | |(1setOf ( |
+ | name) | name) |type3 keyword | name))|
+ | | | |
+ | | | media-ready |
+ | | |(1setOf ( |
+ | | |type3 keyword | name))|
+ +-------------------+----------------------+----------------------+
+ | printer-resolution| printer-resolution- | printer-resolution- |
+ | (resolution) | default | supported |
+ | | (resolution) |(1setOf resolution) |
+ +-------------------+----------------------+----------------------+
+ | print-quality | print-quality-default| print-quality- |
+ | (type2 enum) | (type2 enum) | supported |
+ | | |(1setOf type2 enum) |
+ +-------------------+----------------------+----------------------+
+
+4.2.1 job-priority (integer(1:100))
+
+ This attribute specifies a priority for scheduling the Job. A higher
+ value specifies a higher priority. The value 1 indicates the lowest
+ possible priority. The value 100 indicates the highest possible
+ priority. Among those jobs that are ready to print, a Printer MUST
+ print all jobs with a priority value of n before printing those with
+ a priority value of n-1 for all n.
+
+ If the Printer object supports this attribute, it MUST always support
+ the full range from 1 to 100. No administrative restrictions are
+ permitted. This way an end-user can always make full use of the
+ entire range with any Printer object. If privileged jobs are
+ implemented outside IPP/1.1, they MUST have priorities higher than
+ 100, rather than restricting the range available to end-users.
+
+ If the client does not supply this attribute and this attribute is
+ supported by the Printer object, the Printer object MUST use the
+ value of the Printer object's "job-priority-default" at job
+ submission time (unlike most Job Template attributes that are used if
+ necessary at job processing time).
+
+ The syntax for the "job-priority-supported" is also integer(1:100).
+ This single integer value indicates the number of priority levels
+ supported. The Printer object MUST take the value supplied by the
+ client and map it to the closest integer in a sequence of n integers
+
+
+
+Hastings, et al. Standards Track [Page 94]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ values that are evenly distributed over the range from 1 to 100 using
+ the formula:
+
+ roundToNearestInt((100x+50)/n)
+
+ where n is the value of "job-priority-supported" and x ranges from 0
+ through n-1.
+
+ For example, if n=1 the sequence of values is 50; if n=2, the
+ sequence of values is: 25 and 75; if n = 3, the sequence of values
+ is: 17, 50 and 83; if n = 10, the sequence of values is: 5, 15, 25,
+ 35, 45, 55, 65, 75, 85, and 95; if n = 100, the sequence of values
+ is: 1, 2, 3, ... 100.
+
+ If the value of the Printer object's "job-priority-supported" is 10
+ and the client supplies values in the range 1 to 10, the Printer
+ object maps them to 5, in the range 11 to 20, the Printer object maps
+ them to 15, etc.
+
+4.2.2 job-hold-until (type3 keyword | name (MAX))
+
+ This attribute specifies the named time period during which the Job
+ MUST become a candidate for printing.
+
+ Standard keyword values for named time periods are:
+
+ 'no-hold': immediately, if there are not other reasons to hold the
+ job
+ 'indefinite': - the job is held indefinitely, until a client
+ performs a Release-Job (section 3.3.6)
+ 'day-time': during the day
+ 'evening': evening
+ 'night': night
+ 'weekend': weekend
+ 'second-shift': second-shift (after close of business)
+ 'third-shift': third-shift (after midnight)
+
+ An administrator MUST associate allowable print times with a named
+ time period (by means outside the scope of this IPP/1.1 document).
+ An administrator is encouraged to pick names that suggest the type of
+ time period. An administrator MAY define additional values using the
+ 'name' or 'keyword' attribute syntax, depending on implementation.
+
+ If the value of this attribute specifies a time period that is in the
+ future, the Printer SHOULD add the 'job-hold-until-specified' value
+ to the job's "job-state-reasons" attribute, MUST move the job to the
+
+
+
+
+
+Hastings, et al. Standards Track [Page 95]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'pending-held' state, and MUST NOT schedule the job for printing
+ until the specified time-period arrives.
+
+ When the specified time period arrives, the Printer MUST remove the
+ 'job-hold-until-specified' value from the job's "job-state-reason"
+ attribute, if present. If there are no other job state reasons that
+ keep the job in the 'pending-held' state, the Printer MUST consider
+ the job as a candidate for processing by moving the job to the
+ 'pending' state.
+
+ If this job attribute value is the named value 'no-hold', or the
+ specified time period has already started, the job MUST be a
+ candidate for processing immediately.
+
+ If the client does not supply this attribute and this attribute is
+ supported by the Printer object, the Printer object MUST use the
+ value of the Printer object's "job-hold-until-default" at job
+ submission time (unlike most Job Template attributes that are used if
+ necessary at job processing time).
+
+4.2.3 job-sheets (type3 keyword | name(MAX))
+
+ This attribute determines which job start/end sheet(s), if any, MUST
+ be printed with a job.
+
+ Standard keyword values are:
+
+ 'none': no job sheet is printed
+ 'standard': one or more site specific standard job sheets are
+ printed, e.g. a single start sheet or both start and end sheet is
+ printed
+
+ An administrator MAY define additional values using the 'name' or
+ 'keyword' attribute syntax, depending on implementation.
+
+ The effect of this attribute on jobs with multiple documents MAY be
+ affected by the "multiple-document-handling" job attribute (section
+ 4.2.4), depending on the job sheet semantics.
+
+4.2.4 multiple-document-handling (type2 keyword)
+
+ This attribute is relevant only if a job consists of two or more
+ documents. This attribute MUST be supported with at least one value
+ if the Printer supports multiple documents per job (see sections
+ 3.2.4 and 3.3.1). The attribute controls finishing operations and
+ the placement of one or more print-stream pages into impressions and
+ onto media sheets. When the value of the "copies" attribute exceeds
+ 1, it also controls the order in which the copies that result from
+
+
+
+Hastings, et al. Standards Track [Page 96]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ processing the documents are produced. For the purposes of this
+ explanations, if "a" represents an instance of document data, then
+ the result of processing the data in document "a" is a sequence of
+ media sheets represented by "a(*)".
+
+ Standard keyword values are:
+
+ 'single-document': If a Job object has multiple documents, say,
+ the document data is called a and b, then the result of
+ processing all the document data (a and then b) MUST be treated
+ as a single sequence of media sheets for finishing operations;
+ that is, finishing would be performed on the concatenation of
+ the sequences a(*),b(*). The Printer object MUST NOT force the
+ data in each document instance to be formatted onto a new
+ print-stream page, nor to start a new impression on a new media
+ sheet. If more than one copy is made, the ordering of the sets
+ of media sheets resulting from processing the document data
+ MUST be a(*), b(*), a(*), b(*), start on a new media sheet.
+ 'separate-documents-uncollated-copies': If a Job object has
+ multiple documents, say, the document data is called a and b,
+ then the result of processing the data in each document
+ instance MUST be treated as a single sequence of media sheets
+ for finishing operations; that is, the sets a(*) and b(*) would
+ each be finished separately. The Printer object MUST force each
+ copy of the result of processing the data in a single document
+ to start on a new media sheet. If more than one copy is made,
+ the ordering of the sets of media sheets resulting from
+ processing the document data MUST be a(*), a(*), ..., b(*),
+ b(*) ... .
+ 'separate-documents-collated-copies': If a Job object has multiple
+ documents, say, the document data is called a and b, then the
+ result of processing the data in each document instance MUST be
+ treated as a single sequence of media sheets for finishing
+ operations; that is, the sets a(*) and b(*) would each be
+ finished separately. The Printer object MUST force each copy of
+ the result of processing the data in a single document to start
+ on a new media sheet. If more than one copy is made, the
+ ordering of the sets of media sheets resulting from processing
+ the document data MUST be a(*), b(*), a(*), b(*), ... .
+ 'single-document-new-sheet': Same as 'single-document', except
+ that the Printer object MUST ensure that the first impression
+ of each document instance in the job is placed on a new media
+ sheet. This value allows multiple documents to be stapled
+ together with a single staple where each document starts on a
+ new sheet.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 97]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The 'single-document' value is the same as 'separate-documents-
+ collated-copies' with respect to ordering of print-stream pages, but
+ not media sheet generation, since 'single-document' will put the
+ first page of the next document on the back side of a sheet if an odd
+ number of pages have been produced so far for the job, while
+ 'separate-documents-collated- copies' always forces the next document
+ or document copy on to a new sheet. In addition, if the "finishings"
+ attribute specifies 'staple', then with 'single-document', documents
+ a and b are stapled together as a single document with no regard to
+ new sheets, with 'single-document-new-sheet', documents a and b are
+ stapled together as a single document, but document b starts on a new
+ sheet, but with 'separate-documents-uncollated-copies' and
+ 'separate-documents-collated-copies', documents a and b are stapled
+ separately.
+
+ Note: None of these values provide means to produce uncollated sheets
+ within a document, i.e., where multiple copies of sheet n are
+ produced before sheet n+1 of the same document.
+
+ The relationship of this attribute and the other attributes that
+ control document processing is described in section 15.3.
+
+4.2.5 copies (integer(1:MAX))
+
+ This attribute specifies the number of copies to be printed.
+
+ On many devices the supported number of collated copies will be
+ limited by the number of physical output bins on the device, and may
+ be different from the number of uncollated copies which can be
+ supported.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.6 finishings (1setOf type2 enum)
+
+ This attribute identifies the finishing operations that the Printer
+ uses for each copy of each printed document in the Job. For Jobs with
+ multiple documents, the "multiple-document-handling" attribute
+ determines what constitutes a "copy" for purposes of finishing.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 98]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'none': Perform no finishing
+ '4' 'staple': Bind the document(s) with one or more staples. The
+ exact number and placement of the staples is site-
+ defined.
+ '5' 'punch': This value indicates that holes are required in the
+ finished document. The exact number and placement of the
+ holes is site-defined The punch specification MAY be
+ satisfied (in a site- and implementation-specific manner)
+ either by drilling/punching, or by substituting pre-
+ drilled media.
+ '6' 'cover': This value is specified when it is desired to select
+ a non-printed (or pre-printed) cover for the document.
+ This does not supplant the specification of a printed
+ cover (on cover stock medium) by the document itself.
+ '7' 'bind': This value indicates that a binding is to be applied
+ to the document; the type and placement of the binding is
+ site-defined.
+ '8' 'saddle-stitch': Bind the document(s) with one or more
+ staples (wire stitches) along the middle fold. The exact
+ number and placement of the staples and the middle fold
+ is implementation and/or site-defined.
+ '9' 'edge-stitch': Bind the document(s) with one or more staples
+ (wire stitches) along one edge. The exact number and
+ placement of the staples is implementation and/or site-
+ defined.
+ '10'-'19' reserved for future generic finishing enum values.
+
+ The following values are more specific; they indicate a corner or an
+ edge as if the document were a portrait document (see below):
+
+ '20' 'staple-top-left': Bind the document(s) with one or more
+ staples in the top left corner.
+ '21' 'staple-bottom-left': Bind the document(s) with one or more
+ staples in the bottom left corner.
+ '22' 'staple-top-right': Bind the document(s) with one or more
+ staples in the top right corner.
+ '23' 'staple-bottom-right': Bind the document(s) with one or more
+ staples in the bottom right corner.
+ '24' 'edge-stitch-left': Bind the document(s) with one or more
+ staples (wire stitches) along the left edge. The exact
+ number and placement of the staples is implementation
+ and/or site-defined.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 99]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ '25' 'edge-stitch-top': Bind the document(s) with one or more
+ staples (wire stitches) along the top edge. The exact
+ number and placement of the staples is implementation
+ and/or site-defined.
+ '26' 'edge-stitch-right': Bind the document(s) with one or more
+ staples (wire stitches) along the right edge. The exact
+ number and placement of the staples is implementation
+ and/or site-defined.
+ '27' 'edge-stitch-bottom': Bind the document(s) with one or more
+ staples (wire stitches) along the bottom edge. The exact
+ number and placement of the staples is implementation
+ and/or site-defined.
+ '28' 'staple-dual-left': Bind the document(s) with two staples
+ (wire stitches) along the left edge assuming a portrait
+ document (see above).
+ '29' 'staple-dual-top': Bind the document(s) with two staples
+ (wire stitches) along the top edge assuming a portrait
+ document (see above).
+ '30' 'staple-dual-right': Bind the document(s) with two staples
+ (wire stitches) along the right edge assuming a portrait
+ document (see above).
+ '31' 'staple-dual-bottom': Bind the document(s) with two staples
+ (wire stitches) along the bottom edge assuming a portrait
+ document (see above).
+
+ The 'staple-xxx' values are specified with respect to the document as
+ if the document were a portrait document. If the document is
+ actually a landscape or a reverse-landscape document, the client
+ supplies the appropriate transformed value. For example, to position
+ a staple in the upper left hand corner of a landscape document when
+ held for reading, the client supplies the 'staple-bottom-left' value
+ (since landscape is defined as a +90 degree rotation of the image
+ with respect to the media from portrait, i.e., anti-clockwise). On
+ the other hand, to position a staple in the upper left hand corner of
+ a reverse-landscape document when held for reading, the client
+ supplies the 'staple-top-right' value (since reverse-landscape is
+ defined as a -90 degree rotation of the image with respect to the
+ media from portrait, i.e., clockwise).
+
+ The angle (vertical, horizontal, angled) of each staple with respect
+ to the document depends on the implementation which may in turn
+ depend on the value of the attribute.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+
+
+Hastings, et al. Standards Track [Page 100]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If the client supplies a value of 'none' along with any other
+ combination of values, it is the same as if only that other
+ combination of values had been supplied (that is the 'none' value has
+ no effect).
+
+4.2.7 page-ranges (1setOf rangeOfInteger (1:MAX))
+
+ This attribute identifies the range(s) of print-stream pages that the
+ Printer object uses for each copy of each document which are to be
+ printed. Nothing is printed for any pages identified that do not
+ exist in the document(s). Ranges MUST be in ascending order, for
+ example: 1-3, 5-7, 15-19 and MUST NOT overlap, so that a non-spooling
+ Printer object can process the job in a single pass. If the ranges
+ are not ascending or are overlapping, the IPP object MUST reject the
+ request and return the 'client-error-bad-request' status code. The
+ attribute is associated with print-stream pages not application-
+ numbered pages (for example, the page numbers found in the headers
+ and or footers for certain word processing applications).
+
+ For Jobs with multiple documents, the "multiple-document-handling"
+ attribute determines what constitutes a "copy" for purposes of the
+ specified page range(s). When "multiple-document-handling" is
+ 'single-document', the Printer object MUST apply each supplied page
+ range once to the concatenation of the print-stream pages. For
+ example, if there are 8 documents of 10 pages each, the page-range
+ '41:60' prints the pages in the 5th and 6th documents as a single
+ document and none of the pages of the other documents are printed.
+ When "multiple-document- handling" is 'separate-documents-
+ uncollated-copies' or 'separate-documents-collated-copies', the
+ Printer object MUST apply each supplied page range repeatedly to each
+ document copy. For the same job, the page-range '1:3, 10:10' would
+ print the first 3 pages and the 10th page of each of the 8 documents
+ in the Job, as 8 separate documents.
+
+ In most cases, the exact pages to be printed will be generated by a
+ device driver and this attribute would not be required. However,
+ when printing an archived document which has already been formatted,
+ the end user may elect to print just a subset of the pages contained
+ in the document. In this case, if page-range = n.m is specified, the
+ first page to be printed will be page n. All subsequent pages of the
+ document will be printed through and including page m.
+
+ "page-ranges-supported" is a boolean value indicating whether or not
+ the printer is capable of supporting the printing of page ranges.
+ This capability may differ from one PDL to another. There is no
+ "page-ranges-default" attribute. If the "page-ranges" attribute is
+ not supplied by the client, all pages of the document will be
+ printed.
+
+
+
+Hastings, et al. Standards Track [Page 101]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.8 sides (type2 keyword)
+
+ This attribute specifies how print-stream pages are to be imposed
+ upon the sides of an instance of a selected medium, i.e., an
+ impression.
+
+ The standard keyword values are:
+
+ 'one-sided': imposes each consecutive print-stream page upon the
+ same side of consecutive media sheets.
+ 'two-sided-long-edge': imposes each consecutive pair of print-
+ stream pages upon front and back sides of consecutive media
+ sheets, such that the orientation of each pair of print-stream
+ pages on the medium would be correct for the reader as if for
+ binding on the long edge. This imposition is sometimes called
+ 'duplex' or 'head-to-head'.
+ 'two-sided-short-edge': imposes each consecutive pair of print-
+ stream pages upon front and back sides of consecutive media
+ sheets, such that the orientation of each pair of print-stream
+ pages on the medium would be correct for the reader as if for
+ binding on the short edge. This imposition is sometimes called
+ 'tumble' or 'head-to-toe'.
+ 'two-sided-long-edge', 'two-sided-short-edge',
+ 'tumble', and 'duplex' all work the same for portrait or
+ landscape. However
+ 'head-to-toe' is
+ 'tumble' in portrait but 'duplex' in landscape. 'head-to-head'
+ also switches between 'duplex' and 'tumble' when using portrait
+ and landscape modes.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.9 number-up (integer(1:MAX))
+
+ This attribute specifies the number of print-stream pages to impose
+ upon a single side of an instance of a selected medium. For example,
+ if the value is:
+
+
+
+
+Hastings, et al. Standards Track [Page 102]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Value Description
+
+ '1' the Printer MUST place one print-stream page on a single side
+ of an instance of the selected medium (MAY add some sort
+ of translation, scaling, or rotation).
+ '2' the Printer MUST place two print-stream pages on a single side
+ of an instance of the selected medium (MAY add some sort
+ of translation, scaling, or rotation).
+ '4' the Printer MUST place four print-stream pages on a single
+ side of an instance of the selected medium (MAY add some
+ sort of translation, scaling, or rotation).
+
+ This attribute primarily controls the translation, scaling and
+ rotation of print-stream pages.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.10 orientation-requested (type2 enum)
+
+ This attribute indicates the desired orientation for printed print-
+ stream pages; it does not describe the orientation of the client-
+ supplied print-stream pages.
+
+ For some document formats (such as 'application/postscript'), the
+ desired orientation of the print-stream pages is specified within the
+ document data. This information is generated by a device driver
+ prior to the submission of the print job. Other document formats
+ (such as 'text/plain') do not include the notion of desired
+ orientation within the document data. In the latter case it is
+ possible for the Printer object to bind the desired orientation to
+ the document data after it has been submitted. It is expected that a
+ Printer object would only support "orientations-requested" for some
+ document formats (e.g., 'text/plain' or 'text/html') but not others
+ (e.g., 'application/postscript'). This is no different than any
+ other Job Template attribute since section 4.2, item 1, points out
+ that a Printer object may support or not support any Job Template
+ attribute based on the document format supplied by the client.
+ However, a special mention is made here since it is very likely that
+ a Printer object will support "orientation-requested" for only a
+ subset of the supported document formats.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 103]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'portrait': The content will be imaged across the short edge
+ of the medium.
+ '4' 'landscape': The content will be imaged across the long edge
+ of the medium. Landscape is defined to be a rotation of
+ the print-stream page to be imaged by +90 degrees with
+ respect to the medium (i.e. anti-clockwise) from the
+ portrait orientation. Note: The +90 direction was
+ chosen because simple finishing on the long edge is the
+ same edge whether portrait or landscape
+ '5' 'reverse-landscape': The content will be imaged across the
+ long edge of the medium. Reverse-landscape is defined to
+ be a rotation of the print-stream page to be imaged by -
+ 90 degrees with respect to the medium (i.e. clockwise)
+ from the portrait orientation. Note: The 'reverse-
+ landscape' value was added because some applications
+ rotate landscape -90 degrees from portrait, rather than
+ +90 degrees.
+ '6' 'reverse-portrait': The content will be imaged across the
+ short edge of the medium. Reverse-portrait is defined to
+ be a rotation of the print-stream page to be imaged by
+ 180 degrees with respect to the medium from the portrait
+ orientation. Note: The 'reverse-portrait' value was
+ added for use with the "finishings" attribute in cases
+ where the opposite edge is desired for finishing a
+ portrait document on simple finishing devices that have
+ only one finishing position. Thus a 'text'/plain'
+ portrait document can be stapled "on the right" by a
+ simple finishing device as is common use with some middle
+ eastern languages such as Hebrew.
+
+ Note: The effect of this attribute on jobs with multiple documents is
+ controlled by the "multiple-document-handling" job attribute (section
+ 4.2.4) and the relationship of this attribute and the other
+ attributes that control document processing is described in section
+ 15.3.
+
+4.2.11 media (type3 keyword | name(MAX))
+
+ This attribute identifies the medium that the Printer uses for all
+ impressions of the Job.
+
+ The values for "media" include medium-names, medium-sizes, input-
+ trays and electronic forms so that one attribute specifies the media.
+ If a Printer object supports a medium name as a value of this
+
+
+
+Hastings, et al. Standards Track [Page 104]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ attribute, such a medium name implicitly selects an input-tray that
+ contains the specified medium. If a Printer object supports a medium
+ size as a value of this attribute, such a medium size implicitly
+ selects a medium name that in turn implicitly selects an input-tray
+ that contains the medium with the specified size. If a Printer
+ object supports an input-tray as the value of this attribute, such an
+ input-tray implicitly selects the medium that is in that input-tray
+ at the time the job prints. This case includes manual-feed input-
+ trays. If a Printer object supports an electronic form as the value
+ of this attribute, such an electronic form implicitly selects a
+ medium-name that in turn implicitly selects an input-tray that
+ contains the medium specified by the electronic form. The electronic
+ form also implicitly selects an image that the Printer MUST merge
+ with the document data as its prints each page.
+
+ Standard keyword values are taken from ISO DPA [ISO10175], the
+ Printer MIB [RFC1759], and ASME-Y14.1M [ASME-Y14.1M] and are listed
+ in section 14. An administrator MAY define additional values using
+ the 'name' or 'keyword' attribute syntax, depending on
+ implementation.
+
+ There is also an additional Printer attribute named "media-ready"
+ which differs from "media-supported" in that legal values only
+ include the subset of "media-supported" values that are physically
+ loaded and ready for printing with no operator intervention required.
+ If an IPP object supports "media-supported", it NEED NOT support
+ "media-ready".
+
+ The relationship of this attribute and the other attributes that
+ control document processing is described in section 15.3.
+
+4.2.12 printer-resolution (resolution)
+
+ This attribute identifies the resolution that Printer uses for the
+ Job.
+
+4.2.13 print-quality (type2 enum)
+
+ This attribute specifies the print quality that the Printer uses for
+ the Job.
+
+ The standard enum values are:
+
+ Value Symbolic Name and Description
+
+ '3' 'draft': lowest quality available on the printer
+ '4' 'normal': normal or intermediate quality on the printer
+ '5' 'high': highest quality available on the printer
+
+
+
+Hastings, et al. Standards Track [Page 105]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3 Job Description Attributes
+
+ The attributes in this section form the attribute group called "job-
+ description". The following table summarizes these attributes. The
+ third column indicates whether the attribute is a REQUIRED attribute
+ that MUST be supported by Printer objects. If it is not indicated as
+ REQUIRED, then it is OPTIONAL. The maximum size in octets for 'text'
+ and 'name' attributes is indicated in parenthesizes.
+
+ +----------------------------+----------------------+--------------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+----------------------+--------------+
+ | job-uri | uri | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-id | integer(1:MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-printer-uri | uri | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-more-info | uri | |
+ +----------------------------+----------------------+--------------+
+ | job-name | name (MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-originating-user-name | name (MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-state | type1 enum | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-state-reasons | 1setOf type2 keyword | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-state-message | text (MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-detailed-status- | 1setOf text (MAX) | |
+ | messages | | |
+ +----------------------------+----------------------+--------------+
+ | job-document-access-errors | 1setOf text (MAX) | |
+ +----------------------------+----------------------+--------------+
+ | number-of-documents | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | output-device-assigned | name (127) | |
+ +----------------------------+----------------------+--------------+
+ | time-at-creation | integer (MIN:MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | time-at-processing | integer (MIN:MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | time-at-completed | integer (MIN:MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | job-printer-up-time | integer (1:MAX) | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | date-time-at-creation | dateTime | |
+
+
+
+Hastings, et al. Standards Track [Page 106]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ +----------------------------+----------------------+--------------+
+ | date-time-at-processing | dateTime | |
+ +----------------------------+----------------------+--------------+
+ | date-time-at-completed | dateTime | |
+ +----------------------------+----------------------+--------------+
+ | number-of-intervening-jobs | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-message-from-operator | text (127) | |
+ +----------------------------+----------------------+--------------+
+ | job-k-octets | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-impressions | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-media-sheets | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-k-octets-processed | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-impressions-completed | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | job-media-sheets-completed | integer (0:MAX) | |
+ +----------------------------+----------------------+--------------+
+ | attributes-charset | charset | REQUIRED |
+ +----------------------------+----------------------+--------------+
+ | attributes-natural-language| naturalLanguage | REQUIRED |
+ +----------------------------+----------------------+--------------+
+
+4.3.1 job-uri (uri)
+
+ This REQUIRED attribute contains the URI for the job. The Printer
+ object, on receipt of a new job, generates a URI which identifies the
+ new Job. The Printer object returns the value of the "job-uri"
+ attribute as part of the response to a create request. The precise
+ format of a Job URI is implementation dependent. If the Printer
+ object supports more than one URI and there is some relationship
+ between the newly formed Job URI and the Printer object's URI, the
+ Printer object uses the Printer URI supplied by the client in the
+ create request. For example, if the create request comes in over a
+ secure channel, the new Job URI MUST use the same secure channel.
+ This can be guaranteed because the Printer object is responsible for
+ generating the Job URI and the Printer object is aware of its
+ security configuration and policy as well as the Printer URI used in
+ the create request.
+
+ For a description of this attribute and its relationship to "job-id"
+ and "job-printer-uri" attribute, see the discussion in section 2.4 on
+ "Object Identity".
+
+
+
+
+
+Hastings, et al. Standards Track [Page 107]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.2 job-id (integer(1:MAX))
+
+ This REQUIRED attribute contains the ID of the job. The Printer, on
+ receipt of a new job, generates an ID which identifies the new Job on
+ that Printer. The Printer returns the value of the "job-id"
+ attribute as part of the response to a create request. The 0 value
+ is not included to allow for compatibility with SNMP index values
+ which also cannot be 0.
+
+ For a description of this attribute and its relationship to "job-uri"
+ and "job-printer-uri" attribute, see the discussion in section 2.4 on
+ "Object Identity".
+
+4.3.3 job-printer-uri (uri)
+
+ This REQUIRED attribute identifies the Printer object that created
+ this Job object. When a Printer object creates a Job object, it
+ populates this attribute with the Printer object URI that was used in
+ the create request. This attribute permits a client to identify the
+ Printer object that created this Job object when only the Job
+ object's URI is available to the client. The client queries the
+ creating Printer object to determine which languages, charsets,
+ operations, are supported for this Job.
+
+ For a description of this attribute and its relationship to "job-uri"
+ and "job-id" attribute, see the discussion in section 2.4 on "Object
+ Identity".
+
+4.3.4 job-more-info (uri)
+
+ Similar to "printer-more-info", this attribute contains the URI
+ referencing some resource with more information about this Job
+ object, perhaps an HTML page containing information about the Job.
+
+4.3.5 job-name (name(MAX))
+
+ This REQUIRED attribute is the name of the job. It is a name that is
+ more user friendly than the "job-uri" attribute value. It does not
+ need to be unique between Jobs. The Job's "job-name" attribute is
+ set to the value supplied by the client in the "job-name" operation
+ attribute in the create request (see Section 3.2.1.1). If, however,
+ the "job-name" operation attribute is not supplied by the client in
+ the create request, the Printer object, on creation of the Job, MUST
+ generate a name. The printer SHOULD generate the value of the Job's
+ "job-name" attribute from the first of the following sources that
+ produces a value: 1) the "document-name" operation attribute of the
+
+
+
+
+
+Hastings, et al. Standards Track [Page 108]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ first (or only) document, 2) the "document-URI" attribute of the
+ first (or only) document, or 3) any other piece of Job specific
+ and/or Document Content information.
+
+4.3.6 job-originating-user-name (name(MAX))
+
+ This REQUIRED attribute contains the name of the end user that
+ submitted the print job. The Printer object sets this attribute to
+ the most authenticated printable name that it can obtain from the
+ authentication service over which the IPP operation was received.
+ Only if such is not available, does the Printer object use the value
+ supplied by the client in the "requesting-user-name" operation
+ attribute of the create operation (see Sections 4.4.2, 4.4.3, and 8).
+
+ Note: The Printer object needs to keep an internal originating user
+ id of some form, typically as a credential of a principal, with the
+ Job object. Since such an internal attribute is implementation-
+ dependent and not of interest to clients, it is not specified as a
+ Job Description attribute. This originating user id is used for
+ authorization checks (if any) on all subsequent operations.
+
+4.3.7 job-state (type1 enum)
+
+ This REQUIRED attribute identifies the current state of the job.
+ Even though the IPP protocol defines seven values for job states
+ (plus the out-of-band 'unknown' value - see Section 4.1),
+ implementations only need to support those states which are
+ appropriate for the particular implementation. In other words, a
+ Printer supports only those job states implemented by the output
+ device and available to the Printer object implementation.
+
+ Standard enum values are:
+
+ Values Symbolic Name and Description
+
+ '3' 'pending': The job is a candidate to start processing, but is
+ not yet processing.
+
+ '4' 'pending-held': The job is not a candidate for processing for
+ any number of reasons but will return to the 'pending'
+ state as soon as the reasons are no longer present. The
+ job's "job-state-reason" attribute MUST indicate why the
+ job is no longer a candidate for processing.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 109]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ '5' 'processing': One or more of:
+
+ 1. the job is using, or is attempting to use, one or
+ more purely software processes that are analyzing,
+ creating, or interpreting a PDL, etc.,
+ 2. the job is using, or is attempting to use, one or
+ more hardware devices that are interpreting a PDL, making
+ marks on a medium, and/or performing finishing, such as
+ stapling, etc.,
+ 3. the Printer object has made the job ready for
+ printing, but the output device is not yet printing it,
+ either because the job hasn't reached the output device
+ or because the job is queued in the output device or some
+ other spooler, awaiting the output device to print it.
+
+ When the job is in the 'processing' state, the entire job
+ state includes the detailed status represented in the
+ Printer object's "printer-state", "printer-state-
+ reasons", and "printer-state-message" attributes.
+
+ Implementations MAY, though they NEED NOT, include
+ additional values in the job's "job-state-reasons"
+ attribute to indicate the progress of the job, such as
+ adding the 'job-printing' value to indicate when the
+ output device is actually making marks on paper and/or
+ the 'processing-to-stop-point' value to indicate that the
+ IPP object is in the process of canceling or aborting the
+ job. Most implementations won't bother with this nuance.
+
+ '6' 'processing-stopped': The job has stopped while processing
+ for any number of reasons and will return to the
+ 'processing' state as soon as the reasons are no longer
+ present.
+
+ The job's "job-state-reason" attribute MAY indicate why
+ the job has stopped processing. For example, if the
+ output device is stopped, the 'printer-stopped' value MAY
+ be included in the job's "job-state-reasons" attribute.
+
+ Note: When an output device is stopped, the device
+ usually indicates its condition in human readable form
+ locally at the device. A client can obtain more complete
+ device status remotely by querying the Printer object's
+ "printer-state", "printer-state-reasons" and "printer-
+ state-message" attributes.
+
+ '7' 'canceled': The job has been canceled by a Cancel-Job
+ operation and the Printer object has completed canceling
+
+
+
+Hastings, et al. Standards Track [Page 110]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ the job and all job status attributes have reached their
+ final values for the job. While the Printer object is
+ canceling the job, the job remains in its current state,
+ but the job's "job-state-reasons" attribute SHOULD
+ contain the 'processing-to-stop-point' value and one of
+ the 'canceled-by-user', 'canceled-by-operator', or
+ 'canceled-at-device' value. When the job moves to the
+ 'canceled' state, the 'processing-to-stop-point' value,
+ if present, MUST be removed, but the 'canceled-by-xxx',
+ if present, MUST remain.
+
+ '8' 'aborted': The job has been aborted by the system, usually
+ while the job was in the 'processing' or 'processing-
+ stopped' state and the Printer has completed aborting the
+ job and all job status attributes have reached their
+ final values for the job. While the Printer object is
+ aborting the job, the job remains in its current state,
+ but the job's "job-state-reasons" attribute SHOULD
+ contain the 'processing-to-stop-point' and 'aborted-by-
+ system' values. When the job moves to the 'aborted'
+ state, the 'processing-to-stop-point' value, if present,
+ MUST be removed, but the 'aborted-by-system' value, if
+ present, MUST remain.
+
+ '9' 'completed': The job has completed successfully or with
+ warnings or errors after processing and all of the job
+ media sheets have been successfully stacked in the
+ appropriate output bin(s) and all job status attributes
+ have reached their final values for the job. The job's
+ "job-state-reasons" attribute SHOULD contain one of:
+ 'completed-successfully', 'completed-with-warnings', or
+ 'completed-with-errors' values.
+
+ The final value for this attribute MUST be one of: 'completed',
+ 'canceled', or 'aborted' before the Printer removes the job
+ altogether. The length of time that jobs remain in the 'canceled',
+ 'aborted', and 'completed' states depends on implementation. See
+ section 4.3.7.2.
+
+ The following figure shows the normal job state transitions.
+
+ +----> canceled
+ /
+ +----> pending --------> processing ---------+------> completed
+ | ^ ^ \
+ --->+ | | +----> aborted
+ | v v /
+ +----> pending-held processing-stopped ---+
+
+
+
+Hastings, et al. Standards Track [Page 111]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Normally a job progresses from left to right. Other state
+ transitions are unlikely, but are not forbidden. Not shown are the
+ transitions to the 'canceled' state from the 'pending', 'pending-
+ held', and 'processing-stopped' states.
+
+ Jobs reach one of the three terminal states: 'completed', 'canceled',
+ or 'aborted', after the jobs have completed all activity, including
+ stacking output media, after the jobs have completed all activity,
+ and all job status attributes have reached their final values for the
+ job.
+
+4.3.7.1 Forwarding Servers
+
+ As with all other IPP attributes, if the implementation cannot
+ determine the correct value for this attribute, it SHOULD respond
+ with the out-of-band value 'unknown' (see section 4.1) rather than
+ try to guess at some possibly incorrect value and give the end user
+ the wrong impression about the state of the Job object. For example,
+ if the implementation is just a gateway into some printing system
+ from which it can normally get status, but temporarily is unable,
+ then the implementation should return the 'unknown' value. However,
+ if the implementation is a gateway to a printing system that never
+ provides detailed status about the print job, the implementation MAY
+ set the IPP Job object's state to 'completed', provided that it also
+ sets the 'queued-in-device' value in the job's "job-state-reasons"
+ attribute (see section 4.3.8).
+
+4.3.7.2 Partitioning of Job States
+
+ This section partitions the 7 job states into phases: Job Not
+ Completed, Job Retention, Job History, and Job Removal. This section
+ also explains the 'job-restartable' value of the "job-state-reasons"
+ Job Description attribute for use with the Restart-Job operation.
+
+ Job Not Completed: When a job is in the 'pending', 'pending-held',
+ 'processing', or 'processing-stopped' states, the job is not
+ completed.
+
+ Job Retention: When a job enters one of the three terminal job
+ states: 'completed', 'canceled', or 'aborted', the IPP Printer
+ object MAY "retain" the job in a restartable condition for an
+ implementation-defined time period. This time period MAY be zero
+ seconds and MAY depend on the terminal job state. This phase is
+ called Job Retention. While in the Job Retention phase, the job's
+ document data is retained and a client may restart the job using the
+ Restart-Job operation. If the IPP object supports the Restart-Job
+
+
+
+
+
+Hastings, et al. Standards Track [Page 112]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ operation, then it SHOULD indicate that the job is restartable by
+ adding the 'job-restartable' value to the job's "job-state-reasons"
+ attribute (see Section 4.3.8) during the Job Retention phase.
+
+ Job History: After the Job Retention phase expires for a job, the
+ Printer object deletes the document data for the job and the job
+ becomes part of the Job History. The Printer object MAY also delete
+ any number of the job attributes. Since the job is no longer
+ restartable, the Printer object MUST remove the 'job-restartable'
+ value from the job's "job-state-reasons" attribute, if present.
+
+ Job Removal: After the job has remained in the Job History for an
+ implementation-defined time, such as when the number of jobs exceeds
+ a fixed number or after a fixed time period (which MAY be zero
+ seconds), the IPP Printer removes the job from the system.
+
+ Using the Get-Jobs operation and supplying the 'not-completed' value
+ for the "which-jobs" operation attribute, a client is requesting jobs
+ in the Job Not Completed phase. Using the Get-Jobs operation and
+ supplying the 'completed' value for the "which-jobs" operation
+ attribute, a client is requesting jobs in the Job Retention and Job
+ History phases. Using the Get-Job-Attributes operation, a client is
+ requesting a job in any phase except Job Removal. After Job Removal,
+ the Get-Job-Attributes and Get-Jobs operations no longer are capable
+ of returning any information about a job.
+
+4.3.8 job-state-reasons (1setOf type2 keyword)
+
+ This REQUIRED attribute provides additional information about the
+ job's current state, i.e., information that augments the value of the
+ job's "job-state" attribute.
+
+ These values MAY be used with any job state or states for which the
+ reason makes sense. Some of these value definitions indicate
+ conformance requirements; the rest are OPTIONAL. Furthermore, when
+ implemented, the Printer MUST return these values when the reason
+ applies and MUST NOT return them when the reason no longer applies
+ whether the value of the Job's "job-state" attribute changed or not.
+ When the Job does not have any reasons for being in its current
+ state, the value of the Job's "job-state-reasons" attribute MUST be
+ 'none'.
+
+ Note: While values cannot be added to the 'job-state' attribute
+ without impacting deployed clients that take actions upon receiving
+ "job-state" values, it is the intent that additional "job-state-
+ reasons" values can be defined and registered without impacting such
+ deployed clients. In other words, the "job-state-reasons" attribute
+ is intended to be extensible.
+
+
+
+Hastings, et al. Standards Track [Page 113]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following standard keyword values are defined. For ease of
+ understanding, the values are presented in the order in which the
+ reasons are likely to occur (if implemented), starting with the
+ 'job-incoming' value:
+
+ 'none': There are no reasons for the job's current state. This
+ state reason is semantically equivalent to "job-state-reasons"
+ without any value and MUST be used when there is no other
+ value, since the 1setOf attribute syntax requires at least one
+ value.
+ 'job-incoming': Either (1) the Printer has accepted the Create-
+ Job operation and is expecting additional Send-Document and/or
+ Send-URI operations, or (2) the Printer is retrieving/accepting
+ document data as a result of a Print-Job, Print-URI, Send-
+ Document or Send-URI operation.
+ 'job-data-insufficient': The Create-Job operation has been
+ accepted by the Printer, but the Printer is expecting
+ additional document data before it can move the job into the
+ 'processing' state. If a Printer starts processing before it
+ has received all data, the Printer removes the 'job-data-
+ insufficient' reason, but the 'job-incoming' remains. If a
+ Printer starts processing after it has received all data, the
+ Printer removes the 'job-data-insufficient' reason and the
+ 'job-incoming' at the same time.
+ 'document-access-error': After accepting a Print-URI or Send-URI
+ request, the Printer could not access one or more documents
+ passed by reference. This reason is intended to cover any file
+ access problem, including file does not exist and access denied
+ because of an access control problem. The Printer MAY also
+ indicate the document access error using the "job-document-
+ access-errors" Job Description attribute (see section 4.3.11).
+ Whether the Printer aborts the job and moves the job to the
+ 'aborted' job state or prints all documents that are accessible
+ and moves the job to the 'completed' job state and adds the
+ 'completed-with-errors' value in the job's "job-state-reasons"
+ attribute depends on implementation and/or site policy. This
+ value SHOULD be supported if the Print-URI or Send-URI
+ operations are supported.
+ 'submission-interrupted': The job was not completely submitted
+ for some unforeseen reason, such as: (1) the Printer has
+ crashed before the job was closed by the client, (2) the
+ Printer or the document transfer method has crashed in some
+ non-recoverable way before the document data was entirely
+ transferred to the Printer, (3) the client crashed or failed to
+ close the job before the time-out period. See section 4.4.31.
+ 'job-outgoing': The Printer is transmitting the job to the output
+ device.
+
+
+
+
+Hastings, et al. Standards Track [Page 114]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'job-hold-until-specified': The value of the job's "job-hold-
+ until" attribute was specified with a time period that is still
+ in the future. The job MUST NOT be a candidate for processing
+ until this reason is removed and there are no other reasons to
+ hold the job. This value SHOULD be supported if the "job-
+ hold-until" Job Template attribute is supported.
+ 'resources-are-not-ready': At least one of the resources needed
+ by the job, such as media, fonts, resource objects, etc., is
+ not ready on any of the physical printer's for which the job is
+ a candidate. This condition MAY be detected when the job is
+ accepted, or subsequently while the job is pending or
+ processing, depending on implementation. The job may remain in
+ its current state or be moved to the 'pending-held' state,
+ depending on implementation and/or job scheduling policy.
+ 'printer-stopped-partly': The value of the Printer's "printer-
+ state-reasons" attribute contains the value 'stopped-partly'.
+ 'printer-stopped': The value of the Printer's "printer-state"
+ attribute is 'stopped'.
+ 'job-interpreting': Job is in the 'processing' state, but more
+ specifically, the Printer is interpreting the document data.
+ 'job-queued': Job is in the 'processing' state, but more
+ specifically, the Printer has queued the document data.
+ 'job-transforming': Job is in the 'processing' state, but more
+ specifically, the Printer is interpreting document data and
+ producing another electronic representation.
+ 'job-queued-for-marker': Job is in any of the 'pending-held',
+ 'pending', or 'processing' states, but more specifically, the
+ Printer has completed enough processing of the document to be
+ able to start marking and the job is waiting for the marker.
+ Systems that require human intervention to release jobs using
+ the Release-Job operation, put the job into the 'pending-held'
+ job state. Systems that automatically select a job to use the
+ marker put the job into the 'pending' job state or keep the
+ job in the 'processing' job state while waiting for the marker,
+ depending on implementation. All implementations put the job
+ into (or back into) the 'processing' state when marking does
+ begin.
+ 'job-printing': The output device is marking media. This value is
+ useful for Printers which spend a great deal of time processing
+ (1) when no marking is happening and then want to show that
+ marking is now happening or (2) when the job is in the process
+ of being canceled or aborted while the job remains in the
+ 'processing' state, but the marking has not yet stopped so that
+ impression or sheet counts are still increasing for the job.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 115]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'job-canceled-by-user': The job was canceled by the owner of the
+ job using the Cancel-Job request, i.e., by a user whose
+ authenticated identity is the same as the value of the
+ originating user that created the Job object, or by some other
+ authorized end-user, such as a member of the job owner's
+ security group. This value SHOULD be supported.
+ 'job-canceled-by-operator': The job was canceled by the operator
+ using the Cancel-Job request, i.e., by a user who has been
+ authenticated as having operator privileges (whether local or
+ remote). If the security policy is to allow anyone to cancel
+ anyone's job, then this value may be used when the job is
+ canceled by other than the owner of the job. For such a
+ security policy, in effect, everyone is an operator as far as
+ canceling jobs with IPP is concerned. This value SHOULD be
+ supported if the implementation permits canceling by other than
+ the owner of the job.
+ 'job-canceled-at-device': The job was canceled by an unidentified
+ local user, i.e., a user at a console at the device. This
+ value SHOULD be supported if the implementation supports
+ canceling jobs at the console.
+ 'aborted-by-system': The job (1) is in the process of being
+ aborted, (2) has been aborted by the system and placed in the
+ 'aborted' state, or (3) has been aborted by the system and
+ placed in the 'pending-held' state, so that a user or operator
+ can manually try the job again. This value SHOULD be
+ supported.
+ 'unsupported-compression': The job was aborted by the system
+ because the Printer determined while attempting to decompress
+ the document-data's that the compression is actually not among
+ those supported by the Printer. This value MUST be supported,
+ since "compressions is a REQUIRED operation attribute.
+ 'compression-error': The job was aborted by the system because the
+ Printer encountered an error in the document-data while
+ decompressing it. If the Printer posts this reason, the
+ document-data has already passed any tests that would have led
+ to the 'unsupported-compression' job-state-reason.
+ 'unsupported-document-format': The job was aborted by the system
+ because the document-data's document-format is not among those
+ supported by the Printer. If the client specifies the
+ document-format as 'application/octet-stream', the printer MAY
+ abort the job and post this reason even though the format is a
+ member of the "document-format-supported" printer attribute,
+ but not among the auto-sensed document-formats. This value
+ MUST be supported, since "document-format" is a REQUIRED
+ operation attribute.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 116]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'document-format-error': The job was aborted by the system because
+ the Printer encountered an error in the document-data while
+ processing it. If the Printer posts this reason, the
+ document-data has already passed any tests that would have led
+ to the 'unsupported-document-format' job-state-reason.
+ 'processing-to-stop-point': The requester has issued a Cancel-Job
+ operation or the Printer object has aborted the job, but is
+ still performing some actions on the job until a specified stop
+ point occurs or job termination/cleanup is completed.
+
+ If the implementation requires some measurable time to cancel
+ the job in the 'processing' or 'processing-stopped' job states,
+ the IPP object MUST use this value to indicate that the Printer
+ object is still performing some actions on the job while the
+ job remains in the 'processing' or 'processing-stopped' state.
+ After all the job's job description attributes have stopped
+ incrementing, the Printer object moves the job from the
+ 'processing' state to the 'canceled' or
+ 'aborted' job states.
+
+ 'service-off-line': The Printer is off-line and accepting no
+ jobs. All 'pending' jobs are put into the 'pending-held'
+ state. This situation could be true if the service's or
+ document transform's input is impaired or broken.
+ 'job-completed-successfully': The job completed successfully.
+ This value SHOULD be supported.
+ 'job-completed-with-warnings': The job completed with warnings.
+ This value SHOULD be supported if the implementation detects
+ warnings.
+ 'job-completed-with-errors': The job completed with errors (and
+ possibly warnings too). This value SHOULD be supported if the
+ implementation detects errors.
+ 'job-restartable' - This job is retained (see section 4.3.7.2) and
+ is currently able to be restarted using the Restart-Job
+ operation (see section 3.3.7). If 'job-restartable' is a value
+ of the job's 'job-state-reasons' attribute, then the IPP object
+ MUST accept a Restart-Job operation for that job. This value
+ SHOULD be supported if the Restart-Job operation is supported.
+ 'queued-in-device': The job has been forwarded to a device or
+ print system that is unable to send back status. The Printer
+ sets the job's "job-state " attribute to 'completed' and adds
+ the 'queued-in-device' value to the job's "job-state-reasons"
+ attribute to indicate that the Printer has no additional
+ information about the job and never will have any better
+ information. See section 4.3.7.1.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 117]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.9 job-state-message (text(MAX))
+
+ This attribute specifies information about the "job-state" and "job-
+ state-reasons" attributes in human readable text. If the Printer
+ object supports this attribute, the Printer object MUST be able to
+ generate this message in any of the natural languages identified by
+ the Printer's "generated-natural-language-supported" attribute (see
+ the "attributes-natural-language" operation attribute specified in
+ Section 3.1.4.1).
+
+ The value SHOULD NOT contain additional information not contained in
+ the values of the "job-state" and "job-states-reasons" attributes,
+ such as interpreter error information. Otherwise, application
+ programs might attempt to parse the (localized text). For such
+ additional information such as interpreter errors for application
+ program consumption or specific document access errors, new
+ attributes with keyword values, needs to be developed and registered.
+
+4.3.10 job-detailed-status-messages (1setOf text(MAX))
+
+ This attribute specifies additional detailed and technical
+ information about the job. The Printer NEED NOT localize the
+ message(s), since they are intended for use by the system
+ administrator or other experienced technical persons. Localization
+ might obscure the technical meaning of such messages. Clients MUST
+ NOT attempt to parse the value of this attribute. See "job-
+ document-access-errors" (section 4.3.11) for additional errors that a
+ program can process.
+
+4.3.11 job-document-access-errors (1setOf text(MAX))
+
+ This attribute provides additional information about each document
+ access error for this job encountered by the Printer after it
+ returned a response to the Print-URI or Send-URI operation and
+ subsequently attempted to access document(s) supplied in the Print-
+ URI or Send-URI operation. For errors in the protocol that is
+ identified by the URI scheme in the "document-uri" operation
+ attribute, such as 'http:' or 'ftp:', the error code is returned in
+ parentheses, followed by the URI. For example:
+
+ (404) http://ftp.pwg.org/pub/pwg/ipp/new_MOD/ipp-model-v11.pdf
+
+ Most Internet protocols use decimal error codes (unlike IPP), so the
+ ASCII error code representation is in decimal.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 118]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.12 number-of-documents (integer(0:MAX))
+
+ This attribute indicates the number of documents in the job, i.e.,
+ the number of Send-Document, Send-URI, Print-Job, or Print-URI
+ operations that the Printer has accepted for this job, regardless of
+ whether the document data has reached the Printer object or not.
+
+ Implementations supporting the OPTIONAL Create-Job/Send-
+ Document/Send-URI operations SHOULD support this attribute so that
+ clients can query the number of documents in each job.
+
+4.3.13 output-device-assigned (name(127))
+
+ This attribute identifies the output device to which the Printer
+ object has assigned this job. If an output device implements an
+ embedded Printer object, the Printer object NEED NOT set this
+ attribute. If a print server implements a Printer object, the value
+ MAY be empty (zero- length string) or not returned until the Printer
+ object assigns an output device to the job. This attribute is
+ particularly useful when a single Printer object supports multiple
+ devices (so called "fan-out" - see section 2.1).
+
+4.3.14 Event Time Job Description Attributes
+
+ This section defines the Job Description attributes that indicate the
+ time at which certain events occur for a job. If the job event has
+ not yet occurred, then the IPP object MUST return the 'no-value'
+ out-of-band value (see the beginning of Section 4.1). The "time-at-
+ xxx(integer)" attributes represent time as an 'integer' representing
+ the number of seconds since the device was powered up (informally
+ called "time ticks"). The "date-time-at-xxx(dateTime)" attributes
+ represent time as 'dateTime' representing date and time (including an
+ offset from UTC).
+
+ In order to populate these attributes, the Printer object copies the
+ value(s) of the following Printer Description attributes at the time
+ the event occurs:
+
+ 1. the value in the Printer's "printer-up-time" attribute for the
+ "time-at-xxx(integer)" attributes
+
+ 2. the value in the Printer's "printer-current-time" attribute for
+ the "date-time-at-xxx(dateTime)" attributes.
+
+ If the Printer resets its "printer-up-time" attribute to 1 on power-
+ up (see section 4.4.29) and has persistent jobs, then it MUST change
+ all of jobs' "time-at-xxx(integer)" (time tick) job attributes whose
+ events have occurred either to:
+
+
+
+Hastings, et al. Standards Track [Page 119]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 1. 0 to indicate that the event happened before the most recent
+ power up OR
+
+ 2. the negative of the number of seconds before the most recent
+ power-up that the event took place, though the negative number
+ NEED NOT reflect the exact number of seconds.
+
+ If a client queries a "time-at-xxx(integer)" time tick Job attribute
+ and finds the value to be 0 or negative, the client MUST assume that
+ the event occurred in some life other than the Printer's current
+ life.
+
+ Note: A Printer does not change the values of any "date-time-at-
+ xxx(dateTime)" job attributes on power-up.
+
+4.3.14.1 time-at-creation (integer(MIN:MAX))
+
+ This REQUIRED attribute indicates the time at which the Job object
+ was created.
+
+4.3.14.2 time-at-processing (integer(MIN:MAX))
+
+ This REQUIRED attribute indicates the time at which the Job object
+ first began processing after the create operation or the most recent
+ Restart-Job operation. The out-of-band 'no-value' value is returned
+ if the job has not yet been in the 'processing' state (see the
+ beginning of Section 4.1).
+
+4.3.14.3 time-at-completed (integer(MIN:MAX))
+
+ This REQUIRED attribute indicates the time at which the Job object
+ completed (or was canceled or aborted). The out-of-band 'no-value'
+ value is returned if the job has not yet completed, been canceled, or
+ aborted (see the beginning of Section 4.1).
+
+4.3.14.4 job-printer-up-time (integer(1:MAX))
+
+ This REQUIRED Job Description attribute indicates the amount of time
+ (in seconds) that the Printer implementation has been up and running.
+ This attribute is an alias for the "printer-up-time" Printer
+ Description attribute (see Section 4.4.29).
+
+ A client MAY request this attribute in a Get-Job-Attributes or Get-
+ Jobs request and use the value returned in combination with other
+ requested Event Time Job Description Attributes in order to display
+ time attributes to a user. The difference between this attribute and
+ the 'integer' value of a "time-at-xxx" attribute is the number of
+
+
+
+
+Hastings, et al. Standards Track [Page 120]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ seconds ago that the "time-at-xxx" event occurred. A client can
+ compute the wall-clock time at which the "time-at-xxx" event occurred
+ by subtracting this difference from the client's wall-clock time.
+
+4.3.14.5 date-time-at-creation (dateTime)
+
+ This attribute indicates the date and time at which the Job object
+ was created.
+
+4.3.14.6 date-time-at-processing (dateTime)
+
+ This attribute indicates the date and time at which the Job object
+ first began processing after the create operation or the most recent
+ Restart-Job operation.
+
+4.3.14.7 date-time-at-completed (dateTime)
+
+ This attribute indicates the date and time at which the Job object
+ completed (or was canceled or aborted).
+
+4.3.15 number-of-intervening-jobs (integer(0:MAX))
+
+ This attribute indicates the number of jobs that are "ahead" of this
+ job in the relative chronological order of expected time to complete
+ (i.e., the current scheduled order). For efficiency, it is only
+ necessary to calculate this value when an operation is performed that
+ requests this attribute.
+
+4.3.16 job-message-from-operator (text(127))
+
+ This attribute provides a message from an operator, system
+ administrator or "intelligent" process to indicate to the end user
+ the reasons for modification or other management action taken on a
+ job.
+
+4.3.17 Job Size Attributes
+
+ This sub-section defines job attributes that describe the size of the
+ job. These attributes are not intended to be counters; they are
+ intended to be useful routing and scheduling information if known.
+ For these attributes, the Printer object may try to compute the value
+ if it is not supplied in the create request. Even if the client does
+ supply a value for these three attributes in the create request, the
+ Printer object MAY choose to change the value if the Printer object
+ is able to compute a value which is more accurate than the client
+ supplied value. The Printer object may be able to determine the
+ correct value for these attributes either right at job submission
+ time or at any later point in time.
+
+
+
+Hastings, et al. Standards Track [Page 121]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.17.1 job-k-octets (integer(0:MAX))
+
+ This attribute specifies the total size of the document(s) in K
+ octets, i.e., in units of 1024 octets requested to be processed in
+ the job. The value MUST be rounded up, so that a job between 1 and
+ 1024 octets MUST be indicated as being 1, 1025 to 2048 MUST be 2,
+ etc.
+
+ This value MUST NOT include the multiplicative factors contributed by
+ the number of copies specified by the "copies" attribute, independent
+ of whether the device can process multiple copies without making
+ multiple passes over the job or document data and independent of
+ whether the output is collated or not. Thus the value is independent
+ of the implementation and indicates the size of the document(s)
+ measured in K octets independent of the number of copies.
+
+ This value MUST also not include the multiplicative factor due to a
+ copies instruction embedded in the document data. If the document
+ data actually includes replications of the document data, this value
+ will include such replication. In other words, this value is always
+ the size of the source document data, rather than a measure of the
+ hardcopy output to be produced.
+
+4.3.17.2 job-impressions (integer(0:MAX))
+
+ This attribute specifies the total size in number of impressions of
+ the document(s) being submitted (see the definition of impression in
+ section 12.2.5).
+
+ As with "job-k-octets", this value MUST NOT include the
+ multiplicative factors contributed by the number of copies specified
+ by the "copies" attribute, independent of whether the device can
+ process multiple copies without making multiple passes over the job
+ or document data and independent of whether the output is collated or
+ not. Thus the value is independent of the implementation and
+ reflects the size of the document(s) measured in impressions
+ independent of the number of copies.
+
+ As with "job-k-octets", this value MUST also not include the
+ multiplicative factor due to a copies instruction embedded in the
+ document data. If the document data actually includes replications
+ of the document data, this value will include such replication. In
+ other words, this value is always the number of impressions in the
+ source document data, rather than a measure of the number of
+ impressions to be produced by the job.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 122]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.17.3 job-media-sheets (integer(0:MAX))
+
+ This attribute specifies the total number of media sheets to be
+ produced for this job.
+
+ Unlike the "job-k-octets" and the "job-impressions" attributes, this
+ value MUST include the multiplicative factors contributed by the
+ number of copies specified by the "copies" attribute and a 'number of
+ copies' instruction embedded in the document data, if any. This
+ difference allows the system administrator to control the lower and
+ upper bounds of both (1) the size of the document(s) with "job-k-
+ octets-supported" and "job-impressions-supported" and (2) the size of
+ the job with "job-media-sheets-supported".
+
+4.3.18 Job Progress Attributes
+
+ This sub-section defines job attributes that describe the progress of
+ the job. These attributes are intended to be counters. That is, the
+ value for a job that has not started processing MUST be 0. When the
+ job's "job-state" is 'processing' or 'processing-stopped', this value
+ is intended to contain the amount of the job that has been processed
+ to the time at which the attributes are requested. When the job
+ enters the 'completed', 'canceled', or 'aborted' states, these values
+ are the final values for the job.
+
+4.3.18.1 job-k-octets-processed (integer(0:MAX))
+
+ This attribute specifies the total number of octets processed in K
+ octets, i.e., in units of 1024 octets so far. The value MUST be
+ rounded up, so that a job between 1 and 1024 octets inclusive MUST be
+ indicated as being 1, 1025 to 2048 inclusive MUST be 2, etc.
+
+ For implementations where multiple copies are produced by the
+ interpreter with only a single pass over the data, the final value
+ MUST be equal to the value of the "job-k-octets" attribute. For
+ implementations where multiple copies are produced by the interpreter
+ by processing the data for each copy, the final value MUST be a
+ multiple of the value of the "job-k-octets" attribute.
+
+4.3.18.2 job-impressions-completed (integer(0:MAX))
+
+ This job attribute specifies the number of impressions completed for
+ the job so far. For printing devices, the impressions completed
+ includes interpreting, marking, and stacking the output.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 123]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.3.18.3 job-media-sheets-completed (integer(0:MAX))
+
+ This job attribute specifies the media-sheets completed marking and
+ stacking for the entire job so far whether those sheets have been
+ processed on one side or on both.
+
+4.3.19 attributes-charset (charset)
+
+ This REQUIRED attribute is populated using the value in the client
+ supplied "attributes-charset" attribute in the create request. It
+ identifies the charset (coded character set and encoding method) used
+ by any Job attributes with attribute syntax 'text' and 'name' that
+ were supplied by the client in the create request. See Section 3.1.4
+ for a complete description of the "attributes-charset" operation
+ attribute.
+
+ This attribute does not indicate the charset in which the 'text' and
+ 'name' values are stored internally in the Job object. The internal
+ charset is implementation-defined. The IPP object MUST convert from
+ whatever the internal charset is to that being requested in an
+ operation as specified in Section 3.1.4.
+
+4.3.20 attributes-natural-language (naturalLanguage)
+
+ This REQUIRED attribute is populated using the value in the client
+ supplied "attributes-natural-language" attribute in the create
+ request. It identifies the natural language used for any Job
+ attributes with attribute syntax 'text' and 'name' that were supplied
+ by the client in the create request. See Section 3.1.4 for a
+ complete description of the "attributes-natural-language" operation
+ attribute. See Sections 4.1.1.2 and 4.1.2.2 for how a Natural
+ Language Override may be supplied explicitly for each 'text' and
+ 'name' attribute value that differs from the value identified by the
+ "attributes-natural-language" attribute.
+
+4.4 Printer Description Attributes
+
+ These attributes form the attribute group called "printer-
+ description". The following table summarizes these attributes, their
+ syntax, and whether or not they are REQUIRED for a Printer object to
+ support. If they are not indicated as REQUIRED, they are OPTIONAL.
+ The maximum size in octets for 'text' and 'name' attributes is
+ indicated in parenthesizes.
+
+ Note: How these attributes are set by an Administrator is outside the
+ scope of this IPP/1.1 document.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 124]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ +----------------------------+---------------------------+-----------+
+ | Attribute | Syntax | REQUIRED? |
+ +----------------------------+---------------------------+-----------+
+ | printer-uri-supported | 1setOf uri | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | uri-security-supported | 1setOf type2 keyword | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | uri-authentication- | 1setOf type2 keyword | REQUIRED |
+ | supported | | |
+ +----------------------------+---------------------------+-----------+
+ | printer-name | name (127) | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-location | text (127) | |
+ +----------------------------+---------------------------+-----------+
+ | printer-info | text (127) | |
+ +----------------------------+---------------------------+-----------+
+ | printer-more-info | uri | |
+ +----------------------------+---------------------------+-----------+
+ | printer-driver-installer | uri | |
+ +----------------------------+---------------------------+-----------+
+ | printer-make-and-model | text (127) | |
+ +----------------------------+---------------------------+-----------+
+ | printer-more-info- | uri | |
+ | manufacturer | | |
+ +----------------------------+---------------------------+-----------+
+ | printer-state | type1 enum | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-state-reasons | 1setOf type2 keyword | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-state-message | text (MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | ipp-versions-supported | 1setOf type2 keyword | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | operations-supported | 1setOf type2 enum | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | multiple-document-jobs- | boolean | |
+ | supported | | |
+ +----------------------------+---------------------------+-----------+
+ | charset-configured | charset | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | charset-supported | 1setOf charset | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | natural-language-configured| naturalLanguage | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | generated-natural-language-| 1setOf naturalLanguage | REQUIRED |
+ | supported | | |
+ +----------------------------+---------------------------+-----------+
+ | document-format-default | mimeMediaType | REQUIRED |
+
+
+
+Hastings, et al. Standards Track [Page 125]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ +----------------------------+---------------------------+-----------+
+ | document-format-supported | 1setOf mimeMediaType | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-is-accepting-jobs | boolean | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | queued-job-count | integer (0:MAX) | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-message-from- | text (127) | |
+ | operator | | |
+ +----------------------------+---------------------------+-----------+
+ | color-supported | boolean | |
+ +----------------------------+---------------------------+-----------+
+ | reference-uri-schemes- | 1setOf uriScheme | |
+ | supported | | |
+ +----------------------------+---------------------------+-----------+
+ | pdl-override-supported | type2 keyword | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-up-time | integer (1:MAX) | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | printer-current-time | dateTime | |
+ +----------------------------+---------------------------+-----------+
+ | multiple-operation-time-out| integer (1:MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | compression-supported | 1setOf type3 keyword | REQUIRED |
+ +----------------------------+---------------------------+-----------+
+ | job-k-octets-supported | rangeOfInteger (0:MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | job-impressions-supported | rangeOfInteger (0:MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | job-media-sheets-supported | rangeOfInteger (0:MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | pages-per-minute | integer(0:MAX) | |
+ +----------------------------+---------------------------+-----------+
+ | pages-per-minute-color | integer(0:MAX) | |
+ +----------------------------+---------------------------+-----------+
+
+4.4.1 printer-uri-supported (1setOf uri)
+
+ This REQUIRED Printer attribute contains at least one URI for the
+ Printer object. It OPTIONALLY contains more than one URI for the
+ Printer object. An administrator determines a Printer object's
+ URI(s) and configures this attribute to contain those URIs by some
+ means outside the scope of this IPP/1.1 document. The precise format
+ of this URI is implementation dependent and depends on the protocol.
+ See the next two sections for a description of the "uri-security-
+ supported" and "uri-authentication-supported" attributes, both of
+
+
+
+
+
+Hastings, et al. Standards Track [Page 126]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ which are the REQUIRED companion attributes to this "printer-uri-
+ supported" attribute. See section 2.4 on Printer object identity and
+ section 8.2 on security and URIs for more information.
+
+4.4.2 uri-authentication-supported (1setOf type2 keyword)
+
+ This REQUIRED Printer attribute MUST have the same cardinality
+ (contain the same number of values) as the "printer-uri-supported"
+ attribute. This attribute identifies the Client Authentication
+ mechanism associated with each URI listed in the "printer-uri-
+ supported" attribute. The Printer object uses the specified mechanism
+ to identify the authenticated user (see section 8.3). The "i th"
+ value in "uri-authentication-supported" corresponds to the "i th"
+ value in "printer-uri-supported" and it describes the authentication
+ mechanisms used by the Printer when accessed via that URI. See
+ [RFC2910] for more details on Client Authentication.
+
+ The following standard keyword values are defined:
+
+ 'none': There is no authentication mechanism associated with the
+ URI. The Printer object assumes that the authenticated user is
+ "anonymous".
+ 'requesting-user-name': When a client performs an operation whose
+ target is the associated URI, the Printer object assumes that
+ the authenticated user is specified by the "requesting-user-
+ name" Operation attribute (see section 8.3). If the
+ "requesting-user-name" attribute is absent in a request, the
+ Printer object assumes that the authenticated user is
+ "anonymous".
+ 'basic': When a client performs an operation whose target is the
+ associated URI, the Printer object challenges the client with
+ HTTP basic authentication [RFC2617]. The Printer object assumes
+ that the authenticated user is the name received via the basic
+ authentication mechanism.
+ 'digest': When a client performs an operation whose target is the
+ associated URI, the Printer object challenges the client with
+ HTTP digest authentication [RFC2617]. The Printer object
+ assumes that the authenticated user is the name received via
+ the digest authentication mechanism.
+ 'certificate': When a client performs an operation whose target is
+ the associated URI, the Printer object expects the client to
+ provide a certificate. The Printer object assumes that the
+ authenticated user is the textual name contained within the
+ certificate.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 127]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.4.3 uri-security-supported (1setOf type2 keyword)
+
+ This REQUIRED Printer attribute MUST have the same cardinality
+ (contain the same number of values) as the "printer-uri-supported"
+ attribute. This attribute identifies the security mechanisms used
+ for each URI listed in the "printer-uri-supported" attribute. The "i
+ th" value in "uri-security-supported" corresponds to the "i th" value
+ in "printer-uri-supported" and it describes the security mechanisms
+ used for accessing the Printer object via that URI. See [RFC2910]
+ for more details on security mechanisms.
+
+ The following standard keyword values are defined:
+
+ 'none': There are no secure communication channel protocols in use
+ for the given URI.
+ 'ssl3': SSL3 [SSL] is the secure communications channel protocol
+ in use for the given URI.
+ 'tls': TLS [RFC2246] is the secure communications channel
+ protocol in use for the given URI.
+
+ This attribute is orthogonal to the definition of a Client
+ Authentication mechanism. Specifically, 'none' does not exclude
+ Client Authentication. See section 4.4.2.
+
+ Consider the following example. For a single Printer object, an
+ administrator configures the "printer-uri-supported", "uri-
+ authentication-supported" and "uri-security-supported" attributes as
+ follows:
+
+ "printer-uri-supported": 'xxx://acme.com/open-use-printer',
+ 'xxx://acme.com/restricted-use-printer',
+ 'xxx://acme.com/private-printer'
+ "uri-authentication-supported": 'none', 'digest', 'basic'
+ "uri-security-supported": 'none', 'none', 'tls'
+
+ Note: 'xxx' is not a valid scheme. See the IPP/1.1 "Transport and
+ Encoding" document [RFC2910] for the actual URI schemes to be used in
+ object target attributes.
+
+ In this case, one Printer object has three URIs.
+
+ - For the first URI, 'xxx://acme.com/open-use-printer', the value
+ 'none' in "uri-security-supported" indicates that there is no
+ secure channel protocol configured to run under HTTP. The value
+ of 'none' in "uri-authentication-supported" indicates that all
+ users are 'anonymous'. There will be no challenge and the
+ Printer will ignore "requesting-user-name".
+
+
+
+
+Hastings, et al. Standards Track [Page 128]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - For the second URI, 'xxx://acme.com/restricted-use-printer', the
+ value 'none' in "uri-security-supported" indicates that there is
+ no secure channel protocol configured to run under HTTP. The
+ value of 'digest' in "uri-authentication-supported" indicates
+ that the Printer will issue a challenge and that the Printer
+ will use the name supplied by the digest mechanism to determine
+ the authenticated user (see section 8.3).
+ - For the third URI, 'xxx://acme.com/private-printer', the value
+ 'tls' in "uri-security-supported" indicates that TLS is being
+ used to secure the channel. The client SHOULD be prepared to
+ use TLS framing to negotiate an acceptable ciphersuite to use
+ while communicating with the Printer object. In this case, the
+ name implies the use of a secure communications channel, but the
+ fact is made explicit by the presence of the 'tls' value in
+ "uri-security-supported". The client does not need to resort to
+ understanding which security it must use by following naming
+ conventions or by parsing the URI to determine which security
+ mechanisms are implied. The value of 'basic' in "uri-
+ authentication-supported" indicates that the Printer will issue
+ a challenge and that the Printer will use the name supplied by
+ the digest mechanism to determine the authenticated user (see
+ section 8.3). Because this challenge occurs in a tls session,
+ the channel is secure.
+
+ It is expected that many IPP Printer objects will be configured to
+ support only one channel (either configured to use TLS access or not)
+ and only one authentication mechanism. Such Printer objects only have
+ one URI listed in the "printer-uri-supported" attribute. No matter
+ the configuration of the Printer object (whether it has only one URI
+ or more than one URI), a client MUST supply only one URI in the
+ target "printer-uri" operation attribute.
+
+4.4.4 printer-name (name(127))
+
+ This REQUIRED Printer attribute contains the name of the Printer
+ object. It is a name that is more end-user friendly than a URI. An
+ administrator determines a printer's name and sets this attribute to
+ that name. This name may be the last part of the printer's URI or it
+ may be unrelated. In non-US-English locales, a name may contain
+ characters that are not allowed in a URI.
+
+4.4.5 printer-location (text(127))
+
+ This Printer attribute identifies the location of the device. This
+ could include things like: "in Room 123A, second floor of building
+ XYZ".
+
+
+
+
+
+Hastings, et al. Standards Track [Page 129]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.4.6 printer-info (text(127))
+
+ This Printer attribute identifies the descriptive information about
+ this Printer object. This could include things like: "This printer
+ can be used for printing color transparencies for HR presentations",
+ or "Out of courtesy for others, please print only small (1-5 page)
+ jobs at this printer", or even "This printer is going away on July 1,
+ 1997, please find a new printer".
+
+4.4.7 printer-more-info (uri)
+
+ This Printer attribute contains a URI used to obtain more information
+ about this specific Printer object. For example, this could be an
+ HTTP type URI referencing an HTML page accessible to a Web Browser.
+ The information obtained from this URI is intended for end user
+ consumption. Features outside the scope of IPP can be accessed from
+ this URI. The information is intended to be specific to this printer
+ instance and site specific services (e.g. job pricing, services
+ offered, end user assistance). The device manufacturer may initially
+ populate this attribute.
+
+4.4.8 printer-driver-installer (uri)
+
+ This Printer attribute contains a URI to use to locate the driver
+ installer for this Printer object. This attribute is intended for
+ consumption by automata. The mechanics of print driver installation
+ is outside the scope of this IPP/1.1 document. The device
+ manufacturer may initially populate this attribute.
+
+4.4.9 printer-make-and-model (text(127))
+
+ This Printer attribute identifies the make and model of the device.
+ The device manufacturer may initially populate this attribute.
+
+4.4.10 printer-more-info-manufacturer (uri)
+
+ This Printer attribute contains a URI used to obtain more information
+ about this type of device. The information obtained from this URI is
+ intended for end user consumption. Features outside the scope of IPP
+ can be accessed from this URI (e.g., latest firmware, upgrades, print
+ drivers, optional features available, details on color support). The
+ information is intended to be germane to this printer without regard
+ to site specific modifications or services. The device manufacturer
+ may initially populate this attribute.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 130]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.4.11 printer-state (type1 enum)
+
+ This REQUIRED Printer attribute identifies the current state of the
+ device. The "printer-state reasons" attribute augments the
+ "printer-state" attribute to give more detailed information about the
+ Printer in the given printer state.
+
+ A Printer object need only update this attribute before responding to
+ an operation which requests the attribute; the Printer object NEED
+ NOT update this attribute continually, since asynchronous event
+ notification is not part of IPP/1.1. A Printer NEED NOT implement
+ all values if they are not applicable to a given implementation.
+
+ The following standard enum values are defined:
+
+ Value Symbolic Name and Description
+
+ '3' 'idle': Indicates that new jobs can start processing without
+ waiting.
+ '4' 'processing': Indicates that jobs are processing; new jobs
+ will wait before processing.
+ '5' 'stopped': Indicates that no jobs can be processed and
+ intervention is required.
+
+ Values of "printer-state-reasons", such as 'spool-area-full' and
+ 'stopped-partly', MAY be used to provide further information.
+
+4.4.12 printer-state-reasons (1setOf type2 keyword)
+
+ This REQUIRED Printer attribute supplies additional detail about the
+ device's state. Some of the these value definitions indicate
+ conformance requirements; the rest are OPTIONAL.
+
+ Each keyword value MAY have a suffix to indicate its level of
+ severity. The three levels are: report (least severe), warning, and
+ error (most severe).
+
+ - '-report': This suffix indicates that the reason is a "report".
+ An implementation may choose to omit some or all reports. Some
+ reports specify finer granularity about the printer state;
+ others serve as a precursor to a warning. A report MUST contain
+ nothing that could affect the printed output.
+ - '-warning': This suffix indicates that the reason is a
+ "warning". An implementation may choose to omit some or all
+ warnings. Warnings serve as a precursor to an error. A warning
+ MUST contain nothing that prevents a job from completing, though
+ in some cases the output may be of lower quality.
+
+
+
+
+Hastings, et al. Standards Track [Page 131]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - '-error': This suffix indicates that the reason is an "error".
+ An implementation MUST include all errors. If this attribute
+ contains one or more errors, printer MUST be in the stopped
+ state.
+
+ If the implementation does not add any one of the three suffixes, all
+ parties MUST assume that the reason is an "error".
+
+ If a Printer object controls more than one output device, each value
+ of this attribute MAY apply to one or more of the output devices. An
+ error on one output device that does not stop the Printer object as a
+ whole MAY appear as a warning in the Printer's "printer-state-reasons
+ attribute". If the "printer-state" for such a Printer has a value of
+ 'stopped', then there MUST be an error reason among the values in the
+ "printer-state-reasons" attribute.
+
+ The following standard keyword values are defined:
+
+ 'other': The device has detected an error other than one listed in
+ this document.
+ 'none': There are not reasons. This state reason is semantically
+ equivalent to "printer-state-reasons" without any value and
+ MUST be used, since the 1setOf attribute syntax requires at
+ least one value.
+ 'media-needed': A tray has run out of media.
+ 'media-jam': The device has a media jam.
+ 'moving-to-paused': Someone has paused the Printer object using
+ the Pause-Printer operation (see section 3.2.7) or other means,
+ but the device(s) are taking an appreciable time to stop.
+ Later, when all output has stopped, the "printer-state" becomes
+ 'stopped', and the 'paused' value replaces the 'moving-to-
+ paused' value in the "printer-state-reasons" attribute. This
+ value MUST be supported, if the Pause-Printer operation is
+ supported and the implementation takes significant time to
+ pause a device in certain circumstances.
+ 'paused': Someone has paused the Printer object using the Pause-
+ Printer operation (see section 3.2.7) or other means and the
+ Printer object's "printer-state" is 'stopped'. In this state,
+ a Printer MUST NOT produce printed output, but it MUST perform
+ other operations requested by a client. If a Printer had been
+ printing a job when the Printer was paused, the Printer MUST
+ resume printing that job when the Printer is no longer paused
+ and leave no evidence in the printed output of such a pause.
+ This value MUST be supported, if the Pause-Printer operation is
+ supported.
+ 'shutdown': Someone has removed a Printer object from service, and
+ the device may be powered down or physically removed. In this
+ state, a Printer object MUST NOT produce printed output, and
+
+
+
+Hastings, et al. Standards Track [Page 132]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ unless the Printer object is realized by a print server that is
+ still active, the Printer object MUST perform no other
+ operations requested by a client, including returning this
+ value. If a Printer object had been printing a job when it was
+ shutdown, the Printer NEED NOT resume printing that job when
+ the Printer is no longer shutdown. If the Printer resumes
+ printing such a job, it may leave evidence in the printed
+ output of such a shutdown, e.g. the part printed before the
+ shutdown may be printed a second time after the shutdown.
+ 'connecting-to-device': The Printer object has scheduled a job on
+ the output device and is in the process of connecting to a
+ shared network output device (and might not be able to actually
+ start printing the job for an arbitrarily long time depending
+ on the usage of the output device by other servers on the
+ network).
+ 'timed-out': The server was able to connect to the output device
+ (or is always connected), but was unable to get a response from
+ the output device.
+ 'stopping': The Printer object is in the process of stopping the
+ device and will be stopped in a while. When the device is
+ stopped, the Printer object will change the Printer object's
+ state to 'stopped'. The 'stopping-warning' reason is never an
+ error, even for a Printer with a single output device. When an
+ output-device ceases accepting jobs, the Printer will have this
+ reason while the output device completes printing.
+ 'stopped-partly': When a Printer object controls more than one
+ output device, this reason indicates that one or more output
+ devices are stopped. If the reason is a report, fewer than
+ half of the output devices are stopped. If the reason is a
+ warning, fewer than all of the output devices are stopped.
+ 'toner-low': The device is low on toner.
+ 'toner-empty': The device is out of toner.
+ 'spool-area-full': The limit of persistent storage allocated for
+ spooling has been reached. The Printer is temporarily unable
+ to accept more jobs. The Printer will remove this value when
+ it is able to accept more jobs. This value SHOULD be used by a
+ non-spooling Printer that only accepts one or a small number
+ jobs at a time or a spooling Printer that has filled the spool
+ space.
+ 'cover-open': One or more covers on the device are open.
+ 'interlock-open': One or more interlock devices on the printer are
+ unlocked.
+ 'door-open': One or more doors on the device are open.
+ 'input-tray-missing': One or more input trays are not in the
+ device.
+ 'media-low': At least one input tray is low on media.
+ 'media-empty': At least one input tray is empty.
+
+
+
+
+Hastings, et al. Standards Track [Page 133]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'output-tray-missing': One or more output trays are not in the
+ device
+ 'output-area-almost-full': One or more output area is almost full
+ (e.g. tray, stacker, collator).
+ 'output-area-full': One or more output area is full. (e.g. tray,
+ stacker, collator)
+ 'marker-supply-low': The device is low on at least one marker
+ supply. (e.g. toner, ink, ribbon)
+ 'marker-supply-empty: The device is out of at least one marker
+ supply. (e.g. toner, ink, ribbon)
+ 'marker-waste-almost-full': The device marker supply waste
+ receptacle is almost full.
+ 'marker-waste-full': The device marker supply waste receptacle is
+ full.
+ 'fuser-over-temp': The fuser temperature is above normal.
+ 'fuser-under-temp': The fuser temperature is below normal.
+ 'opc-near-eol': The optical photo conductor is near end of life.
+ 'opc-life-over': The optical photo conductor is no longer
+ functioning.
+ 'developer-low': The device is low on developer.
+ 'developer-empty: The device is out of developer.
+ 'interpreter-resource-unavailable': An interpreter resource is
+ unavailable (i.e. font, form)
+
+4.4.13 printer-state-message (text(MAX))
+
+ This Printer attribute specifies information about the "printer-
+ state" and "printer-state-reasons" attributes in human readable text.
+ If the Printer object supports this attribute, the Printer object
+ MUST be able to generate this message in any of the natural languages
+ identified by the Printer's "generated-natural-language-supported"
+ attribute (see the "attributes-natural-language" operation attribute
+ specified in Section 3.1.4.1).
+
+4.4.14 ipp-versions-supported (1setOf type2 keyword)
+
+ This REQUIRED attribute identifies the IPP protocol version(s) that
+ this Printer supports, including major and minor versions, i.e., the
+ version numbers for which this Printer implementation meets the
+ conformance requirements. For version number validation, the Printer
+ matches the (two-octet binary) "version-number" parameter supplied by
+ the client in each request (see sections 3.1.1 and 3.1.8) with the
+ (US-ASCII) keyword values of this attribute.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 134]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following standard keyword values are defined:
+
+ '1.0': Meets the conformance requirement of IPP version 1.0 as
+ specified in RFC 2566 [RFC2566] and RFC 2565 [RFC2565]
+ including any extensions registered according to Section 6 and
+ any extension defined in this version or any future version of
+ the IPP "Model and Semantics" document or the IPP "Encoding and
+ Transport" document following the rules, if any, when the
+ "version-number" parameter is '1.0'.
+ '1.1': Meets the conformance requirement of IPP version 1.1 as
+ specified in this document and [RFC2910] including any
+ extensions registered according to Section 6 and any extension
+ defined in any future versions of the IPP "Model and Semantics"
+ document or the IPP Encoding and Transport document following
+ the rules, if any, when the "version-number" parameter is
+ '1.1'.
+
+4.4.15 operations-supported (1setOf type2 enum)
+
+ This REQUIRED Printer attribute specifies the set of supported
+ operations for this Printer object and contained Job objects.
+
+ This attribute is encoded as any other enum attribute syntax
+ according to [RFC2910] as 32-bits. However, all 32-bit enum values
+ for this attribute MUST NOT exceed 0x00008FFF, since these same
+ values are also passed in two octets in the "operation-id" parameter
+ (see section 3.1.1) in each Protocol request with the two high order
+ octets omitted in order to indicate the operation being performed
+ [RFC2910].
+
+ The following standard enum and "operation-id" (see section 3.1.2)
+ values are defined:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 135]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Value Operation Name
+ ----------------- -------------------------------------
+
+ 0x0000 reserved, not used
+ 0x0001 reserved, not used
+ 0x0002 Print-Job
+ 0x0003 Print-URI
+ 0x0004 Validate-Job
+ 0x0005 Create-Job
+ 0x0006 Send-Document
+ 0x0007 Send-URI
+ 0x0008 Cancel-Job
+ 0x0009 Get-Job-Attributes
+ 0x000A Get-Jobs
+ 0x000B Get-Printer-Attributes
+ 0x000C Hold-Job
+ 0x000D Release-Job
+ 0x000E Restart-Job
+ 0x000F reserved for a future operation
+ 0x0010 Pause-Printer
+ 0x0011 Resume-Printer
+ 0x0012 Purge-Jobs
+ 0x0013-0x3FFF reserved for future IETF standards track
+ operations (see section 6.4)
+ 0x4000-0x8FFF reserved for vendor extensions (see section 6.4)
+
+4.4.16 multiple-document-jobs-supported (boolean)
+
+ This Printer attribute indicates whether or not the Printer supports
+ more than one document per job, i.e., more than one Send-Document or
+ Send-Data operation with document data. If the Printer supports the
+ Create-Job and Send-Document operations (see section 3.2.4 and
+ 3.3.1), it MUST support this attribute.
+
+4.4.17 charset-configured (charset)
+
+ This REQUIRED Printer attribute identifies the charset that the
+ Printer object has been configured to represent 'text' and 'name'
+ Printer attributes that are set by the operator, system
+ administrator, or manufacturer, i.e., for "printer-name" (name),
+ "printer-location" (text), "printer-info" (text), and "printer-make-
+ and-model" (text). Therefore, the value of the Printer object's
+ "charset-configured" attribute MUST also be among the values of the
+ Printer object's "charset-supported" attribute.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 136]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.4.18 charset-supported (1setOf charset)
+
+ This REQUIRED Printer attribute identifies the set of charsets that
+ the Printer and contained Job objects support in attributes with
+ attribute syntax 'text' and 'name'. At least the value 'utf-8' MUST
+ be present, since IPP objects MUST support the UTF-8 [RFC2279]
+ charset. If a Printer object supports a charset, it means that for
+ all attributes of syntax 'text' and 'name' the IPP object MUST (1)
+ accept the charset in requests and return the charset in responses as
+ needed.
+
+ If more charsets than UTF-8 are supported, the IPP object MUST
+ perform charset conversion between the charsets as described in
+ Section 3.1.4.2.
+
+4.4.19 natural-language-configured (naturalLanguage)
+
+ This REQUIRED Printer attribute identifies the natural language that
+ the Printer object has been configured to represent 'text' and 'name'
+ Printer attributes that are set by the operator, system
+ administrator, or manufacturer, i.e., for "printer-name" (name),
+ "printer-location" (text), "printer-info" (text), and "printer-make-
+ and-model" (text). When returning these Printer attributes, the
+ Printer object MAY return them in the configured natural language
+ specified by this attribute, instead of the natural language
+ requested by the client in the "attributes-natural-language"
+ operation attribute. See Section 3.1.4.1 for the specification of
+ the OPTIONAL multiple natural language support. Therefore, the value
+ of the Printer object's "natural-language-configured" attribute MUST
+ also be among the values of the Printer object's "generated-natural-
+ language-supported" attribute.
+
+4.4.20 generated-natural-language-supported (1setOf naturalLanguage)
+
+ This REQUIRED Printer attribute identifies the natural language(s)
+ that the Printer object and contained Job objects support in
+ attributes with attribute syntax 'text' and 'name'. The natural
+ language(s) supported depends on implementation and/or configuration.
+ Unlike charsets, IPP objects MUST accept requests with any natural
+ language or any Natural Language Override whether the natural
+ language is supported or not.
+
+ If a Printer object supports a natural language, it means that for
+ any of the attributes for which the Printer or Job object generates
+ messages, i.e., for the "job-state-message" and "printer-state-
+ message" attributes and Operation Messages (see Section 3.1.5) in
+ operation responses, the Printer and Job objects MUST be able to
+
+
+
+
+Hastings, et al. Standards Track [Page 137]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ generate messages in any of the Printer's supported natural
+ languages. See section 3.1.4 for the definition of 'text' and 'name'
+ attributes in operation requests and responses.
+
+ Note: A Printer object that supports multiple natural languages,
+ often has separate catalogs of messages, one for each natural
+ language supported.
+
+4.4.21 document-format-default (mimeMediaType)
+
+ This REQUIRED Printer attribute identifies the document format that
+ the Printer object has been configured to assume if the client does
+ not supply a "document-format" operation attribute in any of the
+ operation requests that supply document data. The standard values
+ for this attribute are Internet Media types (sometimes called MIME
+ types). For further details see the description of the
+ 'mimeMediaType' attribute syntax in Section 4.1.9.
+
+4.4.22 document-format-supported (1setOf mimeMediaType)
+
+ This REQUIRED Printer attribute identifies the set of document
+ formats that the Printer object and contained Job objects can
+ support. For further details see the description of the
+ 'mimeMediaType' attribute syntax in Section 4.1.9.
+
+4.4.23 printer-is-accepting-jobs (boolean)
+
+ This REQUIRED Printer attribute indicates whether the printer is
+ currently able to accept jobs, i.e., is accepting Print-Job, Print-
+ URI, and Create-Job requests. If the value is 'true', the printer is
+ accepting jobs. If the value is 'false', the Printer object is
+ currently rejecting any jobs submitted to it. In this case, the
+ Printer object returns the 'server-error-not-accepting-jobs' status
+ code.
+
+ This value is independent of the "printer-state" and "printer-state-
+ reasons" attributes because its value does not affect the current
+ job; rather it affects future jobs. This attribute, when 'false',
+ causes the Printer to reject jobs even when the "printer-state" is
+ 'idle' or, when 'true', causes the Printer object to accepts jobs
+ even when the "printer-state" is 'stopped'.
+
+4.4.24 queued-job-count (integer(0:MAX))
+
+ This REQUIRED Printer attribute contains a count of the number of
+ jobs that are either 'pending', 'processing', 'pending-held', or
+ 'processing-stopped' and is set by the Printer object.
+
+
+
+
+Hastings, et al. Standards Track [Page 138]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+4.4.25 printer-message-from-operator (text(127))
+
+ This Printer attribute provides a message from an operator, system
+ administrator or "intelligent" process to indicate to the end user
+ information or status of the printer, such as why it is unavailable
+ or when it is expected to be available.
+
+4.4.26 color-supported (boolean)
+
+ This Printer attribute identifies whether the device is capable of
+ any type of color printing at all, including highlight color. All
+ document instructions having to do with color are embedded within the
+ document PDL (none are external IPP attributes in IPP/1.1).
+
+ Note: end-users are able to determine the nature and details of the
+ color support by querying the "printer-more-info-manufacturer"
+ Printer attribute.
+
+4.4.27 reference-uri-schemes-supported (1setOf uriScheme)
+
+ This Printer attribute specifies which URI schemes are supported for
+ use in the "document-uri" operation attribute of the Print-URI or
+ Send-URI operation. If a Printer object supports these optional
+ operations, it MUST support the "reference-uri-schemes-supported"
+ Printer attribute with at least the following schemed URI value:
+
+ 'ftp': The Printer object will use an FTP 'get' operation as
+ defined in RFC 2228 [RFC2228] using FTP URLs as defined by
+ [RFC2396] and [RFC2316].
+
+ The Printer object MAY OPTIONALLY support other URI schemes (see
+ section 4.1.6).
+
+4.4.28 pdl-override-supported (type2 keyword)
+
+ This REQUIRED Printer attribute expresses the ability for a
+ particular Printer implementation to either attempt to override
+ document data instructions with IPP attributes or not.
+
+ This attribute takes on the following keyword values:
+
+ - 'attempted': This value indicates that the Printer object
+ attempts to make the IPP attribute values take precedence over
+ embedded instructions in the document data, however there is no
+ guarantee.
+ - 'not-attempted': This value indicates that the Printer object
+ makes no attempt to make the IPP attribute values take
+ precedence over embedded instructions in the document data.
+
+
+
+Hastings, et al. Standards Track [Page 139]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Section 15 contains a full description of how this attribute
+ interacts with and affects other IPP attributes, especially the
+ "ipp-attribute-fidelity" attribute.
+
+4.4.29 printer-up-time (integer(1:MAX))
+
+ This REQUIRED Printer attribute indicates the amount of time (in
+ seconds) that this Printer instance has been up and running. The
+ value is a monotonically increasing value starting from 1 when the
+ Printer object is started-up (initialized, booted, etc.). This value
+ is used to populate the Event Time Job Description Job attributes
+ "time-at-creation", "time-at-processing", and "time-at-completed"
+ (see section 4.3.14).
+
+ If the Printer object goes down at some value 'n', and comes back up,
+ the implementation MAY:
+
+ 1. Know how long it has been down, and resume at some value
+ greater than 'n', or
+ 2. Restart from 1.
+
+ In other words, if the device or devices that the Printer object is
+ representing are restarted or power cycled, the Printer object MAY
+ continue counting this value or MAY reset this value to 1 depending
+ on implementation. However, if the Printer object software ceases
+ running, and restarts without knowing the last value for "printer-
+ up-time", the implementation MUST reset this value to 1. If this
+ value is reset and the Printer has persistent jobs, the Printer MUST
+ reset the "time-at-xxx(integer) Event Time Job Description attributes
+ according to Section 4.3.14. An implementation MAY use both
+ implementation alternatives, depending on warm versus cold start,
+ respectively.
+
+4.4.30 printer-current-time (dateTime)
+
+ This Printer attribute indicates the current date and time. This
+ value is used to populate the Event Time Job Description attributes:
+ "date-time-at-creation", "date-time-at-processing", and "date-time-
+ at-completed" (see Section 4.3.14).
+
+ The date and time is obtained on a "best efforts basis" and does not
+ have to be that precise in order to work in practice. A Printer
+ implementation sets the value of this attribute by obtaining the date
+ and time via some implementation-dependent means, such as getting the
+ value from a network time server, initialization at time of
+ manufacture, or setting by an administrator. See [IPP-IIG] for
+ examples. If an implementation supports this attribute and the
+ implementation knows that it has not yet been set, then the
+
+
+
+Hastings, et al. Standards Track [Page 140]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ implementation MUST return the value of this attribute using the
+ out-of-band 'no-value' meaning not configured. See the beginning of
+ section 4.1.
+
+ The time zone of this attribute NEED NOT be the time zone used by
+ people located near the Printer object or device. The client MUST
+ NOT expect that the time zone of any received 'dateTime' value to be
+ in the time zone of the client or in the time zone of the people
+ located near the printer.
+
+ The client SHOULD display any dateTime attributes to the user in
+ client local time by converting the 'dateTime' value returned by the
+ server to the time zone of the client, rather than using the time
+ zone returned by the Printer in attributes that use the 'dateTime'
+ attribute syntax.
+
+4.4.31 multiple-operation-time-out (integer(1:MAX))
+
+ This Printer attributes identifies the minimum time (in seconds) that
+ the Printer object waits for additional Send-Document or Send-URI
+ operations to follow a still-open Job object before taking any
+ recovery actions, such as the ones indicated in section 3.3.1. If
+ the Printer object supports the Create-Job and Send-Document
+ operations (see section 3.2.4 and 3.3.1), it MUST support this
+ attribute.
+
+ It is RECOMMENDED that vendors supply a value for this attribute that
+ is between 60 and 240 seconds. An implementation MAY allow a system
+ administrator to set this attribute (by means outside this IPP/1.1
+ document). If so, the system administrator MAY be able to set values
+ outside this range.
+
+4.4.32 compression-supported (1setOf type3 keyword)
+
+ This REQUIRED Printer attribute identifies the set of supported
+ compression algorithms for document data. Compression only applies
+ to the document data; compression does not apply to the encoding of
+ the IPP operation itself. The supported values are used to validate
+ the client supplied "compression" operation attributes in Print-Job,
+ Send-Document, and Send-URI requests.
+
+ Standard keyword values are :
+
+ 'none': no compression is used.
+ 'deflate': ZIP public domain inflate/deflate) compression technology
+ in RFC 1951 [RFC1951]
+ 'gzip' GNU zip compression technology described in RFC 1952
+ [RFC1952].
+
+
+
+Hastings, et al. Standards Track [Page 141]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'compress': UNIX compression technology in RFC 1977 [RFC1977]
+
+4.4.33 job-k-octets-supported (rangeOfInteger(0:MAX))
+
+ This Printer attribute specifies the upper and lower bounds of total
+ sizes of jobs in K octets, i.e., in units of 1024 octets. The
+ supported values are used to validate the client supplied "job-k-
+ octets" operation attributes in create requests. The corresponding
+ job description attribute "job-k-octets" is defined in section
+ 4.3.17.1.
+
+4.4.34 job-impressions-supported (rangeOfInteger(0:MAX))
+
+ This Printer attribute specifies the upper and lower bounds for the
+ number of impressions per job. The supported values are used to
+ validate the client supplied "job-impressions" operation attributes
+ in create requests. The corresponding job description attribute
+ "job-impressions" is defined in section 4.3.17.2.
+
+4.4.35 job-media-sheets-supported (rangeOfInteger(0:MAX))
+
+ This Printer attribute specifies the upper and lower bounds for the
+ number of media sheets per job. The supported values are used to
+ validate the client supplied "job-media-sheets" operation attributes
+ in create requests. The corresponding Job attribute "job-media-
+ sheets" is defined in section 4.3.17.3.
+
+4.4.36 pages-per-minute (integer(0:MAX))
+
+ This Printer attributes specifies the nominal number of pages per
+ minute to the nearest whole number which may be generated by this
+ printer (e.g., simplex, black-and-white). This attribute is
+ informative, not a service guarantee. Generally, it is the value
+ used in the marketing literature to describe the device.
+
+ A value of 0 indicates a device that takes more than two minutes to
+ process a page.
+
+4.4.37 pages-per-minute-color (integer(0:MAX))
+
+ This Printer attributes specifies the nominal number of pages per
+ minute to the nearest whole number which may be generated by this
+ printer when printing color (e.g., simplex, color). For purposes of
+ this attribute, "color" means the same as for the "color-supported"
+ attribute, namely, the device is capable of any type of color
+ printing at all, including highlight color. This attribute is
+
+
+
+
+
+Hastings, et al. Standards Track [Page 142]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ informative, not a service guarantee. Generally, it is the value
+ used in the marketing literature to describe the color capabilities
+ of this device.
+
+ A value of 0 indicates a device that takes more than two minutes to
+ process a page.
+
+ If a color device has several color modes, it MAY use the pages-per-
+ minute value for this attribute that corresponds to the mode that
+ produces the highest number.
+
+ Black and white only printers MUST NOT support this attribute. If
+ this attribute is present, then the "color-supported" Printer
+ description attribute MUST be present and have a 'true' value.
+
+ The values of these two attributes returned by the Get-Printer-
+ Attributes operation MAY be affected by the "document-format"
+ attribute supplied by the client in the Get-Printer-Attributes
+ request. In other words, the implementation MAY have different
+ speeds depending on the document format being processed. See section
+ 3.2.5.1 Get-Printer-Attributes.
+
+5. Conformance
+
+ This section describes conformance issues and requirements. This
+ document introduces model entities such as objects, operations,
+ attributes, attribute syntaxes, and attribute values. These
+ conformance sections describe the conformance requirements which
+ apply to these model entities.
+
+5.1 Client Conformance Requirements
+
+ This section describes the conformance requirements for a client (see
+ section 2.1), whether it be:
+
+ 1. contained within software controlled by an end user, e.g.
+ activated by the "Print" menu item in an application that sends
+ IPP requests or
+
+ 2. the print server component that sends IPP requests to either an
+ output device or another "downstream" print server.
+
+ A conforming client MUST support all REQUIRED operations as defined
+ in this document. For each attribute included in an operation
+ request, a conforming client MUST supply a value whose type and value
+ syntax conforms to the requirements of the Model document as
+ specified in Sections 3 and 4. A conforming client MAY supply any
+
+
+
+
+Hastings, et al. Standards Track [Page 143]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ IETF standards track extensions and/or vendor extensions in an
+ operation request, as long as the extensions meet the requirements in
+ Section 6.
+
+ Otherwise, there are no conformance requirements placed on the user
+ interfaces provided by IPP clients or their applications. For
+ example, one application might not allow an end user to submit
+ multiple documents per job, while another does. One application
+ might first query a Printer object in order to supply a graphical
+ user interface (GUI) dialogue box with supported and default values
+ whereas a different implementation might not.
+
+ When sending a request, an IPP client NEED NOT supply any attributes
+ that are indicated as OPTIONALLY supplied by the client.
+
+ A client MUST be able to accept any of the attribute syntaxes defined
+ in Section 4.1, including their full range, that may be returned to
+ it in a response from a Printer object. In particular for each
+ attribute that the client supports whose attribute syntax is 'text',
+ the client MUST accept and process both the 'textWithoutLanguage' and
+ 'textWithLanguage' forms. Similarly, for each attribute that the
+ client supports whose attribute syntax is 'name', the client MUST
+ accept and process both the 'nameWithoutLanguage' and
+ 'nameWithLanguage' forms. For presentation purposes, truncation of
+ long attribute values is not recommended. A recommended approach
+ would be for the client implementation to allow the user to scroll
+ through long attribute values.
+
+ A response MAY contain attribute groups, attributes, attribute
+ syntaxes, values, and status codes that the client does not expect.
+ Therefore, a client implementation MUST gracefully handle such
+ responses and not refuse to inter-operate with a conforming Printer
+ that is returning IETF standards track extension or vendor
+ extensions, including attribute groups, attributes, attribute
+ syntaxes, attribute values, status codes, and out-of-band attribute
+ values that conform to Section 6. Clients may choose to ignore any
+ parameters, attribute groups, attributes, attribute syntaxes, or
+ values that they do not understand.
+
+ While a client is sending data to a printer, it SHOULD do its best to
+ prevent a channel from being closed by a lower layer when the channel
+ is blocked (i.e. flow-controlled off) for whatever reason, e.g. 'out
+ of paper' or 'job ahead hasn't freed up enough memory'. However, the
+ layer that launched the print submission (e.g. an end user) MAY close
+ the channel in order to cancel the job. When a client closes a
+ channel, a Printer MAY print all or part of the received portion of
+ the document. See the "Encoding and Transport" document [RFC2910]
+ for more details.
+
+
+
+Hastings, et al. Standards Track [Page 144]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ A client MUST support Client Authentication as defined in the IPP/1.1
+ Encoding and Transport document [RFC2910]. A client SHOULD support
+ Operation Privacy and Server Authentication as defined in the IPP/1.1
+ Encoding and Transport document [RFC2910]. See also section 8 of
+ this document.
+
+5.2 IPP Object Conformance Requirements
+
+ This section specifies the conformance requirements for conforming
+ implementations of IPP objects (see section 2). These requirements
+ apply to an IPP object whether it is:
+
+ (1) an (embedded) device component that accepts IPP requests and
+ controls the device or
+
+ (2) a component of a print server that accepts IPP requests (where
+ the print server control one or more networked devices using IPP or
+ other protocols).
+
+5.2.1 Objects
+
+ Conforming implementations MUST implement all of the model objects as
+ defined in this document in the indicated sections:
+
+ Section 2.1 - Printer Object
+ Section 2.2 - Job Object
+
+5.2.2 Operations
+
+ Conforming IPP object implementations MUST implement all of the
+ REQUIRED model operations, including REQUIRED responses, as defined
+ in this document in the indicated sections:
+
+ For a Printer object:
+ Print-Job (section 3.2.1) REQUIRED
+ Print-URI (section 3.2.2) OPTIONAL
+ Validate-Job (section 3.2.3) REQUIRED
+ Create-Job (section 3.2.4) OPTIONAL
+ Get-Printer-Attributes (section 3.2.5) REQUIRED
+ Get-Jobs (section 3.2.6) REQUIRED
+ Pause-Printer (section 3.2.7) OPTIONAL
+ Resume-Printer (section 3.2.8) OPTIONAL
+ Purge-Jobs (section 3.2.9) OPTIONAL
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 145]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ For a Job object:
+ Send-Document (section 3.3.1) OPTIONAL
+ Send-URI (section 3.3.2) OPTIONAL
+ Cancel-Job (section 3.3.3) REQUIRED
+ Get-Job-Attributes (section 3.3.4) REQUIRED
+ Hold-Job (section 3.3.5) OPTIONAL
+ Release-Job (section 3.3.6) OPTIONAL
+ Restart-Job (section 3.3.7) OPTIONAL
+
+ Conforming IPP objects MUST support all REQUIRED operation attributes
+ and all values of such attributes if so indicated in the description.
+ Conforming IPP objects MUST ignore all unsupported or unknown
+ operation attributes or operation attribute groups received in a
+ request, but MUST reject a request that contains a supported
+ operation attribute that contains an unsupported value.
+
+ Conforming IPP objects MAY return operation responses that contain
+ attributes groups, attributes names, attribute syntaxes, attribute
+ values, and status codes that are extensions to this standard. The
+ additional attribute groups MAY occur in any order.
+
+ The following section on object attributes specifies the support
+ required for object attributes.
+
+5.2.3 IPP Object Attributes
+
+ Conforming IPP objects MUST support all of the REQUIRED object
+ attributes, as defined in this document in the indicated sections.
+
+ If an object supports an attribute, it MUST support only those values
+ specified in this document or through the extension mechanism
+ described in section 5.2.4. It MAY support any non-empty subset of
+ these values. That is, it MUST support at least one of the specified
+ values and at most all of them.
+
+5.2.4 Versions
+
+ IPP/1.1 clients MUST meet the conformance requirements for clients
+ specified in this document and [RFC2910]. IPP/1.1 clients MUST send
+ requests containing a "version-number" parameter with a '1.1' value.
+
+ IPP/1.1 Printer and Job objects MUST meet the conformance
+ requirements for IPP objects specified in this document and
+ [RFC2910]. IPP/1.1 objects MUST accept requests containing a
+ "version-number" parameter with a '1.1' value (or reject the request
+ if the operation is not supported).
+
+
+
+
+
+Hastings, et al. Standards Track [Page 146]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ It is beyond the scope of this specification to mandate conformance
+ with previous versions. IPP/1.1 was deliberately designed, however,
+ to make supporting previous versions easy. It is worth noting that,
+ at the time of composing this specification (1999), we would expect
+ IPP/1.1 Printer implementations to:
+
+ understand any valid request in the format of IPP/1.0, or 1.1;
+
+ respond appropriately with a response containing the same
+ "version-number" parameter value used by the client in the request.
+
+ And we would expect IPP/1.1 clients to:
+
+ understand any valid response in the format of IPP/1.0, or 1.1.
+
+ It is recommended that IPP/1.1 clients try supplying alternate
+ version numbers if they receive a 'server-error-version-not-
+ supported' error return in a response.
+
+5.2.5 Extensions
+
+ A conforming IPP object MAY support IETF standards track extensions
+ and vendor extensions, as long as the extensions meet the
+ requirements specified in Section 6.
+
+ For each attribute included in an operation response, a conforming
+ IPP object MUST return a value whose type and value syntax conforms
+ to the requirement of the Model document as specified in Sections 3
+ and 4.
+
+5.2.6 Attribute Syntaxes
+
+ An IPP object MUST be able to accept any of the attribute syntaxes
+ defined in Section 4.1, including their full range, in any operation
+ in which a client may supply attributes or the system administrator
+ may configure attributes (by means outside the scope of this IPP/1.1
+ document). In particular for each attribute that the IPP object
+ supports whose attribute syntax is 'text', the IPP object MUST accept
+ and process both the 'textWithoutLanguage' and 'textWithLanguage'
+ forms. Similarly, for each attribute that the IPP object supports
+ whose attribute syntax is 'name', the IPP object MUST accept and
+ process both the 'nameWithoutLanguage' and 'nameWithLanguage' forms.
+ Furthermore, an IPP object MUST return attributes to the client in
+ operation responses that conform to the syntax specified in Section
+ 4.1, including their full range if supplied previously by a client.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 147]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+5.2.7 Security
+
+ An IPP Printer implementation SHOULD contain support for Client
+ Authentication as defined in the IPP/1.1 Encoding and Transport
+ document [RFC2910]. A Printer implementation MAY allow an
+ administrator to configure the Printer so that all, some, or none of
+ the users are authenticated. See also section 8 of this document.
+
+ An IPP Printer implementation SHOULD contain support for Operation
+ Privacy and Server Authentication as defined in the IPP/1.1 Encoding
+ and Transport document [RFC2910]. A Printer implementation MAY allow
+ an administrator to configure the degree of support for Operation
+ Privacy and Server Authentication. See also section 8 of this
+ document.
+
+ Security MUST NOT be compromised when a client supplies a lower
+ "version-number" parameter in a request. For example, if an IPP/1.1
+ conforming Printer object accepts version '1.0' requests and is
+ configured to enforce Digest Authentication, it MUST do the same for
+ a version '1.0' request.
+
+5.3 Charset and Natural Language Requirements
+
+ All clients and IPP objects MUST support the 'utf-8' charset as
+ defined in section 4.1.7.
+
+ IPP objects MUST be able to accept any client request which correctly
+ uses the "attributes-natural-language" operation attribute or the
+ Natural Language Override mechanism on any individual attribute
+ whether or not the natural language is supported by the IPP object.
+ If an IPP object supports a natural language, then it MUST be able to
+ translate (perhaps by table lookup) all generated 'text' or 'name'
+ attribute values into one of the supported languages (see section
+ 3.1.4). That is, the IPP object that supports a natural language
+ NEED NOT be a general purpose translator of any arbitrary 'text' or
+ 'name' value supplied by the client into that natural language.
+ However, the object MUST be able to translate (automatically
+ generate) any of its own attribute values and messages into that
+ natural language.
+
+6. IANA Considerations
+
+ This section describes the procedures for defining semantics for the
+ following IETF standards track extensions and vendor extensions to
+ the IPP/1.1 Model and Semantics document:
+
+ 1. keyword attribute values
+ 2. enum attribute values
+
+
+
+Hastings, et al. Standards Track [Page 148]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 3. attributes
+ 4. attribute syntaxes
+ 5. operations
+ 6. attribute groups
+ 7. status codes
+ 8. out-of-band attribute values
+
+ Extensions registered for use with IPP/1.1 are OPTIONAL for client
+ and IPP object conformance to the IPP/1.1 "Model and Semantics"
+ document (this document).
+
+ These extension procedures are aligned with the guidelines as set
+ forth by the IESG [IANA-CON]. Section 11 describes how to propose
+ new registrations for consideration. IANA will reject registration
+ proposals that leave out required information or do not follow the
+ appropriate format described in Section 11. The IPP/1.1 Model and
+ Semantics document may also be extended by an appropriate RFC that
+ specifies any of the above extensions.
+
+6.1 Typed 'keyword' and 'enum' Extensions
+
+ IPP allows for 'keyword' and 'enum' extensions (see sections 4.1.2.3
+ and 4.1.4). This document uses prefixes to the 'keyword' and 'enum'
+ basic attribute syntax type in order to communicate extra information
+ to the reader through its name. This extra information is not
+ represented in the protocol because it is unimportant to a client or
+ Printer object. The list below describes the prefixes and their
+ meaning.
+
+ "type1": This IPP specification document must be revised (or
+ another IETF standards track document which augments this
+ document) to add a new keyword or a new enum. No vendor
+ defined keywords or enums are allowed.
+
+ "type2": Implementers can, at any time, add new keyword or enum
+ values by proposing the complete specification to IANA:
+
+ iana@iana.org
+
+ IANA will forward the registration proposal to the IPP
+ Designated Expert who will review the proposal with a mailing
+ list that the Designated Expert keeps for this purpose.
+ Initially, that list will be the mailing list used by the IPP
+ WG:
+
+ ipp@pwg.org
+
+ even after the IPP WG is disbanded as permitted by [IANA-CON].
+
+
+
+Hastings, et al. Standards Track [Page 149]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The IPP Designated Expert is appointed by the IESG Area
+ Director responsible for IPP, according to [IANA-CON].
+
+ When a type2 keyword or enum is approved, the IPP Designated
+ Expert becomes the point of contact for any future maintenance
+ that might be required for that registration.
+
+ "type3": Implementers can, at any time, add new keyword and enum
+ values by submitting the complete specification to IANA as for
+ type2 who will forward the proposal to the IPP Designated
+ Expert. While no additional technical review is required, the
+ IPP Designated Expert may, at his/her discretion, forward the
+ proposal to the same mailing list as for type2 registrations
+ for advice and comment.
+
+ When a type3 keyword or enum is approved by the IPP Designated
+ Expert, the original proposer becomes the point of contact for
+ any future maintenance that might be required for that
+ registration.
+
+ For type2 and type3 keywords, the proposer includes the name of the
+ keyword in the registration proposal and the name is part of the
+ technical review.
+
+ After type2 and type3 enums specifications are approved, the IPP
+ Designated Expert in consultation with IANA assigns the next
+ available enum number for each enum value.
+
+ IANA will publish approved type2 and type3 keyword and enum
+ attributes value registration specifications in:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-values/xxx/yyy.txt
+
+ where xxx is the attribute name that specifies the initial values and
+ yyy.txt is a descriptive file name that contains one or more enums or
+ keywords approved at the same time. For example, if several
+ additional enums for stapling are approved for use with the
+ "finishings" attribute (and "finishings-default" and "finishings-
+ supported" attributes), IANA will publish the additional values in
+ the file:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-
+ values/finishings/stapling.txt
+
+ Note: Some attributes are defined to be: 'type3 keywords' | 'name'
+ which allows for attribute values to be extended by a site
+ administrator with administrator defined names. Such names are not
+ registered with IANA.
+
+
+
+Hastings, et al. Standards Track [Page 150]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ By definition, each of the three types above assert some sort of
+ registry or review process in order for extensions to be considered
+ valid. Each higher numbered level (1, 2, 3) tends to be decreasingly
+ less stringent than the previous level. Therefore, any typeN value
+ MAY be registered using a process for some typeM where M is less than
+ N, however such registration is NOT REQUIRED. For example, a type3
+ value MAY be registered in a type 1 manner (by being included in a
+ future version of an IPP specification), however, it is NOT REQUIRED.
+
+ This document defines keyword and enum values for all of the above
+ types, including type3 keywords.
+
+ For vendor keyword extensions, implementers SHOULD use keywords with
+ a suitable distinguishing prefix, such as "xxx-" where xxx follows
+ the syntax rules for keywords (see section 4.1.3) and is the
+ (lowercase) fully qualified company name registered with IANA for use
+ in domain names [RFC1035]. For example, if the company XYZ Corp. had
+ obtained the domain name "XYZ.com", then a vendor keyword 'abc' would
+ be: 'xyz.com-abc'.
+
+ Note: RFC 1035 [RFC1035] indicates that while upper and lower case
+ letters are allowed in domain names, no significance is attached to
+ the case. That is, two names with the same spelling but different
+ case are to be treated as if identical. Also, the labels in a domain
+ name must follow the rules for ARPANET host names: They must start
+ with a letter, end with a letter or digit, and have as interior
+ characters only letters, digits, and hyphen. Labels must be 63
+ characters or less. Labels are separated by the "." character.
+
+ For vendor enum extensions, implementers MUST use values in the
+ reserved integer range which is 2**30 to 2**31-1.
+
+6.2 Attribute Extensibility
+
+ Attribute names (see section 4.1.3) are type2 keywords. Therefore,
+ new attributes may be registered and have the same status as
+ attributes in this document by following the type2 extension rules.
+ For vendor attribute extensions, implementers SHOULD use keywords
+ with a suitable distinguishing prefix as described in Section 6.1.
+
+ IANA will publish approved attribute registration specifications as
+ separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attributes/xxx-yyy.txt
+
+ where "xxx-yyy" is the new attribute name.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 151]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If a new Printer object attribute is defined and its values can be
+ affected by a specific document format, its specification needs to
+ contain the following sentence:
+
+ "The value of this attribute returned in a Get-Printer-
+ Attributes response MAY depend on the "document-format"
+ attribute supplied (see Section 3.2.5.1)."
+
+ If the specification does not, then its value in the Get-Printer-
+ Attributes response MUST NOT depend on the "document-format" supplied
+ in the request. When a new Job Template attribute is registered, the
+ value of the Printer attributes MAY vary with "document-format"
+ supplied in the request without the specification having to indicate
+ so.
+
+6.3 Attribute Syntax Extensibility
+
+ Attribute syntaxes (see section 4.1) are like type2 enums.
+ Therefore, new attribute syntaxes may be registered and have the same
+ status as attribute syntaxes in this document by following the type2
+ extension rules described in Section 6.1. The initial set of value
+ codes that identify each of the attribute syntaxes have been assigned
+ in the "Encoding and Transport" document [RFC2910], including a
+ designated range for vendor extension.
+
+ For attribute syntaxes, the IPP Designated Expert in consultation
+ with IANA assigns the next attribute syntax code in the appropriate
+ range as specified in [RFC2910]. IANA will publish approved
+ attribute syntax registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-syntaxes/xxx-yyy.txt
+
+ where 'xxx-yyy' is the new attribute syntax name.
+
+6.4 Operation Extensibility
+
+ Operations (see section 3) may also be registered following the type2
+ procedures described in Section 6.1, though major new operations will
+ usually be done by a new standards track RFC that augments this
+ document. For vendor operation extensions, implementers MUST use the
+ range for the "operation-id" in requests specified in Section 4.4.15
+ "operations-supported" Printer attribute.
+
+ For operations, the IPP Designated Expert in consultation with IANA
+ assigns the next operation-id code as specified in Section 4.4.15.
+ IANA will publish approved operation registration specifications as
+ separate files:
+
+
+
+
+Hastings, et al. Standards Track [Page 152]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ ftp.isi.edu/iana/assignments/ipp/operations/Xxx-Yyy.txt
+
+ where "Xxx-Yyy" is the new operation name.
+
+6.5 Attribute Group Extensibility
+
+ Attribute groups (see section 3.1.3) passed in requests and responses
+ may be registered following the type2 procedures described in Section
+ 6.1. The initial set of attribute group tags have been assigned in
+ the "Encoding and Transport" document [RFC2910], including a
+ designated range for vendor extension.
+
+ For attribute groups, the IPP Designated Expert in consultation with
+ IANA assigns the next attribute group tag code in the appropriate
+ range as specified in [RFC2910]. IANA will publish approved
+ attribute group registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/attribute-group-tags/xxx-yyy-
+ tag.txt
+
+ where 'xxx-yyy-tag' is the new attribute group tag name.
+
+6.6 Status Code Extensibility
+
+ Operation status codes (see section 3.1.6.1) may also be registered
+ following the type2 procedures described in Section 6.1. The values
+ for status codes are allocated in ranges as specified in Section 14
+ for each status code class:
+
+ "informational" - Request received, continuing process
+ "successful" - The action was successfully received, understood, and
+ accepted
+ "redirection" - Further action must be taken in order to complete the
+ request
+ "client-error" - The request contains bad syntax or cannot be
+ fulfilled
+ "server-error" - The IPP object failed to fulfill an apparently
+ valid request
+
+ For vendor operation status code extensions, implementers MUST use
+ the top of each range as specified in Section 13.
+
+ For operation status codes, the IPP Designated Expert in consultation
+ with IANA assigns the next status code in the appropriate class range
+ as specified in Section 13. IANA will publish approved status code
+ registration specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/status-codes/xxx-yyy.txt
+
+
+
+Hastings, et al. Standards Track [Page 153]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ where "xxx-yyy" is the new operation status code keyword.
+
+6.7 Out-of-band Attribute Value Extensibility
+
+ Out-of-band attribute values (see the beginning of section 4.1)
+ passed in requests and responses may be registered following the
+ type2 procedures described in Section 6.1. The initial set of out-
+ of-band attribute value tags have been assigned in the "Encoding and
+ Transport" document [RFC2910].
+
+ For out-of-band attribute value tags, the IPP Designated Expert in
+ consultation with IANA assigns the next out-of-band attribute value
+ tag code in the appropriate range as specified in [RFC2910]. IANA
+ will publish approved out-of-band attribute value tags registration
+ specifications as separate files:
+
+ ftp.isi.edu/iana/assignments/ipp/out-of-band-attribute-value-
+ tags/xxx-yyy-tag.txt
+
+ where 'xxx-yyy-tag' is the new out-of-band attribute value tag name.
+
+6.8 Registration of MIME types/sub-types for document-formats
+
+ The "document-format" attribute's syntax is 'mimeMediaType'. This
+ means that valid values are Internet Media Types (see Section 4.1.9).
+ RFC 2045 [RFC2045] defines the syntax for valid Internet media types.
+ IANA is the registry for all Internet media types.
+
+6.9 Registration of charsets for use in 'charset' attribute values
+
+ The "attributes-charset" attribute's syntax is 'charset'. This means
+ that valid values are charsets names. When a charset in the IANA
+ registry has more than one name (alias), the name labeled as
+ "(preferred MIME name)", if present, MUST be used (see Section
+ 4.1.7). IANA is the registry for charsets following the procedures
+ of [RFC2278].
+
+7. Internationalization Considerations
+
+ Some of the attributes have values that are text strings and names
+ which are intended for human understanding rather than machine
+ understanding (see the 'text' and 'name' attribute syntaxes in
+ Sections 4.1.1 and 4.1.2).
+
+ In each operation request, the client
+
+ - identifies the charset and natural language of the request which
+ affects each supplied 'text' and 'name' attribute value, and
+
+
+
+Hastings, et al. Standards Track [Page 154]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - requests the charset and natural language for attributes
+ returned by the IPP object in operation responses (as described
+ in Section 3.1.4.1).
+
+ In addition, the client MAY separately and individually identify the
+ Natural Language Override of a supplied 'text' or 'name' attribute
+ using the 'textWithLanguage' and 'nameWithLanguage' technique
+ described section 4.1.1.2 and 4.1.2.2 respectively.
+
+ All IPP objects MUST support the UTF-8 [RFC2279] charset in all
+ 'text' and 'name' attributes supported. If an IPP object supports
+ more than the UTF-8 charset, the object MUST convert between them in
+ order to return the requested charset to the client according to
+ Section 3.1.4.2. If an IPP object supports more than one natural
+ language, the object SHOULD return 'text' and 'name' values in the
+ natural language requested where those values are generated by the
+ Printer (see Section 3.1.4.1).
+
+ For Printers that support multiple charsets and/or multiple natural
+ languages in 'text' and 'name' attributes, different jobs may have
+ been submitted in differing charsets and/or natural languages. All
+ responses MUST be returned in the charset requested by the client.
+ However, the Get-Jobs operation uses the 'textWithLanguage' and
+ 'nameWithLanguage' mechanism to identify the differing natural
+ languages with each job attribute returned.
+
+ The Printer object also has configured charset and natural language
+ attributes. The client can query the Printer object to determine
+ the list of charsets and natural languages supported by the Printer
+ object and what the Printer object's configured values are. See the
+ "charset-configured", "charset-supported", "natural-language-
+ configured", and "generated-natural-language-supported" Printer
+ description attributes for more details.
+
+ The "charset-supported" attributed identifies the supported charsets.
+ If a charset is supported, the IPP object MUST be capable of
+ converting to and from that charset into any other supported charset.
+ In many cases, an IPP object will support only one charset and it
+ MUST be the UTF-8 charset.
+
+ The "charset-configured" attribute identifies the one supported
+ charset which is the native charset given the current configuration
+ of the IPP object (administrator defined).
+
+ The "generated-natural-language-supported" attribute identifies the
+ set of supported natural languages for generated messages; it is not
+ related to the set of natural languages that must be accepted for
+ client supplied 'text' and 'name' attributes. For client supplied
+
+
+
+Hastings, et al. Standards Track [Page 155]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'text' and 'name' attributes, an IPP object MUST accept ALL supplied
+ natural languages. Just because a Printer object is currently
+ configured to support 'en-us' natural language does not mean that the
+ Printer object should reject a job if the client supplies a job name
+ that is in 'fr-ca'.
+
+ The "natural-language-configured" attribute identifies the one
+ supported natural language for generated messages which is the native
+ natural language given the current configuration of the IPP object
+ (administrator defined).
+
+ Attributes of type 'text' and 'name' are populated from different
+ sources. These attributes can be categorized into following groups
+ (depending on the source of the attribute):
+
+ 1. Some attributes are supplied by the client (e.g., the client
+ supplied "job-name", "document-name", and "requesting-user-
+ name" operation attributes along with the corresponding Job
+ object's "job-name" and "job-originating-user-name"
+ attributes). The IPP object MUST accept these attributes in
+ any natural language no matter what the set of supported
+ languages for generated messages
+ 2. Some attributes are supplied by the system administrator (e.g.,
+ the Printer object's "printer-name" and "printer-location"
+ attributes). These too can be in any natural language. If the
+ natural language for these attributes is different than what a
+ client requests, then they must be reported using the Natural
+ Language Override mechanism.
+ 3. Some attributes are supplied by the device manufacturer (e.g.,
+ the Printer object's "printer-make-and-model" attribute).
+ These too can be in any natural language. If the natural
+ language for these attributes is different than what a client
+ requests, then they must be reported using the Natural Language
+ Override mechanism.
+ 4. Some attributes are supplied by the operator (e.g., the Job
+ object's "job-message-from-operator" attribute). These too can
+ be in any natural language. If the natural language for these
+ attributes is different than what a client requests, then they
+ must be reported using the Natural Language Override mechanism.
+ 5. Some attributes are generated by the IPP object (e.g., the Job
+ object's "job-state-message" attribute, the Printer object's
+ "printer-state-message" attribute, and the "status-message"
+ operation attribute). These attributes can only be in one of
+ the "generated-natural-language-supported" natural languages.
+ If a client requests some natural language for these attributes
+ other than one of the supported values, the IPP object SHOULD
+
+
+
+
+
+Hastings, et al. Standards Track [Page 156]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ respond using the value of the "natural-language-configured"
+ attribute (using the Natural Language Override mechanism if
+ needed).
+
+ The 'text' and 'name' attributes specified in this version of this
+ document (additional ones will be registered according to the
+ procedures in Section 6) are:
+
+ Attributes Source
+
+ Operation Attributes:
+ job-name (name) client
+ document-name (name) client
+ requesting-user-name (name) client
+ status-message (text) Job or Printer object
+ detailed-status-message (text) Job or Printer object -
+ see rule 1
+ document-access-error (text) Job or Printer object -
+ see rule 1
+
+ Job Template Attributes:
+ job-hold-until (keyword | name) client matches
+ administrator-configured
+ job-hold-until-default (keyword | name) client matches
+ administrator-configured
+ job-hold-until-supported (keyword | client matches
+ name) administrator-configured
+ job-sheets (keyword | name) client matches
+ administrator-configured
+ job-sheets-default (keyword | name) client matches
+ administrator-configured
+ job-sheets-supported (keyword | name) client matches
+ administrator-configured
+ media (keyword | name) client matches
+ administrator-configured
+ media-default (keyword | name) client matches
+ administrator-configured
+ media-supported (keyword | name) client matches
+ administrator-configured
+ media-ready (keyword | name) client matches
+ administrator-configured
+
+ Job Description Attributes:
+ job-name (name) client or Printer object
+ job-originating-user-name (name) Printer object
+ job-state-message (text) Job or Printer object
+ output-device-assigned (name(127)) administrator
+ job-message-from-operator (text(127)) operator
+
+
+
+Hastings, et al. Standards Track [Page 157]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ job-detailed-status-messages (1setOf Job or Printer object -
+ text) see rule 1
+ job-document-access-errors (1setOf Job or Printer object -
+ text) see rule 1
+
+ Printer Description Attributes:
+ printer-name (name(127)) administrator
+ printer-location (text(127)) administrator
+ printer-info (text(127)) administrator
+ printer-make-and-model (text(127)) administrator or
+ manufacturer
+ printer-state-message (text) Printer object
+ printer-message-from-operator operator
+ (text(127))
+
+ Rule 1 - Neither the Printer nor the client localizes these message
+ attributes, since they are intended for use by the system
+ administrator or other experienced technical persons.
+
+8. Security Considerations
+
+ It is difficult to anticipate the security risks that might exist in
+ any given IPP environment. For example, if IPP is used within a given
+ corporation over a private network, the risks of exposing document
+ data may be low enough that the corporation will choose not to use
+ encryption on that data. However, if the connection between the
+ client and the IPP object is over a public network, the client may
+ wish to protect the content of the information during transmission
+ through the network with encryption.
+
+ Furthermore, the value of the information being printed may vary from
+ one IPP environment to the next. Printing payroll checks, for
+ example, would have a different value than printing public
+ information from a file. There is also the possibly of denial-of-
+ service attacks, but denial-of-service attacks against printing
+ resources are not well understood and there is no published
+ precedents regarding this scenario.
+
+ Once the authenticated identity of the requester has been supplied to
+ the IPP object, the object uses that identity to enforce any
+ authorization policy that might be in place. For example, one site's
+ policy might be that only the job owner is allowed to cancel a job.
+ The details and mechanisms to set up a particular access control
+ policy are not part of IPP/1.1, and must be established via some
+ other type of administrative or access control framework. However,
+ there are operation status codes that allow an IPP server to return
+ information back to a client about any potential access control
+ violations for an IPP object.
+
+
+
+Hastings, et al. Standards Track [Page 158]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ During a create operation, the client's identity is recorded in the
+ Job object in an implementation-defined attribute. This information
+ can be used to verify a client's identity for subsequent operations
+ on that Job object in order to enforce any access control policy that
+ might be in effect. See section 8.3 below for more details.
+
+ Since the security levels or the specific threats that an IPP system
+ administrator may be concerned with cannot be anticipated, IPP MUST
+ be capable of operating with different security mechanisms and
+ security policies as required by the individual installation.
+ Security policies might vary from very strong, to very weak, to none
+ at all, and corresponding security mechanisms will be required.
+
+8.1 Security Scenarios
+
+ The following sections describe specific security attacks for IPP
+ environments. Where examples are provided they should be considered
+ illustrative of the environment and not an exhaustive set. Not all of
+ these environments will necessarily be addressed in initial
+ implementations of IPP.
+
+8.1.1 Client and Server in the Same Security Domain
+
+ This environment is typical of internal networks where traditional
+ office workers print the output of personal productivity applications
+ on shared work-group printers, or where batch applications print
+ their output on large production printers. Although the identity of
+ the user may be trusted in this environment, a user might want to
+ protect the content of a document against such attacks as
+ eavesdropping, replaying or tampering.
+
+8.1.2 Client and Server in Different Security Domains
+
+ Examples of this environment include printing a document created by
+ the client on a publicly available printer, such as at a commercial
+ print shop; or printing a document remotely on a business associate's
+ printer. This latter operation is functionally equivalent to sending
+ the document to the business associate as a facsimile. Printing
+ sensitive information on a Printer in a different security domain
+ requires strong security measures. In this environment authentication
+ of the printer is required as well as protection against unauthorized
+ use of print resources. Since the document crosses security domains,
+ protection against eavesdropping and document tampering are also
+ required. It will also be important in this environment to protect
+ Printers against "spamming" and malicious document content.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 159]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+8.1.3 Print by Reference
+
+ When the document is not stored on the client, printing can be done
+ by reference. That is, the print request can contain a reference, or
+ pointer, to the document instead of the actual document itself (see
+ sections 3.2.2 and 3.3.2). Standard methods currently do not exist
+ for remote entities to "assume" the credentials of a client for
+ forwarding requests to a 3rd party. It is anticipated that Print-By-
+ Reference will be used to access "public" documents and that
+ sophisticated methods for authenticating "proxies" is not specified
+ in this document.
+
+8.2 URIs in Operation, Job, and Printer attributes
+
+ The "printer-uri-supported" attribute contains the Printer object's
+ URI(s). Its companion attribute, "uri-security-supported",
+ identifies the security mechanism used for each URI listed in the
+ "printer-uri-supported" attribute. For each Printer operation
+ request, a client MUST supply only one URI in the "printer-uri"
+ operation attribute. In other words, even though the Printer
+ supports more than one URI, the client only interacts with the
+ Printer object using one if its URIs. This duality is not needed for
+ Job objects, since the Printer objects is the factory for Job
+ objects, and the Printer object will generate the correct URI for new
+ Job objects depending on the Printer object's security configuration.
+
+8.3 URIs for each authentication mechanisms
+
+ Each URI has an authentication mechanism associated with it. If the
+ URI is the i'th element of "printer-uri-supported", then
+ authentication mechanism is the "i th" element of "uri-
+ authentication-supported". For a list of possible authentication
+ mechanisms, see section 4.4.2.
+
+ The Printer object uses an authentication mechanism to determine the
+ name of the user performing an operation. This user is called the
+ "authenticated user". The credibility of authentication depends on
+ the mechanism that the Printer uses to obtain the user's name. When
+ the authentication mechanism is 'none', all authenticated users are
+ "anonymous".
+
+ During job creation operations, the Printer initializes the value of
+ the "job-originating-user-name" attribute (see section 4.3.6) to be
+ the authenticated user. The authenticated user is this case is called
+ the "job owner".
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 160]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ If an implementation can be configured to support more than one
+ authentication mechanism (see section 4.4.2), then it MUST implement
+ rules for determining equality of authenticated user names which have
+ been authenticated via different authentication mechanisms. One
+ possible policy is that identical names that are authenticated via
+ different mechanisms are different. For example, a user can cancel
+ his job only if he uses the same authentication mechanism for both
+ Cancel-Job and Print-Job. Another policy is that identical names
+ that are authenticated via different mechanism are the same if the
+ authentication mechanism for the later operation is not less strong
+ than the authentication mechanism for the earlier job creation
+ operation. For example, a user can cancel his job only if he uses
+ the same or stronger authentication mechanism for Cancel-Job and
+ Print-Job. With this second policy a job submitted via 'requesting-
+ user-name' authentication could be canceled via 'digest'
+ authentication. With the first policy, the job could not be canceled
+ in this way.
+
+ A client is able to determine the authentication mechanism used to
+ create a job. It is the i'th value of the Printer's "uri-
+ authentication-supported" attribute (see section 4.4.2), where i is
+ the index of the element of the Printer's "printer-uri-supported"
+ attribute (see section 4.4.1) equal to the job's "job-printer-uri"
+ attribute (see section 4.3.3).
+
+8.4 Restricted Queries
+
+ In many IPP operations, a client supplies a list of attributes to be
+ returned in the response. For security reasons, an IPP object may be
+ configured not to return all attributes (or all values) that a client
+ requests. The job attributes returned MAY depend on whether the
+ requesting user is the same as the user that submitted the job. The
+ IPP object MAY even return none of the requested attributes. In such
+ cases, the status returned is the same as if the object had returned
+ all requested attributes. The client cannot tell by such a response
+ whether the requested attribute was present or absent on the object.
+
+8.5 Operations performed by operators and system administrators
+
+ For the three printer operations Pause-Printer, Resume-Printer, and
+ Purge-Jobs (see sections 3.2.7, 3.2.8 and 3.2.9), the requesting user
+ is intended to be an operator or administrator of the Printer object
+ (see section 1). Otherwise, the IPP Printer MUST reject the
+ operation and return: 'client-error-forbidden', 'client-error-not-
+ authenticated', or 'client-error-not-authorized' as appropriate. For
+ operations on jobs, the requesting user is intended to be the job
+
+
+
+
+
+Hastings, et al. Standards Track [Page 161]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ owner or may be an operator or administrator of the Printer object.
+ The means for authorizing an operator or administrator of the Printer
+ object are not specified in this document.
+
+8.6 Queries on jobs submitted using non-IPP protocols
+
+ If the device that an IPP Printer is representing is able to accept
+ jobs using other job submission protocols in addition to IPP, it is
+ RECOMMENDED that such an implementation at least allow such "foreign"
+ jobs to be queried using Get-Jobs returning "job-id" and "job-uri" as
+ 'unknown'. Such an implementation NEED NOT support all of the same
+ IPP job attributes as for IPP jobs. The IPP object returns the
+ 'unknown' out-of-band value for any requested attribute of a foreign
+ job that is supported for IPP jobs, but not for foreign jobs.
+
+ It is further RECOMMENDED, that the IPP Printer generate "job-id" and
+ "job-uri" values for such "foreign jobs", if possible, so that they
+ may be targets of other IPP operations, such as Get-Job-Attributes
+ and Cancel-Job. Such an implementation also needs to deal with the
+ problem of authentication of such foreign jobs. One approach would
+ be to treat all such foreign jobs as belonging to users other than
+ the user of the IPP client. Another approach would be for the
+ foreign job to belong to 'anonymous'. Only if the IPP client has
+ been authenticated as an operator or administrator of the IPP Printer
+ object, could the foreign jobs be queried by an IPP request.
+ Alternatively, if the security policy is to allow users to query
+ other users' jobs, then the foreign jobs would also be visible to an
+ end-user IPP client using Get-Jobs and Get-Job-Attributes.
+
+9. References
+
+ [ASME-Y14.1M] Metric Drawing Sheet Size and Format, ASME Y14.1M-1995.
+ This standard defines metric sheet sizes and formats
+ for engineering drawings.
+
+ [ASCII] Coded Character Set - 7-bit American Standard Code for
+ Information Interchange (ASCII), ANSI X3.4-1986. This
+ standard is the specification of the US-ASCII charset.
+
+ [BCP-11] Bradner S. and R. Hovey, "The Organizations Involved in
+ the IETF Standards Process", BCP 11, RFC 2028, October
+ 1996.
+
+ [HTPP] J. Barnett, K. Carter, R. DeBry, "Initial Draft -
+ Hypertext Printing Protocol - HTPP/1.0", October 1996,
+ ftp://ftp.pwg.org/pub/pwg/ipp/historic/htpp/overview.ps.gz
+
+
+
+
+
+Hastings, et al. Standards Track [Page 162]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ [IANA-CON] Narten, T. and H. Alvestrand, "Guidelines for Writing
+ an IANA Considerations Section in RFCs", BCP 26, RFC
+ 2434, October 1998.
+
+ [IANA-CS] IANA Registry of Coded Character Sets:
+ ftp://ftp.isi.edu/in-notes/iana/assignments/character-
+ sets
+
+ [IANA-MT] IANA Registry of Media Types: ftp://ftp.isi.edu/in-
+ notes/iana/assignments/media-types/
+
+ [IPP-IIG] Hastings, T., Manros, C., Kugler, C., Holst, H., and P.
+ Zehler, "Internet Printing Protocol/1.1: draft-ietf-
+ ipp-implementers-guide-v11-01.txt, work in progress,
+ May 30, 2000.
+
+ [ISO10646-1] ISO/IEC 10646-1:1993, "Information technology --
+ Universal Multiple-Octet Coded Character Set (UCS) -
+ Part 1: Architecture and Basic Multilingual Plane,
+ JTC1/SC2."
+
+ [ISO8859-1] ISO/IEC 8859-1:1987, "Information technology -- 8-bit
+ One-Byte Coded Character Set - Part 1: Latin Alphabet
+ Nr 1", 1987, JTC1/SC2.
+
+ [ISO10175] ISO/IEC 10175 Document Printing Application (DPA), June
+ 1996.
+
+ [LDPA] T. Hastings, S. Isaacson, M. MacKay, C. Manros, D.
+ Taylor, P. Zehler, "LDPA - Lightweight Document
+ Printing Application", October 1996,
+ ftp://ftp.pwg.org/pub/pwg/ipp/historic/ldpa/ldpa8.pdf.gz
+
+ [P1387.4] Kirk, M. (editor), POSIX System Administration - Part
+ 4: Printing Interfaces, POSIX 1387.4 D8, 1994.
+
+ [PSIS] Herriot, R. (editor), X/Open A Printing System
+ Interoperability Specification (PSIS), August 1995.
+
+ [PWG] Printer Working Group, http://www.pwg.org.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1179] McLaughlin, L., "Line Printer Daemon Protocol", RFC
+ 1179, August 1990.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 163]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ [RFC1759] Smith, R., Wright, F., Hastings, T., Zilles, S. and J.
+ Gyllenskog, "Printer MIB", RFC 1759, March 1995.
+
+ [RFC1766] Alvestrand, H., "Tags for the Identification of
+ Languages", RFC 1766, March 1995.
+
+ [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format
+ Specification version 1.3 ", RFC 1951, May 1996.
+
+ [RFC1952] Deutsch, P., "GZIP file format specification version
+ 4.3", RFC 1952, May 1996.
+
+ [RFC1977] Schryver, V., "PPP BSD Compression Protocol", RFC 1977,
+ August 1996.
+
+ [RFC2026] Bradner, S., "The Internet Standards Process --
+ Revision 3", BCP 9, RFC 2026, October 1996.
+
+ [RFC2045] Freed, N. and N. Borenstein, ", Multipurpose Internet
+ Mail Extensions (MIME) Part One: Format of Internet
+ Message Bodies", RFC 2045, November 1996.
+
+ [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet
+ Mail Extensions (MIME) Part Two: Media Types", RFC
+ 2046, November 1996.
+
+ [RFC2048] Freed, N., Klensin, J. and J. Postel, "Multipurpose
+ Internet Mail Extension (MIME) Part Four: Registration
+ Procedures", RFC 2048, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2228] Horowitz, M. and S. Lunt, "FTP Security Extensions",
+ RFC 2228, October 1997.
+
+ [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol Version
+ 1.0", RFC 2246, January 1999.
+
+ [RFC2277] Alvestrand, H., "IETF Policy on Character Sets and
+ Languages" BCP 18, RFC 2277, January 1998.
+
+ [RFC2278] Freed, N. and J. Postel: "IANA CharSet Registration
+ Procedures", BCP 19, RFC 2278, January 1998.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO
+ 10646", RFC 2279, January 1998.
+
+
+
+
+Hastings, et al. Standards Track [Page 164]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ [RFC2316] Bellovin, S., "Report of the IAB Security Architecture
+ Workshop", RFC 2316, April 1998.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Turner,
+ "Internet Printing Protocol/1.0: Encoding and
+ Transport", RFC 2565, April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and
+ P. Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569,
+ April 1999.
+
+ [RFC2579] McCloghrie, K., Perkins, D. and J. Schoenwaelder,
+ "Textual Conventions for SMIv2", STD 58, RFC 2579,
+ April 1999.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
+ Masinter, L., Leach, P. and T. Berners-Lee, "Hypertext
+ Transfer Protocol - HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC2617] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence,
+ S., Leach, P., Luotonen, A. and L. Stewart, "HTTP
+ Authentication: Basic and Digest Access
+ Authentication", RFC 2617, June 1999.
+
+ [RFC2639] Hastings, T. and C. Manros, "Internet Printing
+ Protocol/1.0: Encoding and Transport", RFC 2639, July
+ 1999.
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P., Turner, R. and J.
+ Wenn, "Internet Printing Protocol/1.1: Encoding and
+ Transport", RFC 2910, September 2000.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 165]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ [SSL] Netscape, The SSL Protocol, Version 3, (Text version
+ 3.02), November 1996.
+
+ [SWP] P. Moore, B. Jahromi, S. Butler, "Simple Web Printing
+ SWP/1.0", May 7, 1997,
+ ftp://ftp.pwg.org/pub/pwg/ipp/new_PRO/swp9705.pdf
+
+10. Authors' Addresses
+
+ Scott A. Isaacson, Editor
+ Novell, Inc.
+ 122 E 1700 S
+ Provo, UT 84606
+
+ Phone: 801-861-7366
+ Fax: 801-861-2517
+ EMail: sisaacson@novell.com
+
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St. ESAE 231
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Robert Herriot
+ Xerox Corp.
+ 3400 Hill View Ave, Building 1
+ Palo Alto, CA 94304
+
+ Phone: 650-813-7696
+ Fax: 650-813-6860
+ EMail: robert.herriot@pahv.xerox.com
+
+
+ Roger deBry
+ Utah Valley State College
+ Orem, UT 84058
+
+ Phone: (801) 222-8000
+ EMail: debryro@uvsc.edu
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 166]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Patrick Powell
+ Astart Technologies
+ 9475 Chesapeake Dr., Suite D
+ San Diego, CA 95123
+
+ Phone: (619) 874-6543
+ Fax: (619) 279-8424
+ EMail: papowell@astart.com
+
+ IPP Web Page: http://www.pwg.org/ipp/
+ IPP Mailing List: ipp@pwg.org
+
+ To subscribe to the ipp mailing list, send the following email:
+ 1) send it to majordomo@pwg.org
+ 2) leave the subject line blank
+ 3) put the following two lines in the message body:
+ subscribe ipp
+ end
+
+ Implementers of this specification document are encouraged to join
+ IPP Mailing List in order to participate in any discussions of
+ clarification issues and review of registration proposals for
+ additional attributes and values.
+
+ Other Participants:
+
+ Chuck Adams - Tektronix Shivaun Albright - HP
+ Stefan Andersson - Axis Jeff Barnett - IBM
+ Ron Bergman - Hitachi Koki Imaging Dennis Carney - IBM
+ Systems
+ Keith Carter - IBM Angelo Caruso - Xerox
+ Rajesh Chawla - TR Computing Nancy Chen - Okidata
+ Solutions
+ Josh Cohen - Microsoft Jeff Copeland - QMS
+ Andy Davidson - Tektronix Roger deBry - IBM
+ Maulik Desai - Auco Mabry Dozier - QMS
+ Lee Farrell - Canon Information Satoshi Fujitami - Ricoh
+ Systems
+ Steve Gebert - IBM Sue Gleeson - Digital
+ Charles Gordon - Osicom Brian Grimshaw - Apple
+ Jerry Hadsell - IBM Richard Hart - Digital
+ Tom Hastings - Xerox Henrik Holst - I-data
+ Stephen Holmstead Zhi-Hong Huang - Zenographics
+ Scott Isaacson - Novell Babek Jahromi - Microsoft
+ Swen Johnson - Xerox David Kellerman - Northlake
+ Software
+ Robert Kline - TrueSpectra Charles Kong - Panasonic
+ Carl Kugler - IBM Dave Kuntz - Hewlett-Packard
+
+
+
+Hastings, et al. Standards Track [Page 167]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Takami Kurono - Brother Rick Landau - Digital
+ Scott Lawrence - Agranot Systems Greg LeClair - Epson
+ Dwight Lewis - Lexmark Harry Lewis - IBM
+ Tony Liao - Vivid Image Roy Lomicka - Digital
+ Pete Loya - HP Ray Lutz - Cognisys
+ Mike MacKay - Novell, Inc. David Manchala - Xerox
+ Carl-Uno Manros - Xerox Jay Martin - Underscore
+ Stan McConnell - Xerox Larry Masinter - Xerox
+ Sandra Matts - Hewlett Packard Peter Michalek - Shinesoft
+ Ira McDonald - High North Inc. Mike Moldovan - G3 Nova
+ Tetsuya Morita - Ricoh Yuichi Niwa - Ricoh
+ Pat Nogay - IBM Ron Norton - Printronics
+ Hugo Parra, Novell Bob Pentecost - Hewlett-Packard
+ Patrick Powell - Astart Jeff Rackowitz - Intermec
+ Technologies
+ Eric Random - Peerless Rob Rhoads - Intel
+ Xavier Riley - Xerox Gary Roberts - Ricoh
+ David Roach - Unisys Stuart Rowley - Kyocera
+ Yuji Sasaki - Japan Computer Richard Schneider - Epson
+ Industry
+ Kris Schoff - HP Katsuaki Sekiguchi - Canon
+ Bob Setterbo - Adobe Gail Songer - Peerless
+ Hideki Tanaka - Cannon Devon Taylor - Novell
+ Mike Timperman - Lexmark Atsushi Uchino - Epson
+ Shigeru Ueda - Canon Bob Von Andel - Allegro Software
+ William Wagner - NetSilicon/DPI Jim Walker - DAZEL
+ Chris Wellens - Interworking Labs Trevor Wells - Hewlett Packard
+ Craig Whittle - Sharp Labs Rob Whittle - Novell, Inc.
+ Jasper Wong - Xionics Don Wright - Lexmark
+ Michael Wu - Heidelberg Digital Rick Yardumian - Xerox
+ Michael Yeung - Toshiba Lloyd Young - Lexmark
+ Atsushi Yuki - Kyocera Peter Zehler - Xerox
+ William Zhang- Canon Information Frank Zhao - Panasonic
+ Systems
+ Steve Zilles - Adobe Rob Zirnstein - Canon Information
+ Systems
+
+11. Formats for IPP Registration Proposals
+
+ In order to propose an IPP extension for registration, the proposer
+ must submit an application to IANA by email to "iana@iana.org" or by
+ filling out the appropriate form on the IANA web pages
+ (http://www.iana.org). This section specifies the required
+ information and the formats for proposing registrations of extensions
+ to IPP as provided in Section 6 for:
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 168]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 1. type2 'keyword' attribute values
+ 2. type3 'keyword' attribute values
+ 3. type2 'enum' attribute values
+ 4. type3 'enum' attribute values
+ 5. attributes
+ 6. attribute syntaxes
+ 7. operations
+ 8. status codes
+ 9. out-of-band attribute values
+
+11.1 Type2 keyword attribute values registration,
+
+ Type of registration: type2 keyword attribute value
+ Name of attribute to which this keyword specification is to be added:
+ Proposed keyword name of this keyword value:
+ Specification of this keyword value (follow the style of IPP Model
+ Section 4.1.2.3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type2 keywords, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.2 Type3 keyword attribute values registration
+
+ Type of registration: type3 keyword attribute value
+ Name of attribute to which this keyword specification is to be added:
+ Proposed keyword name of this keyword value:
+ Specification of this keyword value (follow the style of IPP Model
+ Section 4.1.2.3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type3 keywords, the proposer will be the point of contact
+ for the approved registration specification, if any maintenance of
+ the registration specification is needed.
+
+11.3 Type2 enum attribute values registration
+
+ Type of registration: type2 enum attribute value
+ Name of attribute to which this enum specification is to be added:
+ Keyword symbolic name of this enum value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+
+
+
+
+Hastings, et al. Standards Track [Page 169]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Specification of this enum value (follow the style of IPP Model
+ Section 4.1.4):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type2 enums, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.4 Type3 enum attribute values registration
+
+ Type of registration: type3 enum attribute value
+ Name of attribute to which this enum specification is to be added:
+ Keyword symbolic name of this enum value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Specification of this enum value (follow the style of IPP Model
+ Section 4.1.4):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For type3 enums, the proposer will be the point of contact for
+ the approved registration specification, if any maintenance of the
+ registration specification is needed.
+
+11.5 Attribute registration
+
+ Type of registration: attribute
+ Proposed keyword name of this attribute:
+ Types of attribute (Operation, Job Template, Job Description, Printer
+ Description):
+ Operations to be used with if the attribute is an operation attribute:
+ Object (Job, Printer, etc. if bound to an object):
+ Attribute syntax(es) (include 1setOf and range as in Section 4.2):
+ If attribute syntax is 'keyword' or 'enum', is it type2 or type3:
+ If this is a Printer attribute, MAY the value returned depend on
+ "document-format" (See Section 6.2):
+ If this is a Job Template attribute, how does its specification depend
+ on the value of the "multiple-document-handling" attribute:
+ Specification of this attribute (follow the style of IPP Model Section
+ 4.2):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+
+
+
+
+Hastings, et al. Standards Track [Page 170]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Note: For attributes, the IPP Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.6 Attribute Syntax registration
+
+ Type of registration: attribute syntax
+ Proposed name of this attribute syntax:
+ Type of attribute syntax (integer, octetString, character-string, see
+ [RFC2910]):
+ Numeric tag according to [RFC2910] (to be assigned by the IPP
+ Designated Expert in consultation with IANA):
+ Specification of this attribute (follow the style of IPP Model Section
+ 4.1):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For attribute syntaxes, the IPP Designated Expert will be the
+ point of contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.7 Operation registration
+
+ Type of registration: operation
+ Proposed name of this operation:
+ Numeric operation-id value according to section 4.4.15 (to be assigned
+ by the IPP Designated Expert in consultation with IANA):
+ Object Target (Job, Printer, etc. that operation is upon):
+ Specification of this operation (follow the style of IPP Model Section
+ 3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For operations, the IPP Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.8 Attribute Group registration
+
+ Type of registration: attribute group
+ Proposed name of this attribute group:
+ Numeric tag according to [RFC2910] (to be assigned by the IPP
+ Designated Expert in consultation with IANA):
+ Operation requests and group number for each operation in which the
+ attribute group occurs:
+
+
+
+
+Hastings, et al. Standards Track [Page 171]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Operation responses and group number for each operation in which the
+ attribute group occurs:
+ Specification of this attribute group (follow the style of IPP Model
+ Section 3):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For attribute groups, the IPP Designated Expert will be the
+ point of contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.9 Status code registration
+
+ Type of registration: status code
+ Keyword symbolic name of this status code value:
+ Numeric value (to be assigned by the IPP Designated Expert in
+ consultation with IANA):
+ Operations that this status code may be used with:
+ Specification of this status code (follow the style of IPP Model
+ Section 13 APPENDIX B: Status Codes and Suggested Status Code
+ Messages):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For status codes, the Designated Expert will be the point of
+ contact for the approved registration specification, if any
+ maintenance of the registration specification is needed.
+
+11.10 Out-of-band Attribute Value registration
+
+ Type of registration: out-of-band attribute value
+ Proposed name of this out-of-band attribute value:
+ Numeric tag according to [RFC2910] (to be assigned by the IPP Designated
+ Expert in consultation with IANA):
+ Operations that this out-of-band attribute value may be used with:
+ Attributes that this out-of-band attribute value may be used with:
+ Specification of this out-of-band attribute value (follow the style of
+ the beginning of IPP Model Section 4.1):
+ Name of proposer:
+ Address of proposer:
+ Email address of proposer:
+
+ Note: For out-of-band attribute values, the IPP Designated Expert
+ will be the point of contact for the approved registration
+ specification, if any maintenance of the registration specification
+ is needed.
+
+
+
+Hastings, et al. Standards Track [Page 172]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+12. APPENDIX A: Terminology
+
+ This specification document uses the terminology defined in this
+ section.
+
+12.1 Conformance Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
+ interpreted as described in RFC 2119 [RFC2119].
+
+12.1.1 NEED NOT
+
+ This term is not included in RFC 2119. The verb "NEED NOT" indicates
+ an action that the subject of the sentence does not have to implement
+ in order to claim conformance to the standard. The verb "NEED NOT"
+ is used instead of "MAY NOT" since "MAY NOT" sounds like a
+ prohibition.
+
+12.2 Model Terminology
+
+12.2.1 Keyword
+
+ Keywords are used within this document as identifiers of semantic
+ entities within the abstract model (see section 4.1.2.3). Attribute
+ names, some attribute values, attribute syntaxes, and attribute group
+ names are represented as keywords.
+
+12.2.2 Attributes
+
+ An attribute is an item of information that is associated with an
+ instance of an IPP object. An attribute consists of an attribute
+ name and one or more attribute values. Each attribute has a specific
+ attribute syntax. All object attributes are defined in section 4 and
+ all operation attributes are defined in section 3.
+
+ Job Template Attributes are described in section 4.2. The client
+ optionally supplies Job Template attributes in a create request
+ (operation requests that create Job objects). The Printer object has
+ associated attributes which define supported and default values for
+ the Printer.
+
+12.2.2.1 Attribute Name
+
+ Each attribute is uniquely identified in this document by its
+ attribute name. An attribute name is a keyword. The keyword
+ attribute name is given in the section header describing that
+
+
+
+
+Hastings, et al. Standards Track [Page 173]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ attribute. In running text in this document, attribute names are
+ indicated inside double quotation marks (") where the quotation marks
+ are not part of the keyword itself.
+
+12.2.2.2 Attribute Group Name
+
+ Related attributes are grouped into named groups. The name of the
+ group is a keyword. The group name may be used in place of naming
+ all the attributes in the group explicitly. Attribute groups are
+ defined in section 3.
+
+12.2.2.3 Attribute Value
+
+ Each attribute has one or more values. Attribute values are
+ represented in the syntax type specified for that attribute. In
+ running text in this document, attribute values are indicated inside
+ single quotation marks ('), whether their attribute syntax is
+ keyword, integer, text, etc. where the quotation marks are not part
+ of the value itself.
+
+12.2.2.4 Attribute Syntax
+
+ Each attribute is defined using an explicit syntax type. In this
+ document, each syntax type is defined as a keyword with specific
+ meaning. The "Encoding and Transport" document [RFC2910] indicates
+ the actual "on-the-wire" encoding rules for each syntax type.
+ Attribute syntax types are defined in section 4.1.
+
+12.2.3 Supports
+
+ By definition, a Printer object supports an attribute only if that
+ Printer object responds with the corresponding attribute populated
+ with some value(s) in a response to a query for that attribute. A
+ Printer object supports an attribute value if the value is one of the
+ Printer object's "supported values" attributes. The device behind a
+ Printer object may exhibit a behavior that corresponds to some IPP
+ attribute, but if the Printer object, when queried for that
+ attribute, doesn't respond with the attribute, then as far as IPP is
+ concerned, that implementation does not support that feature. If the
+ Printer object's "xxx-supported" attribute is not populated with a
+ particular value (even if that value is a legal value for that
+ attribute), then that Printer object does not support that particular
+ value.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 174]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ A conforming implementation MUST support all REQUIRED attributes.
+ However, even for REQUIRED attributes, conformance to IPP does not
+ mandate that all implementations support all possible values
+ representing all possible job processing behaviors and features. For
+ example, if a given instance of a Printer supports only certain
+ document formats, then that Printer responds with the "document-
+ format-supported" attribute populated with a set of values, possibly
+ only one, taken from the entire set of possible values defined for
+ that attribute. This limited set of values represents the Printer's
+ set of supported document formats. Supporting an attribute and some
+ set of values for that attribute enables IPP end users to be aware of
+ and make use of those features associated with that attribute and
+ those values. If an implementation chooses to not support an
+ attribute or some specific value, then IPP end users would have no
+ ability to make use of that feature within the context of IPP itself.
+ However, due to existing practice and legacy systems which are not
+ IPP aware, there might be some other mechanism outside the scope of
+ IPP to control or request the "unsupported" feature (such as embedded
+ instructions within the document data itself).
+
+ For example, consider the "finishings-supported" attribute.
+
+ 1) If a Printer object is not physically capable of stapling, the
+ "finishings-supported" attribute MUST NOT be populated with the
+ value of 'staple'.
+ 2) A Printer object is physically capable of stapling, however an
+ implementation chooses not to support stapling in the IPP
+ "finishings" attribute. In this case, 'staple' MUST NOT be a
+ value in the "finishings-supported" Printer object attribute.
+ Without support for the value 'staple', an IPP end user would
+ have no means within the protocol itself to request that a Job
+ be stapled. However, an existing document data formatter might
+ be able to request that the document be stapled directly with
+ an embedded instruction within the document data. In this
+ case, the IPP implementation does not "support" stapling,
+ however the end user is still able to have some control over
+ the stapling of the completed job.
+ 3) A Printer object is physically capable of stapling, and an
+ implementation chooses to support stapling in the IPP
+ "finishings" attribute. In this case, 'staple' MUST be a value
+ in the "finishings-supported" Printer object attribute. Doing
+ so, would enable end users to be aware of and make use of the
+ stapling feature using IPP attributes.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 175]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Even though support for Job Template attributes by a Printer object
+ is OPTIONAL, it is RECOMMENDED that if the device behind a Printer
+ object is capable of realizing any feature or function that
+ corresponds to an IPP attribute and some associated value, then that
+ implementation SHOULD support that IPP attribute and value.
+
+ The set of values in any of the supported value attributes is set
+ (populated) by some administrative process or automatic sensing
+ mechanism that is outside the scope of this IPP/1.1 document. For
+ administrative policy and control reasons, an administrator may
+ choose to make only a subset of possible values visible to the end
+ user. In this case, the real output device behind the IPP Printer
+ abstraction may be capable of a certain feature, however an
+ administrator is specifying that access to that feature not be
+ exposed to the end user through the IPP protocol. Also, since a
+ Printer object may represent a logical print device (not just a
+ physical device) the actual process for supporting a value is
+ undefined and left up to the implementation. However, if a Printer
+ object supports a value, some manual human action may be needed to
+ realize the semantic action associated with the value, but no end
+ user action is required.
+
+ For example, if one of the values in the "finishings-supported"
+ attribute is 'staple', the actual process might be an automatic
+ staple action by a physical device controlled by some command sent to
+ the device. Or, the actual process of stapling might be a manual
+ action by an operator at an operator attended Printer object.
+
+ For another example of how supported attributes function, consider a
+ system administrator who desires to control all print jobs so that no
+ job sheets are printed in order to conserve paper. To force no job
+ sheets, the system administrator sets the only supported value for
+ the "job-sheets-supported" attribute to 'none'. In this case, if a
+ client requests anything except 'none', the create request is
+ rejected or the "job-sheets" value is ignored (depending on the value
+ of "ipp-attribute-fidelity"). To force the use of job start/end
+ sheets on all jobs, the administrator does not include the value
+ 'none' in the "job-sheets- supported" attribute. In this case, if a
+ client requests 'none', the create request is rejected or the "job-
+ sheets" value is ignored (again depending on the value of "ipp-
+ attribute-fidelity").
+
+12.2.4 print-stream page
+
+ A "print-stream page" is a page according to the definition of pages
+ in the language used to express the document data.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 176]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+12.2.5 impression
+
+ An "impression" is the image (possibly many print-stream pages in
+ different configurations) imposed onto a single media page.
+
+13. APPENDIX B: Status Codes and Suggested Status Code Messages
+
+ This section defines status code enum keywords and values that are
+ used to provide semantic information on the results of an operation
+ request. Each operation response MUST include a status code. The
+ response MAY also contain a status message that provides a short
+ textual description of the status. The status code is intended for
+ use by automata, and the status message is intended for the human end
+ user. Since the status message is an OPTIONAL component of the
+ operation response, an IPP application (i.e., a browser, GUI, print
+ driver or gateway) is NOT REQUIRED to examine or display the status
+ message, since it MAY not be returned to the application.
+
+ The prefix of the status keyword defines the class of response as
+ follows:
+
+ "informational" - Request received, continuing process
+ "successful" - The action was successfully received, understood,
+ and accepted
+ "redirection" - Further action must be taken in order to complete
+ the request
+ "client-error" - The request contains bad syntax or cannot be
+ fulfilled
+ "server-error" - The IPP object failed to fulfill an apparently
+ valid request
+
+ As with type2 enums, IPP status codes are extensible. IPP clients
+ are NOT REQUIRED to understand the meaning of all registered status
+ codes, though such understanding is obviously desirable. However,
+ IPP clients MUST understand the class of any status code, as
+ indicated by the prefix, and treat any unrecognized response as being
+ equivalent to the first status code of that class, with the exception
+ that an unrecognized response MUST NOT be cached. For example, if an
+ unrecognized status code of "client-error-xxx-yyy" is received by the
+ client, it can safely assume that there was something wrong with its
+ request and treat the response as if it had received a "client-
+ error-bad-request" status code. In such cases, IPP applications
+ SHOULD present the OPTIONAL message (if present) to the end user
+ since the message is likely to contain human readable information
+ which will help to explain the unusual status. The name of the enum
+ is the suggested status message for US English.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 177]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The status code values range from 0x0000 to 0x7FFF. The value ranges
+ for each status code class are as follows:
+
+ "successful" - 0x0000 to 0x00FF
+ "informational" - 0x0100 to 0x01FF
+ "redirection" - 0x0200 to 0x02FF
+ "client-error" - 0x0400 to 0x04FF
+ "server-error" - 0x0500 to 0x05FF
+
+ The top half (128 values) of each range (0x0n40 to 0x0nFF, for n = 0
+ to 5) is reserved for vendor use within each status code class.
+ Values 0x0600 to 0x7FFF are reserved for future assignment by IETF
+ standards track documents and MUST NOT be used.
+
+13.1 Status Codes
+
+ Each status code is described below. Section 13.1.5.9 contains a
+ table that indicates which status codes apply to which operations.
+ The Implementer's Guide [IPP-IIG] describe the suggested steps for
+ processing IPP attributes for all operations, including returning
+ status codes.
+
+13.1.1 Informational
+
+ This class of status code indicates a provisional response and is to
+ be used for informational purposes only.
+
+ There are no status codes defined in IPP/1.1 for this class of status
+ code.
+
+13.1.2 Successful Status Codes
+
+ This class of status code indicates that the client's request was
+ successfully received, understood, and accepted.
+
+13.1.2.1 successful-ok (0x0000)
+
+ The request has succeeded and no request attributes were substituted
+ or ignored. In the case of a response to a create request, the
+ 'successful-ok' status code indicates that the request was
+ successfully received and validated, and that the Job object has been
+ created; it does not indicate that the job has been processed. The
+ transition of the Job object into the 'completed' state is the only
+ indicator that the job has been printed.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 178]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.2.2 successful-ok-ignored-or-substituted-attributes (0x0001)
+
+ The request has succeeded, but some supplied (1) attributes were
+ ignored or (2) unsupported values were substituted with supported
+ values or were ignored in order to perform the operation without
+ rejecting it. Unsupported attributes, attribute syntaxes, or values
+ MUST be returned in the Unsupported Attributes group of the response
+ for all operations. There is an exception to this rule for the query
+ operations: Get-Printer-Attributes, Get-Jobs, and Get-Job-Attributes
+ for the "requested-attributes" operation attribute only. When the
+ supplied values of the "requested-attributes" operation attribute are
+ requesting attributes that are not supported, the IPP object MAY, but
+ is NOT REQUIRED to, return the "requested-attributes" attribute in
+ the Unsupported Attribute response group (with the unsupported values
+ only). See sections 3.1.7 and 3.2.1.2.
+
+13.1.2.3 successful-ok-conflicting-attributes (0x0002)
+
+ The request has succeeded, but some supplied attribute values
+ conflicted with the values of other supplied attributes. These
+ conflicting values were either (1) substituted with (supported)
+ values or (2) the attributes were removed in order to process the job
+ without rejecting it. Attributes or values which conflict with other
+ attributes and have been substituted or ignored MUST be returned in
+ the Unsupported Attributes group of the response for all operations
+ as supplied by the client. See sections 3.1.7 and 3.2.1.2.
+
+13.1.3 Redirection Status Codes
+
+ This class of status code indicates that further action needs to be
+ taken to fulfill the request.
+
+ There are no status codes defined in IPP/1.1 for this class of status
+ code.
+
+13.1.4 Client Error Status Codes
+
+ This class of status code is intended for cases in which the client
+ seems to have erred. The IPP object SHOULD return a message
+ containing an explanation of the error situation and whether it is a
+ temporary or permanent condition.
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 179]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.4.1 client-error-bad-request (0x0400)
+
+ The request could not be understood by the IPP object due to
+ malformed syntax (such as the value of a fixed length attribute whose
+ length does not match the prescribed length for that attribute - see
+ the Implementer's Guide [IPP-IIG] ). The IPP application SHOULD NOT
+ repeat the request without modifications.
+
+13.1.4.2 client-error-forbidden (0x0401)
+
+ The IPP object understood the request, but is refusing to fulfill it.
+ Additional authentication information or authorization credentials
+ will not help and the request SHOULD NOT be repeated. This status
+ code is commonly used when the IPP object does not wish to reveal
+ exactly why the request has been refused or when no other response is
+ applicable.
+
+13.1.4.3 client-error-not-authenticated (0x0402)
+
+ The request requires user authentication. The IPP client may repeat
+ the request with suitable authentication information. If the request
+ already included authentication information, then this status code
+ indicates that authorization has been refused for those credentials.
+ If this response contains the same challenge as the prior response,
+ and the user agent has already attempted authentication at least
+ once, then the response message may contain relevant diagnostic
+ information. This status codes reveals more information than
+ "client-error-forbidden".
+
+13.1.4.4 client-error-not-authorized (0x0403)
+
+ The requester is not authorized to perform the request. Additional
+ authentication information or authorization credentials will not help
+ and the request SHOULD NOT be repeated. This status code is used
+ when the IPP object wishes to reveal that the authentication
+ information is understandable, however, the requester is explicitly
+ not authorized to perform the request. This status codes reveals
+ more information than "client-error-forbidden" and "client-error-
+ not-authenticated".
+
+13.1.4.5 client-error-not-possible (0x0404)
+
+ This status code is used when the request is for something that can
+ not happen. For example, there might be a request to cancel a job
+ that has already been canceled or aborted by the system. The IPP
+ client SHOULD NOT repeat the request.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 180]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.4.6 client-error-timeout (0x0405)
+
+ The client did not produce a request within the time that the IPP
+ object was prepared to wait. For example, a client issued a Create-
+ Job operation and then, after a long period of time, issued a Send-
+ Document operation and this error status code was returned in
+ response to the Send-Document request (see section 3.3.1). The IPP
+ object might have been forced to clean up resources that had been
+ held for the waiting additional Documents. The IPP object was forced
+ to close the Job since the client took too long. The client SHOULD
+ NOT repeat the request without modifications.
+
+13.1.4.7 client-error-not-found (0x0406)
+
+ The IPP object has not found anything matching the request URI. No
+ indication is given of whether the condition is temporary or
+ permanent. For example, a client with an old reference to a Job (a
+ URI) tries to cancel the Job, however in the mean time the Job might
+ have been completed and all record of it at the Printer has been
+ deleted. This status code, 'client-error-not-found' is returned
+ indicating that the referenced Job can not be found. This error
+ status code is also used when a client supplies a URI as a reference
+ to the document data in either a Print-URI or Send-URI operation, but
+ the document can not be found.
+
+ In practice, an IPP application should avoid a not found situation by
+ first querying and presenting a list of valid Printer URIs and Job
+ URIs to the end-user.
+
+13.1.4.8 client-error-gone (0x0407)
+
+ The requested object is no longer available and no forwarding address
+ is known. This condition should be considered permanent. Clients
+ with link editing capabilities should delete references to the
+ request URI after user approval. If the IPP object does not know or
+ has no facility to determine, whether or not the condition is
+ permanent, the status code "client-error-not-found" should be used
+ instead.
+
+ This response is primarily intended to assist the task of maintenance
+ by notifying the recipient that the resource is intentionally
+ unavailable and that the IPP object administrator desires that remote
+ links to that resource be removed. It is not necessary to mark all
+ permanently unavailable resources as "gone" or to keep the mark for
+ any length of time -- that is left to the discretion of the IPP
+ object administrator and/or Printer implementation.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 181]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.4.9 client-error-request-entity-too-large (0x0408)
+
+ The IPP object is refusing to process a request because the request
+ entity is larger than the IPP object is willing or able to process.
+ An IPP Printer returns this status code when it limits the size of
+ print jobs and it receives a print job that exceeds that limit or
+ when the attributes are so many that their encoding causes the
+ request entity to exceed IPP object capacity.
+
+13.1.4.10 client-error-request-value-too-long (0x0409)
+
+ The IPP object is refusing to service the request because one or more
+ of the client-supplied attributes has a variable length value that is
+ longer than the maximum length specified for that attribute. The IPP
+ object might not have sufficient resources (memory, buffers, etc.) to
+ process (even temporarily), interpret, and/or ignore a value larger
+ than the maximum length. Another use of this error code is when the
+ IPP object supports the processing of a large value that is less than
+ the maximum length, but during the processing of the request as a
+ whole, the object may pass the value onto some other system component
+ which is not able to accept the large value. For more details, see
+ the Implementer's Guide [IPP-IIG] .
+
+ Note: For attribute values that are URIs, this rare condition is
+ only likely to occur when a client has improperly submitted a request
+ with long query information (e.g. an IPP application allows an end-
+ user to enter an invalid URI), when the client has descended into a
+ URI "black hole" of redirection (e.g., a redirected URI prefix that
+ points to a suffix of itself), or when the IPP object is under attack
+ by a client attempting to exploit security holes present in some IPP
+ objects using fixed-length buffers for reading or manipulating the
+ Request-URI.
+
+13.1.4.11 client-error-document-format-not-supported (0x040A)
+
+ The IPP object is refusing to service the request because the
+ document data is in a format, as specified in the "document-format"
+ operation attribute, that is not supported by the Printer object.
+ This error is returned independent of the client-supplied "ipp-
+ attribute-fidelity". The Printer object MUST return this status
+ code, even if there are other Job Template attributes that are not
+ supported as well, since this error is a bigger problem than with Job
+ Template attributes. See sections 3.1.6.1, 3.1.7, and 3.2.1.1.
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 182]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.4.12 client-error-attributes-or-values-not-supported (0x040B)
+
+ In a create request, if the Printer object does not support one or
+ more attributes, attribute syntaxes, or attribute values supplied in
+ the request and the client supplied the "ipp-attribute-fidelity"
+ operation attribute with the 'true' value, the Printer object MUST
+ return this status code. The Printer object MUST also return in the
+ Unsupported Attributes Group all the attributes and/or values
+ supplied by the client that are not supported. See section 3.1.7.
+ For example, if the request indicates 'iso-a4' media, but that media
+ type is not supported by the Printer object. Or, if the client
+ supplies a Job Template attribute and the attribute itself is not
+ even supported by the Printer. If the "ipp-attribute-fidelity"
+ attribute is 'false', the Printer MUST ignore or substitute values
+ for unsupported Job Template attributes and values rather than reject
+ the request and return this status code.
+
+ For any operation where a client requests attributes (such as a Get-
+ Jobs, Get-Printer-Attributes, or Get-Job-Attributes operation), if
+ the IPP object does not support one or more of the requested
+ attributes, the IPP object simply ignores the unsupported requested
+ attributes and processes the request as if they had not been
+ supplied, rather than returning this status code. In this case, the
+ IPP object MUST return the 'successful-ok-ignored-or-substituted-
+ attributes' status code and MAY return the unsupported attributes as
+ values of the "requested-attributes" in the Unsupported Attributes
+ Group (see section 13.1.2.2).
+
+13.1.4.13 client-error-uri-scheme-not-supported (0x040C)
+
+ The scheme of the client-supplied URI in a Print-URI or a Send-URI
+ operation is not supported. See sections 3.1.6.1 and 3.1.7.
+
+13.1.4.14 client-error-charset-not-supported (0x040D)
+
+ For any operation, if the IPP Printer does not support the charset
+ supplied by the client in the "attributes-charset" operation
+ attribute, the Printer MUST reject the operation and return this
+ status and any 'text' or 'name' attributes using the 'utf-8' charset
+ (see Section 3.1.4.1). See sections 3.1.6.1 and 3.1.7.
+
+13.1.4.15 client-error-conflicting-attributes (0x040E)
+
+ The request is rejected because some attribute values conflicted with
+ the values of other attributes which this document does not permit to
+ be substituted or ignored. The Printer object MUST also return in
+ the Unsupported Attributes Group the conflicting attributes supplied
+ by the client. See sections 3.1.7 and 3.2.1.2.
+
+
+
+Hastings, et al. Standards Track [Page 183]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.4.16 client-error-compression-not-supported (0x040F)
+
+ The IPP object is refusing to service the request because the
+ document data, as specified in the "compression" operation attribute,
+ is compressed in a way that is not supported by the Printer object.
+ This error is returned independent of the client-supplied "ipp-
+ attribute-fidelity". The Printer object MUST return this status
+ code, even if there are other Job Template attributes that are not
+ supported as well, since this error is a bigger problem than with Job
+ Template attributes. See sections 3.1.6.1, 3.1.7, and 3.2.1.1.
+
+13.1.4.17 client-error-compression-error (0x0410)
+
+ The IPP object is refusing to service the request because the
+ document data cannot be decompressed when using the algorithm
+ specified by the "compression" operation attribute. This error is
+ returned independent of the client-supplied "ipp-attribute-fidelity".
+ The Printer object MUST return this status code, even if there are
+ Job Template attributes that are not supported as well, since this
+ error is a bigger problem than with Job Template attributes. See
+ sections 3.1.7 and 3.2.1.1.
+
+13.1.4.18 client-error-document-format-error (0x0411)
+
+ The IPP object is refusing to service the request because Printer
+ encountered an error in the document data while interpreting it.
+ This error is returned independent of the client-supplied "ipp-
+ attribute-fidelity". The Printer object MUST return this status
+ code, even if there are Job Template attributes that are not
+ supported as well, since this error is a bigger problem than with Job
+ Template attributes. See sections 3.1.7 and 3.2.1.1.
+
+13.1.4.19 client-error-document-access-error (0x0412)
+
+ The IPP object is refusing to service the Print-URI or Send-URI
+ request because Printer encountered an access error while attempting
+ to validate the accessibility or access the document data specified
+ in the "document-uri" operation attribute. The Printer MAY also
+ return a specific document access error code using the "document-
+ access-error" operation attribute (see section 3.1.6.4). This error
+ is returned independent of the client-supplied "ipp-attribute-
+ fidelity". The Printer object MUST return this status code, even if
+ there are Job Template attributes that are not supported as well,
+ since this error is a bigger problem than with Job Template
+ attributes. See sections 3.1.6.1 and 3.1.7.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 184]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.5 Server Error Status Codes
+
+ This class of status codes indicates cases in which the IPP object is
+ aware that it has erred or is incapable of performing the request.
+ The IPP object SHOULD include a message containing an explanation of
+ the error situation, and whether it is a temporary or permanent
+ condition.
+
+13.1.5.1 server-error-internal-error (0x0500)
+
+ The IPP object encountered an unexpected condition that prevented it
+ from fulfilling the request. This error status code differs from
+ "server-error-temporary-error" in that it implies a more permanent
+ type of internal error. It also differs from "server-error-device-
+ error" in that it implies an unexpected condition (unlike a paper-jam
+ or out-of-toner problem which is undesirable but expected). This
+ error status code indicates that probably some knowledgeable human
+ intervention is required.
+
+13.1.5.2 server-error-operation-not-supported (0x0501)
+
+ The IPP object does not support the functionality required to fulfill
+ the request. This is the appropriate response when the IPP object
+ does not recognize an operation or is not capable of supporting it.
+ See sections 3.1.6.1 and 3.1.7.
+
+13.1.5.3 server-error-service-unavailable (0x0502)
+
+ The IPP object is currently unable to handle the request due to a
+ temporary overloading or maintenance of the IPP object. The
+ implication is that this is a temporary condition which will be
+ alleviated after some delay. If known, the length of the delay may be
+ indicated in the message. If no delay is given, the IPP application
+ should handle the response as it would for a "server-error-
+ temporary-error" response. If the condition is more permanent, the
+ error status codes "client-error-gone" or "client-error-not-found"
+ could be used.
+
+13.1.5.4 server-error-version-not-supported (0x0503)
+
+ The IPP object does not support, or refuses to support, the IPP
+ protocol version that was supplied as the value of the "version-
+ number" operation parameter in the request. The IPP object is
+ indicating that it is unable or unwilling to complete the request
+ using the same major and minor version number as supplied in the
+ request other than with this error message. The error response SHOULD
+ contain a "status-message" attribute (see section 3.1.6.2) describing
+
+
+
+
+Hastings, et al. Standards Track [Page 185]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ why that version is not supported and what other versions are
+ supported by that IPP object. See sections 3.1.6.1, 3.1.7, and
+ 3.1.8.
+
+ The error response MUST identify in the "version-number" operation
+ parameter the closest version number that the IPP object does
+ support. For example, if a client supplies version '1.0' and an
+ IPP/1.1 object supports version '1.0', then it responds with version
+ '1.0' in all responses to such a request. If the IPP/1.1 object does
+ not support version '1.0', then it should accept the request and
+ respond with version '1.1' or may reject the request and respond with
+ this error code and version
+ '1.1'. If a client supplies a version '1.2', the IPP/1.1 object
+ should accept the request and return version '1.1' or may reject the
+ request and respond with this error code and version '1.1'. See
+ sections 3.1.8 and 4.4.14.
+
+13.1.5.5 server-error-device-error (0x0504)
+
+ A printer error, such as a paper jam, occurs while the IPP object
+ processes a Print or Send operation. The response contains the true
+ Job Status (the values of the "job-state" and "job-state-reasons"
+ attributes). Additional information can be returned in the OPTIONAL
+ "job-state-message" attribute value or in the OPTIONAL status message
+ that describes the error in more detail. This error status code is
+ only returned in situations where the Printer is unable to accept the
+ create request because of such a device error. For example, if the
+ Printer is unable to spool, and can only accept one job at a time,
+ the reason it might reject a create request is that the printer
+ currently has a paper jam. In many cases however, where the Printer
+ object can accept the request even though the Printer has some error
+ condition, the 'successful-ok' status code will be returned. In such
+ a case, the client would look at the returned Job Object Attributes
+ or later query the Printer to determine its state and state reasons.
+
+13.1.5.6 server-error-temporary-error (0x0505)
+
+ A temporary error such as a buffer full write error, a memory
+ overflow (i.e. the document data exceeds the memory of the Printer),
+ or a disk full condition, occurs while the IPP Printer processes an
+ operation. The client MAY try the unmodified request again at some
+ later point in time with an expectation that the temporary internal
+ error condition may have been cleared. Alternatively, as an
+ implementation option, a Printer object MAY delay the response until
+ the temporary condition is cleared so that no error is returned.
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 186]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+13.1.5.7 server-error-not-accepting-jobs (0x0506)
+
+ A temporary error indicating that the Printer is not currently
+ accepting jobs, because the administrator has set the value of the
+ Printer's "printer-is-accepting-jobs" attribute to 'false' (by means
+ outside the scope of this IPP/1.1 document).
+
+13.1.5.8 server-error-busy (0x0507)
+
+ A temporary error indicating that the Printer is too busy processing
+ jobs and/or other requests. The client SHOULD try the unmodified
+ request again at some later point in time with an expectation that
+ the temporary busy condition will have been cleared.
+
+13.1.5.9 server-error-job-canceled (0x0508)
+
+ An error indicating that the job has been canceled by an operator or
+ the system while the client was transmitting the data to the IPP
+ Printer. If a job-id and job-uri had been created, then they are
+ returned in the Print-Job, Send-Document, or Send-URI response as
+ usual; otherwise, no job-id and job-uri are returned in the response.
+
+13.1.5.10 server-error-multiple-document-jobs-not-supported (0x0509)
+
+ The IPP object does not support multiple documents per job and a
+ client attempted to supply document data with a second Send-Document
+ or Send-URI operation.
+
+13.2 Status Codes for IPP Operations
+
+ PJ = Print-Job, PU = Print-URI, CJ = Create-Job, SD = Send-Document
+ SU = Send-URI, V = Validate-Job, GA = Get-Job-Attributes and
+ Get-Printer-Attributes, GJ = Get-Jobs, C = Cancel-Job
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 187]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ IPP Operations
+ IPP Status Keyword PJ PU CJ SD SU V GA GJ C
+ ------------------ -- -- -- -- -- - -- -- -
+ successful-ok x x x x x x x x x
+ successful-ok-ignored-or-substituted- x x x x x x x x x
+ attributes
+ successful-ok-conflicting-attributes x x x x x x x x x
+ client-error-bad-request x x x x x x x x x
+ client-error-forbidden x x x x x x x x x
+ client-error-not-authenticated x x x x x x x x x
+ client-error-not-authorized x x x x x x x x x
+ client-error-not-possible x x x x x x x x x
+ client-error-timeout x x
+ client-error-not-found x x x x x x x x x
+ client-error-gone x x x x x x x x x
+ client-error-request-entity-too-large x x x x x x x x x
+ client-error-request-value-too-long x x x x x x x x x
+ client-error-document-format-not- x x x x x x
+ supported
+ client-error-attributes-or-values-not- x x x x x x x x x
+ supported
+ client-error-uri-scheme-not-supported x x
+ client-error-charset-not-supported x x x x x x x x x
+ client-error-conflicting-attributes x x x x x x x x x
+ client-error-compression-not-supported x x x x x
+ client-error-compression-error x x x x
+ client-error-document-format-error x x x x
+ client-error-document-access-error x x
+ server-error-internal-error x x x x x x x x x
+ server-error-operation-not-supported x x x x
+ server-error-service-unavailable x x x x x x x x x
+ server-error-version-not-supported x x x x x x x x x
+ server-error-device-error x x x x x
+ server-error-temporary-error x x x x x
+ server-error-not-accepting-jobs x x x x
+ server-error-busy x x x x x x x x x
+ server-error-job-canceled x x x
+ server-error-multiple-document-jobs- x x
+ not-supported
+
+ HJ = Hold-Job, RJ = Release-Job, RS = Restart-Job
+ PP = Pause-Printer, RP = Resume-Printer, PJ = Purge-Jobs
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 188]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ IPP Operations (cont.)
+ IPP Status Keyword HJ RJ RS PP RP PJ
+ ------------------ -- -- -- -- -- --
+ successful-ok x x x x x x
+ successful-ok-ignored-or-substituted- x x x x x x
+ attributes
+ successful-ok-conflicting-attributes x x x x x x
+ client-error-bad-request x x x x x x
+ client-error-forbidden x x x x x x
+ client-error-not-authenticated x x x x x x
+ client-error-not-authorized x x x x x x
+ client-error-not-possible x x x x x x
+ client-error-timeout
+ client-error-not-found x x x x x x
+ client-error-gone x x x x x x
+ client-error-request-entity-too-large x x x x x x
+ client-error-request-value-too-long x x x x x x
+ client-error-document-format-not-
+ supported
+ client-error-attributes-or-values-not- x x x x x x
+ supported
+ client-error-uri-scheme-not-supported
+ client-error-charset-not-supported x x x x x x
+ client-error-conflicting-attributes x x x x x x
+ client-error-compression-not-supported
+ client-error-compression-error
+ client-error-document-format-error
+ client-error-document-access-error
+ server-error-internal-error x x x x x x
+ server-error-operation-not-supported x x x x x x
+ server-error-service-unavailable x x x x x x
+ server-error-version-not-supported x x x x x x
+ server-error-device-error
+ server-error-temporary-error x x x x x x
+ server-error-not-accepting-jobs
+ server-error-busy x x x x x x
+ server-error-job-canceled
+ server-error-multiple-document-jobs-
+ not-supported
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 189]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+14. APPENDIX C: "media" keyword values
+
+ Standard keyword values are taken from several sources.
+
+ Standard values are defined (taken from DPA[ISO10175] and the Printer
+ MIB[RFC1759]):
+
+ 'default': The default medium for the output device
+ 'iso-a4-white': Specifies the ISO A4 white medium: 210 mm x 297 mm
+ 'iso-a4-colored': Specifies the ISO A4 colored medium: 210 mm x 297
+ mm
+ 'iso-a4-transparent' Specifies the ISO A4 transparent medium: 210 mm
+ x 297 mm
+ 'iso-a3-white': Specifies the ISO A3 white medium: 297 mm x 420 mm
+ 'iso-a3-colored': Specifies the ISO A3 colored medium: 297 mm x 420
+ mm
+ 'iso-a5-white': Specifies the ISO A5 white medium: 148 mm x 210 mm
+ 'iso-a5-colored': Specifies the ISO A5 colored medium: 148 mm x 210
+ mm
+ 'iso-b4-white': Specifies the ISO B4 white medium: 250 mm x 353 mm
+ 'iso-b4-colored': Specifies the ISO B4 colored medium: 250 mm x 353
+ mm
+ 'iso-b5-white': Specifies the ISO B5 white medium: 176 mm x 250 mm
+ 'iso-b5-colored': Specifies the ISO B5 colored medium: 176 mm x 250
+ mm
+ 'jis-b4-white': Specifies the JIS B4 white medium: 257 mm x 364 mm
+ 'jis-b4-colored': Specifies the JIS B4 colored medium: 257 mm x 364
+ mm
+ 'jis-b5-white': Specifies the JIS B5 white medium: 182 mm x 257 mm
+ 'jis-b5-colored': Specifies the JIS B5 colored medium: 182 mm x 257
+ mm
+
+ The following standard values are defined for North American media:
+
+ 'na-letter-white': Specifies the North American letter white medium
+ 'na-letter-colored': Specifies the North American letter colored
+ medium
+ 'na-letter-transparent': Specifies the North American letter
+ transparent medium
+ 'na-legal-white': Specifies the North American legal white medium
+ 'na-legal-colored': Specifies the North American legal colored
+ medium
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 190]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following standard values are defined for envelopes:
+
+ 'iso-b4-envelope': Specifies the ISO B4 envelope medium
+ 'iso-b5-envelope': Specifies the ISO B5 envelope medium
+ 'iso-c3-envelope': Specifies the ISO C3 envelope medium
+ 'iso-c4-envelope': Specifies the ISO C4 envelope medium
+ 'iso-c5-envelope': Specifies the ISO C5 envelope medium
+ 'iso-c6-envelope': Specifies the ISO C6 envelope medium
+ 'iso-designated-long-envelope': Specifies the ISO Designated Long
+ envelope medium
+ 'na-10x13-envelope': Specifies the North American 10x13 envelope
+ medium
+ 'na-9x12-envelope': Specifies the North American 9x12 envelope
+ medium
+ 'monarch-envelope': Specifies the Monarch envelope
+ 'na-number-10-envelope': Specifies the North American number 10
+ business envelope medium
+ 'na-7x9-envelope': Specifies the North American 7x9 inch envelope
+ 'na-9x11-envelope': Specifies the North American 9x11 inch
+ envelope
+ 'na-10x14-envelope': Specifies the North American 10x14 inch
+ envelope
+ 'na-number-9-envelope': Specifies the North American number 9
+ business envelope
+ 'na-6x9-envelope': Specifies the North American 6x9 inch envelope
+ 'na-10x15-envelope': Specifies the North American 10x15 inch
+ envelope
+
+ The following standard values are defined for the less commonly used
+ media:
+
+ 'executive-white': Specifies the white executive medium
+ 'folio-white': Specifies the folio white medium
+ 'invoice-white': Specifies the white invoice medium
+ 'ledger-white': Specifies the white ledger medium
+ 'quarto-white': Specified the white quarto medium
+ 'iso-a0-white': Specifies the ISO A0 white medium: 841 mm x 1189 mm
+ 'iso-a0-transparent': Specifies the ISO A0 transparent medium: 841 mm
+ x 1189 mm
+ 'iso-a0-translucent': Specifies the ISO A0 translucent medium: 841 mm
+ x 1189 mm
+ 'iso-a1-white': Specifies the ISO A1 white medium: 594 mm x 841 mm
+ 'iso-a1-transparent': Specifies the ISO A1 transparent medium: 594 mm
+ x 841 mm
+ 'iso-a1-translucent': Specifies the ISO A1 translucent medium: 594 mm
+ x 841 mm
+ 'iso-a2-white': Specifies the ISO A2 white medium: 420 mm x 594 mm
+
+
+
+
+Hastings, et al. Standards Track [Page 191]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'iso-a2-transparent': Specifies the ISO A2 transparent medium: 420 mm
+ x 594 mm
+ 'iso-a2-translucent': Specifies the ISO A2 translucent medium: 420 mm
+ x 594 mm
+ 'iso-a3-transparent': Specifies the ISO A3 transparent medium: 297 mm
+ x 420 mm
+ 'iso-a3-translucent': Specifies the ISO A3 translucent medium: 297 mm
+ x 420 mm
+ 'iso-a4-translucent': Specifies the ISO A4 translucent medium: 210 mm
+ x 297 mm
+ 'iso-a5-transparent': Specifies the ISO A5 transparent medium: 148 mm
+ x 210 mm
+ 'iso-a5-translucent': Specifies the ISO A5 translucent medium: 148 mm
+ x 210 mm
+ 'iso-a6-white': Specifies the ISO A6 white medium: 105 mm x 148 mm
+ 'iso-a7-white': Specifies the ISO A7 white medium: 74 mm x 105 mm
+ 'iso-a8-white': Specifies the ISO A8 white medium: 52 mm x 74 mm
+ 'iso-a9-white': Specifies the ISO A9 white medium: 37 mm x 52 mm
+ 'iso-a10-white': Specifies the ISO A10 white medium: 26 mm x 37 mm
+ 'iso-b0-white': Specifies the ISO B0 white medium: 1000 mm x 1414 mm
+ 'iso-b1-white': Specifies the ISO B1 white medium: 707 mm x 1000 mm
+ 'iso-b2-white': Specifies the ISO B2 white medium: 500 mm x 707 mm
+ 'iso-b3-white': Specifies the ISO B3 white medium: 353 mm x 500 mm
+ 'iso-b6-white': Specifies the ISO B6 white medium: 125 mm x 176 mm
+ 'iso-b7-white': Specifies the ISO B7 white medium: 88 mm x 125 mm
+ 'iso-b8-white': Specifies the ISO B8 white medium: 62 mm x 88 mm
+ 'iso-b9-white': Specifies the ISO B9 white medium: 44 mm x 62 mm
+ 'iso-b10-white': Specifies the ISO B10 white medium: 31 mm x 44 mm
+ 'jis-b0-white': Specifies the JIS B0 white medium: 1030 mm x 1456 mm
+ 'jis-b0-transparent': Specifies the JIS B0 transparent medium: 1030
+ mm x 1456 mm
+ 'jis-b0-translucent': Specifies the JIS B0 translucent medium: 1030
+ mm x 1456 mm
+ 'jis-b1-white': Specifies the JIS B1 white medium: 728 mm x 1030 mm
+ 'jis-b1-transparent': Specifies the JIS B1 transparent medium: 728 mm
+ x 1030 mm
+ 'jis-b1-translucent': Specifies the JIS B1 translucent medium: 728 mm
+ x 1030 mm
+ 'jis-b2-white': Specifies the JIS B2 white medium: 515 mm x 728 mm
+ 'jis-b2-transparent': Specifies the JIS B2 transparent medium: 515 mm
+ x 728 mm
+ 'jis-b2-translucent': Specifies the JIS B2 translucent medium: 515 mm
+ x 728 mm
+ 'jis-b3-white': Specifies the JIS B3 white medium: 364 mm x 515 mm
+ 'jis-b3-transparent': Specifies the JIS B3 transparent medium: 364 mm
+ x 515 mm
+ 'jis-b3-translucent': Specifies the JIS B3 translucent medium: 364 mm
+ x 515 mm
+
+
+
+Hastings, et al. Standards Track [Page 192]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'jis-b4-transparent': Specifies the JIS B4 transparent medium: 257 mm
+ x 364 mm
+ 'jis-b4-translucent': Specifies the JIS B4 translucent medium: 257 mm
+ x 364 mm
+ 'jis-b5-transparent': Specifies the JIS B5 transparent medium: 182 mm
+ x 257 mm
+ 'jis-b5-translucent': Specifies the JIS B5 translucent medium: 182 mm
+ x 257 mm
+ 'jis-b6-white': Specifies the JIS B6 white medium: 128 mm x 182 mm
+ 'jis-b7-white': Specifies the JIS B7 white medium: 91 mm x 128 mm
+ 'jis-b8-white': Specifies the JIS B8 white medium: 64 mm x 91 mm
+ 'jis-b9-white': Specifies the JIS B9 white medium: 45 mm x 64 mm
+ 'jis-b10-white': Specifies the JIS B10 white medium: 32 mm x 45 mm
+
+ The following standard values are defined for American Standard (i.e.
+ ANSI) engineering media:
+
+ 'a-white': Specifies the engineering ANSI A size white medium: 8.5
+ inches x 11 inches
+ 'a-transparent': Specifies the engineering ANSI A size transparent
+ medium: 8.5 inches x 11 inches
+ 'a-translucent': Specifies the engineering ANSI A size translucent
+ medium: 8.5 inches x 11 inches
+ 'b-white': Specifies the engineering ANSI B size white medium: 11
+ inches x 17 inches
+ 'b-transparent': Specifies the engineering ANSI B size transparent
+ medium: 11 inches x 17 inches)
+ 'b-translucent': Specifies the engineering ANSI B size translucent
+ medium: 11 inches x 17 inches
+ 'c-white': Specifies the engineering ANSI C size white medium: 17
+ inches x 22 inches
+ 'c-transparent': Specifies the engineering ANSI C size transparent
+ medium: 17 inches x 22 inches
+ 'c-translucent': Specifies the engineering ANSI C size translucent
+ medium: 17 inches x 22 inches
+ 'd-white': Specifies the engineering ANSI D size white medium: 22
+ inches x 34 inches
+ 'd-transparent': Specifies the engineering ANSI D size transparent
+ medium: 22 inches x 34 inches
+ 'd-translucent': Specifies the engineering ANSI D size translucent
+ medium: 22 inches x 34 inches
+ 'e-white': Specifies the engineering ANSI E size white medium: 34
+ inches x 44 inches
+ 'e-transparent': Specifies the engineering ANSI E size transparent
+ medium: 34 inches x 44 inches
+ 'e-translucent': Specifies the engineering ANSI E size translucent
+ medium: 34 inches x 44 inches
+
+
+
+
+Hastings, et al. Standards Track [Page 193]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following standard values are defined for American Standard (i.e.
+ ANSI) engineering media for devices that provide the "synchro-cut"
+ feature (see section 14.1):
+
+ 'axsynchro-white': Specifies the roll paper having the width of the
+ longer edge (11 inches) of the engineering ANSI A size white medium
+ and cuts synchronizing with data.
+ 'axsynchro-transparent': Specifies the roll paper having the width of
+ the longer edge (11 inches) of the engineering ANSI A size
+ transparent medium and cuts synchronizing with data.
+ 'axsynchro-translucent': Specifies the roll paper having the width of
+ the longer edge (11 inches) of the engineering ANSI A size
+ translucent medium and cuts synchronizing with data.
+ 'bxsynchro-white': Specifies the roll paper having the width of the
+ longer edge (17 inches) of the engineering ANSI B size white medium
+ and cuts synchronizing with data.
+ 'bxsynchro-transparent': Specifies the roll paper having the width of
+ the longer edge (17 inches) of the engineering ANSI B size
+ transparent medium and cuts synchronizing with data.
+ 'bxsynchro-translucent': Specifies the roll paper having the width of
+ the longer edge (17 inches) of the engineering ANSI B size
+ translucent medium and cuts synchronizing with data.
+ 'cxsynchro-white': Specifies the roll paper having the width of the
+ longer edge (22 inches) of the engineering ANSI C size white medium
+ and cuts synchronizing with data.
+ 'cxsynchro-transparent': Specifies the roll paper having the width of
+ the longer edge (22 inches) of the engineering ANSI C size
+ transparent medium and cuts synchronizing with data.
+ 'cxsynchro-translucent': Specifies the roll paper having the width of
+ the longer edge (22 inches) of the engineering ANSI C size
+ translucent medium and cuts synchronizing with data.
+ 'dxsynchro-white': Specifies the roll paper having the width of the
+ longer edge (34 inches) of the engineering ANSI D size white medium
+ and cuts synchronizing with data.
+ 'dxsynchro-transparent': Specifies the roll paper having the width of
+ the longer edge (34 inches) of the engineering ANSI D size
+ transparent medium and cuts synchronizing with data.
+ 'dxsynchro-translucent': Specifies the roll paper having the width of
+ the longer edge (34 inches) of the engineering ANSI D size
+ translucent medium and cuts synchronizing with data.
+ 'exsynchro-white': Specifies the roll paper having the width of the
+ longer edge (44 inches) of the engineering ANSI E size white medium
+ and cuts synchronizing with data.
+ 'exsynchro-transparent': Specifies the roll paper having the width of
+ the longer edge (44 inches) of the engineering ANSI E size
+ transparent medium and cuts synchronizing with data.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 194]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'exsynchro-translucent': Specifies the roll paper having the width of
+ the longer edge (44 inches) of the engineering ANSI E size
+ translucent medium and cuts synchronizing with data.
+
+ The following standard values are defined for American Architectural
+ engineering media:
+
+ 'arch-a-white': Specifies the Architectural A size white medium: 9
+ inches x 12 inches
+ 'arch-a-transparent': Specifies the Architectural A size transparent
+ medium: 9 inches x 12 inches
+ 'arch-a-translucent': Specifies the Architectural A size translucent
+ medium: 9 inches x 12 inches
+ 'arch-b-white': Specifies the Architectural B size white medium: 12
+ inches x 18 inches
+ 'arch-b-transparent': Specifies the Architectural B size transparent
+ medium: 12 inches x 18 inches
+ 'arch-b-translucent': Specifies the Architectural B size translucent
+ medium: 12 inches x 18 inches
+ 'arch-c-white': Specifies the Architectural C size white medium: 18
+ inches x 24 inches
+ 'arch-c-transparent': Specifies the Architectural C size transparent
+ medium: 18 inches x 24 inches
+ 'arch-c-translucent': Specifies the Architectural C size translucent
+ medium: 18 inches x 24 inches
+ 'arch-d-white': Specifies the Architectural D size white medium: 24
+ inches x 36 inches
+ 'arch-d-transparent': Specifies the Architectural D size transparent
+ medium: 24 inches x 36 inches
+ 'arch-d-translucent': Specifies the Architectural D size translucent
+ medium: 24 inches x 36 inches
+ 'arch-e-white': Specifies the Architectural E size white medium: 36
+ inches x 48 inches
+ 'arch-e-transparent': Specifies the Architectural E size transparent
+ medium: 36 inches x 48 inches
+ 'arch-e-translucent': Specifies the Architectural E size translucent
+ medium: 36 inches x 48 inches
+
+ The following standard values are defined for American Architectural
+ engineering media for devices that provide the "synchro-cut" feature
+ (see section 14.1):
+
+ 'arch-axsynchro-white': Specifies the roll paper having the width of
+ the longer edge (12 inches) of the Architectural A size white
+ medium and cuts synchronizing with data.
+ 'arch-axsynchro-transparent': Specifies the roll paper having the
+ width of the longer edge (12 inches) of the Architectural A size
+ transparent medium and cuts synchronizing with data.
+
+
+
+Hastings, et al. Standards Track [Page 195]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'arch-axsynchro-translucent': Specifies the roll paper having the
+ width of the longer edge (12 inches) of the Architectural A size
+ translucent medium and cuts synchronizing with data.
+ 'arch-bxsynchro-white': Specifies the roll paper having the width of
+ the longer edge (18 inches) of the Architectural B size white
+ medium and cuts synchronizing with data.
+ 'arch-bxsynchro-transparent': Specifies the roll paper having the
+ width of the longer edge (18 inches) of the Architectural B size
+ transparent medium and cuts synchronizing with data.
+ 'arch-bxsynchro-translucent': Specifies the roll paper having the
+ width of the longer edge (18 inches) of the Architectural B size
+ translucent medium and cuts synchronizing with data.
+ 'arch-cxsynchro-white': Specifies the roll paper having the width of
+ the longer edge (24 inches) of the Architectural C size white
+ medium and cuts synchronizing with data.
+ 'arch-cxsynchro-transparent': Specifies the roll paper having the
+ width of the longer edge (24 inches) of the Architectural C size
+ transparent medium and cuts synchronizing with data.
+ 'arch-cxsynchro-translucent': Specifies the roll paper having the
+ width of the longer edge (24 inches) of the Architectural C size
+ translucent medium and cuts synchronizing with data.
+ 'arch-dxsynchro-white': Specifies the roll paper having the width of
+ the longer edge (36 inches) of the Architectural D size white
+ medium and cuts synchronizing with data.
+ 'arch-dxsynchro-transparent': Specifies the roll paper having the
+ width of the longer edge (36 inches) of the Architectural D size
+ transparent medium and cuts synchronizing with data.
+ 'arch-dxsynchro-translucent': Specifies the roll paper having the
+ width of the longer edge (36 inches) of the Architectural D size
+ translucent medium and cuts synchronizing with data.
+ 'arch-exsynchro-white': Specifies the roll paper having the width of
+ the longer edge (48 inches) of the Architectural E size white
+ medium and cuts synchronizing with data.
+ 'arch-exsynchro-transparent': Specifies the roll paper having the
+ width of the longer edge (48 inches) of the Architectural E size
+ transparent medium and cuts synchronizing with data.
+ 'arch-exsynchro-translucent': Specifies the roll paper having the
+ width of the longer edge (48 inches) of the Architectural E size
+ translucent medium and cuts synchronizing with data.
+
+ The following standard values are defined for Japanese and European
+ Standard (i.e. ISO) engineering media, which are of a long fixed size
+ [ASME-Y14.1M]:
+
+ 'iso-a1x3-white': Specifies the ISO A1X3 white medium having the
+ width of the longer edge (841 mm) of the ISO A1 medium
+
+
+
+
+
+Hastings, et al. Standards Track [Page 196]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'iso-a1x3-transparent': Specifies the ISO A1X3 transparent medium
+ having the width of the longer edge (841 mm) of the ISO A1
+ medium
+ 'iso-a1x3-translucent': Specifies the ISO A1X3 translucent medium
+ having the width of the longer edge (841 mm) of the ISO A1
+ medium
+ 'iso-a1x4-white': Specifies the ISO A1X4 white medium having the
+ width of the longer edge (841 mm) of the ISO A1 medium
+ 'iso-a1x4-transparent': Specifies the ISO A1X4 transparent medium
+ having the width of the longer edge (841 mm) of the ISO A1
+ medium
+ 'iso-a1x4- translucent': Specifies the ISO A1X4 translucent medium
+ having the width of the longer edge (841 mm) of the ISO A1
+ medium
+ 'iso-a2x3-white': Specifies the ISO A2X3 white medium having the
+ width of the longer edge (594 mm) of the ISO A2 medium
+ 'iso-a2x3-transparent': Specifies the ISO A2X3 transparent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a2x3-translucent': Specifies the ISO A2X3 translucent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a2x4-white': Specifies the ISO A2X4 white medium having the
+ width of the longer edge (594 mm) of the ISO A2 medium
+ 'iso-a2x4-transparent': Specifies the ISO A2X4 transparent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a2x4-translucent': Specifies the ISO A2X4 translucent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a2x5-white': Specifies the ISO A2X5 white medium having the
+ width of the longer edge (594 mm) of the ISO A2 medium
+ 'iso-a2x5-transparent': Specifies the ISO A2X5 transparent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a2x5-translucent': Specifies the ISO A2X5 translucent medium
+ having the width of the longer edge (594 mm) of the ISO A2
+ medium
+ 'iso-a3x3-white': Specifies the ISO A3X3 white medium having the
+ width of the longer edge (420 mm) of the ISO A3 medium
+ 'iso-a3x3-transparent': Specifies the ISO A3X3 transparent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x3-translucent': Specifies the ISO A3X3 translucent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x4-white': Specifies the ISO A3X4 white medium having the
+ width of the longer edge (420 mm) of the ISO A3 medium
+
+
+
+Hastings, et al. Standards Track [Page 197]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'iso-a3x4-transparent': Specifies the ISO A3X4 transparent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x4-translucent': Specifies the ISO A3X4 translucent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x5-white': Specifies the ISO A3X5 white medium having the
+ width of the longer edge (420 mm) of the ISO A3 medium
+ 'iso-a3x5-transparent': Specifies the ISO A3X5 transparent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x5-translucent': Specifies the ISO A3X5 translucent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x6-white': Specifies the ISO A3X6 white medium having the
+ width of the longer edge (420 mm) of the ISO A3 medium
+ 'iso-a3x6-transparent': Specifies the ISO A3X6 transparent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x6-translucent': Specifies the ISO A3X6 translucent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x7-white': Specifies the ISO A3X7 white medium having the
+ width of the longer edge (420 mm) of the ISO A3 medium
+ 'iso-a3x7-transparent': Specifies the ISO A3X7 transparent medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a3x7-translucent'': Specifies the ISO A3X7 translucent' medium
+ having the width of the longer edge (420 mm) of the ISO A3
+ medium
+ 'iso-a4x3-white': Specifies the ISO A4X3 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x3-transparent': Specifies the ISO A4X3 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x3-translucent'': Specifies the ISO A4X3 translucent' medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x4-white': Specifies the ISO A4X4 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x4-transparent': Specifies the ISO A4X4 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x4-translucent': Specifies the ISO A4X4 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x5-white': Specifies the ISO A4X5 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+
+
+
+Hastings, et al. Standards Track [Page 198]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'iso-a4x5-transparent': Specifies the ISO A4X5 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x5-translucent': Specifies the ISO A4X5 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x6-white': Specifies the ISO A4X6 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x6-transparent': Specifies the ISO A4X6 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x6-translucent': Specifies the ISO A4X6 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x7-white': Specifies the ISO A4X7 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x7-transparent': Specifies the ISO A4X7 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x7-translucent': Specifies the ISO A4X7 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x8-white': Specifies the ISO A4X8 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x8-transparent': Specifies the ISO A4X8 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x8-translucent': Specifies the ISO A4X8 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x9-white': Specifies the ISO A4X9 white medium having the
+ width of the longer edge (297 mm) of the ISO A4 medium
+ 'iso-a4x9-transparent': Specifies the ISO A4X9 transparent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+ 'iso-a4x9-translucent': Specifies the ISO A4X9 translucent medium
+ having the width of the longer edge (297 mm) of the ISO A4
+ medium
+
+ The following standard values are defined for Japanese and European
+ Standard (i.e. ISO) engineering media, which are either a long fixed
+ size [ASME-Y14.1M] or roll feed, for devices that provide the
+ "synchro-cut" feature (see section 14.1):
+
+ 'iso-a0xsynchro-white': Specifies the paper having the width of the
+ longer edge (1189 mm) of the ISO A0 white medium and cuts
+ synchronizing with data.
+
+
+
+
+Hastings, et al. Standards Track [Page 199]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'iso-a0xsynchro-transparent': Specifies the paper having the width of
+ the longer edge (1189 mm) of the ISO A0 transparent medium and
+ cuts synchronizing with data.
+ 'iso-a0xsynchro-translucent': Specifies the paper having the width of
+ the longer edge (1189 mm) of the ISO A0 translucent medium and
+ cuts synchronizing with data.
+ 'iso-a1xsynchro-white': Specifies the paper having the width of the
+ longer edge (841 mm) of the ISO A1 white medium and cuts
+ synchronizing with data.
+ 'iso-a1xsynchro-transparent': Specifies the paper having the width of
+ the longer edge (841 mm) of the ISO A1 transparent medium and
+ cuts synchronizing with data.
+ 'iso-a1xsynchro-translucent': Specifies the paper having the width of
+ the longer edge (841 mm) of the ISO A1 translucent medium and
+ cuts synchronizing with data.
+ 'iso-a2xsynchro-white': Specifies the paper having the width of the
+ longer edge (594 mm) of the ISO A2 white medium and cuts
+ synchronizing with data.
+ 'iso-a2xsynchro-transparent': Specifies the paper having the width of
+ the longer edge (594 mm) of the ISO A2 transparent medium and
+ cuts synchronizing with data.
+ 'iso-a2xsynchro-translucent': Specifies the paper having the width of
+ the longer edge (594 mm) of the ISO A2 translucent medium and
+ cuts synchronizing with data.
+ 'iso-a3xsynchro-white': Specifies the paper having the width of the
+ longer edge (420 mm) of the ISO A3 white medium and cuts
+ synchronizing with data.
+ 'iso-a3xsynchro-transparent': Specifies the paper having the width of
+ the longer edge (420 mm) of the ISO A3 transparent medium and
+ cuts synchronizing with data.
+ 'iso-a3xsynchro-translucent': Specifies the paper having the width of
+ the longer edge (420 mm) of the ISO A3 translucent medium and
+ cuts synchronizing with data.
+ 'iso-a4xsynchro-white': Specifies the paper having the width of the
+ longer edge (297 mm) of the ISO A4 white medium and cuts
+ synchronizing with data.
+ 'iso-a4xsynchro-transparent': Specifies the paper having the width of
+ the longer edge (297 mm) of the ISO A4 transparent medium and
+ cuts synchronizing with data.
+ 'iso-a4xsynchro-translucent': Specifies the paper having the width of
+ the longer edge (297 mm) of the ISO A4 transparent medium and
+ cuts synchronizing with data.
+
+ The following standard values are defined for American Standard (i.e.
+ ANSI) engineering media, American Architectural engineering media,
+ and Japanese and European Standard (i.e. ISO) engineering media,
+
+
+
+
+
+Hastings, et al. Standards Track [Page 200]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ which are either a long fixed size [ASME-Y14.1M] or roll feed, for
+ devices that provide the "synchro-cut" feature and/or the "auto-
+ select" feature (see section 14.1):
+
+ 'auto-white': Specifies that the printer selects the white medium
+ with the appropriate fixed size (e.g. a1, a2, etc.) or data-
+ synchro size, and the selection is implementation-defined.
+ 'auto-transparent': Specifies that the printer selects the
+ transparent medium with the appropriate fixed size (e.g. a1, a2,
+ etc.) or data-synchro size, and the selection is implementation-
+ defined.
+ 'auto-translucent': Specifies that the printer selects the
+ translucent medium with the appropriate fixed size (e.g. a1, a2,
+ etc.) or data-synchro size, and the selection is implementation-
+ defined.
+ 'auto-fixed-size-white': Specifies that the printer selects the white
+ medium with the appropriate fixed size (e.g. a1, a2, etc.) or
+ the appropriate long fixed size listed above.
+ 'auto-fixed-size-transparent': Specifies that the printer selects the
+ transparent medium with the appropriate fixed size (e.g. a1, a2,
+ etc.) or the appropriate long fixed size listed above.
+ 'auto-fixed-size-translucent': Specifies that the printer selects the
+ translucent medium with the appropriate fixed size (e.g. a1, a2,
+ etc.) or the appropriate long fixed size listed above.
+ 'auto-synchro-white': Specifies that the printer selects the white
+ paper with the appropriate width and cuts it synchronizing with
+ data.
+ 'auto-synchro-transparent': Specifies that the printer selects the
+ transparent paper with the appropriate width and cuts it
+ synchronizing with data.
+ 'auto-synchro-translucent': Specifies that the printer selects the
+ translucent paper with the appropriate width and cuts it
+ synchronizing with data.
+
+ The following standard values are defined for input-trays (from ISO
+ DPA and the Printer MIB):
+
+ 'top': The top input tray in the printer.
+ 'middle': The middle input tray in the printer.
+ 'bottom': The bottom input tray in the printer.
+ 'envelope': The envelope input tray in the printer.
+ 'manual': The manual feed input tray in the printer.
+ 'large-capacity': The large capacity input tray in the printer.
+ 'main': The main input tray
+ 'side': The side input tray
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 201]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following standard values are defined for media sizes (from ISO
+ DPA):
+
+ 'iso-a0': Specifies the ISO A0 size: 841 mm by 1189 mm as defined in
+ ISO 216
+ 'iso-a1': Specifies the ISO A1 size: 594 mm by 841 mm as defined in
+ ISO 216
+ 'iso-a2': Specifies the ISO A2 size: 420 mm by 594 mm as defined in
+ ISO 216
+ 'iso-a3': Specifies the ISO A3 size: 297 mm by 420 mm as defined in
+ ISO 216
+ 'iso-a4': Specifies the ISO A4 size: 210 mm by 297 mm as defined in
+ ISO 216
+ 'iso-a5': Specifies the ISO A5 size: 148 mm by 210 mm as defined in
+ ISO 216
+ 'iso-a6': Specifies the ISO A6 size: 105 mm by 148 mm as defined in
+ ISO 216
+ 'iso-a7': Specifies the ISO A7 size: 74 mm by 105 mm as defined in
+ ISO 216
+ 'iso-a8': Specifies the ISO A8 size: 52 mm by 74 mm as defined in ISO
+ 216
+ 'iso-a9': Specifies the ISO A9 size: 37 mm by 52 mm as defined in ISO
+ 216
+ 'iso-a10': Specifies the ISO A10 size: 26 mm by 37 mm as defined in
+ ISO 216
+ 'iso-b0': Specifies the ISO B0 size: 1000 mm by 1414 mm as defined in
+ ISO 216
+ 'iso-b1': Specifies the ISO B1 size: 707 mm by 1000 mm as defined in
+ ISO 216
+ 'iso-b2': Specifies the ISO B2 size: 500 mm by 707 mm as defined in
+ ISO 216
+ 'iso-b3': Specifies the ISO B3 size: 353 mm by 500 mm as defined in
+ ISO 216
+ 'iso-b4': Specifies the ISO B4 size: 250 mm by 353 mm as defined in
+ ISO 216
+ 'iso-b5': Specifies the ISO B5 size: 176 mm by 250 mm as defined in
+ ISO 216
+ 'iso-b6': Specifies the ISO B6 size: 125 mm by 176 mm as defined in
+ ISO 216
+ 'iso-b7': Specifies the ISO B7 size: 88 mm by 125 mm as defined in
+ ISO 216
+ 'iso-b8': Specifies the ISO B8 size: 62 mm by 88 mm as defined in ISO
+ 216
+ 'iso-b9': Specifies the ISO B9 size: 44 mm by 62 mm as defined in ISO
+ 216
+ 'iso-b10': Specifies the ISO B10 size: 31 mm by 44 mm as defined in
+ ISO 216
+
+
+
+
+Hastings, et al. Standards Track [Page 202]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'na-letter': Specifies the North American letter size: 8.5 inches by
+ 11 inches
+ 'na-legal': Specifies the North American legal size: 8.5 inches by 14
+ inches
+ 'na-8x10': Specifies the North American 8 inches by 10 inches
+ 'na-5x7': Specifies the North American 5 inches by 7 inches
+ 'executive': Specifies the executive size (7.25 X 10.5 in)
+ 'folio': Specifies the folio size (8.5 X 13 in)
+ 'invoice': Specifies the invoice size (5.5 X 8.5 in)
+ 'ledger': Specifies the ledger size (11 X 17 in)
+ 'quarto': Specifies the quarto size (8.5 X 10.83 in)
+ 'iso-c3': Specifies the ISO C3 size: 324 mm by 458 mm as defined in
+ ISO 269
+ 'iso-c4': Specifies the ISO C4 size: 229 mm by 324 mm as defined in
+ ISO 269
+ 'iso-c5': Specifies the ISO C5 size: 162 mm by 229 mm as defined in
+ ISO 269
+ 'iso-c6': Specifies the ISO C6 size: 114 mm by 162 mm as defined in
+ ISO 269
+ 'iso-designated-long': Specifies the ISO Designated Long size: 110 mm
+ by 220 mm as defined in ISO 269
+ 'na-10x13-envelope': Specifies the North American 10x13 size: 10
+ inches by 13 inches
+ 'na-9x12-envelope': Specifies the North American 9x12 size: 9 inches
+ by 12 inches
+ 'na-number-10-envelope': Specifies the North American number 10
+ business envelope size: 4.125 inches by 9.5 inches
+ 'na-7x9-envelope': Specifies the North American 7x9 inch envelope
+ size
+ 'na-9x11-envelope': Specifies the North American 9x11 inch envelope
+ size
+ 'na-10x14-envelope': Specifies the North American 10x14 inch envelope
+ size
+ 'na-number-9-envelope': Specifies the North American number 9
+ business envelope size
+ 'na-6x9-envelope': Specifies the North American 6x9 envelope size
+ 'na-10x15-envelope': Specifies the North American 10x15 envelope size
+ 'monarch-envelope': Specifies the Monarch envelope size (3.87 x 7.5
+ in)
+ 'jis-b0': Specifies the JIS B0 size: 1030mm x 1456mm
+ 'jis-b1': Specifies the JIS B1 size: 728mm x 1030mm
+ 'jis-b2': Specifies the JIS B2 size: 515mm x 728mm
+ 'jis-b3': Specifies the JIS B3 size: 364mm x 515mm
+ 'jis-b4': Specifies the JIS B4 size: 257mm x 364mm
+ 'jis-b5': Specifies the JIS B5 size: 182mm x 257mm
+ 'jis-b6': Specifies the JIS B6 size: 128mm x 182mm
+ 'jis-b7': Specifies the JIS B7 size: 91mm x 128mm
+ 'jis-b8': Specifies the JIS B8 size: 64mm x 91mm
+
+
+
+Hastings, et al. Standards Track [Page 203]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 'jis-b9': Specifies the JIS B9 size: 45mm x 64mm
+ 'jis-b10': Specifies the JIS B10 size: 32mm x 45mm
+
+ The following standard values are defined for American Standard (i.e.
+ ANSI) engineering media sizes:
+
+ 'a': Specifies the engineering ANSI A size medium: 8.5 inches x 11
+ inches
+ 'b': Specifies the engineering ANSI B size medium: 11 inches x 17
+ inches
+ 'c': Specifies the engineering ANSI C size medium: 17 inches x 22
+ inches
+ 'd': Specifies the engineering ANSI D size medium: 22 inches x 34
+ inches
+ 'e': Specifies the engineering ANSI E size medium: 34 inches x 44
+ inches
+
+ The following standard values are defined for American Architectural
+ engineering media sizes:
+
+ 'arch-a': Specifies the Architectural A size medium: 9 inches x 12
+ inches
+ 'arch-b': Specifies the Architectural B size medium: 12 inches x 18
+ inches
+ 'arch-c': Specifies the Architectural C size medium: 18 inches x 24
+ inches
+ 'arch-d': Specifies the Architectural D size medium: 24 inches x 36
+ inches
+ 'arch-e': Specifies the Architectural E size medium: 36 inches x 48
+ inches
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 204]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+14.1. Examples
+
+ Below are examples to supplement the engineering media value
+ definitions.
+
+ Example 1: "Synchro-Cut", a device cutting the roll paper in
+ synchronization with the data
+
+ data height: A1 height
+ data width (shaded): A1 width < data width < (A1 width) x 2
+ specified value: 'iso-a1xsynchro-white'
+
+ | |
+ |<--- data width --->|
+ | |
+ | | | |
+ |<- A1 width ->|<- A1 width ->|
+ | | | |
+ cross ^ | | | |
+ feed | +--------------------------------------------/
+ direction | |//////////////|/////| | ^ /
+ | |//////////////|/////| | | /
+ | |//////////////|/////| | | /
+ | |//////////////|/////| | | \
+<-----------+- |//////////////|/////| | A1 \ roll
+feed | |//////////////|/////| | height \ paper
+direction |//////////////|/////| | | \
+ |//////////////|/////| | | /
+ |//////////////|/////| | v /
+ +------------------------------------------/
+ |
+ |
+ |<------ CUT HERE (to synchronize
+ | with data width)
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 205]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Example 2: "Auto-Cut", a device cutting the roll paper at multiples
+ of fixed-size media width
+
+ data height: A1 height
+ data width (shaded): A1 width < data width < (A1 width) x 2
+ specified value: 'auto-fixed-size-white'
+
+ | |
+ |<--- data width --->|
+ | |
+ | | | |
+ |<- A1 width ->|<- A1 width ->|
+ | | | |
+ cross ^ | | | |
+ feed | +--------------------------------------------/
+ direction | |//////////////|/////| | ^ /
+ | |//////////////|/////| | | /
+ | |//////////////|/////| | | /
+ | |//////////////|/////| | | \
+<-----------+- |//////////////|/////| | A1 \ roll
+feed | |//////////////|/////| | height \ paper
+direction |//////////////|/////| | | \
+ |//////////////|/////| | | /
+ |//////////////|/////| | v /
+ +------------------------------------------/
+ |
+ |
+ |<--- CUT HERE
+ | (to synchronize
+ | with data width)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 206]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Example 3: the 'iso-a4x4-white' fixed size paper
+
+ paper height: A4 height
+ paper width: (A4 width) x 4
+ specified value: 'iso-a4x4-white'
+
+ | | | | |
+ |<- A4 width ->|<- A4 width ->|<- A4 width ->|<- A4 width ->|
+ | | | | |
+ | | | | |
+ +-----------------------------------------------------------+
+ | ^ | | | |
+ | | | | | |
+ | | | | | |
+ | A4 | | | |
+ | height | | | |
+ | | | | | |
+ | | | | | |
+ | | | | | |
+ | v | | | |
+ +-----------------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 207]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Example 4: "Synchro-Cut", a device cutting the fixed size paper in
+ synchronization with the data
+
+ data height: A4 height
+ data width (shaded): (A4 width) x 2 < data width < (A4 width) x 3
+ specified value: 'iso-a4xsynchro-white'
+
+ | |
+ |<---------- data width ----------->|
+ | |
+ | | | | |
+ |<- A4 width ->|<- A4 width ->|<- A4 width ->|
+ | | | | |
+ cross ^ | | | | |
+ feed | +--------------------------------------------+
+ direction | |//////////////|//////////////|/////| ^ |
+ | |//////////////|//////////////|/////| | |
+ | |//////////////|//////////////|/////| | |
+ | |//////////////|//////////////|/////| | |
+ <-----------+- |//////////////|//////////////|/////| A4 |
+ feed | |//////////////|//////////////|/////| height |
+ direction |//////////////|//////////////|/////| | |
+ |//////////////|//////////////|/////| | |
+ |//////////////|//////////////|/////| v |
+ +--------------------------------------------+
+ |
+ CUT HERE ---->|
+ (to synchronize |
+ with data width) |
+
+15. APPENDIX D: Processing IPP Attributes
+
+ When submitting a print job to a Printer object, the IPP model allows
+ a client to supply operation and Job Template attributes along with
+ the document data. These Job Template attributes in the create
+ request affect the rendering, production and finishing of the
+ documents in the job. Similar types of instructions may also be
+ contained in the document to be printed, that is, embedded within the
+ print data itself. In addition, the Printer has a set of attributes
+ that describe what rendering and finishing options which are
+ supported by that Printer. This model, which allows for flexibility
+ and power, also introduces the potential that at job submission time,
+ these client-supplied attributes may conflict with either:
+
+ - what the implementation is capable of realizing (i.e., what the
+ Printer supports), as well as
+ - the instructions embedded within the print data itself.
+
+
+
+
+Hastings, et al. Standards Track [Page 208]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The following sections describe how these two types of conflicts are
+ handled in the IPP model.
+
+15.1 Fidelity
+
+ If there is a conflict between what the client requests and what a
+ Printer object supports, the client may request one of two possible
+ conflict handling mechanisms:
+
+ 1) either reject the job since the job can not be processed
+ exactly as specified, or
+ 2) allow the Printer to make any changes necessary to proceed with
+ processing the Job the best it can.
+
+ In the first case the client is indicating to the Printer object:
+ "Print the job exactly as specified with no exceptions, and if that
+ can't be done, don't even bother printing the job at all." In the
+ second case, the client is indicating to the Printer object: "It is
+ more important to make sure the job is printed rather than be
+ processed exactly as specified; just make sure the job is printed
+ even if some client-supplied attributes need to be changed or
+ ignored."
+
+ The IPP model accounts for this situation by introducing an "ipp-
+ attribute-fidelity" attribute.
+
+ In a create request, "ipp-attribute-fidelity" is a boolean operation
+ attribute that is OPTIONALLY supplied by the client. The value
+ 'true' indicates that total fidelity to client supplied Job Template
+ attributes and values is required. The client is requesting that the
+ Job be printed exactly as specified, and if that is not possible then
+ the job MUST be rejected rather than processed incorrectly. The
+ value 'false' indicates that a reasonable attempt to print the Job is
+ acceptable. If a Printer does not support some of the client
+ supplied Job Template attributes or values, the Printer MUST ignore
+ them or substitute any supported value for unsupported values,
+ respectively. The Printer may choose to substitute the default value
+ associated with that attribute, or use some other supported value
+ that is similar to the unsupported requested value. For example, if
+ a client supplies a "media" value of 'na-letter', the Printer may
+ choose to substitute 'iso-a4' rather than a default value of
+ 'envelope'. If the client does not supply the "ipp-attribute-
+ fidelity" attribute, the Printer assumes a value of 'false'.
+
+ Each Printer implementation MUST support both types of "fidelity"
+ printing (that is whether the client supplies a value of 'true' or
+ 'false'):
+
+
+
+
+Hastings, et al. Standards Track [Page 209]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ - If the client supplies 'false' or does not supply the attribute,
+ the Printer object MUST always accept the request by ignoring
+ unsupported Job Template attributes and by substituting
+ unsupported values of supported Job Template attributes with
+ supported values.
+ - If the client supplies 'true', the Printer object MUST reject
+ the request if the client supplies unsupported Job Template
+ attributes.
+
+ Since a client can always query a Printer to find out exactly what is
+ and is not supported, "ipp-attribute-fidelity" set to 'false' is
+ useful when:
+
+ 1) The End-User uses a command line interface to request
+ attributes that might not be supported.
+ 2) In a GUI context, if the End User expects the job might be
+ moved to another printer and prefers a sub-optimal result to
+ nothing at all.
+ 3) The End User just wants something reasonable in lieu of nothing
+ at all.
+
+15.2 Page Description Language (PDL) Override
+
+ If there is a conflict between the value of an IPP Job Template
+ attribute and a corresponding instruction in the document data, the
+ value of the IPP attribute SHOULD take precedence over the document
+ instruction. Consider the case where a previously formatted file of
+ document data is sent to an IPP Printer. In this case, if the client
+ supplies any attributes at job submission time, the client desires
+ that those attributes override the embedded instructions. Consider
+ the case were a previously formatted document has embedded in it
+ commands to load 'iso-a4' media. However, the document is passed to
+ an end user that only has access to a printer with 'na-letter' media
+ loaded. That end user most likely wants to submit that document to
+ an IPP Printer with the "media" Job Template attribute set to 'na-
+ letter'. The job submission attribute should take precedence over
+ the embedded PDL instruction. However, until companies that supply
+ document data interpreters allow a way for external IPP attributes to
+ take precedence over embedded job production instructions, a Printer
+ might not be able to support the semantics that IPP attributes
+ override the embedded instructions.
+
+ The IPP model accounts for this situation by introducing a "pdl-
+ override-supported" attribute that describes the Printer objects
+ capabilities to override instructions embedded in the PDL data
+ stream. The value of the "pdl-override-supported" attribute is
+ configured by means outside the scope of this IPP/1.1 document.
+
+
+
+
+Hastings, et al. Standards Track [Page 210]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ This REQUIRED Printer attribute takes on the following values:
+
+ - 'attempted': This value indicates that the Printer object
+ attempts to make the IPP attribute values take precedence over
+ embedded instructions in the document data, however there is no
+ guarantee.
+ - 'not-attempted': This value indicates that the Printer object
+ makes no attempt to make the IPP attribute values take
+ precedence over embedded instructions in the document data.
+
+ At job processing time, an implementation that supports the value of
+ 'attempted' might do one of several different actions:
+
+ 1) Generate an output device specific command sequence to realize
+ the feature represented by the IPP attribute value.
+ 2) Parse the document data itself and replace the conflicting
+ embedded instruction with a new embedded instruction that
+ matches the intent of the IPP attribute value.
+ 3) Indicate to the Printer that external supplied attributes take
+ precedence over embedded instructions and then pass the
+ external IPP attribute values to the document data interpreter.
+ 4) Anything else that allows for the semantics that IPP attributes
+ override embedded document data instructions.
+
+ Since 'attempted' does not offer any type of guarantee, even though a
+ given Printer object might not do a very "good" job of attempting to
+ ensure that IPP attributes take a higher precedence over instructions
+ embedded in the document data, it would still be a conforming
+ implementation.
+
+ At job processing time, an implementation that supports the value of
+ 'not-attempted' might do one of the following actions:
+
+ 1) Simply pre-pend the document data with the PDL instruction that
+ corresponds to the client-supplied PDL attribute, such that if
+ the document data also has the same PDL instruction, it will
+ override what the Printer object pre-pended. In other words,
+ this implementation is using the same implementation semantics
+ for the client-supplied IPP attributes as for the Printer
+ object defaults.
+
+ 2) Parse the document data and replace the conflicting embedded
+ instruction with a new embedded instruction that approximates,
+ but does not match, the semantic intent of the IPP attribute
+ value.
+
+ Note: The "ipp-attribute-fidelity" attribute applies to the
+ Printer's ability to either accept or reject other unsupported Job
+
+
+
+Hastings, et al. Standards Track [Page 211]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ Template attributes. In other words, if "ipp-attribute-fidelity" is
+ set to 'true', a Job is accepted if and only if the client supplied
+ Job Template attributes and values are supported by the Printer.
+ Whether these attributes actually affect the processing of the Job
+ when the document data contains embedded instructions depends on the
+ ability of the Printer to override the instructions embedded in the
+ document data with the semantics of the IPP attributes. If the
+ document data attributes can be overridden ("pdl-override-supported"
+ set to 'attempted'), the Printer makes an attempt to use the IPP
+ attributes when processing the Job. If the document data attributes
+ can not be overridden ("pdl-override-supported" set to 'not-
+ attempted'), the Printer makes no attempt to override the embedded
+ document data instructions with the IPP attributes when processing
+ the Job, and hence, the IPP attributes may fail to affect the Job
+ processing and output when the corresponding instruction is embedded
+ in the document data.
+
+15.3 Using Job Template Attributes During Document Processing.
+
+ The Printer object uses some of the Job object's Job Template
+ attributes during the processing of the document data associated with
+ that job. These include, but are not limited to, "orientation-
+ requested", "number-up", "sides", "media", and "copies". The
+ processing of each document in a Job Object MUST follow the steps
+ below. These steps are intended only to identify when and how
+ attributes are to be used in processing document data and any
+ alternative steps that accomplishes the same effect can be used to
+ implement this specification document.
+
+ 1. Using the client supplied "document-format" attribute or some
+ form of document format detection algorithm (if the value of
+ "document-format" is not specific enough), determine whether or
+ not the document data has already been formatted for printing.
+ If the document data has been formatted, then go to step 2.
+ Otherwise, the document data MUST be formatted. The formatting
+ detection algorithm is implementation defined and is not
+ specified by this document. The formatting of the document
+ data uses the "orientation-requested" attribute to determine
+ how the formatted print data should be placed on a print-stream
+ page, see section 4.2.10 for the details.
+
+ 2. The document data is in the form of a print-stream in a known
+ media type. The "page-ranges" attribute is used to select, as
+ specified in section 4.2.7, a sub-sequence of the pages in the
+ print-stream that are to be processed and images.
+
+ 3. The input to this step is a sequence of print-stream pages.
+ This step is controlled by the "number-up" attribute. If the
+
+
+
+Hastings, et al. Standards Track [Page 212]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ value of "number-up" is N, then during the processing of the
+ print-stream pages, each N print-stream pages are positioned,
+ as specified in section 4.2.9, to create a single impression.
+ If a given document does not have N more print-stream pages,
+ then the completion of the impression is controlled by the
+ "multiple-document-handling" attribute as described in section
+ 4.2.4; when the value of this attribute is 'single-document' or
+ 'single-document-new-sheet', the print-stream pages of document
+ data from subsequent documents is used to complete the
+ impression.
+
+ The size(scaling), position(translation) and rotation of the
+ print-stream pages on the impression is implementation defined.
+ Note that during this process the print-stream pages may be
+ rendered to a form suitable for placing on the impression; this
+ rendering is controlled by the values of the "printer-
+ resolution" and "print-quality" attributes as described in
+ sections 4.2.12 and 4.2.13. In the case N=1, the impression is
+ nearly the same as the print-stream page; the differences would
+ only be in the size, position and rotation of the print-stream
+ page and/or any decoration, such as a frame to the page, that
+ is added by the implementation.
+
+ 4. The collection of impressions is placed, in sequence, onto
+ sides of the media sheets. This placement is controlled by the
+ "sides" attribute and the orientation of the print-stream page,
+ as described in section 4.2.8. The orientation of the print-
+ stream pages affects the orientation of the impression; for
+ example, if "number-up" equals 2, then, typically, two portrait
+ print-stream pages become one landscape impression. Note that
+ the placement of impressions onto media sheets is also
+ controlled by the "multiple-document-handling" attribute as
+ described in section 4.2.4.
+
+ 5. The "copies" and "multiple-document-handling" attributes are
+ used to determine how many copies of each media instance are
+ created and in what order. See sections 4.2.5 and 4.2.4 for the
+ details.
+
+ 6. When the correct number of copies are created, the media
+ instances are finished according to the values of the
+ "finishings" attribute as described in 4.2.6. Note that
+ sometimes finishing operations may require manual intervention
+ to perform the finishing operations on the copies, especially
+ uncollated copies. This document allows any or all of the
+ processing steps to be performed automatically or manually at
+ the discretion of the Printer object.
+
+
+
+
+Hastings, et al. Standards Track [Page 213]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+16. APPENDIX E: Generic Directory Schema
+
+ This section defines a generic schema for an entry in a directory
+ service. A directory service is a means by which service users can
+ locate service providers. In IPP environments, this means that IPP
+ Printers can be registered (either automatically or with the help of
+ an administrator) as entries of type printer in the directory using
+ an implementation specific mechanism such as entry attributes, entry
+ type fields, specific branches, etc. Directory clients can search or
+ browse for entries of type printer. Clients use the directory
+ service to find entries based on naming, organizational contexts, or
+ filtered searches on attribute values of entries. For example, a
+ client can find all printers in the "Local Department" context.
+ Authentication and authorization are also often part of a directory
+ service so that an administrator can place limits on end users so
+ that they are only allowed to find entries to which they have certain
+ access rights. IPP itself does not require any specific directory
+ service protocol or provider.
+
+ Note: Some directory implementations allow for the notion of
+ "aliasing". That is, one directory entry object can appear as
+ multiple directory entry object with different names for each object.
+ In each case, each alias refers to the same directory entry object
+ which refers to a single IPP Printer object.
+
+ The generic schema is a subset of IPP Printer Job Template and
+ Printer Description attributes (sections 4.2 and 4.4). These
+ attributes are identified as either RECOMMENDED or OPTIONAL for the
+ directory entry itself. This conformance labeling is NOT the same
+ conformance labeling applied to the attributes of IPP Printers
+ objects. The conformance labeling in this Appendix is intended to
+ apply to directory templates and to IPP Printer implementations that
+ subscribe by adding one or more entries to a directory. RECOMMENDED
+ attributes SHOULD be associated with each directory entry. OPTIONAL
+ attributes MAY be associated with the directory entry (if known or
+ supported). In addition, all directory entry attributes SHOULD
+ reflect the current attribute values for the corresponding Printer
+ object.
+
+ The names of attributes in directory schema and entries SHOULD be the
+ same as the IPP Printer attribute names as shown, as much as
+ possible.
+
+ In order to bridge between the directory service and the IPP Printer
+ object, one of the RECOMMENDED directory entry attributes is the
+ Printer object's "printer-uri-supported" attribute. The directory
+ client queries the "printer-uri-supported" attribute (or its
+ equivalent) in the directory entry and then the IPP client addresses
+
+
+
+Hastings, et al. Standards Track [Page 214]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ the IPP Printer object using one of its URIs. The "uri-security-
+ supported" attribute identifies the protocol (if any) used to secure
+ a channel.
+
+ The following attributes define the generic schema for directory
+ entries of type PRINTER:
+
+ printer-uri-supported RECOMMENDED Section 4.4.1
+ uri-authentication-supported RECOMMENDED Section 4.4.2
+ uri-security-supported RECOMMENDED Section 4.4.3
+ printer-name RECOMMENDED Section 4.4.4
+ printer-location RECOMMENDED Section 4.4.5
+ printer-info OPTIONAL Section 4.4.6
+ printer-more-info OPTIONAL Section 4.4.7
+ printer-make-and-model RECOMMENDED Section 4.4.9
+ ipp-versions-supported RECOMMENDED Section 4.4.14
+ multiple-document-jobs-supported OPTIONAL Section 4.4.16
+ charset-supported OPTIONAL Section 4.4.18
+
+ generated-natural-language-
+ supported OPTIONAL Section 4.4.20
+ document-format-supported RECOMMENDED Section 4.4.22
+ color-supported RECOMMENDED Section 4.4.26
+ compression-supported RECOMMENDED Section 4.4.32
+ pages-per-minute OPTIONAL Section 4.4.36
+ pages-per-minute-color OPTIONAL Section 4.4.37
+
+ finishings-supported OPTIONAL Section 4.2.6
+ number-up-supported OPTIONAL Section 4.2.7
+ sides-supported RECOMMENDED Section 4.2.8
+ media-supported RECOMMENDED Section 4.2.11
+ printer-resolution-supported OPTIONAL Section 4.2.12
+ print-quality-supported OPTIONAL Section 4.2.13
+
+17. APPENDIX F: Differences between the IPP/1.0 and IPP/1.1 "Model and
+ Semantics" Documents
+
+ This Appendix is divided into two lists that summarize the
+ differences between IPP/1.1 (this document) and IPP/1.0 [RFC2566].
+ The section numbers refer to the numbers in this document which in
+ some cases have changed from RFC 2566. When a change affects
+ multiple sections, the item is listed once in the order of the first
+ section affected and the remaining affected section numbers are
+ indicated.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 215]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ The first list contains extensions and clarifications and the second
+ list contains changes in semantics or conformance. However, client
+ and IPP object implementations of IPP/1.0 MAY implement any of the
+ extensions and clarifications in this document.
+
+ The following extensions and clarifications have been incorporated
+ into this document:
+
+ 1. Section 2.1 - clarified that the term "client" can be either
+ contained in software controlled by an end user or a part of a
+ print server that controls devices.
+ 2. Section 2 - clarified that the term "IPP object" and "Printer
+ object" can either be embedded in a device object or part of a
+ print server that accepts IPP requests.
+ 3. Section 2.4 - added the description of the new "uri-
+ authentication-supported" Printer Description attribute.
+ 4. Section 3.1.3, 3.1.6, 3.2.5.2, and 3.2.6.2 - clarified the
+ error handling for operation attributes that have their own
+ status code.
+ 5. Section 3.1.3 - clarified that multiple occurrences of the
+ same attribute in an attribute group is mal-formed. An IPP
+ Printer MAY reject the request or choose one of the
+ attributes.
+ 6. Section 3.1.6 - reorganized this section into sub-sections to
+ separately describe "status-code", "status-message",
+ "detailed-status-message", and "document-access-error"
+ attributes.
+ 7. Section 3.1.6.1 - clarified the error status codes and their
+ relationship to operation attributes.
+ 8. Section 3.1.6.3 - Added the OPTIONAL "detailed-status-message
+ (text(MAX))" operation attribute to provide additional more
+ detailed information about a response.
+ 9. Section 3.1.6.4 and 3.2.2 - Added the OPTIONAL "document-
+ access-error (text(MAX))" operation attribute for use with
+ Print-URI and Send-URI responses.
+ 10. Sections 3.1.7 - Added this new section to clarify returning
+ Unsupported Attributes for all operations, including only
+ returning attributes that were in the request. Moved the text
+ from section 3.2.1.2 Unsupported Attributes to this section.
+ 11. Sections 3.1.7 and 4.1 - clarified the encoding of the "out-
+ of-band" 'unsupported' and 'unknown' values.
+ 12. Section 3.1.8 - clarified that only the version number
+ parameter will be carried forward into future major or minor
+ versions of the protocol.
+ 13. Section 3.1.8 - relaxed the requirements to increment the
+ major version number in future versions of the Model and
+ Semantics document.
+
+
+
+
+Hastings, et al. Standards Track [Page 216]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 14. Section 3.1.9, and 3.2.5 - added the 'processing' state to the
+ list of job states that a job can be in after a Create-Job
+ operation.
+ 15. Section 3.1.9 - clarified that a non-spooling Printer MAY
+ accept zero or more subsequent jobs while processing a job and
+ flow control them down. Subsequent create requests are
+ rejected with the 'server-error-busy' error status.
+ 16. Section 3.2.1.1 - clarified the validation of the
+ "compression" operation attribute and its relationship to the
+ validation of the "document-format" attribute and returning
+ Unsupported Attributes.
+ 17. Sections 3.2.1.1, 4.3.8, 13.1.4.16, and 13.1.4.17 - added the
+ 'client-error-compression-not-supported', 'client-error-
+ compression-error' status codes and the 'unsupported-
+ compression' and 'compression-error' job-state-reasons.
+ 18. Sections 3.2.1.1 and 4.3.8 - added 'unsupported-document-
+ format' and 'document-format-error' job-state-reasons.
+ 19. Sections 3.2.2, 4.3.8 and 13.1.4.19 - added 'client-error-
+ document-access-error' status code and 'document-access-error'
+ job state reason.
+ 20. Section 3.2.5.2 and 3.2.6.2 - clarified that the Unsupported
+ Attributes group MUST NOT include attributes not requested in
+ the Get-Printer-Attributes request.
+ 21. Section 3.2.6 - clarified that "limit" takes precedence over
+ "which-jobs" and "my-jobs'.
+ 22. Section 3.2.6.2 - clarified that Get-Jobs returns
+ 'successful-ok' when no jobs to return.
+ 23. Sections 3.2.7, 3.2.8, and 3.2.9 - added the OPTIONAL Pause-
+ Printer, Resume-Printer, and Purge-Jobs operations
+ 24. Section 3.3.1 - clarified that the authorization required for
+ a Send-Document request MUST be the same user as the Create-
+ Job or an operator.
+ 25. Section 3.3.1.1 - clarified that a Create-Job Send-Document
+ with "last-document" = 'true' and no data is not an error; its
+ a job with no documents.
+ 26. Sections 3.3.5, 3.3.6, and 3.3.7 - added the OPTIONAL Hold-
+ Job, Release-Job, and Restart-Job operations. Clarified the
+ Restart-Job operation so that the Printer MUST re-fetch any
+ documents passed by-reference (Print-URI or Send-URI).
+ 27. Section 4.1 - clarified that the encoding of the out-of-band
+ values are specified in the Encoding and Transport" document.
+ 28. Section 4.1 - Clarified that the requirement that clients MUST
+ NOT send "out-of-band" values in requests applies only to
+ operations defined in this document. Other operations are
+ allowed to define "out-of-band" values that clients can
+ supply.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 217]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 29. Sections 4.1.1 and 4.1.2 - clarified that the maximum 'text'
+ and 'name' values of 1023 and 255 are for the
+ 'textWithoutLanguage' portion of the 'textWithLanguage' form,
+ so that the maximum number of octets for the actual text and
+ name data is the same for the without and with language forms;
+ the 'naturalLanguage' part is in addition.
+ 30. Section 4.1.9 - clarified that 'mimeMediaType' values can
+ include any parameters from the IANA Registry, not just
+ charset parameters.
+ 31. Section 4.1.9.1 - clarified that 'application/octet-stream'
+ auto-sensing can happen at create request time and/or
+ job/document processing time.
+ 32. Section 4.1.9.1 - clarified that auto-sensing involves the
+ Printer examining some number of octets of document data using
+ an implementation-dependent method.
+ 33. Section 4.1.14 - clarified that the localization of dateTime
+ by the client includes the time zone.
+ 34. Section 4.2 - clarified that xxx-supported have multiple
+ keywords and/or names by adding parentheses to the table to
+ give: (1setOf (type3 keyword | name))
+ 35. Section 4.2.2 - added the 'indefinite' keyword value to the
+ "job-hold-until" attribute for use with the create operations
+ and Hold-Job and Restart-Job operations.
+ 36. Section 4.2.6 - added more enum values to the "finishings" Job
+ Template attribute.
+ 37. Section 4.2.6 - clarified that the landscape definition is a
+ rotation of the image with respect to the medium.
+ 38. Section 4.3.7 - added that a forwarding server that cannot get
+ any job state MAY return the job's state as 'completed',
+ provided that it also return the new 'queued-in-device' job
+ state reason.
+ 39. Section 4.3.7.2 - added the Partitioning of Job States section
+ to clarify the concepts of Job Retention, Job History, and Job
+ Removal.
+ 40. Section 4.3.8 - added 'job-data-insufficient' job state reason
+ to indicate whether sufficient data has arrived for the
+ document to start to be processed.
+ 41. Section 4.3.8 - added 'document-access-error' job state reason
+ to indicate an access error of any kind.
+ 42. Section 4.3.8 - added 'job-queued-for-marker' job state reason
+ to indicate whether the job has completed some processing and
+ is waiting for the marker.
+ 43. Section 4.3.8 - added 'unsupported-compression' and
+ 'compression-error' job state reasons to indicate compression
+ not supported or compression processing error after the create
+ has been accepted.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 218]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 44. Section 4.3.8 - added 'unsupported-document-format' and
+ 'document-format-error' job state reasons to indicate document
+ not supported or document format processing error after the
+ create has been accepted.
+ 45. Section 4.3.8 - added 'queued-in-device' job state reason to
+ indicate that a job as been forwarded to a print system or
+ device that does not provide any job status.
+ 46. Section 4.3.10 - added "job-detailed-status-messages (1setOf
+ text(MAX)) for returning detailed error messages.
+ 47. Section 4.3.11 - added the "job-document-access-errors (1setOf
+ text(MAX))
+ 48. Section 4.3.14.2 - clarified that the time recorded is the
+ first time processing since the create operation or the
+ Restart-Job operation.
+ 49. Section 4.3.14.2 and 4.3.14.3 - clarified that the out-of-band
+ value 'no-value' is returned if the job has not started
+ processing or has not completed, respectively.
+ 50. Section 4.3.14 - Added the OPTIONAL "date-time-at-creation",
+ "date-time-at-processing", and "date-time-at-completed" Event
+ Time Job Description attributes
+ 51. Section 4.4.3 - added the 'tls' value to "uri-security-
+ supported" attribute.
+ 52. Section 4.4.3 - clarified "uri-security-supported" is
+ orthogonal to Client Authentication so that 'none' does not
+ exclude Client Authentication.
+ 53. Section 4.4.11 - simplified the "printer-state" descriptions
+ while generalizing to allow high end devices that interpret
+ one or more jobs while marking another. Indicated that
+ 'spool-area-full' and 'stopped-partly' "printer-state-reasons"
+ may be used to provide further state information.
+ 54. Section 4.4.12 - added the 'moving-to-paused' keyword value to
+ the "printer-state-reasons" attribute for use with the Pause-
+ Printer operation.
+ 55. Section 4.4.12 - replaced the duplicate 'marker-supply-low'
+ keyword with the missing 'toner-empty' keyword for the
+ "printer-state-reasons" attribute. (This correction was also
+ made before RFC 2566 was published).
+ 56. Section 4.4.12 - clarified 'spool-area-full' "printer-state-
+ reasons" to include non-spooling printers to indicate when it
+ can and cannot accept another job.
+ 57. Section 4.4.15 - added the enum values to the "operations-
+ supported" attribute for the new operations. Clarified that
+ the values of this attribute are encoded as any enum, namely
+ 32-bit values.
+ 58. Section 4.4.30 - clarified that the dateTime value of
+ "printer-current-time" is on a "best efforts basis". If a
+ proper date-time cannot be obtained, the implementation
+ returns the 'no-value' out-of-band value. Also clarified that
+
+
+
+Hastings, et al. Standards Track [Page 219]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ the time zone NEED NOT be the time zone that the people near
+ the device use and that the client SHOULD display the dateTime
+ attributes in the user's local time.
+ 59. Sections 4.4.36 and 4.4.37 - added the OPTIONAL "pages-per-
+ minute" and "pages-per-minute-color" Printer Description
+ attributes.
+ 60. Section 5.1 - clarified that the client conformance
+ requirements apply to clients controlled by an end user and
+ clients in servers.
+ 61. Section 5.1 - clarified that any response MAY contain
+ additional attribute groups, attributes, attribute syntaxes,
+ or attribute values.
+ 62. Section 5.1 - clarified that a client SHOULD do its best to
+ prevent a channel from being closed by a lower layer when the
+ channel is flow controlled off by the IPP Printer.
+ 63. Section 5.2 - clarified that the IPP object requirements apply
+ to objects embedded in devices or that are parts of servers.
+ 64. Section 5.2.2 - clarified that IPP objects MAY return
+ operation responses that contain attribute groups, attribute
+ names, attribute syntaxes, attribute values, and status codes
+ that are extensions to this standard.
+ 65. Section 6 - changed the terminology of "private extensions" to
+ "vendor extensions" and indicated that they are registered
+ with IANA along with IETF standards track extensions.
+ 66. Section 6.7 - inserted this section on registering out-of-band
+ attribute values with IANA as extensions.
+ 67. Section 8.3 - clarified the use of URIs for each Client
+ Authentication mechanism.
+ 68. Section 8.5 - added the security discussion around the new
+ operator/administrator operations.
+ 69. Section 13.1.4.16 - added client-error-compression-not-
+ supported (0x040F)
+ 70. Section 13.1.4.17 - added client-error-compression-error
+ (0x0410)
+ 71. Section 13.1.4.18 - added client-error-document-format-error
+ (0x0411)
+ 72. Section 13.1.4.19 - added client-error-document-access-error
+ (0x0412)
+ 73. Section 13.1.5.10 - added server-error-multiple-document-
+ jobs-not-supported (0x0509)
+ 74. Section 14 - added 'a-white', 'b-white', 'c-white', 'd-white',
+ and 'e-white' and clarified that the existing 'a', 'b', 'c',
+ 'd', and 'e' values are size values. Added American,
+ Japanese, and European Engineering sizes, filled out
+ -transparent and - translucent media names and drawings for
+ the synchro cut sizes.
+
+
+
+
+
+Hastings, et al. Standards Track [Page 220]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 75. Section 16 - softened the RECOMMENDATION for IPP Printer
+ attributes in a Directory schema so that they can have
+ equivalents.
+ 76. Section 16 - added the OPTIONAL "pages-per-minute" and
+ "pages-per-minute-color" Printer attributes to the Directory
+ schema.
+ 77. Section 16 - added OPTIONAL "multiple-document-jobs-supported"
+ to the Directory schema.
+ 78. Section 16 - added RECOMMENDED "uri-authentication-supported",
+ "ipp-versions-supported", and "compression-supported" to the
+ Directory schema.
+
+ The following changes in semantics and/or conformance have been
+ incorporated into this document:
+
+ 1. Section 3.1.6.3 - allowed a Printer to localize the
+ "detailed-status-message" operation response attribute, but
+ indicated that such localization might obscure the technical
+ meaning of such messages.
+ 2. Section 3.1.8, 5.2.4, and 13.1.5.4 - Clients and IPP objects
+ MUST support version 1.1 conformance requirements. It is
+ recommended that they interoperate with 1.0. Also clarified
+ that IPP Printers MUST accept '1.1' requests. It is
+ recommended that they also accept '1.x' requests.
+
+ 3. Section 3.2.1.1 and section 4.4.32 - changed the "compression"
+ operation and the "compression-supported" Printer Description
+ attribute from OPTIONAL to REQUIRED.
+ 4. Sections 3.2.1.2 and 4.3.8 - changed "job-state-reasons" from
+ RECOMMENDED to REQUIRED, so that "job-state-reasons" MUST be
+ returned in create operation responses.
+ 5. Sections 3.2.4, 3.3.1, 4.4.16, and 16 - changed Create-
+ Job/Send-Document so that they MAY be implemented while only
+ supporting one document jobs. Added the "multiple-document-
+ jobs-supported" boolean Printer Description attribute to
+ indicate whether Create-Job/Send-Document support multiple
+ document jobs or not. Added to the Directory schema.
+ 6. Section 4.1.9 - deleted 'text/plain; charset=iso-10646-ucs-2',
+ since binary is not legal with the 'text' type.
+ 7. Section 4.1.9.1 - added the RECOMMENDATION that a Printer
+ indicate by printing on the job's job-start-sheet that auto-
+ sensing has occurred and what document format was auto-sensed.
+ 8. Section 4.2.4 - indicated that the "multiple-document-
+ handling" Job Template attribute MUST be supported with at
+ least one value if the Printer supports multiple documents per
+ job
+
+
+
+
+
+Hastings, et al. Standards Track [Page 221]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 9. Section 4.3.7.2 - indicated that the 'job-restartable' job
+ state reason SHOULD be supported if the Restart-Job operation
+ is supported.
+ 10. Section 4.3.8 - changed "job-state-reasons" from RECOMMENDED
+ to REQUIRED.
+ 11. Section 4.3.8 - clarified the conformance of the values of the
+ "job-state-reasons" attribute by copying conformance
+ requirements from other sections of the document so that it is
+ clear from reading the definition of "job-state-reasons" which
+ values MUST or SHOULD be supported. The 'none',
+ 'unsupported-compression', and 'unsupported-document-format'
+ values MUST be supported. The 'job-hold-until-specified'
+ SHOULD be specified if the "job-hold-until" Job Template is
+ supported. The following values SHOULD be supported: 'job-
+ canceled-by-user', 'aborted-by-system', and 'job-completed-
+ successfully'. The
+ 'job-canceled-by-operator' SHOULD be supported if the
+ implementation permits canceling by other than the job owner.
+ The 'job-canceled-at-device' SHOULD be supported if the device
+ supports canceling jobs at the console. The 'job-completed-
+ with-warnings' SHOULD be supported, if the implementation
+ detects warnings. The 'job-completed-with-errors' SHOULD be
+ supported if the implementation detects errors. The 'job-
+ restartable' SHOULD be supported if the Restart-Job operation
+ is supported.
+ 12. Section 4.3.10 - allowed a Printer to localize the "job-
+ detailed-status-message" Job Description attribute, but
+ indicated that such localization might obscure the technical
+ meaning of such messages.
+ 13. Section 4.3.14 - changed the "time-at-creation", "time-at-
+ processing", and "time-at-completed" Event Time Job
+ Description attributes from OPTIONAL to REQUIRED.
+ 14. Section 4.3.14.4 - added the REQUIRED "job-printer-up-time
+ (integer(1:MAX))" Job Description attribute as an alias for
+ "printer-up-time" to reduce number of operations to get job
+ times.
+ 15. Section 4.4.2 - added the REQUIRED "uri-authentication-
+ supported (1setOf type2 keyword)" Printer Description
+ attribute to describe the Client Authentication used by each
+ Printer URI.
+ 16. Section 4.4.12 - changed "printer-state-reasons" Printer
+ Description attribute from OPTIONAL to REQUIRED.
+ 17. Section 4.4.12 - changed 'paused' value of "printer-state-
+ reasons" to MUST if Pause-Printer operation is supported.
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 222]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+ 18. Section 4.4.14 - added the REQUIRED "ipp-versions-supported
+ (1setOf keyword)" Printer Description attribute, since IPP/1.1
+ Printers do not have to support version '1.0' conformance
+ requirements. Section 4.4.16 - added the "multiple-document-
+ jobs-supported (boolean)" Printer Description attribute so
+ that a client can tell whether a Printer that supports
+ Create-Job/Send-Document supports multiple document jobs or
+ not. This attribute is REQUIRED if the Create-Job operation
+ is supported.
+ 19. Section 4.4.24 - changed the "queued-job-count" Printer
+ Description attribute from RECOMMENDED to REQUIRED.
+ 20. Section 4.4.32 - changed "compression-supported (1setOf type3
+ keyword)" Printer Description attribute from OPTIONAL to
+ REQUIRED.
+ 21. Section 5.1 - changed the client security requirements from
+ RECOMMENDED non-standards track SSL3 to MUST support Client
+ Authentication as defined in the IPP/1.1 Encoding and
+ Transport document [RFC2910]. A client SHOULD support
+ Operation Privacy and Server Authentication as defined in the
+ IPP/1.1 Encoding and Transport document [RFC2910].
+ 22. Section 5.2.7 - changed the IPP object security requirements
+ from OPTIONAL non-standards track SSL3 to SHOULD contain
+ support for Client Authentication as defined in the IPP/1.1
+ Encoding and Transport document [RFC2910]. A Printer
+ implementation MAY allow an administrator to configure the
+ Printer so that all, some, or none of the users are
+ authenticated. An IPP Printer implementation SHOULD contain
+ support for Operation Privacy and Server Authentication as
+ defined in the IPP/1.1 Encoding and Transport document
+ [RFC2910]. A Printer implementation MAY allow an
+ administrator to configure the degree of support for Operation
+ Privacy and Server Authentication. Security MUST NOT be
+ compromised when the client supplies a lower version-number in
+ a request.
+ 23. Section 14 (Appendix C): Corrected typo, changing the keyword
+ 'iso-10-white' to 'iso-a10-white'.
+
+ See also the "IPP/1.1 Encoding and Transport" [RFC2910] document for
+ differences between IPP/1.0 [RFC2565] and IPP/1.1 [RFC2910].
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 223]
+
+RFC 2911 IPP/1.1: Model and Semantics September 2000
+
+
+18. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et al. Standards Track [Page 224]
+
diff --git a/standards/rfc2965.txt b/standards/rfc2965.txt
new file mode 100644
index 000000000..8a4d02b17
--- /dev/null
+++ b/standards/rfc2965.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group D. Kristol
+Request for Comments: 2965 Bell Laboratories, Lucent Technologies
+Obsoletes: 2109 L. Montulli
+Category: Standards Track Epinions.com, Inc.
+ October 2000
+
+
+ HTTP State Management Mechanism
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+IESG Note
+
+ The IESG notes that this mechanism makes use of the .local top-level
+ domain (TLD) internally when handling host names that don't contain
+ any dots, and that this mechanism might not work in the expected way
+ should an actual .local TLD ever be registered.
+
+Abstract
+
+ This document specifies a way to create a stateful session with
+ Hypertext Transfer Protocol (HTTP) requests and responses. It
+ describes three new headers, Cookie, Cookie2, and Set-Cookie2, which
+ carry state information between participating origin servers and user
+ agents. The method described here differs from Netscape's Cookie
+ proposal [Netscape], but it can interoperate with HTTP/1.0 user
+ agents that use Netscape's method. (See the HISTORICAL section.)
+
+ This document reflects implementation experience with RFC 2109 and
+ obsoletes it.
+
+1. TERMINOLOGY
+
+ The terms user agent, client, server, proxy, origin server, and
+ http_URL have the same meaning as in the HTTP/1.1 specification
+ [RFC2616]. The terms abs_path and absoluteURI have the same meaning
+ as in the URI Syntax specification [RFC2396].
+
+
+
+
+Kristol & Montulli Standards Track [Page 1]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Host name (HN) means either the host domain name (HDN) or the numeric
+ Internet Protocol (IP) address of a host. The fully qualified domain
+ name is preferred; use of numeric IP addresses is strongly
+ discouraged.
+
+ The terms request-host and request-URI refer to the values the client
+ would send to the server as, respectively, the host (but not port)
+ and abs_path portions of the absoluteURI (http_URL) of the HTTP
+ request line. Note that request-host is a HN.
+
+ The term effective host name is related to host name. If a host name
+ contains no dots, the effective host name is that name with the
+ string .local appended to it. Otherwise the effective host name is
+ the same as the host name. Note that all effective host names
+ contain at least one dot.
+
+ The term request-port refers to the port portion of the absoluteURI
+ (http_URL) of the HTTP request line. If the absoluteURI has no
+ explicit port, the request-port is the HTTP default, 80. The
+ request-port of a cookie is the request-port of the request in which
+ a Set-Cookie2 response header was returned to the user agent.
+
+ Host names can be specified either as an IP address or a HDN string.
+ Sometimes we compare one host name with another. (Such comparisons
+ SHALL be case-insensitive.) Host A's name domain-matches host B's if
+
+ * their host name strings string-compare equal; or
+
+ * A is a HDN string and has the form NB, where N is a non-empty
+ name string, B has the form .B', and B' is a HDN string. (So,
+ x.y.com domain-matches .Y.com but not Y.com.)
+
+ Note that domain-match is not a commutative operation: a.b.c.com
+ domain-matches .c.com, but not the reverse.
+
+ The reach R of a host name H is defined as follows:
+
+ * If
+
+ - H is the host domain name of a host; and,
+
+ - H has the form A.B; and
+
+ - A has no embedded (that is, interior) dots; and
+
+ - B has at least one embedded dot, or B is the string "local".
+ then the reach of H is .B.
+
+
+
+
+Kristol & Montulli Standards Track [Page 2]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ * Otherwise, the reach of H is H.
+
+ For two strings that represent paths, P1 and P2, P1 path-matches P2
+ if P2 is a prefix of P1 (including the case where P1 and P2 string-
+ compare equal). Thus, the string /tec/waldo path-matches /tec.
+
+ Because it was used in Netscape's original implementation of state
+ management, we will use the term cookie to refer to the state
+ information that passes between an origin server and user agent, and
+ that gets stored by the user agent.
+
+1.1 Requirements
+
+ The key words "MAY", "MUST", "MUST NOT", "OPTIONAL", "RECOMMENDED",
+ "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+2. STATE AND SESSIONS
+
+ This document describes a way to create stateful sessions with HTTP
+ requests and responses. Currently, HTTP servers respond to each
+ client request without relating that request to previous or
+ subsequent requests; the state management mechanism allows clients
+ and servers that wish to exchange state information to place HTTP
+ requests and responses within a larger context, which we term a
+ "session". This context might be used to create, for example, a
+ "shopping cart", in which user selections can be aggregated before
+ purchase, or a magazine browsing system, in which a user's previous
+ reading affects which offerings are presented.
+
+ Neither clients nor servers are required to support cookies. A
+ server MAY refuse to provide content to a client that does not return
+ the cookies it sends.
+
+3. DESCRIPTION
+
+ We describe here a way for an origin server to send state information
+ to the user agent, and for the user agent to return the state
+ information to the origin server. The goal is to have a minimal
+ impact on HTTP and user agents.
+
+3.1 Syntax: General
+
+ The two state management headers, Set-Cookie2 and Cookie, have common
+ syntactic properties involving attribute-value pairs. The following
+ grammar uses the notation, and tokens DIGIT (decimal digits), token
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 3]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ (informally, a sequence of non-special, non-white space characters),
+ and http_URL from the HTTP/1.1 specification [RFC2616] to describe
+ their syntax.
+
+ av-pairs = av-pair *(";" av-pair)
+ av-pair = attr ["=" value] ; optional value
+ attr = token
+ value = token | quoted-string
+
+ Attributes (names) (attr) are case-insensitive. White space is
+ permitted between tokens. Note that while the above syntax
+ description shows value as optional, most attrs require them.
+
+ NOTE: The syntax above allows whitespace between the attribute and
+ the = sign.
+
+3.2 Origin Server Role
+
+ 3.2.1 General The origin server initiates a session, if it so
+ desires. To do so, it returns an extra response header to the
+ client, Set-Cookie2. (The details follow later.)
+
+ A user agent returns a Cookie request header (see below) to the
+ origin server if it chooses to continue a session. The origin server
+ MAY ignore it or use it to determine the current state of the
+ session. It MAY send back to the client a Set-Cookie2 response
+ header with the same or different information, or it MAY send no
+ Set-Cookie2 header at all. The origin server effectively ends a
+ session by sending the client a Set-Cookie2 header with Max-Age=0.
+
+ Servers MAY return Set-Cookie2 response headers with any response.
+ User agents SHOULD send Cookie request headers, subject to other
+ rules detailed below, with every request.
+
+ An origin server MAY include multiple Set-Cookie2 headers in a
+ response. Note that an intervening gateway could fold multiple such
+ headers into a single header.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 4]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ 3.2.2 Set-Cookie2 Syntax The syntax for the Set-Cookie2 response
+ header is
+
+ set-cookie = "Set-Cookie2:" cookies
+ cookies = 1#cookie
+ cookie = NAME "=" VALUE *(";" set-cookie-av)
+ NAME = attr
+ VALUE = value
+ set-cookie-av = "Comment" "=" value
+ | "CommentURL" "=" <"> http_URL <">
+ | "Discard"
+ | "Domain" "=" value
+ | "Max-Age" "=" value
+ | "Path" "=" value
+ | "Port" [ "=" <"> portlist <"> ]
+ | "Secure"
+ | "Version" "=" 1*DIGIT
+ portlist = 1#portnum
+ portnum = 1*DIGIT
+
+ Informally, the Set-Cookie2 response header comprises the token Set-
+ Cookie2:, followed by a comma-separated list of one or more cookies.
+ Each cookie begins with a NAME=VALUE pair, followed by zero or more
+ semi-colon-separated attribute-value pairs. The syntax for
+ attribute-value pairs was shown earlier. The specific attributes and
+ the semantics of their values follows. The NAME=VALUE attribute-
+ value pair MUST come first in each cookie. The others, if present,
+ can occur in any order. If an attribute appears more than once in a
+ cookie, the client SHALL use only the value associated with the first
+ appearance of the attribute; a client MUST ignore values after the
+ first.
+
+ The NAME of a cookie MAY be the same as one of the attributes in this
+ specification. However, because the cookie's NAME must come first in
+ a Set-Cookie2 response header, the NAME and its VALUE cannot be
+ confused with an attribute-value pair.
+
+ NAME=VALUE
+ REQUIRED. The name of the state information ("cookie") is NAME,
+ and its value is VALUE. NAMEs that begin with $ are reserved and
+ MUST NOT be used by applications.
+
+ The VALUE is opaque to the user agent and may be anything the
+ origin server chooses to send, possibly in a server-selected
+ printable ASCII encoding. "Opaque" implies that the content is of
+ interest and relevance only to the origin server. The content
+ may, in fact, be readable by anyone that examines the Set-Cookie2
+ header.
+
+
+
+Kristol & Montulli Standards Track [Page 5]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Comment=value
+ OPTIONAL. Because cookies can be used to derive or store private
+ information about a user, the value of the Comment attribute
+ allows an origin server to document how it intends to use the
+ cookie. The user can inspect the information to decide whether to
+ initiate or continue a session with this cookie. Characters in
+ value MUST be in UTF-8 encoding. [RFC2279]
+
+ CommentURL="http_URL"
+ OPTIONAL. Because cookies can be used to derive or store private
+ information about a user, the CommentURL attribute allows an
+ origin server to document how it intends to use the cookie. The
+ user can inspect the information identified by the URL to decide
+ whether to initiate or continue a session with this cookie.
+
+ Discard
+ OPTIONAL. The Discard attribute instructs the user agent to
+ discard the cookie unconditionally when the user agent terminates.
+
+ Domain=value
+ OPTIONAL. The value of the Domain attribute specifies the domain
+ for which the cookie is valid. If an explicitly specified value
+ does not start with a dot, the user agent supplies a leading dot.
+
+ Max-Age=value
+ OPTIONAL. The value of the Max-Age attribute is delta-seconds,
+ the lifetime of the cookie in seconds, a decimal non-negative
+ integer. To handle cached cookies correctly, a client SHOULD
+ calculate the age of the cookie according to the age calculation
+ rules in the HTTP/1.1 specification [RFC2616]. When the age is
+ greater than delta-seconds seconds, the client SHOULD discard the
+ cookie. A value of zero means the cookie SHOULD be discarded
+ immediately.
+
+ Path=value
+ OPTIONAL. The value of the Path attribute specifies the subset of
+ URLs on the origin server to which this cookie applies.
+
+ Port[="portlist"]
+ OPTIONAL. The Port attribute restricts the port to which a cookie
+ may be returned in a Cookie request header. Note that the syntax
+ REQUIREs quotes around the OPTIONAL portlist even if there is only
+ one portnum in portlist.
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 6]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Secure
+ OPTIONAL. The Secure attribute (with no value) directs the user
+ agent to use only (unspecified) secure means to contact the origin
+ server whenever it sends back this cookie, to protect the
+ confidentially and authenticity of the information in the cookie.
+
+ The user agent (possibly with user interaction) MAY determine what
+ level of security it considers appropriate for "secure" cookies.
+ The Secure attribute should be considered security advice from the
+ server to the user agent, indicating that it is in the session's
+ interest to protect the cookie contents. When it sends a "secure"
+ cookie back to a server, the user agent SHOULD use no less than
+ the same level of security as was used when it received the cookie
+ from the server.
+
+ Version=value
+ REQUIRED. The value of the Version attribute, a decimal integer,
+ identifies the version of the state management specification to
+ which the cookie conforms. For this specification, Version=1
+ applies.
+
+ 3.2.3 Controlling Caching An origin server must be cognizant of the
+ effect of possible caching of both the returned resource and the
+ Set-Cookie2 header. Caching "public" documents is desirable. For
+ example, if the origin server wants to use a public document such as
+ a "front door" page as a sentinel to indicate the beginning of a
+ session for which a Set-Cookie2 response header must be generated,
+ the page SHOULD be stored in caches "pre-expired" so that the origin
+ server will see further requests. "Private documents", for example
+ those that contain information strictly private to a session, SHOULD
+ NOT be cached in shared caches.
+
+ If the cookie is intended for use by a single user, the Set-Cookie2
+ header SHOULD NOT be cached. A Set-Cookie2 header that is intended
+ to be shared by multiple users MAY be cached.
+
+ The origin server SHOULD send the following additional HTTP/1.1
+ response headers, depending on circumstances:
+
+ * To suppress caching of the Set-Cookie2 header:
+
+ Cache-control: no-cache="set-cookie2"
+
+ and one of the following:
+
+ * To suppress caching of a private document in shared caches:
+
+ Cache-control: private
+
+
+
+Kristol & Montulli Standards Track [Page 7]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ * To allow caching of a document and require that it be validated
+ before returning it to the client:
+
+ Cache-Control: must-revalidate, max-age=0
+
+ * To allow caching of a document, but to require that proxy
+ caches (not user agent caches) validate it before returning it
+ to the client:
+
+ Cache-Control: proxy-revalidate, max-age=0
+
+ * To allow caching of a document and request that it be validated
+ before returning it to the client (by "pre-expiring" it):
+
+ Cache-control: max-age=0
+
+ Not all caches will revalidate the document in every case.
+
+ HTTP/1.1 servers MUST send Expires: old-date (where old-date is a
+ date long in the past) on responses containing Set-Cookie2 response
+ headers unless they know for certain (by out of band means) that
+ there are no HTTP/1.0 proxies in the response chain. HTTP/1.1
+ servers MAY send other Cache-Control directives that permit caching
+ by HTTP/1.1 proxies in addition to the Expires: old-date directive;
+ the Cache-Control directive will override the Expires: old-date for
+ HTTP/1.1 proxies.
+
+3.3 User Agent Role
+
+ 3.3.1 Interpreting Set-Cookie2 The user agent keeps separate track
+ of state information that arrives via Set-Cookie2 response headers
+ from each origin server (as distinguished by name or IP address and
+ port). The user agent MUST ignore attribute-value pairs whose
+ attribute it does not recognize. The user agent applies these
+ defaults for optional attributes that are missing:
+
+ Discard The default behavior is dictated by the presence or absence
+ of a Max-Age attribute.
+
+ Domain Defaults to the effective request-host. (Note that because
+ there is no dot at the beginning of effective request-host,
+ the default Domain can only domain-match itself.)
+
+ Max-Age The default behavior is to discard the cookie when the user
+ agent exits.
+
+ Path Defaults to the path of the request URL that generated the
+ Set-Cookie2 response, up to and including the right-most /.
+
+
+
+Kristol & Montulli Standards Track [Page 8]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Port The default behavior is that a cookie MAY be returned to any
+ request-port.
+
+ Secure If absent, the user agent MAY send the cookie over an
+ insecure channel.
+
+ 3.3.2 Rejecting Cookies To prevent possible security or privacy
+ violations, a user agent rejects a cookie according to rules below.
+ The goal of the rules is to try to limit the set of servers for which
+ a cookie is valid, based on the values of the Path, Domain, and Port
+ attributes and the request-URI, request-host and request-port.
+
+ A user agent rejects (SHALL NOT store its information) if the Version
+ attribute is missing. Moreover, a user agent rejects (SHALL NOT
+ store its information) if any of the following is true of the
+ attributes explicitly present in the Set-Cookie2 response header:
+
+ * The value for the Path attribute is not a prefix of the
+ request-URI.
+
+ * The value for the Domain attribute contains no embedded dots,
+ and the value is not .local.
+
+ * The effective host name that derives from the request-host does
+ not domain-match the Domain attribute.
+
+ * The request-host is a HDN (not IP address) and has the form HD,
+ where D is the value of the Domain attribute, and H is a string
+ that contains one or more dots.
+
+ * The Port attribute has a "port-list", and the request-port was
+ not in the list.
+
+ Examples:
+
+ * A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
+ would be rejected, because H is y.x and contains a dot.
+
+ * A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
+ would be accepted.
+
+ * A Set-Cookie2 with Domain=.com or Domain=.com., will always be
+ rejected, because there is no embedded dot.
+
+ * A Set-Cookie2 with Domain=ajax.com will be accepted, and the
+ value for Domain will be taken to be .ajax.com, because a dot
+ gets prepended to the value.
+
+
+
+
+Kristol & Montulli Standards Track [Page 9]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ * A Set-Cookie2 with Port="80,8000" will be accepted if the
+ request was made to port 80 or 8000 and will be rejected
+ otherwise.
+
+ * A Set-Cookie2 from request-host example for Domain=.local will
+ be accepted, because the effective host name for the request-
+ host is example.local, and example.local domain-matches .local.
+
+ 3.3.3 Cookie Management If a user agent receives a Set-Cookie2
+ response header whose NAME is the same as that of a cookie it has
+ previously stored, the new cookie supersedes the old when: the old
+ and new Domain attribute values compare equal, using a case-
+ insensitive string-compare; and, the old and new Path attribute
+ values string-compare equal (case-sensitive). However, if the Set-
+ Cookie2 has a value for Max-Age of zero, the (old and new) cookie is
+ discarded. Otherwise a cookie persists (resources permitting) until
+ whichever happens first, then gets discarded: its Max-Age lifetime is
+ exceeded; or, if the Discard attribute is set, the user agent
+ terminates the session.
+
+ Because user agents have finite space in which to store cookies, they
+ MAY also discard older cookies to make space for newer ones, using,
+ for example, a least-recently-used algorithm, along with constraints
+ on the maximum number of cookies that each origin server may set.
+
+ If a Set-Cookie2 response header includes a Comment attribute, the
+ user agent SHOULD store that information in a human-readable form
+ with the cookie and SHOULD display the comment text as part of a
+ cookie inspection user interface.
+
+ If a Set-Cookie2 response header includes a CommentURL attribute, the
+ user agent SHOULD store that information in a human-readable form
+ with the cookie, or, preferably, SHOULD allow the user to follow the
+ http_URL link as part of a cookie inspection user interface.
+
+ The cookie inspection user interface may include a facility whereby a
+ user can decide, at the time the user agent receives the Set-Cookie2
+ response header, whether or not to accept the cookie. A potentially
+ confusing situation could arise if the following sequence occurs:
+
+ * the user agent receives a cookie that contains a CommentURL
+ attribute;
+
+ * the user agent's cookie inspection interface is configured so
+ that it presents a dialog to the user before the user agent
+ accepts the cookie;
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 10]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ * the dialog allows the user to follow the CommentURL link when
+ the user agent receives the cookie; and,
+
+ * when the user follows the CommentURL link, the origin server
+ (or another server, via other links in the returned content)
+ returns another cookie.
+
+ The user agent SHOULD NOT send any cookies in this context. The user
+ agent MAY discard any cookie it receives in this context that the
+ user has not, through some user agent mechanism, deemed acceptable.
+
+ User agents SHOULD allow the user to control cookie destruction, but
+ they MUST NOT extend the cookie's lifetime beyond that controlled by
+ the Discard and Max-Age attributes. An infrequently-used cookie may
+ function as a "preferences file" for network applications, and a user
+ may wish to keep it even if it is the least-recently-used cookie. One
+ possible implementation would be an interface that allows the
+ permanent storage of a cookie through a checkbox (or, conversely, its
+ immediate destruction).
+
+ Privacy considerations dictate that the user have considerable
+ control over cookie management. The PRIVACY section contains more
+ information.
+
+ 3.3.4 Sending Cookies to the Origin Server When it sends a request
+ to an origin server, the user agent includes a Cookie request header
+ if it has stored cookies that are applicable to the request, based on
+
+ * the request-host and request-port;
+
+ * the request-URI;
+
+ * the cookie's age.
+
+ The syntax for the header is:
+
+cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
+cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
+cookie-version = "$Version" "=" value
+NAME = attr
+VALUE = value
+path = "$Path" "=" value
+domain = "$Domain" "=" value
+port = "$Port" [ "=" <"> value <"> ]
+
+ The value of the cookie-version attribute MUST be the value from the
+ Version attribute of the corresponding Set-Cookie2 response header.
+ Otherwise the value for cookie-version is 0. The value for the path
+
+
+
+Kristol & Montulli Standards Track [Page 11]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ attribute MUST be the value from the Path attribute, if one was
+ present, of the corresponding Set-Cookie2 response header. Otherwise
+ the attribute SHOULD be omitted from the Cookie request header. The
+ value for the domain attribute MUST be the value from the Domain
+ attribute, if one was present, of the corresponding Set-Cookie2
+ response header. Otherwise the attribute SHOULD be omitted from the
+ Cookie request header.
+
+ The port attribute of the Cookie request header MUST mirror the Port
+ attribute, if one was present, in the corresponding Set-Cookie2
+ response header. That is, the port attribute MUST be present if the
+ Port attribute was present in the Set-Cookie2 header, and it MUST
+ have the same value, if any. Otherwise, if the Port attribute was
+ absent from the Set-Cookie2 header, the attribute likewise MUST be
+ omitted from the Cookie request header.
+
+ Note that there is neither a Comment nor a CommentURL attribute in
+ the Cookie request header corresponding to the ones in the Set-
+ Cookie2 response header. The user agent does not return the comment
+ information to the origin server.
+
+ The user agent applies the following rules to choose applicable
+ cookie-values to send in Cookie request headers from among all the
+ cookies it has received.
+
+ Domain Selection
+ The origin server's effective host name MUST domain-match the
+ Domain attribute of the cookie.
+
+ Port Selection
+ There are three possible behaviors, depending on the Port
+ attribute in the Set-Cookie2 response header:
+
+ 1. By default (no Port attribute), the cookie MAY be sent to any
+ port.
+
+ 2. If the attribute is present but has no value (e.g., Port), the
+ cookie MUST only be sent to the request-port it was received
+ from.
+
+ 3. If the attribute has a port-list, the cookie MUST only be
+ returned if the new request-port is one of those listed in
+ port-list.
+
+ Path Selection
+ The request-URI MUST path-match the Path attribute of the cookie.
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 12]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Max-Age Selection
+ Cookies that have expired should have been discarded and thus are
+ not forwarded to an origin server.
+
+ If multiple cookies satisfy the criteria above, they are ordered in
+ the Cookie header such that those with more specific Path attributes
+ precede those with less specific. Ordering with respect to other
+ attributes (e.g., Domain) is unspecified.
+
+ Note: For backward compatibility, the separator in the Cookie header
+ is semi-colon (;) everywhere. A server SHOULD also accept comma (,)
+ as the separator between cookie-values for future compatibility.
+
+ 3.3.5 Identifying What Version is Understood: Cookie2 The Cookie2
+ request header facilitates interoperation between clients and servers
+ that understand different versions of the cookie specification. When
+ the client sends one or more cookies to an origin server, if at least
+ one of those cookies contains a $Version attribute whose value is
+ different from the version that the client understands, then the
+ client MUST also send a Cookie2 request header, the syntax for which
+ is
+
+ cookie2 = "Cookie2:" cookie-version
+
+ Here the value for cookie-version is the highest version of cookie
+ specification (currently 1) that the client understands. The client
+ needs to send at most one such request header per request.
+
+ 3.3.6 Sending Cookies in Unverifiable Transactions Users MUST have
+ control over sessions in order to ensure privacy. (See PRIVACY
+ section below.) To simplify implementation and to prevent an
+ additional layer of complexity where adequate safeguards exist,
+ however, this document distinguishes between transactions that are
+ verifiable and those that are unverifiable. A transaction is
+ verifiable if the user, or a user-designated agent, has the option to
+ review the request-URI prior to its use in the transaction. A
+ transaction is unverifiable if the user does not have that option.
+ Unverifiable transactions typically arise when a user agent
+ automatically requests inlined or embedded entities or when it
+ resolves redirection (3xx) responses from an origin server.
+ Typically the origin transaction, the transaction that the user
+ initiates, is verifiable, and that transaction may directly or
+ indirectly induce the user agent to make unverifiable transactions.
+
+ An unverifiable transaction is to a third-party host if its request-
+ host U does not domain-match the reach R of the request-host O in the
+ origin transaction.
+
+
+
+
+Kristol & Montulli Standards Track [Page 13]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ When it makes an unverifiable transaction, a user agent MUST disable
+ all cookie processing (i.e., MUST NOT send cookies, and MUST NOT
+ accept any received cookies) if the transaction is to a third-party
+ host.
+
+ This restriction prevents a malicious service author from using
+ unverifiable transactions to induce a user agent to start or continue
+ a session with a server in a different domain. The starting or
+ continuation of such sessions could be contrary to the privacy
+ expectations of the user, and could also be a security problem.
+
+ User agents MAY offer configurable options that allow the user agent,
+ or any autonomous programs that the user agent executes, to ignore
+ the above rule, so long as these override options default to "off".
+
+ (N.B. Mechanisms may be proposed that will automate overriding the
+ third-party restrictions under controlled conditions.)
+
+ Many current user agents already provide a review option that would
+ render many links verifiable. For instance, some user agents display
+ the URL that would be referenced for a particular link when the mouse
+ pointer is placed over that link. The user can therefore determine
+ whether to visit that site before causing the browser to do so.
+ (Though not implemented on current user agents, a similar technique
+ could be used for a button used to submit a form -- the user agent
+ could display the action to be taken if the user were to select that
+ button.) However, even this would not make all links verifiable; for
+ example, links to automatically loaded images would not normally be
+ subject to "mouse pointer" verification.
+
+ Many user agents also provide the option for a user to view the HTML
+ source of a document, or to save the source to an external file where
+ it can be viewed by another application. While such an option does
+ provide a crude review mechanism, some users might not consider it
+ acceptable for this purpose.
+
+3.4 How an Origin Server Interprets the Cookie Header
+
+ A user agent returns much of the information in the Set-Cookie2
+ header to the origin server when the request-URI path-matches the
+ Path attribute of the cookie. When it receives a Cookie header, the
+ origin server SHOULD treat cookies with NAMEs whose prefix is $
+ specially, as an attribute for the cookie.
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 14]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+3.5 Caching Proxy Role
+
+ One reason for separating state information from both a URL and
+ document content is to facilitate the scaling that caching permits.
+ To support cookies, a caching proxy MUST obey these rules already in
+ the HTTP specification:
+
+ * Honor requests from the cache, if possible, based on cache
+ validity rules.
+
+ * Pass along a Cookie request header in any request that the
+ proxy must make of another server.
+
+ * Return the response to the client. Include any Set-Cookie2
+ response header.
+
+ * Cache the received response subject to the control of the usual
+ headers, such as Expires,
+
+ Cache-control: no-cache
+
+ and
+
+ Cache-control: private
+
+ * Cache the Set-Cookie2 subject to the control of the usual
+ header,
+
+ Cache-control: no-cache="set-cookie2"
+
+ (The Set-Cookie2 header should usually not be cached.)
+
+ Proxies MUST NOT introduce Set-Cookie2 (Cookie) headers of their own
+ in proxy responses (requests).
+
+4. EXAMPLES
+
+4.1 Example 1
+
+ Most detail of request and response headers has been omitted. Assume
+ the user agent has no stored cookies.
+
+ 1. User Agent -> Server
+
+ POST /acme/login HTTP/1.1
+ [form data]
+
+ User identifies self via a form.
+
+
+
+Kristol & Montulli Standards Track [Page 15]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ 2. Server -> User Agent
+
+ HTTP/1.1 200 OK
+ Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
+
+ Cookie reflects user's identity.
+
+ 3. User Agent -> Server
+
+ POST /acme/pickitem HTTP/1.1
+ Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
+ [form data]
+
+ User selects an item for "shopping basket".
+
+ 4. Server -> User Agent
+
+ HTTP/1.1 200 OK
+ Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
+ Path="/acme"
+
+ Shopping basket contains an item.
+
+ 5. User Agent -> Server
+
+ POST /acme/shipping HTTP/1.1
+ Cookie: $Version="1";
+ Customer="WILE_E_COYOTE"; $Path="/acme";
+ Part_Number="Rocket_Launcher_0001"; $Path="/acme"
+ [form data]
+
+ User selects shipping method from form.
+
+ 6. Server -> User Agent
+
+ HTTP/1.1 200 OK
+ Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"
+
+ New cookie reflects shipping method.
+
+ 7. User Agent -> Server
+
+ POST /acme/process HTTP/1.1
+ Cookie: $Version="1";
+ Customer="WILE_E_COYOTE"; $Path="/acme";
+ Part_Number="Rocket_Launcher_0001"; $Path="/acme";
+ Shipping="FedEx"; $Path="/acme"
+ [form data]
+
+
+
+Kristol & Montulli Standards Track [Page 16]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ User chooses to process order.
+
+ 8. Server -> User Agent
+
+ HTTP/1.1 200 OK
+
+ Transaction is complete.
+
+ The user agent makes a series of requests on the origin server, after
+ each of which it receives a new cookie. All the cookies have the
+ same Path attribute and (default) domain. Because the request-URIs
+ all path-match /acme, the Path attribute of each cookie, each request
+ contains all the cookies received so far.
+
+4.2 Example 2
+
+ This example illustrates the effect of the Path attribute. All
+ detail of request and response headers has been omitted. Assume the
+ user agent has no stored cookies.
+
+ Imagine the user agent has received, in response to earlier requests,
+ the response headers
+
+ Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
+ Path="/acme"
+
+ and
+
+ Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";
+ Path="/acme/ammo"
+
+ A subsequent request by the user agent to the (same) server for URLs
+ of the form /acme/ammo/... would include the following request
+ header:
+
+ Cookie: $Version="1";
+ Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
+ Part_Number="Rocket_Launcher_0001"; $Path="/acme"
+
+ Note that the NAME=VALUE pair for the cookie with the more specific
+ Path attribute, /acme/ammo, comes before the one with the less
+ specific Path attribute, /acme. Further note that the same cookie
+ name appears more than once.
+
+ A subsequent request by the user agent to the (same) server for a URL
+ of the form /acme/parts/ would include the following request header:
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 17]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001";
+ $Path="/acme"
+
+ Here, the second cookie's Path attribute /acme/ammo is not a prefix
+ of the request URL, /acme/parts/, so the cookie does not get
+ forwarded to the server.
+
+5. IMPLEMENTATION CONSIDERATIONS
+
+ Here we provide guidance on likely or desirable details for an origin
+ server that implements state management.
+
+5.1 Set-Cookie2 Content
+
+ An origin server's content should probably be divided into disjoint
+ application areas, some of which require the use of state
+ information. The application areas can be distinguished by their
+ request URLs. The Set-Cookie2 header can incorporate information
+ about the application areas by setting the Path attribute for each
+ one.
+
+ The session information can obviously be clear or encoded text that
+ describes state. However, if it grows too large, it can become
+ unwieldy. Therefore, an implementor might choose for the session
+ information to be a key to a server-side resource. Of course, using
+ a database creates some problems that this state management
+ specification was meant to avoid, namely:
+
+ 1. keeping real state on the server side;
+
+ 2. how and when to garbage-collect the database entry, in case the
+ user agent terminates the session by, for example, exiting.
+
+5.2 Stateless Pages
+
+ Caching benefits the scalability of WWW. Therefore it is important
+ to reduce the number of documents that have state embedded in them
+ inherently. For example, if a shopping-basket-style application
+ always displays a user's current basket contents on each page, those
+ pages cannot be cached, because each user's basket's contents would
+ be different. On the other hand, if each page contains just a link
+ that allows the user to "Look at My Shopping Basket", the page can be
+ cached.
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 18]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+5.3 Implementation Limits
+
+ Practical user agent implementations have limits on the number and
+ size of cookies that they can store. In general, user agents' cookie
+ support should have no fixed limits. They should strive to store as
+ many frequently-used cookies as possible. Furthermore, general-use
+ user agents SHOULD provide each of the following minimum capabilities
+ individually, although not necessarily simultaneously:
+
+ * at least 300 cookies
+
+ * at least 4096 bytes per cookie (as measured by the characters
+ that comprise the cookie non-terminal in the syntax description
+ of the Set-Cookie2 header, and as received in the Set-Cookie2
+ header)
+
+ * at least 20 cookies per unique host or domain name
+
+ User agents created for specific purposes or for limited-capacity
+ devices SHOULD provide at least 20 cookies of 4096 bytes, to ensure
+ that the user can interact with a session-based origin server.
+
+ The information in a Set-Cookie2 response header MUST be retained in
+ its entirety. If for some reason there is inadequate space to store
+ the cookie, it MUST be discarded, not truncated.
+
+ Applications should use as few and as small cookies as possible, and
+ they should cope gracefully with the loss of a cookie.
+
+ 5.3.1 Denial of Service Attacks User agents MAY choose to set an
+ upper bound on the number of cookies to be stored from a given host
+ or domain name or on the size of the cookie information. Otherwise a
+ malicious server could attempt to flood a user agent with many
+ cookies, or large cookies, on successive responses, which would force
+ out cookies the user agent had received from other servers. However,
+ the minima specified above SHOULD still be supported.
+
+6. PRIVACY
+
+ Informed consent should guide the design of systems that use cookies.
+ A user should be able to find out how a web site plans to use
+ information in a cookie and should be able to choose whether or not
+ those policies are acceptable. Both the user agent and the origin
+ server must assist informed consent.
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 19]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+6.1 User Agent Control
+
+ An origin server could create a Set-Cookie2 header to track the path
+ of a user through the server. Users may object to this behavior as
+ an intrusive accumulation of information, even if their identity is
+ not evident. (Identity might become evident, for example, if a user
+ subsequently fills out a form that contains identifying information.)
+ This state management specification therefore requires that a user
+ agent give the user control over such a possible intrusion, although
+ the interface through which the user is given this control is left
+ unspecified. However, the control mechanisms provided SHALL at least
+ allow the user
+
+ * to completely disable the sending and saving of cookies.
+
+ * to determine whether a stateful session is in progress.
+
+ * to control the saving of a cookie on the basis of the cookie's
+ Domain attribute.
+
+ Such control could be provided, for example, by mechanisms
+
+ * to notify the user when the user agent is about to send a
+ cookie to the origin server, to offer the option not to begin a
+ session.
+
+ * to display a visual indication that a stateful session is in
+ progress.
+
+ * to let the user decide which cookies, if any, should be saved
+ when the user concludes a window or user agent session.
+
+ * to let the user examine and delete the contents of a cookie at
+ any time.
+
+ A user agent usually begins execution with no remembered state
+ information. It SHOULD be possible to configure a user agent never
+ to send Cookie headers, in which case it can never sustain state with
+ an origin server. (The user agent would then behave like one that is
+ unaware of how to handle Set-Cookie2 response headers.)
+
+ When the user agent terminates execution, it SHOULD let the user
+ discard all state information. Alternatively, the user agent MAY ask
+ the user whether state information should be retained; the default
+ should be "no". If the user chooses to retain state information, it
+ would be restored the next time the user agent runs.
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 20]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ NOTE: User agents should probably be cautious about using files to
+ store cookies long-term. If a user runs more than one instance of
+ the user agent, the cookies could be commingled or otherwise
+ corrupted.
+
+6.2 Origin Server Role
+
+ An origin server SHOULD promote informed consent by adding CommentURL
+ or Comment information to the cookies it sends. CommentURL is
+ preferred because of the opportunity to provide richer information in
+ a multiplicity of languages.
+
+6.3 Clear Text
+
+ The information in the Set-Cookie2 and Cookie headers is unprotected.
+ As a consequence:
+
+ 1. Any sensitive information that is conveyed in them is exposed
+ to intruders.
+
+ 2. A malicious intermediary could alter the headers as they travel
+ in either direction, with unpredictable results.
+
+ These facts imply that information of a personal and/or financial
+ nature should only be sent over a secure channel. For less sensitive
+ information, or when the content of the header is a database key, an
+ origin server should be vigilant to prevent a bad Cookie value from
+ causing failures.
+
+ A user agent in a shared user environment poses a further risk.
+ Using a cookie inspection interface, User B could examine the
+ contents of cookies that were saved when User A used the machine.
+
+7. SECURITY CONSIDERATIONS
+
+7.1 Protocol Design
+
+ The restrictions on the value of the Domain attribute, and the rules
+ concerning unverifiable transactions, are meant to reduce the ways
+ that cookies can "leak" to the "wrong" site. The intent is to
+ restrict cookies to one host, or a closely related set of hosts.
+ Therefore a request-host is limited as to what values it can set for
+ Domain. We consider it acceptable for hosts host1.foo.com and
+ host2.foo.com to share cookies, but not a.com and b.com.
+
+ Similarly, a server can set a Path only for cookies that are related
+ to the request-URI.
+
+
+
+
+Kristol & Montulli Standards Track [Page 21]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+7.2 Cookie Spoofing
+
+ Proper application design can avoid spoofing attacks from related
+ domains. Consider:
+
+ 1. User agent makes request to victim.cracker.edu, gets back
+ cookie session_id="1234" and sets the default domain
+ victim.cracker.edu.
+
+ 2. User agent makes request to spoof.cracker.edu, gets back cookie
+ session-id="1111", with Domain=".cracker.edu".
+
+ 3. User agent makes request to victim.cracker.edu again, and
+ passes
+
+ Cookie: $Version="1"; session_id="1234",
+ $Version="1"; session_id="1111"; $Domain=".cracker.edu"
+
+ The server at victim.cracker.edu should detect that the second
+ cookie was not one it originated by noticing that the Domain
+ attribute is not for itself and ignore it.
+
+7.3 Unexpected Cookie Sharing
+
+ A user agent SHOULD make every attempt to prevent the sharing of
+ session information between hosts that are in different domains.
+ Embedded or inlined objects may cause particularly severe privacy
+ problems if they can be used to share cookies between disparate
+ hosts. For example, a malicious server could embed cookie
+ information for host a.com in a URI for a CGI on host b.com. User
+ agent implementors are strongly encouraged to prevent this sort of
+ exchange whenever possible.
+
+7.4 Cookies For Account Information
+
+ While it is common practice to use them this way, cookies are not
+ designed or intended to be used to hold authentication information,
+ such as account names and passwords. Unless such cookies are
+ exchanged over an encrypted path, the account information they
+ contain is highly vulnerable to perusal and theft.
+
+8. OTHER, SIMILAR, PROPOSALS
+
+ Apart from RFC 2109, three other proposals have been made to
+ accomplish similar goals. This specification began as an amalgam of
+ Kristol's State-Info proposal [DMK95] and Netscape's Cookie proposal
+ [Netscape].
+
+
+
+
+Kristol & Montulli Standards Track [Page 22]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ Brian Behlendorf proposed a Session-ID header that would be user-
+ agent-initiated and could be used by an origin server to track
+ "clicktrails". It would not carry any origin-server-defined state,
+ however. Phillip Hallam-Baker has proposed another client-defined
+ session ID mechanism for similar purposes.
+
+ While both session IDs and cookies can provide a way to sustain
+ stateful sessions, their intended purpose is different, and,
+ consequently, the privacy requirements for them are different. A
+ user initiates session IDs to allow servers to track progress through
+ them, or to distinguish multiple users on a shared machine. Cookies
+ are server-initiated, so the cookie mechanism described here gives
+ users control over something that would otherwise take place without
+ the users' awareness. Furthermore, cookies convey rich, server-
+ selected information, whereas session IDs comprise user-selected,
+ simple information.
+
+9. HISTORICAL
+
+9.1 Compatibility with Existing Implementations
+
+ Existing cookie implementations, based on the Netscape specification,
+ use the Set-Cookie (not Set-Cookie2) header. User agents that
+ receive in the same response both a Set-Cookie and Set-Cookie2
+ response header for the same cookie MUST discard the Set-Cookie
+ information and use only the Set-Cookie2 information. Furthermore, a
+ user agent MUST assume, if it received a Set-Cookie2 response header,
+ that the sending server complies with this document and will
+ understand Cookie request headers that also follow this
+ specification.
+
+ New cookies MUST replace both equivalent old- and new-style cookies.
+ That is, if a user agent that follows both this specification and
+ Netscape's original specification receives a Set-Cookie2 response
+ header, and the NAME and the Domain and Path attributes match (per
+ the Cookie Management section) a Netscape-style cookie, the
+ Netscape-style cookie MUST be discarded, and the user agent MUST
+ retain only the cookie adhering to this specification.
+
+ Older user agents that do not understand this specification, but that
+ do understand Netscape's original specification, will not recognize
+ the Set-Cookie2 response header and will receive and send cookies
+ according to the older specification.
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 23]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+ A user agent that supports both this specification and Netscape-style
+ cookies SHOULD send a Cookie request header that follows the older
+ Netscape specification if it received the cookie in a Set-Cookie
+ response header and not in a Set-Cookie2 response header. However,
+ it SHOULD send the following request header as well:
+
+ Cookie2: $Version="1"
+
+ The Cookie2 header advises the server that the user agent understands
+ new-style cookies. If the server understands new-style cookies, as
+ well, it SHOULD continue the stateful session by sending a Set-
+ Cookie2 response header, rather than Set-Cookie. A server that does
+ not understand new-style cookies will simply ignore the Cookie2
+ request header.
+
+9.2 Caching and HTTP/1.0
+
+ Some caches, such as those conforming to HTTP/1.0, will inevitably
+ cache the Set-Cookie2 and Set-Cookie headers, because there was no
+ mechanism to suppress caching of headers prior to HTTP/1.1. This
+ caching can lead to security problems. Documents transmitted by an
+ origin server along with Set-Cookie2 and Set-Cookie headers usually
+ either will be uncachable, or will be "pre-expired". As long as
+ caches obey instructions not to cache documents (following Expires:
+ <a date in the past> or Pragma: no-cache (HTTP/1.0), or Cache-
+ control: no-cache (HTTP/1.1)) uncachable documents present no
+ problem. However, pre-expired documents may be stored in caches.
+ They require validation (a conditional GET) on each new request, but
+ some cache operators loosen the rules for their caches, and sometimes
+ serve expired documents without first validating them. This
+ combination of factors can lead to cookies meant for one user later
+ being sent to another user. The Set-Cookie2 and Set-Cookie headers
+ are stored in the cache, and, although the document is stale
+ (expired), the cache returns the document in response to later
+ requests, including cached headers.
+
+10. ACKNOWLEDGEMENTS
+
+ This document really represents the collective efforts of the HTTP
+ Working Group of the IETF and, particularly, the following people, in
+ addition to the authors: Roy Fielding, Yaron Goland, Marc Hedlund,
+ Ted Hardie, Koen Holtman, Shel Kaphan, Rohit Khare, Foteos Macrides,
+ David W. Morris.
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 24]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+11. AUTHORS' ADDRESSES
+
+ David M. Kristol
+ Bell Laboratories, Lucent Technologies
+ 600 Mountain Ave. Room 2A-333
+ Murray Hill, NJ 07974
+
+ Phone: (908) 582-2250
+ Fax: (908) 582-1239
+ EMail: dmk@bell-labs.com
+
+
+ Lou Montulli
+ Epinions.com, Inc.
+ 2037 Landings Dr.
+ Mountain View, CA 94301
+
+ EMail: lou@montulli.org
+
+12. REFERENCES
+
+ [DMK95] Kristol, D.M., "Proposed HTTP State-Info Mechanism",
+ available at <http://portal.research.bell-
+ labs.com/~dmk/state-info.html>, September, 1995.
+
+ [Netscape] "Persistent Client State -- HTTP Cookies", available at
+ <http://www.netscape.com/newsref/std/cookie_spec.html>,
+ undated.
+
+ [RFC2109] Kristol, D. and L. Montulli, "HTTP State Management
+ Mechanism", RFC 2109, February 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2279] Yergeau, F., "UTF-8, a transformation format of Unicode
+ and ISO-10646", RFC 2279, January 1998.
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
+ Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1",
+ RFC 2616, June 1999.
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 25]
+
+RFC 2965 HTTP State Management Mechanism October 2000
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kristol & Montulli Standards Track [Page 26]
+
diff --git a/standards/rfc3380.txt b/standards/rfc3380.txt
new file mode 100644
index 000000000..6ea6c07ce
--- /dev/null
+++ b/standards/rfc3380.txt
@@ -0,0 +1,3307 @@
+
+
+
+
+
+
+Network Working Group T. Hastings
+Request for Comments: 3380 Xerox Corporation
+Updates: 2910, 2911 R. Herriot
+Category: Standards Track Consultant
+ C. Kugler
+ H. Lewis
+ IBM Corporation
+ September 2002
+
+
+ Internet Printing Protocol (IPP):
+ Job and Printer Set Operations
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document is an OPTIONAL extension to the Internet Printing
+ Protocol (IPP/1.0 and IPP/1.1). This document specifies 3 additional
+ OPTIONAL operations for use with the Internet Printing Protocol/1.0
+ (IPP) and IPP/1.1. The end user, operator, and administrator Set-
+ Job-Attributes and Set-Printer-Attributes operations are used to
+ modify IPP Job objects and Printer objects, respectively. The Get-
+ Printer-Supported-Values administrative operation returns values that
+ the IPP Printer will accept for setting its "xxx-supported"
+ attributes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 1]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+Table of Contents
+
+ 1 Introduction......................................................4
+ 2 Terminology.......................................................5
+ 2.1 Conformance Terminology.........................................5
+ 2.2 Other terminology...............................................5
+ 3 Requirements and Use Cases........................................5
+ 4 Definition of the Set operations..................................6
+ 4.1 Set-Printer-Attributes Operation................................7
+ 4.1.1 Settable and READ-ONLY Printer Description attributes.........9
+ 4.1.2 Set-Printer-Attributes Request...............................10
+ 4.1.3 Set-Printer-Attributes Response..............................12
+ 4.2 Set-Job-Attributes Operation...................................13
+ 4.2.1 Settable and READ-ONLY Job Description attributes............16
+ 4.2.2 Set-Job-Attributes Request...................................17
+ 4.2.3 Set-Job-Attributes Response..................................18
+ 4.3 Get-Printer-Supported-Values Operation.........................19
+ 4.3.1 Definition of the usage of the 'admin-define' out-of-band
+ attribute value..............................................20
+ 5 New Operation attributes.........................................22
+ 5.1 printer-message-from-operator (text(127))......................22
+ 5.2 job-message-from-operator (text(127))..........................23
+ 6 New Printer Description Attributes...............................24
+ 6.1 printer-settable-attributes-supported (1setOf type2 keyword)...24
+ 6.2 job-settable-attributes-supported (1setOf type2 keyword).......25
+ 6.3 document-format-varying-attributes (1setOf type2 keyword)......25
+ 6.4 printer-message-time (integer(MIN:MAX))........................25
+ 6.5 printer-message-date-time (dateTime)...........................26
+ 6.6 printer-xri-supported (1setOf collection)......................26
+ 6.7 xri-uri-scheme-supported (1setOf uriScheme)....................28
+ 6.8 xri-authentication-supported (1setOf type2 keyword)............29
+ 6.9 xri-security-supported (1setOf type2 keyword)..................29
+ 7 Additional status codes..........................................29
+ 7.1 client-error-attributes-not-settable (0x0413)..................29
+ 8 Additional out-of-band values....................................30
+ 8.1 'not-settable' out-of-band value...............................30
+ 8.1.1 Encoding of the 'not-settable' out-of-band attribute value...30
+ 8.2 'delete-attribute' out-of-band value...........................30
+ 8.2.1 Encoding of the 'delete-attribute' out-of-band value.........31
+ 8.3 'admin-define' out-of-band attribute value.....................31
+ 8.3.1 Encoding of the 'admin-define' out-of-band attribute value...32
+ 9 New Values for Existing Printer Description Attributes...........33
+ 9.1 operations-supported (1setOf type2 enum).......................33
+ 10 Conformance Requirements........................................33
+ 11 IANA Considerations.............................................34
+ 11.1 Operation Registrations.......................................35
+ 11.2 Additional Enum Attribute Value Registrations for the
+ "operations-supported" Printer Attribute......................35
+
+
+
+Hastings, et. al. Standards Track [Page 2]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ 11.3 Attribute Registrations.......................................35
+ 11.4 Status code Registrations.....................................36
+ 11.5 Out-of-band Attribute Value Registrations.....................36
+ 12 Internationalization Considerations.............................37
+ 13 Security Considerations.........................................37
+ 14 References......................................................38
+ 14.1 Normative References..........................................38
+ 14.2 Informative References........................................38
+ Appendix A: Allowed Values for Set-Printer-Attributes and Set-Job-
+ Attributes requests (Normative)........................39
+ Appendix B: Attributes returned from Get-Printer-Supported-Values
+ (Normative)............................................50
+ Appendix C: Description of the Base IPP Documents (Informative)....55
+ Authors' Addresses.................................................56
+ Full Copyright Statement...........................................58
+
+Table of Tables
+
+ Table 1 - Operation-Id assignments.................................7
+ Table 2 - Job State Transition Table for the Set-Job-Attributes
+ operation ..............................................15
+ Table 3 - Member attributes of "printer-xri-supported" (1setOf
+ collection) ............................................27
+ Table 4 - Operation-id assignments................................33
+ Table 5 - Validation rules for 'Any of "xxx-supported" '..........40
+ Table 6 - Validation rules for 'From Get-Printer-Supported-Values'41
+ Table 7 - Values allowed for Job Template Attributes in the Set-Job-
+ Attributes Operation ...................................42
+ Table 8 - Values allowed for Job Description Attributes in the Set-
+ Job-Attributes Operation ...............................43
+ Table 9 - Values allowed for Printer Job Template Attributes in the
+ Set-Printer-Attributes Operation .......................44
+ Table 10 - Values allowed for Printer Description Attributes in the
+ Set-Printer-Attributes Operation .......................47
+ Table 11 - Printer Job Template Attributes returned from Get-Printer-
+ Supported-Values .......................................51
+ Table 12 - Printer Job Template Attributes returned from Get-Printer-
+ Supported-Values .......................................51
+ Table 13 - Printer Description Attributes returned from Get-Printer-
+ Supported-Values .......................................51
+ Table 14 - Printer Job Template Attributes returned from Get-Printer-
+ Supported-Values .......................................52
+ Table 15 - Printer Job Template Attributes returned from Get-Printer-
+ Supported-Values .......................................52
+ Table 16 - Printer Description Attributes returned from Get-Printer-
+ Supported-Values .......................................53
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 3]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+1 Introduction
+
+ This document is an OPTIONAL extension to IPP/1.0 [RFC2565, RFC2566]
+ and IPP/1.1 [RFC2911, RFC2910]. For a description of the base IPP
+ documents see Appendix C.
+
+ The Internet Printing Protocol (IPP) is an application level protocol
+ that can be used for distributed printing using Internet tools and
+ technologies. IPP version 1.1 [RFC2911, RFC2910] focuses on end user
+ functionality with a few administrative operations included. This
+ document defines additional OPTIONAL end user, operator, and
+ administrator Set-Job-Attributes and Set-Printer-Attributes
+ operations used to modify IPP Job objects and Printer objects,
+ respectively. It also defines a third Get-Printer-Supported-Values
+ administrator operation that returns values that the IPP Printer will
+ accept for setting its "xxx-supported" attributes. The Get-Printer-
+ Supported-Values operation MUST be supported, if the implementation
+ supports setting any "xxx-supported" Printer attributes using the
+ Set-Printer-Attributes operation.
+
+ Nine Printer Description attributes are defined:
+
+ printer-settable-attributes-supported (1setOf type2 keyword)
+ job-settable-attributes-supported (1setOf type2 keyword)
+ document-format-varying-attributes (1setOf type2 keyword)
+ printer-message-time (integer(MIN:MAX))
+ printer-message-date-time (dateTime)
+ printer-xri-supported (1setOf collection)
+ xri-uri-scheme-supported (1setOf uriScheme)
+ xri-authentication-supported (1setOf type2 keyword)
+ xri-security-supported (1setOf type2 keyword)
+
+ Three out-of-band values are defined for use with these three
+ operations: 'delete-attribute' for deleting Job attributes with the
+ Set-Job-Attributes request, 'not-settable' for use in either the
+ Set-Job-Attributes or Set-Printer-Attributes responses, and 'admin-
+ define' for use in the Get-Printer-Supported-Values response.
+
+ Two operation attributes: "printer-message-from-operator" (text) and
+ "job-message-from-operator" (text) are defined to set the
+ corresponding IPP/1.1 Printer and Job Description attributes with the
+ same names. These operation attributes may be used with any
+ operation that affect the Printer or Job object for which an
+ operation might want to indicate a message. For the Set-Job-
+ Attributes and Set-Printer-Attributes operations, the client MUST
+ explicitly set them, rather than using these operation attributes.
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 4]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ A Printer implementation can make the value of some attributes
+ dependent on the document-format, e.g., "resolution-supported".
+
+2 Terminology
+
+ This section defines terminology used throughout this document.
+
+2.1 Conformance Terminology
+
+ Capitalized terms, such as MUST, MUST NOT, REQUIRED, SHOULD, SHOULD
+ NOT, MAY, NEED NOT, and OPTIONAL, have special meaning relating to
+ conformance as defined in BCP 14, RFC 2119 [RFC2119] and [RFC2911]
+ section 12.1. If an implementation supports the extension defined in
+ this document, then these terms apply; otherwise, they do not. These
+ terms define conformance to this document only; they do not affect
+ conformance to other documents, unless explicitly stated otherwise.
+
+2.2 Other terminology
+
+ This document uses terms such as Job object (or Job), IPP Printer
+ object (or Printer), "operation", "request", response", "attributes",
+ "keywords", and "support". These terms have special meaning and are
+ defined in the model terminology [RFC2911], section 12.2. The
+ following additional terms are introduced in this document:
+
+ READ-ONLY: used in an attribute definition document to indicate that
+ the attribute MUST NOT be settable using an IPP protocol Set
+ operation. In other words, the attribute is not settable by
+ definition.
+
+ not-settable: an implementation does not support setting an attribute
+ (whether or not the attribute's definition is READ-ONLY).
+
+3 Requirements and Use Cases
+
+ The following requirements and usage are intended to be met by the
+ specification in this document.
+
+ 1. The end-user and the operator need a way to modify a Job that is
+ in the 'pending' or 'pending-held' state.
+
+ Usage: The end-user discovers that he/she forgot to include a
+ print instruction, such as "finishings" = 'staple' after
+ submitting a job. Rather than canceling the job and resubmitting
+ it to the same IPP Printer, the end-user is able to modify the job
+ on the IPP Printer.
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 5]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ The operator needs to modify a job because it is requesting a
+ particular kind of media for which there is no more, but the
+ policy is to print the job on a comparable medium.
+
+ 2. The system administrator needs a way to re-configure or change the
+ policy of the IPP Printer remotely.
+
+ Usage: The system administrator is adding additional named media
+ to the supported media list (setting 'name' values to the "media-
+ supported" Printer attribute).
+
+ The system administrator is reducing the capability of the IPP
+ Printer by removing one of the operations from the supported
+ operations list, such as Cancel-Job, because the policy is to run
+ the IPP Printer like a public facsimile machine. After having
+ removed Cancel-Job from the list of supported operations, an
+ administrative client needs to be able to display to an
+ administrator that the implementation is capable of being
+ reconfigured to support Cancel-Job once again.
+
+ The system administrator is remotely configuring the IPP Printer
+ after installing it, and so is replacing the Printer Description
+ attributes that have the out-of-band 'no-value' value (see
+ [RFC2911], section 4.1) with the proper values.
+
+ The operator is changing the media loaded in the input tray, and
+ so is replacing the "media-ready" Job Template Printer attribute
+ value with the proper values.
+
+4 Definition of the Set operations
+
+ The Set-Printer-Attributes operations (as are all Printer operations)
+ are directed at Printer objects. A client MUST always supply the
+ "printer-uri" operation attribute in order to identify the correct
+ target of the operation. These descriptions assume all of the common
+ semantics of the IPP/1.1 Model and Semantics document [RFC2911],
+ section 3.1.
+
+ The Set-Job-Attributes operations (as are all Job operations) are
+ directed at Job objects. A client MUST always supply some means of
+ identifying the Job object in order to identify the correct target of
+ the operation. That job identification MAY either be a single Job
+ URI or a combination of a Printer URI with a Job ID, as defined in
+ [RFC2911]. The IPP object implementation MUST support both forms of
+ identification for every job. If possible, a client SHOULD use the
+ Printer URI with a Job ID rather than a Job URI, since the 32-bit
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 6]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ "job-id" is more readily translated to and from other print protocols
+ that MAY be serving as gateways into or out of the IPP
+ implementation.
+
+ The Set Printer operations are summarized in Table 1:
+
+ Table 1 - Operation-Id assignments
+
+ Operation Name Operation Brief description
+ -Id
+
+ Set-Printer- 0x0013 Sets attribute values of the target
+ Attributes Printer object
+
+ Set-Job-Attributes 0x0014 Sets attribute values of the target
+ Job object
+
+ Get-Printer- 0x0015 Gets values that are valid for
+ Supported-Values setting "xxx-supported" attributes
+ using the Set-Printer-Attributes
+ operation
+
+4.1 Set-Printer-Attributes Operation
+
+ This OPTIONAL operation allows a client to set the values of the
+ attributes of a Printer object. In the request, the client supplies
+ the set of Printer keyword attribute names and values that are to be
+ set. In the response, the Printer object returns success or rejects
+ the entire request with indications of which attribute or attributes
+ could not be set.
+
+ The Printer object validates the client-supplied attributes in the
+ Set-Printer-Attributes request. For an attribute to validate, it
+ MUST meet all of the following rules:
+
+ 1. The number of attributes supplied by the client MUST NOT exceed
+ the maximum number that the Printer supports in a Set-Printer-
+ Attributes request. A Printer MUST accept at least one attribute,
+ but SHOULD accept a reasonable number in a single Set-Printer-
+ Attributes request.
+
+ Note: There is no way for the client to determine the maximum
+ number of attributes that the Printer supports in a Set-Printer-
+ Attributes request, except to try a reasonable number.
+
+ 2. The Printer MUST support the attribute.
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 7]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ 3. The attribute MUST NOT be READ-ONLY, i.e., the definition of the
+ attribute MUST NOT indicate that the attribute is READ-ONLY (see
+ Appendix A for an indication of which IPP/1.1 attributes are
+ READ-ONLY).
+
+ 4. The attribute MUST be settable in this implementation.
+
+ 5. The Printer MUST support the value, according to the rules defined
+ in Appendix A, i.e., each value of each supplied "xxx" attribute
+ MUST be validated against the value of a corresponding "xxx-
+ supported" Printer attribute. One of those rules permits an
+ administrator to set arbitrary 'name' values to those "xxx-
+ supported" Printer attributes that include the 'name' attribute
+ syntax if the implementation supports the 'admin-define' out-of-
+ band value for that "xxx-supported" attribute (see section 8.3 and
+ Appendix A).
+
+ 6. The attribute's values MUST NOT conflict with the values of other
+ Printer attributes, including ones being set in this same
+ operation.
+
+ If any of the supplied attributes are not validate, the Printer
+ object MUST reject the entire operation; the Printer object MUST NOT
+ partially set some of the supplied attributes. In other words, after
+ the operation, all the supplied attributes MUST be set or none of
+ them MUST be set, thus making the Set-Printer-Attributes an atomic
+ operation.
+
+ The Printer MUST accept this operation when its READ-ONLY "printer-
+ state" attribute (see [RFC2911], section 4.4.11) is 'idle' or
+ 'stopped', and SHOULD accept it when the value is 'processing'. The
+ Printer MUST accept this operation for any of the values of the
+ Printer object's READ-ONLY "printer-state-reasons" and "printer-is-
+ accepting-jobs" attributes, unless explicitly defined otherwise in
+ the definition of these attributes' values.
+
+ This operation MUST NOT change the value of attributes not specified
+ in the operation unless the definition of the attribute explicitly
+ specifies such side-effects. For example, this document explicitly
+ specifies that when this operation sets "printer-message-from-
+ operator", the Printer also MUST set the READ-ONLY "printer-message-
+ time" and READ-ONLY "printer-message-date-time" attributes to the
+ time of the operation as a side effect. In particular, if this
+ operation changes an "xxx-default" attribute, the new value MUST be
+ in the "xxx-supported" attributes or the request MUST contain a new
+ value for "xxx-supported", which contains the new value for the
+ "xxx-default". Otherwise, the Printer MUST reject the operation. In
+ general, Printer attribute definitions that are settable will not
+
+
+
+Hastings, et. al. Standards Track [Page 8]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ define side-effects on other attributes that are settable, only side
+ effects on READ-ONLY attributes, if any.
+
+4.1.1 Settable and READ-ONLY Printer Description attributes
+
+ If the Printer supports the Set-Printer-Attributes operation, then it
+ SHOULD support the setting of:
+
+ all Job Template Default ("xxx-default") attributes
+ all Job Template Supported ("xxx-supported") attributes
+ all Job Template Ready ("xxx-ready") attributes
+
+ that the implementation supports (see [RFC2911] section 4.2 and
+ extensions).
+
+ Some Printer Description attributes (see [RFC2911] section 4.4) MUST
+ NOT be settable, i.e., they are defined to be READ-ONLY. An
+ attribute marked as "READ-ONLY" in the Printer Description attribute
+ table in Appendix A is such an attribute. The Printer attributes
+ that are not marked as "READ-ONLY" MAY be settable using the Set-
+ Printer-Attributes operation, depending on implementation.
+
+ Note: From now on, all extensions that define new object attributes
+ will indicate whether or not the attributes are READ-ONLY, by
+ including the "READ-ONLY" adjective in their descriptions and/or
+ explicitly stating whether they MAY be settable.
+
+ The current values of each "xxx-supported" Printer attribute MUST
+ reflect the current policy for support of the corresponding "xxx"
+ attribute. If an "xxx-supported" Printer attribute is settable in an
+ implementation, then its value(s) MUST affect the behavior of the
+ implementation. If an "xxx-supported" Printer attribute is defined
+ to be READ-ONLY or is not-settable in an implementation, then its
+ values MUST NOT be settable using the Set-Printer-Attributes
+ operation. Consider the following examples:
+
+ For example, if the "operations-supported" Printer Description
+ attribute (see [RFC2911] section 4.4.15) is settable in a
+ particular implementation, then changing its value with a Set-
+ Printer-Attributes operation MUST affect the operations that the
+ implementation accepts or rejects. Such an implementation will
+ need to be able to reject values for operations that it contains
+ no code support for (see section 4.3). If the "operations-
+ supported" Printer Description attribute is not settable in a
+ particular implementation, then that implementation MUST reject an
+ attempt to set it with a Set-Printer-Attributes operation, return
+ the 'client-error-attributes-not-settable' status code (see
+ section 7.1), and return the "operations-supported" attribute,
+
+
+
+Hastings, et. al. Standards Track [Page 9]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ with the out-of-band 'not-settable' value in the Unsupported
+ Attributes Group.
+
+ As another example, consider an implementation in which the
+ "media-default" and "media-supported" are settable. If a client
+ supplies a Set-Printer-Attributes request that contains the
+ "media-default" attribute with a value that is not a member of the
+ Printer's "media-supported" attribute, the Printer MUST reject the
+ request and return the "client-error-conflicting-attributes"
+ status code with the "media-default" and "media-supported"
+ attributes and their values (see [RFC2911] section 3.1.7).
+
+ As a third example, if a client supplies a Set-Printer-Attributes
+ request that contains both the "media-default" and the "media-
+ supported" attributes, but includes a value in the "media-default"
+ that is not a member of the supplied "media-supported" attribute,
+ the Printer MUST reject the request and return the "client-error-
+ conflicting-attributes" status code with the "media-default" and
+ "media-supported" attributes and their values (see [RFC2911]
+ section 3.1.7).
+
+ Access Rights: The authenticated user (see [RFC2911] section 8.3)
+ performing this operation must be an operator or administrator of the
+ Printer object (see [RFC2911] Sections 1 and 8.5). Most Printer
+ attributes will require administrator access rights to set, such as
+ "xxx-supported", while some will require operator access rights only,
+ such as "media-ready" and "printer-message-from-operator". Which
+ attributes require which access rights depends on implementation, and
+ MAY depend on site policy.
+
+4.1.2 Set-Printer-Attributes Request
+
+ The following sets of attributes are part of the Set-Printer-
+ Attributes Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes, as described in [RFC2911], section 3.1.4.1.
+
+ Target:
+ The "printer-uri" (uri) operation attribute, which is the
+ target for this operation, as described in [RFC2911], section
+ 3.1.5.
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 10]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client, as described in [RFC2911], section 8.3.
+
+ "document-format" (mimeMediaType):
+ The client OPTIONALLY supplies this attribute. The Printer
+ object MUST support this attribute. This attribute is useful
+ for a client to select the document-format to which the
+ attribute modification should be applied. A Printer
+ implementation MAY allow some attributes to have different
+ values for each document format that it supports. See
+ [RFC2911], section 3.2.5.1 "Get-Printer-Attributes Request".
+
+ If the client includes this attribute, the Printer MUST change
+ the supplied attributes for the document format specified by
+ this attribute. If a supplied attribute is a member of the
+ "document-format-varying-attributes" (i.e., the attribute
+ varies by document format, see section 6.3), the Printer MUST
+ change the supplied attribute for the document format specified
+ by this attribute, but not for other document formats. If a
+ supplied attribute isn't a member of the "document-format-
+ varying-attributes" (i.e., it doesn't vary by document format),
+ the Printer MUST change the supplied attribute for all document
+ formats.
+
+ If the client omits this attribute, the Printer MUST change the
+ supplied attributes for all document formats, whether or not
+ they vary by document-format.
+
+ If the client supplies a value for the "document-format"
+ Operation attribute, that is either 'application/octet-stream'
+ or not supported by the Printer, i.e., is not among the values
+ of the Printer object's "document-format-supported" attribute,
+ the Printer object MUST reject the operation and return the
+ 'client-error-document-format-not-supported' status code.
+ Note: the document-format 'application/octet-stream' is the
+ union of several document-formats (see [RFC2911] section
+ 3.2.5.1, Get-Printer-Attributes) and is not a true document-
+ format.
+
+ Group 2: Printer Attributes
+
+ The client MUST supply a set of Printer attributes with one or
+ more values (including explicitly allowed out-of-band values) as
+ defined in [RFC2911] section 4.2 Job Template Attributes ("xxx-
+ default", "xxx-supported", and "xxx-ready" attributes), section
+ 4.4 Printer Description Attributes, and any attribute extensions
+ supported by the Printer. The value(s) of each Printer attribute
+
+
+
+Hastings, et. al. Standards Track [Page 11]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ supplied in Group 2 replaces the value(s) of the corresponding
+ Printer attribute on the target Printer object. For attributes
+ that can have multiple values (1setOf), all values supplied by the
+ client replace all values of the corresponding Printer object
+ attribute. If a Printer object attribute had not yet been
+ configured, and so assumed the 'no-value' out-of-band value (see
+ [RFC2911] section 4.1), the supplied value(s) replaces the 'no-
+ value' value.
+
+4.1.3 Set-Printer-Attributes Response
+
+ The Printer object returns the following sets of attributes as part
+ of the Get-Printer-Attributes Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute, as described in [RFC2911] sections 3.1.6
+ and 13.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes, as described in [RFC2911], section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See [RFC2911], section 3.1.7, for details on returning Unsupported
+ Attributes.
+
+ If some of the attributes in the operation fail to validate, the
+ Printer MUST reject the operation, MUST NOT change any Printer
+ attributes, and MUST return the indicated status code below. In
+ this group, the Printer MUST also return all attributes that fail
+ to validate. The following are the reasons that an attribute
+ fails to validate and the value returns for the attribute, along
+ with the indicated status code and order of detection:
+
+ 1. The number of attributes supplied by the client exceeds the
+ maximum number that the Printer supports in a Set-Printer-
+ Attributes request: return the 'client-error-request-entity-
+ too-large' (see [RFC2911], section 13.1.4.9).
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 12]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ 2. The Printer doesn't support the attribute: return the attribute
+ with the "out-of-band" value 'unsupported' (see [RFC2911]
+ section 3.1.7 and [RFC2910]) and the 'client-error-attributes-
+ or-values-not-supported (see [RFC2911], section 13.1.4.12).
+
+ 3. The attribute is either READ-ONLY (in its definition) or is
+ not-settable in this implementation: return the attribute with
+ the "out-of-band" value 'not-settable' (see section 8.1) and
+ the 'client-error-attributes-not-settable' status code (see
+ section 7.1).
+
+ 4. The Printer doesn't support the value: if the attribute in the
+ operation has a single value, return it. If the attribute in
+ the operation is multi-valued, return only those values in a
+ 1setOf that are not supported. Return the 'client-error-
+ attributes-or-values-not-supported' status code (see [RFC2911],
+ section 13.1.4.12).
+
+ 5. The values of some of the supplied attributes conflict with one
+ another and/or other Printer attribute values not being set: if
+ the conflicting attribute in the operation has a single value,
+ return the attribute and the value. If the attribute in the
+ operation is multi-valued, return only the attribute and those
+ values in a 1setOf that are conflicting with other attributes.
+ Return the 'client-error-conflicting-attributes' status code
+ (see [RFC2911], section 13.1.4.15).
+
+4.2 Set-Job-Attributes Operation
+
+ This OPTIONAL operation allows a client to set the values of the
+ attributes of a Job object. In the request, the client supplies the
+ set of Job keyword attribute names and values that are to be set. In
+ the response, the IPP object returns success or rejects the entire
+ request with indications of which attribute or attributes could not
+ be set.
+
+ This operation is almost identical to the Set-Printer-Attributes
+ operation and follows the same rules for validation (see section
+ 4.1). The only differences are that the Set-Job-Attributes operation
+ is directed at a Job object rather than a Printer object, there is no
+ "document-format" operation attribute used when setting a Job object,
+ the operation can add an attribute to the (Job) object, the 'delete-
+ attributes' out-of-band value is permitted to remove an attribute,
+ and the validation is the same as the Job Creation operations
+ (Print-Job, Print-URI, and Create-Job), i.e., depends on the "xxx-
+ supported" Printer Description attributes (see [RFC2911] section
+ 3.1). Using the Set-Printer-Attributes operation, the administrator
+ can set arbitrary 'name' values to those "xxx-supported" Printer
+
+
+
+Hastings, et. al. Standards Track [Page 13]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ attributes, that include the 'name' attribute syntax, if the
+ implementation supports the 'admin-define' out-of-band value for that
+ "xxx-supported" attribute (see section 8.3 and Appendix A). However,
+ the Set-Job-Attributes cannot be used to add unsupported names to the
+ Job object.
+
+ If a client supplies a job attribute in a Set-Job-Attributes request
+ that the Printer supports, and the job was originally submitted
+ without supplying that attribute, the Printer adds the attribute to
+ the Job object.
+
+ If the client supplies a job attribute with the "out-of-band" value
+ 'delete-attribute' (see section 8.2), then the Printer MUST remove
+ the attribute and all of its values from the Job object, if present.
+ The semantic effect of the client supplying the 'delete-attribute'
+ value in a Set-Job-Attributes operation MUST be the same as if the
+ attribute had not been supplied with the Job object in the Job
+ Creation operation, i.e., the Printer applies its default attribute
+ or behavior with lower precedence that the PDL (see the beginning of
+ [RFC2911] section 4.2 and [RFC2911] 3.2.1.1). Any subsequent query
+ of the Job object using Get-Job-Attributes or Get-Jobs, MUST NOT
+ return any attribute that has been deleted using the 'delete-
+ attribute' out-of-band value. However, a client can re-establish
+ such a deleted Job attribute with any supported value(s), using a
+ subsequent Set-Job-Attributes operation.
+
+ If the client supplies an attribute in a Set-Job-Attributes request
+ with the 'delete-attribute' value and that attribute is not present
+ on the Job object, the Printer ignores that supplied attribute in the
+ request, does not return the attribute in the Unsupported Attributes
+ group, and returns the 'successful-ok' status code, if there are no
+ other problems with the request.
+
+ The validation of the Set-Job-Attributes request is performed by the
+ Printer as if the job had been submitted originally with the new
+ attribute values (and the deleted attributes removed) and with "ipp-
+ attribute-fidelity" set to 'true', i.e., all modified attributes Job
+ attributes and values MUST be supported in combination with the Job
+ attributes not modified. If such a Job Creation operation would have
+ been accepted, then the Set-Job-Attributes MUST be accepted. If such
+ a Job Creation operation would have been rejected, then the Set-Job-
+ Attributes MUST be rejected and the Job MUST be unchanged. In
+ addition, if any of the supplied attributes are not supported, are
+ not settable, or the values are not supported, the Printer object
+ MUST reject the entire operation; the Printer object MUST NOT
+ partially set some of the supplied attributes. In other words, after
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 14]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ the operation, all the supplied attributes MUST be set or none of
+ them MUST be set, thus making the Set-Job-Attributes an atomic
+ operation.
+
+ The IPP object MUST accept or reject this operation when the Job's
+ READ-ONLY "job-state" attribute has the values shown in Table 2. The
+ job's current state MUST affect whether the IPP object accepts or
+ rejects the request. For example, in the case where the operation
+ creates a request for unavailable resources, the Job transitions to a
+ new state. Table 2 shows the allowed behaviors in each job state and
+ the transitions.
+
+ Table 2 - Job State Transition Table for the Set-Job-Attributes
+ operation
+
+ Current New IPP object's response status code
+ "job-state" "job-state" and "action":
+
+
+ 'pending' 'pending' 'successful-ok'
+
+ 'pending' 'pending-held' 'successful-ok' - needed resources
+ are not ready
+
+ 'pending-held' 'pending-held' 'successful-ok'
+
+ 'pending-held' 'pending' 'successful-ok' - needed resources
+ are ready
+
+ 'processing' 'processing' 'successful-ok' or 'client-error-
+ not-possible' depending on
+ implementation, including the
+ attributes being set, whether the
+ job has started marking media,
+ etc.
+
+ 'processing- 'processing- 'successful-ok' or 'client-error-
+ stopped' stopped' not-possible' depending on
+ implementation, including the
+ attributes being set, whether the
+ job has started marking media,
+ etc.
+
+ 'completed' 'completed' 'client-error-not-possible'
+
+ 'canceled' 'canceled' 'client-error-not-possible'
+
+ 'aborted' 'aborted' 'client-error-not-possible'
+
+
+
+Hastings, et. al. Standards Track [Page 15]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ This operation MUST NOT change the value of attributes not specified
+ in the operation unless the definition of the attribute explicitly
+ specifies such side-effects. In general, Job attribute definitions
+ that are settable will not define side-effects on other attributes
+ that are settable, only side effects on READ-ONLY attributes, if any.
+
+4.2.1 Settable and READ-ONLY Job Description attributes
+
+ If the Printer supports the "job-message-from-operator" Job
+ Description attribute (see [RFC2911] section 4.3.16) and the client
+ explicitly supplies a new value for the "job-message-from-operator"
+ Job Description attribute in Group 2 in the Set-Job-Attributes
+ request, then the Printer MUST set the "job-message-from-operator"
+ Job Description attribute to this new value.
+
+ If the Printer supports the Set-Job-Attributes operation, then it
+ SHOULD support the setting of:
+
+ all Job Template job ("xxx") attributes
+
+ that the implementation supports (see [RFC2911] section 4.2 and
+ extensions).
+
+ Some Job Description attributes (see [RFC2911] section 4.3) MUST NOT
+ be settable, i.e., they are defined to be READ-ONLY. An attribute
+ marked as "READ-ONLY" in the Job Description attribute table in
+ Appendix A is such an attribute. The Job attributes not marked as
+ "READ-ONLY" MAY be settable using the Set-Job-Attributes operation,
+ depending on implementation.
+
+ Note: From now on, all extensions that define new object attributes
+ will indicate whether or not the attributes are READ-ONLY, by
+ including the "READ-ONLY" adjective in their descriptions and/or
+ explicitly stating whether they MAY be settable.
+
+ Access Rights: The authenticated user (see [RFC2911] section 8.3)
+ performing this operation must either be the job owner (as determined
+ in the Job Creation operation) or an operator or administrator of the
+ Printer object (see [RFC2911] Sections 1 and 8.5).
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 16]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+4.2.2 Set-Job-Attributes Request
+
+ The following sets of attributes are part of the Set-Job-Attributes
+ Request:
+
+ Group 1: Operation Attributes
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in [RFC2911], section 3.1.4.1.
+
+ Target:
+ Either (1) the "printer-uri" (uri) plus "job-id"
+ (integer(1:MAX)) or (2) the "job-uri" (uri) operation
+ attribute(s), which defines the target for this operation as
+ described in [RFC2911], section 3.1.5.
+
+ Requesting User Name:
+ The "requesting-user-name" (name(MAX)) attribute SHOULD be
+ supplied by the client, as described in [RFC2911], section 8.3.
+
+ Group 2: Job Attributes
+
+ The client MUST supply a set of Job attributes with one or more
+ values (including explicitly allowed out-of-band values) as
+ defined in [RFC2911], section 4.2, Job Template Attributes ("xxx"
+ attributes), section 4.3, Job Description Attributes, and any
+ attribute extensions supported by the Printer. The value(s) of
+ each Job attribute supplied in Group 2 replaces the value(s) of
+ the corresponding Job attribute on the target Job object. For
+ attributes that can have multiple values (1setOf), all values
+ supplied by the client replace all values of the corresponding Job
+ object attribute.
+
+ If the client supplies an "xxx" attribute with the 'delete-
+ attribute' out-of-band value (see section 8.2), the Printer MUST
+ remove the "xxx" attribute from the Job object, if present.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 17]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+4.2.3 Set-Job-Attributes Response
+
+ The IPP object returns the following sets of attributes as part of
+ the Set-Job-Attributes Response:
+
+ Group 1: Operation Attributes
+
+ Status Message:
+ In addition to the REQUIRED status code returned in every
+ response, the response OPTIONALLY includes a "status-message"
+ (text(255)) and/or a "detailed-status-message" (text(MAX))
+ operation attribute as described in [RFC2911], sections 3.1.6
+ and 13.
+
+ Natural Language and Character Set:
+ The "attributes-charset" and "attributes-natural-language"
+ attributes as described in [RFC2911], section 3.1.4.2.
+
+ Group 2: Unsupported Attributes
+
+ See [RFC2911], section 3.1.7, for details on returning Unsupported
+ Attributes.
+
+ If some of the attributes in the operation fail to validate, the
+ Printer MUST reject the operation, MUST NOT change any Job
+ attributes, and MUST return the indicated status code below. In
+ this group, the Printer MUST also return all attributes that fail
+ to validate. The following are the reasons that an attribute
+ fails to validate and the value returns for the attribute, along
+ with the indicated status code and order of detection:
+
+ 1. The number of attributes supplied by the client exceeds the
+ maximum number that the Printer supports in a Set-Printer-
+ Attributes request: return the 'client-error-request-entity-
+ too-large' (see [RFC2911], section 13.1.4.9).
+
+ 2. The Printer doesn't support the attribute: return the attribute
+ with the 'unsupported' out-of-band attribute value (see
+ [RFC2911], section 3.1.7 and [RFC2910]) and the 'client-error-
+ attributes-or-values-not-supported (see [RFC2911], section
+ 13.1.4.12).
+
+ 3. The attribute is READ-ONLY (in its definition) or is not-
+ settable in this implementation: return the attribute with the
+ 'not-settable' out-of-band attribute value (see section 8.1)
+ and the 'client-error-attributes-not-settable' status code (see
+ section 7.1).
+
+
+
+
+Hastings, et. al. Standards Track [Page 18]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ 4. The Printer doesn't support the value: if the attribute in the
+ operation has a single value return it. If the attribute in
+ the operation is multi-valued, return only those values in a
+ 1setOf that are not supported. Return the 'client-error-
+ attributes-or-values-not-supported' status code (see [RFC2911],
+ section 13.1.4.12).
+
+ 5. The values of some of the supplied attributes conflict with one
+ another and/or other Job attribute values not being set: if
+ the conflicting attribute in the operation has a single value,
+ return the attribute and the value. If the attribute in the
+ operation is multi-valued, return only the attribute and those
+ values in a 1setOf that are conflicting with other attributes.
+ Return the 'client-error-conflicting-attributes' status code
+ (see [RFC2911],y section 13.1.4.15).
+
+4.3 Get-Printer-Supported-Values Operation
+
+ This OPTIONAL operation allows a client to request the values that
+ the Printer allows in the Set-Printer-Attributes operation for "xxx-
+ supported" attributes. If the Printer supports the Set-Printer-
+ Attributes operation AND some of its "xxx-supported" Printer
+ attributes are settable, then the Printer MUST also support this
+ operation.
+
+ The Printer MUST return in the Get-Printer-Supported-Values response,
+ those, and only those, "xxx-supported" Printer attributes that it
+ supports setting with the Set-Printer-Attributes operation.
+ Furthermore, if a client requests the value of an attribute that is
+ not settable or is not supported (as in the Get-Printer-Attributes
+ response), the Unsupported Attributes Group of the response NEED NOT
+ contain the "requested-attributes" operation attribute with any such
+ requested (attribute keyword) values.
+
+ This operation has identical request/response attributes to the Get-
+ Printer-Attributes operation in IPP/1.1 [RFC2911]. The operation
+ also behaves identically to the Get-Printer-Attributes operation in
+ IPP/1.1 [RFC2911], with the following exceptions:
+
+ 1. The Get-Printer-Supported-Values operation supports only "xxx-
+ supported" attributes.
+
+ 2. The Get-Printer-Attributes operation returns the few "xxx-
+ supported" attributes that are defined to be single valued, such
+ as "page-ranges-supported" (boolean) or "pdl-override-supported"
+ (type2 keyword), as single values, while Get-Printer-Supported-
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 19]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Values returns the possible values that can be set as a 1setOf of
+ the same attribute syntax type (See Appendix B: Attributes
+ returned from Get-Printer-Supported-Values).
+
+ 3. The Get-Printer-Attributes operation returns the current values of
+ requested attributes, while the Get-Printer-Supported-Values
+ operation returns the values that are inherently supported by the
+ implementation code, i.e., the values that an administrative
+ client can set in a Set-Printer-Attributes request.
+
+ 4. The Get-Printer-Attributes operation returns the current values of
+ requested "xxx-supported" attributes that the Printer is
+ configured to accept in Job Creation operations, including
+ additional values defined by the administrator, while the Get-
+ Printer-Supported-Values operation returns only the values of
+ "xxx-supported" attributes that are inherently supported by the
+ implementation and does not return any additional values defined
+ by the administrator, where the implementation supports the
+ 'admin-define' out-of-band value.
+
+ 5. The Get-Printer-Attributes never returns the 'admin-define' out-
+ of-band attribute value, while the Get-Printer-Supported-
+ Attributes operation does, if the implementation allows the
+ administrator to define name values by setting that "xxx-
+ supported" attribute with any 'name' value(s).
+
+ 6. The Get-Printer-Attributes operation only requires end-user access
+ rights, while the Get-Printer-Supported-Values requires
+ administrator access rights.
+
+ Access Rights: The authenticated user (see [RFC2911], section 8.3)
+ performing this operation must be an administrator of the Printer
+ object (see [RFC2911], Sections 1 and 8.5).
+
+4.3.1 Definition of the usage of the 'admin-define' out-of-band
+ attribute value
+
+ If the Set-Printer-Attributes operation allows the System
+ Administrator to define arbitrary 'name' values for an "xxx-
+ supported" attribute, then the Get-Printer-Supported-Values operation
+ MUST return the 'admin-define' out-of-band attribute value (see
+ section 8.3) as one of the values of the "xxx-supported" attribute.
+ In other words, the 'admin-define' out-of-band attribute value
+ indicates that the Printer implementation supports clients setting
+ arbitrary 'name' attribute syntax values for that "xxx-supported"
+ attribute using the Set-Printer-Attributes operation, as long as the
+ attribute is defined with the 'name' attribute syntax.
+
+
+
+
+Hastings, et. al. Standards Track [Page 20]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ For example, if the Get-Printer-Supported-Values operation returns
+ several keywords as the value of the "media-supported" attribute,
+ then the Set-Printer-Attributes operation MUST accept any of these
+ keywords as values for the "media-supported" attribute. If the Get-
+ Printer-Supported-Values operation returns an 'admin-define' out-of-
+ band attribute value as one of the values of the "media-supported"
+ attribute, then the Set-Printer-Attributes operation MUST accept any
+ value whose attribute syntax is 'name', as a value for the "media-
+ supported" attribute (provided that the user is properly
+ authenticated to use the Set-Printer-Attributes operation, e.g., has
+ administrative access rights).
+
+ The Get-Printer-Supported-Values MAY return the 'admin-define' out-
+ of-band attribute value for any IPP/1.1 or extension Job Template
+ attribute if the implementation supports allowing the System
+ Administrator to add values to the "xxx-supported" attribute using
+ the Set-Printer-Attributes operation. In this case, the Printer MUST
+ accept any 'name' value of the correct attribute syntax in a Set-
+ Printer-Attributes operation that is setting that attribute. For
+ "xxx-supported" attributes that are defined with a choice of
+ attribute syntaxes, such as 'keyword | name', it is the 'name'
+ attribute syntax that the System Administrator can use to add new
+ values, not the 'keyword' attribute syntax. For IPP/1.1, this
+ requirement includes the following Job Template attributes:
+
+ media-supported
+ job-hold-until-supported
+ job-sheets-supported
+
+ Implementations that support additional Job Template attributes that
+ include the 'name' attribute syntax, MAY use the 'admin-define' out-
+ of-band value with them.
+
+ If the 'admin-define' out-of-band attribute value is not one of the
+ values of an "xxx-supported" attribute returned in a Get-Printer-
+ Supported-Values response, then the Printer MUST NOT allow the Set-
+ Printer-Attributes operation for that attribute to contain a value
+ that is not one of the explicit 'keyword' or 'name' values returned
+ in a Get-Printer-Supported-Values response.
+
+ See Appendix B: Attributes returned from Get-Printer-Supported-Values
+ for a full list of values returned by this operation.
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 21]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+5 New Operation attributes
+
+ This section defines new operation attributes for use with the
+ IPP/1.1 operations indicated. As new operations are defined, they
+ will also indicate explicitly whether these operation attributes are
+ defined for use with them.
+
+5.1 printer-message-from-operator (text(127))
+
+ The Printer SHOULD support this Operation attribute in following
+ operations if it supports the corresponding "printer-message-from-
+ operator" Printer Description attribute.
+
+ Pause-Printer
+ Resume-Printer
+ Purge-Jobs
+
+ The client OPTIONALLY supplies this Operation attribute in the above
+ operations. The value of this attribute is a message from the
+ operator about the Printer object on which the operator is performing
+ the operation. If this operation attribute is supported, the Printer
+ copies the value to its "printer-message-from-operator" Printer
+ Description attribute (see [RFC2911], section 4.4.25), even if this
+ Operation attribute is a zero-length text value or consists solely of
+ white space.
+
+ If the Printer supports this operation attribute, it MUST support
+ both a zero-length text value and the 'no-value' out-of-band value
+ (see [RFC2911] section 4.1) to indicate that the operator has sent no
+ message. In this case, the Printer sets the value of the "printer-
+ message-from-operator" to the zero-length value or 'no-value' out-
+ of-band value, respectively. If the client queries the "printer-
+ message-from-operator" Printer attribute, the Printer returns the
+ attribute with the zero-length value or the 'no-value' value,
+ respectively.
+
+ In addition, the Printer automatically copies:
+
+ 1. the value of its "printer-up-time" attribute (see [RFC2911],
+ section 4.4.29) to its "printer-message-time" attribute,
+
+ 2. the value of its printer-current-time" (dateTime) attribute (see
+ [RFC2911], section 4.4.30) to its "printer-message-date-time"
+ attribute, if supported.
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 22]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ If the client omits this operation attribute, the Printer does not
+ change the value of its "printer-message-from-operator", "printer-
+ message-time" and "printer-message-date-time" Printer Description
+ attributes.
+
+ The "printer-message-from-operator" operation attribute MUST NOT be
+ supported as an operation attribute for the Set-Printer-Attributes
+ operation. If the operator wants to set the Printer's "printer-
+ message-from-operator" Printer Description attribute when issuing the
+ Set-Printer-Attributes operation, the client supplies the "printer-
+ message-from-operator" explicitly with its new value as one of the
+ Printer Description attributes in Group 2 in the request; the Printer
+ also updates its "printer-message-time" and "printer-message-date-
+ time" Printer Description attributes. If the client does not
+ explicitly supply the "printer-message-from-operator" with its new
+ value in the Set-Printer-Attributes request, the Printer leaves the
+ value of the Printer's "printer-message-from-operator" Printer
+ Description attribute unchanged.
+
+5.2 job-message-from-operator (text(127))
+
+ The Printer SHOULD support this Operation attribute in following
+ operations if it supports the corresponding "job-message-from-
+ operator" Job Description attribute.
+
+ Cancel-Job
+ Hold-Job
+ Release-Job
+ Restart-Job
+
+ The client OPTIONALLY supplies this attribute in the above
+ operations. The value of this attribute is a message from the
+ operator about the Job object on which the operator has just
+ performed an operation. If supported, the Printer copies the value
+ to the Job's "job-message-from-operator" Job Description attribute
+ (see [RFC2911], section 4.3.16) (even if this Operation attribute is
+ a zero-length text value or consists solely of white space).
+
+ If the Printer supports this operation attribute, it MUST support
+ both a zero-length text value and the 'no-value' out-of-band value
+ (see [RFC2911], section 4.1), to indicate that the operator has sent
+ no message. In this case, the Printer sets the value of the "job-
+ message-from-operator" to the zero-length value or 'no-value' out-
+ of-band value, respectively. If the client queries the "job-
+ message-from-operator" Job attribute, the IPP object returns the
+ attribute with the zero-length value or the 'no-value' value,
+ respectively.
+
+
+
+
+Hastings, et. al. Standards Track [Page 23]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ If the client omits this attribute, the Printer does not change the
+ value of its "job-message-from-operator" Job Description attribute.
+
+ Note: There are no corresponding 'job-message-time" and "job-
+ message-date-time" Job Description attributes, since the usual
+ lifetime of a job is limited.
+
+ The "job-message-from-operator" operation attribute MUST NOT be
+ supported as an operation attribute for the Set-Job-Attributes
+ operation. If the operator wants to set the Job's "job-message-
+ from-operator" Job Description attribute when issuing the Set-Job-
+ Attributes operation, the client MUST supply the "job-message-from-
+ operator" with its new value as one of the Job Description attributes
+ in Group 2 in the request. Otherwise, the Printer leaves the value
+ of the Job's "job-message-from-operator" Job Description attribute
+ unchanged by not explicitly setting the attribute. If the client
+ does not explicitly supply the "job-message-from-operator" with its
+ new value in the Set-Job-Attributes request, the Printer leaves the
+ value of the Job's "job-message-from-operator" Job Description
+ attribute unchanged.
+
+6 New Printer Description Attributes
+
+ The following new Printer Description attributes are needed to
+ support the new operations defined in this document.
+
+6.1 printer-settable-attributes-supported (1setOf type2 keyword)
+
+ This REQUIRED READ-ONLY Printer Description attribute identifies the
+ Printer object attributes that are settable in this implementation,
+ i.e., that are settable using the Set-Printer-Attributes operations
+ (see section 4.1). This attribute MUST be supported if the Set-
+ Printer-Attributes operations is supported. The Printer MUST reject
+ attempts to set any Printer attributes that are not one of the values
+ of this attribute, returning the 'client-error-attributes-not-
+ settable' status code (see section 7.1). The value of this attribute
+ MAY depend on the value of the "document-format" operation attribute
+ supplied in the Get-Printer-Attributes operation (see [RFC2911],
+ section 3.2.5.1).
+
+ Standard keyword values are:
+
+ 'none': There are no settable Printer attributes.
+ 'xxx': Where 'xxx' is any of the keyword attribute names allowed
+ by section 4.1.1.
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 24]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+6.2 job-settable-attributes-supported (1setOf type2 keyword)
+
+ This REQUIRED READ-ONLY Printer Description attribute identifies the
+ Job object attributes that are settable in this implementation, i.e.,
+ that are settable using the Set-Job-Attributes operation (see section
+ 4.2). This attribute MUST be supported if the Set-Job-Attributes
+ operations are supported. The Printer MUST reject attempts to set
+ any Job attributes that are not one of the values of this attribute,
+ returning the 'client-error-attributes-not-settable' status code (see
+ section 7.1).
+
+ Standard keyword values are:
+
+ 'none': There are no settable Job attributes.
+ 'xxx': Where 'xxx' is any of the keyword attribute names allowed
+ by section 4.2.1.
+
+6.3 document-format-varying-attributes (1setOf type2 keyword)
+
+ This OPTIONAL READ-ONLY Printer Description attribute contains a set
+ of attribute name keywords. This attribute SHOULD be supported by a
+ Printer object if the Printer object has Printer attributes whose
+ value vary depending on document format (see [RFC2911], Get-Printer-
+ Attributes operation). This attribute specifies which attribute
+ values can vary by document-format. If an attribute's name, "xxx",
+ is a member of this attribute and the value of attribute "xxx" is
+ changed with the Set-Printer-Attributes operation that included the
+ "document-format" operation attribute, then the Printer MUST change
+ the value for the specified document format and no other document
+ formats (see section 4.1.2). If an attribute's name, "xxx", is not a
+ member of this attribute and the value of attribute "xxx" is changed
+ with the Set-Printer-Attributes operation, then the attribute is
+ changed for all document formats (whether or not the client supplied
+ the "document-format" operation attribute).
+
+6.4 printer-message-time (integer(MIN:MAX))
+
+ This OPTIONAL READ-ONLY Printer Description attribute contains the
+ time that the Printer's "printer-message-from-operator" was changed
+ by the operator using any operation where the client supplied the
+ "printer-message-from-operator" operation attribute (see section 5.1)
+ or was explicitly set using the Set-Printer-Attributes operation (see
+ section 4.1). This attribute allows the users to know when the
+ "printer-message-from-operator" Printer Description attribute was
+ last set.
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 25]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ The Printer sets the value of this attribute by copying the value of
+ the Printer's "printer-up-time" attribute (see [RFC2911], section
+ 4.3.14). If the Printer resets its "printer-up-time" attribute to 1
+ on power-up, then it MUST change the value of the "printer-message-
+ time" to 0 or a negative number as specified in [RFC2911], section
+ 4.3.14.
+
+ Note: This attribute helps users better understand the context for
+ the "printer-message-from-operator" message.
+
+6.5 printer-message-date-time (dateTime)
+
+ This OPTIONAL READ-ONLY Printer Description attribute contains the
+ date and time that the Printer's "printer-message-from-operator" was
+ changed by the operator, using any operation where the client
+ supplied the "printer-message-from-operator" operation attribute (see
+ section 5.1) or was explicitly set using the Set-Printer-Attributes
+ operation (see section 4.1). This attribute allows the users to know
+ when the "printer-message-from-operator" Printer Description
+ attribute was last set.
+
+ This attribute MUST be supported if the Printer supports both the
+ "printer-message-time" and the "printer-current-time" (dateTime)
+ attributes (see [RFC2911], section 4.4.30).
+
+ Note: This attribute helps users better understand the context for
+ the "printer-message-from-operator" message.
+
+6.6 printer-xri-supported (1setOf collection)
+
+ This OPTIONAL Printer Description attribute is a multi-valued
+ attribute where each value has the 'collection' attribute syntax (see
+ [RFC3382]), containing member attributes with the same semantics as
+ the following IPP/1.1 READ-ONLY Printer Description attributes,
+ except for cardinality:
+
+ printer-uri-supported (1setOf uri)
+ - see [RFC2911], section 4.4.1
+ uri-authentication-supported (1setOf type2 keyword)
+ - see [RFC2911], section 4.4.2.
+ uri-security-supported (1setOf type2 keyword)
+ - see [RFC2911], section 4.4.3.
+
+ When setting the "printer-xri-supported" attribute with a Set-
+ Printer-Attributes request, the Printer MUST also set these three
+ IPP/1.1 READ-ONLY Printer Description attributes as a defined side
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 26]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ effect. Thus, this collection attribute provides the means to set
+ these three IPP/1.1 READ-ONLY attributes atomically so that they are
+ never left in a partially inconsistent state.
+
+ An IPP Printer MUST NOT provide any other way, using IPP, to set
+ these three IPP/1.1 READ-ONLY Printer Description attributes, since
+ they are READ-ONLY and MUST have consistent values at all times.
+ Note: The "printer-xri-supported" (1setOf collection) attribute can
+ be put into a directory schema that requires a single text string
+ value, such as could be used with SLPv2 [RFC2608], [RFC2609] or
+ LDAPv3 [RFC2251], [RFC2252], [RFC2926], by using suitable delimiting
+ characters to separate member attributes of the collection and/or
+ terminating collection values.
+
+ The member attributes of the "printer-xri-supported" (1setOf
+ collection) are given in Table 3.
+
+ Table 3 - Member attributes of "printer-xri-supported" (1setOf
+ collection)
+
+ Member attribute client Printer
+ MUST MUST
+ supply support
+
+ xri-uri (uri) yes yes
+
+ xri-authentication (type2 keyword) yes yes
+
+ xri-security (type2 keyword) yes yes
+
+ Other than the uniqueness and the cardinality requirements, the
+ semantics of these three member attributes is given in [RFC2911]
+ sections 4.4.1, 4.4.2, and 4.4.3, respectively.
+
+ A client can query the current values using the Get-Printer-
+ Attributes operation by supplying either:
+
+ 1. the three IPP/1.1 attribute names: "printer-uri-supported", "uri-
+ authentication-supported", "uri-security-supported" and getting
+ back the parallel values OR
+
+ 2. the single attribute name: "printer-xri-supported" and getting
+ back the 1setOf collection which contains the same information
+ semantically, but in a different form.
+
+ A client can query what member attribute values can be set by
+ supplying the three attribute names: "xri-uri-scheme-supported",
+ "xri-authentication-supported", and "xri-security-supported" in a
+
+
+
+Hastings, et. al. Standards Track [Page 27]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Get-Printer-Supported-Values request and getting back the uriScheme
+ and type2 keyword values that can be set. Since the "printer-xri-
+ supported", "uri-authentication-supported", and "uri-security-
+ supported" attributes are READ-ONLY, they are not queriable with the
+ Get-Printer-Supported-Values operation (see section 4.3). See Table
+ 16.
+
+ For example:
+
+ "printer-xri-supported =
+ { "xri-uri" = ipp://abc.com/p1
+ "xri-authentication" = basic
+ "xri-security" = tls
+ },
+ { "xri-uri" = ipp://abc.com/p2
+ "xri-authentication" = digest
+ "xri-security" = tls
+ },
+ { "xri-uri" = ipp://abc.com/p3
+ "xri-authentication" = none
+ "xri-security" = none
+ }
+
+ would cause the Printer to set the three corresponding IPP/1.1 READ-
+ ONLY attributes, each with three parallel values as follows:
+
+ "printer-uri-supported" = { ipp://abc.com/p1, ipp://abc.com/p2,
+ ipp://abc.com/p3 }
+ "uri-authentication-supported" = { basic, digest, none }
+ "uri-security-supported" = { tls, tls, none }
+
+6.7 xri-uri-scheme-supported (1setOf uriScheme)
+
+ This OPTIONAL READ-ONLY Printer Description attribute identifies the
+ URI schemes that the implementation supports for use in the
+ "printer-uri-supported" (1setOf uri) Printer Description attribute
+ (see [RFC2911] section 4.4.1) and the "xri-uri" member attribute of
+ the "printer-xri-supported" (1setOf collection) Printer Description
+ attribute (see section 6.6).
+
+ A Printer MUST support this attribute if it supports the setting of
+ the "printer-xri-supported" (1setOf collection) with the Set-
+ Printer-Attributes operation.
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 28]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+6.8 xri-authentication-supported (1setOf type2 keyword)
+
+ This OPTIONAL READ-ONLY Printer Description attribute identifies the
+ Client Authentication mechanisms that the implementation supports for
+ use in the "uri-authentication-supported" (1setOf type2 keyword)
+ Printer Description attribute (see [RFC2911], section 4.4.2) and the
+ "xri-authentication" member attribute of the "printer-xri-supported"
+ (1setOf collection) Printer Description attribute (see section 6.6).
+
+ A Printer MUST support this attribute if it supports setting the
+ "printer-xri-supported" (1setOf collection) with the Set-Printer-
+ Attributes operation.
+
+6.9 xri-security-supported (1setOf type2 keyword)
+
+ This OPTIONAL READ-ONLY Printer Description attribute identifies the
+ URI schemes that the implementation supports for use in the "uri-
+ security-supported" (1setOf type2 keyword) Printer Description
+ attribute (see [RFC2911], section 4.4.3) and the "xri-security"
+ member attribute of the "printer-xri-supported" (1setOf collection)
+ Printer Description attribute (see section 6.6).
+
+ A Printer MUST support this attribute if it supports setting the
+ "printer-xri-supported" (1setOf collection) with the Set-Printer-
+ Attributes operation.
+
+7 Additional status codes
+
+ This section defines new status codes used by the operations defined
+ in this document.
+
+7.1 client-error-attributes-not-settable (0x0413)
+
+ The Set-Printer-Attributes or Set-Job-Attributes operation failed
+ because one or more of the specified attributes cannot be set, either
+ because the attribute is defined to be READ-ONLY or the attribute is
+ not settable in this implementation (see sections 4.1.3 and 4.2.3).
+ The Printer MUST return this error code and the attribute keyword
+ name(s) and the 'not-settable' out-of-band value (see section 8.1) in
+ the Unsupported Attributes Group (see [RFC2911], section 3.1.7) for
+ all of the attributes that could not be set. When the Printer
+ returns this status, it MUST NOT change any of the attributes
+ supplied in the operation.
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 29]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+8 Additional out-of-band values
+
+ This section defines additional out-of-band values. As with all
+ out-of-band values, a client or a Printer MUST NOT use an out-of-band
+ value unless the definition of the attribute in an operation request
+ and/or response explicitly allows such usage. See the beginning of
+ [RFC2911], section 4.1.
+
+8.1 'not-settable' out-of-band value
+
+ The 'not-settable' out-of-band attribute value is returned by the IPP
+ Printer in the Unsupported Attributes group of a response to indicate
+ that the attribute supplied by the client in the request is READ-ONLY
+ by definition or is not settable in this implementation.
+
+ The 'not-settable' out-of-band attribute value is defined for use
+ with the Set-Job-Attributes and Set-Printer-Attributes responses
+ only. If a future additional "set" operation allows the 'not-
+ settable' out-of-band value, its definition document MUST indicate
+ such use explicitly, including with which attributes.
+
+ An IPP object MUST support the 'not-settable' out-of-band value in a
+ Set-Job-Attributes or Set-Printer-Attributes request if it supports
+ those operations. A client MUST NOT supply the 'not-settable' out-
+ of-band value in any request. An IPP object MUST NOT support the
+ 'not-settable' out-of-band value in other operations, unless the
+ operations' definition document explicitly defines such usage. If a
+ Printer receives this out-of-band value in any operation request, the
+ Printer MUST either (1) reject the entire request and return the
+ 'client-error-bad-request' status code or (2) ignore the attribute
+ and return it with the 'unsupported' out-of-band value.
+
+ See sections 4.1.3 and 4.2.3 in this document for an example
+ definition of the usage of the 'not-settable' out-of-band value in
+ the Set-Printer-Attributes and Set-Job-Attributes responses.
+
+8.1.1 Encoding of the 'not-settable' out-of-band attribute value
+
+ The encoding of the 'not-settable' out-of-band value is 0x15 (see
+ [RFC2910]). The value-length MUST be 0 and the value empty.
+
+8.2 'delete-attribute' out-of-band value
+
+ The 'delete-attribute' out-of-band attribute value is supplied by the
+ client in a request to indicate that the Printer is to remove the
+ supplied attribute and all of its values from the target object, if
+ present.
+
+
+
+
+Hastings, et. al. Standards Track [Page 30]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ The 'delete-attribute' out-of-band attribute value is defined for use
+ with the Set-Job-Attributes request only. If a future additional
+ "set" operation allows the 'delete-attribute' out-of-band value, its
+ definition document MUST indicate such use explicitly, including with
+ which attributes.
+
+ An IPP Printer MUST support the 'delete-attribute' out-of-band value
+ if it supports the Set-Job-Attributes operation. A client MUST NOT
+ supply, and an IPP object MUST NOT support, the 'delete-attribute'
+ out-of-band value in other operations, unless the operations'
+ definition document explicitly defines such usage. For example, the
+ 'delete-attribute' out-of-band value MUST NOT be used in the Set-
+ Printer-Attributes operation, where the absence of an attribute from
+ an IPP object indicates that the attribute is not supported. If a
+ Printer receives this out-of-band value in other operation requests,
+ the Printer MUST either (1) reject the entire request and return the
+ 'client-error-bad-request' status code or (2) ignore the attribute
+ and return it with the 'unsupported' out-of-band value.
+
+ See section 4.2 in this document for the definition of the usage of
+ the 'delete-attribute' out-of-band value in the Set-Job-Attributes
+ request.
+
+8.2.1 Encoding of the 'delete-attribute' out-of-band value
+
+ The encoding of the 'delete-attribute' out-of-band value is 0x16 (see
+ [RFC2910]). The value-length MUST be 0 and the value empty.
+
+8.3 'admin-define' out-of-band attribute value
+
+ Section 4.3 defines the Get-Printer-Supported-Values response to
+ contain the values of an "xxx-supported" attribute that are supported
+ by the implementation before any additional values are defined by the
+ administrator. The 'admin-define' out-of-band attribute value is
+ returned as an additional value of an "xxx-supported" attribute in a
+ Get-Printer-Supported-Values response to indicate that the
+ implementation supports allowing an administrator to define
+ additional arbitrary 'name' values for that "xxx-supported"
+ attribute.
+
+ For example, if the "media-supported" (1setOf (type3 keyword | name))
+ attribute contains this value, then the Printer MUST permit an
+ administrator to add new media names to the Printer's "media-
+ supported" attribute. In order for an administrator to add new
+ values to a Printer's "xxx-supported" attribute, the client supplies
+ the existing and new values in a Set-Printer-Attributes request for
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 31]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ that attribute. The client MUST supply any such administratively
+ defined values in the Set-Printer-Attributes request, using the
+ 'name' attribute syntax.
+
+ The 'admin-define' out-of-band attribute value is defined for use
+ with the Get-Printer-Supported-Values response only. A Printer MUST
+ NOT return the 'admin-define' out-of-band value in a Get-Printer-
+ Attributes response, since such a response indicates what an end-user
+ client can supply in a Job Creation operation. If a future
+ additional "get" operation allows the 'admin-define' out-of-band
+ value, its definition document MUST indicate such use explicitly,
+ including with which attributes.
+
+ An IPP Printer MUST support the 'admin-define' out-of-band value, if
+ it supports a client setting arbitrary 'name' values of an "xxx-
+ supported" Printer attribute using the Set-Printer-Attributes
+ operation. A client MUST NOT supply the 'admin-define' out-of-band
+ value in any request. An IPP object MUST NOT support the 'admin-
+ define' out-of-band value in other operations, unless the operations'
+ definition document explicitly defines such usage. If a Printer
+ receives this out-of-band value in any operation request, the Printer
+ MUST either (1) reject the entire request and return the 'client-
+ error-bad-request' status code or (2) ignore the attribute and return
+ it with the 'unsupported' out-of-band value.
+
+ This document defines that the 'admin-define' out-of-band value MUST
+ be used only with "xxx-supported" attributes that are defined to
+ include the 'name' attribute syntax. This out-of-band value is not
+ intended to be used with "xxx-supported" attributes of other
+ attribute syntaxes, such as 'uri', even though the administrator
+ defines arbitrary values for such attributes. If other documents
+ extend the use of the 'admin-define' out-of-band value to other
+ attribute syntaxes, such a document MUST define such use explicitly,
+ including with which attributes.
+
+ See section 4.3 in this document for an example definition of the
+ usage of the 'admin-define' out-of-band attribute value in any "xxx-
+ supported" attribute returned in a Get-Printer-Supported-Values
+ response that is defined to include the 'name' attribute syntax.
+
+8.3.1 Encoding of the 'admin-define' out-of-band attribute value
+
+ The encoding of the 'admin-define' out-of-band attribute value is
+ 0x17 (see [RFC2910]). The value-length MUST be 0 and the value
+ empty.
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 32]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+9 New Values for Existing Printer Description Attributes
+
+ This section contains those attributes for which additional values
+ are added.
+
+9.1 operations-supported (1setOf type2 enum)
+
+ The following "operation-id" values are added in order to support the
+ new operations defined in this document:
+
+ Table 4 - Operation-id assignments
+
+ Value Operation Name
+
+ 0x0013 Set-Printer-Attributes
+
+ 0x0014 Set-Job-Attributes
+
+ 0x0015 Get-Printer-Supported-Values
+
+10 Conformance Requirements
+
+ This section specifies the conformance requirements for clients and
+ IPP objects.
+
+ Both the Set-Job-Attributes and the Set-Printer-Attributes operations
+ defined in the document are OPTIONAL for an IPP object to support.
+ Either one MAY be supported without the other or both MAY be
+ supported. However, if the Set-Printer-Attributes operation is
+ supported, then the Get-Printer-Supported-Values operation MUST be
+ supported if any "xxx-supported" attributes are settable. Otherwise,
+ the Get-Printer-Supported-Values operation is OPTIONAL for an IPP
+ Printer to support.
+
+ If the Set-Printer-Attributes operation is supported, then the
+ Printer MUST support the following additional items:
+
+ 1. the Get-Printer-Supported-Values operation (see section 5), if
+ any "xxx-supported" attributes are settable.
+
+ 2. the "printer-settable-attributes-supported" Printer Description
+ attribute (see section 6.1).
+
+ 3. the 'not-settable' out-of-band value in responses (see section
+ 8.1).
+
+ 4. the 'client-error-not-settable' status code (see section 7.1).
+
+
+
+
+Hastings, et. al. Standards Track [Page 33]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ 5. if the "printer-message-from-operator" Printer Description
+ attribute is supported (see [RFC2911], section 4.4.25), then it
+ MUST be settable.
+
+ 6. the Get-Printer-Supported-Values operation (see section 4.3),
+ if any "xxx-supported" attributes are settable.
+
+ 7. If a client can set a value with the 'name' attribute syntax
+ for one or more "xxx-supported" attributes, then the 'admin-
+ define' out-of-band attribute value (see section 8.3) MUST be
+ supported in the Get-Printer-Supported-Values response for each
+ such settable attribute (see section 4.3)
+
+ If the Set-Job-Attributes operation is supported, then the Printer
+ MUST support the following additional items:
+
+ 1. the "job-settable-attributes-supported" Printer Description
+ attribute (see section 6.2).
+
+ 2. the 'not-settable' out-of-band value in responses (see section
+ 8.1).
+
+ 3. the 'delete-attribute' out-of-band value in requests (see
+ section 8.2).
+
+ 4. the 'client-error-not-settable' status code (see section 7.1).
+
+ 5. if the "job-message-from-operator" Printer Description
+ attribute is supported (see [RFC2911], 4.3.16), then it MUST be
+ settable.
+
+ It is OPTIONAL for the Printer object to support the "printer-
+ message-time" (integer) and "printer-message-date-time" (dateTime)
+ Printer Description attributes. If both the "printer-message-time"
+ (integer) and the "printer-current-time" (dateTime) (see [RFC2911],
+ section 4.4.30) attributes are supported, then the "printer-message-
+ date-time" (dateTime) Printer Description attribute MUST be
+ supported.
+
+ As with all out-of-band values, a client or a Printer MUST NOT use an
+ out-of-band value, unless the definition document for the attribute
+ in an operation request and/or response explicitly allows such usage.
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 34]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+11 IANA Considerations
+
+ This section contains registration information for IANA to add to the
+ various IPP Registries according to the procedures defined in RFC
+ 2911 [RFC2911], section 6. The resulting registrations will be
+ published in the http://www.iana.org/assignments/ipp-registrations
+ registry.
+
+11.1 Operation Registrations
+
+ The following table lists all of the operations defined in this
+ document. These are to be registered according to the procedures
+ defined in RFC 2911 [RFC2911], section 6.4.
+
+ Operations: Ref. Section:
+ Set-Printer-Attributes RFC 3380 4.1
+ Set-Job-Attributes RFC 3380 4.2
+ Get-Printer-Supported-Values RFC 3380 4.3
+
+11.2 Additional Enum Attribute Value Registrations for the
+ "operations-supported" Printer Attribute
+
+ The following table lists all the new enum attribute values defined
+ in this document as additional type2 enum values for use with the
+ "operations-supported" Printer Description attribute. These are to
+ be registered according to the procedures defined in RFC 2911 [RFC
+ 2911], section 6.1.
+
+ Enum Attribute Values: Value Ref. Section:
+ Set-Printer-Attributes 0x0013 RFC 3380 4
+ Set-Job-Attributes 0x0014 RFC 3380 4
+ Get-Printer-Supported-Values 0x0015 RFC 3380 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 35]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+11.3 Keyword attribute value registrations
+
+ The following table lists all of the attributes defined in this
+ standard which have keywords values defined:
+
+ printer-settable-attributes-supported (1setOf type2 keyword)
+ RFC 3380 6.1
+ none RFC 3380 6.1
+ <Any other Printer attribute keyword name>
+ job-settable-attributes-supported (1setOf type2 keyword)
+ RFC 3380 6.2
+ none RFC 3380 6.2
+ <Any other Job attribute keyword name>
+ document-format-varying-attributes (1setOf type2 keyword)
+ RFC 3380 6.3
+ none
+ <Any Printer attribute keyword name>
+ xri-security-supported (1setOf type2 keyword) RFC 3380 6.9
+ none RFC 2911 4.4.3
+ ssl3 RFC 2911 4.4.3
+ tls' RFC 2911 4.4.3
+ xri-authentication-supported (1setOf type2 keyword)
+ none RFC 2911 4.4.2
+ requesting-user-name RFC 2911 4.4.2
+ basic RFC 2911 4.4.2
+ digest RFC 2911 4.4.2
+ certificate RFC 2911 4.4.2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 36]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+11.4 Attribute Registrations
+
+ The following table lists all of the attributes defined in this
+ document. These are to be registered according to the procedures in
+ RFC 2911 [RFC2911], section 6.2.
+
+ Operation attributes: Ref. Section:
+ printer-message-from-operator (text(127)) RFC 3380 5.1
+ job-message-from-operator (text(127)) RFC 3380 5.2
+
+ Printer Description attributes: Ref. Section:
+ printer-settable-attributes-supported (1setOf type2 keyword)
+ RFC 3380 6.1
+ job-settable-attributes-supported (1setOf type2 keyword)
+ RFC 3380 6.2
+ document-format-varying-attributes (1setOf type2 keyword)
+ RFC 3380 6.3
+ printer-message-time (integer(MIN:MAX)) RFC 3380 6.4
+ printer-message-date-time (dateTime) RFC 3380 6.5
+ printer-xri-supported (1setOf collection) RFC 3380 6.6
+ xri-uri (uri) RFC 3380 6.6
+ xri-authentication (type2 keyword) RFC 3380 6.6
+ xri-security (type2 keyword) RFC 3380 6.6
+ xri-uri-scheme-supported (1setOf uriScheme) RFC 3380 6.7
+ xri-authentication-supported (1setOf type2 keyword) 6.8
+ xri-security-supported (1setOf type2 keyword) RFC 3380 6.9
+
+11.5 Status code Registrations
+
+ The following table lists the status code defined in this document.
+ This is to be registered according to the procedures in RFC 2911
+ [RFC2911], section 6.6.
+
+ Status codes: Ref. Section:
+ client-error-attributes-not-settable (0x0413) RFC 3380 7.1
+
+11.6 Out-of-band Attribute Value Registrations
+
+ The following table lists all of the out-of-band attribute values
+ defined in this document. These are to be registered according to
+ the procedures in RFC 2911 [RFC2911] section 6.7.
+
+ Value: Out-of-band Attribute value name: Ref. Section:
+ 0x15 not-settable RFC 3380 8.1
+ 0x16 delete-attribute RFC 3380 8.2
+ 0x17 admin-define RFC 3380 8.3
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 37]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+12 Internationalization Considerations
+
+ This document has the same localization considerations as [RFC2911].
+
+13 Security Considerations
+
+ The IPP Model and Semantics document ([RFC2911], section 8) discusses
+ high level security requirements (Client Authentication, Server
+ Authentication and Operation Privacy). Client Authentication is the
+ mechanism by which the client proves its identity to the server in a
+ secure manner. Server Authentication is the mechanism by which the
+ server proves its identity to the client in a secure manner.
+ Operation Privacy is defined as a mechanism for protecting operations
+ from eavesdropping.
+
+ In addition, the introduction of the Set-Printer-Attributes and Set-
+ Job-Attributes operations creates another security threat, since the
+ client is able to modify the Printer and Job attributes stored in the
+ Printer. Such modifications could lead to denial of service.
+
+ A malicious user could alter the policy established by the system
+ administrator and stored in the Printer attributes. Such alteration
+ could either grant access to more resources or deny access to
+ resources that the system administrator has established. For
+ example, the malicious user could remove all of the document-format
+ values from the "document-format-supported" Printer attribute so that
+ the Printer would refuse to accept all jobs.
+
+ The general remedy for such malicious user actions against Printer
+ attributes is to have strong Client Authentication coupled with
+ Printer access control, to limit the users who have System
+ Administrator or Operator privileges.
+
+ A malicious user could modify the Job Template attributes of another
+ user's Job, such as the "copies" attribute. For example, setting the
+ number of copies to a large number.
+
+ The general remedy for such malicious user actions against another
+ user's job is to have strong Client Authentication coupled with
+ Printer access control to limit the users who have System
+ Administrator or Operator privileges who can modify any job and, in
+ addition, store the Client Authentication with each Job so that only
+ the job owner End User can modify his/her own job.
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 38]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+14 References
+
+14.1 Normative References
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P. and R. Turner,
+ "Internet Printing Protocol/1.1: Encoding and Transport",
+ RFC 2910, September 2000.
+
+ [RFC2911] Hastings, T., Herriot, R., deBry, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2911, September 2000.
+
+ [RFC3382] deBry, R., Hastings, T., Herriot, R., Ocke, K. and P.
+ Zehler, "Internet Printing Protocol (IPP): The
+ 'collection' attribute syntax", RFC 3382, September 2002.
+
+14.2 Informative References
+
+ [RFC2251] Wahl, M., Howes, T. abd S. Kille, "Lightweight Directory
+ Access Protocol (v3)", RFC 2251, December 1997.
+
+ [RFC2252] Wahl, M., Coulbeck, A., Howes, T. and S. Kille,
+ "Lightweight Directory Access Protocol (v3): Attribute
+ Syntax Definitions", RFC 2252, December 1997.
+
+ [RFC2608] Guttman, E., Perkins, C., Veizades, J. and M. Day,
+ "Service Location Protocol, Version 2", RFC 2608, June
+ 1999.
+
+ [RFC2609] Guttman, E., Perkins, C. and J. Kempf, "Service Templates
+ and service: Schemes", RFC 2609, June 1999.
+
+ [RFC3196] Hastings, T., Manros, C., Zehler, P., Kugler, C. and H.
+ Holst, "Internet Printing Protocol/1.1: Implementor's
+ Guide", RFC 3196, November 2001.
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 39]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+Appendix A: Allowed Values for Set-Printer-Attributes and
+ Set-Job-Attributes requests (Normative)
+
+ This appendix is a normative part of this document and contains a
+ table of all IPP/1.1 attributes. Each row contains:
+
+ - an attribute and
+
+ - the values allowed in the Set-Printer-Attributes or Set-Job-
+ Attributes request for the attribute. The entry in each cell
+ is the name (first few words) of each item below 1, 2, 3, 4a-g,
+ and 5.
+
+ The allowed values include the following cases:
+
+ 1. READ-ONLY: the Set-Printer-Attributes or Set-Job-Attributes
+ operation MUST NOT change this attribute and MUST reject the
+ entire operation (see section 7.1).
+
+ 2. Any of "xxx-supported": the Set-Printer-Attributes or Set-
+ Job-Attributes operation accepts values that are allowed
+ according to the IPP/1.1 rules for validating the value(s) of
+ an "xxx" Printer or Job attribute against the value(s) of the
+ corresponding "xxx-supported" Printer attribute. Table 5
+ summarizes those validation rules depending on each attribute
+ syntax and value of an "xxx" attribute supplied in the request
+ and that of the corresponding "xxx-supported" Printer
+ attribute. The "xxx-supported" attribute syntax type and
+ value(s) are obtained from a Get-Printer-Supported-Values
+ response (see the tables in this Appendix).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 40]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 5 - Validation rules for 'Any of "xxx-supported" '
+
+ Type of "xxx" Type of "xxx- Validates if:
+ value to be supported" value
+ set
+
+ integer rangeOfInteger each value is in one of the
+ "xxx-supported" ranges
+
+ uri uriScheme each uri scheme matches one
+ of the "xxx-supported"
+ schemes
+
+ any boolean if the boolean "xxx-
+ supported" is 'true'
+
+ any same type each value matches an "xxx-
+ supported" value of the same
+ type
+
+ For additional non-normative explanatory information see section
+ 3.1.2.3 of the "Internet Printing Protocol/1.1: Implementer's Guide"
+ [RFC3196].
+
+ 3. From Get-Printer-Supported-Values: the Set-Printer-Attributes
+ operation accepts values that are allowed according to the
+ IPP/1.1 rules for validating the value(s) of an "xxx" Printer
+ attribute against the value(s) of the corresponding "xxx-
+ supported" Printer attribute. Table 6 summarizes those
+ validation rules depending on each attribute syntax and value
+ of an "xxx" attribute supplied in the request and that of the
+ corresponding "xxx-supported" Printer attribute. The "xxx-
+ supported" attribute syntax type and attribute value(s) are
+ obtained from a Get-Printer-Supported-Values response (see
+ Appendix B: Attributes returned from Get-Printer-Supported-
+ Values below).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 41]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 6 - Validation rules for 'From Get-Printer-Supported-Values'
+
+ Type of -
+ "xxx" supported" value Validates if:
+ value to
+ be set Type of "xxx
+
+
+ integer rangeOfInteger each 'integer' value is in one of
+ the "xxx-supported" ranges
+
+ uri uriScheme the uri scheme of each value
+ matches one of the "xxx-supported"
+ schemes
+
+ any boolean if the boolean "xxx-supported" is
+ 'true'
+
+ name 'admin-define' any 'name' value matches
+ out-of-band
+ value
+
+ any same type each value matches an "xxx-
+ supported" value of the same type
+
+ For additional non-normative explanatory information see section
+ 3.1.2.3 of the "Internet Printing Protocol/1.1: Implementer's Guide"
+ [RFC3196].
+
+ 4. Any value of the proper attribute syntax: the Set-Printer-
+ Attributes or Set-Job-Attributes operation accepts any value of
+ the specified attribute syntax. The attribute syntaxes
+ supported are enumerated below.
+
+ a. Any text(127)
+ b. Any name(127)
+ c. Any uri
+ d. Any boolean
+ e. Any positive integer
+ f. Any dateTime
+ g. 1setOf any uri
+
+ 5. Combination of 'Any of "xxx-supported"' or 'Any name'. If a
+ Printer implementation doesn't want to allow setting values
+ indicated in this Appendix as "any xxx", it can make the value
+ be not-settable.
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 42]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 7 - Values allowed for Job Template Attributes in the
+ Set-Job-Attributes Operation
+
+ Job Template Attributes Values allowed for
+ Set
+
+ job-priority (integer(1:100)) Any of "xxx-
+ supported"
+
+ job-hold-until (type3 keyword | name (MAX)) Any of "xxx-
+ supported"
+
+ job-sheets (type3 keyword | name(MAX)) Any of "xxx-
+ supported"
+
+ multiple-document-handling (type2 keyword) Any of "xxx-
+ supported"
+
+ copies (integer(1:MAX)) Any of "xxx-
+ supported"
+
+ finishings (1setOf type2 enum) Any of "xxx-
+ supported"
+
+ page-ranges (1setOf rangeOfInteger (1:MAX)) Any of "xxx-
+ supported"
+
+ sides (type2 keyword) Any of "xxx-
+ supported"
+
+ number-up (integer(1:MAX)) Any of "xxx-
+ supported"
+
+ orientation-requested (type2 enum) Any of "xxx-
+ supported"
+
+ media (type3 keyword | name(MAX)) Any of "xxx-
+ supported"
+
+ printer-resolution (resolution) Any of "xxx-
+ supported"
+
+ print-quality (type2 enum) Any of "xxx-
+ supported"
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 43]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 8 - Values allowed for Job Description Attributes in the
+ Set-Job-Attributes Operation
+
+ Job Description Attributes Values allowed for
+ Set
+
+ job-uri (uri) READ-ONLY
+
+ job-id (integer(1:MAX)) READ-ONLY
+
+ job-printer-uri (uri) READ-ONLY
+
+ job-more-info (uri) READ-ONLY
+
+ job-name (name(MAX)) Any name(MAX)
+
+ job-originating-user-name (name(MAX)) READ-ONLY
+
+ job-state (type1 enum) READ-ONLY
+
+ job-state-reasons (1setOf type2 keyword) READ-ONLY
+
+ job-state-message (text(MAX)) READ-ONLY
+
+ job-detailed-status-messages (1setOf READ-ONLY
+ text(MAX))
+
+ job-document-access-errors (1setOf READ-ONLY
+ text(MAX))
+
+ number-of-documents (integer(0:MAX)) READ-ONLY
+
+ output-device-assigned (name(127)) READ-ONLY
+
+ time-at-creation (integer(MIN:MAX)) READ-ONLY
+
+ time-at-processing (integer(MIN:MAX)) READ-ONLY
+
+ time-at-completed (integer(MIN:MAX)) READ-ONLY
+
+ job-printer-up-time (integer(1:MAX)) READ-ONLY
+
+ date-time-at-creation (dateTime) READ-ONLY
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 44]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Job Description Attributes Values allowed for
+ Set
+
+ date-time-at-processing (dateTime) READ-ONLY
+
+ date-time-at-completed (dateTime) READ-ONLY
+
+ number-of-intervening-jobs (integer(0:MAX)) READ-ONLY
+
+ job-message-from-operator (text(127)) Any text(127)
+
+ job-k-octets (integer(0:MAX)) READ-ONLY
+
+ job-impressions (integer(0:MAX)) READ-ONLY
+
+ job-media-sheets (integer(0:MAX)) READ-ONLY
+
+ job-k-octets-processed (integer(0:MAX)) READ-ONLY
+
+ job-impressions-completed (integer(0:MAX)) READ-ONLY
+
+ job-media-sheets-completed (integer(0:MAX)) READ-ONLY
+
+ attributes-charset (charset) READ-ONLY
+
+ attributes-natural-language READ-ONLY
+ (naturalLanguage)
+
+ Table 9 - Values allowed for Printer Job Template Attributes in
+ the Set-Printer-Attributes Operation
+
+ Printer Job Template Attributes Values allowed
+ for Set
+
+ job-priority-default (integer(1:100)) Any of "xxx-
+ supported"
+
+ job-hold-until-default (type3 keyword | name Any of "xxx-
+ (MAX)) supported"
+
+ job-sheets-default (type3 keyword | name(MAX)) Any of "xxx-
+ supported"
+
+ multiple-document-handling-default (type2 Any of "xxx-
+ keyword) supported"
+
+ copies-default (integer(1:MAX)) Any of "xxx-
+ supported"
+
+
+
+Hastings, et. al. Standards Track [Page 45]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Job Template Attributes Values allowed
+ for Set
+
+ finishings-default (1setOf type2 enum) Any of "xxx-
+ supported"
+
+ sides-default (type2 keyword) Any of "xxx-
+ supported"
+
+ number-up-default (integer(1:MAX)) Any of "xxx-
+ supported"
+
+ orientation-requested-default (type2 enum) Any of "xxx-
+ supported"
+
+ media-default (type3 keyword | name(MAX)) Any of "xxx-
+ supported"
+
+ printer-resolution-default (resolution) Any of "xxx-
+ supported"
+
+ print-quality-default (type2 enum) Any of "xxx-
+ supported"
+
+ job-priority-supported (integer(1:100)) From Get-
+ Printer-
+ Supported-Values
+
+ job-hold-until-supported (1setOf(type3 keyword From Get-
+ | name (MAX))) Printer-
+ Supported-Values
+
+ job-sheets-supported (1setOf(type3 keyword | From Get-
+ name(MAX))) Printer-
+ Supported-Values
+
+ multiple-document-handling-supported (1setOf From Get-
+ type2 keyword) Printer-
+ Supported-Values
+
+ copies-supported (rangeOfInteger(1:MAX)) From Get-
+ Printer-
+ Supported-Values
+
+ finishings-supported (1setOf type2 enum) From Get-
+ Printer-
+ Supported-Values
+
+
+
+
+Hastings, et. al. Standards Track [Page 46]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Job Template Attributes Values allowed
+ for Set
+
+ page-ranges-supported (boolean) From Get-
+ Printer-
+ Supported-Values
+
+ sides-supported (1setOf type2 keyword) From Get-
+ Printer-
+ Supported-Values
+
+ number-up-supported (1setOf (integer(1:MAX) | From Get-
+ rangeOfInteger(1:MAX))) Printer-
+ Supported-Values
+
+ orientation-requested-supported (1setOf type2 From Get-
+ enum) Printer-
+ Supported-Values
+
+ media-supported (1setOf (type3 keyword | From Get-
+ name(MAX))) Printer-
+ Supported-Values
+
+ printer-resolution-supported (1setOf From Get-
+ resolution) Printer-
+ Supported-Values
+
+ print-quality-supported (1setOf type2 enum) From Get-
+ Printer-
+ Supported-Values
+
+ media-ready (type3 keyword | name(MAX)) From Get-
+ Printer-
+ Supported-Values
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 47]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 10 - Values allowed for Printer Description Attributes in
+ the Set-Printer-Attributes Operation
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ printer-uri-supported (1setOf uri) READ-ONLY
+
+ uri-authentication-supported (1setOf type2 READ-ONLY
+ keyword)
+
+ uri-security-supported (1setOf type2 READ-ONLY
+ keyword)
+
+ printer-xri-supported (1setOf collection)
+ member attributes:
+
+ xri-uri (uri) any uriScheme of
+ "xri-uri-scheme-
+ supported" from
+ Get-Printer-
+ Attributes
+
+ xri-authentication (type2 keyword) any keyword of
+ "xri-
+ authentication-
+ supported" from
+ Get-Printer-
+ Attributes
+
+ xri-security (type2 keyword) any keyword of
+ "xri-security-
+ supported" from
+ Get-Printer-
+ Attributes
+
+ xri-uri-scheme-supported (1setOf uriScheme) READ-ONLY
+
+ xri-authentication-supported (1setOf type2 READ-ONLY
+ keyword)
+
+ xri-security-supported (1setOf type2 READ-ONLY
+ keyword)
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 48]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ printer-name (name(127)) Any name(127)
+
+ printer-location (text(127)) Any text(127)
+
+ printer-info (text(127)) Any text(127)
+
+ printer-more-info (uri) Any uri
+
+ printer-driver-installer (uri) Any uri
+
+ printer-make-and-model (text(127)) Any text(127)
+
+ printer-more-info-manufacturer (uri) Any uri
+
+ printer-state (type1 enum) READ-ONLY
+
+ printer-state-reasons (1setOf type2 READ-ONLY
+ keyword)
+
+ printer-state-message (text(MAX)) READ-ONLY
+
+ ipp-versions-supported (1setOf type2 From Get-Printer-
+ keyword) Supported-Values
+
+ operations-supported (1setOf type2 enum) From Get-Printer-
+ Supported-Values
+
+ multiple-document-jobs-supported (boolean) From Get-Printer-
+ Supported-Values
+
+ charset-configured (charset) Any of "xxx-
+ supported", use
+ "charset-supported"
+
+ charset-supported (1setOf charset) From Get-Printer-
+ Supported-Values
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 49]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ natural-language-configured Any of "xxx-
+ (naturalLanguage) supported", use
+ "generated-natural-
+ language-supported"
+
+ generated-natural-language-supported From Get-Printer-
+ (1setOf naturalLanguage) Supported-Values
+
+ document-format-default (mimeMediaType) Any of "xxx-
+ supported"
+
+ document-format-supported (1setOf From Get-Printer-
+ mimeMediaType) Supported-Values
+
+ printer-is-accepting-jobs (boolean) READ-ONLY
+
+ queued-job-count (integer(0:MAX)) READ-ONLY
+
+ printer-message-from-operator (text(127)) Any text(127)
+
+ color-supported (boolean) From Get-Printer-
+ Supported-Values
+
+ reference-uri-schemes-supported (1setOf From Get-Printer-
+ uriScheme) Supported-Values
+
+ pdl-override-supported (type2 keyword) From Get-Printer-
+ Supported-Values
+
+ printer-up-time (integer(1:MAX)) READ-ONLY
+
+ printer-current-time (dateTime) Any dateTime **
+
+ multiple-operation-time-out any positive
+ (integer(1:MAX)) integer
+
+ compression-supported (1setOf type3 From Get-Printer-
+ keyword) Supported-Values
+
+ job-k-octets-supported From Get-Printer-
+ (rangeOfInteger(0:MAX)) Supported-Values
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 50]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ job-impressions-supported From-Get-Printer-
+ (rangeOfInteger(0:MAX)) Supported-Values
+
+ job-media-sheets-supported From Get-Printer-
+ (rangeOfInteger(0:MAX)) Supported-Values
+
+ pages-per-minute (integer(0:MAX)) READ-ONLY
+
+ pages-per-minute-color (integer(0:MAX)) READ-ONLY
+
+ printer-settable-attributes-supported From Get-Printer-
+ (1setOf type2 keyword) Supported-Values
+
+ job-settable-attributes-supported (1setOf From Get-Printer-
+ type2 keyword) Supported-Values
+
+ document-format-varying-attributes (1setOf READ-ONLY
+ type2 keyword)
+
+ printer-message-time (integer(MIN:MAX)) READ-ONLY
+
+ printer-message-date-time(dateTime) READ-ONLY
+
+ ** - The "printer-current-time" (dateTime) attribute is settable in
+ order to allow an administrator to correct an incorrect dateTime or
+ time zone.
+
+Appendix B: Attributes returned from Get-Printer-Supported-Values
+ (Normative)
+
+ This Appendix is a normative part of this document and lists all the
+ attributes that are possible for an implementation to return in a
+ Get-Printer-Supported-Values response, i.e., all the "xxx-supported"
+ attributes that can be supplied in a Set-Printer-Attributes request.
+ READ-ONLY attributes MUST NOT be returned in a Get-Printer-
+ Supported-Values response and are indicated in the tables as "READ-
+ ONLY - MUST NOT be returned."
+
+ For the following attributes, the value allowed by the Set-Printer-
+ Attributes operation MUST be a single integer value in the range
+ specified by the value returned by the Get-Printer-Supported-Values
+ operation.
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 51]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 11 - Printer Job Template Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Job Template Attributes Values Returned
+
+ job-priority-supported (integer(1:100)) rangeOfInteger(1:100)
+
+ For the following attributes, the value allowed by the Set-Printer-
+ Attributes operation MUST be a single rangeOfInteger value whose
+ bounds do not exceed those of the range specified by the value
+ returned by the Get-Printer-Supported-Values operation.
+
+ Table 12 - Printer Job Template Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Job Template Attributes Values Returned
+
+ copies-supported (rangeOfInteger(1:MAX)) rangeOfInteger(1:MAX)
+
+ The following table has the same criteria as the last, but is for
+ Printer Description attributes.
+
+ Table 13 - Printer Description Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Description Attributes Values allowed for Set
+
+ job-k-octets-supported rangeOfInteger(0:MAX)
+ (rangeOfInteger(0:MAX))
+
+ job-impressions-supported
+ (rangeOfInteger(0:MAX)) rangeOfInteger(0:MAX)
+
+ job-media-sheets-supported rangeOfInteger(0:MAX)
+ (rangeOfInteger(0:MAX))
+
+ For the following attributes, the value allowed by the Set-Printer-
+ Attributes operation MUST be one or more integers and rangeOfInteger
+ values, such that the integer values described by these integers and
+ rangeOfInteger is the same as or a subset of the integers described
+ by the integers and rangeOf Integer of values returned by the Get-
+ Printer-Supported-Values operation.
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 52]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Table 14 - Printer Job Template Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Job Template Attributes Values Returned
+
+ number-up-supported (1setOf (integer(1:MAX) 1setOf
+ | rangeOfInteger(1:MAX))) (integer(1:MAX) |
+ rangeOfInteger(1:MA
+ X))
+
+ For the following attributes, the value allowed by the Set-Printer-
+ Attributes operation MUST be one or more values, where each such
+ value matches a value returned by the Get-Printer-Supported-Values
+ operation. A keyword, enum, boolean, charset, naturalLanguage,
+ uriScheme, mimeMediaType or resolution value matches if it is equal.
+ For Job Template attributes, with the attribute syntax 'type3 keyword
+ | name', any 'name' attribute syntax value matches the 'admin-define'
+ out-of-band value, if the implementation allows the administrator to
+ set any name values for the attribute.
+
+ Table 15 - Printer Job Template Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Job Template Attributes Values Returned
+
+ job-hold-until-supported (1setOf(type3 1setOf (type3
+ keyword | name (MAX))) keyword | 'admin-
+ define')
+
+ job-sheets-supported (1setOf(type3 keyword 1setOf (type3
+ | name(MAX))) keyword | 'admin-
+ define')
+
+ multiple-document-handling-supported 1setOf type2
+ (1setOf type2 keyword) keyword
+
+ finishings-supported (1setOf type2 enum) 1setOf type2 enum
+
+ page-ranges-supported (boolean) 1setOf boolean **
+
+ sides-supported (1setOf type2 keyword) 1setOf type2
+ keyword
+
+ orientation-requested-supported (1setOf 1setOf type2 enum
+ type2 enum)
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 53]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Job Template Attributes Values Returned
+
+ media-supported (1setOf (type3 keyword | 1setOf (type3
+ name(MAX))) keyword | 'admin-
+ define')
+
+ printer-resolution-supported (1setOf 1setOf resolution
+ resolution)
+
+ print-quality-supported (1setOf type2 enum) 1setOf type2 enum
+
+ ** Note: the Get-Printer-Supported-Values returns a '1setOf boolean'
+ so that all possible values are indicated, while ** Get-Printer-
+ Attributes returns only a single 'boolean' value.
+
+ The following table has the same criteria as the last, but is for
+ Printer Description attributes.
+
+ Table 16 - Printer Description Attributes returned from
+ Get-Printer-Supported-Values
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ printer-uri-supported (1setOf uri) READ-ONLY - MUST
+ NOT be returned
+
+ uri-authentication-supported (1setOf type2 READ-ONLY - MUST
+ keyword) NOT be returned
+
+ uri-security-supported (1setOf type2 READ-ONLY - MUST
+ keyword) NOT be returned
+
+ printer-xri-supported (1setOf collection) MUST NOT be
+ returned; see next
+ three attributes
+ returned with Get-
+ Printer-Attributes:
+
+ xri-uri-scheme-supported (1setOf uriScheme) READ-ONLY - MUST
+ NOT be returned
+
+ xri-authentication-supported (1setOf type2 READ-ONLY - MUST
+ keyword) NOT be returned
+
+ xri-security-supported (1setOf type2 READ-ONLY - MUST
+ keyword) NOT be returned
+
+
+
+
+Hastings, et. al. Standards Track [Page 54]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ Printer Description Attributes Values allowed for
+ Set
+
+ ipp-versions-supported (1setOf type2 1setOf type2
+ keyword) keyword
+
+ operations-supported (1setOf type2 enum) 1setOf type2
+ keyword
+
+ multiple-document-jobs-supported (boolean) 1setOf boolean **
+
+ charset-supported (1setOf charset) 1setOf charset
+
+ generated-natural-language-supported 1setOf
+ (1setOf naturalLanguage) naturalLanguage
+
+ document-format-supported (1setOf 1setOf
+ mimeMediaType) mimeMediaType
+
+ color-supported (boolean) 1setOf boolean **
+
+ reference-uri-schemes-supported (1setOf 1setOf uriScheme
+ uriScheme)
+
+ pdl-override-supported (type2 keyword) 1setOf type2
+ keyword **
+
+ compression-supported (1setOf type3 1setOf type3
+ keyword) keyword
+
+ printer-settable-attributes-supported 1setOf type2
+ (1setOf type2 keyword) keyword
+
+ job-settable-attributes-supported (1setOf 1setOf type2
+ type2 keyword) keyword
+
+ ** Note: the Get-Printer-Supported-Values returns a '1setOf X' so
+ that all possible values are indicated, while Get-Printer-Attributes
+ returns only a single 'X' value.
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 55]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+Appendix C: Description of the Base IPP Documents (Informative)
+
+ The base set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics [RFC2911]
+ Internet Printing Protocol/1.1: Encoding and Transport [RFC2910]
+ Internet Printing Protocol/1.1: Implementer's Guide [RFC3196]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0 [RFC2566, RFC2565]. A few OPTIONAL operator
+ operations have been added to IPP/1.1 [RFC2911, RFC2910].
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specification documents, and gives background and rationale
+ for the IETF IPP working group's major decisions.
+
+ The "Internet Printing Protocol/1.1: Model and Semantics" document
+ describes a simplified model with abstract objects, their attributes,
+ and their operations. The model introduces a Printer and a Job. The
+ Job supports multiple documents per Job. The model document also
+ addresses how security, internationalization, and directory issues
+ are addressed.
+
+ The "Internet Printing Protocol/1.1: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1 [RFC2616]. It also defines the
+ encoding rules for a new Internet MIME media type called
+ "application/ipp". This document also defines the rules for
+ transporting over HTTP, a message body whose Content-Type is
+ "application/ipp". This document defines the 'ipp' scheme for
+ identifying IPP printers and jobs.
+
+ The "Internet Printing Protocol/1.1: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.1 and some of
+ the considerations that may assist them in the design of their client
+
+
+
+
+Hastings, et. al. Standards Track [Page 56]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions are also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+Authors' Addresses
+
+ Carl Kugler
+ IBM
+ P.O. Box 1900
+ Boulder, CO 80301-9191
+
+ Phone: (303) 924-5060
+ EMail: kugler@us.ibm.com
+
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St. ESAE 231
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Robert Herriot
+ Consultant
+ 706 Colorado Ave
+ Palo Alto, CA 94303
+
+ Phone: 650-327-4466
+ Fax: 650-327-4466
+ EMail: bob@Herriot.com
+
+
+ Harry Lewis
+ IBM
+ 6300 Diagonal Hwy.
+ Boulder, CO 80301-9191
+
+ Phone: (303) 924-5337
+ EMail: harryl@us.ibm.com
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 57]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+ IPP Web Page: http://www.pwg.org/ipp/
+ IPP Mailing List: ipp@pwg.org
+
+ To subscribe to the ipp mailing list, send the following email:
+
+ 1) send it to majordomo@pwg.org
+ 2) leave the subject line blank
+ 3) put the following two lines in the message body:
+ subscribe ipp
+ end
+
+ Implementers of this specification document are encouraged to join
+ the IPP Mailing List in order to participate in any discussions of
+ clarification issues and review of registration proposals for
+ additional attributes and values. In order to reduce spam the
+ mailing list rejects mail from non-subscribers, so you must subscribe
+ to the mailing list in order to send a question or comment to the
+ mailing list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 58]
+
+RFC 3380 IPP: Job and Printer Set Operations September 2002
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 59]
+
diff --git a/standards/rfc3381.txt b/standards/rfc3381.txt
new file mode 100644
index 000000000..d7fd60f81
--- /dev/null
+++ b/standards/rfc3381.txt
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group T. Hastings
+Request for Comments: 3381 Xerox Corporation
+Updates: 2910 H. Lewis
+Category: Standards Track IBM Printing Company
+ R. Bergman
+ Hitachi Koki Imaging Solutions
+ September 2002
+
+
+ Internet Printing Protocol (IPP):
+ Job Progress Attributes
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document defines four new Job Description attributes for
+ monitoring job progress to be registered as OPTIONAL extensions to
+ the Internet Printing Protocol (IPP/1.0 and IPP/1.1). These
+ attributes are drawn from the PWG Job Monitoring MIB. This document
+ also defines a new "sheet-collate" Job Template attribute to control
+ sheet collation and to help with the interpretation of the job
+ progress attributes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 1]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+Table of Contents
+
+ 1 Introduction.....................................................2
+ 2 Terminology......................................................2
+ 2.1 Conformance Terminology........................................4
+ 2.2 Other terminology..............................................4
+ 3 Job Template attributes..........................................4
+ 3.1 sheet-collate (type2 keyword)..................................4
+ 4 IPP Job Description attributes for monitoring Job Progress.......6
+ 4.1 job-collation-type (type2 enum)................................9
+ 4.2 sheet-completed-copy-number (integer(0:MAX))..................11
+ 4.3 sheet-completed-document-number (integer(0:MAX))..............11
+ 4.4 impressions-completed-current-copy (integer(0:MAX))...........11
+ 5 Conformance Requirements........................................11
+ 6 IANA Considerations.............................................12
+ 6.1 Attributes....................................................
+ 6.2 Keyword Attribute Values......................................
+ 6.3 Enum Attribute Values.........................................
+ 7 Internationalization Considerations.............................12
+ 8 Security Considerations.........................................12
+ 9 References......................................................12
+ 10 Description of the Base IPP Documents..........................13
+ 11 Authors' Addresses.............................................15
+ 12 Full Copyright Statement.......................................16
+
+1 Introduction
+
+ This document defines four new Job Description attributes for
+ monitoring job progress to be registered as OPTIONAL extensions to
+ IPP/1.0 [RFC2566] and IPP/1.1 [RFC2911]. These attributes are drawn
+ from the PWG Job Monitoring MIB [RFC2707]. See section 10 for a
+ description of the base IPP documents. The new Job Description
+ attributes are:
+
+ "job-collation-type" (type2 enum)
+ "sheet-completed-copy-number" (integer(0:MAX))
+ "sheet-completed-document-number" (integer(0:MAX))
+ "impressions-completed-current-copy" (integer(0:MAX))
+
+ This document also defines a new "sheet-collate" Job Template
+ attribute to control sheet collation and to help with the
+ interpretation of the job progress attributes. These new attributes
+ may also be used by themselves in combination with the IPP/1.1 "job-
+ impressions-completed" attribute, as useful job progress monitoring
+ attributes and/or may be passed in an IPP Notification (see [ipp-
+ ntfy]).
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 2]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+2 Terminology
+
+ This section defines terminology used throughout this document.
+
+2.1 Conformance Terminology
+
+ Capitalized terms, such as MUST, MUST NOT, REQUIRED, SHOULD, SHOULD
+ NOT, MAY, NEED NOT, and OPTIONAL, have special meaning relating to
+ conformance, as defined in RFC 2119 [RFC2119] and [RFC2911] section
+ 12.1. If an implementation supports the extension defined in this
+ document, then these terms apply; otherwise, they do not. These
+ terms define conformance to this document only; they do not affect
+ conformance to other documents, unless explicitly stated otherwise.
+
+2.2 Other terminology
+
+ This document uses terms such as Job object (or Job), IPP Printer
+ object (or Printer), "operation", "attribute", "keyword", "support",
+ and "impression". These terms have special meaning and are defined
+ in the model terminology [RFC2911], section 12.2.
+
+3 Job Template attributes
+
+3.1 sheet-collate (type2 keyword)
+
+ +===================+======================+=====================+
+ | Job Attribute |Printer: Default Value| Printer: Supported |
+ | | Attribute | Values Attribute |
+ +===================+======================+=====================+
+ | sheet-collate | sheet-collate-default| sheet-collate- |
+ | (type2 keyword) | (type2 keyword) | supported (1setOf |
+ | | | type2 keyword) |
+ +-------------------+----------------------+---------------------+
+
+ This attribute specifies whether or not the media sheets of each copy
+ of each printed document in a job are to be in sequence, when
+ multiple copies of the document are specified by the 'copies'
+ attribute.
+
+ Standard keyword values are:
+
+ 'uncollated': each print-stream sheet is printed a number of
+ times in succession equal to the value of the 'copies'
+ attribute, followed by the next print-stream sheet.
+
+ 'collated': each copy of each document is printed with the
+ print-stream sheets in sequence, followed by the next document
+ copy.
+
+
+
+Hastings, et. al. Standards Track [Page 3]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ For example, suppose a document produces two media sheets as output,
+ and "copies" is equal to '6'. For the 'uncollated' case, six copies
+ of the first media sheet are printed, followed by six copies of the
+ second media sheet. For the 'collated' case, one copy of each of the
+ six sheets is printed, followed by another copy of each of the six
+ media sheets.
+
+ Whether the effect of sheet collation is achieved by placing copies
+ of a document in multiple output bins, or in the same output bin with
+ implementation defined document separation, is implementation
+ dependent. Also whether it is achieved by making multiple passes
+ over the job or by using an output sorter, is implementation
+ dependent.
+
+ Note: IPP/1.0 [RFC2566] and IPP/1.1 [RFC2911] are silent on whether
+ or not sheets within documents are collated. The "sheet-collate-
+ supported" Printer attribute permits a Printer object to indicate
+ whether or not it collates sheets with each document and whether it
+ allows the client to control sheet collation. An implementation is
+ able to indicate that it supports uncollated sheets, collated sheets,
+ or both, using the 'uncollated', 'collated', or both 'uncollated' and
+ 'collated' values, respectively.
+
+ This attribute is affected by "multiple-document-handling". The
+ "multiple-document-handling" attribute describes the collation of
+ documents, and the "sheet-collate" attribute describes the semantics
+ of collating individual pages within a document. To better explain
+ the interaction between these two attributes, the term "set" is
+ introduced. A "set" is a logical boundary between the delivered
+ media sheets of a printed job. For example, in the case of a ten
+ page single document with collated pages and a request for 50 copies,
+ each of the 50 printed copies of the document constitutes a "set".
+ In the above example if the pages were uncollated, then 50 copies of
+ each of the individual pages within the document would represent each
+ "set".
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 4]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ The following table describes the interaction of "sheet-collate" with
+ multiple document handling.
+
+ "sheet- "multiple- Semantics
+ collate" document-
+ handling"
+
+ 'collated' 'single- Each copy of the concatenated
+ document' documents, with their pages in
+ sequence, represents a "set".
+
+ 'collated' 'single- Each copy of the concatenated
+ document-new- documents, with their pages in
+ sheet' sequence, represents a "set".
+
+ 'collated' 'separate- Each copy of each separate
+ documents- document, with its pages in
+ collated- sequence, represents a "set".
+ copies'
+
+ 'collated' 'separate- Each copy of each separate
+ documents- document, with its pages in
+ uncollated- sequence, represents a "set".
+ copies
+
+ 'uncollated' 'single- Each media sheet of the document
+ document' is printed a number of times equal
+ to the "copies" attribute; which
+ constitutes a "set".
+
+ 'uncollated' 'single- Each media sheet of the
+ document-new- concatenated documents is printed
+ sheet' a number of times equal to the
+ "copies" attribute; which
+ constitutes a "set".
+
+ 'uncollated' 'separate- This is a degenerate case, and the
+ documents- printer object MUST reject the job
+ collated- and return the status, "client-
+ copies' error-conflicting-attributes".
+
+ 'uncollated' 'separate- This is a degenerate case, and the
+ documents- printer object MUST reject the job
+ uncollated- and return the status "client-
+ copies error-conflicting-attributes".
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 5]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ From the above table it is obvious that the implicit value of the
+ "sheet-collate" attribute in a printer that does not support the
+ "sheet-collate" attribute, is 'collated.' The semantics of
+ "multiple-document-handling" are otherwise nonsensical in the case
+ of separate documents.
+
+4 IPP Job Description attributes for monitoring Job Progress
+
+ The following IPP Job Description attributes are proposed to be added
+ to IPP through the type2 registration procedures. They are useful
+ for monitoring the progress of a job. They are also used as
+ attributes in the notification content in a notification report
+ [ipp-ntfy].
+
+ There are a number of Job Description attributes for monitoring the
+ progress of a job. These objects and attributes count the number of
+ K octets, impressions, sheets, and pages requested or completed. For
+ impressions and sheets, "completed" means stacked, unless the
+ implementation is unable to detect when each sheet is stacked, in
+ which case, stacked is approximated when the processing of each sheet
+ is completed. There are objects and attributes for the overall job
+ and for the current copy of the document currently being stacked.
+ For the latter, the rate at which the various objects and attributes
+ count, depends on the sheet and document collation of the job.
+
+ Consider the following four Job Description attributes that are used
+ to monitor the progress of a job's impressions:
+
+ 1. "job-impressions-completed" - counts the total number of
+ impressions stacked for the job (see [RFC2911] section
+ 4.3.18.2).
+
+ 2. "impressions-completed-current-copy" - counts the number of
+ impressions stacked for the current document copy.
+
+ 3. "sheet-completed-copy-number" - identifies the number of the
+ copy for the current document being stacked, where the first
+ copy is 1.
+
+ 4. "sheet-completed-document-number" - identifies the current
+ document within the job that is being stacked, where the first
+ document in a job is 1. NOTE: this attribute SHOULD NOT be
+ implemented for implementations that only support one document
+ per job.
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 6]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ For each of the three types of job collation, a job with three copies
+ of two documents (1, 2), where each document consists of 3
+ impressions, the four variables have the following values, as each
+ sheet is stacked for one-sided printing:
+
+ "job-collation-type" = 'uncollated-sheets(3)'
+
+ "job- "impressions- "sheet- "sheet-
+ impressions- completed- completed- completed-
+ completed" current-copy" copy-number" document-
+ number"
+
+ 0 0 0 0
+ 1 1 1 1
+ 2 1 2 1
+ 3 1 3 1
+ 4 2 1 1
+ 5 2 2 1
+ 6 2 3 1
+ 7 3 1 1
+ 8 3 2 1
+ 9 3 3 1
+ 10 1 1 2
+ 11 1 2 2
+ 12 1 3 2
+ 13 2 1 2
+ 14 2 2 2
+ 15 2 3 2
+ 16 3 1 2
+ 17 3 2 2
+ 18 3 3 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 7]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ "job-collation-type" = 'collated-documents(4)'
+
+ "job- "impressions- "sheet- "sheet-
+ impressions- completed- completed- completed-
+ completed" current-copy" copy- document-
+ number" number"
+
+ 0 0 0 0
+ 1 1 1 1
+ 2 2 1 1
+ 3 3 1 1
+ 4 1 1 2
+ 5 2 1 2
+ 6 3 1 2
+ 7 1 2 1
+ 8 2 2 1
+ 9 3 2 1
+ 10 1 2 2
+ 11 2 2 2
+ 12 3 2 2
+ 13 1 3 1
+ 14 2 3 1
+ 15 3 3 1
+ 16 1 3 2
+ 17 2 3 2
+ 18 3 3 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 8]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ "job-collation-type" = 'uncollated-documents(5)'
+
+ "job- "impressions- "sheet- "sheet-
+ impressions- completed- completed- completed-
+ completed" current-copy" copy-t document-
+ number" number"
+
+ 0 0 0 0
+ 1 1 1 1
+ 2 2 1 1
+ 3 3 1 1
+ 4 1 2 1
+ 5 2 2 1
+ 6 3 2 1
+ 7 1 3 1
+ 8 2 3 1
+ 9 3 3 1
+ 10 1 1 2
+ 11 2 1 2
+ 12 3 1 2
+ 13 1 2 2
+ 14 2 2 2
+ 15 3 2 2
+ 16 1 3 2
+ 17 2 3 2
+ 18 3 3 2
+
+4.1 job-collation-type (type2 enum)
+
+ Job Collation includes sheet collation and document collation. Sheet
+ collation is defined to be the ordering of sheets within a document
+ copy. Document collation is defined to be the ordering of document
+ copies within a multi-document job. The value of the "job-
+ collation-type" is affected by the value of the "sheet-collate" Job
+ Template attribute (see section 3.1), if supplied and supported.
+
+ The Standard enum values are:
+
+ '1' 'other': not one of the defined values
+
+ '2' 'unknown': the collation type is unknown
+
+ '3' 'uncollated-sheets': No collation of the sheets within each
+ document copy, i.e., each sheet of a document that
+ is to produce multiple copies, is replicated before
+ the next sheet in the document is processed and
+ stacked. If the device has an output bin collator,
+ the 'uncollated-sheets(3)' value may actually
+
+
+
+Hastings, et. al. Standards Track [Page 9]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ produce collated sheets as far as the user is
+ concerned (in the output bins). However, when the
+ job collation is the 'uncollated-sheets(3)' value,
+ job progress is indistinguishable from a monitoring
+ application between a device that has an output bin
+ collator and one that does not.
+
+ '4' 'collated-documents': Collation of the sheets within each
+ document copy is performed within the printing
+ device by making multiple passes over, either the
+ source or an intermediate representation of the
+ document. In addition, when there are multiple
+ documents per job, the i'th copy of each document is
+ stacked before the j'th copy of each document, i.e.,
+ the documents are collated within each job copy.
+ For example, if a job is submitted with documents, A
+ and B, the job is made available to the end user as:
+ A, B, A, B, .... The 'collated-documents(4)' value
+ corresponds to the IPP [RFC2911] 'separate-
+ documents-collated-copies' keyword value of the
+ "multiple-document-handling" attribute.
+
+ If the job's "copies" attribute is '1' (or not
+ supplied), then the "job-collation-type" attribute
+ is defined to be '4'.
+
+ '5' 'uncollated-documents': Collation of the sheets within each
+ document copy is performed within the printing
+ device by making multiple passes over either the
+ source or an intermediate representation of the
+ document. In addition, when there are multiple
+ documents per job, all copies of the first document
+ in the job are stacked before any copied of the next
+ document in the job, i.e., the documents are
+ uncollated within the job. For example, if a job is
+ submitted with documents, A and B, the job is made
+ available to the end user as: A, A, ..., B, B, ....
+ The 'uncollated-documents(5)' value corresponds to
+ the IPP [RFC2911] 'separate-documents-uncollated-
+ copies' keyword value of the "multiple-document-
+ handling" attribute.
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 10]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+4.2 sheet-completed-copy-number (integer(0:MAX))
+
+ The number of the copy being stacked for the current document. This
+ number starts at 0, is set to 1 when the first sheet of the first
+ copy for each document is being stacked and is equal to n where n is
+ the nth sheet stacked in the current document copy. If the value is
+ unknown, the Printer MUST return the 'unknown' out-of-band value (see
+ [RFC2911] section 4.1), rather than the -2 value used in some MIBs
+ [RFC2707].
+
+4.3 sheet-completed-document-number (integer(0:MAX))
+
+ The ordinal number of the document in the job that is currently being
+ stacked. This number starts at 0, increments to 1 when the first
+ sheet of the first document in the job is being stacked, and is equal
+ to n where n is the nth document in the job, starting with 1. If the
+ value is unknown, the Printer MUST return the 'unknown' out-of-band
+ value (see [RFC2911] section 4.1), rather than the -2 value used in
+ some MIBs [RFC2707].
+
+ Implementations that only support one document job SHOULD NOT
+ implement this attribute.
+
+4.4 impressions-completed-current-copy (integer(0:MAX))
+
+ The number of impressions completed by the device for the current
+ copy of the current document so far. For printing, the impressions
+ completed includes interpreting, marking, and stacking the output.
+ For other types of job services, the number of impressions completed
+ includes the number of impressions processed. If the value is
+ unknown, the Printer MUST return the 'unknown' out-of-band value (see
+ [RFC2911] section 4.1), rather than the -2 value used in some MIBs
+ [RFC2707].
+
+ This value MUST be reset to 0 for each document in the job and for
+ each document copy.
+
+5 Conformance Requirements
+
+ This section summarizes the Conformance Requirements detailed in the
+ definitions in this document. In general each of the attributes
+ defined in this document are OPTIONAL for a client and/or a Printer
+ to support, so that client and Printer implementers MAY implement any
+ combination of these attributes.
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 11]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+6 IANA Considerations
+
+ This section contains registration information for IANA to add to the
+ IPP Registry according to the procedures defined in RFC 2911
+ [RFC2911], section 6. The resulting registrations will be published
+ in the http://www.iana.org/assignments/ipp-registrations registry.
+
+6.1 Attributes
+
+ Job Template attributes: Ref. Section:
+ sheet-collate (type2 keyword) RFC 3381 3.1
+ sheet-default (type2 keyword) RFC 3381 3.1
+ sheet-supported (1setOf type2 keyword) RFC 3381 3.1
+
+ Job Description attributes: Ref. Section:
+ job-collation-type (type2 enum) RFC 3381 4.1
+ sheet-completed-copy-number (integer(0:MAX)) RFC 3381 4.2
+ sheet-completed-document-number (integer(0:MAX))RFC 3381 4.3
+ impressions-completed-current-copy (integer(0:MAX))
+ RFC 3381 4.4
+6.2 Keyword Attribute Values
+
+ The following table provides registration information for all of the
+ attributes defined in this document that have keyword values. These
+ keywords are to be registered according to the procedures defined in
+ RFC 2911 [RFC2911] section 6.1.
+
+ sheet-collate (type2 keyword) RFC 3381 3.1
+ 'uncollated' RFC 3381 3.1
+ 'collated' RFC 3381 3.1
+ sheet-collate-default (type2 keyword) RFC 3381 3.1
+ See "sheet-collate" attribute
+ sheet-collate-supported (1setOf type2 keyword) RFC 3381 3.1
+ See "sheet-collate" attribute
+
+6.3 Enum Attribute Values
+
+ The following table provides registration information for all of the
+ attributes defined in this document that have enum values. These
+ enums are to be registered according to the procedures defined in RFC
+ 2911 [RFC2911] section 6.1.
+
+ job-collation-type (type2 enum) RFC 3381 4.1
+ '1' 'other' RFC 3381 4.1
+ '2' 'unknown' RFC 3381 4.1
+ '3' 'uncollated-sheets' RFC 3381 4.1
+ '4' 'collated-documents' RFC 3381 4.1
+ '5' 'uncollated-documents' RFC 3381 4.1
+
+
+
+Hastings, et. al. Standards Track [Page 12]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+7 Internationalization Considerations
+
+ The IPP extensions defined in this document require the same
+ internationalization considerations as any of the Job Template and
+ Job Description attributes defined in IPP/1.1 [RFC2911].
+
+8 Security Considerations
+
+ The IPP extensions defined in this document require the same security
+ considerations as any of the Job Template attributes and Job
+ Description attributes defined in IPP/1.1 [RFC2911].
+
+9 References
+
+9.1 Normative References
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P. and R. Turner,
+ "Internet Printing Protocol/1.1: Encoding and Transport",
+ RFC 2910, September 2000.
+
+ [RFC2911] Hastings, T., Herriot, R., deBry, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.1: Model and
+ Semantics", RFC 2911, September 2000.
+
+9.2 Informative References
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Turner,
+ "Internet Printing Protocol/1.0: Encoding and Transport",
+ RFC 2565, April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2567] Wright, F.D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2707] Bergman, R., Hastings, T., Isaacson, S. and H. Lewis, "PWG
+ Job Monitoring MIB - V1", RFC 2707, November 1999.
+
+
+
+
+Hastings, et. al. Standards Track [Page 13]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ [RFC3196] Hastings, T., Manros, C., Zehler, P., Kugler, C. and H.
+ Holst, "Internet Printing Protocol/1.1: Implementor's
+ Guide", RFC 3196, November 2001.
+
+ [ipp-ntfy] Herriot, R., Hastings, T., et. al., "Internet Printing
+ Protocol (IPP): Event Notification and Subscriptions",
+ Work in Progress.
+
+10 Description of the Base IPP Documents
+
+ The base set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics [RFC2911]
+ Internet Printing Protocol/1.1: Encoding and Transport [RFC2910]
+ Internet Printing Protocol/1.1: Implementer's Guide [RFC3196]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0 [RFC2566, RFC2565]. A few OPTIONAL operator
+ operations have been added to IPP/1.1 [RFC2911, RFC2910].
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specification documents, and gives background and rationale
+ for the IETF IPP working group's major decisions.
+
+ The "Internet Printing Protocol/1.1: Model and Semantics" document
+ describes a simplified model with abstract objects, their attributes,
+ and their operations. The model introduces a Printer and a Job. The
+ Job supports multiple documents per Job. The model document also
+ addresses how security, internationalization, and directory issues
+ are addressed.
+
+ The "Internet Printing Protocol/1.1: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1 [RFC2616]. It also defines the
+ encoding rules for a new Internet MIME media type called
+ "application/ipp". This document also defines the rules for
+ transporting over HTTP a message body whose Content-Type is
+
+
+
+Hastings, et. al. Standards Track [Page 14]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+ "application/ipp". This document defines the 'ipp' scheme for
+ identifying IPP printers and jobs.
+
+ The "Internet Printing Protocol/1.1: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.1 and some of
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+ In addition to the base IPP documents, the "Event Notification
+ Specification" document [ipp-ntfy] defines OPTIONAL operations that
+ allow a client to subscribe to printing related events.
+ Subscriptions include "Per-Job subscriptions" and "Per-Printer
+ subscriptions". Subscriptions are modeled as Subscription objects.
+ Four other operations are defined for subscription objects: get
+ attributes, get subscriptions, renew a subscription, and cancel a
+ subscription.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 15]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+11 Authors' Addresses
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St. ESAE 231
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+ Harry Lewis
+ IBM
+ 6300 Diagonal Hwy
+ Boulder, CO 80301-9191
+
+ Phone: (303) 924-5337
+ EMail: harryl@us.ibm.com
+
+ Ron Bergman (Editor)
+ Hitachi Koki Imaging Solutions
+ 1757 Tapo Canyon Road
+ Simi Valley, CA 93063-3394
+
+ Phone: 805-578-4421
+ Fax: 805-578-4001
+ EMail: rbergma@hitachi-hkis.com
+
+ IPP Web Page: http://www.pwg.org/ipp/
+ IPP Mailing List: ipp@pwg.org
+
+ To subscribe to the ipp mailing list, send the following email:
+
+ 1) send it to majordomo@pwg.org
+ 2) leave the subject line blank
+ 3) put the following two lines in the message body:
+ subscribe ipp
+ end
+
+ Implementers of this specification document are encouraged to join
+ the IPP Mailing List in order to participate in any discussions of
+ clarification issues and review of registration proposals for
+ additional attributes and values. In order to reduce spam, the
+ mailing list rejects mail from non-subscribers, so you must subscribe
+ to the mailing list in order to send a question or comment to the
+ mailing list.
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 16]
+
+RFC 3381 IPP: Job Progress Attributes September 2002
+
+
+12 Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hastings, et. al. Standards Track [Page 17]
+
diff --git a/standards/rfc3382.txt b/standards/rfc3382.txt
new file mode 100644
index 000000000..4181c5bc5
--- /dev/null
+++ b/standards/rfc3382.txt
@@ -0,0 +1,2131 @@
+
+
+
+
+
+
+Network Working Group R. deBry
+Request for Comments: 3382 Utah Valley State College
+Updates: 2910, 2911 R. Herriot
+Category: Standards Track Consultant
+ T. Hastings
+ K. Ocke
+ P. Zehler
+ Xerox Corporation
+ September 2002
+
+
+ Internet Printing Protocol (IPP):
+ The 'collection' attribute syntax
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document specifies an OPTIONAL attribute syntax called
+ 'collection' for use with the Internet Printing Protocol (IPP/1.0 and
+ IPP/1.1). A 'collection' is a container holding one or more named
+ values, which are called "member" attributes. A collection allows
+ data to be grouped like a PostScript dictionary or a Java Map. This
+ document also specifies the conformance requirements for a definition
+ document that defines a collection attribute. Finally, this document
+ gives some illustrative example collection attribute definitions that
+ are not intended as actual attribute specifications.
+
+Table of Contents
+
+ 1 Introduction.....................................................3
+ 1.1 Problem Statement..............................................3
+ 1.2 Solution.......................................................3
+ 2 Terminology......................................................4
+ 2.1 Conformance Terminology........................................4
+ 2.2 Other terminology..............................................5
+ 3 Definition of a Collection Attribute.............................5
+ 3.1 Information to Include.........................................5
+
+
+
+deBry, et. al. Standards Track [Page 1]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ 3.2 Nested Collections.............................................9
+ 4 Collection Attributes as Attributes in Operations................9
+ 4.1 General Rules..................................................9
+ 4.2 Unsupported Values.............................................9
+ 5 Example definition of a collection attribute.....................9
+ 5.1 media-col (collection)........................................10
+ 5.1.1 media-color (type3 keyword | name(MAX)......................10
+ 5.1.2 media-size (collection).....................................11
+ 5.2 media-col-default (collection)................................11
+ 5.3 media-col-ready (1setOf collection)...........................12
+ 5.4 media-col-supported (1setOf type2 keyword)....................12
+ 6 A Second Example Definition Of A Collection Attribute...........12
+ 7 Encoding........................................................13
+ 7.1 Additional tags defined for representing a collection
+ attribute value...............................................13
+ 7.2 Example encoding: "media-col" (collection)....................14
+ 8 Legacy issues...................................................20
+ 9 IANA Considerations.............................................20
+ 10 Internationalization Considerations............................20
+ 11 Security Considerations........................................21
+ 12 References.....................................................21
+ Appendix A: Encoding Example of a Simple Collection (Informative).22
+ Appendix B: Encoding Example of 1setOf Collection (Informative)...25
+ Appendix C: Encoding Example of Collection containing 1setOf XXX
+ attribute (Informative)...............................31
+ Appendix D: Description of the Base IPP Documents (Informative)...35
+ Authors' Addresses................................................36
+ Full Copyright Statement..........................................38
+
+Table of Tables
+
+ Table 1 - "media-col" member attributes...........................10
+ Table 2 - "media-size" collection member attributes...............11
+ Table 3 - Tags defined for encoding the 'collection' attribute
+ syntax .................................................13
+ Table 4 - Overview Encoding of "media-col" collection.............15
+ Table 5 - Example Encoding of "media-col" collection..............16
+ Table 6 - Overview Encoding of simple collection..................22
+ Table 7 - Example Encoding of simple collection...................22
+ Table 8 - Overview Encoding of 1setOf collection..................25
+ Table 9 - Example Encoding of 1setOf collection...................26
+ Table 10 - Overview Encoding of collection with 1setOf value......31
+ Table 11 - Example Encoding of collection with 1setOf value.......32
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 2]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+1 Introduction
+
+ This document is an OPTIONAL extension to IPP/1.0 [RFC2565, RFC2566]
+ and IPP/1.1 [RFC2911, RFC2910]. For a description of the base IPP
+ documents see Appendix D.
+
+1.1 Problem Statement
+
+ The IPP Model and Semantics [RFC2911] supports most of the common
+ data structures that are available in programming languages. It
+ lacks a mechanism for grouping several attributes of different types.
+ The Java language uses the Map to solve this problem and PostScript
+ has a dictionary. The new mechanism for grouping attributes together
+ (called 'collection' mechanism) must allow for optional members and
+ the subsequent addition of new members.
+
+ The 'collection' mechanism must be encoded in a manner consistent
+ with existing 1.0 and 1.1 parsing rules (see [RFC2910]). Current 1.0
+ and 1.1 parsers that don't support the 'collection' mechanism must
+ not confuse collections or parts of a collection they receive with
+ other attributes.
+
+1.2 Solution
+
+ The new mechanism is a new IPP attribute syntax called a
+ 'collection'. As such, each collection value is a value of an
+ attribute whose attribute syntax type is defined to be a
+ 'collection'. Such an attribute is called a collection attribute.
+ The name of the collection attribute serves to identify the
+ collection value in an operation request or response, as with any
+ attribute value.
+
+ The 'collection' attribute syntax is a container holding one or more
+ named values (i.e., attributes), which are called member attributes.
+ Each collection attribute definition document lists the mandatory and
+ optional member attributes of each collection value. A collection
+ value is similar to an IPP attribute group in a request or a
+ response, such as the operation attributes group. They both consist
+ of a set of attributes.
+
+ As with any attribute syntax, the document that defines a collection
+ attribute specifies whether the attribute is single-valued
+ (collection) or multi-valued (1setOf collection). If the attribute
+ is multi-valued (1setOf collection), each collection value MUST be a
+ separate instance of a single definition of a collection, i.e., it
+ MUST have the same member attributes except for OPTIONAL member
+ attributes. If we view each collection definition as a separate
+ syntax type, this rule continues the IPP/1.1 notion that each
+
+
+
+deBry, et. al. Standards Track [Page 3]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ attribute has a single type or pattern (e.g., "keyword | name" is a
+ pattern). Without this rule, the supported values would be more
+ difficult to describe and the mechanism defined in item 4 of section
+ 3.1 would not be sufficient.
+
+ The name of each member attribute MUST be unique for a collection
+ attribute, but MAY be the same as the name of a member attribute in
+ another collection attribute and/or MAY be the same as the name of an
+ attribute that is not a member of a collection. The rules for naming
+ member attributes are given in section 3.1.
+
+ Each member attribute can have any attribute syntax type, including
+ 'collection', and can be either single-valued or multi-valued. The
+ length of a collection value is not limited. However, the length of
+ each member attribute MUST NOT exceed the limit of its attribute
+ syntax.
+
+ The member attributes in a collection MAY be in any order in a
+ request or response. When a client sends a collection attribute to
+ the Printer, the order that the Printer stores the member attributes
+ of the collection value and the order returned in a response MAY be
+ different from the order sent by the client.
+
+ A collection value MUST NOT contain two or more member attributes
+ with the same attribute name. Such a collection is mal-formed.
+ Clients MUST NOT submit such malformed requests and Printers MUST NOT
+ return such malformed responses. If such a malformed request is
+ submitted to a Printer, the Printer MUST (depending on
+ implementation) either (1) reject the request with the 'client-
+ error-bad-request' status code (see [RFC2911] section 13.1.4.1), or
+ (2) accept the request and use only one of each duplicate member
+ attributes.
+
+2 Terminology
+
+ This section defines terminology used throughout this document.
+
+2.1 Conformance Terminology
+
+ Capitalized terms, such as MUST, MUST NOT, REQUIRED, SHOULD, SHOULD
+ NOT, MAY, NEED NOT, and OPTIONAL, have special meaning relating to
+ conformance as defined in BCP 14, RFC 2119 [RFC2119] and [RFC2911],
+ section 12.1. If an implementation supports the extension defined in
+ this document, then these terms apply; otherwise, they do not. These
+ terms define conformance to this document only; they do not affect
+ conformance to other documents, unless explicitly stated otherwise.
+
+
+
+
+
+deBry, et. al. Standards Track [Page 4]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+2.2 Other terminology
+
+ This document uses terms such as Job object (or Job), IPP Printer
+ object (or Printer), "operation", "request", response", "attributes",
+ "keywords", and "support". These terms have special meaning and are
+ defined in the model terminology [RFC2911] section 12.2. The
+ following additional terms are introduced in this document:
+
+ collection: an attribute syntax in which each attribute value is a
+ set of attributes, called member attributes.
+
+ member attribute: an attribute that is defined to be used as one
+ of the attributes in a collection.
+
+ collection attribute: an attribute whose definition specifies the
+ 'collection' attribute syntax and each of the member attributes
+ that MAY occur in a collection attribute value.
+
+3 Definition of a Collection Attribute
+
+ This section describes the requirements for any collection attribute
+ definition.
+
+3.1 Information to Include
+
+ When a specification document defines an "xxx" collection attribute,
+ i.e., an attribute whose attribute syntax type is 'collection' or
+ '1setOf collection'; the definition document MUST include the
+ following aspects of the attribute semantics. Suppose the "xxx"
+ collection attribute contains N member attributes named "aaa1",
+ "aaa2", ..., "aaaN" ("aaaI" represents any one of these N member
+ attributes).
+
+ 1. The name of the collection attribute MUST be specified (e.g.,
+ "xxx"). The selection of the name "xxx" MUST follow the same
+ rules for uniqueness as for attributes of any other syntax type,
+ (as defined by IPP/1.1) unless "xxx" is a member attribute of
+ another collection. Then the selection of the name "xxx" MUST
+ follow the rules for uniqueness defined in item 5a) of this list.
+
+ 2. The collection attribute syntax MUST be of type 'collection' or
+ '1setOf collection'.
+
+ 3. The context of the collection attribute MUST be specified, i.e.,
+ whether the attribute is an operation attribute, a Job Template
+ attribute, a Job Description attribute, a Printer Description
+ attribute, a member attribute of a particular collection
+ attribute, etc.
+
+
+
+deBry, et. al. Standards Track [Page 5]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ 4. An "xxx-supported" attribute MUST be specified and it has one of
+ the following two forms:
+
+ a) "xxx-supported" is a "1setOf collection", which enumerates all
+ of the supported collection values of "xxx". If a collection
+ of this form contains a nested collection, it MUST be of the
+ same form.
+
+ For example, "media-size-supported" might have the values {{x-
+ dimension:210, y-dimension:297},{x-dimension:297, y-
+ dimension:420}} to show that it supports two values of "media
+ size": A4 (210x297) and A3 (297x420). It does not support
+ other combinations of "x-dimension" and "y-dimension" member
+ attributes, such as 210x420 or 297x297, and it does not support
+ non-enumerated values, such as 420x595.
+
+ b) "xxx-supported" is a "1setOf type2 keyword", which enumerates
+ the names of all of the member attributes of "xxx": "aaa1",
+ "aaa2", ..., "aaaN". If a collection of this form contains a
+ nested collection, it MAY be of either form. See item 5f)
+ below for details on supported values of member attributes.
+
+ For example, "media-col-supported" might have the keyword
+ values: "media-size" and "media-color".
+
+ 5. The member attributes MUST be defined. For each member attribute,
+ the definition document MUST provide the following information:
+
+ a) The member attribute's name (e.g., "aaa") MUST be unique within
+ the collection being defined and MUST either:
+
+ i) reuse the attribute name of another attribute (that is
+ unique across the entire IPP attribute name space) and
+ have the same syntax and semantics as the reused attribute
+ (if the condition of item 4b) above is met). For example,
+ a member attribute definition could reuse the IPP/1.1
+ "media" attribute.
+
+ ii) potentially occur elsewhere in the entire IPP attribute
+ name space. (if the condition of item 4a) above is met).
+ For example, a member attribute could be "x-dimension",
+ which could potentially occur in another collection or as
+ an attribute outside of a collection.
+
+ iii) be unique across the entire IPP attribute name space (if
+ the condition of item 4b) above is met). For example, a
+ member attribute could be "media-color" which must be
+ unique across the entire IPP attribute name space.
+
+
+
+deBry, et. al. Standards Track [Page 6]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ b) Whether the member attribute is REQUIRED or OPTIONAL for the
+ Printer to support.
+
+ c) Whether the member attribute is REQUIRED or OPTIONAL for the
+ client to supply in a request.
+
+ d) The member attribute's syntax type, which can be any attribute
+ syntax, including '1setOf X', 'collection', and '1setOf
+ collection'. If this attribute name reuses the name of another
+ attribute (case of item a1 above), it MUST have the same
+ attribute syntax, including cardinality (whether or not
+ 1setOf).
+
+ e) The semantics of the "aaa" member attribute. The semantic
+ definition MUST include a description of any constraint or
+ boundary conditions the member attribute places on the
+ associated attribute, especially if the attribute reuses the
+ name of another attribute (case of item a1 above).
+
+ f) The supported values for each "aaaI" member attribute (of the
+ member attributes "aaa1", "aaa2", ..., "aaaN") is specified by
+ one of two mechanisms.
+
+ i) If "xxx-supported" is a "1setOf collection" (see item 4a)
+ above), the value for each "aaaI" is specified in each
+ collection value of "xxx-supported", in the context of
+ other member attributes. That is, "xxx-supported"
+ enumerates all supported values of "xxx".
+
+ ii) If the value of "xxx-supported" is a "1setOf type2
+ keyword" (see item 4b) above), the supported values of
+ "aaaI" are the values specified by either i) the "aaaI-
+ supported" attribute or ii) the definition of the member
+ attribute "aaaI" within the document defining the "xxx"
+ attribute. The values of each member attribute "aaaI" are
+ specified independently of other member attributes, though
+ a Printer is not required to support all combinations of
+ supported values.
+
+ For example, "media-col-supported" might have the keyword
+ values: "media-size" and "media-color". Using the first
+ method for defining supported values (an "aaaI-supported"
+ attribute), the collection values of "media-col" are
+ combinations of values of "media-size-supported" and
+ "media-color-supported". If "media-size-supported" has
+ the values of '210x297' and '297x420' and "media-color-
+ supported" has the values of 'white' and 'pink', the
+
+
+
+
+deBry, et. al. Standards Track [Page 7]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Printer might support only the combinations 'white-
+ 210x297', 'pink-210x297' and 'white-297x420', and not
+ 'pink-297x420'.
+
+ If a collection contains a member "aaaI", whose syntax
+ type is "text", the supported values would probably be
+ defined by the definition of "xxx" rather than by the
+ attribute "aaaI-supported".
+
+ g) the default value of each "aaaI" member attribute if it is
+ OPTIONAL for a client to supply the "aaa" member attribute in a
+ request. The default value is specified by the attribute's
+ definition within a document and MUST be one of the following:
+
+ i) a fixed default
+
+ ii) a mechanism by which the Printer determines default
+
+ iii) an indefinite default that is left to the implementation.
+
+ iv) an attribute that the Printer uses to determine the
+ default
+
+ 6. The default value of "xxx", if a client does not supply it. The
+ default value is specified by the attribute's definition within a
+ document and MUST be one of the following:
+
+ a) a fixed default
+
+ b) a mechanism by which the Printer determines default
+
+ c) an indefinite default that is left to the implementation
+
+ d) a Printer attribute "xxx-default" which is a collection with
+ the same member attributes as "xxx". If optional member
+ attributes are absent, the Printer uses the defaulting rules of
+ item 5g) above.
+
+ 7. The "xxx-ready (1setOf collection)" attribute, if human
+ intervention is required to make many of the supported values
+ available. For example, "media-col" is an attribute which has a
+ "ready" attribute. Most attributes do not have a "ready"
+ attribute.
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 8]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+3.2 Nested Collections
+
+ A member attribute may have a syntax type of 'collection' or '1setOf
+ collection', in which case it is called a nested collection
+ attribute. The rules for a nested collection attribute are the same
+ as for a collection attribute as specified in section 3.1.
+
+4 Collection Attributes as Attributes in Operations
+
+4.1 General Rules
+
+ A collection value is like any other IPP/1.1 value, except that it is
+ structured. The rules for attributes with collection values are the
+ same as for attributes of any other syntax type (see IPP/1.1), be
+ they in any group of a request of a response.
+
+4.2 Unsupported Values
+
+ The rules for returning an unsupported collection attribute are an
+ extension to the current rules:
+
+ 1. If the entire collection attribute is unsupported, then the
+ Printer returns just the collection attribute name with the
+ 'unsupported' out-of-band value (see the beginning of [RFC2911]
+ section 4.1) in the Unsupported Attributes Group.
+
+ 2. If a collection contains unrecognized, unsupported member
+ attributes and/or conflicting values, the attribute returned in
+ the Unsupported Group is a collection containing the unrecognized,
+ unsupported member attributes, and/or conflicting values. The
+ unrecognized member attributes have an out-of-band value of
+ 'unsupported' (see the beginning of [RFC2911] section 4.1). The
+ unsupported member attributes and conflicting values have their
+ unsupported or conflicting values.
+
+5 Example definition of a collection attribute
+
+ In some printing environments, it is desirable to allow the client to
+ select the media by its properties, e.g., weight, color, size, etc.,
+ instead of by name. In IPP/1.1 (see [RFC2911]), the "media (type3
+ keyword | name) Job Template attribute allows selection by name. It
+ is tempting to extend the "media" attribute syntax to include
+ "collection", but then existing clients could not understand default
+ or supported media values that use the collection value. To preserve
+ interoperability, a new attribute MUST BE added, e.g., "media-col
+ (collection)". The following subsections contain a sample definition
+ of a simplified "media-col" attribute. The definition follows the
+ rules in section 3.
+
+
+
+deBry, et. al. Standards Track [Page 9]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ All of the example attribute definitions in this document are
+ illustrative examples, rather than actual definitions. These
+ examples are intended to illustrate how to define collection
+ attributes. Other documents MUST define collection attributes for
+ use in actual interchange. Such definitions may be very similar to
+ the examples in this document, since we attempted to pick useful
+ examples.
+
+ Note: we picked the name "media-col" because the name "media" is
+ already in use. Ordinarily the collection attribute would have a
+ name like any other attribute and would not end in "col".
+
+ The member attributes of "media-col" attribute ("media-color (type 3
+ keyword)" and "media-size (collection)") both follow the naming rules
+ of item 4a3 of section 3, i.e., the names are unique across the
+ entire IPP attribute name space. The member attributes of the
+ "media-size (collection)" member attribute ("x-dimension
+ (integer(0:MAX))" and "y-dimension (integer(0:MAX))") both follow the
+ naming rules of item 4a2 of section 3, i.e., they potentially occur
+ elsewhere in the IPP attribute name space.
+
+5.1 media-col (collection)
+
+ The "media-col" (collection) attribute augments the IPP/1.1 [RFC2911]
+ "media" attribute. This collection attribute enables a client end
+ user to submit a list of media characteristics to the Printer. When
+ the client specifies media using the "media-col" collection
+ attribute, the Printer object MUST match the requested media exactly.
+ The 'collection' consists of the following member attributes:
+
+ Table 1 - "media-col" member attributes
+
+ Attribute name attribute syntax request Printer
+ Support
+
+ media-color type3 keyword | name (MAX) MAY MUST
+
+ media-size collection MUST MUST
+
+ The definitions for the member attributes is given in the following
+ sub-sections:
+
+5.1.1 media-color (type3 keyword | name(MAX)
+
+ This member attribute identifies the color of the media. Valid
+ values are 'red', 'white' and 'blue'.
+
+
+
+
+
+deBry, et. al. Standards Track [Page 10]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ The "media-color-supported" (1setOf (type3 keyword | name(MAX)))
+ Printer attribute identifies the values of this "media-color" member
+ attribute that the Printer supports, i.e., the colors supported.
+
+ If the client omits this member attribute, the Printer determines the
+ value in an implementation dependent manner.
+
+5.1.2 media-size (collection)
+
+ This member attribute identifies the size of the media. The
+ 'collection' consists of the member attributes shown in Table 2:
+
+ Table 2 - "media-size" collection member attributes
+
+ Attribute name attribute syntax request Printer
+ Support
+
+ x-dimension integer (0:MAX) MUST MUST
+
+ y-dimension integer (0:MAX) MUST MUST
+
+ The definitions for the member attributes are given in the following
+ sub-sections:
+
+5.1.2.1 x-dimension (integer(0:MAX))
+
+ This attribute identifies the width of the media in inch units along
+ the X axis.
+
+5.1.2.2 y-dimension (integer(0:MAX))
+
+ This attribute identifies the height of the media in inch units along
+ the Y axis.
+
+ The "media-size-supported" (1setOf collection) Printer attribute
+ identifies the values of this "media-size" member attribute that the
+ Printer supports, i.e., the size combinations supported. The names
+ of the member attributes are the same as the member attributes of the
+ "media-size" collection attribute, namely "x-dimension", and "y-
+ dimension", since they have the same attribute syntax and the same
+ semantics.
+
+5.2 media-col-default (collection)
+
+ The "media-col-default" Printer attribute specifies the media that
+ the Printer uses, if any, if the client omits the "media-col" and
+ "media". Job Template attributes in the Job Creation operation and
+ the PDL do not include a media specification. The member attributes
+
+
+
+deBry, et. al. Standards Track [Page 11]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ are defined in Table 1. A Printer MUST support the same member
+ attributes for this default collection attribute as it supports for
+ the corresponding "media-col" Job Template attribute.
+
+5.3 media-col-ready (1setOf collection)
+
+ The "media-col-ready" Printer attribute identifies the media that are
+ available for use without human intervention, i.e., the media that
+ are ready to be used without human intervention. The collection
+ value MUST have all of the member attributes that are supported in
+ Table 1.
+
+5.4 media-col-supported (1setOf type2 keyword)
+
+ The "media-col-supported" Printer attribute identifies the keyword
+ names of the member attributes supported in the "media-col"
+ collection Job Template attribute, i.e., the keyword names of the
+ member attributes in Table 1 that the Printer supports.
+
+6 A Second Example Definition Of A Collection Attribute
+
+ All of the example attribute definitions in this document are
+ illustrative examples, rather than actual definitions. These
+ examples are intended to illustrate how to define collection
+ attributes. Other documents MUST define collection attributes for
+ use in actual interchange. Such definitions may be very similar to
+ the examples in this document, since we attempted to pick useful
+ examples.
+
+ In some printing environments, it is desirable to allow the client to
+ select the media for the job start sheet. The reason for not adding
+ the 'collection' attribute syntax to the existing "job-sheets" Job
+ Template attribute is the same as for "media". Instead, a new Job
+ Template attribute is introduced, e.g., "job-sheet-col (collection)".
+
+ The member attributes of "job-sheet-col" attribute ("job-sheets (type
+ 3 keyword)" and "media (type3 keyword | name)") both follow the
+ naming rules of item 4a1 of section 3, i.e., they reuse existing IPP
+ attributes. According to the rules, their supported values come from
+ the existing IPP attributes: "job-sheets-supported" and "media-
+ supported". However, their default values do not come from "job-
+ sheets-default" and "media-default", respectively. Rather, the
+ definition of "job-sheet-col" says that "job-sheets (type 3 keyword)"
+ is required and if "media (type3 keyword | name)" is absent, the
+ Printer uses the same media as the rest of the job uses.
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 12]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ If "job-sheet-col" attribute was defined to contain the member
+ attribute "job-sheet-media (type3 keyword | name)" instead of "media
+ (type3 keyword | name)", then the definition would also have to
+ specify a "job-sheet-media-supported (1setOf (type3 keyword | name))"
+ whose values would be independent of "media-supported (1setOf (type3
+ keyword | name))" and would be set separately by a System
+ Administrator.
+
+ The actual text for the definition of the attribute is left as an
+ exercise for the reader.
+
+7 Encoding
+
+ This section defines the additional encoding tags used according to
+ [RFC2910] and gives an example of their use. The encoding tags
+ defined in this document MUST be used by all collection attributes
+ defined in other documents. However, the example of their use is
+ illustrative only.
+
+7.1 Additional tags defined for representing a collection attribute
+ value
+
+ The 'collection' attribute syntax uses the tags defined in Table 3.
+
+ Table 3 - Tags defined for encoding the 'collection' attribute syntax
+
+ Tag name Tag
+ value Meaning
+
+ begCollection 0x34 Begin the collection attribute value.
+
+ endCollection 0x37 End the collection attribute value.
+
+ memberAttrName 0x4A The value is the name of the
+ collection member attribute
+
+ When encoding a collection attribute "xxx" that contains an attribute
+ "aaa" and is not inside another collection, the encoding follows
+ these rules:
+
+ 1. The beginning of the collection is indicated with a value tag that
+ MUST be syntax type 'begCollection' (0x34) with a name length and
+ Name field that represent the name of the collection attribute
+ ("xxx") as with any attribute, followed by a value. The Printer
+ MAY ignore the value and its length MAY be 0. In the future,
+ however, this field MAY contain useful information, such as the
+ collection name (cf. the name of a C struct).
+
+
+
+
+deBry, et. al. Standards Track [Page 13]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ 2. Each member attribute is encoded as a sequence of two or more
+ values that appear to be part of a single multi-valued attribute,
+ i.e., 1setOf. The first value after the 'begCollection' value has
+ the attribute syntax, 'memberAttrName' (0x4A), and its value holds
+ the name of the first member attribute (e.g., "aaa"). The second
+ value holds the first member's attribute value, which can be of
+ any attribute syntax, except 'memberAttrName' or 'endCollection'.
+ If the first member's attribute value is multi-valued, the third
+ value holds the second value of the first member's value.
+ Otherwise, the third value holds the name of second member
+ attribute (e.g., "bbb"), and its attribute syntax is
+ 'memberAttrName'. In this case, the fourth member's value is the
+ value of "bbb".
+
+ Note that the technique of encoding a 'collection' as a '1setOf'
+ makes it easy for a Printer that doesn't support a particular
+ collection attribute (or the collection attribute syntax at all)
+ to simply skip over the entire collection value.
+
+ 3. The end of the collection is indicated with a value tag that MUST
+ be syntax type 'endCollection' (e.g., 0x37) and MAY have a zero
+ name length and a zero value length. In the future, this field
+ MAY contain useful information, such as the collection name that
+ matches the one in the 'begCollection' .
+
+ 4. It is valid to have a member attribute that is itself, a
+ collection attribute, i.e., collections can be nested within
+ collections. This is represented by the occurrence of a member
+ attribute that is of attribute syntax type 'begCollection'. Such
+ a collection is terminated by a matching 'endCollection'. The
+ name of such a member attribute is in the immediately preceding
+ value, whose syntax type is 'memberAttrName'.
+
+ 5. It is valid for a collection attribute to be multi-valued, i.e.,
+ have more than one collection value. If the next attribute
+ immediately following the 'endCollection' has a zero name length
+ and a tag of 'begCollection', then the collection attribute is a
+ multi-valued collection, as with any attribute. This statement
+ applies to collections within collections and collections that are
+ not in collections.
+
+7.2 Example encoding: "media-col" (collection)
+
+ The collection specified in section 5 is used for the encoding
+ example shown in Table 5. The example also shows nested collections,
+ since the "media-size" member attribute is a 'collection. The
+ encoding example represents a blue 4x6-index card and takes 216
+ octets. The Appendices contain more complex examples.
+
+
+
+deBry, et. al. Standards Track [Page 14]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Additional examples have been included in the appendices.
+
+ The overall structure of the two collection values can be pictorially
+ represented as:
+
+ "media-col" =
+ { "media-color" = 'blue';
+ "media-size" =
+ { "x-dimension" = 6;
+ "y-dimension" = 4
+ }
+ },
+
+ The full encoding is in table 5. A simplified view of the encoding
+ looks like this:
+
+ Table 4 - Overview Encoding of "media-col" collection
+
+ Tag Value Name Value
+
+ begCollection media-col ""
+
+ memberAttrName "" media-color
+
+ keyword "" blue
+
+ memberAttrName "" media-size
+
+ begCollection "" ""
+
+ memberAttrName "" x-dimension
+
+ integer "" 6
+
+ memberAttrName "" y-dimension
+
+ integer "" 4
+
+ endCollection "" ""
+
+ endCollection "" ""
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 15]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Table 5 - Example Encoding of "media-col" collection
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x34 begCollection value-tag beginning of the "media-
+ col" collection attribute
+
+ 0x0009 name- length of (collection)
+ length attribute name
+
+ media-col media-col name name of (collection)
+ attribute
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "media-color"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of "media-color"
+ length keyword
+
+ media-color media-color value value is name of 1st
+ member attribute
+
+
+ 0x44 keyword type value-tag keyword type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 16]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0004 value-
+ length
+
+ blue blue value value of 1st member
+ attribute
+
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "media-size"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000A value- length of "media-size"
+ length keyword
+
+ media-size media-size value Name of 2nd member
+ attribute
+
+ 0x34 begCollection value-tag Beginning of the "media-
+ size" collection attribute
+ which is a sub-collection
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- collection attribute names
+ length have no value
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "x-dimension"
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 17]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of "x-dimension"
+ length keyword
+
+ x-dimension x-dimension value name of 1st sub-
+ collection member
+ attribute
+
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0006 value value of 1st sub-
+ collection member
+ attribute
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "y-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of the "y-
+ length dimension" keyword
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 18]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ y-dimension y-dimension value name of 2nd sub-
+ collection member
+ attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0004 value value of 2nd sub-
+ collection member
+ attribute
+
+ 0x37 endCollection value-tag end of the sub-collection
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x37 endCollection value-tag end of the 1st collection
+ value in 1setOf
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 19]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+8 Legacy issues
+
+ IPP 1.x Printers and Clients will gracefully ignore collections and
+ its member attributes if it does not understand the collection. The
+ begCollection and endCollection elements each look like an attribute
+ with an attribute syntax that the recipient doesn't support and so
+ should ignore the entire attribute. The individual member attributes
+ and their values will look like a 1setOf values of the collection
+ attribute, so that the Printer simply ignores the entire attribute
+ and all of its values. Returning unsupported attributes is also
+ simple, since only the name of the collection attribute is returned
+ with the 'unsupported' out-of-band value (see section 4.2).
+
+9 IANA Considerations
+
+ The following table provides registration for the 'collection'
+ attribute syntax defined in this document. This is to be registered
+ according to the procedures in RFC 2911 [RFC2911] section 6.3.
+
+ Tag value: Attribute Syntaxes: Ref. Section:
+ collection RFC 3382 3
+ 0x34 begCollection RFC 3382 7.1
+ 0x37 endCollection RFC 3382 7.1
+ 0x4A memberAttrName RFC 3382 7.1
+
+ The resulting attribute syntax registration will be published in the
+ http://www.iana.org/assignments/ipp-registrations registry.
+
+10 Internationalization Considerations
+
+ This attribute syntax by itself has no impact on
+ internationalization. However, the member attributes that are
+ subsequently defined for use in a collection may have
+ internationalization considerations, as may any attribute, according
+ to [RFC2911].
+
+
+
+
+deBry, et. al. Standards Track [Page 20]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+11 Security Considerations
+
+ This attribute syntax causes no more security concerns than any other
+ attribute syntax. It is only the attributes that are subsequently
+ defined, to use this or any other attribute syntax, that may have
+ security concerns, depending on the semantics of the attribute,
+ according to [RFC2911].
+
+12 References
+
+12.1 Normative References
+
+ [RFC2910] Herriot, R., Butler, S., Moore, P. and R. Turner, "Internet
+ Printing Protocol/1.1: Encoding and Transport", RFC 2910,
+ September 2000.
+
+ [RFC2911] Isaacson, S., deBry, R., Hastings, T., Herriot, R. and P.
+ Powell, "Internet Printing Protocol/1.1: Model and
+ Semantics", RFC 2911, September 2000.
+
+12.2 Informative References
+
+ [RFC2565] Herriot, R., Butler, S., Moore, P. and R. Tuner, "Internet
+ Printing Protocol/1.0: Encoding and Transport", RFC 2565,
+ April 1999.
+
+ [RFC2566] deBry, R., Hastings, T., Herriot, R., Isaacson, S. and P.
+ Powell, "Internet Printing Protocol/1.0: Model and
+ Semantics", RFC 2566, April 1999.
+
+ [RFC2567] Wright, D., "Design Goals for an Internet Printing
+ Protocol", RFC 2567, April 1999.
+
+ [RFC2568] Zilles, S., "Rationale for the Structure and Model and
+ Protocol for the Internet Printing Protocol", RFC 2568,
+ April 1999.
+
+ [RFC2569] Herriot, R., Hastings, T., Jacobs, N. and J. Martin,
+ "Mapping between LPD and IPP Protocols", RFC 2569, April
+ 1999.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter,
+ L., Leach, P. and T. Berners-Lee, "Hypertext Transfer
+ Protocol - HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC3196] Hastings, T., Manros, C., Zehler, P., Kugler, C. and H.
+ Holst, "Internet Printing Protocol/1.1: Implementor's
+ Guide", RFC 3196, November 2001.
+
+
+
+deBry, et. al. Standards Track [Page 21]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+Appendix A: Encoding Example of a Simple Collection (Informative)
+
+ The overall structure of the collection value can be pictorially
+ represented as:
+
+ "media-size" =
+ { "x-dimension" = 6;
+ "y-dimension" = 4
+ }
+
+ A simplified view of the encoding would look like this:
+
+ Table 6 - Overview Encoding of simple collection
+
+ Tag Value Name Value
+
+ begCollection media-size ""
+
+ memberAttrName "" x-dimension
+
+ integer "" 6
+
+ memberAttrName "" y-dimension
+
+ integer "" 4
+
+ endCollection "" ""
+
+ Note: "" represents a name or value whose length is 0.
+
+ Table 7 - Example Encoding of simple collection
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x34 begCollection value-tag beginning of the "media-
+ size" collection attribute
+
+ 0x000A name- length of (collection)
+ length attribute name
+
+ media-size media-size name name of (collection)
+ attribute
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 22]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts member attribute:
+ "x-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of "x-dimension"
+ length keyword
+
+ x-dimension x-dimension value name of 1st collection
+ member attribute
+
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0006 value value of 1st collection
+ member attribute
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "y-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+
+
+
+deBry, et. al. Standards Track [Page 23]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x000B value- length of the "y-
+ length dimension" keyword
+
+ y-dimension y-dimension value name of 2nd collection
+ member attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf for
+ length media-size
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0004 value value of 2nd collection
+ member attribute
+
+ 0x37 endCollection value-tag end of the collection
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 24]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+Appendix B: Encoding Example of 1setOf Collection (Informative)
+
+ The overall structure of the collection value can be pictorially
+ represented as:
+
+ "media-size-supported" =
+ { "x-dimension" = 6;
+ "y-dimension" = 4
+ },
+ { "x-dimension" = 3;
+ "y-dimension" = 5
+ };
+
+ A simplified view of the encoding would look like this:
+
+ Table 8 - Overview Encoding of 1setOf collection
+
+ Tag Value Name Value
+
+ begCollection media-size- ""
+ supported
+
+ memberAttrName "" x-dimension
+
+ integer "" 6
+
+ memberAttrName "" y-dimension
+
+ integer "" 4
+
+ endCollection "" ""
+
+ begCollection "" ""
+
+ memberAttrName "" x-dimension
+
+ integer "" 3
+
+ memberAttrName "" y-dimension
+
+ integer "" 5
+
+ endCollection "" ""
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 25]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Table 9 - Example Encoding of 1setOf collection
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x34 begCollection value-tag beginning of the "media-
+ size-supported (1setOf
+ collection" attribute
+
+ 0x00014 name- length of (collection)
+ length attribute name
+
+ media-size- media-size- name name of (collection)
+ supported supported attribute
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts member attribute:
+ "x-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of "x-dimension"
+ length keyword
+
+ x-dimension x-dimension value name of 1st collection
+ member attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 26]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0006 value value of 1st collection
+ member attribute
+
+ 0x4A memberAttrName value-tag starts member attribute:
+ "y-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of the "y-
+ length dimension" keyword
+
+ y-dimension y-dimension value name of 2nd collection
+ member attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0004 value value of 2nd collection
+ member attribute
+
+ 0x37 endCollection value-tag end of the collection
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 27]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x34 begCollection value-tag beginning of the 2nd
+ member of the 1setOf
+ "sizes-avail " collection
+ attribute
+
+ 0x0000 name- Zero length name indicates
+ length this is member of previous
+ attribute
+
+ name no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts member attribute:
+ "x-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of "x-dimension"
+ length keyword
+
+ x-dimension x-dimension value name of 1st collection
+ member attribute
+
+ 0x21 integer type value-tag attribute type
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 28]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0003 value value of 1st collection
+ member attribute
+
+ 0x4A memberAttrName value-tag starts member attribute:
+ "y-dimension"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x000B value- length of the "y-
+ length dimension" keyword
+
+ y-dimension y-dimension value name of 2nd collection
+ member attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0005 value value of 2nd collection
+ member attribute
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 29]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x37 endCollection value-tag end of the 1setOf
+ collection value
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 30]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+Appendix C: Encoding Example of Collection containing 1setOf XXX
+ attribute (Informative)
+
+ The overall structure of the collection value can be pictorially
+ represented as:
+
+ "wagons" =
+ { "colors" = red, blue;
+ "sizes" = 4, 6, 8
+ }
+
+ A simplified view of the encoding would look like this:
+
+ Table 10 - Overview Encoding of collection with 1setOf value
+
+ Tag Value Name Value
+
+ begCollection wagons ""
+
+ memberAttrName "" colors
+
+ keyword "" red
+
+ keyword "" blue
+
+ memberAttrName "" sizes
+
+ integer "" 4
+
+ integer "" 6
+
+ integer "" 8
+
+ endCollection "" ""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 31]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Table 11 - Example Encoding of collection with 1setOf value
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x34 begCollection value-tag beginning of the "wagons"
+ collection attribute
+
+ 0x0005 name- length of (collection)
+ length attribute name
+
+ wagons wagons name name of (collection)
+ attribute
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+ no value (since value-
+ length was 0)
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "colors"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0006 value- length of "colors" keyword
+ length
+
+ colors colors value value is name of 1st
+ member attribute
+
+ 0x44 keyword type value-tag keyword type
+
+ 0x0000 name- 0 indicates 1setOf wagons
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value-
+ length
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 32]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ blue blue value value of 1st member
+ attribute
+
+ 0x44 keyword type value-tag keyword type
+
+ 0x0000 name- 0 indicates 1setOf wagons
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0003 value-
+ length
+
+ red red value value of 1st member
+ attribute
+
+ 0x4A memberAttrName value-tag starts a new member
+ attribute: "sizes"
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0005 value- length of "length-avail"
+ length keyword
+
+ sizes sizes value Name of 2nd member
+ attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf wagons
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 33]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ 0x0004 value 1st value for 1setOf
+ integer attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value-
+ length length of an integer = 4
+
+ 0x0006 value 2nd value for 1setOf
+ integer attribute
+
+ 0x21 integer type value-tag attribute type
+
+ 0x0000 name- 0 indicates 1setOf
+ length
+
+ no name (since name-length
+ was 0)
+
+ 0x0004 value- length of an integer = 4
+ length
+
+ 0x0008 value 3rd value for 1setOf
+ integer attribute
+
+ 0x37 endCollection value-tag end of the collection
+
+ 0x0000 name- defined to be 0 for this
+ length type, so part of 1setOf
+
+ no name (since name-length
+ was 0)
+
+ 0x0000 value- defined to be 0 for this
+ length type
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 34]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Octets Symbolic Value Protocol comments
+ field
+
+ no value (since value-
+ length was 0)
+
+Appendix D: Description of the Base IPP Documents (Informative)
+
+ The base set of IPP documents includes:
+
+ Design Goals for an Internet Printing Protocol [RFC2567]
+ Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol [RFC2568]
+ Internet Printing Protocol/1.1: Model and Semantics [RFC2911]
+ Internet Printing Protocol/1.1: Encoding and Transport [RFC2910]
+ Internet Printing Protocol/1.1: Implementer's Guide [RFC3196]
+ Mapping between LPD and IPP Protocols [RFC2569]
+
+ The "Design Goals for an Internet Printing Protocol" document takes a
+ broad look at distributed printing functionality, and it enumerates
+ real-life scenarios that help to clarify the features that need to be
+ included in a printing protocol for the Internet. It identifies
+ requirements for three types of users: end users, operators, and
+ administrators. It calls out a subset of end user requirements that
+ are satisfied in IPP/1.0 [RFC2566, RFC2565]. A few OPTIONAL operator
+ operations have been added to IPP/1.1 [RFC2911, RFC2910].
+
+ The "Rationale for the Structure and Model and Protocol for the
+ Internet Printing Protocol" document describes IPP from a high level
+ view, defines a roadmap for the various documents that form the suite
+ of IPP specification documents, and gives background and rationale
+ for the IETF IPP working group's major decisions.
+
+ The "Internet Printing Protocol/1.1: Model and Semantics" document
+ describes a simplified model with abstract objects, their attributes,
+ and their operations. The model introduces a Printer and a Job. The
+ Job supports multiple documents per Job. The model document also
+ addresses how security, internationalization, and directory issues
+ are addressed.
+
+ The "Internet Printing Protocol/1.1: Encoding and Transport" document
+ is a formal mapping of the abstract operations and attributes defined
+ in the model document onto HTTP/1.1 [RFC2616]. It also defines the
+ encoding rules for a new Internet MIME media type called
+ "application/ipp". This document also defines the rules for
+ transporting over HTTP a message body whose Content-Type is
+ "application/ipp". This document defines the 'ipp' scheme for
+ identifying IPP printers and jobs.
+
+
+
+deBry, et. al. Standards Track [Page 35]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ The "Internet Printing Protocol/1.1: Implementer's Guide" document
+ gives insight and advice to implementers of IPP clients and IPP
+ objects. It is intended to help them understand IPP/1.1 and some of
+ the considerations that may assist them in the design of their client
+ and/or IPP object implementations. For example, a typical order of
+ processing requests is given, including error checking. Motivation
+ for some of the specification decisions is also included.
+
+ The "Mapping between LPD and IPP Protocols" document gives some
+ advice to implementers of gateways between IPP and LPD (Line Printer
+ Daemon) implementations.
+
+Authors' Addresses
+
+ Roger deBry
+ Utah Valley State College
+ Orem, UT 84058
+
+ Phone: (801) 222-8000
+ EMail: debryro@uvsc.edu
+
+
+ Tom Hastings
+ Xerox Corporation
+ 737 Hawaii St. ESAE 231
+ El Segundo, CA 90245
+
+ Phone: 310-333-6413
+ Fax: 310-333-5514
+ EMail: hastings@cp10.es.xerox.com
+
+
+ Robert Herriot
+ Consultant
+ 706 Colorado Ave
+ Palo Alto, CA 94303
+
+ Phone: 650-327-4466
+ Fax: 650-327-4466
+ EMail: bob@herriot.com
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 36]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+ Kirk Ocke
+ Xerox Corp.
+ 800 Phillips Rd
+ M/S 128-30E
+ Webster, NY 14580
+
+ Phone: (585) 442-4832
+ EMail: KOcke@crt.xerox.com
+
+
+ Peter Zehler
+ Xerox Corp.
+ 800 Phillips Rd
+ M/S 128-30E
+ Webster, NY 14580
+
+ Phone: (585) 265-8755
+ EMail: PZehler@crt.xerox.com
+
+ IPP Web Page: http://www.pwg.org/ipp/
+ IPP Mailing List: ipp@pwg.org
+
+ To subscribe to the ipp mailing list, send the following email:
+
+ 1) send it to majordomo@pwg.org
+ 2) leave the subject line blank
+ 3) put the following two lines in the message body:
+ subscribe ipp
+ end
+
+ Implementers of this specification document are encouraged to join
+ the IPP Mailing List in order to participate in any discussions of
+ clarification issues and review of registration proposals for
+ additional attributes and values. In order to reduce spam the
+ mailing list rejects mail from non-subscribers, so you must subscribe
+ to the mailing list in order to send a question or comment to the
+ mailing list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 37]
+
+RFC 3382 IPP: The 'collection' attribute syntax September 2002
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+deBry, et. al. Standards Track [Page 38]
+
diff --git a/systemv/.cvsignore b/systemv/.cvsignore
new file mode 100644
index 000000000..086795e71
--- /dev/null
+++ b/systemv/.cvsignore
@@ -0,0 +1,11 @@
+lp
+cupsaddsmb
+cupstestppd
+lppasswd
+lpoptions
+lpadmin
+accept
+cancel
+lpinfo
+lpmove
+lpstat
diff --git a/systemv/Dependencies b/systemv/Dependencies
new file mode 100644
index 000000000..193d4161e
--- /dev/null
+++ b/systemv/Dependencies
@@ -0,0 +1,28 @@
+# DO NOT DELETE
+
+accept.o: ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+accept.o: ../cups/md5.h ../cups/ppd.h ../cups/string.h ../cups/language.h
+cancel.o: ../config.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
+cancel.o: ../cups/md5.h ../cups/ppd.h ../cups/string.h ../cups/language.h
+cupsaddsmb.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+cupsaddsmb.o: ../cups/ppd.h ../cups/language.h ../cups/string.h ../config.h
+cupstestppd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+cupstestppd.o: ../cups/ppd.h ../cups/string.h ../config.h
+lp.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h ../cups/ppd.h
+lp.o: ../cups/string.h ../config.h ../cups/language.h
+lpadmin.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpadmin.o: ../cups/ppd.h ../cups/string.h ../config.h ../cups/language.h
+lpadmin.o: ../cups/debug.h
+lpinfo.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpinfo.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h ../cups/string.h
+lpinfo.o: ../config.h
+lpmove.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpmove.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h ../cups/string.h
+lpmove.o: ../config.h
+lpoptions.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpoptions.o: ../cups/ppd.h ../cups/string.h ../config.h
+lppasswd.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lppasswd.o: ../cups/ppd.h ../cups/md5.h ../cups/string.h ../config.h
+lpstat.o: ../cups/cups.h ../cups/ipp.h ../cups/http.h ../cups/md5.h
+lpstat.o: ../cups/ppd.h ../cups/language.h ../cups/debug.h ../cups/string.h
+lpstat.o: ../config.h
diff --git a/systemv/Makefile b/systemv/Makefile
new file mode 100644
index 000000000..a9500dbf7
--- /dev/null
+++ b/systemv/Makefile
@@ -0,0 +1,198 @@
+#
+# "$Id$"
+#
+# System V commands makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+TARGETS = accept cancel cupsaddsmb cupstestppd lp lpadmin lpinfo \
+ lpmove lpoptions lppasswd lpstat
+OBJS = accept.o cancel.o cupsaddsmb.o cupstestppd.o lp.o \
+ lpadmin.o lpinfo.o lpmove.o lpoptions.o lppasswd.o \
+ lpstat.o
+
+
+#
+# Make all targets...
+#
+
+all: $(TARGETS)
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) $(OBJS) $(TARGETS) disable enable reject
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies $(OBJS:.o=.c) >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install: all
+ $(INSTALL_DIR) $(SBINDIR)
+ $(INSTALL_BIN) accept $(SBINDIR)
+ $(RM) $(SBINDIR)/reject
+ $(LN) accept $(SBINDIR)/reject
+ $(INSTALL_BIN) cupsaddsmb $(SBINDIR)
+ $(INSTALL_BIN) lpadmin $(SBINDIR)
+ $(INSTALL_BIN) lpinfo $(SBINDIR)
+ $(INSTALL_BIN) lpmove $(SBINDIR)
+ $(INSTALL_DIR) $(BINDIR)
+ $(INSTALL_BIN) cancel $(BINDIR)
+ $(INSTALL_BIN) cupstestppd $(BINDIR)
+ $(RM) $(BINDIR)/disable
+ $(LN) ../sbin/accept $(BINDIR)/disable
+ $(RM) $(BINDIR)/enable
+ $(LN) ../sbin/accept $(BINDIR)/enable
+ $(INSTALL_BIN) lp $(BINDIR)
+ $(INSTALL_BIN) lpoptions $(BINDIR)
+ $(INSTALL_BIN) lpstat $(BINDIR)
+ -$(INSTALL_BIN) -m 4755 -o $(CUPS_USER) -g $(CUPS_GROUP) lppasswd $(BINDIR)
+ if test ! -x $(BINDIR)/lppasswd; then \
+ chmod 755 $(BINDIR)/lppasswd; \
+ fi
+
+
+#
+# accept
+#
+
+accept: accept.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o accept accept.o $(LIBS)
+ $(RM) reject enable disable
+ $(LN) accept reject
+ $(LN) accept enable
+ $(LN) accept disable
+
+
+#
+# cancel
+#
+
+cancel: cancel.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cancel cancel.o $(LIBS)
+
+
+#
+# cupsaddsmb
+#
+
+cupsaddsmb: cupsaddsmb.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cupsaddsmb cupsaddsmb.o $(LIBS)
+
+
+#
+# cupstestppd
+#
+
+cupstestppd: cupstestppd.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o $@ cupstestppd.o $(LIBS)
+
+
+#
+# lp
+#
+
+lp: lp.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lp lp.o $(LIBS)
+
+
+#
+# lpadmin
+#
+
+lpadmin: lpadmin.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpadmin lpadmin.o $(LIBZ) $(LIBS)
+
+
+#
+# lpinfo
+#
+
+lpinfo: lpinfo.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpinfo lpinfo.o $(LIBS)
+
+
+#
+# lpmove
+#
+
+lpmove: lpmove.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpmove lpmove.o $(LIBS)
+
+
+#
+# lpoptions
+#
+
+lpoptions: lpoptions.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpoptions lpoptions.o $(LIBZ) $(LIBS)
+
+
+#
+# lppasswd
+#
+
+lppasswd: lppasswd.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lppasswd lppasswd.o $(LIBZ) $(LIBS)
+
+
+#
+# lpstat
+#
+
+lpstat: lpstat.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o lpstat lpstat.o $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/systemv/accept.c b/systemv/accept.c
new file mode 100644
index 000000000..051da14b2
--- /dev/null
+++ b/systemv/accept.c
@@ -0,0 +1,286 @@
+/*
+ * "$Id$"
+ *
+ * "accept", "disable", "enable", and "reject" commands for the Common
+ * UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and accept/reject jobs or disable/enable printers.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <config.h>
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+
+
+/*
+ * 'main()' - Parse options and accept/reject jobs or disable/enable printers.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* HTTP connection to server */
+ int i; /* Looping var */
+ char *command, /* Command to do */
+ uri[1024], /* Printer URI */
+ *reason; /* Reason for reject/disable */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_op_t op; /* Operation */
+ cups_lang_t *language; /* Language */
+ int cancel; /* Cancel jobs? */
+
+
+ /*
+ * See what operation we're supposed to do...
+ */
+
+ if ((command = strrchr(argv[0], '/')) != NULL)
+ command ++;
+ else
+ command = argv[0];
+
+ cancel = 0;
+
+ if (strcmp(command, "accept") == 0)
+ op = CUPS_ACCEPT_JOBS;
+ else if (strcmp(command, "reject") == 0)
+ op = CUPS_REJECT_JOBS;
+ else if (strcmp(command, "disable") == 0)
+ op = IPP_PAUSE_PRINTER;
+ else if (strcmp(command, "enable") == 0)
+ op = IPP_RESUME_PRINTER;
+ else
+ {
+ fprintf(stderr, "%s: Don't know what to do!\n", command);
+ return (1);
+ }
+
+ http = NULL;
+ reason = NULL;
+
+ /*
+ * Process command-line arguments...
+ */
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ command);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'c' : /* Cancel jobs */
+ cancel = 1;
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http != NULL)
+ httpClose(http);
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fprintf(stderr, "%s: Expected server name after -h!\n",
+ command);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'r' : /* Reason for cancellation */
+ if (argv[i][2] != '\0')
+ reason = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ {
+ fprintf(stderr, "%s: Expected reason text after -r!\n", command);
+ return (1);
+ }
+
+ reason = argv[i];
+ }
+ break;
+
+ default :
+ fprintf(stderr, "%s: Unknown option \'%c\'!\n", command,
+ argv[i][1]);
+ return (1);
+ }
+ else
+ {
+ /*
+ * Accept/disable/enable/reject a destination...
+ */
+
+ if (http == NULL)
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ if (http == NULL)
+ {
+ fputs(command, stderr);
+ perror(": Unable to connect to server");
+ return (1);
+ }
+
+ /*
+ * Build an IPP request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * printer-state-message [optional]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", argv[i]);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ if (reason != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "printer-state-message", NULL, reason);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "%s: Operation failed: %s\n", command,
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "%s: Operation failed: %s\n", command,
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ /*
+ * Cancel all jobs if requested...
+ */
+
+ if (cancel)
+ {
+ /*
+ * Build an IPP_PURGE_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_PURGE_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "%s: Operation failed: %s\n", command,
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "%s: Operation failed: %s\n", command,
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ }
+ }
+
+ if (http != NULL)
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/cancel.c b/systemv/cancel.c
new file mode 100644
index 000000000..29ce7a4f0
--- /dev/null
+++ b/systemv/cancel.c
@@ -0,0 +1,384 @@
+/*
+ * "$Id$"
+ *
+ * "cancel" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and cancel jobs.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <config.h>
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+
+
+/*
+ * 'main()' - Parse options and cancel jobs.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ http_t *http; /* HTTP connection to server */
+ int i; /* Looping var */
+ int job_id; /* Job ID */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+ char *dest, /* Destination printer */
+ *job, /* Job ID pointer */
+ *user; /* Cancel jobs for a user */
+ int purge; /* Purge or cancel jobs? */
+ char uri[1024]; /* Printer or job URI */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_op_t op; /* Operation */
+ cups_lang_t *language; /* Language */
+
+
+ /*
+ * Setup to cancel individual print jobs...
+ */
+
+ op = IPP_CANCEL_JOB;
+ purge = 0;
+ job_id = 0;
+ dest = NULL;
+ user = NULL;
+ http = NULL;
+ num_dests = 0;
+ dests = NULL;
+
+ /*
+ * Process command-line arguments...
+ */
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-' && argv[i][1])
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'a' : /* Cancel all jobs */
+ purge = 1;
+ op = IPP_PURGE_JOBS;
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http != NULL)
+ httpClose(http);
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("cancel: Error - expected hostname after \'-h\' option!\n", stderr);
+ return (1);
+ }
+ else
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'u' : /* Username */
+ op = IPP_PURGE_JOBS;
+
+ if (argv[i][2] != '\0')
+ user = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("cancel: Error - expected username after \'-u\' option!\n", stderr);
+ return (1);
+ }
+ else
+ user = argv[i];
+ }
+ break;
+
+ default :
+ fprintf(stderr, "cancel: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else
+ {
+ /*
+ * Cancel a job or printer...
+ */
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if (strcmp(argv[i], "-") == 0)
+ {
+ /*
+ * Delete the current job...
+ */
+
+ dest = "";
+ job_id = 0;
+ }
+ else if (cupsGetDest(argv[i], NULL, num_dests, dests) != NULL)
+ {
+ /*
+ * Delete the current job on the named destination...
+ */
+
+ dest = argv[i];
+ job_id = 0;
+ }
+ else if ((job = strrchr(argv[i], '-')) != NULL && isdigit(job[1] & 255))
+ {
+ /*
+ * Delete the specified job ID.
+ */
+
+ dest = NULL;
+ op = IPP_CANCEL_JOB;
+ job_id = atoi(job + 1);
+ }
+ else if (isdigit(argv[i][0] & 255))
+ {
+ /*
+ * Delete the specified job ID.
+ */
+
+ dest = NULL;
+ op = IPP_CANCEL_JOB;
+ job_id = atoi(argv[i]);
+ }
+ else
+ {
+ /*
+ * Bad printer name!
+ */
+
+ fprintf(stderr, "cancel: Unknown destination \"%s\"!\n", argv[i]);
+ return (1);
+ }
+
+ /*
+ * For Solaris LP compatibility, ignore a destination name after
+ * cancelling a specific job ID...
+ */
+
+ if (job_id && (i + 1) < argc &&
+ cupsGetDest(argv[i + 1], NULL, num_dests, dests) != NULL)
+ i ++;
+
+ /*
+ * Open a connection to the server...
+ */
+
+ if (http == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ fputs("cancel: Unable to contact server!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Build an IPP request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri + job-id *or* job-uri
+ * [requesting-user-name]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (dest)
+ {
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", dest);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+ job_id);
+ }
+ else
+ {
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
+ uri);
+ }
+
+ if (user)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+ }
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ if (op == IPP_PURGE_JOBS)
+ ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if (op == IPP_PURGE_JOBS)
+ response = cupsDoRequest(http, request, "/admin/");
+ else
+ response = cupsDoRequest(http, request, "/jobs/");
+
+ if (response == NULL ||
+ response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "cancel: %s failed: %s\n",
+ op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job",
+ response ? ippErrorString(response->request.status.status_code) :
+ ippErrorString(cupsLastError()));
+
+ if (response)
+ ippDelete(response);
+
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+
+ if (num_dests == 0 && op == IPP_PURGE_JOBS)
+ {
+ /*
+ * Open a connection to the server...
+ */
+
+ if (http == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ fputs("cancel: Unable to contact server!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Build an IPP request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri + job-id *or* job-uri
+ * [requesting-user-name]
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "ipp://localhost/printers/");
+
+ if (user)
+ {
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+ }
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ response = cupsDoRequest(http, request, "/admin/");
+
+ if (response == NULL ||
+ response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "cancel: %s failed: %s\n",
+ op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job",
+ response ? ippErrorString(response->request.status.status_code) :
+ ippErrorString(cupsLastError()));
+
+ if (response)
+ ippDelete(response);
+
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/cupsaddsmb.c b/systemv/cupsaddsmb.c
new file mode 100644
index 000000000..2203c9447
--- /dev/null
+++ b/systemv/cupsaddsmb.c
@@ -0,0 +1,951 @@
+/*
+ * "$Id$"
+ *
+ * "cupsaddsmb" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2001-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Export printers on the command-line.
+ * convert_ppd() - Convert a PPD file to a form usable by any of the
+ * Windows PostScript printer drivers.
+ * do_samba_command() - Do a SAMBA command, asking for a password as needed.
+ * export_dest() - Export a destination to SAMBA.
+ * ppd_gets() - Get a CR and/or LF-terminated line.
+ * usage() - Show program usage and exit...
+ * write_option() - Write a CUPS option to a PPD file.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/string.h>
+#include <errno.h>
+
+
+/*
+ * Local globals...
+ */
+
+int Verbosity = 0;
+const char *SAMBAUser,
+ *SAMBAServer;
+
+
+/*
+ * Local functions...
+ */
+
+int convert_ppd(const char *src, char *dst, int dstsize, ipp_t *info);
+int do_samba_command(const char *command, const char *subcommand);
+int export_dest(const char *dest);
+char *ppd_gets(FILE *fp, char *buf, int buflen);
+void usage(void);
+int write_option(FILE *dstfp, int order, const char *name,
+ const char *text, const char *attrname,
+ ipp_attribute_t *suppattr, ipp_attribute_t *defattr,
+ int defval, int valcount);
+
+
+/*
+ * 'main()' - Export printers on the command-line.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping vars */
+ int status; /* Status from export_dest() */
+ int export_all; /* Export all printers? */
+ int num_printers; /* Number of printers */
+ char **printers; /* Printers */
+
+
+ /*
+ * Parse command-line arguments...
+ */
+
+ export_all = 0;
+
+ SAMBAUser = cupsUser();
+ SAMBAServer = NULL;
+
+ for (i = 1; i < argc; i ++)
+ if (strcmp(argv[i], "-a") == 0)
+ export_all = 1;
+ else if (strcmp(argv[i], "-U") == 0)
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ SAMBAUser = argv[i];
+ }
+ else if (strcmp(argv[i], "-H") == 0)
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ SAMBAServer = argv[i];
+ }
+ else if (strcmp(argv[i], "-h") == 0)
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ cupsSetServer(argv[i]);
+ }
+ else if (strcmp(argv[i], "-v") == 0)
+ Verbosity = 1;
+ else if (argv[i][0] != '-')
+ {
+ if (SAMBAServer == NULL)
+ SAMBAServer = cupsServer();
+
+ if ((status = export_dest(argv[i])) != 0)
+ return (status);
+ }
+ else
+ usage();
+
+ /*
+ * See if the user specified "-a"...
+ */
+
+ if (export_all)
+ {
+ /*
+ * Export all printers...
+ */
+
+ if (SAMBAServer == NULL)
+ SAMBAServer = cupsServer();
+
+ num_printers = cupsGetPrinters(&printers);
+
+ for (j = 0, status = 0; j < num_printers; j ++)
+ if ((status = export_dest(printers[j])) != 0)
+ break;
+
+ for (j = 0; j < num_printers; j ++)
+ free(printers[j]);
+
+ if (num_printers)
+ free(printers);
+
+ if (status)
+ return (status);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'convert_ppd()' - Convert a PPD file to a form usable by any of the
+ * Windows PostScript printer drivers.
+ */
+
+int /* O - 0 on success, 1 on failure */
+convert_ppd(const char *src, /* I - Source (original) PPD */
+ char *dst, /* O - Destination PPD */
+ int dstsize, /* I - Size of destination buffer */
+ ipp_t *info) /* I - Printer attributes */
+{
+ FILE *srcfp, /* Source file */
+ *dstfp; /* Destination file */
+ int dstfd; /* Destination file descriptor */
+ ipp_attribute_t *suppattr, /* IPP -supported attribute */
+ *defattr; /* IPP -default attribute */
+ char line[256], /* Line from PPD file */
+ junk[256], /* Extra junk to throw away */
+ *ptr, /* Pointer into line */
+ option[41], /* Option */
+ choice[41]; /* Choice */
+ int jcloption, /* In a JCL option? */
+ linenum; /* Current line number */
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
+
+
+ /*
+ * Open the original PPD file...
+ */
+
+ if ((srcfp = fopen(src, "rb")) == NULL)
+ return (1);
+
+ /*
+ * Create a temporary output file using the destination buffer...
+ */
+
+ if ((dstfd = cupsTempFd(dst, dstsize)) < 0)
+ {
+ fclose(srcfp);
+
+ return (1);
+ }
+
+ if ((dstfp = fdopen(dstfd, "w")) == NULL)
+ {
+ /*
+ * Unable to convert to FILE *...
+ */
+
+ close(dstfd);
+
+ fclose(srcfp);
+
+ return (1);
+ }
+
+ /*
+ * Write a new header explaining that this isn't the original PPD...
+ */
+
+ fputs("*PPD-Adobe: \"4.3\"\n", dstfp);
+
+ curtime = time(NULL);
+ curdate = gmtime(&curtime);
+
+ fprintf(dstfp, "*%% Modified on %04d%02d%02d%02d%02d%02d+0000 by cupsaddsmb\n",
+ curdate->tm_year + 1900, curdate->tm_mon + 1, curdate->tm_mday,
+ curdate->tm_hour, curdate->tm_min, curdate->tm_sec);
+
+ /*
+ * Read the existing PPD file, converting all PJL commands to CUPS
+ * job ticket comments...
+ */
+
+ jcloption = 0;
+ linenum = 0;
+
+ while (ppd_gets(srcfp, line, sizeof(line)) != NULL)
+ {
+ linenum ++;
+
+ if (!strncmp(line, "*PPD-Adobe:", 11))
+ {
+ /*
+ * Already wrote the PPD header...
+ */
+
+ continue;
+ }
+ else if (!strncmp(line, "*JCLBegin:", 10) ||
+ !strncmp(line, "*JCLToPSInterpreter:", 20) ||
+ !strncmp(line, "*JCLEnd:", 8) ||
+ !strncmp(line, "*Protocols:", 11))
+ {
+ /*
+ * Don't use existing JCL keywords; we'll create our own, below...
+ */
+
+ fprintf(dstfp, "*%% Commented out by cupsaddsmb...\n*%%%s", line + 1);
+ continue;
+ }
+ else if (!strncmp(line, "*JCLOpenUI", 10))
+ {
+ jcloption = 1;
+ fputs(line, dstfp);
+ }
+ else if (!strncmp(line, "*JCLCloseUI", 11))
+ {
+ jcloption = 0;
+ fputs(line, dstfp);
+ }
+ else if (jcloption &&
+ strncmp(line, "*End", 4) &&
+ strncmp(line, "*Default", 8) &&
+ strncmp(line, "*OrderDependency", 16))
+ {
+ if ((ptr = strchr(line, ':')) == NULL)
+ {
+ fprintf(stderr, "cupsaddsmb: Missing value on line %d!\n", linenum);
+ fclose(srcfp);
+ fclose(dstfp);
+ close(dstfd);
+ unlink(dst);
+ return (1);
+ }
+
+ if ((ptr = strchr(ptr, '\"')) == NULL)
+ {
+ fprintf(stderr, "cupsaddsmb: Missing double quote on line %d!\n",
+ linenum);
+ fclose(srcfp);
+ fclose(dstfp);
+ close(dstfd);
+ unlink(dst);
+ return (1);
+ }
+
+ if (sscanf(line, "*%40s%*[ \t]%40[^/]", option, choice) != 2)
+ {
+ fprintf(stderr, "cupsaddsmb: Bad option + choice on line %d!\n",
+ linenum);
+ fclose(srcfp);
+ fclose(dstfp);
+ close(dstfd);
+ unlink(dst);
+ return (1);
+ }
+
+ if (strchr(ptr + 1, '\"') == NULL)
+ {
+ /*
+ * Skip remaining...
+ */
+
+ while (ppd_gets(srcfp, junk, sizeof(junk)) != NULL)
+ {
+ linenum ++;
+
+ if (!strncmp(junk, "*End", 4))
+ break;
+ }
+ }
+
+ snprintf(ptr + 1, sizeof(line) - (ptr - line + 1),
+ "%%cupsJobTicket: %s=%s\n\"\n*End\n", option, choice);
+
+ fprintf(dstfp, "*%% Changed by cupsaddsmb...\n%s", line);
+ }
+ else
+ fputs(line, dstfp);
+ }
+
+ fclose(srcfp);
+
+ /*
+ * Now add the CUPS-specific attributes and options...
+ */
+
+ fputs("\n*% CUPS Job Ticket support and options...\n", dstfp);
+ fputs("*Protocols: PJL\n", dstfp);
+ fputs("*JCLBegin: \"%!PS-Adobe-3.0<0A>\"\n", dstfp);
+ fputs("*JCLToPSInterpreter: \"\"\n", dstfp);
+ fputs("*JCLEnd: \"\"\n", dstfp);
+
+ fputs("\n*OpenGroup: CUPS/CUPS Options\n\n", dstfp);
+
+ if ((defattr = ippFindAttribute(info, "job-hold-until-default",
+ IPP_TAG_ZERO)) != NULL &&
+ (suppattr = ippFindAttribute(info, "job-hold-until-supported",
+ IPP_TAG_ZERO)) != NULL)
+ write_option(dstfp, 10, "cupsJobHoldUntil", "Hold Until", "job-hold-until",
+ suppattr, defattr, 0, 1);
+
+ if ((defattr = ippFindAttribute(info, "job-priority-default",
+ IPP_TAG_INTEGER)) != NULL &&
+ (suppattr = ippFindAttribute(info, "job-priority-supported",
+ IPP_TAG_RANGE)) != NULL)
+ write_option(dstfp, 11, "cupsJobPriority", "Priority", "job-priority",
+ suppattr, defattr, 0, 1);
+
+ if ((defattr = ippFindAttribute(info, "job-sheets-default",
+ IPP_TAG_ZERO)) != NULL &&
+ (suppattr = ippFindAttribute(info, "job-sheets-supported",
+ IPP_TAG_ZERO)) != NULL)
+ {
+ write_option(dstfp, 20, "cupsJobSheetsStart", "Start Banner",
+ "job-sheets", suppattr, defattr, 0, 2);
+ write_option(dstfp, 21, "cupsJobSheetsEnd", "End Banner",
+ "job-sheets", suppattr, defattr, 1, 2);
+ }
+
+ fputs("*CloseGroup: CUPS\n", dstfp);
+
+ fclose(dstfp);
+ close(dstfd);
+
+ return (0);
+}
+
+
+/*
+ * 'do_samba_command()' - Do a SAMBA command, asking for
+ * a password as needed.
+ */
+
+int /* O - Status of command */
+do_samba_command(const char *command, /* I - Command to run */
+ const char *subcmd) /* I - Sub-command */
+{
+ int status; /* Status of command */
+ char temp[4096]; /* Command/prompt string */
+ static const char *p = NULL; /* Password data */
+
+
+ for (status = 1;;)
+ {
+ if (p == NULL)
+ {
+ snprintf(temp, sizeof(temp),
+ "Password for %s required to access %s via SAMBA: ",
+ SAMBAUser, SAMBAServer);
+
+ if ((p = cupsGetPassword(temp)) == NULL)
+ break;
+ }
+
+ snprintf(temp, sizeof(temp), "%s -N -U\'%s%%%s\' -c \'%s\'",
+ command, SAMBAUser, p, subcmd);
+
+ if (Verbosity)
+ printf("Running command: %s\n", temp);
+ else
+ strlcat(temp, " </dev/null >/dev/null 2>/dev/null", sizeof(temp));
+
+ if ((status = system(temp)) != 0)
+ {
+ if (Verbosity)
+ puts("");
+
+ if (p[0])
+ p = NULL;
+ else
+ break;
+ }
+ else
+ {
+ if (Verbosity)
+ puts("");
+
+ break;
+ }
+ }
+
+ return (status);
+}
+
+
+/*
+ * 'export_dest()' - Export a destination to SAMBA.
+ */
+
+int /* O - 0 on success, non-zero on error */
+export_dest(const char *dest) /* I - Destination to export */
+{
+ int status; /* Status of smbclient/rpcclient commands */
+ const char *ppdfile; /* PPD file for printer drivers */
+ char newppd[1024], /* New PPD file for printer drivers */
+ file[1024], /* File to test for */
+ command[1024], /* Command to run */
+ subcmd[1024]; /* Sub-command */
+ const char *datadir; /* CUPS_DATADIR */
+ http_t *http; /* Connection to server */
+ cups_lang_t *language; /* Default language */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ static const char *pattrs[] = /* Printer attributes we want */
+ {
+ "job-hold-until-supported",
+ "job-hold-until-default",
+ "job-sheets-supported",
+ "job-sheets-default",
+ "job-priority-supported",
+ "job-priority-default"
+ };
+
+
+ /*
+ * Get the location of the printer driver files...
+ */
+
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+ datadir = CUPS_DATADIR;
+
+ /*
+ * Open a connection to the scheduler...
+ */
+
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption())) == NULL)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to connect to server \"%s\" for %s - %s\n",
+ cupsServer(), dest, strerror(errno));
+ return (1);
+ }
+
+ /*
+ * Get the PPD file...
+ */
+
+ if ((ppdfile = cupsGetPPD2(http, dest)) == NULL)
+ {
+ fprintf(stderr, "cupsaddsmb: No PPD file for printer \"%s\" - skipping!\n",
+ dest);
+ httpClose(http);
+ return (0);
+ }
+
+ /*
+ * Append the supported banner pages to the PPD file...
+ */
+
+ request = ippNew();
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(command, sizeof(command), "ipp://localhost/printers/%s", dest);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, command);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "cupsaddsmb: get-printer-attributes failed for \"%s\": %s\n",
+ dest, ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ cupsLangFree(language);
+ httpClose(http);
+ unlink(ppdfile);
+ return (2);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "cupsaddsmb: get-printer-attributes failed for \"%s\": %s\n",
+ dest, ippErrorString(cupsLastError()));
+ cupsLangFree(language);
+ httpClose(http);
+ unlink(ppdfile);
+ return (2);
+ }
+
+ /*
+ * Convert the PPD file to the Windows driver format...
+ */
+
+ if (convert_ppd(ppdfile, newppd, sizeof(newppd), response))
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to convert PPD file for %s - %s\n",
+ dest, strerror(errno));
+ ippDelete(response);
+ cupsLangFree(language);
+ httpClose(http);
+ unlink(ppdfile);
+ return (3);
+ }
+
+ ippDelete(response);
+ cupsLangFree(language);
+ httpClose(http);
+
+ /*
+ * Remove the old PPD and point to the new one...
+ */
+
+ unlink(ppdfile);
+
+ ppdfile = newppd;
+
+ /*
+ * See which drivers are available; the new CUPS v6 and Adobe drivers
+ * depend on the Windows 2k PS driver, so copy that driver first:
+ *
+ * Files:
+ *
+ * ps5ui.dll
+ * pscript.hlp
+ * pscript.ntf
+ * pscript5.dll
+ */
+
+ snprintf(file, sizeof(file), "%s/drivers/pscript5.dll", datadir);
+ if (!access(file, 0))
+ {
+ /*
+ * Windows 2k driver is installed; do the smbclient commands needed
+ * to copy the Win2k drivers over...
+ */
+
+ snprintf(command, sizeof(command), "smbclient //%s/print\\$", SAMBAServer);
+
+ snprintf(subcmd, sizeof(subcmd),
+ "mkdir W32X86;"
+ "put %s W32X86/%s.ppd;"
+ "put %s/drivers/ps5ui.dll W32X86/ps5ui.dll;"
+ "put %s/drivers/pscript.hlp W32X86/pscript.hlp;"
+ "put %s/drivers/pscript.ntf W32X86/pscript.ntf;"
+ "put %s/drivers/pscript5.dll W32X86/pscript5.dll",
+ ppdfile, dest, datadir, datadir, datadir, datadir);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to copy Windows 2000 printer driver files (%d)!\n",
+ status);
+ unlink(ppdfile);
+ return (4);
+ }
+
+ /*
+ * See if we also have the CUPS driver files; if so, use them!
+ */
+
+ snprintf(file, sizeof(file), "%s/drivers/cupsdrv6.dll", datadir);
+ if (!access(file, 0))
+ {
+ /*
+ * Copy the CUPS driver files over...
+ */
+
+ snprintf(subcmd, sizeof(subcmd),
+ "put %s/drivers/cupsdrv6.dll W32X86/cupsdrv6.dll;"
+ "put %s/drivers/cupsui6.dll W32X86/cupsui6.dll",
+ datadir, datadir);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to copy CUPS printer driver files (%d)!\n",
+ status);
+ unlink(ppdfile);
+ return (4);
+ }
+
+ /*
+ * Do the rpcclient command needed for the CUPS drivers...
+ */
+
+ snprintf(subcmd, sizeof(subcmd),
+ "adddriver \"Windows NT x86\" \"%s:"
+ "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
+ "cupsdrv6.dll,cupsui6.dll,pscript.ntf\"",
+ dest, dest);
+ }
+ else
+ {
+ /*
+ * Don't have the CUPS drivers, so just use the standard Windows
+ * drivers...
+ */
+
+ snprintf(subcmd, sizeof(subcmd),
+ "adddriver \"Windows NT x86\" \"%s:"
+ "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
+ "pscript.ntf\"",
+ dest, dest);
+ }
+
+ snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to install Windows 2000 printer driver files (%d)!\n",
+ status);
+ unlink(ppdfile);
+ return (5);
+ }
+ }
+
+ snprintf(file, sizeof(file), "%s/drivers/ADOBEPS4.DRV", datadir);
+ if (!access(file, 0))
+ {
+ /*
+ * Do the smbclient commands needed for the Adobe Win9x drivers...
+ */
+
+ snprintf(command, sizeof(command), "smbclient //%s/print\\$", SAMBAServer);
+
+ snprintf(subcmd, sizeof(subcmd),
+ "mkdir WIN40;"
+ "put %s WIN40/%s.PPD;"
+ "put %s/drivers/ADFONTS.MFM WIN40/ADFONTS.MFM;"
+ "put %s/drivers/ADOBEPS4.DRV WIN40/ADOBEPS4.DRV;"
+ "put %s/drivers/ADOBEPS4.HLP WIN40/ADOBEPS4.HLP;"
+ "put %s/drivers/ICONLIB.DLL WIN40/ICONLIB.DLL;"
+ "put %s/drivers/PSMON.DLL WIN40/PSMON.DLL;",
+ ppdfile, dest, datadir, datadir, datadir, datadir, datadir);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to copy Windows 9x printer driver files (%d)!\n",
+ status);
+ unlink(ppdfile);
+ return (6);
+ }
+
+ /*
+ * Do the rpcclient commands needed for the Adobe Win9x drivers...
+ */
+
+ snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer);
+
+ snprintf(subcmd, sizeof(subcmd),
+ "adddriver \"Windows 4.0\" \"%s:ADOBEPS4.DRV:%s.PPD:NULL:"
+ "ADOBEPS4.HLP:PSMON.DLL:RAW:"
+ "ADOBEPS4.DRV,%s.PPD,ADOBEPS4.HLP,PSMON.DLL,ADFONTS.MFM,"
+ "ICONLIB.DLL\"",
+ dest, dest, dest);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to install Windows 9x printer driver files (%d)!\n",
+ status);
+ unlink(ppdfile);
+ return (7);
+ }
+ }
+
+ unlink(ppdfile);
+
+ /*
+ * Finally, associate the drivers we just added with the queue...
+ */
+
+ snprintf(command, sizeof(command), "rpcclient %s", SAMBAServer);
+
+ snprintf(subcmd, sizeof(subcmd), "setdriver %s %s", dest, dest);
+
+ if ((status = do_samba_command(command, subcmd)) != 0)
+ {
+ fprintf(stderr, "cupsaddsmb: Unable to set Windows printer driver (%d)!\n",
+ status);
+ return (8);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'ppd_gets()' - Get a CR and/or LF-terminated line.
+ */
+
+char * /* O - Line read or NULL on eof/error */
+ppd_gets(FILE *fp, /* I - File to read from*/
+ char *buf, /* O - String buffer */
+ int buflen) /* I - Size of string buffer */
+{
+ int ch; /* Character from file */
+ char *ptr, /* Current position in line buffer */
+ *end; /* End of line buffer */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!fp || !buf || buflen < 2 || feof(fp))
+ return (NULL);
+
+ /*
+ * Now loop until we have a valid line...
+ */
+
+ for (ptr = buf, end = buf + buflen - 1; ptr < end ;)
+ {
+ if ((ch = getc(fp)) == EOF)
+ {
+ if (ptr == buf)
+ return (NULL);
+ else
+ break;
+ }
+
+ *ptr++ = ch;
+
+ if (ch == '\r')
+ {
+ /*
+ * Check for CR LF...
+ */
+
+ if ((ch = getc(fp)) != '\n')
+ ungetc(ch, fp);
+ else if (ptr < end)
+ *ptr++ = ch;
+
+ break;
+ }
+ else if (ch == '\n')
+ {
+ /*
+ * Line feed ends a line...
+ */
+
+ break;
+ }
+ }
+
+ *ptr = '\0';
+
+ return (buf);
+}
+
+
+/*
+ * 'usage()' - Show program usage and exit...
+ */
+
+void
+usage(void)
+{
+ puts("Usage: cupsaddsmb [options] printer1 ... printerN");
+ puts(" cupsaddsmb [options] -a");
+ puts("");
+ puts("Options:");
+ puts(" -H samba-server Use the named SAMBA server");
+ puts(" -U samba-user Authenticate using the named SAMBA user");
+ puts(" -a Export all printers");
+ puts(" -h cups-server Use the named CUPS server");
+ puts(" -v Be verbose (show commands)");
+ exit(1);
+}
+
+
+/*
+ * 'write_option()' - Write a CUPS option to a PPD file.
+ */
+
+int /* O - 0 on success, 1 on failure */
+write_option(FILE *dstfp, /* I - PPD file */
+ int order, /* I - Order dependency */
+ const char *name, /* I - Option name */
+ const char *text, /* I - Option text */
+ const char *attrname, /* I - Attribute name */
+ ipp_attribute_t *suppattr, /* I - IPP -supported attribute */
+ ipp_attribute_t *defattr, /* I - IPP -default attribute */
+ int defval, /* I - Default value number */
+ int valcount) /* I - Number of values */
+{
+ int i; /* Looping var */
+
+
+ if (!dstfp || !name || !text || !suppattr || !defattr)
+ return (1);
+
+ fprintf(dstfp, "*JCLOpenUI *%s/%s: PickOne\n"
+ "*OrderDependency: %d JCLSetup *%s\n",
+ name, text, order, name);
+
+ if (defattr->value_tag == IPP_TAG_INTEGER)
+ {
+ /*
+ * Do numeric options with a range or list...
+ */
+
+ fprintf(dstfp, "*Default%s: %d\n", name, defattr->values[defval].integer);
+
+ if (suppattr->value_tag == IPP_TAG_RANGE)
+ {
+ /*
+ * List each number in the range...
+ */
+
+ for (i = suppattr->values[0].range.lower;
+ i <= suppattr->values[0].range.upper;
+ i ++)
+ {
+ fprintf(dstfp, "*%s %d: \"", name, i);
+
+ if (valcount == 1)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%d\n\"\n*End\n", attrname, i);
+ else if (defval == 0)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%d\"\n", attrname, i);
+ else if (defval < (valcount - 1))
+ fprintf(dstfp, ",%d\"\n", i);
+ else
+ fprintf(dstfp, ",%d\n\"\n*End\n", i);
+ }
+ }
+ else
+ {
+ /*
+ * List explicit numbers...
+ */
+
+ for (i = 0; i < suppattr->num_values; i ++)
+ {
+ fprintf(dstfp, "*%s %d: \"", name, suppattr->values[i].integer);
+
+ if (valcount == 1)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%d\n\"\n*End\n", attrname,
+ suppattr->values[i].integer);
+ else if (defval == 0)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%d\"\n", attrname,
+ suppattr->values[i].integer);
+ else if (defval < (valcount - 1))
+ fprintf(dstfp, ",%d\"\n", suppattr->values[i].integer);
+ else
+ fprintf(dstfp, ",%d\n\"\n*End\n", suppattr->values[i].integer);
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Do text options with a list...
+ */
+
+ fprintf(dstfp, "*Default%s: %s\n", name,
+ defattr->values[defval].string.text);
+
+ for (i = 0; i < suppattr->num_values; i ++)
+ {
+ fprintf(dstfp, "*%s %s: \"", name, suppattr->values[i].string.text);
+
+ if (valcount == 1)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%s\n\"\n*End\n", attrname,
+ suppattr->values[i].string.text);
+ else if (defval == 0)
+ fprintf(dstfp, "%%cupsJobTicket: %s=%s\"\n", attrname,
+ suppattr->values[i].string.text);
+ else if (defval < (valcount - 1))
+ fprintf(dstfp, ",%s\"\n", suppattr->values[i].string.text);
+ else
+ fprintf(dstfp, ",%s\n\"\n*End\n", suppattr->values[i].string.text);
+ }
+ }
+
+ fprintf(dstfp, "*JCLCloseUI: *%s\n\n", name);
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c
new file mode 100644
index 000000000..3721f07eb
--- /dev/null
+++ b/systemv/cupstestppd.c
@@ -0,0 +1,1237 @@
+/*
+ * "$Id$"
+ *
+ * PPD test program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * PostScript is a trademark of Adobe Systems, Inc.
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * main() - Main entry for test program.
+ * show_conflicts() - Show option conflicts in a PPD file.
+ * usage() - Show program usage...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+
+/*
+ * Error codes...
+ */
+
+#define ERROR_NONE 0
+#define ERROR_USAGE 1
+#define ERROR_FILE_OPEN 2
+#define ERROR_PPD_FORMAT 3
+#define ERROR_CONFORMANCE 4
+
+
+/*
+ * Local functions...
+ */
+
+void show_conflicts(ppd_file_t *ppd);
+void usage(void);
+
+
+/*
+ * 'main()' - Main entry for test program.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j, k, m, n; /* Looping vars */
+ int len; /* Length of option name */
+ char *opt; /* Option character */
+ const char *ptr; /* Pointer into string */
+ int files; /* Number of files */
+ int verbose; /* Want verbose output? */
+ int status; /* Exit status */
+ int errors; /* Number of conformance errors */
+ int ppdversion; /* PPD spec version in PPD file */
+ ppd_status_t error; /* Status of ppdOpen*() */
+ int line; /* Line number for error */
+ ppd_file_t *ppd; /* PPD file record */
+ ppd_attr_t *attr; /* PPD attribute */
+ ppd_size_t *size; /* Size record */
+ ppd_group_t *group; /* UI group */
+ ppd_option_t *option; /* Standard UI option */
+ ppd_group_t *group2; /* UI group */
+ ppd_option_t *option2; /* Standard UI option */
+ ppd_choice_t *choice; /* Standard UI option choice */
+ static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
+ static char *sections[] = { "ANY", "DOCUMENT", "EXIT",
+ "JCL", "PAGE", "PROLOG" };
+
+
+ /*
+ * Display PPD files for each file listed on the command-line...
+ */
+
+ ppdSetConformance(PPD_CONFORM_STRICT);
+
+ verbose = 0;
+ ppd = NULL;
+ files = 0;
+ status = ERROR_NONE;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-' && argv[i][1])
+ {
+ for (opt = argv[i] + 1; *opt; opt ++)
+ switch (*opt)
+ {
+ case 'q' : /* Quiet mode */
+ if (verbose > 0)
+ {
+ fputs("cupstestppd: The -q option is incompatible with the -v option.\n",
+ stderr);
+ return (1);
+ }
+
+ verbose --;
+ break;
+
+ case 'r' : /* Relaxed mode */
+ ppdSetConformance(PPD_CONFORM_RELAXED);
+ break;
+
+ case 'v' : /* Verbose mode */
+ if (verbose < 0)
+ {
+ fputs("cupstestppd: The -v option is incompatible with the -q option.\n",
+ stderr);
+ return (1);
+ }
+
+ verbose ++;
+ break;
+
+ default :
+ usage();
+ break;
+ }
+ }
+ else
+ {
+ /*
+ * Open the PPD file...
+ */
+
+ if (files && verbose >= 0)
+ putchar('\n');
+
+ files ++;
+
+ if (argv[i][0] == '-')
+ {
+ /*
+ * Read from stdin...
+ */
+
+ if (verbose >= 0)
+ printf("(stdin):");
+
+ ppd = ppdOpen(stdin);
+ }
+ else if (strlen(argv[i]) > 3 &&
+ !strcmp(argv[i] + strlen(argv[i]) - 3, ".gz"))
+ {
+ /*
+ * Read from a gzipped file...
+ */
+
+ char command[1024]; /* Command string */
+ FILE *gunzip; /* Pipe file */
+
+
+ if (verbose >= 0)
+ printf("%s:", argv[i]);
+
+ snprintf(command, sizeof(command), "gunzip -c \"%s\"", argv[i]);
+ gunzip = popen(command, "r");
+ ppd = ppdOpen(gunzip);
+
+ if (gunzip != NULL)
+ pclose(gunzip);
+ }
+ else
+ {
+ /*
+ * Read from a file...
+ */
+
+ if (verbose >= 0)
+ printf("%s:", argv[i]);
+
+ ppd = ppdOpenFile(argv[i]);
+ }
+
+ if (ppd == NULL)
+ {
+ error = ppdLastError(&line);
+
+ if (verbose >= 0)
+ printf(" FAIL\n **FAIL** Unable to open PPD file - ");
+
+ if (error <= PPD_ALLOC_ERROR)
+ {
+ status = ERROR_FILE_OPEN;
+
+ if (verbose >= 0)
+ puts(strerror(errno));
+ }
+ else
+ {
+ status = ERROR_PPD_FORMAT;
+
+ if (verbose >= 0)
+ {
+ printf("%s on line %d.\n", ppdErrorString(error), line);
+
+ switch (error)
+ {
+ case PPD_MISSING_PPDADOBE4 :
+ puts(" REF: Page 42, section 5.2.");
+ break;
+ case PPD_MISSING_VALUE :
+ puts(" REF: Page 20, section 3.4.");
+ break;
+ case PPD_BAD_OPEN_GROUP :
+ case PPD_NESTED_OPEN_GROUP :
+ puts(" REF: Pages 45-46, section 5.2.");
+ break;
+ case PPD_BAD_OPEN_UI :
+ case PPD_NESTED_OPEN_UI :
+ puts(" REF: Pages 42-45, section 5.2.");
+ break;
+ case PPD_BAD_ORDER_DEPENDENCY :
+ puts(" REF: Pages 48-49, section 5.2.");
+ break;
+ case PPD_BAD_UI_CONSTRAINTS :
+ puts(" REF: Pages 52-54, section 5.2.");
+ break;
+ case PPD_MISSING_ASTERISK :
+ puts(" REF: Page 15, section 3.2.");
+ break;
+ case PPD_LINE_TOO_LONG :
+ puts(" REF: Page 15, section 3.1.");
+ break;
+ case PPD_ILLEGAL_CHARACTER :
+ puts(" REF: Page 15, section 3.1.");
+ break;
+ case PPD_ILLEGAL_MAIN_KEYWORD :
+ puts(" REF: Pages 16-17, section 3.2.");
+ break;
+ case PPD_ILLEGAL_OPTION_KEYWORD :
+ puts(" REF: Page 19, section 3.3.");
+ break;
+ case PPD_ILLEGAL_TRANSLATION :
+ puts(" REF: Page 27, section 3.5.");
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ continue;
+ }
+
+ /*
+ * Show the header and then perform basic conformance tests (limited
+ * only by what the CUPS PPD functions actually load...)
+ */
+
+ errors = 0;
+ ppdversion = 43;
+
+ if (verbose > 0)
+ puts("\n DETAILED CONFORMANCE TEST RESULTS");
+
+ if ((attr = ppdFindAttr(ppd, "FormatVersion", NULL)) != NULL &&
+ attr->value)
+ ppdversion = (int)(10 * atof(attr->value) + 0.5);
+
+ if (verbose > 0)
+ {
+ /*
+ * Look for default keywords with no matching option...
+ */
+
+ for (i = 0; i < ppd->num_attrs; i ++)
+ {
+ attr = ppd->attrs[i];
+
+ if (!strcmp(attr->name, "DefaultColorSpace") ||
+ !strcmp(attr->name, "DefaultFont") ||
+ !strcmp(attr->name, "DefaultImageableArea") ||
+ !strcmp(attr->name, "DefaultOutputOrder") ||
+ !strcmp(attr->name, "DefaultPaperDimension") ||
+ !strcmp(attr->name, "DefaultTransfer"))
+ continue;
+
+ if (!strncmp(attr->name, "Default", 7) &&
+ !ppdFindOption(ppd, attr->name + 7))
+ printf(" WARN %s has no corresponding options!\n",
+ attr->name);
+ }
+ }
+
+ if ((attr = ppdFindAttr(ppd, "DefaultImageableArea", NULL)) == NULL)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED DefaultImageableArea");
+ puts(" REF: Page 102, section 5.15.");
+ }
+
+ errors ++;
+ }
+ else if (ppdPageSize(ppd, attr->value) == NULL)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** BAD DefaultImageableArea %s!\n", attr->value);
+ puts(" REF: Page 102, section 5.15.");
+ }
+
+ errors ++;
+ }
+ else
+ {
+ if (verbose > 0)
+ puts(" PASS DefaultImageableArea");
+ }
+
+ if (ppdFindAttr(ppd, "DefaultPaperDimension", NULL) == NULL)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED DefaultPaperDimension");
+ puts(" REF: Page 103, section 5.15.");
+ }
+
+ errors ++;
+ }
+ else if (ppdPageSize(ppd, attr->value) == NULL)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** BAD DefaultPaperDimension %s!\n", attr->value);
+ puts(" REF: Page 103, section 5.15.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS DefaultPaperDimension");
+
+ for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
+ for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
+ {
+ /*
+ * Verify that we have a default choice...
+ */
+
+ if (option->defchoice[0])
+ {
+ if (ppdFindChoice(option, option->defchoice) == NULL &&
+ strcmp(option->defchoice, "Unknown"))
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** BAD Default%s %s\n", option->keyword,
+ option->defchoice);
+ puts(" REF: Page 40, section 4.5.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ printf(" PASS Default%s\n", option->keyword);
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** REQUIRED Default%s\n", option->keyword);
+ puts(" REF: Page 40, section 4.5.");
+ }
+
+ errors ++;
+ }
+ }
+
+ if (ppdFindAttr(ppd, "FileVersion", NULL) != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS FileVersion");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED FileVersion");
+ puts(" REF: Page 56, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppdFindAttr(ppd, "FormatVersion", NULL) != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS FormatVersion");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED FormatVersion");
+ puts(" REF: Page 56, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->lang_encoding != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS LanguageEncoding");
+ }
+ else if (ppdversion > 40)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED LanguageEncoding");
+ puts(" REF: Pages 56-57, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->lang_version != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS LanguageVersion");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED LanguageVersion");
+ puts(" REF: Pages 57-58, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->manufacturer != NULL)
+ {
+ if (!strncasecmp(ppd->manufacturer, "Hewlett-Packard", 15) ||
+ !strncasecmp(ppd->manufacturer, "Hewlett Packard", 15))
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** BAD Manufacturer (should be \"HP\")");
+ puts(" REF: Page 211, table D.1.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS Manufacturer");
+ }
+ else if (ppdversion >= 43)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED Manufacturer");
+ puts(" REF: Pages 58-59, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->modelname != NULL)
+ {
+ for (ptr = ppd->modelname; *ptr; ptr ++)
+ if (!isalnum(*ptr & 255) && !strchr(" ./-+", *ptr))
+ break;
+
+ if (*ptr)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** BAD ModelName - \"%c\" not allowed in string.\n",
+ *ptr);
+ puts(" REF: Pages 59-60, section 5.3.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS ModelName");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED ModelName");
+ puts(" REF: Pages 59-60, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->nickname != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS NickName");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED NickName");
+ puts(" REF: Page 60, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppdFindOption(ppd, "PageSize") != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS PageSize");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED PageSize");
+ puts(" REF: Pages 99-100, section 5.14.");
+ }
+
+ errors ++;
+ }
+
+ if (ppdFindOption(ppd, "PageRegion") != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS PageRegion");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED PageRegion");
+ puts(" REF: Page 100, section 5.14.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->pcfilename != NULL)
+ {
+ if (verbose > 0)
+ puts(" PASS PCFileName");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED PCFileName");
+ puts(" REF: Pages 61-62, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->product != NULL)
+ {
+ if (ppd->product[0] != '(' ||
+ ppd->product[strlen(ppd->product) - 1] != ')')
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** BAD Product - not \"(string)\".");
+ puts(" REF: Page 62, section 5.3.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS Product");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED Product");
+ puts(" REF: Page 62, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if ((attr = ppdFindAttr(ppd, "PSVersion", NULL)) != NULL &&
+ attr->value != NULL)
+ {
+ char junkstr[255]; /* Temp string */
+ int junkint; /* Temp integer */
+
+
+ if (sscanf(attr->value, "(%[^)])%d", junkstr, &junkint) != 2)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** BAD PSVersion - not \"(string) int\".");
+ puts(" REF: Pages 62-64, section 5.3.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS PSVersion");
+ }
+ else
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED PSVersion");
+ puts(" REF: Pages 62-64, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->shortnickname != NULL)
+ {
+ if (strlen(ppd->shortnickname) > 31)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** BAD ShortNickName - longer than 31 chars.");
+ puts(" REF: Pages 64-65, section 5.3.");
+ }
+
+ errors ++;
+ }
+ else if (verbose > 0)
+ puts(" PASS ShortNickName");
+ }
+ else if (ppdversion >= 43)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED ShortNickName");
+ puts(" REF: Page 64-65, section 5.3.");
+ }
+
+ errors ++;
+ }
+
+ if (ppd->patches != NULL && strchr(ppd->patches, '\"') &&
+ strstr(ppd->patches, "*End"))
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** BAD JobPatchFile attribute in file");
+ puts(" REF: Page 24, section 3.4.");
+ }
+
+ errors ++;
+ }
+
+ /*
+ * Check for page sizes without the corresponding ImageableArea or
+ * PaperDimension values...
+ */
+
+ if (ppd->num_sizes == 0)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ puts(" **FAIL** REQUIRED PageSize");
+ puts(" REF: Page 41, section 5.");
+ puts(" REF: Page 99, section 5.14.");
+ }
+
+ errors ++;
+ }
+ else
+ {
+ for (j = 0, size = ppd->sizes; j < ppd->num_sizes; j ++, size ++)
+ {
+ /*
+ * Don't check custom size...
+ */
+
+ if (!strcmp(size->name, "Custom"))
+ continue;
+
+ /*
+ * Check for ImageableArea...
+ */
+
+ if (size->left == 0.0 && size->bottom == 0.0 &&
+ size->right == 0.0 && size->top == 0.0)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** REQUIRED ImageableArea for PageSize %s\n",
+ size->name);
+ puts(" REF: Page 41, section 5.");
+ puts(" REF: Page 102, section 5.15.");
+ }
+
+ errors ++;
+ }
+
+ /*
+ * Check for PaperDimension...
+ */
+
+ if (size->width == 0.0 && size->length == 0.0)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** REQUIRED PaperDimension for PageSize %s\n",
+ size->name);
+ puts(" REF: Page 41, section 5.");
+ puts(" REF: Page 103, section 5.15.");
+ }
+
+ errors ++;
+ }
+ }
+ }
+
+ /*
+ * Check for a duplex option, and for standard values...
+ */
+
+ if ((option = ppdFindOption(ppd, "Duplex")) == NULL)
+ if ((option = ppdFindOption(ppd, "JCLDuplex")) == NULL)
+ if ((option = ppdFindOption(ppd, "EFDuplex")) == NULL)
+ option = ppdFindOption(ppd, "KD03Duplex");
+
+ if (option != NULL)
+ {
+ if (ppdFindChoice(option, "None") == NULL)
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** REQUIRED %s does not define choice None!\n",
+ option->keyword);
+ puts(" REF: Page 122, section 5.17");
+ }
+
+ errors ++;
+ }
+
+ for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
+ if (strcmp(choice->choice, "None") &&
+ strcmp(choice->choice, "DuplexNoTumble") &&
+ strcmp(choice->choice, "DuplexTumble") &&
+ strcmp(choice->choice, "SimplexTumble"))
+ {
+ if (verbose >= 0)
+ {
+ if (!errors && !verbose)
+ puts(" FAIL");
+
+ printf(" **FAIL** Bad %s choice %s!\n",
+ option->keyword, choice->choice);
+ puts(" REF: Page 122, section 5.17");
+ }
+
+ errors ++;
+ }
+ }
+
+ if (errors)
+ status = ERROR_CONFORMANCE;
+ else if (!verbose)
+ puts(" PASS");
+
+ if (verbose >= 0)
+ {
+ if (option &&
+ strcmp(option->keyword, "Duplex") &&
+ strcmp(option->keyword, "JCLDuplex"))
+ {
+ printf(" WARN Duplex option keyword %s should be named Duplex!\n",
+ option->keyword);
+ }
+
+ ppdMarkDefaults(ppd);
+ if (ppdConflicts(ppd))
+ {
+ puts(" WARN Default choices conflicting!");
+
+ show_conflicts(ppd);
+ }
+
+ if (ppdversion < 43)
+ {
+ printf(" WARN Obsolete PPD version %.1f!\n",
+ 0.1f * ppdversion);
+ puts(" REF: Page 42, section 5.2.");
+ }
+
+ if (!ppd->lang_encoding && ppdversion < 41)
+ {
+ puts(" WARN LanguageEncoding required by PPD 4.3 spec.");
+ puts(" REF: Pages 56-57, section 5.3.");
+ }
+
+ if (!ppd->manufacturer && ppdversion < 43)
+ {
+ puts(" WARN Manufacturer required by PPD 4.3 spec.");
+ puts(" REF: Pages 58-59, section 5.3.");
+ }
+
+ /*
+ * Treat a PCFileName attribute longer than 12 characters as
+ * a warning and not a hard error...
+ */
+
+ if (ppd->pcfilename && strlen(ppd->pcfilename) > 12)
+ {
+ puts(" WARN PCFileName longer than 8.3 in violation of PPD spec.");
+ puts(" REF: Pages 61-62, section 5.3.");
+ }
+
+ if (!ppd->shortnickname && ppdversion < 43)
+ {
+ puts(" WARN ShortNickName required by PPD 4.3 spec.");
+ puts(" REF: Pages 64-65, section 5.3.");
+ }
+
+ /*
+ * Check the Protocols line and flag PJL + BCP since TBCP is
+ * usually used with PJL...
+ */
+
+ if (ppd->protocols)
+ {
+ if (strstr(ppd->protocols, "PJL") &&
+ strstr(ppd->protocols, "BCP") &&
+ !strstr(ppd->protocols, "TBCP"))
+ {
+ puts(" WARN Protocols contains both PJL and BCP; expected TBCP.");
+ puts(" REF: Pages 78-79, section 5.7.");
+ }
+
+ if (strstr(ppd->protocols, "PJL") &&
+ (!ppd->jcl_begin || !ppd->jcl_end || !ppd->jcl_ps))
+ {
+ puts(" WARN Protocols contains PJL but JCL attributes are not set.");
+ puts(" REF: Pages 78-79, section 5.7.");
+ }
+ }
+
+ /*
+ * Check for options with a common prefix, e.g. Duplex and Duplexer,
+ * which are errors according to the spec but won't cause problems
+ * with CUPS specifically...
+ */
+
+ for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
+ for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
+ {
+ len = strlen(option->keyword);
+
+ for (m = 0, group2 = ppd->groups;
+ m < ppd->num_groups;
+ m ++, group2 ++)
+ for (n = 0, option2 = group2->options;
+ n < group2->num_options;
+ n ++, option2 ++)
+ if (option != option2 &&
+ len < strlen(option2->keyword) &&
+ !strncmp(option->keyword, option2->keyword, len))
+ {
+ printf(" WARN %s shares a common prefix with %s\n",
+ option->keyword, option2->keyword);
+ puts(" REF: Page 15, section 3.2.");
+ }
+ }
+ }
+
+ if (verbose > 0)
+ {
+ if (errors)
+ printf(" %d ERROR%s FOUND\n", errors, errors == 1 ? "" : "S");
+ else
+ puts(" NO ERRORS FOUND");
+ }
+
+
+ /*
+ * Then list the options, if "-v" was provided...
+ */
+
+ if (verbose > 1)
+ {
+ puts("");
+ printf(" language_level = %d\n", ppd->language_level);
+ printf(" color_device = %s\n", ppd->color_device ? "TRUE" : "FALSE");
+ printf(" variable_sizes = %s\n", ppd->variable_sizes ? "TRUE" : "FALSE");
+ printf(" landscape = %d\n", ppd->landscape);
+
+ switch (ppd->colorspace)
+ {
+ case PPD_CS_CMYK :
+ puts(" colorspace = PPD_CS_CMYK");
+ break;
+ case PPD_CS_CMY :
+ puts(" colorspace = PPD_CS_CMY");
+ break;
+ case PPD_CS_GRAY :
+ puts(" colorspace = PPD_CS_GRAY");
+ break;
+ case PPD_CS_RGB :
+ puts(" colorspace = PPD_CS_RGB");
+ break;
+ default :
+ puts(" colorspace = <unknown>");
+ break;
+ }
+
+ printf(" num_emulations = %d\n", ppd->num_emulations);
+ for (j = 0; j < ppd->num_emulations; j ++)
+ printf(" emulations[%d] = %s\n", j, ppd->emulations[j].name);
+
+ printf(" lang_encoding = %s\n", ppd->lang_encoding);
+ printf(" lang_version = %s\n", ppd->lang_version);
+ printf(" modelname = %s\n", ppd->modelname);
+ printf(" ttrasterizer = %s\n",
+ ppd->ttrasterizer == NULL ? "None" : ppd->ttrasterizer);
+ printf(" manufacturer = %s\n", ppd->manufacturer);
+ printf(" product = %s\n", ppd->product);
+ printf(" nickname = %s\n", ppd->nickname);
+ printf(" shortnickname = %s\n", ppd->shortnickname);
+ printf(" patches = %d bytes\n",
+ ppd->patches == NULL ? 0 : (int)strlen(ppd->patches));
+
+ printf(" num_groups = %d\n", ppd->num_groups);
+ for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++)
+ {
+ printf(" group[%d] = %s\n", j, group->text);
+
+ for (k = 0, option = group->options; k < group->num_options; k ++, option ++)
+ {
+ printf(" options[%d] = %s (%s) %s %s %.0f (%d choices)\n", k,
+ option->keyword, option->text, uis[option->ui],
+ sections[option->section], option->order,
+ option->num_choices);
+
+ if (strcmp(option->keyword, "PageSize") == 0 ||
+ strcmp(option->keyword, "PageRegion") == 0)
+ {
+ for (m = option->num_choices, choice = option->choices;
+ m > 0;
+ m --, choice ++)
+ {
+ size = ppdPageSize(ppd, choice->choice);
+
+ if (size == NULL)
+ printf(" %s (%s) = ERROR", choice->choice, choice->text);
+ else
+ printf(" %s (%s) = %.2fx%.2fin (%.1f,%.1f,%.1f,%.1f)", choice->choice,
+ choice->text, size->width / 72.0, size->length / 72.0,
+ size->left / 72.0, size->bottom / 72.0,
+ size->right / 72.0, size->top / 72.0);
+
+ if (strcmp(option->defchoice, choice->choice) == 0)
+ puts(" *");
+ else
+ putchar('\n');
+ }
+ }
+ else
+ {
+ for (m = option->num_choices, choice = option->choices;
+ m > 0;
+ m --, choice ++)
+ {
+ printf(" %s (%s)", choice->choice, choice->text);
+
+ if (strcmp(option->defchoice, choice->choice) == 0)
+ puts(" *");
+ else
+ putchar('\n');
+ }
+ }
+ }
+ }
+
+ printf(" num_profiles = %d\n", ppd->num_profiles);
+ for (j = 0; j < ppd->num_profiles; j ++)
+ printf(" profiles[%d] = %s/%s %.3f %.3f [ %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f ]\n",
+ j, ppd->profiles[j].resolution, ppd->profiles[j].media_type,
+ ppd->profiles[j].gamma, ppd->profiles[j].density,
+ ppd->profiles[j].matrix[0][0], ppd->profiles[j].matrix[0][1],
+ ppd->profiles[j].matrix[0][2], ppd->profiles[j].matrix[1][0],
+ ppd->profiles[j].matrix[1][1], ppd->profiles[j].matrix[1][2],
+ ppd->profiles[j].matrix[2][0], ppd->profiles[j].matrix[2][1],
+ ppd->profiles[j].matrix[2][2]);
+
+ printf(" num_fonts = %d\n", ppd->num_fonts);
+ for (j = 0; j < ppd->num_fonts; j ++)
+ printf(" fonts[%d] = %s\n", j, ppd->fonts[j]);
+
+ printf(" num_attrs = %d\n", ppd->num_attrs);
+ for (j = 0; j < ppd->num_attrs; j ++)
+ printf(" attrs[%d] = %s %s%s%s: \"%s\"\n", j,
+ ppd->attrs[j]->name, ppd->attrs[j]->spec,
+ ppd->attrs[j]->text[0] ? "/" : "", ppd->attrs[j]->text,
+ ppd->attrs[j]->value ? ppd->attrs[j]->value : "(null)");
+ }
+
+ ppdClose(ppd);
+ }
+
+ if (!files)
+ usage();
+
+ return (status);
+}
+
+
+/*
+ * 'show_conflicts()' - Show option conflicts in a PPD file.
+ */
+
+void
+show_conflicts(ppd_file_t *ppd) /* I - PPD to check */
+{
+ int i, j; /* Looping variables */
+ ppd_const_t *c; /* Current constraint */
+ ppd_option_t *o1, *o2; /* Options */
+ ppd_choice_t *c1, *c2; /* Choices */
+
+
+ /*
+ * Loop through all of the UI constraints and report any options
+ * that conflict...
+ */
+
+ for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
+ {
+ /*
+ * Grab pointers to the first option...
+ */
+
+ o1 = ppdFindOption(ppd, c->option1);
+
+ if (o1 == NULL)
+ continue;
+ else if (c->choice1[0] != '\0')
+ {
+ /*
+ * This constraint maps to a specific choice.
+ */
+
+ c1 = ppdFindChoice(o1, c->choice1);
+ }
+ else
+ {
+ /*
+ * This constraint applies to any choice for this option.
+ */
+
+ for (j = o1->num_choices, c1 = o1->choices; j > 0; j --, c1 ++)
+ if (c1->marked)
+ break;
+
+ if (j == 0 ||
+ strcasecmp(c1->choice, "None") == 0 ||
+ strcasecmp(c1->choice, "Off") == 0 ||
+ strcasecmp(c1->choice, "False") == 0)
+ c1 = NULL;
+ }
+
+ /*
+ * Grab pointers to the second option...
+ */
+
+ o2 = ppdFindOption(ppd, c->option2);
+
+ if (o2 == NULL)
+ continue;
+ else if (c->choice2[0] != '\0')
+ {
+ /*
+ * This constraint maps to a specific choice.
+ */
+
+ c2 = ppdFindChoice(o2, c->choice2);
+ }
+ else
+ {
+ /*
+ * This constraint applies to any choice for this option.
+ */
+
+ for (j = o2->num_choices, c2 = o2->choices; j > 0; j --, c2 ++)
+ if (c2->marked)
+ break;
+
+ if (j == 0 ||
+ strcasecmp(c2->choice, "None") == 0 ||
+ strcasecmp(c2->choice, "Off") == 0 ||
+ strcasecmp(c2->choice, "False") == 0)
+ c2 = NULL;
+ }
+
+ /*
+ * If both options are marked then there is a conflict...
+ */
+
+ if (c1 != NULL && c1->marked && c2 != NULL && c2->marked)
+ printf(" WARN \"%s %s\" conflicts with \"%s %s\"\n"
+ " (constraint=\"%s %s %s %s\")\n",
+ o1->keyword, c1->choice, o2->keyword, c2->choice,
+ c->option1, c->choice1, c->option2, c->choice2);
+ }
+}
+
+
+/*
+ * 'usage()' - Show program usage...
+ */
+
+void
+usage(void)
+{
+ puts("Usage: cupstestppd [-q] [-r] [-v[v]] filename1.ppd[.gz] [... filenameN.ppd[.gz]]");
+ puts(" program | cupstestppd [-q] [-r] [-v[v]] -");
+
+ exit(ERROR_USAGE);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lp.c b/systemv/lp.c
new file mode 100644
index 000000000..2cbc23dea
--- /dev/null
+++ b/systemv/lp.c
@@ -0,0 +1,770 @@
+/*
+ * "$Id$"
+ *
+ * "lp" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and send files for printing.
+ * restart_job() - Restart a job.
+ * set_job_attrs() - Set job attributes.
+ * sighandler() - Signal catcher for when we print from stdin...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+
+
+#ifndef WIN32
+# include <unistd.h>
+# include <signal.h>
+
+
+/*
+ * Local functions.
+ */
+
+void sighandler(int);
+#endif /* !WIN32 */
+int restart_job(int job_id);
+int set_job_attrs(int job_id, int num_options, cups_option_t *options);
+
+
+/*
+ * Globals...
+ */
+
+char tempfile[1024]; /* Temporary file for printing from stdin */
+
+
+/*
+ * 'main()' - Parse options and send files for printing.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping vars */
+ int job_id; /* Job ID */
+ char *printer, /* Printer name */
+ *instance, /* Instance name */
+ *val, /* Option value */
+ *title; /* Job title */
+ int priority; /* Job priority (1-100) */
+ int num_copies; /* Number of copies per file */
+ int num_files; /* Number of files to print */
+ const char *files[1000]; /* Files to print */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests, /* Destinations */
+ *dest; /* Selected destination */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ int silent; /* Silent or verbose output? */
+ char buffer[8192]; /* Copy buffer */
+ int temp; /* Temporary file descriptor */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Signal action */
+ struct sigaction oldaction; /* Old signal action */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
+
+
+#ifdef __sun
+ /*
+ * Solaris does some rather strange things to re-queue remote print
+ * jobs. On bootup, the "lp" command is run as "printd" to re-spool
+ * any remote jobs in /var/spool/print. Since CUPS doesn't need this
+ * nonsense, we just need to add the necessary check here to prevent
+ * lp from causing boot problems...
+ */
+
+ if ((val = strrchr(argv[0], '/')) != NULL)
+ val ++;
+ else
+ val = argv[0];
+
+ if (strcmp(val, "printd") == 0)
+ return (0);
+#endif /* __sun */
+
+ silent = 0;
+ printer = NULL;
+ num_dests = 0;
+ dests = NULL;
+ num_options = 0;
+ options = NULL;
+ num_files = 0;
+ title = NULL;
+ job_id = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-' && argv[i][1])
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'c' : /* Copy to spool dir (always enabled) */
+ break;
+
+ case 'd' : /* Destination printer or class */
+ if (argv[i][2] != '\0')
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected destination after -d option!\n", stderr);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
+ {
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ }
+ break;
+
+ case 'f' : /* Form */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected form after -f option!\n", stderr);
+ return (1);
+ }
+ }
+
+ fputs("lp: Warning - form option ignored!\n", stderr);
+ break;
+
+ case 'h' : /* Destination host */
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected hostname after -h option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'i' : /* Change job */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected job ID after -i option!\n", stderr);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ if (num_files > 0)
+ {
+ fputs("lp: Error - cannot print files and alter jobs simultaneously!\n", stderr);
+ return (1);
+ }
+
+ if (strrchr(val, '-') != NULL)
+ job_id = atoi(strrchr(val, '-') + 1);
+ else
+ job_id = atoi(val);
+
+ if (job_id < 0)
+ {
+ fputs("lp: Error - bad job ID!\n", stderr);
+ break;
+ }
+ break;
+
+ case 'm' : /* Send email when job is done */
+#ifdef __sun
+ case 'p' : /* Notify on completion */
+#endif /* __sun */
+ case 'w' : /* Write to console or email */
+ break;
+
+ case 'n' : /* Number of copies */
+ if (argv[i][2] != '\0')
+ num_copies = atoi(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected copies after -n option!\n", stderr);
+ return (1);
+ }
+
+ num_copies = atoi(argv[i]);
+ }
+
+ sprintf(buffer, "%d", num_copies);
+ num_options = cupsAddOption("copies", buffer, num_options, &options);
+ break;
+
+ case 'o' : /* Option */
+ if (argv[i][2] != '\0')
+ num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected option string after -o option!\n", stderr);
+ return (1);
+ }
+
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+ }
+ break;
+
+#ifndef __sun
+ case 'p' : /* Queue priority */
+#endif /* !__sun */
+ case 'q' : /* Queue priority */
+ if (argv[i][2] != '\0')
+ priority = atoi(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fprintf(stderr, "lp: Expected priority after -%c option!\n",
+ argv[i - 1][1]);
+ return (1);
+ }
+
+ priority = atoi(argv[i]);
+ }
+
+ /*
+ * For 100% Solaris compatibility, need to add:
+ *
+ * priority = 99 * (39 - priority) / 39 + 1;
+ *
+ * However, to keep CUPS lp the same across all platforms
+ * we will break compatibility this far...
+ */
+
+ if (priority < 1 || priority > 100)
+ {
+ fputs("lp: Priority must be between 1 and 100.\n", stderr);
+ return (1);
+ }
+
+ sprintf(buffer, "%d", priority);
+ num_options = cupsAddOption("job-priority", buffer, num_options, &options);
+ break;
+
+ case 's' : /* Silent */
+ silent = 1;
+ break;
+
+ case 't' : /* Title */
+ if (argv[i][2] != '\0')
+ title = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected title after -t option!\n", stderr);
+ return (1);
+ }
+
+ title = argv[i];
+ }
+ break;
+
+ case 'y' : /* mode-list */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected mode list after -y option!\n", stderr);
+ return (1);
+ }
+ }
+
+ fputs("lp: Warning - mode option ignored!\n", stderr);
+ break;
+
+ case 'H' : /* Hold job */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected hold name after -H option!\n", stderr);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ if (strcmp(val, "hold") == 0)
+ num_options = cupsAddOption("job-hold-until", "indefinite",
+ num_options, &options);
+ else if (strcmp(val, "resume") == 0 ||
+ strcmp(val, "release") == 0)
+ num_options = cupsAddOption("job-hold-until", "no-hold",
+ num_options, &options);
+ else if (strcmp(val, "immediate") == 0)
+ num_options = cupsAddOption("job-priority", "100",
+ num_options, &options);
+ else if (strcmp(val, "restart") == 0)
+ {
+ if (job_id < 1)
+ {
+ fputs("lp: Need job ID (-i) before \"-H restart\"!\n", stderr);
+ return (1);
+ }
+
+ if (restart_job(job_id))
+ return (1);
+ }
+ else
+ num_options = cupsAddOption("job-hold-until", val,
+ num_options, &options);
+ break;
+
+ case 'P' : /* Page list */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected page list after -P option!\n", stderr);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ num_options = cupsAddOption("page-ranges", val, num_options,
+ &options);
+ break;
+
+ case 'S' : /* character set */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected character set after -S option!\n", stderr);
+ return (1);
+ }
+ }
+
+ fputs("lp: Warning - character set option ignored!\n", stderr);
+ break;
+
+ case 'T' : /* Content-Type */
+ if (!argv[i][2])
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lp: Expected content type after -T option!\n", stderr);
+ return (1);
+ }
+ }
+
+ fputs("lp: Warning - content type option ignored!\n", stderr);
+ break;
+
+ default :
+ fprintf(stderr, "lp: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else if (!strcmp(argv[i], "-"))
+ {
+ if (num_files || job_id)
+ {
+ fputs("lp: Error - cannot print from stdin if files or a job ID are "
+ "provided!\n", stderr);
+ return (1);
+ }
+
+ break;
+ }
+ else if (num_files < 1000 && job_id == 0)
+ {
+ /*
+ * Print a file...
+ */
+
+ if (access(argv[i], R_OK) != 0)
+ {
+ fprintf(stderr, "lp: Unable to access \"%s\" - %s\n", argv[i],
+ strerror(errno));
+ return (1);
+ }
+
+ files[num_files] = argv[i];
+ num_files ++;
+
+ if (title == NULL)
+ {
+ if ((title = strrchr(argv[i], '/')) != NULL)
+ title ++;
+ else
+ title = argv[i];
+ }
+ }
+ else
+ fprintf(stderr, "lp: Too many files - \"%s\"\n", argv[i]);
+
+ /*
+ * See if we are altering an existing job...
+ */
+
+ if (job_id)
+ return (set_job_attrs(job_id, num_options, options));
+
+ /*
+ * See if we have any files to print; if not, print from stdin...
+ */
+
+ if (printer == NULL)
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
+ {
+ printer = dest->name;
+
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ val = NULL;
+
+ if ((printer = getenv("LPDEST")) == NULL)
+ {
+ if ((printer = getenv("PRINTER")) != NULL)
+ {
+ if (!strcmp(printer, "lp"))
+ printer = NULL;
+ else
+ val = "PRINTER";
+ }
+ }
+ else
+ val = "LPDEST";
+
+ if (printer && !cupsGetDest(printer, NULL, num_dests, dests))
+ fprintf(stderr, "lp: error - %s environment variable names non-existent destination \"%s\"!\n",
+ val, printer);
+ else if (cupsLastError() == IPP_NOT_FOUND)
+ fputs("lp: error - no default destination available.\n", stderr);
+ else
+ fputs("lp: error - scheduler not responding!\n", stderr);
+
+ return (1);
+ }
+
+ if (num_files > 0)
+ job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
+ else
+ {
+ num_files = 1;
+
+#ifndef WIN32
+# if defined(HAVE_SIGSET)
+ sigset(SIGHUP, sighandler);
+ if (sigset(SIGINT, sighandler) == SIG_IGN)
+ sigset(SIGINT, SIG_IGN);
+ sigset(SIGTERM, sighandler);
+# elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = sighandler;
+
+ sigaction(SIGHUP, &action, NULL);
+ sigaction(SIGINT, NULL, &oldaction);
+ if (oldaction.sa_handler != SIG_IGN)
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+# else
+ signal(SIGHUP, sighandler);
+ if (signal(SIGINT, sighandler) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, sighandler);
+# endif
+#endif /* !WIN32 */
+
+ temp = cupsTempFd(tempfile, sizeof(tempfile));
+
+ if (temp < 0)
+ {
+ fprintf(stderr, "lp: unable to create temporary file \"%s\" - %s\n",
+ tempfile, strerror(errno));
+ return (1);
+ }
+
+ while ((i = read(0, buffer, sizeof(buffer))) > 0)
+ write(temp, buffer, i);
+
+ i = lseek(temp, 0, SEEK_CUR);
+ close(temp);
+
+ if (i == 0)
+ {
+ fputs("lp: stdin is empty, so no job has been sent.\n", stderr);
+ return (1);
+ }
+
+ if (title)
+ job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
+ else
+ job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
+
+ unlink(tempfile);
+ }
+
+ if (job_id < 1)
+ {
+ fprintf(stderr, "lp: unable to print file: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ else if (!silent)
+ printf("request id is %s-%d (%d file(s))\n", printer, job_id, num_files);
+
+ return (0);
+}
+
+
+/*
+ * 'restart_job()' - Restart a job.
+ */
+
+int /* O - Exit status */
+restart_job(int job_id) /* I - Job ID */
+{
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ cups_lang_t *language; /* Language for request */
+ char uri[HTTP_MAX_URI]; /* URI for job */
+
+
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ language = cupsLangDefault();
+
+ request = ippNew();
+ request->request.op.operation_id = IPP_RESTART_JOB;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lp: restart-job failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lp: restart-job failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'set_job_attrs()' - Set job attributes.
+ */
+
+int /* O - Exit status */
+set_job_attrs(int job_id, /* I - Job ID */
+ int num_options,/* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ http_t *http; /* HTTP connection to server */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ cups_lang_t *language; /* Language for request */
+ char uri[HTTP_MAX_URI]; /* URI for job */
+
+
+ if (num_options == 0)
+ return (0);
+
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ language = cupsLangDefault();
+
+ request = ippNew();
+ request->request.op.operation_id = IPP_SET_JOB_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ sprintf(uri, "ipp://localhost/jobs/%d", job_id);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ cupsEncodeOptions(request, num_options, options);
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lp: set-job-attributes failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lp: set-job-attributes failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+#ifndef WIN32
+/*
+ * 'sighandler()' - Signal catcher for when we print from stdin...
+ */
+
+void
+sighandler(int s) /* I - Signal number */
+{
+ /*
+ * Remove the temporary file we're using to print from stdin...
+ */
+
+ unlink(tempfile);
+
+ /*
+ * Exit...
+ */
+
+ exit(s);
+}
+#endif /* !WIN32 */
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lpadmin.c b/systemv/lpadmin.c
new file mode 100644
index 000000000..ec7556b20
--- /dev/null
+++ b/systemv/lpadmin.c
@@ -0,0 +1,2053 @@
+/*
+ * "$Id$"
+ *
+ * "lpadmin" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and configure the scheduler.
+ * add_printer_to_class() - Add a printer to a class.
+ * default_printer() - Set the default printing destination.
+ * delete_printer() - Delete a printer from the system...
+ * delete_printer_from_class() - Delete a printer from a class.
+ * enable_printer() - Enable a printer...
+ * set_printer_device() - Set the device-uri attribute.
+ * set_printer_file() - Set the interface script or PPD file.
+ * set_printer_info() - Set the printer description string.
+ * set_printer_location() - Set the printer location string.
+ * set_printer_model() - Set the driver model file.
+ * set_printer_options() - Set the printer options.
+ * validate_name() - Make sure the printer name only contains
+ * valid chars...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <config.h>
+#ifdef HAVE_LIBZ
+# include <zlib.h>
+#endif /* HAVE_LIBZ */
+
+
+/*
+ * Local functions...
+ */
+
+static int add_printer_to_class(http_t *, char *, char *);
+static int default_printer(http_t *, char *);
+static int delete_printer(http_t *, char *);
+static int delete_printer_from_class(http_t *, char *, char *);
+static int enable_printer(http_t *, char *);
+static char *get_line(char *, int, FILE *fp);
+static int set_printer_device(http_t *, char *, char *);
+static int set_printer_file(http_t *, char *, char *);
+static int set_printer_info(http_t *, char *, char *);
+static int set_printer_location(http_t *, char *, char *);
+static int set_printer_model(http_t *, char *, char *);
+static int set_printer_options(http_t *, char *, int, cups_option_t *);
+static int validate_name(const char *);
+
+
+/*
+ * 'main()' - Parse options and configure the scheduler.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ http_t *http; /* Connection to server */
+ char *printer, /* Destination printer */
+ *pclass, /* Printer class name */
+ *val; /* Pointer to allow/deny value */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+
+
+ http = NULL;
+ printer = NULL;
+ num_options = 0;
+ options = NULL;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'c' : /* Add printer to class */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to add a printer to the class:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ pclass = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected class name after \'-c\' option!\n", stderr);
+ return (1);
+ }
+
+ pclass = argv[i];
+ }
+
+ if (!validate_name(pclass))
+ {
+ fputs("lpadmin: Class name can only contain printable characters!\n", stderr);
+ return (1);
+ }
+
+ if (add_printer_to_class(http, printer, pclass))
+ return (1);
+ break;
+
+ case 'd' : /* Set as default destination */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected printer name after \'-d\' option!\n", stderr);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if (!validate_name(printer))
+ {
+ fputs("lpadmin: Printer name can only contain printable characters!\n", stderr);
+ return (1);
+ }
+
+ if (default_printer(http, printer))
+ return (1);
+
+ i = argc;
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected hostname after \'-h\' option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'i' : /* Use the specified interface script */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the interface script:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_file(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected interface after \'-i\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_file(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ case 'E' : /* Enable the printer */
+ if (printer == NULL)
+ {
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+ }
+
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (enable_printer(http, printer))
+ return (1);
+ break;
+
+ case 'm' : /* Use the specified standard script/PPD file */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the interface script or PPD file:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_model(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected model after \'-m\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_model(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ case 'o' : /* Set option */
+ if (argv[i][2])
+ num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected name=value after \'-o\' option!\n", stderr);
+ return (1);
+ }
+
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+ }
+ break;
+
+ case 'p' : /* Add/modify a printer */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected printer after \'-p\' option!\n", stderr);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if (!validate_name(printer))
+ {
+ fputs("lpadmin: Printer name can only contain printable characters!\n", stderr);
+ return (1);
+ }
+ break;
+
+ case 'r' : /* Remove printer from class */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to remove a printer from the class:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ pclass = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected class after \'-r\' option!\n", stderr);
+ return (1);
+ }
+
+ pclass = argv[i];
+ }
+
+ if (!validate_name(pclass))
+ {
+ fputs("lpadmin: Class name can only contain printable characters!\n", stderr);
+ return (1);
+ }
+
+ if (delete_printer_from_class(http, printer, pclass))
+ return (1);
+ break;
+
+ case 'u' : /* Allow/deny users */
+ if (argv[i][2])
+ val = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected allow/deny:userlist after \'-u\' option!\n", stderr);
+ return (1);
+ }
+
+ val = argv[i];
+ }
+
+ if (strncasecmp(val, "allow:", 6) == 0)
+ num_options = cupsAddOption("requesting-user-name-allowed",
+ val + 6, num_options, &options);
+ else if (strncasecmp(val, "deny:", 5) == 0)
+ num_options = cupsAddOption("requesting-user-name-denied",
+ val + 5, num_options, &options);
+ else
+ {
+ fprintf(stderr, "lpadmin: Unknown allow/deny option \"%s\"!\n",
+ val);
+ return (1);
+ }
+ break;
+
+ case 'v' : /* Set the device-uri attribute */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the device URI:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_device(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected device URI after \'-v\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_device(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ case 'x' : /* Delete a printer */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected printer or class after \'-x\' option!\n", stderr);
+ return (1);
+ }
+
+ printer = argv[i];
+ }
+
+ if (!validate_name(printer))
+ {
+ fputs("lpadmin: Printer name can only contain printable characters!\n", stderr);
+ return (1);
+ }
+
+ if (delete_printer(http, printer))
+ return (1);
+
+ i = argc;
+ break;
+
+ case 'D' : /* Set the printer-info attribute */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the printer description:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_info(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected description after \'-D\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_info(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ case 'I' : /* Set the supported file types (ignored) */
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected file type(s) after \'-I\' option!\n", stderr);
+ return (1);
+ }
+
+ fputs("lpadmin: Warning - content type list ignored!\n", stderr);
+ break;
+
+ case 'L' : /* Set the printer-location attribute */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the printer location:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_location(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected location after \'-L\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_location(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ case 'P' : /* Use the specified PPD file */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the PPD file:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (argv[i][2])
+ {
+ if (set_printer_file(http, printer, argv[i] + 2))
+ return (1);
+ }
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpadmin: Expected PPD after \'-P\' option!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_file(http, printer, argv[i]))
+ return (1);
+ }
+ break;
+
+ default :
+ fprintf(stderr, "lpadmin: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else
+ {
+ fprintf(stderr, "lpadmin: Unknown argument \'%s\'!\n", argv[i]);
+ return (1);
+ }
+
+ /*
+ * Set options as needed...
+ */
+
+ if (num_options)
+ {
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpadmin: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (printer == NULL)
+ {
+ fputs("lpadmin: Unable to set the printer options:\n", stderr);
+ fputs(" You must specify a printer name first!\n", stderr);
+ return (1);
+ }
+
+ if (set_printer_options(http, printer, num_options, options))
+ return (1);
+ }
+
+ if (printer == NULL)
+ {
+ puts("Usage:");
+ puts("");
+ puts(" lpadmin [-h server] -d destination");
+ puts(" lpadmin [-h server] -x destination");
+ puts(" lpadmin [-h server] -p printer [-c add-class] [-i interface] [-m model]");
+ puts(" [-r remove-class] [-v device] [-D description]");
+ puts(" [-P ppd-file] [-o name=value]");
+ puts(" [-u allow:user,user] [-u deny:user,user]");
+ puts("");
+ }
+
+ if (http)
+ httpClose(http);
+
+ return (0);
+}
+
+
+/*
+ * 'add_printer_to_class()' - Add a printer to a class.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+add_printer_to_class(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer to add */
+ char *pclass) /* I - Class to add to */
+{
+ int i; /* Looping var */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr, /* Current attribute */
+ *members; /* Members in class */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
+ printer, pclass));
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass);
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ response = cupsDoRequest(http, request, "/");
+
+ /*
+ * Build a CUPS_ADD_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * member-uris
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_CLASS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * See if the printer is already in the class...
+ */
+
+ if (response != NULL &&
+ (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
+ for (i = 0; i < members->num_values; i ++)
+ if (strcasecmp(printer, members->values[i].string.text) == 0)
+ {
+ fprintf(stderr, "lpadmin: Printer %s is already a member of class %s.\n",
+ printer, pclass);
+ ippDelete(request);
+ ippDelete(response);
+ return (0);
+ }
+
+ /*
+ * OK, the printer isn't part of the class, so add it...
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ if (response != NULL &&
+ (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
+ {
+ /*
+ * Add the printer to the existing list...
+ */
+
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
+ "member-uris", members->num_values + 1, NULL, NULL);
+ for (i = 0; i < members->num_values; i ++)
+ attr->values[i].string.text = strdup(members->values[i].string.text);
+
+ attr->values[i].string.text = strdup(uri);
+ }
+ else
+ attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL, uri);
+
+ /*
+ * Then send the request...
+ */
+
+ ippDelete(response);
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-class failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-class failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'default_printer()' - Set the default printing destination.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+default_printer(http_t *http, /* I - Server connection */
+ char *printer) /* I - Printer name */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));
+
+ /*
+ * Build a CUPS_SET_DEFAULT request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_SET_DEFAULT;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: set-default failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: set-default failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'delete_printer()' - Delete a printer from the system...
+ */
+
+static int /* O - 0 on success, 1 on fail */
+delete_printer(http_t *http, /* I - Server connection */
+ char *printer) /* I - Printer to delete */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("delete_printer(%p, \"%s\")\n", http, printer));
+
+ /*
+ * Build a CUPS_DELETE_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_DELETE_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: delete-printer failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: delete-printer failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'delete_printer_from_class()' - Delete a printer from a class.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+delete_printer_from_class(http_t *http, /* I - Server connection */
+ char *printer,
+ /* I - Printer to remove */
+ char *pclass)
+ /* I - Class to remove from */
+{
+ int i, j, k; /* Looping vars */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr, /* Current attribute */
+ *members; /* Members in class */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
+ printer, pclass));
+
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", pclass);
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
+ response->request.status.status_code == IPP_NOT_FOUND)
+ {
+ ippDelete(response);
+ fprintf(stderr, "lpadmin: Class %s does not exist!\n", pclass);
+ return (1);
+ }
+
+ /*
+ * See if the printer is already in the class...
+ */
+
+ if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
+ {
+ ippDelete(response);
+ fputs("lpadmin: No member names were seen!\n", stderr);
+ return (1);
+ }
+
+ for (i = 0; i < members->num_values; i ++)
+ if (strcasecmp(printer, members->values[i].string.text) == 0)
+ break;
+
+ if (i >= members->num_values)
+ {
+ fprintf(stderr, "lpadmin: Printer %s is not a member of class %s.\n",
+ printer, pclass);
+ ippDelete(response);
+ return (1);
+ }
+
+ if (members->num_values == 1)
+ {
+ /*
+ * Build a CUPS_DELETE_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_DELETE_CLASS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+ }
+ else
+ {
+ /*
+ * Build a CUPS_ADD_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * member-uris
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_CLASS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Delete the printer from the class...
+ */
+
+ members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
+ "member-uris", members->num_values - 1, NULL, NULL);
+
+ for (j = 0, k = 0; j < members->num_values; j ++)
+ if (j != i)
+ attr->values[k ++].string.text = strdup(members->values[j].string.text);
+ }
+
+ /*
+ * Then send the request...
+ */
+
+ ippDelete(response);
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add/delete-class failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add/delete-class failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'enable_printer()' - Enable a printer...
+ */
+
+static int /* O - 0 on success, 1 on fail */
+enable_printer(http_t *http, /* I - Server connection */
+ char *printer) /* I - Printer to enable */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * printer-state
+ * printer-is-accepting-jobs
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
+ IPP_PRINTER_IDLE);
+
+ ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-printer (enable) failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (enable) failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'get_line()' - Get a line that is terminated by a LF, CR, or CR LF.
+ */
+
+static char * /* O - Pointer to buf or NULL on EOF */
+get_line(char *buf, /* I - Line buffer */
+ int length, /* I - Length of buffer */
+ FILE *fp) /* I - File to read from */
+{
+ char *bufptr; /* Pointer into buffer */
+ int ch; /* Character from file */
+
+
+ length --;
+ bufptr = buf;
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ if (ch == '\n')
+ break;
+ else if (ch == '\r')
+ {
+ /*
+ * Look for LF...
+ */
+
+ ch = getc(fp);
+ if (ch != '\n' && ch != EOF)
+ ungetc(ch, fp);
+
+ break;
+ }
+
+ *bufptr++ = ch;
+ length --;
+ if (length == 0)
+ break;
+ }
+
+ *bufptr = '\0';
+
+ if (ch == EOF)
+ return (NULL);
+ else
+ return (buf);
+}
+
+
+/*
+ * 'set_printer_device()' - Set the device-uri attribute.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_device(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer */
+ char *device) /* I - New device URI */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("set_printer_device(%p, \"%s\", \"%s\")\n", http, printer,
+ device));
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Add the device URI...
+ */
+
+ if (device[0] == '/')
+ {
+ /*
+ * Convert filename to URI...
+ */
+
+ snprintf(uri, sizeof(uri), "file:%s", device);
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
+ uri);
+ }
+ else
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
+ device);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set device) failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set device) failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'set_printer_file()' - Set the interface script or PPD file.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_file(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer */
+ char *file) /* I - PPD file or interface script */
+{
+ ipp_status_t status; /* IPP status code */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+#ifdef HAVE_LIBZ
+ char tempfile[1024]; /* Temporary filename */
+ int fd; /* Temporary file */
+ gzFile *gz; /* GZIP'd file */
+ char buffer[8192]; /* Copy buffer */
+ int bytes; /* Bytes in buffer */
+
+
+ DEBUG_printf(("set_printer_file(%p, \"%s\", \"%s\")\n", http, printer,
+ file));
+
+ /*
+ * See if the file is gzip'd; if so, unzip it to a temporary file and
+ * send the uncompressed file.
+ */
+
+ if (strcmp(file + strlen(file) - 3, ".gz") == 0)
+ {
+ /*
+ * Yes, the file is compressed; uncompress to a temp file...
+ */
+
+ if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ {
+ perror("lpadmin: Unable to create temporary file");
+ return (1);
+ }
+
+ if ((gz = gzopen(file, "rb")) == NULL)
+ {
+ perror("lpadmin: Unable to open file");
+ close(fd);
+ unlink(tempfile);
+ return (1);
+ }
+
+ while ((bytes = gzread(gz, buffer, sizeof(buffer))) > 0)
+ write(fd, buffer, bytes);
+
+ close(fd);
+ gzclose(gz);
+
+ file = tempfile;
+ }
+#endif /* HAVE_LIBZ */
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoFileRequest(http, request, "/admin/", file)) == NULL)
+ status = cupsLastError();
+ else
+ {
+ status = response->request.status.status_code;
+ ippDelete(response);
+ }
+
+#ifdef HAVE_LIBZ
+ /*
+ * Remove the temporary file as needed...
+ */
+
+ if (file == tempfile)
+ unlink(tempfile);
+#endif /* HAVE_LIBZ */
+
+ if (status > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set model) failed: %s\n",
+ ippErrorString(status));
+
+ return (1);
+ }
+ else
+ return (0);
+}
+
+
+/*
+ * 'set_printer_info()' - Set the printer description string.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_info(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer */
+ char *info) /* I - New description string */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("set_printer_info(%p, \"%s\", \"%s\")\n", http, printer,
+ info));
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Add the info string...
+ */
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL,
+ info);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set description) failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set description) failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'set_printer_location()' - Set the printer location string.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_location(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer */
+ char *location) /* I - New location string */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ DEBUG_printf(("set_printer_location(%p, \"%s\", \"%s\")\n", http, printer,
+ location));
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Add the location string...
+ */
+
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL,
+ location);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set location) failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set location) failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'set_printer_model()' - Set the driver model file.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_model(http_t *http, /* I - Server connection */
+ char *printer, /* I - Printer */
+ char *model) /* I - Driver model file */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char uri[HTTP_MAX_URI]; /* URI for printer/class */
+
+
+ /*
+ * Build a CUPS_ADD_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * ppd-name
+ */
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_ADD_PRINTER;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "ppd-name", NULL, model);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set model) failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: add-printer (set model) failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'set_printer_options()' - Set the printer options.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+set_printer_options(http_t *http,/* I - Server connection */
+ char *printer,
+ /* I - Printer */
+ int num_options,
+ /* I - Number of options */
+ cups_option_t *options)
+ /* I - Options */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ cups_lang_t *language; /* Default language */
+ ipp_op_t op; /* Operation to perform */
+ const char *val, /* Option value */
+ *ppdfile; /* PPD filename */
+ char uri[HTTP_MAX_URI], /* URI for printer/class */
+ line[1024], /* Line from PPD file */
+ keyword[1024], /* Keyword from Default line */
+ *keyptr, /* Pointer into keyword... */
+ tempfile[1024]; /* Temporary filename */
+ FILE *in, /* PPD file */
+ *out; /* Temporary file */
+ int outfd; /* Temporary file descriptor */
+ const char *protocol; /* Protocol */
+
+
+ DEBUG_printf(("set_printer_options(%p, \"%s\", %d, %p)\n", http, printer,
+ num_options, options));
+
+ language = cupsLangDefault();
+
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", printer);
+
+ /*
+ * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "printer-type");
+
+ /*
+ * Do the request...
+ */
+
+ op = CUPS_ADD_PRINTER;
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * See what kind of printer or class it is...
+ */
+
+ if ((attr = ippFindAttribute(response, "printer-type", IPP_TAG_ENUM)) != NULL)
+ {
+ if (attr->values[0].integer & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+ {
+ op = CUPS_ADD_CLASS;
+ snprintf(uri, sizeof(uri), "ipp://localhost/classes/%s", printer);
+ }
+ }
+
+ ippDelete(response);
+ }
+
+ /*
+ * Build a CUPS_ADD_PRINTER or CUPS_ADD_CLASS request, which requires
+ * the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * other options
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ /*
+ * Add the options...
+ */
+
+ cupsEncodeOptions(request, num_options, options);
+
+ if (op == CUPS_ADD_PRINTER)
+ ppdfile = cupsGetPPD(printer);
+ else
+ ppdfile = NULL;
+
+ if (ppdfile != NULL)
+ {
+ /*
+ * Set default options in the PPD file...
+ */
+
+ if ((outfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ {
+ fprintf(stderr, "lpadmin: Unable to create temporary file - %s\n",
+ strerror(errno));
+ ippDelete(request);
+ unlink(ppdfile);
+ return (1);
+ }
+
+ if ((in = fopen(ppdfile, "rb")) == NULL)
+ {
+ fprintf(stderr, "lpadmin: Unable to open PPD file \"%s\" - %s\n",
+ ppdfile, strerror(errno));
+ ippDelete(request);
+ unlink(ppdfile);
+ close(outfd);
+ unlink(tempfile);
+ return (1);
+ }
+
+ out = fdopen(outfd, "wb");
+ protocol = cupsGetOption("protocol", num_options, options);
+
+ while (get_line(line, sizeof(line), in) != NULL)
+ {
+ if (!strncmp(line, "*cupsProtocol:", 14) && protocol)
+ {
+ /*
+ * Set a new output protocol (BCP or TBCP) below...
+ */
+
+ continue;
+ }
+ else if (strncmp(line, "*Default", 8))
+ fprintf(out, "%s\n", line);
+ else
+ {
+ /*
+ * Get default option name...
+ */
+
+ strlcpy(keyword, line + 8, sizeof(keyword));
+
+ for (keyptr = keyword; *keyptr; keyptr ++)
+ if (*keyptr == ':' || isspace(*keyptr & 255))
+ break;
+
+ *keyptr = '\0';
+
+ if (strcmp(keyword, "PageRegion") == 0)
+ val = cupsGetOption("PageSize", num_options, options);
+ else
+ val = cupsGetOption(keyword, num_options, options);
+
+ if (val != NULL)
+ fprintf(out, "*Default%s: %s\n", keyword, val);
+ else
+ fprintf(out, "%s\n", line);
+ }
+ }
+
+ if (protocol)
+ fprintf(out, "*cupsProtocol: \"%s\"\n", protocol);
+
+ fclose(in);
+ fclose(out);
+ close(outfd);
+
+ /*
+ * Do the request...
+ */
+
+ response = cupsDoFileRequest(http, request, "/admin/", tempfile);
+
+ /*
+ * Clean up temp files... (TODO: catch signals in case we CTRL-C during
+ * lpadmin)
+ */
+
+ unlink(ppdfile);
+ unlink(tempfile);
+ }
+ else
+ {
+ /*
+ * No PPD file - just set the options...
+ */
+
+ response = cupsDoRequest(http, request, "/admin/");
+ }
+
+ /*
+ * Check the response...
+ */
+
+ if (response == NULL)
+ {
+ fprintf(stderr, "lpadmin: %s failed: %s\n",
+ op == CUPS_ADD_PRINTER ? "add-printer" : "add-class",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpadmin: %s failed: %s\n",
+ op == CUPS_ADD_PRINTER ? "add-printer" : "add-class",
+ ippErrorString(response->request.status.status_code));
+
+ ippDelete(response);
+
+ return (1);
+ }
+ else
+ {
+ ippDelete(response);
+
+ return (0);
+ }
+}
+
+
+/*
+ * 'validate_name()' - Make sure the printer name only contains valid chars.
+ */
+
+static int /* O - 0 if name is no good, 1 if name is good */
+validate_name(const char *name) /* I - Name to check */
+{
+ const char *ptr; /* Pointer into name */
+
+
+ /*
+ * Scan the whole name...
+ */
+
+ for (ptr = name; *ptr; ptr ++)
+ if (*ptr == '@')
+ break;
+ else if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/')
+ return (0);
+
+ /*
+ * All the characters are good; validate the length, too...
+ */
+
+ return ((ptr - name) < 128);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lpinfo.c b/systemv/lpinfo.c
new file mode 100644
index 000000000..99568ebff
--- /dev/null
+++ b/systemv/lpinfo.c
@@ -0,0 +1,454 @@
+/*
+ * "$Id$"
+ *
+ * "lpinfo" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and show information.
+ * show_devices() - Show available devices.
+ * show_models() - Show available PPDs.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <cups/string.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int show_devices(http_t *, int);
+static int show_models(http_t *, int);
+
+
+/*
+ * 'main()' - Parse options and show status information.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ http_t *http; /* Connection to server */
+ int long_status; /* Long listing? */
+
+
+ http = NULL;
+ long_status = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'l' : /* Show long listing */
+ long_status = 1;
+ break;
+
+ case 'm' : /* Show models */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpinfo: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (show_models(http, long_status))
+ return (1);
+ break;
+
+ case 'v' : /* Show available devices */
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpinfo: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ if (show_devices(http, long_status))
+ return (1);
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("Error: need hostname after \'-h\' option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ default :
+ fprintf(stderr, "lpinfo: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else
+ {
+ fprintf(stderr, "lpinfo: Unknown argument \'%s\'!\n", argv[i]);
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_devices()' - Show available devices.
+ */
+
+static int /* O - 0 on success, 1 on failure */
+show_devices(http_t *http, /* I - HTTP connection to server */
+ int long_status)/* I - Long status report? */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *device_class, /* Pointer into device-class */
+ *device_info, /* Pointer into device-info */
+ *device_make, /* Pointer into device-make-and-model */
+ *device_uri; /* Pointer into device-uri */
+
+
+ if (http == NULL)
+ return (1);
+
+ /*
+ * Build a CUPS_GET_DEVICES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_DEVICES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * Loop through the device list and display them...
+ */
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpinfo: cups-get-devices failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a device...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this device...
+ */
+
+ device_class = NULL;
+ device_info = NULL;
+ device_make = NULL;
+ device_uri = NULL;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "device-class") == 0 &&
+ attr->value_tag == IPP_TAG_KEYWORD)
+ device_class = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "device-info") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ device_info = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "device-make-and-model") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ device_make = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "device-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ device_uri = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (device_class == NULL || device_info == NULL ||
+ device_make == NULL || device_uri == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * Display the device...
+ */
+
+ if (long_status)
+ {
+ printf("Device: uri = %s\n", device_uri);
+ printf(" class = %s\n", device_class);
+ printf(" info = %s\n", device_info);
+ printf(" make-and-model = %s\n", device_make);
+ }
+ else
+ printf("%s %s\n", device_class, device_uri);
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpinfo: cups-get-devices failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_models()' - Show available PPDs.
+ */
+
+static int /* O - 0 on success, 1 on failure */
+show_models(http_t *http, /* I - HTTP connection to server */
+ int long_status) /* I - Long status report? */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *ppd_language, /* Pointer into ppd-natural-language */
+ *ppd_make, /* Pointer into ppd-make-and-model */
+ *ppd_name; /* Pointer into ppd-name */
+
+
+ if (http == NULL)
+ return (1);
+
+ /*
+ * Build a CUPS_GET_PPDS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PPDS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * Loop through the device list and display them...
+ */
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpinfo: cups-get-ppds failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a PPD...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this PPD...
+ */
+
+ ppd_language = NULL;
+ ppd_make = NULL;
+ ppd_name = NULL;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "ppd-natural-language") == 0 &&
+ attr->value_tag == IPP_TAG_LANGUAGE)
+ ppd_language = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "ppd-make-and-model") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ ppd_make = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "ppd-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ ppd_name = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (ppd_language == NULL || ppd_make == NULL || ppd_name == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * Display the device...
+ */
+
+ if (long_status)
+ {
+ printf("Model: name = %s\n", ppd_name);
+ printf(" natural_language = %s\n", ppd_language);
+ printf(" make-and-model = %s\n", ppd_make);
+ }
+ else
+ printf("%s %s\n", ppd_name, ppd_make);
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpinfo: cups-get-ppds failed: %s\n",
+ ippErrorString(cupsLastError()));
+
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lpmove.c b/systemv/lpmove.c
new file mode 100644
index 000000000..7399c7139
--- /dev/null
+++ b/systemv/lpmove.c
@@ -0,0 +1,235 @@
+/*
+ * "$Id$"
+ *
+ * "lpmove" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and move jobs.
+ * move_job() - Move a job.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <cups/string.h>
+
+
+/*
+ * Local functions...
+ */
+
+static void move_job(http_t *, int, const char *);
+
+
+/*
+ * 'main()' - Parse options and show status information.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ http_t *http; /* Connection to server */
+ const char *job; /* Job name */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+ const char *dest; /* New destination */
+
+
+ http = NULL;
+ job = NULL;
+ dest = NULL;
+ num_dests = 0;
+ dests = NULL;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("Error: need hostname after \'-h\' option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ default :
+ fprintf(stderr, "lpmove: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else if (job == NULL)
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((job = strrchr(argv[i], '-')) != NULL &&
+ cupsGetDest(argv[i], NULL, num_dests, dests) == NULL)
+ job ++;
+ else
+ job = argv[i];
+ }
+ else if (dest == NULL)
+ dest = argv[i];
+ else
+ {
+ fprintf(stderr, "lpmove: Unknown argument \'%s\'!\n", argv[i]);
+ return (1);
+ }
+
+ if (job == NULL || dest == NULL)
+ {
+ puts("Usage: lpmove job dest");
+ return (1);
+ }
+
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpmove: Unable to connect to server");
+ return (1);
+ }
+ }
+
+ move_job(http, atoi(job), dest);
+
+ return (0);
+}
+
+
+/*
+ * 'move_job()' - Move a job.
+ */
+
+static void
+move_job(http_t *http, /* I - HTTP connection to server */
+ int jobid, /* I - Job ID */
+ const char *dest) /* I - Destination */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ cups_lang_t *language; /* Default language */
+ char job_uri[HTTP_MAX_URI],
+ /* job-uri */
+ printer_uri[HTTP_MAX_URI];
+ /* job-printer-uri */
+
+
+ if (http == NULL)
+ return;
+
+ /*
+ * Build a CUPS_MOVE_JOB request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * job-printer-uri
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_MOVE_JOB;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", jobid);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, job_uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+ NULL, cupsUser());
+
+ snprintf(printer_uri, sizeof(printer_uri), "ipp://localhost/printers/%s", dest);
+ ippAddString(request, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri",
+ NULL, printer_uri);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
+ {
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpmove: move-job failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return;
+ }
+
+ ippDelete(response);
+ }
+ else
+ fprintf(stderr, "lpmove: move-job failed: %s\n",
+ ippErrorString(cupsLastError()));
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lpoptions.c b/systemv/lpoptions.c
new file mode 100644
index 000000000..1f5b6cc89
--- /dev/null
+++ b/systemv/lpoptions.c
@@ -0,0 +1,442 @@
+/*
+ * "$Id$"
+ *
+ * Printer option program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Main entry.
+ * list_group() - List printer-specific options from the PPD group.
+ * list_options() - List printer-specific options from the PPD file.
+ * usage() - Show program usage and exit.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <stdlib.h>
+
+
+/*
+ * Local functions...
+ */
+
+void list_group(ppd_group_t *group);
+void list_options(cups_dest_t *dest);
+void usage(void);
+
+
+/*
+ * 'main()' - Main entry.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, j; /* Looping vars */
+ int changes; /* Did we make changes? */
+ int num_options; /* Number of options */
+ cups_option_t *options; /* Options */
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+ cups_dest_t *dest; /* Current destination */
+ char *printer, /* Printer name */
+ *instance, /* Instance name */
+ *option; /* Current option */
+
+
+ /*
+ * Loop through the command-line arguments...
+ */
+
+ dest = NULL;
+ num_dests = 0;
+ dests = NULL;
+ num_options = 0;
+ options = NULL;
+ changes = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'd' : /* -d printer */
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
+ {
+ fputs("lpoptions: Unknown printer or class!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Set the default destination...
+ */
+
+ for (j = 0; j < num_dests; j ++)
+ dests[j].is_default = 0;
+
+ dest->is_default = 1;
+
+ cupsSetDests(num_dests, dests);
+
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ break;
+
+ case 'h' : /* -h server */
+ if (argv[i][2])
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'E' : /* Encrypt connection */
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+ break;
+
+ case 'l' : /* -l (list options) */
+ if (dest == NULL)
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
+ dest = dests;
+ }
+
+ if (dest == NULL)
+ fputs("lpoptions: No printers!?!\n", stderr);
+ else
+ list_options(dest);
+
+ changes = -1;
+ break;
+
+ case 'o' : /* -o option[=value] */
+ if (argv[i][2])
+ num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ num_options = cupsParseOptions(argv[i], num_options, &options);
+ }
+
+ changes = 1;
+ break;
+
+ case 'p' : /* -p printer */
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL)
+ {
+ num_dests = cupsAddDest(printer, instance, num_dests, &dests);
+ dest = cupsGetDest(printer, instance, num_dests, dests);
+
+ if (dest == NULL)
+ {
+ perror("lpoptions: Unable to add printer or instance");
+ return (1);
+ }
+ }
+
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ break;
+
+ case 'r' : /* -r option (remove) */
+ if (argv[i][2])
+ option = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ option = argv[i];
+ }
+
+ for (j = 0; j < num_options; j ++)
+ if (strcasecmp(options[j].name, option) == 0)
+ {
+ /*
+ * Remove this option...
+ */
+
+ num_options --;
+
+ if (j < num_options)
+ memcpy(options + j, options + j + 1,
+ sizeof(cups_option_t) * (num_options - j));
+ break;
+ }
+
+ changes = 1;
+ break;
+
+ case 'x' : /* -x printer */
+ if (argv[i][2])
+ printer = argv[i] + 2;
+ else
+ {
+ i ++;
+ if (i >= argc)
+ usage();
+
+ printer = argv[i];
+ }
+
+ if ((instance = strrchr(printer, '/')) != NULL)
+ *instance++ = '\0';
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if ((dest = cupsGetDest(printer, instance, num_dests, dests)) != NULL)
+ {
+ cupsFreeOptions(dest->num_options, dest->options);
+
+ /*
+ * If we are "deleting" the default printer, then just set the
+ * number of options to 0; if it is also the system default
+ * then cupsSetDests() will remove it for us...
+ */
+
+ if (dest->is_default)
+ {
+ dest->num_options = 0;
+ dest->options = NULL;
+ }
+ else
+ {
+ num_dests --;
+
+ j = dest - dests;
+ if (j < num_dests)
+ memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t));
+ }
+ }
+
+ cupsSetDests(num_dests, dests);
+ dest = NULL;
+ changes = -1;
+ break;
+
+ default :
+ usage();
+ }
+ }
+ else
+ usage();
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests(&dests);
+
+ if (dest == NULL)
+ {
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
+ {
+ for (j = 0; j < dest->num_options; j ++)
+ if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
+ num_options = cupsAddOption(dest->options[j].name,
+ dest->options[j].value,
+ num_options, &options);
+ }
+ }
+
+ if (dest == NULL)
+ return (0);
+
+ if (changes > 0)
+ {
+ /*
+ * Set printer options...
+ */
+
+ cupsFreeOptions(dest->num_options, dest->options);
+
+ dest->num_options = num_options;
+ dest->options = options;
+
+ cupsSetDests(num_dests, dests);
+ }
+ else if (changes == 0)
+ {
+ num_options = dest->num_options;
+ options = dest->options;
+
+ for (i = 0; i < num_options; i ++)
+ {
+ if (i)
+ putchar(' ');
+
+ if (!options[i].value[0])
+ printf("%s", options[i].name);
+ else if (strchr(options[i].value, ' ') != NULL ||
+ strchr(options[i].value, '\t') != NULL)
+ printf("%s=\'%s\'", options[i].name, options[i].value);
+ else
+ printf("%s=%s", options[i].name, options[i].value);
+ }
+
+ putchar('\n');
+ }
+
+ return (0);
+}
+
+/*
+ * 'list_group()' - List printer-specific options from the PPD group.
+ */
+
+void
+list_group(ppd_group_t *group) /* I - Group to show */
+{
+ int i, j; /* Looping vars */
+ ppd_option_t *option; /* Current option */
+ ppd_choice_t *choice; /* Current choice */
+ ppd_group_t *subgroup; /* Current subgroup */
+
+
+ for (i = group->num_options, option = group->options; i > 0; i --, option ++)
+ {
+ printf("%s/%s:", option->keyword, option->text);
+
+ for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
+ if (choice->marked)
+ printf(" *%s", choice->choice);
+ else
+ printf(" %s", choice->choice);
+
+ putchar('\n');
+ }
+
+ for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
+ list_group(subgroup);
+}
+
+
+/*
+ * 'list_options()' - List printer-specific options from the PPD file.
+ */
+
+void
+list_options(cups_dest_t *dest) /* I - Destination to list */
+{
+ int i; /* Looping var */
+ const char *filename; /* PPD filename */
+ ppd_file_t *ppd; /* PPD data */
+ ppd_group_t *group; /* Current group */
+
+
+ if ((filename = cupsGetPPD(dest->name)) == NULL)
+ {
+ fprintf(stderr, "lpoptions: Destination %s has no PPD file!\n", dest->name);
+ return;
+ }
+
+ if ((ppd = ppdOpenFile(filename)) == NULL)
+ {
+ unlink(filename);
+ fprintf(stderr, "lpoptions: Unable to open PPD file for %s!\n", dest->name);
+ return;
+ }
+
+ ppdMarkDefaults(ppd);
+ cupsMarkOptions(ppd, dest->num_options, dest->options);
+
+ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+ list_group(group);
+
+ ppdClose(ppd);
+ unlink(filename);
+}
+
+
+/*
+ * 'usage()' - Show program usage and exit.
+ */
+
+void
+usage(void)
+{
+ puts("Usage: lpoptions [-h server] [-E] -d printer");
+ puts(" lpoptions [-h server] [-E] [-p printer] -l");
+ puts(" lpoptions [-h server] [-E] -p printer -o option[=value] ...");
+ puts(" lpoptions [-h server] [-E] -x printer");
+
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lppasswd.c b/systemv/lppasswd.c
new file mode 100644
index 000000000..6a70e5d2d
--- /dev/null
+++ b/systemv/lppasswd.c
@@ -0,0 +1,498 @@
+/*
+ * "$Id$"
+ *
+ * MD5 password program for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Add, change, or delete passwords from the MD5 password file.
+ * usage() - Show program usage.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <cups/cups.h>
+#include <cups/md5.h>
+#include <cups/string.h>
+
+#ifndef WIN32
+# include <unistd.h>
+# include <signal.h>
+#endif /* !WIN32 */
+
+
+/*
+ * Operations...
+ */
+
+#define ADD 0
+#define CHANGE 1
+#define DELETE 2
+
+
+/*
+ * Local functions...
+ */
+
+static void usage(FILE *fp);
+
+
+/*
+ * 'main()' - Add, change, or delete passwords from the MD5 password file.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ char *opt; /* Option pointer */
+ const char *username; /* Pointer to username */
+ const char *groupname; /* Pointer to group name */
+ int op; /* Operation (add, change, delete) */
+ const char *passwd; /* Password string */
+ FILE *infile, /* Input file */
+ *outfile; /* Output file */
+ char line[256], /* Line from file */
+ userline[17], /* User from line */
+ groupline[17], /* Group from line */
+ md5line[33], /* MD5-sum from line */
+ md5new[33]; /* New MD5 sum */
+ const char *root; /* CUPS server root directory */
+ char passwdmd5[1024],/* passwd.md5 file */
+ passwdold[1024],/* passwd.old file */
+ passwdnew[1024];/* passwd.tmp file */
+ char *newpass, /* new password */
+ *oldpass; /* old password */
+ int flag; /* Password check flags... */
+ int fd; /* Password file descriptor */
+ int error; /* Write error */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Signal action */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
+
+
+ /*
+ * Check to see if stdin, stdout, and stderr are still open...
+ */
+
+ if (fcntl(0, F_GETFD, &i) ||
+ fcntl(1, F_GETFD, &i) ||
+ fcntl(2, F_GETFD, &i))
+ {
+ /*
+ * No, return exit status 2 and don't try to send any output since
+ * someone is trying to bypass the security on the server.
+ */
+
+ return (2);
+ }
+
+ /*
+ * Find the server directory...
+ *
+ * Don't use CUPS_SERVERROOT unless we're run by the
+ * super user.
+ */
+
+ if (!getuid() && (root = getenv("CUPS_SERVERROOT")) != NULL)
+ {
+ snprintf(passwdmd5, sizeof(passwdmd5), "%s/passwd.md5", root);
+ snprintf(passwdold, sizeof(passwdold), "%s/passwd.old", root);
+ snprintf(passwdnew, sizeof(passwdnew), "%s/passwd.new", root);
+ }
+ else
+ {
+ strcpy(passwdmd5, CUPS_SERVERROOT "/passwd.md5");
+ strcpy(passwdold, CUPS_SERVERROOT "/passwd.old");
+ strcpy(passwdnew, CUPS_SERVERROOT "/passwd.new");
+ }
+
+ /*
+ * Find the default system group: "sys", "system", or "root"...
+ */
+
+ if (getgrnam("sys"))
+ groupname = "sys";
+ else if (getgrnam("system"))
+ groupname = "system";
+ else if (getgrnam("root"))
+ groupname = "root";
+ else
+ groupname = "unknown";
+
+ endgrent();
+
+ username = NULL;
+ op = CHANGE;
+
+ /*
+ * Parse command-line options...
+ */
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ for (opt = argv[i] + 1; *opt; opt ++)
+ switch (*opt)
+ {
+ case 'a' : /* Add */
+ op = ADD;
+ break;
+ case 'x' : /* Delete */
+ op = DELETE;
+ break;
+ case 'g' : /* Group */
+ i ++;
+ if (i >= argc)
+ usage(stderr);
+
+ groupname = argv[i];
+ break;
+ case 'h' : /* Help */
+ usage(stdout);
+ break;
+ default : /* Bad option */
+ usage(stderr);
+ break;
+ }
+ else if (!username)
+ username = argv[i];
+ else
+ usage(stderr);
+
+ /*
+ * See if we are trying to add or delete a password when we aren't logged in
+ * as root...
+ */
+
+ if (getuid() && (op != CHANGE || username))
+ {
+ fputs("lppasswd: Only root can add or delete passwords!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Fill in missing info...
+ */
+
+ if (!username)
+ username = cupsUser();
+
+ oldpass = newpass = NULL;
+
+ /*
+ * Obtain old and new password _before_ locking the database
+ * to keep users from locking the file indefinitely.
+ */
+
+ if (op == CHANGE && getuid())
+ {
+ if ((passwd = cupsGetPassword("Enter old password:")) == NULL)
+ return (1);
+
+ if ((oldpass = strdup(passwd)) == NULL)
+ {
+ perror("lppasswd: Unable to copy password string");
+ return (1);
+ }
+ }
+
+ /*
+ * Now get the new password, if necessary...
+ */
+
+ if (op != DELETE)
+ {
+ if ((passwd = cupsGetPassword("Enter password:")) == NULL)
+ return (1);
+
+ if ((newpass = strdup(passwd)) == NULL)
+ {
+ perror("lppasswd: Unable to copy password string!");
+ return (1);
+ }
+
+ if ((passwd = cupsGetPassword("Enter password again:")) == NULL)
+ return (1);
+
+ if (strcmp(passwd, newpass) != 0)
+ {
+ fputs("lppasswd: Sorry, passwords don't match!\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Check that the password contains at least one letter and number.
+ */
+
+ flag = 0;
+
+ for (passwd = newpass; *passwd; passwd ++)
+ if (isdigit(*passwd & 255))
+ flag |= 1;
+ else if (isalpha(*passwd & 255))
+ flag |= 2;
+
+ /*
+ * Only allow passwords that are at least 6 chars, have a letter and
+ * a number, and don't contain the username.
+ */
+
+ if (strlen(newpass) < 6 || strstr(newpass, username) != NULL || flag != 3)
+ {
+ fputs("lppasswd: Sorry, password rejected.\n"
+ "Your password must be at least 6 characters long, cannot contain\n"
+ "your username, and must contain at least one letter and number.\n",
+ stderr);
+ return (1);
+ }
+ }
+
+ /*
+ * Ignore SIGHUP, SIGINT, SIGTERM, and SIGXFSZ (if defined) for the
+ * remainder of the time so that we won't end up with bogus password
+ * files...
+ */
+
+#ifndef WIN32
+# if defined(HAVE_SIGSET)
+ sigset(SIGHUP, SIG_IGN);
+ sigset(SIGINT, SIG_IGN);
+ sigset(SIGTERM, SIG_IGN);
+# ifdef SIGXFSZ
+ sigset(SIGXFSZ, SIG_IGN);
+# endif /* SIGXFSZ */
+# elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+
+ sigaction(SIGHUP, &action, NULL);
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+# ifdef SIGXFSZ
+ sigaction(SIGXFSZ, &action, NULL);
+# endif /* SIGXFSZ */
+# else
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+# ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+# endif /* SIGXFSZ */
+# endif
+#endif /* !WIN32 */
+
+ /*
+ * Open the output file.
+ */
+
+ if ((fd = open(passwdnew, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
+ {
+ if (errno == EEXIST)
+ fputs("lppasswd: Password file busy!\n", stderr);
+ else
+ perror("lppasswd: Unable to open passwd file");
+
+ return (1);
+ }
+
+ if ((outfile = fdopen(fd, "w")) == NULL)
+ {
+ perror("lppasswd: Unable to open passwd file");
+
+ unlink(passwdnew);
+
+ return (1);
+ }
+
+ setbuf(outfile, NULL);
+
+ /*
+ * Open the existing password file and create a new one...
+ */
+
+ infile = fopen(passwdmd5, "r");
+ if (infile == NULL && errno != ENOENT && op != ADD)
+ {
+ perror("lppasswd: Unable to open password file");
+
+ fclose(outfile);
+
+ unlink(passwdnew);
+
+ return (1);
+ }
+
+ /*
+ * Read lines from the password file; the format is:
+ *
+ * username:group:MD5-sum
+ */
+
+ error = 0;
+ userline[0] = '\0';
+ groupline[0] = '\0';
+ md5line[0] = '\0';
+
+ if (infile)
+ {
+ while (fgets(line, sizeof(line), infile) != NULL)
+ {
+ if (sscanf(line, "%16[^:]:%16[^:]:%32s", userline, groupline, md5line) != 3)
+ continue;
+
+ if (strcmp(username, userline) == 0 &&
+ strcmp(groupname, groupline) == 0)
+ break;
+
+ if (fputs(line, outfile) == EOF)
+ {
+ perror("lppasswd: Unable to write to password file");
+ error = 1;
+ break;
+ }
+ }
+
+ if (!error)
+ {
+ while (fgets(line, sizeof(line), infile) != NULL)
+ if (fputs(line, outfile) == EOF)
+ {
+ perror("lppasswd: Unable to write to password file");
+ error = 1;
+ break;
+ }
+ }
+ }
+
+ if (op == CHANGE &&
+ (strcmp(username, userline) || strcmp(groupname, groupline)))
+ {
+ fprintf(stderr, "lppasswd: user \"%s\" and group \"%s\" do not exist.\n",
+ username, groupname);
+ error = 1;
+ }
+ else if (op != DELETE)
+ {
+ if (oldpass &&
+ strcmp(httpMD5(username, "CUPS", oldpass, md5new), md5line) != 0)
+ {
+ fputs("lppasswd: Sorry, password doesn't match!\n", stderr);
+ error = 1;
+ }
+ else
+ {
+ snprintf(line, sizeof(line), "%s:%s:%s\n", username, groupname,
+ httpMD5(username, "CUPS", newpass, md5new));
+ if (fputs(line, outfile) == EOF)
+ {
+ perror("lppasswd: Unable to write to password file");
+ error = 1;
+ }
+ }
+ }
+
+ /*
+ * Close the files...
+ */
+
+ if (infile)
+ fclose(infile);
+
+ if (fclose(outfile) == EOF)
+ error = 1;
+
+ /*
+ * Error out gracefully as needed...
+ */
+
+ if (error)
+ {
+ fputs("lppasswd: Password file not updated!\n", stderr);
+
+ unlink(passwdnew);
+
+ return (1);
+ }
+
+ /*
+ * Save old passwd file
+ */
+
+ unlink(passwdold);
+ if (link(passwdmd5, passwdold))
+ {
+ perror("lppasswd: failed to backup old password file");
+ unlink(passwdnew);
+ return (1);
+ }
+
+ /*
+ * Install new password file
+ */
+
+ if (rename(passwdnew, passwdmd5) < 0)
+ {
+ perror("lppasswd: failed to rename password file");
+ unlink(passwdnew);
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'usage()' - Show program usage.
+ */
+
+static void
+usage(FILE *fp) /* I - File to send usage to */
+{
+ if (getuid())
+ {
+ fputs("Usage: lppasswd [-g groupname]\n", fp);
+ }
+ else
+ {
+ fputs("Usage: lppasswd [-g groupname] [username]\n", fp);
+ fputs(" lppasswd [-g groupname] -a [username]\n", fp);
+ fputs(" lppasswd [-g groupname] -x [username]\n", fp);
+ }
+
+ exit(1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/systemv/lpstat.c b/systemv/lpstat.c
new file mode 100644
index 000000000..673ca4bdc
--- /dev/null
+++ b/systemv/lpstat.c
@@ -0,0 +1,2111 @@
+/*
+ * "$Id$"
+ *
+ * "lpstat" command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and show status information.
+ * check_dest() - Verify that the named destination(s) exists.
+ * connect_server() - Connect to the server as necessary...
+ * show_accepting() - Show acceptance status.
+ * show_classes() - Show printer classes.
+ * show_default() - Show default destination.
+ * show_devices() - Show printer devices.
+ * show_jobs() - Show active print jobs.
+ * show_printers() - Show printers.
+ * show_scheduler() - Show scheduler status.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <cups/cups.h>
+#include <cups/language.h>
+#include <cups/debug.h>
+#include <cups/string.h>
+
+
+/*
+ * Local functions...
+ */
+
+static void check_dest(http_t *, const char *, int *, cups_dest_t **);
+static http_t *connect_server(http_t *);
+static int show_accepting(http_t *, const char *, int, cups_dest_t *);
+static int show_classes(http_t *, const char *);
+static void show_default(int, cups_dest_t *);
+static int show_devices(http_t *, const char *, int, cups_dest_t *);
+static int show_jobs(http_t *, const char *, const char *, int, int,
+ const char *);
+static int show_printers(http_t *, const char *, int, cups_dest_t *, int);
+static void show_scheduler(http_t *);
+
+
+/*
+ * 'main()' - Parse options and show status information.
+ */
+
+int
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i, /* Looping var */
+ status; /* Exit status */
+ http_t *http; /* Connection to server */
+ int num_dests; /* Number of user destinations */
+ cups_dest_t *dests; /* User destinations */
+ int long_status; /* Long status report? */
+ int ranking; /* Show job ranking? */
+ const char *which; /* Which jobs to show? */
+ char op; /* Last operation on command-line */
+
+
+#ifdef LC_TIME
+ setlocale(LC_TIME, "");
+#endif /* LC_TIME */
+
+ http = NULL;
+ num_dests = 0;
+ dests = NULL;
+ long_status = 0;
+ ranking = 0;
+ status = 0;
+ which = "not-completed";
+ op = 0;
+
+ for (i = 1; i < argc; i ++)
+ if (argv[i][0] == '-')
+ switch (argv[i][1])
+ {
+ case 'D' : /* Show description */
+ long_status = 1;
+ break;
+
+ case 'E' : /* Encrypt */
+#ifdef HAVE_SSL
+ cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
+
+ if (http)
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+#else
+ fprintf(stderr, "%s: Sorry, no encryption support compiled in!\n",
+ argv[0]);
+#endif /* HAVE_SSL */
+ break;
+
+ case 'P' : /* Show paper types */
+ op = 'P';
+ break;
+
+ case 'R' : /* Show ranking */
+ ranking = 1;
+ break;
+
+ case 'S' : /* Show charsets */
+ op = 'S';
+ if (!argv[i][2])
+ i ++;
+ break;
+
+ case 'W' : /* Show which jobs? */
+ if (argv[i][2])
+ which = argv[i] + 2;
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("lpstat: Need \"completed\" or \"not-completed\" after -W!\n",
+ stderr);
+ return (1);
+ }
+
+ which = argv[i];
+ }
+
+ if (strcmp(which, "completed") && strcmp(which, "not-completed"))
+ {
+ fputs("lpstat: Need \"completed\" or \"not-completed\" after -W!\n",
+ stderr);
+ return (1);
+ }
+ break;
+
+ case 'a' : /* Show acceptance status */
+ op = 'a';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_accepting(http, argv[i] + 2, num_dests, dests);
+ }
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+
+ check_dest(http, argv[i], &num_dests, &dests);
+
+ status |= show_accepting(http, argv[i], num_dests, dests);
+ }
+ else
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ status |= show_accepting(http, NULL, num_dests, dests);
+ }
+ break;
+
+#ifdef __sgi
+ case 'b' : /* Show both the local and remote status */
+ op = 'b';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ /*
+ * The local and remote status are separated by a blank line;
+ * since all CUPS jobs are networked, we only output the
+ * second list for now... In the future, we might further
+ * emulate this by listing the remote server's queue, but
+ * for now this is enough to make the SGI printstatus program
+ * happy...
+ */
+
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ puts("");
+ status |= show_jobs(http, argv[i] + 2, NULL, 3, ranking, which);
+ }
+ else
+ {
+ fputs("lpstat: The -b option requires a destination argument.\n",
+ stderr);
+
+ return (1);
+ }
+ break;
+#endif /* __sgi */
+
+ case 'c' : /* Show classes and members */
+ op = 'c';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_classes(http, argv[i] + 2);
+ }
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+
+ check_dest(http, argv[i], &num_dests, &dests);
+
+ status |= show_classes(http, argv[i]);
+ }
+ else
+ status |= show_classes(http, NULL);
+ break;
+
+ case 'd' : /* Show default destination */
+ op = 'd';
+ http = connect_server(http);
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ show_default(num_dests, dests);
+ break;
+
+ case 'f' : /* Show forms */
+ op = 'f';
+ if (!argv[i][2])
+ i ++;
+ break;
+
+ case 'h' : /* Connect to host */
+ if (http)
+ {
+ httpClose(http);
+ http = NULL;
+ }
+
+ if (argv[i][2] != '\0')
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+
+ if (i >= argc)
+ {
+ fputs("Error: need hostname after \'-h\' option!\n", stderr);
+ return (1);
+ }
+
+ cupsSetServer(argv[i]);
+ }
+ break;
+
+ case 'l' : /* Long status or long job status */
+#ifdef __sgi
+ op = 'l';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_jobs(http, argv[i] + 2, NULL, 3, ranking, which);
+ }
+ else
+#endif /* __sgi */
+ long_status = 2;
+ break;
+
+ case 'o' : /* Show jobs by destination */
+ op = 'o';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_jobs(http, argv[i] + 2, NULL, long_status,
+ ranking, which);
+ }
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+
+ check_dest(http, argv[i], &num_dests, &dests);
+
+ status |= show_jobs(http, argv[i], NULL, long_status,
+ ranking, which);
+ }
+ else
+ status |= show_jobs(http, NULL, NULL, long_status,
+ ranking, which);
+ break;
+
+ case 'p' : /* Show printers */
+ op = 'p';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_printers(http, argv[i] + 2, num_dests, dests, long_status);
+ }
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+
+ check_dest(http, argv[i], &num_dests, &dests);
+
+ status |= show_printers(http, argv[i], num_dests, dests, long_status);
+ }
+ else
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ status |= show_printers(http, NULL, num_dests, dests, long_status);
+ }
+ break;
+
+ case 'r' : /* Show scheduler status */
+ op = 'r';
+ http = connect_server(http);
+
+ show_scheduler(http);
+ break;
+
+ case 's' : /* Show summary */
+ op = 's';
+ http = connect_server(http);
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ show_default(num_dests, dests);
+ status |= show_classes(http, NULL);
+ status |= show_devices(http, NULL, num_dests, dests);
+ break;
+
+ case 't' : /* Show all info */
+ op = 't';
+ http = connect_server(http);
+
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ show_scheduler(http);
+ show_default(num_dests, dests);
+ status |= show_classes(http, NULL);
+ status |= show_devices(http, NULL, num_dests, dests);
+ status |= show_accepting(http, NULL, num_dests, dests);
+ status |= show_printers(http, NULL, num_dests, dests, long_status);
+ status |= show_jobs(http, NULL, NULL, long_status, ranking, which);
+ break;
+
+ case 'u' : /* Show jobs by user */
+ op = 'u';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ status |= show_jobs(http, NULL, argv[i] + 2, long_status,
+ ranking, which);
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+ status |= show_jobs(http, NULL, argv[i], long_status,
+ ranking, which);
+ }
+ else
+ status |= show_jobs(http, NULL, NULL, long_status,
+ ranking, which);
+ break;
+
+ case 'v' : /* Show printer devices */
+ op = 'v';
+ http = connect_server(http);
+
+ if (argv[i][2] != '\0')
+ {
+ check_dest(http, argv[i] + 2, &num_dests, &dests);
+
+ status |= show_devices(http, argv[i] + 2, num_dests, dests);
+ }
+ else if ((i + 1) < argc && argv[i + 1][0] != '-')
+ {
+ i ++;
+
+ check_dest(http, argv[i], &num_dests, &dests);
+
+ status |= show_devices(http, argv[i], num_dests, dests);
+ }
+ else
+ {
+ if (num_dests == 0)
+ num_dests = cupsGetDests2(http, &dests);
+
+ status |= show_devices(http, NULL, num_dests, dests);
+ }
+ break;
+
+
+ default :
+ fprintf(stderr, "lpstat: Unknown option \'%c\'!\n", argv[i][1]);
+ return (1);
+ }
+ else
+ {
+ http = connect_server(http);
+
+ status |= show_jobs(http, argv[i], NULL, long_status, ranking, which);
+ op = 'o';
+ }
+
+ if (!op)
+ {
+ http = connect_server(http);
+
+ status |= show_jobs(http, NULL, cupsUser(), long_status, ranking, which);
+ }
+
+ return (status);
+}
+
+
+/*
+ * 'check_dest()' - Verify that the named destination(s) exists.
+ */
+
+static void
+check_dest(http_t *http, /* I - HTTP connection */
+ const char *name, /* I - Name of printer/class(es) */
+ int *num_dests, /* IO - Number of destinations */
+ cups_dest_t **dests) /* IO - Destinations */
+{
+ const char *dptr;
+ char *pptr,
+ printer[128];
+
+
+ /*
+ * Load the destination list as necessary...
+ */
+
+ if (*num_dests == 0)
+ *num_dests = cupsGetDests2(http, dests);
+
+ /*
+ * Scan the name string for printer/class name(s)...
+ */
+
+ for (dptr = name; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Extract a single destination name from the name string...
+ */
+
+ for (pptr = printer; !isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0';)
+ {
+ if ((pptr - printer) < (sizeof(printer) - 1))
+ *pptr++ = *dptr++;
+ else
+ {
+ fprintf(stderr, "lpstat: Invalid destination name in list \"%s\"!\n", name);
+ exit(1);
+ }
+ }
+
+ *pptr = '\0';
+
+ /*
+ * Check the destination...
+ */
+
+ if (cupsGetDest(printer, NULL, *num_dests, *dests) == NULL)
+ {
+ fprintf(stderr, "lpstat: Unknown destination \"%s\"!\n", printer);
+ exit(1);
+ }
+ }
+}
+
+
+/*
+ * 'connect_server()' - Connect to the server as necessary...
+ */
+
+static http_t * /* O - New HTTP connection */
+connect_server(http_t *http) /* I - Current HTTP connection */
+{
+ if (!http)
+ {
+ http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption());
+
+ if (http == NULL)
+ {
+ perror("lpstat: Unable to connect to server");
+ exit(1);
+ }
+ }
+
+ return (http);
+}
+
+
+/*
+ * 'show_accepting()' - Show acceptance status.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+show_accepting(http_t *http, /* I - HTTP connection to server */
+ const char *printers, /* I - Destinations */
+ int num_dests, /* I - Number of user-defined dests */
+ cups_dest_t *dests) /* I - User-defined destinations */
+{
+ int i; /* Looping var */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *printer, /* Printer name */
+ *message; /* Printer device URI */
+ int accepting; /* Accepting requests? */
+ const char *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ static const char *pattrs[] = /* Attributes we need for printers... */
+ {
+ "printer-name",
+ "printer-state-message",
+ "printer-is-accepting-jobs"
+ };
+
+
+ DEBUG_printf(("show_accepting(%p, %p)\n", http, printers));
+
+ if (http == NULL)
+ return (1);
+
+ if (printers != NULL && strcmp(printers, "all") == 0)
+ printers = NULL;
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ DEBUG_puts("show_accepting: request succeeded...");
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ /*
+ * Loop through the printers returned in the list and display
+ * their devices...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a printer...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this printer...
+ */
+
+ printer = NULL;
+ message = NULL;
+ accepting = 1;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-state-message") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ message = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-is-accepting-jobs") == 0 &&
+ attr->value_tag == IPP_TAG_BOOLEAN)
+ accepting = attr->values[0].boolean;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (printer == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a printer we're interested in...
+ */
+
+ match = printers == NULL;
+
+ if (printers != NULL)
+ {
+ for (dptr = printers; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = printer;
+ *ptr != '\0' && *dptr != '\0' && tolower(*ptr & 255) == tolower(*dptr & 255);
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the printer entry if needed...
+ */
+
+ if (match)
+ {
+ if (accepting)
+ printf("%s accepting requests since Jan 01 00:00\n", printer);
+ else
+ printf("%s not accepting requests since Jan 01 00:00 -\n\t%s\n", printer,
+ message == NULL ? "reason unknown" : message);
+
+ for (i = 0; i < num_dests; i ++)
+ if (strcasecmp(dests[i].name, printer) == 0 && dests[i].instance)
+ {
+ if (accepting)
+ printf("%s/%s accepting requests since Jan 01 00:00\n", printer, dests[i].instance);
+ else
+ printf("%s/%s not accepting requests since Jan 01 00:00 -\n\t%s\n", printer,
+ dests[i].instance,
+ message == NULL ? "reason unknown" : message);
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_classes()' - Show printer classes.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+show_classes(http_t *http, /* I - HTTP connection to server */
+ const char *dests) /* I - Destinations */
+{
+ int i; /* Looping var */
+ ipp_t *request, /* IPP Request */
+ *response, /* IPP Response */
+ *response2; /* IPP response from remote server */
+ http_t *http2; /* Remote server */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *printer, /* Printer class name */
+ *printer_uri; /* Printer class URI */
+ ipp_attribute_t *members; /* Printer members */
+ char method[HTTP_MAX_URI], /* Request method */
+ username[HTTP_MAX_URI], /* Username:password */
+ server[HTTP_MAX_URI], /* Server name */
+ resource[HTTP_MAX_URI]; /* Resource name */
+ int port; /* Port number */
+ const char *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ static const char *cattrs[] = /* Attributes we need for classes... */
+ {
+ "printer-name",
+ "printer-uri-supported",
+ "member-names"
+ };
+
+
+ DEBUG_printf(("show_classes(%p, %p)\n", http, dests));
+
+ if (http == NULL)
+ return (1);
+
+ if (dests != NULL && strcmp(dests, "all") == 0)
+ dests = NULL;
+
+ /*
+ * Build a CUPS_GET_CLASSES request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_CLASSES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(cattrs) / sizeof(cattrs[0]),
+ NULL, cattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ DEBUG_puts("show_classes: request succeeded...");
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpstat: get-classes failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ /*
+ * Loop through the printers returned in the list and display
+ * their devices...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ printer = NULL;
+ printer_uri = NULL;
+ members = NULL;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-uri-supported") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ printer_uri = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "member-names") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ members = attr;
+
+ attr = attr->next;
+ }
+
+ /*
+ * If this is a remote class, grab the class info from the
+ * remote server...
+ */
+
+ response2 = NULL;
+ if (members == NULL && printer_uri != NULL)
+ {
+ httpSeparate(printer_uri, method, username, server, &port, resource);
+
+ if (!strcasecmp(server, http->hostname))
+ http2 = http;
+ else
+ http2 = httpConnectEncrypt(server, port, cupsEncryption());
+
+ if (http2 != NULL)
+ {
+ /*
+ * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(cattrs) / sizeof(cattrs[0]),
+ NULL, cattrs);
+
+ if ((response2 = cupsDoRequest(http2, request, "/")) != NULL)
+ members = ippFindAttribute(response2, "member-names", IPP_TAG_NAME);
+
+ if (http2 != http)
+ httpClose(http2);
+ }
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (printer == NULL)
+ {
+ if (response2)
+ ippDelete(response2);
+
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a printer we're interested in...
+ */
+
+ match = dests == NULL;
+
+ if (dests != NULL)
+ {
+ for (dptr = dests; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = printer;
+ *ptr != '\0' && *dptr != '\0' && tolower(*ptr & 255) == tolower(*dptr & 255);
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the printer entry if needed...
+ */
+
+ if (match)
+ {
+ printf("members of class %s:\n", printer);
+
+ if (members)
+ {
+ for (i = 0; i < members->num_values; i ++)
+ printf("\t%s\n", members->values[i].string.text);
+ }
+ else
+ puts("\tunknown");
+ }
+
+ if (response2)
+ ippDelete(response2);
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpstat: get-classes failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_default()' - Show default destination.
+ */
+
+static void
+show_default(int num_dests, /* I - Number of user-defined dests */
+ cups_dest_t *dests) /* I - User-defined destinations */
+{
+ cups_dest_t *dest; /* Destination */
+ const char *printer, /* Printer name */
+ *val; /* Environment variable name */
+
+ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
+ {
+ if (dest->instance)
+ printf("system default destination: %s/%s\n", dest->name, dest->instance);
+ else
+ printf("system default destination: %s\n", dest->name);
+ }
+ else
+ {
+ val = NULL;
+
+ if ((printer = getenv("LPDEST")) == NULL)
+ {
+ if ((printer = getenv("PRINTER")) != NULL)
+ {
+ if (!strcmp(printer, "lp"))
+ printer = NULL;
+ else
+ val = "PRINTER";
+ }
+ }
+ else
+ val = "LPDEST";
+
+ if (printer && !cupsGetDest(printer, NULL, num_dests, dests))
+ printf("lpstat: error - %s environment variable names non-existent destination \"%s\"!\n",
+ val, printer);
+ else
+ puts("no system default destination");
+ }
+}
+
+
+/*
+ * 'show_devices()' - Show printer devices.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+show_devices(http_t *http, /* I - HTTP connection to server */
+ const char *printers, /* I - Destinations */
+ int num_dests, /* I - Number of user-defined dests */
+ cups_dest_t *dests) /* I - User-defined destinations */
+{
+ int i; /* Looping var */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *printer, /* Printer name */
+ *uri, /* Printer URI */
+ *device, /* Printer device URI */
+ *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ static const char *pattrs[] = /* Attributes we need for printers... */
+ {
+ "printer-name",
+ "printer-uri-supported",
+ "device-uri"
+ };
+
+
+ DEBUG_printf(("show_devices(%p, %p)\n", http, dests));
+
+ if (http == NULL)
+ return (1);
+
+ if (printers != NULL && strcmp(printers, "all") == 0)
+ printers = NULL;
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ DEBUG_puts("show_devices: request succeeded...");
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ /*
+ * Loop through the printers returned in the list and display
+ * their devices...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ printer = NULL;
+ device = NULL;
+ uri = NULL;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "printer-uri-supported") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ uri = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "device-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ device = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (printer == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a printer we're interested in...
+ */
+
+ match = printers == NULL;
+
+ if (printers != NULL)
+ {
+ for (dptr = printers; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = printer;
+ *ptr != '\0' && *dptr != '\0' && tolower(*ptr & 255) == tolower(*dptr & 255);
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the printer entry if needed...
+ */
+
+ if (match)
+ {
+#ifdef __osf__ /* Compaq/Digital like to do it their own way... */
+ char method[HTTP_MAX_URI], /* Components of printer URI */
+ username[HTTP_MAX_URI],
+ hostname[HTTP_MAX_URI],
+ resource[HTTP_MAX_URI];
+ int port;
+
+
+ if (device == NULL)
+ {
+ httpSeparate(uri, method, username, hostname, &port, resource);
+ printf("Output for printer %s is sent to remote printer %s on %s\n",
+ printer, strrchr(resource, '/') + 1, hostname);
+ }
+ else if (strncmp(device, "file:", 5) == 0)
+ printf("Output for printer %s is sent to %s\n", printer, device + 5);
+ else
+ printf("Output for printer %s is sent to %s\n", printer, device);
+
+ for (i = 0; i < num_dests; i ++)
+ if (strcasecmp(printer, dests[i].name) == 0 && dests[i].instance)
+ {
+ if (device == NULL)
+ printf("Output for printer %s/%s is sent to remote printer %s on %s\n",
+ printer, dests[i].instance, strrchr(resource, '/') + 1,
+ hostname);
+ else if (strncmp(device, "file:", 5) == 0)
+ printf("Output for printer %s/%s is sent to %s\n", printer, dests[i].instance, device + 5);
+ else
+ printf("Output for printer %s/%s is sent to %s\n", printer, dests[i].instance, device);
+ }
+#else
+ if (device == NULL)
+ printf("device for %s: %s\n", printer, uri);
+ else if (strncmp(device, "file:", 5) == 0)
+ printf("device for %s: %s\n", printer, device + 5);
+ else
+ printf("device for %s: %s\n", printer, device);
+
+ for (i = 0; i < num_dests; i ++)
+ if (strcasecmp(printer, dests[i].name) == 0 && dests[i].instance)
+ {
+ if (device == NULL)
+ printf("device for %s/%s: %s\n", printer, dests[i].instance, uri);
+ else if (strncmp(device, "file:", 5) == 0)
+ printf("device for %s/%s: %s\n", printer, dests[i].instance, device + 5);
+ else
+ printf("device for %s/%s: %s\n", printer, dests[i].instance, device);
+ }
+#endif /* __osf__ */
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_jobs()' - Show active print jobs.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+show_jobs(http_t *http, /* I - HTTP connection to server */
+ const char *dests, /* I - Destinations */
+ const char *users, /* I - Users */
+ int long_status, /* I - Show long status? */
+ int ranking, /* I - Show job ranking? */
+ const char *which) /* I - Show which jobs? */
+{
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ const char *dest, /* Pointer into job-printer-uri */
+ *username, /* Pointer to job-originating-user-name */
+ *title; /* Pointer to job-name */
+ int rank, /* Rank in queue */
+ jobid, /* job-id */
+ size; /* job-k-octets */
+ time_t jobtime; /* time-at-creation */
+ struct tm *jobdate; /* Date & time */
+ const char *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ char temp[255], /* Temporary buffer */
+ date[32]; /* Date buffer */
+ static const char *jattrs[] = /* Attributes we need for jobs... */
+ {
+ "job-id",
+ "job-k-octets",
+ "job-name",
+ "time-at-creation",
+ "job-printer-uri",
+ "job-originating-user-name"
+ };
+
+
+ DEBUG_printf(("show_jobs(%p, %p, %p)\n", http, dests, users));
+
+ if (http == NULL)
+ return (1);
+
+ if (dests != NULL && strcmp(dests, "all") == 0)
+ dests = NULL;
+
+ /*
+ * Build a IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * job-uri
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]),
+ NULL, jattrs);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+ NULL, "ipp://localhost/jobs/");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
+ NULL, which);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * Loop through the job list and display them...
+ */
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpstat: get-jobs failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ rank = -1;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ jobid = 0;
+ size = 0;
+ username = NULL;
+ dest = NULL;
+ jobtime = 0;
+ title = "no title";
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobid = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ size = attr->values[0].integer * 1024;
+
+ if (strcmp(attr->name, "time-at-creation") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobtime = attr->values[0].integer;
+
+ if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ dest ++;
+
+ if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ username = attr->values[0].string.text;
+
+ if (strcmp(attr->name, "job-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ title = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (dest == NULL || jobid == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a job we're interested in...
+ */
+
+ match = (dests == NULL && users == NULL);
+ rank ++;
+
+ if (dests != NULL)
+ {
+ for (dptr = dests; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = dest;
+ *ptr != '\0' && *dptr != '\0' && tolower(*ptr & 255) == tolower(*dptr & 255);
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ if (users != NULL && username != NULL)
+ {
+ for (dptr = users; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = username;
+ *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the job...
+ */
+
+ if (match)
+ {
+ jobdate = localtime(&jobtime);
+ snprintf(temp, sizeof(temp), "%s-%d", dest, jobid);
+
+ if (long_status == 3)
+ {
+ /*
+ * Show the consolidated output format for the SGI tools...
+ */
+
+ strftime(date, sizeof(date), "%b %d %H:%M", jobdate);
+
+ printf("%s;%s;%d;%s;%s\n", temp, username ? username : "unknown",
+ size, title ? title : "unknown", date);
+ }
+ else
+ {
+ strftime(date, sizeof(date), CUPS_STRFTIME_FORMAT, jobdate);
+
+ if (ranking)
+ printf("%3d %-21s %-13s %8d %s\n", rank, temp,
+ username ? username : "unknown", size, date);
+ else
+ printf("%-23s %-13s %8d %s\n", temp,
+ username ? username : "unknown", size, date);
+ if (long_status)
+ printf("\tqueued for %s\n", dest);
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpstat: get-jobs failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_printers()' - Show printers.
+ */
+
+static int /* O - 0 on success, 1 on fail */
+show_printers(http_t *http, /* I - HTTP connection to server */
+ const char *printers, /* I - Destinations */
+ int num_dests, /* I - Number of user-defined dests */
+ cups_dest_t *dests, /* I - User-defined destinations */
+ int long_status) /* I - Show long status? */
+{
+ int i, j; /* Looping vars */
+ ipp_t *request, /* IPP Request */
+ *response, /* IPP Response */
+ *jobs; /* IPP Get Jobs response */
+ ipp_attribute_t *attr, /* Current attribute */
+ *jobattr, /* Job ID attribute */
+ *reasons; /* Job state reasons attribute */
+ cups_lang_t *language; /* Default language */
+ const char *printer, /* Printer name */
+ *message, /* Printer state message */
+ *description, /* Description of printer */
+ *location, /* Location of printer */
+ *make_model, /* Make and model of printer */
+ *uri; /* URI of printer */
+ ipp_pstate_t pstate; /* Printer state */
+ cups_ptype_t ptype; /* Printer type */
+ int jobid; /* Job ID of current job */
+ const char *dptr, /* Pointer into destination list */
+ *ptr; /* Pointer into printer name */
+ int match; /* Non-zero if this job matches */
+ char printer_uri[HTTP_MAX_URI];
+ /* Printer URI */
+ const char *root; /* Server root directory... */
+ static const char *pattrs[] = /* Attributes we need for printers... */
+ {
+ "printer-name",
+ "printer-state",
+ "printer-state-message",
+ "printer-state-reasons",
+ "printer-type",
+ "printer-info",
+ "printer-location",
+ "printer-make-and-model",
+ "printer-uri-supported"
+ };
+ static const char *jattrs[] = /* Attributes we need for jobs... */
+ {
+ "job-id"
+ };
+
+
+ DEBUG_printf(("show_printers(%p, %p)\n", http, dests));
+
+ if (http == NULL)
+ return (1);
+
+ if ((root = getenv("CUPS_SERVERROOT")) == NULL)
+ root = CUPS_SERVERROOT;
+
+ if (printers != NULL && strcmp(printers, "all") == 0)
+ printers = NULL;
+
+ /*
+ * Build a CUPS_GET_PRINTERS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = CUPS_GET_PRINTERS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ DEBUG_puts("show_printers: request succeeded...");
+
+ if (response->request.status.status_code > IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(response->request.status.status_code));
+ ippDelete(response);
+ return (1);
+ }
+
+ /*
+ * Loop through the printers returned in the list and display
+ * their status...
+ */
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ printer = NULL;
+ ptype = CUPS_PRINTER_LOCAL;
+ pstate = IPP_PRINTER_IDLE;
+ message = NULL;
+ description = NULL;
+ location = NULL;
+ make_model = NULL;
+ reasons = NULL;
+ uri = NULL;
+ jobid = 0;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (strcmp(attr->name, "printer-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ printer = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ pstate = (ipp_pstate_t)attr->values[0].integer;
+ else if (strcmp(attr->name, "printer-type") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ ptype = (cups_ptype_t)attr->values[0].integer;
+ else if (strcmp(attr->name, "printer-state-message") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ message = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-info") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ description = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-location") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ location = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-make-and-model") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ make_model = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-uri-supported") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ uri = attr->values[0].string.text;
+ else if (strcmp(attr->name, "printer-state-reasons") == 0 &&
+ attr->value_tag == IPP_TAG_KEYWORD)
+ reasons = attr;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (printer == NULL)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * See if this is a printer we're interested in...
+ */
+
+ match = printers == NULL;
+
+ if (printers != NULL)
+ {
+ for (dptr = printers; *dptr != '\0';)
+ {
+ /*
+ * Skip leading whitespace and commas...
+ */
+
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+
+ /*
+ * Compare names...
+ */
+
+ for (ptr = printer;
+ *ptr != '\0' && *dptr != '\0' && tolower(*ptr & 255) == tolower(*dptr & 255);
+ ptr ++, dptr ++);
+
+ if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || isspace(*dptr & 255)))
+ {
+ match = 1;
+ break;
+ }
+
+ /*
+ * Skip trailing junk...
+ */
+
+ while (!isspace(*dptr & 255) && *dptr != ',' && *dptr != '\0')
+ dptr ++;
+ while (isspace(*dptr & 255) || *dptr == ',')
+ dptr ++;
+
+ if (*dptr == '\0')
+ break;
+ }
+ }
+
+ /*
+ * Display the printer entry if needed...
+ */
+
+ if (match)
+ {
+ /*
+ * If the printer state is "IPP_PRINTER_PROCESSING", then grab the
+ * current job for the printer.
+ */
+
+ if (pstate == IPP_PRINTER_PROCESSING)
+ {
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * limit
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL,
+ cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language->language);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ sizeof(jattrs) / sizeof(jattrs[0]), NULL, jattrs);
+
+ snprintf(printer_uri, sizeof(printer_uri), "ipp://%s/printers/%s",
+ http->hostname, printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "limit", 1);
+
+ if ((jobs = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ if ((jobattr = ippFindAttribute(jobs, "job-id", IPP_TAG_INTEGER)) != NULL)
+ jobid = jobattr->values[0].integer;
+
+ ippDelete(jobs);
+ }
+ }
+
+ /*
+ * Display it...
+ */
+
+ switch (pstate)
+ {
+ case IPP_PRINTER_IDLE :
+ printf("printer %s is idle. enabled since Jan 01 00:00\n", printer);
+ break;
+ case IPP_PRINTER_PROCESSING :
+ printf("printer %s now printing %s-%d. enabled since Jan 01 00:00\n", printer, printer, jobid);
+ break;
+ case IPP_PRINTER_STOPPED :
+ printf("printer %s disabled since Jan 01 00:00 -\n", printer);
+ break;
+ }
+
+ if ((message && *message) || pstate == IPP_PRINTER_STOPPED)
+ printf("\t%s\n", message == NULL || !*message ? "reason unknown" :
+ message);
+
+ if (long_status > 1)
+ {
+ puts("\tForm mounted:");
+ puts("\tContent types: any");
+ puts("\tPrinter types: unknown");
+ }
+ if (long_status)
+ {
+ printf("\tDescription: %s\n", description ? description : "");
+ if (reasons)
+ {
+ printf("\tAlerts:");
+ for (i = 0; i < reasons->num_values; i ++)
+ printf(" %s", reasons->values[i].string.text);
+ putchar('\n');
+ }
+ }
+ if (long_status > 1)
+ {
+ printf("\tLocation: %s\n", location ? location : "");
+ printf("\tConnection: %s\n",
+ (ptype & CUPS_PRINTER_REMOTE) ? "remote" : "direct");
+ if (!(ptype & CUPS_PRINTER_REMOTE))
+ {
+ if (make_model && strstr(make_model, "System V Printer"))
+ printf("\tInterface: %s/ppd/%s.ppd\n", root, printer);
+ else if (make_model && !strstr(make_model, "Raw Printer"))
+ printf("\tInterface: %s/ppd/%s.ppd\n", root, printer);
+ }
+ else if (make_model && !strstr(make_model, "System V Printer") &&
+ !strstr(make_model, "Raw Printer") && uri)
+ printf("\tInterface: %s.ppd\n", uri);
+
+ puts("\tOn fault: no alert");
+ puts("\tAfter fault: continue");
+ puts("\tUsers allowed:");
+ puts("\t\t(all)");
+ puts("\tForms allowed:");
+ puts("\t\t(none)");
+ puts("\tBanner required");
+ puts("\tCharset sets:");
+ puts("\t\t(none)");
+ puts("\tDefault pitch:");
+ puts("\tDefault page size:");
+ puts("\tDefault port settings:");
+ }
+
+ for (i = 0; i < num_dests; i ++)
+ if (strcasecmp(printer, dests[i].name) == 0 && dests[i].instance)
+ {
+ switch (pstate)
+ {
+ case IPP_PRINTER_IDLE :
+ printf("printer %s/%s is idle. enabled since Jan 01 00:00\n", printer, dests[i].instance);
+ break;
+ case IPP_PRINTER_PROCESSING :
+ printf("printer %s/%s now printing %s-%d. enabled since Jan 01 00:00\n", printer,
+ dests[i].instance, printer, jobid);
+ break;
+ case IPP_PRINTER_STOPPED :
+ printf("printer %s/%s disabled since Jan 01 00:00 -\n", printer,
+ dests[i].instance);
+ break;
+ }
+
+ if ((message && *message) || pstate == IPP_PRINTER_STOPPED)
+ printf("\t%s\n", message == NULL || !*message ? "reason unknown" :
+ message);
+
+ if (long_status > 1)
+ {
+ puts("\tForm mounted:");
+ puts("\tContent types: any");
+ puts("\tPrinter types: unknown");
+ }
+ if (long_status)
+ {
+ printf("\tDescription: %s\n", description ? description : "");
+ if (reasons)
+ {
+ printf("\tAlerts:");
+ for (j = 0; j < reasons->num_values; j ++)
+ printf(" %s", reasons->values[j].string.text);
+ putchar('\n');
+ }
+ }
+ if (long_status > 1)
+ {
+ printf("\tLocation: %s\n", location ? location : "");
+ printf("\tConnection: %s\n",
+ (ptype & CUPS_PRINTER_REMOTE) ? "remote" : "direct");
+ if (!(ptype & CUPS_PRINTER_REMOTE))
+ {
+ if (make_model && strstr(make_model, "System V Printer"))
+ printf("\tInterface: %s/ppd/%s.ppd\n", root, printer);
+ else if (make_model && !strstr(make_model, "Raw Printer"))
+ printf("\tInterface: %s/ppd/%s.ppd\n", root, printer);
+ }
+ else if (make_model && !strstr(make_model, "System V Printer") &&
+ !strstr(make_model, "Raw Printer") && uri)
+ printf("\tInterface: %s.ppd\n", uri);
+ puts("\tOn fault: no alert");
+ puts("\tAfter fault: continue");
+ puts("\tUsers allowed:");
+ puts("\t\t(all)");
+ puts("\tForms allowed:");
+ puts("\t\t(none)");
+ puts("\tBanner required");
+ puts("\tCharset sets:");
+ puts("\t\t(none)");
+ puts("\tDefault pitch:");
+ puts("\tDefault page size:");
+ puts("\tDefault port settings:");
+ }
+ }
+ }
+
+ if (attr == NULL)
+ break;
+ }
+
+ ippDelete(response);
+ }
+ else
+ {
+ fprintf(stderr, "lpstat: get-printers failed: %s\n",
+ ippErrorString(cupsLastError()));
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'show_scheduler()' - Show scheduler status.
+ */
+
+static void
+show_scheduler(http_t *http) /* I - HTTP connection to server */
+{
+ printf("scheduler is %srunning\n", http == NULL ? "not " : "");
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/templates/Makefile b/templates/Makefile
new file mode 100644
index 000000000..f5e693763
--- /dev/null
+++ b/templates/Makefile
@@ -0,0 +1,111 @@
+#
+# "$Id$"
+#
+# Template makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+#
+# Template files...
+#
+
+FILES = add-class.tmpl \
+ add-printer.tmpl \
+ admin-op.tmpl \
+ admin.tmpl \
+ choose-device.tmpl \
+ choose-make.tmpl \
+ choose-members.tmpl \
+ choose-model.tmpl \
+ choose-serial.tmpl \
+ choose-uri.tmpl \
+ class-added.tmpl \
+ class-confirm.tmpl \
+ class-deleted.tmpl \
+ class-modified.tmpl \
+ classes.tmpl \
+ config-printer.tmpl \
+ config-printer2.tmpl \
+ error.tmpl \
+ header.tmpl \
+ jobs.tmpl \
+ job-cancel.tmpl \
+ job-hold.tmpl \
+ job-op.tmpl \
+ job-release.tmpl \
+ job-restart.tmpl \
+ modify-class.tmpl \
+ modify-printer.tmpl \
+ option-boolean.tmpl \
+ option-conflict.tmpl \
+ option-header.tmpl \
+ option-pickmany.tmpl \
+ option-pickone.tmpl \
+ option-trailer.tmpl \
+ printers.tmpl \
+ printer-accept.tmpl \
+ printer-added.tmpl \
+ printer-configured.tmpl \
+ printer-confirm.tmpl \
+ printer-default.tmpl \
+ printer-deleted.tmpl \
+ printer-modified.tmpl \
+ printer-purge.tmpl \
+ printer-reject.tmpl \
+ printer-start.tmpl \
+ printer-stop.tmpl \
+ test-page.tmpl \
+ trailer.tmpl
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/templates
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/templates; \
+ done
+ cd be; $(MAKE) $(MFLAGS) install
+ cd de; $(MAKE) $(MFLAGS) install
+ cd es; $(MAKE) $(MFLAGS) install
+ cd fr; $(MAKE) $(MFLAGS) install
+
+
+#
+# End of "$Id$".
+#
diff --git a/templates/add-class.tmpl b/templates/add-class.tmpl
new file mode 100644
index 000000000..019a3f9fc
--- /dev/null
+++ b/templates/add-class.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Add New Class</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Location:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/add-printer.tmpl b/templates/add-printer.tmpl
new file mode 100644
index 000000000..bf4a33d83
--- /dev/null
+++ b/templates/add-printer.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Add New Printer</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Location:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/admin-op.tmpl b/templates/admin-op.tmpl
new file mode 100644
index 000000000..16699f815
--- /dev/null
+++ b/templates/admin-op.tmpl
@@ -0,0 +1 @@
+<P>Unsupported administration operation "{op}".
diff --git a/templates/admin.tmpl b/templates/admin.tmpl
new file mode 100644
index 000000000..65a711fd7
--- /dev/null
+++ b/templates/admin.tmpl
@@ -0,0 +1,57 @@
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Classes</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-class">
+ <IMG SRC="/images/add-class.gif" ALT="Add a New Class" BORDER="0"></A>
+ <A HREF="/classes/">
+ <IMG SRC="/images/manage-classes.gif" ALT="Manage Available Classes" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Jobs</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/jobs/">
+ <IMG SRC="/images/manage-jobs.gif" ALT="Manage Jobs" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Printers</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-printer">
+ <IMG SRC="/images/add-printer.gif" ALT="Add a New Printer" BORDER="0"></A>
+ <A HREF="/printers/">
+ <IMG SRC="/images/manage-printers.gif" ALT="Manage Available Printers" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+</TABLE>
diff --git a/templates/be/Makefile b/templates/be/Makefile
new file mode 100644
index 000000000..86534cdf9
--- /dev/null
+++ b/templates/be/Makefile
@@ -0,0 +1,106 @@
+#
+# "$Id$"
+#
+# Template makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Template files...
+#
+
+FILES = add-class.tmpl \
+ add-printer.tmpl \
+ admin-op.tmpl \
+ admin.tmpl \
+ choose-device.tmpl \
+ choose-make.tmpl \
+ choose-members.tmpl \
+ choose-model.tmpl \
+ choose-serial.tmpl \
+ choose-uri.tmpl \
+ class-added.tmpl \
+ class-confirm.tmpl \
+ class-deleted.tmpl \
+ class-modified.tmpl \
+ classes.tmpl \
+ config-printer.tmpl \
+ config-printer2.tmpl \
+ error.tmpl \
+ header.tmpl \
+ jobs.tmpl \
+ job-cancel.tmpl \
+ job-hold.tmpl \
+ job-op.tmpl \
+ job-release.tmpl \
+ job-restart.tmpl \
+ modify-class.tmpl \
+ modify-printer.tmpl \
+ option-boolean.tmpl \
+ option-conflict.tmpl \
+ option-header.tmpl \
+ option-pickmany.tmpl \
+ option-pickone.tmpl \
+ option-trailer.tmpl \
+ printers.tmpl \
+ printer-accept.tmpl \
+ printer-added.tmpl \
+ printer-configured.tmpl \
+ printer-confirm.tmpl \
+ printer-deleted.tmpl \
+ printer-modified.tmpl \
+ printer-purge.tmpl \
+ printer-reject.tmpl \
+ printer-start.tmpl \
+ printer-stop.tmpl \
+ test-page.tmpl \
+ trailer.tmpl
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/templates/be
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/templates/be; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/templates/be/add-class.tmpl b/templates/be/add-class.tmpl
new file mode 100644
index 000000000..3cdcd800a
--- /dev/null
+++ b/templates/be/add-class.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Даданьне новае клÑÑÑ‹</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ðазва:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Знаходжаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ÐпіÑаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/add-printer.tmpl b/templates/be/add-printer.tmpl
new file mode 100644
index 000000000..f4cb4ac6b
--- /dev/null
+++ b/templates/be/add-printer.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Даданьне новае друкаркі</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ðазва:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Знаходжаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ÐпіÑаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/admin-op.tmpl b/templates/be/admin-op.tmpl
new file mode 100644
index 000000000..0777cace7
--- /dev/null
+++ b/templates/be/admin-op.tmpl
@@ -0,0 +1 @@
+<P>ÐдмініÑтратыўнае дзеÑньне, Ñкое не падтрымліваецца "{op}".
diff --git a/templates/be/admin.tmpl b/templates/be/admin.tmpl
new file mode 100644
index 000000000..2d10ac09e
--- /dev/null
+++ b/templates/be/admin.tmpl
@@ -0,0 +1,57 @@
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">КлÑÑÑ‹</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-class">
+ <IMG SRC="/images/add-class.gif" ALT="Даданьне новае клÑÑÑ‹" BORDER="0"></A>
+ <A HREF="/classes/">
+ <IMG SRC="/images/manage-classes.gif" ALT="Кіраваньне наÑўнымі клÑÑамі" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Заданьні</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/jobs/">
+ <IMG SRC="/images/manage-jobs.gif" ALT="Кіраваньне заданьнÑмі" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Друкаркі</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-printer">
+ <IMG SRC="/images/add-printer.gif" ALT="Даданьне новае друкаркі" BORDER="0"></A>
+ <A HREF="/printers/">
+ <IMG SRC="/images/manage-printers.gif" ALT="Кіраваньне наÑўнымі друкаркамі" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+</TABLE>
diff --git a/templates/be/choose-device.tmpl b/templates/be/choose-device.tmpl
new file mode 100644
index 000000000..fe42955d9
--- /dev/null
+++ b/templates/be/choose-device.tmpl
@@ -0,0 +1,32 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Прылада Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Прылада:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="DEVICE_URI">
+ {[device_uri]<OPTION VALUE="{device_uri}" {?current_device_uri={device_uri}?SELECTED:}>
+ {device_info} {?device_make_and_model!Unknown?({device_make_and_model}):}
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/choose-make.tmpl b/templates/be/choose-make.tmpl
new file mode 100644
index 000000000..eaf8c9f46
--- /dev/null
+++ b/templates/be/choose-make.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">МадÑль/кіроўца Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Вытворца:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_MAKE" SIZE="10">
+ {[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/choose-members.tmpl b/templates/be/choose-members.tmpl
new file mode 100644
index 000000000..1d9f85a3e
--- /dev/null
+++ b/templates/be/choose-members.tmpl
@@ -0,0 +1,30 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Удзельнікі Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Удзельнікі:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+ {[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/choose-model.tmpl b/templates/be/choose-model.tmpl
new file mode 100644
index 000000000..447bb0135
--- /dev/null
+++ b/templates/be/choose-model.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">МадÑль/кіроўца Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">МадÑль:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_NAME" SIZE="10">
+ {[ppd_name]<OPTION VALUE="{ppd_name}" {?current_make_and_model={ppd_make_and_model}?SELECTED:}>{ppd_make_and_model} ({ppd_natural_language})
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/choose-serial.tmpl b/templates/be/choose-serial.tmpl
new file mode 100644
index 000000000..8a2713d93
--- /dev/null
+++ b/templates/be/choose-serial.tmpl
@@ -0,0 +1,56 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">УÑталёўкі паÑьлÑдоўнага порта Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ХуткаÑьць:&nbsp;</TD>
+ <TD><SELECT NAME="BAUDRATE">
+ {[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ЦотнаÑьць:&nbsp;</TD>
+ <TD><SELECT NAME="PARITY">
+ <OPTION VALUE="none" {?parity=none?SELECTED:}>нÑма
+ <OPTION VALUE="even" {?parity=even?SELECTED:}>цотны
+ <OPTION VALUE="odd" {?parity=odd?SELECTED:}>нÑцотны
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Біты даньнÑÑž:&nbsp;</TD>
+ <TD><SELECT NAME="BITS">
+ <OPTION {?bits=8?SELECTED:}>8
+ <OPTION {?bits=7?SELECTED:}>7
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Кантроль плыні:&nbsp;</TD>
+ <TD><SELECT NAME="FLOW">
+ <OPTION VALUE="none" {?flow=none?SELECTED:}>нÑма
+ <OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (праграмны)
+ <OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (апаратны)
+ <OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (апаратны)
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/choose-uri.tmpl b/templates/be/choose-uri.tmpl
new file mode 100644
index 000000000..3f9e5e3a1
--- /dev/null
+++ b/templates/be/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">URI прылады Ð´Ð»Ñ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">URI прылады:&nbsp;</TD>
+ <TD><INPUT TYPE="TEXT" SIZE="40" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{device_uri}"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD>Прыклады:
+ <PRE>
+ file:/path/to/filename.prn
+ http://hostname:631/ipp/
+ http://hostname:631/ipp/port1
+ ipp://hostname/ipp/
+ ipp://hostname/ipp/port1
+ lpd://hostname/queue
+ socket://hostname
+ socket://hostname:9100
+ </PRE>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/class-added.tmpl b/templates/be/class-added.tmpl
new file mode 100644
index 000000000..9d85acd1e
--- /dev/null
+++ b/templates/be/class-added.tmpl
@@ -0,0 +1,2 @@
+<P>КлÑÑа <A HREF="/classes/{printer_name}">{printer_name}</A> была паÑьпÑхова
+дадана.
diff --git a/templates/be/class-confirm.tmpl b/templates/be/class-confirm.tmpl
new file mode 100644
index 000000000..9f15a01c2
--- /dev/null
+++ b/templates/be/class-confirm.tmpl
@@ -0,0 +1,5 @@
+<P><B>Увага!</B> Ð’Ñ‹ жадаеце выдаліць клÑÑу {printer_name}! Выдаліць?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-class&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Выдаліць" BORDER="0"></A>
diff --git a/templates/be/class-deleted.tmpl b/templates/be/class-deleted.tmpl
new file mode 100644
index 000000000..73d323fda
--- /dev/null
+++ b/templates/be/class-deleted.tmpl
@@ -0,0 +1 @@
+<P>КлÑÑа {printer_name} паÑьпÑхова выдалена.
diff --git a/templates/be/class-modified.tmpl b/templates/be/class-modified.tmpl
new file mode 100644
index 000000000..1bb1ae011
--- /dev/null
+++ b/templates/be/class-modified.tmpl
@@ -0,0 +1 @@
+<P>КлÑÑа <A HREF="/classes/{printer_name}">{printer_name}</A> паÑьпÑхова зьменена.
diff --git a/templates/be/classes.tmpl b/templates/be/classes.tmpl
new file mode 100644
index 000000000..ac8eb6883
--- /dev/null
+++ b/templates/be/classes.tmpl
@@ -0,0 +1,51 @@
+{#printer_name=0?КлÑÑÑ‹ адÑутнічаюць:
+<P><B>Ð”Ð°Ð¿Ð¾Ð¼Ð½Ð°Ñ Ð´Ñ€ÑƒÐºÐ°Ñ€ÐºÐ°:</B> <A HREF="{default_uri}">{default_name}</A>
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">КлÑÑа друкарак</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN=TOP><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/classes.gif" BORDER="0" ALT=""></A></TD>
+ <TD VALIGN=TOP>ÐпіÑаньне: {printer_info}<BR>
+ Знаходжаньне: {printer_location}<BR>
+ Стан клÑÑÑ‹: {printer_state=3?бÑзьдзейнічае:{printer_state=4?друкуе:ÑпыненаÑ}},
+ {printer_is_accepting_jobs=0?не прыймае заданьні:прыймае заданьні}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?member_names=?:<BR>Удзельнікі: {member_names}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Ðадрукаваць Ñ‚ÑÑтавую Ñтаронку" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-class.gif" ALT="ЗапуÑьціць клÑÑу" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-class.gif" ALT="Спыніць клÑÑу" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Дазволіць заданьні" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Забараніць заданьні" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-class&printer_name={printer_name}">
+ <IMG SRC="/images/modify-class.gif" ALT="ЗьмÑніць клÑÑу" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-class&printer_name={printer_name}">
+ <IMG SRC="/images/delete-class.gif" ALT="Выдаліць клÑÑу" BORDER="0"></A>
+ </TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-class">
+<IMG SRC="/images/add-class.gif" ALT="Дадаць клÑÑу" BORDER="0"></A>
diff --git a/templates/be/config-printer.tmpl b/templates/be/config-printer.tmpl
new file mode 100644
index 000000000..1c012f8df
--- /dev/null
+++ b/templates/be/config-printer.tmpl
@@ -0,0 +1,6 @@
+<P>ÐбÑрыце Ð´Ð°Ð¿Ð¾Ð¼Ð½Ñ‹Ñ Ð²Ñ‹Ð±Ð°Ñ€Ñ‹ Ð´Ð»Ñ {printer_name}.
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
diff --git a/templates/be/config-printer2.tmpl b/templates/be/config-printer2.tmpl
new file mode 100644
index 000000000..bfb42d69f
--- /dev/null
+++ b/templates/be/config-printer2.tmpl
@@ -0,0 +1,2 @@
+</TABLE>
+</FORM>
diff --git a/templates/be/error.tmpl b/templates/be/error.tmpl
new file mode 100644
index 000000000..a9b482e3e
--- /dev/null
+++ b/templates/be/error.tmpl
@@ -0,0 +1,3 @@
+<P>Памылка:
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
diff --git a/templates/be/header.tmpl b/templates/be/header.tmpl
new file mode 100644
index 000000000..bc1bd7523
--- /dev/null
+++ b/templates/be/header.tmpl
@@ -0,0 +1,24 @@
+<HTML>
+<HEAD>
+ <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <TITLE>{title} на вузьле {server_name} - {cups_version}</TITLE>
+ <!-- Prevent caching of CGI content -->
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,0,50,30" HREF="http://www.easysw.com" ALT="СвойÑÐºÐ°Ñ Ñтаронка Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,0,208,30" HREF="/admin" ALT="Выканаць адмініÑÑ‚Ñ€Ð°Ñ‚Ñ‹ÑžÐ½ÑƒÑ Ð¿Ñ€Ð°Ñ†Ñ‹">
+ <AREA SHAPE="RECT" COORDS="225,0,267,30" HREF="/classes" ALT="Кіраваць Ñтанам клÑÑаў друкарак">
+ <AREA SHAPE="RECT" COORDS="284,0,342,30" HREF="/documentation.html" ALT="Ð–Ñ‹Ð²Ð°Ñ Ð´Ð°Ð²ÐµÐ´ÐºÐ°">
+ <AREA SHAPE="RECT" COORDS="359,0,420,30" HREF="/jobs" ALT="Кіраваць заданьнÑмі">
+ <AREA SHAPE="RECT" COORDS="437,0,500,30" HREF="/printers" ALT="Кіраваць друкаркамі">
+ <AREA SHAPE="RECT" COORDS="518,0,585,30" HREF="http://www.cups.org" ALT="Выгрузіць бÑгучую вÑÑ€ÑÑ‹ÑŽ праграмнага забеÑьпÑчÑÐ½ÑŒÐ½Ñ CUPS">
+ </MAP>
+</HEAD>
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="601" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System (ÐÐ³ÑƒÐ»ÑŒÐ½Ð°Ñ ÑÑ‹ÑÑ‚Ñма друку Ð´Ð»Ñ UNIX)">
+</CENTER>
+
+<H1>{title}</H1>
diff --git a/templates/be/job-cancel.tmpl b/templates/be/job-cancel.tmpl
new file mode 100644
index 000000000..79f489b0a
--- /dev/null
+++ b/templates/be/job-cancel.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Заданьне {job_id}</A> ÑкаÑавана.
diff --git a/templates/be/job-hold.tmpl b/templates/be/job-hold.tmpl
new file mode 100644
index 000000000..9df297987
--- /dev/null
+++ b/templates/be/job-hold.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Заданьне {job_id}</A> замарожана.
diff --git a/templates/be/job-op.tmpl b/templates/be/job-op.tmpl
new file mode 100644
index 000000000..68298817b
--- /dev/null
+++ b/templates/be/job-op.tmpl
@@ -0,0 +1 @@
+<P>ДзеÑньне Ð·Ð°Ð´Ð°Ð½ÑŒÐ½Ñ Ð½Ðµ падтрымліваецца "{op}".
diff --git a/templates/be/job-release.tmpl b/templates/be/job-release.tmpl
new file mode 100644
index 000000000..6ad569e41
--- /dev/null
+++ b/templates/be/job-release.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Заданьне {job_id}</A> размарожана.
diff --git a/templates/be/job-restart.tmpl b/templates/be/job-restart.tmpl
new file mode 100644
index 000000000..d8c16a9b4
--- /dev/null
+++ b/templates/be/job-restart.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Заданьне {job_id}</A> перазапушчана.
diff --git a/templates/be/jobs.tmpl b/templates/be/jobs.tmpl
new file mode 100644
index 000000000..9a2a18e68
--- /dev/null
+++ b/templates/be/jobs.tmpl
@@ -0,0 +1,54 @@
+<P>{#job_id=0?ÐÑма {?which_jobs=completed?выкананых:бÑгучых} заданьнÑÑž:
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH>Ід&nbsp;</TH>
+ <TH>Ðазва&nbsp;</TH>
+ <TH>КарыÑтальнік&nbsp;</TH>
+ <TH>Памер&nbsp;</TH>
+ <TH>Стан&nbsp;</TH>
+ <TH>Кіраваньне&nbsp;</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+{[job_id]
+<TR VALIGN="TOP">
+ <TD HEIGHT="28"></TD>
+ <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+ <TD>{?job_name=?ÐевÑдома:{job_name}}&nbsp;</TD>
+ <TD>{job_originating_user_name}&nbsp;</TD>
+ <TD>{job_k_octets}k&nbsp;</TD>
+ <TD>{job_state=3?замоўлена ў<BR>{time_at_creation}:{job_state=4?замарожана ў<BR>{time_at_creation}:
+ {job_state=5?выконваецца з<BR>{time_at_processing}:{job_state=6?Ñпынена Ñž<BR>{time_at_completed}:
+ {job_state=7?ÑкаÑавана Ñž<BR>{time_at_completed}:{job_state=8?перарвана:выканана Ñž <BR>{time_at_completed}}}}}}}&nbsp;</TD>
+ <TD>
+ {job_state>5?
+ {job_k_octets>0?
+ <A HREF="/jobs/?op=restart-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/restart-job.gif" ALT="ПеразапуÑьціць заданьне" BORDER="0"></A>
+ :}:}
+ {job_state>6?:
+ {job_state=4?
+ <A HREF="/jobs/?op=release-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/release-job.gif" ALT="Release Job" BORDER="0"></A>
+ :
+ <A HREF="/jobs/?op=hold-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/hold-job.gif" ALT="Замарозіць заданьне" BORDER="0"></A>
+ }
+ <A HREF="/jobs/?op=cancel-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/cancel-job.gif" ALT="СкаÑаваць заданьне" BORDER="0"></A>
+ }
+ &nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P>{?which_jobs=?
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}?which_jobs=completed">
+<IMG SRC="/images/show-completed.gif" BORDER="0" ALT="Паказаць Ð²Ñ‹ÐºÐ°Ð½Ð°Ð½Ñ‹Ñ Ð·Ð°Ð½Ð´Ð°Ð½ÑŒÐ½Ñ–"></A>
+:
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}">
+<IMG SRC="/images/show-active.gif" BORDER="0" ALT="Паказаць бÑÐ³ÑƒÑ‡Ñ‹Ñ Ð·Ð°Ð´Ð°Ð½ÑŒÐ½Ñ–"></A>
+}
diff --git a/templates/be/modify-class.tmpl b/templates/be/modify-class.tmpl
new file mode 100644
index 000000000..5cf99bce5
--- /dev/null
+++ b/templates/be/modify-class.tmpl
@@ -0,0 +1,34 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">ЗьмÑненьне клÑÑÑ‹ {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ðазва:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Знаходжаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ÐпіÑаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/modify-printer.tmpl b/templates/be/modify-printer.tmpl
new file mode 100644
index 000000000..d1285fa43
--- /dev/null
+++ b/templates/be/modify-printer.tmpl
@@ -0,0 +1,36 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?device_uri=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_DEVICE_URI" VALUE="{device_uri}">}
+{?printer_make_and_model=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{printer_make_and_model}">}
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">ЗьмÑненьне друкаркі {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ðазва:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Знаходжаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">ÐпіÑаньне:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/be/option-boolean.tmpl b/templates/be/option-boolean.tmpl
new file mode 100644
index 000000000..c820578dc
--- /dev/null
+++ b/templates/be/option-boolean.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(канфліктуе)</B></FONT>:}</TD>
+ <TD>
+ {[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+ </TD>
+</TR>
diff --git a/templates/be/option-conflict.tmpl b/templates/be/option-conflict.tmpl
new file mode 100644
index 000000000..fefc244c5
--- /dev/null
+++ b/templates/be/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Памылка:</B> наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð²Ñ‹Ð±Ð°Ñ€Ñ‹ канфліктуюць між Ñабою:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Калі лаÑка, зьмÑніце адзін ці больш выбараў, каб вырашыць канфлікт.
diff --git a/templates/be/option-header.tmpl b/templates/be/option-header.tmpl
new file mode 100644
index 000000000..23a904178
--- /dev/null
+++ b/templates/be/option-header.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/be/option-pickmany.tmpl b/templates/be/option-pickmany.tmpl
new file mode 100644
index 000000000..91f4d4497
--- /dev/null
+++ b/templates/be/option-pickmany.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(канфліктуе)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/be/option-pickone.tmpl b/templates/be/option-pickone.tmpl
new file mode 100644
index 000000000..5ed597a39
--- /dev/null
+++ b/templates/be/option-pickone.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(канфліктуе)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/be/option-trailer.tmpl b/templates/be/option-trailer.tmpl
new file mode 100644
index 000000000..dc74280b9
--- /dev/null
+++ b/templates/be/option-trailer.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="ПрацÑг..." BORDER="0"></TD>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/be/printer-accept.tmpl b/templates/be/printer-accept.tmpl
new file mode 100644
index 000000000..13a30a4da
--- /dev/null
+++ b/templates/be/printer-accept.tmpl
@@ -0,0 +1 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> прыймае заданьні.
diff --git a/templates/be/printer-added.tmpl b/templates/be/printer-added.tmpl
new file mode 100644
index 000000000..0157b4dac
--- /dev/null
+++ b/templates/be/printer-added.tmpl
@@ -0,0 +1 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была паÑьпÑхова дадана.
diff --git a/templates/be/printer-configured.tmpl b/templates/be/printer-configured.tmpl
new file mode 100644
index 000000000..b3c4aa048
--- /dev/null
+++ b/templates/be/printer-configured.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была
+паÑьпÑхова наладжана.
diff --git a/templates/be/printer-confirm.tmpl b/templates/be/printer-confirm.tmpl
new file mode 100644
index 000000000..0eb132739
--- /dev/null
+++ b/templates/be/printer-confirm.tmpl
@@ -0,0 +1,5 @@
+<P><B>Увага!</B> Вы жадаеце выдаліць друкарку {printer_name}! Выдаліць?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-printer&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Выдаліць" BORDER="0"></A>
diff --git a/templates/be/printer-deleted.tmpl b/templates/be/printer-deleted.tmpl
new file mode 100644
index 000000000..893d55d71
--- /dev/null
+++ b/templates/be/printer-deleted.tmpl
@@ -0,0 +1 @@
+<P>Друкарка {printer_name} паÑьпÑхова выдалена.
diff --git a/templates/be/printer-modified.tmpl b/templates/be/printer-modified.tmpl
new file mode 100644
index 000000000..9b0f3a4de
--- /dev/null
+++ b/templates/be/printer-modified.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была паÑьпÑхова
+зьменена.
diff --git a/templates/be/printer-purge.tmpl b/templates/be/printer-purge.tmpl
new file mode 100644
index 000000000..be2f7b5d2
--- /dev/null
+++ b/templates/be/printer-purge.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была вызвалена
+ад уÑÑ–Ñ… заданьнÑÑž.
diff --git a/templates/be/printer-reject.tmpl b/templates/be/printer-reject.tmpl
new file mode 100644
index 000000000..c3c3f2f68
--- /dev/null
+++ b/templates/be/printer-reject.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> больш не прыймае
+заданьні.
diff --git a/templates/be/printer-start.tmpl b/templates/be/printer-start.tmpl
new file mode 100644
index 000000000..5a7139003
--- /dev/null
+++ b/templates/be/printer-start.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была паÑьпÑхова
+запушчана.
diff --git a/templates/be/printer-stop.tmpl b/templates/be/printer-stop.tmpl
new file mode 100644
index 000000000..cdc61518f
--- /dev/null
+++ b/templates/be/printer-stop.tmpl
@@ -0,0 +1,2 @@
+<P>Друкарка <A HREF="/printers/{printer_name}">{printer_name}</A> была паÑьпÑхова
+Ñпынена.
diff --git a/templates/be/printers.tmpl b/templates/be/printers.tmpl
new file mode 100644
index 000000000..069004819
--- /dev/null
+++ b/templates/be/printers.tmpl
@@ -0,0 +1,61 @@
+{#printer_name=0?Друкаркі адÑутнічаюць:
+<P><B>Ð”Ð°Ð¿Ð¾Ð¼Ð½Ð°Ñ Ð´Ñ€ÑƒÐºÐ°Ñ€ÐºÐ°:</B> {default_name?<A HREF="{default_uri}">{default_name}</A>:нÑма}
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">{printer_make_and_model}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN="TOP"><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/printer-{printer_state=3?idle:{printer_state=4?processing:stopped}}.gif" BORDER="0" ALT=""></A>
+ </TD>
+ <TD VALIGN="TOP">ÐпіÑаньне: {printer_info}<BR>
+ Знаходжаньне: {printer_location}<BR>
+ Стан друкаркі: {printer_state=3?бÑзьдзейнічае:{printer_state=4?друкуе:ÑпыненаÑ}},
+ {printer_is_accepting_jobs=0?не прыймае заданьні:прыймае заданьні}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
+ {?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
+ {?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
+ {?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
+ {?device_uri=?:<BR>URI прылады: {device_uri}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Ðадрукаваць Ñ‚ÑÑтавую Ñтаронку" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-printer.gif" ALT="ЗапуÑьціць друкарку" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-printer.gif" ALT="Спыніць друкарку" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Дазволіць заданьні" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Забараніць заданьні" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-printer&printer_name={printer_name}">
+ <IMG SRC="/images/modify-printer.gif" ALT="ЗьмÑніць друкарку" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=config-printer&printer_name={printer_name}">
+ <IMG SRC="/images/config-printer.gif" ALT="Ðаладзіць друкарку" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-printer&printer_name={printer_name}">
+ <IMG SRC="/images/delete-printer.gif" ALT="Выдаліць друкарку" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-printer">
+<IMG SRC="/images/add-printer.gif" ALT="Дадаць друкарку" BORDER="0"></A>
diff --git a/templates/be/test-page.tmpl b/templates/be/test-page.tmpl
new file mode 100644
index 000000000..2ec03fa7d
--- /dev/null
+++ b/templates/be/test-page.tmpl
@@ -0,0 +1,2 @@
+<P>ТÑÑÑ‚Ð°Ð²Ð°Ñ Ñтарона даÑлана; ідÑнтыфікатар заданьнÑ: <A HREF="/printers/{printer_name}">
+{printer_name}-{job_id}</A>.
diff --git a/templates/be/trailer.tmpl b/templates/be/trailer.tmpl
new file mode 100644
index 000000000..e91795581
--- /dev/null
+++ b/templates/be/trailer.tmpl
@@ -0,0 +1,7 @@
+<HR>
+<P>ÐўтарÑÐºÑ–Ñ Ð¿Ñ€Ð°Ð²Ñ‹ Ñž 1993-2004 гадох належаць Easy Software Products. УÑе правы абаронены.
+Common UNIX Printing System, CUPS Ñ– лÑгатып CUPS зьÑўлÑюцца гандлёвымі
+маркамі <A HREF="http://www.easysw.com">Easy Software Products</A>.
+УÑе Ñ–Ð½ÑˆÑ‹Ñ Ð³Ð°Ð½Ð´Ð»Ñ‘Ð²Ñ‹Ñ Ð¼Ð°Ñ€ÐºÑ– належаць Ñ–Ñ… уладальнікам.
+</BODY>
+</HTML>
diff --git a/templates/choose-device.tmpl b/templates/choose-device.tmpl
new file mode 100644
index 000000000..f64810910
--- /dev/null
+++ b/templates/choose-device.tmpl
@@ -0,0 +1,32 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Device for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Device:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="DEVICE_URI">
+ {[device_uri]<OPTION VALUE="{device_uri}" {?current_device_uri={device_uri}?SELECTED:}>
+ {device_info} {?device_make_and_model!Unknown?({device_make_and_model}):}
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/choose-make.tmpl b/templates/choose-make.tmpl
new file mode 100644
index 000000000..8392047c9
--- /dev/null
+++ b/templates/choose-make.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Model/Driver for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Make:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_MAKE" SIZE="10">
+ {[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/choose-members.tmpl b/templates/choose-members.tmpl
new file mode 100644
index 000000000..b83f13e74
--- /dev/null
+++ b/templates/choose-members.tmpl
@@ -0,0 +1,30 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Members for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Members:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+ {[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/choose-model.tmpl b/templates/choose-model.tmpl
new file mode 100644
index 000000000..60efb5634
--- /dev/null
+++ b/templates/choose-model.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Model/Driver for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Model:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_NAME" SIZE="10">
+ {[ppd_name]<OPTION VALUE="{ppd_name}" {?current_make_and_model={ppd_make_and_model}?SELECTED:}>{ppd_make_and_model} ({ppd_natural_language})
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/choose-serial.tmpl b/templates/choose-serial.tmpl
new file mode 100644
index 000000000..a0ea5db2d
--- /dev/null
+++ b/templates/choose-serial.tmpl
@@ -0,0 +1,56 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Serial Port Settings for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Baud Rate:&nbsp;</TD>
+ <TD><SELECT NAME="BAUDRATE">
+ {[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Parity:&nbsp;</TD>
+ <TD><SELECT NAME="PARITY">
+ <OPTION VALUE="none" {?parity=none?SELECTED:}>None
+ <OPTION VALUE="even" {?parity=even?SELECTED:}>Even
+ <OPTION VALUE="odd" {?parity=odd?SELECTED:}>Odd
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Data Bits:&nbsp;</TD>
+ <TD><SELECT NAME="BITS">
+ <OPTION {?bits=8?SELECTED:}>8
+ <OPTION {?bits=7?SELECTED:}>7
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Flow Control:&nbsp;</TD>
+ <TD><SELECT NAME="FLOW">
+ <OPTION VALUE="none" {?flow=none?SELECTED:}>None
+ <OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (Software)
+ <OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (Hardware)
+ <OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (Hardware)
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/choose-uri.tmpl b/templates/choose-uri.tmpl
new file mode 100644
index 000000000..602d66f4e
--- /dev/null
+++ b/templates/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Device URI for {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Device URI:&nbsp;</TD>
+ <TD><INPUT TYPE="TEXT" SIZE="40" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{device_uri}"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD>Examples:
+ <PRE>
+ file:/path/to/filename.prn
+ http://hostname:631/ipp/
+ http://hostname:631/ipp/port1
+ ipp://hostname/ipp/
+ ipp://hostname/ipp/port1
+ lpd://hostname/queue
+ socket://hostname
+ socket://hostname:9100
+ </PRE>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/class-added.tmpl b/templates/class-added.tmpl
new file mode 100644
index 000000000..f740581ad
--- /dev/null
+++ b/templates/class-added.tmpl
@@ -0,0 +1,2 @@
+<P>Class <A HREF="/classes/{printer_name}">{printer_name}</A> has been added
+successfully.
diff --git a/templates/class-confirm.tmpl b/templates/class-confirm.tmpl
new file mode 100644
index 000000000..0fbbd6d53
--- /dev/null
+++ b/templates/class-confirm.tmpl
@@ -0,0 +1,6 @@
+<P><B>Warning:</B> About to delete class {printer_name}! Do you wish to
+continue?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-class&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Continue" BORDER="0"></A>
diff --git a/templates/class-deleted.tmpl b/templates/class-deleted.tmpl
new file mode 100644
index 000000000..269ddd87a
--- /dev/null
+++ b/templates/class-deleted.tmpl
@@ -0,0 +1 @@
+<P>Class {printer_name} has been deleted successfully.
diff --git a/templates/class-modified.tmpl b/templates/class-modified.tmpl
new file mode 100644
index 000000000..861790732
--- /dev/null
+++ b/templates/class-modified.tmpl
@@ -0,0 +1,2 @@
+<P>Class <A HREF="/classes/{printer_name}">{printer_name}</A> has been
+modified successfully.
diff --git a/templates/classes.tmpl b/templates/classes.tmpl
new file mode 100644
index 000000000..04086e1b2
--- /dev/null
+++ b/templates/classes.tmpl
@@ -0,0 +1,53 @@
+{#printer_name=0?No classes:
+<P><B>Default Destination:</B> <A HREF="{default_uri}">{default_name}</A>
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">Printer Class</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN=TOP><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/classes.gif" BORDER="0" ALT=""></A></TD>
+ <TD VALIGN=TOP>Description: {printer_info}<BR>
+ Location: {printer_location}<BR>
+ Class State: {printer_state=3?idle:{printer_state=4?processing:stopped}},
+ {printer_is_accepting_jobs=0?rejecting jobs:accepting jobs}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?member_names=?:<BR>Members: {member_names}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Print Test Page" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-class.gif" ALT="Start Class" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-class.gif" ALT="Stop Class" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Accept Jobs" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Reject Jobs" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-class&printer_name={printer_name}">
+ <IMG SRC="/images/modify-class.gif" ALT="Modify Class" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-class&printer_name={printer_name}">
+ <IMG SRC="/images/delete-class.gif" ALT="Delete Class" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=set-as-default&printer_name={printer_name}">
+ <IMG SRC="/images/set-as-default.gif" ALT="Set As Default" BORDER="0"></A>
+ </TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-class">
+<IMG SRC="/images/add-class.gif" ALT="Add Class" BORDER="0"></A>
diff --git a/templates/config-printer.tmpl b/templates/config-printer.tmpl
new file mode 100644
index 000000000..f24b08f12
--- /dev/null
+++ b/templates/config-printer.tmpl
@@ -0,0 +1,6 @@
+<P>Choose default options for {printer_name}.
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
diff --git a/templates/config-printer2.tmpl b/templates/config-printer2.tmpl
new file mode 100644
index 000000000..bfb42d69f
--- /dev/null
+++ b/templates/config-printer2.tmpl
@@ -0,0 +1,2 @@
+</TABLE>
+</FORM>
diff --git a/templates/de/Makefile b/templates/de/Makefile
new file mode 100644
index 000000000..ff6e66b6a
--- /dev/null
+++ b/templates/de/Makefile
@@ -0,0 +1,106 @@
+#
+# "$Id$"
+#
+# Template makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Template files...
+#
+
+FILES = add-class.tmpl \
+ add-printer.tmpl \
+ admin-op.tmpl \
+ admin.tmpl \
+ choose-device.tmpl \
+ choose-make.tmpl \
+ choose-members.tmpl \
+ choose-model.tmpl \
+ choose-serial.tmpl \
+ choose-uri.tmpl \
+ class-added.tmpl \
+ class-confirm.tmpl \
+ class-deleted.tmpl \
+ class-modified.tmpl \
+ classes.tmpl \
+ config-printer.tmpl \
+ config-printer2.tmpl \
+ error.tmpl \
+ header.tmpl \
+ jobs.tmpl \
+ job-cancel.tmpl \
+ job-hold.tmpl \
+ job-op.tmpl \
+ job-release.tmpl \
+ job-restart.tmpl \
+ modify-class.tmpl \
+ modify-printer.tmpl \
+ option-boolean.tmpl \
+ option-conflict.tmpl \
+ option-header.tmpl \
+ option-pickmany.tmpl \
+ option-pickone.tmpl \
+ option-trailer.tmpl \
+ printers.tmpl \
+ printer-accept.tmpl \
+ printer-added.tmpl \
+ printer-configured.tmpl \
+ printer-confirm.tmpl \
+ printer-deleted.tmpl \
+ printer-modified.tmpl \
+ printer-purge.tmpl \
+ printer-reject.tmpl \
+ printer-start.tmpl \
+ printer-stop.tmpl \
+ test-page.tmpl \
+ trailer.tmpl
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/templates/de
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/templates/de; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/templates/de/add-class.tmpl b/templates/de/add-class.tmpl
new file mode 100644
index 000000000..d8f349cd5
--- /dev/null
+++ b/templates/de/add-class.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Neue Klasse zuf&uuml;gen</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Standort: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Beschreibung: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/add-printer.tmpl b/templates/de/add-printer.tmpl
new file mode 100644
index 000000000..e3ed4b769
--- /dev/null
+++ b/templates/de/add-printer.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Neuen Drucker zuf&uuml;gen</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Standort: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Beschreibung: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/admin-op.tmpl b/templates/de/admin-op.tmpl
new file mode 100644
index 000000000..ff3efe28a
--- /dev/null
+++ b/templates/de/admin-op.tmpl
@@ -0,0 +1 @@
+<P>Nicht unterst&uuml;tze Operation "{op}".
diff --git a/templates/de/admin.tmpl b/templates/de/admin.tmpl
new file mode 100644
index 000000000..561336c43
--- /dev/null
+++ b/templates/de/admin.tmpl
@@ -0,0 +1,56 @@
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Klassen</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-class">
+ <IMG SRC="/images/add-class.gif" ALT="Neue Klasse hinzuf&uuml;gen" BORDER="0"></A>
+ <A HREF="/classes/">
+ <IMG SRC="/images/manage-classes.gif" ALT="Verf&uuml;gbare Klassen verwalten" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Druckauftr&auml;ge</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/jobs/">
+ <IMG SRC="/images/manage-jobs.gif" ALT="Auftr&auml;ge verwalten" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Drucker</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-printer">
+ <IMG SRC="/images/add-printer.gif" ALT="Neuen Drucker Hinzuf&uuml;gen" BORDER="0"></A>
+ <A HREF="/printers/"><IMG SRC="/images/manage-printers.gif" ALT="Verf&uuml;gbare Klassen verwalten" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+</TABLE>
diff --git a/templates/de/choose-device.tmpl b/templates/de/choose-device.tmpl
new file mode 100644
index 000000000..1b13ccf4c
--- /dev/null
+++ b/templates/de/choose-device.tmpl
@@ -0,0 +1,32 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Ger&auml;t f&uuml; {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Gere&auml;t:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="DEVICE_URI">
+ {[device_uri]<OPTION VALUE="{device_uri}" {?current_device_uri={device_uri}?SELECTED:}>
+ {device_info} {?device_make_and_model!Unknown?({device_make_and_model}):}
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/choose-make.tmpl b/templates/de/choose-make.tmpl
new file mode 100644
index 000000000..a29223bd3
--- /dev/null
+++ b/templates/de/choose-make.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Hersteller/Modell f&uuml;r {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Hersteller:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_MAKE" SIZE="10">
+ {[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/choose-members.tmpl b/templates/de/choose-members.tmpl
new file mode 100644
index 000000000..c843c9473
--- /dev/null
+++ b/templates/de/choose-members.tmpl
@@ -0,0 +1,30 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Mitglieder f&uuml;r {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Mitglieder:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+ {[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/choose-model.tmpl b/templates/de/choose-model.tmpl
new file mode 100644
index 000000000..22c54609d
--- /dev/null
+++ b/templates/de/choose-model.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Hersteller/Modell f&uuml;r {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Modell:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_NAME" SIZE="10">
+ {[ppd_name]<OPTION VALUE="{ppd_name}" {?current_make_and_model={ppd_make_and_model}?SELECTED:}>{ppd_make_and_model} ({ppd_natural_language})
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/choose-serial.tmpl b/templates/de/choose-serial.tmpl
new file mode 100644
index 000000000..d94dcf0e3
--- /dev/null
+++ b/templates/de/choose-serial.tmpl
@@ -0,0 +1,56 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Einstellungen der seriellen Schnittstelle f&uuml;r {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">&Uuml;bertragungsgeschwindigkeit:&nbsp;</TD>
+ <TD><SELECT NAME="BAUDRATE">
+ {[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Parit&auml;t:&nbsp;</TD>
+ <TD><SELECT NAME="PARITY">
+ <OPTION VALUE="none" {?parity=none?SELECTED:}>None
+ <OPTION VALUE="even" {?parity=even?SELECTED:}>Even
+ <OPTION VALUE="odd" {?parity=odd?SELECTED:}>Odd
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Datenbits:&nbsp;</TD>
+ <TD><SELECT NAME="BITS">
+ <OPTION {?bits=8?SELECTED:}>8
+ <OPTION {?bits=7?SELECTED:}>7
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Flussksteuerung:&nbsp;</TD>
+ <TD><SELECT NAME="FLOW">
+ <OPTION VALUE="none" {?flow=none?SELECTED:}>None
+ <OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (Software)
+ <OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (Hardware)
+ <OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (Hardware)
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/choose-uri.tmpl b/templates/de/choose-uri.tmpl
new file mode 100644
index 000000000..ac0a5da2b
--- /dev/null
+++ b/templates/de/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Ger&auml;te URI f&uuml;r {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ger&auml;te URI:&nbsp;</TD>
+ <TD><INPUT TYPE="TEXT" SIZE="40" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{device_uri}"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD>Examples:
+ <PRE>
+ file:/path/to/filename.prn
+ http://hostname:631/ipp/
+ http://hostname:631/ipp/port1
+ ipp://hostname/ipp/
+ ipp://hostname/ipp/port1
+ lpd://hostname/queue
+ socket://hostname
+ socket://hostname:9100
+ </PRE>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/class-added.tmpl b/templates/de/class-added.tmpl
new file mode 100644
index 000000000..54df5ab9d
--- /dev/null
+++ b/templates/de/class-added.tmpl
@@ -0,0 +1 @@
+<P>Klasse <A HREF="/classes/{printer_name}">{printer_name}</A> wurde zugef&uuml;gt.
diff --git a/templates/de/class-confirm.tmpl b/templates/de/class-confirm.tmpl
new file mode 100644
index 000000000..c73113a6b
--- /dev/null
+++ b/templates/de/class-confirm.tmpl
@@ -0,0 +1,5 @@
+<P><B>Warnung:</B> Si el&ouml;schen gerade die Klasee {printer_name}! Sind sie sicher?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-class&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></A>
diff --git a/templates/de/class-deleted.tmpl b/templates/de/class-deleted.tmpl
new file mode 100644
index 000000000..c75fab4e5
--- /dev/null
+++ b/templates/de/class-deleted.tmpl
@@ -0,0 +1 @@
+<P>Klasse {printer_name} wurde erfolgreich gel&ouml;scht.
diff --git a/templates/de/class-modified.tmpl b/templates/de/class-modified.tmpl
new file mode 100644
index 000000000..97f1a2ebb
--- /dev/null
+++ b/templates/de/class-modified.tmpl
@@ -0,0 +1 @@
+<P>Klasse <A HREF="/classes/{printer_name}">{printer_name}</A> wurde erfolgreich modifiziert.
diff --git a/templates/de/classes.tmpl b/templates/de/classes.tmpl
new file mode 100644
index 000000000..4e6de731c
--- /dev/null
+++ b/templates/de/classes.tmpl
@@ -0,0 +1,51 @@
+{#printer_name=0?No classes:
+<P><B>Systemvoreinstellung f&uuml;r Druckziel:</B> <A HREF="{default_uri}">{default_name}</A>
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">Druckerklasse</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN=TOP><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/classes.gif" BORDER="0" ALT=""></A></TD>
+ <TD VALIGN=TOP>Beschreibung: {printer_info}<BR>
+ Standort: {printer_location}<BR>
+ Klassenstatus: {printer_state=3?gelangweilt:{printer_state=4?processing:stopped}},
+ {printer_is_accepting_jobs=0?rejecting jobs:nimmt Druckauftr&auml;ge entgegen}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?member_names=?:<BR>Members: {member_names}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Drucker Testseite" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-class.gif" ALT="Klasse starten" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-class.gif" ALT="Klasse anhalten" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Auftr&auml;ge annehmen" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Auftr&auml;ge ablehnen" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-class&printer_name={printer_name}">
+ <IMG SRC="/images/modify-class.gif" ALT="Klassen modifizieren" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-class&printer_name={printer_name}">
+ <IMG SRC="/images/delete-class.gif" ALT="Klasse l&ouml;schen" BORDER="0"></A>
+ </TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-class">
+<IMG SRC="/images/add-class.gif" ALT="Klasse hinzuf&uuml;gen" BORDER="0"></A>
diff --git a/templates/de/config-printer.tmpl b/templates/de/config-printer.tmpl
new file mode 100644
index 000000000..6baee536f
--- /dev/null
+++ b/templates/de/config-printer.tmpl
@@ -0,0 +1,6 @@
+<P>Wählen Sie die Vorgabeoptionen f&uuml;r {printer_name}.
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
diff --git a/templates/de/config-printer2.tmpl b/templates/de/config-printer2.tmpl
new file mode 100644
index 000000000..bfb42d69f
--- /dev/null
+++ b/templates/de/config-printer2.tmpl
@@ -0,0 +1,2 @@
+</TABLE>
+</FORM>
diff --git a/templates/de/error.tmpl b/templates/de/error.tmpl
new file mode 100644
index 000000000..c34292fc7
--- /dev/null
+++ b/templates/de/error.tmpl
@@ -0,0 +1,3 @@
+<P>Fehler:
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
diff --git a/templates/de/header.tmpl b/templates/de/header.tmpl
new file mode 100644
index 000000000..b4d397695
--- /dev/null
+++ b/templates/de/header.tmpl
@@ -0,0 +1,24 @@
+<HTML>
+<HEAD>
+ <TITLE>{title} auf {server_name} - {cups_version}</TITLE>
+ <!-- Prevent caching of CGI content -->
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,10,50,20" HREF="http://www.easysw.com" ALT="Easy Software Produkt-Homepage">
+ <AREA SHAPE="RECT" COORDS="82,10,226,20" HREF="/admin" ALT="Einrichtungsaufgaben">
+ <AREA SHAPE="RECT" COORDS="235,10,403,20" HREF="/classes" ALT="Druckerklassen verwalten">
+ <AREA SHAPE="RECT" COORDS="412,10,488,20" HREF="/documentation.html" ALT="Online Hilfe">
+ <AREA SHAPE="RECT" COORDS="497,10,590,20" HREF="/jobs" ALT="Druckauftr&auml;ge">
+ <AREA SHAPE="RECT" COORDS="599,10,717,20" HREF="/printers" ALT="Drucker verwalten">
+ <AREA SHAPE="RECT" COORDS="726,10,887,20" HREF="http://www.cups.org" ALT="Aktuelle CUPS Software">
+ </MAP>
+</HEAD>
+
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="902" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1>{title}</H1>
diff --git a/templates/de/job-cancel.tmpl b/templates/de/job-cancel.tmpl
new file mode 100644
index 000000000..06b305c6f
--- /dev/null
+++ b/templates/de/job-cancel.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde abgebrochen.
diff --git a/templates/de/job-hold.tmpl b/templates/de/job-hold.tmpl
new file mode 100644
index 000000000..fed851943
--- /dev/null
+++ b/templates/de/job-hold.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde unterbrochen.
diff --git a/templates/de/job-op.tmpl b/templates/de/job-op.tmpl
new file mode 100644
index 000000000..d59f08b60
--- /dev/null
+++ b/templates/de/job-op.tmpl
@@ -0,0 +1 @@
+<P>Nicht unterst&uuml;tzte Auftragsoperation "{op}".
diff --git a/templates/de/job-release.tmpl b/templates/de/job-release.tmpl
new file mode 100644
index 000000000..ef11eeb0f
--- /dev/null
+++ b/templates/de/job-release.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde zum Druck freigegeben.
diff --git a/templates/de/job-restart.tmpl b/templates/de/job-restart.tmpl
new file mode 100644
index 000000000..940611763
--- /dev/null
+++ b/templates/de/job-restart.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Auftrag {job_id}</A> wurde neu gestartet.
diff --git a/templates/de/jobs.tmpl b/templates/de/jobs.tmpl
new file mode 100644
index 000000000..f658bf580
--- /dev/null
+++ b/templates/de/jobs.tmpl
@@ -0,0 +1,58 @@
+<P>{#job_id=0?No {?which_jobs=completed?Completed:Active} Druckauftr&auml;ge:
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH>ID&nbsp;</TH>
+ <TH>Name&nbsp;</TH>
+ <TH>Benutzer&nbsp;</TH>
+ <TH>Gr&ouml;sse&nbsp;</TH>
+ <TH>Status&nbsp;</TH>
+ <TH>Steuerung&nbsp;</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+{[job_id]
+<TR VALIGN="TOP">
+ <TD HEIGHT="28"></TD>
+ <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+ <TD>{?job_name=?Unknown:{job_name}}&nbsp;</TD>
+ <TD>{job_originating_user_name}&nbsp;</TD>
+ <TD>{job_k_octets}k&nbsp;</TD>
+ <TD>{job_state=3?in Auftrag seit<BR>
+ {time_at_creation}:{job_state=4?angehalten seit<BR>
+ {time_at_creation}:{job_state=5?in Verarbeitung seit<BR>
+ {time_at_processing}:{job_state=6?angehalten am<BR>
+ {time_at_completed}:{job_state=7?gel&ouml;scht am<BR>
+ {time_at_completed}:{job_state=8?abgebrochen:fertig am<BR>
+ {time_at_completed}}}}}}}&nbsp;</TD>
+ <TD>
+ {job_state>5?
+ {job_k_octets>0?
+ <A HREF="/jobs/?op=restart-job&job_id={job_id}">
+ <IMG SRC="/images/restart-job.gif" ALT="Auftrag wieder starten" BORDER="0"></A>
+ :}:}
+ {job_state>6?:
+ {job_state=4?
+ <A HREF="/jobs/?op=release-job&job_id={job_id}">
+ <IMG SRC="/images/release-job.gif" ALT="Auftrag freigeben" BORDER="0"></A>
+ :
+ <A HREF="/jobs/?op=hold-job&job_id={job_id}">
+ <IMG SRC="/images/hold-job.gif" ALT="Auftrag anhalten" BORDER="0"></A>
+ }
+ <A HREF="/jobs/?op=cancel-job&job_id={job_id}">
+ <IMG SRC="/images/cancel-job.gif" ALT="Auftrag l&ouml;schen" BORDER="0"></A>
+ }
+ &nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P>{?which_jobs=?
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}?which_jobs=completed">
+<IMG SRC="/images/show-completed.gif" BORDER="0" ALT="Fertige Auftr&auml;ge anzeigen"></A>
+:
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}">
+<IMG SRC="/images/show-active.gif" BORDER="0" ALT="Aktive Auftr&auml;ge anzeigen"></A>
+}
diff --git a/templates/de/modify-class.tmpl b/templates/de/modify-class.tmpl
new file mode 100644
index 000000000..a53011857
--- /dev/null
+++ b/templates/de/modify-class.tmpl
@@ -0,0 +1,34 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Druckerklasse {printer_name} modifizieren</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name: </TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Standort: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Beschreibung: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/modify-printer.tmpl b/templates/de/modify-printer.tmpl
new file mode 100644
index 000000000..33c77c956
--- /dev/null
+++ b/templates/de/modify-printer.tmpl
@@ -0,0 +1,36 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?device_uri=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_DEVICE_URI" VALUE="{device_uri}">}
+{?printer_make_and_model=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{printer_make_and_model}">}
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Drucker {printer_name} modifizieren</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name: </TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Standort: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Beschreibung: </TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/de/option-boolean.tmpl b/templates/de/option-boolean.tmpl
new file mode 100644
index 000000000..a8360fc82
--- /dev/null
+++ b/templates/de/option-boolean.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{keytext}:</TD>
+ <TD>
+ {[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+ </TD>
+</TR>
diff --git a/templates/de/option-conflict.tmpl b/templates/de/option-conflict.tmpl
new file mode 100644
index 000000000..ac932967a
--- /dev/null
+++ b/templates/de/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Störung:</B> Die folgenden Wahlen widersprechen:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Ändern Sie bitte eine oder mehr der Wahlen, um die Konflikte zu beheben.
diff --git a/templates/de/option-header.tmpl b/templates/de/option-header.tmpl
new file mode 100644
index 000000000..23a904178
--- /dev/null
+++ b/templates/de/option-header.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/de/option-pickmany.tmpl b/templates/de/option-pickmany.tmpl
new file mode 100644
index 000000000..8340889b4
--- /dev/null
+++ b/templates/de/option-pickmany.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT" VALIGN="TOP">{keytext}:</TD>
+ <TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/de/option-pickone.tmpl b/templates/de/option-pickone.tmpl
new file mode 100644
index 000000000..6880b968b
--- /dev/null
+++ b/templates/de/option-pickone.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{keytext}:</TD>
+ <TD><SELECT NAME="{keyword}">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/de/option-trailer.tmpl b/templates/de/option-trailer.tmpl
new file mode 100644
index 000000000..0feadf593
--- /dev/null
+++ b/templates/de/option-trailer.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></TD>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/de/printer-accept.tmpl b/templates/de/printer-accept.tmpl
new file mode 100644
index 000000000..63f4ab259
--- /dev/null
+++ b/templates/de/printer-accept.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> nimmt nun Druckaufträge entgegen.
diff --git a/templates/de/printer-added.tmpl b/templates/de/printer-added.tmpl
new file mode 100644
index 000000000..83d21ecb0
--- /dev/null
+++ b/templates/de/printer-added.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde erfolgreich zugefügt.
diff --git a/templates/de/printer-configured.tmpl b/templates/de/printer-configured.tmpl
new file mode 100644
index 000000000..6ba6afa1a
--- /dev/null
+++ b/templates/de/printer-configured.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde erfolgreich konfiguriert.
diff --git a/templates/de/printer-confirm.tmpl b/templates/de/printer-confirm.tmpl
new file mode 100644
index 000000000..e95816b84
--- /dev/null
+++ b/templates/de/printer-confirm.tmpl
@@ -0,0 +1,5 @@
+<P><B>Warnung:</B> Sie l&ouml;schen gerade einen Drucker {printer_name}! Sind Sie sicher?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-printer&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Weiter" BORDER="0"></A>
diff --git a/templates/de/printer-deleted.tmpl b/templates/de/printer-deleted.tmpl
new file mode 100644
index 000000000..00c941bb7
--- /dev/null
+++ b/templates/de/printer-deleted.tmpl
@@ -0,0 +1 @@
+<P>Drucker {printer_name} wurde erfolgreich entfernt.
diff --git a/templates/de/printer-modified.tmpl b/templates/de/printer-modified.tmpl
new file mode 100644
index 000000000..1f340352a
--- /dev/null
+++ b/templates/de/printer-modified.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde modifiziert.
diff --git a/templates/de/printer-purge.tmpl b/templates/de/printer-purge.tmpl
new file mode 100644
index 000000000..863d33916
--- /dev/null
+++ b/templates/de/printer-purge.tmpl
@@ -0,0 +1 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been purged of all jobs.
diff --git a/templates/de/printer-reject.tmpl b/templates/de/printer-reject.tmpl
new file mode 100644
index 000000000..6feda6428
--- /dev/null
+++ b/templates/de/printer-reject.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> nimmt nun keine Druckauftr&auml;ge mehr entgegen.
diff --git a/templates/de/printer-start.tmpl b/templates/de/printer-start.tmpl
new file mode 100644
index 000000000..bfef05afe
--- /dev/null
+++ b/templates/de/printer-start.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> wurde gestartet.
diff --git a/templates/de/printer-stop.tmpl b/templates/de/printer-stop.tmpl
new file mode 100644
index 000000000..3b253a9cc
--- /dev/null
+++ b/templates/de/printer-stop.tmpl
@@ -0,0 +1 @@
+<P>Drucker <A HREF="/printers/{printer_name}">{printer_name}</A> ist angehalten.
diff --git a/templates/de/printers.tmpl b/templates/de/printers.tmpl
new file mode 100644
index 000000000..aaa11e49d
--- /dev/null
+++ b/templates/de/printers.tmpl
@@ -0,0 +1,61 @@
+{#printer_name=0?No printers:
+<P><B>Systemvoreingestelltes Druckziel: </B> {default_name?<A HREF="{default_uri}">{default_name}</A>:none}
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">{printer_make_and_model}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN="TOP"><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/printer-{printer_state=3?idle:{printer_state=4?processing:stopped}}.gif" BORDER="0" ALT=""></A>
+ </TD>
+ <TD VALIGN="TOP">Beschreibung: {printer_info}<BR>
+ Standort: {printer_location}<BR>
+ Ger&auml;testatus: {printer_state=3?gelangweilt:{printer_state=4?arbeitend:angehalten}},
+ {printer_is_accepting_jobs=0?weist Auftr&auml;ge ab:Nimmt Auftr&auml;ge entgegen}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
+ {?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
+ {?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
+ {?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
+ {?device_uri=?:<BR>Ger&auml;te URI: {device_uri}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Drucker Testseite" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-printer.gif" ALT="Drucker starten" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-printer.gif" ALT="Drucker anhalten" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Auftr&auml;ge annehmen" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Auftr&auml;ge ablehnen" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-printer&printer_name={printer_name}">
+ <IMG SRC="/images/modify-printer.gif" ALT="Drucker modifizieren" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=config-printer&printer_name={printer_name}">
+ <IMG SRC="/images/config-printer.gif" ALT="Drucker konfigurieren" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-printer&printer_name={printer_name}">
+ <IMG SRC="/images/delete-printer.gif" ALT="Drucker l&ouml;schen" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-printer">
+<IMG SRC="/images/add-printer.gif" ALT="Drucker hinzuf&uuml;gen" BORDER="0"></A>
diff --git a/templates/de/test-page.tmpl b/templates/de/test-page.tmpl
new file mode 100644
index 000000000..559b2ea45
--- /dev/null
+++ b/templates/de/test-page.tmpl
@@ -0,0 +1,2 @@
+<P>eine Testseite wurde gesendet; Auftrags ID ist <A HREF="/printers/{printer_name}">
+{printer_name}-{job_id}</A>.
diff --git a/templates/de/trailer.tmpl b/templates/de/trailer.tmpl
new file mode 100644
index 000000000..2d2a1ef19
--- /dev/null
+++ b/templates/de/trailer.tmpl
@@ -0,0 +1,7 @@
+<HR>
+<P>Copyright 1993-2004 Easy Software Products, Alle Rechte vorbehalten.
+Das "Common UNIX Printing System", CUPS, und das CUPS logo
+sind eingetragene Warenzeichen von <A HREF="http://www.easysw.com">Easy Software Products</A>.
+Alle anderen Markenzeichen sind Eigentum der jeweiligen Eigent&uuml;mer.
+</BODY>
+</HTML>
diff --git a/templates/error.tmpl b/templates/error.tmpl
new file mode 100644
index 000000000..eb15a06ff
--- /dev/null
+++ b/templates/error.tmpl
@@ -0,0 +1,3 @@
+<P>Error:
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
diff --git a/templates/es/Makefile b/templates/es/Makefile
new file mode 100644
index 000000000..b8e6483cd
--- /dev/null
+++ b/templates/es/Makefile
@@ -0,0 +1,106 @@
+#
+# "$Id$"
+#
+# Template makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Template files...
+#
+
+FILES = add-class.tmpl \
+ add-printer.tmpl \
+ admin-op.tmpl \
+ admin.tmpl \
+ choose-device.tmpl \
+ choose-make.tmpl \
+ choose-members.tmpl \
+ choose-model.tmpl \
+ choose-serial.tmpl \
+ choose-uri.tmpl \
+ class-added.tmpl \
+ class-confirm.tmpl \
+ class-deleted.tmpl \
+ class-modified.tmpl \
+ classes.tmpl \
+ config-printer.tmpl \
+ config-printer2.tmpl \
+ error.tmpl \
+ header.tmpl \
+ jobs.tmpl \
+ job-cancel.tmpl \
+ job-hold.tmpl \
+ job-op.tmpl \
+ job-release.tmpl \
+ job-restart.tmpl \
+ modify-class.tmpl \
+ modify-printer.tmpl \
+ option-boolean.tmpl \
+ option-conflict.tmpl \
+ option-header.tmpl \
+ option-pickmany.tmpl \
+ option-pickone.tmpl \
+ option-trailer.tmpl \
+ printers.tmpl \
+ printer-accept.tmpl \
+ printer-added.tmpl \
+ printer-configured.tmpl \
+ printer-confirm.tmpl \
+ printer-deleted.tmpl \
+ printer-modified.tmpl \
+ printer-purge.tmpl \
+ printer-reject.tmpl \
+ printer-start.tmpl \
+ printer-stop.tmpl \
+ test-page.tmpl \
+ trailer.tmpl
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/templates/es
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/templates/es; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/templates/es/add-class.tmpl b/templates/es/add-class.tmpl
new file mode 100644
index 000000000..55df07abe
--- /dev/null
+++ b/templates/es/add-class.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">A&ntilde;adir nueva clase</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nombre:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ubicaci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Descripci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/add-printer.tmpl b/templates/es/add-printer.tmpl
new file mode 100644
index 000000000..616d00639
--- /dev/null
+++ b/templates/es/add-printer.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">A&ntilde;adir nueva impresora</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nombre:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ubicaci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Descripci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/admin-op.tmpl b/templates/es/admin-op.tmpl
new file mode 100644
index 000000000..c5a00c237
--- /dev/null
+++ b/templates/es/admin-op.tmpl
@@ -0,0 +1 @@
+<P>Procedimiento de administraci&oacute;n no soportado "{op}".
diff --git a/templates/es/admin.tmpl b/templates/es/admin.tmpl
new file mode 100644
index 000000000..636f47e3c
--- /dev/null
+++ b/templates/es/admin.tmpl
@@ -0,0 +1,57 @@
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Clases</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-class">
+ <IMG SRC="/images/add-class.gif" ALT="A&ntilde;adir clase nueva" BORDER="0"></A>
+ <A HREF="/classes/">
+ <IMG SRC="/images/manage-classes.gif" ALT="Administrar clases disponibles" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Trabajos</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/jobs/">
+ <IMG SRC="/images/manage-jobs.gif" ALT="Administrar trabajos" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Impresoras</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-printer">
+ <IMG SRC="/images/add-printer.gif" ALT="A&ntilde;adir impresora nueva" BORDER="0"></A>
+ <A HREF="/printers/">
+ <IMG SRC="/images/manage-printers.gif" ALT="Administrar impresoras disponibles" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+</TABLE>
diff --git a/templates/es/choose-device.tmpl b/templates/es/choose-device.tmpl
new file mode 100644
index 000000000..4557d7f4d
--- /dev/null
+++ b/templates/es/choose-device.tmpl
@@ -0,0 +1,32 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Tipo de conexi&oacute;n de {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Conexi&oacute;n:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="DEVICE_URI">
+ {[device_uri]<OPTION VALUE="{device_uri}" {?current_device_uri={device_uri}?SELECTED:}>
+ {device_info} {?device_make_and_model!Unknown?({device_make_and_model}):}
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/choose-make.tmpl b/templates/es/choose-make.tmpl
new file mode 100644
index 000000000..15444fc0f
--- /dev/null
+++ b/templates/es/choose-make.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modelo/Controlador de {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Fabricante:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_MAKE" SIZE="10">
+ {[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/choose-members.tmpl b/templates/es/choose-members.tmpl
new file mode 100644
index 000000000..a75525d9b
--- /dev/null
+++ b/templates/es/choose-members.tmpl
@@ -0,0 +1,30 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Miembros de {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Miembros:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+ {[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/choose-model.tmpl b/templates/es/choose-model.tmpl
new file mode 100644
index 000000000..403a52b94
--- /dev/null
+++ b/templates/es/choose-model.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modelo/Controlador para {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Modelo:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_NAME" SIZE="10">
+ {[ppd_name]<OPTION VALUE="{ppd_name}" {?current_make_and_model={ppd_make_and_model}?SELECTED:}>{ppd_make_and_model} ({ppd_natural_language})
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/choose-serial.tmpl b/templates/es/choose-serial.tmpl
new file mode 100644
index 000000000..7514fa236
--- /dev/null
+++ b/templates/es/choose-serial.tmpl
@@ -0,0 +1,56 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Ajustes del puerto serie para {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Baudios:&nbsp;</TD>
+ <TD><SELECT NAME="BAUDRATE">
+ {[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Paridad:&nbsp;</TD>
+ <TD><SELECT NAME="PARITY">
+ <OPTION VALUE="none" {?parity=none?SELECTED:}>Ninguna
+ <OPTION VALUE="even" {?parity=even?SELECTED:}>Par
+ <OPTION VALUE="odd" {?parity=odd?SELECTED:}>Impar
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Bits de datos:&nbsp;</TD>
+ <TD><SELECT NAME="BITS">
+ <OPTION {?bits=8?SELECTED:}>8
+ <OPTION {?bits=7?SELECTED:}>7
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Control de flujo:&nbsp;</TD>
+ <TD><SELECT NAME="FLOW">
+ <OPTION VALUE="none" {?flow=none?SELECTED:}>Ninguno
+ <OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (Software)
+ <OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (Hardware)
+ <OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (Hardware)
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/choose-uri.tmpl b/templates/es/choose-uri.tmpl
new file mode 100644
index 000000000..93f44f8e7
--- /dev/null
+++ b/templates/es/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">URI de la conexi&oacute;n para {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">URI de la conexi&oacute;n:&nbsp;</TD>
+ <TD><INPUT TYPE="TEXT" SIZE="40" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{device_uri}"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD>Ejemplos:
+ <PRE>
+ file:/ruta/del/archivo.prn
+ http://nombre_ordenador:631/ipp/
+ http://nombre_ordenador:631/ipp/puerto1
+ ipp://nombre_ordenador/ipp/
+ ipp://nombre_ordenador/ipp/puerto1
+ lpd://nombre_ordenador/cola
+ socket://nombre_ordenador
+ socket://nombre_ordenador:9100
+ </PRE>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/class-added.tmpl b/templates/es/class-added.tmpl
new file mode 100644
index 000000000..faf659ae1
--- /dev/null
+++ b/templates/es/class-added.tmpl
@@ -0,0 +1 @@
+<P>Se ha a&ntilde;adido con &eacute;xito la clase <A HREF="/classes/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/class-confirm.tmpl b/templates/es/class-confirm.tmpl
new file mode 100644
index 000000000..57b6f7d29
--- /dev/null
+++ b/templates/es/class-confirm.tmpl
@@ -0,0 +1,5 @@
+<P><B>Advertencia:</B> Se va a proceder al borrado de la clase {printer_name} &iquest;Desea seguir?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-class&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></A>
diff --git a/templates/es/class-deleted.tmpl b/templates/es/class-deleted.tmpl
new file mode 100644
index 000000000..c73465f50
--- /dev/null
+++ b/templates/es/class-deleted.tmpl
@@ -0,0 +1 @@
+<P>Se ha borrado con &eacute;xito la clase {printer_name}.
diff --git a/templates/es/class-modified.tmpl b/templates/es/class-modified.tmpl
new file mode 100644
index 000000000..4a2870f13
--- /dev/null
+++ b/templates/es/class-modified.tmpl
@@ -0,0 +1 @@
+<P>Se ha modificado con &eacute;xito la clase <A HREF="/classes/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/classes.tmpl b/templates/es/classes.tmpl
new file mode 100644
index 000000000..a04612fa0
--- /dev/null
+++ b/templates/es/classes.tmpl
@@ -0,0 +1,53 @@
+{#printer_name=0?No hay clases:
+<P><B>Predeterminada:</B> <A HREF="{default_uri}">{default_name}</A>
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">Clase de Impresora</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN=TOP><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/classes.gif" BORDER="0" ALT=""></A></TD>
+ <TD VALIGN=TOP>Descripci&oacute;n: {printer_info}<BR>
+ Ubicaci&oacute;n: {printer_location}<BR>
+ Estado de la clase: {printer_state=3?inactiva:{printer_state=4?procesando:parada}},
+ {printer_is_accepting_jobs=0?rechazando trabajos:aceptando trabajos}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?member_names=?:<BR>Miembros: {member_names}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Imprimir p&aacute;gina de prueba" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-class.gif" ALT="Iniciar clase" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-class.gif" ALT="Detener clase" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Aceptar trabajos" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Rechazar trabajos" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-class&printer_name={printer_name}">
+ <IMG SRC="/images/modify-class.gif" ALT="Modificar clase" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-class&printer_name={printer_name}">
+ <IMG SRC="/images/delete-class.gif" ALT="Borrar clase" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=set-as-default&printer_name={printer_name}">
+ <IMG SRC="/images/set-as-default.gif" ALT="Poner como predeterminada" BORDER="0"></A>
+ </TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-class">
+<IMG SRC="/images/add-class.gif" ALT="A&ntilde;adir clase" BORDER="0"></A>
diff --git a/templates/es/config-printer.tmpl b/templates/es/config-printer.tmpl
new file mode 100644
index 000000000..627380202
--- /dev/null
+++ b/templates/es/config-printer.tmpl
@@ -0,0 +1,6 @@
+<P>Escoja las opciones por defecto de {printer_name}.
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
diff --git a/templates/es/config-printer2.tmpl b/templates/es/config-printer2.tmpl
new file mode 100644
index 000000000..bfb42d69f
--- /dev/null
+++ b/templates/es/config-printer2.tmpl
@@ -0,0 +1,2 @@
+</TABLE>
+</FORM>
diff --git a/templates/es/error.tmpl b/templates/es/error.tmpl
new file mode 100644
index 000000000..eb15a06ff
--- /dev/null
+++ b/templates/es/error.tmpl
@@ -0,0 +1,3 @@
+<P>Error:
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
diff --git a/templates/es/header.tmpl b/templates/es/header.tmpl
new file mode 100644
index 000000000..8ae9a065c
--- /dev/null
+++ b/templates/es/header.tmpl
@@ -0,0 +1,23 @@
+<HTML>
+<HEAD>
+ <TITLE>{title} on {server_name} - {cups_version}</TITLE>
+ <!-- Prevent caching of CGI content -->
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,8,50,22" HREF="http://www.easysw.com" ALT="P&aacute;gina inicial de Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="82,8,198,22" HREF="/admin" ALT="Tareas de administraci&oacute;n">
+ <AREA SHAPE="RECT" COORDS="216,8,270,22" HREF="/classes" ALT="Administra las clases de impresoras">
+ <AREA SHAPE="RECT" COORDS="292,8,344,22" HREF="/documentation.html" ALT="Ayuda en l&iacute;nea">
+ <AREA SHAPE="RECT" COORDS="366,8,435,22" HREF="/jobs" ALT="Administra trabajos">
+ <AREA SHAPE="RECT" COORDS="456,8,544,22" HREF="/printers" ALT="Administra impresoras">
+ <AREA SHAPE="RECT" COORDS="566,8,638,22" HREF="http://www.cups.org" ALT="Descargar la versi&oacute;n actual de CUPS">
+ </MAP>
+</HEAD>
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="653" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="CUPS (Sistema de impresi&oacute;n com&uacute;n de UNIX)">
+</CENTER>
+
+<H1>{title}</H1>
diff --git a/templates/es/job-cancel.tmpl b/templates/es/job-cancel.tmpl
new file mode 100644
index 000000000..84d65e58f
--- /dev/null
+++ b/templates/es/job-cancel.tmpl
@@ -0,0 +1 @@
+<P>Se ha cancelado el <A HREF="{job_printer_uri}">Trabajo {job_id}</A>.
diff --git a/templates/es/job-hold.tmpl b/templates/es/job-hold.tmpl
new file mode 100644
index 000000000..f424bca89
--- /dev/null
+++ b/templates/es/job-hold.tmpl
@@ -0,0 +1 @@
+<P>Se ha retenido el <A HREF="{job_printer_uri}">Trabajo {job_id}</A>.
diff --git a/templates/es/job-op.tmpl b/templates/es/job-op.tmpl
new file mode 100644
index 000000000..8fd6af9a1
--- /dev/null
+++ b/templates/es/job-op.tmpl
@@ -0,0 +1 @@
+<P>Procedimiento no soportado "{op}".
diff --git a/templates/es/job-release.tmpl b/templates/es/job-release.tmpl
new file mode 100644
index 000000000..14e2d0277
--- /dev/null
+++ b/templates/es/job-release.tmpl
@@ -0,0 +1 @@
+<P>Se ha liberado el <A HREF="{job_printer_uri}">Trabajo {job_id}</A>.
diff --git a/templates/es/job-restart.tmpl b/templates/es/job-restart.tmpl
new file mode 100644
index 000000000..d35dfb4a3
--- /dev/null
+++ b/templates/es/job-restart.tmpl
@@ -0,0 +1 @@
+<P>Se ha reiniciado el <A HREF="{job_printer_uri}">Trabajo {job_id}</A>.
diff --git a/templates/es/jobs.tmpl b/templates/es/jobs.tmpl
new file mode 100644
index 000000000..8927a9d1e
--- /dev/null
+++ b/templates/es/jobs.tmpl
@@ -0,0 +1,54 @@
+<P>{#job_id=0?No hay trabajos {?which_jobs=completed?completados:activos}:
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH>ID&nbsp;</TH>
+ <TH>Nombre&nbsp;</TH>
+ <TH>Usuario&nbsp;</TH>
+ <TH>Tama&ntilde;o&nbsp;</TH>
+ <TH>Estado&nbsp;</TH>
+ <TH>Control&nbsp;</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+{[job_id]
+<TR VALIGN="TOP">
+ <TD HEIGHT="28"></TD>
+ <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+ <TD>{?job_name=?Desconocido:{job_name}}&nbsp;</TD>
+ <TD>{job_originating_user_name}&nbsp;</TD>
+ <TD>{job_k_octets}k&nbsp;</TD>
+ <TD>{job_state=3?pendiente desde<BR>{time_at_creation}:{job_state=4?retenido desde<BR>{time_at_creation}:
+ {job_state=5?en proceso desde<BR>{time_at_processing}:{job_state=6?parado el<BR>{time_at_completed}:
+ {job_state=7?cancelado el<BR>{time_at_completed}:{job_state=8?abandonado:completado el<BR>{time_at_completed}}}}}}}&nbsp;</TD>
+ <TD>
+ {job_state>5?
+ {job_k_octets>0?
+ <A HREF="/jobs/?op=restart-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/restart-job.gif" ALT="Reiniciar trabajo" BORDER="0"></A>
+ :}:}
+ {job_state>6?:
+ {job_state=4?
+ <A HREF="/jobs/?op=release-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/release-job.gif" ALT="Liberar trabajo" BORDER="0"></A>
+ :
+ <A HREF="/jobs/?op=hold-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/hold-job.gif" ALT="Retener trabajo" BORDER="0"></A>
+ }
+ <A HREF="/jobs/?op=cancel-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/cancel-job.gif" ALT="Cancelar trabajo" BORDER="0"></A>
+ }
+ &nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P>{?which_jobs=?
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}?which_jobs=completed">
+<IMG SRC="/images/show-completed.gif" BORDER="0" ALT="Mostrar todos los trabajos"></A>
+:
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}">
+<IMG SRC="/images/show-active.gif" BORDER="0" ALT="Mostrar trabajos activos"></A>
+}
diff --git a/templates/es/modify-class.tmpl b/templates/es/modify-class.tmpl
new file mode 100644
index 000000000..d09c4c2bc
--- /dev/null
+++ b/templates/es/modify-class.tmpl
@@ -0,0 +1,34 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modificar clase {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nombre:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ubicaci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Descripci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/modify-printer.tmpl b/templates/es/modify-printer.tmpl
new file mode 100644
index 000000000..cf935a58b
--- /dev/null
+++ b/templates/es/modify-printer.tmpl
@@ -0,0 +1,36 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?device_uri=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_DEVICE_URI" VALUE="{device_uri}">}
+{?printer_make_and_model=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{printer_make_and_model}">}
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modificar impresora {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nombre:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Ubicaci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Descripci&oacute;n:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/es/option-boolean.tmpl b/templates/es/option-boolean.tmpl
new file mode 100644
index 000000000..9aca916e1
--- /dev/null
+++ b/templates/es/option-boolean.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD>
+ {[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+ </TD>
+</TR>
diff --git a/templates/es/option-conflict.tmpl b/templates/es/option-conflict.tmpl
new file mode 100644
index 000000000..ed98e5630
--- /dev/null
+++ b/templates/es/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Error:</B> Las siguientes opciones est&aacute;n en conflicto:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Cambie una o m&aacute;s de las opciones para resolver el problema.
diff --git a/templates/es/option-header.tmpl b/templates/es/option-header.tmpl
new file mode 100644
index 000000000..23a904178
--- /dev/null
+++ b/templates/es/option-header.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/es/option-pickmany.tmpl b/templates/es/option-pickmany.tmpl
new file mode 100644
index 000000000..531b9bd6a
--- /dev/null
+++ b/templates/es/option-pickmany.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/es/option-pickone.tmpl b/templates/es/option-pickone.tmpl
new file mode 100644
index 000000000..7e99eb4c8
--- /dev/null
+++ b/templates/es/option-pickone.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/es/option-trailer.tmpl b/templates/es/option-trailer.tmpl
new file mode 100644
index 000000000..099652984
--- /dev/null
+++ b/templates/es/option-trailer.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Siguiente" BORDER="0"></TD>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/es/printer-accept.tmpl b/templates/es/printer-accept.tmpl
new file mode 100644
index 000000000..f44606889
--- /dev/null
+++ b/templates/es/printer-accept.tmpl
@@ -0,0 +1 @@
+<P>La impresora <A HREF="/printers/{printer_name}">{printer_name}</A> ahora acepta trabajos.
diff --git a/templates/es/printer-added.tmpl b/templates/es/printer-added.tmpl
new file mode 100644
index 000000000..f0825b1c2
--- /dev/null
+++ b/templates/es/printer-added.tmpl
@@ -0,0 +1 @@
+<P>Se ha a&ntilde;adido con &eacute;xito la impresora <A HREF="/printers/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/printer-configured.tmpl b/templates/es/printer-configured.tmpl
new file mode 100644
index 000000000..db65caef3
--- /dev/null
+++ b/templates/es/printer-configured.tmpl
@@ -0,0 +1 @@
+<P>Se ha configurado con &eacute;xito la impresora <A HREF="/printers/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/printer-confirm.tmpl b/templates/es/printer-confirm.tmpl
new file mode 100644
index 000000000..ca8a0ed5a
--- /dev/null
+++ b/templates/es/printer-confirm.tmpl
@@ -0,0 +1,6 @@
+<P><B>Advertencia:</B> Se va a proceder al borrado de la impresora {printer_name} &iquest;Desea seguir?
+
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-printer&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Continue" BORDER="0"></A>
diff --git a/templates/es/printer-default.tmpl b/templates/es/printer-default.tmpl
new file mode 100644
index 000000000..71df4088d
--- /dev/null
+++ b/templates/es/printer-default.tmpl
@@ -0,0 +1,4 @@
+<P>Se ha puesto como predeterminada en el servidor la impresora
+<A HREF="/printers/{printer_name}">{printer_name}</A>. Observe que cualquier
+opci&oacute;n de usuario que haya sido activada por mediaci&oacute;n del comando
+<TT>lpoptions</TT> tiene mayor preferencia que este ajuste por defecto. \ No newline at end of file
diff --git a/templates/es/printer-deleted.tmpl b/templates/es/printer-deleted.tmpl
new file mode 100644
index 000000000..ca8ed01f1
--- /dev/null
+++ b/templates/es/printer-deleted.tmpl
@@ -0,0 +1 @@
+<P>Se ha borrado con &eacute;xito la impresora {printer_name}.
diff --git a/templates/es/printer-modified.tmpl b/templates/es/printer-modified.tmpl
new file mode 100644
index 000000000..515d9ee8a
--- /dev/null
+++ b/templates/es/printer-modified.tmpl
@@ -0,0 +1 @@
+<P>Se ha modificado con &eacute;xito la impresora <A HREF="/printers/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/printer-purge.tmpl b/templates/es/printer-purge.tmpl
new file mode 100644
index 000000000..442970055
--- /dev/null
+++ b/templates/es/printer-purge.tmpl
@@ -0,0 +1 @@
+<P>Se han purgado todos los trabajos de la impresora <A HREF="/printers/{printer_name}">{printer_name}</A>.
diff --git a/templates/es/printer-reject.tmpl b/templates/es/printer-reject.tmpl
new file mode 100644
index 000000000..453a77bba
--- /dev/null
+++ b/templates/es/printer-reject.tmpl
@@ -0,0 +1 @@
+<P>La impresora <A HREF="/printers/{printer_name}">{printer_name}</A> ya no acepta trabajos.
diff --git a/templates/es/printer-start.tmpl b/templates/es/printer-start.tmpl
new file mode 100644
index 000000000..5ec3a7c93
--- /dev/null
+++ b/templates/es/printer-start.tmpl
@@ -0,0 +1 @@
+<P>La impresora <A HREF="/printers/{printer_name}">{printer_name}</A> ha sido iniciada.
diff --git a/templates/es/printer-stop.tmpl b/templates/es/printer-stop.tmpl
new file mode 100644
index 000000000..3788ba3ce
--- /dev/null
+++ b/templates/es/printer-stop.tmpl
@@ -0,0 +1 @@
+<P>La impresora <A HREF="/printers/{printer_name}">{printer_name}</A> ha sido parada.
diff --git a/templates/es/printers.tmpl b/templates/es/printers.tmpl
new file mode 100644
index 000000000..a6aa15d5f
--- /dev/null
+++ b/templates/es/printers.tmpl
@@ -0,0 +1,63 @@
+{#printer_name=0?No hay impresoras:
+<P><B>Predeterminada:</B> {default_name?<A HREF="{default_uri}">{default_name}</A>:ninguna}
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">{printer_make_and_model}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN="TOP"><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/printer-{printer_state=3?idle:{printer_state=4?processing:stopped}}.gif" BORDER="0" ALT=""></A>
+ </TD>
+ <TD VALIGN="TOP">Descripci&oacute;n: {printer_info}<BR>
+ Ubicaci&oacute;n: {printer_location}<BR>
+ Estado de la impresora: {printer_state=3?inactiva:{printer_state=4?procesando:parada}},
+ {printer_is_accepting_jobs=0?rechazando trabajos:aceptando trabajo}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
+ {?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
+ {?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
+ {?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
+ {?device_uri=?:<BR>URI de la conexi&oacute;n: {device_uri}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Imprimir p&aacute;gina de prueba" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-printer.gif" ALT="Iniciar impresora" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-printer.gif" ALT="Detener impresora" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Aceptar trabajos" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Rechazar trabajos" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-printer&printer_name={printer_name}">
+ <IMG SRC="/images/modify-printer.gif" ALT="Modificar impresora" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=config-printer&printer_name={printer_name}">
+ <IMG SRC="/images/config-printer.gif" ALT="Configurar impresora" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-printer&printer_name={printer_name}">
+ <IMG SRC="/images/delete-printer.gif" ALT="Borrar impresora" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=set-as-default&printer_name={printer_name}">
+ <IMG SRC="/images/set-as-default.gif" ALT="Poner como predeterminada" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-printer">
+<IMG SRC="/images/add-printer.gif" ALT="A&ntilde;adir impresora" BORDER="0"></A>
diff --git a/templates/es/test-page.tmpl b/templates/es/test-page.tmpl
new file mode 100644
index 000000000..0ef541d82
--- /dev/null
+++ b/templates/es/test-page.tmpl
@@ -0,0 +1,2 @@
+<P>Se ha enviado la p&aacute;gina de test; la ID del trabajo es <A HREF="/printers/{printer_name}">
+{printer_name}-{job_id}</A>.
diff --git a/templates/es/trailer.tmpl b/templates/es/trailer.tmpl
new file mode 100644
index 000000000..a4bac04fb
--- /dev/null
+++ b/templates/es/trailer.tmpl
@@ -0,0 +1,7 @@
+<HR>
+<P>El copyright de CUPS 1993-2004 es de Easy Software Products. Todos los derechos reservados.
+Common UNIX Printing System, CUPS, y el logo de CUPS son
+marcas registradas de <A HREF="http://www.easysw.com">Easy Software Products</A>.
+ El resto de marcas pertenecen a sus respectivos propietarios.
+</BODY>
+</HTML>
diff --git a/templates/fr/Makefile b/templates/fr/Makefile
new file mode 100644
index 000000000..5446fc30b
--- /dev/null
+++ b/templates/fr/Makefile
@@ -0,0 +1,106 @@
+#
+# "$Id$"
+#
+# Template makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1993-2004 by Easy Software Products.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../../Makedefs
+
+#
+# Template files...
+#
+
+FILES = add-class.tmpl \
+ add-printer.tmpl \
+ admin-op.tmpl \
+ admin.tmpl \
+ choose-device.tmpl \
+ choose-make.tmpl \
+ choose-members.tmpl \
+ choose-model.tmpl \
+ choose-serial.tmpl \
+ choose-uri.tmpl \
+ class-added.tmpl \
+ class-confirm.tmpl \
+ class-deleted.tmpl \
+ class-modified.tmpl \
+ classes.tmpl \
+ config-printer.tmpl \
+ config-printer2.tmpl \
+ error.tmpl \
+ header.tmpl \
+ jobs.tmpl \
+ job-cancel.tmpl \
+ job-hold.tmpl \
+ job-op.tmpl \
+ job-release.tmpl \
+ job-restart.tmpl \
+ modify-class.tmpl \
+ modify-printer.tmpl \
+ option-boolean.tmpl \
+ option-conflict.tmpl \
+ option-header.tmpl \
+ option-pickmany.tmpl \
+ option-pickone.tmpl \
+ option-trailer.tmpl \
+ printers.tmpl \
+ printer-accept.tmpl \
+ printer-added.tmpl \
+ printer-configured.tmpl \
+ printer-confirm.tmpl \
+ printer-deleted.tmpl \
+ printer-modified.tmpl \
+ printer-purge.tmpl \
+ printer-reject.tmpl \
+ printer-start.tmpl \
+ printer-stop.tmpl \
+ test-page.tmpl \
+ trailer.tmpl
+
+
+#
+# Make everything...
+#
+
+all:
+
+
+#
+# Clean all config and object files...
+#
+
+clean:
+
+
+#
+# Install files...
+#
+
+install:
+ $(INSTALL_DIR) $(DATADIR)/templates/fr
+ for file in $(FILES); do \
+ $(INSTALL_DATA) $$file $(DATADIR)/templates/fr; \
+ done
+
+
+#
+# End of "$Id$".
+#
diff --git a/templates/fr/add-class.tmpl b/templates/fr/add-class.tmpl
new file mode 100644
index 000000000..dd300e46b
--- /dev/null
+++ b/templates/fr/add-class.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Ajouter une nouvelle classe d'imprimantes</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nom:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Emplacement:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/add-printer.tmpl b/templates/fr/add-printer.tmpl
new file mode 100644
index 000000000..44d273f9f
--- /dev/null
+++ b/templates/fr/add-printer.tmpl
@@ -0,0 +1,33 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Ajouter une nouvelle imprimante</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nom:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_NAME" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Emplacement:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/admin-op.tmpl b/templates/fr/admin-op.tmpl
new file mode 100644
index 000000000..ba0653a58
--- /dev/null
+++ b/templates/fr/admin-op.tmpl
@@ -0,0 +1 @@
+<P>Opération d'administration "{op}" non prise en charge.
diff --git a/templates/fr/admin.tmpl b/templates/fr/admin.tmpl
new file mode 100644
index 000000000..3a8e73fa9
--- /dev/null
+++ b/templates/fr/admin.tmpl
@@ -0,0 +1,57 @@
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Classes</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-class">
+ <IMG SRC="/images/add-class.gif" ALT="Ajouter une nouvelle classe" BORDER="0"></A>
+ <A HREF="/classes/">
+ <IMG SRC="/images/manage-classes.gif" ALT="Administer les classes" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Travaux d'impression</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/jobs/">
+ <IMG SRC="/images/manage-jobs.gif" ALT="Administrer les travaux d'impression" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966">Imprimantes</TH>
+ <TH WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD><A HREF="/admin/?op=add-printer">
+ <IMG SRC="/images/add-printer.gif" ALT="Ajouter une nouvelle imprimante" BORDER="0"></A>
+ <A HREF="/printers/">
+ <IMG SRC="/images/manage-printers.gif" ALT="Administrer les imprimantes disponibles" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+</TABLE>
diff --git a/templates/fr/choose-device.tmpl b/templates/fr/choose-device.tmpl
new file mode 100644
index 000000000..170c5f673
--- /dev/null
+++ b/templates/fr/choose-device.tmpl
@@ -0,0 +1,32 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Périphérique d'accès à l'imprimante {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Périphérique:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="DEVICE_URI">
+ {[device_uri]<OPTION VALUE="{device_uri}" {?current_device_uri={device_uri}?SELECTED:}>
+ {device_info} {?device_make_and_model!Unknown?({device_make_and_model}):}
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/choose-make.tmpl b/templates/fr/choose-make.tmpl
new file mode 100644
index 000000000..c34222609
--- /dev/null
+++ b/templates/fr/choose-make.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modèle/Pilote pour {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Type:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_MAKE" SIZE="10">
+ {[ppd_make]<OPTION VALUE="{ppd_make}" {?current_make={ppd_make}?SELECTED:}>{ppd_make}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/choose-members.tmpl b/templates/fr/choose-members.tmpl
new file mode 100644
index 000000000..04e1b33c6
--- /dev/null
+++ b/templates/fr/choose-members.tmpl
@@ -0,0 +1,30 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Membres de la classe {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Membres:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="MEMBER_URIS" SIZE="10" MULTIPLE>
+ {[member_uris]<OPTION VALUE="{member_uris}" {?member_selected}>{member_names}}
+ </SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/choose-model.tmpl b/templates/fr/choose-model.tmpl
new file mode 100644
index 000000000..db0699811
--- /dev/null
+++ b/templates/fr/choose-model.tmpl
@@ -0,0 +1,35 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<INPUT TYPE="HIDDEN" NAME="BAUDRATE" VALUE="{?baudrate}">
+<INPUT TYPE="HIDDEN" NAME="BITS" VALUE="{?bits}">
+<INPUT TYPE="HIDDEN" NAME="PARITY" VALUE="{?parity}">
+<INPUT TYPE="HIDDEN" NAME="FLOW" VALUE="{?flow}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modèle/Pilote pour {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Modèle:&nbsp;</TD>
+ <TD>
+ <SELECT NAME="PPD_NAME" SIZE="10">
+ {[ppd_name]<OPTION VALUE="{ppd_name}" {?current_make_and_model={ppd_make_and_model}?SELECTED:}>{ppd_make_and_model} ({ppd_natural_language})
+ }</SELECT>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/choose-serial.tmpl b/templates/fr/choose-serial.tmpl
new file mode 100644
index 000000000..a20112c62
--- /dev/null
+++ b/templates/fr/choose-serial.tmpl
@@ -0,0 +1,56 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="DEVICE_URI" VALUE="{device_uri}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Paramètres du port série pour {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Taux de transfert (Baud rate):&nbsp;</TD>
+ <TD><SELECT NAME="BAUDRATE">
+ {[baudrates]<OPTION {?baudrate={baudrates}?SELECTED:}>{baudrates}}
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Contrôle de parité:&nbsp;</TD>
+ <TD><SELECT NAME="PARITY">
+ <OPTION VALUE="none" {?parity=none?SELECTED:}>None
+ <OPTION VALUE="even" {?parity=even?SELECTED:}>Even
+ <OPTION VALUE="odd" {?parity=odd?SELECTED:}>Odd
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Bits de données (Data bits):&nbsp;</TD>
+ <TD><SELECT NAME="BITS">
+ <OPTION {?bits=8?SELECTED:}>8
+ <OPTION {?bits=7?SELECTED:}>7
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Control de flux:&nbsp;</TD>
+ <TD><SELECT NAME="FLOW">
+ <OPTION VALUE="none" {?flow=none?SELECTED:}>None
+ <OPTION VALUE="soft" {?flow=soft?SELECTED:}>XON/XOFF (Software)
+ <OPTION VALUE="hard" {?flow=hard?SELECTED:}>RTS/CTS (Hardware)
+ <OPTION VALUE="dtrdsr" {?flow=dtrdsr?SELECTED:}>DTR/DSR (Hardware)
+ </SELECT></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/choose-uri.tmpl b/templates/fr/choose-uri.tmpl
new file mode 100644
index 000000000..c2ba8b0c6
--- /dev/null
+++ b/templates/fr/choose-uri.tmpl
@@ -0,0 +1,43 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_LOCATION" VALUE="{?printer_location}">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_INFO" VALUE="{?printer_info}">
+<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{?current_make_and_model}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">URI de périphérique pour {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">URI de périphérique:&nbsp;</TD>
+ <TD><INPUT TYPE="TEXT" SIZE="40" MAXLENGTH="1024" NAME="DEVICE_URI" VALUE="{device_uri}"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD>Exemples:
+ <PRE>
+ file:/chemin/vers/fichier.prn
+ http://nom_ordinateur:631/ipp/
+ http://nom_ordinateur:631/ipp/port1
+ ipp://nom_ordinateur/ipp/
+ ipp://nom_ordinateur/ipp/port1
+ lpd://nom_ordinateur/queue
+ socket://nom_ordinateur
+ socket://nom_ordinateur:9100
+ </PRE>
+ </TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/class-added.tmpl b/templates/fr/class-added.tmpl
new file mode 100644
index 000000000..085246915
--- /dev/null
+++ b/templates/fr/class-added.tmpl
@@ -0,0 +1,2 @@
+<P>La classe d'imprimante <A HREF="/classes/{printer_name}">{printer_name}</A>
+a été ajouté avec succès.
diff --git a/templates/fr/class-confirm.tmpl b/templates/fr/class-confirm.tmpl
new file mode 100644
index 000000000..acf0a7f86
--- /dev/null
+++ b/templates/fr/class-confirm.tmpl
@@ -0,0 +1,6 @@
+<P><B>Avertissement:</B> Vous êtes sur le point de supprimer la classe
+ {printer_name}! Voulez-vous continuer ?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-class&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></A>
diff --git a/templates/fr/class-deleted.tmpl b/templates/fr/class-deleted.tmpl
new file mode 100644
index 000000000..19f6620e5
--- /dev/null
+++ b/templates/fr/class-deleted.tmpl
@@ -0,0 +1 @@
+<P>La classe d'imprimante {printer_name} a été supprimée avec succès.
diff --git a/templates/fr/class-modified.tmpl b/templates/fr/class-modified.tmpl
new file mode 100644
index 000000000..a6f9bec53
--- /dev/null
+++ b/templates/fr/class-modified.tmpl
@@ -0,0 +1,2 @@
+<P>La classe d'imprimantes <A HREF="/classes/{printer_name}">{printer_name}</A>
+a été modifiée avec succès.
diff --git a/templates/fr/classes.tmpl b/templates/fr/classes.tmpl
new file mode 100644
index 000000000..79d3051db
--- /dev/null
+++ b/templates/fr/classes.tmpl
@@ -0,0 +1,51 @@
+{#printer_name=0?Aucune classe d'imprimantes définie:
+<P><B>Destination implicite ("par défaut"):</B> <A HREF="{default_uri}">{default_name}</A>
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">Classes d'imprimantes</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN=TOP><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/classes.gif" BORDER="0" ALT=""></A></TD>
+ <TD VALIGN=TOP>Description: {printer_info}<BR>
+ Emplacement: {printer_location}<BR>
+ Etat de la classe: {printer_state=3?idle:{printer_state=4?fonctionne:arrêtée}},
+ {printer_is_accepting_jobs=0?rejette travaux:accepte travaux}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?member_names=?:<BR>Membres: {member_names}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Imprimer page de test" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-class.gif" ALT="Démarrer la classe" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-class.gif" ALT="Arrêter la classe" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Accepter les travaux" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Rejeter les travaux" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-class&printer_name={printer_name}">
+ <IMG SRC="/images/modify-class.gif" ALT="Modifier la classe" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-class&printer_name={printer_name}">
+ <IMG SRC="/images/delete-class.gif" ALT="Supprimer la classe" BORDER="0"></A>
+ </TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-class">
+<IMG SRC="/images/add-class.gif" ALT="Ajouter une classe" BORDER="0"></A>
diff --git a/templates/fr/config-printer.tmpl b/templates/fr/config-printer.tmpl
new file mode 100644
index 000000000..74d49b667
--- /dev/null
+++ b/templates/fr/config-printer.tmpl
@@ -0,0 +1,6 @@
+<P>Choisissez les options implicites pour {printer_name}.
+
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
diff --git a/templates/fr/config-printer2.tmpl b/templates/fr/config-printer2.tmpl
new file mode 100644
index 000000000..bfb42d69f
--- /dev/null
+++ b/templates/fr/config-printer2.tmpl
@@ -0,0 +1,2 @@
+</TABLE>
+</FORM>
diff --git a/templates/fr/error.tmpl b/templates/fr/error.tmpl
new file mode 100644
index 000000000..b38d2b4bb
--- /dev/null
+++ b/templates/fr/error.tmpl
@@ -0,0 +1,3 @@
+<P>Erreur:
+
+<BLOCKQUOTE>{error}</BLOCKQUOTE>
diff --git a/templates/fr/header.tmpl b/templates/fr/header.tmpl
new file mode 100644
index 000000000..871804d5d
--- /dev/null
+++ b/templates/fr/header.tmpl
@@ -0,0 +1,23 @@
+<HTML>
+<HEAD>
+ <TITLE>{title} sur {server_name} - {cups_version}</TITLE>
+ <!-- Prevent caching of CGI content -->
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="14,8,50,22" HREF="http://www.easysw.com" ALT="Page d'accueil Easy Software Products">
+ <AREA SHAPE="RECT" COORDS="76,8,182,22" HREF="/admin" ALT="Tâches d'administration">
+ <AREA SHAPE="RECT" COORDS="202,8,260,22" HREF="/classes" ALT="Etat des classes d'imprimantes">
+ <AREA SHAPE="RECT" COORDS="280,8,316,22" HREF="/documentation.html" ALT="Aide électronique en ligne">
+ <AREA SHAPE="RECT" COORDS="334,8,394,22" HREF="/jobs" ALT="Etat des travaux d'impression">
+ <AREA SHAPE="RECT" COORDS="416,8,506,22" HREF="/printers" ALT="Etat des imprimantes">
+ <AREA SHAPE="RECT" COORDS="526,8,582,22" HREF="http://www.cups.org" ALT="Télécharger la dernière version du logiciel CUPS">
+ </MAP>
+</HEAD>
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="596" HEIGHT="28" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1>{title}</H1>
diff --git a/templates/fr/job-cancel.tmpl b/templates/fr/job-cancel.tmpl
new file mode 100644
index 000000000..018450742
--- /dev/null
+++ b/templates/fr/job-cancel.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Le travail d'impression {job_id}</A> a été annulé.
diff --git a/templates/fr/job-hold.tmpl b/templates/fr/job-hold.tmpl
new file mode 100644
index 000000000..13c8c49ac
--- /dev/null
+++ b/templates/fr/job-hold.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">L'impression du travail {job_id}</A> a été retenue.
diff --git a/templates/fr/job-op.tmpl b/templates/fr/job-op.tmpl
new file mode 100644
index 000000000..a82aa033a
--- /dev/null
+++ b/templates/fr/job-op.tmpl
@@ -0,0 +1 @@
+<P>Opération "{op}" non prise en charge pour les travaux d'impression.
diff --git a/templates/fr/job-release.tmpl b/templates/fr/job-release.tmpl
new file mode 100644
index 000000000..c49fab0ce
--- /dev/null
+++ b/templates/fr/job-release.tmpl
@@ -0,0 +1,2 @@
+<P><A HREF="{job_printer_uri}">L'impression du travail {job_id}</A>
+a été libérée.
diff --git a/templates/fr/job-restart.tmpl b/templates/fr/job-restart.tmpl
new file mode 100644
index 000000000..7638216da
--- /dev/null
+++ b/templates/fr/job-restart.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Le travail d'impression {job_id}</A> a été relancé.
diff --git a/templates/fr/jobs.tmpl b/templates/fr/jobs.tmpl
new file mode 100644
index 000000000..5f8a29b19
--- /dev/null
+++ b/templates/fr/jobs.tmpl
@@ -0,0 +1,54 @@
+<P>{#job_id=0?Pas de travaux {?which_jobs=completed?complétés:actifs}:
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH>N°&nbsp;</TH>
+ <TH>Nom&nbsp;</TH>
+ <TH>Utilisateur&nbsp;</TH>
+ <TH>Taille&nbsp;</TH>
+ <TH>Etat&nbsp;</TH>
+ <TH>Contrôle&nbsp;</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+{[job_id]
+<TR VALIGN="TOP">
+ <TD HEIGHT="28"></TD>
+ <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+ <TD>{?job_name=?Inconnu:{job_name}}&nbsp;</TD>
+ <TD>{job_originating_user_name}&nbsp;</TD>
+ <TD>{job_k_octets}k&nbsp;</TD>
+ <TD>{job_state=3?En attente depuis<BR>{time_at_creation}:{job_state=4?held since<BR>{time_at_creation}:
+ {job_state=5?En cours de traitement depuis<BR>{time_at_processing}:{job_state=6?stopped at<BR>{time_at_completed}:
+ {job_state=7?Annulé depuis<BR>{time_at_completed}:{job_state=8?Abandonné à:Complété à<BR>{time_at_completed}}}}}}}&nbsp;</TD>
+ <TD>
+ {job_state>5?
+ {job_k_octets>0?
+ <A HREF="/jobs/?op=restart-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/restart-job.gif" ALT="Restart Job" BORDER="0"></A>
+ :}:}
+ {job_state>6?:
+ {job_state=4?
+ <A HREF="/jobs/?op=release-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/release-job.gif" ALT="Release Job" BORDER="0"></A>
+ :
+ <A HREF="/jobs/?op=hold-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/hold-job.gif" ALT="Hold Job" BORDER="0"></A>
+ }
+ <A HREF="/jobs/?op=cancel-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/cancel-job.gif" ALT="Cancel Job" BORDER="0"></A>
+ }
+ &nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P>{?which_jobs=?
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}?which_jobs=completed">
+<IMG SRC="/images/show-completed.gif" BORDER="0" ALT="Show Completed Jobs"></A>
+:
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}">
+<IMG SRC="/images/show-active.gif" BORDER="0" ALT="Show Active Jobs"></A>
+}
diff --git a/templates/fr/modify-class.tmpl b/templates/fr/modify-class.tmpl
new file mode 100644
index 000000000..493267420
--- /dev/null
+++ b/templates/fr/modify-class.tmpl
@@ -0,0 +1,34 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modifier la classe d'imprimante {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nom:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Emplacement:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/modify-printer.tmpl b/templates/fr/modify-printer.tmpl
new file mode 100644
index 000000000..0278029b2
--- /dev/null
+++ b/templates/fr/modify-printer.tmpl
@@ -0,0 +1,36 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?device_uri=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_DEVICE_URI" VALUE="{device_uri}">}
+{?printer_make_and_model=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{printer_make_and_model}">}
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modifier l'imprimante {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Nom:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Emplacement:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/fr/option-boolean.tmpl b/templates/fr/option-boolean.tmpl
new file mode 100644
index 000000000..a8360fc82
--- /dev/null
+++ b/templates/fr/option-boolean.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{keytext}:</TD>
+ <TD>
+ {[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+ </TD>
+</TR>
diff --git a/templates/fr/option-conflict.tmpl b/templates/fr/option-conflict.tmpl
new file mode 100644
index 000000000..f62944f32
--- /dev/null
+++ b/templates/fr/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Erreur:</B> Les options suivantes entrent en conflit:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Veuillez changer une ou plusieurs de ces options pour résoudre les conflits.
diff --git a/templates/fr/option-header.tmpl b/templates/fr/option-header.tmpl
new file mode 100644
index 000000000..23a904178
--- /dev/null
+++ b/templates/fr/option-header.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/fr/option-pickmany.tmpl b/templates/fr/option-pickmany.tmpl
new file mode 100644
index 000000000..8340889b4
--- /dev/null
+++ b/templates/fr/option-pickmany.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT" VALIGN="TOP">{keytext}:</TD>
+ <TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/fr/option-pickone.tmpl b/templates/fr/option-pickone.tmpl
new file mode 100644
index 000000000..6880b968b
--- /dev/null
+++ b/templates/fr/option-pickone.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{keytext}:</TD>
+ <TD><SELECT NAME="{keyword}">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/fr/option-trailer.tmpl b/templates/fr/option-trailer.tmpl
new file mode 100644
index 000000000..d88956679
--- /dev/null
+++ b/templates/fr/option-trailer.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></TD>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/fr/printer-accept.tmpl b/templates/fr/printer-accept.tmpl
new file mode 100644
index 000000000..c832849bb
--- /dev/null
+++ b/templates/fr/printer-accept.tmpl
@@ -0,0 +1,2 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A>
+accepte désormais les travaux d'impression.
diff --git a/templates/fr/printer-added.tmpl b/templates/fr/printer-added.tmpl
new file mode 100644
index 000000000..8f460b7d6
--- /dev/null
+++ b/templates/fr/printer-added.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> a été ajoutée avec succès.
diff --git a/templates/fr/printer-configured.tmpl b/templates/fr/printer-configured.tmpl
new file mode 100644
index 000000000..10dcb8f61
--- /dev/null
+++ b/templates/fr/printer-configured.tmpl
@@ -0,0 +1,2 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A>
+a été configurée avec succès.
diff --git a/templates/fr/printer-confirm.tmpl b/templates/fr/printer-confirm.tmpl
new file mode 100644
index 000000000..c8dc1ec49
--- /dev/null
+++ b/templates/fr/printer-confirm.tmpl
@@ -0,0 +1,6 @@
+<P><B>Avertissement:</B> Vous êtes sur le point de supprimer l'imprimante {printer_name}!
+Voulez-vous continuer?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-printer&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Suite..." BORDER="0"></A>
diff --git a/templates/fr/printer-deleted.tmpl b/templates/fr/printer-deleted.tmpl
new file mode 100644
index 000000000..521be9c16
--- /dev/null
+++ b/templates/fr/printer-deleted.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante {printer_name} a été supprimée avec succès.
diff --git a/templates/fr/printer-modified.tmpl b/templates/fr/printer-modified.tmpl
new file mode 100644
index 000000000..f74d08879
--- /dev/null
+++ b/templates/fr/printer-modified.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> a été modifiée avec succès.
diff --git a/templates/fr/printer-purge.tmpl b/templates/fr/printer-purge.tmpl
new file mode 100644
index 000000000..a2a91cedf
--- /dev/null
+++ b/templates/fr/printer-purge.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> a été purgée de tous ses travaux d'impression.
diff --git a/templates/fr/printer-reject.tmpl b/templates/fr/printer-reject.tmpl
new file mode 100644
index 000000000..c68dd42e5
--- /dev/null
+++ b/templates/fr/printer-reject.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> n'accepte désormais plus de travaux d'impression.
diff --git a/templates/fr/printer-start.tmpl b/templates/fr/printer-start.tmpl
new file mode 100644
index 000000000..e4a6089a8
--- /dev/null
+++ b/templates/fr/printer-start.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> a été démarrée.
diff --git a/templates/fr/printer-stop.tmpl b/templates/fr/printer-stop.tmpl
new file mode 100644
index 000000000..7d9aeb6bb
--- /dev/null
+++ b/templates/fr/printer-stop.tmpl
@@ -0,0 +1 @@
+<P>L'imprimante <A HREF="/printers/{printer_name}">{printer_name}</A> a été arrêtée.
diff --git a/templates/fr/printers.tmpl b/templates/fr/printers.tmpl
new file mode 100644
index 000000000..b4eccd33b
--- /dev/null
+++ b/templates/fr/printers.tmpl
@@ -0,0 +1,61 @@
+{#printer_name=0?Aucune imprimante définie:
+<P><B>Destination d'impression implicite :</B> {default_name?<A HREF="{default_uri}">{default_name}</A>:none}
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">{printer_make_and_model}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN="TOP"><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/printer-{printer_state=3?idle:{printer_state=4?processing:stopped}}.gif" BORDER="0" ALT=""></A>
+ </TD>
+ <TD VALIGN="TOP">Description: {printer_info}<BR>
+ Emplacement: {printer_location}<BR>
+ Etat de l'imprimante: {printer_state=3?au repos:{printer_state=4?fonctionne:arrêtée}},
+ {printer_is_accepting_jobs=0?rejette les travaux:accepte les travaux}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
+ {?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
+ {?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
+ {?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
+ {?device_uri=?:<BR>URI de périphérique: {device_uri}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Imprimer une page de test" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-printer.gif" ALT="Démarrer l'imprimante" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-printer.gif" ALT="Arrêter l'imprimante" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Accepter les travaux d'impression" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Rejeter les travaux d'impression" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-printer&printer_name={printer_name}">
+ <IMG SRC="/images/modify-printer.gif" ALT="Modifier l'imprimante" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=config-printer&printer_name={printer_name}">
+ <IMG SRC="/images/config-printer.gif" ALT="Configurer l'imprimante" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-printer&printer_name={printer_name}">
+ <IMG SRC="/images/delete-printer.gif" ALT="Supprimer l'imprimante" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-printer">
+<IMG SRC="/images/add-printer.gif" ALT="Ajouter une imprimante" BORDER="0"></A>
diff --git a/templates/fr/test-page.tmpl b/templates/fr/test-page.tmpl
new file mode 100644
index 000000000..69437e6c0
--- /dev/null
+++ b/templates/fr/test-page.tmpl
@@ -0,0 +1,2 @@
+<P>Page de test envoyée; Le n° d'identification du travail d'impression est <A HREF="/printers/{printer_name}">
+{printer_name}-{job_id}</A>.
diff --git a/templates/fr/trailer.tmpl b/templates/fr/trailer.tmpl
new file mode 100644
index 000000000..fbea549b1
--- /dev/null
+++ b/templates/fr/trailer.tmpl
@@ -0,0 +1,7 @@
+<HR>
+<P>Copyright 1993-2004 by Easy Software Products, Tous droits réservés.
+Common UNIX Printing System, CUPS, et le logo CUPS
+sont des marques déposées de <A HREF="http://www.easysw.com">Easy Software Products</A>.
+Toutes les autres marques déposées appartiennent à leurs propriétaires respectifs.
+</BODY>
+</HTML>
diff --git a/templates/header.tmpl b/templates/header.tmpl
new file mode 100644
index 000000000..b22bc73f0
--- /dev/null
+++ b/templates/header.tmpl
@@ -0,0 +1,23 @@
+<HTML>
+<HEAD>
+ <TITLE>{title} on {server_name} - {cups_version}</TITLE>
+ <!-- Prevent caching of CGI content -->
+ <META HTTP-EQUIV="Expires" CONTENT="now">
+ <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
+ <MAP NAME="navbar">
+ <AREA SHAPE="RECT" COORDS="12,0,50,30" HREF="http://www.easysw.com" ALT="Easy Software Products Home Page">
+ <AREA SHAPE="RECT" COORDS="82,0,196,30" HREF="/admin" ALT="Do Administration Tasks">
+ <AREA SHAPE="RECT" COORDS="216,0,280,30" HREF="/classes" ALT="Manage Printer Classes Status">
+ <AREA SHAPE="RECT" COORDS="300,0,336,30" HREF="/documentation.html" ALT="On-Line Help">
+ <AREA SHAPE="RECT" COORDS="356,0,394,30" HREF="/jobs" ALT="Manage Jobs">
+ <AREA SHAPE="RECT" COORDS="414,0,476,30" HREF="/printers" ALT="Manage Printers">
+ <AREA SHAPE="RECT" COORDS="496,0,568,30" HREF="http://www.cups.org" ALT="Download the Current CUPS Software">
+ </MAP>
+</HEAD>
+<BODY BGCOLOR="#cccc99" TEXT="#000000" LINK="#0000FF" VLINK="#FF00FF">
+<CENTER>
+<IMG SRC="/images/navbar.gif" WIDTH="583" HEIGHT="30" USEMAP="#navbar" BORDER="0" ALT="Common UNIX Printing System">
+</CENTER>
+
+<H1>{title}</H1>
diff --git a/templates/job-cancel.tmpl b/templates/job-cancel.tmpl
new file mode 100644
index 000000000..fbdda31dd
--- /dev/null
+++ b/templates/job-cancel.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Job {job_id}</A> has been cancelled.
diff --git a/templates/job-hold.tmpl b/templates/job-hold.tmpl
new file mode 100644
index 000000000..3e391543b
--- /dev/null
+++ b/templates/job-hold.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Job {job_id}</A> has been held from printing.
diff --git a/templates/job-op.tmpl b/templates/job-op.tmpl
new file mode 100644
index 000000000..19520367f
--- /dev/null
+++ b/templates/job-op.tmpl
@@ -0,0 +1 @@
+<P>Unsupported job operation "{op}".
diff --git a/templates/job-release.tmpl b/templates/job-release.tmpl
new file mode 100644
index 000000000..d04622353
--- /dev/null
+++ b/templates/job-release.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Job {job_id}</A> has been released for printing.
diff --git a/templates/job-restart.tmpl b/templates/job-restart.tmpl
new file mode 100644
index 000000000..d575c47a7
--- /dev/null
+++ b/templates/job-restart.tmpl
@@ -0,0 +1 @@
+<P><A HREF="{job_printer_uri}">Job {job_id}</A> has been restarted.
diff --git a/templates/jobs.tmpl b/templates/jobs.tmpl
new file mode 100644
index 000000000..cf61c7bfe
--- /dev/null
+++ b/templates/jobs.tmpl
@@ -0,0 +1,54 @@
+<P>{#job_id=0?No {?which_jobs=completed?Completed:Active} Jobs:
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH>ID&nbsp;</TH>
+ <TH>Name&nbsp;</TH>
+ <TH>User&nbsp;</TH>
+ <TH>Size&nbsp;</TH>
+ <TH>State&nbsp;</TH>
+ <TH>Control&nbsp;</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+{[job_id]
+<TR VALIGN="TOP">
+ <TD HEIGHT="28"></TD>
+ <TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+ <TD>{?job_name=?Unknown:{job_name}}&nbsp;</TD>
+ <TD>{job_originating_user_name}&nbsp;</TD>
+ <TD>{job_k_octets}k&nbsp;</TD>
+ <TD>{job_state=3?pending since<BR>{time_at_creation}:{job_state=4?held since<BR>{time_at_creation}:
+ {job_state=5?processing since<BR>{time_at_processing}:{job_state=6?stopped at<BR>{time_at_completed}:
+ {job_state=7?cancelled at<BR>{time_at_completed}:{job_state=8?aborted:completed at<BR>{time_at_completed}}}}}}}&nbsp;</TD>
+ <TD>
+ {job_state>5?
+ {job_k_octets>0?
+ <A HREF="/jobs/?op=restart-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/restart-job.gif" ALT="Restart Job" BORDER="0"></A>
+ :}:}
+ {job_state>6?:
+ {job_state=4?
+ <A HREF="/jobs/?op=release-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/release-job.gif" ALT="Release Job" BORDER="0"></A>
+ :
+ <A HREF="/jobs/?op=hold-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/hold-job.gif" ALT="Hold Job" BORDER="0"></A>
+ }
+ <A HREF="/jobs/?op=cancel-job&job_id={job_id}&job_printer_uri={job_printer_uri}">
+ <IMG SRC="/images/cancel-job.gif" ALT="Cancel Job" BORDER="0"></A>
+ }
+ &nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P>{?which_jobs=?
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}?which_jobs=completed">
+<IMG SRC="/images/show-completed.gif" BORDER="0" ALT="Show Completed Jobs"></A>
+:
+<A HREF="{?printer_name=?/jobs:/printers/{printer_name}}">
+<IMG SRC="/images/show-active.gif" BORDER="0" ALT="Show Active Jobs"></A>
+}
diff --git a/templates/modify-class.tmpl b/templates/modify-class.tmpl
new file mode 100644
index 000000000..17aeedbba
--- /dev/null
+++ b/templates/modify-class.tmpl
@@ -0,0 +1,34 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modify Class {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Location:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/modify-printer.tmpl b/templates/modify-printer.tmpl
new file mode 100644
index 000000000..68e36cd8e
--- /dev/null
+++ b/templates/modify-printer.tmpl
@@ -0,0 +1,36 @@
+<FORM METHOD="POST" ACTION="/admin">
+<INPUT TYPE="HIDDEN" NAME="OP" VALUE="{op}">
+{?device_uri=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_DEVICE_URI" VALUE="{device_uri}">}
+{?printer_make_and_model=?:<INPUT TYPE="HIDDEN" NAME="CURRENT_MAKE_AND_MODEL" VALUE="{printer_make_and_model}">}
+<TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+<TR BGCOLOR="#999966">
+ <TH WIDTH="16"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH COLSPAN="2">Modify Printer {printer_name}</TH>
+ <TH BGCOLOR="#cccc99" WIDTH="16"><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Name:</TD>
+ <TD><INPUT TYPE="HIDDEN" NAME="PRINTER_NAME" VALUE="{printer_name}">
+ {printer_name}</TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Location:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_LOCATION" VALUE="{?printer_location}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">Description:</TD>
+ <TD><INPUT TYPE="TEXT" NAME="PRINTER_INFO" VALUE="{?printer_info}" SIZE="40" MAXLENGTH="127"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+</TABLE>
+</FORM>
diff --git a/templates/option-boolean.tmpl b/templates/option-boolean.tmpl
new file mode 100644
index 000000000..9aca916e1
--- /dev/null
+++ b/templates/option-boolean.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD>
+ {[choices]<INPUT TYPE="RADIO" NAME="{keyword}" {choices={defchoice}?CHECKED:} VALUE="{choices}">{text}}
+ </TD>
+</TR>
diff --git a/templates/option-conflict.tmpl b/templates/option-conflict.tmpl
new file mode 100644
index 000000000..eb5058c39
--- /dev/null
+++ b/templates/option-conflict.tmpl
@@ -0,0 +1,7 @@
+<P><B>Error:</B> The following options are conflicting:</P>
+
+<UL>
+{[ckeyword]<LI><A HREF="#{ckeyword}">{ckeytext}</A></LI>
+}</UL>
+
+<P>Please change one or more of the options to resolve the conflicts.
diff --git a/templates/option-header.tmpl b/templates/option-header.tmpl
new file mode 100644
index 000000000..23a904178
--- /dev/null
+++ b/templates/option-header.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966" COLSPAN="2">{group}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/option-pickmany.tmpl b/templates/option-pickmany.tmpl
new file mode 100644
index 000000000..531b9bd6a
--- /dev/null
+++ b/templates/option-pickmany.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}" MULTIPLE SIZE="10">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/option-pickone.tmpl b/templates/option-pickone.tmpl
new file mode 100644
index 000000000..7e99eb4c8
--- /dev/null
+++ b/templates/option-pickone.tmpl
@@ -0,0 +1,7 @@
+<TR>
+ <TD></TD>
+ <TD ALIGN="RIGHT">{conflicted=1?<FONT COLOR="#ff0000"><B>:}<A NAME="{keyword}">{keytext}</A>:{conflicted=1?<BR>(conflicting)</B></FONT>:}</TD>
+ <TD><SELECT NAME="{keyword}">
+ {[choices]<OPTION {choices={defchoice}?SELECTED:} VALUE="{choices}">{text}}
+ </SELECT></TD>
+</TR>
diff --git a/templates/option-trailer.tmpl b/templates/option-trailer.tmpl
new file mode 100644
index 000000000..803022837
--- /dev/null
+++ b/templates/option-trailer.tmpl
@@ -0,0 +1,8 @@
+<TR>
+ <TD></TD>
+ <TD></TD>
+ <TD><INPUT TYPE="IMAGE" SRC="/images/continue.gif" ALT="Continue" BORDER="0"></TD>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
diff --git a/templates/printer-accept.tmpl b/templates/printer-accept.tmpl
new file mode 100644
index 000000000..3a269eb0d
--- /dev/null
+++ b/templates/printer-accept.tmpl
@@ -0,0 +1 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> is now accepting jobs.
diff --git a/templates/printer-added.tmpl b/templates/printer-added.tmpl
new file mode 100644
index 000000000..ba5f550c2
--- /dev/null
+++ b/templates/printer-added.tmpl
@@ -0,0 +1,2 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been added
+successfully.
diff --git a/templates/printer-configured.tmpl b/templates/printer-configured.tmpl
new file mode 100644
index 000000000..7ec86879a
--- /dev/null
+++ b/templates/printer-configured.tmpl
@@ -0,0 +1,2 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has
+been configured successfully.
diff --git a/templates/printer-confirm.tmpl b/templates/printer-confirm.tmpl
new file mode 100644
index 000000000..690c6479b
--- /dev/null
+++ b/templates/printer-confirm.tmpl
@@ -0,0 +1,6 @@
+<P><B>Warning:</B> About to delete printer {printer_name}! Do you wish to
+continue?
+
+<P ALIGN="CENTER">
+<A HREF="/admin/?op=delete-printer&printer_name={printer_name}&confirm=yes">
+<IMG SRC="/images/continue.gif" ALT="Continue" BORDER="0"></A>
diff --git a/templates/printer-default.tmpl b/templates/printer-default.tmpl
new file mode 100644
index 000000000..e5dd0b08c
--- /dev/null
+++ b/templates/printer-default.tmpl
@@ -0,0 +1,4 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been
+made the default printer on the server. Please note that any user default
+that has been set via the <TT>lpoptions</TT> command will override this
+default setting.
diff --git a/templates/printer-deleted.tmpl b/templates/printer-deleted.tmpl
new file mode 100644
index 000000000..f1336b037
--- /dev/null
+++ b/templates/printer-deleted.tmpl
@@ -0,0 +1 @@
+<P>Printer {printer_name} has been deleted successfully.
diff --git a/templates/printer-modified.tmpl b/templates/printer-modified.tmpl
new file mode 100644
index 000000000..a16abd169
--- /dev/null
+++ b/templates/printer-modified.tmpl
@@ -0,0 +1,2 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been
+modified successfully.
diff --git a/templates/printer-purge.tmpl b/templates/printer-purge.tmpl
new file mode 100644
index 000000000..863d33916
--- /dev/null
+++ b/templates/printer-purge.tmpl
@@ -0,0 +1 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been purged of all jobs.
diff --git a/templates/printer-reject.tmpl b/templates/printer-reject.tmpl
new file mode 100644
index 000000000..e73d87380
--- /dev/null
+++ b/templates/printer-reject.tmpl
@@ -0,0 +1 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> is no longer accepting jobs.
diff --git a/templates/printer-start.tmpl b/templates/printer-start.tmpl
new file mode 100644
index 000000000..e8d9f497f
--- /dev/null
+++ b/templates/printer-start.tmpl
@@ -0,0 +1,2 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been
+started.
diff --git a/templates/printer-stop.tmpl b/templates/printer-stop.tmpl
new file mode 100644
index 000000000..e01b82677
--- /dev/null
+++ b/templates/printer-stop.tmpl
@@ -0,0 +1,2 @@
+<P>Printer <A HREF="/printers/{printer_name}">{printer_name}</A> has been
+stopped.
diff --git a/templates/printers.tmpl b/templates/printers.tmpl
new file mode 100644
index 000000000..576a992da
--- /dev/null
+++ b/templates/printers.tmpl
@@ -0,0 +1,63 @@
+{#printer_name=0?No printers:
+<P><B>Default Destination:</B> {default_name?<A HREF="{default_uri}">{default_name}</A>:none}
+<P><TABLE CELLPADDING="0" CELLSPACING="0" BORDER="0" WIDTH="100%">
+{[printer_name]
+<TR>
+ <TH BGCOLOR="#999966"><IMG SRC="/images/left.gif" ALT=""></TH>
+ <TH BGCOLOR="#999966"><A HREF="{printer_uri_supported}">{printer_name}</A></TH>
+ <TH BGCOLOR="#999966">{printer_make_and_model}</TH>
+ <TH><IMG SRC="/images/right.gif" ALT=""></TH>
+</TR>
+<TR>
+ <TD HEIGHT="4"></TD>
+</TR>
+<TR>
+ <TD></TD>
+ <TD VALIGN="TOP"><A HREF="{printer_uri_supported}">
+ <IMG SRC="../images/printer-{printer_state=3?idle:{printer_state=4?processing:stopped}}.gif" BORDER="0" ALT=""></A>
+ </TD>
+ <TD VALIGN="TOP">Description: {printer_info}<BR>
+ Location: {printer_location}<BR>
+ Printer State: {printer_state=3?idle:{printer_state=4?processing:stopped}},
+ {printer_is_accepting_jobs=0?rejecting jobs:accepting jobs}.
+ {?printer_state_message=?:<BR><I>"{printer_state_message}"</I>}
+ {?printer_state_history2.printer_state_message=?:<BR><I>"{printer_state_history2.printer_state_message}"</I>}
+ {?printer_state_history3.printer_state_message=?:<BR><I>"{printer_state_history3.printer_state_message}"</I>}
+ {?printer_state_history4.printer_state_message=?:<BR><I>"{printer_state_history4.printer_state_message}"</I>}
+ {?printer_state_history5.printer_state_message=?:<BR><I>"{printer_state_history5.printer_state_message}"</I>}
+ {?device_uri=?:<BR>Device URI: {device_uri}}
+ <P>
+ <A HREF="{printer_uri_supported}?op=print-test-page">
+ <IMG SRC="/images/print-test-page.gif" ALT="Print Test Page" BORDER="0"></A>
+ {printer_state=5?
+ <A HREF="{admin_uri}?op=start-printer&printer_name={printer_name}">
+ <IMG SRC="/images/start-printer.gif" ALT="Start Printer" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=stop-printer&printer_name={printer_name}">
+ <IMG SRC="/images/stop-printer.gif" ALT="Stop Printer" BORDER="0"></A>
+ }
+ {printer_is_accepting_jobs=0?
+ <A HREF="{admin_uri}?op=accept-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/accept-jobs.gif" ALT="Accept Jobs" BORDER="0"></A>
+ :
+ <A HREF="{admin_uri}?op=reject-jobs&printer_name={printer_name}">
+ <IMG SRC="/images/reject-jobs.gif" ALT="Reject Jobs" BORDER="0"></A>
+ }
+ <A HREF="{admin_uri}?op=modify-printer&printer_name={printer_name}">
+ <IMG SRC="/images/modify-printer.gif" ALT="Modify Printer" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=config-printer&printer_name={printer_name}">
+ <IMG SRC="/images/config-printer.gif" ALT="Configure Printer" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=delete-printer&printer_name={printer_name}">
+ <IMG SRC="/images/delete-printer.gif" ALT="Delete Printer" BORDER="0"></A>
+ <A HREF="{admin_uri}?op=set-as-default&printer_name={printer_name}">
+ <IMG SRC="/images/set-as-default.gif" ALT="Set As Default" BORDER="0"></A>
+ </TD>
+</TR>
+<TR>
+ <TD>&nbsp;</TD>
+</TR>
+}
+</TABLE>
+}
+<P><A HREF="/admin/?op=add-printer">
+<IMG SRC="/images/add-printer.gif" ALT="Add Printer" BORDER="0"></A>
diff --git a/templates/test-page.tmpl b/templates/test-page.tmpl
new file mode 100644
index 000000000..5c5005438
--- /dev/null
+++ b/templates/test-page.tmpl
@@ -0,0 +1,2 @@
+<P>Test page sent; job ID is <A HREF="/printers/{printer_name}">
+{printer_name}-{job_id}</A>.
diff --git a/templates/trailer.tmpl b/templates/trailer.tmpl
new file mode 100644
index 000000000..6000b05a6
--- /dev/null
+++ b/templates/trailer.tmpl
@@ -0,0 +1,7 @@
+<HR>
+<P>Copyright 1993-2004 by Easy Software Products, All Rights Reserved.
+The Common UNIX Printing System, CUPS, and the CUPS logo
+are the trademark property of <A HREF="http://www.easysw.com">Easy Software Products</A>.
+All other trademarks are the property of their respective owners.
+</BODY>
+</HTML>
diff --git a/test/.cvsignore b/test/.cvsignore
new file mode 100644
index 000000000..07b5722d6
--- /dev/null
+++ b/test/.cvsignore
@@ -0,0 +1 @@
+ipptest
diff --git a/test/4.1-requests.test b/test/4.1-requests.test
new file mode 100644
index 000000000..ca0c8d326
--- /dev/null
+++ b/test/4.1-requests.test
@@ -0,0 +1,140 @@
+#
+# "$Id: 4.1-requests.test 1595 2001-03-01 20:40:17Z mike $"
+#
+# Verify that the server requires the following attributes:
+#
+# attributes-charset
+# attributes-natural-language
+# printer-uri/job-uri
+#
+{
+ # The name of the test...
+ NAME "No Attributes"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # What statuses are OK?
+ STATUS client-error-bad-request
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Charset Attribute"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+
+ # What statuses are OK?
+ STATUS client-error-bad-request
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Language Attribute"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR language attributes-natural-language en
+
+ # What statuses are OK?
+ STATUS client-error-bad-request
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Language + Charset Attributes"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR language attributes-natural-language en
+ ATTR charset attributes-charset utf-8
+
+ # What statuses are OK?
+ STATUS client-error-bad-request
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Charset + Language Attributes"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+
+ # What statuses are OK?
+ STATUS client-error-bad-request
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Charset + Language + Printer URI Attributes"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Charset + Language + Job URI Attributes"
+
+ # The operation to use
+ OPERATION get-jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri job-uri $method://$hostname:$port/jobs
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+#
+# End of "$Id: 4.1-requests.test 1595 2001-03-01 20:40:17Z mike $"
+#
diff --git a/test/4.2-cups-printer-ops.test b/test/4.2-cups-printer-ops.test
new file mode 100644
index 000000000..8dfd724c5
--- /dev/null
+++ b/test/4.2-cups-printer-ops.test
@@ -0,0 +1,214 @@
+#
+# "$Id: 4.2-cups-printer-ops.test 1595 2001-03-01 20:40:17Z mike $"
+#
+# Verify that the CUPS printer operations work.
+#
+{
+ # The name of the test...
+ NAME "Add Printer Test1"
+
+ # The operation to use
+ OPERATION cups-add-printer
+ RESOURCE /admin/
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ FILE testhp.ppd
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Verify Printer Test1 Added"
+
+ # The operation to use
+ OPERATION get-printer-attributes
+ RESOURCE /
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Delete Printer Test1"
+
+ # The operation to use
+ OPERATION cups-delete-printer
+ RESOURCE /admin/
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Verify Printer Test1 Deleted"
+
+ # The operation to use
+ OPERATION get-printer-attributes
+ RESOURCE /
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ # What statuses are OK?
+ STATUS client-error-not-found
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Add Printer Test2"
+
+ # The operation to use
+ OPERATION cups-add-printer
+ RESOURCE /admin/
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+
+ FILE testps.ppd
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Verify Printer Test2 Added"
+
+ # The operation to use
+ OPERATION get-printer-attributes
+ RESOURCE /
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Modify Printer Test2"
+
+ # The operation to use
+ OPERATION cups-add-printer
+ RESOURCE /admin/
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+
+ GROUP printer
+ ATTR uri device-uri file:/tmp/Test2
+ ATTR enum printer-state 3
+ ATTR boolean printer-is-accepting-jobs true
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Re-Add Printer Test1"
+
+ # The operation to use
+ OPERATION cups-add-printer
+ RESOURCE /admin/
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ GROUP printer
+ ATTR uri device-uri file:/tmp/Test1
+ ATTR enum printer-state 3
+ ATTR boolean printer-is-accepting-jobs true
+
+ FILE testhp.ppd
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Verify Printer Test1 Re-Added"
+
+ # The operation to use
+ OPERATION get-printer-attributes
+ RESOURCE /
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+
+#
+# End of "$Id: 4.2-cups-printer-ops.test 1595 2001-03-01 20:40:17Z mike $"
+#
diff --git a/test/4.3-job-ops.test b/test/4.3-job-ops.test
new file mode 100644
index 000000000..831850ffe
--- /dev/null
+++ b/test/4.3-job-ops.test
@@ -0,0 +1,297 @@
+#
+# "$Id: 4.3-job-ops.test 1595 2001-03-01 20:40:17Z mike $"
+#
+# Verify that the IPP job operations work.
+#
+{
+ # The name of the test...
+ NAME "Print PostScript Job to Test1"
+
+ # The operation to use
+ OPERATION print-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
+
+ FILE testfile.ps
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+}
+{
+ # The name of the test...
+ NAME "Get Job Attributes"
+
+ # The operation to use
+ OPERATION get-job-attributes
+ RESOURCE /jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR integer job-id $job-id
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+ EXPECT job-uri
+ EXPECT job-state
+}
+{
+ # The name of the test...
+ NAME "Print PostScript Job to Test2"
+
+ # The operation to use
+ OPERATION print-job
+ RESOURCE /printers/Test2
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+ ATTR name requesting-user-name $user
+
+ FILE testfile.ps
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+}
+{
+ # The name of the test...
+ NAME "Get Job Attributes"
+
+ # The operation to use
+ OPERATION get-job-attributes
+ RESOURCE /jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test2
+ ATTR integer job-id $job-id
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+ EXPECT job-uri
+ EXPECT job-state
+}
+{
+ # The name of the test...
+ NAME "Print Text Job to Test1"
+
+ # The operation to use
+ OPERATION print-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
+
+ FILE testfile.txt
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+}
+{
+ # The name of the test...
+ NAME "Print PDF Job to Test1"
+
+ # The operation to use
+ OPERATION print-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
+
+ FILE testfile.pdf
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+}
+{
+ # The name of the test...
+ NAME "Print Image Job to Test1"
+
+ # The operation to use
+ OPERATION print-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
+
+ FILE testfile.jpg
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-id
+}
+{
+ # The name of the test...
+ NAME "Hold Job on Test1"
+
+ # The operation to use
+ OPERATION hold-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Release Job on Test1"
+
+ # The operation to use
+ OPERATION release-job
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Get Job List on Test1"
+
+ # The operation to use
+ OPERATION get-jobs
+ RESOURCE /printers/Test1
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $method://$hostname:$port/printers/Test1
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+{
+ # The name of the test...
+ NAME "Get All Jobs"
+
+ # The operation to use
+ OPERATION get-jobs
+ RESOURCE /jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri job-uri $method://$hostname:$port/jobs
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+ EXPECT job-uri
+ EXPECT job-id
+ EXPECT job-state
+}
+{
+ # The name of the test...
+ NAME "Cancel Job"
+
+ # The operation to use
+ OPERATION cancel-job
+ RESOURCE /jobs
+
+ # The attributes to send
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri job-uri $method://$hostname:$port/jobs/$job-id
+ ATTR name requesting-user-name $user
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT attributes-charset
+ EXPECT attributes-natural-language
+}
+
+#
+# End of "$Id: 4.3-job-ops.test 1595 2001-03-01 20:40:17Z mike $"
+#
diff --git a/test/5.1-lpadmin.sh b/test/5.1-lpadmin.sh
new file mode 100755
index 000000000..f74b0e634
--- /dev/null
+++ b/test/5.1-lpadmin.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpadmin command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "Add Printer Test"
+echo ""
+echo " lpadmin -p Test3 -v file:/dev/null -E -m deskjet.ppd"
+../systemv/lpadmin -p Test3 -v file:/dev/null -E -m deskjet.ppd 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "Modify Printer Test"
+echo ""
+echo " lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4"
+../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "Delete Printer Test"
+echo ""
+echo " lpadmin -x Test3"
+../systemv/lpadmin -x Test3 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.2-lpc.sh b/test/5.2-lpc.sh
new file mode 100755
index 000000000..790bb4ba0
--- /dev/null
+++ b/test/5.2-lpc.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpc command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPC Test"
+echo ""
+echo " lpc status"
+../berkeley/lpc status 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.3-lpq.sh b/test/5.3-lpq.sh
new file mode 100755
index 000000000..87953debf
--- /dev/null
+++ b/test/5.3-lpq.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpq command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPQ Test"
+echo ""
+echo " lpq"
+../berkeley/lpq 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.4-lpstat.sh b/test/5.4-lpstat.sh
new file mode 100755
index 000000000..ebba553bf
--- /dev/null
+++ b/test/5.4-lpstat.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpstat command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPSTAT Test"
+echo ""
+echo " lpstat -t"
+../systemv/lpstat -t 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.5-lp.sh b/test/5.5-lp.sh
new file mode 100755
index 000000000..4403399f5
--- /dev/null
+++ b/test/5.5-lp.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lp command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LP Default Test"
+echo ""
+echo " lp testfile.jpg"
+../systemv/lp testfile.jpg 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LP Destination Test"
+echo ""
+echo " lp -d Test1 testfile.jpg"
+../systemv/lp -d Test1 testfile.jpg 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LP Flood Test"
+echo ""
+echo " lp -d Test1 testfile.jpg ($1 times in parallel)"
+i=0
+while test $i -lt $1; do
+ echo " flood copy $i..." 1>&2
+ ../systemv/lp -d Test1 testfile.jpg 2>&1 &
+ lppid=$!
+ i=`expr $i + 1`
+done
+wait $lppid
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.6-lpr.sh b/test/5.6-lpr.sh
new file mode 100755
index 000000000..34fbfb0a9
--- /dev/null
+++ b/test/5.6-lpr.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpr command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPR Default Test"
+echo ""
+echo " lpr testfile.jpg"
+../berkeley/lpr testfile.jpg 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LPR Destination Test"
+echo ""
+echo " lpr -P Test1 testfile.jpg"
+../berkeley/lpr -P Test1 testfile.jpg 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LPR Flood Test"
+echo ""
+echo " lpr -P Test1 testfile.jpg ($1 times in parallel)"
+i=0
+while test $i -lt $1; do
+ echo " flood copy $i..." 1>&2
+ ../berkeley/lpr -P Test1 testfile.jpg 2>&1 &
+ lprpid=$!
+ i=`expr $i + 1`
+done
+wait $lppid
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.7-lprm.sh b/test/5.7-lprm.sh
new file mode 100755
index 000000000..bdaaa3893
--- /dev/null
+++ b/test/5.7-lprm.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lprm command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPRM Current Test"
+echo ""
+echo " lprm"
+../berkeley/lprm 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LPRM Destination Test"
+echo ""
+echo " lprm Test1"
+../berkeley/lprm Test1 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.8-cancel.sh b/test/5.8-cancel.sh
new file mode 100755
index 000000000..5c25733be
--- /dev/null
+++ b/test/5.8-cancel.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the cancel command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "Cancel Destination Test"
+echo ""
+echo " cancel Test1"
+../systemv/cancel Test1 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "Cancel All Test"
+echo ""
+echo " cancel -a -"
+../systemv/cancel -a - 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/5.9-lpinfo.sh b/test/5.9-lpinfo.sh
new file mode 100755
index 000000000..c935baddb
--- /dev/null
+++ b/test/5.9-lpinfo.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Test the lpinfo command.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+echo "LPINFO Devices Test"
+echo ""
+echo " lpinfo -v"
+../systemv/lpinfo -v 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+echo "LPINFO Drivers Test"
+echo ""
+echo " lpinfo -m"
+../systemv/lpinfo -m 2>&1
+if test $? != 0; then
+ echo " FAILED"
+ exit 1
+else
+ echo " PASSED"
+fi
+echo ""
+
+#
+# End of "$Id$".
+#
diff --git a/test/Dependencies b/test/Dependencies
new file mode 100644
index 000000000..cb014d95d
--- /dev/null
+++ b/test/Dependencies
@@ -0,0 +1,4 @@
+# DO NOT DELETE
+
+ipptest.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
+ipptest.o: ../cups/http.h ../cups/md5.h ../cups/ppd.h ../cups/language.h
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 000000000..eaa148503
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,85 @@
+#
+# "$Id$"
+#
+# IPP test makefile for the Common UNIX Printing System (CUPS).
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3142 USA
+#
+# Voice: (301) 373-9600
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+include ../Makedefs
+
+
+#
+# Make all targets...
+#
+
+all: ipptest
+
+
+#
+# Clean all object files...
+#
+
+clean:
+ $(RM) ipptest ipptest.o
+
+
+#
+# Update dependencies (without system header dependencies...)
+#
+
+depend:
+ makedepend -Y -I.. -fDependencies ipptest.c >/dev/null 2>&1
+
+
+#
+# Install all targets...
+#
+
+install:
+
+
+#
+# ipptest
+#
+
+ipptest: ipptest.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o ipptest ipptest.o $(LIBS)
+
+
+#
+# purify target for doing tests on the CUPS API...
+#
+
+purify: ipptest.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ purify $(CC) $(LDFLAGS) -o ipptest.pure ipptest.o $(LIBS)
+
+
+#
+# Dependencies...
+#
+
+include Dependencies
+
+
+#
+# End of "$Id$".
+#
diff --git a/test/create-job-format.test b/test/create-job-format.test
new file mode 100644
index 000000000..87d94a5b6
--- /dev/null
+++ b/test/create-job-format.test
@@ -0,0 +1,56 @@
+# Print a test page using create-job + send-document, specifying the
+# document format.
+{
+ # The name of the test...
+ NAME "Print test page using create-job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION create-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ GROUP job
+ ATTR integer copies 1
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
+{
+ # The name of the test...
+ NAME "... and send-document"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION send-document
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+ ATTR mimetype document-format application/postscript
+ ATTR boolean last-document true
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/create-job-sheets.test b/test/create-job-sheets.test
new file mode 100644
index 000000000..d15bb7d4b
--- /dev/null
+++ b/test/create-job-sheets.test
@@ -0,0 +1,55 @@
+# Test create-job + send-document with job-sheets attribute
+{
+ # The name of the test...
+ NAME "Print test page using create-job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION create-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ GROUP job
+ ATTR integer copies 1
+ ATTR name job-sheets standard
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
+{
+ # The name of the test...
+ NAME "... and send-document"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION send-document
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+ ATTR boolean last-document true
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/create-job-timeout.test b/test/create-job-timeout.test
new file mode 100644
index 000000000..b0e035797
--- /dev/null
+++ b/test/create-job-timeout.test
@@ -0,0 +1,55 @@
+# Print a test page using create-job + send-document, but don't send
+# last-document = true
+{
+ # The name of the test...
+ NAME "Print test page using create-job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION create-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ GROUP job
+ ATTR integer copies 1
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
+{
+ # The name of the test...
+ NAME "... and send-document"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION send-document
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+ ATTR mimetype document-format application/octet-stream
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/create-job.test b/test/create-job.test
new file mode 100644
index 000000000..3cfaac532
--- /dev/null
+++ b/test/create-job.test
@@ -0,0 +1,54 @@
+# Print a test page using create-job + send-document
+{
+ # The name of the test...
+ NAME "Print test page using create-job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION create-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ GROUP job
+ ATTR integer copies 1
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
+{
+ # The name of the test...
+ NAME "... and send-document"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION send-document
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+ ATTR boolean last-document true
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/get-devices.test b/test/get-devices.test
new file mode 100644
index 000000000..76bb5ec76
--- /dev/null
+++ b/test/get-devices.test
@@ -0,0 +1,21 @@
+# Get devices using CUPS-get-devices
+{
+ # The name of the test...
+ NAME "Get devices using CUPS-get-devices"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-get-devices
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/get-job-attributes.test b/test/get-job-attributes.test
new file mode 100644
index 000000000..35b241b06
--- /dev/null
+++ b/test/get-job-attributes.test
@@ -0,0 +1,27 @@
+# Test get-job-attributes by sending a print job, getting the attributes,
+# and cancelling it.
+{
+ # The name of the test...
+ NAME "Get job info with get-job-attributes"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION get-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri job-uri $uri
+
+ # What statuses are OK?
+ #STATUS ok
+ #STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-uri
+ EXPECT job-state
+ EXPECT bogus-attribute
+}
diff --git a/test/get-job-attributes2.test b/test/get-job-attributes2.test
new file mode 100644
index 000000000..029940bff
--- /dev/null
+++ b/test/get-job-attributes2.test
@@ -0,0 +1,29 @@
+# Test get-job-attributes
+{
+ # The name of the test...
+ NAME "get-job-attributes"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION get-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id 7350
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-uri
+ EXPECT job-state
+ EXPECT time-at-creation
+ EXPECT time-at-completed
+ EXPECT time-at-processing
+}
diff --git a/test/get-ppds.test b/test/get-ppds.test
new file mode 100644
index 000000000..90f59eb6e
--- /dev/null
+++ b/test/get-ppds.test
@@ -0,0 +1,21 @@
+# Get PPD files using CUPS-get-ppds
+{
+ # The name of the test...
+ NAME "Get PPD files using CUPS-get-ppds"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION CUPS-get-ppds
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
diff --git a/test/get-printer-attributes.test b/test/get-printer-attributes.test
new file mode 100644
index 000000000..79d4dfffa
--- /dev/null
+++ b/test/get-printer-attributes.test
@@ -0,0 +1,44 @@
+# Get printer attributes using get-printer-attributes
+{
+ # The name of the test...
+ NAME "Get printer attributes using get-printer-attributes"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION get-printer-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+
+ # What statuses are OK?
+ STATUS successful-ok
+
+ # What attributes do we expect?
+ EXPECT charset-configured
+ EXPECT charset-supported
+ EXPECT compression-supported
+ EXPECT document-format-default
+ EXPECT document-format-supported
+ EXPECT generated-natural-language-supported
+ EXPECT ipp-versions-supported
+ EXPECT natural-language-configured
+ EXPECT operations-supported
+ EXPECT printer-info
+ EXPECT printer-is-accepting-jobs
+ EXPECT printer-location
+ EXPECT printer-make-and-model
+ EXPECT printer-more-info
+ EXPECT printer-name
+ EXPECT printer-state
+ EXPECT printer-state-reasons
+ EXPECT printer-up-time
+ EXPECT printer-uri-supported
+ EXPECT uri-authentication-supported
+ EXPECT uri-security-supported
+ EXPECT foo
+}
diff --git a/test/ipptest.c b/test/ipptest.c
new file mode 100644
index 000000000..26696abe5
--- /dev/null
+++ b/test/ipptest.c
@@ -0,0 +1,826 @@
+/*
+ * "$Id$"
+ *
+ * IPP test command for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ * main() - Parse options and do tests.
+ * do_tests() - Do tests as specified in the test file.
+ * get_operation() - Get an IPP opcode from an operation name...
+ * get_status() - Get an IPP status from a status name...
+ * get_tag() - Get an IPP value or group tag from a name...
+ * get_token() - Get a token from a file.
+ * print_attr() - Print an attribute on the screen.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <cups/cups.h>
+#include <cups/language.h>
+
+
+/*
+ * Local globals...
+ */
+
+
+/*
+ * Local functions...
+ */
+
+int do_tests(const char *, const char *);
+ipp_op_t get_operation(const char *);
+ipp_status_t get_status(const char *);
+ipp_tag_t get_tag(const char *);
+char *get_token(FILE *, char *, int);
+void print_attr(ipp_attribute_t *);
+
+
+/*
+ * 'main()' - Parse options and do tests.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ int status; /* Status of tests... */
+
+
+ /*
+ * We need at least:
+ *
+ * testipp URL testfile
+ */
+
+ if (argc < 3)
+ {
+ fputs("Usage: ipptest URL testfile [ ... testfileN ]\n", stderr);
+ return (1);
+ }
+
+ /*
+ * Run tests...
+ */
+
+ for (i = 2, status = 1; status && i < argc; i ++)
+ status = status && do_tests(argv[1], argv[i]);
+
+ /*
+ * Exit...
+ */
+
+ return (!status);
+}
+
+
+/*
+ * 'do_tests()' - Do tests as specified in the test file.
+ */
+
+int /* 1 = success, 0 = failure */
+do_tests(const char *uri, /* I - URI to connect on */
+ const char *testfile) /* I - Test file to use */
+{
+ int i; /* Looping var */
+ int version; /* IPP version number to use */
+ http_t *http; /* HTTP connection to server */
+ char method[HTTP_MAX_URI], /* URI method */
+ userpass[HTTP_MAX_URI], /* username:password */
+ server[HTTP_MAX_URI], /* Server */
+ resource[HTTP_MAX_URI]; /* Resource path */
+ int port; /* Port number */
+ FILE *fp; /* Test file */
+ char token[1024], /* Token from file */
+ *tokenptr, /* Pointer into token */
+ temp[1024], /* Temporary string */
+ *tempptr; /* Pointer into temp string */
+ ipp_t *request; /* IPP request */
+ ipp_t *response; /* IPP response */
+ ipp_op_t op; /* Operation */
+ ipp_tag_t group; /* Current group */
+ ipp_tag_t value; /* Current value type */
+ ipp_attribute_t *attrptr; /* Attribute pointer */
+ char attr[128]; /* Attribute name */
+ int num_statuses; /* Number of valid status codes */
+ ipp_status_t statuses[100]; /* Valid status codes */
+ int num_expects; /* Number of expected attributes */
+ char *expects[100]; /* Expected attributes */
+ char name[1024]; /* Name of test */
+ char filename[1024]; /* Filename */
+ int pass; /* Did we pass the test? */
+ int job_id; /* Job ID from last operation */
+
+
+ /*
+ * Open the test file...
+ */
+
+ if ((fp = fopen(testfile, "r")) == NULL)
+ {
+ printf("Unable to open test file %s - %s\n", testfile, strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Connect to the server...
+ */
+
+ httpSeparate(uri, method, userpass, server, &port, resource);
+ if ((http = httpConnect(server, port)) == NULL)
+ {
+ printf("Unable to connect to %s on port %d - %s\n", server, port,
+ strerror(errno));
+ return (0);
+ }
+
+ /*
+ * Loop on tests...
+ */
+
+ printf("\"%s\":\n", testfile);
+ pass = 1;
+ job_id = 0;
+ version = 1;
+
+ while (get_token(fp, token, sizeof(token)) != NULL)
+ {
+ /*
+ * Expect an open brace...
+ */
+
+ if (strcmp(token, "{") != 0)
+ {
+ printf("Unexpected token %s seen - aborting test!\n", token);
+ httpClose(http);
+ return (0);
+ }
+
+ /*
+ * Initialize things...
+ */
+
+ httpSeparate(uri, method, userpass, server, &port, resource);
+
+ request = ippNew();
+ op = (ipp_op_t)0;
+ group = IPP_TAG_OPERATION;
+ value = IPP_TAG_ZERO;
+ num_statuses = 0;
+ num_expects = 0;
+ filename[0] = '\0';
+
+ strcpy(name, testfile);
+ if (strrchr(name, '.') != NULL)
+ *strrchr(name, '.') = '\0';
+
+ /*
+ * Parse until we see a close brace...
+ */
+
+ while (get_token(fp, token, sizeof(token)) != NULL)
+ {
+ if (strcmp(token, "}") == 0)
+ break;
+ else if (strcasecmp(token, "NAME") == 0)
+ {
+ /*
+ * Name of test...
+ */
+
+ get_token(fp, name, sizeof(name));
+ }
+ else if (strcasecmp(token, "VERSION") == 0)
+ {
+ /*
+ * IPP version number for test...
+ */
+
+ get_token(fp, temp, sizeof(temp));
+ sscanf(temp, "%*d.%d", &version);
+ }
+ else if (strcasecmp(token, "RESOURCE") == 0)
+ {
+ /*
+ * Resource name...
+ */
+
+ get_token(fp, resource, sizeof(resource));
+ }
+ else if (strcasecmp(token, "OPERATION") == 0)
+ {
+ /*
+ * Operation...
+ */
+
+ get_token(fp, token, sizeof(token));
+ op = get_operation(token);
+ }
+ else if (strcasecmp(token, "GROUP") == 0)
+ {
+ /*
+ * Attribute group...
+ */
+
+ get_token(fp, token, sizeof(token));
+ group = get_tag(token);
+ }
+ else if (strcasecmp(token, "ATTR") == 0)
+ {
+ /*
+ * Attribute...
+ */
+
+ get_token(fp, token, sizeof(token));
+ value = get_tag(token);
+ get_token(fp, attr, sizeof(attr));
+ get_token(fp, temp, sizeof(temp));
+
+ token[sizeof(token) - 1] = '\0';
+
+ for (tempptr = temp, tokenptr = token;
+ *tempptr && tokenptr < (token + sizeof(token) - 1);)
+ if (*tempptr == '$')
+ {
+ /*
+ * Substitute a string/number...
+ */
+
+ if (strncasecmp(tempptr + 1, "uri", 3) == 0)
+ {
+ strlcpy(tokenptr, uri, sizeof(token) - (tokenptr - token));
+ tempptr += 4;
+ }
+ else if (strncasecmp(tempptr + 1, "method", 6) == 0)
+ {
+ strlcpy(tokenptr, method, sizeof(token) - (tokenptr - token));
+ tempptr += 7;
+ }
+ else if (strncasecmp(tempptr + 1, "username", 8) == 0)
+ {
+ strlcpy(tokenptr, userpass, sizeof(token) - (tokenptr - token));
+ tempptr += 9;
+ }
+ else if (strncasecmp(tempptr + 1, "hostname", 8) == 0)
+ {
+ strlcpy(tokenptr, server, sizeof(token) - (tokenptr - token));
+ tempptr += 9;
+ }
+ else if (strncasecmp(tempptr + 1, "port", 4) == 0)
+ {
+ snprintf(tokenptr, sizeof(token) - (tokenptr - token),
+ "%d", port);
+ tempptr += 5;
+ }
+ else if (strncasecmp(tempptr + 1, "resource", 8) == 0)
+ {
+ strlcpy(tokenptr, resource, sizeof(token) - (tokenptr - token));
+ tempptr += 9;
+ }
+ else if (strncasecmp(tempptr + 1, "job-id", 6) == 0)
+ {
+ snprintf(tokenptr, sizeof(token) - (tokenptr - token),
+ "%d", job_id);
+ tempptr += 7;
+ }
+ else if (strncasecmp(tempptr + 1, "user", 4) == 0)
+ {
+ strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
+ tempptr += 5;
+ }
+ else
+ {
+ *tokenptr++ = *tempptr ++;
+ *tokenptr = '\0';
+ }
+
+ tokenptr += strlen(tokenptr);
+ }
+ else
+ {
+ *tokenptr++ = *tempptr++;
+ *tokenptr = '\0';
+ }
+
+ switch (value)
+ {
+ case IPP_TAG_BOOLEAN :
+ if (strcasecmp(token, "true") == 0)
+ ippAddBoolean(request, group, attr, 1);
+ else
+ ippAddBoolean(request, group, attr, atoi(token));
+ break;
+
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ ippAddInteger(request, group, value, attr, atoi(token));
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ puts(" ERROR: resolution tag not yet supported!");
+ break;
+
+ case IPP_TAG_RANGE :
+ puts(" ERROR: range tag not yet supported!");
+ break;
+
+ default :
+ ippAddString(request, group, value, attr, NULL, token);
+ break;
+ }
+ }
+ else if (strcasecmp(token, "FILE") == 0)
+ {
+ /*
+ * File...
+ */
+
+ get_token(fp, filename, sizeof(filename));
+ }
+ else if (strcasecmp(token, "STATUS") == 0)
+ {
+ /*
+ * Status...
+ */
+
+ get_token(fp, token, sizeof(token));
+ statuses[num_statuses] = get_status(token);
+ num_statuses ++;
+ }
+ else if (strcasecmp(token, "EXPECT") == 0)
+ {
+ /*
+ * Status...
+ */
+
+ get_token(fp, token, sizeof(token));
+ expects[num_expects] = strdup(token);
+ num_expects ++;
+ }
+ else
+ {
+ printf("Unexpected token %s seen - aborting test!\n", token);
+ httpClose(http);
+ ippDelete(request);
+ return (0);
+ }
+ }
+
+ /*
+ * Submit the IPP request...
+ */
+
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = op;
+ request->request.op.request_id = 1;
+
+ printf(" %-60.60s [ ]", name);
+ fflush(stdout);
+
+ if (filename[0])
+ response = cupsDoFileRequest(http, request, resource, filename);
+ else
+ response = cupsDoRequest(http, request, resource);
+
+ if (response == NULL)
+ {
+ time_t curtime;
+
+ curtime = time(NULL);
+
+ printf("\b\b\b\b\bFAIL]\n");
+ printf(" ERROR %x\n", cupsLastError());
+ printf(" (%s) @ %s\n",
+ ippErrorString(cupsLastError()), ctime(&curtime));
+ pass = 0;
+ }
+ else
+ {
+ if ((attrptr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
+ job_id = attrptr->values[0].integer;
+
+ for (i = 0; i < num_statuses; i ++)
+ if (response->request.status.status_code == statuses[i])
+ break;
+
+ if (i == num_statuses && num_statuses > 0)
+ {
+ printf("\b\b\b\b\bFAIL]\n");
+ printf(" STATUS %x\n", response->request.status.status_code);
+ printf(" (%s)\n",
+ ippErrorString(response->request.status.status_code));
+ printf(" (%lu bytes in response)\n",
+ (unsigned long)ippLength(response));
+
+ pass = 0;
+ }
+ else
+ {
+ for (i = 0; i < num_expects; i ++)
+ if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
+ {
+ if (pass)
+ {
+ printf("\b\b\b\b\bFAIL]\n");
+ printf(" (%lu bytes in response)\n",
+ (unsigned long)ippLength(response));
+ pass = 0;
+ }
+
+ printf(" EXPECTED %s\n", expects[i]);
+ }
+
+ if (pass)
+ {
+ printf("\b\b\b\b\bPASS]\n");
+ printf(" (%lu bytes in response)\n",
+ (unsigned long)ippLength(response));
+ }
+ else
+ {
+ puts(" RECEIVED");
+ printf(" status-code = %04x\n",
+ response->request.status.status_code);
+
+ for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
+ print_attr(attrptr);
+ }
+ }
+
+ ippDelete(response);
+ }
+
+ for (i = 0; i < num_expects; i ++)
+ free(expects[i]);
+
+ if (!pass)
+ break;
+ }
+
+ fclose(fp);
+ httpClose(http);
+
+ return (pass);
+}
+
+
+/*
+ * 'get_operation()' - Get an IPP opcode from an operation name...
+ */
+
+ipp_op_t
+get_operation(const char *name)
+{
+ int i;
+ static char *ipp_ops[] =
+ {
+ "",
+ "",
+ "print-job",
+ "print-uri",
+ "validate-job",
+ "create-job",
+ "send-document",
+ "send-uri",
+ "cancel-job",
+ "get-job-attributes",
+ "get-jobs",
+ "get-printer-attributes",
+ "hold-job",
+ "release-job",
+ "restart-job",
+ "",
+ "pause-printer",
+ "resume-printer",
+ "purge-jobs",
+ "set-printer-attributes",
+ "set-job-attributes",
+ "get-printer-supported-values"
+ },
+ *cups_ops[] =
+ {
+ "cups-get-default",
+ "cups-get-printers",
+ "cups-add-printer",
+ "cups-delete-printer",
+ "cups-get-classes",
+ "cups-add-class",
+ "cups-delete-class",
+ "cups-accept-jobs",
+ "cups-reject-jobs",
+ "cups-set-default",
+ "cups-get-devices",
+ "cups-get-ppds",
+ "cups-move-job"
+ };
+
+
+ for (i = 0; i < (sizeof(ipp_ops) / sizeof(ipp_ops[0])); i ++)
+ if (strcasecmp(name, ipp_ops[i]) == 0)
+ return ((ipp_op_t)i);
+
+ if (strcasecmp(name, "windows-ext") == 0)
+ return (IPP_PRIVATE);
+
+ for (i = 0; i < (sizeof(cups_ops) / sizeof(cups_ops[0])); i ++)
+ if (strcasecmp(name, cups_ops[i]) == 0)
+ return ((ipp_op_t)(i + 0x4001));
+
+ return ((ipp_op_t)0);
+}
+
+
+/*
+ * 'get_status()' - Get an IPP status from a status name...
+ */
+
+ipp_status_t
+get_status(const char *name)
+{
+ int i;
+ static const char *status_oks[] = /* "OK" status codes */
+ {
+ "successful-ok",
+ "successful-ok-ignored-or-substituted-attributes",
+ "successful-ok-conflicting-attributes"
+ },
+ *status_400s[] = /* Client errors */
+ {
+ "client-error-bad-request",
+ "client-error-forbidden",
+ "client-error-not-authenticated",
+ "client-error-not-authorized",
+ "client-error-not-possible",
+ "client-error-timeout",
+ "client-error-not-found",
+ "client-error-gone",
+ "client-error-request-entity-too-large",
+ "client-error-request-value-too-long",
+ "client-error-document-format-not-supported",
+ "client-error-attributes-or-values-not-supported",
+ "client-error-uri-scheme-not-supported",
+ "client-error-charset-not-supported",
+ "client-error-conflicting-attributes",
+ "client-error-compression-not-supported",
+ "client-error-compression-error",
+ "client-error-document-format-error",
+ "client-error-document-access-error"
+ },
+ *status_500s[] = /* Server errors */
+ {
+ "server-error-internal-error",
+ "server-error-operation-not-supported",
+ "server-error-service-unavailable",
+ "server-error-version-not-supported",
+ "server-error-device-error",
+ "server-error-temporary-error",
+ "server-error-not-accepting-jobs",
+ "server-error-busy",
+ "server-error-job-canceled",
+ "server-error-multiple-document-jobs-not-supported"
+ };
+
+
+ for (i = 0; i < (sizeof(status_oks) / sizeof(status_oks[0])); i ++)
+ if (strcasecmp(name, status_oks[i]) == 0)
+ return ((ipp_status_t)i);
+
+ for (i = 0; i < (sizeof(status_400s) / sizeof(status_400s[0])); i ++)
+ if (strcasecmp(name, status_400s[i]) == 0)
+ return ((ipp_status_t)(i + 0x400));
+
+ for (i = 0; i < (sizeof(status_500s) / sizeof(status_500s[0])); i ++)
+ if (strcasecmp(name, status_500s[i]) == 0)
+ return ((ipp_status_t)(i + 0x500));
+
+ return ((ipp_status_t)-1);
+}
+
+
+/*
+ * 'get_tag()' - Get an IPP value or group tag from a name...
+ */
+
+ipp_tag_t
+get_tag(const char *name)
+{
+ int i;
+ static char *names[] =
+ {
+ "zero", "operation", "job", "end", "printer",
+ "unsupported-group", "", "", "", "", "", "", "",
+ "", "", "", "unsupported-value", "default",
+ "unknown", "novalue", "", "notsettable",
+ "deleteattr", "anyvalue", "", "", "", "", "", "",
+ "", "", "", "integer", "boolean", "enum", "", "",
+ "", "", "", "", "", "", "", "", "", "", "string",
+ "date", "resolution", "range", "collection",
+ "textlang", "namelang", "", "", "", "", "", "", "",
+ "", "", "", "text", "name", "", "keyword", "uri",
+ "urischeme", "charset", "language", "mimetype"
+ };
+
+
+ for (i = 0; i < (sizeof(names) / sizeof(names[0])); i ++)
+ if (strcasecmp(name, names[i]) == 0)
+ return ((ipp_tag_t)i);
+
+ return (IPP_TAG_ZERO);
+}
+
+
+/*
+ * 'get_token()' - Get a token from a file.
+ */
+
+char * /* O - Token from file or NULL on EOF */
+get_token(FILE *fp, /* I - File to read from */
+ char *buf, /* I - Buffer to read into */
+ int buflen) /* I - Length of buffer */
+{
+ int ch, /* Character from file */
+ quote; /* Quoting character */
+ char *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+
+
+ for (;;)
+ {
+ /*
+ * Skip whitespace...
+ */
+
+ while (isspace(ch = getc(fp)));
+
+ /*
+ * Read a token...
+ */
+
+ if (ch == EOF)
+ return (NULL);
+ else if (ch == '\'' || ch == '\"')
+ {
+ /*
+ * Quoted text...
+ */
+
+ quote = ch;
+ bufptr = buf;
+ bufend = buf + buflen - 1;
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch == quote)
+ break;
+ else if (bufptr < bufend)
+ *bufptr++ = ch;
+
+ *bufptr = '\0';
+ return (buf);
+ }
+ else if (ch == '#')
+ {
+ /*
+ * Comment...
+ */
+
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\n')
+ break;
+ }
+ else
+ {
+ /*
+ * Whitespace delimited text...
+ */
+
+ ungetc(ch, fp);
+
+ bufptr = buf;
+ bufend = buf + buflen - 1;
+
+ while ((ch = getc(fp)) != EOF)
+ if (isspace(ch) || ch == '#')
+ break;
+ else if (bufptr < bufend)
+ *bufptr++ = ch;
+
+ if (ch == '#')
+ ungetc(ch, fp);
+
+ *bufptr = '\0';
+ return (buf);
+ }
+ }
+}
+
+
+/*
+ * 'print_attr()' - Print an attribute on the screen.
+ */
+
+void
+print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
+{
+ int i; /* Looping var */
+
+
+ if (attr->name == NULL)
+ {
+ puts(" -- separator --");
+ return;
+ }
+
+ printf(" %s = ", attr->name);
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ case IPP_TAG_ENUM :
+ for (i = 0; i < attr->num_values; i ++)
+ printf("%d ", attr->values[i].integer);
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ for (i = 0; i < attr->num_values; i ++)
+ if (attr->values[i].boolean)
+ printf("true ");
+ else
+ printf("false ");
+ break;
+
+ case IPP_TAG_NOVALUE :
+ printf("novalue");
+ break;
+
+ case IPP_TAG_RANGE :
+ for (i = 0; i < attr->num_values; i ++)
+ printf("%d-%d ", attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ for (i = 0; i < attr->num_values; i ++)
+ printf("%dx%d%s ", attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units == IPP_RES_PER_INCH ?
+ "dpi" : "dpc");
+ break;
+
+ case IPP_TAG_STRING :
+ case IPP_TAG_TEXT :
+ case IPP_TAG_NAME :
+ case IPP_TAG_KEYWORD :
+ case IPP_TAG_CHARSET :
+ case IPP_TAG_URI :
+ case IPP_TAG_MIMETYPE :
+ case IPP_TAG_LANGUAGE :
+ for (i = 0; i < attr->num_values; i ++)
+ printf("\"%s\" ", attr->values[i].string.text);
+ break;
+
+ case IPP_TAG_TEXTLANG :
+ case IPP_TAG_NAMELANG :
+ for (i = 0; i < attr->num_values; i ++)
+ printf("\"%s\",%s ", attr->values[i].string.text,
+ attr->values[i].string.charset);
+ break;
+
+ default :
+ break; /* anti-compiler-warning-code */
+ }
+
+ putchar('\n');
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/test/print-job-hold.test b/test/print-job-hold.test
new file mode 100644
index 000000000..6bdaa8381
--- /dev/null
+++ b/test/print-job-hold.test
@@ -0,0 +1,33 @@
+# Test print-job and job-hold-until attribute
+{
+ # The name of the test...
+ NAME "Print with print-job + job-hold-until"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION print-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+ ATTR mimetype document-format application/postscript
+ ATTR keyword job-hold-until indefinite
+
+ GROUP job
+ ATTR integer copies 1
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
diff --git a/test/print-job.test b/test/print-job.test
new file mode 100644
index 000000000..cdab3322f
--- /dev/null
+++ b/test/print-job.test
@@ -0,0 +1,33 @@
+# Print a test page using print-job
+{
+ # The name of the test...
+ NAME "Print test page using print-job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION print-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+ ATTR mimetype document-format application/postscript
+
+ GROUP job
+ ATTR integer copies 1
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ #STATUS ok
+ #STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+ EXPECT bogus
+}
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
new file mode 100755
index 000000000..36fe851c0
--- /dev/null
+++ b/test/run-stp-tests.sh
@@ -0,0 +1,471 @@
+#!/bin/sh
+#
+# "$Id$"
+#
+# Perform the complete set of IPP compliance tests specified in the
+# CUPS Software Test Plan.
+#
+# Copyright 1997-2004 by Easy Software Products, all rights reserved.
+#
+# These coded instructions, statements, and computer programs are the
+# property of Easy Software Products and are protected by Federal
+# copyright law. Distribution and use rights are outlined in the file
+# "LICENSE.txt" which should have been included with this file. If this
+# file is missing or damaged please contact Easy Software Products
+# at:
+#
+# Attn: CUPS Licensing Information
+# Easy Software Products
+# 44141 Airport View Drive, Suite 204
+# Hollywood, Maryland 20636-3111 USA
+#
+# Voice: (301) 373-9603
+# EMail: cups-info@cups.org
+# WWW: http://www.cups.org
+#
+
+#
+# Make the IPP test program...
+#
+
+make
+
+#
+# Greet the tester...
+#
+
+echo "Welcome to the CUPS Automated Test Script."
+echo ""
+echo "Before we begin, it is important that you understand that the larger"
+echo "tests require significant amounts of RAM and disk space. If you"
+echo "attempt to run one of the big tests on a system that lacks sufficient"
+echo "disk and virtual memory, the UNIX kernel might decide to kill one or"
+echo "more system processes that you've grown attached to, like the X"
+echo "server. The question you may want to ask yourself before running a"
+echo "large test is: Do you feel lucky?"
+echo ""
+echo "OK, now that we have the Dirty Harry quote out of the way, please"
+echo "choose the type of test you wish to perform:"
+echo ""
+echo "1 - Basic conformance test, no load testing (all systems)"
+echo "2 - Basic conformance test, some load testing (minimum 256MB VM, 50MB disk)"
+echo "3 - Basic conformance test, extreme load testing (minimum 1GB VM, 500MB disk)"
+echo "4 - Basic conformance test, torture load testing (minimum 2GB VM, 1GB disk)"
+echo ""
+echo "Please enter the number of the test you wish to perform:"
+
+read testtype
+
+case "$testtype" in
+ 2)
+ echo "Running the medium tests (2)"
+ nprinters1=10
+ nprinters2=20
+ pjobs=20
+ ;;
+ 3)
+ echo "Running the extreme tests (3)"
+ nprinters1=500
+ nprinters2=1000
+ pjobs=100
+ ;;
+ 4)
+ echo "Running the torture tests (4)"
+ nprinters1=10000
+ nprinters2=20000
+ pjobs=200
+ ;;
+ *)
+ echo "Running the timid tests (1)"
+ nprinters1=0
+ nprinters2=0
+ pjobs=0
+ ;;
+esac
+
+#
+# Information for the server/tests...
+#
+
+user=`whoami`
+port=8631
+cwd=`pwd`
+root=`dirname $cwd`
+
+#
+# Make sure that the LPDEST and PRINTER environment variables are
+# not included in the environment that is passed to the tests. These
+# will usually cause tests to fail erroneously...
+#
+
+typeset +x LPDEST
+typeset +x PRINTER
+
+#
+# See if we want to use valgrind...
+#
+
+echo ""
+echo "This test script can use the Valgrind software from:"
+echo ""
+echo " http://developer.kde.org/~sewardj/"
+echo ""
+echo "Please enter Y to use Valgrind or N to not use Valgrind:"
+
+read usevalgrind
+
+case "$usevalgrind" in
+ Y* | y*)
+ valgrind="valgrind --tool=memcheck --logfile=/tmp/$user/log/valgrind --error-limit=no --leak-check=yes --trace-children=yes"
+ echo "Using Valgrind; log files can be found in /tmp/$user/log..."
+ ;;
+
+ *)
+ valgrind=""
+ ;;
+esac
+
+#
+# Start by creating temporary directories for the tests...
+#
+
+rm -rf /tmp/$user
+mkdir /tmp/$user
+mkdir /tmp/$user/bin
+mkdir /tmp/$user/bin/backend
+mkdir /tmp/$user/bin/filter
+mkdir /tmp/$user/certs
+mkdir /tmp/$user/share
+mkdir /tmp/$user/share/banners
+mkdir /tmp/$user/share/model
+mkdir /tmp/$user/interfaces
+mkdir /tmp/$user/log
+mkdir /tmp/$user/ppd
+mkdir /tmp/$user/spool
+mkdir /tmp/$user/spool/temp
+mkdir /tmp/$user/ssl
+
+ln -s $root/backend/http /tmp/$user/bin/backend
+ln -s $root/backend/ipp /tmp/$user/bin/backend
+ln -s $root/backend/lpd /tmp/$user/bin/backend
+ln -s $root/backend/parallel /tmp/$user/bin/backend
+ln -s $root/backend/serial /tmp/$user/bin/backend
+ln -s $root/backend/socket /tmp/$user/bin/backend
+ln -s $root/backend/usb /tmp/$user/bin/backend
+ln -s $root/cgi-bin /tmp/$user/bin
+ln -s $root/filter/hpgltops /tmp/$user/bin/filter
+ln -s $root/filter/imagetops /tmp/$user/bin/filter
+ln -s $root/filter/imagetoraster /tmp/$user/bin/filter
+ln -s $root/filter/pstops /tmp/$user/bin/filter
+ln -s $root/filter/rastertoepson /tmp/$user/bin/filter
+ln -s $root/filter/rastertohp /tmp/$user/bin/filter
+ln -s $root/filter/texttops /tmp/$user/bin/filter
+ln -s $root/pdftops/pdftops /tmp/$user/bin/filter
+
+ln -s $root/data/classified /tmp/$user/share/banners
+ln -s $root/data/confidential /tmp/$user/share/banners
+ln -s $root/data/secret /tmp/$user/share/banners
+ln -s $root/data/standard /tmp/$user/share/banners
+ln -s $root/data/topsecret /tmp/$user/share/banners
+ln -s $root/data/unclassified /tmp/$user/share/banners
+ln -s $root/data /tmp/$user/share/charsets
+ln -s $root/data /tmp/$user/share
+ln -s $root/fonts /tmp/$user/share
+ln -s $root/ppd/*.ppd /tmp/$user/share/model
+ln -s $root/templates /tmp/$user/share
+
+#
+# Then create the necessary config files...
+#
+
+cat >/tmp/$user/cupsd.conf <<EOF
+Browsing Off
+FileDevice yes
+Printcap
+Listen 127.0.0.1:$port
+User $user
+ServerRoot /tmp/$user
+ServerBin /tmp/$user/bin
+DataDir /tmp/$user/share
+FontPath /tmp/$user/share/fonts
+DocumentRoot $root/doc
+RequestRoot /tmp/$user/spool
+TempDir /tmp/$user/spool/temp
+MaxLogSize 0
+AccessLog /tmp/$user/log/access_log
+ErrorLog /tmp/$user/log/error_log
+PageLog /tmp/$user/log/page_log
+LogLevel debug2
+PreserveJobHistory Yes
+<Location />
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+</Location>
+<Location /admin>
+Order deny,allow
+Deny from all
+Allow from 127.0.0.1
+Require valid-user
+</Location>
+EOF
+
+touch /tmp/$user/classes.conf
+touch /tmp/$user/printers.conf
+
+#
+# Setup lots of test queues - 500 with PPD files, 500 without...
+#
+
+i=1
+while test $i -le $nprinters1; do
+ cat >>/tmp/$user/printers.conf <<EOF
+<Printer test-$i>
+Accepting Yes
+DeviceURI file:/dev/null
+Info Test PS printer $i
+JobSheets none none
+Location CUPS test suite
+State Idle
+StateMessage Printer $1 is idle.
+</Printer>
+EOF
+
+ cp testps.ppd /tmp/$user/ppd/test-$i.ppd
+
+ i=`expr $i + 1`
+done
+
+while test $i -le $nprinters2; do
+ cat >>/tmp/$user/printers.conf <<EOF
+<Printer test-$i>
+Accepting Yes
+DeviceURI file:/dev/null
+Info Test raw printer $i
+JobSheets none none
+Location CUPS test suite
+State Idle
+StateMessage Printer $1 is idle.
+</Printer>
+EOF
+
+ i=`expr $i + 1`
+done
+
+cp /tmp/$user/printers.conf /tmp/$user/printers.conf.orig
+
+cp $root/conf/mime.types /tmp/$user/mime.types
+cp $root/conf/mime.convs /tmp/$user/mime.convs
+
+#
+# Setup the paths...
+#
+
+if test "x$LD_LIBRARY_PATH" = x; then
+ LD_LIBRARY_PATH="$root/cups:$root/filter"
+else
+ LD_LIBRARY_PATH="$root/cups:$root/filter:$LD_LIBRARY_PATH"
+fi
+
+export LD_LIBRARY_PATH
+
+LD_PRELOAD="$root/cups/libcups.so:$root/filter/libcupsimage.so"
+export LD_PRELOAD
+
+if test "x$DYLD_LIBRARY_PATH" = x; then
+ DYLD_LIBRARY_PATH="$root/cups:$root/filter"
+else
+ DYLD_LIBRARY_PATH="$root/cups:$root/filter:$DYLD_LIBRARY_PATH"
+fi
+
+export DYLD_LIBRARY_PATH
+
+if test "x$SHLIB_PATH" = x; then
+ SHLIB_PATH="$root/cups:$root/filter"
+else
+ SHLIB_PATH="$root/cups:$root/filter:$SHLIB_PATH"
+fi
+
+export SHLIB_PATH
+
+CUPS_SERVERROOT=/tmp/$user; export CUPS_SERVERROOT
+CUPS_DATADIR=/tmp/$user/share; export CUPS_DATADIR
+
+#
+# Set a new home directory to avoid getting user options mixed in...
+#
+
+HOME=/tmp/$user
+export HOME
+
+#
+# Start the server; run as foreground daemon in the background...
+#
+
+echo "Starting scheduler:"
+echo " $valgrind ../scheduler/cupsd -c /tmp/$user/cupsd.conf -f >/tmp/$user/log/debug_log &"
+
+$valgrind ../scheduler/cupsd -c /tmp/$user/cupsd.conf -f >/tmp/$user/log/debug_log &
+cupsd=$!
+
+echo "Scheduler is PID $cupsd; run debugger now if you need to."
+echo ""
+echo "Press ENTER to continue..."
+read junk
+
+IPP_PORT=$port; export IPP_PORT
+
+while true; do
+ running=`../systemv/lpstat -r 2>/dev/null`
+ if test "x$running" = "xscheduler is running"; then
+ break
+ fi
+
+ echo "Waiting for scheduler to become ready..."
+ sleep 10
+done
+
+#
+# Create the test report source file...
+#
+
+strfile=cups-str-1.1-`date +%Y-%m-%d`-`whoami`.shtml
+
+rm -f $strfile
+cat str-header.html >$strfile
+
+#
+# Run the IPP tests...
+#
+
+echo "Running IPP compliance tests..."
+
+echo "<H1>IPP Compliance Tests</H1>" >>$strfile
+echo "<P>This section provides the results to the IPP compliance tests" >>$strfile
+echo "outlined in the CUPS Software Test Plan. These tests were run on" >>$strfile
+echo `date "+%Y-%m-%d"` by `whoami` on `hostname`. >>$strfile
+echo "<PRE>" >>$strfile
+
+fail=0
+for file in 4*.test; do
+ echo "Performing $file..."
+ echo "" >>$strfile
+
+ ./ipptest ipp://localhost:$port/printers $file >>$strfile
+ status=$?
+
+ if test $status != 0; then
+ echo Test failed.
+ fail=`expr $fail + 1`
+ fi
+done
+
+echo "</PRE>" >>$strfile
+
+#
+# Run the command tests...
+#
+
+echo "Running command tests..."
+
+echo "<H1>Command Tests</H1>" >>$strfile
+echo "<P>This section provides the results to the command tests" >>$strfile
+echo "outlined in the CUPS Software Test Plan. These tests were run on" >>$strfile
+echo `date "+%Y-%m-%d"` by `whoami` on `hostname`. >>$strfile
+echo "<PRE>" >>$strfile
+
+for file in 5*.sh; do
+ echo "Performing $file..."
+ echo "" >>$strfile
+ echo "\"$file\":" >>$strfile
+
+ sh $file $pjobs >>$strfile
+ status=$?
+
+ if test $status != 0; then
+ echo Test failed.
+ fail=`expr $fail + 1`
+ fi
+done
+
+echo "</PRE>" >>$strfile
+
+#
+# Wait for jobs to complete...
+#
+
+while true; do
+ jobs=`../systemv/lpstat 2>/dev/null`
+ if test "x$jobs" = "x"; then
+ break
+ fi
+
+ echo "Waiting for jobs to complete..."
+ sleep 10
+done
+
+#
+# Stop the server...
+#
+
+kill $cupsd
+
+#
+# Append the log files for post-mortim...
+#
+
+echo "<H1>Log Files</H1>" >>$strfile
+
+echo "<H2>access_log</H2>" >>$strfile
+echo "<PRE>" >>$strfile
+cat /tmp/$user/log/access_log >>$strfile
+echo "</PRE>" >>$strfile
+
+echo "<H2>error_log</H2>" >>$strfile
+echo "<PRE>" >>$strfile
+cat /tmp/$user/log/error_log >>$strfile
+echo "</PRE>" >>$strfile
+
+echo "<H2>page_log</H2>" >>$strfile
+echo "<PRE>" >>$strfile
+cat /tmp/$user/log/page_log >>$strfile
+echo "</PRE>" >>$strfile
+
+#
+# Format the reports and tell the user where to find them...
+#
+
+echo "Formatting reports..."
+
+cat str-trailer.html >>$strfile
+
+htmlfile=`basename $strfile .shtml`.html
+pdffile=`basename $strfile .shtml`.pdf
+
+htmldoc --numbered --verbose --titleimage ../doc/images/cups-large.gif \
+ -f $htmlfile $strfile
+htmldoc --numbered --verbose --titleimage ../doc/images/cups-large.gif \
+ -f $pdffile $strfile
+
+echo ""
+
+if test $fail != 0; then
+ echo "$fail tests failed."
+else
+ echo "All tests were successful."
+fi
+
+if test "x$valgrind" != x; then
+ echo "Valgrind log files can be found in /tmp/$user/log."
+fi
+
+echo ""
+echo "See the following files for details:"
+echo ""
+echo " $htmlfile"
+echo " $pdffile"
+echo ""
+
+#
+# End of "$Id$"
+#
diff --git a/test/set-attrs-hold.test b/test/set-attrs-hold.test
new file mode 100644
index 000000000..377819ae4
--- /dev/null
+++ b/test/set-attrs-hold.test
@@ -0,0 +1,180 @@
+# Test print-job and later job-hold-until attribute
+{
+ # The name of the test...
+ NAME "Disable printer..."
+
+ # The resource to use for the POST
+ RESOURCE /admin/
+
+ # The operation to use
+ OPERATION pause-printer
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
+
+{
+ # The name of the test...
+ NAME "Print job"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION print-job
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+ ATTR mimetype document-format application/postscript
+
+ GROUP job
+ ATTR integer copies 1
+
+ FILE ../data/testprint.ps
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-id
+ EXPECT job-uri
+}
+
+{
+ # The name of the test...
+ NAME "Get job attrs"
+
+ # The resource to use for the POST
+ RESOURCE /
+
+ # The operation to use
+ OPERATION get-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-state
+ EXPECT job-hold-until
+}
+
+{
+ # The name of the test...
+ NAME "Set job attrs with job-hold-until"
+
+ # The resource to use for the POST
+ # RESOURCE /admin
+
+ # The operation to use
+ OPERATION set-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+ ATTR name requesting-user-name $user
+
+ GROUP job
+ ATTR name job-hold-until 00:30:00
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
+
+{
+ # The name of the test...
+ NAME "Get job attrs again"
+
+ # The resource to use for the POST
+ RESOURCE /
+
+ # The operation to use
+ OPERATION get-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-state
+ EXPECT job-hold-until
+}
+
+{
+ # The name of the test...
+ NAME "Enable printer..."
+
+ # The resource to use for the POST
+ RESOURCE /admin/
+
+ # The operation to use
+ OPERATION resume-printer
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR name requesting-user-name $user
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+}
+
+{
+ # The name of the test...
+ NAME "Get job attrs (last time)"
+
+ # The resource to use for the POST
+ RESOURCE /
+
+ # The operation to use
+ OPERATION get-job-attributes
+
+ # Attributes, starting in the operation group...
+ GROUP operation
+ ATTR charset attributes-charset utf-8
+ ATTR language attributes-natural-language en
+ ATTR uri printer-uri $uri
+ ATTR integer job-id $job-id
+
+ # What statuses are OK?
+ STATUS ok
+ STATUS ok-subst
+
+ # What attributes do we expect?
+ EXPECT job-state
+ EXPECT job-hold-until
+}
diff --git a/test/str-header.html b/test/str-header.html
new file mode 100644
index 000000000..a2e93e876
--- /dev/null
+++ b/test/str-header.html
@@ -0,0 +1,35 @@
+<HTML>
+<HEAD>
+ <META NAME="Description" CONTENT="Common UNIX Printing System Software Test Report">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.1">
+ <META NAME="Author" CONTENT="Easy Software Products">
+ <TITLE>CUPS Software Test Report</TITLE>
+</HEAD>
+<BODY>
+
+<H1>Scope</H1>
+
+<H2>Identification</H2>
+
+<P>This software test report provides detailed test results that
+are used to evaluate the stability and compliance of the Common
+UNIX Printing System ("CUPS") Version 1.1.
+
+<EMBED SRC="../doc/system-overview.shtml">
+
+<H2>Document Overview</H2>
+
+<P>This software test plan is organized into the following sections:
+
+<UL>
+ <LI>1 - Scope</LI>
+ <LI>2 - References</LI>
+ <LI>3 - IPP Compliance Tests</LI>
+ <LI>4 - Command Tests</LI>
+ <LI>5 - Log Files</LI>
+ <LI>A - Glossary</LI>
+</UL>
+
+<EMBED SRC="../doc/references.shtml">
+
diff --git a/test/str-trailer.html b/test/str-trailer.html
new file mode 100644
index 000000000..4c8ddd526
--- /dev/null
+++ b/test/str-trailer.html
@@ -0,0 +1,5 @@
+<EMBED SRC="../doc/glossary.shtml">
+
+
+</BODY>
+</HTML>
diff --git a/test/testfile.jpg b/test/testfile.jpg
new file mode 100644
index 000000000..9f4b39938
--- /dev/null
+++ b/test/testfile.jpg
Binary files differ
diff --git a/test/testfile.pdf b/test/testfile.pdf
new file mode 100644
index 000000000..8ae73cb58
--- /dev/null
+++ b/test/testfile.pdf
Binary files differ
diff --git a/test/testfile.ps b/test/testfile.ps
new file mode 100644
index 000000000..ae4e7e8e7
--- /dev/null
+++ b/test/testfile.ps
@@ -0,0 +1,512 @@
+%!PS-Adobe-3.0
+%%BoundingBox: 0 0 612 792
+%%Pages: 1
+%%LanguageLevel: 1
+%%DocumentData: Clean7Bit
+%%DocumentSuppliedResources: procset testprint/1.0
+%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman
+%%Creator: Michael Sweet, Easy Software Products
+%%CreationDate: May 11, 1999
+%%Title: Test Page
+%%EndComments
+%%BeginProlog
+%%BeginResource procset testprint 1.1 0
+%
+% PostScript test page for the Common UNIX Printing System ("CUPS").
+%
+% Copyright 1993-2003 by Easy Software Products
+%
+% These coded instructions, statements, and computer programs contain
+% unpublished proprietary information of Easy Software Products, and
+% are protected by Federal copyright law. They may not be disclosed
+% to third parties or copied or duplicated in any form, in whole or
+% in part, without the prior written consent of Easy Software Products.
+%
+/OCTANT { % Draw a color wheel OCTANT...
+ % (name) radius r g b OCTANT -
+ % Loop through 100 shades...
+ 0 0.010101 0.98 {
+ % Set the color...
+ 3 index 1 eq % R == 1?
+ 3 index 1 eq % G == 1?
+ 3 index 1 eq % B == 1?
+ and and {
+ 0 index 4 index mul % R * val
+ 1 index 4 index mul % G * val
+ 2 index 4 index mul % B * val
+ } {
+ 0 index 4 index mul % R * val
+ 1 index neg 1 add add % + (1 - val)
+ 1 index 4 index mul % G * val
+ 2 index neg 1 add add % + (1 - val)
+ 2 index 4 index mul % B * val
+ 3 index neg 1 add add % + (1 - val)
+ } ifelse
+ setrgbcolor
+
+ % Draw a polygon...
+ dup 5 index mul dup 0 % x1, y1
+ moveto
+ 0.707106781 mul dup lineto % x2, y2
+
+ 0.010101 add 4 index mul dup % x3
+ 0.707106781 mul dup lineto % x3, y3
+ 0 lineto % x4, y4
+ closepath
+ fill
+ } for
+
+ % Draw a line around the polygons...
+ pop pop pop dup
+ 0 setgray
+ 0 0 moveto
+ dup 0 lineto
+ 0.707106781 mul dup lineto
+ closepath
+ stroke
+
+ % Draw the label...
+ 0 exch dup -9 div exch % text offset = 0, -radius/9
+ dup 0.923879532 mul % x = radius * cos(22.5)
+ exch 0.382683432 mul % y = radius * cos(22.5)
+ moveto % position label
+ gsave
+ 22.5 rotate % rotate label
+ rmoveto % offset label
+ show % show label
+ grestore
+} bind def
+/CENTER { % Draw centered text
+ % (name) CENTER -
+ dup stringwidth pop % Get the width of the string
+ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance
+ show % Show the string
+} bind def
+/RIGHT { % Draw right-justified text
+ % (name) RIGHT -
+ dup stringwidth pop % Get the width of the string
+ neg 0 rmoveto % Shift left the entire distance
+ show % Show the string
+} bind def
+/NUMBER { % Draw a number
+ % power n NUMBER -
+ 1 index 1 eq { % power == 1?
+ round cvi exch pop % Convert "n" to integer
+ } {
+ 1 index mul round exch div % Truncate extra decimal places
+ } ifelse
+ 100 string cvs show % Convert to a string and show it...
+} bind def
+/CUPSLOGO { % Draw the CUPS logo
+ % height CUPSLOGO
+ % Start with a big C...
+ /Helvetica findfont 1 index scalefont setfont
+ 0 setgray
+ 0 0 moveto
+ (C) show
+
+ % Then "UNIX Printing System" much smaller...
+ /Helvetica-Bold findfont 1 index 9 div scalefont setfont
+ 0.25 mul
+ dup dup 2.0 mul moveto
+ (UNIX) show
+ dup dup 1.6 mul moveto
+ (Printing) show
+ dup 1.2 mul moveto
+ (System) show
+} bind def
+/ESPLOGO { % Draw the ESP logo
+ % height ESPLOGO
+ % Compute the size of the logo...
+ 0 0
+ 2 index 1.5 mul 3 index
+
+ % Do the "metallic" fill from 10% black to 40% black...
+ 1 -0.001 0 {
+ dup % loopval
+ -0.15 mul % loopval * -0.15
+ 0.9 add % 0.9 - loopval * 0.15
+ setgray % set gray shade
+
+ 0 % x
+ 1 index neg % loopval
+ 1 add % 1 - loopval
+ 3 index % height
+ mul % height * (1 - loopval)
+ moveto % starting point
+
+ dup % loopval
+ 3 index % width
+ mul % loopval * width
+ 2 index % height
+ lineto % Next point
+
+ 0 % x
+ 2 index % height
+ lineto % Next point
+
+ closepath
+ fill
+
+ dup % loopval
+ 0.15 mul % loopval * 0.15
+ 0.6 add % 0.6 + loopval * 0.15
+ setgray
+
+ dup % loopval
+ neg 1 add % 1 - loopval
+ 3 index % width
+ mul % (1 - loopval) * width
+ 0 % y
+ moveto % Starting point
+
+ 2 index % width
+ exch % loopval
+ 2 index % height
+ mul % loopval * height
+ lineto % Next point
+
+ 1 index % width
+ 0 % y
+ lineto % Next point
+
+ closepath
+ fill
+ } for
+
+ 0 setgray rectstroke
+
+ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont
+ dup 40 div
+
+ dup 4 mul 1 index 25 mul moveto (E) show
+ dup 10 mul 1 index 15 mul moveto (S) show
+ dup 16 mul 1 index 5 mul moveto (P) show
+
+ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont
+ dup 14 mul 1 index 29 mul moveto (asy) show
+ dup 20 mul 1 index 19 mul moveto (oftware) show
+ dup 26 mul 1 index 9 mul moveto (roducts) show
+
+ pop
+} bind def
+%%EndResource
+%%EndProlog
+%%Page: 1 1
+gsave
+
+ % Determine the imageable area and device resolution...
+ initclip newpath clippath pathbbox % Get bounding rectangle
+ 72 div /pageTop exch def % Get top margin in inches
+ 72 div /pageRight exch def % Get right margin in inches
+ 72 div /pageBottom exch def % Get bottom margin in inches
+ 72 div /pageLeft exch def % Get left margin in inches
+
+ 4 setlinewidth % Draw wide lines
+ 0 setgray closepath stroke % Draw a clipping rectangle
+ 1 setlinewidth % Draw normal lines
+
+ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft
+ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom
+
+ 72 72 dtransform % Get device resolution per inch
+ /yResolution exch abs def % yResolution = abs(yres)
+ /xResolution exch abs def % xResolution = abs(xres)
+
+ % Figure out the sizes of things...
+ /wheelSize % size of wheels
+ pageWidth pageHeight lt
+ { pageWidth 9 mul }
+ { pageHeight 7 mul }
+ ifelse def
+
+ % Create fonts...
+ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold
+ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33)
+
+ /mediumFont /Helvetica findfont % mediumFont = Helvetica
+ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5)
+
+ /smallFont /Times-Roman findfont % smallFont = Times-Roman
+ pageHeight scalefont def % size = pageHeight (nominally 11)
+
+ % Offset page to account for lower-left margin...
+ pageLeft 72 mul
+ pageBottom 72 mul
+ translate
+
+ % Draw the color wheel...
+ mediumFont setfont % Font
+ 0 setgray % Color
+
+ gsave
+ % Position the wheel on the left side...
+ pageWidth 18 mul % x = pageWidth * 1/4 * 72
+ pageHeight 54 mul % y = pageHeight * 3/4 * 72
+ translate
+
+ % Size the wheel...
+ wheelSize
+
+ % Draw the colors...
+ dup (C) exch 0 1 1 OCTANT 45 rotate
+ dup (M) exch 1 0 1 OCTANT 45 rotate
+ dup (Y) exch 1 1 0 OCTANT 45 rotate
+ dup (K) exch 0 0 0 OCTANT 45 rotate
+ dup (R) exch 1 0 0 OCTANT 45 rotate
+ dup (G) exch 0 1 0 OCTANT 45 rotate
+ dup (B) exch 0 0 1 OCTANT 45 rotate
+ (W) exch 1 1 1 OCTANT 45 rotate
+ grestore
+
+ % Label the color wheel...
+ pageWidth 18 mul % x = pageWidth * 1/4 * 72
+ pageHeight 44 mul % y = pageHeight * 19/32 * 72
+ moveto % Position the text
+ (Color Wheel) CENTER % Show the text centered
+
+ % Draw radial lines...
+ gsave
+ 0 setlinewidth % 1 pixel lines
+
+ % Position the lines on the left side...
+ pageWidth 54 mul % x = pageWidth * 3/4 * 72
+ pageHeight 54 mul % y = pageHeight * 3/4 * 72
+ translate
+
+ % Size the wheel...
+ wheelSize
+
+ % Loop at 1 degree increments
+ 0 1 359 {
+ pop % Discard angle - not used
+ 0 0 moveto % Start line at the center
+ dup 0 lineto % Draw to the radius
+ 1 rotate % Rotate 1 degree
+ } for
+
+ pop % Discard radius - not needed anymore
+ stroke % Draw lines...
+
+ grestore
+
+ % Label the lines...
+ pageWidth 54 mul % x = pageWidth * 3/4 * 72
+ pageHeight 44 mul % y = pageHeight * 19/32 * 72
+ moveto % Position the text
+ (1 Degree Radial Lines) CENTER % Show the text centered
+
+ % Imageable area...
+ pageHeight 15 mul % Height of imageable area
+
+ pageWidth 4.5 mul % x = pageWidth * 1/16 * 72
+ pageHeight 35.5 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 1/4 * 72
+ 3 index % height
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 4 mul % x = pageWidth * 1/16 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 3/8 * 72
+ 3 index % height
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ pop % Discard height
+
+ % Label the imageable area...
+ pageWidth 4 mul % x = pageWidth * 1/16 * 72
+ pageHeight 37 mul % y = pageHeight * 1/2 * 72
+ moveto % Position the text
+ mediumFont setfont % Font
+ (Imageable Area) show % Show the text
+
+ smallFont setfont % Font
+ pageWidth 14 mul % x = pageWidth * 3/16 * 72
+ pageHeight 36 mul % y = pageWidth * 1/2 * 72
+ pageHeight -2 mul add % y -= 2 * smallFont height
+
+ % Page Size inches
+ 2 copy moveto % Move to x & y
+ (Page Size: ) RIGHT % Label
+ 100 pageWidth NUMBER % pageWidth
+ (x) show % "x"
+ 100 pageHeight NUMBER % pageHeight
+ (in) show % "in"
+
+ % Page Size millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageWidth 25.4 mul NUMBER % pageWidth
+ (x) show % "x"
+ 10 pageHeight 25.4 mul NUMBER % pageHeight
+ (mm) show % "mm"
+
+ % Lower-left inches
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Lower-Left: ) RIGHT % Label
+ 100 pageLeft NUMBER % pageLeft
+ (x) show % "x"
+ 100 pageBottom NUMBER % pageBottom
+ (in) show % "in"
+
+ % Lower-left millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageLeft 25.4 mul NUMBER % pageLeft
+ (x) show % "x"
+ 10 pageBottom 25.4 mul NUMBER % pageBottom
+ (mm) show % "mm"
+
+ % Upper-right inches
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Upper-Right: ) RIGHT % Label
+ 100 pageRight NUMBER % pageRight
+ (x) show % "x"
+ 100 pageTop NUMBER % pageTop
+ (in) show % "in"
+
+ % Upper-right millimeters
+ pageHeight sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ 10 pageRight 25.4 mul NUMBER % pageRight
+ (x) show % "x"
+ 10 pageTop 25.4 mul NUMBER % pageTop
+ (mm) show % "mm"
+
+ % Resolution dots-per-inch
+ pageHeight 2 mul sub % Move down...
+
+ 2 copy moveto % Move to x & y
+ (Resolution: ) RIGHT % Label
+ 1 xResolution NUMBER % xResolution
+ (x) show % "x"
+ 1 yResolution NUMBER % yResolution
+ (dpi) show % "dpi"
+
+ % Resolution dots-per-meter
+ pageHeight sub % Move down...
+
+ moveto % Move to x & y
+ 1 xResolution 39.27 mul NUMBER % xResolution
+ (x) show % "x"
+ 1 yResolution 39.27 mul NUMBER % yResolution
+ (dpm) show % "dpm"
+
+ % Interpreter Information...
+ pageHeight 15 mul % Height of interpreter information
+
+ pageWidth 40.5 mul % x = pageWidth * 9/16 * 72
+ pageHeight 35.5 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 1/4 * 72
+ 3 index % height
+ 0.5 setgray rectfill % Draw a shadow
+
+ pageWidth 40 mul % x = pageWidth * 9/16 * 72
+ pageHeight 36 mul % y = pageHeight * 1/2 * 72
+ 2 index sub % y -= height
+ pageWidth 28 mul % width = pageWidth * 3/8 * 72
+ 3 index % height
+ 4 copy 1 setgray rectfill % Clear the box to white
+ 0 setgray rectstroke % Draw a black box around it...
+
+ pop % Discard height
+
+ % Label the interpreter info...
+ pageWidth 40 mul % x = pageWidth * 9/16 * 72
+ pageHeight 37 mul % y = pageHeight * 1/2 * 72
+ moveto % Position the text
+ mediumFont setfont % Font
+ (Interpreter Information) show % Show the text
+
+ smallFont setfont % Font
+ pageWidth 49 mul % x = pageWidth * 11/16 * 72
+ pageHeight 36 mul % y = pageWidth * 1/2 * 72
+ pageHeight 2 mul sub % y -= 2 * smallFont height
+
+ % Language level
+ 2 copy moveto % Move to x & y
+ (PostScript: ) RIGHT % Label
+ (Level ) show % "Level "
+ 1 languagelevel NUMBER % Language level
+
+ % Version
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Version: ) RIGHT % Label
+ version show % Version
+ ( \() show % " ("
+ 1 revision NUMBER % Revision
+ (\)) show % ")"
+
+ % Product
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Product: ) RIGHT % Label
+ product show % Product name
+
+ % Serial Number
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Move to x & y
+ (Serial #: ) RIGHT % Label
+ 1 serialnumber NUMBER % S/N
+
+ % Draw the label at the top...
+ pageWidth 36 mul % Center of page
+ pageHeight 68 mul % Top of page (15/16ths)
+ 2 copy moveto % Position text
+ bigFont setfont % Font
+ (Printer Test Page) CENTER % Show text centered
+
+ % Draw the copyright notice at the bottom...
+ pageWidth 36 mul % Center of page
+ pageHeight 10 mul % Bottom of page
+ 2 copy moveto % Position text
+ (Printed Using CUPS v1.1.x) CENTER % Show text centered
+
+ pageHeight 2 mul sub % Move down...
+ 2 copy moveto % Position text
+ smallFont setfont % Font
+ (Copyright 1993-2003 by Easy Software Products, All Rights Reserved.) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (CUPS, and the CUPS logo are the trademark property of) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (Easy Software Products, 44141 Airport View Drive, Suite 204,) CENTER
+ pageHeight sub % Move down...
+ 2 copy moveto % Position text
+ (Hollywood, Maryland, 20636-3111, USA.) CENTER
+
+ % Then the CUPS logo....
+ gsave
+ pageWidth 4 mul
+ pageHeight 4 mul
+ translate
+ pageWidth 9 mul CUPSLOGO
+ grestore
+
+ % And the ESP logo....
+ gsave
+ pageWidth 59 mul
+ pageHeight 4 mul
+ translate
+ pageWidth 6 mul ESPLOGO
+ grestore
+% Show the page...
+grestore
+showpage
+%
+% End of "$Id: testfile.ps 3041 2002-12-17 19:00:27Z swdev $".
+%
+%%EOF
diff --git a/test/testfile.txt b/test/testfile.txt
new file mode 100644
index 000000000..46bbf0848
--- /dev/null
+++ b/test/testfile.txt
@@ -0,0 +1,60 @@
+All work and no play makes Johhny a dull boy. All work and no
+play makes Johhny a dull boy. All work and no play makes Johhny
+a dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy. All
+work and no play makes Johhny a dull boy. All work and no play
+makes Johhny a dull boy. All work and no play makes Johhny a
+dull boy. All work and no play makes Johhny a dull boy.
diff --git a/test/testhp.ppd b/test/testhp.ppd
new file mode 100644
index 000000000..41003d309
--- /dev/null
+++ b/test/testhp.ppd
@@ -0,0 +1,195 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Test HP PPD file for the Common UNIX Printing System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "TESTHP.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*cupsFilter: "application/vnd.cups-raster 50 rastertohp"
+*ModelName: "Test HP Printer"
+*ShortNickName: "Test HP Printer"
+*NickName: "Test HP Printer CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Resolution 600dpi *ColorModel CMYK
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "18 36 594 756"
+*ImageableArea Legal/US Legal: "18 36 594 972"
+*ImageableArea Executive/US Executive: "18 36 504 684"
+*ImageableArea Tabloid/US Tabloid: "18 36 774 1188"
+*ImageableArea A3/A3: "18 36 824 1155"
+*ImageableArea A4/A4: "18 36 577 806"
+*ImageableArea A5/A5: "18 36 403 559"
+*ImageableArea B5/JIS B5: "18 36 498 693"
+*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673"
+*ImageableArea Env10/Com-10: "18 36 279 648"
+*ImageableArea EnvC5/EnvC5: "18 36 441 613"
+*ImageableArea EnvDL/EnvDL: "18 36 294 588"
+*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *MediaType/Media Type: PickOne
+*OrderDependency: 10 AnySetup *MediaType
+*DefaultMediaType: Plain
+*MediaType Plain/Plain Paper: "<</MediaType(Plain)/cupsMediaType 0>>setpagedevice"
+*MediaType Bond/Bond Paper: "<</MediaType(Bond)/cupsMediaType 1>>setpagedevice"
+*MediaType Special/Special Paper: "<</MediaType(Special)/cupsMediaType 2>>setpagedevice"
+*MediaType Transparency/Transparency: "<</MediaType(Transparency)/cupsMediaType 3>>setpagedevice"
+*MediaType Glossy/Glossy Paper: "<</MediaType(Glossy)/cupsMediaType 4>>setpagedevice"
+*CloseUI: *MediaType
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Tray
+*InputSlot Tray/Tray: "<</cupsMediaPosition 1>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</cupsMediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</cupsMediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 100dpi
+*Resolution 75dpi/75 DPI: "<</HWResolution[75 75]>>setpagedevice"
+*Resolution 100dpi/100 DPI: "<</HWResolution[100 100]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/CMYK Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 2>>setpagedevice"
+*ColorModel RGB/CMY Color: "<</cupsColorOrder 1/cupsColorSpace 4/cupsCompression 2>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/test/testps.ppd b/test/testps.ppd
new file mode 100644
index 000000000..3187ecf03
--- /dev/null
+++ b/test/testps.ppd
@@ -0,0 +1,192 @@
+*PPD-Adobe: "4.3"
+*%
+*% "$Id$"
+*%
+*% Test PS PPD file for the Common UNIX Printing System (CUPS).
+*%
+*% Copyright 1997-2003 by Easy Software Products.
+*%
+*% These coded instructions, statements, and computer programs are the
+*% property of Easy Software Products and are protected by Federal
+*% copyright law. Distribution and use rights are outlined in the file
+*% "LICENSE.txt" which should have been included with this file. If this
+*% file is missing or damaged please contact Easy Software Products
+*% at:
+*%
+*% Attn: CUPS Licensing Information
+*% Easy Software Products
+*% 44141 Airport View Drive, Suite 204
+*% Hollywood, Maryland 20636-3111 USA
+*%
+*% Voice: (301) 373-9603
+*% EMail: cups-info@cups.org
+*% WWW: http://www.cups.org
+*%
+*FormatVersion: "4.3"
+*FileVersion: "1.1"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "TESTPS.PPD"
+*Manufacturer: "ESP"
+*Product: "(CUPS v1.1)"
+*ModelName: "Test PS Printer"
+*ShortNickName: "Test PS Printer"
+*NickName: "Test PS Printer CUPS v1.1"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: True
+*DefaultColorSpace: RGB
+*FileSystem: False
+*Throughput: "1"
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+*TTRasterizer: Type42
+
+*UIConstraints: *PageSize Executive *InputSlot Envelope
+*UIConstraints: *PageSize Letter *InputSlot Envelope
+*UIConstraints: *PageSize Legal *InputSlot Envelope
+*UIConstraints: *PageSize Tabloid *InputSlot Envelope
+*UIConstraints: *PageSize A3 *InputSlot Envelope
+*UIConstraints: *PageSize A4 *InputSlot Envelope
+*UIConstraints: *PageSize A5 *InputSlot Envelope
+*UIConstraints: *PageSize B5 *InputSlot Envelope
+*UIConstraints: *Resolution 600dpi *ColorModel CMYK
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 10 AnySetup *PageSize
+*DefaultPageSize: Letter
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageSize Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageSize Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageSize A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageSize B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageSize EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageSize Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageSize EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageSize EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageSize EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*OpenUI *PageRegion: PickOne
+*OrderDependency: 10 AnySetup *PageRegion
+*DefaultPageRegion: Letter
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*PageRegion Executive/US Executive: "<</PageSize[522 756]/ImagingBBox null>>setpagedevice"
+*PageRegion Tabloid/US Tabloid: "<</PageSize[792 1224]/ImagingBBox null>>setpagedevice"
+*PageRegion A3/A3: "<</PageSize[842 1191]/ImagingBBox null>>setpagedevice"
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion A5/A5: "<</PageSize[421 595]/ImagingBBox null>>setpagedevice"
+*PageRegion B5/B5 (JIS): "<</PageSize[516 729]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvISOB5/Envelope B5: "<</PageSize[499 709]/ImagingBBox null>>setpagedevice"
+*PageRegion Env10/Envelope #10: "<</PageSize[297 684]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvC5/Envelope C5: "<</PageSize[459 649]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvDL/Envelope DL: "<</PageSize[312 624]/ImagingBBox null>>setpagedevice"
+*PageRegion EnvMonarch/Envelope Monarch: "<</PageSize[279 540]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageRegion
+
+*DefaultImageableArea: Letter
+*ImageableArea Letter/US Letter: "18 36 594 756"
+*ImageableArea Legal/US Legal: "18 36 594 972"
+*ImageableArea Executive/US Executive: "18 36 504 684"
+*ImageableArea Tabloid/US Tabloid: "18 36 774 1188"
+*ImageableArea A3/A3: "18 36 824 1155"
+*ImageableArea A4/A4: "18 36 577 806"
+*ImageableArea A5/A5: "18 36 403 559"
+*ImageableArea B5/JIS B5: "18 36 498 693"
+*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673"
+*ImageableArea Env10/Com-10: "18 36 279 648"
+*ImageableArea EnvC5/EnvC5: "18 36 441 613"
+*ImageableArea EnvDL/EnvDL: "18 36 294 588"
+*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504"
+
+*DefaultPaperDimension: Letter
+*PaperDimension Letter/US Letter: "612 792"
+*PaperDimension Legal/US Legal: "612 1008"
+*PaperDimension Executive/US Executive: "522 756"
+*PaperDimension Tabloid/US Tabloid: "792 1224"
+*PaperDimension A3/A3: "842 1191"
+*PaperDimension A4/A4: "595 842"
+*PaperDimension A5/A5: "421 595"
+*PaperDimension B5/B5 (JIS): "516 729"
+*PaperDimension EnvISOB5/Envelope B5: "499 709"
+*PaperDimension Env10/Envelope #10: "297 684"
+*PaperDimension EnvC5/Envelope C5: "459 649"
+*PaperDimension EnvDL/Envelope DL: "312 624"
+*PaperDimension EnvMonarch/Envelope Monarch: "279 540"
+
+*OpenUI *MediaType/Media Type: PickOne
+*OrderDependency: 10 AnySetup *MediaType
+*DefaultMediaType: Plain
+*MediaType Plain/Plain Paper: "<</MediaType(Plain)/cupsMediaType 0>>setpagedevice"
+*MediaType Bond/Bond Paper: "<</MediaType(Bond)/cupsMediaType 1>>setpagedevice"
+*MediaType Special/Special Paper: "<</MediaType(Special)/cupsMediaType 2>>setpagedevice"
+*MediaType Transparency/Transparency: "<</MediaType(Transparency)/cupsMediaType 3>>setpagedevice"
+*MediaType Glossy/Glossy Paper: "<</MediaType(Glossy)/cupsMediaType 4>>setpagedevice"
+*CloseUI: *MediaType
+
+*OpenUI *InputSlot/Media Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Tray
+*InputSlot Tray/Tray: "<</cupsMediaPosition 1>>setpagedevice"
+*InputSlot Manual/Manual Feed: "<</cupsMediaPosition 2>>setpagedevice"
+*InputSlot Envelope/Envelope Feed: "<</cupsMediaPosition 3>>setpagedevice"
+*CloseUI: *InputSlot
+
+*OpenUI *Resolution/Output Resolution: PickOne
+*OrderDependency: 20 AnySetup *Resolution
+*DefaultResolution: 100dpi
+*Resolution 75dpi/75 DPI: "<</HWResolution[75 75]>>setpagedevice"
+*Resolution 100dpi/100 DPI: "<</HWResolution[100 100]>>setpagedevice"
+*CloseUI: *Resolution
+
+*OpenUI *ColorModel/Output Mode: PickOne
+*OrderDependency: 10 AnySetup *ColorModel
+*DefaultColorModel: CMYK
+*ColorModel CMYK/CMYK Color: "<</cupsColorOrder 1/cupsColorSpace 8/cupsCompression 2>>setpagedevice"
+*ColorModel RGB/CMY Color: "<</cupsColorOrder 1/cupsColorSpace 4/cupsCompression 2>>setpagedevice"
+*ColorModel Gray/Grayscale: "<</cupsColorOrder 0/cupsColorSpace 3/cupsCompression 2>>setpagedevice"
+*CloseUI: *ColorModel
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+*Font ZapfDingbats: Special "(001.004S)" Standard ROM
+*%
+*% End of "$Id$".
+*%
diff --git a/visualc/config.h b/visualc/config.h
new file mode 100644
index 000000000..a3174f9e0
--- /dev/null
+++ b/visualc/config.h
@@ -0,0 +1,290 @@
+/*
+ * "$Id$"
+ *
+ * Configuration file for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2004 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9600
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ */
+
+/*
+ * Compiler stuff...
+ */
+
+#undef const
+#undef __CHAR_UNSIGNED__
+
+
+/*
+ * Version of software...
+ */
+
+#define CUPS_SVERSION "CUPS v1.1.20"
+
+
+/*
+ * Default user and group...
+ */
+
+#define CUPS_DEFAULT_USER "lp"
+#define CUPS_DEFAULT_GROUP "sys"
+
+
+/*
+ * Maximum number of file descriptors to support.
+ */
+
+#define CUPS_MAX_FDS 4096
+
+
+/*
+ * Where are files stored?
+ */
+
+#define CUPS_LOCALEDIR "C:/CUPS/locale"
+#define CUPS_SERVERROOT "C:/CUPS/etc"
+#define CUPS_SERVERBIN "C:/CUPS"
+#define CUPS_DOCROOT "C:/CUPS/share/doc"
+#define CUPS_REQUESTS "C:/CUPS/spool"
+#define CUPS_LOGDIR "C:/CUPS/logs"
+#define CUPS_DATADIR "C:/CUPS/share"
+#define CUPS_FONTPATH "C:/CUPS/share/fonts"
+
+
+/*
+ * What is the format string for strftime?
+ */
+
+#define CUPS_STRFTIME_FORMAT "%c"
+
+
+/*
+ * Do we have various image libraries?
+ */
+
+#undef HAVE_LIBPNG
+#undef HAVE_LIBZ
+#undef HAVE_LIBJPEG
+#undef HAVE_LIBTIFF
+
+
+/*
+ * Does this machine store words in big-endian (MSB-first) order?
+ */
+
+#undef WORDS_BIGENDIAN
+
+
+/*
+ * Which directory functions and headers do we use?
+ */
+
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_NDIR_H
+
+/*
+ * Do we have PAM stuff?
+ */
+
+#ifndef HAVE_LIBPAM
+#define HAVE_LIBPAM 0
+#endif /* !HAVE_LIBPAM */
+
+#undef HAVE_PAM_PAM_APPL_H
+
+
+/*
+ * Do we have <shadow.h>?
+ */
+
+#undef HAVE_SHADOW_H
+
+
+/*
+ * Do we have <crypt.h>?
+ */
+
+#undef HAVE_CRYPT_H
+
+
+/*
+ * How about standard C header files?
+ */
+
+#undef HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+
+
+/*
+ * Use <string.h>, <strings.h>, and/or <bstring.h>?
+ */
+
+#define HAVE_STRING_H
+#undef HAVE_STRINGS_H
+#undef HAVE_BSTRING_H
+
+
+/*
+ * Do we have the strXXX() functions?
+ */
+
+#define HAVE_STRDUP
+#define HAVE_STRCASECMP
+#define HAVE_STRNCASECMP
+#undef HAVE_STRLCAT
+#undef HAVE_STRLCPY
+
+
+/*
+ * Do we have the vsyslog() function?
+ */
+
+#undef HAVE_VSYSLOG
+
+
+/*
+ * Do we have the (v)snprintf() functions?
+ */
+
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+
+
+/*
+ * What signal functions to use?
+ */
+
+#undef HAVE_SIGSET
+#undef HAVE_SIGACTION
+
+/*
+ * What wait functions to use?
+ */
+
+#undef HAVE_WAITPID
+#undef HAVE_WAIT3
+
+
+/*
+ * Do we have the mallinfo function and malloc.h?
+ */
+
+#undef HAVE_MALLINFO
+#undef HAVE_MALLOC_H
+
+
+/*
+ * Which encryption libraries do we have?
+ */
+
+#undef HAVE_CDSASSL
+#undef HAVE_GNUTLS
+#undef HAVE_LIBSSL
+#undef HAVE_SSL
+
+
+/*
+ * Do we have the OpenSLP library?
+ */
+
+#undef HAVE_LIBSLP
+
+
+/*
+ * Do we have libpaper?
+ */
+
+#undef HAVE_LIBPAPER
+
+
+/*
+ * Do we have <sys/ioctl.h>?
+ */
+
+#undef HAVE_SYS_IOCTL_H
+
+
+/*
+ * Do we have mkstemp() and/or mkstemps()?
+ */
+
+#undef HAVE_MKSTEMP
+#undef HAVE_MKSTEMPS
+
+
+/*
+ * Does the "tm" structure contain the "tm_gmtoff" member?
+ */
+
+#undef HAVE_TM_GMTOFF
+
+
+/*
+ * Do we have rresvport()?
+ */
+
+#undef HAVE_RRESVPORT
+
+
+/*
+ * Do we have getifaddrs()?
+ */
+
+#undef HAVE_GETIFADDRS
+
+
+/*
+ * Do we have hstrerror()?
+ */
+
+#undef HAVE_HSTRERROR
+
+
+/*
+ * Do we have the <sys/sockio.h> header file?
+ */
+
+#undef HAVE_SYS_SOCKIO_H
+
+
+/*
+ * Does the sockaddr structure contain an sa_len parameter?
+ */
+
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+
+/*
+ * Various scripting languages...
+ */
+
+#undef HAVE_JAVA
+#define CUPS_JAVA "/usr/bin/java"
+#undef HAVE_PERL
+#define CUPS_PERL "/usr/bin/perl"
+#undef HAVE_PHP
+#define CUPS_PHP "/usr/bin/php"
+#undef HAVE_PYTHON
+#define CUPS_PYTHON "/usr/bin/python"
+
+
+/*
+ * End of "$Id$".
+ */